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