From 2ca4ead570b9ddc35203b3ff02ae0dfaac985d3e Mon Sep 17 00:00:00 2001 From: TomW Date: Thu, 20 Mar 2014 14:03:55 +0000 Subject: [PATCH] Implemented preliminary S3 ViRGE 2D blitter emulation. Misc ViRGE fixes. Changes to memory mapping. Changes to PCI handling. Disabled 'AMI WinBIOS 486 PCI' due to incomplete chipset emulation. Invalid GUS register reads no longer kill the emulator. --- src/386.c | 2 +- src/808x.c | 6 - src/Makefile.mingw | 2 +- src/ali1429.c | 62 +-- src/ega.c | 32 -- src/headland.c | 4 +- src/i430vx.c | 52 ++- src/mem.c | 510 ++++++++------------ src/mem.h | 33 +- src/model.c | 7 +- src/model.h | 1 + src/pc.c | 8 +- src/pc.rc | 20 +- src/pci.h | 5 + src/rom.c | 96 ++++ src/rom.h | 10 + src/sis496.c | 63 +-- src/sound_gus.c | 8 +- src/um8881f.c | 9 +- src/vid_ati18800.c | 12 +- src/vid_ati28800.c | 12 +- src/vid_ati_mach64.c | 126 ++++- src/vid_cga.c | 2 +- src/vid_cl5429.c | 14 +- src/vid_ega.c | 25 +- src/vid_ega.h | 2 + src/vid_et4000.c | 12 +- src/vid_et4000w32.c | 109 ++++- src/vid_hercules.c | 2 +- src/vid_mda.c | 2 +- src/vid_olivetti_m24.c | 2 +- src/vid_oti067.c | 40 +- src/vid_oti067.h | 1 + src/vid_paradise.c | 58 ++- src/vid_paradise.h | 5 +- src/vid_pc1512.c | 2 +- src/vid_pc1640.c | 9 +- src/vid_pc200.c | 2 +- src/vid_pcjr.c | 2 +- src/vid_s3.c | 372 +++++++++++---- src/vid_s3_virge.c | 1011 ++++++++++++++++++++++++++++++++++++---- src/vid_svga.c | 2 +- src/vid_tandy.c | 2 +- src/vid_tgui9440.c | 35 +- src/vid_tvga.c | 19 +- src/vid_vga.c | 12 +- src/vid_voodoo.c | 6 +- src/video.c | 11 +- src/win.c | 15 +- 49 files changed, 2116 insertions(+), 738 deletions(-) delete mode 100644 src/ega.c diff --git a/src/386.c b/src/386.c index a8fa33e..eb2b800 100644 --- a/src/386.c +++ b/src/386.c @@ -64,7 +64,7 @@ int cgate32; uint32_t mmucache[0x100000]; uint8_t romext[32768]; -uint8_t *ram,*rom,*vram,*vrom; +uint8_t *ram,*rom; uint16_t biosmask; uint32_t rmdat32; diff --git a/src/808x.c b/src/808x.c index b6f19df..1848b4b 100644 --- a/src/808x.c +++ b/src/808x.c @@ -561,14 +561,8 @@ chdir(pcempath); f=fopen("ram8.bin","wb"); fwrite(ram+0x3D210,0x200,1,f); fclose(f); */ - f=fopen("vram.dmp","wb"); - fwrite(vram,0x400000,1,f); - fclose(f); /* f=fopen("bios.dmp","wb"); fwrite(rom,0x20000,1,f); - fclose(f); - f=fopen("vbios.dmp","wb"); - fwrite(vrom,0x8000,1,f); fclose(f);*/ /* f=fopen("kernel.dmp","wb"); for (c=0;c<0x200000;c++) putc(readmemb(c+0xC0000000),f); diff --git a/src/Makefile.mingw b/src/Makefile.mingw index cf34e12..31aa708 100644 --- a/src/Makefile.mingw +++ b/src/Makefile.mingw @@ -4,7 +4,7 @@ CC = gcc.exe WINDRES = windres.exe CFLAGS = -O3 -march=i686 -fomit-frame-pointer OBJ = 386.o 808x.o acer386sx.o ali1429.o amstrad.o cdrom-ioctl.o \ - config.o cpu.o dac.o device.o dma.o ega.o fdc.o \ + config.o cpu.o dac.o device.o dma.o fdc.o \ headland.o i430vx.o ide.o io.o jim.o keyboard.o keyboard_amstrad.o keyboard_at.o \ keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o model.o \ mouse.o mouse_ps2.o mouse_serial.o neat.o nvr.o olivetti_m24.o \ diff --git a/src/ali1429.c b/src/ali1429.c index 5a156c2..8c22573 100644 --- a/src/ali1429.c +++ b/src/ali1429.c @@ -9,9 +9,42 @@ static int ali1429_index; static uint8_t ali1429_regs[256]; +static void ali1429_recalc() +{ + int c; + + for (c = 0; c < 8; c++) + { + uint32_t base = 0xc0000 + (c << 15); + if (ali1429_regs[0x13] & (1 << c)) + { + switch (ali1429_regs[0x14] & 3) + { + case 0: + mem_set_mem_state(base, 0x8000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + break; + case 1: + mem_set_mem_state(base, 0x8000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); + break; + case 2: + mem_set_mem_state(base, 0x8000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); + break; + case 3: + mem_set_mem_state(base, 0x8000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + } + } + else + mem_set_mem_state(base, 0x8000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + } + + flushmmucache(); +} + void ali1429_write(uint16_t port, uint8_t val, void *priv) { -// return; + int c; + if (!(port & 1)) ali1429_index = val; else @@ -21,35 +54,12 @@ void ali1429_write(uint16_t port, uint8_t val, void *priv) switch (ali1429_index) { case 0x13: - if (!(val & 0xc0)) - { - shadowbios = 0; - if (!shadowbios_write) - mem_bios_set_state(0xf0000, 0x10000, 0, 0); - else - mem_bios_set_state(0xf0000, 0x10000, 0, 1); - flushmmucache(); - } + ali1429_recalc(); break; case 0x14: shadowbios = val & 1; shadowbios_write = val & 2; - switch (val & 3) - { - case 0: - mem_bios_set_state(0xf0000, 0x10000, 0, 0); - break; - case 1: - mem_bios_set_state(0xf0000, 0x10000, 1, 0); - break; - case 2: - mem_bios_set_state(0xf0000, 0x10000, 0, 1); - break; - case 3: - mem_bios_set_state(0xf0000, 0x10000, 1, 1); - break; - } - flushmmucache(); + ali1429_recalc(); break; } } diff --git a/src/ega.c b/src/ega.c deleted file mode 100644 index 2dcca31..0000000 --- a/src/ega.c +++ /dev/null @@ -1,32 +0,0 @@ -#include "ibm.h" -#include "video.h" - - -void dumpegaregs() -{ -/* int c; - printf("CRTC :"); - for (c=0;c<0x20;c++) printf(" %02X",crtc[c]); - printf("\n"); - printf(" EXT :"); - for (c=0;c<0x20;c++) printf(" %02X",crtc[c+32]); - printf("\n"); - printf(" EXT2:"); - for (c=0;c<0x20;c++) printf(" %02X",crtc[c+64]); - printf("\n"); - printf("SEQ :"); - for (c=0;c<0x10;c++) printf(" %02X",seqregs[c]); - printf("\n"); - printf(" EXT :"); - for (c=0;c<0x10;c++) printf(" %02X",seqregs[c + 0x10]); - printf("\n"); - printf("ATTR :"); - for (c=0;c<0x20;c++) printf(" %02X",attrregs[c]); - printf("\n"); - printf("GDC :"); - for (c=0;c<0x10;c++) printf(" %02X",gdcreg[c]); - printf("\n"); -// printf("OLD CTRL2 = %02X NEW CTRL2 = %02X DAC = %02X 3C2 = %02X\n",tridentoldctrl2,tridentnewctrl2,tridentdac,ega3c2); - printf("BPP = %02X\n",bpp);*/ -} - diff --git a/src/headland.c b/src/headland.c index d6fae72..b4f460f 100644 --- a/src/headland.c +++ b/src/headland.c @@ -20,9 +20,9 @@ void headland_write(uint16_t addr, uint8_t val, void *priv) shadowbios = val & 0x10; shadowbios_write = !(val & 0x10); if (shadowbios) - mem_bios_set_state(0xf0000, 0x10000, 1, 0); + mem_set_mem_state(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); else - mem_bios_set_state(0xf0000, 0x10000, 0, 1); + mem_set_mem_state(0xf0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); } } else diff --git a/src/i430vx.c b/src/i430vx.c index f058ccc..5f2cb05 100644 --- a/src/i430vx.c +++ b/src/i430vx.c @@ -13,16 +13,22 @@ static void i430vx_map(uint32_t addr, uint32_t size, int state) { switch (state & 3) { - case 0x0: mem_bios_set_state(addr, size, 0, 0); break; /*DRAM disabled, accesses directed to PCI bus*/ - case 0x1: mem_bios_set_state(addr, size, 1, 0); break; /*Read only, DRAM write protected, non-cacheable*/ - case 0x2: mem_bios_set_state(addr, size, 0, 1); break; /*Write only*/ - case 0x3: mem_bios_set_state(addr, size, 1, 1); break; /*Read/write, non-cacheable*/ - /*Below are redundant*/ -// case 0x5: mem_sethandler(addr, size, mem_read_ram, mem_read_ramw, mem_read_raml, NULL, NULL, NULL ); break; /*Read only, DRAM write protected, cacheable*/ -// case 0x7: mem_sethandler(addr, size, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml); break; /*Read/write, non-cacheable*/ + case 0: + mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + break; + case 1: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); + break; + case 2: + mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); + break; + case 3: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; } flushmmucache_nopc(); } + void i430vx_write(int func, int addr, uint8_t val, void *priv) { if (func) @@ -43,18 +49,42 @@ void i430vx_write(int func, int addr, uint8_t val, void *priv) } pclog("i430vx_write : PAM0 write %02X\n", val); break; + case 0x5a: /*PAM1*/ + if ((card_i430vx[0x5a] ^ val) & 0x0f) + i430vx_map(0xc0000, 0x04000, val & 0xf); + if ((card_i430vx[0x5a] ^ val) & 0xf0) + i430vx_map(0xc4000, 0x04000, val >> 4); + break; + case 0x5b: /*PAM2*/ + if ((card_i430vx[0x5b] ^ val) & 0x0f) + i430vx_map(0xc8000, 0x04000, val & 0xf); + if ((card_i430vx[0x5b] ^ val) & 0xf0) + i430vx_map(0xcc000, 0x04000, val >> 4); + break; + case 0x5c: /*PAM3*/ + if ((card_i430vx[0x5c] ^ val) & 0x0f) + i430vx_map(0xd0000, 0x04000, val & 0xf); + if ((card_i430vx[0x5c] ^ val) & 0xf0) + i430vx_map(0xd4000, 0x04000, val >> 4); + break; + case 0x5d: /*PAM4*/ + if ((card_i430vx[0x5d] ^ val) & 0x0f) + i430vx_map(0xd8000, 0x04000, val & 0xf); + if ((card_i430vx[0x5d] ^ val) & 0xf0) + i430vx_map(0xdc000, 0x04000, val >> 4); + break; case 0x5e: /*PAM5*/ if ((card_i430vx[0x5e] ^ val) & 0x0f) - i430vx_map(0xe0000, 0x04000, val & 0xf); + i430vx_map(0xe0000, 0x04000, val & 0xf); if ((card_i430vx[0x5e] ^ val) & 0xf0) - i430vx_map(0xe4000, 0x04000, val >> 4); + i430vx_map(0xe4000, 0x04000, val >> 4); pclog("i430vx_write : PAM5 write %02X\n", val); break; case 0x5f: /*PAM6*/ if ((card_i430vx[0x5f] ^ val) & 0x0f) - i430vx_map(0xe8000, 0x04000, val & 0xf); + i430vx_map(0xe8000, 0x04000, val & 0xf); if ((card_i430vx[0x5f] ^ val) & 0xf0) - i430vx_map(0xec000, 0x04000, val >> 4); + i430vx_map(0xec000, 0x04000, val >> 4); pclog("i430vx_write : PAM6 write %02X\n", val); break; } diff --git a/src/mem.c b/src/mem.c index 15fe5c6..5e74022 100644 --- a/src/mem.c +++ b/src/mem.c @@ -16,20 +16,25 @@ #include "cpu.h" #include "rom.h" -static uint8_t (*_mem_read_b[0x40000])(uint32_t addr, void *priv); -static uint16_t (*_mem_read_w[0x40000])(uint32_t addr, void *priv); -static uint32_t (*_mem_read_l[0x40000])(uint32_t addr, void *priv); -static void (*_mem_write_b[0x40000])(uint32_t addr, uint8_t val, void *priv); -static void (*_mem_write_w[0x40000])(uint32_t addr, uint16_t val, void *priv); -static void (*_mem_write_l[0x40000])(uint32_t addr, uint32_t val, void *priv); -static void *_mem_priv[0x40000]; -static mem_mapping_t *_mem_mapping[0x40000]; +static uint8_t (*_mem_read_b[0x40000])(uint32_t addr, void *priv); +static uint16_t (*_mem_read_w[0x40000])(uint32_t addr, void *priv); +static uint32_t (*_mem_read_l[0x40000])(uint32_t addr, void *priv); +static void (*_mem_write_b[0x40000])(uint32_t addr, uint8_t val, void *priv); +static void (*_mem_write_w[0x40000])(uint32_t addr, uint16_t val, void *priv); +static void (*_mem_write_l[0x40000])(uint32_t addr, uint32_t val, void *priv); +static uint8_t *_mem_exec[0x40000]; +static void *_mem_priv_r[0x40000]; +static void *_mem_priv_w[0x40000]; +static mem_mapping_t *_mem_mapping_r[0x40000]; +static mem_mapping_t *_mem_mapping_w[0x40000]; +static int _mem_state[0x40000]; static mem_mapping_t base_mapping; static mem_mapping_t ram_low_mapping; static mem_mapping_t ram_high_mapping; +static mem_mapping_t ram_mid_mapping; static mem_mapping_t bios_mapping[8]; -static mem_mapping_t vrom_mapping; +static mem_mapping_t bios_high_mapping[8]; static mem_mapping_t romext_mapping; int shadowbios,shadowbios_write; @@ -42,7 +47,7 @@ uint32_t biosmask; int readlnum=0,writelnum=0; int cachesize=256; -uint8_t *ram,*rom,*vram,*vrom; +uint8_t *ram,*rom,*vram; uint8_t romext[32768]; static void mem_load_xtide_bios() @@ -71,179 +76,6 @@ static void mem_load_atide_bios() } } -int mem_load_video_bios() -{ - FILE *f = NULL; - int c; - switch (gfxcard) - { - case GFX_EGA: - f=romfopen("roms/ibm_6277356_ega_card_u44_27128.bin","rb"); - if (f) - { - pclog("Read EGA ROM!\n"); - fread(vrom,16384,1,f); - if (vrom[0x3FFE]==0xAA && vrom[0x3FFF]==0x55) - { - pclog("Read EGA ROM in reverse\n"); - fseek(f,0,SEEK_SET); - for (c=0x3FFF;c>=0;c--) - vrom[c]=getc(f); - } - fclose(f); - return 1; - } - break; - - case GFX_TVGA: - f=romfopen("roms/trident.bin","rb"); - if (f) - { - fread(vrom,32768,1,f); - fclose(f); - return 1; - } - break; - - case GFX_ET4000: - f=romfopen("roms/et4000.bin","rb"); - if (f) - { - fread(vrom,32768,1,f); - fclose(f); - return 1; - } - break; - - case GFX_ET4000W32: - f=romfopen("roms/et4000w32.bin","rb"); - if (f) - { - fread(vrom,32768,1,f); - fclose(f); - return 1; - } - break; - - case GFX_BAHAMAS64: - f=romfopen("roms/bahamas64.bin","rb"); - if (f) - { - fread(vrom,32768,1,f); - fclose(f); - return 1; - } - break; - - case GFX_N9_9FX: - f=romfopen("roms/s3_764.bin","rb"); - if (f) - { - fread(vrom,32768,1,f); - fclose(f); - return 1; - } - break; - - case GFX_STEALTH64: - f=romfopen("roms/TRIO64 (Ver. 1.5-07) [VGA] (S3 Incorporated).bin","rb"); - if (f) - { - fread(vrom,32768,1,f); - fclose(f); - return 1; - } - break; - - case GFX_VIRGE: - f=romfopen("roms/s3virge.bin","rb"); - if (f) - { - fread(vrom,32768,1,f); - fclose(f); - return 1; - } - break; - - case GFX_TGUI9440: - f=romfopen("roms/9440.vbi","rb"); - if (f) - { - fread(vrom,32768,1,f); - fclose(f); - return 1; - } - break; - - case GFX_VGA: - f=romfopen("roms/ibm_vga.bin","rb"); - if (f) - { - fread(vrom,32768,1,f); - fclose(f); - return 1; - } - break; - - case GFX_VGAEDGE16: - f=romfopen("roms/vgaedge16.vbi","rb"); - if (f) - { - fread(vrom,32768,1,f); - fclose(f); - return 1; - } - break; - - case GFX_VGACHARGER: - f=romfopen("roms/bios.bin","rb"); - if (f) - { - fread(vrom,32768,1,f); - fclose(f); - return 1; - } - break; - - case GFX_OTI067: - f=romfopen("roms/oti067/bios.bin","rb"); - if (f) - { - fread(vrom,32768,1,f); - fclose(f); - return 1; - } - break; - - case GFX_MACH64GX: - f=romfopen("roms/mach64gx/bios.bin","rb"); - if (f) - { - fread(vrom,32768,1,f); - fclose(f); - return 1; - } - break; - - case GFX_CL_GD5429: - f=romfopen("roms/5429.vbi","rb"); - if (f) - { - fread(vrom,32768,1,f); - fclose(f); - return 1; - } - break; - - default: - memset(vrom,0x63,0x8000); - return 1; - } - pclog("mem_load_video_bios : failed to load video BIOS for gfxcard %i\n", gfxcard); - memset(vrom,0x63,0x8000); - return 0; -} - int loadbios() { FILE *f=NULL,*ff=NULL; @@ -270,7 +102,6 @@ int loadbios() } fclose(ff); fclose(f); - memset(vrom,0x63,0x8000); mem_load_xtide_bios(); loadfont("roms/pc1512/40078.ic127", 2); return 1; @@ -287,7 +118,6 @@ int loadbios() fclose(f); f=romfopen("roms/pc1640/40100","rb"); if (!f) break; - fread(vrom,0x8000,1,f); fclose(f); mem_load_xtide_bios(); return 1; @@ -302,7 +132,6 @@ int loadbios() } fclose(ff); fclose(f); - memset(vrom,0x63,0x8000); mem_load_xtide_bios(); loadfont("roms/pc200/40109.bin", 1); return 1; @@ -311,7 +140,6 @@ int loadbios() if (!f) break; fread(rom,65536,1,f); fclose(f); - memset(vrom,0x63,0x8000); mem_load_xtide_bios(); return 1; /* case ROM_IBMPCJR: @@ -350,7 +178,6 @@ int loadbios() if (!f) break; fread(rom, 0x10000, 1, f); fclose(f); - memset(vrom,0x63,0x8000); return 1; case ROM_GENXT: @@ -396,11 +223,8 @@ int loadbios() fclose(f); f = romfopen("roms/pc2086/40186.ic171", "rb"); if (!f) break; - pclog("Loading VBIOS\n"); - fread(vrom, 32768, 1, f); fclose(f); mem_load_xtide_bios(); - pclog("%02X %02X %02X\n", rom[0xfff0], rom[0xfff1], rom[0xfff2]); biosmask = 0x3fff; return 1; @@ -411,11 +235,8 @@ int loadbios() fclose(f); f = romfopen("roms/pc3086/c000.bin", "rb"); if (!f) break; - pclog("Loading VBIOS\n"); - fread(vrom, 32768, 1, f); fclose(f); mem_load_xtide_bios(); - pclog("%02X %02X %02X\n", rom[0xfff0], rom[0xfff1], rom[0xfff2]); biosmask = 0x3fff; return 1; @@ -488,9 +309,7 @@ int loadbios() rom[0x40d4]=0x51; /*PUSH CX*/ f=romfopen("roms/acer386/oti067.bin","rb"); if (!f) break; - fread(vrom,0x8000,1,f); fclose(f); - vrom[0x5D]=0x74; return 1; case ROM_AMI286: @@ -536,15 +355,9 @@ int loadbios() return 1; case ROM_MEGAPC: - pclog("Loading MegaPC\n"); f = romfopen("roms/megapc/41651-bios lo.u18", "rb"); ff = romfopen("roms/megapc/211253-bios hi.u19", "rb"); if (!f || !ff) break; - for (c = 0x0000; c < 0x8000; c+=2) - { - vrom[c]=getc(f); - vrom[c+1]=getc(ff); - } fseek(f, 0x8000, SEEK_SET); fseek(ff, 0x8000, SEEK_SET); for (c = 0x0000; c < 0x10000; c+=2) @@ -567,7 +380,6 @@ int loadbios() case ROM_WIN486: // f=romfopen("roms/win486/win486.bin","rb"); f=romfopen("roms/win486/ALI1429G.AMW","rb"); - if (!f) break; fread(rom,65536,1,f); fclose(f); @@ -589,6 +401,7 @@ int loadbios() fread(rom, 0x20000, 1, f); fclose(f); biosmask = 0x1ffff; + pclog("Load SIS496 %x %x\n", rom[0x1fff0], rom[0xfff0]); return 1; case ROM_430VX: @@ -970,10 +783,17 @@ pctrans=1; addreadlookup(a2,a); // if (a > 0xc0000000) // printf("%016X %016X %016X\n", ((long)a&0xFFFFF000), ((long)a2&~0xFFF), (uint8_t *)(a&0xFFFFF000) - (uint8_t *)(a2&~0xFFF)); +// pclog("getpccache: virt=%08x phys=%08x RAM\n", a2, a); return &ram[(uint8_t *)(a&0xFFFFF000) - (uint8_t *)(a2&~0xFFF)]; } // if (logit) printf("PCCACHE - %08X -> %08X\n",a2,a); - switch (a>>16) + if (_mem_exec[a >> 14]) + { +// pclog("getpccache: %p %p %p\n", ram, rom, &_mem_exec[a >> 14][(a & 0x3000) - (a2 & ~0xFFF)]); +// pclog("getpccache: virt=%08x phys=%08x %08x %08x %08x %08x\n", a2, a, _mem_exec[a >> 14], &_mem_exec[a >> 14][(a & 0x3000) - (a2 & ~0xFFF)], &_mem_exec[a >> 14][(a & 0x3000) - (a2 & ~0xFFF)] + 0xf0000, rom); + return &_mem_exec[a >> 14][(a & 0x3000) - (a2 & ~0xFFF)]; + } +/* switch (a>>16) { case 0xC: if (a&0x8000) return &romext[(uint8_t *)(a&0x7000) - (uint8_t *)(a2&~0xFFF)]; return &vrom[(uint8_t *)(a&0x7000) - (uint8_t *)(a2&~0xFFF)]; @@ -982,7 +802,8 @@ pctrans=1; case 0xF: if (shadowbios) return &ram[(uint8_t *)(a&0xFFF000) - (uint8_t *)(a2&~0xFFF)]; return &rom[(uint8_t *)((a & biosmask) & ~ 0xfff) - (uint8_t *)(a2 & ~0xFFF)]; } - return &rom[(long)(a&0xF000) - (long)(a2&~0xFFF)]; + return &rom[(long)(a&0xF000) - (long)(a2&~0xFFF)];*/ + fatal("Bad getpccache %08X\n", a); /*printf("Bad getpccache %08X\n",a); dumpregs(); exit(-1);*/ @@ -1000,7 +821,7 @@ uint8_t readmembl(uint32_t addr) } addr &= rammask; - if (_mem_read_b[addr >> 14]) return _mem_read_b[addr >> 14](addr, _mem_priv[addr >> 14]); + if (_mem_read_b[addr >> 14]) return _mem_read_b[addr >> 14](addr, _mem_priv_r[addr >> 14]); // pclog("Bad readmembl %08X %04X:%08X\n", addr, CS, pc); return 0xFF; } @@ -1016,8 +837,8 @@ void writemembl(uint32_t addr, uint8_t val) } addr &= rammask; - if (_mem_write_b[addr >> 14]) _mem_write_b[addr >> 14](addr, val, _mem_priv[addr >> 14]); -// else pclog("Bad write %08X %02X %04X:%08X\n", addr, val, CS, pc); + if (_mem_write_b[addr >> 14]) _mem_write_b[addr >> 14](addr, val, _mem_priv_w[addr >> 14]); +// else pclog("Bad writemembl %08X %02X %04X:%08X\n", addr, val, CS, pc); } uint8_t readmemb386l(uint32_t seg, uint32_t addr) @@ -1042,7 +863,7 @@ uint8_t readmemb386l(uint32_t seg, uint32_t addr) addr &= rammask; - if (_mem_read_b[addr >> 14]) return _mem_read_b[addr >> 14](addr, _mem_priv[addr >> 14]); + if (_mem_read_b[addr >> 14]) return _mem_read_b[addr >> 14](addr, _mem_priv_r[addr >> 14]); // pclog("Bad readmemb386l %08X %04X:%08X\n", addr, CS, pc); return 0xFF; } @@ -1068,8 +889,8 @@ void writememb386l(uint32_t seg, uint32_t addr, uint8_t val) /* if (addr >= 0xa0000 && addr < 0xc0000) pclog("writemembl %08X %02X\n", addr, val);*/ - if (_mem_write_b[addr >> 14]) _mem_write_b[addr >> 14](addr, val, _mem_priv[addr >> 14]); -// else pclog("Bad write %08X %02X %04X:%08X\n", addr, val, CS, pc); + if (_mem_write_b[addr >> 14]) _mem_write_b[addr >> 14](addr, val, _mem_priv_w[addr >> 14]); +// else pclog("Bad writememb386l %08X %02X %04X:%08X\n", addr, val, CS, pc); } uint16_t readmemwl(uint32_t seg, uint32_t addr) @@ -1099,13 +920,14 @@ uint16_t readmemwl(uint32_t seg, uint32_t addr) addr2 &= rammask; - if (_mem_read_w[addr2 >> 14]) return _mem_read_w[addr2 >> 14](addr2, _mem_priv[addr2 >> 14]); + if (_mem_read_w[addr2 >> 14]) return _mem_read_w[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]); if (_mem_read_b[addr2 >> 14]) { - if (AT) return _mem_read_b[addr2 >> 14](addr2, _mem_priv[addr2 >> 14]) | (_mem_read_b[(addr2 + 1) >> 14](addr2 + 1, _mem_priv[addr2 >> 14]) << 8); - else return _mem_read_b[addr2 >> 14](addr2, _mem_priv[addr2 >> 14]) | (_mem_read_b[(seg + ((addr + 1) & 0xffff)) >> 14](seg + ((addr + 1) & 0xffff), _mem_priv[addr2 >> 14]) << 8); + if (AT) return _mem_read_b[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | (_mem_read_b[(addr2 + 1) >> 14](addr2 + 1, _mem_priv_r[addr2 >> 14]) << 8); + else return _mem_read_b[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | (_mem_read_b[(seg + ((addr + 1) & 0xffff)) >> 14](seg + ((addr + 1) & 0xffff), _mem_priv_r[addr2 >> 14]) << 8); } +// pclog("Bad readmemwl %08X\n", addr2); return 0xffff; } @@ -1151,17 +973,17 @@ void writememwl(uint32_t seg, uint32_t addr, uint16_t val) if (_mem_write_w[addr2 >> 14]) { - _mem_write_w[addr2 >> 14](addr2, val, _mem_priv[addr2 >> 14]); + _mem_write_w[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]); return; } if (_mem_write_b[addr2 >> 14]) { - _mem_write_b[addr2 >> 14](addr2, val, _mem_priv[addr2 >> 14]); - _mem_write_b[(addr2 + 1) >> 14](addr2 + 1, val >> 8, _mem_priv[addr2 >> 14]); + _mem_write_b[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]); + _mem_write_b[(addr2 + 1) >> 14](addr2 + 1, val >> 8, _mem_priv_w[addr2 >> 14]); return; } -// pclog("Bad write %08X %04X\n", addr2, val); +// pclog("Bad writememwl %08X %04X\n", addr2, val); } uint32_t readmemll(uint32_t seg, uint32_t addr) @@ -1192,12 +1014,13 @@ uint32_t readmemll(uint32_t seg, uint32_t addr) addr2&=rammask; - if (_mem_read_l[addr2 >> 14]) return _mem_read_l[addr2 >> 14](addr2, _mem_priv[addr2 >> 14]); + if (_mem_read_l[addr2 >> 14]) return _mem_read_l[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]); - if (_mem_read_w[addr2 >> 14]) return _mem_read_w[addr2 >> 14](addr2, _mem_priv[addr2 >> 14]) | (_mem_read_w[addr2 >> 14](addr2 + 2, _mem_priv[addr2 >> 14]) << 16); + if (_mem_read_w[addr2 >> 14]) return _mem_read_w[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | (_mem_read_w[addr2 >> 14](addr2 + 2, _mem_priv_r[addr2 >> 14]) << 16); - if (_mem_read_b[addr2 >> 14]) return _mem_read_b[addr2 >> 14](addr2, _mem_priv[addr2 >> 14]) | (_mem_read_b[addr2 >> 14](addr2 + 1, _mem_priv[addr2 >> 14]) << 8) | (_mem_read_b[addr2 >> 14](addr2 + 2, _mem_priv[addr2 >> 14]) << 16) | (_mem_read_b[addr2 >> 14](addr2 + 3, _mem_priv[addr2 >> 14]) << 24); + if (_mem_read_b[addr2 >> 14]) return _mem_read_b[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | (_mem_read_b[addr2 >> 14](addr2 + 1, _mem_priv_r[addr2 >> 14]) << 8) | (_mem_read_b[addr2 >> 14](addr2 + 2, _mem_priv_r[addr2 >> 14]) << 16) | (_mem_read_b[addr2 >> 14](addr2 + 3, _mem_priv_r[addr2 >> 14]) << 24); +// pclog("Bad readmemll %08X\n", addr2); return 0xffffffff; } @@ -1235,24 +1058,24 @@ void writememll(uint32_t seg, uint32_t addr, uint32_t val) if (_mem_write_l[addr2 >> 14]) { - _mem_write_l[addr2 >> 14](addr2, val, _mem_priv[addr2 >> 14]); + _mem_write_l[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]); return; } if (_mem_write_w[addr2 >> 14]) { - _mem_write_w[addr2 >> 14](addr2, val, _mem_priv[addr2 >> 14]); - _mem_write_w[addr2 >> 14](addr2 + 2, val >> 16, _mem_priv[addr2 >> 14]); + _mem_write_w[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]); + _mem_write_w[addr2 >> 14](addr2 + 2, val >> 16, _mem_priv_w[addr2 >> 14]); return; } if (_mem_write_b[addr2 >> 14]) { - _mem_write_b[addr2 >> 14](addr2, val, _mem_priv[addr2 >> 14]); - _mem_write_b[addr2 >> 14](addr2 + 1, val >> 8, _mem_priv[addr2 >> 14]); - _mem_write_b[addr2 >> 14](addr2 + 2, val >> 16, _mem_priv[addr2 >> 14]); - _mem_write_b[addr2 >> 14](addr2 + 3, val >> 24, _mem_priv[addr2 >> 14]); + _mem_write_b[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]); + _mem_write_b[addr2 >> 14](addr2 + 1, val >> 8, _mem_priv_w[addr2 >> 14]); + _mem_write_b[addr2 >> 14](addr2 + 2, val >> 16, _mem_priv_w[addr2 >> 14]); + _mem_write_b[addr2 >> 14](addr2 + 3, val >> 24, _mem_priv_w[addr2 >> 14]); return; } -// pclog("Bad write %08X %08X\n", addr2, val); +// pclog("Bad writememll %08X %08X\n", addr2, val); } uint8_t mem_readb_phys(uint32_t addr) @@ -1260,7 +1083,7 @@ uint8_t mem_readb_phys(uint32_t addr) mem_logical_addr = 0xffffffff; if (_mem_read_b[addr >> 14]) - return _mem_read_b[addr >> 14](addr, _mem_priv[addr >> 14]); + return _mem_read_b[addr >> 14](addr, _mem_priv_r[addr >> 14]); return 0xff; } @@ -1270,24 +1093,24 @@ void mem_writeb_phys(uint32_t addr, uint8_t val) mem_logical_addr = 0xffffffff; if (_mem_write_b[addr >> 14]) - _mem_write_b[addr >> 14](addr, val, _mem_priv[addr >> 14]); + _mem_write_b[addr >> 14](addr, val, _mem_priv_w[addr >> 14]); } uint8_t mem_read_ram(uint32_t addr, void *priv) { -// if (addr >= 0xe0000 && addr < 0x100000) pclog("Read RAMb %08X\n", addr); +// if (addr >= 0xc0000 && addr < 0x0c8000) pclog("Read RAMb %08X\n", addr); addreadlookup(mem_logical_addr, addr); return ram[addr]; } uint16_t mem_read_ramw(uint32_t addr, void *priv) { -// if (addr >= 0xe0000 && addr < 0x100000) pclog("Read RAMw %08X\n", addr); +// if (addr >= 0xc0000 && addr < 0x0c8000) pclog("Read RAMw %08X\n", addr); addreadlookup(mem_logical_addr, addr); return *(uint16_t *)&ram[addr]; } uint32_t mem_read_raml(uint32_t addr, void *priv) { -// if (addr >= 0xe0000 && addr < 0x100000) pclog("Read RAMl %08X\n", addr); +// if (addr >= 0xc0000 && addr < 0x0c8000) pclog("Read RAMl %08X\n", addr); addreadlookup(mem_logical_addr, addr); return *(uint32_t *)&ram[addr]; } @@ -1296,19 +1119,19 @@ void mem_write_ram(uint32_t addr, uint8_t val, void *priv) { addwritelookup(mem_logical_addr, addr); ram[addr] = val; -// if (addr >= 0xe0000 && addr < 0x100000) pclog("Write RAMb %08X\n", addr); +// if (addr >= 0xc0000 && addr < 0x0c8000) pclog("Write RAMb %08X\n", addr); } void mem_write_ramw(uint32_t addr, uint16_t val, void *priv) { addwritelookup(mem_logical_addr, addr); *(uint16_t *)&ram[addr] = val; -// if (addr >= 0xe0000 && addr < 0x100000) pclog("Write RAMw %08X %04X:%04X %i %04X %04X:%04X %04X:%04X\n", addr, CS, pc, ins, val, DS,SI, ES,DI); +// if (addr >= 0xc0000 && addr < 0x0c8000) pclog("Write RAMw %08X %04X:%04X %i %04X %04X:%04X %04X:%04X\n", addr, CS, pc, ins, val, DS,SI, ES,DI); } void mem_write_raml(uint32_t addr, uint32_t val, void *priv) { addwritelookup(mem_logical_addr, addr); *(uint32_t *)&ram[addr] = val; -// if (addr >= 0xe0000 && addr < 0x100000) pclog("Write RAMl %08X %04X:%04X %04X:%04X %04X:%04X\n", addr, CS, pc, DS,SI, ES,DI); +// if (addr >= 0xc0000 && addr < 0x0c8000) pclog("Write RAMl %08X %04X:%04X %04X:%04X %04X:%04X\n", addr, CS, pc, DS,SI, ES,DI); } uint8_t mem_read_bios(uint32_t addr, void *priv) @@ -1333,19 +1156,6 @@ uint32_t mem_read_biosl(uint32_t addr, void *priv) return *(uint32_t *)&rom[addr & biosmask]; } -uint8_t mem_read_vrom(uint32_t addr, void *priv) -{ - return vrom[addr & 0x7fff]; -} -uint16_t mem_read_vromw(uint32_t addr, void *priv) -{ - return *(uint16_t *)&vrom[addr & 0x7fff]; -} -uint32_t mem_read_vroml(uint32_t addr, void *priv) -{ - return *(uint32_t *)&vrom[addr & 0x7fff]; -} - uint8_t mem_read_romext(uint32_t addr, void *priv) { return romext[addr & 0x7fff]; @@ -1359,6 +1169,15 @@ uint32_t mem_read_romextl(uint32_t addr, void *priv) return *(uint32_t *)&romext[addr & 0x7fff]; } +void mem_write_null(uint32_t addr, uint8_t val, void *p) +{ +} +void mem_write_nullw(uint32_t addr, uint16_t val, void *p) +{ +} +void mem_write_nulll(uint32_t addr, uint32_t val, void *p) +{ +} void mem_updatecache() { @@ -1383,50 +1202,88 @@ void mem_updatecache() } } -static void mem_mapping_recalc(uint32_t base, uint32_t size) +static inline int mem_mapping_read_allowed(uint32_t flags, int state) { - uint32_t c; +// pclog("mem_mapping_read_allowed: flags=%x state=%x\n", flags, state); + switch (state & MEM_READ_MASK) + { + case MEM_READ_ANY: + return 1; + case MEM_READ_EXTERNAL: + return !(flags & MEM_MAPPING_INTERNAL); + case MEM_READ_INTERNAL: + return !(flags & MEM_MAPPING_EXTERNAL); + default: + fatal("mem_mapping_read_allowed : bad state %x\n", state); + } +} + +static inline int mem_mapping_write_allowed(uint32_t flags, int state) +{ + switch (state & MEM_WRITE_MASK) + { + case MEM_WRITE_DISABLED: + return 0; + case MEM_WRITE_ANY: + return 1; + case MEM_WRITE_EXTERNAL: + return !(flags & MEM_MAPPING_INTERNAL); + case MEM_WRITE_INTERNAL: + return !(flags & MEM_MAPPING_EXTERNAL); + default: + fatal("mem_mapping_write_allowed : bad state %x\n", state); + } +} + +static void mem_mapping_recalc(uint64_t base, uint64_t size) +{ + uint64_t c; mem_mapping_t *mapping = base_mapping.next; - if ((base + size) > 0xffff8000) - size = 0xffff0000 - base; - /*Clear out old mappings*/ for (c = base; c < base + size; c += 0x4000) { _mem_read_b[c >> 14] = NULL; _mem_read_w[c >> 14] = NULL; _mem_read_l[c >> 14] = NULL; + _mem_priv_r[c >> 14] = NULL; + _mem_mapping_r[c >> 14] = NULL; _mem_write_b[c >> 14] = NULL; _mem_write_w[c >> 14] = NULL; _mem_write_l[c >> 14] = NULL; - _mem_priv[c >> 14] = NULL; - _mem_mapping[c >> 14] = NULL; + _mem_priv_w[c >> 14] = NULL; + _mem_mapping_w[c >> 14] = NULL; } -// pclog("mem_mapping_recalc %08X %08X\n", base, size); + /*Walk mapping list*/ while (mapping != NULL) { -// pclog("mapping=%p next=%p base=%08X size=%08X enable=%i\n", mapping, mapping->next, mapping->base, mapping->size, mapping->enable); /*In range?*/ - if (mapping->enable && mapping->base < (base + size) && (mapping->base + mapping->size) >= base) + if (mapping->enable && (uint64_t)mapping->base < ((uint64_t)base + (uint64_t)size) && ((uint64_t)mapping->base + (uint64_t)mapping->size) > (uint64_t)base) { - uint32_t start = (mapping->base < base) ? mapping->base : base; - uint32_t end = ((mapping->base + mapping->size) < (base + size)) ? (mapping->base + mapping->size) : (base + size); - + uint64_t start = (mapping->base < base) ? mapping->base : base; + uint64_t end = (((uint64_t)mapping->base + (uint64_t)mapping->size) < (base + size)) ? ((uint64_t)mapping->base + (uint64_t)mapping->size) : (base + size); + for (c = start; c < end; c += 0x4000) { - if (_mem_mapping[c >> 14] == NULL) + if ((mapping->read_b || mapping->read_w || mapping->read_l) && + mem_mapping_read_allowed(mapping->flags, _mem_state[c >> 14])) { -// pclog(" Add %08X\n", c); _mem_read_b[c >> 14] = mapping->read_b; _mem_read_w[c >> 14] = mapping->read_w; _mem_read_l[c >> 14] = mapping->read_l; + _mem_exec[c >> 14] = mapping->exec + (c - mapping->base); + _mem_priv_r[c >> 14] = mapping->p; + _mem_mapping_r[c >> 14] = mapping; + } + if ((mapping->write_b || mapping->write_w || mapping->write_l) && + mem_mapping_write_allowed(mapping->flags, _mem_state[c >> 14])) + { _mem_write_b[c >> 14] = mapping->write_b; _mem_write_w[c >> 14] = mapping->write_w; _mem_write_l[c >> 14] = mapping->write_l; - _mem_priv[c >> 14] = mapping->p; - _mem_mapping[c >> 14] = mapping; + _mem_priv_w[c >> 14] = mapping->p; + _mem_mapping_w[c >> 14] = mapping; } } } @@ -1443,6 +1300,8 @@ void mem_mapping_add(mem_mapping_t *mapping, void (*write_b)(uint32_t addr, uint8_t val, void *p), void (*write_w)(uint32_t addr, uint16_t val, void *p), void (*write_l)(uint32_t addr, uint32_t val, void *p), + uint8_t *exec, + uint32_t flags, void *p) { mem_mapping_t *dest = &base_mapping; @@ -1464,6 +1323,8 @@ void mem_mapping_add(mem_mapping_t *mapping, mapping->write_b = write_b; mapping->write_w = write_w; mapping->write_l = write_l; + mapping->exec = exec; + mapping->flags = flags; mapping->p = p; mapping->next = NULL; @@ -1502,6 +1363,13 @@ void mem_mapping_set_addr(mem_mapping_t *mapping, uint32_t base, uint32_t size) mem_mapping_recalc(mapping->base, mapping->size); } +void mem_mapping_set_exec(mem_mapping_t *mapping, uint8_t *exec) +{ + mapping->exec = exec; + + mem_mapping_recalc(mapping->base, mapping->size); +} + void mem_mapping_set_p(mem_mapping_t *mapping, void *p) { mapping->p = p; @@ -1521,6 +1389,38 @@ void mem_mapping_enable(mem_mapping_t *mapping) mem_mapping_recalc(mapping->base, mapping->size); } +void mem_set_mem_state(uint32_t base, uint32_t size, int state) +{ + uint32_t c; + +// pclog("mem_set_pci_enable: base=%08x size=%08x\n", base, size); + for (c = 0; c < size; c += 0x4000) + _mem_state[(c + base) >> 14] = state; + + mem_mapping_recalc(base, size); +} + +void mem_add_bios() +{ + mem_mapping_add(&bios_mapping[0], 0xe0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom, MEM_MAPPING_EXTERNAL, 0); + mem_mapping_add(&bios_mapping[1], 0xe4000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x4000 & biosmask), MEM_MAPPING_EXTERNAL, 0); + mem_mapping_add(&bios_mapping[2], 0xe8000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x8000 & biosmask), MEM_MAPPING_EXTERNAL, 0); + mem_mapping_add(&bios_mapping[3], 0xec000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0xc000 & biosmask), MEM_MAPPING_EXTERNAL, 0); + mem_mapping_add(&bios_mapping[4], 0xf0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x10000 & biosmask), MEM_MAPPING_EXTERNAL, 0); + mem_mapping_add(&bios_mapping[5], 0xf4000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x14000 & biosmask), MEM_MAPPING_EXTERNAL, 0); + mem_mapping_add(&bios_mapping[6], 0xf8000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x18000 & biosmask), MEM_MAPPING_EXTERNAL, 0); + mem_mapping_add(&bios_mapping[7], 0xfc000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x1c000 & biosmask), MEM_MAPPING_EXTERNAL, 0); + + mem_mapping_add(&bios_high_mapping[0], 0xfffe0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom, 0, 0); + mem_mapping_add(&bios_high_mapping[1], 0xfffe4000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x4000 & biosmask), 0, 0); + mem_mapping_add(&bios_high_mapping[2], 0xfffe8000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x8000 & biosmask), 0, 0); + mem_mapping_add(&bios_high_mapping[3], 0xfffec000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0xc000 & biosmask), 0, 0); + mem_mapping_add(&bios_high_mapping[4], 0xffff0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x10000 & biosmask), 0, 0); + mem_mapping_add(&bios_high_mapping[5], 0xffff4000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x14000 & biosmask), 0, 0); + mem_mapping_add(&bios_high_mapping[6], 0xffff8000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x18000 & biosmask), 0, 0); + mem_mapping_add(&bios_high_mapping[7], 0xffffc000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x1c000 & biosmask), 0, 0); +} + void mem_init() { int c; @@ -1528,7 +1428,6 @@ void mem_init() ram = malloc(mem_size * 1024 * 1024); rom = malloc(0x20000); vram = malloc(0x800000); - vrom = malloc(0x8000); readlookup2 = malloc(1024 * 1024 * 4); writelookup2 = malloc(1024 * 1024 * 4); cachelookup2 = malloc(1024 * 1024); @@ -1553,21 +1452,16 @@ void mem_init() memset(&base_mapping, 0, sizeof(base_mapping)); - mem_mapping_add(&ram_low_mapping, 0x00000, 0xa0000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, NULL); + memset(_mem_state, 0, sizeof(_mem_state)); + + mem_set_mem_state(0xc0000, 0x40000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + + mem_mapping_add(&ram_low_mapping, 0x00000, 0xa0000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram, 0, NULL); if (mem_size > 1) - mem_mapping_add(&ram_low_mapping, 0x100000, (mem_size - 1) * 1024 * 1024, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, NULL); + mem_mapping_add(&ram_high_mapping, 0x100000, (mem_size - 1) * 1024 * 1024, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram + 0x100000, 0, NULL); + mem_mapping_add(&ram_mid_mapping, 0xc0000, 0x40000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram + 0xc0000, MEM_MAPPING_INTERNAL, NULL); - mem_mapping_add(&bios_mapping[0], 0xe0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml, NULL); - mem_mapping_add(&bios_mapping[1], 0xe4000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml, NULL); - mem_mapping_add(&bios_mapping[2], 0xe8000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml, NULL); - mem_mapping_add(&bios_mapping[3], 0xec000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml, NULL); - mem_mapping_add(&bios_mapping[4], 0xf0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml, NULL); - mem_mapping_add(&bios_mapping[5], 0xf4000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml, NULL); - mem_mapping_add(&bios_mapping[6], 0xf8000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml, NULL); - mem_mapping_add(&bios_mapping[7], 0xfc000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml, NULL); - - mem_mapping_add(&vrom_mapping, 0xc0000, 0x08000, mem_read_vrom, mem_read_vromw, mem_read_vroml, NULL, NULL, NULL, NULL); - mem_mapping_add(&romext_mapping, 0xc8000, 0x08000, mem_read_romext, mem_read_romextw, mem_read_romextl, NULL, NULL, NULL, NULL); + mem_mapping_add(&romext_mapping, 0xc8000, 0x08000, mem_read_romext, mem_read_romextw, mem_read_romextl, NULL, NULL, NULL, romext, 0, NULL); // pclog("Mem resize %i %i\n",mem_size,c); } @@ -1595,57 +1489,23 @@ void mem_resize() memset(_mem_write_l, 0, sizeof(_mem_write_l)); memset(&base_mapping, 0, sizeof(base_mapping)); + + memset(_mem_state, 0, sizeof(_mem_state)); - mem_mapping_add(&ram_low_mapping, 0x00000, 0xa0000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, NULL); + mem_set_mem_state(0xc0000, 0x40000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + + mem_mapping_add(&ram_low_mapping, 0x00000, 0xa0000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram, 0, NULL); if (mem_size > 1) - mem_mapping_add(&ram_low_mapping, 0x100000, (mem_size - 1) * 1024 * 1024, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, NULL); - - mem_mapping_add(&bios_mapping[0], 0xe0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml, NULL); - mem_mapping_add(&bios_mapping[1], 0xe4000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml, NULL); - mem_mapping_add(&bios_mapping[2], 0xe8000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml, NULL); - mem_mapping_add(&bios_mapping[3], 0xec000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml, NULL); - mem_mapping_add(&bios_mapping[4], 0xf0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml, NULL); - mem_mapping_add(&bios_mapping[5], 0xf4000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml, NULL); - mem_mapping_add(&bios_mapping[6], 0xf8000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml, NULL); - mem_mapping_add(&bios_mapping[7], 0xfc000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml, NULL); + mem_mapping_add(&ram_high_mapping, 0x100000, (mem_size - 1) * 1024 * 1024, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram + 0x100000, 0, NULL); + mem_mapping_add(&ram_mid_mapping, 0xc0000, 0x40000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram + 0xc0000, MEM_MAPPING_INTERNAL, NULL); - mem_mapping_add(&vrom_mapping, 0xc0000, 0x08000, mem_read_vrom, mem_read_vromw, mem_read_vroml, NULL, NULL, NULL, NULL); - mem_mapping_add(&romext_mapping, 0xc8000, 0x08000, mem_read_romext, mem_read_romextw, mem_read_romextl, NULL, NULL, NULL, NULL); + mem_add_bios(); + + mem_mapping_add(&romext_mapping, 0xc8000, 0x08000, mem_read_romext, mem_read_romextw, mem_read_romextl, NULL, NULL, NULL, romext, 0, NULL); // pclog("Mem resize %i %i\n",mem_size,c); } -void mem_bios_set_state(uint32_t base, uint32_t size, int read_ram, int write_ram) -{ - uint32_t c; - int state = (read_ram ? 1 : 0) | (write_ram ? 2: 0); - - if (base < 0xe0000 || base > 0xfffff) - return; - if ((base + size) > 0x100000) - size = 0x100000 - base; - - for (c = base; c < (base + size); c+= 0x4000) - { -// pclog("mem_bios_set_state: c=%08X base=%08X size=%08X bios=%i\n", c, base, size, (c - 0xe0000) >> 14); - switch (state) - { - case 0: - mem_mapping_set_handler(&bios_mapping[(c - 0xe0000) >> 14], mem_read_bios, mem_read_biosw, mem_read_biosl, NULL, NULL, NULL); - break; - case 1: - mem_mapping_set_handler(&bios_mapping[(c - 0xe0000) >> 14], mem_read_ram, mem_read_ramw, mem_read_raml, NULL, NULL, NULL); - break; - case 2: - mem_mapping_set_handler(&bios_mapping[(c - 0xe0000) >> 14], mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml); - break; - case 3: - mem_mapping_set_handler(&bios_mapping[(c - 0xe0000) >> 14], mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml); - break; - } - } -} - int mem_a20_key = 0, mem_a20_alt = 0; static int mem_a20_state = 0; diff --git a/src/mem.h b/src/mem.h index dfafb66..b130239 100644 --- a/src/mem.h +++ b/src/mem.h @@ -14,10 +14,19 @@ typedef struct mem_mapping_t void (*write_w)(uint32_t addr, uint16_t val, void *priv); void (*write_l)(uint32_t addr, uint32_t val, void *priv); + uint8_t *exec; + + uint32_t flags; + void *p; } mem_mapping_t; -extern uint8_t *ram,*rom,*vram,*vrom; +/*Only present on external bus (ISA/PCI)*/ +#define MEM_MAPPING_EXTERNAL 1 +/*Only present on internal bus (RAM)*/ +#define MEM_MAPPING_INTERNAL 2 + +extern uint8_t *ram,*rom; extern uint8_t romext[32768]; extern int readlnum,writelnum; extern int memspeed[11]; @@ -34,6 +43,8 @@ void mem_mapping_add(mem_mapping_t *mapping, void (*write_b)(uint32_t addr, uint8_t val, void *p), void (*write_w)(uint32_t addr, uint16_t val, void *p), void (*write_l)(uint32_t addr, uint32_t val, void *p), + uint8_t *exec, + uint32_t flags, void *p); void mem_mapping_set_handler(mem_mapping_t *mapping, uint8_t (*read_b)(uint32_t addr, void *p), @@ -44,10 +55,22 @@ void mem_mapping_set_handler(mem_mapping_t *mapping, void (*write_l)(uint32_t addr, uint32_t val, void *p)); void mem_mapping_set_p(mem_mapping_t *mapping, void *p); void mem_mapping_set_addr(mem_mapping_t *mapping, uint32_t base, uint32_t size); +void mem_mapping_set_exec(mem_mapping_t *mapping, uint8_t *exec); void mem_mapping_disable(mem_mapping_t *mapping); void mem_mapping_enable(mem_mapping_t *mapping); -void mem_bios_set_state(uint32_t base, uint32_t size, int read_ram, int write_ram); +void mem_set_mem_state(uint32_t base, uint32_t size, int state); + +#define MEM_READ_ANY 0x00 +#define MEM_READ_INTERNAL 0x10 +#define MEM_READ_EXTERNAL 0x20 +#define MEM_READ_MASK 0xf0 + +#define MEM_WRITE_ANY 0x00 +#define MEM_WRITE_INTERNAL 0x01 +#define MEM_WRITE_EXTERNAL 0x02 +#define MEM_WRITE_DISABLED 0x03 +#define MEM_WRITE_MASK 0x0f extern int mem_a20_alt; extern int mem_a20_key; @@ -68,6 +91,8 @@ uint8_t mem_read_bios(uint32_t addr, void *priv); uint16_t mem_read_biosw(uint32_t addr, void *priv); uint32_t mem_read_biosl(uint32_t addr, void *priv); -FILE *romfopen(char *fn, char *mode); +void mem_write_null(uint32_t addr, uint8_t val, void *p); +void mem_write_nullw(uint32_t addr, uint16_t val, void *p); +void mem_write_nulll(uint32_t addr, uint32_t val, void *p); -int mem_load_video_bios(); +FILE *romfopen(char *fn, char *mode); diff --git a/src/model.c b/src/model.c index eb20bfb..8d94136 100644 --- a/src/model.c +++ b/src/model.c @@ -78,12 +78,17 @@ MODEL models[] = {"AMI 386 clone", ROM_AMI386, { "Intel", cpus_i386, "AMD", cpus_Am386, "Cyrix", cpus_486SDLC}, 0, at_headland_init}, {"AMI 486 clone", ROM_AMI486, { "Intel", cpus_i486, "AMD", cpus_Am486, "Cyrix", cpus_Cx486}, 0, at_ali1429_init}, {"AMI WinBIOS 486", ROM_WIN486, { "Intel", cpus_i486, "AMD", cpus_Am486, "Cyrix", cpus_Cx486}, 0, at_ali1429_init}, - {"AMI WinBIOS 486 PCI", ROM_PCI486, { "Intel", cpus_i486, "AMD", cpus_Am486, "Cyrix", cpus_Cx486}, 0, at_um8881f_init}, +/* {"AMI WinBIOS 486 PCI", ROM_PCI486, { "Intel", cpus_i486, "AMD", cpus_Am486, "Cyrix", cpus_Cx486}, 0, at_um8881f_init},*/ {"Award SiS 496/497", ROM_SIS496, { "Intel", cpus_i486, "AMD", cpus_Am486, "Cyrix", cpus_Cx486}, 0, at_sis496_init}, {"Award 430VX PCI", ROM_430VX, { "IDT", cpus_WinChip, "", NULL, "", NULL}, 0, at_i430vx_init}, {"", -1, {"", 0, "", 0, "", 0}, 0} }; +int model_count() +{ + return (sizeof(models) / sizeof(MODEL)) - 1; +} + int model_getromset() { return models[model].id; diff --git a/src/model.h b/src/model.h index 9f42c5c..91e1ebd 100644 --- a/src/model.h +++ b/src/model.h @@ -15,6 +15,7 @@ extern MODEL models[]; extern int model; +int model_count(); int model_getromset(); int model_getmodel(int romset); char *model_getname(); diff --git a/src/pc.c b/src/pc.c index 2d70adb..1895eb2 100644 --- a/src/pc.c +++ b/src/pc.c @@ -85,6 +85,7 @@ void fatal(const char *format, ...) va_end(ap); fputs(buf,pclogf); fflush(pclogf); + dumppic(); dumpregs(); exit(-1); } @@ -206,9 +207,9 @@ void initpc() initvideo(); mem_init(); - mem_load_video_bios(); loadbios(); - + mem_add_bios(); + loaddisc(0,discfns[0]); loaddisc(1,discfns[1]); @@ -436,6 +437,9 @@ void loadconfig() model = get_config_int(NULL, "model", 14); + if (model >= model_count()) + model = model_count() - 1; + romset = model_getromset(); cpu_manufacturer = get_config_int(NULL, "cpu_manufacturer", 0); cpu = get_config_int(NULL, "cpu", 0); diff --git a/src/pc.rc b/src/pc.rc index 352767a..6f690bb 100644 --- a/src/pc.rc +++ b/src/pc.rc @@ -47,20 +47,20 @@ BEGIN END END -ConfigureDlg DIALOGEX 0, 0, 182, 240 +ConfigureDlg DIALOGEX 0, 0, 232, 240 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Configure PCem" FONT 8, "MS Sans Serif" BEGIN - DEFPUSHBUTTON "OK",IDOK,17,216,50,14, WS_TABSTOP - PUSHBUTTON "Cancel",IDCANCEL,71,216,50,14, WS_TABSTOP - COMBOBOX IDC_COMBO1,62,16,107,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP - COMBOBOX IDC_COMBOVID,62,36,107,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP - COMBOBOX IDC_COMBOCPUM,62,56,107,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP - COMBOBOX IDC_COMBO3,62,76,107,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP - COMBOBOX IDC_COMBOCHC,62,96,107,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP - COMBOBOX IDC_COMBOSPD,62,116,107,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP - COMBOBOX IDC_COMBOSND,62,136,107,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + DEFPUSHBUTTON "OK",IDOK,64,216,50,14, WS_TABSTOP + PUSHBUTTON "Cancel",IDCANCEL,128,216,50,14, WS_TABSTOP + COMBOBOX IDC_COMBO1,62,16,157,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_COMBOVID,62,36,157,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_COMBOCPUM,62,56,157,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_COMBO3,62,76,157,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_COMBOCHC,62,96,157,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_COMBOSPD,62,116,157,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_COMBOSND,62,136,157,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP EDITTEXT IDC_MEMTEXT, 62, 152, 36, 14, ES_AUTOHSCROLL | ES_NUMBER CONTROL "", IDC_MEMSPIN, UPDOWN_CLASS, UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_SETBUDDYINT, 98, 152, 12, 14 LTEXT "MB", IDC_STATIC, 98, 152, 40, 10 diff --git a/src/pci.h b/src/pci.h index eec1f33..f053f2f 100644 --- a/src/pci.h +++ b/src/pci.h @@ -1,3 +1,8 @@ void pci_init(); void pci_add_specific(int card, uint8_t (*read)(int func, int addr, void *priv), void (*write)(int func, int addr, uint8_t val, void *priv), void *priv); void pci_add(uint8_t (*read)(int func, int addr, void *priv), void (*write)(int func, int addr, uint8_t val, void *priv), void *priv); + +#define PCI_REG_COMMAND 0x04 + +#define PCI_COMMAND_IO 0x01 +#define PCI_COMMAND_MEM 0x02 diff --git a/src/rom.c b/src/rom.c index d04c960..87fc885 100644 --- a/src/rom.c +++ b/src/rom.c @@ -1,5 +1,7 @@ +#include #include #include "ibm.h" +#include "mem.h" #include "rom.h" FILE *romfopen(char *fn, char *mode) @@ -27,3 +29,97 @@ int rom_present(char *fn) } return 0; } + +static uint8_t rom_read(uint32_t addr, void *p) +{ + rom_t *rom = (rom_t *)p; +// pclog("rom_read : %08x %08x %02x\n", addr, rom->mask, rom->rom[addr & rom->mask]); + return rom->rom[addr & rom->mask]; +} +uint16_t rom_readw(uint32_t addr, void *p) +{ + rom_t *rom = (rom_t *)p; +// pclog("rom_readw: %08x %08x %04x\n", addr, rom->mask, *(uint16_t *)&rom->rom[addr & rom->mask]); + return *(uint16_t *)&rom->rom[addr & rom->mask]; +} +uint32_t rom_readl(uint32_t addr, void *p) +{ + rom_t *rom = (rom_t *)p; +// pclog("rom_readl: %08x %08x %08x\n", addr, rom->mask, *(uint32_t *)&rom->rom[addr & rom->mask]); + return *(uint32_t *)&rom->rom[addr & rom->mask]; +} + +int rom_init(rom_t *rom, char *fn, uint32_t address, int size, int mask, int file_offset, uint32_t flags) +{ + FILE *f = romfopen(fn, "rb"); + + if (!f) + { + pclog("ROM image not found : %s\n", fn); + return -1; + } + + rom->rom = malloc(size); + fseek(f, file_offset, SEEK_SET); + fread(rom->rom, size, 1, f); + fclose(f); + + rom->mask = mask; + + mem_mapping_add(&rom->mapping, address, size, rom_read, + rom_readw, + rom_readl, + mem_write_null, + mem_write_nullw, + mem_write_nulll, + rom->rom, + flags, + rom); + + return 0; +} + +int rom_init_interleaved(rom_t *rom, char *fn_low, char *fn_high, uint32_t address, int size, int mask, int file_offset, uint32_t flags) +{ + FILE *f_low = romfopen(fn_low, "rb"); + FILE *f_high = romfopen(fn_high, "rb"); + int c; + + if (!f_low || !f_high) + { + if (!f_low) + pclog("ROM image not found : %s\n", fn_low); + else + fclose(f_low); + if (!f_high) + pclog("ROM image not found : %s\n", fn_high); + else + fclose(f_high); + return -1; + } + + rom->rom = malloc(size); + fseek(f_low, file_offset, SEEK_SET); + fseek(f_high, file_offset, SEEK_SET); + for (c = 0; c < size; c += 2) + { + rom->rom[c] = getc(f_low); + rom->rom[c + 1] = getc(f_high); + } + fclose(f_high); + fclose(f_low); + + rom->mask = mask; + + mem_mapping_add(&rom->mapping, address, size, rom_read, + rom_readw, + rom_readl, + mem_write_null, + mem_write_nullw, + mem_write_nulll, + rom->rom, + flags, + rom); + + return 0; +} diff --git a/src/rom.h b/src/rom.h index 62624c1..06ace63 100644 --- a/src/rom.h +++ b/src/rom.h @@ -1,2 +1,12 @@ FILE *romfopen(char *fn, char *mode); int rom_present(char *fn); + +typedef struct rom_t +{ + uint8_t *rom; + uint32_t mask; + mem_mapping_t mapping; +} rom_t; + +int rom_init(rom_t *rom, char *fn, uint32_t address, int size, int mask, int file_offset, uint32_t flags); +int rom_init_interleaved(rom_t *rom, char *fn_low, char *fn_high, uint32_t address, int size, int mask, int file_offset, uint32_t flags); diff --git a/src/sis496.c b/src/sis496.c index d18cab3..51633b4 100644 --- a/src/sis496.c +++ b/src/sis496.c @@ -14,45 +14,32 @@ typedef struct sis496_t void sis496_recalcmapping(sis496_t *sis496) { - if (sis496->pci_conf[0x44] & 0x10) + int c; + + for (c = 0; c < 8; c++) { - if (sis496->pci_conf[0x45] & 0x01) - mem_bios_set_state(0xe0000, 0x08000, 1, 0); + uint32_t base = 0xc0000 + (c << 15); + if (sis496->pci_conf[0x44] & (1 << c)) + { + switch (sis496->pci_conf[0x45] & 3) + { + case 0: + mem_set_mem_state(base, 0x8000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); + break; + case 1: + mem_set_mem_state(base, 0x8000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + break; + case 2: + mem_set_mem_state(base, 0x8000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + case 3: + mem_set_mem_state(base, 0x8000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); + break; + } + } else - mem_bios_set_state(0xe0000, 0x08000, 1, 1); + mem_set_mem_state(base, 0x8000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); } - else - mem_bios_set_state(0xe0000, 0x08000, 0, 1); - - if (sis496->pci_conf[0x44] & 0x20) - { - if (sis496->pci_conf[0x45] & 0x01) - mem_bios_set_state(0xe8000, 0x08000, 1, 0); - else - mem_bios_set_state(0xe8000, 0x08000, 1, 1); - } - else - mem_bios_set_state(0xe8000, 0x08000, 0, 1); - - if (sis496->pci_conf[0x44] & 0x40) - { - if (sis496->pci_conf[0x45] & 0x01) - mem_bios_set_state(0xf0000, 0x08000, 1, 0); - else - mem_bios_set_state(0xf0000, 0x08000, 1, 1); - } - else - mem_bios_set_state(0xf0000, 0x08000, 0, 1); - - if (sis496->pci_conf[0x44] & 0x80) - { - if (sis496->pci_conf[0x45] & 0x01) - mem_bios_set_state(0xf8000, 0x08000, 1, 0); - else - mem_bios_set_state(0xf8000, 0x08000, 1, 1); - } - else - mem_bios_set_state(0xf8000, 0x08000, 0, 1); flushmmucache(); shadowbios = (sis496->pci_conf[0x44] & 0xf0); @@ -61,7 +48,7 @@ void sis496_recalcmapping(sis496_t *sis496) void sis496_write(int func, int addr, uint8_t val, void *p) { sis496_t *sis496 = (sis496_t *)p; -//pclog("sis496_write : addr=%02x val=%02x\n", addr, val); + //pclog("sis496_write : addr=%02x val=%02x\n", addr, val); switch (addr) { case 0x44: /*Shadow configure*/ @@ -72,8 +59,6 @@ void sis496_write(int func, int addr, uint8_t val, void *p) } break; case 0x45: /*Shadow configure*/ - //if (val == 3) - // output = 3; if ((sis496->pci_conf[0x45] & val) ^ 0x01) { sis496->pci_conf[0x45] = val; diff --git a/src/sound_gus.c b/src/sound_gus.c index 03b0fed..b801923 100644 --- a/src/sound_gus.c +++ b/src/sound_gus.c @@ -638,8 +638,8 @@ uint8_t readgus(uint16_t addr, void *p) val = 0xff; break; - default: - fatal("Bad GUS global low read %02X\n",gus->global); +// default: +// fatal("Bad GUS global low read %02X\n",gus->global); } break; case 0x345: /*Global high*/ @@ -693,8 +693,8 @@ uint8_t readgus(uint16_t addr, void *p) val = 0xff; break; - default: - fatal("Bad GUS global high read %02X\n",gus->global); +// default: +// fatal("Bad GUS global high read %02X\n",gus->global); } break; case 0x346: return 0xff; diff --git a/src/um8881f.c b/src/um8881f.c index a045797..b469bbd 100644 --- a/src/um8881f.c +++ b/src/um8881f.c @@ -10,28 +10,29 @@ static uint8_t card_18[256]; void um8881f_write(int func, int addr, uint8_t val, void *priv) { +// pclog("um8881f_write : addr=%02x val=%02x %04x:%04x\n", addr, val, CS, pc); if (addr == 0x54) { - if ((card_16[0x54] ^ val) & 0x01) +/* if ((card_16[0x54] ^ val) & 0x01) { if (val & 1) mem_bios_set_state(0xe0000, 0x10000, 1, 1); else mem_bios_set_state(0xe0000, 0x10000, 0, 0); - } + }*/ flushmmucache_nopc(); } if (addr == 0x55) { if ((card_16[0x55] ^ val) & 0xc0) { - switch (val & 0xc0) +/* switch (val & 0xc0) { case 0x00: mem_bios_set_state(0xf0000, 0x10000, 0, 1); break; case 0x40: mem_bios_set_state(0xf0000, 0x10000, 0, 0); break; case 0x80: mem_bios_set_state(0xf0000, 0x10000, 1, 1); break; case 0xc0: mem_bios_set_state(0xf0000, 0x10000, 1, 0); break; - } + }*/ shadowbios = val & 0x80; shadowbios_write = !(val & 0x40); flushmmucache_nopc(); diff --git a/src/vid_ati18800.c b/src/vid_ati18800.c index 656d1bd..fa40d74 100644 --- a/src/vid_ati18800.c +++ b/src/vid_ati18800.c @@ -4,6 +4,7 @@ #include "device.h" #include "io.h" #include "mem.h" +#include "rom.h" #include "video.h" #include "vid_ati18800.h" #include "vid_ati_eeprom.h" @@ -13,6 +14,8 @@ typedef struct ati18800_t { svga_t svga; ati_eeprom_t eeprom; + + rom_t bios_rom; uint8_t regs[256]; int index; @@ -122,6 +125,8 @@ void *ati18800_init() ati18800_t *ati18800 = malloc(sizeof(ati18800_t)); memset(ati18800, 0, sizeof(ati18800_t)); + rom_init(&ati18800->bios_rom, "roms/vgaedge16.vbi", 0xc0000, 0x8000, 0x7fff, 0, 0); + svga_init(&ati18800->svga, ati18800, 1 << 19, /*512kb*/ NULL, ati18800_in, ati18800_out, @@ -137,6 +142,11 @@ void *ati18800_init() return ati18800; } +static int ati18800_available() +{ + return rom_present("roms/vgaedge16.vbi"); +} + void ati18800_close(void *p) { ati18800_t *ati18800 = (ati18800_t *)p; @@ -173,7 +183,7 @@ device_t ati18800_device = 0, ati18800_init, ati18800_close, - NULL, + ati18800_available, ati18800_speed_changed, ati18800_force_redraw, ati18800_add_status_info diff --git a/src/vid_ati28800.c b/src/vid_ati28800.c index 19361a2..b68e5d2 100644 --- a/src/vid_ati28800.c +++ b/src/vid_ati28800.c @@ -4,6 +4,7 @@ #include "device.h" #include "io.h" #include "mem.h" +#include "rom.h" #include "video.h" #include "vid_ati28800.h" #include "vid_ati_eeprom.h" @@ -15,6 +16,8 @@ typedef struct ati28800_t svga_t svga; ati_eeprom_t eeprom; + rom_t bios_rom; + uint8_t regs[256]; int index; } ati28800_t; @@ -143,6 +146,8 @@ void *ati28800_init() ati28800_t *ati28800 = malloc(sizeof(ati28800_t)); memset(ati28800, 0, sizeof(ati28800_t)); + rom_init(&ati28800->bios_rom, "roms/bios.bin", 0xc0000, 0x8000, 0x7fff, 0, 0); + svga_init(&ati28800->svga, ati28800, 1 << 19, /*512kb*/ ati28800_recalctimings, ati28800_in, ati28800_out, @@ -158,6 +163,11 @@ void *ati28800_init() return ati28800; } +static int ati28800_available() +{ + return rom_present("roms/bios.bin"); +} + void ati28800_close(void *p) { ati28800_t *ati28800 = (ati28800_t *)p; @@ -194,7 +204,7 @@ device_t ati28800_device = 0, ati28800_init, ati28800_close, - NULL, + ati28800_available, ati28800_speed_changed, ati28800_force_redraw, ati28800_add_status_info diff --git a/src/vid_ati_mach64.c b/src/vid_ati_mach64.c index 03a44fd..4270f1a 100644 --- a/src/vid_ati_mach64.c +++ b/src/vid_ati_mach64.c @@ -5,6 +5,7 @@ #include "io.h" #include "mem.h" #include "pci.h" +#include "rom.h" #include "video.h" #include "vid_svga.h" #include "vid_ati68860_ramdac.h" @@ -25,8 +26,12 @@ typedef struct mach64_t ics2595_t ics2595; svga_t svga; + rom_t bios_rom; + uint8_t regs[256]; int index; + + uint8_t pci_regs[256]; int bank_r[2]; int bank_w[2]; @@ -338,6 +343,16 @@ void mach64_updatemapping(mach64_t *mach64) { svga_t *svga = &mach64->svga; + if (!(mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) + { + pclog("Update mapping - PCI disabled\n"); + mem_mapping_disable(&svga->mapping); + mem_mapping_disable(&mach64->linear_mapping); + mem_mapping_disable(&mach64->mmio_mapping); + mem_mapping_disable(&mach64->mmio_linear_mapping); + return; + } + mem_mapping_disable(&mach64->mmio_mapping); // pclog("Write mapping %02X\n", val); switch (svga->gdcreg[6] & 0xc) @@ -1835,9 +1850,13 @@ uint16_t mach64_ext_inw(uint16_t port, void *p) switch (port) { default: +#ifdef MACH64_DEBUG pclog(" "); +#endif ret = mach64_ext_inb(port, p); +#ifdef MACH64_DEBUG pclog(" "); +#endif ret |= (mach64_ext_inb(port + 1, p) << 8); break; } @@ -1860,9 +1879,13 @@ uint32_t mach64_ext_inl(uint16_t port, void *p) break; default: +#ifdef MACH64_DEBUG pclog(" "); +#endif ret = mach64_ext_inw(port, p); +#ifdef MACH64_DEBUG pclog(" "); +#endif ret |= (mach64_ext_inw(port + 2, p) << 16); break; } @@ -2053,6 +2076,42 @@ void mach64_hwcursor_draw(svga_t *svga, int displine) svga->hwcursor_latch.addr += 16; } +static void mach64_io_remove(mach64_t *mach64) +{ + int c; + + io_removehandler(0x03c0, 0x0020, mach64_in, NULL, NULL, mach64_out, NULL, NULL, mach64); + + for (c = 0; c < 8; c++) + { + io_removehandler((c * 0x1000) + 0x2ec, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64); + io_removehandler((c * 0x1000) + 0x6ec, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64); + io_removehandler((c * 0x1000) + 0xaec, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64); + io_removehandler((c * 0x1000) + 0xeec, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64); + } + + io_removehandler(0x01ce, 0x0002, mach64_in, NULL, NULL, mach64_out, NULL, NULL, mach64); +} + +static void mach64_io_set(mach64_t *mach64) +{ + int c; + + mach64_io_remove(mach64); + + io_sethandler(0x03c0, 0x0020, mach64_in, NULL, NULL, mach64_out, NULL, NULL, mach64); + + for (c = 0; c < 8; c++) + { + io_sethandler((c * 0x1000) + 0x2ec, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64); + io_sethandler((c * 0x1000) + 0x6ec, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64); + io_sethandler((c * 0x1000) + 0xaec, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64); + io_sethandler((c * 0x1000) + 0xeec, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64); + } + + io_sethandler(0x01ce, 0x0002, mach64_in, NULL, NULL, mach64_out, NULL, NULL, mach64); +} + uint8_t mach64_pci_read(int func, int addr, void *p) { mach64_t *mach64 = (mach64_t *)p; @@ -2068,7 +2127,8 @@ uint8_t mach64_pci_read(int func, int addr, void *p) case 0x02: return 'X'; /*88800GX*/ case 0x03: return 'G'; - case 0x04: return 0x03; /*Respond to IO and memory accesses*/ + case PCI_REG_COMMAND: + return mach64->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ case 0x07: return 1 << 1; /*Medium DEVSEL timing*/ @@ -2083,10 +2143,10 @@ uint8_t mach64_pci_read(int func, int addr, void *p) case 0x12: return mach64->linear_base >> 16; case 0x13: return mach64->linear_base >> 24; - case 0x30: return 0x01; /*BIOS ROM address*/ + case 0x30: return mach64->pci_regs[0x30] & 0x01; /*BIOS ROM address*/ case 0x31: return 0x00; - case 0x32: return 0x0C; - case 0x33: return 0x00; + case 0x32: return mach64->pci_regs[0x32]; + case 0x33: return mach64->pci_regs[0x33]; } return 0; } @@ -2099,6 +2159,15 @@ void mach64_pci_write(int func, int addr, uint8_t val, void *p) switch (addr) { + case PCI_REG_COMMAND: + mach64->pci_regs[PCI_REG_COMMAND] = val & 0x27; + if (val & PCI_COMMAND_IO) + mach64_io_set(mach64); + else + mach64_io_remove(mach64); + mach64_updatemapping(mach64); + break; + case 0x12: mach64->linear_base = (mach64->linear_base & 0xff000000) | ((val & 0x80) << 16); mach64_updatemapping(mach64); @@ -2107,6 +2176,21 @@ void mach64_pci_write(int func, int addr, uint8_t val, void *p) mach64->linear_base = (mach64->linear_base & 0x800000) | (val << 24); mach64_updatemapping(mach64); break; + + case 0x30: case 0x32: case 0x33: + mach64->pci_regs[addr] = val; + if (mach64->pci_regs[0x30] & 0x01) + { + uint32_t addr = (mach64->pci_regs[0x32] << 16) | (mach64->pci_regs[0x33] << 24); + pclog("Mach64 bios_rom enabled at %08x\n", addr); + mem_mapping_set_addr(&mach64->bios_rom.mapping, addr, 0x8000); + } + else + { + pclog("Mach64 bios_rom disabled\n"); + mem_mapping_disable(&mach64->bios_rom.mapping); + } + return; } } @@ -2121,24 +2205,23 @@ void *mach64gx_init() mach64_in, mach64_out, mach64_hwcursor_draw); - mem_mapping_add(&mach64->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, &mach64->svga); - mem_mapping_add(&mach64->mmio_linear_mapping, 0, 0, mach64_ext_readb, mach64_ext_readw, mach64_ext_readl, mach64_ext_writeb, mach64_ext_writew, mach64_ext_writel, mach64); - mem_mapping_add(&mach64->mmio_mapping, 0xbc000, 0x04000, mach64_ext_readb, mach64_ext_readw, mach64_ext_readl, mach64_ext_writeb, mach64_ext_writew, mach64_ext_writel, mach64); + rom_init(&mach64->bios_rom, "roms/mach64gx/bios.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + if (PCI) + mem_mapping_disable(&mach64->bios_rom.mapping); + + mem_mapping_add(&mach64->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL, 0, &mach64->svga); + mem_mapping_add(&mach64->mmio_linear_mapping, 0, 0, mach64_ext_readb, mach64_ext_readw, mach64_ext_readl, mach64_ext_writeb, mach64_ext_writew, mach64_ext_writel, NULL, 0, mach64); + mem_mapping_add(&mach64->mmio_mapping, 0xbc000, 0x04000, mach64_ext_readb, mach64_ext_readw, mach64_ext_readl, mach64_ext_writeb, mach64_ext_writew, mach64_ext_writel, NULL, 0, mach64); mem_mapping_disable(&mach64->mmio_mapping); - io_sethandler(0x03c0, 0x0020, mach64_in, NULL, NULL, mach64_out, NULL, NULL, mach64); - - for (c = 0; c < 8; c++) - { - io_sethandler((c * 0x1000) + 0x2ec, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64); - io_sethandler((c * 0x1000) + 0x6ec, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64); - io_sethandler((c * 0x1000) + 0xaec, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64); - io_sethandler((c * 0x1000) + 0xeec, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64); - } - - io_sethandler(0x01ce, 0x0002, mach64_in, NULL, NULL, mach64_out, NULL, NULL, mach64); + mach64_io_set(mach64); pci_add(mach64_pci_read, mach64_pci_write, mach64); + + mach64->pci_regs[PCI_REG_COMMAND] = 3; + mach64->pci_regs[0x30] = 0x00; + mach64->pci_regs[0x32] = 0x0c; + mach64->pci_regs[0x33] = 0x00; ati_eeprom_load(&mach64->eeprom, "mach64.nvr", 1); @@ -2149,6 +2232,11 @@ void *mach64gx_init() return mach64; } +int mach64gx_available() +{ + return rom_present("roms/mach64gx/bios.bin"); +} + void mach64_close(void *p) { mach64_t *mach64 = (mach64_t *)p; @@ -2225,7 +2313,7 @@ device_t mach64gx_device = 0, mach64gx_init, mach64_close, - NULL, + mach64gx_available, mach64_speed_changed, mach64_force_redraw, mach64_add_status_info diff --git a/src/vid_cga.c b/src/vid_cga.c index 5982eb7..6c3293a 100644 --- a/src/vid_cga.c +++ b/src/vid_cga.c @@ -499,7 +499,7 @@ void *cga_standalone_init() q_filt[c] = 512.0 * sin((3.14 * (cga_tint + c * 4) / 16.0) - 33.0 / 180.0); } timer_add(cga_poll, &cga->vidtime, TIMER_ALWAYS_ENABLED, cga); - mem_mapping_add(&cga->mapping, 0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, cga); + mem_mapping_add(&cga->mapping, 0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL, 0, cga); io_sethandler(0x03d0, 0x0010, cga_in, NULL, NULL, cga_out, NULL, NULL, cga); return cga; } diff --git a/src/vid_cl5429.c b/src/vid_cl5429.c index a60dab0..dc4264c 100644 --- a/src/vid_cl5429.c +++ b/src/vid_cl5429.c @@ -4,6 +4,7 @@ #include "device.h" #include "io.h" #include "mem.h" +#include "rom.h" #include "video.h" #include "vid_cl5429.h" #include "vid_svga.h" @@ -16,6 +17,8 @@ typedef struct gd5429_t svga_t svga; + rom_t bios_rom; + uint32_t bank[2]; uint32_t mask; @@ -816,6 +819,8 @@ void *gd5429_init() svga_t *svga = &gd5429->svga; memset(gd5429, 0, sizeof(gd5429_t)); + rom_init(&gd5429->bios_rom, "roms/5429.vbi", 0xc0000, 0x8000, 0x7fff, 0, 0); + svga_init(&gd5429->svga, gd5429, 1 << 21, /*2mb*/ gd5429_recalctimings, gd5429_in, gd5429_out, @@ -824,7 +829,7 @@ void *gd5429_init() mem_mapping_set_handler(&gd5429->svga.mapping, gd5429_read, NULL, NULL, gd5429_write, NULL, NULL); mem_mapping_set_p(&gd5429->svga.mapping, gd5429); - mem_mapping_add(&gd5429->mmio_mapping, 0, 0, gd5429_mmio_read, NULL, NULL, gd5429_mmio_write, NULL, NULL, gd5429); + mem_mapping_add(&gd5429->mmio_mapping, 0, 0, gd5429_mmio_read, NULL, NULL, gd5429_mmio_write, NULL, NULL, NULL, 0, gd5429); io_sethandler(0x03c0, 0x0020, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429); @@ -836,6 +841,11 @@ void *gd5429_init() return gd5429; } +static int gd5429_available() +{ + return rom_present("roms/5429.vbi"); +} + void gd5429_close(void *p) { gd5429_t *gd5429 = (gd5429_t *)p; @@ -872,7 +882,7 @@ device_t gd5429_device = DEVICE_NOT_WORKING, gd5429_init, gd5429_close, - NULL, + gd5429_available, gd5429_speed_changed, gd5429_force_redraw, gd5429_add_status_info diff --git a/src/vid_ega.c b/src/vid_ega.c index 734994d..388f618 100644 --- a/src/vid_ega.c +++ b/src/vid_ega.c @@ -4,6 +4,7 @@ #include "device.h" #include "io.h" #include "mem.h" +#include "rom.h" #include "timer.h" #include "video.h" #include "vid_ega.h" @@ -810,15 +811,35 @@ void *ega_standalone_init() int c, d, e; ega_t *ega = malloc(sizeof(ega_t)); memset(ega, 0, sizeof(ega_t)); + + rom_init(&ega->bios_rom, "roms/ibm_6277356_ega_card_u44_27128.bin", 0xc0000, 0x8000, 0x7fff, 0, 0); + + if (ega->bios_rom.rom[0x3ffe] == 0xaa && ega->bios_rom.rom[0x3fff] == 0x55) + { + int c; + pclog("Read EGA ROM in reverse\n"); + + for (c = 0; c < 0x2000; c++) + { + uint8_t temp = ega->bios_rom.rom[c]; + ega->bios_rom.rom[c] = ega->bios_rom.rom[0x3fff - c]; + ega->bios_rom.rom[0x3fff - c] = temp; + } + } ega_init(ega); - mem_mapping_add(&ega->mapping, 0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, ega); + mem_mapping_add(&ega->mapping, 0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL, 0, ega); timer_add(ega_poll, &ega->vidtime, TIMER_ALWAYS_ENABLED, ega); io_sethandler(0x03a0, 0x0040, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); return ega; } +static int ega_standalone_available() +{ + return rom_present("roms/ibm_6277356_ega_card_u44_27128.bin"); +} + void ega_close(void *p) { ega_t *ega = (ega_t *)p; @@ -840,7 +861,7 @@ device_t ega_device = 0, ega_standalone_init, ega_close, - NULL, + ega_standalone_available, ega_speed_changed, NULL, NULL diff --git a/src/vid_ega.h b/src/vid_ega.h index f8039c5..47de8f4 100644 --- a/src/vid_ega.h +++ b/src/vid_ega.h @@ -2,6 +2,8 @@ typedef struct ega_t { mem_mapping_t mapping; + rom_t bios_rom; + uint8_t crtcreg; uint8_t crtc[32]; uint8_t gdcreg[16]; diff --git a/src/vid_et4000.c b/src/vid_et4000.c index 50395e7..e6dd38d 100644 --- a/src/vid_et4000.c +++ b/src/vid_et4000.c @@ -4,6 +4,7 @@ #include "device.h" #include "io.h" #include "mem.h" +#include "rom.h" #include "video.h" #include "vid_svga.h" #include "vid_unk_ramdac.h" @@ -15,6 +16,8 @@ typedef struct et4000_t svga_t svga; unk_ramdac_t ramdac; + rom_t bios_rom; + uint8_t banking; } et4000_t; @@ -129,7 +132,9 @@ void *et4000_init() { et4000_t *et4000 = malloc(sizeof(et4000_t)); memset(et4000, 0, sizeof(et4000_t)); - + + rom_init(&et4000->bios_rom, "roms/et4000.bin", 0xc0000, 0x8000, 0x7fff, 0, 0); + io_sethandler(0x03c0, 0x0020, et4000_in, NULL, NULL, et4000_out, NULL, NULL, et4000); svga_init(&et4000->svga, et4000, 1 << 20, /*1mb*/ @@ -140,6 +145,11 @@ void *et4000_init() return et4000; } +static int et4000_available() +{ + return rom_present("roms/et4000.bin"); +} + void et4000_close(void *p) { et4000_t *et4000 = (et4000_t *)p; diff --git a/src/vid_et4000w32.c b/src/vid_et4000w32.c index 129f808..2bffd96 100644 --- a/src/vid_et4000w32.c +++ b/src/vid_et4000w32.c @@ -9,6 +9,7 @@ #include "io.h" #include "mem.h" #include "pci.h" +#include "rom.h" #include "video.h" #include "vid_svga.h" #include "vid_icd2061.h" @@ -19,6 +20,8 @@ typedef struct et4000w32p_t mem_mapping_t linear_mapping; mem_mapping_t mmu_mapping; + rom_t bios_rom; + svga_t svga; stg_ramdac_t ramdac; icd2061_t icd2061; @@ -28,7 +31,9 @@ typedef struct et4000w32p_t uint32_t linearbase, linearbase_old; uint8_t banking, banking2; - + + uint8_t pci_regs[256]; + /*Accelerator*/ struct { @@ -260,6 +265,15 @@ void et4000w32p_recalcmapping(et4000w32p_t *et4000) { svga_t *svga = &et4000->svga; + if (!(et4000->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) + { + pclog("Update mapping - PCI disabled\n"); + mem_mapping_disable(&svga->mapping); + mem_mapping_disable(&et4000->linear_mapping); + mem_mapping_disable(&et4000->mmu_mapping); + return; + } + pclog("recalcmapping %p\n", svga); if (svga->crtc[0x36] & 0x10) /*Linear frame buffer*/ { @@ -887,6 +901,36 @@ void et4000w32p_hwcursor_draw(svga_t *svga, int displine) svga->hwcursor_latch.addr += 16; } +static void et4000w32p_io_remove(et4000w32p_t *et4000) +{ + io_removehandler(0x03c0, 0x0020, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); + + io_removehandler(0x210A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); + io_removehandler(0x211A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); + io_removehandler(0x212A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); + io_removehandler(0x213A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); + io_removehandler(0x214A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); + io_removehandler(0x215A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); + io_removehandler(0x216A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); + io_removehandler(0x217A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); +} + +static void et4000w32p_io_set(et4000w32p_t *et4000) +{ + et4000w32p_io_remove(et4000); + + io_sethandler(0x03c0, 0x0020, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); + + io_sethandler(0x210A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); + io_sethandler(0x211A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); + io_sethandler(0x212A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); + io_sethandler(0x213A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); + io_sethandler(0x214A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); + io_sethandler(0x215A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); + io_sethandler(0x216A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); + io_sethandler(0x217A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); +} + uint8_t et4000w32p_pci_read(int func, int addr, void *p) { et4000w32p_t *et4000 = (et4000w32p_t *)p; @@ -902,7 +946,8 @@ uint8_t et4000w32p_pci_read(int func, int addr, void *p) case 0x02: return 0x06; /*ET4000W32p Rev D*/ case 0x03: return 0x32; - case 0x04: return 0x03; /*Respond to IO and memory accesses*/ + case PCI_REG_COMMAND: + return et4000->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ case 0x07: return 1 << 1; /*Medium DEVSEL timing*/ @@ -917,10 +962,10 @@ uint8_t et4000w32p_pci_read(int func, int addr, void *p) case 0x12: return svga->crtc[0x5a] & 0x80; case 0x13: return svga->crtc[0x59]; - case 0x30: return 0x01; /*BIOS ROM address*/ + case 0x30: return et4000->pci_regs[0x30] & 0x01; /*BIOS ROM address*/ case 0x31: return 0x00; - case 0x32: return 0x0C; - case 0x33: return 0x00; + case 0x32: return et4000->pci_regs[0x32]; + case 0x33: return et4000->pci_regs[0x33]; } return 0; } @@ -931,10 +976,34 @@ void et4000w32p_pci_write(int func, int addr, uint8_t val, void *p) switch (addr) { + case PCI_REG_COMMAND: + et4000->pci_regs[PCI_REG_COMMAND] = val & 0x27; + if (val & PCI_COMMAND_IO) + et4000w32p_io_set(et4000); + else + et4000w32p_io_remove(et4000); + et4000w32p_recalcmapping(et4000); + break; + case 0x13: et4000->linearbase = val << 24; et4000w32p_recalcmapping(et4000); break; + + case 0x30: case 0x32: case 0x33: + et4000->pci_regs[addr] = val; + if (et4000->pci_regs[0x30] & 0x01) + { + uint32_t addr = (et4000->pci_regs[0x32] << 16) | (et4000->pci_regs[0x33] << 24); + pclog("ET4000 bios_rom enabled at %08x\n", addr); + mem_mapping_set_addr(&et4000->bios_rom.mapping, addr, 0x8000); + } + else + { + pclog("ET4000 bios_rom disabled\n"); + mem_mapping_disable(&et4000->bios_rom.mapping); + } + return; } } @@ -948,25 +1017,31 @@ void *et4000w32p_init() et4000w32p_in, et4000w32p_out, et4000w32p_hwcursor_draw); - mem_mapping_add(&et4000->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, &et4000->svga); - mem_mapping_add(&et4000->mmu_mapping, 0, 0, et4000w32p_mmu_read, NULL, NULL, et4000w32p_mmu_write, NULL, NULL, et4000); + rom_init(&et4000->bios_rom, "roms/et4000w32.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + if (PCI) + mem_mapping_disable(&et4000->bios_rom.mapping); - io_sethandler(0x03c0, 0x0020, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); + mem_mapping_add(&et4000->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL, 0, &et4000->svga); + mem_mapping_add(&et4000->mmu_mapping, 0, 0, et4000w32p_mmu_read, NULL, NULL, et4000w32p_mmu_write, NULL, NULL, NULL, 0, et4000); - io_sethandler(0x210A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); - io_sethandler(0x211A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); - io_sethandler(0x212A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); - io_sethandler(0x213A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); - io_sethandler(0x214A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); - io_sethandler(0x215A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); - io_sethandler(0x216A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); - io_sethandler(0x217A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); + et4000w32p_io_set(et4000); pci_add(et4000w32p_pci_read, et4000w32p_pci_write, et4000); + + et4000->pci_regs[0x04] = 7; + + et4000->pci_regs[0x30] = 0x00; + et4000->pci_regs[0x32] = 0x0c; + et4000->pci_regs[0x33] = 0x00; return et4000; } +int et4000w32p_available() +{ + return rom_present("roms/et4000w32.bin"); +} + void et4000w32p_close(void *p) { et4000w32p_t *et4000 = (et4000w32p_t *)p; @@ -1003,7 +1078,7 @@ device_t et4000w32p_device = 0, et4000w32p_init, et4000w32p_close, - NULL, + et4000w32p_available, et4000w32p_speed_changed, et4000w32p_force_redraw, et4000w32p_add_status_info diff --git a/src/vid_hercules.c b/src/vid_hercules.c index 68343e3..b9832f0 100644 --- a/src/vid_hercules.c +++ b/src/vid_hercules.c @@ -313,7 +313,7 @@ void *hercules_init() hercules->vram = malloc(0x10000); timer_add(hercules_poll, &hercules->vidtime, TIMER_ALWAYS_ENABLED, hercules); - mem_mapping_add(&hercules->mapping, 0xb0000, 0x08000, hercules_read, NULL, NULL, hercules_write, NULL, NULL, hercules); + mem_mapping_add(&hercules->mapping, 0xb0000, 0x08000, hercules_read, NULL, NULL, hercules_write, NULL, NULL, NULL, 0, hercules); io_sethandler(0x03b0, 0x0010, hercules_in, NULL, NULL, hercules_out, NULL, NULL, hercules); for (c = 0; c < 256; c++) diff --git a/src/vid_mda.c b/src/vid_mda.c index 43db3a5..3897624 100644 --- a/src/vid_mda.c +++ b/src/vid_mda.c @@ -270,7 +270,7 @@ void *mda_init() mda->vram = malloc(0x1000); timer_add(mda_poll, &mda->vidtime, TIMER_ALWAYS_ENABLED, mda); - mem_mapping_add(&mda->mapping, 0xb0000, 0x08000, mda_read, NULL, NULL, mda_write, NULL, NULL, mda); + mem_mapping_add(&mda->mapping, 0xb0000, 0x08000, mda_read, NULL, NULL, mda_write, NULL, NULL, NULL, 0, mda); io_sethandler(0x03b0, 0x0010, mda_in, NULL, NULL, mda_out, NULL, NULL, mda); for (c = 0; c < 256; c++) diff --git a/src/vid_olivetti_m24.c b/src/vid_olivetti_m24.c index 73bc128..aadfe9b 100644 --- a/src/vid_olivetti_m24.c +++ b/src/vid_olivetti_m24.c @@ -459,7 +459,7 @@ void *m24_init() m24->vram = malloc(0x8000); timer_add(m24_poll, &m24->vidtime, TIMER_ALWAYS_ENABLED, m24); - mem_mapping_add(&m24->mapping, 0xb8000, 0x08000, m24_read, NULL, NULL, m24_write, NULL, NULL, m24); + mem_mapping_add(&m24->mapping, 0xb8000, 0x08000, m24_read, NULL, NULL, m24_write, NULL, NULL, NULL, 0, m24); io_sethandler(0x03d0, 0x0010, m24_in, NULL, NULL, m24_out, NULL, NULL, m24); return m24; } diff --git a/src/vid_oti067.c b/src/vid_oti067.c index 0f00854..939d2fa 100644 --- a/src/vid_oti067.c +++ b/src/vid_oti067.c @@ -4,6 +4,7 @@ #include "device.h" #include "io.h" #include "mem.h" +#include "rom.h" #include "video.h" #include "vid_oti067.h" #include "vid_svga.h" @@ -12,6 +13,8 @@ typedef struct oti067_t { svga_t svga; + rom_t bios_rom; + int index; uint8_t regs[32]; } oti067_t; @@ -110,11 +113,13 @@ void oti067_recalctimings(svga_t *svga) svga->interlace = oti067->regs[0x14] & 0x80; } -void *oti067_init() +void *oti067_common_init(char *bios_fn) { oti067_t *oti067 = malloc(sizeof(oti067_t)); memset(oti067, 0, sizeof(oti067_t)); + rom_init(&oti067->bios_rom, bios_fn, 0xc0000, 0x8000, 0x7fff, 0, 0); + svga_init(&oti067->svga, oti067, 1 << 19, /*512kb*/ oti067_recalctimings, oti067_in, oti067_out, @@ -126,6 +131,26 @@ void *oti067_init() return oti067; } +void *oti067_init() +{ + return oti067_common_init("roms/oti067/bios.bin"); +} + +void *oti067_acer386_init() +{ + oti067_t *oti067 = oti067_common_init("roms/acer386/oti067.bin"); + + if (oti067) + oti067->bios_rom.rom[0x5d] = 0x74; + + return oti067; +} + +static int oti067_available() +{ + return rom_present("roms/oti067/bios.bin"); +} + void oti067_close(void *p) { oti067_t *oti067 = (oti067_t *)p; @@ -162,7 +187,18 @@ device_t oti067_device = 0, oti067_init, oti067_close, - NULL, + oti067_available, + oti067_speed_changed, + oti067_force_redraw, + oti067_add_status_info +}; +device_t oti067_acer386_device = +{ + "Oak OTI-067 (Acermate 386SX/25N)", + 0, + oti067_acer386_init, + oti067_close, + oti067_available, oti067_speed_changed, oti067_force_redraw, oti067_add_status_info diff --git a/src/vid_oti067.h b/src/vid_oti067.h index 3e28595..81d4358 100644 --- a/src/vid_oti067.h +++ b/src/vid_oti067.h @@ -1 +1,2 @@ extern device_t oti067_device; +extern device_t oti067_acer386_device; diff --git a/src/vid_paradise.c b/src/vid_paradise.c index 7fbd2db..5d75a99 100644 --- a/src/vid_paradise.c +++ b/src/vid_paradise.c @@ -7,6 +7,7 @@ #include "ibm.h" #include "device.h" #include "mem.h" +#include "rom.h" #include "video.h" #include "vid_paradise.h" #include "vid_svga.h" @@ -17,6 +18,8 @@ typedef struct paradise_t { svga_t svga; + rom_t bios_rom; + enum { PVGA1A = 0, @@ -312,6 +315,38 @@ void *paradise_wd90c11_init() return paradise; } +static void *paradise_pvga1a_pc2086_init() +{ + paradise_t *paradise = paradise_pvga1a_init(); + + if (paradise) + rom_init(¶dise->bios_rom, "roms/pc2086/40186.ic171", 0xc0000, 0x8000, 0x7fff, 0, 0); + + return paradise; +} +static void *paradise_pvga1a_pc3086_init() +{ + paradise_t *paradise = paradise_pvga1a_init(); + + if (paradise) + rom_init(¶dise->bios_rom, "roms/pc3086/c000.bin", 0xc0000, 0x8000, 0x7fff, 0, 0); + + return paradise; +} + +static void *paradise_wd90c11_megapc_init() +{ + paradise_t *paradise = paradise_wd90c11_init(); + + if (paradise) + rom_init_interleaved(¶dise->bios_rom, + "roms/megapc/41651-bios lo.u18", + "roms/megapc/211253-bios hi.u19", + 0xc0000, 0x8000, 0x7fff, 0, 0); + + return paradise; +} + void paradise_close(void *p) { paradise_t *paradise = (paradise_t *)p; @@ -342,22 +377,33 @@ int paradise_add_status_info(char *s, int max_len, void *p) return svga_add_status_info(s, max_len, ¶dise->svga); } -device_t paradise_pvga1a_device = +device_t paradise_pvga1a_pc2086_device = { - "Paradise PVGA1A", + "Paradise PVGA1A (Amstrad PC2086)", 0, - paradise_pvga1a_init, + paradise_pvga1a_pc2086_init, paradise_close, NULL, paradise_speed_changed, paradise_force_redraw, paradise_add_status_info }; -device_t paradise_wd90c11_device = +device_t paradise_pvga1a_pc3086_device = { - "Paradise WD90C11", + "Paradise PVGA1A (Amstrad PC3086)", 0, - paradise_wd90c11_init, + paradise_pvga1a_pc3086_init, + paradise_close, + NULL, + paradise_speed_changed, + paradise_force_redraw, + paradise_add_status_info +}; +device_t paradise_wd90c11_megapc_device = +{ + "Paradise WD90C11 (Amstrad MegaPC)", + 0, + paradise_wd90c11_megapc_init, paradise_close, NULL, paradise_speed_changed, diff --git a/src/vid_paradise.h b/src/vid_paradise.h index b791d46..e25d5b3 100644 --- a/src/vid_paradise.h +++ b/src/vid_paradise.h @@ -1,2 +1,3 @@ -extern device_t paradise_pvga1a_device; -extern device_t paradise_wd90c11_device; +extern device_t paradise_pvga1a_pc2086_device; +extern device_t paradise_pvga1a_pc3086_device; +extern device_t paradise_wd90c11_megapc_device; diff --git a/src/vid_pc1512.c b/src/vid_pc1512.c index 7026cf2..9fd57e4 100644 --- a/src/vid_pc1512.c +++ b/src/vid_pc1512.c @@ -460,7 +460,7 @@ static void *pc1512_init() pc1512->cgamode = 0x12; timer_add(pc1512_poll, &pc1512->vidtime, TIMER_ALWAYS_ENABLED, pc1512); - mem_mapping_add(&pc1512->mapping, 0xb8000, 0x08000, pc1512_read, NULL, NULL, pc1512_write, NULL, NULL, pc1512); + mem_mapping_add(&pc1512->mapping, 0xb8000, 0x08000, pc1512_read, NULL, NULL, pc1512_write, NULL, NULL, NULL, 0, pc1512); io_sethandler(0x03d0, 0x0010, pc1512_in, NULL, NULL, pc1512_out, NULL, NULL, pc1512); return pc1512; } diff --git a/src/vid_pc1640.c b/src/vid_pc1640.c index 6abba50..3cad4b6 100644 --- a/src/vid_pc1640.c +++ b/src/vid_pc1640.c @@ -5,6 +5,7 @@ #include "device.h" #include "io.h" #include "mem.h" +#include "rom.h" #include "timer.h" #include "video.h" #include "vid_cga.h" @@ -19,6 +20,8 @@ typedef struct pc1640_t cga_t cga; ega_t ega; + rom_t bios_rom; + int cga_enabled; int dispontime, dispofftime, vidtime; } pc1640_t; @@ -114,14 +117,16 @@ void *pc1640_init() ega_t *ega = &pc1640->ega; memset(pc1640, 0, sizeof(pc1640_t)); + rom_init(&pc1640->bios_rom, "roms/pc1640/40100", 0xc0000, 0x8000, 0x7fff, 0, 0); + ega_init(&pc1640->ega); pc1640->cga.vram = pc1640->ega.vram; pc1640->cga_enabled = 1; cga_init(&pc1640->cga); timer_add(pc1640_poll, &pc1640->vidtime, TIMER_ALWAYS_ENABLED, pc1640); - mem_mapping_add(&pc1640->cga_mapping, 0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, cga); - mem_mapping_add(&pc1640->ega_mapping, 0, 0, ega_read, NULL, NULL, ega_write, NULL, NULL, ega); + mem_mapping_add(&pc1640->cga_mapping, 0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL, 0, cga); + mem_mapping_add(&pc1640->ega_mapping, 0, 0, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL, 0, ega); io_sethandler(0x03a0, 0x0040, pc1640_in, NULL, NULL, pc1640_out, NULL, NULL, pc1640); return pc1640; } diff --git a/src/vid_pc200.c b/src/vid_pc200.c index 57dce0b..888a766 100644 --- a/src/vid_pc200.c +++ b/src/vid_pc200.c @@ -111,7 +111,7 @@ void *pc200_init() cga_init(&pc200->cga); timer_add(cga_poll, &cga->vidtime, TIMER_ALWAYS_ENABLED, cga); - mem_mapping_add(&pc200->mapping, 0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, cga); + mem_mapping_add(&pc200->mapping, 0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL, 0, cga); io_sethandler(0x03d0, 0x0010, pc200_in, NULL, NULL, pc200_out, NULL, NULL, pc200); return cga; } diff --git a/src/vid_pcjr.c b/src/vid_pcjr.c index 8e39d02..1c5959d 100644 --- a/src/vid_pcjr.c +++ b/src/vid_pcjr.c @@ -615,7 +615,7 @@ static void *pcjr_video_init() q_filt[c] = 512.0 * sin((3.14 * (pcjr_tint + c * 4) / 16.0) - 33.0 / 180.0); } timer_add(pcjr_poll, &pcjr->vidtime, TIMER_ALWAYS_ENABLED, pcjr); - mem_mapping_add(&pcjr->mapping, 0xb8000, 0x08000, pcjr_read, NULL, NULL, pcjr_write, NULL, NULL, pcjr); + mem_mapping_add(&pcjr->mapping, 0xb8000, 0x08000, pcjr_read, NULL, NULL, pcjr_write, NULL, NULL, NULL, 0, pcjr); io_sethandler(0x03d0, 0x0010, pcjr_in, NULL, NULL, pcjr_out, NULL, NULL, pcjr); return pcjr; } diff --git a/src/vid_s3.c b/src/vid_s3.c index d13da8a..eeff4c6 100644 --- a/src/vid_s3.c +++ b/src/vid_s3.c @@ -5,6 +5,7 @@ #include "io.h" #include "mem.h" #include "pci.h" +#include "rom.h" #include "video.h" #include "vid_s3.h" #include "vid_svga.h" @@ -16,6 +17,8 @@ typedef struct s3_t mem_mapping_t linear_mapping; mem_mapping_t mmio_mapping; + rom_t bios_rom; + svga_t svga; sdac_ramdac_t ramdac; @@ -25,8 +28,12 @@ typedef struct s3_t int bpp; uint8_t id, id_ext; + + int packed_mmio; uint32_t linear_base, linear_size; + + uint8_t pci_regs[256]; float (*getclock)(int clock, void *p); void *getclock_p; @@ -238,7 +245,7 @@ uint8_t s3_in(uint16_t addr, void *p) case 0x3d4: return svga->crtcreg; case 0x3d5: -// pclog("Read CRTC R%02X %04X:%04X\n", crtcreg, CS, pc); +// pclog("Read CRTC R%02X %04X:%04X\n", svga->crtcreg, CS, pc); switch (svga->crtcreg) { case 0x2d: return 0x88; /*Extended chip ID*/ @@ -322,6 +329,14 @@ void s3_updatemapping(s3_t *s3) // video_write_a000_w = video_write_a000_l = NULL; + if (!(s3->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) + { +// pclog("Update mapping - PCI disabled\n"); + mem_mapping_disable(&svga->mapping); + mem_mapping_disable(&s3->linear_mapping); + mem_mapping_disable(&s3->mmio_mapping); + return; + } // pclog("Update mapping - bank %02X ", svga->gdcreg[6] & 0xc); switch (svga->gdcreg[6] & 0xc) /*Banked framebuffer*/ @@ -371,8 +386,11 @@ void s3_updatemapping(s3_t *s3) if (s3->linear_base == 0xa0000) { mem_mapping_disable(&s3->linear_mapping); - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); - svga->banked_mask = 0xffff; + if (!(svga->crtc[0x53] & 0x10)) + { + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + svga->banked_mask = 0xffff; + } // mem_mapping_set_addr(&s3->linear_mapping, 0xa0000, 0x10000); } else @@ -383,7 +401,10 @@ void s3_updatemapping(s3_t *s3) // pclog("Memory mapped IO %02X\n", svga->crtc[0x53] & 0x10); if (svga->crtc[0x53] & 0x10) /*Memory mapped IO*/ + { + mem_mapping_disable(&svga->mapping); mem_mapping_enable(&s3->mmio_mapping); + } else mem_mapping_disable(&s3->mmio_mapping); } @@ -412,6 +433,7 @@ void s3_accel_out(uint16_t port, uint8_t val, void *p) { s3_t *s3 = (s3_t *)p; // pclog("Accel out %04X %02X\n", port, val); + switch (port) { case 0x42e8: @@ -795,12 +817,109 @@ uint8_t s3_accel_in(uint16_t port, void *p) return 0; } +#define WRITE8(addr, var, val) switch ((addr) & 3) \ + { \ + case 0: var = (var & 0xffffff00) | (val); break; \ + case 1: var = (var & 0xffff00ff) | ((val) << 8); break; \ + case 2: var = (var & 0xff00ffff) | ((val) << 16); break; \ + case 3: var = (var & 0x00ffffff) | ((val) << 24); break; \ + } + void s3_accel_write(uint32_t addr, uint8_t val, void *p) { s3_t *s3 = (s3_t *)p; // pclog("Write S3 accel %08X %02X\n", addr, val); + if (s3->packed_mmio) + { + int addr_lo = addr & 1; + switch (addr & 0xfffe) + { + case 0x8100: addr = 0x82e8; break; /*ALT_CURXY*/ + case 0x8102: addr = 0x86e8; break; + + case 0x8104: addr = 0x82ea; break; /*ALT_CURXY2*/ + case 0x8106: addr = 0x86ea; break; + + case 0x8108: addr = 0x8ae8; break; /*ALT_STEP*/ + case 0x810a: addr = 0x8ee8; break; + + case 0x810c: addr = 0x8aea; break; /*ALT_STEP2*/ + case 0x810e: addr = 0x8eea; break; + + case 0x8110: addr = 0x92e8; break; /*ALT_ERR*/ + case 0x8112: addr = 0x92ee; break; + + case 0x8118: addr = 0x9ae8; break; /*ALT_CMD*/ + case 0x811a: addr = 0x9aea; break; + + case 0x811c: addr = 0x9ee8; break; /*SHORT_STROKE*/ + + case 0x8120: case 0x8122: /*BKGD_COLOR*/ + WRITE8(addr, s3->accel.bkgd_color, val); + return; + + case 0x8124: case 0x8126: /*FRGD_COLOR*/ + WRITE8(addr, s3->accel.frgd_color, val); + return; + + case 0x8128: case 0x812a: /*WRT_MASK*/ + WRITE8(addr, s3->accel.wrt_mask, val); + return; + + case 0x812c: case 0x812e: /*RD_MASK*/ + WRITE8(addr, s3->accel.rd_mask, val); + return; + + case 0x8130: case 0x8132: /*COLOR_CMP*/ + WRITE8(addr, s3->accel.color_cmp, val); + return; + + case 0x8134: addr = 0xb6e8; break; /*ALT_MIX*/ + case 0x8136: addr = 0xbae8; break; + + case 0x8138: /*SCISSORS_T*/ + WRITE8(addr & 1, s3->accel.multifunc[1], val); + return; + case 0x813a: /*SCISSORS_L*/ + WRITE8(addr & 1, s3->accel.multifunc[2], val); + return; + case 0x813c: /*SCISSORS_B*/ + WRITE8(addr & 1, s3->accel.multifunc[3], val); + return; + case 0x813e: /*SCISSORS_R*/ + WRITE8(addr & 1, s3->accel.multifunc[4], val); + return; + + case 0x8140: /*PIX_CNTL*/ + WRITE8(addr & 1, s3->accel.multifunc[0xa], val); + return; + case 0x8142: /*MULT_MISC2*/ + WRITE8(addr & 1, s3->accel.multifunc[0xd], val); + return; + case 0x8144: /*MULT_MISC*/ + WRITE8(addr & 1, s3->accel.multifunc[0xe], val); + return; + case 0x8146: /*READ_SEL*/ + WRITE8(addr & 1, s3->accel.multifunc[0xf], val); + return; + + case 0x8148: /*ALT_PCNT*/ + WRITE8(addr & 1, s3->accel.multifunc[0], val); + return; + case 0x814a: addr = 0x96e8; break; + case 0x814c: addr = 0x96ea; break; + + case 0x8168: addr = 0xeae8; break; + case 0x816a: addr = 0xeaea; break; + } + addr |= addr_lo; + } + + if (addr & 0x8000) - s3_accel_out(addr & 0xffff, val, p); + { + s3_accel_out(addr & 0xffff, val, p); + } else { if (s3->accel.cmd & 0x100) @@ -819,8 +938,8 @@ void s3_accel_write_w(uint32_t addr, uint16_t val, void *p) // pclog("Write S3 accel w %08X %04X\n", addr, val); if (addr & 0x8000) { - s3_accel_out( addr & 0xffff, val, p); - s3_accel_out((addr & 0xffff) + 1, val >> 8, p); + s3_accel_write(addr, val, p); + s3_accel_write(addr + 1, val >> 8, p); } else { @@ -844,10 +963,10 @@ void s3_accel_write_l(uint32_t addr, uint32_t val, void *p) // pclog("Write S3 accel l %08X %08X\n", addr, val); if (addr & 0x8000) { - s3_accel_out( addr & 0xffff, val, p); - s3_accel_out((addr & 0xffff) + 1, val >> 8, p); - s3_accel_out((addr & 0xffff) + 2, val >> 16, p); - s3_accel_out((addr & 0xffff) + 3, val >> 24, p); + s3_accel_write(addr, val, p); + s3_accel_write(addr + 1, val >> 8, p); + s3_accel_write(addr + 2, val >> 16, p); + s3_accel_write(addr + 3, val >> 24, p); } else { @@ -1531,78 +1650,37 @@ void s3_hwcursor_draw(svga_t *svga, int displine) } -uint8_t s3_pci_read(int func, int addr, void *p) +static void s3_io_remove(s3_t *s3) { - s3_t *s3 = (s3_t *)p; - svga_t *svga = &s3->svga; -// pclog("S3 PCI read %08X\n", addr); - switch (addr) - { - case 0x00: return 0x33; /*'S3'*/ - case 0x01: return 0x53; - - case 0x02: return s3->id_ext; - case 0x03: return 0x88; - - case 0x04: return 0x03; /*Respond to IO and memory accesses*/ - - case 0x07: return 1 << 1; /*Medium DEVSEL timing*/ - - case 0x08: return 0; /*Revision ID*/ - case 0x09: return 0; /*Programming interface*/ - - case 0x0a: return 0x01; /*Supports VGA interface*/ - case 0x0b: return 0x03; - - case 0x10: return 0x00; /*Linear frame buffer address*/ - case 0x11: return 0x00; - case 0x12: return svga->crtc[0x5a] & 0x80; - case 0x13: return svga->crtc[0x59]; - - case 0x30: return 0x01; /*BIOS ROM address*/ - case 0x31: return 0x00; - case 0x32: return 0x0C; - case 0x33: return 0x00; - } - return 0; -} - -void s3_pci_write(int func, int addr, uint8_t val, void *p) -{ - s3_t *s3 = (s3_t *)p; - svga_t *svga = &s3->svga; - switch (addr) - { - case 0x12: - svga->crtc[0x5a] = val & 0x80; - s3_updatemapping(s3); - break; - case 0x13: - svga->crtc[0x59] = val; - s3_updatemapping(s3); - break; - } -} - -static void *s3_init() -{ - s3_t *s3 = malloc(sizeof(s3_t)); - svga_t *svga = &s3->svga; - memset(s3, 0, sizeof(s3_t)); + io_removehandler(0x03c0, 0x0020, s3_in, NULL, NULL, s3_out, NULL, NULL, s3); - mem_mapping_add(&s3->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, &s3->svga); - mem_mapping_add(&s3->mmio_mapping, 0xa0000, 0x10000, s3_accel_read, NULL, NULL, s3_accel_write, s3_accel_write_w, s3_accel_write_l, s3); - mem_mapping_disable(&s3->mmio_mapping); + io_removehandler(0x42e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x46e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x4ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x82e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x86e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x8ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x8ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x92e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x96e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x9ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x9ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xa2e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xa6e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xaae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xaee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xb2e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xb6e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xbae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xbee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xe2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); +} - svga_init(&s3->svga, s3, 1 << 22, /*4mb - 864 supports 8mb but buggy VESA driver reports 0mb*/ - s3_recalctimings, - s3_in, s3_out, - s3_hwcursor_draw); +static void s3_io_set(s3_t *s3) +{ + s3_io_remove(s3); io_sethandler(0x03c0, 0x0020, s3_in, NULL, NULL, s3_out, NULL, NULL, s3); - - svga->crtc[0x36] = 1 | (2 << 2) | (1 << 4) | (4 << 5); - svga->crtc[0x37] = 1 | (7 << 5); io_sethandler(0x42e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0x46e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -1624,31 +1702,149 @@ static void *s3_init() io_sethandler(0xbae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xbee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xe2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); +} + + +uint8_t s3_pci_read(int func, int addr, void *p) +{ + s3_t *s3 = (s3_t *)p; + svga_t *svga = &s3->svga; +// pclog("S3 PCI read %08X\n", addr); + switch (addr) + { + case 0x00: return 0x33; /*'S3'*/ + case 0x01: return 0x53; + + case 0x02: return s3->id_ext; + case 0x03: return 0x88; + + case PCI_REG_COMMAND: + return s3->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ + + case 0x07: return 1 << 1; /*Medium DEVSEL timing*/ + + case 0x08: return 0; /*Revision ID*/ + case 0x09: return 0; /*Programming interface*/ + + case 0x0a: return 0x01; /*Supports VGA interface*/ + case 0x0b: return 0x03; + + case 0x10: return 0x00; /*Linear frame buffer address*/ + case 0x11: return 0x00; + case 0x12: return svga->crtc[0x5a] & 0x80; + case 0x13: return svga->crtc[0x59]; + + case 0x30: return s3->pci_regs[0x30] & 0x01; /*BIOS ROM address*/ + case 0x31: return 0x00; + case 0x32: return s3->pci_regs[0x32]; + case 0x33: return s3->pci_regs[0x33]; + } + return 0; +} + +void s3_pci_write(int func, int addr, uint8_t val, void *p) +{ + s3_t *s3 = (s3_t *)p; + svga_t *svga = &s3->svga; + pclog("s3_pci_write: addr=%02x val=%02x\n", addr, val); + switch (addr) + { + case PCI_REG_COMMAND: + s3->pci_regs[PCI_REG_COMMAND] = val & 0x27; + if (val & PCI_COMMAND_IO) + s3_io_set(s3); + else + s3_io_remove(s3); + s3_updatemapping(s3); + break; + + case 0x12: + svga->crtc[0x5a] = val & 0x80; + s3_updatemapping(s3); + break; + case 0x13: + svga->crtc[0x59] = val; + s3_updatemapping(s3); + break; + + case 0x30: case 0x32: case 0x33: + s3->pci_regs[addr] = val; + if (s3->pci_regs[0x30] & 0x01) + { + uint32_t addr = (s3->pci_regs[0x32] << 16) | (s3->pci_regs[0x33] << 24); + pclog("S3 bios_rom enabled at %08x\n", addr); + mem_mapping_set_addr(&s3->bios_rom.mapping, addr, 0x8000); + } + else + { + pclog("S3 bios_rom disabled\n"); + mem_mapping_disable(&s3->bios_rom.mapping); + } + return; + } +} + +static void *s3_init(char *bios_fn) +{ + s3_t *s3 = malloc(sizeof(s3_t)); + svga_t *svga = &s3->svga; + memset(s3, 0, sizeof(s3_t)); + + rom_init(&s3->bios_rom, bios_fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + if (PCI) + mem_mapping_disable(&s3->bios_rom.mapping); + + mem_mapping_add(&s3->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL, 0, &s3->svga); + mem_mapping_add(&s3->mmio_mapping, 0xa0000, 0x10000, s3_accel_read, NULL, NULL, s3_accel_write, s3_accel_write_w, s3_accel_write_l, NULL, 0, s3); + mem_mapping_disable(&s3->mmio_mapping); + + svga_init(&s3->svga, s3, 1 << 22, /*4mb - 864 supports 8mb but buggy VESA driver reports 0mb*/ + s3_recalctimings, + s3_in, s3_out, + s3_hwcursor_draw); + + svga->crtc[0x36] = 1 | (2 << 2) | (1 << 4) | (4 << 5); + svga->crtc[0x37] = 1 | (7 << 5); + + s3_io_set(s3); pci_add(s3_pci_read, s3_pci_write, s3); + + s3->pci_regs[0x04] = 7; + + s3->pci_regs[0x30] = 0x00; + s3->pci_regs[0x32] = 0x0c; + s3->pci_regs[0x33] = 0x00; return s3; } void *s3_bahamas64_init() { - s3_t *s3 = s3_init(); + s3_t *s3 = s3_init("roms/bahamas64.bin"); s3->id = 0xc1; /*Vision864P*/ - s3->id_ext = 0xc1; /*Trio64*/ - + s3->id_ext = 0xc1; + s3->packed_mmio = 0; + s3->getclock = sdac_getclock; s3->getclock_p = &s3->ramdac; return s3; } +int s3_bahamas64_available() +{ + return rom_present("roms/bahamas64.bin"); +} + void *s3_9fx_init() { - s3_t *s3 = s3_init(); + s3_t *s3 = s3_init("roms/s3_764.bin"); - s3->id = 0xe1; - s3->id_ext = 0x11; /*Trio64*/ + s3->id = 0xe1; /*Trio64*/ + s3->id_ext = 0x11; + s3->packed_mmio = 1; s3->getclock = s3_trio64_getclock; s3->getclock_p = s3; @@ -1656,6 +1852,12 @@ void *s3_9fx_init() return s3; } +int s3_9fx_available() +{ + return rom_present("roms/s3_764.bin"); +} + + void s3_close(void *p) { s3_t *s3 = (s3_t *)p; @@ -1692,7 +1894,7 @@ device_t s3_bahamas64_device = 0, s3_bahamas64_init, s3_close, - NULL, + s3_bahamas64_available, s3_speed_changed, s3_force_redraw, s3_add_status_info @@ -1704,7 +1906,7 @@ device_t s3_9fx_device = 0, s3_9fx_init, s3_close, - NULL, + s3_9fx_available, s3_speed_changed, s3_force_redraw, s3_add_status_info diff --git a/src/vid_s3_virge.c b/src/vid_s3_virge.c index 337bd7d..407ee09 100644 --- a/src/vid_s3_virge.c +++ b/src/vid_s3_virge.c @@ -7,6 +7,7 @@ #include "io.h" #include "mem.h" #include "pci.h" +#include "rom.h" #include "video.h" #include "vid_s3_virge.h" #include "vid_svga.h" @@ -15,8 +16,11 @@ typedef struct virge_t { - mem_mapping_t linear_mapping; - mem_mapping_t mmio_mapping; + mem_mapping_t linear_mapping; + mem_mapping_t mmio_mapping; + mem_mapping_t new_mmio_mapping; + + rom_t bios_rom; svga_t svga; @@ -30,18 +34,97 @@ typedef struct virge_t uint32_t linear_base, linear_size; uint8_t pci_regs[256]; + + struct + { + uint32_t src_base; + uint32_t dest_base; + int clip_l, clip_r, clip_t, clip_b; + int dest_str, src_str; + uint32_t mono_pat_0; + uint32_t mono_pat_1; + uint32_t pat_bg_clr; + uint32_t pat_fg_clr; + uint32_t src_bg_clr; + uint32_t src_fg_clr; + uint32_t cmd_set; + int r_width, r_height; + int rsrc_x, rsrc_y; + int rdest_x, rdest_y; + + int lxend0, lxend1; + int32_t ldx; + uint32_t lxstart, lystart; + int lycnt; + int line_dir; + + int src_x, src_y; + int dest_x, dest_y; + int w, h; + uint8_t rop; + + int data_left_count; + uint32_t data_left; + + uint32_t pattern_8[8*8]; + uint32_t pattern_16[8*8]; + uint32_t pattern_32[8*8]; + } s3d; } virge_t; -void s3_virge_updatemapping(virge_t *virge); +static void s3_virge_updatemapping(virge_t *virge); -uint8_t s3_virge_mmio_read(uint32_t addr, void *p); -uint16_t s3_virge_mmio_read_w(uint32_t addr, void *p); -uint32_t s3_virge_mmio_read_l(uint32_t addr, void *p); -void s3_virge_mmio_write(uint32_t addr, uint8_t val, void *p); -void s3_virge_mmio_write_w(uint32_t addr, uint16_t val, void *p); -void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p); +static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat); -void s3_virge_out(uint16_t addr, uint8_t val, void *p) +static uint8_t s3_virge_mmio_read(uint32_t addr, void *p); +static uint16_t s3_virge_mmio_read_w(uint32_t addr, void *p); +static uint32_t s3_virge_mmio_read_l(uint32_t addr, void *p); +static void s3_virge_mmio_write(uint32_t addr, uint8_t val, void *p); +static void s3_virge_mmio_write_w(uint32_t addr, uint16_t val, void *p); +static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p); + +static uint8_t s3_virge_new_mmio_read(uint32_t addr, void *p); +static uint16_t s3_virge_new_mmio_read_w(uint32_t addr, void *p); +static uint32_t s3_virge_new_mmio_read_l(uint32_t addr, void *p); +static void s3_virge_new_mmio_write(uint32_t addr, uint8_t val, void *p); +static void s3_virge_new_mmio_write_w(uint32_t addr, uint16_t val, void *p); +static void s3_virge_new_mmio_write_l(uint32_t addr, uint32_t val, void *p); + +enum +{ + CMD_SET_AE = 1, + CMD_SET_HC = (1 << 1), + + CMD_SET_FORMAT_MASK = (7 << 2), + CMD_SET_FORMAT_8 = (0 << 2), + CMD_SET_FORMAT_16 = (1 << 2), + CMD_SET_FORMAT_24 = (2 << 2), + + CMD_SET_MS = (1 << 6), + CMD_SET_IDS = (1 << 7), + CMD_SET_MP = (1 << 8), + CMD_SET_TP = (1 << 9), + + CMD_SET_ITA_MASK = (3 << 10), + CMD_SET_ITA_BYTE = (0 << 10), + CMD_SET_ITA_WORD = (1 << 10), + CMD_SET_ITA_DWORD = (2 << 10), + + CMD_SET_XP = (1 << 25), + CMD_SET_YP = (1 << 26), + + CMD_SET_COMMAND_MASK = (15 << 27) +}; + +enum +{ + CMD_SET_COMMAND_BITBLT = (0 << 27), + CMD_SET_COMMAND_RECTFILL = (2 << 27), + CMD_SET_COMMAND_LINE = (3 << 27), + CMD_SET_COMMAND_NOP = (15 << 27) +}; + +static void s3_virge_out(uint16_t addr, uint8_t val, void *p) { virge_t *virge = (virge_t *)p; svga_t *svga = &virge->svga; @@ -49,7 +132,7 @@ void s3_virge_out(uint16_t addr, uint8_t val, void *p) if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; - + // pclog("S3 out %04X %02X %04X:%08X %04X %04X %i\n", addr, val, CS, pc, ES, BX, ins); switch (addr) @@ -76,7 +159,7 @@ void s3_virge_out(uint16_t addr, uint8_t val, void *p) svga->crtcreg = val & 0x7f; return; case 0x3d5: -// if (crtcreg == 0x67) pclog("Write CRTC R%02X %02X\n", crtcreg, val); + //pclog("Write CRTC R%02X %02X\n", svga->crtcreg, val); if (svga->crtcreg <= 7 && svga->crtc[0x11] & 0x80) return; if (svga->crtcreg >= 0x20 && svga->crtcreg != 0x38 && (svga->crtc[0x38] & 0xcc) != 0x48) @@ -132,7 +215,8 @@ void s3_virge_out(uint16_t addr, uint8_t val, void *p) case 0x45: svga->hwcursor.ena = val & 1; break; - case 0x48: + case 0x46: case 0x47: case 0x48: case 0x49: + case 0x4c: case 0x4d: case 0x4e: case 0x4f: svga->hwcursor.x = ((svga->crtc[0x46] << 8) | svga->crtc[0x47]) & 0x7ff; if (svga->bpp == 32) svga->hwcursor.x >>= 1; svga->hwcursor.y = ((svga->crtc[0x48] << 8) | svga->crtc[0x49]) & 0x7ff; @@ -151,8 +235,8 @@ void s3_virge_out(uint16_t addr, uint8_t val, void *p) { case 3: svga->bpp = 15; break; case 5: svga->bpp = 16; break; - case 7: svga->bpp = 24; break; - case 13: svga->bpp = 32; break; +// case 7: svga->bpp = 24; break; + case 13: svga->bpp = 24; break; default: svga->bpp = 8; break; } break; @@ -172,7 +256,7 @@ void s3_virge_out(uint16_t addr, uint8_t val, void *p) svga_out(addr, val, svga); } -uint8_t s3_virge_in(uint16_t addr, void *p) +static uint8_t s3_virge_in(uint16_t addr, void *p) { virge_t *virge = (virge_t *)p; svga_t *svga = &virge->svga; @@ -195,7 +279,7 @@ uint8_t s3_virge_in(uint16_t addr, void *p) case 0x3D4: return svga->crtcreg; case 0x3D5: -// pclog("Read CRTC R%02X %04X:%04X\n", crtcreg, CS, pc); +// pclog("Read CRTC R%02X %04X:%04X (%02x)\n", svga->crtcreg, CS, pc, svga->crtc[svga->crtcreg]); switch (svga->crtcreg) { case 0x2d: return virge->virge_id_high; /*Extended chip ID*/ @@ -204,6 +288,7 @@ uint8_t s3_virge_in(uint16_t addr, void *p) case 0x30: return virge->virge_id; /*Chip ID*/ case 0x31: return (svga->crtc[0x31] & 0xcf) | ((virge->ma_ext & 3) << 4); case 0x35: return (svga->crtc[0x35] & 0xf0) | (virge->bank & 0xf); + case 0x36: return (svga->crtc[0x36] & 0xfc) | 2; /*PCI bus*/ case 0x51: return (svga->crtc[0x51] & 0xf0) | ((virge->bank >> 2) & 0xc) | ((virge->ma_ext >> 2) & 3); case 0x69: return virge->ma_ext; case 0x6a: return virge->bank; @@ -213,7 +298,7 @@ uint8_t s3_virge_in(uint16_t addr, void *p) return svga_in(addr, svga); } -void s3_virge_recalctimings(svga_t *svga) +static void s3_virge_recalctimings(svga_t *svga) { virge_t *virge = (virge_t *)svga->p; // pclog("recalctimings\n"); @@ -252,20 +337,41 @@ void s3_virge_recalctimings(svga_t *svga) else if (svga->crtc[0x43] & 0x04) svga->rowoffset += 0x100; if (!svga->rowoffset) svga->rowoffset = 256; svga->interlace = svga->crtc[0x42] & 0x20; - if (svga->bpp == 32) +// pclog("svga->rowoffset = %i bpp=%i\n", svga->rowoffset, svga->bpp); + if (svga->bpp == 15 || svga->bpp == 16) + { + svga->htotal >>= 1; + svga->hdisp >>= 1; + } + if (svga->bpp == 24) + { + svga->rowoffset = (svga->rowoffset * 3) / 4; /*Hack*/ + } + +/* if (svga->bpp == 32) { svga->htotal <<= 2; svga->hdisp <<= 2; - } + }*/ //svga_clock = cpuclock / sdac_getclock((svga_miscout >> 2) & 3); // pclog("SVGA_CLOCK = %f %02X %f\n", svga_clock, svga_miscout, cpuclock); //if (bpp > 8) svga_clock /= 2; } -void s3_virge_updatemapping(virge_t *virge) +static void s3_virge_updatemapping(virge_t *virge) { svga_t *svga = &virge->svga; - + + if (!(virge->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) + { +// pclog("Update mapping - PCI disabled\n"); + mem_mapping_disable(&svga->mapping); + mem_mapping_disable(&virge->linear_mapping); + mem_mapping_disable(&virge->mmio_mapping); + mem_mapping_disable(&virge->new_mmio_mapping); + return; + } + pclog("Update mapping - bank %02X ", svga->gdcreg[6] & 0xc); switch (svga->gdcreg[6] & 0xc) /*Banked framebuffer*/ { @@ -287,10 +393,11 @@ void s3_virge_updatemapping(virge_t *virge) break; } + virge->linear_base = (svga->crtc[0x5a] << 16) | (svga->crtc[0x59] << 24); + pclog("Linear framebuffer %02X ", svga->crtc[0x58] & 0x10); if (svga->crtc[0x58] & 0x10) /*Linear framebuffer*/ { - virge->linear_base = (svga->crtc[0x5a] << 16) | (svga->crtc[0x59] << 24); switch (svga->crtc[0x58] & 3) { case 0: /*64k*/ @@ -315,13 +422,13 @@ void s3_virge_updatemapping(virge_t *virge) mem_mapping_disable(&virge->linear_mapping); } else - mem_mapping_set_addr(&svga->mapping, virge->linear_base, virge->linear_size); + mem_mapping_set_addr(&virge->linear_mapping, virge->linear_base, virge->linear_size); } else mem_mapping_disable(&virge->linear_mapping); pclog("Memory mapped IO %02X\n", svga->crtc[0x53] & 0x18); - if ((svga->crtc[0x53] & 0x18) == 0x10) /*Memory mapped IO*/ + if (svga->crtc[0x53] & 0x10) /*Old MMIO*/ { if (svga->crtc[0x53] & 0x20) mem_mapping_set_addr(&virge->mmio_mapping, 0xb8000, 0x8000); @@ -330,47 +437,707 @@ void s3_virge_updatemapping(virge_t *virge) } else mem_mapping_disable(&virge->mmio_mapping); + + if (svga->crtc[0x53] & 0x08) /*New MMIO*/ + mem_mapping_set_addr(&virge->new_mmio_mapping, virge->linear_base + 0x1000000, 0x10000); + else + mem_mapping_disable(&virge->new_mmio_mapping); + } -uint8_t s3_virge_mmio_read(uint32_t addr, void *p) +static uint8_t s3_virge_mmio_read(uint32_t addr, void *p) { - pclog("MMIO readb %08X\n", addr); +// pclog("MMIO readb %08X\n", addr); return 0xff; } -uint16_t s3_virge_mmio_read_w(uint32_t addr, void *p) +static uint16_t s3_virge_mmio_read_w(uint32_t addr, void *p) { - pclog("MMIO readw %08X\n", addr); +// pclog("MMIO readw %08X\n", addr); return 0xffff; } -uint32_t s3_virge_mmio_read_l(uint32_t addr, void *p) +static uint32_t s3_virge_mmio_read_l(uint32_t addr, void *p) { - pclog("MMIO readl %08X\n", addr); +// pclog("MMIO readl %08X\n", addr); return 0xffffffff; } -void s3_virge_mmio_write(uint32_t addr, uint8_t val, void *p) +static void s3_virge_mmio_write(uint32_t addr, uint8_t val, void *p) { - pclog("MMIO writeb %08X %02X\n", addr, val); +// pclog("MMIO writeb %08X %02X\n", addr, val); } -void s3_virge_mmio_write_w(uint32_t addr, uint16_t val, void *p) +static void s3_virge_mmio_write_w(uint32_t addr, uint16_t val, void *p) { - pclog("MMIO writew %08X %04X\n", addr, val); +// pclog("MMIO writew %08X %04X\n", addr, val); } -void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p) +static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p) { - pclog("MMIO writel %08X %08X\n", addr, val); +// pclog("MMIO writel %08X %08X\n", addr, val); +} + +static uint8_t s3_virge_new_mmio_read(uint32_t addr, void *p) +{ +// pclog("New MMIO readb %08X\n", addr); + switch (addr & 0xffff) + { + case 0x83b0: case 0x83b1: case 0x83b2: case 0x83b3: + case 0x83b4: case 0x83b5: case 0x83b6: case 0x83b7: + case 0x83b8: case 0x83b9: case 0x83ba: case 0x83bb: + case 0x83bc: case 0x83bd: case 0x83be: case 0x83bf: + case 0x83c0: case 0x83c1: case 0x83c2: case 0x83c3: + case 0x83c4: case 0x83c5: case 0x83c6: case 0x83c7: + case 0x83c8: case 0x83c9: case 0x83ca: case 0x83cb: + case 0x83cc: case 0x83cd: case 0x83ce: case 0x83cf: + case 0x83d0: case 0x83d1: case 0x83d2: case 0x83d3: + case 0x83d4: case 0x83d5: case 0x83d6: case 0x83d7: + case 0x83d8: case 0x83d9: case 0x83da: case 0x83db: + case 0x83dc: case 0x83dd: case 0x83de: case 0x83df: + return s3_virge_in(addr & 0x3ff, p); + } + return 0xff; +} +static uint16_t s3_virge_new_mmio_read_w(uint32_t addr, void *p) +{ +// pclog("New MMIO readw %08X\n", addr); + switch (addr & 0xfffe) + { + default: + return s3_virge_new_mmio_read(addr, p) | (s3_virge_new_mmio_read(addr + 1, p) << 8); + } + return 0xffff; +} +static uint32_t s3_virge_new_mmio_read_l(uint32_t addr, void *p) +{ + virge_t *virge = (virge_t *)p; + uint32_t ret = 0xffffffff; +// pclog("New MMIO readl %08X\n", addr); + switch (addr & 0xfffc) + { + case 0x8504: + ret = (0x1f << 8) | (1 << 13); + break; + case 0xa4d4: + ret = virge->s3d.src_base; + break; + case 0xa4d8: + ret = virge->s3d.dest_base; + break; + case 0xa4dc: + ret = (virge->s3d.clip_l << 16) | virge->s3d.clip_r; + break; + case 0xa4e0: + ret = (virge->s3d.clip_t << 16) | virge->s3d.clip_b; + break; + case 0xa4e4: + ret = (virge->s3d.dest_str << 16) | virge->s3d.src_str; + break; + case 0xa4e8: + ret = virge->s3d.mono_pat_0; + break; + case 0xa4ec: + ret = virge->s3d.mono_pat_1; + break; + case 0xa4f0: + ret = virge->s3d.pat_bg_clr; + break; + case 0xa4f4: + ret = virge->s3d.pat_fg_clr; + break; + case 0xa4f8: + ret = virge->s3d.src_bg_clr; + break; + case 0xa4fc: + ret = virge->s3d.src_fg_clr; + break; + case 0xa500: + ret = virge->s3d.cmd_set; + break; + case 0xa504: + ret = (virge->s3d.r_width << 16) | virge->s3d.r_height; + break; + case 0xa508: + ret = (virge->s3d.rsrc_x << 16) | virge->s3d.rsrc_y; + break; + case 0xa50c: + ret = (virge->s3d.rdest_x << 16) | virge->s3d.rdest_y; + break; + + default: + return s3_virge_new_mmio_read_w(addr, p) | (s3_virge_new_mmio_read_w(addr + 2, p) << 16); + } + return ret; +} +static void s3_virge_new_mmio_write(uint32_t addr, uint8_t val, void *p) +{ + virge_t *virge = (virge_t *)p; + svga_t *svga = &virge->svga; + +// pclog("New MMIO writeb %08X %02X\n", addr, val); + + if ((addr & 0xfffc) < 0x8000) + s3_virge_bitblt(virge, 8, val); + else switch (addr & 0xffff) + { + case 0x83b0: case 0x83b1: case 0x83b2: case 0x83b3: + case 0x83b4: case 0x83b5: case 0x83b6: case 0x83b7: + case 0x83b8: case 0x83b9: case 0x83ba: case 0x83bb: + case 0x83bc: case 0x83bd: case 0x83be: case 0x83bf: + case 0x83c0: case 0x83c1: case 0x83c2: case 0x83c3: + case 0x83c4: case 0x83c5: case 0x83c6: case 0x83c7: + case 0x83c8: case 0x83c9: case 0x83ca: case 0x83cb: + case 0x83cc: case 0x83cd: case 0x83ce: case 0x83cf: + case 0x83d0: case 0x83d1: case 0x83d2: case 0x83d3: + case 0x83d4: case 0x83d5: case 0x83d6: case 0x83d7: + case 0x83d8: case 0x83d9: case 0x83da: case 0x83db: + case 0x83dc: case 0x83dd: case 0x83de: case 0x83df: + s3_virge_out(addr & 0x3ff, val, p); + break; + } + + +} +static void s3_virge_new_mmio_write_w(uint32_t addr, uint16_t val, void *p) +{ + virge_t *virge = (virge_t *)p; +// pclog("New MMIO writew %08X %04X\n", addr, val); + if ((addr & 0xfffc) < 0x8000) + { + if (virge->s3d.cmd_set & CMD_SET_MS) + s3_virge_bitblt(virge, 16, ((val >> 8) | (val << 8)) << 16); + else + s3_virge_bitblt(virge, 16, val); + } + else switch (addr & 0xfffe) + { + case 0x83d4: + s3_virge_new_mmio_write(addr, val, p); + s3_virge_new_mmio_write(addr + 1, val >> 8, p); + break; + } +} +static void s3_virge_new_mmio_write_l(uint32_t addr, uint32_t val, void *p) +{ + virge_t *virge = (virge_t *)p; + +// if ((addr & 0xfffc) >= 0x8000) +// pclog("New MMIO writel %08X %08X\n", addr, val); + + if ((addr & 0xfffc) < 0x8000) + { + if (virge->s3d.cmd_set & CMD_SET_MS) + s3_virge_bitblt(virge, 32, ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24)); + else + s3_virge_bitblt(virge, 32, val); + } + else switch (addr & 0xfffc) + { + case 0xa000: case 0xa004: case 0xa008: case 0xa00c: + case 0xa010: case 0xa014: case 0xa018: case 0xa01c: + case 0xa020: case 0xa024: case 0xa028: case 0xa02c: + case 0xa030: case 0xa034: case 0xa038: case 0xa03c: + case 0xa040: case 0xa044: case 0xa048: case 0xa04c: + case 0xa050: case 0xa054: case 0xa058: case 0xa05c: + case 0xa060: case 0xa064: case 0xa068: case 0xa06c: + case 0xa070: case 0xa074: case 0xa078: case 0xa07c: + case 0xa080: case 0xa084: case 0xa088: case 0xa08c: + case 0xa090: case 0xa094: case 0xa098: case 0xa09c: + case 0xa0a0: case 0xa0a4: case 0xa0a8: case 0xa0ac: + case 0xa0b0: case 0xa0b4: case 0xa0b8: case 0xa0bc: + case 0xa0c0: case 0xa0c4: case 0xa0c8: case 0xa0cc: + case 0xa0d0: case 0xa0d4: case 0xa0d8: case 0xa0dc: + case 0xa0e0: case 0xa0e4: case 0xa0e8: case 0xa0ec: + case 0xa0f0: case 0xa0f4: case 0xa0f8: case 0xa0fc: + case 0xa100: case 0xa104: case 0xa108: case 0xa10c: + case 0xa110: case 0xa114: case 0xa118: case 0xa11c: + case 0xa120: case 0xa124: case 0xa128: case 0xa12c: + case 0xa130: case 0xa134: case 0xa138: case 0xa13c: + case 0xa140: case 0xa144: case 0xa148: case 0xa14c: + case 0xa150: case 0xa154: case 0xa158: case 0xa15c: + case 0xa160: case 0xa164: case 0xa168: case 0xa16c: + case 0xa170: case 0xa174: case 0xa178: case 0xa17c: + case 0xa180: case 0xa184: case 0xa188: case 0xa18c: + case 0xa190: case 0xa194: case 0xa198: case 0xa19c: + case 0xa1a0: case 0xa1a4: case 0xa1a8: case 0xa1ac: + case 0xa1b0: case 0xa1b4: case 0xa1b8: case 0xa1bc: + case 0xa1c0: case 0xa1c4: case 0xa1c8: case 0xa1cc: + case 0xa1d0: case 0xa1d4: case 0xa1d8: case 0xa1dc: + case 0xa1e0: case 0xa1e4: case 0xa1e8: case 0xa1ec: + case 0xa1f0: case 0xa1f4: case 0xa1f8: case 0xa1fc: + { + int x = addr & 4; + int y = (addr >> 3) & 7; + virge->s3d.pattern_8[y*8 + x] = val & 0xff; + virge->s3d.pattern_8[y*8 + x + 1] = val >> 8; + virge->s3d.pattern_8[y*8 + x + 2] = val >> 16; + virge->s3d.pattern_8[y*8 + x + 3] = val >> 24; + + x = (addr >> 1) & 6; + y = (addr >> 4) & 7; + virge->s3d.pattern_16[y*8 + x] = val & 0xffff; + virge->s3d.pattern_16[y*8 + x + 1] = val >> 16; + + x = (addr >> 2) & 7; + y = (addr >> 5) & 7; + virge->s3d.pattern_32[y*8 + x] = val & 0xffffff; + } + break; + + + case 0xa4d4: case 0xa8d4: + virge->s3d.src_base = val & 0x3ffff8; + break; + case 0xa4d8: case 0xa8d8: + virge->s3d.dest_base = val & 0x3ffff8; + break; + case 0xa4dc: case 0xa8dc: + virge->s3d.clip_l = (val >> 16) & 0x7ff; + virge->s3d.clip_r = val & 0x7ff; + break; + case 0xa4e0: case 0xa8e0: + virge->s3d.clip_t = (val >> 16) & 0x7ff; + virge->s3d.clip_b = val & 0x7ff; + break; + case 0xa4e4: case 0xa8e4: + virge->s3d.dest_str = (val >> 16) & 0xff8; + virge->s3d.src_str = val & 0xff8; + break; + case 0xa4e8: + virge->s3d.mono_pat_0 = val; + break; + case 0xa4ec: + virge->s3d.mono_pat_1 = val; + break; + case 0xa4f0: + virge->s3d.pat_bg_clr = val; + break; + case 0xa4f4: case 0xa8f4: + virge->s3d.pat_fg_clr = val; + break; + case 0xa4f8: + virge->s3d.src_bg_clr = val; + break; + case 0xa4fc: + virge->s3d.src_fg_clr = val; + break; + case 0xa500: case 0xa900: + virge->s3d.cmd_set = val; + if (!(val & CMD_SET_AE)) + s3_virge_bitblt(virge, -1, 0); + break; + case 0xa504: + virge->s3d.r_width = (val >> 16) & 0x7ff; + virge->s3d.r_height = val & 0x7ff; + break; + case 0xa508: + virge->s3d.rsrc_x = (val >> 16) & 0x7ff; + virge->s3d.rsrc_y = val & 0x7ff; + break; + case 0xa50c: + virge->s3d.rdest_x = (val >> 16) & 0x7ff; + virge->s3d.rdest_y = val & 0x7ff; + if (virge->s3d.cmd_set & CMD_SET_AE) + s3_virge_bitblt(virge, -1, 0); + break; + case 0xa96c: + virge->s3d.lxend0 = (val >> 16) & 0x7ff; + virge->s3d.lxend1 = val & 0x7ff; + break; + case 0xa970: + virge->s3d.ldx = (int32_t)val; + break; + case 0xa974: + virge->s3d.lxstart = val; + break; + case 0xa978: + virge->s3d.lystart = val & 0x7ff; + break; + case 0xa97c: + virge->s3d.lycnt = val & 0x7ff; + virge->s3d.line_dir = val >> 31; + if (virge->s3d.cmd_set & CMD_SET_AE) + s3_virge_bitblt(virge, -1, 0); + break; + } +} + +#define READ(addr, val) \ + do \ + { \ + switch (bpp) \ + { \ + case 0: /*8 bpp*/ \ + val = vram[addr & 0x3fffff]; \ + break; \ + case 1: /*16 bpp*/ \ + val = *(uint16_t *)&vram[addr & 0x3fffff]; \ + break; \ + case 2: /*24 bpp*/ \ + val = (*(uint32_t *)&vram[addr & 0x3fffff]) & 0xffffff; \ + break; \ + } \ + } while (0) + +#define CLIP(x, y) \ + do \ + { \ + if ((virge->s3d.cmd_set & CMD_SET_HC) && \ + (x < virge->s3d.clip_l || \ + x > virge->s3d.clip_r || \ + y < virge->s3d.clip_t || \ + y > virge->s3d.clip_b)) \ + update = 0; \ + } while (0) + +#define MIX() \ + do \ + { \ + int c; \ + for (c = 0; c < 24; c++) \ + { \ + int d = (dest & (1 << c)) ? 1 : 0; \ + if (source & (1 << c)) d |= 2; \ + if (pattern & (1 << c)) d |= 4; \ + if (virge->s3d.rop & (1 << d)) out |= (1 << c); \ + } \ + } while (0) + +#define WRITE(addr, val) \ + do \ + { \ + switch (bpp) \ + { \ + case 0: /*8 bpp*/ \ + vram[addr & 0x3fffff] = val; \ + virge->svga.changedvram[(addr & 0x3fffff) >> 10] = changeframecount; \ + break; \ + case 1: /*16 bpp*/ \ + *(uint16_t *)&vram[addr & 0x3fffff] = val; \ + virge->svga.changedvram[(addr & 0x3fffff) >> 10] = changeframecount; \ + break; \ + case 2: /*24 bpp*/ \ + *(uint32_t *)&vram[addr & 0x3fffff] = (val & 0xffffff) | \ + (vram[(addr + 3) & 0x3fffff] << 24); \ + virge->svga.changedvram[(addr & 0x3fffff) >> 10] = changeframecount; \ + break; \ + } \ + } while (0) + +static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) +{ + int cpu_input = (count != -1); + uint8_t *vram = virge->svga.vram; + uint32_t mono_pattern[64]; + int count_mask; + int x_inc = (virge->s3d.cmd_set & CMD_SET_XP) ? 1 : -1; + int y_inc = (virge->s3d.cmd_set & CMD_SET_YP) ? 1 : -1; + int bpp; + int x_mul; + int cpu_dat_shift; + uint32_t *pattern_data; + + switch (virge->s3d.cmd_set & CMD_SET_FORMAT_MASK) + { + case CMD_SET_FORMAT_8: + bpp = 0; + x_mul = 1; + cpu_dat_shift = 8; + pattern_data = virge->s3d.pattern_8; + break; + case CMD_SET_FORMAT_16: + bpp = 1; + x_mul = 2; + cpu_dat_shift = 16; + pattern_data = virge->s3d.pattern_16; + break; + case CMD_SET_FORMAT_24: + default: + bpp = 2; + x_mul = 3; + cpu_dat_shift = 24; + pattern_data = virge->s3d.pattern_32; + break; + } + if (virge->s3d.cmd_set & CMD_SET_MP) + pattern_data = mono_pattern; + + switch (virge->s3d.cmd_set & CMD_SET_ITA_MASK) + { + case CMD_SET_ITA_BYTE: + count_mask = ~0x7; + break; + case CMD_SET_ITA_WORD: + count_mask = ~0xf; + break; + case CMD_SET_ITA_DWORD: + default: + count_mask = ~0x1f; + break; + } + if (virge->s3d.cmd_set & CMD_SET_MP) + { + int x, y; + for (y = 0; y < 4; y++) + { + for (x = 0; x < 8; x++) + { + if (virge->s3d.mono_pat_0 & (1 << (x + y*8))) + mono_pattern[y*8 + x] = virge->s3d.pat_fg_clr; + else + mono_pattern[y*8 + x] = virge->s3d.pat_bg_clr; + if (virge->s3d.mono_pat_1 & (1 << (x + y*8))) + mono_pattern[(y+4)*8 + x] = virge->s3d.pat_fg_clr; + else + mono_pattern[(y+4)*8 + x] = virge->s3d.pat_bg_clr; + } + } + } + switch (virge->s3d.cmd_set & CMD_SET_COMMAND_MASK) + { + case CMD_SET_COMMAND_NOP: + break; + + case CMD_SET_COMMAND_BITBLT: + if (count == -1) + { + virge->s3d.src_x = virge->s3d.rsrc_x; + virge->s3d.src_y = virge->s3d.rsrc_y; + virge->s3d.dest_x = virge->s3d.rdest_x; + virge->s3d.dest_y = virge->s3d.rdest_y; + virge->s3d.w = virge->s3d.r_width; + virge->s3d.h = virge->s3d.r_height; + virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; + virge->s3d.data_left_count = 0; + + /* pclog("BitBlt start %i,%i %i,%i %02X\n", virge->s3d.dest_x, + virge->s3d.dest_y, + virge->s3d.w, + virge->s3d.h, + virge->s3d.rop);*/ + + if (virge->s3d.cmd_set & CMD_SET_IDS) + return; + } + if (!virge->s3d.h) + return; + while (count) + { + uint32_t src_addr = virge->s3d.src_base + (virge->s3d.src_x * x_mul) + (virge->s3d.src_y * virge->s3d.src_str); + uint32_t dest_addr = virge->s3d.dest_base + (virge->s3d.dest_x * x_mul) + (virge->s3d.dest_y * virge->s3d.dest_str); + uint32_t source, dest, pattern; + uint32_t out = 0; + int update = 1; + + switch (virge->s3d.cmd_set & (CMD_SET_MS | CMD_SET_IDS)) + { + case 0: + case CMD_SET_MS: + READ(src_addr, source); + break; + case CMD_SET_IDS: + if (virge->s3d.data_left_count) + { + /*Handle shifting for 24-bit data*/ + source = virge->s3d.data_left; + source |= ((cpu_dat << virge->s3d.data_left_count) & ~0xff000000); + cpu_dat >>= (cpu_dat_shift - virge->s3d.data_left_count); + count -= (cpu_dat_shift - virge->s3d.data_left_count); + virge->s3d.data_left_count = 0; + if (count < cpu_dat_shift) + { + virge->s3d.data_left = cpu_dat; + virge->s3d.data_left_count = count; + count = 0; + } + } + else + { + source = cpu_dat; + cpu_dat >>= cpu_dat_shift; + count -= cpu_dat_shift; + if (count < cpu_dat_shift) + { + virge->s3d.data_left = cpu_dat; + virge->s3d.data_left_count = count; + count = 0; + } + } + break; + case CMD_SET_IDS | CMD_SET_MS: + source = (cpu_dat & (1 << 31)) ? virge->s3d.src_fg_clr : virge->s3d.src_bg_clr; + if ((virge->s3d.cmd_set & CMD_SET_TP) && !(cpu_dat & (1 << 31))) + update = 0; + cpu_dat <<= 1; + count--; + break; + } + + CLIP(virge->s3d.dest_x, virge->s3d.dest_y); + + if (update) + { + READ(dest_addr, dest); + pattern = pattern_data[(virge->s3d.dest_y & 7)*8 + (virge->s3d.dest_x & 7)]; + MIX(); + + WRITE(dest_addr, out); + } + + virge->s3d.src_x += x_inc; + virge->s3d.dest_x += x_inc; + if (!virge->s3d.w) + { + virge->s3d.src_x = virge->s3d.rsrc_x; + virge->s3d.dest_x = virge->s3d.rdest_x; + virge->s3d.w = virge->s3d.r_width; + + virge->s3d.src_y += y_inc; + virge->s3d.dest_y += y_inc; + virge->s3d.h--; + + switch (virge->s3d.cmd_set & (CMD_SET_MS | CMD_SET_IDS)) + { + case CMD_SET_IDS: + cpu_dat >>= (count - (count & count_mask)); + count &= count_mask; + virge->s3d.data_left_count = 0; + break; + + case CMD_SET_IDS | CMD_SET_MS: + cpu_dat <<= (count - (count & count_mask)); + count &= count_mask; + break; + } + if (!virge->s3d.h) + { + return; + } + } + else + virge->s3d.w--; + } + break; + + case CMD_SET_COMMAND_RECTFILL: + /*No source, pattern = pat_fg_clr*/ + if (count == -1) + { + virge->s3d.src_x = virge->s3d.rsrc_x; + virge->s3d.src_y = virge->s3d.rsrc_y; + virge->s3d.dest_x = virge->s3d.rdest_x; + virge->s3d.dest_y = virge->s3d.rdest_y; + virge->s3d.w = virge->s3d.r_width; + virge->s3d.h = virge->s3d.r_height; + virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; + +/* pclog("RctFll start %i,%i %i,%i %02X\n", virge->s3d.dest_x, + virge->s3d.dest_y, + virge->s3d.w, + virge->s3d.h, + virge->s3d.rop);*/ + } + + while (count) + { + uint32_t dest_addr = virge->s3d.dest_base + (virge->s3d.dest_x * x_mul) + (virge->s3d.dest_y * virge->s3d.dest_str); + uint32_t source = 0, dest, pattern = virge->s3d.pat_fg_clr; + uint32_t out = 0; + int update = 1; + + CLIP(virge->s3d.dest_x, virge->s3d.dest_y); + + if (update) + { + READ(dest_addr, dest); + + MIX(); + + WRITE(dest_addr, out); + } + + virge->s3d.src_x += x_inc; + virge->s3d.dest_x += x_inc; + if (!virge->s3d.w) + { + virge->s3d.src_x = virge->s3d.rsrc_x; + virge->s3d.dest_x = virge->s3d.rdest_x; + virge->s3d.w = virge->s3d.r_width; + + virge->s3d.src_y += y_inc; + virge->s3d.dest_y += y_inc; + virge->s3d.h--; + if (!virge->s3d.h) + { + return; + } + } + else + virge->s3d.w--; + count--; + } + break; + + case CMD_SET_COMMAND_LINE: + if (count == -1) + { + virge->s3d.dest_x = virge->s3d.lxstart; + virge->s3d.dest_y = virge->s3d.lystart; + virge->s3d.h = virge->s3d.lycnt; + virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; + if (virge->s3d.ldx >= 0) + virge->s3d.dest_x -= virge->s3d.ldx / 2; + else + virge->s3d.dest_x += virge->s3d.ldx / 2; + //virge->s3d.dest_dest_x = virge->s3d.dest_x + virge->s3d.ldx; + } + while (virge->s3d.h) + { + int x = virge->s3d.dest_x >> 20; + int new_x = (virge->s3d.dest_x + virge->s3d.ldx) >> 20; + + do + { + uint32_t dest_addr = virge->s3d.dest_base + (x * x_mul) + (virge->s3d.dest_y * virge->s3d.dest_str); + uint32_t source = 0, dest, pattern; + uint32_t out = 0; + int update = 1; + + CLIP(x, virge->s3d.dest_y); + + if (update) + { + READ(dest_addr, dest); + pattern = virge->s3d.pat_fg_clr; + + MIX(); + + WRITE(dest_addr, out); + } + + if (x < new_x) + x++; + else if (x > new_x) + x--; + } while (x != new_x); + + virge->s3d.dest_x += virge->s3d.ldx; + virge->s3d.dest_y--; + virge->s3d.h--; + } + break; + + default: + fatal("s3_virge_bitblt : blit command %i %08x\n", (virge->s3d.cmd_set >> 27) & 0xf, virge->s3d.cmd_set); + } } - -void s3_virge_hwcursor_draw(svga_t *svga, int displine) +static void s3_virge_hwcursor_draw(svga_t *svga, int displine) { int x; uint16_t dat[2]; int xx; int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; - pclog("HWcursor %i %i\n", svga->hwcursor_latch.x, svga->hwcursor_latch.y); +// pclog("HWcursor %i %i\n", svga->hwcursor_latch.x, svga->hwcursor_latch.y); for (x = 0; x < 64; x += 16) { dat[0] = (svga->vram[svga->hwcursor_latch.addr] << 8) | svga->vram[svga->hwcursor_latch.addr + 1]; @@ -394,72 +1161,150 @@ void s3_virge_hwcursor_draw(svga_t *svga, int displine) } } - -uint8_t s3_virge_pci_read(int func, int addr, void *p) +static uint8_t s3_virge_pci_read(int func, int addr, void *p) { virge_t *virge = (virge_t *)p; svga_t *svga = &virge->svga; -// pclog("S3 PCI read %08X\n", addr); + uint8_t ret = 0; +// pclog("S3 PCI read %08X ", addr); switch (addr) { - case 0x00: return 0x33; /*'S3'*/ - case 0x01: return 0x53; + case 0x00: ret = 0x33; break; /*'S3'*/ + case 0x01: ret = 0x53; break; - case 0x02: return virge->virge_id_low; - case 0x03: return virge->virge_id_high; - - case 0x08: return 0; /*Revision ID*/ - case 0x09: return 0; /*Programming interface*/ - - case 0x0a: return 0x00; /*Supports VGA interface*/ - case 0x0b: return 0x03; - - case 0x10: return 0x00; /*Linear frame buffer address*/ - case 0x11: return 0x00; - case 0x12: return 0x00; - case 0x13: return svga->crtc[0x59] & 0xfc; + case 0x02: ret = virge->virge_id_low; break; + case 0x03: ret = virge->virge_id_high; break; - case 0x30: return 0x01; /*BIOS ROM address*/ - case 0x31: return 0x00; - case 0x32: return 0x0C; - case 0x33: return 0x00; + case 0x04: ret = virge->pci_regs[0x04] & 0x27; break; + + case 0x07: ret = virge->pci_regs[0x07] & 0x36; break; + + case 0x08: ret = 0; break; /*Revision ID*/ + case 0x09: ret = 0; break; /*Programming interface*/ + + case 0x0a: ret = 0x00; break; /*Supports VGA interface*/ + case 0x0b: ret = 0x03; /*output = 3; */break; + + case 0x0d: ret = virge->pci_regs[0x0d] & 0xf8; break; + + case 0x10: ret = 0x00; break;/*Linear frame buffer address*/ + case 0x11: ret = 0x00; break; + case 0x12: ret = 0x00; break; + case 0x13: ret = svga->crtc[0x59] & 0xfc; break; + + case 0x30: ret = virge->pci_regs[0x30] & 0x01; break; /*BIOS ROM address*/ + case 0x31: ret = 0x00; break; + case 0x32: ret = virge->pci_regs[0x32]; break; + case 0x33: ret = virge->pci_regs[0x33]; break; + + case 0x3c: ret = virge->pci_regs[0x3c]; break; + + case 0x3d: ret = 0x01; break; /*INTA*/ + + case 0x3e: ret = 0x04; break; + case 0x3f: ret = 0xff; break; } - return virge->pci_regs[addr]; +// pclog("%02X\n", ret); + return ret; } -void s3_virge_pci_write(int func, int addr, uint8_t val, void *p) +static void s3_virge_pci_write(int func, int addr, uint8_t val, void *p) { virge_t *virge = (virge_t *)p; svga_t *svga = &virge->svga; - +// pclog("S3 PCI write %08X %02X %04X:%08X\n", addr, val, CS, pc); switch (addr) { case 0x00: case 0x01: case 0x02: case 0x03: case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x3d: case 0x3e: case 0x3f: - break; + return; + + case PCI_REG_COMMAND: + if (val & PCI_COMMAND_IO) + { + io_removehandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); + io_sethandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); + } + else + io_removehandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); + virge->pci_regs[PCI_REG_COMMAND] = val & 0x27; + return; + case 0x07: + virge->pci_regs[0x07] = val & 0x3e; + return; + case 0x0d: + virge->pci_regs[0x0d] = val & 0xf8; + return; case 0x13: svga->crtc[0x59] = val & 0xfc; s3_virge_updatemapping(virge); - break; + return; + + case 0x30: case 0x32: case 0x33: + virge->pci_regs[addr] = val; + if (virge->pci_regs[0x30] & 0x01) + { + uint32_t addr = (virge->pci_regs[0x32] << 16) | (virge->pci_regs[0x33] << 24); + pclog("Virge bios_rom enabled at %08x\n", addr); + mem_mapping_set_addr(&virge->bios_rom.mapping, addr, 0x8000); + mem_mapping_enable(&virge->bios_rom.mapping); + } + else + { + pclog("Virge bios_rom disabled\n"); + mem_mapping_disable(&virge->bios_rom.mapping); + } + return; + case 0x3c: + virge->pci_regs[0x3c] = val; + return; } - virge->pci_regs[addr] = val; } -void *s3_virge_init() +static void *s3_virge_init() { virge_t *virge = malloc(sizeof(virge_t)); memset(virge, 0, sizeof(virge_t)); - + svga_init(&virge->svga, virge, 1 << 22, /*4mb*/ s3_virge_recalctimings, s3_virge_in, s3_virge_out, s3_virge_hwcursor_draw); - mem_mapping_add(&virge->mmio_mapping, 0, 0, s3_virge_mmio_read, s3_virge_mmio_read_w, s3_virge_mmio_read_l, s3_virge_mmio_write, s3_virge_mmio_write_w, s3_virge_mmio_write_l, virge); - mem_mapping_add(&virge->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, &virge->svga); + rom_init(&virge->bios_rom, "roms/s3virge.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + if (PCI) + mem_mapping_disable(&virge->bios_rom.mapping); + + mem_mapping_add(&virge->mmio_mapping, 0, 0, s3_virge_mmio_read, + s3_virge_mmio_read_w, + s3_virge_mmio_read_l, + s3_virge_mmio_write, + s3_virge_mmio_write_w, + s3_virge_mmio_write_l, + NULL, + 0, + virge); + mem_mapping_add(&virge->new_mmio_mapping, 0, 0, s3_virge_new_mmio_read, + s3_virge_new_mmio_read_w, + s3_virge_new_mmio_read_l, + s3_virge_new_mmio_write, + s3_virge_new_mmio_write_w, + s3_virge_new_mmio_write_l, + NULL, + 0, + virge); + mem_mapping_add(&virge->linear_mapping, 0, 0, svga_read_linear, + svga_readw_linear, + svga_readl_linear, + svga_write_linear, + svga_writew_linear, + svga_writel_linear, + NULL, + 0, + &virge->svga); io_sethandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); @@ -467,6 +1312,7 @@ void *s3_virge_init() virge->pci_regs[5] = 0; virge->pci_regs[6] = 0; virge->pci_regs[7] = 2; + virge->pci_regs[0x32] = 0x0c; virge->pci_regs[0x3d] = 1; virge->pci_regs[0x3e] = 4; virge->pci_regs[0x3f] = 0xff; @@ -476,15 +1322,17 @@ void *s3_virge_init() virge->virge_rev = 0; virge->virge_id = 0xe1; - virge->svga.crtc[0x36] = 1 | (2 << 2) | (1 << 4) | (4 << 5); - virge->svga.crtc[0x37] = 1 | (7 << 5); + virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4); + virge->svga.crtc[0x37] = 1;// | (7 << 5); + virge->svga.crtc[0x53] = 1 << 3; + virge->svga.crtc[0x59] = 0x70; pci_add(s3_virge_pci_read, s3_virge_pci_write, virge); return virge; } -void s3_virge_close(void *p) +static void s3_virge_close(void *p) { virge_t *virge = (virge_t *)p; @@ -493,21 +1341,26 @@ void s3_virge_close(void *p) free(virge); } -void s3_virge_speed_changed(void *p) +static int s3_virge_available() +{ + return rom_present("roms/s3virge.bin"); +} + +static void s3_virge_speed_changed(void *p) { virge_t *virge = (virge_t *)p; svga_recalctimings(&virge->svga); } -void s3_virge_force_redraw(void *p) +static void s3_virge_force_redraw(void *p) { virge_t *virge = (virge_t *)p; virge->svga.fullchange = changeframecount; } -int s3_virge_add_status_info(char *s, int max_len, void *p) +static int s3_virge_add_status_info(char *s, int max_len, void *p) { virge_t *virge = (virge_t *)p; @@ -520,7 +1373,7 @@ device_t s3_virge_device = DEVICE_NOT_WORKING, s3_virge_init, s3_virge_close, - NULL, + s3_virge_available, s3_virge_speed_changed, s3_virge_force_redraw, s3_virge_add_status_info diff --git a/src/vid_svga.c b/src/vid_svga.c index 5193abc..d73ff15 100644 --- a/src/vid_svga.c +++ b/src/vid_svga.c @@ -641,7 +641,7 @@ int svga_init(svga_t *svga, void *p, int memsize, svga->hwcursor_draw = hwcursor_draw; // _svga_recalctimings(svga); - mem_mapping_add(&svga->mapping, 0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, svga); + mem_mapping_add(&svga->mapping, 0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL, 0, svga); timer_add(svga_poll, &svga->vidtime, TIMER_ALWAYS_ENABLED, svga); vramp = svga->vram; diff --git a/src/vid_tandy.c b/src/vid_tandy.c index c7883fa..d7ed474 100644 --- a/src/vid_tandy.c +++ b/src/vid_tandy.c @@ -667,7 +667,7 @@ void *tandy_init() q_filt[c] = 512.0 * sin((3.14 * (tandy_tint + c * 4) / 16.0) - 33.0 / 180.0); } timer_add(tandy_poll, &tandy->vidtime, TIMER_ALWAYS_ENABLED, tandy); - mem_mapping_add(&tandy->mapping, 0xb8000, 0x08000, tandy_read, NULL, NULL, tandy_write, NULL, NULL, tandy); + mem_mapping_add(&tandy->mapping, 0xb8000, 0x08000, tandy_read, NULL, NULL, tandy_write, NULL, NULL, NULL, 0, tandy); io_sethandler(0x03d0, 0x0010, tandy_in, NULL, NULL, tandy_out, NULL, NULL, tandy); io_sethandler(0x00a0, 0x0001, tandy_in, NULL, NULL, tandy_out, NULL, NULL, tandy); return tandy; diff --git a/src/vid_tgui9440.c b/src/vid_tgui9440.c index 152c2fd..1aeba17 100644 --- a/src/vid_tgui9440.c +++ b/src/vid_tgui9440.c @@ -4,6 +4,7 @@ #include "device.h" #include "io.h" #include "mem.h" +#include "rom.h" #include "video.h" #include "vid_svga.h" #include "vid_svga_render.h" @@ -15,6 +16,8 @@ typedef struct tgui_t mem_mapping_t linear_mapping; mem_mapping_t accel_mapping; + rom_t bios_rom; + svga_t svga; struct @@ -462,37 +465,20 @@ void tgui_pci_write(int func, int addr, uint8_t val, void *p) } } -void *tgui8900d_init() -{ - tgui_t *tgui = malloc(sizeof(tgui_t)); - memset(tgui, 0, sizeof(tgui_t)); - - svga_init(&tgui->svga, tgui, 1 << 20, /*1mb - chip supports 2mb, but drivers are buggy*/ - tgui_recalctimings, - tgui_in, tgui_out, - NULL); - - mem_mapping_add(&tgui->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, &tgui->svga); - mem_mapping_add(&tgui->accel_mapping, 0xbc000, 0x4000, tgui_accel_read, tgui_accel_read_w, tgui_accel_read_l, tgui_accel_write, tgui_accel_write_w, tgui_accel_write_l, tgui); - mem_mapping_disable(&tgui->linear_mapping); - mem_mapping_disable(&tgui->accel_mapping); - - io_sethandler(0x03c0, 0x0020, tgui_in, NULL, NULL, tgui_out, NULL, NULL, tgui); - - return tgui; -} void *tgui9440_init() { tgui_t *tgui = malloc(sizeof(tgui_t)); memset(tgui, 0, sizeof(tgui_t)); + rom_init(&tgui->bios_rom, "roms/9440.vbi", 0xc0000, 0x8000, 0x7fff, 0, 0); + svga_init(&tgui->svga, tgui, 1 << 21, /*2mb*/ tgui_recalctimings, tgui_in, tgui_out, tgui_hwcursor_draw); - mem_mapping_add(&tgui->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, &tgui->svga); - mem_mapping_add(&tgui->accel_mapping, 0xbc000, 0x4000, tgui_accel_read, tgui_accel_read_w, tgui_accel_read_l, tgui_accel_write, tgui_accel_write_w, tgui_accel_write_l, tgui); + mem_mapping_add(&tgui->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL, 0, &tgui->svga); + mem_mapping_add(&tgui->accel_mapping, 0xbc000, 0x4000, tgui_accel_read, tgui_accel_read_w, tgui_accel_read_l, tgui_accel_write, tgui_accel_write_w, tgui_accel_write_l, NULL, 0, tgui); mem_mapping_disable(&tgui->accel_mapping); io_sethandler(0x03c0, 0x0020, tgui_in, NULL, NULL, tgui_out, NULL, NULL, tgui); @@ -503,6 +489,11 @@ void *tgui9440_init() return tgui; } +static int tgui9440_available() +{ + return rom_present("roms/9440.vbi"); +} + void tgui_close(void *p) { tgui_t *tgui = (tgui_t *)p; @@ -1127,7 +1118,7 @@ device_t tgui9440_device = 0, tgui9440_init, tgui_close, - NULL, + tgui9440_available, tgui_speed_changed, tgui_force_redraw, tgui_add_status_info diff --git a/src/vid_tvga.c b/src/vid_tvga.c index 813c32d..a6c91e7 100644 --- a/src/vid_tvga.c +++ b/src/vid_tvga.c @@ -4,6 +4,7 @@ #include "device.h" #include "io.h" #include "mem.h" +#include "rom.h" #include "video.h" #include "vid_svga.h" #include "vid_svga_render.h" @@ -17,6 +18,8 @@ typedef struct tvga_t svga_t svga; tkd8001_ramdac_t ramdac; + + rom_t bios_rom; uint8_t tvga_3d8, tvga_3d9; int oldmode; @@ -48,7 +51,10 @@ void tvga_out(uint16_t addr, uint8_t val, void *p) break; case 0xd: if (tvga->oldmode) - tvga->oldctrl2 = val; + { + tvga->oldctrl2 = val; + svga->vrammask = (val & 0x10) ? 0xfffff : 0x3ffff; + } else tvga->newctrl2 = val; break; @@ -92,7 +98,7 @@ void tvga_out(uint16_t addr, uint8_t val, void *p) if (svga->crtcreg <= 7 && svga->crtc[0x11] & 0x80) return; old = svga->crtc[svga->crtcreg]; svga->crtc[svga->crtcreg] = val; -// if (svga->crtcreg != 0xE && svga->crtcreg != 0xF) pclog("CRTC R%02X = %02X\n", svga->crtcreg, val); +// if (svga->crtcreg != 0xC && svga->crtcreg != 0xE && svga->crtcreg != 0xF) pclog("CRTC R%02X = %02X %04X:%04X\n", svga->crtcreg, val, CS, pc); if (old != val) { if (svga->crtcreg < 0xE || svga->crtcreg > 0x10) @@ -240,6 +246,8 @@ void *tvga8900d_init() { tvga_t *tvga = malloc(sizeof(tvga_t)); memset(tvga, 0, sizeof(tvga_t)); + + rom_init(&tvga->bios_rom, "roms/trident.bin", 0xc0000, 0x8000, 0x7fff, 0, 0); svga_init(&tvga->svga, tvga, 1 << 20, /*1mb - chip supports 2mb, but drivers are buggy*/ tvga_recalctimings, @@ -251,6 +259,11 @@ void *tvga8900d_init() return tvga; } +static int tvga8900d_available() +{ + return rom_present("roms/trident.bin"); +} + void tvga_close(void *p) { tvga_t *tvga = (tvga_t *)p; @@ -287,7 +300,7 @@ device_t tvga8900d_device = 0, tvga8900d_init, tvga_close, - NULL, + tvga8900d_available, tvga_speed_changed, tvga_force_redraw, tvga_add_status_info diff --git a/src/vid_vga.c b/src/vid_vga.c index 9ec2777..830fc21 100644 --- a/src/vid_vga.c +++ b/src/vid_vga.c @@ -4,6 +4,7 @@ #include "device.h" #include "io.h" #include "mem.h" +#include "rom.h" #include "video.h" #include "vid_svga.h" #include "vid_vga.h" @@ -11,6 +12,8 @@ typedef struct vga_t { svga_t svga; + + rom_t bios_rom; } vga_t; void vga_out(uint16_t addr, uint8_t val, void *p) @@ -78,6 +81,8 @@ void *vga_init() vga_t *vga = malloc(sizeof(vga_t)); memset(vga, 0, sizeof(vga_t)); + rom_init(&vga->bios_rom, "roms/ibm_vga.bin", 0xc0000, 0x8000, 0x7fff, 0, 0); + svga_init(&vga->svga, vga, 1 << 18, /*256kb*/ NULL, vga_in, vga_out, @@ -91,6 +96,11 @@ void *vga_init() return vga; } +static int vga_available() +{ + return rom_present("roms/ibm_vga.bin"); +} + void vga_close(void *p) { vga_t *vga = (vga_t *)p; @@ -127,7 +137,7 @@ device_t vga_device = DEVICE_NOT_WORKING, vga_init, vga_close, - NULL, + vga_available, vga_speed_changed, vga_force_redraw, vga_add_status_info diff --git a/src/vid_voodoo.c b/src/vid_voodoo.c index b8d5434..7156b06 100644 --- a/src/vid_voodoo.c +++ b/src/vid_voodoo.c @@ -734,9 +734,9 @@ void voodoo_init() voodoo_make_dither(); pci_add(voodoo_pci_read, voodoo_pci_write, NULL); - mem_mapping_add(&voodoo.mmio_mapping, 0, 0, NULL, NULL, voodoo_readl, NULL, NULL, voodoo_writel, NULL); - mem_mapping_add(&voodoo.fb_mapping, 0, 0, NULL, voodoo_fb_readw, voodoo_fb_readl, NULL, voodoo_fb_writew, voodoo_fb_writel, NULL); - mem_mapping_add(&voodoo.tex_mapping, 0, 0, NULL, NULL, NULL, NULL, voodoo_tex_writew, voodoo_tex_writel, NULL); + mem_mapping_add(&voodoo.mmio_mapping, 0, 0, NULL, NULL, voodoo_readl, NULL, NULL, voodoo_writel, NULL, 0, NULL); + mem_mapping_add(&voodoo.fb_mapping, 0, 0, NULL, voodoo_fb_readw, voodoo_fb_readl, NULL, voodoo_fb_writew, voodoo_fb_writel, NULL, 0, NULL); + mem_mapping_add(&voodoo.tex_mapping, 0, 0, NULL, NULL, NULL, NULL, voodoo_tex_writew, voodoo_tex_writel, NULL, 0, NULL); voodoo.fb_mem = malloc(2 * 1024 * 1024); voodoo.tex_mem = malloc(2 * 1024 * 1024); diff --git a/src/video.c b/src/video.c index bb8ec69..7601493 100644 --- a/src/video.c +++ b/src/video.c @@ -8,6 +8,7 @@ #include "vid_svga.h" #include "io.h" #include "cpu.h" +#include "rom.h" #include "timer.h" #include "vid_ati18800.h" @@ -229,11 +230,15 @@ void video_init() return; case ROM_PC2086: - case ROM_PC3086: - device_add(¶dise_pvga1a_device); + device_add(¶dise_pvga1a_pc2086_device); return; + + case ROM_PC3086: + device_add(¶dise_pvga1a_pc3086_device); + return; + case ROM_MEGAPC: - device_add(¶dise_wd90c11_device); + device_add(¶dise_wd90c11_megapc_device); return; case ROM_ACER386: diff --git a/src/win.c b/src/win.c index 03f6900..7db963b 100644 --- a/src/win.c +++ b/src/win.c @@ -386,18 +386,14 @@ int WINAPI WinMain (HINSTANCE hThisInstance, } } - d = gfxcard; + for (c = 0; c < 18; c++) - { - gfxcard = c; - gfx_present[c] = mem_load_video_bios(); - } - gfxcard = d; - c = mem_load_video_bios(); - if (!c) + gfx_present[c] = video_card_available(video_old_to_new(c)); + + if (!video_card_available(video_old_to_new(gfxcard))) { if (romset!=-1) MessageBox(hwnd,"Configured video BIOS not available.\nDefaulting to available romset.","PCem error",MB_OK); - for (c=0;c<18;c++) + for (c = 17; c >= 0; c--) { if (gfx_present[c]) { @@ -783,7 +779,6 @@ BOOL CALLBACK configdlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lPara sound_card_current = temp_sound_card_current; mem_resize(); - mem_load_video_bios(); loadbios(); resetpchard(); }