From b82c098ad59acd0c76cd0a29b33dee0c3355aede Mon Sep 17 00:00:00 2001 From: squall-leonhart Date: Sun, 11 Oct 2009 08:43:52 +0000 Subject: [PATCH] added rumble, and solar sensor to Core, however they will need to be properly exposed and integrated into the MFC/GTK/SDL interface ports at a later time. git-svn-id: https://svn.code.sf.net/p/vbam/code/trunk@917 a31d4220-a93d-0410-bf67-fe4944624d44 --- src/System.h | 5 +++ src/gb/GB.cpp | 7 ++++ src/gb/gbMemory.cpp | 14 ++++++-- src/gba/GBA.cpp | 1 + src/gba/GBAinline.h | 64 ++++++++++++++++++++++++++++------ src/gba/RTC.cpp | 85 +++++++++++++++++++++++++++++++++++++++++---- src/gba/RTC.h | 1 + 7 files changed, 157 insertions(+), 20 deletions(-) diff --git a/src/System.h b/src/System.h index 9c1b384a..d8125518 100644 --- a/src/System.h +++ b/src/System.h @@ -48,6 +48,11 @@ extern void systemDrawScreen(); extern bool systemReadJoypads(); // return information about the given joystick, -1 for default joystick extern u32 systemReadJoypad(int); +// this function should turn on or off rumble on the gamepad +extern void systemCartridgeRumble(bool); +extern void systemPossibleCartridgeRumble(bool); +// This should be called once per frame +extern void updateRumbleFrame(); extern u32 systemGetClock(); extern void systemMessage(int, const char *, ...); extern void systemSetTitle(const char *); diff --git a/src/gb/GB.cpp b/src/gb/GB.cpp index 794a5920..14039ab1 100644 --- a/src/gb/GB.cpp +++ b/src/gb/GB.cpp @@ -1437,6 +1437,8 @@ void gbWriteMemory(register u16 address, register u8 value) int paletteHiLo = (v & 0x01); // No access to gbPalette during mode 3 (Color Panel Demo) + // CAK - The following check has to be commented out for + // colourised roms like Metroid 2 DX if (((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks>=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-1)))) && (!gbSpeed)) || (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) || ((gbLcdMode == 3) && (gbLcdTicks>(GBLCD_MODE_3_CLOCK_TICKS-2))) || @@ -1491,6 +1493,8 @@ void gbWriteMemory(register u16 address, register u8 value) paletteIndex += 32; // No access to gbPalette during mode 3 (Color Panel Demo) + // CAK - The following check has to be commented out for + // colourised roms like Metroid 2 DX if (((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks>=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-1)))) && (!gbSpeed)) || (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) || ((gbLcdMode == 3) && (gbLcdTicks>(GBLCD_MODE_3_CLOCK_TICKS-2))) || @@ -2141,6 +2145,7 @@ void gbGetHardwareType() void gbReset() { + systemCartridgeRumble(false); gbGetHardwareType(); oldRegister_WY = 146; @@ -2614,6 +2619,8 @@ void gbReset() memset(&gbDataMBC5, 0, sizeof(gbDataMBC5)); gbDataMBC5.mapperROMBank = 1; + if (gbRomType >= 0x1c && gbRomType<=0x1e) + gbDataMBC5.isRumbleCartridge = 1; memset(&gbDataHuC1, 0, sizeof(gbDataHuC1)); gbDataHuC1.mapperROMBank = 1; diff --git a/src/gb/gbMemory.cpp b/src/gb/gbMemory.cpp index 53a7f69e..9a6f9981 100644 --- a/src/gb/gbMemory.cpp +++ b/src/gb/gbMemory.cpp @@ -579,10 +579,18 @@ void mapperMBC5ROM(u16 address, u8 value) gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; } break; - case 0x4000: // RAM bank select - if(gbDataMBC5.isRumbleCartridge) + case 0x4000: // RAM bank select, plus rumble + // Some games support rumble, such as Disney Tarzan, but aren't on a + // rumble cartridge. As long as the RAM is less than or equal to 256Kbit + // we know that the last address line is not used for real RAM addresses, + // so it must be a rumble signal instead. + if(gbDataMBC5.isRumbleCartridge) { + systemCartridgeRumble(value & 0x08); value &= 0x07; - else + } else if (gbRamSizeMask <= 0x7FFF) { + systemPossibleCartridgeRumble(value & 0x08); + value &= 0x07; + } else value &= 0x0f; if(value == gbDataMBC5.mapperRAMBank) break; diff --git a/src/gba/GBA.cpp b/src/gba/GBA.cpp index 1ade6998..2cc378ed 100644 --- a/src/gba/GBA.cpp +++ b/src/gba/GBA.cpp @@ -3054,6 +3054,7 @@ void CPUInit(const char *biosFileName, bool useBiosFile) void CPUReset() { + systemCartridgeRumble(false); if(gbaSaveType == 0) { if(eepromInUse) gbaSaveType = 3; diff --git a/src/gba/GBAinline.h b/src/gba/GBAinline.h index df366ed8..caf7994b 100644 --- a/src/gba/GBAinline.h +++ b/src/gba/GBAinline.h @@ -103,11 +103,13 @@ static inline u32 CPUReadMemory(u32 address) value = READ32LE(((u32 *)&oam[address & 0x3FC])); break; case 8: + // Must be cartridge ROM, reading other sensors doesn't allow 32-bit access. case 9: case 10: case 11: case 12: value = READ32LE(((u32 *)&rom[address&0x1FFFFFC])); + break; case 13: if(cpuEEPROMEnabled) @@ -115,6 +117,20 @@ static inline u32 CPUReadMemory(u32 address) return eepromRead(address); goto unreadable; case 14: + // Yoshi's Universal Gravitation (Topsy Turvy) + // Koro Koro + if(cpuEEPROMSensorEnabled) { + switch(address & 0x00008f00) { + case 0x8200: + return systemGetSensorX() & 255; + case 0x8300: + return (systemGetSensorX() >> 8)|0x80; + case 0x8400: + return systemGetSensorY() & 255; + case 0x8500: + return systemGetSensorY() >> 8; + } + } if(cpuFlashEnabled | cpuSramEnabled) // no need to swap this return flashRead(address); @@ -239,6 +255,15 @@ static inline u32 CPUReadHalfWord(u32 address) value = READ16LE(((u16 *)&oam[address & 0x3fe])); break; case 8: + // Use existing case statement and faster test for potential speed improvement + // This is possibly the GPIO port that controls the real time clock, + // WarioWare Twisted! tilt sensors, rumble, and solar sensors. + if(address >= 0x80000c4 && address <= 0x80000c8) { + // this function still works if there is no real time clock + // and does a normal memory read in that case. + value = rtcRead(address & 0xFFFFFFE); + break; + } case 9: case 10: case 11: @@ -247,6 +272,7 @@ static inline u32 CPUReadHalfWord(u32 address) value = rtcRead(address); else value = READ16LE(((u16 *)&rom[address & 0x1FFFFFE])); + break; case 13: if(cpuEEPROMEnabled) @@ -254,6 +280,20 @@ static inline u32 CPUReadHalfWord(u32 address) return eepromRead(address); goto unreadable; case 14: + // Yoshi's Universal Gravitation (Topsy Turvy) + // Koro Koro + if(cpuEEPROMSensorEnabled) { + switch(address & 0x00008f00) { + case 0x8200: + return systemGetSensorX() & 255; + case 0x8300: + return (systemGetSensorX() >> 8)|0x80; + case 0x8400: + return systemGetSensorY() & 255; + case 0x8500: + return systemGetSensorY() >> 8; + } + } if(cpuFlashEnabled | cpuSramEnabled) // no need to swap this return flashRead(address); @@ -329,30 +369,34 @@ static inline u8 CPUReadByte(u32 address) case 7: return oam[address & 0x3ff]; case 8: + // the real time clock doesn't support byte reads, so don't bother checking for it. case 9: case 10: case 11: case 12: return rom[address & 0x1FFFFFF]; + case 13: if(cpuEEPROMEnabled) return eepromRead(address); goto unreadable; case 14: - if(cpuSramEnabled | cpuFlashEnabled) - return flashRead(address); + // Yoshi's Universal Gravitation (Topsy Turvy) + // Koro Koro if(cpuEEPROMSensorEnabled) { switch(address & 0x00008f00) { - case 0x8200: - return systemGetSensorX() & 255; - case 0x8300: - return (systemGetSensorX() >> 8)|0x80; - case 0x8400: - return systemGetSensorY() & 255; - case 0x8500: - return systemGetSensorY() >> 8; + case 0x8200: + return systemGetSensorX() & 255; + case 0x8300: + return (systemGetSensorX() >> 8)|0x80; + case 0x8400: + return systemGetSensorY() & 255; + case 0x8500: + return systemGetSensorY() >> 8; } } + if(cpuSramEnabled | cpuFlashEnabled) + return flashRead(address); // default default: unreadable: diff --git a/src/gba/RTC.cpp b/src/gba/RTC.cpp index 21d0a2de..878102eb 100644 --- a/src/gba/RTC.cpp +++ b/src/gba/RTC.cpp @@ -7,6 +7,8 @@ #include #include +u8 systemGetSensorDarkness(); +int systemGetSensorZ(); enum RTCSTATE { IDLE, COMMAND, DATA, READDATA }; @@ -27,6 +29,7 @@ typedef struct { static RTCCLOCKDATA rtcClockData; static bool rtcEnabled = false; +static bool rtcWarioRumbleEnabled = false; void rtcEnable(bool e) { @@ -38,6 +41,12 @@ bool rtcIsEnabled() return rtcEnabled; } +void rtcEnableWarioRumble(bool e) +{ + if (e) rtcEnable(true); + rtcWarioRumbleEnabled = e; +} + u16 rtcRead(u32 address) { if(rtcEnabled) { @@ -49,12 +58,34 @@ u16 rtcRead(u32 address) return rtcClockData.byte1; break; case 0x80000c4: - return rtcClockData.byte0; + + // Boktai Solar Sensor + if (rtcClockData.byte1 == 7) { + if (rtcClockData.reserved[11] >= systemGetSensorDarkness()) { + rtcClockData.reserved[10] = 0; + rtcClockData.reserved[11] = 0; + return 8; + } else return 0; + + // WarioWare Twisted Tilt Sensor + } else if (rtcClockData.byte1 == 0x0b) { + //sprintf(DebugStr, "Reading Twisted Sensor bit %d", rtcClockData.reserved[11]); + u16 v = systemGetSensorZ(); + return ((v >> rtcClockData.reserved[11]) & 1) << 2; + + // Real Time Clock + } else { + //sprintf(DebugStr, "Reading RTC %02x, %02x, %02x", rtcClockData.byte0, rtcClockData.byte1, rtcClockData.byte2); + return rtcClockData.byte0; + } break; } } - +#ifdef USE_VM + return VMRead16( address & 0x1FFFFFE ); +#else return READ16LE((&rom[address & 0x1FFFFFE])); +#endif } static u8 toBCD(u8 value) @@ -71,12 +102,51 @@ bool rtcWrite(u32 address, u16 value) return false; if(address == 0x80000c8) { - rtcClockData.byte2 = (u8)value; // enable ? + rtcClockData.byte2 = (u8)value; // bit 0 = enable reading from 0x80000c4 c6 and c8 } else if(address == 0x80000c6) { - rtcClockData.byte1 = (u8)value; // read/write - } else if(address == 0x80000c4) { - if(rtcClockData.byte2 & 1) { - if(rtcClockData.state == IDLE && rtcClockData.byte0 == 1 && value == 5) { + rtcClockData.byte1 = (u8)value; // 0=read/1=write (for each of 4 low bits) + // rumble is off when not writing to that pin + if (rtcWarioRumbleEnabled && !(value & 8)) systemCartridgeRumble(false); + } else if(address == 0x80000c4) { // 4 bits of I/O Port Data (upper bits not used) + + // WarioWare Twisted rumble + if(rtcWarioRumbleEnabled && (rtcClockData.byte1 & 8)) { + systemCartridgeRumble(value & 8); + } + + // Boktai solar sensor + if (rtcClockData.byte1 == 7) { + if (value & 2) { + // reset counter to 0 + rtcClockData.reserved[11]=0; + rtcClockData.reserved[10]=0; + } + if ((value & 1) && (!(rtcClockData.reserved[10] & 1))) { + // increase counter, ready to do another read + if (rtcClockData.reserved[11]<255) rtcClockData.reserved[11]++; + } + rtcClockData.reserved[10] = value & rtcClockData.byte1; + } + + // WarioWare Twisted rotation sensor + if (rtcClockData.byte1 == 0xb) { + if (value & 2) { + // clock goes high in preperation for reading a bit + rtcClockData.reserved[11]--; + } + if (value & 1) { + // start ADC conversion + rtcClockData.reserved[11] = 15; + } + + rtcClockData.byte0 = value & rtcClockData.byte1; + + // Real Time Clock + } + /**/ + + if(rtcClockData.byte2 & 1) { // if reading is enabled + if(rtcClockData.state == IDLE && rtcClockData.byte0 == 1 && value == 5) { rtcClockData.state = COMMAND; rtcClockData.bits = 0; rtcClockData.command = 0; @@ -195,6 +265,7 @@ void rtcReset() rtcClockData.dataLen = 0; rtcClockData.bits = 0; rtcClockData.state = IDLE; + rtcClockData.reserved[11] = 0; } void rtcSaveGame(gzFile gzFile) diff --git a/src/gba/RTC.h b/src/gba/RTC.h index 8bedd68e..b8d5ceab 100644 --- a/src/gba/RTC.h +++ b/src/gba/RTC.h @@ -4,6 +4,7 @@ u16 rtcRead(u32 address); bool rtcWrite(u32 address, u16 value); void rtcEnable(bool); +void rtcEnableWarioRumble(bool); bool rtcIsEnabled(); void rtcReset();