diff --git a/Src/Model3/Real3D.cpp b/Src/Model3/Real3D.cpp index 7fcffa5..30bdb37 100644 --- a/Src/Model3/Real3D.cpp +++ b/Src/Model3/Real3D.cpp @@ -1,12 +1,12 @@ /** ** Supermodel ** A Sega Model 3 Arcade Emulator. - ** Copyright 2011 Bart Trzynadlowski, Nik Henson + ** Copyright 2011 Bart Trzynadlowski, Nik Henson ** ** This file is part of Supermodel. ** ** Supermodel is free software: you can redistribute it and/or modify it under - ** the terms of the GNU General Public License as published by the Free + ** the terms of the GNU General Public License as published by the Free ** Software Foundation, either version 3 of the License, or (at your option) ** any later version. ** @@ -18,10 +18,10 @@ ** You should have received a copy of the GNU General Public License along ** with Supermodel. If not, see . **/ - + /* * Real3D.cpp - * + * * The Model 3's Real3D-based graphics hardware. Based on the Real3D Pro-1000 * family of image generators. * @@ -29,8 +29,8 @@ * ------- * It appears that Step 2.0 returns a different PCI ID depending on whether * the PCI configuration space or DMA register are accessed. For example, - * Virtual On 2 expects 0x178611DB from the PCI configuration header but - * 0x16C311DB from the DMA device. + * Virtual On 2 expects 0x178611DB from the PCI configuration header but + * 0x16C311DB from the DMA device. * * To-Do List * ---------- @@ -85,11 +85,11 @@ static void UpdateRenderConfig(IRender3D *Render3D, uint64_t internalRenderConfi void CReal3D::SaveState(CBlockFile *SaveState) { SaveState->NewBlock("Real3D", __FILE__); - + SaveState->Write(memoryPool, MEM_POOL_SIZE_RW); // Don't write out read-only snapshots or dirty page arrays SaveState->Write(&fifoIdx, sizeof(fifoIdx)); SaveState->Write(m_vromTextureFIFO, sizeof(m_vromTextureFIFO)); - + SaveState->Write(&dmaSrc, sizeof(dmaSrc)); SaveState->Write(&dmaDest, sizeof(dmaDest)); SaveState->Write(&dmaLength, sizeof(dmaLength)); @@ -97,7 +97,7 @@ void CReal3D::SaveState(CBlockFile *SaveState) SaveState->Write(&dmaUnknownReg, sizeof(dmaUnknownReg)); SaveState->Write(&dmaStatus, sizeof(dmaStatus)); SaveState->Write(&dmaConfig, sizeof(dmaConfig)); - + // These used to be occupied by JTAG state SaveState->Write(m_internalRenderConfig, sizeof(m_internalRenderConfig)); SaveState->Write(commandPortWritten); @@ -118,7 +118,7 @@ void CReal3D::LoadState(CBlockFile *SaveState) ErrorLog("Unable to load Real3D GPU state. Save state file is corrupt."); return; } - + SaveState->Read(memoryPool, MEM_POOL_SIZE_RW); // If multi-threaded, update read-only snapshots too @@ -127,7 +127,7 @@ void CReal3D::LoadState(CBlockFile *SaveState) Render3D->UploadTextures(0, 0, 0, 2048, 2048); SaveState->Read(&fifoIdx, sizeof(fifoIdx)); SaveState->Read(&m_vromTextureFIFO, sizeof(m_vromTextureFIFO)); - + SaveState->Read(&dmaSrc, sizeof(dmaSrc)); SaveState->Read(&dmaDest, sizeof(dmaDest)); SaveState->Read(&dmaLength, sizeof(dmaLength)); @@ -135,7 +135,7 @@ void CReal3D::LoadState(CBlockFile *SaveState) SaveState->Read(&dmaUnknownReg, sizeof(dmaUnknownReg)); SaveState->Read(&dmaStatus, sizeof(dmaStatus)); SaveState->Read(&dmaConfig, sizeof(dmaConfig)); - + SaveState->Read(m_internalRenderConfig, sizeof(m_internalRenderConfig)); UpdateRenderConfig(Render3D, m_internalRenderConfig); SaveState->Read(&commandPortWritten); @@ -224,14 +224,14 @@ uint32_t CReal3D::UpdateSnapshot(bool copyWhole, uint8_t *src, uint8_t *dst, uns copied += toCopy; } d >>= 1; - pSrc += PAGE_SIZE; + pSrc += PAGE_SIZE; pDst += PAGE_SIZE; } dirty[i] = 0; } else { - pSrc += 8 * PAGE_SIZE; + pSrc += 8 * PAGE_SIZE; pDst += 8 * PAGE_SIZE; } } @@ -357,7 +357,7 @@ void CReal3D::StoreTexture(unsigned level, unsigned xPos, unsigned yPos, unsigne for (uint32_t yy = 0; yy < tileY; yy++) { for (uint32_t xx = 0; xx < tileX; xx++) - { + { if (m_gpuMultiThreaded) MARK_DIRTY(textureRAMDirty, destOffset * 2); if (tileX == 1) texData -= tileY; @@ -518,7 +518,7 @@ void CReal3D::UploadTexture(uint32_t header, const uint16_t *texData) /****************************************************************************** DMA Device - + Register 0xC: ------------- +---+---+---+---+---+---+---+---+ @@ -531,7 +531,7 @@ void CReal3D::UploadTexture(uint32_t header, const uint16_t *texData) void CReal3D::DMACopy(void) { DebugLog("Real3D DMA copy (PC=%08X, LR=%08X): %08X -> %08X, %X %s\n", ppc_get_pc(), ppc_get_lr(), dmaSrc, dmaDest, dmaLength*4, (dmaConfig&0x80)?"(byte reversed)":""); - //printf("Real3D DMA copy (PC=%08X, LR=%08X): %08X -> %08X, %X %s\n", ppc_get_pc(), ppc_get_lr(), dmaSrc, dmaDest, dmaLength*4, (dmaConfig&0x80)?"(byte reversed)":""); + //printf("Real3D DMA copy (PC=%08X, LR=%08X): %08X -> %08X, %X %s\n", ppc_get_pc(), ppc_get_lr(), dmaSrc, dmaDest, dmaLength*4, (dmaConfig&0x80)?"(byte reversed)":""); if ((dmaConfig&0x80)) // reverse bytes { while (dmaLength != 0) @@ -566,7 +566,7 @@ uint8_t CReal3D::ReadDMARegister8(unsigned reg) default: break; } - + DebugLog("Real3D: ReadDMARegister8: reg=%X\n", reg); return 0; } @@ -601,7 +601,7 @@ uint32_t CReal3D::ReadDMARegister32(unsigned reg) default: break; } - + DebugLog("Real3D: ReadDMARegister32: reg=%X\n", reg); return 0; } @@ -652,7 +652,7 @@ void CReal3D::WriteDMARegister32(unsigned reg, uint32_t data) void CReal3D::Flush(void) { - commandPortWritten = true; + commandPortWritten = true; DebugLog("Real3D 88000000 written @ PC=%08X\n", ppc_get_pc()); // Upload textures (if any) @@ -825,13 +825,13 @@ uint32_t CReal3D::ReadRegister(unsigned reg) uint32_t CReal3D::ReadPCIConfigSpace(unsigned device, unsigned reg, unsigned bits, unsigned offset) { uint32_t d; - + if ((bits==8)) { DebugLog("Real3D: %d-bit PCI read request for reg=%02X\n", bits, reg); return 0; } - + // This is a little endian device, must return little endian words switch (reg) { @@ -859,16 +859,16 @@ uint32_t CReal3D::ReadPCIConfigSpace(unsigned device, unsigned reg, unsigned bit return 0; } - + void CReal3D::WritePCIConfigSpace(unsigned device, unsigned reg, unsigned bits, unsigned offset, uint32_t data) { DebugLog("Real3D: PCI %d-bit write request for reg=%02X, data=%08X\n", bits, reg, data); } - + void CReal3D::Reset(void) { error = false; - + m_pingPong = 0; commandPortWritten = false; commandPortWrittenRO = false; @@ -886,7 +886,7 @@ void CReal3D::Reset(void) dmaUnknownReg = 0; dmaStatus = 0; dmaConfig = 0; - + unsigned memSize = (m_gpuMultiThreaded ? MEMORY_POOL_SIZE : MEM_POOL_SIZE_RW); memset(memoryPool, 0, memSize); memset(m_vromTextureFIFO, 0, sizeof(m_vromTextureFIFO)); @@ -933,11 +933,11 @@ void CReal3D::SetStepping(int stepping, uint32_t pciIDValue) // Set PCI ID pciID = pciIDValue; - + // Pass to renderer if (Render3D != NULL) Render3D->SetStepping(step); - + // Set ASIC ID codes m_asicID.clear(); if (step == 0x10) @@ -983,15 +983,15 @@ bool CReal3D::Init(const uint8_t *vromPtr, IBus *BusObjectPtr, CIRQ *IRQObjectPt float memSizeMB = (float)memSize/(float)0x100000; // IRQ and bus objects - Bus = BusObjectPtr; + Bus = BusObjectPtr; IRQ = IRQObjectPtr; dmaIRQ = dmaIRQBit; - + // Allocate all Real3D RAM regions memoryPool = new(std::nothrow) uint8_t[memSize]; if (NULL == memoryPool) return ErrorLog("Insufficient memory for Real3D object (needs %1.1f MB).", memSizeMB); - + // Set up main pointers cullingRAMLo = (uint32_t *) &memoryPool[OFFSET_8C]; cullingRAMHi = (uint32_t *) &memoryPool[OFFSET_8E]; @@ -1011,10 +1011,10 @@ bool CReal3D::Init(const uint8_t *vromPtr, IBus *BusObjectPtr, CIRQ *IRQObjectPt polyRAMDirty = (uint8_t *) &memoryPool[OFFSET_98_DIRTY]; textureRAMDirty = (uint8_t *) &memoryPool[OFFSET_TEXRAM_DIRTY]; } - + // VROM pointer passed to us vrom = (uint32_t *) vromPtr; - + DebugLog("Initialized Real3D (allocated %1.1f MB)\n", memSizeMB); return OKAY; } @@ -1022,7 +1022,7 @@ bool CReal3D::Init(const uint8_t *vromPtr, IBus *BusObjectPtr, CIRQ *IRQObjectPt CReal3D::CReal3D(const Util::Config::Node &config) : m_config(config), m_gpuMultiThreaded(config["GPUMultiThreaded"].ValueAs()) -{ +{ Render3D = NULL; memoryPool = NULL; cullingRAMLo = NULL; @@ -1047,7 +1047,7 @@ CReal3D::CReal3D(const Util::Config::Node &config) * Destructor. */ CReal3D::~CReal3D(void) -{ +{ // Dump memory #if 0 FILE *fp; @@ -1092,8 +1092,10 @@ CReal3D::~CReal3D(void) // Dump textures if requested if (m_config["DumpTextures"].ValueAsDefault(false)) { - Util::WriteSurfaceToBMP("textures_t1rgb5.bmp", reinterpret_cast(textureRAM), 2048, 2048, false); - printf("Wrote textures as T1RGB5 to 'textures_t1rgb5.bmp'\n"); + Util::WriteSurfaceToBMP("textures_t1rgb5_contour.bmp", reinterpret_cast(textureRAM), 2048, 2048, false); + printf("Wrote textures as T1RGB5 (contour bit enabled) to 'textures_t1rgb5_contour.bmp'\n"); + Util::WriteSurfaceToBMP("textures_t1rgb5_opaque.bmp", reinterpret_cast(textureRAM), 2048, 2048, false); + printf("Wrote textures as T1RGB5 (contour bit ignored) to 'textures_t1rgb5_opaque.bmp'\n"); Util::WriteSurfaceToBMP("textures_a4l4_lo.bmp", reinterpret_cast(textureRAM), 2048, 2048, false); printf("Wrote textures as A4L4 (low) to 'textures_a4l4_lo.bmp'\n"); Util::WriteSurfaceToBMP("textures_l4a4_lo.bmp", reinterpret_cast(textureRAM), 2048, 2048, false); diff --git a/Src/Util/BMPFile.h b/Src/Util/BMPFile.h index 9bf0c4f..b8a5a63 100644 --- a/Src/Util/BMPFile.h +++ b/Src/Util/BMPFile.h @@ -28,9 +28,9 @@ namespace Util { id[0] = 'B'; id[1] = 'M'; - } + } }; - + // BITMAPV4HEADER struct BMPInfoHeader { @@ -93,7 +93,7 @@ namespace Util gamma_blue(0) {} }; - + struct FileHeader { BMPHeader bmp_header; @@ -129,6 +129,7 @@ namespace Util }; // Texture format 0: TRRR RRGG GGGB BBBB, T = contour bit + template struct T1RGB5 { static const unsigned bytes_per_pixel = 2; @@ -146,11 +147,21 @@ namespace Util } static inline uint8_t GetAlpha(const uint8_t *pixel) { - bool t = (*reinterpret_cast(pixel) >> 15) & 0x1; - return t ? uint8_t(0x00) : uint8_t(0xff); // T-bit indicates transparency + if (EnableContour) + { + bool t = (*reinterpret_cast(pixel) >> 15) & 0x1; + return t ? uint8_t(0x00) : uint8_t(0xff); // T-bit indicates transparency + } + else + { + return 0xff; // force opaque + } } }; + using T1RGB5ContourEnabled = struct T1RGB5; + using T1RGB5ContourIgnored = struct T1RGB5; + // Texture format 1: xxxx xxxx AAAA LLLL struct A4L4Low {