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.

This commit is contained in:
squall-leonhart 2009-10-11 08:43:52 +00:00
parent f800bf8b0b
commit 96868aa21b
7 changed files with 157 additions and 20 deletions

View File

@ -48,6 +48,11 @@ extern void systemDrawScreen();
extern bool systemReadJoypads(); extern bool systemReadJoypads();
// return information about the given joystick, -1 for default joystick // return information about the given joystick, -1 for default joystick
extern u32 systemReadJoypad(int); 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 u32 systemGetClock();
extern void systemMessage(int, const char *, ...); extern void systemMessage(int, const char *, ...);
extern void systemSetTitle(const char *); extern void systemSetTitle(const char *);

View File

@ -1437,6 +1437,8 @@ void gbWriteMemory(register u16 address, register u8 value)
int paletteHiLo = (v & 0x01); int paletteHiLo = (v & 0x01);
// No access to gbPalette during mode 3 (Color Panel Demo) // 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)) || if (((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks>=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-1)))) && (!gbSpeed)) ||
(gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) || (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) ||
((gbLcdMode == 3) && (gbLcdTicks>(GBLCD_MODE_3_CLOCK_TICKS-2))) || ((gbLcdMode == 3) && (gbLcdTicks>(GBLCD_MODE_3_CLOCK_TICKS-2))) ||
@ -1491,6 +1493,8 @@ void gbWriteMemory(register u16 address, register u8 value)
paletteIndex += 32; paletteIndex += 32;
// No access to gbPalette during mode 3 (Color Panel Demo) // 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)) || if (((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks>=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-1)))) && (!gbSpeed)) ||
(gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) || (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) ||
((gbLcdMode == 3) && (gbLcdTicks>(GBLCD_MODE_3_CLOCK_TICKS-2))) || ((gbLcdMode == 3) && (gbLcdTicks>(GBLCD_MODE_3_CLOCK_TICKS-2))) ||
@ -2141,6 +2145,7 @@ void gbGetHardwareType()
void gbReset() void gbReset()
{ {
systemCartridgeRumble(false);
gbGetHardwareType(); gbGetHardwareType();
oldRegister_WY = 146; oldRegister_WY = 146;
@ -2614,6 +2619,8 @@ void gbReset()
memset(&gbDataMBC5, 0, sizeof(gbDataMBC5)); memset(&gbDataMBC5, 0, sizeof(gbDataMBC5));
gbDataMBC5.mapperROMBank = 1; gbDataMBC5.mapperROMBank = 1;
if (gbRomType >= 0x1c && gbRomType<=0x1e)
gbDataMBC5.isRumbleCartridge = 1;
memset(&gbDataHuC1, 0, sizeof(gbDataHuC1)); memset(&gbDataHuC1, 0, sizeof(gbDataHuC1));
gbDataHuC1.mapperROMBank = 1; gbDataHuC1.mapperROMBank = 1;

View File

@ -579,10 +579,18 @@ void mapperMBC5ROM(u16 address, u8 value)
gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
} }
break; break;
case 0x4000: // RAM bank select case 0x4000: // RAM bank select, plus rumble
if(gbDataMBC5.isRumbleCartridge) // 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; value &= 0x07;
else } else if (gbRamSizeMask <= 0x7FFF) {
systemPossibleCartridgeRumble(value & 0x08);
value &= 0x07;
} else
value &= 0x0f; value &= 0x0f;
if(value == gbDataMBC5.mapperRAMBank) if(value == gbDataMBC5.mapperRAMBank)
break; break;

View File

