diff --git a/platforms/desktop-shared/emu.cpp b/platforms/desktop-shared/emu.cpp index 59b3407..80a039b 100644 --- a/platforms/desktop-shared/emu.cpp +++ b/platforms/desktop-shared/emu.cpp @@ -355,6 +355,9 @@ static const char* get_mapper(Cartridge::CartridgeTypes type) case Cartridge::CartridgeColecoVision: return "ColecoVision"; break; + case Cartridge::CartridgeMegaCart: + return "MegaCart"; + break; case Cartridge::CartridgeNotSupported: return "Not Supported"; break; diff --git a/platforms/desktop-shared/gui.cpp b/platforms/desktop-shared/gui.cpp index 32b8d27..5e02006 100644 --- a/platforms/desktop-shared/gui.cpp +++ b/platforms/desktop-shared/gui.cpp @@ -72,6 +72,7 @@ static void menu_ffwd(void); static void show_info(void); static void show_fps(void); static Cartridge::CartridgeRegions get_region(int index); +//static Cartridge::CartridgeTypes get_mapper(int index); void gui_init(void) { @@ -1418,6 +1419,10 @@ static void show_fps(void) // return Cartridge::CartridgeNotSupported; // case 1: // return Cartridge::CartridgeColecoVision; +// case 2: +// return Cartridge::CartridgeMegaCart; +// case 3: +// return Cartridge::CartridgeActivisionCart; // default: // return Cartridge::CartridgeNotSupported; // } diff --git a/platforms/desktop-shared/gui_debug.cpp b/platforms/desktop-shared/gui_debug.cpp index 2c3d0cd..ebf621d 100644 --- a/platforms/desktop-shared/gui_debug.cpp +++ b/platforms/desktop-shared/gui_debug.cpp @@ -195,6 +195,17 @@ static void debug_window_memory(void) Cartridge* cart = core->GetCartridge(); Video* video = core->GetVideo(); + ImGui::PushFont(gui_default_font); + + ImGui::TextColored(cyan, " ROM: ");ImGui::SameLine(); + + ImGui::TextColored(magenta, "BANK");ImGui::SameLine(); + ImGui::Text("$%02X", memory->GetRomBank()); ImGui::SameLine(); + ImGui::TextColored(magenta, " ADDRESS");ImGui::SameLine(); + ImGui::Text("$%05X", memory->GetRomBankAddress()); + + ImGui::PopFont(); + if (ImGui::BeginTabBar("##memory_tabs", ImGuiTabBarFlags_None)) { if (ImGui::BeginTabItem("BIOS")) @@ -213,10 +224,18 @@ static void debug_window_memory(void) ImGui::EndTabItem(); } + if (ImGui::BeginTabItem("SGM RAM")) + { + ImGui::PushFont(gui_default_font); + mem_edit.DrawContents(memory->GetSGMRam(), 0x8000, 0x0000); + ImGui::PopFont(); + ImGui::EndTabItem(); + } + if (IsValidPointer(cart->GetROM()) && ImGui::BeginTabItem("ROM")) { ImGui::PushFont(gui_default_font); - mem_edit.DrawContents(cart->GetROM(), 0x8000, 0x8000); + mem_edit.DrawContents(cart->GetROM(), cart->GetROMSize(), 0x0000); ImGui::PopFont(); ImGui::EndTabItem(); } @@ -576,11 +595,15 @@ static void debug_window_disassembler(void) if (show_segment) { ImGui::SameLine(); - ImGui::TextColored(color_segment, "%s ", vec[item].record->segment); + ImGui::TextColored(color_segment, "%s", vec[item].record->segment); } ImGui::SameLine(); - ImGui::TextColored(color_addr, "%04X ", vec[item].record->address); + if (strcmp(vec[item].record->segment, "ROM") == 0) + ImGui::TextColored(color_addr, "%02X:%04X ", vec[item].record->bank, vec[item].record->address); + else + ImGui::TextColored(color_addr, " %04X ", vec[item].record->address); + if (show_mem) { diff --git a/src/Audio.h b/src/Audio.h index 2e1e744..0a4be27 100644 --- a/src/Audio.h +++ b/src/Audio.h @@ -34,6 +34,9 @@ class Audio void SetSampleRate(int rate); void SetVolume(float volume); void WriteAudioRegister(u8 value); + void SGMWrite(u8 value); + u8 SGMRead(); + void SGMRegister(u8 reg); void Tick(unsigned int clockCycles); void EndFrame(s16* pSampleBuffer, int* pSampleCount); void SaveState(std::ostream& stream); @@ -46,6 +49,8 @@ class Audio int m_iSampleRate; blip_sample_t* m_pSampleBuffer; bool m_bPAL; + u8 m_SGMRegister; + u8 m_SGMRegisters[16]; }; inline void Audio::Tick(unsigned int clockCycles) @@ -58,4 +63,24 @@ inline void Audio::WriteAudioRegister(u8 value) m_pApu->write_data(m_ElapsedCycles, value); } +inline void Audio::SGMWrite(u8 value) +{ + uint8_t mask[16] = { + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0x1F, 0xFF, + 0x1F, 0x1F, 0x1F, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, + }; + + m_SGMRegisters[m_SGMRegister] = value & mask[m_SGMRegister]; +} + +inline u8 Audio::SGMRead() +{ + return m_SGMRegisters[m_SGMRegister]; +} + +inline void Audio::SGMRegister(u8 reg) +{ + m_SGMRegister = reg & 0x0F; +} + #endif /* AUDIO_H */ diff --git a/src/Cartridge.cpp b/src/Cartridge.cpp index e64ff1a..9d323c7 100644 --- a/src/Cartridge.cpp +++ b/src/Cartridge.cpp @@ -116,6 +116,14 @@ void Cartridge::ForceConfig(Cartridge::ForceConfiguration config) m_Type = config.type; Log("Forcing Mapper: Colecovision"); break; + case Cartridge::CartridgeMegaCart: + m_Type = config.type; + Log("Forcing Mapper: MegaCart"); + break; + case Cartridge::CartridgeActivisionCart: + m_Type = config.type; + Log("Forcing Mapper: Activision"); + break; default: break; } @@ -304,7 +312,9 @@ bool Cartridge::LoadFromBuffer(const u8* buffer, int size) m_iCRC = CalculateCRC32(0, m_pROM, m_iROMSize); - return GatherMetadata(m_iCRC); + GatherMetadata(m_iCRC); + + return true; } else return false; @@ -317,38 +327,49 @@ bool Cartridge::GatherMetadata(u32 crc) Log("ROM Size: %d KB", m_iROMSize / 1024); - m_iROMBankCount = (m_iROMSize / 0x2000) + (m_iROMSize % 0x2000 ? 1 : 0); + m_iROMBankCount = (m_iROMSize / 0x4000) + (m_iROMSize % 0x4000 ? 1 : 0); Log("ROM Bank Count: %d", m_iROMBankCount); + m_Type = Cartridge::CartridgeNotSupported; + int headerOffset = 0; + u16 header = m_pROM[headerOffset + 1] | (m_pROM[headerOffset + 0] << 8); + m_bValidROM = (header == 0xAA55) || (header == 0x55AA); - if (m_iROMSize > 0x8000) + if (header == 0x6699) { - Log("Cartridge is probably Mega Cart. ROM size: %d bytes", m_iROMSize); - headerOffset = m_iROMSize - 0x4000; + Log("Cartridge is a Colec Adam expansion ROM. Header: %X", header); } - u16 header = m_pROM[headerOffset + 1] | (m_pROM[headerOffset + 0] << 8); - m_bValidROM = (header == 0xAA55) || (header == 0x55AA); - - if (m_bValidROM) + if (m_bValidROM && (m_iROMSize <= 0x8000)) { - Log("ROM is Valid. Header found: %X", header); + m_Type = Cartridge::CartridgeColecoVision; + Log("Cartridge is Colecovision. ROM size: %d bytes.", m_iROMSize); } - else + else if (m_bValidROM && (m_iROMSize > 0x8000)) { - Log("ROM is NOT Valid. No header found."); + m_Type = Cartridge::CartridgeActivisionCart; + Log("Cartridge is Mega Cart. ROM size: %d bytes. Banks %d.", m_iROMSize, m_iROMBankCount); } + else if (!m_bValidROM && (m_iROMSize > 0x8000)) + { + headerOffset = m_iROMSize - 0x4000; + header = m_pROM[headerOffset + 1] | (m_pROM[headerOffset + 0] << 8); + m_bValidROM = (header == 0xAA55) || (header == 0x55AA); - if (header == 0x6699) + if (m_bValidROM) + { + m_Type = Cartridge::CartridgeMegaCart; + Log("Cartridge is Mega Cart. ROM size: %d bytes. Banks %d.", m_iROMSize, m_iROMBankCount); + } + } + else { - Log("Cartridge is a Colec Adam expansion ROM. Header: %X", header); + m_Type = Cartridge::CartridgeNotSupported; + Log("ROM is NOT Valid. No header found."); } - //m_Type = m_bValidROM ? Cartridge::CartridgeColecoVision : Cartridge::CartridgeNotSupported; - m_Type = Cartridge::CartridgeColecoVision; - GetInfoFromDB(crc); switch (m_Type) @@ -356,6 +377,12 @@ bool Cartridge::GatherMetadata(u32 crc) case Cartridge::CartridgeColecoVision: Log("ColecoVision mapper found"); break; + case Cartridge::CartridgeMegaCart: + Log("MegaCart mapper found"); + break; + case Cartridge::CartridgeActivisionCart: + Log("Activision mapper found"); + break; case Cartridge::CartridgeNotSupported: Log("Cartridge not supported!!"); break; diff --git a/src/Cartridge.h b/src/Cartridge.h index b2caa5d..aec4ab3 100644 --- a/src/Cartridge.h +++ b/src/Cartridge.h @@ -29,6 +29,8 @@ class Cartridge enum CartridgeTypes { CartridgeColecoVision, + CartridgeMegaCart, + CartridgeActivisionCart, CartridgeNotSupported }; diff --git a/src/ColecoVisionIOPorts.h b/src/ColecoVisionIOPorts.h index d76fb90..5357572 100644 --- a/src/ColecoVisionIOPorts.h +++ b/src/ColecoVisionIOPorts.h @@ -72,6 +72,15 @@ inline u8 ColecoVisionIOPorts::In(u8 port) { return m_pInput->ReadInput(port); } + default: + { + if (port == 0x52) + { + return m_pAudio->SGMRead(); + return 0xAA; + } + return 0xFF; + } } Log("--> ** Attempting to read from port $%X", port); @@ -112,7 +121,28 @@ inline void ColecoVisionIOPorts::Out(u8 port, u8 value) } default: { - Log("--> ** Output to port $%X: %X", port, value); + if (port == 0x50) + { + m_pAudio->SGMRegister(value); + break; + } + else if (port == 0x51) + { + m_pAudio->SGMWrite(value); + break; + } + else if (port == 0x53) + { + m_pMemory->EnableSGMUpper(value & 0x01); + } + else if (port == 0x7F) + { + m_pMemory->EnableSGMLower(~value & 0x02); + } + else + { + Log("--> ** Output to port $%X: %X", port, value); + } } } } diff --git a/src/Memory.cpp b/src/Memory.cpp index 1cc1034..5feea03 100644 --- a/src/Memory.cpp +++ b/src/Memory.cpp @@ -31,17 +31,23 @@ Memory::Memory(Cartridge* pCartridge) InitPointer(m_pDisassembledRomMap); InitPointer(m_pDisassembledRamMap); InitPointer(m_pDisassembledBiosMap); - InitPointer(m_pDisassembledExpansionMap); + InitPointer(m_pDisassembledSGMRamMap); InitPointer(m_pRunToBreakpoint); InitPointer(m_pBios); InitPointer(m_pRam); + InitPointer(m_pSGMRam); m_bBiosLoaded = false; + m_bSGMUpper = false; + m_bSGMLower = false; + m_RomBankAddress = 0; + m_RomBank = 0; } Memory::~Memory() { SafeDeleteArray(m_pBios); SafeDeleteArray(m_pRam); + SafeDeleteArray(m_pSGMRam); if (IsValidPointer(m_pDisassembledRomMap)) { @@ -70,13 +76,13 @@ Memory::~Memory() SafeDeleteArray(m_pDisassembledBiosMap); } - if (IsValidPointer(m_pDisassembledExpansionMap)) + if (IsValidPointer(m_pDisassembledSGMRamMap)) { - for (int i = 0; i < 0x4000; i++) + for (int i = 0; i < 0x8000; i++) { - SafeDelete(m_pDisassembledExpansionMap[i]); + SafeDelete(m_pDisassembledSGMRamMap[i]); } - SafeDeleteArray(m_pDisassembledExpansionMap); + SafeDeleteArray(m_pDisassembledSGMRamMap); } } @@ -89,6 +95,7 @@ void Memory::Init() { m_pRam = new u8[0x0400]; m_pBios = new u8[0x2000]; + m_pSGMRam = new u8[0x8000]; #ifndef GEARCOLECO_DISABLE_DISASSEMBLER m_pDisassembledRomMap = new stDisassembleRecord*[MAX_ROM_SIZE]; @@ -109,10 +116,10 @@ void Memory::Init() InitPointer(m_pDisassembledBiosMap[i]); } - m_pDisassembledExpansionMap = new stDisassembleRecord*[0x4000]; - for (int i = 0; i < 0x4000; i++) + m_pDisassembledSGMRamMap = new stDisassembleRecord*[0x8000]; + for (int i = 0; i < 0x8000; i++) { - InitPointer(m_pDisassembledExpansionMap[i]); + InitPointer(m_pDisassembledSGMRamMap[i]); } #endif @@ -126,11 +133,21 @@ void Memory::Init() void Memory::Reset() { + m_bSGMUpper = false; + m_bSGMLower = false; + m_RomBank = 0; + m_RomBankAddress = 0x0000; + for (int i = 0; i < 0x400; i++) { m_pRam[i] = rand() % 256; } + for (int i = 0; i < 0x8000; i++) + { + m_pSGMRam[i] = rand() % 256; + } + if (m_pCartridge->IsPAL()) m_pBios[0x69] = 0x32; else @@ -140,11 +157,21 @@ void Memory::Reset() void Memory::SaveState(std::ostream& stream) { stream.write(reinterpret_cast (m_pRam), 0x400); + stream.write(reinterpret_cast (m_pSGMRam), 0x8000); + stream.write(reinterpret_cast (m_bSGMUpper), sizeof(m_bSGMUpper)); + stream.write(reinterpret_cast (m_bSGMLower), sizeof(m_bSGMLower)); + stream.write(reinterpret_cast (m_RomBankAddress), sizeof(m_RomBankAddress)); + stream.write(reinterpret_cast (m_RomBank), sizeof(m_RomBank)); } void Memory::LoadState(std::istream& stream) { stream.read(reinterpret_cast (m_pRam), 0x400); + stream.read(reinterpret_cast (m_pSGMRam), 0x8000); + stream.read(reinterpret_cast (m_bSGMUpper), sizeof(m_bSGMUpper)); + stream.read(reinterpret_cast (m_bSGMLower), sizeof(m_bSGMLower)); + stream.read(reinterpret_cast (m_RomBankAddress), sizeof(m_RomBankAddress)); + stream.read(reinterpret_cast (m_RomBank), sizeof(m_RomBank)); } std::vector* Memory::GetBreakpointsCPU() @@ -204,16 +231,42 @@ u8* Memory::GetRam() return m_pRam; } +u8* Memory::GetSGMRam() +{ + return m_pSGMRam; +} + + u8* Memory::GetBios() { return m_pBios; } +u8 Memory::GetRomBank() +{ + return m_RomBank; +} + +u32 Memory::GetRomBankAddress() +{ + return m_RomBankAddress; +} + bool Memory::IsBiosLoaded() { return m_bBiosLoaded; } +void Memory::EnableSGMUpper(bool enable) +{ + m_bSGMUpper = enable; +} + +void Memory::EnableSGMLower(bool enable) +{ + m_bSGMLower = enable; +} + void Memory::CheckBreakpoints(u16 address, bool write) { size_t size = m_BreakpointsMem.size(); @@ -281,11 +334,11 @@ void Memory::ResetRomDisassembledMemory() } } - if (IsValidPointer(m_pDisassembledExpansionMap)) + if (IsValidPointer(m_pDisassembledSGMRamMap)) { - for (int i = 0; i < 0x4000; i++) + for (int i = 0; i < 0x8000; i++) { - SafeDelete(m_pDisassembledExpansionMap[i]); + SafeDelete(m_pDisassembledSGMRamMap[i]); } } @@ -299,36 +352,55 @@ Memory::stDisassembleRecord* Memory::GetDisassembleRecord(u16 address, bool crea stDisassembleRecord** map = NULL; int offset = address; int segment = 0; + int bank = 0; switch (address & 0xE000) { case 0x0000: { offset = address; - map = m_pDisassembledBiosMap; - segment = 0; + map = m_bSGMLower ? m_pDisassembledSGMRamMap : m_pDisassembledBiosMap; + segment = m_bSGMLower ? 1 : 0; break; } case 0x2000: case 0x4000: { - offset = address - 0x2000; - map = m_pDisassembledExpansionMap; + offset = address; + map = m_pDisassembledSGMRamMap; segment = 1; break; } case 0x6000: { - offset = address & 0x03FF; - map = m_pDisassembledRamMap; - segment = 2; + offset = m_bSGMUpper ? address : address & 0x03FF; + map = m_bSGMUpper ? m_pDisassembledSGMRamMap : m_pDisassembledRamMap; + segment = m_bSGMUpper ? 1 : 2; break; } default: { - offset = address - 0x8000; - map = m_pDisassembledRomMap; - segment = 3; + if (m_pCartridge->GetType() == Cartridge::CartridgeMegaCart) + { + map = m_pDisassembledRomMap; + segment = 3; + if (address < 0xC000) + { + offset = (address & 0x3FFF) + (m_pCartridge->GetROMSize() - 0x4000); + bank = m_pCartridge->GetROMBankCount() - 1; + } + else + { + offset = (address & 0x3FFF) + m_RomBankAddress; + bank = m_RomBank; + } + } + else + { + offset = address - 0x8000; + map = m_pDisassembledRomMap; + segment = 3; + } } } @@ -337,7 +409,7 @@ Memory::stDisassembleRecord* Memory::GetDisassembleRecord(u16 address, bool crea map[offset] = new Memory::stDisassembleRecord; map[offset]->address = address; - map[offset]->bank = 0; + map[offset]->bank = bank; map[offset]->name[0] = 0; map[offset]->bytes[0] = 0; map[offset]->size = 0; @@ -355,7 +427,7 @@ Memory::stDisassembleRecord* Memory::GetDisassembleRecord(u16 address, bool crea } case 1: { - strcpy(map[offset]->segment, "EXP "); + strcpy(map[offset]->segment, "SGM "); break; } case 2: @@ -365,7 +437,7 @@ Memory::stDisassembleRecord* Memory::GetDisassembleRecord(u16 address, bool crea } case 3: { - strcpy(map[offset]->segment, "ROM "); + strcpy(map[offset]->segment, "ROM"); break; } } diff --git a/src/Memory.h b/src/Memory.h index 4354f4b..2924852 100644 --- a/src/Memory.h +++ b/src/Memory.h @@ -60,7 +60,10 @@ class Memory u8 Read(u16 address); void Write(u16 address, u8 value); u8* GetRam(); + u8* GetSGMRam(); u8* GetBios(); + u8 GetRomBank(); + u32 GetRomBankAddress(); void LoadBios(const char* szFilePath); bool IsBiosLoaded(); void SaveState(std::ostream& stream); @@ -70,11 +73,13 @@ class Memory stDisassembleRecord** GetDisassembledRomMemoryMap(); stDisassembleRecord** GetDisassembledRamMemoryMap(); stDisassembleRecord** GetDisassembledBiosMemoryMap(); - stDisassembleRecord** GetDisassembledExpansionMemoryMap(); + stDisassembleRecord** GetDisassembledSGMRamMemoryMap(); std::vector* GetBreakpointsCPU(); std::vector* GetBreakpointsMem(); stDisassembleRecord* GetRunToBreakpoint(); void SetRunToBreakpoint(stDisassembleRecord* pBreakpoint); + void EnableSGMUpper(bool enable); + void EnableSGMLower(bool enable); private: void CheckBreakpoints(u16 address, bool write); @@ -85,13 +90,18 @@ class Memory stDisassembleRecord** m_pDisassembledRomMap; stDisassembleRecord** m_pDisassembledRamMap; stDisassembleRecord** m_pDisassembledBiosMap; - stDisassembleRecord** m_pDisassembledExpansionMap; + stDisassembleRecord** m_pDisassembledSGMRamMap; std::vector m_BreakpointsCPU; std::vector m_BreakpointsMem; stDisassembleRecord* m_pRunToBreakpoint; bool m_bBiosLoaded; + bool m_bSGMUpper; + bool m_bSGMLower; u8* m_pBios; u8* m_pRam; + u8* m_pSGMRam; + u32 m_RomBankAddress; + u8 m_RomBank; }; #include "Memory_inline.h" diff --git a/src/Memory_inline.h b/src/Memory_inline.h index 94499f4..ae163de 100644 --- a/src/Memory_inline.h +++ b/src/Memory_inline.h @@ -32,17 +32,16 @@ inline u8 Memory::Read(u16 address) { case 0x0000: { - return m_pBios[address]; + return m_bSGMLower ? m_pSGMRam[address] : m_pBios[address]; } case 0x2000: case 0x4000: { - Log("--> ** Attempting to read from expansion: %X", address); - return 0xFF; + return m_bSGMUpper ? m_pSGMRam[address] : 0xFF; } case 0x6000: { - return m_pRam[address & 0x03FF]; + return m_bSGMUpper ? m_pSGMRam[address] : m_pRam[address & 0x03FF]; } case 0x8000: case 0xA000: @@ -52,13 +51,32 @@ inline u8 Memory::Read(u16 address) u8* pRom = m_pCartridge->GetROM(); int romSize = m_pCartridge->GetROMSize(); - if (address >= (romSize + 0x8000)) + if (m_pCartridge->GetType() == Cartridge::CartridgeMegaCart) { - Log("--> ** Attempting to read from outer ROM: %X. ROM Size: %X", address, romSize); - return 0xFF; + if (address < 0xC000) + { + return pRom[(address & 0x3FFF) + (romSize - 0x4000)]; + } + else + { + if (address >= 0xFFC0) + { + m_RomBank = address & (m_pCartridge->GetROMBankCount() - 1); + m_RomBankAddress = m_RomBank << 14; + } + return pRom[(address & 0x3FFF) + m_RomBankAddress]; + } } + else + { + if (address >= (romSize + 0x8000)) + { + Log("--> ** Attempting to read from outer ROM: %X. ROM Size: %X", address, romSize); + return 0xFF; + } - return pRom[address & 0x7FFF]; + return pRom[address & 0x7FFF]; + } } default: return 0xFF; @@ -75,18 +93,23 @@ inline void Memory::Write(u16 address, u8 value) { case 0x0000: { - Log("--> ** Attempting to write on BIOS: %X %X", address, value); + if (m_bSGMLower) + m_pSGMRam[address] = value; break; } case 0x2000: case 0x4000: { - Log("--> ** Attempting to write on expansion: %X %X", address, value); + if (m_bSGMUpper) + m_pSGMRam[address] = value; break; } case 0x6000: { - m_pRam[address & 0x03FF] = value; + if (m_bSGMUpper) + m_pSGMRam[address] = value; + else + m_pRam[address & 0x03FF] = value; break; } case 0x8000: @@ -103,6 +126,11 @@ inline void Memory::Write(u16 address, u8 value) u8* pRom = m_pCartridge->GetROM(); pRom[(address + 0x800) & 0x7FFF] = value; } + else if ((m_pCartridge->GetType() == Cartridge::CartridgeMegaCart) && (address >= 0xFFC0)) + { + m_RomBank = address & (m_pCartridge->GetROMBankCount() - 1); + m_RomBankAddress = m_RomBank << 14; + } else { Log("--> ** Attempting to write on ROM: %X %X", address, value); @@ -127,9 +155,9 @@ inline Memory::stDisassembleRecord** Memory::GetDisassembledBiosMemoryMap() return m_pDisassembledBiosMap; } -inline Memory::stDisassembleRecord** Memory::GetDisassembledExpansionMemoryMap() +inline Memory::stDisassembleRecord** Memory::GetDisassembledSGMRamMemoryMap() { - return m_pDisassembledExpansionMap; + return m_pDisassembledSGMRamMap; } #endif /* MEMORY_INLINE_H */