2 SHARP MZ-3500 Emulator 'EmuZ-3500'
4 Author : Takeda.Toshiya
13 #define SET_BANK(s, e, w, r) { \
14 int sb = (s) >> 11, eb = (e) >> 11; \
15 for(int i = sb; i <= eb; i++) { \
19 wbank[i] = (w) + 0x800 * (i - sb); \
24 rbank[i] = (r) + 0x800 * (i - sb); \
29 void SUB::initialize()
32 memset(kanji, 0xff, sizeof(kanji));
34 FILEIO* fio = new FILEIO();
35 if(fio->Fopen(create_local_path(_T("FONT.ROM")), FILEIO_READ_BINARY)) {
36 fio->Fread(font, sizeof(font), 1);
39 if(fio->Fopen(create_local_path(_T("KANJI.ROM")), FILEIO_READ_BINARY)) {
40 fio->Fread(kanji, sizeof(kanji), 1);
43 if(fio->Fopen(create_local_path(_T("MB83256-019.ROM")), FILEIO_READ_BINARY)) {
44 fio->Fread(kanji + 0x00000, 0x8000, 1);
47 if(fio->Fopen(create_local_path(_T("MB83256-020.ROM")), FILEIO_READ_BINARY)) {
48 fio->Fread(kanji + 0x08000, 0x8000, 1);
51 if(fio->Fopen(create_local_path(_T("MB83256-021.ROM")), FILEIO_READ_BINARY)) {
52 fio->Fread(kanji + 0x10000, 0x8000, 1);
55 if(fio->Fopen(create_local_path(_T("MB83256-022.ROM")), FILEIO_READ_BINARY)) {
56 fio->Fread(kanji + 0x18000, 0x8000, 1);
63 memset(ram, 0, sizeof(ram));
64 memset(vram_chr, 0, sizeof(vram_chr));
65 memset(vram_gfx, 0, sizeof(vram_gfx));
67 SET_BANK(0x0000, 0x1fff, wdmy, ipl);
68 SET_BANK(0x2000, 0x27ff, common, common);
69 SET_BANK(0x2800, 0x3fff, wdmy, rdmy);
70 SET_BANK(0x4000, 0x7fff, ram, ram);
71 SET_BANK(0x8000, 0xffff, wdmy, rdmy);
73 crt_400line = (config.monitor_type == 0 || config.monitor_type == 1);
75 register_frame_event(this);
80 memset(disp, 0, sizeof(disp));
84 void SUB::write_data8(uint32_t addr, uint32_t data)
87 wbank[addr >> 11][addr & 0x7ff] = data;
90 uint32_t SUB::read_data8(uint32_t addr)
93 return rbank[addr >> 11][addr & 0x7ff];
96 void SUB::write_io8(uint32_t addr, uint32_t data)
99 case 0x00: // mz3500sm p.18,77
100 // this->out_debug_log(_T("SUB->MAIN\tINT0=1\n"));
101 d_main->write_signal(SIG_MAIN_INT0, 1, 1);
103 case 0x50: // mz3500sm p.28
104 if((addr & 0x0f) == 0x0d) {
107 disp[addr & 0x0f] = data;
113 uint32_t SUB::read_io8(uint32_t addr)
115 switch(addr & 0xf0) {
116 case 0x50: // mz3500sm p.28
117 if((addr & 0x0f) == 0x0d) {
120 return disp[addr & 0x0f];
126 void SUB::event_frame()
133 void SUB::draw_screen()
135 memset(screen_chr, 0, sizeof(screen_chr));
136 memset(screen_gfx, 0, sizeof(screen_gfx));
149 } else if(disp[5] & 1) {
150 draw_gfx_200line_16bit();
152 draw_gfx_200line_8bit();
155 uint8_t back = disp[3] & 7;
158 scrntype_t palette_pc[8];
160 for(int i = 0; i < 8; i++) {
161 if(config.monitor_type == 1 || config.monitor_type == 3) {
163 palette_pc[i] = RGB_COLOR(0, (i != 0) ? 255 : 0, 0);
164 } else if(!(disp[4] & 1)) {
166 palette_pc[i] = RGB_COLOR((i != 0) ? 255 : 0, (i != 0) ? 255 : 0, (i != 0) ? 255 : 0);
169 palette_pc[i] = RGB_COLOR((i & 2) ? 255 : 0, (i & 4) ? 255 : 0, (i & 1) ? 255 : 0);
175 for(int y = 0; y <400; y++) {
176 scrntype_t* dest = emu->get_screen_buffer(y);
177 uint8_t* src_chr = screen_chr[y];
178 uint8_t* src_gfx = screen_gfx[y];
180 for(int x = 0; x < 640; x++) {
181 dest[x] = palette_pc[(src_chr[x] ? (src_chr[x] & 7) : src_gfx[x] ? (src_gfx[x] & 7) : back)];
184 emu->screen_skip_line(false);
186 for(int y = 0; y < 400; y += 2) {
187 scrntype_t* dest0 = emu->get_screen_buffer(y + 0);
188 scrntype_t* dest1 = emu->get_screen_buffer(y + 1);
189 uint8_t* src_chr = screen_chr[y];
190 uint8_t* src_gfx = screen_gfx[y];
192 for(int x = 0; x < 640; x++) {
193 dest0[x] = palette_pc[(src_chr[x] ? (src_chr[x] & 7) : src_gfx[x] ? (src_gfx[x] & 7) : back)];
195 if(config.scan_line) {
196 memset(dest1, 0, 640 * sizeof(scrntype_t));
198 my_memcpy(dest1, dest0, 640 * sizeof(scrntype_t));
201 emu->screen_skip_line(true);
205 void SUB::draw_chr_400line()
208 int width = (disp[5] & 2) ? 1 : 2; // 80/40 columns
209 int height = (disp[7] & 1) ? 20 : 16; // 20/16 dots/ine
210 int ymax = (disp[7] & 1) ? 20 : 25; // 20/25 lines
212 for(int i = 0, ytop = 0; i < 4; i++) {
213 uint32_t ra = ra_chr[4 * i];
214 ra |= ra_chr[4 * i + 1] << 8;
215 ra |= ra_chr[4 * i + 2] << 16;
216 ra |= ra_chr[4 * i + 3] << 24;
217 int src = ra & 0x1fff;
218 int len = ((ra >> 20) & 0x3ff) / height;
219 int caddr = ((cs_chr[0] & 0x80) && ((cs_chr[1] & 0x20) || !(cblink & 0x10))) ? (*ead_chr & 0x1fff) : -1;
221 for(int y = ytop; y < (ytop + len) && y < ymax; y++) {
222 for(int x = 0; x < 80; x += width) {
223 bool cursor = (src == caddr);
224 uint32_t code = vram_chr[(src * 2 + 0) & 0xfff]; // low byte : code
225 uint8_t attr = vram_chr[(src * 2 + 1) & 0xfff]; // high byte : attr
226 uint32_t knji = vram_chr[((src* 2 + 0) & 0xfff) | 0x1000];
231 pattern = &kanji[((code << 4) | (knji << 12)) & 0x1ffff];
233 pattern = &font[0x1000 | (code << 4)];
238 // bit2: reverse or green
239 // bit1: horizontal line or red
240 // bit0: vertical line or blue
243 bool vline, hline, reverse, blink;
248 color = (~attr & 7) | 8;
250 color = (attr & 7) | 8;
252 vline = hline = reverse = false;
256 vline = ((attr & 1) != 0);
257 hline = ((attr & 2) != 0);
258 reverse = ((attr & 4) != 0);
260 blink = ((attr & 8) != 0 && (cblink & 0x10) != 0);
261 reverse = (reverse != blink);
263 // NOTE: need to consider 200 line mode
265 for(int l = 0; l < 16; l++) {
266 int yy = y * height + l;
270 uint8_t pat = reverse ? ~pattern[l] : pattern[l];
271 uint8_t *dest = &screen_chr[yy][x << 3];
275 dest[0] = (pat & 0x80) ? color : 0;
276 dest[1] = (pat & 0x40) ? color : 0;
277 dest[2] = (pat & 0x20) ? color : 0;
278 dest[3] = (pat & 0x10) ? color : 0;
279 dest[4] = (pat & 0x08) ? color : 0;
280 dest[5] = (pat & 0x04) ? color : 0;
281 dest[6] = (pat & 0x02) ? color : 0;
282 dest[7] = (pat & 0x01) ? color : 0;
284 // 16dots (40columns)
285 dest[ 0] = dest[ 1] = (pat & 0x80) ? color : 0;
286 dest[ 2] = dest[ 3] = (pat & 0x40) ? color : 0;
287 dest[ 4] = dest[ 5] = (pat & 0x20) ? color : 0;
288 dest[ 6] = dest[ 7] = (pat & 0x10) ? color : 0;
289 dest[ 8] = dest[ 9] = (pat & 0x08) ? color : 0;
290 dest[10] = dest[11] = (pat & 0x04) ? color : 0;
291 dest[12] = dest[13] = (pat & 0x02) ? color : 0;
292 dest[14] = dest[15] = (pat & 0x01) ? color : 0;
296 for(int l = 0; l < ((height == 16) ? 16 : 18); l++) {
297 int yy = y * height + l;
301 screen_chr[yy][(x << 3) + (width * 8 - 1)] = color;
305 int yy = y * height + ((height == 16) ? 15 : 17);
307 memset(&screen_chr[yy][x << 3], color, width * 8);
311 int top = cs_chr[1] & 0x1f, bottom = cs_chr[2] >> 3;
312 for(int l = top; l < bottom && l < height; l++) {
313 int yy = y * height + l;
317 memset(&screen_chr[yy][x << 3], 7, width * 8); // always white ???
326 void SUB::draw_chr_200line()
329 int width = (disp[5] & 2) ? 1 : 2; // 80/40 columns
330 int height = (disp[7] & 1) ? 10 : 8; // 20/16 dots/ine
331 int ymax = (disp[7] & 1) ? 20 : 25; // 20/25 lines
333 for(int i = 0, ytop = 0; i < 4; i++) {
334 uint32_t ra = ra_chr[4 * i];
335 ra |= ra_chr[4 * i + 1] << 8;
336 ra |= ra_chr[4 * i + 2] << 16;
337 ra |= ra_chr[4 * i + 3] << 24;
338 int src = ra & 0x1fff;
339 int len = ((ra >> 20) & 0x3ff) / height;
340 int caddr = ((cs_chr[0] & 0x80) && ((cs_chr[1] & 0x20) || !(cblink & 0x10))) ? (*ead_chr & 0x1fff) : -1;
342 for(int y = ytop; y < (ytop + len) && y < ymax; y++) {
343 for(int x = 0; x < 80; x += width) {
344 bool cursor = (src == caddr);
345 uint32_t code = vram_chr[(src * 2 + 0) & 0xfff]; // low byte : code
346 uint8_t attr = vram_chr[(src * 2 + 1) & 0xfff]; // high byte : attr
347 uint32_t knji = vram_chr[((src* 2 + 0) & 0xfff) | 0x1000];
352 pattern = &kanji[((code << 4) | (knji << 12)) & 0x1ffff];
354 pattern = &font[(code << 4) + ((config.dipswitch & 0x100) ? 0 : 8)];
359 // bit2: reverse or green
360 // bit1: horizontal line or red
361 // bit0: vertical line or blue
364 bool vline, hline, reverse, blink;
368 color = (attr & 7) ? (attr & 7) : 7;
369 vline = hline = reverse = false;
373 vline = ((attr & 1) != 0);
374 hline = ((attr & 2) != 0);
375 reverse = ((attr & 4) != 0);
377 blink = ((attr & 8) != 0 && (cblink & 0x10) != 0);
378 reverse = (reverse != blink);
380 // NOTE: need to consider 200 line mode
382 for(int l = 0; l < 8; l++) {
383 int yy = (y * height + l) * 2;
387 uint8_t pat = reverse ? ~pattern[l] : pattern[l];
388 uint8_t *dest = &screen_chr[yy][x << 3];
392 dest[0] = (pat & 0x80) ? color : 0;
393 dest[1] = (pat & 0x40) ? color : 0;
394 dest[2] = (pat & 0x20) ? color : 0;
395 dest[3] = (pat & 0x10) ? color : 0;
396 dest[4] = (pat & 0x08) ? color : 0;
397 dest[5] = (pat & 0x04) ? color : 0;
398 dest[6] = (pat & 0x02) ? color : 0;
399 dest[7] = (pat & 0x01) ? color : 0;
401 // 16dots (40columns)
402 dest[ 0] = dest[ 1] = (pat & 0x80) ? color : 0;
403 dest[ 2] = dest[ 3] = (pat & 0x40) ? color : 0;
404 dest[ 4] = dest[ 5] = (pat & 0x20) ? color : 0;
405 dest[ 6] = dest[ 7] = (pat & 0x10) ? color : 0;
406 dest[ 8] = dest[ 9] = (pat & 0x08) ? color : 0;
407 dest[10] = dest[11] = (pat & 0x04) ? color : 0;
408 dest[12] = dest[13] = (pat & 0x02) ? color : 0;
409 dest[14] = dest[15] = (pat & 0x01) ? color : 0;
413 for(int l = 0; l < ((height == 8) ? 8 : 9); l++) {
414 int yy = (y * height + l) * 2;
418 screen_chr[yy][(x << 3) + (width * 8 - 1)] = color;
422 int yy = (y * height + ((height == 8) ? 7 : 8)) * 2;
424 memset(&screen_chr[yy][x << 3], color, width * 8);
428 int top = cs_chr[1] & 0x1f, bottom = cs_chr[2] >> 3;
429 for(int l = top; l < bottom && l < height; l++) {
430 int yy = (y * height + l) * 2;
434 memset(&screen_chr[yy][x << 3], 7, width * 8); // always white ???
443 void SUB::draw_gfx_400line()
445 for(int i = 0, ytop = 0; i < 4; i++) {
446 uint32_t ra = ra_gfx[4 * i];
447 ra |= ra_gfx[4 * i + 1] << 8;
448 ra |= ra_gfx[4 * i + 2] << 16;
449 ra |= ra_gfx[4 * i + 3] << 24;
450 int src = ra & 0x1fff;
451 int len = (ra >> 20) & 0x3ff;
453 for(int y = ytop; y < (ytop + len) && y < 400; y++) {
457 for(int x = 0; x < 40; x++) {
458 uint8_t lo_b = (disp[1] & 1) ? vram_gfx[((src * 2 + 0) & 0x7fff) | 0x00000] : 0;
459 uint8_t hi_b = (disp[1] & 1) ? vram_gfx[((src * 2 + 1) & 0x7fff) | 0x00000] : 0;
460 uint8_t lo_r = (disp[1] & 2) ? vram_gfx[((src * 2 + 0) & 0x7fff) | 0x08000] : 0;
461 uint8_t hi_r = (disp[1] & 2) ? vram_gfx[((src * 2 + 1) & 0x7fff) | 0x08000] : 0;
462 uint8_t lo_g = (disp[1] & 4) ? vram_gfx[((src * 2 + 0) & 0x7fff) | 0x10000] : 0;
463 uint8_t hi_g = (disp[1] & 4) ? vram_gfx[((src * 2 + 1) & 0x7fff) | 0x10000] : 0;
466 uint8_t *dest = &screen_gfx[y][x * 16];
467 dest[ 0] = ((lo_b & 0x01) ) | ((lo_r & 0x01) << 1) | ((lo_g & 0x01) << 2);
468 dest[ 1] = ((lo_b & 0x02) >> 1) | ((lo_r & 0x02) ) | ((lo_g & 0x02) << 1);
469 dest[ 2] = ((lo_b & 0x04) >> 2) | ((lo_r & 0x04) >> 1) | ((lo_g & 0x04) );
470 dest[ 3] = ((lo_b & 0x08) >> 3) | ((lo_r & 0x08) >> 2) | ((lo_g & 0x08) >> 1);
471 dest[ 4] = ((lo_b & 0x10) >> 4) | ((lo_r & 0x10) >> 3) | ((lo_g & 0x10) >> 2);
472 dest[ 5] = ((lo_b & 0x20) >> 5) | ((lo_r & 0x20) >> 4) | ((lo_g & 0x20) >> 3);
473 dest[ 6] = ((lo_b & 0x40) >> 6) | ((lo_r & 0x40) >> 5) | ((lo_g & 0x40) >> 4);
474 dest[ 7] = ((lo_b & 0x80) >> 7) | ((lo_r & 0x80) >> 6) | ((lo_g & 0x80) >> 5);
475 dest[ 8] = ((hi_b & 0x01) ) | ((hi_r & 0x01) << 1) | ((hi_g & 0x01) << 2);
476 dest[ 9] = ((hi_b & 0x02) >> 1) | ((hi_r & 0x02) ) | ((hi_g & 0x02) << 1);
477 dest[10] = ((hi_b & 0x04) >> 2) | ((hi_r & 0x04) >> 1) | ((hi_g & 0x04) );
478 dest[11] = ((hi_b & 0x08) >> 3) | ((hi_r & 0x08) >> 2) | ((hi_g & 0x08) >> 1);
479 dest[12] = ((hi_b & 0x10) >> 4) | ((hi_r & 0x10) >> 3) | ((hi_g & 0x10) >> 2);
480 dest[13] = ((hi_b & 0x20) >> 5) | ((hi_r & 0x20) >> 4) | ((hi_g & 0x20) >> 3);
481 dest[14] = ((hi_b & 0x40) >> 6) | ((hi_r & 0x40) >> 5) | ((hi_g & 0x40) >> 4);
482 dest[15] = ((hi_b & 0x80) >> 7) | ((hi_r & 0x80) >> 6) | ((hi_g & 0x80) >> 5);
489 void SUB::draw_gfx_200line_16bit()
491 for(int i = 0, ytop = 0; i < 4; i++) {
492 uint32_t ra = ra_gfx[4 * i];
493 ra |= ra_gfx[4 * i + 1] << 8;
494 ra |= ra_gfx[4 * i + 2] << 16;
495 ra |= ra_gfx[4 * i + 3] << 24;
496 int src = ra & 0x1fff;
497 int len = (ra >> 20) & 0x3ff;
499 for(int y = ytop; y < (ytop + len) && y < 200; y++) {
503 for(int x = 0; x < 40; x++) {
504 uint8_t lo_b = (disp[1] & 1) ? vram_gfx[((src * 2 + 0) & 0x7fff) | 0x00000] : 0;
505 uint8_t hi_b = (disp[1] & 1) ? vram_gfx[((src * 2 + 1) & 0x7fff) | 0x00000] : 0;
506 uint8_t lo_r = (disp[1] & 2) ? vram_gfx[((src * 2 + 0) & 0x7fff) | 0x08000] : 0;
507 uint8_t hi_r = (disp[1] & 2) ? vram_gfx[((src * 2 + 1) & 0x7fff) | 0x08000] : 0;
508 uint8_t lo_g = (disp[1] & 4) ? vram_gfx[((src * 2 + 0) & 0x7fff) | 0x10000] : 0;
509 uint8_t hi_g = (disp[1] & 4) ? vram_gfx[((src * 2 + 1) & 0x7fff) | 0x10000] : 0;
512 uint8_t *dest = &screen_gfx[y * 2][x * 16];
513 dest[ 0] = ((lo_b & 0x01) ) | ((lo_r & 0x01) << 1) | ((lo_g & 0x01) << 2);
514 dest[ 1] = ((lo_b & 0x02) >> 1) | ((lo_r & 0x02) ) | ((lo_g & 0x02) << 1);
515 dest[ 2] = ((lo_b & 0x04) >> 2) | ((lo_r & 0x04) >> 1) | ((lo_g & 0x04) );
516 dest[ 3] = ((lo_b & 0x08) >> 3) | ((lo_r & 0x08) >> 2) | ((lo_g & 0x08) >> 1);
517 dest[ 4] = ((lo_b & 0x10) >> 4) | ((lo_r & 0x10) >> 3) | ((lo_g & 0x10) >> 2);
518 dest[ 5] = ((lo_b & 0x20) >> 5) | ((lo_r & 0x20) >> 4) | ((lo_g & 0x20) >> 3);
519 dest[ 6] = ((lo_b & 0x40) >> 6) | ((lo_r & 0x40) >> 5) | ((lo_g & 0x40) >> 4);
520 dest[ 7] = ((lo_b & 0x80) >> 7) | ((lo_r & 0x80) >> 6) | ((lo_g & 0x80) >> 5);
521 dest[ 8] = ((hi_b & 0x01) ) | ((hi_r & 0x01) << 1) | ((hi_g & 0x01) << 2);
522 dest[ 9] = ((hi_b & 0x02) >> 1) | ((hi_r & 0x02) ) | ((hi_g & 0x02) << 1);
523 dest[10] = ((hi_b & 0x04) >> 2) | ((hi_r & 0x04) >> 1) | ((hi_g & 0x04) );
524 dest[11] = ((hi_b & 0x08) >> 3) | ((hi_r & 0x08) >> 2) | ((hi_g & 0x08) >> 1);
525 dest[12] = ((hi_b & 0x10) >> 4) | ((hi_r & 0x10) >> 3) | ((hi_g & 0x10) >> 2);
526 dest[13] = ((hi_b & 0x20) >> 5) | ((hi_r & 0x20) >> 4) | ((hi_g & 0x20) >> 3);
527 dest[14] = ((hi_b & 0x40) >> 6) | ((hi_r & 0x40) >> 5) | ((hi_g & 0x40) >> 4);
528 dest[15] = ((hi_b & 0x80) >> 7) | ((hi_r & 0x80) >> 6) | ((hi_g & 0x80) >> 5);
535 void SUB::draw_gfx_200line_8bit()
537 for(int i = 0, ytop = 0; i < 4; i++) {
538 uint32_t ra = ra_gfx[4 * i];
539 ra |= ra_gfx[4 * i + 1] << 8;
540 ra |= ra_gfx[4 * i + 2] << 16;
541 ra |= ra_gfx[4 * i + 3] << 24;
542 int src = ra & 0x1fff;
543 int len = (ra >> 20) & 0x3ff;
545 for(int y = ytop; y < (ytop + len) && y < 200; y++) {
549 for(int x = 0; x < 80; x++) {
550 uint8_t b = (disp[1] & 1) ? vram_gfx[((src * 2 + 0) & 0x7fff) | 0x00000] : 0;
551 uint8_t r = (disp[1] & 2) ? vram_gfx[((src * 2 + 1) & 0x7fff) | 0x00000] : 0;
552 uint8_t g = (disp[1] & 4) ? vram_gfx[((src * 2 + 0) & 0x7fff) | 0x10000] : 0;
555 uint8_t *dest = &screen_gfx[y * 2][x * 8];
556 dest[0] = ((b & 0x01) ) | ((r & 0x01) << 1) | ((g & 0x01) << 2);
557 dest[1] = ((b & 0x02) >> 1) | ((r & 0x02) ) | ((g & 0x02) << 1);
558 dest[2] = ((b & 0x04) >> 2) | ((r & 0x04) >> 1) | ((g & 0x04) );
559 dest[3] = ((b & 0x08) >> 3) | ((r & 0x08) >> 2) | ((g & 0x08) >> 1);
560 dest[4] = ((b & 0x10) >> 4) | ((r & 0x10) >> 3) | ((g & 0x10) >> 2);
561 dest[5] = ((b & 0x20) >> 5) | ((r & 0x20) >> 4) | ((g & 0x20) >> 3);
562 dest[6] = ((b & 0x40) >> 6) | ((r & 0x40) >> 5) | ((g & 0x40) >> 4);
563 dest[7] = ((b & 0x80) >> 7) | ((r & 0x80) >> 6) | ((g & 0x80) >> 5);
570 #define STATE_VERSION 3
572 bool SUB::process_state(FILEIO* state_fio, bool loading)
574 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
577 if(!state_fio->StateCheckInt32(this_device_id)) {
580 state_fio->StateBuffer(ram, sizeof(ram), 1);
581 state_fio->StateBuffer(vram_chr, sizeof(vram_chr), 1);
582 state_fio->StateBuffer(vram_gfx, sizeof(vram_gfx), 1);
583 state_fio->StateBuffer(disp, sizeof(disp), 1);
584 state_fio->StateInt32(cblink);
585 state_fio->StateBool(crt_400line);