Add emulation of IBM PS/1 Model 2121.

As part of this :
- FDC Specify command now completes immediately
- Implemented keyboard system flag status
- Added ability to remap 384kb reserved memory to above extended memory
This commit is contained in:
SarahW
2016-05-02 20:06:49 +01:00
parent f6a4c54741
commit 0724cfcae4
20 changed files with 461 additions and 26 deletions

BIN
nvr/ibmps1_2121.nvr Normal file

Binary file not shown.

View File

@@ -261,6 +261,14 @@ deskpro386\109592-005.U11.bin
deskpro386\109591-005.U13.bin
IBM PS/1 Model 2121 (1990)
This is a 386SX with integrated VGA.
ROM files needed:
ibmps1_2121\fc0000.bin
Acermate 386SX/25N (1992?)
An integrated 386SX clone, with onboard Oak SVGA and IO.

View File

@@ -29,7 +29,7 @@ sound_speaker.c sound_ssi2001.c sound_wss.c sound_ym7128.c soundopenal.c tandy_e
timer.c um8669f.c um8881f.c vid_ati_eeprom.c vid_ati_mach64.c vid_ati18800.c vid_ati28800.c \
vid_ati68860_ramdac.c vid_cga.c vid_cl5429.c vid_ega.c vid_et4000.c vid_et4000w32.c vid_hercules.c \
vid_icd2061.c vid_ics2595.c vid_incolor.c vid_mda.c vid_olivetti_m24.c vid_oti067.c vid_paradise.c vid_pc200.c \
vid_pc1512.c vid_pc1640.c vid_pcjr.c vid_s3.c vid_s3_virge.c vid_sdac_ramdac.c \
vid_pc1512.c vid_pc1640.c vid_pcjr.c vid_ps1_svga.c vid_s3.c vid_s3_virge.c vid_sdac_ramdac.c \
vid_stg_ramdac.c vid_svga.c vid_svga_render.c vid_tandy.c vid_tandysl.c vid_tgui9440.c \
vid_tkd8001_ramdac.c vid_tvga.c vid_unk_ramdac.c vid_vga.c vid_voodoo.c video.c wd76c10.c \
x86seg.c x87.c xtide.c sound_dbopl.cc sound_resid.cc dosbox/dbopl.cpp \

View File

@@ -16,7 +16,7 @@ OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o ali1429.o amstrad
vid_ati28800.o vid_ati68860_ramdac.o vid_cga.o vid_cl5429.o vid_ega.o vid_et4000.o \
vid_et4000w32.o vid_et4000w32i.o vid_hercules.o vid_icd2061.o vid_ics2595.o vid_incolor.o vid_mda.o \
vid_olivetti_m24.o vid_oti067.o vid_paradise.o vid_pc1512.o vid_pc1640.o vid_pc200.o \
vid_pcjr.o vid_s3.o vid_s3_virge.o vid_sdac_ramdac.o vid_stg_ramdac.o vid_svga.o \
vid_pcjr.o vid_ps1_svga.o vid_s3.o vid_s3_virge.o vid_sdac_ramdac.o vid_stg_ramdac.o vid_svga.o \
vid_svga_render.o vid_tandy.o vid_tandysl.o vid_tgui9440.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-config.o win-d3d.o win-d3d-fs.o win-ddraw.o \
win-ddraw-fs.o win-deviceconfig.o win-hdconf.o win-joystick.o win-keyboard.o win-midi.o win-mouse.o \

View File

@@ -16,7 +16,7 @@ OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o ali1429.o amstrad
vid_ati28800.o vid_ati68860_ramdac.o vid_cga.o vid_cl5429.o vid_ega.o vid_et4000.o \
vid_et4000w32.o vid_et4000w32i.o vid_hercules.o vid_icd2061.o vid_ics2595.o vid_incolor.o vid_mda.o \
vid_olivetti_m24.o vid_oti067.o vid_paradise.o vid_pc1512.o vid_pc1640.o vid_pc200.o \
vid_pcjr.o vid_s3.o vid_s3_virge.o vid_sdac_ramdac.o vid_stg_ramdac.o vid_svga.o \
vid_pcjr.o vid_ps1_svga.o vid_s3.o vid_s3_virge.o vid_sdac_ramdac.o vid_stg_ramdac.o vid_svga.o \
vid_svga_render.o vid_tandy.o vid_tandysl.o vid_tgui9440.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-config.o win-d3d.o win-d3d-fs.o win-ddraw.o \
win-ddraw-fs.o win-deviceconfig.o win-hdconf.o win-joystick.o win-keyboard.o win-midi.o win-mouse.o \

