From 057884ffa921eb2b19b152a1623da4d318d17e12 Mon Sep 17 00:00:00 2001 From: Christian Groessler <chris@groessler.org> Date: Thu, 2 Jan 2014 19:28:22 +0100 Subject: [PATCH 01/31] Atari: initial support to create cassette bootable programs -- unfinished --- cfg/atari-cassette.cfg | 53 ++++++++++++++++++++++++++++++++++++++++++ libsrc/atari/cashdr.s | 40 +++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 cfg/atari-cassette.cfg create mode 100644 libsrc/atari/cashdr.s diff --git a/cfg/atari-cassette.cfg b/cfg/atari-cassette.cfg new file mode 100644 index 000000000..ba640a54e --- /dev/null +++ b/cfg/atari-cassette.cfg @@ -0,0 +1,53 @@ +FEATURES { + STARTADDRESS: default = $1000; +} +SYMBOLS { +_cas_init: type = import; + __STACKSIZE__: type = weak, value = $0800; # 2k stack + __STARTADDRESS__: type = export, value = %S; + __RESERVED_MEMORY__: type = weak, value = $0000; +} +MEMORY { + ZP: file = "", define = yes, start = $0082, size = $007E; + +# file header, just $FFFF +# HEADER: file = "", start = $0000, size = $0002; + +# CASHDR: file = %O, start = $3FD, size = 128, fill = yes; + CASHDR: file = %O, start = $0, size = 6; +# "main program" load chunk +# MAINHDR: file = "", start = $0000, size = $0004; + RAM: file = %O, define = yes, start = %S, size = $BC20 - __STACKSIZE__ - __RESERVED_MEMORY__ - %S; +# TRAILER: file = "", start = $0000, size = $0006; +} +SEGMENTS { +# EXEHDR: load = HEADER, type = ro; +# MAINHDR: load = MAINHDR, type = ro; + CASHDR: load = CASHDR, type = ro; + CASINIT: load = RAM, type = ro; + STARTUP: load = RAM, type = ro, define = yes; + LOWCODE: load = RAM, type = ro, define = yes, optional = yes; + INIT: load = RAM, type = ro, optional = yes; + CODE: load = RAM, type = ro, define = yes; + RODATA: load = RAM, type = ro; + DATA: load = RAM, type = rw; + BSS: load = RAM, type = bss, define = yes; + ZEROPAGE: load = ZP, type = zp; + EXTZP: load = ZP, type = zp, optional = yes; +# AUTOSTRT: load = TRAILER, type = ro; +} +FEATURES { + CONDES: type = constructor, + label = __CONSTRUCTOR_TABLE__, + count = __CONSTRUCTOR_COUNT__, + segment = INIT; + CONDES: type = destructor, + label = __DESTRUCTOR_TABLE__, + count = __DESTRUCTOR_COUNT__, + segment = RODATA; + CONDES: type = interruptor, + label = __INTERRUPTOR_TABLE__, + count = __INTERRUPTOR_COUNT__, + segment = RODATA, + import = __CALLIRQ__; +} diff --git a/libsrc/atari/cashdr.s b/libsrc/atari/cashdr.s new file mode 100644 index 000000000..8d3d0868a --- /dev/null +++ b/libsrc/atari/cashdr.s @@ -0,0 +1,40 @@ +; +; Cassette boot file header +; +; Christian Groessler, chris@groessler.org, 2013 +; + +.ifndef __ATARIXL__ + + .include "atari.inc" + + .import __BSS_RUN__, __STARTADDRESS__, start + .export _cas_init + +.segment "CASHDR" + + .byte 0 ; ignored + .byte <((__BSS_RUN__ - __STARTADDRESS__ + 127 + 6) / 128) + .word __STARTADDRESS__ + .word _cas_init + +.segment "CASINIT" + + lda #33 + ldy #80 + sta (SAVMSC),y + clc + rts + +_cas_init: + lda #34 + ldy #81 + sta (SAVMSC),y + + lda #<start + sta DOSVEC + lda #>start + sta DOSVEC+1 + rts + +.endif ; .ifdef __ATARIXL__ From 2ab89621a9cee8cf32176f750d9ac9ffedaef7e0 Mon Sep 17 00:00:00 2001 From: Christian Groessler <chris@groessler.org> Date: Thu, 2 Jan 2014 21:45:12 +0100 Subject: [PATCH 02/31] Use deferred VBI instead of immediate VBI. A deferred VBI won't be called if the user program has interrupts disabled which makes it easier to avoid race conditions. --- libsrc/atari/irq.s | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/libsrc/atari/irq.s b/libsrc/atari/irq.s index 8ec1b12df..9f12d47ed 100644 --- a/libsrc/atari/irq.s +++ b/libsrc/atari/irq.s @@ -16,11 +16,11 @@ .segment "INIT" initirq: - lda VVBLKI - ldx VVBLKI+1 + lda VVBLKD + ldx VVBLKD+1 sta IRQInd+1 stx IRQInd+2 - lda #6 + lda #7 ldy #<IRQStub ldx #>IRQStub jsr SETVBV @@ -31,7 +31,7 @@ initirq: .code doneirq: - lda #6 + lda #7 ldy IRQInd+1 ldx IRQInd+2 jsr SETVBV @@ -44,7 +44,6 @@ doneirq: IRQStub: cld ; Just to be sure .ifdef __ATARIXL__ - pha .ifdef CHARGEN_RELOC lda CHBAS pha @@ -64,7 +63,6 @@ IRQStub: sta CHBAS sta CHBASE .endif - pla .endif jmp IRQInd ; Jump to the saved IRQ vector From 95c6063f909e6e5c6bf9330e23cb472c12914005 Mon Sep 17 00:00:00 2001 From: Christian Groessler <chris@groessler.org> Date: Fri, 3 Jan 2014 23:40:22 +0100 Subject: [PATCH 03/31] Add "joystick mouse" driver and default mouse callback routine (not using P/M graphics). --- libsrc/atari/libref.s | 3 +- libsrc/atari/mcbdefault.s | 114 ++++++++ libsrc/atari/mou/atrjoy.s | 443 +++++++++++++++++++++++++++++++ libsrc/atari/mouse_stat_stddrv.s | 22 ++ libsrc/atari/mouse_stddrv.s | 18 ++ libsrc/atari/mul40.s | 2 +- 6 files changed, 600 insertions(+), 2 deletions(-) create mode 100644 libsrc/atari/mcbdefault.s create mode 100644 libsrc/atari/mou/atrjoy.s create mode 100644 libsrc/atari/mouse_stat_stddrv.s create mode 100644 libsrc/atari/mouse_stddrv.s diff --git a/libsrc/atari/libref.s b/libsrc/atari/libref.s index 8d96ff62d..e6b9df6a5 100644 --- a/libsrc/atari/libref.s +++ b/libsrc/atari/libref.s @@ -2,12 +2,13 @@ ; Oliver Schmidt, 2013-05-31 ; - .export em_libref, joy_libref, tgi_libref, ser_libref + .export em_libref, joy_libref, tgi_libref, ser_libref, mouse_libref .import _exit .import atari_ser_libref em_libref := _exit joy_libref := _exit +mouse_libref := _exit ser_libref := atari_ser_libref .ifdef __ATARIXL__ .import CIO_handler diff --git a/libsrc/atari/mcbdefault.s b/libsrc/atari/mcbdefault.s new file mode 100644 index 000000000..91e920ac4 --- /dev/null +++ b/libsrc/atari/mcbdefault.s @@ -0,0 +1,114 @@ +; +; Default mouse callbacks for the Ataris +; +; Christian Groessler, 03.01.2014 +; +; derived from Apple2 version by +; Oliver Schmidt, 22.09.2005 +; +; All functions in this module should be interrupt safe, because they may +; be called from an interrupt handler +; + + .export _mouse_def_callbacks + .importzp tmp4 + .import mul40,loc_tmp + + .include "atari.inc" + +; ------------------------------------------------------------------------ + + .bss + +backup: .res 1 +helper: .res 2 + +; ------------------------------------------------------------------------ + + .segment "EXTZP" : zeropage +scrptr: .res 2 + +; ------------------------------------------------------------------------ + + + .rodata + + ; Callback structure +_mouse_def_callbacks: + .addr hide + .addr show + .addr movex + .addr movey + +; ------------------------------------------------------------------------ + + .data + +cursor = 11 ; '+' screen code' + +; setcursor + +getcursor: +column: ldy #$00 ; Patched at runtime + lda (scrptr),y ; Patched at runtime + cmp #cursor + rts + +setcursor: + lda #cursor +setscr: sta (scrptr),y ; Patched at runtime + rts + +; ------------------------------------------------------------------------ + + .code + +done: + rts + +; Hide the mouse cursor. +hide: + jsr getcursor ; Cursor visible at current position? + bne done ; No, we're done + lda backup ; Get character at cursor position + jmp setscr ; Draw character + +; Show the mouse cursor. +show: + jsr getcursor ; Cursor visible at current position? + beq done ; Yes, we're done + sta backup ; Save character at cursor position + jmp setcursor ; Draw cursor + + +; Move the mouse cursor x position to the value in A/X. +movex: + cpx #0 + cpx #1 + ror a + lsr a ; convert to character position + lsr a + sta column+1 + rts + +; Move the mouse cursor y position to the value in A/X. +movey: + tax + ldy tmp4 ; mul40 uses tmp4 + lda loc_tmp ; and this local variable + pha + txa ; get parameter back + lsr a ; convert y position to character line + lsr a + lsr a + jsr mul40 + clc + adc SAVMSC + sta scrptr + txa + adc SAVMSC+1 + sta scrptr+1 + pla + sta loc_tmp + sty tmp4 + rts diff --git a/libsrc/atari/mou/atrjoy.s b/libsrc/atari/mou/atrjoy.s new file mode 100644 index 000000000..1a5afa71a --- /dev/null +++ b/libsrc/atari/mou/atrjoy.s @@ -0,0 +1,443 @@ +; +; Driver for a "joystick mouse". +; +; C128 version: Ullrich von Bassewitz, 2004-04-05, 2009-09-26 +; Adapted to Atari: Christian Groessler, 2014-01-02 +; + + .include "zeropage.inc" + .include "mouse-kernel.inc" + .include "atari.inc" + + .macpack generic + +; ------------------------------------------------------------------------ +; Header. Includes jump table + +.segment "JUMPTABLE" + +HEADER: + +; Driver signature + + .byte $6d, $6f, $75 ; "mou" + .byte MOUSE_API_VERSION ; Mouse driver API version number + +; Library reference + + .addr $0000 + +; Jump table + + .addr INSTALL + .addr UNINSTALL + .addr HIDE + .addr SHOW + .addr SETBOX + .addr GETBOX + .addr MOVE + .addr BUTTONS + .addr POS + .addr INFO + .addr IOCTL + .addr IRQ + +; Mouse driver flags + + .byte MOUSE_FLAG_LATE_IRQ + +; Callback table, set by the kernel before INSTALL is called + +CHIDE: jmp $0000 ; Hide the cursor +CSHOW: jmp $0000 ; Show the cursor +CMOVEX: jmp $0000 ; Move the cursor to X coord +CMOVEY: jmp $0000 ; Move the cursor to Y coord + + +;---------------------------------------------------------------------------- +; Constants + +SCREEN_HEIGHT = 191 +SCREEN_WIDTH = 319 + +.enum JOY + UP = $01 + DOWN = $02 + LEFT = $04 + RIGHT = $08 +.endenum + +;---------------------------------------------------------------------------- +; Global variables. The bounding box values are sorted so that they can be +; written with the least effort in the SETBOX and GETBOX routines, so don't +; reorder them. + +.bss + +Vars: +YPos: .res 2 ; Current mouse position, Y +XPos: .res 2 ; Current mouse position, X +XMin: .res 2 ; X1 value of bounding box +YMin: .res 2 ; Y1 value of bounding box +XMax: .res 2 ; X2 value of bounding box +YMax: .res 2 ; Y2 value of bounding box +Buttons: .res 1 ; Button mask + + +Temp: .res 1 ; Temporary value used in the int handler +visible: .res 1 + +; Default values for above variables + +.rodata + +.proc DefVars + .word SCREEN_HEIGHT/2 ; YPos + .word SCREEN_WIDTH/2 ; XPos + .word 0 ; XMin + .word 0 ; YMin + .word SCREEN_WIDTH ; XMax + .word SCREEN_HEIGHT ; YMax + .byte 0 ; Buttons +.endproc + +.code + +;---------------------------------------------------------------------------- +; INSTALL routine. Is called after the driver is loaded into memory. If +; possible, check if the hardware is present. +; Must return an MOUSE_ERR_xx code in a/x. + +INSTALL: + +; Initialize variables. Just copy the default stuff over + + ldx #.sizeof(DefVars)-1 +@L1: lda DefVars,x + sta Vars,x + dex + bpl @L1 + +; Be sure the mouse cursor is invisible and at the default location. We +; need to do that here, because our mouse interrupt handler doesn't set the +; mouse position if it hasn't changed. + + sei + jsr CHIDE + lda XPos + ldx XPos+1 + jsr CMOVEX + lda YPos + ldx YPos+1 + jsr CMOVEY + cli + +; Done, return zero (= MOUSE_ERR_OK) + + ldx #$00 + txa + rts + +;---------------------------------------------------------------------------- +; UNINSTALL routine. Is called before the driver is removed from memory. +; No return code required (the driver is removed from memory on return). + +UNINSTALL = HIDE ; Hide cursor on exit + +;---------------------------------------------------------------------------- +; HIDE routine. Is called to hide the mouse pointer. The mouse kernel manages +; a counter for calls to show/hide, and the driver entry point is only called +; if the mouse is currently visible and should get hidden. For most drivers, +; no special action is required besides hiding the mouse cursor. +; No return code required. + +HIDE: dec visible + sei + jsr CHIDE + cli + rts + +;---------------------------------------------------------------------------- +; SHOW routine. Is called to show the mouse pointer. The mouse kernel manages +; a counter for calls to show/hide, and the driver entry point is only called +; if the mouse is currently hidden and should become visible. For most drivers, +; no special action is required besides enabling the mouse cursor. +; No return code required. + +SHOW: inc visible + sei + jsr CSHOW + cli + rts + +;---------------------------------------------------------------------------- +; SETBOX: Set the mouse bounding box. The parameters are passed as they come +; from the C program, that is, a pointer to a mouse_box struct in a/x. +; No checks are done if the mouse is currently inside the box, this is the job +; of the caller. It is not necessary to validate the parameters, trust the +; caller and save some code here. No return code required. + +SETBOX: sta ptr1 + stx ptr1+1 ; Save data pointer + + ldy #.sizeof (MOUSE_BOX)-1 + sei + +@L1: lda (ptr1),y + sta XMin,y + dey + bpl @L1 + + cli + rts + +;---------------------------------------------------------------------------- +; GETBOX: Return the mouse bounding box. The parameters are passed as they +; come from the C program, that is, a pointer to a mouse_box struct in a/x. + +GETBOX: sta ptr1 + stx ptr1+1 ; Save data pointer + + ldy #.sizeof (MOUSE_BOX)-1 + sei + +@L1: lda XMin,y + sta (ptr1),y + dey + bpl @L1 + + cli + rts + +;---------------------------------------------------------------------------- +; MOVE: Move the mouse to a new position. The position is passed as it comes +; from the C program, that is: X on the stack and Y in a/x. The C wrapper will +; remove the parameter from the stack on return. +; No checks are done if the new position is valid (within the bounding box or +; the screen). No return code required. +; + +MOVE: sei ; No interrupts + + pha + txa + pha + jsr CHIDE + pla + tax + pla + + sta YPos + stx YPos+1 ; New Y position + jsr CMOVEY ; Set it + + ldy #$01 + lda (sp),y + sta XPos+1 + tax + dey + lda (sp),y + sta XPos ; New X position + + jsr CMOVEX ; Move the cursor + + lda visible + beq @Ret + + jsr CSHOW + +@Ret: cli ; Allow interrupts + rts + +;---------------------------------------------------------------------------- +; BUTTONS: Return the button mask in a/x. + +BUTTONS: + lda Buttons + ldx #$00 + rts + +;---------------------------------------------------------------------------- +; POS: Return the mouse position in the MOUSE_POS struct pointed to by ptr1. +; No return code required. + +POS: ldy #MOUSE_POS::XCOORD ; Structure offset + + sei ; Disable interrupts + lda XPos ; Transfer the position + sta (ptr1),y + lda XPos+1 + iny + sta (ptr1),y + lda YPos + iny + sta (ptr1),y + lda YPos+1 + cli ; Enable interrupts + + iny + sta (ptr1),y ; Store last byte + + rts ; Done + +;---------------------------------------------------------------------------- +; INFO: Returns mouse position and current button mask in the MOUSE_INFO +; struct pointed to by ptr1. No return code required. +; +; We're cheating here to keep the code smaller: The first fields of the +; mouse_info struct are identical to the mouse_pos struct, so we will just +; call _mouse_pos to initialize the struct pointer and fill the position +; fields. + +INFO: jsr POS + +; Fill in the button state + + lda Buttons + ldy #MOUSE_INFO::BUTTONS + sta (ptr1),y + + rts + +;---------------------------------------------------------------------------- +; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl +; specific data in ptr1, and the ioctl code in A. +; Must return an error code in a/x. +; + +IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioclts for now + ldx #>MOUSE_ERR_INV_IOCTL +hlprts: rts + +;---------------------------------------------------------------------------- +; IRQ: Irq handler entry point. Called as a subroutine but in IRQ context +; (so be careful). The routine MUST return carry set if the interrupt has been +; 'handled' - which means that the interrupt source is gone. Otherwise it +; MUST return carry clear. +; + +IRQ: + +; Check for a pressed button and place the result into Buttons + + ldx #0 + lda TRIG0 ; joystick #0 trigger + bne @L0 ; not pressed + ldx #MOUSE_BTN_LEFT +@L0: stx Buttons + + lda PORTA ; get joystick direction bits + and #15 ; clear joystick #1 bits + eor #15 + sta Temp + clc + beq hlprts ; no movement, do nothing + + jsr CHIDE + +; Check left/right + + lda Temp ; Read joystick #0 + and #(JOY::LEFT | JOY::RIGHT) + beq @SkipX ; + +; We will cheat here and rely on the fact that either the left, OR the right +; bit can be active + + and #JOY::RIGHT ; Check RIGHT bit + bne @Right + lda #$FF + tax + bne @AddX ; Branch always +@Right: lda #$01 + ldx #$00 + +; Calculate the new X coordinate (--> a/y) + +@AddX: add XPos + tay ; Remember low byte + txa + adc XPos+1 + tax + +; Limit the X coordinate to the bounding box + + cpy XMin + sbc XMin+1 + bpl @L1 + ldy XMin + ldx XMin+1 + jmp @L2 +@L1: txa + + cpy XMax + sbc XMax+1 + bmi @L2 + ldy XMax + ldx XMax+1 +@L2: sty XPos + stx XPos+1 + +; Move the mouse pointer to the new X pos + + tya + jsr CMOVEX + +; Calculate the Y movement vector + +@SkipX: lda Temp ; Read joystick #0 + and #(JOY::UP | JOY::DOWN) ; Check up/down + beq @SkipY ; + +; We will cheat here and rely on the fact that either the up, OR the down +; bit can be active + + lsr a + bcc @Down + lda #$FF + tax + bne @AddY +@Down: lda #$01 + ldx #$00 + +; Calculate the new Y coordinate (--> a/y) + +@AddY: add YPos + tay ; Remember low byte + txa + adc YPos+1 + tax + +; Limit the Y coordinate to the bounding box + + cpy YMin + sbc YMin+1 + bpl @L3 + ldy YMin + ldx YMin+1 + jmp @L4 +@L3: txa + + cpy YMax + sbc YMax+1 + bmi @L4 + ldy YMax + ldx YMax+1 +@L4: sty YPos + stx YPos+1 + +; Move the mouse pointer to the new X pos + + tya + jsr CMOVEY + +; Done + +@SkipY: lda visible + beq @Done + + jsr CSHOW + +@Done: clc ; Interrupt not "handled" + rts + diff --git a/libsrc/atari/mouse_stat_stddrv.s b/libsrc/atari/mouse_stat_stddrv.s new file mode 100644 index 000000000..18ebda9a2 --- /dev/null +++ b/libsrc/atari/mouse_stat_stddrv.s @@ -0,0 +1,22 @@ +; +; Address of the static standard mouse driver +; +; Christian Groessler, 2014-01-02 +; +; const void mouse_static_stddrv[]; +; + + .export _mouse_static_stddrv + .ifdef __ATARIXL__ + .import _atrxjoy_mou + .else + .import _atrjoy_mou + .endif + +.rodata + + .ifdef __ATARIXL__ +_mouse_static_stddrv := _atrxjoy_mou + .else +_mouse_static_stddrv := _atrjoy_mou + .endif diff --git a/libsrc/atari/mouse_stddrv.s b/libsrc/atari/mouse_stddrv.s new file mode 100644 index 000000000..443e53254 --- /dev/null +++ b/libsrc/atari/mouse_stddrv.s @@ -0,0 +1,18 @@ +; +; Name of the standard mouse driver +; +; Christian Groessler, 2014-01-02 +; +; const char mouse_stddrv[]; +; + + .export _mouse_stddrv + +.rodata + +_mouse_stddrv: + .ifdef __ATARIXL__ + .asciiz "ATRXJOY.MOU" + .else + .asciiz "ATRJOY.MOU" + .endif diff --git a/libsrc/atari/mul40.s b/libsrc/atari/mul40.s index b94ab5c52..96235bf6c 100644 --- a/libsrc/atari/mul40.s +++ b/libsrc/atari/mul40.s @@ -6,7 +6,7 @@ ; uses tmp4 .importzp tmp4 - .export mul40 + .export mul40,loc_tmp .proc mul40 From 95bf72f12397a02f550e1c60983163171604ed4e Mon Sep 17 00:00:00 2001 From: Christian Groessler <chris@groessler.org> Date: Sat, 4 Jan 2014 16:37:59 +0100 Subject: [PATCH 04/31] fix typo --- asminc/atari.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/asminc/atari.inc b/asminc/atari.inc index c60f6642d..49a125efb 100644 --- a/asminc/atari.inc +++ b/asminc/atari.inc @@ -318,7 +318,7 @@ APPMHI = $0E ;APPLICATIONS MEMORY HI LIMIT INTZBS = $10 ;INTERRUPT HANDLER -POKMSK = $10 ;SYSTEM MASK FOR POKEY IRG ENABLE +POKMSK = $10 ;SYSTEM MASK FOR POKEY IRQ ENABLE BRKKEY = $11 ;BREAK KEY FLAG RTCLOK = $12 ;REAL TIME CLOCK (IN 16 MSEC UNITS> BUFADR = $15 ;INDIRECT BUFFER ADDRESS REGISTER From d742eeca9fd10158cdd08237975848917997b570 Mon Sep 17 00:00:00 2001 From: Christian Groessler <chris@groessler.org> Date: Sat, 4 Jan 2014 18:28:24 +0100 Subject: [PATCH 05/31] Add drivers for ST mouse, Amiga mouse, and Atari trakball. Access routines taken from old mouse.s. --- libsrc/atari/mou/atrami.s | 2 + libsrc/atari/mou/atrst.s | 695 ++++++++++++++++++++++++++++++++++++ libsrc/atari/mou/atrtrk.s | 2 + libsrc/atari/mouse.s_ | 576 ------------------------------ libsrc/atari/mouse_stddrv.s | 4 +- 5 files changed, 701 insertions(+), 578 deletions(-) create mode 100644 libsrc/atari/mou/atrami.s create mode 100644 libsrc/atari/mou/atrst.s create mode 100644 libsrc/atari/mou/atrtrk.s delete mode 100644 libsrc/atari/mouse.s_ diff --git a/libsrc/atari/mou/atrami.s b/libsrc/atari/mou/atrami.s new file mode 100644 index 000000000..21e1b4c81 --- /dev/null +++ b/libsrc/atari/mou/atrami.s @@ -0,0 +1,2 @@ +AMIGA_MOUSE = 1 +.include "atrst.s" diff --git a/libsrc/atari/mou/atrst.s b/libsrc/atari/mou/atrst.s new file mode 100644 index 000000000..1e7e77b3a --- /dev/null +++ b/libsrc/atari/mou/atrst.s @@ -0,0 +1,695 @@ +; +; Mouse driver for ST & Amiga mouses and Atari trakball. +; +; Original access routines: 05/07/2000 Freddy Offenga +; Converted to driver: Christian Groessler, 2014-01-04 +; +; Defines: +; AMIGA_MOUSE - builds Amiga mouse version +; TRAK_MOUSE - builds trakball version +; If none of these defines are active, the ST mouse version +; is being built. +; + + .include "zeropage.inc" + .include "mouse-kernel.inc" + .include "atari.inc" + + .macpack generic + +.if .not ( .defined (AMIGA_MOUSE) .or .defined (TRAK_MOUSE)) + ST_MOUSE = 1 +.endif + +; ------------------------------------------------------------------------ +; Header. Includes jump table + +.segment "JUMPTABLE" + +HEADER: + +; Driver signature + + .byte $6d, $6f, $75 ; "mou" + .byte MOUSE_API_VERSION ; Mouse driver API version number + +; Library reference + + .addr $0000 + +; Jump table + + .addr INSTALL + .addr UNINSTALL + .addr HIDE + .addr SHOW + .addr SETBOX + .addr GETBOX + .addr MOVE + .addr BUTTONS + .addr POS + .addr INFO + .addr IOCTL + .addr IRQ + +; Mouse driver flags + + .byte MOUSE_FLAG_LATE_IRQ + +; Callback table, set by the kernel before INSTALL is called + +CHIDE: jmp $0000 ; Hide the cursor +CSHOW: jmp $0000 ; Show the cursor +CMOVEX: jmp $0000 ; Move the cursor to X coord +CMOVEY: jmp $0000 ; Move the cursor to Y coord + + +;---------------------------------------------------------------------------- +; Constants + +SCREEN_HEIGHT = 191 +SCREEN_WIDTH = 319 + +.enum JOY + UP = $01 + DOWN = $02 + LEFT = $04 + RIGHT = $08 +.endenum + +;---------------------------------------------------------------------------- +; Global variables. The bounding box values are sorted so that they can be +; written with the least effort in the SETBOX and GETBOX routines, so don't +; reorder them. + +.bss + +Vars: +YPos: .res 2 ; Current mouse position, Y +XPos: .res 2 ; Current mouse position, X +XMin: .res 2 ; X1 value of bounding box +YMin: .res 2 ; Y1 value of bounding box +XMax: .res 2 ; X2 value of bounding box +YMax: .res 2 ; Y2 value of bounding box +Buttons: .res 1 ; Button mask + +XPosWrk: .res 2 +YPosWrk: .res 2 + +OldT1: .res 2 +visible: .res 1 + +.if .defined (AMIGA_MOUSE) .or .defined (ST_MOUSE) +dumx: .res 1 +dumy: .res 1 +.endif + +.ifdef TRAK_MOUSE +oldval: .res 1 +.endif + + +; Default values for some of the above variables + +.rodata + +.proc DefVars + .word (SCREEN_HEIGHT+1)/2 ; YPos + .word (SCREEN_WIDTH+1)/2 ; XPos + .word 0 ; XMin + .word 0 ; YMin + .word SCREEN_WIDTH ; XMax + .word SCREEN_HEIGHT ; YMax + .byte 0 ; Buttons +.endproc + +.ifdef ST_MOUSE + +; ST mouse lookup table + +STTab: .byte $FF,$01,$00,$01 + .byte $00,$FF,$00,$01 + .byte $01,$00,$FF,$00 + .byte $01,$00,$01,$FF + +.endif + +.ifdef AMIGA_MOUSE + +; Amiga mouse lookup table + +AmiTab: .byte $FF,$01,$00,$FF + .byte $00,$FF,$FF,$01 + .byte $01,$FF,$FF,$00 + .byte $FF,$00,$01,$FF + +.endif + +.code + +;---------------------------------------------------------------------------- +; INSTALL routine. Is called after the driver is loaded into memory. If +; possible, check if the hardware is present. +; Must return an MOUSE_ERR_xx code in a/x. + +INSTALL: + +; Initialize variables. Just copy the default stuff over + + ldx #.sizeof(DefVars)-1 +@L1: lda DefVars,x + sta Vars,x + dex + bpl @L1 + +; Be sure the mouse cursor is invisible and at the default location. We +; need to do that here, because our mouse interrupt handler doesn't set the +; mouse position if it hasn't changed. + + sei + jsr CHIDE + lda XPos + sta XPosWrk + ldx XPos+1 + stx XPosWrk+1 + jsr CMOVEX + lda YPos + sta YPosWrk + ldx YPos+1 + stx YPosWrk+1 + jsr CMOVEY + cli + +; install timer irq routine to poll mouse + + lda VTIMR1 + sta OldT1 + lda VTIMR1+1 + sta OldT1+1 + + php + sei + lda #<T1Han + sta VTIMR1 + lda #>T1Han + sta VTIMR1+1 + plp + + lda #%00000001 + sta AUDCTL + + lda #0 + sta AUDC1 + + lda #15 + sta AUDF1 + sta STIMER + + lda POKMSK + ora #%00000001 ; timer 1 enable + sta POKMSK + sta IRQEN + +; Done, return zero (= MOUSE_ERR_OK) + + ldx #$00 + txa + rts + +;---------------------------------------------------------------------------- +; UNINSTALL routine. Is called before the driver is removed from memory. +; No return code required (the driver is removed from memory on return). + +UNINSTALL: + +; uninstall timer irq routine + + lda POKMSK + and #%11111110 ; timer 1 disable + sta IRQEN + sta POKMSK + + php + sei + lda OldT1 + sta VTIMR1 + lda OldT1+1 + sta VTIMR1+1 + plp + + ; fall thru... + +;---------------------------------------------------------------------------- +; HIDE routine. Is called to hide the mouse pointer. The mouse kernel manages +; a counter for calls to show/hide, and the driver entry point is only called +; if the mouse is currently visible and should get hidden. For most drivers, +; no special action is required besides hiding the mouse cursor. +; No return code required. + +HIDE: dec visible + php + sei + jsr CHIDE + plp + rts + +;---------------------------------------------------------------------------- +; SHOW routine. Is called to show the mouse pointer. The mouse kernel manages +; a counter for calls to show/hide, and the driver entry point is only called +; if the mouse is currently hidden and should become visible. For most drivers, +; no special action is required besides enabling the mouse cursor. +; No return code required. + +SHOW: inc visible + php + sei + jsr CSHOW + plp + rts + +;---------------------------------------------------------------------------- +; SETBOX: Set the mouse bounding box. The parameters are passed as they come +; from the C program, that is, a pointer to a mouse_box struct in a/x. +; No checks are done if the mouse is currently inside the box, this is the job +; of the caller. It is not necessary to validate the parameters, trust the +; caller and save some code here. No return code required. + +SETBOX: sta ptr1 + stx ptr1+1 ; Save data pointer + + ldy #.sizeof (MOUSE_BOX)-1 + php + sei + +@L1: lda (ptr1),y + sta XMin,y + dey + bpl @L1 + + plp + rts + +;---------------------------------------------------------------------------- +; GETBOX: Return the mouse bounding box. The parameters are passed as they +; come from the C program, that is, a pointer to a mouse_box struct in a/x. + +GETBOX: sta ptr1 + stx ptr1+1 ; Save data pointer + + ldy #.sizeof (MOUSE_BOX)-1 + php + sei + +@L1: lda XMin,y + sta (ptr1),y + dey + bpl @L1 + + plp + rts + +;---------------------------------------------------------------------------- +; MOVE: Move the mouse to a new position. The position is passed as it comes +; from the C program, that is: X on the stack and Y in a/x. The C wrapper will +; remove the parameter from the stack on return. +; No checks are done if the new position is valid (within the bounding box or +; the screen). No return code required. +; + +MOVE: php + sei ; No interrupts + + pha + txa + pha + + lda visible + beq @L01 + + jsr CHIDE + +@L01: pla + tax + pla + + sta YPos + sta YPosWrk + stx YPos+1 ; New Y position + stx YPosWrk+1 + jsr CMOVEY ; Set it + + ldy #$01 + lda (sp),y + sta XPos+1 + sta XPosWrk+1 + tax + dey + lda (sp),y + sta XPos ; New X position + sta XPosWrk + + jsr CMOVEX ; Move the cursor + + lda visible + beq @Ret + + jsr CSHOW + +@Ret: plp ; Restore interrupt flag + rts + +;---------------------------------------------------------------------------- +; BUTTONS: Return the button mask in a/x. + +BUTTONS: + lda Buttons + ldx #$00 + rts + +;---------------------------------------------------------------------------- +; POS: Return the mouse position in the MOUSE_POS struct pointed to by ptr1. +; No return code required. + +POS: ldy #MOUSE_POS::XCOORD ; Structure offset + + php + sei ; Disable interrupts + lda XPos ; Transfer the position + sta (ptr1),y + lda XPos+1 + iny + sta (ptr1),y + lda YPos + iny + sta (ptr1),y + lda YPos+1 + plp ; Restore interrupt flag + + iny + sta (ptr1),y ; Store last byte + + rts ; Done + +;---------------------------------------------------------------------------- +; INFO: Returns mouse position and current button mask in the MOUSE_INFO +; struct pointed to by ptr1. No return code required. +; +; We're cheating here to keep the code smaller: The first fields of the +; mouse_info struct are identical to the mouse_pos struct, so we will just +; call _mouse_pos to initialize the struct pointer and fill the position +; fields. + +INFO: jsr POS + +; Fill in the button state + + lda Buttons + ldy #MOUSE_INFO::BUTTONS + sta (ptr1),y + + rts + +;---------------------------------------------------------------------------- +; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl +; specific data in ptr1, and the ioctl code in A. +; Must return an error code in a/x. +; + +IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioclts for now + ldx #>MOUSE_ERR_INV_IOCTL + rts + +;---------------------------------------------------------------------------- +; IRQ: Irq handler entry point. Called as a subroutine but in IRQ context +; (so be careful). The routine MUST return carry set if the interrupt has been +; 'handled' - which means that the interrupt source is gone. Otherwise it +; MUST return carry clear. +; + +IRQ: + +; Check for a pressed button and place the result into Buttons + + ldx #0 + lda TRIG0 ; joystick #0 trigger + bne @L0 ; not pressed + ldx #MOUSE_BTN_LEFT +@L0: stx Buttons + +; Update coordinates if needed + + lda XPosWrk + cmp XPos + bne @Update + lda XPosWrk+1 + cmp XPos+1 + bne @Update + lda YPosWrk + cmp YPos + bne @Update + lda YPosWrk+1 + cmp YPos+1 + beq @Done + +@Update:ldx visible + beq @L1 + jsr CHIDE + +; Limit the X coordinate to the bounding box + +@L1: lda XPosWrk+1 + ldy XPosWrk + tax + cpy XMin + sbc XMin+1 + bpl @L2 + ldy XMin + ldx XMin+1 + jmp @L3 +@L2: txa + + cpy XMax + sbc XMax+1 + bmi @L3 + ldy XMax + ldx XMax+1 +@L3: sty XPos + stx XPos+1 + + tya + jsr CMOVEX + +; Limit the Y coordinate to the bounding box + + lda YPosWrk+1 + ldy YPosWrk + tax + cpy YMin + sbc YMin+1 + bpl @L4 + ldy YMin + ldx YMin+1 + jmp @L5 +@L4: txa + + cpy YMax + sbc YMax+1 + bmi @L5 + ldy YMax + ldx YMax+1 +@L5: sty YPos + stx YPos+1 + + tya + jsr CMOVEY + + ldx visible + beq @Done + + jsr CSHOW + +@Done: clc + rts + +;---------------------------------------------------------------------------- +; T1Han: Local IRQ routine to poll mouse +; + +T1Han: tya + pha + txa + pha + +.ifdef DEBUG + lda RANDOM + sta COLBK +.endif + + lda PORTA + tay + +.ifdef ST_MOUSE + +; ST mouse version + + and #%00000011 + ora dumx + tax + lda STTab,x + bmi nxst + + beq xist + + dec XPosWrk + lda XPosWrk + cmp #255 + bne nxst + dec XPosWrk+1 + jmp nxst + +xist: inc XPosWrk + bne nxst + inc XPosWrk+1 + +nxst: tya + and #%00001100 + ora dumy + tax + lda STTab,x + bmi nyst + + bne yst + + dec YPosWrk + lda YPosWrk + cmp #255 + bne nyst + dec YPosWrk+1 + jmp nyst + +yst: inc YPosWrk + bne nyst + inc YPosWrk+1 + +; store old readings + +nyst: tya + and #%00000011 + asl + asl + sta dumx + tya + and #%00001100 + lsr + lsr + sta dumy + +.elseif .defined (AMIGA_MOUSE) + +; Amiga mouse version + + lsr + and #%00000101 + ora dumx + tax + lda AmiTab,x + bmi nxami + + bne xiami + + dec XPosWrk + lda XPosWrk + cmp #255 + bne nxami + dec XPosWrk+1 + jmp nxami + +xiami: inc XPosWrk + bne nxami + inc XPosWrk+1 + +nxami: tya + + and #%00000101 + ora dumy + tax + lda AmiTab,x + bmi nyami + + bne yiami + + dec YPosWrk + lda YPosWrk + cmp #255 + bne nyami + dec YPosWrk+1 + jmp nyami + +yiami: inc YPosWrk + bne nyami + inc YPosWrk+1 + +; store old readings + +nyami: tya + and #%00001010 + sta dumx + tya + and #%00000101 + asl + sta dumy + +.elseif .defined (TRAK_MOUSE) + +; trakball version + + eor oldval + and #%00001000 + beq horiz + + tya + and #%00000100 + beq mmup + + inc YPosWrk + bne horiz + inc YPosWrk+1 + bne horiz + +mmup: dec YPosWrk + lda YPosWrk + cmp #255 + bne horiz + dec YPosWrk+1 + +horiz: tya + eor oldval + and #%00000010 + beq mmexit + + tya + and #%00000001 + beq mmleft + + inc XPosWrk + bne mmexit + inc XPosWrk+1 + bne mmexit + +mmleft: dec XPosWrk + lda XPosWrk + cmp #255 + bne mmexit + dec XPosWrk+1 + +mmexit: sty oldval + +.endif + + pla + tax + pla + tay + pla + rti + diff --git a/libsrc/atari/mou/atrtrk.s b/libsrc/atari/mou/atrtrk.s new file mode 100644 index 000000000..699d12a0d --- /dev/null +++ b/libsrc/atari/mou/atrtrk.s @@ -0,0 +1,2 @@ +TRAK_MOUSE = 1 +.include "atrst.s" diff --git a/libsrc/atari/mouse.s_ b/libsrc/atari/mouse.s_ deleted file mode 100644 index 9c722b49c..000000000 --- a/libsrc/atari/mouse.s_ +++ /dev/null @@ -1,576 +0,0 @@ -;-------------------------------------------------------------------- -; Atari 8-bit mouse routines -- 05/07/2000 Freddy Offenga -; Some changes by Christian Groessler, Ullrich von Bassewitz -; -; The following devices are supported: -; - Atari trak-ball -; - ST mouse -; - Amiga mouse -; -; Mouse checks are done in the timer 1 IRQ and the mouse arrow is -; drawn in player 0 during the vertical blank -;-------------------------------------------------------------------- - - .export _mouse_init, _mouse_done, _mouse_box - .export _mouse_show, _mouse_hide, _mouse_move - .export _mouse_buttons, _mouse_pos, _mouse_info - .constructor initmouse,27 - - .import popax - .importzp ptr1 - - .include "atari.inc" - -TRAK_BALL = 0 ; device Atari trak-ball -ST_MOUSE = 1 ; device ST mouse -AMIGA_MOUSE = 2 ; device Amiga mouse -MAX_TYPE = 3 ; first illegal device type - -; the default values force the mouse cursor inside the test screen (no access to border) -defxmin = 48 ; default x minimum -defymin = 31 ; default y minimum -defxmax = 204 ; default x maximum -defymax = 211 ; default y maximum - -pmsize = 16 ; y size pm shape - -xinit = defxmin ; init. x pos. -yinit = defymin ; init. y pos. - -;-------------------------------------------------------------------- -; reserve memory for the mouse pointer - -initmouse: - lda APPMHI+1 - and #%11111000 ; make 2k aligned - sec - sbc #%00001000 ; reserve 2k - tax - adc #3 ; add 4 (C = 1) - sta mouse_pm0 - lda #0 - sta APPMHI - stx APPMHI+1 - rts - - -;-------------------------------------------------------------------- -; Initialize mouse routines -; void __fastcall__ mouse_init (unsigned char type); - -_mouse_init: - cmp #MAX_TYPE+1 ; Check for a valid type - bcc setup - -ifail: lda #0 ; init. failed - tax - rts - -setup: tax - lda lvectab,x - sta mouse_vec+1 - lda hvectab,x - sta mouse_vec+2 - - jsr pminit - - lda VTIMR1 - sta old_t1 - lda VTIMR1+1 - sta old_t1+1 - - lda #<t1_vec - sta VTIMR1 - lda #>t1_vec - sta VTIMR1+1 - - lda #%00000001 - sta AUDCTL - - lda #0 - sta AUDC1 - - lda #15 - sta AUDF1 - sta STIMER - - sei - lda POKMSK - ora #%00000001 ; timer 1 enable - sta POKMSK - sta IRQEN - cli - - lda VVBLKI - sta vbi_jmp+1 - lda VVBLKI+1 - sta vbi_jmp+2 - - lda #6 - ldy #<vbi - ldx #>vbi - jsr SETVBV - - lda #$C0 - sta NMIEN - - ldx #0 - lda #1 - sta mouse_off - rts - -;-------------------------------------------------------------------- -; Finish mouse routines -; void mouse_done(void) - -_mouse_done: - sei - lda POKMSK - and #%11111110 ; timer 1 disable - sta IRQEN - sta POKMSK - cli - - lda old_t1 - sta VTIMR1 - lda old_t1+1 - sta VTIMR1+1 - - lda #$40 - sta NMIEN - - lda #6 - ldy vbi_jmp+1 - ldx vbi_jmp+2 - jsr SETVBV - - ldx #0 - stx GRACTL - stx HPOSP0 - inx - stx mouse_off - rts - -;-------------------------------------------------------------------- -; Set mouse limits -; void __fastcall__ mouse_box(int xmin, int ymin, int xmax, int ymax) - -_mouse_box: - sta ymax - jsr popax ; always ignore high byte - sta xmax - jsr popax - sta ymin - jsr popax - sta xmin - rts - -;-------------------------------------------------------------------- -; Set mouse position -; void __fastcall__ mouse_move(int xpos, int ypos) - -_mouse_move: - sta mousey ; always ignore high byte - jsr popax - sta mousex - rts - -;-------------------------------------------------------------------- -; Show mouse arrow -; void mouse_show(void) - -_mouse_show: - lda mouse_off ; Already on? - beq @L1 - dec mouse_off -@L1: rts - -;-------------------------------------------------------------------- -; Hide mouse arrow -; void mouse_hide(void) - -_mouse_hide: - inc mouse_off - rts - -;-------------------------------------------------------------------- -; Ask mouse button -; unsigned char mouse_buttons(void) - -_mouse_buttons: - ldx #0 - lda STRIG0 - bne nobut -; lda #14 -;??? sta COLOR1 - lda #1 - rts -nobut: txa - rts - -;-------------------------------------------------------------------- -; Get the mouse position -; void mouse_pos (struct mouse_pos* pos); - -_mouse_pos: - sta ptr1 - stx ptr1+1 ; Store argument pointer - ldy #0 - lda mousex ; X position - sta (ptr1),y - lda #0 - iny - sta (ptr1),y - lda mousey ; Y position - iny - sta (ptr1),y - lda #0 - iny - sta (ptr1),y - rts - -;-------------------------------------------------------------------- -; Get the mouse position and button information -; void mouse_info (struct mouse_info* info); - -_mouse_info: - -; We're cheating here to keep the code smaller: The first fields of the -; mouse_info struct are identical to the mouse_pos struct, so we will just -; call _mouse_pos to initialize the struct pointer and fill the position -; fields. - - jsr _mouse_pos - -; Fill in the button state - - jsr _mouse_buttons ; Will not touch ptr1 - ldy #4 - sta (ptr1),y - - rts - -;-------------------------------------------------------------------- -; Atari trak-ball check, A,Y = 4-bit port value - -trak_check: - eor oldval - and #%00001000 - beq horiz - - tya - and #%00000100 - beq mmup - - inc mousey - bne horiz - -mmup: dec mousey - -horiz: tya - eor oldval - and #%00000010 - beq mmexit - - tya - and #%00000001 - beq mmleft - - inc mousex - bne mmexit - -mmleft: dec mousex - -mmexit: sty oldval - rts - -;-------------------------------------------------------------------- -; ST mouse check, A,Y = 4-bit port value - -st_check: - and #%00000011 - ora dumx - tax - lda sttab,x - bmi nxst - - beq xist - dec mousex ; 1 = left - bne nxst -xist: inc mousex ; 0 = right - -nxst: tya - and #%00001100 - ora dumy - tax - lda sttab,x - bmi nyst - - bne yst - dec mousey ; 0 = up - bne nyst -yst: inc mousey ; 1 = down - -; store old readings - -nyst: tya - and #%00000011 - asl - asl - sta dumx - tya - and #%00001100 - lsr - lsr - sta dumy - rts - -;-------------------------------------------------------------------- -; Amiga mouse check, A,Y = 4-bit port value - -amiga_check: - - lsr - and #%00000101 - ora dumx - tax - lda amitab,x - bmi nxami - - bne xiami - dec mousex ; 0 = left - bne nxami -xiami: inc mousex ; 1 = right - -nxami: tya - - and #%00000101 - ora dumy - tax - lda amitab,x - bmi nyami - - bne yiami - dec mousey ; 0 = up - bne nyami -yiami: inc mousey ; 1 = down - -; store old readings - -nyami: tya - and #%00001010 - sta dumx - tya - and #%00000101 - asl - sta dumy - rts - -;-------------------------------------------------------------------- -; timer 1 IRQ routine - check mouse - -t1_vec: tya - pha - txa - pha - -.ifdef DEBUG - lda RANDOM - sta COLBK ; debug -.endif - - lda PORTA - tay - -mouse_vec: - jsr st_check ; will be modified; won't be ROMmable - - pla - tax - pla - tay - pla - rti - -;-------------------------------------------------------------------- -; VBI - check mouse limits and display mouse arrow - -vbi: lda mousex - cmp xmin - bcs ok1 ; xmin <= mousex - lda xmin - sta mousex - -ok1: lda mousey - cmp ymin - bcs ok2 ; ymin <= mousey - lda ymin - sta mousey - -ok2: lda xmax - cmp mousex - bcs ok3 ; xmax >= mousex - lda xmax - sta mousex - -ok3: lda ymax - cmp mousey - bcs ok4 ; ymax >= mousey - lda ymax - sta mousey - -ok4: jsr clrpm - - lda mouse_off - beq mon - lda #0 - sta HPOSP0 - beq moff - -mon: jsr drwpm - lda mousey - sta omy - - lda #3 -moff: sta GRACTL - -vbi_jmp: - jmp SYSVBV ; will be modified; won't be ROMmable - -;-------------------------------------------------------------------- -; initialize mouse pm - -pminit: lda mouse_pm0 - sta mpatch1+2 - sta mpatch2+2 - sta mpatch3+2 - - ldx #0 - txa -mpatch1: -clpm: sta $1000,x ; will be patched - inx - bne clpm - - lda mouse_pm0 - sec - sbc #4 - sta PMBASE - - lda #62 - sta SDMCTL - - lda #1 - sta GPRIOR - - lda #0 - sta PCOLR0 - sta SIZEP0 - rts - -;-------------------------------------------------------------------- -; draw new mouse pm - -drwpm: lda mousex - sta HPOSP0 - - lda mousey - tax - - ldy #0 -fmp2: lda mskpm,y -mpatch2: - sta $1000,x ; will be patched - inx - iny - cpy #pmsize - bne fmp2 - rts - -;-------------------------------------------------------------------- -; clear old mouse pm - -clrpm: lda omy - tax - - ldy #0 - tya -mpatch3: -fmp1: sta $1000,x ; will be patched - inx - iny - cpy #pmsize - bne fmp1 - rts - -;-------------------------------------------------------------------- - .rodata - -; mouse arrow - pm shape - -mskpm: .byte %00000000 - .byte %10000000 - .byte %11000000 - .byte %11000000 - - .byte %11100000 - .byte %11100000 - .byte %11110000 - .byte %11100000 - - .byte %11100000 - .byte %00100000 - .byte %00100000 - .byte %00110000 - - .byte %00110000 - .byte %00000000 - .byte %00000000 - .byte %00000000 - -; ST mouse lookup table - -sttab: .byte $FF,$01,$00,$01 - .byte $00,$FF,$00,$01 - .byte $01,$00,$FF,$00 - .byte $01,$00,$01,$FF - -; Amiga mouse lookup table - -amitab: .byte $FF,$01,$00,$FF - .byte $00,$FF,$FF,$01 - .byte $01,$FF,$FF,$00 - .byte $FF,$00,$01,$FF - -; Device vectors - -lvectab: - .byte <trak_check, <st_check, <amiga_check -hvectab: - .byte >trak_check, >st_check, >amiga_check - -; default values - -xmin: .byte defxmin -ymin: .byte defymin -xmax: .byte defxmax -ymax: .byte defymax - -mousex: .byte xinit -mousey: .byte yinit - -;-------------------------------------------------------------------- - .bss - -; Misc. vars - -old_t1: .res 2 ; old timer interrupt vector -oldval: .res 1 ; used by trakball routines -dumx: .res 1 -dumy: .res 1 -omy: .res 1 ; old y pos - -mouse_off: - .res 1 -mouse_pm0: - .res 1 diff --git a/libsrc/atari/mouse_stddrv.s b/libsrc/atari/mouse_stddrv.s index 443e53254..493c90d77 100644 --- a/libsrc/atari/mouse_stddrv.s +++ b/libsrc/atari/mouse_stddrv.s @@ -12,7 +12,7 @@ _mouse_stddrv: .ifdef __ATARIXL__ - .asciiz "ATRXJOY.MOU" + .asciiz "ATRXST.MOU" .else - .asciiz "ATRJOY.MOU" + .asciiz "ATRST.MOU" .endif From d614fc4e6483d03e4ce4544e692ce4351d8418c4 Mon Sep 17 00:00:00 2001 From: Christian Groessler <chris@groessler.org> Date: Sat, 4 Jan 2014 20:05:57 +0100 Subject: [PATCH 06/31] When disabling interrupts, restore original interrupt flag afterwards. --- libsrc/atari/mou/atrjoy.s | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/libsrc/atari/mou/atrjoy.s b/libsrc/atari/mou/atrjoy.s index 1a5afa71a..e1c745adf 100644 --- a/libsrc/atari/mou/atrjoy.s +++ b/libsrc/atari/mou/atrjoy.s @@ -122,6 +122,7 @@ INSTALL: ; need to do that here, because our mouse interrupt handler doesn't set the ; mouse position if it hasn't changed. + php sei jsr CHIDE lda XPos @@ -130,7 +131,7 @@ INSTALL: lda YPos ldx YPos+1 jsr CMOVEY - cli + plp ; Done, return zero (= MOUSE_ERR_OK) @@ -152,9 +153,10 @@ UNINSTALL = HIDE ; Hide cursor on exit ; No return code required. HIDE: dec visible + php sei jsr CHIDE - cli + plp rts ;---------------------------------------------------------------------------- @@ -165,9 +167,10 @@ HIDE: dec visible ; No return code required. SHOW: inc visible + php sei jsr CSHOW - cli + plp rts ;---------------------------------------------------------------------------- @@ -181,6 +184,7 @@ SETBOX: sta ptr1 stx ptr1+1 ; Save data pointer ldy #.sizeof (MOUSE_BOX)-1 + php sei @L1: lda (ptr1),y @@ -188,7 +192,7 @@ SETBOX: sta ptr1 dey bpl @L1 - cli + plp rts ;---------------------------------------------------------------------------- @@ -199,6 +203,7 @@ GETBOX: sta ptr1 stx ptr1+1 ; Save data pointer ldy #.sizeof (MOUSE_BOX)-1 + php sei @L1: lda XMin,y @@ -206,7 +211,7 @@ GETBOX: sta ptr1 dey bpl @L1 - cli + plp rts ;---------------------------------------------------------------------------- @@ -217,7 +222,8 @@ GETBOX: sta ptr1 ; the screen). No return code required. ; -MOVE: sei ; No interrupts +MOVE: php + sei ; No interrupts pha txa @@ -246,7 +252,7 @@ MOVE: sei ; No interrupts jsr CSHOW -@Ret: cli ; Allow interrupts +@Ret: plp ; Restore interrupt flag rts ;---------------------------------------------------------------------------- @@ -263,6 +269,7 @@ BUTTONS: POS: ldy #MOUSE_POS::XCOORD ; Structure offset + php sei ; Disable interrupts lda XPos ; Transfer the position sta (ptr1),y @@ -273,7 +280,7 @@ POS: ldy #MOUSE_POS::XCOORD ; Structure offset iny sta (ptr1),y lda YPos+1 - cli ; Enable interrupts + plp ; Restore interrupt flag iny sta (ptr1),y ; Store last byte From 24198a9ebbfd5f6541a948f021c3a07aed2fedc0 Mon Sep 17 00:00:00 2001 From: Christian Groessler <chris@groessler.org> Date: Sun, 5 Jan 2014 11:09:01 +0100 Subject: [PATCH 07/31] small cleanup --- libsrc/atari/mcbdefault.s | 1 - 1 file changed, 1 deletion(-) diff --git a/libsrc/atari/mcbdefault.s b/libsrc/atari/mcbdefault.s index 91e920ac4..8d60a9ef7 100644 --- a/libsrc/atari/mcbdefault.s +++ b/libsrc/atari/mcbdefault.s @@ -83,7 +83,6 @@ show: ; Move the mouse cursor x position to the value in A/X. movex: - cpx #0 cpx #1 ror a lsr a ; convert to character position From 09da71c5d913eba6e799c69c057fe6f67b6562fe Mon Sep 17 00:00:00 2001 From: Christian Groessler <chris@groessler.org> Date: Sun, 5 Jan 2014 11:18:34 +0100 Subject: [PATCH 08/31] another small cleanup --- libsrc/atari/mcbdefault.s | 1 - 1 file changed, 1 deletion(-) diff --git a/libsrc/atari/mcbdefault.s b/libsrc/atari/mcbdefault.s index 8d60a9ef7..e68dba243 100644 --- a/libsrc/atari/mcbdefault.s +++ b/libsrc/atari/mcbdefault.s @@ -21,7 +21,6 @@ .bss backup: .res 1 -helper: .res 2 ; ------------------------------------------------------------------------ From c22b91e3c382e8bad5a62b9218b36d27d73f5c75 Mon Sep 17 00:00:00 2001 From: Christian Groessler <chris@groessler.org> Date: Sat, 11 Jan 2014 01:05:13 +0100 Subject: [PATCH 09/31] align comment to the same column --- libsrc/atari/mcbdefault.s | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libsrc/atari/mcbdefault.s b/libsrc/atari/mcbdefault.s index e68dba243..e1b78f033 100644 --- a/libsrc/atari/mcbdefault.s +++ b/libsrc/atari/mcbdefault.s @@ -43,19 +43,19 @@ _mouse_def_callbacks: .data -cursor = 11 ; '+' screen code' +cursor = 11 ; '+' screen code' ; setcursor getcursor: column: ldy #$00 ; Patched at runtime - lda (scrptr),y ; Patched at runtime + lda (scrptr),y ; Patched at runtime cmp #cursor rts setcursor: lda #cursor -setscr: sta (scrptr),y ; Patched at runtime +setscr: sta (scrptr),y ; Patched at runtime rts ; ------------------------------------------------------------------------ From c78d7a82fb1d83a5ee34abdafb70abcdc95cc35f Mon Sep 17 00:00:00 2001 From: Christian Groessler <chris@groessler.org> Date: Sat, 11 Jan 2014 01:33:59 +0100 Subject: [PATCH 10/31] use ST mouse as static standard driver, too --- libsrc/atari/mouse_stat_stddrv.s | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libsrc/atari/mouse_stat_stddrv.s b/libsrc/atari/mouse_stat_stddrv.s index 18ebda9a2..55e29878b 100644 --- a/libsrc/atari/mouse_stat_stddrv.s +++ b/libsrc/atari/mouse_stat_stddrv.s @@ -8,15 +8,15 @@ .export _mouse_static_stddrv .ifdef __ATARIXL__ - .import _atrxjoy_mou + .import _atrxst_mou .else - .import _atrjoy_mou + .import _atrst_mou .endif .rodata .ifdef __ATARIXL__ -_mouse_static_stddrv := _atrxjoy_mou +_mouse_static_stddrv := _atrxst_mou .else -_mouse_static_stddrv := _atrjoy_mou +_mouse_static_stddrv := _atrst_mou .endif From 597c4a6b891a0145c223af00230fb66ffe83d469 Mon Sep 17 00:00:00 2001 From: Christian Groessler <chris@groessler.org> Date: Sat, 11 Jan 2014 01:35:32 +0100 Subject: [PATCH 11/31] add comment --- libsrc/atari/mou/atrjoy.s | 2 ++ libsrc/atari/mou/atrst.s | 2 ++ 2 files changed, 4 insertions(+) diff --git a/libsrc/atari/mou/atrjoy.s b/libsrc/atari/mou/atrjoy.s index e1c745adf..9915a4ff1 100644 --- a/libsrc/atari/mou/atrjoy.s +++ b/libsrc/atari/mou/atrjoy.s @@ -91,6 +91,8 @@ visible: .res 1 .rodata +; (We use ".proc" because we want to define both a label and a scope.) + .proc DefVars .word SCREEN_HEIGHT/2 ; YPos .word SCREEN_WIDTH/2 ; XPos diff --git a/libsrc/atari/mou/atrst.s b/libsrc/atari/mou/atrst.s index 1e7e77b3a..72808ad16 100644 --- a/libsrc/atari/mou/atrst.s +++ b/libsrc/atari/mou/atrst.s @@ -113,6 +113,8 @@ oldval: .res 1 .rodata +; (We use ".proc" because we want to define both a label and a scope.) + .proc DefVars .word (SCREEN_HEIGHT+1)/2 ; YPos .word (SCREEN_WIDTH+1)/2 ; XPos From 7a682cf71a1cfda82015eb41a94b9d49986850d0 Mon Sep 17 00:00:00 2001 From: Christian Groessler <chris@groessler.org> Date: Mon, 13 Jan 2014 00:45:35 +0100 Subject: [PATCH 12/31] fix some typos --- asminc/atari.inc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/asminc/atari.inc b/asminc/atari.inc index 49a125efb..da926af81 100644 --- a/asminc/atari.inc +++ b/asminc/atari.inc @@ -485,10 +485,10 @@ VKEYBD = $0208 ;POKEY KEYBOARD IRQ VECTOR VSERIN = $020A ;POKEY SERIAL INPUT READY IRQ VSEROR = $020C ;POKEY SERIAL OUTPUT READY IRQ VSEROC = $020E ;POKEY SERIAL OUTPUT COMPLETE IRQ -VTIMR1 = $0210 ;POKEY TIMER 1 IRG -VTIMR2 = $0212 ;POKEY TIMER 2 IRG -VTIMR4 = $0214 ;POKEY TIMER 4 IRG -VIMIRQ = $0216 ;IMMEDIATE IRG VECTOR +VTIMR1 = $0210 ;POKEY TIMER 1 IRQ +VTIMR2 = $0212 ;POKEY TIMER 2 IRQ +VTIMR4 = $0214 ;POKEY TIMER 4 IRQ +VIMIRQ = $0216 ;IMMEDIATE IRQ VECTOR CDTMV1 = $0218 ;COUNT DOWN TIMER 1 CDTMV2 = $021A ;COUNT DOWN TIMER 2 CDTMV3 = $021C ;COUNT DOWN TIMER 3 From 77ba5b7e1c218b1294da14b8d9b1bb70337bfddb Mon Sep 17 00:00:00 2001 From: Christian Groessler <chris@groessler.org> Date: Tue, 14 Jan 2014 11:43:34 +0100 Subject: [PATCH 13/31] Fix timer IRQ hooking for atarixl target. --- libsrc/atari/libref.s | 4 +- libsrc/atari/mou/atrst.s | 49 ++++++++++++++--- libsrc/atari/shadow_ram_timerirq1.s | 81 +++++++++++++++++++++++++++++ 3 files changed, 126 insertions(+), 8 deletions(-) create mode 100644 libsrc/atari/shadow_ram_timerirq1.s diff --git a/libsrc/atari/libref.s b/libsrc/atari/libref.s index e6b9df6a5..4f7cbbef6 100644 --- a/libsrc/atari/libref.s +++ b/libsrc/atari/libref.s @@ -8,11 +8,13 @@ em_libref := _exit joy_libref := _exit -mouse_libref := _exit ser_libref := atari_ser_libref .ifdef __ATARIXL__ .import CIO_handler tgi_libref := CIO_handler + .import set_VTIMR1_handler +mouse_libref := set_VTIMR1_handler .else +mouse_libref := _exit tgi_libref := _exit .endif diff --git a/libsrc/atari/mou/atrst.s b/libsrc/atari/mou/atrst.s index 72808ad16..04580f31a 100644 --- a/libsrc/atari/mou/atrst.s +++ b/libsrc/atari/mou/atrst.s @@ -35,7 +35,7 @@ HEADER: ; Library reference - .addr $0000 +libref: .addr $0000 ; Jump table @@ -96,7 +96,6 @@ Buttons: .res 1 ; Button mask XPosWrk: .res 2 YPosWrk: .res 2 -OldT1: .res 2 visible: .res 1 .if .defined (AMIGA_MOUSE) .or .defined (ST_MOUSE) @@ -108,11 +107,18 @@ dumy: .res 1 oldval: .res 1 .endif +.ifndef __ATARIXL__ +OldT1: .res 2 +.else -; Default values for some of the above variables +.data +set_VTIMR1_handler: + .byte $4C, 0, 0 +.endif .rodata +; Default values for some of the above variables ; (We use ".proc" because we want to define both a label and a scope.) .proc DefVars @@ -182,7 +188,23 @@ INSTALL: jsr CMOVEY cli -; install timer irq routine to poll mouse +; Install timer irq routine to poll mouse. + +.ifdef __ATARIXL__ + + ; Setup pointer to wrapper install/deinstall function. + lda libref + sta set_VTIMR1_handler+1 + lda libref+1 + sta set_VTIMR1_handler+2 + + ; Install my handler. + sec + lda #<T1Han + ldx #>T1Han + jsr set_VTIMR1_handler + +.else lda VTIMR1 sta OldT1 @@ -197,6 +219,8 @@ INSTALL: sta VTIMR1+1 plp +.endif + lda #%00000001 sta AUDCTL @@ -231,6 +255,13 @@ UNINSTALL: sta IRQEN sta POKMSK +.ifdef __ATARIXL__ + + clc + jsr set_VTIMR1_handler + +.else + php sei lda OldT1 @@ -239,6 +270,7 @@ UNINSTALL: sta VTIMR1+1 plp +.endif ; fall thru... ;---------------------------------------------------------------------------- @@ -354,7 +386,7 @@ MOVE: php lda visible beq @Ret - + jsr CSHOW @Ret: plp ; Restore interrupt flag @@ -520,7 +552,7 @@ IRQ: T1Han: tya pha txa - pha + pha .ifdef DEBUG lda RANDOM @@ -692,6 +724,9 @@ mmexit: sty oldval tax pla tay +.ifdef __ATARIXL__ + rts +.else pla rti - +.endif diff --git a/libsrc/atari/shadow_ram_timerirq1.s b/libsrc/atari/shadow_ram_timerirq1.s new file mode 100644 index 000000000..f8a3e9b4d --- /dev/null +++ b/libsrc/atari/shadow_ram_timerirq1.s @@ -0,0 +1,81 @@ +; +; Atari XL shadow RAM timer IRQ #1 handler +; +; Christian Groessler, chris@groessler.org, 2014 +; + +;DEBUG = 1 + +.ifdef __ATARIXL__ + +SHRAM_HANDLERS = 1 + .include "atari.inc" + .include "romswitch.inc" + .export set_VTIMR1_handler + + +.segment "LOWBSS" + +VTIMR1_handler: .res 3 + + +.segment "BSS" + +old_VTIMR1_handler: + .res 2 + + +.segment "LOWCODE" + +; timer interrupt handler: +; disable ROM, call user handler, enable ROM again + +my_VTIMR1_handler: + disable_rom_quick + jsr VTIMR1_handler + enable_rom_quick + pla + rti + +.segment "CODE" + +; install or remove VTIMR1 handler +; input: CF - 0/1 for remove/install handler +; AX - pointer to handler (if CF=1) +; registers destroyed + +set_VTIMR1_handler: + + bcc @remove + +; install vector + + stx VTIMR1_handler+2 + sta VTIMR1_handler+1 ; save passed vector in low memory + lda #$4C ; "JMP" opcode + sta VTIMR1_handler + + lda VTIMR1 + sta old_VTIMR1_handler + lda VTIMR1+1 + sta old_VTIMR1_handler+1 + + lda #<my_VTIMR1_handler + php + sei + sta VTIMR1 + lda #>my_VTIMR1_handler + sta VTIMR1+1 + plp + rts + +@remove: php + sei + lda old_VTIMR1_handler + sta VTIMR1 + lda old_VTIMR1_handler+1 + sta VTIMR1+1 + plp + rts + +.endif ; .ifdef __ATARIXL__ From 2be7c7c88d278855aea59b146ff73e10c7330027 Mon Sep 17 00:00:00 2001 From: Christian Groessler <chris@groessler.org> Date: Tue, 14 Jan 2014 13:57:47 +0100 Subject: [PATCH 14/31] Always print the mouse cursor, even if coordinates haven't changed. This makes sure that the cursor is always visible, even if the program has written text to the screen (only valid for non-P/M mouse callbacks). --- libsrc/atari/mou/atrjoy.s | 11 ++--------- libsrc/atari/mou/atrst.s | 23 ++--------------------- 2 files changed, 4 insertions(+), 30 deletions(-) diff --git a/libsrc/atari/mou/atrjoy.s b/libsrc/atari/mou/atrjoy.s index 9915a4ff1..2c2d2c178 100644 --- a/libsrc/atari/mou/atrjoy.s +++ b/libsrc/atari/mou/atrjoy.s @@ -120,12 +120,8 @@ INSTALL: dex bpl @L1 -; Be sure the mouse cursor is invisible and at the default location. We -; need to do that here, because our mouse interrupt handler doesn't set the -; mouse position if it hasn't changed. +; Be sure the mouse cursor is invisible and at the default location. - php - sei jsr CHIDE lda XPos ldx XPos+1 @@ -133,7 +129,6 @@ INSTALL: lda YPos ldx YPos+1 jsr CMOVEY - plp ; Done, return zero (= MOUSE_ERR_OK) @@ -316,7 +311,7 @@ INFO: jsr POS IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioclts for now ldx #>MOUSE_ERR_INV_IOCTL -hlprts: rts + rts ;---------------------------------------------------------------------------- ; IRQ: Irq handler entry point. Called as a subroutine but in IRQ context @@ -339,8 +334,6 @@ IRQ: and #15 ; clear joystick #1 bits eor #15 sta Temp - clc - beq hlprts ; no movement, do nothing jsr CHIDE diff --git a/libsrc/atari/mou/atrst.s b/libsrc/atari/mou/atrst.s index 04580f31a..03f9f0b53 100644 --- a/libsrc/atari/mou/atrst.s +++ b/libsrc/atari/mou/atrst.s @@ -170,11 +170,8 @@ INSTALL: dex bpl @L1 -; Be sure the mouse cursor is invisible and at the default location. We -; need to do that here, because our mouse interrupt handler doesn't set the -; mouse position if it hasn't changed. +; Be sure the mouse cursor is invisible and at the default location. - sei jsr CHIDE lda XPos sta XPosWrk @@ -186,7 +183,6 @@ INSTALL: ldx YPos+1 stx YPosWrk+1 jsr CMOVEY - cli ; Install timer irq routine to poll mouse. @@ -470,22 +466,7 @@ IRQ: ldx #MOUSE_BTN_LEFT @L0: stx Buttons -; Update coordinates if needed - - lda XPosWrk - cmp XPos - bne @Update - lda XPosWrk+1 - cmp XPos+1 - bne @Update - lda YPosWrk - cmp YPos - bne @Update - lda YPosWrk+1 - cmp YPos+1 - beq @Done - -@Update:ldx visible + ldx visible beq @L1 jsr CHIDE From 09aa007191b79fcf90ceea8e6d6bd74ba8ec8f67 Mon Sep 17 00:00:00 2001 From: Christian Groessler <chris@groessler.org> Date: Tue, 14 Jan 2014 14:00:17 +0100 Subject: [PATCH 15/31] Change display logic of mouse cursor (hide and show functions). --- libsrc/atari/mcbdefault.s | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/libsrc/atari/mcbdefault.s b/libsrc/atari/mcbdefault.s index e1b78f033..11b7e07be 100644 --- a/libsrc/atari/mcbdefault.s +++ b/libsrc/atari/mcbdefault.s @@ -49,13 +49,12 @@ cursor = 11 ; '+' screen code' getcursor: column: ldy #$00 ; Patched at runtime - lda (scrptr),y ; Patched at runtime - cmp #cursor + lda (scrptr),y rts setcursor: - lda #cursor -setscr: sta (scrptr),y ; Patched at runtime +column2:ldy #$00 ; Patched at runtime + sta (scrptr),y rts ; ------------------------------------------------------------------------ @@ -67,16 +66,19 @@ done: ; Hide the mouse cursor. hide: - jsr getcursor ; Cursor visible at current position? - bne done ; No, we're done - lda backup ; Get character at cursor position - jmp setscr ; Draw character + jsr getcursor ; Get character at cursor position + cmp #cursor ; "mouse" character + bne overwr ; no, probably program has overwritten it + lda backup ; + jmp setcursor ; Draw character +overwr: sta backup + rts ; Show the mouse cursor. show: jsr getcursor ; Cursor visible at current position? - beq done ; Yes, we're done sta backup ; Save character at cursor position + lda #cursor jmp setcursor ; Draw cursor @@ -87,6 +89,7 @@ movex: lsr a ; convert to character position lsr a sta column+1 + sta column2+1 rts ; Move the mouse cursor y position to the value in A/X. From d61b8754fb522d815c60294fe10a8134de97df64 Mon Sep 17 00:00:00 2001 From: Christian Groessler <chris@groessler.org> Date: Sat, 18 Jan 2014 00:02:29 +0100 Subject: [PATCH 16/31] Adapt to new mouse driver interface ('prep' and 'draw') --- libsrc/atari/mcbdefault.s | 11 ++++++++++ libsrc/atari/mou/atrjoy.s | 32 ++++++++++------------------ libsrc/atari/mou/atrst.s | 44 +++++++++++++-------------------------- 3 files changed, 36 insertions(+), 51 deletions(-) diff --git a/libsrc/atari/mcbdefault.s b/libsrc/atari/mcbdefault.s index 11b7e07be..ac5056cf9 100644 --- a/libsrc/atari/mcbdefault.s +++ b/libsrc/atari/mcbdefault.s @@ -21,6 +21,7 @@ .bss backup: .res 1 +visible:.res 1 ; ------------------------------------------------------------------------ @@ -36,6 +37,8 @@ scrptr: .res 2 _mouse_def_callbacks: .addr hide .addr show + .addr prep + .addr draw .addr movex .addr movey @@ -66,6 +69,9 @@ done: ; Hide the mouse cursor. hide: + dec visible + +prep: jsr getcursor ; Get character at cursor position cmp #cursor ; "mouse" character bne overwr ; no, probably program has overwritten it @@ -76,6 +82,11 @@ overwr: sta backup ; Show the mouse cursor. show: + inc visible + +draw: + lda visible + beq done jsr getcursor ; Cursor visible at current position? sta backup ; Save character at cursor position lda #cursor diff --git a/libsrc/atari/mou/atrjoy.s b/libsrc/atari/mou/atrjoy.s index 2c2d2c178..aa61615ad 100644 --- a/libsrc/atari/mou/atrjoy.s +++ b/libsrc/atari/mou/atrjoy.s @@ -50,6 +50,8 @@ HEADER: CHIDE: jmp $0000 ; Hide the cursor CSHOW: jmp $0000 ; Show the cursor +CPREP: jmp $0000 ; Prepare to move the cursor +CDRAW: jmp $0000 ; Draw the cursor CMOVEX: jmp $0000 ; Move the cursor to X coord CMOVEY: jmp $0000 ; Move the cursor to Y coord @@ -85,7 +87,6 @@ Buttons: .res 1 ; Button mask Temp: .res 1 ; Temporary value used in the int handler -visible: .res 1 ; Default values for above variables @@ -120,9 +121,8 @@ INSTALL: dex bpl @L1 -; Be sure the mouse cursor is invisible and at the default location. +; Make sure the mouse cursor is at the default location. - jsr CHIDE lda XPos ldx XPos+1 jsr CMOVEX @@ -149,8 +149,7 @@ UNINSTALL = HIDE ; Hide cursor on exit ; no special action is required besides hiding the mouse cursor. ; No return code required. -HIDE: dec visible - php +HIDE: php sei jsr CHIDE plp @@ -163,8 +162,7 @@ HIDE: dec visible ; no special action is required besides enabling the mouse cursor. ; No return code required. -SHOW: inc visible - php +SHOW: php sei jsr CSHOW plp @@ -225,7 +223,7 @@ MOVE: php pha txa pha - jsr CHIDE + jsr CPREP pla tax pla @@ -241,15 +239,11 @@ MOVE: php dey lda (sp),y sta XPos ; New X position - jsr CMOVEX ; Move the cursor - lda visible - beq @Ret - - jsr CSHOW + jsr CDRAW -@Ret: plp ; Restore interrupt flag + plp ; Restore interrupt flag rts ;---------------------------------------------------------------------------- @@ -335,7 +329,7 @@ IRQ: eor #15 sta Temp - jsr CHIDE + jsr CPREP ; Check left/right @@ -435,11 +429,7 @@ IRQ: ; Done -@SkipY: lda visible - beq @Done - - jsr CSHOW - -@Done: clc ; Interrupt not "handled" +@SkipY: jsr CDRAW + clc ; Interrupt not "handled" rts diff --git a/libsrc/atari/mou/atrst.s b/libsrc/atari/mou/atrst.s index 03f9f0b53..116cecee2 100644 --- a/libsrc/atari/mou/atrst.s +++ b/libsrc/atari/mou/atrst.s @@ -60,6 +60,8 @@ libref: .addr $0000 CHIDE: jmp $0000 ; Hide the cursor CSHOW: jmp $0000 ; Show the cursor +CPREP: jmp $0000 ; Prepare to move the cursor +CDRAW: jmp $0000 ; Draw the cursor CMOVEX: jmp $0000 ; Move the cursor to X coord CMOVEY: jmp $0000 ; Move the cursor to Y coord @@ -96,8 +98,6 @@ Buttons: .res 1 ; Button mask XPosWrk: .res 2 YPosWrk: .res 2 -visible: .res 1 - .if .defined (AMIGA_MOUSE) .or .defined (ST_MOUSE) dumx: .res 1 dumy: .res 1 @@ -170,9 +170,8 @@ INSTALL: dex bpl @L1 -; Be sure the mouse cursor is invisible and at the default location. +; Make sure the mouse cursor is at the default location. - jsr CHIDE lda XPos sta XPosWrk ldx XPos+1 @@ -276,8 +275,7 @@ UNINSTALL: ; no special action is required besides hiding the mouse cursor. ; No return code required. -HIDE: dec visible - php +HIDE: php sei jsr CHIDE plp @@ -290,8 +288,7 @@ HIDE: dec visible ; no special action is required besides enabling the mouse cursor. ; No return code required. -SHOW: inc visible - php +SHOW: php sei jsr CSHOW plp @@ -352,13 +349,8 @@ MOVE: php pha txa pha - - lda visible - beq @L01 - - jsr CHIDE - -@L01: pla + jsr CPREP + pla tax pla @@ -377,15 +369,11 @@ MOVE: php lda (sp),y sta XPos ; New X position sta XPosWrk - jsr CMOVEX ; Move the cursor - lda visible - beq @Ret + jsr CDRAW - jsr CSHOW - -@Ret: plp ; Restore interrupt flag + plp ; Restore interrupt flag rts ;---------------------------------------------------------------------------- @@ -466,13 +454,11 @@ IRQ: ldx #MOUSE_BTN_LEFT @L0: stx Buttons - ldx visible - beq @L1 - jsr CHIDE + jsr CPREP ; Limit the X coordinate to the bounding box -@L1: lda XPosWrk+1 + lda XPosWrk+1 ldy XPosWrk tax cpy XMin @@ -518,14 +504,12 @@ IRQ: tya jsr CMOVEY - ldx visible - beq @Done + jsr CDRAW - jsr CSHOW - -@Done: clc + clc rts + ;---------------------------------------------------------------------------- ; T1Han: Local IRQ routine to poll mouse ; From 6026776460e193551f9d1e186e3d8d4a9cf459c0 Mon Sep 17 00:00:00 2001 From: Christian Groessler <chris@groessler.org> Date: Sun, 5 Jan 2014 16:43:17 +0100 Subject: [PATCH 17/31] Trakball mouse driver --- libsrc/atari/mou/atrtt.s | 481 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 481 insertions(+) create mode 100644 libsrc/atari/mou/atrtt.s diff --git a/libsrc/atari/mou/atrtt.s b/libsrc/atari/mou/atrtt.s new file mode 100644 index 000000000..16ed32602 --- /dev/null +++ b/libsrc/atari/mou/atrtt.s @@ -0,0 +1,481 @@ +; +; Mouse driver for Atari Trakball +; +; Christian Groessler, 2014-01-05 +; + + .include "zeropage.inc" + .include "mouse-kernel.inc" + .include "atari.inc" + + .macpack generic + +; ------------------------------------------------------------------------ +; Header. Includes jump table + +.segment "JUMPTABLE" + +HEADER: + +; Driver signature + + .byte $6d, $6f, $75 ; "mou" + .byte MOUSE_API_VERSION ; Mouse driver API version number + +; Library reference + + .addr $0000 + +; Jump table + + .addr INSTALL + .addr UNINSTALL + .addr HIDE + .addr SHOW + .addr SETBOX + .addr GETBOX + .addr MOVE + .addr BUTTONS + .addr POS + .addr INFO + .addr IOCTL + .addr IRQ + +; Mouse driver flags + + .byte MOUSE_FLAG_LATE_IRQ + +; Callback table, set by the kernel before INSTALL is called + +CHIDE: jmp $0000 ; Hide the cursor +CSHOW: jmp $0000 ; Show the cursor +CMOVEX: jmp $0000 ; Move the cursor to X coord +CMOVEY: jmp $0000 ; Move the cursor to Y coord + + +;---------------------------------------------------------------------------- +; Constants + +SCREEN_HEIGHT = 191 +SCREEN_WIDTH = 319 + +.enum JOY + UP = $01 + DOWN = $02 + LEFT = $04 + RIGHT = $08 +.endenum + +;---------------------------------------------------------------------------- +; Global variables. The bounding box values are sorted so that they can be +; written with the least effort in the SETBOX and GETBOX routines, so don't +; reorder them. + +.bss + +Vars: +YPos: .res 2 ; Current mouse position, Y +XPos: .res 2 ; Current mouse position, X +XMin: .res 2 ; X1 value of bounding box +YMin: .res 2 ; Y1 value of bounding box +XMax: .res 2 ; X2 value of bounding box +YMax: .res 2 ; Y2 value of bounding box +Buttons: .res 1 ; Button mask + + +visible: .res 1 + +; Default values for above variables + +.rodata + +.proc DefVars + .word SCREEN_HEIGHT/2 ; YPos + .word SCREEN_WIDTH/2 ; XPos + .word 0 ; XMin + .word 0 ; YMin + .word SCREEN_WIDTH ; XMax + .word SCREEN_HEIGHT ; YMax + .byte 0 ; Buttons +.endproc + +.code + +;---------------------------------------------------------------------------- +; INSTALL routine. Is called after the driver is loaded into memory. If +; possible, check if the hardware is present. +; Must return an MOUSE_ERR_xx code in a/x. + +INSTALL: + +; Initialize variables. Just copy the default stuff over + + ldx #.sizeof(DefVars)-1 +@L1: lda DefVars,x + sta Vars,x + dex + bpl @L1 + +; Be sure the mouse cursor is invisible and at the default location. We +; need to do that here, because our mouse interrupt handler doesn't set the +; mouse position if it hasn't changed. + + php + sei + jsr CHIDE + lda XPos + ldx XPos+1 + jsr CMOVEX + lda YPos + ldx YPos+1 + jsr CMOVEY + plp + +; Done, return zero (= MOUSE_ERR_OK) + + ldx #$00 + txa + rts + +;---------------------------------------------------------------------------- +; UNINSTALL routine. Is called before the driver is removed from memory. +; No return code required (the driver is removed from memory on return). + +UNINSTALL = HIDE ; Hide cursor on exit + +;---------------------------------------------------------------------------- +; HIDE routine. Is called to hide the mouse pointer. The mouse kernel manages +; a counter for calls to show/hide, and the driver entry point is only called +; if the mouse is currently visible and should get hidden. For most drivers, +; no special action is required besides hiding the mouse cursor. +; No return code required. + +HIDE: dec visible + php + sei + jsr CHIDE + plp + rts + +;---------------------------------------------------------------------------- +; SHOW routine. Is called to show the mouse pointer. The mouse kernel manages +; a counter for calls to show/hide, and the driver entry point is only called +; if the mouse is currently hidden and should become visible. For most drivers, +; no special action is required besides enabling the mouse cursor. +; No return code required. + +SHOW: inc visible + php + sei + jsr CSHOW + plp + rts + +;---------------------------------------------------------------------------- +; SETBOX: Set the mouse bounding box. The parameters are passed as they come +; from the C program, that is, a pointer to a mouse_box struct in a/x. +; No checks are done if the mouse is currently inside the box, this is the job +; of the caller. It is not necessary to validate the parameters, trust the +; caller and save some code here. No return code required. + +SETBOX: sta ptr1 + stx ptr1+1 ; Save data pointer + + ldy #.sizeof (MOUSE_BOX)-1 + php + sei + +@L1: lda (ptr1),y + sta XMin,y + dey + bpl @L1 + + plp + rts + +;---------------------------------------------------------------------------- +; GETBOX: Return the mouse bounding box. The parameters are passed as they +; come from the C program, that is, a pointer to a mouse_box struct in a/x. + +GETBOX: sta ptr1 + stx ptr1+1 ; Save data pointer + + ldy #.sizeof (MOUSE_BOX)-1 + php + sei + +@L1: lda XMin,y + sta (ptr1),y + dey + bpl @L1 + + plp + rts + +;---------------------------------------------------------------------------- +; MOVE: Move the mouse to a new position. The position is passed as it comes +; from the C program, that is: X on the stack and Y in a/x. The C wrapper will +; remove the parameter from the stack on return. +; No checks are done if the new position is valid (within the bounding box or +; the screen). No return code required. +; + +MOVE: php + sei ; No interrupts + + pha + lda visible + beq @nohide + txa + pha + jsr CHIDE + pla + tax +@nohide:pla + + sta YPos + stx YPos+1 ; New Y position + jsr CMOVEY ; Set it + + ldy #$01 + lda (sp),y + sta XPos+1 + tax + dey + lda (sp),y + sta XPos ; New X position + + jsr CMOVEX ; Move the cursor + + lda visible + beq @Ret + + jsr CSHOW + +@Ret: plp ; Restore interrupt flag + rts + +;---------------------------------------------------------------------------- +; BUTTONS: Return the button mask in a/x. + +BUTTONS: + lda Buttons + ldx #$00 + rts + +;---------------------------------------------------------------------------- +; POS: Return the mouse position in the MOUSE_POS struct pointed to by ptr1. +; No return code required. + +POS: ldy #MOUSE_POS::XCOORD ; Structure offset + + php + sei ; Disable interrupts + lda XPos ; Transfer the position + sta (ptr1),y + lda XPos+1 + iny + sta (ptr1),y + lda YPos + iny + sta (ptr1),y + lda YPos+1 + plp ; Restore interrupt flag + + iny + sta (ptr1),y ; Store last byte + + rts ; Done + +;---------------------------------------------------------------------------- +; INFO: Returns mouse position and current button mask in the MOUSE_INFO +; struct pointed to by ptr1. No return code required. +; +; We're cheating here to keep the code smaller: The first fields of the +; mouse_info struct are identical to the mouse_pos struct, so we will just +; call _mouse_pos to initialize the struct pointer and fill the position +; fields. + +INFO: jsr POS + +; Fill in the button state + + lda Buttons + ldy #MOUSE_INFO::BUTTONS + sta (ptr1),y + + rts + +;---------------------------------------------------------------------------- +; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl +; specific data in ptr1, and the ioctl code in A. +; Must return an error code in a/x. +; + +IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioclts for now + ldx #>MOUSE_ERR_INV_IOCTL + rts + +;---------------------------------------------------------------------------- +; IRQ: Irq handler entry point. Called as a subroutine but in IRQ context +; (so be careful). The routine MUST return carry set if the interrupt has been +; 'handled' - which means that the interrupt source is gone. Otherwise it +; MUST return carry clear. +; + +IRQ: + +; Check for a pressed button and place the result into Buttons + + ldx #0 + stx XPos+1 + stx YPos+1 + lda TRIG0 ; joystick #0 trigger + bne @L00 ; not pressed + ldx #MOUSE_BTN_LEFT +@L00: stx Buttons + + lda PORTA ; get other buttons + eor #255 + tax + and #4 + beq @L01 + lda #MOUSE_BTN_LEFT + ora Buttons + sta Buttons +@L01: txa + and #8 + beq @L02 + lda #MOUSE_BTN_RIGHT + ora Buttons + sta Buttons + +@L02: lda visible + beq @L03 + jsr CHIDE + +; Get cursor position +; ------------------- +; The touchpad is read thru the paddle potentiometers. The possible +; values are 1..228. Since the maximum value is less than the X +; dimension we have to "stretch" this value. In order to use only +; divisions by powers of two, we use the following appoximation: +; 320/227 = 1.4096 +; 1+1/2-1/8+1/32 = 1.4062 +; For Y we subtract 1/8 of it to get in the YMax ballpark. +; 228-228/8=199.5 +; A small area in the Y dimension of the touchpad isn't used with +; this approximation. The Y value is inverted, (0,0) is the bottom +; left corner of the touchpad. + +; X + +@L03: ldx PADDL0 ; get X postion + dex ; decrement, since it's 1-based + stx XPos + txa + lsr a + tax + clc + adc XPos + sta XPos + bcc @L04 + inc XPos+1 +@L04: txa + lsr a ; port value / 4 + lsr a ; port value / 8 + tax + sec + lda XPos + stx XPos + sbc XPos + sta XPos + bcs @L05 + dec XPos+1 +@L05: txa + lsr a ; port value / 16 + lsr a ; port value / 32 + clc + adc XPos + sta XPos + bcc @L06 + inc XPos+1 + +@L06: tay + lda XPos+1 + tax + +; Limit the X coordinate to the bounding box + + cpy XMin + sbc XMin+1 + bpl @L07 + ldy XMin + ldx XMin+1 + jmp @L08 +@L07: txa + + cpy XMax + sbc XMax+1 + bmi @L08 + ldy XMax + ldx XMax+1 +@L08: sty XPos + stx XPos+1 + +; Move the mouse pointer to the new X pos + + tya + jsr CMOVEX + +; Y + + ldx PADDL1 ; get Y postion + dex ; decrement, since it's 1-based + stx YPos + lda #228 + sec + sbc YPos ; invert value + tax + lsr a + lsr a + lsr a + sta YPos + txa + sec + sbc YPos + sta YPos + tay + lda YPos+1 + tax + +; Limit the Y coordinate to the bounding box + + cpy YMin + sbc YMin+1 + bpl @L09 + ldy YMin + ldx YMin+1 + jmp @L10 +@L09: txa + + cpy YMax + sbc YMax+1 + bmi @L10 + ldy YMax + ldx YMax+1 +@L10: sty YPos + stx YPos+1 + +; Move the mouse pointer to the new X pos + + tya + jsr CMOVEY + + lda visible + beq @L11 + jsr CSHOW + +@L11: clc ; Interrupt not "handled" + rts + From 97d512a1e180c1c9faa64b04d42e59cc1c9ac1d7 Mon Sep 17 00:00:00 2001 From: Christian Groessler <chris@groessler.org> Date: Mon, 6 Jan 2014 13:36:09 +0100 Subject: [PATCH 18/31] Detect pen button. If we read 228 for X or Y position, don't change cursor position, since the pen was probably lifted from the pad. --- libsrc/atari/mou/atrtt.s | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/libsrc/atari/mou/atrtt.s b/libsrc/atari/mou/atrtt.s index 16ed32602..5bf9e38a2 100644 --- a/libsrc/atari/mou/atrtt.s +++ b/libsrc/atari/mou/atrtt.s @@ -330,15 +330,12 @@ IRQ: ldx #0 stx XPos+1 stx YPos+1 - lda TRIG0 ; joystick #0 trigger - bne @L00 ; not pressed - ldx #MOUSE_BTN_LEFT -@L00: stx Buttons + stx Buttons lda PORTA ; get other buttons eor #255 tax - and #4 + and #5 ; pen button and left button are mapped to left mouse button beq @L01 lda #MOUSE_BTN_LEFT ora Buttons @@ -350,7 +347,18 @@ IRQ: ora Buttons sta Buttons -@L02: lda visible +; If we read 228 for X or Y positions, we assume the user has lifted the pen +; and don't change the cursor position. + +@L02: lda PADDL0 + cmp #228 + beq @Dont + lda PADDL1 + cmp #228 + bne @Do +@Dont: jmp @Done + +@Do: lda visible beq @L03 jsr CHIDE @@ -473,9 +481,9 @@ IRQ: jsr CMOVEY lda visible - beq @L11 + beq @Done jsr CSHOW -@L11: clc ; Interrupt not "handled" +@Done: clc ; Interrupt not "handled" rts From ecd10e632a65ea0cc256ed2797de15e6f776e231 Mon Sep 17 00:00:00 2001 From: Christian Groessler <chris@groessler.org> Date: Wed, 8 Jan 2014 02:28:39 +0100 Subject: [PATCH 19/31] some comment fixes --- libsrc/atari/mou/atrtt.s | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsrc/atari/mou/atrtt.s b/libsrc/atari/mou/atrtt.s index 5bf9e38a2..dc402db26 100644 --- a/libsrc/atari/mou/atrtt.s +++ b/libsrc/atari/mou/atrtt.s @@ -1,5 +1,5 @@ ; -; Mouse driver for Atari Trakball +; Mouse driver for Atari Touch Tablet ; ; Christian Groessler, 2014-01-05 ; @@ -364,7 +364,7 @@ IRQ: ; Get cursor position ; ------------------- -; The touchpad is read thru the paddle potentiometers. The possible +; The touch pad is read thru the paddle potentiometers. The possible ; values are 1..228. Since the maximum value is less than the X ; dimension we have to "stretch" this value. In order to use only ; divisions by powers of two, we use the following appoximation: From 1fd7c2b3182e83242cc030aed5df2cfc2a4353b3 Mon Sep 17 00:00:00 2001 From: Christian Groessler <chris@groessler.org> Date: Sat, 11 Jan 2014 01:49:21 +0100 Subject: [PATCH 20/31] fix bug where the high byte of X and Y positions were destroyed of the user had lifted the pen --- libsrc/atari/mou/atrtt.s | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/libsrc/atari/mou/atrtt.s b/libsrc/atari/mou/atrtt.s index dc402db26..9d2dac1c9 100644 --- a/libsrc/atari/mou/atrtt.s +++ b/libsrc/atari/mou/atrtt.s @@ -89,6 +89,8 @@ visible: .res 1 .rodata +; (We use ".proc" because we want to define both a label and a scope.) + .proc DefVars .word SCREEN_HEIGHT/2 ; YPos .word SCREEN_WIDTH/2 ; XPos @@ -328,14 +330,12 @@ IRQ: ; Check for a pressed button and place the result into Buttons ldx #0 - stx XPos+1 - stx YPos+1 stx Buttons lda PORTA ; get other buttons eor #255 tax - and #5 ; pen button and left button are mapped to left mouse button + and #5 ; pen button and left button are mapped to left mouse button beq @L01 lda #MOUSE_BTN_LEFT ora Buttons @@ -350,18 +350,22 @@ IRQ: ; If we read 228 for X or Y positions, we assume the user has lifted the pen ; and don't change the cursor position. -@L02: lda PADDL0 - cmp #228 - beq @Dont - lda PADDL1 - cmp #228 - bne @Do -@Dont: jmp @Done +@L02: lda PADDL0 + cmp #228 + beq @Dont + lda PADDL1 + cmp #228 + bne @Do +@Dont: jmp @Done -@Do: lda visible +@Do: lda visible beq @L03 jsr CHIDE +@L03: ldx #0 + stx XPos+1 + stx YPos+1 + ; Get cursor position ; ------------------- ; The touch pad is read thru the paddle potentiometers. The possible @@ -378,7 +382,7 @@ IRQ: ; X -@L03: ldx PADDL0 ; get X postion + ldx PADDL0 ; get X postion dex ; decrement, since it's 1-based stx XPos txa From 9e155eb096412bc38e3bb71fbcf292743eb7c149 Mon Sep 17 00:00:00 2001 From: Christian Groessler <chris@groessler.org> Date: Tue, 14 Jan 2014 13:59:42 +0100 Subject: [PATCH 21/31] Always print the mouse cursor, even if coordinates haven't changed. This makes sure that the cursor is always visible, even if the program has written text to the screen (only valid for non-P/M mouse callbacks). --- libsrc/atari/mou/atrtt.s | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/libsrc/atari/mou/atrtt.s b/libsrc/atari/mou/atrtt.s index 9d2dac1c9..f58838720 100644 --- a/libsrc/atari/mou/atrtt.s +++ b/libsrc/atari/mou/atrtt.s @@ -118,12 +118,8 @@ INSTALL: dex bpl @L1 -; Be sure the mouse cursor is invisible and at the default location. We -; need to do that here, because our mouse interrupt handler doesn't set the -; mouse position if it hasn't changed. +; Be sure the mouse cursor is invisible and at the default location. - php - sei jsr CHIDE lda XPos ldx XPos+1 @@ -131,7 +127,6 @@ INSTALL: lda YPos ldx YPos+1 jsr CMOVEY - plp ; Done, return zero (= MOUSE_ERR_OK) @@ -352,15 +347,18 @@ IRQ: @L02: lda PADDL0 cmp #228 - beq @Dont + beq @Cont ; CF set if equal lda PADDL1 - cmp #228 - bne @Do -@Dont: jmp @Done + cmp #228 ; CF set if equal -@Do: lda visible - beq @L03 +@Cont: lda visible + beq @Go + php ; remember CF jsr CHIDE + plp ; restore CF + +@Go: bcc @L03 + jmp @Show @L03: ldx #0 stx XPos+1 @@ -484,7 +482,7 @@ IRQ: tya jsr CMOVEY - lda visible +@Show: lda visible beq @Done jsr CSHOW From 63ce6e28fef215bd571cff9ef35306563d3dea9f Mon Sep 17 00:00:00 2001 From: Christian Groessler <chris@groessler.org> Date: Sat, 18 Jan 2014 00:02:40 +0100 Subject: [PATCH 22/31] Adapt to new mouse driver interface ('prep' and 'draw') --- libsrc/atari/mou/atrtt.s | 40 +++++++++++++--------------------------- 1 file changed, 13 insertions(+), 27 deletions(-) diff --git a/libsrc/atari/mou/atrtt.s b/libsrc/atari/mou/atrtt.s index f58838720..e373ec015 100644 --- a/libsrc/atari/mou/atrtt.s +++ b/libsrc/atari/mou/atrtt.s @@ -49,6 +49,8 @@ HEADER: CHIDE: jmp $0000 ; Hide the cursor CSHOW: jmp $0000 ; Show the cursor +CPREP: jmp $0000 ; Prepare to move the cursor +CDRAW: jmp $0000 ; Draw the cursor CMOVEX: jmp $0000 ; Move the cursor to X coord CMOVEY: jmp $0000 ; Move the cursor to Y coord @@ -82,9 +84,6 @@ XMax: .res 2 ; X2 value of bounding box YMax: .res 2 ; Y2 value of bounding box Buttons: .res 1 ; Button mask - -visible: .res 1 - ; Default values for above variables .rodata @@ -118,9 +117,8 @@ INSTALL: dex bpl @L1 -; Be sure the mouse cursor is invisible and at the default location. +; Make sure the mouse cursor is at the default location. - jsr CHIDE lda XPos ldx XPos+1 jsr CMOVEX @@ -147,8 +145,7 @@ UNINSTALL = HIDE ; Hide cursor on exit ; no special action is required besides hiding the mouse cursor. ; No return code required. -HIDE: dec visible - php +HIDE: php sei jsr CHIDE plp @@ -161,8 +158,7 @@ HIDE: dec visible ; no special action is required besides enabling the mouse cursor. ; No return code required. -SHOW: inc visible - php +SHOW: php sei jsr CSHOW plp @@ -221,14 +217,12 @@ MOVE: php sei ; No interrupts pha - lda visible - beq @nohide txa pha - jsr CHIDE + jsr CPREP pla tax -@nohide:pla + pla sta YPos stx YPos+1 ; New Y position @@ -241,15 +235,11 @@ MOVE: php dey lda (sp),y sta XPos ; New X position - jsr CMOVEX ; Move the cursor - lda visible - beq @Ret - jsr CSHOW -@Ret: plp ; Restore interrupt flag + plp ; Restore interrupt flag rts ;---------------------------------------------------------------------------- @@ -351,13 +341,11 @@ IRQ: lda PADDL1 cmp #228 ; CF set if equal -@Cont: lda visible - beq @Go - php ; remember CF - jsr CHIDE +@Cont: php ; remember CF + jsr CPREP plp ; restore CF -@Go: bcc @L03 + bcc @L03 jmp @Show @L03: ldx #0 @@ -482,10 +470,8 @@ IRQ: tya jsr CMOVEY -@Show: lda visible - beq @Done - jsr CSHOW +@Show: jsr CDRAW -@Done: clc ; Interrupt not "handled" + clc ; Interrupt not "handled" rts From 478da8e51f1e294649b4ee2b861ff15e965b18af Mon Sep 17 00:00:00 2001 From: Christian Groessler <chris@groessler.org> Date: Thu, 20 Feb 2014 00:45:48 +0100 Subject: [PATCH 23/31] load CASHDR segment into RAM --- cfg/atari-cassette.cfg | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cfg/atari-cassette.cfg b/cfg/atari-cassette.cfg index ba640a54e..e69abfb4e 100644 --- a/cfg/atari-cassette.cfg +++ b/cfg/atari-cassette.cfg @@ -14,7 +14,7 @@ MEMORY { # HEADER: file = "", start = $0000, size = $0002; # CASHDR: file = %O, start = $3FD, size = 128, fill = yes; - CASHDR: file = %O, start = $0, size = 6; +# CASHDR: file = %O, start = $0, size = 6; # "main program" load chunk # MAINHDR: file = "", start = $0000, size = $0004; RAM: file = %O, define = yes, start = %S, size = $BC20 - __STACKSIZE__ - __RESERVED_MEMORY__ - %S; @@ -23,7 +23,8 @@ MEMORY { SEGMENTS { # EXEHDR: load = HEADER, type = ro; # MAINHDR: load = MAINHDR, type = ro; - CASHDR: load = CASHDR, type = ro; +# CASHDR: load = CASHDR, type = ro; + CASHDR: load = RAM, type = ro; CASINIT: load = RAM, type = ro; STARTUP: load = RAM, type = ro, define = yes; LOWCODE: load = RAM, type = ro, define = yes, optional = yes; From 8178c71de1da66a8093a7a308541a5a1b75441fc Mon Sep 17 00:00:00 2001 From: Christian Groessler <chris@groessler.org> Date: Thu, 20 Feb 2014 00:56:22 +0100 Subject: [PATCH 24/31] add utility program to write files to cassette --- util/atari/w2cas.c | 186 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 util/atari/w2cas.c diff --git a/util/atari/w2cas.c b/util/atari/w2cas.c new file mode 100644 index 000000000..38c2f0fdf --- /dev/null +++ b/util/atari/w2cas.c @@ -0,0 +1,186 @@ +/* w2cas.c -- write file to cassette + * + * This program writes a boot file (typically linked with + * 'atari-cassette.cfg') to the cassette. + * Only files < 32K are supported, since the loading of + * larger files requires a special loader inside the program. + * + * Christian Groessler, chris@groessler.org, 2014 + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <6502.h> +#include <atari.h> +#include <conio.h> + +static int verbose = 1; +static char C_dev[] = "C:"; + +static struct __iocb *findfreeiocb(void) +{ + struct __iocb *iocb = &IOCB; /* first IOCB (#0) */ + int i; + + for (i = 0; i < 8; i++) { + if (iocb->handler == 0xff) + return iocb; + iocb++; + } + return NULL; +} + +int main(int argc, char **argv) +{ + char *filename, *x; + char buf[20]; + FILE *file; + unsigned char *buffer; + size_t filen, buflen = 32768l + 1; + struct regs regs; + struct __iocb *iocb = findfreeiocb(); + int iocb_num; + + if (! iocb) { + fprintf(stderr, "couldn't find a free iocb\n"); + if (_dos_type != 1) + cgetc(); + return 1; + } + iocb_num = (iocb - &IOCB) * 16; + if (verbose) + printf("using iocb index $%02X ($%04X)\n", iocb_num, iocb); + + if (argc < 2) { + printf("\nfilename: "); + x = fgets(buf, 19, stdin); + printf("\n"); + if (! x) + return 1; + if (*x && *(x + strlen(x) - 1) == '\n') + *(x + strlen(x) - 1) = 0; + filename = x; + } + else { + filename = *(argv+1); + } + + /* allocate buffer */ + buffer = malloc(buflen); + if (! buffer) { + buflen = _heapmaxavail() - 8; /* get as much as we can */ + buffer = malloc(buflen); + if (! buffer) { + fprintf(stderr, "cannot alloc %ld bytes -- aborting...\n", (long)buflen); + if (_dos_type != 1) + cgetc(); + return 1; + } + } + if (verbose) + printf("buffer size: %ld bytes\n", (long)buflen); + + /* open file */ + file = fopen(filename, "rb"); + if (! file) { + free(buffer); + fprintf(stderr, "cannot open '%s': %s\n", filename, strerror(errno)); + if (_dos_type != 1) + cgetc(); + return 1; + } + + /* read file -- file length must be < 32K */ + if (verbose) + printf("reading input file...\n"); + filen = fread(buffer, 1, buflen, file); + if (! filen) { + fprintf(stderr, "read error\n"); + file_err: + fclose(file); + free(buffer); + if (_dos_type != 1) + cgetc(); + return 1; + } + if (filen > 32767l) { + fprintf(stderr, "file is too large (must be < 32768)\n"); + goto file_err; + } + if (filen == buflen) { /* we have a buffer < 32768 and the file fits into it (and is most probably larger) */ + fprintf(stderr, "not enough memory\n"); + goto file_err; + } + if (verbose) + printf("file size: %ld bytes\n", (long)filen); + + /* close input file */ + fclose(file); + + /* open cassette */ + if (verbose) + printf("opening cassette...\n"); + iocb->buffer = C_dev; + iocb->aux1 = 8; /* open for output */ + iocb->aux2 = 128; /* short breaks and no stop between data blocks */ + iocb->command = IOCB_OPEN; + regs.x = iocb_num; + regs.pc = 0xe456; /* CIOV */ + + _sys(®s); + if (regs.y != 1) { + fprintf(stderr, "CIO call to open cassette returned %d\n", regs.y); + free(buffer); + if (_dos_type != 1) + cgetc(); + return 1; + } + + /* write file */ + if (verbose) + printf("writing to cassette...\n"); + iocb->buffer = buffer; + iocb->buflen = filen; + iocb->command = IOCB_PUTCHR; + regs.x = iocb_num; + regs.pc = 0xe456; /* CIOV */ + + _sys(®s); + if (regs.y != 1) { + fprintf(stderr, "CIO call to write file returned %d\n", regs.y); + free(buffer); + + iocb->command = IOCB_CLOSE; + regs.x = iocb_num; + regs.pc = 0xe456; /* CIOV */ + _sys(®s); + + if (_dos_type != 1) + cgetc(); + return 1; + } + + /* free buffer */ + free(buffer); + + /* close cassette */ + iocb->command = IOCB_CLOSE; + regs.x = iocb_num; + regs.pc = 0xe456; /* CIOV */ + _sys(®s); + + if (regs.y != 1) { + fprintf(stderr, "CIO call to close cassette returned %d\n", regs.y); + if (_dos_type != 1) + cgetc(); + return 1; + } + + /* all is fine */ + printf("success\n"); + if (_dos_type != 1) + cgetc(); + return 0; +} From 09f7eb72c247d59d5f1a0bee80039f118e42c658 Mon Sep 17 00:00:00 2001 From: Christian Groessler <chris@groessler.org> Date: Fri, 21 Feb 2014 22:42:09 +0100 Subject: [PATCH 25/31] remove workaround for _heapmaxavail --- util/atari/w2cas.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/atari/w2cas.c b/util/atari/w2cas.c index 38c2f0fdf..050218cfe 100644 --- a/util/atari/w2cas.c +++ b/util/atari/w2cas.c @@ -70,7 +70,7 @@ int main(int argc, char **argv) /* allocate buffer */ buffer = malloc(buflen); if (! buffer) { - buflen = _heapmaxavail() - 8; /* get as much as we can */ + buflen = _heapmaxavail(); /* get as much as we can */ buffer = malloc(buflen); if (! buffer) { fprintf(stderr, "cannot alloc %ld bytes -- aborting...\n", (long)buflen); From 8b876b2ce50e1c5cb85e62280e9030b9597451fe Mon Sep 17 00:00:00 2001 From: Christian Groessler <chris@groessler.org> Date: Fri, 21 Feb 2014 22:42:54 +0100 Subject: [PATCH 26/31] document 'atari-cassette.cfg' --- doc/atari.sgml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/doc/atari.sgml b/doc/atari.sgml index 9f7a3fbc4..908763a3f 100644 --- a/doc/atari.sgml +++ b/doc/atari.sgml @@ -221,6 +221,16 @@ that the cartridge doesn't prevent the booting of DOS. The option byte will be located at address $BFFD. For more information about its use, see e.g. "Mapping the Atari". +<sect2><tt/atari-cassette.cfg/<p> + +This config file can be used to create cassette boot files. It's suited both +for C and assembly language programs. + +The size of a cassette boot file is restricted to 32K. Larger programs +would need to be split in more parts and the parts to be loaded manually. + +To write the generated file to a cassette, an utility program to run +on an Atari is provided (<tt/util/atari/w2cas.c/). <sect1><tt/atarixl/ config files<p> From 81fe7a38051030924a55ff278469a70c7e5b43c0 Mon Sep 17 00:00:00 2001 From: Christian Groessler <chris@groessler.org> Date: Fri, 21 Feb 2014 22:43:44 +0100 Subject: [PATCH 27/31] cleanups; split 'header' and 'init' part into two source files --- cfg/atari-cassette.cfg | 42 ++++++++++++---------------------- libsrc/atari/cashdr.s | 51 ++++++++++++++++++++---------------------- libsrc/atari/casinit.s | 31 +++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 55 deletions(-) create mode 100644 libsrc/atari/casinit.s diff --git a/cfg/atari-cassette.cfg b/cfg/atari-cassette.cfg index e69abfb4e..1099bf91c 100644 --- a/cfg/atari-cassette.cfg +++ b/cfg/atari-cassette.cfg @@ -1,41 +1,27 @@ FEATURES { - STARTADDRESS: default = $1000; + STARTADDRESS: default = $0700; } SYMBOLS { -_cas_init: type = import; - __STACKSIZE__: type = weak, value = $0800; # 2k stack + __STACKSIZE__: type = weak, value = $0800; # 2k stack + __RESERVED_MEMORY__: type = weak, value = $0000; __STARTADDRESS__: type = export, value = %S; - __RESERVED_MEMORY__: type = weak, value = $0000; + _cas_hdr: type = import; } MEMORY { ZP: file = "", define = yes, start = $0082, size = $007E; - -# file header, just $FFFF -# HEADER: file = "", start = $0000, size = $0002; - -# CASHDR: file = %O, start = $3FD, size = 128, fill = yes; -# CASHDR: file = %O, start = $0, size = 6; -# "main program" load chunk -# MAINHDR: file = "", start = $0000, size = $0004; RAM: file = %O, define = yes, start = %S, size = $BC20 - __STACKSIZE__ - __RESERVED_MEMORY__ - %S; -# TRAILER: file = "", start = $0000, size = $0006; } SEGMENTS { -# EXEHDR: load = HEADER, type = ro; -# MAINHDR: load = MAINHDR, type = ro; -# CASHDR: load = CASHDR, type = ro; - CASHDR: load = RAM, type = ro; - CASINIT: load = RAM, type = ro; - STARTUP: load = RAM, type = ro, define = yes; - LOWCODE: load = RAM, type = ro, define = yes, optional = yes; - INIT: load = RAM, type = ro, optional = yes; - CODE: load = RAM, type = ro, define = yes; - RODATA: load = RAM, type = ro; - DATA: load = RAM, type = rw; - BSS: load = RAM, type = bss, define = yes; - ZEROPAGE: load = ZP, type = zp; - EXTZP: load = ZP, type = zp, optional = yes; -# AUTOSTRT: load = TRAILER, type = ro; + CASHDR: load = RAM, type = ro; + STARTUP: load = RAM, type = ro, define = yes, optional = yes; + LOWCODE: load = RAM, type = ro, define = yes, optional = yes; + INIT: load = RAM, type = ro, optional = yes; + CODE: load = RAM, type = ro, define = yes; + RODATA: load = RAM, type = ro, optional = yes; + DATA: load = RAM, type = rw, optional = yes; + BSS: load = RAM, type = bss, define = yes, optional = yes; + ZEROPAGE: load = ZP, type = zp, optional = yes; + EXTZP: load = ZP, type = zp, optional = yes; } FEATURES { CONDES: type = constructor, diff --git a/libsrc/atari/cashdr.s b/libsrc/atari/cashdr.s index 8d3d0868a..99aefe68f 100644 --- a/libsrc/atari/cashdr.s +++ b/libsrc/atari/cashdr.s @@ -1,40 +1,37 @@ ; ; Cassette boot file header ; -; Christian Groessler, chris@groessler.org, 2013 +; Christian Groessler, chris@groessler.org, 2014 ; +;DEBUG = 1 + .ifndef __ATARIXL__ - .include "atari.inc" + .include "atari.inc" - .import __BSS_RUN__, __STARTADDRESS__, start - .export _cas_init + .import __BSS_RUN__, __STARTADDRESS__, _cas_init + .export _cas_hdr + +.assert ((__BSS_RUN__ - __STARTADDRESS__ + 127) / 128) < $101, error, "File to big to load from cassette" + + +; for a description of the cassette header, see De Re Atari, appendix C .segment "CASHDR" - .byte 0 ; ignored - .byte <((__BSS_RUN__ - __STARTADDRESS__ + 127 + 6) / 128) - .word __STARTADDRESS__ - .word _cas_init +_cas_hdr: + .byte 0 ; ignored + .byte <((__BSS_RUN__ - __STARTADDRESS__ + 127) / 128) ; # of 128-byte records to read + .word __STARTADDRESS__ ; load address + .word _cas_init ; init address -.segment "CASINIT" +.ifdef DEBUG + lda #33 + ldy #80 + sta (SAVMSC),y +.endif + clc + rts - lda #33 - ldy #80 - sta (SAVMSC),y - clc - rts - -_cas_init: - lda #34 - ldy #81 - sta (SAVMSC),y - - lda #<start - sta DOSVEC - lda #>start - sta DOSVEC+1 - rts - -.endif ; .ifdef __ATARIXL__ +.endif ; .ifdef __ATARIXL__ diff --git a/libsrc/atari/casinit.s b/libsrc/atari/casinit.s new file mode 100644 index 000000000..c91989aad --- /dev/null +++ b/libsrc/atari/casinit.s @@ -0,0 +1,31 @@ +; +; Cassette boot file init routine +; +; Christian Groessler, chris@groessler.org, 2014 +; + +;DEBUG = 1 + +.ifndef __ATARIXL__ + + .include "atari.inc" + + .import start + .export _cas_init + +.segment "INIT" + +_cas_init: +.ifdef DEBUG + lda #34 + ldy #81 + sta (SAVMSC),y +.endif + + lda #<start + sta DOSVEC + lda #>start + sta DOSVEC+1 + rts + +.endif ; .ifdef __ATARIXL__ From 4b58a20b8c414527af035ec37c32fc38621d8c2b Mon Sep 17 00:00:00 2001 From: Christian Groessler <chris@groessler.org> Date: Fri, 21 Feb 2014 23:34:05 +0100 Subject: [PATCH 28/31] Increase the default start address a bit in case BASIC is started ('OPTION' not pressed at power on). It would otherwise overwrite parts at the beginning. --- cfg/atari-cassette.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cfg/atari-cassette.cfg b/cfg/atari-cassette.cfg index 1099bf91c..2116aecd0 100644 --- a/cfg/atari-cassette.cfg +++ b/cfg/atari-cassette.cfg @@ -1,5 +1,5 @@ FEATURES { - STARTADDRESS: default = $0700; + STARTADDRESS: default = $0900; } SYMBOLS { __STACKSIZE__: type = weak, value = $0800; # 2k stack From dec2376195db1faf89aba3dba9c30373768f320d Mon Sep 17 00:00:00 2001 From: Christian Groessler <chris@groessler.org> Date: Sat, 1 Mar 2014 01:48:45 +0100 Subject: [PATCH 29/31] small wording change --- doc/atari.sgml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/atari.sgml b/doc/atari.sgml index 908763a3f..781fdf03b 100644 --- a/doc/atari.sgml +++ b/doc/atari.sgml @@ -229,7 +229,7 @@ for C and assembly language programs. The size of a cassette boot file is restricted to 32K. Larger programs would need to be split in more parts and the parts to be loaded manually. -To write the generated file to a cassette, an utility program to run +To write the generated file to a cassette, a utility to run on an Atari is provided (<tt/util/atari/w2cas.c/). <sect1><tt/atarixl/ config files<p> From 69f81f6d67a2fb3127adbca68f508c65c1d4dd33 Mon Sep 17 00:00:00 2001 From: Christian Groessler <chris@groessler.org> Date: Sat, 1 Mar 2014 13:10:01 +0100 Subject: [PATCH 30/31] make 'w2cas' a targetutil --- doc/atari.sgml | 2 +- libsrc/Makefile | 1 + libsrc/atari/targetutil/Makefile.inc | 14 ++++++++++++++ {util/atari => libsrc/atari/targetutil}/w2cas.c | 0 4 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 libsrc/atari/targetutil/Makefile.inc rename {util/atari => libsrc/atari/targetutil}/w2cas.c (100%) diff --git a/doc/atari.sgml b/doc/atari.sgml index 781fdf03b..867f25c1d 100644 --- a/doc/atari.sgml +++ b/doc/atari.sgml @@ -230,7 +230,7 @@ The size of a cassette boot file is restricted to 32K. Larger programs would need to be split in more parts and the parts to be loaded manually. To write the generated file to a cassette, a utility to run -on an Atari is provided (<tt/util/atari/w2cas.c/). +on an Atari is provided (<tt/W2CAS.COM/). <sect1><tt/atarixl/ config files<p> diff --git a/libsrc/Makefile b/libsrc/Makefile index 3d8277ae5..89f952376 100644 --- a/libsrc/Makefile +++ b/libsrc/Makefile @@ -102,6 +102,7 @@ MKINC = $(GEOS) \ nes TARGETUTIL = apple2 \ + atari \ geos-apple GEOSDIRS = common \ diff --git a/libsrc/atari/targetutil/Makefile.inc b/libsrc/atari/targetutil/Makefile.inc new file mode 100644 index 000000000..eb371e111 --- /dev/null +++ b/libsrc/atari/targetutil/Makefile.inc @@ -0,0 +1,14 @@ +ifeq ($(TARGET),atari) + +DEPS += ../wrk/$(TARGET)/w2cas.d + +../wrk/$(TARGET)/w2cas.o: CC65FLAGS:=-O -W error +../wrk/$(TARGET)/w2cas.o: $(SRCDIR)/targetutil/w2cas.c | ../wrk/$(TARGET) + $(COMPILE_recipe) + +../targetutil/W2CAS.COM: ../wrk/$(TARGET)/w2cas.o ../lib/$(TARGET).lib | ../targetutil + $(LD65) -o $@ -t $(TARGET) $^ + +$(TARGET): ../targetutil/W2CAS.COM + +endif diff --git a/util/atari/w2cas.c b/libsrc/atari/targetutil/w2cas.c similarity index 100% rename from util/atari/w2cas.c rename to libsrc/atari/targetutil/w2cas.c From 7a9fa9d4cd69bebf10054f123c836cde768e6884 Mon Sep 17 00:00:00 2001 From: Christian Groessler <chris@groessler.org> Date: Mon, 3 Mar 2014 18:12:11 +0100 Subject: [PATCH 31/31] rename W2CAS.COM to w2cas.com (lowercase) --- doc/atari.sgml | 2 +- libsrc/atari/targetutil/Makefile.inc | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/atari.sgml b/doc/atari.sgml index 867f25c1d..79a3e3015 100644 --- a/doc/atari.sgml +++ b/doc/atari.sgml @@ -230,7 +230,7 @@ The size of a cassette boot file is restricted to 32K. Larger programs would need to be split in more parts and the parts to be loaded manually. To write the generated file to a cassette, a utility to run -on an Atari is provided (<tt/W2CAS.COM/). +on an Atari is provided in the <tt/targetutil/ directory (<tt/w2cas.com/). <sect1><tt/atarixl/ config files<p> diff --git a/libsrc/atari/targetutil/Makefile.inc b/libsrc/atari/targetutil/Makefile.inc index eb371e111..a54d96100 100644 --- a/libsrc/atari/targetutil/Makefile.inc +++ b/libsrc/atari/targetutil/Makefile.inc @@ -6,9 +6,9 @@ DEPS += ../wrk/$(TARGET)/w2cas.d ../wrk/$(TARGET)/w2cas.o: $(SRCDIR)/targetutil/w2cas.c | ../wrk/$(TARGET) $(COMPILE_recipe) -../targetutil/W2CAS.COM: ../wrk/$(TARGET)/w2cas.o ../lib/$(TARGET).lib | ../targetutil +../targetutil/w2cas.com: ../wrk/$(TARGET)/w2cas.o ../lib/$(TARGET).lib | ../targetutil $(LD65) -o $@ -t $(TARGET) $^ -$(TARGET): ../targetutil/W2CAS.COM +$(TARGET): ../targetutil/w2cas.com endif