← BEF9 KRAKOUT title-logo glyph bitmaps Map C1D4 → Post-load handler for the LOAD LEVELS tape read
C073: Options / start menu
Runs the options screen, where the player sets the bat side, sound effects, ball speed, control type and its inertia or dual-speed value. The player can also load a fresh level set from tape, and Q returns to the title screen.
Entry setup: clear the display and flood every attribute with $47 (bright white ink on black paper). Then draw the menu text and current settings, and fall into the input loop.
options_menu C073 CALL clear_screen Clear the display, then flood all attributes to bright white ink on black.
C076 LD A,$47
C078 CALL fill_attrs
C07B CALL draw_options_menu
Top of the input loop, re-entered after every change. A fixed busy-wait paces the cursor blink, then the selected row is recolored. The controls are read once (read_ctrl), and the held direction or fire is dispatched.
options_loop C07E LD BC,$2710 Pace the cursor blink with a busy-wait of 10000 iterations.
C081 CALL delay
Highlight the selected row. Its ink advances to the next color on every pass of the loop, and paper, bright and flash stay. The highlight cycles through the ink colors.
C084 LD A,(options_cursor) Fetch the selected row's screen address from the options-row screen addresses, a word per row.
C087 ADD A,A
C088 LD E,A
C089 LD D,$00
C08B LD HL,opt_row_addrs
C08E ADD HL,DE
C08F LD A,(HL)
C090 INC HL
C091 LD H,(HL)
C092 LD L,A
C093 LD A,H Convert the screen address to its attribute-file address.
C094 AND $18
C096 RRCA
C097 RRCA
C098 RRCA
C099 ADD A,$58
C09B LD H,A
C09C LD A,(HL) Step the row's ink on to the next of the eight, and keep paper, bright and flash, across the whole row.
C09D AND $F8
C09F LD C,A
C0A0 LD A,(HL)
C0A1 INC A
C0A2 AND $07
C0A4 OR C
C0A5 LD B,$15
options_highlight C0A7 LD (HL),A Flood the new attribute across the row's 21 cells.
C0A8 INC HL
C0A9 DJNZ options_highlight
C0AB CALL read_ctrl Read the controls into the control bits.
C0AE LD HL,controls Play the key-press blip to acknowledge any held control.
C0B1 LD A,(HL)
C0B2 OR A
C0B3 CALL NZ,sfx_key_blip
C0B6 BIT 3,(HL) If up is held (bit 3), move the cursor up; otherwise check down.
C0B8 JR Z,options_check_down
C0BA CALL draw_options_menu Redraw to erase the old highlight before the move.
C0BD LD A,(options_cursor) Cursor 0 wraps up to the last row; otherwise decrement.
C0C0 OR A
C0C1 JR NZ,options_cursor_up
C0C3 LD A,$05
C0C5 JR options_cur_store_up
options_cursor_up C0C7 DEC A Any other cursor row just steps back one.
options_cur_store_up C0C8 LD (options_cursor),A Store the cursor and rerun the loop.
C0CB JP options_loop
options_check_down C0CE BIT 2,(HL) If down is held (bit 2), move the cursor down; otherwise check fire.
C0D0 JR Z,options_fire
C0D2 CALL draw_options_menu Redraw to erase the old highlight before the move.
C0D5 LD A,(options_cursor) The last row wraps down to 0; otherwise increment.
C0D8 CP $05
C0DA JR C,options_cursor_down
C0DC XOR A
C0DD JR options_cur_store_down
options_cursor_down C0DF INC A Any other row steps forward one.
options_cur_store_down C0E0 LD (options_cursor),A Store the cursor and rerun the loop.
C0E3 JP options_loop
options_fire C0E6 BIT 4,(HL) Fire held (bit 4)? If not, nothing changed – poll for Q to quit.
C0E8 JP Z,options_poll_quit
Fire acts on the row the cursor sits on. Each row's own entry states the values it accepts.
Row Option Variable
0 Bat side bat_side
1 Sound effects sound_fx
2 Ball speed ball_speed
3 Control type bat_control_type
4, control type 0 Inertia rate inertia_accel
4, control type 1 Dual-speed slow bat_speed_slow
4, control type 2 Dual-speed fast bat_speed_fast
5 LOAD LEVELS –
C0EB LD A,(options_cursor) Dispatch on the cursor row; row 0 is bat side.
C0EE OR A
C0EF JR NZ,options_opt_sound
C0F1 LD A,(bat_side) Bat side: toggle it between 0 and 1, the edge the bat rides.
C0F4 INC A
C0F5 AND $01
C0F7 LD (bat_side),A
C0FA CALL mirror_sprite_bank Mirror every sprite to face the new side, then apply.
C0FD JP options_apply_tail
Sound FX (row 1). Toggle the sound-effects flag between 0 (off) and 1 (on), then redraw. The redraw is what actually mutes, through the sound primitive. This handler also restores the two speaker-port writes inside it, the high write and the low write. Its path to disable them when off never runs.
options_opt_sound C100 CP $01 The sound-FX row
C102 JR NZ,options_opt_speed
C104 LD A,(sound_fx) Toggle the sound-effects flag between 0 (off) and 1 (on).
C107 INC A
C108 AND $01
C10A LD (sound_fx),A
C10D CALL draw_options_menu Redraw. This re-patches the first byte of the sound primitive to RET when sound is off.
BUG: the sound-off branch is unreachable. It is taken only when the redraw returns with the zero flag set. That routine always returns with it reset, because its last action, a string print, returns on the set bit 7 of the string's terminator. The two speaker writes are therefore always restored. The mute still works through the sound primitive. The path that disables the speaker writes is dead code.
C110 JR Z,options_sound_off Restore the two OUT ($FE),A writes inside the sound primitive. This runs whether sound is on or off.
C112 LD HL,SPEAKER_OUT_OPCODE
C115 LD (sound_lvl_hi),HL
C118 LD (sound_lvl_lo),HL
C11B JR options_applied
options_sound_off C11D LD HL,$0000 Sound off (unreachable): blank the two speaker writes to NOP NOP.
C120 LD (sound_lvl_hi),HL
C123 LD (sound_lvl_lo),HL
options_applied C126 JP options_apply_tail Either way, redraw the options page with the new value.
options_opt_speed C129 CP $02 The ball-speed row
C12B JR NZ,options_opt_control
C12D LD A,(ball_speed) Ball speed: cycle it up, and wrap the top of the range back to the bottom.
C130 INC A
C131 CP $07
C133 JR C,options_set_speed
C135 LD A,$01
options_set_speed C137 LD (ball_speed),A Store the speed and rewrite the digit shown on the BALL SPEED line.
C13A ADD A,$30
C13C LD (ball_speed_digit),A
C13F JP options_apply_tail
options_opt_control C142 CP $03 The control-type row
C144 JR NZ,options_ctrl_value
C146 LD A,(bat_control_type) Control type: cycle it up by 1, and wrap the last value back to 0.
C149 INC A
C14A CP $03
C14C JR C,options_set_control
C14E XOR A
options_set_control C14F LD (bat_control_type),A Store the type, then apply. The redraw refreshes the row text.
C152 JP options_apply_tail
Row 4 edits one of three values, picked by the current control type.
options_ctrl_value C155 CP $04 The control-type value row
C157 JR NZ,options_opt_load
C159 LD A,(bat_control_type) Branch on control type: 0 edits inertia here, and non-zero edits a dual-speed value.
C15C OR A
C15D JR NZ,options_opt_dual_slow
C15F LD A,(inertia_accel) Inertia: cycle it up, and wrap the top of the range back to the bottom.
C162 INC A
C163 CP $0A
C165 JR C,options_set_inertia
C167 LD A,$01
options_set_inertia C169 LD (inertia_accel),A Store and rewrite the digit on the INERTIA line.
C16C ADD A,$30
C16E LD (inertia_digit),A
C171 JP options_apply_tail
options_opt_dual_slow C174 CP $01 Dual-speed: the lower type edits slow, the higher fast.
C176 JR NZ,options_opt_dual_fast
C178 LD A,(bat_speed_slow) Dual-speed slow: cycle it up, and wrap the top of the range back to the bottom.
C17B INC A
C17C CP $0A
C17E JR C,options_set_dual_slow
C180 LD A,$01
options_set_dual_slow C182 LD (bat_speed_slow),A Store and rewrite the digit on the DUAL SPEED SLOW line.
C185 ADD A,$30
C187 LD (dual_slow_digit),A
C18A JR options_apply_tail
options_opt_dual_fast C18C LD A,(bat_speed_fast) Dual-speed fast: cycle it up, and wrap the top of the range back to the bottom.
C18F INC A
C190 CP $09
C192 JR C,options_set_dual_fast
C194 LD A,$01
options_set_dual_fast C196 LD (bat_speed_fast),A Store and rewrite the digit on the DUAL SPEED FAST line.
C199 ADD A,$30
C19B LD (dual_fast_digit),A
C19E JR options_apply_tail
LOAD LEVELS (row 5). Reached only with the cursor on row 5. Its guard sends any other row to the apply tail. Waits for all keys to release, then prints the PRESS PLAY ON TAPE prompt. It then loads a fresh level set from tape through the ROM tape loader into the level-data region. The post-load continuation runs once the load finishes.
options_opt_load C1A0 CP $05 Only the LOAD LEVELS row loads; any other goes to the apply tail.
C1A2 JR NZ,options_apply_tail
C1A4 CALL wait_no_key Wait for all keys to release.
C1A7 LD HL,opt_press_play_cell Print the PRESS PLAY ON TAPE prompt.
C1AA LD DE,msg_press_play
C1AD LD C,$C7
C1AF CALL print_string_2x
C1B2 LD IX,level_layouts Set up the ROM tape load: a fresh level set straight into the level-data region.
C1B6 LD DE,$2454
C1B9 LD A,$FF
C1BB SCF
C1BC LD HL,load_result Hold the post-load continuation in HL, and save the flag byte and the load carry in AF', as the ROM loader's own entry does.
C1BF INC D
C1C0 EX AF,AF'
C1C1 DEC D
C1C2 DI Border white, stack the post-load continuation as the loader's return, then jump into the ROM tape loader.
C1C3 LD A,$0F
C1C5 OUT ($FE),A
C1C7 PUSH HL
C1C8 IN A,($FE)
C1CA RRA
C1CB AND $20
C1CD OR $03
C1CF LD C,A
C1D0 CP A
C1D1 JP $056B
← BEF9 KRAKOUT title-logo glyph bitmaps Map C1D4 → Post-load handler for the LOAD LEVELS tape read
Fork me on GitHub