From 8bb8ac888caf73bd3e9136043047de19d04b98f5 Mon Sep 17 00:00:00 2001 From: Marcus Rowe Date: Sun, 16 Jun 2024 22:05:05 +1000 Subject: [PATCH 01/22] Fix potential Hyperkin mouse read errors with FastROM --- pvsneslib/source/vblank.asm | 41 ++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/pvsneslib/source/vblank.asm b/pvsneslib/source/vblank.asm index 551ecf06..22e02a61 100644 --- a/pvsneslib/source/vblank.asm +++ b/pvsneslib/source/vblank.asm @@ -486,18 +486,35 @@ _MouseData: rts @_m20: - rep #$10 - ldy #16 ; Read 16 bit data. - sep #$10 - -@_m30: - lda REG_JOYA,x - - lsr a - rol mouse_x,x - rol mouse_y,x - dey - bne @_m30 + + + ; According to https://snes.nesdev.org/wiki/Mouse the Hyperkin mouse had extra timing requirements: + ; * At least 170 master cycles between bit reads + ; * At least 336 master cycles between reading the 2nd and 3rd byte + ; + ; The second requirement is already met. Auto-Joypad read will read the first 16 bits and there + ; is a significant delay between the end of Auto-Joypad read and the start of this read-loop. + ; + ; SlowROM: This loop is 190 m-cycles. No read-delay was required. + ; FastROM: This loop is 188 m-cycles. 2 nop instructions were required. + ; + ; The delays were manually cycle counted and verified with Mesen's Debugger. + + ; Read 16 bits + ldy #16 + @_m30: + lda.w REG_JOYA,x + + lsr a + rol.w mouse_x,x + rol.w mouse_y,x + .ifdef FASTROM + nop ; Read delay for hyperkin mouse support. + nop ; 1 extra nop for safety (to match the SnesDev wiki) + .endif + dey + bne @_m30 + stz mousePressed,x From cd2174f7d8d402c90d657ed08bce2de6e135e42f Mon Sep 17 00:00:00 2001 From: Marcus Rowe Date: Sun, 14 Jul 2024 11:35:23 +1000 Subject: [PATCH 02/22] Decrease the maximum number of loops in mouseSpeedChange to 4 The Hyperkin mouse always outputs a sensitivity of 0, which will cause the mouseSpeedChange loop to always timeout. Decreasing the maximum number of loops will reduce CPU usage when using a Hyperkin mouse. --- pvsneslib/source/input.asm | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pvsneslib/source/input.asm b/pvsneslib/source/input.asm index 2a1737e2..4db5ab15 100644 --- a/pvsneslib/source/input.asm +++ b/pvsneslib/source/input.asm @@ -320,7 +320,12 @@ mouseSpeedChange: lda mouseConnect,x beq _s25 - lda #$10 + + ; Limit the number of cycle-sensitivity commands to send to the mouse. + ; Done for 2 reasons: + ; 1. Prevents an infinite loop if the mouse has been disconnected. + ; 2. The Hyperkin mouse will always report a mouse sensitivity of 0. + lda #4 sta tcc__r0h _s10: From c8db9b085fb853fd4b300db364f21493bceda406 Mon Sep 17 00:00:00 2001 From: Marcus Rowe Date: Sun, 14 Jul 2024 11:48:54 +1000 Subject: [PATCH 03/22] Fix mouseSpeedChange clobbering high byte of index registers --- pvsneslib/source/input.asm | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/pvsneslib/source/input.asm b/pvsneslib/source/input.asm index 4db5ab15..b2de1c63 100644 --- a/pvsneslib/source/input.asm +++ b/pvsneslib/source/input.asm @@ -287,20 +287,26 @@ detectSuperScope: ; void mouseSpeedChange(u8 port) mouseSpeedChange: php - sep #$30 phb + rep #$30 ; Must push/pop 16 bit index (switching to 8 bit Index clobbers high byte) phx phy - lda #$00 ; Set Data Bank to 0 + sep #$30 +.ACCU 8 +.INDEX 8 + + lda #$00 pha plb +// DB = 0 - lda 8,s ; Set port + lda 10,s ; port argument tax jsr @speed_change + rep #$30 ply plx plb From 06a9093fece165f09cf288552a8ff117e650177b Mon Sep 17 00:00:00 2001 From: Marcus Rowe Date: Sun, 14 Jul 2024 11:50:54 +1000 Subject: [PATCH 04/22] Fix missing bounds test in mouseSpeedChange() --- pvsneslib/source/input.asm | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pvsneslib/source/input.asm b/pvsneslib/source/input.asm index b2de1c63..5f4be6f7 100644 --- a/pvsneslib/source/input.asm +++ b/pvsneslib/source/input.asm @@ -302,9 +302,11 @@ mouseSpeedChange: // DB = 0 lda 10,s ; port argument - tax - - jsr @speed_change + cmp #2 + bcs + + tax + jsr @speed_change + + rep #$30 ply From cfccdda1d1acbdfa84731720756ba83d8a8964f4 Mon Sep 17 00:00:00 2001 From: Marcus Rowe Date: Sun, 14 Jul 2024 12:29:27 +1000 Subject: [PATCH 05/22] Optimise mouseSpeedChange() Also removes the unread private `mouse_sp` variable --- pvsneslib/source/input.asm | 82 +++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 40 deletions(-) diff --git a/pvsneslib/source/input.asm b/pvsneslib/source/input.asm index 5f4be6f7..fe354c9f 100644 --- a/pvsneslib/source/input.asm +++ b/pvsneslib/source/input.asm @@ -105,7 +105,6 @@ snes_mouse db ; for lib use. Tells the system to initialize mouse usage mouseConnect dsb 2 ; Mouse connection ports (D0=4016, D0=4017) mouseSpeedSet dsb 2 ; Mouse speed setting -mouse_sp dsb 2 ; Mouse speed mouseButton dsb 2 ; Mouse button trigger mousePressed dsb 2 ; Mouse button turbo @@ -317,71 +316,74 @@ mouseSpeedChange: ; Called by _MouseRead in the Vblank ISR +; TIMING: Not auto-joypad read ; X = 0 or 1 +; KEEP: X ; DB = 0 .ACCU 8 .INDEX 8 @speed_change: - php - sep #$30 - + ; Early exit if mouse is not connected lda mouseConnect,x - beq _s25 + beq @Return + lda mouseSpeedSet,x + and #2 + tay ; Limit the number of cycle-sensitivity commands to send to the mouse. ; Done for 2 reasons: ; 1. Prevents an infinite loop if the mouse has been disconnected. ; 2. The Hyperkin mouse will always report a mouse sensitivity of 0. lda #4 - sta tcc__r0h + sta.b tcc__r0h -_s10: - lda #$01 - sta REG_JOYA - lda REG_JOYA,x ; Speed change (1 step) - stz REG_JOYA + @CycleLoop: + ; X = port + ; Y = requested sensitivity + ; tcc__r0h = decrementing loop counter - lda #$01 ; Read speed data. - sta REG_JOYA ; Shift register clear. - lda #$00 - sta REG_JOYA + ; Send a cycle-sensitivity command to the mouse + lda #$01 + sta REG_JOYA + lda REG_JOYA,x + stz REG_JOYA - sta mouse_sp,x ; Speed register clear. - ldy #10 ; Shift register read has no meaning + ; Read sensitivity bits from mouse + ; + ; No Hyperkin mouse read delay is required as the Hyperkin mouse does not support + ; cycle-sensitivity commands. -_s20: - lda REG_JOYA,x - dey - bne _s20 + ; Skip the first 10 bits + ; Using A for loop counter so Y is unchanged + lda #10 + - + bit REG_JOYA,x + dec a + bne - - lda REG_JOYA,x ; Read speed + ; Read the 2 sensitivity bits + stz.b tcc__r0 - lsr a - rol mouse_sp,x + lda REG_JOYA,x + lsr + rol.b tcc__r0 - lda REG_JOYA, x + lda REG_JOYA,x + lsr + rol.b tcc__r0 - lsr a - rol mouse_sp,x - lda mouse_sp,x - cmp mouseSpeedSet,x ; Set speed or not? + ; Return if read sensitivity == Y + cpy.b tcc__r0 + beq @Return - beq _s30 + dec.b tcc__r0h + bne @CycleLoop - dec tcc__r0h ; For error check - bne _s10 - -_s25: - lda #$80 ; Speed change error. - sta mouse_sp,x - -_s30: - plp +@Return: rts - .ENDS From dab42368ee088c93d01392e848f99d837b51e17a Mon Sep 17 00:00:00 2001 From: Marcus Rowe Date: Sun, 14 Jul 2024 19:56:58 +1000 Subject: [PATCH 06/22] Rewrite and optimise _MouseData mouse reading code --- pvsneslib/source/input.asm | 20 +++--- pvsneslib/source/vblank.asm | 133 +++++++++++++++--------------------- 2 files changed, 65 insertions(+), 88 deletions(-) diff --git a/pvsneslib/source/input.asm b/pvsneslib/source/input.asm index fe354c9f..1fff52c6 100644 --- a/pvsneslib/source/input.asm +++ b/pvsneslib/source/input.asm @@ -96,25 +96,23 @@ scope_sinceshot dsb 2 .ENDS ;--------------------------------------------------------------------------------- -; Mouse Driver Routine (Ver 1 .00) +; Mouse variables ;--------------------------------------------------------------------------------- .RAMSECTION ".reg_mouse" BANK 0 SLOT 1 -snes_mouse db ; for lib use. Tells the system to initialize mouse usage -mouseConnect dsb 2 ; Mouse connection ports (D0=4016, D0=4017) +snes_mouse db ; Flag to enable mouse reading in VBlank ISR -mouseSpeedSet dsb 2 ; Mouse speed setting +mouseConnect dsb 2 ; Mouse connection status -mouseButton dsb 2 ; Mouse button trigger -mousePressed dsb 2 ; Mouse button turbo +mouseSpeedSet dsb 2 ; Mouse speed setting -mouse_y dsb 2 ; Mouse Y direction -mouse_x dsb 2 ; Mouse X direction +mouseButton dsb 2 ; Mouse buttons pressed this frame +mousePressed dsb 2 ; Mouse buttons held/pressed +mousePreviousPressed dsb 2 ; Mouse buttons held/pressed in the previous frame -mouse_sb dsb 2 ; Previous switch status - -connect_st dsb 2 +mouse_y dsb 2 ; Mouse Y displacement +mouse_x dsb 2 ; Mouse X displacement .ENDS diff --git a/pvsneslib/source/vblank.asm b/pvsneslib/source/vblank.asm index 22e02a61..9d16487a 100644 --- a/pvsneslib/source/vblank.asm +++ b/pvsneslib/source/vblank.asm @@ -377,28 +377,7 @@ _GetScope: ;--------------------------------------------------------------------------------- - -;* mouse read - -;--------------------------------------------------------------------------------- - -;* If this routine is called every frame, then the mouse status will be set -;* to the appropriate registers. -;* INPUT -;* None (Mouse key read automatically) -;* OUTPUT -;* Connection status (mouse_con) D0=1 Mouse connected to Joyl -;* D1=1 Mouse connected to Joy2 -;* Switch (mousePressed,1) D0=left switch turbo -;* D1=right switch turbo -;* Switch (mouseButton,1) D0=left switch trigger -;* D1=right switch trigger -;* Mouse movement (ball) value -;* (mouse_x) D7=0 Positive turn, D7=1 Negative turn -;* D6-D0 X movement value -;* (mouse_y) D7=0 Positive turn, D7=1 Negative turn -;* D6-D0 X movement value - +; Mouse read ;--------------------------------------------------------------------------------- @@ -418,35 +397,23 @@ _MouseRead: ; The code assumes Joypad Auto-Read is not active. ; This is enforced by a REG_HVBJOY spinloop in the VBlank ISR. - ldx #$01 - lda REG_JOY2L ; Joy2 + ldx #1 + lda REG_JOY2L jsr _MouseData - lda connect_st+1 - beq @_20 - - jsr mouseSpeedChange@speed_change - stz connect_st+1 - -@_20: - dex - lda REG_JOY1L ; Joy1 + ldx #0 + lda REG_JOY1L jsr _MouseData - lda connect_st - beq @_30 - - jsr mouseSpeedChange@speed_change - stz connect_st - -@_30: + ; Disable `snes_mouse` if both mice have been disconnected. lda mouseConnect ora mouseConnect+1 bne + - stz snes_mouse ; Disable mouse flag if no mouse connected + stz snes_mouse + + + -+: rep #$10 rts @@ -455,39 +422,43 @@ _MouseRead: ;; ;; IN: A = REG_JOY1L or REG_JOY2L ;; IN: X = 0 or 1 +;; KEEP: X ;; ;; DB = 0 ;; D = tcc__registers_nmi_isr (NOT ZERO) .accu 8 .index 8 _MouseData: + tay - sta tcc__r0 ; (421A / 4218 saved to reg0) - and.b #$0F - cmp.b #$01 ; Is the mouse connected? - beq @_m10 + ; Test if a mouse is connected + and.b #$0f + cmp.b #$01 + bne @NoMouseConnected - stz mouseConnect,x ; No connection. + ; Test if the mouse was connected on this frame + lda mouseConnect,x + beq @SetMouseSensitvity - stz mouseButton,x - stz mousePressed,x - stz mouse_x,x - stz mouse_y,x - rts + ; Update mouse button/pressed variables + lda mousePressed,x + sta mousePreviousPressed,x -@_m10: - lda mouseConnect,x ; When mouse is connected, speed will change. - bne @_m20 ; Previous connection status - ; (mouse.com judged by lower 1 bit) - lda #$01 ; Connection check flag on - sta mouseConnect,x - sta connect_st,x - rts + tya + asl a + rol a + rol a + and #3 + sta mousePressed,x -@_m20: + eor mousePreviousPressed,x + and mousePressed,x + sta mouseButton,x + ; Manually read the displacement bits from the controller port. + ; ; According to https://snes.nesdev.org/wiki/Mouse the Hyperkin mouse had extra timing requirements: ; * At least 170 master cycles between bit reads ; * At least 336 master cycles between reading the 2nd and 3rd byte @@ -515,31 +486,39 @@ _MouseData: dey bne @_m30 + rts - stz mousePressed,x - - rol tcc__r0 - rol mousePressed,x - rol tcc__r0 - rol mousePressed,x ; Switch turbo - lda mousePressed,x - eor mouse_sb,x ; Get switch trigger - bne @_m40 +; The Nintendo Mouse has a bug where the reported sensitivity and the internal sensitivity do +; not match when the mouse is powered on. +; +; To fix this bug at a cycle-sensitivity command must be sent to the mouse when it is first +; connected to the console, even if the sensitivity bits are what the user wants. +; +; Calling `speed_change` will cycle the sensitivity at least once and try to cycle the sensitivity +; to match `mouseSpeedSet`. +@SetMouseSensitvity: + jsr mouseSpeedChange@speed_change - stz mouseButton,x + ; Set mouse connected flag + lda #1 + sta mouseConnect,x - rts + ; Clear mouse variables, they might not be valid. + bra @ClearMouseState -@_m40: - lda mousePressed,x - sta mouseButton,x - sta mouse_sb,x +@NoMouseConnected: + stz mouseConnect,x +@ClearMouseState: + stz mouseButton,x + stz mousePressed,x + stz mousePreviousPressed,x + stz mouse_x,x + stz mouse_y,x rts - ;--------------------------------------------------------------------------------- .accu 16 From 0492c77296fb8acddebb491009a419fa3fda8df8 Mon Sep 17 00:00:00 2001 From: Marcus Rowe Date: Mon, 15 Jul 2024 17:21:50 +1000 Subject: [PATCH 07/22] Move mouseConnect test out of mouseSpeedChange@speed_change and into mouseSpeedChange, since mouseConnect is always true when speed_change is called by the VBlank ISR. --- pvsneslib/source/input.asm | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/pvsneslib/source/input.asm b/pvsneslib/source/input.asm index 1fff52c6..d5b7c27f 100644 --- a/pvsneslib/source/input.asm +++ b/pvsneslib/source/input.asm @@ -302,7 +302,11 @@ mouseSpeedChange: cmp #2 bcs + tax - jsr @speed_change + + ; Call `speed_change` if the mouse if connected. + lda mouseConnect,x + beq + + jsr @speed_change + rep #$30 @@ -315,16 +319,13 @@ mouseSpeedChange: ; Called by _MouseRead in the Vblank ISR ; TIMING: Not auto-joypad read +; REQUIRES: Mouse connected on port X ; X = 0 or 1 ; KEEP: X ; DB = 0 .ACCU 8 .INDEX 8 @speed_change: - ; Early exit if mouse is not connected - lda mouseConnect,x - beq @Return - lda mouseSpeedSet,x and #2 tay From 86fb14747ba2323e811d4795dad4c49a46751e25 Mon Sep 17 00:00:00 2001 From: Marcus Rowe Date: Sun, 28 Jul 2024 13:42:14 +1000 Subject: [PATCH 08/22] Fix detectMouse() not detecting a mouse if a non-standard controller is connected to the other controller port. --- pvsneslib/source/input.asm | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/pvsneslib/source/input.asm b/pvsneslib/source/input.asm index d5b7c27f..78f06784 100644 --- a/pvsneslib/source/input.asm +++ b/pvsneslib/source/input.asm @@ -398,23 +398,31 @@ detectMouse: lda #$0 ; change bank address to 0 pha plb +; DB = 0 --: lda REG_HVBJOY - and.b #$01 - bne - + ; Wait until the Joypad Auto-Read has finished. + lda.b #1 + - + bit.w REG_HVBJOY + bne - - rep #$20 - lda REG_JOY1L - ora REG_JOY2L - and.w #$000F - cmp.w #$0001 ; Is the mouse connected on any port? - bne + - sep #$20 - lda #$01 - sta snes_mouse + ; Set `snes_mouse` if JOY1L or JOY2L is a mouse by checking the signature bits. + lda.w REG_JOY1L + and.b #$0f + cmp.b #1 + beq @MouseDetected -+: + lda.w REG_JOY2L + and.b #$0f + cmp.b #1 + bne @Return + + @MouseDetected: + lda.b #$01 + sta.w snes_mouse + +@Return: plb plp rtl From 93712a2b7ef023cf781e8d07399766926f98c514 Mon Sep 17 00:00:00 2001 From: Marcus Rowe Date: Sun, 28 Jul 2024 13:53:07 +1000 Subject: [PATCH 09/22] Do not clear snes_mouse if the mouse has been disconnected If the developer was unaware `snes_mouse` was cleared by the VBlank ISR then the player could lock the game if the mouse was ever disconnected. `snes_mouse` can no-longer be used to detect if the mouse has been disconnected from the console. The developer will have to check the `mouseConnect[]` variable instead. --- pvsneslib/source/vblank.asm | 9 --------- 1 file changed, 9 deletions(-) diff --git a/pvsneslib/source/vblank.asm b/pvsneslib/source/vblank.asm index 9d16487a..56caca90 100644 --- a/pvsneslib/source/vblank.asm +++ b/pvsneslib/source/vblank.asm @@ -405,15 +405,6 @@ _MouseRead: lda REG_JOY1L jsr _MouseData - - ; Disable `snes_mouse` if both mice have been disconnected. - lda mouseConnect - ora mouseConnect+1 - bne + - stz snes_mouse - + - - rep #$10 rts From a32cb988b928564a87575b756c8fdd8de143a743 Mon Sep 17 00:00:00 2001 From: Marcus Rowe Date: Sun, 28 Jul 2024 14:29:15 +1000 Subject: [PATCH 10/22] Add mouse-data-test example --- snes-examples/input/mouse-data-test/Makefile | 33 +++ snes-examples/input/mouse-data-test/data.asm | 9 + snes-examples/input/mouse-data-test/hdr.asm | 100 +++++++ .../input/mouse-data-test/mouse-data-test.c | 247 ++++++++++++++++++ .../input/mouse-data-test/pvsneslibfont.bmp | Bin 0 -> 3190 bytes 5 files changed, 389 insertions(+) create mode 100644 snes-examples/input/mouse-data-test/Makefile create mode 100644 snes-examples/input/mouse-data-test/data.asm create mode 100644 snes-examples/input/mouse-data-test/hdr.asm create mode 100644 snes-examples/input/mouse-data-test/mouse-data-test.c create mode 100644 snes-examples/input/mouse-data-test/pvsneslibfont.bmp diff --git a/snes-examples/input/mouse-data-test/Makefile b/snes-examples/input/mouse-data-test/Makefile new file mode 100644 index 00000000..ad731146 --- /dev/null +++ b/snes-examples/input/mouse-data-test/Makefile @@ -0,0 +1,33 @@ +ifeq ($(strip $(PVSNESLIB_HOME)),) +$(error "Please create an environment variable PVSNESLIB_HOME by following this guide: https://github.com/alekmaul/pvsneslib/wiki/Installation") +endif + + +export ROMNAME := mouse-data-test + +FASTROM := 1 + +# Memory map +# (set to 1 to use HIROM) +# This variable MUST MATCH hdr.asm +HIROM := 0 + + +include ${PVSNESLIB_HOME}/devkitsnes/snes_rules + +.PHONY: bitmaps all + +#--------------------------------------------------------------------------------- + +all: bitmaps $(ROMNAME).sfc + +clean: cleanBuildRes cleanRom cleanGfx + +#--------------------------------------------------------------------------------- + +pvsneslibfont.pic: pvsneslibfont.bmp + @echo convert font with no tile reduction ... $(notdir $@) + $(GFXCONV) -s 8 -o 2 -u 4 -p -t bmp -i $< + +bitmaps : pvsneslibfont.pic + diff --git a/snes-examples/input/mouse-data-test/data.asm b/snes-examples/input/mouse-data-test/data.asm new file mode 100644 index 00000000..277e8408 --- /dev/null +++ b/snes-examples/input/mouse-data-test/data.asm @@ -0,0 +1,9 @@ +;; Resources and Data used by the program + +.include "hdr.asm" + +.section "Resources_Font" SUPERFREE + Font_Tiles: .incbin "pvsneslibfont.pic" + Font_Palette: .incbin "pvsneslibfont.pal" +.ends + diff --git a/snes-examples/input/mouse-data-test/hdr.asm b/snes-examples/input/mouse-data-test/hdr.asm new file mode 100644 index 00000000..ef412c06 --- /dev/null +++ b/snes-examples/input/mouse-data-test/hdr.asm @@ -0,0 +1,100 @@ +;; Memory map and SNES header + + +; `tad-audio.asm` needs to know the memory map. +; `.define` either a HIROM or LOROM constant to to select the memory map. +; +; If you change the mapping, you must also change the `HIROM` variable in the makefile. +.define LOROM + + +.if defined(LOROM) + ; LOROM memory mapping + + ; Memory map MUST MATCH PVSnesLib memory map + .memorymap + slotsize $8000 + defaultslot 0 + + slot 0 $8000 + slot 1 $0000 $2000 ; zeropage and lowram access + slot 2 $2000 $e000 ; bank $7e Work-RAM variables + slot 3 $0000 $10000 + .endme + + .rombanksize $8000 + .rombanks 8 + __HDR_ROM_SIZE__ = 8 + + .base $80 + +.elif defined(HIROM) + ; HIROM memory mapping + + ; Memory map MUST MATCH PVSnesLib memory map + .memorymap + slotsize $10000 + defaultslot 0 + + slot 0 $0000 + slot 1 $0000 $2000 ; zeropage and lowram access + slot 2 $2000 $e000 ; bank $7e Work-RAM variables + slot 3 $0000 $10000 + slot 4 $6000 ; SRAM access + .endme + + .rombanksize $10000 + .rombanks 4 + __HDR_ROM_SIZE__ = 8 + + .base $c0 +.else + .fail "Unknown memory map, please .define HIROM or LOROM in hdr.asm" +.endif + + +.snesheader + id " " + + name "MOUSE DATA TEST " ; Program Title. 21 bytes padded with spaces + ; "123456789012345678901" + + .ifdef FASTROM + fastrom + .else + slowrom + .endif + + .ifdef HIROM + hirom + .else + lorom + .endif + + cartridgetype 0 ; ROM only + romsize __HDR_ROM_SIZE__ ; 2^romsize bytes + sramsize 0 ; No SRAM + country 1 ; US + + licenseecode 0 ; blank + + version 0 ; version 1.00 +.endsnes + + +.snesnativevector + cop EmptyHandler + brk EmptyHandler + abort EmptyHandler + nmi VBlank + irq EmptyHandler +.endnativevector + +.snesemuvector + cop EmptyHandler + abort EmptyHandler + nmi EmptyHandler + reset tcc__start + irqbrk EmptyHandler +.endemuvector + diff --git a/snes-examples/input/mouse-data-test/mouse-data-test.c b/snes-examples/input/mouse-data-test/mouse-data-test.c new file mode 100644 index 00000000..ed39b700 --- /dev/null +++ b/snes-examples/input/mouse-data-test/mouse-data-test.c @@ -0,0 +1,247 @@ +/* + * Mouse data test. + * + * Used to verify the mouse reading code with a Hyperkin mouse. + */ + +#include + +#define JOYPAD_PORT 0 +#define MOUSE_PORT 1 + +#define MAX_XPOS 255 +#define MAX_YPOS 224 + + +#define COL_1_XPOS 18 +#define COL_2_XPOS 26 + +#define LABEL_YPOS 8 + +#define BUTTON_YPOS 8 +#define SPEED_YPOS 10 +#define DELTA_YPOS 12 +#define POS_YPOS 14 +#define LAG_YPOS 18 + +#define CONTOLS_YPOS 22 + + +#define N_LABELS 6 +const char* const LABELS[N_LABELS] = { + "Button:", + "Set speed:", + "Displacement:", + "Position:", + "", + "Lag counter:" +}; + +const char* const BUTTON_STRINGS[4] = { + " ", + "LEFT ", + "RIGHT", + "BOTH ", +}; + +const u8 CURSOR_TILE[32] = { + 0b11000000, 0b00000000, + 0b11100000, 0b01000000, + 0b11110000, 0b01100000, + 0b11111000, 0b01110000, + 0b11111100, 0b01111000, + 0b11111000, 0b01100000, + 0b11100000, 0b00000000, + 0b00000000, 0b00000000, +}; + +const u16 CURSOR_PALETTE[4] = { + 0, 0, 0x17e5, 0x17e5 +}; + +#define VRAM_BG3_MAP_WADDR 0x0000 +#define VRAM_BG3_TILE_WADDR 0x1000 +#define VRAM_OBJ_TILE_WADDR 0x6000 + +void printU8(u16 xPos, u16 yPos, u16 value); +void drawMouseDelta(u16 xPos, u16 value); + +extern char Font_Tiles, Font_Palette; + +u16 cursor_xPos = 128; +u16 cursor_yPos = 112; + +int main(void) +{ + u16 i; + + consoleInit(); + + setMode(BG_MODE1, 0); + bgSetDisable(0); + bgSetDisable(1); + + bgSetGfxPtr(2, VRAM_BG3_TILE_WADDR); + bgSetMapPtr(2, VRAM_BG3_MAP_WADDR, SC_32x32); + + oamInitGfxSet((void*)&CURSOR_TILE, sizeof(CURSOR_TILE), (void*)&CURSOR_PALETTE, sizeof(CURSOR_PALETTE), 0, VRAM_OBJ_TILE_WADDR, OBJ_SIZE8_L16); + + consoleSetTextVramBGAdr(VRAM_BG3_MAP_WADDR); + consoleSetTextVramAdr(VRAM_BG3_TILE_WADDR); + consoleSetTextOffset(0x0000); + consoleInitText(0, 4 * 2, &Font_Tiles, &Font_Palette); + + consoleDrawText(2, 2, "MOUSE DATA TEST:"); + + + consoleDrawText(2, CONTOLS_YPOS, "Controls (Joypad %d):", JOYPAD_PORT + 1); + consoleDrawText(5, CONTOLS_YPOS + 1, "Y/X/A - Set mouse speed"); + consoleDrawText(5, CONTOLS_YPOS + 2, " B - Add lag"); + + + for (i = 0; i < N_LABELS; i++) { + consoleDrawText(2, LABEL_YPOS + i * 2, "%s", LABELS[i]); + } + + + // Set initial speed to medium + mouseSpeedSet[MOUSE_PORT] = 1; + printU8(COL_1_XPOS, SPEED_YPOS, mouseSpeedSet[MOUSE_PORT]); + + + // Setup the cursor sprite (hard coded) + oamMemory[0] = cursor_xPos; + oamMemory[1] = cursor_yPos; + oamMemory[2] = 0; + oamMemory[3] = 0x30; + oamMemory[512] = 0; // Clear hi table + + detectMouse(); + consoleDrawText(2, 4, "READING MOUSE ON PORT %d", MOUSE_PORT + 1); + + setScreenOn(); + + + while (true) { + WaitForVBlank(); + + if (mouseConnect[MOUSE_PORT] == false) { + while (mouseConnect[MOUSE_PORT] == false) { + consoleDrawText(2, 4, "NO MOUSE ON PORT %d ", MOUSE_PORT + 1); + + detectMouse(); + WaitForVBlank(); + } + + consoleDrawText(2, 4, "READING MOUSE ON PORT %d", MOUSE_PORT + 1); + WaitForVBlank(); + } + + // Update cursor position + if (mouse_x[MOUSE_PORT] & 0x80) { + cursor_xPos -= mouse_x[MOUSE_PORT] & 0x7e; + if (cursor_xPos >= 0x8000) { + cursor_xPos = 0; + } + } + else { + cursor_xPos += mouse_x[MOUSE_PORT]; + if (cursor_xPos >= MAX_XPOS + 1) { + cursor_xPos = MAX_XPOS; + } + } + + if (mouse_y[MOUSE_PORT] & 0x80) { + cursor_yPos -= mouse_y[MOUSE_PORT] & 0x7e; + if (cursor_yPos >= 0x8000) { + cursor_yPos = 0; + } + } + else { + cursor_yPos += mouse_y[MOUSE_PORT]; + if (cursor_yPos >= MAX_YPOS + 1) { + cursor_yPos = MAX_YPOS; + } + } + + if (padsDown(JOYPAD_PORT) & (KEY_Y | KEY_X | KEY_A)) { + if (padsDown(JOYPAD_PORT) & KEY_Y) { + mouseSpeedSet[MOUSE_PORT] = 0; + } + if (padsDown(JOYPAD_PORT) & KEY_X) { + mouseSpeedSet[MOUSE_PORT] = 1; + } + if (padsDown(JOYPAD_PORT) & KEY_A) { + mouseSpeedSet[MOUSE_PORT] = 2; + } + printU8(COL_1_XPOS, SPEED_YPOS, mouseSpeedSet[MOUSE_PORT]); + mouseSpeedChange(MOUSE_PORT); + } + + if (padsCurrent(JOYPAD_PORT) & KEY_B) { + // Add lag + for(i = 0; i < 1500; i++) {} + } + + // Update mouse cursor sprite + oamMemory[0] = cursor_xPos; + oamMemory[1] = cursor_yPos; + + consoleDrawText(COL_1_XPOS, BUTTON_YPOS, BUTTON_STRINGS[mousePressed[MOUSE_PORT] & 3]); + consoleDrawText(COL_2_XPOS, BUTTON_YPOS, BUTTON_STRINGS[mouseButton[MOUSE_PORT] & 3]); + + drawMouseDelta(COL_1_XPOS, mouse_x[MOUSE_PORT]); + drawMouseDelta(COL_2_XPOS, mouse_y[MOUSE_PORT]); + + printU8(COL_1_XPOS, POS_YPOS, cursor_xPos); + printU8(COL_2_XPOS, POS_YPOS, cursor_yPos); + + consoleDrawText(COL_1_XPOS, LAG_YPOS, "%d", lag_frame_counter); + } + return 0; +} + +// Hack to quickly print a u8 without lag +const char* const U8_STR_TABLE[256] = { + " 0", " 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" +}; + + +void drawMouseDelta(u16 xPos, u16 value) { + if (value & 0x80) { + consoleDrawText(xPos - 1, DELTA_YPOS, "-"); + } + else { + consoleDrawText(xPos - 1, DELTA_YPOS, "+"); + } + + consoleDrawText(xPos, DELTA_YPOS, U8_STR_TABLE[value & 0x7f]); +} + +void printU8(u16 xPos, u16 yPos, u16 value) { + consoleDrawText(xPos, yPos, U8_STR_TABLE[value & 0xff]); +} + diff --git a/snes-examples/input/mouse-data-test/pvsneslibfont.bmp b/snes-examples/input/mouse-data-test/pvsneslibfont.bmp new file mode 100644 index 0000000000000000000000000000000000000000..71bc2193705ac527d98aa6fc83cc62ef408bcbf1 GIT binary patch literal 3190 zcmbu9L6+1o5JS@s7A#nFZoxU&bDg>Vp#N1)(o6;xxI3|3mP#te$;CUPU-Dd`EC0kE&t1*^u{{qCYcE?gmJ_$?KlQ z$_9JrS3xf;ullQg&>2%JIna3I2i82qG8;RJ=Qyh3WYo4t>W%7N1IMdCY*H1Tbs%x; zfc?@}bl3}i0PGn6UKbf4OxJoqw%+ENe8W94XS}h@;~Brq`P;h%ctNx-(p8brr8Upe zZV!ZgTsfO#)%1!jzrLbT4*TyYtI4CJNoOCTpJ2ZT!<-8Vcd9>akDa{>V*5B-$_V7)#wPysG{7;_O`738K0+*M0o_{ky%);>PBYpk;fb+^eJUw64 zf(D+o#lv=6@*mG-lBa{h1!1|AyYyKK0L2rrko4sP2O~GPA`+wiTc(n7)*h7AOeEHq z(bb`Q!RTOX zdbzmi;YT+<s%Smm)rWWeSz*^_KmzXZu!@8y3D{tx_+^T5$$)|pJ l^X9k41Sz+TqSL_8aWm9&vEqbp+nMNQIg8|?%Q0uaegh|&OWObd literal 0 HcmV?d00001 From eb561a4524300b215839be5b8b9b1e0603f660a3 Mon Sep 17 00:00:00 2001 From: Marcus Rowe Date: Sun, 28 Jul 2024 19:51:27 +1000 Subject: [PATCH 11/22] Fix mouseSpeedChange() unable to set medium sensitivity Fixes a typo in the `mouseSpeedSet` mask. --- pvsneslib/source/input.asm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pvsneslib/source/input.asm b/pvsneslib/source/input.asm index 78f06784..97cd93a4 100644 --- a/pvsneslib/source/input.asm +++ b/pvsneslib/source/input.asm @@ -327,7 +327,7 @@ mouseSpeedChange: .INDEX 8 @speed_change: lda mouseSpeedSet,x - and #2 + and #3 tay ; Limit the number of cycle-sensitivity commands to send to the mouse. From 143add7b580d20b12df2ad3c06b50d44895d368e Mon Sep 17 00:00:00 2001 From: Marcus Rowe Date: Sat, 3 Aug 2024 13:18:39 +1000 Subject: [PATCH 12/22] Fix input.h doxygen variable documentation --- pvsneslib/include/snes/input.h | 53 +++++++++++++++++----------------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/pvsneslib/include/snes/input.h b/pvsneslib/include/snes/input.h index 0c897b93..d3900408 100644 --- a/pvsneslib/include/snes/input.h +++ b/pvsneslib/include/snes/input.h @@ -80,32 +80,33 @@ extern u16 pad_keys[5]; //!< current pad value extern u16 pad_keysold[5]; //!< previous pad value extern u16 pad_keysdown[5]; //!< newly pressed down pad keys -extern u8 snes_mplay5; /*! \brief 1 if MultiPlay5 is connected */ -extern u8 snes_mouse; /*! \brief 1 if Mouse is going to be used */ -extern u8 snes_sscope; /*! \brief 1 if SuperScope is connected */ - -extern u8 mouseConnect[2]; /*! \brief 1 if Mouse present */ -extern u8 mouseButton[2]; /*! \brief 1 if button is pressed, stays for a bit and then it gets released (Click mode). */ -extern u8 mousePressed[2]; /*! \brief 1 if button is pressed, stays until is unpressed (Turbo mode). */ -extern u8 mouse_x[2], mouse_y[2]; /*! \brief Mouse acceleration. daaaaaaa, d = direction (0: up/left, 1: down/right), a = acceleration. */ -extern u8 mouseSpeedSet[2]; /*! \brief Mouse speed setting. 0: slow, 1: normal, 2: fast */ - -#define mouse_L 0x01 /*! \brief SNES Mouse Left button mask.*/ -#define mouse_R 0x02 /*! \brief SNES Mouse Right button mask.*/ - -extern u16 scope_holddelay; /*! \brief Hold delay. */ -extern u16 scope_repdelay; /*! \brief Repeat rate. */ -extern u16 scope_shothraw; /*! \brief Horizontal shot position, not adjusted. */ -extern u16 scope_shotvraw; /*! \brief Vertical shot position, not adjusted. */ -extern u16 scope_shoth; /*! \brief Horizontal shot position, adjusted for aim. */ -extern u16 scope_shotv; /*! \brief Vertical shot position, adjusted for aim. */ -extern u16 scope_centerh; /*! \brief 0x0000 is the center of the screen, positive values go to bottom right. */ -extern u16 scope_centerv; /*! \brief 0x0000 is the center of the screen, positive values go to bottom right. */ -extern u16 scope_down; /*! \brief flags that are currently true.*/ -extern u16 scope_now; /*! \brief flags that have become true this frame.*/ -extern u16 scope_held; /*! \brief flagsthat have been true for a certain length of time.*/ -extern u16 scope_last; /*! \brief flags that were true on the previous frame.*/ -extern u16 scope_sinceshot; /*! \brief Number of frames elapsed since last shot was fired.*/ +extern u8 snes_mplay5; /*!< \brief 1 if MultiPlay5 is connected */ +extern u8 snes_mouse; /*!< \brief 1 if Mouse is going to be used */ +extern u8 snes_sscope; /*!< \brief 1 if SuperScope is connected */ + +extern u8 mouseConnect[2]; /*!< \brief 1 if Mouse present */ +extern u8 mouseButton[2]; /*!< \brief 1 if button is pressed, stays for a bit and then it gets released (Click mode). */ +extern u8 mousePressed[2]; /*!< \brief 1 if button is pressed, stays until is unpressed (Turbo mode). */ +extern u8 mouse_x[2]; /*!< \brief Mouse X acceleration. daaaaaaa, d = direction (0: up/left, 1: down/right), a = acceleration. */ +extern u8 mouse_y[2]; /*!< \brief Mouse Y acceleration. daaaaaaa, d = direction (0: up/left, 1: down/right), a = acceleration. */ +extern u8 mouseSpeedSet[2]; /*!< \brief Mouse speed setting. 0: slow, 1: normal, 2: fast */ + +#define mouse_L 0x01 /*!< \brief SNES Mouse Left button mask.*/ +#define mouse_R 0x02 /*!< \brief SNES Mouse Right button mask.*/ + +extern u16 scope_holddelay; /*!< \brief Hold delay. */ +extern u16 scope_repdelay; /*!< \brief Repeat rate. */ +extern u16 scope_shothraw; /*!< \brief Horizontal shot position, not adjusted. */ +extern u16 scope_shotvraw; /*!< \brief Vertical shot position, not adjusted. */ +extern u16 scope_shoth; /*!< \brief Horizontal shot position, adjusted for aim. */ +extern u16 scope_shotv; /*!< \brief Vertical shot position, adjusted for aim. */ +extern u16 scope_centerh; /*!< \brief 0x0000 is the center of the screen, positive values go to bottom right. */ +extern u16 scope_centerv; /*!< \brief 0x0000 is the center of the screen, positive values go to bottom right. */ +extern u16 scope_down; /*!< \brief flags that are currently true.*/ +extern u16 scope_now; /*!< \brief flags that have become true this frame.*/ +extern u16 scope_held; /*!< \brief flagsthat have been true for a certain length of time.*/ +extern u16 scope_last; /*!< \brief flags that were true on the previous frame.*/ +extern u16 scope_sinceshot; /*!< \brief Number of frames elapsed since last shot was fired.*/ /*! \def REG_JOYxLH From 8c5b0f9d52c2a14373b76b7a05bda67b8b812d6a Mon Sep 17 00:00:00 2001 From: Marcus Rowe Date: Sat, 3 Aug 2024 13:56:26 +1000 Subject: [PATCH 13/22] Delay mouse sensitivity changes to the VBlank ISR (changing the Mouse API) The old `mouseSpeedChange(u8 port)` function has a timing conflict with the auto-joypad-read. The automatic joypad read must not start while the CPU is in the middle of the `mouseSpeedChange()` function. Delaying all mouse sensitivity changes to the VBlank ISR will remove this timing conflict and ensure the mouse sensitivity is cycled at the correct time. This commit removes the old `mouseSpeedSet` variable and the `mouseSpeedChange()` function, replacing them with a `mouseRequestChangeSensitivity` variable that will signal to `_MouseData` that the MainLoop wants to either: * Cycle the mouse sensitivity once. * Cycle the mouse sensitivity twice (decrementing the sensitivity). * Setting the mouse sensitivity to a specific value. This commit also adds a `mouseSensitivity` variable that serves three purposes: 1. Allows the developer to read the reported mouse sensitivity. 2. Allows the developer to set the initial mouse sensitivity. 3. Restore the mouse sensitivity when the mouse is disconnected, then reconnected. Three helper functions have been added to simplify the `mouseRequestChangeSensitivity` writes: * void mouseCycleSensitivity(u16 port) * void mouseCycleSensitivityTwice(u16 port) * void mouseSetSensitivity(u16 port, u16 sensitivity) The two mouse examples have been modified to use the new mouse sensitivity functions and to display the reported mouse sensitivity. --- pvsneslib/include/snes/input.h | 70 +++++- pvsneslib/source/input.asm | 199 ++++++++---------- pvsneslib/source/vblank.asm | 128 ++++++++++- .../input/mouse-data-test/mouse-data-test.c | 32 +-- snes-examples/input/mouse/mouse.c | 177 ++++++++-------- 5 files changed, 370 insertions(+), 236 deletions(-) diff --git a/pvsneslib/include/snes/input.h b/pvsneslib/include/snes/input.h index d3900408..e042d1ab 100644 --- a/pvsneslib/include/snes/input.h +++ b/pvsneslib/include/snes/input.h @@ -89,7 +89,32 @@ extern u8 mouseButton[2]; /*!< \brief 1 if button is pressed, stays for extern u8 mousePressed[2]; /*!< \brief 1 if button is pressed, stays until is unpressed (Turbo mode). */ extern u8 mouse_x[2]; /*!< \brief Mouse X acceleration. daaaaaaa, d = direction (0: up/left, 1: down/right), a = acceleration. */ extern u8 mouse_y[2]; /*!< \brief Mouse Y acceleration. daaaaaaa, d = direction (0: up/left, 1: down/right), a = acceleration. */ -extern u8 mouseSpeedSet[2]; /*!< \brief Mouse speed setting. 0: slow, 1: normal, 2: fast */ + +/*! + * \brief Mouse sensitivity + * + * * When a mouse is connected to the port: sensitivity bits read from the mouse. + * * When no mouse is connected: The sensitivity to set the mouse to when the mouse is connected to the console. + * + * CAUTION: The Hyperkin clone mouse ignores sensitivity changes and always reports a sensitivity of 0. + */ +extern u8 mouseSensitivity[2]; + +/*! + * \brief Request a change mouse sensitivity. + * + * To prevent auto-joypad read corruption the change sensitivity commands are delayed until the + * next non-lag VBlank ISR (after the mouse data has been read). + * + * Values: + * * `0x00`: No changes to mouse sensitivity. + * * `0x01`: Cycle the mouse sensitivity once. + * * `0x02-0x7f`: Cycle the mouse sensitivity twice. + * * `0x80-0xff`: Set the sensitivity to `value & 3`. + * + * CAUTION: The Hyperkin clone mouse ignores sensitivity changes and always reports a sensitivity of 0. + */ +extern u8 mouseRequestChangeSensitivity[2]; #define mouse_L 0x01 /*!< \brief SNES Mouse Left button mask.*/ #define mouse_R 0x02 /*!< \brief SNES Mouse Right button mask.*/ @@ -193,15 +218,46 @@ void detectMPlay5(void); */ void detectMouse(void); -/*! \fn mouseSpeedChange(u8 port) - \brief Set mouse hardware speed (populate mouseSpeed[] first). - \param port Specify wich port to use (0-1) -*/ -void mouseSpeedChange(u8 port); - /*! \fn detectSuperScope(void) \brief Detects if SuperScope is connected on Port 1 (second controller port on console) and populate snes_sscope (0 or 1 for connected) */ void detectSuperScope(void); +/*! + * \brief Queue a cycle mouse sensitivity command for the next VBlank. + * + * \param port the port the mouse is connected to (0 or 1). + * + * CAUTION: + * * The changes to @ref mouseSensitivity are delayed one frame. + * * This function will override any pending @ref mouseRequestChangeSensitivity commands. + * * This function has no effect on the Hyperkin clone mouse. + */ +void mouseCycleSensitivity(u16 port); + +/*! + * \brief Queue a cycle mouse sensitivity twice (decrementing the sensitivity) command for the next VBlank. + * + * \param port the port the mouse is connected to (0 or 1). + * + * CAUTION: + * * The changes to @ref mouseSensitivity are delayed one frame. + * * This function will override any pending @ref mouseRequestChangeSensitivity commands. + * * This function has no effect on the Hyperkin clone mouse. + */ +void mouseCycleSensitivityTwice(u16 port); + +/*! + * \brief Queue a set mouse sensitivity command (to be executed on the next VBlank). + * + * \param port the port the mouse is connected to (0 or 1). + * \param sensitivity the sensitivity to set the mouse to (0 - 2). + * + * CAUTION: + * * The changes to @ref mouseSensitivity are delayed one frame. + * * This function will override any pending @ref mouseRequestChangeSensitivity commands. + * * This function has no effect on the Hyperkin clone mouse. + */ +void mouseSetSensitivity(u16 port, u16 sensitivity); + #endif // SNES_PADS_INCLUDE diff --git a/pvsneslib/source/input.asm b/pvsneslib/source/input.asm index 97cd93a4..8776c73d 100644 --- a/pvsneslib/source/input.asm +++ b/pvsneslib/source/input.asm @@ -105,8 +105,6 @@ snes_mouse db ; Flag to enable mouse reading in VBlank ISR mouseConnect dsb 2 ; Mouse connection status -mouseSpeedSet dsb 2 ; Mouse speed setting - mouseButton dsb 2 ; Mouse buttons pressed this frame mousePressed dsb 2 ; Mouse buttons held/pressed mousePreviousPressed dsb 2 ; Mouse buttons held/pressed in the previous frame @@ -114,6 +112,14 @@ mousePreviousPressed dsb 2 ; Mouse buttons held/pressed in the previous frame mouse_y dsb 2 ; Mouse Y displacement mouse_x dsb 2 ; Mouse X displacement +mouseSensitivity dsb 2 ; Mouse sensitivity & sensitivity to set when mouse is connected + +; Request a sensitivity change in VBlank ISR +; $01 - cycle sensitivity once +; $02..=$7f - cycle sensitivity twice +; $80..=$ff - set sensitivity to `mouseRequestChangeSensitivity & 3` +mouseRequestChangeSensitivity dsb 2 + .ENDS @@ -277,114 +283,6 @@ detectSuperScope: .ENDS -; Must be in bank 0, used by _MouseRead in the VBlank ISR. -.SECTION ".mousespeedchange_text" SEMIFREE BANK 0 - -;--------------------------------------------------------------------------------- -; void mouseSpeedChange(u8 port) -mouseSpeedChange: - php - phb - rep #$30 ; Must push/pop 16 bit index (switching to 8 bit Index clobbers high byte) - phx - phy - - sep #$30 -.ACCU 8 -.INDEX 8 - - lda #$00 - pha - plb -// DB = 0 - - lda 10,s ; port argument - cmp #2 - bcs + - tax - - ; Call `speed_change` if the mouse if connected. - lda mouseConnect,x - beq + - jsr @speed_change - + - - rep #$30 - ply - plx - plb - plp - rtl - - -; Called by _MouseRead in the Vblank ISR -; TIMING: Not auto-joypad read -; REQUIRES: Mouse connected on port X -; X = 0 or 1 -; KEEP: X -; DB = 0 -.ACCU 8 -.INDEX 8 -@speed_change: - lda mouseSpeedSet,x - and #3 - tay - - ; Limit the number of cycle-sensitivity commands to send to the mouse. - ; Done for 2 reasons: - ; 1. Prevents an infinite loop if the mouse has been disconnected. - ; 2. The Hyperkin mouse will always report a mouse sensitivity of 0. - lda #4 - sta.b tcc__r0h - - @CycleLoop: - ; X = port - ; Y = requested sensitivity - ; tcc__r0h = decrementing loop counter - - ; Send a cycle-sensitivity command to the mouse - lda #$01 - sta REG_JOYA - lda REG_JOYA,x - stz REG_JOYA - - - ; Read sensitivity bits from mouse - ; - ; No Hyperkin mouse read delay is required as the Hyperkin mouse does not support - ; cycle-sensitivity commands. - - ; Skip the first 10 bits - ; Using A for loop counter so Y is unchanged - lda #10 - - - bit REG_JOYA,x - dec a - bne - - - ; Read the 2 sensitivity bits - stz.b tcc__r0 - - lda REG_JOYA,x - lsr - rol.b tcc__r0 - - lda REG_JOYA,x - lsr - rol.b tcc__r0 - - - ; Return if read sensitivity == Y - cpy.b tcc__r0 - beq @Return - - dec.b tcc__r0h - bne @CycleLoop - -@Return: - rts -.ENDS - .SECTION ".detectmouse_text" SUPERFREE @@ -428,3 +326,84 @@ detectMouse: rtl .ENDS + + +.SECTION ".mouseCycleSensitivity_text" SUPERFREE + +; void mouseCycleSensitivity(u16 port); +mouseCycleSensitivity: + php + rep #$30 + phx + + lda 7,s ; port argument + cmp.w #2 + bcs + + tax + sep #$20 + .accu 8 + + lda.b #1 + sta.l mouseRequestChangeSensitivity,x + + +// A size unknown + + plx + plp + rtl +.ENDS + + +.SECTION ".mouseCycleSensitivityTwice_text" SUPERFREE + +; void mouseCycleSensitivityTwice(u16 port); +mouseCycleSensitivityTwice: + php + rep #$30 + phx + + lda 7,s ; port argument + cmp.w #2 + bcs + + tax + sep #$20 + .accu 8 + + lda.b #2 + sta.l mouseRequestChangeSensitivity,x + + +// A size unknown + + plx + plp + rtl +.ENDS + + +.SECTION ".mouseSetSensitivity_text" SUPERFREE + +; void mouseSetSensitivity(u16 port, u8 sensitivity); +mouseSetSensitivity: + php + rep #$30 + phx + + lda 7,s ; port argument + cmp.w #2 + bcs + + tax + sep #$20 + .accu 8 + + lda 9,s ; sensitivity argument + ora.b #$80 + sta.l mouseRequestChangeSensitivity,x + + +// A size unknown + + plx + plp + rtl +.ENDS + + diff --git a/pvsneslib/source/vblank.asm b/pvsneslib/source/vblank.asm index 56caca90..30057cba 100644 --- a/pvsneslib/source/vblank.asm +++ b/pvsneslib/source/vblank.asm @@ -429,7 +429,7 @@ _MouseData: ; Test if the mouse was connected on this frame lda mouseConnect,x - beq @SetMouseSensitvity + beq @MouseConnectedThisFrame ; Update mouse button/pressed variables @@ -437,10 +437,17 @@ _MouseData: sta mousePreviousPressed,x tya - asl a - rol a - rol a + lsr a + lsr a + lsr a + lsr a + tay and #3 + sta mouseSensitivity,x + + tya + lsr a + lsr a sta mousePressed,x eor mousePreviousPressed,x @@ -464,7 +471,7 @@ _MouseData: ; Read 16 bits ldy #16 - @_m30: + - lda.w REG_JOYA,x lsr a @@ -475,7 +482,11 @@ _MouseData: nop ; 1 extra nop for safety (to match the SnesDev wiki) .endif dey - bne @_m30 + bne - + + + lda.w mouseRequestChangeSensitivity,x + bne @ChangeSensitivityRequest rts @@ -486,22 +497,30 @@ _MouseData: ; To fix this bug at a cycle-sensitivity command must be sent to the mouse when it is first ; connected to the console, even if the sensitivity bits are what the user wants. ; -; Calling `speed_change` will cycle the sensitivity at least once and try to cycle the sensitivity -; to match `mouseSpeedSet`. -@SetMouseSensitvity: - jsr mouseSpeedChange@speed_change +@MouseConnectedThisFrame: + ; Using `mouseSensitivity` so the sensitivity can be restored if the mouse is + ; disconnected then reconnected to the console. + lda mouseSensitivity,x + and #3 + jsr @SetMouseSensitvity ; Set mouse connected flag lda #1 sta mouseConnect,x + ; Clear stale or uninitialised request change sensitivity command. + stz mouseRequestChangeSensitivity,x + ; Clear mouse variables, they might not be valid. bra @ClearMouseState @NoMouseConnected: stz mouseConnect,x + @ClearMouseState: + ; Not clearing mouseSensitivity. + ; It is used to restore the sensitivity when the mouse is reconnected stz mouseButton,x stz mousePressed,x stz mousePreviousPressed,x @@ -510,6 +529,95 @@ _MouseData: rts +; A = mouseRequestChangeSensitivity +; negative flag = MSB of `mouseRequestChangeSensitivity` +@ChangeSensitivityRequest: + stz mouseRequestChangeSensitivity,x + + bmi @RequestSpecificSensitivity + + ; Send one or two cycle-sensitivity commands to the mouse + ldy #$01 + sty REG_JOYA + dec a + beq + + ldy REG_JOYA,x + + + ldy REG_JOYA,x + stz REG_JOYA + +@Return: + rts + + +; A = mouseRequestChangeSensitivity +@RequestSpecificSensitivity: + and.b #3 + cmp mouseSensitivity,x + beq @Return + + +; Repeatedly cycle through the mouse sensitivity until reported sensitivity matches the requested sensitivity. +; CAUTION: This code will always cycle the sensitivity at least once (required when mouse is connected to the console) +; A = requested sensitivity (0 - 2) +@SetMouseSensitvity: + tay + + ; Limit the number of cycle-sensitivity commands to send to the mouse. + ; Done for 2 reasons: + ; 1. Prevents an infinite loop if the mouse has been disconnected. + ; 2. The Hyperkin mouse will always report a mouse sensitivity of 0. + lda #4 + sta.b tcc__r0h + + @CycleLoop: + ; X = port + ; Y = requested sensitivity + ; tcc__r0h = decrementing loop counter + + ; Send a cycle-sensitivity command to the mouse + lda #$01 + sta REG_JOYA + lda REG_JOYA,x + stz REG_JOYA + + + ; Read sensitivity bits from mouse + ; + ; No Hyperkin mouse read delay is required as the Hyperkin mouse does not support + ; cycle-sensitivity commands. + + ; Skip the first 10 bits + ; Using A for loop counter so Y is unchanged + lda #10 + - + bit REG_JOYA,x + dec a + bne - + + ; Read the 2 sensitivity bits + stz.b tcc__r0 + + lda REG_JOYA,x + lsr + rol.b tcc__r0 + + lda REG_JOYA,x + lsr + rol.b tcc__r0 + + + ; Return if read sensitivity == Y + cpy.b tcc__r0 + beq @EndCycleLoop + + dec.b tcc__r0h + bne @CycleLoop + +@EndCycleLoop: + rts + + ;--------------------------------------------------------------------------------- .accu 16 diff --git a/snes-examples/input/mouse-data-test/mouse-data-test.c b/snes-examples/input/mouse-data-test/mouse-data-test.c index ed39b700..738ecfca 100644 --- a/snes-examples/input/mouse-data-test/mouse-data-test.c +++ b/snes-examples/input/mouse-data-test/mouse-data-test.c @@ -30,7 +30,7 @@ #define N_LABELS 6 const char* const LABELS[N_LABELS] = { "Button:", - "Set speed:", + "Sensitivity:", "Displacement:", "Position:", "", @@ -96,19 +96,14 @@ int main(void) consoleDrawText(2, CONTOLS_YPOS, "Controls (Joypad %d):", JOYPAD_PORT + 1); consoleDrawText(5, CONTOLS_YPOS + 1, "Y/X/A - Set mouse speed"); - consoleDrawText(5, CONTOLS_YPOS + 2, " B - Add lag"); + consoleDrawText(5, CONTOLS_YPOS + 2, " L/R - Cycle mouse speed"); + consoleDrawText(5, CONTOLS_YPOS + 3, " B - Add lag"); for (i = 0; i < N_LABELS; i++) { consoleDrawText(2, LABEL_YPOS + i * 2, "%s", LABELS[i]); } - - // Set initial speed to medium - mouseSpeedSet[MOUSE_PORT] = 1; - printU8(COL_1_XPOS, SPEED_YPOS, mouseSpeedSet[MOUSE_PORT]); - - // Setup the cursor sprite (hard coded) oamMemory[0] = cursor_xPos; oamMemory[1] = cursor_yPos; @@ -116,6 +111,9 @@ int main(void) oamMemory[3] = 0x30; oamMemory[512] = 0; // Clear hi table + // Set initial sensitivity to medium + mouseSensitivity[MOUSE_PORT] = 1; + detectMouse(); consoleDrawText(2, 4, "READING MOUSE ON PORT %d", MOUSE_PORT + 1); @@ -164,18 +162,22 @@ int main(void) } } - if (padsDown(JOYPAD_PORT) & (KEY_Y | KEY_X | KEY_A)) { + if (padsDown(JOYPAD_PORT) & (KEY_Y | KEY_X | KEY_A | KEY_L | KEY_R)) { if (padsDown(JOYPAD_PORT) & KEY_Y) { - mouseSpeedSet[MOUSE_PORT] = 0; + mouseSetSensitivity(MOUSE_PORT, 0); } if (padsDown(JOYPAD_PORT) & KEY_X) { - mouseSpeedSet[MOUSE_PORT] = 1; + mouseSetSensitivity(MOUSE_PORT, 1); } if (padsDown(JOYPAD_PORT) & KEY_A) { - mouseSpeedSet[MOUSE_PORT] = 2; + mouseSetSensitivity(MOUSE_PORT, 2); + } + if (padsDown(JOYPAD_PORT) & KEY_R) { + mouseCycleSensitivity(MOUSE_PORT); + } + if (padsDown(JOYPAD_PORT) & KEY_L) { + mouseCycleSensitivityTwice(MOUSE_PORT); } - printU8(COL_1_XPOS, SPEED_YPOS, mouseSpeedSet[MOUSE_PORT]); - mouseSpeedChange(MOUSE_PORT); } if (padsCurrent(JOYPAD_PORT) & KEY_B) { @@ -190,6 +192,8 @@ int main(void) consoleDrawText(COL_1_XPOS, BUTTON_YPOS, BUTTON_STRINGS[mousePressed[MOUSE_PORT] & 3]); consoleDrawText(COL_2_XPOS, BUTTON_YPOS, BUTTON_STRINGS[mouseButton[MOUSE_PORT] & 3]); + printU8(COL_1_XPOS, SPEED_YPOS, mouseSensitivity[MOUSE_PORT]); + drawMouseDelta(COL_1_XPOS, mouse_x[MOUSE_PORT]); drawMouseDelta(COL_2_XPOS, mouse_y[MOUSE_PORT]); diff --git a/snes-examples/input/mouse/mouse.c b/snes-examples/input/mouse/mouse.c index 01b0b69b..79ba559c 100644 --- a/snes-examples/input/mouse/mouse.c +++ b/snes-examples/input/mouse/mouse.c @@ -35,7 +35,6 @@ bool printed[2] = {false}; bool mouseDown_L[2] = {false}; bool mouseDown_R[2] = {false}; bool mouseDown_LR[2] = {false}; -bool speedset[2] = {true}; //--------------------------------------------------------------------------------- int main(void) @@ -52,9 +51,12 @@ int main(void) // Draw a wonderful text :P consoleDrawText(11, 1, "MOUSE TEST"); - // we set mouse speed, or it will just output a random speed. We can change it later manually - mouseSpeedSet[0] = slow; - mouseSpeedSet[1] = slow; + // Set the sensitivity to use when the mouse is connected to the console, + // or it will just output a random speed. + // + // This can be changed later with mouseSetSensitivity(). + mouseSensitivity[0] = slow; + mouseSensitivity[1] = slow; detectMouse(); // Let's check if a mouse is plugged in any port on boot, be sure nmi interrupt was called at least once (in this case, previous oamInitGfxSet() function was enough) WaitForVBlank(); // Let's make sure we read mouse for the first time after detectMouse() @@ -290,130 +292,115 @@ int main(void) } } - WaitForVBlank(); // mouseButton works as a one frame value, so it gets released shortly after pressing the button. Good for clicking stuff that need to be called once, like buttons. - if (mouseConnect[0]) + // mouseButton is 0 if there is no mouse connected + if (mouseButton[0] & mouse_L) { - if (mouseButton[0] & mouse_L) + // Let's choose speed setting + if ((p1_mouse_y > 0x5E) && (p1_mouse_y < 0x6C)) { - // Let's choose speed setting - if ((p1_mouse_y > 0x5E) && (p1_mouse_y < 0x6C)) + if ((p1_mouse_x > 0x44) && (p1_mouse_x < 0x64)) + { + mouseSetSensitivity(0, slow); // Queue a set sensitivity command + } + if ((p1_mouse_x > 0x6C) && (p1_mouse_x < 0x94)) + { + mouseSetSensitivity(0, normal); // Queue a set sensitivity command + } + if ((p1_mouse_x > 0x9C) && (p1_mouse_x < 0xBC)) { - if ((p1_mouse_x > 0x44) && (p1_mouse_x < 0x64)) - { - mouseSpeedSet[0] = slow; - speedset[0] = true; - mouseSpeedChange(0); // Let's tell the mouse we want to change speed. mouseSpeedSet[] has to be populated first. - } - if ((p1_mouse_x > 0x6C) && (p1_mouse_x < 0x94)) - { - mouseSpeedSet[0] = normal; - speedset[0] = true; - mouseSpeedChange(0); // Let's tell the mouse we want to change speed. mouseSpeedSet[] has to be populated first. - } - if ((p1_mouse_x > 0x9C) && (p1_mouse_x < 0xBC)) - { - mouseSpeedSet[0] = fast; - speedset[0] = true; - mouseSpeedChange(0); // Let's tell the mouse we want to change speed. mouseSpeedSet[] has to be populated first. - } + mouseSetSensitivity(0, fast); // Queue a set sensitivity command } } + } - if (speedset[0]) + if (mouseButton[1] & mouse_L) + { + // Let's choose speed setting + if ((p2_mouse_y > 0xBE) && (p2_mouse_y < 0xCC)) { - dmaCopyVram(&buttonsmap + 0x40, 0x6188, 0x20); // released buttons - dmaCopyVram(&buttonsmap + 0x80, 0x61A8, 0x20); // released buttons - - switch (mouseSpeedSet[0]) + if ((p2_mouse_x > 0x44) && (p2_mouse_x < 0x64)) + { + mouseSetSensitivity(1, slow); // Queue a set sensitivity command + } + if ((p2_mouse_x > 0x6C) && (p2_mouse_x < 0x94)) + { + mouseSetSensitivity(1, normal); // Queue a set sensitivity command + } + if ((p2_mouse_x > 0x9C) && (p2_mouse_x < 0xBC)) { - case slow: - dmaCopyVram(&buttonsmap + 0x60, 0x6188, 0x0A); // SLOW button pressed - dmaCopyVram(&buttonsmap + 0xA0, 0x61A8, 0x0A); // SLOW button pressed - break; - case normal: - dmaCopyVram(&buttonsmap + 0x6A, 0x618D, 0x0C); // NORMAL button pressed - dmaCopyVram(&buttonsmap + 0xAA, 0x61AD, 0x0C); // NORMAL button pressed - break; - case fast: - dmaCopyVram(&buttonsmap + 0x76, 0x6193, 0x0A); // FAST button pressed - dmaCopyVram(&buttonsmap + 0xB6, 0x61B3, 0x0A); // FAST button pressed - break; + mouseSetSensitivity(1, fast); // Queue a set sensitivity command } - speedset[0] = false; + } + } + + WaitForVBlank(); + + // START VBLANK CODE + + if (mouseConnect[0]) + { + dmaCopyVram(&buttonsmap + 0x40, 0x6188, 0x20); // released buttons + dmaCopyVram(&buttonsmap + 0x80, 0x61A8, 0x20); // released buttons + + // Show reported sensitivity + switch (mouseSensitivity[0]) + { + case slow: + dmaCopyVram(&buttonsmap + 0x60, 0x6188, 0x0A); // SLOW button pressed + dmaCopyVram(&buttonsmap + 0xA0, 0x61A8, 0x0A); // SLOW button pressed + break; + case normal: + dmaCopyVram(&buttonsmap + 0x6A, 0x618D, 0x0C); // NORMAL button pressed + dmaCopyVram(&buttonsmap + 0xAA, 0x61AD, 0x0C); // NORMAL button pressed + break; + case fast: + dmaCopyVram(&buttonsmap + 0x76, 0x6193, 0x0A); // FAST button pressed + dmaCopyVram(&buttonsmap + 0xB6, 0x61B3, 0x0A); // FAST button pressed + break; } if (mousePressed[0] == false) dmaFillVram(&buttonsmap, 0x6940, 0x40); // wipe text } - else if (speedset[0] == false) + else { dmaFillVram(&buttonsmap + 0x40, 0x6188, 0x20); // remove buttons dmaFillVram(&buttonsmap + 0x80, 0x61A8, 0x20); // remove buttons - speedset[0] = true; } if (mouseConnect[1]) { - if (mouseButton[1] & mouse_L) - { - // Let's choose speed setting - if ((p2_mouse_y > 0xBE) && (p2_mouse_y < 0xCC)) - { - if ((p2_mouse_x > 0x44) && (p2_mouse_x < 0x64)) - { - mouseSpeedSet[1] = slow; - speedset[1] = true; - mouseSpeedChange(1); // Let's tell the mouse we want to change speed. mouseSpeedSet[] has to be populated first. - } - if ((p2_mouse_x > 0x6C) && (p2_mouse_x < 0x94)) - { - mouseSpeedSet[1] = normal; - speedset[1] = true; - mouseSpeedChange(1); // Let's tell the mouse we want to change speed. mouseSpeedSet[] has to be populated first. - } - if ((p2_mouse_x > 0x9C) && (p2_mouse_x < 0xBC)) - { - mouseSpeedSet[1] = fast; - speedset[1] = true; - mouseSpeedChange(1); // Let's tell the mouse we want to change speed. mouseSpeedSet[] has to be populated first. - } - } - } + dmaCopyVram(&buttonsmap + 0x40, 0x6308, 0x20); // released buttons + dmaCopyVram(&buttonsmap + 0x80, 0x6328, 0x20); // released buttons - if (speedset[1]) + switch (mouseSensitivity[1]) { - dmaCopyVram(&buttonsmap + 0x40, 0x6308, 0x20); // released buttons - dmaCopyVram(&buttonsmap + 0x80, 0x6328, 0x20); // released buttons - - switch (mouseSpeedSet[1]) - { - case slow: - dmaCopyVram(&buttonsmap + 0x60, 0x6308, 0x0A); // SLOW button pressed - dmaCopyVram(&buttonsmap + 0xA0, 0x6328, 0x0A); // SLOW button pressed - break; - case normal: - dmaCopyVram(&buttonsmap + 0x6A, 0x630D, 0x0C); // NORMAL button pressed - dmaCopyVram(&buttonsmap + 0xAA, 0x632D, 0x0C); // NORMAL button pressed - break; - case fast: - dmaCopyVram(&buttonsmap + 0x76, 0x6313, 0x0A); // FAST button pressed - dmaCopyVram(&buttonsmap + 0xB6, 0x6333, 0x0A); // FAST button pressed - break; - } - speedset[1] = false; + case slow: + dmaCopyVram(&buttonsmap + 0x60, 0x6308, 0x0A); // SLOW button pressed + dmaCopyVram(&buttonsmap + 0xA0, 0x6328, 0x0A); // SLOW button pressed + break; + case normal: + dmaCopyVram(&buttonsmap + 0x6A, 0x630D, 0x0C); // NORMAL button pressed + dmaCopyVram(&buttonsmap + 0xAA, 0x632D, 0x0C); // NORMAL button pressed + break; + case fast: + dmaCopyVram(&buttonsmap + 0x76, 0x6313, 0x0A); // FAST button pressed + dmaCopyVram(&buttonsmap + 0xB6, 0x6333, 0x0A); // FAST button pressed + break; } if (mousePressed[1] == false) dmaFillVram(&buttonsmap, 0x6AC0, 0x40); // wipe text } - else if (speedset[1] == false) + else { dmaFillVram(&buttonsmap + 0x40, 0x6308, 0x20); // remove buttons dmaFillVram(&buttonsmap + 0x80, 0x6328, 0x20); // remove buttons - speedset[1] = true; } + + // END VBLANK CODE } return 0; -} \ No newline at end of file +} From 7c3d98202611788ff2e6ae91d2b0b75fdfe5d81f Mon Sep 17 00:00:00 2001 From: Marcus Rowe Date: Sat, 3 Aug 2024 14:31:12 +1000 Subject: [PATCH 14/22] Add initMouse function --- pvsneslib/include/snes/input.h | 12 +++++++ pvsneslib/source/input.asm | 36 +++++++++++++++++++ .../input/mouse-data-test/mouse-data-test.c | 4 +-- snes-examples/input/mouse/mouse.c | 13 +++---- 4 files changed, 54 insertions(+), 11 deletions(-) diff --git a/pvsneslib/include/snes/input.h b/pvsneslib/include/snes/input.h index e042d1ab..bc2db501 100644 --- a/pvsneslib/include/snes/input.h +++ b/pvsneslib/include/snes/input.h @@ -223,6 +223,18 @@ void detectMouse(void); */ void detectSuperScope(void); + +/*! + * \brief Enable mouse reading and set the initial mouse sensitivity + * + * Initialises mouse variables and enable mouse reading in the VBlank ISR. + * + * \param sensitivity sensitivity to use when the mouse is connected to the console + * (has no effect on a Hyperkin clone mouse) + */ +void initMouse(u8 sensitivity); + + /*! * \brief Queue a cycle mouse sensitivity command for the next VBlank. * diff --git a/pvsneslib/source/input.asm b/pvsneslib/source/input.asm index 8776c73d..d83ffd69 100644 --- a/pvsneslib/source/input.asm +++ b/pvsneslib/source/input.asm @@ -328,6 +328,42 @@ detectMouse: .ENDS +.SECTION ".initMouse_text" SUPERFREE + +; void initMouse(u8 sensitivity); +initMouse: + php + + ; Clear mouse variables + ; Assumes mouse array variables are 2 bytes in size + rep #$20 + + stz mouseConnect + stz mouseButton + stz mousePressed + stz mousePreviousPressed + stz mouse_x + stz mouse_y + stz mouseRequestChangeSensitivity + + + sep #$20 + + ; Set initial mouse sensitivity + lda 5,s ; sensitivity + sta mouseSensitivity + 0 + sta mouseSensitivity + 1 + + ; Enable mouse reading in the VBlank ISR + lda #1 + sta snes_mouse + + plp + rts + +.ENDS + + .SECTION ".mouseCycleSensitivity_text" SUPERFREE ; void mouseCycleSensitivity(u16 port); diff --git a/snes-examples/input/mouse-data-test/mouse-data-test.c b/snes-examples/input/mouse-data-test/mouse-data-test.c index 738ecfca..eb6da9e9 100644 --- a/snes-examples/input/mouse-data-test/mouse-data-test.c +++ b/snes-examples/input/mouse-data-test/mouse-data-test.c @@ -112,9 +112,9 @@ int main(void) oamMemory[512] = 0; // Clear hi table // Set initial sensitivity to medium - mouseSensitivity[MOUSE_PORT] = 1; + // Enable mouse reading and set the initial mouse sensitivity to medium + initMouse(1); - detectMouse(); consoleDrawText(2, 4, "READING MOUSE ON PORT %d", MOUSE_PORT + 1); setScreenOn(); diff --git a/snes-examples/input/mouse/mouse.c b/snes-examples/input/mouse/mouse.c index 79ba559c..8b0afcf2 100644 --- a/snes-examples/input/mouse/mouse.c +++ b/snes-examples/input/mouse/mouse.c @@ -51,15 +51,10 @@ int main(void) // Draw a wonderful text :P consoleDrawText(11, 1, "MOUSE TEST"); - // Set the sensitivity to use when the mouse is connected to the console, - // or it will just output a random speed. - // - // This can be changed later with mouseSetSensitivity(). - mouseSensitivity[0] = slow; - mouseSensitivity[1] = slow; - - detectMouse(); // Let's check if a mouse is plugged in any port on boot, be sure nmi interrupt was called at least once (in this case, previous oamInitGfxSet() function was enough) - WaitForVBlank(); // Let's make sure we read mouse for the first time after detectMouse() + // Enable mouse reading and set the initial mouse sensitivity + initMouse(slow); + + WaitForVBlank(); // Let's make sure we read mouse for the first time after initMouse() if (mouseConnect[0] == false) consoleDrawText(3, 5, "NO MOUSE PLUGGED ON PORT 0"); From f93f9d4d4f23b47dc3f18a18707138b16c53e024 Mon Sep 17 00:00:00 2001 From: Marcus Rowe Date: Sat, 3 Aug 2024 14:36:35 +1000 Subject: [PATCH 15/22] Remove unnecessary detectMouse() calls from the mouse examples --- snes-examples/input/mouse-data-test/mouse-data-test.c | 1 - snes-examples/input/mouse/mouse.c | 3 --- 2 files changed, 4 deletions(-) diff --git a/snes-examples/input/mouse-data-test/mouse-data-test.c b/snes-examples/input/mouse-data-test/mouse-data-test.c index eb6da9e9..e17ef9c9 100644 --- a/snes-examples/input/mouse-data-test/mouse-data-test.c +++ b/snes-examples/input/mouse-data-test/mouse-data-test.c @@ -127,7 +127,6 @@ int main(void) while (mouseConnect[MOUSE_PORT] == false) { consoleDrawText(2, 4, "NO MOUSE ON PORT %d ", MOUSE_PORT + 1); - detectMouse(); WaitForVBlank(); } diff --git a/snes-examples/input/mouse/mouse.c b/snes-examples/input/mouse/mouse.c index 8b0afcf2..966ecf91 100644 --- a/snes-examples/input/mouse/mouse.c +++ b/snes-examples/input/mouse/mouse.c @@ -96,9 +96,6 @@ int main(void) while (1) { - if (snes_mouse == false) - detectMouse(); // Let's check if a mouse is plugged in any port - odd++; // Optimize Draw text by printing new text just once if (mouseConnect[0] != mc_mem[0]) From ffdc81cd89b79eb6c004f3a2b4b7dc8e7e472f06 Mon Sep 17 00:00:00 2001 From: Marcus Rowe Date: Sun, 4 Aug 2024 08:59:19 +1000 Subject: [PATCH 16/22] Fix mouse displacement variables comments The direction bits now match the snes wiki https://snes.nesdev.org/wiki/Mouse#Report --- pvsneslib/include/snes/input.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pvsneslib/include/snes/input.h b/pvsneslib/include/snes/input.h index bc2db501..846a1740 100644 --- a/pvsneslib/include/snes/input.h +++ b/pvsneslib/include/snes/input.h @@ -87,8 +87,8 @@ extern u8 snes_sscope; /*!< \brief 1 if SuperScope is connected */ extern u8 mouseConnect[2]; /*!< \brief 1 if Mouse present */ extern u8 mouseButton[2]; /*!< \brief 1 if button is pressed, stays for a bit and then it gets released (Click mode). */ extern u8 mousePressed[2]; /*!< \brief 1 if button is pressed, stays until is unpressed (Turbo mode). */ -extern u8 mouse_x[2]; /*!< \brief Mouse X acceleration. daaaaaaa, d = direction (0: up/left, 1: down/right), a = acceleration. */ -extern u8 mouse_y[2]; /*!< \brief Mouse Y acceleration. daaaaaaa, d = direction (0: up/left, 1: down/right), a = acceleration. */ +extern u8 mouse_x[2]; /*!< \brief Mouse horizontal displacement. daaaaaaa, d = direction (1: left, 0: right), a = acceleration. */ +extern u8 mouse_y[2]; /*!< \brief Mouse vertical displacement. daaaaaaa, d = direction (1: up, 0: down), a = acceleration. */ /*! * \brief Mouse sensitivity From 4b775cb9862546351445d5652dffe4a571c42402 Mon Sep 17 00:00:00 2001 From: Marcus Rowe Date: Sun, 4 Aug 2024 09:00:55 +1000 Subject: [PATCH 17/22] Fix mouseSetSensitivity() function declaration not matching the mouseSetSensitivity comment in `pvsneslib/source/input.asm`. --- pvsneslib/include/snes/input.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pvsneslib/include/snes/input.h b/pvsneslib/include/snes/input.h index 846a1740..fb69461d 100644 --- a/pvsneslib/include/snes/input.h +++ b/pvsneslib/include/snes/input.h @@ -267,9 +267,10 @@ void mouseCycleSensitivityTwice(u16 port); * * CAUTION: * * The changes to @ref mouseSensitivity are delayed one frame. + * * A sensitivity value of 3 is invalid. * * This function will override any pending @ref mouseRequestChangeSensitivity commands. * * This function has no effect on the Hyperkin clone mouse. */ -void mouseSetSensitivity(u16 port, u16 sensitivity); +void mouseSetSensitivity(u16 port, u8 sensitivity); #endif // SNES_PADS_INCLUDE From cbe0663dedb3a7e74e9ec4276bb1e70139756855 Mon Sep 17 00:00:00 2001 From: Marcus Rowe Date: Sun, 4 Aug 2024 09:06:36 +1000 Subject: [PATCH 18/22] Remove redundant comment from mouse-data-test.c --- snes-examples/input/mouse-data-test/mouse-data-test.c | 1 - 1 file changed, 1 deletion(-) diff --git a/snes-examples/input/mouse-data-test/mouse-data-test.c b/snes-examples/input/mouse-data-test/mouse-data-test.c index e17ef9c9..c3f90599 100644 --- a/snes-examples/input/mouse-data-test/mouse-data-test.c +++ b/snes-examples/input/mouse-data-test/mouse-data-test.c @@ -111,7 +111,6 @@ int main(void) oamMemory[3] = 0x30; oamMemory[512] = 0; // Clear hi table - // Set initial sensitivity to medium // Enable mouse reading and set the initial mouse sensitivity to medium initMouse(1); From abe8d33eb8d8733ebacda1de6796f3f713355c28 Mon Sep 17 00:00:00 2001 From: Marcus Rowe Date: Sun, 4 Aug 2024 09:34:04 +1000 Subject: [PATCH 19/22] Update the wiki to the new mouse API Also added a few notes about the mouse buttons and mouse sensitivity --- wiki/Input-and-Output.md | 74 +++++++++++++++++++++++++++++----------- 1 file changed, 54 insertions(+), 20 deletions(-) diff --git a/wiki/Input-and-Output.md b/wiki/Input-and-Output.md index 20129b59..69390211 100644 --- a/wiki/Input-and-Output.md +++ b/wiki/Input-and-Output.md @@ -178,31 +178,42 @@ At least, the pad is refresh during VBL (thanks to VBlank function), so it is no ### Mouse -**snes_mouse** has to be turned on (snes_mouse = 1). This is set 0 by default after consoleInit(). -This will tell the system to read from a mouse, if it is found. -Mouse and pads can be used simultaneously, on any ports. Externs in the pad.h file goes like this: +**snes_mouse** has to be turned on (`snes_mouse` = 1). This is set to 0 by default after `consoleInit()`. + +You can set `snes_mouse` to 1 by calling `initMouse()` or `detectMouse()`. + * `initMouse()` will also clear the mouse variables and set the initial mouse sensitivity. + * `detectMouse()` will only set `snes_mouse` to 1 if it detects a mouse on one of the console ports. + + +When `snes_mouse` is non-zero, the VBlank ISR will read mouse data from the controller ports +and update the following mouse state variables (the array index specifies the controller port [0 or +1]): ``` -snes_mouse; /*!1 if Mouse is going to be used */ +extern u8 mouseConnect[2]; /*!< \brief 1 if Mouse present */ +extern u8 mouseButton[2]; /*!< \brief 1 if button is pressed, stays for a bit and then it gets released (Click mode). */ +extern u8 mousePressed[2]; /*!< \brief 1 if button is pressed, stays until is unpressed (Turbo mode). */ +extern u8 mouse_x[2]; /*!< \brief Mouse horizontal displacement. daaaaaaa, d = direction (1: left, 0: right), a = acceleration. */ +extern u8 mouse_y[2]; /*!< \brief Mouse vertical displacement. daaaaaaa, d = direction (1: up, 0: down), a = acceleration. */ +extern u8 mouseSensitivity[2]; /*!< \brief Mouse sensitivity (0-2) */ ``` -mouseConnect[2]; /* 1 if Mouse present */ -mouseButton[2]; /* 1 if button is pressed, stays for a bit and then it gets released (Click mode). */ -mousePressed[2]; /* 1 if button is pressed, stays until is unpressed (Turbo mode). */ -mouse_x[2], mouse_y[2]; /* Mouse acceleration. daaaaaaa, d = direction (0: up/left, 1: down/right), a = acceleration. */ -mouseSpeedSet[2]; /* Mouse speed setting. 0: slow, 1: normal, 2: fast */ -First, we might use **detectMouse()** to populate snes_mouse to 1, so It can be called at boot and like this: +To use the mouse, we first call **initMouse()** or **detectMouse()** to populate snes_mouse to 1. +It can be called at boot and like this: ``` -if (snes_mouse == false) -{ - detectMouse(); - // some other code you might need in your program, like displaying warning messages and stopping your game. -} +// Enable mouse reading and set the initial mouse sensitivity to medium +initMouse(1); ``` -the number inside array specifies port (0 or 1). I recommend using this code structure to convert raw acceleration into usable values: +Reading the two mouse buttons is done by reading the `mouseButton` or `mousePressed` variables in +the same manner a detecting joypad buttons. `mouseButton` will contain buttons that are newly +pressed on this frame and `mousePressed` contains the buttons that are currently depressed (held +down). + + +I recommend using this code structure to convert raw displacement data into usable values: ``` u16 p1_mouse_x = 0x80; @@ -210,17 +221,40 @@ u16 p1_mouse_y = 0x70; u16 p2_mouse_x = 0x80; u16 p2_mouse_y = 0x70; - if (mouse_x[0] & 0x80) +if (mouse_x[0] & 0x80) p1_mouse_x -= mouse_x[0] & 0x7F; else - p1_mouse_x += mouse_x[0] & 0x7F; + p1_mouse_x += mouse_x[0]; + if (mouse_y[0] & 0x80) p1_mouse_y -= mouse_y[0] & 0x7F; else - p1_mouse_y += mouse_y[0] & 0x7F; + p1_mouse_y += mouse_y[0]; ``` -And that's most of it. You can look inside the example file (**snes-examples/input** folder) to have an idea of how you can program Mouse games. +To get a better idea on how to read the mouse, please see the following examples: + * `snes-examples/input/mouse`: A mouse demo that can read 2 mice at the same time. + * `snes-examples/input/mouse-data-test`: Prints the mouse data from controller port 2 to the user. + + +#### Sensitivity + +The Nintendo mouse has 3 sensitivity settings (0=low, 1=medium, 2=high) that can be adjusted by +sending cycle-sensitivity commands to the mouse through the controller port. + +The Hyperkin clone mouse will always report 0 sensitity and will ignore cycle sensitivity commands. + +The `u8 mouseRequestChangeSensitivity[2]` variable is used to signal to the VBlank ISR that the +MainLoop wants to change the Nintendo Mouse's sensitivity setting. Cycling the sensitity is done in +the VBlank ISR to prevent a timing conflict with the SNES's Automatic Joypad read. + +To adjust the mouse sensitity, either modify `mouseRequestChangeSensitivity` (see `input.h`) or call +one of these functions: + * `void mouseCycleSensitivity(u16 port);` - cycles the mouse sensitivity once (incrementing the sensitivity) + * `void mouseCycleSensitivityTwice(u16 port);` - cycles the mouse sensitity twice (decrementing the sensitivity) + * `void mouseSetSensitivity(u16 port, u8 sensitivity);` - changes the mouse sensitivity to `sensitivity & 3`. (A sensitivity value of 3 is invalid) + +Please be aware that the reported sensitivity in the `mouseSensitivity` variable will be delayed one frame. ### SuperScope From d8d604ed1e7fcada0368892e29f403824c720ee0 Mon Sep 17 00:00:00 2001 From: Marcus Rowe Date: Wed, 14 Aug 2024 20:10:36 +1000 Subject: [PATCH 20/22] Make mousePreviousPressed array public --- pvsneslib/include/snes/input.h | 1 + wiki/Input-and-Output.md | 1 + 2 files changed, 2 insertions(+) diff --git a/pvsneslib/include/snes/input.h b/pvsneslib/include/snes/input.h index fb69461d..7872fef5 100644 --- a/pvsneslib/include/snes/input.h +++ b/pvsneslib/include/snes/input.h @@ -87,6 +87,7 @@ extern u8 snes_sscope; /*!< \brief 1 if SuperScope is connected */ extern u8 mouseConnect[2]; /*!< \brief 1 if Mouse present */ extern u8 mouseButton[2]; /*!< \brief 1 if button is pressed, stays for a bit and then it gets released (Click mode). */ extern u8 mousePressed[2]; /*!< \brief 1 if button is pressed, stays until is unpressed (Turbo mode). */ +extern u8 mousePreviousPressed[2];/*!< \brief Mouse buttons held or pressed in the previous frame */ extern u8 mouse_x[2]; /*!< \brief Mouse horizontal displacement. daaaaaaa, d = direction (1: left, 0: right), a = acceleration. */ extern u8 mouse_y[2]; /*!< \brief Mouse vertical displacement. daaaaaaa, d = direction (1: up, 0: down), a = acceleration. */ diff --git a/wiki/Input-and-Output.md b/wiki/Input-and-Output.md index 69390211..7a770f90 100644 --- a/wiki/Input-and-Output.md +++ b/wiki/Input-and-Output.md @@ -193,6 +193,7 @@ and update the following mouse state variables (the array index specifies the co extern u8 mouseConnect[2]; /*!< \brief 1 if Mouse present */ extern u8 mouseButton[2]; /*!< \brief 1 if button is pressed, stays for a bit and then it gets released (Click mode). */ extern u8 mousePressed[2]; /*!< \brief 1 if button is pressed, stays until is unpressed (Turbo mode). */ +extern u8 mousePreviousPressed[2];/*!< \brief Mouse buttons held or pressed in the previous frame */ extern u8 mouse_x[2]; /*!< \brief Mouse horizontal displacement. daaaaaaa, d = direction (1: left, 0: right), a = acceleration. */ extern u8 mouse_y[2]; /*!< \brief Mouse vertical displacement. daaaaaaa, d = direction (1: up, 0: down), a = acceleration. */ extern u8 mouseSensitivity[2]; /*!< \brief Mouse sensitivity (0-2) */ From c0e0768ea52ad3397d1d4eb0259e61f6b6c3110e Mon Sep 17 00:00:00 2001 From: Marcus Rowe Date: Wed, 14 Aug 2024 20:15:13 +1000 Subject: [PATCH 21/22] Improve mouseButton and mousePressed documentation --- pvsneslib/include/snes/input.h | 4 ++-- wiki/Input-and-Output.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pvsneslib/include/snes/input.h b/pvsneslib/include/snes/input.h index 7872fef5..86b36774 100644 --- a/pvsneslib/include/snes/input.h +++ b/pvsneslib/include/snes/input.h @@ -85,8 +85,8 @@ extern u8 snes_mouse; /*!< \brief 1 if Mouse is going to be used */ extern u8 snes_sscope; /*!< \brief 1 if SuperScope is connected */ extern u8 mouseConnect[2]; /*!< \brief 1 if Mouse present */ -extern u8 mouseButton[2]; /*!< \brief 1 if button is pressed, stays for a bit and then it gets released (Click mode). */ -extern u8 mousePressed[2]; /*!< \brief 1 if button is pressed, stays until is unpressed (Turbo mode). */ +extern u8 mouseButton[2]; /*!< \brief Mouse buttons that are pressed on this frame (Click mode). */ +extern u8 mousePressed[2]; /*!< \brief Mouse buttons that are currently pressed, stays until is unpressed (Turbo mode). */ extern u8 mousePreviousPressed[2];/*!< \brief Mouse buttons held or pressed in the previous frame */ extern u8 mouse_x[2]; /*!< \brief Mouse horizontal displacement. daaaaaaa, d = direction (1: left, 0: right), a = acceleration. */ extern u8 mouse_y[2]; /*!< \brief Mouse vertical displacement. daaaaaaa, d = direction (1: up, 0: down), a = acceleration. */ diff --git a/wiki/Input-and-Output.md b/wiki/Input-and-Output.md index 7a770f90..27e990e1 100644 --- a/wiki/Input-and-Output.md +++ b/wiki/Input-and-Output.md @@ -191,8 +191,8 @@ and update the following mouse state variables (the array index specifies the co ``` extern u8 mouseConnect[2]; /*!< \brief 1 if Mouse present */ -extern u8 mouseButton[2]; /*!< \brief 1 if button is pressed, stays for a bit and then it gets released (Click mode). */ -extern u8 mousePressed[2]; /*!< \brief 1 if button is pressed, stays until is unpressed (Turbo mode). */ +extern u8 mouseButton[2]; /*!< \brief Mouse buttons that are pressed on this frame (Click mode). */ +extern u8 mousePressed[2]; /*!< \brief Mouse buttons that are currently pressed, stays until is unpressed (Turbo mode). */ extern u8 mousePreviousPressed[2];/*!< \brief Mouse buttons held or pressed in the previous frame */ extern u8 mouse_x[2]; /*!< \brief Mouse horizontal displacement. daaaaaaa, d = direction (1: left, 0: right), a = acceleration. */ extern u8 mouse_y[2]; /*!< \brief Mouse vertical displacement. daaaaaaa, d = direction (1: up, 0: down), a = acceleration. */ From 56c038b6f64fa84be9a8440ff9641105606afe9b Mon Sep 17 00:00:00 2001 From: Marcus Rowe Date: Wed, 14 Aug 2024 20:25:13 +1000 Subject: [PATCH 22/22] Add mouse sensitivity enum constants --- pvsneslib/include/snes/input.h | 12 +++++++ .../input/mouse-data-test/mouse-data-test.c | 6 ++-- snes-examples/input/mouse/mouse.c | 35 +++++++------------ 3 files changed, 28 insertions(+), 25 deletions(-) diff --git a/pvsneslib/include/snes/input.h b/pvsneslib/include/snes/input.h index 86b36774..0f9024de 100644 --- a/pvsneslib/include/snes/input.h +++ b/pvsneslib/include/snes/input.h @@ -76,6 +76,18 @@ typedef enum SUPERSCOPE_BITS SSC_NOISE = BIT(8), //!< superscope NOISE flag. } SUPERSCOPE_BITS; +/*! + * \brief Mouse sensitivity values + * + * enum values for the mouse sensitivity. + */ +typedef enum MOUSE_SENSITIVITY +{ + MOUSE_SLOW = 0, //!< slow sensitivity + MOUSE_MEDIUM = 1, //!< medium sensitivity + MOUSE_FAST = 2, //!< fast sensitivity +} MOUSE_SENSITIVITY; + extern u16 pad_keys[5]; //!< current pad value extern u16 pad_keysold[5]; //!< previous pad value extern u16 pad_keysdown[5]; //!< newly pressed down pad keys diff --git a/snes-examples/input/mouse-data-test/mouse-data-test.c b/snes-examples/input/mouse-data-test/mouse-data-test.c index c3f90599..bcb18bfe 100644 --- a/snes-examples/input/mouse-data-test/mouse-data-test.c +++ b/snes-examples/input/mouse-data-test/mouse-data-test.c @@ -162,13 +162,13 @@ int main(void) if (padsDown(JOYPAD_PORT) & (KEY_Y | KEY_X | KEY_A | KEY_L | KEY_R)) { if (padsDown(JOYPAD_PORT) & KEY_Y) { - mouseSetSensitivity(MOUSE_PORT, 0); + mouseSetSensitivity(MOUSE_PORT, MOUSE_SLOW); } if (padsDown(JOYPAD_PORT) & KEY_X) { - mouseSetSensitivity(MOUSE_PORT, 1); + mouseSetSensitivity(MOUSE_PORT, MOUSE_MEDIUM); } if (padsDown(JOYPAD_PORT) & KEY_A) { - mouseSetSensitivity(MOUSE_PORT, 2); + mouseSetSensitivity(MOUSE_PORT, MOUSE_FAST); } if (padsDown(JOYPAD_PORT) & KEY_R) { mouseCycleSensitivity(MOUSE_PORT); diff --git a/snes-examples/input/mouse/mouse.c b/snes-examples/input/mouse/mouse.c index 966ecf91..56db0e57 100644 --- a/snes-examples/input/mouse/mouse.c +++ b/snes-examples/input/mouse/mouse.c @@ -10,15 +10,6 @@ ---------------------------------------------------------------------------------*/ #include -#ifndef MOUSE_SPEED -#define MOUSE_SPEED - -#define slow 0 -#define normal 1 -#define fast 2 - -#endif - extern char snesfont, snespal, cursorsprite, cursorsprite_end, cursorpal, buttonsmap, buttonstiles, buttonstiles_end, buttonspal; char hex_string[4]; @@ -52,7 +43,7 @@ int main(void) consoleDrawText(11, 1, "MOUSE TEST"); // Enable mouse reading and set the initial mouse sensitivity - initMouse(slow); + initMouse(MOUSE_SLOW); WaitForVBlank(); // Let's make sure we read mouse for the first time after initMouse() @@ -294,15 +285,15 @@ int main(void) { if ((p1_mouse_x > 0x44) && (p1_mouse_x < 0x64)) { - mouseSetSensitivity(0, slow); // Queue a set sensitivity command + mouseSetSensitivity(0, MOUSE_SLOW); // Queue a set sensitivity command } if ((p1_mouse_x > 0x6C) && (p1_mouse_x < 0x94)) { - mouseSetSensitivity(0, normal); // Queue a set sensitivity command + mouseSetSensitivity(0, MOUSE_MEDIUM); // Queue a set sensitivity command } if ((p1_mouse_x > 0x9C) && (p1_mouse_x < 0xBC)) { - mouseSetSensitivity(0, fast); // Queue a set sensitivity command + mouseSetSensitivity(0, MOUSE_FAST); // Queue a set sensitivity command } } } @@ -314,15 +305,15 @@ int main(void) { if ((p2_mouse_x > 0x44) && (p2_mouse_x < 0x64)) { - mouseSetSensitivity(1, slow); // Queue a set sensitivity command + mouseSetSensitivity(1, MOUSE_SLOW); // Queue a set sensitivity command } if ((p2_mouse_x > 0x6C) && (p2_mouse_x < 0x94)) { - mouseSetSensitivity(1, normal); // Queue a set sensitivity command + mouseSetSensitivity(1, MOUSE_MEDIUM); // Queue a set sensitivity command } if ((p2_mouse_x > 0x9C) && (p2_mouse_x < 0xBC)) { - mouseSetSensitivity(1, fast); // Queue a set sensitivity command + mouseSetSensitivity(1, MOUSE_FAST); // Queue a set sensitivity command } } } @@ -339,15 +330,15 @@ int main(void) // Show reported sensitivity switch (mouseSensitivity[0]) { - case slow: + case MOUSE_SLOW: dmaCopyVram(&buttonsmap + 0x60, 0x6188, 0x0A); // SLOW button pressed dmaCopyVram(&buttonsmap + 0xA0, 0x61A8, 0x0A); // SLOW button pressed break; - case normal: + case MOUSE_MEDIUM: dmaCopyVram(&buttonsmap + 0x6A, 0x618D, 0x0C); // NORMAL button pressed dmaCopyVram(&buttonsmap + 0xAA, 0x61AD, 0x0C); // NORMAL button pressed break; - case fast: + case MOUSE_FAST: dmaCopyVram(&buttonsmap + 0x76, 0x6193, 0x0A); // FAST button pressed dmaCopyVram(&buttonsmap + 0xB6, 0x61B3, 0x0A); // FAST button pressed break; @@ -369,15 +360,15 @@ int main(void) switch (mouseSensitivity[1]) { - case slow: + case MOUSE_SLOW: dmaCopyVram(&buttonsmap + 0x60, 0x6308, 0x0A); // SLOW button pressed dmaCopyVram(&buttonsmap + 0xA0, 0x6328, 0x0A); // SLOW button pressed break; - case normal: + case MOUSE_MEDIUM: dmaCopyVram(&buttonsmap + 0x6A, 0x630D, 0x0C); // NORMAL button pressed dmaCopyVram(&buttonsmap + 0xAA, 0x632D, 0x0C); // NORMAL button pressed break; - case fast: + case MOUSE_FAST: dmaCopyVram(&buttonsmap + 0x76, 0x6313, 0x0A); // FAST button pressed dmaCopyVram(&buttonsmap + 0xB6, 0x6333, 0x0A); // FAST button pressed break;