← AF1E Pointer to the brick state map entry of the slot the sweep is at Map B0AE → Advance the 15-step golden-twinkle timer
AF20: Scan and process the brick field
Sweeps three rows of the brick field per frame, and steps each queued break animation. A sweep that finds each slot empty, or with the golden brick at its plain face, sets the level-cleared flag.
scan_brick_field AF20 LD A,(sweep_offset) The in-progress sweep offset: non-zero means a sweep is already in progress, so skip the once-per-sweep setup.
AF23 OR A
AF24 JR NZ,scan_frame_rows
AF26 XOR A Start of a sweep: zero the cleared-slot tally and the on-field prize flag.
AF27 LD (cleared_cell_count),A
AF2A LD (prize_on_field),A
AF2D LD A,(bat_side) Point the slot pointer at the field's first brick slot for the current bat side. Side 0, with the bat on the right, starts the field at column 2, and side 1 at column 12.
AF30 OR A
AF31 JR NZ,scan_brick_field_0
AF33 LD HL,TILEMAP_BASE+$82
AF36 JR scan_brick_field_1
scan_brick_field_0 AF38 LD HL,TILEMAP_BASE+$8C A non-zero side takes the far one.
scan_brick_field_1 AF3B LD (scan_cell_ptr),HL Either way, keep it for the sweep.
AF3E CALL tick_golden_flash_timer Tick the golden-twinkle flash timer once per sweep restart.
scan_frame_rows AF41 XOR A Zero this frame's count of rows swept, and pick up the sweep offset in D.
AF42 LD (sweep_rows_done),A
AF45 LD A,(sweep_offset)
AF48 LD D,A
scan_row AF49 LD E,$00 E steps across the row's 9 columns.
scan_cell AF4B LD HL,(scan_cell_ptr) Load the slot pointer and read its first tile byte.
AF4E LD A,(HL)
AF4F CP $20 A slot is empty only when both its tile bytes are the space tile.
AF51 JR NZ,scan_brick_field_2
AF53 INC HL
AF54 LD A,(HL)
AF55 DEC HL
AF56 CP $20
AF58 JR Z,scan_count_cleared
scan_brick_field_2 AF5A CP $59 The lone golden tile counts as non-brick too.
AF5C JR NZ,scan_prize_flag
scan_count_cleared AF5E EXX Count this slot as cleared toward the 81-slot level-clear total.
AF5F LD HL,cleared_cell_count
AF62 INC (HL)
AF63 EXX
scan_prize_flag AF64 LD A,(HL) A bomb, missile or double bat prize still on the field raises the on-field prize flag.
AF65 CP $7D
AF67 JR Z,scan_set_prize
AF69 CP $81
AF6B JR Z,scan_set_prize
AF6D CP $89
AF6F JR NZ,scan_brick_entry
scan_set_prize AF71 LD A,$01 Mark a prize present on the field.
AF73 LD (prize_on_field),A
scan_brick_entry AF76 LD HL,brick_state_map Address this slot's brick state map entry and save the pointer for the helpers below.
AF79 LD B,$00
AF7B LD C,D
AF7C ADD HL,BC
AF7D LD (scan_entry_ptr),HL
AF80 LD A,(HL) A settled slot: just run the golden brick's twinkle check, then advance.
AF81 OR A
AF82 JR NZ,scan_anim
AF84 CALL check_golden_twinkle
AF87 JP scan_next_cell
scan_anim AF8A CP $10 The finished marker skips the table lookup and goes straight to the sub-frame advance. Otherwise the entry less one picks this class's pointer from the head of the break-animation sequences. The sequence start it yields is kept for the sub-frame lookup below.
AF8C JP Z,scan_advance_subframe
AF8F DEC A
AF90 ADD A,A
AF91 LD HL,anim_brick
AF94 LD B,$00
AF96 LD C,A
AF97 ADD HL,BC
AF98 LD C,(HL)
AF99 INC HL
AF9A LD B,(HL)
AF9B LD (scan_anim_seq_ptr),BC
AF9F LD HL,(scan_entry_ptr)
AFA2 LD A,(HL)
AFA3 CP $11
AFA5 JR NZ,scan_brick_field_3
AFA7 INC HL A class that loops wraps its sub-frame index within the sequence.
AFA8 LD A,(HL)
AFA9 AND $03
AFAB JR scan_brick_field_4
scan_brick_field_3 AFAD INC HL Any other class reads the index straight.
AFAE LD A,(HL)
scan_brick_field_4 AFAF ADD A,A Scale it to the sub-frame's byte offset.
AFB0 ADD A,A
AFB1 ADD A,A
AFB2 LD (brick_anim_offset),A
AFB5 LD HL,(scan_anim_seq_ptr)
AFB8 LD B,$00
AFBA LD C,A
AFBB ADD HL,BC
AFBC LD A,(HL)
AFBD CP $FF
AFBF JR NZ,scan_blit_frame
scan_seq_end AFC1 LD HL,(scan_entry_ptr) This sub-frame is the sequence's terminator. What the cell settles to depends on the class that just played. A prize class leaves its glyph on the field.
AFC4 LD A,(HL)
AFC5 CP $07
AFC7 JR C,scan_seq_settle
AFC9 CP $10
AFCB JR NC,scan_seq_settle
AFCD CP $0E
AFCF JR Z,scan_seq_to_loop
AFD1 LD (HL),$10
AFD3 JP scan_next_cell
scan_seq_settle AFD6 LD (HL),$00 Classes below the prize classes, and the golden brick's twinkle, settle back to idle.
AFD8 JP scan_next_cell
scan_seq_to_loop AFDB LD (HL),$11 The slow ball reveal hands the cell on to the glyph's own loop sequence.
AFDD JP scan_next_cell
scan_blit_frame AFE0 PUSH DE Blit the current sub-frame's tile bytes into the tile map and stamp the cells' dirty counters in the parallel buffer. Unless the sub-frame marks its attributes as unchanged, also write its four attribute bytes into the attribute file.
AFE1 LD B,H
AFE2 LD C,L
AFE3 LD DE,(scan_cell_ptr)
AFE7 LD L,E
AFE8 LD H,D
AFE9 INC H
AFEA INC H
AFEB INC H
AFEC LD (DE),A
AFED LD (HL),$02
AFEF INC HL
AFF0 INC DE
AFF1 INC BC
AFF2 LD A,(BC)
AFF3 LD (DE),A
AFF4 LD (HL),$02
AFF6 PUSH BC
AFF7 LD BC,$001F
AFFA ADD HL,BC
AFFB PUSH HL
AFFC EX DE,HL
AFFD ADD HL,BC
AFFE EX DE,HL
AFFF POP HL
B000 POP BC
B001 INC BC
B002 LD A,(BC)
B003 LD (DE),A
B004 LD (HL),$02
B006 INC HL
B007 INC DE
B008 INC BC
B009 LD A,(BC)
B00A LD (DE),A
B00B LD (HL),$02
B00D POP DE
B00E INC BC
B00F LD A,(BC)
B010 CP $FF
B012 JR Z,scan_advance_subframe
B014 LD HL,(scan_cell_ptr)
B017 LD A,H
B018 SUB $A0
B01A LD H,A
B01B LD A,(BC)
B01C LD (HL),A
B01D INC HL
B01E INC BC
B01F LD A,(BC)
B020 LD (HL),A
B021 PUSH BC
B022 LD BC,$001F
B025 ADD HL,BC
B026 POP BC
B027 INC BC
B028 LD A,(BC)
B029 LD (HL),A
B02A INC HL
B02B INC BC
B02C LD A,(BC)
B02D LD (HL),A
scan_advance_subframe B02E LD HL,(scan_entry_ptr) Advance this slot's animation sub-frame counter.
B031 INC HL
B032 INC (HL)
B033 DEC HL
B034 LD A,(HL)
B035 CP $10
B037 JR Z,scan_brick_field_5
B039 CP $11 A cell that neither finished nor looped just moves on.
B03B JR NZ,scan_next_cell
scan_brick_field_5 B03D LD BC,(scan_cell_ptr) A cell that rests or loops is checked for the three glyphs that would claim the secondary object. This test is the bomb.
B041 LD A,(BC)
B042 CP $7D
B044 JR Z,scan_brick_field_6
B046 CP $81 This one is the missile prize.
B048 JR Z,scan_brick_field_6
B04A CP $89 This one is the double bat prize.
B04C JR NZ,scan_brick_field_7
scan_brick_field_6 B04E LD A,(ball_gem_frame) While the ball gem is out, the sweep shatters those three instead.
B051 OR A
B052 JR NZ,scan_brick_field_8
B054 LD A,(missile_shot) A missile shot in the secondary object spares them: they go on to the lifetime test below.
B057 OR A
B058 JR NZ,scan_brick_field_7
B05A LD A,(ball_b_in_play) While ball B is live, the sweep shatters them too.
B05D OR A
B05E JR NZ,scan_brick_field_8
scan_brick_field_7 B060 INC HL Every other glyph waits out its lifetime: the sweep counts this cell up and clears it once the count reaches the fixed limit.
B061 LD A,(HL)
B062 DEC HL
B063 CP $FA
B065 JR NZ,scan_next_cell
scan_brick_field_8 B067 LD (HL),$01 Clear the glyph: restart the plain break sequence on its cell.
B069 INC HL
B06A LD (HL),$00
scan_next_cell B06C LD HL,(scan_cell_ptr) Step the slot pointer forward two bytes to the next column.
B06F INC HL
B070 INC HL
B071 LD (scan_cell_ptr),HL
B074 INC D Brick-map offset advances two bytes and the column one, per slot.
B075 INC D
B076 INC E
B077 LD A,E Loop until the row's columns are done.
B078 CP $09
B07A JP NZ,scan_cell
scan_next_row B07D LD HL,(scan_cell_ptr) End of row. Step the pointer past the row's unscanned tail so it lands on the next row's first slot. A row holds 9 slots at 2 bytes per slot within a 64-byte row stride.
B080 LD BC,$002E
B083 ADD HL,BC
B084 LD (scan_cell_ptr),HL
B087 LD HL,sweep_rows_done Stop after three rows this frame.
B08A INC (HL)
B08B LD A,(HL)
B08C CP $03
B08E JP NZ,scan_row
scan_sweep_done B091 LD A,D Save the sweep offset for next frame; at the end of the map, the sweep of the whole 9×9 field is complete.
B092 LD (sweep_offset),A
B095 CP $A2
B097 RET NZ
B098 XOR A Sweep complete: reset the sweep offset and latch the on-field prize flag into its steady copy.
B099 LD (sweep_offset),A
B09C LD A,(prize_on_field)
B09F LD (prize_on_field_latched),A
B0A2 LD A,(cleared_cell_count) A tally that reaches the whole field sets the level-cleared flag.
B0A5 CP $51
B0A7 RET NZ
B0A8 LD A,$01
B0AA LD (level_cleared),A
B0AD RET
← AF1E Pointer to the brick state map entry of the slot the sweep is at Map B0AE → Advance the 15-step golden-twinkle timer
Fork me on GitHub