// GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
// Cleanups/fixes by James L. Hammons
//
+bool specialLog = false;
-//#define GEN_CODE
-//#define LOG_BLITS
-// Generic blitter it is, until all blitter bugs are squashed!
-#define USE_GENERIC_BLITTER
-
#include "jaguar.h"
#include "blitter2.h" // Testing purposes only!
-#define null 0
-extern int jaguar_active_memory_dumps;
-
#define REG(A) (((uint32)blitter_ram[(A)] << 24) | ((uint32)blitter_ram[(A)+1] << 16) \
| ((uint32)blitter_ram[(A)+2] << 8) | (uint32)blitter_ram[(A)+3])
#define WREG(A,D) (blitter_ram[(A)] = ((D)>>24)&0xFF, blitter_ram[(A)+1] = ((D)>>16)&0xFF, \
blitter_ram[(A)+2] = ((D)>>8)&0xFF, blitter_ram[(A)+3] = (D)&0xFF)
-int start_logging = 0;
-
-// Blitter register RAM (most of it is hidden from the user)
-
-static uint8 blitter_ram[0x100];
-
// Blitter registers (offsets from F02200)
#define A1_BASE ((UINT32)0x00)
#define XADD0 2
#define XADDINC 3
-#define XSIGNSUB_A1 (REG(A1_FLAGS)&0x80000)
-#define XSIGNSUB_A2 (REG(A2_FLAGS)&0x80000)
+#define XSIGNSUB_A1 (REG(A1_FLAGS)&0x080000)
+#define XSIGNSUB_A2 (REG(A2_FLAGS)&0x080000)
#define YSIGNSUB_A1 (REG(A1_FLAGS)&0x100000)
#define YSIGNSUB_A2 (REG(A2_FLAGS)&0x100000)
-#define YADD1_A1 (REG(A1_FLAGS)&0x40000)
-#define YADD1_A2 (REG(A2_FLAGS)&0x40000)
+#define YADD1_A1 (REG(A1_FLAGS)&0x040000)
+#define YADD1_A2 (REG(A2_FLAGS)&0x040000)
// 1 bpp pixel read
#define PIXEL_SHIFT_1(a) (((~a##_x) >> 16) & 7)
// 16 bpp z data write
#define WRITE_ZDATA_16(a,d) { jaguar_word_write(a##_addr+(ZDATA_OFFSET_16(a)<<1),d); }
-//#define WRITE_ZDATA_16(a,d) { jaguar_word_write(a##_addr+(ZDATA_OFFSET_16(a)<<1),d); \
- WriteLog("16bpp z write --> "); }
+//#define WRITE_ZDATA_16(a,d) { jaguar_word_write(a##_addr+(ZDATA_OFFSET_16(a)<<1),d); WriteLog("16bpp z write --> "); }
// z data write
#define WRITE_ZDATA(a,f,d) WRITE_ZDATA_16(a,d);
#define WRITE_PIXEL_8(a,d) { jaguar_byte_write(a##_addr+PIXEL_OFFSET_8(a),d); }
// 16 bpp pixel write
-#define WRITE_PIXEL_16(a,d) { jaguar_word_write(a##_addr+(PIXEL_OFFSET_16(a)<<1),d); }
-//#define WRITE_PIXEL_16(a,d) { jaguar_word_write(a##_addr+(PIXEL_OFFSET_16(a)<<1),d); \
- WriteLog("16bpp pixel write --> "); }
+//#define WRITE_PIXEL_16(a,d) { jaguar_word_write(a##_addr+(PIXEL_OFFSET_16(a)<<1),d); }
+#define WRITE_PIXEL_16(a,d) { jaguar_word_write(a##_addr+(PIXEL_OFFSET_16(a)<<1),d); if (specialLog) WriteLog("Pixel write address: %08X\n", a##_addr+(PIXEL_OFFSET_16(a)<<1)); }
-//This is where the bad YPOS values are being written... How to fix???
// 32 bpp pixel write
#define WRITE_PIXEL_32(a,d) { jaguar_long_write(a##_addr+(PIXEL_OFFSET_32(a)<<2),d); }
-//#define WRITE_PIXEL_32(a,d) { jaguar_long_write(a##_addr+(PIXEL_OFFSET_32(a)<<2),d); \
- WriteLog("32bpp pixel write --> "); }
+//#define WRITE_PIXEL_32(a,d) { jaguar_long_write(a##_addr+(PIXEL_OFFSET_32(a)<<2),d); WriteLog("32bpp pixel write --> "); }
// pixel write
#define WRITE_PIXEL(a,f,d) {\
case 5: WRITE_PIXEL_32(a,d); break; \
}}
+// External global variables
+
+extern int jaguar_active_memory_dumps;
+
+// Local global variables
+
+int start_logging = 0;
+uint8 blitter_working = 0;
+
+// Blitter register RAM (most of it is hidden from the user)
+
+static uint8 blitter_ram[0x100];
+
// Width in Pixels of a Scanline
// This is a pretranslation of the value found in the A1 & A2 flags: It's really a floating point value
// of the form EEEEMM where MM is the mantissa with an implied "1." in front of it and the EEEE value is
//static uint16 gint[4];
//static uint16 gfrac[4];
//static uint8 gcolour[4];
-static int gd_i[4];
-static int gd_c[4];
-static int gd_ia, gd_ca;
-static int colour_index = 0;
-static int32 zadd;
-static uint32 z_i[4];
-
-static uint32 a1_clip_x, a1_clip_y;
-
-static uint8 blitter_code_cache[4096];
-static uint8 * blitter_ptr;
-uint8 blitter_working = 0;
-
-typedef void (blitter_fn)(void);
-
-typedef struct s_blitter_cache
-{
- uint32 hashcode;
- uint8 * code;
- uint32 ready;
- uint8 used;
- struct s_blitter_cache * next;
- struct s_blitter_cache * prev;
-} s_blitter_code_cache;
-
-s_blitter_cache * blitter_cache[256];
-
-uint8 blitter_cache_init = 0;
-static uint8 BPP_LUT[8] = { 1, 2, 4, 8, 16, 32, 0, 0 };
-
-FILE * blitters_code_fp;
-FILE * blitters_code_init_fp;
-
-//////////////////////////////////////////////////////////////////////////////
-// build C code for the specified blitter
-//////////////////////////////////////////////////////////////////////////////
-//
-//
-//
-//////////////////////////////////////////////////////////////////////////////
-void blitter_gen_c_code(FILE *fp, uint32 cmd,uint32 hashcode)
-{
- static uint8 inhibit_modified=0;
-
- fprintf(fp,"#ifndef blitter_code_0x%.8x\n",hashcode);
- fprintf(fp,"#define blitter_code_0x%.8x\n",hashcode);
-
- fprintf(fp,"void blitter_0x%.8x(void)\n",hashcode);
- fprintf(fp,"{\n");
- fprintf(fp,"\twhile (outer_loop--)\n");
- fprintf(fp,"\t{\n");
- fprintf(fp,"\t\tinner_loop=n_pixels;\n");
- fprintf(fp,"\t\twhile (inner_loop--)\n");
- fprintf(fp,"\t\t{\n");
- fprintf(fp,"\t\t\tuint32 srcdata = 0;\n");
- fprintf(fp,"\t\t\tuint32 srczdata = 0;\n");
- fprintf(fp,"\t\t\tuint32 dstdata = 0;\n");
- fprintf(fp,"\t\t\tuint32 dstzdata = 0;\n");
- fprintf(fp,"\t\t\tuint32 writedata = 0;\n");
- fprintf(fp,"\t\t\tuint32 inhibit = 0;\n");
-
- char *src;
- char *dst;
- uint32 src_flags;
- uint32 dst_flags;
-
- if (!DSTA2)
- {
- src="a2";
- dst="a1";
- src_flags=A2_FLAGS;
- dst_flags=A1_FLAGS;
- }
- else
- {
- src="a1";
- dst="a2";
- src_flags=A1_FLAGS;
- dst_flags=A2_FLAGS;
- }
-
- // load src data and Z
- if (SRCEN)
- {
- fprintf(fp, "\t\t\tsrcdata = READ_PIXEL_%i(%s);\n", BPP_LUT[(((REG(dst_flags)) >> 3) & 0x07)], src);
- if (SRCENZ)
- fprintf(fp,"\t\t\tsrczdata = READ_ZDATA_%i(%s);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],src);
- else
- if (cmd & 0x001c020)
- fprintf(fp,"\t\t\tsrczdata = READ_RDATA_%i(SRCZINT, %s, %s_phrase_mode);\n",BPP_LUT[(((REG(src_flags))>>3)&0x07)],src,src);
- }
- else
- {
- fprintf(fp,"\t\t\tsrcdata = READ_RDATA_%i(SRCDATA, %s, %s_phrase_mode);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],src,src);
- if (cmd & 0x001c020)
- fprintf(fp,"\t\t\tsrczdata = READ_RDATA_%i(SRCZINT, %s, %s_phrase_mode);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],src,src);
- }
-
- // load dst data and Z
- if (DSTEN)
- {
- fprintf(fp,"\t\t\tdstdata = READ_PIXEL_%i(%s);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],dst);
- if (DSTENZ)
- fprintf(fp,"\t\t\tdstzdata = READ_ZDATA_%i(%s);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],dst);
- else
- fprintf(fp,"\t\t\tdstzdata = READ_RDATA_%i(DSTZ, %s, %s_phrase_mode);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],dst,dst);
- }
- else
- {
- fprintf(fp,"\t\t\tdstdata = READ_RDATA_%i(DSTDATA, %s, %s_phrase_mode);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],dst,dst);
-
- if (DSTENZ)
- fprintf(fp,"\t\t\tdstzdata = READ_RDATA_%i(DSTZ, %s, %s_phrase_mode);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],dst,dst);
- }
-
- // a1 clipping
- if ((cmd & 0x00000040)&&(!DSTA2))
-
- {
- fprintf(fp,"\t\t\tif (a1_x < 0 || a1_y < 0 || (a1_x >> 16) >= (REG(A1_CLIP) & 0x7fff) || (a1_y >> 16) >= ((REG(A1_CLIP) >> 16) & 0x7fff)) inhibit = 1;\n");
- inhibit_modified=1;
- }
- if(GOURZ)
- {
- fprintf(fp,"\t\t\tsrczdata=z_i[colour_index]>>16;\n");
- }
- // apply z comparator
- if (Z_OP_INF) { fprintf(fp,"\t\t\tif (srczdata < dstzdata) inhibit = 1;\n"); inhibit_modified=1;}
- if (Z_OP_EQU) { fprintf(fp,"\t\t\tif (srczdata == dstzdata) inhibit = 1;\n"); inhibit_modified=1;}
- if (Z_OP_SUP) { fprintf(fp,"\t\t\tif (srczdata > dstzdata) inhibit = 1;\n"); inhibit_modified=1;}
-
- // apply data comparator
- if (DCOMPEN)
- {
- if (!CMPDST)
- {
- // compare source pixel with pattern pixel
- fprintf(fp,"\t\t\tif (srcdata == READ_RDATA_%i(PATTERNDATA, %s,%s_phrase_mode)) inhibit=1;\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],src,src);
- inhibit_modified=1;
- }
- else
- {
- // compare destination pixel with pattern pixel
- fprintf(fp,"\t\t\tif (dstdata == READ_RDATA_%i(PATTERNDATA, %s,%s_phrase_mode)) inhibit=1;\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],dst,dst);
- inhibit_modified=1;
- }
- }
-
- // compute the write data and store
- if (inhibit_modified) fprintf(fp,"\t\t\tif (!inhibit)\n\t\t\t{\n");
- if (PATDSEL)
- {
- // use pattern data for write data
- fprintf(fp,"\t\t\t\twritedata= READ_RDATA_%i(PATTERNDATA, %s, %s_phrase_mode);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],dst,dst);
- }
- else
- if (INTADD)
- {
- // intensity addition
- fprintf(fp,"\t\t\t\twritedata = (srcdata & 0xff) + (dstdata & 0xff);\n");
- if (!(TOPBEN))
- fprintf(fp,"\t\t\t\tif (writedata > 0xff) writedata = 0xff;\n");
-
- fprintf(fp,"\t\t\t\twritedata |= (srcdata & 0xf00) + (dstdata & 0xf00);\n");
- if (!(TOPNEN)) fprintf(fp,"\t\t\t\tif (writedata > 0xfff) writedata = 0xfff;\n");
- fprintf(fp,"\t\t\t\twritedata |= (srcdata & 0xf000) + (dstdata & 0xf000);\n");
- }
- else
- {
- if (LFU_NAN) fprintf(fp,"\t\t\t\twritedata |= ~srcdata & ~dstdata;\n");
- if (LFU_NA) fprintf(fp,"\t\t\t\twritedata |= ~srcdata & dstdata;\n");
- if (LFU_AN) fprintf(fp,"\t\t\t\twritedata |= srcdata & ~dstdata;\n");
- if (LFU_A) fprintf(fp,"\t\t\t\twritedata |= srcdata & dstdata;\n");
- }
- if(GOURD)
- {
- fprintf(fp,"\t\t\t\twritedata = ((gd_c[colour_index])<<8)|(gd_i[colour_index]>>16);\n");
- }
- if(SRCSHADE)
- {
- fprintf(fp,"\t\t\t\t{\n");
- fprintf(fp,"\t\t\t\tint intensity = srcdata & 0xFF;\n");
- fprintf(fp,"\t\t\t\tint ia = gd_ia >> 16;\n");
- fprintf(fp,"\t\t\t\tif(ia & 0x80)\n");
- fprintf(fp,"\t\t\t\t ia = 0xFFFFFF00 | ia;\n");
- fprintf(fp,"\t\t\t\tintensity += ia;\n");
- fprintf(fp,"\t\t\t\tif(intensity < 0)\n");
- fprintf(fp,"\t\t\t\t intensity = 0;\n");
- fprintf(fp,"\t\t\t\tif(intensity > 0xFF)\n");
- fprintf(fp,"\t\t\t\t intensity = 0xFF;\n");
- fprintf(fp,"\t\t\t\twritedata = (srcdata & 0xFF00) | intensity;\n");
- fprintf(fp,"\t\t\t\t}\n");
- }
- if (inhibit_modified)
- {
- fprintf(fp,"\t\t\t} else { srczdata=dstzdata; writedata=dstdata; }\n");
- }
-
- if ((DSTA2?a2_phrase_mode:a1_phrase_mode) || BKGWREN)
- {
- // write to the destination
- fprintf(fp,"\t\t\tWRITE_PIXEL_%i(%s, writedata);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],dst);
- if (DSTWRZ) fprintf(fp,"\t\t\tWRITE_ZDATA_%i(%s, srczdata);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],dst);
- }
- else
- {
- if (inhibit_modified) fprintf(fp,"\t\t\tif (!inhibit)\n\t\t\t{\n");
- // write to the destination
- fprintf(fp,"\t\t\t\tWRITE_PIXEL_%i(%s, writedata);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],dst);
- if (DSTWRZ) fprintf(fp,"\t\t\t\tWRITE_ZDATA_%i(%s, srczdata);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],dst);
- if (inhibit_modified) fprintf(fp,"\t\t\t}\n");
- }
- // update x and y
- fprintf(fp,"\t\t\ta1_x += a1_xadd;\n");
- fprintf(fp,"\t\t\ta1_y += a1_yadd;\n");
- fprintf(fp,"\t\t\ta2_x = (a2_x + a2_xadd) & a2_mask_x;\n");
- fprintf(fp,"\t\t\ta2_y = (a2_y + a2_yadd) & a2_mask_y;\n");
- if (GOURZ)
- {
- fprintf(fp,"\t\t\tz_i[colour_index]+=zadd;\n");
- }
- if ((GOURD)||(SRCSHADE))
- {
- fprintf(fp,"\t\t\tgd_i[colour_index] += gd_ia;\n");
- fprintf(fp,"\t\t\tgd_c[colour_index] += gd_ca;\n");
- }
- if ((GOURD)||(SRCSHADE)||(GOURZ))
- {
- if (a1_phrase_mode)
- fprintf(fp,"\t\t\t colour_index=(colour_index+1)&0x3;\n");
- }
- fprintf(fp,"\t\t}\n");
-
- fprintf(fp,"\t\ta1_x+=a1_step_x;\n");
- fprintf(fp,"\t\ta1_y+=a1_step_y;\n");
- fprintf(fp,"\t\ta2_x+=a2_step_x;\n");
- fprintf(fp,"\t\ta2_y+=a2_step_y;\n");
- fprintf(fp,"\t}\n");
-
- // write values back to registers
- fprintf(fp,"\tWREG(A1_PIXEL, (a1_y & 0xffff0000) | ((a1_x >> 16) & 0xffff));\n");
- fprintf(fp,"\tWREG(A1_FPIXEL, (a1_y << 16) | (a1_x & 0xffff));\n");
- fprintf(fp,"\tWREG(A2_PIXEL, (a2_y & 0xffff0000) | ((a2_x >> 16) & 0xffff));\n");
- fprintf(fp,"}\n");
- fprintf(fp,"#endif\n");
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// Generate a start of function in x86 assembly
-//////////////////////////////////////////////////////////////////////////////
-//
-//
-//
-//////////////////////////////////////////////////////////////////////////////
-void blitter_gen_start_of_function(void)
-{
- *blitter_ptr++ = 0x55; // push ebp
- *blitter_ptr++ = 0x8B; // mov ebp,esp
- *blitter_ptr++ = 0xEC;
-}
-//////////////////////////////////////////////////////////////////////////////
-// Generate a end of function in x86 assembly
-//////////////////////////////////////////////////////////////////////////////
-//
-//
-//
-//////////////////////////////////////////////////////////////////////////////
-void blitter_gen_end_of_function(void)
-{
- *blitter_ptr++ = 0x8B; // mov esp,ebp
- *blitter_ptr++ = 0xE5;
- *blitter_ptr++ = 0x5D; // pop ebp
- *blitter_ptr++ = 0xC3; // ret
-}
+static int gd_i[4];
+static int gd_c[4];
+static int gd_ia, gd_ca;
+static int colour_index = 0;
+static int32 zadd;
+static uint32 z_i[4];
-#define HASHCODE_BIT(C,B) if (C) hashcode|=(1<<B);
-#define HASHCODE_BIT_TEST(B) (hashcode&(1<<B))
+static int32 a1_clip_x, a1_clip_y;
-uint32 blitter_calc_hashcode(uint32 cmd)
-{
- uint32 hashcode=0x00000000;
-
- // source and destination bit depth
- hashcode|=((REG(A1_FLAGS)>>3)&0x07)<<0;
- hashcode|=((REG(A2_FLAGS)>>3)&0x07)<<3;
-
- HASHCODE_BIT(DSTA2, 6);
- HASHCODE_BIT(SRCEN, 7);
- HASHCODE_BIT(SRCENZ, 8);
- HASHCODE_BIT(DSTEN, 9);
- HASHCODE_BIT(DSTENZ, 10);
- HASHCODE_BIT(Z_OP_INF, 11);
- HASHCODE_BIT(Z_OP_EQU, 12);
- HASHCODE_BIT(Z_OP_SUP, 13);
- HASHCODE_BIT(DCOMPEN, 14);
- HASHCODE_BIT(CMPDST, 15);
- HASHCODE_BIT(PATDSEL, 16);
- HASHCODE_BIT(INTADD, 17);
- HASHCODE_BIT(TOPBEN, 18);
- HASHCODE_BIT(TOPNEN, 19);
- HASHCODE_BIT(LFU_NAN, 20);
- HASHCODE_BIT(LFU_NA, 21);
- HASHCODE_BIT(LFU_AN, 22);
- HASHCODE_BIT(LFU_A, 23);
- HASHCODE_BIT(BKGWREN, 24);
- HASHCODE_BIT(DSTWRZ, 25);
- HASHCODE_BIT((cmd & 0x001c020), 26); // extra data read/write
- HASHCODE_BIT((cmd & 0x00000040), 27); // source clipping
- HASHCODE_BIT(a1_phrase_mode, 28);
- HASHCODE_BIT(a2_phrase_mode, 29);
-
- return(hashcode);
-}
-//////////////////////////////////////////////////////////////////////////////
-// Build the blitter code for the current blitter operation in the cache
-//////////////////////////////////////////////////////////////////////////////
-//
-//
-//
-//////////////////////////////////////////////////////////////////////////////
-void blitter_build_cached_code(uint32 cmd, uint32 cache_index)
-{
-}
-//////////////////////////////////////////////////////////////////////////////
-// Check if the blitter code for the current blitter operation is cached
-//////////////////////////////////////////////////////////////////////////////
-//
-//
-//
-//////////////////////////////////////////////////////////////////////////////
-struct s_blitter_cache * blitter_in_cache(uint32 cmd)
-{
- uint32 i;
- uint32 hashcode=blitter_calc_hashcode(cmd);
-#ifdef LOG_BLITS
- WriteLog("blitter: hashcode= 0x%.8x\n",hashcode);
-#endif
- struct s_blitter_cache *blitter_list=blitter_cache[hashcode>>24];
-
- i=0;
- while (blitter_list->next)
- {
- blitter_list=blitter_list->next;
-
- if (blitter_list->hashcode==hashcode)
- return(blitter_list);
- }
-#ifdef GEN_CODE
- blitter_list->next=(struct s_blitter_cache *)malloc(sizeof(struct s_blitter_cache));
- blitter_list->next->prev=blitter_list;
- blitter_list->next->next=null;
- blitter_list=blitter_list->next;
-
- blitter_list->code=(uint8*)malloc(4096);
- blitter_list->hashcode=hashcode;
- blitter_list->ready=0;
- blitter_gen_c_code(blitters_code_fp,cmd,hashcode);
- fprintf(blitters_code_init_fp,"\tblitter_add(0x%.8x,(uint8*)&blitter_0x%.8x);\n",hashcode,hashcode);
-#else
- //WriteLog("warning: using generic blitter for blitter 0x%.8x\n",hashcode);
-#endif
- return(null);
-}
-#ifndef USE_GENERIC_BLITTER
-#include "include/blit_c.h"
-#endif
-//////////////////////////////////////////////////////////////////////////////
-// Execute the cached blitter code for the current blitter operation
-//////////////////////////////////////////////////////////////////////////////
-//
-//
-//
-//////////////////////////////////////////////////////////////////////////////
-uint32 blitter_execute_cached_code(struct s_blitter_cache * blitter)
-{
- if ((blitter == null) || (blitter->ready == 0))
- return 0;
-
- blitter_fn * fn = (blitter_fn *)blitter->code;
- blitter->used = 1;
- (*fn)();
-
- return 1;
-}
-
-void blitter_add(uint32 hashcode, uint8 *code)
-{
- struct s_blitter_cache *blitter_list=blitter_cache[(hashcode>>24)];
-
-// WriteLog("adding blitter for hashcode 0x%.8x\n",hashcode);
-
- while (blitter_list->next)
- {
- blitter_list=blitter_list->next;
-
- if (blitter_list->hashcode==hashcode)
- return;
- }
- blitter_list->next=(struct s_blitter_cache *)malloc(sizeof(struct s_blitter_cache));
- blitter_list->next->prev=blitter_list;
- blitter_list->next->next=null;
- blitter_list=blitter_list->next;
-
- blitter_list->code=code;
- blitter_list->hashcode=hashcode;
- blitter_list->ready=1;
- blitter_list->used=0;
-}
-
-void blitter_list(void)
-{
-/*
- WriteLog("Used blitters list:\n");
-
- for (int i=0;i<256;i++)
- {
- struct s_blitter_cache *blitter_list=blitter_cache[i];
-
- while (blitter_list->next)
- {
- blitter_list=blitter_list->next;
- if (blitter_list->used)
- WriteLog("\t0%.8x\n",blitter_list->hashcode);
- }
- }
-*/
-}
+// In the spirit of "get it right first, *then* optimize" I've taken the liberty
+// of removing all the unnecessary code caching. If it turns out to be a good way
+// to optimize the blitter, then we may revisit it in the future...
//
// Generic blit handler
//
-
void blitter_generic(uint32 cmd)
{
//Testing only!
//uint32 logGo = ((cmd == 0x01800E01 && REG(A1_BASE) == 0x898000) ? 1 : 0);
-
-/* uint32 srcdata = 0;
- uint32 srczdata = 0;
- uint32 dstdata = 0;
- uint32 dstzdata = 0;
- uint32 writedata = 0;
- uint32 inhibit = 0;*/
uint32 srcdata, srczdata, dstdata, dstzdata, writedata, inhibit;
+if (specialLog)
+{
+ WriteLog("About to do 8x8 blit (BM width is 448 pixels)...\n");
+}
while (outer_loop--)
{
+if (specialLog)
+{
+ WriteLog(" A1_X/Y = %08X/%08X, A2_X/Y = %08X/%08X\n", a1_x, a1_y, a2_x, a2_y);
+}
inner_loop = n_pixels;
while (inner_loop--)
{
+if (specialLog)
+{
+ WriteLog(" A1_X/Y = %08X/%08X, A2_X/Y = %08X/%08X\n", a1_x, a1_y, a2_x, a2_y);
+}
srcdata = srczdata = dstdata = dstzdata = writedata = inhibit = 0;
if (!DSTA2)
else
WriteLog("Blitter: Bad BPP (%u) selected for BCOMPEN mode!\n", A2bpp);//*/
// What it boils down to is this:
-// ***CHECK*** Hmm. Seems to cause Rayman to freeze. Investigate.
-// This doesn't seem to be it. Hmm.
-// It was a bug in the TOM read word code (reading VC)
if (srcdata == 0)
inhibit = 1;//*/
}
if (/*a1_phrase_mode || */BKGWREN || !inhibit)
{
-// This is the sole source of the bogus YPOS values being written to the object list... !!! FIX !!!
/*if (((REG(A1_FLAGS) >> 3) & 0x07) == 5)
{
uint32 offset = a1_addr+(PIXEL_OFFSET_32(a1)<<2);
else
WriteLog("Blitter: Bad BPP (%u) selected for BCOMPEN mode!\n", A1bpp);//*/
// What it boils down to is this:
-// ***CHECK*** Hmm. Seems to cause Rayman to freeze. Investigate.
-// This doesn't seem to be it. Hmm.
-// It was a bug in the TOM read word code (reading VC)
if (srcdata == 0)
inhibit = 1;//*/
}
WREG(A1_PIXEL, (a1_y & 0xFFFF0000) | ((a1_x >> 16) & 0xFFFF));
WREG(A1_FPIXEL, (a1_y << 16) | (a1_x & 0xFFFF));
WREG(A2_PIXEL, (a2_y & 0xFFFF0000) | ((a2_x >> 16) & 0xFFFF));
+specialLog = false;
}
void blitter_blit(uint32 cmd)
{
+ uint32 pitchValue[4] = { 0, 1, 3, 2 };
colour_index = 0;
src = cmd & 0x07;
dst = (cmd >> 3) & 0x07;
ctrl = (cmd >> 25) & 0x3F;
a1_addr = REG(A1_BASE);
+//Just for testing Trevor McFur...
+//if (a1_addr == 0x130CB0) specialLog = true;
+//extern bool suppressOutput;
+//if (a1_addr == 0x130CB0) suppressOutput = false;
+//End testing
a2_addr = REG(A2_BASE);
a1_zoffs = (REG(A1_FLAGS) >> 6) & 7;
xadd_a1_control = (REG(A1_FLAGS) >> 16) & 0x03;
xadd_a2_control = (REG(A2_FLAGS) >> 16) & 0x03;
- a1_pitch = (REG(A1_FLAGS) & 3) ^ ((REG(A1_FLAGS) & 2) >> 1);
- a2_pitch = (REG(A2_FLAGS) & 3) ^ ((REG(A2_FLAGS) & 2) >> 1);
+// a1_pitch = (REG(A1_FLAGS) & 3) ^ ((REG(A1_FLAGS) & 2) >> 1);
+// a2_pitch = (REG(A2_FLAGS) & 3) ^ ((REG(A2_FLAGS) & 2) >> 1);
+ a1_pitch = pitchValue[(REG(A1_FLAGS) & 0x03)];
+ a2_pitch = pitchValue[(REG(A2_FLAGS) & 0x03)];
n_pixels = REG(PIXLINECOUNTER) & 0xFFFF;
n_lines = (REG(PIXLINECOUNTER) >> 16) & 0xFFFF;
a1_x = (REG(A1_PIXEL) << 16) | (REG(A1_FPIXEL) & 0xFFFF);
a1_y = (REG(A1_PIXEL) & 0xFFFF0000) | (REG(A1_FPIXEL) >> 16);
+//According to the JTRM, X is restricted to 15 bits and Y is restricted to 12.
+//But it seems to fuck up T2K! !!! FIX !!!
+// a1_x &= 0x7FFFFFFF, a1_y &= 0x0FFFFFFF;
+
// a1_width = blitter_scanline_width[((REG(A1_FLAGS) & 0x00007E00) >> 9)];
UINT32 m = (REG(A1_FLAGS) >> 9) & 0x03, e = (REG(A1_FLAGS) >> 11) & 0x0F;
a1_width = ((0x04 | m) << e) >> 2;//*/
a2_x = (REG(A2_PIXEL) & 0x0000FFFF) << 16;
a2_y = (REG(A2_PIXEL) & 0xFFFF0000);
+//According to the JTRM, X is restricted to 15 bits and Y is restricted to 12.
+//But it seems to fuck up T2K! !!! FIX !!!
+// a2_x &= 0x7FFFFFFF, a2_y &= 0x0FFFFFFF;
+
// a2_width = blitter_scanline_width[((REG(A2_FLAGS) & 0x00007E00) >> 9)];
m = (REG(A2_FLAGS) >> 9) & 0x03, e = (REG(A2_FLAGS) >> 11) & 0x0F;
a2_width = ((0x04 | m) << e) >> 2;//*/
break;
//This really isn't a valid bit combo for A2... Shouldn't this cause the blitter to just say no?
case XADDINC:
+WriteLog("BLIT: Asked to used invalid bit combo for A2...\n");
// add the contents of the increment register
// since there is no register for a2 we just add 1
- a2_xadd = 1 << 16;
+//Let's do nothing, since it's not listed as a valid bit combo...
+// a2_xadd = 1 << 16;
break;
}
if (XSIGNSUB_A2)
WriteLog(" A1 -> pitch: %d phrases, depth: %s, z-off: %d, width: %d (%02X), addctl: %s %s %s %s\n", 1 << p1, bppStr[d1], zo1, iw1, w1, ctrlStr[ac1&0x03], (ac1&0x04 ? "YADD1" : "YADD0"), (ac1&0x08 ? "XSIGNSUB" : "XSIGNADD"), (ac1&0x10 ? "YSIGNSUB" : "YSIGNADD"));
WriteLog(" A2 -> pitch: %d phrases, depth: %s, z-off: %d, width: %d (%02X), addctl: %s %s %s %s\n", 1 << p2, bppStr[d2], zo2, iw2, w2, ctrlStr[ac2&0x03], (ac2&0x04 ? "YADD1" : "YADD0"), (ac2&0x08 ? "XSIGNSUB" : "XSIGNADD"), (ac2&0x10 ? "YSIGNSUB" : "YSIGNADD"));
- WriteLog(" x/y: %d/%d\n", a2_x >> 16, a2_y >> 16);
+ WriteLog(" A1 x/y: %d/%d, A2 x/y: %d/%d\n", a1_x >> 16, a1_y >> 16, a2_x >> 16, a2_y >> 16);
// blit_start_log = 0;
// op_start_log = 1;
}
blitter_working = 1;
-#ifndef USE_GENERIC_BLITTER
- if (!blitter_execute_cached_code(blitter_in_cache(cmd)))
-#endif
- blitter_generic(cmd);
+//#ifndef USE_GENERIC_BLITTER
+// if (!blitter_execute_cached_code(blitter_in_cache(cmd)))
+//#endif
+ blitter_generic(cmd);
/*if (blit_start_log)
{
void blitter_init(void)
{
- if (!blitter_cache_init)
- {
- for (int i=0;i<256;i++)
- {
- blitter_cache[i] = (struct s_blitter_cache *)malloc(sizeof(struct s_blitter_cache));
- blitter_cache[i]->next=null;
- blitter_cache[i]->prev=null;
- }
- blitter_cache_init = 1;
- }
-#ifndef USE_GENERIC_BLITTER
- #include "include/blit_i.h"
-#endif
-
blitter_reset();
-#ifdef GEN_CODE
- blitters_code_fp = fopen("include/blit_c.h", "awrt");
- blitters_code_init_fp = fopen("include/blit_i.h", "awrt");
-#endif
}
void blitter_reset(void)
void blitter_done(void)
{
-// blitter_list();
-#ifdef GEN_CODE
- fclose(blitters_code_fp);
- fclose(blitters_code_init_fp);
-#endif
WriteLog("BLIT: Done.\n");
}
void blitter_byte_write(uint32 offset, uint8 data)
{
/*if (offset & 0xFF == 0x7B)
-{
- WriteLog("--> Wrote to B_STOP: value -> %02X\n", data);
-}*/
+ WriteLog("--> Wrote to B_STOP: value -> %02X\n", data);*/
offset &= 0xFF;
// if ((offset >= 0x7C) && (offset <= 0x9B))
#include "gpu.h"
-// For GPU dissasembly...
+//#define GPU_DEBUG
-//#define GPU_DIS_ABS
-//#define GPU_DIS_ADDC
-//#define GPU_DIS_CMP
-//#define GPU_DIS_CMPQ
-//#define GPU_DIS_DIV
-//#define GPU_DIS_JUMP
-//#define GPU_DIS_JR
-//#define GPU_DIS_ROR
-//#define GPU_DIS_RORQ
-//#define GPU_DIS_SH
-//#define GPU_DIS_SHA
-//#define GPU_DIS_SHARQ
-//#define GPU_DIS_SHLQ
-//#define GPU_DIS_SHRQ
-//#define GPU_DIS_STORE14R
-//#define GPU_DIS_STORE15R
-//#define GPU_DIS_SUBC
+// For GPU dissasembly...
+/*
+#define GPU_DIS_ABS
+#define GPU_DIS_ADD
+#define GPU_DIS_ADDC
+#define GPU_DIS_ADDQ
+#define GPU_DIS_ADDQT
+#define GPU_DIS_AND
+#define GPU_DIS_BCLR
+#define GPU_DIS_BSET
+#define GPU_DIS_BTST
+#define GPU_DIS_CMP
+#define GPU_DIS_CMPQ
+#define GPU_DIS_DIV
+#define GPU_DIS_IMULT
+#define GPU_DIS_JUMP
+#define GPU_DIS_JR
+#define GPU_DIS_LOAD
+#define GPU_DIS_LOADB
+#define GPU_DIS_LOADW
+#define GPU_DIS_LOAD14I
+#define GPU_DIS_LOAD14R
+#define GPU_DIS_LOAD15I
+#define GPU_DIS_LOAD15R
+#define GPU_DIS_MOVE
+#define GPU_DIS_MOVEFA
+#define GPU_DIS_MOVEI
+#define GPU_DIS_MOVEPC
+#define GPU_DIS_MOVETA
+#define GPU_DIS_MOVEQ
+#define GPU_DIS_MULT
+#define GPU_DIS_NEG
+#define GPU_DIS_NOP
+#define GPU_DIS_NOT
+#define GPU_DIS_OR
+#define GPU_DIS_PACK
+#define GPU_DIS_ROR
+#define GPU_DIS_RORQ
+#define GPU_DIS_SAT8
+#define GPU_DIS_SH
+#define GPU_DIS_SHA
+#define GPU_DIS_SHARQ
+#define GPU_DIS_SHLQ
+#define GPU_DIS_SHRQ
+#define GPU_DIS_STORE
+#define GPU_DIS_STOREB
+#define GPU_DIS_STOREW
+#define GPU_DIS_STORE14I
+#define GPU_DIS_STORE14R
+#define GPU_DIS_STORE15I
+#define GPU_DIS_STORE15R
+#define GPU_DIS_SUB
+#define GPU_DIS_SUBC
+#define GPU_DIS_SUBQ
+#define GPU_DIS_SUBQT
+#define GPU_DIS_XOR
+//*/
/*
GPU opcodes use (BIOS flying ATARI logo):
- add 357416
- addq 538030
- addqt 6999
- sub 116663
- subq 188059
- subqt 15086
- neg 36097
- and 233993
- or 109332
- xor 1384
- btst 111924
- bset 25029
- bclr 10551
- mult 28147
- imult 69148
++ add 357416
++ addq 538030
++ addqt 6999
++ sub 116663
++ subq 188059
++ subqt 15086
++ neg 36097
++ and 233993
++ or 109332
++ xor 1384
++ btst 111924
++ bset 25029
++ bclr 10551
++ mult 28147
++ imult 69148
+ div 64102
+ abs 159394
+ shlq 194690
+ rorq 58672
+ cmp 244963
+ cmpq 114834
- move 833472
- moveq 56427
- moveta 220814
- movefa 170678
- movei 152025
- loadw 108220
- load 430936
- storew 3036
- store 372490
- move_pc 2330
++ move 833472
++ moveq 56427
++ moveta 220814
++ movefa 170678
++ movei 152025
++ loadw 108220
++ load 430936
++ storew 3036
++ store 372490
++ move_pc 2330
+ jump 349134
+ jr 529171
mmult 64904
- nop 432179
++ nop 432179
*/
+// Various bits
+
+#define CINT0FLAG 0x0200
+#define CINT1FLAG 0x0400
+#define CINT2FLAG 0x0800
+#define CINT3FLAG 0x1000
+#define CINT4FLAG 0x2000
+#define CINT04FLAGS (CINT0FLAG | CINT1FLAG | CINT2FLAG | CINT3FLAG | CINT4FLAG)
+
+// GPU_FLAGS bits
+
+#define ZERO_FLAG 0x0001
+#define CARRY_FLAG 0x0002
+#define NEGA_FLAG 0x0004
+#define IMASK 0x0008
+#define INT_ENA0 0x0010
+#define INT_ENA1 0x0020
+#define INT_ENA2 0x0040
+#define INT_ENA3 0x0080
+#define INT_ENA4 0x0100
+#define INT_CLR0 0x0200
+#define INT_CLR1 0x0400
+#define INT_CLR2 0x0800
+#define INT_CLR3 0x1000
+#define INT_CLR4 0x2000
+#define REGPAGE 0x4000
+#define DMAEN 0x8000
+
// Private function prototypes
+void GPUUpdateRegisterBanks(void);
+
void gpu_dump_disassembly(void);
void gpu_dump_registers(void);
void gpu_dump_memory(void);
-#define CINT0FLAG 0x00200
-#define CINT1FLAG 0x00400
-#define CINT2FLAG 0x00800
-#define CINT3FLAG 0x01000
-#define CINT4FLAG 0x02000
-#define CINT04FLAGS (CINT0FLAG | CINT1FLAG | CINT2FLAG | CINT3FLAG | CINT4FLAG)
-
extern int start_logging;
extern int gpu_start_log;
static uint32 gpu_data_organization;
static uint32 gpu_control;
static uint32 gpu_div_control;
+// There is a distinct advantage to having these separated out--there's no need to clear
+// a bit before writing a result. I.e., if the result of an operation leaves a zero in
+// the carry flag, you don't have to zero gpu_flag_c before you can write that zero!
static uint8 gpu_flag_z, gpu_flag_n, gpu_flag_c;
-static uint8 gpu_alternate_flag_z, gpu_alternate_flag_n, gpu_alternate_flag_c;
-static uint32 * gpu_reg;
-static uint32 * gpu_alternate_reg;
static uint32 * gpu_reg_bank_0;
static uint32 * gpu_reg_bank_1;
+static uint32 * gpu_reg;
+static uint32 * gpu_alternate_reg;
static uint32 gpu_instruction;
static uint32 gpu_opcode_first_parameter;
uint32 gpu_opcode_use[64];
-void gpu_update_register_banks(void);
-
char * gpu_opcode_str[64]=
{
"add", "addc", "addq", "addqt",
static uint32 gpu_in_exec = 0;
static uint32 gpu_releaseTimeSlice_flag = 0;
-
+bool GPUInterruptPending = false;
void gpu_releaseTimeslice(void)
{
return gpu_pc;
}
-#define ZFLAG 0x00001
+/*#define ZFLAG 0x00001
#define CFLAG 0x00002
-#define NFLAG 0x00004
+#define NFLAG 0x00004*/
void build_branch_condition_table(void)
{
{
int result = 1;
if (j & 1)
- if (i & ZFLAG)
+ if (i & ZERO_FLAG)
result = 0;
if (j & 2)
- if (!(i & ZFLAG))
+ if (!(i & ZERO_FLAG))
result = 0;
if (j & 4)
- if (i & (CFLAG << (j >> 4)))
+ if (i & (CARRY_FLAG << (j >> 4)))
result = 0;
if (j & 8)
- if (!(i & (CFLAG << (j >> 4))))
+ if (!(i & (CARRY_FLAG << (j >> 4))))
result = 0;
branch_condition_table[i * 32 + j] = result;
}
//
// GPU byte access (read)
//
-
+//unsigned gpu_byte_read(unsigned int offset, uint32 calledBy)
unsigned gpu_byte_read(unsigned int offset)
-{
+{
if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
return gpu_ram_8[offset & 0xFFF];
else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
//
// GPU word access (read)
//
-
unsigned gpu_word_read(unsigned int offset)
{
if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
//
// GPU dword access (read)
//
-
unsigned gpu_long_read(unsigned int offset)
{
-
- if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
+// if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE + 0x1000))
+ if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFC))
{
offset &= 0xFFF;
return ((uint32)gpu_ram_8[offset] << 24) | ((uint32)gpu_ram_8[offset+1] << 16)
- | ((uint32)gpu_ram_8[offset+2] << 8) | (uint32)gpu_ram_8[offset+3];
+ | ((uint32)gpu_ram_8[offset+2] << 8) | (uint32)gpu_ram_8[offset+3];//*/
+// return GET32(gpu_ram_8, offset);
}
- else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
+// else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
+ else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1C))
{
offset &= 0x1F;
switch (offset)
case 0x1C:
return gpu_remain;
default: // unaligned long read
+#ifdef GPU_DEBUG
+ WriteLog("GPU: Read32--unaligned 32 bit read at %08X.\n", GPU_CONTROL_RAM_BASE + offset);
+#endif // GPU_DEBUG
return 0;
- //exit(0);
- // __asm int 3
- // }
}
- // to prevent any lock-ups
}
//TEMP--Mirror of F03000?
if (offset >= 0xF0B000 && offset <= 0xF0BFFF)
/*if (offset >= 0xF1D000 && offset <= 0xF1DFFF)
WriteLog("[GPUR32] --> Reading from Wavetable ROM!\n");//*/
- return (jaguar_word_read(offset) << 16) | jaguar_word_read(offset+2);
+ return (jaguar_word_read(offset) << 16) | jaguar_word_read(offset + 2);
}
//
// GPU byte access (write)
//
-
void gpu_byte_write(unsigned offset, unsigned data)
{
- if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
+ if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFF))
{
gpu_ram_8[offset & 0xFFF] = data;
- if (gpu_in_exec == 0)
+
+ if (!gpu_in_exec)
{
-// s68000releaseTimeslice();
m68k_end_timeslice();
dsp_releaseTimeslice();
}
return;
}
- else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
+ else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1F))
{
uint32 reg = offset & 0x1C;
int bytenum = offset & 0x03;
//This is definitely wrong!
if ((reg >= 0x1C) && (reg <= 0x1F))
- gpu_div_control = (gpu_div_control & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
+ gpu_div_control = (gpu_div_control & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
else
{
uint32 old_data = gpu_long_read(offset & 0xFFFFFFC);
bytenum = 3 - bytenum; // convention motorola !!!
- old_data = (old_data & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
+ old_data = (old_data & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
gpu_long_write(offset & 0xFFFFFFC, old_data);
}
return;
//
// GPU word access (write)
//
-
void gpu_word_write(unsigned offset, unsigned data)
{
-
- if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
+ if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFE))
{
-//if (offset >= 0xF03000 && offset <= 0xF03003)
-// WriteLog("--> GPU(16): Writing %04X at %08X ***\n", data, offset);
-
gpu_ram_8[offset & 0xFFF] = (data>>8) & 0xFF;
- gpu_ram_8[(offset+1) & 0xFFF] = data & 0xFF;
- if (gpu_in_exec == 0)
+ gpu_ram_8[(offset+1) & 0xFFF] = data & 0xFF;//*/
+/* offset &= 0xFFF;
+ SET16(gpu_ram_8, offset, data);//*/
+
+ if (!gpu_in_exec)
{
-// s68000releaseTimeslice();
m68k_end_timeslice();
dsp_releaseTimeslice();
}
return;
}
- if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
+ else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1E))
{
if (offset & 0x01) // This is supposed to weed out unaligned writes, but does nothing...
{
- //exit(0);
- //__asm int 3
+#ifdef GPU_DEBUG
+ WriteLog("GPU: Write16--unaligned write @ %08X [%04X]\n", offset, data);
+ gpu_dump_registers();
+#endif // GPU_DEBUG
+ return;
}
+//Dual locations in this range: $1C Divide unit remainder/Divide unit control (R/W)
+//This just literally sucks.
if ((offset & 0x1C) == 0x1C)
{
//This doesn't look right either--handles cases 1, 2, & 3 all the same!
- if (offset & 0x03)
- gpu_div_control = (gpu_div_control&0xFFFF0000) | (data&0xFFFF);
+ if (offset & 0x02)
+ gpu_div_control = (gpu_div_control & 0xFFFF0000) | (data & 0xFFFF);
else
- gpu_div_control = (gpu_div_control&0xFFFF) | ((data&0xFFFF)<<16);
+ gpu_div_control = (gpu_div_control & 0x0000FFFF) | ((data & 0xFFFF) << 16);
}
else
{
+//WriteLog("[GPU W16:%08X,%04X]", offset, data);
uint32 old_data = gpu_long_read(offset & 0xFFFFFFC);
- if (offset & 0x03)
+ if (offset & 0x02)
old_data = (old_data & 0xFFFF0000) | (data & 0xFFFF);
else
- old_data = (old_data & 0xFFFF) | ((data & 0xFFFF) << 16);
+ old_data = (old_data & 0x0000FFFF) | ((data & 0xFFFF) << 16);
gpu_long_write(offset & 0xFFFFFFC, old_data);
}
return;
}
+ else if ((offset == GPU_WORK_RAM_BASE + 0x0FFF) || (GPU_CONTROL_RAM_BASE + 0x1F))
+ {
+#ifdef GPU_DEBUG
+ WriteLog("GPU: Write16--unaligned write @ %08X [%04X]\n", offset, data);
+ gpu_dump_registers();
+#endif // GPU_DEBUG
+ return;
+ }
-// WriteLog("gpu: writing %.4x at 0x%.8x\n",data,offset);
-//This is done by the blitter...
-//if ((offset >= 0x1FF020 && offset <= 0x1FF03F) || (offset >= 0x1FF820 && offset <= 0x1FF83F))
-// WriteLog("GPU(16): Writing %08X at %08X\n", data, offset);
-//if ((offset >= 0x1FE020 && offset <= 0x1FE03F) || (offset >= 0x1FE820 && offset <= 0x1FE83F))
-// WriteLog("GPU(16): Writing %08X at %08X\n", data, offset);
-//if (offset >= 0xF02200 && offset <= 0xF0229F)
-// WriteLog("GPU(16): Writing to blitter --> %08X at %08X\n", data, offset);
-
+ // Have to be careful here--this can cause an infinite loop!
jaguar_word_write(offset, data);
}
//
// GPU dword access (write)
//
-
void gpu_long_write(unsigned offset, unsigned data)
{
-
- if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
+// if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE + 0x1000))
+ if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFC))
{
#ifdef GPU_DEBUG
if (offset & 0x03)
{
- WriteLog("GPU: Someone is trying an unaligned write @ %08X [%08X]\n", offset, data)
+ WriteLog("GPU: Write32--unaligned write @ %08X [%08X]\n", offset, data);
gpu_dump_registers();
}
-#endif // #ifdef GPU_DEBUG
-/*if (offset == 0xF03000)
-{
- WriteLog("GPU Write [F03000]: %08X\n", data);
-// data = 0x03D0DEAD; // Why isn't this there???
-// data = 0xABCDEFFF; // Why isn't this there???
-}//*/
- gpu_ram_8[offset & 0xFFF] = (data >> 24) & 0xFF,
+#endif // GPU_DEBUG
+
+/* gpu_ram_8[offset & 0xFFF] = (data >> 24) & 0xFF,
gpu_ram_8[(offset+1) & 0xFFF] = (data >> 16) & 0xFF,
gpu_ram_8[(offset+2) & 0xFFF] = (data >> 8) & 0xFF,
- gpu_ram_8[(offset+3) & 0xFFF] = data & 0xFF;
+ gpu_ram_8[(offset+3) & 0xFFF] = data & 0xFF;//*/
+ offset &= 0xFFF;
+ SET32(gpu_ram_8, offset, data);//*/
return;
}
- else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
+// else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
+ else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1C))
{
offset &= 0x1F;
switch (offset)
{
case 0x00:
- /*if (data&0x8)
- gpu_flags=(data&(~0x08))|(gpu_flags&0x08); // update dsp_flags, but keep imask unchanged
- else*/
gpu_flags = data;
- gpu_flag_z = gpu_flags & 0x01;
- gpu_flag_c = (gpu_flags>>1) & 0x01;
- gpu_flag_n = (gpu_flags>>2) & 0x01;
- gpu_update_register_banks();
- gpu_control &= ~((gpu_flags & CINT04FLAGS) >> 3);
- gpu_check_irqs();
+ gpu_flag_z = gpu_flags & ZERO_FLAG;
+ gpu_flag_c = (gpu_flags & CARRY_FLAG) >> 1;
+ gpu_flag_n = (gpu_flags & NEGA_FLAG) >> 2;
+ GPUUpdateRegisterBanks();
+ gpu_control &= ~((gpu_flags & CINT04FLAGS) >> 3); // Interrupt latch clear bits
+//Writing here is only an interrupt enable--this approach is just plain wrong!
+// GPUHandleIRQs();
+//This, however, is A-OK! ;-)
+ if (!(gpu_flags & IMASK) && GPUInterruptPending) // IMASK was cleared
+ {
+ GPUInterruptPending = false;
+ GPUHandleIRQs();
+ }
+#ifdef GPU_DEBUG
+ if (gpu_flags & (INT_ENA0 | INT_ENA1 | INT_ENA2 | INT_ENA3 | INT_ENA4))
+ WriteLog("GPU: Setting interrupt enable! Bits: %02X\n", (gpu_flags >> 4) & 0x1F);
+ WriteLog("GPU: REGPAGE %s...\n", (gpu_flags & REGPAGE ? "set" : "cleared"));
+#endif // GPU_DEBUG
break;
case 0x04:
gpu_matrix_control = data;
gpu_data_organization = data;
break;
case 0x10:
- gpu_pc = data; /*WriteLog("setting gpu pc to 0x%.8x\n",gpu_pc);*/
+ gpu_pc = data;
+#ifdef GPU_DEBUG
+WriteLog("GPU: Setting GPU PC to %08X %s\n", gpu_pc, (GPU_RUNNING ? "(GPU is RUNNING!)" : ""));//*/
+#endif // GPU_DEBUG
break;
case 0x14:
{
- uint32 gpu_was_running = GPU_RUNNING;
-
-// data &= (~0x07C0); // disable writes to irq pending
- data &= (~0xF7C0); // Disable writes to INT_LAT0-4 & TOM version number
- /*if (GPU_RUNNING)
- {
- WriteLog("gpu pc is 0x%.8x\n",gpu_pc);
- fclose(log_get());
- exit(0);
- }*/
- // check for GPU->CPU interrupt
+// uint32 gpu_was_running = GPU_RUNNING;
+ data &= ~0xF7C0; // Disable writes to INT_LAT0-4 & TOM version number
+
+ // check for GPU -> CPU interrupt
if (data & 0x02)
{
-// WriteLog("GPU->CPU interrupt\n");
+//WriteLog("GPU->CPU interrupt\n");
if (tom_irq_enabled(IRQ_GPU))
{
if ((tom_irq_enabled(IRQ_GPU)) && (jaguar_interrupt_handler_is_valid(64)))
{
tom_set_pending_gpu_int();
-// s68000interrupt(7,64);
-// s68000flushInterrupts();
m68k_set_irq(7); // Set 68000 NMI
gpu_releaseTimeslice();
}
-/*
- uint32 addr=jaguar_word_read(((IRQ_GPU+64)<<2)+0);
- addr<<=16;
- addr|=jaguar_word_read(((IRQ_GPU+64)<<2)+2);
- if ((addr)&&(jaguar_interrupt_handler_is_valid(IRQ_GPU+64)))
- {
- s68000interrupt(7,IRQ_GPU+64);
- s68000flushInterrupts();
- }
-*/
}
- data &= ~(0x02);
+ data &= ~0x02;
}
- // check for CPU->GPU interrupt
+
+ // check for CPU -> GPU interrupt #0
if (data & 0x04)
{
- //WriteLog("CPU->GPU interrupt\n");
- gpu_set_irq_line(0, 1);
-// s68000releaseTimeslice();
+//WriteLog("CPU->GPU interrupt\n");
+ GPUSetIRQLine(0, ASSERT_LINE);
m68k_end_timeslice();
dsp_releaseTimeslice();
- data &= ~(0x04);
+ data &= ~0x04;
}
+
// single stepping
if (data & 0x10)
{
//WriteLog("asked to perform a single step (single step is %senabled)\n",(data&0x8)?"":"not ");
}
// gpu_control = (gpu_control & 0x107C0) | (data & (~0x107C0));
- gpu_control = (gpu_control & 0x1F7C0) | (data & (~0x1F7C0));
+ gpu_control = (gpu_control & 0xF7C0) | (data & (~0xF7C0));
// if gpu wasn't running but is now running, execute a few cycles
#ifndef GPU_SINGLE_STEPPING
- if ((!gpu_was_running) && (GPU_RUNNING))
+/* if (!gpu_was_running && GPU_RUNNING)
+#ifdef GPU_DEBUG
+ {
+ WriteLog("GPU: Write32--About to do stupid braindead GPU execution for 200 cycles.\n");
+#endif // GPU_DEBUG
gpu_exec(200);
+#ifdef GPU_DEBUG
+ }
+#endif // GPU_DEBUG//*/
#else
if (gpu_control & 0x18)
gpu_exec(1);
#ifdef GPU_DEBUG
WriteLog("Write to GPU CTRL: %08X ", data);
if (GPU_RUNNING)
- WriteLog("-- Starting to run at %08X...", gpu_pc);
+ WriteLog(" --> Starting to run at %08X...", gpu_pc);
+else
+ WriteLog(" --> Stopped! (GPU_PC: %08X)", gpu_pc);
WriteLog("\n");
-#endif // #ifdef GPU_DEBUG
+#endif // GPU_DEBUG
//if (GPU_RUNNING)
// gpu_dump_disassembly();
+ // (?) If we're set running by the M68K (or DSP?) then end its timeslice to
+ // allow the GPU a chance to run...
+ // Yes! This partially fixed Trevor McFur...
+ if (GPU_RUNNING)
+ m68k_end_timeslice();
break;
}
case 0x18:
return;
}
-//This is done by the blitter...
-//if ((offset >= 0x1FF020 && offset <= 0x1FF03F) || (offset >= 0x1FF820 && offset <= 0x1FF83F))
-// WriteLog("GPU(32): Writing %08X at %08X\n", data, offset);
-//if ((offset >= 0x1FE020 && offset <= 0x1FE03F) || (offset >= 0x1FE820 && offset <= 0x1FE83F))
-// WriteLog("GPU(32): Writing %08X at %08X\n", data, offset);
-//if (offset >= 0xF02200 && offset <= 0xF0229F)
-// WriteLog("GPU(32): Writing to blitter --> %08X at %08X\n", data, offset);
-
jaguar_word_write(offset, (data >> 16) & 0xFFFF);
jaguar_word_write(offset+2, data & 0xFFFF);
}
-void gpu_update_register_banks(void)
+//
+// Change register banks if necessary
+//
+void GPUUpdateRegisterBanks(void)
{
- uint32 temp;
- int bank = (gpu_flags & 0x4000);
-
-// WriteLog("gpu_update_register_banks at gpu pc 0x%.8x bank=%i iflag=%i\n",gpu_pc,bank?1:0,(gpu_flags&0x8)?1:0);
+ int bank = (gpu_flags & 0x4000); // REGPAGE bit
- if (gpu_flags & 0x8)
- bank = 0;
+ if (gpu_flags & 0x0008) // IMASK bit
+ bank = 0; // IMASK forces main bank to be bank 0
- if ((!bank && (gpu_reg_bank_0 != gpu_reg)) || (bank && (gpu_reg_bank_1 != gpu_reg)))
- {
-// WriteLog("\tswitching to bank %i\n",bank?1:0);
- for(int i=0; i<32; i++)
- {
- temp = gpu_reg[i];
- gpu_reg[i] = gpu_alternate_reg[i];
- gpu_alternate_reg[i] = temp;
- }
-
- // switch flags
- temp = gpu_flag_z;
- gpu_flag_z = gpu_alternate_flag_z;
- gpu_alternate_flag_z = temp;
-
- temp = gpu_flag_n;
- gpu_flag_n = gpu_alternate_flag_n;
- gpu_alternate_flag_n = temp;
-
- temp = gpu_flag_c;
- gpu_flag_c = gpu_alternate_flag_c;
- gpu_alternate_flag_c = temp;
-
- if (!bank)
- {
- gpu_reg_bank_0 = gpu_reg;
- gpu_reg_bank_1 = gpu_alternate_reg;
- }
- else
- {
- gpu_reg_bank_0 = gpu_alternate_reg;
- gpu_reg_bank_1 = gpu_reg;
- }
- }
-// else
-// {
-// WriteLog("\tnot switching banks\n");
-// }
+ if (bank)
+ gpu_reg = gpu_reg_bank_1, gpu_alternate_reg = gpu_reg_bank_0;
+ else
+ gpu_reg = gpu_reg_bank_0, gpu_alternate_reg = gpu_reg_bank_1;
}
-void gpu_check_irqs(void)
+void GPUHandleIRQs(void)
{
- int bits, mask, which = 0;
-
- // get the active interrupt bits
- bits = (gpu_control >> 6) & 0x1F;
- bits |= (gpu_control >> 10) & 0x20;
-
- // get the interrupt mask
- mask = (gpu_flags >> 4) & 0x1F;
- mask |= (gpu_flags >> 11) & 0x20;
+ // Get the interrupt latch & enable bits
+ uint32 bits = (gpu_control >> 6) & 0x1F, mask = (gpu_flags >> 4) & 0x1F;
- // bail if nothing is available
+ // Bail out if latched interrupts aren't enabled
bits &= mask;
if (!bits)
return;
- // determine which interrupt
- if (bits & 0x01) which = 0;
- if (bits & 0x02) which = 1;
- if (bits & 0x04) which = 2;
- if (bits & 0x08) which = 3;
- if (bits & 0x10) which = 4;
- if (bits & 0x20) which = 5;
-
- if (gpu_flags & 0x08)
+ // Bail out if we're already in an interrupt! (Note that the order this executes
+ // in is critical--we don't have a pending interrupt unless it's been enabled!)
+ if (gpu_flags & IMASK)
+ {
+ GPUInterruptPending = true;
return;
+ }
+
+ // Determine which interrupt to service
+ uint32 which = 0; //Isn't there a #pragma to disable this warning???
+ if (bits & 0x01)
+ which = 0;
+ if (bits & 0x02)
+ which = 1;
+ if (bits & 0x04)
+ which = 2;
+ if (bits & 0x08)
+ which = 3;
+ if (bits & 0x10)
+ which = 4;
if (start_logging)
- WriteLog("GPU: generating irq %i\n", which);
+ WriteLog("GPU: Generating IRQ #%i\n", which);
// set the interrupt flag
- gpu_flags |= 0x08;
- gpu_update_register_banks();
+ gpu_flags |= IMASK;
+ GPUUpdateRegisterBanks();
// subqt #4,r31 ; pre-decrement stack pointer
// move pc,r30 ; address of interrupted code
gpu_reg[30] = gpu_pc;
}
-void gpu_set_irq_line(int irqline, int state)
+void GPUSetIRQLine(int irqline, int state)
{
if (start_logging)
- WriteLog("GPU: setting irg line %i\n", irqline);
- int mask = 0x40 << irqline;
- gpu_control &= ~mask;
+ WriteLog("GPU: Setting GPU IRQ line #%i\n", irqline);
+
+ uint32 mask = 0x0040 << irqline;
+ gpu_control &= ~mask; // Clear the interrupt latch
if (state)
{
- gpu_control |= mask;
- gpu_check_irqs();
+ gpu_control |= mask; // Assert the interrupt latch
+ GPUHandleIRQs(); // And handle the interrupt...
}
}
void gpu_init(void)
{
- memory_malloc_secure((void **)&gpu_ram_8, 0x1000, "GPU work ram");
-// gpu_ram_16=(uint16*)gpu_ram_8;
-// gpu_ram_32=(uint32*)gpu_ram_8;
+ memory_malloc_secure((void **)&gpu_ram_8, 0x1000, "GPU work RAM");
+// memory_malloc_secure((void **)&gpu_reg, 32*sizeof(int32), "GPU bank 0 regs");
+// memory_malloc_secure((void **)&gpu_alternate_reg, 32*sizeof(int32), "GPU bank 1 regs");
+ memory_malloc_secure((void **)&gpu_reg_bank_0, 32 * sizeof(int32), "GPU bank 0 regs");
+ memory_malloc_secure((void **)&gpu_reg_bank_1, 32 * sizeof(int32), "GPU bank 1 regs");
- memory_malloc_secure((void **)&gpu_reg, 32*sizeof(int32), "GPU bank 0 regs");
- memory_malloc_secure((void **)&gpu_alternate_reg, 32*sizeof(int32), "GPU bank 1 regs");
-
build_branch_condition_table();
gpu_reset();
void gpu_reset(void)
{
- gpu_pc = 0x00F03000;
- gpu_acc = 0x00000000;
- gpu_remain = 0x00000000;
- gpu_hidata = 0x00000000;
- gpu_flags = 0x00040000;
+ // GPU registers (directly visible)
+ gpu_flags = 0x00000000;
gpu_matrix_control = 0x00000000;
gpu_pointer_to_matrix = 0x00000000;
gpu_data_organization = 0xFFFFFFFF;
- gpu_control = 0x00012800; // Correctly sets this a TOM Rev. 2
+ gpu_pc = 0x00F03000;
+ gpu_control = 0x00002800; // Correctly sets this as TOM Rev. 2
+ gpu_hidata = 0x00000000;
+ gpu_remain = 0x00000000; // These two registers are RO/WO
gpu_div_control = 0x00000000;
- gpu_in_exec = 0;
- for(int i=0; i<32; i++)
- {
- gpu_reg[i] = 0x00000000;
- gpu_alternate_reg[i] = 0x00000000;
- }
-
- gpu_reg_bank_0 = gpu_reg;
- gpu_reg_bank_1 = gpu_alternate_reg;
-// gpu_reg_bank_1 = gpu_reg;
-// gpu_reg_bank_0 = gpu_alternate_reg;
+ // GPU internal register
+ gpu_acc = 0x00000000;
- CLR_ZNC;
+ gpu_reg = gpu_reg_bank_0;
+ gpu_alternate_reg = gpu_reg_bank_1;
- gpu_alternate_flag_z = 0;
- gpu_alternate_flag_n = 0;
- gpu_alternate_flag_c = 0;
+ for(int i=0; i<32; i++)
+ gpu_reg[i] = gpu_alternate_reg[i] = 0x00000000;
+ CLR_ZNC;
memset(gpu_ram_8, 0xFF, 0x1000);
-
+ gpu_in_exec = 0;
+ GPUInterruptPending = false;
gpu_reset_stats();
}
{
WriteLog("GPU: stopped at PC=%08X (GPU %s running)\n", (unsigned int)gpu_pc, GPU_RUNNING ? "was" : "wasn't");
- // get the active interrupt bits
- int bits = (gpu_control >> 6) & 0x1F;
- bits |= (gpu_control >> 10) & 0x20;
-
- // get the interrupt mask
- int mask = (gpu_flags >> 4) & 0x1F;
- mask |= (gpu_flags >> 11) & 0x20;
-
+ // Get the interrupt latch & enable bits
+ uint8 bits = (gpu_control >> 6) & 0x1F, mask = (gpu_flags >> 4) & 0x1F;
+ WriteLog("GPU: Latch bits = %02X, enable bits = %02X\n", bits, mask);
- WriteLog("GPU: ibits=0x%.8x imask=0x%.8x\n", bits, mask);
// WriteLog("\nregisters bank 0\n");
// for (int j=0;j<8;j++)
// {
//
// Main GPU execution core
//
-
static int testCount = 1;
static int len = 0;
void gpu_exec(int32 cycles)
gpu_control &= ~0x10;
}
#endif
- gpu_check_irqs();
+ GPUHandleIRQs();
gpu_releaseTimeSlice_flag = 0;
gpu_in_exec++;
if (gpu_start_log)
{
- gpu_reset_stats();
+// gpu_reset_stats();
static char buffer[512];
dasmjag(JAGUAR_GPU, buffer, gpu_pc);
WriteLog("GPU: [%08X] %s (RM=%08X, RN=%08X) -> ", gpu_pc, buffer, RM, RN);
static void gpu_opcode_add(void)
{
-/* int dreg = jaguar.op & 31;
- UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
- UINT32 r2 = jaguar.r[dreg];
- UINT32 res = r2 + r1;
- jaguar.r[dreg] = res;
- CLR_ZNC; SET_ZNC_ADD(r2,r1,res);*/
-
+#ifdef GPU_DIS_ADD
+ WriteLog("%06X: ADD R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
+#endif
UINT32 res = RN + RM;
CLR_ZNC; SET_ZNC_ADD(RN, RM, res);
RN = res;
+#ifdef GPU_DIS_ADD
+ WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
+#endif
}
static void gpu_opcode_addc(void)
static void gpu_opcode_addq(void)
{
-/* int dreg = jaguar.op & 31;
- UINT32 r1 = convert_zero[(jaguar.op >> 5) & 31];
- UINT32 r2 = jaguar.r[dreg];
- UINT32 res = r2 + r1;
- jaguar.r[dreg] = res;
- CLR_ZNC; SET_ZNC_ADD(r2,r1,res);*/
-
+#ifdef GPU_DIS_ADDQ
+ WriteLog("%06X: ADDQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", gpu_pc-2, gpu_convert_zero[IMM_1], IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
+#endif
UINT32 r1 = gpu_convert_zero[IMM_1];
UINT32 res = RN + r1;
CLR_ZNC; SET_ZNC_ADD(RN, r1, res);
RN = res;
+#ifdef GPU_DIS_ADDQ
+ WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
+#endif
}
static void gpu_opcode_addqt(void)
{
+#ifdef GPU_DIS_ADDQT
+ WriteLog("%06X: ADDQT #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", gpu_pc-2, gpu_convert_zero[IMM_1], IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
+#endif
RN += gpu_convert_zero[IMM_1];
+#ifdef GPU_DIS_ADDQT
+ WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
+#endif
}
static void gpu_opcode_sub(void)
{
-/* int dreg = jaguar.op & 31;
- UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
- UINT32 r2 = jaguar.r[dreg];
- UINT32 res = r2 - r1;
- jaguar.r[dreg] = res;
- CLR_ZNC; SET_ZNC_SUB(r2,r1,res);*/
-
+#ifdef GPU_DIS_SUB
+ WriteLog("%06X: SUB R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
+#endif
UINT32 res = RN - RM;
SET_ZNC_SUB(RN, RM, res);
RN = res;
+#ifdef GPU_DIS_SUB
+ WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
+#endif
}
static void gpu_opcode_subc(void)
static void gpu_opcode_subq(void)
{
+#ifdef GPU_DIS_SUBQ
+ WriteLog("%06X: SUBQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", gpu_pc-2, gpu_convert_zero[IMM_1], IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
+#endif
UINT32 r1 = gpu_convert_zero[IMM_1];
UINT32 res = RN - r1;
SET_ZNC_SUB(RN, r1, res);
RN = res;
+#ifdef GPU_DIS_SUBQ
+ WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
+#endif
}
static void gpu_opcode_subqt(void)
{
+#ifdef GPU_DIS_SUBQT
+ WriteLog("%06X: SUBQT #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", gpu_pc-2, gpu_convert_zero[IMM_1], IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
+#endif
RN -= gpu_convert_zero[IMM_1];
+#ifdef GPU_DIS_SUBQT
+ WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
+#endif
}
static void gpu_opcode_cmp(void)
static void gpu_opcode_cmpq(void)
{
+ static int32 sqtable[32] =
+ { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1 };
#ifdef GPU_DIS_CMPQ
WriteLog("%06X: CMPQ #%d, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", gpu_pc-2, sqtable[IMM_1], IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
#endif
- static int32 sqtable[32] =
- { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1 };
-
UINT32 r1 = sqtable[IMM_1 & 0x1F]; // I like this better -> (INT8)(jaguar.op >> 2) >> 3;
UINT32 res = RN - r1;
SET_ZNC_SUB(RN, r1, res);
static void gpu_opcode_and(void)
{
+#ifdef GPU_DIS_AND
+ WriteLog("%06X: AND R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
+#endif
RN = RN & RM;
SET_ZN(RN);
+#ifdef GPU_DIS_AND
+ WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
+#endif
}
static void gpu_opcode_or(void)
{
+#ifdef GPU_DIS_OR
+ WriteLog("%06X: OR R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
+#endif
RN = RN | RM;
SET_ZN(RN);
+#ifdef GPU_DIS_OR
+ WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
+#endif
}
static void gpu_opcode_xor(void)
{
+#ifdef GPU_DIS_XOR
+ WriteLog("%06X: XOR R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
+#endif
RN = RN ^ RM;
SET_ZN(RN);
+#ifdef GPU_DIS_XOR
+ WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
+#endif
}
static void gpu_opcode_not(void)
{
+#ifdef GPU_DIS_NOT
+ WriteLog("%06X: NOT R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
+#endif
RN = ~RN;
SET_ZN(RN);
+#ifdef GPU_DIS_NOT
+ WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
+#endif
}
static void gpu_opcode_move_pc(void)
{
+#ifdef GPU_DIS_MOVEPC
+ WriteLog("%06X: MOVE PC, R%02u [NCZ:%u%u%u, PC=%08X, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, gpu_pc-2, IMM_2, RN);
+#endif
// Should be previous PC--this might not always be previous instruction!
// Then again, this will point right at the *current* instruction, i.e., MOVE PC,R!
RN = gpu_pc - 2;
+#ifdef GPU_DIS_MOVEPC
+ WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
+#endif
}
static void gpu_opcode_sat8(void)
{
+#ifdef GPU_DIS_SAT8
+ WriteLog("%06X: SAT8 R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", gpu_pc-2, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
+#endif
RN = ((int32)RN < 0 ? 0 : (RN > 0xFF ? 0xFF : RN));
SET_ZN(RN);
+#ifdef GPU_DIS_SAT8
+ WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
+#endif
}
static void gpu_opcode_sat16(void)
static void gpu_opcode_store_r14_indexed(void)
{
+#ifdef GPU_DIS_STORE14I
+ WriteLog("%06X: STORE R%02u, (R14+$%02X) [NCZ:%u%u%u, R%02u=%08X, R14+$%02X=%08X]\n", gpu_pc-2, IMM_2, gpu_convert_zero[IMM_1] << 2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN, gpu_convert_zero[IMM_1] << 2, gpu_reg[14]+(gpu_convert_zero[IMM_1] << 2));
+#endif
gpu_long_write(gpu_reg[14] + (gpu_convert_zero[IMM_1] << 2), RN);
}
static void gpu_opcode_store_r15_indexed(void)
{
+#ifdef GPU_DIS_STORE15I
+ WriteLog("%06X: STORE R%02u, (R15+$%02X) [NCZ:%u%u%u, R%02u=%08X, R15+$%02X=%08X]\n", gpu_pc-2, IMM_2, gpu_convert_zero[IMM_1] << 2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN, gpu_convert_zero[IMM_1] << 2, gpu_reg[15]+(gpu_convert_zero[IMM_1] << 2));
+#endif
gpu_long_write(gpu_reg[15] + (gpu_convert_zero[IMM_1] << 2), RN);
}
static void gpu_opcode_load_r14_ri(void)
{
+#ifdef GPU_DIS_LOAD14R
+ WriteLog("%06X: LOAD (R14+R%02u), R%02u [NCZ:%u%u%u, R14+R%02u=%08X, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM+gpu_reg[14], IMM_2, RN);
+#endif
RN = gpu_long_read(gpu_reg[14] + RM);
+#ifdef GPU_DIS_LOAD14R
+ WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
+#endif
}
static void gpu_opcode_load_r15_ri(void)
{
+#ifdef GPU_DIS_LOAD15R
+ WriteLog("%06X: LOAD (R15+R%02u), R%02u [NCZ:%u%u%u, R15+R%02u=%08X, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM+gpu_reg[15], IMM_2, RN);
+#endif
RN = gpu_long_read(gpu_reg[15] + RM);
+#ifdef GPU_DIS_LOAD15R
+ WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
+#endif
}
static void gpu_opcode_store_r14_ri(void)
static void gpu_opcode_pack(void)
{
+#ifdef GPU_DIS_PACK
+ WriteLog("%06X: %s R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", gpu_pc-2, (!IMM_1 ? "PACK " : "UNPACK"), IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
+#endif
uint32 val = RN;
- if (RM == 0) // Pack
+//BUG! if (RM == 0) // Pack
+ if (IMM_1 == 0) // Pack
RN = ((val >> 10) & 0x0000F000) | ((val >> 5) & 0x00000F00) | (val & 0x000000FF);
else // Unpack
RN = ((val & 0x0000F000) << 10) | ((val & 0x00000F00) << 5) | (val & 0x000000FF);
+#ifdef GPU_DIS_PACK
+ WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
+#endif
}
static void gpu_opcode_storeb(void)
{
+#ifdef GPU_DIS_STOREB
+ WriteLog("%06X: STOREB R%02u, (R%02u) [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", gpu_pc-2, IMM_2, IMM_1, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN, IMM_1, RM);
+#endif
//Is this right???
// Would appear to be so...!
if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
static void gpu_opcode_storew(void)
{
+#ifdef GPU_DIS_STOREW
+ WriteLog("%06X: STOREW R%02u, (R%02u) [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", gpu_pc-2, IMM_2, IMM_1, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN, IMM_1, RM);
+#endif
if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
gpu_long_write(RM, RN & 0xFFFF);
else
static void gpu_opcode_store(void)
{
+#ifdef GPU_DIS_STORE
+ WriteLog("%06X: STORE R%02u, (R%02u) [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", gpu_pc-2, IMM_2, IMM_1, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN, IMM_1, RM);
+#endif
gpu_long_write(RM, RN);
}
static void gpu_opcode_loadb(void)
{
+#ifdef GPU_DIS_LOADB
+ WriteLog("%06X: LOADB (R%02u), R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
+#endif
if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
RN = gpu_long_read(RM) & 0xFF;
else
RN = jaguar_byte_read(RM);
+#ifdef GPU_DIS_LOADB
+ WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
+#endif
}
static void gpu_opcode_loadw(void)
{
+#ifdef GPU_DIS_LOADW
+ WriteLog("%06X: LOADW (R%02u), R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
+#endif
if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
RN = gpu_long_read(RM) & 0xFFFF;
else
RN = jaguar_word_read(RM);
+#ifdef GPU_DIS_LOADW
+ WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
+#endif
}
static void gpu_opcode_load(void)
{
+#ifdef GPU_DIS_LOAD
+ WriteLog("%06X: LOAD (R%02u), R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
+#endif
RN = gpu_long_read(RM);
+#ifdef GPU_DIS_LOAD
+ WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
+#endif
}
static void gpu_opcode_loadp(void)
static void gpu_opcode_load_r14_indexed(void)
{
+#ifdef GPU_DIS_LOAD14I
+ WriteLog("%06X: LOAD (R14+$%02X), R%02u [NCZ:%u%u%u, R14+$%02X=%08X, R%02u=%08X] -> ", gpu_pc-2, gpu_convert_zero[IMM_1] << 2, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, gpu_convert_zero[IMM_1] << 2, gpu_reg[14]+(gpu_convert_zero[IMM_1] << 2), IMM_2, RN);
+#endif
RN = gpu_long_read(gpu_reg[14] + (gpu_convert_zero[IMM_1] << 2));
+#ifdef GPU_DIS_LOAD14I
+ WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
+#endif
}
static void gpu_opcode_load_r15_indexed(void)
{
+#ifdef GPU_DIS_LOAD15I
+ WriteLog("%06X: LOAD (R15+$%02X), R%02u [NCZ:%u%u%u, R15+$%02X=%08X, R%02u=%08X] -> ", gpu_pc-2, gpu_convert_zero[IMM_1] << 2, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, gpu_convert_zero[IMM_1] << 2, gpu_reg[15]+(gpu_convert_zero[IMM_1] << 2), IMM_2, RN);
+#endif
RN = gpu_long_read(gpu_reg[15] + (gpu_convert_zero[IMM_1] << 2));
+#ifdef GPU_DIS_LOAD15I
+ WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
+#endif
}
static void gpu_opcode_movei(void)
{
+#ifdef GPU_DIS_MOVEI
+ WriteLog("%06X: MOVEI #$%08X, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", gpu_pc-2, (uint32)gpu_word_read(gpu_pc) | ((uint32)gpu_word_read(gpu_pc + 2) << 16), IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
+#endif
// This instruction is followed by 32-bit value in LSW / MSW format...
RN = (uint32)gpu_word_read(gpu_pc) | ((uint32)gpu_word_read(gpu_pc + 2) << 16);
gpu_pc += 4;
+#ifdef GPU_DIS_MOVEI
+ WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
+#endif
}
static void gpu_opcode_moveta(void)
{
+#ifdef GPU_DIS_MOVETA
+ WriteLog("%06X: MOVETA R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u(alt)=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, ALTERNATE_RN);
+#endif
ALTERNATE_RN = RM;
+#ifdef GPU_DIS_MOVETA
+ WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u(alt)=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, ALTERNATE_RN);
+#endif
}
static void gpu_opcode_movefa(void)
{
+#ifdef GPU_DIS_MOVEFA
+ WriteLog("%06X: MOVEFA R%02u, R%02u [NCZ:%u%u%u, R%02u(alt)=%08X, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, ALTERNATE_RM, IMM_2, RN);
+#endif
RN = ALTERNATE_RM;
+#ifdef GPU_DIS_MOVEFA
+ WriteLog("[NCZ:%u%u%u, R%02u(alt)=%08X, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, ALTERNATE_RM, IMM_2, RN);
+#endif
}
static void gpu_opcode_move(void)
{
+#ifdef GPU_DIS_MOVE
+ WriteLog("%06X: MOVE R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
+#endif
RN = RM;
+#ifdef GPU_DIS_MOVE
+ WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
+#endif
}
static void gpu_opcode_moveq(void)
{
- RN = IMM_1;
+#ifdef GPU_DIS_MOVEQ
+ WriteLog("%06X: MOVEQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
+#endif
+ RN = IMM_1;
+#ifdef GPU_DIS_MOVEQ
+ WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
+#endif
}
static void gpu_opcode_resmac(void)
static void gpu_opcode_imult(void)
{
+#ifdef GPU_DIS_IMULT
+ WriteLog("%06X: IMULT R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
+#endif
RN = (int16)RN * (int16)RM;
SET_ZN(RN);
+#ifdef GPU_DIS_IMULT
+ WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
+#endif
}
static void gpu_opcode_mult(void)
{
+#ifdef GPU_DIS_MULT
+ WriteLog("%06X: MULT R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
+#endif
RN = (uint16)RM * (uint16)RN;
SET_ZN(RN);
+#ifdef GPU_DIS_MULT
+ WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
+#endif
}
static void gpu_opcode_bclr(void)
{
+#ifdef GPU_DIS_BCLR
+ WriteLog("%06X: BCLR #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
+#endif
UINT32 res = RN & ~(1 << IMM_1);
RN = res;
SET_ZN(res);
+#ifdef GPU_DIS_BCLR
+ WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
+#endif
}
static void gpu_opcode_btst(void)
{
+#ifdef GPU_DIS_BTST
+ WriteLog("%06X: BTST #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
+#endif
gpu_flag_z = (~RN >> IMM_1) & 1;
+#ifdef GPU_DIS_BTST
+ WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
+#endif
}
static void gpu_opcode_bset(void)
{
+#ifdef GPU_DIS_BSET
+ WriteLog("%06X: BSET #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
+#endif
UINT32 res = RN | (1 << IMM_1);
RN = res;
SET_ZN(res);
+#ifdef GPU_DIS_BSET
+ WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
+#endif
}
static void gpu_opcode_imacn(void)
static void gpu_opcode_neg(void)
{
+#ifdef GPU_DIS_NEG
+ WriteLog("%06X: NEG R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", gpu_pc-2, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
+#endif
UINT32 res = -RN;
SET_ZNC_SUB(0, RN, res);
RN = res;
+#ifdef GPU_DIS_NEG
+ WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
+#endif
}
static void gpu_opcode_shlq(void)
{
int result = 1;
if (j & 1)
- if (i & ZFLAG) result = 0;
+ if (i & ZERO_FLAG) result = 0;
if (j & 2)
- if (!(i & ZFLAG)) result = 0;
+ if (!(i & ZERO_FLAG)) result = 0;
if (j & 4)
- if (i & (CFLAG << (j >> 4))) result = 0;
+ if (i & (CARRY_FLAG << (j >> 4))) result = 0;
if (j & 8)
- if (!(i & (CFLAG << (j >> 4)))) result = 0;
+ if (!(i & (CARRY_FLAG << (j >> 4)))) result = 0;
condition_table[i * 32 + j] = result;
}
}
void blitter_long_write(uint32 offset, uint32 data);
uint32 blitter_reg_read(uint32 offset);
void blitter_reg_write(uint32 offset, uint32 data);
+
extern uint8 blitter_working;
#endif
#define GPU_CONTROL_RAM_BASE 0x00F02100
#define GPU_WORK_RAM_BASE 0x00F03000
+#define ASSERT_LINE 1
+#define CLEAR_LINE 0
+
void gpu_init(void);
void gpu_reset(void);
void gpu_exec(int32);
void gpu_done(void);
void gpu_update_register_banks(void);
-void gpu_check_irqs(void);
-void gpu_set_irq_line(int irqline, int state);
+void GPUHandleIRQs(void);
+void GPUSetIRQLine(int irqline, int state);
unsigned gpu_byte_read(unsigned int offset);
unsigned gpu_word_read(unsigned int offset);
unsigned gpu_long_read(unsigned int offset);
void gpu_reset_stats(void);
uint32 gpu_read_pc(void);
-#endif // #ifndef __GPU_H__
+#endif // __GPU_H__
uint32 jaguar_interrupt_handler_is_valid(uint32 i);
void jaguar_dasm(uint32 offset, uint32 qt);
+//New stuff...
+void JaguarExecute(int16 * backbuffer, bool render);
+
// Some handy macros to help converting native endian to big endian (jaguar native)
// & vice versa
-#define SET32(r, a, v) r[a] = ((v) & 0xFF000000) >> 24, r[a+1] = ((v) & 0x00FF0000) >> 16, \
- r[a+2] = ((v) & 0x0000FF00) >> 8, r[a+3] = (v) & 0x000000FF
-#define GET32(r, a) ((r[a] << 24) | (r[a+1] << 16) | (r[a+2] << 8) | r[a+3])
-#define SET16(r, a, v) r[a] = ((v) & 0xFF00) >> 8, r[a+1] = (v) & 0xFF
-#define GET16(r, a) ((r[a] << 8) | r[a+1])
+#define SET32(r, a, v) r[(a)] = ((v) & 0xFF000000) >> 24, r[(a)+1] = ((v) & 0x00FF0000) >> 16, \
+ r[(a)+2] = ((v) & 0x0000FF00) >> 8, r[(a)+3] = (v) & 0x000000FF
+#define GET32(r, a) ((r[(a)] << 24) | (r[(a)+1] << 16) | (r[(a)+2] << 8) | r[(a)+3])
+#define SET16(r, a, v) r[(a)] = ((v) & 0xFF00) >> 8, r[(a)+1] = (v) & 0xFF
+#define GET16(r, a) ((r[(a)] << 8) | r[(a)+1])
//Temp debug stuff
void DumpMainMemory(void);
uint8 * GetRamPtr(void);
-#endif // #ifndef __JAGUAR_H__
+#endif // __JAGUAR_H__
#include "jaguar.h"
-#define TOM_VBLANK_DURATION_IN_SCANLINES 25
+//#define TOM_VBLANK_DURATION_IN_SCANLINES 25
#define VIDEO_MODE_16BPP_CRY 0
#define VIDEO_MODE_24BPP_RGB 1
uint16 tom_get_scanline(void);
uint32 tom_getHBlankWidthInPixels(void);
-// Interrupts
+// 68000 Interrupt bit positions (enabled at $F000E0)
-#define IRQ_VBLANK 0
+/*#define IRQ_VBLANK 0
#define IRQ_GPU 1
#define IRQ_HBLANK 2
#define IRQ_OPFLAG IRQ_HBLANK
#define IRQ_TIMER 3
-#define IRQ_DSP 4
+#define IRQ_DSP 4*/
+enum { IRQ_VBLANK = 0, IRQ_GPU, IRQ_OPFLAG, IRQ_TIMER, IRQ_DSP };
int tom_irq_enabled(int irq);
uint16 tom_irq_control_reg(void);
void tom_set_pending_video_int(void);
void tom_reset_timer(void);
+uint32 TOMGetSDLScreenPitch(void);
+
#endif // __TOM_H__
+++ /dev/null
- uint8 *paletteRam=&tom_ram_8[0x400];
- paletteRam+=(idx<<2);
-
- if (flags&FLAGS_HFLIP)
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(cnt>>19));
- c=(c>>(8-((cnt>>16)&0x07)))&0x01;
- if (flags&FLAGS_TRANSPARENT)
- {
- if (c)
- {
- *current_line_buffer--=paletteRam[(c<<1)+0];
- *current_line_buffer--=paletteRam[(c<<1)+1];
- }
- else
- current_line_buffer-=2;
- }
- else
- {
- *current_line_buffer--=paletteRam[(c<<1)+0];
- *current_line_buffer--=paletteRam[(c<<1)+1];
- }
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- else
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(cnt>>19));
- c=(c>>(8-((cnt>>16)&0x07)))&0x01;
- if (flags&FLAGS_TRANSPARENT)
- {
- if (c)
- {
- *current_line_buffer++=paletteRam[(c<<1)+0];
- *current_line_buffer++=paletteRam[(c<<1)+1];
- }
- else
- current_line_buffer+=2;
- }
- else
- {
- *current_line_buffer++=paletteRam[(c<<1)+0];
- *current_line_buffer++=paletteRam[(c<<1)+1];
- }
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
+++ /dev/null
- if (flags & FLAGS_READMODIFY)
- {
- if (flags & FLAGS_HFLIP)
- {
- if (flags & FLAGS_TRANSPARENT)
- {
- while (scaled_width)
- {
- uint16 c = jaguar_byte_read(ptr + ((cnt >> 16) << 1) + 0);
- c <<= 8;
- c |= jaguar_byte_read(ptr + ((cnt >> 16) << 1) + 1);
- if (c)
- {
- *current_line_buffer-- = BLEND_Y(*current_line_buffer, c >> 8);
- *current_line_buffer-- = BLEND_CC(*current_line_buffer, c & 0xFF);
- }
- else
- current_line_buffer -= 2;
- cnt += hscale_fixed;
- scaled_width--;
- }
- }
- else
- {
- while (scaled_width)
- {
- *current_line_buffer-- = BLEND_Y(*current_line_buffer, jaguar_byte_read(ptr+((cnt>>16)<<1)+0));
- *current_line_buffer-- = BLEND_CC(*current_line_buffer, jaguar_byte_read(ptr+((cnt>>16)<<1)+1));
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- }
- else
- {
- if (flags&FLAGS_TRANSPARENT)
- {
- while (scaled_width)
- {
- uint16 c=jaguar_byte_read(ptr+((cnt>>16)<<1)+0);;
- c<<=8;
- c|=jaguar_byte_read(ptr+((cnt>>16)<<1)+1);
- if (c)
- {
- *current_line_buffer++=BLEND_Y(*current_line_buffer,(c>>8));
- *current_line_buffer++=BLEND_CC(*current_line_buffer,(c&0xff));
- }
- else
- current_line_buffer+=2;
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- else
- {
- while (scaled_width)
- {
- *current_line_buffer++=BLEND_Y(*current_line_buffer,jaguar_byte_read(ptr+((cnt>>16)<<1)+0));
- *current_line_buffer++=BLEND_CC(*current_line_buffer,jaguar_byte_read(ptr+((cnt>>16)<<1)+1));
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- }
- }
- else
- {
- if (flags&FLAGS_HFLIP)
- {
- if (flags&FLAGS_TRANSPARENT)
- {
- while (scaled_width)
- {
- uint16 c=jaguar_byte_read(ptr+((cnt>>16)<<1)+0);;
- c<<=8;
- c|=jaguar_byte_read(ptr+((cnt>>16)<<1)+1);
- if (c)
- {
- *current_line_buffer--=(c>>8);
- *current_line_buffer--=(c&0xff);
- }
- else
- current_line_buffer-=2;
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- else
- {
- while (scaled_width)
- {
- *current_line_buffer--=jaguar_byte_read(ptr+((cnt>>16)<<1)+0);
- *current_line_buffer--=jaguar_byte_read(ptr+((cnt>>16)<<1)+1);
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- }
- else
- {
- if (flags & FLAGS_TRANSPARENT)
- {
- while (scaled_width)
- {
- uint16 c = jaguar_byte_read(ptr + ((cnt >> 16) << 1) + 0);
- c <<= 8;
- c |= jaguar_byte_read(ptr + ((cnt >> 16) << 1) + 1);
- if (c)
- {
- *current_line_buffer++ = c >> 8;
- *current_line_buffer++ = c & 0xFF;
- }
- else
- current_line_buffer += 2;
- cnt += hscale_fixed;
- scaled_width--;
- }
- }
- else
- {
- while (scaled_width)
- {
- *current_line_buffer++ = jaguar_byte_read(ptr + ((cnt >> 16) << 1) + 0);
- *current_line_buffer++ = jaguar_byte_read(ptr + ((cnt >> 16) << 1) + 1);
- cnt += hscale_fixed;
- scaled_width--;
- }
- }
- }
- }
+++ /dev/null
- if (flags&FLAGS_READMODIFY)
- {
- if (flags&FLAGS_HFLIP)
- {
- if (flags&FLAGS_TRANSPARENT)
- {
- while (scaled_width)
- {
- uint16 c=jaguar_byte_read(ptr+((((cnt>>16) & (~0x3))*pitch)+((cnt>>16)&0x3)<<1)+0);;
- c<<=8;
- c|=jaguar_byte_read(ptr+((((cnt>>16) & (~0x3))*pitch)+((cnt>>16)&0x3)<<1)+1);
- if (c)
- {
- *current_line_buffer--=BLEND_Y(*current_line_buffer,(c>>8));
- *current_line_buffer--=BLEND_CC(*current_line_buffer,(c&0xff));
- }
- else
- current_line_buffer-=2;
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- else
- {
- while (scaled_width)
- {
- *current_line_buffer--=BLEND_Y(*current_line_buffer,jaguar_byte_read(ptr+((((cnt>>16) & (~0x3))*pitch)+((cnt>>16)&0x3)<<1)+0));
- *current_line_buffer--=BLEND_CC(*current_line_buffer,jaguar_byte_read(ptr+((((cnt>>16) & (~0x3))*pitch)+((cnt>>16)&0x3)<<1)+1));
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- }
- else
- {
- if (flags&FLAGS_TRANSPARENT)
- {
- while (scaled_width)
- {
- uint16 c=jaguar_byte_read(ptr+((((cnt>>16) & (~0x3))*pitch)+((cnt>>16)&0x3)<<1)+0);;
- c<<=8;
- c|=jaguar_byte_read(ptr+((((cnt>>16) & (~0x3))*pitch)+((cnt>>16)&0x3)<<1)+1);
- if (c)
- {
- *current_line_buffer++=BLEND_Y(*current_line_buffer,(c>>8));
- *current_line_buffer++=BLEND_CC(*current_line_buffer,(c&0xff));
- }
- else
- current_line_buffer+=2;
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- else
- {
- while (scaled_width)
- {
- *current_line_buffer++=BLEND_Y(*current_line_buffer,jaguar_byte_read(ptr+((((cnt>>16) & (~0x3))*pitch)+((cnt>>16)&0x3)<<1)+0));
- *current_line_buffer++=BLEND_CC(*current_line_buffer,jaguar_byte_read(ptr+((((cnt>>16) & (~0x3))*pitch)+((cnt>>16)&0x3)<<1)+1));
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- }
- }
- else
- {
- if (flags&FLAGS_HFLIP)
- {
- if (flags&FLAGS_TRANSPARENT)
- {
- while (scaled_width)
- {
- uint16 c=jaguar_byte_read(ptr+((((cnt>>16) & (~0x3))*pitch)+((cnt>>16)&0x3)<<1)+0);;
- c<<=8;
- c|=jaguar_byte_read(ptr+((((cnt>>16) & (~0x3))*pitch)+((cnt>>16)&0x3)<<1)+1);
- if (c)
- {
- *current_line_buffer--=(c>>8);
- *current_line_buffer--=(c&0xff);
- }
- else
- current_line_buffer-=2;
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- else
- {
- while (scaled_width)
- {
- *current_line_buffer--=jaguar_byte_read(ptr+((((cnt>>16) & (~0x3))*pitch)+((cnt>>16)&0x3)<<1)+0);
- *current_line_buffer--=jaguar_byte_read(ptr+((((cnt>>16) & (~0x3))*pitch)+((cnt>>16)&0x3)<<1)+1);
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- }
- else
- {
- if (flags&FLAGS_TRANSPARENT)
- {
- while (scaled_width)
- {
- uint16 c=jaguar_byte_read(ptr+((((cnt>>16) & (~0x3))*pitch)+((cnt>>16)&0x3)<<1)+0);;
- c<<=8;
- c|=jaguar_byte_read(ptr+((((cnt>>16) & (~0x3))*pitch)+((cnt>>16)&0x3)<<1)+1);
- if (c)
- {
- *current_line_buffer++=(c>>8);
- *current_line_buffer++=(c&0xff);
- }
- else
- current_line_buffer+=2;
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- else
- {
- while (scaled_width)
- {
- *current_line_buffer++=jaguar_byte_read(ptr+((((cnt>>16) & (~0x3))*pitch)+((cnt>>16)&0x3)<<1)+0);
- *current_line_buffer++=jaguar_byte_read(ptr+((((cnt>>16) & (~0x3))*pitch)+((cnt>>16)&0x3)<<1)+1);
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- }
- }
+++ /dev/null
- uint8 *paletteRam=&tom_ram_8[0x400];
- paletteRam+=(idx<<2);
-
- if (flags&FLAGS_HFLIP)
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(((cnt>>16) & (~0x3f))*pitch)+((cnt>>16)&0x3f));
- c=(c>>(8-((cnt>>16)&0x07)))&0x01;
- if (flags&FLAGS_TRANSPARENT)
- {
- if (c)
- {
- *current_line_buffer--=paletteRam[(c<<1)+0];
- *current_line_buffer--=paletteRam[(c<<1)+1];
- }
- else
- current_line_buffer-=2;
- }
- else
- {
- *current_line_buffer--=paletteRam[(c<<1)+0];
- *current_line_buffer--=paletteRam[(c<<1)+1];
- }
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- else
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(((cnt>>16) & (~0x3f))*pitch)+((cnt>>16)&0x3f));
- c=(c>>(8-((cnt>>16)&0x07)))&0x01;
- if (flags&FLAGS_TRANSPARENT)
- {
- if (c)
- {
- *current_line_buffer++=paletteRam[(c<<1)+0];
- *current_line_buffer++=paletteRam[(c<<1)+1];
- }
- else
- current_line_buffer+=2;
- }
- else
- {
- *current_line_buffer++=paletteRam[(c<<1)+0];
- *current_line_buffer++=paletteRam[(c<<1)+1];
- }
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
+++ /dev/null
- uint8 *paletteRam=&tom_ram_8[0x400];
- paletteRam+=idx*2;
-
- if (flags&FLAGS_READMODIFY)
- {
- if (flags&FLAGS_HFLIP)
- {
- if (flags&FLAGS_TRANSPARENT)
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(cnt>>18));
- c>>=(6-(2*((cnt>>16)&0x03)));
- c&=0x03;
-
- if (c)
- {
- *current_line_buffer--=BLEND_Y(*current_line_buffer,paletteRam[((c&0x03)<<1)+0]);
- *current_line_buffer--=BLEND_CC(*current_line_buffer,paletteRam[((c&0x03)<<1)+1]);
- }
- else
- current_line_buffer-=2;
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- else
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(cnt>>18));
- c>>=(6-(2*((cnt>>16)&0x03)));
- c&=0x03;
- *current_line_buffer--=BLEND_Y(*current_line_buffer,paletteRam[((c&0x03)<<1)+0]);
- *current_line_buffer--=BLEND_CC(*current_line_buffer,paletteRam[((c&0x03)<<1)+1]);
-
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- }
- else
- {
- if (flags&FLAGS_TRANSPARENT)
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(cnt>>18));
- c>>=(6-(2*((cnt>>16)&0x03)));
- c&=0x03;
- if (c)
- {
- *current_line_buffer++=BLEND_Y(*current_line_buffer,paletteRam[((c&0x03)<<1)+0]);
- *current_line_buffer++=BLEND_CC(*current_line_buffer,paletteRam[((c&0x03)<<1)+1]);
- }
- else
- current_line_buffer+=2;
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- else
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(cnt>>18));
- c>>=(6-(2*((cnt>>16)&0x03)));
- c&=0x03;
- *current_line_buffer++=BLEND_Y(*current_line_buffer,paletteRam[((c&0x03)<<1)+0]);
- *current_line_buffer++=BLEND_CC(*current_line_buffer,paletteRam[((c&0x03)<<1)+1]);
-
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- }
- }
- else
- {
- if (flags&FLAGS_HFLIP)
- {
- if (flags&FLAGS_TRANSPARENT)
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(cnt>>18));
- c>>=(6-(2*((cnt>>16)&0x03)));
- c&=0x03;
- if (c)
- {
- *current_line_buffer--=paletteRam[((c&0x03)<<1)+0];
- *current_line_buffer--=paletteRam[((c&0x03)<<1)+1];
- }
- else
- current_line_buffer-=2;
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- else
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(cnt>>18));
- c>>=(6-(2*((cnt>>16)&0x03)));
- c&=0x03;
- *current_line_buffer--=paletteRam[((c&0x03)<<1)+0];
- *current_line_buffer--=paletteRam[((c&0x03)<<1)+1];
-
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- }
- else
- {
- if (flags&FLAGS_TRANSPARENT)
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(cnt>>18));
- c>>=(6-(2*((cnt>>16)&0x03)));
- c&=0x03;
- if (c)
- {
- *current_line_buffer++=paletteRam[((c&0x03)<<1)+0];
- *current_line_buffer++=paletteRam[((c&0x03)<<1)+1];
- }
- else
- current_line_buffer+=2;
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- else
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(cnt>>18));
- c>>=(6-(2*((cnt>>16)&0x03)));
- c&=0x03;
- *current_line_buffer++=paletteRam[((c&0x03)<<1)+0];
- *current_line_buffer++=paletteRam[((c&0x03)<<1)+1];
-
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- }
- }
+++ /dev/null
- uint8 *paletteRam=&tom_ram_8[0x400];
- paletteRam+=idx*2;
-
- if (flags&FLAGS_READMODIFY)
- {
- if (flags&FLAGS_HFLIP)
- {
- if (flags&FLAGS_TRANSPARENT)
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(((cnt>>16) & (~0x1f))*pitch)+((cnt>>16)&0x1f));
- c>>=(6-(2*((cnt>>16)&0x03)));
- c&=0x03;
-
- if (c)
- {
- *current_line_buffer--=BLEND_Y(*current_line_buffer,paletteRam[((c&0x03)<<1)+0]);
- *current_line_buffer--=BLEND_CC(*current_line_buffer,paletteRam[((c&0x03)<<1)+1]);
- }
- else
- current_line_buffer-=2;
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- else
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(((cnt>>16) & (~0x1f))*pitch)+((cnt>>16)&0x1f));
- c>>=(6-(2*((cnt>>16)&0x03)));
- c&=0x03;
- *current_line_buffer--=BLEND_Y(*current_line_buffer,paletteRam[((c&0x03)<<1)+0]);
- *current_line_buffer--=BLEND_CC(*current_line_buffer,paletteRam[((c&0x03)<<1)+1]);
-
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- }
- else
- {
- if (flags&FLAGS_TRANSPARENT)
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(((cnt>>16) & (~0x1f))*pitch)+((cnt>>16)&0x1f));
- c>>=(6-(2*((cnt>>16)&0x03)));
- c&=0x03;
- if (c)
- {
- *current_line_buffer++=BLEND_Y(*current_line_buffer,paletteRam[((c&0x03)<<1)+0]);
- *current_line_buffer++=BLEND_CC(*current_line_buffer,paletteRam[((c&0x03)<<1)+1]);
- }
- else
- current_line_buffer+=2;
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- else
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(((cnt>>16) & (~0x1f))*pitch)+((cnt>>16)&0x1f));
- c>>=(6-(2*((cnt>>16)&0x03)));
- c&=0x03;
- *current_line_buffer++=BLEND_Y(*current_line_buffer,paletteRam[((c&0x03)<<1)+0]);
- *current_line_buffer++=BLEND_CC(*current_line_buffer,paletteRam[((c&0x03)<<1)+1]);
-
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- }
- }
- else
- {
- if (flags&FLAGS_HFLIP)
- {
- if (flags&FLAGS_TRANSPARENT)
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(((cnt>>16) & (~0x1f))*pitch)+((cnt>>16)&0x1f));
- c>>=(6-(2*((cnt>>16)&0x03)));
- c&=0x03;
- if (c)
- {
- *current_line_buffer--=paletteRam[((c&0x03)<<1)+0];
- *current_line_buffer--=paletteRam[((c&0x03)<<1)+1];
- }
- else
- current_line_buffer-=2;
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- else
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(((cnt>>16) & (~0x1f))*pitch)+((cnt>>16)&0x1f));
- c>>=(6-(2*((cnt>>16)&0x03)));
- c&=0x03;
- *current_line_buffer--=paletteRam[((c&0x03)<<1)+0];
- *current_line_buffer--=paletteRam[((c&0x03)<<1)+1];
-
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- }
- else
- {
- if (flags&FLAGS_TRANSPARENT)
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(((cnt>>16) & (~0x1f))*pitch)+((cnt>>16)&0x1f));
- c>>=(6-(2*((cnt>>16)&0x03)));
- c&=0x03;
- if (c)
- {
- *current_line_buffer++=paletteRam[((c&0x03)<<1)+0];
- *current_line_buffer++=paletteRam[((c&0x03)<<1)+1];
- }
- else
- current_line_buffer+=2;
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- else
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(((cnt>>16) & (~0x1f))*pitch)+((cnt>>16)&0x1f));
- c>>=(6-(2*((cnt>>16)&0x03)));
- c&=0x03;
- *current_line_buffer++=paletteRam[((c&0x03)<<1)+0];
- *current_line_buffer++=paletteRam[((c&0x03)<<1)+1];
-
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- }
- }
+++ /dev/null
- uint8 *paletteRam=&tom_ram_8[0x400];
- paletteRam+=idx*4;
-
- if (flags&FLAGS_READMODIFY)
- {
- if (flags&FLAGS_HFLIP)
- {
- if (flags&FLAGS_TRANSPARENT)
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(cnt>>17));
- if (!(cnt&(1<<16)))
- c>>=4;
- if (c)
- {
- *current_line_buffer--=BLEND_Y(*current_line_buffer,paletteRam[((c&0x0f)<<1)+0]);
- *current_line_buffer--=BLEND_CC(*current_line_buffer,paletteRam[((c&0x0f)<<1)+1]);
- }
- else
- current_line_buffer-=2;
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- else
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(cnt>>17));
- if (!(cnt&(1<<16)))
- c>>=4;
- *current_line_buffer--=BLEND_Y(*current_line_buffer,paletteRam[((c&0x0f)<<1)+0]);
- *current_line_buffer--=BLEND_CC(*current_line_buffer,paletteRam[((c&0x0f)<<1)+1]);
-
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- }
- else
- {
- if (flags&FLAGS_TRANSPARENT)
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(cnt>>17));
- if (!(cnt&(1<<16)))
- c>>=4;
- if (c)
- {
- *current_line_buffer++=BLEND_Y(*current_line_buffer,paletteRam[((c&0x0f)<<1)+0]);
- *current_line_buffer++=BLEND_CC(*current_line_buffer,paletteRam[((c&0x0f)<<1)+1]);
- }
- else
- current_line_buffer+=2;
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- else
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(cnt>>17));
- if (!(cnt&(1<<16)))
- c>>=4;
- *current_line_buffer++=BLEND_Y(*current_line_buffer,paletteRam[((c&0x0f)<<1)+0]);
- *current_line_buffer++=BLEND_CC(*current_line_buffer,paletteRam[((c&0x0f)<<1)+1]);
-
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- }
- }
- else
- {
- if (flags&FLAGS_HFLIP)
- {
- if (flags&FLAGS_TRANSPARENT)
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(cnt>>17));
- if (!(cnt&(1<<16)))
- c>>=4;
- if (c)
- {
- *current_line_buffer--=paletteRam[((c&0x0f)<<1)+0];
- *current_line_buffer--=paletteRam[((c&0x0f)<<1)+1];
- }
- else
- current_line_buffer-=2;
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- else
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(cnt>>17));
- if (!(cnt&(1<<16)))
- c>>=4;
- *current_line_buffer--=paletteRam[((c&0x0f)<<1)+0];
- *current_line_buffer--=paletteRam[((c&0x0f)<<1)+1];
-
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- }
- else
- {
- if (flags&FLAGS_TRANSPARENT)
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(cnt>>17));
- if (!(cnt&(1<<16)))
- c>>=4;
- if (c)
- {
- *current_line_buffer++=paletteRam[((c&0x0f)<<1)+0];
- *current_line_buffer++=paletteRam[((c&0x0f)<<1)+1];
- }
- else
- current_line_buffer+=2;
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- else
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(cnt>>17));
- if (!(cnt&(1<<16)))
- c>>=4;
- *current_line_buffer++=paletteRam[((c&0x0f)<<1)+0];
- *current_line_buffer++=paletteRam[((c&0x0f)<<1)+1];
-
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- }
- }
+++ /dev/null
- uint8 *paletteRam=&tom_ram_8[0x400];
- paletteRam+=idx*4;
-
- if (flags&FLAGS_READMODIFY)
- {
- if (flags&FLAGS_HFLIP)
- {
- if (flags&FLAGS_TRANSPARENT)
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(((cnt>>16) & (~0x0f))*pitch)+((cnt>>16)&0x0f));
- if (!(cnt&(1<<16)))
- c>>=4;
- if (c)
- {
- *current_line_buffer--=BLEND_Y(*current_line_buffer,paletteRam[((c&0x0f)<<1)+0]);
- *current_line_buffer--=BLEND_CC(*current_line_buffer,paletteRam[((c&0x0f)<<1)+1]);
- }
- else
- current_line_buffer-=2;
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- else
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(((cnt>>16) & (~0x0f))*pitch)+((cnt>>16)&0x0f));
- if (!(cnt&(1<<16)))
- c>>=4;
- *current_line_buffer--=BLEND_Y(*current_line_buffer,paletteRam[((c&0x0f)<<1)+0]);
- *current_line_buffer--=BLEND_CC(*current_line_buffer,paletteRam[((c&0x0f)<<1)+1]);
-
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- }
- else
- {
- if (flags&FLAGS_TRANSPARENT)
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(((cnt>>16) & (~0x0f))*pitch)+((cnt>>16)&0x0f));
- if (!(cnt&(1<<16)))
- c>>=4;
- if (c)
- {
- *current_line_buffer++=BLEND_Y(*current_line_buffer,paletteRam[((c&0x0f)<<1)+0]);
- *current_line_buffer++=BLEND_CC(*current_line_buffer,paletteRam[((c&0x0f)<<1)+1]);
- }
- else
- current_line_buffer+=2;
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- else
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(((cnt>>16) & (~0x0f))*pitch)+((cnt>>16)&0x0f));
- if (!(cnt&(1<<16)))
- c>>=4;
- *current_line_buffer++=BLEND_Y(*current_line_buffer,paletteRam[((c&0x0f)<<1)+0]);
- *current_line_buffer++=BLEND_CC(*current_line_buffer,paletteRam[((c&0x0f)<<1)+1]);
-
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- }
- }
- else
- {
- if (flags&FLAGS_HFLIP)
- {
- if (flags&FLAGS_TRANSPARENT)
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(((cnt>>16) & (~0x0f))*pitch)+((cnt>>16)&0x0f));
- if (!(cnt&(1<<16)))
- c>>=4;
- if (c)
- {
- *current_line_buffer--=paletteRam[((c&0x0f)<<1)+0];
- *current_line_buffer--=paletteRam[((c&0x0f)<<1)+1];
- }
- else
- current_line_buffer-=2;
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- else
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(((cnt>>16) & (~0x0f))*pitch)+((cnt>>16)&0x0f));
- if (!(cnt&(1<<16)))
- c>>=4;
- *current_line_buffer--=paletteRam[((c&0x0f)<<1)+0];
- *current_line_buffer--=paletteRam[((c&0x0f)<<1)+1];
-
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- }
- else
- {
- if (flags&FLAGS_TRANSPARENT)
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(((cnt>>16) & (~0x0f))*pitch)+((cnt>>16)&0x0f));
- if (!(cnt&(1<<16)))
- c>>=4;
- if (c)
- {
- *current_line_buffer++=paletteRam[((c&0x0f)<<1)+0];
- *current_line_buffer++=paletteRam[((c&0x0f)<<1)+1];
- }
- else
- current_line_buffer+=2;
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- else
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(((cnt>>16) & (~0x0f))*pitch)+((cnt>>16)&0x0f));
- if (!(cnt&(1<<16)))
- c>>=4;
- *current_line_buffer++=paletteRam[((c&0x0f)<<1)+0];
- *current_line_buffer++=paletteRam[((c&0x0f)<<1)+1];
-
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- }
- }
+++ /dev/null
- uint8 *paletteRam=&tom_ram_8[0x400];
- paletteRam+=(idx&0x1)*256*2;
- if (flags&FLAGS_READMODIFY)
- {
- if (flags&FLAGS_HFLIP)
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(cnt>>16));
- c<<=1;
- if (flags&FLAGS_TRANSPARENT)
- {
- if (c)
- {
- *current_line_buffer--=BLEND_Y(*current_line_buffer,paletteRam[c+0]);
- *current_line_buffer--=BLEND_CC(*current_line_buffer,paletteRam[c+1]);
- }
- else
- current_line_buffer-=2;
- }
- else
- {
- *current_line_buffer--=BLEND_Y(*current_line_buffer,paletteRam[c+0]);
- *current_line_buffer--=BLEND_CC(*current_line_buffer,paletteRam[c+1]);
- }
-
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- else
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(cnt>>16));
- c<<=1;
- if (flags&FLAGS_TRANSPARENT)
- {
- if (c)
- {
- *current_line_buffer++=BLEND_Y(*current_line_buffer,paletteRam[c+0]);
- *current_line_buffer++=BLEND_CC(*current_line_buffer,paletteRam[c+1]);
- }
- else
- current_line_buffer+=2;
- }
- else
- {
- *current_line_buffer++=BLEND_Y(*current_line_buffer,paletteRam[c+0]);
- *current_line_buffer++=BLEND_CC(*current_line_buffer,paletteRam[c+1]);
- }
-
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- }
- else
- {
- if (flags&FLAGS_HFLIP)
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(cnt>>16));
- c<<=1;
- if (flags&FLAGS_TRANSPARENT)
- {
- if (c)
- {
- *current_line_buffer--=paletteRam[c+0];
- *current_line_buffer--=paletteRam[c+1];
- }
- else
- current_line_buffer-=2;
- }
- else
- {
- *current_line_buffer--=paletteRam[c+0];
- *current_line_buffer--=paletteRam[c+1];
- }
-
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- else
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(cnt>>16));
- c<<=1;
- if (flags&FLAGS_TRANSPARENT)
- {
- if (c)
- {
- *current_line_buffer++=paletteRam[c+0];
- *current_line_buffer++=paletteRam[c+1];
- }
- else
- current_line_buffer+=2;
- }
- else
- {
- *current_line_buffer++=paletteRam[c+0];
- *current_line_buffer++=paletteRam[c+1];
- }
-
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- }
+++ /dev/null
- uint8 *paletteRam=&tom_ram_8[0x400];
- paletteRam+=(idx&0x1)*256*2;
- if (flags&FLAGS_READMODIFY)
- {
- if (flags&FLAGS_HFLIP)
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(((cnt>>16) & (~0x07))*pitch)+((cnt>>16)&0x07));
- c<<=1;
- if (flags&FLAGS_TRANSPARENT)
- {
- if (c)
- {
- *current_line_buffer--=BLEND_Y(*current_line_buffer,paletteRam[c+0]);
- *current_line_buffer--=BLEND_CC(*current_line_buffer,paletteRam[c+1]);
- }
- else
- current_line_buffer-=2;
- }
- else
- {
- *current_line_buffer--=BLEND_Y(*current_line_buffer,paletteRam[c+0]);
- *current_line_buffer--=BLEND_CC(*current_line_buffer,paletteRam[c+1]);
- }
-
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- else
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(((cnt>>16) & (~0x07))*pitch)+((cnt>>16)&0x07));
- c<<=1;
- if (flags&FLAGS_TRANSPARENT)
- {
- if (c)
- {
- *current_line_buffer++=BLEND_Y(*current_line_buffer,paletteRam[c+0]);
- *current_line_buffer++=BLEND_CC(*current_line_buffer,paletteRam[c+1]);
- }
- else
- current_line_buffer+=2;
- }
- else
- {
- *current_line_buffer++=BLEND_Y(*current_line_buffer,paletteRam[c+0]);
- *current_line_buffer++=BLEND_CC(*current_line_buffer,paletteRam[c+1]);
- }
-
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- }
- else
- {
- if (flags&FLAGS_HFLIP)
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(((cnt>>16) & (~0x07))*pitch)+((cnt>>16)&0x07));
- c<<=1;
- if (flags&FLAGS_TRANSPARENT)
- {
- if (c)
- {
- *current_line_buffer--=paletteRam[c+0];
- *current_line_buffer--=paletteRam[c+1];
- }
- else
- current_line_buffer-=2;
- }
- else
- {
- *current_line_buffer--=paletteRam[c+0];
- *current_line_buffer--=paletteRam[c+1];
- }
-
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- else
- {
- while (scaled_width)
- {
- uint32 c=jaguar_byte_read(ptr+(((cnt>>16) & (~0x07))*pitch)+((cnt>>16)&0x07));
- c<<=1;
- if (flags&FLAGS_TRANSPARENT)
- {
- if (c)
- {
- *current_line_buffer++=paletteRam[c+0];
- *current_line_buffer++=paletteRam[c+1];
- }
- else
- current_line_buffer+=2;
- }
- else
- {
- *current_line_buffer++=paletteRam[c+0];
- *current_line_buffer++=paletteRam[c+1];
- }
-
- cnt+=hscale_fixed;
- scaled_width--;
- }
- }
- }
#include "jaguar.h"
//#include "m68kdasmAG.h"
-//#include "crc32.h"
//#define LOG_UNMAPPED_MEMORY_ACCESSES
//#define SOUND_OUTPUT
#define CPU_DEBUG
#define JAGUAR_WIP_RELEASE
-#define JAGUAR_REAL_SPEED
//Do this in makefile??? Yes! Could, but it's easier to define here...
//#define LOG_UNMAPPED_MEMORY_ACCESSES
-//
// Private function prototypes
-//
unsigned jaguar_unknown_readbyte(unsigned address);
unsigned jaguar_unknown_readword(unsigned address);
void jaguar_unknown_writeword(unsigned address, unsigned data);
void M68K_show_context(void);
+// External variables
+
+extern bool hardwareTypeNTSC; // Set to false for PAL
+
// These values are overridden by command line switches...
bool dsp_enabled = false;
//
// Callback function to detect illegal instructions
//
-
void M68KInstructionHook(void)
{
uint32 m68kPC = m68k_get_reg(NULL, M68K_REG_PC);
-
+
+/* static char buffer[2048];
+ m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
+ WriteLog("%08X: %s \t\tD0=%08X, A0=%08X\n", m68kPC, buffer, m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_A0));//*/
+
+/* if (m68kPC == 0x803F16)
+ {
+ WriteLog("M68K: Registers found at $803F16:\n");
+ WriteLog( "\t68K PC=%06X\n", m68k_get_reg(NULL, M68K_REG_PC));
+ for(int i=M68K_REG_D0; i<=M68K_REG_D7; i++)
+ WriteLog( "\tD%i = %08X\n", i-M68K_REG_D0, m68k_get_reg(NULL, (m68k_register_t)i));
+ WriteLog( "\n");
+ for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
+ WriteLog( "\tA%i = %08X\n", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
+ }*/
+
if (!m68k_is_valid_instruction(jaguar_word_read(m68kPC), M68K_CPU_TYPE_68000))
{
WriteLog("\nEncountered illegal instruction at %08X!!!\n\nAborting!\n", m68kPC);
//WriteLog( "[WM16 PC=%08X] Addr: %08X, val: %04X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
//if (address >= 0xF02200 && address <= 0xF0229F)
// WriteLog("M68K: Writing to blitter --> %04X at %08X\n", value, address);
+//if (address >= 0x0E75D0 && address <= 0x0E75E7)
+// WriteLog("M68K: Writing %04X at %08X, M68K PC=%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));
+/*extern uint32 totalFrames;
+extern bool suppressOutput;
+if (totalFrames >= 59)
+ suppressOutput = false;//*/
+/*if (address == 0xF02114)
+ WriteLog("M68K: Writing to GPU_CTRL (frame:%u)... [M68K PC:%08X]\n", totalFrames, m68k_get_reg(NULL, M68K_REG_PC));
+if (address == 0xF02110)
+ WriteLog("M68K: Writing to GPU_PC (frame:%u)... [M68K PC:%08X]\n", totalFrames, m68k_get_reg(NULL, M68K_REG_PC));//*/
+//if (address >= 0xF03B00 && address <= 0xF03DFF)
+// WriteLog("M68K: Writing %04X to %08X...\n", value, address);
+
if ((address >= 0x000000) && (address <= 0x3FFFFE))
{
jaguar_mainRam[address] = value >> 8;
// jaguar_dasm(s68000readPC()-0x1000,0x20000);
jaguar_dasm(m68k_get_reg(NULL, M68K_REG_PC) - 0x80, 0x200);
// jaguar_dasm(0x5000, 0x14414);
- WriteLog( "..................\n");
+ WriteLog( "..................\n");
if (tom_irq_enabled(IRQ_VBLANK))
{
}
else
WriteLog( "vblank int: disabled\n");
+
WriteLog( "..................\n");
for(int i=0; i<256; i++)
for(uint32 i=0; i<qt; i++)
{
- oldpc = pc;
-// for(int j=0; j<64; j++)
-// mem[j^0x01] = jaguar_byte_read(pc + j);
+/* oldpc = pc;
+ for(int j=0; j<64; j++)
+ mem[j^0x01] = jaguar_byte_read(pc + j);
-// pc += Dasm68000((char *)mem, buffer, 0);
+ pc += Dasm68000((char *)mem, buffer, 0);
+ WriteLog("%08X: %s\n", oldpc, buffer);//*/
+ oldpc = pc;
pc += m68k_disassemble(buffer, pc, M68K_CPU_TYPE_68000);
- WriteLog("%08X: %s\n", oldpc, buffer);
+ WriteLog("%08X: %s\n", oldpc, buffer);//*/
}
#endif
}
unsigned jaguar_long_read(unsigned int offset)
{
-/* uint32 data = jaguar_word_read(offset);
- data = (data<<16) | jaguar_word_read(offset+2);
- return data;*/
return (jaguar_word_read(offset) << 16) | jaguar_word_read(offset+2);
}
//else
// WriteLog("JagLW: DSP halted... (Old value: %08X)\n", dsp_control);
-//extern int effect_start;
-// $10, $0C, $0A, $09 too much, $08 too little...
-//if (effect_start && offset == 0xF03000) data = (data & 0xFFFF0000) | (((data & 0xFFFF) + 0x0008) & 0xFFFF);
-//Doesn't work--offsets horizontally if (effect_start && offset == 0xF03004) data -= (0x300 * 8); // one line is $300
-//if (effect_start && offset == 0xF03000) data = 0x00000000; // Let's try making the top/bottom *always* 0!
-//Interesting: it seems to pin half of the screen down (but too low)...
-//Definitely the fine scroll offsets (for left side of screen)...
-
-//if ((offset >= 0x1FF020 && offset <= 0x1FF03F) || (offset >= 0x1FF820 && offset <= 0x1FF83F))
-// WriteLog("JagLW: Writing %08X at %08X\n", data, offset);
jaguar_word_write(offset, data >> 16);
jaguar_word_write(offset+2, data & 0xFFFF);
}
//
-// Jaguar initialization
+// Jaguar console initialization
//
-
-//void jaguar_init(const char * filename)
void jaguar_init(void)
{
-// uint32 romsize;
-
- jaguar_screen_scanlines = 525; // PAL screen size
- m68k_cycles_per_scanline = 13300000 / (jaguar_screen_scanlines * 60);
- gpu_cycles_per_scanline = (26591000 / 4) / (jaguar_screen_scanlines * 60);
- dsp_cycles_per_scanline = (26591000 / 4) / (jaguar_screen_scanlines * 60);
-
memory_malloc_secure((void **)&jaguar_mainRam, 0x400000, "Jaguar 68K CPU RAM");
memory_malloc_secure((void **)&jaguar_bootRom, 0x040000, "Jaguar 68K CPU BIOS ROM");
memory_malloc_secure((void **)&jaguar_mainRom, 0x600000, "Jaguar 68K CPU ROM");
// memset(jaguar_mainRom, 0xFF, 0x200000); // & set it to all Fs...
memset(jaguar_mainRom, 0x00, 0x200000); // & set it to all 0s...
-// jaguar_rom_load_to(jaguar_bootRom, jaguar_bootRom_path, &romsize);
-// memcpy(jaguar_mainRam, jaguar_bootRom, 8);
-// SET32(jaguar_mainRam, 0, 0x00200000);
-
-#ifdef JAGUAR_WIP_RELEASE
-// strcpy(romLoadDialog_filePath, filename);
-// jaguar_load_cart(romLoadDialog_filePath, jaguar_mainRom, 0x0000, 0x00802000, 0);
-
- if ((jaguar_mainRom_crc32 == 0x3966698f) || (jaguar_mainRom_crc32 == 0x5e705756)
- || (jaguar_mainRom_crc32 == 0x2630cbc4) || (jaguar_mainRom_crc32 == 0xd46437e8)
- || (jaguar_mainRom_crc32 == 0x2630cbc4))
- dsp_enabled = true;
-
- if ((jaguar_mainRom_crc32 == 0x6e90989f) || (jaguar_mainRom_crc32 == 0xfc8f0dcd)
- || (jaguar_mainRom_crc32 == 0x2a512a83) || (jaguar_mainRom_crc32 == 0x41307601)
- || (jaguar_mainRom_crc32 == 0x3c7bfda8) || (jaguar_mainRom_crc32 == 0x5e705756))
- gpu_cycles_per_scanline = (26591000 / 1) / (jaguar_screen_scanlines * 60);
-
- if (jaguar_mainRom_crc32 == 0x7ae20823)
- {
- dsp_enabled = true;
- gpu_cycles_per_scanline = (26591000 / 1) / (jaguar_screen_scanlines * 60);
- dsp_cycles_per_scanline = (26591000 / 1) / (jaguar_screen_scanlines * 60);
- }
- if (jaguar_mainRom_crc32 == 0xe21d0e2f)
- {
- dsp_enabled = true;
- gpu_cycles_per_scanline = (26591000 / 1) / (jaguar_screen_scanlines * 60);
- dsp_cycles_per_scanline = (26591000 / 1) / (jaguar_screen_scanlines * 60);
- }
- if (jaguar_mainRom_crc32 == 0x66f8914c)
- {
- gpu_cycles_per_scanline = (26591000 / 1) /(jaguar_screen_scanlines * 60);
- }
- if (jaguar_mainRom_crc32 == 0x5a5b9c68)
- {
- gpu_cycles_per_scanline = (26591000 / 1) / (jaguar_screen_scanlines * 60);
- }
- if (jaguar_mainRom_crc32 == 0xdcb0197a)
- {
- dsp_enabled = false; // dsp not needed
- gpu_cycles_per_scanline = (26591000 / 1) / (jaguar_screen_scanlines * 60);
- //dsp_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
- }
- if ((jaguar_mainRom_crc32 == 0x3966698f) || (jaguar_mainRom_crc32 == 0xe21d0e2f))
- dsp_enabled = true;
- if (jaguar_mainRom_crc32 == 0x5e705756)
- {
- gpu_cycles_per_scanline = (26591000 / 1) / (jaguar_screen_scanlines * 60);
- dsp_enabled = true;
- }
- if (jaguar_mainRom_crc32 == 0x2630cbc4)
- {
- // ultra vortek
- gpu_cycles_per_scanline = (26591000 / 1) / (jaguar_screen_scanlines * 60);
- dsp_cycles_per_scanline = (26591000 / 1) / (jaguar_screen_scanlines * 60);
- dsp_enabled = true;
- }
- if ((jaguar_mainRom_crc32 == 0xd46437e8) || (jaguar_mainRom_crc32 == 0xba74c3ed))
- {
- gpu_cycles_per_scanline = (26591000 / 1) / (jaguar_screen_scanlines * 60);
- dsp_enabled = true;
- }
- if (jaguar_mainRom_crc32 == 0x6e90989f)
- gpu_cycles_per_scanline = (26591000 / 1) / (jaguar_screen_scanlines * 60);
-
- if (jaguar_mainRom_crc32 == 0x41307601)
- {
- gpu_cycles_per_scanline = (26591000 / 1) / (jaguar_screen_scanlines * 60);
- }
-
- if (jaguar_mainRom_crc32 == 0x8483392b)
- {
- dsp_enabled = true;
- }
-
-#else // #ifdef JAGUAR_WIP_RELEASE
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/flashback.jag",jaguar_mainRom,0x0000, 0x20000080,0);
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/Pinball Fantasies.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/alien vs predator (1994).jag",jaguar_mainRom,0x0000, 0x20000080,0);
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/cannon fodder (1995) (computer west).jag",jaguar_mainRom,0x0000, 0x20000080,0);
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/double dragon v (1995) (williams).jag",jaguar_mainRom,0x0000, 0x20000080,0);
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/Dragon - The Bruce Lee Story.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/Syndicate.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/Theme Park.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/Brutal Sports Football.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/International Sensible Soccer.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/Defender 2000.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/Fever Pitch Soccer.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/Rayman.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/Tempest 2000.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/zool 2 (1994).jag",jaguar_mainRom,0x0000, 0x20000080,0);
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/Bubsy - Fractured Furry Tails.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/Raiden.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/Dino Olympics.jag",jaguar_mainRom,0x0000, 0x20000080,0);
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/I-War.jag",jaguar_mainRom,0x0000, 0x20000080,0);
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/Attack of the Mutant Penguins.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/Cybermorph.jag",jaguar_mainRom,0x0000, 0x20000080,0);
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/Troy Aikman NFL Football (1995) (Williams).jag",jaguar_mainRom,0x0000, 0x20000080,0);
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/Power Drive Rally (1995) (TWI).jag",jaguar_mainRom,0x0000, 0x20000080,0);
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/Zoop! (1996).jag",jaguar_mainRom,0x0000, 0x20000080,0);
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/Missile Command 3D.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/Hover Strike.jag",jaguar_mainRom,0x0000, 0x20000080,0);
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/worms.bin",jaguar_mainRom,0x0000, 0x20000080,0);
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/Atari Kart.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/native.bin",jaguar_mainRam,0x5000, 0x50000000,0x00);
-
- if (jaguar_mainRom_crc32==0xe21d0e2f)
- {
- dsp_enabled=true;
- gpu_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
- dsp_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
- }
- if (jaguar_mainRom_crc32==0x66f8914c)
- {
- gpu_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
- }
- if (jaguar_mainRom_crc32==0x5a5b9c68)
- {
- gpu_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
- }
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/Super Cross 3D.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
- if (jaguar_mainRom_crc32==0xdcb0197a)
- {
- dsp_enabled=true; // dsp not needed
- gpu_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
- //dsp_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
- }
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/wolfenstein 3d (1994).jag",jaguar_mainRom,0x0000, 0x20000080,0);
- if ((jaguar_mainRom_crc32==0x3966698f)||(jaguar_mainRom_crc32==0xe21d0e2f))
- dsp_enabled=true;
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/NBA JAM.jag",jaguar_mainRom,0x0000, 0x20000080,0);
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/Doom - Evil Unleashed.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
- if (jaguar_mainRom_crc32==0x5e705756)
- {
- gpu_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
- dsp_enabled=true;
- }
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/Ultra Vortek.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
- if (jaguar_mainRom_crc32==0x2630cbc4)
- {
- // ultra vortek
- gpu_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
- dsp_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
- dsp_enabled=true;
- }
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/fflbeta.rom",jaguar_mainRom,0x0000, 0x20000080,0);
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/Fight for Your Life.jag",jaguar_mainRom,0x0000, 0x20000080,0);
- if ((jaguar_mainRom_crc32==0xd46437e8)||(jaguar_mainRom_crc32==0xba74c3ed))
- {
- gpu_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
-// dsp_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
- dsp_enabled=true;
- }
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/Pitfall - The Mayan Adventure.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
- if (jaguar_mainRom_crc32==0x6e90989f)
- gpu_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
-
-// missing some sprites
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/Crescent Galaxy.jag",jaguar_mainRom,0x0000, 0x20000080,0);
- if (jaguar_mainRom_crc32==0x41307601)
- {
- gpu_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
- }
-
-// missing vertical bar shades
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/Phase Zero (2000) (PD).rom",jaguar_mainRom,0x0000, 0x20000080,0);
- if (jaguar_mainRom_crc32==0x8483392b)
- {
- dsp_enabled=true;
- }
-// cpu/dsp/gpu synchronization problems
-
-
-// locks up during the game
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/Club Drive.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
-
-// no parallax floor, locks up at the start of the game
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/Kasumi Ninja.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
-
-// displaying the sound control dialog. no way to exit from it
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/Checkered Flag.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
-
-// no 3d
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/Iron Soldier.jag",jaguar_mainRom,0x0000, 0x20000080,0);
-
-// locks up at the start of the game
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/Super Burnout.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
- if (jaguar_mainRom_crc32==0x20ae75f4)
- {
- dsp_enabled=true;
- gpu_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
- dsp_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
- }
-// locks up at the start of the game
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/Val D'Isere Skiing & Snowboarding (1994).jag",jaguar_mainRom,0x0000, 0x20000080,0);
- if (jaguar_mainRom_crc32==0x4664ebd1)
- {
- dsp_enabled=true;
- }
-
-// fonctionne avec le gpu et le dsp activés et gpu à frequence nominale, et dsp à 1/4 de la frequence nominale
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/white men can't jump (1995).jag",jaguar_mainRom,0x0000, 0x20000080,0);
- if (jaguar_mainRom_crc32==0x7ae20823)
- {
- dsp_enabled=true;
- gpu_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
- }
-// not working at all
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/Flip Out.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
- if (jaguar_mainRom_crc32==0x6f57dcd2)
- {
- gpu_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
- dsp_enabled=false;
-
- }
-
- jaguar_load_cart("C:/ftp/jaguar/roms/roms/Ruiner.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
- if (jaguar_mainRom_crc32==0x6a7c7430)
- {
- dsp_enabled=true;
- }
-
- if (jaguar_mainRom_crc32==0x2f032271)
- {
- dsp_enabled=true;
- dsp_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
- gpu_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
- }
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/tetris.bin",jaguar_mainRam,0x4fe4, 0x50000000,0x00);
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/painter.bin",jaguar_mainRam,0xffe4, 0x00000001,0x00);
-// jaguar_load_cart("./roms/jagcd.rom",jaguar_mainRom,0x0000, 0x20000080,0);
-
-// jaguar_load_cart("cart.jag",jaguar_mainRom,0x0000, 0x20000080,0);
-
-
// cd_bios_boot("C:\\ftp\\jaguar\\cd\\Brain Dead 13.cdi");
// cd_bios_boot("C:\\ftp\\jaguar\\cd\\baldies.cdi");
// cd_bios_boot("C:\\ftp\\jaguar\\cd\\mystdemo.cdi");
// cd_bios_boot("C:\\ftp\\jaguar\\cd\\primalrage.cdi");
// cd_bios_boot("C:\\ftp\\jaguar\\cd\\Dragons Lair.cdi");
-// jaguar_load_cart("C:/ftp/jaguar/roms/roms/raw.jag",jaguar_mainRam,0x4000, 0x40000000,0x00);
-#endif // #ifdef JAGUAR_WIP_RELEASE
+// NTSC PAL
+// GPU/DSP/video clock rate 26.590906 26.593900
+// 68000 clock rate 13.295453 13.296950
+// (clock rates in MHz)
+
+ // Should these be hardwired or read from VP?
+ jaguar_screen_scanlines = (hardwareTypeNTSC ? 524 : 624);
+//Should the divisor be 50 for PAL??? Let's try it!
+ m68k_cycles_per_scanline = (hardwareTypeNTSC ? 13295453 : 13296950) / (jaguar_screen_scanlines * (hardwareTypeNTSC ? 60 : 50));
+ gpu_cycles_per_scanline = dsp_cycles_per_scanline
+ = (hardwareTypeNTSC ? 26590906 : 26593900) / (jaguar_screen_scanlines * (hardwareTypeNTSC ? 60 : 50));
-#ifdef JAGUAR_REAL_SPEED
- gpu_cycles_per_scanline = (26591000 / 1) / (jaguar_screen_scanlines * 60);
- dsp_cycles_per_scanline = (26591000 / 1) / (jaguar_screen_scanlines * 60);
-#endif
#ifdef SOUND_OUTPUT
ws_audio_init();
#endif
//#ifdef CPU_DEBUG
// for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
// WriteLog("\tA%i = 0x%.8x\n", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
- uint32 topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
+ int32 topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
WriteLog("M68K: Top of stack: %08X. Stack trace:\n", jaguar_long_read(topOfStack));
- for(int i=0; i<10; i++)
- WriteLog("%06X: %08X\n", topOfStack - (i * 4), jaguar_long_read(topOfStack - (i * 4)));
+ for(int i=-2; i<9; i++)
+ WriteLog("%06X: %08X\n", topOfStack + (i * 4), jaguar_long_read(topOfStack + (i * 4)));
+
+/* WriteLog("\nM68000 disassembly at $802288...\n");
+ jaguar_dasm(0x802288, 3);
+ WriteLog("\nM68000 disassembly at $802200...\n");
+ jaguar_dasm(0x802200, 500);
+ WriteLog("\nM68000 disassembly at $802518...\n");
+ jaguar_dasm(0x802518, 100);//*/
+
+/* WriteLog("\n\nM68000 disassembly at $803F00 (look @ $803F2A)...\n");
+ jaguar_dasm(0x803F00, 500);
+ WriteLog("\n");//*/
+
+/* WriteLog("\n\nM68000 disassembly at $802B00 (look @ $802B5E)...\n");
+ jaguar_dasm(0x802B00, 500);
+ WriteLog("\n");//*/
+
// WriteLog("Jaguar: CD BIOS version %04X\n", jaguar_word_read(0x3004));
+ WriteLog("Jaguar: Interrupt enable = %02X\n", tom_byte_read(0xF000E1) & 0x1F);
WriteLog("Jaguar: VBL interrupt is %s\n", ((tom_irq_enabled(IRQ_VBLANK)) && (jaguar_interrupt_handler_is_valid(64))) ? "enabled" : "disabled");
M68K_show_context();
//#endif
// vblank
if ((tom_irq_enabled(IRQ_VBLANK)) && (jaguar_interrupt_handler_is_valid(64)))
{
- if (jaguar_word_read(0xF0004E) != 0xFFFF)
+ if (jaguar_word_read(0xF0004E) != 0x07FF) // VI (11 bits wide!)
{
tom_set_pending_video_int();
// s68000interrupt(7, IRQ_VBLANK+64);
#endif
}
+//
+// Main Jaguar execution loop (1 frame)
+//
+void JaguarExecute(int16 * backbuffer, bool render)
+{
+ uint16 vp = tom_word_read(0xF0003E);//Hmm. This is a WO register. Will work? Looks like. But wrong behavior!
+ uint16 vi = tom_word_read(0xF0004E);//Another WO register...
+ uint16 vdb = tom_word_read(0xF00046);
+// uint16 endingLine =
+//Note: This is the *definite* end of the display, though VDE *might* be less than this...
+// uint16 vbb = tom_word_read(0xF00040);
+//It seems that they mean it when they say that VDE is the end of object processing.
+//However, we need to be able to tell the OP (or TOM) that we've reached the end of the
+//buffer and not to write any more pixels...
+ uint16 vde = tom_word_read(0xF00048);
+
+/*extern int effect_start;
+if (effect_start)
+{
+ WriteLog("JagExe: VP=%u, VI=%u, VDB=%u, VBB=%u CPU CPS=%u, GPU CPS=%u\n", vp, vi, vdb, vbb, m68k_cycles_per_scanline, gpu_cycles_per_scanline);
+}//*/
+
+ for(uint16 i=0; i<vp; i++)
+ {
+ // Increment the horizontal count (why? RNG?)
+ tom_word_write(0xF00004, tom_word_read(0xF00004) + 1);
+
+ tom_word_write(0xF00006, i); // Write the VC
+
+ if (i == vi) // Time for Vertical Interrupt?
+ {
+ if (tom_irq_enabled(IRQ_VBLANK) && jaguar_interrupt_handler_is_valid(64))
+ {
+ // We don't have to worry about autovectors & whatnot because the Jaguar
+ // tells you through registers who sent the interrupt...
+ tom_set_pending_video_int();
+ m68k_set_irq(7);
+ }
+ }
+
+// uint32 invalid_instruction_address = s68000exec(m68k_cycles_per_scanline);
+// if (invalid_instruction_address != 0x80000000)
+// cd_bios_process(invalid_instruction_address);
+ // These are divided by 2 because we're executing *half* lines...!
+ m68k_execute(m68k_cycles_per_scanline / 2);
+ // No CD handling... !!! FIX !!!
+ cd_bios_exec(i); // NOTE: Ignores parameter...
+ tom_pit_exec(m68k_cycles_per_scanline / 2);
+ jerry_pit_exec(m68k_cycles_per_scanline / 2);
+ jerry_i2s_exec(m68k_cycles_per_scanline / 2);
+ gpu_exec(gpu_cycles_per_scanline / 2);
+ if (dsp_enabled)
+ dsp_exec(dsp_cycles_per_scanline / 2);
+
+//Interlacing is still not handled correctly here...
+ if (i >= vdb && i < vde)//vbb)
+ {
+ if (!(i & 0x01)) // Execute OP only on even lines (non-interlaced only!)
+ {
+ tom_exec_scanline(backbuffer, i/2, render); // i/2 is a kludge...
+ backbuffer += TOMGetSDLScreenPitch() / 2; // Convert bytes to words...
+ }
+ }
+ }
+
+#ifdef SOUND_OUTPUT
+ system_sound_update();
+#endif
+}
+
// Temp debugging stuff
void DumpMainMemory(void)
// This logger is used mainly to ensure that text gets written to the log file
// even if the program crashes. The performance hit is acceptable in this case!
//
-
+//bool suppressOutput = true;//temporary stuff
+bool suppressOutput = false;//temporary stuff
void WriteLog(const char * text, ...)
{
+ if (suppressOutput)
+ return;
+
va_list arg;
va_start(arg, text);
* instruction.
*/
void M68KInstructionHook(void);
-#define M68K_INSTRUCTION_HOOK OPT_OFF
-//#define M68K_INSTRUCTION_HOOK OPT_SPECIFY_HANDLER
+//#define M68K_INSTRUCTION_HOOK OPT_OFF
+#define M68K_INSTRUCTION_HOOK OPT_SPECIFY_HANDLER
//#define M68K_INSTRUCTION_CALLBACK() your_instruction_hook_function()
#define M68K_INSTRUCTION_CALLBACK() M68KInstructionHook()
static void d68000_cmpi_32(void)
{
char* str;
- LIMIT_CPU_TYPES(M68020_PLUS);
+//BUG!!! Argh! LIMIT_CPU_TYPES(M68020_PLUS);
str = get_imm_str_s32();
sprintf(g_dasm_str, "cmpi.l %s, %s", str, get_ea_mode_str_32(g_cpu_ir));
}
#define BLEND_Y(dst, src) op_blend_y[(((uint16)dst<<8)) | ((uint16)(src))]
#define BLEND_CR(dst, src) op_blend_cr[(((uint16)dst)<<8) | ((uint16)(src))]
-//Delete this once we're rid of zbmpop*.h...
-#define BLEND_CC(dst, src) op_blend_cr[(((uint16)dst)<<8) | ((uint16)(src))]
#define OBJECT_TYPE_BITMAP 0 // 000
#define OBJECT_TYPE_SCALE 1 // 001
#define CONDITION_OP_FLAG_SET 3
#define CONDITION_SECOND_HALF_LINE 4
-//Delete this once we're rid of zbmpop*.h...
-#define FLAGS_RELEASE 8
-#define FLAGS_TRANSPARENT 4
-#define FLAGS_READMODIFY 2
-#define FLAGS_HFLIP 1
-
#define OPFLAG_RELEASE 8 // Bus release bit
#define OPFLAG_TRANS 4 // Transparency bit
#define OPFLAG_RMW 2 // Read-Modify-Write bit
void OPProcessFixedBitmap(int scanline, uint64 p0, uint64 p1, bool render);
void OPProcessScaledBitmap(int scanline, uint64 p0, uint64 p1, uint64 p2, bool render);
+void DumpScaledObject(uint64 p0, uint64 p1, uint64 p2);
+void DumpFixedObject(uint64 p0, uint64 p1);
+uint64 op_load_phrase(uint32 offset);
// External global variables
static uint8 * op_blend_y;
static uint8 * op_blend_cr;
-// There may be a problem with this "RAM" overlapping some of the
-// regular TOM RAM...
+// There may be a problem with this "RAM" overlapping (and thus being independent of)
+// some of the regular TOM RAM...
static uint8 objectp_ram[0x40]; // This is based at $F00000
uint8 objectp_running;
bool objectp_stop_reading_list;
static uint8 op_bitmap_bit_depth[8] = { 1, 2, 4, 8, 16, 24, 32, 0 };
-static uint32 op_bitmap_bit_size[8] =
- { (uint32)(0.125*65536), (uint32)(0.25*65536), (uint32)(0.5*65536), (uint32)(1*65536),
- (uint32)(2*65536), (uint32)(1*65536), (uint32)(1*65536), (uint32)(1*65536) };
+//static uint32 op_bitmap_bit_size[8] =
+// { (uint32)(0.125*65536), (uint32)(0.25*65536), (uint32)(0.5*65536), (uint32)(1*65536),
+// (uint32)(2*65536), (uint32)(1*65536), (uint32)(1*65536), (uint32)(1*65536) };
static uint32 op_pointer;
+int32 phraseWidthToPixels[8] = { 64, 32, 16, 8, 4, 2, 0, 0 };
+
//
// Object Processor initialization
void op_done(void)
{
+ char * opType[8] =
+ { "(BITMAP)", "(SCALED BITMAP)", "(GPU INT)", "(BRANCH)", "(STOP)", "???", "???", "???" };
+ char * ccType[8] =
+ { "\"==\"", "\"<\"", "\">\"", "(opflag set)", "(second half line)", "?", "?", "?" };
+
+ uint32 olp = op_get_list_pointer();
+ WriteLog("OP: OLP = %08X\n", olp);
+ WriteLog("OP: Phrase dump\n ----------\n");
+ for(uint32 i=0; i<0x100; i+=8)
+ {
+ uint32 hi = jaguar_long_read(olp + i), lo = jaguar_long_read(olp + i + 4);
+ WriteLog("\t%08X: %08X %08X %s", olp + i, hi, lo, opType[lo & 0x07]);
+ if ((lo & 0x07) == 3)
+ {
+ uint16 ypos = (lo >> 3) & 0x7FF;
+ uint8 cc = (lo >> 14) & 0x03;
+ 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(op_load_phrase(olp+i), op_load_phrase(olp+i+8));
+ if ((lo & 0x07) == 1)
+ DumpScaledObject(op_load_phrase(olp+i), op_load_phrase(olp+i+8), op_load_phrase(olp+i+16));
+ }
+ WriteLog("\n");
}
//
// Object Processor memory access
-// Memory range: F00010 (F00008?) - F00027
+// Memory range: F00010 - F00027
//
void op_byte_write(uint32 offset, uint8 data)
{
{
//Not sure this is right... Wouldn't it just be stored 64 bit BE?
// Stored as least significant 32 bits first, ms32 last in big endian
- objectp_ram[0x13] = object & 0xFF; object >>= 8;
+/* objectp_ram[0x13] = object & 0xFF; object >>= 8;
objectp_ram[0x12] = object & 0xFF; object >>= 8;
objectp_ram[0x11] = object & 0xFF; object >>= 8;
objectp_ram[0x10] = object & 0xFF; object >>= 8;
objectp_ram[0x17] = object & 0xFF; object >>= 8;
objectp_ram[0x16] = object & 0xFF; object >>= 8;
objectp_ram[0x15] = object & 0xFF; object >>= 8;
- objectp_ram[0x14] = object & 0xFF;
+ objectp_ram[0x14] = object & 0xFF;*/
+// Let's try regular good old big endian...
+ objectp_ram[0x17] = object & 0xFF; object >>= 8;
+ objectp_ram[0x16] = object & 0xFF; object >>= 8;
+ objectp_ram[0x15] = object & 0xFF; object >>= 8;
+ objectp_ram[0x14] = object & 0xFF; object >>= 8;
+
+ objectp_ram[0x13] = object & 0xFF; object >>= 8;
+ objectp_ram[0x12] = object & 0xFF; object >>= 8;
+ objectp_ram[0x11] = object & 0xFF; object >>= 8;
+ objectp_ram[0x10] = object & 0xFF;
}
uint64 op_load_phrase(uint32 offset)
return ((uint64)jaguar_long_read(offset) << 32) | (uint64)jaguar_long_read(offset+4);
}
-//
-// OP replacement functions
-//
-
void OPStorePhrase(uint32 offset, uint64 p)
{
offset &= ~0x07; // 8 byte alignment
}
//
-// *** NEW ***
+// 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;
+ int16 ypos = ((p0 >> 3) & 0x3FF); // ??? 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);
+ 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));
+ uint8 bitdepth = (p1 >> 12) & 0x07;
+ int16 ypos = ((p0 >> 3) & 0x3FF); // ??? 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(" [%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);
+}
+
+//
// Object Processor main routine
//
void OPProcessList(int scanline, bool render)
// If jaguar_exec() is working right, we should *never* have to check for this
// condition...
- if (scanline < tom_get_vdb())
+/* if (scanline < tom_get_vdb())
return;
if (scanline >= 525)//tom_getVideoModeHeight()+tom_get_vdb())
- return;
+ return;//*/
op_pointer = op_get_list_pointer();
uint64 p0 = op_load_phrase(op_pointer);
op_pointer += 8;
if (scanline == tom_get_vdb() && op_start_log)
+//if (scanline == 215 && op_start_log)
{
WriteLog("%08X --> phrase %08X %08X", op_pointer - 8, (int)(p0>>32), (int)(p0&0xFFFFFFFF));
if ((p0 & 0x07) == OBJECT_TYPE_BITMAP)
xpos = (xpos & 0x800 ? xpos | 0xFFFFF000 : xpos);
uint32 iwidth = ((p1 >> 28) & 0x3FF);
uint32 dwidth = ((p1 >> 18) & 0x3FF); // Unsigned!
- uint16 height = ((p0 >> 14) & 0x3FF) - 1;
+ 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&FLAGS_HFLIP ? "REFLECT " : ""), (flags&FLAGS_READMODIFY ? "RMW " : ""), (flags&FLAGS_TRANSPARENT ? "TRANS " : ""), (flags&FLAGS_RELEASE ? "RELEASE" : ""), idx, pitch);
+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);
}
if ((p0 & 0x07) == OBJECT_TYPE_SCALE)
{
WriteLog(" (SCALED BITMAP)");
uint64 p1 = op_load_phrase(op_pointer), p2 = op_load_phrase(op_pointer+8);
WriteLog("\n%08X --> phrase %08X %08X ", op_pointer, (int)(p1>>32), (int)(p1&0xFFFFFFFF));
+WriteLog("\n%08X --> phrase %08X %08X ", op_pointer+8, (int)(p2>>32), (int)(p2&0xFFFFFFFF));
uint8 bitdepth = (p1 >> 12) & 0x07;
int16 ypos = ((p0 >> 3) & 0x3FF); // ??? 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) - 1;
+ 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&FLAGS_HFLIP ? "REFLECT " : ""), (flags&FLAGS_READMODIFY ? "RMW " : ""), (flags&FLAGS_TRANSPARENT ? "TRANS " : ""), (flags&FLAGS_RELEASE ? "RELEASE" : ""), idx, pitch);
+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);
uint32 hscale = p2 & 0xFF;
uint32 vscale = (p2 >> 8) & 0xFF;
uint32 remainder = (p2 >> 16) & 0xFF;
// There's probably another bit somewhere that enables this mode--but so far, doesn't seem
// to affect any other game in a negative way (that I've seen).
// Either that, or it's an undocumented bug...
- if (ypos == 0)
- ypos = tom_word_read(0xF00046) / 2; // Get the VDB value
+
+//No, the reason this was needed is that the OP code before was wrong. Any value
+//less than VDB will get written to the top line of the display!
+// if (ypos == 0)
+// ypos = tom_word_read(0xF00046) / 2; // Get the VDB value
uint32 height = (p0 & 0xFFC000) >> 14;
uint32 oldOPP = op_pointer - 8;
// *** BEGIN OP PROCESSOR TESTING ONLY ***
// There's probably another bit somewhere that enables this mode--but so far, doesn't seem
// to affect any other game in a negative way (that I've seen).
// Either that, or it's an undocumented bug...
- if (ypos == 0)
- ypos = tom_word_read(0xF00046) / 2; // Get the VDB value
+
+//No, the reason this was needed is that the OP code before was wrong. Any value
+//less than VDB will get written to the top line of the display!
+// if (ypos == 0)
+// ypos = tom_word_read(0xF00046) / 2; // Get the VDB value
uint32 height = (p0 & 0xFFC000) >> 14;
uint32 oldOPP = op_pointer - 8;
// *** BEGIN OP PROCESSOR TESTING ONLY ***
if (inhibit && op_start_log)
- WriteLog("!!! ^^^ This object is INHIBITED! ^^^ !!!\n");
+{
+ WriteLog("!!! ^^^ This object is INHIBITED! ^^^ !!! (scanline=%u, ypos=%u, height=%u)\n", scanline, ypos, height);
+ DumpScaledObject(p0, op_load_phrase(op_pointer), op_load_phrase(op_pointer+8));
+}
bitmapCounter++;
if (!inhibit) // For OP testing only!
// *** END OP PROCESSOR TESTING ONLY ***
// uint64 height = ((p0 & 0xFFC000) - 0x4000) & 0xFFC000;
uint8 remainder = p2 >> 16, vscale = p2 >> 8;
+//Actually, we should skip this object if it has a vscale of zero.
+//Or do we? Not sure... Atari Karts has a few lines that look like:
+// (SCALED BITMAP)
+//000E8268 --> phrase 00010000 7000B00D
+// [7 (0) x 1 @ (13, 0) (8 bpp), l: 000E82A0, p: 000E0FC0 fp: 00, fl:RELEASE, idx:00, pt:01]
+// [hsc: 9A, vsc: 00, rem: 00]
+// Could it be the vscale is overridden if the DWIDTH is zero? Hmm...
+
if (vscale == 0)
- vscale = 0x20; // OP bug???
+ vscale = 0x20; // OP bug??? Nope, it isn't...! Or is it?
remainder -= 0x20; // 1.0f in [3.5] fixed point format
if (remainder & 0x80) // I.e., it's negative
}
case OBJECT_TYPE_GPU:
{
+//WriteLog("OP: Asserting GPU IRQ #3...\n");
op_set_current_object(p0);
- gpu_set_irq_line(3, 1);
+ GPUSetIRQLine(3, ASSERT_LINE);
+//Also, OP processing is suspended from this point until OBF (F00026) is written to...
+// !!! FIX !!!
+//Do something like:
+//OPSuspendedByGPU = true;
+//Dunno if the OP keeps processing from where it was interrupted, or if it just continues
+//on the next scanline...
break;
}
case OBJECT_TYPE_BRANCH:
switch (cc)
{
case CONDITION_EQUAL:
- if (ypos != 0x7FF && (ypos & 0x01))
- ypos ^= 0x01;
- if ((2 * tom_get_scanline()) == ypos || ypos == 0x7FF)
+//Why do this for the equal case? If they wrote an odd YPOS, then it wouldn't be detected!
+// if (ypos != 0x7FF && (ypos & 0x01))
+// ypos ^= 0x01;
+// if ((2 * tom_get_scanline()) == ypos || ypos == 0x7FF)
+//Here we're using VC instead of the bogus tom_get_scanline() value...
+ if (tom_word_read(0xF00006) == ypos || ypos == 0x7FF)
op_pointer = link;
break;
case CONDITION_LESS_THAN:
- if ((2 * tom_get_scanline()) < ypos)
+// if ((2 * tom_get_scanline()) < ypos)
+ if (tom_word_read(0xF00006) < ypos)
op_pointer = link;
break;
case CONDITION_GREATER_THAN:
- if ((2 * tom_get_scanline()) > ypos)
+// if ((2 * tom_get_scanline()) > ypos)
+ if (tom_word_read(0xF00006) > ypos)
op_pointer = link;
break;
case CONDITION_OP_FLAG_SET:
break;
case CONDITION_SECOND_HALF_LINE:
// This basically means branch if bit 10 of HC is set
- WriteLog("OP: Unexpected CONDITION_SECOND_HALF_LINE in BRANCH object\nop: shuting down\n");
+ WriteLog("OP: Unexpected CONDITION_SECOND_HALF_LINE in BRANCH object\nOP: shuting down\n");
fclose(log_get());
exit(0);
break;
//op_start_log = 0;
// unsure
//WriteLog("OP: --> STOP\n");
- op_set_status_register(((p0>>3) & 0xFFFFFFFF));
+// op_set_status_register(((p0>>3) & 0xFFFFFFFF));
+//This seems more likely...
+ op_set_current_object(p0);
- if (p0 & 0x8)
+ if (p0 & 0x08)
{
tom_set_pending_object_int();
- if (tom_irq_enabled(2) && jaguar_interrupt_handler_is_valid(64))
+ if (tom_irq_enabled(IRQ_OPFLAG) && jaguar_interrupt_handler_is_valid(64))
m68k_set_irq(7); // Cause an NMI to occur...
}
return;
- break;
+// break;
}
default:
WriteLog("op: unknown object type %i\n", ((uint8)p0 & 0x07));
}
//
-// *** NEW ***
// Store fixed size bitmap in line buffer
//
// Need to make sure that when writing that it stays within the line buffer...
// LBUF ($F01800 - $F01D9E) 360 x 32-bit RAM
uint8 depth = (p1 >> 12) & 0x07; // Color depth of image
-//Why is HBlankWidthInPixels subtracted from this???
-// int32 xpos = (((int32)((p1 << 20) & 0xFFFFFFFF)) >> 20) - tom_getHBlankWidthInPixels();
int32 xpos = ((int16)((p1 << 4) & 0xFFFF)) >> 4;// Image xpos in LBUF
uint32 iwidth = (p1 >> 28) & 0x3FF; // Image width in *phrases*
uint32 data = (p0 >> 40) & 0xFFFFF8; // Pixel data address
-#ifdef OP_DEBUG_BMP
+//#ifdef OP_DEBUG_BMP
// Prolly should use this... Though not sure exactly how.
uint32 firstPix = (p1 >> 49) & 0x3F;
-#endif
+ // "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..."
+ firstPix &= 0x3E;
+//#endif
// We can ignore the RELEASE (high order) bit for now--probably forever...!
// uint8 flags = (p1 >> 45) & 0x0F; // REFLECT, RMW, TRANS, RELEASE
//Optimize: break these out to their own BOOL values
uint8 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 index = (p1 >> 37) & 0xFE; // CLUT index offset (upper pix, 1-4 bpp)
uint16 * paletteRAM16 = (uint16 *)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&FLAGS_HFLIP ? "yes" : "no"), (flags&FLAGS_READMODIFY ? "yes" : "no"), (flags&FLAGS_TRANSPARENT ? "yes" : "no"));
+// 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.
//#define OP_DEBUG_BMP
//#ifdef OP_DEBUG_BMP
// WriteLog("bitmap %ix%i %ibpp at %i,%i firstpix=%i data=0x%.8x pitch %i hflipped=%s dwidth=%i (linked to 0x%.8x) Transluency=%s\n",
-// iwidth, height, op_bitmap_bit_depth[bitdepth], xpos, ypos, firstPix, ptr, pitch, (flags&FLAGS_HFLIP ? "yes" : "no"), dwidth, op_pointer, (flags&FLAGS_READMODIFY ? "yes" : "no"));
+// iwidth, height, op_bitmap_bit_depth[bitdepth], xpos, ypos, firstPix, ptr, pitch, (flags&OPFLAG_REFLECT ? "yes" : "no"), dwidth, op_pointer, (flags&OPFLAG_RMW ? "yes" : "no"));
//#endif
- int32 phraseWidthToPixels[8] = { 64, 32, 16, 8, 4, 2, 0, 0 };
// int32 leftMargin = xpos, rightMargin = (xpos + (phraseWidthToPixels[depth] * iwidth)) - 1;
int32 startPos = xpos, endPos = xpos +
- (!(flags & OPFLAG_REFLECT) ? (phraseWidthToPixels[depth] * iwidth) - 1
+ (!flagREFLECT ? (phraseWidthToPixels[depth] * iwidth) - 1
: -((phraseWidthToPixels[depth] * iwidth) + 1));
uint32 clippedWidth = 0, phraseClippedWidth = 0, dataClippedWidth = 0;//, phrasePixel = 0;
bool in24BPPMode = (((GET16(tom_ram_8, 0x0028) >> 1) & 0x03) == 1 ? true : false); // VMODE
// That way, you could simply set XPOS to leftMargin if !REFLECT and to rightMargin otherwise.
// Still have to be careful with the DATA and IWIDTH values though...
-// if ((!(flags & OPFLAG_REFLECT) && (rightMargin < 0 || leftMargin > lbufWidth))
-// || ((flags & OPFLAG_REFLECT) && (leftMargin < 0 || rightMargin > lbufWidth)))
+// if ((!flagREFLECT && (rightMargin < 0 || leftMargin > lbufWidth))
+// || (flagREFLECT && (leftMargin < 0 || rightMargin > lbufWidth)))
// return;
- if ((!(flags & OPFLAG_REFLECT) && (endPos < 0 || startPos > lbufWidth))
- || ((flags & OPFLAG_REFLECT) && (startPos < 0 || endPos > lbufWidth)))
+ if ((!flagREFLECT && (endPos < 0 || startPos > lbufWidth))
+ || (flagREFLECT && (startPos < 0 || endPos > lbufWidth)))
return;
// Otherwise, find the clip limits and clip the phrase as well...
//The strange thing is that it seems to work, but that's no guarantee that it's bulletproof!
//Yup. Seems that JagMania doesn't work correctly with this...
//Dunno if this is the problem, but Atari Karts is showing *some* of the road now...
-// if (!(flags & OPFLAG_REFLECT))
+// if (!flagREFLECT)
/*
if (leftMargin < 0)
// rightMargin = lbufWidth + (clippedWidth % phraseWidthToPixels[depth]);
// rightMargin = lbufWidth;
*/
+if (depth > 5)
+ WriteLog("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...!
if (startPos < 0) // Case #1: Begin out, end in, L to R
if (depth == 0) // 1 BPP
{
-// uint32 paletteIndex = index << 1;
- // The LSB is OPFLAG_REFLECT, so sign extend it and or 2 into it.
+ // The LSB of flags is OPFLAG_REFLECT, so sign extend it and or 2 into it.
int32 lbufDelta = ((int8)((flags << 7) & 0xFF) >> 5) | 0x02;
+ // Fetch 1st phrase...
+ uint64 pixels = ((uint64)jaguar_long_read(data) << 32) | jaguar_long_read(data + 4);
+//Note that firstPix should only be honored *if* we start with the 1st phrase of the bitmap
+//i.e., we didn't clip on the margin...
+ pixels <<= firstPix; // Skip first N pixels (N=firstPix)...
+ int i = firstPix; // Start counter at right spot...
+
while (iwidth--)
{
- // Fetch phrase...
- uint64 pixels = ((uint64)jaguar_long_read(data) << 32) | jaguar_long_read(data + 4);
- data += pitch << 3; // Multiply pitch * 8 (optimize: precompute this value)
-
- for(int i=0; i<64; i++)
+ while (i++ < 64)
{
uint8 bit = pixels >> 63;
-// Seems to me that both of these are in the same endian, so we could cast it as
-// uint16 * 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--this *won't* work...
- if ((flags & OPFLAG_TRANS) && bit == 0)
+ if (flagTRANS && bit == 0)
; // Do nothing...
else
{
- if (!(flags & OPFLAG_RMW))
+ if (!flagRMW)
//Optimize: Set palleteRAM16 to beginning of palette RAM + index*2 and use only [bit] as index...
+//Won't optimize RMW case though...
+ // This is the *only* correct use of endian-dependent code
+ // (i.e., mem-to-mem direct copying)!
*(uint16 *)currentLineBuffer = paletteRAM16[index | bit];
else
*currentLineBuffer =
currentLineBuffer += lbufDelta;
pixels <<= 1;
}
+ i = 0;
+ // Fetch next phrase...
+ data += pitch << 3; // Multiply pitch * 8 (optimize: precompute this value)
+ pixels = ((uint64)jaguar_long_read(data) << 32) | jaguar_long_read(data + 4);
}
}
else if (depth == 1) // 2 BPP
{
+if (firstPix)
+ WriteLog("OP: Fixed bitmap @ 2 BPP requesting FIRSTPIX! (fp=%u)\n", firstPix);
index &= 0xFC; // Top six bits form CLUT index
// The LSB is OPFLAG_REFLECT, so sign extend it and or 2 into it.
int32 lbufDelta = ((int8)((flags << 7) & 0xFF) >> 5) | 0x02;
// 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--this *won't* work...
- if ((flags & OPFLAG_TRANS) && bits == 0)
+ if (flagTRANS && bits == 0)
; // Do nothing...
else
{
- if (!(flags & OPFLAG_RMW))
+ if (!flagRMW)
*(uint16 *)currentLineBuffer = paletteRAM16[index | bits];
else
*currentLineBuffer =
}
else if (depth == 2) // 4 BPP
{
+if (firstPix)
+ WriteLog("OP: Fixed bitmap @ 4 BPP requesting FIRSTPIX! (fp=%u)\n", firstPix);
index &= 0xF0; // Top four bits form CLUT index
// The LSB is OPFLAG_REFLECT, so sign extend it and or 2 into it.
int32 lbufDelta = ((int8)((flags << 7) & 0xFF) >> 5) | 0x02;
// 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--this *won't* work...
- if ((flags & OPFLAG_TRANS) && bits == 0)
+ if (flagTRANS && bits == 0)
; // Do nothing...
else
{
- if (!(flags & OPFLAG_RMW))
+ if (!flagRMW)
*(uint16 *)currentLineBuffer = paletteRAM16[index | bits];
else
*currentLineBuffer =
}
else if (depth == 3) // 8 BPP
{
+if (firstPix)
+ WriteLog("OP: Fixed bitmap @ 8 BPP requesting FIRSTPIX! (fp=%u)\n", firstPix);
// The LSB is OPFLAG_REFLECT, so sign extend it and or 2 into it.
int32 lbufDelta = ((int8)((flags << 7) & 0xFF) >> 5) | 0x02;
// 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--this *won't* work...
- if ((flags & OPFLAG_TRANS) && bits == 0)
+ if (flagTRANS && bits == 0)
; // Do nothing...
else
{
- if (!(flags & OPFLAG_RMW))
+ if (!flagRMW)
*(uint16 *)currentLineBuffer = paletteRAM16[bits];
else
*currentLineBuffer =
}
else if (depth == 4) // 16 BPP
{
+if (firstPix)
+ WriteLog("OP: Fixed bitmap @ 16 BPP requesting FIRSTPIX! (fp=%u)\n", firstPix);
// The LSB is OPFLAG_REFLECT, so sign extend it and or 2 into it.
int32 lbufDelta = ((int8)((flags << 7) & 0xFF) >> 5) | 0x02;
// 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...
- if ((flags & OPFLAG_TRANS) && (bitsLo | bitsHi) == 0)
+ if (flagTRANS && (bitsLo | bitsHi) == 0)
; // Do nothing...
else
{
- if (!(flags & OPFLAG_RMW))
+ if (!flagRMW)
*currentLineBuffer = bitsHi,
*(currentLineBuffer + 1) = bitsLo;
else
}
else if (depth == 5) // 24 BPP
{
-WriteLog("OP: Writing 24 BPP bitmap!\n");
+//Looks like Iron Soldier is the only game that uses 24BPP mode...
+//There *might* be others...
+//WriteLog("OP: Writing 24 BPP bitmap!\n");
+if (firstPix)
+ WriteLog("OP: Fixed bitmap @ 24 BPP requesting FIRSTPIX! (fp=%u)\n", firstPix);
// Not sure, but I think RMW only works with 16 BPP and below, and only in CRY mode...
// The LSB is OPFLAG_REFLECT, so sign extend it and or 4 into it.
int32 lbufDelta = ((int8)((flags << 7) & 0xFF) >> 4) | 0x04;
// 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...
- if ((flags & OPFLAG_TRANS) && (bits3 | bits2 | bits1 | bits0) == 0)
+ if (flagTRANS && (bits3 | bits2 | bits1 | bits0) == 0)
; // Do nothing...
else
*currentLineBuffer = bits3,
}
//
-// *** NEW ***
// Store scaled bitmap in line buffer
//
void OPProcessScaledBitmap(int scanline, uint64 p0, uint64 p1, uint64 p2, bool render)
{
- int32 xpos = (((int32)((p1 << 20) & 0xFFFFFFFF)) >> 20) - tom_getHBlankWidthInPixels();
-// uint16 ypos = ((p0 & 0x3FF8) >> 3) / 2;
- uint16 iwidth = ((p1 >> 28) & 0x3FF) * 4;
- uint16 dwidth = ((p1 >> 18) & 0x3FF) * 4; // Unsigned!
-// uint16 height = (p0 >> 14) & 0x3FF; // Unsigned!
-// uint32 link = ((p0 >> 24) & 0x7FFFF) << 3;
- uint32 ptr = (p0 >> 40) & 0xFFFFF8;
-//unused uint32 firstPix = (p1 >> 49) & 0x3F;
- uint8 flags = (p1 >> 45) & 0x0F;
- uint8 idx = (p1 >> 38) & 0x7F;
- uint8 pitch = (p1 >> 15) & 0x07;
- uint8 bitdepth = (p1 >> 12) & 0x07;
+// Need to make sure that when writing that it stays within the line buffer...
+// LBUF ($F01800 - $F01D9E) 360 x 32-bit RAM
+ uint8 depth = (p1 >> 12) & 0x07; // Color depth of image
+ int32 xpos = ((int16)((p1 << 4) & 0xFFFF)) >> 4;// Image xpos in LBUF
+ uint32 iwidth = (p1 >> 28) & 0x3FF; // Image width in *phrases*
+ uint32 data = (p0 >> 40) & 0xFFFFF8; // Pixel data address
+//#ifdef OP_DEBUG_BMP
+// Prolly should use this... Though not sure exactly how.
+//Use the upper bits as an offset into the phrase depending on the BPP. That's how!
+ uint32 firstPix = (p1 >> 49) & 0x3F;
+//This is WEIRD! I'm sure I saw Atari Karts request 8 BPP FIRSTPIX! What happened???
+if (firstPix)
+ WriteLog("OP: FIRSTPIX != 0!\n");
+//#endif
+// We can ignore the RELEASE (high order) bit for now--probably forever...!
+// uint8 flags = (p1 >> 45) & 0x0F; // REFLECT, RMW, TRANS, RELEASE
+//Optimize: break these out to their own BOOL values
+ uint8 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);
+ uint8 index = (p1 >> 37) & 0xFE; // CLUT index offset (upper pix, 1-4 bpp)
+ uint32 pitch = (p1 >> 15) & 0x07; // Phrase pitch
- int16 scanline_width = tom_getVideoModeWidth();
+// int16 scanlineWidth = tom_getVideoModeWidth();
uint8 * tom_ram_8 = tom_get_ram_pointer();
- uint8 * current_line_buffer = &tom_ram_8[0x1800];
+ uint8 * paletteRAM = &tom_ram_8[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!)
+ uint16 * paletteRAM16 = (uint16 *)paletteRAM;
- uint32 vscale_fixed3p5 = (p2 >> 8) & 0xFF;
- uint32 hscale_fixed3p5 = p2 & 0xFF;
- float vscale = (float)vscale_fixed3p5 / 32.0f, hscale = (float)hscale_fixed3p5 / 32.0f;
+ uint8 hscale = p2 & 0xFF;
+ uint8 horizontalRemainder = hscale; // Not sure if it starts full, but seems reasonable
+ int32 scaledWidthInPixels = (iwidth * phraseWidthToPixels[depth] * hscale) >> 5;
+ uint32 scaledPhrasePixels = (phraseWidthToPixels[depth] * hscale) >> 5;
-//No hacks!
-/* if (jaguar_mainRom_crc32==0x5a5b9c68) // atari karts
- {
- if (vscale == 0.0f)
- vscale = 1.0f;
-
- if (ypos == 0)
- ypos = scanline;
- }*/
-#ifdef OP_DEBUG_BMP
- if (xpos == -3)
- WriteLog("[scanline %i] %ix%i scaled to %ix%i scale (%f, %f)%i bpp pitch %i at (%i,%i) @ 0x%.8x Transluency=%s\n",
- scanline, iwidth,height, (int)(iwidth*hscale), (int)(height*vscale), hscale, vscale,
- op_bitmap_bit_depth[bitdepth], pitch, xpos, ypos, ptr, (flags&FLAGS_READMODIFY) ? "yes" : "no");
-#endif
-//No hacks!
-/* if (jaguar_mainRom_crc32==0x2f032271)
- ypos += 8;*/
-
- if (!render || dwidth == 0 || ptr == 0 || pitch == 0)
- return;
+// 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"));
- if (bitdepth <= 3) // 1, 2, 4, 8 BPP
- iwidth *= 2, dwidth *= 2;
+//Looks like an hscale of zero means don't draw!
+ if (!render || iwidth == 0 || hscale == 0)
+ return;
- uint16 scaled_width = (uint16)((float)iwidth * hscale);
+//#define OP_DEBUG_BMP
+//#ifdef OP_DEBUG_BMP
+// WriteLog("bitmap %ix%i %ibpp at %i,%i firstpix=%i data=0x%.8x pitch %i hflipped=%s dwidth=%i (linked to 0x%.8x) Transluency=%s\n",
+// iwidth, height, op_bitmap_bit_depth[bitdepth], xpos, ypos, firstPix, ptr, pitch, (flags&OPFLAG_REFLECT ? "yes" : "no"), dwidth, op_pointer, (flags&OPFLAG_RMW ? "yes" : "no"));
+//#endif
- if (op_bitmap_bit_depth[bitdepth] == 4) // why ?
- scaled_width *= 2;
+ int32 startPos = xpos, endPos = xpos +
+ (!flagREFLECT ? scaledWidthInPixels - 1 : -(scaledWidthInPixels + 1));
+ uint32 clippedWidth = 0, phraseClippedWidth = 0, dataClippedWidth = 0;
+ bool in24BPPMode = (((GET16(tom_ram_8, 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 limit = GET16(tom_ram_8, 0x0008); // LIMIT
+ int32 limit = 720;
+ int32 lbufWidth = (!in24BPPMode ? limit - 1 : (limit / 2) - 1); // Zero based limit...
- if (op_bitmap_bit_depth[bitdepth] == 2) // why ?
- scaled_width *= 4;
+ // 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.
+// 2. image sits on left edge and REFLECT; starts in bounds but ends out of bounds.
+// 3. image sits on right edge and REFLECT; starts out of bounds but ends in bounds.
+// 4. image sits on right edge and no REFLECT; starts in bounds but ends out of bounds.
+//Numbers 2 & 4 can be caught by checking the LBUF clip while in the inner loop,
+// numbers 1 & 3 are of concern.
+// This *indirectly* handles only cases 2 & 4! And is WRONG is REFLECT is set...!
+// if (rightMargin < 0 || leftMargin > lbufWidth)
- if (op_bitmap_bit_depth[bitdepth] == 1) // why ?
- scaled_width *= 8;
+// It might be easier to swap these (if REFLECTed) and just use XPOS down below...
+// That way, you could simply set XPOS to leftMargin if !REFLECT and to rightMargin otherwise.
+// Still have to be careful with the DATA and IWIDTH values though...
- // visible ?
-/* if ((scanline < ypos) || (scanline > (ypos + scaled_height)) || ((xpos + scaled_width) < 0)
- || (xpos >= scanline_width))*/
- if ((xpos + scaled_width) < 0 || xpos >= scanline_width)
+ if ((!flagREFLECT && (endPos < 0 || startPos > lbufWidth))
+ || (flagREFLECT && (startPos < 0 || endPos > lbufWidth)))
return;
- if (xpos < 0)
- {
- scaled_width += xpos;
- ptr += (pitch * op_bitmap_bit_size[bitdepth] * ((uint32)((-xpos) / hscale))) >> 16;
- xpos = 0;
- }
+ // Otherwise, find the clip limits and clip the phrase as well...
+ // NOTE: I'm fudging here by letting the actual blit overstep the bounds of the
+ // line buffer, but it shouldn't matter since there are two unused line
+ // buffers below and nothing above and I'll at most write 40 bytes outside
+ // the line buffer... I could use a fractional clip begin/end value, but
+ // this makes the blit a *lot* more hairy. I might fix this in the future
+ // if it becomes necessary. (JLH)
+ // Probably wouldn't be *that* hairy. Just use a delta that tells the inner loop
+ // which pixel in the phrase is being written, and quit when either end of phrases
+ // is reached or line buffer extents are surpassed.
- if (iwidth <= 0)
- return;
+//This stuff is probably wrong as well... !!! FIX !!!
+//The strange thing is that it seems to work, but that's no guarantee that it's bulletproof!
+//Yup. Seems that JagMania doesn't work correctly with this...
+//Dunno if this is the problem, but Atari Karts is showing *some* of the road now...
+//Actually, it is! Or, it was. It doesn't seem to be clipping here, so the problem lies
+//elsewhere! Hmm. Putting the scaling code into the 1/2/8 BPP cases seems to draw the ground
+// a bit more accurately... Strange!
+//It's probably a case of the REFLECT flag being set and the background being written
+//from the right side of the screen...
+//But no, it isn't... At least if the diagnostics are telling the truth!
- if (flags & FLAGS_HFLIP)
- {
- if (xpos < 0 || (xpos-scaled_width) >= scanline_width)
- return;
+ // 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...!
- if ((xpos - scaled_width) < 0)
- scaled_width = xpos;
- }
- else
- {
- if ((xpos + scaled_width) < 0 || xpos >= scanline_width)
- return;
+//There's a problem here with scaledPhrasePixels in that it can be forced to zero when
+//the scaling factor is small. So fix it already! !!! FIX !!!
+/*if (scaledPhrasePixels == 0)
+{
+ WriteLog("OP: [Scaled] We're about to encounter a divide by zero error!\n");
+ DumpScaledObject(p0, p1, p2);
+}//*/
+//NOTE: I'm almost 100% sure that this is wrong... And it is! :-p
+ if (startPos < 0) // Case #1: Begin out, end in, L to R
+/* clippedWidth = 0 - startPos,
+ dataClippedWidth = phraseClippedWidth = clippedWidth / phraseWidthToPixels[depth],
+ startPos = 0 - (clippedWidth % phraseWidthToPixels[depth]);*/
+ clippedWidth = 0 - startPos,
+ dataClippedWidth = phraseClippedWidth = clippedWidth / scaledPhrasePixels,
+ startPos = 0 - (clippedWidth % scaledPhrasePixels);
- if ((xpos + scaled_width) > scanline_width)
- scaled_width = scanline_width-xpos;
- }
-
- current_line_buffer += xpos * 2;
+ if (endPos < 0) // Case #2: Begin in, end out, R to L
+/* clippedWidth = 0 - endPos,
+ phraseClippedWidth = clippedWidth / phraseWidthToPixels[depth];*/
+ clippedWidth = 0 - endPos,
+ phraseClippedWidth = clippedWidth / scaledPhrasePixels;
+
+ if (endPos > lbufWidth) // Case #3: Begin in, end out, L to R
+/* clippedWidth = endPos - lbufWidth,
+ phraseClippedWidth = clippedWidth / phraseWidthToPixels[depth];*/
+ clippedWidth = endPos - lbufWidth,
+ phraseClippedWidth = clippedWidth / scaledPhrasePixels;
+
+ if (startPos > lbufWidth) // Case #4: Begin out, end in, R to L
+/* clippedWidth = startPos - lbufWidth,
+ dataClippedWidth = phraseClippedWidth = clippedWidth / phraseWidthToPixels[depth],
+ startPos = lbufWidth + (clippedWidth % phraseWidthToPixels[depth]);*/
+ clippedWidth = startPos - lbufWidth,
+ dataClippedWidth = phraseClippedWidth = clippedWidth / scaledPhrasePixels,
+ startPos = lbufWidth + (clippedWidth % scaledPhrasePixels);
+
+extern int op_start_log;
+if (op_start_log && clippedWidth != 0)
+ WriteLog("OP: Clipped line. SP=%i, EP=%i, clip=%u, iwidth=%u, hscale=%02X\n", startPos, endPos, clippedWidth, iwidth, hscale);
+if (op_start_log && startPos == 13)
+{
+ WriteLog("OP: Scaled line. SP=%i, EP=%i, clip=%u, iwidth=%u, hscale=%02X, depth=%u, firstPix=%u\n", startPos, endPos, clippedWidth, iwidth, hscale, depth, firstPix);
+ DumpScaledObject(p0, p1, p2);
+}
+ // If the image is sitting on the line buffer left or right edge, we need to compensate
+ // by decreasing the image phrase width accordingly.
+ iwidth -= phraseClippedWidth;
+
+ // Also, if we're clipping the phrase we need to make sure we're in the correct part of
+ // the pixel data.
+// data += phraseClippedWidth * (pitch << 3);
+ data += dataClippedWidth * (pitch << 3);
+
+ // NOTE: When the bitmap is in REFLECT mode, the XPOS marks the *right* side of the
+ // bitmap! This makes clipping & etc. MUCH, much easier...!
+// uint32 lbufAddress = 0x1800 + (!in24BPPMode ? leftMargin * 2 : leftMargin * 4);
+ uint32 lbufAddress = 0x1800 + (!in24BPPMode ? startPos * 2 : startPos * 4);
+ uint8 * currentLineBuffer = &tom_ram_8[lbufAddress];
+
+ // Render.
- int32 hscale_fixed = (int32)(65536.0f / hscale);
- int32 cnt = 0;
+// Hmm. We check above for 24 BPP mode, but don't do anything about it below...
+// If we *were* in 24 BPP mode, how would you convert CRY to RGB24? Seems to me
+// that if you're in CRY mode then you wouldn't be able to use 24 BPP bitmaps
+// anyway.
- if (op_bitmap_bit_depth[bitdepth] == 1)
+ if (depth == 0) // 1 BPP
{
- if (pitch == 1)
- {
-#include "zbmpop1.h"
- }
- else
+if (firstPix != 0)
+ WriteLog("OP: Scaled bitmap @ 1 BPP requesting FIRSTPIX!\n");
+ // The LSB of flags is OPFLAG_REFLECT, so sign extend it and or 2 into it.
+ int32 lbufDelta = ((int8)((flags << 7) & 0xFF) >> 5) | 0x02;
+
+ int pixCount = 0;
+ uint64 pixels = ((uint64)jaguar_long_read(data) << 32) | jaguar_long_read(data + 4);
+
+ while ((int32)iwidth > 0)
{
-#include "zbmpop1p.h"
+ uint8 bits = pixels >> 63;
+
+ if (flagTRANS && bits == 0)
+ ; // Do nothing...
+ else
+ {
+ if (!flagRMW)
+ // This is the *only* correct use of endian-dependent code
+ // (i.e., mem-to-mem direct copying)!
+ *(uint16 *)currentLineBuffer = paletteRAM16[index | bits];
+ else
+ *currentLineBuffer =
+ BLEND_CR(*currentLineBuffer, paletteRAM[(index | bits) << 1]),
+ *(currentLineBuffer + 1) =
+ BLEND_Y(*(currentLineBuffer + 1), paletteRAM[((index | bits) << 1) + 1]);
+ }
+
+ currentLineBuffer += lbufDelta;
+
+ horizontalRemainder -= 0x20; // Subtract 1.0f in [3.5] fixed point format
+ while (horizontalRemainder & 0x80)
+ {
+ horizontalRemainder += hscale;
+ pixCount++;
+ pixels <<= 1;
+ }
+
+ if (pixCount > 63)
+ {
+ int phrasesToSkip = pixCount / 64, pixelShift = pixCount % 64;
+
+ data += (pitch << 3) * phrasesToSkip;
+ pixels = ((uint64)jaguar_long_read(data) << 32) | jaguar_long_read(data + 4);
+ pixels <<= 1 * pixelShift;
+ iwidth -= phrasesToSkip;
+ pixCount = pixelShift;
+ }
}
}
- else if (op_bitmap_bit_depth[bitdepth] == 2)
+ else if (depth == 1) // 2 BPP
{
- if (pitch == 1)
- {
-#include "zbmpop2.h"
- }
- else
+if (firstPix != 0)
+ WriteLog("OP: Scaled bitmap @ 2 BPP requesting FIRSTPIX!\n");
+ index &= 0xFC; // Top six bits form CLUT index
+ // The LSB is OPFLAG_REFLECT, so sign extend it and or 2 into it.
+ int32 lbufDelta = ((int8)((flags << 7) & 0xFF) >> 5) | 0x02;
+
+ int pixCount = 0;
+ uint64 pixels = ((uint64)jaguar_long_read(data) << 32) | jaguar_long_read(data + 4);
+
+ while ((int32)iwidth > 0)
{
-#include "zbmpop2p.h"
+ uint8 bits = pixels >> 62;
+
+ if (flagTRANS && bits == 0)
+ ; // Do nothing...
+ else
+ {
+ if (!flagRMW)
+ // This is the *only* correct use of endian-dependent code
+ // (i.e., mem-to-mem direct copying)!
+ *(uint16 *)currentLineBuffer = paletteRAM16[index | bits];
+ else
+ *currentLineBuffer =
+ BLEND_CR(*currentLineBuffer, paletteRAM[(index | bits) << 1]),
+ *(currentLineBuffer + 1) =
+ BLEND_Y(*(currentLineBuffer + 1), paletteRAM[((index | bits) << 1) + 1]);
+ }
+
+ currentLineBuffer += lbufDelta;
+
+ horizontalRemainder -= 0x20; // Subtract 1.0f in [3.5] fixed point format
+ while (horizontalRemainder & 0x80)
+ {
+ horizontalRemainder += hscale;
+ pixCount++;
+ pixels <<= 2;
+ }
+
+ if (pixCount > 31)
+ {
+ int phrasesToSkip = pixCount / 32, pixelShift = pixCount % 32;
+
+ data += (pitch << 3) * phrasesToSkip;
+ pixels = ((uint64)jaguar_long_read(data) << 32) | jaguar_long_read(data + 4);
+ pixels <<= 2 * pixelShift;
+ iwidth -= phrasesToSkip;
+ pixCount = pixelShift;
+ }
}
}
- else if (op_bitmap_bit_depth[bitdepth] == 4)
+ else if (depth == 2) // 4 BPP
{
- if (pitch == 1)
- {
-#include "zbmpop4.h"
- }
- else
+if (firstPix != 0)
+ WriteLog("OP: Scaled bitmap @ 4 BPP requesting FIRSTPIX!\n");
+ index &= 0xF0; // Top four bits form CLUT index
+ // The LSB is OPFLAG_REFLECT, so sign extend it and or 2 into it.
+ int32 lbufDelta = ((int8)((flags << 7) & 0xFF) >> 5) | 0x02;
+
+ int pixCount = 0;
+ uint64 pixels = ((uint64)jaguar_long_read(data) << 32) | jaguar_long_read(data + 4);
+
+ while ((int32)iwidth > 0)
{
-#include "zbmpop4p.h"
+ uint8 bits = pixels >> 60;
+
+ if (flagTRANS && bits == 0)
+ ; // Do nothing...
+ else
+ {
+ if (!flagRMW)
+ // This is the *only* correct use of endian-dependent code
+ // (i.e., mem-to-mem direct copying)!
+ *(uint16 *)currentLineBuffer = paletteRAM16[index | bits];
+ else
+ *currentLineBuffer =
+ BLEND_CR(*currentLineBuffer, paletteRAM[(index | bits) << 1]),
+ *(currentLineBuffer + 1) =
+ BLEND_Y(*(currentLineBuffer + 1), paletteRAM[((index | bits) << 1) + 1]);
+ }
+
+ currentLineBuffer += lbufDelta;
+
+ horizontalRemainder -= 0x20; // Subtract 1.0f in [3.5] fixed point format
+ while (horizontalRemainder & 0x80)
+ {
+ horizontalRemainder += hscale;
+ pixCount++;
+ pixels <<= 4;
+ }
+
+ if (pixCount > 15)
+ {
+ int phrasesToSkip = pixCount / 16, pixelShift = pixCount % 16;
+
+ data += (pitch << 3) * phrasesToSkip;
+ pixels = ((uint64)jaguar_long_read(data) << 32) | jaguar_long_read(data + 4);
+ pixels <<= 4 * pixelShift;
+ iwidth -= phrasesToSkip;
+ pixCount = pixelShift;
+ }
}
}
- else if (op_bitmap_bit_depth[bitdepth] == 8)
+ else if (depth == 3) // 8 BPP
{
- if (pitch == 1)
- {
-#include "zbmpop8.h"
- }
- else
+if (firstPix)
+ WriteLog("OP: Scaled bitmap @ 8 BPP requesting FIRSTPIX! (fp=%u)\n", firstPix);
+ // The LSB is OPFLAG_REFLECT, so sign extend it and or 2 into it.
+ int32 lbufDelta = ((int8)((flags << 7) & 0xFF) >> 5) | 0x02;
+
+ int pixCount = 0;
+ uint64 pixels = ((uint64)jaguar_long_read(data) << 32) | jaguar_long_read(data + 4);
+
+ while ((int32)iwidth > 0)
{
-#include "zbmpop8p.h"
+ uint8 bits = pixels >> 56;
+
+ if (flagTRANS && bits == 0)
+ ; // Do nothing...
+ else
+ {
+ if (!flagRMW)
+ // This is the *only* correct use of endian-dependent code
+ // (i.e., mem-to-mem direct copying)!
+ *(uint16 *)currentLineBuffer = paletteRAM16[bits];
+ else
+ *currentLineBuffer =
+ BLEND_CR(*currentLineBuffer, paletteRAM[bits << 1]),
+ *(currentLineBuffer + 1) =
+ BLEND_Y(*(currentLineBuffer + 1), paletteRAM[(bits << 1) + 1]);
+ }
+
+ currentLineBuffer += lbufDelta;
+
+ horizontalRemainder -= 0x20; // Subtract 1.0f in [3.5] fixed point format
+ while (horizontalRemainder & 0x80)
+ {
+ horizontalRemainder += hscale;
+ pixCount++;
+ pixels <<= 8;
+ }
+
+ if (pixCount > 7)
+ {
+ int phrasesToSkip = pixCount / 8, pixelShift = pixCount % 8;
+
+ data += (pitch << 3) * phrasesToSkip;
+ pixels = ((uint64)jaguar_long_read(data) << 32) | jaguar_long_read(data + 4);
+ pixels <<= 8 * pixelShift;
+ iwidth -= phrasesToSkip;
+ pixCount = pixelShift;
+ }
}
}
- else if (op_bitmap_bit_depth[bitdepth] == 16)
+ else if (depth == 4) // 16 BPP
{
- if (pitch == 1)
+if (firstPix != 0)
+ WriteLog("OP: Scaled bitmap @ 16 BPP requesting FIRSTPIX!\n");
+ // The LSB is OPFLAG_REFLECT, so sign extend it and OR 2 into it.
+ int32 lbufDelta = ((int8)((flags << 7) & 0xFF) >> 5) | 0x02;
+
+ int pixCount = 0;
+ uint64 pixels = ((uint64)jaguar_long_read(data) << 32) | jaguar_long_read(data + 4);
+
+ while ((int32)iwidth > 0)
{
-#include "zbmpop16.h"
+ uint8 bitsHi = pixels >> 56, bitsLo = pixels >> 48;
+
+ if (flagTRANS && (bitsLo | bitsHi) == 0)
+ ; // Do nothing...
+ else
+ {
+ if (!flagRMW)
+ *currentLineBuffer = bitsHi,
+ *(currentLineBuffer + 1) = bitsLo;
+ else
+ *currentLineBuffer =
+ BLEND_CR(*currentLineBuffer, bitsHi),
+ *(currentLineBuffer + 1) =
+ BLEND_Y(*(currentLineBuffer + 1), bitsLo);
+ }
+
+ currentLineBuffer += lbufDelta;
+
+ horizontalRemainder -= 0x20; // Subtract 1.0f in [3.5] fixed point format
+ while (horizontalRemainder & 0x80)
+ {
+ horizontalRemainder += hscale;
+ pixCount++;
+ pixels <<= 16;
+ }
+
+ if (pixCount > 3)
+ {
+ int phrasesToSkip = pixCount / 4, pixelShift = pixCount % 4;
+
+ data += (pitch << 3) * phrasesToSkip;
+ pixels = ((uint64)jaguar_long_read(data) << 32) | jaguar_long_read(data + 4);
+ pixels <<= 16 * pixelShift;
+
+ iwidth -= phrasesToSkip;
+
+ pixCount = pixelShift;
+ }
}
- else
+ }
+ else if (depth == 5) // 24 BPP
+ {
+//I'm not sure that you can scale a 24 BPP bitmap properly--the JTRM seem to indicate as much.
+WriteLog("OP: Writing 24 BPP scaled bitmap!\n");
+if (firstPix != 0)
+ WriteLog("OP: Scaled bitmap @ 24 BPP requesting FIRSTPIX!\n");
+ // Not sure, but I think RMW only works with 16 BPP and below, and only in CRY mode...
+ // The LSB is OPFLAG_REFLECT, so sign extend it and or 4 into it.
+ int32 lbufDelta = ((int8)((flags << 7) & 0xFF) >> 4) | 0x04;
+
+ while (iwidth--)
{
-#include "zbmpop16p.h"
+ // Fetch phrase...
+ uint64 pixels = ((uint64)jaguar_long_read(data) << 32) | jaguar_long_read(data + 4);
+ data += pitch << 3; // Multiply pitch * 8 (optimize: precompute this value)
+
+ for(int i=0; i<2; i++)
+ {
+ uint8 bits3 = pixels >> 56, bits2 = pixels >> 48,
+ bits1 = pixels >> 40, bits0 = pixels >> 32;
+// Seems to me that both of these are in the same endian, so we could cast it as
+// uint16 * 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...
+ if (flagTRANS && (bits3 | bits2 | bits1 | bits0) == 0)
+ ; // Do nothing...
+ else
+ *currentLineBuffer = bits3,
+ *(currentLineBuffer + 1) = bits2,
+ *(currentLineBuffer + 2) = bits1,
+ *(currentLineBuffer + 3) = bits0;
+
+ currentLineBuffer += lbufDelta;
+ pixels <<= 32;
+ }
}
}
- else
- WriteLog("(unimplemented) %i bpp scaled bitmap\n",op_bitmap_bit_depth[bitdepth]);
+/*if (depth == 3 && startPos == 13)
+{
+if (op_start_log)
+WriteLog("OP: Writing in the margins...\n");
+ for(int i=0; i<100*2; i+=2)
+// for(int i=0; i<14*2; i+=2)
+ tom_ram_8[0x1800 + i] = 0xFF,
+ tom_ram_8[0x1800 + i + 1] = 0xFF;
+}*/
+// uint32 lbufAddress = 0x1800 + (!in24BPPMode ? startPos * 2 : startPos * 4);
+// uint8 * currentLineBuffer = &tom_ram_8[lbufAddress];
}
#define MEMCON1 0x00
#define MEMCON2 0x02
#define HC 0x04
+#define VC 0x06
#define VMODE 0x28
#define MODE 0x0006 // Line buffer to video generator mode
#define BGEN 0x0080 // Background enable (CRY & RGB16 only)
#define VS 0x44
#define VDB 0x46
#define VDE 0x48
+#define VI 0x4E
#define BG 0x58
//This can be defined in the makefile as well...
uint16 tom_get_vdb(void)
{
- return GET16(tom_ram_8, VBE);
+ // This in NOT VDB!!!
+// return GET16(tom_ram_8, VBE);
+ return GET16(tom_ram_8, VDB);
}
//
{
tom_scanline = scanline;
- // Increment the horizontal count (why?)
- SET16(tom_ram_8, HC, GET16(tom_ram_8, HC) + 1);
+ // Increment the horizontal count (why? RNG?)
+// tom_word_write(0xF00004, tom_word_read(0xF00004) + 1);
if (render)
{
// Clear line buffer with BG
if (GET16(tom_ram_8, VMODE) & BGEN) // && (CRY or RGB16)...
- for(uint32 i=0; i<tom_real_internal_width; i++)
+ for(uint32 i=0; i<720; i++)
*current_line_buffer++ = bgHI, *current_line_buffer++ = bgLO;
// op_process_list(backbuffer, scanline, render);
}
}
+uint32 TOMGetSDLScreenPitch(void)
+{
+ return surface->pitch();
+}
+
//
// TOM initialization
//
uint32 tom_getVideoModeWidth(void)
{
-// static uint16 onetime = 1;
-
uint16 vmode = GET16(tom_ram_8, VMODE);
uint16 hdb1 = GET16(tom_ram_8, HDB1);
// uint16 hde = GET16(tom_ram_8, HDE);
// uint16 hbb = GET16(tom_ram_8, HBB);
// uint16 hbe = GET16(tom_ram_8, HBE);
- int clock_cycles_per_pixel = (vmode & PWIDTH) >> 9;
+ // NOTE: PWIDTH is value + 1...!
+ int pwidth = ((vmode & PWIDTH) >> 9) + 1;
+ // Also note that the JTRM says that PWIDTH of 4 gives pixels that are "about" square--
+ // this implies that the other modes have pixels that are *not* square!
uint32 width = 640;
- switch (clock_cycles_per_pixel)
+ switch (pwidth)
{
- case 0: width = 640; break;
- case 1: width = 640; break;
- case 2: width = 448; break;
- case 3: width = 320; break;
- case 4: width = 256; break;
+/* case 1: width = 640; break;
+ case 2: width = 640; break;
+ case 3: width = 448; break;
+ case 4: width = 320; break;
case 5: width = 256; break;
case 6: width = 256; break;
- case 7: width = 320; break;
-// default: WriteLog("%i \n",clock_cycles_per_pixel);
+ case 7: width = 256; break;
+ case 8: width = 320; break;//*/
+ case 1: width = 1330; break; // 0.25:1 pixels (X:Y ratio)
+ case 2: width = 665; break; // 0.50:1 pixels
+ case 3: width = 443; break; // 0.75:1 pixels
+ case 4: width = 332; break; // 1.00:1 pixels
+ case 5: width = 266; break; // 1.25:1 pixels
+ case 6: width = 222; break; // 1.50:1 pixels
+ case 7: width = 190; break; // 1.75:1 pixels
+ case 8: width = 166; break; // 2.00:1 pixels
+//Temporary, for testing Doom...
+// case 8: width = 332; break; // 2.00:1 pixels
+//*/
}
-/* if (jaguar_mainRom_crc32 == 0x3c7bfda8) // Kludge for what???
- {
- if (width == 320)
- width += 80;
- if (width == 448)
- width -= 16;
- }//*/
-
if (hdb1 == 123)
hblankWidthInPixels = 16;
else
hblankWidthInPixels = 0;
-// WriteLog("hdb1=%i hbe=%i\n",hdb1,hbe);
+// WriteLog("TOM: HDB1=%i HBE=%i\n", hdb1, hbe);
return width;
}
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 vdb = GET16(tom_ram_8, VDB);
- uint16 vde = GET16(tom_ram_8, VDE);
- uint16 vp = GET16(tom_ram_8, VP);
+ 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);
/* if (vde == 0xFFFF)
vde = vbb;//*/
// VC counts from 0 to VP. VDB starts the OP. Either when
// VDE is reached or VP, the OP is stopped. Let's try it...
// Also note that we're conveniently ignoring interlaced display modes...!
- return ((vde > vp ? vp : vde) - vdb) >> 1;
+// return ((vde > vp ? vp : vde) - vdb) >> 1;
+// return ((vde > vbb ? vbb : vde) - vdb) >> 1;
+//Let's try from the Vertical Blank interval...
+ return (vbb - vbe) >> 1;
}
//
// TOM reset code
// NOTE: Should set up PAL values here when in PAL mode (use BIOS to find default values)
-// for when user starts with -nobios -pal flags...
+// for when user starts with -nobios -pal flags... [DONE]
//
void tom_reset(void)
{
+ extern bool hardwareTypeNTSC;
+
op_reset();
blitter_reset();
pcm_reset();
memset(tom_ram_8, 0x00, 0x4000);
- SET16(tom_ram_8, MEMCON1, 0x1861);
- SET16(tom_ram_8, MEMCON2, 0x0000);
- SET16(tom_ram_8, VMODE, 0x06C1);
- SET16(tom_ram_8, VP, 523);
- SET16(tom_ram_8, HP, 844);
- SET16(tom_ram_8, VS, 523 - 6);
- SET16(tom_ram_8, VBB, 434);
- SET16(tom_ram_8, VBE, 24);
- SET16(tom_ram_8, HBB, 689 + 0x400);
- SET16(tom_ram_8, HBE, 125);
-
- SET16(tom_ram_8, VDE, 2047);//65535);
- SET16(tom_ram_8, VDB, 28);
- SET16(tom_ram_8, HDB1, 166);
- SET16(tom_ram_8, HDE, 2047);//65535);
+
+ if (hardwareTypeNTSC)
+ {
+ SET16(tom_ram_8, MEMCON1, 0x1861);
+ SET16(tom_ram_8, MEMCON2, 0x35CC);
+ SET16(tom_ram_8, HP, 844); // Horizontal Period
+ SET16(tom_ram_8, HBB, 1713); // Horizontal Blank Begin
+ SET16(tom_ram_8, HBE, 125); // Horizontal Blank End
+ SET16(tom_ram_8, HDE, 1665); // Horizontal Display End
+ SET16(tom_ram_8, HDB1, 203); // Horizontal Display Begin 1
+ SET16(tom_ram_8, VP, 523); // Vertical Period (1-based; in this case VP = 524)
+ SET16(tom_ram_8, VBE, 24); // Vertical Blank End
+ SET16(tom_ram_8, VDB, 38); // Vertical Display Begin
+ SET16(tom_ram_8, VDE, 518); // Vertical Display End
+ SET16(tom_ram_8, VBB, 500); // Vertical Blank Begin
+ SET16(tom_ram_8, VS, 517); // Vertical Sync
+ SET16(tom_ram_8, VMODE, 0x06C1);
+ }
+ else // PAL Jaguar
+ {
+ SET16(tom_ram_8, MEMCON1, 0x1861);
+ SET16(tom_ram_8, MEMCON2, 0x35CC);
+ SET16(tom_ram_8, HP, 850); // Horizontal Period
+ SET16(tom_ram_8, HBB, 1711); // Horizontal Blank Begin
+ SET16(tom_ram_8, HBE, 158); // Horizontal Blank End
+ SET16(tom_ram_8, HDE, 1665); // Horizontal Display End
+ SET16(tom_ram_8, HDB1, 203); // Horizontal Display Begin 1
+ SET16(tom_ram_8, VP, 623); // Vertical Period (1-based; in this case VP = 624)
+ SET16(tom_ram_8, VBE, 34); // Vertical Blank End
+ SET16(tom_ram_8, VDB, 38); // Vertical Display Begin
+ SET16(tom_ram_8, VDE, 518); // Vertical Display End
+ SET16(tom_ram_8, VBB, 600); // Vertical Blank Begin
+ SET16(tom_ram_8, VS, 618); // Vertical Sync
+ SET16(tom_ram_8, VMODE, 0x06C1);
+ }
tom_width = tom_real_internal_width = 0;
tom_height = 0;
// It seems so. Perhaps it's the +$8000 offset being written to (32-bit interface)?
// However, the 32-bit interface is WRITE ONLY, so that can't be it...
// Also, the 68K CANNOT make use of the 32-bit interface, since its bus width is only 16-bits...
- offset &= 0xFF3FFF;
+// offset &= 0xFF3FFF;
#ifdef TOM_DEBUG
WriteLog("TOM: Reading byte at %06X\n", offset);
unsigned tom_word_read(unsigned int offset)
{
//???Is this needed???
- offset &= 0xFF3FFF;
+// offset &= 0xFF3FFF;
#ifdef TOM_DEBUG
WriteLog("TOM: Reading word at %06X\n", offset);
#endif
+if (offset >= 0xF02000 && offset <= 0xF020FF)
+ WriteLog("TOM: Read attempted from GPU register file (unimplemented)!\n");
+
if (offset == 0xF000E0)
{
uint16 data = (tom_puck_int_pending << 4) | (tom_timer_int_pending << 3)
//WriteLog("tom: interrupt status is 0x%.4x \n",data);
return data;
}
- else if (offset == 0xF00006) // VC
+//Shoud be handled by the jaguar main loop now...
+/* else if (offset == 0xF00006) // VC
// What if we're in interlaced mode?
// According to docs, in non-interlace mode VC is ALWAYS even...
// return (tom_scanline << 1);// + 1;
//But it's causing Rayman to be fucked up... Why???
- return (tom_scanline << 1) + 1;
+//Because VC is even in NI mode when calling the OP! That's why!
+ return (tom_scanline << 1) + 1;//*/
else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
return gpu_word_read(offset);
else if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
#ifdef TOM_DEBUG
WriteLog("TOM: Writing word %04X at %06X\n", data, offset);
#endif
+if (offset == 0xF00000 + MEMCON1)
+ WriteLog("TOM: Memory Configuration 1 written: %04X\n", data);
+if (offset == 0xF00000 + MEMCON2)
+ WriteLog("TOM: Memory Configuration 2 written: %04X\n", data);
+if (offset >= 0xF02000 && offset <= 0xF020FF)
+ WriteLog("TOM: Write attempted to GPU register file (unimplemented)!\n");
if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
{
gpu_word_write(offset, data);
return;
}
- else if ((offset >= 0xF00000) && (offset < 0xF00002))
+//What's so special about this?
+/* else if ((offset >= 0xF00000) && (offset < 0xF00002))
{
tom_byte_write(offset, data >> 8);
tom_byte_write(offset+1, data & 0xFF);
- }
+ }*/
else if ((offset >= 0xF00010) && (offset < 0xF00028))
{
op_word_write(offset, data);
}
else if (offset == 0xF000E0)
{
+//Check this out...
if (data & 0x0100)
tom_video_int_pending = 0;
if (data & 0x0200)
tom_byte_write(offset, data >> 8);
tom_byte_write(offset+1, data & 0xFF);
- // detect screen resolution changes
- if ((offset >= 0x28) && (offset <= 0x4F))
- {
if (offset == VDB)
- WriteLog("TOM: Vertical Display Begin written: %04X\n", data);
+ WriteLog("TOM: Vertical Display Begin written: %u\n", data);
if (offset == VDE)
- WriteLog("TOM: Vertical Display End written: %04X\n", data);
+ WriteLog("TOM: Vertical Display End written: %u\n", data);
if (offset == VP)
- WriteLog("TOM: Vertical Period written: %04X (%sinterlaced)\n", data, (data & 0x01 ? "non-" : ""));
+ WriteLog("TOM: Vertical Period written: %u (%sinterlaced)\n", data, (data & 0x01 ? "non-" : ""));
if (offset == HDB1)
- WriteLog("TOM: Horizontal Display Begin 1 written: %04X\n", data);
+ WriteLog("TOM: Horizontal Display Begin 1 written: %u\n", data);
if (offset == HDE)
- WriteLog("TOM: Horizontal Display End written: %04X\n", data);
+ WriteLog("TOM: Horizontal Display End written: %u\n", data);
if (offset == HP)
- WriteLog("TOM: Horizontal Period written: %04X\n", data);
+ WriteLog("TOM: Horizontal Period written: %u\n", data);
+if (offset == VBB)
+ WriteLog("TOM: Vertical Blank Begin written: %u\n", data);
+if (offset == VBE)
+ WriteLog("TOM: Vertical Blank End written: %u\n", data);
+if (offset == VS)
+ WriteLog("TOM: Vertical Sync written: %u\n", data);
+if (offset == VI)
+ WriteLog("TOM: Vertical Interrupt written: %u\n", data);
+if (offset == HBB)
+ WriteLog("TOM: Horizontal Blank Begin written: %u\n", data);
+if (offset == HBE)
+ WriteLog("TOM: Horizontal Blank End written: %u\n", data);
if (offset == VMODE)
- WriteLog("TOM: Video Mode written: %04X\n", data);
+ WriteLog("TOM: Video Mode written: %04X (PWIDTH = %u, VC = %u)\n", data, ((data >> 9) & 0x07) + 1, GET16(tom_ram_8, VC));
+ // detect screen resolution changes
+//This may go away in the future, if we do the virtualized screen thing...
+ if ((offset >= 0x28) && (offset <= 0x4F))
+ {
uint32 width = tom_getVideoModeWidth(), height = tom_getVideoModeHeight();
tom_real_internal_width = width;
- if (width == 640)
+//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));
+ memcpy(scanline_render, scanline_render_normal, sizeof(scanline_render));//*/
if ((width != tom_width) || (height != tom_height))
{
int tom_irq_enabled(int irq)
{
- return jaguar_byte_read(0xF000E1) & (1 << irq);
+ // This is the correct byte in big endian... D'oh!
+// return jaguar_byte_read(0xF000E1) & (1 << irq);
+ return tom_ram_8[0xE1] & (1 << irq);
}
-void tom_set_irq_latch(int irq, int enabled)
+//unused
+/*void tom_set_irq_latch(int irq, int enabled)
{
tom_ram_8[0xE0] = (tom_ram_8[0xE0] & (~(1<<irq))) | (enabled ? (1<<irq) : 0);
-}
+}*/
-uint16 tom_irq_control_reg(void)
+//unused
+/*uint16 tom_irq_control_reg(void)
{
return (tom_ram_8[0xE0] << 8) | tom_ram_8[0xE1];
-}
+}*/
void tom_reset_timer(void)
{
- if ((!tom_timer_prescaler) || (!tom_timer_divider))
+ if (!tom_timer_prescaler || !tom_timer_divider)
tom_timer_counter = 0;
else
tom_timer_counter = (1 + tom_timer_prescaler) * (1 + tom_timer_divider);
if (tom_timer_counter <= 0)
{
tom_set_pending_timer_int();
- gpu_set_irq_line(2, 1);
+ GPUSetIRQLine(2, ASSERT_LINE);
if ((tom_irq_enabled(IRQ_TIMER)) && (jaguar_interrupt_handler_is_valid(64)))
m68k_set_irq(7); // Cause a 68000 NMI...
void version_display(FILE * fp)
{
- fprintf(fp, "VirtualJaguar v1.0.4 (Last full build on %s %s)\n", __DATE__, __TIME__);
+ fprintf(fp, "VirtualJaguar v1.0.5 (Last full build on %s %s)\n", __DATE__, __TIME__);
}
void version_done(void)
// Cleanups/fixes by James L. Hammons
//
+//
+// Important info:
+//
+// NTSC PAL
+// GPU/DSP/video clock rate 26.590906 26.593900
+// 68000 clock rate 13.295453 13.296950
+// (clock rates in MHz)
+//
+
// Added by SDLEMU (http://sdlemu.ngemu.com)
// Added for GCC UNIX compatibility
#ifdef __GCCUNIX__
// Added/changed by SDLEMU http://sdlemu.ngemu.com
+uint32 totalFrames;//so we can grab this from somewhere else...
int main(int argc, char * argv[])
{
- uint32 startTime, totalFrames;//, endTime;//, w, h;
+ uint32 startTime;//, totalFrames;//, endTime;//, w, h;
// int32 * vs;
uint32 nNormalLast = 0;
int32 nNormalFrac = 0;
int32 nFrame = 0; // No. of Frame
int32 nJoyport = 0; // Joystick port
- printf("Virtual Jaguar/SDL v1.0.4 (GCC/SDL Port)\n");
+ printf("Virtual Jaguar/SDL v1.0.5 (GCC/SDL Port)\n");
printf("Based upon Virtual Jaguar core v1.0.0 by cal2 of Potato emulation.\n");
printf("Written by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)\n");
printf("Portions massaged by James L. Hammons (WIN32)\n");
jaguar_exec(backbuffer, false);
#endif
// Setting up new backbuffer with new pixels and data
- jaguar_exec(backbuffer, true);
+// jaguar_exec(backbuffer, true);
+ JaguarExecute(backbuffer, true);
totalFrames++;
// Simple frameskip