From 9f5a19a04ad50777135f86b8469556b5a194ad0d Mon Sep 17 00:00:00 2001 From: Ian Curtis Date: Mon, 9 Jul 2018 08:06:06 +0000 Subject: [PATCH] Use correct PCI IDs (Harry Tuttle) --- Config/Games.xml | 63 +-- Src/Graphics/New3D/New3D.cpp | 29 +- Src/Model3/Model3.cpp | 995 ++++++++++++++++++----------------- Src/Model3/Real3D.cpp | 110 ++-- Src/Model3/Real3D.h | 15 +- 5 files changed, 594 insertions(+), 618 deletions(-) diff --git a/Config/Games.xml b/Config/Games.xml index 61b43e5..0cfd12e 100644 --- a/Config/Games.xml +++ b/Config/Games.xml @@ -457,7 +457,7 @@ - + @@ -574,7 +574,7 @@ - + @@ -850,11 +850,7 @@ - - - - - + @@ -1128,6 +1124,10 @@ + + + + @@ -1639,6 +1639,7 @@ + @@ -1810,14 +1811,8 @@ - - - - - - - - + + @@ -1876,7 +1871,8 @@ - + @@ -2293,16 +2290,6 @@ - - - - @@ -2330,10 +2317,6 @@ - - - - @@ -2362,18 +2345,6 @@ 0x29234e96 - - - - @@ -2448,10 +2419,6 @@ - - - - @@ -2581,10 +2548,6 @@ - - - - diff --git a/Src/Graphics/New3D/New3D.cpp b/Src/Graphics/New3D/New3D.cpp index 3ded60f..3dd339b 100644 --- a/Src/Graphics/New3D/New3D.cpp +++ b/Src/Graphics/New3D/New3D.cpp @@ -23,15 +23,12 @@ CNew3D::CNew3D(const Util::Config::Node &config, std::string gameName) m_cullingRAMHi = nullptr; m_polyRAM = nullptr; m_vrom = nullptr; - m_textureRAM = nullptr; - m_sunClamp = true; - m_shadeIsSigned = true; - - // Fall-back mechanism for games with patched (not working) JTAG - if (m_gameName == "swtrilgy") m_shadeIsSigned = false; -} - -CNew3D::~CNew3D() + m_textureRAM = nullptr; + m_sunClamp = true; + m_shadeIsSigned = true; +} + +CNew3D::~CNew3D() { m_vbo.Destroy(); } @@ -1662,12 +1659,10 @@ void CNew3D::SetSunClamp(bool enable) { m_sunClamp = enable; } - -void CNew3D::SetSignedShade(bool enable) -{ - if (m_gameName == "swtrilgy") return; // jtag has been patched out in star wars - todo fix this - - m_shadeIsSigned = enable; -} - + +void CNew3D::SetSignedShade(bool enable) +{ + m_shadeIsSigned = enable; +} + } // New3D diff --git a/Src/Model3/Model3.cpp b/Src/Model3/Model3.cpp index efd6c98..8ddd63d 100644 --- a/Src/Model3/Model3.cpp +++ b/Src/Model3/Model3.cpp @@ -523,13 +523,13 @@ UINT8 CModel3::ReadInputs(unsigned reg) if (m_game.inputs & (Game::INPUT_GUN1 | Game::INPUT_GUN2)) { return 0x0C; } - else { - return 0; - } - - case 0x3C: // ADC - - // Load ADC channels with input data + else { + return 0; + } + + case 0x3C: // ADC + + // Load ADC channels with input data memset(adc, 0, sizeof(adc)); if ((m_game.inputs & Game::INPUT_VEHICLE)) { @@ -892,126 +892,128 @@ UINT8 CModel3::Read8(UINT32 addr) if (addr<0x00800000) return ram[addr^3]; - // Other - switch ((addr >> 24)) - { - // CROM - case 0xFF: - if (addr < 0xFF800000) - return cromBank[(addr & 0x7FFFFF) ^ 3]; - else - return crom[(addr & 0x7FFFFF) ^ 3]; - - // Real3D DMA - case 0xC2: - return GPU.ReadDMARegister8(addr & 0xFF); - - // Various - case 0xF0: - case 0xFE: // mirror - - switch ((addr >> 16) & 0xFF) - { - // Inputs - case 0x04: - return ReadInputs(addr & 0x3F); - - // Sound Board - case 0x08: - if ((addr & 0xF) == 4) // MIDI control port - return 0x83; // magtruck country check - else - return 0; - break; - - // System registers - case 0x10: - return ReadSystemRegister(addr & 0x3F); - - // RTC - case 0x14: - if ((addr & 3) == 1) // battery voltage test - return 0x03; - else if ((addr & 3) == 0) - return RTC.ReadRegister((addr >> 2) & 0xF); - return 0; - - // Unknown - default: - //printf("CMODEL3 : unknown R8 mirror : %x\n", addr >> 16); - break; - } - - break; - - // Tile generator - case 0xF1: - if (addr < 0xF1120000) - { - // Tile generator accesses its RAM as little endian, no adjustment needed here - return TileGen.ReadRAM8(addr & 0x1FFFFF); - } - break; - - // 53C810 SCSI - case 0xC0: // only on Step 1.0 -#ifndef NET_BOARD - if (m_game.stepping != "1.0") - { - //printf("Model3 : Read8 %x\n", addr); - break; - } -#endif -#ifdef NET_BOARD - if (m_game.stepping != "1.0" && (NetBoard.IsAttached() && (m_config["EmulateNet"].ValueAs()))) // check for Step 1.0 - { - switch ((addr & 0x3ffff) >> 16) - { - case 0: - //printf("R8 netbuffer @%x=%x\n", (addr & 0xFFFF), netBuffer[(addr & 0xFFFF)]); - return netBuffer[(addr & 0xFFFF)]; - - case 1: // ioreg 32bits access in 16bits environment - if (addr > 0xc00101ff) - { - printf("R8 ATTENTION OUT OF RANGE\n"); - MessageBox(NULL, "Out of Range", NULL, MB_OK); - } - printf("R8 ioreg @%x=%x\n", (addr & 0x1FF), netBuffer[0x10000 + ((addr & 0x1FF) / 2)]); - return netBuffer[0x10000 + ((addr & 0x1FF) / 2)]; - - case 2: - case 3: - if (addr > 0xc002ffff) - { - printf("R8 ATTENTION OUT OF RANGE\n"); - MessageBox(NULL, "Out of Range", NULL, MB_OK); - } - //printf("R8 netram @%x=%x\n", (addr & 0x1FFFF), netRAM[addr & 0x1ffff]); - return netRAM[((addr & 0x1FFFF) / 2)]; - /*case 3: - //printf("R8 netram @%x=%x\n", (addr & 0x1FFFF), netRAM[addr & 0x1ffff]); - return netRAM[((addr & 0x1FFFF) / 2)];*/ - - default: - printf("R8 ATTENTION OUT OF RANGE\n"); - MessageBox(NULL, "Out of Range", NULL, MB_OK); - break; - } - } - else if (m_game.stepping != "1.0") break; -#endif - case 0xF9: - case 0xC1: + // Other + switch ((addr >> 24)) + { + // CROM + case 0xFF: + if (addr < 0xFF800000) + return cromBank[(addr & 0x7FFFFF) ^ 3]; + else + return crom[(addr & 0x7FFFFF) ^ 3]; + + // Real3D DMA + case 0xC2: + return GPU.ReadDMARegister8(addr & 0xFF); + + // Various + case 0xF0: + case 0xFE: // mirror + + switch ((addr >> 16) & 0xFF) + { + // Inputs + case 0x04: + return ReadInputs(addr & 0x3F); + + // Sound Board + case 0x08: + if ((addr & 0xF) == 4) // MIDI control port + + return 0x83; // magtruck country check + + else + return 0; + break; + + // System registers + case 0x10: + return ReadSystemRegister(addr & 0x3F); + + // RTC + case 0x14: + if ((addr & 3) == 1) // battery voltage test + return 0x03; + else if ((addr & 3) == 0) + return RTC.ReadRegister((addr >> 2) & 0xF); + return 0; + + // Unknown + default: + //printf("CMODEL3 : unknown R8 mirror : %x\n", addr >> 16); + break; + } + + break; + + // Tile generator + case 0xF1: + if (addr < 0xF1120000) + { + // Tile generator accesses its RAM as little endian, no adjustment needed here + return TileGen.ReadRAM8(addr & 0x1FFFFF); + } + break; + + // 53C810 SCSI + case 0xC0: // only on Step 1.0 +#ifndef NET_BOARD + if (m_game.stepping != "1.0") + { + //printf("Model3 : Read8 %x\n", addr); + break; + } +#endif +#ifdef NET_BOARD + if (m_game.stepping != "1.0" && (NetBoard.IsAttached() && (m_config["EmulateNet"].ValueAs()))) // check for Step 1.0 + { + switch ((addr & 0x3ffff) >> 16) + { + case 0: + //printf("R8 netbuffer @%x=%x\n", (addr & 0xFFFF), netBuffer[(addr & 0xFFFF)]); + return netBuffer[(addr & 0xFFFF)]; + + case 1: // ioreg 32bits access in 16bits environment + if (addr > 0xc00101ff) + { + printf("R8 ATTENTION OUT OF RANGE\n"); + MessageBox(NULL, "Out of Range", NULL, MB_OK); + } + printf("R8 ioreg @%x=%x\n", (addr & 0x1FF), netBuffer[0x10000 + ((addr & 0x1FF) / 2)]); + return netBuffer[0x10000 + ((addr & 0x1FF) / 2)]; + + case 2: + case 3: + if (addr > 0xc002ffff) + { + printf("R8 ATTENTION OUT OF RANGE\n"); + MessageBox(NULL, "Out of Range", NULL, MB_OK); + } + //printf("R8 netram @%x=%x\n", (addr & 0x1FFFF), netRAM[addr & 0x1ffff]); + return netRAM[((addr & 0x1FFFF) / 2)]; + /*case 3: + //printf("R8 netram @%x=%x\n", (addr & 0x1FFFF), netRAM[addr & 0x1ffff]); + return netRAM[((addr & 0x1FFFF) / 2)];*/ + + default: + printf("R8 ATTENTION OUT OF RANGE\n"); + MessageBox(NULL, "Out of Range", NULL, MB_OK); + break; + } + } + else if (m_game.stepping != "1.0") break; +#endif + case 0xF9: + case 0xC1: return SCSI.ReadRegister(addr&0xFF); - // Unknown - default: -#ifdef NET_BOARD - printf("CMODEL3 : unknown R8 : %x\n", addr >> 24); -#endif - break; - } + // Unknown + default: +#ifdef NET_BOARD + printf("CMODEL3 : unknown R8 : %x\n", addr >> 24); +#endif + break; + } DebugLog("PC=%08X\tread8 : %08X\n", ppc_get_pc(), addr); return 0xFF; @@ -1080,13 +1082,13 @@ UINT16 CModel3::Read16(UINT32 addr) case 0xEE: case 0xEF: return PCIBridge.ReadPCIConfigData(16,addr&3); - - // Unknown - default: - //printf("CMODEL3 : unknown R16 mirror : %x\n", addr >> 16); - break; - } - + + // Unknown + default: + //printf("CMODEL3 : unknown R16 mirror : %x\n", addr >> 16); + break; + } + break; // Tile generator @@ -1098,33 +1100,33 @@ UINT16 CModel3::Read16(UINT32 addr) return FLIPENDIAN16(data); } break; - -#ifdef NET_BOARD - case 0xc0: // spikeout call this - // interresting : poking @4 master to same value as slave (0x100) or simply !=0 -> connected and go in game, but freeze (prints comm error) as soon as players appear after the gate - // sort of sync ack ? who writes this 16b value ? - { - UINT16 result; - switch ((addr & 0x3ffff) >> 16) - { - case 0: - //printf("R16 netbuffer @%x=%x\n", (addr & 0xFFFF), FLIPENDIAN16(*(UINT16 *)&netBuffer[(addr & 0xFFFF)])); - result = *(UINT16 *)&netBuffer[(addr & 0xFFFF)]; - return FLIPENDIAN16(result); // result - default: - printf("CMODEL3 : unknown R16 : %x (C0)\n", addr); - break; - } - } -#endif - // Unknown - default: -#ifdef NET_BOARD - printf("CMODEL3 : unknown R16 : %x (%x)\n", addr, addr >> 24); - MessageBox(NULL, "CMODEL3 : Unknown R16", NULL, MB_OK); -#endif - break; - } + +#ifdef NET_BOARD + case 0xc0: // spikeout call this + // interresting : poking @4 master to same value as slave (0x100) or simply !=0 -> connected and go in game, but freeze (prints comm error) as soon as players appear after the gate + // sort of sync ack ? who writes this 16b value ? + { + UINT16 result; + switch ((addr & 0x3ffff) >> 16) + { + case 0: + //printf("R16 netbuffer @%x=%x\n", (addr & 0xFFFF), FLIPENDIAN16(*(UINT16 *)&netBuffer[(addr & 0xFFFF)])); + result = *(UINT16 *)&netBuffer[(addr & 0xFFFF)]; + return FLIPENDIAN16(result); // result + default: + printf("CMODEL3 : unknown R16 : %x (C0)\n", addr); + break; + } + } +#endif + // Unknown + default: +#ifdef NET_BOARD + printf("CMODEL3 : unknown R16 : %x (%x)\n", addr, addr >> 24); + MessageBox(NULL, "CMODEL3 : Unknown R16", NULL, MB_OK); +#endif + break; + } DebugLog("PC=%08X\tread16: %08X\n", ppc_get_pc(), addr); return 0xFFFF; @@ -1234,13 +1236,13 @@ UINT32 CModel3::Read32(UINT32 addr) // Security board registers case 0x1A: return ReadSecurity(addr&0x3F); - - // Unknown - default: - //printf("CModel 3 unknown R32 mirror %x", (addr >> 16) & 0xFF); - break; - } - + + // Unknown + default: + //printf("CModel 3 unknown R32 mirror %x", (addr >> 16) & 0xFF); + break; + } + break; // Tile generator @@ -1272,13 +1274,13 @@ UINT32 CModel3::Read32(UINT32 addr) switch ((addr & 0x3ffff) >> 16) { - case 0: - //printf("R32 netbuffer @%x=%x\n", (addr & 0xFFFF), FLIPENDIAN32(*(UINT32 *)&netBuffer[(addr & 0xFFFF)])); - result = *(UINT32 *)&netBuffer[(addr & 0xFFFF)]; - return _rotl(FLIPENDIAN32(result), 16); - //return FLIPENDIAN32(result); // result - - case 1: // ioreg 32bits access to 16bits range + case 0: + //printf("R32 netbuffer @%x=%x\n", (addr & 0xFFFF), FLIPENDIAN32(*(UINT32 *)&netBuffer[(addr & 0xFFFF)])); + result = *(UINT32 *)&netBuffer[(addr & 0xFFFF)]; + return _rotl(FLIPENDIAN32(result), 16); + //return FLIPENDIAN32(result); // result + + case 1: // ioreg 32bits access to 16bits range //printf("R32 ioreg @%x=%x\n", (addr & 0x1FF), FLIPENDIAN32(*(UINT32 *)&netBuffer[0x10000 + ((addr & 0x1FF) / 2)])); if (addr > 0xc00101ff) { @@ -1313,26 +1315,26 @@ UINT32 CModel3::Read32(UINT32 addr) default: printf("R32 ATTENTION OUT OF RANGE\n"); break; - } - - } - else if (m_game.stepping != "1.0") break; -#endif - case 0xF9: - case 0xC1: + } + + } + else if (m_game.stepping != "1.0") break; +#endif + case 0xF9: + case 0xC1: data = (SCSI.ReadRegister((addr+0)&0xFF) << 24); data |= (SCSI.ReadRegister((addr+1)&0xFF) << 16); data |= (SCSI.ReadRegister((addr+2)&0xFF) << 8); data |= (SCSI.ReadRegister((addr+3)&0xFF) << 0); return data; - // Unknown - default: -#ifdef NET_BOARD - printf("CMODEL3 : unknown R32 : %x\n", addr >> 24); -#endif - break; - } + // Unknown + default: +#ifdef NET_BOARD + printf("CMODEL3 : unknown R32 : %x\n", addr >> 24); +#endif + break; + } DebugLog("PC=%08X\tread32: %08X\n", ppc_get_pc(), addr); return 0xFFFFFFFF; @@ -1410,13 +1412,13 @@ void CModel3::Write8(UINT32 addr, UINT8 data) if ((addr&3)==0) RTC.WriteRegister((addr>>2)&0xF,data); break; - - // Unknown - default: - //printf("CMODEL3 : unknown W8 mirror : %x\n", addr >> 16); - break; - } - + + // Unknown + default: + //printf("CMODEL3 : unknown W8 mirror : %x\n", addr >> 16); + break; + } + DebugLog("PC=%08X\twrite8 : %08X=%02X\n", ppc_get_pc(), addr, data); break; @@ -1425,13 +1427,13 @@ void CModel3::Write8(UINT32 addr, UINT8 data) if (addr < 0xF1120000) { // Tile generator accesses its RAM as little endian, no adjustment needed here - TileGen.WriteRAM8(addr&0x1FFFFF, data); - break; - } - goto Unknown8; - - // MPC105/106 - case 0xF8: + TileGen.WriteRAM8(addr&0x1FFFFF, data); + break; + } + goto Unknown8; + + // MPC105/106 + case 0xF8: PCIBridge.WriteRegister(addr&0xFF,data); break; @@ -1489,13 +1491,13 @@ void CModel3::Write8(UINT32 addr, UINT8 data) NetBoard.CodeReady = true; NetBoard.Reset(); } - - break; - } - else if (m_game.stepping != "1.0") break; -#endif - case 0xF9: - case 0xC1: + + break; + } + else if (m_game.stepping != "1.0") break; +#endif + case 0xF9: + case 0xC1: SCSI.WriteRegister(addr&0xFF,data); break; @@ -1550,13 +1552,13 @@ void CModel3::Write16(UINT32 addr, UINT16 data) case 0xC0: // F0C00CF8 PCIBridge.WritePCIConfigData(16,addr&2,data); break; - - // Unknown - default: - //printf("CMODEL3 : unknown W16 mirror : %x\n", addr >> 16); - break; - } - + + // Unknown + default: + //printf("CMODEL3 : unknown W16 mirror : %x\n", addr >> 16); + break; + } + DebugLog("PC=%08X\twrite16 : %08X=%04X\n", ppc_get_pc(), addr, data); break; @@ -1575,34 +1577,35 @@ void CModel3::Write16(UINT32 addr, UINT16 data) PCIBridge.WriteRegister((addr&0xFF)+0,data>>8); PCIBridge.WriteRegister((addr&0xFF)+1,data&0xFF); break; - -#ifdef NET_BOARD - case 0xC0: // skichamp only - //printf("CModel 3 : write16 %x<-%x\n", addr, data); - - switch ((addr & 0x3ffff) >> 16) - { - case 0: - //printf("W16 netbuffer @%x<-%x\n", (addr & 0xFFFF), data); - *(UINT16 *)&netBuffer[(addr & 0xFFFF)] = FLIPENDIAN16(data); - break; - - default: - printf("CMODEL3 : unknown W16 : %x\n", addr >> 24); - break; - } - - break; -#endif - - // Unknown - default: - Unknown16: - DebugLog("PC=%08X\twrite16: %08X=%04X\n", ppc_get_pc(), addr, data); - break; - } -} - + +#ifdef NET_BOARD + case 0xC0: // skichamp only + //printf("CModel 3 : write16 %x<-%x\n", addr, data); + + + switch ((addr & 0x3ffff) >> 16) + { + case 0: + //printf("W16 netbuffer @%x<-%x\n", (addr & 0xFFFF), data); + *(UINT16 *)&netBuffer[(addr & 0xFFFF)] = FLIPENDIAN16(data); + break; + + default: + //printf("CMODEL3 : unknown W16 : %x\n", addr >> 24); + break; + } + + break; +#endif + + // Unknown + default: + Unknown16: + DebugLog("PC=%08X\twrite16: %08X=%04X\n", ppc_get_pc(), addr, data); + break; + } +} + void CModel3::Write32(UINT32 addr, UINT32 data) { if ((addr&3)) @@ -1690,28 +1693,28 @@ void CModel3::Write32(UINT32 addr, UINT32 data) // MPC105 case 0x80: // F0800CF8 (never observed at 0xFExxxxxx) PCIBridge.WritePCIConfigAddress(data); - break; - - // MPC105/106 - case 0xC0: case 0xD0: case 0xE0: - case 0xC1: case 0xD1: case 0xE1: - case 0xC2: case 0xD2: case 0xE2: - case 0xC3: case 0xD3: case 0xE3: - case 0xC4: case 0xD4: case 0xE4: - case 0xC5: case 0xD5: case 0xE5: - case 0xC6: case 0xD6: case 0xE6: - case 0xC7: case 0xD7: case 0xE7: - case 0xC8: case 0xD8: case 0xE8: - case 0xC9: case 0xD9: case 0xE9: - case 0xCA: case 0xDA: case 0xEA: - case 0xCB: case 0xDB: case 0xEB: - case 0xCC: case 0xDC: case 0xEC: - case 0xCD: case 0xDD: case 0xED: - case 0xCE: case 0xDE: case 0xEE: - case 0xCF: case 0xDF: case 0xEF: - if ((addr>=0xF0C00CF8) && (addr<0xF0C00D00)) // MPC105 - PCIBridge.WritePCIConfigData(32,0,data); - else if ((addr>=0xFEC00000) && (addr<0xFEE00000)) // MPC106 + break; + + // MPC105/106 + case 0xC0: case 0xD0: case 0xE0: + case 0xC1: case 0xD1: case 0xE1: + case 0xC2: case 0xD2: case 0xE2: + case 0xC3: case 0xD3: case 0xE3: + case 0xC4: case 0xD4: case 0xE4: + case 0xC5: case 0xD5: case 0xE5: + case 0xC6: case 0xD6: case 0xE6: + case 0xC7: case 0xD7: case 0xE7: + case 0xC8: case 0xD8: case 0xE8: + case 0xC9: case 0xD9: case 0xE9: + case 0xCA: case 0xDA: case 0xEA: + case 0xCB: case 0xDB: case 0xEB: + case 0xCC: case 0xDC: case 0xEC: + case 0xCD: case 0xDD: case 0xED: + case 0xCE: case 0xDE: case 0xEE: + case 0xCF: case 0xDF: case 0xEF: + if ((addr>=0xF0C00CF8) && (addr<0xF0C00D00)) // MPC105 + PCIBridge.WritePCIConfigData(32,0,data); + else if ((addr>=0xFEC00000) && (addr<0xFEE00000)) // MPC106 PCIBridge.WritePCIConfigAddress(data); else if ((addr>=0xFEE00000) && (addr<0xFEF00000)) // MPC106 PCIBridge.WritePCIConfigData(32,0,data); @@ -1737,16 +1740,16 @@ void CModel3::Write32(UINT32 addr, UINT32 data) break; // Security board registers - case 0x1A: - WriteSecurity(addr&0x3F,data); - break; - - // Unknown - default: - //printf("CMODEL3 : unknown W32 mirror : %x\n", addr >> 16); - break; - } - + case 0x1A: + WriteSecurity(addr&0x3F,data); + break; + + // Unknown + default: + //printf("CMODEL3 : unknown W32 mirror : %x\n", addr >> 16); + break; + } + DebugLog("PC=%08X\twrite32: %08X=%08X\n", ppc_get_pc(), addr, data); break; @@ -1777,23 +1780,23 @@ void CModel3::Write32(UINT32 addr, UINT32 data) break; // 53C810 SCSI - case 0xC0: // step 1.0 only -#ifndef NET_BOARD - if (m_game.stepping != "1.0") - goto Unknown32; -#endif -#ifdef NET_BOARD - if (m_game.stepping != "1.0" && (NetBoard.IsAttached() && (m_config["EmulateNet"].ValueAs()))) // assuming there is no scsi card for step>1.0 because same address for network card (right or wrong ??) + case 0xC0: // step 1.0 only +#ifndef NET_BOARD + if (m_game.stepping != "1.0") + goto Unknown32; +#endif +#ifdef NET_BOARD + if (m_game.stepping != "1.0" && (NetBoard.IsAttached() && (m_config["EmulateNet"].ValueAs()))) // assuming there is no scsi card for step>1.0 because same address for network card (right or wrong ??) { switch ((addr & 0x3ffff) >> 16) { - case 0: - //printf("W32 netbuffer @%x<-%x\n", (addr & 0xFFFF), data); - //*(UINT32 *)&netBuffer[(addr & 0xFFFF)] = FLIPENDIAN32(data); - *(UINT32 *)&netBuffer[(addr & 0xFFFF)] = _rotl(FLIPENDIAN32(data), 16); - break; - - case 1: // ioreg 32bits access to 16bits range + case 0: + //printf("W32 netbuffer @%x<-%x\n", (addr & 0xFFFF), data); + //*(UINT32 *)&netBuffer[(addr & 0xFFFF)] = FLIPENDIAN32(data); + *(UINT32 *)&netBuffer[(addr & 0xFFFF)] = _rotl(FLIPENDIAN32(data), 16); + break; + + case 1: // ioreg 32bits access to 16bits range if (addr > 0xc00101ff) { printf("W32 ATTENTION OUT OF RANGE\n"); @@ -1819,29 +1822,29 @@ void CModel3::Write32(UINT32 addr, UINT32 data) break;*/ default: printf("W32 ATTENTION OUT OF RANGE\n"); - break; - } - - if ((*(UINT16 *)&netBuffer[(0xc00100c0 & 0x3FFFF)] == FLIPENDIAN16(0x0000)) && NetBoard.CodeReady == true) // c0=180/2 // reset net when reboot - not perfect, I think memory must be cleared - { - printf("Network pause\n"); - NetBoard.CodeReady = false; - NetBoard.Reset(); - } - - if ((*(UINT16 *)&netBuffer[(0xc0010088 & 0x3FFFF)] == FLIPENDIAN16(0x0080)) && NetBoard.CodeReady == false) // 88=110/2 - { + break; + } + + if ((*(UINT16 *)&netBuffer[(0xc00100c0 & 0x3FFFF)] == FLIPENDIAN16(0x0000)) && NetBoard.CodeReady == true) // c0=180/2 // reset net when reboot - not perfect, I think memory must be cleared + { + printf("Network pause\n"); + NetBoard.CodeReady = false; + NetBoard.Reset(); + } + + if ((*(UINT16 *)&netBuffer[(0xc0010088 & 0x3FFFF)] == FLIPENDIAN16(0x0080)) && NetBoard.CodeReady == false) // 88=110/2 + { printf("Network code copy ending\n"); NetBoard.CodeReady = true; NetBoard.Reset(); } - - break; - } - else if (m_game.stepping != "1.0") break; -#endif - case 0xF9: - case 0xC1: + + break; + } + else if (m_game.stepping != "1.0") break; +#endif + case 0xF9: + case 0xC1: SCSI.WriteRegister((addr&0xFF)+0,(data>>24)&0xFF); SCSI.WriteRegister((addr&0xFF)+1,(data>>16)&0xFF); SCSI.WriteRegister((addr&0xFF)+2,(data>>8)&0xFF); @@ -1859,14 +1862,14 @@ void CModel3::Write32(UINT32 addr, UINT32 data) break; } } - -void CModel3::Write64(UINT32 addr, UINT64 data) -{ - //printf("write64 %x <- %x\n", addr, data); - Write32(addr+0, (UINT32) (data>>32)); - Write32(addr+4, (UINT32) data); -} - + +void CModel3::Write64(UINT32 addr, UINT64 data) +{ + //printf("write64 %x <- %x\n", addr, data); + Write32(addr+0, (UINT32) (data>>32)); + Write32(addr+4, (UINT32) data); +} + /****************************************************************************** Emulation and Interface Functions @@ -2020,40 +2023,40 @@ void CModel3::RunFrame(void) if (!notifyLock->Unlock()) goto ThreadError; - // If multi-threading GPU, then sync GPUs last while PPC main board thread is waiting - if (m_gpuMultiThreaded) - SyncGPUs(); - - /*if (NetBoard.IsAttached()) - RunNetBoardFrame();*/ - } - else - { + // If multi-threading GPU, then sync GPUs last while PPC main board thread is waiting + if (m_gpuMultiThreaded) + SyncGPUs(); + + /*if (NetBoard.IsAttached()) + RunNetBoardFrame();*/ + } + else + { // If not multi-threaded, then just process and render a single frame for PPC main board, sound board and drive board in turn in this thread RunMainBoardFrame(); SyncGPUs(); RenderFrame(); RunSoundBoardFrame(); - if (DriveBoard.IsAttached()) - RunDriveBoardFrame(); -#ifdef NET_BOARD - if (NetBoard.IsAttached() && (m_config["EmulateNet"].ValueAs()) && ((*(UINT16 *)&netBuffer[(0xc00100C0 & 0x3FFFF)] == 0xFFFF) || (netBuffer[(0xc00100C0 & 0x3FFFF)] == 0xFF) || (*(UINT16 *)&netBuffer[(0xc00100C0 & 0x3FFFF)] == 0x0001)) && (NetBoard.CodeReady == true)) - { - // ppc irq network needed ? no effect, is it really active/needed ? - //RunNetBoardFrame(); - IRQ.Assert(0x10); - ppc_execute(200); // give PowerPC time to acknowledge IRQ - //RunNetBoardFrame(); - IRQ.Deassert(0x10); - ppc_execute(200); // acknowledge that IRQ was deasserted (TODO: is this really needed?) - RunNetBoardFrame(); - // Hum hum, if runnetboardframe is called at 1st place or between ppc irq assert/deassert, spikout freezes just after the gate with net error - // if runnetboardframe is called after ppc irq assert/deassert, spikout works - } -#endif - } - - timings.frameTicks = CThread::GetTicks() - start; + if (DriveBoard.IsAttached()) + RunDriveBoardFrame(); +#ifdef NET_BOARD + if (NetBoard.IsAttached() && (m_config["EmulateNet"].ValueAs()) && ((*(UINT16 *)&netBuffer[(0xc00100C0 & 0x3FFFF)] == 0xFFFF) || (netBuffer[(0xc00100C0 & 0x3FFFF)] == 0xFF) || (*(UINT16 *)&netBuffer[(0xc00100C0 & 0x3FFFF)] == 0x0001)) && (NetBoard.CodeReady == true)) + { + // ppc irq network needed ? no effect, is it really active/needed ? + //RunNetBoardFrame(); + IRQ.Assert(0x10); + ppc_execute(200); // give PowerPC time to acknowledge IRQ + //RunNetBoardFrame(); + IRQ.Deassert(0x10); + ppc_execute(200); // acknowledge that IRQ was deasserted (TODO: is this really needed?) + RunNetBoardFrame(); + // Hum hum, if runnetboardframe is called at 1st place or between ppc irq assert/deassert, spikout freezes just after the gate with net error + // if runnetboardframe is called after ppc irq assert/deassert, spikout works + } +#endif + } + + timings.frameTicks = CThread::GetTicks() - start; return; @@ -2339,13 +2342,13 @@ void CModel3::RunDriveBoardFrame(void) timings.drvTicks = CThread::GetTicks() - start; } -#ifdef NET_BOARD -void CModel3::RunNetBoardFrame(void) -{ - NetBoard.RunFrame(); -} -#endif - +#ifdef NET_BOARD +void CModel3::RunNetBoardFrame(void) +{ + NetBoard.RunFrame(); +} +#endif + bool CModel3::StartThreads(void) { if (startedThreads) @@ -2408,13 +2411,13 @@ bool CModel3::StartThreads(void) goto ThreadError; } - // Set audio callback if sound board thread is unsync'd - if (!syncSndBrdThread) - { - SetAudioCallback(AudioCallback, this); - } - - startedThreads = true; + // Set audio callback if sound board thread is unsync'd + if (!syncSndBrdThread) + { + SetAudioCallback(AudioCallback, this); + } + + startedThreads = true; return true; ThreadError: @@ -2606,13 +2609,13 @@ void CModel3::DumpTimings(void) timings.renderTicks, (timings.renderTicks > timings.ppcTicks ? '!' : ','), timings.syncSize / 1024, (timings.syncSize / 1024 > 128 ? '!' : ','), timings.syncTicks, (timings.syncTicks > 1 ? '!' : ','), - timings.sndTicks, (timings.sndTicks > 10 ? '!' : ','), - timings.drvTicks, (timings.drvTicks > 10 ? '!' : ','), -#ifdef NET_BOARD - timings.netTicks, (timings.netTicks > 10 ? '!' : ','), -#endif - timings.frameTicks, (timings.frameTicks > 16 ? '!' : ' ')); -} + timings.sndTicks, (timings.sndTicks > 10 ? '!' : ','), + timings.drvTicks, (timings.drvTicks > 10 ? '!' : ','), +#ifdef NET_BOARD + timings.netTicks, (timings.netTicks > 10 ? '!' : ','), +#endif + timings.frameTicks, (timings.frameTicks > 16 ? '!' : ' ')); +} FrameTimings CModel3::GetTimings(void) { @@ -2644,13 +2647,12 @@ int CModel3::StartDriveBoardThread(void *data) { // Call method on CModel3 to run drive board thread CModel3 *model3 = (CModel3*)data; - return model3->RunDriveBoardThread(); -} - - -int CModel3::RunMainBoardThread(void) -{ - for (;;) + return model3->RunDriveBoardThread(); +} + +int CModel3::RunMainBoardThread(void) +{ + for (;;) { bool wait = true; bool exit = false; @@ -2942,14 +2944,12 @@ int CModel3::RunDriveBoardThread(void) ThreadError: ErrorLog("Threading error in RunDriveBoardThread: %s\nSwitching back to single-threaded mode.\n", CThread::GetLastError()); m_multiThreaded = false; - return 1; -} - - - -void CModel3::Reset(void) -{ - // Clear memory (but do not modify backup RAM!) + return 1; +} + +void CModel3::Reset(void) +{ + // Clear memory (but do not modify backup RAM!) memset(ram, 0, 0x800000); // Initial bank is bank 0 @@ -3021,14 +3021,14 @@ void CModel3::Reset(void) #define OFFSET_DSBMPEGROM 0xE0E0000 // 16 MB (DSB MPEG data -- Z80 version only uses 8MB) #define OFFSET_DRIVEROM 0xF0E0000 // 64 KB #ifndef NET_BOARD -#define MEMORY_POOL_SIZE (0x800000 + 0x800000 + 0x8000000 + 0x4000000 + 0x20000 + 0x20000 + 0x80000 + 0x1000000 + 0x20000 + 0x1000000 + 0x10000) -#endif -#ifdef NET_BOARD -#define OFFSET_NETBUFFER 0xC000000 // not really 128kb (64kb buffer 0000-ffff + i/o 10000-101ff) -#define OFFSET_NETRAM 0xC020000 // 128 KB (c0020000-c003ffff) -#define MEMORY_POOL_SIZE (0x800000 + 0x800000 + 0x8000000 + 0x4000000 + 0x20000 + 0x20000 + 0x80000 + 0x1000000 + 0x20000 + 0x1000000 + 0x10000 + 0x40000) - //8MB 8MB 128MB 64MB 128KB 128KB 512KB 16MB 128KB 16MB 64KB 256KB -#endif +#define MEMORY_POOL_SIZE (0x800000 + 0x800000 + 0x8000000 + 0x4000000 + 0x20000 + 0x20000 + 0x80000 + 0x1000000 + 0x20000 + 0x1000000 + 0x10000) +#endif +#ifdef NET_BOARD +#define OFFSET_NETBUFFER 0xC000000 // not really 128kb (64kb buffer 0000-ffff + i/o 10000-101ff) +#define OFFSET_NETRAM 0xC020000 // 128 KB (c0020000-c003ffff) +#define MEMORY_POOL_SIZE (0x800000 + 0x800000 + 0x8000000 + 0x4000000 + 0x20000 + 0x20000 + 0x80000 + 0x1000000 + 0x20000 + 0x1000000 + 0x10000 + 0x40000) + //8MB 8MB 128MB 64MB 128KB 128KB 512KB 16MB 128KB 16MB 64KB 256KB +#endif // 64-bit magic number used to detect loading of optional ROMs #define MAGIC_NUMBER 0x4C444D5245505553ULL @@ -3077,13 +3077,13 @@ bool CModel3::LoadGame(const Game &game, const ROMSet &rom_set) else rom_set.get_rom("sound_samples").CopyTo(sampleROM, 16*0x100000); rom_set.get_rom("sound_program").CopyTo(soundROM, 512*1024); - rom_set.get_rom("mpeg_program").CopyTo(dsbROM, 128*1024); - rom_set.get_rom("mpeg_music").CopyTo(mpegROM, 16*0x100000); - rom_set.get_rom("driveboard_program").CopyTo(driveROM, 64*1024); - - // Convert PowerPC and 68K ROMs to little endian words - Util::FlipEndian32(crom, 8*0x100000 + 128*0x100000); - Util::FlipEndian16(soundROM, 512*1024); + rom_set.get_rom("mpeg_program").CopyTo(dsbROM, 128*1024); + rom_set.get_rom("mpeg_music").CopyTo(mpegROM, 16*0x100000); + rom_set.get_rom("driveboard_program").CopyTo(driveROM, 64*1024); + + // Convert PowerPC and 68K ROMs to little endian words + Util::FlipEndian32(crom, 8*0x100000 + 128*0x100000); + Util::FlipEndian16(soundROM, 512*1024); Util::FlipEndian16(sampleROM, 16*0x100000); // Initialize CPU @@ -3097,23 +3097,27 @@ bool CModel3::LoadGame(const Game &game, const ROMSet &rom_set) } else if (game.stepping == "1.5") { - ppc_config.pvr = PPC_MODEL_603E; // 100 MHz - ppc_config.bus_frequency = BUS_FREQUENCY_66MHZ; - ppc_config.bus_frequency_multiplier = 0x15; // 1.5X multiplier - if (game.name == "scudp1") - PCIBridge.SetModel(0x106); // some Step 1.x games use MPC106 - else - PCIBridge.SetModel(0x105); // MPC105 + ppc_config.pvr = PPC_MODEL_603E; // 100 MHz + ppc_config.bus_frequency = BUS_FREQUENCY_66MHZ; + ppc_config.bus_frequency_multiplier = 0x15; // 1.5X multiplier + if (game.name == "scudplusa" + || game.name == "vs215" || game.name == "vs215o" + || game.name == "vs29815" || game.name == "vs29915" + ) + PCIBridge.SetModel(0x106); // some Step 1.x games use MPC106 + else + PCIBridge.SetModel(0x105); // MPC105 } else if (game.stepping == "1.0") { - ppc_config.pvr = PPC_MODEL_603R; // 66 MHz - ppc_config.bus_frequency = BUS_FREQUENCY_66MHZ; - ppc_config.bus_frequency_multiplier = 0x10; // 1X multiplier - if (game.name == "bass" || game.name == "getbass") - PCIBridge.SetModel(0x106); // some Step 1.x games use MPC106 - else - PCIBridge.SetModel(0x105); // MPC105 + ppc_config.pvr = PPC_MODEL_603R; // 66 MHz + ppc_config.bus_frequency = BUS_FREQUENCY_66MHZ; + ppc_config.bus_frequency_multiplier = 0x10; // 1X multiplier + if (game.name == "bass" || game.name == "bassdx" || game.name == "getbass") + + PCIBridge.SetModel(0x106); // some Step 1.x games use MPC106 + else + PCIBridge.SetModel(0x105); // MPC105 } else { @@ -3132,13 +3136,23 @@ bool CModel3::LoadGame(const Game &game, const ROMSet &rom_set) PPCFetchRegions[2].end = 0; PPCFetchRegions[2].ptr = NULL; ppc_set_fetch(PPCFetchRegions); - - // Initialize Real3D - int stepping = ((game.stepping[0] - '0') << 4) | (game.stepping[2] - '0'); - GPU.SetStepping(stepping); - - // MPEG board (if present) - if (rom_set.get_rom("mpeg_program").size) + + // Initialize Real3D + int stepping = ((game.stepping[0] - '0') << 4) | (game.stepping[2] - '0'); + // Some step 2+ games need the older PCI ID (obvious symptom: + // vbl is enabled briefly then disabled so the game hangs) + bool step20_with_old_real3d; + if (game.name == "von2" || game.name == "von2a" || game.name == "von254g" + || game.name == "dirtdvls" || game.name == "dirtdvlsa" || game.name == "dirtdvlsj" + || game.name == "magtruck" || game.name == "lamachin" + ) + step20_with_old_real3d = true; + else + step20_with_old_real3d = false; + GPU.SetStepping(stepping, step20_with_old_real3d); + + // MPEG board (if present) + if (rom_set.get_rom("mpeg_program").size) { if (game.mpeg_board == "DSB1") { @@ -3269,54 +3283,54 @@ bool CModel3::Init(void) if (OKAY != GPU.Init(vrom,this,&IRQ,0x100)) // same for Real3D DMA interrupt return FAIL; if (OKAY != SoundBoard.Init(soundROM,sampleROM)) - return FAIL; -#ifdef NET_BOARD - if (OKAY != NetBoard.Init(netRAM, netBuffer)) - return FAIL; -#endif - - PCIBridge.AttachPCIBus(&PCIBus); - PCIBus.AttachDevice(13,&GPU); - PCIBus.AttachDevice(14,&SCSI); + return FAIL; +#ifdef NET_BOARD + if (OKAY != NetBoard.Init(netRAM, netBuffer)) + return FAIL; +#endif + + PCIBridge.AttachPCIBus(&PCIBus); + PCIBus.AttachDevice(13,&GPU); + PCIBus.AttachDevice(14,&SCSI); PCIBus.AttachDevice(16,this); DebugLog("Initialized Model 3 (allocated %1.1f MB)\n", memSizeMB); return OKAY; } - -CSoundBoard *CModel3::GetSoundBoard(void) -{ - return &SoundBoard; -} - -CDriveBoard *CModel3::GetDriveBoard(void) + +CSoundBoard *CModel3::GetSoundBoard(void) +{ + return &SoundBoard; +} + +CDriveBoard *CModel3::GetDriveBoard(void) { return &DriveBoard; } -#ifdef NET_BOARD -CNetBoard *CModel3::GetNetBoard(void) -{ - return &NetBoard; -} -#endif - +#ifdef NET_BOARD +CNetBoard *CModel3::GetNetBoard(void) +{ + return &NetBoard; +} +#endif + CModel3::CModel3(const Util::Config::Node &config) : m_config(config), m_multiThreaded(config["MultiThreaded"].ValueAs()), m_gpuMultiThreaded(config["GPUMultiThreaded"].ValueAs()), TileGen(config), GPU(config), - SoundBoard(config), - DriveBoard(config), -#ifdef NET_BOARD - NetBoard(config), -#endif - m_jtag(GPU) -{ - // Initialize pointers so dtor can know whether to free them - memoryPool = NULL; + SoundBoard(config), + DriveBoard(config), +#ifdef NET_BOARD + NetBoard(config), +#endif + m_jtag(GPU) +{ + // Initialize pointers so dtor can know whether to free them + memoryPool = NULL; // Various uninitialized pointers Inputs = NULL; @@ -3334,37 +3348,37 @@ CModel3::CModel3(const Util::Config::Node &config) #ifdef NET_BOARD netRAM = NULL; netBuffer = NULL; -#endif - - DSB = NULL; - - securityPtr = 0; - - startedThreads = false; - pauseThreads = false; - stopThreads = false; - ppcBrdThread = NULL; - sndBrdThread = NULL; - drvBrdThread = NULL; - - ppcBrdThreadRunning = false; - ppcBrdThreadDone = false; - sndBrdThreadRunning = false; - sndBrdThreadDone = false; - drvBrdThreadRunning = false; - drvBrdThreadDone = false; - - syncSndBrdThread = false; - ppcBrdThreadSync = NULL; - sndBrdThreadSync = NULL; - drvBrdThreadSync = NULL; - - notifyLock = NULL; - notifySync = NULL; - - DebugLog("Built Model 3\n"); -} - +#endif + + DSB = NULL; + + securityPtr = 0; + + startedThreads = false; + pauseThreads = false; + stopThreads = false; + ppcBrdThread = NULL; + sndBrdThread = NULL; + drvBrdThread = NULL; + + ppcBrdThreadRunning = false; + ppcBrdThreadDone = false; + sndBrdThreadRunning = false; + sndBrdThreadDone = false; + drvBrdThreadRunning = false; + drvBrdThreadDone = false; + + syncSndBrdThread = false; + ppcBrdThreadSync = NULL; + sndBrdThreadSync = NULL; + drvBrdThreadSync = NULL; + + notifyLock = NULL; + notifySync = NULL; + + DebugLog("Built Model 3\n"); +} + // Dumps a memory region to a file for debugging purposes /* static void Dump(const char *file, uint8_t *buf, size_t size, bool reverse32, bool reverse16) @@ -3408,13 +3422,12 @@ CModel3::~CModel3(void) if (DSB != NULL) { delete DSB; - DSB = NULL; - } - - - Inputs = NULL; - Outputs = NULL; - ram = NULL; + DSB = NULL; + } + + Inputs = NULL; + Outputs = NULL; + ram = NULL; crom = NULL; vrom = NULL; soundROM = NULL; @@ -3427,7 +3440,7 @@ CModel3::~CModel3(void) #ifdef NET_BOARD netRAM = NULL; netBuffer = NULL; -#endif - - DebugLog("Destroyed Model 3\n"); -} \ No newline at end of file +#endif + + DebugLog("Destroyed Model 3\n"); +} diff --git a/Src/Model3/Real3D.cpp b/Src/Model3/Real3D.cpp index 47e01ec..a3f2b1a 100644 --- a/Src/Model3/Real3D.cpp +++ b/Src/Model3/Real3D.cpp @@ -263,12 +263,12 @@ void CReal3D::BeginFrame(void) // If multi-threaded, perform now any queued texture uploads to renderer before rendering begins if (m_gpuMultiThreaded) { - for (const auto &it : queuedUploadTexturesRO) { + for (const auto &it : queuedUploadTexturesRO) { Render3D->UploadTextures(it.level, it.x, it.y, it.width, it.height); - } + } - // done syncing data - queuedUploadTexturesRO.clear(); + // done syncing data + queuedUploadTexturesRO.clear(); } Render3D->BeginFrame(); @@ -628,15 +628,15 @@ void CReal3D::WriteDMARegister32(unsigned reg, uint32_t data) dmaLength = data; DMACopy(); dmaStatus |= 1; - IRQ->Assert(dmaIRQ); - break; - case 0x10: // command register - if ((data&0x20000000)) - { - dmaData = 0x16C311DB; // Virtual On 2 expects this from DMA - DebugLog("Real3D: DMA ID command issued (ATTENTION: make sure we're returning the correct value), PC=%08X, LR=%08X\n", ppc_get_pc(), ppc_get_lr()); - } - else if ((data&0x80000000)) + IRQ->Assert(dmaIRQ); + break; + case 0x10: // command register + if ((data&0x20000000)) // DMA ID command + { + dmaData = pciID; + DebugLog("Real3D: DMA ID command issued (ATTENTION: make sure we're returning the correct value), PC=%08X, LR=%08X\n", ppc_get_pc(), ppc_get_lr()); + } + else if ((data&0x80000000)) { dmaData = ReadRegister(data & 0x3F); } @@ -656,35 +656,36 @@ void CReal3D::WriteDMARegister32(unsigned reg, uint32_t data) ******************************************************************************/ void CReal3D::Flush(void) -{ - commandPortWritten = true; - DebugLog("Real3D 88000000 written @ PC=%08X\n", ppc_get_pc()); - - // Upload textures (if any) - if (fifoIdx > 0) - { +{ + commandPortWritten = true; + DebugLog("Real3D 88000000 written @ PC=%08X\n", ppc_get_pc()); + + // Upload textures (if any) + if (fifoIdx > 0) + { for (uint32_t i = 0; i < fifoIdx; ) { - uint32_t size = 2+textureFIFO[i+0]/2; - size /= 4; - uint32_t header = textureFIFO[i+1]; // texture information header - - // Spikeout seems to be uploading 0 length textures - if (0 == size) - { + uint32_t size = 2+textureFIFO[i+0]/2; + size /= 4; + uint32_t header = textureFIFO[i+1]; // texture information header + + // Spikeout seems to be uploading 0 length textures + if (0 == size) + { DebugLog("Real3D: 0-length texture upload @ PC=%08X (%08X %08X %08X)\n", ppc_get_pc(), textureFIFO[i+0], textureFIFO[i+1], textureFIFO[i+2]); break; } - - UploadTexture(header,(uint16_t *)&textureFIFO[i+2]); - DebugLog("Real3D: Texture upload completed: %X bytes (%X)\n", size*4, textureFIFO[i+0]); - i += size; - } - } - - // Reset texture FIFO - fifoIdx = 0; -} + + UploadTexture(header,(uint16_t *)&textureFIFO[i+2]); + DebugLog("Real3D: Texture upload completed: %X bytes (%X)\n", size*4, textureFIFO[i+0]); + + i += size; + } + } + + // Reset texture FIFO + fifoIdx = 0; +} void CReal3D::WriteTextureFIFO(uint32_t data) { @@ -865,23 +866,26 @@ void CReal3D::AttachRenderer(IRender3D *Render3DPtr) uint32_t CReal3D::GetASICIDCode(ASIC asic) const { auto it = m_asicID.find(asic); - return it == m_asicID.end() ? 0 : it->second; -} - -void CReal3D::SetStepping(int stepping) -{ - step = stepping; - if ((step!=0x10) && (step!=0x15) && (step!=0x20) && (step!=0x21)) + return it == m_asicID.end() ? 0 : it->second; +} + +void CReal3D::SetStepping(int stepping, bool step20_with_old_real3d) + +{ + step = stepping; + if ((step!=0x10) && (step!=0x15) && (step!=0x20) && (step!=0x21)) { - DebugLog("Real3D: Unrecognized stepping: %d.%d\n", (step>>4)&0xF, step&0xF); - step = 0x10; - } - - // Set PCI ID - if (step < 0x20) - pciID = 0x16C311DB; // vendor 0x11DB = Sega - else - pciID = 0x178611DB; + DebugLog("Real3D: Unrecognized stepping: %d.%d\n", (step>>4)&0xF, step&0xF); + step = 0x10; + } + + // Set PCI ID + // Some step 2+ games need the older PCI ID (obvious symptom: + // vbl is enabled briefly then disabled so the game hangs) + if ((step < 0x20) || step20_with_old_real3d) + pciID = 0x16C311DB; // vendor 0x11DB = Sega + else + pciID = 0x178611DB; // Pass to renderer if (Render3D != NULL) diff --git a/Src/Model3/Real3D.h b/Src/Model3/Real3D.h index f69d281..9c93234 100644 --- a/Src/Model3/Real3D.h +++ b/Src/Model3/Real3D.h @@ -359,13 +359,14 @@ public: * any other emulation functions and after Init(). * * Parameters: - * stepping 0x10 for Step 1.0, 0x15 for Step 1.5, 0x20 for Step 2.0, or - * 0x21 for Step 2.1. Anything else defaults to 1.0. - */ - void SetStepping(int stepping); - - /* - * Init(vromPtr, BusObjectPtr, IRQObjectPtr, dmaIRQBit): + * stepping 0x10 for Step 1.0, 0x15 for Step 1.5, 0x20 for Step 2.0, or + * 0x21 for Step 2.1. Anything else defaults to 1.0. + */ + void SetStepping(int stepping, bool step20_with_old_real3d); + + + /* + * Init(vromPtr, BusObjectPtr, IRQObjectPtr, dmaIRQBit): * * One-time initialization of the context. Must be called prior to all * other members. Connects the Real3D device to its video ROM and allocates