]> Shamusworld >> Repos - virtualjaguar/commitdiff
Added interlace display to TOM/video handler.
authorShamus Hammons <jlhamm@acm.org>
Tue, 10 Mar 2015 21:26:03 +0000 (16:26 -0500)
committerShamus Hammons <jlhamm@acm.org>
Tue, 10 Mar 2015 21:26:03 +0000 (16:26 -0500)
docs/WHATSNEW
src/gui/glwidget.cpp
src/jaguar.cpp
src/op.cpp
src/tom.cpp
src/tom.h

index 1e3892096f9237e6e84a62942234669d39e49586..730343657771f017361fe108f44c913bf74cc8b1 100644 (file)
@@ -1,7 +1,7 @@
 Virtual Jaguar v2.1.3 GCC/Qt
 ----------------------------
 
-* Nothing yet. ;-) [Shamus]
+* Added interlaced mode handling. [Shamus]
 
 
 Virtual Jaguar v2.1.2 GCC/Qt
index 8d69f63ff6a356e8775e929c7a5cfb58f4c60d18..b8c7a32609adac1c928a6d59f6fd4624efdc91f6 100644 (file)
@@ -61,25 +61,22 @@ void GLWidget::initializeGL()
 
 void GLWidget::paintGL()
 {
-//kludge [NO MORE!]
-//rasterHeight = (vjs.hardwareTypeNTSC ? VIRTUAL_SCREEN_HEIGHT_NTSC : VIRTUAL_SCREEN_HEIGHT_PAL);
-
        // If we're in fullscreen mode, we take the value of the screen width as
        // set by MainWin, since it may be wider than what our aspect ratio allows.
        // In that case, we adjust the viewport over so that it's centered on the
        // screen. Otherwise, we simply take the width from our width() funtion
        // which will always be correct in windowed mode.
 
-//     unsigned outputWidth  = width();
        if (!fullscreen)
                outputWidth = width();
 
+       // Bit 0 in VP is interlace flag. 0 = interlace, 1 = non-interlaced
+       double multiplier = (TOMGetVP() & 0x0001 ? 1.0 : 2.0);
        unsigned outputHeight = height();
 
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(0, outputWidth, 0, outputHeight, -1.0, 1.0);
-//     glViewport(0, 0, outputWidth, outputHeight);
        glViewport(0 + offset, 0, outputWidth, outputHeight);
 
        glMatrixMode(GL_MODELVIEW);
@@ -87,29 +84,18 @@ void GLWidget::paintGL()
 
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (vjs.glFilter ? GL_LINEAR : GL_NEAREST));
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (vjs.glFilter ? GL_LINEAR : GL_NEAREST));
-//     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, rasterWidth, rasterHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, buffer);
-//more kludge
-       glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, TOMGetVideoModeWidth(), rasterHeight, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, buffer);
-//     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, rasterWidth, rasterHeight, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, buffer);
+       glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, TOMGetVideoModeWidth(), rasterHeight * multiplier, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, buffer);
 
        double w = (double)TOMGetVideoModeWidth()  / (double)textureWidth;
-//     double w = (double)rasterWidth  / (double)textureWidth;
-       double h = (double)rasterHeight / (double)textureHeight;
+       double h = ((double)rasterHeight * multiplier) / (double)textureHeight;
        unsigned u = outputWidth;
        unsigned v = outputHeight;
 
        glBegin(GL_TRIANGLE_STRIP);
-#if 1
        glTexCoord2f(0, 0); glVertex3i(0, v, 0);
        glTexCoord2f(w, 0); glVertex3i(u, v, 0);
        glTexCoord2f(0, h); glVertex3i(0, 0, 0);
        glTexCoord2f(w, h); glVertex3i(u, 0, 0);