View File

@@ -34,7 +34,7 @@ typedef struct FDC
int tc;
int written;
int pcjr;
int pcjr, ps1;
int watchdog_timer;
int watchdog_count;
@@ -574,6 +574,14 @@ bad_command:
fdc.inread = 1;
break;
case 3: /*Specify*/
fdc.stat=0x80;
fdc.specify[0] = fdc.params[0];
fdc.specify[1] = fdc.params[1];
fdc.dma = (fdc.specify[1] & 1) ^ 1;
disctime = 0;
break;
case 5: /*Write data*/
fdc_rate(fdc.drive);
fdc.head=fdc.params[2];
@@ -675,7 +683,21 @@ uint8_t fdc_read(uint16_t addr, void *priv)
temp &= ~0x20;
break;
case 3:
if (!fdc.enh_mode)
drive = (fdc.dor & 1) ^ fdd_swap;
if (fdc.ps1)
{
/*PS/1 Model 2121 seems return drive type in port 0x3f3,
despite the 82077AA FDC not implementing this. This is
presumably implemented outside the FDC on one of the
motherboard's support chips.*/
if (fdd_is_525(drive))
temp = 0x20;
else if (fdd_is_ed(drive))
temp = 0x10;
else
temp = 0x00;
}
else if (!fdc.enh_mode)
temp = 0x20;
else
{
@@ -800,12 +822,6 @@ void fdc_callback()
disc_readsector(fdc.drive, SECTOR_NEXT, fdc.track[fdc.drive], fdc.head, fdc.rate, fdc.params[4]);
fdc.inread = 1;
return;
case 3: /*Specify*/
fdc.stat=0x80;
fdc.specify[0] = fdc.params[0];
fdc.specify[1] = fdc.params[1];
fdc.dma = (fdc.specify[1] & 1) ^ 1;
return;
case 4: /*Sense drive status*/
fdc.res[10] = (fdc.params[0] & 7) | 0x28;
if (fdd_track0(fdc.drive))
@@ -1330,6 +1346,7 @@ 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);
fdc.pcjr = 0;
fdc.ps1 = 0;
}
void fdc_add_pcjr()
@@ -1337,6 +1354,7 @@ void fdc_add_pcjr()
io_sethandler(0x00f0, 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL);
timer_add(fdc_watchdog_poll, &fdc.watchdog_timer, &fdc.watchdog_timer, &fdc);
fdc.pcjr = 1;
fdc.ps1 = 0;
}
void fdc_remove()
@@ -1360,3 +1378,8 @@ void fdc_3f1_enable(int enable)
{
fdc.enable_3f1 = enable;
}
void fdc_set_ps1()
{
fdc.ps1 = 1;
}

View File

@@ -9,6 +9,7 @@ void fdc_abort();
void fdc_discchange_clear(int drive);
void fdc_set_dskchg_activelow();
void fdc_3f1_enable(int enable);
void fdc_set_ps1();
int fdc_get_bitcell_period();
/* A few functions to communicate between Super I/O chips and the FDC. */

View File

@@ -181,3 +181,13 @@ int fdd_get_type(int drive)
{
return fdd[drive].type;
}
int fdd_is_525(int drive)
{
return drive_types[fdd[drive].type].flags & FLAG_525;
}
int fdd_is_ed(int drive)
{
return drive_types[fdd[drive].type].flags & FLAG_HOLE2;
}

View File

