Apple 2 mouse driver and other stuff from Oliver Schmidt

git-svn-id: svn://svn.cc65.org/cc65/trunk@3717 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz
2006-04-06 19:51:37 +00:00
parent f507124733
commit 685235795c
17 changed files with 660 additions and 46 deletions

View File

@@ -1,5 +1,6 @@
*.emd
*.joy
*.mou
*.ser
*.tgi
closedir.s

View File

@@ -32,6 +32,9 @@ CFLAGS = -Osir -g -T -t $(SYS) --forget-inc-paths -I . -I ../../include
%.joy: %.o ../runtime/zeropage.o
@$(LD) -t module -o $@ $^
%.mou: %.o ../runtime/zeropage.o
@$(LD) -t module -o $@ $^
%.ser: %.o ../runtime/zeropage.o
@$(LD) -t module -o $@ $^
@@ -76,6 +79,7 @@ S_OBJS= _scrsize.o \
joy_stddrv.o \
kbhit.o \
mainargs.o \
mcbdefault.o \
mli.o \
open.o \
oserrlist.o \
@@ -109,6 +113,8 @@ EMDS = apple2-lc.emd
JOYS = apple2-stdjoy.joy
MOUS = apple2-stdmou.mou
SERS = apple2-ssc.ser
TGIS = apple2-40-40-16.tgi apple2-280-192-6.tgi
@@ -118,14 +124,13 @@ TGIS = apple2-40-40-16.tgi apple2-280-192-6.tgi
.PHONY: all clean zap
all: $(C_OBJS) $(S_OBJS) $(EMDS) $(JOYS) $(SERS) $(TGIS)
all: $(C_OBJS) $(S_OBJS) $(EMDS) $(JOYS) $(MOUS) $(SERS) $(TGIS)
../runtime/zeropage.o:
$(MAKE) -C $(dir $@) $(notdir $@)
clean:
@$(RM) $(C_OBJS:.o=.s) $(C_OBJS) $(S_OBJS) $(EMDS:.emd=.o) $(JOYS:.joy=.o) $(SERS:.ser=.o) $(TGIS:.tgi=.o)
zap: clean
@$(RM) $(EMDS) $(JOYS) $(SERS) $(TGIS)
@$(RM) $(C_OBJS:.o=.s) $(C_OBJS) $(S_OBJS) $(EMDS:.emd=.o) $(JOYS:.joy=.o) $(MOUS:.mou=.o) $(SERS:.ser=.o) $(TGIS:.tgi=.o)
zap: clean
@$(RM) $(EMDS) $(JOYS) $(MOUS) $(SERS) $(TGIS)

View File

