From 3a1c9e2035c28ced266fa018e5a73c027d514e35 Mon Sep 17 00:00:00 2001
From: windwakr <284886+windwakr@users.noreply.github.com>
Date: Tue, 10 Oct 2023 22:27:29 -0400
Subject: [PATCH 1/7] Slot2: Add Slide Controller
---
desmume/src/Makefile.am | 1 +
desmume/src/addons/slot2_slideController.cpp | 264 ++++++++++++++++++
desmume/src/frontend/interface/meson.build | 2 +-
.../windows/DeSmuME_Interface.vcxproj | 1 +
.../windows/DeSmuME_Interface.vcxproj.filters | 3 +
desmume/src/frontend/posix/Makefile.am | 2 +-
desmume/src/frontend/posix/meson.build | 2 +-
desmume/src/frontend/windows/DeSmuME.vcxproj | 1 +
.../frontend/windows/DeSmuME.vcxproj.filters | 3 +
.../src/frontend/windows/gbaslot_config.cpp | 17 +-
desmume/src/frontend/windows/inputdx.cpp | 2 +
desmume/src/frontend/windows/inputdx.h | 5 +
desmume/src/frontend/windows/main.cpp | 34 +++
desmume/src/slot2.cpp | 25 +-
desmume/src/slot2.h | 26 +-
15 files changed, 356 insertions(+), 32 deletions(-)
create mode 100644 desmume/src/addons/slot2_slideController.cpp
diff --git a/desmume/src/Makefile.am b/desmume/src/Makefile.am
index b17d4df7f..1db6c6fa0 100644
--- a/desmume/src/Makefile.am
+++ b/desmume/src/Makefile.am
@@ -96,6 +96,7 @@ libdesmume_a_SOURCES = \
addons/slot2_rumblepak.cpp \
addons/slot2_guitarGrip.cpp \
addons/slot2_hcv1000.cpp \
+ addons/slot2_slideController.cpp \
addons/slot2_expMemory.cpp \
addons/slot2_piano.cpp \
addons/slot2_passme.cpp \
diff --git a/desmume/src/addons/slot2_slideController.cpp b/desmume/src/addons/slot2_slideController.cpp
new file mode 100644
index 000000000..b75cae51c
--- /dev/null
+++ b/desmume/src/addons/slot2_slideController.cpp
@@ -0,0 +1,264 @@
+/*
+ Copyright (C) 2023 DeSmuME team
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This file is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the this software. If not, see .
+*/
+
+//Absolute barebones implementation of the Slide Controller add-on. Rumble is not implemented.
+//The game does a bunch of mystery reads of various sizes which have not been investigated at all.
+
+#include "../slot2.h"
+#include "../emufile.h"
+
+#define SC_BITIN(X, Y) \
+do { \
+ X = (X << 1) | (Y & 1); \
+ bitsWritten++; \
+} while (0)
+
+#define SC_BITOUT(X, Y) \
+do { \
+ X = ((Y >> 7 - bitsRead) & 1); \
+ bitsRead++; \
+} while(0)
+
+u8 motionStatus;
+u8 xMotion;
+u8 yMotion;
+
+class Slot2_SlideController : public ISlot2Interface
+{
+private:
+ u8 prevClock;
+ u8 bitsWritten;
+ u8 bitsRead;
+ u8 inByte;
+ u16 regSel;
+
+ u8 configBits;
+ u8 framePeriodLower;
+ u8 framePeriodUpper;
+public:
+
+ virtual Slot2Info const* info()
+ {
+ static Slot2InfoSimple info("Slide Controller", "Slide Controller add-on", 0x0A);
+ return &info;
+ }
+
+ virtual void connect()
+ {
+ prevClock = 0;
+ bitsWritten = 0;
+ bitsRead = 0;
+ inByte = 0;
+ regSel = 0xFFFF;
+
+ motionStatus = 0;
+ xMotion = 0;
+ yMotion = 0;
+ configBits = 0;
+ framePeriodLower = 0x20;
+ framePeriodUpper = 0xD1;
+ }
+
+ virtual void writeWord(u8 PROCNUM, u32 addr, u16 val)
+ {
+ if (addr == 0x081E0000)
+ {
+ if ((prevClock == 0) && (val & 0x2) && (val & 0x8))
+ {
+ SC_BITIN(inByte, val);
+ if (bitsWritten == 8)
+ {
+ bitsWritten = 0;
+ if (regSel == 0xFFFF) //First byte written
+ {
+ regSel = inByte;
+ }
+ else //Second byte written
+ {
+ //printf("WRITE TO REG: %02X = %02X\n", regSel & 0x7F , inByte);
+ switch (regSel & 0x7F)
+ {
+ case 0x0A: //Config bits
+ configBits = inByte;
+ break;
+ case 0x10: //Frame period (lower)
+ framePeriodLower = inByte;
+ break;
+ case 0x11: //Frame period(upper)
+ framePeriodUpper = inByte;
+ break;
+ }
+ regSel = 0xFFFF;
+ }
+ }
+ }
+ prevClock = (val & 0x2) >> 1;
+ }
+
+ if (configBits & 0x80) //Reset
+ {
+ motionStatus = 0;
+ xMotion = 0;
+ yMotion = 0;
+ configBits = 0;
+ framePeriodLower = 0x20;
+ framePeriodUpper = 0xD1;
+
+ prevClock = 0;
+ bitsWritten = 0;
+ bitsRead = 0;
+ inByte = 0;
+ regSel = 0xFFFF;
+ }
+ }
+
+ virtual u8 readByte(u8 PROCNUM, u32 addr)
+ {
+ if (addr == 0x080000B2)
+ {
+ return 0x96;
+ }
+ return 0xFF;
+ }
+
+ virtual u16 readWord(u8 PROCNUM, u32 addr)
+ {
+ u16 outWord = 0;
+
+ if (addr < 0x08000100)
+ {
+ outWord = 0xFEF0;
+ }
+
+ if (addr == 0x081E0000)
+ {
+ switch (regSel)
+ {
+ case 0x00: //Product ID
+ SC_BITOUT(outWord, 0x3);
+ break;
+ case 0x01: //Revision ID
+ SC_BITOUT(outWord, 0x20); //Is this correct?
+ break;
+ case 0x02: //Motion status
+ SC_BITOUT(outWord, motionStatus);
+ if (bitsRead == 8) motionStatus = 0;
+ break;
+ case 0x03: //X motion delta
+ SC_BITOUT(outWord, xMotion);
+ if (bitsRead == 8) xMotion = 0;
+ break;
+ case 0x04: //Y motion delta
+ SC_BITOUT(outWord, yMotion);
+ if (bitsRead == 8) yMotion = 0;
+ break;
+ case 0x05: //Surface quality
+ SC_BITOUT(outWord, 128);
+ break;
+ case 0x06: //Average pixel
+ SC_BITOUT(outWord, 32);
+ break;
+ case 0x07: //Maximum pixel
+ SC_BITOUT(outWord, 63);
+ break;
+ case 0x0A: //Configuration bits
+ SC_BITOUT(outWord, configBits);
+ break;
+ case 0x0C: //Data out (lower)
+ SC_BITOUT(outWord, 0);
+ break;
+ case 0x0D: //Data out (upper)
+ SC_BITOUT(outWord, 0);
+ break;
+ case 0x0E: //Shutter value (lower)
+ SC_BITOUT(outWord, 64);
+ break;
+ case 0x0F: //Shutter value (upper)
+ SC_BITOUT(outWord, 0);
+ break;
+ case 0x10: //Frame period (lower)
+ SC_BITOUT(outWord, framePeriodLower);
+ break;
+ case 0x11: //Frame period (upper)
+ SC_BITOUT(outWord, framePeriodUpper);
+ break;
+ }
+
+ if (bitsRead == 8)
+ {
+ bitsRead = 0;
+ //printf("READ FROM REG: %02X\n", regSel);
+ regSel = 0xFFFF;
+ }
+ }
+
+ return outWord;
+ }
+
+ virtual void savestate(EMUFILE& os)
+ {
+ s32 version = 0;
+ os.write_32LE(version);
+
+ os.write_u8(prevClock);
+ os.write_u8(bitsWritten);
+ os.write_u8(bitsRead);
+ os.write_u8(inByte);
+ os.write_16LE(regSel);
+
+ os.write_u8(configBits);
+ os.write_u8(framePeriodLower);
+ os.write_u8(framePeriodUpper);
+ os.write_u8(motionStatus);
+ os.write_u8(xMotion);
+ os.write_u8(yMotion);
+ }
+
+ virtual void loadstate(EMUFILE& is)
+ {
+ s32 version = is.read_s32LE();
+
+ if (version == 0)
+ {
+ is.read_u8(prevClock);
+ is.read_u8(bitsWritten);
+ is.read_u8(bitsRead);
+ is.read_u8(inByte);
+ is.read_16LE(regSel);
+
+ is.read_u8(configBits);
+ is.read_u8(framePeriodLower);
+ is.read_u8(framePeriodUpper);
+ is.read_u8(motionStatus);
+ is.read_u8(xMotion);
+ is.read_u8(yMotion);
+ }
+ }
+};
+
+ISlot2Interface* construct_Slot2_SlideController() { return new Slot2_SlideController(); }
+
+void slideController_updateMotion(s8 x, s8 y)
+{
+ xMotion = (u8)x;
+ yMotion = (u8)y;
+ if (xMotion || yMotion)
+ motionStatus = 0x80;
+}
+
+#undef SC_BITIN
+#undef SC_BITOUT
diff --git a/desmume/src/frontend/interface/meson.build b/desmume/src/frontend/interface/meson.build
index 6a62fbb2e..70693ce42 100644
--- a/desmume/src/frontend/interface/meson.build
+++ b/desmume/src/frontend/interface/meson.build
@@ -109,7 +109,7 @@ libdesmume_src += [
'../../utils/tinyxml/tinyxmlerror.cpp',
'../../utils/tinyxml/tinyxmlparser.cpp',
'../../utils/colorspacehandler/colorspacehandler.cpp',
- '../../addons/slot2_auto.cpp', '../../addons/slot2_mpcf.cpp', '../../addons/slot2_paddle.cpp', '../../addons/slot2_gbagame.cpp', '../../addons/slot2_none.cpp', '../../addons/slot2_rumblepak.cpp', '../../addons/slot2_guitarGrip.cpp', '../../addons/slot2_hcv1000.cpp', '../../addons/slot2_expMemory.cpp', '../../addons/slot2_piano.cpp', '../../addons/slot2_passme.cpp', '../../addons/slot1_none.cpp', '../../addons/slot1_r4.cpp', '../../addons/slot1_retail_nand.cpp', '../../addons/slot1_retail_auto.cpp', '../../addons/slot1_retail_mcrom.cpp', '../../addons/slot1_retail_mcrom_debug.cpp', '../../addons/slot1comp_mc.cpp', '../../addons/slot1comp_rom.cpp', '../../addons/slot1comp_protocol.cpp',
+ '../../addons/slot2_auto.cpp', '../../addons/slot2_mpcf.cpp', '../../addons/slot2_paddle.cpp', '../../addons/slot2_gbagame.cpp', '../../addons/slot2_none.cpp', '../../addons/slot2_rumblepak.cpp', '../../addons/slot2_guitarGrip.cpp', '../../addons/slot2_hcv1000.cpp', '../../addons/slot2_slideController.cpp', '../../addons/slot2_expMemory.cpp', '../../addons/slot2_piano.cpp', '../../addons/slot2_passme.cpp', '../../addons/slot1_none.cpp', '../../addons/slot1_r4.cpp', '../../addons/slot1_retail_nand.cpp', '../../addons/slot1_retail_auto.cpp', '../../addons/slot1_retail_mcrom.cpp', '../../addons/slot1_retail_mcrom_debug.cpp', '../../addons/slot1comp_mc.cpp', '../../addons/slot1comp_rom.cpp', '../../addons/slot1comp_protocol.cpp',
'../../cheatSystem.cpp',
'../../texcache.cpp', '../../rasterize.cpp',
'../../metaspu/metaspu.cpp',
diff --git a/desmume/src/frontend/interface/windows/DeSmuME_Interface.vcxproj b/desmume/src/frontend/interface/windows/DeSmuME_Interface.vcxproj
index ab87e284e..33e7243a5 100644
--- a/desmume/src/frontend/interface/windows/DeSmuME_Interface.vcxproj
+++ b/desmume/src/frontend/interface/windows/DeSmuME_Interface.vcxproj
@@ -269,6 +269,7 @@
+
diff --git a/desmume/src/frontend/interface/windows/DeSmuME_Interface.vcxproj.filters b/desmume/src/frontend/interface/windows/DeSmuME_Interface.vcxproj.filters
index cb3248c43..64101c1a3 100755
--- a/desmume/src/frontend/interface/windows/DeSmuME_Interface.vcxproj.filters
+++ b/desmume/src/frontend/interface/windows/DeSmuME_Interface.vcxproj.filters
@@ -135,6 +135,9 @@
addons
+
+ addons
+
addons
diff --git a/desmume/src/frontend/posix/Makefile.am b/desmume/src/frontend/posix/Makefile.am
index 4329a89e7..68a63e774 100644
--- a/desmume/src/frontend/posix/Makefile.am
+++ b/desmume/src/frontend/posix/Makefile.am
@@ -98,7 +98,7 @@ libdesmume_a_SOURCES = \
../../utils/tinyxml/tinyxmlparser.cpp \
../../utils/glcorearb.h \
../../utils/colorspacehandler/colorspacehandler.cpp ../../utils/colorspacehandler/colorspacehandler.h \
- ../../addons/slot2_auto.cpp ../../addons/slot2_mpcf.cpp ../../addons/slot2_paddle.cpp ../../addons/slot2_gbagame.cpp ../../addons/slot2_none.cpp ../../addons/slot2_rumblepak.cpp ../../addons/slot2_guitarGrip.cpp ../../addons/slot2_hcv1000.cpp ../../addons/slot2_expMemory.cpp ../../addons/slot2_piano.cpp ../../addons/slot2_passme.cpp ../../addons/slot1_none.cpp ../../addons/slot1_r4.cpp ../../addons/slot1_retail_nand.cpp ../../addons/slot1_retail_auto.cpp ../../addons/slot1_retail_mcrom.cpp ../../addons/slot1_retail_mcrom_debug.cpp ../../addons/slot1comp_mc.cpp ../../addons/slot1comp_mc.h ../../addons/slot1comp_rom.h ../../addons/slot1comp_rom.cpp ../../addons/slot1comp_protocol.h ../../addons/slot1comp_protocol.cpp \
+ ../../addons/slot2_auto.cpp ../../addons/slot2_mpcf.cpp ../../addons/slot2_paddle.cpp ../../addons/slot2_gbagame.cpp ../../addons/slot2_none.cpp ../../addons/slot2_rumblepak.cpp ../../addons/slot2_guitarGrip.cpp ../../addons/slot2_hcv1000.cpp ../../addons/slot2_slideController.cpp ../../addons/slot2_expMemory.cpp ../../addons/slot2_piano.cpp ../../addons/slot2_passme.cpp ../../addons/slot1_none.cpp ../../addons/slot1_r4.cpp ../../addons/slot1_retail_nand.cpp ../../addons/slot1_retail_auto.cpp ../../addons/slot1_retail_mcrom.cpp ../../addons/slot1_retail_mcrom_debug.cpp ../../addons/slot1comp_mc.cpp ../../addons/slot1comp_mc.h ../../addons/slot1comp_rom.h ../../addons/slot1comp_rom.cpp ../../addons/slot1comp_protocol.h ../../addons/slot1comp_protocol.cpp \
../../cheatSystem.cpp ../../cheatSystem.h \
../../texcache.cpp ../../texcache.h ../../rasterize.cpp ../../rasterize.h \
../../metaspu/metaspu.cpp ../../metaspu/metaspu.h \
diff --git a/desmume/src/frontend/posix/meson.build b/desmume/src/frontend/posix/meson.build
index 89e0e4bef..59e93afba 100644
--- a/desmume/src/frontend/posix/meson.build
+++ b/desmume/src/frontend/posix/meson.build
@@ -104,7 +104,7 @@ libdesmume_src = [
'../../utils/tinyxml/tinyxmlerror.cpp',
'../../utils/tinyxml/tinyxmlparser.cpp',
'../../utils/colorspacehandler/colorspacehandler.cpp',
- '../../addons/slot2_auto.cpp', '../../addons/slot2_mpcf.cpp', '../../addons/slot2_paddle.cpp', '../../addons/slot2_gbagame.cpp', '../../addons/slot2_none.cpp', '../../addons/slot2_rumblepak.cpp', '../../addons/slot2_guitarGrip.cpp', '../../addons/slot2_hcv1000.cpp', '../../addons/slot2_expMemory.cpp', '../../addons/slot2_piano.cpp', '../../addons/slot2_passme.cpp', '../../addons/slot1_none.cpp', '../../addons/slot1_r4.cpp', '../../addons/slot1_retail_nand.cpp', '../../addons/slot1_retail_auto.cpp', '../../addons/slot1_retail_mcrom.cpp', '../../addons/slot1_retail_mcrom_debug.cpp', '../../addons/slot1comp_mc.cpp', '../../addons/slot1comp_rom.cpp', '../../addons/slot1comp_protocol.cpp',
+ '../../addons/slot2_auto.cpp', '../../addons/slot2_mpcf.cpp', '../../addons/slot2_paddle.cpp', '../../addons/slot2_gbagame.cpp', '../../addons/slot2_none.cpp', '../../addons/slot2_rumblepak.cpp', '../../addons/slot2_guitarGrip.cpp', '../../addons/slot2_hcv1000.cpp', '../../addons/slot2_slideController.cpp', '../../addons/slot2_expMemory.cpp', '../../addons/slot2_piano.cpp', '../../addons/slot2_passme.cpp', '../../addons/slot1_none.cpp', '../../addons/slot1_r4.cpp', '../../addons/slot1_retail_nand.cpp', '../../addons/slot1_retail_auto.cpp', '../../addons/slot1_retail_mcrom.cpp', '../../addons/slot1_retail_mcrom_debug.cpp', '../../addons/slot1comp_mc.cpp', '../../addons/slot1comp_rom.cpp', '../../addons/slot1comp_protocol.cpp',
'../../cheatSystem.cpp',
'../../texcache.cpp', '../../rasterize.cpp',
'../../metaspu/metaspu.cpp',
diff --git a/desmume/src/frontend/windows/DeSmuME.vcxproj b/desmume/src/frontend/windows/DeSmuME.vcxproj
index bd4484362..5bd3c3ac1 100644
--- a/desmume/src/frontend/windows/DeSmuME.vcxproj
+++ b/desmume/src/frontend/windows/DeSmuME.vcxproj
@@ -73,6 +73,7 @@
+
diff --git a/desmume/src/frontend/windows/DeSmuME.vcxproj.filters b/desmume/src/frontend/windows/DeSmuME.vcxproj.filters
index 3e18bf156..35e1d4720 100644
--- a/desmume/src/frontend/windows/DeSmuME.vcxproj.filters
+++ b/desmume/src/frontend/windows/DeSmuME.vcxproj.filters
@@ -933,6 +933,9 @@
addons
+
+ addons
+
diff --git a/desmume/src/frontend/windows/gbaslot_config.cpp b/desmume/src/frontend/windows/gbaslot_config.cpp
index 9109eba18..5df2b0cc4 100644
--- a/desmume/src/frontend/windows/gbaslot_config.cpp
+++ b/desmume/src/frontend/windows/gbaslot_config.cpp
@@ -526,11 +526,12 @@ u32 GBAslot_IDDs[NDS_SLOT2_COUNT] = {
IDD_GBASLOT_RUMBLEPAK,
IDD_GBASLOT_GBAGAME,
IDD_GBASLOT_GUITARGRIP,
- IDD_GBASLOT_NONE, //expmem
+ IDD_GBASLOT_NONE, //expmem
IDD_GBASLOT_PIANO,
- IDD_GBASLOT_PADDLE, //paddle
- IDD_GBASLOT_NONE, //PassME
- IDD_GBASLOT_HCV1000, //HCV-1000
+ IDD_GBASLOT_PADDLE, //paddle
+ IDD_GBASLOT_NONE, //PassME
+ IDD_GBASLOT_HCV1000, //HCV-1000
+ IDD_GBASLOT_NONE, //Slide Controller
};
DLGPROC GBAslot_Procs[NDS_SLOT2_COUNT] = {
@@ -540,11 +541,12 @@ DLGPROC GBAslot_Procs[NDS_SLOT2_COUNT] = {
GbaSlotRumblePak,
GbaSlotGBAgame,
GbaSlotGuitarGrip,
- GbaSlotNone, //expmem
+ GbaSlotNone, //expmem
GbaSlotPiano,
GbaSlotPaddle,
- GbaSlotNone, // PassME
+ GbaSlotNone, // PassME
GbaSlotHCV1000, //HCV-1000
+ GbaSlotNone, //Slide Controller
};
@@ -696,6 +698,8 @@ void GBAslotDialog(HWND hwnd)
WritePrivateProfileString("Slot2.HCV1000", "barcode", tmp_hcv1000_barcode, IniName);
WritePrivateProfileInt("Slot2.HCV1000", "scankey", HCV1000.SCANKEY, IniName);
break;
+ case NDS_SLOT2_SLIDECONTROLLER:
+ break;
default:
return;
}
@@ -708,6 +712,7 @@ void GBAslotDialog(HWND hwnd)
Piano.Enabled = (slot2_GetCurrentType() == NDS_SLOT2_EASYPIANO)?true:false;
Paddle.Enabled = (slot2_GetCurrentType() == NDS_SLOT2_PADDLE)?true:false;
HCV1000.Enabled = (slot2_GetCurrentType() == NDS_SLOT2_HCV1000)?true:false;
+ SlideController.Enabled = (slot2_GetCurrentType() == NDS_SLOT2_SLIDECONTROLLER)?true:false;
}
}
diff --git a/desmume/src/frontend/windows/inputdx.cpp b/desmume/src/frontend/windows/inputdx.cpp
index c6a6b40a9..ecdbbcc48 100644
--- a/desmume/src/frontend/windows/inputdx.cpp
+++ b/desmume/src/frontend/windows/inputdx.cpp
@@ -261,6 +261,8 @@ SPaddle DefaultPaddle = { false, 'K', 'L' };
SHCV1000 HCV1000;
SHCV1000 DefaultHCV1000 = { false, 'L'};
+SSLIDECONTROLLER SlideController;
+
bool killStylusTopScreen = false;
bool killStylusOffScreen = false;
bool allowUpAndDown = false;
diff --git a/desmume/src/frontend/windows/inputdx.h b/desmume/src/frontend/windows/inputdx.h
index 5b23b2c3f..50611250d 100644
--- a/desmume/src/frontend/windows/inputdx.h
+++ b/desmume/src/frontend/windows/inputdx.h
@@ -158,10 +158,15 @@ struct SHCV1000 {
WORD SCANKEY;
};
+struct SSLIDECONTROLLER {
+ BOOL Enabled;
+};
+
extern SGuitar Guitar;
extern SPiano Piano;
extern SPaddle Paddle;
extern SHCV1000 HCV1000;
+extern SSLIDECONTROLLER SlideController;
#endif
diff --git a/desmume/src/frontend/windows/main.cpp b/desmume/src/frontend/windows/main.cpp
index 5588ace62..be90abb41 100644
--- a/desmume/src/frontend/windows/main.cpp
+++ b/desmume/src/frontend/windows/main.cpp
@@ -1581,6 +1581,7 @@ static BOOL LoadROM(const char * filename, const char * physicalName, const char
Piano.Enabled = (selectedSlot2Type == NDS_SLOT2_EASYPIANO)?true:false;
Paddle.Enabled = (selectedSlot2Type == NDS_SLOT2_PADDLE)?true:false;
HCV1000.Enabled = (selectedSlot2Type == NDS_SLOT2_HCV1000)?true:false;
+ SlideController.Enabled = (selectedSlot2Type == NDS_SLOT2_SLIDECONTROLLER)?true:false;
LoadSaveStateInfo();
lagframecounter=0;
@@ -2132,6 +2133,13 @@ int _main()
exit(-1);
}
+ RAWINPUTDEVICE rid = {};
+ rid.usUsagePage = 0x01;
+ rid.usUsage = 0x02;
+ rid.dwFlags = 0;
+ rid.hwndTarget = MainWindow->getHWnd();
+ RegisterRawInputDevices(&rid, 1, sizeof(rid));
+
//disable wacky stylus stuff
//TODO - we are obliged to call GlobalDeleteAtom
GlobalAddAtom(MICROSOFT_TABLETPENSERVICE_PROPERTY);
@@ -2264,6 +2272,8 @@ int _main()
break;
case NDS_SLOT2_HCV1000:
break;
+ case NDS_SLOT2_SLIDECONTROLLER:
+ break;
default:
slot2_device_type = NDS_SLOT2_NONE;
break;
@@ -2275,6 +2285,7 @@ int _main()
Piano.Enabled = (slot2_device_type == NDS_SLOT2_EASYPIANO)?true:false;
Paddle.Enabled = (slot2_device_type == NDS_SLOT2_PADDLE)?true:false;
HCV1000.Enabled = (slot2_device_type == NDS_SLOT2_HCV1000)?true:false;
+ SlideController.Enabled = (slot2_device_type == NDS_SLOT2_SLIDECONTROLLER)?true:false;
CommonSettings.WifiBridgeDeviceID = GetPrivateProfileInt("Wifi", "BridgeAdapter", 0, IniName);
@@ -4514,6 +4525,29 @@ DOKEYDOWN:
}
#endif
+ case WM_INPUT:
+ {
+ if (SlideController.Enabled)
+ {
+ UINT dataSize;
+ GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dataSize, sizeof(RAWINPUTHEADER));
+ LPBYTE rawdata = new BYTE[dataSize];
+ if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, rawdata, &dataSize, sizeof(RAWINPUTHEADER)) == dataSize)
+ {
+ RAWINPUT* raw = (RAWINPUT*)rawdata;
+ if (raw->header.dwType == RIM_TYPEMOUSE)
+ {
+ LONG xMotion = raw->data.mouse.lLastX;
+ LONG yMotion = raw->data.mouse.lLastY;
+ xMotion = max((LONG)-127, min(xMotion, (LONG)127));
+ yMotion = max((LONG)-127, min(yMotion, (LONG)127));
+ slideController_updateMotion(xMotion, -yMotion);
+ }
+ }
+ }
+ }
+ return 0;
+
case WM_COMMAND:
if(HIWORD(wParam) == 0 || HIWORD(wParam) == 1)
{
diff --git a/desmume/src/slot2.cpp b/desmume/src/slot2.cpp
index a947fe7b6..dd361aa08 100644
--- a/desmume/src/slot2.cpp
+++ b/desmume/src/slot2.cpp
@@ -59,18 +59,20 @@ void slot2_Init()
extern TISlot2InterfaceConstructor construct_Slot2_Paddle;
extern TISlot2InterfaceConstructor construct_Slot2_PassME;
extern TISlot2InterfaceConstructor construct_Slot2_HCV1000;
+ extern TISlot2InterfaceConstructor construct_Slot2_SlideController;
- slot2_List[NDS_SLOT2_NONE] = construct_Slot2_None();
- slot2_List[NDS_SLOT2_AUTO] = construct_Slot2_Auto();
- slot2_List[NDS_SLOT2_CFLASH] = construct_Slot2_CFlash();
- slot2_List[NDS_SLOT2_RUMBLEPAK] = construct_Slot2_RumblePak();
- slot2_List[NDS_SLOT2_GBACART] = construct_Slot2_GbaCart();
- slot2_List[NDS_SLOT2_GUITARGRIP] = construct_Slot2_GuitarGrip();
- slot2_List[NDS_SLOT2_EXPMEMORY] = construct_Slot2_ExpansionPak();
- slot2_List[NDS_SLOT2_EASYPIANO] = construct_Slot2_EasyPiano();
- slot2_List[NDS_SLOT2_PADDLE] = construct_Slot2_Paddle();
- slot2_List[NDS_SLOT2_PASSME] = construct_Slot2_PassME();
- slot2_List[NDS_SLOT2_HCV1000] = construct_Slot2_HCV1000();
+ slot2_List[NDS_SLOT2_NONE] = construct_Slot2_None();
+ slot2_List[NDS_SLOT2_AUTO] = construct_Slot2_Auto();
+ slot2_List[NDS_SLOT2_CFLASH] = construct_Slot2_CFlash();
+ slot2_List[NDS_SLOT2_RUMBLEPAK] = construct_Slot2_RumblePak();
+ slot2_List[NDS_SLOT2_GBACART] = construct_Slot2_GbaCart();
+ slot2_List[NDS_SLOT2_GUITARGRIP] = construct_Slot2_GuitarGrip();
+ slot2_List[NDS_SLOT2_EXPMEMORY] = construct_Slot2_ExpansionPak();
+ slot2_List[NDS_SLOT2_EASYPIANO] = construct_Slot2_EasyPiano();
+ slot2_List[NDS_SLOT2_PADDLE] = construct_Slot2_Paddle();
+ slot2_List[NDS_SLOT2_PASSME] = construct_Slot2_PassME();
+ slot2_List[NDS_SLOT2_HCV1000] = construct_Slot2_HCV1000();
+ slot2_List[NDS_SLOT2_SLIDECONTROLLER] = construct_Slot2_SlideController();
}
@@ -257,6 +259,7 @@ NDS_SLOT2_TYPE slot2_DetermineTypeByGameCode(const char *theGameCode)
{"C4A", NDS_SLOT2_HCV1000}, // Card de Asobu! Hajimete no DS
{"A6I", NDS_SLOT2_HCV1000}, // Kouchuu Ouja: Mushi King Super Collection
{"ALB", NDS_SLOT2_HCV1000}, // Oshare Majo Berry and Love
+ {"AGU", NDS_SLOT2_SLIDECONTROLLER}, // Slide Adventure MAGKID
};
for(size_t i = 0; i < ARRAY_SIZE(gameCodeDeviceTypes); i++)
diff --git a/desmume/src/slot2.h b/desmume/src/slot2.h
index 66f84f708..634c4048a 100644
--- a/desmume/src/slot2.h
+++ b/desmume/src/slot2.h
@@ -87,18 +87,19 @@ typedef ISlot2Interface* TISlot2InterfaceConstructor();
enum NDS_SLOT2_TYPE
{
- NDS_SLOT2_NONE, // 0xFF
- NDS_SLOT2_AUTO, // 0xFE - Auto-select
- NDS_SLOT2_CFLASH, // 0x01 - Compact flash
- NDS_SLOT2_RUMBLEPAK, // 0x02 - RumblePak
- NDS_SLOT2_GBACART, // 0x03 - GBA cartrindge in slot
- NDS_SLOT2_GUITARGRIP, // 0x04 - Guitar Grip
- NDS_SLOT2_EXPMEMORY, // 0x05 - Memory Expansion Pak
- NDS_SLOT2_EASYPIANO, // 0x06 - Easy Piano
- NDS_SLOT2_PADDLE, // 0x07 - Arkanoids DS paddle
- NDS_SLOT2_PASSME, // 0x08 - PassME/Homebrew
- NDS_SLOT2_HCV1000, // 0x09 - HCV-1000 Sega Card Reader
- NDS_SLOT2_COUNT // use for counter addons - MUST TO BE LAST!!!
+ NDS_SLOT2_NONE, // 0xFF
+ NDS_SLOT2_AUTO, // 0xFE - Auto-select
+ NDS_SLOT2_CFLASH, // 0x01 - Compact flash
+ NDS_SLOT2_RUMBLEPAK, // 0x02 - RumblePak
+ NDS_SLOT2_GBACART, // 0x03 - GBA cartrindge in slot
+ NDS_SLOT2_GUITARGRIP, // 0x04 - Guitar Grip
+ NDS_SLOT2_EXPMEMORY, // 0x05 - Memory Expansion Pak
+ NDS_SLOT2_EASYPIANO, // 0x06 - Easy Piano
+ NDS_SLOT2_PADDLE, // 0x07 - Arkanoids DS paddle
+ NDS_SLOT2_PASSME, // 0x08 - PassME/Homebrew
+ NDS_SLOT2_HCV1000, // 0x09 - HCV-1000 Sega Card Reader
+ NDS_SLOT2_SLIDECONTROLLER, // 0x0A - Slide Controller
+ NDS_SLOT2_COUNT // use for counter addons - MUST TO BE LAST!!!
};
extern ISlot2Interface* slot2_device; //the current slot2 device instance
@@ -160,4 +161,5 @@ extern void guitarGrip_setKey(bool green, bool red, bool yellow, bool blue); //
extern void piano_setKey(bool c, bool cs, bool d, bool ds, bool e, bool f, bool fs, bool g, bool gs, bool a, bool as, bool b, bool hic); //piano keys
extern void HCV1000_setReady();
extern void HCV1000_setBarcode(std::string barcode);
+extern void slideController_updateMotion(s8 x, s8 y);
#endif //__SLOT_H__
From c3cdf8b41230061333f0a7dfcfb41dca3c36f39d Mon Sep 17 00:00:00 2001
From: windwakr <284886+windwakr@users.noreply.github.com>
Date: Tue, 10 Oct 2023 23:26:29 -0400
Subject: [PATCH 2/7] Slot2: rewrite Slide Controller
---
desmume/src/addons/slot2_slideController.cpp | 329 +++++++++----------
1 file changed, 149 insertions(+), 180 deletions(-)
diff --git a/desmume/src/addons/slot2_slideController.cpp b/desmume/src/addons/slot2_slideController.cpp
index b75cae51c..b07578a22 100644
--- a/desmume/src/addons/slot2_slideController.cpp
+++ b/desmume/src/addons/slot2_slideController.cpp
@@ -1,3 +1,6 @@
+//Serial handling code heavily inspired by the Magic Reader code in GBE+
+//https://github.com/shonumi/gbe-plus/blob/7986317958a672d72ff54ea33f31bcca13cf8330/src/nds/slot2.cpp#L155
+
/*
Copyright (C) 2023 DeSmuME team
@@ -21,34 +24,127 @@
#include "../slot2.h"
#include "../emufile.h"
-#define SC_BITIN(X, Y) \
-do { \
- X = (X << 1) | (Y & 1); \
- bitsWritten++; \
-} while (0)
-
-#define SC_BITOUT(X, Y) \
-do { \
- X = ((Y >> 7 - bitsRead) & 1); \
- bitsRead++; \
-} while(0)
-
-u8 motionStatus;
-u8 xMotion;
-u8 yMotion;
+//Product ID, Revision ID, Motion status, X delta, Y delta, Surface quality
+//Average pixel, Maximum pixel, Reserved, Reserved, Configuration, Reserved
+//Data out lower, Data out upper, Shutter lower, Shutter upper, Frame period lower, Frame period upper
+static u8 scRegs[18] = { 0x03, 0x20, 0x00, 0x00, 0x00, 0x80, 0x20, 0x3F, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x20, 0xD1 };
class Slot2_SlideController : public ISlot2Interface
{
private:
- u8 prevClock;
- u8 bitsWritten;
- u8 bitsRead;
- u8 inByte;
- u16 regSel;
+ struct slideControllerSerial
+ {
+ u16 in_data;
+ u16 out_data;
+ u8 counter;
+ u8 state;
+ u8 sck;
+ u8 reg_sel;
+ u8 tmp;
+ } slideCon = {};
+
+ void slideCon_reset()
+ {
+ slideCon.in_data = 0;
+ slideCon.out_data = 0;
+ slideCon.counter = 0;
+ slideCon.state = 0;
+ slideCon.sck = 0;
+ slideCon.reg_sel = 0;
+ slideCon.tmp = 0;
+
+ scRegs[0x02] = 0x00; //Motion status
+ scRegs[0x03] = 0x00; //X delta
+ scRegs[0x04] = 0x00; //Y delta
+ scRegs[0x0A] = 0x00; //Config bits
+ scRegs[0x10] = 0x20; //Frame period lower
+ scRegs[0x11] = 0xD1; //Frame period upper
+ }
+
+ void slideCon_process()
+ {
+ //Serial clock in bit 1
+ u8 new_sck = (slideCon.in_data & 0x2) >> 1;
+ //Serial data in bit 0
+ u8 sd = slideCon.in_data & 0x1;
+
+ switch (slideCon.state)
+ {
+ case 0: //reg select
+ //build reg select byte
+ if ((slideCon.sck == 0) && (new_sck == 1) && (slideCon.counter < 8))
+ {
+ slideCon.reg_sel = (slideCon.reg_sel << 1) | sd;
+ slideCon.counter++;
+ }
+ else if (slideCon.counter == 8)
+ {
+ //check if it's a read or a write by MSB
+ if (slideCon.reg_sel & 0x80)
+ {
+ slideCon.state = 1;
+ slideCon.reg_sel &= 0x7F;
+ slideCon.tmp = 0;
+ }
+ else
+ {
+ slideCon.state = 2;
+ }
+ slideCon.counter = 0;
+ }
+
+
+ break;
+ case 1: //write reg
+ if ((slideCon.sck == 0) && (new_sck == 1) && (slideCon.counter < 8))
+ {
+ slideCon.tmp = (slideCon.tmp << 1) | sd;
+ slideCon.counter++;
+ }
+ else if ((slideCon.sck == 0) && (new_sck == 0) && (slideCon.counter == 8))
+ {
+ //printf("WRITE REG: %02X = %02X\n", slideCon.reg_sel, slideCon.tmp);
+ slideCon.state = 0;
+ slideCon.counter = 0;
+
+ if (slideCon.reg_sel <= 0x11)
+ scRegs[slideCon.reg_sel] = slideCon.tmp;
+ }
+ break;
+ case 2: //read reg
+ if ((slideCon.sck == 0) && (new_sck == 1) && (slideCon.counter < 8))
+ {
+ if (slideCon.reg_sel <= 0x11)
+ slideCon.out_data = (scRegs[slideCon.reg_sel] >> (7 - slideCon.counter)) & 1;
+ else
+ slideCon.out_data = 0;
+ slideCon.counter++;
+ }
+ else if ((slideCon.sck == 0) && (new_sck == 0) && (slideCon.counter == 8))
+ {
+ //printf("READ REG: %02X = %02X\n", slideCon.reg_sel, scRegs[slideCon.reg_sel]);
+ slideCon.state = 0;
+ slideCon.counter = 0;
+
+ //Reset motion flag if reg was motion status
+ if (slideCon.reg_sel == 0x02)
+ scRegs[0x02] &= 0x7F;
+ //Reset motion deltas if they were read
+ if ((slideCon.reg_sel == 0x03) || (slideCon.reg_sel == 0x04))
+ scRegs[slideCon.reg_sel] = 0x00;
+ }
+ break;
+ }
+
+ slideCon.sck = new_sck;
+
+ if (scRegs[0x0A] & 0x80) //Reset
+ {
+ slideCon_reset();
+ }
+ }
- u8 configBits;
- u8 framePeriodLower;
- u8 framePeriodUpper;
public:
virtual Slot2Info const* info()
@@ -59,152 +155,34 @@ public:
virtual void connect()
{
- prevClock = 0;
- bitsWritten = 0;
- bitsRead = 0;
- inByte = 0;
- regSel = 0xFFFF;
-
- motionStatus = 0;
- xMotion = 0;
- yMotion = 0;
- configBits = 0;
- framePeriodLower = 0x20;
- framePeriodUpper = 0xD1;
+ slideCon_reset();
}
virtual void writeWord(u8 PROCNUM, u32 addr, u16 val)
{
if (addr == 0x081E0000)
{
- if ((prevClock == 0) && (val & 0x2) && (val & 0x8))
- {
- SC_BITIN(inByte, val);
- if (bitsWritten == 8)
- {
- bitsWritten = 0;
- if (regSel == 0xFFFF) //First byte written
- {
- regSel = inByte;
- }
- else //Second byte written
- {
- //printf("WRITE TO REG: %02X = %02X\n", regSel & 0x7F , inByte);
- switch (regSel & 0x7F)
- {
- case 0x0A: //Config bits
- configBits = inByte;
- break;
- case 0x10: //Frame period (lower)
- framePeriodLower = inByte;
- break;
- case 0x11: //Frame period(upper)
- framePeriodUpper = inByte;
- break;
- }
- regSel = 0xFFFF;
- }
- }
- }
- prevClock = (val & 0x2) >> 1;
- }
-
- if (configBits & 0x80) //Reset
- {
- motionStatus = 0;
- xMotion = 0;
- yMotion = 0;
- configBits = 0;
- framePeriodLower = 0x20;
- framePeriodUpper = 0xD1;
-
- prevClock = 0;
- bitsWritten = 0;
- bitsRead = 0;
- inByte = 0;
- regSel = 0xFFFF;
+ slideCon.in_data = val;
+ slideCon_process();
}
}
virtual u8 readByte(u8 PROCNUM, u32 addr)
{
if (addr == 0x080000B2)
- {
return 0x96;
- }
- return 0xFF;
+ else
+ return 0xFF;
}
virtual u16 readWord(u8 PROCNUM, u32 addr)
{
- u16 outWord = 0;
+ u16 outWord = 0xFFFF;
if (addr < 0x08000100)
- {
outWord = 0xFEF0;
- }
-
- if (addr == 0x081E0000)
- {
- switch (regSel)
- {
- case 0x00: //Product ID
- SC_BITOUT(outWord, 0x3);
- break;
- case 0x01: //Revision ID
- SC_BITOUT(outWord, 0x20); //Is this correct?
- break;
- case 0x02: //Motion status
- SC_BITOUT(outWord, motionStatus);
- if (bitsRead == 8) motionStatus = 0;
- break;
- case 0x03: //X motion delta
- SC_BITOUT(outWord, xMotion);
- if (bitsRead == 8) xMotion = 0;
- break;
- case 0x04: //Y motion delta
- SC_BITOUT(outWord, yMotion);
- if (bitsRead == 8) yMotion = 0;
- break;
- case 0x05: //Surface quality
- SC_BITOUT(outWord, 128);
- break;
- case 0x06: //Average pixel
- SC_BITOUT(outWord, 32);
- break;
- case 0x07: //Maximum pixel
- SC_BITOUT(outWord, 63);
- break;
- case 0x0A: //Configuration bits
- SC_BITOUT(outWord, configBits);
- break;
- case 0x0C: //Data out (lower)
- SC_BITOUT(outWord, 0);
- break;
- case 0x0D: //Data out (upper)
- SC_BITOUT(outWord, 0);
- break;
- case 0x0E: //Shutter value (lower)
- SC_BITOUT(outWord, 64);
- break;
- case 0x0F: //Shutter value (upper)
- SC_BITOUT(outWord, 0);
- break;
- case 0x10: //Frame period (lower)
- SC_BITOUT(outWord, framePeriodLower);
- break;
- case 0x11: //Frame period (upper)
- SC_BITOUT(outWord, framePeriodUpper);
- break;
- }
-
- if (bitsRead == 8)
- {
- bitsRead = 0;
- //printf("READ FROM REG: %02X\n", regSel);
- regSel = 0xFFFF;
- }
- }
+ else if (addr == 0x081E0000)
+ outWord = slideCon.out_data;
return outWord;
}
@@ -214,18 +192,15 @@ public:
s32 version = 0;
os.write_32LE(version);
- os.write_u8(prevClock);
- os.write_u8(bitsWritten);
- os.write_u8(bitsRead);
- os.write_u8(inByte);
- os.write_16LE(regSel);
-
- os.write_u8(configBits);
- os.write_u8(framePeriodLower);
- os.write_u8(framePeriodUpper);
- os.write_u8(motionStatus);
- os.write_u8(xMotion);
- os.write_u8(yMotion);
+ for (int i = 0; i < 18; i++)
+ os.write_u8(scRegs[i]);
+ os.write_16LE(slideCon.in_data);
+ os.write_16LE(slideCon.out_data);
+ os.write_u8(slideCon.counter);
+ os.write_u8(slideCon.state);
+ os.write_u8(slideCon.sck);
+ os.write_u8(slideCon.reg_sel);
+ os.write_u8(slideCon.tmp);
}
virtual void loadstate(EMUFILE& is)
@@ -234,18 +209,15 @@ public:
if (version == 0)
{
- is.read_u8(prevClock);
- is.read_u8(bitsWritten);
- is.read_u8(bitsRead);
- is.read_u8(inByte);
- is.read_16LE(regSel);
-
- is.read_u8(configBits);
- is.read_u8(framePeriodLower);
- is.read_u8(framePeriodUpper);
- is.read_u8(motionStatus);
- is.read_u8(xMotion);
- is.read_u8(yMotion);
+ for (int i = 0; i < 18; i++)
+ scRegs[i] = is.read_u8();
+ is.read_16LE(slideCon.in_data);
+ is.read_16LE(slideCon.out_data);
+ is.read_u8(slideCon.counter);
+ is.read_u8(slideCon.state);
+ is.read_u8(slideCon.sck);
+ is.read_u8(slideCon.reg_sel);
+ is.read_u8(slideCon.tmp);
}
}
};
@@ -254,11 +226,8 @@ ISlot2Interface* construct_Slot2_SlideController() { return new Slot2_SlideContr
void slideController_updateMotion(s8 x, s8 y)
{
- xMotion = (u8)x;
- yMotion = (u8)y;
- if (xMotion || yMotion)
- motionStatus = 0x80;
+ scRegs[0x03] = (u8)x;
+ scRegs[0x04] = (u8)y;
+ if (scRegs[0x03] || scRegs[0x04])
+ scRegs[0x02] |= 0x80;
}
-
-#undef SC_BITIN
-#undef SC_BITOUT
From b6cc718d8101dbed74dea34ae0701b41b91e8bb3 Mon Sep 17 00:00:00 2001
From: windwakr <284886+windwakr@users.noreply.github.com>
Date: Wed, 11 Oct 2023 18:31:28 -0400
Subject: [PATCH 3/7] Slot2: Slide Controller fixes
---
desmume/src/addons/slot2_slideController.cpp | 10 +++--
desmume/src/frontend/windows/main.cpp | 41 ++++++++++----------
2 files changed, 27 insertions(+), 24 deletions(-)
diff --git a/desmume/src/addons/slot2_slideController.cpp b/desmume/src/addons/slot2_slideController.cpp
index b07578a22..fd3a0141a 100644
--- a/desmume/src/addons/slot2_slideController.cpp
+++ b/desmume/src/addons/slot2_slideController.cpp
@@ -226,8 +226,10 @@ ISlot2Interface* construct_Slot2_SlideController() { return new Slot2_SlideContr
void slideController_updateMotion(s8 x, s8 y)
{
- scRegs[0x03] = (u8)x;
- scRegs[0x04] = (u8)y;
- if (scRegs[0x03] || scRegs[0x04])
- scRegs[0x02] |= 0x80;
+ if (x || y)
+ {
+ scRegs[0x03] = (u8)x;
+ scRegs[0x04] = (u8)y;
+ scRegs[0x02] |= 0x80; //Set motion flag in the motion status register
+ }
}
diff --git a/desmume/src/frontend/windows/main.cpp b/desmume/src/frontend/windows/main.cpp
index be90abb41..2311862c0 100644
--- a/desmume/src/frontend/windows/main.cpp
+++ b/desmume/src/frontend/windows/main.cpp
@@ -2133,12 +2133,13 @@ int _main()
exit(-1);
}
- RAWINPUTDEVICE rid = {};
- rid.usUsagePage = 0x01;
- rid.usUsage = 0x02;
- rid.dwFlags = 0;
- rid.hwndTarget = MainWindow->getHWnd();
- RegisterRawInputDevices(&rid, 1, sizeof(rid));
+ //Raw input for the Slide Controller add-on
+ RAWINPUTDEVICE Rid[1];
+ Rid[0].usUsagePage = 0x01;
+ Rid[0].usUsage = 0x02;
+ Rid[0].dwFlags = 0x00;
+ Rid[0].hwndTarget = MainWindow->getHWnd();
+ RegisterRawInputDevices(Rid, 1, sizeof(Rid[0]));
//disable wacky stylus stuff
//TODO - we are obliged to call GlobalDeleteAtom
@@ -4529,24 +4530,24 @@ DOKEYDOWN:
{
if (SlideController.Enabled)
{
- UINT dataSize;
- GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dataSize, sizeof(RAWINPUTHEADER));
- LPBYTE rawdata = new BYTE[dataSize];
- if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, rawdata, &dataSize, sizeof(RAWINPUTHEADER)) == dataSize)
+ UINT dwSize = sizeof(RAWINPUT);
+ static BYTE lpb[sizeof(RAWINPUT)];
+
+ GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER));
+
+ RAWINPUT* raw = (RAWINPUT*)lpb;
+
+ if (raw->header.dwType == RIM_TYPEMOUSE)
{
- RAWINPUT* raw = (RAWINPUT*)rawdata;
- if (raw->header.dwType == RIM_TYPEMOUSE)
- {
- LONG xMotion = raw->data.mouse.lLastX;
- LONG yMotion = raw->data.mouse.lLastY;
- xMotion = max((LONG)-127, min(xMotion, (LONG)127));
- yMotion = max((LONG)-127, min(yMotion, (LONG)127));
- slideController_updateMotion(xMotion, -yMotion);
- }
+ int xMotion = raw->data.mouse.lLastX;
+ int yMotion = raw->data.mouse.lLastY;
+ xMotion = max(-127, min(xMotion, 127));
+ yMotion = max(-127, min(yMotion, 127));
+ slideController_updateMotion(xMotion, -yMotion);
}
+ return 0;
}
}
- return 0;
case WM_COMMAND:
if(HIWORD(wParam) == 0 || HIWORD(wParam) == 1)
From 199f69d3b33311e9193becb8f1469487127ed021 Mon Sep 17 00:00:00 2001
From: windwakr <284886+windwakr@users.noreply.github.com>
Date: Wed, 11 Oct 2023 19:32:02 -0400
Subject: [PATCH 4/7] Slot2: Slide Controller fixes
---
desmume/src/addons/slot2_slideController.cpp | 34 ++++++++++++++++----
1 file changed, 27 insertions(+), 7 deletions(-)
diff --git a/desmume/src/addons/slot2_slideController.cpp b/desmume/src/addons/slot2_slideController.cpp
index fd3a0141a..496e4bce1 100644
--- a/desmume/src/addons/slot2_slideController.cpp
+++ b/desmume/src/addons/slot2_slideController.cpp
@@ -24,11 +24,16 @@
#include "../slot2.h"
#include "../emufile.h"
+static u8 xDelta;
+static u8 yDelta;
//Product ID, Revision ID, Motion status, X delta, Y delta, Surface quality
//Average pixel, Maximum pixel, Reserved, Reserved, Configuration, Reserved
//Data out lower, Data out upper, Shutter lower, Shutter upper, Frame period lower, Frame period upper
-static u8 scRegs[18] = { 0x03, 0x20, 0x00, 0x00, 0x00, 0x80, 0x20, 0x3F, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x20, 0xD1 };
+static u8 scRegs[18] =
+{ 0x03, 0x20, 0x00, 0x00, 0x00, 0x80,
+ 0x20, 0x3F, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x64, 0x00, 0x20, 0xD1
+};
class Slot2_SlideController : public ISlot2Interface
{
@@ -46,6 +51,9 @@ private:
void slideCon_reset()
{
+ xDelta = 0;
+ yDelta = 0;
+
slideCon.in_data = 0;
slideCon.out_data = 0;
slideCon.counter = 0;
@@ -90,11 +98,20 @@ private:
else
{
slideCon.state = 2;
+
+ if (slideCon.reg_sel == 0x02)
+ {
+ //set motion flag if there has been movement
+ if (xDelta || yDelta)
+ scRegs[0x02] |= 0x80;
+ //freeze motion deltas
+ scRegs[0x03] = xDelta;
+ scRegs[0x04] = yDelta;
+ xDelta = yDelta = 0;
+ }
}
slideCon.counter = 0;
}
-
-
break;
case 1: //write reg
if ((slideCon.sck == 0) && (new_sck == 1) && (slideCon.counter < 8))
@@ -192,6 +209,8 @@ public:
s32 version = 0;
os.write_32LE(version);
+ os.write_u8(xDelta);
+ os.write_u8(yDelta);
for (int i = 0; i < 18; i++)
os.write_u8(scRegs[i]);
os.write_16LE(slideCon.in_data);
@@ -209,6 +228,8 @@ public:
if (version == 0)
{
+ is.read_u8(xDelta);
+ is.read_u8(yDelta);
for (int i = 0; i < 18; i++)
scRegs[i] = is.read_u8();
is.read_16LE(slideCon.in_data);
@@ -228,8 +249,7 @@ void slideController_updateMotion(s8 x, s8 y)
{
if (x || y)
{
- scRegs[0x03] = (u8)x;
- scRegs[0x04] = (u8)y;
- scRegs[0x02] |= 0x80; //Set motion flag in the motion status register
+ xDelta = (u8)x;
+ yDelta = (u8)y;
}
}
From 3f708ff53f2600f647056ab56a53c1e1d065e279 Mon Sep 17 00:00:00 2001
From: windwakr
Date: Wed, 11 Oct 2023 20:21:23 -0400
Subject: [PATCH 5/7] whoops
---
desmume/src/frontend/windows/main.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/desmume/src/frontend/windows/main.cpp b/desmume/src/frontend/windows/main.cpp
index 2311862c0..a3485210c 100644
--- a/desmume/src/frontend/windows/main.cpp
+++ b/desmume/src/frontend/windows/main.cpp
@@ -4548,6 +4548,7 @@ DOKEYDOWN:
return 0;
}
}
+ break;
case WM_COMMAND:
if(HIWORD(wParam) == 0 || HIWORD(wParam) == 1)
From 4add68c92ea27f643868f074633b5c97ce344582 Mon Sep 17 00:00:00 2001
From: windwakr <284886+windwakr@users.noreply.github.com>
Date: Wed, 11 Oct 2023 22:14:58 -0400
Subject: [PATCH 6/7] Slot2: Slide Controller - add rumble
Must be explicitly enabled by frontent
---
desmume/src/addons/slot2_rumblepak.cpp | 2 --
desmume/src/addons/slot2_slideController.cpp | 35 +++++++++++++++++++-
desmume/src/frontend/windows/main.cpp | 2 ++
desmume/src/slot2.cpp | 2 ++
desmume/src/slot2.h | 1 +
5 files changed, 39 insertions(+), 3 deletions(-)
diff --git a/desmume/src/addons/slot2_rumblepak.cpp b/desmume/src/addons/slot2_rumblepak.cpp
index e4c471900..e76c28127 100644
--- a/desmume/src/addons/slot2_rumblepak.cpp
+++ b/desmume/src/addons/slot2_rumblepak.cpp
@@ -18,8 +18,6 @@
#include "../slot2.h"
-void (*FeedbackON)(bool enable) = NULL;
-
class Slot2_RumblePak : public ISlot2Interface
{
private:
diff --git a/desmume/src/addons/slot2_slideController.cpp b/desmume/src/addons/slot2_slideController.cpp
index 496e4bce1..1d9a0bdee 100644
--- a/desmume/src/addons/slot2_slideController.cpp
+++ b/desmume/src/addons/slot2_slideController.cpp
@@ -18,12 +18,14 @@
along with the this software. If not, see .
*/
-//Absolute barebones implementation of the Slide Controller add-on. Rumble is not implemented.
+//Absolute barebones implementation of the Slide Controller add-on.
//The game does a bunch of mystery reads of various sizes which have not been investigated at all.
#include "../slot2.h"
#include "../emufile.h"
+static bool rumbleEnable = false;
+
static u8 xDelta;
static u8 yDelta;
//Product ID, Revision ID, Motion status, X delta, Y delta, Surface quality
@@ -38,6 +40,8 @@ static u8 scRegs[18] =
class Slot2_SlideController : public ISlot2Interface
{
private:
+ u8 old_rumble;
+
struct slideControllerSerial
{
u16 in_data;
@@ -51,6 +55,10 @@ private:
void slideCon_reset()
{
+ old_rumble = 0;
+ if (FeedbackON)
+ FeedbackON(false);
+
xDelta = 0;
yDelta = 0;
@@ -76,6 +84,14 @@ private:
u8 new_sck = (slideCon.in_data & 0x2) >> 1;
//Serial data in bit 0
u8 sd = slideCon.in_data & 0x1;
+ //Rumble in bit 8
+ u8 rumble = (slideCon.in_data & 0x100) >> 8;
+
+ if (FeedbackON && rumbleEnable && (old_rumble != rumble))
+ {
+ old_rumble = rumble;
+ FeedbackON(rumble);
+ }
switch (slideCon.state)
{
@@ -175,6 +191,12 @@ public:
slideCon_reset();
}
+ virtual void disconnect()
+ {
+ if (FeedbackON)
+ FeedbackON(false);
+ }
+
virtual void writeWord(u8 PROCNUM, u32 addr, u16 val)
{
if (addr == 0x081E0000)
@@ -240,6 +262,10 @@ public:
is.read_u8(slideCon.reg_sel);
is.read_u8(slideCon.tmp);
}
+
+ old_rumble = 0;
+ if (FeedbackON)
+ FeedbackON(false);
}
};
@@ -253,3 +279,10 @@ void slideController_updateMotion(s8 x, s8 y)
yDelta = (u8)y;
}
}
+
+void slideController_rumbleEnable(bool enable)
+{
+ rumbleEnable = enable;
+ if (FeedbackON && (enable == false))
+ FeedbackON(false);
+}
diff --git a/desmume/src/frontend/windows/main.cpp b/desmume/src/frontend/windows/main.cpp
index a3485210c..b37bb0ac3 100644
--- a/desmume/src/frontend/windows/main.cpp
+++ b/desmume/src/frontend/windows/main.cpp
@@ -2211,6 +2211,8 @@ int _main()
slot2_HCV1000_barcode = GetPrivateProfileStdString("Slot2.HCV1000", "barcode", "").substr(0, 16);
HCV1000_setBarcode(slot2_HCV1000_barcode);
+ slideController_rumbleEnable(GetPrivateProfileBool("Slot2.SlideController", "rumble", false, IniName));
+
cmdline.process_addonCommands();
WIN_InstallCFlash();
WIN_InstallGBACartridge();
diff --git a/desmume/src/slot2.cpp b/desmume/src/slot2.cpp
index dd361aa08..2ab33753f 100644
--- a/desmume/src/slot2.cpp
+++ b/desmume/src/slot2.cpp
@@ -33,6 +33,8 @@ std::string CFlash_Path;
std::string GBACartridge_RomPath;
std::string GBACartridge_SRAMPath;
+void (*FeedbackON)(bool enable) = NULL;
+
ISlot2Interface* slot2_List[NDS_SLOT2_COUNT] = {0};
ISlot2Interface* slot2_device = NULL;
diff --git a/desmume/src/slot2.h b/desmume/src/slot2.h
index 634c4048a..0e95b01d1 100644
--- a/desmume/src/slot2.h
+++ b/desmume/src/slot2.h
@@ -162,4 +162,5 @@ extern void piano_setKey(bool c, bool cs, bool d, bool ds, bool e, bool f, bool
extern void HCV1000_setReady();
extern void HCV1000_setBarcode(std::string barcode);
extern void slideController_updateMotion(s8 x, s8 y);
+extern void slideController_rumbleEnable(bool enable);
#endif //__SLOT_H__
From b4225f436a4b2210d3695f1d8d0dbd9f516d5aaa Mon Sep 17 00:00:00 2001
From: windwakr <284886+windwakr@users.noreply.github.com>
Date: Thu, 12 Oct 2023 22:14:09 -0400
Subject: [PATCH 7/7] Slot2: Slide Controller - rumble Rumble is now always
allowed. Turns out there's an in-game option to turn it off so there's no
need for this.
---
desmume/src/addons/slot2_slideController.cpp | 97 +++++++++-----------
desmume/src/frontend/windows/main.cpp | 2 -
desmume/src/slot2.h | 1 -
3 files changed, 43 insertions(+), 57 deletions(-)
diff --git a/desmume/src/addons/slot2_slideController.cpp b/desmume/src/addons/slot2_slideController.cpp
index 1d9a0bdee..5e09ea18d 100644
--- a/desmume/src/addons/slot2_slideController.cpp
+++ b/desmume/src/addons/slot2_slideController.cpp
@@ -19,19 +19,16 @@
*/
//Absolute barebones implementation of the Slide Controller add-on.
-//The game does a bunch of mystery reads of various sizes which have not been investigated at all.
#include "../slot2.h"
#include "../emufile.h"
-static bool rumbleEnable = false;
-
-static u8 xDelta;
-static u8 yDelta;
+static u8 delta_x;
+static u8 delta_y;
//Product ID, Revision ID, Motion status, X delta, Y delta, Surface quality
//Average pixel, Maximum pixel, Reserved, Reserved, Configuration, Reserved
//Data out lower, Data out upper, Shutter lower, Shutter upper, Frame period lower, Frame period upper
-static u8 scRegs[18] =
+static u8 sc_regs[18] =
{ 0x03, 0x20, 0x00, 0x00, 0x00, 0x80,
0x20, 0x3F, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x64, 0x00, 0x20, 0xD1
@@ -42,7 +39,7 @@ class Slot2_SlideController : public ISlot2Interface
private:
u8 old_rumble;
- struct slideControllerSerial
+ struct
{
u16 in_data;
u16 out_data;
@@ -55,13 +52,13 @@ private:
void slideCon_reset()
{
+ delta_x = 0;
+ delta_y = 0;
+
old_rumble = 0;
if (FeedbackON)
FeedbackON(false);
- xDelta = 0;
- yDelta = 0;
-
slideCon.in_data = 0;
slideCon.out_data = 0;
slideCon.counter = 0;
@@ -70,12 +67,12 @@ private:
slideCon.reg_sel = 0;
slideCon.tmp = 0;
- scRegs[0x02] = 0x00; //Motion status
- scRegs[0x03] = 0x00; //X delta
- scRegs[0x04] = 0x00; //Y delta
- scRegs[0x0A] = 0x00; //Config bits
- scRegs[0x10] = 0x20; //Frame period lower
- scRegs[0x11] = 0xD1; //Frame period upper
+ sc_regs[0x02] = 0x00; //Motion status
+ sc_regs[0x03] = 0x00; //X delta
+ sc_regs[0x04] = 0x00; //Y delta
+ sc_regs[0x0A] = 0x00; //Config bits
+ sc_regs[0x10] = 0x20; //Frame period lower
+ sc_regs[0x11] = 0xD1; //Frame period upper
}
void slideCon_process()
@@ -87,7 +84,7 @@ private:
//Rumble in bit 8
u8 rumble = (slideCon.in_data & 0x100) >> 8;
- if (FeedbackON && rumbleEnable && (old_rumble != rumble))
+ if (FeedbackON && (old_rumble != rumble))
{
old_rumble = rumble;
FeedbackON(rumble);
@@ -95,8 +92,8 @@ private:
switch (slideCon.state)
{
- case 0: //reg select
- //build reg select byte
+ case 0: //Reg select
+ //Build reg select byte
if ((slideCon.sck == 0) && (new_sck == 1) && (slideCon.counter < 8))
{
slideCon.reg_sel = (slideCon.reg_sel << 1) | sd;
@@ -104,7 +101,7 @@ private:
}
else if (slideCon.counter == 8)
{
- //check if it's a read or a write by MSB
+ //Check if it's a read or a write by MSB
if (slideCon.reg_sel & 0x80)
{
slideCon.state = 1;
@@ -117,19 +114,19 @@ private:
if (slideCon.reg_sel == 0x02)
{
- //set motion flag if there has been movement
- if (xDelta || yDelta)
- scRegs[0x02] |= 0x80;
- //freeze motion deltas
- scRegs[0x03] = xDelta;
- scRegs[0x04] = yDelta;
- xDelta = yDelta = 0;
+ //Set motion flag if there has been movement
+ if (delta_x || delta_y)
+ sc_regs[0x02] |= 0x80;
+ //Freeze motion deltas
+ sc_regs[0x03] = delta_x;
+ sc_regs[0x04] = delta_y;
+ delta_x = delta_y = 0;
}
}
slideCon.counter = 0;
}
break;
- case 1: //write reg
+ case 1: //Write reg
if ((slideCon.sck == 0) && (new_sck == 1) && (slideCon.counter < 8))
{
slideCon.tmp = (slideCon.tmp << 1) | sd;
@@ -137,42 +134,42 @@ private:
}
else if ((slideCon.sck == 0) && (new_sck == 0) && (slideCon.counter == 8))
{
- //printf("WRITE REG: %02X = %02X\n", slideCon.reg_sel, slideCon.tmp);
+ //printf("SLIDECON WRITE REG: %02X = %02X\n", slideCon.reg_sel, slideCon.tmp);
slideCon.state = 0;
slideCon.counter = 0;
if (slideCon.reg_sel <= 0x11)
- scRegs[slideCon.reg_sel] = slideCon.tmp;
+ sc_regs[slideCon.reg_sel] = slideCon.tmp;
}
break;
- case 2: //read reg
+ case 2: //Read reg
if ((slideCon.sck == 0) && (new_sck == 1) && (slideCon.counter < 8))
{
if (slideCon.reg_sel <= 0x11)
- slideCon.out_data = (scRegs[slideCon.reg_sel] >> (7 - slideCon.counter)) & 1;
+ slideCon.out_data = (sc_regs[slideCon.reg_sel] >> (7 - slideCon.counter)) & 1;
else
slideCon.out_data = 0;
slideCon.counter++;
}
else if ((slideCon.sck == 0) && (new_sck == 0) && (slideCon.counter == 8))
{
- //printf("READ REG: %02X = %02X\n", slideCon.reg_sel, scRegs[slideCon.reg_sel]);
+ //printf("SLIDECON READ REG: %02X = %02X\n", slideCon.reg_sel, sc_regs[slideCon.reg_sel]);
slideCon.state = 0;
slideCon.counter = 0;
//Reset motion flag if reg was motion status
if (slideCon.reg_sel == 0x02)
- scRegs[0x02] &= 0x7F;
+ sc_regs[0x02] &= 0x7F;
//Reset motion deltas if they were read
if ((slideCon.reg_sel == 0x03) || (slideCon.reg_sel == 0x04))
- scRegs[slideCon.reg_sel] = 0x00;
+ sc_regs[slideCon.reg_sel] = 0x00;
}
break;
}
slideCon.sck = new_sck;
- if (scRegs[0x0A] & 0x80) //Reset
+ if (sc_regs[0x0A] & 0x80) //Reset
{
slideCon_reset();
}
@@ -226,15 +223,17 @@ public:
return outWord;
}
+ virtual u32 readLong(u8 PROCNUM, u32 addr) { return 0xFEF0FEF0; }
+
virtual void savestate(EMUFILE& os)
{
s32 version = 0;
os.write_32LE(version);
- os.write_u8(xDelta);
- os.write_u8(yDelta);
+ os.write_u8(delta_x);
+ os.write_u8(delta_y);
for (int i = 0; i < 18; i++)
- os.write_u8(scRegs[i]);
+ os.write_u8(sc_regs[i]);
os.write_16LE(slideCon.in_data);
os.write_16LE(slideCon.out_data);
os.write_u8(slideCon.counter);
@@ -250,10 +249,10 @@ public:
if (version == 0)
{
- is.read_u8(xDelta);
- is.read_u8(yDelta);
+ is.read_u8(delta_x);
+ is.read_u8(delta_y);
for (int i = 0; i < 18; i++)
- scRegs[i] = is.read_u8();
+ sc_regs[i] = is.read_u8();
is.read_16LE(slideCon.in_data);
is.read_16LE(slideCon.out_data);
is.read_u8(slideCon.counter);
@@ -273,16 +272,6 @@ ISlot2Interface* construct_Slot2_SlideController() { return new Slot2_SlideContr
void slideController_updateMotion(s8 x, s8 y)
{
- if (x || y)
- {
- xDelta = (u8)x;
- yDelta = (u8)y;
- }
-}
-
-void slideController_rumbleEnable(bool enable)
-{
- rumbleEnable = enable;
- if (FeedbackON && (enable == false))
- FeedbackON(false);
+ delta_x = (u8)x;
+ delta_y = (u8)y;
}
diff --git a/desmume/src/frontend/windows/main.cpp b/desmume/src/frontend/windows/main.cpp
index b37bb0ac3..a3485210c 100644
--- a/desmume/src/frontend/windows/main.cpp
+++ b/desmume/src/frontend/windows/main.cpp
@@ -2211,8 +2211,6 @@ int _main()
slot2_HCV1000_barcode = GetPrivateProfileStdString("Slot2.HCV1000", "barcode", "").substr(0, 16);
HCV1000_setBarcode(slot2_HCV1000_barcode);
- slideController_rumbleEnable(GetPrivateProfileBool("Slot2.SlideController", "rumble", false, IniName));
-
cmdline.process_addonCommands();
WIN_InstallCFlash();
WIN_InstallGBACartridge();
diff --git a/desmume/src/slot2.h b/desmume/src/slot2.h
index 0e95b01d1..634c4048a 100644
--- a/desmume/src/slot2.h
+++ b/desmume/src/slot2.h
@@ -162,5 +162,4 @@ extern void piano_setKey(bool c, bool cs, bool d, bool ds, bool e, bool f, bool
extern void HCV1000_setReady();
extern void HCV1000_setBarcode(std::string barcode);
extern void slideController_updateMotion(s8 x, s8 y);
-extern void slideController_rumbleEnable(bool enable);
#endif //__SLOT_H__