OSDN Git Service

6aca8eba0a05bee6f7bbaef42cbc19f04c829ef5
[csp-qt/common_source_project-fm7.git] / source / src / vm / pc100 / crtc.cpp
1 /*
2         NEC PC-100 Emulator 'ePC-100'
3
4         Author : Takeda.Toshiya
5         Date   : 2008.07.14 -
6
7         [ crtc ]
8 */
9
10 #include "crtc.h"
11 #include "../i8259.h"
12
13 void CRTC::initialize()
14 {
15         // init vram
16         memset(vram, 0, sizeof(vram));
17         
18         // init bit control
19         shift = 0;
20         maskl = maskh = busl = bush = 0;
21         
22         // init vram plane
23         write_plane = 1;
24         read_plane = 0;
25         
26         // init pallete
27         for(int i = 1; i < 16; i++) {
28                 palette[i] = 0x1ff;
29                 update_palette(i);
30         }
31         palette[0] = 0;
32         update_palette(0);
33         
34         // register event
35         register_vline_event(this);
36 }
37
38 void CRTC::event_vline(int v, int clock)
39 {
40         if(v == 512) {
41                 d_pic->write_signal(SIG_I8259_IR4, 1, 1);
42         }
43 }
44
45 void CRTC::write_io8(uint32_t addr, uint32_t data)
46 {
47         switch(addr & 0xff) {
48         case 0x30:
49                 shift = data & 0x0f;
50                 break;
51         case 0x38:
52                 sel = data;
53                 break;
54         case 0x3a:
55                 regs[sel & 7] = data;
56                 break;
57         case 0x3c:
58                 vs = (vs & 0xff00) | data;
59                 break;
60         case 0x3e:
61                 vs = (vs & 0xff) | (data << 8);
62                 break;
63         case 0x40:
64         case 0x42:
65         case 0x44:
66         case 0x46:
67         case 0x48:
68         case 0x4a:
69         case 0x4c:
70         case 0x4e:
71         case 0x50:
72         case 0x52:
73         case 0x54:
74         case 0x56:
75         case 0x58:
76         case 0x5a:
77         case 0x5c:
78         case 0x5e:
79                 palette[(addr >> 1) & 0x0f] = (palette[(addr >> 1) & 0x0f] & 0xff00) | data;
80                 update_palette((addr >> 1) & 0x0f);
81                 break;
82         case 0x41:
83         case 0x43:
84         case 0x45:
85         case 0x47:
86         case 0x49:
87         case 0x4b:
88         case 0x4d:
89         case 0x4f:
90         case 0x51:
91         case 0x53:
92         case 0x55:
93         case 0x57:
94         case 0x59:
95         case 0x5b:
96         case 0x5d:
97         case 0x5f:
98                 palette[(addr >> 1) & 0x0f] = (palette[(addr >> 1) & 0x0f] & 0xff) | (data << 8);
99                 update_palette((addr >> 1) & 0x0f);
100                 break;
101         case 0x60:
102                 cmd = (cmd & 0xff00) | data;
103                 break;
104         case 0x61:
105                 cmd = (cmd & 0xff) | (data << 8);
106                 break;
107         }
108 }
109
110 uint32_t CRTC::read_io8(uint32_t addr)
111 {
112         uint32_t val = 0xff;
113         
114         switch(addr & 0x3ff) {
115         case 0x30:
116                 return shift;
117         case 0x38:
118                 return sel;
119         case 0x3a:
120                 return regs[sel & 7];
121         case 0x3c:
122                 return vs & 0xff;
123         case 0x3e:
124                 return vs >> 8;
125         case 0x40:
126         case 0x42:
127         case 0x44:
128         case 0x46:
129         case 0x48:
130         case 0x4a:
131         case 0x4c:
132         case 0x4e:
133         case 0x50:
134         case 0x52:
135         case 0x54:
136         case 0x56:
137         case 0x58:
138         case 0x5a:
139         case 0x5c:
140         case 0x5e:
141                 return palette[(addr >> 1) & 0x0f] & 0xff;
142         case 0x41:
143         case 0x43:
144         case 0x45:
145         case 0x47:
146         case 0x49:
147         case 0x4b:
148         case 0x4d:
149         case 0x4f:
150         case 0x51:
151         case 0x53:
152         case 0x55:
153         case 0x57:
154         case 0x59:
155         case 0x5b:
156         case 0x5d:
157         case 0x5f:
158                 return palette[(addr >> 1) & 0x0f] >> 8;
159         case 0x60:
160                 return cmd & 0xff;
161         case 0x61:
162                 return cmd >> 8;
163         }
164         return 0xff;
165 }
166
167 void CRTC::write_memory_mapped_io8(uint32_t addr, uint32_t data)
168 {
169         if(addr & 1) {
170                 bush = data;
171         } else {
172                 busl = data;
173         }
174         uint32_t bus = busl | (bush << 8) | (busl << 16) | (bush << 24);
175         bus >>= shift;
176         
177         if(addr & 1) {
178                 uint32_t h = (bus >> 8) & 0xff;
179                 for(int pl = 0; pl < 4; pl++) {
180                         if(write_plane & (1 << pl)) {
181                                 int ofsh = (addr & 0x1ffff) | (0x20000 * pl);
182                                 vram[ofsh] = (vram[ofsh] & maskh) | (h & ~maskh);
183                         }
184                 }
185         } else {
186                 uint32_t l = bus & 0xff;
187                 for(int pl = 0; pl < 4; pl++) {
188                         if(write_plane & (1 << pl)) {
189                                 int ofsl = (addr & 0x1ffff) | (0x20000 * pl);
190                                 vram[ofsl] = (vram[ofsl] & maskl) | (l & ~maskl);
191                         }
192                 }
193         }
194 }
195
196 uint32_t CRTC::read_memory_mapped_io8(uint32_t addr)
197 {
198         return vram[(addr & 0x1ffff) | (0x20000 * read_plane)];
199 }
200
201 void CRTC::write_memory_mapped_io16(uint32_t addr, uint32_t data)
202 {
203         busl = (addr & 1) ? (data >> 8) : (data & 0xff);
204         bush = (addr & 1) ? (data & 0xff) : (data >> 8);
205         uint32_t bus = busl | (bush << 8) | (busl << 16) | (bush << 24);
206         bus >>= shift;
207         uint32_t l = bus & 0xff;
208         uint32_t h = (bus >> 8) & 0xff;
209         
210         for(int pl = 0; pl < 4; pl++) {
211                 if(write_plane & (1 << pl)) {
212                         int ofsl = ((addr & 1 ? (addr + 1) : addr) & 0x1ffff) | (0x20000 * pl);
213                         int ofsh = ((addr & 1 ? addr : (addr + 1)) & 0x1ffff) | (0x20000 * pl);
214                         vram[ofsl] = (vram[ofsl] & maskl) | (l & ~maskl);
215                         vram[ofsh] = (vram[ofsh] & maskh) | (h & ~maskh);
216                 }
217         }
218 }
219
220 uint32_t CRTC::read_memory_mapped_io16(uint32_t addr)
221 {
222         uint32_t val = read_memory_mapped_io8(addr);
223         val |= read_memory_mapped_io8(addr + 1) << 8;
224         return val;
225 }
226
227 void CRTC::write_signal(int id, uint32_t data, uint32_t mask)
228 {
229         if(id == SIG_CRTC_BITMASK_LOW) {
230                 // $18: 8255 PA
231                 maskl = data & 0xff;
232         } else if(id == SIG_CRTC_BITMASK_HIGH) {
233                 // $1A: 8255 PB
234                 maskh = data & 0xff;
235         } else if(id == SIG_CRTC_VRAM_PLANE) {
236                 // $1C: 8255 PC
237                 write_plane = data & 0x0f;
238                 read_plane = (data >> 4) & 3;
239         }
240 }
241
242 void CRTC::draw_screen()
243 {
244         // display region
245         int hd = (regs[2] >> 1) & 0x3f;
246         int vd = (regs[6] >> 1) & 0x3f;
247         int hs = (int)(int8_t)((regs[0] & 0x40) ? (regs[0] | 0x80) : (regs[0] & 0x3f));
248 //      int hs = (int)(int8_t)regs[0];
249         int vs_tmp = (int)(int16_t)((vs & 0x400) ? (vs | 0xf800) : (vs & 0x3ff));
250         int sa = (hs + hd + 1) * 2 + (vs_tmp + vd) * 0x80;
251 //      int sa = (hs + hd + 1) * 2 + ((vs & 0x3ff) + vd) * 0x80;
252         
253         if(cmd != 0xffff) {
254                 // mono
255                 scrntype_t col = RGB_COLOR(255, 255, 255);
256                 for(int y = 0; y < 512; y++) {
257                         int ptr = sa & 0x1ffff;
258                         sa += 0x80;
259                         scrntype_t *dest = emu->get_screen_buffer(y);
260                         
261                         for(int x = 0; x < 720; x += 8) {
262                                 uint8_t pat = vram[ptr];
263                                 ptr = (ptr + 1) & 0x1ffff;
264                                 
265                                 dest[x + 0] = pat & 0x01 ? col : 0;
266                                 dest[x + 1] = pat & 0x02 ? col : 0;
267                                 dest[x + 2] = pat & 0x04 ? col : 0;
268                                 dest[x + 3] = pat & 0x08 ? col : 0;
269                                 dest[x + 4] = pat & 0x10 ? col : 0;
270                                 dest[x + 5] = pat & 0x20 ? col : 0;
271                                 dest[x + 6] = pat & 0x40 ? col : 0;
272                                 dest[x + 7] = pat & 0x80 ? col : 0;
273                         }
274                 }
275         } else {
276                 // color
277                 for(int y = 0; y < 512; y++) {
278                         int ptr = sa & 0x1ffff;
279                         sa += 0x80;
280                         scrntype_t *dest = emu->get_screen_buffer(y);
281                         
282                         for(int x = 0; x < 720; x += 8) {
283                                 uint8_t p0 = vram[0x00000 | ptr];
284                                 uint8_t p1 = vram[0x20000 | ptr];
285                                 uint8_t p2 = vram[0x40000 | ptr];
286                                 uint8_t p3 = vram[0x60000 | ptr];
287                                 ptr = (ptr + 1) & 0x1ffff;
288                                 
289                                 dest[x + 0] = palette_pc[((p0 & 0x01) << 0) | ((p1 & 0x01) << 1) | ((p2 & 0x01) << 2) | ((p3 & 0x01) << 3)];
290                                 dest[x + 1] = palette_pc[((p0 & 0x02) >> 1) | ((p1 & 0x02) << 0) | ((p2 & 0x02) << 1) | ((p3 & 0x02) << 2)];
291                                 dest[x + 2] = palette_pc[((p0 & 0x04) >> 2) | ((p1 & 0x04) >> 1) | ((p2 & 0x04) << 0) | ((p3 & 0x04) << 1)];
292                                 dest[x + 3] = palette_pc[((p0 & 0x08) >> 3) | ((p1 & 0x08) >> 2) | ((p2 & 0x08) >> 1) | ((p3 & 0x08) << 0)];
293                                 dest[x + 4] = palette_pc[((p0 & 0x10) >> 4) | ((p1 & 0x10) >> 3) | ((p2 & 0x10) >> 2) | ((p3 & 0x10) >> 1)];
294                                 dest[x + 5] = palette_pc[((p0 & 0x20) >> 5) | ((p1 & 0x20) >> 4) | ((p2 & 0x20) >> 3) | ((p3 & 0x20) >> 2)];
295                                 dest[x + 6] = palette_pc[((p0 & 0x40) >> 6) | ((p1 & 0x40) >> 5) | ((p2 & 0x40) >> 4) | ((p3 & 0x40) >> 3)];
296                                 dest[x + 7] = palette_pc[((p0 & 0x80) >> 7) | ((p1 & 0x80) >> 6) | ((p2 & 0x80) >> 5) | ((p3 & 0x80) >> 4)];
297                         }
298                 }
299         }
300         emu->screen_skip_line(false);
301 }
302
303 void CRTC::update_palette(int num)
304 {
305         int r = (palette[num] >> 0) & 7;
306         int g = (palette[num] >> 3) & 7;
307         int b = (palette[num] >> 6) & 7;
308         palette_pc[num] = RGB_COLOR(r << 5, g << 5, b << 5);
309 }
310
311 #define STATE_VERSION   1
312
313 #include "../../statesub.h"
314
315 void CRTC::decl_state()
316 {
317         enter_decl_state(STATE_VERSION);
318
319         DECL_STATE_ENTRY_SCRNTYPE_T_1D_ARRAY(palette_pc, 16);
320         DECL_STATE_ENTRY_1D_ARRAY(palette, 16);
321         DECL_STATE_ENTRY_UINT8(sel);
322         DECL_STATE_ENTRY_1D_ARRAY(regs, sizeof(regs));
323         DECL_STATE_ENTRY_UINT16(vs);
324         DECL_STATE_ENTRY_UINT16(cmd);
325         DECL_STATE_ENTRY_1D_ARRAY(vram, sizeof(vram));
326         DECL_STATE_ENTRY_UINT32(shift);
327         DECL_STATE_ENTRY_UINT32(maskl);
328         DECL_STATE_ENTRY_UINT32(maskh);
329         DECL_STATE_ENTRY_UINT32(busl);
330         DECL_STATE_ENTRY_UINT32(bush);
331         DECL_STATE_ENTRY_UINT32(write_plane);
332         DECL_STATE_ENTRY_UINT32(read_plane);
333         
334         leave_decl_state();
335 }
336         
337 void CRTC::save_state(FILEIO* state_fio)
338 {
339         if(state_entry != NULL) {
340                 state_entry->save_state(state_fio);
341         }
342 //      state_fio->FputUint32(STATE_VERSION);
343 //      state_fio->FputInt32(this_device_id);
344         
345 //      state_fio->Fwrite(palette_pc, sizeof(palette_pc), 1);
346 //      state_fio->Fwrite(palette, sizeof(palette), 1);
347 //      state_fio->FputUint8(sel);
348 //      state_fio->Fwrite(regs, sizeof(regs), 1);
349 //      state_fio->FputUint16(vs);
350 //      state_fio->FputUint16(cmd);
351 //      state_fio->Fwrite(vram, sizeof(vram), 1);
352 //      state_fio->FputUint32(shift);
353 //      state_fio->FputUint32(maskl);
354 //      state_fio->FputUint32(maskh);
355 //      state_fio->FputUint32(busl);
356 //      state_fio->FputUint32(bush);
357 //      state_fio->FputUint32(write_plane);
358 //      state_fio->FputUint32(read_plane);
359 }
360
361 bool CRTC::load_state(FILEIO* state_fio)
362 {
363         bool mb = false;
364         if(state_entry != NULL) {
365                 mb = state_entry->load_state(state_fio);
366         }
367         if(!mb) {
368                 return false;
369         }
370 //      if(state_fio->FgetUint32() != STATE_VERSION) {
371 //              return false;
372 //      }
373 //      if(state_fio->FgetInt32() != this_device_id) {
374 //              return false;
375 //      }
376 //      state_fio->Fread(palette_pc, sizeof(palette_pc), 1);
377 //      state_fio->Fread(palette, sizeof(palette), 1);
378 //      sel = state_fio->FgetUint8();
379 //      state_fio->Fread(regs, sizeof(regs), 1);
380 //      vs = state_fio->FgetUint16();
381 //      cmd = state_fio->FgetUint16();
382 //      state_fio->Fread(vram, sizeof(vram), 1);
383 //      shift = state_fio->FgetUint32();
384 //      maskl = state_fio->FgetUint32();
385 //      maskh = state_fio->FgetUint32();
386 //      busl = state_fio->FgetUint32();
387 //      bush = state_fio->FgetUint32();
388 //      write_plane = state_fio->FgetUint32();
389 //      read_plane = state_fio->FgetUint32();
390         return true;
391 }
392
393 bool CRTC::process_state(FILEIO* state_fio, bool loading)
394 {
395         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
396                 return false;
397         }
398         if(!state_fio->StateCheckInt32(this_device_id)) {
399                 return false;
400         }
401         state_fio->StateBuffer(palette_pc, sizeof(palette_pc), 1);
402         state_fio->StateBuffer(palette, sizeof(palette), 1);
403         state_fio->StateUint8(sel);
404         state_fio->StateBuffer(regs, sizeof(regs), 1);
405         state_fio->StateUint16(vs);
406         state_fio->StateUint16(cmd);
407         state_fio->StateBuffer(vram, sizeof(vram), 1);
408         state_fio->StateUint32(shift);
409         state_fio->StateUint32(maskl);
410         state_fio->StateUint32(maskh);
411         state_fio->StateUint32(busl);
412         state_fio->StateUint32(bush);
413         state_fio->StateUint32(write_plane);
414         state_fio->StateUint32(read_plane);
415         return true;
416 }