-#else
-       glTexCoord2f(0, 0); glVertex3i(0 + offset, v, 0);
-       glTexCoord2f(w, 0); glVertex3i(u + offset, v, 0);
-       glTexCoord2f(0, h); glVertex3i(0 + offset, 0, 0);
-       glTexCoord2f(w, h); glVertex3i(u + offset, 0, 0);
-#endif
        glEnd();
 }
 
index ac8a4308e72dc9f22183cf3606e79da7d0dd6396..7cf0bca8f6338238f7103236e93a534da9d30cf7 100644 (file)
@@ -2131,14 +2131,13 @@ void JaguarExecuteNew(void)
 }
 
 
-#define USE_CORRECT_PAL_TIMINGS
-// A lot of confusion comes from here...
-// The thing to keep in mind is that the VC is advanced every HALF line, regardless
-// of whether the display is interlaced or not. The only difference with an
-// interlaced display is that the high bit of VC will be set when the lower
-// field is being rendered. (NB: The high bit of VC is ALWAYS set on the lower field,
-// regardless of whether it's in interlace mode or not.
-// NB2: Seems it doens't always, not sure what the constraint is...)
+//
+// The thing to keep in mind is that the VC is advanced every HALF line,
+// regardless of whether the display is interlaced or not. The only difference
+// with an interlaced display is that the high bit of VC will be set when the
+// lower field is being rendered. (NB: The high bit of VC is ALWAYS set on the
+// lower field, regardless of whether it's in interlace mode or not.
+// NB2: Seems it doesn't always, not sure what the constraint is...)
 //
 // Normally, TVs will render a full frame in 1/30s (NTSC) or 1/25s (PAL) by
 // rendering two fields that are slighty vertically offset from each other.
@@ -2149,46 +2148,37 @@ void JaguarExecuteNew(void)
 // We execute a half frame in each timeslice (1/60s NTSC, 1/50s PAL).
 // Since the number of lines in a FULL frame is 525 for NTSC, 625 for PAL,
 // it will be half this number for a half frame. BUT, since we're counting
-// HALF lines, we double this number and we're back at 525 for NTSC, 625 for PAL.
+// HALF lines, we double this number and we're back at 525 for NTSC, 625 for
+// PAL.
 //
 // Scanline times are 63.5555... μs in NTSC and 64 μs in PAL
 // Half line times are, naturally, half of this. :-P
+//
 void HalflineCallback(void)
 {
-//OK, this is hardwired to run in NTSC, and for who knows how long.
-//Need to fix this so that it does a half-line in the correct amount of time
-//and number of lines, depending on which mode we're in. [FIXED]
        uint16_t vc = TOMReadWord(0xF00006, JAGUAR);
        uint16_t vp = TOMReadWord(0xF0003E, JAGUAR) + 1;
        uint16_t vi = TOMReadWord(0xF0004E, JAGUAR);
 //     uint16_t vbb = TOMReadWord(0xF00040, JAGUAR);
        vc++;
 
-#ifdef USE_CORRECT_PAL_TIMINGS
        // Each # of lines is for a full frame == 1/30s (NTSC), 1/25s (PAL).
        // So we cut the number of half-lines in a frame in half. :-P
        uint16_t numHalfLines = ((vjs.hardwareTypeNTSC ? 525 : 625) * 2) / 2;
 
        if ((vc & 0x7FF) >= numHalfLines)
-#else
-       if ((vc & 0x7FF) >= vp)
-#endif
        {
-               vc = 0;
-//             lowerField = !lowerField;
-
-               // If we're rendering the lower field, set the high bit (#12, counting
-               // from 1) of VC
-               if (lowerField)
-                       vc = 0x0800;
+               lowerField = !lowerField;
+               // If we're rendering the lower field, set the high bit (#11, counting
+               // from 0) of VC
+               vc = (lowerField ? 0x0800 : 0x0000);
        }
 
-//WriteLog("SLC: Currently on line %u (VP=%u)...\n", vc, vp);
+//WriteLog("HLC: Currently on line %u (VP=%u)...\n", vc, vp);
        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...
-       if ((vc & 0x7FF) == vi && (vc & 0x7FF) > 0 && TOMIRQEnabled(IRQ_VIDEO)) // Time for Vertical Interrupt?
+       // Time for Vertical Interrupt?
+       if ((vc & 0x7FF) == vi && (vc & 0x7FF) > 0 && TOMIRQEnabled(IRQ_VIDEO))
        {
                // We don't have to worry about autovectors & whatnot because the Jaguar
                // tells you through its HW registers who sent the interrupt...
@@ -2207,22 +2197,6 @@ void HalflineCallback(void)
                frameDone = true;
        }//*/
 
-#ifdef USE_CORRECT_PAL_TIMINGS
        SetCallbackTime(HalflineCallback, (vjs.hardwareTypeNTSC ? 31.777777777 : 32.0));
-#else
-//     SetCallbackTime(HalflineCallback, 63.5555);
-       SetCallbackTime(HalflineCallback, 31.77775);
-#endif
 }
 
