OSDN Git Service

[VM][General][WIP] Start to merge upstream 2018-10-14.Open branch upstream_20181014 .
[csp-qt/common_source_project-fm7.git] / source / src / vm / pv1000 / vdp.cpp
1 /*
2         CASIO PV-1000 Emulator 'ePV-1000'
3
4         Author : Takeda.Toshiya
5         Date   : 2006.11.16 -
6
7         [ video processor ]
8 */
9
10 #include "vdp.h"
11
12 namespace PV1000 {
13
14 static const scrntype_t palette_pc[8] = {
15         RGB_COLOR(  0,  0,  0), RGB_COLOR(255,  0,  0), RGB_COLOR(  0,255,  0), RGB_COLOR(255,255,  0),
16         RGB_COLOR(  0,  0,255), RGB_COLOR(255,  0,255), RGB_COLOR(  0,255,255), RGB_COLOR(255,255,255)
17 };
18 static const uint8_t plane[4] = {0, 1, 2, 4};
19
20 void VDP::initialize()
21 {
22         // register event to interrupt
23         register_vline_event(this);
24 }
25
26 void VDP::reset()
27 {
28         force_pattern = false;
29 }
30
31 void VDP::write_io8(uint32_t addr, uint32_t data)
32 {
33         switch(addr & 0xff) {
34         case 0xfe:
35                 vram = base + (data << 8);
36                 pcg = base + (data << 8) + 0x400;
37                 break;
38         case 0xff:
39                 pattern = base + ((data & 0x20) << 8);
40                 force_pattern = ((data & 0x10) != 0);
41                 break;
42         }
43 }
44
45 void VDP::event_callback(int event_id, int err)
46 {
47         d_cpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
48 }
49
50 void VDP::event_vline(int v, int clock)
51 {
52         if(v < LINES_PER_HBLANK) {
53                 d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
54                 register_event_by_clock(this, 0, 800, false, NULL);
55         } else {
56                 // hsync interrupt (not pending ???)
57                 d_cpu->set_intr_line(true, false, 0);
58         }
59 }
60
61 void VDP::draw_screen()
62 {
63         memset(bg, 0, sizeof(bg));
64         
65         for(int y = 0; y < 24; y++) {
66                 int y8 = y << 3, y32 = y << 5;
67                 
68                 for(int x = 2; x < 30; x++) {
69                         int x8 = x << 3;
70                         uint8_t code = vram[y32 + x];
71                         
72                         if(code < 0xe0 || force_pattern) {
73                                 draw_pattern(x8, y8, code << 5);
74                         } else {
75                                 draw_pcg(x8, y8, (code & 0x1f) << 5);
76                         }
77                 }
78         }
79         for(int y = 0; y < 192; y++) {
80                 scrntype_t* dest = emu->get_screen_buffer(y);
81                 for(int x = 0; x < 256; x++) {
82                         dest[x] = palette_pc[bg[y][x] & 7];
83                 }
84         }
85 }
86
87 void VDP::draw_pattern(int x8, int y8, uint16_t top)
88 {
89         // draw pattern on rom
90         for(int p = 1; p < 4; p++) {
91                 uint8_t col = plane[p];
92                 uint16_t p8 = top + (p << 3);
93                 
94                 for(int l = 0; l < 8; l++) {
95                         uint8_t* dest = &bg[y8 + l][x8];
96                         uint8_t pat = pattern[p8 + l];
97                         
98                         if(pat & 0x80) dest[0] |= col;
99                         if(pat & 0x40) dest[1] |= col;
100                         if(pat & 0x20) dest[2] |= col;
101                         if(pat & 0x10) dest[3] |= col;
102                         if(pat & 0x08) dest[4] |= col;
103                         if(pat & 0x04) dest[5] |= col;
104                         if(pat & 0x02) dest[6] |= col;
105                         if(pat & 0x01) dest[7] |= col;
106                 }
107         }
108 }
109
110 void VDP::draw_pcg(int x8, int y8, uint16_t top)
111 {
112         // draw pattern on ram
113         for(int p = 1; p < 4; p++) {
114                 uint8_t col = plane[p];
115                 uint16_t p8 = top + (p << 3);
116                 
117                 for(int l = 0; l < 8; l++) {
118                         uint8_t* dest = &bg[y8 + l][x8];
119                         uint8_t pat = pcg[p8 + l];
120                         
121                         if(pat & 0x80) dest[0] |= col;
122                         if(pat & 0x40) dest[1] |= col;
123                         if(pat & 0x20) dest[2] |= col;
124                         if(pat & 0x10) dest[3] |= col;
125                         if(pat & 0x08) dest[4] |= col;
126                         if(pat & 0x04) dest[5] |= col;
127                         if(pat & 0x02) dest[6] |= col;
128                         if(pat & 0x01) dest[7] |= col;
129                 }
130         }
131 }
132
133 #define STATE_VERSION   1
134
135 bool VDP::process_state(FILEIO* state_fio, bool loading)
136 {
137         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
138                 return false;
139         }
140         if(!state_fio->StateCheckInt32(this_device_id)) {
141                 return false;
142         }
143         if(loading) {
144                 vram = base + state_fio->FgetInt32_LE();
145                 pcg = base + state_fio->FgetInt32_LE();
146                 pattern = base + state_fio->FgetInt32_LE();
147         } else {
148                 state_fio->FputInt32_LE((int)(vram - base));
149                 state_fio->FputInt32_LE((int)(pcg - base));
150                 state_fio->FputInt32_LE((int)(pattern - base));
151         }
152         state_fio->StateValue(force_pattern);
153         return true;
154 }
155
156 }
157