OSDN Git Service

[VM][DEVICE][WIP] Updating State functions.Still cause FTBFS.
[csp-qt/common_source_project-fm7.git] / source / src / vm / tms9918a.cpp
1 /*
2         Skelton for retropc emulator
3
4         Origin : MAME TMS9928A Core
5         Author : Takeda.Toshiya
6         Date   : 2006.08.18 -
7                  2007.07.21 -
8
9         [ TMS9918A ]
10 */
11
12 #include "tms9918a.h"
13
14 //#define ADDR_MASK (TMS9918A_VRAM_SIZE - 1)
15
16 static const scrntype_t palette_pc_noalpha[16] = {
17         RGB_COLOR(  0,   0,   0), 
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)
22 };
23
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)
29 };
30
31 void TMS9918A::initialize()
32 {
33         DEVICE::initialize();
34         // register event
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"));
40         
41         if(_VRAM_SIZE == 0) _VRAM_SIZE = 0x4000;
42         _ADDR_MASK = _VRAM_SIZE - 1; 
43         vram = (uint8_t *)malloc(_VRAM_SIZE * sizeof(uint8_t));
44         
45         if(_use_alpha_blending_to_impose) {
46                 palette_pc = palette_pc_alpha;
47         } else {
48                 palette_pc = palette_pc_noalpha;
49         }
50         
51         register_vline_event(this);
52 }
53
54 void TMS9918A::release()
55 {
56         if(vram != NULL) free(vram);
57 }
58 void TMS9918A::reset()
59 {
60         memset(vram, 0, _VRAM_SIZE * sizeof(uint8_t));
61         memset(regs, 0, sizeof(regs));
62         status_reg = read_ahead = first_byte = 0;
63         vram_addr = 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;
68 }
69
70 void TMS9918A::write_io8(uint32_t addr, uint32_t data)
71 {
72         if(addr & 1) {
73                 // register
74                 if(latch) {
75                         if(data & 0x80) {
76                                 switch(data & 7) {
77                                 case 0:
78                                         regs[0] = first_byte & 3;
79                                         if(regs[0] & 2) {
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);
84                                         } else {
85                                                 color_table = (regs[3] * 64) & _ADDR_MASK;
86                                                 pattern_table = (regs[4] * 2048) & _ADDR_MASK;
87                                         }
88                                         break;
89                                 case 1:
90                                         regs[1] = first_byte & 0xfb;
91                                         set_intstat((regs[1] & 0x20) && (status_reg & 0x80));
92                                         break;
93                                 case 2:
94                                         regs[2] = first_byte & 0x0f;
95                                         name_table = (regs[2] * 1024) & _ADDR_MASK;
96                                         break;
97                                 case 3:
98                                         regs[3] = first_byte;
99                                         if(regs[0] & 2) {
100                                                 color_table = ((regs[3] & 0x80) * 64) & _ADDR_MASK;
101                                                 color_mask = ((regs[3] & 0x7f) * 8) | 7;
102                                         } else {
103                                                 color_table = (regs[3] * 64) & _ADDR_MASK;
104                                         }
105                                         pattern_mask = ((regs[4] & 3) * 256) | (color_mask & 0xff);
106                                         break;
107                                 case 4:
108                                         regs[4] = first_byte & 7;
109                                         if(regs[0] & 2) {
110                                                 pattern_table = ((regs[4] & 4) * 2048) & _ADDR_MASK;
111                                                 pattern_mask = ((regs[4] & 3) * 256) | 255;
112                                         } else {
113                                                 pattern_table = (regs[4] * 2048) & _ADDR_MASK;
114                                         }
115                                         break;
116                                 case 5:
117                                         regs[5] = first_byte & 0x7f;
118                                         sprite_attrib = (regs[5] * 128) & _ADDR_MASK;
119                                         break;
120                                 case 6:
121                                         regs[6] = first_byte & 7;
122                                         sprite_pattern = (regs[6] * 2048) & _ADDR_MASK;
123                                         break;
124                                 case 7:
125                                         regs[7] = first_byte;
126                                         break;
127                                 }
128                         } else {
129                                 vram_addr = ((data * 256) | first_byte) & _ADDR_MASK;
130                                 if(!(data & 0x40)) {
131                                         read_io8(0);    // read ahead
132                                 }
133                         }
134                         latch = false;
135                 } else {
136                         first_byte = data;
137                         latch = true;
138                 }
139         } else {
140                 // vram
141                 vram[vram_addr] = data;
142                 vram_addr = (vram_addr + 1) & _ADDR_MASK;
143                 read_ahead = data;
144                 latch = false;
145         }
146 }
147
148 uint32_t TMS9918A::read_io8(uint32_t addr)
149 {
150         if(addr & 1) {
151                 // register
152                 uint8_t val = status_reg;
153                 status_reg = 0x1f;
154                 set_intstat(false);
155                 latch = false;
156                 return val;
157         } else {
158                 // vram
159                 uint8_t val = read_ahead;
160                 read_ahead = vram[vram_addr];
161                 vram_addr = (vram_addr + 1) & _ADDR_MASK;
162                 latch = false;
163                 return val;
164         }
165 }
166
167 //#ifdef TMS9918A_SUPER_IMPOSE
168 void TMS9918A::write_signal(int id, uint32_t data, uint32_t mask)
169 {
170         if(_tms9918a_super_impose) {
171                 if(id == SIG_TMS9918A_SUPER_IMPOSE) {
172                         now_super_impose = ((data & mask) != 0);
173                 }
174         }
175 }
176 //#endif
177
178 inline void TMS9918A::draw_screen_512_impose()
179 {
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;
189                                 if(c != 0) {
190                                         dest0[x2] = dest0[x2 + 1] = dest1[x2] = dest1[x2 + 1] = palette_pc[c];
191                                 }
192                         }
193                 } else {
194                         for(int x = 0, x2 = 0; x < 256; x++, x2 += 2) {
195                                 dest0[x2] = dest0[x2 + 1] = palette_pc[src[x] & 0x0f];
196                         }
197                         my_memcpy(dest1, dest0, 512 * sizeof(scrntype_t));
198                 }
199         }
200 //#endif
201 }
202
203 inline void TMS9918A::draw_screen_512_nonimpose()
204 {
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];
212                 }
213                 my_memcpy(dest1, dest0, 512 * sizeof(scrntype_t));
214         }
215 }
216
217 inline void TMS9918A::draw_screen_256_impose()
218 {
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;
227                                 if(c != 0) {
228                                         dest[x] = palette_pc[c];
229                                 }
230                         }
231                 } else {
232 //#endif
233                         for(int x = 0; x < 256; x++) {
234                                 dest[x] = palette_pc[src[x] & 0x0f];
235                         }
236                 }
237         }
238 }
239
240 inline void TMS9918A::draw_screen_256_nonimpose()
241 {
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];
248                 }
249         }                                       
250 }
251
252 //#endif
253
254 void TMS9918A::draw_screen()
255 {
256 //#ifdef TMS9918A_SUPER_IMPOSE
257         if(_tms9918a_super_impose) {
258                 if(now_super_impose) {
259                         osd->get_video_buffer();
260                 }
261         }
262 //#endif
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();
268                 } else {
269                         draw_screen_512_nonimpose();
270                 }
271         } else {
272                 if(_tms9918a_super_impose && !_use_alpha_blending_to_impose) {
273                         draw_screen_256_impose();
274                 } else {
275                         draw_screen_256_nonimpose();
276                 }
277         }
278 }
279
280 void TMS9918A::event_vline(int v, int clock)
281 {
282         if(v == 192) {
283                 // create virtual screen
284                 if(regs[1] & 0x40) {
285                         // draw character plane
286                         int mode = (regs[0] & 2) | ((regs[1] & 0x10) >> 4) | ((regs[1] & 8) >> 1);
287                         switch(mode) {
288                         case 0:
289                                 draw_mode0();
290                                 break;
291                         case 1:
292                                 draw_mode1();
293                                 break;
294                         case 2:
295                                 draw_mode2();
296                                 break;
297                         case 3:
298                                 draw_mode12();
299                                 break;
300                         case 4:
301                                 draw_mode3();
302                                 break;
303                         case 6:
304                                 draw_mode23();
305                                 break;
306                         case 5:
307                         case 7:
308                                 draw_modebogus();
309                                 break;
310                         }
311                         // draw sprite plane
312                         if((regs[1] & 0x50) == 0x40) {
313                                 draw_sprites();
314                         }
315                 } else {
316                         memset(screen, 0, sizeof(screen));
317                 }
318                 
319                 // do interrupt
320                 status_reg |= 0x80;
321                 set_intstat((regs[1] & 0x20) != 0);
322         }
323 }
324
325 void TMS9918A::set_intstat(bool val)
326 {
327         if(val != intstat) {
328                 write_signals(&outputs_irq, val ? 0xffffffff : 0);
329                 intstat = val;
330         }
331 }
332
333 void TMS9918A::draw_mode0()
334 {
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;
353                         }
354                 }
355         }
356 }
357
358 void TMS9918A::draw_mode1()
359 {
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;
376                         }
377                 }
378         }
379 }
380
381 void TMS9918A::draw_mode2()
382 {
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;
402                         }
403                 }
404         }
405 }
406
407 void TMS9918A::draw_mode12()
408 {
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;
425                         }
426                 }
427         }
428 }
429
430 void TMS9918A::draw_mode3()
431 {
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;
444                                 }
445                         }
446                 }
447         }
448 }
449
450 void TMS9918A::draw_mode23()
451 {
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;
464                                 }
465                         }
466                 }
467         }
468 }
469
470 void TMS9918A::draw_modebogus()
471 {
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];
476                 int x = 0;
477                 for(int i = 0; i < 8; i++) {
478                         buffer[x++] = bg;
479                 }
480                 for(int i = 0; i < 40; i++) {
481                         for(int j = 0; j < 4; j++) {
482                                 buffer[x++] = fg;
483                         }
484                         for(int j = 0; j < 2; j++) {
485                                 buffer[x++] = bg;
486                         }
487                 }
488                 for(int i = 0; i < 8; i++) {
489                         buffer[x++] = bg;
490                 }
491         }
492 }
493
494 void TMS9918A::draw_sprites()
495 {
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));
503         status_reg = 0x80;
504         
505         for(p = 0; p < 32; p++) {
506                 int y = *attrib_ptr++;
507                 if(y == 208) {
508                         break;
509                 }
510                 if(y > 208) {
511                         y = -(~y & 0xff);
512                 } else {
513                         y++;
514                 }
515                 int x = *attrib_ptr++;
516                 uint8_t* pattern_ptr = vram + sprite_pattern + ((size == 16) ? (*attrib_ptr & 0xfc) : *attrib_ptr) * 8;
517                 attrib_ptr++;
518                 uint8_t c = *attrib_ptr & 0x0f;
519                 if(*attrib_ptr & 0x80) {
520                         x -= 32;
521                 }
522                 attrib_ptr++;
523                 
524                 if(!large) {
525                         // draw sprite (not enlarged)
526                         for(int yy = y; yy < y + size; yy++) {
527                                 if(yy < 0 || 191 < yy) {
528                                         continue;
529                                 }
530                                 if(limit[yy] == 0) {
531                                         // illegal sprite line
532                                         if(yy < illegal_sprite_line) {
533                                                 illegal_sprite_line = yy;
534                                                 illegal_sprite = p;
535                                         } else if(illegal_sprite_line == yy) {
536                                                 if(illegal_sprite > p) {
537                                                         illegal_sprite = p;
538                                                 }
539                                         }
540 //#ifdef TMS9918A_LIMIT_SPRITES
541                                         if(_tms9918a_limit_sprites) continue;
542 //#endif
543                                 } else {
544                                         limit[yy]--;
545                                 }
546                                 uint16_t line = pattern_ptr[yy - y] * 256 + pattern_ptr[yy - y + 16];
547                                 for(int xx = x; xx < x + size; xx++) {
548                                         if(line & 0x8000) {
549                                                 if(0 <= xx && xx < 256) {
550                                                         if(collision[yy][xx]) {
551                                                                 status_reg |= 0x20;
552                                                         } else {
553                                                                 collision[yy][xx] = 1;
554                                                         }
555                                                         if(c && !(collision[yy][xx] & 2)) {
556                                                                 collision[yy][xx] |= 2;
557                                                                 screen[yy][xx] = c;
558                                                         }
559                                                 }
560                                         }
561                                         line *= 2;
562                                 }
563                         }
564                 } else {
565                         // draw enlarged sprite
566                         for(int i = 0; i < size; i++) {
567                                 int yy = y + i * 2;
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) {
571                                                 if(limit[yy] == 0) {
572                                                         // illegal sprite line
573                                                         if(yy < illegal_sprite_line) {
574                                                                 illegal_sprite_line = yy;
575                                                                  illegal_sprite = p;
576                                                         } else if(illegal_sprite_line == yy) {
577                                                                 if(illegal_sprite > p) {
578                                                                         illegal_sprite = p;
579                                                                 }
580                                                         }
581 //#ifdef TMS9918A_LIMIT_SPRITES
582                                                         if(_tms9918a_limit_sprites) continue;
583 //#endif
584                                                 } else {
585                                                         limit[yy]--;
586                                                 }
587                                                 uint16_t line = line2;
588                                                 for(int xx = x; xx < x + size * 2; xx += 2) {
589                                                         if(line & 0x8000) {
590                                                                 if(0 <= xx && xx < 256) {
591                                                                         if(collision[yy][xx]) {
592                                                                                 status_reg |= 0x20;
593                                                                         } else {
594                                                                                 collision[yy][xx] = 1;
595                                                                         }
596                                                                         if(c && !(collision[yy][xx] & 2)) {
597                                                                                 collision[yy][xx] |= 2;
598                                                                                 screen[yy][xx] = c;
599                                                                         }
600                                                                 }
601                                                                 if(0 <= xx + 1 && xx + 1 < 256) {
602                                                                         if(collision[yy][xx + 1]) {
603                                                                                 status_reg |= 0x20;
604                                                                         } else {
605                                                                                 collision[yy][xx + 1] = 1;
606                                                                         }
607                                                                         if(c && !(collision[yy][xx + 1] & 2)) {
608                                                                                 collision[yy][xx + 1] |= 2;
609                                                                                 screen[yy][xx + 1] = c;
610                                                                         }
611                                                                 }
612                                                         }
613                                                         line *= 2;
614                                                 }
615                                         }
616                                         yy++;
617                                 }
618                         }
619                 }
620         }
621         if(illegal_sprite_line == 255) {
622                 status_reg |= (p > 31) ? 31 : p;
623         } else {
624                 status_reg |= 0x40 + illegal_sprite;
625         }
626 }
627
628 //#ifdef USE_DEBUGGER
629 void TMS9918A::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len)
630 {
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);
635 }
636 //#endif
637
638 #define STATE_VERSION   1
639
640 bool TMS9918A::process_state(FILEIO* state_fio, bool loading)
641 {
642         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
643                 return false;
644         }
645         if(!state_fio->StateCheckInt32(this_device_id)) {
646                 return false;
647         }
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);
665         }
666         return true;
667 }
668