+;\r
+; Macro definitions for screen layout modules\r
+;\r
+\r
+ .include "extzp.inc"\r
+ \r
+.linecont +\r
+\r
+;\r
+; Internal function for screensize()\r
+;\r
+.macro osi_screensize ScrWidth, ScrHeight\r
+ ; Macro implementation of internal screensize\r
+ ; function for given width and height in\r
+ ; characters\r
+ \r
+ .export screensize\r
+\r
+.proc screensize\r
+ ldx #ScrWidth\r
+ ldy #ScrHeight\r
+ rts\r
+.endproc\r
+.endmacro\r
+\r
+;\r
+; void clrscr (void);\r
+;\r
+.macro osi_clrscr ScrBase, ScrRamSize\r
+\r
+ .export _clrscr\r
+\r
+.proc _clrscr\r
+ lda #<ScrBase ; Fill whole video RAM with blanks by calling\r
+ ldx #>ScrBase ; memset appropriately\r
+ jsr pushax\r
+ \r
+ lda #' '\r
+ ldx #$00\r
+ jsr pushax\r
+ \r
+ lda #<ScrRamSize\r
+ ldx #>ScrRamSize\r
+ jsr _memset\r
+\r
+ lda #$00 ; Cursor in upper left corner\r
+ sta CURS_X\r
+ sta CURS_Y\r
+ \r
+ jmp plot ; Set the cursor position\r
+.endproc\r
+\r
+.endmacro\r
+\r
+;\r
+; cputc/cputcxy for Challenger 1P\r
+; Based on PET/CBM implementation\r
+;\r
+\r
+.macro osi_cputfuncs ScrBase, ScrFirstChar, ScrWidth, ScrHeight, \\r
+ ScrollDist, ScrLo, ScrHi\r
+\r
+ ; Number of characters to move for scrolling\r
+ ; by one line\r
+ScrollLength = (ScrHeight - 1) * ScrollDist\r
+\r
+;\r
+; void cputcxy (unsigned char x, unsigned char y, char c);\r
+; void cputc (char c);\r
+;\r
+ .export _cputcxy, _cputc, cputdirect, putchar\r
+ .export newline, plot\r
+\r
+_cputcxy:\r
+ pha ; Save C\r
+ jsr popa ; Get Y\r
+ jsr _gotoxy ; Set cursor, drop x\r
+ pla ; Restore C\r
+\r
+; Plot a character - also used as internal function\r
+\r
+_cputc: cmp #$0A ; CR?\r
+ bne L1\r
+ lda #0\r
+ sta CURS_X\r
+ beq plot ; Recalculate pointers\r
+\r
+L1: cmp #$0D ; LF?\r
+ beq newline ; Recalculate pointers\r
+\r
+cputdirect:\r
+ jsr putchar ; Write the character to the screen\r
+\r
+; Advance cursor position, register Y contains horizontal position after\r
+; putchar\r
+\r
+ cpy #(ScrWidth - 1) ; Check whether line is full\r
+ bne L3\r
+ jsr newline ; New line\r
+ ldy #$FF ; + cr\r
+L3: iny\r
+ sty CURS_X\r
+ rts\r
+\r
+newline:\r
+ inc CURS_Y\r
+ lda CURS_Y\r
+ cmp #ScrHeight ; Screen height\r
+ bne plot\r
+ dec CURS_Y ; Bottom of screen reached, scroll\r
+\r
+ ; Scroll destination address\r
+ lda #<(ScrBase + ScrFirstChar)\r
+ ldx #>(ScrBase + ScrFirstChar)\r
+ jsr pushax\r
+ \r
+ ; Scroll source address\r
+ lda #<(ScrBase + ScrFirstChar + ScrollDist)\r
+ ldx #>(ScrBase + ScrFirstChar + ScrollDist)\r
+ jsr pushax\r
+ \r
+ ; Number of characters to move\r
+ lda #<ScrollLength\r
+ ldx #>ScrollLength\r
+ jsr _memmove\r
+\r
+ ; Address of first character in last line\r
+ ; of screen\r
+ lda #<(ScrBase + ScrFirstChar + ScrollLength)\r
+ sta ptr1\r
+ lda #>(ScrBase + ScrFirstChar + ScrollLength)\r
+ sta ptr1+1\r
+ \r
+ ldy #ScrWidth ; Fill last line with blanks\r
+ lda #' '\r
+clrln: sta (ptr1),y\r
+ dey\r
+ bpl clrln\r
+\r
+plot: ldy CURS_Y\r
+ lda ScrLo,y\r
+ sta SCREEN_PTR\r
+ lda ScrHi,y\r
+ sta SCREEN_PTR+1\r
+ rts\r
+\r
+; Write one character to the screen without doing anything else, return X\r
+; position in register Y\r
+\r
+putchar:\r
+ ldy CURS_X\r
+ sta (SCREEN_PTR),y ; Set char\r
+ rts\r
+ \r
+.endmacro\r
+\r
+.macro osi_screen_funcs ScrBase, ScrRamSize, ScrFirstChar, \\r
+ ScrWidth, ScrHeight, ScrollDist\r
+\r
+ .import popa, _gotoxy\r
+ .import _memmove, _memset, pushax\r
+ .importzp ptr1\r
+\r
+.rodata\r
+\r
+; Screen address tables - offset to real screen\r
+ScrTabLo:\r
+ .repeat ScrHeight, I\r
+ .byte <(ScrBase + ScrFirstChar + I * ScrollDist)\r
+ .endrep\r
+ \r
+ScrTabHi:\r
+ .repeat ScrHeight, I\r
+ .byte >(ScrBase + ScrFirstChar + I * ScrollDist)\r
+ .endrep\r
+\r
+.code\r
+\r
+osi_cputfuncs ScrBase, ScrFirstChar, ScrWidth, ScrHeight, \\r
+ ScrollDist, ScrTabLo, ScrTabHi\r
+osi_screensize ScrWidth, ScrHeight\r
+osi_clrscr ScrBase, ScrRamSize\r
+\r
+.endmacro
\ No newline at end of file