diff --git a/src/GameGearIOPorts.cpp b/src/GameGearIOPorts.cpp index ce2ddc96..19e6d853 100644 --- a/src/GameGearIOPorts.cpp +++ b/src/GameGearIOPorts.cpp @@ -18,11 +18,6 @@ */ #include "GameGearIOPorts.h" -#include "Audio.h" -#include "Video.h" -#include "Input.h" -#include "Cartridge.h" -#include "Memory.h" GameGearIOPorts::GameGearIOPorts(Audio* pAudio, Video* pVideo, Input* pInput, Cartridge* pCartridge, Memory* pMemory) { @@ -31,8 +26,7 @@ GameGearIOPorts::GameGearIOPorts(Audio* pAudio, Video* pVideo, Input* pInput, Ca m_pInput = pInput; m_pCartridge = pCartridge; m_pMemory = pMemory; - m_Port3F = 0; - m_Port3F_HC = 0; + Reset(); } GameGearIOPorts::~GameGearIOPorts() @@ -41,151 +35,13 @@ GameGearIOPorts::~GameGearIOPorts() void GameGearIOPorts::Reset() { - m_Port3F = 0; - m_Port3F_HC = 0; - m_Port2 = 0; -} - -u8 GameGearIOPorts::DoInput(u8 port) -{ - if (port < 0x07) - { - switch (port) - { - case 0x00: - { - u8 port00 = m_pInput->GetPort00(); - if (m_pCartridge->GetZone() != Cartridge::CartridgeJapanGG) - port00 |= 0x40; - return port00; - } - case 0x01: - return 0x7F; - case 0x02: - return m_Port2; - case 0x03: - case 0x05: - return 0x00; - default: - return 0xFF; - } - } - else if (port < 0x40) - { - // Reads return $FF (GG) - Debug("--> ** Attempting to read from port $%X", port); - return 0xFF; - } - else if ((port >= 0x40) && (port < 0x80)) - { - // Reads from even addresses return the V counter - // Reads from odd addresses return the H counter - if ((port & 0x01) == 0x00) - return m_pVideo->GetVCounter(); - else - return m_pVideo->GetHCounter(); - } - else if ((port >= 0x80) && (port < 0xC0)) - { - // Reads from even addresses return the VDP data port contents - // Reads from odd address return the VDP status flags - if ((port & 0x01) == 0x00) - return m_pVideo->GetDataPort(); - else - return m_pVideo->GetStatusFlags(); - } - else - { - // Reads from $C0 and $DC return the I/O port A/B register. - // Reads from $C1 and $DD return the I/O port B/misc. register. - // The remaining locations return $FF. - switch (port) - { - case 0xC0: - case 0xDC: - { - return m_pInput->GetPortDC(); - } - case 0xC1: - case 0xDD: - { - return ((m_pInput->GetPortDD() & 0x3F) | (m_Port3F & 0xC0)); - } - default: - { - Debug("--> ** Attempting to read from port $%X", port); - return 0xFF; - } - } - } -} - -void GameGearIOPorts::DoOutput(u8 port, u8 value) -{ - if (port < 0x07) - { - if (port == 0x06) - { - // SN76489 PSG - m_pAudio->WriteGGStereoRegister(value); - } - else if (port == 0x02) - { - m_Port2 = value; - } - } - else if (port < 0x40) - { - // Writes to even addresses go to memory control register. - // Writes to odd addresses go to I/O control register. - if ((port & 0x01) == 0x00) - { - Debug("--> ** Output to memory control port $%X: %X", port, value); - m_pMemory->SetPort3E(value); - } - else - { - if (((value & 0x01) && !(m_Port3F_HC & 0x01)) || ((value & 0x08) && !(m_Port3F_HC & 0x08))) - m_pVideo->LatchHCounter(); - m_Port3F_HC = value & 0x05; - - m_Port3F = ((value & 0x80) | (value & 0x20) << 1) & 0xC0; - if (m_pCartridge->GetZone() == Cartridge::CartridgeJapanGG) - m_Port3F ^= 0xC0; - } - } - else if ((port >= 0x40) && (port < 0x80)) - { - // Writes to any address go to the SN76489 PSG - m_pAudio->WriteAudioRegister(value); - } - else if ((port >= 0x80) && (port < 0xC0)) - { - // Writes to even addresses go to the VDP data port. - // Writes to odd addresses go to the VDP control port. - if ((port & 0x01) == 0x00) - m_pVideo->WriteData(value); - else - m_pVideo->WriteControl(value); - } -#ifdef DEBUG_GEARSYSTEM - else - { - // Writes have no effect. - if ((port == 0xDE) || (port == 0xDF)) - { - Debug("--> ** Output to keyboard port $%X: %X", port, value); - } - else if ((port == 0xF0) || (port == 0xF1) || (port == 0xF2)) - { - Debug("--> ** Output to YM2413 port $%X: %X", port, value); - } - else - { - Debug("--> ** Output to port $%X: %X", port, value); - } - } -#endif + m_Port3F = 0xFF; + m_Ports[0] = 0xC0; + m_Ports[1] = 0x7F; + m_Ports[2] = 0xFF; + m_Ports[3] = 0x00; + m_Ports[4] = 0xFF; + m_Ports[5] = 0x00; } void GameGearIOPorts::SaveState(std::ostream& stream) @@ -193,7 +49,7 @@ void GameGearIOPorts::SaveState(std::ostream& stream) using namespace std; stream.write(reinterpret_cast (&m_Port3F), sizeof(m_Port3F)); - stream.write(reinterpret_cast (&m_Port3F_HC), sizeof(m_Port3F_HC)); + stream.write(reinterpret_cast (m_Ports), sizeof(m_Ports)); } void GameGearIOPorts::LoadState(std::istream& stream) @@ -201,5 +57,5 @@ void GameGearIOPorts::LoadState(std::istream& stream) using namespace std; stream.read(reinterpret_cast (&m_Port3F), sizeof(m_Port3F)); - stream.read(reinterpret_cast (&m_Port3F_HC), sizeof(m_Port3F_HC)); + stream.read(reinterpret_cast (m_Ports), sizeof(m_Ports)); } diff --git a/src/GameGearIOPorts.h b/src/GameGearIOPorts.h index 1afb23b0..d1359a7c 100644 --- a/src/GameGearIOPorts.h +++ b/src/GameGearIOPorts.h @@ -38,6 +38,7 @@ class GameGearIOPorts : public IOPorts virtual void DoOutput(u8 port, u8 value); virtual void SaveState(std::ostream& stream); virtual void LoadState(std::istream& stream); + private: Audio* m_pAudio; Video* m_pVideo; @@ -45,8 +46,147 @@ class GameGearIOPorts : public IOPorts Memory* m_pMemory; Cartridge* m_pCartridge; u8 m_Port3F; - u8 m_Port3F_HC; - u8 m_Port2; + u8 m_Ports[6]; }; +#include "Audio.h" +#include "Video.h" +#include "Input.h" +#include "Cartridge.h" +#include "Memory.h" + +inline u8 GameGearIOPorts::DoInput(u8 port) +{ + if (port < 0x07) + { + if (port == 0x00) + { + u8 start_button = m_pInput->GetPort00(); + if (m_pCartridge->GetZone() != Cartridge::CartridgeJapanGG) + start_button |= 0x40; + return start_button; + } + else if (port < 6) + return m_Ports[port]; + else + return 0xFF; + } + else if (port < 0x40) + { + // Reads return $FF (GG) + Debug("--> ** Attempting to read from port $%X", port); + return 0xFF; + } + else if (port < 0x80) + { + // Reads from even addresses return the V counter + if ((port & 0x01) == 0x00) + return m_pVideo->GetVCounter(); + // Reads from odd addresses return the H counter + else + return m_pVideo->GetHCounter(); + } + else if (port < 0xC0) + { + // Reads from even addresses return the VDP data port contents + if ((port & 0x01) == 0x00) + return m_pVideo->GetDataPort(); + // Reads from odd address return the VDP status flags + else + return m_pVideo->GetStatusFlags(); + } + else + { + switch (port) + { + // Reads from $C0 and $DC return the I/O port A/B register. + case 0xC0: + case 0xDC: + { + return m_pInput->GetPortDC(); + } + // Reads from $C1 and $DD return the I/O port B/misc. register. + case 0xC1: + case 0xDD: + { + return ((m_pInput->GetPortDD() & 0x3F) | (m_Port3F & 0xC0)); + } + // The remaining locations return $FF. + default: + { + Debug("--> ** Attempting to read from port $%X", port); + return 0xFF; + } + } + } +} + +inline void GameGearIOPorts::DoOutput(u8 port, u8 value) +{ + if (port < 0x07) + { + if (port == 0x06) + { + // SN76489 PSG + m_pAudio->WriteGGStereoRegister(value); + } + else if (port != 0x00) + { + m_Ports[port] = value; + } + } + else if (port < 0x40) + { + // Writes to even addresses go to memory control register. + if ((port & 0x01) == 0x00) + { + Debug("--> ** Output to memory control port $%X: %X", port, value); + m_pMemory->SetPort3E(value); + } + // Writes to odd addresses go to I/O control register. + else + { + bool th_changed_a = (value & 0x02) && (value & 0x20) && !(m_Port3F & 0x20); + bool th_changed_b = (value & 0x08) && (value & 0x80) && !(m_Port3F & 0x80); + + if (th_changed_a || th_changed_b) + m_pVideo->LatchHCounter(); + + m_Port3F = value; + } + } + else if (port < 0x80) + { + // Writes to any address go to the SN76489 PSG + m_pAudio->WriteAudioRegister(value); + } + else if (port < 0xC0) + { + // Writes to even addresses go to the VDP data port. + if ((port & 0x01) == 0x00) + m_pVideo->WriteData(value); + // Writes to odd addresses go to the VDP control port. + else + m_pVideo->WriteControl(value); + } +#ifdef DEBUG_GEARSYSTEM + else + { + // Writes have no effect. + if ((port == 0xDE) || (port == 0xDF)) + { + Debug("--> ** Output to keyboard port $%X: %X", port, value); + } + else if ((port == 0xF0) || (port == 0xF1) || (port == 0xF2)) + { + Debug("--> ** Output to YM2413 port $%X: %X", port, value); + } + else + { + Debug("--> ** Output to port $%X: %X", port, value); + } + } +#endif +} + #endif /* GAMEGEARIOPORTS_H */ diff --git a/src/Input.cpp b/src/Input.cpp index 7347945c..17cce3f8 100644 --- a/src/Input.cpp +++ b/src/Input.cpp @@ -123,14 +123,7 @@ u8 Input::GetPortDD() u8 Input::GetPort00() { - if (m_bPhaser) - { - return 0x00; - } - else - { - return (IsSetBit(m_Joypad1, Key_Start) ? 0x80 : 0) & 0x80; - } + return (IsSetBit(m_Joypad1, Key_Start) ? 0x80 : 0) & 0x80; } u8 Input::GetGlassesRegistry() diff --git a/src/SmsIOPorts.cpp b/src/SmsIOPorts.cpp index 9238c6d3..d19d874f 100644 --- a/src/SmsIOPorts.cpp +++ b/src/SmsIOPorts.cpp @@ -27,7 +27,7 @@ SmsIOPorts::SmsIOPorts(Audio* pAudio, Video* pVideo, Input* pInput, Cartridge* p m_pCartridge = pCartridge; m_pMemory = pMemory; m_pProcessor = pProcessor; - m_Port3F = 0xFF; + Reset(); } SmsIOPorts::~SmsIOPorts() diff --git a/src/SmsIOPorts.h b/src/SmsIOPorts.h index 47ff189a..7eb35ddd 100644 --- a/src/SmsIOPorts.h +++ b/src/SmsIOPorts.h @@ -39,6 +39,7 @@ class SmsIOPorts : public IOPorts void DoOutput(u8 port, u8 value); void SaveState(std::ostream& stream); void LoadState(std::istream& stream); + private: Audio* m_pAudio; Video* m_pVideo; @@ -46,7 +47,6 @@ class SmsIOPorts : public IOPorts Cartridge* m_pCartridge; Memory* m_pMemory; Processor* m_pProcessor; - u8 m_Port3F; }; @@ -65,7 +65,7 @@ inline u8 SmsIOPorts::DoInput(u8 port) Debug("--> ** Attempting to read from port $%02X", port); return 0xFF; } - else if ((port >= 0x40) && (port < 0x80)) + else if (port < 0x80) { // Reads from even addresses return the V counter if ((port & 0x01) == 0x00) @@ -74,7 +74,7 @@ inline u8 SmsIOPorts::DoInput(u8 port) else return m_pVideo->GetHCounter(); } - else if ((port >= 0x80) && (port < 0xC0)) + else if (port < 0xC0) { // Reads from even addresses return the VDP data port contents if ((port & 0x01) == 0x00) @@ -155,14 +155,14 @@ inline void SmsIOPorts::DoOutput(u8 port, u8 value) m_Port3F = value; } } - else if ((port >= 0x40) && (port < 0x80)) + else if (port < 0x80) { // Writes to any address go to the SN76489 PSG m_pAudio->WriteAudioRegister(value); if (m_pCartridge->IsSG1000()) m_pProcessor->InjectTStates(32); } - else if ((port >= 0x80) && (port < 0xC0)) + else if (port < 0xC0) { // Writes to even addresses go to the VDP data port. if ((port & 0x01) == 0x00)