Merge pull request #266 from MoochMcGee/master

Many RIVA 128 fixes
This commit is contained in:
OBattler
2018-02-26 22:16:22 +01:00
committed by GitHub

View File

@@ -207,6 +207,8 @@ typedef struct riva128_t
uint32_t dma_intr, dma_intr_en;
uint32_t status;
struct
{
uint32_t point_color;
@@ -238,14 +240,17 @@ typedef struct riva128_t
{
int scl;
int sda;
int busy;
enum
{
I2C_START, I2C_STOP, I2C_WAITACK, I2C_READ, I2C_WRITE
} state;
unsigned addrbits;
unsigned databits;
uint8_t addr; //actually 7 bits
uint8_t data;
struct
{
uint8_t addr;
uint8_t addr; //actually 7 bits
uint8_t edid_rom[128];
} edid_rom;
} i2c;
@@ -1267,6 +1272,21 @@ void rivatnt_pgraph_ctx_switch(void *p)
ret = riva128->pgraph.fifo_enable & 1;
break;
case 0x4006b0:
ret = riva128->pgraph.status & 0xff;
break;
case 0x4006b1:
ret = (riva128->pgraph.status >> 8) & 0xff;
break;
case 0x4006b2:
ret = (riva128->pgraph.status >> 16) & 0xff;
break;
case 0x4006b3:
ret = (riva128->pgraph.status >> 24) & 0xff;
//HACK
riva128->pgraph.status ^= 0x1f131111;
break;
case 0x401100:
ret = riva128->pgraph.dma_intr & 0xff;
break;
@@ -1808,14 +1828,13 @@ void riva128_pgraph_vblank_interrupt(void *p)
{
riva128_t *riva128 = (riva128_t *)p;
uint32_t ramht_base = riva128->pfifo.ramht_addr;
uint32_t ret = 0;
uint32_t tmp = handle;
uint32_t hash = 0;
int bits;
pclog("RIVA 128 RAMHT lookup with handle %08X %04X:%08X\n", handle, CS, cpu_state.pc);
switch(riva128->pfifo.ramht_size)
{
case 4096:
@@ -1828,21 +1847,25 @@ void riva128_pgraph_vblank_interrupt(void *p)
bits = 15;
}
while(handle)
while(tmp)
{
hash ^= (tmp & (riva128->pfifo.ramht_size - 1));
tmp = handle >> 1;
tmp = tmp >> 1;
}
hash ^= riva128->pfifo.caches[1].chanid << (bits - 4);
return riva128->pramin[ramht_base + (hash * 8)];
ret = riva128->pramin[ramht_base + (hash * 8)];
pclog("RIVA 128 RAMHT lookup with handle %08X returned %08X %04X:%08X\n", handle, ret, CS, cpu_state.pc);
return ret;
}
void riva128_puller_exec_method(int chanid, int subchanid, int offset, uint32_t val, void *p)
{
riva128_t *riva128 = (riva128_t *)p;
pclog("RIVA 128 Puller executing method %04X on channel %01X[%01X] %04X:%08X\n", offset, chanid, subchanid, val, CS, cpu_state.pc);
pclog("RIVA 128 Puller executing method %04X on channel %01X[%01X] param %08X %04X:%08X\n", offset, chanid, subchanid, val, CS, cpu_state.pc);
if(riva128->card_id == 0x03)
{
@@ -1927,6 +1950,36 @@ void riva128_pgraph_vblank_interrupt(void *p)
}
}
uint8_t riva128_user_read(uint32_t addr, void *p)
{
riva128_t *riva128 = (riva128_t *)p;
int chanid = (addr >> 16) & 0xf;
int subchanid = (addr >> 13) & 0x7;
int offset = addr & 0x1fff;
uint8_t ret = 0;
pclog("RIVA 128 USER read %08X %04X:%08X\n", addr, CS, cpu_state.pc);
addr -= 0x800000;
if(riva128->pfifo.chan_mode & (1 << chanid))
{
//DMA mode reads???
}
else
{
//PIO mode
switch(offset)
{
//HACK
case 0x10: ret = 0xff; break;
case 0x11: ret = 0x7f; break;
}
}
return ret;
}
void riva128_user_write(uint32_t addr, uint32_t val, void *p)
{
riva128_t *riva128 = (riva128_t *)p;
@@ -1954,8 +2007,23 @@ void riva128_pgraph_vblank_interrupt(void *p)
}
else
{
uint32_t err = -1;
int intr = 1;
//PIO mode
riva128_puller_exec_method(chanid, subchanid, offset, val, riva128);
//if((offset & 0x1f00) && (offset != 0)) err = 5; //Reserved access
//if((offset & 0x1ff0) == 0x0020) intr = 0;
//if(!riva128->pfifo.caches[1].push_enabled) err = 1; //Pusher disabled
//else
{
riva128_puller_exec_method(chanid, subchanid, offset, val, riva128);
riva128->pgraph.status = 0x1f131111; //HACK
}
if(err != -1)
{
uint32_t w = (addr & 0x7fffff) | (err << 28);
if(intr) riva128_pfifo_interrupt(4, riva128);
}
}
}
@@ -1981,6 +2049,7 @@ void riva128_pgraph_vblank_interrupt(void *p)
if((addr >= 0x300000) && (addr <= 0x30ffff) && (riva128->card_id >= 0x04)) ret = riva128->bios_rom.rom[addr & riva128->bios_rom.mask];
if((addr >= 0x400000) && (addr <= 0x400fff)) ret = riva128_pgraph_read(addr, riva128);
if((addr >= 0x680000) && (addr <= 0x680fff)) ret = riva128_pramdac_read(addr, riva128);
if(addr >= 0x800000) ret = riva128_user_read(addr, riva128);
switch(addr)
{
@@ -2246,34 +2315,47 @@ void riva128_ptimer_tick(void *p)
case 0x3D5:
switch(svga->crtcreg)
{
case 0x3e:
if(riva128->i2c.busy == 2)
{
if(riva128->i2c.addr == 0xA1)
{
//pclog("RIVA 128 Read EDID %02x %02x\n", riva128->i2c.edid_rom.addr, riva128->i2c.edid_rom.edid_rom[riva128->i2c.edid_rom.addr]);
riva128->i2c.data <<= 1;
riva128->i2c.data |= (riva128->i2c.edid_rom.edid_rom[riva128->i2c.edid_rom.addr] & (1 << riva128->i2c.databits)) >> riva128->i2c.databits;
}
riva128->i2c.databits++;
if(riva128->i2c.databits == 8)
{
riva128->i2c.databits = 0;
riva128->i2c.edid_rom.addr++;
riva128->i2c.busy = 0;
}
}
ret = (riva128->i2c.sda << 3) | (riva128->i2c.scl << 2);
break;
case 0x28:
ret = svga->crtc[0x28] & 0x3f;
break;
case 0x34:
ret = svga->displine & 0xff;
break;
case 0x35:
ret = (svga->displine >> 8) & 7;
break;
case 0x3e:
//DDC status register
ret = (riva128->i2c.sda << 3) | (riva128->i2c.scl << 2);
if(riva128->i2c.state == I2C_READ)
{
if(riva128->i2c.scl)
{
if(riva128->i2c.databits > 8)
{
riva128->i2c.data <<= 1;
if(riva128->i2c.addr == 0xA1)
{
riva128->i2c.data |= (riva128->i2c.edid_rom.edid_rom[riva128->i2c.edid_rom.addr] & (0x80 >> riva128->i2c.databits)) >> riva128->i2c.databits;
}
else riva128->i2c.data = 0;
riva128->i2c.databits++;
}
if(riva128->i2c.databits == 8)
{
riva128->i2c.state = I2C_WAITACK;
riva128->i2c.sda = 0;
riva128->i2c.edid_rom.addr++;
}
}
}
break;
default:
ret = svga->crtc[svga->crtcreg];
break;
}
//if(svga->crtcreg > 0x18)
// pclog("RIVA 128 Extended CRTC read %02X %04X:%08X\n", svga->crtcreg, CS, cpu_state.pc);
if(svga->crtcreg > 0x18)
pclog("RIVA 128 Extended CRTC read %02X %04X:%08X\n", svga->crtcreg, CS, cpu_state.pc);
break;
default:
ret = svga_in(addr, svga);
@@ -2343,44 +2425,46 @@ void riva128_ptimer_tick(void *p)
riva128->rma.mode = val & 0xf;
break;
case 0x3f:
if((val & 0x20) && (riva128->i2c.sda == 0) && (val & 0x10))
//FULL EMULATION OF I2C AND DDC PROTOCOLS INCOMING
if(riva128->i2c.sda && riva128->i2c.scl && ((val & 0x30) == 0))
{
//I2C Start Condition.
riva128->i2c.busy = 1;
riva128->i2c.state = I2C_START;
riva128->i2c.addr = 0;
riva128->i2c.addrbits = 0;
riva128->i2c.data = 0;
riva128->i2c.databits = 0;
}
if((val & 0x20) && (riva128->i2c.sda == 1) && !(val & 0x10))
else if(!riva128->i2c.sda && !riva128->i2c.scl && ((val & 0x30) == 0x30)) riva128->i2c.state = I2C_STOP;
else if(riva128->i2c.state == I2C_START)
{
//I2C Stop Condition.
riva128->i2c.busy = 0;
}
riva128->i2c.scl = (val & 0x20) ? 1 : 0;
riva128->i2c.sda = (val & 0x10) ? 1 : 0;
if(riva128->i2c.busy == 1)
{
riva128->i2c.addr <<= 1;
riva128->i2c.addr |= riva128->i2c.sda;
riva128->i2c.addrbits++;
if(riva128->i2c.addrbits == 8)
if(val & 0x20)
{
riva128->i2c.busy = 2;
riva128->i2c.addrbits = 0;
}
}
if(riva128->i2c.busy == 2)
{
riva128->i2c.data <<= 1;
riva128->i2c.addr |= riva128->i2c.sda;
riva128->i2c.databits++;
if(riva128->i2c.databits == 8)
{
if(riva128->i2c.addr == 0xA0)
if(riva128->i2c.addrbits > 8)
{
//pclog("RIVA 128 Write EDID Address %02x\n", riva128->i2c.data);
riva128->i2c.edid_rom.addr = riva128->i2c.data;
riva128->i2c.addr <<= 1;
riva128->i2c.addr |= (val >> 4) & 1;
riva128->i2c.addrbits++;
}
if(riva128->i2c.addrbits == 8)
{
riva128->i2c.state = I2C_WAITACK;
riva128->i2c.sda = 0;
if(riva128->i2c.addr == 0xA1) riva128->i2c.edid_rom.addr = 0;
}
riva128->i2c.databits = 0;
}
}
else if(riva128->i2c.state == I2C_WAITACK)
{
if(riva128->i2c.edid_rom.addr == 0x80)
{
riva128->i2c.edid_rom.addr = 0;
riva128->i2c.state = I2C_STOP;
}
else riva128->i2c.state = I2C_READ;
}
riva128->i2c.sda = (val >> 4) & 1;
riva128->i2c.scl = (val >> 5) & 1;
break;
}
//if(svga->crtcreg > 0x18)
@@ -2979,7 +3063,7 @@ void *riva128_init(device_t *info)
riva128->i2c.addrbits = 0;
riva128->i2c.databits = 0;
riva128->i2c.busy = 0;
riva128->i2c.state = I2C_STOP;
uint8_t edid_rom[128] = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
0x04, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -3010,7 +3094,7 @@ void *riva128_init(device_t *info)
riva128->nvenable = 1;
timer_add(riva128_mclk_poll, &riva128->mtime, &timer_one, riva128);
timer_add(riva128_nvclk_poll, &riva128->nvtime, &riva128->nvenable, riva128);
timer_add(riva128_nvclk_poll, &riva128->nvtime, &timer_one, riva128);
riva128->svga.vblank_start = riva128_vblank_start;
@@ -3214,7 +3298,7 @@ void *rivatnt_init(device_t *info)
riva128->i2c.addrbits = 0;
riva128->i2c.databits = 0;
riva128->i2c.busy = 0;
riva128->i2c.state = I2C_STOP;
uint8_t edid_rom[128] = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
0x04, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -3241,11 +3325,11 @@ void *rivatnt_init(device_t *info)
}
}
riva128->menable = 0;
riva128->nvenable = 0;
riva128->menable = 1;
riva128->nvenable = 1;
timer_add(riva128_mclk_poll, &riva128->mtime, &riva128->menable, riva128);
timer_add(riva128_nvclk_poll, &riva128->nvtime, &riva128->nvenable, riva128);
timer_add(riva128_mclk_poll, &riva128->mtime, &timer_one, riva128);
timer_add(riva128_nvclk_poll, &riva128->nvtime, &timer_one, riva128);
riva128->svga.vblank_start = riva128_vblank_start;
@@ -3422,7 +3506,7 @@ void *rivatnt2_init(device_t *info)
riva128->i2c.addrbits = 0;
riva128->i2c.databits = 0;
riva128->i2c.busy = 0;
riva128->i2c.state = I2C_STOP;
uint8_t edid_rom[128] = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
0x04, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -3449,11 +3533,11 @@ void *rivatnt2_init(device_t *info)
}
}
riva128->menable = 0;
riva128->nvenable = 0;
riva128->menable = 1;
riva128->nvenable = 1;
timer_add(riva128_mclk_poll, &riva128->mtime, &riva128->menable, riva128);
timer_add(riva128_nvclk_poll, &riva128->nvtime, &riva128->nvenable, riva128);
timer_add(riva128_mclk_poll, &riva128->mtime, &timer_one, riva128);
timer_add(riva128_nvclk_poll, &riva128->nvtime, &timer_one, riva128);
riva128->svga.vblank_start = riva128_vblank_start;