From 738eddcaed270a7f50a9530aacd67f7a364b071c Mon Sep 17 00:00:00 2001 From: mc78 Date: Wed, 28 Aug 2024 13:07:55 +0200 Subject: [PATCH] Separated init and switching code for alternate screen --- include/cbm.h | 9 +- libsrc/c64/workingscreenaddr.s | 185 +++++++++++++++++++++------------ 2 files changed, 123 insertions(+), 71 deletions(-) diff --git a/include/cbm.h b/include/cbm.h index f08dfcb11..5dd61a068 100644 --- a/include/cbm.h +++ b/include/cbm.h @@ -318,12 +318,15 @@ void __fastcall__ cbm_closedir (unsigned char lfn); /*****************************************************************************/ - -int __fastcall__ cbm_set_working_screen(unsigned char screen_hi); +int __fastcall__ cbm_init_alt_screen(char fillchar, unsigned char screen_hi); /* Sets the address of the working screen (no switching of viewport) to screen_hi*0x100. Checks, if the screen_hi is a multiple of 4. If not, fails with EXIT_FAILURE. */ -int __fastcall__ cbm_reset_working_screen(void); +int __fastcall__ cbm_set_alt_screen(void); +/* Sets the address of the working screen (no switching of viewport) to screen_hi*0x100. + Checks, if the screen_hi is a multiple of 4. If not, fails with EXIT_FAILURE. */ + +int __fastcall__ cbm_set_def_screen(void); /* Resets the address of the working screen (no switching of viewport) to default (0x400). */ /* End of cbm.h */ diff --git a/libsrc/c64/workingscreenaddr.s b/libsrc/c64/workingscreenaddr.s index 4ee13bfce..0c7f13023 100644 --- a/libsrc/c64/workingscreenaddr.s +++ b/libsrc/c64/workingscreenaddr.s @@ -1,100 +1,149 @@ ; ; Stefan 'MonteCarlos' Andree, 26.08.2024 ; -; int __fastcall__ _set_working_screen(unsigned char screen_hi); +; int __fastcall__ _init_alt_screen(unsigned char screen_hi, char fillchar) +; int __fastcall__ _set_alt_screen(void); ; .include "c64.inc" - .import PLOT - .export _cbm_set_working_screen, _cbm_reset_working_screen + .importzp ptr1 + .import popa, PLOT + .import _restorecursorfrom, _savecursorto + .export _cbm_init_alt_screen, _cbm_set_alt_screen, _cbm_set_def_screen -_cbm_set_working_screen: - ldx screen_selected ; If selected screen is already alternate screen, then error - bne @error +.proc _cbm_set_alt_screen + ldx screen_selected ; If alternate screen is already set, then error + bne @error + + ldx SCREEN_HI + stx old_screen_hi + + lda alt_screen_addr + beq @error ; not initialized + sta SCREEN_HI ; Tell kernal to which memory screen output will go + + lda #def_screen_crsr_pos + jsr _savecursorto + + lda #alt_screen_crsr_pos + jsr _restorecursorfrom + + inc screen_selected + + lda #0 tax - beq @error ; Reject setting screen at zero page location - and #3 - bne @error + rts + @error: + lda #$01 + ldx #$00 + rts +.endproc + + +.proc _cbm_set_def_screen + lda screen_selected ; If original screen is already set, then error + beq @error + + lda old_screen_hi + sta SCREEN_HI + + lda #def_screen_crsr_pos + jsr _restorecursorfrom + + dec screen_selected + + lda #0 + tax + rts + @error: + lda #$01 + ldx #$00 + rts +.endproc + + +.proc _cbm_init_alt_screen + jsr check_screen_addr + bcs @error + + sta alt_screen_addr + sta ptr1 + 1 + lda #0 + sta ptr1 + + jsr popa ; fetch fillchar + ldy #0 + ldx #4 ; This may depend on the target system + @fill_screen: + sta (ptr1), y + iny + bne @fill_screen + + inc ptr1 + 1 + dex + bne @fill_screen + + stx alt_screen_crsr_pos ; Init cursor pos to 0/0 on alt screen + stx alt_screen_crsr_pos + 1 + + lda #0 + tax + rts + @error: + jsr popa + lda #$01 + ldx #$00 + rts +.endproc + + +.proc check_screen_addr + tax + beq @error ; Reject setting screen at zero page location + and #3 + bne @error txa - ldy #reject_range_count - 1 + ldx #reject_range_count - 1 @check_ranges: - cmp reject_range_start, y + cmp reject_range_start, x bcc @accept - cmp reject_range_end, y + cmp reject_range_end, x bcc @error @accept: - dey + dex bpl @check_ranges - ldx SCREEN_HI - stx old_screen_hi - sta SCREEN_HI ; Tell kernal to which memory screen output will go - sec - jsr PLOT - stx old_crsr_row - sty old_crsr_col - ldx alt_crsr_row - ldy alt_crsr_col clc - jsr PLOT - - inc screen_selected - - lda #0 - tax rts + @error: - lda #$01 - ldx #$00 - rts - - -_cbm_reset_working_screen: - lda screen_selected ; If original screen is already alternate screen, then error - beq @error - lda old_screen_hi - sta SCREEN_HI - sec - jsr PLOT - stx alt_crsr_row - sty alt_crsr_col - - ldx old_crsr_row - ldy old_crsr_col - clc - jsr PLOT - - dec screen_selected - - lda #0 - tax - rts - @error: - lda #$01 - ldx #$00 rts +.endproc + ; Screen addr must not be set to $1000-$1fff nor $9000-$9fff for shadowing reasons and not to $d000-$dfff, due to registers reject_range_start: - .byte $d0, $90, $10 + .byte $d0, $90, $10 reject_range_end: - .byte $e0, $a0, $20 + .byte $e0, $a0, $20 reject_range_count = reject_range_end - reject_range_start + +alt_screen_addr: + .byte 0 screen_selected: - .byte 0 -old_crsr_row: - .res 1 -old_crsr_col: - .res 1 + .res 1 +def_screen_crsr_pos: + .res 2 old_screen_hi: - .res 1 -alt_crsr_row: - .byte 0 -alt_crsr_col: - .byte 0 + .res 1 +alt_screen_crsr_pos: + .res 2