5 // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
6 // Cleanups by James L. Hammons
15 //#define OP_DEBUG_BMP
16 //WTFITF???static int cnt = 0;
17 extern uint32 jaguar_mainRom_crc32;
19 static uint8 * op_blend_y;
20 static uint8 * op_blend_cc;
22 #define BLEND_Y(dst,src) op_blend_y[(((uint16)dst)<<8) | ((uint16)(src))]
23 #define BLEND_CC(dst,src) op_blend_cc[(((uint16)dst)<<8) | ((uint16)(src))]
25 static uint8 objectp_ram[0x40];
26 uint8 objectp_running;
28 uint8 objectp_stop_reading_list;
30 #define OBJECT_TYPE_BITMAP 0
31 #define OBJECT_TYPE_SCALE 1
32 #define OBJECT_TYPE_GPU 2
33 #define OBJECT_TYPE_BRANCH 3
34 #define OBJECT_TYPE_STOP 4
36 #define OBJECT_TYPE_BITMAP 000
37 #define OBJECT_TYPE_SCALE 001
38 #define OBJECT_TYPE_GPU 010
39 #define OBJECT_TYPE_BRANCH 011
40 #define OBJECT_TYPE_STOP 100
43 #define CONDITION_EQUAL 0
44 #define CONDITION_LESS_THAN 1
45 #define CONDITION_GREATER_THAN 2
46 #define CONDITION_OP_FLAG_SET 3
47 #define CONDITION_SECOND_HALF_LINE 4
49 #define FLAGS_RELEASE 8
50 #define FLAGS_TRANSPARENT 4
51 #define FLAGS_READMODIFY 2
54 static uint8 op_bitmap_bit_depth[8] = { 1, 2, 4, 8, 16, 24, 32, 0 };
55 static uint32 op_bitmap_bit_size[8] =
56 { (uint32)(0.125*65536), (uint32)(0.25*65536), (uint32)(0.5*65536), (uint32)(1*65536),
57 (uint32)(2*65536), (uint32)(1*65536), (uint32)(1*65536), (uint32)(1*65536) };
58 static uint32 op_pointer;
59 //WTFITF???static int cnt_bitmap = 0;
62 // Object Processor bitmap processing
65 void op_process_bitmap(int16 * backbuffer, int scanline, uint64 p0, uint64 p1, int render)
67 uint8 bitdepth = (p1 >> 12) & 0x07;
68 int16 ypos = ((p0 >> 3) & 0x3FF) / 2; // ??? What if not interlaced (/2)?
69 int32 xpos = (((int32)((p1 << 20) & 0xFFFFFFFF)) >> 20) - tom_getHBlankWidthInPixels();
70 int32 iwidth = ((p1 >> 28) & 0x3FF) * 4;
71 int32 dwidth = ((p1 >> 18) & 0x3FF) * 4; // ??? Should it be signed or unsigned ???
72 int16 height = ((p0 >> 14) & 0x3FF) - 1;
73 uint32 link = ((p0 >> 24) & 0x7FFFF) << 3;
74 uint32 ptr = ((p0 >> 43) & 0x1FFFFF) << 3;
76 uint32 firstPix = (p1 >> 49) & 0x3F;
78 uint8 flags = (p1 >> 45) & 0x0F;
79 uint8 idx = (p1 >> 38) & 0x7F;
80 uint32 pitch = (p1 >> 15) & 0x07;
81 int16 scanline_width = tom_getVideoModeWidth();
82 uint8 * tom_ram_8 = tom_get_ram_pointer();
83 uint8 * current_line_buffer = &tom_ram_8[0x1800];
84 uint8 * paletteRam = &tom_ram_8[0x400];
87 //if (scanline == 200)
88 // fprintf(log_get(), "OP --> Current OPPtr: %08X, next: %08X, BMPPtr: %08X\n", op_pointer, link, ptr);
92 if (!render || (op_pointer == 0) || (height < 0) || (dwidth < 0) || (ptr == 0) || (pitch == 0))
96 dwidth = iwidth = height;
98 if (jaguar_mainRom_crc32 == 0x5e705756) // doom
100 if ((iwidth==160)&&(height==179)&&(xpos==-9)&&(ypos==24))
106 // il y a un offset vertical de 20 pour un des bitmaps
107 // dans dinon olympics pour une raison encore inconnue
108 if (jaguar_mainRom_crc32==0x3c7bfda8)
110 if ((iwidth==220)&&(height==184)&&(ypos==0))
116 if (jaguar_mainRom_crc32==0x2f032271)
120 if (op_bitmap_bit_depth[bitdepth] == 24)
125 if (op_bitmap_bit_depth[bitdepth] == 8)
130 if (op_bitmap_bit_depth[bitdepth] == 4)
135 if (op_bitmap_bit_depth[bitdepth] == 2)
140 if (op_bitmap_bit_depth[bitdepth] == 1)
145 // Power Drive Rally (fixed size bitmaps have a 240 lines vertical offset)
146 // but could well be a modulo 240
147 if (jaguar_mainRom_crc32==0x0ab88d90)
151 fprintf(log_get(),"bitmap %ix%i %ibpp at %i,%i firstpix=%i ptr=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");
154 if ((scanline < ypos) || (scanline > (ypos + height)))
157 // seek to the good bitmap scanline
158 // not sure for palettized modes
159 if (op_bitmap_bit_depth[bitdepth] > 8)
160 ptr += ((dwidth * op_bitmap_bit_size[bitdepth]) >> 16) * (scanline - ypos);
162 ptr += dwidth * (scanline - ypos);
167 ptr += (pitch * op_bitmap_bit_size[bitdepth] * (-xpos)) >> 16;
174 fprintf(log_get(), "not rendering because iwidth <= 0\n");
179 if (flags & FLAGS_HFLIP)
181 if ((xpos < 0) || ((xpos - iwidth) >= scanline_width))
184 if ((xpos - iwidth) < 0)
189 if (((xpos + iwidth) < 0) || (xpos >= scanline_width))
192 if ((xpos + iwidth) > scanline_width)
193 iwidth = scanline_width - xpos;
196 current_line_buffer += xpos * 2; // 2 in 16 bpp modes (need to take the mode into account)
198 // doom switches the resolution from 320 to 160 to double the display width
199 // this is not yet supported
204 uint8 d0=jaguar_byte_read(ptr+0);
205 uint8 d1=jaguar_byte_read(ptr+1);
206 *current_line_buffer++=d0;
207 *current_line_buffer++=d1;
208 *current_line_buffer++=d0;
209 *current_line_buffer++=d1;
215 if (op_bitmap_bit_depth[bitdepth] == 1)
223 #include "fbmpop1p.h"
226 else if (op_bitmap_bit_depth[bitdepth] == 2)
234 #include "fbmpop2p.h"
237 else if (op_bitmap_bit_depth[bitdepth] == 4)
245 #include "fbmpop4p.h"
248 else if (op_bitmap_bit_depth[bitdepth] == 8)
256 #include "fbmpop8p.h"
259 else if (op_bitmap_bit_depth[bitdepth] == 16)
263 #include "fbmpop16.h"
267 #include "fbmpop16p.h"
270 else if (op_bitmap_bit_depth[bitdepth] == 24)
274 #include "fbmpop24.h"
278 #include "fbmpop24p.h"
284 // Object Processor scaled bitmap processing
287 void op_process_scaled_bitmap(int16 * backbuffer, int scanline, uint64 p0, uint64 p1, uint64 p2, int render)
289 // if ((render == 0) || (op_pointer == 0) || (height < 0) || (dwidth < 0) || (ptr == 0) || (pitch == 0))
291 int32 xpos = (((int32)((p1 << 20) & 0xFFFFFFFF)) >> 20) - tom_getHBlankWidthInPixels();
292 int16 ypos = ((p0 & 0x3FF8) >> 3) / 2;
293 uint16 iwidth = ((p1 >> 28) & 0x3FF) * 4;
294 int16 dwidth = ((p1 >> 18) & 0x3FF) * 4; // ??? Signed or unsigned ???
295 int16 height = (p0 >> 14) & 0x3FF; // ??? Signed or unsigned ???
296 uint32 link = ((p0 >> 24) & 0x7FFFF) << 3;
297 uint32 ptr = ((p0 >> 43) & 0x1FFFFF) << 3;
298 //unused uint32 firstPix = (p1 >> 49) & 0x3F;
299 uint8 flags = (p1 >> 45) & 0x0F;
300 uint8 idx = (p1 >> 38) & 0x7F;
301 uint8 pitch = (p1 >> 15) & 0x07;
302 uint8 bitdepth = (p1 >> 12) & 0x07;
303 int16 scanline_width = tom_getVideoModeWidth();
304 uint8 * tom_ram_8 = tom_get_ram_pointer();
305 uint8 * current_line_buffer = &tom_ram_8[0x1800];
306 uint32 vscale_fixed3p5 = ((p2 >> 8) & 0xFF);
307 uint32 hscale_fixed3p5 = (p2 & 0xFF);
308 float vscale = (float)vscale_fixed3p5 / 32.0f, hscale = (float)hscale_fixed3p5 / 32.0f;
312 if (jaguar_mainRom_crc32==0x5a5b9c68) // atari karts
322 fprintf(log_get(), "[scanline %i] %ix%i scaled to %ix%i scale (%f, %f)%i bpp pitch %i at (%i,%i) @ 0x%.8x Transluency=%s\n",
323 scanline, iwidth,height, (int)(iwidth*hscale), (int)(height*vscale), hscale, vscale,
324 op_bitmap_bit_depth[bitdepth], pitch, xpos, ypos, ptr, (flags&FLAGS_READMODIFY) ? "yes" : "no");
326 if (jaguar_mainRom_crc32==0x2f032271)
329 if ((render == 0) || (op_pointer == 0) || (height < 0) || (dwidth < 0) || (ptr == 0) || (pitch == 0))
332 if (op_bitmap_bit_depth[bitdepth]==8)
337 if (op_bitmap_bit_depth[bitdepth]==4)
342 if (op_bitmap_bit_depth[bitdepth]==2)
347 if (op_bitmap_bit_depth[bitdepth]==1)
353 uint16 scaled_width = (uint16)((float)iwidth * hscale),
354 scaled_height = (uint16)((float)height * vscale);
356 if (op_bitmap_bit_depth[bitdepth] == 4) // why ?
359 if (op_bitmap_bit_depth[bitdepth] == 2) // why ?
362 if (op_bitmap_bit_depth[bitdepth] == 1) // why ?
365 // seek to the good bitmap scanline
366 // not sure for palettized modes
367 if (op_bitmap_bit_depth[bitdepth] > 8)
368 ptr += ((dwidth * op_bitmap_bit_size[bitdepth]) >> 16) * ((uint32)((scanline - ypos) / vscale));
370 ptr += dwidth * ((uint32)((scanline - ypos) / vscale));
373 if ((scanline < ypos) || (scanline > (ypos+scaled_height)) || ((xpos+scaled_width) < 0)
374 || (xpos >= scanline_width))
379 scaled_width += xpos;
380 ptr += (pitch * op_bitmap_bit_size[bitdepth] * ((uint32)((-xpos) / hscale))) >> 16;
387 if (flags&FLAGS_HFLIP)
389 if ((xpos<0)||((xpos-scaled_width)>=scanline_width))
392 if ((xpos-scaled_width)<0)
397 if (((xpos+scaled_width)<0)||(xpos>=scanline_width))
400 if ((xpos+scaled_width)>scanline_width)
401 scaled_width=scanline_width-xpos;
404 current_line_buffer += xpos * 2;
406 int32 hscale_fixed = (int32)(65536.0f / hscale);
409 if (op_bitmap_bit_depth[bitdepth] == 1)
417 #include "zbmpop1p.h"
420 else if (op_bitmap_bit_depth[bitdepth] == 2)
428 #include "zbmpop2p.h"
431 else if (op_bitmap_bit_depth[bitdepth] == 4)
439 #include "zbmpop4p.h"
442 else if (op_bitmap_bit_depth[bitdepth] == 8)
450 #include "zbmpop8p.h"
453 else if (op_bitmap_bit_depth[bitdepth] == 16)
457 #include "zbmpop16.h"
461 #include "zbmpop16p.h"
465 fprintf(log_get(),"(unimplemented) %i bpp scaled bitmap\n",op_bitmap_bit_depth[bitdepth]);
468 uint64 op_load_phrase(uint32 offset)
470 offset &= ~0x07; // 8 byte alignment
471 return ((uint64)jaguar_long_read(offset) << 32) | (uint64)jaguar_long_read(offset+4);
475 // Object Processor main list processing
478 void op_process_list(int16 * backbuffer, int scanline, int render)
480 // char * condition_to_str[8] =
481 // { "==", "<", ">", "(opflag set)", "(second half line)", "?", "?", "?" };
482 //WTFITF??? cnt_bitmap = 0;
484 if (scanline < tom_get_vdb())
487 if (scanline >= 525)//tom_getVideoModeHeight()+tom_get_vdb())
490 op_pointer = op_get_list_pointer();
492 objectp_stop_reading_list = 0;
495 // if (op_pointer) fprintf(log_get()," new op list at 0x%.8x scanline %i\n",op_pointer,scanline);
498 if (objectp_stop_reading_list)
501 uint64 p0 = op_load_phrase(op_pointer);
503 /*if (scanline == tom_get_vdb())
505 fprintf(log_get(), "%08X --> phrase %08X %08X", op_pointer - 8, (int)(p0>>32), (int)(p0&0xFFFFFFFF));
506 if ((p0 & 0x07) == OBJECT_TYPE_BITMAP)
508 fprintf(log_get(), " (BITMAP) ");
509 uint64 p1 = op_load_phrase(op_pointer);
510 fprintf(log_get(), "\n%08X --> phrase %08X %08X ", op_pointer, (int)(p1>>32), (int)(p1&0xFFFFFFFF));
511 uint8 bitdepth = (p1 >> 12) & 0x07;
512 int16 ypos = ((p0 >> 3) & 0x3FF); // ??? What if not interlaced (/2)?
513 // int32 xpos = (((int32)((p1 << 20) & 0xFFFFFFFF)) >> 20);
514 int32 xpos = p1 & 0xFFF;
515 xpos = (xpos & 0x800 ? xpos | 0xFFFFF000 : xpos);
516 uint32 iwidth = ((p1 >> 28) & 0x3FF);
517 uint32 dwidth = ((p1 >> 18) & 0x3FF); // ??? Should it be signed or unsigned ???
518 int16 height = ((p0 >> 14) & 0x3FF) - 1;
519 uint32 link = ((p0 >> 24) & 0x7FFFF) << 3;
520 uint32 ptr = ((p0 >> 43) & 0x1FFFFF) << 3;
521 uint32 firstPix = (p1 >> 49) & 0x3F;
522 uint8 flags = (p1 >> 45) & 0x0F;
523 uint8 idx = (p1 >> 38) & 0x7F;
524 uint32 pitch = (p1 >> 15) & 0x07;
525 fprintf(log_get(), "[%u (%u) x %u @ %i, %u (%u bpp), l: %08X, p: %08X fp: %02X, fl:%02X, idx:%02X, pt:%02X]\n", iwidth, dwidth, height, xpos, ypos, op_bitmap_bit_depth[bitdepth], link, ptr, firstPix, flags, idx, pitch);
526 uint8 * jaguar_mainRam = GetRamPtr();
527 fprintf(log_get(), "[RAM] --> ");
528 for(int k=0; k<16; k++)
529 fprintf(log_get(), "%02X ", jaguar_mainRam[op_pointer-8 + k]);
530 fprintf(log_get(), "\n");
532 if ((p0 & 0x07) == OBJECT_TYPE_SCALE)
534 fprintf(log_get(), " (SCALED BITMAP)\n");
536 if ((p0 & 0x07) == OBJECT_TYPE_GPU)
537 fprintf(log_get(), " (GPU)\n");
538 if ((p0 & 0x07) == OBJECT_TYPE_BRANCH)
540 fprintf(log_get(), " (BRANCH)\n");
541 uint8 * jaguar_mainRam = GetRamPtr();
542 fprintf(log_get(), "[RAM] --> ");
543 for(int k=0; k<8; k++)
544 fprintf(log_get(), "%02X ", jaguar_mainRam[op_pointer-8 + k]);
545 fprintf(log_get(), "\n");
547 if ((p0 & 0x07) == OBJECT_TYPE_STOP)
548 fprintf(log_get(), " --> List end\n");
551 // fprintf(log_get(),"0x%.8x type %i\n",op_pointer,((uint8)p0&0x07));
552 switch ((uint8)p0 & 0x07)
554 case OBJECT_TYPE_BITMAP:
556 uint64 p1 = op_load_phrase(op_pointer);
558 op_process_bitmap(backbuffer, scanline, p0, p1, render);
561 case OBJECT_TYPE_SCALE:
563 uint64 p1 = op_load_phrase(op_pointer);
565 uint64 p2 = op_load_phrase(op_pointer);
567 op_process_scaled_bitmap(backbuffer, scanline, p0, p1, p2, render);
570 case OBJECT_TYPE_GPU:
572 //unused uint64 data = p0 >> 3;
573 op_set_current_object(p0);
574 gpu_set_irq_line(3, 1);
577 case OBJECT_TYPE_BRANCH:
579 uint16 vcnt = (p0 >> 3) & 0x7FF;
580 uint8 cc = (p0 >> 14) & 0x03;
581 uint32 link = ((p0 >> 24) & 0x1FFFFF) << 3;
583 // if ((vcnt!=507)&&(vcnt!=25))
584 // fprintf(log_get(),"\t%i%s%i link=0x%.8x\n",scanline,condition_to_str[cc],vcnt>>1,link);
587 case CONDITION_EQUAL:
588 if ((vcnt != 0x7FF) && (vcnt & 0x01))
590 if (((2 * tom_get_scanline()) == vcnt) || (vcnt == 0x7FF))
593 case CONDITION_LESS_THAN:
594 if ((2 * tom_get_scanline()) < vcnt)
597 case CONDITION_GREATER_THAN:
598 if ((2 * tom_get_scanline()) > vcnt)
601 case CONDITION_OP_FLAG_SET:
602 if (op_get_status_register() & 0x01)
605 case CONDITION_SECOND_HALF_LINE:
606 fprintf(log_get(), "op: unexpected CONDITION_SECOND_HALF_LINE in BRANCH object\nop: shuting down\n");
611 fprintf(log_get(),"op: unimplemented branch condition %i\n", cc);
615 case OBJECT_TYPE_STOP:
618 op_set_status_register(((p0>>3) & 0xFFFFFFFF));
622 tom_set_pending_object_int();
623 if ((tom_irq_enabled(2)) && (jaguar_interrupt_handler_is_valid(64)))
625 // s68000interrupt(7,64);
626 // s68000flushInterrupts();
627 m68k_set_irq(7); // Cause an NMI to occur...
635 fprintf(log_get(),"op: unknown object type %i\n", ((uint8)p0 & 0x07));
642 // Object Processor initialization
647 memory_malloc_secure((void **)&op_blend_y, 0x10000, "Jaguar Object processor Y blend lookup table");
648 memory_malloc_secure((void **)&op_blend_cc, 0x10000, "Jaguar Object processor C blend lookup table");
650 for(int i=0; i<256*256; i++)
652 int y = (i >> 8) & 0xFF;
653 int dy = (int8)(i & 0xFF);
662 for(int i=0; i<256*256; i++)
664 int cl = (i >> 8) & 0xFF;
665 int dcl = (int8)(i & 0xFF);
677 // Object Processor reset
682 memset(objectp_ram, 0x00, 0x40);
690 void op_byte_write(uint32 offset, uint8 data)
693 objectp_ram[offset] = data;
696 void op_word_write(uint32 offset, uint16 data)
699 objectp_ram[offset] = (data >> 8) & 0xFF;
700 objectp_ram[offset+1] = data & 0xFF;
702 /*if (offset == 0x20)
703 fprintf(log_get(), "OP: Setting lo list pointer: %04X\n", data);
705 fprintf(log_get(), "OP: Setting hi list pointer: %04X\n", data);//*/
708 // Memory range: F00010 - F00027
710 uint8 op_byte_read(uint32 offset)
713 return objectp_ram[offset];
716 uint16 op_word_read(uint32 offset)
718 return (objectp_ram[offset & 0x3F] << 8) | objectp_ram[(offset+1) & 0x3F];
721 // F00010-F00017 R xxxxxxxx xxxxxxxx OB - current object code from the graphics processor
722 // F00020-F00023 W xxxxxxxx xxxxxxxx OLP - start of the object list
723 // F00026 W -------- -------x OBF - object processor flag
725 uint32 op_get_list_pointer(void)
727 // Note: This register is WORD swapped, hence the funky look of this...
728 /* uint32 ptr = objectp_ram[0x22];
730 ptr |= objectp_ram[0x23];
732 ptr |= objectp_ram[0x20];
734 ptr |= objectp_ram[0x21];
735 fprintf(log_get(), "OP: Getting list pointer: %08X\n", (unsigned int)ptr);
739 return (objectp_ram[0x22] << 24) | (objectp_ram[0x23] << 16) | (objectp_ram[0x20] << 8) | objectp_ram[0x21];
742 uint32 op_get_status_register(void)
744 /* uint32 ptr = objectp_ram[0x26];
746 ptr |= objectp_ram[0x27];
748 ptr |= objectp_ram[0x28];
750 ptr |= objectp_ram[0x29];
753 return (objectp_ram[0x26] << 24) | (objectp_ram[0x27] << 16) | (objectp_ram[0x28] << 8) | objectp_ram[0x29];
756 void op_set_status_register(uint32 data)
758 objectp_ram[0x26] = (data & 0xFF000000) >> 24;
759 objectp_ram[0x27] = (data & 0x00FF0000) >> 16;
760 objectp_ram[0x28] = (data & 0x0000FF00) >> 8;
761 objectp_ram[0x29] |= (data & 0xFE);
764 void op_set_current_object(uint64 object)
767 32 28 24 20 16 12 8 4 0
768 +--------^---------^---------^--------^--------^--------^--------^--------+
770 +-------------------------------------------------------------------------+
772 64 60 56 52 48 44 40 36 32
773 +--------^---------^---------^--------^--------^--------^--------^--------+
775 +-------------------------------------------------------------------------+
777 // Stored as least significant 32 bits first, ms32 last in big endian
778 objectp_ram[0x13] = object & 0xFF; object >>= 8;
779 objectp_ram[0x12] = object & 0xFF; object >>= 8;
780 objectp_ram[0x11] = object & 0xFF; object >>= 8;
781 objectp_ram[0x10] = object & 0xFF; object >>= 8;
783 objectp_ram[0x17] = object & 0xFF; object >>= 8;
784 objectp_ram[0x16] = object & 0xFF; object >>= 8;
785 objectp_ram[0x15] = object & 0xFF; object >>= 8;
786 objectp_ram[0x14] = object & 0xFF;