vars /ecavars U[64] buf // A buffer that can store the current and next row U curr_gen = 0 // Swap these offsets back and forth per generation U next_gen = 32 UU drawing_row_offset = 0 // Use this to track which row we're drawing U current_rule = %01001001 fn init_eca_state() // Scroll to attributes ppu_reset_addr($2000 + 960) // Set attributes for background for U i = 0; i < 64; i+= 1 {PPUDATA}(%11111111) // Init the buffer to zero buf = U[64]() // Add an initial cell buf[16] = 1 fn assemble_code(U left, U middle, U right) U U out = %00000000 out |= left << 2 out |= middle << 1 out |= right return out fn calc_next_cell(U left, U middle, U right) U U code = assemble_code(left, middle, right) ct U mask7 = %10000000 ct U mask6 = %01000000 ct U mask5 = %00100000 ct U mask4 = %00010000 ct U mask3 = %00001000 ct U mask2 = %00000100 ct U mask1 = %00000010 ct U mask0 = %00000001 switch code case %00000111 return (current_rule & mask7) >> 7 case %00000110 return (current_rule & mask6) >> 6 case %00000101 return (current_rule & mask5) >> 5 case %00000100 return (current_rule & mask4) >> 4 case %00000011 return (current_rule & mask3) >> 3 case %00000010 return (current_rule & mask2) >> 2 case %00000001 return (current_rule & mask1) >> 1 case %00000000 return (current_rule & mask0) >> 0 fn calc_and_advance_gen() // Calculate the next row's values U left_ind = 0 U right_ind = 0 U left_cell = 0 U mid_cell = 0 U right_cell = 0 U next_cell = 0 for U i = 0; i < 32; i += 1 // Calculate indices for left and right of cell if i == 0 left_ind = 31 else left_ind = i - 1 if i == 31 right_ind = 0 else right_ind = i + 1 // Get left and right of cell left_cell = buf[curr_gen + left_ind] mid_cell = buf[curr_gen + i] right_cell = buf[curr_gen + right_ind] // Calc next cell next_cell = calc_next_cell(left_cell, mid_cell, right_cell) // Set next cell buf[next_gen + i] = next_cell // Advance next generation if curr_gen == 0 curr_gen = 32 next_gen = 0 else curr_gen = 0 next_gen = 32 // advance drawing row offset, looping back to top drawing_row_offset += 1 if drawing_row_offset == 30 drawing_row_offset = 0 fn upload_curr_gen() // "scroll" to the row we're at UU row_start = $2000 row_start += (drawing_row_offset * 32) ppu_reset_addr(row_start) for U i = 0; i < 32; i += 1 //32 columns //next_cell = 0 //get_next_gen(i) {PPUDATA}(buf[i+curr_gen]) nmi eca_nmi() // Turn on rendering sprites and bg ppu_upload_oam_poll_pads(0) {PPUMASK}(PPUMASK_ON | PPUMASK_NO_CLIP) upload_curr_gen() ppu_reset_scroll(0, 0) // Main mode for running the ECA mode eca_main() : nmi eca_nmi : vars /ecavars // Initialize the screen init_eca_state() // Wait 60 frames before beginning for U i = 0; i < 60; i += 1 nmi // Loop forever: while true nmi update_pads() if pads[0].released & BUTTON_START goto mode settings() : preserves /ecavars calc_and_advance_gen() charmap settingsmap(".E!@#I$T%R^&*L()_i{}|ta:01", 47) //Back up to 47 to grab a blank space data /settingsscreen // Initing settings to Initial Rule which is 73 %01001001 [] settingschars ("................................" "................................" "................................" "....E!I$.R^L(..................." "....@#T%.&*)_..................." "................................" "................................" "....111....110....101....100...." ".....0......1......0......0....." "................................" "....011....010....001....000...." ".....1......0......0......1....." "................................" "................................" "................................" "................................" "....E!I$.i{t...................." "....@#T%.}|:a..................." "................................" "................................" "00000000000000000000000000000000" "................................" "................................" "................................" "................................" "................................" "................................" "................................" "................................" "................................"settingsmap) vars /settings_vars U slow_counter = 0 U editing_rule = 1 // Start off editing the rule U rule_pos = 0 // Start off on highest bit U generation_pos = 0 U cursor_x = 0 U cursor_y = 0 U cursor_frame = 0 U loaded = 0 nmi settings_nmi() // Turn on rendering sprites and bg ppu_upload_oam_poll_pads(0) if loaded {PPUMASK}(PPUMASK_ON | PPUMASK_NO_CLIP) ppu_reset_scroll(0, 0) mode settings() : nmi settings_nmi : vars /ecavars : vars /settings_vars // Turn rendering off while we load the screen {PPUMASK}(~PPUMASK_ON) ppu_reset_addr($2000) // Load the settings screen CCC/settingsscreen settingsp = @settingschars for UU i = 0; i < 960; i += 1 {PPUDATA}(settingsp{i}) for UU i = 0; i < 64; i += 1 {PPUDATA}(%00000000) loaded = 1 {PPUMASK}(PPUMASK_ON) // Set the init to the current generation and set the rule to the current rule // TODO ^ while true nmi update_pads() //update_cursor() //upload_cursor() if pads[0].released & BUTTON_START goto mode eca_main() : preserves /ecavars charmap titlemap(".#-=N!@~E$%^S&*(C)_+A{}|12345678qwertyuiop") data /titlescreen [] title ("................................" "................................" "................................" "................................" "..........############.........." ".........##############........." ".........##..........##........." ".........##..........##........." ".........##..N!E$S&..##........." ".........##..@~%^*(..##........." ".........##....C)....##........." ".........##...._+....##........." ".........##....A{....##........." ".........##....}|....##........." ".........##..........##........." ".........##..........##........." ".........##############........." "..........############.........." "................................" "................................" "...........###########.........." "..........#..........#.........." "..........#.12345678.#.........." "..........#...<...>..#.........." "..........#..........#.........." "..........###########..........." "................................" "................................" "................................" "................................" "................................"titlemap) vars /titlescreen UU wipeline = 0 // nmi for entrypoint for the program nmi main_nmi() // Turn on rendering sprites and bg {PPUMASK}(PPUMASK_ON | PPUMASK_NO_CLIP) ppu_reset_scroll(0, 0) if wipeline UU row_start = $2000 row_start += ((wipeline - 1) * 32) ppu_reset_addr(row_start) for U i = 0; i < 32; i += 1 //32 columns //next_cell = 0 //get_next_gen(i) {PPUDATA}(0) // The main entry point for the program mode main() : nmi main_nmi : vars /titlescreen /ecavars // Set the palette: palette = example_palette ppu_upload_palette() ppu_reset_addr($2000) // Load the title screen CCC/titlescreen titlep = @title for UU i = 0; i < 960; i += 1 {PPUDATA}(titlep{i}) for UU i = 0; i < 64; i += 1 {PPUDATA}(%00000000) // Turn rendering on {PPUMASK}(PPUMASK_BG_ON) // Turn the NMI on {PPUCTRL}(PPUCTRL_NMI_ON) // Display title screen for 120 frames for U i = 0; i < 120; i += 1 nmi for U i = 1; i <= 30; i += 1 // use this to wipe the screen wipeline = i nmi // Go to the main eca mode goto mode settings() : preserves /ecavars // Define the tileset (commonly called CHR): chrrom file(fmt, "spritesheet.chr")