-
-// This isn't currently used, but maybe it should be...
-/*
-Nah, the scanline based code is good enough, and runs in 1 frame. The GUI
-handles all the rest, so this isn't needed. :-P
-*/
-void RenderCallback(void)
-{
-//     SetCallbackTime(RenderCallback, 33303.082);     // # Scanlines * scanline time
-       SetCallbackTime(RenderCallback, 16651.541);     // # Scanlines * scanline time
-}
index 3cca7fa669aaa69969146d5511bd24cb5814cdc6..f4f858da1472aff8e6749fbf65dbdcd845edb9d0 100644 (file)
@@ -792,27 +792,22 @@ OP: Scaled bitmap 4x? 4bpp at 34,? hscale=80 fpix=0 data=000756E8 pitch 1 hflipp
                case OBJECT_TYPE_BRANCH:
                {
                        uint16_t 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_t  cc   = (p0 >> 14) & 0x03;
+                       // JTRM is wrong: CC is bits 14-16 (3 bits, *not* 2)
+                       uint8_t  cc   = (p0 >> 14) & 0x07;
                        uint32_t link = (p0 >> 21) & 0x3FFFF8;
 
-//                     if ((ypos!=507)&&(ypos!=25))
-//                             WriteLog("\t%i%s%i link=0x%.8x\n",halfline,condition_to_str[cc],ypos>>1,link);
                        switch (cc)
                        {
                        case CONDITION_EQUAL:
-                               if (TOMReadWord(0xF00006, OP) == ypos || ypos == 0x7FF)
+                               if (halfline == ypos || ypos == 0x7FF)
                                        op_pointer = link;
                                break;
                        case CONDITION_LESS_THAN:
-                               if (TOMReadWord(0xF00006, OP) < ypos)
+                               if (halfline < ypos)
                                        op_pointer = link;
                                break;
                        case CONDITION_GREATER_THAN:
-                               if (TOMReadWord(0xF00006, OP) > ypos)
+                               if (halfline > ypos)
                                        op_pointer = link;
                                break;
                        case CONDITION_OP_FLAG_SET:
@@ -820,15 +815,9 @@ OP: Scaled bitmap 4x? 4bpp at 34,? hscale=80 fpix=0 data=000756E8 pitch 1 hflipp
                                        op_pointer = link;
                                break;
                        case CONDITION_SECOND_HALF_LINE:
-//Here's the ASIC code:
-//  ND4(cctrue5, newheight[2], heightl[1], heightl[0], hcb[10]);
-//which means, do the link if bit 10 of HC is set...
-
-                               // This basically means branch if bit 10 of HC is set
-#warning "Unhandled condition code causes emulator to crash... !!! FIX !!!"
-                               WriteLog("OP: Unexpected CONDITION_SECOND_HALF_LINE in BRANCH object\nOP: shutting down!\n");
-                               LogDone();
-                               exit(0);
+                               // Branch if bit 10 of HC is set...
+                               if (TOMGetHC() & 0x0400)
+                                       op_pointer = link;
                                break;
                        default:
                                // Basically, if you do this, the OP does nothing. :-)
@@ -838,31 +827,19 @@ OP: Scaled bitmap 4x? 4bpp at 34,? hscale=80 fpix=0 data=000756E8 pitch 1 hflipp
                }
                case OBJECT_TYPE_STOP:
                {
-//op_start_log = 0;
-                       // unsure
-//WriteLog("OP: --> STOP\n");
-//                     op_set_status_register(((p0>>3) & 0xFFFFFFFF));
-//This seems more likely...
                        OPSetCurrentObject(p0);
 
-                       if (p0 & 0x08)
+                       if ((p0 & 0x08) && TOMIRQEnabled(IRQ_OPFLAG))
                        {
-                               // We need to check whether these interrupts are enabled or
-                               // not, THEN set an IRQ + pending flag if necessary...
-                               if (TOMIRQEnabled(IRQ_OPFLAG))
-                               {
-                                       TOMSetPendingObjectInt();
-                                       m68k_set_irq(2);                // Cause a 68K IPL 2 to occur...
-                               }
+                               TOMSetPendingObjectInt();
+                               m68k_set_irq(2);                // Cause a 68K IPL 2 to occur...
                        }
 
+                       // Bail out, we're done...
                        return;
-//                     break;
                }
                default:
-//                     WriteLog("op: unknown object type %i\n", ((uint8_t)p0 & 0x07));
-//                     return;
-                       ;
+                       WriteLog("OP: Unknown object type %i\n", (uint8_t)p0 & 0x07);
                }
 
                // Here is a little sanity check to keep the OP from locking up the
