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();
// 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 *);

View File

@ -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;

View File

@ -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;

View File

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

View File

@ -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:

View File

@ -7,6 +7,8 @@
#include <time.h>
#include <memory.h>
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)

View File

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