| ← BEF9 | Map | C1D4 → |
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.
|
||||||||||||||||||||||||||||||
| 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 | Map | C1D4 → |