@@ -885,56 +862,59 @@ void OPProcessFixedBitmap(uint64_t p0, uint64_t p1, bool render)
 {
 // Need to make sure that when writing that it stays within the line buffer...
 // LBUF ($F01800 - $F01D9E) 360 x 32-bit RAM
-       uint8_t depth = (p1 >> 12) & 0x07;                              // Color depth of image
+       uint8_t depth = (p1 >> 12) & 0x07;              // Color depth of image
        int32_t xpos = ((int16_t)((p1 << 4) & 0xFFFF)) >> 4;// Image xpos in LBUF
-       uint32_t iwidth = (p1 >> 28) & 0x3FF;                           // Image width in *phrases*
-       uint32_t data = (p0 >> 40) & 0xFFFFF8;                  // Pixel data address
-//#ifdef OP_DEBUG_BMP
+       uint32_t iwidth = (p1 >> 28) & 0x3FF;   // Image width in *phrases*
+       uint32_t data = (p0 >> 40) & 0xFFFFF8;  // Pixel data address
        uint32_t firstPix = (p1 >> 49) & 0x3F;
        // "The LSB is significant only for scaled objects..." -JTRM
-       // "In 1 BPP mode, all five bits are significant. In 2 BPP mode, the top four are significant..."
+       // "In 1 BPP mode, all five bits are significant. In 2 BPP mode, the top
+       //  four are significant..."
        firstPix &= 0x3E;
-//#endif
+
 // We can ignore the RELEASE (high order) bit for now--probably forever...!
 //     uint8_t flags = (p1 >> 45) & 0x0F;      // REFLECT, RMW, TRANS, RELEASE
 //Optimize: break these out to their own BOOL values
-       uint8_t flags = (p1 >> 45) & 0x07;                              // REFLECT (0), RMW (1), TRANS (2)
+       uint8_t flags = (p1 >> 45) & 0x07;              // REFLECT (0), RMW (1), TRANS (2)
        bool flagREFLECT = (flags & OPFLAG_REFLECT ? true : false),
                flagRMW = (flags & OPFLAG_RMW ? true : false),
                flagTRANS = (flags & OPFLAG_TRANS ? true : false);
 // "For images with 1 to 4 bits/pixel the top 7 to 4 bits of the index
 //  provide the most significant bits of the palette address."
-       uint8_t index = (p1 >> 37) & 0xFE;                              // CLUT index offset (upper pix, 1-4 bpp)
-       uint32_t pitch = (p1 >> 15) & 0x07;                             // Phrase pitch
-       pitch <<= 3;                                                                    // Optimization: Multiply pitch by 8
+       uint8_t index = (p1 >> 37) & 0xFE;              // CLUT index offset (upper pix, 1-4 bpp)
+       uint32_t pitch = (p1 >> 15) & 0x07;             // Phrase pitch
+       pitch <<= 3;                                                    // Optimization: Multiply pitch by 8
 
 //     int16_t scanlineWidth = tom_getVideoModeWidth();
        uint8_t * tomRam8 = TOMGetRamPointer();
        uint8_t * paletteRAM = &tomRam8[0x400];
-       // This is OK as long as it's used correctly: For 16-bit RAM to RAM direct copies--NOT
-       // for use when using endian-corrected data (i.e., any of the *_word_read functions!)
+       // This is OK as long as it's used correctly: For 16-bit RAM to RAM direct
+       // copies--NOT for use when using endian-corrected data (i.e., any of the
+       // *_word_read functions!)
        uint16_t * paletteRAM16 = (uint16_t *)paletteRAM;
 
 //     WriteLog("bitmap %ix? %ibpp at %i,? firstpix=? data=0x%.8x pitch %i hflipped=%s dwidth=? (linked to ?) RMW=%s Tranparent=%s\n",
 //             iwidth, op_bitmap_bit_depth[bitdepth], xpos, ptr, pitch, (flags&OPFLAG_REFLECT ? "yes" : "no"), (flags&OPFLAG_RMW ? "yes" : "no"), (flags&OPFLAG_TRANS ? "yes" : "no"));
 
 // 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.
+// 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...
+//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!
+//I'm not convinced that we need to concern ourselves with data & op_pointer
+//here either!
        if (!render || iwidth == 0)
                return;
 
-//OK, so we know the position in the line buffer is correct. It's the clipping in
-//24bpp mode that's wrong!
+//OK, so we know the position in the line buffer is correct. It's the clipping
+//in 24bpp mode that's wrong!
 #if 0
 //This is a total kludge, based upon the fact that 24BPP mode puts *4* bytes
 //into the line buffer for each pixel.
@@ -954,17 +934,12 @@ if (depth == 5)   // i.e., 24bpp mode...
                : -((phraseWidthToPixels[depth] * iwidth) + 1));
        uint32_t clippedWidth = 0, phraseClippedWidth = 0, dataClippedWidth = 0;//, phrasePixel = 0;
        bool in24BPPMode = (((GET16(tomRam8, 0x0028) >> 1) & 0x03) == 1 ? true : false);        // VMODE
