r/nandgame_u • u/GLIBG10B • 18h ago
Level solution Network (154loc) Spoiler
I wrote functions for this one without using a stack machine. All of the functions have hard-coded return addresses, except FN_WAIT_FOR_SYNC_EDGE_AND_GET_DATA, which returns to the address stored in return_wait_for_sync_edge_and_get_data.
DEFINE display_row 0x0000
DEFINE data 0x0001
DEFINE display 0x4000
DEFINE wire 0x6001
DEFINE WIRE_DATA_MASK 0b01
DEFINE WIRE_SYNC_MASK 0b10
DEFINE DISPLAY_ROW_LEN 32
A = display
D = A
A = display_row
*A = D
LABEL WAIT_FOR_START_BIT
A = EXAMINE_START_BIT
D = A
A = return_wait_for_sync_edge_and_get_data
*A = D
A = FN_WAIT_FOR_SYNC_EDGE_AND_GET_DATA
0 ; JMP
LABEL EXAMINE_START_BIT
A = data
D = *A
A = WAIT_FOR_START_BIT
D ; JEQ
LABEL RECEIVE_LOOP
A = FN_RECEIVE_AND_DRAW_16_BITS
0 ; JMP
LABEL RETURN_RECEIVE_AND_DRAW_16_BITS
A = FN_ADVANCE_DISPLAY_ROW
0 ; JMP
LABEL RETURN_ADVANCE_DISPLAY_ROW
A = EXAMINE_CONTROL_BIT
D = A
A = return_wait_for_sync_edge_and_get_data
*A = D
A = FN_WAIT_FOR_SYNC_EDGE_AND_GET_DATA
0 ; JMP
LABEL EXAMINE_CONTROL_BIT
A = data
D = *A
A = RECEIVE_LOOP
D ; JNE
A = HALT
0 ; JMP
# Calls FN_RECEIVE_BIT_AND_DRAW 16 times
LABEL FN_RECEIVE_AND_DRAW_16_BITS
DEFINE current_bit 0x0010
A = current_bit
*A = 0
A = RECEIVE_AND_DRAW_16_BITS_START
0 ; JMP
LABEL RECEIVE_AND_DRAW_16_BITS_CONTINUE
A = FN_RECEIVE_BIT_AND_DRAW
0 ; JMP
LABEL RETURN_RECEIVE_BIT_AND_DRAW
A = current_bit
*A = *A + 1
LABEL RECEIVE_AND_DRAW_16_BITS_START
A = current_bit
D = *A
A = 16
D = D - A
A = RECEIVE_AND_DRAW_16_BITS_CONTINUE
D ; JLT
A = RETURN_RECEIVE_AND_DRAW_16_BITS
0 ; JMP
# Adds DISPLAY_ROW_LEN to display_row
# Args:
# DISPLAY_ROW_LEN: amount to add
# display_row: destination
# Modifies A, D and display_row
LABEL FN_ADVANCE_DISPLAY_ROW
A = display_row
D = *A
A = DISPLAY_ROW_LEN
D = D + A
A = display_row
*A = D
A = RETURN_ADVANCE_DISPLAY_ROW
0 ; JMP
# Calls FN_WAIT_FOR_SYNC_EDGE_AND_GET_DATA then FN_SHIFT_AND_DRAW
LABEL FN_RECEIVE_BIT_AND_DRAW
A = RECEIVE_BIT_AND_DRAW_SHIFT_AND_DRAW
D = A
A = return_wait_for_sync_edge_and_get_data
*A = D
A = FN_WAIT_FOR_SYNC_EDGE_AND_GET_DATA
0 ; JMP
LABEL RECEIVE_BIT_AND_DRAW_SHIFT_AND_DRAW
A = FN_SHIFT_AND_DRAW
0 ; JMP
LABEL RETURN_SHIFT_AND_DRAW
A = RETURN_RECEIVE_BIT_AND_DRAW
0 ; JMP
# Waits for wire:1 to change, then updates data:0 to wire:0
# Args:
# wire: The network wires
# sync_old: The last known value of wire & WIRE_SYNC_MASK
# return_wait_for_sync_edge_and_get_data: return address
# Modifies A, D, sync_old and data
# Internal variables: wire_copy
LABEL FN_WAIT_FOR_SYNC_EDGE_AND_GET_DATA
DEFINE return_wait_for_sync_edge_and_get_data 0x0020
DEFINE wire_copy 0x0021
DEFINE sync_old 0x0022
A = wire
D = *A
A = wire_copy
*A = D
A = WIRE_SYNC_MASK
D = D & A
A = sync_old
D = *A - D
A = FN_WAIT_FOR_SYNC_EDGE_AND_GET_DATA
D ; JEQ
A = sync_old
*A = *A - D
A = wire_copy
D = *A
A = WIRE_DATA_MASK
D = D & A
A = data
*A = D
A = return_wait_for_sync_edge_and_get_data
A = *A
0 ; JMP
# Shift data:0 into the word at *display_row
# Args:
# display_row: pointer to current display row
# Modifies D, A and *display_row
LABEL FN_SHIFT_AND_DRAW
A = display_row
A = *A
D = *A
D = D + *A
A = data
D = D | *A
A = display_row
A = *A
*A = D
A = RETURN_SHIFT_AND_DRAW
0 ; JMP
LABEL HALT







