OSDN Git Service

[General] Tracking to upstream, rev 2015-01-14.
[csp-qt/common_source_project-fm7.git] / source / src / vm / mz2500 / memory80b.cpp
1 /*\r
2         SHARP MZ-80B Emulator 'EmuZ-80B'\r
3         SHARP MZ-2200 Emulator 'EmuZ-2200'\r
4 \r
5         Author : Takeda.Toshiya\r
6         Date   : 2013.03.14-\r
7 \r
8         [ memory/crtc ]\r
9 */\r
10 \r
11 #include "memory80b.h"\r
12 #include "../i8255.h"\r
13 #include "../z80.h"\r
14 #include "../../fileio.h"\r
15 \r
16 #define EVENT_HBLANK            0\r
17 \r
18 #define MONITOR_TYPE_COLOR      0\r
19 #define MONITOR_TYPE_GREEN      1\r
20 \r
21 #define SET_BANK(s, e, w, r, v) { \\r
22         int sb = (s) >> 11, eb = (e) >> 11; \\r
23         for(int i = sb; i <= eb; i++) { \\r
24                 if((w) == wdmy) { \\r
25                         wbank[i] = wdmy; \\r
26                 } else { \\r
27                         wbank[i] = (w) + 0x800 * (i - sb); \\r
28                 } \\r
29                 if((r) == rdmy) { \\r
30                         rbank[i] = rdmy; \\r
31                 } else { \\r
32                         rbank[i] = (r) + 0x800 * (i - sb); \\r
33                 } \\r
34                 is_vram[i] = v; \\r
35         } \\r
36 }\r
37 \r
38 void MEMORY::initialize()\r
39 {\r
40         // memory\r
41         memset(rdmy, 0xff, sizeof(rdmy));\r
42         memset(ram, 0, sizeof(ram));\r
43         memset(vram, 0, sizeof(vram));\r
44         memset(tvram, 0, sizeof(tvram));\r
45         memset(ipl, 0xff, sizeof(ipl));\r
46         \r
47         FILEIO* fio = new FILEIO();\r
48         if(fio->Fopen(emu->bios_path(_T("IPL.ROM")), FILEIO_READ_BINARY)) {\r
49                 fio->Fread(ipl, sizeof(ipl), 1);\r
50                 fio->Fclose();\r
51         }\r
52         if(fio->Fopen(emu->bios_path(_T("FONT.ROM")), FILEIO_READ_BINARY)) {\r
53                 fio->Fread(font, sizeof(font), 1);\r
54                 fio->Fclose();\r
55         }\r
56         delete fio;\r
57         \r
58         vram_sel = vram_page = 0;\r
59         \r
60         // crtc\r
61         back_color = 0;\r
62         text_color = vram_mask = 7;\r
63         width80 = reverse = false;\r
64         \r
65         update_palette();\r
66         register_vline_event(this);\r
67 }\r
68 \r
69 void MEMORY::reset()\r
70 {\r
71         // ipl reset\r
72         SET_BANK(0x0000, 0x07ff, wdmy, ipl, false);\r
73         SET_BANK(0x0800, 0x7fff, wdmy, rdmy, false);\r
74         SET_BANK(0x8000, 0xffff, ram, ram, false);\r
75         \r
76         ipl_selected = true;\r
77         update_vram_map();\r
78 }\r
79 \r
80 void MEMORY::special_reset()\r
81 {\r
82         // reset\r
83         SET_BANK(0x0000, 0xffff, ram, ram, false);\r
84         \r
85         ipl_selected = false;\r
86         update_vram_map();\r
87 }\r
88 \r
89 void MEMORY::write_data8(uint32 addr, uint32 data)\r
90 {\r
91         addr &= 0xffff;\r
92         if(!hblank && is_vram[addr >> 11]) {\r
93                 d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);\r
94         }\r
95         wbank[addr >> 11][addr & 0x7ff] = data;\r
96 }\r
97 \r
98 uint32 MEMORY::read_data8(uint32 addr)\r
99 {\r
100         addr &= 0xffff;\r
101         if(!hblank && is_vram[addr >> 11]) {\r
102                 d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);\r
103         }\r
104         return rbank[addr >> 11][addr & 0x7ff];\r
105 }\r
106 \r
107 uint32 MEMORY::fetch_op(uint32 addr, int *wait)\r
108 {\r
109         addr &= 0xffff;\r
110         *wait = (ipl_selected && addr < 0x800);\r
111         return rbank[addr >> 11][addr & 0x7ff];\r
112 }\r
113 \r
114 void MEMORY::write_io8(uint32 addr, uint32 data)\r
115 {\r
116         switch(addr & 0xff) {\r
117 #ifndef _MZ80B\r
118         case 0xf4:\r
119                 back_color = data & 7;\r
120                 break;\r
121         case 0xf5:\r
122                 text_color = data;\r
123                 break;\r
124         case 0xf6:\r
125                 vram_mask = data;\r
126                 break;\r
127         case 0xf7:\r
128                 if(vram_page != (data & 3)) {\r
129                         vram_page = data & 3;\r
130                         if(vram_sel == 0x80) {\r
131                                 update_vram_map();\r
132                         }\r
133                 }\r
134                 break;\r
135 #else\r
136         case 0xf4:\r
137         case 0xf5:\r
138         case 0xf6:\r
139         case 0xf7:\r
140                 if(vram_page != (data & 7)) {\r
141                         uint8 prev_page = vram_page;\r
142                         vram_page = data & 7;\r
143                         if((prev_page & 1) != (vram_page & 1) && (vram_sel == 0x80 || vram_sel == 0xc0)) {\r
144                                 update_vram_map();\r
145                         }\r
146                 }\r
147                 break;\r
148 #endif\r
149         }\r
150 }\r
151 \r
152 void MEMORY::write_signal(int id, uint32 data, uint32 mask)\r
153 {\r
154         if(id == SIG_MEMORY_VRAM_SEL) {\r
155                 if(vram_sel != (data & mask)) {\r
156                         vram_sel = data & mask;\r
157                         update_vram_map();\r
158                 }\r
159         } else if(id == SIG_CRTC_WIDTH80) {\r
160                 width80 = ((data & mask) != 0);\r
161         } else if(id == SIG_CRTC_REVERSE) {\r
162                 reverse = ((data & mask) == 0);\r
163 #ifndef _MZ80B\r
164                 if(config.monitor_type != MONITOR_TYPE_COLOR)\r
165 #endif\r
166                 update_palette();\r
167         }\r
168 }\r
169 \r
170 void MEMORY::event_vline(int v, int clock)\r
171 {\r
172         if(v == 0) {\r
173                 d_pio->write_signal(SIG_I8255_PORT_B, 1, 1);\r
174         } else if(v == 200) {\r
175                 d_pio->write_signal(SIG_I8255_PORT_B, 0, 1);\r
176         }\r
177 //      if(v < 200) {\r
178                 hblank = false;\r
179                 register_event_by_clock(this, EVENT_HBLANK, 184, false, NULL);\r
180 //      }\r
181 }\r
182 \r
183 void MEMORY::event_callback(int event_id, int err)\r
184 {\r
185         if(event_id == EVENT_HBLANK) {\r
186                 hblank = true;\r
187                 d_cpu->write_signal(SIG_CPU_BUSREQ, 0, 0);\r
188         }\r
189 }\r
190 \r
191 #ifndef _MZ80B\r
192 void MEMORY::update_config()\r
193 {\r
194         update_palette();\r
195 }\r
196 #endif\r
197 \r
198 void MEMORY::update_palette()\r
199 {\r
200 #ifndef _MZ80B\r
201         if(config.monitor_type == MONITOR_TYPE_COLOR) {\r
202                 for(int i = 0; i < 8; i++) {\r
203                         palette_pc[i] = RGB_COLOR((i & 2) ? 255 : 0, (i & 4) ? 255 : 0, (i & 1) ? 255 : 0);\r
204                 }\r
205         } else\r
206 #endif\r
207         if(reverse) {\r
208                 for(int i = 0; i < 8; i++) {\r
209                         palette_pc[i] = RGB_COLOR(0, i ? 0 : 255, 0);\r
210                 }\r
211         } else {\r
212                 for(int i = 0; i < 8; i++) {\r
213                         palette_pc[i] = RGB_COLOR(0, i ? 255 : 0, 0);\r
214                 }\r
215         }\r
216 }\r
217 \r
218 void MEMORY::update_vram_map()\r
219 {\r
220 #ifndef _MZ80B\r
221         if(vram_sel == 0x80) {\r
222                 if(vram_page) {\r
223                         SET_BANK(0xc000, 0xffff, vram + 0x4000 * vram_page, vram + 0x4000 * vram_page, true);\r
224                 } else {\r
225                         SET_BANK(0xc000, 0xffff, wdmy, rdmy, false);\r
226                 }\r
227         } else {\r
228                 if(ipl_selected) {\r
229                         SET_BANK(0xc000, 0xffff, ram + 0x4000, ram + 0x4000, false);\r
230                 } else {\r
231                         SET_BANK(0xc000, 0xffff, ram + 0xc000, ram + 0xc000, false);\r
232                 }\r
233                 if(vram_sel == 0xc0) {\r
234                         SET_BANK(0xd000, 0xdfff, tvram, tvram, true);\r
235                 }\r
236         }\r
237 #else\r
238         if(ipl_selected) {\r
239                 SET_BANK(0x5000, 0x7fff, wdmy, rdmy, false);\r
240                 SET_BANK(0xd000, 0xffff, ram + 0x5000, ram + 0x5000, false);\r
241         } else {\r
242                 SET_BANK(0x5000, 0x7fff, ram + 0x5000, ram + 0x5000, false);\r
243                 SET_BANK(0xd000, 0xffff, ram + 0xd000, ram + 0xd000, false);\r
244         }\r
245         if(vram_sel == 0x80) {\r
246                 SET_BANK(0xd000, 0xdfff, tvram, tvram, true);\r
247                 SET_BANK(0xe000, 0xffff, vram + 0x4000 * (vram_page & 1), vram + 0x4000 * (vram_page & 1), true);\r
248         } else if(vram_sel == 0xc0) {\r
249                 SET_BANK(0x5000, 0x5fff, tvram, tvram, true);\r
250                 SET_BANK(0x6000, 0x7fff, vram + 0x4000 * (vram_page & 1), vram + 0x4000 * (vram_page & 1), true);\r
251         }\r
252 #endif\r
253 }\r
254 \r
255 void MEMORY::load_dat_image(_TCHAR* file_path)\r
256 {\r
257         FILEIO* fio = new FILEIO();\r
258         if(fio->Fopen(file_path, FILEIO_READ_BINARY)) {\r
259                 memset(ram, 0, sizeof(ram));\r
260                 memset(vram, 0, sizeof(vram));\r
261                 memset(tvram, 0, sizeof(tvram));\r
262                 \r
263                 fio->Fread(ram, sizeof(ram), 1);\r
264                 fio->Fclose();\r
265                 vm->special_reset();\r
266         }\r
267         delete fio;\r
268 }\r
269 \r
270 bool MEMORY::load_mzt_image(_TCHAR* file_path)\r
271 {\r
272         bool result = false;\r
273         bool is_mtw = check_file_extension(file_path, _T(".mtw"));\r
274         \r
275         if(is_mtw || ipl_selected) {\r
276                 FILEIO* fio = new FILEIO();\r
277                 if(fio->Fopen(file_path, FILEIO_READ_BINARY)) {\r
278                         uint8 header[128];\r
279                         fio->Fread(header, sizeof(header), 1);\r
280                         uint16 size = header[0x12] | (header[0x13] << 8);\r
281                         uint16 offs = header[0x14] | (header[0x15] << 8);\r
282                         \r
283 //                      if(header[0] == 0x01 && (is_mtw || size > 0x7e00)) {\r
284                         if(header[0] == 0x01 && offs == 0) {\r
285                                 memset(ram, 0, sizeof(ram));\r
286                                 memset(vram, 0, sizeof(vram));\r
287                                 memset(tvram, 0, sizeof(tvram));\r
288                                 \r
289                                 fio->Fread(ram, size, 1);\r
290                                 vm->special_reset();\r
291                                 result = true;\r
292                         }\r
293                         fio->Fclose();\r
294                 }\r
295                 delete fio;\r
296         }\r
297         return result;\r
298 }\r
299 \r
300 void MEMORY::draw_screen()\r
301 {\r
302         // render text\r
303 #ifndef _MZ80B\r
304         uint8 color = (text_color & 7) ? (text_color & 7) : 8;\r
305 #else\r
306         #define color 1\r
307 #endif\r
308         for(int y = 0, addr = 0; y < 200; y += 8) {\r
309                 for(int x = 0; x < (width80 ? 80 : 40); x++) {\r
310                         uint8 code = tvram[addr++];\r
311                         for(int l = 0; l < 8; l++) {\r
312                                 uint8 pat = font[(code << 3) + l];\r
313                                 uint8* d = &screen_txt[y + l][x << 3];\r
314                                 \r
315                                 d[0] = (pat & 0x80) ? color : 0;\r
316                                 d[1] = (pat & 0x40) ? color : 0;\r
317                                 d[2] = (pat & 0x20) ? color : 0;\r
318                                 d[3] = (pat & 0x10) ? color : 0;\r
319                                 d[4] = (pat & 0x08) ? color : 0;\r
320                                 d[5] = (pat & 0x04) ? color : 0;\r
321                                 d[6] = (pat & 0x02) ? color : 0;\r
322                                 d[7] = (pat & 0x01) ? color : 0;\r
323                         }\r
324                 }\r
325         }\r
326         \r
327         // render graphics\r
328 #ifndef _MZ80B\r
329         if(config.monitor_type != MONITOR_TYPE_COLOR && (vram_mask & 8)) {\r
330                 memset(screen_gra, 0, sizeof(screen_gra));\r
331         } else {\r
332                 // vram[0x0000-0x3fff] should be always blank\r
333                 uint8 *vram_b = vram + ((vram_mask & 1) ? 0x4000 : 0);\r
334                 uint8 *vram_r = vram + ((vram_mask & 2) ? 0x8000 : 0);\r
335                 uint8 *vram_g = vram + ((vram_mask & 4) ? 0xc000 : 0);\r
336                 for(int y = 0, addr = 0; y < 200; y++) {\r
337                         for(int x = 0; x < 80; x++) {\r
338                                 uint8 b = vram_b[addr];\r
339                                 uint8 r = vram_r[addr];\r
340                                 uint8 g = vram_g[addr];\r
341                                 addr++;\r
342                                 uint8* d = &screen_gra[y][x << 3];\r
343                                 \r
344                                 d[0] = ((b & 0x01) >> 0) | ((r & 0x01) << 1) | ((g & 0x01) << 2);\r
345                                 d[1] = ((b & 0x02) >> 1) | ((r & 0x02) >> 0) | ((g & 0x02) << 1);\r
346                                 d[2] = ((b & 0x04) >> 2) | ((r & 0x04) >> 1) | ((g & 0x04) >> 0);\r
347                                 d[3] = ((b & 0x08) >> 3) | ((r & 0x08) >> 2) | ((g & 0x08) >> 1);\r
348                                 d[4] = ((b & 0x10) >> 4) | ((r & 0x10) >> 3) | ((g & 0x10) >> 2);\r
349                                 d[5] = ((b & 0x20) >> 5) | ((r & 0x20) >> 4) | ((g & 0x20) >> 3);\r
350                                 d[6] = ((b & 0x40) >> 6) | ((r & 0x40) >> 5) | ((g & 0x40) >> 4);\r
351                                 d[7] = ((b & 0x80) >> 7) | ((r & 0x80) >> 6) | ((g & 0x80) >> 5);\r
352                         }\r
353                 }\r
354         }\r
355 #else\r
356         if(!(vram_page & 6)) {\r
357                 memset(screen_gra, 0, sizeof(screen_gra));\r
358         } else {\r
359                 // vram[0x8000-0xbfff] should be always blank\r
360                 uint8 *vram_1 = vram + ((vram_page & 2) ? 0x0000 : 0x8000);\r
361                 uint8 *vram_2 = vram + ((vram_page & 4) ? 0x4000 : 0x8000);\r
362                 for(int y = 0, addr = 0; y < 200; y++) {\r
363                         for(int x = 0; x < 40; x++) {\r
364                                 uint8 pat = vram_1[addr] | vram_2[addr];\r
365                                 addr++;\r
366                                 uint8* d = &screen_gra[y][x << 3];\r
367                                 \r
368                                 d[0] = (pat & 0x01) >> 0;\r
369                                 d[1] = (pat & 0x02) >> 1;\r
370                                 d[2] = (pat & 0x04) >> 2;\r
371                                 d[3] = (pat & 0x08) >> 3;\r
372                                 d[4] = (pat & 0x10) >> 4;\r
373                                 d[5] = (pat & 0x20) >> 5;\r
374                                 d[6] = (pat & 0x40) >> 6;\r
375                                 d[7] = (pat & 0x80) >> 7;\r
376                         }\r
377                 }\r
378         }\r
379 #endif\r
380         \r
381         // copy to real screen\r
382         for(int y = 0; y < 200; y++) {\r
383                 scrntype* dest0 = emu->screen_buffer(y * 2 + 0);\r
384                 scrntype* dest1 = emu->screen_buffer(y * 2 + 1);\r
385                 uint8* src_txt = screen_txt[y];\r
386                 uint8* src_gra = screen_gra[y];\r
387 #ifndef _MZ80B\r
388                 uint8 back = (config.monitor_type == MONITOR_TYPE_COLOR) ? back_color : 0;\r
389                 \r
390                 if(text_color & 8) {\r
391                         // graphics > text\r
392                         for(int x = 0; x < 640; x++) {\r
393                                 uint8 txt = src_txt[width80 ? x : (x >> 1)], gra = src_gra[x];\r
394                                 dest0[x] = palette_pc[gra ? gra : txt ? (txt & 7) : back];\r
395                         }\r
396                 } else {\r
397                         // text > graphics\r
398                         for(int x = 0; x < 640; x++) {\r
399                                 uint8 txt = src_txt[width80 ? x : (x >> 1)], gra = src_gra[x];\r
400                                 dest0[x] = palette_pc[txt ? (txt & 7) : gra ? gra : back];\r
401                         }\r
402                 }\r
403 #else\r
404                 if(width80) {\r
405                         for(int x = 0; x < 640; x++) {\r
406                                 uint8 txt = src_txt[x], gra = src_gra[x >> 1];\r
407                                 dest0[x] = palette_pc[txt | gra];\r
408                         }\r
409                 } else {\r
410                         for(int x = 0, x2 = 0; x < 320; x++, x2 += 2) {\r
411                                 uint8 txt = src_txt[x], gra = src_gra[x];\r
412                                 dest0[x2] = dest0[x2 + 1] = palette_pc[txt | gra];\r
413                         }\r
414                 }\r
415 #endif\r
416                 if(config.scan_line) {\r
417                         memset(dest1, 0, 640 * sizeof(scrntype));\r
418                 } else {\r
419                         memcpy(dest1, dest0, 640 * sizeof(scrntype));\r
420                 }\r
421         }\r
422 #ifndef _MZ80B\r
423         emu->screen_skip_line = true;\r
424 #endif\r
425 }\r
426 \r
427 #define STATE_VERSION   1\r
428 \r
429 void MEMORY::save_state(FILEIO* state_fio)\r
430 {\r
431         state_fio->FputUint32(STATE_VERSION);\r
432         state_fio->FputInt32(this_device_id);\r
433         \r
434         state_fio->Fwrite(ram, sizeof(ram), 1);\r
435         state_fio->Fwrite(vram, sizeof(vram), 1);\r
436         state_fio->Fwrite(tvram, sizeof(tvram), 1);\r
437         state_fio->FputBool(ipl_selected);\r
438         state_fio->FputUint8(vram_sel);\r
439         state_fio->FputUint8(vram_page);\r
440         state_fio->FputUint8(back_color);\r
441         state_fio->FputUint8(text_color);\r
442         state_fio->FputUint8(vram_mask);\r
443         state_fio->FputBool(width80);\r
444         state_fio->FputBool(reverse);\r
445         state_fio->FputBool(hblank);\r
446 }\r
447 \r
448 bool MEMORY::load_state(FILEIO* state_fio)\r
449 {\r
450         if(state_fio->FgetUint32() != STATE_VERSION) {\r
451                 return false;\r
452         }\r
453         if(state_fio->FgetInt32() != this_device_id) {\r
454                 return false;\r
455         }\r
456         state_fio->Fread(ram, sizeof(ram), 1);\r
457         state_fio->Fread(vram, sizeof(vram), 1);\r
458         state_fio->Fread(tvram, sizeof(tvram), 1);\r
459         ipl_selected = state_fio->FgetBool();\r
460         vram_sel = state_fio->FgetUint8();\r
461         vram_page = state_fio->FgetUint8();\r
462         back_color = state_fio->FgetUint8();\r
463         text_color = state_fio->FgetUint8();\r
464         vram_mask = state_fio->FgetUint8();\r
465         width80 = state_fio->FgetBool();\r
466         reverse = state_fio->FgetBool();\r
467         hblank = state_fio->FgetBool();\r
468         \r
469         if(ipl_selected) {\r
470                 SET_BANK(0x0000, 0x07ff, wdmy, ipl, false);\r
471                 SET_BANK(0x0800, 0x7fff, wdmy, rdmy, false);\r
472                 SET_BANK(0x8000, 0xffff, ram, ram, false);\r
473         } else {\r
474                 SET_BANK(0x0000, 0xffff, ram, ram, false);\r
475         }\r
476         update_vram_map();\r
477         update_palette();\r
478         return true;\r
479 }\r
480 \r