@ -3054,6 +3054,7 @@ void CPUInit(const char *biosFileName, bool useBiosFile)
void CPUReset() void CPUReset()
{ {
systemCartridgeRumble(false);
if(gbaSaveType == 0) { if(gbaSaveType == 0) {
if(eepromInUse) if(eepromInUse)
gbaSaveType = 3; gbaSaveType = 3;

View File

@ -103,11 +103,13 @@ static inline u32 CPUReadMemory(u32 address)
value = READ32LE(((u32 *)&oam[address & 0x3FC])); value = READ32LE(((u32 *)&oam[address & 0x3FC]));
break; break;
case 8: case 8:
// Must be cartridge ROM, reading other sensors doesn't allow 32-bit access.
case 9: case 9:
case 10: case 10:
case 11: case 11:
case 12: case 12:
value = READ32LE(((u32 *)&rom[address&0x1FFFFFC])); value = READ32LE(((u32 *)&rom[address&0x1FFFFFC]));
break; break;
case 13: case 13:
if(cpuEEPROMEnabled) if(cpuEEPROMEnabled)
@ -115,6 +117,20 @@ static inline u32 CPUReadMemory(u32 address)
return eepromRead(address); return eepromRead(address);
goto unreadable; goto unreadable;
case 14: 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) if(cpuFlashEnabled | cpuSramEnabled)
// no need to swap this // no need to swap this
return flashRead(address); return flashRead(address);
@ -239,6 +255,15 @@ static inline u32 CPUReadHalfWord(u32 address)
value = READ16LE(((u16 *)&oam[address & 0x3fe])); value = READ16LE(((u16 *)&oam[address & 0x3fe]));
break; break;
case 8: 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 9:
case 10: case 10:
case 11: case 11:
@ -247,6 +272,7 @@ static inline u32 CPUReadHalfWord(u32 address)
value = rtcRead(address); value = rtcRead(address);
else else
value = READ16LE(((u16 *)&rom[address & 0x1FFFFFE])); value = READ16LE(((u16 *)&rom[address & 0x1FFFFFE]));
break; break;
case 13: case 13:
if(cpuEEPROMEnabled) if(cpuEEPROMEnabled)
@ -254,6 +280,20 @@ static inline u32 CPUReadHalfWord(u32 address)
return eepromRead(address); return eepromRead(address);
goto unreadable; goto unreadable;
case 14: 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) if(cpuFlashEnabled | cpuSramEnabled)
// no need to swap this // no need to swap this
return flashRead(address); return flashRead(address);
@ -329,18 +369,20 @@ static inline u8 CPUReadByte(u32 address)
case 7: case 7:
return oam[address & 0x3ff]; return oam[address & 0x3ff];
case 8: case 8:
// the real time clock doesn't support byte reads, so don't bother checking for it.
case 9: case 9:
case 10: case 10:
case 11: case 11:
case 12: case 12:
return rom[address & 0x1FFFFFF]; return rom[address & 0x1FFFFFF];
case 13: case 13:
if(cpuEEPROMEnabled) if(cpuEEPROMEnabled)
return eepromRead(address); return eepromRead(address);
goto unreadable; goto unreadable;
case 14: case 14:
if(cpuSramEnabled | cpuFlashEnabled) // Yoshi's Universal Gravitation (Topsy Turvy)
return flashRead(address); // Koro Koro
if(cpuEEPROMSensorEnabled) { if(cpuEEPROMSensorEnabled) {
switch(address & 0x00008f00) { switch(address & 0x00008f00) {
case 0x8200: case 0x8200:
@ -353,6 +395,8 @@ static inline u8 CPUReadByte(u32 address)
return systemGetSensorY() >> 8; return systemGetSensorY() >> 8;
} }
} }
if(cpuSramEnabled | cpuFlashEnabled)
return flashRead(address);
// default // default
default: default:
unreadable: unreadable:

View File

@ -7,6 +7,8 @@
#include <time.h> #include <time.h>
#include <memory.h> #include <memory.h>
u8 systemGetSensorDarkness();
int systemGetSensorZ();
enum RTCSTATE { IDLE, COMMAND, DATA, READDATA }; enum RTCSTATE { IDLE, COMMAND, DATA, READDATA };
@ -27,6 +29,7 @@ typedef struct {
static RTCCLOCKDATA rtcClockData; static RTCCLOCKDATA rtcClockData;
static bool rtcEnabled = false; static bool rtcEnabled = false;
static bool rtcWarioRumbleEnabled = false;
void rtcEnable(bool e) void rtcEnable(bool e)
{ {
@ -38,6 +41,12 @@ bool rtcIsEnabled()
return rtcEnabled; return rtcEnabled;
} }
void rtcEnableWarioRumble(bool e)
{
if (e) rtcEnable(true);
rtcWarioRumbleEnabled = e;
}
u16 rtcRead(u32 address) u16 rtcRead(u32 address)
{ {
if(rtcEnabled) { if(rtcEnabled) {
@ -49,12 +58,34 @@ u16 rtcRead(u32 address)
return rtcClockData.byte1; return rtcClockData.byte1;
break; break;
case 0x80000c4: case 0x80000c4:
// 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; return rtcClockData.byte0;
}
break; break;
} }
} }
#ifdef USE_VM
return VMRead16( address & 0x1FFFFFE );
#else
return READ16LE((&rom[address & 0x1FFFFFE])); return READ16LE((&rom[address & 0x1FFFFFE]));
#endif
} }
static u8 toBCD(u8 value) static u8 toBCD(u8 value)
@ -71,11 +102,50 @@ bool rtcWrite(u32 address, u16 value)
return false; return false;
if(address == 0x80000c8) { 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) { } else if(address == 0x80000c6) {
rtcClockData.byte1 = (u8)value; // read/write rtcClockData.byte1 = (u8)value; // 0=read/1=write (for each of 4 low bits)
} else if(address == 0x80000c4) { // rumble is off when not writing to that pin
if(rtcClockData.byte2 & 1) { 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) { if(rtcClockData.state == IDLE && rtcClockData.byte0 == 1 && value == 5) {
rtcClockData.state = COMMAND; rtcClockData.state = COMMAND;
rtcClockData.bits = 0; rtcClockData.bits = 0;
@ -195,6 +265,7 @@ void rtcReset()
rtcClockData.dataLen = 0; rtcClockData.dataLen = 0;
rtcClockData.bits = 0; rtcClockData.bits = 0;
rtcClockData.state = IDLE; rtcClockData.state = IDLE;
rtcClockData.reserved[11] = 0;
} }
void rtcSaveGame(gzFile gzFile) void rtcSaveGame(gzFile gzFile)

View File

@ -4,6 +4,7 @@
u16 rtcRead(u32 address); u16 rtcRead(u32 address);
bool rtcWrite(u32 address, u16 value); bool rtcWrite(u32 address, u16 value);
void rtcEnable(bool); void rtcEnable(bool);
void rtcEnableWarioRumble(bool);
bool rtcIsEnabled(); bool rtcIsEnabled();
void rtcReset(); void rtcReset();