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();
|
||||
// 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 *);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -3054,6 +3054,7 @@ void CPUInit(const char *biosFileName, bool useBiosFile)
|
|||
|
||||
void CPUReset()
|
||||
{
|
||||
systemCartridgeRumble(false);
|
||||
if(gbaSaveType == 0) {
|
||||
if(eepromInUse)
|
||||
gbaSaveType = 3;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
u16 rtcRead(u32 address);
|
||||
bool rtcWrite(u32 address, u16 value);
|
||||
void rtcEnable(bool);
|
||||
void rtcEnableWarioRumble(bool);
|
||||
bool rtcIsEnabled();
|
||||
void rtcReset();
|
||||
|
||||
|
|
Loading…
Reference in New Issue