]> Shamusworld >> Repos - virtualjaguar/blobdiff - src/op.cpp
Added Object Processor browser window for debug mode.
[virtualjaguar] / src / op.cpp
index e10e4bb6d2769e7b170d6f4799348d62b198d869..25322c91c6109b280bb2fbf01763924bce537e90 100644 (file)
@@ -3,10 +3,10 @@
 //
 // Original source by David Raingeard (Cal2)
 // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
-// Extensive cleanups/fixes/rewrites by James L. Hammons
+// Extensive cleanups/fixes/rewrites by James Hammons
 // (C) 2010 Underground Software
 //
-// JLH = James L. Hammons <jlhamm@acm.org>
+// JLH = James Hammons <jlhamm@acm.org>
 //
 // Who  When        What
 // ---  ----------  -------------------------------------------------------------
@@ -20,7 +20,7 @@
 #include "gpu.h"
 #include "jaguar.h"
 #include "log.h"
-#include "m68k.h"
+#include "m68000/m68kinterface.h"
 #include "memory.h"
 #include "tom.h"
 
 #define OBJECT_TYPE_BRANCH     3                                       // 011
 #define OBJECT_TYPE_STOP       4                                       // 100
 
-#define CONDITION_EQUAL                                0
-#define CONDITION_LESS_THAN                    1
-#define CONDITION_GREATER_THAN         2
+#define CONDITION_EQUAL                                0                       // VC == YPOS
+#define CONDITION_LESS_THAN                    1                       // VC < YPOS
+#define CONDITION_GREATER_THAN         2                       // VC > YPOS
 #define CONDITION_OP_FLAG_SET          3
 #define CONDITION_SECOND_HALF_LINE     4
 
+#if 0
 #define OPFLAG_RELEASE         8                                       // Bus release bit
 #define OPFLAG_TRANS           4                                       // Transparency bit
 #define OPFLAG_RMW                     2                                       // Read-Modify-Write bit
 #define OPFLAG_REFLECT         1                                       // Horizontal mirror bit
+#endif
 
 // Private function prototypes
 
 void OPProcessFixedBitmap(uint64 p0, uint64 p1, bool render);
 void OPProcessScaledBitmap(uint64 p0, uint64 p1, uint64 p2, bool render);
+void OPDiscoverObjects(uint32 address);
+void OPDumpObjectList(void);
 void DumpScaledObject(uint64 p0, uint64 p1, uint64 p2);
 void DumpFixedObject(uint64 p0, uint64 p1);
+void DumpBitmapCore(uint64 p0, uint64 p1);
 uint64 OPLoadPhrase(uint32 offset);
 
 // Local global variables
@@ -122,6 +127,7 @@ void OPInit(void)
        OPReset();
 }
 
+
 //
 // Object Processor reset
 //
@@ -131,21 +137,35 @@ void OPReset(void)
        objectp_running = 0;
 }
 
