diff --git a/WeeGUI.xcodeproj/project.pbxproj b/WeeGUI.xcodeproj/project.pbxproj index ea5632f..ddce831 100644 --- a/WeeGUI.xcodeproj/project.pbxproj +++ b/WeeGUI.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXFileReference section */ + 70427F2219D648730031D960 /* mouse.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = mouse.s; sourceTree = ""; }; 70868EE019BD150C00E4B4CB /* rects.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = rects.s; sourceTree = ""; }; 70868EE119BD178F00E4B4CB /* zeropage.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = zeropage.s; sourceTree = ""; }; 709E88E319AC0A5F0069DB55 /* views.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = views.s; sourceTree = ""; }; @@ -38,6 +39,7 @@ 70868EE019BD150C00E4B4CB /* rects.s */, 709E88E319AC0A5F0069DB55 /* views.s */, 70A3A2C219BFE2C3006A2EC4 /* applesoft.s */, + 70427F2219D648730031D960 /* mouse.s */, 70D435B219A013AF001BFD9B /* gui.s */, 709E88E419AC0DC20069DB55 /* unit_test.s */, 70D435B419A0141F001BFD9B /* guidemo.s */, diff --git a/gui.s b/gui.s index cd10a70..1ce752e 100644 --- a/gui.s +++ b/gui.s @@ -22,7 +22,7 @@ main: jsr WGInit jsr WG80 - rts + ;rts ;jmp tortureTestPrint ;jmp tortureTestRects @@ -46,10 +46,12 @@ main: ; lda #0 ; jsr WGScrollX - lda #-17 - jsr WGScrollY +; lda #-17 +; jsr WGScrollY - jsr testPaintContents +; jsr testPaintContents + + jsr WGEnableMouse keyLoop: lda KBD @@ -242,6 +244,7 @@ read80ColSwitch_40: .include "painting.s" .include "rects.s" .include "views.s" +.include "mouse.s" .include "applesoft.s" .include "unit_test.s" .include "memory.s" diff --git a/guidemo.dsk b/guidemo.dsk index 5b79665..723df61 100644 Binary files a/guidemo.dsk and b/guidemo.dsk differ diff --git a/memory.s b/memory.s index 3479300..316b46b 100644 --- a/memory.s +++ b/memory.s @@ -22,6 +22,9 @@ VIEW_STYLE_TAKESFOCUS = $02 ; Styles >= this one are selectable VIEW_STYLE_APPLESOFT = $80 ; High nybble flag bit for views created from Applesoft +IRQVECTORL = $03fe +IRQVECTORH = $03ff + ; ROM entry points @@ -29,6 +32,7 @@ COUT = $fded BASCALC = $fbc1 PRBYTE = $fdda RDKEY = $fd0c +BELL = $fbdd ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/mouse.s b/mouse.s new file mode 100644 index 0000000..6c6f9b6 --- /dev/null +++ b/mouse.s @@ -0,0 +1,351 @@ +; +; mouse.s +; Routines for handling the mouse +; +; Created by Quinn Dunki on 8/15/14. +; Copyright (c) 2014 One Girl, One Laptop Productions. All rights reserved. +; + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Mouse firmware ROM entry points and constants +; +SETMOUSE = $c412 ; Indirect +SERVEMOUSE = $c413 ; Indirect +READMOUSE = $c414 ; Indirect +CLEARMOUSE = $c415 ; Indirect +POSMOUSE = $c416 ; Indirect +CLAMPMOUSE = $c417 ; Indirect +HOMEMOUSE = $c418 ; Indirect +INITMOUSE = $c419 ; Indirect + +MOUSTAT = $0778 ; + Slot Num +MOUSE_XL = $0478 ; + Slot Num +MOUSE_XH = $0578 ; + Slot Num +MOUSE_YL = $04f8 ; + Slot Num +MOUSE_YH = $05f8 ; + Slot Num +MOUSE_CLAMPL = $04f8 +MOUSE_CLAMPH = $05f8 + +MOUSTAT_MASK_BUTTONINT = %00000100 +MOUSTAT_MASK_MOVEINT = %00000010 +MOUSTAT_MASK_DOWN = %10000000 +MOUSTAT_MASK_HELD = %01000000 +MOUSTAT_MASK_MOVED = %00100000 + +MOUSEMODE_OFF = $00 ; Mouse off +MOUSEMODE_PASSIVE = $01 ; Passive mode (polling only) +MOUSEMODE_MOVEINT = $03 ; Interrupts on movement +MOUSEMODE_BUTINT = $05 ; Interrupts on button +MOUSEMODE_COMBINT = $07 ; Interrupts on movement and button + + +.macro CALLMOUSE name ; Mouse firmware is all indirectly called, because + pha + lda name ; it moved around a lot in different Apple ][ ROM + sta WG_MOUSE_JUMPL ; versions. This macro abstracts this for us. + + pla + php ; Note that mouse firmware is not re-entrant, + sei ; so we must disable interrupts inside them + + phx + phy + jsr WGEnableMouse_CallFirmware + ply + plx + + plp + +.endmacro + + +CH_MOUSEPOINTER = 'B' + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; WGEnableMouse +; Prepares the mouse for use +; +WGEnableMouse: + pha + + ; Find slot number and calculate the various indirections needed + lda #$4 + sta WG_MOUSE_SLOT + lda #$c0 + ora WG_MOUSE_SLOT + sta WG_MOUSE_JUMPH + lda WG_MOUSE_SLOT + asl + asl + asl + asl + sta WG_MOUSE_SLOTSHIFTED + + ; Install our interrupt handler + lda #WGMouseInterruptHandler + sta IRQVECTORH + + ; Initialize the mouse + lda #0 + sta WG_MOUSEPOS_X + sta WG_MOUSEPOS_Y + sta WG_MOUSEBG + + CALLMOUSE INITMOUSE + bcs WGEnableMouse_Error ; Firmware sets carry if mouse is not available + + CALLMOUSE CLEARMOUSE + + lda #MOUSEMODE_COMBINT + CALLMOUSE SETMOUSE + + ; Scale the mouse's range into something ease to do math with, + ; while retaining as much range of motion and precision as possible + lda #$80 ; 640 horizontally + sta MOUSE_CLAMPL + lda #$02 + sta MOUSE_CLAMPH + lda #0 + CALLMOUSE CLAMPMOUSE + + lda #$e0 ; 736 vertically + sta MOUSE_CLAMPL + lda #$02 + sta MOUSE_CLAMPH + lda #1 + CALLMOUSE CLAMPMOUSE + + lda #1 + sta WG_MOUSEACTIVE + + cli + bra WGEnableMouse_done + +WGEnableMouse_Error: + lda #0 + sta WG_MOUSEACTIVE + +WGEnableMouse_done: + pla + rts + +WGEnableMouse_CallFirmware: + ldx WG_MOUSE_JUMPH + ldy WG_MOUSE_SLOTSHIFTED + jmp (WG_MOUSE_JUMPL) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; WGDisableMouse +; Shuts off the mouse when we're done with it +; +WGDisableMouse: + pha + + lda MOUSEMODE_OFF + CALLMOUSE SETMOUSE + + lda #0 + sta WG_MOUSEACTIVE + + pla + rts + + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; WGMouseInterruptHandler +; Handles interrupts that may be related to the mouse +; +WGMouseInterruptHandler: + SAVE_AXY + SETSWITCH PAGE2OFF ; Turn this off so we don't mess up page 4 screen holes! + + CALLMOUSE SERVEMOUSE + bcs WGMouseInterruptHandler_disregard + + CALLMOUSE READMOUSE + + jsr WGUndrawPointer ; Prepare to move the pointer + + ; Read mouse position and divide by 16 to get into our screen space + ldx WG_MOUSE_SLOT + lsr MOUSE_XH,x + ror MOUSE_XL,x + lsr MOUSE_XH,x + ror MOUSE_XL,x + lsr MOUSE_XH,x + ror MOUSE_XL,x + + lda MOUSE_XL,x + sta WG_MOUSEPOS_X + + lsr MOUSE_YH,x + ror MOUSE_YL,x + lsr MOUSE_YH,x + ror MOUSE_YL,x + lsr MOUSE_YH,x + ror MOUSE_YL,x + lsr MOUSE_YH,x + ror MOUSE_YL,x + lsr MOUSE_YH,x + ror MOUSE_YL,x + + lda MOUSE_YL,x + sta WG_MOUSEPOS_Y + + lda MOUSTAT,x + and #MOUSTAT_MASK_DOWN + bne WGMouseInterruptHandler_button + + bra WGMouseInterruptHandler_intDone + +WGMouseInterruptHandler_button: + jsr BELL + +WGMouseInterruptHandler_intDone: + jsr WGDrawPointer ; Redraw the pointer + + RESTORE_AXY + +WGMouseInterruptHandler_disregard: + rti + + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; WGUndrawPointer +; Unplots the mouse pointer at current location +; Side effects: Clobbers BASL,BASH +; +WGUndrawPointer: + SAVE_AXY + + lda WG_MOUSEBG + beq WGUndrawPointer_done ; Mouse pointer has never rendered + + ldx WG_MOUSEPOS_Y + cpx #24 + bcs WGUndrawPointer_done + + lda TEXTLINES_L,x ; Compute video memory address of point + sta BASL + lda TEXTLINES_H,x + sta BASH + + lda WG_MOUSEPOS_X + cmp #80 + bcs WGUndrawPointer_done + + lsr + clc + adc BASL + sta BASL + lda #$0 + adc BASH + sta BASH + + lda WG_MOUSEPOS_X ; X even? + and #$01 + bne WGUndrawPointer_xOdd + + SETSWITCH PAGE2ON ; Restore the background + ldy #$0 + lda WG_MOUSEBG + sta (BASL),y + bra WGUndrawPointer_done + +WGUndrawPointer_xOdd: + SETSWITCH PAGE2OFF ; Restore the background + ldy #$0 + lda WG_MOUSEBG + sta (BASL),y + +WGUndrawPointer_done: + SETSWITCH PAGE2OFF ; Turn this off so we don't mess up page 4 screen holes! + RESTORE_AXY + rts + + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; WGDrawPointer +; Plots the mouse pointer at current location +; Side effects: Clobbers BASL,BASH +; +WGDrawPointer: + SAVE_AXY + + ldx WG_MOUSEPOS_Y + cpx #24 + bcs WGDrawPointer_done + + lda TEXTLINES_L,x ; Compute video memory address of point + sta BASL + lda TEXTLINES_H,x + sta BASH + + lda WG_MOUSEPOS_X + cmp #80 + bcs WGDrawPointer_done + + lsr + clc + adc BASL + sta BASL + lda #$0 + adc BASH + sta BASH + + lda WG_MOUSEPOS_X ; X even? + and #$01 + bne WGDrawPointer_xOdd + + SETSWITCH PAGE2ON + ldy #$0 + lda (BASL),y ; Save background + sta WG_MOUSEBG + lda #CH_MOUSEPOINTER ; Draw the pointer + sta (BASL),y + bra WGDrawPointer_done + +WGDrawPointer_xOdd: + SETSWITCH PAGE2OFF + ldy #$0 + lda (BASL),y ; Save background + sta WG_MOUSEBG + lda #CH_MOUSEPOINTER ; Draw the pointer + sta (BASL),y + +WGDrawPointer_done: + SETSWITCH PAGE2OFF ; Turn this off so we don't mess up page 4 screen holes! + RESTORE_AXY + rts + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Mouse API state +; +WG_MOUSEACTIVE: +.byte 0 + +WG_MOUSEPOS_X: +.byte 39 +WG_MOUSEPOS_Y: +.byte 11 + +WG_MOUSEBG: +.byte 0 + +WG_MOUSE_JUMPL: +.byte 0 +WG_MOUSE_JUMPH: +.byte 0 +WG_MOUSE_SLOT: +.byte 0 +WG_MOUSE_SLOTSHIFTED: +.byte 0