More Hercules fixes.
This commit is contained in:
@@ -36,7 +36,7 @@
|
||||
typedef struct {
|
||||
mem_mapping_t mapping;
|
||||
|
||||
uint8_t crtc[32];
|
||||
uint8_t crtc[32], charbuffer[4096];
|
||||
int crtcreg;
|
||||
|
||||
uint8_t ctrl,
|
||||
@@ -125,27 +125,31 @@ hercules_out(uint16_t addr, uint8_t val, void *priv)
|
||||
dev->crtc[10] = 0xb;
|
||||
dev->crtc[11] = 0xc;
|
||||
}
|
||||
#if 0
|
||||
if (old ^ val)
|
||||
recalc_timings(dev);
|
||||
#else
|
||||
|
||||
if (old != val) {
|
||||
if ((dev->crtcreg < 0xe) || (dev->crtcreg > 0x10)) {
|
||||
fullchange = changeframecount;
|
||||
recalc_timings(dev);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0x03b8:
|
||||
old = dev->ctrl;
|
||||
/* Prevent settings of bits if they are disabled in CTRL2. */
|
||||
if (!(dev->ctrl2 & 0x01) && (val & 0x02))
|
||||
val &= 0xfd;
|
||||
if (!(dev->ctrl2 & 0x02) && (val & 0x80))
|
||||
val &= 0x7f;
|
||||
dev->ctrl = val;
|
||||
|
||||
/* Prevent setting of bits if they are disabled in CTRL2. */
|
||||
if ((old & 0x02) && !(val & 0x02))
|
||||
dev->ctrl &= 0xfd;
|
||||
else if ((val & 0x02) && (dev->ctrl2 & 0x01))
|
||||
dev->ctrl |= 0x02;
|
||||
|
||||
if ((old & 0x80) && !(val & 0x80))
|
||||
dev->ctrl &= 0x7f;
|
||||
else if ((val & 0x80) && (dev->ctrl2 & 0x02))
|
||||
dev->ctrl |= 0x80;
|
||||
|
||||
dev->ctrl = (dev->ctrl & 0x82) | (val & 0x7d);
|
||||
|
||||
if (old ^ val)
|
||||
recalc_timings(dev);
|
||||
break;
|
||||
@@ -158,6 +162,19 @@ hercules_out(uint16_t addr, uint8_t val, void *priv)
|
||||
case 0x03bf:
|
||||
old = dev->ctrl2;
|
||||
dev->ctrl2 = val;
|
||||
/* According to the Programmer's guide to the Hercules graphics cars
|
||||
by David B. Doty from 1988, the CTRL2 modes (bits 1,0) are as follow:
|
||||
- 00: DIAG: Text mode only, only page 0 accessible;
|
||||
- 01: HALF: Graphics mode allowed, only page 0 accessible;
|
||||
- 11: FULL: Graphics mode allowed, both pages accessible. */
|
||||
if (val & 0x01)
|
||||
mem_mapping_set_exec(&dev->mapping, dev->vram);
|
||||
else
|
||||
mem_mapping_set_exec(&dev->mapping, NULL);
|
||||
if (val & 0x02)
|
||||
mem_mapping_set_addr(&dev->mapping, 0xb0000, 0x10000);
|
||||
else
|
||||
mem_mapping_set_addr(&dev->mapping, 0xb0000, 0x08000);
|
||||
if (old ^ val)
|
||||
recalc_timings(dev);
|
||||
break;
|
||||
@@ -187,21 +204,18 @@ hercules_in(uint16_t addr, void *priv)
|
||||
case 0x03b5:
|
||||
case 0x03b7:
|
||||
ret = dev->crtc[dev->crtcreg];
|
||||
if (dev->crtcreg == 12)
|
||||
ret = (dev->ma >> 8) & 0x3f;
|
||||
else
|
||||
ret = dev->ma & 0xff;
|
||||
break;
|
||||
|
||||
case 0x03ba:
|
||||
// ret = 0x72; /* Hercules ident */
|
||||
ret = 0x70; /* Hercules ident */
|
||||
ret |= (dev->lp_ff ? 2 : 0);
|
||||
#if 0
|
||||
if (dev->stat & 0x08)
|
||||
ret |= 0x88;
|
||||
#else
|
||||
ret |= (dev->stat & 0x01);
|
||||
if (dev->stat & 0x08)
|
||||
ret |= 0x80;
|
||||
#endif
|
||||
if ((dev->stat & 0x09) == 0x01)
|
||||
ret |= (dev->stat & 0x01);
|
||||
if ((ret & 0x81) == 0x80)
|
||||
ret |= 0x08;
|
||||
break;
|
||||
@@ -230,15 +244,12 @@ hercules_write(uint32_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
hercules_t *dev = (hercules_t *)priv;
|
||||
|
||||
/* According to the Programmer's guide to the Hercules graphics cars
|
||||
by David B. Doty from 1988, the CTRL2 modes (bits 1,0) are as follow:
|
||||
- 00: DIAG: Text mode only, only page 0 accessible;
|
||||
- 01: HALF: Graphics mode allowed, only page 0 accessible;
|
||||
- 11: FULL: Graphics mode allowed, both pages accessible. */
|
||||
if ((addr >= 0xb8000) && ((dev->ctrl2 & 0x03) != 0x03))
|
||||
return;
|
||||
if (dev->ctrl2 & 0x01)
|
||||
addr &= 0xffff;
|
||||
else
|
||||
addr &= 0x0fff;
|
||||
|
||||
dev->vram[addr & 0xffff] = val;
|
||||
dev->vram[addr] = val;
|
||||
|
||||
hercules_waitstates(dev);
|
||||
}
|
||||
@@ -248,13 +259,18 @@ static uint8_t
|
||||
hercules_read(uint32_t addr, void *priv)
|
||||
{
|
||||
hercules_t *dev = (hercules_t *)priv;
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
if ((addr >= 0xb8000) && ((dev->ctrl2 & 0x03) != 0x03))
|
||||
return 0xff;
|
||||
|
||||
return(dev->vram[addr & 0xffff]);
|
||||
if (dev->ctrl2 & 0x01)
|
||||
addr &= 0xffff;
|
||||
else
|
||||
addr &= 0x0fff;
|
||||
|
||||
hercules_waitstates(dev);
|
||||
|
||||
ret = dev->vram[addr];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -282,14 +298,14 @@ hercules_poll(void *priv)
|
||||
|
||||
if (dev->dispon) {
|
||||
if (dev->displine < dev->firstline) {
|
||||
dev->firstline = dev->displine;
|
||||
video_wait_for_buffer();
|
||||
dev->firstline = dev->displine;
|
||||
video_wait_for_buffer();
|
||||
}
|
||||
dev->lastline = dev->displine;
|
||||
|
||||
if ((dev->ctrl & 0x02) && (dev->ctrl2 & 0x01)) {
|
||||
if (dev->ctrl & 0x02) {
|
||||
ca = (dev->sc & 3) * 0x2000;
|
||||
if ((dev->ctrl & 0x80) && (dev->ctrl2 & 0x02))
|
||||
if (dev->ctrl & 0x80)
|
||||
ca += 0x8000;
|
||||
|
||||
for (x = 0; x < dev->crtc[1]; x++) {
|
||||
@@ -304,13 +320,12 @@ hercules_poll(void *priv)
|
||||
video_blend((x << 4) + c, dev->displine);
|
||||
}
|
||||
} else {
|
||||
pa = ((dev->ctrl & 0x80) && (dev->ctrl2 & 0x02)) ? 0x8000 : 0x0000;
|
||||
for (x = 0; x < dev->crtc[1]; x++) {
|
||||
if (dev->ctrl & 8) {
|
||||
/* Undocumented behavior: page 1 in text mode means characters are read
|
||||
from page 1 and attributes from page 0. */
|
||||
chr = dev->vram[((dev->ma << 1) & 0xfff) + pa];
|
||||
attr = dev->vram[((dev->ma << 1) + 1) & 0xfff];
|
||||
chr = dev->charbuffer[x << 1];
|
||||
attr = dev->charbuffer[(x << 1) + 1];
|
||||
} else
|
||||
chr = attr = 0;
|
||||
drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron);
|
||||
@@ -328,7 +343,10 @@ hercules_poll(void *priv)
|
||||
else
|
||||
buffer32->line[dev->displine][(x * 9) + 8] = dev->cols[attr][blink][0];
|
||||
}
|
||||
dev->ma++;
|
||||
if (dev->ctrl2 & 0x01)
|
||||
dev->ma = (dev->ma + 1) & 0x3fff;
|
||||
else
|
||||
dev->ma = (dev->ma + 1) & 0x7ff;
|
||||
|
||||
if (drawcursor) {
|
||||
for (c = 0; c < 9; c++)
|
||||
@@ -347,6 +365,9 @@ hercules_poll(void *priv)
|
||||
} else {
|
||||
timer_advance_u64(&dev->timer, dev->dispontime);
|
||||
|
||||
if (dev->dispon)
|
||||
dev->stat &= ~1;
|
||||
|
||||
dev->linepos = 0;
|
||||
if (dev->vsynctime) {
|
||||
dev->vsynctime--;
|
||||
@@ -364,42 +385,51 @@ hercules_poll(void *priv)
|
||||
dev->sc++;
|
||||
dev->sc &= 31;
|
||||
dev->ma = dev->maback;
|
||||
|
||||
dev->vadj--;
|
||||
if (! dev->vadj) {
|
||||
dev->dispon = 1;
|
||||
dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff;
|
||||
dev->sc = 0;
|
||||
}
|
||||
} else if (dev->sc == dev->crtc[9] || ((dev->crtc[8] & 3) == 3 && dev->sc == (dev->crtc[9] >> 1))) {
|
||||
} else if (((dev->crtc[8] & 3) != 3 && dev->sc == dev->crtc[9]) || ((dev->crtc[8] & 3) == 3 && dev->sc == (dev->crtc[9] >> 1))) {
|
||||
dev->maback = dev->ma;
|
||||
dev->sc = 0;
|
||||
oldvc = dev->vc;
|
||||
dev->vc++;
|
||||
dev->vc &= 127;
|
||||
|
||||
if (dev->vc == dev->crtc[6])
|
||||
dev->dispon = 0;
|
||||
|
||||
if (oldvc == dev->crtc[4]) {
|
||||
dev->vc = 0;
|
||||
dev->vadj = dev->crtc[5];
|
||||
if (! dev->vadj)
|
||||
if (! dev->vadj) {
|
||||
dev->dispon = 1;
|
||||
if (! dev->vadj)
|
||||
dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff;
|
||||
if ((dev->crtc[10] & 0x60) == 0x20)
|
||||
dev->cursoron = 0;
|
||||
else
|
||||
dev->cursoron = dev->blink & 16;
|
||||
}
|
||||
switch (dev->crtc[10] & 0x60) {
|
||||
case 0x20:
|
||||
dev->cursoron = 0;
|
||||
break;
|
||||
case 0x60:
|
||||
dev->cursoron = dev->blink & 0x10;
|
||||
break;
|
||||
default:
|
||||
dev->cursoron = dev->blink & 0x08;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (dev->vc == dev->crtc[7]) {
|
||||
dev->dispon = 0;
|
||||
dev->displine = 0;
|
||||
dev->vsynctime = 16;//(crtcm[3]>>4)+1;
|
||||
if ((dev->crtc[8] & 3) == 3)
|
||||
dev->vsynctime = ((int32_t)dev->crtc[4] * ((dev->crtc[9] >> 1) + 1)) + dev->crtc[5] - dev->crtc[7] + 1;
|
||||
else
|
||||
dev->vsynctime = ((int32_t)dev->crtc[4] * (dev->crtc[9] + 1)) + dev->crtc[5] - dev->crtc[7] + 1;
|
||||
if (dev->crtc[7]) {
|
||||
// if ((dev->ctrl & 2) && (dev->ctrl2 & 1))
|
||||
if (dev->ctrl & 2)
|
||||
if (dev->ctrl & 0x02)
|
||||
x = dev->crtc[1] << 4;
|
||||
else
|
||||
x = dev->crtc[1] * 9;
|
||||
@@ -419,7 +449,8 @@ hercules_poll(void *priv)
|
||||
|
||||
video_blit_memtoscreen_8(0, dev->firstline, 0, ysize, xsize, ysize);
|
||||
frames++;
|
||||
if ((dev->ctrl & 2) && (dev->ctrl2 & 1)) {
|
||||
// if ((dev->ctrl & 2) && (dev->ctrl2 & 1)) {
|
||||
if (dev->ctrl & 0x02) {
|
||||
video_res_x = dev->crtc[1] * 16;
|
||||
video_res_y = dev->crtc[6] * 4;
|
||||
video_bpp = 1;
|
||||
@@ -439,12 +470,15 @@ hercules_poll(void *priv)
|
||||
dev->ma = dev->maback;
|
||||
}
|
||||
|
||||
if (dev->dispon)
|
||||
dev->stat &= ~1;
|
||||
|
||||
if ((dev->sc == (dev->crtc[10] & 31) ||
|
||||
((dev->crtc[8] & 3)==3 && dev->sc == ((dev->crtc[10] & 31) >> 1))))
|
||||
dev->con = 1;
|
||||
if (dev->dispon && !(dev->ctrl & 0x02)) {
|
||||
for (x = 0; x < (dev->crtc[1] << 1); x++) {
|
||||
pa = (dev->ctrl & 0x80) ? ((x & 1) ? 0x0000 : 0x8000) : 0x0000;
|
||||
dev->charbuffer[x] = dev->vram[(((dev->ma << 1) + x) & 0x3fff) + pa];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -462,9 +496,9 @@ hercules_init(const device_t *info)
|
||||
|
||||
timer_add(&dev->timer, hercules_poll, dev, 1);
|
||||
|
||||
mem_mapping_add(&dev->mapping, 0xb0000, 0x10000,
|
||||
mem_mapping_add(&dev->mapping, 0xb0000, 0x08000,
|
||||
hercules_read,NULL,NULL, hercules_write,NULL,NULL,
|
||||
dev->vram, MEM_MAPPING_EXTERNAL, dev);
|
||||
NULL /*dev->vram*/, MEM_MAPPING_EXTERNAL, dev);
|
||||
|
||||
io_sethandler(0x03b0, 16,
|
||||
hercules_in,NULL,NULL, hercules_out,NULL,NULL, dev);
|
||||
|
Reference in New Issue
Block a user