IBM.H is gone, video stuff re-organized. Keyboard stuff reorganized. Machines that have their own video, mouse and/or keyboard now have all this in their machine file. Fixed and other cleanups here and there.
794 lines
19 KiB
C
794 lines
19 KiB
C
/*
|
|
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
|
* running old operating systems and software designed for IBM
|
|
* PC systems and compatibles from 1981 through fairly recent
|
|
* system designs based on the PCI bus.
|
|
*
|
|
* This file is part of the 86Box distribution.
|
|
*
|
|
* Emulation of the Olivetti M24.
|
|
*
|
|
* Version: @(#)m_olivetti_m24.c 1.0.2 2017/11/03
|
|
*
|
|
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
|
* Miran Grca, <mgrca8@gmail.com>
|
|
* Fred N. van Kempen, <decwiz@yahoo.com>
|
|
*
|
|
* Copyright 2008-2017 Sarah Walker.
|
|
* Copyright 2016,2017 Miran Grca.
|
|
* Copyright 2017 Fred N. van Kempen.
|
|
*/
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <wchar.h>
|
|
#include "../86box.h"
|
|
#include "../io.h"
|
|
#include "../pic.h"
|
|
#include "../pit.h"
|
|
#include "../ppi.h"
|
|
#include "../nmi.h"
|
|
#include "../mem.h"
|
|
#include "../timer.h"
|
|
#include "../device.h"
|
|
#include "../nvr.h"
|
|
#include "../keyboard.h"
|
|
#include "../mouse.h"
|
|
#include "../game/gameport.h"
|
|
#include "../sound/sound.h"
|
|
#include "../sound/snd_speaker.h"
|
|
#include "../video/video.h"
|
|
#include "machine.h"
|
|
|
|
|
|
#define STAT_PARITY 0x80
|
|
#define STAT_RTIMEOUT 0x40
|
|
#define STAT_TTIMEOUT 0x20
|
|
#define STAT_LOCK 0x10
|
|
#define STAT_CD 0x08
|
|
#define STAT_SYSFLAG 0x04
|
|
#define STAT_IFULL 0x02
|
|
#define STAT_OFULL 0x01
|
|
|
|
|
|
typedef struct {
|
|
/* Video stuff. */
|
|
mem_mapping_t mapping;
|
|
uint8_t crtc[32];
|
|
int crtcreg;
|
|
uint8_t *vram;
|
|
uint8_t charbuffer[256];
|
|
uint8_t ctrl;
|
|
uint32_t base;
|
|
uint8_t cgamode, cgacol;
|
|
uint8_t stat;
|
|
int linepos, displine;
|
|
int sc, vc;
|
|
int con, coff, cursoron, blink;
|
|
int64_t vsynctime;
|
|
int vadj;
|
|
int lineff;
|
|
uint16_t ma, maback;
|
|
int dispon;
|
|
int64_t dispontime, dispofftime;
|
|
int64_t vidtime;
|
|
int firstline, lastline;
|
|
|
|
/* Keyboard stuff. */
|
|
int wantirq;
|
|
uint8_t command;
|
|
uint8_t status;
|
|
uint8_t out;
|
|
uint8_t output_port;
|
|
int param,
|
|
param_total;
|
|
uint8_t params[16];
|
|
uint8_t scan[7];
|
|
|
|
/* Mouse stuff. */
|
|
int mouse_mode;
|
|
int x, y, b;
|
|
} olim24_t;
|
|
|
|
|
|
static uint8_t crtcmask[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 uint8_t key_queue[16];
|
|
static int key_queue_start = 0,
|
|
key_queue_end = 0;
|
|
|
|
|
|
static void
|
|
recalc_timings(olim24_t *m24)
|
|
{
|
|
double _dispontime, _dispofftime, disptime;
|
|
|
|
if (m24->cgamode & 1) {
|
|
disptime = m24->crtc[0] + 1;
|
|
_dispontime = m24->crtc[1];
|
|
} else {
|
|
disptime = (m24->crtc[0] + 1) << 1;
|
|
_dispontime = m24->crtc[1] << 1;
|
|
}
|
|
|
|
_dispofftime = disptime - _dispontime;
|
|
_dispontime *= CGACONST / 2;
|
|
_dispofftime *= CGACONST / 2;
|
|
m24->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT));
|
|
m24->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT));
|
|
}
|
|
|
|
|
|
static void
|
|
vid_out(uint16_t addr, uint8_t val, void *priv)
|
|
{
|
|
olim24_t *m24 = (olim24_t *)priv;
|
|
uint8_t old;
|
|
|
|
switch (addr) {
|
|
case 0x3d4:
|
|
m24->crtcreg = val & 31;
|
|
break;
|
|
|
|
case 0x3d5:
|
|
old = m24->crtc[m24->crtcreg];
|
|
m24->crtc[m24->crtcreg] = val & crtcmask[m24->crtcreg];
|
|
if (old != val) {
|
|
if (m24->crtcreg < 0xe || m24->crtcreg > 0x10) {
|
|
fullchange = changeframecount;
|
|
recalc_timings(m24);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 0x3d8:
|
|
m24->cgamode = val;
|
|
break;
|
|
|
|
case 0x3d9:
|
|
m24->cgacol = val;
|
|
break;
|
|
|
|
case 0x3de:
|
|
m24->ctrl = val;
|
|
m24->base = (val & 0x08) ? 0x4000 : 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
static uint8_t
|
|
vid_in(uint16_t addr, void *priv)
|
|
{
|
|
olim24_t *m24 = (olim24_t *)priv;
|
|
uint8_t ret = 0xff;
|
|
|
|
switch (addr) {
|
|
case 0x3d4:
|
|
ret = m24->crtcreg;
|
|
break;
|
|
|
|
case 0x3d5:
|
|
ret = m24->crtc[m24->crtcreg];
|
|
break;
|
|
|
|
case 0x3da:
|
|
ret = m24->stat;
|
|
break;
|
|
}
|
|
|
|
return(ret);
|
|
}
|
|
|
|
|
|
static void
|
|
vid_write(uint32_t addr, uint8_t val, void *priv)
|
|
{
|
|
olim24_t *m24 = (olim24_t *)priv;
|
|
|
|
m24->vram[addr & 0x7FFF]=val;
|
|
m24->charbuffer[ ((int)(((m24->dispontime - m24->vidtime) * 2) / (CGACONST / 2))) & 0xfc] = val;
|
|
m24->charbuffer[(((int)(((m24->dispontime - m24->vidtime) * 2) / (CGACONST / 2))) & 0xfc) | 1] = val;
|
|
}
|
|
|
|
|
|
static uint8_t
|
|
vid_read(uint32_t addr, void *priv)
|
|
{
|
|
olim24_t *m24 = (olim24_t *)priv;
|
|
|
|
return(m24->vram[addr & 0x7FFF]);
|
|
}
|
|
|
|
|
|
static void
|
|
vid_poll(void *priv)
|
|
{
|
|
olim24_t *m24 = (olim24_t *)priv;
|
|
uint16_t ca = (m24->crtc[15] | (m24->crtc[14] << 8)) & 0x3fff;
|
|
int drawcursor;
|
|
int x, c;
|
|
int oldvc;
|
|
uint8_t chr, attr;
|
|
uint16_t dat, dat2;
|
|
int cols[4];
|
|
int col;
|
|
int oldsc;
|
|
|
|
if (!m24->linepos) {
|
|
m24->vidtime += m24->dispofftime;
|
|
m24->stat |= 1;
|
|
m24->linepos = 1;
|
|
oldsc = m24->sc;
|
|
if ((m24->crtc[8] & 3) == 3)
|
|
m24->sc = (m24->sc << 1) & 7;
|
|
if (m24->dispon) {
|
|
if (m24->displine < m24->firstline) {
|
|
m24->firstline = m24->displine;
|
|
}
|
|
m24->lastline = m24->displine;
|
|
for (c = 0; c < 8; c++) {
|
|
if ((m24->cgamode & 0x12) == 0x12) {
|
|
buffer->line[m24->displine][c] = 0;
|
|
if (m24->cgamode & 1)
|
|
buffer->line[m24->displine][c + (m24->crtc[1] << 3) + 8] = 0;
|
|
else
|
|
buffer->line[m24->displine][c + (m24->crtc[1] << 4) + 8] = 0;
|
|
} else {
|
|
buffer->line[m24->displine][c] = (m24->cgacol & 15) + 16;
|
|
if (m24->cgamode & 1)
|
|
buffer->line[m24->displine][c + (m24->crtc[1] << 3) + 8] = (m24->cgacol & 15) + 16;
|
|
else
|
|
buffer->line[m24->displine][c + (m24->crtc[1] << 4) + 8] = (m24->cgacol & 15) + 16;
|
|
}
|
|
}
|
|
if (m24->cgamode & 1) {
|
|
for (x = 0; x < m24->crtc[1]; x++) {
|
|
chr = m24->charbuffer[ x << 1];
|
|
attr = m24->charbuffer[(x << 1) + 1];
|
|
drawcursor = ((m24->ma == ca) && m24->con && m24->cursoron);
|
|
if (m24->cgamode & 0x20) {
|
|
cols[1] = (attr & 15) + 16;
|
|
cols[0] = ((attr >> 4) & 7) + 16;
|
|
if ((m24->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[m24->displine][(x << 3) + c + 8] = cols[(fontdatm[chr][((m24->sc & 7) << 1) | m24->lineff] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
|
|
} else {
|
|
for (c = 0; c < 8; c++)
|
|
buffer->line[m24->displine][(x << 3) + c + 8] = cols[(fontdatm[chr][((m24->sc & 7) << 1) | m24->lineff] & (1 << (c ^ 7))) ? 1 : 0];
|
|
}
|
|
m24->ma++;
|
|
}
|
|
} else if (!(m24->cgamode & 2)) {
|
|
for (x = 0; x < m24->crtc[1]; x++) {
|
|
chr = m24->vram[((m24->ma << 1) & 0x3fff) + m24->base];
|
|
attr = m24->vram[(((m24->ma << 1) + 1) & 0x3fff) + m24->base];
|
|
drawcursor = ((m24->ma == ca) && m24->con && m24->cursoron);
|
|
if (m24->cgamode & 0x20) {
|
|
cols[1] = (attr & 15) + 16;
|
|
cols[0] = ((attr >> 4) & 7) + 16;
|
|
if ((m24->blink & 16) && (attr & 0x80))
|
|
cols[1] = cols[0];
|
|
} else {
|
|
cols[1] = (attr & 15) + 16;
|
|
cols[0] = (attr >> 4) + 16;
|
|
}
|
|
m24->ma++;
|
|
if (drawcursor) {
|
|
for (c = 0; c < 8; c++)
|
|
buffer->line[m24->displine][(x << 4) + (c << 1) + 8] =
|
|
buffer->line[m24->displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr][((m24->sc & 7) << 1) | m24->lineff] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
|
|
} else {
|
|
for (c = 0; c < 8; c++)
|
|
buffer->line[m24->displine][(x << 4) + (c << 1) + 8] =
|
|
buffer->line[m24->displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr][((m24->sc & 7) << 1) | m24->lineff] & (1 << (c ^ 7))) ? 1 : 0];
|
|
}
|
|
}
|
|
} else if (!(m24->cgamode & 16)) {
|
|
cols[0] = (m24->cgacol & 15) | 16;
|
|
col = (m24->cgacol & 16) ? 24 : 16;
|
|
if (m24->cgamode & 4) {
|
|
cols[1] = col | 3;
|
|
cols[2] = col | 4;
|
|
cols[3] = col | 7;
|
|
} else if (m24->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 < m24->crtc[1]; x++) {
|
|
dat = (m24->vram[((m24->ma << 1) & 0x1fff) + ((m24->sc & 1) * 0x2000) + m24->base] << 8) |
|
|
m24->vram[((m24->ma << 1) & 0x1fff) + ((m24->sc & 1) * 0x2000) + 1 + m24->base];
|
|
m24->ma++;
|
|
for (c = 0; c < 8; c++) {
|
|
buffer->line[m24->displine][(x << 4) + (c << 1) + 8] =
|
|
buffer->line[m24->displine][(x << 4) + (c << 1) + 1 + 8] = cols[dat >> 14];
|
|
dat <<= 2;
|
|
}
|
|
}
|
|
} else {
|
|
if (m24->ctrl & 1) {
|
|
dat2 = ((m24->sc & 1) * 0x4000) | (m24->lineff * 0x2000);
|
|
cols[0] = 0; cols[1] = /*(m24->cgacol & 15)*/15 + 16;
|
|
} else {
|
|
dat2 = (m24->sc & 1) * 0x2000;
|
|
cols[0] = 0; cols[1] = (m24->cgacol & 15) + 16;
|
|
}
|
|
for (x = 0; x < m24->crtc[1]; x++) {
|
|
dat = (m24->vram[((m24->ma << 1) & 0x1fff) + dat2] << 8) | m24->vram[((m24->ma << 1) & 0x1fff) + dat2 + 1];
|
|
m24->ma++;
|
|
for (c = 0; c < 16; c++) {
|
|
buffer->line[m24->displine][(x << 4) + c + 8] = cols[dat >> 15];
|
|
dat <<= 1;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
cols[0] = ((m24->cgamode & 0x12) == 0x12) ? 0 : (m24->cgacol & 15) + 16;
|
|
if (m24->cgamode & 1) hline(buffer, 0, m24->displine, (m24->crtc[1] << 3) + 16, cols[0]);
|
|
else hline(buffer, 0, m24->displine, (m24->crtc[1] << 4) + 16, cols[0]);
|
|
}
|
|
|
|
if (m24->cgamode & 1)
|
|
x = (m24->crtc[1] << 3) + 16;
|
|
else
|
|
x = (m24->crtc[1] << 4) + 16;
|
|
|
|
m24->sc = oldsc;
|
|
if (m24->vc == m24->crtc[7] && !m24->sc)
|
|
m24->stat |= 8;
|
|
m24->displine++;
|
|
if (m24->displine >= 720) m24->displine = 0;
|
|
} else {
|
|
m24->vidtime += m24->dispontime;
|
|
if (m24->dispon) m24->stat &= ~1;
|
|
m24->linepos = 0;
|
|
m24->lineff ^= 1;
|
|
if (m24->lineff) {
|
|
m24->ma = m24->maback;
|
|
} else {
|
|
if (m24->vsynctime) {
|
|
m24->vsynctime--;
|
|
if (!m24->vsynctime)
|
|
m24->stat &= ~8;
|
|
}
|
|
if (m24->sc == (m24->crtc[11] & 31) || ((m24->crtc[8] & 3) == 3 && m24->sc == ((m24->crtc[11] & 31) >> 1))) {
|
|
m24->con = 0;
|
|
m24->coff = 1;
|
|
}
|
|
if (m24->vadj) {
|
|
m24->sc++;
|
|
m24->sc &= 31;
|
|
m24->ma = m24->maback;
|
|
m24->vadj--;
|
|
if (!m24->vadj) {
|
|
m24->dispon = 1;
|
|
m24->ma = m24->maback = (m24->crtc[13] | (m24->crtc[12] << 8)) & 0x3fff;
|
|
m24->sc = 0;
|
|
}
|
|
} else if (m24->sc == m24->crtc[9] || ((m24->crtc[8] & 3) == 3 && m24->sc == (m24->crtc[9] >> 1))) {
|
|
m24->maback = m24->ma;
|
|
m24->sc = 0;
|
|
oldvc = m24->vc;
|
|
m24->vc++;
|
|
m24->vc &= 127;
|
|
|
|
if (m24->vc == m24->crtc[6])
|
|
m24->dispon=0;
|
|
|
|
if (oldvc == m24->crtc[4]) {
|
|
m24->vc = 0;
|
|
m24->vadj = m24->crtc[5];
|
|
if (!m24->vadj) m24->dispon = 1;
|
|
if (!m24->vadj) m24->ma = m24->maback = (m24->crtc[13] | (m24->crtc[12] << 8)) & 0x3fff;
|
|
if ((m24->crtc[10] & 0x60) == 0x20)
|
|
m24->cursoron = 0;
|
|
else
|
|
m24->cursoron = m24->blink & 16;
|
|
}
|
|
|
|
if (m24->vc == m24->crtc[7]) {
|
|
m24->dispon = 0;
|
|
m24->displine = 0;
|
|
m24->vsynctime = (m24->crtc[3] >> 4) + 1;
|
|
if (m24->crtc[7]) {
|
|
if (m24->cgamode & 1)
|
|
x = (m24->crtc[1] << 3) + 16;
|
|
else
|
|
x = (m24->crtc[1] << 4) + 16;
|
|
m24->lastline++;
|
|
if ((x != xsize) || ((m24->lastline - m24->firstline) != ysize) || video_force_resize_get()) {
|
|
xsize = x;
|
|
ysize = m24->lastline - m24->firstline;
|
|
if (xsize < 64) xsize = 656;
|
|
if (ysize < 32) ysize = 200;
|
|
set_screen_size(xsize, ysize + 16);
|
|
|
|
if (video_force_resize_get())
|
|
video_force_resize_set(0);
|
|
}
|
|
|
|
video_blit_memtoscreen_8(0, m24->firstline - 8, 0, (m24->lastline - m24->firstline) + 16, xsize, (m24->lastline - m24->firstline) + 16);
|
|
frames++;
|
|
|
|
video_res_x = xsize - 16;
|
|
video_res_y = ysize;
|
|
if (m24->cgamode & 1) {
|
|
video_res_x /= 8;
|
|
video_res_y /= (m24->crtc[9] + 1) * 2;
|
|
video_bpp = 0;
|
|
} else if (!(m24->cgamode & 2)) {
|
|
video_res_x /= 16;
|
|
video_res_y /= (m24->crtc[9] + 1) * 2;
|
|
video_bpp = 0;
|
|
} else if (!(m24->cgamode & 16)) {
|
|
video_res_x /= 2;
|
|
video_res_y /= 2;
|
|
video_bpp = 2;
|
|
} else if (!(m24->ctrl & 1)) {
|
|
video_res_y /= 2;
|
|
video_bpp = 1;
|
|
}
|
|
}
|
|
m24->firstline = 1000;
|
|
m24->lastline = 0;
|
|
m24->blink++;
|
|
}
|
|
} else {
|
|
m24->sc++;
|
|
m24->sc &= 31;
|
|
m24->ma = m24->maback;
|
|
}
|
|
if ((m24->sc == (m24->crtc[10] & 31) || ((m24->crtc[8] & 3) == 3 && m24->sc == ((m24->crtc[10] & 31) >> 1))))
|
|
m24->con = 1;
|
|
}
|
|
if (m24->dispon && (m24->cgamode & 1)) {
|
|
for (x = 0; x < (m24->crtc[1] << 1); x++)
|
|
m24->charbuffer[x] = m24->vram[(((m24->ma << 1) + x) & 0x3fff) + m24->base];
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
speed_changed(void *priv)
|
|
{
|
|
olim24_t *m24 = (olim24_t *)priv;
|
|
|
|
recalc_timings(m24);
|
|
}
|
|
|
|
|
|
static void
|
|
kbd_poll(void *priv)
|
|
{
|
|
olim24_t *m24 = (olim24_t *)priv;
|
|
|
|
keyboard_delay += (1000LL * TIMER_USEC);
|
|
if (m24->wantirq) {
|
|
m24->wantirq = 0;
|
|
picint(2);
|
|
#if ENABLE_KEYBOARD_LOG
|
|
pclog("M24: take IRQ\n");
|
|
#endif
|
|
}
|
|
|
|
if (!(m24->status & STAT_OFULL) && key_queue_start != key_queue_end) {
|
|
#if ENABLE_KEYBOARD_LOG
|
|
pclog("Reading %02X from the key queue at %i\n",
|
|
m24->out, key_queue_start);
|
|
#endif
|
|
m24->out = key_queue[key_queue_start];
|
|
key_queue_start = (key_queue_start + 1) & 0xf;
|
|
m24->status |= STAT_OFULL;
|
|
m24->status &= ~STAT_IFULL;
|
|
m24->wantirq = 1;
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
kbd_adddata(uint8_t val)
|
|
{
|
|
key_queue[key_queue_end] = val;
|
|
key_queue_end = (key_queue_end + 1) & 0xf;
|
|
}
|
|
|
|
|
|
static void
|
|
kbd_write(uint16_t port, uint8_t val, void *priv)
|
|
{
|
|
olim24_t *m24 = (olim24_t *)priv;
|
|
|
|
#if ENABLE_KEYBOARD_LOG
|
|
pclog("M24: write %04X %02X\n", port, val);
|
|
#endif
|
|
|
|
#if 0
|
|
if (ram[8] == 0xc3) {
|
|
output = 3;
|
|
}
|
|
#endif
|
|
switch (port) {
|
|
case 0x60:
|
|
if (m24->param != m24->param_total) {
|
|
m24->params[m24->param++] = val;
|
|
if (m24->param == m24->param_total) {
|
|
switch (m24->command) {
|
|
case 0x11:
|
|
m24->mouse_mode = 0;
|
|
m24->scan[0] = m24->params[0];
|
|
m24->scan[1] = m24->params[1];
|
|
m24->scan[2] = m24->params[2];
|
|
m24->scan[3] = m24->params[3];
|
|
m24->scan[4] = m24->params[4];
|
|
m24->scan[5] = m24->params[5];
|
|
m24->scan[6] = m24->params[6];
|
|
break;
|
|
|
|
case 0x12:
|
|
m24->mouse_mode = 1;
|
|
m24->scan[0] = m24->params[0];
|
|
m24->scan[1] = m24->params[1];
|
|
m24->scan[2] = m24->params[2];
|
|
break;
|
|
|
|
default:
|
|
pclog("M24: bad keyboard command complete %02X\n", m24->command);
|
|
}
|
|
}
|
|
} else {
|
|
m24->command = val;
|
|
switch (val) {
|
|
case 0x01: /*Self-test*/
|
|
break;
|
|
|
|
case 0x05: /*Read ID*/
|
|
kbd_adddata(0x00);
|
|
break;
|
|
|
|
case 0x11:
|
|
m24->param = 0;
|
|
m24->param_total = 9;
|
|
break;
|
|
|
|
case 0x12:
|
|
m24->param = 0;
|
|
m24->param_total = 4;
|
|
break;
|
|
|
|
default:
|
|
pclog("M24: bad keyboard command %02X\n", val);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 0x61:
|
|
ppi.pb = val;
|
|
|
|
timer_process();
|
|
timer_update_outstanding();
|
|
|
|
speaker_update();
|
|
speaker_gated = val & 1;
|
|
speaker_enable = val & 2;
|
|
if (speaker_enable)
|
|
was_speaker_enable = 1;
|
|
pit_set_gate(&pit, 2, val & 1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
static uint8_t
|
|
kbd_read(uint16_t port, void *priv)
|
|
{
|
|
olim24_t *m24 = (olim24_t *)priv;
|
|
uint8_t ret = 0xff;
|
|
|
|
switch (port) {
|
|
case 0x60:
|
|
ret = m24->out;
|
|
if (key_queue_start == key_queue_end) {
|
|
m24->status &= ~STAT_OFULL;
|
|
m24->wantirq = 0;
|
|
} else {
|
|
m24->out = key_queue[key_queue_start];
|
|
key_queue_start = (key_queue_start + 1) & 0xf;
|
|
m24->status |= STAT_OFULL;
|
|
m24->status &= ~STAT_IFULL;
|
|
m24->wantirq = 1;
|
|
}
|
|
break;
|
|
|
|
case 0x61:
|
|
ret = ppi.pb;
|
|
break;
|
|
|
|
case 0x64:
|
|
ret = m24->status;
|
|
m24->status &= ~(STAT_RTIMEOUT | STAT_TTIMEOUT);
|
|
break;
|
|
|
|
default:
|
|
pclog("\nBad M24 keyboard read %04X\n", port);
|
|
}
|
|
|
|
return(ret);
|
|
}
|
|
|
|
|
|
static uint8_t
|
|
ms_poll(int x, int y, int z, int b, void *priv)
|
|
{
|
|
olim24_t *m24 = (olim24_t *)priv;
|
|
|
|
m24->x += x;
|
|
m24->y += y;
|
|
|
|
if (((key_queue_end - key_queue_start) & 0xf) > 14) return(0xff);
|
|
|
|
if ((b & 1) && !(m24->b & 1))
|
|
kbd_adddata(m24->scan[0]);
|
|
if (!(b & 1) && (m24->b & 1))
|
|
kbd_adddata(m24->scan[0] | 0x80);
|
|
m24->b = (m24->b & ~1) | (b & 1);
|
|
|
|
if (((key_queue_end - key_queue_start) & 0xf) > 14) return(0xff);
|
|
|
|
if ((b & 2) && !(m24->b & 2))
|
|
kbd_adddata(m24->scan[2]);
|
|
if (!(b & 2) && (m24->b & 2))
|
|
kbd_adddata(m24->scan[2] | 0x80);
|
|
m24->b = (m24->b & ~2) | (b & 2);
|
|
|
|
if (((key_queue_end - key_queue_start) & 0xf) > 14) return(0xff);
|
|
|
|
if ((b & 4) && !(m24->b & 4))
|
|
kbd_adddata(m24->scan[1]);
|
|
if (!(b & 4) && (m24->b & 4))
|
|
kbd_adddata(m24->scan[1] | 0x80);
|
|
m24->b = (m24->b & ~4) | (b & 4);
|
|
|
|
if (m24->mouse_mode) {
|
|
if (((key_queue_end - key_queue_start) & 0xf) > 12) return(0xff);
|
|
|
|
if (!m24->x && !m24->y) return(0xff);
|
|
|
|
m24->y = -m24->y;
|
|
|
|
if (m24->x < -127) m24->x = -127;
|
|
if (m24->x > 127) m24->x = 127;
|
|
if (m24->x < -127) m24->x = 0x80 | ((-m24->x) & 0x7f);
|
|
|
|
if (m24->y < -127) m24->y = -127;
|
|
if (m24->y > 127) m24->y = 127;
|
|
if (m24->y < -127) m24->y = 0x80 | ((-m24->y) & 0x7f);
|
|
|
|
kbd_adddata(0xfe);
|
|
kbd_adddata(m24->x);
|
|
kbd_adddata(m24->y);
|
|
|
|
m24->x = m24->y = 0;
|
|
} else {
|
|
while (m24->x < -4) {
|
|
if (((key_queue_end - key_queue_start) & 0xf) > 14)
|
|
return(0xff);
|
|
m24->x += 4;
|
|
kbd_adddata(m24->scan[3]);
|
|
}
|
|
while (m24->x > 4) {
|
|
if (((key_queue_end - key_queue_start) & 0xf) > 14)
|
|
return(0xff);
|
|
m24->x -= 4;
|
|
kbd_adddata(m24->scan[4]);
|
|
}
|
|
while (m24->y < -4) {
|
|
if (((key_queue_end - key_queue_start) & 0xf) > 14)
|
|
return(0xff);
|
|
m24->y += 4;
|
|
kbd_adddata(m24->scan[5]);
|
|
}
|
|
while (m24->y > 4) {
|
|
if (((key_queue_end - key_queue_start) & 0xf) > 14)
|
|
return(0xff);
|
|
m24->y -= 4;
|
|
kbd_adddata(m24->scan[6]);
|
|
}
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
|
|
static uint8_t
|
|
m24_read(uint16_t port, void *priv)
|
|
{
|
|
switch (port) {
|
|
case 0x66:
|
|
return 0x00;
|
|
case 0x67:
|
|
return 0x20 | 0x40 | 0x0C;
|
|
}
|
|
|
|
return(0xff);
|
|
}
|
|
|
|
|
|
device_t m24_device = {
|
|
"Olivetti M24",
|
|
0, 0,
|
|
NULL, NULL, NULL,
|
|
NULL,
|
|
speed_changed,
|
|
NULL, NULL,
|
|
NULL
|
|
};
|
|
|
|
|
|
void
|
|
machine_olim24_init(machine_t *model)
|
|
{
|
|
olim24_t *m24;
|
|
|
|
m24 = (olim24_t *)malloc(sizeof(olim24_t));
|
|
memset(m24, 0x00, sizeof(olim24_t));
|
|
|
|
machine_common_init(model);
|
|
|
|
io_sethandler(0x0066, 2, m24_read, NULL, NULL, NULL, NULL, NULL, m24);
|
|
|
|
/* Initialize the video adapter. */
|
|
m24->vram = malloc(0x8000);
|
|
overscan_x = overscan_y = 16;
|
|
mem_mapping_add(&m24->mapping, 0xb8000, 0x08000,
|
|
vid_read, NULL, NULL,
|
|
vid_write, NULL, NULL, NULL, 0, m24);
|
|
io_sethandler(0x03d0, 16, vid_in, NULL, NULL, vid_out, NULL, NULL, m24);
|
|
timer_add(vid_poll, &m24->vidtime, TIMER_ALWAYS_ENABLED, m24);
|
|
device_add(&m24_device);
|
|
|
|
/* Initialize the keyboard. */
|
|
m24->status = STAT_LOCK | STAT_CD;
|
|
m24->scan[0] = 0x1c;
|
|
m24->scan[1] = 0x53;
|
|
m24->scan[2] = 0x01;
|
|
m24->scan[3] = 0x4b;
|
|
m24->scan[4] = 0x4d;
|
|
m24->scan[5] = 0x48;
|
|
m24->scan[6] = 0x50;
|
|
io_sethandler(0x0060, 2,
|
|
kbd_read, NULL, NULL, kbd_write, NULL, NULL, m24);
|
|
io_sethandler(0x0064, 1,
|
|
kbd_read, NULL, NULL, kbd_write, NULL, NULL, m24);
|
|
keyboard_send = kbd_adddata;
|
|
keyboard_scan = 1;
|
|
timer_add(kbd_poll, &keyboard_delay, TIMER_ALWAYS_ENABLED, m24);
|
|
|
|
/* Tell mouse driver about our internal mouse. */
|
|
mouse_setpoll(ms_poll, m24);
|
|
|
|
if (joystick_type != 7)
|
|
device_add(&gameport_device);
|
|
|
|
/* FIXME: make sure this is correct?? */
|
|
nvr_at_init(8);
|
|
|
|
nmi_init();
|
|
}
|