-       // Not sure if this is Jaguar Two only location or what...
-       // From the docs, it is... If we want to limit here we should think of something else.
-//     int32_t limit = GET16(tom_ram_8, 0x0008);                       // LIMIT
-//     int32_t limit = 720;
-//     int32_t lbufWidth = (!in24BPPMode ? limit - 1 : (limit / 2) - 1);       // Zero based limit...
-//printf("[OP:xpos=%i,spos=%i,epos=%i>", xpos, startPos, endPos);
        // This is correct, the OP line buffer is a constant size... 
        int32_t limit = 720;
        int32_t lbufWidth = 719;
 
-       // If the image is completely to the left or right of the line buffer, then bail.
+       // If the image is completely to the left or right of the line buffer, then
+       // bail.
 //If in REFLECT mode, then these values are swapped! !!! FIX !!! [DONE]
 //There are four possibilities:
 //  1. image sits on left edge and no REFLECT; starts out of bounds but ends in bounds.
@@ -1020,7 +995,8 @@ if (depth == 5)    // i.e., 24bpp mode...
 if (depth > 5)
        WriteLog("OP: We're about to encounter a divide by zero error!\n");
        // NOTE: We're just using endPos to figure out how much, if any, to clip by.
-       // ALSO: There may be another case where we start out of bounds and end out of bounds...!
+       // ALSO: There may be another case where we start out of bounds and end out
+       // of bounds...!
        // !!! FIX !!!
        if (startPos < 0)                       // Case #1: Begin out, end in, L to R
                clippedWidth = 0 - startPos,
