PS55DA2: add char drawing func in BitBlt

This build is still in work.

* Added character drawing function to support for DOS/V Extension DSPXDA2 driver.
* Implement CRTC regs: start address, end address, line compare to support line compare scrolling in DOS/V Extension.
* Enable updating CRTC regs when output is disabled.
This commit is contained in:
Akamaki
2025-04-03 15:16:58 +09:00
parent 94a928978e
commit fc06d3de89

View File

@@ -66,7 +66,7 @@
#define DA2_MASK_VRAM 0xfffff /* 0xFFFFF */
#define DA2_MASK_VRAMPLANE 0x1ffff /* 0x1FFFF */
#define DA2_PIXELCLOCK 29000000.0 /* 58 MHz interlaced */
#define DA2_BLT_MEMSIZE 0x100
#define DA2_BLT_MEMSIZE 0x1000
#define DA2_BLT_REGSIZE 0x40
#define DA2_DEBUG_BLTLOG_SIZE (DA2_BLT_REGSIZE + 1)
#define DA2_DEBUG_BLTLOG_MAX (256 * 1024)
@@ -112,8 +112,8 @@
EFD8h * Display Adapter/J [Atlas-SP2]
[Japanese DOS and Display Adapter compatibility]
| | | K3.31 | J4.04 | J4.08 | OS2J1.3 | Win3.02 | DOSVExt |
| POS ID | Adapter Name | 5605JBK | 5605PAA | 5605PCA | 5605PDE | 5605PAW | 5605PXA |
| | | 5605JBK | 5605PAA | 5605PCA | 5605PDE | 5605PAW | 5605PXB |
| POS ID | Adapter Name | K3.31 | J4.05 | J4.08 | J1.33 | 3.02 | 2.0 |
|------------|-----------------------------|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|
| EFFFh | Display Adapter | X | | | | | |
| FFEDh | ? [Atlas EVT] | X | | | | | |
@@ -124,7 +124,14 @@
| ECECh | Display Adapter IV,B1 | | X | X | X | X | X |
| 9000-901Fh | Display Adapter A1,A2 | | X | X | | X | X |
| EFD8h | Display Adapter /J | | | X | X | X | X |
*/
- 5605JBK : Japanese DOS K3.3, K3.4 (for PS/55 model 55xx-S, T, V, Z)
- 5605PAA : DOS J4.0
- 5605PCA : DOS J4.0 (with MKK)
- 5605PDE : OS/2 Extended Edition J1.3
- 5605PAW : Japanese Microsoft Windows 3.0 (IBMJ OEM)
- 5605PXB : DOS/V Extension V2.0
*/
/* IO 3E0/3E1:0Ah Hardware Configuration Value L (imported from OS/2 DDK) */
#define OldLSI 0x20 /* 1 = DA-2, 0 = DA-3 */
// #define Mon_ID3 0x10
@@ -163,8 +170,10 @@
#define LF_INDEX 0x3e2
#define LF_DATA 0x3e3
#define LF_MMIO_SEL 0x08 /* added */
#define LF_MMIO_09 0x09 /* added */
#define LF_MMIO_ADDR 0x0A /* added */
#define LF_MMIO_MODE 0x0B /* added */
#define LF_PD_RESET 0x18 /* added */
#define LC_INDEX 0x3E4
#define LC_DATA 0x3E5
#define LC_HORIZONTAL_TOTAL 0x00
@@ -251,12 +260,12 @@
#define LG_SET_RESET_2 0x10
#ifndef RELEASE_BUILD
// #define ENABLE_DA2_LOG 1
#define ENABLE_DA2_LOG 1
#endif
#ifdef ENABLE_DA2_LOG
// # define ENABLE_DA2_DEBUGIO 1
// # define ENABLE_DA2_DEBUGBLT 1
# define ENABLE_DA2_DEBUGBLT 1
// # define ENABLE_DA2_DEBUGVRAM 1
// # define ENABLE_DA2_DEBUGFULLSCREEN 1
// # define ENABLE_DA2_DEBUGMONWAIT 1
@@ -328,7 +337,7 @@ typedef struct da2_t {
int vtotal, dispend, vsyncstart, split, vblankstart;
int hdisp, htotal, hdisp_time, rowoffset;
int lowres, interlace;
int lowres;
int rowcount;
double clock;
uint32_t ma_latch, ca_adj;
@@ -343,7 +352,7 @@ typedef struct da2_t {
uint32_t ma, maback, ca;
int vc;
int sc;
int linepos, vslines, linecountff, oddeven;
int linepos, vslines, linecountff;
int con, cursoron, blink, blinkconf;
int scrollcache;
int char_width;
@@ -457,6 +466,53 @@ DA2_vram_w(uint32_t addr, uint8_t val, da2_t *da2)
da2->vram[addr] = val;
return;
}
/* get font data for bitblt operation */
static uint32_t
getFontIBMJ(int32_t code, int line, int x, void *p)
{
da2_t *da2 = (da2_t *) p;
uint32_t font = 0;
int fline = line - 2; /* Start line of drawing character (line >= 1 AND line < 24 + 1 ) */
if (code < 0x100) { /* SBCS 13x29 */
code *= 0x40;
code += DA2_GAIJIRAM_SBCS + (line * 2) + x;
font = da2->mmio.ram[code];
font <<= 8;
font |= da2->mmio.ram[code + 1];
font <<= 16;
return font;
}
if ((code >= 0x8000) && (code <= 0x8183))
code -= 0x6000; /* shift for IBM extended characters */
if ((code < (DA2_FONTROM_SIZE / 72)) && (fline >= 0) && (fline < 24)) { /* DBCS 24x24 */
code = (code * 72) + (fline * 3) + x;
// font = da2->mmio.font[code]; /* 0000 0000 0000 0000 0000 0000 1111 1111 */
// font <<= 8; /* 0000 0000 0000 0000 1111 1111 0000 0000 */
// font |= da2->mmio.font[code + 1] & 0xf0; /* 0000 0000 0000 0000 1111 1111 2222 0000 */
// font <<= 3; /* 0000 0000 0000 0111 1111 1222 2000 0000 */
// font |= da2->mmio.font[code + 1] & 0x0f; /* 0000 0000 0000 0111 1111 1222 2000 2222 */
// font <<= 8; /* 0000 0111 1111 1222 2000 2222 0000 0000 */
// font |= da2->mmio.font[code + 2]; /* 0000 0111 1111 1222 2000 2222 3333 3333 */
// font <<= 4; /* 0111 1111 1222 2000 2222 3333 3333 0000 */
} else if ((code >= 0xb000) && (code <= 0xb75f)) { /* DBCS 26x29 */
/* convert code->address in gaiji memory */
code -= 0xb000;
code = (code * 0x80) + (line * 4) + x;
font = da2->mmio.ram[code];
font <<= 8;
font |= da2->mmio.ram[code + 1];
font <<= 8;
font |= da2->mmio.ram[code + 2];
font <<= 8;
font |= da2->mmio.ram[code + 3];
// font <<= 16;
} else if (code > (DA2_FONTROM_SIZE / 72))
font = 0xffffffffu;
else
font = 0;
return font;
}
/* write pixel data with rop (Note: bitmask must be in big endian) */
static void
DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32 *srcpx, da2_t *da2)
@@ -482,6 +538,11 @@ DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32 *s
for (int i = 0; i < 8; i++) {
if (da2->bitblt.bitshift_destr > 0)
srcpx->p8[i] <<= 16 - da2->bitblt.bitshift_destr;
// #ifdef ENABLE_DA2_DEBUGBLT
// if (i == 0) {
// pclog("writeplane: src %08X mask %08X dest %08X\n", srcpx->p8[i], mask32.d, writepx[i]);
// }
// #endif
if (da2->bitblt.raster_op & 0x2010) /* NOT Src or NOT Pattern */
srcpx->p8[i] = ~srcpx->p8[i] & mask32.d;
if (da2->bitblt.raster_op & 0x20) /* Dest NOT */
@@ -560,24 +621,68 @@ DA2_CopyPlaneDataWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask,
DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2);
}
/* Reverse the bit order of attribute code IBGR to IRGB(used in Mode 3 and Cursor Color) */
static int8_t
IBGRtoIRGB(uint8_t attr)
{
attr = ((attr & 0x01) << 6) | ((attr & 0x02) << 4) | ((attr & 0x04) << 2) | ((attr & 0x08) << 4);
return attr >>= 4;
}
static void
DA2_PutcharWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, da2_t *da2)
DA2_PutcharWithBitmask(uint32_t codeIBMJ, int width, uint16_t attr, int line, uint32_t destaddr, uint16_t maskl, uint16_t maskr, da2_t *da2)
{
pixel32 srcpx;
if (srcaddr >= DA2_FONTROM_SIZE) {
da2_log("DA2 Putchar Addr Error %x\n", srcaddr);
return;
// if (codeIBMJ >= DA2_FONTROM_SIZE / 72) {
// da2_log("DA2 Putchar Addr Error %x\n", srcaddr);
// return;
// }
uint8_t color = (~attr >> 8) & 0x0f;
// color = IBGRtoIRGB(color);
uint8_t bg = (~attr >> 12) & 0x0f;
// bg = 0x00;
// bg = IBGRtoIRGB(bg);
uint32_t font = getFontIBMJ(codeIBMJ, line, 0, da2);
uint32_t fontinv;
if (width == 1) {
fontinv = ~font;
for (int i = 0; i < 8; i++) {
srcpx.p8[i] = (color & (1 << i)) ? font >> 16 : 0;
srcpx.p8[i] |= (bg & (1 << i)) ? fontinv >> 16 : 0;
}
pclog("putchar: %08X mask %04X %04X\n", srcpx.p8[0], maskl, maskr);
DA2_WritePlaneDataWithBitmask(destaddr, maskl, &srcpx, da2);
for (int i = 0; i < 8; i++) {
srcpx.p8[i] = (color & (1 << i)) ? font : 0;
srcpx.p8[i] |= (bg & (1 << i)) ? fontinv : 0;
}
pclog("putchar: %08X mask %04X %04X\n", srcpx.p8[0], maskl, maskr);
DA2_WritePlaneDataWithBitmask(destaddr + 2, maskr, &srcpx, da2);
} else {
font = (font & 0xfff80000) | ((font & 0x0000ffff) << 3);
fontinv = ~font;
pclog("putchar: ft %08X shftr %X\n", font, da2->bitblt.bitshift_destr);
for (int i = 0; i < 8; i++) {
srcpx.p8[i] = (color & (1 << i)) ? font >> 16 : 0;
srcpx.p8[i] |= (bg & (1 << i)) ? fontinv >> 16 : 0;
}
// pclog("putchar: %08X mask %04X\n", srcpx.p8[3], maskl);
DA2_WritePlaneDataWithBitmask(destaddr, maskl, &srcpx, da2);
for (int i = 0; i < 8; i++) {
srcpx.p8[i] = (color & (1 << i)) ? font : 0;
srcpx.p8[i] |= (bg & (1 << i)) ? fontinv : 0;
}
// pclog("putchar: %08X mask %04X\n", srcpx.p8[3], maskr);
DA2_WritePlaneDataWithBitmask(destaddr + 2, 0xffff, &srcpx, da2);
for (int i = 0; i < 8; i++) {
srcpx.p8[i] = (color & (1 << i)) ? font << 16 : 0;
srcpx.p8[i] |= (bg & (1 << i)) ? fontinv << 16 : 0;
}
// pclog("putchar: %08X mask %04X %04X\n", srcpx.p8[3], maskl, maskr);
DA2_WritePlaneDataWithBitmask(destaddr + 4, maskr, &srcpx, da2);
}
for (int i = 0; i < 8; i++)
srcpx.p8[i] = ((uint32_t) da2->mmio.font[srcaddr] << 24)
| ((uint32_t) da2->mmio.font[srcaddr + 1] << 16)
| ((uint32_t) da2->mmio.font[srcaddr + 2] << 8)
| ((uint32_t) da2->mmio.font[srcaddr + 3] << 0);
DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2);
}
#ifdef ENABLE_DA2_DEBUGBLT
uint8_t
static uint8_t
pixel1tohex(uint32_t addr, int index, da2_t *da2)
{
uint8_t pixeldata = 0;
@@ -587,14 +692,14 @@ pixel1tohex(uint32_t addr, int index, da2_t *da2)
}
return pixeldata;
}
void
static void
print_pixelbyte(uint32_t addr, da2_t *da2)
{
for (int i = 0; i < 8; i++) {
pclog("%X", pixel1tohex(addr, i, da2));
}
}
void
static void
print_bytetobin(uint8_t b)
{
for (int i = 0; i < 8; i++) {
@@ -606,17 +711,17 @@ print_bytetobin(uint8_t b)
}
}
/* Convert internal char code to Shift JIS code */
inline int
static int
isKanji1(uint8_t chr)
{
return (chr >= 0x81 && chr <= 0x9f) || (chr >= 0xe0 && chr <= 0xfc);
}
inline int
static int
isKanji2(uint8_t chr)
{
return (chr >= 0x40 && chr <= 0x7e) || (chr >= 0x80 && chr <= 0xfc);
}
uint16_t
static uint16_t
IBMJtoSJIS(uint16_t knj)
{
if (knj < 0x100)
@@ -710,6 +815,27 @@ da2_bitblt_load(da2_t *da2)
// da2->gdcreg[da2->bitblt.payload[i + 1]] = value64;
i += 7;
break;
case 0xa1:
value64 = da2->bitblt.payload[i + 9];
value64 <<= 8;
value64 |= da2->bitblt.payload[i + 8];
value64 <<= 8;
value64 |= da2->bitblt.payload[i + 7];
value64 <<= 8;
value64 |= da2->bitblt.payload[i + 6];
value64 <<= 8;
value64 |= da2->bitblt.payload[i + 5];
value64 <<= 8;
value64 |= da2->bitblt.payload[i + 4];
value64 <<= 8;
value64 |= da2->bitblt.payload[i + 3];
value64 <<= 8;
value64 |= da2->bitblt.payload[i + 2];
da2_bltlog("[%02x] %02x: %02x %02x %02x %02x %02x %02x %02x %02x\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3],
da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7], da2->bitblt.payload[i + 8], da2->bitblt.payload[i + 9]);
da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value64;
i += 9;
break;
case 0x00:
break;
default:
@@ -734,14 +860,15 @@ da2_bitblt_load(da2_t *da2)
da2->bitblt.debug_reg_ip = 0;
da2->bitblt.debug_exesteps = 0;
#endif
da2_log("bltload_exec: %x, rop: %x CS:PC=%4x:%4x\n", da2->bitblt.reg[0x5], da2->bitblt.reg[0x0b], CS, cpu_state.pc);
da2->bitblt.bitshift_destr = ((da2->bitblt.reg[0x3] >> 4) & 0x0f); /* set bit shift */
da2_log("bltload_exec: %x, rop: %x CS:PC=%4x:%4x\n", da2->bitblt.reg[0x5], da2->bitblt.reg[0xb], CS, cpu_state.pc);
da2->bitblt.bitshift_destr = ((da2->bitblt.reg[0x03] >> 4) & 0x0f); /* set bit shift */
da2->bitblt.raster_op = da2->bitblt.reg[0x0b];
da2->bitblt.destaddr = da2->bitblt.reg[0x29];
da2->bitblt.size_x = da2->bitblt.reg[0x33];
da2->bitblt.size_y = da2->bitblt.reg[0x35];
da2->bitblt.destpitch = da2->bitblt.reg[0x21];
da2->bitblt.srcpitch = da2->bitblt.reg[0x22];
/* 80h = 128d = 10000000b, 90h = 144d = 10010000b, B0h = 176d = 10110000 */
if (da2->bitblt.reg[0x2F] == 0x90) /* destaddr -= 2, length += 1; */
{
da2->bitblt.destaddr -= 2;
@@ -757,7 +884,7 @@ da2_bitblt_load(da2_t *da2)
da2->bitblt.exec = DA2_BLT_CDONE;
/* Put DBCS char used by OS/2 (i'm not sure what the condition is) */
if (da2->bitblt.reg[0x10] == 0xbc04) {
if (!(da2->bitblt.reg[0xb] & 0x08)) {
da2->bitblt.exec = DA2_BLT_CPUTCHAR;
/* Todo: addressing */
// if (da2->bitblt.reg[0x2F] == 0x90) /* destaddr -= 2, length += 1; */
@@ -767,29 +894,22 @@ da2_bitblt_load(da2_t *da2)
// da2->bitblt.destpitch += 2;
// da2->bitblt.srcpitch += 2;
// }
da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + 2;
da2->bitblt.fcolor = da2->bitblt.reg[0x1];
da2->bitblt.srcaddr = da2->bitblt.reg[0x12];
da2->bitblt.destaddr += 2;
da2->bitblt.srcpitch = 0;
da2->bitblt.bitshift_destr += 1;
#ifdef ENABLE_DA2_DEBUGBLT
uint32_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8;
uint32_t sjis_l = IBMJtoSJIS(da2->bitblt.reg[0x12]) & 0xff;
da2_log("put char src=%x, dest=%x, x=%d, y=%d, w=%d, h=%d, c=%c%c\n",
da2->bitblt.srcaddr, da2->bitblt.destaddr,
da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2),
da2->bitblt.size_x, da2->bitblt.size_y, sjis_h, sjis_l);
#endif
}
/* Put SBCS char used by OS/2 */
else if (da2->bitblt.reg[0x10] == 0x0004 || da2->bitblt.reg[0x10] == 0x0E04) {
da2->bitblt.exec = DA2_BLT_CPUTCHAR;
da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 64 + 2 + DA2_FONTROM_BASESBCS;
da2->bitblt.destaddr += 2;
da2->bitblt.srcpitch = 0;
da2->bitblt.bitshift_destr += 1;
#ifdef ENABLE_DA2_DEBUGBLT
uint32_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8;
uint32_t sjis_l = IBMJtoSJIS(da2->bitblt.reg[0x12]) & 0xff;
uint8_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8;
uint8_t sjis_l = IBMJtoSJIS(da2->bitblt.reg[0x12]) & 0xff;
if (da2->bitblt.reg[0x12] < 0x100) {
sjis_h = 0x20;
sjis_l = da2->bitblt.reg[0x12];
} else {
if (!(isKanji1(sjis_h)))
sjis_h = 0x3f;
if (!(isKanji2(sjis_l)))
sjis_l = 0x3f;
}
da2_log("put char src=%x, dest=%x, x=%d, y=%d, w=%d, h=%d, c=%c%c\n",
da2->bitblt.srcaddr, da2->bitblt.destaddr,
da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2),
@@ -1040,49 +1160,35 @@ da2_bitblt_exec(void *p)
da2->bitblt.srcaddr -= 2;
break;
case DA2_BLT_CPUTCHAR: /* used in OS/2 J1.3 wo ROM patch. TODO: still not work */
// da2->bitblt.y += 2;
da2->bitblt.destaddr = da2->bitblt.reg[0x29] + da2->bitblt.x * 2 + da2->bitblt.y * 130 + 0 + 260;
// pclog("scr %x dest %x :", da2->bitblt.srcaddr, da2->bitblt.destaddr);
da2->bitblt.destaddr = da2->bitblt.reg[0x29] + da2->bitblt.y * 130;
// da2->bitblt.srcaddr += 2;
if (da2->bitblt.reg[0x12] < 0x100)
da2->bitblt.srcaddr = DA2_FONTROM_BASESBCS + da2->bitblt.reg[0x12] * 64 + (da2->bitblt.x * 2) + (da2->bitblt.y * 2) - 2;
else
da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + (da2->bitblt.x * 2) + (da2->bitblt.y * 3) - 2;
// print_bytetobin(da2->mmio.font[da2->bitblt.srcaddr + 2]);
// print_bytetobin(da2->mmio.font[da2->bitblt.srcaddr + 3]);
// pclog("\n");
if (da2->bitblt.x >= da2->bitblt.size_x - 1) {
// if (1) {
DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2);
if (da2->bitblt.y >= da2->bitblt.size_y - 3) {
da2->bitblt.exec = DA2_BLT_CDONE;
}
da2->bitblt.x = 0;
// if (da2->bitblt.reg[0x12] < 0x100)
// da2->bitblt.srcaddr = DA2_FONTROM_BASESBCS + da2->bitblt.reg[0x12] * 64 + (da2->bitblt.x * 2) + (da2->bitblt.y * 2) - 2;
// else
// da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + (da2->bitblt.x * 2) + (da2->bitblt.y * 3) - 2;
da2->bitblt.srcaddr = da2->bitblt.reg[0x12];
da2->bitblt.size_x = da2->bitblt.reg[0x33];
pclog("scr %x dest %x x %x y %x\n", da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y);
if (da2->bitblt.y >= da2->bitblt.size_y) {
da2->bitblt.exec = DA2_BLT_CDONE;
} else {
DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.size_x, da2->bitblt.fcolor, da2->bitblt.y, da2->bitblt.destaddr, da2->bitblt.maskl, da2->bitblt.maskr, da2);
}
da2->bitblt.y++;
da2->bitblt.destaddr += 130;
// da2->bitblt.destaddr += da2->bitblt.destpitch + 2;
// da2->bitblt.srcaddr += -1;
} else if (da2->bitblt.x == 0) {
DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2);
da2->bitblt.x++;
// da2->bitblt.x++;
} else {
DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, 0xffff, da2);
da2->bitblt.x++;
// da2->bitblt.x++;
}
// }
// da2->bitblt.destaddr = da2->bitblt.reg[0x29] + da2->bitblt.x + da2->bitblt.y * 130 + 2;
////da2->bitblt.srcaddr += 2;
// da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + (da2->bitblt.x * 2 ) + (da2->bitblt.y * 3) + 2;
break;
case DA2_BLT_CDONE:
if (!(da2->bitblt.reg[0x20] & 0x20)) {
/* initialize regs and set magic value for debug dump */
for (int i = 0; i < DA2_BLT_REGSIZE; i++) {
if (da2->bitblt.reg[i] != DA2_DEBUG_BLT_NEVERUSED)
da2->bitblt.reg[i] = DA2_DEBUG_BLT_USEDRESET;
}
} else /* without init regs */
// if (!(da2->bitblt.reg[0x20] & 0x20)) {
// /* initialize regs and set magic value for debug dump */
// for (int i = 0; i < DA2_BLT_REGSIZE; i++) {
// if (da2->bitblt.reg[i] != DA2_DEBUG_BLT_NEVERUSED)
// da2->bitblt.reg[i] = DA2_DEBUG_BLT_USEDRESET;
// }
// } else /* without init regs */
da2->bitblt.reg[0x20] = 0; /* need to stop execution */
if (da2->bitblt.indata)
da2->bitblt.exec = DA2_BLT_CLOAD;
@@ -1193,6 +1299,10 @@ da2_out(uint16_t addr, uint16_t val, void *p)
da2->fctl[da2->fctladdr] = val;
if (da2->fctladdr == 0 && oldval != val) {
da2_iolog("DA2 Out FCTL addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->fctladdr, val, cs >> 4, cpu_state.pc);
} else if ((da2->fctladdr == LF_PD_RESET) && ((val & 0x7) == 7)) {
/* Reset Bitblt busy */
da2->bitblt.indata = 0;
da2->bitblt.exec = DA2_BLT_CIDLE;
}
break;
case LC_INDEX:
@@ -1214,10 +1324,12 @@ da2_out(uint16_t addr, uint16_t val, void *p)
val = 0;
break;
case LC_START_ADDRESS_HIGH:
// if (val == 0xff) /* adjust (need to confirm) */
// val = 0;
case LC_START_ADDRESS_LOW:
/* The DOS J4.0 MODE 4 command and OS/2 driver write 0xFF00.
OS/2 DOS MODE 1 setup reads this to set the base line, but it causes the screen glitch. */
val = 0;
// val = 0;
break;
case LC_VERTICAL_TOTALJ: /* Vertical Total */
case LC_VERTICAL_SYNC_START: /* Vertical Retrace Start Register */
@@ -1227,25 +1339,21 @@ da2_out(uint16_t addr, uint16_t val, void *p)
val = 0x400; /* for debugging bitblt in Win 3.x */
#endif
break;
case LC_VIEWPORT_SELECT: /* ViewPort Select? */
// return;
break;
case LC_VIEWPORT_NUMBER: /* Compatibility? */
break;
}
da2->crtc[da2->crtcaddr] = val;
switch (da2->crtcaddr) {
case LC_H_DISPLAY_ENABLE_END:
case LC_VERTICAL_TOTALJ:
case LC_MAXIMUM_SCAN_LINE:
// case LC_START_ADDRESS_HIGH:
// case LC_START_ADDRESS_LOW:
case LC_START_ADDRESS_HIGH:
case LC_START_ADDRESS_LOW:
case LC_VERTICAL_SYNC_START:
case LC_V_DISPLAY_ENABLE_END:
case LC_START_VERTICAL_BLANK:
case LC_START_H_DISPLAY_ENAB:
case LC_START_V_DISPLAY_ENAB:
case LC_VIEWPORT_PRIORITY:
case LC_LINE_COMPAREJ:
da2->fullchange = changeframecount;
da2_recalctimings(da2);
break;
@@ -1432,7 +1540,7 @@ da2_in(uint16_t addr, void *p)
// timer_advance_u64(&da2->bitblt.timer, da2->bitblt.timerspeed);
// }
}
if (da2->bitblt.indata) temp |= 0x08;
// if (da2->bitblt.indata) temp |= 0x08;
#ifdef ENABLE_DA2_DEBUGMONWAIT
da2_iolog("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr, temp, cs >> 4, cpu_state.pc);
#endif
@@ -1464,6 +1572,10 @@ da2_in(uint16_t addr, void *p)
da2->cgastat &= ~0x30;
else
da2->cgastat ^= 0x30; /* toggle */
if (da2->cgastat & 0x08)
da2->cgastat &= ~0x08;
else
da2->cgastat ^= 0x08; /* toggle */
temp = da2->cgastat;
} else
temp = da2->attrc[da2->attraddr];
@@ -1496,7 +1608,7 @@ static void
da2_outb(uint16_t addr, uint8_t val, void *p)
{
da2_t *da2 = (da2_t *) p;
// da2_iolog("DA2 Outb addr %03X val %02X %04X:%04X es:di=%x:%x ds:si=%x:%x\n", addr, val, cs >> 4, cpu_state.pc, ES, DI, DS, SI);
da2_iolog("DA2 Outb addr %03X val %02X %04X:%04X es:di=%x:%x ds:si=%x:%x\n", addr, val, cs >> 4, cpu_state.pc, ES, DI, DS, SI);
da2->inflipflop = 0;
switch (addr) {
case LS_DATA:
@@ -2195,17 +2307,18 @@ da2_recalctimings(da2_t *da2)
double crtcconst;
double _dispontime, _dispofftime, disptime;
/* if output disabled or VGA passthrough */
if (da2->ioctl[LS_MODE] & 0x02 || !(da2->attrc[LV_COMPATIBILITY] & 0x08)) {
da2->render = da2_render_blank;
return;
}
// /* if output disabled or VGA passthrough */
// if (da2->ioctl[LS_MODE] & 0x02 || !(da2->attrc[LV_COMPATIBILITY] & 0x08)) {
// da2->render = da2_render_blank;
// return;
// }
da2->vtotal = da2->crtc[LC_VERTICAL_TOTALJ] & 0xfff;
da2->dispend = da2->crtc[LC_V_DISPLAY_ENABLE_END] & 0xfff;
da2->vsyncstart = da2->crtc[LC_VERTICAL_SYNC_START] & 0xfff;
da2->split = da2->crtc[LC_LINE_COMPAREJ] & 0xfff;
da2->split = 0xfff;
da2->split -= 1;
// da2->split = 0xfff;
da2->vblankstart = da2->crtc[LC_START_VERTICAL_BLANK] & 0xfff;
da2->hdisp = da2->crtc[LC_H_DISPLAY_ENABLE_END];
@@ -2225,17 +2338,23 @@ da2_recalctimings(da2_t *da2)
// da2->interlace = 0;
// da2->ma_latch = ((da2->crtc[LC_START_ADDRESS_HIGH] & 0x3ff) << 8) | da2->crtc[LC_START_ADDRESS_LOW];//w + b
if (da2->crtc[LC_VIEWPORT_SELECT] & 0x80 || da2->split == 0)
da2->ma_latch = 0;
else
da2->ma_latch = ((da2->crtc[LC_START_ADDRESS_HIGH] & 0x3ff) << 8) | da2->crtc[LC_START_ADDRESS_LOW]; // w + b
da2->ca_adj = 0;
da2->rowcount = da2->crtc[LC_MAXIMUM_SCAN_LINE];
da2->hdisp_time = da2->hdisp;
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 */
if (!(da2->ioctl[LS_MODE] & 0x01)) {
} else if (!(da2->ioctl[LS_MODE] & 0x01)) {
da2->hdisp *= 16;
da2->char_width = 13;
if (da2->crtc[LC_VIEWPORT_PRIORITY] & 0x80) {
@@ -2294,7 +2413,7 @@ da2_recalctimings(da2_t *da2)
da2_log("da2 horiz total %i display end %i vidclock %f\n", da2->crtc[0], da2->crtc[1], da2->clock);
da2_log("da2 vert total %i display end %i max row %i vsync %i\n",da2->vtotal,da2->dispend,(da2->crtc[9]&31)+1,da2->vsyncstart);
da2_log("da2 dispon %lu dispoff %lu on(us) %f off(us) %f\n",da2->dispontime, da2->dispofftime, (double)da2->dispontime / (double)cpuclock / (double) (1ULL << 32) * 1000000.0, (double)da2->dispofftime / (double)cpuclock / (double) (1ULL << 32) * 1000000.0);
// da2_log("da2->render %08X\n", da2->render);
da2_log("da2 linecompare %d\n", da2->split);
}
static void
@@ -2452,7 +2571,7 @@ da2_mmio_read(uint32_t addr, void *p)
uint32_t index = da2->fctl[LF_MMIO_MODE] & 0x0f;
index <<= 8;
index |= da2->fctl[LF_MMIO_ADDR];
addr += index * 0x40;
addr += index * 0x80;
}
// da2_log("PS55_MemHnd: Read from mem %x, bank %x, addr %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr);
switch (da2->fctl[LF_MMIO_MODE] & 0xf0) {
@@ -2475,6 +2594,7 @@ da2_mmio_read(uint32_t addr, void *p)
return da2->mmio.font[addr];
break;
default:
da2_log("PS55_MemHnd: Invalid read mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 72, addr, da2->mmio.font[addr]);
return DA2_INVALIDACCESS8; /* invalid memory access */
break;
}
@@ -2549,35 +2669,56 @@ da2_mmio_readw(uint32_t addr, void *p)
return (uint16_t) da2_mmio_read(addr, da2) | (uint16_t) (da2_mmio_read(addr + 1, da2) << 8);
}
}
static void
da2_bitblt_addpayload(uint8_t val, void *p)
{
da2_t *da2 = (da2_t *) p;
da2->bitblt.indata = 1;
if (da2->bitblt.payload_addr >= DA2_BLT_MEMSIZE)
da2_log("da2_mmio_write payload overflow! addr %x, val %x\n", da2->bitblt.payload_addr, val);
else {
da2->bitblt.payload[da2->bitblt.payload_addr] = val;
da2->bitblt.payload_addr++;
}
}
static void
da2_mmio_write(uint32_t addr, uint8_t val, void *p)
{
da2_t *da2 = (da2_t *) p;
uint32_t index = 0;
// da2_log("da2_mmio_write %x %x\n", addr, val);
// if ((addr & ~DA2_MASK_MMIO) != 0xA0000)
// return;
addr &= DA2_MASK_MMIO;
if (da2->ioctl[LS_MMIO] & 0x10) {
if (da2->ioctl[LS_MMIO] == 0x1f) {/* write bitblt fifo data */
da2_bitblt_addpayload(val, da2);
}
else if (da2->ioctl[LS_MMIO] & 0x10) { /* access to gaiji ram */
// if(da2->ioctl[LS_MMIO] == 0x1f) da2_log("mw mem %x, addr %x, val %x, ESDI %x:%x DSSI %x:%x\n", da2->fctl[LF_MMIO_MODE], addr, val, ES, DI, DS, SI);
/* Gaiji RAM */
if (da2->fctl[LF_MMIO_SEL] == 0x80)
addr |= ((uint32_t) da2->fctl[LF_MMIO_ADDR] << 17); /* xxxy yyyy yyyy yyyy yyyy */
else {
uint32_t index = da2->fctl[LF_MMIO_MODE] & 0x0f;
else {
index = da2->fctl[LF_MMIO_MODE] & 0x0f;
index <<= 8;
index |= da2->fctl[LF_MMIO_ADDR];
addr += index * 0x40;
// addr += index * 0x40;
// addr += index * 0x80;
// da2_log("da2_mmio_w io %x, sl %x, 09 %x, ad %x, mm %x, addr %x, val %x\n", da2->ioctl[LS_MMIO],da2->fctl[LF_MMIO_SEL],
// da2->fctl[LF_MMIO_09],da2->fctl[LF_MMIO_ADDR], da2->fctl[LF_MMIO_MODE], addr, val);
}
switch (da2->fctl[LF_MMIO_MODE]) {
case 0xb0: /* Gaiji RAM 1011 0000 */
switch (da2->fctl[LF_MMIO_MODE] & 0xf0) {
case 0xb0: /* Gaiji RAM 1011 0000 */
addr += index * 0x80;
da2->mmio.ram[addr & DA2_MASK_GAIJIRAM] = val;
break;
case 0x10: /* Font ROM 0001 0000 */
/* Read-Only */
break;
case 0x00:
case 0x00: /* SBCS in Gaiji RAM (used by DOS/V Extension DSPXDA2 driver) */
addr += index * 0x40;
da2->mmio.ram[(DA2_GAIJIRAM_SBCS + addr) & DA2_MASK_GAIJIRAM] = val;
// da2_log("da2_mmio_write %x %x %04X:%04X\n", addr, val, CS, cpu_state.pc);
// addr &= 0x7f;/* OS/2 write addr 1cf80-1cfc3, val xx */
// if (addr >= DA2_BLT_MEMSIZE)
@@ -2585,16 +2726,9 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p)
// da2_log("da2_mmio_write failed mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val);
// return;
// }
da2->bitblt.indata = 1;
if (da2->bitblt.payload_addr >= DA2_BLT_MEMSIZE)
da2_log("da2_mmio_write payload overflow! mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val);
else {
da2->bitblt.payload[da2->bitblt.payload_addr] = val;
da2->bitblt.payload_addr++;
}
break;
default:
da2_log("da2_mmio_write failed mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val);
da2_log("da2_mmio_write failed io %x, mm %x, addr %x, val %x\n", da2->ioctl[LS_MMIO] ,da2->fctl[LF_MMIO_MODE], addr, val);
break;
}
} else if (!(da2->ioctl[LS_MODE] & 1)) { /* 16 color or 256 color mode */
@@ -2802,15 +2936,21 @@ da2_mmio_writew(uint32_t addr, uint16_t val, void *p)
// return;
// if ((addr & ~0x1ffff) != 0xA0000) return;
if (da2->ioctl[LS_MMIO] & 0x10) {
// da2_log("da2_mmio_writeW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val);
#ifdef ENABLE_DA2_DEBUGVRAM
da2_log("da2_mmio_writeW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val);
#endif
da2_mmio_write(addr, val & 0xff, da2);
da2_mmio_write(addr + 1, val >> 8, da2);
} else if (!(da2->ioctl[LS_MODE] & 1)) { /* 16 color or 256 color mode */
// da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val);
#ifdef ENABLE_DA2_DEBUGVRAM
da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val);
#endif
da2_mmio_gc_writeW(addr, val, da2);
} else { /* mode 3h text */
#ifdef ENABLE_DA2_DEBUGVRAM
// if (addr & 0xff00 == 0) da2_log("da2_mmio_write %x %x %04X:%04X\n", addr, val, CS, cpu_state.pc);
// da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val);
da2_log("da2_mmio_write3W %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val);
#endif
da2_mmio_write(addr, val & 0xff, da2);
da2_mmio_write(addr + 1, val >> 8, da2);
}
@@ -2836,7 +2976,7 @@ da2_code_writeb(uint32_t addr, uint8_t val, void *p)
static void
da2_code_writew(uint32_t addr, uint16_t val, void *p)
{
// da2_log("DA2_code_writew: Write to %x, val %x\n", addr, val);
// da2_log("DA2_code_writ ew: Write to %x, val %x\n", addr, val);
da2_t *da2 = (da2_t *) p;
cycles -= video_timing_write_w;
da2_code_write(addr, val & 0xff, da2);
@@ -2945,8 +3085,6 @@ da2_poll(void *priv)
da2->sc = 0;
da2->maback += (da2->rowoffset << 1); /* color = 0x50(80), mono = 0x40(64) */
if (da2->interlace)
da2->maback += (da2->rowoffset << 1);
da2->maback &= da2->vram_display_mask;
da2->ma = da2->maback;
} else {
@@ -2959,6 +3097,13 @@ da2_poll(void *priv)
da2->vc++;
da2->vc &= 2047;
if (da2->vc == da2->split) {
// da2->ma = da2->maback = da2->hblank_sub;
da2->ma = da2->maback = 0;
da2->sc = 0;
// da2->displine = 0;
}
if (da2->vc == da2->dispend) {
da2->dispon = 0;
// if (da2->crtc[10] & 0x20) da2->cursoron = 0;
@@ -3002,13 +3147,11 @@ da2_poll(void *priv)
da2->firstline_draw = 2000;
da2->lastline_draw = 0;
da2->oddeven ^= 1;
changeframecount = da2->interlace ? 3 : 2;
changeframecount = 2;
da2->vslines = 0;
da2->ma
= da2->maback = da2->ma_latch;
= da2->maback = da2->ma_latch << 1;
da2->ca = ((da2->crtc[LC_CURSOR_LOC_HIGH] << 8) | da2->crtc[LC_CURSOR_LOC_LOWJ]) + da2->ca_adj;
da2->ca <<= 1;
@@ -3020,7 +3163,7 @@ da2_poll(void *priv)
da2->vc = 0;
da2->sc = da2->crtc[LC_PRESET_ROW_SCANJ] & 0x1f;
da2->dispon = 1;
da2->displine = (da2->interlace && da2->oddeven) ? 1 : 0;
da2->displine = 0;
da2->scrollcache = da2->attrc[LV_PANNING] & 7;
}
if (da2->sc == (da2->crtc[LC_CURSOR_ROW_START] & 31))
@@ -3111,7 +3254,6 @@ da2_reset(void *priv)
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->ma_latch = 0;
da2->interlace = 0;
da2->attrc[LV_CURSOR_CONTROL] = 0x13; /* cursor options */
da2->attr_palette_enable = 0; /* disable attribute generator */
@@ -3245,6 +3387,12 @@ da2_close(void *p)
fprintf(f, "3ee(?) %02X: %4X\n", i, da2->reg3ee[i]);
fclose(f);
}
f = fopen("ram_low.dmp", "wb");
if (f != NULL) {
fwrite(&ram[0x0], 0x100000, 1, f);
fclose(f);
}
pclog("closed %04X:%04X DS %04X\n", cs >> 4, cpu_state.pc, DS);
#endif
#ifdef ENABLE_DA2_DEBUGBLT
f = fopen("da2_bltdump.csv", "w");
@@ -3262,8 +3410,16 @@ da2_close(void *p)
;
else if (da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y] == DA2_DEBUG_BLT_USEDRESET)
fprintf(f, "\"\"\t");
else
else {
fprintf(f, "\"%X\"\t", da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y]);
if (y == 0x12) {
int chr = da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + 0x12];
if ((chr >= 0x20) && (chr < 0x7f))
fprintf(f, "\"%c\"\t", chr);
else
fprintf(f, "\"\"\t");
}
}
}
fprintf(f, "\n");
}