+
+static const char * opType[8] =
+{ "(BITMAP)", "(SCALED BITMAP)", "(GPU INT)", "(BRANCH)", "(STOP)", "???", "???", "???" };
+static const char * ccType[8] =
+       { "\"==\"", "\"<\"", "\">\"", "(opflag set)", "(second half line)", "?", "?", "?" };
+static uint32 object[8192];
+static uint32 numberOfObjects;
+//static uint32 objectLink[8192];
+//static uint32 numberOfLinks;
+
+
 void OPDone(void)
 {
-#warning "!!! Fix OL dump so that it follows links !!!"
-       const char * opType[8] =
-       { "(BITMAP)", "(SCALED BITMAP)", "(GPU INT)", "(BRANCH)", "(STOP)", "???", "???", "???" };
-       const char * ccType[8] =
-               { "\"==\"", "\"<\"", "\">\"", "(opflag set)", "(second half line)", "?", "?", "?" };
+//#warning "!!! Fix OL dump so that it follows links !!!"
+//     const char * opType[8] =
+//     { "(BITMAP)", "(SCALED BITMAP)", "(GPU INT)", "(BRANCH)", "(STOP)", "???", "???", "???" };
+//     const char * ccType[8] =
+//             { "\"==\"", "\"<\"", "\">\"", "(opflag set)", "(second half line)", "?", "?", "?" };
 
        uint32 olp = OPGetListPointer();
-       WriteLog("OP: OLP = %08X\n", olp);
+       WriteLog("\nOP: OLP = $%08X\n", olp);
        WriteLog("OP: Phrase dump\n    ----------\n");
+
+#if 0
        for(uint32 i=0; i<0x100; i+=8)
        {
                uint32 hi = JaguarReadLong(olp + i, OP), lo = JaguarReadLong(olp + i + 4, OP);
                WriteLog("\t%08X: %08X %08X %s", olp + i, hi, lo, opType[lo & 0x07]);
+
                if ((lo & 0x07) == 3)
                {
                        uint16 ypos = (lo >> 3) & 0x7FF;
@@ -153,18 +173,116 @@ void OPDone(void)
                        uint32 link = ((hi << 11) | (lo >> 21)) & 0x3FFFF8;
                        WriteLog(" YPOS=%u, CC=%s, link=%08X", ypos, ccType[cc], link);
                }
+
                WriteLog("\n");
+
                if ((lo & 0x07) == 0)
                        DumpFixedObject(OPLoadPhrase(olp+i), OPLoadPhrase(olp+i+8));
+
                if ((lo & 0x07) == 1)
                        DumpScaledObject(OPLoadPhrase(olp+i), OPLoadPhrase(olp+i+8), OPLoadPhrase(olp+i+16));
        }
+
        WriteLog("\n");
+#else
+//#warning "!!! Fix lockup in OPDiscoverObjects() !!!"
+//temp, to keep the following function from locking up on bad/weird OLs
+//return;
+
+       numberOfObjects = 0;
+//printf("OPDiscoverObjects...\n");
+       OPDiscoverObjects(olp);
+//printf("OPDumpObjectList...\n");
+       OPDumpObjectList();
+#endif
+}
+
 
-//     memory_free(op_blend_y);
-//     memory_free(op_blend_cr);
+bool OPObjectExists(uint32 address)
+{
+       // Yes, we really do a linear search, every time. :-/
+       for(uint32 i=0; i<numberOfObjects; i++)
+       {
+               if (address == object[i])
+                       return true;
+       }
+
+       return false;
 }
 
+
+void OPDiscoverObjects(uint32 address)
+{
+       uint8 objectType = 0;
+
+       do
+       {
+               // If we've seen this object already, bail out!
+               // Otherwise, add it to the list
+               if (OPObjectExists(address))
+                       return;
+
+               object[numberOfObjects++] = address;
+
+               // Get the object & decode its type, link address
+               uint32 hi = JaguarReadLong(address + 0, OP);
+               uint32 lo = JaguarReadLong(address + 4, OP);
+               objectType = lo & 0x07;
+               uint32 link = ((hi << 11) | (lo >> 21)) & 0x3FFFF8;
+
+               if (objectType == 3)
+               {
+                       // Recursion needed to follow all links! This does depth-first recursion
+                       // on the not-taken objects
+                       OPDiscoverObjects(address + 8);
+               }
+
+               // Get the next object...
+               address = link;
+       }
+       while (objectType != 4);
+}
+
+
+void OPDumpObjectList(void)
+{
+       for(uint32 i=0; i<numberOfObjects; i++)
+       {
+               uint32 address = object[i];
+
+               uint32 hi = JaguarReadLong(address + 0, OP);
+               uint32 lo = JaguarReadLong(address + 4, OP);
+               uint8 objectType = lo & 0x07;
+               uint32 link = ((hi << 11) | (lo >> 21)) & 0x3FFFF8;
+               WriteLog("%08X: %08X %08X %s", address, hi, lo, opType[objectType]);
+
+               if (objectType == 3)
+               {
+                       uint16 ypos = (lo >> 3) & 0x7FF;
+                       uint8  cc   = (lo >> 14) & 0x07;        // Proper # of bits == 3
+                       WriteLog(" YPOS=%u, CC=%s, link=$%08X", ypos, ccType[cc], link);
+               }
+
+               WriteLog("\n");
+
+               if (objectType == 0)
+                       DumpFixedObject(OPLoadPhrase(address + 0), OPLoadPhrase(address + 8));
+
+               if (objectType == 1)
+                       DumpScaledObject(OPLoadPhrase(address + 0), OPLoadPhrase(address + 8),
+                               OPLoadPhrase(address + 16));
+
+               if (address == link)    // Ruh roh...
+               {
+                       // Runaway recursive link is bad!
+                       WriteLog("***** SELF REFERENTIAL LINK *****\n\n");
+               }
+       }
+
+       WriteLog("\n");
+}
+
+
 //
 // Object Processor memory access
 // Memory range: F00010 - F00027