@@ -1277,11 +1253,12 @@ if (firstPix)
                        for(int i=0; i<4; i++)
                        {
                                uint8_t bitsHi = pixels >> 56, bitsLo = pixels >> 48;
-// Seems to me that both of these are in the same endian, so we could cast it as
-// uint16_t * and do straight across copies (what about 24 bpp? Treat it differently...)
-// This only works for the palettized modes (1 - 8 BPP), since we actually have to
-// copy data from memory in 16 BPP mode (or does it? Isn't this the same as the CLUT case?)
-// No, it isn't because we read the memory in an endian safe way--it *won't* work...
+// Seems to me that both of these are in the same endian, so we could cast it
+// as uint16_t * and do straight across copies (what about 24 bpp? Treat it
+// differently...) This only works for the palettized modes (1 - 8 BPP), since
+// we actually have to copy data from memory in 16 BPP mode (or does it? Isn't
+// this the same as the CLUT case?) No, it isn't because we read the memory in
+// an endian safe way--it *won't* work...
 //This doesn't seem right... Let's try the encoded black value ($8800):
 //Apparently, CRY 0 maps to $8800...
                                if (flagTRANS && ((bitsLo | bitsHi) == 0))
index be4972a56debe876ef22c1070eabe8e4dd733a84..111adfdad762cf16936e9af58b807a2b823b943e 100644 (file)
@@ -649,6 +649,18 @@ uint16_t TOMGetVDB(void)
 }
 
 
+uint16_t TOMGetHC(void)
+{
+       return GET16(tomRam8, HC);
+}
+
+
+uint16_t TOMGetVP(void)
+{
+       return GET16(tomRam8, VP);
+}
+
+
 #define LEFT_BG_FIX
 //
 // 16 BPP CRY/RGB mixed mode rendering
@@ -854,37 +866,36 @@ void tom_render_16bpp_rgb_scanline(uint32_t * backbuffer)
 
 
 //
