OSDN Git Service

[VM][Qt][OSD][Genaral] Sync to upstream ; phase 1: Merege upstream 20151217.
[csp-qt/common_source_project-fm7.git] / source / src / vm / pcengine / pce.cpp
1 /*
2         NEC-HE PC Engine Emulator 'ePCEngine'
3         SHARP X1twin Emulator 'eX1twin'
4
5         Origin : Ootake (joypad)
6                : xpce (psg)
7                : MESS (vdc/vce/vpc)
8         Author : Takeda.Toshiya
9         Date   : 2009.03.11-
10
11         [ PC-Eninge ]
12 */
13
14 #include <math.h>
15 #include "pce.h"
16 #include "../huc6280.h"
17
18 #define STATE_VSW               0
19 #define STATE_VDS               1
20 #define STATE_VDW               2
21 #define STATE_VCR               3
22
23 /* Bits in the VDC status register */
24
25 #define VDC_BSY         0x40    /* Set when the VDC accesses VRAM */
26 #define VDC_VD          0x20    /* Set when in the vertical blanking period */
27 #define VDC_DV          0x10    /* Set when a VRAM > VRAM DMA transfer is done */
28 #define VDC_DS          0x08    /* Set when a VRAM > SATB DMA transfer is done */
29 #define VDC_RR          0x04    /* Set when the current scanline equals the RCR register */
30 #define VDC_OR          0x02    /* Set when there are more than 16 sprites on a line */
31 #define VDC_CR          0x01    /* Set when sprite #0 overlaps with another sprite */
32
33 /* Bits in the CR register */
34
35 #define CR_BB           0x80    /* Background blanking */
36 #define CR_SB           0x40    /* Object blanking */
37 #define CR_VR           0x08    /* Interrupt on vertical blank enable */
38 #define CR_RC           0x04    /* Interrupt on line compare enable */
39 #define CR_OV           0x02    /* Interrupt on sprite overflow enable */
40 #define CR_CC           0x01    /* Interrupt on sprite #0 collision enable */
41
42 /* Bits in the DCR regsiter */
43
44 #define DCR_DSR         0x10    /* VRAM > SATB auto-transfer enable */
45 #define DCR_DID         0x08    /* Destination diretion */
46 #define DCR_SID         0x04    /* Source direction */
47 #define DCR_DVC         0x02    /* VRAM > VRAM EOT interrupt enable */
48 #define DCR_DSC         0x01    /* VRAM > SATB EOT interrupt enable */
49
50 /* just to keep things simple... */
51 enum vdc_regs {MAWR = 0, MARR, VxR, reg3, reg4, CR, RCR, BXR, BYR, MWR, HSR, HDR, VPR, VDW, VCR, DCR, SOUR, DESR, LENR, DVSSR };
52
53 enum line_state
54 {
55         CLEAR_LINE = 0,                         // clear (a fired or held) line
56         ASSERT_LINE,                            // assert an interrupt immediately
57         HOLD_LINE,                              // hold interrupt line until acknowledged
58         PULSE_LINE                              // pulse interrupt line instantaneously (only for NMI, RESET)
59 };
60
61 enum
62 {
63         INPUT_LINE_IRQ1 = 0,
64         INPUT_LINE_IRQ2 = 1,
65         INPUT_LINE_TIRQ = 2,
66         INPUT_LINE_NMI
67 };
68
69 void PCE::initialize()
70 {
71         // get context
72         joy_stat = emu->joy_buffer();
73         key_stat = emu->key_buffer();
74         
75         // register event
76         register_vline_event(this);
77         
78 #ifdef SUPPORT_BACKUP_RAM
79         static const uint8 image[8] = {0x48, 0x55, 0x42, 0x4d, 0x00, 0x88, 0x10, 0x80};
80         memset(backup, 0, sizeof(backup));
81         memcpy(backup, image, sizeof(image));
82         
83         FILEIO* fio = new FILEIO();
84         if(fio->Fopen(create_local_path(_T("BACKUP.BIN")), FILEIO_READ_BINARY)) {
85                 fio->Fread(backup, sizeof(backup), 1);
86                 fio->Fclose();
87         }
88         delete fio;
89         
90         backup_crc32 = getcrc32(backup, sizeof(backup));
91 #endif
92         inserted = false;
93 }
94
95 void PCE::release()
96 {
97 #ifdef SUPPORT_BACKUP_RAM
98         if(backup_crc32 != getcrc32(backup, sizeof(backup))) {
99                 FILEIO* fio = new FILEIO();
100                 if(fio->Fopen(create_local_path(_T("BACKUP.BIN")), FILEIO_WRITE_BINARY)) {
101                         fio->Fwrite(backup, sizeof(backup), 1);
102                         fio->Fclose();
103                 }
104                 delete fio;
105         }
106 #endif
107 }
108
109 void PCE::reset()
110 {
111         // reset memory bus
112         memset(ram, 0, sizeof(ram));
113         bank = 0x80000;
114         buffer = 0xff;  // ???
115         
116         // reset devices
117         vdc_reset();
118         psg_reset();
119         joy_reset();
120         
121         prev_width = -1;
122 }
123
124 void PCE::event_vline(int v, int clock)
125 {
126 #ifdef SUPPORT_SUPER_GFX
127         if(support_sgfx) {
128                 sgx_interrupt();
129         } else
130 #endif
131         pce_interrupt();
132 }
133
134 void PCE::write_data8(uint32 addr, uint32 data)
135 {
136         uint8 mpr = (addr >> 13) & 0xff;
137         uint16 ofs = addr & 0x1fff;
138         
139         switch(mpr) {
140         case 0x40:
141         case 0x41:
142         case 0x42:
143         case 0x43:
144                 // populous
145                 cart[addr & 0xfffff] = data;
146                 return;
147 #ifdef SUPPORT_BACKUP_RAM
148         case 0xf7:
149 //              if(inserted) {
150                         backup[ofs] = data;
151 //              }
152                 return;
153 #endif
154         case 0xf8:
155                 ram[ofs] = data;
156                 return;
157 #ifdef SUPPORT_SUPER_GFX
158         case 0xf9:
159         case 0xfa:
160         case 0xfb:
161                 if(support_sgfx) {
162                         ram[addr & 0x7fff] = data;
163                 }
164                 return;
165 #endif
166         case 0xff:
167                 switch(addr & 0x1c00) {
168                 case 0x0000:    // vdc
169 #ifdef SUPPORT_SUPER_GFX
170                         if(support_sgfx) {
171                                 switch(addr & 0x18) {
172                                 case 0x00:
173                                         vdc_w(0, addr, data);
174                                         break;
175                                 case 0x08:
176                                         vpc_w(addr, data);
177                                         break;
178                                 case 0x10:
179                                         vdc_w(1, addr, data);
180                                         break;
181                                 }
182                         } else
183 #endif
184                         vdc_w(0, addr, data);
185                         break;
186                 case 0x0400:    // vce
187                         vce_w(addr, data);
188                         break;
189                 case 0x0800:    // psg
190                         buffer = data;
191                         psg_write(addr, data);
192                         break;
193                 case 0x0c00:    // timer
194                         buffer = data;
195                         d_cpu->timer_w(addr, data);
196                         break;
197                 case 0x1000:    // joypad
198                         buffer = data;
199                         joy_write(addr, data);
200                         break;
201                 case 0x1400:    // interrupt control
202                         buffer = data;
203                         d_cpu->irq_status_w(addr, data);
204                         break;
205                 }
206                 return;
207         }
208         // bank switch for sf2d
209         if((addr & 0x1ffc) == 0x1ff0) {
210                 bank = 0x80000 * ((addr & 3) + 1);
211         }
212 }
213
214 uint32 PCE::read_data8(uint32 addr)
215 {
216         uint8 mpr = (addr >> 13) & 0xff;
217         uint16 ofs = addr & 0x1fff;
218         
219         if(mpr <= 0x3f) {
220                 return cart[addr & 0x7ffff];
221         }
222         if(mpr <= 0x7f) {
223                 return cart[bank | (addr & 0x7ffff)];
224         }
225         switch(mpr) {
226 #ifdef SUPPORT_BACKUP_RAM
227         case 0xf7:
228                 return backup[ofs];
229 #endif
230         case 0xf8:
231                 return ram[ofs];
232 #ifdef SUPPORT_SUPER_GFX
233         case 0xf9:
234         case 0xfa:
235         case 0xfb:
236                 if(support_sgfx) {
237                         return ram[addr & 0x7fff];
238                 }
239                 return 0xff;
240 #endif
241         case 0xff:
242                 switch (addr & 0x1c00) {
243                 case 0x0000: // vdc
244 #ifdef SUPPORT_SUPER_GFX
245                         if(support_sgfx) {
246                                 switch(addr & 0x18) {
247                                 case 0x00:
248                                         return vdc_r(0, addr);
249                                 case 0x08:
250                                         return vpc_r(addr);
251                                 case 0x10:
252                                         return vdc_r(1, addr);
253                                 }
254                                 return 0xff;
255                         } else
256 #endif
257                         return vdc_r(0, addr);
258                 case 0x0400: // vce
259                         return vce_r(addr);
260                 case 0x0800: // psg
261 //                      return psg_read(addr);
262                         return buffer;
263                 case 0x0c00: // timer
264                         buffer = (buffer & 0x80) | (d_cpu->timer_r(addr) & 0x7f);
265                         return buffer;
266                 case 0x1000: // joypad
267                         buffer = (buffer & 0xb0) | (joy_read(addr) & 0x0f);
268                         return buffer;
269                 case 0x1400: // interrupt control
270                         if(addr & 2) {
271                                 buffer = (buffer & 0xf8) | (d_cpu->irq_status_r(addr) & 0x07);
272                         }
273                         return buffer;
274                 }
275                 break;
276         }
277         return 0xff;
278 }
279
280 void PCE::write_io8(uint32 addr, uint32 data)
281 {
282 #ifdef SUPPORT_SUPER_GFX
283         if(support_sgfx) {
284                 sgx_vdc_w(addr, data);
285         } else
286 #endif
287         vdc_w(0, addr, data);
288 }
289
290 uint32 PCE::read_io8(uint32 addr)
291 {
292 #ifdef SUPPORT_SUPER_GFX
293         if(support_sgfx) {
294                 return sgx_vdc_r(addr);
295         } else
296 #endif
297         return vdc_r(0, addr);
298 }
299
300 void PCE::draw_screen()
301 {
302         int dx = (SCREEN_WIDTH - vdc[0].physical_width) / 2, sx = 0;
303         int dy = (SCREEN_HEIGHT - 238) / 2;
304         
305         if(dx < 0) {
306                 sx = -dx;
307                 dx = 0;
308         }
309 #ifndef _X1TWIN
310         if(prev_width != vdc[0].physical_width) {
311                 for(int y = 0; y < SCREEN_HEIGHT; y++) {
312                         memset(emu->screen_buffer(y), 0, sizeof(scrntype) * SCREEN_WIDTH);
313                 }
314                 prev_width = vdc[0].physical_width;
315         }
316 #endif
317         for(int y = 0; y < 238; y++, dy++) {
318                 scrntype* src = &vce.bmp[y + 17][86];
319                 scrntype* dst = emu->screen_buffer(dy);
320                 for(int x = sx, x2 = dx; x < vdc[0].physical_width && x2 < SCREEN_WIDTH; x++, x2++) {
321                         dst[x2] = src[x];
322                 }
323         }
324 }
325
326 void PCE::open_cart(const _TCHAR* file_path)
327 {
328         FILEIO* fio = new FILEIO();
329         
330         if(fio->Fopen(file_path, FILEIO_READ_BINARY)) {
331                 memset(cart, 0xff, sizeof(cart));
332                 fio->Fseek(0, FILEIO_SEEK_END);
333                 int size = fio->Ftell();
334                 int head = size % 1024;
335                 size -= head;
336                 fio->Fseek(head, FILEIO_SEEK_SET);
337                 fio->Fread(cart, size, 1);
338                 fio->Fclose();
339                 
340                 if(size == 512 * 1024) {
341                         bool overdump = true;
342                         for(int i = 0x40000; i < 0x60000; i++) {
343                                 if(cart[i] != cart[i + 0x20000]) {
344                                         overdump = false;
345                                         break;
346                                 }
347                         }
348                         if(overdump) {
349                                 size = 384 * 1024;
350                         }
351                 }
352                 if(size == 384 * 1024) {
353                         memcpy(cart + 0x060000, cart + 0x040000, 0x020000);     /* Set up 060000 - 07FFFF mirror */
354                         memcpy(cart + 0x080000, cart + 0x040000, 0x040000);     /* Set up 080000 - 0BFFFF region */
355                         memcpy(cart + 0x0C0000, cart + 0x040000, 0x040000);     /* Set up 0C0000 - 0FFFFF region */
356                         memcpy(cart + 0x040000, cart, 0x040000);                /* Set up 040000 - 07FFFF region */
357                 }
358                 else {
359                         /* mirror 256KB rom data */
360                         if (size <= 0x040000)
361                                 memcpy(cart + 0x040000, cart, 0x040000);
362                         /* mirror 512KB rom data */
363                         if (size <= 0x080000)
364                                 memcpy(cart + 0x080000, cart, 0x080000);
365                 }
366                 uint32 cart_crc32 = getcrc32(cart,size);
367                 support_sgfx = (size == 0x100000 && cart_crc32 == 0x8c4588e2)   // 1941 Counter Attack
368                             || (size == 0x100000 && cart_crc32 == 0x4c2126b0)   // Aldynes
369                             || (size == 0x080000 && cart_crc32 == 0x3b13af61)   // Battle Ace
370                             || (size == 0x100000 && cart_crc32 == 0xb486a8ed)   // Daimakaimura
371                             || (size == 0x0c0000 && cart_crc32 == 0xbebfe042)   // Darius Plus
372                             || (size == 0x100000 && cart_crc32 == 0x1e1d0319)   // Darius Plus (1024K)
373                             || (size == 0x080000 && cart_crc32 == 0x1f041166);  // Grandzort
374                 support_6btn = (size == 0x280000 && cart_crc32 == 0xd15cb6bb);  // Street Fighter II
375                 inserted = true;
376         }
377         delete fio;
378 }
379
380 void PCE::close_cart()
381 {
382         memset(cart, 0xff, sizeof(cart));
383         inserted = false;
384 }
385
386 // vdc
387
388 void PCE::pce_interrupt()
389 {
390         /* Draw the last scanline */
391         if ( vce.current_bitmap_line >= 14 && vce.current_bitmap_line < 14 + 242 )
392         {
393                 /* We are in the active display area */
394                 /* First fill the line with the overscan color */
395                 draw_overscan_line(vce.current_bitmap_line );
396
397                 /* Check if we need to draw more just the overscan color */
398                 if ( vdc[0].current_segment == STATE_VDW )
399                 {
400                         /* 0 - no sprite and background pixels drawn
401                            1 - background pixel drawn
402                            otherwise is 2 + sprite# */
403                         uint8 drawn[VDC_WPF];
404                         /* our line buffer */
405                         scrntype *line_buffer = &vce.bmp[vce.current_bitmap_line][86];
406
407                         /* clear our priority/sprite collision detection buffer. */
408                         memset(drawn, 0, VDC_WPF);
409
410                         vdc[0].y_scroll = ( vdc[0].current_segment_line == 0 ) ? vdc[0].vdc_data[BYR].w.l : ( vdc[0].y_scroll + 1 );
411
412                         /* Draw VDC #0 background layer */
413                         pce_refresh_line(0, vdc[0].current_segment_line, 0, drawn, line_buffer);
414
415                         /* Draw VDC #0 sprite layer */
416                         if(vdc[0].vdc_data[CR].w.l & CR_SB)
417                         {
418                                 pce_refresh_sprites(0, vdc[0].current_segment_line, drawn, line_buffer);
419                         }
420                 }
421         }
422         else
423         {
424                 /* We are in one of the blanking areas */
425                 draw_black_line(vce.current_bitmap_line );
426         }
427
428         /* bump current scanline */
429         vce.current_bitmap_line = ( vce.current_bitmap_line + 1 ) % VDC_LPF;
430         vdc_advance_line(0);
431 }
432
433 void PCE::sgx_interrupt()
434 {
435         /* Draw the last scanline */
436         if ( vce.current_bitmap_line >= 14 && vce.current_bitmap_line < 14 + 242 )
437         {
438                 /* We are in the active display area */
439                 /* First fill the line with the overscan color */
440                 draw_sgx_overscan_line(vce.current_bitmap_line );
441
442                 /* Check if we need to draw more just the overscan color */
443                 if ( vdc[0].current_segment == STATE_VDW )
444                 {
445                         /* 0 - no sprite and background pixels drawn
446                            1 - background pixel drawn
447                            otherwise is 2 + sprite# */
448                         uint8 drawn[2][512];
449                         scrntype *line_buffer;
450                         scrntype temp_buffer[2][512];
451                         int i;
452
453                         /* clear our priority/sprite collision detection buffer. */
454                         memset( drawn, 0, sizeof(drawn) );
455
456                         vdc[0].y_scroll = ( vdc[0].current_segment_line == 0 ) ? vdc[0].vdc_data[BYR].w.l : ( vdc[0].y_scroll + 1 );
457                         vdc[1].y_scroll = ( vdc[1].current_segment_line == 0 ) ? vdc[1].vdc_data[BYR].w.l : ( vdc[1].y_scroll + 1 );
458
459                         /* Draw VDC #0 background layer */
460                         pce_refresh_line( 0, vdc[0].current_segment_line, 0, drawn[0], temp_buffer[0]);
461
462                         /* Draw VDC #0 sprite layer */
463                         if(vdc[0].vdc_data[CR].w.l & CR_SB)
464                         {
465                                 pce_refresh_sprites(0, vdc[0].current_segment_line, drawn[0], temp_buffer[0]);
466                         }
467
468                         /* Draw VDC #1 background layer */
469                         pce_refresh_line( 1, vdc[1].current_segment_line, 1, drawn[1], temp_buffer[1]);
470
471                         /* Draw VDC #1 sprite layer */
472                         if ( vdc[1].vdc_data[CR].w.l & CR_SB )
473                         {
474                                 pce_refresh_sprites(1, vdc[1].current_segment_line, drawn[1], temp_buffer[1]);
475                         }
476
477                         line_buffer = &vce.bmp[vce.current_bitmap_line][86];
478                         /* Combine the output of both VDCs */
479                         for( i = 0; i < 512; i++ )
480                         {
481                                 int cur_prio = vpc.prio_map[i];
482
483                                 if ( vpc.vpc_prio[cur_prio].vdc0_enabled )
484                                 {
485                                         if ( vpc.vpc_prio[cur_prio].vdc1_enabled )
486                                         {
487                                                 switch( vpc.vpc_prio[cur_prio].prio )
488                                                 {
489                                                 case 0: /* BG1 SP1 BG0 SP0 */
490                                                         if ( drawn[0][i] )
491                                                         {
492                                                                 line_buffer[i] = temp_buffer[0][i];
493                                                         }
494                                                         else if ( drawn[1][i] )
495                                                         {
496                                                                 line_buffer[i] = temp_buffer[1][i];
497                                                         }
498                                                         break;
499                                                 case 1: /* BG1 BG0 SP1 SP0 */
500                                                         if ( drawn[0][i] )
501                                                         {
502                                                                 if ( drawn[0][i] > 1 )
503                                                                 {
504                                                                         line_buffer[i] = temp_buffer[0][i];
505                                                                 }
506                                                                 else
507                                                                 {
508                                                                         if ( drawn[1][i] > 1 )
509                                                                         {
510                                                                                 line_buffer[i] = temp_buffer[1][i];
511                                                                         }
512                                                                         else
513                                                                         {
514                                                                                 line_buffer[i] = temp_buffer[0][i];
515                                                                         }
516                                                                 }
517                                                         }
518                                                         else if ( drawn[1][i] )
519                                                         {
520                                                                 line_buffer[i] = temp_buffer[1][i];
521                                                         }
522                                                         break;
523                                                 case 2: /* BG1 + SP1 => SP1
524                                                            BG0 + SP1 => BG0
525                                                            BG0 + BG1 => BG0
526                                                            BG0 + SP0 => SP0
527                                                            BG1 + SP0 => BG1
528                                                            SP0 + SP1 => SP0 */
529                                                         if ( drawn[0][i] )
530                                                         {
531                                                                 if ( drawn[0][i] > 1 )
532                                                                 {
533                                                                         if ( drawn[1][i] == 1 )
534                                                                         {
535                                                                                 line_buffer[i] = temp_buffer[1][i];
536                                                                         }
537                                                                         else
538                                                                         {
539                                                                                 line_buffer[i] = temp_buffer[0][i];
540                                                                         }
541                                                                 }
542                                                                 else
543                                                                 {
544                                                                         line_buffer[i] = temp_buffer[0][i];
545                                                                 }
546                                                         }
547                                                         else if ( drawn[1][i] )
548                                                         {
549                                                                 line_buffer[i] = temp_buffer[1][i];
550                                                         }
551                                                         break;
552                                                 }
553                                         }
554                                         else
555                                         {
556                                                 if ( drawn[0][i] )
557                                                 {
558                                                         line_buffer[i] = temp_buffer[0][i];
559                                                 }
560                                         }
561                                 }
562                                 else
563                                 {
564                                         if ( vpc.vpc_prio[cur_prio].vdc1_enabled )
565                                         {
566                                                 if ( drawn[1][i] )
567                                                 {
568                                                         line_buffer[i] = temp_buffer[1][i];
569                                                 }
570                                         }
571                                 }
572                         }
573                 }
574         }
575         else
576         {
577                 /* We are in one of the blanking areas */
578                 draw_black_line(vce.current_bitmap_line );
579         }
580
581         /* bump current scanline */
582         vce.current_bitmap_line = ( vce.current_bitmap_line + 1 ) % VDC_LPF;
583         vdc_advance_line(0);
584         vdc_advance_line(1);
585 }
586
587 void PCE::vdc_advance_line(int which)
588 {
589         int ret = 0;
590
591         vdc[which].curline += 1;
592         vdc[which].current_segment_line += 1;
593         vdc[which].raster_count += 1;
594
595         if ( vdc[which].satb_countdown )
596         {
597                 vdc[which].satb_countdown -= 1;
598                 if ( vdc[which].satb_countdown == 0 )
599                 {
600                         if ( vdc[which].vdc_data[DCR].w.l & DCR_DSC )
601                         {
602                                 vdc[which].status |= VDC_DS;    /* set satb done flag */
603                                 ret = 1;
604                         }
605                 }
606         }
607
608         if ( vce.current_bitmap_line == 0 )
609         {
610                 vdc[which].current_segment = STATE_VSW;
611                 vdc[which].current_segment_line = 0;
612                 vdc[which].vblank_triggered = 0;
613                 vdc[which].curline = 0;
614         }
615
616         if ( STATE_VSW == vdc[which].current_segment && vdc[which].current_segment_line >= ( vdc[which].vdc_data[VPR].b.l & 0x1F ) )
617         {
618                 vdc[which].current_segment = STATE_VDS;
619                 vdc[which].current_segment_line = 0;
620         }
621
622         if ( STATE_VDS == vdc[which].current_segment && vdc[which].current_segment_line >= vdc[which].vdc_data[VPR].b.h )
623         {
624                 vdc[which].current_segment = STATE_VDW;
625                 vdc[which].current_segment_line = 0;
626                 vdc[which].raster_count = 0x40;
627         }
628
629         if ( STATE_VDW == vdc[which].current_segment && vdc[which].current_segment_line > ( vdc[which].vdc_data[VDW].w.l & 0x01FF ) )
630         {
631                 vdc[which].current_segment = STATE_VCR;
632                 vdc[which].current_segment_line = 0;
633
634                 /* Generate VBlank interrupt, sprite DMA */
635                 vdc[which].vblank_triggered = 1;
636                 if ( vdc[which].vdc_data[CR].w.l & CR_VR )
637                 {
638                         vdc[which].status |= VDC_VD;
639                         ret = 1;
640                 }
641
642                 /* do VRAM > SATB DMA if the enable bit is set or the DVSSR reg. was written to */
643                 if( ( vdc[which].vdc_data[DCR].w.l & DCR_DSR ) || vdc[which].dvssr_write )
644                 {
645                         int i;
646
647                         vdc[which].dvssr_write = 0;
648
649                         for( i = 0; i < 256; i++ )
650                         {
651                                 vdc[which].sprite_ram[i] = ( vdc[which].vram[ ( vdc[which].vdc_data[DVSSR].w.l << 1 ) + i * 2 + 1 ] << 8 ) | vdc[which].vram[ ( vdc[which].vdc_data[DVSSR].w.l << 1 ) + i * 2 ];
652                         }
653
654                         /* generate interrupt if needed */
655                         if ( vdc[which].vdc_data[DCR].w.l & DCR_DSC )
656                         {
657                                 vdc[which].satb_countdown = 4;
658                         }
659                 }
660         }
661
662         if ( STATE_VCR == vdc[which].current_segment )
663         {
664                 if ( vdc[which].current_segment_line >= 3 && vdc[which].current_segment_line >= vdc[which].vdc_data[VCR].b.l )
665                 {
666                         vdc[which].current_segment = STATE_VSW;
667                         vdc[which].current_segment_line = 0;
668                         vdc[which].curline = 0;
669                 }
670         }
671
672         /* generate interrupt on line compare if necessary */
673         if ( vdc[which].raster_count == vdc[which].vdc_data[RCR].w.l && vdc[which].vdc_data[CR].w.l & CR_RC )
674         {
675                 vdc[which].status |= VDC_RR;
676                 ret = 1;
677         }
678
679         /* handle frame events */
680         if(vdc[which].curline == 261 && ! vdc[which].vblank_triggered )
681         {
682
683                 vdc[which].vblank_triggered = 1;
684                 if(vdc[which].vdc_data[CR].w.l & CR_VR)
685                 {       /* generate IRQ1 if enabled */
686                         vdc[which].status |= VDC_VD;    /* set vblank flag */
687                         ret = 1;
688                 }
689
690                 /* do VRAM > SATB DMA if the enable bit is set or the DVSSR reg. was written to */
691                 if ( ( vdc[which].vdc_data[DCR].w.l & DCR_DSR ) || vdc[which].dvssr_write )
692                 {
693                         int i;
694
695                         vdc[which].dvssr_write = 0;
696                         for( i = 0; i < 256; i++ )
697                         {
698                                 vdc[which].sprite_ram[i] = ( vdc[which].vram[ ( vdc[which].vdc_data[DVSSR].w.l << 1 ) + i * 2 + 1 ] << 8 ) | vdc[which].vram[ ( vdc[which].vdc_data[DVSSR].w.l << 1 ) + i * 2 ];
699                         }
700
701                         /* generate interrupt if needed */
702                         if(vdc[which].vdc_data[DCR].w.l & DCR_DSC)
703                         {
704                                 vdc[which].satb_countdown = 4;
705                         }
706                 }
707         }
708
709         if (ret)
710                 d_cpu->write_signal(INPUT_LINE_IRQ1, HOLD_LINE, 0);
711 }
712
713 void PCE::vdc_reset()
714 {
715         /* clear context */
716         memset(&vdc, 0, sizeof(vdc));
717         memset(&vce, 0, sizeof(vce));
718         memset(&vpc, 0, sizeof(vpc));
719
720         vdc[0].inc = 1;
721         vdc[1].inc = 1;
722
723         /* initialize palette */
724         int i;
725
726         for( i = 0; i < 512; i++ )
727         {
728                 int r = (( i >> 3) & 7) << 5;
729                 int g = (( i >> 6) & 7) << 5;
730                 int b = (( i     ) & 7) << 5;
731                 int y = ( (  66 * r + 129 * g +  25 * b + 128) >> 8) +  16;
732                 vce.palette[i] = RGB_COLOR(r, g, b);
733                 vce.palette[512+i] = RGB_COLOR(y, y, y);
734         }
735
736         vpc_w( 0, 0x11 );
737         vpc_w( 1, 0x11 );
738         vpc.window1.w.l = 0;
739         vpc.window2.w.l = 0;
740         vpc.vdc_select = 0;
741 }
742
743 void PCE::draw_black_line(int line)
744 {
745         int i;
746
747         /* our line buffer */
748         scrntype *line_buffer = vce.bmp[line];
749
750         for( i=0; i< VDC_WPF; i++ )
751                 line_buffer[i] = 0;
752 }
753
754 void PCE::draw_overscan_line(int line)
755 {
756         int i;
757
758         /* Are we in greyscale mode or in color mode? */
759         scrntype *color_base = vce.palette + (vce.vce_control & 0x80 ? 512 : 0);
760
761         /* our line buffer */
762         scrntype *line_buffer = vce.bmp[line];
763
764         for ( i = 0; i < VDC_WPF; i++ )
765                 line_buffer[i] = color_base[vce.vce_data[0x100].w.l];
766 }
767
768 void PCE::draw_sgx_overscan_line(int line)
769 {
770         int i;
771
772         /* Are we in greyscale mode or in color mode? */
773         scrntype *color_base = vce.palette + (vce.vce_control & 0x80 ? 512 : 0);
774
775         /* our line buffer */
776         scrntype *line_buffer = vce.bmp[line];
777
778         for ( i = 0; i < VDC_WPF; i++ )
779                 line_buffer[i] = color_base[vce.vce_data[0].w.l];
780 }
781
782 void PCE::vram_write(int which, uint32 offset, uint8 data)
783 {
784         if(offset & 0x10000)
785         {
786                 return;
787         }
788         else
789         {
790                 vdc[which].vram[offset] = data;
791         }
792 }
793
794 uint8 PCE::vram_read(int which, uint32 offset)
795 {
796         uint8 temp;
797
798         if(offset & 0x10000)
799         {
800                 temp = vdc[which].vram[offset & 0xFFFF];
801         }
802         else
803         {
804                 temp = vdc[which].vram[offset];
805         }
806
807         return temp;
808 }
809
810 void PCE::vdc_w(int which, uint16 offset, uint8 data)
811 {
812         switch(offset&3)
813         {
814                 case 0x00:      /* VDC register select */
815                         vdc[which].vdc_register = (data & 0x1F);
816                         break;
817
818                 case 0x02:      /* VDC data (LSB) */
819                         vdc[which].vdc_data[vdc[which].vdc_register].b.l = data;
820                         switch(vdc[which].vdc_register)
821                         {
822                                 case VxR:       /* LSB of data to write to VRAM */
823                                         vdc[which].vdc_latch = data;
824                                         break;
825
826                                 case BYR:
827                                         vdc[which].y_scroll=vdc[which].vdc_data[BYR].w.l;
828                                         break;
829
830                                 case HDR:
831                                         vdc[which].physical_width = ((data & 0x003F) + 1) << 3;
832                                         break;
833
834                                 case VDW:
835                                         vdc[which].physical_height &= 0xFF00;
836                                         vdc[which].physical_height |= (data & 0xFF);
837                                         vdc[which].physical_height &= 0x01FF;
838                                         break;
839
840                                 case LENR:
841                                         break;
842                                 case SOUR:
843                                         break;
844                                 case DESR:
845                                         break;
846                         }
847                         break;
848
849                 case 0x03:      /* VDC data (MSB) */
850                         vdc[which].vdc_data[vdc[which].vdc_register].b.h = data;
851                         switch(vdc[which].vdc_register)
852                         {
853                                 case VxR:       /* MSB of data to write to VRAM */
854                                         vram_write(which, vdc[which].vdc_data[MAWR].w.l*2+0, vdc[which].vdc_latch);
855                                         vram_write(which, vdc[which].vdc_data[MAWR].w.l*2+1, data);
856                                         vdc[which].vdc_data[MAWR].w.l += vdc[which].inc;
857                                         break;
858
859                                 case CR:
860                                         {
861                                                 static const unsigned char inctab[] = {1, 32, 64, 128};
862                                                 vdc[which].inc = inctab[(data >> 3) & 3];
863                                         }
864                                         break;
865
866                                 case VDW:
867                                         vdc[which].physical_height &= 0x00FF;
868                                         vdc[which].physical_height |= (data << 8);
869                                         vdc[which].physical_height &= 0x01FF;
870                                         break;
871
872                                 case DVSSR:
873                                         /* Force VRAM <> SATB DMA for this frame */
874                                         vdc[which].dvssr_write = 1;
875                                         break;
876
877                                 case BYR:
878                                         vdc[which].y_scroll=vdc[which].vdc_data[BYR].w.l;
879                                         break;
880
881                                 case LENR:
882                                         vdc_do_dma(which);
883                                         break;
884                                 case SOUR:
885                                         break;
886                                 case DESR:
887                                         break;
888                         }
889                         break;
890         }
891 }
892
893 uint8 PCE::vdc_r(int which, uint16 offset)
894 {
895         int temp = 0;
896         switch(offset & 3)
897         {
898                 case 0x00:
899                         temp = vdc[which].status;
900                         vdc[which].status &= ~(VDC_VD | VDC_DV | VDC_DS | VDC_RR | VDC_OR | VDC_CR);
901                         d_cpu->write_signal(INPUT_LINE_IRQ1, CLEAR_LINE, 0);
902                         break;
903
904                 case 0x02:
905                         temp = vram_read(which, vdc[which].vdc_data[MARR].w.l * 2 + 0);
906                         break;
907
908                 case 0x03:
909                         temp = vram_read(which, vdc[which].vdc_data[MARR].w.l * 2 + 1);
910                         if ( vdc[which].vdc_register == VxR )
911                         {
912                                 vdc[which].vdc_data[MARR].w.l += vdc[which].inc;
913                         }
914                         break;
915         }
916         return (temp);
917 }
918
919 uint8 PCE::vce_r(uint16 offset)
920 {
921         int temp = 0xFF;
922         switch(offset & 7)
923         {
924                 case 0x04:      /* color table data (LSB) */
925                         temp = vce.vce_data[vce.vce_address.w.l].b.l;
926                         break;
927
928                 case 0x05:      /* color table data (MSB) */
929                         temp = vce.vce_data[vce.vce_address.w.l].b.h;
930                         temp |= 0xFE;
931                         vce.vce_address.w.l = (vce.vce_address.w.l + 1) & 0x01FF;
932                         break;
933         }
934         return (temp);
935 }
936
937 void PCE::vce_w(uint16 offset, uint8 data)
938 {
939         switch(offset & 7)
940         {
941                 case 0x00:      /* control reg. */
942                         vce.vce_control = data;
943                         break;
944
945                 case 0x02:      /* color table address (LSB) */
946                         vce.vce_address.b.l = data;
947                         vce.vce_address.w.l &= 0x1FF;
948                         break;
949
950                 case 0x03:      /* color table address (MSB) */
951                         vce.vce_address.b.h = data;
952                         vce.vce_address.w.l &= 0x1FF;
953                         break;
954
955                 case 0x04:      /* color table data (LSB) */
956                         vce.vce_data[vce.vce_address.w.l].b.l = data;
957                         break;
958
959                 case 0x05:      /* color table data (MSB) */
960                         vce.vce_data[vce.vce_address.w.l].b.h = data & 0x01;
961
962                         /* bump internal address */
963                         vce.vce_address.w.l = (vce.vce_address.w.l + 1) & 0x01FF;
964                         break;
965         }
966 }
967
968 void PCE::pce_refresh_line(int which, int line, int external_input, uint8 *drawn, scrntype *line_buffer)
969 {
970         static const int width_table[4] = {5, 6, 7, 7};
971
972         int scroll_y = ( vdc[which].y_scroll & 0x01FF);
973         int scroll_x = (vdc[which].vdc_data[BXR].w.l & 0x03FF);
974         int nt_index;
975
976         /* is virtual map 32 or 64 characters tall ? (256 or 512 pixels) */
977         int v_line = (scroll_y) & (vdc[which].vdc_data[MWR].w.l & 0x0040 ? 0x1FF : 0x0FF);
978
979         /* row within character */
980         int v_row = (v_line & 7);
981
982         /* row of characters in BAT */
983         int nt_row = (v_line >> 3);
984
985         /* virtual X size (# bits to shift) */
986         int v_width =           width_table[(vdc[which].vdc_data[MWR].w.l >> 4) & 3];
987
988         /* pointer to the name table (Background Attribute Table) in VRAM */
989         uint8 *bat = &(vdc[which].vram[nt_row << (v_width+1)]);
990
991         /* Are we in greyscale mode or in color mode? */
992         scrntype *color_base = vce.palette + (vce.vce_control & 0x80 ? 512 : 0);
993
994         int b0, b1, b2, b3;
995         int i0, i1, i2, i3;
996         int cell_pattern_index;
997         int cell_palette;
998         int x, c, i;
999
1000         /* character blanking bit */
1001         if(!(vdc[which].vdc_data[CR].w.l & CR_BB))
1002         {
1003                 return;
1004         }
1005         else
1006         {
1007                 int     pixel = 0;
1008                 int phys_x = - ( scroll_x & 0x07 );
1009
1010                 for(i=0;i<(vdc[which].physical_width >> 3) + 1;i++)
1011                 {
1012                         nt_index = (i + (scroll_x >> 3)) & ((2 << (v_width-1))-1);
1013                         nt_index *= 2;
1014
1015                         /* get name table data: */
1016
1017                         /* palette # = index from 0-15 */
1018                         cell_palette = ( bat[nt_index + 1] >> 4 ) & 0x0F;
1019
1020                         /* This is the 'character number', from 0-0x0FFF         */
1021                         /* then it is shifted left 4 bits to form a VRAM address */
1022                         /* and one more bit to convert VRAM word offset to a     */
1023                         /* byte-offset within the VRAM space                     */
1024                         cell_pattern_index = ( ( ( bat[nt_index + 1] << 8 ) | bat[nt_index] ) & 0x0FFF) << 5;
1025
1026                         b0 = vram_read(which, (cell_pattern_index) + (v_row << 1) + 0x00);
1027                         b1 = vram_read(which, (cell_pattern_index) + (v_row << 1) + 0x01);
1028                         b2 = vram_read(which, (cell_pattern_index) + (v_row << 1) + 0x10);
1029                         b3 = vram_read(which, (cell_pattern_index) + (v_row << 1) + 0x11);
1030
1031                         for(x=0;x<8;x++)
1032                         {
1033                                 i0 = (b0 >> (7-x)) & 1;
1034                                 i1 = (b1 >> (7-x)) & 1;
1035                                 i2 = (b2 >> (7-x)) & 1;
1036                                 i3 = (b3 >> (7-x)) & 1;
1037                                 c = (cell_palette << 4 | i3 << 3 | i2 << 2 | i1 << 1 | i0);
1038
1039                                 /* colour #0 always comes from palette #0 */
1040                                 if ( ! ( c & 0x0F ) )
1041                                         c &= 0x0F;
1042
1043                                 if ( phys_x >= 0 && phys_x < vdc[which].physical_width )
1044                                 {
1045                                         drawn[ pixel ] = c ? 1 : 0;
1046                                         if ( c || ! external_input )
1047                                                 line_buffer[ pixel ] = color_base[vce.vce_data[c].w.l];
1048                                         pixel++;
1049 //                                      if ( vdc[which].physical_width != 512 )
1050 //                                      {
1051 //                                              while ( pixel < ( ( ( phys_x + 1 ) * 512 ) / vdc[which].physical_width ) )
1052 //                                              {
1053 //                                                      drawn[ pixel ] = c ? 1 : 0;
1054 //                                                      if ( c || ! external_input )
1055 //                                                      line_buffer[ pixel ] = color_base[vce.vce_data[c].w.l];
1056 //                                                      pixel++;
1057 //                                              }
1058 //                                      }
1059                                 }
1060                                 phys_x += 1;
1061                         }
1062                 }
1063         }
1064 }
1065
1066 void PCE::conv_obj(int which, int i, int l, int hf, int vf, char *buf)
1067 {
1068         int b0, b1, b2, b3, i0, i1, i2, i3, x;
1069         int xi;
1070         int tmp;
1071
1072         l &= 0x0F;
1073         if(vf) l = (15 - l);
1074
1075         tmp = l + ( i << 5);
1076
1077         b0 = vram_read(which, (tmp + 0x00)<<1);
1078         b0 |= vram_read(which, ((tmp + 0x00)<<1)+1)<<8;
1079         b1 = vram_read(which, (tmp + 0x10)<<1);
1080         b1 |= vram_read(which, ((tmp + 0x10)<<1)+1)<<8;
1081         b2 = vram_read(which, (tmp + 0x20)<<1);
1082         b2 |= vram_read(which, ((tmp + 0x20)<<1)+1)<<8;
1083         b3 = vram_read(which, (tmp + 0x30)<<1);
1084         b3 |= vram_read(which, ((tmp + 0x30)<<1)+1)<<8;
1085
1086         for(x=0;x<16;x++)
1087         {
1088                 if(hf) xi = x; else xi = (15 - x);
1089                 i0 = (b0 >> xi) & 1;
1090                 i1 = (b1 >> xi) & 1;
1091                 i2 = (b2 >> xi) & 1;
1092                 i3 = (b3 >> xi) & 1;
1093                 buf[x] = (i3 << 3 | i2 << 2 | i1 << 1 | i0);
1094         }
1095 }
1096
1097 void PCE::pce_refresh_sprites(int which, int line, uint8 *drawn, scrntype *line_buffer)
1098 {
1099         int i;
1100         uint8 sprites_drawn = 0;
1101
1102         /* Are we in greyscale mode or in color mode? */
1103         scrntype *color_base = vce.palette + (vce.vce_control & 0x80 ? 512 : 0);
1104
1105         /* count up: Highest priority is Sprite 0 */
1106         for(i = 0; i < 64; i++)
1107         {
1108                 static const int cgy_table[] = {16, 32, 64, 64};
1109
1110                 int obj_y = (vdc[which].sprite_ram[(i << 2) + 0] & 0x03FF) - 64;
1111                 int obj_x = (vdc[which].sprite_ram[(i << 2) + 1] & 0x03FF) - 32;
1112                 int obj_i = (vdc[which].sprite_ram[(i << 2) + 2] & 0x07FE);
1113                 int obj_a = (vdc[which].sprite_ram[(i << 2) + 3]);
1114                 int cgx   = (obj_a >> 8) & 1;   /* sprite width */
1115                 int cgy   = (obj_a >> 12) & 3;  /* sprite height */
1116                 int hf    = (obj_a >> 11) & 1;  /* horizontal flip */
1117                 int vf    = (obj_a >> 15) & 1;  /* vertical flip */
1118                 int palette = (obj_a & 0x000F);
1119                 int priority = (obj_a >> 7) & 1;
1120                 int obj_h = cgy_table[cgy];
1121                 int obj_l = (line - obj_y);
1122                 int cgypos;
1123                 char buf[16];
1124
1125                 if ((obj_y == -64) || (obj_y > line)) continue;
1126                 if ((obj_x == -32) || (obj_x >= vdc[which].physical_width)) continue;
1127
1128                 /* no need to draw an object that's ABOVE where we are. */
1129                 if((obj_y + obj_h) < line) continue;
1130
1131                 /* If CGX is set, bit 0 of sprite pattern index is forced to 0 */
1132                 if ( cgx )
1133                         obj_i &= ~2;
1134
1135                 /* If CGY is set to 1, bit 1 of the sprite pattern index is forced to 0. */
1136                 if ( cgy & 1 )
1137                         obj_i &= ~4;
1138
1139                 /* If CGY is set to 2 or 3, bit 1 and 2 of the sprite pattern index are forced to 0. */
1140                 if ( cgy & 2 )
1141                         obj_i &= ~12;
1142
1143                 if (obj_l < obj_h)
1144                 {
1145
1146                         sprites_drawn++;
1147                         if(sprites_drawn > 16)
1148                         {
1149                                 if(vdc[which].vdc_data[CR].w.l & CR_OV)
1150                                 {
1151                                         /* note: flag is set only if irq is taken, Mizubaku Daibouken relies on this behaviour */
1152                                         vdc[which].status |= VDC_OR;
1153                                         d_cpu->write_signal(INPUT_LINE_IRQ1, ASSERT_LINE, 0);
1154                                 }
1155                                 continue;  /* Should cause an interrupt */
1156                         }
1157
1158                         cgypos = (obj_l >> 4);
1159                         if(vf) cgypos = ((obj_h - 1) >> 4) - cgypos;
1160
1161                         if(cgx == 0)
1162                         {
1163                                 int x;
1164                                 int pixel_x = obj_x;//( ( obj_x * 512 ) / vdc[which].physical_width );
1165
1166                                 conv_obj(which, obj_i + (cgypos << 2), obj_l, hf, vf, buf);
1167
1168                                 for(x = 0; x < 16; x++)
1169                                 {
1170                                         if(((obj_x + x) < (vdc[which].physical_width)) && ((obj_x + x) >= 0))
1171                                         {
1172                                                 if ( buf[x] )
1173                                                 {
1174                                                         if( drawn[pixel_x] < 2 )
1175                                                         {
1176                                                                 if( priority || drawn[pixel_x] == 0 )
1177                                                                 {
1178                                                                         line_buffer[pixel_x] = color_base[vce.vce_data[0x100 + (palette << 4) + buf[x]].w.l];
1179 //                                                                      if ( vdc[which].physical_width != 512 )
1180 //                                                                      {
1181 //                                                                              int dp = 1;
1182 //                                                                              while ( pixel_x + dp < ( ( ( obj_x + x + 1 ) * 512 ) / vdc[which].physical_width ) )
1183 //                                                                              {
1184 //                                                                                      drawn[pixel_x + dp] = i + 2;
1185 //                                                                                      line_buffer[pixel_x + dp] = color_base[vce.vce_data[0x100 + (palette << 4) + buf[x]].w.l];
1186 //                                                                                      dp++;
1187 //                                                                              }
1188 //                                                                      }
1189                                                                 }
1190                                                                 drawn[pixel_x] = i + 2;
1191                                                         }
1192                                                         /* Check for sprite #0 collision */
1193                                                         else if (drawn[pixel_x] == 2)
1194                                                         {
1195                                                                 if(vdc[which].vdc_data[CR].w.l & CR_CC)
1196                                                                         d_cpu->write_signal(INPUT_LINE_IRQ1, ASSERT_LINE, 0);
1197                                                                 vdc[which].status |= VDC_CR;
1198                                                         }
1199                                                 }
1200                                         }
1201 //                                      if ( vdc[which].physical_width != 512 )
1202 //                                      {
1203 //                                              pixel_x = ( ( obj_x + x + 1 ) * 512 ) / vdc[which].physical_width;
1204 //                                      }
1205 //                                      else
1206 //                                      {
1207                                                 pixel_x += 1;
1208 //                                      }
1209                                 }
1210                         }
1211                         else
1212                         {
1213                                 int x;
1214                                 int pixel_x = obj_x;//( ( obj_x * 512 ) / vdc[which].physical_width );
1215
1216                                 conv_obj(which, obj_i + (cgypos << 2) + (hf ? 2 : 0), obj_l, hf, vf, buf);
1217
1218                                 for(x = 0; x < 16; x++)
1219                                 {
1220                                         if(((obj_x + x) < (vdc[which].physical_width)) && ((obj_x + x) >= 0))
1221                                         {
1222                                                 if ( buf[x] )
1223                                                 {
1224                                                         if( drawn[pixel_x] < 2 )
1225                                                         {
1226                                                                 if ( priority || drawn[pixel_x] == 0 )
1227                                                                 {
1228                                                                         line_buffer[pixel_x] = color_base[vce.vce_data[0x100 + (palette << 4) + buf[x]].w.l];
1229 //                                                                      if ( vdc[which].physical_width != 512 )
1230 //                                                                      {
1231 //                                                                              int dp = 1;
1232 //                                                                              while ( pixel_x + dp < ( ( ( obj_x + x + 1 ) * 512 ) / vdc[which].physical_width ) )
1233 //                                                                              {
1234 //                                                                                      drawn[pixel_x + dp] = i + 2;
1235 //                                                                                      line_buffer[pixel_x + dp] = color_base[vce.vce_data[0x100 + (palette << 4) + buf[x]].w.l];
1236 //                                                                                      dp++;
1237 //                                                                              }
1238 //                                                                      }
1239                                                                 }
1240                                                                 drawn[pixel_x] = i + 2;
1241                                                         }
1242                                                         /* Check for sprite #0 collision */
1243                                                         else if ( drawn[pixel_x] == 2 )
1244                                                         {
1245                                                                 if(vdc[which].vdc_data[CR].w.l & CR_CC)
1246                                                                         d_cpu->write_signal(INPUT_LINE_IRQ1, ASSERT_LINE, 0);
1247                                                                 vdc[which].status |= VDC_CR;
1248                                                         }
1249                                                 }
1250                                         }
1251 //                                      if ( vdc[which].physical_width != 512 )
1252 //                                      {
1253 //                                              pixel_x = ( ( obj_x + x + 1 ) * 512 ) / vdc[which].physical_width;
1254 //                                      }
1255 //                                      else
1256 //                                      {
1257                                                 pixel_x += 1;
1258 //                                      }
1259                                 }
1260
1261                                 /* 32 pixel wide sprites are counted as 2 sprites and the right half
1262                                    is only drawn if there are 2 open slots.
1263                                 */
1264                                 sprites_drawn++;
1265                                 if( sprites_drawn > 16 )
1266                                 {
1267                                         if(vdc[which].vdc_data[CR].w.l&CR_OV)
1268                                         {
1269                                                 /* note: flag is set only if irq is taken, Mizubaku Daibouken relies on this behaviour */
1270                                                 vdc[which].status |= VDC_OR;
1271                                                 d_cpu->write_signal(INPUT_LINE_IRQ1, ASSERT_LINE, 0);
1272                                         }
1273                                 }
1274                                 else
1275                                 {
1276                                         conv_obj(which, obj_i + (cgypos << 2) + (hf ? 0 : 2), obj_l, hf, vf, buf);
1277                                         for(x = 0; x < 16; x++)
1278                                         {
1279                                                 if(((obj_x + 0x10 + x) < (vdc[which].physical_width)) && ((obj_x + 0x10 + x) >= 0))
1280                                                 {
1281                                                         if ( buf[x] )
1282                                                         {
1283                                                                 if( drawn[pixel_x] < 2 )
1284                                                                 {
1285                                                                         if( priority || drawn[pixel_x] == 0 )
1286                                                                         {
1287                                                                                 line_buffer[pixel_x] = color_base[vce.vce_data[0x100 + (palette << 4) + buf[x]].w.l];
1288 //                                                                              if ( vdc[which].physical_width != 512 )
1289 //                                                                              {
1290 //                                                                                      int dp = 1;
1291 //                                                                                      while ( pixel_x + dp < ( ( ( obj_x + x + 17 ) * 512 ) / vdc[which].physical_width ) )
1292 //                                                                                      {
1293 //                                                                                              drawn[pixel_x + dp] = i + 2;
1294 //                                                                                              line_buffer[pixel_x + dp] = color_base[vce.vce_data[0x100 + (palette << 4) + buf[x]].w.l];
1295 //                                                                                              dp++;
1296 //                                                                                      }
1297 //                                                                              }
1298                                                                         }
1299                                                                         drawn[pixel_x] = i + 2;
1300                                                                 }
1301                                                                 /* Check for sprite #0 collision */
1302                                                                 else if ( drawn[pixel_x] == 2 )
1303                                                                 {
1304                                                                         if(vdc[which].vdc_data[CR].w.l & CR_CC)
1305                                                                                 d_cpu->write_signal(INPUT_LINE_IRQ1, ASSERT_LINE, 0);
1306                                                                         vdc[which].status |= VDC_CR;
1307                                                                 }
1308                                                         }
1309                                                 }
1310 //                                              if ( vdc[which].physical_width != 512 )
1311 //                                              {
1312 //                                                      pixel_x = ( ( obj_x + x + 17 ) * 512 ) / vdc[which].physical_width;
1313 //                                              }
1314 //                                              else
1315 //                                              {
1316                                                         pixel_x += 1;
1317 //                                              }
1318                                         }
1319                                 }
1320                         }
1321                 }
1322         }
1323 }
1324
1325 void PCE::vdc_do_dma(int which)
1326 {
1327         int src = vdc[which].vdc_data[SOUR].w.l;
1328         int dst = vdc[which].vdc_data[DESR].w.l;
1329         int len = vdc[which].vdc_data[LENR].w.l;
1330
1331         int did = (vdc[which].vdc_data[DCR].w.l >> 3) & 1;
1332         int sid = (vdc[which].vdc_data[DCR].w.l >> 2) & 1;
1333         int dvc = (vdc[which].vdc_data[DCR].w.l >> 1) & 1;
1334
1335         do {
1336                 uint8 l, h;
1337
1338                 l = vram_read(which, src<<1);
1339                 h = vram_read(which, (src<<1) + 1);
1340
1341                 vram_write(which, dst<<1,l);
1342                 vram_write(which, 1+(dst<<1),h);
1343
1344                 if(sid) src = (src - 1) & 0xFFFF;
1345                 else    src = (src + 1) & 0xFFFF;
1346
1347                 if(did) dst = (dst - 1) & 0xFFFF;
1348                 else    dst = (dst + 1) & 0xFFFF;
1349
1350                 len = (len - 1) & 0xFFFF;
1351
1352         } while (len != 0xFFFF);
1353
1354         vdc[which].status |= VDC_DV;
1355         vdc[which].vdc_data[SOUR].w.l = src;
1356         vdc[which].vdc_data[DESR].w.l = dst;
1357         vdc[which].vdc_data[LENR].w.l = len;
1358         if(dvc)
1359         {
1360                 d_cpu->write_signal(INPUT_LINE_IRQ1, ASSERT_LINE, 0);
1361         }
1362
1363 }
1364
1365 void PCE::vpc_update_prio_map()
1366 {
1367         int i;
1368
1369         for( i = 0; i < 512; i++ )
1370         {
1371                 vpc.prio_map[i] = 0;
1372                 if ( vpc.window1.w.l < 0x40 || i > vpc.window1.w.l )
1373                 {
1374                         vpc.prio_map[i] |= 1;
1375                 }
1376                 if ( vpc.window2.w.l < 0x40 || i > vpc.window2.w.l )
1377                 {
1378                         vpc.prio_map[i] |= 2;
1379                 }
1380         }
1381 }
1382
1383 void PCE::vpc_w(uint16 offset, uint8 data)
1384 {
1385         switch( offset & 0x07 )
1386         {
1387         case 0x00:      /* Priority register #0 */
1388                 vpc.priority.b.l = data;
1389                 vpc.vpc_prio[0].prio = ( data >> 2 ) & 3;
1390                 vpc.vpc_prio[0].vdc0_enabled = data & 1;
1391                 vpc.vpc_prio[0].vdc1_enabled = data & 2;
1392                 vpc.vpc_prio[1].prio = ( data >> 6 ) & 3;
1393                 vpc.vpc_prio[1].vdc0_enabled = data & 0x10;
1394                 vpc.vpc_prio[1].vdc1_enabled = data & 0x20;
1395                 break;
1396         case 0x01:      /* Priority register #1 */
1397                 vpc.priority.b.h = data;
1398                 vpc.vpc_prio[2].prio = ( data >> 2 ) & 3;
1399                 vpc.vpc_prio[2].vdc0_enabled = data & 1;
1400                 vpc.vpc_prio[2].vdc1_enabled = data & 2;
1401                 vpc.vpc_prio[3].prio = ( data >> 6 ) & 3;
1402                 vpc.vpc_prio[3].vdc0_enabled = data & 0x10;
1403                 vpc.vpc_prio[3].vdc1_enabled = data & 0x20;
1404                 break;
1405         case 0x02:      /* Window 1 LSB */
1406                 vpc.window1.b.l = data;
1407                 vpc_update_prio_map();
1408                 break;
1409         case 0x03:      /* Window 1 MSB */
1410                 vpc.window1.b.h = data & 3;
1411                 vpc_update_prio_map();
1412                 break;
1413         case 0x04:      /* Window 2 LSB */
1414                 vpc.window2.b.l = data;
1415                 vpc_update_prio_map();
1416                 break;
1417         case 0x05:      /* Window 2 MSB */
1418                 vpc.window2.b.h = data & 3;
1419                 vpc_update_prio_map();
1420                 break;
1421         case 0x06:      /* VDC I/O select */
1422                 vpc.vdc_select = data & 1;
1423                 break;
1424         }
1425 }
1426
1427 uint8 PCE::vpc_r(uint16 offset)
1428 {
1429         uint8 data = 0;
1430         switch( offset & 0x07 )
1431         {
1432         case 0x00:  /* Priority register #0 */
1433                 data = vpc.priority.b.l;
1434                 break;
1435         case 0x01:  /* Priority register #1 */
1436                 data = vpc.priority.b.h;
1437                 break;
1438         case 0x02:  /* Window 1 LSB */
1439                 data = vpc.window1.b.l;
1440                 break;
1441         case 0x03:  /* Window 1 MSB; high bits are 0 or 1? */
1442                 data = vpc.window1.b.h;
1443                 break;
1444         case 0x04:  /* Window 2 LSB */
1445                 data = vpc.window2.b.l;
1446                 break;
1447         case 0x05:  /* Window 2 MSB; high bits are 0 or 1? */
1448                 data = vpc.window2.b.h;
1449                 break;
1450         }
1451         return data;
1452 }
1453
1454 void PCE::sgx_vdc_w(uint16 offset, uint8 data)
1455 {
1456         if ( vpc.vdc_select )
1457         {
1458                 vdc_w( 1, offset, data );
1459         }
1460         else
1461         {
1462                 vdc_w( 0, offset, data );
1463         }
1464 }
1465
1466 uint8 PCE::sgx_vdc_r(uint16 offset)
1467 {
1468         return ( vpc.vdc_select ) ? vdc_r( 1, offset ) : vdc_r( 0, offset );
1469 }
1470
1471 // psg
1472
1473 void PCE::psg_reset()
1474 {
1475         memset(psg, 0, sizeof(psg));
1476         for (int i = 0; i < 6; i++) {
1477                 psg[i].regs[4] = 0x80;
1478         }
1479         psg[4].randval = psg[5].randval = 0x51f631e4;
1480         
1481         psg_ch = 0;
1482         psg_vol = psg_lfo_freq = psg_lfo_ctrl = 0;
1483 }
1484
1485 void PCE::psg_write(uint16 addr, uint8 data)
1486 {
1487         switch(addr & 0x1f) {
1488         case 0:
1489                 psg_ch = data & 7;
1490                 break;
1491         case 1:
1492                 psg_vol = data;
1493                 break;
1494         case 2:
1495                 psg[psg_ch].regs[2] = data;
1496                 break;
1497         case 3:
1498 //              psg[psg_ch].regs[3] = data & 0x1f;
1499                 psg[psg_ch].regs[3] = data & 0xf;
1500                 break;
1501         case 4:
1502                 psg[psg_ch].regs[4] = data;
1503                 break;
1504         case 5:
1505                 psg[psg_ch].regs[5] = data;
1506                 break;
1507         case 6:
1508                 if(psg[psg_ch].regs[4] & 0x40) {
1509                         psg[psg_ch].wav[0] =data & 0x1f;
1510                 }
1511                 else {
1512                         psg[psg_ch].wav[psg[psg_ch].wavptr] = data & 0x1f;
1513                         psg[psg_ch].wavptr = (psg[psg_ch].wavptr + 1) & 0x1f;
1514                 }
1515                 break;
1516         case 7:
1517                 psg[psg_ch].regs[7] = data;
1518                 break;
1519         case 8:
1520                 psg_lfo_freq = data;
1521                 break;
1522         case 9:
1523                 psg_lfo_ctrl = data;
1524                 break;
1525         }
1526 }
1527
1528 uint8 PCE::psg_read(uint16 addr)
1529 {
1530         int ptr;
1531         
1532         switch(addr & 0x1f) {
1533         case 0:
1534                 return psg_ch;
1535         case 1:
1536                 return psg_vol;
1537         case 2:
1538                 return psg[psg_ch].regs[2];
1539         case 3:
1540                 return psg[psg_ch].regs[3];
1541         case 4:
1542                 return psg[psg_ch].regs[4];
1543         case 5:
1544                 return psg[psg_ch].regs[5];
1545         case 6:
1546                 ptr = psg[psg_ch].wavptr;
1547                 psg[psg_ch].wavptr = (psg[psg_ch].wavptr + 1) & 0x1f;
1548                 return psg[psg_ch].wav[ptr];
1549         case 7:
1550                 return psg[psg_ch].regs[7];
1551         case 8:
1552                 return psg_lfo_freq;
1553         case 9:
1554                 return psg_lfo_ctrl;
1555         }
1556         return 0xff;
1557 }
1558
1559 void PCE::mix(int32* buffer, int cnt)
1560 {
1561         int vol_tbl[32] = {
1562                  100, 451, 508, 573, 646, 728, 821, 925,1043,1175,1325, 1493, 1683, 1898, 2139, 2411,
1563                 2718,3064,3454,3893,4388,4947,5576,6285,7085,7986,9002,10148,11439,12894,14535,16384
1564         };
1565         
1566         if(!inserted) {
1567                 return;
1568         }
1569         for(int ch = 0; ch < 6; ch++) {
1570                 if(!(psg[ch].regs[4] & 0x80)) {
1571                         // mute
1572                         psg[ch].genptr = psg[ch].remain = 0;
1573                 }
1574                 else if(psg[ch].regs[4] & 0x40) {
1575                         // dda
1576                         int32 wav = ((int32)psg[ch].wav[0] - 16) * 702;
1577                         int32 vol = max((psg_vol >> 3) & 0x1e, (psg_vol << 1) & 0x1e) + (psg[ch].regs[4] & 0x1f) + max((psg[ch].regs[5] >> 3) & 0x1e, (psg[ch].regs[5] << 1) & 0x1e) - 60;
1578                         vol = (vol < 0) ? 0 : (vol > 31) ? 31 : vol;
1579                         vol = wav * vol_tbl[vol] / 16384;
1580                         for(int i = 0, j = 0; i < cnt; i++, j += 2) {
1581                                 buffer[j    ] += vol; // L
1582                                 buffer[j + 1] += vol; // R
1583                         }
1584                 }
1585                 else if(ch >= 4 && (psg[ch].regs[7] & 0x80)) {
1586                         // noise
1587                         uint16 freq = (psg[ch].regs[7] & 0x1f);
1588                         int32 vol = max((psg_vol >> 3) & 0x1e, (psg_vol << 1) & 0x1e) + (psg[ch].regs[4] & 0x1f) + max((psg[ch].regs[5] >> 3) & 0x1e, (psg[ch].regs[5] << 1) & 0x1e) - 60;
1589                         vol = (vol < 0) ? 0 : (vol > 31) ? 31 : vol;
1590                         vol = vol_tbl[vol];
1591                         for(int i = 0, j = 0; i < cnt; i++, j += 2) {
1592                                 psg[ch].remain += 3000 + freq * 512;
1593                                 uint32 t = psg[ch].remain / sample_rate;
1594                                 if(t >= 1) {
1595                                         if(psg[ch].randval & 0x80000) {
1596                                                 psg[ch].randval = ((psg[ch].randval ^ 4) << 1) + 1;
1597                                                 psg[ch].noise = true;
1598                                         }
1599                                         else {
1600                                                 psg[ch].randval <<= 1;
1601                                                 psg[ch].noise = false;
1602                                         }
1603                                         psg[ch].remain -= sample_rate * t;
1604                                 }
1605                                 int32 outvol = (int32)((psg[ch].noise ? 10 * 702 : -10 * 702) * vol / 16384);
1606                                 buffer[j    ] += outvol; // L
1607                                 buffer[j + 1] += outvol; // R
1608                         }
1609                 }
1610                 else {
1611                         int32 wav[32];
1612                         for(int i = 0; i < 32; i++) {
1613                                 wav[i] = ((int32)psg[ch].wav[i] - 16) * 702;
1614                         }
1615                         uint32 freq = psg[ch].regs[2] + ((uint32)psg[ch].regs[3] << 8);
1616                         if(freq) {
1617                                 int32 vol = max((psg_vol >> 3) & 0x1e, (psg_vol << 1) & 0x1e) + (psg[ch].regs[4] & 0x1f) + max((psg[ch].regs[5] >> 3) & 0x1e, (psg[ch].regs[5] << 1) & 0x1e) - 60;
1618                                 vol = (vol < 0) ? 0 : (vol > 31) ? 31 : vol;
1619                                 vol = vol_tbl[vol];
1620                                 for(int i = 0, j = 0; i < cnt; i++, j += 2) {
1621                                         int32 outvol = wav[psg[ch].genptr] * vol / 16384;
1622                                         buffer[j    ] += outvol; // L
1623                                         buffer[j + 1] += outvol; // R
1624                                         psg[ch].remain += 32 * 1118608 / freq;
1625                                         uint32 t = psg[ch].remain / (10 * sample_rate);
1626                                         psg[ch].genptr = (psg[ch].genptr + t) & 0x1f;
1627                                         psg[ch].remain -= 10 * sample_rate * t;
1628                                 }
1629                         }
1630                 }
1631         }
1632 }
1633
1634 // joypad (non multipad)
1635
1636 void PCE::joy_reset()
1637 {
1638         joy_sel = joy_bank = 1;
1639         joy_clr = joy_count = 0;
1640 }
1641
1642 void PCE::joy_write(uint16 addr, uint8 data)
1643 {
1644         uint8 new_sel = data & 1;
1645         uint8 new_clr = data & 2;
1646         
1647         if(joy_sel && new_sel) {
1648                 if(joy_clr && !new_clr) {
1649                         joy_count = 0;
1650                         joy_bank ^= 1;
1651                 }
1652         }
1653         else if(!joy_sel && new_sel) {
1654                 joy_count = (joy_count + 1) & 15;
1655         }
1656         joy_sel = new_sel;
1657         joy_clr = new_clr;
1658 }
1659
1660 uint8 PCE::joy_read(uint16 addr)
1661 {
1662         uint8 val = 0xf;
1663         uint32 stat = 0;
1664         
1665         if(joy_count == 0) {
1666                 stat = joy_stat[0];
1667                 if(key_stat[0x26]) stat |= 0x001;       // up
1668                 if(key_stat[0x28]) stat |= 0x002;       // down
1669                 if(key_stat[0x25]) stat |= 0x004;       // left
1670                 if(key_stat[0x27]) stat |= 0x008;       // right
1671                 if(key_stat[0x44]) stat |= 0x010;       // d (1)
1672                 if(key_stat[0x53]) stat |= 0x020;       // s (2)
1673                 if(key_stat[0x20]) stat |= 0x040;       // space (select)
1674                 if(key_stat[0x0d]) stat |= 0x080;       // enter (run)
1675                 if(key_stat[0x41]) stat |= 0x100;       // a (3)
1676                 if(key_stat[0x51]) stat |= 0x200;       // q (4)
1677                 if(key_stat[0x57]) stat |= 0x400;       // w (5)
1678                 if(key_stat[0x45]) stat |= 0x800;       // e (6)
1679         } else if(joy_count == 1) {
1680                 stat = joy_stat[1];
1681         }
1682         if(support_6btn && joy_bank) {
1683                 if(joy_sel) {
1684                         val = 0;
1685                 } else {
1686                         if(stat & 0x100) val &= ~1;     // b3
1687                         if(stat & 0x200) val &= ~2;     // b4
1688                         if(stat & 0x400) val &= ~4;     // b5
1689                         if(stat & 0x800) val &= ~8;     // b6
1690                 }
1691         } else {
1692                 if(joy_sel) {
1693                         if(stat & 0x001) val &= ~1;     // up
1694                         if(stat & 0x008) val &= ~2;     // right
1695                         if(stat & 0x002) val &= ~4;     // down
1696                         if(stat & 0x004) val &= ~8;     // left
1697                 } else {
1698                         if(stat & 0x010) val &= ~1;     // b1
1699                         if(stat & 0x020) val &= ~2;     // b2
1700                         if(stat & 0x040) val &= ~4;     // sel
1701                         if(stat & 0x080) val &= ~8;     // run
1702                 }
1703         }
1704         if(joy_count == 4) {
1705                 joy_bank = 1;
1706         }
1707         return val;
1708 }
1709
1710 #define STATE_VERSION   2
1711
1712 void PCE::save_state(FILEIO* state_fio)
1713 {
1714         state_fio->FputUint32(STATE_VERSION);
1715         state_fio->FputInt32(this_device_id);
1716         
1717         state_fio->FputBool(support_6btn);
1718         state_fio->FputBool(support_sgfx);
1719         state_fio->Fwrite(ram, sizeof(ram), 1);
1720         state_fio->Fwrite(cart + 0x80000, 0x80000, 1);
1721 #ifdef SUPPORT_BACKUP_RAM
1722         state_fio->Fwrite(backup, sizeof(backup), 1);
1723         state_fio->FputUint32(backup_crc32);
1724 #endif
1725         state_fio->FputUint32(bank);
1726         state_fio->FputUint8(buffer);
1727         state_fio->FputInt32(prev_width);
1728         state_fio->FputBool(inserted);
1729         state_fio->Fwrite(vdc, sizeof(vdc), 1);
1730         state_fio->Fwrite(&vce, sizeof(vce), 1);
1731         state_fio->Fwrite(&vpc, sizeof(vpc), 1);
1732         state_fio->Fwrite(psg, sizeof(psg), 1);
1733         state_fio->FputUint8(psg_ch);
1734         state_fio->FputUint8(psg_vol);
1735         state_fio->FputUint8(psg_lfo_freq);
1736         state_fio->FputUint8(psg_lfo_ctrl);
1737         state_fio->FputUint8(joy_sel);
1738         state_fio->FputUint8(joy_clr);
1739         state_fio->FputUint8(joy_count);
1740         state_fio->FputUint8(joy_bank);
1741         state_fio->FputBool(joy_6btn);
1742 }
1743
1744 bool PCE::load_state(FILEIO* state_fio)
1745 {
1746         if(state_fio->FgetUint32() != STATE_VERSION) {
1747                 return false;
1748         }
1749         if(state_fio->FgetInt32() != this_device_id) {
1750                 return false;
1751         }
1752         support_6btn = state_fio->FgetBool();
1753         support_sgfx = state_fio->FgetBool();
1754         state_fio->Fread(ram, sizeof(ram), 1);
1755         state_fio->Fread(cart + 0x80000, 0x80000, 1);
1756 #ifdef SUPPORT_BACKUP_RAM
1757         state_fio->Fread(backup, sizeof(backup), 1);
1758         backup_crc32 = state_fio->FgetUint32();
1759 #endif
1760         bank = state_fio->FgetUint32();
1761         buffer = state_fio->FgetUint8();
1762         prev_width = state_fio->FgetInt32();
1763         inserted = state_fio->FgetBool();
1764         state_fio->Fread(vdc, sizeof(vdc), 1);
1765         state_fio->Fread(&vce, sizeof(vce), 1);
1766         state_fio->Fread(&vpc, sizeof(vpc), 1);
1767         state_fio->Fread(psg, sizeof(psg), 1);
1768         psg_ch = state_fio->FgetUint8();
1769         psg_vol = state_fio->FgetUint8();
1770         psg_lfo_freq = state_fio->FgetUint8();
1771         psg_lfo_ctrl = state_fio->FgetUint8();
1772         joy_sel = state_fio->FgetUint8();
1773         joy_clr = state_fio->FgetUint8();
1774         joy_count = state_fio->FgetUint8();
1775         joy_bank = state_fio->FgetUint8();
1776         joy_6btn = state_fio->FgetBool();
1777         return true;
1778 }
1779