1
0
mirror of https://github.com/cc65/cc65.git synced 2025-01-19 17:31:31 +00:00

Separated init and switching code for alternate screen

This commit is contained in:
mc78 2024-08-28 13:07:55 +02:00
parent 92b5ee133a
commit 738eddcaed
2 changed files with 123 additions and 71 deletions

View File

@ -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 */

View File

@ -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
ldx #>def_screen_crsr_pos
jsr _savecursorto
lda #<alt_screen_crsr_pos
ldx #>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
ldx #>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