-// Process a single scanline
-// (this is bad terminology; each tick of the VC is actually a half-line)
+// Process a single halfline
 //
 void TOMExecHalfline(uint16_t halfline, bool render)
 {
-#warning "!!! Need to handle multiple fields properly !!!"
-       // We ignore the problem for now
-       halfline &= 0x7FF;
-
+       uint16_t field2 = halfline & 0x0800;
+       halfline &= 0x07FF;
        bool inActiveDisplayArea = true;
 
-//Interlacing is still not handled correctly here... !!! FIX !!!
-       if (halfline & 0x01)                                                    // Execute OP only on even halflines (non-interlaced only!)
+       // Execute OP only on even halflines (skip higher resolutions for now...)
+       if (halfline & 0x01)
                return;
 
 //Hm, it seems that the OP needs to execute from zero, so let's try it:
-// And it works! But need to do some optimizations in the OP to keep it from attempting
-// to do a scanline render in the non-display area... [DONE]
+// And it works! But need to do some optimizations in the OP to keep it from
+// attempting to do a scanline render in the non-display area... [DONE]
 //this seems to cause a regression in certain games, like rayman
 //which means I have to dig thru the asic nets to see what's wrong...
 /*
-No, the OP doesn't start until VDB, that much is certain. The thing is, VDB is the
-HALF line that the OP starts on--which means that it needs to start at VDB / 2!!!
+No, the OP doesn't start until VDB, that much is certain. The thing is, VDB is
+the HALF line that the OP starts on--which means that it needs to start at
+VDB / 2!!!
 
-Hrm, doesn't seem to be enough, though it should be... still sticks for 20 frames.
+Hrm, doesn't seem to be enough, though it should be... still sticks for 20
+frames.
 
 
-What triggers this is writing $FFFF to VDE. This causes the OP start signal in VID to 
-latch on, which in effect sets VDB to zero. So that much is correct. But the thing with
-Rayman is that it shouldn't cause the graphical glitches seen there, so still have to
-investigate what's going on there. By all rights, it shouldn't glitch because:
+What triggers this is writing $FFFF to VDE. This causes the OP start signal in VID to latch on, which in effect sets VDB to zero. So that much is correct. But
+the thing with Rayman is that it shouldn't cause the graphical glitches seen
+there, so still have to investigate what's going on there. By all rights, it
+shouldn't glitch because:
 
 00006C00: 0000000D 82008F73 (BRANCH) YPOS=494, CC=">", link=$00006C10
 00006C08: 000003FF 00008173 (BRANCH) YPOS=46, CC=">", link=$001FF800
@@ -892,8 +903,8 @@ investigate what's going on there. By all rights, it shouldn't glitch because:
 001FF800: 12FC2BFF 02380000 (BITMAP)
           00008004 8180CFF1
 
-Even if the OP is running all the time, the link should tell it to stop at the right
-place (which it seems to do). But we still get glitchy screen.
+Even if the OP is running all the time, the link should tell it to stop at the
+right place (which it seems to do). But we still get glitchy screen.
 
 Seems the glitchy screen went away... Maybe the GPU alignment fixes fixed it???
 Just need to add the proper checking here then.
@@ -921,18 +932,19 @@ TOM: Vertical Display Begin written by M68K: 41
 TOM: Vertical Display End written by M68K: 2047
 TOM: Vertical Interrupt written by M68K: 491
 */
-#if 1
+
        // Initial values that "well behaved" programs use
        uint16_t startingHalfline = GET16(tomRam8, VDB);
        uint16_t endingHalfline = GET16(tomRam8, VDE);
 
        // Simulate the OP start bug here!
        // Really, this value is somewhere around 507 for an NTSC Jaguar. But this
-       // should work in a majority of cases, at least until we can figure it out properly.
+       // should work in a majority of cases, at least until we can figure it out
+       // properly.
        if (endingHalfline > GET16(tomRam8, VP))
                startingHalfline = 0;
 
-       if (halfline >= startingHalfline && halfline < endingHalfline)
+       if ((halfline >= startingHalfline) && (halfline < endingHalfline))
 //     if (halfline >= 0 && halfline < (uint16_t)GET16(tomRam8, VDE))
 // 16 isn't enough, and neither is 32 for raptgun. 32 fucks up Rayman
 //     if (halfline >= ((uint16_t)GET16(tomRam8, VDB) / 2) && halfline < ((uint16_t)GET16(tomRam8, VDE) / 2))
@@ -955,49 +967,33 @@ TOM: Vertical Interrupt written by M68K: 491
        }
        else
                inActiveDisplayArea = false;
-#else
-       inActiveDisplayArea =
-               (halfline >= (uint16_t)GET16(tomRam8, VDB) && halfline < (uint16_t)GET16(tomRam8, VDE)
-                       ? true : false);
 
-       if (halfline < (uint16_t)GET16(tomRam8, VDE))
-       {
-               if (render)//With JaguarExecuteNew() this is always true...
-               {
-                       uint8_t * current_line_buffer = (uint8_t *)&tomRam8[0x1800];
-                       uint8_t bgHI = tomRam8[BG], bgLO = tomRam8[BG + 1];
-
-                       // Clear line buffer with BG
-                       if (GET16(tomRam8, VMODE) & BGEN) // && (CRY or RGB16)...
-                               for(uint32_t i=0; i<720; i++)
-                                       *current_line_buffer++ = bgHI, *current_line_buffer++ = bgLO;
-
-//                     OPProcessList(halfline, render);
-//This seems to take care of it...
-                       OPProcessList(halfline, inActiveDisplayArea);
-               }
-       }
-#endif
-
-       // Try to take PAL into account... [We do now!]
+       // Take PAL into account...
 
        uint16_t topVisible = (vjs.hardwareTypeNTSC ? TOP_VISIBLE_VC : TOP_VISIBLE_VC_PAL),
                bottomVisible = (vjs.hardwareTypeNTSC ? BOTTOM_VISIBLE_VC : BOTTOM_VISIBLE_VC_PAL);
