aboutsummaryrefslogtreecommitdiff
path: root/main.fab
diff options
context:
space:
mode:
authorPatrick Kingston <patrick@pkingston.xyz>2026-02-14 18:17:50 -0500
committerPatrick Kingston <patrick@pkingston.xyz>2026-02-14 18:17:50 -0500
commiteb7da883997f4ae3bb5baa7875d94d37a6c14f1d (patch)
tree007050dc116435ef0f0b7d0f851a2cd4c9cf2671 /main.fab
parent62966cf7418c73d68870a6f1adb87042a23c2471 (diff)
Create Elementary cellular automata
Cellular automata now makes a new row every frame and resets at the top.
Diffstat (limited to 'main.fab')
-rw-r--r--main.fab132
1 files changed, 98 insertions, 34 deletions
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)
+ // Scroll to attributes
+ ppu_reset_addr($2000 + 960)
+ // Set attributes for background
+ for U i = 0; i < 64; i+= 1
+ {PPUDATA}(%11111111)
- // Set background tiles
- for UU i = 0; i < 960; i += 1
- {PPUDATA}(1)
+ //// Init the buffers to 0
+ //for i = 0; i < 64; i += 1
+ // buf[i] = 0
- U i = 0
- // Set attributes for background
- for i = 0; i < 64; i+= 1
- {PPUDATA}(%00011011)
+ // Init the buffer to zero
+ buf = U[64]()
+ // Add an initial cell
+ buf[16] = 1
- // Init the buffers to 0
- for i = 0; i < 8; i += 1
- buf[i] = 0
-fn calc_and_upload_next_row()
- // "scroll" to the row we're at
- UU row_start = $2000
- row_start += (drawing_row_offset * 32)
- ppu_reset_addr(row_start)
+fn assemble_code(U left, U middle, U right) U
+ U out = %00000000
+ out |= left << 2
+ out |= middle << 1
+ out |= right
+ return out
- for UU i = 0; i < 32; i += 1
- //next_cell = 0 //get_next_gen(i)
- {PPUDATA}(next_cell)
+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
- drawing_row_offset += 1
+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
- if next_cell
- next_cell = 0
- else
- next_cell = 1
-nmi main_nmi()
- ppu_upload_oam_poll_pads(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])
- calc_and_upload_next_row()
+nmi main_nmi()
// 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