From 1c67127d1d13e55bb709935a4850b92f8f7b77cf Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Mon, 16 Feb 2026 00:57:23 +0900 Subject: [PATCH 01/11] ps55da2: avoid resizing when video output is disabled --- src/video/vid_ps55da2.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 3df73f92c..a1d7fe25f 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -2352,12 +2352,8 @@ da2_recalctimings(da2_t *da2) da2->render = da2_render_blank; /* determine display mode */ // if (da2->attr_palette_enable && (da2->attrc[0x1f] & 0x08)) - /* if output disabled or VGA passthrough */ - if (da2->ioctl[LS_MODE] & 0x02 || !(da2->attrc[LV_COMPATIBILITY] & 0x08)) { - da2->render = da2_render_blank; - // return; /* 16 color graphics mode */ - } else if (!(da2->ioctl[LS_MODE] & 0x01)) { + if (!(da2->ioctl[LS_MODE] & 0x01)) { da2->hdisp *= 16; da2->char_width = 13; if (da2->crtc[LC_VIEWPORT_PRIORITY] & 0x80) { @@ -2383,6 +2379,9 @@ da2_recalctimings(da2_t *da2) da2->hdisp *= 13; da2->char_width = 13; } + /* if output disabled or VGA passthrough */ + if (da2->ioctl[LS_MODE] & 0x02 || !(da2->attrc[LV_COMPATIBILITY] & 0x08)) + da2->render = da2_render_blank; if (da2->vblankstart < da2->dispend) da2->dispend = da2->vblankstart; From c3db24162131f7dba9b76b3015f1ddb0a55ccd45 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Thu, 19 Feb 2026 11:00:09 +0900 Subject: [PATCH 02/11] IBM 5550: Added font 16 emulation --- src/include/86box/machine.h | 4 +- src/machine/m_xt_ibm5550.c | 392 ++++++++++++++++++++++++++++++------ src/machine/machine_table.c | 2 +- 3 files changed, 331 insertions(+), 67 deletions(-) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index af39e17e4..8a631f40a 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -1521,7 +1521,9 @@ extern int machine_xt_lxt3_init(const machine_t *); extern int machine_xt_compaq_deskpro_init(const machine_t *); /* m_xt_ibm5550.c */ - +#ifdef EMU_DEVICE_H +extern const device_t ibm5550_vid_device; +#endif extern int machine_xt_ibm5550_init(const machine_t *); /* m_xt_t1000.c */ diff --git a/src/machine/m_xt_ibm5550.c b/src/machine/m_xt_ibm5550.c index fed353344..089de761f 100644 --- a/src/machine/m_xt_ibm5550.c +++ b/src/machine/m_xt_ibm5550.c @@ -74,6 +74,8 @@ #define EPOCH_MASK_VRAM 0x3ffff /* 0xFFFFF */ // #define EPOCH_MASK_VRAMPLANE 0x1ffff /* 0x1FFFF */ #define EPOCH_PIXELCLOCK 40000000.0 /* 40 MHz interlaced */ +#define EPOCH_CONFIG_MONO16 0 /* Model 5551-Axx (Font 16, monochrome) */ +#define EPOCH_CONFIG_MONO24 1 /* Model 5551-Bxx (Font 24, monochrome) */ #define LC_INDEX 0x3D0 #define LC_DATA 0x3D1 @@ -156,11 +158,11 @@ enum epoch_nvr_ADDR { }; #ifndef RELEASE_BUILD -// #define ENABLE_EPOCH_LOG 1 +#define ENABLE_EPOCH_LOG 1 #endif #ifdef ENABLE_EPOCH_LOG -// #define ENABLE_EPOCH_DEBUGIO 1 +#define ENABLE_EPOCH_DEBUGIO 1 // #define ENABLE_EPOCH_DEBUGKBD 1 int epoch_do_log = ENABLE_EPOCH_LOG; @@ -236,6 +238,7 @@ typedef struct epoch_t { int cursorvisible, cursoron, blink; int scrollcache; int char_width; + int font24; int firstline, lastline; int firstline_draw, lastline_draw; @@ -307,6 +310,30 @@ The IBM 5550 has different IRQ assignments like the 6580 Displaywriter System. | FC000h | ROM | */ +#ifdef ENABLE_EPOCH_LOG +// #include +// static int dumpno = 0x61; +// static void +// epoch_dumpvram(void *priv) +// { +// FILE *fp; +// epoch_t *epoch = (epoch_t *) priv; +// char str1[64] = "epoch_vramvm_"; +// char str2[3] = {0x30, 0x30, 0}; +// if (!isalnum(dumpno)) +// return; +// str2[0] = dumpno; +// dumpno++; +// str2[1] = (epoch->crtmode & 0xf) + 0x30; +// strcat(str1,str2); +// fp = fopen(str1, "wb"); +// if (fp != NULL) { +// fwrite(epoch->vram, EPOCH_SIZE_VRAM, 1, fp); +// fclose(fp); +// } +// } +#endif + static void epoch_out(uint16_t addr, uint16_t val, void *priv) { @@ -370,7 +397,11 @@ epoch_out(uint16_t addr, uint16_t val, void *priv) // mem_mapping_enable(&epoch->paritymap); break; case 0x3D8: + /* Bit 3: Font access in read, Bit 1: graphic mode, Bit 0: Font access in write */ epoch->crtmode = val; +#ifdef ENABLE_EPOCH_LOG + // epoch_dumpvram(epoch); +#endif epoch_recalctimings(epoch); // epoch->attrff ^= 1; break; @@ -613,22 +644,43 @@ epoch_inw(uint16_t addr, void *priv) return temp; } -/* Get character line pattern from jfont rom or gaiji volatile memory */ +/* Get font pattern in a line from video memory */ static uint32_t getfont_ps55dbcs(int32_t code, int32_t line, void *priv) { - epoch_t *epoch = (epoch_t *) priv; + epoch_t *epoch = (epoch_t *) priv; uint32_t font = 0; - if (code < 1536) { - code *= 0x80; - font = epoch->vram[code + line * 4]; - font <<= 8; - font |= epoch->vram[code + line * 4 + 1]; - font <<= 8; - font |= epoch->vram[code + line * 4 + 2]; - font <<= 8; - font |= epoch->vram[code + line * 4 + 3]; - } else + if (code < 1536) { + code *= 0x80; + code += line * 4; + if (epoch->font24) { /* Font 24 (2 x 13 x 29) */ + font = epoch->vram[code]; + font <<= 8; + code++; + font |= epoch->vram[code]; + font <<= 8; + code++; + font |= epoch->vram[code]; + font <<= 8; + code++; + font |= epoch->vram[code]; + } else { /* Font 16 (2 x 9 x 21) */ + int bitnum = code & 0x7; + font = epoch->vram[code]; + font <<= 8; + font |= (epoch->vram[(code >> 3) + 0x20000 ] << (7 - bitnum)) & 0xff; /* get 9th bit */ + // font &= 0xffffff80; + // font |= epoch->vram[code + line * 4 + 1]; + font <<= 8; + code++; + font |= epoch->vram[code]; + font <<= 8; + bitnum = code & 0x7; + font |= (epoch->vram[(code >> 3) + 0x20000 ] << (7 - bitnum)) & 0xff; /* get 9th bit */ + font &= 0xff80ff80; + // font |= epoch->vram[code + line * 4 + 3]; + } + } else font = EPOCH_INVALIDACCESS32; return font; } @@ -676,12 +728,13 @@ epoch_render_text(epoch_t *epoch) uint8_t chr, attr; int fg, bg; uint32_t chr_dbcs; + int underscore_y = (epoch->font24) ? 28 : 20; int chr_wide = 0; // int colormode = ((epoch->attrc[LV_PAS_STATUS_CNTRL] & 0x80) == 0x80); int colormode = 0; // epoch_log("displ: %x, first: %x, epochma: %x, epochsc: %x\n", // epoch->displine , epoch->firstline_draw, epoch->memaddr, epoch->scanline); - for (x = 0; x < epoch->hdisp; x += 13) { + for (x = 0; x < epoch->hdisp; x += epoch->char_width) { chr = epoch->cram[(epoch->memaddr) & EPOCH_MASK_CRAM]; attr = epoch->cram[(epoch->memaddr + 1) & EPOCH_MASK_CRAM]; // if(chr!=0x20) epoch_log("chr: %x, attr: %x ", chr, attr); @@ -713,7 +766,7 @@ epoch_render_text(epoch_t *epoch) // if(chr!=0x20) epoch_log("chr: %x, %x, %x, %x, %x ", chr, attr, fg, epoch->egapal[fg], epoch->pallook[epoch->egapal[fg]]); } /* Draw character */ - for (uint32_t n = 0; n < 13; n++) + for (uint32_t n = 0; n < epoch->char_width; n++) p[n] = epoch->pallook[epoch->egapal[bg]]; /* draw blank */ /* SBCS or DBCS left half */ if (chr_wide == 0) { @@ -729,23 +782,37 @@ epoch_render_text(epoch_t *epoch) /* Get the font pattern */ uint32_t font = getfont_ps55dbcs(chr_dbcs, epoch->scanline, epoch); /* Draw 13 dots */ - for (uint32_t n = 0; n < 13; n++) { + for (uint32_t n = 0; n < epoch->char_width; n++) { p[n] = epoch->pallook[epoch->egapal[(font & 0x80000000) ? fg : bg]]; font <<= 1; } } else { /* the char code is SBCS (ANK) */ uint32_t fontbase; + uint16_t font; if (attr & 0x02) /* second map of SBCS font */ fontbase = EPOCH_VRAM_SBEX; else fontbase = EPOCH_VRAM_SBCS; - uint16_t font = epoch->vram[fontbase + chr * 0x80 + epoch->scanline * 4]; /* w13xh29 font */ - font <<= 8; - font |= epoch->vram[fontbase + chr * 0x80 + epoch->scanline * 4 + 1]; /* w13xh29 font */ + if (epoch->font24) { + font = epoch->vram[fontbase + chr * 0x80 + epoch->scanline * 4 + 2]; /* w13xh29 font */ + font <<= 8; + font |= epoch->vram[fontbase + chr * 0x80 + epoch->scanline * 4 + 3]; + } else { + int bitnum; + fontbase = (fontbase & 0x1ffff) + chr * 0x80 + epoch->scanline * 4; + bitnum = fontbase & 0x7; + font = epoch->vram[fontbase + 2]; /* w9xh21 font */ + font <<= 8; + // font |= epoch->vram[fontbase + chr * 0x80 + epoch->scanline * 4 + 3]; + fontbase >>= 3; + fontbase += 0x20000; /* real: C0000h */ + font |= epoch->vram[fontbase] << (8 + 7 - bitnum); + // if(chr!=0x20) epoch_log("faddr: %x, scline: %x, chr: %x, font: %x ", fontbase + chr * 0x80 + epoch->scanline * 4, epoch->scanline, chr, font); + } // if(chr!=0x20) epoch_log("memaddr: %x, scanline: %x, chr: %x, font: %x ", epoch->memaddr, epoch->scanline, chr, font); /* Draw 13 dots */ - for (uint32_t n = 0; n < 13; n++) { + for (uint32_t n = 0; n < epoch->char_width; n++) { p[n] = epoch->pallook[epoch->egapal[(font & 0x8000) ? fg : bg]]; font <<= 1; } @@ -755,15 +822,15 @@ epoch_render_text(epoch_t *epoch) else { uint32_t font = getfont_ps55dbcs(chr_dbcs, epoch->scanline, epoch); /* Draw 13 dots */ - for (uint32_t n = 0; n < 13; n++) { + for (uint32_t n = 0; n < epoch->char_width; n++) { p[n] = epoch->pallook[epoch->egapal[(font & 0x8000) ? fg : bg]]; font <<= 1; } chr_wide = 0; } /* Line 28 (Underscore) Note: Draw this first to display blink + vertical + underline correctly. */ - if (epoch->scanline == 28 && attr & 0x40 && !colormode) { /* Underscore only in monochrome mode */ - for (uint32_t n = 0; n < 13; n++) + if (epoch->scanline == underscore_y && attr & 0x40 && !colormode) { /* Underscore only in monochrome mode */ + for (uint32_t n = 0; n < epoch->char_width; n++) p[n] = epoch->pallook[epoch->egapal[fg]]; /* under line (white) */ } /* Column 1 (Vertical Line) */ @@ -771,14 +838,14 @@ epoch_render_text(epoch_t *epoch) p[0] = epoch->pallook[epoch->egapal[2]]; /* vertical line (white) */ } if (epoch->scanline == 0 && attr & 0x20) { /* HGrid */ - for (uint32_t n = 0; n < 13; n++) + for (uint32_t n = 0; n < epoch->char_width; n++) p[n] = epoch->pallook[epoch->egapal[2]]; /* horizontal line (white) */ } /* Drawing text cursor */ drawcursor = ((epoch->memaddr == epoch->cursoraddr) && epoch->cursorvisible && epoch->cursoron); if (drawcursor && epoch->scanline >= epoch->crtc[LC_CURSOR_ROW_START] && epoch->scanline <= epoch->crtc[LC_CURSOR_ROW_END]) { // int cursorwidth = (epoch->crtc[LC_COMPATIBILITY] & 0x20 ? 26 : 13); - int cursorwidth = 13; + int cursorwidth = epoch->char_width; int cursorcolor = 2; /* Choose color 2 if mode 8 */ fg = ((attr & 0x08) ? 3 : 2); bg = 0; @@ -793,7 +860,7 @@ epoch_render_text(epoch_t *epoch) p[n] = (p[n] == epoch->pallook[epoch->egapal[bg]]) ? epoch->pallook[epoch->egapal[cursorcolor]] : p[n]; } epoch->memaddr += 2; - p += 13; + p += epoch->char_width; } } } @@ -905,8 +972,13 @@ epoch_recalctimings(epoch_t *epoch) /* determine display mode */ if (epoch->crtmode & 0x02) { - epoch->hdisp *= 16; - epoch->char_width = 16; + if (epoch->font24) { + epoch->hdisp *= 16; + epoch->char_width = 16; + } else { + epoch->hdisp *= 11; + epoch->char_width = 11; + } /* PS/55 8-color */ epoch_log("Set videomode to PS/55 4 bpp graphics.\n"); epoch->render = epoch_render_color_4bpp; @@ -916,8 +988,13 @@ epoch_recalctimings(epoch_t *epoch) epoch_log("Set videomode to PS/55 Mode 8/E text.\n"); epoch->render = epoch_render_text; epoch->vram_display_mask = EPOCH_MASK_CRAM; - epoch->hdisp *= 13; - epoch->char_width = 13; + if (epoch->font24) { + epoch->hdisp *= 13; + epoch->char_width = 13; + } else { + epoch->hdisp *= 9; + epoch->char_width = 9; + } } if (epoch->crtmode & 0x08) epoch->render = epoch_render_blank; @@ -1114,55 +1191,211 @@ epoch_vram_write(uint32_t addr, uint8_t val, void *priv) { epoch_t *epoch = (epoch_t *) priv; // if ((addr & ~0xfff) != 0xE0000) return; - addr -= 0xA0000; + // epoch_log("epoch_vw: %x %x\n", addr, val); addr &= EPOCH_MASK_VRAM; epoch->vram[addr] = val; epoch->fullchange = changeframecount; // if(val == 0x66) // epoch_log("66 %04X:%04X %04X:%04X>%04X:%04X\n", cs >> 4, cpu_state.pc, DS, SI,ES,DI); } -static void -epoch_vram_writeb(uint32_t addr, uint8_t val, void *priv) -{ - epoch_t *epoch = (epoch_t *) priv; - // epoch_log("%04X:%04X epoch_vram_writeb: %x, val %x\n", cs >> 4, cpu_state.pc, addr, val); - cycles -= video_timing_write_b; - epoch_vram_write(addr, val, epoch); -} -static void -epoch_vram_writew(uint32_t addr, uint16_t val, void *priv) -{ - // epoch_log("%04X:%04X epoch_vram_writew: %x, val %x\n", cs >> 4, cpu_state.pc, addr, val); - epoch_t *epoch = (epoch_t *) priv; - cycles -= video_timing_write_w; - epoch_vram_write(addr, val & 0xff, epoch); - epoch_vram_write(addr + 1, val >> 8, epoch); -} - static uint8_t epoch_vram_read(uint32_t addr, void *priv) { epoch_t *epoch = (epoch_t *) priv; // if ((addr & ~epoch_MASK_CRAM) != 0xE0000) // return epoch_INVALIDACCESS8; - addr -= 0xA0000; addr &= EPOCH_MASK_VRAM; return epoch->vram[addr]; } + +static void +epoch_vram_writeb(uint32_t addr, uint8_t val, void *priv) +{ + epoch_t *epoch = (epoch_t *) priv; +// epoch_log("%04X:%04X epoch_vwb: %x, val %x\n", cs >> 4, cpu_state.pc, addr, val); + cycles -= video_timing_write_b; + // return; +// epoch_vram_write(addr, val, epoch); +} +static void +epoch_vram_writew(uint32_t addr, uint16_t val, void *priv) +{ + epoch_t *epoch = (epoch_t *) priv; + // uint8_t convert[8] = {0, 2, 8, 8, 1, 3, 8, 8};/* only even chars */ + //uint8_t convert[8] = {8, 8, 0, 2, 8, 8, 1, 3};/* only even chars */ + // uint8_t convert[8] = {0, 1, 2, 3, 4, 5, 6, 7};/* all but alt */ + // uint8_t convert[8] = {0, 1, 2, 3, 8, 8, 8, 8};/* even alt */ + // uint8_t convert[8] = {8, 8, 8, 8, 0, 1, 2, 3};/* even alt */ + // uint8_t convert[8] = {0, 4, 1, 5, 2, 6, 3, 7};/* all but pos+-1 */ + // uint8_t convert[8] = {8, 8, 4, 6, 8, 8, 5, 7};/* only odd (0) */ + // uint8_t convert[8] = {8, 8, 0, 2, 8, 8, 1, 3};/* only even */ + // uint8_t convert[8] = {4, 6, 8, 8, 5, 7, 8, 8};/* only odd (0) */ + // uint8_t convert[8] = {8, 4, 6, 8, 8, 5, 7, 8};/* none */ + // epoch_log("%04X:%04X epoch_vww: %x, val %x DS %x SI %x ES %x DI %x %x\n", cs >> 4, cpu_state.pc, addr, val,DS,SI,ES,DI, epoch->crtc[LC_INTERLACE_AND_SKEW]); + epoch_log("%04X:%04X epoch_vww: %x, val %x cm %x\n", cs >> 4, cpu_state.pc, addr, val, epoch->crtmode); + cycles -= video_timing_write_w; + addr -= 0xA0000; + // addr &= 0xfffffffe; + // if (0) { + if (!(epoch->crtmode & 0x02) && !(epoch->font24)) { + uint32_t toaddr, bitnum; + // if (addr < 0xd0000) { + // int index = (addr - 0xA0000) >> 7; /* 128 bytes per char */ + // addr &= 0x007f; + // addr += 0xA0000 + 84 * index; + // epoch_log("%x %x\n", addr, index); + // } else if (addr >= 0xD8000) { + // int index = (addr - 0xD8000) >> 7; /* 128 bytes per char */ + // addr &= 0x007f; + // if (addr & 2) return; + // addr >>= 1; + // addr += 0xC0000 + 42 * index; + // epoch_log("%x %x\n", addr, index); + // } else + // return; + + // if (addr < 0xd0000) { + // addr -= 0xA0000; + // if (addr & 2) + // return; + // addr >>= 1; + // addr += 0xA0000; + // } else if (addr >= 0xD8000) { + // addr -= 0xD8000; + // if (addr & 2) + // return; + // addr >>= 1; + // addr += 0xD8000; + // } else + // return; + + // addr >>= 1; + // if(addr & 0x02) + // addr--; + // addr ^= 0x06; + //addr &= 0xffffd;/* 1101 */ + // addr >>= 1; + + // if (convert[(addr + 0) & 7] > 7) + // return; + // epoch_vram_write((addr & 0xffff8) + convert[(addr + 0) & 7], val & 0xff, epoch); + // epoch_vram_write((addr & 0xffff8) + convert[(addr + 1) & 7], val >> 8, epoch); + + /* rw one word with 9 bits */ + /* virtual: 20000h (0010b, 0011b) -> real: 00001h (0000b, 0001b) */ + toaddr = addr; + if (addr & 2) + toaddr--; + if (addr & 0x20000) + toaddr+=2; + toaddr &= 0xdffff; + + //addr >>= 1; + + epoch_vram_write(toaddr, val & 0xff, epoch); + // epoch_log("%x %x ", toaddr, val); + /* get 9th bit */ + bitnum = addr & 0x7; + val >>= 15; + val <<= bitnum; + addr >>= 3; + addr += 0x20000; /* real: C0000h */ + val |= epoch_vram_read(addr, epoch) & ~(1 << bitnum);/* mask to update one bit */ + epoch_vram_write(addr, val, epoch); + // epoch_log("%x %x\n", addr, val); + } else {/* is graphic mode */ + epoch_vram_write(addr, val & 0xff, epoch); + epoch_vram_write(addr + 1, val >> 8, epoch); + } + // epoch_log("%x %x\n", addr, addr + 1); +} + static uint8_t epoch_vram_readb(uint32_t addr, void *priv) { epoch_t *epoch = (epoch_t *) priv; cycles -= video_timing_read_b; - return epoch_vram_read(addr, epoch); + // return 0xff; + // epoch_log("%04X:%04X epoch_vrb: %x, val %x\n", cs >> 4, cpu_state.pc, addr, epoch_vram_read(addr, epoch)); + // return epoch_vram_read(addr, epoch); } static uint16_t epoch_vram_readw(uint32_t addr, void *priv) { epoch_t *epoch = (epoch_t *) priv; + // uint8_t convert[8] = {0, 2, 4, 6, 1, 3, 5, 7};/* all but pos+-1 */ + // uint8_t convert[8] = {0, 4, 8, 8, 8, 8, 8, 8};/* all but pos+-1 */ cycles -= video_timing_read_w; - return epoch_vram_read(addr, epoch) | (epoch_vram_read(addr + 1, epoch) << 8); + addr -= 0xA0000; + epoch_log("%04X:%04X epoch_vrw: %x cm %x\n", + cs >> 4, cpu_state.pc, addr, epoch->crtmode); + // addr &= 0xfffffffe; + //read 0->0,1 2->2,3 4->4,5 6->6,7 + //read 0->0,2 2->1,3 4->4,6 6->5,7 + // if (0) { + if (!(epoch->crtmode & 0x02) && !(epoch->font24)) { + uint16_t ret; + uint32_t bitnum; + uint32_t toaddr; + // if (addr < 0xd0000) { + // int index = (addr - 0xA0000) >> 7; /* 128 bytes per char */ + // addr &= 0x007f; + // addr += 0xA0000 + 84 * index; + // epoch_log("%x %x %x\n", addr, index, epoch_vram_read(addr, epoch) | (epoch_vram_read(addr + 1, epoch) << 8)); + // } else if (addr >= 0xD8000) { + // int index = (addr - 0xD8000) >> 7; /* 128 bytes per char */ + // addr &= 0x007f; + // if (addr & 2) return EPOCH_INVALIDACCESS16; + // addr >>= 1; + // addr += 0xC0000 + 42 * index; + // epoch_log("%x %x %x\n", addr, index, epoch_vram_read(addr, epoch) | (epoch_vram_read(addr + 1, epoch) << 8)); + // } else + // return EPOCH_INVALIDACCESS16; + + // if (addr < 0xd0000) { + // addr -= 0xA0000; + // if (addr & 2) + // return EPOCH_INVALIDACCESS16; + // addr >>= 1; + // addr += 0xA0000; + // } else if (addr >= 0xD8000) { + // addr -= 0xD8000; + // if (addr & 2) + // return EPOCH_INVALIDACCESS16; + // addr >>= 1; + // addr += 0xD8000; + // } else + // return EPOCH_INVALIDACCESS16; + + // if(addr & 0x02) + // addr--; + // // addr ^= 0x06; + // addr >>= 1; + + // if (convert[(addr + 0) & 7] > 7) + // return 0; + // return epoch_vram_read((addr & 0xffff8) + convert[addr & 7], epoch) | (epoch_vram_read((addr & 0xffff8) + convert[(addr + 1) & 7], epoch) << 8); + + /* rw one word with 9 bits */ + /* virtual: 20000h (0010b, 0011b) -> real: 00001h (0000b, 0001b) */ + toaddr = addr; /* 1101 */ + if (addr & 2) + toaddr--; + if (addr & 0x20000) + toaddr+=2; + toaddr &= 0xdffff; + ret = epoch_vram_read(toaddr, epoch); + /* get 9th bit */ + bitnum = addr & 0x7; + addr >>= 3; + addr += 0x20000; /* real: C0000h */ + ret |= (epoch_vram_read(addr, epoch) << (8 + 7 - bitnum)) & 0x8000; + return ret; + // return epoch_vram_read(addr, epoch) | (epoch_vram_read(addr + 1, epoch) << 8); + } else {/* is graphic mode */ + return epoch_vram_read(addr, epoch) | (epoch_vram_read(addr + 1, epoch) << 8); + } } @@ -1327,8 +1560,10 @@ x1xx xxxx: No floppy drive 1xxx xxxx: No (bootable?) hard drive */ case 0xA2: - ret = 0xA8;/* Mono 24 */ - // ret = 0xA2;/* Mono 16 */ + if (epoch->font24) + ret = 0xA8; /* Mono 24 */ + else + ret = 0xA2; /* Mono 16 */ break; /* I/O A3h R: @@ -1502,7 +1737,7 @@ static void kbd_epoch_adddata(uint16_t val) { key_queue[key_queue_end] = val; - epoch_kbdlog("epochkbd: %02X added to key queue at %i\n", + epoch_log("epochkbd: %02X added to key queue at %i\n", val, key_queue_end); key_queue_end = (key_queue_end + 1) & 0x0f; } @@ -1703,6 +1938,7 @@ kbd_close(void *priv) /* Stop the timer. */ timer_disable(&kbd->send_delay_timer); + mouse_close(); /* Disable scanning. */ keyboard_scan = 0; @@ -1967,10 +2203,12 @@ epoch_reset(void *priv) epoch->parityenabled = 1; epoch->lowmemorydisabled = 1; epoch->crtioenabled = 0; + mem_mapping_disable(&epoch->cmap); + mem_mapping_disable(&epoch->vmap); // epoch->attrc[LV_CURSOR_COLOR] = 0x0f; /* cursor color */ epoch->crtc[LC_HORIZONTAL_TOTAL] = 103; /* Horizontal Total */ epoch->crtc[LC_VERTICAL_TOTAL] = 26; /* Vertical Total (These two must be set before the timer starts.) */ - epoch->crtmode = 0x08; + epoch->crtmode = 0; epoch->vram_display_mask = EPOCH_MASK_CRAM; // epoch->plane_mask = 1; epoch->oddeven = 0; @@ -2080,8 +2318,6 @@ epoch_init(UNUSED(const device_t *info)) epoch->epochconst = (uint64_t) ((cpuclock / EPOCH_PIXELCLOCK) * (double) (1ull << 32)); - epoch_reset(epoch); - mem_mapping_add(&epoch->cmap, 0xE0000, 0x1000, epoch_cram_readb, epoch_cram_readw, NULL, epoch_cram_writeb, epoch_cram_writew, NULL, NULL, MEM_MAPPING_EXTERNAL, epoch); mem_mapping_add(&epoch->vmap, 0xA0000, 0x40000, epoch_vram_readb, epoch_vram_readw, NULL, @@ -2089,8 +2325,6 @@ epoch_init(UNUSED(const device_t *info)) // mem_mapping_add(&epoch->fontcard.map, 0xF0000, 0xC000, epoch_font_readb, NULL, NULL, // epoch_font_writeb, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, epoch); - mem_mapping_disable(&epoch->cmap); - mem_mapping_disable(&epoch->vmap); // mem_mapping_disable(&epoch->fontcard.map); mem_mapping_add(&epoch->paritymap, 0, 0xA0000, epoch_parity_readb, epoch_parity_readw, NULL, epoch_parity_writeb, epoch_parity_writew, NULL, NULL, MEM_MAPPING_CACHE, epoch); @@ -2106,10 +2340,14 @@ epoch_init(UNUSED(const device_t *info)) // io_sethandler(0x160, 0x0010, // epoch_misc_in, NULL, NULL, epoch_misc_out, NULL, NULL, epoch); + epoch_reset(epoch); + timer_add(&epoch->timer, epoch_poll, epoch, 1); epoch_nvr_init(epoch, 17); + epoch->font24 = device_get_config_int("model"); + return epoch; } @@ -2138,6 +2376,7 @@ epoch_close(void *priv) // } fp = fopen("epoch_daregs.txt", "w"); if (fp != NULL) { + fprintf(fp, "3d8(crtmode) %02X\n", epoch->crtmode); // for (uint8_t i = 0; i < 0x10; i++) // fprintf(fp, "3e1(ioctl) %02X: %4X %d\n", i, epoch->ioctl[i], epoch->ioctl[i]); // for (uint8_t i = 0; i < 0x20; i++) @@ -2186,8 +2425,31 @@ epoch_force_redraw(void *priv) epoch->fullchange = changeframecount; } -static const device_t epoch_device = { - .name = "IBM 5550 (Epoch) Video Controller", +static const device_config_t epoch_config[] = { + // clang-format off + { + .name = "model", + .description = "Model", + .type = CONFIG_SELECTION, + .default_int = EPOCH_CONFIG_MONO24, + .selection = { + { + .description = "A (Font 16)", + .value = EPOCH_CONFIG_MONO16 + }, + { + .description = "B (Font 24)", + .value = EPOCH_CONFIG_MONO24 + }, + { .description = "" } + } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t ibm5550_vid_device = { + .name = "IBM 5550 Video Adapter", .internal_name = "ibm5550vid", .flags = DEVICE_ISA, .local = 0, @@ -2197,7 +2459,7 @@ static const device_t epoch_device = { .available = NULL, .speed_changed = epoch_speed_changed, .force_redraw = epoch_force_redraw, - .config = NULL + .config = epoch_config }; static void @@ -2258,7 +2520,7 @@ machine_xt_ibm5550_init(const machine_t *model) pit_ibm5550_init(); nmi_mask = 0; - device_add(&epoch_device); + device_add(&ibm5550_vid_device); device_add(&lpt_port_device); serial_t *uart = device_add(&ns8250_device); diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 85b09676e..2e76f5a24 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -2728,7 +2728,7 @@ const machine_t machines[] = { .kbd_device = NULL, .fdc_device = NULL, .sio_device = NULL, - .vid_device = NULL, + .vid_device = &ibm5550_vid_device, .snd_device = NULL, .net_device = NULL }, From 0a4b44184affb8abf55017e933b2079b57577e2f Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Thu, 19 Feb 2026 11:04:37 +0900 Subject: [PATCH 03/11] IBM 5550: comment out unused code --- src/machine/m_xt_ibm5550.c | 54 ++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/src/machine/m_xt_ibm5550.c b/src/machine/m_xt_ibm5550.c index 089de761f..ff369dede 100644 --- a/src/machine/m_xt_ibm5550.c +++ b/src/machine/m_xt_ibm5550.c @@ -79,8 +79,6 @@ #define LC_INDEX 0x3D0 #define LC_DATA 0x3D1 -#define LS_ENABLE 0x3D2 -#define LS_DISABLE 0x3D3 #define LC_HORIZONTAL_TOTAL 0x00 /* -1 */ #define LC_HORIZONTAL_DISPLAYED 0x01 #define LC_H_SYNC_POSITION 0x02 @@ -99,6 +97,10 @@ #define LC_CURSOR_LOC_LOWJ 0x0F #define LC_LIGHT_PEN_HIGH 0x10 #define LC_LIGHT_PEN_LOW 0x11 +#define LS_ENABLE 0x3D2 +#define LS_DISABLE 0x3D3 +#define LS_MODE 0x3D8 +#define LS_MONSENSE 0x3DA // #define LV_PORT 0x3E8 // #define LV_PALETTE_0 0x00 // #define LV_MODE_CONTROL 0x10 @@ -396,8 +398,8 @@ epoch_out(uint16_t addr, uint16_t val, void *priv) mem_mapping_disable(&epoch->vmap); // mem_mapping_enable(&epoch->paritymap); break; - case 0x3D8: - /* Bit 3: Font access in read, Bit 1: graphic mode, Bit 0: Font access in write */ + case LS_MODE: + /* Bit 3: Video output enable, Bit 1: Graphic mode (switch 16 / 9 bit word in Font 16 system) */ epoch->crtmode = val; #ifdef ENABLE_EPOCH_LOG // epoch_dumpvram(epoch); @@ -515,7 +517,7 @@ epoch_in(uint16_t addr, void *priv) // // epoch_iolog("epoch In %04X(%02X) %04X %04X:%04X\n", addr, epoch->attraddr, temp, cs >> 4, cpu_state.pc); // epoch->attrff = 0; /* reset flipflop (VGA does not reset flipflop) */ // break; - case 0x3DA: + case LS_MONSENSE: temp = 0xff; if (!(epoch->crtmode & 0x08)) {/* The video out is active */ if(epoch->cgastat & 8) @@ -525,7 +527,7 @@ epoch_in(uint16_t addr, void *priv) // temp &= 0xfe; /* color */ break; } - if (addr != 0x3DA) + if (addr != LS_MONSENSE) epoch_iolog("%04X:%04X epoch In %04X %04X\n", cs >> 4, cpu_state.pc, addr, temp); return temp; } @@ -1208,15 +1210,15 @@ epoch_vram_read(uint32_t addr, void *priv) return epoch->vram[addr]; } -static void -epoch_vram_writeb(uint32_t addr, uint8_t val, void *priv) -{ - epoch_t *epoch = (epoch_t *) priv; -// epoch_log("%04X:%04X epoch_vwb: %x, val %x\n", cs >> 4, cpu_state.pc, addr, val); - cycles -= video_timing_write_b; - // return; -// epoch_vram_write(addr, val, epoch); -} +// static void +// epoch_vram_writeb(uint32_t addr, uint8_t val, void *priv) +// { +// epoch_t *epoch = (epoch_t *) priv; +// // epoch_log("%04X:%04X epoch_vwb: %x, val %x\n", cs >> 4, cpu_state.pc, addr, val); +// cycles -= video_timing_write_b; +// // return; +// // epoch_vram_write(addr, val, epoch); +// } static void epoch_vram_writew(uint32_t addr, uint16_t val, void *priv) { @@ -1310,15 +1312,15 @@ epoch_vram_writew(uint32_t addr, uint16_t val, void *priv) // epoch_log("%x %x\n", addr, addr + 1); } -static uint8_t -epoch_vram_readb(uint32_t addr, void *priv) -{ - epoch_t *epoch = (epoch_t *) priv; - cycles -= video_timing_read_b; - // return 0xff; - // epoch_log("%04X:%04X epoch_vrb: %x, val %x\n", cs >> 4, cpu_state.pc, addr, epoch_vram_read(addr, epoch)); - // return epoch_vram_read(addr, epoch); -} +// static uint8_t +// epoch_vram_readb(uint32_t addr, void *priv) +// { +// epoch_t *epoch = (epoch_t *) priv; +// cycles -= video_timing_read_b; +// // return 0xff; +// // epoch_log("%04X:%04X epoch_vrb: %x, val %x\n", cs >> 4, cpu_state.pc, addr, epoch_vram_read(addr, epoch)); +// // return epoch_vram_read(addr, epoch); +// } static uint16_t epoch_vram_readw(uint32_t addr, void *priv) @@ -2320,8 +2322,8 @@ epoch_init(UNUSED(const device_t *info)) mem_mapping_add(&epoch->cmap, 0xE0000, 0x1000, epoch_cram_readb, epoch_cram_readw, NULL, epoch_cram_writeb, epoch_cram_writew, NULL, NULL, MEM_MAPPING_EXTERNAL, epoch); - mem_mapping_add(&epoch->vmap, 0xA0000, 0x40000, epoch_vram_readb, epoch_vram_readw, NULL, - epoch_vram_writeb, epoch_vram_writew, NULL, NULL, MEM_MAPPING_EXTERNAL, epoch); + mem_mapping_add(&epoch->vmap, 0xA0000, 0x40000, NULL, epoch_vram_readw, NULL, + NULL, epoch_vram_writew, NULL, NULL, MEM_MAPPING_EXTERNAL, epoch); // mem_mapping_add(&epoch->fontcard.map, 0xF0000, 0xC000, epoch_font_readb, NULL, NULL, // epoch_font_writeb, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, epoch); From 4284f155747e944e902bc7be34ebfe6e7fab1617 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Fri, 20 Feb 2026 09:03:45 +0900 Subject: [PATCH 04/11] Keyboard: Fix a bug in IBM 5576-001 emulation Fix a bug that the make code is sent when the 5576-001 emulation is enabled and the key is released. --- src/device/keyboard.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/device/keyboard.c b/src/device/keyboard.c index e77a5fc1d..ea8bcc1e7 100644 --- a/src/device/keyboard.c +++ b/src/device/keyboard.c @@ -216,22 +216,24 @@ key_process(uint16_t scan, int down) */ if (key5576mode) { int i = 0; - if (!down) { - /* Do and exit the 5576-001 emulation when a key is pressed other than trigger keys. */ - if (scan != 0x1d && scan != 0x2a && scan != 0x138) - { + if (down) { + while (scconv55_8a[i].sc != 0) { + if (scconv55_8a[i].sc == scan) { + while (scconv55_8a[i].mk[c] != 0) + keyboard_send(scconv55_8a[i].mk[c++]); + } + i++; + } + } + /* Do and exit the 5576-001 emulation when a key is pressed other than trigger keys. */ + if (scan != 0x1d && scan != 0x2a && scan != 0x138) { + if (!down) { key5576mode = 0; kbc_at_log("5576-001 key emulation disabled.\n"); } - } - while (scconv55_8a[i].sc != 0) - { - if (scconv55_8a[i].sc == scan) { - while (scconv55_8a[i].mk[c] != 0) - keyboard_send(scconv55_8a[i].mk[c++]); - return; - } - i++; + /* If the key is found in the table, the scancode has been sent. + Or else, do nothing. */ + return; } } From c1661b5a90121cb37952c29db6901c29c747fa8a Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Fri, 20 Feb 2026 09:06:33 +0900 Subject: [PATCH 05/11] IBM 5550: Fix the screen res in graphic mode --- src/machine/m_xt_ibm5550.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/machine/m_xt_ibm5550.c b/src/machine/m_xt_ibm5550.c index ff369dede..35edec8f3 100644 --- a/src/machine/m_xt_ibm5550.c +++ b/src/machine/m_xt_ibm5550.c @@ -305,7 +305,7 @@ The IBM 5550 has different IRQ assignments like the 6580 Displaywriter System. | 40000h | 128 KB Expansion RAM Card | | 60000h | 128 KB Expansion RAM Card | | 80000h | 128 KB Expansion RAM Card | -| A0000h | 256 KB Video RAM | +| A0000h | Video RAM (Font 16: 144 KB, Font 24: 256 KB) | | E0000h | 4 KB Code/Attribute Buffer | | E8000h | ? KB Hard Disk Control Local Memory (not implemented) | | F0000h | Kanji Font Card (not implemented) | @@ -917,13 +917,15 @@ epoch_render_color_4bpp(epoch_t *epoch) /* INT 10h video modes supported in DOS K3.44. Mode Type Colors Text Base Address PELs Render - 2 A/N 3 80 x 25 E0000h 1040 x 725 text - 8 A/N/K 3 80 x 25 E0000h 1040 x 725 text + 2 A/N 3 80 x 25 E0000h 1040 x 725* text + 8 A/N/K 3 80 x 25 E0000h 1040 x 725* text + 9 APA 2 80 x 25 A0000h 720 x 512 color_4bpp Ah APA 2 78 x 25 A0000h 1024 x 768 color_4bpp Bh APA 16 40 x 25 A0000h 360 x 512 n/a Ch APA 16 80 x 25 A0000h 720 x 512 n/a Dh APA 16 78 x 25 A0000h 1024 x 768 n/a - Eh A/N/K 16 80 x 25 E0000h 1040 x 725 n/a + Eh A/N/K 16 80 x 25 E0000h 1040 x 725* n/a + (* 720 x 525 in the Font 16 system.) */ static void epoch_recalctimings(epoch_t *epoch) @@ -978,8 +980,8 @@ epoch_recalctimings(epoch_t *epoch) epoch->hdisp *= 16; epoch->char_width = 16; } else { - epoch->hdisp *= 11; - epoch->char_width = 11; + epoch->hdisp *= 12; + epoch->char_width = 12; } /* PS/55 8-color */ epoch_log("Set videomode to PS/55 4 bpp graphics.\n"); From 45c300a566b43af67a0da631bfc435d580532a46 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Fri, 20 Feb 2026 09:10:16 +0900 Subject: [PATCH 06/11] IBM 5550: Change method to store 9th bit into memory --- src/machine/m_xt_ibm5550.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/src/machine/m_xt_ibm5550.c b/src/machine/m_xt_ibm5550.c index 35edec8f3..f13ccd6be 100644 --- a/src/machine/m_xt_ibm5550.c +++ b/src/machine/m_xt_ibm5550.c @@ -1236,7 +1236,7 @@ epoch_vram_writew(uint32_t addr, uint16_t val, void *priv) // uint8_t convert[8] = {4, 6, 8, 8, 5, 7, 8, 8};/* only odd (0) */ // uint8_t convert[8] = {8, 4, 6, 8, 8, 5, 7, 8};/* none */ // epoch_log("%04X:%04X epoch_vww: %x, val %x DS %x SI %x ES %x DI %x %x\n", cs >> 4, cpu_state.pc, addr, val,DS,SI,ES,DI, epoch->crtc[LC_INTERLACE_AND_SKEW]); - epoch_log("%04X:%04X epoch_vww: %x, val %x cm %x\n", cs >> 4, cpu_state.pc, addr, val, epoch->crtmode); + // epoch_log("%04X:%04X epoch_vww: %x, val %x cm %x\n", cs >> 4, cpu_state.pc, addr, val, epoch->crtmode); cycles -= video_timing_write_w; addr -= 0xA0000; // addr &= 0xfffffffe; @@ -1291,21 +1291,21 @@ epoch_vram_writew(uint32_t addr, uint16_t val, void *priv) if (addr & 2) toaddr--; if (addr & 0x20000) - toaddr+=2; - toaddr &= 0xdffff; + toaddr += 2; + toaddr &= 0x1ffff; //addr >>= 1; epoch_vram_write(toaddr, val & 0xff, epoch); // epoch_log("%x %x ", toaddr, val); /* get 9th bit */ - bitnum = addr & 0x7; + bitnum = toaddr & 0x7; + toaddr >>= 3; + toaddr += 0x20000; /* real: C0000h */ val >>= 15; val <<= bitnum; - addr >>= 3; - addr += 0x20000; /* real: C0000h */ - val |= epoch_vram_read(addr, epoch) & ~(1 << bitnum);/* mask to update one bit */ - epoch_vram_write(addr, val, epoch); + val |= epoch_vram_read(toaddr, epoch) & ~(1 << bitnum);/* mask to update one bit */ + epoch_vram_write(toaddr, val, epoch); // epoch_log("%x %x\n", addr, val); } else {/* is graphic mode */ epoch_vram_write(addr, val & 0xff, epoch); @@ -1332,8 +1332,7 @@ epoch_vram_readw(uint32_t addr, void *priv) // uint8_t convert[8] = {0, 4, 8, 8, 8, 8, 8, 8};/* all but pos+-1 */ cycles -= video_timing_read_w; addr -= 0xA0000; - epoch_log("%04X:%04X epoch_vrw: %x cm %x\n", - cs >> 4, cpu_state.pc, addr, epoch->crtmode); + // epoch_log("%04X:%04X epoch_vrw: %x cm %x\n", cs >> 4, cpu_state.pc, addr, epoch->crtmode); // addr &= 0xfffffffe; //read 0->0,1 2->2,3 4->4,5 6->6,7 //read 0->0,2 2->1,3 4->4,6 6->5,7 @@ -1387,14 +1386,14 @@ epoch_vram_readw(uint32_t addr, void *priv) if (addr & 2) toaddr--; if (addr & 0x20000) - toaddr+=2; - toaddr &= 0xdffff; + toaddr += 2; + toaddr &= 0x1ffff; ret = epoch_vram_read(toaddr, epoch); /* get 9th bit */ - bitnum = addr & 0x7; - addr >>= 3; - addr += 0x20000; /* real: C0000h */ - ret |= (epoch_vram_read(addr, epoch) << (8 + 7 - bitnum)) & 0x8000; + bitnum = toaddr & 0x7; + toaddr >>= 3; + toaddr += 0x20000; /* real: C0000h */ + ret |= (epoch_vram_read(toaddr, epoch) << (8 + 7 - bitnum)) & 0x8000; return ret; // return epoch_vram_read(addr, epoch) | (epoch_vram_read(addr + 1, epoch) << 8); } else {/* is graphic mode */ @@ -1806,7 +1805,7 @@ kbd_write(uint16_t port, uint8_t val, void *priv) timer_process(); speaker_update(); - + // if(!speaker_enable && (val & 2)) epoch_log("Buz!\n"); speaker_gated = val & 2; speaker_enable = val & 2; From 617be3b135e6a89a4f6c973aba14f16b745d1a03 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Fri, 20 Feb 2026 10:51:00 +0900 Subject: [PATCH 07/11] IBM 5550: Fix a bug in Font 16 drawing --- src/machine/m_xt_ibm5550.c | 78 +++++++++++++++++++++----------------- 1 file changed, 44 insertions(+), 34 deletions(-) diff --git a/src/machine/m_xt_ibm5550.c b/src/machine/m_xt_ibm5550.c index f13ccd6be..2edb547a4 100644 --- a/src/machine/m_xt_ibm5550.c +++ b/src/machine/m_xt_ibm5550.c @@ -646,6 +646,18 @@ epoch_inw(uint16_t addr, void *priv) return temp; } +static uint32_t +getaddr_9bitword(int32_t addr) +{ + int32_t bit9addr = addr; + if (bit9addr & 2) + bit9addr--; + if (bit9addr & 0x20000) + bit9addr += 2; + bit9addr &= 0x1ffff; + return bit9addr; +} + /* Get font pattern in a line from video memory */ static uint32_t getfont_ps55dbcs(int32_t code, int32_t line, void *priv) @@ -667,19 +679,22 @@ getfont_ps55dbcs(int32_t code, int32_t line, void *priv) code++; font |= epoch->vram[code]; } else { /* Font 16 (2 x 9 x 21) */ - int bitnum = code & 0x7; + int32_t bit9addr = getaddr_9bitword(code); + int bitnum = bit9addr & 7; + bit9addr >>= 3; + bit9addr += 0x20000; /* real: C0000h */ font = epoch->vram[code]; font <<= 8; - font |= (epoch->vram[(code >> 3) + 0x20000 ] << (7 - bitnum)) & 0xff; /* get 9th bit */ - // font &= 0xffffff80; + font |= (epoch->vram[bit9addr] << (7 - bitnum)) & 0x80; /* get 9th bit */ + // font &= 0xff80; // font |= epoch->vram[code + line * 4 + 1]; font <<= 8; code++; font |= epoch->vram[code]; font <<= 8; bitnum = code & 0x7; - font |= (epoch->vram[(code >> 3) + 0x20000 ] << (7 - bitnum)) & 0xff; /* get 9th bit */ - font &= 0xff80ff80; + font |= (epoch->vram[bit9addr] << (7 - bitnum)) & 0x80; /* get 9th bit */ + // font &= 0xff80ff80; // font |= epoch->vram[code + line * 4 + 3]; } } else @@ -801,15 +816,17 @@ epoch_render_text(epoch_t *epoch) font <<= 8; font |= epoch->vram[fontbase + chr * 0x80 + epoch->scanline * 4 + 3]; } else { - int bitnum; - fontbase = (fontbase & 0x1ffff) + chr * 0x80 + epoch->scanline * 4; - bitnum = fontbase & 0x7; + uint32_t bitnum, bit9addr; + fontbase += chr * 0x80 + epoch->scanline * 4; + bit9addr = getaddr_9bitword(fontbase); + bitnum = bit9addr & 7; + bit9addr >>= 3; + bit9addr += 0x20000; /* real: C0000h */ + + fontbase &= 0x1ffff; font = epoch->vram[fontbase + 2]; /* w9xh21 font */ font <<= 8; - // font |= epoch->vram[fontbase + chr * 0x80 + epoch->scanline * 4 + 3]; - fontbase >>= 3; - fontbase += 0x20000; /* real: C0000h */ - font |= epoch->vram[fontbase] << (8 + 7 - bitnum); + font |= (epoch->vram[bit9addr] << (7 - bitnum)) & 0x80; // if(chr!=0x20) epoch_log("faddr: %x, scline: %x, chr: %x, font: %x ", fontbase + chr * 0x80 + epoch->scanline * 4, epoch->scanline, chr, font); } // if(chr!=0x20) epoch_log("memaddr: %x, scanline: %x, chr: %x, font: %x ", epoch->memaddr, epoch->scanline, chr, font); @@ -1287,31 +1304,27 @@ epoch_vram_writew(uint32_t addr, uint16_t val, void *priv) /* rw one word with 9 bits */ /* virtual: 20000h (0010b, 0011b) -> real: 00001h (0000b, 0001b) */ - toaddr = addr; - if (addr & 2) - toaddr--; - if (addr & 0x20000) - toaddr += 2; - toaddr &= 0x1ffff; - - //addr >>= 1; + toaddr = getaddr_9bitword(addr); + bitnum = toaddr & 7; epoch_vram_write(toaddr, val & 0xff, epoch); - // epoch_log("%x %x ", toaddr, val); + // epoch_log("%x %x\n", toaddr, val); /* get 9th bit */ - bitnum = toaddr & 0x7; toaddr >>= 3; toaddr += 0x20000; /* real: C0000h */ val >>= 15; + // epoch_log("%x %x ", toaddr, val); val <<= bitnum; - val |= epoch_vram_read(toaddr, epoch) & ~(1 << bitnum);/* mask to update one bit */ + // epoch_log("%x ", val); + val |= (epoch_vram_read(toaddr, epoch) & (~(1 << bitnum)));/* mask to update one bit */ epoch_vram_write(toaddr, val, epoch); + // epoch_log("%x %x\n", toaddr, val); // epoch_log("%x %x\n", addr, val); } else {/* is graphic mode */ epoch_vram_write(addr, val & 0xff, epoch); epoch_vram_write(addr + 1, val >> 8, epoch); } - // epoch_log("%x %x\n", addr, addr + 1); + // epoch_log("%x %x\n", addr, val); } // static uint8_t @@ -1382,15 +1395,10 @@ epoch_vram_readw(uint32_t addr, void *priv) /* rw one word with 9 bits */ /* virtual: 20000h (0010b, 0011b) -> real: 00001h (0000b, 0001b) */ - toaddr = addr; /* 1101 */ - if (addr & 2) - toaddr--; - if (addr & 0x20000) - toaddr += 2; - toaddr &= 0x1ffff; + toaddr = getaddr_9bitword(addr); + bitnum = toaddr & 7; ret = epoch_vram_read(toaddr, epoch); /* get 9th bit */ - bitnum = toaddr & 0x7; toaddr >>= 3; toaddr += 0x20000; /* real: C0000h */ ret |= (epoch_vram_read(toaddr, epoch) << (8 + 7 - bitnum)) & 0x8000; @@ -2148,11 +2156,11 @@ epoch_nvr_reset(nvr_t *nvr) } static void -epoch_nvr_init(epoch_t *epoch, int size) +epoch_nvr_init(epoch_t *epoch) { nvr_t* nvr = &epoch->nvr; /* This is machine specific. */ - nvr->size = size; + nvr->size = 17; nvr->irq = -1; /* Set up any local handlers here. */ nvr->reset = epoch_nvr_reset; @@ -2315,6 +2323,8 @@ epoch_init(UNUSED(const device_t *info)) changeframecount = 3; epoch->vram = calloc(1, 256* 1024); + // for(int i=0;i<256*1024;i++) /* for debug */ + // epoch->vram[i] = 0xff; epoch->cram = calloc(1, 4 * 1024); // epoch->fontcard.rom = calloc(1, EPOCH_FONTROM_SIZE); // epoch_video_load_font("roms/machines/ibm5550/GEN1FONT.BIN", epoch); @@ -2347,7 +2357,7 @@ epoch_init(UNUSED(const device_t *info)) timer_add(&epoch->timer, epoch_poll, epoch, 1); - epoch_nvr_init(epoch, 17); + epoch_nvr_init(epoch); epoch->font24 = device_get_config_int("model"); From c03a4e91c945fe1745d958e7d44e6074c276644a Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Fri, 20 Feb 2026 23:36:08 +0900 Subject: [PATCH 08/11] IBM 5550: Add cursor blinking Added cursor blinking controlled by CRTC (HD46505). --- src/machine/m_xt_ibm5550.c | 20 +++++++++++++++++--- src/video/vid_ps55da2.c | 2 +- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/machine/m_xt_ibm5550.c b/src/machine/m_xt_ibm5550.c index 2edb547a4..ccc55578b 100644 --- a/src/machine/m_xt_ibm5550.c +++ b/src/machine/m_xt_ibm5550.c @@ -862,7 +862,7 @@ epoch_render_text(epoch_t *epoch) } /* Drawing text cursor */ drawcursor = ((epoch->memaddr == epoch->cursoraddr) && epoch->cursorvisible && epoch->cursoron); - if (drawcursor && epoch->scanline >= epoch->crtc[LC_CURSOR_ROW_START] && epoch->scanline <= epoch->crtc[LC_CURSOR_ROW_END]) { + if (drawcursor) { // int cursorwidth = (epoch->crtc[LC_COMPATIBILITY] & 0x20 ? 26 : 13); int cursorwidth = epoch->char_width; int cursorcolor = 2; /* Choose color 2 if mode 8 */ @@ -1140,11 +1140,25 @@ epoch_poll(void *priv) // if (epoch->attrc[LV_CURSOR_CONTROL] & 0x01) /* cursor blinking */ // { // epoch->cursoron = (epoch->blink | 1) & epoch->blinkconf; - epoch->cursoron = 1; + // epoch->cursoron = 1; // } else { // epoch->cursoron = 0; // } - if (!(epoch->blink & (0x10 - 1))) /* force redrawing for cursor and blink attribute */ + switch (epoch->crtc[LC_CURSOR_ROW_START] & 0x60) { + case 0x20: + epoch->cursoron = 0; + break; + case 0x60: + epoch->cursoron = epoch->blink & 0x10; + break; + case 0x40: + epoch->cursoron = epoch->blink & 0x08; + break; + default: + epoch->cursoron = 1; + break; + } + if (!(epoch->blink & (0x08 - 2))) /* force redrawing for cursor and blink attribute */ epoch->fullchange = changeframecount; } epoch->blink++; diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index a1d7fe25f..9dffcdf97 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -2055,7 +2055,7 @@ da2_render_text(da2_t *da2) } /* Drawing text cursor */ drawcursor = ((da2->memaddr == da2->cursoraddr) && da2->cursorvisible && da2->cursoron); - if (drawcursor && da2->scanline >= da2->crtc[LC_CURSOR_ROW_START] && da2->scanline <= da2->crtc[LC_CURSOR_ROW_END]) { + if (drawcursor) { int cursorwidth = (da2->crtc[LC_COMPATIBILITY] & 0x20 ? 26 : 13); int cursorcolor = (colormode) ? IRGBtoBGRI(da2->attrc[LV_CURSOR_COLOR]) : 2; /* Choose color 2 if mode 8 */ fg = (colormode) ? getPS55ForeColor(attr, da2) : ((attr & 0x08) ? 3 : 2); From 894e4bb0cf08456d3221b47b67744dfce04c7ed9 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 21 Feb 2026 02:25:07 +0900 Subject: [PATCH 09/11] IBM 5550: Set pixel clock for Font 16 --- src/machine/m_xt_ibm5550.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/machine/m_xt_ibm5550.c b/src/machine/m_xt_ibm5550.c index ccc55578b..aefbf0193 100644 --- a/src/machine/m_xt_ibm5550.c +++ b/src/machine/m_xt_ibm5550.c @@ -73,7 +73,8 @@ #define EPOCH_MASK_CRAM 0xfff /* 0xFFF */ #define EPOCH_MASK_VRAM 0x3ffff /* 0xFFFFF */ // #define EPOCH_MASK_VRAMPLANE 0x1ffff /* 0x1FFFF */ -#define EPOCH_PIXELCLOCK 40000000.0 /* 40 MHz interlaced */ +#define EPOCH_PIXELCLOCK24 40000000.0 /* 40 MHz interlaced */ +#define EPOCH_PIXELCLOCK16 20000000.0 /* 20 MHz interlaced (not confirmed) */ #define EPOCH_CONFIG_MONO16 0 /* Model 5551-Axx (Font 16, monochrome) */ #define EPOCH_CONFIG_MONO24 1 /* Model 5551-Bxx (Font 24, monochrome) */ @@ -241,6 +242,7 @@ typedef struct epoch_t { int scrollcache; int char_width; int font24; + double pixelclock; int firstline, lastline; int firstline_draw, lastline_draw; @@ -1088,7 +1090,7 @@ epoch_poll(void *priv) video_wait_for_buffer(); } - if((epoch->displine ^ !epoch->oddeven) & 1) + if ((epoch->displine ^ !epoch->oddeven) & 1) epoch->render(epoch); if (epoch->lastline < epoch->displine) @@ -1199,8 +1201,8 @@ epoch_poll(void *priv) epoch->vslines = 0; - epoch->memaddr - = epoch->memaddr_backup = epoch->memaddr_latch << 1; + epoch->memaddr + = epoch->memaddr_backup = epoch->memaddr_latch << 1; epoch->cursoraddr = ((epoch->crtc[LC_CURSOR_LOC_HIGH] << 8) | epoch->crtc[LC_CURSOR_LOC_LOWJ]) + epoch->ca_adj; epoch->cursoraddr <<= 1; @@ -1431,7 +1433,7 @@ epoch_cram_write(uint32_t addr, uint8_t val, void *priv) // if ((addr & ~0xfff) != 0xE0000) return; addr &= EPOCH_MASK_CRAM; epoch->cram[addr] = val; - epoch->fullchange = changeframecount;; + epoch->fullchange = changeframecount; // epoch_log("cw %04X:%04X %04X %02X\n", cs >> 4, cpu_state.pc, addr, val); } static void @@ -2328,6 +2330,8 @@ static void * epoch_init(UNUSED(const device_t *info)) { epoch_t *epoch = calloc(1, sizeof(epoch_t)); + epoch->font24 = device_get_config_int("model"); + video_inform(VIDEO_FLAG_TYPE_NONE, &timing_epoch_vid); video_update_timing(); @@ -2335,6 +2339,10 @@ epoch_init(UNUSED(const device_t *info)) epoch->dispofftime = 1000ull << 32; // epoch->changedvram = calloc(1, (EPOCH_MASK_VRAMPLANE + 1) >> 9); /* XX000h */ changeframecount = 3; + if (epoch->font24) + epoch->pixelclock = EPOCH_PIXELCLOCK24; + else + epoch->pixelclock = EPOCH_PIXELCLOCK16; epoch->vram = calloc(1, 256* 1024); // for(int i=0;i<256*1024;i++) /* for debug */ @@ -2343,7 +2351,7 @@ epoch_init(UNUSED(const device_t *info)) // epoch->fontcard.rom = calloc(1, EPOCH_FONTROM_SIZE); // epoch_video_load_font("roms/machines/ibm5550/GEN1FONT.BIN", epoch); - epoch->epochconst = (uint64_t) ((cpuclock / EPOCH_PIXELCLOCK) * (double) (1ull << 32)); + epoch->epochconst = (uint64_t) ((cpuclock / epoch->pixelclock) * (double) (1ull << 32)); mem_mapping_add(&epoch->cmap, 0xE0000, 0x1000, epoch_cram_readb, epoch_cram_readw, NULL, epoch_cram_writeb, epoch_cram_writew, NULL, NULL, MEM_MAPPING_EXTERNAL, epoch); @@ -2373,8 +2381,6 @@ epoch_init(UNUSED(const device_t *info)) epoch_nvr_init(epoch); - epoch->font24 = device_get_config_int("model"); - return epoch; } @@ -2441,7 +2447,7 @@ static void epoch_speed_changed(void *priv) { epoch_t *epoch = (epoch_t *) priv; - epoch->epochconst = (uint64_t) ((cpuclock / EPOCH_PIXELCLOCK) * (double) (1ull << 32)); + epoch->epochconst = (uint64_t) ((cpuclock / epoch->pixelclock) * (double) (1ull << 32)); epoch_recalctimings(epoch); } From 3a199fb8cb83d4540d985e677d0431208f398ec8 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 21 Feb 2026 02:26:54 +0900 Subject: [PATCH 10/11] PS55DA2: Change to interlaced screen update --- src/video/vid_ps55da2.c | 62 ++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 25 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 9dffcdf97..0bd5035b0 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -64,7 +64,7 @@ #define DA2_MASK_GAIJIRAM 0x3ffff /* 0x3FFFF */ #define DA2_MASK_VRAM 0xfffff /* 0xFFFFF */ #define DA2_MASK_VRAMPLANE 0x1ffff /* 0x1FFFF */ -#define DA2_PIXELCLOCK 29000000.0 /* 58 MHz interlaced */ +#define DA2_PIXELCLOCK 58000000.0 /* 58 MHz interlaced */ #define DA2_BLT_MEMSIZE 0x10 #define DA2_BLT_REGSIZE 0x40 #define DA2_DEBUG_BLTLOG_SIZE (DA2_BLT_REGSIZE + 1) @@ -368,6 +368,7 @@ typedef struct da2_t { int firstline, lastline; int firstline_draw, lastline_draw; int displine; + int oddeven; /* Attribute Buffer E0000-E0FFFh (4 KB) */ uint8_t *cram; @@ -441,6 +442,9 @@ typedef struct da2_t { int old_pos2; } da2_t; +static video_timings_t timing_da2_mca = +{ .type = VIDEO_MCA, .write_b = 4, .write_w = 4, .write_l = 10, .read_b = 4, .read_w = 4, .read_l = 10 }; + static void da2_recalctimings(da2_t *da2); static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p); static void da2_bitblt_exec(void *p); @@ -515,7 +519,7 @@ da2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32 *s uint32_t writepx[8]; destaddr &= 0xfffffffe; /* align to word address to work bit shift correctly */ // da2_log("DA2_WPDWB addr %x mask %x rop %x shift %d\n", destaddr, mask, da2->bitblt.raster_op, da2->bitblt.bitshift_destr); - da2->changedvram[(DA2_MASK_VRAMPLANE & destaddr) >> 9] = changeframecount; + da2->changedvram[(DA2_MASK_VRAMPLANE & destaddr) >> 9] = 3; destaddr <<= 3; /* read destination data with big endian order */ for (uint8_t i = 0; i < 8; i++) @@ -1245,7 +1249,7 @@ da2_out(uint16_t addr, uint16_t val, void *priv) case 0x3C9: /* Data */ // da2_iolog("DA2 Out addr %03X idx %d:%d val %02X %04X:%04X esdi %04X:%04X\n", addr, da2->dac_write, da2->dac_pos, val, cs >> 4, cpu_state.pc, ES, DI); da2->dac_status = 0; - da2->fullchange = changeframecount; + da2->fullchange = 3; switch (da2->dac_pos) { case 0: da2->dac_r = val; @@ -1283,7 +1287,7 @@ da2_out(uint16_t addr, uint16_t val, void *priv) if (da2->ioctladdr == LS_RESET && val & 0x01) /* Reset register */ da2_reset_ioctl(da2); else if (da2->ioctladdr == LS_MODE && ((oldval ^ val) & 0x03)) { /* Mode register */ - da2->fullchange = changeframecount; + da2->fullchange = 3; da2_recalctimings(da2); da2_updatevidselector(da2); } @@ -1372,7 +1376,7 @@ da2_out(uint16_t addr, uint16_t val, void *priv) case LC_START_V_DISPLAY_ENAB: case LC_VIEWPORT_SELECT: case LC_VIEWPORT_PRIORITY: - da2->fullchange = changeframecount; + da2->fullchange = 3; da2_recalctimings(da2); break; default: @@ -1391,13 +1395,13 @@ da2_out(uint16_t addr, uint16_t val, void *priv) // da2_iolog("set attraddr: %X\n", da2->attraddr); } else { if ((da2->attraddr == LV_PANNING) && (da2->attrc[LV_PANNING] != val)) - da2->fullchange = changeframecount; + da2->fullchange = 3; if (da2->attrc[da2->attraddr & 0x3f] != val) da2_iolog("attr changed %x: %x -> %x\n", da2->attraddr & 0x3f, da2->attrc[da2->attraddr & 0x3f], val); da2->attrc[da2->attraddr & 0x3f] = val; // da2_iolog("set attrc %x: %x\n", da2->attraddr & 31, val); if (da2->attraddr < 16) - da2->fullchange = changeframecount; + da2->fullchange = 3; if (da2->attraddr == LV_MODE_CONTROL || da2->attraddr < 0x10) { for (uint8_t c = 0; c < 16; c++) { // if (da2->attrc[LV_MODE_CONTROL] & 0x80) da2->egapal[c] = (da2->attrc[c] & 0xf) | ((da2->attrc[0x14] & 0xf) << 4); @@ -1411,7 +1415,7 @@ da2_out(uint16_t addr, uint16_t val, void *priv) switch (da2->attraddr) { case LV_COLOR_PLANE_ENAB: if ((val & 0xff) != da2->plane_mask) - da2->fullchange = changeframecount; + da2->fullchange = 3; da2->plane_mask = val & 0xff; break; case LV_CURSOR_CONTROL: @@ -2743,7 +2747,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *priv) //} #endif cycles -= video_timing_write_b; - da2->changedvram[addr >> 9] = changeframecount;/* 0x1FFFF -> 0x1F */ + da2->changedvram[addr >> 9] = 3;/* 0x1FFFF -> 0x1F */ addr <<= 3; for (uint8_t i = 0; i < 8; i++) @@ -2804,7 +2808,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *priv) } else { /* mode 3h text */ cycles -= video_timing_write_b; da2_vram_w(addr, val, da2); - da2->fullchange = 2; + da2->fullchange = 3; } } static uint16_t @@ -2843,7 +2847,7 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *priv) // da2_log("da2_gcW m%d a%x d%x\n", da2->writemode, addr, val); // da2_log("da2_gcW %05X %02X %04X:%04X esdi %04X:%04X dssi %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc, ES, DI, DS, SI); - da2->changedvram[addr >> 9] = changeframecount; + da2->changedvram[addr >> 9] = 3; addr <<= 3; for (uint8_t i = 0; i < 8; i++) @@ -2942,7 +2946,7 @@ da2_code_write(uint32_t addr, uint8_t val, void *priv) // if ((addr & ~0xfff) != 0xE0000) return; addr &= DA2_MASK_CRAM; da2->cram[addr] = val; - da2->fullchange = 2; + da2->fullchange = 3; } static void da2_code_writeb(uint32_t addr, uint8_t val, void *priv) @@ -2987,7 +2991,7 @@ da2_code_readw(uint32_t addr, void *priv) } static void -da2_doblit(int y1, int y2, int wx, int wy, da2_t *da2) +da2_doblit(int wx, int wy, da2_t *da2) { if (wx != xsize || wy != ysize) { xsize = wx; @@ -3026,14 +3030,14 @@ da2_poll(void *priv) video_wait_for_buffer(); } - if (!da2->override) + if (!da2->override && ((da2->displine ^ !da2->oddeven) & 1)) da2->render(da2); if (da2->lastline < da2->displine) da2->lastline = da2->displine; } - - // da2_log("%03i %06X %06X\n", da2->displine, da2->memaddr,da2->vram_display_mask); + // if(da2->fullchange) + // pclog("%03i %05X %d %d\n", da2->displine, da2->memaddr, ((da2->displine ^ !da2->oddeven) & 1), da2->fullchange); da2->displine++; if ((da2->cgastat & 8) && ((da2->displine & 0xf) == (da2->crtc[LC_VERTICAL_SYNC_END] & 0xf)) && da2->vslines) { // da2_log("Vsync off at line %i\n",displine); @@ -3085,14 +3089,13 @@ da2_poll(void *priv) // if (da2->crtc[10] & 0x20) da2->cursoron = 0; // else da2->cursoron = da2->blink & 16; if (da2->ioctl[LS_MODE] & 1) { /* in text mode */ - if (da2->attrc[LV_CURSOR_CONTROL] & 0x01) /* cursor blinking */ - { + if (da2->attrc[LV_CURSOR_CONTROL] & 0x01) {/* cursor blinking */ da2->cursoron = (da2->blink | 1) & da2->blinkconf; } else { da2->cursoron = 0; } - if (!(da2->blink & (0x10 - 1))) /* force redrawing for cursor and blink attribute */ - da2->fullchange = 2; + if (!(da2->blink & (0x08 - 1))) /* force redrawing for cursor and blink attribute */ + da2->fullchange = 3; } da2->blink++; @@ -3103,6 +3106,7 @@ da2_poll(void *priv) // memset(changedvram,0,2048); del if (da2->fullchange) { da2->fullchange--; + // pclog("fc %d %d\n",da2->fullchange,da2->oddeven); } } if (da2->vc == da2->vsyncstart) { @@ -3112,10 +3116,15 @@ da2_poll(void *priv) da2->cgastat |= 8; x = da2->hdisp; + if (!da2->oddeven) + da2->lastline++; + if (da2->oddeven) + da2->firstline--; + wx = x; wy = da2->lastline - da2->firstline; - da2_doblit(da2->firstline_draw, da2->lastline_draw + 1, wx, wy, da2); + da2_doblit(wx, wy, da2); da2->firstline = 2000; da2->lastline = 0; @@ -3123,7 +3132,8 @@ da2_poll(void *priv) da2->firstline_draw = 2000; da2->lastline_draw = 0; - changeframecount = 2; + da2->oddeven ^= 1; + da2->vslines = 0; da2->memaddr @@ -3137,7 +3147,7 @@ da2_poll(void *priv) // da2_log("VC vtotal\n"); // printf("Frame over at line %i %i %i %i\n",displine,vc,da2_vsyncstart,da2_dispend); da2->vc = 0; - da2->scanline = da2->crtc[LC_PRESET_ROW_SCANJ] & 0x1f; + da2->scanline = da2->crtc[LC_PRESET_ROW_SCANJ] & 0x1f; da2->dispon = 1; da2->displine = 0; da2->scrollcache = da2->attrc[LV_PANNING] & 7; @@ -3229,7 +3239,8 @@ da2_reset(void *priv) da2->attrc[LV_CURSOR_COLOR] = 0x0f; /* cursor color */ da2->crtc[LC_HORIZONTAL_TOTAL] = 63; /* Horizontal Total */ da2->crtc[LC_VERTICAL_TOTALJ] = 255; /* Vertical Total (These two must be set before the timer starts.) */ - da2->memaddr_latch = 0; + da2->memaddr_latch = 0; + da2->oddeven = 0; da2->attrc[LV_CURSOR_CONTROL] = 0x13; /* cursor options */ da2->attr_palette_enable = 0; /* disable attribute generator */ @@ -3278,6 +3289,7 @@ da2_init(UNUSED(const device_t *info)) mca_add(da2_mca_read, da2_mca_write, da2_mca_feedb, da2_mca_reset, da2); da2->da2const = (uint64_t) ((cpuclock / DA2_PIXELCLOCK) * (double) (1ull << 32)); + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_da2_mca); memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); memset(da2->bitblt.reg, 0xfe, DA2_BLT_REGSIZE * sizeof(uint32_t)); /* clear memory */ #ifdef ENABLE_DA2_DEBUGBLT @@ -3432,7 +3444,7 @@ static void da2_force_redraw(void *priv) { da2_t *da2 = (da2_t *) priv; - da2->fullchange = changeframecount; + da2->fullchange = 3; } static const device_config_t da2_configuration[] = { From dad8edd32e89094d85a8ca7533dcae0aa222b72f Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 21 Feb 2026 02:40:26 +0900 Subject: [PATCH 11/11] cleanup (m_xt_ibm5550.c) --- src/machine/m_xt_ibm5550.c | 169 ++++--------------------------------- 1 file changed, 17 insertions(+), 152 deletions(-) diff --git a/src/machine/m_xt_ibm5550.c b/src/machine/m_xt_ibm5550.c index aefbf0193..00f203f1a 100644 --- a/src/machine/m_xt_ibm5550.c +++ b/src/machine/m_xt_ibm5550.c @@ -18,7 +18,7 @@ * These first-gen models have 1-3 DSQD diskette drives. * You need select "Type: 5.25" 720k" in the Settings dialog - Floppy & CD-ROM drives. * - * Currently, this module only support the model B configuration without hard disk. + * Currently, this module supports model A and B configurations without hard disk. * * Authors: Akamaki. * @@ -133,12 +133,12 @@ // #define LV_OUTPUT 0x3E // #define LV_COMPATIBILITY 0x3F -#define TIMER_CTR_0 0 //DMA -#define TIMER_CTR_1 1 //8253 timer -#define TIMER_CTR_2 2 //Speaker +#define TIMER_CTR_0 0 /* DMA */ +#define TIMER_CTR_1 1 /* PIT */ +#define TIMER_CTR_2 2 /* Speaker */ -#define EPOCH_IRQ3_BIT (1 << 3) //Keyboard -#define EPOCH_IRQ6_BIT (1 << 6) //Timer +#define EPOCH_IRQ3_BIT (1 << 3) /* Keyboard */ +#define EPOCH_IRQ6_BIT (1 << 6) /* PIT */ enum epoch_nvr_ADDR { epoch_nvr_SECOND1, @@ -161,7 +161,7 @@ enum epoch_nvr_ADDR { }; #ifndef RELEASE_BUILD -#define ENABLE_EPOCH_LOG 1 +//#define ENABLE_EPOCH_LOG 1 #endif #ifdef ENABLE_EPOCH_LOG @@ -381,7 +381,7 @@ epoch_out(uint16_t addr, uint16_t val, void *priv) case LC_MAXIMUM_SCAN_LINE: case LC_START_ADDRESS_HIGH: case LC_START_ADDRESS_LOW: - epoch->fullchange = changeframecount; + epoch->fullchange = 3; epoch_recalctimings(epoch); break; default: @@ -648,6 +648,7 @@ epoch_inw(uint16_t addr, void *priv) return temp; } +/* Return a memory address for 9-bit word access */ static uint32_t getaddr_9bitword(int32_t addr) { @@ -1139,13 +1140,6 @@ epoch_poll(void *priv) if (epoch->vc == epoch->dispend) { epoch->dispon = 0; if (!(epoch->crtmode & 0x02)) { /* in text mode */ - // if (epoch->attrc[LV_CURSOR_CONTROL] & 0x01) /* cursor blinking */ - // { - // epoch->cursoron = (epoch->blink | 1) & epoch->blinkconf; - // epoch->cursoron = 1; - // } else { - // epoch->cursoron = 0; - // } switch (epoch->crtc[LC_CURSOR_ROW_START] & 0x60) { case 0x20: epoch->cursoron = 0; @@ -1161,7 +1155,7 @@ epoch_poll(void *priv) break; } if (!(epoch->blink & (0x08 - 2))) /* force redrawing for cursor and blink attribute */ - epoch->fullchange = changeframecount; + epoch->fullchange = 3; } epoch->blink++; @@ -1227,112 +1221,44 @@ static void epoch_vram_write(uint32_t addr, uint8_t val, void *priv) { epoch_t *epoch = (epoch_t *) priv; - // if ((addr & ~0xfff) != 0xE0000) return; // epoch_log("epoch_vw: %x %x\n", addr, val); addr &= EPOCH_MASK_VRAM; epoch->vram[addr] = val; - epoch->fullchange = changeframecount; - // if(val == 0x66) - // epoch_log("66 %04X:%04X %04X:%04X>%04X:%04X\n", cs >> 4, cpu_state.pc, DS, SI,ES,DI); + epoch->fullchange = 3; } static uint8_t epoch_vram_read(uint32_t addr, void *priv) { epoch_t *epoch = (epoch_t *) priv; - // if ((addr & ~epoch_MASK_CRAM) != 0xE0000) - // return epoch_INVALIDACCESS8; addr &= EPOCH_MASK_VRAM; return epoch->vram[addr]; } -// static void -// epoch_vram_writeb(uint32_t addr, uint8_t val, void *priv) -// { -// epoch_t *epoch = (epoch_t *) priv; -// // epoch_log("%04X:%04X epoch_vwb: %x, val %x\n", cs >> 4, cpu_state.pc, addr, val); -// cycles -= video_timing_write_b; -// // return; -// // epoch_vram_write(addr, val, epoch); -// } static void epoch_vram_writew(uint32_t addr, uint16_t val, void *priv) { epoch_t *epoch = (epoch_t *) priv; - // uint8_t convert[8] = {0, 2, 8, 8, 1, 3, 8, 8};/* only even chars */ - //uint8_t convert[8] = {8, 8, 0, 2, 8, 8, 1, 3};/* only even chars */ - // uint8_t convert[8] = {0, 1, 2, 3, 4, 5, 6, 7};/* all but alt */ - // uint8_t convert[8] = {0, 1, 2, 3, 8, 8, 8, 8};/* even alt */ - // uint8_t convert[8] = {8, 8, 8, 8, 0, 1, 2, 3};/* even alt */ - // uint8_t convert[8] = {0, 4, 1, 5, 2, 6, 3, 7};/* all but pos+-1 */ - // uint8_t convert[8] = {8, 8, 4, 6, 8, 8, 5, 7};/* only odd (0) */ - // uint8_t convert[8] = {8, 8, 0, 2, 8, 8, 1, 3};/* only even */ - // uint8_t convert[8] = {4, 6, 8, 8, 5, 7, 8, 8};/* only odd (0) */ - // uint8_t convert[8] = {8, 4, 6, 8, 8, 5, 7, 8};/* none */ // epoch_log("%04X:%04X epoch_vww: %x, val %x DS %x SI %x ES %x DI %x %x\n", cs >> 4, cpu_state.pc, addr, val,DS,SI,ES,DI, epoch->crtc[LC_INTERLACE_AND_SKEW]); // epoch_log("%04X:%04X epoch_vww: %x, val %x cm %x\n", cs >> 4, cpu_state.pc, addr, val, epoch->crtmode); cycles -= video_timing_write_w; addr -= 0xA0000; - // addr &= 0xfffffffe; - // if (0) { if (!(epoch->crtmode & 0x02) && !(epoch->font24)) { uint32_t toaddr, bitnum; - // if (addr < 0xd0000) { - // int index = (addr - 0xA0000) >> 7; /* 128 bytes per char */ - // addr &= 0x007f; - // addr += 0xA0000 + 84 * index; - // epoch_log("%x %x\n", addr, index); - // } else if (addr >= 0xD8000) { - // int index = (addr - 0xD8000) >> 7; /* 128 bytes per char */ - // addr &= 0x007f; - // if (addr & 2) return; - // addr >>= 1; - // addr += 0xC0000 + 42 * index; - // epoch_log("%x %x\n", addr, index); - // } else - // return; - - // if (addr < 0xd0000) { - // addr -= 0xA0000; - // if (addr & 2) - // return; - // addr >>= 1; - // addr += 0xA0000; - // } else if (addr >= 0xD8000) { - // addr -= 0xD8000; - // if (addr & 2) - // return; - // addr >>= 1; - // addr += 0xD8000; - // } else - // return; - - // addr >>= 1; - // if(addr & 0x02) - // addr--; - // addr ^= 0x06; - //addr &= 0xffffd;/* 1101 */ - // addr >>= 1; - - // if (convert[(addr + 0) & 7] > 7) - // return; - // epoch_vram_write((addr & 0xffff8) + convert[(addr + 0) & 7], val & 0xff, epoch); - // epoch_vram_write((addr & 0xffff8) + convert[(addr + 1) & 7], val >> 8, epoch); /* rw one word with 9 bits */ /* virtual: 20000h (0010b, 0011b) -> real: 00001h (0000b, 0001b) */ - toaddr = getaddr_9bitword(addr); bitnum = toaddr & 7; epoch_vram_write(toaddr, val & 0xff, epoch); - // epoch_log("%x %x\n", toaddr, val); + /* get 9th bit */ toaddr >>= 3; toaddr += 0x20000; /* real: C0000h */ val >>= 15; - // epoch_log("%x %x ", toaddr, val); val <<= bitnum; - // epoch_log("%x ", val); - val |= (epoch_vram_read(toaddr, epoch) & (~(1 << bitnum)));/* mask to update one bit */ + + /* mask to update one bit */ + val |= (epoch_vram_read(toaddr, epoch) & (~(1 << bitnum))); epoch_vram_write(toaddr, val, epoch); // epoch_log("%x %x\n", toaddr, val); // epoch_log("%x %x\n", addr, val); @@ -1343,72 +1269,17 @@ epoch_vram_writew(uint32_t addr, uint16_t val, void *priv) // epoch_log("%x %x\n", addr, val); } -// static uint8_t -// epoch_vram_readb(uint32_t addr, void *priv) -// { -// epoch_t *epoch = (epoch_t *) priv; -// cycles -= video_timing_read_b; -// // return 0xff; -// // epoch_log("%04X:%04X epoch_vrb: %x, val %x\n", cs >> 4, cpu_state.pc, addr, epoch_vram_read(addr, epoch)); -// // return epoch_vram_read(addr, epoch); -// } - static uint16_t epoch_vram_readw(uint32_t addr, void *priv) { epoch_t *epoch = (epoch_t *) priv; - // uint8_t convert[8] = {0, 2, 4, 6, 1, 3, 5, 7};/* all but pos+-1 */ - // uint8_t convert[8] = {0, 4, 8, 8, 8, 8, 8, 8};/* all but pos+-1 */ cycles -= video_timing_read_w; addr -= 0xA0000; // epoch_log("%04X:%04X epoch_vrw: %x cm %x\n", cs >> 4, cpu_state.pc, addr, epoch->crtmode); - // addr &= 0xfffffffe; - //read 0->0,1 2->2,3 4->4,5 6->6,7 - //read 0->0,2 2->1,3 4->4,6 6->5,7 - // if (0) { if (!(epoch->crtmode & 0x02) && !(epoch->font24)) { uint16_t ret; uint32_t bitnum; uint32_t toaddr; - // if (addr < 0xd0000) { - // int index = (addr - 0xA0000) >> 7; /* 128 bytes per char */ - // addr &= 0x007f; - // addr += 0xA0000 + 84 * index; - // epoch_log("%x %x %x\n", addr, index, epoch_vram_read(addr, epoch) | (epoch_vram_read(addr + 1, epoch) << 8)); - // } else if (addr >= 0xD8000) { - // int index = (addr - 0xD8000) >> 7; /* 128 bytes per char */ - // addr &= 0x007f; - // if (addr & 2) return EPOCH_INVALIDACCESS16; - // addr >>= 1; - // addr += 0xC0000 + 42 * index; - // epoch_log("%x %x %x\n", addr, index, epoch_vram_read(addr, epoch) | (epoch_vram_read(addr + 1, epoch) << 8)); - // } else - // return EPOCH_INVALIDACCESS16; - - // if (addr < 0xd0000) { - // addr -= 0xA0000; - // if (addr & 2) - // return EPOCH_INVALIDACCESS16; - // addr >>= 1; - // addr += 0xA0000; - // } else if (addr >= 0xD8000) { - // addr -= 0xD8000; - // if (addr & 2) - // return EPOCH_INVALIDACCESS16; - // addr >>= 1; - // addr += 0xD8000; - // } else - // return EPOCH_INVALIDACCESS16; - - // if(addr & 0x02) - // addr--; - // // addr ^= 0x06; - // addr >>= 1; - - // if (convert[(addr + 0) & 7] > 7) - // return 0; - // return epoch_vram_read((addr & 0xffff8) + convert[addr & 7], epoch) | (epoch_vram_read((addr & 0xffff8) + convert[(addr + 1) & 7], epoch) << 8); - /* rw one word with 9 bits */ /* virtual: 20000h (0010b, 0011b) -> real: 00001h (0000b, 0001b) */ toaddr = getaddr_9bitword(addr); @@ -1430,10 +1301,9 @@ static void epoch_cram_write(uint32_t addr, uint8_t val, void *priv) { epoch_t *epoch = (epoch_t *) priv; - // if ((addr & ~0xfff) != 0xE0000) return; addr &= EPOCH_MASK_CRAM; epoch->cram[addr] = val; - epoch->fullchange = changeframecount; + epoch->fullchange = 3; // epoch_log("cw %04X:%04X %04X %02X\n", cs >> 4, cpu_state.pc, addr, val); } static void @@ -1458,8 +1328,6 @@ static uint8_t epoch_cram_read(uint32_t addr, void *priv) { epoch_t *epoch = (epoch_t *) priv; - // if ((addr & ~epoch_MASK_CRAM) != 0xE0000) - // return epoch_INVALIDACCESS8; addr &= EPOCH_MASK_CRAM; return epoch->cram[addr]; } @@ -1495,7 +1363,6 @@ epoch_parity_readb(uint32_t addr, void *priv) return EPOCH_INVALIDACCESS8; } } - // return EPOCH_INVALIDACCESS8; return mem_read_ram(addr, priv); } @@ -1533,8 +1400,6 @@ epoch_parity_writeb(uint32_t addr, uint8_t val, void *priv) return; } } - // if (val == 0xcb) - // epoch_log("CB %04X:%04X %04X:%04X>%04X:%04X\n", cs >> 4, cpu_state.pc, DS, SI, ES, DI); mem_write_ram(addr, val, priv); } static void @@ -2338,7 +2203,7 @@ epoch_init(UNUSED(const device_t *info)) epoch->dispontime = 1000ull << 32; epoch->dispofftime = 1000ull << 32; // epoch->changedvram = calloc(1, (EPOCH_MASK_VRAMPLANE + 1) >> 9); /* XX000h */ - changeframecount = 3; + if (epoch->font24) epoch->pixelclock = EPOCH_PIXELCLOCK24; else