src/mess/video/fmtowns.c
| r7293 | r7294 | |
| 115 | 115 | static rectangle towns_crtc_layerscr[2]; // each layer has independent sizes |
| 116 | 116 | static UINT8 towns_display_plane; |
| 117 | 117 | static UINT8 towns_display_page_sel; |
| 118 | static UINT8 towns_vblank_flag; |
| 118 | 119 | |
| 119 | 120 | extern UINT32* towns_vram; |
| 120 | 121 | extern UINT8* towns_gfxvram; |
| 121 | 122 | extern UINT8* towns_txtvram; |
| 122 | | extern UINT8* towns_sprram; |
| 123 | //extern UINT8* towns_sprram; |
| 123 | 124 | |
| 124 | 125 | extern UINT32 towns_mainmem_enable; |
| 125 | 126 | extern UINT32 towns_ankcg_enable; |
| r7293 | r7294 | |
| 464 | 465 | { |
| 465 | 466 | case 0x02: // 0x5ca - VSync clear? |
| 466 | 467 | pic8259_set_irq_line(dev,3,0); |
| 468 | //towns_vblank_flag = 0; |
| 467 | 469 | break; |
| 468 | 470 | } |
| 469 | 471 | logerror("VID: wrote 0x%02x to port %04x\n",data,offset+0x5c8); |
| r7293 | r7294 | |
| 477 | 479 | */ |
| 478 | 480 | READ8_HANDLER(towns_video_fd90_r) |
| 479 | 481 | { |
| 482 | UINT8 ret = 0; |
| 480 | 483 | switch(offset) |
| 481 | 484 | { |
| 482 | 485 | case 0x00: |
| r7293 | r7294 | |
| 496 | 499 | case 0x0e: |
| 497 | 500 | case 0x0f: |
| 498 | 501 | return towns_degipal[offset-0x08]; |
| 502 | case 0x10: // "sub status register" - bit 0 = vblank, bit 1 = hblank |
| 503 | if(towns_vblank_flag) |
| 504 | ret |= 0x01; |
| 505 | return ret; |
| 499 | 506 | } |
| 500 | 507 | // logerror("VID: read port %04x\n",offset+0xfd90); |
| 501 | 508 | return 0x00; |
| r7293 | r7294 | |
| 564 | 571 | { // 0xc8000-0xc8fff |
| 565 | 572 | if(towns_mainmem_enable == 0) |
| 566 | 573 | { |
| 567 | | if(towns_tvram_enable == 0) |
| 568 | | return towns_sprram[offset]; |
| 569 | | else |
| 574 | // if(towns_tvram_enable == 0) |
| 575 | // return towns_sprram[offset]; |
| 576 | // else |
| 570 | 577 | return towns_txtvram[offset]; |
| 571 | 578 | } |
| 572 | 579 | else |
| r7293 | r7294 | |
| 582 | 589 | { |
| 583 | 590 | if(towns_ankcg_enable != 0 && offset < 0x2800) |
| 584 | 591 | return ROM[0x180000 + 0x3d000 + (offset-0x2000)]; |
| 585 | | if(towns_tvram_enable == 0) |
| 586 | | return towns_sprram[offset]; |
| 587 | | else |
| 592 | // if(towns_tvram_enable == 0) |
| 593 | // return towns_sprram[offset]; |
| 594 | // else |
| 588 | 595 | return towns_txtvram[offset]; |
| 589 | 596 | } |
| 590 | 597 | else |
| r7293 | r7294 | |
| 620 | 627 | |
| 621 | 628 | READ8_HANDLER( towns_spriteram_r) |
| 622 | 629 | { |
| 623 | | return towns_sprram[offset]; |
| 630 | return towns_txtvram[offset]; |
| 624 | 631 | } |
| 625 | 632 | |
| 626 | 633 | WRITE8_HANDLER( towns_spriteram_w) |
| 627 | 634 | { |
| 628 | | towns_sprram[offset] = data; |
| 635 | towns_txtvram[offset] = data; |
| 629 | 636 | } |
| 630 | 637 | |
| 631 | 638 | /* |
| r7293 | r7294 | |
| 684 | 691 | for(xpos=xstart;xpos!=xend;xpos+=xdir) |
| 685 | 692 | { |
| 686 | 693 | voffset = 0; |
| 687 | | pixel = (towns_sprram[poffset] & 0xf0) >> 4; |
| 688 | | col = towns_sprram[coffset+(pixel*2)] | (towns_sprram[coffset+(pixel*2)+1] << 8); |
| 694 | pixel = (towns_txtvram[poffset] & 0xf0) >> 4; |
| 695 | col = towns_txtvram[coffset+(pixel*2)] | (towns_txtvram[coffset+(pixel*2)+1] << 8); |
| 689 | 696 | voffset += (towns_crtc_reg[24] * 4) * ypos; // scanline size in bytes * y pos |
| 690 | 697 | voffset += (xpos & 0x1ff) * 2; |
| 691 | 698 | voffset &= 0x3ffff; |
| r7293 | r7294 | |
| 699 | 706 | voffset+=2; |
| 700 | 707 | else |
| 701 | 708 | voffset-=2; |
| 702 | | pixel = towns_sprram[poffset] & 0x0f; |
| 703 | | col = towns_sprram[coffset+(pixel*2)] | (towns_sprram[coffset+(pixel*2)+1] << 8); |
| 709 | pixel = towns_txtvram[poffset] & 0x0f; |
| 710 | col = towns_txtvram[coffset+(pixel*2)] | (towns_txtvram[coffset+(pixel*2)+1] << 8); |
| 704 | 711 | voffset &= 0x3ffff; |
| 705 | 712 | voffset += (towns_sprite_reg[6] & 0x10) ? 0x60000 : 0x40000; |
| 706 | 713 | if(xpos <= rect->max_x && ypos <= rect->max_y && pixel != 0) |
| r7293 | r7294 | |
| 750 | 757 | for(xpos=xstart;xpos!=xend;xpos+=xdir) |
| 751 | 758 | { |
| 752 | 759 | voffset = (towns_sprite_reg[6] & 0x10) ? 0x60000 : 0x40000; |
| 753 | | col = towns_sprram[poffset] | (towns_sprram[poffset+1] << 8); |
| 760 | col = towns_txtvram[poffset] | (towns_txtvram[poffset+1] << 8); |
| 754 | 761 | voffset += (towns_crtc_reg[24] * 4) * ypos; // scanline size in bytes * y pos |
| 755 | 762 | voffset += (xpos & 0x1ff) * 2; |
| 756 | 763 | voffset &= 0x7ffff; |
| r7293 | r7294 | |
| 781 | 788 | |
| 782 | 789 | for(n=sprite_limit;n<1024;n++) |
| 783 | 790 | { |
| 784 | | x = towns_sprram[8*n] | (towns_sprram[8*n+1] << 8); |
| 785 | | y = towns_sprram[8*n+2] | (towns_sprram[8*n+3] << 8); |
| 786 | | attr = towns_sprram[8*n+4] | (towns_sprram[8*n+5] << 8); |
| 787 | | colour = towns_sprram[8*n+6] | (towns_sprram[8*n+7] << 8); |
| 791 | x = towns_txtvram[8*n] | (towns_txtvram[8*n+1] << 8); |
| 792 | y = towns_txtvram[8*n+2] | (towns_txtvram[8*n+3] << 8); |
| 793 | attr = towns_txtvram[8*n+4] | (towns_txtvram[8*n+5] << 8); |
| 794 | colour = towns_txtvram[8*n+6] | (towns_txtvram[8*n+7] << 8); |
| 788 | 795 | if(attr & 0x8000) |
| 789 | 796 | { |
| 790 | 797 | x += xoff; |
| r7293 | r7294 | |
| 1149 | 1156 | } |
| 1150 | 1157 | } |
| 1151 | 1158 | |
| 1152 | | void draw_text_layer(running_machine* machine,bitmap_t* bitmap, const rectangle* rect) |
| 1159 | void render_text_char(running_machine* machine, UINT8 x, UINT8 y, UINT8 ascii, UINT16 jis, UINT8 attr) |
| 1153 | 1160 | { |
| 1161 | UINT32 rom_addr; |
| 1162 | UINT32 vram_addr; |
| 1163 | UINT16 linesize = towns_crtc_reg[24] * 4; |
| 1164 | UINT8 code_h,code_l; |
| 1165 | UINT8 colour; |
| 1166 | UINT8 data; |
| 1167 | UINT8 temp; |
| 1168 | UINT8* font_rom = memory_region(machine,"user"); |
| 1169 | int a,b; |
| 1170 | |
| 1171 | // all characters are 16 pixels high |
| 1172 | vram_addr = (x * 16) * linesize; |
| 1173 | |
| 1174 | if((attr & 0xc0) == 0) |
| 1175 | rom_addr = 0x3d800 + (ascii * 128); |
| 1176 | else |
| 1177 | { |
| 1178 | code_h = (jis & 0xff00) >> 8; |
| 1179 | code_l = jis & 0x00ff; |
| 1180 | if(code_h < 0x30) |
| 1181 | { |
| 1182 | rom_addr = ((code_l & 0x1f) << 4) |
| 1183 | | (((code_l - 0x20) & 0x20) << 8) |
| 1184 | | (((code_l - 0x20) & 0x40) << 6) |
| 1185 | | ((code_h & 0x07) << 9); |
| 1186 | } |
| 1187 | else if(towns_kanji_code_h < 0x70) |
| 1188 | { |
| 1189 | rom_addr = ((code_l & 0x1f) << 4) |
| 1190 | + (((code_l - 0x20) & 0x60) << 8) |
| 1191 | + ((code_h & 0x0f) << 9) |
| 1192 | + (((code_h - 0x30) & 0x70) * 0xc00) |
| 1193 | + 0x8000; |
| 1194 | } |
| 1195 | else |
| 1196 | { |
| 1197 | rom_addr = ((code_l & 0x1f) << 4) |
| 1198 | | (((code_l - 0x20) & 0x20) << 8) |
| 1199 | | (((code_l - 0x20) & 0x40) << 6) |
| 1200 | | ((code_h & 0x07) << 9) |
| 1201 | | 0x38000; |
| 1202 | } |
| 1203 | } |
| 1204 | colour = attr & 0x07; |
| 1205 | if(attr & 0x20) |
| 1206 | colour |= 0x08; |
| 1207 | |
| 1208 | for(a=0;a<16;a++) // for each scanline |
| 1209 | { |
| 1210 | if((attr & 0xc0) == 0) |
| 1211 | data = font_rom[0x180000 + rom_addr + a]; |
| 1212 | else |
| 1213 | { |
| 1214 | if((attr & 0xc0) == 0x80) |
| 1215 | data = font_rom[0x180000 + rom_addr + (a*2)]; |
| 1216 | else |
| 1217 | data = font_rom[0x180000 + rom_addr + (a*2) + 1]; |
| 1218 | } |
| 1219 | |
| 1220 | if(attr & 0x08) |
| 1221 | data = ~data; // inverse |
| 1222 | |
| 1223 | // and finally, put the data in VRAM |
| 1224 | for(b=0;b<8;b+=2) |
| 1225 | { |
| 1226 | temp = 0; |
| 1227 | if(data & (1<<b)) |
| 1228 | temp |= ((colour & 0x0f) << 4); |
| 1229 | if(data & (1<<(b+1))) |
| 1230 | temp |= (colour & 0x0f); |
| 1231 | } |
| 1232 | |
| 1233 | vram_addr += linesize; |
| 1234 | } |
| 1235 | } |
| 1236 | |
| 1237 | void draw_text_layer(running_machine* machine) |
| 1238 | { |
| 1154 | 1239 | /* |
| 1155 | | * Text layer format |
| 1240 | * Text format |
| 1156 | 1241 | * 2 bytes per character at both 0xc8000 and 0xca000 |
| 1157 | 1242 | * 0xc8xxx: Byte 1: ASCII character |
| 1158 | 1243 | * Byte 2: Attributes |
| r7293 | r7294 | |
| 1165 | 1250 | * If either bits 6 or 7 are high, then a fullwidth Kanji character is displayed |
| 1166 | 1251 | * at this location. The character displayed is represented by a 2-byte |
| 1167 | 1252 | * JIS code at the same offset at 0xca000. |
| 1253 | * |
| 1254 | * The video hardware renders text to VRAM layer 1, there is no separate text layer |
| 1168 | 1255 | */ |
| 1169 | | int x,y; |
| 1170 | | UINT8 colour; |
| 1171 | | UINT32 colourcode; |
| 1172 | | UINT8 row; // JIS row number |
| 1173 | | UINT16 code; |
| 1174 | | int off = 0; |
| 1256 | int x,y,c = 0; |
| 1175 | 1257 | |
| 1176 | 1258 | for(y=0;y<40;y++) |
| 1177 | 1259 | { |
| 1178 | | off = 160 * y; |
| 1179 | 1260 | for(x=0;x<80;x++) |
| 1180 | 1261 | { |
| 1181 | | colour = towns_txtvram[off+1] & 0x07; |
| 1182 | | if(towns_txtvram[off+1] & 0x20) |
| 1183 | | { // Bright |
| 1184 | | colourcode = (((colour & 0x02) ? 0xfe : 0x00) << 16) |
| 1185 | | | (((colour & 0x04) ? 0xfe : 0x00) << 8) |
| 1186 | | | ((colour & 0x01) ? 0xfe : 0x00); |
| 1187 | | } |
| 1188 | | else |
| 1189 | | { |
| 1190 | | colourcode = (((colour & 0x02) ? 0x7f : 0x00) << 16) |
| 1191 | | | (((colour & 0x04) ? 0x7f : 0x00) << 8) |
| 1192 | | | ((colour & 0x01) ? 0x7f : 0x00); |
| 1193 | | } |
| 1194 | | |
| 1195 | | if((towns_txtvram[off+1] & 0xc0) != 0) |
| 1196 | | { // double width |
| 1197 | | if(towns_txtvram[off+1] & 0x40) |
| 1198 | | { |
| 1199 | | row = (towns_txtvram[off+0x2000] - 32); |
| 1200 | | code = 0; |
| 1201 | | if(row <= 8) |
| 1202 | | { |
| 1203 | | code = (row & 0x07) * 0x20; |
| 1204 | | code += ((towns_txtvram[off+0x2001]-32) & 0x1f) |
| 1205 | | | (((towns_txtvram[off+0x2001]-32) & 0x40) << 2) |
| 1206 | | | (((towns_txtvram[off+0x2001]-32) & 0x20) << 4); |
| 1207 | | } |
| 1208 | | if(row >= 16) // Kanji |
| 1209 | | { |
| 1210 | | code = 0x400; |
| 1211 | | code += ((towns_txtvram[off+0x2001]) & 0x1f) |
| 1212 | | + (((towns_txtvram[off+0x2001]-32) & 0x60) << 4) |
| 1213 | | + ((row & 0x0f) << 5) |
| 1214 | | + (((row-16) & 0x70) * 0x60); |
| 1215 | | } |
| 1216 | | drawgfx_transpen_raw(bitmap,rect,machine->gfx[1],code, |
| 1217 | | colourcode, 0,0,towns_crtc_layerscr[0].min_x+(x*8),towns_crtc_layerscr[0].min_y+(y*16),0); |
| 1218 | | } |
| 1219 | | } |
| 1220 | | else |
| 1221 | | { |
| 1222 | | drawgfx_transpen_raw(bitmap,rect,machine->gfx[0],towns_txtvram[off], |
| 1223 | | colourcode, 0,0,towns_crtc_layerscr[0].min_x+(x*8),towns_crtc_layerscr[0].min_y+(y*16),0); |
| 1224 | | } |
| 1225 | | off += 2; |
| 1262 | render_text_char(machine,x,y,towns_txtvram[c],((towns_txtvram[c+0x2000] << 8)|(towns_txtvram[c+0x2001])),towns_txtvram[c+1]); |
| 1263 | c+=2; |
| 1226 | 1264 | } |
| 1227 | 1265 | } |
| 1228 | 1266 | } |
| r7293 | r7294 | |
| 1232 | 1270 | // here we'll clear the vsync signal, I presume it goes low on it's own eventually |
| 1233 | 1271 | running_device* dev = (running_device*)ptr; |
| 1234 | 1272 | pic8259_set_irq_line(dev,3,0); // IRQ11 = VSync |
| 1273 | towns_vblank_flag = 0; |
| 1235 | 1274 | } |
| 1236 | 1275 | |
| 1237 | 1276 | INTERRUPT_GEN( towns_vsync_irq ) |
| 1238 | 1277 | { |
| 1239 | 1278 | running_device* dev = devtag_get_device(device->machine,"pic8259_slave"); |
| 1240 | 1279 | pic8259_set_irq_line(dev,3,1); // IRQ11 = VSync |
| 1280 | towns_vblank_flag = 1; |
| 1241 | 1281 | timer_set(device->machine,video_screen_get_time_until_vblank_end(device->machine->primary_screen),(void*)dev,0,towns_vblank_end); |
| 1282 | if(towns_tvram_enable) |
| 1283 | draw_text_layer(dev->machine); |
| 1242 | 1284 | if(towns_sprite_reg[1] & 0x80) // if sprites are enabled, then sprites are drawn on this layer. |
| 1243 | 1285 | draw_sprites(dev->machine,&towns_crtc_layerscr[1]); |
| 1244 | 1286 | } |
| r7293 | r7294 | |
| 1267 | 1309 | towns_crtc_draw_layer(screen->machine,bitmap,&towns_crtc_layerscr[1],1); |
| 1268 | 1310 | } |
| 1269 | 1311 | |
| 1270 | | if(!(towns_sprite_reg[1] & 0x80)) // if sprites are not enabled |
| 1271 | | draw_text_layer(screen->machine,bitmap,cliprect); |
| 1272 | | |
| 1273 | 1312 | #ifdef SPR_DEBUG |
| 1274 | 1313 | if(input_code_pressed(screen->machine,KEYCODE_O)) |
| 1275 | 1314 | pshift+=0x80; |
| r7293 | r7294 | |
| 1279 | 1318 | #endif |
| 1280 | 1319 | |
| 1281 | 1320 | #ifdef CRTC_REG_DISP |
| 1282 | | popmessage("CRTC: %i %i %i %i %i %i %i %i %i\n%i %i %i %i | %i %i %i %i\n%i %i %i %i | %i %i %i %i\nZOOM: %04x\nVideo: %02x %02x\nText=%i", |
| 1321 | popmessage("CRTC: %i %i %i %i %i %i %i %i %i\n%i %i %i %i | %i %i %i %i\n%i %i %i %i | %i %i %i %i\nZOOM: %04x\nVideo: %02x %02x\nText=%i Spr=%02x", |
| 1283 | 1322 | towns_crtc_reg[0],towns_crtc_reg[1],towns_crtc_reg[2],towns_crtc_reg[3], |
| 1284 | 1323 | towns_crtc_reg[4],towns_crtc_reg[5],towns_crtc_reg[6],towns_crtc_reg[7], |
| 1285 | 1324 | towns_crtc_reg[8], |
| r7293 | r7294 | |
| 1287 | 1326 | towns_crtc_reg[13],towns_crtc_reg[14],towns_crtc_reg[15],towns_crtc_reg[16], |
| 1288 | 1327 | towns_crtc_reg[17],towns_crtc_reg[18],towns_crtc_reg[19],towns_crtc_reg[20], |
| 1289 | 1328 | towns_crtc_reg[21],towns_crtc_reg[22],towns_crtc_reg[23],towns_crtc_reg[24], |
| 1290 | | towns_crtc_reg[27],towns_video_reg[0],towns_video_reg[1],towns_tvram_enable); |
| 1329 | towns_crtc_reg[27],towns_video_reg[0],towns_video_reg[1],towns_tvram_enable,towns_sprite_reg[1] & 0x80); |
| 1291 | 1330 | #endif |
| 1292 | 1331 | |
| 1293 | 1332 | return 0; |