vars /allvars 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 = 73 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 {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 // Initialize the screen init_eca_state() // Wait 10 frames nmi nmi nmi nmi nmi nmi nmi nmi nmi nmi // Loop forever: while true nmi calc_and_advance_gen() charmap(".#-=n!@~E$%^S&*(C)_+A{}|12345678qwertyuiop") data /titlescreen [] title ("................................" "................................" "................................" "................................" "..........############.........." ".........##############........." ".........##..........##........." ".........##..........##........." ".........##..n!E$S&..##........." ".........##..@~%^*(..##........." ".........##....C)....##........." ".........##...._+....##........." ".........##....A{....##........." ".........##....}|....##........." ".........##..........##........." ".........##..........##........." ".........##############........." "..........############.........." "................................" "................................" "...........###########.........." "..........#..........#.........." "..........#.12345678.#.........." "..........#...<...>..#.........." "..........#..........#.........." "..........###########..........." "................................" "................................" "................................" "................................" "................................") 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 // 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 eca_main() : preserves /allvars // Define the tileset (commonly called CHR): chrrom file(fmt, "spritesheet.chr")