OSDN Git Service

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