OSDN Git Service

12402a546ee56fb9d79c1778b0a1fccab5de5fc8
[csp-qt/common_source_project-fm7.git] / source / src / vm / multi8 / display.cpp
1 /*
2         MITSUBISHI Electric MULTI8 Emulator 'EmuLTI8'
3
4         Author : Takeda.Toshiya
5         Date   : 2007.02.08 -
6
7         [ display ]
8 */
9
10 #include "display.h"
11
12 void DISPLAY::initialize()
13 {
14         // load rom image
15         FILEIO* fio = new FILEIO();
16         if(fio->Fopen(create_local_path(_T("FONT.ROM")), FILEIO_READ_BINARY)) {
17                 fio->Fread(font, sizeof(font), 1);
18                 fio->Fclose();
19         }
20         delete fio;
21         
22         // create pc palette
23         for(int i = 0; i < 8; i++) {
24                 palette_pc[i] = RGB_COLOR((i & 2) ? 255 : 0, (i & 4) ? 255 : 0, (i & 1) ? 255 : 0);
25         }
26         
27         // initialize
28         for(int i = 0; i < 7; i++) {
29                 pal[i] = i;
30         }
31         text_wide = true;
32         text_color = false;
33         graph_color = 0xfe;
34         graph_page = 7;
35         cblink = 0;
36         blink = false;
37         
38         // register event
39         register_frame_event(this);
40 }
41
42 void DISPLAY::write_io8(uint32_t addr, uint32_t data)
43 {
44         uint8_t mask;
45         
46         switch(addr & 0xff) {
47         case 0x30:
48         case 0x31:
49         case 0x32:
50         case 0x33:
51         case 0x34:
52         case 0x35:
53         case 0x36:
54         case 0x37:
55                 pal[addr & 7] = data & 7;
56                 mask = 1 << (addr & 7);
57                 if(data & 7) {
58                         graph_color |= mask;
59                 } else {
60                         graph_color &= ~mask;
61                 }
62                 break;
63         }
64 }
65
66 uint32_t DISPLAY::read_io8(uint32_t addr)
67 {
68         switch(addr & 0xff) {
69         case 0x30:
70         case 0x31:
71         case 0x32:
72         case 0x33:
73         case 0x34:
74         case 0x35:
75         case 0x36:
76         case 0x37:
77                 return pal[addr & 7];
78         }
79         return 0xff;
80 }
81
82 void DISPLAY::write_signal(int id, uint32_t data, uint32_t mask)
83 {
84         if(id == SIG_DISPLAY_I8255_B) {
85                 data &= mask;
86                 graph_page = data & 7;
87                 text_color = ((data & 0x80) == 0);
88                 text_wide = ((data & 0x40) == 0);
89         }
90 }
91
92 void DISPLAY::event_frame()
93 {
94         cblink = (cblink + 1) & 0x1f;
95 }
96
97 void DISPLAY::draw_screen()
98 {
99         if((regs[8] & 0x30) != 0x30) {
100                 if((regs[8] & 0xc0) == 0xc0) {
101                         cursor = -1;
102                 } else {
103                         cursor = ((regs[14] << 8) | regs[15]) & 0x7ff;
104                 }
105                 
106                 // render screen
107                 if(graph_color) {
108                         draw_graph_color();
109                 } else {
110                         draw_graph_mono();
111                 }
112                 if(text_wide) {
113                         draw_text_wide();
114                 } else {
115                         draw_text_normal();
116                 }
117         } else {
118                 memset(screen, 0, sizeof(screen));
119         }
120         
121         // copy to real screen
122         emu->set_vm_screen_lines(200);
123         for(int y = 0; y < 200; y++) {
124                 scrntype_t* dest0 = emu->get_screen_buffer(y * 2 + 0);
125                 scrntype_t* dest1 = emu->get_screen_buffer(y * 2 + 1);
126                 uint8_t* src = screen[y];
127                 
128                 for(int x = 0; x < 640; x++) {
129                         dest0[x] = palette_pc[src[x] & 7];
130                 }
131                 if(config.scan_line) {
132 //                      for(int x = 0; x < 640; x++) {
133 //                              dest1[x] = palette_pc[0];
134 //                      }
135                         memset(dest1, 0, 640 * sizeof(scrntype_t));
136                 } else {
137                         my_memcpy(dest1, dest0, 640 * sizeof(scrntype_t));
138                 }
139         }
140         emu->screen_skip_line(true);
141 }
142
143 void DISPLAY::draw_graph_color()
144 {
145         uint16_t src = ((regs[12] << 11) | (regs[13] << 3)) & 0x3fff;
146         
147         for(int y = 0; y < 200; y ++) {
148                 for(int x = 0; x < 80; x++) {
149                         uint8_t b = vram_b[src];
150                         uint8_t r = vram_r[src];
151                         uint8_t g = vram_g[src];
152                         uint8_t* d = &screen[y][x << 3];
153                         
154                         d[0] = pal[((b & 0x80) >> 7) | ((r & 0x80) >> 6) | ((g & 0x80) >> 5)];
155                         d[1] = pal[((b & 0x40) >> 6) | ((r & 0x40) >> 5) | ((g & 0x40) >> 4)];
156                         d[2] = pal[((b & 0x20) >> 5) | ((r & 0x20) >> 4) | ((g & 0x20) >> 3)];
157                         d[3] = pal[((b & 0x10) >> 4) | ((r & 0x10) >> 3) | ((g & 0x10) >> 2)];
158                         d[4] = pal[((b & 0x08) >> 3) | ((r & 0x08) >> 2) | ((g & 0x08) >> 1)];
159                         d[5] = pal[((b & 0x04) >> 2) | ((r & 0x04) >> 1) | ((g & 0x04) >> 0)];
160                         d[6] = pal[((b & 0x02) >> 1) | ((r & 0x02) >> 0) | ((g & 0x02) << 1)];
161                         d[7] = pal[((b & 0x01) >> 0) | ((r & 0x01) << 1) | ((g & 0x01) << 2)];
162                         
163                         src = (src + 1) & 0x3fff;
164                 }
165         }
166 }
167
168 void DISPLAY::draw_graph_mono()
169 {
170         uint16_t src = ((regs[12] << 11) | (regs[13] << 3)) & 0x3fff;
171         
172         for(int y = 0; y < 200; y ++) {
173                 for(int x = 0; x < 80; x++) {
174                         uint8_t p1 = (graph_page & 1) ? vram_b[src] : 0;
175                         uint8_t p2 = (graph_page & 2) ? vram_r[src] : 0;
176                         uint8_t p3 = (graph_page & 4) ? vram_g[src] : 0;
177                         uint8_t pat = p1 | p2 | p3;
178                         uint8_t* d = &screen[y][x << 3];
179                         
180                         d[0] = (pat & 0x80) ? 7 : 0;
181                         d[1] = (pat & 0x40) ? 7 : 0;
182                         d[2] = (pat & 0x20) ? 7 : 0;
183                         d[3] = (pat & 0x10) ? 7 : 0;
184                         d[4] = (pat & 0x08) ? 7 : 0;
185                         d[5] = (pat & 0x04) ? 7 : 0;
186                         d[6] = (pat & 0x02) ? 7 : 0;
187                         d[7] = (pat & 0x01) ? 7 : 0;
188                         
189                         src = (src + 1) & 0x3fff;
190                 }
191         }
192 }
193
194 void DISPLAY::draw_text_wide()
195 {
196         uint16_t src = ((regs[12] << 8) | regs[13]) & 0x7ff;
197         int hz = (regs[1] <= 80) ? regs[1] : 80;
198         int vt = (regs[6] <= 25) ? regs[6] : 25;
199         int ht = ((regs[9] <= 9) ? regs[9] : 9) + 1;
200         uint8_t bp = regs[10] & 0x60;
201         
202         for(int y = 0; y < vt; y++) {
203                 for(int x = 0; x < hz; x += 2) {
204                         uint8_t code = vram_t[src];
205                         uint8_t attr = vram_a[src];
206                         
207                         // check attribute
208                         bool secret = ((attr & 8) || ((attr & 0x10) && blink));
209                         bool reverse = ((attr & 0x20) != 0);
210                         uint8_t col = text_color ? (attr & 7) : 7;
211                         
212                         // draw pattern
213                         for(int l = 0; l < 8; l++) {
214                                 uint8_t pat = font[(code << 3) + l];
215                                 pat = secret ? 0 : reverse ? ~pat : pat;
216                                 int yy = y * ht + l;
217                                 if(yy >= 200) {
218                                         break;
219                                 }
220                                 uint8_t* d = &screen[yy][x << 3];
221                                 
222                                 d[ 0] = (pat & 0x80) ? col : d[ 0];
223                                 d[ 1] = (pat & 0x80) ? col : d[ 1];
224                                 d[ 2] = (pat & 0x40) ? col : d[ 2];
225                                 d[ 3] = (pat & 0x40) ? col : d[ 3];
226                                 d[ 4] = (pat & 0x20) ? col : d[ 4];
227                                 d[ 5] = (pat & 0x20) ? col : d[ 5];
228                                 d[ 6] = (pat & 0x10) ? col : d[ 6];
229                                 d[ 7] = (pat & 0x10) ? col : d[ 7];
230                                 d[ 8] = (pat & 0x08) ? col : d[ 8];
231                                 d[ 9] = (pat & 0x08) ? col : d[ 9];
232                                 d[10] = (pat & 0x04) ? col : d[10];
233                                 d[11] = (pat & 0x04) ? col : d[11];
234                                 d[12] = (pat & 0x02) ? col : d[12];
235                                 d[13] = (pat & 0x02) ? col : d[13];
236                                 d[14] = (pat & 0x01) ? col : d[14];
237                                 d[15] = (pat & 0x01) ? col : d[15];
238                         }
239                         // draw cursor
240                         if(src == cursor) {
241                                 int s = regs[10] & 0x1f;
242                                 int e = regs[11] & 0x1f;
243                                 if(bp == 0 || (bp == 0x40 && (cblink & 8)) || (bp == 0x60 && (cblink & 0x10))) {
244                                         for(int l = s; l <= e && l < ht; l++) {
245                                                 int yy = y * ht + l;
246                                                 if(yy < 200) {
247                                                         memset(&screen[yy][x << 3], 7, 16);
248                                                 }
249                                         }
250                                 }
251                         }
252                         src = (src + 2) & 0x7ff;
253                 }
254         }
255 }
256
257 void DISPLAY::draw_text_normal()
258 {
259         uint16_t src = ((regs[12] << 8) | regs[13]) & 0x7ff;
260         int hz = (regs[1] <= 80) ? regs[1] : 80;
261         int vt = (regs[6] <= 25) ? regs[6] : 25;
262         int ht = ((regs[9] <= 9) ? regs[9] : 9) + 1;
263         uint8_t bp = regs[10] & 0x60;
264         
265         for(int y = 0; y < vt; y++) {
266                 for(int x = 0; x < hz; x++) {
267                         uint8_t code = vram_t[src];
268                         uint8_t attr = vram_a[src];
269                         
270                         // check attribute
271                         bool secret = ((attr & 8) || ((attr & 0x10) && blink));
272                         bool reverse = ((attr & 0x20) != 0);
273                         uint8_t col = text_color ? (attr & 7) : 7;
274                         
275                         // draw pattern
276                         for(int l = 0; l < 8; l++) {
277                                 uint8_t pat = font[(code << 3) + l];
278                                 pat = secret ? 0 : reverse ? ~pat : pat;
279                                 int yy = y * ht + l;
280                                 if(yy >= 200) {
281                                         break;
282                                 }
283                                 uint8_t* d = &screen[yy][x << 3];
284                                 
285                                 d[0] = (pat & 0x80) ? col : d[0];
286                                 d[1] = (pat & 0x40) ? col : d[1];
287                                 d[2] = (pat & 0x20) ? col : d[2];
288                                 d[3] = (pat & 0x10) ? col : d[3];
289                                 d[4] = (pat & 0x08) ? col : d[4];
290                                 d[5] = (pat & 0x04) ? col : d[5];
291                                 d[6] = (pat & 0x02) ? col : d[6];
292                                 d[7] = (pat & 0x01) ? col : d[7];
293                         }
294                         // draw cursor
295                         if(src == cursor) {
296                                 int s = regs[10] & 0x1f;
297                                 int e = regs[11] & 0x1f;
298                                 if(bp == 0 || (bp == 0x40 && (cblink & 8)) || (bp == 0x60 && (cblink & 0x10))) {
299                                         for(int l = s; l <= e && l < ht; l++) {
300                                                 int yy = y * ht + l;
301                                                 if(yy < 200) {
302                                                         memset(&screen[yy][x << 3], 7, 8);
303                                                 }
304                                         }
305                                 }
306                         }
307                         src = (src + 1) & 0x7ff;
308                 }
309         }
310 }
311
312 #define STATE_VERSION   1
313
314 #include "../../statesub.h"
315
316 void DISPLAY::decl_state()
317 {
318         enter_decl_state(STATE_VERSION);
319
320         DECL_STATE_ENTRY_1D_ARRAY(pal, sizeof(pal));
321         DECL_STATE_ENTRY_BOOL(text_wide);
322         DECL_STATE_ENTRY_BOOL(text_color);
323         DECL_STATE_ENTRY_UINT8(graph_color);
324         DECL_STATE_ENTRY_UINT8(graph_page);
325         DECL_STATE_ENTRY_UINT16(cursor);
326         DECL_STATE_ENTRY_UINT16(cblink);
327         DECL_STATE_ENTRY_BOOL(hsync);
328         DECL_STATE_ENTRY_BOOL(vsync);
329         DECL_STATE_ENTRY_BOOL(display);
330         DECL_STATE_ENTRY_BOOL(blink);
331
332         leave_decl_state();
333 }
334
335 void DISPLAY::save_state(FILEIO* state_fio)
336 {
337         if(state_entry != NULL) {
338                 state_entry->save_state(state_fio);
339         }
340 //      state_fio->FputUint32(STATE_VERSION);
341 //      state_fio->FputInt32(this_device_id);
342         
343 //      state_fio->Fwrite(pal, sizeof(pal), 1);
344 //      state_fio->FputBool(text_wide);
345 //      state_fio->FputBool(text_color);
346 //      state_fio->FputUint8(graph_color);
347 //      state_fio->FputUint8(graph_page);
348 //      state_fio->FputUint16(cursor);
349 //      state_fio->FputUint16(cblink);
350 //      state_fio->FputBool(hsync);
351 //      state_fio->FputBool(vsync);
352 //      state_fio->FputBool(display);
353 //      state_fio->FputBool(blink);
354 }
355
356 bool DISPLAY::load_state(FILEIO* state_fio)
357 {
358         bool mb = false;
359         if(state_entry != NULL) {
360                 mb = state_entry->load_state(state_fio);
361         }
362         if(!mb) {
363                 return false;
364         }
365 //      if(state_fio->FgetUint32() != STATE_VERSION) {
366 //              return false;
367 //      }
368 //      if(state_fio->FgetInt32() != this_device_id) {
369 //              return false;
370 //      }
371 //      state_fio->Fread(pal, sizeof(pal), 1);
372 //      text_wide = state_fio->FgetBool();
373 //      text_color = state_fio->FgetBool();
374 //      graph_color = state_fio->FgetUint8();
375 //      graph_page = state_fio->FgetUint8();
376 //      cursor = state_fio->FgetUint16();
377 //      cblink = state_fio->FgetUint16();
378 //      hsync = state_fio->FgetBool();
379 //      vsync = state_fio->FgetBool();
380 //      display = state_fio->FgetBool();
381 //      blink = state_fio->FgetBool();
382         return true;
383 }
384
385 bool DISPLAY::process_state(FILEIO* state_fio, bool loading)
386 {
387         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
388                 return false;
389         }
390         if(!state_fio->StateCheckInt32(this_device_id)) {
391                 return false;
392         }
393         state_fio->StateBuffer(pal, sizeof(pal), 1);
394         state_fio->StateBool(text_wide);
395         state_fio->StateBool(text_color);
396         state_fio->StateUint8(graph_color);
397         state_fio->StateUint8(graph_page);
398         state_fio->StateUint16(cursor);
399         state_fio->StateUint16(cblink);
400         state_fio->StateBool(hsync);
401         state_fio->StateBool(vsync);
402         state_fio->StateBool(display);
403         state_fio->StateBool(blink);
404         return true;
405 }