@@ -205,12 +323,14 @@ WriteLog("OP: Setting hi list pointer: %04X\n", data);//*/
 }
 #endif
 
+
 uint32 OPGetListPointer(void)
 {
        // Note: This register is LO / HI WORD, hence the funky look of this...
        return GET16(tomRam8, 0x20) | (GET16(tomRam8, 0x22) << 16);
 }
 
+
 // This is WRONG, since the OBF is only 16 bits wide!!! [FIXED]
 
 uint32 OPGetStatusRegister(void)
@@ -218,6 +338,7 @@ uint32 OPGetStatusRegister(void)
        return GET16(tomRam8, 0x26);
 }
 
+
 // This is WRONG, since the OBF is only 16 bits wide!!! [FIXED]
 
 void OPSetStatusRegister(uint32 data)
@@ -226,6 +347,7 @@ void OPSetStatusRegister(uint32 data)
        tomRam8[0x27] |= (data & 0xFE);
 }
 
+
 void OPSetCurrentObject(uint64 object)
 {
 //Not sure this is right... Wouldn't it just be stored 64 bit BE?
@@ -251,12 +373,14 @@ void OPSetCurrentObject(uint64 object)
        tomRam8[0x10] = object & 0xFF;
 }
 
+
 uint64 OPLoadPhrase(uint32 offset)
 {
        offset &= ~0x07;                                                // 8 byte alignment
        return ((uint64)JaguarReadLong(offset, OP) << 32) | (uint64)JaguarReadLong(offset+4, OP);
 }
 
+
 void OPStorePhrase(uint32 offset, uint64 p)
 {
        offset &= ~0x07;                                                // 8 byte alignment
@@ -264,45 +388,37 @@ void OPStorePhrase(uint32 offset, uint64 p)
        JaguarWriteLong(offset + 4, p & 0xFFFFFFFF, OP);
 }
 
+
 //
 // Debugging routines
 //
 void DumpScaledObject(uint64 p0, uint64 p1, uint64 p2)
 {
-       WriteLog(" (SCALED BITMAP)");
-       WriteLog(" %08X --> phrase %08X %08X\n", op_pointer, (uint32)(p1>>32), (uint32)(p1&0xFFFFFFFF));
-       WriteLog("                 %08X --> phrase %08X %08X ", op_pointer+8, (uint32)(p2>>32), (uint32)(p2&0xFFFFFFFF));
-       uint8 bitdepth = (p1 >> 12) & 0x07;
-//WAS: int16 ypos = ((p0 >> 3) & 0x3FF);                       // ??? What if not interlaced (/2)?
-       int16 ypos = ((p0 >> 3) & 0x7FF);                       // ??? What if not interlaced (/2)?
-       int32 xpos = p1 & 0xFFF;
-       xpos = (xpos & 0x800 ? xpos | 0xFFFFF000 : xpos);
-       uint32 iwidth = ((p1 >> 28) & 0x3FF);
-       uint32 dwidth = ((p1 >> 18) & 0x3FF);           // Unsigned!
-       uint16 height = ((p0 >> 14) & 0x3FF);
-       uint32 link = ((p0 >> 24) & 0x7FFFF) << 3;
-       uint32 ptr = ((p0 >> 43) & 0x1FFFFF) << 3;
-       uint32 firstPix = (p1 >> 49) & 0x3F;
-       uint8 flags = (p1 >> 45) & 0x0F;
-       uint8 idx = (p1 >> 38) & 0x7F;
-       uint32 pitch = (p1 >> 15) & 0x07;
-       WriteLog("\n    [%u (%u) x %u @ (%i, %u) (%u bpp), l: %08X, p: %08X fp: %02X, fl:%s%s%s%s, idx:%02X, pt:%02X]\n",
-               iwidth, dwidth, height, xpos, ypos, op_bitmap_bit_depth[bitdepth], link, ptr, firstPix, (flags&OPFLAG_REFLECT ? "REFLECT " : ""), (flags&OPFLAG_RMW ? "RMW " : ""), (flags&OPFLAG_TRANS ? "TRANS " : ""), (flags&OPFLAG_RELEASE ? "RELEASE" : ""), idx, pitch);
+       WriteLog("          %08X %08X\n", (uint32)(p1>>32), (uint32)(p1&0xFFFFFFFF));
+       WriteLog("          %08X %08X\n", (uint32)(p2>>32), (uint32)(p2&0xFFFFFFFF));
+       DumpBitmapCore(p0, p1);
        uint32 hscale = p2 & 0xFF;
        uint32 vscale = (p2 >> 8) & 0xFF;
        uint32 remainder = (p2 >> 16) & 0xFF;
        WriteLog("    [hsc: %02X, vsc: %02X, rem: %02X]\n", hscale, vscale, remainder);
 }
 
