Re-integrated the Amstrad machines.
This commit is contained in:
@@ -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(¶dise_pvga1a_pc2086_device);
|
||||
break;
|
||||
|
||||
case ROM_PC3086:
|
||||
device_add(¶dise_pvga1a_pc3086_device);
|
||||
break;
|
||||
|
||||
case ROM_MEGAPC:
|
||||
device_add(¶dise_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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user