OSDN Git Service

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