+
 void DumpFixedObject(uint64 p0, uint64 p1)
 {
-       WriteLog(" (BITMAP)");
-       WriteLog(" %08X --> phrase %08X %08X\n", op_pointer, (uint32)(p1>>32), (uint32)(p1&0xFFFFFFFF));
+       WriteLog("          %08X %08X\n", (uint32)(p1>>32), (uint32)(p1&0xFFFFFFFF));
+       DumpBitmapCore(p0, p1);
+}
+
+
+void DumpBitmapCore(uint64 p0, uint64 p1)
+{
+       uint32 bdMultiplier[8] = { 64, 32, 16, 8, 4, 2, 1, 1 };
        uint8 bitdepth = (p1 >> 12) & 0x07;
 //WAS: int16 ypos = ((p0 >> 3) & 0x3FF);                       // ??? What if not interlaced (/2)?
        int16 ypos = ((p0 >> 3) & 0x7FF);                       // ??? What if not interlaced (/2)?
        int32 xpos = p1 & 0xFFF;
-       xpos = (xpos & 0x800 ? xpos | 0xFFFFF000 : xpos);
+       xpos = (xpos & 0x800 ? xpos | 0xFFFFF000 : xpos);       // Sign extend that mutha!
        uint32 iwidth = ((p1 >> 28) & 0x3FF);
        uint32 dwidth = ((p1 >> 18) & 0x3FF);           // Unsigned!
        uint16 height = ((p0 >> 14) & 0x3FF);
@@ -312,16 +428,25 @@ void DumpFixedObject(uint64 p0, uint64 p1)
        uint8 flags = (p1 >> 45) & 0x0F;
        uint8 idx = (p1 >> 38) & 0x7F;
        uint32 pitch = (p1 >> 15) & 0x07;
-       WriteLog("    [%u (%u) x %u @ (%i, %u) (%u bpp), l: %08X, p: %08X fp: %02X, fl:%s%s%s%s, idx:%02X, pt:%02X]\n",
-               iwidth, dwidth, height, xpos, ypos, op_bitmap_bit_depth[bitdepth], link, ptr, firstPix, (flags&OPFLAG_REFLECT ? "REFLECT " : ""), (flags&OPFLAG_RMW ? "RMW " : ""), (flags&OPFLAG_TRANS ? "TRANS " : ""), (flags&OPFLAG_RELEASE ? "RELEASE" : ""), idx, pitch);
+       WriteLog("    [%u x %u @ (%i, %u) (iw:%u, dw:%u) (%u bpp), l:%08X, p:%08X fp:%02X, fl:%s%s%s%s, idx:%02X, pt:%02X]\n",
+               iwidth * bdMultiplier[bitdepth],
+               height, xpos, ypos, iwidth, dwidth, op_bitmap_bit_depth[bitdepth], link,
+               ptr, firstPix, (flags&OPFLAG_REFLECT ? "REFLECT " : ""),
+               (flags&OPFLAG_RMW ? "RMW " : ""), (flags&OPFLAG_TRANS ? "TRANS " : ""),
+               (flags&OPFLAG_RELEASE ? "RELEASE" : ""), idx, pitch);
 }
 
