X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Ftom.cpp;h=27f0a45387abdf58f0618c15cde9f37688f3c621;hb=3e5606b067152768044d035863be184d721897e1;hp=f634284a8dad4f99f59b1f910ce469a28aa4a1bf;hpb=a44520039d2164202dd5fbde323cfb0b36fafada;p=virtualjaguar diff --git a/src/tom.cpp b/src/tom.cpp index f634284..27f0a45 100644 --- a/src/tom.cpp +++ b/src/tom.cpp @@ -244,11 +244,13 @@ // F02298 W xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx B_Z0 - Z0 // ------------------------------------------------------------ -#include +//#include #include "tom.h" +#include "video.h" #include "gpu.h" #include "objectp.h" #include "cry2rgb.h" +#include "settings.h" // TOM registers (offset from $F00000) @@ -261,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 @@ -277,6 +281,18 @@ #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 TOP_VISIBLE_VC 25 +//#define BOTTOM_VISIBLE_VC 503 +#define TOP_VISIBLE_VC 31 +#define BOTTOM_VISIBLE_VC 511 + //This can be defined in the makefile as well... //(It's easier to do it here, though...) //#define TOM_DEBUG @@ -294,6 +310,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", @@ -342,6 +359,102 @@ render_xxx_scanline_fn * scanline_render_stretch[]= render_xxx_scanline_fn * scanline_render[8]; +// Screen info for various games [NTSC]... +/* +Doom +TOM: Horizontal Display End written by M68K: 1727 +TOM: Horizontal Display Begin 1 written by M68K: 123 +TOM: Vertical Display Begin written by M68K: 25 +TOM: Vertical Display End written by M68K: 2047 +TOM: Video Mode written by M68K: 0EC1. PWIDTH = 8, MODE = 16 BPP CRY, flags: BGEN (VC = 5) +Also does PWIDTH = 4... +Vertical resolution: 238 lines + +Rayman +TOM: Horizontal Display End written by M68K: 1727 +TOM: Horizontal Display Begin 1 written by M68K: 123 +TOM: Vertical Display Begin written by M68K: 25 +TOM: Vertical Display End written by M68K: 2047 +TOM: Vertical Interrupt written by M68K: 507 +TOM: Video Mode written by M68K: 06C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN (VC = 92) +TOM: Horizontal Display Begin 1 written by M68K: 208 +TOM: Horizontal Display End written by M68K: 1670 +Display starts at 31, then 52! +Vertical resolution: 238 lines + +Atari Karts +TOM: Horizontal Display End written by M68K: 1727 +TOM: Horizontal Display Begin 1 written by M68K: 123 +TOM: Vertical Display Begin written by M68K: 25 +TOM: Vertical Display End written by M68K: 2047 +TOM: Video Mode written by GPU: 08C7. PWIDTH = 5, MODE = 16 BPP RGB, flags: BGEN (VC = 4) +TOM: Video Mode written by GPU: 06C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN (VC = 508) +Display starts at 31 (PWIDTH = 4), 24 (PWIDTH = 5) + +Iron Soldier +TOM: Vertical Interrupt written by M68K: 2047 +TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 0) +TOM: Horizontal Display End written by M68K: 1727 +TOM: Horizontal Display Begin 1 written by M68K: 123 +TOM: Vertical Display Begin written by M68K: 25 +TOM: Vertical Display End written by M68K: 2047 +TOM: Vertical Interrupt written by M68K: 507 +TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 369) +TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 510) +TOM: Video Mode written by M68K: 06C3. PWIDTH = 4, MODE = 24 BPP RGB, flags: BGEN (VC = 510) +Display starts at 31 +Vertical resolution: 238 lines +[Seems to be a problem between the horizontal positioning of the 16-bit CRY & 24-bit RGB] + +JagMania +TOM: Horizontal Period written by M68K: 844 (+1*2 = 1690) +TOM: Horizontal Blank Begin written by M68K: 1713 +TOM: Horizontal Blank End written by M68K: 125 +TOM: Horizontal Display End written by M68K: 1696 +TOM: Horizontal Display Begin 1 written by M68K: 166 +TOM: Vertical Period written by M68K: 523 (non-interlaced) +TOM: Vertical Blank End written by M68K: 24 +TOM: Vertical Display Begin written by M68K: 46 +TOM: Vertical Display End written by M68K: 496 +TOM: Vertical Blank Begin written by M68K: 500 +TOM: Vertical Sync written by M68K: 517 +TOM: Vertical Interrupt written by M68K: 497 +TOM: Video Mode written by M68K: 04C1. PWIDTH = 3, MODE = 16 BPP CRY, flags: BGEN (VC = 270) +Display starts at 55 + +Double Dragon V +TOM: Horizontal Display End written by M68K: 1727 +TOM: Horizontal Display Begin 1 written by M68K: 123 +TOM: Vertical Display Begin written by M68K: 25 +TOM: Vertical Display End written by M68K: 2047 +TOM: Vertical Interrupt written by M68K: 507 +TOM: Video Mode written by M68K: 06C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN (VC = 9) + +Dino Dudes +TOM: Horizontal Display End written by M68K: 1823 +TOM: Horizontal Display Begin 1 written by M68K: 45 +TOM: Vertical Display Begin written by M68K: 40 +TOM: Vertical Display End written by M68K: 2047 +TOM: Vertical Interrupt written by M68K: 491 +TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 398) +Display starts at 11 (123 - 45 = 78, 78 / 4 = 19 pixels to skip) +Width is 417, so maybe width of 379 would be good (starting at 123, ending at 1639) +Vertical resolution: 238 lines + +Flashback +TOM: Horizontal Display End written by M68K: 1727 +TOM: Horizontal Display Begin 1 written by M68K: 188 +TOM: Vertical Display Begin written by M68K: 1 +TOM: Vertical Display End written by M68K: 2047 +TOM: Vertical Interrupt written by M68K: 483 +TOM: Video Mode written by M68K: 08C7. PWIDTH = 5, MODE = 16 BPP RGB, flags: BGEN (VC = 99) +Width would be 303 with above scheme, but border width would be 13 pixels + +Trevor McFur +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"); @@ -421,6 +534,16 @@ void tom_render_16bpp_cry_rgb_mix_scanline(int16 * backbuffer) uint16 width = tom_width; uint8 * current_line_buffer = (uint8 *)&tom_ram_8[0x1800]; + //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 + startPos /= pwidth; + if (startPos < 0) + current_line_buffer += 2 * -startPos; + else + backbuffer += 2 * startPos, width -= startPos; + while (width) { uint16 color = (*current_line_buffer++) << 8; @@ -438,6 +561,16 @@ void tom_render_16bpp_cry_scanline(int16 * backbuffer) uint16 width = tom_width; uint8 * current_line_buffer = (uint8 *)&tom_ram_8[0x1800]; + //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 + startPos /= pwidth; + if (startPos < 0) + current_line_buffer += 2 * -startPos; + else + backbuffer += 2 * startPos, width -= startPos; + while (width) { uint16 color = (*current_line_buffer++) << 8; @@ -464,8 +597,20 @@ void tom_render_24bpp_scanline(int16 * backbuffer) uint16 width = tom_width; uint8 * current_line_buffer = (uint8 *)&tom_ram_8[0x1800]; + //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 + startPos /= pwidth; + if (startPos < 0) + current_line_buffer += 4 * -startPos; + else + backbuffer += 2 * startPos, width -= startPos; + while (width) { + // This is NOT a good 8 -> 5 bit RGB conversion! (It saturates values below 8 + // to zero and throws away almost *half* the color resolution!) uint16 green = (*current_line_buffer++) >> 3; uint16 red = (*current_line_buffer++) >> 3; current_line_buffer++; @@ -502,6 +647,16 @@ void tom_render_16bpp_rgb_scanline(int16 * backbuffer) uint16 width = tom_width; uint8 * current_line_buffer = (uint8 *)&tom_ram_8[0x1800]; + //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 + startPos /= pwidth; + if (startPos < 0) + current_line_buffer += 2 * -startPos; + else + backbuffer += 2 * startPos, width -= startPos; + while (width) { uint16 color = (*current_line_buffer++) << 8; @@ -638,31 +793,58 @@ 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)) { - uint8 * current_line_buffer = (uint8 *)&tom_ram_8[0x1800]; - uint8 bgHI = tom_ram_8[BG], bgLO = tom_ram_8[BG + 1]; + 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; + // 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); - scanline_render[tom_getVideoMode()](backbuffer); + OPProcessList(scanline, render); + } } -} + else + inActiveDisplayArea = false; -uint32 TOMGetSDLScreenPitch(void) -{ - extern SDL_Surface * surface; + // Here's our virtualized scanline code... + if (scanline >= TOP_VISIBLE_VC && scanline < BOTTOM_VISIBLE_VC) + { + 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); + + for(uint32 i=0; ipitch; + TOMBackbuffer += GetSDLScreenPitch() / 2; // Returns bytes, but we need words + } } // @@ -726,11 +908,19 @@ uint32 tom_getVideoModeWidth(void) // return width[(GET16(tom_ram_8, VMODE) & PWIDTH) >> 9]; // Now, we just calculate it... - uint16 hdb1 = GET16(tom_ram_8, HDB1), hde = GET16(tom_ram_8, HDE), +/* uint16 hdb1 = GET16(tom_ram_8, HDB1), hde = GET16(tom_ram_8, HDE), hbb = GET16(tom_ram_8, HBB), pwidth = ((GET16(tom_ram_8, VMODE) & PWIDTH) >> 9) + 1; // return ((hbb < hde ? hbb : hde) - hdb1) / pwidth; //Temporary, for testing Doom... - return ((hbb < hde ? hbb : hde) - hdb1) / (pwidth = 8 ? 4 : pwidth); + return ((hbb < hde ? hbb : hde) - hdb1) / (pwidth == 8 ? 4 : pwidth);*/ + + // To make it easier to make a quasi-fixed display size, we restrict the viewing + // area to an arbitrary range of the Horizontal Count. + uint16 pwidth = ((GET16(tom_ram_8, VMODE) & PWIDTH) >> 9) + 1; + return (RIGHT_VISIBLE_HC - LEFT_VISIBLE_HC) / pwidth; +//Temporary, for testing Doom... +// 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 @@ -746,18 +936,21 @@ uint32 tom_getVideoModeWidth(void) // which to measure HBB & HDB1/2 against when rendering LBUF (i.e., if HDB1 is 20 ticks // to the right of the ALDL and PWIDTH is 4, then start writing the LBUF starting at // backbuffer + 5 pixels). + +// 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... -// Same with the width... +// 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); @@ -774,7 +967,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); } // @@ -783,15 +981,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); @@ -828,10 +1024,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; @@ -962,25 +1154,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) @@ -1035,13 +1227,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) @@ -1109,55 +1301,19 @@ if (offset == HBE) WriteLog("TOM: Horizontal Blank End written by %s: %u\n", whoName[who], data); if (offset == VMODE) WriteLog("TOM: Video Mode written by %s: %04X. PWIDTH = %u, MODE = %s, flags:%s%s (VC = %u)\n", whoName[who], data, ((data >> 9) & 0x07) + 1, videoMode_to_str[(data & MODE) >> 1], (data & BGEN ? " BGEN" : ""), (data & VARMOD ? " VARMOD" : ""), GET16(tom_ram_8, VC)); -/*#define MODE 0x0006 // Line buffer to video generator mode -#define BGEN 0x0080 // Background enable (CRY & RGB16 only) -#define VARMOD 0x0100 // Mixed CRY/RGB16 mode -#define PWIDTH 0x0E00 // Pixel width in video clock cycles (value written + 1)*/ // detect screen resolution changes //This may go away in the future, if we do the virtualized screen thing... +//This may go away soon! if ((offset >= 0x28) && (offset <= 0x4F)) { uint32 width = tom_getVideoModeWidth(), height = tom_getVideoModeHeight(); tom_real_internal_width = width; -//This looks like an attempt to render non-square pixels (though wrong...) -/* if (width == 640) - { - memcpy(scanline_render, scanline_render_stretch, sizeof(scanline_render)); - width = 320; - } - else - memcpy(scanline_render, scanline_render_normal, sizeof(scanline_render));//*/ - 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; - 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); -//???Should we do this??? No! -// SDL_FreeSurface(mainSurface); - 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); + ResizeScreen(tom_width, tom_height); } } } @@ -1181,7 +1337,7 @@ 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; @@ -1195,7 +1351,7 @@ void tom_reset_timer(void) // // TOM Programmable Interrupt Timer handler // -void tom_pit_exec(uint32 cycles) +void TOMExecPIT(uint32 cycles) { if (tom_timer_counter > 0) { @@ -1208,7 +1364,7 @@ void tom_pit_exec(uint32 cycles) if (tom_irq_enabled(IRQ_TIMER) && jaguar_interrupt_handler_is_valid(64)) m68k_set_irq(7); // Cause a 68000 NMI... - tom_reset_timer(); + TOMResetPIT(); } } }