stat -> status; improve MDA register decoding; add MDA CRTC, register and mode enums

This commit is contained in:
starfrost013
2025-06-11 17:37:15 +01:00
parent dd6f7746a9
commit 317a5b7ade
16 changed files with 220 additions and 147 deletions

View File

@@ -459,7 +459,7 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len)
break;
case 0x42e8:
ibm8514_log("VBLANK stat=%02x, val=%02x.\n", dev->subsys_stat, val);
ibm8514_log("VBLANK status=%02x, val=%02x.\n", dev->subsys_stat, val);
if (len == 2) {
dev->subsys_cntl = val;
dev->subsys_stat &= ~val;

View File

@@ -3297,7 +3297,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u
case 0x42e8:
case 0x42e9:
mach_log("VBLANK stat=%02x, val=%02x.\n", dev->subsys_stat, val);
mach_log("VBLANK status=%02x, val=%02x.\n", dev->subsys_stat, val);
if (len == 2)
dev->subsys_cntl = val;
else {

View File

@@ -169,8 +169,8 @@ t3100e_out(uint16_t addr, uint8_t val, void *priv)
t3100e_recalctimings(t3100e);
return;
case 0x3D8: /* CGA control register */
case 0x3D9: /* CGA colour register */
case CGA_REGISTER_MODE_CONTROL: /* CGA control register */
case CGA_REGISTER_COLOR_SELECT: /* CGA colour register */
cga_out(addr, val, &t3100e->cga);
return;

View File

@@ -505,7 +505,7 @@ ega_in(uint16_t addr, void *priv)
case 0x3da:
ega->attrff = 0;
if (type == EGA_TYPE_COMPAQ) {
ret = ega->stat & 0xcf;
ret = ega->status & 0xcf;
switch ((ega->attrregs[0x12] >> 4) & 0x03) {
case 0x00:
/* 00 = Pri. Red (5), Pri. Blue (4) */
@@ -526,8 +526,8 @@ ega_in(uint16_t addr, void *priv)
break;
}
} else {
ega->stat ^= 0x30; /* Fools IBM EGA video BIOS self-test. */
ret = ega->stat;
ega->status ^= 0x30; /* Fools IBM EGA video BIOS self-test. */
ret = ega->status;
}
break;
case 0x7c6:
@@ -837,7 +837,7 @@ ega_poll(void *priv)
if (!ega->linepos) {
timer_advance_u64(&ega->timer, ega->dispofftime);
ega->stat |= 1;
ega->status |= 1;
ega->linepos = 1;
if (ega->dispon) {
@@ -877,8 +877,8 @@ ega_poll(void *priv)
ega->displine++;
if (ega->interlace)
ega->displine++;
if ((ega->stat & 8) && ((ega->displine & 15) == (ega->crtc[0x11] & 15)) && ega->vslines)
ega->stat &= ~8;
if ((ega->status & 8) && ((ega->displine & 15) == (ega->crtc[0x11] & 15)) && ega->vslines)
ega->status &= ~8;
ega->vslines++;
if (ega->chipset) {
if (ega->hdisp >= 800) {
@@ -896,7 +896,7 @@ ega_poll(void *priv)
timer_advance_u64(&ega->timer, ega->dispontime);
if (ega->dispon)
ega->stat &= ~1;
ega->status &= ~1;
ega->hdisp_on = 0;
ega->linepos = 0;
@@ -968,7 +968,7 @@ ega_poll(void *priv)
}
if (ega->vc == ega->vsyncstart) {
ega->dispon = 0;
ega->stat |= 8;
ega->status |= 8;
#if 0
picint(1 << 2);
#endif

View File

@@ -178,8 +178,8 @@ hercules_in(uint16_t addr, void *priv)
case 0x03ba:
ret = 0x70; /* Hercules ident */
ret |= (dev->lp_ff ? 2 : 0);
ret |= (dev->stat & 0x01);
if (dev->stat & 0x08)
ret |= (dev->status & 0x01);
if (dev->status & 0x08)
ret |= 0x80;
if ((ret & 0x81) == 0x80)
ret |= 0x08;
@@ -300,7 +300,7 @@ hercules_poll(void *priv)
if (!dev->linepos) {
timer_advance_u64(&dev->timer, dev->dispofftime);
dev->stat |= 1;
dev->status |= 1;
dev->linepos = 1;
scanline_old = dev->scanline;
@@ -380,7 +380,7 @@ hercules_poll(void *priv)
dev->scanline = scanline_old;
if (dev->vc == dev->crtc[7] && !dev->scanline)
dev->stat |= 8;
dev->status |= 8;
dev->displine++;
if (dev->displine >= 500)
dev->displine = 0;
@@ -388,13 +388,13 @@ hercules_poll(void *priv)
timer_advance_u64(&dev->timer, dev->dispontime);
if (dev->dispon)
dev->stat &= ~1;
dev->status &= ~1;
dev->linepos = 0;
if (dev->vsynctime) {
dev->vsynctime--;
if (!dev->vsynctime)
dev->stat &= ~8;
dev->status &= ~8;
}
if (dev->scanline == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->scanline == ((dev->crtc[11] & 31) >> 1))) {

View File

@@ -157,7 +157,7 @@ typedef struct {
uint8_t crtc[32];
int crtcreg;
uint8_t ctrl, ctrl2, stat;
uint8_t ctrl, ctrl2, status;
uint64_t dispontime, dispofftime;
pc_timer_t timer;
@@ -285,7 +285,7 @@ incolor_in(uint16_t port, void *priv)
case 0x3ba:
/* 0x50: InColor card identity */
ret = (dev->stat & 0xf) | ((dev->stat & 8) << 4) | 0x50;
ret = (dev->status & 0xf) | ((dev->status & 8) << 4) | 0x50;
break;
default:
@@ -863,7 +863,7 @@ incolor_poll(void *priv)
if (!dev->linepos) {
timer_advance_u64(&dev->timer, dev->dispofftime);
dev->stat |= 1;
dev->status |= 1;
dev->linepos = 1;
scanline_old = dev->scanline;
if ((dev->crtc[8] & 3) == 3)
@@ -882,19 +882,19 @@ incolor_poll(void *priv)
}
dev->scanline = scanline_old;
if (dev->vc == dev->crtc[7] && !dev->scanline)
dev->stat |= 8;
dev->status |= 8;
dev->displine++;
if (dev->displine >= 500)
dev->displine = 0;
} else {
timer_advance_u64(&dev->timer, dev->dispontime);
if (dev->dispon)
dev->stat &= ~1;
dev->status &= ~1;
dev->linepos = 0;
if (dev->vsynctime) {
dev->vsynctime--;
if (!dev->vsynctime)
dev->stat &= ~8;
dev->status &= ~8;
}
if (dev->scanline == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->scanline == ((dev->crtc[11] & 31) >> 1))) {

View File

@@ -67,7 +67,7 @@ typedef struct {
uint8_t crtc[32];
int crtcreg;
uint8_t ctrl, ctrl2, stat;
uint8_t ctrl, ctrl2, status;
uint64_t dispontime, dispofftime;
pc_timer_t timer;
@@ -194,7 +194,7 @@ herculesplus_in(uint16_t port, void *priv)
case 0x3ba:
/* 0x10: Hercules Plus card identity */
ret = (dev->stat & 0xf) | ((dev->stat & 8) << 4) | 0x10;
ret = (dev->status & 0xf) | ((dev->status & 8) << 4) | 0x10;
break;
default:
@@ -494,7 +494,7 @@ herculesplus_poll(void *priv)
VIDEO_MONITOR_PROLOGUE();
if (!dev->linepos) {
timer_advance_u64(&dev->timer, dev->dispofftime);
dev->stat |= 1;
dev->status |= 1;
dev->linepos = 1;
scanline_old = dev->scanline;
if ((dev->crtc[8] & 3) == 3)
@@ -519,19 +519,19 @@ herculesplus_poll(void *priv)
}
dev->scanline = scanline_old;
if (dev->vc == dev->crtc[7] && !dev->scanline)
dev->stat |= 8;
dev->status |= 8;
dev->displine++;
if (dev->displine >= 500)
dev->displine = 0;
} else {
timer_advance_u64(&dev->timer, dev->dispontime);
if (dev->dispon)
dev->stat &= ~1;
dev->status &= ~1;
dev->linepos = 0;
if (dev->vsynctime) {
dev->vsynctime--;
if (!dev->vsynctime)
dev->stat &= ~8;
dev->status &= ~8;
}
if (dev->scanline == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->scanline == ((dev->crtc[11] & 31) >> 1))) {

View File

@@ -12,9 +12,11 @@
*
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Connor Hyde, <mario64crashed@gmail.com>
*
* Copyright 2008-2019 Sarah Walker.
* Copyright 2016-2025 Miran Grca.
* Copyright 2025 starfrost / Connor Hyde
*/
#include <stdio.h>
#include <stdint.h>
@@ -44,32 +46,35 @@ mda_out(uint16_t addr, uint8_t val, void *priv)
{
mda_t *mda = (mda_t *) priv;
switch (addr) {
case 0x3b0:
case 0x3b2:
case 0x3b4:
case 0x3b6:
mda->crtcreg = val & 31;
return;
case 0x3b1:
case 0x3b3:
case 0x3b5:
case 0x3b7:
mda->crtc[mda->crtcreg] = val;
if (mda->crtc[10] == 6 && mda->crtc[11] == 7) /*Fix for Generic Turbo XT BIOS, which sets up cursor registers wrong*/
{
mda->crtc[10] = 0xb;
mda->crtc[11] = 0xc;
}
mda_recalctimings(mda);
return;
case 0x3b8:
mda->ctrl = val;
return;
if (addr < MDA_REGISTER_START
|| addr > MDA_REGISTER_CRT_STATUS) // Maintain old behaviour for printer registers, just in case
return;
switch (addr)
{
case MDA_REGISTER_MODE_CONTROL:
mda->mode = val;
return;
default:
break;
}
// addr & 1 == 1 = MDA_REGISTER_CRTC_DATA
// otherwise MDA_REGISTER_CRTC_INDEX
if (addr & 1)
{
mda->crtc[mda->crtcreg] = val;
if (mda->crtc[MDA_CRTC_CURSOR_START] == 6
&& mda->crtc[MDA_CRTC_CURSOR_END] == 7) /*Fix for Generic Turbo XT BIOS, which sets up cursor registers wrong*/
{
mda->crtc[MDA_CRTC_CURSOR_START] = 0xb;
mda->crtc[MDA_CRTC_CURSOR_END] = 0xc;
}
mda_recalctimings(mda);
}
else
mda->crtcreg = val & 31;
}
uint8_t
@@ -77,24 +82,26 @@ mda_in(uint16_t addr, void *priv)
{
const mda_t *mda = (mda_t *) priv;
switch (addr) {
case 0x3b0:
case 0x3b2:
case 0x3b4:
case 0x3b6:
return mda->crtcreg;
case 0x3b1:
case 0x3b3:
case 0x3b5:
case 0x3b7:
return mda->crtc[mda->crtcreg];
case 0x3ba:
return mda->stat | 0xF0;
switch (addr)
{
case MDA_REGISTER_CRT_STATUS:
return mda->status | 0xF0;
default:
if (addr < MDA_REGISTER_START
|| addr > MDA_REGISTER_CRT_STATUS) // Maintain old behaviour for printer registers, just in case
return 0xFF;
// MDA_REGISTER_CRTC_DATA
if (addr & 1)
return mda->crtc[mda->crtcreg];
else
return mda->crtcreg;
break;
}
return 0xff;
return 0xFF;
}
void
@@ -118,8 +125,8 @@ mda_recalctimings(mda_t *mda)
double _dispontime;
double _dispofftime;
double disptime;
disptime = mda->crtc[0] + 1;
_dispontime = mda->crtc[1];
disptime = mda->crtc[MDA_CRTC_HTOTAL] + 1;
_dispontime = mda->crtc[MDA_CRTC_HDISP];
_dispofftime = disptime - _dispontime;
_dispontime *= MDACONST;
_dispofftime *= MDACONST;
@@ -131,7 +138,7 @@ void
mda_poll(void *priv)
{
mda_t *mda = (mda_t *) priv;
uint16_t cursoraddr = (mda->crtc[15] | (mda->crtc[14] << 8)) & 0x3fff;
uint16_t cursoraddr = (mda->crtc[MDA_CRTC_CURSOR_ADDR_LOW] | (mda->crtc[MDA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff;
int drawcursor;
int x;
int c;
@@ -144,10 +151,10 @@ mda_poll(void *priv)
VIDEO_MONITOR_PROLOGUE()
if (!mda->linepos) {
timer_advance_u64(&mda->timer, mda->dispofftime);
mda->stat |= 1;
mda->status |= 1;
mda->linepos = 1;
scanline_old = mda->scanline;
if ((mda->crtc[8] & 3) == 3)
if ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3)
mda->scanline = (mda->scanline << 1) & 7;
if (mda->dispon) {
if (mda->displine < mda->firstline) {
@@ -155,11 +162,11 @@ mda_poll(void *priv)
video_wait_for_buffer();
}
mda->lastline = mda->displine;
for (x = 0; x < mda->crtc[1]; x++) {
for (x = 0; x < mda->crtc[MDA_CRTC_HDISP]; x++) {
chr = mda->vram[(mda->memaddr << 1) & 0xfff];
attr = mda->vram[((mda->memaddr << 1) + 1) & 0xfff];
drawcursor = ((mda->memaddr == cursoraddr) && mda->cursorvisible && mda->cursoron);
blink = ((mda->blink & 16) && (mda->ctrl & 0x20) && (attr & 0x80) && !drawcursor);
blink = ((mda->blink & 16) && (mda->mode & MDA_MODE_BLINK) && (attr & 0x80) && !drawcursor);
if (mda->scanline == 12 && ((attr & 7) == 1)) {
for (c = 0; c < 9; c++)
buffer32->line[mda->displine][(x * 9) + c] = mdacols[attr][blink][1];
@@ -178,11 +185,11 @@ mda_poll(void *priv)
}
}
video_process_8(mda->crtc[1] * 9, mda->displine);
video_process_8(mda->crtc[MDA_CRTC_HDISP] * 9, mda->displine);
}
mda->scanline = scanline_old;
if (mda->vc == mda->crtc[7] && !mda->scanline) {
mda->stat |= 8;
if (mda->vc == mda->crtc[MDA_CRTC_VSYNC] && !mda->scanline) {
mda->status |= 8;
}
mda->displine++;
if (mda->displine >= 500)
@@ -190,15 +197,17 @@ mda_poll(void *priv)
} else {
timer_advance_u64(&mda->timer, mda->dispontime);
if (mda->dispon)
mda->stat &= ~1;
mda->status &= ~1;
mda->linepos = 0;
if (mda->vsynctime) {
mda->vsynctime--;
if (!mda->vsynctime) {
mda->stat &= ~8;
mda->status &= ~8;
}
}
if (mda->scanline == (mda->crtc[11] & 31) || ((mda->crtc[8] & 3) == 3 && mda->scanline == ((mda->crtc[11] & 31) >> 1))) {
if (mda->scanline == (mda->crtc[MDA_CRTC_CURSOR_END] & 31)
|| ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3
&& mda->scanline == ((mda->crtc[MDA_CRTC_CURSOR_END] & 31) >> 1))) {
mda->cursorvisible = 0;
}
if (mda->vadj) {
@@ -208,35 +217,37 @@ mda_poll(void *priv)
mda->vadj--;
if (!mda->vadj) {
mda->dispon = 1;
mda->memaddr = mda->memaddr_backup = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff;
mda->memaddr = mda->memaddr_backup = (mda->crtc[MDA_CRTC_START_ADDR_LOW] | (mda->crtc[MDA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff;
mda->scanline = 0;
}
} else if (mda->scanline == mda->crtc[9] || ((mda->crtc[8] & 3) == 3 && mda->scanline == (mda->crtc[9] >> 1))) {
} else if (mda->scanline == mda->crtc[MDA_CRTC_MAX_SCANLINE_ADDR]
|| ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3
&& mda->scanline == (mda->crtc[MDA_CRTC_MAX_SCANLINE_ADDR] >> 1))) {
mda->memaddr_backup = mda->memaddr;
mda->scanline = 0;
oldvc = mda->vc;
mda->vc++;
mda->vc &= 127;
if (mda->vc == mda->crtc[6])
if (mda->vc == mda->crtc[MDA_CRTC_VDISP])
mda->dispon = 0;
if (oldvc == mda->crtc[4]) {
if (oldvc == mda->crtc[MDA_CRTC_VTOTAL]) {
mda->vc = 0;
mda->vadj = mda->crtc[5];
mda->vadj = mda->crtc[MDA_CRTC_VTOTAL_ADJUST];
if (!mda->vadj)
mda->dispon = 1;
if (!mda->vadj)
mda->memaddr = mda->memaddr_backup = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff;
if ((mda->crtc[10] & 0x60) == 0x20)
mda->memaddr = mda->memaddr_backup = (mda->crtc[MDA_CRTC_START_ADDR_LOW] | (mda->crtc[MDA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff;
if ((mda->crtc[MDA_CRTC_CURSOR_START] & 0x60) == 0x20)
mda->cursoron = 0;
else
mda->cursoron = mda->blink & 16;
}
if (mda->vc == mda->crtc[7]) {
if (mda->vc == mda->crtc[MDA_CRTC_VSYNC]) {
mda->dispon = 0;
mda->displine = 0;
mda->vsynctime = 16;
if (mda->crtc[7]) {
x = mda->crtc[1] * 9;
if (mda->crtc[MDA_CRTC_VSYNC]) {
x = mda->crtc[MDA_CRTC_HDISP] * 9;
mda->lastline++;
if ((x != xsize) || ((mda->lastline - mda->firstline) != ysize) || video_force_resize_get()) {
xsize = x;
@@ -252,8 +263,8 @@ mda_poll(void *priv)
}
video_blit_memtoscreen(0, mda->firstline, xsize, ysize);
frames++;
video_res_x = mda->crtc[1];
video_res_y = mda->crtc[6];
video_res_x = mda->crtc[MDA_CRTC_HDISP];
video_res_y = mda->crtc[MDA_CRTC_VDISP];
video_bpp = 0;
}
mda->firstline = 1000;
@@ -265,7 +276,9 @@ mda_poll(void *priv)
mda->scanline &= 31;
mda->memaddr = mda->memaddr_backup;
}
if (mda->scanline == (mda->crtc[10] & 31) || ((mda->crtc[8] & 3) == 3 && mda->scanline == ((mda->crtc[10] & 31) >> 1))) {
if (mda->scanline == (mda->crtc[MDA_CRTC_CURSOR_START] & 31)
|| ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3
&& mda->scanline == ((mda->crtc[MDA_CRTC_CURSOR_START] & 31) >> 1))) {
mda->cursorvisible = 1;
}
}

View File

@@ -183,8 +183,8 @@ vid_in(uint16_t addr, void *priv)
case 0x3da:
pcjr->array_ff = 0;
pcjr->stat ^= 0x10;
ret = pcjr->stat;
pcjr->status ^= 0x10;
ret = pcjr->status;
break;
default:
@@ -316,7 +316,7 @@ vid_poll(void *priv)
if (!pcjr->linepos) {
timer_advance_u64(&pcjr->timer, pcjr->dispofftime);
pcjr->stat &= ~1;
pcjr->status &= ~1;
pcjr->linepos = 1;
scanline_old = pcjr->scanline;
if ((pcjr->crtc[8] & 3) == 3)
@@ -557,7 +557,7 @@ vid_poll(void *priv)
}
pcjr->scanline = scanline_old;
if (pcjr->vc == pcjr->crtc[7] && !pcjr->scanline) {
pcjr->stat |= 8;
pcjr->status |= 8;
}
pcjr->displine++;
if (pcjr->displine >= 360)
@@ -565,12 +565,12 @@ vid_poll(void *priv)
} else {
timer_advance_u64(&pcjr->timer, pcjr->dispontime);
if (pcjr->dispon)
pcjr->stat |= 1;
pcjr->status |= 1;
pcjr->linepos = 0;
if (pcjr->vsynctime) {
pcjr->vsynctime--;
if (!pcjr->vsynctime) {
pcjr->stat &= ~8;
pcjr->status &= ~8;
}
}
if (pcjr->scanline == (pcjr->crtc[11] & 31) || ((pcjr->crtc[8] & 3) == 3 && pcjr->scanline == ((pcjr->crtc[11] & 31) >> 1))) {

View File

@@ -268,7 +268,7 @@ tandy_vid_in(uint16_t addr, void *priv)
break;
case 0x03da:
ret = vid->stat;
ret = vid->status;
break;
case 0x3db:
@@ -353,7 +353,7 @@ vid_poll(void *priv)
if (!vid->linepos) {
timer_advance_u64(&vid->timer, vid->dispofftime);
vid->stat |= 1;
vid->status |= 1;
vid->linepos = 1;
scanline_old = vid->scanline;
if ((vid->crtc[8] & 3) == 3)
@@ -574,19 +574,19 @@ vid_poll(void *priv)
}
vid->scanline = scanline_old;
if (vid->vc == vid->crtc[7] && !vid->scanline)
vid->stat |= 8;
vid->status |= 8;
vid->displine++;
if (vid->displine >= 360)
vid->displine = 0;
} else {
timer_advance_u64(&vid->timer, vid->dispontime);
if (vid->dispon)
vid->stat &= ~1;
vid->status &= ~1;
vid->linepos = 0;
if (vid->vsynctime) {
vid->vsynctime--;
if (!vid->vsynctime)
vid->stat &= ~8;
vid->status &= ~8;
}
if (vid->scanline == (vid->crtc[11] & 31) || ((vid->crtc[8] & 3) == 3 && vid->scanline == ((vid->crtc[11] & 31) >> 1))) {
vid->cursorvisible = 0;