+
 //
 // Object Processor main routine
 //
 #warning "Need to fix this so that when an GPU object IRQ happens, we can pick up OP processing where we left off. !!! FIX !!!"
 void OPProcessList(int halfline, bool render)
 {
+#warning "!!! NEED TO HANDLE MULTIPLE FIELDS PROPERLY !!!
+// We ignore them, for now; not good
+       halfline &= 0x7FF;
+
 extern int op_start_log;
 //     char * condition_to_str[8] =
 //             { "==", "<", ">", "(opflag set)", "(second half line)", "?", "?", "?" };
@@ -505,8 +630,17 @@ if (!inhibit)      // For OP testing only!
 /*     if (op_pointer > ((p0 & 0x000007FFFF000000LL) >> 21))
                return;*/
 
-                       op_pointer = (p0 & 0x000007FFFF000000LL) >> 21;
+// NOTE: The link address only replaces bits 3-21 in the OLP, and this replaces
+//       EVERYTHING. !!! FIX !!! [DONE]
+#warning "!!! Link address is not linked properly for all object types !!!"
+#warning "!!! Only BITMAP is properly handled !!!"
+                       op_pointer &= 0xFFC00007;
+                       op_pointer |= (p0 & 0x000007FFFF000000LL) >> 21;
 //WriteLog("New OP: %08X\n", op_pointer);
+//kludge: Seems that memory access is mirrored in the first 8MB of memory...
+if (op_pointer > 0x1FFFFF && op_pointer < 0x800000)
+       op_pointer &= 0xFF1FFFFF;       // Knock out bits 21-23
+
                        break;
                }
                case OBJECT_TYPE_SCALE:
@@ -658,6 +792,10 @@ OP: Scaled bitmap 4x? 4bpp at 34,? hscale=80 fpix=0 data=000756E8 pitch 1 hflipp
                case OBJECT_TYPE_BRANCH:
                {
                        uint16 ypos = (p0 >> 3) & 0x7FF;
+// NOTE: The JTRM sez there are only 2 bits used for the CC, but lists *five*
+//       conditions! Need at least one more bit for that! :-P
+// Also, the ASIC nets imply that it uses bits 14-16 (height in BM & SBM objects)
+#warning "!!! Possibly bad CC handling in OP (missing 1 bit) !!!"
                        uint8  cc   = (p0 >> 14) & 0x03;
                        uint32 link = (p0 >> 21) & 0x3FFFF8;
 
@@ -722,7 +860,7 @@ OP: Scaled bitmap 4x? 4bpp at 34,? hscale=80 fpix=0 data=000756E8 pitch 1 hflipp
 //                     break;
                }
                default:
-                       WriteLog("op: unknown object type %i\n", ((uint8)p0 & 0x07));
+//                     WriteLog("op: unknown object type %i\n", ((uint8)p0 & 0x07));
                        return;
                }
 
@@ -737,6 +875,7 @@ OP: Scaled bitmap 4x? 4bpp at 34,? hscale=80 fpix=0 data=000756E8 pitch 1 hflipp
        }
 }
 
+
 //
 // Store fixed size bitmap in line buffer
 //
@@ -780,6 +919,13 @@ void OPProcessFixedBitmap(uint64 p0, uint64 p1, bool render)
 // Is it OK to have a 0 for the data width??? (i.e., undocumented?)
 // Seems to be... Seems that dwidth *can* be zero (i.e., reuse same line) as well.
 // Pitch == 0 is OK too...
+
+//kludge: Seems that the OP treats iwidth == 0 as iwidth == 1... Need to investigate
+//        on real hardware...
+#warning "!!! Need to investigate iwidth == 0 behavior on real hardware !!!"
+if (iwidth == 0)
+       iwidth = 1;
+
 //     if (!render || op_pointer == 0 || ptr == 0 || pitch == 0)
 //I'm not convinced that we need to concern ourselves with data & op_pointer here either!
        if (!render || iwidth == 0)
@@ -1194,6 +1340,7 @@ if (firstPix)
        }
 }
 
+
 //
 // Store scaled bitmap in line buffer
 //