From fcdc03c5e732a7e4461c817c3c315a11ed87d3b9 Mon Sep 17 00:00:00 2001 From: Shamus Hammons Date: Wed, 13 Jul 2011 17:05:21 +0000 Subject: [PATCH] Added stricter TOM memory checking. --- src/blitter.cpp | 12 +++++++-- src/file.cpp | 28 ++++++++++++--------- src/gui/filepicker.cpp | 2 +- src/jaguar.cpp | 39 ++++++++++++++++------------- src/tom.cpp | 57 +++++++++++++++++++++++++++++++++++------- 5 files changed, 96 insertions(+), 42 deletions(-) diff --git a/src/blitter.cpp b/src/blitter.cpp index 3d4207d..3db442f 100644 --- a/src/blitter.cpp +++ b/src/blitter.cpp @@ -31,6 +31,8 @@ // Various conditional compilation goodies... +//#define LOG_BLITS + //#define USE_ORIGINAL_BLITTER //#define USE_MIDSUMMER_BLITTER #define USE_MIDSUMMER_BLITTER_MKII @@ -1825,9 +1827,9 @@ void LogBlit(void) WriteLog(" UPDA2 = %s\n", (UPDA2 ? "1" : "0")); WriteLog(" DSTA2 = %s\n", (DSTA2 ? "1" : "0")); WriteLog(" ZOP = %s %s %s\n", (Z_OP_INF ? "<" : ""), (Z_OP_EQU ? "=" : ""), (Z_OP_SUP ? ">" : "")); - WriteLog("--LFUFUNC = %s\n", opStr[(cmd >> 21) & 0x0F]); + WriteLog("+-LFUFUNC = %s\n", opStr[(cmd >> 21) & 0x0F]); WriteLog("| PATDSEL = %s (PD=%08X%08X)\n", (PATDSEL ? "1" : "0"), REG(PATTERNDATA), REG(PATTERNDATA + 4)); - WriteLog("--ADDDSEL = %s\n", (ADDDSEL ? "1" : "0")); + WriteLog("+-ADDDSEL = %s\n", (ADDDSEL ? "1" : "0")); WriteLog(" CMPDST = %s\n", (CMPDST ? "1" : "0")); WriteLog(" BCOMPEN = %s\n", (BCOMPEN ? "1" : "0")); WriteLog(" DCOMPEN = %s\n", (DCOMPEN ? "1" : "0")); @@ -1854,6 +1856,9 @@ void LogBlit(void) void BlitterMidsummer(uint32 cmd) { +#ifdef LOG_BLITS + LogBlit(); +#endif uint32 outer_loop, inner_loop, a1_addr, a2_addr; int32 a1_x, a1_y, a2_x, a2_y, a1_width, a2_width; uint8 a1_phrase_mode, a2_phrase_mode; @@ -2672,6 +2677,9 @@ bool logBlit = false; void BlitterMidsummer2(void) { +#ifdef LOG_BLITS + LogBlit(); +#endif // Here's what the specs say the state machine does. Note that this can probably be // greatly simplified (also, it's different from what John has in his Oberon docs): //Will remove stuff that isn't in Jaguar I once fully described (stuff like texture won't diff --git a/src/file.cpp b/src/file.cpp index 78b4233..ac39ede 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -483,7 +483,9 @@ uint32 GetFileFromZIP(const char * zipFile, FileType type, uint8 * &buffer) WriteLog("FILE: Found image file '%s'.\n", ze->name); } - if ((type == FT_SOFTWARE) && (CheckExtension(ze->name, ".j64") || CheckExtension(ze->name, ".rom") || CheckExtension(ze->name, ".abs") || CheckExtension(ze->name, ".cof"))) + if ((type == FT_SOFTWARE) && (CheckExtension(ze->name, ".j64") + || CheckExtension(ze->name, ".rom") || CheckExtension(ze->name, ".abs") + || CheckExtension(ze->name, ".cof") || CheckExtension(ze->name, ".jag"))) { found = true; WriteLog("FILE: Found software file '%s'.\n", ze->name); @@ -529,17 +531,7 @@ uint32 GetFileFromZIP(const char * zipFile, FileType type, uint8 * &buffer) // uint32 ParseFileType(uint8 header1, uint8 header2, uint32 size) { - // If the file size is divisible by 1M, we probably have an regular ROM. - // We can also check our CRC32 against the internal ROM database to be sure. - if ((size % 1048576) == 0) - return JST_ROM; - - // If the file size + 8192 bytes is divisible by 1M, we probably have an - // Alpine format ROM. - if (((size + 8192) % 1048576) == 0) - return JST_ALPINE; - - // So much for low hanging fruit. Now try some other types. + // Check headers first... // ABS/COFF type 1 if (header1 == 0x60 && header2 == 0x1B) @@ -553,6 +545,18 @@ uint32 ParseFileType(uint8 header1, uint8 header2, uint32 size) if (header1 == 0x60 && header2 == 0x1A) return JST_JAGSERVER; + // And if that fails, try file sizes... + + // If the file size is divisible by 1M, we probably have an regular ROM. + // We can also check our CRC32 against the internal ROM database to be sure. + if ((size % 1048576) == 0) + return JST_ROM; + + // If the file size + 8192 bytes is divisible by 1M, we probably have an + // Alpine format ROM. + if (((size + 8192) % 1048576) == 0) + return JST_ALPINE; + // Headerless crap return JST_NONE; } diff --git a/src/gui/filepicker.cpp b/src/gui/filepicker.cpp index e01f365..a1694de 100644 --- a/src/gui/filepicker.cpp +++ b/src/gui/filepicker.cpp @@ -420,7 +420,7 @@ void FilePickerWindow::UpdateSelection(const QModelIndex & current, const QModel else fileTypeString = QString(tr("%1MB Alpine ROM")); - fileTypeString = fileTypeString.arg(fileSize / 1048576); + fileTypeString = fileTypeString.arg((fileSize + 8192) / 1048576); } else if (haveUnknown && (fileType == JST_ABS_TYPE1 || fileType == JST_ABS_TYPE2)) fileTypeString = QString(tr("ABS/COF Executable (%1 bytes)")).arg(fileSize); diff --git a/src/jaguar.cpp b/src/jaguar.cpp index 3ae824c..9cdade3 100644 --- a/src/jaguar.cpp +++ b/src/jaguar.cpp @@ -1521,6 +1521,9 @@ void JaguarReset(void) else SET32(jaguarMainRAM, 4, jaguarRunAddress); + if (vjs.useJaguarBIOS && !(biosAvailable & (BIOS_NORMAL | BIOS_STUB1 | BIOS_STUB2))) + WriteLog("Jaguar: Requested BIOS, but none available.\n"); + // WriteLog("jaguar_reset():\n"); TOMReset(); JERRYReset(); @@ -1613,7 +1616,7 @@ void JaguarDone(void) WriteLog("\n");//*/ // WriteLog("Jaguar: CD BIOS version %04X\n", JaguarReadWord(0x3004)); - WriteLog("Jaguar: Interrupt enable = %02X\n", TOMReadByte(0xF000E1) & 0x1F); + WriteLog("Jaguar: Interrupt enable = %02X\n", TOMReadByte(0xF000E1, JAGUAR) & 0x1F); WriteLog("Jaguar: VBL interrupt is %s\n", ((TOMIRQEnabled(IRQ_VBLANK)) && (JaguarInterruptHandlerIsValid(64))) ? "enabled" : "disabled"); M68K_show_context(); //#endif @@ -1630,18 +1633,18 @@ void JaguarDone(void) // void JaguarExecute(uint32 * backbuffer, bool render) { - uint16 vp = TOMReadWord(0xF0003E) + 1; - uint16 vi = TOMReadWord(0xF0004E); + uint16 vp = TOMReadWord(0xF0003E, JAGUAR) + 1; + uint16 vi = TOMReadWord(0xF0004E, JAGUAR); //Using WO registers is OK, since we're the ones controlling access--there's nothing wrong here! ;-) //Though we shouldn't be able to do it using TOMReadWord... !!! FIX !!! -// uint16 vdb = TOMReadWord(0xF00046); +// uint16 vdb = TOMReadWord(0xF00046, JAGUAR); //Note: This is the *definite* end of the display, though VDE *might* be less than this... -// uint16 vbb = TOMReadWord(0xF00040); +// uint16 vbb = TOMReadWord(0xF00040, JAGUAR); //It seems that they mean it when they say that VDE is the end of object processing. //However, we need to be able to tell the OP (or TOM) that we've reached the end of the //buffer and not to write any more pixels... !!! FIX !!! -// uint16 vde = TOMReadWord(0xF00048); +// uint16 vde = TOMReadWord(0xF00048, JAGUAR); uint16 refreshRate = (vjs.hardwareTypeNTSC ? 60 : 50); uint32 m68kClockRate = (vjs.hardwareTypeNTSC ? M68K_CLOCK_RATE_NTSC : M68K_CLOCK_RATE_PAL); @@ -1661,9 +1664,9 @@ if (effect_start) for(uint16 i=0; i= vp) vc = 0; //WriteLog("SLC: Currently on line %u (VP=%u)...\n", vc, vp); - TOMWriteWord(0xF00006, vc); + TOMWriteWord(0xF00006, vc, JAGUAR); //This is a crappy kludge, but maybe it'll work for now... //Maybe it's not so bad, since the IRQ happens on a scanline boundary... @@ -1865,17 +1868,17 @@ void JaguarExecuteNew(void) void ScanlineCallback(void) { - uint16 vc = TOMReadWord(0xF00006); - uint16 vp = TOMReadWord(0xF0003E) + 1; - uint16 vi = TOMReadWord(0xF0004E); -// uint16 vbb = TOMReadWord(0xF00040); + uint16 vc = TOMReadWord(0xF00006, JAGUAR); + uint16 vp = TOMReadWord(0xF0003E, JAGUAR) + 1; + uint16 vi = TOMReadWord(0xF0004E, JAGUAR); +// uint16 vbb = TOMReadWord(0xF00040, JAGUAR); vc++; if (vc >= vp) vc = 0; //WriteLog("SLC: Currently on line %u (VP=%u)...\n", vc, vp); - TOMWriteWord(0xF00006, vc); + TOMWriteWord(0xF00006, vc, JAGUAR); //This is a crappy kludge, but maybe it'll work for now... //Maybe it's not so bad, since the IRQ happens on a scanline boundary... diff --git a/src/tom.cpp b/src/tom.cpp index 3f56c8f..f9054f6 100644 --- a/src/tom.cpp +++ b/src/tom.cpp @@ -1098,7 +1098,7 @@ uint8 TOMReadByte(uint32 offset, uint32 who/*=UNKNOWN*/) // offset &= 0xFF3FFF; #ifdef TOM_DEBUG - WriteLog("TOM: Reading byte at %06X\n", offset); + WriteLog("TOM: Reading byte at %06X for %s\n", offset, whoName[who]); #endif if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20)) @@ -1129,7 +1129,7 @@ uint16 TOMReadWord(uint32 offset, uint32 who/*=UNKNOWN*/) //???Is this needed??? // offset &= 0xFF3FFF; #ifdef TOM_DEBUG - WriteLog("TOM: Reading word at %06X\n", offset); + WriteLog("TOM: Reading word at %06X for %s\n", offset, whoName[who]); #endif if (offset >= 0xF02000 && offset <= 0xF020FF) WriteLog("TOM: Read attempted from GPU register file by %s (unimplemented)!\n", whoName[who]); @@ -1177,17 +1177,33 @@ if (offset >= 0xF02000 && offset <= 0xF020FF) return (TOMReadByte(offset, who) << 8) | TOMReadByte(offset + 1, who); } +#define TOM_STRICT_MEMORY_ACCESS // // TOM byte access (write) // void TOMWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/) { +#ifdef TOM_DEBUG + WriteLog("TOM: Writing byte %02X at %06X", data, offset); +#endif //???Is this needed??? // Perhaps on the writes--32-bit writes that is! And masked with FF7FFF... +#ifndef TOM_STRICT_MEMORY_ACCESS offset &= 0xFF3FFF; - +#else + // "Fast" (32-bit only) write access to the GPU +// if ((offset >= 0xF0A100) && (offset <= 0xF0BFFF)) + if ((offset >= 0xF08000) && (offset <= 0xF0BFFF)) + offset &= 0xFF7FFF; +#endif #ifdef TOM_DEBUG - WriteLog("TOM: Writing byte %02X at %06X\n", data, offset); + WriteLog(" -->[%06X] by %s\n", offset, whoName[who]); +#endif + +#ifdef TOM_STRICT_MEMORY_ACCESS + // Sanity check ("Aww, there ain't no Sanity Clause...") + if ((offset < 0xF00000) || (offset > 0xF03FFF)) + return; #endif if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20)) @@ -1249,12 +1265,28 @@ void TOMWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/) // void TOMWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/) { -//???Is this needed??? +#ifdef TOM_DEBUG + WriteLog("TOM: Writing byte %04X at %06X", data, offset); +#endif +//???Is this needed??? Yes, but we need to be more vigilant than this. +#ifndef TOM_STRICT_MEMORY_ACCESS offset &= 0xFF3FFF; - +#else + // "Fast" (32-bit only) write access to the GPU +// if ((offset >= 0xF0A100) && (offset <= 0xF0BFFF)) + if ((offset >= 0xF08000) && (offset <= 0xF0BFFF)) + offset &= 0xFF7FFF; +#endif #ifdef TOM_DEBUG - WriteLog("TOM: Writing word %04X at %06X\n", data, offset); + WriteLog(" -->[%06X] by %s\n", offset, whoName[who]); #endif + +#ifdef TOM_STRICT_MEMORY_ACCESS + // Sanity check + if ((offset < 0xF00000) || (offset > 0xF03FFF)) + return; +#endif + if (offset == 0xF00000 + MEMCON1) WriteLog("TOM: Memory Configuration 1 written by %s: %04X\n", whoName[who], data); if (offset == 0xF00000 + MEMCON2) @@ -1334,8 +1366,9 @@ if (offset >= 0xF02000 && offset <= 0xF020FF) if (offset == 0x2E || offset == 0x36 || offset == 0x54) data &= 0x03FF; // These are all 10-bit registers - TOMWriteByte(offset, data >> 8, who); - TOMWriteByte(offset+1, data & 0xFF, who); +// Fix a lockup bug... :-P + TOMWriteByte(0xF00000 | offset, data >> 8, who); + TOMWriteByte(0xF00000 | (offset+1), data & 0xFF, who); if (offset == VDB) WriteLog("TOM: Vertical Display Begin written by %s: %u\n", whoName[who], data); @@ -1367,6 +1400,11 @@ if (offset == VMODE) // detect screen resolution changes //This may go away in the future, if we do the virtualized screen thing... //This may go away soon! +// TOM Shouldn't be mucking around with this, it's up to the host system to properly +// handle this kind of crap. +// NOTE: This is needed somehow, need to get rid of the dependency on this crap. +#warning "!!! Need to get rid of this dependency !!!" +#if 1 if ((offset >= 0x28) && (offset <= 0x4F)) { uint32 width = TOMGetVideoModeWidth(), height = TOMGetVideoModeHeight(); @@ -1381,6 +1419,7 @@ if (offset == VMODE) // ResizeScreen(tomWidth, tomHeight); } } +#endif } int TOMIRQEnabled(int irq) -- 2.37.2