2 SHARP MZ-3500 Emulator 'EmuZ-3500'
4 Author : Takeda.Toshiya
15 #define SET_BANK(s, e, w, r) { \
16 int sb = (s) >> 11, eb = (e) >> 11; \
17 for(int i = sb; i <= eb; i++) { \
18 if(((uintptr_t)w) == ((uintptr_t)wdmy)) { \
21 wbank[i] = (w) + 0x800 * (i - sb); \
23 if(((uintptr_t)r) == ((uintptr_t)rdmy)) { \
26 rbank[i] = (r) + 0x800 * (i - sb); \
31 void SUB::initialize()
34 memset(kanji, 0xff, sizeof(kanji));
36 FILEIO* fio = new FILEIO();
37 if(fio->Fopen(create_local_path(_T("FONT.ROM")), FILEIO_READ_BINARY)) {
38 fio->Fread(font, sizeof(font), 1);
41 if(fio->Fopen(create_local_path(_T("KANJI.ROM")), FILEIO_READ_BINARY)) {
42 fio->Fread(kanji, sizeof(kanji), 1);
45 if(fio->Fopen(create_local_path(_T("MB83256-019.ROM")), FILEIO_READ_BINARY)) {
46 fio->Fread(kanji + 0x00000, 0x8000, 1);
49 if(fio->Fopen(create_local_path(_T("MB83256-020.ROM")), FILEIO_READ_BINARY)) {
50 fio->Fread(kanji + 0x08000, 0x8000, 1);
53 if(fio->Fopen(create_local_path(_T("MB83256-021.ROM")), FILEIO_READ_BINARY)) {
54 fio->Fread(kanji + 0x10000, 0x8000, 1);
57 if(fio->Fopen(create_local_path(_T("MB83256-022.ROM")), FILEIO_READ_BINARY)) {
58 fio->Fread(kanji + 0x18000, 0x8000, 1);
65 memset(ram, 0, sizeof(ram));
66 memset(vram_chr, 0, sizeof(vram_chr));
67 memset(vram_gfx, 0, sizeof(vram_gfx));
69 SET_BANK(0x0000, 0x1fff, wdmy, ipl);
70 SET_BANK(0x2000, 0x27ff, common, common);
71 SET_BANK(0x2800, 0x3fff, wdmy, rdmy);
72 SET_BANK(0x4000, 0x7fff, ram, ram);
73 SET_BANK(0x8000, 0xffff, wdmy, rdmy);
75 crt_400line = (config.monitor_type == 0 || config.monitor_type == 1);
77 register_frame_event(this);
82 memset(disp, 0, sizeof(disp));
86 void SUB::write_data8(uint32_t addr, uint32_t data)
89 wbank[addr >> 11][addr & 0x7ff] = data;
92 uint32_t SUB::read_data8(uint32_t addr)
95 return rbank[addr >> 11][addr & 0x7ff];
98 void SUB::write_io8(uint32_t addr, uint32_t data)
100 switch(addr & 0xf0) {
101 case 0x00: // mz3500sm p.18,77
102 // this->out_debug_log(_T("SUB->MAIN\tINT0=1\n"));
103 d_main->write_signal(SIG_MAIN_INT0, 1, 1);
105 case 0x50: // mz3500sm p.28
106 if((addr & 0x0f) == 0x0d) {
109 disp[addr & 0x0f] = data;
115 uint32_t SUB::read_io8(uint32_t addr)
117 switch(addr & 0xf0) {
118 case 0x50: // mz3500sm p.28
119 if((addr & 0x0f) == 0x0d) {
122 return disp[addr & 0x0f];
128 void SUB::event_frame()
130 cblink = (cblink + 1) & 0x1f;
135 void SUB::draw_screen()
137 memset(screen_chr, 0, sizeof(screen_chr));
138 memset(screen_gfx, 0, sizeof(screen_gfx));
151 } else if(disp[5] & 1) {
152 draw_gfx_200line_16bit();
154 draw_gfx_200line_8bit();
157 uint8_t back = disp[3] & 7;
160 scrntype_t palette_pc[8];
162 for(int i = 0; i < 8; i++) {
163 if(config.monitor_type == 1 || config.monitor_type == 3) {
165 palette_pc[i] = RGB_COLOR(0, (i != 0) ? 255 : 0, 0);
166 } else if(!(disp[4] & 1)) {
168 palette_pc[i] = RGB_COLOR((i != 0) ? 255 : 0, (i != 0) ? 255 : 0, (i != 0) ? 255 : 0);
171 palette_pc[i] = RGB_COLOR((i & 2) ? 255 : 0, (i & 4) ? 255 : 0, (i & 1) ? 255 : 0);
177 for(int y = 0; y <400; y++) {
178 scrntype_t* dest = emu->get_screen_buffer(y);
179 uint8_t* src_chr = screen_chr[y];
180 uint8_t* src_gfx = screen_gfx[y];
182 for(int x = 0; x < 640; x++) {
183 dest[x] = palette_pc[(src_chr[x] ? (src_chr[x] & 7) : src_gfx[x] ? (src_gfx[x] & 7) : back)];
186 emu->screen_skip_line(false);
188 for(int y = 0; y < 400; y += 2) {
189 scrntype_t* dest0 = emu->get_screen_buffer(y + 0);
190 scrntype_t* dest1 = emu->get_screen_buffer(y + 1);
191 uint8_t* src_chr = screen_chr[y];
192 uint8_t* src_gfx = screen_gfx[y];
194 for(int x = 0; x < 640; x++) {
195 dest0[x] = palette_pc[(src_chr[x] ? (src_chr[x] & 7) : src_gfx[x] ? (src_gfx[x] & 7) : back)];
197 if(config.scan_line) {
198 memset(dest1, 0, 640 * sizeof(scrntype_t));
200 my_memcpy(dest1, dest0, 640 * sizeof(scrntype_t));
203 emu->screen_skip_line(true);
207 void SUB::draw_chr_400line()
210 int width = (disp[5] & 2) ? 1 : 2; // 80/40 columns
211 int height = (disp[7] & 1) ? 20 : 16; // 20/16 dots/ine
212 int ymax = (disp[7] & 1) ? 20 : 25; // 20/25 lines
214 for(int i = 0, ytop = 0; i < 4; i++) {
215 uint32_t ra = ra_chr[4 * i];
216 ra |= ra_chr[4 * i + 1] << 8;
217 ra |= ra_chr[4 * i + 2] << 16;
218 ra |= ra_chr[4 * i + 3] << 24;
219 int src = ra & 0x1fff;
220 int len = ((ra >> 20) & 0x3ff) / height;
221 int caddr = ((cs_chr[0] & 0x80) && ((cs_chr[1] & 0x20) || !(cblink & 0x10))) ? (*ead_chr & 0x1fff) : -1;
223 for(int y = ytop; y < (ytop + len) && y < ymax; y++) {
224 for(int x = 0; x < 80; x += width) {
225 bool cursor = (src == caddr);
226 uint32_t code = vram_chr[(src * 2 + 0) & 0xfff]; // low byte : code
227 uint8_t attr = vram_chr[(src * 2 + 1) & 0xfff]; // high byte : attr
228 uint32_t knji = vram_chr[((src* 2 + 0) & 0xfff) | 0x1000];
233 pattern = &kanji[((code << 4) | (knji << 12)) & 0x1ffff];
235 pattern = &font[0x1000 | (code << 4)];
240 // bit2: reverse or green
241 // bit1: horizontal line or red
242 // bit0: vertical line or blue
245 bool vline, hline, reverse, blink;
250 color = (~attr & 7) | 8;
252 color = (attr & 7) | 8;
254 vline = hline = reverse = false;
258 vline = ((attr & 1) != 0);
259 hline = ((attr & 2) != 0);
260 reverse = ((attr & 4) != 0);
262 blink = ((attr & 8) != 0 && (cblink & 0x10) != 0);
263 reverse = (reverse != blink);
265 // NOTE: need to consider 200 line mode
267 for(int l = 0; l < 16; l++) {
268 int yy = y * height + l;
272 uint8_t pat = reverse ? ~pattern[l] : pattern[l];
273 uint8_t *dest = &screen_chr[yy][x << 3];
277 dest[0] = (pat & 0x80) ? color : 0;
278 dest[1] = (pat & 0x40) ? color : 0;
279 dest[2] = (pat & 0x20) ? color : 0;
280 dest[3] = (pat & 0x10) ? color : 0;
281 dest[4] = (pat & 0x08) ? color : 0;
282 dest[5] = (pat & 0x04) ? color : 0;
283 dest[6] = (pat & 0x02) ? color : 0;
284 dest[7] = (pat & 0x01) ? color : 0;
286 // 16dots (40columns)
287 dest[ 0] = dest[ 1] = (pat & 0x80) ? color : 0;
288 dest[ 2] = dest[ 3] = (pat & 0x40) ? color : 0;
289 dest[ 4] = dest[ 5] = (pat & 0x20) ? color : 0;
290 dest[ 6] = dest[ 7] = (pat & 0x10) ? color : 0;
291 dest[ 8] = dest[ 9] = (pat & 0x08) ? color : 0;
292 dest[10] = dest[11] = (pat & 0x04) ? color : 0;
293 dest[12] = dest[13] = (pat & 0x02) ? color : 0;
294 dest[14] = dest[15] = (pat & 0x01) ? color : 0;
298 for(int l = 0; l < ((height == 16) ? 16 : 18); l++) {
299 int yy = y * height + l;
303 screen_chr[yy][(x << 3) + (width * 8 - 1)] = color;
307 int yy = y * height + ((height == 16) ? 15 : 17);
309 memset(&screen_chr[yy][x << 3], color, width * 8);
313 int top = cs_chr[1] & 0x1f, bottom = cs_chr[2] >> 3;
314 for(int l = top; l < bottom && l < height; l++) {
315 int yy = y * height + l;
319 memset(&screen_chr[yy][x << 3], 7, width * 8); // always white ???
328 void SUB::draw_chr_200line()
331 int width = (disp[5] & 2) ? 1 : 2; // 80/40 columns
332 int height = (disp[7] & 1) ? 10 : 8; // 20/16 dots/ine
333 int ymax = (disp[7] & 1) ? 20 : 25; // 20/25 lines
335 for(int i = 0, ytop = 0; i < 4; i++) {
336 uint32_t ra = ra_chr[4 * i];
337 ra |= ra_chr[4 * i + 1] << 8;
338 ra |= ra_chr[4 * i + 2] << 16;
339 ra |= ra_chr[4 * i + 3] << 24;
340 int src = ra & 0x1fff;
341 int len = ((ra >> 20) & 0x3ff) / height;
342 int caddr = ((cs_chr[0] & 0x80) && ((cs_chr[1] & 0x20) || !(cblink & 0x10))) ? (*ead_chr & 0x1fff) : -1;
344 for(int y = ytop; y < (ytop + len) && y < ymax; y++) {
345 for(int x = 0; x < 80; x += width) {
346 bool cursor = (src == caddr);
347 uint32_t code = vram_chr[(src * 2 + 0) & 0xfff]; // low byte : code
348 uint8_t attr = vram_chr[(src * 2 + 1) & 0xfff]; // high byte : attr
349 uint32_t knji = vram_chr[((src* 2 + 0) & 0xfff) | 0x1000];
354 pattern = &kanji[((code << 4) | (knji << 12)) & 0x1ffff];
356 pattern = &font[(code << 4) + ((config.dipswitch & 0x100) ? 0 : 8)];
361 // bit2: reverse or green
362 // bit1: horizontal line or red
363 // bit0: vertical line or blue
366 bool vline, hline, reverse, blink;
370 color = (attr & 7) ? (attr & 7) : 7;
371 vline = hline = reverse = false;
375 vline = ((attr & 1) != 0);
376 hline = ((attr & 2) != 0);
377 reverse = ((attr & 4) != 0);
379 blink = ((attr & 8) != 0 && (cblink & 0x10) != 0);
380 reverse = (reverse != blink);
382 // NOTE: need to consider 200 line mode
384 for(int l = 0; l < 8; l++) {
385 int yy = (y * height + l) * 2;
389 uint8_t pat = reverse ? ~pattern[l] : pattern[l];
390 uint8_t *dest = &screen_chr[yy][x << 3];
394 dest[0] = (pat & 0x80) ? color : 0;
395 dest[1] = (pat & 0x40) ? color : 0;
396 dest[2] = (pat & 0x20) ? color : 0;
397 dest[3] = (pat & 0x10) ? color : 0;
398 dest[4] = (pat & 0x08) ? color : 0;
399 dest[5] = (pat & 0x04) ? color : 0;
400 dest[6] = (pat & 0x02) ? color : 0;
401 dest[7] = (pat & 0x01) ? color : 0;
403 // 16dots (40columns)
404 dest[ 0] = dest[ 1] = (pat & 0x80) ? color : 0;
405 dest[ 2] = dest[ 3] = (pat & 0x40) ? color : 0;
406 dest[ 4] = dest[ 5] = (pat & 0x20) ? color : 0;
407 dest[ 6] = dest[ 7] = (pat & 0x10) ? color : 0;
408 dest[ 8] = dest[ 9] = (pat & 0x08) ? color : 0;
409 dest[10] = dest[11] = (pat & 0x04) ? color : 0;
410 dest[12] = dest[13] = (pat & 0x02) ? color : 0;
411 dest[14] = dest[15] = (pat & 0x01) ? color : 0;
415 for(int l = 0; l < ((height == 8) ? 8 : 9); l++) {
416 int yy = (y * height + l) * 2;
420 screen_chr[yy][(x << 3) + (width * 8 - 1)] = color;
424 int yy = (y * height + ((height == 8) ? 7 : 8)) * 2;
426 memset(&screen_chr[yy][x << 3], color, width * 8);
430 int top = cs_chr[1] & 0x1f, bottom = cs_chr[2] >> 3;
431 for(int l = top; l < bottom && l < height; l++) {
432 int yy = (y * height + l) * 2;
436 memset(&screen_chr[yy][x << 3], 7, width * 8); // always white ???
445 void SUB::draw_gfx_400line()
447 for(int i = 0, ytop = 0; i < 4; i++) {
448 uint32_t ra = ra_gfx[4 * i];
449 ra |= ra_gfx[4 * i + 1] << 8;
450 ra |= ra_gfx[4 * i + 2] << 16;
451 ra |= ra_gfx[4 * i + 3] << 24;
452 int src = ra & 0x1fff;
453 int len = (ra >> 20) & 0x3ff;
455 for(int y = ytop; y < (ytop + len) && y < 400; y++) {
459 for(int x = 0; x < 40; x++) {
460 uint8_t lo_b = (disp[1] & 1) ? vram_gfx[((src * 2 + 0) & 0x7fff) | 0x00000] : 0;
461 uint8_t hi_b = (disp[1] & 1) ? vram_gfx[((src * 2 + 1) & 0x7fff) | 0x00000] : 0;
462 uint8_t lo_r = (disp[1] & 2) ? vram_gfx[((src * 2 + 0) & 0x7fff) | 0x08000] : 0;
463 uint8_t hi_r = (disp[1] & 2) ? vram_gfx[((src * 2 + 1) & 0x7fff) | 0x08000] : 0;
464 uint8_t lo_g = (disp[1] & 4) ? vram_gfx[((src * 2 + 0) & 0x7fff) | 0x10000] : 0;
465 uint8_t hi_g = (disp[1] & 4) ? vram_gfx[((src * 2 + 1) & 0x7fff) | 0x10000] : 0;
468 uint8_t *dest = &screen_gfx[y][x * 16];
469 dest[ 0] = ((lo_b & 0x01) ) | ((lo_r & 0x01) << 1) | ((lo_g & 0x01) << 2);
470 dest[ 1] = ((lo_b & 0x02) >> 1) | ((lo_r & 0x02) ) | ((lo_g & 0x02) << 1);
471 dest[ 2] = ((lo_b & 0x04) >> 2) | ((lo_r & 0x04) >> 1) | ((lo_g & 0x04) );
472 dest[ 3] = ((lo_b & 0x08) >> 3) | ((lo_r & 0x08) >> 2) | ((lo_g & 0x08) >> 1);
473 dest[ 4] = ((lo_b & 0x10) >> 4) | ((lo_r & 0x10) >> 3) | ((lo_g & 0x10) >> 2);
474 dest[ 5] = ((lo_b & 0x20) >> 5) | ((lo_r & 0x20) >> 4) | ((lo_g & 0x20) >> 3);
475 dest[ 6] = ((lo_b & 0x40) >> 6) | ((lo_r & 0x40) >> 5) | ((lo_g & 0x40) >> 4);
476 dest[ 7] = ((lo_b & 0x80) >> 7) | ((lo_r & 0x80) >> 6) | ((lo_g & 0x80) >> 5);
477 dest[ 8] = ((hi_b & 0x01) ) | ((hi_r & 0x01) << 1) | ((hi_g & 0x01) << 2);
478 dest[ 9] = ((hi_b & 0x02) >> 1) | ((hi_r & 0x02) ) | ((hi_g & 0x02) << 1);
479 dest[10] = ((hi_b & 0x04) >> 2) | ((hi_r & 0x04) >> 1) | ((hi_g & 0x04) );
480 dest[11] = ((hi_b & 0x08) >> 3) | ((hi_r & 0x08) >> 2) | ((hi_g & 0x08) >> 1);
481 dest[12] = ((hi_b & 0x10) >> 4) | ((hi_r & 0x10) >> 3) | ((hi_g & 0x10) >> 2);
482 dest[13] = ((hi_b & 0x20) >> 5) | ((hi_r & 0x20) >> 4) | ((hi_g & 0x20) >> 3);
483 dest[14] = ((hi_b & 0x40) >> 6) | ((hi_r & 0x40) >> 5) | ((hi_g & 0x40) >> 4);
484 dest[15] = ((hi_b & 0x80) >> 7) | ((hi_r & 0x80) >> 6) | ((hi_g & 0x80) >> 5);
491 void SUB::draw_gfx_200line_16bit()
493 for(int i = 0, ytop = 0; i < 4; i++) {
494 uint32_t ra = ra_gfx[4 * i];
495 ra |= ra_gfx[4 * i + 1] << 8;
496 ra |= ra_gfx[4 * i + 2] << 16;
497 ra |= ra_gfx[4 * i + 3] << 24;
498 int src = ra & 0x1fff;
499 int len = (ra >> 20) & 0x3ff;
501 for(int y = ytop; y < (ytop + len) && y < 200; y++) {
505 for(int x = 0; x < 40; x++) {
506 uint8_t lo_b = (disp[1] & 1) ? vram_gfx[((src * 2 + 0) & 0x7fff) | 0x00000] : 0;
507 uint8_t hi_b = (disp[1] & 1) ? vram_gfx[((src * 2 + 1) & 0x7fff) | 0x00000] : 0;
508 uint8_t lo_r = (disp[1] & 2) ? vram_gfx[((src * 2 + 0) & 0x7fff) | 0x08000] : 0;
509 uint8_t hi_r = (disp[1] & 2) ? vram_gfx[((src * 2 + 1) & 0x7fff) | 0x08000] : 0;
510 uint8_t lo_g = (disp[1] & 4) ? vram_gfx[((src * 2 + 0) & 0x7fff) | 0x10000] : 0;
511 uint8_t hi_g = (disp[1] & 4) ? vram_gfx[((src * 2 + 1) & 0x7fff) | 0x10000] : 0;
514 uint8_t *dest = &screen_gfx[y * 2][x * 16];
515 dest[ 0] = ((lo_b & 0x01) ) | ((lo_r & 0x01) << 1) | ((lo_g & 0x01) << 2);
516 dest[ 1] = ((lo_b & 0x02) >> 1) | ((lo_r & 0x02) ) | ((lo_g & 0x02) << 1);
517 dest[ 2] = ((lo_b & 0x04) >> 2) | ((lo_r & 0x04) >> 1) | ((lo_g & 0x04) );
518 dest[ 3] = ((lo_b & 0x08) >> 3) | ((lo_r & 0x08) >> 2) | ((lo_g & 0x08) >> 1);
519 dest[ 4] = ((lo_b & 0x10) >> 4) | ((lo_r & 0x10) >> 3) | ((lo_g & 0x10) >> 2);
520 dest[ 5] = ((lo_b & 0x20) >> 5) | ((lo_r & 0x20) >> 4) | ((lo_g & 0x20) >> 3);
521 dest[ 6] = ((lo_b & 0x40) >> 6) | ((lo_r & 0x40) >> 5) | ((lo_g & 0x40) >> 4);
522 dest[ 7] = ((lo_b & 0x80) >> 7) | ((lo_r & 0x80) >> 6) | ((lo_g & 0x80) >> 5);
523 dest[ 8] = ((hi_b & 0x01) ) | ((hi_r & 0x01) << 1) | ((hi_g & 0x01) << 2);
524 dest[ 9] = ((hi_b & 0x02) >> 1) | ((hi_r & 0x02) ) | ((hi_g & 0x02) << 1);
525 dest[10] = ((hi_b & 0x04) >> 2) | ((hi_r & 0x04) >> 1) | ((hi_g & 0x04) );
526 dest[11] = ((hi_b & 0x08) >> 3) | ((hi_r & 0x08) >> 2) | ((hi_g & 0x08) >> 1);
527 dest[12] = ((hi_b & 0x10) >> 4) | ((hi_r & 0x10) >> 3) | ((hi_g & 0x10) >> 2);
528 dest[13] = ((hi_b & 0x20) >> 5) | ((hi_r & 0x20) >> 4) | ((hi_g & 0x20) >> 3);
529 dest[14] = ((hi_b & 0x40) >> 6) | ((hi_r & 0x40) >> 5) | ((hi_g & 0x40) >> 4);
530 dest[15] = ((hi_b & 0x80) >> 7) | ((hi_r & 0x80) >> 6) | ((hi_g & 0x80) >> 5);
537 void SUB::draw_gfx_200line_8bit()
539 for(int i = 0, ytop = 0; i < 4; i++) {
540 uint32_t ra = ra_gfx[4 * i];
541 ra |= ra_gfx[4 * i + 1] << 8;
542 ra |= ra_gfx[4 * i + 2] << 16;
543 ra |= ra_gfx[4 * i + 3] << 24;
544 int src = ra & 0x1fff;
545 int len = (ra >> 20) & 0x3ff;
547 for(int y = ytop; y < (ytop + len) && y < 200; y++) {
551 for(int x = 0; x < 80; x++) {
552 uint8_t b = (disp[1] & 1) ? vram_gfx[((src * 2 + 0) & 0x7fff) | 0x00000] : 0;
553 uint8_t r = (disp[1] & 2) ? vram_gfx[((src * 2 + 1) & 0x7fff) | 0x00000] : 0;
554 uint8_t g = (disp[1] & 4) ? vram_gfx[((src * 2 + 0) & 0x7fff) | 0x10000] : 0;
557 uint8_t *dest = &screen_gfx[y * 2][x * 8];
558 dest[0] = ((b & 0x01) ) | ((r & 0x01) << 1) | ((g & 0x01) << 2);
559 dest[1] = ((b & 0x02) >> 1) | ((r & 0x02) ) | ((g & 0x02) << 1);
560 dest[2] = ((b & 0x04) >> 2) | ((r & 0x04) >> 1) | ((g & 0x04) );
561 dest[3] = ((b & 0x08) >> 3) | ((r & 0x08) >> 2) | ((g & 0x08) >> 1);
562 dest[4] = ((b & 0x10) >> 4) | ((r & 0x10) >> 3) | ((g & 0x10) >> 2);
563 dest[5] = ((b & 0x20) >> 5) | ((r & 0x20) >> 4) | ((g & 0x20) >> 3);
564 dest[6] = ((b & 0x40) >> 6) | ((r & 0x40) >> 5) | ((g & 0x40) >> 4);
565 dest[7] = ((b & 0x80) >> 7) | ((r & 0x80) >> 6) | ((g & 0x80) >> 5);
572 #define STATE_VERSION 3
574 bool SUB::process_state(FILEIO* state_fio, bool loading)
576 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
579 if(!state_fio->StateCheckInt32(this_device_id)) {
582 state_fio->StateArray(ram, sizeof(ram), 1);
583 state_fio->StateArray(vram_chr, sizeof(vram_chr), 1);
584 state_fio->StateArray(vram_gfx, sizeof(vram_gfx), 1);
585 state_fio->StateArray(disp, sizeof(disp), 1);
586 state_fio->StateValue(cblink);
587 state_fio->StateValue(crt_400line);