@@ -0,0 +1,411 @@
;
; Driver for the AppleMouse II Card.
;
; Oliver Schmidt, 03.09.2005
;
.include "zeropage.inc"
.include "mouse-kernel.inc"
; ------------------------------------------------------------------------
SETMOUSE = $12 ; Sets mouse mode
SERVEMOUSE = $13 ; Services mouse interrupt
READMOUSE = $14 ; Reads mouse position
CLEARMOUSE = $15 ; Clears mouse position to 0 (for delta mode)
POSMOUSE = $16 ; Sets mouse position to a user-defined pos
CLAMPMOUSE = $17 ; Sets mouse bounds in a window
HOMEMOUSE = $18 ; Sets mouse to upper-left corner of clamp win
INITMOUSE = $19 ; Resets mouse clamps to default values and
; sets mouse position to 0,0
pos1_lo := $0478
pos1_hi := $0578
pos2_lo := $04F8
pos2_hi := $05F8
status := $0778
; ------------------------------------------------------------------------
.segment "JUMPTABLE"
; Driver signature
.byte $6D, $6F, $75 ; "mou"
.byte MOUSE_API_VERSION ; Mouse driver API version number
; Jump table.
.addr INSTALL
.addr UNINSTALL
.addr HIDE
.addr SHOW
.addr BOX
.addr MOVE
.addr BUTTONS
.addr POS
.addr INFO
.addr IOCTL
.addr 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
; ------------------------------------------------------------------------
.bss
slot: .res 1
visible:.res 1
; ------------------------------------------------------------------------
.rodata
offsets:.byte $05 ; Pascal 1.0 ID byte
.byte $07 ; Pascal 1.0 ID byte
.byte $0B ; Pascal 1.1 generic signature byte
.byte $0C ; Device signature byte
values: .byte $38 ; Fixed
.byte $18 ; Fixed
.byte $01 ; Fixed
.byte $20 ; X-Y pointing device type 0
size = * - values
; ------------------------------------------------------------------------
.data
info: .word 279 / 2 ; MOUSE_INFO::MOUSE_POS::XCOORD
.word 191 / 2 ; MOUSE_INFO::MOUSE_POS::YCOORD
.byte %00000000 ; MOUSE_INFO::BUTTONS
firmware:
; Lookup and patch firmware address lobyte
lookup: ldy $FF00,x ; Patched at runtime
sty jump+1 ; Modify code below
; Apple II Mouse TechNote #1, Interrupt Environment with the Mouse:
; "Enter all mouse routines (...) with the X register set to $Cn
; and Y register set to $n0, where n = the slot number."
xparam: ldx #$FF ; Patched at runtime
yparam: ldy #$FF ; Patched at runtime
jump: jmp $FFFF ; Patched at runtime
; ------------------------------------------------------------------------
.code
; INSTALL: 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:
lda #<$C000
sta ptr1
lda #>$C000
sta ptr1+1
; Search for AppleMouse II firmware in slots 1 - 7
next: inc ptr1+1
lda ptr1+1
cmp #>$C800
bcc :+
; Mouse firmware not found
lda #<MOUSE_ERR_NO_DEVICE
ldx #>MOUSE_ERR_NO_DEVICE
rts
; Check Pascal 1.1 Firmware Protocol ID bytes
: ldx #size - 1
: ldy offsets,x
lda values,x
cmp (ptr1),y
bne next
dex
bpl :-
; Get and patch firmware address hibyte
lda ptr1+1
sta lookup+2
sta xparam+1
sta jump+2
; Convert to and save slot number
and #$0F
sta slot
; Convert to and patch I/O register index
asl
asl
asl
asl
sta yparam+1
; Apple II Mouse TechNote #1, Interrupt Environment with the Mouse:
; "Disable interrupts when calling any mouse routine."
sei
; Reset mouse hardware
ldx #INITMOUSE
jsr firmware
; Turn mouse on
lda #%00000001
ldx #SETMOUSE
jsr firmware
; Set initial mouse clamps
lda #<279
ldx #>279
sta pos2_lo
stx pos2_hi
lda #$00 ; Set x clamps
sta pos1_lo
sta pos1_hi
ldx #CLAMPMOUSE
jsr firmware
lda #<191
ldx #>191
sta pos2_lo
stx pos2_hi
lda #$01 ; Set y clamps
ldx #CLAMPMOUSE
jsr firmware
; Set initial mouse position
ldx slot
lda #<(279 / 2)
sta pos1_lo,x
lda #>(279 / 2)
sta pos1_hi,x
lda #<(191 / 2)
sta pos2_lo,x
lda #>(191 / 2)
sta pos2_hi,x
ldx #POSMOUSE
jsr firmware
; Turn VBL interrupt on
lda #%00001001
ldx #SETMOUSE
common: jsr firmware
; Enable interrupts and return success
cli
lda #<MOUSE_ERR_OK
ldx #>MOUSE_ERR_OK
rts
; UNINSTALL: Is called before the driver is removed from memory.
; No return code required (the driver is removed from memory on return).
UNINSTALL:
; Hide cursor
sei
jsr CHIDE
; Turn mouse off
lda #%00000000
ldx #SETMOUSE
bne common ; Branch always
; HIDE: Is called to hide the mouse cursor. 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: Is called to show the mouse cursor. 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
rts
; BOX: Set the mouse bounding box. The parameters are passed as they come from
; the C program, that is, maxy in A/X and the other parameters on the stack.
; The C wrapper will remove the parameters from the stack when the driver
; routine returns.
; 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.
BOX:
; Apple II Mouse TechNote #1, Interrupt Environment with the Mouse:
; "Disable interrupts before placing position information in the screen holes."
sei
; Set high clamp
sta pos2_lo
txa
ldx #$01 ; Set y clamps
ldy #$00 ; Start at top of stack
jsr :+
ldx #$00 ; Set x clamps
ldy #$00 ; Start at top of stack
; Set high clamp
lda (sp),y
iny
sei
sta pos2_lo
lda (sp),y
iny
: sta pos2_hi
; Skip one parameter
iny
iny
; Set low clamp
lda (sp),y
iny
sta pos1_lo
lda (sp),y
sta pos1_hi
txa
ldx #CLAMPMOUSE
bne common ; Branch always
; 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:
ldy slot
sei
; Set y
sta pos2_lo,y
txa
sta pos2_hi,y
tya
tax
ldy #$00 ; Start at top of stack
; Set x
lda (sp),y
iny
sta pos1_lo,x
lda (sp),y
sta pos1_hi,x
; Update cursor
jsr update
ldx #POSMOUSE
bne common ; Branch always
; BUTTONS: Return the button mask in A/X.
BUTTONS:
lda info + MOUSE_INFO::BUTTONS
ldx #$00
rts
; POS: Return the mouse position in the MOUSE_POS struct pointed to by ptr1.
; No return code required.
POS:
ldx #.sizeof(MOUSE_POS)-1
bne copy ; Branch always
; INFO: Returns mouse position and current button mask in the MOUSE_INFO
; struct pointed to by ptr1. No return code required.
INFO:
ldx #.sizeof(MOUSE_INFO)-1
copy: txa
tay
sei
: lda info,x
sta (ptr1),y
dex
dey
bpl :-
cli
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 MOUSE_ERR_xx code in A/X.
IOCTL:
lda #<MOUSE_ERR_INV_IOCTL
ldx #>MOUSE_ERR_INV_IOCTL
rts
; IRQ: Called from the builtin runtime IRQ handler as a subroutine. All
; registers are already saved, no parameters are passed, but the carry flag
; is clear on entry. The routine must return with carry set if the interrupt
; was handled, otherwise with carry clear.
IRQ:
; Check for mouse interrupt
ldx #SERVEMOUSE
jsr firmware
bcc :+
clc ; Interrupt not handled
rts
: ldx #READMOUSE
jsr firmware
; Get status
ldy slot
lda status,y
tax ; Save status
; Extract button down values
asl ; C = Button 0 is currently down
and #%00100000 ; !Z = Button 1 is currently down
; Set button mask
beq :+
lda #MOUSE_BTN_RIGHT
: bcc :+
ora #MOUSE_BTN_LEFT
: sta info + MOUSE_INFO::BUTTONS
; Check for mouse movement
txa ; Restore status
and #%00100000 ; X or Y changed since last READMOUSE
beq :+
; Remove the cursor at the old position
update: jsr CHIDE
; Get and set the new X position
ldy slot
lda pos1_lo,y
ldx pos1_hi,y
sta info + MOUSE_POS::XCOORD
stx info + MOUSE_POS::XCOORD+1
jsr CMOVEX
; Get and set the new Y position
ldy slot
lda pos2_lo,y
ldx pos2_hi,y
sta info + MOUSE_POS::YCOORD
stx info + MOUSE_POS::YCOORD+1
jsr CMOVEY
; Check for visibility
: lda visible
beq :+
; Draw the cursor at the new position
jsr CSHOW
: sec ; Interrupt handled
rts

