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:
parent
f800bf8b0b
commit
96868aa21b
|
@ -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 *);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue