render.c
1 /* 2 only update window clip on window change (?) 3 fix leftmost window/nta render and window bug 4 sprite masking isn't right in sonic/micromachines 2, but 5 seems ok in galaxy force 2 6 */ 7 8 9 #include "shared.h" 10 #include "platform_config.h" 11 12 #ifdef HAS_T4_VGA 13 #include "vga_t_dma.h" 14 #endif 15 extern void emu_DrawLine16(unsigned short *src, int width , int height, int line); 16 extern void emu_printf(char * text); 17 18 19 #ifdef ALIGN_LONG 20 21 /* Or change the names if you depend on these from elsewhere.. */ 22 #undef READ_LONG 23 #undef WRITE_LONG 24 25 26 27 if(reg[12] & 8) 28 { 29 int j; 30 for(j = 0; j < 3; j += 1) 31 { 32 color = &vdp_palette[j][data]; 33 set_color((j << 6), color); 34 } 35 } 36 else 37 { 38 color = &vdp_palette[1][data]; 39 set_color(0x00, color); 40 set_color(0x40, color); 41 set_color(0x80, color); 42 } 43 44 45 46 static __inline__ uint32 READ_LONG(void *address) 47 { 48 if ((uint32)address & 3) 49 { 50 #ifdef LSB_FIRST /* little endian version */ 51 return ( *((uint8 *)address) + 52 (*((uint8 *)address+1) << 8) + 53 (*((uint8 *)address+2) << 16) + 54 (*((uint8 *)address+3) << 24) ); 55 #else /* big endian version */ 56 return ( *((uint8 *)address+3) + 57 (*((uint8 *)address+2) << 8) + 58 (*((uint8 *)address+1) << 16) + 59 (*((uint8 *)address) << 24) ); 60 #endif /* LSB_FIRST */ 61 } 62 else 63 return *(uint32 *)address; 64 } 65 66 static __inline__ void WRITE_LONG(void *address, uint32 data) 67 { 68 if ((uint32)address & 3) 69 { 70 #ifdef LSB_FIRST 71 *((uint8 *)address) = data; 72 *((uint8 *)address+1) = (data >> 8); 73 *((uint8 *)address+2) = (data >> 16); 74 *((uint8 *)address+3) = (data >> 24); 75 #else 76 *((uint8 *)address+3) = data; 77 *((uint8 *)address+2) = (data >> 8); 78 *((uint8 *)address+1) = (data >> 16); 79 *((uint8 *)address) = (data >> 24); 80 #endif /* LSB_FIRST */ 81 return; 82 } 83 else 84 *(uint32 *)address = data; 85 } 86 87 #endif /* ALIGN_LONG */ 88 89 #ifdef ALIGN_LONG 90 /* Draw a single 8-pixel column */ 91 #define DRAW_COLUMN(ATTR, LINE) \ 92 atex = atex_table[(ATTR >> 13) & 7]; \ 93 src = (uint32 *)&bg_pattern_cache[(ATTR & 0x0FFF) << 6 | (LINE)]; \ 94 WRITE_LONG(dst, READ_LONG(src) | atex); \ 95 dst++; \ 96 src++; \ 97 WRITE_LONG(dst, READ_LONG(src) | atex); \ 98 dst++; \ 99 src++; \ 100 ATTR >>= 16; \ 101 atex = atex_table[(ATTR >> 13) & 7]; \ 102 src = (uint32 *)&bg_pattern_cache[(ATTR & 0x0FFF) << 6 | (LINE)]; \ 103 WRITE_LONG(dst, READ_LONG(src) | atex); \ 104 dst++; \ 105 src++; \ 106 WRITE_LONG(dst, READ_LONG(src) | atex); \ 107 dst++; \ 108 src++; 109 110 111 /* Draw a single 16-pixel column */ 112 #define DRAW_COLUMN_IM2(ATTR, LINE) \ 113 atex = atex_table[(ATTR >> 13) & 7]; \ 114 offs = (ATTR & 0x03FF) << 7 | (ATTR & 0x0800) << 6 | (LINE); \ 115 if(ATTR & 0x1000) offs ^= 0x40; \ 116 src = (uint32 *)&bg_pattern_cache[offs]; \ 117 WRITE_LONG(dst, READ_LONG(src) | atex); \ 118 dst++; \ 119 src++; \ 120 WRITE_LONG(dst, READ_LONG(src) | atex); \ 121 dst++; \ 122 src++; \ 123 ATTR >>= 16; \ 124 atex = atex_table[(ATTR >> 13) & 7]; \ 125 offs = (ATTR & 0x03FF) << 7 | (ATTR & 0x0800) << 6 | (LINE); \ 126 if(ATTR & 0x1000) offs ^= 0x40; \ 127 src = (uint32 *)&bg_pattern_cache[offs]; \ 128 WRITE_LONG(dst, READ_LONG(src) | atex); \ 129 dst++; \ 130 src++; \ 131 WRITE_LONG(dst, READ_LONG(src) | atex); \ 132 dst++; \ 133 src++; 134 135 #else 136 137 #define DRAW_COLUMN(ATTR, LINE) \ 138 atex = atex_table[(ATTR >> 13) & 7]; \ 139 src = (uint32 *)&bg_pattern_cache[(ATTR & 0x0FFF) << 6 | (LINE)]; \ 140 *dst++ = (*src++ | atex); \ 141 *dst++ = (*src++ | atex); \ 142 ATTR >>= 16; \ 143 atex = atex_table[(ATTR >> 13) & 7]; \ 144 src = (uint32 *)&bg_pattern_cache[(ATTR & 0x0FFF) << 6 | (LINE)]; \ 145 *dst++ = (*src++ | atex); \ 146 *dst++ = (*src++ | atex); 147 148 #define DRAW_COLUMN_IM2(ATTR, LINE) \ 149 atex = atex_table[(ATTR >> 13) & 7]; \ 150 offs = (ATTR & 0x03FF) << 7 | (ATTR & 0x0800) << 6 | (LINE); \ 151 if(ATTR & 0x1000) offs ^= 0x40; \ 152 src = (uint32 *)&bg_pattern_cache[offs]; \ 153 *dst++ = (*src++ | atex); \ 154 *dst++ = (*src++ | atex); \ 155 ATTR >>= 16; \ 156 atex = atex_table[(ATTR >> 13) & 7]; \ 157 offs = (ATTR & 0x03FF) << 7 | (ATTR & 0x0800) << 6 | (LINE); \ 158 if(ATTR & 0x1000) offs ^= 0x40; \ 159 src = (uint32 *)&bg_pattern_cache[offs]; \ 160 *dst++ = (*src++ | atex); \ 161 *dst++ = (*src++ | atex); 162 163 164 165 #endif /* ALIGN_LONG */ 166 167 168 169 /* 170 gcc complains about this: 171 *lb++ = table[(*lb << 8) |(*src++ | palette)]; 172 .. claiming the result on lb is undefined. 173 So we manually advance lb and use constant offsets into the line buffer. 174 */ 175 #define DRAW_SPRITE_TILE \ 176 lb[0] = table[(lb[0] << 8) |(*src++ | palette)]; \ 177 lb[1] = table[(lb[1] << 8) |(*src++ | palette)]; \ 178 lb[2] = table[(lb[2] << 8) |(*src++ | palette)]; \ 179 lb[3] = table[(lb[3] << 8) |(*src++ | palette)]; \ 180 lb[4] = table[(lb[4] << 8) |(*src++ | palette)]; \ 181 lb[5] = table[(lb[5] << 8) |(*src++ | palette)]; \ 182 lb[6] = table[(lb[6] << 8) |(*src++ | palette)]; \ 183 lb[7] = table[(lb[7] << 8) |(*src++ | palette)] 184 185 /* Pixel creation macros, input is four bits each */ 186 187 /* 3:3:2 RGB */ 188 #define MAKE_PIXEL_8(r,g,b) ((r) << 5 | (g) << 2 | ((b) >> 1)) 189 190 /* 5:6:5 RGB */ 191 #define MAKE_PIXEL_16(r,g,b) ((r) << 12 | (g) << 7 | (b) << 1) 192 193 /* Clip data */ 194 static clip_t clip[2]; 195 196 /* Attribute expansion table */ 197 static const uint32 atex_table[] = { 198 0x00000000, 0x10101010, 0x20202020, 0x30303030, 199 0x40404040, 0x50505050, 0x60606060, 0x70707070 200 }; 201 202 /* Sprite name look-up table */ 203 static uint8 name_lut[0x400]; 204 205 /* Sprite line buffer data */ 206 static uint8 object_index_count; 207 208 struct { 209 uint16 ypos; 210 uint16 xpos; 211 uint16 attr; 212 uint8 size; 213 uint8 index; 214 }object_info[20]; 215 216 /* Pixel look-up tables and table base address */ 217 static uint8 *lut[5]; 218 #include "genlut.h" 219 220 /* 16-bit pixel remapping data */ 221 static uint16 pixel_16[0x100]; 222 static uint16 pixel_16_lut[3][0x200]; 223 224 /* Line buffers */ 225 static uint8 tmp_buf[0x400]; /* Temporary buffer */ 226 static uint8 bg_buf[0x400]; /* Merged background buffer */ 227 static uint8 nta_buf[0x400]; /* Plane A / Window line buffer */ 228 static uint8 ntb_buf[0x400]; /* Plane B line buffer */ 229 static uint8 obj_buf[0x400]; /* Object layer line buffer */ 230 231 static uint16 line_buf[0x400]; 232 233 234 235 /*--------------------------------------------------------------------------*/ 236 /* Init, reset, shutdown routines */ 237 /*--------------------------------------------------------------------------*/ 238 239 int render_init(void) 240 { 241 int i; 242 243 /* Pixel look-up tables */ 244 lut[0] = (uint8 *)(lut_base); 245 for(i = 1; i < LUT_MAX; i += 1) 246 { 247 lut[i] = lut[0] + (i * LUT_SIZE); 248 } 249 250 /* Make pixel data tables */ 251 for(i = 0; i < 0x200; i += 1) 252 { 253 int r, g, b; 254 255 r = (i >> 6) & 7; 256 g = (i >> 3) & 7; 257 b = (i >> 0) & 7; 258 259 pixel_16_lut[0][i] = MAKE_PIXEL_16(r,g,b); 260 pixel_16_lut[1][i] = MAKE_PIXEL_16(r<<1,g<<1,b<<1); 261 pixel_16_lut[2][i] = MAKE_PIXEL_16(r|8,g|8,b|8); 262 } 263 264 265 /* Set up color update function */ 266 color_update = color_update_16; 267 268 /* Make sprite name look-up table */ 269 make_name_lut(); 270 271 return (1); 272 } 273 274 void make_name_lut(void) 275 { 276 int col, row; 277 int vcol, vrow; 278 int width, height; 279 int flipx, flipy; 280 int i, name; 281 282 memset(name_lut, 0, sizeof(name_lut)); 283 284 for(i = 0; i < 0x400; i += 1) 285 { 286 vcol = col = i & 3; 287 vrow = row = (i >> 2) & 3; 288 height = (i >> 4) & 3; 289 width = (i >> 6) & 3; 290 flipx = (i >> 8) & 1; 291 flipy = (i >> 9) & 1; 292 293 if(flipx) 294 vcol = (width - col); 295 if(flipy) 296 vrow = (height - row); 297 298 name = vrow + (vcol * (height + 1)); 299 300 if((row > height) || col > width) 301 name = -1; 302 303 name_lut[i] = name; 304 } 305 } 306 307 308 309 void render_reset(void) 310 { 311 memset(&clip, 0, sizeof(clip)); 312 313 memset(bg_buf, 0, sizeof(bg_buf)); 314 memset(tmp_buf, 0, sizeof(tmp_buf)); 315 memset(nta_buf, 0, sizeof(nta_buf)); 316 memset(ntb_buf, 0, sizeof(ntb_buf)); 317 memset(obj_buf, 0, sizeof(obj_buf)); 318 319 //memset(&pixel_8, 0, sizeof(pixel_8)); 320 memset(&pixel_16, 0, sizeof(pixel_16)); 321 } 322 323 324 void render_shutdown(void) 325 { 326 } 327 328 /*--------------------------------------------------------------------------*/ 329 /* Line render function */ 330 /*--------------------------------------------------------------------------*/ 331 332 void render_line(int line) 333 { 334 // uint8 *lb = (gbitmap.remap == 1) ? tmp_buf : &gbitmap.data[(line * gbitmap.pitch)]; 335 uint8 *lb = tmp_buf; 336 337 if((reg[1] & 0x40) == 0x00) 338 { 339 /* Use the overscan color to clear the screen */ 340 memset(&lb[gbitmap.viewport.x], 0x40 | border, gbitmap.viewport.w); 341 } 342 else 343 { 344 update_bg_pattern_cache(); 345 window_clip(line); 346 347 if(im2_flag) 348 { 349 render_ntx_im2(0, line, nta_buf); 350 render_ntx_im2(1, line, ntb_buf); 351 } 352 else 353 { 354 if(reg[0x0B] & 4) 355 { 356 render_ntx_vs(0, line, nta_buf); 357 render_ntx_vs(1, line, ntb_buf); 358 } 359 else 360 { 361 render_ntx(0, line, nta_buf); 362 render_ntx(1, line, ntb_buf); 363 } 364 } 365 366 if(im2_flag) 367 render_ntw_im2(line, nta_buf); 368 else 369 render_ntw(line, nta_buf); 370 371 if(reg[12] & 8) 372 { 373 merge(&nta_buf[0x20], &ntb_buf[0x20], &bg_buf[0x20], lut[2], (reg[12] & 1) ? 320 : 256); 374 memset(&obj_buf[0x20], 0, (reg[12] & 1) ? 320 : 256); 375 376 if(im2_flag) 377 render_obj_im2(line, obj_buf, lut[3]); 378 else 379 render_obj(line, obj_buf, lut[3]); 380 381 merge(&obj_buf[0x20], &bg_buf[0x20], &lb[0x20], lut[4], (reg[12] & 1) ? 320 : 256); 382 } 383 else 384 { 385 merge(&nta_buf[0x20], &ntb_buf[0x20], &lb[0x20], lut[0], (reg[12] & 1) ? 320 : 256); 386 if(im2_flag) 387 render_obj_im2(line, lb, lut[1]); 388 else 389 render_obj(line, lb, lut[1]); 390 } 391 } 392 393 if(reg[0] & 0x20) 394 { 395 memset(&lb[gbitmap.viewport.x], 0x40 | border, 0x08); 396 } 397 398 399 int width = (reg[12] & 1) ? 320 : 256; 400 remap_16(lb+0x20, line_buf, pixel_16, width); 401 emu_DrawLine16(line_buf, width ,256, line); 402 } 403 /*--------------------------------------------------------------------------*/ 404 /* Window rendering */ 405 /*--------------------------------------------------------------------------*/ 406 407 void render_ntw(int line, uint8 *buf) 408 { 409 int column, v_line, width; 410 uint32 *nt, *src, *dst, atex, atbuf; 411 412 v_line = (line & 7) << 3; 413 width = (reg[12] & 1) ? 7 : 6; 414 415 nt = (uint32 *)&vram[ntwb | ((line >> 3) << width)]; 416 dst = (uint32 *)&buf[0x20 + (clip[1].left << 4)]; 417 418 for(column = clip[1].left; column < clip[1].right; column += 1) 419 { 420 atbuf = nt[column]; 421 DRAW_COLUMN(atbuf, v_line) 422 } 423 } 424 425 void render_ntw_im2(int line, uint8 *buf) 426 { 427 int column, v_line, width; 428 uint32 *nt, *src, *dst, atex, atbuf, offs; 429 430 v_line = ((line & 7) << 1 | ((status >> 4) & 1)) << 3; 431 width = (reg[12] & 1) ? 7 : 6; 432 433 nt = (uint32 *)&vram[ntwb | ((line >> 3) << width)]; 434 dst = (uint32 *)&buf[0x20 + (clip[1].left << 4)]; 435 436 for(column = clip[1].left; column < clip[1].right; column += 1) 437 { 438 atbuf = nt[column]; 439 DRAW_COLUMN_IM2(atbuf, v_line) 440 } 441 } 442 443 /*--------------------------------------------------------------------------*/ 444 /* Background plane rendering */ 445 /*--------------------------------------------------------------------------*/ 446 447 void render_ntx(int which, int line, uint8 *buf) 448 { 449 int column; 450 int start, end; 451 int index; 452 int shift; 453 int nametable_row_mask = (playfield_col_mask >> 1); 454 int v_line; 455 uint32 atex, atbuf, *src, *dst; 456 uint16 xascroll, xbscroll, xscroll; 457 int y_scroll; 458 uint32 *nt; 459 int vsr_shift; 460 uint32 *vs; 461 uint16 table; 462 463 464 465 466 table = (which) ? ntbb : ntab; 467 468 get_hscroll(line, &xascroll, &xbscroll); 469 xscroll = (which) ? xbscroll : xascroll; 470 471 shift = (xscroll & 0x0F); 472 index = ((playfield_col_mask + 1) >> 1) - ((xscroll >> 4) & nametable_row_mask); 473 474 if(which) 475 { 476 start = 0; 477 end = (reg[0x0C] & 1) ? 20 : 16; 478 } 479 else 480 { 481 // Looks correct if clip[0].left has 1 subtracted 482 // Otherwise window has gap between endpoint and where the first normal 483 // nta column starts 484 485 if(clip[0].enable == 0) return; 486 start = clip[0].left; 487 end = clip[0].right; 488 index = (index + clip[0].left) & nametable_row_mask; 489 } 490 491 vsr_shift = (which) ? 16 : 0; 492 vs = (uint32 *)&vsram[0]; 493 494 y_scroll = (vs[0] >> vsr_shift) & 0xFFFF; 495 496 // int dy = line & 0x7; 497 // int rev_line = (line & 0x1f8) + (dy^7); 498 499 y_scroll = (line + (y_scroll & 0x3FF)) & playfield_row_mask; 500 501 int dy = y_scroll & 0x7; 502 int y_scroll2 = (y_scroll & 0x1f8) + (dy^7); 503 504 505 506 507 v_line = (y_scroll & 7) << 3; 508 int v_line2 = (y_scroll2 & 7) << 3; 509 510 nt = (uint32 *)&vram[table + (((y_scroll >> 3) << playfield_shift) & y_mask)]; 511 512 if(shift) 513 { 514 dst = (uint32 *)&buf[0x20-(0x10-shift)]; 515 atbuf = nt[(index-1) & nametable_row_mask]; 516 //DRAW_COLUMN(atbuf, v_line) 517 // JMH 518 if (atbuf & 0x1000) { 519 DRAW_COLUMN(atbuf, v_line2); 520 } 521 else { 522 DRAW_COLUMN(atbuf, v_line); 523 } 524 } 525 buf = (buf + 0x20 + shift); 526 dst = (uint32 *)&buf[start<<4]; 527 528 529 530 for(column = start; column < end; column += 1, index += 1) 531 { 532 atbuf = nt[index & nametable_row_mask]; 533 // JMH 534 if (atbuf & 0x1000) { 535 DRAW_COLUMN(atbuf, v_line2); 536 } 537 else 538 { 539 DRAW_COLUMN(atbuf, v_line); 540 } 541 } 542 543 } 544 545 546 void render_ntx_im2(int which, int line, uint8 *buf) 547 { 548 int column; 549 int start, end; 550 int index; 551 int shift; 552 int nametable_row_mask = (playfield_col_mask >> 1); 553 int v_line; 554 uint32 atex, atbuf, *src, *dst; 555 uint16 xascroll, xbscroll, xscroll; 556 int y_scroll; 557 uint32 *nt; 558 int vsr_shift; 559 uint32 *vs; 560 uint16 table; 561 uint32 offs; 562 563 table = (which) ? ntbb : ntab; 564 565 get_hscroll(line, &xascroll, &xbscroll); 566 xscroll = (which) ? xbscroll : xascroll; 567 568 shift = (xscroll & 0x0F); 569 index = ((playfield_col_mask + 1) >> 1) - ((xscroll >> 4) & nametable_row_mask); 570 571 if(which) 572 { 573 start = 0; 574 end = (reg[0x0C] & 1) ? 20 : 16; 575 } 576 else 577 { 578 if(clip[0].enable == 0) return; 579 start = clip[0].left; 580 end = clip[0].right; 581 index = (index + clip[0].left) & nametable_row_mask; 582 } 583 584 vsr_shift = (which) ? 16 : 0; 585 vs = (uint32 *)&vsram[0]; 586 587 y_scroll = (vs[0] >> vsr_shift) & 0xFFFF; 588 y_scroll = (line + ((y_scroll >> 1) & 0x3FF)) & playfield_row_mask; 589 v_line = (((y_scroll & 7) << 1) | ((status >> 4) & 1)) << 3; 590 nt = (uint32 *)&vram[table + (((y_scroll >> 3) << playfield_shift) & y_mask)]; 591 592 if(shift) 593 { 594 dst = (uint32 *)&buf[0x20-(0x10-shift)]; 595 atbuf = nt[(index-1) & nametable_row_mask]; 596 DRAW_COLUMN_IM2(atbuf, v_line) 597 } 598 buf = (buf + 0x20 + shift); 599 dst = (uint32 *)&buf[start<<4]; 600 601 for(column = start; column < end; column += 1, index += 1) 602 { 603 atbuf = nt[index & nametable_row_mask]; 604 DRAW_COLUMN_IM2(atbuf, v_line) 605 } 606 } 607 608 609 void render_ntx_vs(int which, int line, uint8 *buf) 610 { 611 int column; 612 int start, end; 613 int index; 614 int shift; 615 int nametable_row_mask = (playfield_col_mask >> 1); 616 int v_line; 617 uint32 atex, atbuf, *src, *dst; 618 uint16 xascroll, xbscroll, xscroll; 619 int y_scroll; 620 uint32 *nt; 621 int vsr_shift; 622 uint32 *vs; 623 uint16 table; 624 625 table = (which) ? ntbb : ntab; 626 627 get_hscroll(line, &xascroll, &xbscroll); 628 xscroll = (which) ? xbscroll : xascroll; 629 shift = (xscroll & 0x0F); 630 index = ((playfield_col_mask + 1) >> 1) - ((xscroll >> 4) & nametable_row_mask); 631 632 if(which) 633 { 634 start = 0; 635 end = (reg[0x0C] & 1) ? 20 : 16; 636 } 637 else 638 { 639 if(clip[0].enable == 0) return; 640 start = clip[0].left; 641 end = clip[0].right; 642 index = (index + clip[0].left) & nametable_row_mask; 643 } 644 645 vsr_shift = (which) ? 16 : 0; 646 vs = (uint32 *)&vsram[0]; 647 end = (reg[0x0C] & 1) ? 20 : 16; 648 649 if(shift) 650 { 651 dst = (uint32 *)&buf[0x20-(0x10-shift)]; 652 y_scroll = (line & playfield_row_mask); 653 v_line = (y_scroll & 7) << 3; 654 nt = (uint32 *)&vram[table + (((y_scroll >> 3) << playfield_shift) & y_mask)]; 655 atbuf = nt[(index-1) & nametable_row_mask]; 656 DRAW_COLUMN(atbuf, v_line) 657 } 658 659 buf = (buf + 0x20 + shift); 660 dst = (uint32 *)&buf[start << 4]; 661 662 for(column = start; column < end; column += 1, index += 1) 663 { 664 y_scroll = (vs[column] >> vsr_shift) & 0xFFFF; 665 y_scroll = (line + (y_scroll & 0x3FF)) & playfield_row_mask; 666 v_line = (y_scroll & 7) << 3; 667 nt = (uint32 *)&vram[table + (((y_scroll >> 3) << playfield_shift) & y_mask)]; 668 atbuf = nt[index & nametable_row_mask]; 669 DRAW_COLUMN(atbuf, v_line) 670 } 671 } 672 /*--------------------------------------------------------------------------*/ 673 /* Helper functions (cache update, hscroll, window clip) */ 674 /*--------------------------------------------------------------------------*/ 675 676 void update_bg_pattern_cache(void) 677 { 678 int i; 679 uint8 x, y, c; 680 uint16 name; 681 682 if(!bg_list_index) return; 683 684 for(i = 0; i < bg_list_index; i += 1) 685 { 686 name = bg_name_list[i]; 687 bg_name_list[i] = 0; 688 689 for(y = 0; y < 8; y += 1) 690 { 691 if(bg_name_dirty[name] & (1 << y)) 692 { 693 uint8 *dst = &bg_pattern_cache[name << 6]; 694 uint32 bp = *(uint32 *)&vram[(name << 5) | (y << 2)]; 695 696 for(x = 0; x < 8; x += 1) 697 { 698 c = (bp >> ((x ^ 3) << 2)) & 0x0F; 699 dst[0x00000 | (y << 3) | (x)] = (c); 700 dst[0x20000 | (y << 3) | (x ^ 7)] = (c); 701 //dst[0x40000 | ((y ^ 7) << 3) | (x)] = (c); 702 //dst[0x60000 | ((y ^ 7) << 3) | (x ^ 7)] = (c); 703 } 704 } 705 } 706 bg_name_dirty[name] = 0; 707 } 708 bg_list_index = 0; 709 } 710 711 void get_hscroll(int line, uint16 *scrolla, uint16 *scrollb) 712 { 713 switch(reg[11] & 3) 714 { 715 case 0: /* Full-screen */ 716 *scrolla = *(uint16 *)&vram[hscb + 0]; 717 *scrollb = *(uint16 *)&vram[hscb + 2]; 718 break; 719 720 case 1: /* First 8 lines */ 721 *scrolla = *(uint16 *)&vram[hscb + ((line & 7) << 2) + 0]; 722 *scrollb = *(uint16 *)&vram[hscb + ((line & 7) << 2) + 2]; 723 break; 724 725 case 2: /* Every 8 lines */ 726 *scrolla = *(uint16 *)&vram[hscb + ((line & ~7) << 2) + 0]; 727 *scrollb = *(uint16 *)&vram[hscb + ((line & ~7) << 2) + 2]; 728 break; 729 730 case 3: /* Every line */ 731 *scrolla = *(uint16 *)&vram[hscb + (line << 2) + 0]; 732 *scrollb = *(uint16 *)&vram[hscb + (line << 2) + 2]; 733 break; 734 } 735 736 *scrolla &= 0x03FF; 737 *scrollb &= 0x03FF; 738 } 739 740 void window_clip(int line) 741 { 742 /* Window size and invert flags */ 743 int hp = (reg[17] & 0x1F); 744 int hf = (reg[17] >> 7) & 1; 745 int vp = (reg[18] & 0x1F) << 3; 746 int vf = (reg[18] >> 7) & 1; 747 748 /* Display size */ 749 int sw = (reg[12] & 1) ? 20 : 16; 750 751 /* Clear clipping data */ 752 memset(&clip, 0, sizeof(clip)); 753 754 /* Check if line falls within window range */ 755 if(vf == (line >= vp)) 756 { 757 /* Window takes up entire line */ 758 clip[1].right = sw; 759 clip[1].enable = 1; 760 } 761 else 762 { 763 /* Perform horizontal clipping; the results are applied in reverse 764 if the horizontal inversion flag is set */ 765 int a = hf; 766 int w = hf ^ 1; 767 768 if(hp) 769 { 770 if(hp > sw) 771 { 772 /* Plane W takes up entire line */ 773 clip[w].right = sw; 774 clip[w].enable = 1; 775 } 776 else 777 { 778 /* Window takes left side, Plane A takes right side */ 779 clip[w].right = hp; 780 clip[a].left = hp; 781 clip[a].right = sw; 782 clip[0].enable = clip[1].enable = 1; 783 } 784 } 785 else 786 { 787 /* Plane A takes up entire line */ 788 clip[a].right = sw; 789 clip[a].enable = 1; 790 } 791 } 792 } 793 794 795 796 797 798 799 800 /*--------------------------------------------------------------------------*/ 801 /* Remap functions */ 802 /*--------------------------------------------------------------------------*/ 803 void remap_16(uint8 *src, uint16 *dst, uint16 *table, int length) 804 { 805 int count; 806 for(count = 0; count < length; count += 1) 807 { 808 *dst++ = table[*src++]; 809 } 810 } 811 812 813 /*--------------------------------------------------------------------------*/ 814 /* Merge functions */ 815 /*--------------------------------------------------------------------------*/ 816 817 void merge(uint8 *srca, uint8 *srcb, uint8 *dst, uint8 *table, int width) 818 { 819 int i; 820 for(i = 0; i < width; i += 1) 821 { 822 uint8 a = srca[i]; 823 uint8 b = srcb[i]; 824 uint8 c = table[(b << 8) | (a)]; 825 dst[i] = c; 826 } 827 } 828 829 830 void color_update_16(int index, uint16 data) 831 { 832 if(reg[12] & 8) 833 { 834 pixel_16[0x00 | index] = pixel_16_lut[0][data]; 835 pixel_16[0x40 | index] = pixel_16_lut[1][data]; 836 pixel_16[0x80 | index] = pixel_16_lut[2][data]; 837 } 838 else 839 { 840 uint16 temp = pixel_16_lut[1][data]; 841 pixel_16[0x00 | index] = temp; 842 pixel_16[0x40 | index] = temp; 843 pixel_16[0x80 | index] = temp; 844 } 845 } 846 847 848 /*--------------------------------------------------------------------------*/ 849 /* Object render functions */ 850 /*--------------------------------------------------------------------------*/ 851 852 void parse_satb(int line) 853 { 854 static uint8 sizetab[] = {8, 16, 24, 32}; 855 uint8 *p, *q, link = 0; 856 uint16 ypos; 857 858 int count; 859 int height; 860 861 int limit = (reg[12] & 1) ? 20 : 16; 862 int total = (reg[12] & 1) ? 80 : 64; 863 864 object_index_count = 0; 865 866 for(count = 0; count < total; count += 1) 867 { 868 q = &sat[link << 3]; 869 p = &vram[satb + (link << 3)]; 870 871 ypos = *(uint16 *)&q[0]; 872 873 if(im2_flag) 874 ypos = (ypos >> 1) & 0x1FF; 875 else 876 ypos &= 0x1FF; 877 878 height = sizetab[q[3] & 3]; 879 880 if((line >= ypos) && (line < (ypos + height))) 881 { 882 object_info[object_index_count].ypos = *(uint16 *)&q[0]; 883 object_info[object_index_count].xpos = *(uint16 *)&p[6]; 884 885 // using xpos from internal satb stops sprite x 886 // scrolling in bloodlin.bin, 887 // but this seems to go against the test prog 888 // object_info[object_index_count].xpos = *(uint16 *)&q[6]; 889 object_info[object_index_count].attr = *(uint16 *)&p[4]; 890 object_info[object_index_count].size = q[3]; 891 object_info[object_index_count].index = count; 892 893 object_index_count += 1; 894 895 if(object_index_count == limit) 896 { 897 if(vint_pending == 0) 898 status |= 0x40; 899 return; 900 } 901 } 902 903 link = q[2] & 0x7F; 904 if(link == 0) break; 905 } 906 } 907 908 void render_obj(int line, uint8 *buf, uint8 *table) 909 { 910 uint16 ypos; 911 uint16 attr; 912 uint16 xpos; 913 uint8 sizetab[] = {8, 16, 24, 32}; 914 uint8 size; 915 uint8 *src; 916 917 int count; 918 int pixellimit = (reg[12] & 1) ? 320 : 256; 919 int pixelcount = 0; 920 int width; 921 int height; 922 int v_line; 923 int column; 924 int sol_flag = 0; 925 int left = 0x80; 926 int right = 0x80 + ((reg[12] & 1) ? 320 : 256); 927 928 uint8 *s, *lb; 929 uint16 name, index; 930 uint8 palette; 931 932 int attr_mask, nt_row; 933 934 if(object_index_count == 0) return; 935 936 for(count = 0; count < object_index_count; count += 1) 937 { 938 size = object_info[count].size & 0x0f; 939 xpos = object_info[count].xpos; 940 xpos &= 0x1ff; 941 942 width = sizetab[(size >> 2) & 3]; 943 944 if(xpos != 0) sol_flag = 1; 945 else 946 if(xpos == 0 && sol_flag) return; 947 948 if(pixelcount > pixellimit) return; 949 pixelcount += width; 950 951 if(((xpos + width) >= left) && (xpos < right)) 952 { 953 ypos = object_info[count].ypos; 954 ypos &= 0x1ff; 955 956 attr = object_info[count].attr; 957 // attr_mask = (attr & 0x1800); 958 attr_mask = (attr & 0x800); 959 960 height = sizetab[size & 3]; 961 palette = (attr >> 9) & 0x70; 962 963 v_line = (line - ypos); 964 nt_row = (v_line >> 3) & 3; 965 966 if (attr & 0x1000) { 967 v_line = ((v_line & 7)^0x07) << 3; 968 } 969 else { 970 v_line = ((v_line & 7)) << 3; 971 } 972 973 name = (attr & 0x07FF); 974 s = &name_lut[((attr >> 3) & 0x300) | (size << 4) | (nt_row << 2)]; 975 976 lb = (uint8 *)&buf[0x20 + (xpos - 0x80)]; 977 978 width >>= 3; 979 for(column = 0; column < width; column += 1, lb+=8) 980 { 981 index = attr_mask | ((name + s[column]) & 0x07FF); 982 src = &bg_pattern_cache[(index << 6) | (v_line)]; 983 DRAW_SPRITE_TILE; 984 } 985 } 986 } 987 } 988 989 void render_obj_im2(int line, uint8 *buf, uint8 *table) 990 { 991 uint16 ypos; 992 uint16 attr; 993 uint16 xpos; 994 uint8 sizetab[] = {8, 16, 24, 32}; 995 uint8 size; 996 uint8 *src; 997 998 int count; 999 int pixellimit = (reg[12] & 1) ? 320 : 256; 1000 int pixelcount = 0; 1001 int width; 1002 int height; 1003 int v_line; 1004 int column; 1005 int sol_flag = 0; 1006 int left = 0x80; 1007 int right = 0x80 + ((reg[12] & 1) ? 320 : 256); 1008 1009 uint8 *s, *lb; 1010 uint16 name, index; 1011 uint8 palette; 1012 uint32 offs; 1013 1014 int attr_mask, nt_row; 1015 1016 if(object_index_count == 0) return; 1017 1018 for(count = 0; count < object_index_count; count += 1) 1019 { 1020 size = object_info[count].size & 0x0f; 1021 xpos = object_info[count].xpos; 1022 xpos &= 0x1ff; 1023 1024 width = sizetab[(size >> 2) & 3]; 1025 1026 if(xpos != 0) sol_flag = 1; 1027 else 1028 if(xpos == 0 && sol_flag) return; 1029 1030 if(pixelcount > pixellimit) return; 1031 pixelcount += width; 1032 1033 if(((xpos + width) >= left) && (xpos < right)) 1034 { 1035 ypos = object_info[count].ypos; 1036 ypos = (ypos >> 1) & 0x1ff; 1037 1038 attr = object_info[count].attr; 1039 // attr_mask = (attr & 0x1800); 1040 attr_mask = (attr & 0x800); 1041 1042 height = sizetab[size & 3]; 1043 palette = (attr >> 9) & 0x70; 1044 1045 v_line = (line - ypos); 1046 nt_row = (v_line >> 3) & 3; 1047 v_line = ((((v_line & 7)/*^0x07*/) << 1) | ((status >> 4) & 1)) << 3; 1048 1049 name = (attr & 0x03FF); 1050 s = &name_lut[((attr >> 3) & 0x300) | (size << 4) | (nt_row << 2)]; 1051 1052 lb = (uint8 *)&buf[0x20 + (xpos - 0x80)]; 1053 1054 width >>= 3; 1055 for(column = 0; column < width; column += 1, lb+=8) 1056 { 1057 index = (name + s[column]) & 0x3ff; 1058 offs = index << 7 | attr_mask << 6 | v_line; 1059 if(attr & 0x1000) offs ^= 0x40; 1060 src = &bg_pattern_cache[offs]; 1061 DRAW_SPRITE_TILE; 1062 } 1063 } 1064 } 1065 }