X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Ftom.cpp;h=c01ddecc032201b9b3d35ce0bc46c295269a1dce;hb=a71ef511af0a3680237ad91e7f80b2f77a10dcc4;hp=c949c728609c86116f1d4397b1f1cad565b9fab4;hpb=220217373079ff8d737f3d6dc07bbbad8f46e1ca;p=virtualjaguar diff --git a/src/tom.cpp b/src/tom.cpp index c949c72..c01ddec 100644 --- a/src/tom.cpp +++ b/src/tom.cpp @@ -250,6 +250,7 @@ #include "gpu.h" #include "objectp.h" #include "cry2rgb.h" +#include "settings.h" // TOM registers (offset from $F00000) @@ -262,6 +263,8 @@ #define BGEN 0x0080 // Background enable (CRY & RGB16 only) #define VARMOD 0x0100 // Mixed CRY/RGB16 mode (only works in MODE 0!) #define PWIDTH 0x0E00 // Pixel width in video clock cycles (value written + 1) +#define BORD1 0x2A // Border green/red values (8 BPP) +#define BORD2 0x2C // Border blue value (8 BPP) #define HP 0x2E // Values range from 1 - 1024 (value written + 1) #define HBB 0x30 #define HBE 0x32 @@ -278,17 +281,30 @@ #define BG 0x58 #define INT1 0xE0 +//NOTE: These arbitrary cutoffs are NOT taken into account for PAL jaguar screens. !!! FIX !!! + // Arbitrary video cutoff values (i.e., first/last visible spots on a TV, in HC ticks) -/*#define LEFT_VISIBLE_HC 208 -#define RIGHT_VISIBLE_HC 1528//*/ -#define LEFT_VISIBLE_HC 208 -#define RIGHT_VISIBLE_HC 1488 +/*#define LEFT_VISIBLE_HC 208 +#define RIGHT_VISIBLE_HC 1528//*/ +#define LEFT_VISIBLE_HC 208 +#define RIGHT_VISIBLE_HC 1488 +//#define TOP_VISIBLE_VC 25 +//#define BOTTOM_VISIBLE_VC 503 +#define TOP_VISIBLE_VC 31 +#define BOTTOM_VISIBLE_VC 511 + +//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 TOP_VISIBLE_VC_PAL 67 +#define BOTTOM_VISIBLE_VC_PAL 579 //This can be defined in the makefile as well... //(It's easier to do it here, though...) //#define TOM_DEBUG -extern uint32 jaguar_mainRom_crc32; extern uint8 objectp_running; static uint8 * tom_ram_8; @@ -301,6 +317,7 @@ static int32 tom_timer_counter; uint16 tom_jerry_int_pending, tom_timer_int_pending, tom_object_int_pending, tom_gpu_int_pending, tom_video_int_pending; uint16 * tom_cry_rgb_mix_lut; +int16 * TOMBackbuffer; static char * videoMode_to_str[8] = { "16 BPP CRY", "24 BPP RGB", "16 BPP DIRECT", "16 BPP RGB", @@ -349,7 +366,82 @@ render_xxx_scanline_fn * scanline_render_stretch[]= render_xxx_scanline_fn * scanline_render[8]; -// Screen info for various games... +// Screen info for various games [PAL]... +/* +BIOS +TOM: Horizontal Period written by M68K: 850 (+1*2 = 1702) +TOM: Horizontal Blank Begin written by M68K: 1711 +TOM: Horizontal Blank End written by M68K: 158 +TOM: Horizontal Display End written by M68K: 1696 +TOM: Horizontal Display Begin 1 written by M68K: 166 +TOM: Vertical Period written by M68K: 623 (non-interlaced) +TOM: Vertical Blank End written by M68K: 34 +TOM: Vertical Display Begin written by M68K: 46 +TOM: Vertical Display End written by M68K: 526 +TOM: Vertical Blank Begin written by M68K: 600 +TOM: Vertical Sync written by M68K: 618 +TOM: Horizontal Display End written by M68K: 1665 +TOM: Horizontal Display Begin 1 written by M68K: 203 +TOM: Vertical Display Begin written by M68K: 38 +TOM: Vertical Display End written by M68K: 518 +TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 151) +TOM: Horizontal Display End written by M68K: 1713 +TOM: Horizontal Display Begin 1 written by M68K: 157 +TOM: Vertical Display Begin written by M68K: 35 +TOM: Vertical Display End written by M68K: 2047 +Horizontal range: 157 - 1713 (width: 1557 / 4 = 389.25, / 5 = 315.4) + +Asteroid +TOM: Horizontal Period written by M68K: 845 (+1*2 = 1692) +TOM: Horizontal Blank Begin written by M68K: 1700 +TOM: Horizontal Blank End written by M68K: 122 +TOM: Horizontal Display End written by M68K: 1600 +TOM: Horizontal Display Begin 1 written by M68K: 268 +TOM: Vertical Period written by M68K: 523 (non-interlaced) +TOM: Vertical Blank End written by M68K: 40 +TOM: Vertical Display Begin written by M68K: 44 +TOM: Vertical Display End written by M68K: 492 +TOM: Vertical Blank Begin written by M68K: 532 +TOM: Vertical Sync written by M68K: 513 +TOM: Video Mode written by M68K: 04C7. PWIDTH = 3, MODE = 16 BPP RGB, flags: BGEN (VC = 461) + +Rayman +TOM: Horizontal Display End written by M68K: 1713 +TOM: Horizontal Display Begin 1 written by M68K: 157 +TOM: Vertical Display Begin written by M68K: 35 +TOM: Vertical Display End written by M68K: 2047 +TOM: Video Mode written by M68K: 06C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN (VC = 89) +TOM: Horizontal Display Begin 1 written by M68K: 208 +TOM: Horizontal Display End written by M68K: 1662 +TOM: Vertical Display Begin written by M68K: 100 +TOM: Vertical Display End written by M68K: 2047 +TOM: Video Mode written by M68K: 07C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN VARMOD (VC = 205) +Horizontal range: 208 - 1662 (width: 1455 / 4 = 363.5) + +Alien vs Predator +TOM: Vertical Display Begin written by M68K: 96 +TOM: Vertical Display End written by M68K: 2047 +TOM: Horizontal Display Begin 1 written by M68K: 239 +TOM: Horizontal Display End written by M68K: 1692 +TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 378) +TOM: Vertical Display Begin written by M68K: 44 +TOM: Vertical Display End written by M68K: 2047 +TOM: Horizontal Display Begin 1 written by M68K: 239 +TOM: Horizontal Display End written by M68K: 1692 +TOM: Video Mode written by M68K: 06C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN (VC = 559) +TOM: Vertical Display Begin written by M68K: 84 +TOM: Vertical Display End written by M68K: 2047 +TOM: Horizontal Display Begin 1 written by M68K: 239 +TOM: Horizontal Display End written by M68K: 1692 +TOM: Vertical Display Begin written by M68K: 44 +TOM: Vertical Display End written by M68K: 2047 +TOM: Horizontal Display Begin 1 written by M68K: 239 +TOM: Horizontal Display End written by M68K: 1692 +Horizontal range: 239 - 1692 (width: 1454 / 4 = 363.5) + +*/ + +// Screen info for various games [NTSC]... /* Doom TOM: Horizontal Display End written by M68K: 1727 @@ -447,8 +539,6 @@ Vertical resolution: 238 lines void tom_calc_cry_rgb_mix_lut(void) { - memory_malloc_secure((void **)&tom_cry_rgb_mix_lut, 2 * 0x10000, "CRY/RGB mixed mode LUT"); - for (uint32 i=0; i<0x10000; i++) { uint16 color = i; @@ -468,6 +558,7 @@ void tom_calc_cry_rgb_mix_lut(void) blue = (((uint32)bluecv[chrm][chrl]) * y) >> 11; color = (red << 10) | (green << 5) | blue; } + tom_cry_rgb_mix_lut[i] = color; } } @@ -527,11 +618,15 @@ void tom_render_16bpp_cry_rgb_mix_scanline(int16 * backbuffer) //New stuff--restrict our drawing... uint8 pwidth = ((GET16(tom_ram_8, VMODE) & PWIDTH) >> 9) + 1; //NOTE: May have to check HDB2 as well! - int16 startPos = GET16(tom_ram_8, HDB1) - LEFT_VISIBLE_HC; // Get start position in HC ticks + // Get start position in HC ticks + int16 startPos = GET16(tom_ram_8, HDB1) - (vjs.hardwareTypeNTSC ? LEFT_VISIBLE_HC : LEFT_VISIBLE_HC_PAL); startPos /= pwidth; if (startPos < 0) 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... backbuffer += 2 * startPos, width -= startPos; while (width) @@ -554,7 +649,7 @@ void tom_render_16bpp_cry_scanline(int16 * backbuffer) //New stuff--restrict our drawing... uint8 pwidth = ((GET16(tom_ram_8, VMODE) & PWIDTH) >> 9) + 1; //NOTE: May have to check HDB2 as well! - int16 startPos = GET16(tom_ram_8, HDB1) - LEFT_VISIBLE_HC; // Get start position in HC ticks + int16 startPos = GET16(tom_ram_8, HDB1) - (vjs.hardwareTypeNTSC ? LEFT_VISIBLE_HC : LEFT_VISIBLE_HC_PAL);// Get start position in HC ticks startPos /= pwidth; if (startPos < 0) current_line_buffer += 2 * -startPos; @@ -590,7 +685,7 @@ void tom_render_24bpp_scanline(int16 * backbuffer) //New stuff--restrict our drawing... uint8 pwidth = ((GET16(tom_ram_8, VMODE) & PWIDTH) >> 9) + 1; //NOTE: May have to check HDB2 as well! - int16 startPos = GET16(tom_ram_8, HDB1) - LEFT_VISIBLE_HC; // Get start position in HC ticks + int16 startPos = GET16(tom_ram_8, HDB1) - (vjs.hardwareTypeNTSC ? LEFT_VISIBLE_HC : LEFT_VISIBLE_HC_PAL); // Get start position in HC ticks startPos /= pwidth; if (startPos < 0) current_line_buffer += 4 * -startPos; @@ -640,7 +735,7 @@ void tom_render_16bpp_rgb_scanline(int16 * backbuffer) //New stuff--restrict our drawing... uint8 pwidth = ((GET16(tom_ram_8, VMODE) & PWIDTH) >> 9) + 1; //NOTE: May have to check HDB2 as well! - int16 startPos = GET16(tom_ram_8, HDB1) - LEFT_VISIBLE_HC; // Get start position in HC ticks + int16 startPos = GET16(tom_ram_8, HDB1) - (vjs.hardwareTypeNTSC ? LEFT_VISIBLE_HC : LEFT_VISIBLE_HC_PAL); // Get start position in HC ticks startPos /= pwidth; if (startPos < 0) current_line_buffer += 2 * -startPos; @@ -783,23 +878,60 @@ void tom_render_16bpp_rgb_stretch_scanline(int16 *backbuffer) } } +void TOMResetBackbuffer(int16 * backbuffer) +{ + TOMBackbuffer = backbuffer; +} + // // Process a single scanline // -void tom_exec_scanline(int16 * backbuffer, int32 scanline, bool render) +void TOMExecScanline(uint16 scanline, bool render) { - if (render) + bool inActiveDisplayArea = true; + +//Interlacing is still not handled correctly here... !!! FIX !!! + if (scanline & 0x01) // Execute OP only on even lines (non-interlaced only!) + return; + + if (scanline >= (uint16)GET16(tom_ram_8, VDB) && scanline < (uint16)GET16(tom_ram_8, VDE)) + { + if (render) + { + uint8 * current_line_buffer = (uint8 *)&tom_ram_8[0x1800]; + uint8 bgHI = tom_ram_8[BG], bgLO = tom_ram_8[BG + 1]; + + // Clear line buffer with BG + if (GET16(tom_ram_8, VMODE) & BGEN) // && (CRY or RGB16)... + for(uint32 i=0; i<720; i++) + *current_line_buffer++ = bgHI, *current_line_buffer++ = bgLO; + + OPProcessList(scanline, render); + } + } + else + inActiveDisplayArea = false; + +//Try to take PAL into account... +uint16 topVisible = (vjs.hardwareTypeNTSC ? TOP_VISIBLE_VC : TOP_VISIBLE_VC_PAL), + bottomVisible = (vjs.hardwareTypeNTSC ? BOTTOM_VISIBLE_VC : BOTTOM_VISIBLE_VC_PAL); + // Here's our virtualized scanline code... + if (scanline >= topVisible && scanline < bottomVisible) { - uint8 * current_line_buffer = (uint8 *)&tom_ram_8[0x1800]; - uint8 bgHI = tom_ram_8[BG], bgLO = tom_ram_8[BG + 1]; + if (inActiveDisplayArea) + scanline_render[tom_getVideoMode()](TOMBackbuffer); + else + { + // If outside of VDB & VDE, then display the border color + int16 * currentLineBuffer = TOMBackbuffer; + uint8 g = tom_ram_8[BORD1], r = tom_ram_8[BORD1 + 1], b = tom_ram_8[BORD2 + 1]; + uint16 pixel = ((r & 0xF8) << 7) | ((g & 0xF8) << 2) | (b >> 3); - // Clear line buffer with BG - if (GET16(tom_ram_8, VMODE) & BGEN) // && (CRY or RGB16)... - for(uint32 i=0; i<720; i++) - *current_line_buffer++ = bgHI, *current_line_buffer++ = bgLO; + for(uint32 i=0; i> 9) + 1; -// return (RIGHT_VISIBLE_HC - LEFT_VISIBLE_HC) / pwidth; + return (vjs.hardwareTypeNTSC ? RIGHT_VISIBLE_HC - LEFT_VISIBLE_HC : RIGHT_VISIBLE_HC_PAL - LEFT_VISIBLE_HC_PAL) / pwidth; //Temporary, for testing Doom... - return (RIGHT_VISIBLE_HC - LEFT_VISIBLE_HC) / (pwidth == 8 ? 4 : pwidth); +// return (RIGHT_VISIBLE_HC - LEFT_VISIBLE_HC) / (pwidth == 8 ? 4 : pwidth); +//// return (RIGHT_VISIBLE_HC - LEFT_VISIBLE_HC) / (pwidth == 4 ? 8 : pwidth); // More speculating... // According to the JTRM, the number of potential pixels across is given by the @@ -900,11 +1036,12 @@ uint32 tom_getVideoModeWidth(void) // height at 240 lines and clip using the VDB and VDE/VP registers... // Same with the width... [Width is pretty much virtualized now.] +// Now that that the width is virtualized, let's virtualize the height. :-) uint32 tom_getVideoModeHeight(void) { // uint16 vmode = GET16(tom_ram_8, VMODE); - uint16 vbe = GET16(tom_ram_8, VBE); - uint16 vbb = GET16(tom_ram_8, VBB); +// uint16 vbe = GET16(tom_ram_8, VBE); +// uint16 vbb = GET16(tom_ram_8, VBB); // uint16 vdb = GET16(tom_ram_8, VDB); // uint16 vde = GET16(tom_ram_8, VDE); // uint16 vp = GET16(tom_ram_8, VP); @@ -921,7 +1058,12 @@ uint32 tom_getVideoModeHeight(void) // return ((vde > vbb ? vbb : vde) - vdb) >> 1; //Let's try from the Vertical Blank interval... //Seems to work OK! - return (vbb - vbe) >> 1; // Again, doesn't take interlacing into account... +// return (vbb - vbe) >> 1; // Again, doesn't take interlacing into account... +// This of course doesn't take interlacing into account. But I haven't seen any +// Jaguar software that takes advantage of it either... +//Also, doesn't reflect PAL Jaguar either... !!! FIX !!! [DONE] +// return 240; // Set virtual screen height to 240 lines... + return (vjs.hardwareTypeNTSC ? 240 : 256); } // @@ -930,15 +1072,13 @@ uint32 tom_getVideoModeHeight(void) // void tom_reset(void) { - extern bool hardwareTypeNTSC; - op_reset(); blitter_reset(); //This should be done by JERRY! pcm_reset(); memset(tom_ram_8, 0x00, 0x4000); - if (hardwareTypeNTSC) + if (vjs.hardwareTypeNTSC) { SET16(tom_ram_8, MEMCON1, 0x1861); SET16(tom_ram_8, MEMCON2, 0x35CC); @@ -975,10 +1115,6 @@ void tom_reset(void) tom_width = tom_real_internal_width = 0; tom_height = 0; -// tom_scanline = 0; - -//This is WRONG -// hblankWidthInPixels = GET16(tom_ram_8, HDB1) >> 1; tom_jerry_int_pending = 0; tom_timer_int_pending = 0; @@ -986,7 +1122,7 @@ void tom_reset(void) tom_gpu_int_pending = 0; tom_video_int_pending = 0; - tom_timer_prescaler = 0; + tom_timer_prescaler = 0; // TOM PIT is disabled tom_timer_divider = 0; tom_timer_counter = 0; memcpy(scanline_render, scanline_render_normal, sizeof(scanline_render)); @@ -1109,25 +1245,25 @@ void TOMWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/) else if (offset == 0xF00050) { tom_timer_prescaler = (tom_timer_prescaler & 0x00FF) | (data << 8); - tom_reset_timer(); + TOMResetPIT(); return; } else if (offset == 0xF00051) { tom_timer_prescaler = (tom_timer_prescaler & 0xFF00) | data; - tom_reset_timer(); + TOMResetPIT(); return; } else if (offset == 0xF00052) { tom_timer_divider = (tom_timer_divider & 0x00FF) | (data << 8); - tom_reset_timer(); + TOMResetPIT(); return; } else if (offset == 0xF00053) { tom_timer_divider = (tom_timer_divider & 0xFF00) | data; - tom_reset_timer(); + TOMResetPIT(); return; } else if (offset >= 0xF00400 && offset <= 0xF007FF) // CLUT (A & B) @@ -1182,13 +1318,13 @@ if (offset >= 0xF02000 && offset <= 0xF020FF) else if (offset == 0xF00050) { tom_timer_prescaler = data; - tom_reset_timer(); + TOMResetPIT(); return; } else if (offset == 0xF00052) { tom_timer_divider = data; - tom_reset_timer(); + TOMResetPIT(); return; } else if (offset == 0xF000E0) @@ -1267,31 +1403,8 @@ if (offset == VMODE) if ((width != tom_width) || (height != tom_height)) { -// extern SDL_Surface * surface, * mainSurface; -// extern Uint32 mainSurfaceFlags; -// static char window_title[256]; - tom_width = width, tom_height = height; ResizeScreen(tom_width, tom_height); -/* SDL_FreeSurface(surface); - surface = SDL_CreateRGBSurface(SDL_SWSURFACE, tom_width, tom_height, - 16, 0x7C00, 0x03E0, 0x001F, 0); - if (surface == NULL) - { - WriteLog("TOM: Could not create primary SDL surface: %s", SDL_GetError()); - exit(1); - } - - sprintf(window_title, "Virtual Jaguar (%i x %i)", (int)tom_width, (int)tom_height); - mainSurface = SDL_SetVideoMode(tom_width, tom_height, 16, mainSurfaceFlags); - - if (mainSurface == NULL) - { - WriteLog("Joystick: SDL is unable to set the video mode: %s\n", SDL_GetError()); - exit(1); - } - - SDL_WM_SetCaption(window_title, window_title);//*/ } } } @@ -1315,34 +1428,35 @@ int tom_irq_enabled(int irq) return (tom_ram_8[0xE0] << 8) | tom_ram_8[0xE1]; }*/ -void tom_reset_timer(void) +void TOMResetPIT(void) { - if (!tom_timer_prescaler || !tom_timer_divider) - tom_timer_counter = 0; - else -//Probably should *add* this amount to the counter to retain cycle accuracy! !!! FIX !!! -//Also, why +1??? - tom_timer_counter = (1 + tom_timer_prescaler) * (1 + tom_timer_divider); +//Probably should *add* this amount to the counter to retain cycle accuracy! !!! FIX !!! [DONE] +//Also, why +1??? 'Cause that's what it says in the JTRM...! +//There is a small problem with this approach: If both the prescaler and the divider are equal +//to $FFFF then the counter won't be large enough to handle it. !!! FIX !!! + if (tom_timer_prescaler) + tom_timer_counter += (1 + tom_timer_prescaler) * (1 + tom_timer_divider); // WriteLog("tom: reseting timer to 0x%.8x (%i)\n",tom_timer_counter,tom_timer_counter); } // // TOM Programmable Interrupt Timer handler +// NOTE: TOM's PIT is only enabled if the prescaler is != 0 // -void tom_pit_exec(uint32 cycles) +void TOMExecPIT(uint32 cycles) { - if (tom_timer_counter > 0) + if (tom_timer_prescaler) { tom_timer_counter -= cycles; if (tom_timer_counter <= 0) { tom_set_pending_timer_int(); - GPUSetIRQLine(GPUIRQ_TIMER, ASSERT_LINE); - if (tom_irq_enabled(IRQ_TIMER) && jaguar_interrupt_handler_is_valid(64)) - m68k_set_irq(7); // Cause a 68000 NMI... + GPUSetIRQLine(GPUIRQ_TIMER, ASSERT_LINE); // GPUSetIRQLine does the 'IRQ enabled' checking + if (tom_irq_enabled(IRQ_TIMER))//get rid of this crap -> && jaguar_interrupt_handler_is_valid(64)) + m68k_set_irq(7); // Cause a 68000 NMI... - tom_reset_timer(); + TOMResetPIT(); } } }