Now up to date with current dev version.

Changes since v0.7 :
- Major CPU reorganisation. This has possibly broken some stuff, though I fixed all the regressions I could find
- Lazy flags. This brought 10% speed improvement at one point, but that's probably been lost now
- 430 VX chipset emulation
- IDT Winchip emulation (currently sans MMX). Timing is probably wrong
- Fixed a few FPU bugs
- Timer reorganisation
- Sound reorganisation
- Other general reorganisation
- AdLib Gold emulation
- Windows Sound System emulation
- Pro Audio Spectrum 16 emulation. This currently works with most DOS stuff, but not in Windows
- Major improvements to GUS emulation. Has the downside that it now conflicts with SB emulation, so probably best to not enable both simultaneously
- New graphics cards :
  - ATI-18800 (VGA Edge-16)
  - ATI-28800 (VGA Charger)
  - ATI Mach64GX (Graphics Pro Turbo). Quite a few features missing, but Windows doesn't seem to use half the features of this card
  - Cirrus Logic CL-GD5429. Blitter is a bit broken
  - Oak OTI-067
  - S3 Trio64 (Number Nine 9FX)
  - S3 Virge. Only framebuffer stuff at the minute, Windows won't recognise the card
  - Trident TGUI-9440
  - VGA. Doesn't work yet
- Beginnings of 3DFX emulation, however this is in extremely early stages and doesn't do anything useful
- Fixed DMA bug stopping floppy drives working in Windows 3.x
- Fixed some other stuff probably
- Broke some other stuff probably as well
This commit is contained in:
TomW 2013-05-27 17:46:42 +01:00
commit 9312de19ac
87 changed files with 4528 additions and 9373 deletions

7748
src/386.c

File diff suppressed because it is too large Load diff

View file

@ -3,20 +3,22 @@ CPP = g++.exe
CC = gcc.exe CC = gcc.exe
WINDRES = windres.exe WINDRES = windres.exe
CFLAGS = -O3 -march=i686 -fomit-frame-pointer CFLAGS = -O3 -march=i686 -fomit-frame-pointer
OBJ = 286.o 386.o acer386sx.o adlib.o ali1429.o amstrad.o cdrom-ioctl.o cms.o \ OBJ = 386.o 808x.o acer386sx.o ali1429.o amstrad.o cdrom-ioctl.o \
config.o cpu.o dac.o dma.o ega.o fdc.o gus.o harddisk.o \ config.o cpu.o dac.o device.o dma.o ega.o fdc.o harddisk.o \
headland.o ide.o io.o jim.o keyboard.o keyboard_amstrad.o keyboard_at.o \ headland.o i430vx.o ide.o io.o jim.o keyboard.o keyboard_amstrad.o keyboard_at.o \
keyboard_olim24.o keyboard_xt.o lpt.o mcr.o mem.o model.o \ keyboard_olim24.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 \ mouse.o mouse_ps2.o mouse_serial.o neat.o nvr.o olivetti_m24.o \
opti.o pc.o pci.o pic.o pit.o \ opti.o pc.o pci.o pic.o piix.o pit.o ppi.o serial.o sound.o sound_adlib.o \
ppi.o psg.o sblaster.o serial.o sound.o soundopenal.o um8881f.o \ sound_adlibgold.o sound_cms.o sound_gus.o sound_opl.o sound_pas16.o sound_sb.o \
vid_cga.o vid_ega.o vid_et4000.o vid_et4000w32.o \ sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_wss.o soundopenal.o timer.o \
vid_et4000w32i.o vid_hercules.o vid_icd2061.o vid_mda.o vid_olivetti_m24.o \ um8881f.o um8669f.o vid_ati_eeprom.o vid_ati_mach64.o vid_ati18800.o \
vid_oti067.o vid_paradise.o vid_pc1512.o vid_pc1640.o \ vid_ati28800.o vid_ati68860_ramdac.o vid_cga.o vid_cl5429.o vid_ega.o \
vid_pc200.o vid_s3.o vid_sdac_ramdac.o vid_stg_ramdac.o \ vid_et4000.o vid_et4000w32.o vid_et4000w32i.o vid_hercules.o vid_icd2061.o \
vid_svga.o vid_tandy.o vid_tkd8001_ramdac.o vid_tvga.o \ vid_ics2595.o vid_mda.o vid_olivetti_m24.o vid_oti067.o vid_paradise.o \
vid_unk_ramdac.o video.o wd76c10.o win.o win-ddraw.o \ vid_pc1512.o vid_pc1640.o vid_pc200.o vid_s3.o vid_s3_virge.o vid_sdac_ramdac.o \
win-keyboard.o win-mouse.o win-timer.o win-video.o x86.o \ vid_stg_ramdac.o vid_svga.o vid_svga_render.o vid_tandy.o vid_tkd8001_ramdac.o \
vid_tvga.o vid_unk_ramdac.o vid_vga.o vid_voodoo.o video.o wd76c10.o \
win.o win-ddraw.o win-keyboard.o win-mouse.o win-timer.o win-video.o \
x86seg.o x87.o xtide.o pc.res x86seg.o x87.o xtide.o pc.res
FMOBJ = fmopl.o ymf262.o FMOBJ = fmopl.o ymf262.o

View file

@ -7,7 +7,7 @@
static int acer_index = 0; static int acer_index = 0;
static uint8_t acer_regs[256]; static uint8_t acer_regs[256];
void acer386sx_write(uint16_t addr, uint8_t val) void acer386sx_write(uint16_t addr, uint8_t val, void *priv)
{ {
if (addr & 1) if (addr & 1)
acer_regs[acer_index] = val; acer_regs[acer_index] = val;
@ -15,7 +15,7 @@ void acer386sx_write(uint16_t addr, uint8_t val)
acer_index = val; acer_index = val;
} }
uint8_t acer386sx_read(uint16_t addr) uint8_t acer386sx_read(uint16_t addr, void *priv)
{ {
if (addr & 1) if (addr & 1)
{ {
@ -29,5 +29,5 @@ uint8_t acer386sx_read(uint16_t addr)
void acer386sx_init() void acer386sx_init()
{ {
io_sethandler(0x0022, 0x0002, acer386sx_read, NULL, NULL, acer386sx_write, NULL, NULL); io_sethandler(0x0022, 0x0002, acer386sx_read, NULL, NULL, acer386sx_write, NULL, NULL, NULL);
} }

View file

@ -9,7 +9,7 @@
static int ali1429_index; static int ali1429_index;
static uint8_t ali1429_regs[256]; static uint8_t ali1429_regs[256];
void ali1429_write(uint16_t port, uint8_t val) void ali1429_write(uint16_t port, uint8_t val, void *priv)
{ {
// return; // return;
if (!(port&1)) ali1429_index=val; if (!(port&1)) ali1429_index=val;
@ -31,9 +31,9 @@ void ali1429_write(uint16_t port, uint8_t val)
{ {
shadowbios=0; shadowbios=0;
if (!shadowbios_write) if (!shadowbios_write)
mem_sethandler(0xf0000, 0x10000, mem_read_bios, mem_read_biosw, mem_read_biosl, NULL, NULL, NULL ); mem_sethandler(0xf0000, 0x10000, mem_read_bios, mem_read_biosw, mem_read_biosl, NULL, NULL, NULL, NULL);
else else
mem_sethandler(0xf0000, 0x10000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml); mem_sethandler(0xf0000, 0x10000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml, NULL);
flushmmucache(); flushmmucache();
} }
break; break;
@ -42,10 +42,10 @@ void ali1429_write(uint16_t port, uint8_t val)
shadowbios_write=val&2; shadowbios_write=val&2;
switch (val & 3) switch (val & 3)
{ {
case 0: mem_sethandler(0xf0000, 0x10000, mem_read_bios, mem_read_biosw, mem_read_biosl, NULL, NULL, NULL ); break; case 0: mem_sethandler(0xf0000, 0x10000, mem_read_bios, mem_read_biosw, mem_read_biosl, NULL, NULL, NULL, NULL); break;
case 1: mem_sethandler(0xf0000, 0x10000, mem_read_ram, mem_read_ramw, mem_read_raml, NULL, NULL, NULL ); break; case 1: mem_sethandler(0xf0000, 0x10000, mem_read_ram, mem_read_ramw, mem_read_raml, NULL, NULL, NULL, NULL); break;
case 2: mem_sethandler(0xf0000, 0x10000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml); break; case 2: mem_sethandler(0xf0000, 0x10000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml, NULL); break;
case 3: mem_sethandler(0xf0000, 0x10000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml); break; case 3: mem_sethandler(0xf0000, 0x10000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, NULL); break;
} }
// if (val==0x43) shadowbios=1; // if (val==0x43) shadowbios=1;
@ -56,7 +56,7 @@ void ali1429_write(uint16_t port, uint8_t val)
} }
} }
uint8_t ali1429_read(uint16_t port) uint8_t ali1429_read(uint16_t port, void *priv)
{ {
if (!(port&1)) return ali1429_index; if (!(port&1)) return ali1429_index;
if ((ali1429_index >= 0xc0 || ali1429_index == 0x20) && cpu_iscyrix) if ((ali1429_index >= 0xc0 || ali1429_index == 0x20) && cpu_iscyrix)
@ -72,5 +72,5 @@ void ali1429_reset()
void ali1429_init() void ali1429_init()
{ {
io_sethandler(0x0022, 0x0002, ali1429_read, NULL, NULL, ali1429_write, NULL, NULL); io_sethandler(0x0022, 0x0002, ali1429_read, NULL, NULL, ali1429_write, NULL, NULL, NULL);
} }

View file

@ -8,7 +8,7 @@
static uint8_t amstrad_dead; static uint8_t amstrad_dead;
uint8_t amstrad_read(uint16_t port) uint8_t amstrad_read(uint16_t port, void *priv)
{ {
pclog("amstrad_read : %04X\n",port); pclog("amstrad_read : %04X\n",port);
switch (port) switch (port)
@ -25,7 +25,7 @@ uint8_t amstrad_read(uint16_t port)
return 0xff; return 0xff;
} }
void amstrad_write(uint16_t port, uint8_t val) void amstrad_write(uint16_t port, uint8_t val, void *priv)
{ {
switch (port) switch (port)
{ {
@ -37,16 +37,15 @@ void amstrad_write(uint16_t port, uint8_t val)
static uint8_t mousex,mousey; static uint8_t mousex,mousey;
void amstrad_mouse_write(uint16_t addr, uint8_t val) void amstrad_mouse_write(uint16_t addr, uint8_t val, void *priv)
{ {
// pclog("Write mouse %04X %02X %04X:%04X\n", addr, val, CS, pc); // pclog("Write mouse %04X %02X %04X:%04X\n", addr, val, CS, pc);
if (addr==0x78) mousex=0; if (addr==0x78) mousex=0;
else mousey=0; else mousey=0;
} }
uint8_t amstrad_mouse_read(uint16_t addr) uint8_t amstrad_mouse_read(uint16_t addr, void *priv)
{ {
uint8_t temp;
// printf("Read mouse %04X %04X:%04X %02X\n", addr, CS, pc, (addr == 0x78) ? mousex : mousey); // printf("Read mouse %04X %04X:%04X %02X\n", addr, CS, pc, (addr == 0x78) ? mousex : mousey);
if (addr==0x78) return mousex; if (addr==0x78) return mousex;
return mousey; return mousey;
@ -73,12 +72,12 @@ void amstrad_mouse_poll(int x, int y, int b)
void amstrad_init() void amstrad_init()
{ {
lpt2_remove(); lpt2_remove_ams();
io_sethandler(0x0078, 0x0001, amstrad_mouse_read, NULL, NULL, amstrad_mouse_write, NULL, NULL); io_sethandler(0x0078, 0x0001, amstrad_mouse_read, NULL, NULL, amstrad_mouse_write, NULL, NULL, NULL);
io_sethandler(0x007a, 0x0001, amstrad_mouse_read, NULL, NULL, amstrad_mouse_write, NULL, NULL); io_sethandler(0x007a, 0x0001, amstrad_mouse_read, NULL, NULL, amstrad_mouse_write, NULL, NULL, NULL);
io_sethandler(0x0379, 0x0002, amstrad_read, NULL, NULL, NULL, NULL, NULL); io_sethandler(0x0379, 0x0002, amstrad_read, NULL, NULL, NULL, NULL, NULL, NULL);
io_sethandler(0xdead, 0x0001, amstrad_read, NULL, NULL, amstrad_write, NULL, NULL); io_sethandler(0xdead, 0x0001, amstrad_read, NULL, NULL, amstrad_write, NULL, NULL, NULL);
mouse_poll = amstrad_mouse_poll; mouse_poll = amstrad_mouse_poll;
} }

View file

@ -44,7 +44,7 @@ void ioctl_audio_callback(int16_t *output, int len)
{ {
RAW_READ_INFO in; RAW_READ_INFO in;
DWORD count; DWORD count;
int c;
// return; // return;
// pclog("Audio callback %08X %08X %i %i %i %04X %i\n", ioctl_cd_pos, ioctl_cd_end, ioctl_cd_state, cd_buflen, len, cd_buffer[4], GetTickCount()); // pclog("Audio callback %08X %08X %i %i %i %04X %i\n", ioctl_cd_pos, ioctl_cd_end, ioctl_cd_state, cd_buflen, len, cd_buffer[4], GetTickCount());
if (ioctl_cd_state != CD_PLAYING) if (ioctl_cd_state != CD_PLAYING)
@ -143,7 +143,6 @@ static void ioctl_playaudio(uint32_t pos, uint32_t len, int ismsf)
static void ioctl_pause(void) static void ioctl_pause(void)
{ {
long size;
if (!cdrom_drive) return; if (!cdrom_drive) return;
if (ioctl_cd_state == CD_PLAYING) if (ioctl_cd_state == CD_PLAYING)
ioctl_cd_state = CD_PAUSED; ioctl_cd_state = CD_PAUSED;
@ -154,7 +153,6 @@ static void ioctl_pause(void)
static void ioctl_resume(void) static void ioctl_resume(void)
{ {
long size;
if (!cdrom_drive) return; if (!cdrom_drive) return;
if (ioctl_cd_state == CD_PAUSED) if (ioctl_cd_state == CD_PAUSED)
ioctl_cd_state = CD_PLAYING; ioctl_cd_state = CD_PLAYING;
@ -165,7 +163,6 @@ static void ioctl_resume(void)
static void ioctl_stop(void) static void ioctl_stop(void)
{ {
long size;
if (!cdrom_drive) return; if (!cdrom_drive) return;
ioctl_cd_state = CD_STOPPED; ioctl_cd_state = CD_STOPPED;
// ioctl_open(0); // ioctl_open(0);
@ -175,7 +172,6 @@ static void ioctl_stop(void)
static void ioctl_seek(uint32_t pos) static void ioctl_seek(uint32_t pos)
{ {
long size;
if (!cdrom_drive) return; if (!cdrom_drive) return;
// ioctl_cd_state = CD_STOPPED; // ioctl_cd_state = CD_STOPPED;
pclog("Seek %08X\n", pos); pclog("Seek %08X\n", pos);
@ -229,8 +225,7 @@ static uint8_t ioctl_getcurrentsubchannel(uint8_t *b, int msf)
SUB_Q_CHANNEL_DATA sub; SUB_Q_CHANNEL_DATA sub;
long size; long size;
int pos=0; int pos=0;
int c; uint32_t cdpos;
uint32_t temp, cdpos;
if (!cdrom_drive) return 0; if (!cdrom_drive) return 0;
insub.Format = IOCTL_CDROM_CURRENT_POSITION; insub.Format = IOCTL_CDROM_CURRENT_POSITION;
ioctl_open(0); ioctl_open(0);

View file

@ -26,7 +26,7 @@ int get_config_int(char *head, char *name, int def)
if (!f) if (!f)
return def; return def;
pclog("Searching for %s\n", name); // pclog("Searching for %s\n", name);
while (1) while (1)
{ {
@ -46,9 +46,9 @@ int get_config_int(char *head, char *name, int def)
if (!buffer[c]) continue; if (!buffer[c]) continue;
name2[d] = 0; name2[d] = 0;
pclog("Comparing %s and %s\n", name, name2); // pclog("Comparing %s and %s\n", name, name2);
if (strcmp(name, name2)) continue; if (strcmp(name, name2)) continue;
pclog("Found!\n"); // pclog("Found!\n");
while ((buffer[c] == '=' || buffer[c] == ' ') && buffer[c]) while ((buffer[c] == '=' || buffer[c] == ' ') && buffer[c])
c++; c++;
@ -56,7 +56,7 @@ int get_config_int(char *head, char *name, int def)
if (!buffer[c]) continue; if (!buffer[c]) continue;
sscanf(&buffer[c], "%i", &res); sscanf(&buffer[c], "%i", &res);
pclog("Reading value - %i\n", res); // pclog("Reading value - %i\n", res);
break; break;
} }
@ -78,7 +78,7 @@ char *get_config_string(char *head, char *name, char *def)
if (!f) if (!f)
return config_return_string; return config_return_string;
pclog("Searching for %s\n", name); // pclog("Searching for %s\n", name);
while (1) while (1)
{ {
@ -98,9 +98,9 @@ char *get_config_string(char *head, char *name, char *def)
if (!buffer[c]) continue; if (!buffer[c]) continue;
name2[d] = 0; name2[d] = 0;
pclog("Comparing %s and %s\n", name, name2); // pclog("Comparing %s and %s\n", name, name2);
if (strcmp(name, name2)) continue; if (strcmp(name, name2)) continue;
pclog("Found!\n"); // pclog("Found!\n");
while ((buffer[c] == '=' || buffer[c] == ' ') && buffer[c]) while ((buffer[c] == '=' || buffer[c] == ' ') && buffer[c])
c++; c++;
@ -110,11 +110,11 @@ char *get_config_string(char *head, char *name, char *def)
strcpy(config_return_string, &buffer[c]); strcpy(config_return_string, &buffer[c]);
c = strlen(config_return_string) - 1; c = strlen(config_return_string) - 1;
pclog("string len %i\n", c); // pclog("string len %i\n", c);
while (config_return_string[c] <= 32 && config_return_string[c]) while (config_return_string[c] <= 32 && config_return_string[c])
config_return_string[c--] = 0; config_return_string[c--] = 0;
pclog("Reading value - %s\n", config_return_string); // pclog("Reading value - %s\n", config_return_string);
break; break;
} }
@ -125,19 +125,19 @@ char *get_config_string(char *head, char *name, char *def)
void set_config_int(char *head, char *name, int val) void set_config_int(char *head, char *name, int val)
{ {
FILE *f = fopen(config_file, "at"); FILE *f = fopen(config_file, "at");
if (!f) pclog("set_config_int - !f\n"); // if (!f) pclog("set_config_int - !f\n");
fprintf(f, "%s = %i\n", name, val); fprintf(f, "%s = %i\n", name, val);
pclog("Write %s = %i\n", name, val); // pclog("Write %s = %i\n", name, val);
fclose(f); fclose(f);
pclog("fclose\n"); // pclog("fclose\n");
} }
void set_config_string(char *head, char *name, char *val) void set_config_string(char *head, char *name, char *val)
{ {
FILE *f = fopen(config_file, "at"); FILE *f = fopen(config_file, "at");
if (!f) pclog("set_config_string - !f\n"); // if (!f) pclog("set_config_string - !f\n");
fprintf(f, "%s = %s\n", name, val); fprintf(f, "%s = %s\n", name, val);
pclog("Write %s = %s\n", name, val); // pclog("Write %s = %s\n", name, val);
fclose(f); fclose(f);
} }

View file

@ -3,3 +3,7 @@ int get_config_int(char *head, char *name, int def);
char *get_config_string(char *head, char *name, char *def); char *get_config_string(char *head, char *name, char *def);
void set_config_int(char *head, char *name, int val); void set_config_int(char *head, char *name, int val);
void set_config_string(char *head, char *name, char *val); void set_config_string(char *head, char *name, char *val);
char *get_filename(char *s);
void append_filename(char *dest, char *s1, char *s2, int size);
void put_backslash(char *s);

View file

@ -2,6 +2,7 @@
#include "cpu.h" #include "cpu.h"
#include "model.h" #include "model.h"
#include "io.h" #include "io.h"
#include "x86_ops.h"
int cpu = 3, cpu_manufacturer = 0; int cpu = 3, cpu_manufacturer = 0;
CPU *cpu_s; CPU *cpu_s;
@ -9,6 +10,7 @@ int cpu_multi;
int cpu_iscyrix; int cpu_iscyrix;
int cpu_16bitbus; int cpu_16bitbus;
int cpu_busspeed; int cpu_busspeed;
int cpu_hasrdtsc;
int timing_rr; int timing_rr;
int timing_mr, timing_mrl; int timing_mr, timing_mrl;
@ -32,6 +34,9 @@ int timing_bt, timing_bnt;
12 = 133 MHz 12 = 133 MHz
13 = 150 MHz 13 = 150 MHz
14 = 160 MHz 14 = 160 MHz
15 = 166 MHz
16 = 180 MHz
17 = 200 MHz
*/ */
CPU cpus_8088[] = CPU cpus_8088[] =
@ -197,6 +202,23 @@ CPU cpus_Cx486[] =
{"", -1, 0, 0, 0} {"", -1, 0, 0, 0}
}; };
CPU cpus_WinChip[] =
{
/*IDT WinChip*/
{"WinChip 75", CPU_WINCHIP, 7, 75000000, 2, 0x540, 0x540, 0},
{"WinChip 90", CPU_WINCHIP, 9, 90000000, 2, 0x540, 0x540, 0},
{"WinChip 100", CPU_WINCHIP, 10, 100000000, 2, 0x540, 0x540, 0},
{"WinChip 120", CPU_WINCHIP, 11, 120000000, 2, 0x540, 0x540, 0},
{"WinChip 133", CPU_WINCHIP, 12, 133333333, 2, 0x540, 0x540, 0},
{"WinChip 150", CPU_WINCHIP, 13, 150000000, 3, 0x540, 0x540, 0},
{"WinChip 166", CPU_WINCHIP, 15, 166666666, 3, 0x540, 0x540, 0},
{"WinChip 180", CPU_WINCHIP, 16, 180000000, 3, 0x540, 0x540, 0},
{"WinChip 200", CPU_WINCHIP, 17, 200000000, 3, 0x540, 0x540, 0},
{"WinChip 225", CPU_WINCHIP, 17, 225000000, 3, 0x540, 0x540, 0},
{"WinChip 240", CPU_WINCHIP, 17, 240000000, 6, 0x540, 0x540, 0},
{"", -1, 0, 0, 0}
};
void cpu_set_edx() void cpu_set_edx()
{ {
EDX = models[model].cpu[cpu_manufacturer].cpus[cpu].edx_reset; EDX = models[model].cpu[cpu_manufacturer].cpus[cpu].edx_reset;
@ -216,17 +238,37 @@ void cpu_set()
if (cpu_s->multi) if (cpu_s->multi)
cpu_busspeed = cpu_s->rspeed / cpu_s->multi; cpu_busspeed = cpu_s->rspeed / cpu_s->multi;
cpu_multi = cpu_s->multi; cpu_multi = cpu_s->multi;
cpu_hasrdtsc = 0;
if (cpu_iscyrix) if (cpu_iscyrix)
io_sethandler(0x0022, 0x0002, cyrix_read, NULL, NULL, cyrix_write, NULL, NULL); io_sethandler(0x0022, 0x0002, cyrix_read, NULL, NULL, cyrix_write, NULL, NULL, NULL);
else else
io_removehandler(0x0022, 0x0002, cyrix_read, NULL, NULL, cyrix_write, NULL, NULL); io_removehandler(0x0022, 0x0002, cyrix_read, NULL, NULL, cyrix_write, NULL, NULL, NULL);
pclog("hasfpu - %i\n",hasfpu); pclog("hasfpu - %i\n",hasfpu);
pclog("is486 - %i %i\n",is486,cpu_s->cpu_type); pclog("is486 - %i %i\n",is486,cpu_s->cpu_type);
x86_setopcodes(ops_386, ops_386_0f);
switch (cpu_s->cpu_type) switch (cpu_s->cpu_type)
{ {
case CPU_8088:
case CPU_8086:
break;
case CPU_286:
x86_setopcodes(ops_286, ops_286_0f);
timing_rr = 2; /*register dest - register src*/
timing_rm = 7; /*register dest - memory src*/
timing_mr = 7; /*memory dest - register src*/
timing_mm = 7; /*memory dest - memory src*/
timing_rml = 9; /*register dest - memory src long*/
timing_mrl = 11; /*memory dest - register src long*/
timing_mml = 11; /*memory dest - memory src*/
timing_bt = 7-3; /*branch taken*/
timing_bnt = 3; /*branch not taken*/
break;
case CPU_386SX: case CPU_386SX:
timing_rr = 2; /*register dest - register src*/ timing_rr = 2; /*register dest - register src*/
timing_rm = 6; /*register dest - memory src*/ timing_rm = 6; /*register dest - memory src*/
@ -326,6 +368,22 @@ void cpu_set()
timing_bt = 5-1; /*branch taken*/ timing_bt = 5-1; /*branch taken*/
timing_bnt = 1; /*branch not taken*/ timing_bnt = 1; /*branch not taken*/
break; break;
case CPU_WINCHIP:
timing_rr = 1; /*register dest - register src*/
timing_rm = 2; /*register dest - memory src*/
timing_mr = 3; /*memory dest - register src*/
timing_mm = 3;
timing_rml = 2; /*register dest - memory src long*/
timing_mrl = 3; /*memory dest - register src long*/
timing_mml = 3;
timing_bt = 3-1; /*branch taken*/
timing_bnt = 1; /*branch not taken*/
cpu_hasrdtsc = 1;
break;
default:
fatal("cpu_set : unknown CPU type %i\n", cpu_s->cpu_type);
} }
} }
@ -354,6 +412,7 @@ void cpu_CPUID()
case CPU_Am486SX: case CPU_Am486SX:
if (!EAX) if (!EAX)
{ {
EAX = 1;
EBX = 0x68747541; EBX = 0x68747541;
ECX = 0x444D4163; ECX = 0x444D4163;
EDX = 0x69746E65; EDX = 0x69746E65;
@ -370,6 +429,7 @@ void cpu_CPUID()
case CPU_Am486DX: case CPU_Am486DX:
if (!EAX) if (!EAX)
{ {
EAX = 1;
EBX = 0x68747541; EBX = 0x68747541;
ECX = 0x444D4163; ECX = 0x444D4163;
EDX = 0x69746E65; EDX = 0x69746E65;
@ -383,19 +443,37 @@ void cpu_CPUID()
else else
EAX = 0; EAX = 0;
break; break;
case CPU_WINCHIP:
if (!EAX)
{
EAX = 1;
EBX = 0x746e6543; /*CentaurHauls*/
ECX = 0x736c7561;
EDX = 0x48727561;
}
else if (EAX == 1)
{
EAX = CPUID;
EBX = ECX = 0;
EDX = 1; /*FPU*/
}
else
EAX = 0;
break;
} }
} }
static int cyrix_addr; static int cyrix_addr;
void cyrix_write(uint16_t addr, uint8_t val) void cyrix_write(uint16_t addr, uint8_t val, void *priv)
{ {
if (!(addr & 1)) cyrix_addr = val; if (!(addr & 1)) cyrix_addr = val;
// else pclog("Write Cyrix %02X %02X\n",cyrix_addr,val); // else pclog("Write Cyrix %02X %02X\n",cyrix_addr,val);
} }
uint8_t cyrix_read(uint16_t addr) uint8_t cyrix_read(uint16_t addr, void *priv)
{ {
if (addr & 1) if (addr & 1)
{ {

View file

@ -22,9 +22,13 @@ extern int cpu, cpu_manufacturer;
#define CPU_Cx486DX 12 #define CPU_Cx486DX 12
#define CPU_Cx5x86 13 #define CPU_Cx5x86 13
/*586 class CPUs*/
#define CPU_WINCHIP 14
#define MANU_INTEL 0 #define MANU_INTEL 0
#define MANU_AMD 1 #define MANU_AMD 1
#define MANU_CYRIX 2 #define MANU_CYRIX 2
#define MANU_IDT 3
extern int timing_rr; extern int timing_rr;
extern int timing_mr, timing_mrl; extern int timing_mr, timing_mrl;
@ -55,6 +59,7 @@ extern CPU cpus_486SDLC[];
extern CPU cpus_i486[]; extern CPU cpus_i486[];
extern CPU cpus_Am486[]; extern CPU cpus_Am486[];
extern CPU cpus_Cx486[]; extern CPU cpus_Cx486[];
extern CPU cpus_WinChip[];
extern CPU cpus_pc1512[]; extern CPU cpus_pc1512[];
extern CPU cpus_ibmat[]; extern CPU cpus_ibmat[];
@ -65,7 +70,9 @@ extern int cpu_16bitbus;
extern int cpu_busspeed; extern int cpu_busspeed;
extern int cpu_multi; extern int cpu_multi;
void cyrix_write(uint16_t addr, uint8_t val); extern int cpu_hasrdtsc;
uint8_t cyrix_read(uint16_t addr);
void cyrix_write(uint16_t addr, uint8_t val, void *priv);
uint8_t cyrix_read(uint16_t addr, void *priv);
extern int is8086; extern int is8086;

340
src/dma.c
View file

@ -1,7 +1,9 @@
#include "ibm.h" #include "ibm.h"
#include "video.h"
#include "io.h"
#include "dma.h" #include "dma.h"
#include "fdc.h"
#include "io.h"
#include "video.h"
extern int ins; extern int ins;
int output; int output;
@ -38,10 +40,10 @@ void dma_reset()
dma16.m=0; dma16.m=0;
} }
uint8_t dma_read(uint16_t addr) uint8_t dma_read(uint16_t addr, void *priv)
{ {
uint8_t temp; uint8_t temp;
// printf("Read DMA %04X %04X:%04X\n",addr,cs>>4,pc); // printf("Read DMA %04X %04X:%04X %i %02X\n",addr,CS,pc, pic_intpending, pic.pend);
switch (addr&0xF) switch (addr&0xF)
{ {
case 0: case 0:
@ -69,7 +71,8 @@ uint8_t dma_read(uint16_t addr)
case 8: /*Status register*/ case 8: /*Status register*/
temp=dma.stat; temp=dma.stat;
dma.stat=0; dma.stat=0;
return temp|1; // pclog("Read DMA status %02X\n", temp);
return temp;
case 0xD: case 0xD:
return 0; return 0;
} }
@ -77,9 +80,9 @@ uint8_t dma_read(uint16_t addr)
return dmaregs[addr&0xF]; return dmaregs[addr&0xF];
} }
void dma_write(uint16_t addr, uint8_t val) void dma_write(uint16_t addr, uint8_t val, void *priv)
{ {
// printf("Write DMA %04X %02X %04X:%04X\n",addr,val,CS,pc); printf("Write DMA %04X %02X %04X:%04X\n",addr,val,CS,pc);
dmaregs[addr&0xF]=val; dmaregs[addr&0xF]=val;
switch (addr&0xF) switch (addr&0xF)
{ {
@ -122,7 +125,7 @@ void dma_write(uint16_t addr, uint8_t val)
} }
} }
uint8_t dma16_read(uint16_t addr) uint8_t dma16_read(uint16_t addr, void *priv)
{ {
uint8_t temp; uint8_t temp;
// printf("Read DMA %04X %04X:%04X\n",addr,cs>>4,pc); // printf("Read DMA %04X %04X:%04X\n",addr,cs>>4,pc);
@ -154,12 +157,12 @@ uint8_t dma16_read(uint16_t addr)
case 8: /*Status register*/ case 8: /*Status register*/
temp=dma16.stat; temp=dma16.stat;
dma16.stat=0; dma16.stat=0;
return temp|1; return temp;
} }
return dma16regs[addr&0xF]; return dma16regs[addr&0xF];
} }
void dma16_write(uint16_t addr, uint8_t val) void dma16_write(uint16_t addr, uint8_t val, void *priv)
{ {
// printf("Write dma16 %04X %02X %04X:%04X\n",addr,val,CS,pc); // printf("Write dma16 %04X %02X %04X:%04X\n",addr,val,CS,pc);
addr>>=1; addr>>=1;
@ -205,14 +208,14 @@ void dma16_write(uint16_t addr, uint8_t val)
} }
uint8_t dmapages[16]; uint8_t dmapages[16];
static int primed = 0;
void dma_page_write(uint16_t addr, uint8_t val) void dma_page_write(uint16_t addr, uint8_t val, void *priv)
{ {
if (!(addr&0xF)) /* if (!(addr&0xF))
{ {*/
// printf("Write page %03X %02X %04X:%04X\n",addr,val,CS,pc); pclog("Write page %03X %02X %04X:%04X\n",addr,val,CS,pc);
// if (val==0x29 && pc==0xD25) output=1; // if (val==0x29 && pc==0xD25) output=1;
} // }
dmapages[addr&0xF]=val; dmapages[addr&0xF]=val;
switch (addr&0xF) switch (addr&0xF)
{ {
@ -233,21 +236,21 @@ void dma_page_write(uint16_t addr, uint8_t val)
// printf("Page write %04X %02X\n",addr,val); // printf("Page write %04X %02X\n",addr,val);
} }
uint8_t dma_page_read(uint16_t addr) uint8_t dma_page_read(uint16_t addr, void *priv)
{ {
return dmapages[addr&0xF]; return dmapages[addr&0xF];
} }
void dma_init() void dma_init()
{ {
io_sethandler(0x0000, 0x0010, dma_read, NULL, NULL, dma_write, NULL, NULL); io_sethandler(0x0000, 0x0010, dma_read, NULL, NULL, dma_write, NULL, NULL, NULL);
io_sethandler(0x0080, 0x0008, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL); io_sethandler(0x0080, 0x0008, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL);
} }
void dma16_init() void dma16_init()
{ {
io_sethandler(0x00C0, 0x0020, dma16_read, NULL, NULL, dma16_write, NULL, NULL); io_sethandler(0x00C0, 0x0020, dma16_read, NULL, NULL, dma16_write, NULL, NULL, NULL);
io_sethandler(0x0088, 0x0008, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL); io_sethandler(0x0088, 0x0008, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL);
} }
@ -256,11 +259,11 @@ uint8_t _dma_read(uint32_t addr)
switch (addr&0xFFFF8000) switch (addr&0xFFFF8000)
{ {
case 0xA0000: case 0xA8000: case 0xA0000: case 0xA8000:
return video_read_a000(addr); return video_read_a000(addr, NULL);
case 0xB0000: case 0xB0000:
return video_read_b000(addr); return video_read_b000(addr, NULL);
case 0xB8000: case 0xB8000:
return video_read_b800(addr); return video_read_b800(addr, NULL);
} }
if (isram[addr>>16]) return ram[addr]; if (isram[addr>>16]) return ram[addr];
return 0xff; return 0xff;
@ -271,19 +274,20 @@ void _dma_write(uint32_t addr, uint8_t val)
switch (addr&0xFFFF8000) switch (addr&0xFFFF8000)
{ {
case 0xA0000: case 0xA8000: case 0xA0000: case 0xA8000:
video_write_a000(addr,val); video_write_a000(addr,val, NULL);
return; return;
case 0xB0000: case 0xB0000:
video_write_b000(addr,val); video_write_b000(addr,val, NULL);
return; return;
case 0xB8000: case 0xB8000:
video_write_b800(addr,val); video_write_b800(addr,val, NULL);
return; return;
case 0xC0000: case 0xC8000: case 0xD0000: case 0xD8000: case 0xC0000: case 0xC8000: case 0xD0000: case 0xD8000:
case 0xE0000: case 0xE8000: case 0xF0000: case 0xF8000: case 0xE0000: case 0xE8000: case 0xF0000: case 0xF8000:
return; return;
} }
if (isram[addr>>16]) ram[addr]=val; if (isram[addr >> 16])
ram[addr] = val;
} }
/*void writedma2(uint8_t val) /*void writedma2(uint8_t val)
{ {
@ -301,10 +305,144 @@ void _dma_write(uint32_t addr, uint8_t val)
} }
}*/ }*/
int dma_channel_read(int channel)
{
uint16_t temp;
if (channel < 4)
{
// pclog("Read DMA channel %i\n", channel);
if (dma.m & (1 << channel))
return DMA_NODATA;
if ((dma.mode[channel] & 0xC) != 8)
return DMA_NODATA;
temp = _dma_read(dma.ac[channel] + (dma.page[channel] << 16)); //ram[(dma.ac[2]+(dma.page[2]<<16))&rammask];
// pclog(" - %02X %05X\n", temp, dma.ac[channel] + (dma.page[channel] << 16));
if (dma.mode[channel] & 0x20) dma.ac[channel]--;
else dma.ac[channel]++;
dma.cc[channel]--;
if (!dma.cc[channel] && (dma.mode[channel] & 0x10))
{
dma.cc[channel] = dma.cb[channel] + 1;
dma.ac[channel] = dma.ab[channel];
dma.stat |= (1 << channel);
}
else if (dma.cc[channel]<=-1)
{
dma.m |= (1 << channel);
dma.stat |= (1 << channel);
}
return temp;
}
else
{
channel &= 3;
if (dma16.m & (1 << channel))
return DMA_NODATA;
if ((dma16.mode[channel] & 0xC) != 8)
return DMA_NODATA;
temp = _dma_read((dma16.ac[channel] << 1) + ((dma16.page[channel] & ~1) << 16)) |
(_dma_read((dma16.ac[channel] << 1) + ((dma16.page[channel] & ~1) << 16) + 1) << 8);
if (dma16.mode[channel] & 0x20) dma16.ac[channel]--;
else dma16.ac[channel]++;
dma16.cc[channel]--;
if (!dma16.cc[channel] && (dma16.mode[channel] & 0x10))
{
dma16.cc[channel] = dma16.cb[channel] + 1;
dma16.ac[channel] = dma16.ab[channel];
dma16.stat |= (1 << channel);
}
else if (dma16.cc[channel]<=-1)
{
dma16.m |= (1 << channel);
dma16.stat |= (1 << channel);
}
return temp;
}
}
int dma_channel_write(int channel, uint16_t val)
{
if (channel < 4)
{
if (dma.m & (1 << channel))
return DMA_NODATA;
if ((dma.mode[channel] & 0xC) != 4)
return DMA_NODATA;
_dma_write(dma.ac[channel] + (dma.page[channel] << 16), val);
if (dma.mode[channel]&0x20) dma.ac[channel]--;
else dma.ac[channel]++;
dma.cc[channel]--;
if (!dma.cc[channel] && (dma.mode[channel] & 0x10))
{
dma.cc[channel] = dma.cb[channel] + 1;
dma.ac[channel] = dma.ab[channel];
dma.stat |= (1 << channel);
}
else if (dma.cc[channel]<=-1)
{
dma.m |= (1 << channel);
dma.stat |= (1 << channel);
}
}
else
{
channel &= 3;
if (dma16.m & (1 << channel))
return DMA_NODATA;
if ((dma16.mode[channel] & 0xC) != 4)
return DMA_NODATA;
_dma_write((dma16.ac[channel] << 1) + ((dma16.page[channel] & ~1) << 16), val);
_dma_write((dma16.ac[channel] << 1) + ((dma16.page[channel] & ~1) << 16) + 1, val >> 8);
if (dma16.mode[channel]&0x20) dma16.ac[channel]--;
else dma16.ac[channel]++;
dma16.cc[channel]--;
if (!dma16.cc[channel] && (dma16.mode[channel] & 0x10))
{
dma16.cc[channel] = dma16.cb[channel] + 1;
dma16.ac[channel] = dma16.ab[channel];
dma16.stat |= (1 << channel);
}
else if (dma16.cc[channel] <= -1)
{
dma16.m |= (1 << channel);
dma16.stat |= (1 << channel);
}
}
return 0;
}
extern int sbbufferpos;
int readdma1()
{
uint8_t temp;
pclog("readdma1 : Read DMA1 %02X %02X %i\n",dma.m,dma.mode[1], dma.cc[1]);
if (dma.m & (1 << 1))
return DMA_NODATA;
if ((dma.mode[1]&0xC)!=8)
return DMA_NODATA;
temp=_dma_read((dma.ac[1]+(dma.page[1]<<16))&rammask); //ram[(dma.ac[2]+(dma.page[2]<<16))&rammask];
pclog("readdma1 : DMA1 %02X %05X\n",temp,(dma.ac[1]+(dma.page[1]<<16))&rammask);
if (dma.mode[1]&0x20) dma.ac[1]--;
else dma.ac[1]++;
dma.cc[1]--;
if (!dma.cc[1] && (dma.mode[1]&0x10))
{
dma.cc[1]=dma.cb[1]+1;
dma.ac[1]=dma.ab[1];
dma.stat |= (1 << 1);
}
else if (dma.cc[1]<=-1)
{
dma.m |= (1 << 1);
dma.stat |= (1 << 1);
}
return temp;
}
uint8_t readdma2() uint8_t readdma2()
{ {
uint8_t temp; uint8_t temp;
// pclog("Read DMA2 %02X %02X\n",dma.m,dma.mode[2]); // pclog("Read DMA2 %02X %02X %i\n",dma.m,dma.mode[2], dma.cc[2]);
if (dma.m&4) if (dma.m&4)
{ {
fdc_abort(); fdc_abort();
@ -324,12 +462,68 @@ uint8_t readdma2()
{ {
dma.cc[2]=dma.cb[2]+1; dma.cc[2]=dma.cb[2]+1;
dma.ac[2]=dma.ab[2]; dma.ac[2]=dma.ab[2];
dma.stat |= (1 << 2);
} }
else if (dma.cc[2]<=-1) else if (dma.cc[2]<=-1)
dma.m|=4; {
dma.m|=4;
dma.stat |= (1 << 2);
}
return temp;
}
int readdma3()
{
uint8_t temp;
// pclog("Read DMA1 %02X %02X %i\n",dma.m,dma.mode[1], dma.cc[1]);
if (dma.m & (1 << 3))
return DMA_NODATA;
if ((dma.mode[3]&0xC)!=8)
return DMA_NODATA;
temp=_dma_read((dma.ac[3]+(dma.page[3]<<16))&rammask); //ram[(dma.ac[2]+(dma.page[2]<<16))&rammask];
//pclog("DMA3 %02X %05X\n",temp,(dma.ac[3]+(dma.page[3]<<16))&rammask);
if (dma.mode[3]&0x20) dma.ac[3]--;
else dma.ac[3]++;
dma.cc[3]--;
if (!dma.cc[3] && (dma.mode[3]&0x10))
{
dma.cc[3]=dma.cb[3]+1;
dma.ac[3]=dma.ab[3];
dma.stat |= (1 << 3);
}
else if (dma.cc[3]<=-1)
{
dma.m |= (1 << 3);
dma.stat |= (1 << 3);
}
return temp; return temp;
} }
void writedma1(uint8_t temp)
{
// pclog("Write DMA1 %02X %02X %04X\n",dma.m,dma.mode[1],dma.cc[1]);
if (dma.m & (1 << 1))
return;
if ((dma.mode[1] & 0xC) != 4)
return;
// pclog("Write %05X %05X %02X\n",(dma.ac[2]+(dma.page[2]<<16)),rammask,temp);
// ram[(dma.ac[2]+(dma.page[2]<<16))&rammask]=temp;
_dma_write((dma.ac[1]+(dma.page[1]<<16))&rammask,temp);
if (dma.mode[1]&0x20) dma.ac[1]--;
else dma.ac[1]++;
dma.cc[1]--;
if (!dma.cc[1] && (dma.mode[1]&0x10))
{
dma.cc[1]=dma.cb[1]+1;
dma.ac[1]=dma.ab[1];
dma.stat |= (1 << 1);
}
else if (dma.cc[1]<=-1)
{
// pclog("Reached TC\n");
dma.m |= (1 << 1);
dma.stat |= (1 << 1);
}
}
void writedma2(uint8_t temp) void writedma2(uint8_t temp)
{ {
// pclog("Write DMA2 %02X %02X %04X\n",dma.m,dma.mode[2],dma.cc[2]); // pclog("Write DMA2 %02X %02X %04X\n",dma.m,dma.mode[2],dma.cc[2]);
@ -353,35 +547,41 @@ void writedma2(uint8_t temp)
{ {
dma.cc[2]=dma.cb[2]+1; dma.cc[2]=dma.cb[2]+1;
dma.ac[2]=dma.ab[2]; dma.ac[2]=dma.ab[2];
dma.stat |= (1 << 2);
} }
else if (dma.cc[2]<=-1) else if (dma.cc[2]<=-1)
{ {
// pclog("Reached TC\n"); // pclog("Reached TC\n");
fdc_abort(); fdc_abort();
dma.m|=4; dma.m|=4;
dma.stat |= (1 << 2);
} }
} }
void writedma3(uint8_t temp)
uint8_t readdma1()
{ {
uint8_t temp=0; // pclog("Write DMA3 %02X %02X %04X\n",dma.m,dma.mode[3],dma.cc[3]);
/*if ((dma.ac[1]+(dma.page[1]<<16))<0x800000) */temp=ram[(dma.ac[1]+(dma.page[1]<<16))&rammask]; if (dma.m & (1 << 3))
// printf("Read DMA1 from %05X %02X %04X %02X %i\n",dma.ac[1]+(dma.page[1]<<16),dma.mode[1],dma.cc[1],temp,dmaon[1]); return;
if (!dmaon[1]) if ((dma.mode[3] & 0xC) != 4)
return;
// pclog("Write %05X %05X %02X\n",(dma.ac[2]+(dma.page[2]<<16)),rammask,temp);
// ram[(dma.ac[2]+(dma.page[2]<<16))&rammask]=temp;
_dma_write((dma.ac[3]+(dma.page[3]<<16))&rammask,temp);
if (dma.mode[3]&0x20) dma.ac[3]--;
else dma.ac[3]++;
dma.cc[3]--;
if (!dma.cc[3] && (dma.mode[3]&0x10))
{ {
// printf("DMA off!\n"); dma.cc[3]=dma.cb[3]+1;
return temp; dma.ac[3]=dma.ab[3];
dma.stat |= (1 << 3);
} }
dma.ac[1]++; else if (dma.cc[3]<=-1)
dma.cc[1]--;
if (dma.cc[1]<=-1 && (dma.mode[1]&0x10))
{ {
dma.cc[1]=dma.cb[1]; // pclog("Reached TC\n");
dma.ac[1]=dma.ab[1]; dma.m |= (1 << 3);
dma.stat |= (1 << 3);
} }
else if (dma.cc[1]<=-1)
dmaon[1]=0;
return temp;
} }
uint16_t readdma5() uint16_t readdma5()
@ -402,26 +602,16 @@ uint16_t readdma5()
{ {
dma16.cc[1]=dma16.cb[1]; dma16.cc[1]=dma16.cb[1];
dma16.ac[1]=dma16.ab[1]; dma16.ac[1]=dma16.ab[1];
dma16.stat |= (1 << 1);
} }
else if (dma16.cc[1]<=-1) else if (dma16.cc[1]<=-1)
dma16on[1]=0; {
dma16on[1]=0;
dma16.stat |= (1 << 1);
}
return temp; return temp;
} }
void writedma1(uint8_t temp)
{
if (!dmaon[1]) return;
ram[(dma.ac[1]+(dma.page[1]<<16))&rammask]=temp;
dma.ac[1]++;
dma.cc[1]--;
if (!dma.cc[1] && (dma.mode[1]&0x10))
{
dma.cc[1]=dma.cb[1]+1;
dma.ac[1]=dma.ab[1];
}
else if (dma.cc[1]<=-1)
dmaon[1]=0;
}
void writedma5(uint16_t temp) void writedma5(uint16_t temp)
{ {
if (!dma16on[1]) return; if (!dma16on[1]) return;
@ -434,31 +624,15 @@ void writedma5(uint16_t temp)
{ {
dma16.cc[1]=dma16.cb[1]; dma16.cc[1]=dma16.cb[1];
dma16.ac[1]=dma16.ab[1]; dma16.ac[1]=dma16.ab[1];
dma16.stat |= (1 << 1);
} }
else if (dma16.cc[1]<=-1) else if (dma16.cc[1]<=-1)
dma16on[1]=0; {
dma16on[1]=0;
dma16.stat |= (1 << 1);
}
} }
int readdma3()
{
uint8_t temp=ram[((dma.page[3]<<16)+dma.ac[3])&rammask];
if (dma.m&8)
{
return -1;
}
// printf("Read DMA 3 - %02X %05X %i\n",temp,(dma.page[3]<<16)+dma.ac[3],dma.cc[3]);
if (!(dma.m&8))
{
dma.ac[3]++;
dma.cc[3]--;
if (dma.cc[3]==-1)
{
dma.m|=8;
dma.stat|=8;
}
}
return temp;
}
void readdma0() void readdma0()
{ {
if (AT) ppi.pb^=0x10; if (AT) ppi.pb^=0x10;
@ -474,9 +648,9 @@ void readdma0()
dma.cc[0]--; dma.cc[0]--;
if (dma.cc[0]==-1) if (dma.cc[0]==-1)
{ {
dma.stat|=1;
dma.ac[0]=dma.ab[0]; dma.ac[0]=dma.ab[0];
dma.cc[0]=dma.cb[0]; dma.cc[0]=dma.cb[0];
dma.stat |= 1;
} }
// } // }
// ppi.pb^=0x10; // ppi.pb^=0x10;

View file

@ -1,3 +1,15 @@
void dma_init(); void dma_init();
void dma16_init(); void dma16_init();
void dma_reset(); void dma_reset();
#define DMA_NODATA -1
void readdma0();
int readdma1();
uint8_t readdma2();
int readdma3();
void writedma2(uint8_t temp);
int dma_channel_read(int channel);
int dma_channel_write(int channel, uint16_t val);

View file

@ -16,7 +16,6 @@ uint8_t svga3d8;
uint8_t oldvram=0; uint8_t oldvram=0;
int frames; int frames;
int incga=1;
int hsync; int hsync;
uint8_t cgastat; uint8_t cgastat;
@ -36,7 +35,7 @@ uint8_t *vram;
int egares; int egares;
uint8_t seqregs[32]; uint8_t seqregs[64];
int seqaddr; int seqaddr;
uint8_t oak_regs[32]; uint8_t oak_regs[32];
@ -54,7 +53,8 @@ int palchange=1;
int fullchange; int fullchange;
float dispontime,dispofftime,disptime; int dispontime,dispofftime;
double disptime;
int ega_vtotal,ega_dispend,ega_vsyncstart,ega_split,ega_hdisp,ega_rowoffset; int ega_vtotal,ega_dispend,ega_vsyncstart,ega_split,ega_hdisp,ega_rowoffset;
int vidclock; int vidclock;
@ -135,8 +135,6 @@ void initega()
} }
} }
crtc[0xC]=crtc[0xD]=0; crtc[0xC]=crtc[0xD]=0;
if (romset==ROM_PC1640 || romset==ROM_PC1512) incga=1;
else incga=0;
for (c=0;c<4;c++) for (c=0;c<4;c++)
{ {
for (d=0;d<4;d++) for (d=0;d<4;d++)
@ -277,6 +275,7 @@ int ega_getdepth()
if (TRIDENT || ET4000W32) return bpp; if (TRIDENT || ET4000W32) return bpp;
return 8; return 8;
} }
return 0;
} }
int ega_getx() int ega_getx()

104
src/fdc.c
View file

@ -2,6 +2,11 @@
#include <string.h> #include <string.h>
#include "ibm.h" #include "ibm.h"
#include "dma.h"
#include "io.h"
#include "pic.h"
#include "timer.h"
void fdc_poll(); void fdc_poll();
int timetolive; int timetolive;
int TRACKS[2] = {80, 80}; int TRACKS[2] = {80, 80};
@ -105,9 +110,8 @@ void fdc_reset()
} }
int ins; int ins;
void fdc_write(uint16_t addr, uint8_t val) void fdc_write(uint16_t addr, uint8_t val, void *priv)
{ {
int c;
// printf("Write FDC %04X %02X %04X:%04X %i %02X %i rate=%i\n",addr,val,cs>>4,pc,ins,fdc.st0,ins,fdc.rate); // printf("Write FDC %04X %02X %04X:%04X %i %02X %i rate=%i\n",addr,val,cs>>4,pc,ins,fdc.st0,ins,fdc.rate);
switch (addr&7) switch (addr&7)
{ {
@ -122,7 +126,9 @@ void fdc_write(uint16_t addr, uint8_t val)
} }
if ((val&4) && !(fdc.dor&4)) if ((val&4) && !(fdc.dor&4))
{ {
disctime=128; timer_process();
disctime = 128 * (1 << TIMER_SHIFT);
timer_update_outstanding();
discint=-1; discint=-1;
fdc_reset(); fdc_reset();
} }
@ -132,7 +138,9 @@ void fdc_write(uint16_t addr, uint8_t val)
case 4: case 4:
if (val & 0x80) if (val & 0x80)
{ {
disctime=128; timer_process();
disctime = 128 * (1 << TIMER_SHIFT);
timer_update_outstanding();
discint=-1; discint=-1;
fdc_reset(); fdc_reset();
} }
@ -247,7 +255,9 @@ void fdc_write(uint16_t addr, uint8_t val)
// exit(-1); // exit(-1);
fdc.stat=0x10; fdc.stat=0x10;
discint=0xfc; discint=0xfc;
disctime=200; timer_process();
disctime = 200 * (1 << TIMER_SHIFT);
timer_update_outstanding();
break; break;
} }
} }
@ -259,7 +269,8 @@ void fdc_write(uint16_t addr, uint8_t val)
// pclog("Got all params\n"); // pclog("Got all params\n");
fdc.stat=0x30; fdc.stat=0x30;
discint=fdc.command&0x1F; discint=fdc.command&0x1F;
disctime=1024; timer_process();
disctime = 1024 * (1 << TIMER_SHIFT);
fdc.drive=fdc.params[0]&1; fdc.drive=fdc.params[0]&1;
if (discint==2 || discint==5 || discint==6) if (discint==2 || discint==5 || discint==6)
{ {
@ -285,13 +296,13 @@ void fdc_write(uint16_t addr, uint8_t val)
{ {
// pclog("Wrong rate %i %i\n",fdc.rate,discrate[fdc.drive]); // pclog("Wrong rate %i %i\n",fdc.rate,discrate[fdc.drive]);
discint=0xFF; discint=0xFF;
disctime=1024; disctime = 1024 * (1 << TIMER_SHIFT);
} }
if (driveempty[fdc.drive]) if (driveempty[fdc.drive])
{ {
// pclog("Drive empty\n"); // pclog("Drive empty\n");
discint=0xFE; discint=0xFE;
disctime=1024; disctime = 1024 * (1 << TIMER_SHIFT);
} }
} }
if (discint == 7 || discint == 0xf) if (discint == 7 || discint == 0xf)
@ -303,6 +314,7 @@ void fdc_write(uint16_t addr, uint8_t val)
{ {
fdc.head = (fdc.params[0] & 4) ? 1 : 0; fdc.head = (fdc.params[0] & 4) ? 1 : 0;
} }
timer_update_outstanding();
// if (discint==5) fdc.pos=512; // if (discint==5) fdc.pos=512;
} }
} }
@ -320,7 +332,7 @@ void fdc_write(uint16_t addr, uint8_t val)
} }
int paramstogo=0; int paramstogo=0;
uint8_t fdc_read(uint16_t addr) uint8_t fdc_read(uint16_t addr, void *priv)
{ {
uint8_t temp; uint8_t temp;
// /*if (addr!=0x3f4) */printf("Read FDC %04X %04X:%04X %04X %i %02X %i ",addr,cs>>4,pc,BX,fdc.pos,fdc.st0,ins); // /*if (addr!=0x3f4) */printf("Read FDC %04X %04X:%04X %04X %i %02X %i ",addr,cs>>4,pc,BX,fdc.pos,fdc.st0,ins);
@ -360,7 +372,12 @@ uint8_t fdc_read(uint16_t addr)
lastbyte=0; lastbyte=0;
temp=fdc.dat; temp=fdc.dat;
} }
if (discint==0xA) disctime=1024; if (discint==0xA)
{
timer_process();
disctime = 1024 * (1 << TIMER_SHIFT);
timer_update_outstanding();
}
fdc.stat &= 0xf0; fdc.stat &= 0xf0;
break; break;
case 7: /*Disk change*/ case 7: /*Disk change*/
@ -395,6 +412,7 @@ static int fdc_reset_stat = 0;
void fdc_poll() void fdc_poll()
{ {
int temp; int temp;
disctime = 0;
// pclog("fdc_poll %08X %i %02X\n", discint, fdc.drive, fdc.st0); // pclog("fdc_poll %08X %i %02X\n", discint, fdc.drive, fdc.st0);
switch (discint) switch (discint)
{ {
@ -420,7 +438,9 @@ void fdc_poll()
fdc.dat=disc[fdc.drive][fdc.head][fdc.track[fdc.drive]][fdc.sector-1][fdc.pos]; fdc.dat=disc[fdc.drive][fdc.head][fdc.track[fdc.drive]][fdc.sector-1][fdc.pos];
// pclog("Read %i %i %i %i %02X\n",fdc.head,fdc.track,fdc.sector,fdc.pos,fdc.dat); // pclog("Read %i %i %i %i %02X\n",fdc.head,fdc.track,fdc.sector,fdc.pos,fdc.dat);
writedma2(fdc.dat); writedma2(fdc.dat);
disctime=60; timer_process();
disctime = 60 * (1 << TIMER_SHIFT);
timer_update_outstanding();
} }
else else
{ {
@ -437,17 +457,6 @@ void fdc_poll()
fdc.res[9]=fdc.params[4]; fdc.res[9]=fdc.params[4];
paramstogo=7; paramstogo=7;
return; return;
disctime=1024;
picint(0x40);
fdc.stat=0xD0;
switch (fdc.pos-512)
{
case 0: case 1: case 2: fdc.dat=0; break;
case 3: fdc.dat=fdc.track[fdc.drive]; break;
case 4: fdc.dat=fdc.head; break;
case 5: fdc.dat=fdc.sector; break;
case 6: fdc.dat=fdc.params[4]; discint=-2; lastbyte=1; break;
}
} }
fdc.pos++; fdc.pos++;
if (fdc.pos==512 && fdc.params[5]!=1) if (fdc.pos==512 && fdc.params[5]!=1)
@ -491,14 +500,18 @@ void fdc_poll()
{ {
fdc_abort_f=0; fdc_abort_f=0;
discint=0xFD; discint=0xFD;
disctime=50; timer_process();
disctime = 50 * (1 << TIMER_SHIFT);
timer_update_outstanding();
return; return;
} }
else else
{ {
fdc.dat=disc[fdc.drive][fdc.head][fdc.track[fdc.drive]][fdc.sector-1][fdc.pos]=temp; fdc.dat=disc[fdc.drive][fdc.head][fdc.track[fdc.drive]][fdc.sector-1][fdc.pos]=temp;
// printf("Write data %i %i %02X %i:%i:%i:%i\n",fdc.sector-1,fdc.pos,fdc.dat,fdc.head,fdc.track[fdc.drive],fdc.sector-1,fdc.pos); // printf("Write data %i %i %02X %i:%i:%i:%i\n",fdc.sector-1,fdc.pos,fdc.dat,fdc.head,fdc.track[fdc.drive],fdc.sector-1,fdc.pos);
disctime=60; timer_process();
disctime = 60 * (1 << TIMER_SHIFT);
timer_update_outstanding();
} }
} }
else else
@ -517,19 +530,6 @@ void fdc_poll()
fdc.res[10]=fdc.params[4]; fdc.res[10]=fdc.params[4];
paramstogo=7; paramstogo=7;
return; return;
disctime=1024;
picint(0x40);
fdc.stat=0xD0;
switch (fdc.pos-512)
{
case 0: fdc.dat=0x40; break;
case 1: fdc.dat=2; break;
case 2: fdc.dat=0; break;
case 3: fdc.dat=fdc.track[fdc.drive]; break;
case 4: fdc.dat=fdc.head; break;
case 5: fdc.dat=fdc.sector; break;
case 6: fdc.dat=fdc.params[4]; discint=-2; break;
}
} }
fdc.pos++; fdc.pos++;
if (fdc.pos==512 && fdc.sector!=fdc.params[5]) if (fdc.pos==512 && fdc.sector!=fdc.params[5])
@ -548,7 +548,9 @@ void fdc_poll()
fdc.dat=disc[fdc.drive][fdc.head][fdc.track[fdc.drive]][fdc.sector-1][fdc.pos]; fdc.dat=disc[fdc.drive][fdc.head][fdc.track[fdc.drive]][fdc.sector-1][fdc.pos];
// printf("Read disc %i %i %i %i %02X\n",fdc.head,fdc.track,fdc.sector,fdc.pos,fdc.dat); // printf("Read disc %i %i %i %i %02X\n",fdc.head,fdc.track,fdc.sector,fdc.pos,fdc.dat);
writedma2(fdc.dat); writedma2(fdc.dat);
disctime=60; timer_process();
disctime = 60 * (1 << TIMER_SHIFT);
timer_update_outstanding();
} }
else else
{ {
@ -579,12 +581,12 @@ void fdc_poll()
fdc.pos++; fdc.pos++;
if (fdc.pos==512)// && fdc.sector!=fdc.params[5]) if (fdc.pos==512)// && fdc.sector!=fdc.params[5])
{ {
// printf("Sector complete! %02X\n",fdc.params[5]); // pclog("Sector complete! %02X\n",fdc.params[5]);
fdc.pos=0; fdc.pos=0;
fdc.sector++; fdc.sector++;
if (fdc.sector > fdc.params[5]) if (fdc.sector > fdc.params[5])
{ {
// printf("Overrunnit!\n"); // pclog("Overrunnit! %02X\n", fdc.command & 0x80);
// dumpregs(); // dumpregs();
// exit(-1); // exit(-1);
fdc.sector=1; fdc.sector=1;
@ -617,7 +619,9 @@ void fdc_poll()
if (!driveempty[fdc.dor & 1]) discchanged[fdc.dor & 1] = 0; if (!driveempty[fdc.dor & 1]) discchanged[fdc.dor & 1] = 0;
fdc.st0=0x20|fdc.drive|(fdc.head?4:0); fdc.st0=0x20|fdc.drive|(fdc.head?4:0);
discint=-3; discint=-3;
disctime=2048; timer_process();
disctime = 2048 * (1 << TIMER_SHIFT);
timer_update_outstanding();
// printf("Recalibrate complete!\n"); // printf("Recalibrate complete!\n");
fdc.stat = 0x80 | (1 << fdc.drive); fdc.stat = 0x80 | (1 << fdc.drive);
return; return;
@ -663,7 +667,9 @@ void fdc_poll()
// printf("Seeked to track %i %i\n",fdc.track[fdc.drive], fdc.drive); // printf("Seeked to track %i %i\n",fdc.track[fdc.drive], fdc.drive);
fdc.st0=0x20|fdc.drive|(fdc.head?4:0); fdc.st0=0x20|fdc.drive|(fdc.head?4:0);
discint=-3; discint=-3;
disctime=2048; timer_process();
disctime = 2048 * (1 << TIMER_SHIFT);
timer_update_outstanding();
fdc.stat = 0x80 | (1 << fdc.drive); fdc.stat = 0x80 | (1 << fdc.drive);
// pclog("Stat %02X ST0 %02X\n", fdc.stat, fdc.st0); // pclog("Stat %02X ST0 %02X\n", fdc.stat, fdc.st0);
return; return;
@ -792,15 +798,19 @@ void fdc_poll()
// exit(-1); // exit(-1);
} }
void fdc_init() void fdc_init()
{ {
io_sethandler(0x03f0, 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL); timer_add(fdc_poll, &disctime, &disctime, NULL);
io_sethandler(0x03f7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL); }
void fdc_add()
{
io_sethandler(0x03f0, 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL);
io_sethandler(0x03f7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL);
} }
void fdc_remove() void fdc_remove()
{ {
io_removehandler(0x03f0, 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL); io_removehandler(0x03f0, 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL);
io_removehandler(0x03f7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL); io_removehandler(0x03f7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL);
} }

View file

@ -1,4 +1,6 @@
void fdc_init(); void fdc_init();
void fdc_add();
void fdc_remove(); void fdc_remove();
void fdc_reset(); void fdc_reset();
void fdc_poll(); void fdc_poll();
void fdc_abort();

View file

@ -8,7 +8,7 @@
static int headland_index; static int headland_index;
static uint8_t headland_regs[256]; static uint8_t headland_regs[256];
void headland_write(uint16_t addr, uint8_t val) void headland_write(uint16_t addr, uint8_t val, void *priv)
{ {
if (addr & 1) if (addr & 1)
{ {
@ -20,15 +20,15 @@ void headland_write(uint16_t addr, uint8_t val)
shadowbios = val & 0x10; shadowbios = val & 0x10;
shadowbios_write = !(val & 0x10); shadowbios_write = !(val & 0x10);
if (shadowbios) if (shadowbios)
mem_sethandler(0xf0000, 0x10000, mem_read_ram, mem_read_ramw, mem_read_raml, NULL, NULL, NULL ); mem_sethandler(0xf0000, 0x10000, mem_read_ram, mem_read_ramw, mem_read_raml, NULL, NULL, NULL , NULL);
else else
mem_sethandler(0xf0000, 0x10000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml); mem_sethandler(0xf0000, 0x10000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml, NULL);
} }
} }
else headland_index = val; else headland_index = val;
} }
uint8_t headland_read(uint16_t addr) uint8_t headland_read(uint16_t addr, void *priv)
{ {
if (addr & 1) if (addr & 1)
{ {
@ -41,5 +41,5 @@ uint8_t headland_read(uint16_t addr)
void headland_init() void headland_init()
{ {
io_sethandler(0x0022, 0x0002, headland_read, NULL, NULL, headland_write, NULL, NULL); io_sethandler(0x0022, 0x0002, headland_read, NULL, NULL, headland_write, NULL, NULL, NULL);
} }

View file

@ -1,5 +1,6 @@
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <string.h>
#define printf pclog #define printf pclog
/*Memory*/ /*Memory*/
@ -291,9 +292,8 @@ int driveempty[2];
#define PCI (romset == ROM_PCI486) #define PCI (romset == ROM_PCI486)
#define AMIBIOS (romset==ROM_AMI386 || romset==ROM_AMI486 || romset == ROM_WIN486) #define AMIBIOS (romset==ROM_AMI386 || romset==ROM_AMI486 || romset == ROM_WIN486)
int FASTDISC;
int ADLIB; int GAMEBLASTER, GUS;
int GAMEBLASTER;
enum enum
{ {
@ -320,7 +320,8 @@ enum
ROM_AMI386, ROM_AMI386,
ROM_AMI486, ROM_AMI486,
ROM_WIN486, ROM_WIN486,
ROM_PCI486 ROM_PCI486,
ROM_430VX
}; };
//#define ROM_IBMPCJR 5 /*Not working! ROMs are corrupt*/ //#define ROM_IBMPCJR 5 /*Not working! ROMs are corrupt*/
@ -337,10 +338,18 @@ int romset;
//#define GFX_OTI067 3 /*Using BIOS from Acer 386SX/25N - edit - only works with Acer BIOS! Stupid integrated systems*/ //#define GFX_OTI067 3 /*Using BIOS from Acer 386SX/25N - edit - only works with Acer BIOS! Stupid integrated systems*/
#define GFX_TVGA 4 /*Using Trident 8900D BIOS*/ #define GFX_TVGA 4 /*Using Trident 8900D BIOS*/
#define GFX_ET4000 5 /*Tseng ET4000*/ #define GFX_ET4000 5 /*Tseng ET4000*/
#define GFX_ET4000W32 6 /*Tseng ET4000/W32p (Diamond Stealth 32)*/ #define GFX_ET4000W32 6 /*Tseng ET4000/W32p (Diamond Stealth 32)*/
#define GFX_BAHAMAS64 7 /*S3 Vision864 (Paradise Bahamas 64)*/ #define GFX_BAHAMAS64 7 /*S3 Vision864 (Paradise Bahamas 64)*/
#define GFX_N9_9FX 8 /*S3 764/Trio64 (Number Nine 9FX)*/ #define GFX_N9_9FX 8 /*S3 764/Trio64 (Number Nine 9FX)*/
#define GFX_STEALTH64 9 /*S3 Vision964 (Diamond Stealth 64 VRAM PCI)*/ #define GFX_STEALTH64 9 /*S3 Vision964 (Diamond Stealth 64 VRAM PCI)*/
#define GFX_VIRGE 10 /*S3 Virge*/
#define GFX_TGUI9440 11 /*Trident TGUI9440*/
#define GFX_VGA 12 /*IBM VGA*/
#define GFX_VGAEDGE16 13 /*ATI VGA Edge-16 (18800-1)*/
#define GFX_VGACHARGER 14 /*ATI VGA Charger (28800-5)*/
#define GFX_OTI067 15 /*Oak OTI-067*/
#define GFX_MACH64GX 16 /*ATI Graphics Pro Turbo (Mach64)*/
#define GFX_CL_GD5429 17 /*Cirrus Logic CL-GD5429*/
int gfxcard; int gfxcard;
@ -354,7 +363,6 @@ int readflash;
uint8_t hercctrl; uint8_t hercctrl;
int slowega,egacycles,egacycles2; int slowega,egacycles,egacycles2;
extern uint8_t gdcreg[16]; extern uint8_t gdcreg[16];
extern int incga;
extern int egareads,egawrites; extern int egareads,egawrites;
extern int cga_comp; extern int cga_comp;
extern int vid_resize; extern int vid_resize;
@ -383,13 +391,10 @@ extern int mousedelay;
/*Sound*/ /*Sound*/
uint8_t spkstat; uint8_t spkstat;
float spktime,soundtime,gustime,gustime2,vidtime,rtctime; float spktime;
int rtctime;
int soundtime,gustime,gustime2,vidtime;
int ppispeakon; int ppispeakon;
//#define SPKCONST (8000000.0/44100.0)
float SPKCONST;
float SOUNDCONST;
float CASCONST;
float GUSCONST,GUSCONST2;
float CGACONST; float CGACONST;
float MDACONST; float MDACONST;
float VGACONST1,VGACONST2; float VGACONST1,VGACONST2;
@ -400,38 +405,23 @@ int gated,speakval,speakon;
/*Sound Blaster*/ /*Sound Blaster*/
int sbenable,sblatchi,sblatcho,sbcount,sb_enable_i,sb_count_i; /*int sbenable,sblatchi,sblatcho,sbcount,sb_enable_i,sb_count_i;
int16_t sbdat; int16_t sbdat;*/
void setsbclock(float clock); void setsbclock(float clock);
#define SADLIB 1 /*No DSP*/ #define SADLIB 1 /*No DSP*/
#define SB1 2 /*DSP v1.05*/ #define SB1 2 /*DSP v1.05*/
#define SB15 3 /*DSP v2.00*/ #define SB15 3 /*DSP v2.00*/
#define SB2 4 /*DSP v2.01 - needed for high-speed DMA*/ #define SB2 4 /*DSP v2.01 - needed for high-speed DMA*/
#define SBPRO 5 /*DSP v3.00*/ #define SBPRO 5 /*DSP v3.00*/
#define SBPRO2 6 /*DSP v3.02 + OPL3*/ #define SBPRO2 6 /*DSP v3.02 + OPL3*/
#define SB16 7 /*DSP v4.05 + OPL3*/ #define SB16 7 /*DSP v4.05 + OPL3*/
#define SADGOLD 8 /*AdLib Gold*/
#define SND_WSS 9 /*Windows Sound System*/
#define SND_PAS16 10 /*Pro Audio Spectrum 16*/
int sbtype; int sbtype;
struct
{
int vocl,vocr,voc;
int midl,midr,mid;
int masl,masr,mas;
} sbpmixer;
extern int sb_freq;
struct
{
int master_l,master_r;
int voice_l,voice_r;
int fm_l,fm_r;
int bass_l,bass_r;
int treble_l,treble_r;
int filter;
} mixer;
int clocks[3][12][4]; int clocks[3][12][4];
int at70hz; int at70hz;
@ -466,3 +456,5 @@ extern int times;
extern float isa_timing, bus_timing; extern float isa_timing, bus_timing;
extern int frame;

388
src/ide.c
View file

@ -2,7 +2,7 @@
IDE emulation*/ IDE emulation*/
//#define RPCEMU_IDE //#define RPCEMU_IDE
#define IDE_TIME 5 #define IDE_TIME (5 * 100 * (1 << TIMER_SHIFT))
#define _LARGEFILE_SOURCE #define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE #define _LARGEFILE64_SOURCE
@ -20,6 +20,9 @@
#include "arm.h" #include "arm.h"
#else #else
#include "ibm.h" #include "ibm.h"
#include "io.h"
#include "pic.h"
#include "timer.h"
#endif #endif
#include "ide.h" #include "ide.h"
@ -50,6 +53,11 @@
#define WIN_SPECIFY 0x91 /* Initialize Drive Parameters */ #define WIN_SPECIFY 0x91 /* Initialize Drive Parameters */
#define WIN_PACKETCMD 0xA0 /* Send a packet command. */ #define WIN_PACKETCMD 0xA0 /* Send a packet command. */
#define WIN_PIDENTIFY 0xA1 /* Identify ATAPI device */ #define WIN_PIDENTIFY 0xA1 /* Identify ATAPI device */
#define WIN_READ_MULTIPLE 0xC4
#define WIN_WRITE_MULTIPLE 0xC5
#define WIN_SET_MULTIPLE_MODE 0xC6
#define WIN_READ_DMA 0xC8
#define WIN_WRITE_DMA 0xCA
#define WIN_SETIDLE1 0xE3 #define WIN_SETIDLE1 0xE3
#define WIN_IDENTIFY 0xEC /* Ask drive to identify itself */ #define WIN_IDENTIFY 0xEC /* Ask drive to identify itself */
@ -134,6 +142,7 @@ typedef struct IDE
int lba; int lba;
uint32_t lba_addr; uint32_t lba_addr;
int skip512; int skip512;
int blocksize, blockcount;
} IDE; } IDE;
IDE ide_drives[4]; IDE ide_drives[4];
@ -142,6 +151,10 @@ IDE *ext_ide;
char ide_fn[2][512]; char ide_fn[2][512];
int (*ide_bus_master_read_sector)(int channel, uint8_t *data);
int (*ide_bus_master_write_sector)(int channel, uint8_t *data);
void (*ide_bus_master_set_irq)(int channel);
static void callreadcd(IDE *ide); static void callreadcd(IDE *ide);
static void atapicommand(int ide_board); static void atapicommand(int ide_board);
@ -272,8 +285,15 @@ static void ide_identify(IDE *ide)
#else #else
ide_padstr((char *) (ide->buffer + 27), "PCemHD", 40); /* Model */ ide_padstr((char *) (ide->buffer + 27), "PCemHD", 40); /* Model */
#endif #endif
ide->buffer[49] = (1<<9); /* LBA supported */ ide->buffer[20] = 3; /*Buffer type*/
ide->buffer[21] = 512; /*Buffer size*/
ide->buffer[47] = 16; /*Max sectors on multiple transfer command*/
ide->buffer[48] = 1; /*Dword transfers supported*/
ide->buffer[49] = (1 << 9) | (1 << 8); /* LBA and DMA supported */
ide->buffer[50] = 0x4000; /* Capabilities */ ide->buffer[50] = 0x4000; /* Capabilities */
ide->buffer[51] = 2 << 8; /*PIO timing mode*/
ide->buffer[52] = 2 << 8; /*DMA timing mode*/
ide->buffer[59] = ide->blocksize ? (ide->blocksize | 0x100) : 0;
#ifdef RPCEMU_IDE #ifdef RPCEMU_IDE
ide->buffer[60] = (65535 * 16 * 63) & 0xFFFF; /* Total addressable sectors (LBA) */ ide->buffer[60] = (65535 * 16 * 63) & 0xFFFF; /* Total addressable sectors (LBA) */
ide->buffer[61] = (65535 * 16 * 63) >> 16; ide->buffer[61] = (65535 * 16 * 63) >> 16;
@ -281,6 +301,8 @@ static void ide_identify(IDE *ide)
ide->buffer[60] = (hdc[cur_ide[0]].tracks * hdc[cur_ide[0]].hpc * hdc[cur_ide[0]].spt) & 0xFFFF; /* Total addressable sectors (LBA) */ ide->buffer[60] = (hdc[cur_ide[0]].tracks * hdc[cur_ide[0]].hpc * hdc[cur_ide[0]].spt) & 0xFFFF; /* Total addressable sectors (LBA) */
ide->buffer[61] = (hdc[cur_ide[0]].tracks * hdc[cur_ide[0]].hpc * hdc[cur_ide[0]].spt) >> 16; ide->buffer[61] = (hdc[cur_ide[0]].tracks * hdc[cur_ide[0]].hpc * hdc[cur_ide[0]].spt) >> 16;
#endif #endif
ide->buffer[63] = 7; /*Multiword DMA*/
ide->buffer[80] = 0xe; /*ATA-1 to ATA-3 supported*/
} }
/** /**
@ -571,7 +593,9 @@ void writeidew(int ide_board, uint16_t val)
if (ide->pos>=(ide->packlen+2)) if (ide->pos>=(ide->packlen+2))
{ {
ide->packetstatus=5; ide->packetstatus=5;
timer_process();
idecallback[ide_board]=6*IDE_TIME; idecallback[ide_board]=6*IDE_TIME;
timer_update_outstanding();
// pclog("Packet over!\n"); // pclog("Packet over!\n");
ide_irq_lower(ide); ide_irq_lower(ide);
} }
@ -583,8 +607,10 @@ void writeidew(int ide_board, uint16_t val)
ide->pos=0; ide->pos=0;
ide->atastat = BUSY_STAT; ide->atastat = BUSY_STAT;
ide->packetstatus=1; ide->packetstatus=1;
idecallback[ide_board]=6*IDE_TIME; /* idecallback[ide_board]=6*IDE_TIME;*/
timer_process();
callbackide(ide_board); callbackide(ide_board);
timer_update_outstanding();
// idecallback[ide_board]=60*IDE_TIME; // idecallback[ide_board]=60*IDE_TIME;
// if ((ide->buffer[0]&0xFF)==0x43) idecallback[ide_board]=1*IDE_TIME; // if ((ide->buffer[0]&0xFF)==0x43) idecallback[ide_board]=1*IDE_TIME;
// pclog("Packet now waiting!\n"); // pclog("Packet now waiting!\n");
@ -598,15 +624,25 @@ void writeidew(int ide_board, uint16_t val)
{ {
ide->pos=0; ide->pos=0;
ide->atastat = BUSY_STAT; ide->atastat = BUSY_STAT;
idecallback[ide_board]=6*IDE_TIME; timer_process();
// callbackide(ide_board); if (ide->command == WIN_WRITE_MULTIPLE)
callbackide(ide_board);
else
idecallback[ide_board]=6*IDE_TIME;
timer_update_outstanding();
} }
} }
void writeidel(int ide_board, uint32_t val)
{
// pclog("WriteIDEl %08X\n", val);
writeidew(ide_board, val);
writeidew(ide_board, val >> 16);
}
void writeide(int ide_board, uint16_t addr, uint8_t val) void writeide(int ide_board, uint16_t addr, uint8_t val)
{ {
IDE *ide = &ide_drives[cur_ide[ide_board]]; IDE *ide = &ide_drives[cur_ide[ide_board]];
uint8_t *idebufferb = (uint8_t *) ide->buffer;
#ifndef RPCEMU_IDE #ifndef RPCEMU_IDE
/* if (ide_board && (cr0&1) && !(eflags&VM_FLAG)) /* if (ide_board && (cr0&1) && !(eflags&VM_FLAG))
{ {
@ -614,6 +650,8 @@ void writeide(int ide_board, uint16_t addr, uint8_t val)
return; return;
}*/ }*/
#endif #endif
// if ((cr0&1) && !(eflags&VM_FLAG))
// pclog("WriteIDE %04X %02X from %04X(%08X):%08X\n", addr, val, CS, cs, pc);
// return; // return;
addr|=0x80; addr|=0x80;
// if (ide_board) pclog("Write IDEb %04X %02X %04X(%08X):%04X %i %02X %02X\n",addr,val,CS,cs,pc,ins,ide->atastat,ide_drives[0].atastat); // if (ide_board) pclog("Write IDEb %04X %02X %04X(%08X):%04X %i %02X %02X\n",addr,val,CS,cs,pc,ins,ide->atastat,ide_drives[0].atastat);
@ -660,9 +698,26 @@ void writeide(int ide_board, uint16_t addr, uint8_t val)
dumpregs(); dumpregs();
exit(-1); exit(-1);
}*/ }*/
cur_ide[ide_board]=((val>>4)&1)+(ide_board<<1);
ide = &ide_drives[cur_ide[ide_board]]; if (cur_ide[ide_board] != ((val>>4)&1)+(ide_board<<1))
{
cur_ide[ide_board]=((val>>4)&1)+(ide_board<<1);
if (ide->reset)
{
ide->atastat = READY_STAT | DSC_STAT;
ide->error=1;
ide->secount=1;
ide->sector=1;
ide->head=0;
ide->cylinder=0;
ide->reset = 0;
return;
}
ide = &ide_drives[cur_ide[ide_board]];
}
ide->head=val&0xF; ide->head=val&0xF;
ide->lba=val&0x40; ide->lba=val&0x40;
@ -684,17 +739,32 @@ void writeide(int ide_board, uint16_t addr, uint8_t val)
case WIN_SRST: /* ATAPI Device Reset */ case WIN_SRST: /* ATAPI Device Reset */
if (IDE_DRIVE_IS_CDROM(ide)) ide->atastat = BUSY_STAT; if (IDE_DRIVE_IS_CDROM(ide)) ide->atastat = BUSY_STAT;
else ide->atastat = READY_STAT; else ide->atastat = READY_STAT;
timer_process();
idecallback[ide_board]=100*IDE_TIME; idecallback[ide_board]=100*IDE_TIME;
timer_update_outstanding();
return; return;
case WIN_RESTORE: case WIN_RESTORE:
case WIN_SEEK: case WIN_SEEK:
// pclog("WIN_RESTORE start\n");
ide->atastat = READY_STAT; ide->atastat = READY_STAT;
timer_process();
idecallback[ide_board]=100*IDE_TIME; idecallback[ide_board]=100*IDE_TIME;
timer_update_outstanding();
return; return;
case WIN_READ_MULTIPLE:
if (!ide->blocksize)
fatal("READ_MULTIPLE - blocksize = 0\n");
#if 0
if (ide->lba) pclog("Read Multiple %i sectors from LBA addr %07X\n",ide->secount,ide->lba_addr);
else pclog("Read Multiple %i sectors from sector %i cylinder %i head %i %i\n",ide->secount,ide->sector,ide->cylinder,ide->head,ins);
#endif
ide->blockcount = 0;
case WIN_READ: case WIN_READ:
case WIN_READ_NORETRY: case WIN_READ_NORETRY:
case WIN_READ_DMA:
/* if (ide.secount>1) /* if (ide.secount>1)
{ {
fatal("Read %i sectors from sector %i cylinder %i head %i\n",ide.secount,ide.sector,ide.cylinder,ide.head); fatal("Read %i sectors from sector %i cylinder %i head %i\n",ide.secount,ide.sector,ide.cylinder,ide.head);
@ -704,12 +774,23 @@ void writeide(int ide_board, uint16_t addr, uint8_t val)
else pclog("Read %i sectors from sector %i cylinder %i head %i %i\n",ide->secount,ide->sector,ide->cylinder,ide->head,ins); else pclog("Read %i sectors from sector %i cylinder %i head %i %i\n",ide->secount,ide->sector,ide->cylinder,ide->head,ins);
#endif #endif
ide->atastat = BUSY_STAT; ide->atastat = BUSY_STAT;
timer_process();
idecallback[ide_board]=200*IDE_TIME; idecallback[ide_board]=200*IDE_TIME;
timer_update_outstanding();
return; return;
case WIN_WRITE_MULTIPLE:
if (!ide->blocksize)
fatal("Write_MULTIPLE - blocksize = 0\n");
#if 0
if (ide->lba) pclog("Write Multiple %i sectors from LBA addr %07X\n",ide->secount,ide->lba_addr);
else pclog("Write Multiple %i sectors to sector %i cylinder %i head %i\n",ide->secount,ide->sector,ide->cylinder,ide->head);
#endif
ide->blockcount = 0;
case WIN_WRITE: case WIN_WRITE:
case WIN_WRITE_NORETRY: case WIN_WRITE_NORETRY:
/* if (ide.secount>1) /* if (ide.secount>1)
{ {
fatal("Write %i sectors to sector %i cylinder %i head %i\n",ide.secount,ide.sector,ide.cylinder,ide.head); fatal("Write %i sectors to sector %i cylinder %i head %i\n",ide.secount,ide.sector,ide.cylinder,ide.head);
}*/ }*/
@ -721,13 +802,26 @@ void writeide(int ide_board, uint16_t addr, uint8_t val)
ide->pos=0; ide->pos=0;
return; return;
case WIN_WRITE_DMA:
#if 0
if (ide->lba) pclog("Write %i sectors from LBA addr %07X\n",ide->secount,ide->lba_addr);
else pclog("Write %i sectors to sector %i cylinder %i head %i\n",ide->secount,ide->sector,ide->cylinder,ide->head);
#endif
ide->atastat = BUSY_STAT;
timer_process();
idecallback[ide_board]=200*IDE_TIME;
timer_update_outstanding();
return;
case WIN_VERIFY: case WIN_VERIFY:
#if 0 #if 0
if (ide->lba) pclog("Read verify %i sectors from LBA addr %07X\n",ide->secount,ide->lba_addr); if (ide->lba) pclog("Read verify %i sectors from LBA addr %07X\n",ide->secount,ide->lba_addr);
else pclog("Read verify %i sectors from sector %i cylinder %i head %i\n",ide->secount,ide->sector,ide->cylinder,ide->head); else pclog("Read verify %i sectors from sector %i cylinder %i head %i\n",ide->secount,ide->sector,ide->cylinder,ide->head);
#endif #endif
ide->atastat = BUSY_STAT; ide->atastat = BUSY_STAT;
timer_process();
idecallback[ide_board]=200*IDE_TIME; idecallback[ide_board]=200*IDE_TIME;
timer_update_outstanding();
return; return;
case WIN_FORMAT: case WIN_FORMAT:
@ -739,17 +833,22 @@ void writeide(int ide_board, uint16_t addr, uint8_t val)
case WIN_SPECIFY: /* Initialize Drive Parameters */ case WIN_SPECIFY: /* Initialize Drive Parameters */
ide->atastat = BUSY_STAT; ide->atastat = BUSY_STAT;
timer_process();
idecallback[ide_board]=200*IDE_TIME; idecallback[ide_board]=200*IDE_TIME;
timer_update_outstanding();
// pclog("SPECIFY\n"); // pclog("SPECIFY\n");
// output=1; // output=1;
return; return;
case WIN_DRIVE_DIAGNOSTICS: /* Execute Drive Diagnostics */ case WIN_DRIVE_DIAGNOSTICS: /* Execute Drive Diagnostics */
case WIN_PIDENTIFY: /* Identify Packet Device */ case WIN_PIDENTIFY: /* Identify Packet Device */
case WIN_SET_MULTIPLE_MODE: /*Set Multiple Mode*/
// output=1; // output=1;
case WIN_SETIDLE1: /* Idle */ case WIN_SETIDLE1: /* Idle */
ide->atastat = BUSY_STAT; ide->atastat = BUSY_STAT;
timer_process();
idecallback[ide_board]=200*IDE_TIME; idecallback[ide_board]=200*IDE_TIME;
timer_update_outstanding();
return; return;
case WIN_IDENTIFY: /* Identify Device */ case WIN_IDENTIFY: /* Identify Device */
@ -757,13 +856,17 @@ void writeide(int ide_board, uint16_t addr, uint8_t val)
// output=3; // output=3;
// timetolive=500; // timetolive=500;
ide->atastat = BUSY_STAT; ide->atastat = BUSY_STAT;
timer_process();
idecallback[ide_board]=200*IDE_TIME; idecallback[ide_board]=200*IDE_TIME;
timer_update_outstanding();
return; return;
case WIN_PACKETCMD: /* ATAPI Packet */ case WIN_PACKETCMD: /* ATAPI Packet */
ide->packetstatus=0; ide->packetstatus=0;
ide->atastat = BUSY_STAT; ide->atastat = BUSY_STAT;
timer_process();
idecallback[ide_board]=1;//30*IDE_TIME; idecallback[ide_board]=1;//30*IDE_TIME;
timer_update_outstanding();
ide->pos=0; ide->pos=0;
return; return;
@ -772,15 +875,18 @@ void writeide(int ide_board, uint16_t addr, uint8_t val)
ide->atastat = READY_STAT | ERR_STAT | DSC_STAT; ide->atastat = READY_STAT | ERR_STAT | DSC_STAT;
ide->error = ABRT_ERR; ide->error = ABRT_ERR;
ide_irq_raise(ide); ide_irq_raise(ide);
/* fatal("Bad IDE command %02X\n", val);*/
return; return;
} }
// fatal("Bad IDE command %02X\n", val);
return; return;
case 0x3F6: /* Device control */ case 0x3F6: /* Device control */
if ((ide->fdisk&4) && !(val&4) && (ide->type != IDE_NONE)) if ((ide->fdisk&4) && !(val&4) && (ide->type != IDE_NONE))
{ {
timer_process();
idecallback[ide_board]=500*IDE_TIME; idecallback[ide_board]=500*IDE_TIME;
timer_update_outstanding();
ide->reset = 1; ide->reset = 1;
ide->atastat = BUSY_STAT; ide->atastat = BUSY_STAT;
// pclog("IDE Reset\n"); // pclog("IDE Reset\n");
@ -795,7 +901,6 @@ void writeide(int ide_board, uint16_t addr, uint8_t val)
uint8_t readide(int ide_board, uint16_t addr) uint8_t readide(int ide_board, uint16_t addr)
{ {
IDE *ide = &ide_drives[cur_ide[ide_board]]; IDE *ide = &ide_drives[cur_ide[ide_board]];
const uint8_t *idebufferb = (const uint8_t *) ide->buffer;
uint8_t temp; uint8_t temp;
uint16_t tempw; uint16_t tempw;
@ -807,6 +912,8 @@ uint8_t readide(int ide_board, uint16_t addr)
return 0xFF; return 0xFF;
}*/ }*/
#endif #endif
// if ((cr0&1) && !(eflags&VM_FLAG))
// pclog("ReadIDE %04X from %04X(%08X):%08X\n", addr, CS, cs, pc);
// return 0xFF; // return 0xFF;
if (ide->type == IDE_NONE && addr != 0x1f6) return 0xff; if (ide->type == IDE_NONE && addr != 0x1f6) return 0xff;
@ -866,7 +973,7 @@ uint8_t readide(int ide_board, uint16_t addr)
else else
{ {
// && ide->service) return ide.atastat[ide.board]|SERVICE_STAT; // && ide->service) return ide.atastat[ide.board]|SERVICE_STAT;
// pclog("Return status %02X\n",ide->atastat); // pclog("Return status %02X %04X:%04X %02X %02X\n",ide->atastat, CS ,pc, AH, BH);
temp = ide->atastat; temp = ide->atastat;
} }
break; break;
@ -910,7 +1017,7 @@ uint16_t readidew(int ide_board)
}*/ }*/
#endif #endif
// return 0xFFFF; // return 0xFFFF;
// pclog("Read IDEw %04X %04X:%04X %02X %i\n",ide->buffer[ide->pos >> 1],CS,pc,opcode,ins); // pclog("Read IDEw %04X %04X:%04X %02X %i %i\n",ide->buffer[ide->pos >> 1],CS,pc,opcode,ins, ide->pos);
//if (idedebug) pclog("Read IDEW %08X\n",PC); //if (idedebug) pclog("Read IDEW %08X\n",PC);
@ -921,7 +1028,7 @@ uint16_t readidew(int ide_board)
ide->pos+=2; ide->pos+=2;
if ((ide->pos>=512 && ide->command != WIN_PACKETCMD) || (ide->command == WIN_PACKETCMD && ide->pos>=ide->packlen)) if ((ide->pos>=512 && ide->command != WIN_PACKETCMD) || (ide->command == WIN_PACKETCMD && ide->pos>=ide->packlen))
{ {
// pclog("Over! packlen %i %i\n",ide.packlen,ide.pos); // pclog("Over! packlen %i %i\n",ide->packlen,ide->pos);
ide->pos=0; ide->pos=0;
if (ide->command == WIN_PACKETCMD)// && ide.packetstatus==6) if (ide->command == WIN_PACKETCMD)// && ide.packetstatus==6)
{ {
@ -932,16 +1039,24 @@ uint16_t readidew(int ide_board)
{ {
ide->atastat = READY_STAT | DSC_STAT; ide->atastat = READY_STAT | DSC_STAT;
ide->packetstatus=0; ide->packetstatus=0;
if (ide->command == WIN_READ || ide->command == WIN_READ_NORETRY) if (ide->command == WIN_READ || ide->command == WIN_READ_NORETRY || ide->command == WIN_READ_MULTIPLE)
{ {
ide->secount--; ide->secount--;
if (ide->secount) if (ide->secount)
{ {
ide_next_sector(ide); ide_next_sector(ide);
ide->atastat = BUSY_STAT; ide->atastat = BUSY_STAT;
idecallback[ide_board]=6*IDE_TIME; timer_process();
if (ide->command == WIN_READ_MULTIPLE)
callbackide(ide_board);
else
idecallback[ide_board]=6*IDE_TIME;
timer_update_outstanding();
// pclog("set idecallback\n");
// callbackide(ide_board); // callbackide(ide_board);
} }
// else
// pclog("readidew done %02X\n", ide->atastat);
} }
} }
} }
@ -949,6 +1064,12 @@ uint16_t readidew(int ide_board)
return temp; return temp;
} }
uint32_t readidel(int ide_board)
{
uint16_t temp = readidew(ide_board);
return temp | (readidew(ide_board) << 16);
}
int times30=0; int times30=0;
void callbackide(int ide_board) void callbackide(int ide_board)
{ {
@ -972,6 +1093,7 @@ void callbackide(int ide_board)
ide->head=0; ide->head=0;
ide->cylinder=0; ide->cylinder=0;
ide->reset = 0; ide->reset = 0;
ide->blocksize = 0;
// pclog("Reset callback\n"); // pclog("Reset callback\n");
return; return;
} }
@ -996,9 +1118,10 @@ void callbackide(int ide_board)
case WIN_RESTORE: case WIN_RESTORE:
case WIN_SEEK: case WIN_SEEK:
if (IDE_DRIVE_IS_CDROM(ide)) { if (IDE_DRIVE_IS_CDROM(ide)) {
pclog("WIN_RESTORE callback on CD-ROM\n");
goto abort_cmd; goto abort_cmd;
} }
// pclog("Restore callback\n"); // pclog("WIN_RESTORE callback\n");
ide->atastat = READY_STAT | DSC_STAT; ide->atastat = READY_STAT | DSC_STAT;
ide_irq_raise(ide); ide_irq_raise(ide);
return; return;
@ -1026,6 +1149,66 @@ void callbackide(int ide_board)
#endif #endif
return; return;
case WIN_READ_DMA:
if (IDE_DRIVE_IS_CDROM(ide)) {
goto abort_cmd;
}
addr = ide_get_sector(ide) * 512;
fseeko64(ide->hdfile, addr, SEEK_SET);
fread(ide->buffer, 512, 1, ide->hdfile);
ide->pos=0;
if (ide_bus_master_read_sector)
{
if (ide_bus_master_read_sector(ide_board, (uint8_t *)ide->buffer))
idecallback[ide_board]=6*IDE_TIME; /*DMA not performed, try again later*/
else
{
/*DMA successful*/
ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT;
ide->secount--;
if (ide->secount)
{
ide_next_sector(ide);
ide->atastat = BUSY_STAT;
idecallback[ide_board]=6*IDE_TIME;
}
else
{
ide_irq_raise(ide);
ide_bus_master_set_irq(ide_board);
}
}
}
#ifndef RPCEMU_IDE
readflash=1;
#endif
return;
case WIN_READ_MULTIPLE:
if (IDE_DRIVE_IS_CDROM(ide)) {
goto abort_cmd;
}
addr = ide_get_sector(ide) * 512;
// pclog("Read multiple from %08X %i (%i) %i\n", addr, ide->blockcount, ide->blocksize, ide->secount);
fseeko64(ide->hdfile, addr, SEEK_SET);
fread(ide->buffer, 512, 1, ide->hdfile);
ide->pos=0;
ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT;
if (!ide->blockcount)// || ide->secount == 1)
{
// pclog("Read multiple int\n");
ide_irq_raise(ide);
}
ide->blockcount++;
if (ide->blockcount >= ide->blocksize)
ide->blockcount = 0;
#ifndef RPCEMU_IDE
readflash=1;
#endif
return;
case WIN_WRITE: case WIN_WRITE:
case WIN_WRITE_NORETRY: case WIN_WRITE_NORETRY:
if (IDE_DRIVE_IS_CDROM(ide)) { if (IDE_DRIVE_IS_CDROM(ide)) {
@ -1049,6 +1232,71 @@ void callbackide(int ide_board)
readflash=1; readflash=1;
#endif #endif
return; return;
case WIN_WRITE_DMA:
if (IDE_DRIVE_IS_CDROM(ide)) {
goto abort_cmd;
}
if (ide_bus_master_write_sector)
{
if (ide_bus_master_write_sector(ide_board, (uint8_t *)ide->buffer))
idecallback[ide_board]=6*IDE_TIME; /*DMA not performed, try again later*/
else
{
/*DMA successful*/
addr = ide_get_sector(ide) * 512;
fseeko64(ide->hdfile, addr, SEEK_SET);
fwrite(ide->buffer, 512, 1, ide->hdfile);
ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT;
ide->secount--;
if (ide->secount)
{
ide_next_sector(ide);
ide->atastat = BUSY_STAT;
idecallback[ide_board]=6*IDE_TIME;
}
else
{
ide_irq_raise(ide);
ide_bus_master_set_irq(ide_board);
}
}
}
#ifndef RPCEMU_IDE
readflash=1;
#endif
return;
case WIN_WRITE_MULTIPLE:
if (IDE_DRIVE_IS_CDROM(ide)) {
goto abort_cmd;
}
addr = ide_get_sector(ide) * 512;
// pclog("Write sector callback %i %i %i offset %08X %i left %i\n",ide.sector,ide.cylinder,ide.head,addr,ide.secount,ide.spt);
fseeko64(ide->hdfile, addr, SEEK_SET);
fwrite(ide->buffer, 512, 1, ide->hdfile);
ide->blockcount++;
if (ide->blockcount >= ide->blocksize || ide->secount == 1)
{
ide->blockcount = 0;
ide_irq_raise(ide);
}
ide->secount--;
if (ide->secount)
{
ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT;
ide->pos=0;
ide_next_sector(ide);
}
else
ide->atastat = READY_STAT | DSC_STAT;
#ifndef RPCEMU_IDE
readflash=1;
#endif
return;
case WIN_VERIFY: case WIN_VERIFY:
if (IDE_DRIVE_IS_CDROM(ide)) { if (IDE_DRIVE_IS_CDROM(ide)) {
@ -1117,6 +1365,21 @@ void callbackide(int ide_board)
// pclog("Not ATAPI\n"); // pclog("Not ATAPI\n");
goto abort_cmd; goto abort_cmd;
case WIN_SET_MULTIPLE_MODE:
if (IDE_DRIVE_IS_CDROM(ide)) {
#ifndef RPCEMU_IDE
pclog("IS CDROM - ABORT\n");
#endif
goto abort_cmd;
}
ide->blocksize = ide->secount;
ide->atastat = READY_STAT | DSC_STAT;
#ifndef RPCEMU_IDE
pclog("Set multiple mode - %i\n", ide->blocksize);
#endif
ide_irq_raise(ide);
return;
case WIN_SETIDLE1: /* Idle */ case WIN_SETIDLE1: /* Idle */
case 0xEF: case 0xEF:
goto abort_cmd; goto abort_cmd;
@ -1207,6 +1470,18 @@ abort_cmd:
ide_irq_raise(ide); ide_irq_raise(ide);
} }
void ide_callback_pri()
{
idecallback[0] = 0;
callbackide(0);
}
void ide_callback_sec()
{
idecallback[1] = 0;
callbackide(1);
}
/*ATAPI CD-ROM emulation /*ATAPI CD-ROM emulation
This mostly seems to work. It is implemented only on Windows at the moment as This mostly seems to work. It is implemented only on Windows at the moment as
I haven't had time to implement any interfaces for it in the generic gui. I haven't had time to implement any interfaces for it in the generic gui.
@ -1714,44 +1989,93 @@ static void callreadcd(IDE *ide)
void ide_write_pri(uint16_t addr, uint8_t val) void ide_write_pri(uint16_t addr, uint8_t val, void *priv)
{ {
writeide(0, addr, val); writeide(0, addr, val);
} }
void ide_write_pri_w(uint16_t addr, uint16_t val) void ide_write_pri_w(uint16_t addr, uint16_t val, void *priv)
{ {
writeidew(0, val); writeidew(0, val);
} }
uint8_t ide_read_pri(uint16_t addr) void ide_write_pri_l(uint16_t addr, uint32_t val, void *priv)
{
writeidel(0, val);
}
uint8_t ide_read_pri(uint16_t addr, void *priv)
{ {
return readide(0, addr); return readide(0, addr);
} }
uint16_t ide_read_pri_w(uint16_t addr) uint16_t ide_read_pri_w(uint16_t addr, void *priv)
{ {
return readidew(0); return readidew(0);
} }
uint32_t ide_read_pri_l(uint16_t addr, void *priv)
{
return readidel(0);
}
void ide_write_sec(uint16_t addr, uint8_t val) void ide_write_sec(uint16_t addr, uint8_t val, void *priv)
{ {
writeide(1, addr, val); writeide(1, addr, val);
} }
void ide_write_sec_w(uint16_t addr, uint16_t val) void ide_write_sec_w(uint16_t addr, uint16_t val, void *priv)
{ {
writeidew(1, val); writeidew(1, val);
} }
uint8_t ide_read_sec(uint16_t addr) void ide_write_sec_l(uint16_t addr, uint32_t val, void *priv)
{
writeidel(1, val);
}
uint8_t ide_read_sec(uint16_t addr, void *priv)
{ {
return readide(1, addr); return readide(1, addr);
} }
uint16_t ide_read_sec_w(uint16_t addr) uint16_t ide_read_sec_w(uint16_t addr, void *priv)
{ {
return readidew(1); return readidew(1);
} }
uint32_t ide_read_sec_l(uint16_t addr, void *priv)
{
return readidel(1);
}
void ide_pri_enable()
{
io_sethandler(0x01f0, 0x0008, ide_read_pri, ide_read_pri_w, ide_read_pri_l, ide_write_pri, ide_write_pri_w, ide_write_pri_l, NULL);
io_sethandler(0x03f6, 0x0001, ide_read_pri, NULL, NULL, ide_write_pri, NULL, NULL , NULL);
}
void ide_pri_disable()
{
io_removehandler(0x01f0, 0x0008, ide_read_pri, ide_read_pri_w, ide_read_pri_l, ide_write_pri, ide_write_pri_w, ide_write_pri_l, NULL);
io_removehandler(0x03f6, 0x0001, ide_read_pri, NULL, NULL, ide_write_pri, NULL, NULL , NULL);
}
void ide_sec_enable()
{
io_sethandler(0x0170, 0x0008, ide_read_sec, ide_read_sec_w, ide_read_sec_l, ide_write_sec, ide_write_sec_w, ide_write_sec_l, NULL);
io_sethandler(0x0376, 0x0001, ide_read_sec, NULL, NULL, ide_write_sec, NULL, NULL , NULL);
}
void ide_sec_disable()
{
io_removehandler(0x0170, 0x0008, ide_read_sec, ide_read_sec_w, ide_read_sec_l, ide_write_sec, ide_write_sec_w, ide_write_sec_l, NULL);
io_removehandler(0x0376, 0x0001, ide_read_sec, NULL, NULL, ide_write_sec, NULL, NULL , NULL);
}
void ide_init() void ide_init()
{ {
io_sethandler(0x01f0, 0x0008, ide_read_pri, ide_read_pri_w, NULL, ide_write_pri, ide_write_pri_w, NULL); ide_pri_enable();
io_sethandler(0x03f6, 0x0001, ide_read_pri, NULL, NULL, ide_write_pri, NULL, NULL); ide_sec_enable();
io_sethandler(0x0170, 0x0008, ide_read_sec, ide_read_sec_w, NULL, ide_write_sec, ide_write_sec_w, NULL); ide_bus_master_read_sector = ide_bus_master_write_sector = NULL;
io_sethandler(0x0376, 0x0001, ide_read_sec, NULL, NULL, ide_write_sec, NULL, NULL);
timer_add(ide_callback_pri, &idecallback[0], &idecallback[0], NULL);
timer_add(ide_callback_sec, &idecallback[1], &idecallback[1], NULL);
}
void ide_set_bus_master(int (*read_sector)(int channel, uint8_t *data), int (*write_sector)(int channel, uint8_t *data), void (*set_irq)(int channel))
{
ide_bus_master_read_sector = read_sector;
ide_bus_master_write_sector = write_sector;
ide_bus_master_set_irq = set_irq;
} }

View file

@ -10,6 +10,11 @@ extern uint16_t readidew(int ide_board);
extern void callbackide(int ide_board); extern void callbackide(int ide_board);
extern void resetide(void); extern void resetide(void);
extern void ide_init(); extern void ide_init();
extern void ide_pri_enable();
extern void ide_sec_enable();
extern void ide_pri_disable();
extern void ide_sec_disable();
extern void ide_set_bus_master(int (*read_sector)(int channel, uint8_t *data), int (*write_sector)(int channel, uint8_t *data), void (*set_irq)(int channel));
/*ATAPI stuff*/ /*ATAPI stuff*/
typedef struct ATAPI typedef struct ATAPI

208
src/io.c
View file

@ -1,89 +1,112 @@
#include "ibm.h" #include "ibm.h"
#include "ide.h" #include "ide.h"
#include "io.h"
#include "video.h" #include "video.h"
#include "cpu.h" #include "cpu.h"
uint8_t (*port_inb[0x10000][2])(uint16_t addr); uint8_t (*port_inb[0x10000][2])(uint16_t addr, void *priv);
uint16_t (*port_inw[0x10000][2])(uint16_t addr); uint16_t (*port_inw[0x10000][2])(uint16_t addr, void *priv);
uint32_t (*port_inl[0x10000][2])(uint16_t addr); uint32_t (*port_inl[0x10000][2])(uint16_t addr, void *priv);
void (*port_outb[0x10000][2])(uint16_t addr, uint8_t val); void (*port_outb[0x10000][2])(uint16_t addr, uint8_t val, void *priv);
void (*port_outw[0x10000][2])(uint16_t addr, uint16_t val); void (*port_outw[0x10000][2])(uint16_t addr, uint16_t val, void *priv);
void (*port_outl[0x10000][2])(uint16_t addr, uint32_t val); void (*port_outl[0x10000][2])(uint16_t addr, uint32_t val, void *priv);
void *port_priv[0x10000][2];
void io_init() void io_init()
{ {
int c; int c;
pclog("io_init\n");
for (c = 0; c < 0x10000; c++) for (c = 0; c < 0x10000; c++)
{ {
port_inb[c][0] = port_inw[c][0] = port_inl[c][0] = NULL; port_inb[c][0] = port_inw[c][0] = port_inl[c][0] = NULL;
port_outb[c][0] = port_outw[c][0] = port_outl[c][0] = NULL; port_outb[c][0] = port_outw[c][0] = port_outl[c][0] = NULL;
port_inb[c][1] = port_inw[c][1] = port_inl[c][1] = NULL; port_inb[c][1] = port_inw[c][1] = port_inl[c][1] = NULL;
port_outb[c][1] = port_outw[c][1] = port_outl[c][1] = NULL; port_outb[c][1] = port_outw[c][1] = port_outl[c][1] = NULL;
port_priv[c][0] = port_priv[c][1] = NULL;
} }
} }
void io_sethandler(uint16_t base, int size, void io_sethandler(uint16_t base, int size,
uint8_t (*inb)(uint16_t addr), uint8_t (*inb)(uint16_t addr, void *priv),
uint16_t (*inw)(uint16_t addr), uint16_t (*inw)(uint16_t addr, void *priv),
uint32_t (*inl)(uint16_t addr), uint32_t (*inl)(uint16_t addr, void *priv),
void (*outb)(uint16_t addr, uint8_t val), void (*outb)(uint16_t addr, uint8_t val, void *priv),
void (*outw)(uint16_t addr, uint16_t val), void (*outw)(uint16_t addr, uint16_t val, void *priv),
void (*outl)(uint16_t addr, uint32_t val)) void (*outl)(uint16_t addr, uint32_t val, void *priv),
void *priv)
{ {
int c; int c;
for (c = 0; c < size; c++) for (c = 0; c < size; c++)
{ {
if (!port_inb[ base + c][0]) port_inb[ base + c][0] = inb; if (!port_inb[ base + c][0] && !port_inw[ base + c][0] && !port_inl[ base + c][0] &&
else if (!port_inb[ base + c][1]) port_inb[ base + c][1] = inb; !port_outb[base + c][0] && !port_outw[base + c][0] && !port_outl[base + c][0])
if (!port_inw[ base + c][0]) port_inw[ base + c][0] = inw; {
else if (!port_inw[ base + c][1]) port_inw[ base + c][1] = inw; port_inb[ base + c][0] = inb;
if (!port_inl[ base + c][0]) port_inl[ base + c][0] = inl; port_inw[ base + c][0] = inw;
else if (!port_inl[ base + c][1]) port_inl[ base + c][1] = inl; port_inl[ base + c][0] = inl;
if (!port_outb[base + c][0]) port_outb[base + c][0] = outb; port_outb[base + c][0] = outb;
else if (!port_outb[base + c][1]) port_outb[base + c][1] = outb; port_outw[base + c][0] = outw;
if (!port_outw[base + c][0]) port_outw[base + c][0] = outw; port_outl[base + c][0] = outl;
else if (!port_outw[base + c][1]) port_outw[base + c][1] = outw; port_priv[base + c][0] = priv;
if (!port_outl[base + c][0]) port_outl[base + c][0] = outl; }
else if (!port_outl[base + c][1]) port_outl[base + c][1] = outl; else if (!port_inb[ base + c][1] && !port_inw[ base + c][1] && !port_inl[ base + c][1] &&
!port_outb[base + c][1] && !port_outw[base + c][1] && !port_outl[base + c][1])
{
port_inb[ base + c][1] = inb;
port_inw[ base + c][1] = inw;
port_inl[ base + c][1] = inl;
port_outb[base + c][1] = outb;
port_outw[base + c][1] = outw;
port_outl[base + c][1] = outl;
port_priv[base + c][1] = priv;
}
} }
} }
void io_removehandler(uint16_t base, int size, void io_removehandler(uint16_t base, int size,
uint8_t (*inb)(uint16_t addr), uint8_t (*inb)(uint16_t addr, void *priv),
uint16_t (*inw)(uint16_t addr), uint16_t (*inw)(uint16_t addr, void *priv),
uint32_t (*inl)(uint16_t addr), uint32_t (*inl)(uint16_t addr, void *priv),
void (*outb)(uint16_t addr, uint8_t val), void (*outb)(uint16_t addr, uint8_t val, void *priv),
void (*outw)(uint16_t addr, uint16_t val), void (*outw)(uint16_t addr, uint16_t val, void *priv),
void (*outl)(uint16_t addr, uint32_t val)) void (*outl)(uint16_t addr, uint32_t val, void *priv),
void *priv)
{ {
int c; int c;
for (c = 0; c < size; c++) for (c = 0; c < size; c++)
{ {
if (port_inb[ base + c][0] == inb) if (port_priv[base + c][0] == priv)
port_inb[ base + c][0] = NULL; {
if (port_inb[ base + c][1] == inb) if (port_inb[ base + c][0] == inb)
port_inb[ base + c][1] = NULL; port_inb[ base + c][0] = NULL;
if (port_inw[ base + c][0] == inw) if (port_inw[ base + c][0] == inw)
port_inw[ base + c][0] = NULL; port_inw[ base + c][0] = NULL;
if (port_inw[ base + c][1] == inw) if (port_inl[ base + c][0] == inl)
port_inw[ base + c][1] = NULL; port_inl[ base + c][0] = NULL;
if (port_inl[ base + c][0] == inl) if (port_outb[ base + c][0] == outb)
port_inl[ base + c][0] = NULL; port_outb[ base + c][0] = NULL;
if (port_inl[ base + c][1] == inl) if (port_outw[ base + c][0] == outw)
port_inl[ base + c][1] = NULL; port_outw[ base + c][0] = NULL;
if (port_outb[ base + c][0] == outb) if (port_outl[ base + c][0] == outl)
port_outb[ base + c][0] = NULL; port_outl[ base + c][0] = NULL;
if (port_outb[ base + c][1] == outb) }
port_outb[ base + c][1] = NULL; if (port_priv[base + c][1] == priv)
if (port_outw[ base + c][0] == outw) {
port_outw[ base + c][0] = NULL; if (port_inb[ base + c][1] == inb)
if (port_outw[ base + c][1] == outw) port_inb[ base + c][1] = NULL;
port_outw[ base + c][1] = NULL; if (port_inw[ base + c][1] == inw)
if (port_outl[ base + c][0] == outl) port_inw[ base + c][1] = NULL;
port_outl[ base + c][0] = NULL; if (port_inl[ base + c][1] == inl)
if (port_outl[ base + c][1] == outl) port_inl[ base + c][1] = NULL;
port_outl[ base + c][1] = NULL; if (port_outb[ base + c][1] == outb)
port_outb[ base + c][1] = NULL;
if (port_outw[ base + c][1] == outw)
port_outw[ base + c][1] = NULL;
if (port_outl[ base + c][1] == outl)
port_outl[ base + c][1] = NULL;
}
} }
} }
@ -95,63 +118,39 @@ int t237=0;
uint8_t inb(uint16_t port) uint8_t inb(uint16_t port)
{ {
uint8_t temp = 0xff; uint8_t temp = 0xff;
int tempi;
if (port_inb[port][0])
temp &= port_inb[port][0](port);
if (port_inb[port][1])
temp &= port_inb[port][1](port);
return temp;
if (port&0x80) sw9=2;
// if ((port&0x3F0)==0x3D0) printf("Video access read %03X %04X:%04X\n",port,cs>>4,pc);
// if (cs<0xF0000 || cs>0x100000) printf("IN %04X %04X(%06X):%08X\n",port,CS,cs,pc);
// /*if (output==3) */printf("IN %04X %04X:%04X\n",port,CS,pc);
// if (port == 0x23) pclog("IN %04X %04X:%08X\n", port, CS, pc);
switch (port)
{
case 0x220: case 0x221: case 0x222: case 0x223: /*Gameblaster*/
if (sbtype>=SBPRO) return readsb(port);
if (GAMEBLASTER) return readcms(port);
return 0xFF;
}
// printf("Bad IN port %04X %04X:%04X\n",port,cs>>4,pc);
return 0xff;
/*dumpregs();
exit(-1);*/
}
/*uint8_t inb(uint16_t port) if (port_inb[port][0])
{ temp &= port_inb[port][0](port, port_priv[port][0]);
uint8_t temp = _inb(port); if (port_inb[port][1])
// if (port != 0x61) pclog("IN %04X %02X %04X(%08X):%08X %f %04X %i %i\n", port, temp, CS, cs, pc, pit.c[1], CX, keybsenddelay, GetTickCount()); temp &= port_inb[port][1](port, port_priv[port][1]);
/* if (!port_inb[port][0] && !port_inb[port][1])
pclog("Bad INB %04X %04X:%04X\n", port, CS, pc);*/
return temp; return temp;
}*/ }
uint8_t cpu_readport(uint32_t port) { return inb(port); } uint8_t cpu_readport(uint32_t port) { return inb(port); }
void outb(uint16_t port, uint8_t val) void outb(uint16_t port, uint8_t val)
{ {
// /*if (output==3) */printf("OUT %04X %02X %04X(%08X):%08X %i %i\n", port, val, CS, cs, pc, ins, GetTickCount());
if (port_outb[port][0]) if (port_outb[port][0])
port_outb[port][0](port, val); port_outb[port][0](port, val, port_priv[port][0]);
if (port_outb[port][1]) if (port_outb[port][1])
port_outb[port][1](port, val); port_outb[port][1](port, val, port_priv[port][1]);
/* if (!port_outb[port][0] && !port_outb[port][1])
pclog("Bad OUTB %04X %02X %04X:%08X\n", port, val, CS, pc);*/
return; return;
switch (port)
{
case 0x220: case 0x221: case 0x222: case 0x223: /*Gameblaster*/
if (GAMEBLASTER) writecms(port,val);
return;
}
pclog("OUT %04X %02X %04X:%08X\n",port,val,CS,pc);
} }
uint16_t inw(uint16_t port) uint16_t inw(uint16_t port)
{ {
// pclog("INW %04X\n", port);
if (port_inw[port][0]) if (port_inw[port][0])
return port_inw[port][0](port); return port_inw[port][0](port, port_priv[port][0]);
if (port_inw[port][1]) if (port_inw[port][1])
return port_inw[port][1](port); return port_inw[port][1](port, port_priv[port][1]);
return inb(port) | (inb(port + 1) << 8); return inb(port) | (inb(port + 1) << 8);
} }
@ -159,10 +158,13 @@ uint16_t inw(uint16_t port)
void outw(uint16_t port, uint16_t val) void outw(uint16_t port, uint16_t val)
{ {
// printf("OUTW %04X %04X %04X:%08X\n",port,val, CS, pc); // printf("OUTW %04X %04X %04X:%08X\n",port,val, CS, pc);
/* if ((port & ~0xf) == 0xf000)
pclog("OUTW %04X %04X\n", port, val);*/
if (port_outw[port][0]) if (port_outw[port][0])
port_outw[port][0](port, val); port_outw[port][0](port, val, port_priv[port][0]);
if (port_outw[port][1]) if (port_outw[port][1])
port_outw[port][1](port, val); port_outw[port][1](port, val, port_priv[port][1]);
if (port_outw[port][0] || port_outw[port][1]) if (port_outw[port][0] || port_outw[port][1])
return; return;
@ -173,20 +175,24 @@ void outw(uint16_t port, uint16_t val)
uint32_t inl(uint16_t port) uint32_t inl(uint16_t port)
{ {
// pclog("INL %04X\n", port);
if (port_inl[port][0]) if (port_inl[port][0])
return port_inl[port][0](port); return port_inl[port][0](port, port_priv[port][0]);
if (port_inl[port][1]) if (port_inl[port][1])
return port_inl[port][1](port); return port_inl[port][1](port, port_priv[port][1]);
return inw(port) | (inw(port + 2) << 16); return inw(port) | (inw(port + 2) << 16);
} }
void outl(uint16_t port, uint32_t val) void outl(uint16_t port, uint32_t val)
{ {
/* if ((port & ~0xf) == 0xf000)
pclog("OUTL %04X %08X\n", port, val);*/
if (port_outl[port][0]) if (port_outl[port][0])
port_outl[port][0](port, val); port_outl[port][0](port, val, port_priv[port][0]);
if (port_outl[port][1]) if (port_outl[port][1])
port_outl[port][1](port, val); port_outl[port][1](port, val, port_priv[port][1]);
if (port_outl[port][0] || port_outl[port][1]) if (port_outl[port][0] || port_outl[port][1])
return; return;

View file

@ -1,17 +1,19 @@
void io_init(); void io_init();
void io_sethandler(uint16_t base, int size, void io_sethandler(uint16_t base, int size,
uint8_t (*inb)(uint16_t addr), uint8_t (*inb)(uint16_t addr, void *priv),
uint16_t (*inw)(uint16_t addr), uint16_t (*inw)(uint16_t addr, void *priv),
uint32_t (*inl)(uint16_t addr), uint32_t (*inl)(uint16_t addr, void *priv),
void (*outb)(uint16_t addr, uint8_t val), void (*outb)(uint16_t addr, uint8_t val, void *priv),
void (*outw)(uint16_t addr, uint16_t val), void (*outw)(uint16_t addr, uint16_t val, void *priv),
void (*outl)(uint16_t addr, uint32_t val)); void (*outl)(uint16_t addr, uint32_t val, void *priv),
void *priv);
void io_removehandler(uint16_t base, int size, void io_removehandler(uint16_t base, int size,
uint8_t (*inb)(uint16_t addr), uint8_t (*inb)(uint16_t addr, void *priv),
uint16_t (*inw)(uint16_t addr), uint16_t (*inw)(uint16_t addr, void *priv),
uint32_t (*inl)(uint16_t addr), uint32_t (*inl)(uint16_t addr, void *priv),
void (*outb)(uint16_t addr, uint8_t val), void (*outb)(uint16_t addr, uint8_t val, void *priv),
void (*outw)(uint16_t addr, uint16_t val), void (*outw)(uint16_t addr, uint16_t val, void *priv),
void (*outl)(uint16_t addr, uint32_t val)); void (*outl)(uint16_t addr, uint32_t val, void *priv),
void *priv);

View file

@ -1,6 +1,7 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "ibm.h" #include "ibm.h"
#include "io.h"
uint8_t europcdat[16]; uint8_t europcdat[16];
struct struct
@ -10,7 +11,7 @@ struct
int addr; int addr;
} europc_rtc; } europc_rtc;
void writejim(uint16_t addr, uint8_t val) void writejim(uint16_t addr, uint8_t val, void *p)
{ {
if ((addr&0xFF0)==0x250) europcdat[addr&0xF]=val; if ((addr&0xFF0)==0x250) europcdat[addr&0xF]=val;
switch (addr) switch (addr)
@ -38,7 +39,7 @@ void writejim(uint16_t addr, uint8_t val)
// printf("Write JIM %04X %02X\n",addr,val); // printf("Write JIM %04X %02X\n",addr,val);
} }
uint8_t readjim(uint16_t addr) uint8_t readjim(uint16_t addr, void *p)
{ {
// printf("Read JIM %04X\n",addr); // printf("Read JIM %04X\n",addr);
switch (addr) switch (addr)
@ -74,5 +75,5 @@ void jim_init()
else viddat=0x10; else viddat=0x10;
europc_rtc.dat[0xB]=viddat; europc_rtc.dat[0xB]=viddat;
europc_rtc.dat[0xD]=viddat; /*Checksum*/ europc_rtc.dat[0xD]=viddat; /*Checksum*/
io_sethandler(0x250, 0x10, readjim, NULL, NULL, writejim, NULL, NULL); io_sethandler(0x250, 0x10, readjim, NULL, NULL, writejim, NULL, NULL, NULL);
} }

View file

@ -248,7 +248,7 @@ void keyboard_process()
continue; continue;
if (!key[c] && scancodes[c].scancodes_break[0] == -1) if (!key[c] && scancodes[c].scancodes_break[0] == -1)
continue; continue;
pclog("Key %02X start\n", c); // pclog("Key %02X start\n", c);
d = 0; d = 0;
if (key[c]) if (key[c])
{ {

View file

@ -1,6 +1,7 @@
#include "ibm.h" #include "ibm.h"
#include "io.h" #include "io.h"
#include "mem.h" #include "mem.h"
#include "pic.h"
#include "sound.h" #include "sound.h"
#include "keyboard.h" #include "keyboard.h"
@ -53,7 +54,7 @@ void keyboard_amstrad_adddata(uint8_t val)
return; return;
} }
void keyboard_amstrad_write(uint16_t port, uint8_t val) void keyboard_amstrad_write(uint16_t port, uint8_t val, void *priv)
{ {
pclog("keyboard_amstrad : write %04X %02X %02X\n", port, val, keyboard_amstrad.pb); pclog("keyboard_amstrad : write %04X %02X %02X\n", port, val, keyboard_amstrad.pb);
/* if (ram[8] == 0xc3) /* if (ram[8] == 0xc3)
@ -102,7 +103,7 @@ void keyboard_amstrad_write(uint16_t port, uint8_t val)
} }
} }
uint8_t keyboard_amstrad_read(uint16_t port) uint8_t keyboard_amstrad_read(uint16_t port, void *priv)
{ {
uint8_t temp; uint8_t temp;
// pclog("keyboard_amstrad : read %04X ", port); // pclog("keyboard_amstrad : read %04X ", port);
@ -161,7 +162,7 @@ void keyboard_amstrad_init()
{ {
//return; //return;
pclog("keyboard_amstrad_init\n"); pclog("keyboard_amstrad_init\n");
io_sethandler(0x0060, 0x0006, keyboard_amstrad_read, NULL, NULL, keyboard_amstrad_write, NULL, NULL); io_sethandler(0x0060, 0x0006, keyboard_amstrad_read, NULL, NULL, keyboard_amstrad_write, NULL, NULL, NULL);
keyboard_amstrad_reset(); keyboard_amstrad_reset();
keyboard_send = keyboard_amstrad_adddata; keyboard_send = keyboard_amstrad_adddata;
keyboard_poll = keyboard_amstrad_poll; keyboard_poll = keyboard_amstrad_poll;

View file

@ -1,7 +1,9 @@
#include "ibm.h" #include "ibm.h"
#include "io.h" #include "io.h"
#include "mem.h" #include "mem.h"
#include "pic.h"
#include "sound.h" #include "sound.h"
#include "timer.h"
#include "keyboard.h" #include "keyboard.h"
#include "keyboard_at.h" #include "keyboard_at.h"
@ -44,22 +46,23 @@ int mouse_queue_start = 0, mouse_queue_end = 0;
void keyboard_at_poll() void keyboard_at_poll()
{ {
keybsenddelay += (1000 * TIMER_USEC);
if (keyboard_at.wantirq) if (keyboard_at.wantirq)
{ {
keyboard_at.wantirq = 0; keyboard_at.wantirq = 0;
picint(2); picint(2);
pclog("keyboard_at : take IRQ\n"); // pclog("keyboard_at : take IRQ\n");
} }
else if (keyboard_at.wantirq12) else if (keyboard_at.wantirq12)
{ {
keyboard_at.wantirq12 = 0; keyboard_at.wantirq12 = 0;
picint(0x1000); picint(0x1000);
pclog("keyboard_at : take IRQ 12\n"); // pclog("keyboard_at : take IRQ 12\n");
} }
if (!(keyboard_at.status & STAT_OFULL) && !(keyboard_at.mem[0] & 0x10) && if (!(keyboard_at.status & STAT_OFULL) && !(keyboard_at.mem[0] & 0x10) &&
mouse_queue_start != mouse_queue_end) mouse_queue_start != mouse_queue_end)
{ {
pclog("Reading %02X from the mouse queue at %i\n", keyboard_at.out, key_queue_start); // pclog("Reading %02X from the mouse queue at %i\n", keyboard_at.out, key_queue_start);
keyboard_at.out = mouse_queue[mouse_queue_start]; keyboard_at.out = mouse_queue[mouse_queue_start];
mouse_queue_start = (mouse_queue_start + 1) & 0xf; mouse_queue_start = (mouse_queue_start + 1) & 0xf;
keyboard_at.status |= STAT_OFULL | STAT_MFULL; keyboard_at.status |= STAT_OFULL | STAT_MFULL;
@ -70,7 +73,7 @@ void keyboard_at_poll()
else if (!(keyboard_at.status & STAT_OFULL) && !(keyboard_at.mem[0] & 0x10) && else if (!(keyboard_at.status & STAT_OFULL) && !(keyboard_at.mem[0] & 0x10) &&
key_queue_start != key_queue_end) key_queue_start != key_queue_end)
{ {
pclog("Reading %02X from the key queue at %i\n", keyboard_at.out, key_queue_start); // pclog("Reading %02X from the key queue at %i\n", keyboard_at.out, key_queue_start);
keyboard_at.out = key_queue[key_queue_start]; keyboard_at.out = key_queue[key_queue_start];
key_queue_start = (key_queue_start + 1) & 0xf; key_queue_start = (key_queue_start + 1) & 0xf;
keyboard_at.status |= STAT_OFULL; keyboard_at.status |= STAT_OFULL;
@ -81,7 +84,7 @@ void keyboard_at_poll()
else if (!(keyboard_at.status & STAT_OFULL) && else if (!(keyboard_at.status & STAT_OFULL) &&
key_ctrl_queue_start != key_ctrl_queue_end) key_ctrl_queue_start != key_ctrl_queue_end)
{ {
pclog("Reading %02X from the key ctrl_queue at %i\n", keyboard_at.out, key_ctrl_queue_start); // pclog("Reading %02X from the key ctrl_queue at %i\n", keyboard_at.out, key_ctrl_queue_start);
keyboard_at.out = key_ctrl_queue[key_ctrl_queue_start]; keyboard_at.out = key_ctrl_queue[key_ctrl_queue_start];
key_ctrl_queue_start = (key_ctrl_queue_start + 1) & 0xf; key_ctrl_queue_start = (key_ctrl_queue_start + 1) & 0xf;
keyboard_at.status |= STAT_OFULL; keyboard_at.status |= STAT_OFULL;
@ -97,7 +100,7 @@ void keyboard_at_adddata(uint8_t val)
// { // {
key_ctrl_queue[key_ctrl_queue_end] = val; key_ctrl_queue[key_ctrl_queue_end] = val;
key_ctrl_queue_end = (key_ctrl_queue_end + 1) & 0xf; key_ctrl_queue_end = (key_ctrl_queue_end + 1) & 0xf;
pclog("keyboard_at : %02X added to queue\n", val); // pclog("keyboard_at : %02X added to queue\n", val);
/* return; /* return;
} }
keyboard_at.out = val; keyboard_at.out = val;
@ -110,9 +113,15 @@ void keyboard_at_adddata(uint8_t val)
void keyboard_at_adddata_keyboard(uint8_t val) void keyboard_at_adddata_keyboard(uint8_t val)
{ {
/* if (val == 0x1c)
{
key_1c++;
if (key_1c == 4)
output = 3;
}*/
key_queue[key_queue_end] = val; key_queue[key_queue_end] = val;
key_queue_end = (key_queue_end + 1) & 0xf; key_queue_end = (key_queue_end + 1) & 0xf;
pclog("keyboard_at : %02X added to key queue\n", val); // pclog("keyboard_at : %02X added to key queue\n", val);
return; return;
} }
@ -120,13 +129,13 @@ void keyboard_at_adddata_mouse(uint8_t val)
{ {
mouse_queue[mouse_queue_end] = val; mouse_queue[mouse_queue_end] = val;
mouse_queue_end = (mouse_queue_end + 1) & 0xf; mouse_queue_end = (mouse_queue_end + 1) & 0xf;
pclog("keyboard_at : %02X added to mouse queue\n", val); // pclog("keyboard_at : %02X added to mouse queue\n", val);
return; return;
} }
void keyboard_at_write(uint16_t port, uint8_t val) void keyboard_at_write(uint16_t port, uint8_t val, void *priv)
{ {
pclog("keyboard_at : write %04X %02X %i %02X\n", port, val, keyboard_at.key_wantdata, ram[8]); // pclog("keyboard_at : write %04X %02X %i %02X\n", port, val, keyboard_at.key_wantdata, ram[8]);
/* if (ram[8] == 0xc3) /* if (ram[8] == 0xc3)
{ {
output = 3; output = 3;
@ -165,7 +174,7 @@ void keyboard_at_write(uint16_t port, uint8_t val)
break; break;
case 0xd1: /*Write output port*/ case 0xd1: /*Write output port*/
pclog("Write output port - %02X %02X %04X:%04X\n", keyboard_at.output_port, val, CS, pc); // pclog("Write output port - %02X %02X %04X:%04X\n", keyboard_at.output_port, val, CS, pc);
if ((keyboard_at.output_port ^ val) & 0x02) /*A20 enable change*/ if ((keyboard_at.output_port ^ val) & 0x02) /*A20 enable change*/
{ {
mem_a20_key = val & 0x02; mem_a20_key = val & 0x02;
@ -384,7 +393,7 @@ void keyboard_at_write(uint16_t port, uint8_t val)
} }
} }
uint8_t keyboard_at_read(uint16_t port) uint8_t keyboard_at_read(uint16_t port, void *priv)
{ {
uint8_t temp = 0xff; uint8_t temp = 0xff;
cycles -= 4; cycles -= 4;
@ -428,9 +437,11 @@ void keyboard_at_reset()
void keyboard_at_init() void keyboard_at_init()
{ {
//return; //return;
io_sethandler(0x0060, 0x0005, keyboard_at_read, NULL, NULL, keyboard_at_write, NULL, NULL); io_sethandler(0x0060, 0x0005, keyboard_at_read, NULL, NULL, keyboard_at_write, NULL, NULL, NULL);
keyboard_at_reset(); keyboard_at_reset();
keyboard_send = keyboard_at_adddata_keyboard; keyboard_send = keyboard_at_adddata_keyboard;
keyboard_poll = keyboard_at_poll; keyboard_poll = keyboard_at_poll;
mouse_write = NULL; mouse_write = NULL;
timer_add(keyboard_at_poll, &keybsenddelay, TIMER_ALWAYS_ENABLED, NULL);
} }

View file

@ -2,6 +2,7 @@
#include "io.h" #include "io.h"
#include "mem.h" #include "mem.h"
#include "mouse.h" #include "mouse.h"
#include "pic.h"
#include "keyboard.h" #include "keyboard.h"
#include "keyboard_olim24.h" #include "keyboard_olim24.h"
@ -63,7 +64,7 @@ void keyboard_olim24_adddata(uint8_t val)
return; return;
} }
void keyboard_olim24_write(uint16_t port, uint8_t val) void keyboard_olim24_write(uint16_t port, uint8_t val, void *priv)
{ {
pclog("keyboard_olim24 : write %04X %02X\n", port, val); pclog("keyboard_olim24 : write %04X %02X\n", port, val);
/* if (ram[8] == 0xc3) /* if (ram[8] == 0xc3)
@ -138,7 +139,7 @@ void keyboard_olim24_write(uint16_t port, uint8_t val)
} }
} }
uint8_t keyboard_olim24_read(uint16_t port) uint8_t keyboard_olim24_read(uint16_t port, void *priv)
{ {
uint8_t temp; uint8_t temp;
// pclog("keyboard_olim24 : read %04X ", port); // pclog("keyboard_olim24 : read %04X ", port);
@ -276,8 +277,8 @@ void mouse_olim24_poll(int x, int y, int b)
void keyboard_olim24_init() void keyboard_olim24_init()
{ {
//return; //return;
io_sethandler(0x0060, 0x0001, keyboard_olim24_read, NULL, NULL, keyboard_olim24_write, NULL, NULL); io_sethandler(0x0060, 0x0001, keyboard_olim24_read, NULL, NULL, keyboard_olim24_write, NULL, NULL, NULL);
io_sethandler(0x0064, 0x0001, keyboard_olim24_read, NULL, NULL, keyboard_olim24_write, NULL, NULL); io_sethandler(0x0064, 0x0001, keyboard_olim24_read, NULL, NULL, keyboard_olim24_write, NULL, NULL, NULL);
keyboard_olim24_reset(); keyboard_olim24_reset();
keyboard_send = keyboard_olim24_adddata; keyboard_send = keyboard_olim24_adddata;
keyboard_poll = keyboard_olim24_poll; keyboard_poll = keyboard_olim24_poll;

View file

@ -1,7 +1,9 @@
#include "ibm.h" #include "ibm.h"
#include "io.h" #include "io.h"
#include "mem.h" #include "mem.h"
#include "pic.h"
#include "sound.h" #include "sound.h"
#include "timer.h"
#include "keyboard.h" #include "keyboard.h"
#include "keyboard_xt.h" #include "keyboard_xt.h"
@ -28,6 +30,7 @@ static int key_queue_start = 0, key_queue_end = 0;
void keyboard_xt_poll() void keyboard_xt_poll()
{ {
keybsenddelay += (1000 * TIMER_USEC);
if (keyboard_xt.wantirq) if (keyboard_xt.wantirq)
{ {
keyboard_xt.wantirq = 0; keyboard_xt.wantirq = 0;
@ -51,7 +54,7 @@ void keyboard_xt_adddata(uint8_t val)
return; return;
} }
void keyboard_xt_write(uint16_t port, uint8_t val) void keyboard_xt_write(uint16_t port, uint8_t val, void *priv)
{ {
pclog("keyboard_xt : write %04X %02X %02X\n", port, val, keyboard_xt.pb); pclog("keyboard_xt : write %04X %02X %02X\n", port, val, keyboard_xt.pb);
/* if (ram[8] == 0xc3) /* if (ram[8] == 0xc3)
@ -86,10 +89,10 @@ void keyboard_xt_write(uint16_t port, uint8_t val)
} }
} }
uint8_t keyboard_xt_read(uint16_t port) uint8_t keyboard_xt_read(uint16_t port, void *priv)
{ {
uint8_t temp; uint8_t temp;
// pclog("keyboard_xt : read %04X ", port); pclog("keyboard_xt : read %04X ", port);
switch (port) switch (port)
{ {
case 0x60: case 0x60:
@ -142,7 +145,7 @@ uint8_t keyboard_xt_read(uint16_t port)
//dumpregs(); //dumpregs();
//exit(-1); //exit(-1);
} }
// pclog("%02X\n", temp); pclog("%02X\n", temp);
return temp; return temp;
} }
@ -156,8 +159,10 @@ void keyboard_xt_reset()
void keyboard_xt_init() void keyboard_xt_init()
{ {
//return; //return;
io_sethandler(0x0060, 0x0004, keyboard_xt_read, NULL, NULL, keyboard_xt_write, NULL, NULL); io_sethandler(0x0060, 0x0004, keyboard_xt_read, NULL, NULL, keyboard_xt_write, NULL, NULL, NULL);
keyboard_xt_reset(); keyboard_xt_reset();
keyboard_send = keyboard_xt_adddata; keyboard_send = keyboard_xt_adddata;
keyboard_poll = keyboard_xt_poll; keyboard_poll = keyboard_xt_poll;
timer_add(keyboard_xt_poll, &keybsenddelay, TIMER_ALWAYS_ENABLED, NULL);
} }

View file

@ -4,7 +4,7 @@
#include "lpt.h" #include "lpt.h"
static uint8_t lpt1_dat, lpt2_dat; static uint8_t lpt1_dat, lpt2_dat;
void lpt1_write(uint16_t port, uint8_t val) void lpt1_write(uint16_t port, uint8_t val, void *priv)
{ {
switch (port & 3) switch (port & 3)
{ {
@ -17,7 +17,7 @@ void lpt1_write(uint16_t port, uint8_t val)
break; break;
} }
} }
uint8_t lpt1_read(uint16_t port) uint8_t lpt1_read(uint16_t port, void *priv)
{ {
switch (port & 3) switch (port & 3)
{ {
@ -29,7 +29,7 @@ uint8_t lpt1_read(uint16_t port)
return 0xff; return 0xff;
} }
void lpt2_write(uint16_t port, uint8_t val) void lpt2_write(uint16_t port, uint8_t val, void *priv)
{ {
switch (port & 3) switch (port & 3)
{ {
@ -42,7 +42,7 @@ void lpt2_write(uint16_t port, uint8_t val)
break; break;
} }
} }
uint8_t lpt2_read(uint16_t port) uint8_t lpt2_read(uint16_t port, void *priv)
{ {
switch (port & 3) switch (port & 3)
{ {
@ -56,11 +56,32 @@ uint8_t lpt2_read(uint16_t port)
void lpt_init() void lpt_init()
{ {
io_sethandler(0x0278, 0x0003, lpt1_read, NULL, NULL, lpt1_write, NULL, NULL); io_sethandler(0x0278, 0x0003, lpt1_read, NULL, NULL, lpt1_write, NULL, NULL, NULL);
io_sethandler(0x0378, 0x0003, lpt2_read, NULL, NULL, lpt2_write, NULL, NULL); io_sethandler(0x0378, 0x0003, lpt2_read, NULL, NULL, lpt2_write, NULL, NULL, NULL);
} }
void lpt1_init(uint16_t port)
{
io_sethandler(port, 0x0003, lpt1_read, NULL, NULL, lpt1_write, NULL, NULL, NULL);
}
void lpt1_remove()
{
io_removehandler(0x0278, 0x0003, lpt1_read, NULL, NULL, lpt1_write, NULL, NULL, NULL);
io_removehandler(0x0378, 0x0003, lpt1_read, NULL, NULL, lpt1_write, NULL, NULL, NULL);
io_removehandler(0x03bc, 0x0003, lpt1_read, NULL, NULL, lpt1_write, NULL, NULL, NULL);
}
void lpt2_init(uint16_t port)
{
io_sethandler(port, 0x0003, lpt2_read, NULL, NULL, lpt2_write, NULL, NULL, NULL);
}
void lpt2_remove() void lpt2_remove()
{ {
io_removehandler(0x0379, 0x0002, lpt2_read, NULL, NULL, lpt2_write, NULL, NULL); io_removehandler(0x0278, 0x0003, lpt2_read, NULL, NULL, lpt2_write, NULL, NULL, NULL);
io_removehandler(0x0378, 0x0003, lpt2_read, NULL, NULL, lpt2_write, NULL, NULL, NULL);
io_removehandler(0x03bc, 0x0003, lpt2_read, NULL, NULL, lpt2_write, NULL, NULL, NULL);
}
void lpt2_remove_ams()
{
io_removehandler(0x0379, 0x0002, lpt2_read, NULL, NULL, lpt2_write, NULL, NULL, NULL);
} }

View file

@ -1,2 +1,6 @@
void lpt_init(); extern void lpt_init();
void lpt2_remove(); extern void lpt1_init(uint16_t port);
extern void lpt1_remove();
extern void lpt2_init(uint16_t port);
extern void lpt2_remove();
extern void lpt2_remove_ams();

454
src/mem.c
View file

@ -8,17 +8,20 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "ibm.h" #include "ibm.h"
#include "config.h"
#include "mem.h" #include "mem.h"
#include "video.h" #include "video.h"
#include "x86.h" #include "x86.h"
#include "cpu.h" #include "cpu.h"
static uint8_t (*_mem_read_b[0x20000])(uint32_t addr); static uint8_t (*_mem_read_b[0x40000])(uint32_t addr, void *priv);
static uint16_t (*_mem_read_w[0x20000])(uint32_t addr); static uint16_t (*_mem_read_w[0x40000])(uint32_t addr, void *priv);
static uint32_t (*_mem_read_l[0x20000])(uint32_t addr); static uint32_t (*_mem_read_l[0x40000])(uint32_t addr, void *priv);
static void (*_mem_write_b[0x20000])(uint32_t addr, uint8_t val); static void (*_mem_write_b[0x40000])(uint32_t addr, uint8_t val, void *priv);
static void (*_mem_write_w[0x20000])(uint32_t addr, uint16_t val); static void (*_mem_write_w[0x40000])(uint32_t addr, uint16_t val, void *priv);
static void (*_mem_write_l[0x20000])(uint32_t addr, uint32_t val); static void (*_mem_write_l[0x40000])(uint32_t addr, uint32_t val, void *priv);
static void *_mem_priv[0x40000];
int shadowbios,shadowbios_write; int shadowbios,shadowbios_write;
@ -40,14 +43,14 @@ uint8_t romext[32768];
FILE *romfopen(char *fn, char *mode) FILE *romfopen(char *fn, char *mode)
{ {
char s[512]; char s[512];
pclog("romfopen %s\n", fn); // pclog("romfopen %s\n", fn);
strcpy(s,pcempath); strcpy(s,pcempath);
pclog("s = %s\n", s); // pclog("s = %s\n", s);
put_backslash(s); put_backslash(s);
pclog("s = %s\n", s); // pclog("s = %s\n", s);
pclog("strcat %s %s\n", s, fn); // pclog("strcat %s %s\n", s, fn);
strcat(s,fn); strcat(s,fn);
pclog("s = %s\n", s); // pclog("s = %s\n", s);
return fopen(s,mode); return fopen(s,mode);
} }
@ -76,18 +79,14 @@ static void mem_load_atide_bios()
fclose(f); fclose(f);
} }
} }
int loadbios() int mem_load_video_bios()
{ {
FILE *f=NULL,*ff=NULL; FILE *f = NULL;
int c; int c;
switch (gfxcard)
loadfont("mda.rom", 0);
memset(vrom,0x63,0x8000);
// printf("Loadrom - VGA %i\n",VGA);
if (VID_EGA)
{ {
case GFX_EGA:
f=romfopen("roms/ibm_6277356_ega_card_u44_27128.bin","rb"); f=romfopen("roms/ibm_6277356_ega_card_u44_27128.bin","rb");
if (f) if (f)
{ {
@ -101,67 +100,170 @@ int loadbios()
vrom[c]=getc(f); vrom[c]=getc(f);
} }
fclose(f); fclose(f);
return 1;
} }
} break;
if (VGA)
{ case GFX_TVGA:
f=romfopen("roms/trident.bin","rb"); f=romfopen("roms/trident.bin","rb");
if (f) if (f)
{ {
fread(vrom,32768,1,f); fread(vrom,32768,1,f);
fclose(f); fclose(f);
return 1;
} }
} break;
if (ET4000)
{ case GFX_ET4000:
f=romfopen("roms/et4000.bin","rb"); f=romfopen("roms/et4000.bin","rb");
if (f) if (f)
{ {
fread(vrom,32768,1,f); fread(vrom,32768,1,f);
fclose(f); fclose(f);
return 1;
} }
} break;
if (ET4000W32)
{ case GFX_ET4000W32:
f=romfopen("roms/et4000w32.bin","rb"); f=romfopen("roms/et4000w32.bin","rb");
if (f) if (f)
{ {
fread(vrom,32768,1,f); fread(vrom,32768,1,f);
fclose(f); fclose(f);
return 1;
} }
} break;
if (gfxcard == GFX_BAHAMAS64)
{ case GFX_BAHAMAS64:
f=romfopen("roms/bahamas64.bin","rb"); f=romfopen("roms/bahamas64.bin","rb");
if (f) if (f)
{ {
fread(vrom,32768,1,f); fread(vrom,32768,1,f);
fclose(f); fclose(f);
return 1;
} }
} break;
if (gfxcard == GFX_N9_9FX)
{ case GFX_N9_9FX:
f=romfopen("roms/s3_764.bin","rb"); f=romfopen("roms/s3_764.bin","rb");
if (f) if (f)
{ {
fread(vrom,32768,1,f); fread(vrom,32768,1,f);
fclose(f); fclose(f);
return 1;
} }
} break;
if (gfxcard == GFX_STEALTH64)
{ case GFX_STEALTH64:
f=romfopen("roms/TRIO64 (Ver. 1.5-07) [VGA] (S3 Incorporated).bin","rb"); f=romfopen("roms/TRIO64 (Ver. 1.5-07) [VGA] (S3 Incorporated).bin","rb");
if (f) if (f)
{ {
fread(vrom,32768,1,f); fread(vrom,32768,1,f);
fclose(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;
memset(romext,0x63,0x8000); 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;
int c;
loadfont("mda.rom", 0);
biosmask = 0xffff; biosmask = 0xffff;
memset(romext,0x63,0x4000);
pclog("Starting with romset %i\n", romset); pclog("Starting with romset %i\n", romset);
switch (romset) switch (romset)
@ -484,6 +586,17 @@ int loadbios()
//is486=1; //is486=1;
return 1; return 1;
case ROM_430VX:
// f = romfopen("roms/430vx/Ga586atv.bin", "rb");
// f = fopen("roms/430vx/vx29.BIN", "rb");
f = romfopen("roms/430vx/55XWUQ0E.BIN", "rb");
// f=romfopen("roms/430vx/430vx","rb");
if (!f) break;
fread(rom, 0x20000, 1, f);
fclose(f);
biosmask = 0x1ffff;
//is486=1;
return 1;
} }
printf("Failed to load ROM!\n"); printf("Failed to load ROM!\n");
if (f) fclose(f); if (f) fclose(f);
@ -663,20 +776,23 @@ extern uint32_t testr[9];
uint32_t mmutranslatereal(uint32_t addr, int rw) uint32_t mmutranslatereal(uint32_t addr, int rw)
{ {
int mmuout=0;
uint32_t addr2; uint32_t addr2;
uint32_t temp,temp2,temp3; uint32_t temp,temp2,temp3;
if (abrt) return -1; if (abrt)
{
// pclog("Translate recursive abort\n");
return -1;
}
/* if ((addr&~0xFFFFF)==0x77f00000) pclog("Do translate %08X %i %08X %08X\n",addr,rw,EAX,pc); /* if ((addr&~0xFFFFF)==0x77f00000) pclog("Do translate %08X %i %08X %08X\n",addr,rw,EAX,pc);
if (addr==0x77f61000) output = 3; if (addr==0x77f61000) output = 3;
if (addr==0x77f62000) { dumpregs(); exit(-1); } if (addr==0x77f62000) { dumpregs(); exit(-1); }
if (addr==0x77f9a000) { dumpregs(); exit(-1); }*/ if (addr==0x77f9a000) { dumpregs(); exit(-1); }*/
addr2=(cr3+((addr>>20)&0xFFC)); addr2=(cr3+((addr>>20)&0xFFC));
temp=temp2=((uint32_t *)ram)[addr2>>2]; temp=temp2=((uint32_t *)ram)[addr2>>2];
// pclog("Do translate %08X %i %08X\n", addr, rw, temp); // if (output == 3) pclog("Do translate %08X %i %08X\n", addr, rw, temp);
if (!(temp&1))// || (CPL==3 && !(temp&4) && !cpl_override) || (rw && !(temp&2) && (CPL==3 || cr0&WP_FLAG))) if (!(temp&1))// || (CPL==3 && !(temp&4) && !cpl_override) || (rw && !(temp&2) && (CPL==3 || cr0&WP_FLAG)))
{ {
// if (/*output==3 && */!nopageerrors) pclog("Section not present! %08X %08X %02X %04X:%08X %i %i\n",addr,temp,opcode,CS,pc,CPL,rw); // /*if (!nopageerrors && opcode != 0xf3 && opcode != 0x89) */pclog("Section not present! %08X %08X %02X %04X:%08X %i %i\n",addr,temp,opcode,CS,pc,CPL,rw);
cr2=addr; cr2=addr;
temp&=1; temp&=1;
@ -693,13 +809,16 @@ uint32_t mmutranslatereal(uint32_t addr, int rw)
} }
temp=((uint32_t *)ram)[((temp&~0xFFF)+((addr>>10)&0xFFC))>>2]; temp=((uint32_t *)ram)[((temp&~0xFFF)+((addr>>10)&0xFFC))>>2];
temp3=temp&temp2; temp3=temp&temp2;
// pclog("Do translate %08X %08X\n", temp, temp3); // if (output == 3) pclog("Do translate %08X %08X\n", temp, temp3);
if (!(temp&1) || (CPL==3 && !(temp3&4) && !cpl_override) || (rw && !(temp3&2) && (CPL==3 || cr0&WP_FLAG))) if (!(temp&1) || (CPL==3 && !(temp3&4) && !cpl_override) || (rw && !(temp3&2) && (CPL==3 || cr0&WP_FLAG)))
{ {
// if (!nopageerrors) pclog("Page not present! %08X %08X %02X %02X %04X:%08X %04X:%08X %i %i %i\n",addr,temp,opcode,opcode2,CS,pc,SS,ESP,ins,CPL,rw); // /*if (!nopageerrors && opcode != 0xf3 && opcode != 0x89) */pclog("Page not present! %08X %08X %02X %02X %i %08X %04X:%08X %04X:%08X %i %i %i\n",addr,temp,opcode,opcode2,frame,rmdat32, CS,pc,SS,ESP,ins,CPL,rw);
// dumpregs();
// exit(-1);
// if (addr == 0x815F6E90) output = 3; // if (addr == 0x815F6E90) output = 3;
/* if (addr == 0x10ADE020) output = 3; /* if (addr == 0x10ADE020) output = 3;*/
if (addr == 0x10000008) /* if (addr == 0x10150010 && !nopageerrors)
{ {
dumpregs(); dumpregs();
exit(-1); exit(-1);
@ -816,7 +935,7 @@ uint8_t *getpccache(uint32_t a)
{ {
// int logit=(a>0xFFFFF); // int logit=(a>0xFFFFF);
uint32_t a2=a; uint32_t a2=a;
if (readlookup2[a>>12]!=0xFFFFFFFF) return &ram[(uint8_t *)readlookup2[a>>12] - (uint8_t *)(a&~0xFFF)]; //if (readlookup2[a>>12]!=0xFFFFFFFF) return &ram[(uint8_t *)readlookup2[a>>12] - (uint8_t *)(a&~0xFFF)];
if (cr0>>31) if (cr0>>31)
{ {
// if (output==3) pclog("Translate GetPCCache %08X\n",a); // if (output==3) pclog("Translate GetPCCache %08X\n",a);
@ -870,12 +989,8 @@ uint8_t readmembl(uint32_t addr)
} }
addr &= rammask; addr &= rammask;
switch (addr>>16) if (_mem_read_b[addr >> 14]) return _mem_read_b[addr >> 14](addr, _mem_priv[addr >> 14]);
{ // pclog("Bad readmembl %08X %04X:%08X\n", addr, CS, pc);
case 13: if (romset==ROM_AMI286) return neat_readems(addr); return 0xFF;
// case 14: pclog("Read %06X\n", addr); if (shadowbios) { /*printf("Read shadow RAM %08X %02X\n",addr,ram[addr]);*/ return ram[addr]; }
}
if (_mem_read_b[addr >> 15]) return _mem_read_b[addr >> 15](addr);
return 0xFF; return 0xFF;
} }
@ -890,15 +1005,8 @@ void writemembl(uint32_t addr, uint8_t val)
} }
addr &= rammask; addr &= rammask;
switch (addr>>16) 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);
case 13: if (romset==ROM_AMI286) neat_writeems(addr,val); return;
// case 14: printf("Write %08X %02X\n",addr,val); //ram[addr]=val;
// if (isram[(addr>>16)&0xFF]) ram[addr]=val;
// return;
}
if (_mem_write_b[addr >> 15]) _mem_write_b[addr >> 15](addr, val);
// else pclog("Bad write %08X %02X\n", addr, val);
} }
uint8_t readmemb386l(uint32_t seg, uint32_t addr) uint8_t readmemb386l(uint32_t seg, uint32_t addr)
@ -910,10 +1018,10 @@ uint8_t readmemb386l(uint32_t seg, uint32_t addr)
return -1; return -1;
} }
mem_logical_addr = addr = addr + seg; mem_logical_addr = addr = addr + seg;
if (readlookup2[mem_logical_addr >> 12] != 0xFFFFFFFF) /* if (readlookup2[mem_logical_addr >> 12] != 0xFFFFFFFF)
{ {
return ram[readlookup2[mem_logical_addr >> 12] + (mem_logical_addr & 0xFFF)]; return ram[readlookup2[mem_logical_addr >> 12] + (mem_logical_addr & 0xFFF)];
} }*/
if (cr0 >> 31) if (cr0 >> 31)
{ {
@ -923,7 +1031,8 @@ uint8_t readmemb386l(uint32_t seg, uint32_t addr)
addr &= rammask; addr &= rammask;
if (_mem_read_b[addr >> 15]) return _mem_read_b[addr >> 15](addr); if (_mem_read_b[addr >> 14]) return _mem_read_b[addr >> 14](addr, _mem_priv[addr >> 14]);
// pclog("Bad readmemb386l %08X %04X:%08X\n", addr, CS, pc);
return 0xFF; return 0xFF;
} }
@ -945,8 +1054,11 @@ void writememb386l(uint32_t seg, uint32_t addr, uint8_t val)
addr &= rammask; addr &= rammask;
if (_mem_write_b[addr >> 15]) _mem_write_b[addr >> 15](addr, val); /* if (addr >= 0xa0000 && addr < 0xc0000)
// else pclog("Bad write %08X %02X\n", addr, val); 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);
} }
uint16_t readmemwl(uint32_t seg, uint32_t addr) uint16_t readmemwl(uint32_t seg, uint32_t addr)
@ -956,8 +1068,8 @@ uint16_t readmemwl(uint32_t seg, uint32_t addr)
{ {
if (cr0>>31) if (cr0>>31)
{ {
if (mmutranslate(addr2, 0) == 0xffffffff) return; if (mmutranslate(addr2, 0) == 0xffffffff) return 0xffff;
if (mmutranslate(addr2+1, 0) == 0xffffffff) return; if (mmutranslate(addr2+1, 0) == 0xffffffff) return 0xffff;
} }
if (is386) return readmemb386l(seg,addr)|(readmemb386l(seg,addr+1)<<8); if (is386) return readmemb386l(seg,addr)|(readmemb386l(seg,addr+1)<<8);
else return readmembl(seg+addr)|(readmembl(seg+addr+1)<<8); else return readmembl(seg+addr)|(readmembl(seg+addr+1)<<8);
@ -976,12 +1088,12 @@ uint16_t readmemwl(uint32_t seg, uint32_t addr)
addr2 &= rammask; addr2 &= rammask;
if (_mem_read_w[addr2 >> 15]) return _mem_read_w[addr2 >> 15](addr2); if (_mem_read_w[addr2 >> 14]) return _mem_read_w[addr2 >> 14](addr2, _mem_priv[addr2 >> 14]);
if (_mem_read_b[addr2 >> 15]) if (_mem_read_b[addr2 >> 14])
{ {
if (AT) return _mem_read_b[addr2 >> 15](addr2) | (_mem_read_b[(addr2 + 1) >> 15](addr2 + 1) << 8); 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 >> 15](addr2) | (_mem_read_b[(seg + ((addr + 1) & 0xffff)) >> 15](seg + ((addr + 1) & 0xffff)) << 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);
} }
return 0xffff; return 0xffff;
} }
@ -1022,19 +1134,20 @@ void writememwl(uint32_t seg, uint32_t addr, uint16_t val)
} }
addr2 &= rammask; addr2 &= rammask;
/* if (addr2 >= 0xa0000 && addr2 < 0xc0000)
pclog("writememwl %08X %02X\n", addr2, val);*/
if (_mem_write_w[addr2 >> 15]) if (_mem_write_w[addr2 >> 14])
{ {
_mem_write_w[addr2 >> 15](addr2, val); _mem_write_w[addr2 >> 14](addr2, val, _mem_priv[addr2 >> 14]);
return; return;
} }
if (_mem_write_b[addr2 >> 15]) if (_mem_write_b[addr2 >> 14])
{ {
_mem_write_b[addr2 >> 15](addr2, val); _mem_write_b[addr2 >> 14](addr2, val, _mem_priv[addr2 >> 14]);
_mem_write_b[(addr2 + 1) >> 15](addr2 + 1, val >> 8); _mem_write_b[(addr2 + 1) >> 14](addr2 + 1, val >> 8, _mem_priv[addr2 >> 14]);
// if (AT) _
// else _mem_write_b[(seg + ((addr + 1) & 0xffff)) >> 15](seg + ((addr + 1) & 0xffff), val >> 8);
return; return;
} }
// pclog("Bad write %08X %04X\n", addr, val); // pclog("Bad write %08X %04X\n", addr, val);
@ -1047,8 +1160,8 @@ uint32_t readmemll(uint32_t seg, uint32_t addr)
{ {
if (cr0>>31) if (cr0>>31)
{ {
if (mmutranslate(addr2, 0) == 0xffffffff) return; if (mmutranslate(addr2, 0) == 0xffffffff) return 0xffffffff;
if (mmutranslate(addr2+3, 0) == 0xffffffff) return; if (mmutranslate(addr2+3, 0) == 0xffffffff) return 0xffffffff;
} }
return readmemwl(seg,addr)|(readmemwl(seg,addr+2)<<16); return readmemwl(seg,addr)|(readmemwl(seg,addr+2)<<16);
} }
@ -1068,11 +1181,11 @@ uint32_t readmemll(uint32_t seg, uint32_t addr)
addr2&=rammask; addr2&=rammask;
if (_mem_read_l[addr2 >> 15]) return _mem_read_l[addr2 >> 15](addr2); if (_mem_read_l[addr2 >> 14]) return _mem_read_l[addr2 >> 14](addr2, _mem_priv[addr2 >> 14]);
if (_mem_read_w[addr2 >> 15]) return _mem_read_w[addr2 >> 15](addr2) | (_mem_read_w[addr2 >> 15](addr2 + 2) << 16); 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_b[addr2 >> 15]) return _mem_read_b[addr2 >> 15](addr2) | (_mem_read_b[addr2 >> 15](addr2 + 1) << 8) | (_mem_read_b[addr2 >> 15](addr2 + 2) << 16) | (_mem_read_b[addr2 >> 15](addr2 + 3) << 24); 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);
return 0xffffffff; return 0xffffffff;
} }
@ -1106,67 +1219,70 @@ void writememll(uint32_t seg, uint32_t addr, uint32_t val)
addr2&=rammask; addr2&=rammask;
if (_mem_write_l[addr2 >> 15]) /* if (addr >= 0xa0000 && addr < 0xc0000)
pclog("writememll %08X %08X\n", addr, val);*/
if (_mem_write_l[addr2 >> 14])
{ {
_mem_write_l[addr2 >> 15](addr2, val); _mem_write_l[addr2 >> 14](addr2, val, _mem_priv[addr2 >> 14]);
return; return;
} }
if (_mem_write_w[addr2 >> 15]) if (_mem_write_w[addr2 >> 14])
{ {
_mem_write_w[addr2 >> 15](addr2, val); _mem_write_w[addr2 >> 14](addr2, val, _mem_priv[addr2 >> 14]);
_mem_write_w[addr2 >> 15](addr2 + 2, val >> 16); _mem_write_w[addr2 >> 14](addr2 + 2, val >> 16, _mem_priv[addr2 >> 14]);
return; return;
} }
if (_mem_write_b[addr2 >> 15]) if (_mem_write_b[addr2 >> 14])
{ {
_mem_write_b[addr2 >> 15](addr2, val); _mem_write_b[addr2 >> 14](addr2, val, _mem_priv[addr2 >> 14]);
_mem_write_b[addr2 >> 15](addr2 + 1, val >> 8); _mem_write_b[addr2 >> 14](addr2 + 1, val >> 8, _mem_priv[addr2 >> 14]);
_mem_write_b[addr2 >> 15](addr2 + 2, val >> 16); _mem_write_b[addr2 >> 14](addr2 + 2, val >> 16, _mem_priv[addr2 >> 14]);
_mem_write_b[addr2 >> 15](addr2 + 3, val >> 24); _mem_write_b[addr2 >> 14](addr2 + 3, val >> 24, _mem_priv[addr2 >> 14]);
return; return;
} }
// pclog("Bad write %08X %08X\n", addr, val); // pclog("Bad write %08X %08X\n", addr, val);
} }
uint8_t mem_read_ram(uint32_t addr) uint8_t mem_read_ram(uint32_t addr, void *priv)
{ {
// if (addr < 0xa0000) pclog("Read RAMb %08X\n", addr); // if (addr >= 0xe0000 && addr < 0x100000) pclog("Read RAMb %08X\n", addr);
addreadlookup(mem_logical_addr, addr); addreadlookup(mem_logical_addr, addr);
return ram[addr]; return ram[addr];
} }
uint16_t mem_read_ramw(uint32_t addr) uint16_t mem_read_ramw(uint32_t addr, void *priv)
{ {
// if (addr < 0xa0000) pclog("Read RAMw %08X\n", addr); // if (addr >= 0xe0000 && addr < 0x100000) pclog("Read RAMw %08X\n", addr);
addreadlookup(mem_logical_addr, addr); addreadlookup(mem_logical_addr, addr);
return *(uint16_t *)&ram[addr]; return *(uint16_t *)&ram[addr];
} }
uint32_t mem_read_raml(uint32_t addr) uint32_t mem_read_raml(uint32_t addr, void *priv)
{ {
// if (addr < 0xa0000) pclog("Read RAMl %08X\n", addr); // if (addr >= 0xe0000 && addr < 0x100000) pclog("Read RAMl %08X\n", addr);
addreadlookup(mem_logical_addr, addr); addreadlookup(mem_logical_addr, addr);
return *(uint32_t *)&ram[addr]; return *(uint32_t *)&ram[addr];
} }
void mem_write_ram(uint32_t addr, uint8_t val) void mem_write_ram(uint32_t addr, uint8_t val, void *priv)
{ {
addwritelookup(mem_logical_addr, addr); addwritelookup(mem_logical_addr, addr);
ram[addr] = val; ram[addr] = val;
// if (addr >= 0xe0000 && addr < 0x100000) pclog("Write RAMb %08X\n", addr); // if (addr >= 0xe0000 && addr < 0x100000) pclog("Write RAMb %08X\n", addr);
} }
void mem_write_ramw(uint32_t addr, uint16_t val) void mem_write_ramw(uint32_t addr, uint16_t val, void *priv)
{ {
addwritelookup(mem_logical_addr, addr); addwritelookup(mem_logical_addr, addr);
*(uint16_t *)&ram[addr] = val; *(uint16_t *)&ram[addr] = val;
// if (addr >= 0xe0000 && addr < 0x100000) pclog("Write RAMw %08X %04X:%04X\n", addr, CS, pc); // 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);
} }
void mem_write_raml(uint32_t addr, uint32_t val) void mem_write_raml(uint32_t addr, uint32_t val, void *priv)
{ {
addwritelookup(mem_logical_addr, addr); addwritelookup(mem_logical_addr, addr);
*(uint32_t *)&ram[addr] = val; *(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 >= 0xe0000 && addr < 0x100000) 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) uint8_t mem_read_bios(uint32_t addr, void *priv)
{ {
if (AMIBIOS && (addr&0xFFFFF)==0xF8281) /*This is read constantly during AMIBIOS POST, but is never written to. It's clearly a status register of some kind, but for what?*/ if (AMIBIOS && (addr&0xFFFFF)==0xF8281) /*This is read constantly during AMIBIOS POST, but is never written to. It's clearly a status register of some kind, but for what?*/
{ {
@ -1177,39 +1293,39 @@ uint8_t mem_read_bios(uint32_t addr)
// if (output) pclog("Read BIOS %08X %02X %04X:%04X\n", addr, rom[addr & biosmask], CS, pc); // if (output) pclog("Read BIOS %08X %02X %04X:%04X\n", addr, rom[addr & biosmask], CS, pc);
return rom[addr & biosmask]; return rom[addr & biosmask];
} }
uint16_t mem_read_biosw(uint32_t addr) uint16_t mem_read_biosw(uint32_t addr, void *priv)
{ {
// if (output) pclog("Read BIOS %08X %04X %04X:%04X\n", addr, *(uint16_t *)&rom[addr & biosmask], CS, pc); // /*if (output) */pclog("Read BIOS %08X %04X %04X:%04X\n", addr, *(uint16_t *)&rom[addr & biosmask], CS, pc);
return *(uint16_t *)&rom[addr & biosmask]; return *(uint16_t *)&rom[addr & biosmask];
} }
uint32_t mem_read_biosl(uint32_t addr) uint32_t mem_read_biosl(uint32_t addr, void *priv)
{ {
// if (output) pclog("Read BIOS %08X %02X %04X:%04X\n", addr, *(uint32_t *)&rom[addr & biosmask], CS, pc); // pclog("Read BIOS %08X %02X %04X:%04X\n", addr, *(uint32_t *)&rom[addr & biosmask], CS, pc);
return *(uint32_t *)&rom[addr & biosmask]; return *(uint32_t *)&rom[addr & biosmask];
} }
uint8_t mem_read_vrom(uint32_t addr) uint8_t mem_read_vrom(uint32_t addr, void *priv)
{ {
return vrom[addr & 0x7fff]; return vrom[addr & 0x7fff];
} }
uint16_t mem_read_vromw(uint32_t addr) uint16_t mem_read_vromw(uint32_t addr, void *priv)
{ {
return *(uint16_t *)&vrom[addr & 0x7fff]; return *(uint16_t *)&vrom[addr & 0x7fff];
} }
uint32_t mem_read_vroml(uint32_t addr) uint32_t mem_read_vroml(uint32_t addr, void *priv)
{ {
return *(uint32_t *)&vrom[addr & 0x7fff]; return *(uint32_t *)&vrom[addr & 0x7fff];
} }
uint8_t mem_read_romext(uint32_t addr) uint8_t mem_read_romext(uint32_t addr, void *priv)
{ {
return romext[addr & 0x7fff]; return romext[addr & 0x7fff];
} }
uint16_t mem_read_romextw(uint32_t addr) uint16_t mem_read_romextw(uint32_t addr, void *priv)
{ {
return *(uint16_t *)&romext[addr & 0x7fff]; return *(uint16_t *)&romext[addr & 0x7fff];
} }
uint32_t mem_read_romextl(uint32_t addr) uint32_t mem_read_romextl(uint32_t addr, void *priv)
{ {
return *(uint32_t *)&romext[addr & 0x7fff]; return *(uint32_t *)&romext[addr & 0x7fff];
} }
@ -1233,16 +1349,16 @@ void mem_init()
isram[c]=1; isram[c]=1;
if (c >= 0xa && c<=0xF) isram[c]=0; if (c >= 0xa && c<=0xF) isram[c]=0;
} }
for (c = 0; c < 0x20000; c++) for (c = 0; c < 0x40000; c++)
_mem_read_b[c] = _mem_read_w[c] = _mem_read_l[c] = _mem_write_b[c] = _mem_write_w[c] = _mem_write_l[c] = NULL; _mem_read_b[c] = _mem_read_w[c] = _mem_read_l[c] = _mem_write_b[c] = _mem_write_w[c] = _mem_write_l[c] = _mem_priv[c] = NULL;
mem_sethandler(0x00000, 0xa0000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml); mem_sethandler(0x00000, 0xa0000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, NULL);
if (mem_size > 1) if (mem_size > 1)
mem_sethandler(0x100000, (mem_size - 1) * 1024 * 1024, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml); mem_sethandler(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_sethandler(0xc0000, 0x08000, mem_read_vrom, mem_read_vromw, mem_read_vroml, NULL, NULL, NULL); mem_sethandler(0xc0000, 0x08000, mem_read_vrom, mem_read_vromw, mem_read_vroml, NULL, NULL, NULL, NULL);
mem_sethandler(0xc8000, 0x08000, mem_read_romext, mem_read_romextw, mem_read_romextl, NULL, NULL, NULL); mem_sethandler(0xc8000, 0x08000, mem_read_romext, mem_read_romextw, mem_read_romextl, NULL, NULL, NULL, NULL);
mem_sethandler(0xe0000, 0x20000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml); mem_sethandler(0xe0000, 0x20000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml, NULL);
// pclog("Mem resize %i %i\n",mem_size,c); // pclog("Mem resize %i %i\n",mem_size,c);
} }
@ -1258,16 +1374,16 @@ void mem_resize()
isram[c]=1; isram[c]=1;
if (c >= 0xa && c<=0xF) isram[c]=0; if (c >= 0xa && c<=0xF) isram[c]=0;
} }
for (c = 0; c < 0x20000; c++) for (c = 0; c < 0x40000; c++)
_mem_read_b[c] = _mem_read_w[c] = _mem_read_l[c] = _mem_write_b[c] = _mem_write_w[c] = _mem_write_l[c] = NULL; _mem_read_b[c] = _mem_read_w[c] = _mem_read_l[c] = _mem_write_b[c] = _mem_write_w[c] = _mem_write_l[c] = _mem_priv[c] = NULL;
mem_sethandler(0x00000, 0xa0000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml); mem_sethandler(0x00000, 0xa0000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, NULL);
if (mem_size > 1) if (mem_size > 1)
mem_sethandler(0x100000, (mem_size - 1) * 1024 * 1024, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml); mem_sethandler(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_sethandler(0xc0000, 0x8000, mem_read_vrom, mem_read_vromw, mem_read_vroml, NULL, NULL, NULL); mem_sethandler(0xc0000, 0x8000, mem_read_vrom, mem_read_vromw, mem_read_vroml, NULL, NULL, NULL, NULL);
mem_sethandler(0xc8000, 0x8000, mem_read_romext, mem_read_romextw, mem_read_romextl, NULL, NULL, NULL); mem_sethandler(0xc8000, 0x8000, mem_read_romext, mem_read_romextw, mem_read_romextl, NULL, NULL, NULL, NULL);
mem_sethandler(0xe0000, 0x20000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml); mem_sethandler(0xe0000, 0x20000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml, NULL);
// pclog("Mem resize %i %i\n",mem_size,c); // pclog("Mem resize %i %i\n",mem_size,c);
} }
@ -1295,44 +1411,62 @@ void mem_updatecache()
} }
void mem_sethandler(uint32_t base, uint32_t size, void mem_sethandler(uint32_t base, uint32_t size,
uint8_t (*read_b)(uint32_t addr), uint8_t (*read_b)(uint32_t addr, void *priv),
uint16_t (*read_w)(uint32_t addr), uint16_t (*read_w)(uint32_t addr, void *priv),
uint32_t (*read_l)(uint32_t addr), uint32_t (*read_l)(uint32_t addr, void *priv),
void (*write_b)(uint32_t addr, uint8_t val), void (*write_b)(uint32_t addr, uint8_t val, void *priv),
void (*write_w)(uint32_t addr, uint16_t val), void (*write_w)(uint32_t addr, uint16_t val, void *priv),
void (*write_l)(uint32_t addr, uint32_t val)) void (*write_l)(uint32_t addr, uint32_t val, void *priv),
void *priv)
{ {
uint32_t c; uint32_t c;
for (c = base; c < base + size; c += 0x8000) // printf("mem_sethandler : %05X %04X %08X %08X %08X %08X %08X\n", base, size, read_w, write_w, mem_read_biosw, mem_read_ramw, mem_write_ramw);
for (c = base; c < base + size; c += 0x4000)
{ {
_mem_read_b[ c >> 15] = read_b; _mem_read_b[ c >> 14] = read_b;
_mem_read_w[ c >> 15] = read_w; _mem_read_w[ c >> 14] = read_w;
_mem_read_l[ c >> 15] = read_l; _mem_read_l[ c >> 14] = read_l;
_mem_write_b[c >> 15] = write_b; _mem_write_b[c >> 14] = write_b;
_mem_write_w[c >> 15] = write_w; _mem_write_w[c >> 14] = write_w;
_mem_write_l[c >> 15] = write_l; _mem_write_l[c >> 14] = write_l;
_mem_priv[c >> 14] = priv;
}
for (c = base; c < base + size; c += 0x1000)
{
readlookup2[c >> 12] = 0xFFFFFFFF;
writelookup2[c >> 12] = 0xFFFFFFFF;
} }
} }
void mem_removehandler(uint32_t base, uint32_t size, void mem_removehandler(uint32_t base, uint32_t size,
uint8_t (*read_b)(uint32_t addr), uint8_t (*read_b)(uint32_t addr, void *priv),
uint16_t (*read_w)(uint32_t addr), uint16_t (*read_w)(uint32_t addr, void *priv),
uint32_t (*read_l)(uint32_t addr), uint32_t (*read_l)(uint32_t addr, void *priv),
void (*write_b)(uint32_t addr, uint8_t val), void (*write_b)(uint32_t addr, uint8_t val, void *priv),
void (*write_w)(uint32_t addr, uint16_t val), void (*write_w)(uint32_t addr, uint16_t val, void *priv),
void (*write_l)(uint32_t addr, uint32_t val)) void (*write_l)(uint32_t addr, uint32_t val, void *priv),
void *priv)
{ {
uint32_t c; uint32_t c;
if ((base + size) > 0xffff8000) if ((base + size) > 0xffff8000)
size = 0xffff0000 - base; size = 0xffff0000 - base;
for (c = base; c < base + size; c += 0x8000) for (c = base; c < base + size; c += 0x4000)
{ {
if ( _mem_read_b[c >> 15] == read_b) _mem_read_b[c >> 15] = NULL; if (_mem_priv[c >> 14] == priv)
if ( _mem_read_w[c >> 15] == read_w) _mem_read_w[c >> 15] = NULL; {
if ( _mem_read_l[c >> 15] == read_l) _mem_read_l[c >> 15] = NULL; if ( _mem_read_b[c >> 14] == read_b) _mem_read_b[c >> 14] = NULL;
if (_mem_write_b[c >> 15] == write_b) _mem_write_b[c >> 15] = NULL; if ( _mem_read_w[c >> 14] == read_w) _mem_read_w[c >> 14] = NULL;
if (_mem_write_w[c >> 15] == write_w) _mem_write_w[c >> 15] = NULL; if ( _mem_read_l[c >> 14] == read_l) _mem_read_l[c >> 14] = NULL;
if (_mem_write_l[c >> 15] == write_l) _mem_write_l[c >> 15] = NULL; if (_mem_write_b[c >> 14] == write_b) _mem_write_b[c >> 14] = NULL;
if (_mem_write_w[c >> 14] == write_w) _mem_write_w[c >> 14] = NULL;
if (_mem_write_l[c >> 14] == write_l) _mem_write_l[c >> 14] = NULL;
_mem_priv[c >> 14] = NULL;
}
}
for (c = base; c < base + size; c += 0x1000)
{
readlookup2[c >> 12] = 0xFFFFFFFF;
writelookup2[c >> 12] = 0xFFFFFFFF;
} }
} }
@ -1342,7 +1476,7 @@ static int mem_a20_state = 0;
void mem_a20_recalc() void mem_a20_recalc()
{ {
int state = mem_a20_key | mem_a20_alt; int state = mem_a20_key | mem_a20_alt;
pclog("A20 recalc %i %i\n", state, mem_a20_state); // pclog("A20 recalc %i %i\n", state, mem_a20_state);
if (state && !mem_a20_state) if (state && !mem_a20_state)
{ {
rammask = 0xffffffff; rammask = 0xffffffff;
@ -1353,6 +1487,6 @@ void mem_a20_recalc()
rammask = 0xffefffff; rammask = 0xffefffff;
flushmmucache(); flushmmucache();
} }
pclog("rammask now %08X\n", rammask); // pclog("rammask now %08X\n", rammask);
mem_a20_state = state; mem_a20_state = state;
} }

View file

@ -7,34 +7,38 @@ extern int cache;
extern int memwaitstate; extern int memwaitstate;
void mem_sethandler(uint32_t base, uint32_t size, void mem_sethandler(uint32_t base, uint32_t size,
uint8_t (*read_b)(uint32_t addr), uint8_t (*read_b)(uint32_t addr, void *priv),
uint16_t (*read_w)(uint32_t addr), uint16_t (*read_w)(uint32_t addr, void *priv),
uint32_t (*read_l)(uint32_t addr), uint32_t (*read_l)(uint32_t addr, void *priv),
void (*write_b)(uint32_t addr, uint8_t val), void (*write_b)(uint32_t addr, uint8_t val, void *priv),
void (*write_w)(uint32_t addr, uint16_t val), void (*write_w)(uint32_t addr, uint16_t val, void *priv),
void (*write_l)(uint32_t addr, uint32_t val)); void (*write_l)(uint32_t addr, uint32_t val, void *priv),
void *priv);
void mem_removehandler(uint32_t base, uint32_t size, void mem_removehandler(uint32_t base, uint32_t size,
uint8_t (*read_b)(uint32_t addr), uint8_t (*read_b)(uint32_t addr, void *priv),
uint16_t (*read_w)(uint32_t addr), uint16_t (*read_w)(uint32_t addr, void *priv),
uint32_t (*read_l)(uint32_t addr), uint32_t (*read_l)(uint32_t addr, void *priv),
void (*write_b)(uint32_t addr, uint8_t val), void (*write_b)(uint32_t addr, uint8_t val, void *priv),
void (*write_w)(uint32_t addr, uint16_t val), void (*write_w)(uint32_t addr, uint16_t val, void *priv),
void (*write_l)(uint32_t addr, uint32_t val)); void (*write_l)(uint32_t addr, uint32_t val, void *priv),
void *priv);
extern int mem_a20_alt; extern int mem_a20_alt;
extern int mem_a20_key; extern int mem_a20_key;
void mem_a20_recalc(); void mem_a20_recalc();
uint8_t mem_read_ram(uint32_t addr); uint8_t mem_read_ram(uint32_t addr, void *priv);
uint16_t mem_read_ramw(uint32_t addr); uint16_t mem_read_ramw(uint32_t addr, void *priv);
uint32_t mem_read_raml(uint32_t addr); uint32_t mem_read_raml(uint32_t addr, void *priv);
void mem_write_ram(uint32_t addr, uint8_t val); void mem_write_ram(uint32_t addr, uint8_t val, void *priv);
void mem_write_ramw(uint32_t addr, uint16_t val); void mem_write_ramw(uint32_t addr, uint16_t val, void *priv);
void mem_write_raml(uint32_t addr, uint32_t val); void mem_write_raml(uint32_t addr, uint32_t val, void *priv);
uint8_t mem_read_bios(uint32_t addr); uint8_t mem_read_bios(uint32_t addr, void *priv);
uint16_t mem_read_biosw(uint32_t addr); uint16_t mem_read_biosw(uint32_t addr, void *priv);
uint32_t mem_read_biosl(uint32_t addr); uint32_t mem_read_biosl(uint32_t addr, void *priv);
FILE *romfopen(char *fn, char *mode); FILE *romfopen(char *fn, char *mode);
int mem_load_video_bios();

View file

@ -6,14 +6,17 @@
#include "acer386sx.h" #include "acer386sx.h"
#include "ali1429.h" #include "ali1429.h"
#include "amstrad.h" #include "amstrad.h"
#include "device.h"
#include "dma.h" #include "dma.h"
#include "fdc.h" #include "fdc.h"
#include "headland.h" #include "headland.h"
#include "i430vx.h"
#include "ide.h" #include "ide.h"
#include "jim.h" #include "jim.h"
#include "keyboard_xt.h" #include "keyboard_amstrad.h"
#include "keyboard_at.h" #include "keyboard_at.h"
#include "keyboard_olim24.h" #include "keyboard_olim24.h"
#include "keyboard_xt.h"
#include "lpt.h" #include "lpt.h"
#include "mouse_ps2.h" #include "mouse_ps2.h"
#include "mouse_serial.h" #include "mouse_serial.h"
@ -22,9 +25,11 @@
#include "olivetti_m24.h" #include "olivetti_m24.h"
#include "pci.h" #include "pci.h"
#include "pic.h" #include "pic.h"
#include "piix.h"
#include "pit.h" #include "pit.h"
#include "psg.h"
#include "serial.h" #include "serial.h"
#include "sound_sn76489.h"
#include "um8669f.h"
#include "um8881f.h" #include "um8881f.h"
#include "wd76c10.h" #include "wd76c10.h"
#include "xtide.h" #include "xtide.h"
@ -41,33 +46,35 @@ void at_wd76c10_init();
void at_ali1429_init(); void at_ali1429_init();
void at_headland_init(); void at_headland_init();
void at_um8881f_init(); void at_um8881f_init();
void at_i430vx_init();
int model; int model;
MODEL models[] = MODEL models[] =
{ {
{"IBM PC", ROM_IBMPC, { "", cpus_8088, "", NULL, "", NULL}, 0, xt_init}, {"IBM PC", ROM_IBMPC, { "", cpus_8088, "", NULL, "", NULL}, 0, xt_init},
{"IBM XT", ROM_IBMXT, { "", cpus_8088, "", NULL, "", NULL}, 0, xt_init}, {"IBM XT", ROM_IBMXT, { "", cpus_8088, "", NULL, "", NULL}, 0, xt_init},
{"Generic XT clone", ROM_GENXT, { "", cpus_8088, "", NULL, "", NULL}, 0, xt_init}, {"Generic XT clone", ROM_GENXT, { "", cpus_8088, "", NULL, "", NULL}, 0, xt_init},
{"DTK XT clone", ROM_DTKXT, { "", cpus_8088, "", NULL, "", NULL}, 0, xt_init}, {"DTK XT clone", ROM_DTKXT, { "", cpus_8088, "", NULL, "", NULL}, 0, xt_init},
{"Tandy 1000", ROM_TANDY, { "", cpus_8088, "", NULL, "", NULL}, 1, tandy1k_init}, {"Tandy 1000", ROM_TANDY, { "", cpus_8088, "", NULL, "", NULL}, 1, tandy1k_init},
{"Amstrad PC1512", ROM_PC1512, { "", cpus_pc1512,"", NULL, "", NULL}, 1, ams_init}, {"Amstrad PC1512", ROM_PC1512, { "", cpus_pc1512, "", NULL, "", NULL}, 1, ams_init},
{"Sinclair PC200", ROM_PC200, { "", cpus_8086, "", NULL, "", NULL}, 1, ams_init}, {"Sinclair PC200", ROM_PC200, { "", cpus_8086, "", NULL, "", NULL}, 1, ams_init},
{"Euro PC", ROM_EUROPC, { "", cpus_8086, "", NULL, "", NULL}, 0, europc_init}, {"Euro PC", ROM_EUROPC, { "", cpus_8086, "", NULL, "", NULL}, 0, europc_init},
{"Olivetti M24", ROM_OLIM24, { "", cpus_8086, "", NULL, "", NULL}, 1, olim24_init}, {"Olivetti M24", ROM_OLIM24, { "", cpus_8086, "", NULL, "", NULL}, 1, olim24_init},
{"Amstrad PC1640", ROM_PC1640, { "", cpus_8086, "", NULL, "", NULL}, 1, ams_init}, {"Amstrad PC1640", ROM_PC1640, { "", cpus_8086, "", NULL, "", NULL}, 1, ams_init},
{"Amstrad PC2086", ROM_PC2086, { "", cpus_8086, "", NULL, "", NULL}, 1, ams_init}, {"Amstrad PC2086", ROM_PC2086, { "", cpus_8086, "", NULL, "", NULL}, 1, ams_init},
{"Amstrad PC3086", ROM_PC3086, { "", cpus_8086, "", NULL, "", NULL}, 1, ams_init}, {"Amstrad PC3086", ROM_PC3086, { "", cpus_8086, "", NULL, "", NULL}, 1, ams_init},
{"IBM AT", ROM_IBMAT, { "", cpus_ibmat, "", NULL, "", NULL}, 0, at_init}, {"IBM AT", ROM_IBMAT, { "", cpus_ibmat, "", NULL, "", NULL}, 0, at_init},
{"Commodore PC 30 III", ROM_CMDPC30, { "", cpus_286, "", NULL, "", NULL}, 0, at_init}, {"Commodore PC 30 III", ROM_CMDPC30, { "", cpus_286, "", NULL, "", NULL}, 0, at_init},
{"AMI 286 clone", ROM_AMI286, { "", cpus_286, "", NULL, "", NULL}, 0, at_neat_init}, {"AMI 286 clone", ROM_AMI286, { "", cpus_286, "", NULL, "", NULL}, 0, at_neat_init},
{"DELL System 200", ROM_DELL200, { "", cpus_286, "", NULL, "", NULL}, 0, at_init}, {"DELL System 200", ROM_DELL200, { "", cpus_286, "", NULL, "", NULL}, 0, at_init},
{"Acer 386SX25/N", ROM_ACER386, { "Intel", cpus_acer, "", NULL, "", NULL}, 1, at_acer386sx_init}, {"Acer 386SX25/N", ROM_ACER386, { "Intel", cpus_acer, "", NULL, "", NULL}, 1, at_acer386sx_init},
{"Amstrad MegaPC", ROM_MEGAPC, { "Intel", cpus_i386, "AMD", cpus_Am386, "Cyrix", cpus_486SDLC}, 1, at_wd76c10_init}, {"Amstrad MegaPC", ROM_MEGAPC, { "Intel", cpus_i386, "AMD", cpus_Am386, "Cyrix", cpus_486SDLC}, 1, at_wd76c10_init},
{"AMI 386 clone", ROM_AMI386, { "Intel", cpus_i386, "AMD", cpus_Am386, "Cyrix", cpus_486SDLC}, 0, at_headland_init}, {"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 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", 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 430VX PCI", ROM_430VX, { "IDT", cpus_WinChip, "", NULL, "", NULL}, 0, at_i430vx_init},
{"", -1, {"", 0, "", 0, "", 0}, 0} {"", -1, {"", 0, "", 0, "", 0}, 0}
}; };
@ -84,7 +91,7 @@ char *model_getname()
void common_init() void common_init()
{ {
dma_init(); dma_init();
fdc_init(); fdc_add();
lpt_init(); lpt_init();
pic_init(); pic_init();
pit_init(); pit_init();
@ -105,7 +112,7 @@ void tandy1k_init()
common_init(); common_init();
keyboard_xt_init(); keyboard_xt_init();
mouse_serial_init(); mouse_serial_init();
psg_init(); device_add(&sn76489_device);
xtide_init(); xtide_init();
} }
@ -191,6 +198,16 @@ void at_um8881f_init()
um8881f_init(); um8881f_init();
} }
void at_i430vx_init()
{
at_init();
mouse_serial_init();
pci_init();
i430vx_init();
piix_init(7);
um8669f_init();
}
void model_init() void model_init()
{ {
pclog("Initting as %s\n", model_getname()); pclog("Initting as %s\n", model_getname());

View file

@ -14,3 +14,7 @@ typedef struct
extern MODEL models[]; extern MODEL models[];
extern int model; extern int model;
int model_getromset();
char *model_getname();
void model_init();

View file

@ -1,6 +1,8 @@
#include "ibm.h" #include "ibm.h"
#include "mouse.h" #include "mouse.h"
#include "pic.h"
#include "serial.h" #include "serial.h"
#include "timer.h"
static int oldb=0; static int oldb=0;
@ -37,11 +39,12 @@ void mouse_serial_poll(int x, int y, int b)
void mouse_serial_rcr() void mouse_serial_rcr()
{ {
mousepos=-1; mousepos=-1;
mousedelay=1000; mousedelay=5000 * (1 << TIMER_SHIFT);
} }
void mousecallback() void mousecallback()
{ {
mousedelay = 0;
if (mousepos == -1) if (mousepos == -1)
{ {
mousepos = 0; mousepos = 0;
@ -62,5 +65,6 @@ void mouse_serial_init()
{ {
mouse_poll = mouse_serial_poll; mouse_poll = mouse_serial_poll;
serial_rcr = mouse_serial_rcr; serial_rcr = mouse_serial_rcr;
timer_add(mousecallback, &mousedelay, &mousedelay, NULL);
} }

View file

@ -7,7 +7,7 @@ static uint8_t neat_regs[256];
static int neat_index; static int neat_index;
static int neat_emspage[4]; static int neat_emspage[4];
void neat_write(uint16_t port, uint8_t val) void neat_write(uint16_t port, uint8_t val, void *priv)
{ {
switch (port) switch (port)
{ {
@ -35,7 +35,7 @@ void neat_write(uint16_t port, uint8_t val)
} }
} }
uint8_t neat_read(uint16_t port) uint8_t neat_read(uint16_t port, void *priv)
{ {
switch (port) switch (port)
{ {
@ -60,9 +60,9 @@ uint8_t neat_readems(uint32_t addr)
void neat_init() void neat_init()
{ {
io_sethandler(0x0022, 0x0002, neat_read, NULL, NULL, neat_write, NULL, NULL); io_sethandler(0x0022, 0x0002, neat_read, NULL, NULL, neat_write, NULL, NULL, NULL);
io_sethandler(0x0208, 0x0002, neat_read, NULL, NULL, neat_write, NULL, NULL); io_sethandler(0x0208, 0x0002, neat_read, NULL, NULL, neat_write, NULL, NULL, NULL);
io_sethandler(0x4208, 0x0002, neat_read, NULL, NULL, neat_write, NULL, NULL); io_sethandler(0x4208, 0x0002, neat_read, NULL, NULL, neat_write, NULL, NULL, NULL);
io_sethandler(0x8208, 0x0002, neat_read, NULL, NULL, neat_write, NULL, NULL); io_sethandler(0x8208, 0x0002, neat_read, NULL, NULL, neat_write, NULL, NULL, NULL);
io_sethandler(0xc208, 0x0002, neat_read, NULL, NULL, neat_write, NULL, NULL); io_sethandler(0xc208, 0x0002, neat_read, NULL, NULL, neat_write, NULL, NULL, NULL);
} }

View file

@ -1,7 +1,10 @@
#include <stdio.h> #include <stdio.h>
#include <windows.h> #include <windows.h>
#include "ibm.h" #include "ibm.h"
#include "io.h"
#include "nvr.h" #include "nvr.h"
#include "pic.h"
#include "timer.h"
int oldromset; int oldromset;
int nvrmask=63; int nvrmask=63;
@ -10,6 +13,8 @@ int nvraddr;
SYSTEMTIME systemtime; SYSTEMTIME systemtime;
int nvr_dosave = 0;
void getnvrtime() void getnvrtime()
{ {
int c,d; int c,d;
@ -51,9 +56,9 @@ void getnvrtime()
void nvr_recalc() void nvr_recalc()
{ {
int c; int c;
float newrtctime; int newrtctime;
c=1<<((nvrram[0xA]&0xF)-1); c=1<<((nvrram[0xA]&0xF)-1);
newrtctime=RTCCONST*(float)c; newrtctime=(int)(RTCCONST * c * (1 << TIMER_SHIFT));
if (rtctime>newrtctime) rtctime=newrtctime; if (rtctime>newrtctime) rtctime=newrtctime;
} }
@ -62,11 +67,11 @@ void nvr_rtc()
int c; int c;
if (!(nvrram[0xA]&0xF)) if (!(nvrram[0xA]&0xF))
{ {
rtctime=99999999; rtctime=0x7fffffff;
return; return;
} }
c=1<<((nvrram[0xA]&0xF)-1); c=1<<((nvrram[0xA]&0xF)-1);
rtctime+=RTCCONST*(float)c; rtctime += (int)(RTCCONST * c * (1 << TIMER_SHIFT));
// pclog("RTCtime now %f\n",rtctime); // pclog("RTCtime now %f\n",rtctime);
nvrram[0xC]=0x40; nvrram[0xC]=0x40;
if (nvrram[0xB]&0x40) if (nvrram[0xB]&0x40)
@ -78,7 +83,7 @@ void nvr_rtc()
} }
} }
void writenvr(uint16_t addr, uint8_t val) void writenvr(uint16_t addr, uint8_t val, void *priv)
{ {
int c; int c;
// printf("Write NVR %03X %02X %02X %04X:%04X %i\n",addr,nvraddr,val,cs>>4,pc,ins); // printf("Write NVR %03X %02X %02X %04X:%04X %i\n",addr,nvraddr,val,cs>>4,pc,ins);
@ -86,7 +91,7 @@ void writenvr(uint16_t addr, uint8_t val)
{ {
// if (nvraddr == 0x33) pclog("NVRWRITE33 %02X %04X:%04X %i\n",val,CS,pc,ins); // if (nvraddr == 0x33) pclog("NVRWRITE33 %02X %04X:%04X %i\n",val,CS,pc,ins);
if (nvraddr >= 0xe && nvrram[nvraddr] != val) if (nvraddr >= 0xe && nvrram[nvraddr] != val)
savenvr(); nvr_dosave = 1;
if (nvraddr!=0xC && nvraddr!=0xD) nvrram[nvraddr]=val; if (nvraddr!=0xC && nvraddr!=0xD) nvrram[nvraddr]=val;
if (nvraddr==0xA) if (nvraddr==0xA)
@ -95,16 +100,16 @@ void writenvr(uint16_t addr, uint8_t val)
if (val&0xF) if (val&0xF)
{ {
c=1<<((val&0xF)-1); c=1<<((val&0xF)-1);
rtctime+=RTCCONST*(float)c; rtctime += (int)(RTCCONST * c * (1 << TIMER_SHIFT));
} }
else else
rtctime=99999999; rtctime = 0x7fffffff;
} }
} }
else nvraddr=val&nvrmask; else nvraddr=val&nvrmask;
} }
uint8_t readnvr(uint16_t addr) uint8_t readnvr(uint16_t addr, void *priv)
{ {
uint8_t temp; uint8_t temp;
// printf("Read NVR %03X %02X %02X %04X:%04X\n",addr,nvraddr,nvrram[nvraddr],cs>>4,pc); // printf("Read NVR %03X %02X %02X %04X:%04X\n",addr,nvraddr,nvrram[nvraddr],cs>>4,pc);
@ -157,6 +162,7 @@ void loadnvr()
case ROM_AMI486: f = romfopen("ami486.nvr", "rb"); nvrmask = 127; break; case ROM_AMI486: f = romfopen("ami486.nvr", "rb"); nvrmask = 127; break;
case ROM_WIN486: f = romfopen("win486.nvr", "rb"); nvrmask = 127; break; case ROM_WIN486: f = romfopen("win486.nvr", "rb"); nvrmask = 127; break;
case ROM_PCI486: f = romfopen("hot-433.nvr", "rb"); nvrmask = 127; break; case ROM_PCI486: f = romfopen("hot-433.nvr", "rb"); nvrmask = 127; break;
case ROM_430VX: f = romfopen("hot-433.nvr", "rb"); nvrmask = 127; break;
default: return; default: return;
} }
if (!f) if (!f)
@ -169,7 +175,7 @@ void loadnvr()
nvrram[0xA]=6; nvrram[0xA]=6;
nvrram[0xB]=0; nvrram[0xB]=0;
c=1<<((6&0xF)-1); c=1<<((6&0xF)-1);
rtctime+=RTCCONST*(float)c; rtctime += (int)(RTCCONST * c * (1 << TIMER_SHIFT));
} }
void savenvr() void savenvr()
{ {
@ -178,7 +184,7 @@ void savenvr()
{ {
case ROM_PC1512: f = romfopen("pc1512.nvr" , "wb"); break; case ROM_PC1512: f = romfopen("pc1512.nvr" , "wb"); break;
case ROM_PC1640: f = romfopen("pc1640.nvr" , "wb"); break; case ROM_PC1640: f = romfopen("pc1640.nvr" , "wb"); break;
case ROM_PC200: f = romfopen("pc200.nvr" , "wb"); break; case ROM_PC200: f = romfopen("pc200.nvr" , "wb"); break;
case ROM_PC2086: f = romfopen("pc2086.nvr" , "wb"); break; case ROM_PC2086: f = romfopen("pc2086.nvr" , "wb"); break;
case ROM_PC3086: f = romfopen("pc3086.nvr" , "wb"); break; case ROM_PC3086: f = romfopen("pc3086.nvr" , "wb"); break;
case ROM_IBMAT: f = romfopen("at.nvr" , "wb"); break; case ROM_IBMAT: f = romfopen("at.nvr" , "wb"); break;
@ -192,6 +198,7 @@ void savenvr()
case ROM_AMI486: f = romfopen("ami486.nvr" , "wb"); break; case ROM_AMI486: f = romfopen("ami486.nvr" , "wb"); break;
case ROM_WIN486: f = romfopen("win486.nvr" , "wb"); break; case ROM_WIN486: f = romfopen("win486.nvr" , "wb"); break;
case ROM_PCI486: f = romfopen("hot-433.nvr", "wb"); break; case ROM_PCI486: f = romfopen("hot-433.nvr", "wb"); break;
case ROM_430VX: f = romfopen("hot-433.nvr", "wb"); break;
default: return; default: return;
} }
fwrite(nvrram,128,1,f); fwrite(nvrram,128,1,f);
@ -200,5 +207,6 @@ void savenvr()
void nvr_init() void nvr_init()
{ {
io_sethandler(0x0070, 0x0002, readnvr, NULL, NULL, writenvr, NULL, NULL); io_sethandler(0x0070, 0x0002, readnvr, NULL, NULL, writenvr, NULL, NULL, NULL);
timer_add(nvr_rtc, &rtctime, TIMER_ALWAYS_ENABLED, NULL);
} }

View file

@ -1 +1,3 @@
void nvr_init(); void nvr_init();
extern int nvr_dosave;

View file

@ -2,7 +2,7 @@
#include "io.h" #include "io.h"
#include "olivetti_m24.h" #include "olivetti_m24.h"
uint8_t olivetti_m24_read(uint16_t port) uint8_t olivetti_m24_read(uint16_t port, void *priv)
{ {
switch (port) switch (port)
{ {
@ -16,5 +16,5 @@ uint8_t olivetti_m24_read(uint16_t port)
void olivetti_m24_init() void olivetti_m24_init()
{ {
io_sethandler(0x0066, 0x0002, olivetti_m24_read, NULL, NULL, NULL, NULL, NULL); io_sethandler(0x0066, 0x0002, olivetti_m24_read, NULL, NULL, NULL, NULL, NULL, NULL);
} }

205
src/pc.c
View file

@ -1,19 +1,36 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <stdarg.h> #include <stdarg.h>
#include "ibm.h" #include "ibm.h"
#include "video.h" #include "device.h"
#include "ali1429.h"
#include "amstrad.h" #include "amstrad.h"
#include "cdrom-ioctl.h"
#include "config.h"
#include "cpu.h"
#include "dma.h" #include "dma.h"
#include "mem.h" #include "fdc.h"
#include "sound_gus.h"
#include "ide.h" #include "ide.h"
#include "keyboard.h"
#include "mem.h"
#include "model.h"
#include "mouse.h" #include "mouse.h"
#include "nvr.h"
#include "pic.h" #include "pic.h"
#include "pit.h" #include "pit.h"
#include "serial.h"
#include "cdrom-ioctl.h"
#include "cpu.h"
#include "model.h"
#include "plat-mouse.h" #include "plat-mouse.h"
#include "serial.h"
#include "sound.h"
#include "sound_cms.h"
#include "sound_opl.h"
#include "sound_sb.h"
#include "timer.h"
#include "vid_voodoo.h"
#include "video.h"
int frame = 0;
int cdrom_enabled; int cdrom_enabled;
int CPUID; int CPUID;
@ -42,8 +59,8 @@ int mousecapture;
FILE *pclogf; FILE *pclogf;
void pclog(const char *format, ...) void pclog(const char *format, ...)
{ {
char buf[256]; char buf[1024];
return; //return;
if (!pclogf) if (!pclogf)
pclogf=fopen("pclog.txt","wt"); pclogf=fopen("pclog.txt","wt");
//return; //return;
@ -79,6 +96,7 @@ int pollmouse_delay = 2;
void pollmouse() void pollmouse()
{ {
int x,y; int x,y;
// return;
pollmouse_delay--; pollmouse_delay--;
if (pollmouse_delay) return; if (pollmouse_delay) return;
pollmouse_delay = 2; pollmouse_delay = 2;
@ -149,6 +167,7 @@ void pc_reset()
{ {
resetx86(); resetx86();
cpu_set(); cpu_set();
//timer_reset();
dma_reset(); dma_reset();
fdc_reset(); fdc_reset();
pic_reset(); pic_reset();
@ -157,8 +176,7 @@ void pc_reset()
setpitclock(models[model].cpu[cpu_manufacturer].cpus[cpu].rspeed); setpitclock(models[model].cpu[cpu_manufacturer].cpus[cpu].rspeed);
adlib_reset(); // sb_reset();
sb_reset();
ali1429_reset(); ali1429_reset();
et4000w32_reset(); et4000w32_reset();
@ -185,31 +203,39 @@ void initpc()
cpuspeed2=(AT)?2:1; cpuspeed2=(AT)?2:1;
// cpuspeed2=cpuspeed; // cpuspeed2=cpuspeed;
atfullspeed=0; atfullspeed=0;
device_init();
pclog("Initvideo\n"); pclog("Initvideo\n");
initvideo(); initvideo();
mem_init(); mem_init();
loadbios(); loadbios();
mem_load_video_bios();
loaddisc(0,discfns[0]); loaddisc(0,discfns[0]);
loaddisc(1,discfns[1]); loaddisc(1,discfns[1]);
timer_reset();
sound_reset();
fdc_init();
//loadfont(); //loadfont();
loadnvr(); loadnvr();
resetvideo(); resetvideo();
initsound(); sound_init();
initpsg();
inithdc(); inithdc();
initega(); initega();
initgus();
resetide(); resetide();
ioctl_open(cdrom_drive); ioctl_open(cdrom_drive);
model_init(); model_init();
video_init(); video_init();
adlib_init(); speaker_init();
sb_init(); sound_card_init(sound_card_current);
gus_init(); if (GUS)
device_add(&gus_device);
if (GAMEBLASTER)
device_add(&cms_device);
pc_reset(); pc_reset();
pit_reset(); pit_reset();
@ -222,7 +248,7 @@ void initpc()
// CPUID=(is486 && (cpuspeed==7 || cpuspeed>=9)); // CPUID=(is486 && (cpuspeed==7 || cpuspeed>=9));
// pclog("Init - CPUID %i %i\n",CPUID,cpuspeed); // pclog("Init - CPUID %i %i\n",CPUID,cpuspeed);
shadowbios=0; shadowbios=0;
voodoo_init();
} }
void resetpc() void resetpc()
@ -236,13 +262,22 @@ void resetpc()
void resetpchard() void resetpchard()
{ {
device_close_all();
device_init();
timer_reset();
sound_reset();
mem_resize(); mem_resize();
fdc_init();
model_init(); model_init();
pclog("Video_init\n"); pclog("Video_init\n");
video_init(); video_init();
adlib_init(); speaker_init();
sb_init(); sound_card_init(sound_card_current);
gus_init(); if (GUS)
device_add(&gus_device);
if (GAMEBLASTER)
device_add(&cms_device);
pc_reset(); pc_reset();
@ -278,14 +313,14 @@ int sreadlnum,swritelnum,segareads,segawrites, scycles_lost;
int serial_fifo_read, serial_fifo_write; int serial_fifo_read, serial_fifo_write;
int emu_fps = 0; int emu_fps = 0;
extern int totaldiff;
void runpc() void runpc()
{ {
char s[200]; char s[200];
int done=0; int done=0;
clockrate = models[model].cpu[cpu_manufacturer].cpus[cpu].rspeed; clockrate = models[model].cpu[cpu_manufacturer].cpus[cpu].rspeed;
if (is386) exec386(models[model].cpu[cpu_manufacturer].cpus[cpu].rspeed / 100); if (is386) exec386(models[model].cpu[cpu_manufacturer].cpus[cpu].rspeed / 100);
else if (AT) exec286(models[model].cpu[cpu_manufacturer].cpus[cpu].rspeed / 100); else if (AT) exec386(models[model].cpu[cpu_manufacturer].cpus[cpu].rspeed / 100);
else execx86(models[model].cpu[cpu_manufacturer].cpus[cpu].rspeed / 100); else execx86(models[model].cpu[cpu_manufacturer].cpus[cpu].rspeed / 100);
keyboard_poll_host(); keyboard_poll_host();
keyboard_process(); keyboard_process();
@ -320,10 +355,12 @@ void runpc()
if (win_title_update) if (win_title_update)
{ {
win_title_update=0; win_title_update=0;
sprintf(s, "PCem v0.7 - %s - %s - %s - %i%% %i %04X %i", model_getname(), models[model].cpu[cpu_manufacturer].cpus[cpu].name, (!mousecapture) ? "Click to capture mouse" : "Press CTRL-END to release mouse", fps, et4000w32p_getclock(), ECX, ins); sprintf(s, "PCem v0.7 - %s - %s - %s - %i%% - %i", model_getname(), models[model].cpu[cpu_manufacturer].cpus[cpu].name, (!mousecapture) ? "Click to capture mouse" : "Press CTRL-END to release mouse", fps, totaldiff);
totaldiff = 0;
set_window_title(s); set_window_title(s);
} }
done++; done++;
frame++;
/* if ((at70hz && VGA)!=oldat70hz) /* if ((at70hz && VGA)!=oldat70hz)
{ {
oldat70hz=(at70hz && VGA); oldat70hz=(at70hz && VGA);
@ -369,7 +406,6 @@ void closepc()
// ioctl_close(); // ioctl_close();
dumpegaregs(); dumpegaregs();
dumppic(); dumppic();
dumpgus();
// output=7; // output=7;
// setpitclock(clocks[0][0][0]); // setpitclock(clocks[0][0][0]);
// while (1) runpc(); // while (1) runpc();
@ -377,6 +413,7 @@ void closepc()
savedisc(1); savedisc(1);
dumpregs(); dumpregs();
closevideo(); closevideo();
device_close_all();
} }
/*int main() /*int main()
@ -398,94 +435,86 @@ void loadconfig()
{ {
char s[512]; char s[512];
char *p; char *p;
append_filename(s,pcempath,"pcem.cfg",511); append_filename(s, pcempath, "pcem.cfg", 511);
set_config_file(s); set_config_file(s);
ADLIB=get_config_int(NULL,"adlib",1); GAMEBLASTER = get_config_int(NULL, "gameblaster", 0);
GAMEBLASTER=get_config_int(NULL,"gameblaster",0); GUS = get_config_int(NULL, "gus", 0);
FASTDISC=get_config_int(NULL,"fast_disc",1);
model = get_config_int(NULL, "model", 14); model = get_config_int(NULL, "model", 14);
pclog("Model %i\n", model);
romset = model_getromset(); romset = model_getromset();
cpu_manufacturer = get_config_int(NULL, "cpu_manufacturer", 0); cpu_manufacturer = get_config_int(NULL, "cpu_manufacturer", 0);
cpu = get_config_int(NULL, "cpu", 0); cpu = get_config_int(NULL, "cpu", 0);
gfxcard=get_config_int(NULL,"gfxcard",0); gfxcard = get_config_int(NULL, "gfxcard", 0);
video_speed = get_config_int(NULL, "video_speed", 3); video_speed = get_config_int(NULL, "video_speed", 3);
sbtype=get_config_int(NULL,"sndcard",SB2); sound_card_current = get_config_int(NULL, "sndcard", SB2);
pclog("Model1 %i\n", model);
p=(char *)get_config_string(NULL,"disc_a","");
if (p) strcpy(discfns[0],p);
else strcpy(discfns[0],"");
pclog("Model2 %i\n", model);
p=(char *)get_config_string(NULL,"disc_b","");
if (p) strcpy(discfns[1],p);
else strcpy(discfns[1],"");
pclog("Model3 %i\n", model);
mem_size=get_config_int(NULL,"mem_size",4);
cdrom_drive=get_config_int(NULL,"cdrom_drive",0);
cdrom_enabled=get_config_int(NULL,"cdrom_enabled",0);
slowega=get_config_int(NULL,"slow_video",1);
cache=get_config_int(NULL,"cache",3);
cga_comp=get_config_int(NULL,"cga_composite",0);
kb_win=get_config_int(NULL,"kb_win",0);
vid_resize=get_config_int(NULL,"vid_resize",0);
// cpuspeed=2;
hdc[0].spt=get_config_int(NULL,"hdc_sectors",0); p = (char *)get_config_string(NULL, "disc_a", "");
hdc[0].hpc=get_config_int(NULL,"hdc_heads",0); if (p) strcpy(discfns[0], p);
hdc[0].tracks=get_config_int(NULL,"hdc_cylinders",0); else strcpy(discfns[0], "");
p = (char *)get_config_string(NULL, "disc_b", "");
if (p) strcpy(discfns[1], p);
else strcpy(discfns[1], "");
mem_size = get_config_int(NULL, "mem_size", 4);
cdrom_drive = get_config_int(NULL, "cdrom_drive", 0);
cdrom_enabled = get_config_int(NULL, "cdrom_enabled", 0);
slowega = get_config_int(NULL, "slow_video", 1);
cache = get_config_int(NULL, "cache", 3);
cga_comp = get_config_int(NULL, "cga_composite", 0);
kb_win = get_config_int(NULL, "kb_win", 0);
vid_resize = get_config_int(NULL, "vid_resize", 0);
hdc[0].spt = get_config_int(NULL, "hdc_sectors", 0);
hdc[0].hpc = get_config_int(NULL, "hdc_heads", 0);
hdc[0].tracks = get_config_int(NULL, "hdc_cylinders", 0);
p = (char *)get_config_string(NULL, "hdc_fn", ""); p = (char *)get_config_string(NULL, "hdc_fn", "");
if (p) strcpy(ide_fn[0], p); if (p) strcpy(ide_fn[0], p);
else strcpy(ide_fn[0], ""); else strcpy(ide_fn[0], "");
hdc[1].spt=get_config_int(NULL,"hdd_sectors",0); hdc[1].spt = get_config_int(NULL, "hdd_sectors", 0);
hdc[1].hpc=get_config_int(NULL,"hdd_heads",0); hdc[1].hpc = get_config_int(NULL, "hdd_heads", 0);
hdc[1].tracks=get_config_int(NULL,"hdd_cylinders",0); hdc[1].tracks = get_config_int(NULL, "hdd_cylinders", 0);
p = (char *)get_config_string(NULL, "hdd_fn", ""); p = (char *)get_config_string(NULL, "hdd_fn", "");
if (p) strcpy(ide_fn[1], p); if (p) strcpy(ide_fn[1], p);
else strcpy(ide_fn[1], ""); else strcpy(ide_fn[1], "");
pclog("Model4 %i\n", model);
} }
void saveconfig() void saveconfig()
{ {
pclog("saveconfig\n");
config_new(); config_new();
pclog("config_new\n"); set_config_int(NULL, "gameblaster", GAMEBLASTER);
set_config_int(NULL,"adlib",ADLIB); set_config_int(NULL, "gus", GUS);
pclog("sci 1\n");
set_config_int(NULL,"gameblaster",GAMEBLASTER);
set_config_int(NULL,"fast_disc",FASTDISC);
set_config_int(NULL, "model", model); set_config_int(NULL, "model", model);
set_config_int(NULL, "cpu_manufacturer", cpu_manufacturer); set_config_int(NULL, "cpu_manufacturer", cpu_manufacturer);
set_config_int(NULL, "cpu", cpu); set_config_int(NULL, "cpu", cpu);
set_config_int(NULL,"gfxcard",gfxcard); set_config_int(NULL, "gfxcard", gfxcard);
set_config_int(NULL,"video_speed", video_speed); set_config_int(NULL, "video_speed", video_speed);
set_config_int(NULL,"sndcard",sbtype); set_config_int(NULL, "sndcard", sound_card_current);
set_config_int(NULL,"cpu_speed",cpuspeed); set_config_int(NULL, "cpu_speed", cpuspeed);
set_config_int(NULL,"has_fpu",hasfpu); set_config_int(NULL, "has_fpu", hasfpu);
set_config_int(NULL,"slow_video",slowega); set_config_int(NULL, "slow_video", slowega);
set_config_int(NULL,"cache",cache); set_config_int(NULL, "cache", cache);
set_config_int(NULL,"cga_composite",cga_comp); set_config_int(NULL, "cga_composite", cga_comp);
set_config_string(NULL,"disc_a",discfns[0]); set_config_string(NULL, "disc_a", discfns[0]);
set_config_string(NULL,"disc_b",discfns[1]); set_config_string(NULL, "disc_b", discfns[1]);
set_config_int(NULL,"mem_size",mem_size); set_config_int(NULL, "mem_size", mem_size);
set_config_int(NULL,"cdrom_drive",cdrom_drive); set_config_int(NULL, "cdrom_drive", cdrom_drive);
set_config_int(NULL,"cdrom_enabled",cdrom_enabled); set_config_int(NULL, "cdrom_enabled", cdrom_enabled);
set_config_int(NULL,"kb_win",kb_win); set_config_int(NULL, "kb_win", kb_win);
set_config_int(NULL,"vid_resize",vid_resize); set_config_int(NULL, "vid_resize", vid_resize);
set_config_int(NULL,"hdc_sectors",hdc[0].spt); set_config_int(NULL, "hdc_sectors", hdc[0].spt);
set_config_int(NULL,"hdc_heads",hdc[0].hpc); set_config_int(NULL, "hdc_heads", hdc[0].hpc);
set_config_int(NULL,"hdc_cylinders",hdc[0].tracks); set_config_int(NULL, "hdc_cylinders", hdc[0].tracks);
set_config_string(NULL, "hdc_fn", ide_fn[0]); set_config_string(NULL, "hdc_fn", ide_fn[0]);
set_config_int(NULL,"hdd_sectors",hdc[1].spt); set_config_int(NULL, "hdd_sectors", hdc[1].spt);
set_config_int(NULL,"hdd_heads",hdc[1].hpc); set_config_int(NULL, "hdd_heads", hdc[1].hpc);
set_config_int(NULL,"hdd_cylinders",hdc[1].tracks); set_config_int(NULL, "hdd_cylinders", hdc[1].tracks);
set_config_string(NULL, "hdd_fn", ide_fn[1]); set_config_string(NULL, "hdd_fn", ide_fn[1]);
pclog("saveconfig done\n");
} }

View file

@ -4,13 +4,12 @@
#include "pci.h" #include "pci.h"
void (*pci_card_write[32])(int func, int addr, uint8_t val); void (*pci_card_write[32])(int func, int addr, uint8_t val, void *priv);
uint8_t (*pci_card_read[32])(int func, int addr); uint8_t (*pci_card_read[32])(int func, int addr, void *priv);
void *pci_priv[32];
static int pci_index, pci_func, pci_card, pci_bus, pci_enable; static int pci_index, pci_func, pci_card, pci_bus, pci_enable;
static uint8_t card_16[256];
static uint8_t card_18[256];
void pci_write(uint16_t port, uint8_t val) void pci_write(uint16_t port, uint8_t val, void *priv)
{ {
switch (port) switch (port)
{ {
@ -32,16 +31,16 @@ void pci_write(uint16_t port, uint8_t val)
if (!pci_enable) if (!pci_enable)
return; return;
pclog("PCI write bus %i card %i index %02X val %02X %04X:%04X\n", pci_bus, pci_card, pci_index | (port & 3), val, CS, pc); // pclog("PCI write bus %i card %i func %i index %02X val %02X %04X:%04X\n", pci_bus, pci_card, pci_func, pci_index | (port & 3), val, CS, pc);
if (!pci_bus && pci_card_write[pci_card]) if (!pci_bus && pci_card_write[pci_card])
pci_card_write[pci_card](pci_func, pci_index | (port & 3), val); pci_card_write[pci_card](pci_func, pci_index | (port & 3), val, pci_priv[pci_card]);
break; break;
} }
} }
uint8_t pci_read(uint16_t port) uint8_t pci_read(uint16_t port, void *priv)
{ {
switch (port) switch (port)
{ {
@ -58,10 +57,10 @@ uint8_t pci_read(uint16_t port)
if (!pci_enable) if (!pci_enable)
return 0xff; return 0xff;
pclog("PCI read bus %i card %i index %02X\n", pci_bus, pci_card, pci_index | (port & 3)); // pclog("PCI read bus %i card %i func %i index %02X\n", pci_bus, pci_card, pci_func, pci_index | (port & 3));
if (!pci_bus && pci_card_read[pci_card]) if (!pci_bus && pci_card_read[pci_card])
return pci_card_read[pci_card](pci_func, pci_index | (port & 3)); return pci_card_read[pci_card](pci_func, pci_index | (port & 3), pci_priv[pci_card]);
return 0xff; return 0xff;
} }
@ -71,19 +70,20 @@ void pci_init()
{ {
int c; int c;
io_sethandler(0x0cf8, 0x0008, pci_read, NULL, NULL, pci_write, NULL, NULL); io_sethandler(0x0cf8, 0x0008, pci_read, NULL, NULL, pci_write, NULL, NULL, NULL);
for (c = 0; c < 32; c++) for (c = 0; c < 32; c++)
pci_card_read[c] = pci_card_write[c] = NULL; pci_card_read[c] = pci_card_write[c] = pci_priv[c] = NULL;
} }
void pci_add_specific(int card, uint8_t (*read)(int func, int addr), void (*write)(int func, int addr, uint8_t val)) 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)
{ {
pci_card_read[card] = read; pci_card_read[card] = read;
pci_card_write[card] = write; pci_card_write[card] = write;
pci_priv[card] = priv;
} }
void pci_add(uint8_t (*read)(int func, int addr), void (*write)(int func, int addr, uint8_t val)) 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)
{ {
int c; int c;
@ -93,6 +93,7 @@ void pci_add(uint8_t (*read)(int func, int addr), void (*write)(int func, int ad
{ {
pci_card_read[c] = read; pci_card_read[c] = read;
pci_card_write[c] = write; pci_card_write[c] = write;
pci_priv[c] = priv;
return; return;
} }
} }

View file

@ -1,3 +1,3 @@
void pci_init(); void pci_init();
void pci_add_specific(int card, uint8_t (*read)(int func, int addr), void (*write)(int func, int addr, uint8_t val)); 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 (*write)(int func, int addr, uint8_t val)); 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);

View file

@ -1,14 +1,16 @@
#include "ibm.h" #include "ibm.h"
#include "io.h"
#include "pic.h"
int output; int output;
int intclear; int intclear;
int keywaiting=0; int keywaiting=0;
int pit0;
int pic_intpending; int pic_intpending;
void pic_updatepending() void pic_updatepending()
{ {
pic_intpending = (((pic.pend&~pic.mask)&~pic.mask2) || ((pic2.pend&~pic2.mask)&~pic2.mask2)); pic_intpending = (((pic.pend&~pic.mask)&~pic.mask2) || ((pic2.pend&~pic2.mask)&~pic2.mask2));
// pclog("pic_intpending = %i %02X %02X %02X\n", pic_intpending, pic.pend, pic.mask, pic.mask2);
} }
@ -27,7 +29,7 @@ void pic_reset()
pic_intpending = 0; pic_intpending = 0;
} }
void pic_write(uint16_t addr, uint8_t val) void pic_write(uint16_t addr, uint8_t val, void *priv)
{ {
int c; int c;
// pclog("Write PIC %04X %02X %04X(%06X):%04X\n",addr,val,CS,cs,pc); // pclog("Write PIC %04X %02X %04X(%06X):%04X\n",addr,val,CS,cs,pc);
@ -87,7 +89,6 @@ void pic_write(uint16_t addr, uint8_t val)
pic.ins&=~(1<<c); pic.ins&=~(1<<c);
pic.mask2&=~(1<<c); pic.mask2&=~(1<<c);
// pic.pend&=~(1<<c); // pic.pend&=~(1<<c);
if (c==0) pit0=1;
if (c==1 && keywaiting) if (c==1 && keywaiting)
{ {
intclear&=~1; intclear&=~1;
@ -109,20 +110,20 @@ void pic_write(uint16_t addr, uint8_t val)
} }
} }
uint8_t pic_read(uint16_t addr) uint8_t pic_read(uint16_t addr, void *priv)
{ {
if (addr&1) { /*pclog("Read PIC mask %02X\n",pic.mask);*/ return pic.mask; } if (addr&1) { /*pclog("Read PIC mask %02X\n",pic.mask);*/ return pic.mask; }
if (pic.read) { /*pclog("Read PIC ins %02X\n",pic.ins);*/ return pic.ins; } if (pic.read) { /*pclog("Read PIC ins %02X\n",pic.ins);*/ return pic.ins | (pic2.ins ? 4 : 0); }
// pclog("Read PIC pend %02X %08X\n",pic.pend,EDX); // pclog("Read PIC pend %02X %08X\n",pic.pend,EDX);
return pic.pend; return pic.pend;
} }
void pic_init() void pic_init()
{ {
io_sethandler(0x0020, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL); io_sethandler(0x0020, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, NULL);
} }
void pic2_write(uint16_t addr, uint8_t val) void pic2_write(uint16_t addr, uint8_t val, void *priv)
{ {
int c; int c;
// pclog("Write PIC2 %04X %02X %04X:%04X %i\n",addr,val,CS,pc,ins); // pclog("Write PIC2 %04X %02X %04X:%04X %i\n",addr,val,CS,pc,ins);
@ -137,6 +138,7 @@ void pic2_write(uint16_t addr, uint8_t val)
break; break;
case 1: /*ICW2*/ case 1: /*ICW2*/
pic2.vector=val&0xF8; pic2.vector=val&0xF8;
// pclog("PIC2 vector %02X\n", val & 0xf8);
if (pic2.icw1&2) pic2.icw=3; if (pic2.icw1&2) pic2.icw=3;
else pic2.icw=2; else pic2.icw=2;
break; break;
@ -188,17 +190,17 @@ void pic2_write(uint16_t addr, uint8_t val)
} }
} }
uint8_t pic2_read(uint16_t addr) uint8_t pic2_read(uint16_t addr, void *priv)
{ {
if (addr&1) { /*pclog("Read PIC2 mask %02X %04X:%08X\n",pic2.mask,CS,pc); */return pic2.mask; } if (addr&1) { /*pclog("Read PIC2 mask %02X %04X:%08X\n",pic2.mask,CS,pc); */return pic2.mask; }
if (pic2.read) { /*pclog("Read PIC2 ins %02X %04X:%08X\n",pic2.ins,CS,pc); */return pic2.ins; } if (pic2.read) { /*pclog("Read PIC2 ins %02X %04X:%08X\n",pic2.ins,CS,pc); */return pic2.ins; }
// pclog("Read PIC2 pend %02X %04X:%08X\n",pic2.pend,CS,pc); /*pclog("Read PIC2 pend %02X %04X:%08X\n",pic2.pend,CS,pc);*/
return pic2.pend; return pic2.pend;
} }
void pic2_init() void pic2_init()
{ {
io_sethandler(0x00a0, 0x0002, pic2_read, NULL, NULL, pic2_write, NULL, NULL); io_sethandler(0x00a0, 0x0002, pic2_read, NULL, NULL, pic2_write, NULL, NULL, NULL);
} }
@ -213,6 +215,7 @@ int pic_current[16];
void picint(uint16_t num) void picint(uint16_t num)
{ {
// pclog("picint : %04X\n", num);
// if (num == 0x10) pclog("PICINT 10\n"); // if (num == 0x10) pclog("PICINT 10\n");
if (num>0xFF) if (num>0xFF)
{ {
@ -222,6 +225,7 @@ void picint(uint16_t num)
{ {
pic.pend|=num; pic.pend|=num;
} }
// pclog("picint : PEND now %02X %02X\n", pic.pend, pic2.pend);
pic_updatepending(); pic_updatepending();
} }
@ -248,7 +252,7 @@ void picintc(uint16_t num)
{ {
int c = 0; int c = 0;
while (!(num & (1 << c))) c++; while (!(num & (1 << c))) c++;
// pclog("INTC %04X %i\n", num, c); //pclog("INTC %04X %i\n", num, c);
pic_current[c]=0; pic_current[c]=0;
if (num>0xFF) pic2.pend&=~(num>>8); if (num>0xFF) pic2.pend&=~(num>>8);
else else
@ -270,6 +274,7 @@ uint8_t picinterrupt()
pic.mask2|=(1<<c); pic.mask2|=(1<<c);
pic_updatepending(); pic_updatepending();
// pclog("picinterrupt : Taking PIC1 int %i\n", c);
// if (!c) pclog("Taking timer int\n"); // if (!c) pclog("Taking timer int\n");
// if (c==5) printf("GUS IRQ!\n"); // if (c==5) printf("GUS IRQ!\n");
// if (c==1) printf("Keyboard int!\n"); // if (c==1) printf("Keyboard int!\n");
@ -277,6 +282,8 @@ uint8_t picinterrupt()
return c+pic.vector; return c+pic.vector;
} }
} }
/* if (pic.mask2 & 4)
return 0xff;*/
temp=pic2.pend&~pic2.mask; temp=pic2.pend&~pic2.mask;
for (c=0;c<8;c++) for (c=0;c<8;c++)
{ {
@ -286,6 +293,7 @@ uint8_t picinterrupt()
pic2.ins|=(1<<c); pic2.ins|=(1<<c);
pic2.mask2|=(1<<c); pic2.mask2|=(1<<c);
pic_updatepending(); pic_updatepending();
//pclog("Taking PIC2 int %i\n", c);
// if (c==(14-8)) pclog("Taking IRQ 14 %02X\n",c+pic2.vector); // if (c==(14-8)) pclog("Taking IRQ 14 %02X\n",c+pic2.vector);
// printf("Taking high IRQ! %i\n",c); // printf("Taking high IRQ! %i\n",c);
// if (c==1) printf("Keyboard int!\n"); // if (c==1) printf("Keyboard int!\n");
@ -298,10 +306,9 @@ uint8_t picinterrupt()
void picclear(int num) void picclear(int num)
{ {
// printf("Pic clear %02X\n",num); // pclog("Pic clear %02X\n",num);
pic.pend&=~num; pic.pend&=~num;
pic.ins&=~num; pic.ins&=~num;
if (num==1) pit0=1;
pic_updatepending(); pic_updatepending();
} }

View file

@ -1,3 +1,9 @@
void pic_init(); void pic_init();
void pic2_init(); void pic2_init();
void pic_reset(); void pic_reset();
void picint(uint16_t num);
void picintlevel(uint16_t num);
void picintc(uint16_t num);
uint8_t picinterrupt();
void picclear(int num);

View file

@ -5,9 +5,15 @@
#include <string.h> #include <string.h>
#include "ibm.h" #include "ibm.h"
#include "pit.h"
#include "video.h"
#include "cpu.h" #include "cpu.h"
#include "dma.h"
#include "io.h"
#include "pic.h"
#include "pit.h"
#include "timer.h"
#include "video.h"
/*B0 to 40, two writes to 43, then two reads - value does not change!*/ /*B0 to 40, two writes to 43, then two reads - value does not change!*/
/*B4 to 40, two writes to 43, then two reads - value _does_ change!*/ /*B4 to 40, two writes to 43, then two reads - value _does_ change!*/
//Tyrian writes 4300 or 17512 //Tyrian writes 4300 or 17512
@ -21,31 +27,25 @@ float isa_timing, bus_timing;
int firsttime=1; int firsttime=1;
void setpitclock(float clock) void setpitclock(float clock)
{ {
float temp;
// printf("PIT clock %f\n",clock); // printf("PIT clock %f\n",clock);
cpuclock=clock; cpuclock=clock;
PITCONST=clock/1193182.0; PITCONST=clock/1193182.0;
SPKCONST=clock/48000.0;
CGACONST=(clock/(19687500.0/11.0)); CGACONST=(clock/(19687500.0/11.0));
MDACONST=(clock/1813000.0); MDACONST=(clock/1813000.0);
VGACONST1=(clock/25175000.0); VGACONST1=(clock/25175000.0);
VGACONST2=(clock/28322000.0); VGACONST2=(clock/28322000.0);
setsbclock(clock);
SOUNDCONST=clock/200.0;
CASCONST=PITCONST*1192;
isa_timing = clock/8000000.0; isa_timing = clock/8000000.0;
bus_timing = clock/(double)cpu_busspeed; bus_timing = clock/(double)cpu_busspeed;
video_updatetiming(); video_updatetiming();
// pclog("egacycles %i egacycles2 %i temp %f clock %f\n",egacycles,egacycles2,temp,clock); // pclog("egacycles %i egacycles2 %i temp %f clock %f\n",egacycles,egacycles2,temp,clock);
GUSCONST=(clock/3125.0)/4.0;
GUSCONST2=(clock/3125.0)/4.0; //Timer 2 at different rate to 1?
video_recalctimings(); video_recalctimings();
RTCCONST=clock/32768.0; RTCCONST=clock/32768.0;
TIMER_USEC = (int)((clock / 1000000.0f) * (float)(1 << TIMER_SHIFT));
device_speed_changed();
} }
//#define PITCONST (8000000.0/1193000.0) //#define PITCONST (8000000.0/1193000.0)
//#define PITCONST (cpuclock/1193000.0) //#define PITCONST (cpuclock/1193000.0)
int pit0;
void pit_reset() void pit_reset()
{ {
memset(&pit,0,sizeof(PIT)); memset(&pit,0,sizeof(PIT));
@ -69,12 +69,10 @@ float pit_timer0_freq()
return 1193182.0f/(float)pit.l[0]; return 1193182.0f/(float)pit.l[0];
} }
extern int ins; extern int ins;
void pit_write(uint16_t addr, uint8_t val) void pit_write(uint16_t addr, uint8_t val, void *priv)
{ {
int t; int t;
uint8_t oldctrl=pit.ctrl;
cycles -= (int)PITCONST; cycles -= (int)PITCONST;
pit0=1;
// printf("Write PIT %04X %02X %04X:%08X %i %i\n",addr,val,CS,pc,ins); // printf("Write PIT %04X %02X %04X:%08X %i %i\n",addr,val,CS,pc,ins);
switch (addr&3) switch (addr&3)
{ {
@ -135,13 +133,15 @@ void pit_write(uint16_t addr, uint8_t val)
pit.l[t]=val; pit.l[t]=val;
pit.thit[t]=0; pit.thit[t]=0;
pit.c[t]=pit.l[t]*PITCONST; pit.c[t]=pit.l[t]*PITCONST;
picintc(1); if (!t)
picintc(1);
break; break;
case 2: case 2:
pit.l[t]=(val<<8); pit.l[t]=(val<<8);
pit.thit[t]=0; pit.thit[t]=0;
pit.c[t]=pit.l[t]*PITCONST; pit.c[t]=pit.l[t]*PITCONST;
picintc(1); if (!t)
picintc(1);
break; break;
case 0: case 0:
pit.l[t]&=0xFF; pit.l[t]&=0xFF;
@ -150,7 +150,8 @@ void pit_write(uint16_t addr, uint8_t val)
// pclog("%04X %f\n",pit.l[t],pit.c[t]); // pclog("%04X %f\n",pit.l[t],pit.c[t]);
pit.thit[t]=0; pit.thit[t]=0;
pit.wm[t]=3; pit.wm[t]=3;
picintc(1); if (!t)
picintc(1);
break; break;
case 3: case 3:
pit.l[t]&=0xFF00; pit.l[t]&=0xFF00;
@ -190,7 +191,7 @@ void pit_write(uint16_t addr, uint8_t val)
} }
} }
uint8_t pit_read(uint16_t addr) uint8_t pit_read(uint16_t addr, void *priv)
{ {
uint8_t temp; uint8_t temp;
cycles -= (int)PITCONST; cycles -= (int)PITCONST;
@ -250,8 +251,8 @@ void pit_poll()
else pit.c[0]+=((float)(0x10000*PITCONST)); else pit.c[0]+=((float)(0x10000*PITCONST));
} }
// pit.c[0]+=(pit.l[0]*PITCONST); // pit.c[0]+=(pit.l[0]*PITCONST);
// printf("PIT over! %f %i\n",pit.c[0],pit.m[0]); // if (output) printf("PIT over! %f %i\n",pit.c[0],pit.m[0]);
if (!pit.thit[0] && (pit.l[0]>0x14)) if (!pit.thit[0])// && (pit.l[0]>0x14))
{ {
// printf("PIT int!\n"); // printf("PIT int!\n");
/// printf("%05X %05X %02X\n",pit.c[0],pit.l[0],pit.ctrls[0]); /// printf("%05X %05X %02X\n",pit.c[0],pit.l[0],pit.ctrls[0]);
@ -259,7 +260,6 @@ void pit_poll()
} }
if (!pit.m[0] || pit.m[0]==4) pit.thit[0]=1; if (!pit.m[0] || pit.m[0]==4) pit.thit[0]=1;
// if ((pit.ctrls[0]&0xE)==2) pit.thit[0]=1; // if ((pit.ctrls[0]&0xE)==2) pit.thit[0]=1;
pit0=0;
pitcount++; pitcount++;
} }
if (pit.c[1]<1) if (pit.c[1]<1)
@ -301,5 +301,5 @@ void pit_poll()
void pit_init() void pit_init()
{ {
io_sethandler(0x0040, 0x0004, pit_read, NULL, NULL, pit_write, NULL, NULL); io_sethandler(0x0040, 0x0004, pit_read, NULL, NULL, pit_write, NULL, NULL, NULL);
} }

View file

@ -31,6 +31,7 @@
#define IDC_CHECK2 1011 #define IDC_CHECK2 1011
#define IDC_CHECK3 1012 #define IDC_CHECK3 1012
#define IDC_CHECK4 1013 #define IDC_CHECK4 1013
#define IDC_CHECKGUS 1014
#define IDC_STATIC 1020 #define IDC_STATIC 1020
#define IDC_EDIT1 1030 #define IDC_EDIT1 1030
#define IDC_EDIT2 1031 #define IDC_EDIT2 1031

View file

@ -1,7 +1,9 @@
#include "ibm.h" #include "ibm.h"
#include "io.h" #include "io.h"
#include "mouse.h" #include "mouse.h"
#include "pic.h"
#include "serial.h" #include "serial.h"
#include "timer.h"
SERIAL serial,serial2; SERIAL serial,serial2;
@ -48,7 +50,7 @@ void sendserial(uint8_t dat)
serial.iir=4; serial.iir=4;
} }
void serial_write(uint16_t addr, uint8_t val) void serial_write(uint16_t addr, uint8_t val, void *priv)
{ {
// printf("Write serial %03X %02X %04X:%04X\n",addr,val,CS,pc); // printf("Write serial %03X %02X %04X:%04X\n",addr,val,CS,pc);
switch (addr&7) switch (addr&7)
@ -89,7 +91,7 @@ void serial_write(uint16_t addr, uint8_t val)
} }
} }
uint8_t serial_read(uint16_t addr) uint8_t serial_read(uint16_t addr, void *priv)
{ {
uint8_t temp; uint8_t temp;
// printf("Read serial %03X %04X(%08X):%04X %i %i ", addr, CS, cs, pc, mousedelay, ins); // printf("Read serial %03X %04X(%08X):%04X %i %i ", addr, CS, cs, pc, mousedelay, ins);
@ -104,7 +106,7 @@ uint8_t serial_read(uint16_t addr)
if (serial_fifo_read != serial_fifo_write) if (serial_fifo_read != serial_fifo_write)
{ {
mousepos = 0; mousepos = 0;
mousedelay = 1000; mousedelay = 5000 * (1 << TIMER_SHIFT);
// pclog("Next FIFO\n"); // pclog("Next FIFO\n");
} }
break; break;
@ -122,7 +124,7 @@ uint8_t serial_read(uint16_t addr)
return temp; return temp;
} }
void serial2_write(uint16_t addr, uint8_t val) void serial2_write(uint16_t addr, uint8_t val, void *priv)
{ {
// printf("Write serial2 %03X %02X %04X:%04X\n",addr,val,cs>>4,pc); // printf("Write serial2 %03X %02X %04X:%04X\n",addr,val,cs>>4,pc);
switch (addr&7) switch (addr&7)
@ -156,7 +158,7 @@ void serial2_write(uint16_t addr, uint8_t val)
} }
} }
uint8_t serial2_read(uint16_t addr) uint8_t serial2_read(uint16_t addr, void *priv)
{ {
uint8_t temp; uint8_t temp;
// printf("Read serial2 %03X %04X:%04X\n",addr,cs>>4,pc); // printf("Read serial2 %03X %04X:%04X\n",addr,cs>>4,pc);
@ -186,25 +188,25 @@ uint8_t serial2_read(uint16_t addr)
/*Tandy might need COM1 at 2f8*/ /*Tandy might need COM1 at 2f8*/
void serial1_init(uint16_t addr) void serial1_init(uint16_t addr)
{ {
io_sethandler(addr, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL); io_sethandler(addr, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, NULL);
serial_rcr = NULL; serial_rcr = NULL;
} }
void serial1_remove() void serial1_remove()
{ {
io_removehandler(0x2e8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL); io_removehandler(0x2e8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, NULL);
io_removehandler(0x2f8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL); io_removehandler(0x2f8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, NULL);
io_removehandler(0x3e8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL); io_removehandler(0x3e8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, NULL);
io_removehandler(0x3f8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL); io_removehandler(0x3f8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, NULL);
} }
void serial2_init(uint16_t addr) void serial2_init(uint16_t addr)
{ {
io_sethandler(addr, 0x0008, serial2_read, NULL, NULL, serial2_write, NULL, NULL); io_sethandler(addr, 0x0008, serial2_read, NULL, NULL, serial2_write, NULL, NULL, NULL);
} }
void serial2_remove() void serial2_remove()
{ {
io_removehandler(0x2e8, 0x0008, serial2_read, NULL, NULL, serial2_write, NULL, NULL); io_removehandler(0x2e8, 0x0008, serial2_read, NULL, NULL, serial2_write, NULL, NULL, NULL);
io_removehandler(0x2f8, 0x0008, serial2_read, NULL, NULL, serial2_write, NULL, NULL); io_removehandler(0x2f8, 0x0008, serial2_read, NULL, NULL, serial2_write, NULL, NULL, NULL);
io_removehandler(0x3e8, 0x0008, serial2_read, NULL, NULL, serial2_write, NULL, NULL); io_removehandler(0x3e8, 0x0008, serial2_read, NULL, NULL, serial2_write, NULL, NULL, NULL);
io_removehandler(0x3f8, 0x0008, serial2_read, NULL, NULL, serial2_write, NULL, NULL); io_removehandler(0x3f8, 0x0008, serial2_read, NULL, NULL, serial2_write, NULL, NULL, NULL);
} }

View file

@ -1,180 +1,146 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include "ibm.h" #include "ibm.h"
#include "device.h"
#include "filters.h" #include "filters.h"
int soundon = 1; #include "sound_opl.h"
int16_t *adbuffer,*adbuffer2;
int16_t *psgbuffer;
uint16_t *cmsbuffer;
int16_t *spkbuffer;
int16_t *outbuffer;
uint16_t *gusbuffer;
void initsound() #include "sound.h"
#include "sound_adlib.h"
#include "sound_adlibgold.h"
#include "sound_pas16.h"
#include "sound_sb.h"
#include "sound_sb_dsp.h"
#include "sound_wss.h"
#include "timer.h"
int sound_card_current = 0;
static int sound_card_last = 0;
typedef struct
{
char name[32];
device_t *device;
} SOUND_CARD;
static SOUND_CARD sound_cards[] =
{
{"None", NULL},
{"Adlib", &adlib_device},
{"Sound Blaster 1.0", &sb_1_device},
{"Sound Blaster 1.5", &sb_15_device},
{"Sound Blaster 2.0", &sb_2_device},
{"Sound Blaster Pro v1", &sb_pro_v1_device},
{"Sound Blaster Pro v2", &sb_pro_v1_device},
{"Sound Blaster 16", &sb_16_device},
{"Adlib Gold", &adgold_device},
{"Windows Sound System", &wss_device},
{"Pro Audio Spectrum 16", &pas16_device},
{"", NULL}
};
char *sound_card_getname(int card)
{
return sound_cards[card].name;
}
void sound_card_init()
{
if (sound_cards[sound_card_current].device)
device_add(sound_cards[sound_card_current].device);
sound_card_last = sound_card_current;
}
static struct
{
void (*poll)(void *p);
void (*get_buffer)(int16_t *buffer, int len, void *p);
void *priv;
} sound_handlers[8];
static int sound_handlers_num;
static int sound_poll_time = 0, sound_get_buffer_time = 0;
int soundon = 1;
static int16_t cd_buffer[SOUNDBUFLEN * 2];
void sound_cd_poll(void *p)
{
}
void sound_cd_get_buffer(int16_t *buffer, int len, void *p)
{
int pos, c;
ioctl_audio_callback(cd_buffer, (len * 2 * 441) / 480);
pos = 0;
for (c = 0; c < len * 2; c+=2)
{
buffer[c] += cd_buffer[((pos >> 16) << 1)] / 2;
buffer[c + 1] += cd_buffer[((pos >> 16) << 1) + 1] / 2;
pos += 60211; //(44100 * 65536) / 48000;
}
}
static uint16_t *outbuffer;
void sound_init()
{ {
initalmain(0,NULL); initalmain(0,NULL);
inital(); inital();
// install_sound(DIGI_AUTODETECT,MIDI_NONE,0);
// as=play_audio_stream(SOUNDBUFLEN,16,1,48000,255,128); outbuffer = malloc(SOUNDBUFLEN * 2 * sizeof(int16_t));
adbuffer=malloc((SOUNDBUFLEN)*2);
adbuffer2=malloc((SOUNDBUFLEN)*2); sound_add_handler(sound_cd_poll, sound_cd_get_buffer, NULL);
psgbuffer=malloc((SOUNDBUFLEN)*2);
cmsbuffer=malloc((SOUNDBUFLEN)*2*2);
gusbuffer=malloc((SOUNDBUFLEN)*2*2);
spkbuffer=malloc(((SOUNDBUFLEN)*2)+32);
outbuffer=malloc((SOUNDBUFLEN)*2*2);
} }
int adpoll=0; void sound_add_handler(void (*poll)(void *p), void (*get_buffer)(int16_t *buffer, int len, void *p), void *p)
void pollad()
{ {
/* if (adpoll>=20) return; sound_handlers[sound_handlers_num].poll = poll;
getadlibl(adbuffer+(adpoll*(48000/200)),48000/200); sound_handlers[sound_handlers_num].get_buffer = get_buffer;
getadlibr(adbuffer2+(adpoll*(48000/200)),48000/200); sound_handlers[sound_handlers_num].priv = p;
adpoll++;*/ sound_handlers_num++;
// printf("ADPOLL %i\n",adpoll);
} }
void polladlib() void sound_poll(void *priv)
{ {
getadlib(adbuffer+(adpoll),adbuffer2+(adpoll),1); int c;
adpoll++;
}
int psgpoll=0; sound_poll_time += (int)((double)TIMER_USEC * (1000000.0 / 48000.0));
void pollpsg()
{ for (c = 0; c < sound_handlers_num; c++)
if (psgpoll>=20) return; sound_handlers[c].poll(sound_handlers[c].priv);
getpsg(psgbuffer+(psgpoll*(48000/200)),48000/200);
psgpoll++;
}
int cmspoll=0;
void pollcms()
{
if (cmspoll>=20) return;
getcms(cmsbuffer+(cmspoll*(48000/200)*2),48000/200);
cmspoll++;
}
int guspoll=0;
void pollgussnd()
{
if (guspoll>=20) return;
getgus(gusbuffer+(guspoll*(48000/200)*2),48000/200);
guspoll++;
}
int spkpos=0;
int wasgated = 0;
void pollspk()
{
if (spkpos>=SOUNDBUFLEN) return;
// printf("SPeaker - %i %i %i %02X\n",speakval,gated,speakon,pit.m[2]);
if (gated)
{
if (!pit.m[2] || pit.m[2]==4)
spkbuffer[spkpos]=speakval;
else
spkbuffer[spkpos]=(speakon)?0x1400:0;
}
else
spkbuffer[spkpos]=(wasgated)?0x1400:0;
spkpos++;
wasgated=0;
} }
FILE *soundf; FILE *soundf;
static int16_t cd_buffer[(SOUNDBUFLEN) * 2]; void sound_get_buffer(void *priv)
void pollsound()
{ {
int c; int c;
int16_t t[4];
uint32_t pos; sound_get_buffer_time += (TIMER_USEC * (1000000 / 10));
// printf("Pollsound! %i\n",soundon);
// if (soundon) memset(outbuffer, 0, SOUNDBUFLEN * 2 * sizeof(int16_t));
// {
for (c=0;c<(SOUNDBUFLEN);c++) outbuffer[c<<1]=outbuffer[(c<<1)+1]=0; for (c = 0; c < sound_handlers_num; c++)
for (c=0;c<(SOUNDBUFLEN);c++) sound_handlers[c].get_buffer(outbuffer, SOUNDBUFLEN, sound_handlers[c].priv);
{
outbuffer[c<<1]+=((adbuffer[c]*mixer.fm_l)>>16); /* if (!soundf) soundf=fopen("sound.pcm","wb");
outbuffer[(c<<1)+1]+=((adbuffer[c]*mixer.fm_r)>>16); fwrite(outbuffer,(SOUNDBUFLEN)*2*2,1,soundf);*/
// if (!c) pclog("F %04X %04X %04X\n",adbuffer[c],outbuffer[c<<1],mixer.fm_l);
} if (soundon) givealbuffer(outbuffer);
addsb(outbuffer);
for (c=0;c<(SOUNDBUFLEN);c++)
{
// if (!c) pclog("M %04X ",outbuffer[c<<1]);
outbuffer[c<<1]=(outbuffer[c<<1]*mixer.master_l)>>16;
outbuffer[(c<<1)+1]=(outbuffer[(c<<1)+1]*mixer.master_r)>>16;
// if (!c) pclog("%04X %04X\n",outbuffer[c<<1],mixer.master_l);
}
if (mixer.bass_l!=8 || mixer.bass_r!=8 || mixer.treble_l!=8 || mixer.treble_r!=8)
{
for (c=0;c<(SOUNDBUFLEN);c++)
{
if (mixer.bass_l>8) outbuffer[c<<1] =(outbuffer[c<<1] +(((int16_t)low_iir(0,(float)outbuffer[c<<1]) *(mixer.bass_l-8))>>1))*((15-mixer.bass_l)+16)>>5;
if (mixer.bass_r>8) outbuffer[(c<<1)+1]=(outbuffer[(c<<1)+1]+(((int16_t)low_iir(1,(float)outbuffer[(c<<1)+1]) *(mixer.bass_r-8))>>1))*((15-mixer.bass_r)+16)>>5;
if (mixer.treble_l>8) outbuffer[c<<1] =(outbuffer[c<<1] +(((int16_t)high_iir(0,(float)outbuffer[c<<1]) *(mixer.treble_l-8))>>1))*((15-mixer.treble_l)+16)>>5;
if (mixer.treble_r>8) outbuffer[(c<<1)+1]=(outbuffer[(c<<1)+1]+(((int16_t)high_iir(1,(float)outbuffer[(c<<1)+1]) *(mixer.treble_r-8))>>1))*((15-mixer.treble_r)+16)>>5;
if (mixer.bass_l<8) outbuffer[c<<1] =(outbuffer[c<<1] +(((int16_t)low_cut_iir(0,(float)outbuffer[c<<1]) *(8-mixer.bass_l))>>1))*(mixer.bass_l+16)>>5;
if (mixer.bass_r<8) outbuffer[(c<<1)+1]=(outbuffer[(c<<1)+1]+(((int16_t)low_cut_iir(1,(float)outbuffer[(c<<1)+1]) *(8-mixer.bass_r))>>1))*(mixer.bass_r+16)>>5;
if (mixer.treble_l<8) outbuffer[c<<1] =(outbuffer[c<<1] +(((int16_t)high_cut_iir(0,(float)outbuffer[c<<1]) *(8-mixer.treble_l))>>1))*(mixer.treble_l+16)>>5;
if (mixer.treble_r<8) outbuffer[(c<<1)+1]=(outbuffer[(c<<1)+1]+(((int16_t)high_cut_iir(1,(float)outbuffer[(c<<1)+1])*(8-mixer.treble_r))>>1))*(mixer.treble_r+16)>>5;
}
}
for (c=0;c<(SOUNDBUFLEN);c++)
{
outbuffer[c<<1]+=(spkbuffer[c]/2);
outbuffer[(c<<1)+1]+=(spkbuffer[c]/2);
}
for (c=0;c<(SOUNDBUFLEN);c++)
{
outbuffer[c<<1]+=(psgbuffer[c]/2);
outbuffer[(c<<1)+1]+=(psgbuffer[c]/2);
}
for (c=0;c<((SOUNDBUFLEN)*2);c++)
outbuffer[c]+=(cmsbuffer[c]/2);
for (c=0;c<((SOUNDBUFLEN)*2);c++)
outbuffer[c]+=(gusbuffer[c]);
adddac(outbuffer);
ioctl_audio_callback(cd_buffer, ((SOUNDBUFLEN) * 2 * 441) / 480);
pos = 0;
for (c = 0; c < (SOUNDBUFLEN) * 2; c+=2)
{
outbuffer[c] += cd_buffer[((pos >> 16) << 1)] / 2;
outbuffer[c + 1] += cd_buffer[((pos >> 16) << 1) + 1] / 2;
// outbuffer[c] += (int16_t)((int32_t)cd_buffer[pos >> 16] * (65536 - (pos & 0xffff))) / 65536;
// outbuffer[c] += (int16_t)((int32_t)cd_buffer[(pos >> 16) + 1] * (pos & 0xffff)) / 65536;
pos += 60211; //(44100 * 65536) / 48000;
}
// if (!soundf) soundf=fopen("sound.pcm","wb");
// fwrite(outbuffer,(SOUNDBUFLEN)*2*2,1,soundf);
if (soundon) givealbuffer(outbuffer);
// }
// addsb(outbuffer);
// adddac(outbuffer);
adpoll=0;
psgpoll=0;
cmspoll=0;
spkpos=0;
guspoll=0;
} }
int sndcount; void sound_reset()
void pollsound60hz()
{ {
// printf("Poll sound %i\n",sndcount); timer_add(sound_poll, &sound_poll_time, TIMER_ALWAYS_ENABLED, NULL);
// pollad(); timer_add(sound_get_buffer, &sound_get_buffer_time, TIMER_ALWAYS_ENABLED, NULL);
pollpsg();
pollcms(); sound_handlers_num = 0;
pollgussnd();
sndcount++;
if (sndcount==20)
{
sndcount=0;
pollsound();
}
} }

View file

@ -1 +1,9 @@
void sound_add_handler(void (*poll)(void *p), void (*get_buffer)(int16_t *buffer, int len, void *p), void *p);
extern int wasgated; extern int wasgated;
extern int sbtype;
extern int sound_card_current;
char *sound_card_getname(int card);
void sound_card_init();

View file

@ -1,6 +1,7 @@
#define USE_OPENAL #define USE_OPENAL
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdlib.h>
#ifdef USE_OPENAL #ifdef USE_OPENAL
#include <AL/al.h> #include <AL/al.h>
#include <AL/alut.h> #include <AL/alut.h>
@ -91,7 +92,6 @@ void givealbuffer(int16_t *buf)
#ifdef USE_OPENAL #ifdef USE_OPENAL
int processed; int processed;
int state; int state;
int c;
//return; //return;

View file

@ -1,22 +1,23 @@
#include "ibm.h" #include "ibm.h"
#include "io.h" #include "io.h"
#include "mem.h" #include "mem.h"
#include "pci.h"
#include "um8881f.h" #include "um8881f.h"
static uint8_t card_16[256]; static uint8_t card_16[256];
static uint8_t card_18[256]; static uint8_t card_18[256];
void um8881f_write(int func, int addr, uint8_t val) void um8881f_write(int func, int addr, uint8_t val, void *priv)
{ {
if (addr == 0x54) if (addr == 0x54)
{ {
if ((card_16[0x54] ^ val) & 0x01) if ((card_16[0x54] ^ val) & 0x01)
{ {
if (val & 1) if (val & 1)
mem_sethandler(0xe0000, 0x10000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml); mem_sethandler(0xe0000, 0x10000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, NULL);
else else
mem_sethandler(0xf0000, 0x10000, mem_read_bios, mem_read_biosw, mem_read_biosl, NULL, NULL, NULL ); mem_sethandler(0xf0000, 0x10000, mem_read_bios, mem_read_biosw, mem_read_biosl, NULL, NULL, NULL , NULL);
} }
flushmmucache_nopc(); flushmmucache_nopc();
} }
@ -26,10 +27,10 @@ void um8881f_write(int func, int addr, uint8_t val)
{ {
switch (val & 0xc0) switch (val & 0xc0)
{ {
case 0x00: mem_sethandler(0xf0000, 0x10000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml); break; case 0x00: mem_sethandler(0xf0000, 0x10000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_ram, mem_write_ramw, mem_write_raml, NULL); break;
case 0x40: mem_sethandler(0xf0000, 0x10000, mem_read_bios, mem_read_biosw, mem_read_biosl, NULL, NULL, NULL ); break; case 0x40: mem_sethandler(0xf0000, 0x10000, mem_read_bios, mem_read_biosw, mem_read_biosl, NULL, NULL, NULL , NULL); break;
case 0x80: mem_sethandler(0xf0000, 0x10000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml); break; case 0x80: mem_sethandler(0xf0000, 0x10000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, NULL); break;
case 0xc0: mem_sethandler(0xf0000, 0x10000, mem_read_ram, mem_read_ramw, mem_read_raml, NULL, NULL, NULL ); break; case 0xc0: mem_sethandler(0xf0000, 0x10000, mem_read_ram, mem_read_ramw, mem_read_raml, NULL, NULL, NULL , NULL); break;
} }
shadowbios = val & 0x80; shadowbios = val & 0x80;
shadowbios_write = !(val & 0x40); shadowbios_write = !(val & 0x40);
@ -40,18 +41,18 @@ void um8881f_write(int func, int addr, uint8_t val)
card_16[addr] = val; card_16[addr] = val;
} }
uint8_t um8881f_read(int func, int addr) uint8_t um8881f_read(int func, int addr, void *priv)
{ {
return card_16[addr]; return card_16[addr];
} }
void um8886f_write(int func, int addr, uint8_t val) void um8886f_write(int func, int addr, uint8_t val, void *priv)
{ {
if (addr >= 4) if (addr >= 4)
card_18[addr] = val; card_18[addr] = val;
} }
uint8_t um8886f_read(int func, int addr) uint8_t um8886f_read(int func, int addr, void *priv)
{ {
return card_18[addr]; return card_18[addr];
} }
@ -60,8 +61,8 @@ uint8_t um8886f_read(int func, int addr)
void um8881f_init() void um8881f_init()
{ {
pci_add_specific(16, um8881f_read, um8881f_write); pci_add_specific(16, um8881f_read, um8881f_write, NULL);
pci_add_specific(18, um8886f_read, um8886f_write); pci_add_specific(18, um8886f_read, um8886f_write, NULL);
card_16[0] = card_18[0] = 0x60; /*UMC*/ card_16[0] = card_18[0] = 0x60; /*UMC*/
card_16[1] = card_18[1] = 0x10; card_16[1] = card_18[1] = 0x10;

View file

@ -1,8 +1,15 @@
/*CGA emulation*/ /*CGA emulation*/
#include <math.h>
#include "ibm.h" #include "ibm.h"
#include "io.h"
#include "mem.h"
#include "timer.h"
#include "video.h" #include "video.h"
#include "vid_cga.h"
void cga_out(uint16_t addr, uint8_t val) void cga_recalctimings();
void cga_out(uint16_t addr, uint8_t val, void *priv)
{ {
uint8_t old; uint8_t old;
// pclog("CGA_OUT %04X %02X\n", addr, val); // pclog("CGA_OUT %04X %02X\n", addr, val);
@ -32,7 +39,7 @@ void cga_out(uint16_t addr, uint8_t val)
} }
} }
uint8_t cga_in(uint16_t addr) uint8_t cga_in(uint16_t addr, void *priv)
{ {
// pclog("CGA_IN %04X\n", addr); // pclog("CGA_IN %04X\n", addr);
switch (addr) switch (addr)
@ -49,7 +56,7 @@ uint8_t cga_in(uint16_t addr)
extern uint8_t charbuffer[256]; extern uint8_t charbuffer[256];
void cga_write(uint32_t addr, uint8_t val) void cga_write(uint32_t addr, uint8_t val, void *priv)
{ {
// pclog("CGA_WRITE %04X %02X\n", addr, val); // pclog("CGA_WRITE %04X %02X\n", addr, val);
vram[addr&0x3FFF]=val; vram[addr&0x3FFF]=val;
@ -58,7 +65,7 @@ void cga_write(uint32_t addr, uint8_t val)
cycles -= 4; cycles -= 4;
} }
uint8_t cga_read(uint32_t addr) uint8_t cga_read(uint32_t addr, void *priv)
{ {
cycles -= 4; cycles -= 4;
charbuffer[ ((int)(((dispontime - vidtime) * 2) / CGACONST)) & 0xfc] = vram[addr&0x3FFF]; charbuffer[ ((int)(((dispontime - vidtime) * 2) / CGACONST)) & 0xfc] = vram[addr&0x3FFF];
@ -69,22 +76,25 @@ uint8_t cga_read(uint32_t addr)
void cga_recalctimings() void cga_recalctimings()
{ {
double _dispontime, _dispofftime;
pclog("Recalc - %i %i %i\n", crtc[0], crtc[1], cgamode & 1); pclog("Recalc - %i %i %i\n", crtc[0], crtc[1], cgamode & 1);
if (cgamode&1) if (cgamode&1)
{ {
disptime=crtc[0]+1; disptime=crtc[0]+1;
dispontime=crtc[1]; _dispontime=crtc[1];
} }
else else
{ {
disptime=(crtc[0]+1)<<1; disptime=(crtc[0]+1)<<1;
dispontime=crtc[1]<<1; _dispontime=crtc[1]<<1;
} }
dispofftime=disptime-dispontime; _dispofftime=disptime-_dispontime;
// printf("%i %f %f %f %i %i\n",cgamode&1,disptime,dispontime,dispofftime,crtc[0],crtc[1]); // printf("%i %f %f %f %i %i\n",cgamode&1,disptime,dispontime,dispofftime,crtc[0],crtc[1]);
dispontime*=CGACONST; _dispontime*=CGACONST;
dispofftime*=CGACONST; _dispofftime*=CGACONST;
// printf("Timings - on %f off %f frame %f second %f\n",dispontime,dispofftime,(dispontime+dispofftime)*262.0,(dispontime+dispofftime)*262.0*59.92); // printf("Timings - on %f off %f frame %f second %f\n",dispontime,dispofftime,(dispontime+dispofftime)*262.0,(dispontime+dispofftime)*262.0*59.92);
dispontime = (int)(_dispontime * (1 << TIMER_SHIFT));
dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT));
} }
static int linepos,displine; static int linepos,displine;
@ -92,7 +102,7 @@ static int sc,vc;
static int cgadispon; static int cgadispon;
static int con,coff,cursoron,cgablink; static int con,coff,cursoron,cgablink;
static int vsynctime,vadj; static int vsynctime,vadj;
static uint16_t ma,maback,ca; static uint16_t ma,maback;
static int oddeven = 0; static int oddeven = 0;
static int ntsc_col[8][8]= static int ntsc_col[8][8]=
@ -117,7 +127,7 @@ void cga_poll()
int x,c; int x,c;
int oldvc; int oldvc;
uint8_t chr,attr; uint8_t chr,attr;
uint16_t dat,dat2,dat3,dat4; uint16_t dat;
int cols[4]; int cols[4];
int col; int col;
int oldsc; int oldsc;
@ -467,7 +477,7 @@ int cga_init()
i_filt[c]=512.0*cos((3.14*(cga_tint+c*4)/16.0) - 33.0/180.0); i_filt[c]=512.0*cos((3.14*(cga_tint+c*4)/16.0) - 33.0/180.0);
q_filt[c]=512.0*sin((3.14*(cga_tint+c*4)/16.0) - 33.0/180.0); q_filt[c]=512.0*sin((3.14*(cga_tint+c*4)/16.0) - 33.0/180.0);
} }
mem_sethandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL); mem_sethandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL);
return 0; return 0;
} }

View file

@ -1,7 +1,7 @@
int cga_init(); int cga_init();
void cga_out(uint16_t addr, uint8_t val); void cga_out(uint16_t addr, uint8_t val, void *priv);
uint8_t cga_in(uint16_t addr); uint8_t cga_in(uint16_t addr, void *priv);
void cga_poll(); void cga_poll();
void cga_write(uint32_t addr, uint8_t val); void cga_write(uint32_t addr, uint8_t val, void *priv);
uint8_t cga_read(uint32_t addr); uint8_t cga_read(uint32_t addr, void *priv);
void cga_recalctimings(); void cga_recalctimings();

View file

@ -1,10 +1,11 @@
/*EGA emulation*/ /*EGA emulation*/
#include "ibm.h" #include "ibm.h"
#include "io.h"
#include "mem.h"
#include "timer.h"
#include "video.h" #include "video.h"
#include "vid_ega.h"
void ega_recalctimings(); #include "vid_svga.h"
void ega_write(uint32_t addr, uint8_t val);
uint8_t ega_read(uint32_t addr);
extern uint8_t edatlookup[4][4]; extern uint8_t edatlookup[4][4];
@ -16,7 +17,7 @@ static uint8_t ega_rotate[8][256];
/*3C2 controls default mode on EGA. On VGA, it determines monitor type (mono or colour)*/ /*3C2 controls default mode on EGA. On VGA, it determines monitor type (mono or colour)*/
int egaswitchread,egaswitches=9; /*7=CGA mode (200 lines), 9=EGA mode (350 lines), 8=EGA mode (200 lines)*/ int egaswitchread,egaswitches=9; /*7=CGA mode (200 lines), 9=EGA mode (350 lines), 8=EGA mode (200 lines)*/
void ega_out(uint16_t addr, uint8_t val) void ega_out(uint16_t addr, uint8_t val, void *priv)
{ {
int c; int c;
uint8_t o,old; uint8_t o,old;
@ -73,21 +74,21 @@ void ega_out(uint16_t addr, uint8_t val)
case 4: readplane=val&3; break; case 4: readplane=val&3; break;
case 5: writemode=val&3; readmode=val&8; break; case 5: writemode=val&3; readmode=val&8; break;
case 6: case 6:
mem_removehandler(0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL); mem_removehandler(0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL);
// pclog("Write mapping %02X\n", val); // pclog("Write mapping %02X\n", val);
switch (val&0xC) switch (val&0xC)
{ {
case 0x0: /*128k at A0000*/ case 0x0: /*128k at A0000*/
mem_sethandler(0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL); mem_sethandler(0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL);
break; break;
case 0x4: /*64k at A0000*/ case 0x4: /*64k at A0000*/
mem_sethandler(0xa0000, 0x10000, ega_read, NULL, NULL, ega_write, NULL, NULL); mem_sethandler(0xa0000, 0x10000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL);
break; break;
case 0x8: /*32k at B0000*/ case 0x8: /*32k at B0000*/
mem_sethandler(0xb0000, 0x08000, ega_read, NULL, NULL, ega_write, NULL, NULL); mem_sethandler(0xb0000, 0x08000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL);
break; break;
case 0xC: /*32k at B8000*/ case 0xC: /*32k at B8000*/
mem_sethandler(0xb8000, 0x08000, ega_read, NULL, NULL, ega_write, NULL, NULL); mem_sethandler(0xb8000, 0x08000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL);
break; break;
} }
@ -114,9 +115,8 @@ void ega_out(uint16_t addr, uint8_t val)
} }
} }
uint8_t ega_in(uint16_t addr) uint8_t ega_in(uint16_t addr, void *priv)
{ {
uint8_t temp;
if ((addr&0xFFF0) == 0x3B0) addr |= 0x20; if ((addr&0xFFF0) == 0x3B0) addr |= 0x20;
switch (addr) switch (addr)
{ {
@ -161,8 +161,9 @@ static int scrollcache;
void ega_recalctimings() void ega_recalctimings()
{ {
float crtcconst; double _dispontime, _dispofftime;
int temp; double crtcconst;
ega_vtotal=crtc[6]; ega_vtotal=crtc[6];
ega_dispend=crtc[0x12]; ega_dispend=crtc[0x12];
ega_vsyncstart=crtc[0x10]; ega_vsyncstart=crtc[0x10];
@ -195,14 +196,16 @@ void ega_recalctimings()
else crtcconst=(seqregs[1]&1)?(CGACONST*(8.0/9.0)):CGACONST; else crtcconst=(seqregs[1]&1)?(CGACONST*(8.0/9.0)):CGACONST;
disptime=crtc[0]+2; disptime=crtc[0]+2;
dispontime=crtc[1]+1; _dispontime=crtc[1]+1;
printf("Disptime %f dispontime %f hdisp %i\n",disptime,dispontime,crtc[1]*8); printf("Disptime %f dispontime %f hdisp %i\n",disptime,_dispontime,crtc[1]*8);
if (seqregs[1]&8) { disptime*=2; dispontime*=2; } if (seqregs[1]&8) { disptime*=2; _dispontime*=2; }
dispofftime=disptime-dispontime; _dispofftime=disptime-_dispontime;
dispontime*=crtcconst; _dispontime*=crtcconst;
dispofftime*=crtcconst; _dispofftime*=crtcconst;
dispontime = (int)(_dispontime * (1 << TIMER_SHIFT));
dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT));
// printf("EGA horiz total %i display end %i clock rate %i vidclock %i %i\n",crtc[0],crtc[1],egaswitchread,vidclock,((ega3c2>>2)&3) | ((tridentnewctrl2<<2)&4)); // printf("EGA horiz total %i display end %i clock rate %i vidclock %i %i\n",crtc[0],crtc[1],egaswitchread,vidclock,((ega3c2>>2)&3) | ((tridentnewctrl2<<2)&4));
// printf("EGA vert total %i display end %i max row %i vsync %i\n",ega_vtotal,ega_dispend,(crtc[9]&31)+1,ega_vsyncstart); // printf("EGA vert total %i display end %i max row %i vsync %i\n",ega_vtotal,ega_dispend,(crtc[9]&31)+1,ega_vsyncstart);
@ -525,11 +528,9 @@ void ega_poll()
} }
void ega_write(uint32_t addr, uint8_t val) void ega_write(uint32_t addr, uint8_t val, void *priv)
{ {
int x,y; uint8_t vala,valb,valc,vald;
char s[2]={0,0};
uint8_t vala,valb,valc,vald,wm=writemask;
egawrites++; egawrites++;
cycles -= video_timing_b; cycles -= video_timing_b;
@ -647,10 +648,9 @@ void ega_write(uint32_t addr, uint8_t val)
} }
} }
uint8_t ega_read(uint32_t addr) uint8_t ega_read(uint32_t addr, void *priv)
{ {
uint8_t temp,temp2,temp3,temp4; uint8_t temp,temp2,temp3,temp4;
uint32_t addr2;
egareads++; egareads++;
cycles -= video_timing_b; cycles -= video_timing_b;
cycles_lost += video_timing_b; cycles_lost += video_timing_b;

View file

@ -1,7 +1,7 @@
int ega_init(); int ega_init();
void ega_out(uint16_t addr, uint8_t val); void ega_out(uint16_t addr, uint8_t val, void *priv);
uint8_t ega_in(uint16_t addr); uint8_t ega_in(uint16_t addr, void *priv);
void ega_poll(); void ega_poll();
void ega_recalctimings(); void ega_recalctimings();
void ega_write(uint32_t addr, uint8_t val); void ega_write(uint32_t addr, uint8_t val, void *priv);
uint8_t ega_read(uint32_t addr); uint8_t ega_read(uint32_t addr, void *priv);

View file

@ -1,5 +1,6 @@
/*ET4000 emulation*/ /*ET4000 emulation*/
#include "ibm.h" #include "ibm.h"
#include "io.h"
#include "video.h" #include "video.h"
#include "vid_svga.h" #include "vid_svga.h"
#include "vid_unk_ramdac.h" #include "vid_unk_ramdac.h"
@ -7,7 +8,7 @@
int et4k_b8000; int et4k_b8000;
void et4000_out(uint16_t addr, uint8_t val) void et4000_out(uint16_t addr, uint8_t val, void *priv)
{ {
uint8_t old; uint8_t old;
@ -18,7 +19,7 @@ void et4000_out(uint16_t addr, uint8_t val)
switch (addr) switch (addr)
{ {
case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
unk_ramdac_out(addr,val); unk_ramdac_out(addr, val, NULL);
return; return;
case 0x3CD: /*Banking*/ case 0x3CD: /*Banking*/
@ -57,13 +58,11 @@ void et4000_out(uint16_t addr, uint8_t val)
if (val==0x29) svgaon=0; if (val==0x29) svgaon=0;
break; break;
} }
svga_out(addr,val); svga_out(addr, val, priv);
} }
uint8_t et4000_in(uint16_t addr) uint8_t et4000_in(uint16_t addr, void *priv)
{ {
uint8_t temp;
if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga_miscout&1)) addr ^= 0x60; if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga_miscout&1)) addr ^= 0x60;
if (addr != 0x3da) pclog("IN ET4000 %04X\n", addr); if (addr != 0x3da) pclog("IN ET4000 %04X\n", addr);
@ -75,7 +74,7 @@ uint8_t et4000_in(uint16_t addr)
break; break;
case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
return unk_ramdac_in(addr); return unk_ramdac_in(addr, NULL);
case 0x3CD: /*Banking*/ case 0x3CD: /*Banking*/
return svgaseg; return svgaseg;
@ -84,7 +83,7 @@ uint8_t et4000_in(uint16_t addr)
case 0x3D5: case 0x3D5:
return crtc[crtcreg]; return crtc[crtcreg];
} }
return svga_in(addr); return svga_in(addr, priv);
} }
void et4000_recalctimings() void et4000_recalctimings()
@ -98,6 +97,7 @@ void et4000_recalctimings()
// if (crtc[0x3F]&0x80) svga_rowoffset+=0x100; // if (crtc[0x3F]&0x80) svga_rowoffset+=0x100;
if (crtc[0x3F]&1) svga_htotal+=256; if (crtc[0x3F]&1) svga_htotal+=256;
if (attrregs[0x16]&0x20) svga_hdisp<<=1; if (attrregs[0x16]&0x20) svga_hdisp<<=1;
// pclog("Rowoffset %i\n",svga_rowoffset); // pclog("Rowoffset %i\n",svga_rowoffset);
switch (((svga_miscout >> 2) & 3) | ((crtc[0x34] << 1) & 4)) switch (((svga_miscout >> 2) & 3) | ((crtc[0x34] << 1) & 4))

View file

@ -5,6 +5,8 @@
*/ */
#include "ibm.h" #include "ibm.h"
#include "io.h"
#include "pci.h"
#include "video.h" #include "video.h"
#include "vid_svga.h" #include "vid_svga.h"
#include "vid_icd2061.h" #include "vid_icd2061.h"
@ -15,14 +17,14 @@ int et4k_b8000;
void et4000w32p_recalcmapping(); void et4000w32p_recalcmapping();
uint8_t et4000w32p_mmu_read(uint32_t addr); uint8_t et4000w32p_mmu_read(uint32_t addr, void *priv);
void et4000w32p_mmu_write(uint32_t addr, uint8_t val); void et4000w32p_mmu_write(uint32_t addr, uint8_t val, void *priv);
static int et4000w32p_index; static int et4000w32p_index;
static uint8_t et4000w32p_regs[256]; static uint8_t et4000w32p_regs[256];
static uint32_t et4000w32p_linearbase, et4000w32p_linearbase_old; static uint32_t et4000w32p_linearbase, et4000w32p_linearbase_old;
void et4000w32p_out(uint16_t addr, uint8_t val) void et4000w32p_out(uint16_t addr, uint8_t val, void *priv)
{ {
uint8_t old; uint8_t old;
@ -39,7 +41,7 @@ void et4000w32p_out(uint16_t addr, uint8_t val)
break; break;
case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
stg_ramdac_out(addr,val); stg_ramdac_out(addr, val, NULL);
return; return;
case 0x3CB: /*Banking extension*/ case 0x3CB: /*Banking extension*/
@ -111,10 +113,10 @@ void et4000w32p_out(uint16_t addr, uint8_t val)
return; return;
} }
svga_out(addr,val); svga_out(addr, val, NULL);
} }
uint8_t et4000w32p_in(uint16_t addr) uint8_t et4000w32p_in(uint16_t addr, void *priv)
{ {
uint8_t temp; uint8_t temp;
// if (addr==0x3DA) pclog("In 3DA %04X(%06X):%04X\n",CS,cs,pc); // if (addr==0x3DA) pclog("In 3DA %04X(%06X):%04X\n",CS,cs,pc);
@ -132,7 +134,7 @@ uint8_t et4000w32p_in(uint16_t addr)
break; break;
case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
return stg_ramdac_in(addr); return stg_ramdac_in(addr, NULL);
case 0x3CB: case 0x3CB:
return svgaseg2; return svgaseg2;
@ -166,15 +168,14 @@ uint8_t et4000w32p_in(uint16_t addr)
} }
return et4000w32p_regs[et4000w32p_index]; return et4000w32p_regs[et4000w32p_index];
} }
return svga_in(addr); return svga_in(addr, NULL);
} }
void et4000w32p_recalctimings() void et4000w32p_recalctimings()
{ {
double clk;
// pclog("Recalc %08X ",svga_ma); // pclog("Recalc %08X ",svga_ma);
svga_ma|=(crtc[0x33]&0x7)<<16; svga_ma|=(crtc[0x33]&0x7)<<16;
pclog("SVGA_MA %08X %i\n", svga_ma, (svga_miscout >> 2) & 3); // pclog("SVGA_MA %08X %i\n", svga_ma, (svga_miscout >> 2) & 3);
if (crtc[0x35]&2) svga_vtotal+=0x400; if (crtc[0x35]&2) svga_vtotal+=0x400;
if (crtc[0x35]&4) svga_dispend+=0x400; if (crtc[0x35]&4) svga_dispend+=0x400;
if (crtc[0x35]&8) svga_vsyncstart+=0x400; if (crtc[0x35]&8) svga_vsyncstart+=0x400;
@ -205,12 +206,12 @@ void et4000w32p_recalcmapping()
{ {
int map; int map;
mem_removehandler(et4000w32p_linearbase_old, 0x200000, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear); mem_removehandler(et4000w32p_linearbase_old, 0x200000, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL);
mem_removehandler(0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); mem_removehandler( 0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL);
mem_removehandler(0xb0000, 0x10000, et4000w32p_mmu_read, NULL, NULL, et4000w32p_mmu_write, NULL, NULL); mem_removehandler( 0xb0000, 0x10000, et4000w32p_mmu_read, NULL, NULL, et4000w32p_mmu_write, NULL, NULL, NULL);
if (crtc[0x36] & 0x10) /*Linear frame buffer*/ if (crtc[0x36] & 0x10) /*Linear frame buffer*/
{ {
mem_sethandler(et4000w32p_linearbase, 0x200000, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear); mem_sethandler(et4000w32p_linearbase, 0x200000, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL);
} }
else else
{ {
@ -220,28 +221,28 @@ void et4000w32p_recalcmapping()
switch (map) switch (map)
{ {
case 0x0: case 0x4: case 0x8: case 0xC: /*128k at A0000*/ case 0x0: case 0x4: case 0x8: case 0xC: /*128k at A0000*/
mem_sethandler(0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); mem_sethandler(0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL);
break; break;
case 0x1: /*64k at A0000*/ case 0x1: /*64k at A0000*/
mem_sethandler(0xa0000, 0x10000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); mem_sethandler(0xa0000, 0x10000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL);
break; break;
case 0x2: /*32k at B0000*/ case 0x2: /*32k at B0000*/
mem_sethandler(0xb0000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); mem_sethandler(0xb0000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL);
break; break;
case 0x3: /*32k at B8000*/ case 0x3: /*32k at B8000*/
mem_sethandler(0xb8000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); mem_sethandler(0xb8000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL);
break; break;
case 0x5: case 0x9: case 0xD: /*64k at A0000, MMU at B8000*/ case 0x5: case 0x9: case 0xD: /*64k at A0000, MMU at B8000*/
mem_sethandler(0xa0000, 0x10000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); mem_sethandler(0xa0000, 0x10000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL);
mem_sethandler(0xb8000, 0x08000, et4000w32p_mmu_read, NULL, NULL, et4000w32p_mmu_write, NULL, NULL); mem_sethandler(0xb8000, 0x08000, et4000w32p_mmu_read, NULL, NULL, et4000w32p_mmu_write, NULL, NULL, NULL);
break; break;
case 0x6: case 0xA: case 0xE: /*32k at B0000, MMU at A8000*/ case 0x6: case 0xA: case 0xE: /*32k at B0000, MMU at A8000*/
mem_sethandler(0xa8000, 0x08000, et4000w32p_mmu_read, NULL, NULL, et4000w32p_mmu_write, NULL, NULL); mem_sethandler(0xa8000, 0x08000, et4000w32p_mmu_read, NULL, NULL, et4000w32p_mmu_write, NULL, NULL, NULL);
mem_sethandler(0xb0000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); mem_sethandler(0xb0000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL);
break; break;
case 0x7: case 0xB: case 0xF: /*32k at B8000, MMU at A8000*/ case 0x7: case 0xB: case 0xF: /*32k at B8000, MMU at A8000*/
mem_sethandler(0xa8000, 0x08000, et4000w32p_mmu_read, NULL, NULL, et4000w32p_mmu_write, NULL, NULL); mem_sethandler(0xa8000, 0x08000, et4000w32p_mmu_read, NULL, NULL, et4000w32p_mmu_write, NULL, NULL, NULL);
mem_sethandler(0xb8000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); mem_sethandler(0xb8000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL);
break; break;
} }
// pclog("ET4K map %02X\n", map); // pclog("ET4K map %02X\n", map);
@ -295,7 +296,7 @@ void et4000w32_reset()
void et4000w32_blit_start(); void et4000w32_blit_start();
void et4000w32_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input); void et4000w32_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input);
void et4000w32p_mmu_write(uint32_t addr, uint8_t val) void et4000w32p_mmu_write(uint32_t addr, uint8_t val, void *priv)
{ {
int bank; int bank;
// pclog("ET4K write %08X %02X %02X %04X(%08X):%08X\n",addr,val,acl.status,acl.internal.ctrl_routing,CS,cs,pc); // pclog("ET4K write %08X %02X %02X %04X(%08X):%08X\n",addr,val,acl.status,acl.internal.ctrl_routing,CS,cs,pc);
@ -402,7 +403,7 @@ void et4000w32p_mmu_write(uint32_t addr, uint8_t val)
} }
} }
uint8_t et4000w32p_mmu_read(uint32_t addr) uint8_t et4000w32p_mmu_read(uint32_t addr, void *priv)
{ {
int bank; int bank;
uint8_t temp; uint8_t temp;
@ -482,6 +483,7 @@ uint8_t et4000w32p_mmu_read(uint32_t addr)
} }
return 0xFF; return 0xFF;
} }
return 0xff;
} }
int et4000w32_max_x[8]={0,0,4,8,16,32,64,0x70000000}; int et4000w32_max_x[8]={0,0,4,8,16,32,64,0x70000000};
@ -846,7 +848,7 @@ void et4000w32p_cursor_draw(int displine)
svga_hwcursor_latch.addr += 16; svga_hwcursor_latch.addr += 16;
} }
uint8_t et4000w32p_pci_read(int func, int addr) uint8_t et4000w32p_pci_read(int func, int addr, void *priv)
{ {
pclog("ET4000 PCI read %08X\n", addr); pclog("ET4000 PCI read %08X\n", addr);
switch (addr) switch (addr)
@ -880,7 +882,7 @@ uint8_t et4000w32p_pci_read(int func, int addr)
return 0; return 0;
} }
void et4000w32p_pci_write(int func, int addr, uint8_t val) void et4000w32p_pci_write(int func, int addr, uint8_t val, void *priv)
{ {
switch (addr) switch (addr)
{ {
@ -893,16 +895,16 @@ int et4000w32p_init()
svga_recalctimings_ex = et4000w32p_recalctimings; svga_recalctimings_ex = et4000w32p_recalctimings;
svga_hwcursor_draw = et4000w32p_cursor_draw; svga_hwcursor_draw = et4000w32p_cursor_draw;
io_sethandler(0x210A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL); io_sethandler(0x210A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, NULL);
io_sethandler(0x211A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL); io_sethandler(0x211A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, NULL);
io_sethandler(0x212A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL); io_sethandler(0x212A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, NULL);
io_sethandler(0x213A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL); io_sethandler(0x213A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, NULL);
io_sethandler(0x214A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL); io_sethandler(0x214A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, NULL);
io_sethandler(0x215A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL); io_sethandler(0x215A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, NULL);
io_sethandler(0x216A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL); io_sethandler(0x216A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, NULL);
io_sethandler(0x217A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL); io_sethandler(0x217A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, NULL);
pci_add(et4000w32p_pci_read, et4000w32p_pci_write); pci_add(et4000w32p_pci_read, et4000w32p_pci_write, NULL);
svga_vram_limit = 2 << 20; /*2mb - chip supports 4mb but can't map both 4mb linear frame buffer and accelerator registers*/ svga_vram_limit = 2 << 20; /*2mb - chip supports 4mb but can't map both 4mb linear frame buffer and accelerator registers*/

View file

@ -1,15 +1,17 @@
/*Hercules emulation*/ /*Hercules emulation*/
#include "ibm.h" #include "ibm.h"
#include "mem.h"
#include "timer.h"
#include "video.h" #include "video.h"
void hercules_recalctimings(); void hercules_recalctimings();
void hercules_write(uint32_t addr, uint8_t val); void hercules_write(uint32_t addr, uint8_t val, void *priv);
uint8_t hercules_read(uint32_t addr); uint8_t hercules_read(uint32_t addr, void *priv);
static uint8_t hercules_ctrl, hercules_ctrl2, hercules_stat; static uint8_t hercules_ctrl, hercules_ctrl2, hercules_stat;
uint8_t crtcm[32],crtcmreg; uint8_t crtcm[32],crtcmreg;
void hercules_out(uint16_t addr, uint8_t val) void hercules_out(uint16_t addr, uint8_t val, void *priv)
{ {
// pclog("Herc out %04X %02X\n",addr,val); // pclog("Herc out %04X %02X\n",addr,val);
switch (addr) switch (addr)
@ -37,7 +39,7 @@ void hercules_out(uint16_t addr, uint8_t val)
} }
} }
uint8_t hercules_in(uint16_t addr) uint8_t hercules_in(uint16_t addr, void *priv)
{ {
// pclog("Herc in %04X %02X %04X:%04X %04X\n",addr,(hercules_stat & 0xF) | ((hercules_stat & 8) << 4),CS,pc,CX); // pclog("Herc in %04X %02X %04X:%04X %04X\n",addr,(hercules_stat & 0xF) | ((hercules_stat & 8) << 4),CS,pc,CX);
switch (addr) switch (addr)
@ -49,33 +51,37 @@ uint8_t hercules_in(uint16_t addr)
case 0x3BA: case 0x3BA:
return (hercules_stat & 0xF) | ((hercules_stat & 8) << 4); return (hercules_stat & 0xF) | ((hercules_stat & 8) << 4);
} }
return 0xff;
} }
void hercules_write(uint32_t addr, uint8_t val) void hercules_write(uint32_t addr, uint8_t val, void *priv)
{ {
// pclog("Herc write %08X %02X\n",addr,val); // pclog("Herc write %08X %02X\n",addr,val);
vram[addr&0xFFFF]=val; vram[addr&0xFFFF]=val;
} }
uint8_t hercules_read(uint32_t addr) uint8_t hercules_read(uint32_t addr, void *priv)
{ {
return vram[addr&0xFFFF]; return vram[addr&0xFFFF];
} }
void hercules_recalctimings() void hercules_recalctimings()
{ {
double _dispontime, _dispofftime;
disptime=crtc[0]+1; disptime=crtc[0]+1;
dispontime=crtc[1]; _dispontime=crtc[1];
dispofftime=disptime-dispontime; _dispofftime=disptime-_dispontime;
dispontime*=MDACONST; _dispontime*=MDACONST;
dispofftime*=MDACONST; _dispofftime*=MDACONST;
dispontime = (int)(_dispontime * (1 << TIMER_SHIFT));
dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT));
} }
int mdacols[256][2][2]; int mdacols[256][2][2];
static int linepos,displine; static int linepos,displine;
static int vc,sc; static int vc,sc;
static uint16_t ma,maback,ca; static uint16_t ma,maback;
static int con,coff,cursoron; static int con,coff,cursoron;
static int cgadispon,cgablink; static int cgadispon,cgablink;
static int vsynctime,vadj; static int vsynctime,vadj;
@ -87,9 +93,8 @@ void hercules_poll()
int x,c; int x,c;
int oldvc; int oldvc;
uint8_t chr,attr; uint8_t chr,attr;
uint16_t dat,dat2,dat3,dat4; uint16_t dat;
int cols[4]; int cols[4];
int col;
int oldsc; int oldsc;
int blink; int blink;
if (!linepos) if (!linepos)
@ -264,7 +269,7 @@ void hercules_poll()
int hercules_init() int hercules_init()
{ {
mem_sethandler(0xb0000, 0x08000, hercules_read, NULL, NULL, hercules_write, NULL, NULL); mem_sethandler(0xb0000, 0x08000, hercules_read, NULL, NULL, hercules_write, NULL, NULL, NULL);
return 0; return 0;
} }

View file

@ -1,5 +1,8 @@
/*MDA emulation*/ /*MDA emulation*/
#include "ibm.h" #include "ibm.h"
#include "io.h"
#include "mem.h"
#include "timer.h"
#include "video.h" #include "video.h"
void mda_recalctimings(); void mda_recalctimings();
@ -7,7 +10,7 @@ void mda_recalctimings();
static uint8_t mda_ctrl,mda_stat; static uint8_t mda_ctrl,mda_stat;
uint8_t crtcm[32],crtcmreg; uint8_t crtcm[32],crtcmreg;
void mda_out(uint16_t addr, uint8_t val) void mda_out(uint16_t addr, uint8_t val, void *priv)
{ {
switch (addr) switch (addr)
{ {
@ -29,7 +32,7 @@ void mda_out(uint16_t addr, uint8_t val)
} }
} }
uint8_t mda_in(uint16_t addr) uint8_t mda_in(uint16_t addr, void *priv)
{ {
switch (addr) switch (addr)
{ {
@ -40,32 +43,36 @@ uint8_t mda_in(uint16_t addr)
case 0x3BA: case 0x3BA:
return mda_stat | 0xF0; return mda_stat | 0xF0;
} }
return 0xff;
} }
void mda_write(uint32_t addr, uint8_t val) void mda_write(uint32_t addr, uint8_t val, void *priv)
{ {
vram[addr&0xFFF]=val; vram[addr&0xFFF]=val;
} }
uint8_t mda_read(uint32_t addr) uint8_t mda_read(uint32_t addr, void *priv)
{ {
return vram[addr&0xFFF]; return vram[addr&0xFFF];
} }
void mda_recalctimings() void mda_recalctimings()
{ {
double _dispontime, _dispofftime;
disptime=crtc[0]+1; disptime=crtc[0]+1;
dispontime=crtc[1]; _dispontime=crtc[1];
dispofftime=disptime-dispontime; _dispofftime=disptime-_dispontime;
dispontime*=MDACONST; _dispontime*=MDACONST;
dispofftime*=MDACONST; _dispofftime*=MDACONST;
dispontime = (int)(_dispontime * (1 << TIMER_SHIFT));
dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT));
} }
int mdacols[256][2][2]; int mdacols[256][2][2];
static int linepos,displine; static int linepos,displine;
static int vc,sc; static int vc,sc;
static uint16_t ma,maback,ca; static uint16_t ma,maback;
static int con,coff,cursoron; static int con,coff,cursoron;
static int cgadispon,cgablink; static int cgadispon,cgablink;
static int vsynctime,vadj; static int vsynctime,vadj;
@ -77,9 +84,7 @@ void mda_poll()
int x,c; int x,c;
int oldvc; int oldvc;
uint8_t chr,attr; uint8_t chr,attr;
uint16_t dat,dat2,dat3,dat4;
int cols[4]; int cols[4];
int col;
int oldsc; int oldsc;
int blink; int blink;
if (!linepos) if (!linepos)
@ -227,7 +232,7 @@ void mda_poll()
int mda_init() int mda_init()
{ {
mem_sethandler(0xb0000, 0x08000, mda_read, NULL, NULL, mda_write, NULL, NULL); mem_sethandler(0xb0000, 0x08000, mda_read, NULL, NULL, mda_write, NULL, NULL, NULL);
return 0; return 0;
} }

View file

@ -1,12 +1,17 @@
/*Olivetti M24 video emulation /*Olivetti M24 video emulation
Essentially double-res CGA*/ Essentially double-res CGA*/
#include "ibm.h" #include "ibm.h"
#include "io.h"
#include "mem.h"
#include "timer.h"
#include "video.h" #include "video.h"
void m24_recalctimings();
static uint8_t m24_ctrl; static uint8_t m24_ctrl;
static uint32_t m24_base; static uint32_t m24_base;
void m24_out(uint16_t addr, uint8_t val) void m24_out(uint16_t addr, uint8_t val, void *priv)
{ {
uint8_t old; uint8_t old;
switch (addr) switch (addr)
@ -39,7 +44,7 @@ void m24_out(uint16_t addr, uint8_t val)
} }
} }
uint8_t m24_in(uint16_t addr) uint8_t m24_in(uint16_t addr, void *priv)
{ {
switch (addr) switch (addr)
{ {
@ -55,35 +60,38 @@ uint8_t m24_in(uint16_t addr)
static uint8_t charbuffer[256]; static uint8_t charbuffer[256];
void m24_write(uint32_t addr, uint8_t val) void m24_write(uint32_t addr, uint8_t val, void *priv)
{ {
vram[addr & 0x7FFF]=val; vram[addr & 0x7FFF]=val;
charbuffer[ ((int)(((dispontime - vidtime) * 2) / (CGACONST / 2))) & 0xfc] = val; charbuffer[ ((int)(((dispontime - vidtime) * 2) / (CGACONST / 2))) & 0xfc] = val;
charbuffer[(((int)(((dispontime - vidtime) * 2) / (CGACONST / 2))) & 0xfc) | 1] = val; charbuffer[(((int)(((dispontime - vidtime) * 2) / (CGACONST / 2))) & 0xfc) | 1] = val;
} }
uint8_t m24_read(uint32_t addr) uint8_t m24_read(uint32_t addr, void *priv)
{ {
return vram[addr & 0x7FFF]; return vram[addr & 0x7FFF];
} }
void m24_recalctimings() void m24_recalctimings()
{ {
double _dispontime, _dispofftime;
if (cgamode & 1) if (cgamode & 1)
{ {
disptime = crtc[0] + 1; disptime = crtc[0] + 1;
dispontime = crtc[1]; _dispontime = crtc[1];
} }
else else
{ {
disptime = (crtc[0] + 1) << 1; disptime = (crtc[0] + 1) << 1;
dispontime = crtc[1] << 1; _dispontime = crtc[1] << 1;
} }
dispofftime = disptime - dispontime; _dispofftime = disptime - _dispontime;
// printf("%i %f %f %f %i %i\n",cgamode&1,disptime,dispontime,dispofftime,crtc[0],crtc[1]); // printf("%i %f %f %f %i %i\n",cgamode&1,disptime,dispontime,dispofftime,crtc[0],crtc[1]);
dispontime *= CGACONST / 2; _dispontime *= CGACONST / 2;
dispofftime *= CGACONST / 2; _dispofftime *= CGACONST / 2;
// printf("Timings - on %f off %f frame %f second %f\n",dispontime,dispofftime,(dispontime+dispofftime)*262.0,(dispontime+dispofftime)*262.0*59.92); // printf("Timings - on %f off %f frame %f second %f\n",dispontime,dispofftime,(dispontime+dispofftime)*262.0,(dispontime+dispofftime)*262.0*59.92);
dispontime = (int)(_dispontime * (1 << TIMER_SHIFT));
dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT));
} }
static int linepos,displine; static int linepos,displine;
@ -92,7 +100,7 @@ static int cgadispon;
static int con,coff,cursoron,cgablink; static int con,coff,cursoron,cgablink;
static int vsynctime,vadj; static int vsynctime,vadj;
static int m24_lineff = 0; static int m24_lineff = 0;
static uint16_t ma,maback,ca; static uint16_t ma,maback;
void m24_poll() void m24_poll()
{ {
@ -101,7 +109,7 @@ void m24_poll()
int x,c; int x,c;
int oldvc; int oldvc;
uint8_t chr,attr; uint8_t chr,attr;
uint16_t dat,dat2,dat3,dat4; uint16_t dat,dat2;
int cols[4]; int cols[4];
int col; int col;
int oldsc; int oldsc;
@ -401,7 +409,7 @@ endblit();
int m24_init() int m24_init()
{ {
mem_sethandler(0xb8000, 0x08000, m24_read, NULL, NULL, m24_write, NULL, NULL); mem_sethandler(0xb8000, 0x08000, m24_read, NULL, NULL, m24_write, NULL, NULL, NULL);
return 0; return 0;
} }

View file

@ -1,16 +1,19 @@
/*Oak OTI067 emulation*/ /*Oak OTI067 emulation*/
#include "ibm.h" #include "ibm.h"
#include "io.h"
#include "video.h" #include "video.h"
#include "vid_svga.h" #include "vid_svga.h"
static int oti067_index; static int oti067_index;
static uint8_t oti067_regs[32]; static uint8_t oti067_regs[32];
void oti067_out(uint16_t addr, uint8_t val) void oti067_out(uint16_t addr, uint8_t val, void *priv)
{ {
uint8_t old; uint8_t old;
if ((addr&0xFFF0) == 0x3B0) addr |= 0x20; // pclog("oti067_out : %04X %02X %02X %i\n", addr, val, ram[0x489], ins);
if ((((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && addr < 0x3de) && !(svga_miscout&1)) addr ^= 0x60;
switch (addr) switch (addr)
{ {
@ -46,28 +49,41 @@ void oti067_out(uint16_t addr, uint8_t val)
} }
return; return;
} }
svga_out(addr,val); svga_out(addr, val, NULL);
} }
uint8_t oti067_in(uint16_t addr) uint8_t oti067_in(uint16_t addr, void *priv)
{ {
uint8_t temp; uint8_t temp;
if ((addr&0xFFF0) == 0x3B0) addr |= 0x20; // if (addr != 0x3da && addr != 0x3ba) pclog("oti067_in : %04X ", addr);
if ((((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && addr < 0x3de) && !(svga_miscout&1)) addr ^= 0x60;
switch (addr) switch (addr)
{ {
case 0x3D4: case 0x3D4:
return crtcreg; temp = crtcreg;
break;
case 0x3D5: case 0x3D5:
return crtc[crtcreg]; temp = crtc[crtcreg];
case 0x3DE: return oti067_index|(2<<5); break;
case 0x3DE:
temp = oti067_index|(2<<5);
break;
case 0x3DF: case 0x3DF:
if (oti067_index==0x10) return 0x40; if (oti067_index==0x10) temp = 0x18;
if (oti067_index==0xD) return oti067_regs[oti067_index]|0xC0; else if (oti067_index==0xD) temp = oti067_regs[oti067_index]|0xC0;
return oti067_regs[oti067_index]; else temp = oti067_regs[oti067_index];
break;
default:
temp = svga_in(addr, NULL);
break;
} }
return svga_in(addr); // if (addr != 0x3da && addr != 0x3ba) pclog("%02X %04X:%04X\n", temp, CS,pc);
return temp;
} }
void oti067_recalctimings() void oti067_recalctimings()
@ -82,6 +98,8 @@ int oti067_init()
svga_recalctimings_ex = oti067_recalctimings; svga_recalctimings_ex = oti067_recalctimings;
svga_vram_limit = 1 << 19; /*512kb*/ svga_vram_limit = 1 << 19; /*512kb*/
vrammask = 0x7ffff; vrammask = 0x7ffff;
bpp = 8;
svga_miscout = 1;
return svga_init(); return svga_init();
} }

View file

@ -4,12 +4,14 @@
MegaPC uses W90C11A MegaPC uses W90C11A
*/ */
#include "ibm.h" #include "ibm.h"
#include "mem.h"
#include "video.h" #include "video.h"
#include "vid_svga.h" #include "vid_svga.h"
#include "vid_unk_ramdac.h" #include "vid_unk_ramdac.h"
void paradise_write(uint32_t addr, uint8_t val); void paradise_write(uint32_t addr, uint8_t val, void *priv);
uint8_t paradise_read(uint32_t addr); uint8_t paradise_read(uint32_t addr, void *priv);
void paradise_remap();
enum enum
{ {
@ -21,7 +23,7 @@ static int paradise_type;
static uint32_t paradise_bank_r[4], paradise_bank_w[4]; static uint32_t paradise_bank_r[4], paradise_bank_w[4];
void paradise_out(uint16_t addr, uint8_t val) void paradise_out(uint16_t addr, uint8_t val, void *priv)
{ {
uint8_t old; uint8_t old;
@ -52,21 +54,21 @@ void paradise_out(uint16_t addr, uint8_t val)
{ {
if ((gdcreg[6] & 0xc) != (val & 0xc)) if ((gdcreg[6] & 0xc) != (val & 0xc))
{ {
mem_removehandler(0xa0000, 0x20000, paradise_read, NULL, NULL, svga_write, NULL, NULL); mem_removehandler(0xa0000, 0x20000, paradise_read, NULL, NULL, paradise_write, NULL, NULL, NULL);
// pclog("Write mapping %02X\n", val); // pclog("Write mapping %02X\n", val);
switch (val&0xC) switch (val&0xC)
{ {
case 0x0: /*128k at A0000*/ case 0x0: /*128k at A0000*/
mem_sethandler(0xa0000, 0x20000, paradise_read, NULL, NULL, paradise_write, NULL, NULL); mem_sethandler(0xa0000, 0x20000, paradise_read, NULL, NULL, paradise_write, NULL, NULL, NULL);
break; break;
case 0x4: /*64k at A0000*/ case 0x4: /*64k at A0000*/
mem_sethandler(0xa0000, 0x10000, paradise_read, NULL, NULL, paradise_write, NULL, NULL); mem_sethandler(0xa0000, 0x10000, paradise_read, NULL, NULL, paradise_write, NULL, NULL, NULL);
break; break;
case 0x8: /*32k at B0000*/ case 0x8: /*32k at B0000*/
mem_sethandler(0xb0000, 0x08000, paradise_read, NULL, NULL, paradise_write, NULL, NULL); mem_sethandler(0xb0000, 0x08000, paradise_read, NULL, NULL, paradise_write, NULL, NULL, NULL);
break; break;
case 0xC: /*32k at B8000*/ case 0xC: /*32k at B8000*/
mem_sethandler(0xb8000, 0x08000, paradise_read, NULL, NULL, paradise_write, NULL, NULL); mem_sethandler(0xb8000, 0x08000, paradise_read, NULL, NULL, paradise_write, NULL, NULL, NULL);
break; break;
} }
} }
@ -114,13 +116,11 @@ void paradise_out(uint16_t addr, uint8_t val)
} }
break; break;
} }
svga_out(addr,val); svga_out(addr, val, NULL);
} }
uint8_t paradise_in(uint16_t addr) uint8_t paradise_in(uint16_t addr, void *priv)
{ {
uint8_t temp;
if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga_miscout&1)) addr ^= 0x60; if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga_miscout&1)) addr ^= 0x60;
// if (addr != 0x3da) pclog("Paradise in %04X\n", addr); // if (addr != 0x3da) pclog("Paradise in %04X\n", addr);
@ -157,7 +157,7 @@ uint8_t paradise_in(uint16_t addr)
return 0xff; return 0xff;
return crtc[crtcreg]; return crtc[crtcreg];
} }
return svga_in(addr); return svga_in(addr, NULL);
} }
void paradise_remap() void paradise_remap()
@ -185,8 +185,8 @@ void paradise_remap()
// pclog("Remap 3\n"); // pclog("Remap 3\n");
paradise_bank_r[0] = paradise_bank_w[0] = (gdcreg[0xa] & 0x7f) << 12; paradise_bank_r[0] = paradise_bank_w[0] = (gdcreg[0xa] & 0x7f) << 12;
paradise_bank_r[1] = paradise_bank_w[1] = ((gdcreg[0xa] & 0x7f) << 12) + ((gdcreg[6] & 0x08) ? 0 : 0x8000); paradise_bank_r[1] = paradise_bank_w[1] = ((gdcreg[0xa] & 0x7f) << 12) + ((gdcreg[6] & 0x08) ? 0 : 0x8000);
paradise_bank_w[2] = paradise_bank_w[2] = (gdcreg[0x9] & 0x7f) << 12; paradise_bank_r[2] = paradise_bank_w[2] = (gdcreg[0x9] & 0x7f) << 12;
paradise_bank_w[3] = paradise_bank_w[3] = ((gdcreg[0x9] & 0x7f) << 12) + ((gdcreg[6] & 0x08) ? 0 : 0x8000); paradise_bank_r[3] = paradise_bank_w[3] = ((gdcreg[0x9] & 0x7f) << 12) + ((gdcreg[6] & 0x08) ? 0 : 0x8000);
} }
} }
else else
@ -207,20 +207,20 @@ void paradise_recalctimings()
#define egacycles 1 #define egacycles 1
#define egacycles2 1 #define egacycles2 1
void paradise_write(uint32_t addr, uint8_t val) void paradise_write(uint32_t addr, uint8_t val, void *priv)
{ {
// pclog("paradise_write : %05X %02X ", addr, val); // pclog("paradise_write : %05X %02X ", addr, val);
addr = (addr & 0x7fff) + paradise_bank_w[(addr >> 15) & 3]; addr = (addr & 0x7fff) + paradise_bank_w[(addr >> 15) & 3];
// pclog("%08X\n", addr); // pclog("%08X\n", addr);
svga_write_linear(addr, val); svga_write_linear(addr, val, priv);
} }
uint8_t paradise_read(uint32_t addr) uint8_t paradise_read(uint32_t addr, void *priv)
{ {
// pclog("paradise_read : %05X ", addr); // pclog("paradise_read : %05X ", addr);
addr = (addr & 0x7fff) + paradise_bank_r[(addr >> 15) & 3]; addr = (addr & 0x7fff) + paradise_bank_r[(addr >> 15) & 3];
// pclog("%08X\n", addr); // pclog("%08X\n", addr);
return svga_read_linear(addr); return svga_read_linear(addr, priv);
} }
int paradise_init() int paradise_init()

View file

@ -8,6 +8,9 @@
and 46 cycles. PCem currently always uses the lower number.*/ and 46 cycles. PCem currently always uses the lower number.*/
#include "ibm.h" #include "ibm.h"
#include "io.h"
#include "mem.h"
#include "timer.h"
#include "video.h" #include "video.h"
#include "vid_cga.h" #include "vid_cga.h"
@ -15,7 +18,7 @@ static uint8_t pc1512_plane_write,pc1512_plane_read,pc1512_border;
void pc1512_recalctimings(); void pc1512_recalctimings();
void pc1512_out(uint16_t addr, uint8_t val) void pc1512_out(uint16_t addr, uint8_t val, void *priv)
{ {
uint8_t old; uint8_t old;
// pclog("PC1512 out %04X %02X %04X:%04X\n",addr,val,CS,pc); // pclog("PC1512 out %04X %02X %04X:%04X\n",addr,val,CS,pc);
@ -59,7 +62,7 @@ void pc1512_out(uint16_t addr, uint8_t val)
} }
} }
uint8_t pc1512_in(uint16_t addr) uint8_t pc1512_in(uint16_t addr, void *priv)
{ {
// pclog("PC1512 in %04X %02X %04X:%04X\n",addr,CS,pc); // pclog("PC1512 in %04X %02X %04X:%04X\n",addr,CS,pc);
switch (addr) switch (addr)
@ -74,7 +77,7 @@ uint8_t pc1512_in(uint16_t addr)
return 0xFF; return 0xFF;
} }
void pc1512_write(uint32_t addr, uint8_t val) void pc1512_write(uint32_t addr, uint8_t val, void *priv)
{ {
/* if (CS==0x023E && pc==0x524E) /* if (CS==0x023E && pc==0x524E)
{ {
@ -95,7 +98,7 @@ void pc1512_write(uint32_t addr, uint8_t val)
vram[addr]=val; vram[addr]=val;
} }
uint8_t pc1512_read(uint32_t addr) uint8_t pc1512_read(uint32_t addr, void *priv)
{ {
// pclog("PC1512 read %08X %02X %01X\n",addr,cgamode&0x12,pc1512_plane_read); // pclog("PC1512 read %08X %02X %01X\n",addr,cgamode&0x12,pc1512_plane_read);
cycles-=12; cycles-=12;
@ -111,32 +114,23 @@ static int sc,vc;
static int cgadispon; static int cgadispon;
static int con,coff,cursoron,cgablink; static int con,coff,cursoron,cgablink;
static int vsynctime,vadj; static int vsynctime,vadj;
static uint16_t ma,maback,ca; static uint16_t ma,maback;
static int ntsc_col[8][8]=
{
{0,0,0,0,0,0,0,0}, /*Black*/
{0,0,1,1,1,1,0,0}, /*Blue*/
{1,0,0,0,0,1,1,1}, /*Green*/
{0,0,0,0,1,1,1,1}, /*Cyan*/
{1,1,1,1,0,0,0,0}, /*Red*/
{0,1,1,1,1,0,0,0}, /*Magenta*/
{1,1,0,0,0,0,1,1}, /*Yellow*/
{1,1,1,1,1,1,1,1} /*White*/
};
int i_filt[8],q_filt[8]; int i_filt[8],q_filt[8];
void pc1512_recalctimings() void pc1512_recalctimings()
{ {
double _dispontime, _dispofftime;
disptime = 128; /*Fixed on PC1512*/ disptime = 128; /*Fixed on PC1512*/
dispontime = 80; _dispontime = 80;
dispofftime=disptime-dispontime; _dispofftime=disptime-_dispontime;
// printf("%i %f %f %f %i %i\n",cgamode&1,disptime,dispontime,dispofftime,crtc[0],crtc[1]); // printf("%i %f %f %f %i %i\n",cgamode&1,disptime,dispontime,dispofftime,crtc[0],crtc[1]);
dispontime*=CGACONST; _dispontime*=CGACONST;
dispofftime*=CGACONST; _dispofftime*=CGACONST;
// printf("Timings - on %f off %f frame %f second %f\n",dispontime,dispofftime,(dispontime+dispofftime)*262.0,(dispontime+dispofftime)*262.0*59.92); // printf("Timings - on %f off %f frame %f second %f\n",dispontime,dispofftime,(dispontime+dispofftime)*262.0,(dispontime+dispofftime)*262.0*59.92);
dispontime = (int)(_dispontime * (1 << TIMER_SHIFT));
dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT));
} }
void pc1512_poll() void pc1512_poll()
@ -417,7 +411,7 @@ endblit();
int pc1512_init() int pc1512_init()
{ {
mem_sethandler(0xb8000, 0x08000, pc1512_read, NULL, NULL, pc1512_write, NULL, NULL); mem_sethandler(0xb8000, 0x08000, pc1512_read, NULL, NULL, pc1512_write, NULL, NULL, NULL);
return 0; return 0;
} }

View file

@ -1,54 +1,56 @@
/*PC1640 video emulation. /*PC1640 video emulation.
Mostly standard EGA, but with CGA & Hercules emulation*/ Mostly standard EGA, but with CGA & Hercules emulation*/
#include "ibm.h" #include "ibm.h"
#include "io.h"
#include "mem.h"
#include "video.h" #include "video.h"
#include "vid_cga.h" #include "vid_cga.h"
#include "vid_ega.h" #include "vid_ega.h"
static int pc1640_cga=1; static int pc1640_cga=1;
void pc1640_out(uint16_t addr, uint8_t val) void pc1640_out(uint16_t addr, uint8_t val, void *priv)
{ {
switch (addr) switch (addr)
{ {
case 0x3DB: case 0x3DB:
pc1640_cga=val&0x40; pc1640_cga=val&0x40;
mem_removehandler(0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL); mem_removehandler(0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL);
mem_removehandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL); mem_removehandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL);
if (pc1640_cga) if (pc1640_cga)
mem_sethandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL); mem_sethandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL);
else else
{ {
switch (gdcreg[6] & 0xC) switch (gdcreg[6] & 0xC)
{ {
case 0x0: /*128k at A0000*/ case 0x0: /*128k at A0000*/
mem_sethandler(0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL); mem_sethandler(0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL);
break; break;
case 0x4: /*64k at A0000*/ case 0x4: /*64k at A0000*/
mem_sethandler(0xa0000, 0x10000, ega_read, NULL, NULL, ega_write, NULL, NULL); mem_sethandler(0xa0000, 0x10000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL);
break; break;
case 0x8: /*32k at B0000*/ case 0x8: /*32k at B0000*/
mem_sethandler(0xb0000, 0x08000, ega_read, NULL, NULL, ega_write, NULL, NULL); mem_sethandler(0xb0000, 0x08000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL);
break; break;
case 0xC: /*32k at B8000*/ case 0xC: /*32k at B8000*/
mem_sethandler(0xb8000, 0x08000, ega_read, NULL, NULL, ega_write, NULL, NULL); mem_sethandler(0xb8000, 0x08000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL);
break; break;
} }
} }
pclog("3DB write %02X\n", val); pclog("3DB write %02X\n", val);
return; return;
} }
if (pc1640_cga) cga_out(addr,val); if (pc1640_cga) cga_out(addr, val, NULL);
else ega_out(addr,val); else ega_out(addr, val, NULL);
} }
uint8_t pc1640_in(uint16_t addr) uint8_t pc1640_in(uint16_t addr, void *priv)
{ {
switch (addr) switch (addr)
{ {
} }
if (pc1640_cga) return cga_in(addr); if (pc1640_cga) return cga_in(addr, NULL);
else return ega_in(addr); else return ega_in(addr, NULL);
} }
void pc1640_recalctimings() void pc1640_recalctimings()
@ -69,7 +71,7 @@ int pc1640_init()
pc1640_cga = 1; pc1640_cga = 1;
mem_sethandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL); mem_sethandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL);
return r; return r;
} }

View file

@ -2,12 +2,14 @@
CGA with some NMI stuff. But we don't need that as it's only used for TV and CGA with some NMI stuff. But we don't need that as it's only used for TV and
LCD displays, and we're emulating a CRT*/ LCD displays, and we're emulating a CRT*/
#include "ibm.h" #include "ibm.h"
#include "io.h"
#include "mem.h"
#include "video.h" #include "video.h"
#include "vid_cga.h" #include "vid_cga.h"
uint8_t pc200_3dd, pc200_3de, pc200_3df; uint8_t pc200_3dd, pc200_3de, pc200_3df;
void pc200_out(uint16_t addr, uint8_t val) void pc200_out(uint16_t addr, uint8_t val, void *priv)
{ {
uint8_t old; uint8_t old;
switch (addr) switch (addr)
@ -48,10 +50,10 @@ void pc200_out(uint16_t addr, uint8_t val)
if (val&0x80) pc200_3dd|=0x40; if (val&0x80) pc200_3dd|=0x40;
return; return;
} }
cga_out(addr,val); cga_out(addr, val, NULL);
} }
uint8_t pc200_in(uint16_t addr) uint8_t pc200_in(uint16_t addr, void *priv)
{ {
uint8_t temp; uint8_t temp;
switch (addr) switch (addr)
@ -70,12 +72,12 @@ uint8_t pc200_in(uint16_t addr)
case 0x3DF: case 0x3DF:
return pc200_3df; return pc200_3df;
} }
return cga_in(addr); return cga_in(addr, NULL);
} }
int pc200_init() int pc200_init()
{ {
mem_sethandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL); mem_sethandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL);
return cga_init(); return cga_init();
} }

View file

@ -1,17 +1,19 @@
/*S3 emulation*/ /*S3 emulation*/
#include "ibm.h" #include "ibm.h"
#include "io.h"
#include "mem.h" #include "mem.h"
#include "pci.h" #include "pci.h"
#include "video.h" #include "video.h"
#include "vid_svga.h" #include "vid_svga.h"
#include "vid_svga_render.h"
#include "vid_sdac_ramdac.h" #include "vid_sdac_ramdac.h"
void s3_updatemapping(); void s3_updatemapping();
void s3_accel_write(uint32_t addr, uint8_t val); void s3_accel_write(uint32_t addr, uint8_t val, void *priv);
void s3_accel_write_w(uint32_t addr, uint16_t val); void s3_accel_write_w(uint32_t addr, uint16_t val, void *priv);
void s3_accel_write_l(uint32_t addr, uint32_t val); void s3_accel_write_l(uint32_t addr, uint32_t val, void *priv);
uint8_t s3_accel_read(uint32_t addr); uint8_t s3_accel_read(uint32_t addr, void *priv);
static uint8_t s3_bank; static uint8_t s3_bank;
static uint8_t s3_ma_ext; static uint8_t s3_ma_ext;
@ -20,7 +22,7 @@ static int s3_bpp = 0;
static uint8_t s3_id, s3_id_ext; static uint8_t s3_id, s3_id_ext;
void s3_out(uint16_t addr, uint8_t val) void s3_out(uint16_t addr, uint8_t val, void *priv)
{ {
uint8_t old; uint8_t old;
@ -40,7 +42,7 @@ void s3_out(uint16_t addr, uint8_t val)
case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
// pclog("Write RAMDAC %04X %02X %04X:%04X\n", addr, val, CS, pc); // pclog("Write RAMDAC %04X %02X %04X:%04X\n", addr, val, CS, pc);
sdac_ramdac_out(addr,val); sdac_ramdac_out(addr, val, NULL);
return; return;
case 0x3D4: case 0x3D4:
@ -141,13 +143,11 @@ void s3_out(uint16_t addr, uint8_t val)
} }
break; break;
} }
svga_out(addr,val); svga_out(addr, val, NULL);
} }
uint8_t s3_in(uint16_t addr) uint8_t s3_in(uint16_t addr, void *priv)
{ {
uint8_t temp;
if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga_miscout&1)) addr ^= 0x60; if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga_miscout&1)) addr ^= 0x60;
// if (addr != 0x3da) pclog("S3 in %04X\n", addr); // if (addr != 0x3da) pclog("S3 in %04X\n", addr);
@ -155,7 +155,7 @@ uint8_t s3_in(uint16_t addr)
{ {
case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
// pclog("Read RAMDAC %04X %04X:%04X\n", addr, CS, pc); // pclog("Read RAMDAC %04X %04X:%04X\n", addr, CS, pc);
return sdac_ramdac_in(addr); return sdac_ramdac_in(addr, NULL);
case 0x3D4: case 0x3D4:
return crtcreg; return crtcreg;
@ -174,7 +174,7 @@ uint8_t s3_in(uint16_t addr)
} }
return crtc[crtcreg]; return crtc[crtcreg];
} }
return svga_in(addr); return svga_in(addr, NULL);
} }
void s3_recalctimings() void s3_recalctimings()
@ -182,7 +182,27 @@ void s3_recalctimings()
// pclog("recalctimings\n"); // pclog("recalctimings\n");
svga_ma |= (s3_ma_ext << 16); svga_ma |= (s3_ma_ext << 16);
// pclog("SVGA_MA %08X\n", svga_ma); // pclog("SVGA_MA %08X\n", svga_ma);
if (gdcreg[5] & 0x40) svga_lowres = !(crtc[0x3a] & 0x10); if ((gdcreg[5] & 0x40) && (crtc[0x3a] & 0x10))
{
switch (bpp)
{
case 8:
svga_render = svga_render_8bpp_highres;
break;
case 15:
svga_render = svga_render_15bpp_highres;
break;
case 16:
svga_render = svga_render_16bpp_highres;
break;
case 24:
svga_render = svga_render_24bpp_highres;
break;
case 32:
svga_render = svga_render_32bpp_highres;
break;
}
}
if (crtc[0x5d] & 0x01) svga_htotal += 0x100; if (crtc[0x5d] & 0x01) svga_htotal += 0x100;
if (crtc[0x5d] & 0x02) svga_hdisp += 0x100; if (crtc[0x5d] & 0x02) svga_hdisp += 0x100;
if (crtc[0x5e] & 0x01) svga_vtotal += 0x400; if (crtc[0x5e] & 0x01) svga_vtotal += 0x400;
@ -201,25 +221,25 @@ void s3_recalctimings()
static uint32_t s3_linear_base = 0, s3_linear_size = 0; static uint32_t s3_linear_base = 0, s3_linear_size = 0;
void s3_updatemapping() void s3_updatemapping()
{ {
mem_removehandler(s3_linear_base, s3_linear_size, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear); mem_removehandler(s3_linear_base, s3_linear_size, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL);
// video_write_a000_w = video_write_a000_l = NULL; // video_write_a000_w = video_write_a000_l = NULL;
mem_removehandler(0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); mem_removehandler(0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL);
// pclog("Update mapping - bank %02X ", gdcreg[6] & 0xc); // pclog("Update mapping - bank %02X ", gdcreg[6] & 0xc);
switch (gdcreg[6] & 0xc) /*Banked framebuffer*/ switch (gdcreg[6] & 0xc) /*Banked framebuffer*/
{ {
case 0x0: /*128k at A0000*/ case 0x0: /*128k at A0000*/
mem_sethandler(0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); mem_sethandler(0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL);
break; break;
case 0x4: /*64k at A0000*/ case 0x4: /*64k at A0000*/
mem_sethandler(0xa0000, 0x10000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); mem_sethandler(0xa0000, 0x10000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL);
break; break;
case 0x8: /*32k at B0000*/ case 0x8: /*32k at B0000*/
mem_sethandler(0xb0000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); mem_sethandler(0xb0000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL);
break; break;
case 0xC: /*32k at B8000*/ case 0xC: /*32k at B8000*/
mem_sethandler(0xb8000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); mem_sethandler(0xb8000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL);
break; break;
} }
@ -246,15 +266,15 @@ void s3_updatemapping()
// pclog("%08X %08X %02X %02X %02X\n", linear_base, linear_size, crtc[0x58], crtc[0x59], crtc[0x5a]); // pclog("%08X %08X %02X %02X %02X\n", linear_base, linear_size, crtc[0x58], crtc[0x59], crtc[0x5a]);
// pclog("Linear framebuffer at %08X size %08X\n", linear_base, linear_size); // pclog("Linear framebuffer at %08X size %08X\n", linear_base, linear_size);
if (s3_linear_base == 0xa0000) if (s3_linear_base == 0xa0000)
mem_sethandler(0xa0000, 0x10000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); mem_sethandler(0xa0000, 0x10000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL);
else else
mem_sethandler(s3_linear_base, s3_linear_size, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear); mem_sethandler(s3_linear_base, s3_linear_size, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL);
} }
// pclog("Memory mapped IO %02X\n", crtc[0x53] & 0x10); // pclog("Memory mapped IO %02X\n", crtc[0x53] & 0x10);
if (crtc[0x53] & 0x10) /*Memory mapped IO*/ if (crtc[0x53] & 0x10) /*Memory mapped IO*/
{ {
mem_sethandler(0xa0000, 0x10000, s3_accel_read, NULL, NULL, s3_accel_write, s3_accel_write_w, s3_accel_write_l); mem_sethandler(0xa0000, 0x10000, s3_accel_read, NULL, NULL, s3_accel_write, s3_accel_write_w, s3_accel_write_l, NULL);
/* video_write_a000 = s3_accel_write; /* video_write_a000 = s3_accel_write;
video_write_a000_w = s3_accel_write_w; video_write_a000_w = s3_accel_write_w;
video_write_a000_l = s3_accel_write_l; video_write_a000_l = s3_accel_write_l;
@ -299,7 +319,7 @@ struct
void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat); void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat);
void s3_accel_out(uint16_t port, uint8_t val) void s3_accel_out(uint16_t port, uint8_t val, void *priv)
{ {
// pclog("Accel out %04X %02X\n", port, val); // pclog("Accel out %04X %02X\n", port, val);
switch (port) switch (port)
@ -503,7 +523,7 @@ void s3_accel_out(uint16_t port, uint8_t val)
} }
} }
void s3_accel_out_w(uint16_t port, uint16_t val) void s3_accel_out_w(uint16_t port, uint16_t val, void *priv)
{ {
// pclog("Accel out w %04X %04X\n", port, val); // pclog("Accel out w %04X %04X\n", port, val);
if (s3_accel.cmd & 0x100) if (s3_accel.cmd & 0x100)
@ -519,7 +539,7 @@ void s3_accel_out_w(uint16_t port, uint16_t val)
} }
} }
void s3_accel_out_l(uint16_t port, uint32_t val) void s3_accel_out_l(uint16_t port, uint32_t val, void *priv)
{ {
// pclog("Accel out l %04X %08X\n", port, val); // pclog("Accel out l %04X %08X\n", port, val);
if (s3_accel.cmd & 0x100) if (s3_accel.cmd & 0x100)
@ -563,7 +583,7 @@ void s3_accel_out_l(uint16_t port, uint32_t val)
} }
} }
uint8_t s3_accel_in(uint16_t port) uint8_t s3_accel_in(uint16_t port, void *priv)
{ {
int temp; int temp;
// pclog("Accel in %04X\n", port); // pclog("Accel in %04X\n", port);
@ -682,11 +702,11 @@ uint8_t s3_accel_in(uint16_t port)
return 0; return 0;
} }
void s3_accel_write(uint32_t addr, uint8_t val) void s3_accel_write(uint32_t addr, uint8_t val, void *priv)
{ {
// pclog("Write S3 accel %08X %02X\n", addr, val); // pclog("Write S3 accel %08X %02X\n", addr, val);
if (addr & 0x8000) if (addr & 0x8000)
s3_accel_out(addr & 0xffff, val); s3_accel_out(addr & 0xffff, val, priv);
else else
{ {
if (s3_accel.cmd & 0x100) if (s3_accel.cmd & 0x100)
@ -699,13 +719,13 @@ void s3_accel_write(uint32_t addr, uint8_t val)
} }
} }
void s3_accel_write_w(uint32_t addr, uint16_t val) void s3_accel_write_w(uint32_t addr, uint16_t val, void *priv)
{ {
// pclog("Write S3 accel w %08X %04X\n", addr, val); // pclog("Write S3 accel w %08X %04X\n", addr, val);
if (addr & 0x8000) if (addr & 0x8000)
{ {
s3_accel_out( addr & 0xffff, val); s3_accel_out( addr & 0xffff, val, priv);
s3_accel_out((addr & 0xffff) + 1, val >> 8); s3_accel_out((addr & 0xffff) + 1, val >> 8, priv);
} }
else else
{ {
@ -723,15 +743,15 @@ void s3_accel_write_w(uint32_t addr, uint16_t val)
} }
} }
void s3_accel_write_l(uint32_t addr, uint32_t val) void s3_accel_write_l(uint32_t addr, uint32_t val, void *priv)
{ {
// pclog("Write S3 accel l %08X %08X\n", addr, val); // pclog("Write S3 accel l %08X %08X\n", addr, val);
if (addr & 0x8000) if (addr & 0x8000)
{ {
s3_accel_out( addr & 0xffff, val); s3_accel_out( addr & 0xffff, val, priv);
s3_accel_out((addr & 0xffff) + 1, val >> 8); s3_accel_out((addr & 0xffff) + 1, val >> 8, priv);
s3_accel_out((addr & 0xffff) + 2, val >> 16); s3_accel_out((addr & 0xffff) + 2, val >> 16, priv);
s3_accel_out((addr & 0xffff) + 3, val >> 24); s3_accel_out((addr & 0xffff) + 3, val >> 24, priv);
} }
else else
{ {
@ -777,11 +797,11 @@ void s3_accel_write_l(uint32_t addr, uint32_t val)
} }
} }
uint8_t s3_accel_read(uint32_t addr) uint8_t s3_accel_read(uint32_t addr, void *priv)
{ {
// pclog("Read S3 accel %08X\n", addr); // pclog("Read S3 accel %08X\n", addr);
if (addr & 0x8000) if (addr & 0x8000)
return s3_accel_in(addr & 0xffff); return s3_accel_in(addr & 0xffff, priv);
return 0; return 0;
} }
@ -828,12 +848,8 @@ uint8_t s3_accel_read(uint32_t addr)
void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat) void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat)
{ {
uint32_t dest, destbak;
int sx, sy, cx, cy;
int x, y;
uint32_t src_dat, dest_dat; uint32_t src_dat, dest_dat;
int frgd_mix, bkgd_mix; int frgd_mix, bkgd_mix;
int mix;
int clip_t = s3_accel.multifunc[1] & 0xfff; int clip_t = s3_accel.multifunc[1] & 0xfff;
int clip_l = s3_accel.multifunc[2] & 0xfff; int clip_l = s3_accel.multifunc[2] & 0xfff;
int clip_b = s3_accel.multifunc[3] & 0xfff; int clip_b = s3_accel.multifunc[3] & 0xfff;
@ -1390,6 +1406,7 @@ void s3_hwcursor_draw(int displine)
int xx; int xx;
int offset = svga_hwcursor_latch.x - svga_hwcursor_latch.xoff; int offset = svga_hwcursor_latch.x - svga_hwcursor_latch.xoff;
pclog("HWcursor %i %i\n", svga_hwcursor_latch.x, svga_hwcursor_latch.y);
for (x = 0; x < 64; x += 16) for (x = 0; x < 64; x += 16)
{ {
dat[0] = (vram[svga_hwcursor_latch.addr] << 8) | vram[svga_hwcursor_latch.addr + 1]; dat[0] = (vram[svga_hwcursor_latch.addr] << 8) | vram[svga_hwcursor_latch.addr + 1];
@ -1414,9 +1431,9 @@ void s3_hwcursor_draw(int displine)
} }
uint8_t s3_pci_read(int func, int addr) uint8_t s3_pci_read(int func, int addr, void *priv)
{ {
pclog("S3 PCI read %08X\n", addr); // pclog("S3 PCI read %08X\n", addr);
switch (addr) switch (addr)
{ {
case 0x00: return 0x33; /*'S3'*/ case 0x00: return 0x33; /*'S3'*/
@ -1448,7 +1465,7 @@ uint8_t s3_pci_read(int func, int addr)
return 0; return 0;
} }
void s3_pci_write(int func, int addr, uint8_t val) void s3_pci_write(int func, int addr, uint8_t val, void *priv)
{ {
switch (addr) switch (addr)
{ {
@ -1482,28 +1499,28 @@ int s3_init()
vrammask = 0x3fffff; vrammask = 0x3fffff;
io_sethandler(0x42e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); io_sethandler(0x42e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL);
io_sethandler(0x46e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); io_sethandler(0x46e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL);
io_sethandler(0x4ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); io_sethandler(0x4ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL);
io_sethandler(0x82e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); io_sethandler(0x82e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL);
io_sethandler(0x86e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); io_sethandler(0x86e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL);
io_sethandler(0x8ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); io_sethandler(0x8ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL);
io_sethandler(0x8ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); io_sethandler(0x8ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL);
io_sethandler(0x92e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); io_sethandler(0x92e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL);
io_sethandler(0x96e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); io_sethandler(0x96e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL);
io_sethandler(0x9ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); io_sethandler(0x9ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL);
io_sethandler(0x9ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); io_sethandler(0x9ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL);
io_sethandler(0xa2e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); io_sethandler(0xa2e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL);
io_sethandler(0xa6e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); io_sethandler(0xa6e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL);
io_sethandler(0xaae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); io_sethandler(0xaae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL);
io_sethandler(0xaee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); io_sethandler(0xaee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL);
io_sethandler(0xb2e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); io_sethandler(0xb2e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL);
io_sethandler(0xb6e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); io_sethandler(0xb6e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL);
io_sethandler(0xbae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); io_sethandler(0xbae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL);
io_sethandler(0xbee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL); io_sethandler(0xbee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, NULL);
io_sethandler(0xe2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l); io_sethandler(0xe2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, NULL);
pci_add(s3_pci_read, s3_pci_write); pci_add(s3_pci_read, s3_pci_write, NULL);
svga_vram_limit = 4 << 20; /*4mb - 864 supports 8mb but buggy VESA driver reports 0mb*/ svga_vram_limit = 4 << 20; /*4mb - 864 supports 8mb but buggy VESA driver reports 0mb*/
return svga_init(); return svga_init();

View file

@ -15,9 +15,8 @@ struct
int rs2; int rs2;
} sdac_ramdac; } sdac_ramdac;
void sdac_ramdac_out(uint16_t addr, uint8_t val) void sdac_ramdac_out(uint16_t addr, uint8_t val, void *priv)
{ {
int didwrite;
// /*if (CS!=0xC000) */pclog("OUT RAMDAC %04X %02X %i %04X:%04X %i\n",addr,val,sdac_ramdac.magic_count,CS,pc, sdac_ramdac.rs2); // /*if (CS!=0xC000) */pclog("OUT RAMDAC %04X %02X %i %04X:%04X %i\n",addr,val,sdac_ramdac.magic_count,CS,pc, sdac_ramdac.rs2);
switch (addr) switch (addr)
{ {
@ -68,10 +67,10 @@ void sdac_ramdac_out(uint16_t addr, uint8_t val)
} }
break; break;
} }
svga_out(addr,val); svga_out(addr, val, NULL);
} }
uint8_t sdac_ramdac_in(uint16_t addr) uint8_t sdac_ramdac_in(uint16_t addr, void *priv)
{ {
uint8_t temp; uint8_t temp;
// /*if (CS!=0xC000) */pclog("IN RAMDAC %04X %04X:%04X %i\n",addr,CS,pc, sdac_ramdac.rs2); // /*if (CS!=0xC000) */pclog("IN RAMDAC %04X %04X:%04X %i\n",addr,CS,pc, sdac_ramdac.rs2);
@ -128,7 +127,7 @@ uint8_t sdac_ramdac_in(uint16_t addr)
} }
break; break;
} }
return svga_in(addr); return svga_in(addr, NULL);
} }
float sdac_getclock(int clock) float sdac_getclock(int clock)

View file

@ -1,4 +1,4 @@
void sdac_ramdac_out(uint16_t addr, uint8_t val); void sdac_ramdac_out(uint16_t addr, uint8_t val, void *priv);
uint8_t sdac_ramdac_in(uint16_t addr); uint8_t sdac_ramdac_in(uint16_t addr, void *priv);
float sdac_getclock(int clock); float sdac_getclock(int clock);

View file

@ -15,7 +15,7 @@ struct
int stg_state_read[2][8]={{1,2,3,4,0,0,0,0}, {1,2,3,4,5,6,7,7}}; int stg_state_read[2][8]={{1,2,3,4,0,0,0,0}, {1,2,3,4,5,6,7,7}};
int stg_state_write[8]={0,0,0,0,0,6,7,7}; int stg_state_write[8]={0,0,0,0,0,6,7,7};
void stg_ramdac_out(uint16_t addr, uint8_t val) void stg_ramdac_out(uint16_t addr, uint8_t val, void *priv)
{ {
int didwrite; int didwrite;
//if (CS!=0xC000) pclog("OUT RAMDAC %04X %02X %i %04X:%04X\n",addr,val,stg_ramdac.magic_count,CS,pc); //if (CS!=0xC000) pclog("OUT RAMDAC %04X %02X %i %04X:%04X\n",addr,val,stg_ramdac.magic_count,CS,pc);
@ -64,10 +64,10 @@ void stg_ramdac_out(uint16_t addr, uint8_t val)
stg_ramdac.magic_count=0; stg_ramdac.magic_count=0;
break; break;
} }
svga_out(addr,val); svga_out(addr, val, NULL);
} }
uint8_t stg_ramdac_in(uint16_t addr) uint8_t stg_ramdac_in(uint16_t addr, void *priv)
{ {
uint8_t temp; uint8_t temp;
//if (CS!=0xC000) pclog("IN RAMDAC %04X %04X:%04X\n",addr,CS,pc); //if (CS!=0xC000) pclog("IN RAMDAC %04X %04X:%04X\n",addr,CS,pc);
@ -100,5 +100,5 @@ uint8_t stg_ramdac_in(uint16_t addr)
stg_ramdac.magic_count=0; stg_ramdac.magic_count=0;
break; break;
} }
return svga_in(addr); return svga_in(addr, NULL);
} }

View file

@ -1,2 +1,2 @@
void stg_ramdac_out(uint16_t addr, uint8_t val); void stg_ramdac_out(uint16_t addr, uint8_t val, void *priv);
uint8_t stg_ramdac_in(uint16_t addr); uint8_t stg_ramdac_in(uint16_t addr, void *priv);

View file

@ -1,9 +1,14 @@
/*Generic SVGA handling*/ /*Generic SVGA handling*/
/*This is intended to be used by another SVGA driver, and not as a card in it's own right*/ /*This is intended to be used by another SVGA driver, and not as a card in it's own right*/
#include "ibm.h" #include "ibm.h"
#include "mem.h"
#include "video.h" #include "video.h"
#include "vid_svga.h" #include "vid_svga.h"
#include "vid_svga_render.h"
#include "io.h" #include "io.h"
#include "timer.h"
#define svga_output 0
uint32_t svga_vram_limit; uint32_t svga_vram_limit;
@ -11,15 +16,19 @@ extern uint8_t edatlookup[4][4];
uint8_t svga_miscout; uint8_t svga_miscout;
static uint8_t la, lb, lc, ld; static uint8_t la, lb, lc, ld;
static uint8_t svga_rotate[8][256]; uint8_t svga_rotate[8][256];
static int svga_fast; static int svga_fast;
void svga_out(uint16_t addr, uint8_t val) void (*svga_render)();
static uint8_t dacmask, dacstatus;
void svga_out(uint16_t addr, uint8_t val, void *priv)
{ {
int c; int c;
uint8_t o; uint8_t o;
//printf("OUT SVGA %03X %02X %04X:%04X %i %08X\n",addr,val,CS,pc,TRIDENT,svgawbank); // printf("OUT SVGA %03X %02X %04X:%04X %i %08X\n",addr,val,CS,pc,TRIDENT,svgawbank);
switch (addr) switch (addr)
{ {
case 0x3C0: case 0x3C0:
@ -45,10 +54,16 @@ void svga_out(uint16_t addr, uint8_t val)
svga_miscout = val; svga_miscout = val;
vres = 0; pallook = pallook256; vres = 0; pallook = pallook256;
vidclock = val & 4; printf("3C2 write %02X\n",val); vidclock = val & 4; printf("3C2 write %02X\n",val);
if (val&1) if (val & 1)
io_sethandler(0x03a0, 0x0020, video_in, NULL, NULL, video_out, NULL, NULL); {
pclog("Remove mono handler\n");
io_removehandler(0x03a0, 0x0020, video_in, NULL, NULL, video_out, NULL, NULL, NULL);
}
else else
io_sethandler(0x03a0, 0x0020, video_in_null, NULL, NULL, video_out_null, NULL, NULL); {
pclog("Set mono handler\n");
io_sethandler(0x03a0, 0x0020, video_in, NULL, NULL, video_out, NULL, NULL, NULL);
}
break; break;
case 0x3C4: seqaddr=val; break; case 0x3C4: seqaddr=val; break;
case 0x3C5: case 0x3C5:
@ -58,7 +73,12 @@ void svga_out(uint16_t addr, uint8_t val)
if (o!=val && (seqaddr&0xF)==1) svga_recalctimings(); if (o!=val && (seqaddr&0xF)==1) svga_recalctimings();
switch (seqaddr&0xF) switch (seqaddr&0xF)
{ {
case 1: if (scrblank && !(val&0x20)) fullchange=3; scrblank=(scrblank&~0x20)|(val&0x20); break; case 1:
if (scrblank && !(val&0x20))
fullchange=3;
scrblank=(scrblank&~0x20)|(val&0x20);
svga_recalctimings();
break;
case 2: writemask=val&0xF; break; case 2: writemask=val&0xF; break;
case 3: case 3:
charset=val&0xF; charset=val&0xF;
@ -71,9 +91,16 @@ void svga_out(uint16_t addr, uint8_t val)
break; break;
} }
break; break;
case 0x3c6: dacmask=val; break;
case 0x3C7: dacread=val; dacpos=0; break; case 0x3C7: dacread=val; dacpos=0; break;
case 0x3C8: dacwrite=val; dacpos=0; break; case 0x3C8: dacwrite=val; dacpos=0; break;
case 0x3C9: case 0x3C9:
dacstatus = 0;
/* if (pc == 0x68AD)
{
dumpregs();
exit(-1);
}*/
palchange=1; palchange=1;
fullchange=changeframecount; fullchange=changeframecount;
switch (dacpos) switch (dacpos)
@ -85,6 +112,7 @@ void svga_out(uint16_t addr, uint8_t val)
break; break;
case 0x3CE: gdcaddr=val; break; case 0x3CE: gdcaddr=val; break;
case 0x3CF: case 0x3CF:
o = gdcreg[gdcaddr & 15];
switch (gdcaddr&15) switch (gdcaddr&15)
{ {
case 2: colourcompare=val; break; case 2: colourcompare=val; break;
@ -93,21 +121,21 @@ void svga_out(uint16_t addr, uint8_t val)
case 6: case 6:
if ((gdcreg[6] & 0xc) != (val & 0xc)) if ((gdcreg[6] & 0xc) != (val & 0xc))
{ {
mem_removehandler(0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); mem_removehandler(0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL);
// pclog("Write mapping %02X\n", val); pclog("Write mapping %02X\n", val);
switch (val&0xC) switch (val&0xC)
{ {
case 0x0: /*128k at A0000*/ case 0x0: /*128k at A0000*/
mem_sethandler(0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); mem_sethandler(0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL);
break; break;
case 0x4: /*64k at A0000*/ case 0x4: /*64k at A0000*/
mem_sethandler(0xa0000, 0x10000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); mem_sethandler(0xa0000, 0x10000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL);
break; break;
case 0x8: /*32k at B0000*/ case 0x8: /*32k at B0000*/
mem_sethandler(0xb0000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); mem_sethandler(0xb0000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL);
break; break;
case 0xC: /*32k at B8000*/ case 0xC: /*32k at B8000*/
mem_sethandler(0xb8000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); mem_sethandler(0xb8000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL);
break; break;
} }
} }
@ -116,11 +144,13 @@ void svga_out(uint16_t addr, uint8_t val)
} }
gdcreg[gdcaddr&15]=val; gdcreg[gdcaddr&15]=val;
svga_fast = (gdcreg[8]==0xFF && !(gdcreg[3]&0x18) && !gdcreg[1]) && chain4; svga_fast = (gdcreg[8]==0xFF && !(gdcreg[3]&0x18) && !gdcreg[1]) && chain4;
if (((gdcaddr & 15) == 5 && (val ^ o) & 0x70) || ((gdcaddr & 15) == 6 && (val ^ o) & 1))
svga_recalctimings();
break; break;
} }
} }
uint8_t svga_in(uint16_t addr) uint8_t svga_in(uint16_t addr, void *priv)
{ {
uint8_t temp; uint8_t temp;
// if (addr!=0x3da) pclog("Read port %04X\n",addr); // if (addr!=0x3da) pclog("Read port %04X\n",addr);
@ -128,12 +158,20 @@ uint8_t svga_in(uint16_t addr)
{ {
case 0x3C0: return attraddr; case 0x3C0: return attraddr;
case 0x3C1: return attrregs[attraddr]; case 0x3C1: return attrregs[attraddr];
case 0x3C2: return 0x10; case 0x3c2:
if ((vgapal[0].r + vgapal[0].g + vgapal[0].b) >= 0x50)
temp = 0;
else
temp = 0x10;
return temp;
case 0x3C4: return seqaddr; case 0x3C4: return seqaddr;
case 0x3C5: case 0x3C5:
return seqregs[seqaddr&0xF]; return seqregs[seqaddr&0xF];
case 0x3c6: return dacmask;
case 0x3c7: return dacstatus;
case 0x3C8: return dacwrite; case 0x3C8: return dacwrite;
case 0x3C9: case 0x3C9:
dacstatus=3;
palchange=1; palchange=1;
switch (dacpos) switch (dacpos)
{ {
@ -156,8 +194,9 @@ uint8_t svga_in(uint16_t addr)
} }
int svga_vtotal, svga_dispend, svga_vsyncstart, svga_split; int svga_vtotal, svga_dispend, svga_vsyncstart, svga_split;
int svga_hdisp, svga_htotal, svga_rowoffset; int svga_hdisp, svga_htotal, svga_hdisp_time, svga_rowoffset;
int svga_lowres, svga_interlace; int svga_lowres, svga_interlace;
int svga_linedbl, svga_rowcount;
double svga_clock; double svga_clock;
uint32_t svga_ma; uint32_t svga_ma;
void (*svga_recalctimings_ex)() = NULL; void (*svga_recalctimings_ex)() = NULL;
@ -166,7 +205,8 @@ void (*svga_hwcursor_draw)(int displine) = NULL;
void svga_recalctimings() void svga_recalctimings()
{ {
double crtcconst; double crtcconst;
int temp; double _dispontime, _dispofftime;
svga_vtotal=crtc[6]; svga_vtotal=crtc[6];
svga_dispend=crtc[0x12]; svga_dispend=crtc[0x12];
svga_vsyncstart=crtc[0x10]; svga_vsyncstart=crtc[0x10];
@ -204,32 +244,131 @@ void svga_recalctimings()
svga_interlace = 0; svga_interlace = 0;
svga_ma = (crtc[0xC]<<8)|crtc[0xD]; svga_ma = (crtc[0xC]<<8)|crtc[0xD];
svga_hdisp_time = svga_hdisp;
svga_render = svga_render_blank;
if (!scrblank)
{
if (!(gdcreg[6]&1)) /*Text mode*/
{
if (seqregs[1]&8) /*40 column*/
{
svga_render = svga_render_text_40;
svga_hdisp *= (seqregs[1] & 1) ? 16 : 18;
}
else
{
svga_render = svga_render_text_80;
svga_hdisp *= (seqregs[1] & 1) ? 8 : 9;
}
}
else
{
svga_hdisp *= (seqregs[1] & 8) ? 16 : 8;
switch (gdcreg[5]&0x60)
{
case 0x00: /*16 colours*/
if (seqregs[1]&8) /*Low res (320)*/
svga_render = svga_render_4bpp_lowres;
else
svga_render = svga_render_4bpp_highres;
break;
case 0x20: /*4 colours*/
svga_render = svga_render_2bpp_lowres;
break;
case 0x40: case 0x60: /*256+ colours*/
switch (bpp)
{
case 8:
if (svga_lowres)
svga_render = svga_render_8bpp_lowres;
else
{
svga_render = svga_render_8bpp_highres;
// svga_hdisp <<= 1;
}
break;
case 15:
if (svga_lowres)
svga_render = svga_render_15bpp_lowres;
else
{
svga_render = svga_render_15bpp_highres;
svga_hdisp <<= 1;
}
break;
case 16:
if (svga_lowres)
svga_render = svga_render_16bpp_lowres;
else
{
svga_render = svga_render_16bpp_highres;
svga_hdisp <<= 1;
}
break;
case 24:
if (svga_lowres)
{
svga_render = svga_render_24bpp_lowres;
svga_hdisp = ((svga_hdisp<<3)/3);
}
else
{
svga_render = svga_render_24bpp_highres;
svga_hdisp = ((svga_hdisp<<3)/3);
}
break;
case 32:
if (svga_lowres)
svga_render = svga_render_32bpp_lowres;
else
{
svga_render = svga_render_32bpp_highres;
svga_hdisp <<= 1;
}
break;
}
break;
}
}
}
// pclog("svga_render %08X : %08X %08X %08X %08X %08X %i %i %02X %i %i\n", svga_render, svga_render_text_40, svga_render_text_80, svga_render_8bpp_lowres, svga_render_8bpp_highres, svga_render_blank, scrblank,gdcreg[6]&1,gdcreg[5]&0x60,bpp,seqregs[1]&8);
svga_linedbl = crtc[9] & 0x80;
svga_rowcount = crtc[9] & 31;
if (svga_recalctimings_ex) svga_recalctimings_ex(); if (svga_recalctimings_ex) svga_recalctimings_ex();
crtcconst=(seqregs[1]&1)?(svga_clock*8.0):(svga_clock*9.0); crtcconst=(seqregs[1]&1)?(svga_clock*8.0):(svga_clock*9.0);
disptime =svga_htotal; disptime =svga_htotal;
dispontime=svga_hdisp; _dispontime = svga_hdisp_time;
// printf("Disptime %f dispontime %f hdisp %i\n",disptime,dispontime,crtc[1]*8); // printf("Disptime %f dispontime %f hdisp %i\n",disptime,dispontime,crtc[1]*8);
if (seqregs[1]&8) { disptime*=2; dispontime*=2; } if (seqregs[1]&8) { disptime*=2; _dispontime*=2; }
dispofftime=disptime-dispontime; _dispofftime=disptime-_dispontime;
dispontime*=crtcconst; _dispontime*=crtcconst;
dispofftime*=crtcconst; _dispofftime*=crtcconst;
dispontime = (int)(_dispontime * (1 << TIMER_SHIFT));
dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT));
// printf("SVGA horiz total %i display end %i clock rate %i vidclock %i %i\n",crtc[0],crtc[1],egaswitchread,vidclock,((ega3c2>>2)&3) | ((tridentnewctrl2<<2)&4)); // printf("SVGA horiz total %i display end %i clock rate %i vidclock %i %i\n",crtc[0],crtc[1],egaswitchread,vidclock,((ega3c2>>2)&3) | ((tridentnewctrl2<<2)&4));
// printf("SVGA vert total %i display end %i max row %i vsync %i\n",svga_vtotal,svga_dispend,(crtc[9]&31)+1,svga_vsyncstart); // printf("SVGA vert total %i display end %i max row %i vsync %i\n",svga_vtotal,svga_dispend,(crtc[9]&31)+1,svga_vsyncstart);
// printf("total %f on %f cycles off %f cycles frame %f sec %f %02X\n",disptime*crtcconst,dispontime,dispofftime,(dispontime+dispofftime)*svga_vtotal,(dispontime+dispofftime)*svga_vtotal*70,seqregs[1]); // printf("total %f on %f cycles off %f cycles frame %f sec %f %02X\n",disptime*crtcconst,dispontime,dispofftime,(dispontime+dispofftime)*svga_vtotal,(dispontime+dispofftime)*svga_vtotal*70,seqregs[1]);
// pclog("svga_render %08X\n", svga_render);
} }
void (*svga_render)();
static uint32_t ma,maback,ca; uint32_t ma, maback, ca;
static int vc,sc; static int vc;
static int linepos, displine, vslines, linecountff, oddeven; int sc;
static int linepos, vslines, linecountff, oddeven;
static int svga_dispon; static int svga_dispon;
static int con, coff, cursoron, cgablink; int con, coff, cursoron, cgablink;
static int scrollcache; int scrollcache;
int svga_hwcursor_on; int svga_hwcursor_on;
@ -237,17 +376,13 @@ SVGA_HWCURSOR svga_hwcursor, svga_hwcursor_latch;
int svga_hdisp_on; int svga_hdisp_on;
static int firstline_draw = 2000, lastline_draw = 0; int firstline_draw = 2000, lastline_draw = 0;
int displine;
void svga_poll() void svga_poll()
{ {
uint8_t chr,dat,attr; int x;
uint32_t charaddr;
int x,xx;
uint32_t fg,bg;
int offset;
uint8_t edat[4];
int drawcursor=0;
if (!linepos) if (!linepos)
{ {
// if (!(vc & 15)) pclog("VC %i %i\n", vc, GetTickCount()); // if (!(vc & 15)) pclog("VC %i %i\n", vc, GetTickCount());
@ -264,305 +399,17 @@ void svga_poll()
ma&=vrammask; ma&=vrammask;
if (firstline==2000) firstline=displine; if (firstline==2000) firstline=displine;
if (scrblank)
{ if (svga_hwcursor_on) changedvram[ma >> 10] = changedvram[(ma >> 10) + 1] = 2;
if (firstline_draw == 2000) firstline_draw = displine;
lastline_draw = displine; svga_render();
for (x=0;x<svga_hdisp;x++)
{
switch (seqregs[1]&9)
{
case 0:
for (xx=0;xx<9;xx++) ((uint32_t *)buffer32->line[displine])[(x*9)+xx+32]=0;
break;
case 1:
for (xx=0;xx<8;xx++) ((uint32_t *)buffer32->line[displine])[(x*8)+xx+32]=0;
break;
case 8:
for (xx=0;xx<18;xx++) ((uint32_t *)buffer32->line[displine])[(x*18)+xx+32]=0;
break;
case 9:
for (xx=0;xx<16;xx++) ((uint32_t *)buffer32->line[displine])[(x*16)+xx+32]=0;
break;
}
}
}
else if (!(gdcreg[6]&1)) /*Text mode*/
{
if (firstline_draw == 2000) firstline_draw = displine;
lastline_draw = displine;
if (fullchange)
{
for (x=0;x<svga_hdisp;x++)
{
drawcursor=((ma==ca) && con && cursoron);
chr=vram[(ma<<1)];
attr=vram[(ma<<1)+4];
if (attr&8) charaddr=charsetb+(chr*128);
else charaddr=charseta+(chr*128);
if (drawcursor) { bg=pallook[egapal[attr&15]]; fg=pallook[egapal[attr>>4]]; }
else
{
fg=pallook[egapal[attr&15]];
bg=pallook[egapal[attr>>4]];
if (attr&0x80 && attrregs[0x10]&8)
{
bg=pallook[egapal[(attr>>4)&7]];
if (cgablink&16) fg=bg;
}
}
dat=vram[charaddr+(sc<<2)];
if (seqregs[1]&8) /*40 column*/
{
if (seqregs[1]&1) { for (xx=0;xx<8;xx++) ((uint32_t *)buffer32->line[displine])[((x<<4)+32+(xx<<1))&2047]=((uint32_t *)buffer32->line[displine])[((x<<4)+33+(xx<<1))&2047]=(dat&(0x80>>xx))?fg:bg; }
else
{
for (xx=0;xx<8;xx++) ((uint32_t *)buffer32->line[displine])[((x*18)+32+(xx<<1))&2047]=((uint32_t *)buffer32->line[displine])[((x*18)+33+(xx<<1))&2047]=(dat&(0x80>>xx))?fg:bg;
if ((chr&~0x1F)!=0xC0 || !(attrregs[0x10]&4)) ((uint32_t *)buffer32->line[displine])[((x*18)+32+16)&2047]=((uint32_t *)buffer32->line[displine])[((x*18)+32+17)&2047]=bg;
else ((uint32_t *)buffer32->line[displine])[((x*18)+32+16)&2047]=((uint32_t *)buffer32->line[displine])[((x*18)+32+17)&2047]=(dat&1)?fg:bg;
}
}
else /*80 column*/
{
if (seqregs[1]&1) { for (xx=0;xx<8;xx++) ((uint32_t *)buffer32->line[displine])[((x<<3)+32+xx)&2047]=(dat&(0x80>>xx))?fg:bg; }
else
{
for (xx=0;xx<8;xx++) ((uint32_t *)buffer32->line[displine])[((x*9)+32+xx)&2047]=(dat&(0x80>>xx))?fg:bg;
if ((chr&~0x1F)!=0xC0 || !(attrregs[0x10]&4)) ((uint32_t *)buffer32->line[displine])[((x*9)+32+8)&2047]=bg;
else ((uint32_t *)buffer32->line[displine])[((x*9)+32+8)&2047]=(dat&1)?fg:bg;
}
}
ma+=4; ma&=vrammask;
}
}
}
else
{
// if (hwcursor_on) changedvram[ma>>10]=changedvram[(ma>>10)+1]=2;
switch (gdcreg[5]&0x60)
{
case 0x00: /*16 colours*/
if (firstline_draw == 2000) firstline_draw = displine;
lastline_draw = displine;
if (seqregs[1]&8) /*Low res (320)*/
{
offset=((8-scrollcache)<<1)+16;
for (x=0;x<=svga_hdisp;x++)
{
edat[0]=vram[ma];
edat[1]=vram[ma|0x1];
edat[2]=vram[ma|0x2];
edat[3]=vram[ma|0x3];
ma+=4; ma&=vrammask;
dat=edatlookup[edat[0]&3][edat[1]&3]|(edatlookup[edat[2]&3][edat[3]&3]<<2);
((uint32_t *)buffer32->line[displine])[(x<<4)+14+offset]=((uint32_t *)buffer32->line[displine])[(x<<4)+15+offset]=pallook[egapal[dat&0xF]];
((uint32_t *)buffer32->line[displine])[(x<<4)+12+offset]=((uint32_t *)buffer32->line[displine])[(x<<4)+13+offset]=pallook[egapal[dat>>4]];
dat=edatlookup[(edat[0]>>2)&3][(edat[1]>>2)&3]|(edatlookup[(edat[2]>>2)&3][(edat[3]>>2)&3]<<2);
((uint32_t *)buffer32->line[displine])[(x<<4)+10+offset]=((uint32_t *)buffer32->line[displine])[(x<<4)+11+offset]=pallook[egapal[dat&0xF]];
((uint32_t *)buffer32->line[displine])[(x<<4)+8+offset]= ((uint32_t *)buffer32->line[displine])[(x<<4)+9+offset]=pallook[egapal[dat>>4]];
dat=edatlookup[(edat[0]>>4)&3][(edat[1]>>4)&3]|(edatlookup[(edat[2]>>4)&3][(edat[3]>>4)&3]<<2);
((uint32_t *)buffer32->line[displine])[(x<<4)+6+offset]= ((uint32_t *)buffer32->line[displine])[(x<<4)+7+offset]=pallook[egapal[dat&0xF]];
((uint32_t *)buffer32->line[displine])[(x<<4)+4+offset]= ((uint32_t *)buffer32->line[displine])[(x<<4)+5+offset]=pallook[egapal[dat>>4]];
dat=edatlookup[edat[0]>>6][edat[1]>>6]|(edatlookup[edat[2]>>6][edat[3]>>6]<<2);
((uint32_t *)buffer32->line[displine])[(x<<4)+2+offset]= ((uint32_t *)buffer32->line[displine])[(x<<4)+3+offset]=pallook[egapal[dat&0xF]];
((uint32_t *)buffer32->line[displine])[(x<<4)+offset]= ((uint32_t *)buffer32->line[displine])[(x<<4)+1+offset]=pallook[egapal[dat>>4]];
}
}
else /*High res (640)*/
{
offset=(8-scrollcache)+24;
for (x=0;x<=svga_hdisp;x++)
{
edat[0]=vram[ma];
edat[1]=vram[ma|0x1];
edat[2]=vram[ma|0x2];
edat[3]=vram[ma|0x3];
ma+=4; ma&=vrammask;
dat=edatlookup[edat[0]&3][edat[1]&3]|(edatlookup[edat[2]&3][edat[3]&3]<<2);
((uint32_t *)buffer32->line[displine])[(x<<3)+7+offset]=pallook[egapal[dat&0xF]];
((uint32_t *)buffer32->line[displine])[(x<<3)+6+offset]=pallook[egapal[dat>>4]];
dat=edatlookup[(edat[0]>>2)&3][(edat[1]>>2)&3]|(edatlookup[(edat[2]>>2)&3][(edat[3]>>2)&3]<<2);
((uint32_t *)buffer32->line[displine])[(x<<3)+5+offset]=pallook[egapal[dat&0xF]];
((uint32_t *)buffer32->line[displine])[(x<<3)+4+offset]=pallook[egapal[dat>>4]];
dat=edatlookup[(edat[0]>>4)&3][(edat[1]>>4)&3]|(edatlookup[(edat[2]>>4)&3][(edat[3]>>4)&3]<<2);
((uint32_t *)buffer32->line[displine])[(x<<3)+3+offset]=pallook[egapal[dat&0xF]];
((uint32_t *)buffer32->line[displine])[(x<<3)+2+offset]=pallook[egapal[dat>>4]];
dat=edatlookup[edat[0]>>6][edat[1]>>6]|(edatlookup[edat[2]>>6][edat[3]>>6]<<2);
((uint32_t *)buffer32->line[displine])[(x<<3)+1+offset]=pallook[egapal[dat&0xF]];
((uint32_t *)buffer32->line[displine])[(x<<3)+offset]= pallook[egapal[dat>>4]];
}
}
break;
case 0x20: /*4 colours*/
if (firstline_draw == 2000) firstline_draw = displine;
lastline_draw = displine;
offset=((8-scrollcache)<<1)+16;
/*Low res (320) only, though high res (640) should be possible*/
for (x=0;x<=svga_hdisp;x++)
{
if (sc&1 && !(crtc[0x17]&1))
{
edat[0]=vram[(ma<<1)+0x8000];
edat[1]=vram[(ma<<1)+0x8004];
}
else
{
edat[0]=vram[(ma<<1)];
edat[1]=vram[(ma<<1)+4];
}
ma+=4; ma&=vrammask;
((uint32_t *)buffer32->line[displine])[(x<<4)+14+offset]=((uint32_t *)buffer32->line[displine])[(x<<4)+15+offset]=pallook[egapal[edat[1]&3]];
((uint32_t *)buffer32->line[displine])[(x<<4)+12+offset]=((uint32_t *)buffer32->line[displine])[(x<<4)+13+offset]=pallook[egapal[(edat[1]>>2)&3]];
dat=edatlookup[(edat[0]>>2)&3][(edat[1]>>2)&3]|(edatlookup[(edat[2]>>2)&3][(edat[3]>>2)&3]<<2);
((uint32_t *)buffer32->line[displine])[(x<<4)+10+offset]=((uint32_t *)buffer32->line[displine])[(x<<4)+11+offset]=pallook[egapal[(edat[1]>>4)&3]];
((uint32_t *)buffer32->line[displine])[(x<<4)+8+offset]= ((uint32_t *)buffer32->line[displine])[(x<<4)+9+offset]=pallook[egapal[(edat[1]>>6)&3]];
dat=edatlookup[(edat[0]>>4)&3][(edat[1]>>4)&3]|(edatlookup[(edat[2]>>4)&3][(edat[3]>>4)&3]<<2);
((uint32_t *)buffer32->line[displine])[(x<<4)+6+offset]= ((uint32_t *)buffer32->line[displine])[(x<<4)+7+offset]=pallook[egapal[(edat[0]>>0)&3]];
((uint32_t *)buffer32->line[displine])[(x<<4)+4+offset]= ((uint32_t *)buffer32->line[displine])[(x<<4)+5+offset]=pallook[egapal[(edat[0]>>2)&3]];
dat=edatlookup[edat[0]>>6][edat[1]>>6]|(edatlookup[edat[2]>>6][edat[3]>>6]<<2);
((uint32_t *)buffer32->line[displine])[(x<<4)+2+offset]= ((uint32_t *)buffer32->line[displine])[(x<<4)+3+offset]=pallook[egapal[(edat[0]>>4)&3]];
((uint32_t *)buffer32->line[displine])[(x<<4)+offset]= ((uint32_t *)buffer32->line[displine])[(x<<4)+1+offset]=pallook[egapal[(edat[0]>>6)&3]];
}
break;
case 0x40: case 0x60: /*256 colours (and more, with high/true colour RAMDAC)*/
if (changedvram[ma>>10] || changedvram[(ma>>10)+1] || changedvram[(ma>>10)+2] || fullchange)
{
if (firstline_draw == 2000) firstline_draw = displine;
lastline_draw = displine;
if (svga_lowres) /*Low res (320)*/
{
// if (!displine) pclog("Lo res %i %i %i\n",bpp,svga_hdisp,(svga_hdisp<<3)/3);
offset=(8-(scrollcache&6))+24;
if (bpp==8) /*Regular 8 bpp palette mode*/
{
for (x=0;x<=svga_hdisp;x++)
{
edat[0]=vram[ma];
edat[1]=vram[ma|0x1];
edat[2]=vram[ma|0x2];
edat[3]=vram[ma|0x3];
ma+=4; ma&=vrammask;
((uint32_t *)buffer32->line[displine])[(x<<3)+6+offset]= ((uint32_t *)buffer32->line[displine])[(x<<3)+7+offset]=pallook[edat[3]];
((uint32_t *)buffer32->line[displine])[(x<<3)+4+offset]= ((uint32_t *)buffer32->line[displine])[(x<<3)+5+offset]=pallook[edat[2]];
((uint32_t *)buffer32->line[displine])[(x<<3)+2+offset]= ((uint32_t *)buffer32->line[displine])[(x<<3)+3+offset]=pallook[edat[1]];
((uint32_t *)buffer32->line[displine])[(x<<3)+offset]= ((uint32_t *)buffer32->line[displine])[(x<<3)+1+offset]=pallook[edat[0]];
}
}
else if (bpp==16) /*16 bpp 565 mode*/
{
for (x=0;x<=svga_hdisp;x++)
{
fg=vram[ma]|(vram[ma|0x1]<<8);
bg=vram[ma|0x2]|(vram[ma|0x3]<<8);
ma+=4; ma&=vrammask;
((uint32_t *)buffer32->line[displine])[(x<<2)+2+offset]=((uint32_t *)buffer32->line[displine])[(x<<2)+3+offset]=((bg&31)<<3)|(((bg>>5)&63)<<10)|(((bg>>11)&31)<<19);
((uint32_t *)buffer32->line[displine])[(x<<2)+0+offset]=((uint32_t *)buffer32->line[displine])[(x<<2)+1+offset]=((fg&31)<<3)|(((fg>>5)&63)<<10)|(((fg>>11)&31)<<19);
}
}
else if (bpp==15) /*15 bpp 555 mode*/
{
for (x=0;x<=svga_hdisp;x++)
{
fg=vram[ma]|(vram[ma|0x1]<<8);
bg=vram[ma|0x2]|(vram[ma|0x3]<<8);
ma+=4; ma&=vrammask;
((uint32_t *)buffer32->line[displine])[(x<<1)+2+offset]=((uint32_t *)buffer32->line[displine])[(x<<2)+3+offset]=((bg&31)<<3)|(((bg>>5)&31)<<11)|(((bg>>10)&31)<<19);
((uint32_t *)buffer32->line[displine])[(x<<1)+0+offset]=((uint32_t *)buffer32->line[displine])[(x<<2)+1+offset]=((fg&31)<<3)|(((fg>>5)&31)<<11)|(((fg>>10)&31)<<19);
}
}
else if (bpp==24) /*24 bpp 888 mode*/
{
for (x=0;x<=((svga_hdisp<<3)/3);x++)
{
fg=vram[ma]|(vram[ma+1]<<8)|(vram[ma+2]<<16);
ma+=3; ma&=vrammask;
((uint32_t *)buffer32->line[displine])[(x<<1)+offset]=((uint32_t *)buffer32->line[displine])[(x<<1)+1+offset]=fg;
}
}
else if (bpp==32) /*32 bpp 8888 mode*/
{
for (x = 0; x <= svga_hdisp; x++)
{
fg = vram[ma] | (vram[ma + 1] << 8) | (vram[ma + 2] << 16);
ma += 4; ma &= vrammask;
((uint32_t *)buffer32->line[displine])[(x << 1) + offset] = ((uint32_t *)buffer32->line[displine])[(x << 1) + 1 + offset] = fg;
}
}
}
else /*High res (SVGA only)*/
{
// if (!displine) pclog("Hi res %i %i %i\n",bpp,svga_hdisp,(svga_hdisp<<3)/3);
offset=(8-((scrollcache&6)>>1))+24;
if (bpp==8)
{
for (x=0;x<=(svga_hdisp<<1);x++)
{
edat[0]=vram[ma];
edat[1]=vram[ma|0x1];
edat[2]=vram[ma|0x2];
edat[3]=vram[ma|0x3];
ma+=4; ma&=vrammask;
((uint32_t *)buffer32->line[displine])[(x<<2)+3+offset]=pallook[edat[3]];
((uint32_t *)buffer32->line[displine])[(x<<2)+2+offset]=pallook[edat[2]];
((uint32_t *)buffer32->line[displine])[(x<<2)+1+offset]=pallook[edat[1]];
((uint32_t *)buffer32->line[displine])[(x<<2)+offset]= pallook[edat[0]];
}
}
else if (bpp==16)
{
for (x=0;x<=(svga_hdisp<<1);x++)
{
fg=vram[ma]|(vram[ma|0x1]<<8);
bg=vram[ma|0x2]|(vram[ma|0x3]<<8);
ma+=4; ma&=vrammask;
((uint32_t *)buffer32->line[displine])[(x<<1)+1+offset]=((bg&31)<<3)|(((bg>>5)&63)<<10)|(((bg>>11)&31)<<19);
((uint32_t *)buffer32->line[displine])[(x<<1)+0+offset]=((fg&31)<<3)|(((fg>>5)&63)<<10)|(((fg>>11)&31)<<19);
}
}
else if (bpp==15)
{
for (x=0;x<=(svga_hdisp<<1);x++)
{
fg=vram[ma]|(vram[ma|0x1]<<8);
bg=vram[ma|0x2]|(vram[ma|0x3]<<8);
ma+=4; ma&=vrammask;
((uint32_t *)buffer32->line[displine])[(x<<1)+1+offset]=((bg&31)<<3)|(((bg>>5)&31)<<11)|(((bg>>10)&31)<<19);
((uint32_t *)buffer32->line[displine])[(x<<1)+0+offset]=((fg&31)<<3)|(((fg>>5)&31)<<11)|(((fg>>10)&31)<<19);
}
}
else if (bpp==24)
{
for (x=0;x<=((svga_hdisp<<3)/3);x++)
{
fg=vram[ma]|(vram[ma+1]<<8)|(vram[ma+2]<<16);
ma+=3; ma&=vrammask;
((uint32_t *)buffer32->line[displine])[x+offset]=fg;
}
}
else if (bpp==32)
{
for (x = 0; x <= (svga_hdisp<<2); x++)
{
fg = vram[ma] | (vram[ma + 1] << 8) | (vram[ma + 2] << 16);
ma += 4; ma &= vrammask;
((uint32_t *)buffer32->line[displine])[x + offset] = fg;
}
}
}
}
break;
}
if (svga_hwcursor_on) if (svga_hwcursor_on)
{ {
svga_hwcursor_draw(displine); svga_hwcursor_draw(displine);
svga_hwcursor_on--; svga_hwcursor_on--;
} }
}
if (lastline<displine) lastline=displine; if (lastline<displine) lastline=displine;
} }
@ -592,12 +439,12 @@ void svga_poll()
if (sc==(crtc[11]&31)) con = 0; if (sc==(crtc[11]&31)) con = 0;
if (svga_dispon) if (svga_dispon)
{ {
if ((crtc[9]&0x80) && !linecountff) if (svga_linedbl && !linecountff)
{ {
linecountff=1; linecountff=1;
ma=maback; ma=maback;
} }
else if (sc==(crtc[9]&31)) else if (sc == svga_rowcount)
{ {
linecountff=0; linecountff=0;
sc=0; sc=0;
@ -642,11 +489,11 @@ void svga_poll()
// pclog("VC vsync %i %i\n", firstline_draw, lastline_draw); // pclog("VC vsync %i %i\n", firstline_draw, lastline_draw);
svga_dispon=0; svga_dispon=0;
cgastat|=8; cgastat|=8;
if (seqregs[1]&8) x=svga_hdisp*((seqregs[1]&1)?8:9)*2; /*if (seqregs[1]&8) x=(svga_hdisp*((seqregs[1]&1)?8:9))*2;
else x=svga_hdisp*((seqregs[1]&1)?8:9); else */x = svga_hdisp;//*((seqregs[1]&1)?8:9);
if (bpp == 16 || bpp == 15) x /= 2; if (bpp == 16 || bpp == 15) x /= 2;
if (bpp == 24) x /= 3; // if (bpp == 24) x /= 3;
if (bpp == 32) x /= 4; if (bpp == 32) x /= 4;
if (svga_interlace && !oddeven) lastline++; if (svga_interlace && !oddeven) lastline++;
if (svga_interlace && oddeven) firstline--; if (svga_interlace && oddeven) firstline--;
@ -704,7 +551,7 @@ void svga_poll()
case 0x40: case 0x60: video_bpp = bpp; break; case 0x40: case 0x60: video_bpp = bpp; break;
} }
} }
video_bpp = bpp;
// if (svga_interlace && oddeven) ma=maback=ma+(svga_rowoffset<<2); // if (svga_interlace && oddeven) ma=maback=ma+(svga_rowoffset<<2);
// pclog("Addr %08X vson %03X vsoff %01X %02X %02X %02X %i %i\n",ma,svga_vsyncstart,crtc[0x11]&0xF,crtc[0xD],crtc[0xC],crtc[0x33], svga_interlace, oddeven); // pclog("Addr %08X vson %03X vsoff %01X %02X %02X %02X %i %i\n",ma,svga_vsyncstart,crtc[0x11]&0xF,crtc[0xD],crtc[0xC],crtc[0x33], svga_interlace, oddeven);
@ -751,20 +598,17 @@ int svga_init()
#define egacycles 1 #define egacycles 1
#define egacycles2 1 #define egacycles2 1
void svga_write(uint32_t addr, uint8_t val) void svga_write(uint32_t addr, uint8_t val, void *priv)
{ {
int x,y;
char s[2]={0,0};
uint8_t vala,valb,valc,vald,wm=writemask; uint8_t vala,valb,valc,vald,wm=writemask;
int writemask2 = writemask; int writemask2 = writemask;
int bankaddr;
egawrites++; egawrites++;
cycles -= video_timing_b; cycles -= video_timing_b;
cycles_lost += video_timing_b; cycles_lost += video_timing_b;
// pclog("Writeega %06X ",addr); if (svga_output) pclog("Writeega %06X ",addr);
if (addr>=0xB0000) addr&=0x7FFF; if (addr>=0xB0000) addr&=0x7FFF;
else else
{ {
@ -783,8 +627,8 @@ void svga_write(uint32_t addr, uint8_t val)
{ {
addr<<=2; addr<<=2;
} }
// pclog("%08X %02X %i %i %i\n", addr, val, writemask2, writemode, chain4);
addr&=0x7FFFFF; addr&=0x7FFFFF;
if (svga_output) pclog("%08X (%i, %i) %02X %i %i %i\n", addr, addr & 1023, addr >> 10, val, writemask2, writemode, chain4);
changedvram[addr>>10]=changeframecount; changedvram[addr>>10]=changeframecount;
switch (writemode) switch (writemode)
@ -929,10 +773,9 @@ void svga_write(uint32_t addr, uint8_t val)
} }
} }
uint8_t svga_read(uint32_t addr) uint8_t svga_read(uint32_t addr, void *priv)
{ {
uint8_t temp,temp2,temp3,temp4; uint8_t temp,temp2,temp3,temp4;
uint32_t addr2;
cycles -= video_timing_b; cycles -= video_timing_b;
cycles_lost += video_timing_b; cycles_lost += video_timing_b;
@ -985,20 +828,17 @@ uint8_t svga_read(uint32_t addr)
return vram[addr|readplane]; return vram[addr|readplane];
} }
void svga_write_linear(uint32_t addr, uint8_t val) void svga_write_linear(uint32_t addr, uint8_t val, void *priv)
{ {
int x,y;
char s[2]={0,0};
uint8_t vala,valb,valc,vald,wm=writemask; uint8_t vala,valb,valc,vald,wm=writemask;
int writemask2 = writemask; int writemask2 = writemask;
int bankaddr;
cycles -= video_timing_b; cycles -= video_timing_b;
cycles_lost += video_timing_b; cycles_lost += video_timing_b;
egawrites++; egawrites++;
// pclog("Write LFB %08X %02X ", addr, val); if (svga_output) pclog("Write LFB %08X %02X ", addr, val);
if (!(gdcreg[6]&1)) fullchange=2; if (!(gdcreg[6]&1)) fullchange=2;
if (chain4) if (chain4)
{ {
@ -1010,7 +850,7 @@ void svga_write_linear(uint32_t addr, uint8_t val)
addr<<=2; addr<<=2;
} }
addr &= 0x7fffff; addr &= 0x7fffff;
// pclog("%08X\n", addr); if (svga_output) pclog("%08X\n", addr);
changedvram[addr>>10]=changeframecount; changedvram[addr>>10]=changeframecount;
switch (writemode) switch (writemode)
@ -1155,7 +995,7 @@ void svga_write_linear(uint32_t addr, uint8_t val)
} }
} }
uint8_t svga_read_linear(uint32_t addr) uint8_t svga_read_linear(uint32_t addr, void *priv)
{ {
uint8_t temp,temp2,temp3,temp4; uint8_t temp,temp2,temp3,temp4;
@ -1220,8 +1060,16 @@ void svga_doblit(int y1, int y2)
ysize=wy+1; ysize=wy+1;
if (xsize<64) xsize=656; if (xsize<64) xsize=656;
if (ysize<32) ysize=200; if (ysize<32) ysize=200;
if (vres) updatewindowsize(xsize,ysize<<1); /* if (bpp > 8)
else updatewindowsize(xsize,ysize); {
if (vres) updatewindowsize(xsize<<1,ysize<<1);
else updatewindowsize(xsize<<1,ysize);
}
else
{*/
if (vres) updatewindowsize(xsize,ysize<<1);
else updatewindowsize(xsize,ysize);
// }
} }
if (vid_resize) if (vid_resize)
{ {
@ -1234,12 +1082,12 @@ void svga_doblit(int y1, int y2)
} }
void svga_writew(uint32_t addr, uint16_t val) void svga_writew(uint32_t addr, uint16_t val, void *priv)
{ {
if (!svga_fast) if (!svga_fast)
{ {
svga_write(addr, val); svga_write(addr, val, priv);
svga_write(addr + 1, val >> 8); svga_write(addr + 1, val >> 8, priv);
return; return;
} }
@ -1248,22 +1096,22 @@ void svga_writew(uint32_t addr, uint16_t val)
cycles -= video_timing_w; cycles -= video_timing_w;
cycles_lost += video_timing_w; cycles_lost += video_timing_w;
// pclog("Writew %05X ", addr); if (svga_output) pclog("Writew %05X ", addr);
addr = (addr & 0xffff) + svgawbank; addr = (addr & 0xffff) + svgawbank;
addr &= 0x7FFFFF; addr &= 0x7FFFFF;
// pclog("%08X %04X\n", addr, val); if (svga_output) pclog("%08X (%i, %i) %04X\n", addr, addr & 1023, addr >> 10, val);
changedvram[addr >> 10] = changeframecount; changedvram[addr >> 10] = changeframecount;
*(uint16_t *)&vram[addr] = val; *(uint16_t *)&vram[addr] = val;
} }
void svga_writel(uint32_t addr, uint32_t val) void svga_writel(uint32_t addr, uint32_t val, void *priv)
{ {
if (!svga_fast) if (!svga_fast)
{ {
svga_write(addr, val); svga_write(addr, val, priv);
svga_write(addr + 1, val >> 8); svga_write(addr + 1, val >> 8, priv);
svga_write(addr + 2, val >> 16); svga_write(addr + 2, val >> 16, priv);
svga_write(addr + 3, val >> 24); svga_write(addr + 3, val >> 24, priv);
return; return;
} }
@ -1272,19 +1120,19 @@ void svga_writel(uint32_t addr, uint32_t val)
cycles -= video_timing_l; cycles -= video_timing_l;
cycles_lost += video_timing_l; cycles_lost += video_timing_l;
// pclog("Writel %05X ", addr); if (svga_output) pclog("Writel %05X ", addr);
addr = (addr & 0xffff) + svgawbank; addr = (addr & 0xffff) + svgawbank;
addr &= 0x7FFFFF; addr &= 0x7FFFFF;
// pclog("%08X %08X\n", addr, val); if (svga_output) pclog("%08X (%i, %i) %08X\n", addr, addr & 1023, addr >> 10, val);
changedvram[addr >> 10] = changeframecount; changedvram[addr >> 10] = changeframecount;
*(uint32_t *)&vram[addr] = val; *(uint32_t *)&vram[addr] = val;
} }
uint16_t svga_readw(uint32_t addr) uint16_t svga_readw(uint32_t addr, void *priv)
{ {
if (!svga_fast) if (!svga_fast)
return svga_read(addr) | (svga_read(addr + 1) << 8); return svga_read(addr, priv) | (svga_read(addr + 1, priv) << 8);
egareads += 2; egareads += 2;
@ -1300,10 +1148,10 @@ uint16_t svga_readw(uint32_t addr)
return *(uint16_t *)&vram[addr]; return *(uint16_t *)&vram[addr];
} }
uint32_t svga_readl(uint32_t addr) uint32_t svga_readl(uint32_t addr, void *priv)
{ {
if (!svga_fast) if (!svga_fast)
return svga_read(addr) | (svga_read(addr + 1) << 8) | (svga_read(addr + 2) << 16) | (svga_read(addr + 3) << 24); return svga_read(addr, priv) | (svga_read(addr + 1, priv) << 8) | (svga_read(addr + 2, priv) << 16) | (svga_read(addr + 3, priv) << 24);
egareads += 4; egareads += 4;
@ -1319,12 +1167,12 @@ uint32_t svga_readl(uint32_t addr)
return *(uint32_t *)&vram[addr]; return *(uint32_t *)&vram[addr];
} }
void svga_writew_linear(uint32_t addr, uint16_t val) void svga_writew_linear(uint32_t addr, uint16_t val, void *priv)
{ {
if (!svga_fast) if (!svga_fast)
{ {
svga_write_linear(addr, val); svga_write_linear(addr, val, priv);
svga_write_linear(addr + 1, val >> 8); svga_write_linear(addr + 1, val >> 8, priv);
return; return;
} }
@ -1333,19 +1181,20 @@ void svga_writew_linear(uint32_t addr, uint16_t val)
cycles -= video_timing_w; cycles -= video_timing_w;
cycles_lost += video_timing_w; cycles_lost += video_timing_w;
if (svga_output) pclog("Write LFBw %08X %04X\n", addr, val);
addr &= 0x7FFFFF; addr &= 0x7FFFFF;
changedvram[addr >> 10] = changeframecount; changedvram[addr >> 10] = changeframecount;
*(uint16_t *)&vram[addr] = val; *(uint16_t *)&vram[addr] = val;
} }
void svga_writel_linear(uint32_t addr, uint32_t val) void svga_writel_linear(uint32_t addr, uint32_t val, void *priv)
{ {
if (!svga_fast) if (!svga_fast)
{ {
svga_write_linear(addr, val); svga_write_linear(addr, val, priv);
svga_write_linear(addr + 1, val >> 8); svga_write_linear(addr + 1, val >> 8, priv);
svga_write_linear(addr + 2, val >> 16); svga_write_linear(addr + 2, val >> 16, priv);
svga_write_linear(addr + 3, val >> 24); svga_write_linear(addr + 3, val >> 24, priv);
return; return;
} }
@ -1354,15 +1203,16 @@ void svga_writel_linear(uint32_t addr, uint32_t val)
cycles -= video_timing_l; cycles -= video_timing_l;
cycles_lost += video_timing_l; cycles_lost += video_timing_l;
if (svga_output) pclog("Write LFBl %08X %08X\n", addr, val);
addr &= 0x7fffff; addr &= 0x7fffff;
changedvram[addr >> 10] = changeframecount; changedvram[addr >> 10] = changeframecount;
*(uint32_t *)&vram[addr] = val; *(uint32_t *)&vram[addr] = val;
} }
uint16_t svga_readw_linear(uint32_t addr) uint16_t svga_readw_linear(uint32_t addr, void *priv)
{ {
if (!svga_fast) if (!svga_fast)
return svga_read_linear(addr) | (svga_read_linear(addr + 1) << 8); return svga_read_linear(addr, priv) | (svga_read_linear(addr + 1, priv) << 8);
egareads += 2; egareads += 2;
@ -1375,10 +1225,10 @@ uint16_t svga_readw_linear(uint32_t addr)
return *(uint16_t *)&vram[addr]; return *(uint16_t *)&vram[addr];
} }
uint32_t svga_readl_linear(uint32_t addr) uint32_t svga_readl_linear(uint32_t addr, void *priv)
{ {
if (!svga_fast) if (!svga_fast)
return svga_read_linear(addr) | (svga_read_linear(addr + 1) << 8) | (svga_read_linear(addr + 2) << 16) | (svga_read_linear(addr + 3) << 24); return svga_read_linear(addr, priv) | (svga_read_linear(addr + 1, priv) << 8) | (svga_read_linear(addr + 2, priv) << 16) | (svga_read_linear(addr + 3, priv) << 24);
egareads += 4; egareads += 4;

View file

@ -1,10 +1,12 @@
/*Vertical timings*/ /*Vertical timings*/
extern int svga_vtotal, svga_dispend, svga_vsyncstart, svga_split; extern int svga_vtotal, svga_dispend, svga_vsyncstart, svga_split;
/*Horizontal timings*/ /*Horizontal timings*/
extern int svga_hdisp, svga_htotal, svga_rowoffset; extern int svga_hdisp, svga_htotal, svga_hdisp_time, svga_rowoffset;
/*Flags - svga_lowres = 1/2 clock in 256+ colour modes, svga_interlace = interlace mode enabled*/ /*Flags - svga_lowres = 1/2 clock in 256+ colour modes, svga_interlace = interlace mode enabled*/
extern int svga_lowres, svga_interlace; extern int svga_lowres, svga_interlace;
extern int svga_linedbl, svga_rowcount;
/*Status of display on*/ /*Status of display on*/
extern int svga_hdisp_on; extern int svga_hdisp_on;
@ -35,19 +37,24 @@ extern SVGA_HWCURSOR svga_hwcursor, svga_hwcursor_latch;
extern int svga_hwcursor_on; extern int svga_hwcursor_on;
extern void (*svga_hwcursor_draw)(int displine); extern void (*svga_hwcursor_draw)(int displine);
uint8_t svga_read(uint32_t addr); uint8_t svga_read(uint32_t addr, void *priv);
uint16_t svga_readw(uint32_t addr); uint16_t svga_readw(uint32_t addr, void *priv);
uint32_t svga_readl(uint32_t addr); uint32_t svga_readl(uint32_t addr, void *priv);
void svga_write(uint32_t addr, uint8_t val); void svga_write(uint32_t addr, uint8_t val, void *priv);
void svga_writew(uint32_t addr, uint16_t val); void svga_writew(uint32_t addr, uint16_t val, void *priv);
void svga_writel(uint32_t addr, uint32_t val); void svga_writel(uint32_t addr, uint32_t val, void *priv);
uint8_t svga_read_linear(uint32_t addr); uint8_t svga_read_linear(uint32_t addr, void *priv);
uint16_t svga_readw_linear(uint32_t addr); uint16_t svga_readw_linear(uint32_t addr, void *priv);
uint32_t svga_readl_linear(uint32_t addr); uint32_t svga_readl_linear(uint32_t addr, void *priv);
void svga_write_linear(uint32_t addr, uint8_t val); void svga_write_linear(uint32_t addr, uint8_t val, void *priv);
void svga_writew_linear(uint32_t addr, uint16_t val); void svga_writew_linear(uint32_t addr, uint16_t val, void *priv);
void svga_writel_linear(uint32_t addr, uint32_t val); void svga_writel_linear(uint32_t addr, uint32_t val, void *priv);
void svga_doblit(int y1, int y2); void svga_doblit(int y1, int y2);
extern uint32_t svga_vram_limit; extern uint32_t svga_vram_limit;
extern uint8_t svga_rotate[8][256];
void svga_out(uint16_t addr, uint8_t val, void *priv);
uint8_t svga_in(uint16_t addr, void *priv);

View file

@ -2,6 +2,7 @@
#include "video.h" #include "video.h"
#include "io.h" #include "io.h"
#include "mem.h" #include "mem.h"
#include "timer.h"
static int tandy_array_index; static int tandy_array_index;
static uint8_t tandy_array[32]; static uint8_t tandy_array[32];
@ -14,7 +15,7 @@ static uint8_t *tandy_vram, *tandy_b8000;
void tandy_recalcaddress(); void tandy_recalcaddress();
void tandy_recalctimings(); void tandy_recalctimings();
void tandy_out(uint16_t addr, uint8_t val) void tandy_out(uint16_t addr, uint8_t val, void *priv)
{ {
uint8_t old; uint8_t old;
// pclog("Tandy OUT %04X %02X\n",addr,val); // pclog("Tandy OUT %04X %02X\n",addr,val);
@ -59,7 +60,7 @@ void tandy_out(uint16_t addr, uint8_t val)
} }
} }
uint8_t tandy_in(uint16_t addr) uint8_t tandy_in(uint16_t addr, void *priv)
{ {
// if (addr!=0x3DA) pclog("Tandy IN %04X\n",addr); // if (addr!=0x3DA) pclog("Tandy IN %04X\n",addr);
switch (addr) switch (addr)
@ -90,14 +91,14 @@ void tandy_recalcaddress()
} }
} }
void tandy_write(uint32_t addr, uint8_t val) void tandy_write(uint32_t addr, uint8_t val, void *priv)
{ {
if (tandy_memctrl==-1) return; if (tandy_memctrl==-1) return;
// pclog("Tandy VRAM write %05X %02X %04X:%04X %04X:%04X\n",addr,val,CS,pc,DS,SI); // pclog("Tandy VRAM write %05X %02X %04X:%04X %04X:%04X\n",addr,val,CS,pc,DS,SI);
tandy_b8000[addr&0x7FFF]=val; tandy_b8000[addr&0x7FFF]=val;
} }
uint8_t tandy_read(uint32_t addr) uint8_t tandy_read(uint32_t addr, void *priv)
{ {
if (tandy_memctrl==-1) return 0xFF; if (tandy_memctrl==-1) return 0xFF;
// pclog("Tandy VRAM read %05X %02X %04X:%04X\n",addr,tandy_b8000[addr&0x7FFF],CS,pc); // pclog("Tandy VRAM read %05X %02X %04X:%04X\n",addr,tandy_b8000[addr&0x7FFF],CS,pc);
@ -106,19 +107,22 @@ uint8_t tandy_read(uint32_t addr)
void tandy_recalctimings() void tandy_recalctimings()
{ {
double _dispontime, _dispofftime;
if (tandy_mode&1) if (tandy_mode&1)
{ {
disptime=crtc[0]+1; disptime=crtc[0]+1;
dispontime=crtc[1]; _dispontime=crtc[1];
} }
else else
{ {
disptime=(crtc[0]+1)<<1; disptime=(crtc[0]+1)<<1;
dispontime=crtc[1]<<1; _dispontime=crtc[1]<<1;
} }
dispofftime=disptime-dispontime; _dispofftime=disptime-_dispontime;
dispontime*=CGACONST; _dispontime*=CGACONST;
dispofftime*=CGACONST; _dispofftime*=CGACONST;
dispontime = (int)(_dispontime * (1 << TIMER_SHIFT));
dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT));
} }
@ -127,7 +131,7 @@ static int sc,vc;
static int cgadispon; static int cgadispon;
static int con,coff,cursoron,cgablink; static int con,coff,cursoron,cgablink;
static int vsynctime,vadj; static int vsynctime,vadj;
static uint16_t ma,maback,ca; static uint16_t ma,maback;
static int ntsc_col[8][8]= static int ntsc_col[8][8]=
{ {
@ -157,7 +161,7 @@ void tandy_poll()
int x,c; int x,c;
int oldvc; int oldvc;
uint8_t chr,attr; uint8_t chr,attr;
uint16_t dat,dat2,dat3,dat4; uint16_t dat;
int cols[4]; int cols[4];
int col; int col;
int oldsc; int oldsc;
@ -582,8 +586,8 @@ void tandy_poll()
int tandy_init() int tandy_init()
{ {
mem_sethandler(0xb8000, 0x8000, tandy_read, NULL, NULL, tandy_write, NULL, NULL); mem_sethandler(0xb8000, 0x8000, tandy_read, NULL, NULL, tandy_write, NULL, NULL, NULL);
io_sethandler(0x00a0, 0x0002, tandy_in, NULL, NULL, tandy_out, NULL, NULL); io_sethandler(0x00a0, 0x0002, tandy_in, NULL, NULL, tandy_out, NULL, NULL, NULL);
tandy_memctrl = -1; tandy_memctrl = -1;
return 0; return 0;
} }

View file

@ -7,7 +7,7 @@
static int tkd8001_state=0; static int tkd8001_state=0;
static uint8_t tkd8001_ctrl; static uint8_t tkd8001_ctrl;
void tkd8001_ramdac_out(uint16_t addr, uint8_t val) void tkd8001_ramdac_out(uint16_t addr, uint8_t val, void *priv)
{ {
// pclog("OUT RAMDAC %04X %02X %04X:%04X\n",addr,val,CS,pc); // pclog("OUT RAMDAC %04X %02X %04X:%04X\n",addr,val,CS,pc);
switch (addr) switch (addr)
@ -40,10 +40,10 @@ void tkd8001_ramdac_out(uint16_t addr, uint8_t val)
tkd8001_state = 0; tkd8001_state = 0;
break; break;
} }
svga_out(addr,val); svga_out(addr, val, NULL);
} }
uint8_t tkd8001_ramdac_in(uint16_t addr) uint8_t tkd8001_ramdac_in(uint16_t addr, void *priv)
{ {
// pclog("IN RAMDAC %04X %04X:%04X\n",addr,CS,pc); // pclog("IN RAMDAC %04X %04X:%04X\n",addr,CS,pc);
switch (addr) switch (addr)
@ -60,5 +60,5 @@ uint8_t tkd8001_ramdac_in(uint16_t addr)
tkd8001_state = 0; tkd8001_state = 0;
break; break;
} }
return svga_in(addr); return svga_in(addr, NULL);
} }

View file

@ -1,2 +1,2 @@
void tkd8001_ramdac_out(uint16_t addr, uint8_t val); void tkd8001_ramdac_out(uint16_t addr, uint8_t val, void *priv);
uint8_t tkd8001_ramdac_in(uint16_t addr); uint8_t tkd8001_ramdac_in(uint16_t addr, void *priv);

View file

@ -1,18 +1,37 @@
/*Trident TVGA (8900D) emulation*/ /*Trident TVGA (8900D) emulation*/
#include "ibm.h" #include "ibm.h"
#include "io.h"
#include "mem.h"
#include "video.h" #include "video.h"
#include "vid_svga.h" #include "vid_svga.h"
#include "vid_svga_render.h"
#include "vid_tkd8001_ramdac.h" #include "vid_tkd8001_ramdac.h"
void tvga_recalcmapping();
uint8_t trident3d8,trident3d9; uint8_t trident3d8,trident3d9;
int tridentoldmode; int tridentoldmode;
uint8_t tridentoldctrl2,tridentnewctrl2; uint8_t tridentoldctrl2,tridentnewctrl2;
uint8_t tridentdac; uint8_t tridentdac;
void tvga_out(uint16_t addr, uint8_t val) uint32_t tvga_linear_base, tvga_linear_size;
uint8_t tvga_accel_read(uint32_t addr, void *priv);
uint16_t tvga_accel_read_w(uint32_t addr, void *priv);
uint32_t tvga_accel_read_l(uint32_t addr, void *priv);
void tvga_accel_write(uint32_t addr, uint8_t val, void *priv);
void tvga_accel_write_w(uint32_t addr, uint16_t val, void *priv);
void tvga_accel_write_l(uint32_t addr, uint32_t val, void *priv);
void tvga_accel_write_fb_l(uint32_t addr, uint32_t val, void *priv);
void tvga_out(uint16_t addr, uint8_t val, void *priv)
{ {
uint8_t old; uint8_t old;
// pclog("tvga_out : %04X %02X %04X:%04X %i\n", addr, val, CS,pc, bpp);
if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga_miscout&1)) addr ^= 0x60; if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga_miscout&1)) addr ^= 0x60;
switch (addr) switch (addr)
@ -32,12 +51,24 @@ void tvga_out(uint16_t addr, uint8_t val)
break; break;
case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
tkd8001_ramdac_out(addr,val); if (gfxcard != GFX_TGUI9440)
return; {
tkd8001_ramdac_out(addr, val, NULL);
return;
}
break;
case 0x3CF: case 0x3CF:
switch (gdcaddr&15) switch (gdcaddr&15)
{ {
case 0x6:
if (gdcreg[6] != val)
{
gdcreg[6] = val;
tvga_recalcmapping();
}
return;
case 0xE: case 0xE:
gdcreg[0xE]=val^2; gdcreg[0xE]=val^2;
if ((gdcreg[0xF]&1)==1) if ((gdcreg[0xF]&1)==1)
@ -51,7 +82,8 @@ void tvga_out(uint16_t addr, uint8_t val)
} }
break; break;
case 0x3D4: case 0x3D4:
crtcreg=val&63; if (gfxcard == GFX_TGUI9440) crtcreg = val & 0x7f;
else crtcreg = val & 0x3f;
return; return;
case 0x3D5: case 0x3D5:
if (crtcreg <= 7 && crtc[0x11] & 0x80) return; if (crtcreg <= 7 && crtc[0x11] & 0x80) return;
@ -66,6 +98,37 @@ void tvga_out(uint16_t addr, uint8_t val)
svga_recalctimings(); svga_recalctimings();
} }
} }
switch (crtcreg)
{
case 0x21:
if (old != val)
tvga_recalcmapping();
break;
case 0x38: /*Pixel bus register*/
// pclog("Pixel bus register %02X\n", val);
if (gfxcard != GFX_TGUI9440)
break;
if ((val & 0xc) == 4) bpp = 16;
else if (!(val & 0xc)) bpp = 8;
else bpp = 24;
break;
case 0x40: case 0x41: case 0x42: case 0x43:
case 0x44: case 0x45: case 0x46: case 0x47:
svga_hwcursor.x = (crtc[0x40] | (crtc[0x41] << 8)) & 0x7ff;
svga_hwcursor.y = (crtc[0x42] | (crtc[0x43] << 8)) & 0x7ff;
svga_hwcursor.xoff = crtc[0x46] & 0x3f;
svga_hwcursor.yoff = crtc[0x47] & 0x3f;
svga_hwcursor.addr = (crtc[0x44] << 10) | ((crtc[0x45] & 0x7) << 18) | (svga_hwcursor.yoff * 8);
break;
case 0x50:
svga_hwcursor.ena = val & 0x80;
break;
}
return; return;
case 0x3D8: case 0x3D8:
trident3d8=val; trident3d8=val;
@ -89,12 +152,12 @@ void tvga_out(uint16_t addr, uint8_t val)
} }
return; return;
} }
svga_out(addr,val); svga_out(addr, val, priv);
} }
uint8_t tvga_in(uint16_t addr) uint8_t tvga_in(uint16_t addr, void *priv)
{ {
uint8_t temp; // if (addr != 0x3da) pclog("tvga_in : %04X %04X:%04X\n", addr, CS,pc);
if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga_miscout&1)) addr ^= 0x60; if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga_miscout&1)) addr ^= 0x60;
@ -105,7 +168,8 @@ uint8_t tvga_in(uint16_t addr)
{ {
// printf("Read Trident ID %04X:%04X %04X\n",CS,pc,readmemw(ss,SP)); // printf("Read Trident ID %04X:%04X %04X\n",CS,pc,readmemw(ss,SP));
tridentoldmode=0; tridentoldmode=0;
return 0x33; /*TVGA8900D*/ if (gfxcard == GFX_TVGA) return 0x33; /*TVGA8900D*/
else return 0xe3; /*TGUI9440AGi*/
} }
if ((seqaddr&0xF)==0xC) if ((seqaddr&0xF)==0xC)
{ {
@ -119,15 +183,21 @@ uint8_t tvga_in(uint16_t addr)
} }
break; break;
case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
return tkd8001_ramdac_in(addr); if (gfxcard != GFX_TGUI9440)
return tkd8001_ramdac_in(addr, NULL);
break;
case 0x3CD: /*Banking*/ case 0x3CD: /*Banking*/
return svgaseg; return svgaseg;
case 0x3D4: case 0x3D4:
return crtcreg; return crtcreg;
case 0x3D5: case 0x3D5:
return crtc[crtcreg]; return crtc[crtcreg];
case 0x3d8:
return trident3d8;
case 0x3d9:
return trident3d9;
} }
return svga_in(addr); return svga_in(addr, priv);
} }
void tvga_recalctimings() void tvga_recalctimings()
@ -147,7 +217,9 @@ void tvga_recalctimings()
} }
if (tridentoldctrl2 & 0x10) /*I'm not convinced this is the right register for this function*/ if (tridentoldctrl2 & 0x10) /*I'm not convinced this is the right register for this function*/
svga_lowres=0; svga_lowres=0;
if (gfxcard == GFX_TGUI9440)
svga_lowres = !(crtc[0x2a] & 0x40);
if (gdcreg[0xF] & 8) if (gdcreg[0xF] & 8)
{ {
svga_htotal<<=1; svga_htotal<<=1;
@ -166,16 +238,703 @@ void tvga_recalctimings()
case 6: svga_clock = cpuclock/50350000.0; break; case 6: svga_clock = cpuclock/50350000.0; break;
case 7: svga_clock = cpuclock/40000000.0; break; case 7: svga_clock = cpuclock/40000000.0; break;
} }
if ((tridentoldctrl2 & 0x10) || (gfxcard == GFX_TGUI9440 && (crtc[0x2a] & 0x40)))
{
switch (bpp)
{
case 8:
svga_render = svga_render_8bpp_highres;
break;
case 15:
svga_render = svga_render_15bpp_highres;
break;
case 16:
svga_render = svga_render_16bpp_highres;
break;
case 24:
svga_render = svga_render_24bpp_highres;
break;
case 32:
svga_render = svga_render_32bpp_highres;
break;
}
}
}
void tvga_recalcmapping()
{
pclog("tvga_recalcmapping : %02X %02X\n", crtc[0x21], gdcreg[6]);
mem_removehandler(0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL);
mem_removehandler(tvga_linear_base, tvga_linear_size, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL);
mem_removehandler(0xbc000, 0x4000, tvga_accel_read, NULL, NULL, tvga_accel_write, NULL, NULL, NULL);
if (crtc[0x21] & 0x20)
{
tvga_linear_base = ((crtc[0x21] & 0xf) | ((crtc[0x21] >> 2) & 0x30)) << 20;
tvga_linear_size = (crtc[0x21] & 0x10) ? 0x200000 : 0x100000;
mem_sethandler(tvga_linear_base, tvga_linear_size, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL);
pclog("Trident linear framebuffer at %08X - size %06X\n", tvga_linear_base, tvga_linear_size);
mem_sethandler(0xbc000, 0x4000, tvga_accel_read, tvga_accel_read_w, tvga_accel_read_l, tvga_accel_write, tvga_accel_write_w, tvga_accel_write_l, NULL);
}
else
{
// pclog("Write mapping %02X\n", val);
switch (gdcreg[6] & 0xC)
{
case 0x0: /*128k at A0000*/
mem_sethandler(0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL);
break;
case 0x4: /*64k at A0000*/
mem_sethandler(0xa0000, 0x10000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL);
mem_sethandler(0xbc000, 0x4000, tvga_accel_read, NULL, NULL, tvga_accel_write, NULL, NULL, NULL);
break;
case 0x8: /*32k at B0000*/
mem_sethandler(0xb0000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL);
break;
case 0xC: /*32k at B8000*/
mem_sethandler(0xb8000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL);
break;
}
}
}
void tvga_hwcursor_draw(int displine)
{
// int x;
uint32_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);
// for (x = 0; x < 32; x += 32)
// {
dat[0] = (vram[svga_hwcursor_latch.addr] << 24) | (vram[svga_hwcursor_latch.addr + 1] << 16) | (vram[svga_hwcursor_latch.addr + 2] << 8) | vram[svga_hwcursor_latch.addr + 3];
dat[1] = (vram[svga_hwcursor_latch.addr + 4] << 24) | (vram[svga_hwcursor_latch.addr + 5] << 16) | (vram[svga_hwcursor_latch.addr + 6] << 8) | vram[svga_hwcursor_latch.addr + 7];
for (xx = 0; xx < 32; xx++)
{
if (offset >= svga_hwcursor_latch.x)
{
if (!(dat[0] & 0x80000000))
((uint32_t *)buffer32->line[displine])[offset + 32] = (dat[1] & 0x80000000) ? 0xffffff : 0;
else if (dat[1] & 0x80000000)
((uint32_t *)buffer32->line[displine])[offset + 32] ^= 0xffffff;
// pclog("Plot %i, %i (%i %i) %04X %04X\n", offset, displine, x+xx, svga_hwcursor_on, dat[0], dat[1]);
}
offset++;
dat[0] <<= 1;
dat[1] <<= 1;
}
svga_hwcursor_latch.addr += 8;
// }
} }
int tvga_init() int tvga_init()
{ {
svga_recalctimings_ex = tvga_recalctimings; svga_recalctimings_ex = tvga_recalctimings;
svga_vram_limit = 1 << 20; /*1mb - chip supports 2mb, but drivers are buggy*/ svga_hwcursor_draw = tvga_hwcursor_draw;
vrammask = 0xfffff; if (gfxcard == GFX_TVGA)
{
vrammask = 0xfffff;
svga_vram_limit = 1 << 20; /*1mb - chip supports 2mb, but drivers are buggy*/
}
else
{
vrammask = 0x1fffff;
svga_vram_limit = 1 << 21; /*2mb*/
}
return svga_init(); return svga_init();
} }
struct tvga_accel
{
uint16_t src_x, src_y;
uint16_t dst_x, dst_y;
uint16_t size_x, size_y;
uint16_t fg_col, bg_col;
uint8_t rop;
uint16_t flags;
uint8_t pattern[0x80];
int command;
int offset;
uint8_t ger22;
int x, y;
uint32_t src, dst, src_old, dst_old;
int pat_x, pat_y;
int use_src;
int pitch, bpp;
} tvga_accel;
enum
{
TGUI_BITBLT = 1
};
enum
{
TGUI_SRCCPU = 0,
TGUI_SRCDISP = 0x04, /*Source is from display*/
TGUI_PATMONO = 0x20, /*Pattern is monochrome and needs expansion*/
TGUI_SRCMONO = 0x40, /*Source is monochrome from CPU and needs expansion*/
TGUI_TRANSENA = 0x1000, /*Transparent (no draw when source == bg col)*/
TGUI_TRANSREV = 0x2000, /*Reverse fg/bg for transparent*/
TGUI_SOLIDFILL = 0x4000 /*Pattern all zero?*/
};
#define READ(addr, dat) if (tvga_accel.bpp == 0) dat = vram[addr & 0x1fffff]; \
else dat = vram_w[addr & 0xfffff];
#define MIX() do \
{ \
out = 0; \
for (c=0;c<16;c++) \
{ \
d=(dst_dat & (1<<c)) ? 1:0; \
if (src_dat & (1<<c)) d|=2; \
if (pat_dat & (1<<c)) d|=4; \
if (tvga_accel.rop & (1<<d)) out|=(1<<c); \
} \
} while (0)
#define WRITE(addr, dat) if (tvga_accel.bpp == 0) \
{ \
vram[addr & 0x1fffff] = dat; \
changedvram[((addr) & 0x1fffff) >> 10] = changeframecount; \
} \
else \
{ \
vram_w[addr & 0xfffff] = dat; \
changedvram[((addr) & 0xfffff) >> 9] = changeframecount; \
}
static uint16_t tvga_pattern[8][8];
void tvga_accel_write_fb_b(uint32_t addr, uint8_t val, void *priv);
void tvga_accel_write_fb_w(uint32_t addr, uint16_t val, void *priv);
void tvga_accel_command(int count, uint32_t cpu_dat)
{
int x, y;
int c, d;
uint16_t src_dat, dst_dat, pat_dat;
uint16_t out;
int xdir = (tvga_accel.flags & 0x200) ? -1 : 1;
int ydir = (tvga_accel.flags & 0x100) ? -1 : 1;
uint16_t trans_col = (tvga_accel.flags & TGUI_TRANSREV) ? tvga_accel.fg_col : tvga_accel.bg_col;
uint16_t *vram_w = (uint16_t *)vram;
if (tvga_accel.bpp == 0)
trans_col &= 0xff;
if (count != -1 && !tvga_accel.x)
{
count -= tvga_accel.offset;
cpu_dat <<= tvga_accel.offset;
}
if (count == -1)
{
tvga_accel.x = tvga_accel.y = 0;
}
if (tvga_accel.flags & TGUI_SOLIDFILL)
{
// pclog("SOLIDFILL\n");
for (y = 0; y < 8; y++)
{
for (x = 0; x < 8; x++)
{
tvga_pattern[y][x] = tvga_accel.fg_col;
}
}
}
else if (tvga_accel.flags & TGUI_PATMONO)
{
// pclog("PATMONO\n");
for (y = 0; y < 8; y++)
{
for (x = 0; x < 8; x++)
{
tvga_pattern[y][x] = (tvga_accel.pattern[y] & (1 << x)) ? tvga_accel.fg_col : tvga_accel.bg_col;
}
}
}
else
{
// pclog("OTHER\n");
for (y = 0; y < 8; y++)
{
for (x = 0; x < 8; x++)
{
tvga_pattern[y][x] = tvga_accel.pattern[x + y*8];
}
}
}
for (y = 0; y < 8; y++)
{
if (count == -1) pclog("Pattern %i : %02X %02X %02X %02X %02X %02X %02X %02X\n", y, tvga_pattern[y][0], tvga_pattern[y][1], tvga_pattern[y][2], tvga_pattern[y][3], tvga_pattern[y][4], tvga_pattern[y][5], tvga_pattern[y][6], tvga_pattern[y][7]);
}
if (count == -1) pclog("Command %i %i\n", tvga_accel.command, TGUI_BITBLT);
switch (tvga_accel.command)
{
case TGUI_BITBLT:
if (count == -1) pclog("BITBLT src %i,%i dst %i,%i size %i,%i flags %04X\n", tvga_accel.src_x, tvga_accel.src_y, tvga_accel.dst_x, tvga_accel.dst_y, tvga_accel.size_x, tvga_accel.size_y, tvga_accel.flags);
if (count == -1)
{
tvga_accel.src = tvga_accel.src_old = tvga_accel.src_x + (tvga_accel.src_y * tvga_accel.pitch);
tvga_accel.dst = tvga_accel.dst_old = tvga_accel.dst_x + (tvga_accel.dst_y * tvga_accel.pitch);
tvga_accel.pat_x = tvga_accel.dst_x;
tvga_accel.pat_y = tvga_accel.dst_y;
}
switch (tvga_accel.flags & (TGUI_SRCMONO|TGUI_SRCDISP))
{
case TGUI_SRCCPU:
if (count == -1)
{
// pclog("Blit start\n");
if (crtc[0x21] & 0x20)
{
mem_removehandler(tvga_linear_base, tvga_linear_size, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL);
mem_sethandler(tvga_linear_base, tvga_linear_size, svga_read_linear, svga_readw_linear, svga_readl_linear, tvga_accel_write_fb_b, tvga_accel_write_fb_w, tvga_accel_write_fb_l, NULL);
}
if (tvga_accel.use_src)
return;
}
else
count >>= 3;
while (count)
{
if (tvga_accel.bpp == 0)
{
src_dat = cpu_dat >> 24;
cpu_dat <<= 8;
}
else
{
src_dat = (cpu_dat >> 24) | ((cpu_dat >> 8) & 0xff00);
cpu_dat <<= 16;
count--;
}
READ(tvga_accel.dst, dst_dat);
pat_dat = tvga_pattern[tvga_accel.pat_y & 7][tvga_accel.pat_x & 7];
if (!(tvga_accel.flags & TGUI_TRANSENA) || src_dat != trans_col)
{
MIX();
WRITE(tvga_accel.dst, out);
}
// pclog(" %i,%i %02X %02X %02X %02X\n", tvga_accel.x, tvga_accel.y, src_dat,dst_dat,pat_dat, out);
tvga_accel.src += xdir;
tvga_accel.dst += xdir;
tvga_accel.pat_x += xdir;
tvga_accel.x++;
if (tvga_accel.x > tvga_accel.size_x)
{
tvga_accel.x = 0;
tvga_accel.y++;
tvga_accel.pat_x = tvga_accel.dst_x;
tvga_accel.src = tvga_accel.src_old = tvga_accel.src_old + (ydir * tvga_accel.pitch);
tvga_accel.dst = tvga_accel.dst_old = tvga_accel.dst_old + (ydir * tvga_accel.pitch);
tvga_accel.pat_y += ydir;
if (tvga_accel.y > tvga_accel.size_y)
{
if (crtc[0x21] & 0x20)
{
// pclog("Blit end\n");
mem_removehandler(tvga_linear_base, tvga_linear_size, svga_read_linear, svga_readw_linear, svga_readl_linear, tvga_accel_write_fb_b, tvga_accel_write_fb_w, tvga_accel_write_fb_l, NULL);
mem_sethandler(tvga_linear_base, tvga_linear_size, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL);
}
return;
}
if (tvga_accel.use_src)
return;
}
count--;
}
break;
case TGUI_SRCMONO | TGUI_SRCCPU:
if (count == -1)
{
// pclog("Blit start\n");
if (crtc[0x21] & 0x20)
{
mem_removehandler(tvga_linear_base, tvga_linear_size, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL);
mem_sethandler(tvga_linear_base, tvga_linear_size, svga_read_linear, svga_readw_linear, svga_readl_linear, tvga_accel_write_fb_b, tvga_accel_write_fb_w, tvga_accel_write_fb_l, NULL);
}
if (tvga_accel.use_src)
return;
}
// pclog("TGUI_SRCMONO | TGUI_SRCCPU\n");
while (count)
{
src_dat = ((cpu_dat >> 31) ? tvga_accel.fg_col : tvga_accel.bg_col);
if (tvga_accel.bpp == 0)
src_dat &= 0xff;
READ(tvga_accel.dst, dst_dat);
pat_dat = tvga_pattern[tvga_accel.pat_y & 7][tvga_accel.pat_x & 7];
if (!(tvga_accel.flags & TGUI_TRANSENA) || src_dat != trans_col)
{
MIX();
WRITE(tvga_accel.dst, out);
}
// pclog(" %i,%i %02X %02X %02X %02X %i\n", tvga_accel.x, tvga_accel.y, src_dat,dst_dat,pat_dat, out, (!(tvga_accel.flags & TGUI_TRANSENA) || src_dat != trans_col));
cpu_dat <<= 1;
tvga_accel.src += xdir;
tvga_accel.dst += xdir;
tvga_accel.pat_x += xdir;
tvga_accel.x++;
if (tvga_accel.x > tvga_accel.size_x)
{
tvga_accel.x = 0;
tvga_accel.y++;
tvga_accel.pat_x = tvga_accel.dst_x;
tvga_accel.src = tvga_accel.src_old = tvga_accel.src_old + (ydir * tvga_accel.pitch);
tvga_accel.dst = tvga_accel.dst_old = tvga_accel.dst_old + (ydir * tvga_accel.pitch);
tvga_accel.pat_y += ydir;
if (tvga_accel.y > tvga_accel.size_y)
{
if (crtc[0x21] & 0x20)
{
// pclog("Blit end\n");
mem_removehandler(tvga_linear_base, tvga_linear_size, svga_read_linear, svga_readw_linear, svga_readl_linear, tvga_accel_write_fb_b, tvga_accel_write_fb_w, tvga_accel_write_fb_l, NULL);
mem_sethandler(tvga_linear_base, tvga_linear_size, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL);
}
return;
}
if (tvga_accel.use_src)
return;
}
count--;
}
break;
default:
while (count)
{
READ(tvga_accel.src, src_dat);
READ(tvga_accel.dst, dst_dat);
pat_dat = tvga_pattern[tvga_accel.pat_y & 7][tvga_accel.pat_x & 7];
if (!(tvga_accel.flags & TGUI_TRANSENA) || src_dat != trans_col)
{
MIX();
WRITE(tvga_accel.dst, out);
}
// pclog(" %i,%i %02X %02X %02X %02X\n", tvga_accel.x, tvga_accel.y, src_dat,dst_dat,pat_dat, out);
tvga_accel.src += xdir;
tvga_accel.dst += xdir;
tvga_accel.pat_x += xdir;
tvga_accel.x++;
if (tvga_accel.x > tvga_accel.size_x)
{
tvga_accel.x = 0;
tvga_accel.y++;
tvga_accel.pat_x = tvga_accel.dst_x;
tvga_accel.src = tvga_accel.src_old = tvga_accel.src_old + (ydir * tvga_accel.pitch);
tvga_accel.dst = tvga_accel.dst_old = tvga_accel.dst_old + (ydir * tvga_accel.pitch);
tvga_accel.pat_y += ydir;
if (tvga_accel.y > tvga_accel.size_y)
return;
}
count--;
}
break;
}
break;
}
}
void tvga_accel_write(uint32_t addr, uint8_t val, void *priv)
{
pclog("tvga_accel_write : %08X %02X %04X(%08X):%08X %02X\n", addr, val, CS,cs,pc, opcode);
if ((addr & ~0xff) != 0xbff00)
return;
switch (addr & 0xff)
{
case 0x22:
tvga_accel.ger22 = val;
tvga_accel.pitch = 512 << ((val >> 2) & 3);
tvga_accel.bpp = (val & 3) ? 1 : 0;
tvga_accel.pitch >>= tvga_accel.bpp;
break;
case 0x24: /*Command*/
tvga_accel.command = val;
tvga_accel_command(-1, 0);
break;
case 0x27: /*ROP*/
tvga_accel.rop = val;
tvga_accel.use_src = (val & 0x33) ^ ((val >> 2) & 0x33);
pclog("Write ROP %02X %i\n", val, tvga_accel.use_src);
break;
case 0x28: /*Flags*/
tvga_accel.flags = (tvga_accel.flags & 0xff00) | val;
break;
case 0x29: /*Flags*/
tvga_accel.flags = (tvga_accel.flags & 0xff) | (val << 8);
break;
case 0x2b:
tvga_accel.offset = val & 7;
break;
case 0x2c: /*Foreground colour*/
tvga_accel.fg_col = (tvga_accel.fg_col & 0xff00) | val;
break;
case 0x2d: /*Foreground colour*/
tvga_accel.fg_col = (tvga_accel.fg_col & 0xff) | (val << 8);
break;
case 0x30: /*Background colour*/
tvga_accel.bg_col = (tvga_accel.bg_col & 0xff00) | val;
break;
case 0x31: /*Background colour*/
tvga_accel.bg_col = (tvga_accel.bg_col & 0xff) | (val << 8);
break;
case 0x38: /*Dest X*/
tvga_accel.dst_x = (tvga_accel.dst_x & 0xff00) | val;
break;
case 0x39: /*Dest X*/
tvga_accel.dst_x = (tvga_accel.dst_x & 0xff) | (val << 8);
break;
case 0x3a: /*Dest Y*/
tvga_accel.dst_y = (tvga_accel.dst_y & 0xff00) | val;
break;
case 0x3b: /*Dest Y*/
tvga_accel.dst_y = (tvga_accel.dst_y & 0xff) | (val << 8);
break;
case 0x3c: /*Src X*/
tvga_accel.src_x = (tvga_accel.src_x & 0xff00) | val;
break;
case 0x3d: /*Src X*/
tvga_accel.src_x = (tvga_accel.src_x & 0xff) | (val << 8);
break;
case 0x3e: /*Src Y*/
tvga_accel.src_y = (tvga_accel.src_y & 0xff00) | val;
break;
case 0x3f: /*Src Y*/
tvga_accel.src_y = (tvga_accel.src_y & 0xff) | (val << 8);
break;
case 0x40: /*Size X*/
tvga_accel.size_x = (tvga_accel.size_x & 0xff00) | val;
break;
case 0x41: /*Size X*/
tvga_accel.size_x = (tvga_accel.size_x & 0xff) | (val << 8);
break;
case 0x42: /*Size Y*/
tvga_accel.size_y = (tvga_accel.size_y & 0xff00) | val;
break;
case 0x43: /*Size Y*/
tvga_accel.size_y = (tvga_accel.size_y & 0xff) | (val << 8);
break;
case 0x80: case 0x81: case 0x82: case 0x83:
case 0x84: case 0x85: case 0x86: case 0x87:
case 0x88: case 0x89: case 0x8a: case 0x8b:
case 0x8c: case 0x8d: case 0x8e: case 0x8f:
case 0x90: case 0x91: case 0x92: case 0x93:
case 0x94: case 0x95: case 0x96: case 0x97:
case 0x98: case 0x99: case 0x9a: case 0x9b:
case 0x9c: case 0x9d: case 0x9e: case 0x9f:
case 0xa0: case 0xa1: case 0xa2: case 0xa3:
case 0xa4: case 0xa5: case 0xa6: case 0xa7:
case 0xa8: case 0xa9: case 0xaa: case 0xab:
case 0xac: case 0xad: case 0xae: case 0xaf:
case 0xb0: case 0xb1: case 0xb2: case 0xb3:
case 0xb4: case 0xb5: case 0xb6: case 0xb7:
case 0xb8: case 0xb9: case 0xba: case 0xbb:
case 0xbc: case 0xbd: case 0xbe: case 0xbf:
case 0xc0: case 0xc1: case 0xc2: case 0xc3:
case 0xc4: case 0xc5: case 0xc6: case 0xc7:
case 0xc8: case 0xc9: case 0xca: case 0xcb:
case 0xcc: case 0xcd: case 0xce: case 0xcf:
case 0xd0: case 0xd1: case 0xd2: case 0xd3:
case 0xd4: case 0xd5: case 0xd6: case 0xd7:
case 0xd8: case 0xd9: case 0xda: case 0xdb:
case 0xdc: case 0xdd: case 0xde: case 0xdf:
case 0xe0: case 0xe1: case 0xe2: case 0xe3:
case 0xe4: case 0xe5: case 0xe6: case 0xe7:
case 0xe8: case 0xe9: case 0xea: case 0xeb:
case 0xec: case 0xed: case 0xee: case 0xef:
case 0xf0: case 0xf1: case 0xf2: case 0xf3:
case 0xf4: case 0xf5: case 0xf6: case 0xf7:
case 0xf8: case 0xf9: case 0xfa: case 0xfb:
case 0xfc: case 0xfd: case 0xfe: case 0xff:
tvga_accel.pattern[addr & 0x7f] = val;
break;
}
}
void tvga_accel_write_w(uint32_t addr, uint16_t val, void *priv)
{
pclog("tvga_accel_write_w %08X %04X\n", addr, val);
tvga_accel_write(addr, val, NULL);
tvga_accel_write(addr + 1, val >> 8, NULL);
}
void tvga_accel_write_l(uint32_t addr, uint32_t val, void *priv)
{
pclog("tvga_accel_write_l %08X %08X\n", addr, val);
tvga_accel_write(addr, val, NULL);
tvga_accel_write(addr + 1, val >> 8, NULL);
tvga_accel_write(addr + 2, val >> 16, NULL);
tvga_accel_write(addr + 3, val >> 24, NULL);
}
uint8_t tvga_accel_read(uint32_t addr, void *priv)
{
// pclog("tvga_accel_read : %08X\n", addr);
if ((addr & ~0xff) != 0xbff00)
return 0xff;
switch (addr & 0xff)
{
case 0x20: /*Status*/
return 0;
case 0x27: /*ROP*/
return tvga_accel.rop;
case 0x28: /*Flags*/
return tvga_accel.flags & 0xff;
case 0x29: /*Flags*/
return tvga_accel.flags >> 8;
case 0x2b:
return tvga_accel.offset;
case 0x2c: /*Background colour*/
return tvga_accel.bg_col & 0xff;
case 0x2d: /*Background colour*/
return tvga_accel.bg_col >> 8;
case 0x30: /*Foreground colour*/
return tvga_accel.fg_col & 0xff;
case 0x31: /*Foreground colour*/
return tvga_accel.fg_col >> 8;
case 0x38: /*Dest X*/
return tvga_accel.dst_x & 0xff;
case 0x39: /*Dest X*/
return tvga_accel.dst_x >> 8;
case 0x3a: /*Dest Y*/
return tvga_accel.dst_y & 0xff;
case 0x3b: /*Dest Y*/
return tvga_accel.dst_y >> 8;
case 0x3c: /*Src X*/
return tvga_accel.src_x & 0xff;
case 0x3d: /*Src X*/
return tvga_accel.src_x >> 8;
case 0x3e: /*Src Y*/
return tvga_accel.src_y & 0xff;
case 0x3f: /*Src Y*/
return tvga_accel.src_y >> 8;
case 0x40: /*Size X*/
return tvga_accel.size_x & 0xff;
case 0x41: /*Size X*/
return tvga_accel.size_x >> 8;
case 0x42: /*Size Y*/
return tvga_accel.size_y & 0xff;
case 0x43: /*Size Y*/
return tvga_accel.size_y >> 8;
case 0x80: case 0x81: case 0x82: case 0x83:
case 0x84: case 0x85: case 0x86: case 0x87:
case 0x88: case 0x89: case 0x8a: case 0x8b:
case 0x8c: case 0x8d: case 0x8e: case 0x8f:
case 0x90: case 0x91: case 0x92: case 0x93:
case 0x94: case 0x95: case 0x96: case 0x97:
case 0x98: case 0x99: case 0x9a: case 0x9b:
case 0x9c: case 0x9d: case 0x9e: case 0x9f:
case 0xa0: case 0xa1: case 0xa2: case 0xa3:
case 0xa4: case 0xa5: case 0xa6: case 0xa7:
case 0xa8: case 0xa9: case 0xaa: case 0xab:
case 0xac: case 0xad: case 0xae: case 0xaf:
case 0xb0: case 0xb1: case 0xb2: case 0xb3:
case 0xb4: case 0xb5: case 0xb6: case 0xb7:
case 0xb8: case 0xb9: case 0xba: case 0xbb:
case 0xbc: case 0xbd: case 0xbe: case 0xbf:
case 0xc0: case 0xc1: case 0xc2: case 0xc3:
case 0xc4: case 0xc5: case 0xc6: case 0xc7:
case 0xc8: case 0xc9: case 0xca: case 0xcb:
case 0xcc: case 0xcd: case 0xce: case 0xcf:
case 0xd0: case 0xd1: case 0xd2: case 0xd3:
case 0xd4: case 0xd5: case 0xd6: case 0xd7:
case 0xd8: case 0xd9: case 0xda: case 0xdb:
case 0xdc: case 0xdd: case 0xde: case 0xdf:
case 0xe0: case 0xe1: case 0xe2: case 0xe3:
case 0xe4: case 0xe5: case 0xe6: case 0xe7:
case 0xe8: case 0xe9: case 0xea: case 0xeb:
case 0xec: case 0xed: case 0xee: case 0xef:
case 0xf0: case 0xf1: case 0xf2: case 0xf3:
case 0xf4: case 0xf5: case 0xf6: case 0xf7:
case 0xf8: case 0xf9: case 0xfa: case 0xfb:
case 0xfc: case 0xfd: case 0xfe: case 0xff:
return tvga_accel.pattern[addr & 0x7f];
}
return 0xff;
}
uint16_t tvga_accel_read_w(uint32_t addr, void *priv)
{
pclog("tvga_accel_read_w %08X\n", addr);
return tvga_accel_read(addr, NULL) | (tvga_accel_read(addr + 1, NULL) << 8);
}
uint32_t tvga_accel_read_l(uint32_t addr, void *priv)
{
pclog("tvga_accel_read_l %08X\n", addr);
return tvga_accel_read_w(addr, NULL) | (tvga_accel_read_w(addr + 2, NULL) << 16);
}
void tvga_accel_write_fb_b(uint32_t addr, uint8_t val, void *priv)
{
// pclog("tvga_accel_write_fb_b %08X %02X\n", addr, val);
tvga_accel_command(8, val << 24);
}
void tvga_accel_write_fb_w(uint32_t addr, uint16_t val, void *priv)
{
// pclog("tvga_accel_write_fb_w %08X %04X\n", addr, val);
tvga_accel_command(16, (((val & 0xff00) >> 8) | ((val & 0x00ff) << 8)) << 16);
}
void tvga_accel_write_fb_l(uint32_t addr, uint32_t val, void *priv)
{
// pclog("tvga_accel_write_fb_l %08X %08X\n", addr, val);
tvga_accel_command(32, ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24));
}
GFXCARD vid_tvga = GFXCARD vid_tvga =
{ {
tvga_init, tvga_init,
@ -197,3 +956,27 @@ GFXCARD vid_tvga =
video_read_null, video_read_null,
video_read_null video_read_null
}; };
GFXCARD vid_tgui9440 =
{
tvga_init,
/*IO at 3Cx/3Dx*/
tvga_out,
tvga_in,
/*IO at 3Ax/3Bx*/
video_out_null,
video_in_null,
svga_poll,
svga_recalctimings,
svga_write,
video_write_null,
video_write_null,
svga_read,
video_read_null,
video_read_null
};

View file

@ -9,7 +9,7 @@
static int unk_state=0; static int unk_state=0;
static uint8_t unk_ctrl; static uint8_t unk_ctrl;
void unk_ramdac_out(uint16_t addr, uint8_t val) void unk_ramdac_out(uint16_t addr, uint8_t val, void *priv)
{ {
//pclog("OUT RAMDAC %04X %02X\n",addr,val); //pclog("OUT RAMDAC %04X %02X\n",addr,val);
switch (addr) switch (addr)
@ -42,10 +42,10 @@ void unk_ramdac_out(uint16_t addr, uint8_t val)
unk_state = 0; unk_state = 0;
break; break;
} }
svga_out(addr,val); svga_out(addr, val, NULL);
} }
uint8_t unk_ramdac_in(uint16_t addr) uint8_t unk_ramdac_in(uint16_t addr, void *priv)
{ {
//pclog("IN RAMDAC %04X\n",addr); //pclog("IN RAMDAC %04X\n",addr);
switch (addr) switch (addr)
@ -62,5 +62,5 @@ uint8_t unk_ramdac_in(uint16_t addr)
unk_state = 0; unk_state = 0;
break; break;
} }
return svga_in(addr); return svga_in(addr, NULL);
} }

View file

@ -1,2 +1,2 @@
void unk_ramdac_out(uint16_t addr, uint8_t val); void unk_ramdac_out(uint16_t addr, uint8_t val, void *priv);
uint8_t unk_ramdac_in(uint16_t addr); uint8_t unk_ramdac_in(uint16_t addr, void *priv);

View file

@ -5,6 +5,9 @@
#include "vid_svga.h" #include "vid_svga.h"
#include "io.h" #include "io.h"
#include "cpu.h" #include "cpu.h"
#include "timer.h"
int video_timer;
/*Video timing settings - /*Video timing settings -
@ -81,46 +84,46 @@ int video_res_x, video_res_y, video_bpp;
void (*video_blit_memtoscreen)(int x, int y, int y1, int y2, int w, int h); void (*video_blit_memtoscreen)(int x, int y, int y1, int y2, int w, int h);
void (*video_blit_memtoscreen_8)(int x, int y, int w, int h); void (*video_blit_memtoscreen_8)(int x, int y, int w, int h);
void (*video_out) (uint16_t addr, uint8_t val); void (*video_out) (uint16_t addr, uint8_t val, void *priv);
void (*video_mono_out)(uint16_t addr, uint8_t val); void (*video_mono_out)(uint16_t addr, uint8_t val, void *priv);
uint8_t (*video_in) (uint16_t addr); uint8_t (*video_in) (uint16_t addr, void *priv);
uint8_t (*video_mono_in)(uint16_t addr); uint8_t (*video_mono_in)(uint16_t addr, void *priv);
void (*video_write_a000)(uint32_t addr, uint8_t val); void (*video_write_a000)(uint32_t addr, uint8_t val, void *priv);
void (*video_write_b000)(uint32_t addr, uint8_t val); void (*video_write_b000)(uint32_t addr, uint8_t val, void *priv);
void (*video_write_b800)(uint32_t addr, uint8_t val); void (*video_write_b800)(uint32_t addr, uint8_t val, void *priv);
void (*video_write_a000_w)(uint32_t addr, uint16_t val); void (*video_write_a000_w)(uint32_t addr, uint16_t val, void *priv);
void (*video_write_a000_l)(uint32_t addr, uint32_t val); void (*video_write_a000_l)(uint32_t addr, uint32_t val, void *priv);
uint8_t (*video_read_a000)(uint32_t addr); uint8_t (*video_read_a000)(uint32_t addr, void *priv);
uint8_t (*video_read_b000)(uint32_t addr); uint8_t (*video_read_b000)(uint32_t addr, void *priv);
uint8_t (*video_read_b800)(uint32_t addr); uint8_t (*video_read_b800)(uint32_t addr, void *priv);
void (*video_recalctimings)(); void (*video_recalctimings)();
void video_out_null(uint16_t addr, uint8_t val) void video_out_null(uint16_t addr, uint8_t val, void *priv)
{ {
} }
uint8_t video_in_null(uint16_t addr) uint8_t video_in_null(uint16_t addr, void *priv)
{ {
return 0xFF; return 0xFF;
} }
void video_write_null(uint32_t addr, uint8_t val) void video_write_null(uint32_t addr, uint8_t val, void *priv)
{ {
} }
uint8_t video_read_null(uint32_t addr) uint8_t video_read_null(uint32_t addr, void *priv)
{ {
return 0xff; return 0xff;
} }
void video_load(GFXCARD g) void video_load(GFXCARD g)
{ {
io_sethandler(0x03a0, 0x0020, g.mono_in, NULL, NULL, g.mono_out, NULL, NULL); io_sethandler(0x03a0, 0x0020, g.mono_in, NULL, NULL, g.mono_out, NULL, NULL, NULL);
io_sethandler(0x03c0, 0x0020, g.in, NULL, NULL, g.out, NULL, NULL); io_sethandler(0x03c0, 0x0020, g.in, NULL, NULL, g.out, NULL, NULL, NULL);
video_out = g.out; video_out = g.out;
video_in = g.in; video_in = g.in;
@ -141,6 +144,8 @@ void video_load(GFXCARD g)
video_write_a000_w = video_write_a000_l = NULL; video_write_a000_w = video_write_a000_l = NULL;
g.init(); g.init();
video_timer = timer_add(pollvideo, &vidtime, TIMER_ALWAYS_ENABLED, NULL);
} }
void video_init() void video_init()
@ -221,6 +226,38 @@ void video_init()
video_load(vid_s3); video_load(vid_s3);
break; break;
case GFX_VIRGE:
video_load(vid_s3_virge);
break;
case GFX_TGUI9440:
video_load(vid_tgui9440);
break;
case GFX_VGA:
video_load(vid_vga);
break;
case GFX_VGAEDGE16:
video_load(vid_ati18800);
break;
case GFX_VGACHARGER:
video_load(vid_ati28800);
break;
case GFX_OTI067:
video_load(vid_oti067);
return;
case GFX_MACH64GX:
video_load(vid_mach64);
return;
case GFX_CL_GD5429:
video_load(vid_gd5429);
return;
default: default:
fatal("Bad gfx card %i\n",gfxcard); fatal("Bad gfx card %i\n",gfxcard);
} }
@ -235,7 +272,8 @@ int speshul=0;
uint8_t fontdat[256][8]; uint8_t fontdat[256][8];
uint8_t fontdatm[256][16]; uint8_t fontdatm[256][16];
float dispontime,dispofftime,disptime; int dispontime,dispofftime;
double disptime;
int svgaon; int svgaon;
uint8_t cgamode=1,cgastat,cgacol=7,ocgamode; uint8_t cgamode=1,cgastat,cgacol=7,ocgamode;
int linepos=0; int linepos=0;
@ -404,7 +442,7 @@ PALETTE comppal=
void initvideo() void initvideo()
{ {
int c,d; int c;
// set_color_depth(desktop_color_depth()); // set_color_depth(desktop_color_depth());
// if (set_gfx_mode(GFX_AUTODETECT_WINDOWED,2048,2048,0,0)) // if (set_gfx_mode(GFX_AUTODETECT_WINDOWED,2048,2048,0,0))
// set_gfx_mode(GFX_AUTODETECT_WINDOWED,1024,768,0,0); // set_gfx_mode(GFX_AUTODETECT_WINDOWED,1024,768,0,0);
@ -473,18 +511,6 @@ void resetvideo()
mdacols[0x08][0][1] = mdacols[0x08][1][1] = 16; mdacols[0x08][0][1] = mdacols[0x08][1][1] = 16;
mdacols[0x80][0][1] = mdacols[0x80][1][1] = 16; mdacols[0x80][0][1] = mdacols[0x80][1][1] = 16;
mdacols[0x88][0][1] = mdacols[0x88][1][1] = 16; mdacols[0x88][0][1] = mdacols[0x88][1][1] = 16;
/* switch (gfxcard)
{
case GFX_CGA: pollvideo=pollcga; break;
case GFX_MDA:
case GFX_HERCULES: pollvideo=pollmda; break;
}
if (TANDY) pollvideo=polltandy;
if (EGA) pollvideo=pollega;
if (romset==ROM_PC1512 || romset==ROM_PC200) pollvideo=pollcga;*/
// tandyvram=&ram[0x9C000];
// printf("Tandy VRAM %08X\n",tandyvram);
// tandyb8000=&ram[0x9C000];
} }
void closevideo() void closevideo()

View file

@ -10,7 +10,7 @@ extern uint8_t gdcreg[16];
extern int gdcaddr; extern int gdcaddr;
extern uint8_t attrregs[32]; extern uint8_t attrregs[32];
extern int attraddr,attrff; extern int attraddr,attrff;
extern uint8_t seqregs[32]; extern uint8_t seqregs[64];
extern int seqaddr; extern int seqaddr;
extern int svgaon; extern int svgaon;
@ -34,31 +34,34 @@ extern int changeframecount;
extern int firstline,lastline; extern int firstline,lastline;
extern int ega_hdisp,ega_rowoffset,ega_split,ega_dispend,ega_vsyncstart,ega_vtotal; extern int ega_hdisp,ega_rowoffset,ega_split,ega_dispend,ega_vsyncstart,ega_vtotal;
extern float dispontime,dispofftime,disptime; extern int dispontime,dispofftime;
extern double disptime;
extern void (*video_out) (uint16_t addr, uint8_t val); extern void (*video_out) (uint16_t addr, uint8_t val, void *priv);
extern void (*video_mono_out)(uint16_t addr, uint8_t val); extern void (*video_mono_out)(uint16_t addr, uint8_t val, void *priv);
extern uint8_t (*video_in) (uint16_t addr); extern uint8_t (*video_in) (uint16_t addr, void *priv);
extern uint8_t (*video_mono_in)(uint16_t addr); extern uint8_t (*video_mono_in)(uint16_t addr, void *priv);
extern void (*video_write_a000)(uint32_t addr, uint8_t val); extern void (*video_write_a000)(uint32_t addr, uint8_t val, void *priv);
extern void (*video_write_b000)(uint32_t addr, uint8_t val); extern void (*video_write_b000)(uint32_t addr, uint8_t val, void *priv);
extern void (*video_write_b800)(uint32_t addr, uint8_t val); extern void (*video_write_b800)(uint32_t addr, uint8_t val, void *priv);
extern uint8_t (*video_read_a000)(uint32_t addr); extern uint8_t (*video_read_a000)(uint32_t addr, void *priv);
extern uint8_t (*video_read_b000)(uint32_t addr); extern uint8_t (*video_read_b000)(uint32_t addr, void *priv);
extern uint8_t (*video_read_b800)(uint32_t addr); extern uint8_t (*video_read_b800)(uint32_t addr, void *priv);
extern void (*video_write_a000_w)(uint32_t addr, uint16_t val); extern void (*video_write_a000_w)(uint32_t addr, uint16_t val, void *priv);
extern void (*video_write_a000_l)(uint32_t addr, uint32_t val); extern void (*video_write_a000_l)(uint32_t addr, uint32_t val, void *priv);
extern void video_out_null(uint16_t addr, uint8_t val); extern void video_out_null(uint16_t addr, uint8_t val, void *priv);
extern uint8_t video_in_null(uint16_t addr); extern uint8_t video_in_null(uint16_t addr, void *priv);
extern void video_write_null(uint32_t addr, uint8_t val); extern void video_write_null(uint32_t addr, uint8_t val, void *priv);
extern uint8_t video_read_null (uint32_t addr); extern uint8_t video_read_null (uint32_t addr, void *priv);
extern int video_timer;
extern uint8_t tridentoldctrl2,tridentnewctrl2; extern uint8_t tridentoldctrl2,tridentnewctrl2;
extern int rowdbl; extern int rowdbl;
@ -73,6 +76,8 @@ extern BITMAP *buffer,*buffer32,*vbuf;
extern BITMAP *screen; extern BITMAP *screen;
BITMAP *create_bitmap(int w, int h);
extern int wx,wy; extern int wx,wy;
extern uint8_t fontdat[256][8]; extern uint8_t fontdat[256][8];
@ -98,18 +103,18 @@ extern uint32_t vrammask;
typedef struct typedef struct
{ {
int (*init)(); int (*init)();
void (*out)(uint16_t addr, uint8_t val); void (*out)(uint16_t addr, uint8_t val, void *priv);
uint8_t (*in)(uint16_t addr); uint8_t (*in)(uint16_t addr, void *priv);
void (*mono_out)(uint16_t addr, uint8_t val); void (*mono_out)(uint16_t addr, uint8_t val, void *priv);
uint8_t (*mono_in)(uint16_t addr); uint8_t (*mono_in)(uint16_t addr, void *priv);
void (*poll)(); void (*poll)();
void (*recalctimings)(); void (*recalctimings)();
void (*write_a000)(uint32_t addr, uint8_t val); void (*write_a000)(uint32_t addr, uint8_t val, void *priv);
void (*write_b000)(uint32_t addr, uint8_t val); void (*write_b000)(uint32_t addr, uint8_t val, void *priv);
void (*write_b800)(uint32_t addr, uint8_t val); void (*write_b800)(uint32_t addr, uint8_t val, void *priv);
uint8_t (*read_a000)(uint32_t addr); uint8_t (*read_a000)(uint32_t addr, void *priv);
uint8_t (*read_b000)(uint32_t addr); uint8_t (*read_b000)(uint32_t addr, void *priv);
uint8_t (*read_b800)(uint32_t addr); uint8_t (*read_b800)(uint32_t addr, void *priv);
} GFXCARD; } GFXCARD;
extern GFXCARD vid_cga; extern GFXCARD vid_cga;
@ -127,7 +132,13 @@ extern GFXCARD vid_tvga;
extern GFXCARD vid_et4000; extern GFXCARD vid_et4000;
extern GFXCARD vid_et4000w32p; extern GFXCARD vid_et4000w32p;
extern GFXCARD vid_s3; extern GFXCARD vid_s3;
extern GFXCARD vid_s3_virge;
extern GFXCARD vid_tgui9440;
extern GFXCARD vid_vga;
extern GFXCARD vid_ati18800;
extern GFXCARD vid_ati28800;
extern GFXCARD vid_mach64;
extern GFXCARD vid_gd5429;
extern float cpuclock; extern float cpuclock;

View file

@ -10,7 +10,7 @@ static uint16_t wd76c10_2072;
static uint16_t wd76c10_2872; static uint16_t wd76c10_2872;
static uint16_t wd76c10_5872; static uint16_t wd76c10_5872;
uint16_t wd76c10_read(uint16_t port) uint16_t wd76c10_read(uint16_t port, void *priv)
{ {
switch (port) switch (port)
{ {
@ -29,7 +29,7 @@ uint16_t wd76c10_read(uint16_t port)
return 0; return 0;
} }
void wd76c10_write(uint16_t port, uint16_t val) void wd76c10_write(uint16_t port, uint16_t val, void *priv)
{ {
pclog("WD76C10 write %04X %04X\n", port, val); pclog("WD76C10 write %04X %04X\n", port, val);
switch (port) switch (port)
@ -68,7 +68,7 @@ void wd76c10_write(uint16_t port, uint16_t val)
fdc_remove(); fdc_remove();
if (!(val & 1)) if (!(val & 1))
fdc_init(); fdc_add();
break; break;
case 0x5872: case 0x5872:
@ -77,26 +77,26 @@ void wd76c10_write(uint16_t port, uint16_t val)
} }
} }
uint8_t wd76c10_readb(uint16_t port) uint8_t wd76c10_readb(uint16_t port, void *priv)
{ {
if (port & 1) if (port & 1)
return wd76c10_read(port & ~1) >> 8; return wd76c10_read(port & ~1, priv) >> 8;
return wd76c10_read(port) & 0xff; return wd76c10_read(port, priv) & 0xff;
} }
void wd76c10_writeb(uint16_t port, uint8_t val) void wd76c10_writeb(uint16_t port, uint8_t val, void *priv)
{ {
uint16_t temp = wd76c10_read(port); uint16_t temp = wd76c10_read(port, priv);
if (port & 1) if (port & 1)
wd76c10_write(port & ~1, (temp & 0x00ff) | (val << 8)); wd76c10_write(port & ~1, (temp & 0x00ff) | (val << 8), priv);
else else
wd76c10_write(port , (temp & 0xff00) | val); wd76c10_write(port , (temp & 0xff00) | val, priv);
} }
void wd76c10_init() void wd76c10_init()
{ {
io_sethandler(0x0092, 0x0002, wd76c10_readb, wd76c10_read, NULL, wd76c10_writeb, wd76c10_write, NULL); io_sethandler(0x0092, 0x0002, wd76c10_readb, wd76c10_read, NULL, wd76c10_writeb, wd76c10_write, NULL, NULL);
io_sethandler(0x2072, 0x0002, wd76c10_readb, wd76c10_read, NULL, wd76c10_writeb, wd76c10_write, NULL); io_sethandler(0x2072, 0x0002, wd76c10_readb, wd76c10_read, NULL, wd76c10_writeb, wd76c10_write, NULL, NULL);
io_sethandler(0x2872, 0x0002, wd76c10_readb, wd76c10_read, NULL, wd76c10_writeb, wd76c10_write, NULL); io_sethandler(0x2872, 0x0002, wd76c10_readb, wd76c10_read, NULL, wd76c10_writeb, wd76c10_write, NULL, NULL);
io_sethandler(0x5872, 0x0002, wd76c10_readb, wd76c10_read, NULL, wd76c10_writeb, wd76c10_write, NULL); io_sethandler(0x5872, 0x0002, wd76c10_readb, wd76c10_read, NULL, wd76c10_writeb, wd76c10_write, NULL, NULL);
} }

View file

@ -1,4 +1,6 @@
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "video.h" #include "video.h"
BITMAP *screen; BITMAP *screen;

227
src/win.c
View file

@ -15,6 +15,8 @@
#include "video.h" #include "video.h"
#include "resources.h" #include "resources.h"
#include "ide.h" #include "ide.h"
#include "nvr.h"
#include "sound.h"
#include "plat-keyboard.h" #include "plat-keyboard.h"
@ -25,7 +27,7 @@
#define TIMER_1SEC 1 #define TIMER_1SEC 1
int winsizex=640,winsizey=480; int winsizex=640,winsizey=480;
int svgapresent, et4000w32_present, bahamas64_present, n9_9fx_present; int gfx_present[18];
int wakeups,wokeups; int wakeups,wokeups;
#undef cs #undef cs
CRITICAL_SECTION cs; CRITICAL_SECTION cs;
@ -44,8 +46,6 @@ void endmainthread();
void endsoundthread(); void endsoundthread();
void silencesound(); void silencesound();
void restoresound(); void restoresound();
static HANDLE soundobject;
static HANDLE frameobject; static HANDLE frameobject;
int infocus=1; int infocus=1;
@ -61,7 +61,7 @@ void vsyncint()
// } // }
} }
int romspresent[25]; int romspresent[26];
int quited=0; int quited=0;
RECT oldclip,pcclip; RECT oldclip,pcclip;
@ -99,11 +99,6 @@ void releasemouse()
} }
} }
static LARGE_INTEGER counter_base;
static LARGE_INTEGER counter_freq;
static LARGE_INTEGER counter_pos;
static LARGE_INTEGER counter_posold;
void setrefresh(int rate) void setrefresh(int rate)
{ {
return; return;
@ -155,6 +150,7 @@ int pause=0;
void mainthread(LPVOID param) void mainthread(LPVOID param)
{ {
int t = 0; int t = 0;
int frames = 0;
DWORD old_time, new_time; DWORD old_time, new_time;
mainthreadon=1; mainthreadon=1;
// Sleep(500); // Sleep(500);
@ -190,12 +186,19 @@ void mainthread(LPVOID param)
runpc(); runpc();
// ddraw_draw(); // ddraw_draw();
endblit(); endblit();
frames++;
if (frames >= 200 && nvr_dosave)
{
frames = 0;
nvr_dosave = 0;
savenvr();
}
//#if 0 //#if 0
//#endif //#endif
} }
else else
{ {
// Sleep(1); Sleep(1);
} }
// } // }
} }
@ -246,9 +249,7 @@ int WINAPI WinMain (HINSTANCE hThisInstance,
HWND hwnd; /* This is the handle for our window */ HWND hwnd; /* This is the handle for our window */
MSG messages; /* Here messages to the application are saved */ MSG messages; /* Here messages to the application are saved */
WNDCLASSEX wincl; /* Data structure for the windowclass */ WNDCLASSEX wincl; /* Data structure for the windowclass */
int c,d; int c, d;
FILE *f;
int oldinfocus=0;
hinstance=hThisInstance; hinstance=hThisInstance;
/* The Window structure */ /* The Window structure */
@ -317,19 +318,19 @@ int WINAPI WinMain (HINSTANCE hThisInstance,
// set_display_switch_mode(SWITCH_BACKGROUND); // set_display_switch_mode(SWITCH_BACKGROUND);
d=romset; d=romset;
for (c=0;c<25;c++) for (c=0;c<26;c++)
{ {
romset=c; romset=c;
romspresent[c]=loadbios(); romspresent[c]=loadbios();
pclog("romset %i - %i\n", c, romspresent[c]); pclog("romset %i - %i\n", c, romspresent[c]);
} }
for (c = 0; c < 25; c++) for (c = 0; c < 26; c++)
{ {
if (romspresent[c]) if (romspresent[c])
break; break;
} }
if (c == 25) if (c == 26)
{ {
MessageBox(hwnd,"No ROMs present!\nYou must have at least one romset to use PCem.","PCem fatal error",MB_OK); MessageBox(hwnd,"No ROMs present!\nYou must have at least one romset to use PCem.","PCem fatal error",MB_OK);
return 0; return 0;
@ -340,8 +341,8 @@ int WINAPI WinMain (HINSTANCE hThisInstance,
if (!c) if (!c)
{ {
if (romset!=-1) MessageBox(hwnd,"Configured romset not available.\nDefaulting to available romset.","PCemu error",MB_OK); if (romset!=-1) MessageBox(hwnd,"Configured romset not available.\nDefaulting to available romset.","PCem error",MB_OK);
for (c=0;c<25;c++) for (c=0;c<26;c++)
{ {
if (romspresent[c]) if (romspresent[c])
{ {
@ -352,60 +353,26 @@ int WINAPI WinMain (HINSTANCE hThisInstance,
} }
} }
f=romfopen("roms/trident.bin","rb"); d = gfxcard;
if (f) for (c = 0; c < 18; c++)
{ {
fclose(f); gfxcard = c;
vgapresent=1; gfx_present[c] = mem_load_video_bios();
} }
else gfxcard = d;
c = mem_load_video_bios();
if (!c)
{ {
vgapresent=0; if (romset!=-1) MessageBox(hwnd,"Configured video BIOS not available.\nDefaulting to available romset.","PCem error",MB_OK);
if (gfxcard==GFX_TVGA) gfxcard=GFX_CGA; for (c=0;c<18;c++)
} {
f=romfopen("roms/et4000.bin","rb"); if (gfx_present[c])
if (f) {
{ gfxcard = c;
fclose(f); mem_load_video_bios();
svgapresent=1; break;
} }
else }
{
svgapresent=0;
if (gfxcard==GFX_ET4000) gfxcard=(svgapresent)?GFX_TVGA:GFX_CGA;
}
f=romfopen("roms/et4000w32.bin","rb");
if (f)
{
fclose(f);
et4000w32_present=1;
}
else
{
et4000w32_present=0;
if (gfxcard==GFX_ET4000W32) gfxcard=(svgapresent)?GFX_TVGA:GFX_CGA;
}
f=romfopen("roms/bahamas64.bin","rb");
if (f)
{
fclose(f);
bahamas64_present=1;
}
else
{
bahamas64_present=0;
if (gfxcard==GFX_BAHAMAS64) gfxcard=(svgapresent)?GFX_TVGA:GFX_CGA;
}
f=romfopen("roms/s3_764.bin","rb");
if (f)
{
fclose(f);
n9_9fx_present=1;
}
else
{
n9_9fx_present=0;
if (gfxcard==GFX_N9_9FX) gfxcard=(svgapresent)?GFX_TVGA:GFX_CGA;
} }
timeBeginPeriod(1); timeBeginPeriod(1);
// soundobject=CreateEvent(NULL, FALSE, FALSE, NULL); // soundobject=CreateEvent(NULL, FALSE, FALSE, NULL);
@ -505,7 +472,6 @@ char openfilestring[260];
int getfile(HWND hwnd, char *f, char *fn) int getfile(HWND hwnd, char *f, char *fn)
{ {
OPENFILENAME ofn; // common dialog box structure OPENFILENAME ofn; // common dialog box structure
char szFile[260]; // buffer for file name
BOOL r; BOOL r;
DWORD err; DWORD err;
@ -546,7 +512,6 @@ int getfile(HWND hwnd, char *f, char *fn)
int getsfile(HWND hwnd, char *f, char *fn) int getsfile(HWND hwnd, char *f, char *fn)
{ {
OPENFILENAME ofn; // common dialog box structure OPENFILENAME ofn; // common dialog box structure
char szFile[260]; // buffer for file name
BOOL r; BOOL r;
DWORD err; DWORD err;
@ -585,12 +550,18 @@ int getsfile(HWND hwnd, char *f, char *fn)
} }
extern int is486; extern int is486;
int romstolist[25], listtomodel[23], romstomodel[25], modeltolist[23]; int romstolist[26], listtomodel[26], romstomodel[26], modeltolist[26];
int vidtolist[10],listtovid[10]; int vidtolist[20],listtovid[20];
int mem_list_to_size[]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,32,48,64}; int mem_list_to_size[]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,32,48,64,256};
int mem_size_to_list[]={0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11,12,13,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,16, int mem_size_to_list[]={0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11,12,13,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,16,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,18}; 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,18,
19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19};
#include "cpu.h" #include "cpu.h"
#include "model.h" #include "model.h"
@ -601,13 +572,14 @@ BOOL CALLBACK configdlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lPara
int c, d; int c, d;
int rom,gfx,mem,fpu; int rom,gfx,mem,fpu;
int temp_cpu, temp_cpu_m, temp_model; int temp_cpu, temp_cpu_m, temp_model;
int temp_GAMEBLASTER, temp_GUS, temp_sound_card_current;
// pclog("Dialog msg %i %08X\n",message,message); // pclog("Dialog msg %i %08X\n",message,message);
switch (message) switch (message)
{ {
case WM_INITDIALOG: case WM_INITDIALOG:
pause=1; pause=1;
h=GetDlgItem(hdlg,IDC_COMBO1); h=GetDlgItem(hdlg,IDC_COMBO1);
for (c=0;c<25;c++) romstolist[c]=0; for (c=0;c<26;c++) romstolist[c]=0;
c = d = 0; c = d = 0;
while (models[c].id != -1) while (models[c].id != -1)
{ {
@ -632,11 +604,19 @@ BOOL CALLBACK configdlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lPara
SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"MDA"); vidtolist[GFX_MDA]=1; listtovid[1]=1; SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"MDA"); vidtolist[GFX_MDA]=1; listtovid[1]=1;
SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Hercules"); vidtolist[GFX_HERCULES]=2; listtovid[2]=2; SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Hercules"); vidtolist[GFX_HERCULES]=2; listtovid[2]=2;
SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"EGA"); vidtolist[GFX_EGA]=3; listtovid[3]=3; SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"EGA"); vidtolist[GFX_EGA]=3; listtovid[3]=3;
if (vgapresent) { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Trident 8900D"); vidtolist[GFX_TVGA]=c; listtovid[c]=GFX_TVGA; c++; } if (gfx_present[GFX_TVGA]) { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Trident 8900D"); vidtolist[GFX_TVGA]=c; listtovid[c]=GFX_TVGA; c++; }
if (svgapresent) { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Tseng ET4000AX"); vidtolist[GFX_ET4000]=c; listtovid[c]=GFX_ET4000; c++; } if (gfx_present[GFX_ET4000]) { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Tseng ET4000AX"); vidtolist[GFX_ET4000]=c; listtovid[c]=GFX_ET4000; c++; }
if (et4000w32_present) { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Diamond Stealth 32"); vidtolist[GFX_ET4000W32]=c; listtovid[c]=GFX_ET4000W32; c++; } if (gfx_present[GFX_ET4000W32]) { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Diamond Stealth 32"); vidtolist[GFX_ET4000W32]=c; listtovid[c]=GFX_ET4000W32; c++; }
if (bahamas64_present) { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Paradise Bahamas 64"); vidtolist[GFX_BAHAMAS64]=c; listtovid[c]=GFX_BAHAMAS64; c++; } if (gfx_present[GFX_BAHAMAS64]) { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Paradise Bahamas 64"); vidtolist[GFX_BAHAMAS64]=c; listtovid[c]=GFX_BAHAMAS64; c++; }
if (n9_9fx_present) { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Number Nine 9FX"); vidtolist[GFX_N9_9FX]=c; listtovid[c]=GFX_N9_9FX; c++; } if (gfx_present[GFX_N9_9FX]) { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Number Nine 9FX"); vidtolist[GFX_N9_9FX]=c; listtovid[c]=GFX_N9_9FX; c++; }
if (gfx_present[GFX_VIRGE]) { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"S3 VIRGE"); vidtolist[GFX_VIRGE]=c; listtovid[c]=GFX_VIRGE; c++; }
if (gfx_present[GFX_TGUI9440]) { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Trident TGUI9440"); vidtolist[GFX_TGUI9440]=c; listtovid[c]=GFX_TGUI9440; c++; }
if (gfx_present[GFX_VGA]) { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"VGA"); vidtolist[GFX_VGA]=c; listtovid[c]=GFX_VGA; c++; }
if (gfx_present[GFX_VGAEDGE16]) { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"ATI VGA Edge-16"); vidtolist[GFX_VGAEDGE16]=c; listtovid[c]=GFX_VGAEDGE16; c++; }
if (gfx_present[GFX_VGACHARGER]) { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"ATI VGA Charger"); vidtolist[GFX_VGACHARGER]=c; listtovid[c]=GFX_VGACHARGER; c++; }
if (gfx_present[GFX_OTI067]) { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Oak OTI-067"); vidtolist[GFX_OTI067]=c; listtovid[c]=GFX_OTI067; c++; }
if (gfx_present[GFX_MACH64GX]) { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"ATI Graphics Pro Turbo"); vidtolist[GFX_MACH64GX]=c; listtovid[c]=GFX_MACH64GX; c++; }
if (gfx_present[GFX_CL_GD5429]) { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Cirrus Logic CL-GD5429"); vidtolist[GFX_CL_GD5429]=c; listtovid[c]=GFX_CL_GD5429; c++; }
SendMessage(h,CB_SETCURSEL,vidtolist[gfxcard],0); SendMessage(h,CB_SETCURSEL,vidtolist[gfxcard],0);
if (models[model].fixed_gfxcard) EnableWindow(h,FALSE); if (models[model].fixed_gfxcard) EnableWindow(h,FALSE);
@ -663,30 +643,30 @@ BOOL CALLBACK configdlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lPara
SendMessage(h, CB_SETCURSEL, cpu, 0); SendMessage(h, CB_SETCURSEL, cpu, 0);
h=GetDlgItem(hdlg,IDC_COMBOSND); h=GetDlgItem(hdlg,IDC_COMBOSND);
SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"None"); c = 0;
SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"AdLib"); while (1)
SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"SoundBlaster v1.0"); {
SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"SoundBlaster v1.5"); char *s = sound_card_getname(c);
SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"SoundBlaster v2.0");
SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"SB Pro v1");
SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"SB Pro v2");
SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"SoundBlaster 16");
SendMessage(h,CB_SETCURSEL,sbtype,0);
// h=GetDlgItem(hdlg,IDC_CHECK2); if (!s[0])
// SendMessage(h,BM_SETCHECK,ADLIB,0); break;
SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)s);
c++;
}
SendMessage(h, CB_SETCURSEL, sound_card_current, 0);
h=GetDlgItem(hdlg, IDC_CHECK3);
SendMessage(h, BM_SETCHECK, GAMEBLASTER, 0);
h=GetDlgItem(hdlg, IDC_CHECKGUS);
SendMessage(h, BM_SETCHECK, GUS, 0);
h=GetDlgItem(hdlg,IDC_CHECK3); h=GetDlgItem(hdlg, IDC_CHECK2);
SendMessage(h,BM_SETCHECK,GAMEBLASTER,0); SendMessage(h, BM_SETCHECK, slowega, 0);
h=GetDlgItem(hdlg,IDC_CHECK1);
SendMessage(h,BM_SETCHECK,FASTDISC,0);
h=GetDlgItem(hdlg,IDC_CHECK2); h=GetDlgItem(hdlg, IDC_CHECK4);
SendMessage(h,BM_SETCHECK,slowega,0); SendMessage(h, BM_SETCHECK, cga_comp, 0);
h=GetDlgItem(hdlg,IDC_CHECK4);
SendMessage(h,BM_SETCHECK,cga_comp,0);
h=GetDlgItem(hdlg,IDC_COMBOCHC); h=GetDlgItem(hdlg,IDC_COMBOCHC);
SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"A little"); SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"A little");
@ -725,6 +705,7 @@ BOOL CALLBACK configdlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lPara
SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"32 MB"); SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"32 MB");
SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"48 MB"); SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"48 MB");
SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"64 MB"); SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"64 MB");
SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"256 MB");
SendMessage(h,CB_SETCURSEL,mem_size_to_list[mem_size-1],0); SendMessage(h,CB_SETCURSEL,mem_size_to_list[mem_size-1],0);
pclog("Init cpuspeed %i\n",cpuspeed); pclog("Init cpuspeed %i\n",cpuspeed);
@ -750,7 +731,16 @@ BOOL CALLBACK configdlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lPara
fpu = (models[temp_model].cpu[temp_cpu_m].cpus[temp_cpu].cpu_type >= CPU_i486DX) ? 1 : 0; fpu = (models[temp_model].cpu[temp_cpu_m].cpus[temp_cpu].cpu_type >= CPU_i486DX) ? 1 : 0;
pclog("newcpu - %i %i %i %i\n",temp_cpu_m,temp_cpu,fpu,models[temp_model].cpu[temp_cpu_m].cpus[temp_cpu].cpu_type); pclog("newcpu - %i %i %i %i\n",temp_cpu_m,temp_cpu,fpu,models[temp_model].cpu[temp_cpu_m].cpus[temp_cpu].cpu_type);
if (temp_model != model || gfx!=gfxcard || mem!=mem_size || fpu!=hasfpu) h = GetDlgItem(hdlg, IDC_CHECK3);
temp_GAMEBLASTER = SendMessage(h, BM_GETCHECK, 0, 0);
h = GetDlgItem(hdlg, IDC_CHECKGUS);
temp_GUS = SendMessage(h, BM_GETCHECK, 0, 0);
h = GetDlgItem(hdlg, IDC_COMBOSND);
temp_sound_card_current = SendMessage(h, CB_GETCURSEL, 0, 0);
if (temp_model != model || gfx != gfxcard || mem != mem_size || fpu != hasfpu || temp_GAMEBLASTER != GAMEBLASTER || temp_GUS != GUS || temp_sound_card_current != sound_card_current)
{ {
if (MessageBox(NULL,"This will reset PCem!\nOkay to continue?","PCem",MB_OKCANCEL)==IDOK) if (MessageBox(NULL,"This will reset PCem!\nOkay to continue?","PCem",MB_OKCANCEL)==IDOK)
{ {
@ -760,9 +750,13 @@ BOOL CALLBACK configdlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lPara
mem_size=mem; mem_size=mem;
cpu_manufacturer = temp_cpu_m; cpu_manufacturer = temp_cpu_m;
cpu = temp_cpu; cpu = temp_cpu;
GAMEBLASTER = temp_GAMEBLASTER;
GUS = temp_GUS;
sound_card_current = temp_sound_card_current;
mem_resize(); mem_resize();
loadbios(); loadbios();
mem_load_video_bios();
resetpchard(); resetpchard();
} }
else else
@ -776,12 +770,6 @@ BOOL CALLBACK configdlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lPara
h=GetDlgItem(hdlg,IDC_COMBOSPD); h=GetDlgItem(hdlg,IDC_COMBOSPD);
video_speed = SendMessage(h,CB_GETCURSEL,0,0); video_speed = SendMessage(h,CB_GETCURSEL,0,0);
h=GetDlgItem(hdlg,IDC_CHECK3);
GAMEBLASTER=SendMessage(h,BM_GETCHECK,0,0);
h=GetDlgItem(hdlg,IDC_CHECK1);
FASTDISC=SendMessage(h,BM_GETCHECK,0,0);
h=GetDlgItem(hdlg,IDC_CHECK4); h=GetDlgItem(hdlg,IDC_CHECK4);
cga_comp=SendMessage(h,BM_GETCHECK,0,0); cga_comp=SendMessage(h,BM_GETCHECK,0,0);
@ -789,9 +777,6 @@ BOOL CALLBACK configdlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lPara
cpu = temp_cpu; cpu = temp_cpu;
cpu_set(); cpu_set();
h=GetDlgItem(hdlg,IDC_COMBOSND);
sbtype=SendMessage(h,CB_GETCURSEL,0,0);
h=GetDlgItem(hdlg,IDC_COMBOCHC); h=GetDlgItem(hdlg,IDC_COMBOCHC);
cache=SendMessage(h,CB_GETCURSEL,0,0); cache=SendMessage(h,CB_GETCURSEL,0,0);
mem_updatecache(); mem_updatecache();
@ -890,7 +875,6 @@ BOOL CALLBACK hdnewdlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam
HWND h; HWND h;
int c; int c;
PcemHDC hd[2]; PcemHDC hd[2];
int changeddrv=0;
FILE *f; FILE *f;
uint8_t buf[512]; uint8_t buf[512];
switch (message) switch (message)
@ -1004,11 +988,7 @@ BOOL CALLBACK hdsizedlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lPara
{ {
char s[260]; char s[260];
HWND h; HWND h;
int c;
PcemHDC hd[2]; PcemHDC hd[2];
int changeddrv=0;
FILE *f;
uint8_t buf[512];
switch (message) switch (message)
{ {
case WM_INITDIALOG: case WM_INITDIALOG:
@ -1090,9 +1070,7 @@ BOOL CALLBACK hdconfdlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lPara
{ {
char s[260]; char s[260];
HWND h; HWND h;
int c;
PcemHDC hd[2]; PcemHDC hd[2];
int changeddrv=0;
FILE *f; FILE *f;
off64_t sz; off64_t sz;
switch (message) switch (message)
@ -1344,8 +1322,6 @@ BOOL CALLBACK hdconfdlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lPara
BOOL CALLBACK statusdlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) BOOL CALLBACK statusdlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
{ {
HWND h;
int c;
int egasp; int egasp;
char s[256]; char s[256];
switch (message) switch (message)
@ -1374,12 +1350,12 @@ BOOL CALLBACK statusdlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lPara
if (chain4) sprintf(s,"VGA chained (possibly mode 13h)"); if (chain4) sprintf(s,"VGA chained (possibly mode 13h)");
else sprintf(s,"VGA unchained (possibly mode-X)"); else sprintf(s,"VGA unchained (possibly mode-X)");
SendDlgItemMessage(hdlg,IDC_STEXT9,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s); SendDlgItemMessage(hdlg,IDC_STEXT9,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s);
if (!video_bpp) sprintf(s,"VGA in text mode"); /* if (!video_bpp) sprintf(s,"VGA in text mode");
else sprintf(s,"VGA colour depth : %i bpp", video_bpp); else */sprintf(s,"VGA colour depth : %i bpp", video_bpp);
SendDlgItemMessage(hdlg,IDC_STEXT10,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s); SendDlgItemMessage(hdlg,IDC_STEXT10,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s);
sprintf(s,"VGA resolution : %i x %i", video_res_x, video_res_y); sprintf(s,"VGA resolution : %i x %i", video_res_x, video_res_y);
SendDlgItemMessage(hdlg,IDC_STEXT11,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s); SendDlgItemMessage(hdlg,IDC_STEXT11,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s);
sprintf(s,"SB frequency : %i Hz",sb_freq); sprintf(s,"SB frequency : %i Hz",0);
SendDlgItemMessage(hdlg,IDC_STEXT12,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s); SendDlgItemMessage(hdlg,IDC_STEXT12,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s);
sprintf(s,"Video refresh rate : %i Hz", emu_fps); sprintf(s,"Video refresh rate : %i Hz", emu_fps);
SendDlgItemMessage(hdlg,IDC_STEXT13,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s); SendDlgItemMessage(hdlg,IDC_STEXT13,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s);
@ -1421,9 +1397,6 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
{ {
HMENU hmenu; HMENU hmenu;
RECT rect; RECT rect;
int c;
int x, y;
POINT po;
// pclog("Message %i %08X\n",message,message); // pclog("Message %i %08X\n",message,message);
switch (message) switch (message)
{ {

View file

@ -1,4 +1,3 @@
uint32_t old8,old82,old83;
uint16_t oldcs; uint16_t oldcs;
uint32_t oldpc; uint32_t oldpc;
extern uint32_t rmdat32; extern uint32_t rmdat32;
@ -16,11 +15,9 @@ int skipnextprint;
int inhlt; int inhlt;
uint8_t opcode; uint8_t opcode;
int ins,noint,notpresent; int ins,noint;
int inint;
uint16_t lastcs,lastpc; uint16_t lastcs,lastpc;
int lldt;
int timetolive,keyboardtimer; int timetolive,keyboardtimer;
#define setznp168 setznp16 #define setznp168 setznp16
@ -96,3 +93,7 @@ extern uint8_t opcode2;
extern uint16_t rds; extern uint16_t rds;
extern uint32_t rmdat32; extern uint32_t rmdat32;
extern int inscounts[256];
void x86illegal();

View file

@ -1,17 +1,387 @@
static inline void setznp8(uint8_t val) enum
{ {
flags&=~0x8d5; FLAGS_UNKNOWN,
flags|=znptable8[val];
FLAGS_ZN8,
FLAGS_ZN16,
FLAGS_ZN32,
FLAGS_ADD8,
FLAGS_ADD16,
FLAGS_ADD32,
FLAGS_SUB8,
FLAGS_SUB16,
FLAGS_SUB32
};
static int flags_op;
static uint32_t flags_res;
static uint32_t flags_op1, flags_op2;
static inline int ZF_SET()
{
switch (flags_op)
{
case FLAGS_ZN8:
case FLAGS_ZN16:
case FLAGS_ZN32:
case FLAGS_ADD8:
case FLAGS_ADD16:
case FLAGS_ADD32:
case FLAGS_SUB8:
case FLAGS_SUB16:
case FLAGS_SUB32:
return !flags_res;
case FLAGS_UNKNOWN:
return flags & Z_FLAG;
}
} }
static inline int NF_SET()
{
switch (flags_op)
{
case FLAGS_ZN8:
case FLAGS_ADD8:
case FLAGS_SUB8:
return flags_res & 0x80;
case FLAGS_ZN16:
case FLAGS_ADD16:
case FLAGS_SUB16:
return flags_res & 0x8000;
case FLAGS_ZN32:
case FLAGS_ADD32:
case FLAGS_SUB32:
return flags_res & 0x80000000;
case FLAGS_UNKNOWN:
return flags & N_FLAG;
}
}
static inline int PF_SET()
{
switch (flags_op)
{
case FLAGS_ZN8:
case FLAGS_ZN16:
case FLAGS_ZN32:
case FLAGS_ADD8:
case FLAGS_ADD16:
case FLAGS_ADD32:
case FLAGS_SUB8:
case FLAGS_SUB16:
case FLAGS_SUB32:
return znptable8[flags_res & 0xff] & P_FLAG;
case FLAGS_UNKNOWN:
return flags & P_FLAG;
}
}
static inline int VF_SET()
{
switch (flags_op)
{
case FLAGS_ZN8:
case FLAGS_ZN16:
case FLAGS_ZN32:
return 0;
case FLAGS_ADD8:
return !((flags_op1 ^ flags_op2) & 0x80) && ((flags_op1 ^ flags_res) & 0x80);
case FLAGS_ADD16:
return !((flags_op1 ^ flags_op2) & 0x8000) && ((flags_op1 ^ flags_res) & 0x8000);
case FLAGS_ADD32:
return !((flags_op1 ^ flags_op2) & 0x80000000) && ((flags_op1 ^ flags_res) & 0x80000000);
case FLAGS_SUB8:
return ((flags_op1 ^ flags_op2) & (flags_op1 ^ flags_res) & 0x80);
case FLAGS_SUB16:
return ((flags_op1 ^ flags_op2) & (flags_op1 ^ flags_res) & 0x8000);
case FLAGS_SUB32:
return ((flags_op1 ^ flags_op2) & (flags_op1 ^ flags_res) & 0x80000000);
case FLAGS_UNKNOWN:
return flags & V_FLAG;
}
}
static inline int AF_SET()
{
switch (flags_op)
{
case FLAGS_ZN8:
case FLAGS_ZN16:
case FLAGS_ZN32:
return 0;
case FLAGS_ADD8:
case FLAGS_ADD16:
case FLAGS_ADD32:
return ((flags_op1 & 0xF) + (flags_op2 & 0xF)) & 0x10;
case FLAGS_SUB8:
case FLAGS_SUB16:
case FLAGS_SUB32:
return ((flags_op1 & 0xF) - (flags_op2 & 0xF)) & 0x10;
case FLAGS_UNKNOWN:
return flags & A_FLAG;
}
}
#if 0
static inline int CF_SET()
{
switch (flags_op)
{
case FLAGS_ZN8:
case FLAGS_ZN16:
case FLAGS_ZN32:
return flags & C_FLAG; /*Temporary*/
case FLAGS_ADD8:
return (flags_op1 + flags_op2) & 0x100;
case FLAGS_ADD16:
// return (flags_op1 + flags_op2) & 0x10000;
case FLAGS_UNKNOWN:
return flags & C_FLAG;
}
}
#endif
//#define ZF_SET() (flags & Z_FLAG)
//#define NF_SET() (flags & N_FLAG)
//#define PF_SET() (flags & P_FLAG)
//#define VF_SET() (flags & V_FLAG)
#define CF_SET() (flags & C_FLAG)
//#define AF_SET() (flags & A_FLAG)
static inline void flags_rebuild()
{
if (flags_op != FLAGS_UNKNOWN)
{
uint16_t tempf = 0;
if (CF_SET()) tempf |= C_FLAG;
if (PF_SET()) tempf |= P_FLAG;
if (AF_SET()) tempf |= A_FLAG;
if (ZF_SET()) tempf |= Z_FLAG;
if (NF_SET()) tempf |= N_FLAG;
if (VF_SET()) tempf |= V_FLAG;
flags = (flags & ~0x8d5) | tempf;
flags_op = FLAGS_UNKNOWN;
}
}
static inline void flags_extract()
{
flags_op = FLAGS_UNKNOWN;
}
static inline void flags_rebuild_c()
{
if (flags_op != FLAGS_UNKNOWN)
{
if (CF_SET())
flags |= C_FLAG;
else
flags &= ~C_FLAG;
}
}
static inline void setznp8(uint8_t val)
{
flags_op = FLAGS_ZN8;
flags_res = val;
flags &= ~C_FLAG;
}
static inline void setznp16(uint16_t val) static inline void setznp16(uint16_t val)
{ {
flags&=~0x8d5; flags_op = FLAGS_ZN16;
flags|=znptable16[val]; flags_res = val;
flags &= ~C_FLAG;
} }
static inline void setznp32(uint32_t val) static inline void setznp32(uint32_t val)
{ {
flags&=~0x8d5; flags_op = FLAGS_ZN32;
flags|=((val&0x80000000)?N_FLAG:((!val)?Z_FLAG:0)); flags_res = val;
flags|=znptable8[val&0xFF]&P_FLAG; flags &= ~C_FLAG;
} }
static inline void setadd8(uint8_t a, uint8_t b)
{
flags_op1 = a;
flags_op2 = b;
flags_res = (a + b) & 0xff;
flags_op = FLAGS_ADD8;
if ((a + b) & 0x100) flags |= C_FLAG;
else flags &= ~C_FLAG;
}
static inline void setadd16(uint16_t a, uint16_t b)
{
flags_op1 = a;
flags_op2 = b;
flags_res = (a + b) & 0xffff;
flags_op = FLAGS_ADD16;
if ((a + b) & 0x10000) flags |= C_FLAG;
else flags &= ~C_FLAG;
}
static inline void setadd32(uint32_t a, uint32_t b)
{
flags_op1 = a;
flags_op2 = b;
flags_res = a + b;
flags_op = FLAGS_ADD32;
if (flags_res < a) flags |= C_FLAG;
else flags &= ~C_FLAG;
}
static inline void setadd8nc(uint8_t a, uint8_t b)
{
flags_op1 = a;
flags_op2 = b;
flags_res = (a + b) & 0xff;
flags_op = FLAGS_ADD8;
}
static inline void setadd16nc(uint16_t a, uint16_t b)
{
flags_op1 = a;
flags_op2 = b;
flags_res = (a + b) & 0xffff;
flags_op = FLAGS_ADD16;
}
static inline void setadd32nc(uint32_t a, uint32_t b)
{
flags_op1 = a;
flags_op2 = b;
flags_res = a + b;
flags_op = FLAGS_ADD32;
}
static inline void setsub8(uint8_t a, uint8_t b)
{
flags_op1 = a;
flags_op2 = b;
flags_res = (a - b) & 0xff;
flags_op = FLAGS_SUB8;
if (a < b) flags |= C_FLAG;
else flags &= ~C_FLAG;
}
static inline void setsub16(uint16_t a, uint16_t b)
{
flags_op1 = a;
flags_op2 = b;
flags_res = (a - b) & 0xffff;
flags_op = FLAGS_SUB16;
if (a < b) flags |= C_FLAG;
else flags &= ~C_FLAG;
}
static inline void setsub32(uint32_t a, uint32_t b)
{
flags_op1 = a;
flags_op2 = b;
flags_res = a - b;
flags_op = FLAGS_SUB32;
if (a < b) flags |= C_FLAG;
else flags &= ~C_FLAG;
}
static inline void setsub8nc(uint8_t a, uint8_t b)
{
flags_op1 = a;
flags_op2 = b;
flags_res = (a - b) & 0xff;
flags_op = FLAGS_SUB8;
}
static inline void setsub16nc(uint16_t a, uint16_t b)
{
flags_op1 = a;
flags_op2 = b;
flags_res = (a - b) & 0xffff;
flags_op = FLAGS_SUB16;
}
static inline void setsub32nc(uint32_t a, uint32_t b)
{
flags_op1 = a;
flags_op2 = b;
flags_res = a - b;
flags_op = FLAGS_SUB32;
}
static inline void setadc8(uint8_t a, uint8_t b)
{
uint16_t c=(uint16_t)a+(uint16_t)b+tempc;
flags_op = FLAGS_UNKNOWN;
flags&=~0x8D5;
flags|=znptable8[c&0xFF];
if (c&0x100) flags|=C_FLAG;
if (!((a^b)&0x80)&&((a^c)&0x80)) flags|=V_FLAG;
if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG;
}
static inline void setadc16(uint16_t a, uint16_t b)
{
uint32_t c=(uint32_t)a+(uint32_t)b+tempc;
flags_op = FLAGS_UNKNOWN;
flags&=~0x8D5;
flags|=znptable16[c&0xFFFF];
if (c&0x10000) flags|=C_FLAG;
if (!((a^b)&0x8000)&&((a^c)&0x8000)) flags|=V_FLAG;
if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG;
}
static inline void setsbc8(uint8_t a, uint8_t b)
{
uint16_t c=(uint16_t)a-(((uint16_t)b)+tempc);
flags_op = FLAGS_UNKNOWN;
flags&=~0x8D5;
flags|=znptable8[c&0xFF];
if (c&0x100) flags|=C_FLAG;
if ((a^b)&(a^c)&0x80) flags|=V_FLAG;
if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG;
}
static inline void setsbc16(uint16_t a, uint16_t b)
{
uint32_t c=(uint32_t)a-(((uint32_t)b)+tempc);
flags_op = FLAGS_UNKNOWN;
flags&=~0x8D5;
flags|=(znptable16[c&0xFFFF]&~4);
flags|=(znptable8[c&0xFF]&4);
if (c&0x10000) flags|=C_FLAG;
if ((a^b)&(a^c)&0x8000) flags|=V_FLAG;
if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG;
}
static inline void setadc32(uint32_t a, uint32_t b)
{
uint32_t c=(uint32_t)a+(uint32_t)b+tempc;
flags_op = FLAGS_UNKNOWN;
flags&=~0x8D5;
flags|=((c&0x80000000)?N_FLAG:((!c)?Z_FLAG:0));
flags|=(znptable8[c&0xFF]&P_FLAG);
if ((c<a) || (c==a && tempc)) flags|=C_FLAG;
if (!((a^b)&0x80000000)&&((a^c)&0x80000000)) flags|=V_FLAG;
if (((a&0xF)+(b&0xF)+tempc)&0x10) flags|=A_FLAG;
}
static inline void setsbc32(uint32_t a, uint32_t b)
{
uint32_t c=(uint32_t)a-(((uint32_t)b)+tempc);
flags_op = FLAGS_UNKNOWN;
flags&=~0x8D5;
flags|=((c&0x80000000)?N_FLAG:((!c)?Z_FLAG:0));
flags|=(znptable8[c&0xFF]&P_FLAG);
if ((c>a) || (c==a && tempc)) flags|=C_FLAG;
if ((a^b)&(a^c)&0x80000000) flags|=V_FLAG;
if (((a&0xF)-((b&0xF)+tempc))&0x10) flags|=A_FLAG;
}

View file

@ -1,8 +1,11 @@
//#if 0 //#if 0
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h>
#include "ibm.h" #include "ibm.h"
#include "mem.h"
#include "x86.h" #include "x86.h"
#include "386.h"
/*Controls whether the accessed bit in a descriptor is set when CS is loaded. The /*Controls whether the accessed bit in a descriptor is set when CS is loaded. The
386 PRM is ambiguous on this subject, but BOCHS doesn't set it and Windows 98 386 PRM is ambiguous on this subject, but BOCHS doesn't set it and Windows 98
@ -29,7 +32,6 @@ int intgatesize;
void taskswitch286(uint16_t seg, uint16_t *segdat, int is32); void taskswitch286(uint16_t seg, uint16_t *segdat, int is32);
void taskswitch386(uint16_t seg, uint16_t *segdat); void taskswitch386(uint16_t seg, uint16_t *segdat);
int notpresent=0;
int output; int output;
void pmodeint(int num, int soft); void pmodeint(int num, int soft);
/*NOT PRESENT is INT 0B /*NOT PRESENT is INT 0B
@ -125,8 +127,6 @@ void x86ts(char *s, uint16_t error)
void x86np(char *s, uint16_t error) void x86np(char *s, uint16_t error)
{ {
// pclog("NP %04X : %s\n", error, s); // pclog("NP %04X : %s\n", error, s);
// dumpregs();
// exit(-1);
abrt = ABRT_NP; abrt = ABRT_NP;
abrt_error = error; abrt_error = error;
} }
@ -325,8 +325,6 @@ void loadcs(uint16_t seg)
{ {
uint16_t segdat[4]; uint16_t segdat[4];
uint32_t addr; uint32_t addr;
int count;
uint16_t oldss,oldsp;
if (output) pclog("Load CS %04X\n",seg); if (output) pclog("Load CS %04X\n",seg);
if (msw&1 && !(eflags&VM_FLAG)) if (msw&1 && !(eflags&VM_FLAG))
{ {
@ -452,10 +450,9 @@ void loadcsjmp(uint16_t seg, uint32_t oxpc)
uint16_t segdat[4]; uint16_t segdat[4];
uint32_t addr; uint32_t addr;
int count; int count;
uint16_t oldss,oldsp;
uint16_t type,seg2; uint16_t type,seg2;
uint32_t newpc; uint32_t newpc;
if (output) pclog("Load CS JMP %04X\n",seg); // pclog("Load CS JMP %04X\n",seg);
if (msw&1 && !(eflags&VM_FLAG)) if (msw&1 && !(eflags&VM_FLAG))
{ {
if (!(seg&~3)) if (!(seg&~3))
@ -495,6 +492,7 @@ void loadcsjmp(uint16_t seg, uint32_t oxpc)
if (output) pclog("%04X %04X %04X %04X\n",segdat[0],segdat[1],segdat[2],segdat[3]); if (output) pclog("%04X %04X %04X %04X\n",segdat[0],segdat[1],segdat[2],segdat[3]);
if (segdat[2]&0x1000) /*Normal code segment*/ if (segdat[2]&0x1000) /*Normal code segment*/
{ {
// pclog("Normal CS\n");
if (!(segdat[2]&0x400)) /*Not conforming*/ if (!(segdat[2]&0x400)) /*Not conforming*/
{ {
if ((seg&3)>CPL) if ((seg&3)>CPL)
@ -528,7 +526,7 @@ void loadcsjmp(uint16_t seg, uint32_t oxpc)
#endif #endif
CS = (seg & ~3) | CPL; CS = (seg & ~3) | CPL;
segdat[2] = (segdat[2] & ~(3 << 5+8)) | (CPL << 5+8); segdat[2] = (segdat[2] & ~(3 << (5+8))) | (CPL << (5+8));
_cs.limit=segdat[0]|((segdat[3]&0xF)<<16); _cs.limit=segdat[0]|((segdat[3]&0xF)<<16);
if (segdat[3]&0x80) _cs.limit=(_cs.limit<<12)|0xFFF; if (segdat[3]&0x80) _cs.limit=(_cs.limit<<12)|0xFFF;
@ -541,6 +539,7 @@ void loadcsjmp(uint16_t seg, uint32_t oxpc)
} }
else /*System segment*/ else /*System segment*/
{ {
// pclog("System CS\n");
if (!(segdat[2]&0x8000)) if (!(segdat[2]&0x8000))
{ {
x86np("Load CS JMP system selector not present\n", seg & 0xfffc); x86np("Load CS JMP system selector not present\n", seg & 0xfffc);
@ -553,6 +552,7 @@ void loadcsjmp(uint16_t seg, uint32_t oxpc)
{ {
case 0x400: /*Call gate*/ case 0x400: /*Call gate*/
case 0xC00: case 0xC00:
// pclog("Call gate\n");
cgate32=(type&0x800); cgate32=(type&0x800);
cgate16=!cgate32; cgate16=!cgate32;
oldcs=CS; oldcs=CS;
@ -654,6 +654,7 @@ void loadcsjmp(uint16_t seg, uint32_t oxpc)
case 0x900: /*386 Task gate*/ case 0x900: /*386 Task gate*/
// pclog("Task gate\n");
pc=oxpc; pc=oxpc;
cpl_override=1; cpl_override=1;
taskswitch286(seg,segdat,segdat[2]&0x800); taskswitch286(seg,segdat,segdat[2]&0x800);
@ -853,7 +854,7 @@ void loadcscall(uint16_t seg)
if (segdat[2]&0x400) if (segdat[2]&0x400)
{ {
seg = (seg & ~3) | CPL; seg = (seg & ~3) | CPL;
segdat[2] = (segdat[2] & ~(3 << 5+8)) | (CPL << 5+8); segdat[2] = (segdat[2] & ~(3 << (5+8))) | (CPL << (5+8));
} }
else /*On non-conforming segments, set RPL = CPL*/ else /*On non-conforming segments, set RPL = CPL*/
seg = (seg & ~3) | CPL; seg = (seg & ~3) | CPL;
@ -1332,7 +1333,7 @@ void pmoderetf(int is32, uint16_t off)
pc=newpc; pc=newpc;
if (segdat[2] & 0x400) if (segdat[2] & 0x400)
segdat[2] = (segdat[2] & ~(3 << 5+8)) | ((seg & 3) << 5+8); segdat[2] = (segdat[2] & ~(3 << (5+8))) | ((seg & 3) << (5+8));
CS = seg; CS = seg;
_cs.limit=segdat[0]|((segdat[3]&0xF)<<16); _cs.limit=segdat[0]|((segdat[3]&0xF)<<16);
if (segdat[3]&0x80) _cs.limit=(_cs.limit<<12)|0xFFF; if (segdat[3]&0x80) _cs.limit=(_cs.limit<<12)|0xFFF;
@ -1493,7 +1494,7 @@ void pmoderetf(int is32, uint16_t off)
#endif #endif
/*Conforming segments don't change CPL, so CPL = RPL*/ /*Conforming segments don't change CPL, so CPL = RPL*/
if (segdat[2]&0x400) if (segdat[2]&0x400)
segdat[2] = (segdat[2] & ~(3 << 5+8)) | ((seg & 3) << 5+8); segdat[2] = (segdat[2] & ~(3 << (5+8))) | ((seg & 3) << (5+8));
pc=newpc; pc=newpc;
CS=seg; CS=seg;
@ -1521,14 +1522,11 @@ void pmodeint(int num, int soft)
{ {
uint16_t segdat[4],segdat2[4],segdat3[4]; uint16_t segdat[4],segdat2[4],segdat3[4];
uint32_t addr, oaddr; uint32_t addr, oaddr;
int dpl; uint16_t newss;
uint16_t oldcs=CPL,oldcs2,newss;
uint32_t oldss,oldsp; uint32_t oldss,oldsp;
uint8_t oldaccess;
int type; int type;
uint32_t newsp; uint32_t newsp;
uint16_t seg; uint16_t seg;
int v86int=eflags&VM_FLAG;
int stack_changed=0; int stack_changed=0;
// if (!num) pclog("Pmode int 0 at %04X(%06X):%08X\n",CS,cs,pc); // if (!num) pclog("Pmode int 0 at %04X(%06X):%08X\n",CS,cs,pc);
// pclog("Pmode int %02X %i %04X:%08X %04X:%08X %i\n",num,soft,CS,pc, SS, ESP, abrt); // pclog("Pmode int %02X %i %04X:%08X %04X:%08X %i\n",num,soft,CS,pc, SS, ESP, abrt);
@ -1910,12 +1908,10 @@ void pmodeint(int num, int soft)
} }
} }
int inint;
void pmodeiret(int is32) void pmodeiret(int is32)
{ {
uint32_t newsp; uint32_t newsp;
uint16_t oldcs=CPL,newss; uint16_t newss;
uint16_t tempw,tempw2;
uint32_t tempflags,flagmask; uint32_t tempflags,flagmask;
uint32_t newpc; uint32_t newpc;
uint16_t segdat[4],segdat2[4]; uint16_t segdat[4],segdat2[4];
@ -1991,7 +1987,6 @@ void pmodeiret(int is32)
cpl_override=0; cpl_override=0;
return; return;
} }
inint=0;
oxpc=pc; oxpc=pc;
flagmask=0xFFFF; flagmask=0xFFFF;
if (CPL) flagmask&=~0x3000; if (CPL) flagmask&=~0x3000;
@ -2254,7 +2249,7 @@ void pmodeiret(int is32)
#endif #endif
/*Conforming segments don't change CPL, so CPL = RPL*/ /*Conforming segments don't change CPL, so CPL = RPL*/
if (segdat[2]&0x400) if (segdat[2]&0x400)
segdat[2] = (segdat[2] & ~(3 << 5+8)) | ((seg & 3) << 5+8); segdat[2] = (segdat[2] & ~(3 << (5+8))) | ((seg & 3) << (5+8));
CS=seg; CS=seg;
_cs.limit=segdat[0]|((segdat[3]&0xF)<<16); _cs.limit=segdat[0]|((segdat[3]&0xF)<<16);
@ -2295,12 +2290,10 @@ void pmodeiret(int is32)
void taskswitch286(uint16_t seg, uint16_t *segdat, int is32) void taskswitch286(uint16_t seg, uint16_t *segdat, int is32)
{ {
uint32_t base,obase=tr.base; uint32_t base;
uint32_t limit; uint32_t limit;
int x386;
uint32_t templ; uint32_t templ;
uint16_t tempw; uint16_t tempw;
int c;
uint32_t new_cr3=0; uint32_t new_cr3=0;
uint16_t new_es,new_cs,new_ss,new_ds,new_fs,new_gs; uint16_t new_es,new_cs,new_ss,new_ds,new_fs,new_gs;
@ -2310,8 +2303,6 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32)
uint32_t addr; uint32_t addr;
uint16_t oldflags;
uint16_t segdat2[4]; uint16_t segdat2[4];
//output=3; //output=3;
@ -2361,6 +2352,7 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32)
if (optype==IRET) flags&=~NT_FLAG; if (optype==IRET) flags&=~NT_FLAG;
// if (output) pclog("Write PC %08X %08X\n",tr.base,pc); // if (output) pclog("Write PC %08X %08X\n",tr.base,pc);
cpu_386_flags_rebuild();
writememl(tr.base,0x1C,cr3); writememl(tr.base,0x1C,cr3);
writememl(tr.base,0x20,pc); writememl(tr.base,0x20,pc);
writememl(tr.base,0x24,flags|(eflags<<16)); writememl(tr.base,0x24,flags|(eflags<<16));
@ -2402,7 +2394,7 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32)
cr3=new_cr3; cr3=new_cr3;
// pclog("New CR3 %08X\n",cr3); pclog("TS New CR3 %08X\n",cr3);
flushmmucache(); flushmmucache();
@ -2411,6 +2403,7 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32)
// if (output) pclog("New pc %08X\n",new_pc); // if (output) pclog("New pc %08X\n",new_pc);
flags=new_flags; flags=new_flags;
eflags=new_flags>>16; eflags=new_flags>>16;
cpu_386_flags_extract();
// if (output) pclog("Load LDT %04X\n",new_ldt); // if (output) pclog("Load LDT %04X\n",new_ldt);
ldt.seg=new_ldt; ldt.seg=new_ldt;

239
src/x87.c
View file

@ -8,8 +8,11 @@
//SCR_CalcRefdef //SCR_CalcRefdef
//Calls R_SetVrect and R_ViewChanged //Calls R_SetVrect and R_ViewChanged
#define fplog 0
#include <math.h> #include <math.h>
#include "ibm.h" #include "ibm.h"
#include "pic.h"
#include "x86.h" #include "x86.h"
#include "x87.h" #include "x87.h"
@ -67,6 +70,30 @@ int TOP;
#define C2 (1<<10) #define C2 (1<<10)
#define C3 (1<<14) #define C3 (1<<14)
#define STATUS_ZERODIVIDE 4
#define x87_div(dst, src1, src2) do \
{ \
if (((double)src2) == 0.0) \
{ \
npxs |= STATUS_ZERODIVIDE; \
if (npxc & STATUS_ZERODIVIDE) \
dst = src1 / (double)src2; \
else \
{ \
pclog("FPU : divide by zero\n"); \
picint(1 << 13); \
} \
return; \
} \
else \
dst = src1 / (double)src2; \
} while (0)
void x87_checkexceptions()
{
}
void x87_reset() void x87_reset()
{ {
} }
@ -80,8 +107,8 @@ void x87_dumpregs()
void x87_print() void x87_print()
{ {
pclog("\tST(0)=%.20f\tST(1)=%.20f\tST(2)=%f\tST(3)=%f\t",ST[TOP],ST[(TOP+1)&7],ST[(TOP+2)&7],ST[(TOP+3)&7]); pclog("\tST(0)=%.20f\tST(1)=%.20f\tST(2)=%f\tST(3)=%f\t",ST[TOP&7],ST[(TOP+1)&7],ST[(TOP+2)&7],ST[(TOP+3)&7]);
pclog("ST(4)=%f\tST(5)=%f\tST(6)=%f\tST(7)=%f\t\n\n",ST[(TOP+4)&7],ST[(TOP+5)&7],ST[(TOP+6)&7],ST[(TOP+7)&7]); pclog("ST(4)=%f\tST(5)=%f\tST(6)=%f\tST(7)=%f\t TOP=%i CR=%04X SR=%04X TAG=%04X\n",ST[(TOP+4)&7],ST[(TOP+5)&7],ST[(TOP+6)&7],ST[(TOP+7)&7], TOP, npxc, npxs, tag);
} }
void x87_push(double i) void x87_push(double i)
@ -186,16 +213,19 @@ void x87_d8()
{ {
case 0xC0: case 0xC1: case 0xC2: case 0xC3: /*FADD*/ case 0xC0: case 0xC1: case 0xC2: case 0xC3: /*FADD*/
case 0xC4: case 0xC5: case 0xC6: case 0xC7: case 0xC4: case 0xC5: case 0xC6: case 0xC7:
if (fplog) pclog("FADD\n");
ST(0)=ST(0)+ST(rmdat32&7); ST(0)=ST(0)+ST(rmdat32&7);
cycles-=8; cycles-=8;
return; return;
case 0xC8: case 0xC9: case 0xCA: case 0xCB: /*FMUL*/ case 0xC8: case 0xC9: case 0xCA: case 0xCB: /*FMUL*/
case 0xCC: case 0xCD: case 0xCE: case 0xCF: case 0xCC: case 0xCD: case 0xCE: case 0xCF:
if (fplog) pclog("FMUL\n");
ST(0)=ST(0)*ST(rmdat32&7); ST(0)=ST(0)*ST(rmdat32&7);
cycles-=16; cycles-=16;
return; return;
case 0xD0: case 0xD1: case 0xD2: case 0xD3: /*FCOM*/ case 0xD0: case 0xD1: case 0xD2: case 0xD3: /*FCOM*/
case 0xD4: case 0xD5: case 0xD6: case 0xD7: case 0xD4: case 0xD5: case 0xD6: case 0xD7:
if (fplog) pclog("FCOM\n");
npxs&=~(C0|C2|C3); npxs&=~(C0|C2|C3);
if (ST(0)==ST(rmdat32&7)) npxs|=C3; if (ST(0)==ST(rmdat32&7)) npxs|=C3;
else if (ST(0)<ST(rmdat32&7)) npxs|=C0; else if (ST(0)<ST(rmdat32&7)) npxs|=C0;
@ -203,6 +233,7 @@ void x87_d8()
return; return;
case 0xD8: case 0xD9: case 0xDA: case 0xDB: /*FCOMP*/ case 0xD8: case 0xD9: case 0xDA: case 0xDB: /*FCOMP*/
case 0xDC: case 0xDD: case 0xDE: case 0xDF: case 0xDC: case 0xDD: case 0xDE: case 0xDF:
if (fplog) pclog("FCOMP\n");
npxs&=~(C0|C2|C3); npxs&=~(C0|C2|C3);
if (ST(0)==ST(rmdat32&7)) npxs|=C3; if (ST(0)==ST(rmdat32&7)) npxs|=C3;
else if (ST(0)<ST(rmdat32&7)) npxs|=C0; else if (ST(0)<ST(rmdat32&7)) npxs|=C0;
@ -211,22 +242,26 @@ void x87_d8()
return; return;
case 0xE0: case 0xE1: case 0xE2: case 0xE3: /*FSUB*/ case 0xE0: case 0xE1: case 0xE2: case 0xE3: /*FSUB*/
case 0xE4: case 0xE5: case 0xE6: case 0xE7: case 0xE4: case 0xE5: case 0xE6: case 0xE7:
if (fplog) pclog("FSUB\n");
ST(0)=ST(0)-ST(rmdat32&7); ST(0)=ST(0)-ST(rmdat32&7);
cycles-=8; cycles-=8;
return; return;
case 0xE8: case 0xE9: case 0xEA: case 0xEB: /*FSUBR*/ case 0xE8: case 0xE9: case 0xEA: case 0xEB: /*FSUBR*/
case 0xEC: case 0xED: case 0xEE: case 0xEF: case 0xEC: case 0xED: case 0xEE: case 0xEF:
if (fplog) pclog("FSUBR\n");
ST(0)=ST(rmdat32&7)-ST(0); ST(0)=ST(rmdat32&7)-ST(0);
cycles-=8; cycles-=8;
return; return;
case 0xF0: case 0xF1: case 0xF2: case 0xF3: /*FDIV*/ case 0xF0: case 0xF1: case 0xF2: case 0xF3: /*FDIV*/
case 0xF4: case 0xF5: case 0xF6: case 0xF7: case 0xF4: case 0xF5: case 0xF6: case 0xF7:
ST(0)=ST(0)/ST(rmdat32&7); if (fplog) pclog("FDIV\n");
x87_div(ST(0), ST(0), ST(rmdat32&7));
cycles-=73; cycles-=73;
return; return;
case 0xF8: case 0xF9: case 0xFA: case 0xFB: /*FDIVR*/ case 0xF8: case 0xF9: case 0xFA: case 0xFB: /*FDIVR*/
case 0xFC: case 0xFD: case 0xFE: case 0xFF: case 0xFC: case 0xFD: case 0xFE: case 0xFF:
ST(0)=ST(rmdat32&7)/ST(0); if (fplog) pclog("FDIVR\n");
x87_div(ST(0), ST(rmdat32&7), ST(0));
cycles-=73; cycles-=73;
return; return;
} }
@ -237,20 +272,25 @@ void x87_d8()
switch (reg) switch (reg)
{ {
case 0: /*FADD short*/ case 0: /*FADD short*/
if (fplog) pclog("FADDs %08X:%08X %f %f\n", easeg, eaaddr, ST(0), ts.s);
ST(0)+=ts.s; ST(0)+=ts.s;
cycles-=8; cycles-=8;
return; return;
case 1: /*FMUL short*/ case 1: /*FMUL short*/
if (fplog) pclog("FMULs %08X:%08X %f %f\n", easeg, eaaddr, ST(0), ts.s);
ST(0)*=ts.s; ST(0)*=ts.s;
cycles-=11; cycles-=11;
if (abrt) pclog("ABRT FMUL\n");
return; return;
case 2: /*FCOM short*/ case 2: /*FCOM short*/
if (fplog) pclog("FCOMs %08X:%08X %f %f\n", easeg, eaaddr, ST(0), ts.s);
npxs&=~(C0|C2|C3); npxs&=~(C0|C2|C3);
if (ST(0)==ts.s) npxs|=C3; if (ST(0)==ts.s) npxs|=C3;
else if (ST(0)<ts.s) npxs|=C0; else if (ST(0)<ts.s) npxs|=C0;
cycles-=4; cycles-=4;
return; return;
case 3: /*FCOMP short*/ case 3: /*FCOMP short*/
if (fplog) pclog("FCOMPs %08X:%08X %f %f\n", easeg, eaaddr, ST(0), ts.s);
npxs&=~(C0|C2|C3); npxs&=~(C0|C2|C3);
if (ST(0)==ts.s) npxs|=C3; if (ST(0)==ts.s) npxs|=C3;
else if (ST(0)<ts.s) npxs|=C0; else if (ST(0)<ts.s) npxs|=C0;
@ -258,19 +298,23 @@ void x87_d8()
x87_pop(); x87_pop();
return; return;
case 4: /*FSUB short*/ case 4: /*FSUB short*/
if (fplog) pclog("FSUBs %08X:%08X %f %f\n", easeg, eaaddr, ST(0), ts.s);
ST(0)-=ts.s; ST(0)-=ts.s;
cycles-=8; cycles-=8;
return; return;
case 5: /*FSUBR short*/ case 5: /*FSUBR short*/
if (fplog) pclog("FSUBRs %08X:%08X %f %f\n", easeg, eaaddr, ST(0), ts.s);
ST(0)=ts.s-ST(0); ST(0)=ts.s-ST(0);
cycles-=8; cycles-=8;
return; return;
case 6: /*FDIV short*/ case 6: /*FDIV short*/
ST(0)=ST(0)/ts.s; if (fplog) pclog("FDIVs %08X:%08X %f %f\n", easeg, eaaddr, ST(0), ts.s);
x87_div(ST(0), ST(0), ts.s);
cycles-=73; cycles-=73;
return; return;
case 7: /*FDIVR short*/ case 7: /*FDIVR short*/
ST(0)=ts.s/ST(0); if (fplog) pclog("FDIVRs %08X:%08X %f %f\n", easeg, eaaddr, ST(0), ts.s);
x87_div(ST(0), ts.s, ST(0));
cycles-=73; cycles-=73;
return; return;
} }
@ -285,7 +329,6 @@ void x87_d9()
float s; float s;
uint32_t i; uint32_t i;
} ts; } ts;
float t;
double td; double td;
int64_t temp64; int64_t temp64;
uint16_t tempw; uint16_t tempw;
@ -295,82 +338,99 @@ void x87_d9()
{ {
case 0xC0: case 0xC1: case 0xC2: case 0xC3: /*FLD*/ case 0xC0: case 0xC1: case 0xC2: case 0xC3: /*FLD*/
case 0xC4: case 0xC5: case 0xC6: case 0xC7: case 0xC4: case 0xC5: case 0xC6: case 0xC7:
if (fplog) pclog("FLD %f\n", ST(rmdat32 & 7));
x87_push(ST(rmdat32&7)); x87_push(ST(rmdat32&7));
cycles-=4; cycles-=4;
return; return;
case 0xC8: case 0xC9: case 0xCA: case 0xCB: /*FXCH*/ case 0xC8: case 0xC9: case 0xCA: case 0xCB: /*FXCH*/
case 0xCC: case 0xCD: case 0xCE: case 0xCF: case 0xCC: case 0xCD: case 0xCE: case 0xCF:
if (fplog) pclog("FXCH\n");
td=ST(0); td=ST(0);
ST(0)=ST(rmdat32&7); ST(0)=ST(rmdat32&7);
ST(rmdat32&7)=td; ST(rmdat32&7)=td;
cycles-=4; cycles-=4;
return; return;
case 0xD0: /*FNOP*/ case 0xD0: /*FNOP*/
if (fplog) pclog("FNOP\n");
cycles-=3; cycles-=3;
return; return;
case 0xE0: /*FCHS*/ case 0xE0: /*FCHS*/
if (fplog) pclog("FCHS\n");
ST(0)=-ST(0); ST(0)=-ST(0);
cycles-=6; cycles-=6;
return; return;
case 0xE1: /*FABS*/ case 0xE1: /*FABS*/
if (fplog) pclog("FABS %f\n", ST(0));
ST(0)=fabs(ST(0)); ST(0)=fabs(ST(0));
cycles-=3; cycles-=3;
return; return;
case 0xE4: /*FTST*/ case 0xE4: /*FTST*/
if (fplog) pclog("FTST\n");
npxs&=~(C0|C2|C3); npxs&=~(C0|C2|C3);
if (ST(0)==0.0) npxs|=C3; if (ST(0)==0.0) npxs|=C3;
else if (ST(0)<0.0) npxs|=C0; else if (ST(0)<0.0) npxs|=C0;
cycles-=4; cycles-=4;
return; return;
case 0xE5: /*FXAM*/ case 0xE5: /*FXAM*/
// pclog("FXAM %f %i\n",ST(0),(tag>>((TOP&1)<<1))&3); if (fplog) pclog("FXAM %i %f\n", ((tag>>((TOP&7)<<1))&3), ST(0));
// pclog("FXAM %f %i\n",ST(0),(tag>>((TOP&7)<<1))&3);
npxs&=~(C0|C2|C3); npxs&=~(C0|C2|C3);
if (((tag>>((TOP&1)<<1))&3)==3) npxs|=(C0|C3); if (((tag>>((TOP&7)<<1))&3)==3) npxs|=(C0|C3);
else if (ST(0)==0.0) npxs|=C3; else if (ST(0)==0.0) npxs|=C3;
else npxs|=C2; else npxs|=C2;
if (ST(0)<0.0) npxs|=C1; if (ST(0)<0.0) npxs|=C1;
cycles-=8; cycles-=8;
return; return;
case 0xE8: /*FLD1*/ case 0xE8: /*FLD1*/
if (fplog) pclog("FLD1\n");
x87_push(1.0); x87_push(1.0);
cycles-=4; cycles-=4;
return; return;
case 0xE9: /*FLDL2T*/ case 0xE9: /*FLDL2T*/
if (fplog) pclog("FLDL2T\n");
x87_push(3.3219280948873623); x87_push(3.3219280948873623);
cycles-=8; cycles-=8;
return; return;
case 0xEA: /*FLDL2E*/ case 0xEA: /*FLDL2E*/
if (fplog) pclog("FLDL2E\n");
x87_push(1.4426950408889634); x87_push(1.4426950408889634);
cycles-=8; cycles-=8;
return; return;
case 0xEB: /*FLDPI*/ case 0xEB: /*FLDPI*/
if (fplog) pclog("FLDPI\n");
x87_push(3.141592653589793); x87_push(3.141592653589793);
cycles-=8; cycles-=8;
return; return;
case 0xEC: /*FLDEG2*/ case 0xEC: /*FLDEG2*/
if (fplog) pclog("FLDEG2\n");
x87_push(0.3010299956639812); x87_push(0.3010299956639812);
cycles-=8; cycles-=8;
return; return;
case 0xED: /*FLDLN2*/ case 0xED: /*FLDLN2*/
if (fplog) pclog("FLDLN2\n");
x87_push(0.693147180559945); x87_push(0.693147180559945);
cycles-=8; cycles-=8;
return; return;
case 0xEE: /*FLDZ*/ case 0xEE: /*FLDZ*/
if (fplog) pclog("FLDZ\n");
// pclog("FLDZ %04X:%08X\n",CS,pc); // pclog("FLDZ %04X:%08X\n",CS,pc);
x87_push(0.0); x87_push(0.0);
tag|=(1<<((TOP&7)<<1)); tag|=(1<<((TOP&7)<<1));
cycles-=4; cycles-=4;
return; return;
case 0xF0: /*F2XM1*/ case 0xF0: /*F2XM1*/
if (fplog) pclog("F2XM1\n");
ST(0)=pow(2.0,ST(0))-1.0; ST(0)=pow(2.0,ST(0))-1.0;
cycles-=200; cycles-=200;
return; return;
case 0xF1: /*FYL2X*/ case 0xF1: /*FYL2X*/
if (fplog) pclog("FYL2X\n");
ST(1)=ST(1)*(log(ST(0))/log(2.0)); ST(1)=ST(1)*(log(ST(0))/log(2.0));
x87_pop(); x87_pop();
cycles-=250; cycles-=250;
return; return;
case 0xF2: /*FPTAN*/ case 0xF2: /*FPTAN*/
if (fplog) pclog("FPTAN\n");
// pclog("Tan of %f = ",ST(0)); // pclog("Tan of %f = ",ST(0));
ST(0)=tan(ST(0)); ST(0)=tan(ST(0));
// pclog("%f\n",ST(0)); // pclog("%f\n",ST(0));
@ -379,20 +439,31 @@ void x87_d9()
cycles-=235; cycles-=235;
return; return;
case 0xF3: /*FPATAN*/ case 0xF3: /*FPATAN*/
if (fplog) pclog("FPATAN\n");
/* times++;
if (times==50)
{
dumpregs();
exit(-1);
}*/
// pclog("FPATAN %08X\n",pc); // pclog("FPATAN %08X\n",pc);
ST(1)=atan2(ST(1),ST(0)); ST(1)=atan2(ST(1),ST(0));
x87_pop(); x87_pop();
cycles-=250; cycles-=250;
return; return;
case 0xF6: /*FDECSTP*/ case 0xF6: /*FDECSTP*/
if (fplog) pclog("FDECSTP\n");
TOP=(TOP-1)&7; TOP=(TOP-1)&7;
return; return;
case 0xF7: /*FINCSTP*/ case 0xF7: /*FINCSTP*/
if (fplog) pclog("FINCSTP\n");
TOP=(TOP+1)&7; TOP=(TOP+1)&7;
return; return;
case 0xF8: /*FPREM*/ case 0xF8: /*FPREM*/
if (fplog) pclog("FPREM %f %f ", ST(0), ST(1));
temp64=(int64_t)(ST(0)/ST(1)); temp64=(int64_t)(ST(0)/ST(1));
ST(0)=ST(0)-(ST(1)*(double)temp64); ST(0)=ST(0)-(ST(1)*(double)temp64);
if (fplog) pclog("%f\n", ST(0));
npxs&=~(C0|C1|C2|C3); npxs&=~(C0|C1|C2|C3);
if (temp64&4) npxs|=C0; if (temp64&4) npxs|=C0;
if (temp64&2) npxs|=C3; if (temp64&2) npxs|=C3;
@ -400,10 +471,12 @@ void x87_d9()
cycles-=100; cycles-=100;
return; return;
case 0xFA: /*FSQRT*/ case 0xFA: /*FSQRT*/
if (fplog) pclog("FSQRT\n");
ST(0)=sqrt(ST(0)); ST(0)=sqrt(ST(0));
cycles-=83; cycles-=83;
return; return;
case 0xFB: /*FSINCOS*/ case 0xFB: /*FSINCOS*/
if (fplog) pclog("FSINCOS\n");
td=ST(0); td=ST(0);
ST(0)=sin(td); ST(0)=sin(td);
x87_push(cos(td)); x87_push(cos(td));
@ -411,22 +484,26 @@ void x87_d9()
cycles-=330; cycles-=330;
return; return;
case 0xFC: /*FRNDINT*/ case 0xFC: /*FRNDINT*/
if (fplog) pclog("FRNDINT\n");
// pclog("FRNDINT %f %i ",ST(0),(npxc>>10)&3); // pclog("FRNDINT %f %i ",ST(0),(npxc>>10)&3);
ST(0)=(double)x87_fround(ST(0)); ST(0)=(double)x87_fround(ST(0));
// pclog("%f\n",ST(0)); // pclog("%f\n",ST(0));
cycles-=21; cycles-=21;
return; return;
case 0xFD: /*FSCALE*/ case 0xFD: /*FSCALE*/
if (fplog) pclog("FSCALE\n");
temp64=(int64_t)ST(1); temp64=(int64_t)ST(1);
ST(0)=ST(0)*pow(2.0,(double)temp64); ST(0)=ST(0)*pow(2.0,(double)temp64);
cycles-=30; cycles-=30;
return; return;
case 0xFE: /*FSIN*/ case 0xFE: /*FSIN*/
if (fplog) pclog("FSIN\n");
ST(0)=sin(ST(0)); ST(0)=sin(ST(0));
npxs&=~C2; npxs&=~C2;
cycles-=300; cycles-=300;
return; return;
case 0xFF: /*FCOS*/ case 0xFF: /*FCOS*/
if (fplog) pclog("FCOS\n");
ST(0)=cos(ST(0)); ST(0)=cos(ST(0));
npxs&=~C2; npxs&=~C2;
cycles-=300; cycles-=300;
@ -438,24 +515,30 @@ void x87_d9()
switch (reg) switch (reg)
{ {
case 0: /*FLD single-precision*/ case 0: /*FLD single-precision*/
if (fplog) pclog("FLDs %08X:%08X\n", easeg, eaaddr);
// if ((rmdat32&0xFFFF)==0xD445) { pclog("FLDS\n"); output=3; dumpregs(); exit(-1); } // if ((rmdat32&0xFFFF)==0xD445) { pclog("FLDS\n"); output=3; dumpregs(); exit(-1); }
ts.i=(float)geteal(); if (abrt) return; ts.i=geteal(); if (abrt) { pclog("FLD sp abort\n"); return; }
if (fplog) pclog(" %f\n", ts.s);
x87_push((double)ts.s); x87_push((double)ts.s);
cycles-=3; cycles-=3;
return; return;
case 2: /*FST single-precision*/ case 2: /*FST single-precision*/
if (fplog) pclog("FSTs %08X:%08X\n", easeg, eaaddr);
ts.s=(float)ST(0); ts.s=(float)ST(0);
seteal(ts.i); seteal(ts.i);
if (abrt) { pclog("FST sp abort\n"); return; }
cycles-=7; cycles-=7;
return; return;
case 3: /*FSTP single-precision*/ case 3: /*FSTP single-precision*/
if (fplog) pclog("FSTPs %08X:%08X\n", easeg, eaaddr);
ts.s=(float)ST(0); ts.s=(float)ST(0);
seteal(ts.i); if (abrt) return; seteal(ts.i); if (abrt) { pclog("FSTP sp abort\n"); return; }
// if (pc==0x3f50c) pclog("FSTP %f %f %08X\n",ST(0),ts.s,ts.i); // if (pc==0x3f50c) pclog("FSTP %f %f %08X\n",ST(0),ts.s,ts.i);
x87_pop(); x87_pop();
cycles-=7; cycles-=7;
return; return;
case 4: /*FLDENV*/ case 4: /*FLDENV*/
if (fplog) pclog("FLDENV %08X:%08X\n", easeg, eaaddr);
switch ((cr0&1)|(op32&0x100)) switch ((cr0&1)|(op32&0x100))
{ {
case 0x000: /*16-bit real mode*/ case 0x000: /*16-bit real mode*/
@ -474,14 +557,17 @@ void x87_d9()
break; break;
} }
cycles-=(cr0&1)?34:44; cycles-=(cr0&1)?34:44;
if (abrt) { pclog("FLDENV\n"); return; }
return; return;
case 5: /*FLDCW*/ case 5: /*FLDCW*/
if (fplog) pclog("FLDCW %08X:%08X\n", easeg, eaaddr);
tempw=geteaw(); tempw=geteaw();
if (abrt) return; if (abrt) if (abrt) { pclog("FLDCW abort\n"); return; }
npxc=tempw; npxc=tempw;
cycles-=4; cycles-=4;
return; return;
case 6: /*FSTENV*/ case 6: /*FSTENV*/
if (fplog) pclog("FSTENV %08X:%08X\n", easeg, eaaddr);
switch ((cr0&1)|(op32&0x100)) switch ((cr0&1)|(op32&0x100))
{ {
case 0x000: /*16-bit real mode*/ case 0x000: /*16-bit real mode*/
@ -518,10 +604,13 @@ void x87_d9()
writememl(easeg,eaaddr+24,x87_op_seg); writememl(easeg,eaaddr+24,x87_op_seg);
break; break;
} }
if (abrt) { pclog("FSTENV\n"); return; }
cycles-=(cr0&1)?56:67; cycles-=(cr0&1)?56:67;
return; return;
case 7: /*FSTCW*/ case 7: /*FSTCW*/
if (fplog) pclog("FSTCW %08X:%08X\n", easeg, eaaddr);
seteaw(npxc); seteaw(npxc);
if (abrt) { pclog("FSTCW\n"); return; }
cycles-=3; cycles-=3;
return; return;
} }
@ -537,6 +626,7 @@ void x87_da()
switch (rmdat32&0xFF) switch (rmdat32&0xFF)
{ {
case 0xE9: /*FUCOMPP*/ case 0xE9: /*FUCOMPP*/
if (fplog) pclog("FUCOMPP\n", easeg, eaaddr);
npxs&=~(C0|C2|C3); npxs&=~(C0|C2|C3);
if (ST(0)==ST(1)) npxs|=C3; if (ST(0)==ST(1)) npxs|=C3;
else if (ST(0)<ST(1)) npxs|=C0; else if (ST(0)<ST(1)) npxs|=C0;
@ -548,24 +638,28 @@ void x87_da()
} }
else else
{ {
templ=geteal(); if (abrt) return; templ=(int32_t)geteal(); if (abrt) return;
switch (reg) switch (reg)
{ {
case 0: /*FIADD*/ case 0: /*FIADD*/
if (fplog) pclog("FIADDl %08X:%08X %f %f\n", easeg, eaaddr, ST(0), (double)templ);
ST(0)=ST(0)+(double)templ; ST(0)=ST(0)+(double)templ;
cycles-=20; cycles-=20;
return; return;
case 1: /*FIMUL*/ case 1: /*FIMUL*/
if (fplog) pclog("FIMULl %08X:%08X %f %f\n", easeg, eaaddr, ST(0), (double)templ);
ST(0)=ST(0)*(double)templ; ST(0)=ST(0)*(double)templ;
cycles-=22; cycles-=22;
return; return;
case 2: /*FICOM*/ case 2: /*FICOM*/
if (fplog) pclog("FICOMl %08X:%08X %f %f\n", easeg, eaaddr, ST(0), (double)templ);
npxs&=~(C0|C2|C3); npxs&=~(C0|C2|C3);
if (ST(0)==(double)templ) npxs|=C3; if (ST(0)==(double)templ) npxs|=C3;
else if (ST(0)<(double)templ) npxs|=C0; else if (ST(0)<(double)templ) npxs|=C0;
cycles-=15; cycles-=15;
return; return;
case 3: /*FICOMP*/ case 3: /*FICOMP*/
if (fplog) pclog("FICOMPl %08X:%08X %f %f\n", easeg, eaaddr, ST(0), (double)templ);
npxs&=~(C0|C2|C3); npxs&=~(C0|C2|C3);
if (ST(0)==(double)templ) npxs|=C3; if (ST(0)==(double)templ) npxs|=C3;
else if (ST(0)<(double)templ) npxs|=C0; else if (ST(0)<(double)templ) npxs|=C0;
@ -573,19 +667,23 @@ void x87_da()
cycles-=15; cycles-=15;
return; return;
case 4: /*FISUB*/ case 4: /*FISUB*/
if (fplog) pclog("FISUBl %08X:%08X %f %f\n", easeg, eaaddr, ST(0), (double)templ);
ST(0)=ST(0)-(double)templ; ST(0)=ST(0)-(double)templ;
cycles-=20; cycles-=20;
return; return;
case 5: /*FISUBR*/ case 5: /*FISUBR*/
if (fplog) pclog("FISUBRl %08X:%08X %f %f\n", easeg, eaaddr, ST(0), (double)templ);
ST(0)=(double)templ-ST(0); ST(0)=(double)templ-ST(0);
cycles-=19; cycles-=19;
return; return;
case 6: /*FIDIV*/ case 6: /*FIDIV*/
ST(0)=ST(0)/(double)templ; if (fplog) pclog("FIDIVl %08X:%08X %f %f\n", easeg, eaaddr, ST(0), (double)templ);
x87_div(ST(0), ST(0), (double)templ);
cycles-=84; cycles-=84;
return; return;
case 7: /*FIDIVR*/ case 7: /*FIDIVR*/
ST(0)=(double)templ/ST(0); if (fplog) pclog("FIDIVRl %08X:%08X %f %f\n", easeg, eaaddr, ST(0), (double)templ);
x87_div(ST(0), (double)templ, ST(0));
cycles-=84; cycles-=84;
return; return;
} }
@ -597,6 +695,7 @@ void x87_db()
{ {
double t; double t;
int32_t templ; int32_t templ;
int64_t temp64;
if (mod==3) if (mod==3)
{ {
switch (reg) switch (reg)
@ -607,9 +706,11 @@ void x87_db()
case 0xE1: case 0xE1:
return; return;
case 0xE2: /*FCLEX*/ case 0xE2: /*FCLEX*/
if (fplog) pclog("FCLEX\n");
npxs&=0xFF00; npxs&=0xFF00;
return; return;
case 0xE3: /*FINIT*/ case 0xE3: /*FINIT*/
if (fplog) pclog("FINIT\n");
npxc=0x37F; npxc=0x37F;
npxs=0; npxs=0;
tag=0xFFFF; tag=0xFFFF;
@ -627,25 +728,38 @@ void x87_db()
switch (reg) switch (reg)
{ {
case 0: /*FILD short*/ case 0: /*FILD short*/
if (fplog) pclog("FILDs %08X:%08X\n", easeg, eaaddr);
templ=geteal(); if (abrt) return; templ=geteal(); if (abrt) return;
if (fplog) pclog(" %f %08X %i\n", (double)templ, templ, templ);
x87_push((double)templ); x87_push((double)templ);
cycles-=9; cycles-=9;
return; return;
case 2: /*FIST short*/ case 2: /*FIST short*/
seteal((int32_t)x87_fround(ST(0))); if (fplog) pclog("FISTs %08X:%08X\n", easeg, eaaddr);
temp64 = x87_fround(ST(0));
/* if (temp64 > 2147483647 || temp64 < -2147483647)
fatal("FISTl out of range! %i\n", temp64);*/
seteal((int32_t)temp64);
cycles-=28; cycles-=28;
return; return;
case 3: /*FISTP short*/ case 3: /*FISTP short*/
seteal((int32_t)x87_fround(ST(0))); if (abrt) return; if (fplog) pclog("FISTPs %08X:%08X\n", easeg, eaaddr);
temp64 = x87_fround(ST(0));
/* if (temp64 > 2147483647 || temp64 < -2147483647)
fatal("FISTPl out of range! %i\n", temp64);*/
seteal((int32_t)temp64); if (abrt) return;
x87_pop(); x87_pop();
cycles-=28; cycles-=28;
return; return;
case 5: /*FLD extended*/ case 5: /*FLD extended*/
if (fplog) pclog("FLDe %08X:%08X\n", easeg, eaaddr);
t=x87_ld80(); if (abrt) return; t=x87_ld80(); if (abrt) return;
if (fplog) pclog(" %f\n", t);
x87_push(t); x87_push(t);
cycles-=6; cycles-=6;
return; return;
case 7: /*FSTP extended*/ case 7: /*FSTP extended*/
if (fplog) pclog("FSTPe %08X:%08X\n", easeg, eaaddr);
x87_st80(ST(0)); if (abrt) return; x87_st80(ST(0)); if (abrt) return;
x87_pop(); x87_pop();
cycles-=6; cycles-=6;
@ -668,32 +782,38 @@ void x87_dc()
{ {
case 0xC0: case 0xC1: case 0xC2: case 0xC3: /*FADD*/ case 0xC0: case 0xC1: case 0xC2: case 0xC3: /*FADD*/
case 0xC4: case 0xC5: case 0xC6: case 0xC7: case 0xC4: case 0xC5: case 0xC6: case 0xC7:
if (fplog) pclog("FADD %f %f\n", ST(rmdat32 & 7), ST(0));
ST(rmdat32&7)=ST(rmdat32&7)+ST(0); ST(rmdat32&7)=ST(rmdat32&7)+ST(0);
cycles-=8; cycles-=8;
return; return;
case 0xC8: case 0xC9: case 0xCA: case 0xCB: /*FMUL*/ case 0xC8: case 0xC9: case 0xCA: case 0xCB: /*FMUL*/
case 0xCC: case 0xCD: case 0xCE: case 0xCF: case 0xCC: case 0xCD: case 0xCE: case 0xCF:
if (fplog) pclog("FMUL %f %f\n", ST(rmdat32 & 7), ST(0));
ST(rmdat32&7)=ST(rmdat32&7)*ST(0); ST(rmdat32&7)=ST(rmdat32&7)*ST(0);
cycles-=16; cycles-=16;
return; return;
case 0xE0: case 0xE1: case 0xE2: case 0xE3: /*FSUBR*/ case 0xE0: case 0xE1: case 0xE2: case 0xE3: /*FSUBR*/
case 0xE4: case 0xE5: case 0xE6: case 0xE7: case 0xE4: case 0xE5: case 0xE6: case 0xE7:
if (fplog) pclog("FSUBR %f %f\n", ST(rmdat32 & 7), ST(0));
ST(rmdat32&7)=ST(0)-ST(rmdat32&7); ST(rmdat32&7)=ST(0)-ST(rmdat32&7);
cycles-=8; cycles-=8;
return; return;
case 0xE8: case 0xE9: case 0xEA: case 0xEB: /*FSUB*/ case 0xE8: case 0xE9: case 0xEA: case 0xEB: /*FSUB*/
case 0xEC: case 0xED: case 0xEE: case 0xEF: case 0xEC: case 0xED: case 0xEE: case 0xEF:
if (fplog) pclog("FSUB %f %f\n", ST(rmdat32 & 7), ST(0));
ST(rmdat32&7)=ST(rmdat32&7)-ST(0); ST(rmdat32&7)=ST(rmdat32&7)-ST(0);
cycles-=8; cycles-=8;
return; return;
case 0xF0: case 0xF1: case 0xF2: case 0xF3: /*FDIVR*/ case 0xF0: case 0xF1: case 0xF2: case 0xF3: /*FDIVR*/
case 0xF4: case 0xF5: case 0xF6: case 0xF7: case 0xF4: case 0xF5: case 0xF6: case 0xF7:
ST(rmdat32&7)=ST(0)/ST(rmdat32&7); if (fplog) pclog("FDIVR %f %f\n", ST(rmdat32 & 7), ST(0));
x87_div(ST(rmdat32&7), ST(0), ST(rmdat32&7));
cycles-=73; cycles-=73;
return; return;
case 0xF8: case 0xF9: case 0xFA: case 0xFB: /*FDIV*/ case 0xF8: case 0xF9: case 0xFA: case 0xFB: /*FDIV*/
case 0xFC: case 0xFD: case 0xFE: case 0xFF: case 0xFC: case 0xFD: case 0xFE: case 0xFF:
ST(rmdat32&7)=ST(rmdat32&7)/ST(0); if (fplog) pclog("FDIV %f %f\n", ST(rmdat32 & 7), ST(0));
x87_div(ST(rmdat32&7), ST(rmdat32&7), ST(0));
cycles-=73; cycles-=73;
return; return;
} }
@ -706,20 +826,24 @@ void x87_dc()
switch (reg) switch (reg)
{ {
case 0: /*FADD double*/ case 0: /*FADD double*/
if (fplog) pclog("FADDd %08X:%08X %f %f\n", easeg, eaaddr, ST(0), t.d);
ST(0)+=t.d; ST(0)+=t.d;
cycles-=8; cycles-=8;
return; return;
case 1: /*FMUL double*/ case 1: /*FMUL double*/
if (fplog) pclog("FMULd %08X:%08X %f %f\n", easeg, eaaddr, ST(0), t.d);
ST(0)*=t.d; ST(0)*=t.d;
cycles-=14; cycles-=14;
return; return;
case 2: /*FCOM double*/ case 2: /*FCOM double*/
if (fplog) pclog("FCOMd %08X:%08X %f %f\n", easeg, eaaddr, ST(0), t.d);
npxs&=~(C0|C2|C3); npxs&=~(C0|C2|C3);
if (ST(0)==t.d) npxs|=C3; if (ST(0)==t.d) npxs|=C3;
else if (ST(0)<t.d) npxs|=C0; else if (ST(0)<t.d) npxs|=C0;
cycles-=4; cycles-=4;
return; return;
case 3: /*FCOMP double*/ case 3: /*FCOMP double*/
if (fplog) pclog("FCOMPd %08X:%08X %f %f\n", easeg, eaaddr, ST(0), t.d);
npxs&=~(C0|C2|C3); npxs&=~(C0|C2|C3);
if (ST(0)==t.d) npxs|=C3; if (ST(0)==t.d) npxs|=C3;
else if (ST(0)<t.d) npxs|=C0; else if (ST(0)<t.d) npxs|=C0;
@ -727,19 +851,23 @@ void x87_dc()
x87_pop(); x87_pop();
return; return;
case 4: /*FSUB double*/ case 4: /*FSUB double*/
if (fplog) pclog("FSUBd %08X:%08X %f %f\n", easeg, eaaddr, ST(0), t.d);
ST(0)-=t.d; ST(0)-=t.d;
cycles-=8; cycles-=8;
return; return;
case 5: /*FSUBR double*/ case 5: /*FSUBR double*/
if (fplog) pclog("FSUBRd %08X:%08X %f %f\n", easeg, eaaddr, ST(0), t.d);
ST(0)=t.d-ST(0); ST(0)=t.d-ST(0);
cycles-=8; cycles-=8;
return; return;
case 6: /*FDIV double*/ case 6: /*FDIV double*/
ST(0)=ST(0)/t.d; if (fplog) pclog("FDIVd %08X:%08X %f %f\n", easeg, eaaddr, ST(0), t.d);
x87_div(ST(0), ST(0), t.d);
cycles-=73; cycles-=73;
return; return;
case 7: /*FDIVR double*/ case 7: /*FDIVR double*/
ST(0)=t.d/ST(0); if (fplog) pclog("FDIVRd %08X:%08X %f %f\n", easeg, eaaddr, ST(0), t.d);
x87_div(ST(0), t.d, ST(0));
cycles-=73; cycles-=73;
return; return;
} }
@ -760,10 +888,12 @@ void x87_dd()
switch (reg) switch (reg)
{ {
case 0: /*FFREE*/ case 0: /*FFREE*/
if (fplog) pclog("FFREE\n");
tag|=(3<<((rmdat32&7)<<1)); tag|=(3<<((rmdat32&7)<<1));
cycles-=3; cycles-=3;
return; return;
case 2: /*FST*/ case 2: /*FST*/
if (fplog) pclog("FST\n");
ST(rmdat32&7)=ST(0); ST(rmdat32&7)=ST(0);
temp=(tag>>((TOP&7)<<1))&3; temp=(tag>>((TOP&7)<<1))&3;
tag&=~(3<<((rmdat32&7)<<1)); tag&=~(3<<((rmdat32&7)<<1));
@ -771,6 +901,7 @@ void x87_dd()
cycles-=3; cycles-=3;
return; return;
case 3: /*FSTP*/ case 3: /*FSTP*/
if (fplog) pclog("FSTP\n");
ST(rmdat32&7)=ST(0); ST(rmdat32&7)=ST(0);
temp=(tag>>((TOP&7)<<1))&3; temp=(tag>>((TOP&7)<<1))&3;
tag&=~(3<<((rmdat32&7)<<1)); tag&=~(3<<((rmdat32&7)<<1));
@ -779,12 +910,14 @@ void x87_dd()
cycles-=3; cycles-=3;
return; return;
case 4: /*FUCOM*/ case 4: /*FUCOM*/
if (fplog) pclog("FUCOM\n");
npxs&=~(C0|C2|C3); npxs&=~(C0|C2|C3);
if (ST(0)==ST(rmdat32&7)) npxs|=C3; if (ST(0)==ST(rmdat32&7)) npxs|=C3;
else if (ST(0)<ST(rmdat32&7)) npxs|=C0; else if (ST(0)<ST(rmdat32&7)) npxs|=C0;
cycles-=4; cycles-=4;
return; return;
case 5: /*FUCOMP*/ case 5: /*FUCOMP*/
if (fplog) pclog("FUCOMP\n");
npxs&=~(C0|C2|C3); npxs&=~(C0|C2|C3);
if (ST(0)==ST(rmdat32&7)) npxs|=C3; if (ST(0)==ST(rmdat32&7)) npxs|=C3;
else if (ST(0)<ST(rmdat32&7)) npxs|=C0; else if (ST(0)<ST(rmdat32&7)) npxs|=C0;
@ -798,18 +931,22 @@ void x87_dd()
switch (reg) switch (reg)
{ {
case 0: /*FLD double-precision*/ case 0: /*FLD double-precision*/
if (fplog) pclog("FLDd %08X:%08X\n", easeg, eaaddr);
t.i=readmeml(easeg,eaaddr); t.i=readmeml(easeg,eaaddr);
t.i|=(uint64_t)readmeml(easeg,eaaddr+4)<<32; if (abrt) return; t.i|=(uint64_t)readmeml(easeg,eaaddr+4)<<32; if (abrt) return;
if (fplog) pclog(" %f\n", t.d);
x87_push(t.d); x87_push(t.d);
cycles-=3; cycles-=3;
return; return;
case 2: /*FST double-precision*/ case 2: /*FST double-precision*/
if (fplog) pclog("FSTd %08X:%08X\n", easeg, eaaddr);
t.d=ST(0); t.d=ST(0);
writememl(easeg,eaaddr,t.i); writememl(easeg,eaaddr,t.i);
writememl(easeg,eaaddr+4,(t.i>>32)); writememl(easeg,eaaddr+4,(t.i>>32));
cycles-=8; cycles-=8;
return; return;
case 3: /*FSTP double-precision*/ case 3: /*FSTP double-precision*/
if (fplog) pclog("FSTPd %08X:%08X\n", easeg, eaaddr);
t.d=ST(0); t.d=ST(0);
writememl(easeg,eaaddr,t.i); writememl(easeg,eaaddr,t.i);
writememl(easeg,eaaddr+4,(t.i>>32)); if (abrt) return; writememl(easeg,eaaddr+4,(t.i>>32)); if (abrt) return;
@ -817,6 +954,7 @@ void x87_dd()
cycles-=8; cycles-=8;
return; return;
case 4: /*FRSTOR*/ case 4: /*FRSTOR*/
if (fplog) pclog("FRSTOR %08X:%08X\n", easeg, eaaddr);
switch ((cr0&1)|(op32&0x100)) switch ((cr0&1)|(op32&0x100))
{ {
case 0x000: /*16-bit real mode*/ case 0x000: /*16-bit real mode*/
@ -847,6 +985,7 @@ void x87_dd()
cycles-=(cr0&1)?34:44; cycles-=(cr0&1)?34:44;
return; return;
case 6: /*FSAVE*/ case 6: /*FSAVE*/
if (fplog) pclog("FSAVE %08X:%08X\n", easeg, eaaddr);
switch ((cr0&1)|(op32&0x100)) switch ((cr0&1)|(op32&0x100))
{ {
case 0x000: /*16-bit real mode*/ case 0x000: /*16-bit real mode*/
@ -922,6 +1061,7 @@ void x87_dd()
cycles-=(cr0&1)?56:67; cycles-=(cr0&1)?56:67;
return; return;
case 7: /*FSTSW*/ case 7: /*FSTSW*/
if (fplog) pclog("FSTSW %08X:%08X\n", easeg, eaaddr);
seteaw((npxs&0xC7FF)|(TOP<<11)); seteaw((npxs&0xC7FF)|(TOP<<11));
cycles-=3; cycles-=3;
return; return;
@ -932,7 +1072,6 @@ void x87_dd()
} }
void x87_de() void x87_de()
{ {
double t;
int32_t templ; int32_t templ;
if (mod==3) if (mod==3)
{ {
@ -940,17 +1079,20 @@ void x87_de()
{ {
case 0xC0: case 0xC1: case 0xC2: case 0xC3: /*FADDP*/ case 0xC0: case 0xC1: case 0xC2: case 0xC3: /*FADDP*/
case 0xC4: case 0xC5: case 0xC6: case 0xC7: case 0xC4: case 0xC5: case 0xC6: case 0xC7:
ST(rmdat32&7)=ST(rmdat32&7)+ST[TOP]; if (fplog) pclog("FADDP %f %f\n", ST(rmdat32 & 7), ST(0));
ST(rmdat32&7)=ST(rmdat32&7)+ST(0);
x87_pop(); x87_pop();
cycles-=8; cycles-=8;
return; return;
case 0xC8: case 0xC9: case 0xCA: case 0xCB: /*FMULP*/ case 0xC8: case 0xC9: case 0xCA: case 0xCB: /*FMULP*/
case 0xCC: case 0xCD: case 0xCE: case 0xCF: case 0xCC: case 0xCD: case 0xCE: case 0xCF:
ST(rmdat32&7)=ST(rmdat32&7)*ST[TOP]; if (fplog) pclog("FMULP %f %f\n", ST(rmdat32 & 7), ST(0));
ST(rmdat32&7)=ST(rmdat32&7)*ST(0);
x87_pop(); x87_pop();
cycles-=16; cycles-=16;
return; return;
case 0xD9: /*FCOMPP*/ case 0xD9: /*FCOMPP*/
if (fplog) pclog("FCOMPP %f %f\n", ST(0), ST(1));
npxs&=~(C0|C2|C3); npxs&=~(C0|C2|C3);
if (ST(0)==ST(1)) npxs|=C3; if (ST(0)==ST(1)) npxs|=C3;
else if (ST(0)<ST(1)) npxs|=C0; else if (ST(0)<ST(1)) npxs|=C0;
@ -960,25 +1102,29 @@ void x87_de()
return; return;
case 0xE0: case 0xE1: case 0xE2: case 0xE3: /*FSUBRP*/ case 0xE0: case 0xE1: case 0xE2: case 0xE3: /*FSUBRP*/
case 0xE4: case 0xE5: case 0xE6: case 0xE7: case 0xE4: case 0xE5: case 0xE6: case 0xE7:
if (fplog) pclog("FSUBRP %f %f\n", ST(rmdat32 & 7), ST(0));
ST(rmdat32&7)=ST(0)-ST(rmdat32&7); ST(rmdat32&7)=ST(0)-ST(rmdat32&7);
x87_pop(); x87_pop();
cycles-=8; cycles-=8;
return; return;
case 0xE8: case 0xE9: case 0xEA: case 0xEB: /*FSUBP*/ case 0xE8: case 0xE9: case 0xEA: case 0xEB: /*FSUBP*/
case 0xEC: case 0xED: case 0xEE: case 0xEF: case 0xEC: case 0xED: case 0xEE: case 0xEF:
ST(rmdat32&7)=ST(rmdat32&7)-ST[TOP]; if (fplog) pclog("FSUBP %f %f\n", ST(rmdat32 & 7), ST(0));
ST(rmdat32&7)=ST(rmdat32&7)-ST(0);
x87_pop(); x87_pop();
cycles-=8; cycles-=8;
return; return;
case 0xF0: case 0xF1: case 0xF2: case 0xF3: /*FDIVRP*/ case 0xF0: case 0xF1: case 0xF2: case 0xF3: /*FDIVRP*/
case 0xF4: case 0xF5: case 0xF6: case 0xF7: case 0xF4: case 0xF5: case 0xF6: case 0xF7:
ST(rmdat32&7)=ST(0)/ST(rmdat32&7); if (fplog) pclog("FDIVRP %f %f\n", ST(rmdat32 & 7), ST(0));
x87_div(ST(rmdat32&7), ST(0), ST(rmdat32&7));
x87_pop(); x87_pop();
cycles-=73; cycles-=73;
return; return;
case 0xF8: case 0xF9: case 0xFA: case 0xFB: /*FDIVP*/ case 0xF8: case 0xF9: case 0xFA: case 0xFB: /*FDIVP*/
case 0xFC: case 0xFD: case 0xFE: case 0xFF: case 0xFC: case 0xFD: case 0xFE: case 0xFF:
ST(rmdat32&7)=ST(rmdat32&7)/ST[TOP]; if (fplog) pclog("FDIVP %f %f %i\n", ST(rmdat32 & 7), ST(0), rmdat32 & 7);
x87_div(ST(rmdat32&7), ST(rmdat32&7), ST(0));
x87_pop(); x87_pop();
cycles-=73; cycles-=73;
return; return;
@ -986,24 +1132,28 @@ void x87_de()
} }
else else
{ {
templ=(int32_t)geteaw(); if (abrt) return; templ=(int32_t)(int16_t)geteaw(); if (abrt) return;
switch (reg) switch (reg)
{ {
case 0: /*FIADD*/ case 0: /*FIADD*/
if (fplog) pclog("FIADDw %08X:%08X %f %f\n", easeg, eaaddr, ST(0), (double)templ);
ST(0)=ST(0)+(double)templ; ST(0)=ST(0)+(double)templ;
cycles-=20; cycles-=20;
return; return;
case 1: /*FIMUL*/ case 1: /*FIMUL*/
if (fplog) pclog("FIMULw %08X:%08X %f %f\n", easeg, eaaddr, ST(0), (double)templ);
ST(0)=ST(0)*(double)templ; ST(0)=ST(0)*(double)templ;
cycles-=22; cycles-=22;
return; return;
case 2: /*FICOM*/ case 2: /*FICOM*/
if (fplog) pclog("FICOMw %08X:%08X %f %f\n", easeg, eaaddr, ST(0), (double)templ);
npxs&=~(C0|C2|C3); npxs&=~(C0|C2|C3);
if (ST(0)==(double)templ) npxs|=C3; if (ST(0)==(double)templ) npxs|=C3;
else if (ST(0)<(double)templ) npxs|=C0; else if (ST(0)<(double)templ) npxs|=C0;
cycles-=15; cycles-=15;
return; return;
case 3: /*FICOMP*/ case 3: /*FICOMP*/
if (fplog) pclog("FICOMPw %08X:%08X %f %f\n", easeg, eaaddr, ST(0), (double)templ);
npxs&=~(C0|C2|C3); npxs&=~(C0|C2|C3);
if (ST(0)==(double)templ) npxs|=C3; if (ST(0)==(double)templ) npxs|=C3;
else if (ST(0)<(double)templ) npxs|=C0; else if (ST(0)<(double)templ) npxs|=C0;
@ -1011,19 +1161,23 @@ void x87_de()
cycles-=15; cycles-=15;
return; return;
case 4: /*FISUB*/ case 4: /*FISUB*/
if (fplog) pclog("FISUBw %08X:%08X %f %f\n", easeg, eaaddr, ST(0), (double)templ);
ST(0)=ST(0)-(double)templ; ST(0)=ST(0)-(double)templ;
cycles-=20; cycles-=20;
return; return;
case 5: /*FISUBR*/ case 5: /*FISUBR*/
if (fplog) pclog("FISUBRw %08X:%08X %f %f\n", easeg, eaaddr, ST(0), (double)templ);
ST(0)=(double)templ-ST(0); ST(0)=(double)templ-ST(0);
cycles-=19; cycles-=19;
return; return;
case 6: /*FIDIV*/ case 6: /*FIDIV*/
ST(0)=ST(0)/(double)templ; if (fplog) pclog("FIDIVw %08X:%08X %f %f\n", easeg, eaaddr, ST(0), (double)templ);
x87_div(ST(0), ST(0), (double)templ);
cycles-=84; cycles-=84;
return; return;
case 7: /*FIDIVR*/ case 7: /*FIDIVR*/
ST(0)=(double)templ/ST(0); if (fplog) pclog("FIDIVRw %08X:%08X %f %f\n", easeg, eaaddr, ST(0), (double)templ);
x87_div(ST(0), (double)templ, ST(0));
cycles-=84; cycles-=84;
return; return;
} }
@ -1046,6 +1200,7 @@ void x87_df()
switch (rmdat32&0xFF) switch (rmdat32&0xFF)
{ {
case 0xE0: /*FSTSW AX*/ case 0xE0: /*FSTSW AX*/
if (fplog) pclog("FSTSW\n");
AX=npxs; AX=npxs;
cycles-=3; cycles-=3;
return; return;
@ -1058,29 +1213,42 @@ void x87_df()
switch (reg) switch (reg)
{ {
case 0: /*FILD short*/ case 0: /*FILD short*/
if (fplog) pclog("FILDw %08X:%08X\n", easeg, eaaddr);
temp16=geteaw(); if (abrt) return; temp16=geteaw(); if (abrt) return;
if (fplog) pclog(" %f\n", (double)temp16);
x87_push((double)temp16); x87_push((double)temp16);
cycles-=13; cycles-=13;
return; return;
case 2: /*FIST word*/ case 2: /*FIST word*/
temp16=x87_fround(ST(0)); if (fplog) pclog("FISTw %08X:%08X\n", easeg, eaaddr);
seteaw(temp16); temp64 = x87_fround(ST(0));
/* if (temp64 > 32767 || temp64 < -32768)
fatal("FISTw overflow %i\n", temp64);*/
seteaw((int16_t)temp64);
cycles-=29; cycles-=29;
return; return;
case 3: /*FISTP word*/ case 3: /*FISTP word*/
temp16=x87_fround(ST(0)); if (fplog) pclog("FISTPw %08X:%08X\n", easeg, eaaddr);
seteaw(temp16); if (abrt) return; temp64 = x87_fround(ST(0));
/* if (temp64 > 32767 || temp64 < -32768)
fatal("FISTw overflow %i\n", temp64);*/
seteaw((int16_t)temp64); if (abrt) return;
x87_pop(); x87_pop();
cycles-=29; cycles-=29;
return; return;
case 5: /*FILD long*/ case 5: /*FILD long*/
if (fplog) pclog("FILDl %08X:%08X\n", easeg, eaaddr);
temp64=geteal(); if (abrt) return; temp64=geteal(); if (abrt) return;
temp64|=(uint64_t)readmeml(easeg,eaaddr+4)<<32; temp64|=(uint64_t)readmeml(easeg,eaaddr+4)<<32;
if (fplog) pclog(" %f %08X %08X\n", (double)temp64, readmeml(easeg,eaaddr), readmeml(easeg,eaaddr+4));
x87_push((double)temp64); x87_push((double)temp64);
cycles-=10; cycles-=10;
return; return;
case 6: /*FBSTP*/ case 6: /*FBSTP*/
if (fplog) pclog("FBSTP %08X:%08X\n", easeg, eaaddr);
tempd=ST(0); tempd=ST(0);
if (tempd < 0.0)
tempd = -tempd;
for (c=0;c<9;c++) for (c=0;c<9;c++)
{ {
tempc=(uint8_t)floor(fmod(tempd,10.0)); tempd-=floor(fmod(tempd,10.0)); tempd/=10.0; tempc=(uint8_t)floor(fmod(tempd,10.0)); tempd-=floor(fmod(tempd,10.0)); tempd/=10.0;
@ -1088,11 +1256,12 @@ void x87_df()
writememb(easeg,eaaddr+c,tempc); writememb(easeg,eaaddr+c,tempc);
} }
tempc=(uint8_t)floor(fmod(tempd,10.0)); tempc=(uint8_t)floor(fmod(tempd,10.0));
if (tempd<0.0) tempc|=0x80; if (ST(0)<0.0) tempc|=0x80;
writememb(easeg,eaaddr+9,tempc); if (abrt) return; writememb(easeg,eaaddr+9,tempc); if (abrt) return;
x87_pop(); x87_pop();
return; return;
case 7: /*FISTP long*/ case 7: /*FISTP long*/
if (fplog) pclog("FISTPl %08X:%08X\n", easeg, eaaddr);
temp64=x87_fround(ST(0)); temp64=x87_fround(ST(0));
seteal(temp64); seteal(temp64);
writememl(easeg,eaaddr+4,temp64>>32); if (abrt) return; writememl(easeg,eaaddr+4,temp64>>32); if (abrt) return;

View file

@ -1,10 +1,12 @@
#include "ibm.h" #include "ibm.h"
#include "xtide.h"
#include "io.h"
#include "ide.h" #include "ide.h"
#include "xtide.h"
uint8_t xtide_high; uint8_t xtide_high;
void xtide_write(uint16_t port, uint8_t val) void xtide_write(uint16_t port, uint8_t val, void *priv)
{ {
switch (port & 0xf) switch (port & 0xf)
{ {
@ -27,7 +29,7 @@ void xtide_write(uint16_t port, uint8_t val)
} }
} }
uint8_t xtide_read(uint16_t port) uint8_t xtide_read(uint16_t port, void *priv)
{ {
uint16_t tempw; uint16_t tempw;
switch (port & 0xf) switch (port & 0xf)
@ -51,5 +53,6 @@ uint8_t xtide_read(uint16_t port)
void xtide_init() void xtide_init()
{ {
io_sethandler(0x0300, 0x0010, xtide_read, NULL, NULL, xtide_write, NULL, NULL); ide_init();
io_sethandler(0x0300, 0x0010, xtide_read, NULL, NULL, xtide_write, NULL, NULL, NULL);
} }