OSDN Git Service

[VM][SCSI_CDROM] Add write_signal() to control CDDA from MACHINE.
[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         adpcm_play_in_progress = false;
1864         msm_idle = 1;
1865         
1866         if(event_cdda_fader != -1) {
1867                 cancel_event(this, event_cdda_fader);
1868         }
1869         if(event_adpcm_fader != -1) {
1870                 cancel_event(this, event_adpcm_fader);
1871         }
1872         cdda_volume = adpcm_volume = 100.0;
1873         event_cdda_fader = event_adpcm_fader = -1;
1874         
1875         d_scsi_cdrom->set_volume((int)cdda_volume);
1876         d_msm->set_volume((int)adpcm_volume);
1877 }
1878
1879 void PCE::cdrom_write(uint16_t addr, uint8_t data)
1880 {
1881         touch_sound();
1882         switch(addr & 0x0f) {
1883         case 0x00:  /* CDC status */
1884                 data = 0xd0; // Force set data to $D0
1885                 // Reset req?
1886                 d_scsi_host->write_signal(SIG_SCSI_SEL, 1, 1);
1887                 d_scsi_host->write_signal(SIG_SCSI_SEL, 0, 1);
1888                 adpcm_dma_enabled = false;
1889                 // From Ootake v2.38
1890                 cdrom_regs[0x03] = 0x00; // Reset IRQ status at al.
1891                 set_cdrom_irq_line(0x0, 0x0); // Update IRQ
1892                 break;
1893                 
1894         case 0x01:  /* CDC command / status / data */
1895                 //out_debug_log(_T("CDC CMD %02x\n"), data);
1896                 write_cdrom_data(data);
1897                 break;
1898                 
1899         case 0x02:  /* ADPCM / CD control / IRQ enable/disable */
1900                 /* bit 6 - transfer ready irq */
1901                 /* bit 5 - transfer done irq */
1902                 /* bit 4 - BRAM irq? */
1903                 /* bit 3 - ADPCM FULL irq */
1904                 /* bit 2 - ADPCM HALF irq */
1905                 if(data & 0x80) {
1906                         set_ack();
1907                 } else {
1908                         clear_ack();
1909                 }
1910                 /* Update mask register now otherwise it won't catch the irq enable/disable change */
1911                 cdrom_regs[0x02] = data;
1912                 /* Don't set or reset any irq lines, but just verify the current state */
1913                 set_cdrom_irq_line(0, 0);
1914                 break;
1915                 
1916         case 0x03:  /* BRAM lock / CD status / IRQ - Read Only register */
1917                 break;
1918                 
1919         case 0x04:  /* CD reset */
1920                 if(data & 0x02) {
1921                         // Reset CDROM
1922                         // From Ootake v2.38
1923                         d_scsi_cdrom->write_signal(SIG_SCSI_CDROM_CDDA_STOP, 0xff, 0xff);
1924                         // Reset ADPCM hardware
1925                         reset_adpcm();
1926                         adpcm_dma_enabled = false;
1927                         out_debug_log(_T("ADPCM CMD=$04 RESET\n"));
1928                         cdrom_regs[0x03] = 0x00; // Reset IRQ status at al.
1929                         set_cdrom_irq_line(0x0, 0x0); // Update IRQ
1930                 }
1931                 d_scsi_host->write_signal(SIG_SCSI_RST, data, 0x02);
1932                 break;
1933                 
1934         case 0x05:  /* Convert PCM data / PCM data */
1935         case 0x06:  /* PCM data */
1936                 break;
1937                 
1938         case 0x07:  /* BRAM unlock / CD status */
1939                 if(data & 0x80) {
1940                         backup_locked = false;
1941                 }
1942                 break;
1943                 
1944         case 0x08:  /* ADPCM address (LSB) / CD data */
1945         case 0x09:  /* ADPCM address (MSB) */
1946                 break;
1947                 
1948         case 0x0a:  /* ADPCM RAM data port */
1949                 if(adpcm_write_buf > 0) {
1950                         adpcm_write_buf--;
1951                 } else {
1952                         write_adpcm_ram(data);
1953                 }
1954                 break;
1955                 
1956         case 0x0b:  /* ADPCM DMA control */
1957                 if(data & 3) {
1958                         /* Start CD to ADPCM transfer */
1959                         adpcm_dma_enabled = true;
1960                         cdrom_regs[0x0c] |= 0x04;
1961                         if(d_scsi_cdrom->get_cur_command() == SCSI_CMD_READ6 &&
1962                            d_scsi_host->read_signal(SIG_SCSI_BSY) != 0 &&
1963                            d_scsi_host->read_signal(SIG_SCSI_REQ) != 0 &&
1964                            d_scsi_host->read_signal(SIG_SCSI_CD ) == 0 &&
1965                            d_scsi_host->read_signal(SIG_SCSI_MSG) == 0 &&
1966                            d_scsi_host->read_signal(SIG_SCSI_IO ) != 0) {
1967                                 // already data is received, read first byte
1968                                 adpcm_do_dma();
1969                                 out_debug_log(_T("Start DMA port $0B/ALREADY READ DATA ADPCM_WRITE_PTR=%04x ADPCM_READ_PTR=%04x MSM_START_ADDR=%04x\n"),adpcm_write_ptr, adpcm_read_ptr, msm_start_addr);
1970                         } else {
1971                                 //cdrom_regs[0x0c] |= 0x04;
1972                                 out_debug_log(_T("Start DMA port $0B/WAIT FOR DATA\n"));
1973                         }
1974                 } else {
1975                         //adpcm_dma_enabled = false;
1976                 }
1977                 break;
1978                 
1979         case 0x0c:  /* ADPCM status */
1980                 break;
1981                 
1982         case 0x0d:  /* ADPCM address control */
1983                 if((cdrom_regs[0x0d] & 0x80) && !(data & 0x80)) {
1984                         // Reset ADPCM hardware
1985                         reset_adpcm();
1986                         adpcm_stop(true);
1987                         out_debug_log(_T("ADPCM CMD=$0D RESET\n"));
1988                 }
1989                 if(data & 0x02) {
1990                         // ADPCM set write address
1991                         adpcm_write_ptr = (cdrom_regs[0x09] << 8) | cdrom_regs[0x08];
1992                         adpcm_write_buf = ((data & 1) == 0) ? 1 : 0;
1993                         adpcm_written = 0;
1994                         out_debug_log(_T("ADPCM SET WRITE ADDRESS ADDR=%04x\n"), adpcm_write_ptr);
1995                 }
1996                 if(data & 0x08) {
1997                         // ADPCM set read address
1998                         adpcm_read_ptr = (cdrom_regs[0x09] << 8) | cdrom_regs[0x08];
1999                         adpcm_read_buf = ((data & 0x04) == 0) ? 2 : 1;
2000                         out_debug_log(_T("ADPCM SET READ ADDRESS ADDR=%04x\n"), adpcm_read_ptr);
2001                 }
2002                 if(data & 0x10) {
2003                         // ADPCM set length
2004                         adpcm_length = (cdrom_regs[0x09] << 8) | cdrom_regs[0x08];
2005                         uint32_t _clk = (ADPCM_CLOCK / 6) / adpcm_clock_divider;
2006
2007                         if(((adpcm_read_ptr & 0xffff) >= 0x4000) &&
2008                            ((adpcm_write_ptr & 0xffff) == 0x0000) &&
2009                            (adpcm_length != 0x8000) &&
2010                            (adpcm_length != 0xffff) &&
2011                            (_clk < 16000)) {
2012                                 adpcm_length = adpcm_length & 0x7fff;
2013                         }
2014                         out_debug_log(_T("ADPCM SET LENGTH LENGTH=%04x\n"), adpcm_length);
2015                 }
2016                 if((((data & 0x40) != 0) && ((cdrom_regs[0x0D] & 0x40) == 0)) ||
2017                    (!(adpcm_play_in_progress) && ((data & 0x20 != 0)))) { // From Ootake v2.83
2018                         // ADPCM play
2019                         msm_start_addr = (adpcm_read_ptr) & 0xffff;
2020                         msm_end_addr = (adpcm_read_ptr + adpcm_length) & 0xffff;
2021                         msm_half_addr = (adpcm_read_ptr + (adpcm_length / 2)) & 0xffff;
2022                         adpcm_write_ptr &= 0xffff;
2023                         msm_nibble = 0;
2024                         adpcm_play_in_progress = true;
2025                         adpcm_play();
2026                         d_msm->reset_w(0);
2027                         out_debug_log(_T("ADPCM START PLAY START=%04x END=%04x HALF=%04x\n"), msm_start_addr, msm_end_addr, msm_half_addr);
2028                 } else if(((data & 0x40) == 0)) {
2029                         if(((cdrom_regs[0x0D] & 0x40) != 0) && (adpcm_play_in_progress)) {
2030                                 // 20181213 K.O: Import from Ootake v2.83.Thanks to developers of Ootake.
2031                                 if(((data & 0x20) != 0) && ((adpcm_length & 0xffff) >= 0x8000) && ((adpcm_length & 0xffff) <= 0x80ff)) {
2032                                         msm_half_addr = (adpcm_read_ptr + 0x85) & 0xffff;
2033                                 } else {
2034                                         msm_half_addr = (adpcm_read_ptr + (adpcm_length >> 1)) & 0xffff;
2035                                 }
2036                         }
2037                         // used by Buster Bros to cancel an in-flight sample
2038                         // if repeat flag (bit5) is high, ADPCM should be fully played (from Ootake)
2039                         if(!(data & 0x20)) {
2040                                 set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_HALF_PLAY, CLEAR_LINE);
2041                                 set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_FULL_PLAY, CLEAR_LINE);
2042                                 adpcm_stop(false);
2043                                 d_msm->reset_w(1);
2044                         }
2045                 }
2046                 break;
2047                 
2048         case 0x0e:  /* ADPCM playback rate */
2049                 adpcm_clock_divider = 0x10 - (data & 0x0f);
2050                 d_msm->change_clock_w((ADPCM_CLOCK / 6) / adpcm_clock_divider);
2051                 break;
2052                 
2053         case 0x0f:  /* ADPCM and CD audio fade timer */
2054                 if(cdrom_regs[0x0f] != data) {
2055                         switch(data & 0x0f) {
2056                         case 0x00: // CD-DA / ADPCM enable (100 msecs)
2057                                 cdda_fade_in(100);
2058                                 adpcm_fade_in(100);
2059                                 break;
2060                         case 0x01: // CD-DA enable (100 msecs)
2061                                 cdda_fade_in(100);
2062                                 break;
2063                         case 0x08: // CD-DA short (1500 msecs) fade out / ADPCM enable
2064                         case 0x0c: // CD-DA short (1500 msecs) fade out / ADPCM enable
2065                                 cdda_fade_out(1500);
2066                                 adpcm_fade_in(100);
2067                                 break;
2068                         case 0x09: // CD-DA long (5000 msecs) fade out
2069                                 cdda_fade_out(5000);
2070                                 break;
2071                         case 0x0a: // ADPCM long (5000 msecs) fade out
2072                                 adpcm_fade_out(5000);
2073                                 break;
2074                         case 0x0d: // CD-DA short (1500 msecs) fade out
2075                                 cdda_fade_out(1500);
2076                                 break;
2077                         case 0x0e: // ADPCM short (1500 msecs) fade out
2078                                 adpcm_fade_out(1500);
2079                                 break;
2080                         }
2081                 }
2082                 break;
2083         }
2084         cdrom_regs[addr & 0x0f] = data;
2085 }
2086
2087 uint8_t PCE::cdrom_read(uint16_t addr)
2088 {
2089         // System 3 Card header handling
2090         if((addr & 0xc0) == 0xc0) {
2091                 switch(addr & 0xcf) {
2092                 case 0xc1: return 0xaa;
2093                 case 0xc2: return 0x55;
2094                 case 0xc3: return 0x00;
2095                 case 0xc5: return 0xaa;
2096                 case 0xc6: return 0x55;
2097                 case 0xc7: return 0x03;
2098                 }
2099                 return 0xff; // From Ootake v2.83.
2100         }
2101         uint8_t data = cdrom_regs[addr & 0x0f];
2102         
2103         switch(addr & 0x0f) {
2104         case 0x00:  /* CDC status */
2105                 if((cdrom_regs[0x02] & 0x80) != 0) {
2106                         // ToDo: Imprement read_1801() at Ootake v2.83.
2107                         // ToDo: Implement _CheckCountAfterRead at CDROM.cpp of Ootake v2.83.
2108                         if((d_scsi_host->read_signal(SIG_SCSI_CD) != 0) &&
2109                            (d_scsi_host->read_signal(SIG_SCSI_MSG) == 0) &&
2110                            (d_scsi_host->read_signal(SIG_SCSI_IO) != 0)) { // STATUS PHASE: Porting from Ootake v2.83.
2111                                 //      // busy = false;
2112                                 cdrom_regs[0x02] = cdrom_regs[0x02] & ~(0x80 | PCE_CD_IRQ_TRANSFER_READY | PCE_CD_IRQ_TRANSFER_DONE);
2113                                 set_cdrom_irq_line(PCE_CD_IRQ_TRANSFER_DONE, CLEAR_LINE);
2114                         }
2115                         return data & ~0x40; // Clear REQ
2116                 }                               
2117                 data = 0;
2118                 if(d_cpu->get_pc() == 0xf34b) {
2119                         // XXX: Hack to wait the CD-DA will be finished for the Manhole
2120                         data |= d_scsi_cdrom->read_signal(SIG_SCSI_CDROM_PLAYING) ? 0x80 : 0;
2121                 }
2122                 data |= d_scsi_host->read_signal(SIG_SCSI_BSY) ? 0x80 : 0;
2123                 data |= d_scsi_host->read_signal(SIG_SCSI_REQ) ? 0x40 : 0;
2124                 data |= d_scsi_host->read_signal(SIG_SCSI_MSG) ? 0x20 : 0;
2125                 data |= d_scsi_host->read_signal(SIG_SCSI_CD ) ? 0x10 : 0;
2126                 data |= d_scsi_host->read_signal(SIG_SCSI_IO ) ? 0x08 : 0;
2127                 cdrom_regs[0x00] = data;
2128                 if(false){
2129                         // Import from Ootake v2.83 20181211 K.O
2130                         if(((data & 0x10) != 0) &&
2131                            ((data & 0x20) == 0) &&
2132                            ((data & 0x08) == 0)){ // Command phase
2133                                 if((data & 0x80) != 0) { // Busy
2134                                         //      data = (data & ~0x40) | 0x08; // (data & ~REQ) | IO
2135                                 } else {
2136                                         //data = data & ~0x40; // (data & ~REQ)
2137                                 }
2138                         } else if((data & 0x80) != 0) { // BUSY
2139                                 data = (data & ~0x40) | 0x10 | 0x80; // (data & ~REQ) | BUSY | CD
2140                         } /*else if(_CheckCountAfterRead == 0) && (Status phase) && (cmd == read6)){
2141                                  data = data & ~0x40;
2142                         } else  */ /* if(_bCDReqWait) {
2143                                 _bCDReqWait = false;
2144                                 if(data boundary) {
2145                                          data = data & ~0x40;
2146                                 }
2147                         }*/
2148                 }
2149                 break;
2150                 
2151         case 0x01:  /* CDC command / status / data */
2152         case 0x08:  /* ADPCM address (LSB) / CD data */
2153                 {
2154                         bool read6_data_in = false;
2155                         if(d_scsi_cdrom->get_cur_command() == SCSI_CMD_READ6 &&
2156                            d_scsi_host->read_signal(SIG_SCSI_BSY) != 0 &&
2157                            d_scsi_host->read_signal(SIG_SCSI_REQ) != 0 &&
2158                            d_scsi_host->read_signal(SIG_SCSI_CD ) == 0 &&
2159                            d_scsi_host->read_signal(SIG_SCSI_MSG) == 0 &&
2160                            d_scsi_host->read_signal(SIG_SCSI_IO ) != 0) {
2161                                 // read6 command, data in phase
2162                                 read6_data_in = true;
2163                         }
2164                         data = read_cdrom_data();
2165                         if(read6_data_in) {
2166                                 // set ack automatically and immediately for correct transfer speed
2167                                 set_ack();
2168                                 
2169                                 // XXX: Hack to wait until next REQ signal is raised
2170                                 // because PCE does not check REQ signal before reads next byte
2171                                 d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
2172                         } else {
2173                                 if((addr & 0x0f) == 0x01) {
2174                                         // ToDo: Imprement read_1801() at Ootake v2.83.
2175                                         // ToDo: Implement _CheckCountAfterRead at CDROM.cpp of Ootake v2.83.
2176                                 }
2177                         }
2178                 }
2179                 break;
2180                 
2181         case 0x02:  /* ADPCM / CD control */
2182                 break;
2183                 
2184         case 0x03:  /* BRAM lock / CD status */
2185                 // from Ootake
2186                 backup_locked = true;
2187                 data |= PCE_CD_IRQ_BRAM;
2188                 cdrom_regs[3] ^= 0x02;
2189                 if(cdrom_regs[2] == 0) {
2190                         cdrom_regs[3] &= 0x02;
2191                 }
2192                 set_cdrom_irq_line(0, 0);
2193                 break;
2194                 
2195         case 0x04:  /* CD reset */
2196                 break;
2197                 
2198         case 0x05:  /* Convert PCM data / PCM data */
2199                 data = (d_scsi_cdrom->read_signal((cdrom_regs[3] & 0x02) ? SIG_SCSI_CDROM_SAMPLE_L : SIG_SCSI_CDROM_SAMPLE_R) >> 0) & 0xff;
2200                 break;
2201                 
2202         case 0x06:  /* PCM data */
2203                 data = (d_scsi_cdrom->read_signal((cdrom_regs[3] & 0x02) ? SIG_SCSI_CDROM_SAMPLE_L : SIG_SCSI_CDROM_SAMPLE_R) >> 8) & 0xff;
2204                 break;
2205                 
2206         case 0x07:  /* BRAM unlock / CD status */
2207                 data = (backup_locked ? (data & 0x7f) : (data | 0x80));
2208                 break;
2209                 
2210         case 0x0a:  /* ADPCM RAM data port */
2211                 if(adpcm_read_buf > 0) {
2212                         adpcm_read_buf--;
2213                         data = 0x00;
2214                 } else {
2215                         data = read_adpcm_ram();
2216                 }
2217                 break;
2218                 
2219         case 0x0b:  /* ADPCM DMA control */
2220                 break;
2221                 
2222         case 0x0c:  /* ADPCM status */
2223                 // Hack from Ootake v2.83.
2224                 if(adpcm_play_in_progress) {
2225                         data = data & ~0x85;
2226                         data = data | 0x08;
2227                 } else {
2228                         data = data | 0x01;
2229                         data = data & ~0x0c;
2230                 }
2231                 cdrom_regs[0x0c] = data;
2232                 // ToDo: HuVideo
2233                 break;
2234         case 0x09:  /* ADPCM address (MSB) */
2235         case 0x0d:  /* ADPCM address control */
2236         case 0x0e:  /* ADPCM playback rate */
2237         case 0x0f:  /* ADPCM and CD audio fade timer */
2238                 data = 0;
2239                 break;
2240         }
2241         return data;
2242 }
2243
2244 void PCE::write_cdrom_data(uint8_t data)
2245 {
2246         d_scsi_host->write_dma_io8(0, data);
2247 }
2248
2249 uint8_t PCE::read_cdrom_data()
2250 {
2251         
2252         return d_scsi_host->read_dma_io8(0);
2253 }
2254
2255 void PCE::reset_adpcm()
2256 {
2257         touch_sound();
2258         // reset ADPCM hardware
2259         adpcm_read_ptr = adpcm_write_ptr = 0;
2260         msm_start_addr = msm_end_addr = msm_half_addr = 0;
2261         msm_nibble = 0;
2262         adpcm_stop(false);
2263         d_msm->reset_w(1);
2264         out_debug_log(_T("RESET ADPCM\n"));
2265         
2266         // stop ADPCM dma
2267         adpcm_dma_enabled = false;
2268 }
2269
2270 void PCE::write_adpcm_ram(uint8_t data)
2271 {
2272         adpcm_ram[(adpcm_write_ptr++) & 0xffff] = data;
2273 //      adpcm_write_ptr = adpcm_write_ptr & 0xffff;
2274 }
2275
2276 uint8_t PCE::read_adpcm_ram()
2277 {
2278         uint8_t _data = adpcm_ram[(adpcm_read_ptr++) & 0xffff];
2279 //      adpcm_read_ptr = adpcm_read_ptr & 0xffff;
2280         return _data;
2281 }
2282
2283 void PCE::adpcm_do_dma()
2284 {
2285         write_adpcm_ram(read_cdrom_data());
2286         adpcm_written++;
2287         set_ack();
2288         cdrom_regs[0x0c] &= ~0x04;
2289 }
2290
2291 void PCE::adpcm_play()
2292 {
2293         touch_sound();
2294         cdrom_regs[0x0c] &= ~PCE_CD_ADPCM_STOP_FLAG;
2295         cdrom_regs[0x0c] |= PCE_CD_ADPCM_PLAY_FLAG;
2296         set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_FULL_PLAY, CLEAR_LINE);
2297         //set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_HALF_PLAY, CLEAR_LINE);
2298         cdrom_regs[0x03] &= ~0x0c;
2299         msm_idle = 0;
2300 }
2301
2302 void PCE::adpcm_stop(bool do_irq)
2303 {
2304         touch_sound();
2305         cdrom_regs[0x0c] |= PCE_CD_ADPCM_STOP_FLAG;
2306         cdrom_regs[0x0c] &= ~PCE_CD_ADPCM_PLAY_FLAG;
2307         if(do_irq) {
2308                 set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_FULL_PLAY, ASSERT_LINE);
2309         }
2310         cdrom_regs[0x0d] &= ~0x60;
2311         msm_idle = 1;
2312         adpcm_play_in_progress = false;
2313 //      adpcm_dma_enabled = false;
2314         out_debug_log(_T("ADPCM STOP PLAY PTR=%04x IRQ=%s\n"), msm_start_addr, (do_irq) ? _T("YES") : _T("NO"));
2315 }
2316
2317 void PCE::set_ack()
2318 {
2319         cdrom_regs[0x03] |= 0x40; // From Ootake v2.38
2320         d_scsi_host->write_signal(SIG_SCSI_ACK, 1, 1);
2321 }
2322
2323 void PCE::clear_ack()
2324 {
2325         cdrom_regs[0x03] &= ~0x40; // From Ootake v2.38
2326         if(d_scsi_host->read_signal(SIG_SCSI_CD) != 0) {
2327                 cdrom_regs[0x0b] &= 0xfc;
2328         }
2329         d_scsi_host->write_signal(SIG_SCSI_ACK, 0, 0);
2330 }
2331
2332 void PCE::set_cdrom_irq_line(int num, int state)
2333 {
2334         if (state == ASSERT_LINE) {
2335                 cdrom_regs[0x03] |= num;
2336         } else {
2337                 cdrom_regs[0x03] &= ~num;
2338         }
2339         if (cdrom_regs[0x02] & cdrom_regs[0x03] & 0x7c) {
2340                 d_cpu->write_signal(INPUT_LINE_IRQ2, ASSERT_LINE, 0);
2341         } else {
2342                 d_cpu->write_signal(INPUT_LINE_IRQ2, CLEAR_LINE, 0);
2343         }
2344 }
2345
2346 void PCE::cdda_fade_in(int time)
2347 {
2348         if(event_cdda_fader != -1) {
2349                 cancel_event(this, event_cdda_fader);
2350         }
2351         register_event(this, EVENT_CDDA_FADE_IN, time, true, &event_cdda_fader);
2352         d_scsi_cdrom->set_volume((int)(cdda_volume = 0.0));
2353 }
2354
2355 void PCE::cdda_fade_out(int time)
2356 {
2357         if(event_cdda_fader != -1) {
2358                 cancel_event(this, event_cdda_fader);
2359         }
2360         register_event(this, EVENT_CDDA_FADE_OUT, time, true, &event_cdda_fader);
2361         d_scsi_cdrom->set_volume((int)(cdda_volume = 100.0));
2362 }
2363
2364 void PCE::adpcm_fade_in(int time)
2365 {
2366         if(event_adpcm_fader != -1) {
2367                 cancel_event(this, event_adpcm_fader);
2368         }
2369         register_event(this, EVENT_ADPCM_FADE_IN, time, true, &event_adpcm_fader);
2370         d_msm->set_volume((int)(adpcm_volume = 0.0));
2371 }
2372
2373 void PCE::adpcm_fade_out(int time)
2374 {
2375         if(event_adpcm_fader != -1) {
2376                 cancel_event(this, event_adpcm_fader);
2377         }
2378         register_event(this, EVENT_ADPCM_FADE_OUT, time, true, &event_adpcm_fader);
2379         d_msm->set_volume((int)(adpcm_volume = 100.0));
2380 }
2381
2382 void PCE::write_signal(int id, uint32_t data, uint32_t mask)
2383 {
2384         switch(id) {
2385         case SIG_PCE_SCSI_IRQ:
2386                 if(data & mask) {
2387                         if(!irq_status) {
2388                                 irq_status = true;
2389                                 
2390                                 if(d_scsi_host->read_signal(SIG_SCSI_BSY) != 0 &&
2391                                    d_scsi_host->read_signal(SIG_SCSI_CD ) != 0 &&
2392                                    d_scsi_host->read_signal(SIG_SCSI_MSG) == 0 &&
2393                                    d_scsi_host->read_signal(SIG_SCSI_IO ) != 0) {
2394                                         // status phase, command is finished
2395                                         set_cdrom_irq_line(PCE_CD_IRQ_TRANSFER_READY, CLEAR_LINE);
2396                                         set_cdrom_irq_line(PCE_CD_IRQ_TRANSFER_DONE, ASSERT_LINE);
2397                                 }
2398                                 // clear busreq because next REQ signal is raised
2399                                 d_cpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
2400                         }
2401                 } else {
2402                         if(irq_status) {
2403                                 irq_status = false;
2404                         }
2405                 }
2406                 break;
2407                 
2408         case SIG_PCE_SCSI_DRQ:
2409                 if(data & mask) {
2410                         if(!drq_status) {
2411                                 drq_status = true;
2412                                 set_cdrom_irq_line(PCE_CD_IRQ_TRANSFER_READY, ASSERT_LINE);
2413                                 
2414                                 // clear busreq because next REQ signal is raised
2415                                 d_cpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
2416                                 
2417                                 if(adpcm_dma_enabled) {
2418                                         if(!(msm_idle) && ((adpcm_write_ptr & 0xffff) >= (msm_start_addr & 0xffff))) {
2419                                                 // now streaming, wait dma not to overwrite buffer before it is played
2420                                                 cdrom_regs[0x0b] = 0x00; // From Ootake v2.38.
2421                                                 //adpcm_do_dma();
2422                                         } else {
2423                                                 adpcm_do_dma();
2424                                         }
2425                                 }
2426                         }
2427                 } else {
2428                         if(drq_status) {
2429                                 drq_status = false;
2430                                 
2431                                 if(d_scsi_cdrom->get_cur_command() == SCSI_CMD_READ6 &&
2432                                    d_scsi_host->read_signal(SIG_SCSI_BSY) != 0 &&
2433                                    d_scsi_host->read_signal(SIG_SCSI_CD ) == 0 &&
2434                                    d_scsi_host->read_signal(SIG_SCSI_MSG) == 0 &&
2435                                    d_scsi_host->read_signal(SIG_SCSI_IO ) != 0) {
2436                                         // clear ack automatically and immediately for correct transfer speed
2437                                         clear_ack();
2438                                 }
2439                         }
2440                 }
2441                 break;
2442                 
2443         case SIG_PCE_SCSI_BSY:
2444                 if(!(data & mask)) {
2445                         // bus free
2446                         set_cdrom_irq_line(PCE_CD_IRQ_TRANSFER_READY, CLEAR_LINE);
2447                         set_cdrom_irq_line(PCE_CD_IRQ_TRANSFER_DONE, CLEAR_LINE);
2448                         if(!(adpcm_play_in_progress) && (adpcm_dma_enabled)){
2449                                 d_msm->reset_w(1);
2450                                 adpcm_dma_enabled = false;
2451                                 out_debug_log(_T("SIG_PCE_SCSI_BSY: RESET ADPCM\n"));
2452                         }
2453                 }
2454                 break;
2455                 
2456         case SIG_PCE_CDDA_DONE:
2457                 touch_sound();
2458                 if(data & mask) {
2459                         set_cdrom_irq_line(PCE_CD_IRQ_TRANSFER_DONE, ASSERT_LINE);
2460                 }
2461                 break;
2462                 
2463         case SIG_PCE_ADPCM_VCLK:
2464                 // Callback for new data from the MSM5205.
2465                 // The PCE cd unit actually divides the clock signal supplied to
2466                 // the MSM5205. Currently we can only use static clocks for the
2467                 // MSM5205.
2468                 if((data & mask) == 0) {
2469                 if(!msm_idle) {
2470                         uint8_t msm_data = (msm_nibble) ? (adpcm_ram[msm_start_addr & 0xffff] & 0x0f) : ((adpcm_ram[msm_start_addr & 0xffff] & 0xf0) >> 4);
2471                         d_msm->data_w(msm_data);
2472                         msm_nibble ^= 1;
2473                         
2474                         if(msm_nibble == 0) {
2475                                 adpcm_written--;
2476                                 // 20181213 K.O: Re-order sequence from Ootake v2.83.Thanks to developers of Ootake.
2477                                 if((msm_start_addr & 0xffff) == msm_end_addr) {
2478                                         // reached to end address
2479                                         if(adpcm_dma_enabled) {
2480                                                 // restart streaming
2481                                                 set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_HALF_PLAY, CLEAR_LINE);
2482                                                 set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_FULL_PLAY, CLEAR_LINE);
2483                                                 //set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_FULL_PLAY, ASSERT_LINE);
2484                                                 out_debug_log(_T("END ADDRESS(DMA) READ_PTR=%04x WRITE_PTR=%04x\n"), adpcm_read_ptr, adpcm_write_ptr);
2485                                         } else {
2486                                                 // stop playing adpcm
2487                                                 set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_HALF_PLAY, CLEAR_LINE);
2488                                                 set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_FULL_PLAY, ASSERT_LINE);
2489                                                 adpcm_stop(true);
2490                                                 d_msm->reset_w(1);
2491                                                 out_debug_log(_T("END ADDRESS(NON-DMA) READ_PTR=%04x WRITE_PTR=%04x\n"), adpcm_read_ptr, adpcm_write_ptr);
2492                                         }
2493                                 } else if(adpcm_dma_enabled && adpcm_written == 0) {
2494                                         // finish streaming when all samples are played
2495                                         set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_HALF_PLAY, CLEAR_LINE);
2496                                         set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_FULL_PLAY, ASSERT_LINE);
2497                                         adpcm_stop(true);
2498                                         d_msm->reset_w(1);
2499                                 } else if((msm_start_addr & 0xffff) == msm_half_addr) {
2500                                         // reached to half address
2501                                         // 20181213 K.O: Porting from Ootake v2.83.Thanks to developers of Ootake.
2502                                         if((adpcm_dma_enabled) && (adpcm_length >= 0x8000) && (adpcm_length <= 0x80ff)) {
2503                                                 msm_half_addr = (msm_half_addr + 0x85) & 0xffff;
2504                                         } else if(adpcm_length < 0x7fff) {
2505                                                 msm_half_addr = (msm_half_addr + (uint16_t)(adpcm_length - 1024)) & 0xffff;
2506                                         }
2507                                         set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_FULL_PLAY, CLEAR_LINE);
2508                                         set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_HALF_PLAY, ASSERT_LINE);
2509                                         out_debug_log(_T("HALF ADDRESS READ_PTR=%04x WRITE_PTR=%04x\n"), adpcm_read_ptr, adpcm_write_ptr);
2510                                 } else if((!((adpcm_dma_enabled) && (adpcm_length >= 0x8000) && (adpcm_length <= 0x80ff)) &&
2511                                                    !(adpcm_length < 0x7fff)) &&
2512                                                   (((msm_start_addr & 0xffff) == 0x8000) || ((msm_start_addr & 0xffff) == 0x0000))) {
2513                                         // 20181213 K.O: Porting from Ootake v2.83.Thanks to developers of Ootake.
2514                                         set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_FULL_PLAY, CLEAR_LINE);
2515                                         set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_HALF_PLAY, ASSERT_LINE);
2516                                         out_debug_log(_T("HALF ADDRESS READ_PTR=%04x WRITE_PTR=%04x\n"), adpcm_read_ptr, adpcm_write_ptr);
2517                                 } 
2518                                 
2519                                 msm_start_addr++;
2520                                 //msm_start_addr = msm_start_addr & 0xffff;
2521                                 if(adpcm_dma_enabled) {
2522                                         if(!(msm_idle) && (adpcm_write_ptr < msm_start_addr)) {
2523                                                 if(d_scsi_cdrom->get_cur_command() == SCSI_CMD_READ6 &&
2524                                                    d_scsi_host->read_signal(SIG_SCSI_BSY) != 0 &&
2525                                                    d_scsi_host->read_signal(SIG_SCSI_REQ) != 0 &&
2526                                                    d_scsi_host->read_signal(SIG_SCSI_CD ) == 0 &&
2527                                                    d_scsi_host->read_signal(SIG_SCSI_MSG) == 0 &&
2528                                                    d_scsi_host->read_signal(SIG_SCSI_IO ) != 0) {
2529                                                         // already data is received, read next byte
2530                                                         adpcm_do_dma();
2531                                                 }
2532                                         }
2533                                 } else {
2534                                 }
2535                         }
2536                 }
2537                 }
2538                 break;
2539         }
2540 }
2541
2542 void PCE::event_callback(int event_id, int err)
2543 {
2544         switch(event_id) {
2545         case EVENT_CDDA_FADE_IN:
2546                 if((cdda_volume += 0.1) >= 100.0) {
2547                         cancel_event(this, event_cdda_fader);
2548                         event_cdda_fader = -1;
2549                         cdda_volume = 100.0;
2550                 }
2551                 d_scsi_cdrom->set_volume((int)cdda_volume);
2552                 break;
2553                 
2554         case EVENT_CDDA_FADE_OUT:
2555                 if((cdda_volume -= 0.1) <= 0) {
2556                         cancel_event(this, event_cdda_fader);
2557                         event_cdda_fader = -1;
2558                         cdda_volume = 0.0;
2559                 }
2560                 d_scsi_cdrom->set_volume((int)cdda_volume);
2561                 break;
2562                 
2563         case EVENT_ADPCM_FADE_IN:
2564                 if((adpcm_volume += 0.1) >= 100.0) {
2565                         cancel_event(this, event_adpcm_fader);
2566                         event_adpcm_fader = -1;
2567                         adpcm_volume = 100.0;
2568                 }
2569                 d_msm->set_volume((int)adpcm_volume);
2570                 break;
2571                 
2572         case EVENT_ADPCM_FADE_OUT:
2573                 if((adpcm_volume -= 0.1) <= 0) {
2574                         cancel_event(this, event_adpcm_fader);
2575                         event_adpcm_fader = -1;
2576                         adpcm_volume = 0.0;
2577                 }
2578                 d_msm->set_volume((int)adpcm_volume);
2579                 break;
2580         }
2581 }
2582 #endif
2583
2584 #define STATE_VERSION   6
2585
2586 void process_state_vdc(vdc_t* val, FILEIO* state_fio)
2587 {
2588         state_fio->StateValue(val->dvssr_write);
2589         state_fio->StateValue(val->physical_width);
2590         state_fio->StateValue(val->physical_height);
2591         state_fio->StateArray(val->sprite_ram, sizeof(val->sprite_ram), 1);
2592         state_fio->StateValue(val->curline);
2593         state_fio->StateValue(val->current_segment);
2594         state_fio->StateValue(val->current_segment_line);
2595         state_fio->StateValue(val->vblank_triggered);
2596         state_fio->StateValue(val->raster_count);
2597         state_fio->StateValue(val->satb_countdown);
2598         state_fio->StateArray(val->vram, sizeof(val->vram), 1);
2599         state_fio->StateValue(val->inc);
2600         state_fio->StateValue(val->vdc_register);
2601         state_fio->StateValue(val->vdc_latch);
2602         state_fio->StateArray(val->vdc_data, sizeof(val->vdc_data), 1);
2603         state_fio->StateValue(val->status);
2604         state_fio->StateValue(val->y_scroll);
2605 }
2606
2607 void process_state_vce(vce_t* val, FILEIO* state_fio)
2608 {
2609         state_fio->StateValue(val->vce_control);
2610         state_fio->StateValue(val->vce_address);
2611         state_fio->StateArray(val->vce_data, sizeof(val->vce_data), 1);
2612         state_fio->StateValue(val->current_bitmap_line);
2613         state_fio->StateArrayScrnType_t(&val->bmp[0][0], sizeof(val->bmp), 1);
2614         state_fio->StateArrayScrnType_t(val->palette, sizeof(val->palette), 1);
2615 }
2616
2617 void process_state_vpc(vpc_t* val, FILEIO* state_fio)
2618 {
2619         for(int i = 0; i < array_length(val->vpc_prio); i++) {
2620                 state_fio->StateValue(val->vpc_prio[i].prio);
2621                 state_fio->StateValue(val->vpc_prio[i].vdc0_enabled);
2622                 state_fio->StateValue(val->vpc_prio[i].vdc1_enabled);
2623         }
2624         state_fio->StateArray(val->prio_map, sizeof(val->prio_map), 1);
2625         state_fio->StateValue(val->priority);
2626         state_fio->StateValue(val->window1);
2627         state_fio->StateValue(val->window2);
2628         state_fio->StateValue(val->vdc_select);
2629 }
2630
2631 void process_state_psg(psg_t* val, FILEIO* state_fio)
2632 {
2633         state_fio->StateArray(val->regs, sizeof(val->regs), 1);
2634         state_fio->StateArray(val->wav, sizeof(val->wav), 1);
2635         state_fio->StateValue(val->wavptr);
2636         state_fio->StateValue(val->genptr);
2637         state_fio->StateValue(val->remain);
2638         state_fio->StateValue(val->noise);
2639         state_fio->StateValue(val->randval);
2640 }
2641
2642 bool PCE::process_state(FILEIO* state_fio, bool loading)
2643 {
2644         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
2645                 return false;
2646         }
2647         if(!state_fio->StateCheckInt32(this_device_id)) {
2648                 return false;
2649         }
2650         state_fio->StateValue(support_6btn_pad);
2651         state_fio->StateValue(support_multi_tap);
2652  #ifdef SUPPORT_SUPER_GFX
2653         state_fio->StateValue(support_sgfx);
2654  #endif
2655  #ifdef SUPPORT_CDROM
2656         state_fio->StateValue(support_cdrom);
2657  #endif
2658         state_fio->StateArray(ram, sizeof(ram), 1);
2659         state_fio->StateArray(cart + 0x80000, 0x80000, 1);
2660  #ifdef SUPPORT_BACKUP_RAM
2661         state_fio->StateArray(backup, sizeof(backup), 1);
2662         state_fio->StateValue(backup_crc32);
2663  #endif
2664         state_fio->StateValue(bank);
2665         state_fio->StateValue(buffer);
2666         state_fio->StateValue(prev_width);
2667         state_fio->StateValue(inserted);
2668         for(int i = 0; i < array_length(vdc); i++) {
2669                 process_state_vdc(&vdc[i], state_fio);
2670         }
2671         process_state_vce(&vce, state_fio);
2672         process_state_vpc(&vpc, state_fio);
2673         for(int i = 0; i < array_length(psg); i++) {
2674                 process_state_psg(&psg[i], state_fio);
2675         }
2676         state_fio->StateValue(psg_ch);
2677         state_fio->StateValue(psg_vol);
2678         state_fio->StateValue(psg_lfo_freq);
2679         state_fio->StateValue(psg_lfo_ctrl);
2680         state_fio->StateValue(joy_counter);
2681         state_fio->StateValue(joy_high_nibble);
2682         state_fio->StateValue(joy_second_byte);
2683 #ifdef SUPPORT_CDROM
2684         state_fio->StateArray(cdrom_ram, sizeof(cdrom_ram), 1);
2685         state_fio->StateArray(cdrom_regs, sizeof(cdrom_regs), 1);
2686         state_fio->StateValue(backup_locked);
2687         state_fio->StateValue(irq_status);
2688         state_fio->StateValue(drq_status);
2689         state_fio->StateArray(adpcm_ram, sizeof(adpcm_ram), 1);
2690         state_fio->StateValue(adpcm_read_ptr);
2691         state_fio->StateValue(adpcm_write_ptr);
2692         state_fio->StateValue(adpcm_written);
2693         state_fio->StateValue(adpcm_length);
2694         state_fio->StateValue(adpcm_clock_divider);
2695         state_fio->StateValue(adpcm_read_buf);
2696         state_fio->StateValue(adpcm_write_buf);
2697         state_fio->StateValue(adpcm_dma_enabled);
2698         state_fio->StateValue(msm_start_addr);
2699         state_fio->StateValue(msm_end_addr);
2700         state_fio->StateValue(msm_half_addr);
2701         state_fio->StateValue(msm_nibble);
2702         state_fio->StateValue(msm_idle);
2703         state_fio->StateValue(cdda_volume);
2704         state_fio->StateValue(adpcm_volume);
2705         state_fio->StateValue(event_cdda_fader);
2706         state_fio->StateValue(event_adpcm_fader);
2707         state_fio->StateValue(adpcm_play_in_progress);
2708 #endif
2709         return true;
2710 }
2711
2712 }