@@ -5,6 +5,8 @@ int fdd_getrpm(int drive);
void fdd_set_densel(int densel);
int fdd_can_read_medium(int drive);
int fdd_doublestep_40(int drive);
int fdd_is_525(int drive);
int fdd_is_ed(int drive);
void fdd_set_type(int drive, int type);
int fdd_get_type(int drive);

View File

@@ -333,7 +333,8 @@ enum
ROM_REVENGE,
ROM_IBMPS1_2011,
ROM_DESKPRO_386,
ROM_IBMPS1_2121,
ROM_MAX
};

View File

@@ -449,7 +449,9 @@ uint8_t keyboard_at_read(uint16_t port, void *priv)
return ppi.pb&~0xe0;
case 0x64:
temp = keyboard_at.status;
temp = keyboard_at.status & ~4;
if (keyboard_at.mem[0] & 0x04)
temp |= 0x04;
keyboard_at.status &= ~(STAT_RTIMEOUT/* | STAT_TTIMEOUT*/);
break;
}

View File

@@ -38,6 +38,7 @@ static mem_mapping_t base_mapping;
mem_mapping_t ram_low_mapping;
static mem_mapping_t ram_high_mapping;
static mem_mapping_t ram_mid_mapping;
static mem_mapping_t ram_remapped_mapping;
mem_mapping_t bios_mapping[8];
static mem_mapping_t bios_high_mapping[8];
static mem_mapping_t romext_mapping;
@@ -522,6 +523,15 @@ int loadbios()
mem_load_atide115_bios();
return 1;
case ROM_IBMPS1_2121:
f = romfopen("roms/ibmps1_2121/fc0000.bin", "rb");
if (!f) break;
fseek(f, 0x20000, SEEK_SET);
fread(rom, 0x20000, 1, f);
fclose(f);
biosmask = 0x1ffff;
return 1;
case ROM_DESKPRO_386:
f=romfopen("roms/deskpro386/109592-005.U11.bin","rb");
ff=romfopen("roms/deskpro386/109591-005.U13.bin","rb");
@@ -1791,18 +1801,18 @@ void mem_init()
{
int c;
ram = malloc(mem_size * 1024);
ram = malloc((mem_size + 384) * 1024);
rom = malloc(0x20000);
vram = malloc(0x800000);
readlookup2 = malloc(1024 * 1024 * sizeof(uintptr_t));
writelookup2 = malloc(1024 * 1024 * sizeof(uintptr_t));
cachelookup2 = malloc(1024 * 1024);
biosmask = 0xffff;
pages = malloc(((mem_size * 1024) >> 12) * sizeof(page_t));
pages = malloc((((mem_size + 384) * 1024) >> 12) * sizeof(page_t));
page_lookup = malloc((1 << 20) * sizeof(page_t *));
memset(ram, 0, mem_size * 1024);
memset(pages, 0, ((mem_size * 1024) >> 12) * sizeof(page_t));
memset(ram, 0, (mem_size + 384) * 1024);
memset(pages, 0, (((mem_size + 384) * 1024) >> 12) * sizeof(page_t));
memset(page_lookup, 0, (1 << 20) * sizeof(page_t *));
@@ -1850,18 +1860,41 @@ void mem_init()
// pclog("Mem resize %i %i\n",mem_size,c);
}
void mem_remap_top_384k()
{
int c;
for (c = ((mem_size * 1024) >> 12); c < (((mem_size + 384) * 1024) >> 12); c++)
{
pages[c].mem = &ram[c << 12];
pages[c].write_b = mem_write_ramb_page;
pages[c].write_w = mem_write_ramw_page;
pages[c].write_l = mem_write_raml_page;
}
for (c = (mem_size / 256); c < ((mem_size + 384) / 256); c++)
{
isram[c] = 1;
if (c >= 0xa && c <= 0xf)
isram[c] = 0;
}
mem_set_mem_state(mem_size * 1024, 384 * 1024, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
mem_mapping_add(&ram_remapped_mapping, mem_size * 1024, 384 * 1024, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram + (mem_size * 1024), MEM_MAPPING_INTERNAL, NULL);
}
void mem_resize()
{
int c;
free(ram);
ram = malloc(mem_size * 1024);
memset(ram, 0, mem_size * 1024);
ram = malloc((mem_size + 384) * 1024);
memset(ram, 0, (mem_size + 384) * 1024);
free(pages);
pages = malloc(((mem_size * 1024) >> 12) * sizeof(page_t));
memset(pages, 0, ((mem_size * 1024) >> 12) * sizeof(page_t));
for (c = 0; c < ((mem_size * 1024) >> 12); c++)
pages = malloc((((mem_size + 384) * 1024) >> 12) * sizeof(page_t));
memset(pages, 0, (((mem_size + 384) * 1024) >> 12) * sizeof(page_t));
for (c = 0; c < (((mem_size + 384) * 1024) >> 12); c++)
{
pages[c].mem = &ram[c << 12];
pages[c].write_b = mem_write_ramb_page;

View File

@@ -163,4 +163,6 @@ void mem_reset_page_blocks();
extern mem_mapping_t ram_low_mapping;
void mem_remap_top_384k();
#endif

View File

@@ -59,7 +59,8 @@ void europc_init();
void olim24_init();
void at_init();
void deskpro386_init();
void ps1_init();
void ps1_m2011_init();
void ps1_m2121_init();
void at_neat_init();
void at_scat_init();
void at_acer386sx_init();
@@ -103,7 +104,8 @@ MODEL models[] =
{"AMI 286 clone", ROM_AMI286, { "", cpus_286, "", NULL, "", NULL}, 0, 1, 1, 16, 1, at_neat_init},
{"Award 286 clone", ROM_AWARD286, { "", cpus_286, "", NULL, "", NULL}, 0, 1, 1, 16, 1, at_scat_init},
{"DELL System 200", ROM_DELL200, { "", cpus_286, "", NULL, "", NULL}, 0, 1, 1, 16, 1, at_init},
{"IBM PS/1 model 2011", ROM_IBMPS1_2011, { "", cpus_ps1_m2011,"", NULL, "", NULL}, 1, 1, 1, 16, 1, ps1_init},
{"IBM PS/1 model 2011", ROM_IBMPS1_2011, { "", cpus_ps1_m2011,"", NULL, "", NULL}, 1, 1, 1, 16, 1, ps1_m2011_init},
{"IBM PS/1 model 2121", ROM_IBMPS1_2121, { "Intel", cpus_i386, "", NULL, "", NULL}, 1, 1, 1, 16, 1, ps1_m2121_init},
{"Compaq Deskpro 386", ROM_DESKPRO_386, { "Intel", cpus_i386, "AMD", cpus_Am386, "Cyrix", cpus_486SDLC}, 0, 1, 1, 15, 1, deskpro386_init},
{"Acer 386SX25/N", ROM_ACER386, { "Intel", cpus_acer, "", NULL, "", NULL}, 1, 1, 1, 16, 1, at_acer386sx_init},
{"DTK 386SX clone", ROM_DTK386, { "Intel", cpus_i386, "AMD", cpus_Am386, "Cyrix", cpus_486SDLC}, 0, 1, 1, 16, 1, at_neat_init},
@@ -278,7 +280,7 @@ void deskpro386_init()
compaq_init();
}
void ps1_init()
void ps1_common_init()
{
AT = 1;
common_init();
@@ -290,13 +292,25 @@ void ps1_init()
mouse_ps2_init();
nvr_init();
pic2_init();
ps1mb_init();
fdc_set_dskchg_activelow();
device_add(&ps1_audio_device);
/*PS/1 audio uses ports 200h and 202-207h, so only initialise gameport on 201h*/
device_add(&gameport_201_device);
}
void ps1_m2011_init()
{
ps1_common_init();
ps1mb_init();
}
void ps1_m2121_init()
{
ps1_common_init();
ps1mb_m2121_init();
fdc_set_ps1();
}
void at_neat_init()
{
at_init();

View File

@@ -137,6 +137,7 @@ void loadnvr()
case ROM_PC3086: f = romfopen("nvr/pc3086.nvr", "rb"); break;
case ROM_IBMAT: f = romfopen("nvr/at.nvr", "rb"); break;
case ROM_IBMPS1_2011: f = romfopen("nvr/ibmps1_2011.nvr", "rb"); /*nvrmask = 127; */break;
case ROM_IBMPS1_2121: f = romfopen("nvr/ibmps1_2121.nvr", "rb"); nvrmask = 127; break;
case ROM_CMDPC30: f = romfopen("nvr/cmdpc30.nvr", "rb"); nvrmask = 127; break;
case ROM_AMI286: f = romfopen("nvr/ami286.nvr", "rb"); nvrmask = 127; break;
case ROM_AWARD286: f = romfopen("nvr/award286.nvr", "rb"); nvrmask = 127; break;
@@ -181,6 +182,7 @@ void savenvr()
case ROM_PC3086: f = romfopen("nvr/pc3086.nvr", "wb"); break;
case ROM_IBMAT: f = romfopen("nvr/at.nvr", "wb"); break;
case ROM_IBMPS1_2011: f = romfopen("nvr/ibmps1_2011.nvr", "wb"); break;
case ROM_IBMPS1_2121: f = romfopen("nvr/ibmps1_2121.nvr", "wb"); break;
case ROM_CMDPC30: f = romfopen("nvr/cmdpc30.nvr", "wb"); break;
case ROM_AMI286: f = romfopen("nvr/ami286.nvr", "wb"); break;
case ROM_AWARD286: f = romfopen("nvr/award286.nvr", "wb"); break;

143
src/ps1.c
View File

@@ -6,6 +6,8 @@
static rom_t ps1_high_rom;
static uint8_t ps1_92, ps1_94, ps1_102, ps1_103, ps1_104, ps1_105, ps1_190;
static int ps1_e0_addr;
static uint8_t ps1_e0_regs[256];
static struct
{
@@ -150,3 +152,144 @@ void ps1mb_init()
memset(&ps1_hd, 0, sizeof(ps1_hd));
}
/*PS/1 Model 2121.
This is similar to the model 2011 but some of the functionality has moved to a
chip at ports 0xe0 (index)/0xe1 (data). The only functions I have identified
are enables for the first 512kb and next 128kb of RAM, in bits 0 of registers
0 and 1 respectively.
Port 0x105 has bit 7 forced high. Without this 128kb of memory will be missed
by the BIOS on cold boots.
The reserved 384kb is remapped to the top of extended memory. If this is not
done then you get an error on startup.
*/
static uint8_t ps1_m2121_read(uint16_t port, void *p)
{
uint8_t temp;
switch (port)
{
case 0x91:
return 0;
case 0x92:
return ps1_92;
case 0x94:
return ps1_94;
case 0xe1:
return ps1_e0_regs[ps1_e0_addr];
case 0x102:
return ps1_102;
case 0x103:
return ps1_103;
case 0x104:
return ps1_104;
case 0x105:
return ps1_105 | 0x80;
case 0x190:
return ps1_190;
default:
temp = 0xff;
break;
}
return temp;
}
static void ps1_m2121_recalc_memory()
{
/*Enable first 512kb*/
mem_set_mem_state(0x00000, 0x80000, (ps1_e0_regs[0] & 0x01) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL));
/*Enable 512-640kb*/
mem_set_mem_state(0x80000, 0x20000, (ps1_e0_regs[1] & 0x01) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL));
}
void ps1_m2121_write(uint16_t port, uint8_t val, void *p)
{
switch (port)
{
case 0x0092:
if (val & 1)
softresetx86();
ps1_92 = val & ~1;
mem_a20_alt = val & 2;
mem_a20_recalc();
break;
case 0x94:
ps1_94 = val;
break;
case 0xe0:
ps1_e0_addr = val;
break;
case 0xe1:
ps1_e0_regs[ps1_e0_addr] = val;
ps1_m2121_recalc_memory();
break;
case 0x102:
lpt1_remove();
if (val & 0x04)
serial1_init(0x3f8, 4);
else
serial1_remove();
if (val & 0x10)
{
switch ((val >> 5) & 3)
{
case 0:
lpt1_init(0x3bc);
break;
case 1:
lpt1_init(0x378);
break;
case 2:
lpt1_init(0x278);
break;
}
}
ps1_102 = val;
break;
case 0x103:
ps1_103 = val;
break;
case 0x104:
ps1_104 = val;
break;
case 0x105:
ps1_105 = val;
break;
case 0x190:
ps1_190 = val;
break;
}
}
void ps1mb_m2121_init()
{
io_sethandler(0x0091, 0x0001, ps1_m2121_read, NULL, NULL, ps1_m2121_write, NULL, NULL, NULL);
io_sethandler(0x0092, 0x0001, ps1_m2121_read, NULL, NULL, ps1_m2121_write, NULL, NULL, NULL);
io_sethandler(0x0094, 0x0001, ps1_m2121_read, NULL, NULL, ps1_m2121_write, NULL, NULL, NULL);
io_sethandler(0x00e0, 0x0002, ps1_m2121_read, NULL, NULL, ps1_m2121_write, NULL, NULL, NULL);
io_sethandler(0x0102, 0x0004, ps1_m2121_read, NULL, NULL, ps1_m2121_write, NULL, NULL, NULL);
io_sethandler(0x0190, 0x0001, ps1_m2121_read, NULL, NULL, ps1_m2121_write, NULL, NULL, NULL);
rom_init(&ps1_high_rom,
"roms/ibmps1_2121/fc0000.bin",
0xfc0000,
0x40000,
0x3ffff,
0,
MEM_MAPPING_EXTERNAL);
ps1_190 = 0;
lpt1_remove();
lpt2_remove();
lpt1_init(0x3bc);
serial1_remove();
serial2_remove();
mem_remap_top_384k();
}

View File

@@ -1 +1,2 @@
void ps1mb_init();
void ps1mb_m2121_init();

187
src/vid_ps1_svga.c Normal file
View File

@@ -0,0 +1,187 @@
/*Emulation of the SVGA chip in the IBM PS/1 Model 2121, or at least the
20 MHz version.
I am not entirely sure what this chip actually is, possibly a CF62011? I can
not find any documentation on the chip so have implemented enough to pass
self-test in the PS/1 BIOS. It has 512kb video memory but I have not found any
native drivers for any operating system and there is no VBE implementation, so
it's just a VGA for now.
*/
#include <stdlib.h>
#include "ibm.h"
#include "device.h"
#include "io.h"
#include "mem.h"
#include "rom.h"
#include "video.h"
#include "vid_svga.h"
#include "vid_vga.h"
typedef struct ps1_m2121_svga_t
{
svga_t svga;
rom_t bios_rom;
uint8_t banking;
uint8_t reg_2100;
uint8_t reg_210a;
} ps1_m2121_svga_t;
void ps1_m2121_svga_out(uint16_t addr, uint8_t val, void *p)
{
ps1_m2121_svga_t *ps1 = (ps1_m2121_svga_t *)p;
svga_t *svga = &ps1->svga;
uint8_t old;
// pclog("svga_out : %04X %02X %04X:%04X %02X %i\n", addr, val, CS,cpu_state.pc, ram[0x489], ins);
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
addr ^= 0x60;
switch (addr)
{
case 0x3D4:
svga->crtcreg = val & 0x1f;
return;
case 0x3D5:
if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80))
return;
if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80))
val = (svga->crtc[7] & ~0x10) | (val & 0x10);
old = svga->crtc[svga->crtcreg];
svga->crtc[svga->crtcreg] = val;
if (old != val)
{
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10)
{
svga->fullchange = changeframecount;
svga_recalctimings(svga);
}
}
break;
case 0x2100:
ps1->reg_2100 = val;
if ((val & 7) < 4)
svga->read_bank = svga->write_bank = 0;
else
svga->read_bank = svga->write_bank = (ps1->banking & 0x7) * 0x10000;
break;
case 0x2108:
if ((ps1->reg_2100 & 7) >= 4)
svga->read_bank = svga->write_bank = (val & 0x7) * 0x10000;
ps1->banking = val;
break;
case 0x210a:
ps1->reg_210a = val;
break;
}
svga_out(addr, val, svga);
}
uint8_t ps1_m2121_svga_in(uint16_t addr, void *p)
{
ps1_m2121_svga_t *ps1 = (ps1_m2121_svga_t *)p;
svga_t *svga = &ps1->svga;
uint8_t temp;
// if (addr != 0x3da) pclog("svga_in : %04X ", addr);
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
addr ^= 0x60;
switch (addr)
{
case 0x100:
temp = 0xfe;
break;
case 0x101:
temp = 0xe8;
break;
case 0x3D4:
temp = svga->crtcreg;
break;
case 0x3D5:
temp = svga->crtc[svga->crtcreg];
break;
case 0x2108:
temp = ps1->banking;
break;
case 0x210a:
temp = ps1->reg_210a;
break;
default:
temp = svga_in(addr, svga);
break;
}
// if (addr != 0x3da) pclog("%02X %04X:%04X\n", temp, CS,pc);
return temp;
}
void *ps1_m2121_svga_init()
{
ps1_m2121_svga_t *ps1 = malloc(sizeof(ps1_m2121_svga_t));
memset(ps1, 0, sizeof(ps1_m2121_svga_t));
svga_init(&ps1->svga, ps1, 1 << 19, /*512kb*/
NULL,
ps1_m2121_svga_in, ps1_m2121_svga_out,
NULL,
NULL);
io_sethandler(0x0100, 0x0002, ps1_m2121_svga_in, NULL, NULL, ps1_m2121_svga_out, NULL, NULL, ps1);
io_sethandler(0x03c0, 0x0020, ps1_m2121_svga_in, NULL, NULL, ps1_m2121_svga_out, NULL, NULL, ps1);
io_sethandler(0x2100, 0x0010, ps1_m2121_svga_in, NULL, NULL, ps1_m2121_svga_out, NULL, NULL, ps1);
// io_sethandler(0x210a, 0x0001, ps1_m2121_svga_in, NULL, NULL, ps1_m2121_svga_out, NULL, NULL, ps1);
ps1->svga.bpp = 8;
ps1->svga.miscout = 1;
return ps1;
}
void ps1_m2121_svga_close(void *p)
{
ps1_m2121_svga_t *ps1 = (ps1_m2121_svga_t *)p;
svga_close(&ps1->svga);
free(ps1);
}
void ps1_m2121_svga_speed_changed(void *p)
{
ps1_m2121_svga_t *ps1 = (ps1_m2121_svga_t *)p;
svga_recalctimings(&ps1->svga);
}
void ps1_m2121_svga_force_redraw(void *p)
{
ps1_m2121_svga_t *ps1 = (ps1_m2121_svga_t *)p;
ps1->svga.fullchange = changeframecount;
}
void ps1_m2121_svga_add_status_info(char *s, int max_len, void *p)
{
ps1_m2121_svga_t *ps1 = (ps1_m2121_svga_t *)p;
svga_add_status_info(s, max_len, &ps1->svga);
}
device_t ps1_m2121_svga_device =
{
"PS/1 Model 2121 SVGA",
0,
ps1_m2121_svga_init,
ps1_m2121_svga_close,
NULL,
ps1_m2121_svga_speed_changed,
ps1_m2121_svga_force_redraw,
ps1_m2121_svga_add_status_info
};

1
src/vid_ps1_svga.h Normal file
View File

@@ -0,0 +1 @@
extern device_t ps1_m2121_svga_device;

View File

@@ -29,6 +29,7 @@
#include "vid_pc1640.h"
#include "vid_pc200.h"
#include "vid_pcjr.h"
#include "vid_ps1_svga.h"
#include "vid_s3.h"
#include "vid_s3_virge.h"
#include "vid_tandy.h"
@@ -269,6 +270,10 @@ void video_init()
case ROM_IBMPS1_2011:
device_add(&ps1vga_device);
return;
case ROM_IBMPS1_2121:
device_add(&ps1_m2121_svga_device);
return;
}
device_add(video_cards[video_old_to_new(gfxcard)].device);
}