From 7f1e69f5e011d540e7a303e57fd9478ad47c47be Mon Sep 17 00:00:00 2001 From: Karri Kaksonen Date: Mon, 4 Apr 2022 10:51:43 +0300 Subject: [PATCH] Add cursor processing --- libsrc/atari7800/setcursor.s | 169 +++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 libsrc/atari7800/setcursor.s diff --git a/libsrc/atari7800/setcursor.s b/libsrc/atari7800/setcursor.s new file mode 100644 index 000000000..9f8765656 --- /dev/null +++ b/libsrc/atari7800/setcursor.s @@ -0,0 +1,169 @@ +; +; 2022-04-03, Karri Kaksonen +; +; setcursor (unsigned char on); +; +; The Atari 7800 does not have a hw cursor. +; This module emulates a cursor to be used with the conio +; implementation. +; +; The actual cursor display is included in the conio dll +; but every scanline has the element silenced by default +; at the end of every zone. +; +; The way the cursor works is to silence it before the cursor +; position changes and enable it afterwards. +; +; In order to get some performance we have a pointer to the +; cursor header structure. This structure is always at the +; end of the zone. So the pointer changes when CURS_Y changes. +; +; There is so many dependencies that it makes sense to +; deal with all CURS_X, CURS_Y stuff in this file and +; definitely not allow direct access to the variables. +; + + .export _cursor_visible + .export _cursorzone + .export _gotoxy, _gotox, _gotoy, wherex, wherey + .constructor init_cursor + + .importzp ptr1, sp + .import _zones + .import pusha, incsp1, pusha0, pushax, popax, tosumula0, incax5 + .include "atari7800.inc" + + .macpack generic + + .data +CURS_X: + .byte 0 +CURS_Y: + .byte 0 +_cursor_visible: + .byte 1 + + .bss +_cursorzone: + .res 2 + + .code + +;----------------------------------------------------------------------------- +; Calculate cursorzone address +; You also need to set the cursorzone to point to the correct cursor Header +; at the end of line CURS_Y. +; Offset to cursor zone 5. To next line offset 11 +; cursorzone points to _zones + CURS_Y * 11 + 5 +; A = CURS_Y +calccursorzone: + jsr pusha0 + lda #11 + jsr tosumula0 + jsr incax5 + clc + adc #<_zones + sta _cursorzone ; calculate new cursorzone + sta ptr1 + txa + adc #>_zones + sta _cursorzone+1 + sta ptr1+1 + rts + +;----------------------------------------------------------------------------- +; Set cursor to Y position. +; You also need to set the cursorzone to point to the correct cursor Header +; at the end of line CURS_Y. +; Offset to cursor zone 5. To next line offset 11 +; cursorzone points to _zones + CURS_Y * 11 + 5 +; +; cursorzone[1] = 0 when not CURS_Y, 30 if CURS_Y +; +; Disable cursor +; cursorzone[1] = 0 +; +; Enable cursor +; if showcursor cursorzone[1] = 30 +; +_gotoy: pha + lda CURS_Y + jsr calccursorzone + ldy #1 + lda #0 + sta (ptr1),y ; disable cursor + pla + sta CURS_Y + jsr calccursorzone + lda _cursor_visible + beq L2 + lda #30 ; enable cursor +L2: ldy #1 + sta (ptr1),y + rts + +;----------------------------------------------------------------------------- +; Set cursor to X position. +; You also need to set the hpos offset to the correct value on this line +; cursorzone[3] = 8 * CURS_X +; +_gotox: tay + lda _cursorzone + ldx _cursorzone+1 + sta ptr1 + stx ptr1+1 + tya + ldy #3 + clc + rol + rol + rol + sta (ptr1),y + rts + +;----------------------------------------------------------------------------- +; Set cursor to desired position (X,Y) +; + .proc _gotoxy + + jsr _gotoy + jsr popax + jsr _gotox + rts + .endproc + +;----------------------------------------------------------------------------- +; Get cursor X position +; + .proc wherex + + lda CURS_X + jsr pusha0 + rts + .endproc + +;----------------------------------------------------------------------------- +; Get cursor Y position +; + .proc wherey + + lda CURS_Y + jsr pusha0 + rts + .endproc + +;----------------------------------------------------------------------------- +; Initialize cursorzone at startup +; Offset to cursor zone 5. +; +; .segment "ONCE" +init_cursor: + lda #0 + jsr calccursorzone + rts + +;----------------------------------------------------------------------------- +; force the init constructor to be imported + + .import initconio +conio_init = initconio