2 Skelton for retropc emulator
13 #include "gamegear/keyboard.h"
15 /* Return values from the V counter */
16 static const uint8_t vcnt[0x200] =
18 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
19 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
20 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
21 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
22 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
23 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
24 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
25 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
26 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
27 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
28 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
29 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
30 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
31 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA,
32 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
33 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
34 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
37 /* Return values from the H counter */
38 static const uint8_t hcnt[0x200] =
40 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
41 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
42 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
43 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
44 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
45 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
46 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
47 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
48 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
49 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
50 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
51 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
52 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
53 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
54 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9,
55 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
56 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
57 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
58 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
59 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
60 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
61 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
64 /* Attribute expansion table */
65 static const uint32_t atex[4] =
73 //#ifdef _MASTERSYSTEM
74 static const uint8_t tms_crom[] =
76 0x00, 0x00, 0x08, 0x0C,
77 0x10, 0x30, 0x01, 0x3C,
78 0x02, 0x03, 0x05, 0x0F,
79 0x04, 0x33, 0x15, 0x3F
83 /* Mark a pattern as dirty */
84 #define MARK_BG_DIRTY(addr) \
86 int name = (addr >> 5) & 0x1FF; \
87 if(bg_name_dirty[name] == 0) \
89 bg_name_list[bg_list_index] = name; \
92 bg_name_dirty[name] |= (1 << ((addr >> 2) & 7)); \
95 void _315_5124::initialize()
98 __MASTERSYSTEM = osd->check_feature(_T("_MASTERSYSTEM"));
99 __315_5124_LIMIT_SPRITES = osd->check_feature(_T("_315_5124_LIMIT_SPRITES"));
100 // Game Gear : console = 0x40, vdp_mode = 4
101 // Mark3 : console = 0x20, vdp_mode = 4
102 // SC-3000 : console = 0x10, vdp_mode = 0
103 // COLECO : console = 0x00, vdp_mode = 0
106 register_vline_event(this);
109 void _315_5124::reset()
112 int bx, sx, b, s, bp, bf, sf, c;
114 /* Generate 64k of data for the look up table */
115 for (bx = 0; bx < 0x100; bx++) {
116 for (sx = 0; sx < 0x100; sx++) {
117 /* Background pixel */
119 /* Background priority */
120 bp = (bx & 0x20) ? 1 : 0;
121 /* Full background pixel + priority + sprite marker */
125 /* Full sprite pixel, w/ palette and marker bits added */
126 sf = (sx & 0x0F) | 0x10 | 0x40;
127 /* Overwriting a sprite pixel ? */
129 /* Return the input */
132 /* Work out priority and transparency for both pixels */
134 /* Underlying pixel is high priority */
145 /* Underlying pixel is low priority */
154 lut[(bx << 8) | (sx)] = c;
158 /* Make bitplane to pixel lookup table */
159 for (i = 0; i < 0x100; i++) {
160 for (j = 0; j < 0x100; j++) {
163 for (x = 0; x < 8; x++) {
164 out |= (j & (0x80 >> x)) ? (uint32_t)(8 << (x << 2)) : 0;
165 out |= (i & (0x80 >> x)) ? (uint32_t)(4 << (x << 2)) : 0;
167 bp_lut[(j << 8) | (i)] = out;
171 for (i = 0; i < 4; i++) {
172 uint8_t c = i << 6 | i << 4 | i << 2 | i;
173 sms_cram_expand_table[i] = c;
176 for (i = 0; i < 16; i++) {
177 uint8_t c = i << 4 | i;
178 gg_cram_expand_table[i] = c;
181 /* Invalidate pattern cache */
182 memset(bg_name_dirty, 0, sizeof(bg_name_dirty));
183 memset(bg_name_list, 0, sizeof(bg_name_list));
185 memset(bg_pattern_cache, 0, sizeof(bg_pattern_cache));
186 memset(cram, 0, sizeof(cram));
197 memset(vram, 0, sizeof(vram));
198 memset(screen, 0, sizeof(screen));
199 memset(regs, 0, sizeof(regs));
200 status_reg = read_ahead = first_byte = 0;
202 intstat = latch = false;
203 color_table = pattern_table = name_table = 0;
204 sprite_pattern = sprite_attrib = 0;
205 color_mask = pattern_mask = 0;
208 palette_pc[0]=RGB_COLOR(0, 0, 0);
209 palette_pc[1]=RGB_COLOR(0, 0, 0);
210 palette_pc[2]=RGB_COLOR(33, 200, 66);
211 palette_pc[3]=RGB_COLOR(94, 220, 120);
212 palette_pc[4]=RGB_COLOR(84, 85, 237);
213 palette_pc[5]=RGB_COLOR(125, 118, 252);
214 palette_pc[6]=RGB_COLOR(212, 82, 77);
215 palette_pc[7]=RGB_COLOR(66, 235, 245);
216 palette_pc[8]=RGB_COLOR(252, 85, 84);
217 palette_pc[9]=RGB_COLOR(255, 121, 120);
218 palette_pc[10]=RGB_COLOR(212, 193, 84);
219 palette_pc[11]=RGB_COLOR(230, 206, 128);
220 palette_pc[12]=RGB_COLOR(33, 176, 59);
221 palette_pc[13]=RGB_COLOR(201, 91, 186);
222 palette_pc[14]=RGB_COLOR(204, 204, 204);
223 palette_pc[15]=RGB_COLOR(255, 255, 255);
224 palette_pc[16]=RGB_COLOR(0, 0, 0);
225 palette_pc[17]=RGB_COLOR(0, 0, 0);
226 palette_pc[18]=RGB_COLOR(0, 0, 0);
227 palette_pc[19]=RGB_COLOR(0, 0, 0);
228 palette_pc[20]=RGB_COLOR(0, 0, 0);
229 palette_pc[21]=RGB_COLOR(0, 0, 0);
230 palette_pc[22]=RGB_COLOR(0, 0, 0);
231 palette_pc[23]=RGB_COLOR(0, 0, 0);
232 palette_pc[24]=RGB_COLOR(0, 0, 0);
233 palette_pc[25]=RGB_COLOR(0, 0, 0);
234 palette_pc[26]=RGB_COLOR(0, 0, 0);
235 palette_pc[27]=RGB_COLOR(0, 0, 0);
236 palette_pc[28]=RGB_COLOR(0, 0, 0);
237 palette_pc[29]=RGB_COLOR(0, 0, 0);
238 palette_pc[30]=RGB_COLOR(0, 0, 0);
239 palette_pc[31]=RGB_COLOR(0, 0, 0);
240 //#ifdef _MASTERSYSTEM // 315-5124 palette
242 if (console) { // without COLECO
243 for (i = 0; i < 32; i++) {
244 int r = (tms_crom[i & 0x0F] >> 0) & 3;
245 int g = (tms_crom[i & 0x0F] >> 2) & 3;
246 int b = (tms_crom[i & 0x0F] >> 4) & 3;
247 r = sms_cram_expand_table[r];
248 g = sms_cram_expand_table[g];
249 b = sms_cram_expand_table[b];
250 palette_pc[i]=RGB_COLOR(r, g, b);
255 vp_x = (console == 0x40) ? 48 : 0;
256 vp_y = (console == 0x40) ? 24 : 0;
257 vp_w = (console == 0x40) ? 160 : 256;
258 vp_h = (console == 0x40) ? 144 : 192;
261 void _315_5124::viewport_check(void)
264 int m1 = (regs[1] >> 4) & 1;
265 int m3 = (regs[1] >> 3) & 1;
266 int m2 = (regs[0] >> 1) & 1;
267 int m4 = (regs[0] >> 2) & 1;
269 // check if this is switching out of tms
270 if (!(console & 0x40)) {
272 // Game Gear or Mark3
273 for(int i = 0; i < 0x20; i++) {
283 name_table = (regs[2] << 10) & 0x3800;
284 color_table = (regs[3] << 6) & 0x3FC0;
285 pattern_table = (regs[4] << 11) & 0x3800;
286 sprite_attrib = (regs[5] << 7) & 0x3F00;
287 sprite_pattern = (regs[6] << 11) & 0x3800;
290 void _315_5124::vdp_reg_w(uint8_t r, uint8_t d)
292 // Store register data
297 case 0x00: // Mode Control No. 1
298 case 0x01: // Mode Control No. 2
299 case 0x02: // Name Table A Base Address
304 case 0x05: // Sprite Attribute Table Base Address
311 void __FASTCALL _315_5124::write_io8(uint32_t addr, uint32_t data)
314 if ((addr & 0x000000ff)==0x7f) {
315 d_psg->write_io8(0xff, data);
322 // Game Gear or Mark3
324 addrmode = (data >> 6) & 3;
325 vram_addr = (data << 8 | first_byte) & 0x3FFF;
327 buffer = vram[vram_addr & 0x3FFF];
328 vram_addr = (vram_addr + 1) & 0x3FFF;
331 int r = (data & 0x0F);
341 regs[0] = first_byte & 3;
343 color_table = ((regs[3] & 0x80) * 64) & ADDR_MASK;
344 color_mask = ((regs[3] & 0x7f) * 8) | 7;
345 pattern_table = ((regs[4] & 4) * 2048) & ADDR_MASK;
346 pattern_mask = ((regs[4] & 3) * 256) | (color_mask & 0xff);
348 color_table = (regs[3] * 64) & ADDR_MASK;
349 pattern_table = (regs[4] * 2048) & ADDR_MASK;
353 regs[1] = first_byte & 0xfb;
354 set_intstat((regs[1] & 0x20) && (status_reg & 0x80));
357 regs[2] = first_byte & 0x0f;
358 name_table = (regs[2] * 1024) & ADDR_MASK;
361 regs[3] = first_byte;
363 color_table = ((regs[3] & 0x80) * 64) & ADDR_MASK;
364 color_mask = ((regs[3] & 0x7f) * 8) | 7;
366 color_table = (regs[3] * 64) & ADDR_MASK;
368 pattern_mask = ((regs[4] & 3) * 256) | (color_mask & 0xff);
371 regs[4] = first_byte & 7;
373 pattern_table = ((regs[4] & 4) * 2048) & ADDR_MASK;
374 pattern_mask = ((regs[4] & 3) * 256) | 255;
376 pattern_table = (regs[4] * 2048) & ADDR_MASK;
380 regs[5] = first_byte & 0x7f;
381 sprite_attrib = (regs[5] * 128) & ADDR_MASK;
384 regs[6] = first_byte & 7;
385 sprite_pattern = (regs[6] * 2048) & ADDR_MASK;
388 regs[7] = first_byte;
392 vram_addr = ((data * 256) | first_byte) & ADDR_MASK;
394 read_io8(0); // read ahead
398 vram_addr = (vram_addr & 0x3F00) | (data & 0xFF);
404 // Game Gear or Mark3
408 case 0: /* VRAM write */
409 case 1: /* VRAM write */
410 case 2: /* VRAM write */
411 index = (vram_addr & 0x3FFF);
412 if (data != vram[index]) {
414 MARK_BG_DIRTY(vram_addr);
417 case 3: /* CRAM write */
418 if (console & 0x40) {
420 cram_latch = (cram_latch & 0x00FF) | ((data & 0xFF) << 8);
421 cram[(vram_addr & 0x3E) | (0)] = (cram_latch >> 0) & 0xFF;
422 cram[(vram_addr & 0x3E) | (1)] = (cram_latch >> 8) & 0xFF;
423 palette_sync((vram_addr >> 1) & 0x1F, 0);
425 cram_latch = (cram_latch & 0xFF00) | ((data & 0xFF) << 0);
428 index = (vram_addr & 0x1F);
429 if(data != cram[index]) {
431 palette_sync(index, 0);
436 vram_addr = (vram_addr + 1) & 0x3FFF;
440 vram[vram_addr] = data;
441 vram_addr = (vram_addr + 1) & ADDR_MASK;
446 uint32_t __FASTCALL _315_5124::read_io8(uint32_t addr)
449 if ((addr & 0x000000ff) == 0x7e) {
451 return vcnt[vcounter & 0x01FF];
453 if ((addr & 0x000000ff) == 0x7f) {
455 uint16_t pixel = (((z80_icount % CYCLES_PER_LINE) / 4) * 3) * 2;
456 return hcnt[(pixel >> 1) & 0x01FF];;
460 case 0: // CPU <-> VDP data buffer
463 buffer = vram[vram_addr & 0x3FFF];
464 vram_addr = (vram_addr + 1) & 0x3FFF;
466 case 1: // Status flags
473 // Just to please the compiler
477 void _315_5124::draw_screen()
479 if(emu->now_waiting_in_debugger) {
481 uint16_t tmp_z80_icount = z80_icount;
482 uint16_t tmp_vcounter = vcounter;
483 uint8_t tmp_status_reg = status_reg;
484 uint16_t tmp_hlatch = hlatch;
485 bool tmp_intstat = intstat;
488 for(int v = /*get_cur_vline() + 1*/0; v < get_lines_per_frame(); v++) {
493 z80_icount = tmp_z80_icount;
494 vcounter = tmp_vcounter;
495 status_reg = tmp_status_reg;
497 intstat = tmp_intstat;
500 // update screen buffer
501 for(int y = 0; y < 192; y++) {
502 //scrntype_t* dest = emu->get_screen_buffer(y);
503 scrntype_t* dest = osd->get_vm_screen_buffer(y);
504 uint8_t* src = screen[y];
505 for(int x = 0; x < 256; x++) {
506 if (x>=vp_x && x<vp_x+vp_w && y>=vp_y && y<vp_y+vp_h) {
507 int color=(src[x] & 0x1f);
508 dest[x] = palette_pc[color];
510 dest[x] = palette_pc[0x10];
516 void _315_5124::event_vline(int v, int clock)
534 if((status_reg & 0x40) && (regs[0] & 0x10)) {
536 set_intstat((regs[0] & 0x10) != 0);
540 if((v < 0xE0) && (status_reg & 0x80) && (regs[1] & 0x20)) {
542 set_intstat((regs[1] & 0x20) != 0);
546 /* Ensure we're within the viewport range */
547 if(v < vp_y || v >= (vp_y + vp_h)) return;
549 /* Point to current line in output buffer */
550 linebuf = (uint8_t *)screen[v];
552 /* Update pattern cache */
553 update_bg_pattern_cache();
555 /* Blank line (full width) */
556 if (!(regs[1] & 0x40)) {
557 memset(linebuf, BACKDROP_COLOR, 256);
559 /* Draw background */
563 /* Blank leftmost column of display */
564 if (regs[0] & 0x20) {
565 memset(linebuf, BACKDROP_COLOR, 8);
570 // create virtual screen
572 // draw character plane
573 int mode = (regs[0] & 2) | ((regs[1] & 0x10) >> 4) | ((regs[1] & 8) >> 1);
600 if((regs[1] & 0x50) == 0x40) {
604 memset(screen, 0, sizeof(screen));
608 set_intstat((regs[1] & 0x20) != 0);
613 void _315_5124::set_intstat(bool val)
616 if(!emu->now_waiting_in_debugger) {
617 write_signals(&outputs_irq, val ? 0xffffffff : 0);
623 void _315_5124::draw_mode0()
625 for(int y = 0, name = 0; y < 24; y++) {
626 for(int x = 0; x < 32; x++) {
627 uint16_t code = vram[name_table + (name++)];
628 uint8_t* pattern_ptr = vram + pattern_table + code * 8;
629 uint8_t color = vram[color_table + (code >> 3)];
630 uint8_t fg = (color & 0xf0) ? (color >> 4) : (regs[7] & 0x0f);
631 uint8_t bg = (color & 0x0f) ? (color & 0x0f) : (regs[7] & 0x0f);
632 for(int yy=0; yy < 8; yy++) {
633 uint8_t pattern = *pattern_ptr++;
634 uint8_t* buffer = screen[y * 8 + yy] + x * 8;
635 buffer[0] = (pattern & 0x80) ? fg : bg;
636 buffer[1] = (pattern & 0x40) ? fg : bg;
637 buffer[2] = (pattern & 0x20) ? fg : bg;
638 buffer[3] = (pattern & 0x10) ? fg : bg;
639 buffer[4] = (pattern & 0x08) ? fg : bg;
640 buffer[5] = (pattern & 0x04) ? fg : bg;
641 buffer[6] = (pattern & 0x02) ? fg : bg;
642 buffer[7] = (pattern & 0x01) ? fg : bg;
648 void _315_5124::draw_mode1()
650 uint8_t fg = regs[7] >> 4;
651 uint8_t bg = regs[7] & 0x0f;
652 for(int y = 0, name = 0; y < 24; y++) {
653 for(int x = 0; x < 40; x++) {
654 uint16_t code = vram[name_table + (name++)];
655 uint8_t* pattern_ptr = vram + pattern_table + code * 8;
656 for(int yy = 0; yy < 8; yy++) {
657 uint8_t pattern = *pattern_ptr++;
658 uint8_t* buffer = screen[y * 8 + yy] + x * 6 + 8;
659 buffer[0] = (pattern & 0x80) ? fg : bg;
660 buffer[1] = (pattern & 0x40) ? fg : bg;
661 buffer[2] = (pattern & 0x20) ? fg : bg;
662 buffer[3] = (pattern & 0x10) ? fg : bg;
663 buffer[4] = (pattern & 0x08) ? fg : bg;
664 buffer[5] = (pattern & 0x04) ? fg : bg;
670 void _315_5124::draw_mode2()
672 for(int y = 0, name = 0; y < 24; y++) {
673 for(int x = 0; x < 32; x++) {
674 uint16_t code = vram[name_table + (name++)] + (y & 0xf8) * 32;
675 uint8_t* pattern_ptr = vram + pattern_table + (code & pattern_mask) * 8;
676 uint8_t* color_ptr = vram + color_table + (code & color_mask) * 8;
677 for(int yy = 0; yy < 8; yy++) {
678 uint8_t pattern = *pattern_ptr++;
679 uint8_t color = *color_ptr++;
680 uint8_t fg = (color & 0xf0) ? (color >> 4) : (regs[7] & 0x0f);
681 uint8_t bg = (color & 0x0f) ? (color & 0x0f) : (regs[7] & 0x0f);
682 uint8_t* buffer = screen[y * 8 + yy] + x * 8;
683 buffer[0] = (pattern & 0x80) ? fg : bg;
684 buffer[1] = (pattern & 0x40) ? fg : bg;
685 buffer[2] = (pattern & 0x20) ? fg : bg;
686 buffer[3] = (pattern & 0x10) ? fg : bg;
687 buffer[4] = (pattern & 0x08) ? fg : bg;
688 buffer[5] = (pattern & 0x04) ? fg : bg;
689 buffer[6] = (pattern & 0x02) ? fg : bg;
690 buffer[7] = (pattern & 0x01) ? fg : bg;
696 void _315_5124::draw_mode12()
698 uint8_t fg = regs[7] >> 4;
699 uint8_t bg = regs[7] & 0x0f;
700 for(int y = 0, name = 0; y < 24; y++) {
701 for(int x = 0; x < 40; x++) {
702 uint16_t code = vram[name_table + (name++)] + (y & 0xf8) * 32;
703 uint8_t* pattern_ptr = vram + pattern_table + (code & pattern_mask) * 8;
704 for(int yy = 0; yy < 8; yy++) {
705 uint8_t pattern = *pattern_ptr++;
706 uint8_t* buffer = screen[y * 8 + yy] + x * 6 + 8;
707 buffer[0] = (pattern & 0x80) ? fg : bg;
708 buffer[1] = (pattern & 0x40) ? fg : bg;
709 buffer[2] = (pattern & 0x20) ? fg : bg;
710 buffer[3] = (pattern & 0x10) ? fg : bg;
711 buffer[4] = (pattern & 0x08) ? fg : bg;
712 buffer[5] = (pattern & 0x04) ? fg : bg;
718 void _315_5124::draw_mode3()
720 for(int y = 0, name = 0; y < 24; y++) {
721 for(int x = 0; x < 32; x++) {
722 uint16_t code = vram[name_table + (name++)];
723 uint8_t* pattern_ptr = vram + pattern_table + code * 8 + (y & 3) * 2;
724 for(int yy = 0; yy < 2; yy++) {
725 uint8_t color = *pattern_ptr++;
726 uint8_t fg = (color & 0xf0) ? (color >> 4) : (regs[7] & 0x0f);
727 uint8_t bg = (color & 0x0f) ? (color & 0x0f) : (regs[7] & 0x0f);
728 for(int yyy = 0; yyy < 4; yyy++) {
729 uint8_t* buffer = screen[y * 8 + yy * 4 + yyy] + x * 8;
730 buffer[0] = buffer[1] = buffer[2] = buffer[3] = fg;
731 buffer[4] = buffer[5] = buffer[6] = buffer[7] = bg;
738 void _315_5124::draw_mode23()
740 for(int y = 0, name = 0; y < 24;y++) {
741 for(int x = 0; x < 32; x++) {
742 uint16_t code = vram[name_table + (name++)];
743 uint8_t* pattern_ptr = vram + pattern_table + ((code + (y & 3) * 2 + (y & 0xf8) * 32) & pattern_mask) * 8;
744 for(int yy = 0; yy < 2; yy++) {
745 uint8_t color = *pattern_ptr++;
746 uint8_t fg = (color & 0xf0) ? (color >> 4) : (regs[7] & 0x0f);
747 uint8_t bg = (color & 0x0f) ? (color & 0x0f) : (regs[7] & 0x0f);
748 for(int yyy = 0; yyy < 4; yyy++) {
749 uint8_t* buffer = screen[y * 8 + yy * 4 + yyy] + x * 8;
750 buffer[0] = buffer[1] = buffer[2] = buffer[3] = fg;
751 buffer[4] = buffer[5] = buffer[6] = buffer[7] = bg;
758 void _315_5124::draw_modebogus()
760 uint8_t fg = regs[7] >> 4;
761 uint8_t bg = regs[7] & 0x0f;
762 for(int y = 0; y < 192; y++) {
763 uint8_t* buffer = screen[y];
765 for(int i = 0; i < 8; i++) {
768 for(int i = 0; i < 40; i++) {
769 for(int j = 0; j < 4; j++) {
772 for(int j = 0; j < 2; j++) {
776 for(int i = 0; i < 8; i++) {
782 void _315_5124::draw_sprites()
784 uint8_t* attrib_ptr = vram + sprite_attrib;
785 int size = (regs[1] & 2) ? 16 : 8;
786 bool large = ((regs[1] & 1) != 0);
787 uint8_t limit[192], collision[192][256];
788 int illegal_sprite = 0, illegal_sprite_line = 255, p;
789 memset(limit, 4, sizeof(limit));
790 memset(collision, 0, sizeof(collision));
793 for(p = 0; p < 32; p++) {
794 int y = *attrib_ptr++;
803 int x = *attrib_ptr++;
804 uint8_t* pattern_ptr = vram + sprite_pattern + ((size == 16) ? (*attrib_ptr & 0xfc) : *attrib_ptr) * 8;
806 uint8_t c = *attrib_ptr & 0x0f;
807 if(*attrib_ptr & 0x80) {
813 // draw sprite (not enlarged)
814 for(int yy = y; yy < y + size; yy++) {
815 if(yy < 0 || 191 < yy) {
819 // illegal sprite line
820 if(yy < illegal_sprite_line) {
821 illegal_sprite_line = yy;
823 } else if(illegal_sprite_line == yy) {
824 if(illegal_sprite > p) {
828 //#ifdef _315_5124_LIMIT_SPRITES
829 if(__315_5124_LIMIT_SPRITES) {
836 uint16_t line = pattern_ptr[yy - y] * 256 + pattern_ptr[yy - y + 16];
837 for(int xx = x; xx < x + size; xx++) {
839 if(0 <= xx && xx < 256) {
840 if(collision[yy][xx]) {
843 collision[yy][xx] = 1;
845 if(c && !(collision[yy][xx] & 2)) {
846 collision[yy][xx] |= 2;
855 // draw enlarged sprite
856 for(int i = 0; i < size; i++) {
858 uint16_t line2 = pattern_ptr[i] * 256 + pattern_ptr[i + 16];
859 for(int j = 0; j < 2; j++) {
860 if(0 <= yy && yy <= 191) {
862 // illegal sprite line
863 if(yy < illegal_sprite_line) {
864 illegal_sprite_line = yy;
866 } else if(illegal_sprite_line == yy) {
867 if(illegal_sprite > p) {
871 //#ifdef _315_5124_LIMIT_SPRITES
872 if(__315_5124_LIMIT_SPRITES) {
879 uint16_t line = line2;
880 for(int xx = x; xx < x + size * 2; xx += 2) {
882 if(0 <= xx && xx < 256) {
883 if(collision[yy][xx]) {
886 collision[yy][xx] = 1;
888 if(c && !(collision[yy][xx] & 2)) {
889 collision[yy][xx] |= 2;
893 if(0 <= xx + 1 && xx + 1 < 256) {
894 if(collision[yy][xx + 1]) {
897 collision[yy][xx + 1] = 1;
899 if(c && !(collision[yy][xx + 1] & 2)) {
900 collision[yy][xx + 1] |= 2;
901 screen[yy][xx + 1] = c;
913 if(illegal_sprite_line == 255) {
914 status_reg |= (p > 31) ? 31 : p;
916 status_reg |= 0x40 + illegal_sprite;
920 /* Draw the background */
921 void _315_5124::render_bg(int line)
924 int yscroll_mask = 224;
925 int v_line = (line + regs[9]) % yscroll_mask;
926 int v_row = (v_line & 7) << 3;
927 int hscroll = ((regs[0] & 0x40) && (line < 0x10)) ? 0 : (0x100 - regs[8]);
930 uint16_t *nt = (uint16_t *)&vram[name_table + ((v_line >> 3) << 6)];
931 int nt_scroll = (hscroll >> 3);
932 int shift = (hscroll & 7);
935 uint32_t *linebuf_ptr = (uint32_t *)&linebuf[0 - shift];
937 /* Draw first column (clipped) */
940 for(x = shift; x < 8; x++)
941 linebuf[(0 - shift) + (x)] = 0;
944 /* Draw a line of the background */
945 for (; column < 32; column++) {
946 /* Stop vertical scrolling for leftmost eight columns */
947 if ((regs[0] & 0x80) && (!locked) && (column >= 24)) {
949 v_row = (line & 7) << 3;
950 nt = (uint16_t *)&vram[((regs[2] << 10) & 0x3800) + ((line >> 3) << 6)];
952 /* Get name table attribute word */
953 attr = nt[(column + nt_scroll) & 0x1F];
954 /* Expand priority and palette bits */
955 atex_mask = atex[(attr >> 11) & 3];
956 /* Point to a line of pattern data in cache */
957 cache_ptr = (uint32_t *)&bg_pattern_cache[((attr & 0x7FF) << 6) | (v_row)];
958 /* Copy the left half, adding the attribute bits in */
959 write_dword( &linebuf_ptr[(column << 1)] , read_dword( &cache_ptr[0] ) | (atex_mask));
960 /* Copy the right half, adding the attribute bits in */
961 write_dword( &linebuf_ptr[(column << 1) | (1)], read_dword( &cache_ptr[1] ) | (atex_mask));
963 /* Draw last column (clipped) */
966 uint8_t *p = &linebuf[(0 - shift)+(column << 3)];
967 attr = nt[(column + nt_scroll) & 0x1F];
968 a = (attr >> 7) & 0x30;
969 for (x = 0; x < shift; x++) {
970 c = bg_pattern_cache[((attr & 0x7FF) << 6) | (v_row) | (x)];
977 void _315_5124::render_obj(int line)
980 uint8_t collision_buffer = 0;
981 /* Sprite count for current line (8 max.) */
983 /* Sprite dimensions */
985 int height = (regs[1] & 0x02) ? 16 : 8;
986 /* Pointer to sprite attribute table */
987 uint8_t *st = (uint8_t *)&vram[sprite_attrib];
988 /* Adjust dimensions for double size sprites */
989 if (regs[1] & 0x01) {
993 /* Draw sprites in front-to-back order */
994 for (i = 0; i < 64; i++) {
995 /* Sprite Y position */
997 /* Found end of sprite list marker for non-extended modes? */
998 if (yp == 208) goto end;
999 /* Actual Y position is +1 */
1001 /* Wrap Y coordinate for sprites > 240 */
1002 if (yp > 240) yp -= 256;
1003 /* Check if sprite falls on current line */
1004 if ((line >= yp) && (line < (yp + height))) {
1005 uint8_t *linebuf_ptr;
1006 /* Width of sprite */
1009 /* Sprite X position */
1010 int xp = st[0x80 + (i << 1)];
1012 int n = st[0x81 + (i << 1)];
1013 /* Bump sprite count */
1015 /* Too many sprites on this line ? */
1020 /* X position shift */
1021 if (regs[0] & 0x08) xp -= 8;
1022 /* Add MSB of pattern name */
1023 if (regs[6] & 0x04) n |= 0x0100;
1024 /* Mask LSB for 8x16 sprites */
1025 if (regs[1] & 0x02) n &= 0x01FE;
1026 /* Point to offset in line buffer */
1027 linebuf_ptr = (uint8_t *)&linebuf[xp];
1028 /* Clip sprites on left edge */
1032 /* Clip sprites on right edge */
1033 if ((xp + width) > 256) {
1036 /* Draw double size sprite */
1037 if (regs[1] & 0x01) {
1039 uint8_t *cache_ptr = (uint8_t *)&bg_pattern_cache[(n << 6) | (((line - yp) >> 1) << 3)];
1040 /* Draw sprite line */
1041 for (x = start; x < end; x++) {
1042 /* Source pixel from cache */
1043 uint8_t sp = cache_ptr[(x >> 1)];
1044 /* Only draw opaque sprite pixels */
1046 /* Background pixel from line buffer */
1047 uint8_t bg = linebuf_ptr[x];
1048 /* Look up result */
1049 linebuf_ptr[x] = lut[(bg << 8) | (sp)];
1050 /* Update collision buffer */
1051 collision_buffer |= bg;
1054 } else { /* Regular size sprite (8x8 / 8x16) */
1056 uint8_t *cache_ptr = (uint8_t *)&bg_pattern_cache[(n << 6) | ((line - yp) << 3)];
1057 /* Draw sprite line */
1058 for (x = start; x < end; x++) {
1059 /* Source pixel from cache */
1060 uint8_t sp = cache_ptr[x];
1061 /* Only draw opaque sprite pixels */
1063 /* Background pixel from line buffer */
1064 uint8_t bg = linebuf_ptr[x];
1065 /* Look up result */
1066 linebuf_ptr[x] = lut[(bg << 8) | (sp)];
1067 /* Update collision buffer */
1068 collision_buffer |= bg;
1075 /* Set sprite collision flag */
1076 if (collision_buffer & 0x40) status_reg |= 0x20;
1079 void _315_5124::update_bg_pattern_cache(void)
1084 if (!bg_list_index) return;
1085 for (i = 0; i < bg_list_index; i++) {
1086 name = bg_name_list[i];
1087 bg_name_list[i] = 0;
1088 for (y = 0; y < 8; y++) {
1089 if (bg_name_dirty[name] & (1 << y)) {
1090 uint8_t *dst = &bg_pattern_cache[name << 6];
1091 uint16_t bp01 = *(uint16_t *)&vram[(name << 5) | (y << 2) | (0)];
1092 uint16_t bp23 = *(uint16_t *)&vram[(name << 5) | (y << 2) | (2)];
1093 uint32_t temp = (bp_lut[bp01] >> 2) | (bp_lut[bp23]);
1094 for (x = 0; x < 8; x++) {
1095 uint8_t c = (temp >> (x << 2)) & 0x0F;
1096 dst[0x00000 | (y << 3) | (x)] = (c);
1097 dst[0x08000 | (y << 3) | (x ^ 7)] = (c);
1098 dst[0x10000 | ((y ^ 7) << 3) | (x)] = (c);
1099 dst[0x18000 | ((y ^ 7) << 3) | (x ^ 7)] = (c);
1103 bg_name_dirty[name] = 0;
1108 void _315_5124::palette_sync(int index, int force)
1111 if (console & 0x40) {
1112 /* ----BBBBGGGGRRRR */
1113 r = (cram[(index << 1) | (0)] >> 0) & 0x0F;
1114 g = (cram[(index << 1) | (0)] >> 4) & 0x0F;
1115 b = (cram[(index << 1) | (1)] >> 0) & 0x0F;
1116 r = gg_cram_expand_table[r];
1117 g = gg_cram_expand_table[g];
1118 b = gg_cram_expand_table[b];
1120 // unless we are forcing an update,
1121 // if not in mode 4, exit
1122 if (!force && (regs[0] & 4) == 0) return;
1124 r = (cram[index] >> 0) & 3;
1125 g = (cram[index] >> 2) & 3;
1126 b = (cram[index] >> 4) & 3;
1127 r = sms_cram_expand_table[r];
1128 g = sms_cram_expand_table[g];
1129 b = sms_cram_expand_table[b];
1131 palette_pc[index] = RGB_COLOR(r, g, b);