-       uint32_t * TOMCurrentLine = &(screenBuffer[((halfline - topVisible) / 2) * screenPitch]);
+       uint32_t * TOMCurrentLine = 0;
+
+       // Bit 0 in VP is interlace flag. 0 = interlace, 1 = non-interlaced
+       if (tomRam8[VP + 1] & 0x01)
+               TOMCurrentLine = &(screenBuffer[((halfline - topVisible) / 2) * screenPitch]);//non-interlace
+       else
+               TOMCurrentLine = &(screenBuffer[(((halfline - topVisible) / 2) * screenPitch * 2) + (field2 ? 0 : screenPitch)]);//interlace
 
        // Here's our virtualized scanline code...
 
-       if (halfline >= topVisible && halfline < bottomVisible)
+       if ((halfline >= topVisible) && (halfline < bottomVisible))
        {
                if (inActiveDisplayArea)
                {
-//NOTE: The following doesn't put BORDER color on the sides... !!! FIX !!!
 #warning "The following doesn't put BORDER color on the sides... !!! FIX !!!"
                        if (vjs.renderType == RT_NORMAL)
-//                             scanline_render[TOMGetVideoMode()](TOMBackbuffer);
+                       {
                                scanline_render[TOMGetVideoMode()](TOMCurrentLine);
-                       else//TV type render
+                       }
+                       else
                        {
+                               // TV type render
 /*
        tom_render_16bpp_cry_scanline,
        tom_render_24bpp_scanline,
@@ -1014,13 +1010,14 @@ TOM: Vertical Interrupt written by M68K: 491
                                uint8_t pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
                                uint8_t mode = ((GET16(tomRam8, VMODE) & MODE) >> 1);
                                bool varmod = GET16(tomRam8, VMODE) & VARMOD;
-//The video texture line buffer ranges from 0 to 1279, with its left edge starting at
-//LEFT_VISIBLE_HC. So, we need to start writing into the backbuffer at HDB1, using pwidth
-//as our scaling factor. The way it generates its image on a real TV!
-
-//So, for example, if HDB1 is less than LEFT_VISIBLE_HC, then we have to figure out where
-//in the VTLB that we start writing pixels from the Jaguar line buffer (VTLB start=0,
-//JLB=something).
+//The video texture line buffer ranges from 0 to 1279, with its left edge
+//starting at LEFT_VISIBLE_HC. So, we need to start writing into the backbuffer
+//at HDB1, using pwidth as our scaling factor. The way it generates its image
+//on a real TV!
+
+//So, for example, if HDB1 is less than LEFT_VISIBLE_HC, then we have to figure
+//out where in the VTLB that we start writing pixels from the Jaguar line
+//buffer (VTLB start=0, JLB=something).
 #if 0
 //
 // 24 BPP mode rendering
index ed89b93cf41b9ae87fc1fedf743ed62ed4622005..8c5640a3d697589c52820e2f89d6a446d8ee9846 100644 (file)
--- a/src/tom.h
+++ b/src/tom.h
@@ -41,6 +41,8 @@ uint8_t TOMGetVideoMode(void);
 uint8_t * TOMGetRamPointer(void);
 uint16_t TOMGetHDB(void);
 uint16_t TOMGetVDB(void);
+uint16_t TOMGetHC(void);
+uint16_t TOMGetVP(void);
 void TOMDumpIORegistersToLog(void);