//
// Originally by David Raingeard (cal2)
// GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
-// Cleanups and endian wrongness amelioration by James L. Hammons
+// Cleanups and endian wrongness amelioration by James Hammons
// (C) 2010 Underground Software
//
-// JLH = James L. Hammons <jlhamm@acm.org>
+// JLH = James Hammons <jlhamm@acm.org>
//
// Who When What
// --- ---------- -------------------------------------------------------------
#include "gpu.h"
#include "jaguar.h"
#include "log.h"
-#include "m68k.h"
+#include "m68000/m68kinterface.h"
//#include "memory.h"
#include "op.h"
#include "settings.h"
// Also note that VC is in *half* lines, i.e. divide by 2 to get the scanline
/*#define LEFT_VISIBLE_HC 208
#define RIGHT_VISIBLE_HC 1528//*/
-#define LEFT_VISIBLE_HC 208
-#define RIGHT_VISIBLE_HC 1488
+// These were right for Rayman, but that one is offset on a real TV too.
+//#define LEFT_VISIBLE_HC 208
+//#define RIGHT_VISIBLE_HC 1488
+// This is more like a real TV display...
+//#define LEFT_VISIBLE_HC (208 - 32)
+//#define RIGHT_VISIBLE_HC (1488 - 32)
+// Split the difference? (Seems to be OK for the most part...)
+
+// (-10 +10)*4 is for opening up the display by 16 pixels (may go to 20). Need to change VIRTUAL_SCREEN_WIDTH to match this as well (went from 320 to 340; this is 4 HCs per one of those pixels).
+//NB: Went back to 330. May shrink more. :-)
+//#define LEFT_VISIBLE_HC (208 - 16 - (8 * 4))
+//#define LEFT_VISIBLE_HC (208 - 16 - (3 * 4))
+#define LEFT_VISIBLE_HC (208 - 16 - (1 * 4))
+//#define RIGHT_VISIBLE_HC (1488 - 16 + (10 * 4))
+#define RIGHT_VISIBLE_HC (LEFT_VISIBLE_HC + (VIRTUAL_SCREEN_WIDTH * 4))
//#define TOP_VISIBLE_VC 25
//#define BOTTOM_VISIBLE_VC 503
#define TOP_VISIBLE_VC 31
//Are these PAL horizontals correct?
//They seem to be for the most part, but there are some games that seem to be
//shifted over to the right from this "window".
-#define LEFT_VISIBLE_HC_PAL 208
-#define RIGHT_VISIBLE_HC_PAL 1488
+//#define LEFT_VISIBLE_HC_PAL (208 - 16 - (4 * 4))
+//#define LEFT_VISIBLE_HC_PAL (208 - 16 - (-1 * 4))
+#define LEFT_VISIBLE_HC_PAL (208 - 16 - (-3 * 4))
+//#define RIGHT_VISIBLE_HC_PAL (1488 - 16 + (10 * 4))
+#define RIGHT_VISIBLE_HC_PAL (LEFT_VISIBLE_HC_PAL + (VIRTUAL_SCREEN_WIDTH * 4))
#define TOP_VISIBLE_VC_PAL 67
#define BOTTOM_VISIBLE_VC_PAL 579
uint32 CRY16ToRGB32[0x10000];
uint32 MIX16ToRGB32[0x10000];
+
#warning "This is not endian-safe. !!! FIX !!!"
void TOMFillLookupTables(void)
{
}
}
+
void TOMSetPendingJERRYInt(void)
{
tom_jerry_int_pending = 1;
}
+
void TOMSetPendingTimerInt(void)
{
tom_timer_int_pending = 1;
}
+
void TOMSetPendingObjectInt(void)
{
tom_object_int_pending = 1;
}
+
void TOMSetPendingGPUInt(void)
{
tom_gpu_int_pending = 1;
}
+
void TOMSetPendingVideoInt(void)
{
tom_video_int_pending = 1;
}
+
uint8 * TOMGetRamPointer(void)
{
return tomRam8;
}
+
uint8 TOMGetVideoMode(void)
{
uint16 vmode = GET16(tomRam8, VMODE);
return ((vmode & VARMOD) >> 6) | ((vmode & MODE) >> 1);
}
+
//Used in only one place (and for debug purposes): OBJECTP.CPP
#warning "Used in only one place (and for debug purposes): OBJECTP.CPP !!! FIX !!!"
uint16 TOMGetVDB(void)
return GET16(tomRam8, VDB);
}
+
+#define LEFT_BG_FIX
//
// 16 BPP CRY/RGB mixed mode rendering
//
//NOTE: May have to check HDB2 as well!
// Get start position in HC ticks
int16 startPos = GET16(tomRam8, HDB1) - (vjs.hardwareTypeNTSC ? LEFT_VISIBLE_HC : LEFT_VISIBLE_HC_PAL);
+ // Convert to pixels
startPos /= pwidth;
+
if (startPos < 0)
+ // This is x2 because current_line_buffer is uint8 & we're in a 16bpp mode
current_line_buffer += 2 * -startPos;
else
//This case doesn't properly handle the "start on the right side of virtual screen" case
//Dunno why--looks Ok...
-//What *is* for sure wrong is that it doesn't copy the linebuffer's BG pixels...
+//What *is* for sure wrong is that it doesn't copy the linebuffer's BG pixels... [FIXED NOW]
//This should likely be 4 instead of 2 (?--not sure)
+// Actually, there should be NO multiplier, as startPos is expressed in PIXELS
+// and so is the backbuffer.
+#ifdef LEFT_BG_FIX
+ {
+ uint8 g = tomRam8[BORD1], r = tomRam8[BORD1 + 1], b = tomRam8[BORD2 + 1];
+ uint32 pixel = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
+
+ for(int16 i=0; i<startPos; i++)
+ *backbuffer++ = pixel;
+
+ width -= startPos;
+ }
+#else
backbuffer += 2 * startPos, width -= startPos;
+#endif
while (width)
{
}
}
+
//
// 16 BPP CRY mode rendering
//
if (startPos < 0)
current_line_buffer += 2 * -startPos;
else
+#ifdef LEFT_BG_FIX
+ {
+ uint8 g = tomRam8[BORD1], r = tomRam8[BORD1 + 1], b = tomRam8[BORD2 + 1];
+ uint32 pixel = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
+
+ for(int16 i=0; i<startPos; i++)
+ *backbuffer++ = pixel;
+
+ width -= startPos;
+ }
+#else
//This should likely be 4 instead of 2 (?--not sure)
backbuffer += 2 * startPos, width -= startPos;
+#endif
while (width)
{
}
}
+
//
// 24 BPP mode rendering
//
if (startPos < 0)
current_line_buffer += 4 * -startPos;
else
+#ifdef LEFT_BG_FIX
+ {
+ uint8 g = tomRam8[BORD1], r = tomRam8[BORD1 + 1], b = tomRam8[BORD2 + 1];
+ uint32 pixel = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
+
+ for(int16 i=0; i<startPos; i++)
+ *backbuffer++ = pixel;
+
+ width -= startPos;
+ }
+#else
//This should likely be 4 instead of 2 (?--not sure)
backbuffer += 2 * startPos, width -= startPos;
+#endif
while (width)
{
}
}
+
//Seems to me that this is NOT a valid mode--the JTRM seems to imply that you would need
//extra hardware outside of the Jaguar console to support this!
//
}
}
+
//
// 16 BPP RGB mode rendering
//
if (startPos < 0)
current_line_buffer += 2 * -startPos;
else
+#ifdef LEFT_BG_FIX
+ {
+ uint8 g = tomRam8[BORD1], r = tomRam8[BORD1 + 1], b = tomRam8[BORD2 + 1];
+ uint32 pixel = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
+
+ for(int16 i=0; i<startPos; i++)
+ *backbuffer++ = pixel;
+
+ width -= startPos;
+ }
+#else
//This should likely be 4 instead of 2 (?--not sure)
backbuffer += 2 * startPos, width -= startPos;
+#endif
while (width)
{
}
-/*void TOMResetBackbuffer(uint32 * backbuffer)
-{
- TOMBackbuffer = backbuffer;
-}*/
-
//
// Process a single scanline
// (this is bad terminology; each tick of the VC is actually a half-line)
//
void TOMExecHalfline(uint16 halfline, bool render)
{
+#warning "!!! Need to handle multiple fields properly !!!"
+ // We ignore the problem for now
+ halfline &= 0x7FF;
+
bool inActiveDisplayArea = true;
//Interlacing is still not handled correctly here... !!! FIX !!!
- if (halfline & 0x01) // Execute OP only on even lines (non-interlaced only!)
+ if (halfline & 0x01) // Execute OP only on even halflines (non-interlaced only!)
return;
//Hm, it seems that the OP needs to execute from zero, so let's try it:
}
}
+
//
// TOM initialization
//
TOMReset();
}
+
void TOMDone(void)
{
OPDone();
// memory_free(tom_cry_rgb_mix_lut);
}
+
uint32 TOMGetVideoModeWidth(void)
{
//These widths are pretty bogus. Should use HDB1/2 & HDE/HBB & PWIDTH to calc the width...
// That's basically what we're doing now...!
}
+
// *** SPECULATION ***
// It might work better to virtualize the height settings, i.e., set the vertical
// height at 240 lines and clip using the VDB and VDE/VP registers...
return (vjs.hardwareTypeNTSC ? 240 : 256);
}
+
//
// TOM reset code
// Now PAL friendly!
//
+/*
+The values in TOMReset come from the Jaguar BIOS.
+These values are from BJL:
+
+NSTC:
+CLK2 181
+HP 844
+HBB 1713
+HBE 125
+HS 1741
+HVS 651
+HEQ 784
+HDE 1696
+HDB1 166
+HDB2 166
+VP 523
+VEE 6
+VBE 24
+VDB 46
+VDE 496
+VBB 500
+VEB 511
+VS 517
+
+PAL:
+CLK2 226
+HP 850
+HBB 1711
+HBE 158
+HS 1749
+HVS 601
+HEQ 787
+HDE 1696
+HDB1 166
+HDB2 166
+VP 625
+VEE 6
+VBE 34
+VDB 46
+VDE 429
+VBB 600
+VEB 613
+VS 618
+*/
void TOMReset(void)
{
OPReset();
tomTimerCounter = 0;
}
+
//
// TOM byte access (read)
//
return tomRam8[offset & 0x3FFF];
}
+
//
// TOM word access (read)
//
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]);
+ WriteLog("TOM: ReadWord attempted from GPU register file by %s (unimplemented)!\n", whoName[who]);
if (offset == 0xF000E0)
{
return (TOMReadByte(offset, who) << 8) | TOMReadByte(offset + 1, who);
}
+
#define TOM_STRICT_MEMORY_ACCESS
//
// TOM byte access (write)
tomRam8[offset & 0x3FFF] = data;
}
+
//
// TOM word access (write)
//
//if (offset == 0xF00000 + MEMCON2)
// WriteLog("TOM: Memory Configuration 2 written by %s: %04X\n", whoName[who], data);
if (offset >= 0xF02000 && offset <= 0xF020FF)
- WriteLog("TOM: Write attempted to GPU register file by %s (unimplemented)!\n", whoName[who]);
+ WriteLog("TOM: WriteWord attempted to GPU register file by %s (unimplemented)!\n", whoName[who]);
if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
{
#endif
}
+
int TOMIRQEnabled(int irq)
{
// This is the correct byte in big endian... D'oh!
return tomRam8[INT1 + 1/*0xE1*/] & (1 << irq);
}
+
// NEW:
// TOM Programmable Interrupt Timer handler
// NOTE: TOM's PIT is only enabled if the prescaler is != 0
void TOMPITCallback(void);
+
void TOMResetPIT(void)
{
#ifndef NEW_TIMER_SYSTEM
#endif
}
+
//
// TOM Programmable Interrupt Timer handler
// NOTE: TOM's PIT is only enabled if the prescaler is != 0
}
}
+
void TOMPITCallback(void)
{
// INT1_RREG |= 0x08; // Set TOM PIT interrupt pending
TOMResetPIT();
}
+