Re-integrated the Amstrad machines.

This commit is contained in:
waltje
2017-11-08 16:29:54 -05:00
parent b8d75f4f5a
commit 354b49d354
12 changed files with 1003 additions and 155 deletions

View File

@@ -6,9 +6,28 @@
*
* This file is part of the 86Box distribution.
*
* Emulation of the Amstrad series PC's.
* Emulation of the Amstrad series of PC's.
*
* Version: @(#)m_amstrad.c 1.0.2 2017/11/03
* The module supports the PC1512, PC1640 and PC200, including
* their keyboard, mouse and video devices.
*
* PC1512: The PC1512 extends CGA with a bit-planar 640x200x16 mode.
* Most CRTC registers are fixed.
*
* The Technical Reference Manual lists the video waitstate
* time as between 12 and 46 cycles. We currently always use
* the lower number.
*
* PC1640: Mostly standard EGA, but with CGA & Hercules emulation.
*
* PC200: 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.
*
*
* TODO: EGA mode does not seem to work in the PC1640; it displays some
* semi-random junk. Video-memory pointer maybe?
*
* Version: @(#)m_amstrad.c 1.0.3 2017/11/08
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -24,6 +43,7 @@
#include <stdlib.h>
#include <wchar.h>
#include "../86box.h"
#include "../cpu/cpu.h"
#include "../io.h"
#include "../nmi.h"
#include "../pic.h"
@@ -38,14 +58,21 @@
#include "../mouse.h"
#include "../game/gameport.h"
#include "../lpt.h"
#include "../sound/sound.h"
#include "../sound/snd_speaker.h"
#include "../floppy/floppy.h"
#include "../floppy/fdd.h"
#include "../floppy/fdc.h"
#include "../sound/sound.h"
#include "../sound/snd_speaker.h"
#include "../video/video.h"
#include "../video/vid_cga.h"
#include "../video/vid_ega.h"
#include "../video/vid_paradise.h"
#include "machine.h"
#define BIOS_1640_PATH L"roms/machines/pc1640/40100"
#define STAT_PARITY 0x80
#define STAT_RTIMEOUT 0x40
#define STAT_TTIMEOUT 0x20
@@ -57,27 +84,791 @@
typedef struct {
/* Machine stuff. */
mem_mapping_t cga_map; /* 1512/1640/200 */
mem_mapping_t ega_map; /* 1640 */
rom_t bios_rom; /* 1640 */
cga_t cga; /* 1640/200 */
ega_t ega; /* 1640 */
uint8_t crtc[32];
int crtcreg;
int cga_enabled; /* 1640 */
uint8_t cgacol,
cgamode,
stat;
uint8_t plane_write, /* 1512/200 */
plane_read, /* 1512/200 */
border; /* 1512/200 */
int linepos,
displine;
int sc, vc;
int cgadispon;
int con, coff,
cursoron,
cgablink;
int64_t vsynctime;
int vadj;
uint16_t ma, maback;
int dispon;
int blink;
int64_t dispontime, /* 1512/1640 */
dispofftime; /* 1512/1640 */
int64_t vidtime; /* 1512/1640 */
int firstline,
lastline;
uint8_t *vram;
} amsvid_t;
typedef struct {
/* Machine stuff. */
uint8_t dead;
uint8_t systemstat_1,
systemstat_2;
/* Keyboard stuff. */
/* Keyboard stuff. */
int8_t wantirq;
uint8_t key_waiting;
uint8_t pa;
uint8_t pb;
/* Mouse stuff. */
/* Mouse stuff. */
uint8_t mousex,
mousey;
int oldb;
/* Video stuff. */
amsvid_t *vid;
} amstrad_t;
static uint8_t key_queue[16];
static int key_queue_start = 0,
key_queue_end = 0;
static uint8_t crtc_mask[32] = {
0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f,
0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static void
recalc_timings_1512(amsvid_t *vid)
{
double _dispontime, _dispofftime, disptime;
disptime = 128; /*Fixed on PC1512*/
_dispontime = 80;
_dispofftime = disptime - _dispontime;
_dispontime *= CGACONST;
_dispofftime *= CGACONST;
vid->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT));
vid->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT));
}
static void
vid_out_1512(uint16_t addr, uint8_t val, void *priv)
{
amsvid_t *vid = (amsvid_t *)priv;
uint8_t old;
switch (addr) {
case 0x3d4:
vid->crtcreg = val & 31;
return;
case 0x3d5:
old = vid->crtc[vid->crtcreg];
vid->crtc[vid->crtcreg] = val & crtc_mask[vid->crtcreg];
if (old != val) {
if (vid->crtcreg < 0xe || vid->crtcreg > 0x10) {
fullchange = changeframecount;
recalc_timings_1512(vid);
}
}
return;
case 0x3d8:
if ((val & 0x12) == 0x12 && (vid->cgamode & 0x12) != 0x12) {
vid->plane_write = 0xf;
vid->plane_read = 0;
}
vid->cgamode = val;
return;
case 0x3d9:
vid->cgacol = val;
return;
case 0x3dd:
vid->plane_write = val;
return;
case 0x3de:
vid->plane_read = val & 3;
return;
case 0x3df:
vid->border = val;
return;
}
}
static uint8_t
vid_in_1512(uint16_t addr, void *priv)
{
amsvid_t *vid = (amsvid_t *)priv;
uint8_t ret = 0xff;
switch (addr) {
case 0x3d4:
ret = vid->crtcreg;
case 0x3d5:
ret = vid->crtc[vid->crtcreg];
case 0x3da:
ret = vid->stat;
}
return(ret);
}
static void
vid_write_1512(uint32_t addr, uint8_t val, void *priv)
{
amsvid_t *vid = (amsvid_t *)priv;
egawrites++;
cycles -= 12;
addr &= 0x3fff;
if ((vid->cgamode & 0x12) == 0x12) {
if (vid->plane_write & 1) vid->vram[addr] = val;
if (vid->plane_write & 2) vid->vram[addr | 0x4000] = val;
if (vid->plane_write & 4) vid->vram[addr | 0x8000] = val;
if (vid->plane_write & 8) vid->vram[addr | 0xc000] = val;
} else
vid->vram[addr] = val;
}
static uint8_t
vid_read_1512(uint32_t addr, void *priv)
{
amsvid_t *vid = (amsvid_t *)priv;
egareads++;
cycles -= 12;
addr &= 0x3fff;
if ((vid->cgamode & 0x12) == 0x12)
return(vid->vram[addr | (vid->plane_read << 14)]);
return(vid->vram[addr]);
}
static void
vid_poll_1512(void *priv)
{
amsvid_t *vid = (amsvid_t *)priv;
uint16_t ca = (vid->crtc[15] | (vid->crtc[14] << 8)) & 0x3fff;
int drawcursor;
int x, c;
uint8_t chr, attr;
uint16_t dat, dat2, dat3, dat4;
int cols[4];
int col;
int oldsc;
if (! vid->linepos) {
vid->vidtime += vid->dispofftime;
vid->stat |= 1;
vid->linepos = 1;
oldsc = vid->sc;
if (vid->dispon) {
if (vid->displine < vid->firstline) {
vid->firstline = vid->displine;
video_wait_for_buffer();
}
vid->lastline = vid->displine;
for (c = 0; c < 8; c++) {
if ((vid->cgamode & 0x12) == 0x12) {
buffer->line[vid->displine][c] = (vid->border & 15) + 16;
if (vid->cgamode & 1)
buffer->line[vid->displine][c + (vid->crtc[1] << 3) + 8] = 0;
else
buffer->line[vid->displine][c + (vid->crtc[1] << 4) + 8] = 0;
} else {
buffer->line[vid->displine][c] = (vid->cgacol & 15) + 16;
if (vid->cgamode & 1)
buffer->line[vid->displine][c + (vid->crtc[1] << 3) + 8] = (vid->cgacol & 15) + 16;
else
buffer->line[vid->displine][c + (vid->crtc[1] << 4) + 8] = (vid->cgacol & 15) + 16;
}
}
if (vid->cgamode & 1) {
for (x = 0; x < 80; x++) {
chr = vid->vram[ ((vid->ma << 1) & 0x3fff)];
attr = vid->vram[(((vid->ma << 1) + 1) & 0x3fff)];
drawcursor = ((vid->ma == ca) && vid->con && vid->cursoron);
if (vid->cgamode & 0x20) {
cols[1] = (attr & 15) + 16;
cols[0] = ((attr >> 4) & 7) + 16;
if ((vid->blink & 16) && (attr & 0x80) && !drawcursor)
cols[1] = cols[0];
} else {
cols[1] = (attr & 15) + 16;
cols[0] = (attr >> 4) + 16;
}
if (drawcursor) {
for (c = 0; c < 8; c++)
buffer->line[vid->displine][(x << 3) + c + 8] = cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
} else {
for (c = 0; c < 8; c++)
buffer->line[vid->displine][(x << 3) + c + 8] = cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
}
vid->ma++;
}
} else if (! (vid->cgamode & 2)) {
for (x = 0; x < 40; x++) {
chr = vid->vram[((vid->ma << 1) & 0x3fff)];
attr = vid->vram[(((vid->ma << 1) + 1) & 0x3fff)];
drawcursor = ((vid->ma == ca) && vid->con && vid->cursoron);
if (vid->cgamode & 0x20) {
cols[1] = (attr & 15) + 16;
cols[0] = ((attr >> 4) & 7) + 16;
if ((vid->blink & 16) && (attr & 0x80))
cols[1] = cols[0];
} else {
cols[1] = (attr & 15) + 16;
cols[0] = (attr >> 4) + 16;
}
vid->ma++;
if (drawcursor) {
for (c = 0; c < 8; c++)
buffer->line[vid->displine][(x << 4) + (c << 1) + 8] =
buffer->line[vid->displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
} else {
for (c = 0; c < 8; c++)
buffer->line[vid->displine][(x << 4) + (c << 1) + 8] =
buffer->line[vid->displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
}
}
} else if (! (vid->cgamode & 16)) {
cols[0] = (vid->cgacol & 15) | 16;
col = (vid->cgacol & 16) ? 24 : 16;
if (vid->cgamode & 4) {
cols[1] = col | 3;
cols[2] = col | 4;
cols[3] = col | 7;
} else if (vid->cgacol & 32) {
cols[1] = col | 3;
cols[2] = col | 5;
cols[3] = col | 7;
} else {
cols[1] = col | 2;
cols[2] = col | 4;
cols[3] = col | 6;
}
for (x = 0; x < 40; x++) {
dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1];
vid->ma++;
for (c = 0; c < 8; c++) {
buffer->line[vid->displine][(x << 4) + (c << 1) + 8] =
buffer->line[vid->displine][(x << 4) + (c << 1) + 1 + 8] = cols[dat >> 14];
dat <<= 2;
}
}
} else {
for (x = 0; x < 40; x++) {
ca = ((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000);
dat = (vid->vram[ca] << 8) | vid->vram[ca + 1];
dat2 = (vid->vram[ca + 0x4000] << 8) | vid->vram[ca + 0x4001];
dat3 = (vid->vram[ca + 0x8000] << 8) | vid->vram[ca + 0x8001];
dat4 = (vid->vram[ca + 0xc000] << 8) | vid->vram[ca + 0xc001];
vid->ma++;
for (c = 0; c < 16; c++) {
buffer->line[vid->displine][(x << 4) + c + 8] = (((dat >> 15) | ((dat2 >> 15) << 1) | ((dat3 >> 15) << 2) | ((dat4 >> 15) << 3)) & (vid->cgacol & 15)) + 16;
dat <<= 1;
dat2 <<= 1;
dat3 <<= 1;
dat4 <<= 1;
}
}
}
} else {
cols[0] = ((vid->cgamode & 0x12) == 0x12) ? 0 : (vid->cgacol & 15) + 16;
if (vid->cgamode & 1)
hline(buffer, 0, vid->displine, (vid->crtc[1] << 3) + 16, cols[0]);
else
hline(buffer, 0, vid->displine, (vid->crtc[1] << 4) + 16, cols[0]);
}
vid->sc = oldsc;
if (vid->vsynctime)
vid->stat |= 8;
vid->displine++;
if (vid->displine >= 360)
vid->displine = 0;
} else {
vid->vidtime += vid->dispontime;
if ((vid->lastline - vid->firstline) == 199)
vid->dispon = 0; /*Amstrad PC1512 always displays 200 lines, regardless of CRTC settings*/
if (vid->dispon)
vid->stat &= ~1;
vid->linepos = 0;
if (vid->vsynctime) {
vid->vsynctime--;
if (! vid->vsynctime)
vid->stat &= ~8;
}
if (vid->sc == (vid->crtc[11] & 31)) {
vid->con = 0;
vid->coff = 1;
}
if (vid->vadj) {
vid->sc++;
vid->sc &= 31;
vid->ma = vid->maback;
vid->vadj--;
if (! vid->vadj) {
vid->dispon = 1;
vid->ma = vid->maback = (vid->crtc[13] | (vid->crtc[12] << 8)) & 0x3fff;
vid->sc = 0;
}
} else if (vid->sc == vid->crtc[9]) {
vid->maback = vid->ma;
vid->sc = 0;
vid->vc++;
vid->vc &= 127;
if (vid->displine == 32) {
vid->vc = 0;
vid->vadj = 6;
if ((vid->crtc[10] & 0x60) == 0x20)
vid->cursoron = 0;
else
vid->cursoron = vid->blink & 16;
}
if (vid->displine >= 262) {
vid->dispon = 0;
vid->displine = 0;
vid->vsynctime = 46;
if (vid->cgamode&1)
x = (vid->crtc[1] << 3) + 16;
else
x = (vid->crtc[1] << 4) + 16;
#if 0
//FIXME: this doesnt seem right???? --FvK
x = 640 + 16;
#endif
vid->lastline++;
if ((x != xsize) || ((vid->lastline - vid->firstline) != ysize) || video_force_resize_get()) {
xsize = x;
ysize = vid->lastline - vid->firstline;
if (xsize < 64) xsize = 656;
if (ysize < 32) ysize = 200;
set_screen_size(xsize, (ysize << 1) + 16);
if (video_force_resize_get())
video_force_resize_set(0);
}
video_blit_memtoscreen_8(0, vid->firstline - 4, 0, (vid->lastline - vid->firstline) + 8, xsize, (vid->lastline - vid->firstline) + 8);
video_res_x = xsize - 16;
video_res_y = ysize;
if (vid->cgamode & 1) {
video_res_x /= 8;
video_res_y /= vid->crtc[9] + 1;
video_bpp = 0;
} else if (! (vid->cgamode & 2)) {
video_res_x /= 16;
video_res_y /= vid->crtc[9] + 1;
video_bpp = 0;
} else if (! (vid->cgamode & 16)) {
video_res_x /= 2;
video_bpp = 2;
} else {
video_bpp = 4;
}
vid->firstline = 1000;
vid->lastline = 0;
vid->blink++;
}
} else {
vid->sc++;
vid->sc &= 31;
vid->ma = vid->maback;
}
if (vid->sc == (vid->crtc[10] & 31))
vid->con = 1;
}
}
static void
vid_init_1512(amstrad_t *ams)
{
amsvid_t *vid;
/* Allocate a video controller block. */
vid = (amsvid_t *)malloc(sizeof(amsvid_t));
memset(vid, 0x00, sizeof(amsvid_t));
vid->vram = malloc(0x10000);
vid->cgacol = 7;
vid->cgamode = 0x12;
timer_add(vid_poll_1512, &vid->vidtime, TIMER_ALWAYS_ENABLED, vid);
mem_mapping_add(&vid->cga_map, 0xb8000, 0x08000,
vid_read_1512, NULL, NULL, vid_write_1512, NULL, NULL,
NULL, 0, vid);
io_sethandler(0x03d0, 16,
vid_in_1512, NULL, NULL, vid_out_1512, NULL, NULL, vid);
overscan_x = overscan_y = 16;
ams->vid = vid;
}
static void
vid_close_1512(void *priv)
{
amsvid_t *vid = (amsvid_t *)priv;
free(vid->vram);
free(vid);
}
static void
vid_speed_change_1512(void *priv)
{
amsvid_t *vid = (amsvid_t *)priv;
recalc_timings_1512(vid);
}
static device_t vid_1512_device = {
"Amstrad PC1512 (video)",
0, 0,
NULL, vid_close_1512, NULL,
NULL,
vid_speed_change_1512,
NULL,
NULL
};
static void
recalc_timings_1640(amsvid_t *vid)
{
cga_recalctimings(&vid->cga);
ega_recalctimings(&vid->ega);
if (vid->cga_enabled) {
overscan_x = overscan_y = 16;
vid->dispontime = vid->cga.dispontime;
vid->dispofftime = vid->cga.dispofftime;
} else {
overscan_x = 16; overscan_y = 28;
vid->dispontime = vid->ega.dispontime;
vid->dispofftime = vid->ega.dispofftime;
}
}
static void
vid_out_1640(uint16_t addr, uint8_t val, void *priv)
{
amsvid_t *vid = (amsvid_t *)priv;
switch (addr) {
case 0x03db:
vid->cga_enabled = val & 0x40;
if (vid->cga_enabled) {
mem_mapping_enable(&vid->cga_map);
mem_mapping_disable(&vid->ega_map);
} else {
mem_mapping_disable(&vid->cga_map);
switch (vid->ega.gdcreg[6] & 0xc) {
case 0x0: /*128k at A0000*/
mem_mapping_set_addr(&vid->ega_map,
0xa0000, 0x20000);
break;
case 0x4: /*64k at A0000*/
mem_mapping_set_addr(&vid->ega_map,
0xa0000, 0x10000);
break;
case 0x8: /*32k at B0000*/
mem_mapping_set_addr(&vid->ega_map,
0xb0000, 0x08000);
break;
case 0xC: /*32k at B8000*/
mem_mapping_set_addr(&vid->ega_map,
0xb8000, 0x08000);
break;
}
}
return;
}
if (vid->cga_enabled)
cga_out(addr, val, &vid->cga);
else
ega_out(addr, val, &vid->ega);
}
static uint8_t
vid_in_1640(uint16_t addr, void *priv)
{
amsvid_t *vid = (amsvid_t *)priv;
switch (addr) {
}
if (vid->cga_enabled)
return(cga_in(addr, &vid->cga));
else
return(ega_in(addr, &vid->ega));
}
static void
vid_poll_1640(void *priv)
{
amsvid_t *vid = (amsvid_t *)priv;
if (vid->cga_enabled) {
overscan_x = overscan_y = 16;
vid->cga.vidtime = vid->vidtime;
cga_poll(&vid->cga);
vid->vidtime = vid->cga.vidtime;
} else {
overscan_x = 16; overscan_y = 28;
vid->ega.vidtime = vid->vidtime;
ega_poll(&vid->ega);
vid->vidtime = vid->ega.vidtime;
}
}
static void
vid_init_1640(amstrad_t *ams)
{
amsvid_t *vid;
/* Allocate a video controller block. */
vid = (amsvid_t *)malloc(sizeof(amsvid_t));
memset(vid, 0x00, sizeof(amsvid_t));
rom_init(&vid->bios_rom, BIOS_1640_PATH, 0xc0000, 0x8000, 0x7fff, 0, 0);
ega_init(&vid->ega);
vid->cga.vram = vid->ega.vram;
vid->cga_enabled = 1;
cga_init(&vid->cga);
mem_mapping_add(&vid->cga_map, 0xb8000, 0x08000,
cga_read, NULL, NULL, cga_write, NULL, NULL, NULL, 0, &vid->cga);
mem_mapping_add(&vid->ega_map, 0, 0,
ega_read, NULL, NULL, ega_write, NULL, NULL, NULL, 0, &vid->ega);
io_sethandler(0x03a0, 64,
vid_in_1640, NULL, NULL, vid_out_1640, NULL, NULL, vid);
timer_add(vid_poll_1640, &vid->vidtime, TIMER_ALWAYS_ENABLED, vid);
overscan_x = overscan_y = 16;
ams->vid = vid;
}
static void
vid_close_1640(void *priv)
{
amsvid_t *vid = (amsvid_t *)priv;
free(vid->ega.vram);
free(vid);
}
static void
vid_speed_changed_1640(void *priv)
{
amsvid_t *vid = (amsvid_t *)priv;
recalc_timings_1640(vid);
}
static device_t vid_1640_device = {
"Amstrad PC1640 (video)",
0, 0,
NULL, vid_close_1640, NULL,
NULL,
vid_speed_changed_1640,
NULL,
NULL
};
static void
vid_out_200(uint16_t addr, uint8_t val, void *priv)
{
amsvid_t *vid = (amsvid_t *)priv;
cga_t *cga = &vid->cga;
uint8_t old;
switch (addr) {
case 0x3d5:
if (!(vid->plane_read & 0x40) && cga->crtcreg <= 11) {
if (vid->plane_read & 0x80)
nmi = 1;
vid->plane_write = 0x20 | (cga->crtcreg & 0x1f);
vid->border = val;
return;
}
old = cga->crtc[cga->crtcreg];
cga->crtc[cga->crtcreg] = val & crtc_mask[cga->crtcreg];
if (old != val) {
if (cga->crtcreg < 0xe || cga->crtcreg > 0x10) {
fullchange = changeframecount;
cga_recalctimings(cga);
}
}
return;
case 0x3d8:
old = cga->cgamode;
cga->cgamode = val;
if ((cga->cgamode ^ old) & 3)
cga_recalctimings(cga);
vid->plane_write |= 0x80;
if (vid->plane_read & 0x80)
nmi = 1;
return;
case 0x3de:
vid->plane_read = val;
vid->plane_write = 0x1f;
if (val & 0x80)
vid->plane_write |= 0x40;
return;
}
cga_out(addr, val, cga);
}
static uint8_t
vid_in_200(uint16_t addr, void *priv)
{
amsvid_t *vid = (amsvid_t *)priv;
cga_t *cga = &vid->cga;
uint8_t ret;
switch (addr) {
case 0x3d8:
return(cga->cgamode);
case 0x3dd:
ret = vid->plane_write;
vid->plane_write &= 0x1f;
nmi = 0;
return(ret);
case 0x3de:
return((vid->plane_read & 0xc7) | 0x10); /*External CGA*/
case 0x3df:
return(vid->border);
}
return(cga_in(addr, cga));
}
static void
vid_init_200(amstrad_t *ams)
{
amsvid_t *vid;
cga_t *cga;
/* Allocate a video controller block. */
vid = (amsvid_t *)malloc(sizeof(amsvid_t));
memset(vid, 0x00, sizeof(amsvid_t));
cga = &vid->cga;
cga->vram = malloc(0x4000);
cga_init(cga);
mem_mapping_add(&vid->cga_map, 0xb8000, 0x08000,
cga_read, NULL, NULL, cga_write, NULL, NULL, NULL, 0, cga);
io_sethandler(0x03d0, 16,
vid_in_200, NULL, NULL, vid_out_200, NULL, NULL, vid);
timer_add(cga_poll, &cga->vidtime, TIMER_ALWAYS_ENABLED, cga);
overscan_x = overscan_y = 16;
ams->vid = vid;
}
static void
vid_close_200(void *priv)
{
amsvid_t *vid = (amsvid_t *)priv;
free(vid->cga.vram);
free(vid);
}
static void
vid_speed_changed_200(void *priv)
{
amsvid_t *vid = (amsvid_t *)priv;
cga_recalctimings(&vid->cga);
}
static device_t vid_200_device = {
"Amstrad PC200 (video)",
0, 0,
NULL, vid_close_200, NULL,
NULL,
vid_speed_changed_200,
NULL,
NULL
};
static void
@@ -104,7 +895,7 @@ ms_read(uint16_t addr, void *priv)
}
static uint8_t
static uint8_t
ms_poll(int x, int y, int z, int b, void *priv)
{
amstrad_t *ams = (amstrad_t *)priv;
@@ -151,7 +942,7 @@ kbd_write(uint16_t port, uint8_t val, void *priv)
switch (port) {
case 0x61:
#if ENABLE_KEYBOARD_LOG
pclog("keyboard_amstrad : pb write %02X %02X %i %02X %i\n",
pclog("keyboard_amstrad : pb write %02X %02X %i %02X %i\n",
val, ams->pb, !(ams->pb&0x40), ams->pb&0x40, (val&0x40));
#endif
if (!(ams->pb & 0x40) && (val & 0x40)) { /*Reset keyboard*/
@@ -238,7 +1029,7 @@ kbd_read(uint16_t port, void *priv)
}
static void
static void
kbd_poll(void *priv)
{
amstrad_t *ams = (amstrad_t *)priv;
@@ -307,12 +1098,14 @@ void
void
machine_amstrad_init(machine_t *model)
{
amstrad_t *ams;
amstrad_t *ams;
ams = (amstrad_t *)malloc(sizeof(amstrad_t));
memset(ams, 0x00, sizeof(amstrad_t));
machine_common_init(model);
nmi_init();
lpt2_remove_ams();
@@ -320,17 +1113,48 @@ machine_amstrad_init(machine_t *model)
amstrad_read, NULL, NULL, NULL, NULL, NULL, ams);
io_sethandler(0xdead, 1,
amstrad_read, NULL, NULL, amstrad_write, NULL, NULL, ams);
amstrad_read, NULL, NULL, amstrad_write, NULL, NULL, ams);
io_sethandler(0x0078, 1,
ms_read, NULL, NULL, ms_write, NULL, NULL, ams);
io_sethandler(0x007a, 1,
ms_read, NULL, NULL, ms_write, NULL, NULL, ams);
switch(romset) {
case ROM_PC1512:
vid_init_1512(ams);
device_add_ex(&vid_1512_device, ams->vid);
break;
case ROM_PC1640:
vid_init_1640(ams);
device_add_ex(&vid_1640_device, ams->vid);
break;
case ROM_PC200:
vid_init_200(ams);
device_add_ex(&vid_200_device, ams->vid);
break;
case ROM_PC2086:
device_add(&paradise_pvga1a_pc2086_device);
break;
case ROM_PC3086:
device_add(&paradise_pvga1a_pc3086_device);
break;
case ROM_MEGAPC:
device_add(&paradise_wd90c11_megapc_device);
break;
}
/* Initialize the (custom) keyboard/mouse interface. */
ams->wantirq = 0;
ams->wantirq = 0;
io_sethandler(0x0060, 6,
kbd_read, NULL, NULL, kbd_write, NULL, NULL, ams);
timer_add(kbd_poll, &keyboard_delay, TIMER_ALWAYS_ENABLED, ams);
keyboard_set_table(scancode_xt);
keyboard_send = kbd_adddata;
keyboard_scan = 1;
@@ -343,7 +1167,5 @@ machine_amstrad_init(machine_t *model)
/* FIXME: make sure this is correct? */
nvr_at_init(1);
nmi_init();
fdc_set_dskchg_activelow();

View File

@@ -8,6 +8,8 @@
*
* Emulation of the IBM PS/1 models 2011, 2121 and 2133.
*
* Model 2011: The initial model, using a 10MHz 80286.
*
* Model 2121: This is similar to 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
@@ -315,7 +317,11 @@ ps1_setup(int model)
io_sethandler(0x00e0, 2,
ps1_read, NULL, NULL, ps1_write, NULL, NULL, ps);
#if 0
#if 1
rom_init(&ps->high_rom,
L"roms/machines/ibmps1_2121/fc0000.bin",
0xfc0000, 0x20000, 0x1ffff, 0, MEM_MAPPING_EXTERNAL);
#else
rom_init(&ps->high_rom,
L"roms/machines/ibmps1_2121/fc0000_shell.bin",
0xfc0000, 0x40000, 0x3ffff, 0, MEM_MAPPING_EXTERNAL);