; os memory map KEYBOARD = $c000 KBDSTROBE = $c010 CLRTEXT = $c050 SETTEXT = $c051 CLRMIXED = $c052 SETMIXED = $c053 TXTPAGE1 = $c054 TXTPAGE2 = $c055 CLRHIRES = $c056 SETHIRES = $c057 set_hires bit CLRTEXT ; start with HGR page 1, full screen bit CLRMIXED bit TXTPAGE1 bit SETHIRES rts ; clear all screens, hires and text clrscr lda #$20 sta clrscr_smc+2 lda #$81 ldy #0 clrscr_smc sta $ff00,y iny bne clrscr_smc inc clrscr_smc+2 ldx clrscr_smc+2 cpx #$40 bcc clrscr_smc lda #0 ldx #39 ?1 jsr text_put_col ; text page 1 jsr text_put_col2 ; text page 2 dex bpl ?1 rts clear_input lda KBDSTROBE rts ; wait for any key any_key lda KBDSTROBE ?1 lda KEYBOARD bpl ?1 lda KBDSTROBE rts ; process gameplay user input. Sets actor_input_dir and various debugging ; input userinput lda KEYBOARD pha ldx #38 ldy #23 jsr debughex ldx #0 pla bpl input_not_movement ; stop movement of player if no direction input ; setting the keyboard strobe causes the key to enter repeat mode if held ; down, which causes a pause after the initial movement. Not setting the ; strobe allows smooth movement from the start, but there's no way to stop ;sta KBDSTROBE check_up cmp #$8d ; up arrow beq input_up cmp #$8b ; up arrow IIe beq input_up cmp #$c1 ; 'A' key beq input_up cmp #$c9 ; I bne check_down input_up lda #TILE_UP sta actor_input_dir,x rts check_down cmp #$af ; down arrow beq input_down cmp #$8a ; down arrow IIe beq input_down cmp #$bb ; ';' key (dvorak keyboards!) beq input_down cmp #$da ; 'Z' key beq input_down cmp #$d4 ; K bne check_left input_down lda #TILE_DOWN sta actor_input_dir,x rts check_left cmp #$88 ; left arrow beq input_left cmp #$c8 ; J bne check_right input_left lda #TILE_LEFT sta actor_input_dir,x rts check_right cmp #$95 ; right arrow beq input_right cmp #$ce ; L bne input_not_movement input_right lda #TILE_RIGHT sta actor_input_dir,x rts input_not_movement lda #0 sta actor_input_dir,x check_special cmp #$80 + 32 beq input_space cmp #$80 + '.' beq input_period cmp #$80 + 'P' beq input_period rts input_space jmp debugflipscreens input_period jsr wait lda KEYBOARD bpl input_period cmp #$80 + 'P' beq input_period rts debugflipscreens lda #20 sta scratch_count debugloop jsr pageflip jsr wait jsr pageflip jsr wait dec scratch_count bne debugloop rts ; delay for a while. 7 reps = 7 * (2 + 256*19 + 2 + 3) = 34097 cycles wait ldy #$06 wait_outer ; outer loop: 2 + 256 * (inner) + 2 + 3 ldx #$ff wait_inner ; inner loop: 14 + 2 + 3 nop nop nop nop nop nop nop dex bne wait_inner dey bne wait_outer rts ; Offsets in pixels from upper left corner of sprite to where it should ; appear on screen given the tile coords of where the game logic thinks ; the sprite is. ; [i*7-3 for i in range(40)] player_col_to_x .byte 0, 3, 10, 17, 24, 31, 38, 45, 52, 59, 66, 73, 80, 87, 94, 101, 108, 115, 122, 129, 136, 143, 150, 157, 164, 171, 178, 185, 192, 199, 206, 213, 220, 227, 234, 241, 248, 248, 248, 248, 248, ;.byte 0, 4, 11, 18, 25, 32, 39, 46, 53, 60, 67, 74, 81, 88, 95, 102, 109, 116, 123, 130, 137, 144, 151, 158, 165, 172, 179, 186, 193, 200, 207, 214, 221, 228, 235, 242, 249, 249, 249, 249, 249 ; [i*8-5 for i in range(24)] player_row_to_y .byte 0, 3, 11, 19, 27, 35, 43, 51, 59, 67, 75, 83, 91, 99, 107, 115, 123, 131, 139, 147, 155, 163, 171, 179 ; defines the zone around the midpoint where the player can change to any ; direction, not just backtracking. On the apple, there are 7 x positions but ; 8 y positions x_allowed_turn .byte 0, 0, 1, 1, 1, 0, 0 y_allowed_turn .byte 0, 0, 1, 1, 1, 0, 0, 0 ; Returns address of tile in col 0 of row y ; row in Y mazerow lda textrows_l,y sta mazeaddr lda textrows_h,y sta mazeaddr+1 rts ; clear text page 2 where most of the variables are stored init_vars ldx #0 txa ?1 sta $800,x sta $900,x sta $a00,x sta $b00,x dex bne ?1 rts ; initialize screen to draw to page 1 (displays page 2) init_screen_once nop lda #0 sta KBDSTROBE sta drawpage jsr draw_to_page1 rts ; set an entire column (24 rows) of the HGR screen to the specified character ; on page 1 ; character in A, col in X text_put_col nop sta $0400,x ; row 0 sta $0480,x ; row 1 sta $0500,x ; row 2 sta $0580,x ; row 3 sta $0600,x ; row 4 sta $0680,x ; row 5 sta $0700,x ; row 6 sta $0780,x ; row 7 sta $0428,x ; row 8 sta $04a8,x ; row 9 sta $0528,x ; row 10 sta $05a8,x ; row 11 sta $0628,x ; row 12 sta $06a8,x ; row 13 sta $0728,x ; row 14 sta $07a8,x ; row 15 sta $0450,x ; row 16 sta $04d0,x ; row 17 sta $0550,x ; row 18 sta $05d0,x ; row 19 sta $0650,x ; row 20 sta $06d0,x ; row 21 sta $0750,x ; row 22 sta $07d0,x ; row 23 rts ; ditto except for page 2 text_put_col2 nop sta $0800,x ; row 0 sta $0880,x ; row 1 sta $0900,x ; row 2 sta $0980,x ; row 3 sta $0a00,x ; row 4 sta $0a80,x ; row 5 sta $0b00,x ; row 6 sta $0b80,x ; row 7 sta $0828,x ; row 8 sta $08a8,x ; row 9 sta $0928,x ; row 10 sta $09a8,x ; row 11 sta $0a28,x ; row 12 sta $0aa8,x ; row 13 sta $0b28,x ; row 14 sta $0ba8,x ; row 15 sta $0850,x ; row 16 sta $08d0,x ; row 17 sta $0950,x ; row 18 sta $09d0,x ; row 19 sta $0a50,x ; row 20 sta $0ad0,x ; row 21 sta $0b50,x ; row 22 sta $0bd0,x ; row 23 rts ; maze is text screen 1 textrows_l .byte $00, $80, $00, $80, $00, $80, $00, $80 .byte $28, $a8, $28, $a8, $28, $a8, $28, $a8 .byte $50, $d0, $50, $d0, $50, $d0, $50, $d0 textrows_h .byte $04, $04, $05, $05, $06, $06, $07, $07 .byte $04, $04, $05, $05, $06, $06, $07, $07 .byte $04, $04, $05, $05, $06, $06, $07, $07 ; sets HGR page 1 to all white using a vertical wipe starting from the ; top moving down wipeclear1 ldy #0 sty param_y wipeclear1_loop lda HGRROWS_L,y sta wipeclear1_save_smc+1 lda HGRROWS_H1,y sta wipeclear1_save_smc+2 ldx #39 lda #$ff wipeclear1_save_smc sta $ffff,x dex bpl wipeclear1_save_smc ldx #WIPE_DELAY wipeclear1_wait nop nop nop nop nop nop dex bne wipeclear1_wait inc param_y ldy param_y cpy #192 bcc wipeclear1_loop rts ; sets HGR page 1 to the contents of page 2 using a vertical wipe starting ; from the top moving down wipe2to1 ldy #0 sty param_y wipe2to1_loop lda HGRROWS_H2,y sta wipe2to1_load_smc+2 lda HGRROWS_L,y sta wipe2to1_load_smc+1 sta wipe2to1_save_smc+1 lda HGRROWS_H1,y sta wipe2to1_save_smc+2 ldx #39 wipe2to1_load_smc lda $ffff,x wipe2to1_save_smc sta $ffff,x dex bpl wipe2to1_load_smc ldx #WIPE_DELAY wipe2to1_wait nop nop nop nop nop nop dex bne wipe2to1_wait inc param_y ldy param_y cpy #192 bcc wipe2to1_loop rts ; simple (slow, non-optimized) copy of the data from HGR page 2 to HGR page 1 copy2to1 lda #$40 sta ?source+2 lda #$20 sta ?dest+2 ?outer ldy #0 ?source lda $ff00,y ?dest sta $ff00,y iny bne ?source inc ?source+2 inc ?dest+2 lda ?dest+2 cmp #$40 bcc ?outer rts ; copy the entire text screen to the current HGR page. The dest_smc address ; is set in the pageflip routine below so they always point to the page ; in back, not the page currently being shown. copytexthgr nop ldy #0 ; y is rows copytexthgr_outer lda textrows_h,y ora #4 sta copytexthgr_src_smc+2 lda textrows_l,y sta copytexthgr_src_smc+1 ldx #0 ; x is columns copytexthgr_src_smc lda $ffff,x copytexthgr_dest_smc jsr $ffff inx cpx #40 bcc copytexthgr_src_smc iny cpy #24 bcc copytexthgr_outer rts ; change pages based on the state of the drawpage variable. drawpage == 0 ; is page 1, drawpage == $80 is page 2 pageflip nop lda drawpage eor #$80 bpl show_page1 ; pos = show 1, draw 2; neg = show 1, draw 1 show_page2 lda #$80 sta drawpage bit TXTPAGE2 ; show page 2, work on page 1 draw_to_page1 lda #$00 sta hgrselect lda #$20 sta hgrhi lda damageindex ; save other page's damage pointer sta damageindex2 lda #DAMAGEPAGE1 ; point to page 1's damage area sta damageptr+1 lda damageindex1 sta damageindex lda tdamageindex ; save other page's damage pointer sta tdamageindex2 lda tdamageindex1 ; point to page 1's damage area sta tdamageindex lda #0 sta damagestart ; copy addresses for functions that write to one page or the other lda #FASTFONT_H1 sta fastfont_smc+2 sta fasttiles_smc+2 sta copytexthgr_dest_smc+2 rts show_page1 lda #0 sta drawpage bit TXTPAGE1 ; show page 1, work on page 2 draw_to_page2 lda #$60 sta hgrselect lda #$40 sta hgrhi lda damageindex ; save other page's damage pointer sta damageindex1 lda #DAMAGEPAGE2 ; point to page 2's damage area sta damageptr+1 lda damageindex2 sta damageindex lda tdamageindex ; save other page's damage pointer sta tdamageindex1 lda tdamageindex2 ; point to page 2's damage area sta tdamageindex lda #128 sta damagestart lda #FASTFONT_H2 sta fastfont_smc+2 sta fasttiles_smc+2 sta copytexthgr_dest_smc+2 rts ; tile for middle left/right (number 12) is a color tile and gets ; the wrong bit pattern when it's in an odd column -- replace the ; image with tile 15 when necessary fastfont nop cmp #12 bne ?2 txa and #1 bne ?1 lda #15 bne ?2 ?1 lda #12 ?2 and #ACTOR_FLAG_MASK fastfont_smc jmp $ffff ; restore a horizontal segment from the text page to the current screen ; param_col = text column ; param_row = text screen row ; param_count = number of characters to copy to hgr screen fasttiles ldx param_col ldy param_row lda textrows_h,y sta fasttiles_row_smc+2 lda textrows_l,y sta fasttiles_row_smc+1 fasttiles_row_smc lda $ffff,x cmp #12 bne ?2 txa and #1 bne ?1 lda #15 bne ?2 ?1 lda #12 ?2 and #ACTOR_FLAG_MASK fasttiles_smc jsr $ffff inx dec param_count bne fasttiles_row_smc rts