;License:MIT ;(c) 2018-2020 by 4am ; ; functions for managing which HGR page is showing, and doing things on the other one ; ; - GetOffscreenAddress ; - LoadTitleOffscreen ; - LoadCoverOffscreen ; - LoadHelpOffscreen ; - LoadGameTitleOffscreen ; - UnpackHGRTitle ; - ResyncPage ; - ShowOtherPage ; - ShowOtherDHGRPage ; - ToggleOffscreenPage ; - ClearScreens ; - ClearOffscreen ; - ClearHGR1 ; - ClearMem ; ; Public variables ; - OffscreenPage ; ;------------------------------------------------------------------------------ ; GetOffscreenAddress ; get high byte of HGR page that is currently not showing ; ; in: none ; out: A = high byte of offscreen HGR page (#$20 or #$40) ; preserves X/Y ;------------------------------------------------------------------------------ GetOffscreenAddress Ignore = * + 1 ; discard IRQs, particularly on the IIc lda #$40 OffscreenPage = * + 1 bne + ; SMC ; 0 = currently showing HGR page 2 ; (so offscreen is page 1 @ $2000) ; 1 = currently showing HGR page 1 ; (so offscreen is page 2 @ $4000) + lsr rts ;------------------------------------------------------------------------------ ; LoadTitleOffscreen ; load title screen in the HGR page that is currently not showing ; ; in: none ; out: all flags and registers clobbered ;------------------------------------------------------------------------------ LoadTitleOffscreen lda #kCoverRecord ; all of these are on the same page rts LoadGameTitleOffscreen ; in: gGameToLaunch = index into gSearchStore (word) jsr GetGameToLaunch jsr okvs_next_field jsr okvs_next_field_PTR_is_already_set ; (PTR) -> length-prefixed game info bitfield ; Y = 0 iny ; Y = 1 lda (PTR), y ; A = game info bitfield bpl .LoadHGRGameTitleOffscreen ; bit 7 = 1 if game has DHGR title, 0 if HGR title jsr SwitchToBank2 - iny lda (PTR), y sta OKVS_CACHE-1, y cpy #6 bne - LoadIndexedDHRFile jsr SwitchToBank2 lda #0 sta OKVS_CACHE lda #$20 ; load first $2000 bytes into auxiliary memory sta OKVS_CACHE + 5 jsr GetOffscreenAddress sta @dhgr_addr_aux + 1 sta @dhgr_addr_main + 1 jsr LoadAuxIndexedFile @dhgr_addr_aux !word $FD00 ; SMC high byte !word OKVS_CACHE jsr SwitchToBank2 lda OKVS_CACHE + 2 ; offset += $2000 (note: stored in big-endian) clc adc #$20 sta OKVS_CACHE + 2 bcc + inc OKVS_CACHE + 1 + jsr LoadIndexedFile ; load next $2000 bytes into main memory @dhgr_addr_main !word $FD00 ; SMC high byte !word OKVS_CACHE rts .LoadHGRGameTitleOffscreen jsr ForceHGRMode jsr GetOffscreenAddress sta @hgr_addr + 1 eor #$1F sta @poke+2 sta @peek+2 @poke sta $3FFD ; SMC high byte to clear screen hole before load +LD16 PTR +ST16 @hgrIndexRecordPtr jsr LoadIndexedFile @hgr_addr !word $FD00 ; SMC high byte @hgrIndexRecordPtr !word $FDFD ; SMC @peek lda $3FFD ; SMC high byte cmp #$4C ; Check if screen hole now contains a JMP beq OFFSCREENRTS ; if so, file was not packed, so skip unpack ; /!\ execution falls through here to UnpackHGRTitle ;------------------------------------------------------------------------------ ; UnpackHGRTitle ; unpack data from screen holes of the off screen HGR page ; ;------------------------------------------------------------------------------ UnpackHGRTitle jsr GetOffscreenAddress sta src+2 ora #$1E sta dest+2 lda #$00 sta src+1 sta dest+1 lda #3 sta $E0 loop ldx #0 -- ldy #$78 src - lda $0000,y ;smc dest sta $0000,x ;smc inx iny bpl - tya ; y = #$80 eor src+1 sta src+1 bne + inc src+2 + cpx #$78 bne -- lda dest+1 eor #$80 sta dest+1 bne + inc dest+2 + dec $E0 bpl loop OFFSCREENRTS rts ;------------------------------------------------------------------------------ ; ClearScreens ; clear and display text screen and then clear both hires screens ; (in this order so that the erasing isn't visible) ; ; in: none ; out: $400..$7FF and $2000..$5FFF cleared ;------------------------------------------------------------------------------ ClearScreens jsr Home lda #$20 ; clear both hi-res pages ldx #$40 ; to flash previous bits of the launcher UI) bne ClearMem ; always ;------------------------------------------------------------------------------ ; ClearOffscreen ; clear $2000..$3FFF or $4000..$5FFF, depending on which HGR page is not ; visible right now ; does not change HGR mode ; ; in: none ; out: $2000..$3FFF or $4000..$5FFF cleared ; A = #$80 ; X = #$00 ; Y = #$00 ; Z = 1 ;------------------------------------------------------------------------------ ClearOffscreen jsr GetOffscreenAddress +HIDE_NEXT_2_BYTES ClearHGR1 lda #$20 ; note to self: LDX #$20 can't move here ldx #$20 ClearMem ldy #$2C ; BIT bne + ; always ;------------------------------------------------------------------------------ ; CopyHGR ; ; in: source and destination page pointers set ; out: all registers clobbered ; 8kb memory region duplicated ;------------------------------------------------------------------------------ CopyHGR ldx #$20 ldy #$B9 ; LDA $0000,Y opcode + sty PageFrom sta PageTo+2 ClearToBlack lda #$00 ClearGR ldy #0 PageFrom lda $FD00,y ; SMC address high byte, also SMC opcode (might be BIT) PageTo sta $FD00,y ; SMC address high byte iny bne PageFrom inc PageFrom+2 inc PageTo+2 dex bne PageFrom sta READMAINMEM rts ResyncPage jsr ToggleOffscreenPage ; /!\ execution falls through here to ShowOtherPage ;------------------------------------------------------------------------------ ; ShowOtherPage ; switch to the HGR page that is not currently showing ; ; in: none ; out: A = new value of OffscreenPage ; preserves X/Y ;------------------------------------------------------------------------------ ShowOtherPage jsr ToggleOffscreenPage bne + bit PAGE2 ; show page 2 rts + bit PAGE1 ; show page 1 rts ShowOtherDHGRPage jsr ToggleOffscreenPage jmp DHGRMode ;------------------------------------------------------------------------------ ; ToggleOffscreenPage ; switch the internal variable that tracks which HGR page is showing ; (does not affect screen) ; ; in: none ; out: A = new value of OffscreenPage ; preserves X/Y ;------------------------------------------------------------------------------ ToggleOffscreenPage lda OffscreenPage eor #$01 sta OffscreenPage rts