File: a2.stdmou.s

package info (click to toggle)
cc65 2.19-2
  • links: PTS
  • area: main
  • in suites: forky, sid, trixie
  • size: 20,268 kB
  • sloc: ansic: 117,151; asm: 66,339; pascal: 4,248; makefile: 1,009; perl: 607
file content (441 lines) | stat: -rw-r--r-- 12,447 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
;
; Driver for the AppleMouse II Card.
;
; Oliver Schmidt, 03.09.2005
;

        .include        "zeropage.inc"
        .include        "mouse-kernel.inc"
        .include        "apple2.inc"

        .macpack        module

; ------------------------------------------------------------------------

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

; ------------------------------------------------------------------------

        .ifdef  __APPLE2ENH__
        module_header   _a2e_stdmou_mou
        .else
        module_header   _a2_stdmou_mou
        .endif

        ; 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_EARLY_IRQ

        ; Callback table, set by the kernel before INSTALL is called
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

; ------------------------------------------------------------------------

        .bss

box:    .tag    MOUSE_BOX
info:   .tag    MOUSE_INFO
slot:   .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

inibox: .word     0             ; MinX
        .word     0             ; MinY
        .word   279             ; MaxX
        .word   191             ; MaxY

; ------------------------------------------------------------------------

        .data

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

        ; Disable interrupts now because setting the slot number makes 
        ; the IRQ handler (maybe called due to some non-mouse IRQ) try
        ; calling the firmware which isn't correctly set up yet
        sei

        ; 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
        
        ; The AppleMouse II Card needs the ROM switched in
        ; to be able to detect an Apple //e and use RDVBL
        bit     $C082

        ; Reset mouse hardware
        ldx     #INITMOUSE
        jsr     firmware
        
        ; Switch in LC bank 2 for R/O
        bit     $C080

        ; Turn mouse on
        lda     #%00000001
        ldx     #SETMOUSE
        jsr     firmware

        ; Set initial mouse clamps
        lda     #<inibox
        ldx     #>inibox
        jsr     SETBOX

        ; 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

        ; Update cursor
        jsr     update

        ; 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

; 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
        
        ; Set x clamps
        ldx     #$00
        ldy     #MOUSE_BOX::MINX
        jsr     :+
        
        ; Set y clamps
        ldx     #$01
        ldy     #MOUSE_BOX::MINY

        ; Apple II Mouse TechNote #1, Interrupt Environment with the Mouse:
        ; "Disable interrupts before placing position information in the
        ;  screen holes."
:       sei

        ; Set low clamp
        lda     (ptr1),y
        sta     box,y
        sta     pos1_lo
        iny
        lda     (ptr1),y
        sta     box,y   
        sta     pos1_hi

        ; Skip one word
        iny
        iny

        ; Set high clamp
        iny
        lda     (ptr1),y
        sta     box,y   
        sta     pos2_lo
        iny
        lda     (ptr1),y
        sta     box,y   
        sta     pos2_hi

        txa
        ldx     #CLAMPMOUSE
        bne     common          ; Branch always

; 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

        ldy     #.sizeof(MOUSE_BOX)-1
:       lda     box,y
        sta     (ptr1),y
        dey
        bpl     :-
        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:
        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

; 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:
        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:
        sei
        jsr     CSHOW
        cli
        rts

; 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:
        ldy     #.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:
        ldy     #.sizeof(MOUSE_INFO)-1
copy:   sei
:       lda     info,y
        sta     (ptr1),y
        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 installed mouse
        lda     slot
        beq     done

        ; Check for mouse interrupt
        ldx     #SERVEMOUSE
        jsr     firmware
        bcc     :+
        clc                     ; Interrupt not handled
done:   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     CPREP

        ; 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

        ; Draw the cursor at the new position
:       jsr     CDRAW
        sec                     ; Interrupt handled
        rts