Merge pull request #6828 from akmed772/master

IBM 5550: Add the Font 16 display adapter
This commit is contained in:
Miran Grča
2026-02-21 04:57:10 +01:00
committed by GitHub
5 changed files with 341 additions and 166 deletions

View File

@@ -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;
}
}

View File

@@ -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 */

View File

@@ -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 <ctype.h>
// 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);

View File

@@ -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
},

View File

@@ -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[] = {