View File

@@ -6,7 +6,7 @@
;
.ifdef __APPLE2ENH__
.constructor initconio
.constructor initconio, 17
.endif
.export _cputcxy, _cputc
.export cputdirect, newline, putchar

View File

@@ -20,7 +20,7 @@
; ProDOS 8 2.0.3 - $23
;
.constructor initdostype, 25
.constructor initdostype, 19
.export __dos_type
.include "mli.inc"

View File

@@ -22,7 +22,7 @@
; TO-DO:
; Add a control-character quoting mechanism.
.constructor initmainargs, 24
.constructor initmainargs, 18
.import __argc, __argv, __dos_type
.include "zeropage.inc"

136
libsrc/apple2/mcbdefault.s Normal file
View File

@@ -0,0 +1,136 @@
;
; Default mouse callbacks for the Apple II
;
; Oliver Schmidt, 22.09.2005
;
; All functions in this module should be interrupt safe, because they may
; be called from an interrupt handler
;
.ifdef __APPLE2ENH__
.constructor initmcb
.endif
.export _mouse_def_callbacks
.include "apple2.inc"
; ------------------------------------------------------------------------
.bss
backup: .res 1
; ------------------------------------------------------------------------
.rodata
; Callback structure
_mouse_def_callbacks:
.addr hide
.addr show
.addr movex
.addr movey
; ------------------------------------------------------------------------
.segment "INIT"
.ifdef __APPLE2ENH__
initmcb:
lda ALTCHARSET ; Alternate charset switched in?
bpl :+ ; No, normal charset
lda #'B' ; MouseText character
sta cmpcur+1
sta getcur+1
: rts
.endif
; ------------------------------------------------------------------------
.data
getcursor:
.ifdef __APPLE2ENH__
bit RD80VID ; In 80 column mode?
bpl column ; No, skip bank switching
switch: bit LOWSCR ; Patched at runtime
.endif
column: ldx #$00 ; Patched at runtime
getscr: lda $0400,x ; Patched at runtime
cmpcur: cmp #'+' | $40 ; Possibly patched by initialization
rts
setcursor:
getcur: lda #'+' | $40 ; Possibly patched by initialization
setscr: sta $0400,x ; Patched at runtime
.ifdef __APPLE2ENH__
bit LOWSCR ; Doesn't hurt in 40 column mode
.endif
rts
; ------------------------------------------------------------------------
.code
done:
.ifdef __APPLE2ENH__
bit LOWSCR ; Doesn't hurt in 40 column mode
.endif
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:
dex ; Is position [256..279]?
bmi :+ ; No, start with column 0
clc
adc #$0100 .MOD 7 ; Bias position
ldx #$0100 / 7 - 1 ; Bias column
: sec
: sbc #7 ; 280 positions / 40 columns
inx
bcs :-
stx column+1
.ifdef __APPLE2ENH__
adc #7 / 2 ; Left or right half of 40-col column?
ldx #<LOWSCR ; Columns 1,3,5..79
bcs :+
.assert LOWSCR + 1 = HISCR, error
inx ; Columns 0,2,4..78
: stx switch+1
.endif
rts
; Move the mouse cursor y position to the value in A/X.
movey:
tax ; ABCDExxx
lsr ; 0ABCDExx
lsr ; 00ABCDEx
lsr ; 000ABCDE
sta getscr+1
lsr ; 0000ABCD
and #%00000011 ; 000000CD
ora #>$0400 ; 000001CD
sta getscr+2
sta setscr+2
txa ; ABCDExxx
ror ; EABCDExx
and #%11100000 ; EAB00000
ora getscr+1 ; EABABCDE
and #%11111000 ; EABAB000
sta getscr+1
sta setscr+1
rts