OSDN Git Service

[VM][STATE] Use namespace {VMNAME} to separate per VMs.
[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/cdrom)
6                : xpce (psg)
7                : MESS (vdc/vce/vpc/cdrom)
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 #ifdef SUPPORT_CDROM
18 #include "../msm5205.h"
19 #include "../scsi_host.h"
20 #include "../scsi_cdrom.h"
21 #endif
22
23 #define STATE_VSW               0
24 #define STATE_VDS               1
25 #define STATE_VDW               2
26 #define STATE_VCR               3
27
28 /* Bits in the VDC status register */
29
30 #define VDC_BSY         0x40    /* Set when the VDC accesses VRAM */
31 #define VDC_VD          0x20    /* Set when in the vertical blanking period */
32 #define VDC_DV          0x10    /* Set when a VRAM > VRAM DMA transfer is done */
33 #define VDC_DS          0x08    /* Set when a VRAM > SATB DMA transfer is done */
34 #define VDC_RR          0x04    /* Set when the current scanline equals the RCR register */
35 #define VDC_OR          0x02    /* Set when there are more than 16 sprites on a line */
36 #define VDC_CR          0x01    /* Set when sprite #0 overlaps with another sprite */
37
38 /* Bits in the CR register */
39
40 #define CR_BB           0x80    /* Background blanking */
41 #define CR_SB           0x40    /* Object blanking */
42 #define CR_VR           0x08    /* Interrupt on vertical blank enable */
43 #define CR_RC           0x04    /* Interrupt on line compare enable */
44 #define CR_OV           0x02    /* Interrupt on sprite overflow enable */
45 #define CR_CC           0x01    /* Interrupt on sprite #0 collision enable */
46
47 /* Bits in the DCR regsiter */
48
49 #define DCR_DSR         0x10    /* VRAM > SATB auto-transfer enable */
50 #define DCR_DID         0x08    /* Destination diretion */
51 #define DCR_SID         0x04    /* Source direction */
52 #define DCR_DVC         0x02    /* VRAM > VRAM EOT interrupt enable */
53 #define DCR_DSC         0x01    /* VRAM > SATB EOT interrupt enable */
54
55 namespace PCEDEV {
56
57 /* just to keep things simple... */
58 enum vdc_regs {MAWR = 0, MARR, VxR, reg3, reg4, CR, RCR, BXR, BYR, MWR, HSR, HDR, VPR, VDW, VCR, DCR, SOUR, DESR, LENR, DVSSR };
59
60 enum line_state
61 {
62         CLEAR_LINE = 0,                         // clear (a fired or held) line
63         ASSERT_LINE,                            // assert an interrupt immediately
64         HOLD_LINE,                              // hold interrupt line until acknowledged
65         PULSE_LINE                              // pulse interrupt line instantaneously (only for NMI, RESET)
66 };
67
68 enum
69 {
70         INPUT_LINE_IRQ1 = 0,
71         INPUT_LINE_IRQ2 = 1,
72         INPUT_LINE_TIRQ = 2,
73         INPUT_LINE_NMI
74 };
75
76 #ifndef SUPPORT_CDROM
77 #define backup_locked   false
78 #endif
79
80 void PCE::initialize()
81 {
82         // get context
83         joy_stat = emu->get_joy_buffer();
84         
85         // register event
86         register_vline_event(this);
87         
88 #ifdef SUPPORT_BACKUP_RAM
89         static const uint8_t image[8] = {0x48, 0x55, 0x42, 0x4d, 0x00, 0x88, 0x10, 0x80};
90         memset(backup, 0, sizeof(backup));
91         memcpy(backup, image, sizeof(image));
92         
93         FILEIO* fio = new FILEIO();
94         if(fio->Fopen(create_local_path(_T("BACKUP.BIN")), FILEIO_READ_BINARY)) {
95                 fio->Fread(backup, sizeof(backup), 1);
96                 fio->Fclose();
97         }
98         delete fio;
99         
100         backup_crc32 = get_crc32(backup, sizeof(backup));
101 #endif
102 #ifdef SUPPORT_CDROM
103         cdrom_initialize();
104 #endif
105         inserted = false;
106 }
107
108 void PCE::release()
109 {
110 #ifdef SUPPORT_BACKUP_RAM
111         if(backup_crc32 != get_crc32(backup, sizeof(backup))) {
112                 FILEIO* fio = new FILEIO();
113                 if(fio->Fopen(create_local_path(_T("BACKUP.BIN")), FILEIO_WRITE_BINARY)) {
114                         fio->Fwrite(backup, sizeof(backup), 1);
115                         fio->Fclose();
116                 }
117                 delete fio;
118         }
119 #endif
120 }
121
122 void PCE::reset()
123 {
124         // reset memory bus
125         memset(ram, 0, sizeof(ram));
126         bank = 0x80000;
127         buffer = 0xff;  // ???
128         
129         // reset devices
130         vdc_reset();
131         psg_reset();
132         joy_reset();
133 #ifdef SUPPORT_CDROM
134         cdrom_reset();
135 #endif
136         
137         prev_width = -1;
138 }
139
140 void PCE::event_vline(int v, int clock)
141 {
142 #ifdef SUPPORT_SUPER_GFX
143         if(support_sgfx) {
144                 sgx_interrupt();
145         } else
146 #endif
147         pce_interrupt();
148 }
149
150 void PCE::write_data8(uint32_t addr, uint32_t data)
151 {
152         uint8_t mpr = (addr >> 13) & 0xff;
153         uint16_t ofs = addr & 0x1fff;
154         
155 #ifdef SUPPORT_CDROM
156         if(support_cdrom && mpr >= 0x68 && mpr <= 0x87) {
157                 cdrom_ram[addr & 0x3ffff] = data;
158                 return;
159         }
160 #endif
161         switch(mpr) {
162         case 0x40:
163         case 0x41:
164         case 0x42:
165         case 0x43:
166                 // populous
167                 cart[addr & 0xfffff] = data;
168                 return;
169 #ifdef SUPPORT_BACKUP_RAM
170         case 0xf7:
171                 if(!backup_locked) {
172                         backup[ofs] = data;
173                 }
174                 return;
175 #endif
176         case 0xf8:
177                 ram[ofs] = data;
178                 return;
179 #ifdef SUPPORT_SUPER_GFX
180         case 0xf9:
181         case 0xfa:
182         case 0xfb:
183                 if(support_sgfx) {
184                         ram[addr & 0x7fff] = data;
185                 }
186                 return;
187 #endif
188         case 0xff:
189                 switch(addr & 0x1c00) {
190                 case 0x0000:    // vdc
191 #ifdef SUPPORT_SUPER_GFX
192                         if(support_sgfx) {
193                                 switch(addr & 0x18) {
194                                 case 0x00:
195                                         vdc_w(0, addr, data);
196                                         break;
197                                 case 0x08:
198                                         vpc_w(addr, data);
199                                         break;
200                                 case 0x10:
201                                         vdc_w(1, addr, data);
202                                         break;
203                                 }
204                         } else
205 #endif
206                         vdc_w(0, addr, data);
207                         break;
208                 case 0x0400:    // vce
209                         vce_w(addr, data);
210                         break;
211                 case 0x0800:    // psg
212                         buffer = data;
213                         psg_write(addr, data);
214                         break;
215                 case 0x0c00:    // timer
216                         buffer = data;
217                         d_cpu->timer_w(addr, data);
218                         break;
219                 case 0x1000:    // joypad
220                         buffer = data;
221                         joy_write(addr, data);
222                         break;
223                 case 0x1400:    // interrupt control
224                         buffer = data;
225                         d_cpu->irq_status_w(addr, data);
226                         break;
227 #ifdef SUPPORT_CDROM
228                 case 0x1800:
229                         if(support_cdrom && (addr & 0x1e00) != 0x1a00) {
230                                 cdrom_write(addr, data);
231                                 break;
232                         }
233 #endif
234                 }
235                 return;
236         }
237         // bank switch for sf2d
238         if((addr & 0x1ffc) == 0x1ff0) {
239                 bank = 0x80000 * ((addr & 3) + 1);
240         }
241 }
242
243 uint32_t PCE::read_data8(uint32_t addr)
244 {
245         uint8_t mpr = (addr >> 13) & 0xff;
246         uint16_t ofs = addr & 0x1fff;
247         
248         if(mpr <= 0x3f) {
249                 return cart[addr & 0x7ffff];
250         }
251 #ifdef SUPPORT_CDROM
252         if(support_cdrom && mpr >= 0x68 && mpr <= 0x87) {
253                 return cdrom_ram[addr & 0x3ffff];
254         }
255 #endif
256         if(mpr <= 0x7f) {
257                 return cart[bank | (addr & 0x7ffff)];
258         }
259         switch(mpr) {
260 #ifdef SUPPORT_BACKUP_RAM
261         case 0xf7:
262                 return backup[ofs];
263 #endif
264         case 0xf8:
265                 return ram[ofs];
266 #ifdef SUPPORT_SUPER_GFX
267         case 0xf9:
268         case 0xfa:
269         case 0xfb:
270                 if(support_sgfx) {
271                         return ram[addr & 0x7fff];
272                 }
273                 return 0xff;
274 #endif
275         case 0xff:
276                 switch (addr & 0x1c00) {
277                 case 0x0000: // vdc
278 #ifdef SUPPORT_SUPER_GFX
279                         if(support_sgfx) {
280                                 switch(addr & 0x18) {
281                                 case 0x00:
282                                         return vdc_r(0, addr);
283                                 case 0x08:
284                                         return vpc_r(addr);
285                                 case 0x10:
286                                         return vdc_r(1, addr);
287                                 }
288                                 return 0xff;
289                         } else
290 #endif
291                         return vdc_r(0, addr);
292                 case 0x0400: // vce
293                         return vce_r(addr);
294                 case 0x0800: // psg
295 //                      return psg_read(addr);
296                         return buffer;
297                 case 0x0c00: // timer
298                         buffer = (buffer & 0x80) | (d_cpu->timer_r(addr) & 0x7f);
299                         return buffer;
300                 case 0x1000: // joypad
301                         buffer = (buffer & 0xb0) | (joy_read(addr) & 0x0f);
302                         return buffer;
303                 case 0x1400: // interrupt control
304                         if(addr & 2) {
305                                 buffer = (buffer & 0xf8) | (d_cpu->irq_status_r(addr) & 0x07);
306                         }
307                         return buffer;
308 #ifdef SUPPORT_CDROM
309                 case 0x1800:
310                         if(support_cdrom && (addr & 0x1e00) != 0x1a00) {
311                                 return cdrom_read(addr);
312                         }
313 #endif
314                 }
315                 break;
316         }
317         return 0xff;
318 }
319
320 void PCE::write_io8(uint32_t addr, uint32_t data)
321 {
322 #ifdef SUPPORT_SUPER_GFX
323         if(support_sgfx) {
324                 sgx_vdc_w(addr, data);
325         } else
326 #endif
327         vdc_w(0, addr, data);
328 }
329
330 uint32_t PCE::read_io8(uint32_t addr)
331 {
332 #ifdef SUPPORT_SUPER_GFX
333         if(support_sgfx) {
334                 return sgx_vdc_r(addr);
335         } else
336 #endif
337         return vdc_r(0, addr);
338 }
339
340 void PCE::draw_screen()
341 {
342         int dx = (SCREEN_WIDTH - vdc[0].physical_width) / 2, sx = 0;
343         int dy = (SCREEN_HEIGHT - 240) / 2;
344         
345         if(dx < 0) {
346                 sx = -dx;
347                 dx = 0;
348         }
349 #ifndef _X1TWIN
350         if(prev_width != vdc[0].physical_width) {
351                 for(int y = 0; y < SCREEN_HEIGHT; y++) {
352                         memset(emu->get_screen_buffer(y), 0, sizeof(scrntype_t) * SCREEN_WIDTH);
353                 }
354                 prev_width = vdc[0].physical_width;
355         }
356         emu->set_vm_screen_lines(240);
357 #endif
358         for(int y = 0; y < 240; y++, dy++) {
359                 scrntype_t* src = &vce.bmp[y + 17][86];
360                 scrntype_t* dst = emu->get_screen_buffer(dy);
361                 for(int x = sx, x2 = dx; x < vdc[0].physical_width && x2 < SCREEN_WIDTH; x++, x2++) {
362                         dst[x2] = src[x];
363                 }
364         }
365 }
366
367 void PCE::open_cart(const _TCHAR* file_path)
368 {
369         FILEIO* fio = new FILEIO();
370         
371         support_6btn_pad = ((config.joystick_type & 1) != 0);
372         support_multi_tap = ((config.joystick_type & 2) != 0);
373 #ifdef SUPPORT_SUPER_GFX
374         support_sgfx = false;
375 #endif
376 #ifdef SUPPORT_CDROM
377         support_cdrom = false;
378 #endif
379         
380         if(fio->Fopen(file_path, FILEIO_READ_BINARY)) {
381                 memset(cart, 0xff, sizeof(cart));
382                 fio->Fseek(0, FILEIO_SEEK_END);
383                 int size = fio->Ftell();
384                 int head = size % 1024;
385                 size -= head;
386                 fio->Fseek(head, FILEIO_SEEK_SET);
387                 fio->Fread(cart, size, 1);
388                 fio->Fclose();
389                 
390                 if(size == 512 * 1024) {
391                         bool overdump = true;
392                         for(int i = 0x40000; i < 0x60000; i++) {
393                                 if(cart[i] != cart[i + 0x20000]) {
394                                         overdump = false;
395                                         break;
396                                 }
397                         }
398                         if(overdump) {
399                                 size = 384 * 1024;
400                         }
401                 }
402                 if(size == 384 * 1024) {
403                         memcpy(cart + 0x060000, cart + 0x040000, 0x020000);     /* Set up 060000 - 07FFFF mirror */
404                         memcpy(cart + 0x080000, cart + 0x040000, 0x040000);     /* Set up 080000 - 0BFFFF region */
405                         memcpy(cart + 0x0C0000, cart + 0x040000, 0x040000);     /* Set up 0C0000 - 0FFFFF region */
406                         memcpy(cart + 0x040000, cart, 0x040000);                /* Set up 040000 - 07FFFF region */
407                 } else {
408                         /* mirror 256KB rom data */
409                         if (size <= 0x040000)
410                                 memcpy(cart + 0x040000, cart, 0x040000);
411                         /* mirror 512KB rom data */
412                         if (size <= 0x080000)
413                                 memcpy(cart + 0x080000, cart, 0x080000);
414                 }
415                 uint32_t cart_crc32 = get_crc32(cart, size);
416 #ifdef SUPPORT_SUPER_GFX
417                 if((size == 0x100000 && cart_crc32 == 0x8c4588e2) ||    // 1941 Counter Attack
418                    (size == 0x100000 && cart_crc32 == 0x4c2126b0) ||    // Aldynes
419                    (size == 0x080000 && cart_crc32 == 0x3b13af61) ||    // Battle Ace
420                    (size == 0x100000 && cart_crc32 == 0xb486a8ed) ||    // Daimakaimura
421                    (size == 0x0c0000 && cart_crc32 == 0xbebfe042) ||    // Darius Plus
422                    (size == 0x100000 && cart_crc32 == 0x1e1d0319) ||    // Darius Plus (1024K)
423                    (size == 0x080000 && cart_crc32 == 0x1f041166)) {    // Grandzort
424                         support_sgfx = true;
425                 }
426 #endif
427 #ifdef SUPPORT_CDROM
428                 if(size >= 0x40000 && memcmp(cart + 0x3ffb6, "PC Engine CD-ROM SYSTEM", 23) == 0) {
429                         support_cdrom = true;
430                 }
431 #endif
432                 if((size == 0x280000 && cart_crc32 == 0xd15cb6bb) ||    // Street Fighter II Champion Edition
433                    (size == 0x100000 && cart_crc32 == 0xd6fc51ce)) {    // Strip Figher II
434                         support_6btn_pad = true;
435                 }
436                 if(size == 0x40000 && cart_crc32 == 0x80c3f824) {       // Yokai Dochu Ki
437                         support_multi_tap = false;
438                 }
439                 inserted = true;
440         }
441         delete fio;
442 }
443
444 void PCE::close_cart()
445 {
446         memset(cart, 0xff, sizeof(cart));
447         inserted = false;
448 }
449
450 // vdc
451
452 void PCE::pce_interrupt()
453 {
454         /* Draw the last scanline */
455         if ( vce.current_bitmap_line >= 14 && vce.current_bitmap_line < 14 + 242 )
456         {
457                 /* We are in the active display area */
458                 /* First fill the line with the overscan color */
459                 draw_overscan_line(vce.current_bitmap_line );
460
461                 /* Check if we need to draw more just the overscan color */
462                 if ( vdc[0].current_segment == STATE_VDW )
463                 {
464                         /* 0 - no sprite and background pixels drawn
465                            1 - background pixel drawn
466                            otherwise is 2 + sprite# */
467                         uint8_t drawn[VDC_WPF];
468                         /* our line buffer */
469                         scrntype_t *line_buffer = &vce.bmp[vce.current_bitmap_line][86];
470
471                         /* clear our priority/sprite collision detection buffer. */
472                         memset(drawn, 0, VDC_WPF);
473
474                         vdc[0].y_scroll = ( vdc[0].current_segment_line == 0 ) ? vdc[0].vdc_data[BYR].w.l : ( vdc[0].y_scroll + 1 );
475
476                         /* Draw VDC #0 background layer */
477                         pce_refresh_line(0, vdc[0].current_segment_line, 0, drawn, line_buffer);
478
479                         /* Draw VDC #0 sprite layer */
480                         if(vdc[0].vdc_data[CR].w.l & CR_SB)
481                         {
482                                 pce_refresh_sprites(0, vdc[0].current_segment_line, drawn, line_buffer);
483                         }
484                 }
485         }
486         else
487         {
488                 /* We are in one of the blanking areas */
489                 draw_black_line(vce.current_bitmap_line );
490         }
491
492         /* bump current scanline */
493         vce.current_bitmap_line = ( vce.current_bitmap_line + 1 ) % VDC_LPF;
494         vdc_advance_line(0);
495 }
496
497 #ifdef SUPPORT_SUPER_GFX
498 void PCE::sgx_interrupt()
499 {
500         /* Draw the last scanline */
501         if ( vce.current_bitmap_line >= 14 && vce.current_bitmap_line < 14 + 242 )
502         {
503                 /* We are in the active display area */
504                 /* First fill the line with the overscan color */
505                 draw_sgx_overscan_line(vce.current_bitmap_line );
506
507                 /* Check if we need to draw more just the overscan color */
508                 if ( vdc[0].current_segment == STATE_VDW )
509                 {
510                         /* 0 - no sprite and background pixels drawn
511                            1 - background pixel drawn
512                            otherwise is 2 + sprite# */
513                         uint8_t drawn[2][512];
514                         scrntype_t *line_buffer;
515                         scrntype_t temp_buffer[2][512];
516                         int i;
517
518                         /* clear our priority/sprite collision detection buffer. */
519                         memset( drawn, 0, sizeof(drawn) );
520
521                         vdc[0].y_scroll = ( vdc[0].current_segment_line == 0 ) ? vdc[0].vdc_data[BYR].w.l : ( vdc[0].y_scroll + 1 );
522                         vdc[1].y_scroll = ( vdc[1].current_segment_line == 0 ) ? vdc[1].vdc_data[BYR].w.l : ( vdc[1].y_scroll + 1 );
523
524                         /* Draw VDC #0 background layer */
525                         pce_refresh_line( 0, vdc[0].current_segment_line, 0, drawn[0], temp_buffer[0]);
526
527                         /* Draw VDC #0 sprite layer */
528                         if(vdc[0].vdc_data[CR].w.l & CR_SB)
529                         {
530                                 pce_refresh_sprites(0, vdc[0].current_segment_line, drawn[0], temp_buffer[0]);
531                         }
532
533                         /* Draw VDC #1 background layer */
534                         pce_refresh_line( 1, vdc[1].current_segment_line, 1, drawn[1], temp_buffer[1]);
535
536                         /* Draw VDC #1 sprite layer */
537                         if ( vdc[1].vdc_data[CR].w.l & CR_SB )
538                         {
539                                 pce_refresh_sprites(1, vdc[1].current_segment_line, drawn[1], temp_buffer[1]);
540                         }
541
542                         line_buffer = &vce.bmp[vce.current_bitmap_line][86];
543                         /* Combine the output of both VDCs */
544                         for( i = 0; i < 512; i++ )
545                         {
546                                 int cur_prio = vpc.prio_map[i];
547
548                                 if ( vpc.vpc_prio[cur_prio].vdc0_enabled )
549                                 {
550                                         if ( vpc.vpc_prio[cur_prio].vdc1_enabled )
551                                         {
552                                                 switch( vpc.vpc_prio[cur_prio].prio )
553                                                 {
554                                                 case 0: /* BG1 SP1 BG0 SP0 */
555                                                         if ( drawn[0][i] )
556                                                         {
557                                                                 line_buffer[i] = temp_buffer[0][i];
558                                                         }
559                                                         else if ( drawn[1][i] )
560                                                         {
561                                                                 line_buffer[i] = temp_buffer[1][i];
562                                                         }
563                                                         break;
564                                                 case 1: /* BG1 BG0 SP1 SP0 */
565                                                         if ( drawn[0][i] )
566                                                         {
567                                                                 if ( drawn[0][i] > 1 )
568                                                                 {
569                                                                         line_buffer[i] = temp_buffer[0][i];
570                                                                 }
571                                                                 else
572                                                                 {
573                                                                         if ( drawn[1][i] > 1 )
574                                                                         {
575                                                                                 line_buffer[i] = temp_buffer[1][i];
576                                                                         }
577                                                                         else
578                                                                         {
579                                                                                 line_buffer[i] = temp_buffer[0][i];
580                                                                         }
581                                                                 }
582                                                         }
583                                                         else if ( drawn[1][i] )
584                                                         {
585                                                                 line_buffer[i] = temp_buffer[1][i];
586                                                         }
587                                                         break;
588                                                 case 2: /* BG1 + SP1 => SP1
589                                                            BG0 + SP1 => BG0
590                                                            BG0 + BG1 => BG0
591                                                            BG0 + SP0 => SP0
592                                                            BG1 + SP0 => BG1
593                                                            SP0 + SP1 => SP0 */
594                                                         if ( drawn[0][i] )
595                                                         {
596                                                                 if ( drawn[0][i] > 1 )
597                                                                 {
598                                                                         if ( drawn[1][i] == 1 )
599                                                                         {
600                                                                                 line_buffer[i] = temp_buffer[1][i];
601                                                                         }
602                                                                         else
603                                                                         {
604                                                                                 line_buffer[i] = temp_buffer[0][i];
605                                                                         }
606                                                                 }
607                                                                 else
608                                                                 {
609                                                                         line_buffer[i] = temp_buffer[0][i];
610                                                                 }
611                                                         }
612                                                         else if ( drawn[1][i] )
613                                                         {
614                                                                 line_buffer[i] = temp_buffer[1][i];
615                                                         }
616                                                         break;
617                                                 }
618                                         }
619                                         else
620                                         {
621                                                 if ( drawn[0][i] )
622                                                 {
623                                                         line_buffer[i] = temp_buffer[0][i];
624                                                 }
625                                         }
626                                 }
627                                 else
628                                 {
629                                         if ( vpc.vpc_prio[cur_prio].vdc1_enabled )
630                                         {
631                                                 if ( drawn[1][i] )
632                                                 {
633                                                         line_buffer[i] = temp_buffer[1][i];
634                                                 }
635                                         }
636                                 }
637                         }
638                 }
639         }
640         else
641         {
642                 /* We are in one of the blanking areas */
643                 draw_black_line(vce.current_bitmap_line );
644         }
645
646         /* bump current scanline */
647         vce.current_bitmap_line = ( vce.current_bitmap_line + 1 ) % VDC_LPF;
648         vdc_advance_line(0);
649         vdc_advance_line(1);
650 }
651 #endif
652
653 void PCE::vdc_advance_line(int which)
654 {
655         int ret = 0;
656
657         vdc[which].curline += 1;
658         vdc[which].current_segment_line += 1;
659         vdc[which].raster_count += 1;
660
661         if ( vdc[which].satb_countdown )
662         {
663                 vdc[which].satb_countdown -= 1;
664                 if ( vdc[which].satb_countdown == 0 )
665                 {
666                         if ( vdc[which].vdc_data[DCR].w.l & DCR_DSC )
667                         {
668                                 vdc[which].status |= VDC_DS;    /* set satb done flag */
669                                 ret = 1;
670                         }
671                 }
672         }
673
674         if ( vce.current_bitmap_line == 0 )
675         {
676                 vdc[which].current_segment = STATE_VSW;
677                 vdc[which].current_segment_line = 0;
678                 vdc[which].vblank_triggered = 0;
679                 vdc[which].curline = 0;
680         }
681
682         if ( STATE_VSW == vdc[which].current_segment && vdc[which].current_segment_line >= ( vdc[which].vdc_data[VPR].b.l & 0x1F ) )
683         {
684                 vdc[which].current_segment = STATE_VDS;
685                 vdc[which].current_segment_line = 0;
686         }
687
688         if ( STATE_VDS == vdc[which].current_segment && vdc[which].current_segment_line >= vdc[which].vdc_data[VPR].b.h )
689         {
690                 vdc[which].current_segment = STATE_VDW;
691                 vdc[which].current_segment_line = 0;
692                 vdc[which].raster_count = 0x40;
693         }
694
695         if ( STATE_VDW == vdc[which].current_segment && vdc[which].current_segment_line > ( vdc[which].vdc_data[VDW].w.l & 0x01FF ) )
696         {
697                 vdc[which].current_segment = STATE_VCR;
698                 vdc[which].current_segment_line = 0;
699
700                 /* Generate VBlank interrupt, sprite DMA */
701                 vdc[which].vblank_triggered = 1;
702                 if ( vdc[which].vdc_data[CR].w.l & CR_VR )
703                 {
704                         vdc[which].status |= VDC_VD;
705                         ret = 1;
706                 }
707
708                 /* do VRAM > SATB DMA if the enable bit is set or the DVSSR reg. was written to */
709                 if( ( vdc[which].vdc_data[DCR].w.l & DCR_DSR ) || vdc[which].dvssr_write )
710                 {
711                         int i;
712
713                         vdc[which].dvssr_write = 0;
714
715                         for( i = 0; i < 256; i++ )
716                         {
717                                 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 ];
718                         }
719
720                         /* generate interrupt if needed */
721                         if ( vdc[which].vdc_data[DCR].w.l & DCR_DSC )
722                         {
723                                 vdc[which].satb_countdown = 4;
724                         }
725                 }
726         }
727
728         if ( STATE_VCR == vdc[which].current_segment )
729         {
730                 if ( vdc[which].current_segment_line >= 3 && vdc[which].current_segment_line >= vdc[which].vdc_data[VCR].b.l )
731                 {
732                         vdc[which].current_segment = STATE_VSW;
733                         vdc[which].current_segment_line = 0;
734                         vdc[which].curline = 0;
735                 }
736         }
737
738         /* generate interrupt on line compare if necessary */
739         if ( vdc[which].raster_count == vdc[which].vdc_data[RCR].w.l && vdc[which].vdc_data[CR].w.l & CR_RC )
740         {
741                 vdc[which].status |= VDC_RR;
742                 ret = 1;
743         }
744
745         /* handle frame events */
746         if(vdc[which].curline == 261 && ! vdc[which].vblank_triggered )
747         {
748
749                 vdc[which].vblank_triggered = 1;
750                 if(vdc[which].vdc_data[CR].w.l & CR_VR)
751                 {       /* generate IRQ1 if enabled */
752                         vdc[which].status |= VDC_VD;    /* set vblank flag */
753                         ret = 1;
754                 }
755
756                 /* do VRAM > SATB DMA if the enable bit is set or the DVSSR reg. was written to */
757                 if ( ( vdc[which].vdc_data[DCR].w.l & DCR_DSR ) || vdc[which].dvssr_write )
758                 {
759                         int i;
760
761                         vdc[which].dvssr_write = 0;
762                         for( i = 0; i < 256; i++ )
763                         {
764                                 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 ];
765                         }
766
767                         /* generate interrupt if needed */
768                         if(vdc[which].vdc_data[DCR].w.l & DCR_DSC)
769                         {
770                                 vdc[which].satb_countdown = 4;
771                         }
772                 }
773         }
774
775         if (ret)
776                 d_cpu->write_signal(INPUT_LINE_IRQ1, HOLD_LINE, 0);
777 }
778
779 void PCE::vdc_reset()
780 {
781         /* clear context */
782         memset(&vdc, 0, sizeof(vdc));
783         memset(&vce, 0, sizeof(vce));
784         memset(&vpc, 0, sizeof(vpc));
785
786         vdc[0].inc = 1;
787         vdc[1].inc = 1;
788
789         /* initialize palette */
790         int i;
791
792         for( i = 0; i < 512; i++ )
793         {
794                 int r = (( i >> 3) & 7) << 5;
795                 int g = (( i >> 6) & 7) << 5;
796                 int b = (( i     ) & 7) << 5;
797                 int y = ( (  66 * r + 129 * g +  25 * b + 128) >> 8) +  16;
798                 vce.palette[i] = RGB_COLOR(r, g, b);
799                 vce.palette[512+i] = RGB_COLOR(y, y, y);
800         }
801
802         vpc_w( 0, 0x11 );
803         vpc_w( 1, 0x11 );
804         vpc.window1.w.l = 0;
805         vpc.window2.w.l = 0;
806         vpc.vdc_select = 0;
807 }
808
809 void PCE::draw_black_line(int line)
810 {
811         int i;
812
813         /* our line buffer */
814         scrntype_t *line_buffer = vce.bmp[line];
815
816         for( i=0; i< VDC_WPF; i++ )
817                 line_buffer[i] = 0;
818 }
819
820 void PCE::draw_overscan_line(int line)
821 {
822         int i;
823
824         /* Are we in greyscale mode or in color mode? */
825         scrntype_t *color_base = vce.palette + (vce.vce_control & 0x80 ? 512 : 0);
826
827         /* our line buffer */
828         scrntype_t *line_buffer = vce.bmp[line];
829
830         for ( i = 0; i < VDC_WPF; i++ )
831                 line_buffer[i] = color_base[vce.vce_data[0x100].w.l];
832 }
833
834 #ifdef SUPPORT_SUPER_GFX
835 void PCE::draw_sgx_overscan_line(int line)
836 {
837         int i;
838
839         /* Are we in greyscale mode or in color mode? */
840         scrntype_t *color_base = vce.palette + (vce.vce_control & 0x80 ? 512 : 0);
841
842         /* our line buffer */
843         scrntype_t *line_buffer = vce.bmp[line];
844
845         for ( i = 0; i < VDC_WPF; i++ )
846                 line_buffer[i] = color_base[vce.vce_data[0].w.l];
847 }
848 #endif
849
850 void PCE::vram_write(int which, uint32_t offset, uint8_t data)
851 {
852         if(offset & 0x10000)
853         {
854                 return;
855         }
856         else
857         {
858                 vdc[which].vram[offset] = data;
859         }
860 }
861
862 uint8_t PCE::vram_read(int which, uint32_t offset)
863 {
864         uint8_t temp;
865
866         if(offset & 0x10000)
867         {
868                 temp = vdc[which].vram[offset & 0xFFFF];
869         }
870         else
871         {
872                 temp = vdc[which].vram[offset];
873         }
874
875         return temp;
876 }
877
878 void PCE::vdc_w(int which, uint16_t offset, uint8_t data)
879 {
880         switch(offset&3)
881         {
882                 case 0x00:      /* VDC register select */
883                         vdc[which].vdc_register = (data & 0x1F);
884                         break;
885
886                 case 0x02:      /* VDC data (LSB) */
887                         vdc[which].vdc_data[vdc[which].vdc_register].b.l = data;
888                         switch(vdc[which].vdc_register)
889                         {
890                                 case VxR:       /* LSB of data to write to VRAM */
891                                         vdc[which].vdc_latch = data;
892                                         break;
893
894                                 case BYR:
895                                         vdc[which].y_scroll=vdc[which].vdc_data[BYR].w.l;
896                                         break;
897
898                                 case HDR:
899                                         vdc[which].physical_width = ((data & 0x003F) + 1) << 3;
900                                         break;
901
902                                 case VDW:
903                                         vdc[which].physical_height &= 0xFF00;
904                                         vdc[which].physical_height |= (data & 0xFF);
905                                         vdc[which].physical_height &= 0x01FF;
906                                         break;
907
908                                 case LENR:
909                                         break;
910                                 case SOUR:
911                                         break;
912                                 case DESR:
913                                         break;
914                         }
915                         break;
916
917                 case 0x03:      /* VDC data (MSB) */
918                         vdc[which].vdc_data[vdc[which].vdc_register].b.h = data;
919                         switch(vdc[which].vdc_register)
920                         {
921                                 case VxR:       /* MSB of data to write to VRAM */
922                                         vram_write(which, vdc[which].vdc_data[MAWR].w.l*2+0, vdc[which].vdc_latch);
923                                         vram_write(which, vdc[which].vdc_data[MAWR].w.l*2+1, data);
924                                         vdc[which].vdc_data[MAWR].w.l += vdc[which].inc;
925                                         break;
926
927                                 case CR:
928                                         {
929                                                 static const unsigned char inctab[] = {1, 32, 64, 128};
930                                                 vdc[which].inc = inctab[(data >> 3) & 3];
931                                         }
932                                         break;
933
934                                 case VDW:
935                                         vdc[which].physical_height &= 0x00FF;
936                                         vdc[which].physical_height |= (data << 8);
937                                         vdc[which].physical_height &= 0x01FF;
938                                         break;
939
940                                 case DVSSR:
941                                         /* Force VRAM <> SATB DMA for this frame */
942                                         vdc[which].dvssr_write = 1;
943                                         break;
944
945                                 case BYR:
946                                         vdc[which].y_scroll=vdc[which].vdc_data[BYR].w.l;
947                                         break;
948
949                                 case LENR:
950                                         vdc_do_dma(which);
951                                         break;
952                                 case SOUR:
953                                         break;
954                                 case DESR:
955                                         break;
956                         }
957                         break;
958         }
959 }
960
961 uint8_t PCE::vdc_r(int which, uint16_t offset)
962 {
963         int temp = 0;
964         switch(offset & 3)
965         {
966                 case 0x00:
967                         temp = vdc[which].status;
968                         vdc[which].status &= ~(VDC_VD | VDC_DV | VDC_DS | VDC_RR | VDC_OR | VDC_CR);
969                         d_cpu->write_signal(INPUT_LINE_IRQ1, CLEAR_LINE, 0);
970                         break;
971
972                 case 0x02:
973                         temp = vram_read(which, vdc[which].vdc_data[MARR].w.l * 2 + 0);
974                         break;
975
976                 case 0x03:
977                         temp = vram_read(which, vdc[which].vdc_data[MARR].w.l * 2 + 1);
978                         if ( vdc[which].vdc_register == VxR )
979                         {
980                                 vdc[which].vdc_data[MARR].w.l += vdc[which].inc;
981                         }
982                         break;
983         }
984         return (temp);
985 }
986
987 uint8_t PCE::vce_r(uint16_t offset)
988 {
989         int temp = 0xFF;
990         switch(offset & 7)
991         {
992                 case 0x04:      /* color table data (LSB) */
993                         temp = vce.vce_data[vce.vce_address.w.l].b.l;
994                         break;
995
996                 case 0x05:      /* color table data (MSB) */
997                         temp = vce.vce_data[vce.vce_address.w.l].b.h;
998                         temp |= 0xFE;
999                         vce.vce_address.w.l = (vce.vce_address.w.l + 1) & 0x01FF;
1000                         break;
1001         }
1002         return (temp);
1003 }
1004
1005 void PCE::vce_w(uint16_t offset, uint8_t data)
1006 {
1007         switch(offset & 7)
1008         {
1009                 case 0x00:      /* control reg. */
1010                         vce.vce_control = data;
1011                         break;
1012
1013                 case 0x02:      /* color table address (LSB) */
1014                         vce.vce_address.b.l = data;
1015                         vce.vce_address.w.l &= 0x1FF;
1016                         break;
1017
1018                 case 0x03:      /* color table address (MSB) */
1019                         vce.vce_address.b.h = data;
1020                         vce.vce_address.w.l &= 0x1FF;
1021                         break;
1022
1023                 case 0x04:      /* color table data (LSB) */
1024                         vce.vce_data[vce.vce_address.w.l].b.l = data;
1025                         break;
1026
1027                 case 0x05:      /* color table data (MSB) */
1028                         vce.vce_data[vce.vce_address.w.l].b.h = data & 0x01;
1029
1030                         /* bump internal address */
1031                         vce.vce_address.w.l = (vce.vce_address.w.l + 1) & 0x01FF;
1032                         break;
1033         }
1034 }
1035
1036 void PCE::pce_refresh_line(int which, int line, int external_input, uint8_t *drawn, scrntype_t *line_buffer)
1037 {
1038         static const int width_table[4] = {5, 6, 7, 7};
1039
1040         int scroll_y = ( vdc[which].y_scroll & 0x01FF);
1041         int scroll_x = (vdc[which].vdc_data[BXR].w.l & 0x03FF);
1042         int nt_index;
1043
1044         /* is virtual map 32 or 64 characters tall ? (256 or 512 pixels) */
1045         int v_line = (scroll_y) & (vdc[which].vdc_data[MWR].w.l & 0x0040 ? 0x1FF : 0x0FF);
1046
1047         /* row within character */
1048         int v_row = (v_line & 7);
1049
1050         /* row of characters in BAT */
1051         int nt_row = (v_line >> 3);
1052
1053         /* virtual X size (# bits to shift) */
1054         int v_width = width_table[(vdc[which].vdc_data[MWR].w.l >> 4) & 3];
1055
1056         /* pointer to the name table (Background Attribute Table) in VRAM */
1057         uint8_t *bat = &(vdc[which].vram[nt_row << (v_width+1)]);
1058
1059         /* Are we in greyscale mode or in color mode? */
1060         scrntype_t *color_base = vce.palette + (vce.vce_control & 0x80 ? 512 : 0);
1061
1062         int b0, b1, b2, b3;
1063         int i0, i1, i2, i3;
1064         int cell_pattern_index;
1065         int cell_palette;
1066         int x, c, i;
1067
1068         /* character blanking bit */
1069         if(!(vdc[which].vdc_data[CR].w.l & CR_BB))
1070         {
1071                 return;
1072         }
1073         else
1074         {
1075                 int     pixel = 0;
1076                 int phys_x = - ( scroll_x & 0x07 );
1077
1078                 for(i=0;i<(vdc[which].physical_width >> 3) + 1;i++)
1079                 {
1080                         nt_index = (i + (scroll_x >> 3)) & ((2 << (v_width-1))-1);
1081                         nt_index *= 2;
1082
1083                         /* get name table data: */
1084
1085                         /* palette # = index from 0-15 */
1086                         cell_palette = ( bat[nt_index + 1] >> 4 ) & 0x0F;
1087
1088                         /* This is the 'character number', from 0-0x0FFF         */
1089                         /* then it is shifted left 4 bits to form a VRAM address */
1090                         /* and one more bit to convert VRAM word offset to a     */
1091                         /* byte-offset within the VRAM space                     */
1092                         cell_pattern_index = ( ( ( bat[nt_index + 1] << 8 ) | bat[nt_index] ) & 0x0FFF) << 5;
1093
1094                         b0 = vram_read(which, (cell_pattern_index) + (v_row << 1) + 0x00);
1095                         b1 = vram_read(which, (cell_pattern_index) + (v_row << 1) + 0x01);
1096                         b2 = vram_read(which, (cell_pattern_index) + (v_row << 1) + 0x10);
1097                         b3 = vram_read(which, (cell_pattern_index) + (v_row << 1) + 0x11);
1098
1099                         for(x=0;x<8;x++)
1100                         {
1101                                 i0 = (b0 >> (7-x)) & 1;
1102                                 i1 = (b1 >> (7-x)) & 1;
1103                                 i2 = (b2 >> (7-x)) & 1;
1104                                 i3 = (b3 >> (7-x)) & 1;
1105                                 c = (cell_palette << 4 | i3 << 3 | i2 << 2 | i1 << 1 | i0);
1106
1107                                 /* colour #0 always comes from palette #0 */
1108                                 if ( ! ( c & 0x0F ) )
1109                                         c &= 0x0F;
1110
1111                                 if ( phys_x >= 0 && phys_x < vdc[which].physical_width )
1112                                 {
1113                                         drawn[ pixel ] = c ? 1 : 0;
1114                                         if ( c || ! external_input )
1115                                                 line_buffer[ pixel ] = color_base[vce.vce_data[c].w.l];
1116                                         pixel++;
1117 //                                      if ( vdc[which].physical_width != 512 )
1118 //                                      {
1119 //                                              while ( pixel < ( ( ( phys_x + 1 ) * 512 ) / vdc[which].physical_width ) )
1120 //                                              {
1121 //                                                      drawn[ pixel ] = c ? 1 : 0;
1122 //                                                      if ( c || ! external_input )
1123 //                                                      line_buffer[ pixel ] = color_base[vce.vce_data[c].w.l];
1124 //                                                      pixel++;
1125 //                                              }
1126 //                                      }
1127                                 }
1128                                 phys_x += 1;
1129                         }
1130                 }
1131         }
1132 }
1133
1134 void PCE::conv_obj(int which, int i, int l, int hf, int vf, char *buf)
1135 {
1136         int b0, b1, b2, b3, i0, i1, i2, i3, x;
1137         int xi;
1138         int tmp;
1139
1140         l &= 0x0F;
1141         if(vf) l = (15 - l);
1142
1143         tmp = l + ( i << 5);
1144
1145         b0 = vram_read(which, (tmp + 0x00)<<1);
1146         b0 |= vram_read(which, ((tmp + 0x00)<<1)+1)<<8;
1147         b1 = vram_read(which, (tmp + 0x10)<<1);
1148         b1 |= vram_read(which, ((tmp + 0x10)<<1)+1)<<8;
1149         b2 = vram_read(which, (tmp + 0x20)<<1);
1150         b2 |= vram_read(which, ((tmp + 0x20)<<1)+1)<<8;
1151         b3 = vram_read(which, (tmp + 0x30)<<1);
1152         b3 |= vram_read(which, ((tmp + 0x30)<<1)+1)<<8;
1153
1154         for(x=0;x<16;x++)
1155         {
1156                 if(hf) xi = x; else xi = (15 - x);
1157                 i0 = (b0 >> xi) & 1;
1158                 i1 = (b1 >> xi) & 1;
1159                 i2 = (b2 >> xi) & 1;
1160                 i3 = (b3 >> xi) & 1;
1161                 buf[x] = (i3 << 3 | i2 << 2 | i1 << 1 | i0);
1162         }
1163 }
1164
1165 void PCE::pce_refresh_sprites(int which, int line, uint8_t *drawn, scrntype_t *line_buffer)
1166 {
1167         int i;
1168         uint8_t sprites_drawn = 0;
1169
1170         /* Are we in greyscale mode or in color mode? */
1171         scrntype_t *color_base = vce.palette + (vce.vce_control & 0x80 ? 512 : 0);
1172
1173         /* count up: Highest priority is Sprite 0 */
1174         for(i = 0; i < 64; i++)
1175         {
1176                 static const int cgy_table[] = {16, 32, 64, 64};
1177
1178                 int obj_y = (vdc[which].sprite_ram[(i << 2) + 0] & 0x03FF) - 64;
1179                 int obj_x = (vdc[which].sprite_ram[(i << 2) + 1] & 0x03FF) - 32;
1180                 int obj_i = (vdc[which].sprite_ram[(i << 2) + 2] & 0x07FE);
1181                 int obj_a = (vdc[which].sprite_ram[(i << 2) + 3]);
1182                 int cgx   = (obj_a >> 8) & 1;   /* sprite width */
1183                 int cgy   = (obj_a >> 12) & 3;  /* sprite height */
1184                 int hf    = (obj_a >> 11) & 1;  /* horizontal flip */
1185                 int vf    = (obj_a >> 15) & 1;  /* vertical flip */
1186                 int palette = (obj_a & 0x000F);
1187                 int priority = (obj_a >> 7) & 1;
1188                 int obj_h = cgy_table[cgy];
1189                 int obj_l = (line - obj_y);
1190                 int cgypos;
1191                 char buf[16];
1192
1193                 if ((obj_y == -64) || (obj_y > line)) continue;
1194                 if ((obj_x == -32) || (obj_x >= vdc[which].physical_width)) continue;
1195
1196                 /* no need to draw an object that's ABOVE where we are. */
1197                 if((obj_y + obj_h) < line) continue;
1198
1199                 /* If CGX is set, bit 0 of sprite pattern index is forced to 0 */
1200                 if ( cgx )
1201                         obj_i &= ~2;
1202
1203                 /* If CGY is set to 1, bit 1 of the sprite pattern index is forced to 0. */
1204                 if ( cgy & 1 )
1205                         obj_i &= ~4;
1206
1207                 /* If CGY is set to 2 or 3, bit 1 and 2 of the sprite pattern index are forced to 0. */
1208                 if ( cgy & 2 )
1209                         obj_i &= ~12;
1210
1211                 if (obj_l < obj_h)
1212                 {
1213
1214                         sprites_drawn++;
1215                         if(sprites_drawn > 16)
1216                         {
1217                                 if(vdc[which].vdc_data[CR].w.l & CR_OV)
1218                                 {
1219                                         /* note: flag is set only if irq is taken, Mizubaku Daibouken relies on this behaviour */
1220                                         vdc[which].status |= VDC_OR;
1221                                         d_cpu->write_signal(INPUT_LINE_IRQ1, ASSERT_LINE, 0);
1222                                 }
1223                                 continue;  /* Should cause an interrupt */
1224                         }
1225
1226                         cgypos = (obj_l >> 4);
1227                         if(vf) cgypos = ((obj_h - 1) >> 4) - cgypos;
1228
1229                         if(cgx == 0)
1230                         {
1231                                 int x;
1232                                 int pixel_x = obj_x;//( ( obj_x * 512 ) / vdc[which].physical_width );
1233
1234                                 conv_obj(which, obj_i + (cgypos << 2), obj_l, hf, vf, buf);
1235
1236                                 for(x = 0; x < 16; x++)
1237                                 {
1238                                         if(((obj_x + x) < (vdc[which].physical_width)) && ((obj_x + x) >= 0))
1239                                         {
1240                                                 if ( buf[x] )
1241                                                 {
1242                                                         if( drawn[pixel_x] < 2 )
1243                                                         {
1244                                                                 if( priority || drawn[pixel_x] == 0 )
1245                                                                 {
1246                                                                         line_buffer[pixel_x] = color_base[vce.vce_data[0x100 + (palette << 4) + buf[x]].w.l];
1247 //                                                                      if ( vdc[which].physical_width != 512 )
1248 //                                                                      {
1249 //                                                                              int dp = 1;
1250 //                                                                              while ( pixel_x + dp < ( ( ( obj_x + x + 1 ) * 512 ) / vdc[which].physical_width ) )
1251 //                                                                              {
1252 //                                                                                      drawn[pixel_x + dp] = i + 2;
1253 //                                                                                      line_buffer[pixel_x + dp] = color_base[vce.vce_data[0x100 + (palette << 4) + buf[x]].w.l];
1254 //                                                                                      dp++;
1255 //                                                                              }
1256 //                                                                      }
1257                                                                 }
1258                                                                 drawn[pixel_x] = i + 2;
1259                                                         }
1260                                                         /* Check for sprite #0 collision */
1261                                                         else if (drawn[pixel_x] == 2)
1262                                                         {
1263                                                                 if(vdc[which].vdc_data[CR].w.l & CR_CC)
1264                                                                         d_cpu->write_signal(INPUT_LINE_IRQ1, ASSERT_LINE, 0);
1265                                                                 vdc[which].status |= VDC_CR;
1266                                                         }
1267                                                 }
1268                                         }
1269 //                                      if ( vdc[which].physical_width != 512 )
1270 //                                      {
1271 //                                              pixel_x = ( ( obj_x + x + 1 ) * 512 ) / vdc[which].physical_width;
1272 //                                      }
1273 //                                      else
1274 //                                      {
1275                                                 pixel_x += 1;
1276 //                                      }
1277                                 }
1278                         }
1279                         else
1280                         {
1281                                 int x;
1282                                 int pixel_x = obj_x;//( ( obj_x * 512 ) / vdc[which].physical_width );
1283
1284                                 conv_obj(which, obj_i + (cgypos << 2) + (hf ? 2 : 0), obj_l, hf, vf, buf);
1285
1286                                 for(x = 0; x < 16; x++)
1287                                 {
1288                                         if(((obj_x + x) < (vdc[which].physical_width)) && ((obj_x + x) >= 0))
1289                                         {
1290                                                 if ( buf[x] )
1291                                                 {
1292                                                         if( drawn[pixel_x] < 2 )
1293                                                         {
1294                                                                 if ( priority || drawn[pixel_x] == 0 )
1295                                                                 {
1296                                                                         line_buffer[pixel_x] = color_base[vce.vce_data[0x100 + (palette << 4) + buf[x]].w.l];
1297 //                                                                      if ( vdc[which].physical_width != 512 )
1298 //                                                                      {
1299 //                                                                              int dp = 1;
1300 //                                                                              while ( pixel_x + dp < ( ( ( obj_x + x + 1 ) * 512 ) / vdc[which].physical_width ) )
1301 //                                                                              {
1302 //                                                                                      drawn[pixel_x + dp] = i + 2;
1303 //                                                                                      line_buffer[pixel_x + dp] = color_base[vce.vce_data[0x100 + (palette << 4) + buf[x]].w.l];
1304 //                                                                                      dp++;
1305 //                                                                              }
1306 //                                                                      }
1307                                                                 }
1308                                                                 drawn[pixel_x] = i + 2;
1309                                                         }
1310                                                         /* Check for sprite #0 collision */
1311                                                         else if ( drawn[pixel_x] == 2 )
1312                                                         {
1313                                                                 if(vdc[which].vdc_data[CR].w.l & CR_CC)
1314                                                                         d_cpu->write_signal(INPUT_LINE_IRQ1, ASSERT_LINE, 0);
1315                                                                 vdc[which].status |= VDC_CR;
1316                                                         }
1317                                                 }
1318                                         }
1319 //                                      if ( vdc[which].physical_width != 512 )
1320 //                                      {
1321 //                                              pixel_x = ( ( obj_x + x + 1 ) * 512 ) / vdc[which].physical_width;
1322 //                                      }
1323 //                                      else
1324 //                                      {
1325                                                 pixel_x += 1;
1326 //                                      }
1327                                 }
1328
1329                                 /* 32 pixel wide sprites are counted as 2 sprites and the right half
1330                                    is only drawn if there are 2 open slots.
1331                                 */
1332                                 sprites_drawn++;
1333                                 if( sprites_drawn > 16 )
1334                                 {
1335                                         if(vdc[which].vdc_data[CR].w.l&CR_OV)
1336                                         {
1337                                                 /* note: flag is set only if irq is taken, Mizubaku Daibouken relies on this behaviour */
1338                                                 vdc[which].status |= VDC_OR;
1339                                                 d_cpu->write_signal(INPUT_LINE_IRQ1, ASSERT_LINE, 0);
1340                                         }
1341                                 }
1342                                 else
1343                                 {
1344                                         conv_obj(which, obj_i + (cgypos << 2) + (hf ? 0 : 2), obj_l, hf, vf, buf);
1345                                         for(x = 0; x < 16; x++)
1346                                         {
1347                                                 if(((obj_x + 0x10 + x) < (vdc[which].physical_width)) && ((obj_x + 0x10 + x) >= 0))
1348                                                 {
1349                                                         if ( buf[x] )
1350                                                         {
1351                                                                 if( drawn[pixel_x] < 2 )
1352                                                                 {
1353                                                                         if( priority || drawn[pixel_x] == 0 )
1354                                                                         {
1355                                                                                 line_buffer[pixel_x] = color_base[vce.vce_data[0x100 + (palette << 4) + buf[x]].w.l];
1356 //                                                                              if ( vdc[which].physical_width != 512 )
1357 //                                                                              {
1358 //                                                                                      int dp = 1;
1359 //                                                                                      while ( pixel_x + dp < ( ( ( obj_x + x + 17 ) * 512 ) / vdc[which].physical_width ) )
1360 //                                                                                      {
1361 //                                                                                              drawn[pixel_x + dp] = i + 2;
1362 //                                                                                              line_buffer[pixel_x + dp] = color_base[vce.vce_data[0x100 + (palette << 4) + buf[x]].w.l];
1363 //                                                                                              dp++;
1364 //                                                                                      }
1365 //                                                                              }
1366                                                                         }
1367                                                                         drawn[pixel_x] = i + 2;
1368                                                                 }
1369                                                                 /* Check for sprite #0 collision */
1370                                                                 else if ( drawn[pixel_x] == 2 )
1371                                                                 {
1372                                                                         if(vdc[which].vdc_data[CR].w.l & CR_CC)
1373                                                                                 d_cpu->write_signal(INPUT_LINE_IRQ1, ASSERT_LINE, 0);
1374                                                                         vdc[which].status |= VDC_CR;
1375                                                                 }
1376                                                         }
1377                                                 }
1378 //                                              if ( vdc[which].physical_width != 512 )
1379 //                                              {
1380 //                                                      pixel_x = ( ( obj_x + x + 17 ) * 512 ) / vdc[which].physical_width;
1381 //                                              }
1382 //                                              else
1383 //                                              {
1384                                                         pixel_x += 1;
1385 //                                              }
1386                                         }
1387                                 }
1388                         }
1389                 }
1390         }
1391 }
1392
1393 void PCE::vdc_do_dma(int which)
1394 {
1395         int src = vdc[which].vdc_data[SOUR].w.l;
1396         int dst = vdc[which].vdc_data[DESR].w.l;
1397         int len = vdc[which].vdc_data[LENR].w.l;
1398
1399         int did = (vdc[which].vdc_data[DCR].w.l >> 3) & 1;
1400         int sid = (vdc[which].vdc_data[DCR].w.l >> 2) & 1;
1401         int dvc = (vdc[which].vdc_data[DCR].w.l >> 1) & 1;
1402
1403         do {
1404                 uint8_t l, h;
1405
1406                 l = vram_read(which, src<<1);
1407                 h = vram_read(which, (src<<1) + 1);
1408
1409                 vram_write(which, dst<<1,l);
1410                 vram_write(which, 1+(dst<<1),h);
1411
1412                 if(sid) src = (src - 1) & 0xFFFF;
1413                 else    src = (src + 1) & 0xFFFF;
1414
1415                 if(did) dst = (dst - 1) & 0xFFFF;
1416                 else    dst = (dst + 1) & 0xFFFF;
1417
1418                 len = (len - 1) & 0xFFFF;
1419
1420         } while (len != 0xFFFF);
1421
1422         vdc[which].status |= VDC_DV;
1423         vdc[which].vdc_data[SOUR].w.l = src;
1424         vdc[which].vdc_data[DESR].w.l = dst;
1425         vdc[which].vdc_data[LENR].w.l = len;
1426         if(dvc)
1427         {
1428                 d_cpu->write_signal(INPUT_LINE_IRQ1, ASSERT_LINE, 0);
1429         }
1430
1431 }
1432
1433 void PCE::vpc_update_prio_map()
1434 {
1435         int i;
1436
1437         for( i = 0; i < 512; i++ )
1438         {
1439                 vpc.prio_map[i] = 0;
1440                 if ( vpc.window1.w.l < 0x40 || i > vpc.window1.w.l )
1441                 {
1442                         vpc.prio_map[i] |= 1;
1443                 }
1444                 if ( vpc.window2.w.l < 0x40 || i > vpc.window2.w.l )
1445                 {
1446                         vpc.prio_map[i] |= 2;
1447                 }
1448         }
1449 }
1450
1451 void PCE::vpc_w(uint16_t offset, uint8_t data)
1452 {
1453         switch( offset & 0x07 )
1454         {
1455         case 0x00:      /* Priority register #0 */
1456                 vpc.priority.b.l = data;
1457                 vpc.vpc_prio[0].prio = ( data >> 2 ) & 3;
1458                 vpc.vpc_prio[0].vdc0_enabled = data & 1;
1459                 vpc.vpc_prio[0].vdc1_enabled = data & 2;
1460                 vpc.vpc_prio[1].prio = ( data >> 6 ) & 3;
1461                 vpc.vpc_prio[1].vdc0_enabled = data & 0x10;
1462                 vpc.vpc_prio[1].vdc1_enabled = data & 0x20;
1463                 break;
1464         case 0x01:      /* Priority register #1 */
1465                 vpc.priority.b.h = data;
1466                 vpc.vpc_prio[2].prio = ( data >> 2 ) & 3;
1467                 vpc.vpc_prio[2].vdc0_enabled = data & 1;
1468                 vpc.vpc_prio[2].vdc1_enabled = data & 2;
1469                 vpc.vpc_prio[3].prio = ( data >> 6 ) & 3;
1470                 vpc.vpc_prio[3].vdc0_enabled = data & 0x10;
1471                 vpc.vpc_prio[3].vdc1_enabled = data & 0x20;
1472                 break;
1473         case 0x02:      /* Window 1 LSB */
1474                 vpc.window1.b.l = data;
1475                 vpc_update_prio_map();
1476                 break;
1477         case 0x03:      /* Window 1 MSB */
1478                 vpc.window1.b.h = data & 3;
1479                 vpc_update_prio_map();
1480                 break;
1481         case 0x04:      /* Window 2 LSB */
1482                 vpc.window2.b.l = data;
1483                 vpc_update_prio_map();
1484                 break;
1485         case 0x05:      /* Window 2 MSB */
1486                 vpc.window2.b.h = data & 3;
1487                 vpc_update_prio_map();
1488                 break;
1489         case 0x06:      /* VDC I/O select */
1490                 vpc.vdc_select = data & 1;
1491                 break;
1492         }
1493 }
1494
1495 uint8_t PCE::vpc_r(uint16_t offset)
1496 {
1497         uint8_t data = 0;
1498         switch( offset & 0x07 )
1499         {
1500         case 0x00:  /* Priority register #0 */
1501                 data = vpc.priority.b.l;
1502                 break;
1503         case 0x01:  /* Priority register #1 */
1504                 data = vpc.priority.b.h;
1505                 break;
1506         case 0x02:  /* Window 1 LSB */
1507                 data = vpc.window1.b.l;
1508                 break;
1509         case 0x03:  /* Window 1 MSB; high bits are 0 or 1? */
1510                 data = vpc.window1.b.h;
1511                 break;
1512         case 0x04:  /* Window 2 LSB */
1513                 data = vpc.window2.b.l;
1514                 break;
1515         case 0x05:  /* Window 2 MSB; high bits are 0 or 1? */
1516                 data = vpc.window2.b.h;
1517                 break;
1518         }
1519         return data;
1520 }
1521
1522 #ifdef SUPPORT_SUPER_GFX
1523 void PCE::sgx_vdc_w(uint16_t offset, uint8_t data)
1524 {
1525         if ( vpc.vdc_select )
1526         {
1527                 vdc_w( 1, offset, data );
1528         }
1529         else
1530         {
1531                 vdc_w( 0, offset, data );
1532         }
1533 }
1534
1535 uint8_t PCE::sgx_vdc_r(uint16_t offset)
1536 {
1537         return ( vpc.vdc_select ) ? vdc_r( 1, offset ) : vdc_r( 0, offset );
1538 }
1539 #endif
1540
1541 // psg
1542
1543 void PCE::psg_reset()
1544 {
1545         touch_sound();
1546         memset(psg, 0, sizeof(psg));
1547         for (int i = 0; i < 6; i++) {
1548                 psg[i].regs[4] = 0x80;
1549         }
1550         psg[4].randval = psg[5].randval = 0x51f631e4;
1551         
1552         psg_ch = 0;
1553         psg_vol = psg_lfo_freq = psg_lfo_ctrl = 0;
1554 }
1555
1556 void PCE::psg_write(uint16_t addr, uint8_t data)
1557 {
1558         switch(addr & 0x1f) {
1559         case 0:
1560                 touch_sound();
1561                 psg_ch = data & 7;
1562                 break;
1563         case 1:
1564                 touch_sound();
1565                 psg_vol = data;
1566                 break;
1567         case 2:
1568                 touch_sound();
1569                 psg[psg_ch].regs[2] = data;
1570                 break;
1571         case 3:
1572                 touch_sound();
1573 //              psg[psg_ch].regs[3] = data & 0x1f;
1574                 psg[psg_ch].regs[3] = data & 0xf;
1575                 break;
1576         case 4:
1577                 touch_sound();
1578                 psg[psg_ch].regs[4] = data;
1579                 break;
1580         case 5:
1581                 touch_sound();
1582                 psg[psg_ch].regs[5] = data;
1583                 break;
1584         case 6:
1585                 touch_sound();
1586                 if(psg[psg_ch].regs[4] & 0x40) {
1587                         psg[psg_ch].wav[0] =data & 0x1f;
1588                 }
1589                 else {
1590                         psg[psg_ch].wav[psg[psg_ch].wavptr] = data & 0x1f;
1591                         psg[psg_ch].wavptr = (psg[psg_ch].wavptr + 1) & 0x1f;
1592                 }
1593                 break;
1594         case 7:
1595                 touch_sound();
1596                 psg[psg_ch].regs[7] = data;
1597                 break;
1598         case 8:
1599                 touch_sound();
1600                 psg_lfo_freq = data;
1601                 break;
1602         case 9:
1603                 touch_sound();
1604                 psg_lfo_ctrl = data;
1605                 break;
1606         }
1607 }
1608
1609 uint8_t PCE::psg_read(uint16_t addr)
1610 {
1611         int ptr;
1612         
1613         switch(addr & 0x1f) {
1614         case 0:
1615                 return psg_ch;
1616         case 1:
1617                 return psg_vol;
1618         case 2:
1619                 return psg[psg_ch].regs[2];
1620         case 3:
1621                 return psg[psg_ch].regs[3];
1622         case 4:
1623                 return psg[psg_ch].regs[4];
1624         case 5:
1625                 return psg[psg_ch].regs[5];
1626         case 6:
1627                 ptr = psg[psg_ch].wavptr;
1628                 psg[psg_ch].wavptr = (psg[psg_ch].wavptr + 1) & 0x1f;
1629                 return psg[psg_ch].wav[ptr];
1630         case 7:
1631                 return psg[psg_ch].regs[7];
1632         case 8:
1633                 return psg_lfo_freq;
1634         case 9:
1635                 return psg_lfo_ctrl;
1636         }
1637         return 0xff;
1638 }
1639
1640 void PCE::mix(int32_t* buffer, int cnt)
1641 {
1642         int vol_tbl[32] = {
1643                  100, 451, 508, 573, 646, 728, 821, 925,1043,1175,1325, 1493, 1683, 1898, 2139, 2411,
1644                 2718,3064,3454,3893,4388,4947,5576,6285,7085,7986,9002,10148,11439,12894,14535,16384
1645         };
1646         
1647         if(!inserted) {
1648                 return;
1649         }
1650         for(int ch = 0; ch < 6; ch++) {
1651                 if(!(psg[ch].regs[4] & 0x80)) {
1652                         // mute
1653                         psg[ch].genptr = psg[ch].remain = 0;
1654                 }
1655                 else if(psg[ch].regs[4] & 0x40) {
1656                         // dda
1657                         int32_t wav = ((int32_t)psg[ch].wav[0] - 16) * 702;
1658                         int32_t 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;
1659                         vol = (vol < 0) ? 0 : (vol > 31) ? 31 : vol;
1660                         int32_t outvol = wav * vol_tbl[vol] / 16384;
1661                         for(int i = 0, j = 0; i < cnt; i++, j += 2) {
1662                                 buffer[j    ] += apply_volume(outvol, volume_l); // L
1663                                 buffer[j + 1] += apply_volume(outvol, volume_r); // R
1664                         }
1665                 }
1666                 else if(ch >= 4 && (psg[ch].regs[7] & 0x80)) {
1667                         // noise
1668                         uint16_t freq = (psg[ch].regs[7] & 0x1f);
1669                         int32_t 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;
1670                         vol = (vol < 0) ? 0 : (vol > 31) ? 31 : vol;
1671                         vol = vol_tbl[vol];
1672                         for(int i = 0, j = 0; i < cnt; i++, j += 2) {
1673                                 psg[ch].remain += 3000 + freq * 512;
1674                                 uint32_t t = psg[ch].remain / sample_rate;
1675                                 if(t >= 1) {
1676                                         if(psg[ch].randval & 0x80000) {
1677                                                 psg[ch].randval = ((psg[ch].randval ^ 4) << 1) + 1;
1678                                                 psg[ch].noise = true;
1679                                         }
1680                                         else {
1681                                                 psg[ch].randval <<= 1;
1682                                                 psg[ch].noise = false;
1683                                         }
1684                                         psg[ch].remain -= sample_rate * t;
1685                                 }
1686                                 int32_t outvol = (int32_t)((psg[ch].noise ? 10 * 702 : -10 * 702) * vol / 16384);
1687                                 buffer[j    ] += apply_volume(outvol, volume_l); // L
1688                                 buffer[j + 1] += apply_volume(outvol, volume_r); // R
1689                         }
1690                 }
1691                 else {
1692                         int32_t wav[32];
1693                         for(int i = 0; i < 32; i++) {
1694                                 wav[i] = ((int32_t)psg[ch].wav[i] - 16) * 702;
1695                         }
1696                         uint32_t freq = psg[ch].regs[2] + ((uint32_t)psg[ch].regs[3] << 8);
1697                         if(freq) {
1698                                 int32_t 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;
1699                                 vol = (vol < 0) ? 0 : (vol > 31) ? 31 : vol;
1700                                 vol = vol_tbl[vol];
1701                                 for(int i = 0, j = 0; i < cnt; i++, j += 2) {
1702                                         int32_t outvol = wav[psg[ch].genptr] * vol / 16384;
1703                                         buffer[j    ] += apply_volume(outvol, volume_l); // L
1704                                         buffer[j + 1] += apply_volume(outvol, volume_r); // R
1705                                         psg[ch].remain += 32 * 1118608 / freq;
1706                                         uint32_t t = psg[ch].remain / (10 * sample_rate);
1707                                         psg[ch].genptr = (psg[ch].genptr + t) & 0x1f;
1708                                         psg[ch].remain -= 10 * sample_rate * t;
1709                                 }
1710                         }
1711                 }
1712         }
1713 #ifdef SUPPORT_CDROM
1714         if(support_cdrom) {
1715                 if(!msm_idle) {
1716                         d_msm->mix(buffer, cnt);
1717                 }
1718                 d_scsi_cdrom->mix(buffer, cnt);
1719         }
1720 #endif
1721 }
1722
1723 void PCE::set_volume(int ch, int decibel_l, int decibel_r)
1724 {
1725         volume_l = decibel_to_volume(decibel_l);
1726         volume_r = decibel_to_volume(decibel_r);
1727 }
1728
1729 // joypad (non multipad)
1730
1731 void PCE::joy_reset()
1732 {
1733         joy_counter = 0;
1734         joy_high_nibble = joy_second_byte = false;
1735 }
1736
1737 void PCE::joy_write(uint16_t addr, uint8_t data)
1738 {
1739         joy_high_nibble = ((data & 1) != 0);
1740         
1741         if(data & 2) {
1742                 joy_counter = 0;
1743                 joy_high_nibble = false;
1744                 joy_second_byte = !joy_second_byte;
1745         }
1746 }
1747
1748 uint8_t PCE::joy_read(uint16_t addr)
1749 {
1750         uint8_t index;
1751         
1752         if(joy_high_nibble) {
1753                 if(++joy_counter == 16) {
1754                         joy_counter = 0;
1755                 }
1756         }
1757         if(joy_counter == 0) {
1758                 return 0x00;
1759         }
1760         if(support_multi_tap) {
1761                 if(joy_counter > 4) {
1762                         return 0x0f;
1763                 }
1764                 index = joy_counter;
1765         } else {
1766                 index = 1;
1767         }
1768         if(support_6btn_pad) {
1769                 return joy_6btn_pad_r(index);
1770         } else {
1771                 return joy_2btn_pad_r(index);
1772         }
1773 }
1774
1775 uint8_t PCE::joy_2btn_pad_r(uint8_t index)
1776 {
1777         uint8_t data = 0x0f;
1778         
1779         if(joy_high_nibble) {
1780                 if(joy_stat[index - 1] & 0x001) data &= ~0x01;  // Up
1781                 if(joy_stat[index - 1] & 0x008) data &= ~0x02;  // Right
1782                 if(joy_stat[index - 1] & 0x002) data &= ~0x04;  // Down
1783                 if(joy_stat[index - 1] & 0x004) data &= ~0x08;  // Left
1784         } else {
1785                 if(joy_stat[index - 1] & 0x010) data &= ~0x01;  // Button #1
1786                 if(joy_stat[index - 1] & 0x020) data &= ~0x02;  // Button #2
1787                 if(joy_stat[index - 1] & 0x040) data &= ~0x04;  // Select
1788                 if(joy_stat[index - 1] & 0x080) data &= ~0x08;  // Run
1789         }
1790         return data;
1791 }
1792
1793 uint8_t PCE::joy_6btn_pad_r(uint8_t index)
1794 {
1795         uint8_t data = 0x0f;
1796         
1797         if(joy_second_byte) {
1798                 if(joy_high_nibble) {
1799                         if(joy_stat[index - 1] & 0x001) data &= ~0x01;  // Up
1800                         if(joy_stat[index - 1] & 0x008) data &= ~0x02;  // Right
1801                         if(joy_stat[index - 1] & 0x002) data &= ~0x04;  // Down
1802                         if(joy_stat[index - 1] & 0x004) data &= ~0x08;  // Left
1803                 } else {
1804                         if(joy_stat[index - 1] & 0x010) data &= ~0x01;  // Button #1
1805                         if(joy_stat[index - 1] & 0x020) data &= ~0x02;  // Button #2
1806                         if(joy_stat[index - 1] & 0x040) data &= ~0x04;  // Select
1807                         if(joy_stat[index - 1] & 0x080) data &= ~0x08;  // Run
1808                 }
1809         } else {
1810                 if(joy_high_nibble) {
1811                         return 0x00;
1812                 } else {
1813                         if(joy_stat[index - 1] & 0x100) data &= ~0x01;  // Button #3
1814                         if(joy_stat[index - 1] & 0x200) data &= ~0x02;  // Button #4
1815                         if(joy_stat[index - 1] & 0x400) data &= ~0x04;  // Button #5
1816                         if(joy_stat[index - 1] & 0x800) data &= ~0x08;  // Button #6
1817                 }
1818         }
1819         if(!support_multi_tap) {
1820                 if(joy_counter == 5 && !joy_high_nibble) {
1821                         joy_second_byte = false;
1822                 }
1823         }
1824         return data;
1825 }
1826
1827 // CD-ROM^2
1828
1829 #ifdef SUPPORT_CDROM
1830 #define PCE_CD_IRQ_TRANSFER_READY       0x40
1831 #define PCE_CD_IRQ_TRANSFER_DONE        0x20
1832 #define PCE_CD_IRQ_BRAM                 0x10 /* ??? */
1833 #define PCE_CD_IRQ_SAMPLE_FULL_PLAY     0x08
1834 #define PCE_CD_IRQ_SAMPLE_HALF_PLAY     0x04
1835
1836 #define PCE_CD_ADPCM_PLAY_FLAG          0x08
1837 #define PCE_CD_ADPCM_STOP_FLAG          0x01
1838
1839 #define EVENT_CDDA_FADE_IN              0
1840 #define EVENT_CDDA_FADE_OUT             1
1841 #define EVENT_ADPCM_FADE_IN             2
1842 #define EVENT_ADPCM_FADE_OUT            3
1843
1844 void PCE::cdrom_initialize()
1845 {
1846         adpcm_clock_divider = 1;
1847         backup_locked = true;
1848         event_cdda_fader = event_adpcm_fader = -1;
1849 }
1850
1851 void PCE::cdrom_reset()
1852 {
1853         touch_sound();
1854         memset(cdrom_regs, 0, sizeof(cdrom_regs));
1855         cdrom_regs[0x0c] |= PCE_CD_ADPCM_STOP_FLAG;
1856         cdrom_regs[0x0c] &= ~PCE_CD_ADPCM_PLAY_FLAG;
1857         
1858         irq_status = drq_status = false;
1859         
1860         adpcm_read_ptr = adpcm_write_ptr = 0;
1861         adpcm_read_buf = adpcm_write_buf = 0;
1862         adpcm_dma_enabled = false;
1863         msm_idle = 1;
1864         
1865         if(event_cdda_fader != -1) {
1866                 cancel_event(this, event_cdda_fader);
1867         }
1868         if(event_adpcm_fader != -1) {
1869                 cancel_event(this, event_adpcm_fader);
1870         }
1871         cdda_volume = adpcm_volume = 100.0;
1872         event_cdda_fader = event_adpcm_fader = -1;
1873         
1874         d_scsi_cdrom->set_volume((int)cdda_volume);
1875         d_msm->set_volume((int)adpcm_volume);
1876 }
1877
1878 void PCE::cdrom_write(uint16_t addr, uint8_t data)
1879 {
1880         touch_sound();
1881         switch(addr & 0x0f) {
1882         case 0x00:  /* CDC status */
1883                 d_scsi_host->write_signal(SIG_SCSI_SEL, 1, 1);
1884                 d_scsi_host->write_signal(SIG_SCSI_SEL, 0, 1);
1885                 adpcm_dma_enabled = false;
1886                 set_cdrom_irq_line(0x70, CLEAR_LINE);
1887                 break;
1888                 
1889         case 0x01:  /* CDC command / status / data */
1890                 write_cdrom_data(data);
1891                 break;
1892                 
1893         case 0x02:  /* ADPCM / CD control / IRQ enable/disable */
1894                 /* bit 6 - transfer ready irq */
1895                 /* bit 5 - transfer done irq */
1896                 /* bit 4 - BRAM irq? */
1897                 /* bit 3 - ADPCM FULL irq */
1898                 /* bit 2 - ADPCM HALF irq */
1899                 if(data & 0x80) {
1900                         set_ack();
1901                 } else {
1902                         clear_ack();
1903                 }
1904                 /* Update mask register now otherwise it won't catch the irq enable/disable change */
1905                 cdrom_regs[0x02] = data;
1906                 /* Don't set or reset any irq lines, but just verify the current state */
1907                 set_cdrom_irq_line(0, 0);
1908                 break;
1909                 
1910         case 0x03:  /* BRAM lock / CD status / IRQ - Read Only register */
1911                 break;
1912                 
1913         case 0x04:  /* CD reset */
1914                 if(data & 0x02) {
1915                         // Reset ADPCM hardware
1916                         reset_adpcm();
1917                         set_cdrom_irq_line(0x70, CLEAR_LINE);
1918                 }
1919                 d_scsi_host->write_signal(SIG_SCSI_RST, data, 0x02);
1920                 break;
1921                 
1922         case 0x05:  /* Convert PCM data / PCM data */
1923         case 0x06:  /* PCM data */
1924                 break;
1925                 
1926         case 0x07:  /* BRAM unlock / CD status */
1927                 if(data & 0x80) {
1928                         backup_locked = false;
1929                 }
1930                 break;
1931                 
1932         case 0x08:  /* ADPCM address (LSB) / CD data */
1933         case 0x09:  /* ADPCM address (MSB) */
1934                 break;
1935                 
1936         case 0x0a:  /* ADPCM RAM data port */
1937                 if(adpcm_write_buf > 0) {
1938                         adpcm_write_buf--;
1939                 } else {
1940                         write_adpcm_ram(data);
1941                 }
1942                 break;
1943                 
1944         case 0x0b:  /* ADPCM DMA control */
1945                 if(data & 3) {
1946                         /* Start CD to ADPCM transfer */
1947                         adpcm_dma_enabled = true;
1948                         
1949                         if(d_scsi_cdrom->get_cur_command() == SCSI_CMD_READ6 &&
1950                            d_scsi_host->read_signal(SIG_SCSI_BSY) != 0 &&
1951                            d_scsi_host->read_signal(SIG_SCSI_REQ) != 0 &&
1952                            d_scsi_host->read_signal(SIG_SCSI_CD ) == 0 &&
1953                            d_scsi_host->read_signal(SIG_SCSI_MSG) == 0 &&
1954                            d_scsi_host->read_signal(SIG_SCSI_IO ) != 0) {
1955                                 // already data is received, read first byte
1956                                 adpcm_do_dma();
1957                         } else {
1958                                 cdrom_regs[0x0c] |= 0x04;
1959                         }
1960                 }
1961                 break;
1962                 
1963         case 0x0c:  /* ADPCM status */
1964                 break;
1965                 
1966         case 0x0d:  /* ADPCM address control */
1967                 if((cdrom_regs[0x0d] & 0x80) && !(data & 0x80)) {
1968                         // Reset ADPCM hardware
1969                         reset_adpcm();
1970                 }
1971                 if(data & 0x02) {
1972                         // ADPCM set write address
1973                         adpcm_write_ptr = (cdrom_regs[0x09] << 8) | cdrom_regs[0x08];
1974                         adpcm_write_buf = data & 1;
1975                         adpcm_written = 0;
1976                 }
1977                 if(data & 0x08) {
1978                         // ADPCM set read address
1979                         adpcm_read_ptr = (cdrom_regs[0x09] << 8) | cdrom_regs[0x08];
1980                         adpcm_read_buf = 2;
1981                 }
1982                 if(data & 0x10) {
1983                         // ADPCM set length
1984                         adpcm_length = (cdrom_regs[0x09] << 8) | cdrom_regs[0x08];
1985                 }
1986                 if((data & 0x40) && ((cdrom_regs[0x0D] & 0x40) == 0)) {
1987                         // ADPCM play
1988                         msm_start_addr = (adpcm_read_ptr) & 0xffff;
1989                         msm_end_addr = (adpcm_read_ptr + adpcm_length) & 0xffff;
1990                         msm_half_addr = (adpcm_read_ptr + (adpcm_length / 2)) & 0xffff;
1991                         adpcm_write_ptr &= 0xffff;
1992                         msm_nibble = 0;
1993                         adpcm_play();
1994                         d_msm->reset_w(0);
1995                 } else if ((data & 0x40) == 0) {
1996                         // used by Buster Bros to cancel an in-flight sample
1997                         // if repeat flag (bit5) is high, ADPCM should be fully played (from Ootake)
1998                         if(!(data & 0x20)) {
1999                                 set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_HALF_PLAY, CLEAR_LINE);
2000                                 set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_FULL_PLAY, CLEAR_LINE);
2001                                 adpcm_stop();
2002                                 d_msm->reset_w(1);
2003                         }
2004                 }
2005                 break;
2006                 
2007         case 0x0e:  /* ADPCM playback rate */
2008                 adpcm_clock_divider = 0x10 - (data & 0x0f);
2009                 d_msm->change_clock_w((ADPCM_CLOCK / 6) / adpcm_clock_divider);
2010                 break;
2011                 
2012         case 0x0f:  /* ADPCM and CD audio fade timer */
2013                 if(cdrom_regs[0x0f] != data) {
2014                         switch(data & 0x0f) {
2015                         case 0x00: // CD-DA / ADPCM enable (100 msecs)
2016                                 cdda_fade_in(100);
2017                                 adpcm_fade_in(100);
2018                                 break;
2019                         case 0x01: // CD-DA enable (100 msecs)
2020                                 cdda_fade_in(100);
2021                                 break;
2022                         case 0x08: // CD-DA short (1500 msecs) fade out / ADPCM enable
2023                         case 0x0c: // CD-DA short (1500 msecs) fade out / ADPCM enable
2024                                 cdda_fade_out(1500);
2025                                 adpcm_fade_in(100);
2026                                 break;
2027                         case 0x09: // CD-DA long (5000 msecs) fade out
2028                                 cdda_fade_out(5000);
2029                                 break;
2030                         case 0x0a: // ADPCM long (5000 msecs) fade out
2031                                 adpcm_fade_out(5000);
2032                                 break;
2033                         case 0x0d: // CD-DA short (1500 msecs) fade out
2034                                 cdda_fade_out(1500);
2035                                 break;
2036                         case 0x0e: // ADPCM short (1500 msecs) fade out
2037                                 adpcm_fade_out(1500);
2038                                 break;
2039                         }
2040                 }
2041                 break;
2042         }
2043         cdrom_regs[addr & 0x0f] = data;
2044 }
2045
2046 uint8_t PCE::cdrom_read(uint16_t addr)
2047 {
2048         // System 3 Card header handling
2049         if((addr & 0xc0) == 0xc0) {
2050                 switch(addr & 0xcf) {
2051                 case 0xc1: return 0xaa;
2052                 case 0xc2: return 0x55;
2053                 case 0xc3: return 0x00;
2054                 case 0xc5: return 0xaa;
2055                 case 0xc6: return 0x55;
2056                 case 0xc7: return 0x03;
2057                 }
2058         }
2059         uint8_t data = cdrom_regs[addr & 0x0f];
2060         
2061         switch(addr & 0x0f) {
2062         case 0x00:  /* CDC status */
2063                 data = 0;
2064                 if(d_cpu->get_pc() == 0xf34b) {
2065                         // XXX: Hack to wait the CD-DA will be finished for the Manhole
2066                         data |= d_scsi_cdrom->read_signal(SIG_SCSI_CDROM_PLAYING) ? 0x80 : 0;
2067                 }
2068                 data |= d_scsi_host->read_signal(SIG_SCSI_BSY) ? 0x80 : 0;
2069                 data |= d_scsi_host->read_signal(SIG_SCSI_REQ) ? 0x40 : 0;
2070                 data |= d_scsi_host->read_signal(SIG_SCSI_MSG) ? 0x20 : 0;
2071                 data |= d_scsi_host->read_signal(SIG_SCSI_CD ) ? 0x10 : 0;
2072                 data |= d_scsi_host->read_signal(SIG_SCSI_IO ) ? 0x08 : 0;
2073                 break;
2074                 
2075         case 0x01:  /* CDC command / status / data */
2076         case 0x08:  /* ADPCM address (LSB) / CD data */
2077                 {
2078                         bool read6_data_in = false;
2079                         if(d_scsi_cdrom->get_cur_command() == SCSI_CMD_READ6 &&
2080                            d_scsi_host->read_signal(SIG_SCSI_BSY) != 0 &&
2081                            d_scsi_host->read_signal(SIG_SCSI_REQ) != 0 &&
2082                            d_scsi_host->read_signal(SIG_SCSI_CD ) == 0 &&
2083                            d_scsi_host->read_signal(SIG_SCSI_MSG) == 0 &&
2084                            d_scsi_host->read_signal(SIG_SCSI_IO ) != 0) {
2085                                 // read6 command, data in phase
2086                                 read6_data_in = true;
2087                         }
2088                         data = read_cdrom_data();
2089                         
2090                         if(read6_data_in) {
2091                                 // set ack automatically and immediately for correct transfer speed
2092                                 set_ack();
2093                                 
2094                                 // XXX: Hack to wait until next REQ signal is raised
2095                                 // because PCE does not check REQ signal before reads next byte
2096                                 d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
2097                         }
2098                 }
2099                 break;
2100                 
2101         case 0x02:  /* ADPCM / CD control */
2102                 break;
2103                 
2104         case 0x03:  /* BRAM lock / CD status */
2105                 // from Ootake
2106                 backup_locked = true;
2107                 data |= PCE_CD_IRQ_BRAM;
2108                 cdrom_regs[3] ^= 0x02;
2109                 if(cdrom_regs[2] == 0) {
2110                         cdrom_regs[3] &= 0x02;
2111                 }
2112                 set_cdrom_irq_line(0, 0);
2113                 break;
2114                 
2115         case 0x04:  /* CD reset */
2116                 break;
2117                 
2118         case 0x05:  /* Convert PCM data / PCM data */
2119                 data = (d_scsi_cdrom->read_signal((cdrom_regs[3] & 0x02) ? SIG_SCSI_CDROM_SAMPLE_L : SIG_SCSI_CDROM_SAMPLE_R) >> 0) & 0xff;
2120                 break;
2121                 
2122         case 0x06:  /* PCM data */
2123                 data = (d_scsi_cdrom->read_signal((cdrom_regs[3] & 0x02) ? SIG_SCSI_CDROM_SAMPLE_L : SIG_SCSI_CDROM_SAMPLE_R) >> 8) & 0xff;
2124                 break;
2125                 
2126         case 0x07:  /* BRAM unlock / CD status */
2127                 data = (backup_locked ? (data & 0x7f) : (data | 0x80));
2128                 break;
2129                 
2130         case 0x0a:  /* ADPCM RAM data port */
2131                 if(adpcm_read_buf > 0) {
2132                         adpcm_read_buf--;
2133                         data = 0x00;
2134                 } else {
2135                         data = read_adpcm_ram();
2136                 }
2137                 break;
2138                 
2139         case 0x0b:  /* ADPCM DMA control */
2140                 break;
2141                 
2142         case 0x0c:  /* ADPCM status */
2143                 break;
2144                 
2145         case 0x09:  /* ADPCM address (MSB) */
2146         case 0x0d:  /* ADPCM address control */
2147         case 0x0e:  /* ADPCM playback rate */
2148         case 0x0f:  /* ADPCM and CD audio fade timer */
2149                 data = 0;
2150                 break;
2151         }
2152         return data;
2153 }
2154
2155 void PCE::write_cdrom_data(uint8_t data)
2156 {
2157         d_scsi_host->write_dma_io8(0, data);
2158 }
2159
2160 uint8_t PCE::read_cdrom_data()
2161 {
2162         return d_scsi_host->read_dma_io8(0);
2163 }
2164
2165 void PCE::reset_adpcm()
2166 {
2167         touch_sound();
2168         // reset ADPCM hardware
2169         adpcm_read_ptr = adpcm_write_ptr = 0;
2170         msm_start_addr = msm_end_addr = msm_half_addr = 0;
2171         msm_nibble = 0;
2172         adpcm_stop();
2173         d_msm->reset_w(1);
2174         
2175         // stop ADPCM dma
2176         adpcm_dma_enabled = false;
2177 }
2178
2179 void PCE::write_adpcm_ram(uint8_t data)
2180 {
2181         adpcm_ram[(adpcm_write_ptr++) & 0xffff] = data;
2182 }
2183
2184 uint8_t PCE::read_adpcm_ram()
2185 {
2186         return adpcm_ram[(adpcm_read_ptr++) & 0xffff];
2187 }
2188
2189 void PCE::adpcm_do_dma()
2190 {
2191         write_adpcm_ram(read_cdrom_data());
2192         adpcm_written++;
2193         set_ack();
2194         cdrom_regs[0x0c] &= ~0x04;
2195 }
2196
2197 void PCE::adpcm_play()
2198 {
2199         touch_sound();
2200         cdrom_regs[0x0c] &= ~PCE_CD_ADPCM_STOP_FLAG;
2201         cdrom_regs[0x0c] |= PCE_CD_ADPCM_PLAY_FLAG;
2202         set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_FULL_PLAY, CLEAR_LINE);
2203         cdrom_regs[0x03] &= ~0x0c;
2204         msm_idle = 0;
2205 }
2206
2207 void PCE::adpcm_stop()
2208 {
2209         touch_sound();
2210         cdrom_regs[0x0c] |= PCE_CD_ADPCM_STOP_FLAG;
2211         cdrom_regs[0x0c] &= ~PCE_CD_ADPCM_PLAY_FLAG;
2212         cdrom_regs[0x0d] &= ~0x60;
2213         msm_idle = 1;
2214 }
2215
2216 void PCE::set_ack()
2217 {
2218         d_scsi_host->write_signal(SIG_SCSI_ACK, 1, 1);
2219 }
2220
2221 void PCE::clear_ack()
2222 {
2223         if(d_scsi_host->read_signal(SIG_SCSI_CD) != 0) {
2224                 cdrom_regs[0x0b] &= 0xfc;
2225         }
2226         d_scsi_host->write_signal(SIG_SCSI_ACK, 0, 0);
2227 }
2228
2229 void PCE::set_cdrom_irq_line(int num, int state)
2230 {
2231         if (state == ASSERT_LINE) {
2232                 cdrom_regs[0x03] |= num;
2233         } else {
2234                 cdrom_regs[0x03] &= ~num;
2235         }
2236         if (cdrom_regs[0x02] & cdrom_regs[0x03] & 0x7c) {
2237                 d_cpu->write_signal(INPUT_LINE_IRQ2, ASSERT_LINE, 0);
2238         } else {
2239                 d_cpu->write_signal(INPUT_LINE_IRQ2, CLEAR_LINE, 0);
2240         }
2241 }
2242
2243 void PCE::cdda_fade_in(int time)
2244 {
2245         if(event_cdda_fader != -1) {
2246                 cancel_event(this, event_cdda_fader);
2247         }
2248         register_event(this, EVENT_CDDA_FADE_IN, time, true, &event_cdda_fader);
2249         d_scsi_cdrom->set_volume((int)(cdda_volume = 0.0));
2250 }
2251
2252 void PCE::cdda_fade_out(int time)
2253 {
2254         if(event_cdda_fader != -1) {
2255                 cancel_event(this, event_cdda_fader);
2256         }
2257         register_event(this, EVENT_CDDA_FADE_OUT, time, true, &event_cdda_fader);
2258         d_scsi_cdrom->set_volume((int)(cdda_volume = 100.0));
2259 }
2260
2261 void PCE::adpcm_fade_in(int time)
2262 {
2263         if(event_adpcm_fader != -1) {
2264                 cancel_event(this, event_adpcm_fader);
2265         }
2266         register_event(this, EVENT_ADPCM_FADE_IN, time, true, &event_adpcm_fader);
2267         d_msm->set_volume((int)(adpcm_volume = 0.0));
2268 }
2269
2270 void PCE::adpcm_fade_out(int time)
2271 {
2272         if(event_adpcm_fader != -1) {
2273                 cancel_event(this, event_adpcm_fader);
2274         }
2275         register_event(this, EVENT_ADPCM_FADE_OUT, time, true, &event_adpcm_fader);
2276         d_msm->set_volume((int)(adpcm_volume = 100.0));
2277 }
2278
2279 void PCE::write_signal(int id, uint32_t data, uint32_t mask)
2280 {
2281         switch(id) {
2282         case SIG_PCE_SCSI_IRQ:
2283                 if(data & mask) {
2284                         if(!irq_status) {
2285                                 irq_status = true;
2286                                 
2287                                 if(d_scsi_host->read_signal(SIG_SCSI_BSY) != 0 &&
2288                                    d_scsi_host->read_signal(SIG_SCSI_CD ) != 0 &&
2289                                    d_scsi_host->read_signal(SIG_SCSI_MSG) == 0 &&
2290                                    d_scsi_host->read_signal(SIG_SCSI_IO ) != 0) {
2291                                         // status phase, command is finished
2292                                         set_cdrom_irq_line(PCE_CD_IRQ_TRANSFER_READY, CLEAR_LINE);
2293                                         set_cdrom_irq_line(PCE_CD_IRQ_TRANSFER_DONE, ASSERT_LINE);
2294                                 }
2295                                 // clear busreq because next REQ signal is raised
2296                                 d_cpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
2297                         }
2298                 } else {
2299                         if(irq_status) {
2300                                 irq_status = false;
2301                         }
2302                 }
2303                 break;
2304                 
2305         case SIG_PCE_SCSI_DRQ:
2306                 if(data & mask) {
2307                         if(!drq_status) {
2308                                 drq_status = true;
2309                                 set_cdrom_irq_line(PCE_CD_IRQ_TRANSFER_READY, ASSERT_LINE);
2310                                 
2311                                 // clear busreq because next REQ signal is raised
2312                                 d_cpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
2313                                 
2314                                 if(adpcm_dma_enabled) {
2315                                         if(!msm_idle && adpcm_write_ptr >= msm_start_addr) {
2316                                                 // now streaming, wait dma not to overwrite buffer before it is played
2317                                         } else {
2318                                                 adpcm_do_dma();
2319                                         }
2320                                 }
2321                         }
2322                 } else {
2323                         if(drq_status) {
2324                                 drq_status = false;
2325                                 
2326                                 if(d_scsi_cdrom->get_cur_command() == SCSI_CMD_READ6 &&
2327                                    d_scsi_host->read_signal(SIG_SCSI_BSY) != 0 &&
2328                                    d_scsi_host->read_signal(SIG_SCSI_CD ) == 0 &&
2329                                    d_scsi_host->read_signal(SIG_SCSI_MSG) == 0 &&
2330                                    d_scsi_host->read_signal(SIG_SCSI_IO ) != 0) {
2331                                         // clear ack automatically and immediately for correct transfer speed
2332                                         clear_ack();
2333                                 }
2334                         }
2335                 }
2336                 break;
2337                 
2338         case SIG_PCE_SCSI_BSY:
2339                 if(!(data & mask)) {
2340                         // bus free
2341                         set_cdrom_irq_line(PCE_CD_IRQ_TRANSFER_READY, CLEAR_LINE);
2342                         set_cdrom_irq_line(PCE_CD_IRQ_TRANSFER_DONE, CLEAR_LINE);
2343                 }
2344                 break;
2345                 
2346         case SIG_PCE_CDDA_DONE:
2347                 touch_sound();
2348                 if(data & mask) {
2349                         set_cdrom_irq_line(PCE_CD_IRQ_TRANSFER_DONE, ASSERT_LINE);
2350                 }
2351                 break;
2352                 
2353         case SIG_PCE_ADPCM_VCLK:
2354                 // Callback for new data from the MSM5205.
2355                 // The PCE cd unit actually divides the clock signal supplied to
2356                 // the MSM5205. Currently we can only use static clocks for the
2357                 // MSM5205.
2358                 if(!msm_idle) {
2359                         uint8_t msm_data = (msm_nibble) ? (adpcm_ram[msm_start_addr & 0xffff] & 0x0f) : ((adpcm_ram[msm_start_addr & 0xffff] & 0xf0) >> 4);
2360                         d_msm->data_w(msm_data);
2361                         msm_nibble ^= 1;
2362                         
2363                         if(msm_nibble == 0) {
2364                                 adpcm_written--;
2365                                 if(adpcm_dma_enabled && adpcm_written == 0) {
2366                                         // finish streaming when all samples are played
2367                                         set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_HALF_PLAY, CLEAR_LINE);
2368                                         set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_FULL_PLAY, ASSERT_LINE);
2369                                         adpcm_stop();
2370                                         d_msm->reset_w(1);
2371                                 } else if((msm_start_addr & 0xffff) == msm_half_addr) {
2372                                         // reached to half address
2373                                         set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_FULL_PLAY, CLEAR_LINE);
2374                                         set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_HALF_PLAY, ASSERT_LINE);
2375                                 } else if((msm_start_addr & 0xffff) == msm_end_addr) {
2376                                         // reached to end address
2377                                         if(adpcm_dma_enabled) {
2378                                                 // restart streaming
2379                                                 set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_HALF_PLAY, CLEAR_LINE);
2380                                                 set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_FULL_PLAY, CLEAR_LINE);
2381                                         } else {
2382                                                 // stop playing adpcm
2383                                                 set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_HALF_PLAY, CLEAR_LINE);
2384                                                 set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_FULL_PLAY, ASSERT_LINE);
2385                                                 adpcm_stop();
2386                                                 d_msm->reset_w(1);
2387                                         }
2388                                 }
2389                                 msm_start_addr++;
2390                                 
2391                                 if(adpcm_dma_enabled) {
2392                                         if(!msm_idle && adpcm_write_ptr < msm_start_addr) {
2393                                                 if(d_scsi_cdrom->get_cur_command() == SCSI_CMD_READ6 &&
2394                                                    d_scsi_host->read_signal(SIG_SCSI_BSY) != 0 &&
2395                                                    d_scsi_host->read_signal(SIG_SCSI_REQ) != 0 &&
2396                                                    d_scsi_host->read_signal(SIG_SCSI_CD ) == 0 &&
2397                                                    d_scsi_host->read_signal(SIG_SCSI_MSG) == 0 &&
2398                                                    d_scsi_host->read_signal(SIG_SCSI_IO ) != 0) {
2399                                                         // already data is received, read next byte
2400                                                         adpcm_do_dma();
2401                                                 }
2402                                         }
2403                                 }
2404                         }
2405                 }
2406                 break;
2407         }
2408 }
2409
2410 void PCE::event_callback(int event_id, int err)
2411 {
2412         switch(event_id) {
2413         case EVENT_CDDA_FADE_IN:
2414                 if((cdda_volume += 0.1) >= 100.0) {
2415                         cancel_event(this, event_cdda_fader);
2416                         event_cdda_fader = -1;
2417                         cdda_volume = 100.0;
2418                 }
2419                 d_scsi_cdrom->set_volume((int)cdda_volume);
2420                 break;
2421                 
2422         case EVENT_CDDA_FADE_OUT:
2423                 if((cdda_volume -= 0.1) <= 0) {
2424                         cancel_event(this, event_cdda_fader);
2425                         event_cdda_fader = -1;
2426                         cdda_volume = 0.0;
2427                 }
2428                 d_scsi_cdrom->set_volume((int)cdda_volume);
2429                 break;
2430                 
2431         case EVENT_ADPCM_FADE_IN:
2432                 if((adpcm_volume += 0.1) >= 100.0) {
2433                         cancel_event(this, event_adpcm_fader);
2434                         event_adpcm_fader = -1;
2435                         adpcm_volume = 100.0;
2436                 }
2437                 d_msm->set_volume((int)adpcm_volume);
2438                 break;
2439                 
2440         case EVENT_ADPCM_FADE_OUT:
2441                 if((adpcm_volume -= 0.1) <= 0) {
2442                         cancel_event(this, event_adpcm_fader);
2443                         event_adpcm_fader = -1;
2444                         adpcm_volume = 0.0;
2445                 }
2446                 d_msm->set_volume((int)adpcm_volume);
2447                 break;
2448         }
2449 }
2450 #endif
2451
2452 #define STATE_VERSION   5
2453
2454 bool PCE::process_state(FILEIO* state_fio, bool loading)
2455 {
2456         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
2457                 return false;
2458         }
2459         if(!state_fio->StateCheckInt32(this_device_id)) {
2460                 return false;
2461         }
2462         state_fio->StateBool(support_6btn_pad);
2463         state_fio->StateBool(support_multi_tap);
2464 #ifdef SUPPORT_SUPER_GFX
2465         state_fio->StateBool(support_sgfx);
2466 #endif
2467 #ifdef SUPPORT_CDROM
2468         state_fio->StateBool(support_cdrom);
2469 #endif
2470         state_fio->StateBuffer(ram, sizeof(ram), 1);
2471         state_fio->StateBuffer(cart + 0x80000, 0x80000, 1);
2472 #ifdef SUPPORT_BACKUP_RAM
2473         state_fio->StateBuffer(backup, sizeof(backup), 1);
2474         state_fio->StateUint32(backup_crc32);
2475 #endif
2476         state_fio->StateUint32(bank);
2477         state_fio->StateUint8(buffer);
2478         state_fio->StateInt32(prev_width);
2479         state_fio->StateBool(inserted);
2480
2481         //state_fio->StateBuffer(vdc, sizeof(vdc), 1);
2482         //state_fio->StateBuffer(&vce, sizeof(vce), 1);
2483         //state_fio->StateBuffer(&vpc, sizeof(vpc), 1);
2484         //state_fio->StateBuffer(psg, sizeof(psg), 1);
2485         // vdc
2486         for(int i = 0; i < 2; i++) {
2487                 state_fio->StateInt32(vdc[i].dvssr_write);              /* Set when the DVSSR register has been written to */
2488                 state_fio->StateInt32(vdc[i].physical_width);           /* Width of the display */
2489                 state_fio->StateInt32(vdc[i].physical_height);          /* Height of the display */
2490                 for(int j = 0; j < (64 * 4); j++) {
2491                         state_fio->StateUint16(vdc[i].sprite_ram[j]);   /* Sprite RAM */
2492                 }
2493                 state_fio->StateInt32(vdc[i].curline);                          /* the current scanline we're on */
2494                 state_fio->StateInt32(vdc[i].current_segment);          /* current segment of display */
2495                 state_fio->StateInt32(vdc[i].current_segment_line);     /* current line inside a segment of display */
2496                 state_fio->StateInt32(vdc[i].vblank_triggered);         /* to indicate whether vblank has been triggered */
2497                 state_fio->StateInt32(vdc[i].raster_count);             /* counter to compare RCR against */
2498                 state_fio->StateInt32(vdc[i].satb_countdown);           /* scanlines to wait to trigger the SATB irq */
2499                 state_fio->StateBuffer((vdc[i].vram), 0x10000, 1);
2500                 state_fio->StateUint8(vdc[i].inc);
2501                 state_fio->StateUint8(vdc[i].vdc_register);
2502                 state_fio->StateUint8(vdc[i].vdc_latch);
2503                 for(int j = 0; j < 32; j++) {
2504                         state_fio->StateUint32(vdc[i].vdc_data[j].d);
2505                 }
2506                 state_fio->StateInt32(vdc[i].status);
2507                 state_fio->StateInt32(vdc[i].y_scroll);
2508         }
2509         // vce
2510         {
2511                 state_fio->StateUint8(vce.vce_control);         /* VCE control register */
2512                 state_fio->StateUint32(vce.vce_address.d);              /* Current address in the palette */
2513                 for(int i = 0; i < 512; i++) {
2514                         state_fio->StateUint32(vce.vce_data[i].d);              /* Palette data */
2515                 }
2516                 state_fio->StateInt32(vce.current_bitmap_line); /* The current line in the display we are on */
2517                 //bitmap_ind16 *bmp;
2518                 for(int i = 0; i < VDC_LPF; i++) {
2519                         for(int j = 0; j < VDC_WPF; j++) {
2520                                 if(loading) {
2521                                         uint8_t r, g, b;
2522                                         r = state_fio->FgetUint8();
2523                                         g = state_fio->FgetUint8();
2524                                         b = state_fio->FgetUint8();
2525                                         vce.bmp[i][j] = RGB_COLOR(r, g, b);
2526                                 } else {
2527                                         uint8_t r, g, b;
2528                                         r = R_OF_COLOR(vce.bmp[i][j]);
2529                                         g = G_OF_COLOR(vce.bmp[i][j]);
2530                                         b = B_OF_COLOR(vce.bmp[i][j]);
2531                                         state_fio->FputUint8(r);
2532                                         state_fio->FputUint8(g);
2533                                         state_fio->FputUint8(b);
2534                                 }
2535                         }
2536                 }
2537                 for(int i = 0; i < 1024; i++) {
2538                         if(loading) {
2539                                 uint8_t r, g, b;
2540                                 r = state_fio->FgetUint8();
2541                                 g = state_fio->FgetUint8();
2542                                 b = state_fio->FgetUint8();
2543                                 vce.palette[i] = RGB_COLOR(r, g, b);
2544                         } else {
2545                                 uint8_t r, g, b;
2546                                 r = R_OF_COLOR(vce.palette[i]);
2547                                 g = G_OF_COLOR(vce.palette[i]);
2548                                 b = B_OF_COLOR(vce.palette[i]);
2549                                 state_fio->FputUint8(r);
2550                                 state_fio->FputUint8(g);
2551                                 state_fio->FputUint8(b);
2552                         }
2553                 }
2554         }
2555         // vpc
2556         {
2557                 for(int i = 0; i < 4; i++) {
2558                         state_fio->StateUint8(vpc.vpc_prio[i].prio);
2559                         state_fio->StateUint8(vpc.vpc_prio[i].vdc0_enabled);
2560                         state_fio->StateUint8(vpc.vpc_prio[i].vdc1_enabled);
2561                 }
2562                 state_fio->StateBuffer(vpc.prio_map, 512, 1);
2563                 state_fio->StateUint32(vpc.priority.d);
2564                 state_fio->StateUint32(vpc.window1.d);
2565                 state_fio->StateUint32(vpc.window2.d);
2566                 state_fio->StateUint8(vpc.vdc_select);
2567         }
2568         // psg
2569         {
2570                 for(int i = 0; i < 8; i++ ){
2571                     state_fio->StateBuffer(psg[i].regs, 8, 1);
2572                         state_fio->StateBuffer(psg[i].wav, 32, 1);
2573                         state_fio->StateUint8(psg[i].wavptr);
2574                         state_fio->StateUint32(psg[i].genptr);
2575                         state_fio->StateUint32(psg[i].remain);
2576                         state_fio->StateBool(psg[i].noise);
2577                         state_fio->StateUint32(psg[i].randval);
2578                 }
2579         }
2580
2581         state_fio->StateUint8(psg_ch);
2582         state_fio->StateUint8(psg_vol);
2583         state_fio->StateUint8(psg_lfo_freq);
2584         state_fio->StateUint8(psg_lfo_ctrl);
2585         state_fio->StateUint8(joy_counter);
2586         state_fio->StateBool(joy_high_nibble);
2587         state_fio->StateBool(joy_second_byte);
2588 #ifdef SUPPORT_CDROM
2589         state_fio->StateBuffer(cdrom_ram, sizeof(cdrom_ram), 1);
2590         state_fio->StateBuffer(cdrom_regs, sizeof(cdrom_regs), 1);
2591         state_fio->StateBool(backup_locked);
2592         state_fio->StateBool(irq_status);
2593         state_fio->StateBool(drq_status);
2594         state_fio->StateBuffer(adpcm_ram, sizeof(adpcm_ram), 1);
2595         state_fio->StateInt32(adpcm_read_ptr);
2596         state_fio->StateInt32(adpcm_write_ptr);
2597         state_fio->StateInt32(adpcm_written);
2598         state_fio->StateInt32(adpcm_length);
2599         state_fio->StateInt32(adpcm_clock_divider);
2600         state_fio->StateUint8(adpcm_read_buf);
2601         state_fio->StateUint8(adpcm_write_buf);
2602         state_fio->StateBool(adpcm_dma_enabled);
2603         state_fio->StateInt32(msm_start_addr);
2604         state_fio->StateInt32(msm_end_addr);
2605         state_fio->StateInt32(msm_half_addr);
2606         state_fio->StateUint8(msm_nibble);
2607         state_fio->StateUint8(msm_idle);
2608         state_fio->StateDouble(cdda_volume);
2609         state_fio->StateDouble(adpcm_volume);
2610         state_fio->StateInt32(event_cdda_fader);
2611         state_fio->StateInt32(event_adpcm_fader);
2612 #endif
2613         return true;
2614 }
2615
2616 }