From eb7da883997f4ae3bb5baa7875d94d37a6c14f1d Mon Sep 17 00:00:00 2001 From: Patrick Kingston Date: Sat, 14 Feb 2026 18:17:50 -0500 Subject: Create Elementary cellular automata Cellular automata now makes a new row every frame and resets at the top. --- main.fab | 136 ++++++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 100 insertions(+), 36 deletions(-) (limited to 'main.fab') diff --git a/main.fab b/main.fab index 8624f9d..a47ec27 100644 --- a/main.fab +++ b/main.fab @@ -1,54 +1,118 @@ vars - U[8] buf // A buffer that can store the current and next row - U row_a = 0 // We swap back and forth between these two offsets for each row - U row_b = 4 - UU drawing_row_offset = 0// Use this to track which row we're drawing + 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 = %00011110 - U next_cell = 0 fn init_screen() - ppu_reset_addr($2000) - - // Set background tiles - for UU i = 0; i < 960; i += 1 - {PPUDATA}(1) - - U i = 0 + // Scroll to attributes + ppu_reset_addr($2000 + 960) // Set attributes for background - for i = 0; i < 64; i+= 1 - {PPUDATA}(%00011011) - - // Init the buffers to 0 - for i = 0; i < 8; i += 1 - buf[i] = 0 + for U i = 0; i < 64; i+= 1 + {PPUDATA}(%11111111) + + //// Init the buffers to 0 + //for i = 0; i < 64; i += 1 + // buf[i] = 0 + + // 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 calc_and_upload_next_row() +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 UU i = 0; i < 32; i += 1 + for U i = 0; i < 32; i += 1 //32 columns //next_cell = 0 //get_next_gen(i) - {PPUDATA}(next_cell) + {PPUDATA}(buf[i+curr_gen]) - drawing_row_offset += 1 - - if drawing_row_offset == 30 - drawing_row_offset = 0 - if next_cell - next_cell = 0 - else - next_cell = 1 nmi main_nmi() - ppu_upload_oam_poll_pads(0) - - calc_and_upload_next_row() - // Turn on rendering sprites and bg {PPUMASK}(PPUMASK_ON | PPUMASK_NO_CLIP) + upload_curr_gen() + ppu_reset_scroll(0, 0) @@ -58,7 +122,7 @@ mode main() palette = example_palette ppu_upload_palette() - // Load the background + // Initialize the screen init_screen() // Turn the NMI on @@ -66,8 +130,8 @@ mode main() // Loop forever: while true - update_pads() nmi + calc_and_advance_gen() // Define the tileset (commonly called CHR): chrrom -- cgit v1.2.3