mirror of
https://github.com/sarah-walker-pcem/pcem.git
synced 2025-07-23 03:33:02 +02:00
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:
BIN
nvr/ibmps1_2121.nvr
Normal file
BIN
nvr/ibmps1_2121.nvr
Normal file
Binary file not shown.
@@ -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.
|
||||
|
||||
|
@@ -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 \
|
||||
|
@@ -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 \
|
||||
|
@@ -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 \
|
||||
|
39
src/fdc.c
39
src/fdc.c
@@ -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;
|
||||
}
|
||||
|
@@ -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. */
|
||||
|
10
src/fdd.c
10
src/fdd.c
@@ -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;
|
||||
}
|
||||
|
@@ -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);
|
||||
|
@@ -333,7 +333,8 @@ enum
|
||||
ROM_REVENGE,
|
||||
ROM_IBMPS1_2011,
|
||||
ROM_DESKPRO_386,
|
||||
|
||||
ROM_IBMPS1_2121,
|
||||
|
||||
ROM_MAX
|
||||
};
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
51
src/mem.c
51
src/mem.c
@@ -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;
|
||||
|
@@ -163,4 +163,6 @@ void mem_reset_page_blocks();
|
||||
|
||||
extern mem_mapping_t ram_low_mapping;
|
||||
|
||||
void mem_remap_top_384k();
|
||||
|
||||
#endif
|
||||
|
22
src/model.c
22
src/model.c
@@ -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();
|
||||
|
@@ -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
143
src/ps1.c
@@ -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();
|
||||
}
|
||||
|
187
src/vid_ps1_svga.c
Normal file
187
src/vid_ps1_svga.c
Normal 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
1
src/vid_ps1_svga.h
Normal file
@@ -0,0 +1 @@
|
||||
extern device_t ps1_m2121_svga_device;
|
@@ -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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user