OSDN Git Service

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