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; } } 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..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. * @@ -73,12 +73,13 @@ #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) */ #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 @@ -97,6 +98,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 @@ -128,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, @@ -156,11 +161,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 +241,8 @@ typedef struct epoch_t { int cursorvisible, cursoron, blink; int scrollcache; int char_width; + int font24; + double pixelclock; int firstline, lastline; int firstline_draw, lastline_draw; @@ -300,13 +307,37 @@ 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) | | 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) { @@ -350,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: @@ -369,8 +400,12 @@ epoch_out(uint16_t addr, uint16_t val, void *priv) mem_mapping_disable(&epoch->vmap); // mem_mapping_enable(&epoch->paritymap); break; - case 0x3D8: + 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); +#endif epoch_recalctimings(epoch); // epoch->attrff ^= 1; break; @@ -484,7 +519,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) @@ -494,7 +529,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; } @@ -613,22 +648,59 @@ epoch_inw(uint16_t addr, void *priv) return temp; } -/* Get character line pattern from jfont rom or gaiji volatile memory */ +/* Return a memory address for 9-bit word access */ +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) { - 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) */ + 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[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[bit9addr] << (7 - bitnum)) & 0x80; /* get 9th bit */ + // font &= 0xff80ff80; + // font |= epoch->vram[code + line * 4 + 3]; + } + } else font = EPOCH_INVALIDACCESS32; return font; } @@ -676,12 +748,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 +786,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 +802,39 @@ 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 { + 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[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); /* 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 +844,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 +860,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]) { + if (drawcursor) { // 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 +882,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; } } } @@ -848,13 +937,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) @@ -905,8 +996,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 *= 12; + epoch->char_width = 12; + } /* PS/55 8-color */ epoch_log("Set videomode to PS/55 4 bpp graphics.\n"); epoch->render = epoch_render_color_4bpp; @@ -916,8 +1012,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; @@ -990,7 +1091,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) @@ -1039,15 +1140,22 @@ 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; - // } - if (!(epoch->blink & (0x10 - 1))) /* force redrawing for cursor and blink attribute */ - epoch->fullchange = changeframecount; + 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 = 3; } epoch->blink++; @@ -1087,8 +1195,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; @@ -1113,48 +1221,52 @@ static void 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); + epoch->fullchange = 3; } -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 uint8_t -epoch_vram_readb(uint32_t addr, void *priv) + +static void +epoch_vram_writew(uint32_t addr, uint16_t val, void *priv) { epoch_t *epoch = (epoch_t *) priv; - cycles -= video_timing_read_b; - return epoch_vram_read(addr, epoch); + // 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; + if (!(epoch->crtmode & 0x02) && !(epoch->font24)) { + uint32_t toaddr, bitnum; + + /* 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); + + /* get 9th bit */ + toaddr >>= 3; + toaddr += 0x20000; /* real: C0000h */ + val >>= 15; + val <<= bitnum; + + /* 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); + } 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, val); } static uint16_t @@ -1162,7 +1274,26 @@ epoch_vram_readw(uint32_t addr, void *priv) { epoch_t *epoch = (epoch_t *) priv; 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); + if (!(epoch->crtmode & 0x02) && !(epoch->font24)) { + uint16_t ret; + uint32_t bitnum; + uint32_t toaddr; + /* rw one word with 9 bits */ + /* virtual: 20000h (0010b, 0011b) -> real: 00001h (0000b, 0001b) */ + toaddr = getaddr_9bitword(addr); + bitnum = toaddr & 7; + ret = epoch_vram_read(toaddr, epoch); + /* get 9th bit */ + 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 */ + return epoch_vram_read(addr, epoch) | (epoch_vram_read(addr + 1, epoch) << 8); + } } @@ -1170,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 @@ -1198,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]; } @@ -1235,7 +1363,6 @@ epoch_parity_readb(uint32_t addr, void *priv) return EPOCH_INVALIDACCESS8; } } - // return EPOCH_INVALIDACCESS8; return mem_read_ram(addr, priv); } @@ -1273,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 @@ -1327,8 +1452,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 +1629,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; } @@ -1567,7 +1694,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; @@ -1703,6 +1830,7 @@ kbd_close(void *priv) /* Stop the timer. */ timer_disable(&kbd->send_delay_timer); + mouse_close(); /* Disable scanning. */ keyboard_scan = 0; @@ -1909,11 +2037,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; @@ -1967,10 +2095,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; @@ -2065,32 +2195,36 @@ 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(); 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 + epoch->pixelclock = EPOCH_PIXELCLOCK16; 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); - epoch->epochconst = (uint64_t) ((cpuclock / EPOCH_PIXELCLOCK) * (double) (1ull << 32)); + 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, - 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); - 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,9 +2240,11 @@ 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_nvr_init(epoch); return epoch; } @@ -2138,6 +2274,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++) @@ -2175,7 +2312,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); } @@ -2186,8 +2323,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 +2357,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 +2418,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 03df2d9df..c7585f5ba 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 }, diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 3df73f92c..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: @@ -2055,7 +2059,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); @@ -2352,12 +2356,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 +2383,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; @@ -2744,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++) @@ -2805,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 @@ -2844,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++) @@ -2943,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) @@ -2988,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; @@ -3027,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); @@ -3086,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++; @@ -3104,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) { @@ -3113,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; @@ -3124,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 @@ -3138,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; @@ -3230,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 */ @@ -3279,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 @@ -3433,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[] = {