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__