2 Skelton for retropc emulator
4 Origin : MAME TMS9928A Core
5 Author : Takeda.Toshiya
14 //#define ADDR_MASK (TMS9918A_VRAM_SIZE - 1)
16 static const scrntype_t palette_pc_noalpha[16] = {
18 RGB_COLOR( 0, 0, 0), RGB_COLOR( 33, 200, 66), RGB_COLOR( 94, 220, 120),
19 RGB_COLOR( 84, 85, 237), RGB_COLOR(125, 118, 252), RGB_COLOR(212, 82, 77), RGB_COLOR( 66, 235, 245),
20 RGB_COLOR(252, 85, 84), RGB_COLOR(255, 121, 120), RGB_COLOR(212, 193, 84), RGB_COLOR(230, 206, 128),
21 RGB_COLOR( 33, 176, 59), RGB_COLOR(201, 91, 186), RGB_COLOR(204, 204, 204), RGB_COLOR(255, 255, 255)
24 static const scrntype_t palette_pc_alpha[16] = {
25 RGBA_COLOR( 0, 0, 0, 0), RGBA_COLOR( 0, 0, 0, 255), RGBA_COLOR( 33, 200, 66, 255), RGBA_COLOR( 94, 220, 120, 255),
26 RGBA_COLOR( 84, 85, 237, 255), RGBA_COLOR(125, 118, 252, 255), RGBA_COLOR(212, 82, 77, 255), RGBA_COLOR( 66, 235, 245, 255),
27 RGBA_COLOR(252, 85, 84, 255), RGBA_COLOR(255, 121, 120, 255), RGBA_COLOR(212, 193, 84, 255), RGBA_COLOR(230, 206, 128, 255),
28 RGBA_COLOR( 33, 176, 59, 255), RGBA_COLOR(201, 91, 186, 255), RGBA_COLOR(204, 204, 204, 255), RGBA_COLOR(255, 255, 255, 255)
31 void TMS9918A::initialize()
35 _use_alpha_blending_to_impose = osd->check_feature(_T("USE_ALPHA_BLENDING_TO_IMPOSE"));
36 _tms9918a_super_impose = osd->check_feature(_T("TMS9918A_SUPER_IMPOSE"));
37 _tms9918a_limit_sprites = osd->check_feature(_T("TMS9918A_LIMIT_SPRITES"));
38 _VRAM_SIZE = osd->get_feature_uint32_value(_T("TMS9918A_VRAM_SIZE"));
39 _SCREEN_WIDTH = osd->get_feature_int_value(_T("SCREEN_WIDTH"));
41 if(_VRAM_SIZE == 0) _VRAM_SIZE = 0x4000;
42 _ADDR_MASK = _VRAM_SIZE - 1;
43 vram = (uint8_t *)malloc(_VRAM_SIZE * sizeof(uint8_t));
45 if(_use_alpha_blending_to_impose) {
46 palette_pc = palette_pc_alpha;
48 palette_pc = palette_pc_noalpha;
51 register_vline_event(this);
54 void TMS9918A::release()
56 if(vram != NULL) free(vram);
58 void TMS9918A::reset()
60 memset(vram, 0, _VRAM_SIZE * sizeof(uint8_t));
61 memset(regs, 0, sizeof(regs));
62 status_reg = read_ahead = first_byte = 0;
64 intstat = latch = false;
65 color_table = pattern_table = name_table = 0;
66 sprite_pattern = sprite_attrib = 0;
67 color_mask = pattern_mask = 0;
70 void TMS9918A::write_io8(uint32_t addr, uint32_t data)
78 regs[0] = first_byte & 3;
80 color_table = ((regs[3] & 0x80) * 64) & _ADDR_MASK;
81 color_mask = ((regs[3] & 0x7f) * 8) | 7;
82 pattern_table = ((regs[4] & 4) * 2048) & _ADDR_MASK;
83 pattern_mask = ((regs[4] & 3) * 256) | (color_mask & 0xff);
85 color_table = (regs[3] * 64) & _ADDR_MASK;
86 pattern_table = (regs[4] * 2048) & _ADDR_MASK;
90 regs[1] = first_byte & 0xfb;
91 set_intstat((regs[1] & 0x20) && (status_reg & 0x80));
94 regs[2] = first_byte & 0x0f;
95 name_table = (regs[2] * 1024) & _ADDR_MASK;
100 color_table = ((regs[3] & 0x80) * 64) & _ADDR_MASK;
101 color_mask = ((regs[3] & 0x7f) * 8) | 7;
103 color_table = (regs[3] * 64) & _ADDR_MASK;
105 pattern_mask = ((regs[4] & 3) * 256) | (color_mask & 0xff);
108 regs[4] = first_byte & 7;
110 pattern_table = ((regs[4] & 4) * 2048) & _ADDR_MASK;
111 pattern_mask = ((regs[4] & 3) * 256) | 255;
113 pattern_table = (regs[4] * 2048) & _ADDR_MASK;
117 regs[5] = first_byte & 0x7f;
118 sprite_attrib = (regs[5] * 128) & _ADDR_MASK;
121 regs[6] = first_byte & 7;
122 sprite_pattern = (regs[6] * 2048) & _ADDR_MASK;
125 regs[7] = first_byte;
129 vram_addr = ((data * 256) | first_byte) & _ADDR_MASK;
131 read_io8(0); // read ahead
141 vram[vram_addr] = data;
142 vram_addr = (vram_addr + 1) & _ADDR_MASK;
148 uint32_t TMS9918A::read_io8(uint32_t addr)
152 uint8_t val = status_reg;
159 uint8_t val = read_ahead;
160 read_ahead = vram[vram_addr];
161 vram_addr = (vram_addr + 1) & _ADDR_MASK;
167 //#ifdef TMS9918A_SUPER_IMPOSE
168 void TMS9918A::write_signal(int id, uint32_t data, uint32_t mask)
170 if(_tms9918a_super_impose) {
171 if(id == SIG_TMS9918A_SUPER_IMPOSE) {
172 now_super_impose = ((data & mask) != 0);
178 inline void TMS9918A::draw_screen_512_impose()
180 emu->set_vm_screen_lines(192);
181 for(int y = 0, y2 = 0; y < 192; y++, y2 += 2) {
182 scrntype_t* dest0 = osd->get_vm_screen_buffer(y2 + 0);
183 scrntype_t* dest1 = osd->get_vm_screen_buffer(y2 + 1);
184 uint8_t* src = screen[y];
185 //#if defined(TMS9918A_SUPER_IMPOSE) && !defined(USE_ALPHA_BLENDING_TO_IMPOSE)
186 if(now_super_impose) {
187 for(int x = 0, x2 = 0; x < 256; x++, x2 += 2) {
188 uint8_t c = src[x] & 0x0f;
190 dest0[x2] = dest0[x2 + 1] = dest1[x2] = dest1[x2 + 1] = palette_pc[c];
194 for(int x = 0, x2 = 0; x < 256; x++, x2 += 2) {
195 dest0[x2] = dest0[x2 + 1] = palette_pc[src[x] & 0x0f];
197 my_memcpy(dest1, dest0, 512 * sizeof(scrntype_t));
203 inline void TMS9918A::draw_screen_512_nonimpose()
205 emu->set_vm_screen_lines(192);
206 for(int y = 0, y2 = 0; y < 192; y++, y2 += 2) {
207 scrntype_t* dest0 = osd->get_vm_screen_buffer(y2 + 0);
208 scrntype_t* dest1 = osd->get_vm_screen_buffer(y2 + 1);
209 uint8_t* src = screen[y];
210 for(int x = 0, x2 = 0; x < 256; x++, x2 += 2) {
211 dest0[x2] = dest0[x2 + 1] = palette_pc[src[x] & 0x0f];
213 my_memcpy(dest1, dest0, 512 * sizeof(scrntype_t));
217 inline void TMS9918A::draw_screen_256_impose()
219 emu->set_vm_screen_lines(192);
220 for(int y = 0; y < 192; y++) {
221 scrntype_t* dest = osd->get_vm_screen_buffer(y);
222 uint8_t* src = screen[y];
223 //#if defined(TMS9918A_SUPER_IMPOSE) && !defined(USE_ALPHA_BLENDING_TO_IMPOSE)
224 if(now_super_impose) {
225 for(int x = 0; x < 256; x++) {
226 uint8_t c = src[x] & 0x0f;
228 dest[x] = palette_pc[c];
233 for(int x = 0; x < 256; x++) {
234 dest[x] = palette_pc[src[x] & 0x0f];
240 inline void TMS9918A::draw_screen_256_nonimpose()
242 emu->set_vm_screen_lines(192);
243 for(int y = 0; y < 192; y++) {
244 scrntype_t* dest = osd->get_vm_screen_buffer(y);
245 uint8_t* src = screen[y];
246 for(int x = 0; x < 256; x++) {
247 dest[x] = palette_pc[src[x] & 0x0f];
254 void TMS9918A::draw_screen()
256 //#ifdef TMS9918A_SUPER_IMPOSE
257 if(_tms9918a_super_impose) {
258 if(now_super_impose) {
259 osd->get_video_buffer();
263 // update screen buffer
264 //#if SCREEN_WIDTH == 512
265 if(_SCREEN_WIDTH == 512) {
266 if(_tms9918a_super_impose && !_use_alpha_blending_to_impose) {
267 draw_screen_512_impose();
269 draw_screen_512_nonimpose();
272 if(_tms9918a_super_impose && !_use_alpha_blending_to_impose) {
273 draw_screen_256_impose();
275 draw_screen_256_nonimpose();
280 void TMS9918A::event_vline(int v, int clock)
283 // create virtual screen
285 // draw character plane
286 int mode = (regs[0] & 2) | ((regs[1] & 0x10) >> 4) | ((regs[1] & 8) >> 1);
312 if((regs[1] & 0x50) == 0x40) {
316 memset(screen, 0, sizeof(screen));
321 set_intstat((regs[1] & 0x20) != 0);
325 void TMS9918A::set_intstat(bool val)
328 write_signals(&outputs_irq, val ? 0xffffffff : 0);
333 void TMS9918A::draw_mode0()
335 for(int y = 0, name = 0; y < 24; y++) {
336 for(int x = 0; x < 32; x++) {
337 uint16_t code = vram[name_table + (name++)];
338 uint8_t* pattern_ptr = vram + pattern_table + code * 8;
339 uint8_t color = vram[color_table + (code >> 3)];
340 uint8_t fg = (color & 0xf0) ? (color >> 4) : (regs[7] & 0x0f);
341 uint8_t bg = (color & 0x0f) ? (color & 0x0f) : (regs[7] & 0x0f);
342 for(int yy=0; yy < 8; yy++) {
343 uint8_t pattern = *pattern_ptr++;
344 uint8_t* buffer = screen[y * 8 + yy] + x * 8;
345 buffer[0] = (pattern & 0x80) ? fg : bg;
346 buffer[1] = (pattern & 0x40) ? fg : bg;
347 buffer[2] = (pattern & 0x20) ? fg : bg;
348 buffer[3] = (pattern & 0x10) ? fg : bg;
349 buffer[4] = (pattern & 0x08) ? fg : bg;
350 buffer[5] = (pattern & 0x04) ? fg : bg;
351 buffer[6] = (pattern & 0x02) ? fg : bg;
352 buffer[7] = (pattern & 0x01) ? fg : bg;
358 void TMS9918A::draw_mode1()
360 uint8_t fg = regs[7] >> 4;
361 uint8_t bg = regs[7] & 0x0f;
362 memset(screen, bg, sizeof(screen));
363 for(int y = 0, name = 0; y < 24; y++) {
364 for(int x = 0; x < 40; x++) {
365 uint16_t code = vram[name_table + (name++)];
366 uint8_t* pattern_ptr = vram + pattern_table + code * 8;
367 for(int yy = 0; yy < 8; yy++) {
368 uint8_t pattern = *pattern_ptr++;
369 uint8_t* buffer = screen[y * 8 + yy] + x * 6 + 8;
370 buffer[0] = (pattern & 0x80) ? fg : bg;
371 buffer[1] = (pattern & 0x40) ? fg : bg;
372 buffer[2] = (pattern & 0x20) ? fg : bg;
373 buffer[3] = (pattern & 0x10) ? fg : bg;
374 buffer[4] = (pattern & 0x08) ? fg : bg;
375 buffer[5] = (pattern & 0x04) ? fg : bg;
381 void TMS9918A::draw_mode2()
383 for(int y = 0, name = 0; y < 24; y++) {
384 for(int x = 0; x < 32; x++) {
385 uint16_t code = vram[name_table + (name++)] + (y & 0xf8) * 32;
386 uint8_t* pattern_ptr = vram + pattern_table + (code & pattern_mask) * 8;
387 uint8_t* color_ptr = vram + color_table + (code & color_mask) * 8;
388 for(int yy = 0; yy < 8; yy++) {
389 uint8_t pattern = *pattern_ptr++;
390 uint8_t color = *color_ptr++;
391 uint8_t fg = (color & 0xf0) ? (color >> 4) : (regs[7] & 0x0f);
392 uint8_t bg = (color & 0x0f) ? (color & 0x0f) : (regs[7] & 0x0f);
393 uint8_t* buffer = screen[y * 8 + yy] + x * 8;
394 buffer[0] = (pattern & 0x80) ? fg : bg;
395 buffer[1] = (pattern & 0x40) ? fg : bg;
396 buffer[2] = (pattern & 0x20) ? fg : bg;
397 buffer[3] = (pattern & 0x10) ? fg : bg;
398 buffer[4] = (pattern & 0x08) ? fg : bg;
399 buffer[5] = (pattern & 0x04) ? fg : bg;
400 buffer[6] = (pattern & 0x02) ? fg : bg;
401 buffer[7] = (pattern & 0x01) ? fg : bg;
407 void TMS9918A::draw_mode12()
409 uint8_t fg = regs[7] >> 4;
410 uint8_t bg = regs[7] & 0x0f;
411 memset(screen, bg, sizeof(screen));
412 for(int y = 0, name = 0; y < 24; y++) {
413 for(int x = 0; x < 40; x++) {
414 uint16_t code = vram[name_table + (name++)] + (y & 0xf8) * 32;
415 uint8_t* pattern_ptr = vram + pattern_table + (code & pattern_mask) * 8;
416 for(int yy = 0; yy < 8; yy++) {
417 uint8_t pattern = *pattern_ptr++;
418 uint8_t* buffer = screen[y * 8 + yy] + x * 6 + 8;
419 buffer[0] = (pattern & 0x80) ? fg : bg;
420 buffer[1] = (pattern & 0x40) ? fg : bg;
421 buffer[2] = (pattern & 0x20) ? fg : bg;
422 buffer[3] = (pattern & 0x10) ? fg : bg;
423 buffer[4] = (pattern & 0x08) ? fg : bg;
424 buffer[5] = (pattern & 0x04) ? fg : bg;
430 void TMS9918A::draw_mode3()
432 for(int y = 0, name = 0; y < 24; y++) {
433 for(int x = 0; x < 32; x++) {
434 uint16_t code = vram[name_table + (name++)];
435 uint8_t* pattern_ptr = vram + pattern_table + code * 8 + (y & 3) * 2;
436 for(int yy = 0; yy < 2; yy++) {
437 uint8_t color = *pattern_ptr++;
438 uint8_t fg = (color & 0xf0) ? (color >> 4) : (regs[7] & 0x0f);
439 uint8_t bg = (color & 0x0f) ? (color & 0x0f) : (regs[7] & 0x0f);
440 for(int yyy = 0; yyy < 4; yyy++) {
441 uint8_t* buffer = screen[y * 8 + yy * 4 + yyy] + x * 8;
442 buffer[0] = buffer[1] = buffer[2] = buffer[3] = fg;
443 buffer[4] = buffer[5] = buffer[6] = buffer[7] = bg;
450 void TMS9918A::draw_mode23()
452 for(int y = 0, name = 0; y < 24;y++) {
453 for(int x = 0; x < 32; x++) {
454 uint16_t code = vram[name_table + (name++)];
455 uint8_t* pattern_ptr = vram + pattern_table + ((code + (y & 3) * 2 + (y & 0xf8) * 32) & pattern_mask) * 8;
456 for(int yy = 0; yy < 2; yy++) {
457 uint8_t color = *pattern_ptr++;
458 uint8_t fg = (color & 0xf0) ? (color >> 4) : (regs[7] & 0x0f);
459 uint8_t bg = (color & 0x0f) ? (color & 0x0f) : (regs[7] & 0x0f);
460 for(int yyy = 0; yyy < 4; yyy++) {
461 uint8_t* buffer = screen[y * 8 + yy * 4 + yyy] + x * 8;
462 buffer[0] = buffer[1] = buffer[2] = buffer[3] = fg;
463 buffer[4] = buffer[5] = buffer[6] = buffer[7] = bg;
470 void TMS9918A::draw_modebogus()
472 uint8_t fg = regs[7] >> 4;
473 uint8_t bg = regs[7] & 0x0f;
474 for(int y = 0; y < 192; y++) {
475 uint8_t* buffer = screen[y];
477 for(int i = 0; i < 8; i++) {
480 for(int i = 0; i < 40; i++) {
481 for(int j = 0; j < 4; j++) {
484 for(int j = 0; j < 2; j++) {
488 for(int i = 0; i < 8; i++) {
494 void TMS9918A::draw_sprites()
496 uint8_t* attrib_ptr = vram + sprite_attrib;
497 int size = (regs[1] & 2) ? 16 : 8;
498 bool large = ((regs[1] & 1) != 0);
499 uint8_t limit[192], collision[192][256];
500 int illegal_sprite = 0, illegal_sprite_line = 255, p;
501 memset(limit, 4, sizeof(limit));
502 memset(collision, 0, sizeof(collision));
505 for(p = 0; p < 32; p++) {
506 int y = *attrib_ptr++;
515 int x = *attrib_ptr++;
516 uint8_t* pattern_ptr = vram + sprite_pattern + ((size == 16) ? (*attrib_ptr & 0xfc) : *attrib_ptr) * 8;
518 uint8_t c = *attrib_ptr & 0x0f;
519 if(*attrib_ptr & 0x80) {
525 // draw sprite (not enlarged)
526 for(int yy = y; yy < y + size; yy++) {
527 if(yy < 0 || 191 < yy) {
531 // illegal sprite line
532 if(yy < illegal_sprite_line) {
533 illegal_sprite_line = yy;
535 } else if(illegal_sprite_line == yy) {
536 if(illegal_sprite > p) {
540 //#ifdef TMS9918A_LIMIT_SPRITES
541 if(_tms9918a_limit_sprites) continue;
546 uint16_t line = pattern_ptr[yy - y] * 256 + pattern_ptr[yy - y + 16];
547 for(int xx = x; xx < x + size; xx++) {
549 if(0 <= xx && xx < 256) {
550 if(collision[yy][xx]) {
553 collision[yy][xx] = 1;
555 if(c && !(collision[yy][xx] & 2)) {
556 collision[yy][xx] |= 2;
565 // draw enlarged sprite
566 for(int i = 0; i < size; i++) {
568 uint16_t line2 = pattern_ptr[i] * 256 + pattern_ptr[i + 16];
569 for(int j = 0; j < 2; j++) {
570 if(0 <= yy && yy <= 191) {
572 // illegal sprite line
573 if(yy < illegal_sprite_line) {
574 illegal_sprite_line = yy;
576 } else if(illegal_sprite_line == yy) {
577 if(illegal_sprite > p) {
581 //#ifdef TMS9918A_LIMIT_SPRITES
582 if(_tms9918a_limit_sprites) continue;
587 uint16_t line = line2;
588 for(int xx = x; xx < x + size * 2; xx += 2) {
590 if(0 <= xx && xx < 256) {
591 if(collision[yy][xx]) {
594 collision[yy][xx] = 1;
596 if(c && !(collision[yy][xx] & 2)) {
597 collision[yy][xx] |= 2;
601 if(0 <= xx + 1 && xx + 1 < 256) {
602 if(collision[yy][xx + 1]) {
605 collision[yy][xx + 1] = 1;
607 if(c && !(collision[yy][xx + 1] & 2)) {
608 collision[yy][xx + 1] |= 2;
609 screen[yy][xx + 1] = c;
621 if(illegal_sprite_line == 255) {
622 status_reg |= (p > 31) ? 31 : p;
624 status_reg |= 0x40 + illegal_sprite;
628 //#ifdef USE_DEBUGGER
629 void TMS9918A::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len)
631 my_stprintf_s(buffer, buffer_len,
632 _T("REGS=%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X VRAM_ADDR=%04X STATUS=%02X"),
633 regs[0], regs[1], regs[2], regs[3], regs[4], regs[5], regs[6], regs[7],
634 vram_addr, status_reg);
638 #define STATE_VERSION 1
640 bool TMS9918A::process_state(FILEIO* state_fio, bool loading)
642 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
645 if(!state_fio->StateCheckInt32(this_device_id)) {
648 state_fio->StateArray(vram, sizeof(vram), 1);
649 state_fio->StateArray(regs, sizeof(regs), 1);
650 state_fio->StateValue(status_reg);
651 state_fio->StateValue(read_ahead);
652 state_fio->StateValue(first_byte);
653 state_fio->StateValue(vram_addr);
654 state_fio->StateValue(latch);
655 state_fio->StateValue(intstat);
656 state_fio->StateValue(color_table);
657 state_fio->StateValue(pattern_table);
658 state_fio->StateValue(name_table);
659 state_fio->StateValue(sprite_pattern);
660 state_fio->StateValue(sprite_attrib);
661 state_fio->StateValue(color_mask);
662 state_fio->StateValue(pattern_mask);
663 if(_tms9918a_super_impose) {
664 state_fio->StateValue(now_super_impose);