OSDN Git Service

[VM][PC9801][MEMBUS] Split update_bios() to functions.
[csp-qt/common_source_project-fm7.git] / source / src / vm / 315-5124.cpp
1 /*
2         Skelton for retropc emulator
3
4         Origin : SMS Plus
5         Author : tanam
6         Date   : 2013.09.14 -
7
8         [ _315_5124 ]
9 */
10
11 #include "z80.h"
12 #include "315-5124.h"
13 #include "gamegear/keyboard.h"
14
15 /* Return values from the V counter */
16 static const uint8_t vcnt[0x200] =
17 {
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,
35 };
36
37 /* Return values from the H counter */
38 static const uint8_t hcnt[0x200] =
39 {
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,
62 };
63
64 /* Attribute expansion table */
65 static const uint32_t atex[4] =
66 {
67         0x00000000,
68         0x10101010,
69         0x20202020,
70         0x30303030,
71 };
72
73 //#ifdef _MASTERSYSTEM
74 static const uint8_t tms_crom[] =
75 {
76         0x00, 0x00, 0x08, 0x0C,
77         0x10, 0x30, 0x01, 0x3C,
78         0x02, 0x03, 0x05, 0x0F,
79         0x04, 0x33, 0x15, 0x3F
80 };
81 //#endif
82
83 /* Mark a pattern as dirty */
84 #define MARK_BG_DIRTY(addr)                                                             \
85 {                                                                                                               \
86         int name = (addr >> 5) & 0x1FF;                                         \
87         if(bg_name_dirty[name] == 0)                                            \
88         {                                                                                                       \
89                 bg_name_list[bg_list_index] = name;                             \
90                 bg_list_index++;                                                                \
91         }                                                                                                       \
92         bg_name_dirty[name] |= (1 << ((addr >> 2) & 7));        \
93 }
94
95 void _315_5124::initialize()
96 {
97         DEVICE::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
104         console = 0x20;
105         // register event
106         register_vline_event(this);
107 }
108
109 void _315_5124::reset()
110 {
111         int i, j;
112         int bx, sx, b, s, bp, bf, sf, c;
113         
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 */
118                         b  = (bx & 0x0F);
119                         /* Background priority */
120                         bp = (bx & 0x20) ? 1 : 0;
121                         /* Full background pixel + priority + sprite marker */
122                         bf = (bx & 0x7F);
123                         /* Sprite pixel */
124                         s  = (sx & 0x0F);
125                         /* Full sprite pixel, w/ palette and marker bits added */
126                         sf = (sx & 0x0F) | 0x10 | 0x40;
127                         /* Overwriting a sprite pixel ? */
128                         if (bx & 0x40) {
129                                 /* Return the input */
130                                 c = bf;
131                         } else {
132                                 /* Work out priority and transparency for both pixels */
133                                 if (bp) {
134                                         /* Underlying pixel is high priority */
135                                         if (b) {
136                                                 c = bf | 0x40;
137                                         } else {
138                                                 if (s) {
139                                                         c = sf;
140                                                 } else {
141                                                         c = bf;
142                                                 }
143                                         }
144                                 } else {
145                                         /* Underlying pixel is low priority */
146                                         if (s) {
147                                                 c = sf;
148                                         } else {
149                                                 c = bf;
150                                         }
151                                 }
152                         }
153                         /* Store result */
154                         lut[(bx << 8) | (sx)] = c;
155                 }
156         }
157         
158         /* Make bitplane to pixel lookup table */
159         for (i = 0; i < 0x100; i++) {
160                 for (j = 0; j < 0x100; j++) {
161                         int x;
162                         uint32_t out = 0;
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;
166                         }
167                         bp_lut[(j << 8) | (i)] = out;
168                 }
169         }
170         
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;
174         }
175         
176         for (i = 0; i < 16; i++) {
177                 uint8_t c = i << 4 | i;
178                 gg_cram_expand_table[i] = c;
179         }
180         
181         /* Invalidate pattern cache */
182         memset(bg_name_dirty, 0, sizeof(bg_name_dirty));
183         memset(bg_name_list, 0, sizeof(bg_name_list));
184         bg_list_index = 0;
185         memset(bg_pattern_cache, 0, sizeof(bg_pattern_cache));
186         memset(cram, 0, sizeof(cram)); 
187         
188         linebuf = 0;
189         cram_latch = 0;
190         addrmode = 0;
191         buffer = 0;
192         hlatch = 0;
193         vcounter = 0;
194 ///     counter = 0;
195         vdp_mode = 4;
196         
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;
201         vram_addr = 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;
206         
207         // TMS9918 palette
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
241         if(__MASTERSYSTEM) {
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);
251                         }
252                 }
253         }
254 //#endif
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;
259 }
260
261 void _315_5124::viewport_check(void)
262 {
263         vdp_mode = 4;
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;
268         
269         // check if this is switching out of tms
270         if (!(console & 0x40)) {
271                 if (m4) {
272                         // Game Gear or Mark3
273                         for(int i = 0; i < 0x20; i++) {
274                                 palette_sync(i, 1);
275                         }
276                 } else {
277                         // SC-3000
278                         d_key->sk1100=true;
279                         console = 0x10;
280                         vdp_mode = 0; 
281                 }
282         }
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;
288 }
289
290 void _315_5124::vdp_reg_w(uint8_t r, uint8_t d)
291 {
292         // Store register data
293         regs[r] = d;
294         
295         switch(r)
296         {
297         case 0x00: // Mode Control No. 1
298         case 0x01: // Mode Control No. 2
299         case 0x02: // Name Table A Base Address
300                 viewport_check();
301                 break;
302         case 0x03:
303         case 0x04:
304         case 0x05: // Sprite Attribute Table Base Address
305         case 0x06:
306         case 0x07:
307                 break;
308         }
309 }
310
311 void __FASTCALL _315_5124::write_io8(uint32_t addr, uint32_t data)
312 {
313         int index;
314         if ((addr & 0x000000ff)==0x7f) {
315                 d_psg->write_io8(0xff, data);
316                 return;
317         }
318         if (addr & 1) {
319                 // register
320                 if(latch) {
321                         latch = false;
322                         // Game Gear or Mark3
323                         if (vdp_mode == 4) {
324                                 addrmode = (data >> 6) & 3;
325                                 vram_addr = (data << 8 | first_byte) & 0x3FFF;
326                                 if (addrmode == 0) {
327                                          buffer = vram[vram_addr & 0x3FFF];
328                                         vram_addr = (vram_addr + 1) & 0x3FFF;
329                                 }
330                                 if (addrmode == 2) {
331                                         int r = (data & 0x0F);
332                                         int d = first_byte;
333                                         vdp_reg_w(r, d);
334                                 }
335                                 return;
336                         }
337                         // SC-3000
338                         if (data & 0x80) {
339                                 switch(data & 7) {
340                                 case 0:
341                                         regs[0] = first_byte & 3;
342                                         if(regs[0] & 2) {
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);
347                                         } else {
348                                                 color_table = (regs[3] * 64) & ADDR_MASK;
349                                                 pattern_table = (regs[4] * 2048) & ADDR_MASK;
350                                         }
351                                         break;
352                                 case 1:
353                                         regs[1] = first_byte & 0xfb;
354                                         set_intstat((regs[1] & 0x20) && (status_reg & 0x80));
355                                         break;
356                                 case 2:
357                                         regs[2] = first_byte & 0x0f;
358                                         name_table = (regs[2] * 1024) & ADDR_MASK;
359                                         break;
360                                 case 3:
361                                         regs[3] = first_byte;
362                                         if(regs[0] & 2) {
363                                                 color_table = ((regs[3] & 0x80) * 64) & ADDR_MASK;
364                                                 color_mask = ((regs[3] & 0x7f) * 8) | 7;
365                                         } else {
366                                                 color_table = (regs[3] * 64) & ADDR_MASK;
367                                         }
368                                         pattern_mask = ((regs[4] & 3) * 256) | (color_mask & 0xff);
369                                         break;
370                                 case 4:
371                                         regs[4] = first_byte & 7;
372                                         if(regs[0] & 2) {
373                                                 pattern_table = ((regs[4] & 4) * 2048) & ADDR_MASK;
374                                                 pattern_mask = ((regs[4] & 3) * 256) | 255;
375                                         } else {
376                                                 pattern_table = (regs[4] * 2048) & ADDR_MASK;
377                                         }
378                                         break;
379                                 case 5:
380                                         regs[5] = first_byte & 0x7f;
381                                         sprite_attrib = (regs[5] * 128) & ADDR_MASK;
382                                         break;
383                                 case 6:
384                                         regs[6] = first_byte & 7;
385                                         sprite_pattern = (regs[6] * 2048) & ADDR_MASK;
386                                         break;
387                                 case 7:
388                                         regs[7] = first_byte;
389                                         break;
390                                 }
391                         } else {
392                                 vram_addr = ((data * 256) | first_byte) & ADDR_MASK;
393                                 if(!(data & 0x40)) {
394                                         read_io8(0);    // read ahead
395                                 }
396                         }
397                 } else {
398             vram_addr = (vram_addr & 0x3F00) | (data & 0xFF);
399                         first_byte = data;
400                         latch = true;
401                 }
402         } else {
403                 latch = false;
404                 // Game Gear or Mark3
405                 if (vdp_mode == 4) {
406                         switch(addrmode)
407                         {
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]) {
413                                         vram[index] = data;
414                                         MARK_BG_DIRTY(vram_addr);
415                                 }
416                                 break;
417                         case 3: /* CRAM write */
418                                 if (console & 0x40) {
419                                         if (vram_addr & 1) {
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);
424                                         } else {
425                                                 cram_latch = (cram_latch & 0xFF00) | ((data & 0xFF) << 0);
426                                         }
427                                 } else {
428                                         index = (vram_addr & 0x1F);
429                                         if(data != cram[index]) {
430                                                 cram[index] = data;
431                                                 palette_sync(index, 0);
432                                         }
433                                 }
434                                 break;
435                         }
436                         vram_addr = (vram_addr + 1) & 0x3FFF;
437                         return;
438                 }
439                 // SC-3000
440                 vram[vram_addr] = data;
441                 vram_addr = (vram_addr + 1) & ADDR_MASK;
442                 read_ahead = data;
443         }
444 }
445
446 uint32_t __FASTCALL _315_5124::read_io8(uint32_t addr)
447 {
448         uint8_t temp;
449         if ((addr & 0x000000ff) == 0x7e) {
450                 /* V Counter */
451                 return vcnt[vcounter & 0x01FF];
452         }
453         if ((addr & 0x000000ff) == 0x7f) {
454                 /* H Counter */
455                 uint16_t pixel = (((z80_icount % CYCLES_PER_LINE) / 4) * 3) * 2;
456                 return hcnt[(pixel >> 1) & 0x01FF];;
457         }
458         switch(addr & 1)
459         {
460         case 0: // CPU <-> VDP data buffer
461                 latch = false;
462                 temp = buffer;
463                 buffer = vram[vram_addr & 0x3FFF];
464                 vram_addr = (vram_addr + 1) & 0x3FFF;
465                 return temp;
466         case 1: // Status flags
467                 temp = status_reg;
468                 latch = false;
469                 status_reg = 0;
470                 set_intstat(false);
471                 return temp;
472         }
473         // Just to please the compiler
474         return -1;
475 }
476
477 void _315_5124::draw_screen()
478 {
479         if(emu->now_waiting_in_debugger) {
480                 // store regs
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;
486                 
487                 // drive vlines
488                 for(int v = /*get_cur_vline() + 1*/0; v < get_lines_per_frame(); v++) {
489                         event_vline(v, 0);
490                 }
491                 
492                 // restore regs
493                 z80_icount = tmp_z80_icount;
494                 vcounter = tmp_vcounter;
495                 status_reg = tmp_status_reg;
496                 hlatch = tmp_hlatch;
497                 intstat = tmp_intstat;
498         }
499         
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];
509                         } else {
510                                 dest[x] = palette_pc[0x10];
511                         }
512                 }
513         }
514 }
515
516 void _315_5124::event_vline(int v, int clock)
517 {
518         z80_icount++;
519         vcounter = v;
520         if (vdp_mode == 4) {
521                 if(v <= 0xC0) {
522                         if(v == 0xC0) {
523                                 status_reg |= 0x80;
524                         }
525                         if(v == 0) {
526                                 hlatch = regs[10];
527                         }
528                         if(hlatch == 0) {
529                                 hlatch = regs[10];
530                                 status_reg |= 0x40;
531                         } else {
532                                 hlatch -= 1;
533                         }
534                         if((status_reg & 0x40) && (regs[0] & 0x10)) {
535                                 status_reg |= 0x40;
536                                 set_intstat((regs[0] & 0x10) != 0);
537                         }
538                 } else {
539                         hlatch = regs[10];
540                         if((v < 0xE0) && (status_reg & 0x80) && (regs[1] & 0x20)) {
541                                 status_reg |= 0x80;
542                                 set_intstat((regs[1] & 0x20) != 0);
543                         }
544                 }
545                 
546                 /* Ensure we're within the viewport range */
547                 if(v < vp_y || v >= (vp_y + vp_h)) return;
548                 
549                 /* Point to current line in output buffer */
550                 linebuf = (uint8_t *)screen[v];
551                 
552                 /* Update pattern cache */
553                 update_bg_pattern_cache();
554                 
555                 /* Blank line (full width) */
556                 if (!(regs[1] & 0x40)) {
557                         memset(linebuf, BACKDROP_COLOR, 256);
558                 } else {
559                         /* Draw background */
560                         render_bg(v);
561                         /* Draw sprites */
562                         render_obj(v);
563                         /* Blank leftmost column of display */
564                         if (regs[0] & 0x20) {
565                                 memset(linebuf, BACKDROP_COLOR, 8);
566                         }
567                 }
568         } else {
569                 if (v == 192) {
570                         // create virtual screen
571                         if(regs[1] & 0x40) {
572                                 // draw character plane
573                                 int mode = (regs[0] & 2) | ((regs[1] & 0x10) >> 4) | ((regs[1] & 8) >> 1);
574                                 switch(mode)
575                                 {
576                                 case 0:
577                                         draw_mode0();
578                                         break;
579                                 case 1:
580                                         draw_mode1();
581                                         break;
582                                 case 2:
583                                         draw_mode2();
584                                         break;
585                                 case 3:
586                                         draw_mode12();
587                                         break;
588                                 case 4:
589                                         draw_mode3();
590                                         break;
591                                 case 6:
592                                         draw_mode23();
593                                         break;
594                                 case 5:
595                                 case 7:
596                                         draw_modebogus();
597                                         break;
598                                 }
599                                 // draw sprite plane
600                                 if((regs[1] & 0x50) == 0x40) {
601                                         draw_sprites();
602                                 }
603                         } else {
604                                 memset(screen, 0, sizeof(screen));
605                         }
606                         // do interrupt
607                         status_reg |= 0x80;
608                         set_intstat((regs[1] & 0x20) != 0);
609                 }
610         }
611 }
612
613 void _315_5124::set_intstat(bool val)
614 {
615         if(val != intstat) {
616                 if(!emu->now_waiting_in_debugger) {
617                         write_signals(&outputs_irq, val ? 0xffffffff : 0);
618                 }
619                 intstat = val;
620         }
621 }
622
623 void _315_5124::draw_mode0()
624 {
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;
643                         }
644                 }
645         }
646 }
647
648 void _315_5124::draw_mode1()
649 {
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;
665                         }
666                 }
667         }
668 }
669
670 void _315_5124::draw_mode2()
671 {
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;
691                         }
692                 }
693         }
694 }
695
696 void _315_5124::draw_mode12()
697 {
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;
713                         }
714                 }
715         }
716 }
717
718 void _315_5124::draw_mode3()
719 {
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;
732                                 }
733                         }
734                 }
735         }
736 }
737
738 void _315_5124::draw_mode23()
739 {
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;
752                                 }
753                         }
754                 }
755         }
756 }
757
758 void _315_5124::draw_modebogus()
759 {
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];
764                 int x = 0;
765                 for(int i = 0; i < 8; i++) {
766                         buffer[x++] = bg;
767                 }
768                 for(int i = 0; i < 40; i++) {
769                         for(int j = 0; j < 4; j++) {
770                                 buffer[x++] = fg;
771                         }
772                         for(int j = 0; j < 2; j++) {
773                                 buffer[x++] = bg;
774                         }
775                 }
776                 for(int i = 0; i < 8; i++) {
777                         buffer[x++] = bg;
778                 }
779         }
780 }
781
782 void _315_5124::draw_sprites()
783 {
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));
791         status_reg = 0x80;
792         
793         for(p = 0; p < 32; p++) {
794                 int y = *attrib_ptr++;
795                 if(y == 208) {
796                         break;
797                 }
798                 if(y > 208) {
799                         y = -(~y & 0xff);
800                 } else {
801                         y++;
802                 }
803                 int x = *attrib_ptr++;
804                 uint8_t* pattern_ptr = vram + sprite_pattern + ((size == 16) ? (*attrib_ptr & 0xfc) : *attrib_ptr) * 8;
805                 attrib_ptr++;
806                 uint8_t c = *attrib_ptr & 0x0f;
807                 if(*attrib_ptr & 0x80) {
808                         x -= 32;
809                 }
810                 attrib_ptr++;
811                 
812                 if(!large) {
813                         // draw sprite (not enlarged)
814                         for(int yy = y; yy < y + size; yy++) {
815                                 if(yy < 0 || 191 < yy) {
816                                         continue;
817                                 }
818                                 if(limit[yy] == 0) {
819                                         // illegal sprite line
820                                         if(yy < illegal_sprite_line) {
821                                                 illegal_sprite_line = yy;
822                                                 illegal_sprite = p;
823                                         } else if(illegal_sprite_line == yy) {
824                                                 if(illegal_sprite > p) {
825                                                         illegal_sprite = p;
826                                                 }
827                                         }
828 //#ifdef _315_5124_LIMIT_SPRITES
829                                         if(__315_5124_LIMIT_SPRITES) {
830                                                 continue;
831                                         }
832 //#endif
833                                 } else {
834                                         limit[yy]--;
835                                 }
836                                 uint16_t line = pattern_ptr[yy - y] * 256 + pattern_ptr[yy - y + 16];
837                                 for(int xx = x; xx < x + size; xx++) {
838                                         if(line & 0x8000) {
839                                                 if(0 <= xx && xx < 256) {
840                                                         if(collision[yy][xx]) {
841                                                                 status_reg |= 0x20;
842                                                         } else {
843                                                                 collision[yy][xx] = 1;
844                                                         }
845                                                         if(c && !(collision[yy][xx] & 2)) {
846                                                                 collision[yy][xx] |= 2;
847                                                                 screen[yy][xx] = c;
848                                                         }
849                                                 }
850                                         }
851                                         line *= 2;
852                                 }
853                         }
854                 } else {
855                         // draw enlarged sprite
856                         for(int i = 0; i < size; i++) {
857                                 int yy = y + i * 2;
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) {
861                                                 if(limit[yy] == 0) {
862                                                         // illegal sprite line
863                                                         if(yy < illegal_sprite_line) {
864                                                                 illegal_sprite_line = yy;
865                                                                  illegal_sprite = p;
866                                                         } else if(illegal_sprite_line == yy) {
867                                                                 if(illegal_sprite > p) {
868                                                                         illegal_sprite = p;
869                                                                 }
870                                                         }
871 //#ifdef _315_5124_LIMIT_SPRITES
872                                                         if(__315_5124_LIMIT_SPRITES) {
873                                                                 continue;
874                                                         }
875 //#endif
876                                                 } else {
877                                                         limit[yy]--;
878                                                 }
879                                                 uint16_t line = line2;
880                                                 for(int xx = x; xx < x + size * 2; xx += 2) {
881                                                         if(line & 0x8000) {
882                                                                 if(0 <= xx && xx < 256) {
883                                                                         if(collision[yy][xx]) {
884                                                                                 status_reg |= 0x20;
885                                                                         } else {
886                                                                                 collision[yy][xx] = 1;
887                                                                         }
888                                                                         if(c && !(collision[yy][xx] & 2)) {
889                                                                                 collision[yy][xx] |= 2;
890                                                                                 screen[yy][xx] = c;
891                                                                         }
892                                                                 }
893                                                                 if(0 <= xx + 1 && xx + 1 < 256) {
894                                                                         if(collision[yy][xx + 1]) {
895                                                                                 status_reg |= 0x20;
896                                                                         } else {
897                                                                                 collision[yy][xx + 1] = 1;
898                                                                         }
899                                                                         if(c && !(collision[yy][xx + 1] & 2)) {
900                                                                                 collision[yy][xx + 1] |= 2;
901                                                                                 screen[yy][xx + 1] = c;
902                                                                         }
903                                                                 }
904                                                         }
905                                                         line *= 2;
906                                                 }
907                                         }
908                                         yy++;
909                                 }
910                         }
911                 }
912         }
913         if(illegal_sprite_line == 255) {
914                 status_reg |= (p > 31) ? 31 : p;
915         } else {
916                 status_reg |= 0x40 + illegal_sprite;
917         }
918 }
919
920 /* Draw the background */
921 void _315_5124::render_bg(int line)
922 {
923         int locked = 0;
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]);
928         int column = 0;
929         uint16_t attr;
930         uint16_t *nt = (uint16_t *)&vram[name_table + ((v_line >> 3) << 6)];
931         int nt_scroll = (hscroll >> 3);
932         int shift = (hscroll & 7);
933         uint32_t atex_mask;
934         uint32_t *cache_ptr;
935         uint32_t *linebuf_ptr = (uint32_t *)&linebuf[0 - shift];
936         
937         /* Draw first column (clipped) */
938         if(shift) {
939                 int x;
940                 for(x = shift; x < 8; x++)
941                         linebuf[(0 - shift) + (x)] = 0;
942                 column++;
943         }
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)) {
948                         locked = 1;
949                         v_row = (line & 7) << 3;
950                         nt = (uint16_t *)&vram[((regs[2] << 10) & 0x3800) + ((line >> 3) << 6)];
951                 }
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));
962         }
963         /* Draw last column (clipped) */
964         if (shift) {
965                 int x, c, a;
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)];
971                         p[x] = ((c) | (a));
972                 }
973         }
974 }
975
976 /* Draw sprites */
977 void _315_5124::render_obj(int line)
978 {
979         int i;
980         uint8_t collision_buffer = 0;
981         /* Sprite count for current line (8 max.) */
982         int count = 0;
983         /* Sprite dimensions */
984         int width = 8;
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) {
990                 width *= 2;
991                 height *= 2;
992         }
993         /* Draw sprites in front-to-back order */
994         for (i = 0; i < 64; i++) {
995                 /* Sprite Y position */
996                 int yp = st[i];
997                 /* Found end of sprite list marker for non-extended modes? */
998                 if (yp == 208) goto end;
999                 /* Actual Y position is +1 */
1000                 yp++;
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 */
1007                         int start = 0;
1008                         int end = width;
1009                         /* Sprite X position */
1010                         int xp = st[0x80 + (i << 1)];
1011                         /* Pattern name */
1012                         int n = st[0x81 + (i << 1)];
1013                         /* Bump sprite count */
1014                         count++;
1015                         /* Too many sprites on this line ? */
1016                         if (count == 9) {
1017                                 status_reg |= 0x40;
1018                                 goto end;
1019                         }
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 */
1029                         if (xp < 0) {
1030                                 start = (0 - xp);
1031                         }
1032                         /* Clip sprites on right edge */
1033                         if ((xp + width) > 256) {
1034                                 end = (256 - xp);
1035                         }
1036                         /* Draw double size sprite */
1037                         if (regs[1] & 0x01) {
1038                                 int x;
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 */
1045                                         if (sp) {
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;
1052                                         }
1053                                 }
1054                         } else { /* Regular size sprite (8x8 / 8x16) */
1055                                 int x;
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 */
1062                                         if (sp) {
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;
1069                                         }
1070                                 }
1071                         }
1072                 }
1073         }
1074 end:
1075         /* Set sprite collision flag */
1076         if (collision_buffer & 0x40) status_reg |= 0x20;
1077 }
1078
1079 void _315_5124::update_bg_pattern_cache(void)
1080 {
1081         int i;
1082         uint8_t x, y;
1083         uint16_t name;
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);
1100                                 }
1101                         }
1102                 }
1103                 bg_name_dirty[name] = 0;
1104         }
1105         bg_list_index = 0;
1106 }
1107
1108 void _315_5124::palette_sync(int index, int force)
1109 {
1110         int r, g, b;
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];
1119         } else {
1120                 // unless we are forcing an update,
1121                 // if not in mode 4, exit
1122                 if (!force && (regs[0] & 4) == 0) return;
1123                 /* --BBGGRR */
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];
1130         }
1131         palette_pc[index] = RGB_COLOR(r, g, b);
1132 }