Removing the remaining unnecessary files that should not have been committed.

This commit is contained in:
OBattler
2023-10-21 08:13:22 +02:00
parent b3bbdd4b93
commit 8184d71aa6
12 changed files with 0 additions and 11837 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,29 +0,0 @@
808x.c: In function 'execx86':
808x.c:1912:13: error: range expressions in switch statements are non-standard [-Werror=pedantic]
1912 | case 0x40 ... 0x47: /* INC r16 */
| ^~~~
808x.c:1927:13: error: range expressions in switch statements are non-standard [-Werror=pedantic]
1927 | case 0x48 ... 0x4f: /* DEC r16 */
| ^~~~
808x.c:1942:13: error: range expressions in switch statements are non-standard [-Werror=pedantic]
1942 | case 0x50 ... 0x57: /* PUSH r16 */
| ^~~~
808x.c:1947:13: error: range expressions in switch statements are non-standard [-Werror=pedantic]
1947 | case 0x58 ... 0x5f: /* POP r16 */
| ^~~~
808x.c:1952:13: error: range expressions in switch statements are non-standard [-Werror=pedantic]
1952 | case 0x60 ... 0x7f: /* JMP rel8 */
| ^~~~
808x.c:2201:13: error: range expressions in switch statements are non-standard [-Werror=pedantic]
2201 | case 0x90 ... 0x97: /* XCHG AX, r */
| ^~~~
808x.c:2482:13: error: range expressions in switch statements are non-standard [-Werror=pedantic]
2482 | case 0xb0 ... 0xb7: /* MOV r8, imm8 */
| ^~~~
808x.c:2494:13: error: range expressions in switch statements are non-standard [-Werror=pedantic]
2494 | case 0xb8 ... 0xbf: /* MOV r16, imm16 */
| ^~~~
808x.c:2766:13: error: range expressions in switch statements are non-standard [-Werror=pedantic]
2766 | case 0xd8 ... 0xdf: /* ESC - FPU instructions. */
| ^~~~
cc1.exe: all warnings being treated as errors

View File

@@ -1 +0,0 @@
gcc $1 -std=gnu17 -Wall -Wclobbered -Wbad-function-cast -Wempty-body -Wignored-qualifiers -Wmissing-field-initializers -Wmissing-parameter-type -Wold-style-declaration -Woverride-init -Wsign-compare -Wtype-limits -Wuninitialized -Wunknown-pragmas -pedantic -Werror -I../include -iquote . 2> error_log.txt

File diff suppressed because it is too large Load Diff

View File

@@ -1,150 +0,0 @@
/*
* 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.
*
* Definitions for the NS8250/16450/16550/16650/16750/16850/16950
* UART emulation.
*
*
*
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
*
* Copyright 2008-2020 Sarah Walker.
* Copyright 2016-2020 Miran Grca.
* Copyright 2017-2020 Fred N. van Kempen.
*/
#ifndef EMU_SERIAL_H
#define EMU_SERIAL_H
#define SERIAL_8250 0
#define SERIAL_8250_PCJR 1
#define SERIAL_16450 2
#define SERIAL_16550 3
#define SERIAL_16650 4
#define SERIAL_16750 5
#define SERIAL_16850 6
#define SERIAL_16950 7
#define SERIAL_FIFO_SIZE 16
/* Default settings for the standard ports. */
#define COM1_ADDR 0x03f8
#define COM1_IRQ 4
#define COM2_ADDR 0x02f8
#define COM2_IRQ 3
#define COM3_ADDR 0x03e8
#define COM3_IRQ 4
#define COM4_ADDR 0x02e8
#define COM4_IRQ 3
struct serial_device_s;
struct serial_s;
typedef struct serial_s {
uint8_t lsr;
uint8_t thr;
uint8_t mctrl;
uint8_t rcr;
uint8_t iir;
uint8_t ier;
uint8_t lcr;
uint8_t msr;
uint8_t dat;
uint8_t int_status;
uint8_t scratch;
uint8_t fcr;
uint8_t irq;
uint8_t type;
uint8_t inst;
uint8_t transmit_enabled;
uint8_t fifo_enabled;
uint8_t rcvr_fifo_len;
uint8_t bits;
uint8_t data_bits;
uint8_t baud_cycles;
uint8_t rcvr_fifo_full;
uint8_t txsr;
uint8_t out;
uint8_t msr_set;
uint8_t pad;
uint8_t irq_state;
uint8_t pad0;
uint16_t dlab;
uint16_t base_address;
uint16_t out_new;
uint16_t pad1;
uint8_t xmit_fifo_pos;
uint8_t xmit_fifo_end;
uint8_t xmit_fifo[SERIAL_FIFO_SIZE];
void *rcvr_fifo;
pc_timer_t transmit_timer;
pc_timer_t timeout_timer;
pc_timer_t receive_timer;
double clock_src;
double transmit_period;
struct serial_device_s *sd;
} serial_t;
typedef struct serial_device_s {
void (*rcr_callback)(struct serial_s *serial, void *p);
void (*dev_write)(struct serial_s *serial, void *p, uint8_t data);
void (*lcr_callback)(struct serial_s *serial, void *p, uint8_t lcr);
void (*transmit_period_callback)(struct serial_s *serial, void *p, double transmit_period);
void *priv;
serial_t *serial;
} serial_device_t;
typedef struct serial_port_s {
uint8_t enabled;
} serial_port_t;
extern serial_port_t com_ports[SERIAL_MAX];
extern serial_t *serial_attach_ex(int port,
void (*rcr_callback)(struct serial_s *serial, void *p),
void (*dev_write)(struct serial_s *serial, void *p, uint8_t data),
void (*transmit_period_callback)(struct serial_s *serial, void *p, double transmit_period),
void (*lcr_callback)(struct serial_s *serial, void *p, uint8_t data_bits),
void *priv);
#define serial_attach(port, rcr_callback, dev_write, priv) \
serial_attach_ex(port, rcr_callback, dev_write, NULL, NULL, priv);
extern void serial_remove(serial_t *dev);
extern void serial_set_type(serial_t *dev, int type);
extern void serial_setup(serial_t *dev, uint16_t addr, uint8_t irq);
extern void serial_clear_fifo(serial_t *dev);
extern void serial_write_fifo(serial_t *dev, uint8_t dat);
extern void serial_set_next_inst(int ni);
extern void serial_standalone_init(void);
extern void serial_set_clock_src(serial_t *dev, double clock_src);
extern void serial_reset_port(serial_t *dev);
extern void serial_device_timeout(void *priv);
extern void serial_set_cts(serial_t *dev, uint8_t enabled);
extern void serial_set_dsr(serial_t *dev, uint8_t enabled);
extern void serial_set_dcd(serial_t *dev, uint8_t enabled);
extern const device_t ns8250_device;
extern const device_t ns8250_pcjr_device;
extern const device_t ns16450_device;
extern const device_t ns16550_device;
extern const device_t ns16650_device;
extern const device_t ns16750_device;
extern const device_t ns16850_device;
extern const device_t ns16950_device;
#endif /*EMU_SERIAL_H*/

View File

@@ -1,194 +0,0 @@
#ifndef _TIMER_H_
#define _TIMER_H_
#include "cpu.h"
/* Maximum period, currently 1 second. */
#define MAX_USEC64 1000000ULL
#define MAX_USEC 1000000.0
#define TIMER_PROCESS 4
#define TIMER_SPLIT 2
#define TIMER_ENABLED 1
#pragma pack(push, 1)
typedef struct ts_struct_t
{
uint32_t frac;
uint32_t integer;
} ts_struct_t;
#pragma pack(pop)
typedef union ts_t {
uint64_t ts64;
ts_struct_t ts32;
} ts_t;
/*Timers are based on the CPU Time Stamp Counter. Timer timestamps are in a
32:32 fixed point format, with the integer part compared against the TSC. The
fractional part is used when advancing the timestamp to ensure a more accurate
period.
As the timer only stores 32 bits of integer timestamp, and the TSC is 64 bits,
the timer period can only be at most 0x7fffffff CPU cycles. To allow room for
(optimistic) CPU frequency growth, timer period must be at most 1 second.
When a timer callback is called, the timer has been disabled. If the timer is
to repeat, the callback must call timer_advance_u64(). This is a change from
the old timer API.*/
typedef struct pc_timer_t {
#ifdef USE_PCEM_TIMER
uint32_t ts_integer;
uint32_t ts_frac;
#else
ts_t ts;
#endif
int flags; /* The flags are defined above. */
int pad;
double period; /* This is used for large period timers to count
the microseconds and split the period. */
void (*callback)(void *priv);
void *priv;
struct pc_timer_t *prev;
struct pc_timer_t *next;
} pc_timer_t;
#ifdef __cplusplus
extern "C" {
#endif
/*Timestamp of nearest enabled timer. CPU emulation must call timer_process()
when TSC matches or exceeds this.*/
extern uint32_t timer_target;
/*Enable timer, without updating timestamp*/
extern void timer_enable(pc_timer_t *timer);
/*Disable timer*/
extern void timer_disable(pc_timer_t *timer);
/*Process any pending timers*/
extern void timer_process(void);
/*Reset timer system*/
extern void timer_close(void);
extern void timer_init(void);
/*Add new timer. If start_timer is set, timer will be enabled with a zero
timestamp - this is useful for permanently enabled timers*/
extern void timer_add(pc_timer_t *timer, void (*callback)(void *priv), void *priv, int start_timer);
/*1us in 32:32 format*/
extern uint64_t TIMER_USEC;
/*True if timer a expires before timer b*/
#define TIMER_LESS_THAN(a, b) ((int64_t) ((a)->ts.ts64 - (b)->ts.ts64) <= 0)
/*True if timer a expires before 32 bit integer timestamp b*/
#define TIMER_LESS_THAN_VAL(a, b) ((int32_t) ((a)->ts.ts32.integer - (b)) <= 0)
/*True if 32 bit integer timestamp a expires before 32 bit integer timestamp b*/
#define TIMER_VAL_LESS_THAN_VAL(a, b) ((int32_t) ((a) - (b)) <= 0)
/*Advance timer by delay, specified in 32:32 format. This should be used to
resume a recurring timer in a callback routine*/
static __inline void
timer_advance_u64(pc_timer_t *timer, uint64_t delay)
{
timer->ts.ts64 += delay;
timer_enable(timer);
}
/*Set a timer to the given delay, specified in 32:32 format. This should be used
when starting a timer*/
static __inline void
timer_set_delay_u64(pc_timer_t *timer, uint64_t delay)
{
timer->ts.ts64 = 0ULL;
timer->ts.ts32.integer = tsc;
timer->ts.ts64 += delay;
timer_enable(timer);
}
/*True if timer currently enabled*/
static __inline int
timer_is_enabled(pc_timer_t *timer)
{
return !!(timer->flags & TIMER_ENABLED);
}
/*True if timer currently on*/
static __inline int
timer_is_on(pc_timer_t *timer)
{
// return ((timer->flags & TIMER_SPLIT) || (timer->flags & TIMER_ENABLED));
return !!(timer->flags & TIMER_ENABLED);
}
/*Return integer timestamp of timer*/
static __inline uint32_t
timer_get_ts_int(pc_timer_t *timer)
{
return timer->ts.ts32.integer;
}
/*Return remaining time before timer expires, in us. If the timer has already
expired then return 0*/
static __inline uint32_t
timer_get_remaining_us(pc_timer_t *timer)
{
int64_t remaining;
if (timer->flags & TIMER_ENABLED) {
remaining = (int64_t) (timer->ts.ts64 - (uint64_t) (tsc << 32));
if (remaining < 0)
return 0;
return remaining / TIMER_USEC;
}
return 0;
}
/*Return remaining time before timer expires, in 32:32 timestamp format. If the
timer has already expired then return 0*/
static __inline uint64_t
timer_get_remaining_u64(pc_timer_t *timer)
{
int64_t remaining;
if (timer->flags & TIMER_ENABLED) {
remaining = (int64_t) (timer->ts.ts64 - (uint64_t) (tsc << 32));
if (remaining < 0)
return 0;
return remaining;
}
return 0;
}
/*Set timer callback function*/
static __inline void
timer_set_callback(pc_timer_t *timer, void (*callback)(void *priv))
{
timer->callback = callback;
}
/*Set timer private data*/
static __inline void
timer_set_p(pc_timer_t *timer, void *priv)
{
timer->priv = priv;
}
/* The API for big timer periods starts here. */
extern void timer_stop(pc_timer_t *timer);
extern void timer_on_auto(pc_timer_t *timer, double period);
#ifdef __cplusplus
}
#endif
#endif /*_TIMER_H_*/

View File

@@ -1,67 +0,0 @@
/* Copyright holders: Sarah Walker
see COPYING for more details
*/
#ifndef VIDEO_MDA_H
#define VIDEO_MDA_H
typedef struct mda_t {
mem_mapping_t mapping;
uint8_t crtc[32];
int crtcreg;
uint8_t ctrl;
uint8_t stat;
uint64_t dispontime;
uint64_t dispofftime;
pc_timer_t timer;
pc_timer_t dot_timer;
int firstline;
int lastline;
int linepos;
int displine;
int vc;
int sc;
uint16_t ma;
uint16_t maback;
int con;
int coff;
int cursoron;
int dispon;
int blink;
int vsynctime;
int vadj;
int monitor_index;
int prev_monitor_index;
uint8_t *vram;
} mda_t;
#define VIDEO_MONITOR_PROLOGUE() \
{ \
mda->prev_monitor_index = monitor_index_global; \
monitor_index_global = mda->monitor_index; \
}
#define VIDEO_MONITOR_EPILOGUE() \
{ \
monitor_index_global = mda->prev_monitor_index; \
}
void mda_init(mda_t *mda);
void mda_setcol(int chr, int blink, int fg, uint8_t cga_ink);
void mda_out(uint16_t addr, uint8_t val, void *priv);
uint8_t mda_in(uint16_t addr, void *priv);
void mda_write(uint32_t addr, uint8_t val, void *priv);
uint8_t mda_read(uint32_t addr, void *priv);
void mda_recalctimings(mda_t *mda);
void mda_poll(void *priv);
#ifdef EMU_DEVICE_H
extern const device_t mda_device;
#endif
#endif /*VIDEO_MDA_H*/

View File

@@ -1,242 +0,0 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include <86box/timer.h>
uint64_t TIMER_USEC;
uint32_t timer_target;
/*Enabled timers are stored in a linked list, with the first timer to expire at
the head.*/
pc_timer_t *timer_head = NULL;
/* Are we initialized? */
int timer_inited = 0;
static void timer_advance_ex(pc_timer_t *timer, int start);
void
timer_enable(pc_timer_t *timer)
{
pc_timer_t *timer_node = timer_head;
if (!timer_inited || (timer == NULL))
return;
if (timer->flags & TIMER_ENABLED)
timer_disable(timer);
if (timer->next || timer->prev)
fatal("timer_enable - timer->next\n");
timer->flags |= TIMER_ENABLED;
/*List currently empty - add to head*/
if (!timer_head) {
timer_head = timer;
timer->next = timer->prev = NULL;
timer_target = timer_head->ts.ts32.integer;
return;
}
if (TIMER_LESS_THAN(timer, timer_head)) {
timer->next = timer_head;
timer->prev = NULL;
timer_head->prev = timer;
timer_head = timer;
timer_target = timer_head->ts.ts32.integer;
return;
}
if (!timer_head->next) {
timer_head->next = timer;
timer->prev = timer_head;
return;
}
pc_timer_t *prev = timer_head;
timer_node = timer_head->next;
while (1) {
/*Timer expires before timer_node. Add to list in front of timer_node*/
if (TIMER_LESS_THAN(timer, timer_node)) {
timer->next = timer_node;
timer->prev = prev;
timer_node->prev = timer;
prev->next = timer;
return;
}
/*timer_node is last in the list. Add timer to end of list*/
if (!timer_node->next) {
timer_node->next = timer;
timer->prev = timer_node;
return;
}
prev = timer_node;
timer_node = timer_node->next;
}
}
void
timer_disable(pc_timer_t *timer)
{
if (!timer_inited || (timer == NULL) || !(timer->flags & TIMER_ENABLED))
return;
if (!timer->next && !timer->prev && timer != timer_head)
fatal("timer_disable - !timer->next\n");
timer->flags &= ~TIMER_ENABLED;
if (timer->prev)
timer->prev->next = timer->next;
else
timer_head = timer->next;
if (timer->next)
timer->next->prev = timer->prev;
timer->prev = timer->next = NULL;
}
void
timer_process(void)
{
pc_timer_t *timer;
if (!timer_head)
return;
while (1) {
timer = timer_head;
if (!TIMER_LESS_THAN_VAL(timer, (uint32_t) tsc))
break;
timer_head = timer->next;
if (timer_head)
timer_head->prev = NULL;
timer->next = timer->prev = NULL;
timer->flags &= ~TIMER_ENABLED;
if (timer->flags & TIMER_SPLIT)
timer_advance_ex(timer, 0); /* We're splitting a > 1 s period into multiple <= 1 s periods. */
else if (timer->callback != NULL) /* Make sure it's no NULL, so that we can have a NULL callback when no operation is needed. */
timer->callback(timer->priv);
}
timer_target = timer_head->ts.ts32.integer;
}
void
timer_close(void)
{
pc_timer_t *t = timer_head;
pc_timer_t *r;
/* Set all timers' prev and next to NULL so it is assured that
timers that are not in malloc'd structs don't keep pointing
to timers that may be in malloc'd structs. */
while (t != NULL) {
r = t;
r->prev = r->next = NULL;
t = r->next;
}
timer_head = NULL;
timer_inited = 0;
}
void
timer_init(void)
{
timer_target = 0ULL;
tsc = 0;
timer_inited = 1;
}
void
timer_add(pc_timer_t *timer, void (*callback)(void *priv), void *priv, int start_timer)
{
memset(timer, 0, sizeof(pc_timer_t));
timer->callback = callback;
timer->priv = priv;
timer->flags = 0;
timer->prev = timer->next = NULL;
if (start_timer)
timer_set_delay_u64(timer, 0);
}
/* The API for big timer periods starts here. */
void
timer_stop(pc_timer_t *timer)
{
if (!timer_inited || (timer == NULL))
return;
timer->period = 0.0;
timer_disable(timer);
timer->flags &= ~TIMER_SPLIT;
}
static void
timer_do_period(pc_timer_t *timer, uint64_t period, int start)
{
if (!timer_inited || (timer == NULL))
return;
if (start)
timer_set_delay_u64(timer, period);
else
timer_advance_u64(timer, period);
}
void
timer_advance_ex(pc_timer_t *timer, int start)
{
if (!timer_inited || (timer == NULL))
return;
if (timer->period > MAX_USEC) {
timer_do_period(timer, MAX_USEC64 * TIMER_USEC, start);
timer->period -= MAX_USEC;
timer->flags |= TIMER_SPLIT;
} else {
if (timer->period > 0.0)
timer_do_period(timer, (uint64_t) (timer->period * ((double) TIMER_USEC)), start);
else
timer_disable(timer);
timer->period = 0.0;
timer->flags &= ~TIMER_SPLIT;
}
}
static void
timer_on(pc_timer_t *timer, double period, int start)
{
if (!timer_inited || (timer == NULL))
return;
timer->period = period;
timer_advance_ex(timer, start);
}
void
timer_on_auto(pc_timer_t *timer, double period)
{
if (!timer_inited || (timer == NULL))
return;
if (period > 0.0) {
// timer_on(timer, period, !(timer->flags & TIMER_PROCESS) && (timer->period <= 0.0));
timer->period = period;
timer_advance_ex(timer, !(timer->flags & TIMER_PROCESS) && (timer->period <= 0.0));
} else
timer_stop(timer);
}

View File

@@ -1,701 +0,0 @@
/*
* 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 old and new IBM CGA graphics cards.
*
*
*
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2019 Sarah Walker.
* Copyright 2016-2019 Miran Grca.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include <math.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/io.h>
#include <86box/timer.h>
#include <86box/pit.h>
#include <86box/mem.h>
#include <86box/rom.h>
#include <86box/device.h>
#include <86box/video.h>
#include <86box/vid_cga.h>
#include <86box/vid_cga_comp.h>
#define CGA_RGB 0
#define CGA_COMPOSITE 1
#define COMPOSITE_OLD 0
#define COMPOSITE_NEW 1
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 video_timings_t timing_cga = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 };
void cga_recalctimings(cga_t *cga);
void
cga_out(uint16_t addr, uint8_t val, void *p)
{
cga_t *cga = (cga_t *) p;
uint8_t old;
if ((addr >= 0x3d0) && (addr <= 0x3d7))
addr = (addr & 0xff9) | 0x004;
switch (addr) {
case 0x3D4:
cga->crtcreg = val & 31;
return;
case 0x3D5:
old = cga->crtc[cga->crtcreg];
cga->crtc[cga->crtcreg] = val & crtcmask[cga->crtcreg];
if (old != val) {
if ((cga->crtcreg < 0xe) || (cga->crtcreg > 0x10)) {
cga->fullchange = changeframecount;
cga_recalctimings(cga);
}
}
return;
case 0x3D8:
old = cga->cgamode;
cga->cgamode = val;
if (old ^ val) {
if ((old ^ val) & 0x07)
update_cga16_color(val);
cga_recalctimings(cga);
}
return;
case 0x3D9:
old = cga->cgacol;
cga->cgacol = val;
if (old ^ val)
cga_recalctimings(cga);
return;
}
}
uint8_t
cga_in(uint16_t addr, void *p)
{
cga_t *cga = (cga_t *) p;
uint8_t ret = 0xff;
if ((addr >= 0x3d0) && (addr <= 0x3d7))
addr = (addr & 0xff9) | 0x004;
switch (addr) {
case 0x3D4:
ret = cga->crtcreg;
break;
case 0x3D5:
ret = cga->crtc[cga->crtcreg];
break;
case 0x3DA:
ret = cga->cgastat;
break;
}
return ret;
}
void
cga_pravetz_out(uint16_t addr, uint8_t val, void *p)
{
cga_t *cga = (cga_t *) p;
cga->fontbase = (((unsigned int) val) << 8);
}
uint8_t
cga_pravetz_in(uint16_t addr, void *p)
{
cga_t *cga = (cga_t *) p;
return (cga->fontbase >> 8);
}
void
cga_waitstates(void *p)
{
cga_t *cga = (cga_t *) p;
int ws_array[16] = { 3, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8 };
int ws;
int q_array[16] = { 5, 5, 4, 4, 4, 3, 8, 8, 8, 7, 7, 7, 6, 6, 6, 5 };
int q;
if (is286) {
ws = ws_array[cycles & 0xf];
cycles -= ws;
} else {
q = 15 - (((int) (timer_get_remaining_u64(&cga->q_timer) >> 32ULL)) & 0x0f);
cycles -= q_array[q];
// pclog("Subtracting %i cycles at index %i\n", q_array[q], q);
}
}
void
cga_write(uint32_t addr, uint8_t val, void *p)
{
cga_t *cga = (cga_t *) p;
cga->vram[addr & 0x3fff] = val;
if (cga->snow_enabled) {
int offset = ((timer_get_remaining_u64(&cga->timer) / CGACONST) * 2) & 0xfc;
cga->charbuffer[offset] = cga->vram[addr & 0x3fff];
cga->charbuffer[offset | 1] = cga->vram[addr & 0x3fff];
}
cga_waitstates(cga);
}
uint8_t
cga_read(uint32_t addr, void *p)
{
cga_t *cga = (cga_t *) p;
cga_waitstates(cga);
if (cga->snow_enabled) {
int offset = ((timer_get_remaining_u64(&cga->timer) / CGACONST) * 2) & 0xfc;
cga->charbuffer[offset] = cga->vram[addr & 0x3fff];
cga->charbuffer[offset | 1] = cga->vram[addr & 0x3fff];
}
return cga->vram[addr & 0x3fff];
}
void
cga_recalctimings(cga_t *cga)
{
double disptime;
double _dispontime;
double _dispofftime;
if (cga->cgamode & 1) {
disptime = (double) (cga->crtc[0] + 1);
_dispontime = (double) cga->crtc[1];
} else {
disptime = (double) ((cga->crtc[0] + 1) << 1);
_dispontime = (double) (cga->crtc[1] << 1);
}
_dispofftime = disptime - _dispontime;
_dispontime = _dispontime * CGACONST;
_dispofftime = _dispofftime * CGACONST;
cga->dispontime = (uint64_t) (_dispontime);
cga->dispofftime = (uint64_t) (_dispofftime);
}
void
cga_q_tick(void *p)
{
cga_t *cga = (cga_t *) p;
timer_advance_u64(&cga->q_timer, CGACONST << 1);
}
void
cga_poll(void *p)
{
cga_t *cga = (cga_t *) p;
uint16_t ca = (cga->crtc[15] | (cga->crtc[14] << 8)) & 0x3fff;
int drawcursor;
int x;
int c;
int xs_temp;
int ys_temp;
int oldvc;
uint8_t chr;
uint8_t attr;
uint8_t border;
uint16_t dat;
int cols[4];
int col;
int oldsc;
if (!cga->linepos) {
timer_advance_u64(&cga->timer, cga->dispofftime);
cga->cgastat |= 1;
cga->linepos = 1;
oldsc = cga->sc;
if ((cga->crtc[8] & 3) == 3)
cga->sc = ((cga->sc << 1) + cga->oddeven) & 7;
if (cga->cgadispon) {
if (cga->displine < cga->firstline) {
cga->firstline = cga->displine;
video_wait_for_buffer();
}
cga->lastline = cga->displine;
for (c = 0; c < 8; c++) {
if ((cga->cgamode & 0x12) == 0x12) {
buffer32->line[cga->displine << 1][c] = buffer32->line[(cga->displine << 1) + 1][c] = 0;
if (cga->cgamode & 1) {
buffer32->line[cga->displine << 1][c + (cga->crtc[1] << 3) + 8] = buffer32->line[(cga->displine << 1) + 1][c + (cga->crtc[1] << 3) + 8] = 0;
} else {
buffer32->line[cga->displine << 1][c + (cga->crtc[1] << 4) + 8] = buffer32->line[(cga->displine << 1) + 1][c + (cga->crtc[1] << 4) + 8] = 0;
}
} else {
buffer32->line[cga->displine << 1][c] = buffer32->line[(cga->displine << 1) + 1][c] = (cga->cgacol & 15) + 16;
if (cga->cgamode & 1) {
buffer32->line[cga->displine << 1][c + (cga->crtc[1] << 3) + 8] = buffer32->line[(cga->displine << 1) + 1][c + (cga->crtc[1] << 3) + 8] = (cga->cgacol & 15) + 16;
} else {
buffer32->line[cga->displine << 1][c + (cga->crtc[1] << 4) + 8] = buffer32->line[(cga->displine << 1) + 1][c + (cga->crtc[1] << 4) + 8] = (cga->cgacol & 15) + 16;
}
}
}
if (cga->cgamode & 1) {
for (x = 0; x < cga->crtc[1]; x++) {
if (cga->cgamode & 8) {
chr = cga->charbuffer[x << 1];
attr = cga->charbuffer[(x << 1) + 1];
} else
chr = attr = 0;
drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron);
cols[1] = (attr & 15) + 16;
if (cga->cgamode & 0x20) {
cols[0] = ((attr >> 4) & 7) + 16;
if ((cga->cgablink & 8) && (attr & 0x80) && !cga->drawcursor)
cols[1] = cols[0];
} else
cols[0] = (attr >> 4) + 16;
if (drawcursor) {
for (c = 0; c < 8; c++) {
buffer32->line[cga->displine << 1][(x << 3) + c + 8] = buffer32->line[(cga->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
}
} else {
for (c = 0; c < 8; c++) {
buffer32->line[cga->displine << 1][(x << 3) + c + 8] = buffer32->line[(cga->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
}
}
cga->ma++;
}
} else if (!(cga->cgamode & 2)) {
for (x = 0; x < cga->crtc[1]; x++) {
if (cga->cgamode & 8) {
chr = cga->vram[(cga->ma << 1) & 0x3fff];
attr = cga->vram[((cga->ma << 1) + 1) & 0x3fff];
} else
chr = attr = 0;
drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron);
cols[1] = (attr & 15) + 16;
if (cga->cgamode & 0x20) {
cols[0] = ((attr >> 4) & 7) + 16;
if ((cga->cgablink & 8) && (attr & 0x80))
cols[1] = cols[0];
} else
cols[0] = (attr >> 4) + 16;
cga->ma++;
if (drawcursor) {
for (c = 0; c < 8; c++) {
buffer32->line[cga->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[cga->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(cga->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[(cga->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
}
} else {
for (c = 0; c < 8; c++) {
buffer32->line[cga->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[cga->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(cga->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[(cga->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
}
}
}
} else if (!(cga->cgamode & 16)) {
cols[0] = (cga->cgacol & 15) | 16;
col = (cga->cgacol & 16) ? 24 : 16;
if (cga->cgamode & 4) {
cols[1] = col | 3; /* Cyan */
cols[2] = col | 4; /* Red */
cols[3] = col | 7; /* White */
} else if (cga->cgacol & 32) {
cols[1] = col | 3; /* Cyan */
cols[2] = col | 5; /* Magenta */
cols[3] = col | 7; /* White */
} else {
cols[1] = col | 2; /* Green */
cols[2] = col | 4; /* Red */
cols[3] = col | 6; /* Yellow */
}
for (x = 0; x < cga->crtc[1]; x++) {
if (cga->cgamode & 8)
dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1];
else
dat = 0;
cga->ma++;
for (c = 0; c < 8; c++) {
buffer32->line[cga->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[cga->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(cga->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[(cga->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[dat >> 14];
dat <<= 2;
}
}
} else {
cols[0] = 0;
cols[1] = (cga->cgacol & 15) + 16;
for (x = 0; x < cga->crtc[1]; x++) {
if (cga->cgamode & 8)
dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1];
else
dat = 0;
cga->ma++;
for (c = 0; c < 16; c++) {
buffer32->line[cga->displine << 1][(x << 4) + c + 8] = buffer32->line[(cga->displine << 1) + 1][(x << 4) + c + 8] = cols[dat >> 15];
dat <<= 1;
}
}
}
} else {
cols[0] = ((cga->cgamode & 0x12) == 0x12) ? 0 : (cga->cgacol & 15) + 16;
if (cga->cgamode & 1) {
hline(buffer32, 0, (cga->displine << 1), ((cga->crtc[1] << 3) + 16) << 2, cols[0]);
hline(buffer32, 0, (cga->displine << 1) + 1, ((cga->crtc[1] << 3) + 16) << 2, cols[0]);
} else {
hline(buffer32, 0, (cga->displine << 1), ((cga->crtc[1] << 4) + 16) << 2, cols[0]);
hline(buffer32, 0, (cga->displine << 1) + 1, ((cga->crtc[1] << 4) + 16) << 2, cols[0]);
}
}
if (cga->cgamode & 1)
x = (cga->crtc[1] << 3) + 16;
else
x = (cga->crtc[1] << 4) + 16;
if (cga->composite) {
border = ((cga->cgamode & 0x12) == 0x12) ? 0 : (cga->cgacol & 15);
Composite_Process(cga->cgamode, border, x >> 2, buffer32->line[cga->displine << 1]);
Composite_Process(cga->cgamode, border, x >> 2, buffer32->line[(cga->displine << 1) + 1]);
} else {
video_process_8(x, cga->displine << 1);
video_process_8(x, (cga->displine << 1) + 1);
}
cga->sc = oldsc;
if (cga->vc == cga->crtc[7] && !cga->sc)
cga->cgastat |= 8;
cga->displine++;
if (cga->displine >= 360)
cga->displine = 0;
} else {
timer_advance_u64(&cga->timer, cga->dispontime);
cga->linepos = 0;
if (cga->vsynctime) {
cga->vsynctime--;
if (!cga->vsynctime)
cga->cgastat &= ~8;
}
if (cga->sc == (cga->crtc[11] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[11] & 31) >> 1))) {
cga->con = 0;
cga->coff = 1;
}
if ((cga->crtc[8] & 3) == 3 && cga->sc == (cga->crtc[9] >> 1))
cga->maback = cga->ma;
if (cga->vadj) {
cga->sc++;
cga->sc &= 31;
cga->ma = cga->maback;
cga->vadj--;
if (!cga->vadj) {
cga->cgadispon = 1;
cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff;
cga->sc = 0;
}
} else if (cga->sc == cga->crtc[9]) {
cga->maback = cga->ma;
cga->sc = 0;
oldvc = cga->vc;
cga->vc++;
cga->vc &= 127;
if (cga->vc == cga->crtc[6])
cga->cgadispon = 0;
if (oldvc == cga->crtc[4]) {
cga->vc = 0;
cga->vadj = cga->crtc[5];
if (!cga->vadj) {
cga->cgadispon = 1;
cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff;
}
switch (cga->crtc[10] & 0x60) {
case 0x20:
cga->cursoron = 0;
break;
case 0x60:
cga->cursoron = cga->cgablink & 0x10;
break;
default:
cga->cursoron = cga->cgablink & 0x08;
break;
}
}
if (cga->vc == cga->crtc[7]) {
cga->cgadispon = 0;
cga->displine = 0;
cga->vsynctime = 16;
if (cga->crtc[7]) {
if (cga->cgamode & 1)
x = (cga->crtc[1] << 3) + 16;
else
x = (cga->crtc[1] << 4) + 16;
cga->lastline++;
xs_temp = x;
ys_temp = (cga->lastline - cga->firstline) << 1;
if ((xs_temp > 0) && (ys_temp > 0)) {
if (xs_temp < 64)
xs_temp = 656;
if (ys_temp < 32)
ys_temp = 400;
if (!enable_overscan)
xs_temp -= 16;
if ((cga->cgamode & 8) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) {
xsize = xs_temp;
ysize = ys_temp;
set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0));
if (video_force_resize_get())
video_force_resize_set(0);
}
if (enable_overscan) {
video_blit_memtoscreen(0, (cga->firstline - 4) << 1,
xsize, ((cga->lastline - cga->firstline) + 8) << 1);
} else {
video_blit_memtoscreen(8, cga->firstline << 1,
xsize, (cga->lastline - cga->firstline) << 1);
}
}
frames++;
video_res_x = xsize;
video_res_y = ysize;
if (cga->cgamode & 1) {
video_res_x /= 8;
video_res_y /= cga->crtc[9] + 1;
video_bpp = 0;
} else if (!(cga->cgamode & 2)) {
video_res_x /= 16;
video_res_y /= cga->crtc[9] + 1;
video_bpp = 0;
} else if (!(cga->cgamode & 16)) {
video_res_x /= 2;
video_bpp = 2;
} else
video_bpp = 1;
}
cga->firstline = 1000;
cga->lastline = 0;
cga->cgablink++;
cga->oddeven ^= 1;
}
} else {
cga->sc++;
cga->sc &= 31;
cga->ma = cga->maback;
}
if (cga->cgadispon)
cga->cgastat &= ~1;
if (cga->sc == (cga->crtc[10] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[10] & 31) >> 1)))
cga->con = 1;
if (cga->cgadispon && (cga->cgamode & 1)) {
for (x = 0; x < (cga->crtc[1] << 1); x++)
cga->charbuffer[x] = cga->vram[((cga->ma << 1) + x) & 0x3fff];
}
}
}
void
cga_init(cga_t *cga)
{
timer_add(&cga->timer, cga_poll, cga, 1);
cga->composite = 0;
}
void *
cga_standalone_init(const device_t *info)
{
int display_type;
cga_t *cga = malloc(sizeof(cga_t));
memset(cga, 0, sizeof(cga_t));
video_inform(VIDEO_FLAG_TYPE_CGA, &timing_cga);
display_type = device_get_config_int("display_type");
cga->composite = (display_type != CGA_RGB);
cga->revision = device_get_config_int("composite_type");
cga->snow_enabled = device_get_config_int("snow_enabled");
cga->vram = malloc(0x4000);
cga_comp_init(cga->revision);
timer_add(&cga->timer, cga_poll, cga, 1);
if (!is286)
timer_add(&cga->q_timer, cga_q_tick, cga, 1);
mem_mapping_add(&cga->mapping, 0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL /*cga->vram*/, MEM_MAPPING_EXTERNAL, cga);
io_sethandler(0x03d0, 0x0010, cga_in, NULL, NULL, cga_out, NULL, NULL, cga);
overscan_x = overscan_y = 16;
cga->rgb_type = device_get_config_int("rgb_type");
cga_palette = (cga->rgb_type << 1);
cgapal_rebuild();
update_cga16_color(cga->cgamode);
return cga;
}
void *
cga_pravetz_init(const device_t *info)
{
cga_t *cga = cga_standalone_init(info);
loadfont("roms/video/cga/PRAVETZ-VDC2.BIN", 10);
io_removehandler(0x03dd, 0x0001, cga_in, NULL, NULL, cga_out, NULL, NULL, cga);
io_sethandler(0x03dd, 0x0001, cga_pravetz_in, NULL, NULL, cga_pravetz_out, NULL, NULL, cga);
cga->fontbase = 0x0300;
return cga;
}
void
cga_close(void *p)
{
cga_t *cga = (cga_t *) p;
free(cga->vram);
free(cga);
}
void
cga_speed_changed(void *p)
{
cga_t *cga = (cga_t *) p;
cga_recalctimings(cga);
}
// clang-format off
const device_config_t cga_config[] = {
{
.name = "display_type",
.description = "Display type",
.type = CONFIG_SELECTION,
.default_int = CGA_RGB,
.selection = {
{
.description = "RGB",
.value = CGA_RGB
},
{
.description = "Composite",
.value = CGA_COMPOSITE
},
{
.description = ""
}
}
},
{
.name = "composite_type",
.description = "Composite type",
.type = CONFIG_SELECTION,
.default_int = COMPOSITE_OLD,
.selection = {
{
.description = "Old",
.value = COMPOSITE_OLD
},
{
.description = "New",
.value = COMPOSITE_NEW
},
{
.description = ""
}
}
},
{
.name = "rgb_type",
.description = "RGB type",
.type = CONFIG_SELECTION,
.default_int = 0,
.selection = {
{
.description = "Color",
.value = 0
},
{
.description = "Green Monochrome",
.value = 1
},
{
.description = "Amber Monochrome",
.value = 2
},
{
.description = "Gray Monochrome",
.value = 3
},
{
.description = "Color (no brown)",
.value = 4
},
{
.description = ""
}
}
},
{
.name = "snow_enabled",
.description = "Snow emulation",
.type = CONFIG_BINARY,
.default_int = 1
},
{
.type = CONFIG_END
}
};
// clang-format on
const device_t cga_device = {
.name = "CGA",
.internal_name = "cga",
.flags = DEVICE_ISA,
.local = 0,
.init = cga_standalone_init,
.close = cga_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = cga_speed_changed,
.force_redraw = NULL,
.config = cga_config
};
const device_t cga_pravetz_device = {
.name = "Pravetz VDC-2",
.internal_name = "cga_pravetz",
.flags = DEVICE_ISA,
.local = 0,
.init = cga_pravetz_init,
.close = cga_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = cga_speed_changed,
.force_redraw = NULL,
.config = cga_config
};

View File

@@ -1,519 +0,0 @@
/*
* 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.
*
* MDA emulation.
*
*
*
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2019 Sarah Walker.
* Copyright 2016-2019 Miran Grca.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include <86box/86box.h>
#include <86box/io.h>
#include <86box/timer.h>
#include <86box/lpt.h>
#include <86box/pit.h>
#include <86box/mem.h>
#include <86box/rom.h>
#include <86box/device.h>
#include <86box/video.h>
#include <86box/vid_mda.h>
#include <86box/plat_unused.h>
static int mdacols[256][2][2];
static video_timings_t timing_mda = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 };
static double dot_clock = 0.0;
void mda_recalctimings(mda_t *mda);
void
mda_out(uint16_t addr, uint8_t val, void *priv)
{
mda_t *mda = (mda_t *) priv;
// pclog("[W] %04X = %02X\n", addr, val);
switch (addr) {
case 0x3b0:
case 0x3b2:
case 0x3b4:
case 0x3b6:
mda->crtcreg = val & 31;
return;
case 0x3b1:
case 0x3b3:
case 0x3b5:
case 0x3b7:
mda->crtc[mda->crtcreg] = val;
#if 0
if (mda->crtc[10] == 6 && mda->crtc[11] == 7) /*Fix for Generic Turbo XT BIOS, which sets up cursor registers wrong*/
{
mda->crtc[10] = 0xb;
mda->crtc[11] = 0xc;
}
#endif
mda_recalctimings(mda);
return;
case 0x3b8:
mda->ctrl = val;
return;
default:
break;
}
}
uint8_t
mda_in(uint16_t addr, void *priv)
{
const mda_t *mda = (mda_t *) priv;
uint8_t ret = 0xff;
switch (addr) {
case 0x3b0:
case 0x3b2:
case 0x3b4:
case 0x3b6:
ret = mda->crtcreg;
break;
case 0x3b1:
case 0x3b3:
case 0x3b5:
case 0x3b7:
ret = mda->crtc[mda->crtcreg];
break;
case 0x3ba:
ret = mda->stat;
// if (mda->ctrl & 0x08)
// ret |= (mda->stat & 0x80) ? 0x08 : 0x00;
// return mda->stat | 0xF0;
break;
default:
break;
}
// pclog("[R] %04X = %02X\n", addr, ret);
return ret;
}
void
mda_write(uint32_t addr, uint8_t val, void *priv)
{
mda_t *mda = (mda_t *) priv;
mda->vram[addr & 0xfff] = val;
}
uint8_t
mda_read(uint32_t addr, void *priv)
{
const mda_t *mda = (mda_t *) priv;
return mda->vram[addr & 0xfff];
}
void
mda_recalctimings(mda_t *mda)
{
double _dispontime;
double _dispofftime;
double disptime;
disptime = mda->crtc[0] + 1;
_dispontime = mda->crtc[1] + 1;
_dispofftime = disptime - _dispontime;
_dispontime *= MDACONST;
_dispofftime *= MDACONST;
mda->dispontime = (uint64_t) (_dispontime);
mda->dispofftime = (uint64_t) (_dispofftime);
dot_clock = ((double) MDACONST) / 9.0;
}
void
mda_dot_poll(void *priv)
{
mda_t *mda = (mda_t *) priv;
uint16_t ca = (mda->crtc[15] | (mda->crtc[14] << 8)) & 0x3fff;
int drawcursor;
int blink;
timer_advance_u64(&mda->dot_timer, (uint64_t) dot_clock);
static uint8_t chr;
static uint8_t attr;
static uint8_t color;
static uint16_t dot = 0x0008;
static uint16_t ch = 0x0000;
static uint16_t line = 0x0000;
static uint16_t sc = 0x0000;
static int sctotal;
static int vtotal;
static int hslast;
static int vslast;
static int ma = 0x000;
sctotal = ((int) mda->crtc[0x09]) + 1;
vtotal = (((int) mda->crtc[0x04]) + ((int) mda->crtc[0x05])) * sctotal;
hslast = ((int) mda->crtc[0x02]) + ((int) mda->crtc[0x03]) - 1;
vslast = ((int) mda->crtc[0x07]) + 16 - 1;
chr = mda->vram[ma & 0xfff];
attr = mda->vram[(ma + 1) & 0xfff];
drawcursor = (mda->ctrl & 0x08) ? ((ma == ca) && mda->con && mda->cursoron) : 0x00;
blink = (mda->ctrl & 0x08) ? ((mda->blink & 16) && (mda->ctrl & 0x20) &&
(attr & 0x80) && !drawcursor) : 0x00;
if ((mda->sc == 12) && ((attr & 7) == 1))
color = mdacols[attr][blink][1];
else {
if (dot == 0) {
if ((chr & ~0x1f) == 0xc0)
color = mdacols[attr][blink][fontdatm[chr][sc] & 1];
else
color = mdacols[attr][blink][0];
} else
color = mdacols[attr][blink][(fontdatm[chr][sc] & (1 << (dot - 1))) ? 1 : 0];
}
if (drawcursor)
color ^= mdacols[attr][0][1];
if (!(mda->ctrl & 0x08) || !(mda->stat & 0x81) || (ch > mda->crtc[1]) || (line > mda->crtc[6]))
mda->stat &= 0xe7;
else
mda->stat = (mda->stat & 0xe7) | ((color & 0x01) << 3) | ((color & 0x08) << 1);
dot--;
if (dot == 0xffff) {
dot = 8;
if (ch == mda->crtc[0x00]) {
ch = 0;
line++;
if (line == vtotal)
line = 0;
sc++;
if (sc == sctotal)
sc = 0;
} else
ch++;
}
if (ch >= mda->crtc[0x02])
mda->stat &= 0xfe;
else if ((hslast >= mda->crtc[0x02]) && (ch >= mda->crtc[0x02]) && (ch <= hslast))
mda->stat &= 0xfe;
else if ((hslast < mda->crtc[0x02]) && (ch <= hslast))
mda->stat &= 0xfe;
else
mda->stat |= 0x01;
if (line >= mda->crtc[0x07])
mda->stat &= 0x7f;
else if ((vslast >= mda->crtc[0x07]) && (line >= mda->crtc[0x07]) && (line <= vslast))
mda->stat &= 0x7f;
else if ((vslast < mda->crtc[0x07]) && (line <= vslast))
mda->stat &= 0x7f;
else
mda->stat |= 0x80;
ma += 2;
if (ma > 0xfff)
ma = 0;
if (!(mda->stat & 0x81))
ma = 0;
}
void
mda_poll(void *priv)
{
mda_t *mda = (mda_t *) priv;
uint16_t ca = (mda->crtc[15] | (mda->crtc[14] << 8)) & 0x3fff;
int drawcursor;
int x;
int c;
int oldvc;
uint8_t chr;
uint8_t attr;
int oldsc;
int blink;
VIDEO_MONITOR_PROLOGUE()
if (!mda->linepos) {
timer_advance_u64(&mda->timer, mda->dispofftime);
// mda->stat |= 1;
mda->linepos = 1;
oldsc = mda->sc;
if ((mda->crtc[8] & 3) == 3)
mda->sc = (mda->sc << 1) & 7;
if (mda->dispon) {
if (mda->displine < mda->firstline) {
mda->firstline = mda->displine;
video_wait_for_buffer();
}
mda->lastline = mda->displine;
for (x = 0; x < mda->crtc[1]; x++) {
chr = (mda->ctrl & 0x08) ? mda->vram[(mda->ma << 1) & 0xfff] : 0x00;
attr = (mda->ctrl & 0x08) ? mda->vram[((mda->ma << 1) + 1) & 0xfff] : 0x00;
drawcursor = (mda->ctrl & 0x08) ? ((mda->ma == ca) && mda->con && mda->cursoron) : 0x00;
blink = (mda->ctrl & 0x08) ? ((mda->blink & 16) && (mda->ctrl & 0x20) &&
(attr & 0x80) && !drawcursor) : 0x00;
if (mda->sc == 12 && ((attr & 7) == 1)) {
for (c = 0; c < 9; c++)
buffer32->line[mda->displine][(x * 9) + c] = mdacols[attr][blink][1];
} else {
for (c = 0; c < 8; c++)
buffer32->line[mda->displine][(x * 9) + c] = mdacols[attr][blink][(fontdatm[chr][mda->sc] & (1 << (c ^ 7))) ? 1 : 0];
if ((chr & ~0x1f) == 0xc0)
buffer32->line[mda->displine][(x * 9) + 8] = mdacols[attr][blink][fontdatm[chr][mda->sc] & 1];
else
buffer32->line[mda->displine][(x * 9) + 8] = mdacols[attr][blink][0];
}
mda->ma++;
if (drawcursor) {
for (c = 0; c < 9; c++)
buffer32->line[mda->displine][(x * 9) + c] ^= mdacols[attr][0][1];
}
}
video_process_8(mda->crtc[1] * 9, mda->displine);
}
mda->sc = oldsc;
// if (mda->vc == mda->crtc[7] && !mda->sc) {
// mda->stat |= 0x80;
// }
mda->displine++;
if (mda->displine >= 500)
mda->displine = 0;
} else {
timer_advance_u64(&mda->timer, mda->dispontime);
// if (mda->dispon)
// mda->stat &= ~1;
mda->linepos = 0;
if (mda->vsynctime) {
mda->vsynctime--;
// if (!mda->vsynctime) {
// mda->stat &= ~0x80;
// }
}
if (mda->sc == (mda->crtc[11] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[11] & 31) >> 1))) {
mda->con = 0;
mda->coff = 1;
}
if (mda->vadj) {
mda->sc++;
mda->sc &= 31;
mda->ma = mda->maback;
mda->vadj--;
if (!mda->vadj) {
mda->dispon = 1;
mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff;
mda->sc = 0;
}
} else if (mda->sc == mda->crtc[9] || ((mda->crtc[8] & 3) == 3 && mda->sc == (mda->crtc[9] >> 1))) {
mda->maback = mda->ma;
mda->sc = 0;
oldvc = mda->vc;
mda->vc++;
mda->vc &= 127;
if (mda->vc == mda->crtc[6])
mda->dispon = 0;
if (oldvc == mda->crtc[4]) {
mda->vc = 0;
mda->vadj = mda->crtc[5];
if (!mda->vadj)
mda->dispon = 1;
if (!mda->vadj)
mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff;
if ((mda->crtc[10] & 0x60) == 0x20)
mda->cursoron = 0;
else
mda->cursoron = mda->blink & 16;
}
if (mda->vc == mda->crtc[7]) {
mda->dispon = 0;
mda->displine = 0;
mda->vsynctime = 16;
if (mda->crtc[7]) {
x = mda->crtc[1] * 9;
mda->lastline++;
if ((x != xsize) || ((mda->lastline - mda->firstline) != ysize) || video_force_resize_get()) {
xsize = x;
ysize = mda->lastline - mda->firstline;
if (xsize < 64)
xsize = 656;
if (ysize < 32)
ysize = 200;
set_screen_size(xsize, ysize);
if (video_force_resize_get())
video_force_resize_set(0);
}
video_blit_memtoscreen(0, mda->firstline, xsize, ysize);
frames++;
video_res_x = mda->crtc[1];
video_res_y = mda->crtc[6];
video_bpp = 0;
}
mda->firstline = 1000;
mda->lastline = 0;
mda->blink++;
}
} else {
mda->sc++;
mda->sc &= 31;
mda->ma = mda->maback;
}
if (mda->sc == (mda->crtc[10] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[10] & 31) >> 1))) {
mda->con = 1;
}
}
VIDEO_MONITOR_EPILOGUE();
}
void
mda_init(mda_t *mda)
{
for (uint16_t c = 0; c < 256; c++) {
mdacols[c][0][0] = mdacols[c][1][0] = mdacols[c][1][1] = 16;
if (c & 8)
mdacols[c][0][1] = 15 + 16;
else
mdacols[c][0][1] = 7 + 16;
}
mdacols[0x70][0][1] = 16;
mdacols[0x70][0][0] = mdacols[0x70][1][0] = mdacols[0x70][1][1] = 16 + 15;
mdacols[0xF0][0][1] = 16;
mdacols[0xF0][0][0] = mdacols[0xF0][1][0] = mdacols[0xF0][1][1] = 16 + 15;
mdacols[0x78][0][1] = 16 + 7;
mdacols[0x78][0][0] = mdacols[0x78][1][0] = mdacols[0x78][1][1] = 16 + 15;
mdacols[0xF8][0][1] = 16 + 7;
mdacols[0xF8][0][0] = mdacols[0xF8][1][0] = mdacols[0xF8][1][1] = 16 + 15;
mdacols[0x00][0][1] = mdacols[0x00][1][1] = 16;
mdacols[0x08][0][1] = mdacols[0x08][1][1] = 16;
mdacols[0x80][0][1] = mdacols[0x80][1][1] = 16;
mdacols[0x88][0][1] = mdacols[0x88][1][1] = 16;
overscan_x = overscan_y = 0;
mda->monitor_index = monitor_index_global;
cga_palette = device_get_config_int("rgb_type") << 1;
if (cga_palette > 6) {
cga_palette = 0;
}
cgapal_rebuild();
timer_add(&mda->timer, mda_poll, mda, 1);
timer_add(&mda->dot_timer, mda_dot_poll, mda, 1);
}
void *
mda_standalone_init(UNUSED(const device_t *info))
{
mda_t *mda = malloc(sizeof(mda_t));
memset(mda, 0, sizeof(mda_t));
video_inform(VIDEO_FLAG_TYPE_MDA, &timing_mda);
mda->vram = malloc(0x1000);
mem_mapping_add(&mda->mapping, 0xb0000, 0x08000, mda_read, NULL, NULL, mda_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, mda);
io_sethandler(0x03b0, 0x0010, mda_in, NULL, NULL, mda_out, NULL, NULL, mda);
mda_init(mda);
lpt3_init(0x3BC);
return mda;
}
void
mda_setcol(int chr, int blink, int fg, uint8_t cga_ink)
{
mdacols[chr][blink][fg] = 16 + cga_ink;
}
void
mda_close(void *priv)
{
mda_t *mda = (mda_t *) priv;
free(mda->vram);
free(mda);
}
void
mda_speed_changed(void *priv)
{
mda_t *mda = (mda_t *) priv;
mda_recalctimings(mda);
}
static const device_config_t mda_config[] = {
// clang-format off
{
.name = "rgb_type",
.description = "Display type",
.type = CONFIG_SELECTION,
.default_int = 0,
.selection = {
{
.description = "Default",
.value = 0
},
{
.description = "Green",
.value = 1
},
{
.description = "Amber",
.value = 2
},
{
.description = "Gray",
.value = 3
},
{
.description = ""
}
}
},
{
.type = CONFIG_END
}
// clang-format on
};
const device_t mda_device = {
.name = "MDA",
.internal_name = "mda",
.flags = DEVICE_ISA,
.local = 0,
.init = mda_standalone_init,
.close = mda_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = mda_speed_changed,
.force_redraw = NULL,
.config = mda_config
};

View File

@@ -1,738 +0,0 @@
/*
* 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.
*
* Oak OTI037C/67/077 emulation.
*
*
*
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2018 Sarah Walker.
* Copyright 2016-2018 Miran Grca.
*/
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include <86box/io.h>
#include <86box/timer.h>
#include <86box/mem.h>
#include <86box/rom.h>
#include <86box/device.h>
#include <86box/video.h>
#include <86box/vid_svga.h>
#include <86box/vid_svga_render.h>
#include <86box/plat_unused.h>
#define BIOS_037C_PATH "roms/video/oti/bios.bin"
#define BIOS_067_AMA932J_PATH "roms/machines/ama932j/OTI067.BIN"
#define BIOS_067_M300_08_PATH "roms/machines/m30008/EVC_BIOS.ROM"
#define BIOS_067_M300_15_PATH "roms/machines/m30015/EVC_BIOS.ROM"
#define BIOS_077_PATH "roms/video/oti/oti077.vbi"
enum {
OTI_037C = 0,
OTI_067 = 2,
OTI_067_AMA932J = 3,
OTI_067_M300 = 4,
OTI_077 = 5
};
typedef struct {
svga_t svga;
rom_t bios_rom;
int index;
uint8_t regs[32];
uint8_t chip_id;
uint8_t pos;
uint8_t enable_register;
uint8_t dipswitch_val;
uint32_t vram_size;
uint32_t vram_mask;
} oti_t;
static video_timings_t timing_oti = { .type = VIDEO_ISA, .write_b = 6, .write_w = 8, .write_l = 16, .read_b = 6, .read_w = 8, .read_l = 16 };
static void
oti_out(uint16_t addr, uint8_t val, void *priv)
{
oti_t *oti = (oti_t *) priv;
svga_t *svga = &oti->svga;
uint8_t old;
uint8_t idx;
uint8_t enable = 0;
uint16_t page = 0x0000;
if (!oti->chip_id && !(oti->enable_register & 1) && (addr != 0x3C3))
return;
if ((((addr & 0xFFF0) == 0x3D0 || (addr & 0xFFF0) == 0x3B0) && addr < 0x3de) && !(svga->miscout & 1))
addr ^= 0x60;
switch (addr) {
case 0x3C3:
if (!oti->chip_id) {
oti->enable_register = val & 1;
return;
}
svga_out(addr, val, svga);
return;
case 0x3c6:
case 0x3c7:
case 0x3c8:
case 0x3c9:
if (oti->chip_id == OTI_077)
sc1148x_ramdac_out(addr, 0, val, svga->ramdac, svga);
else
svga_out(addr, val, svga);
return;
case 0x3D4:
if (oti->chip_id)
svga->crtcreg = val & 0x3f;
else
svga->crtcreg = val; /* FIXME: The BIOS wants to set the test bit? */
return;
case 0x3D5:
if (oti->chip_id && (svga->crtcreg & 0x20))
return;
idx = svga->crtcreg;
if (!oti->chip_id)
idx &= 0x1f;
if ((idx < 7) && (svga->crtc[0x11] & 0x80))
return;
if ((idx == 7) && (svga->crtc[0x11] & 0x80))
val = (svga->crtc[7] & ~0x10) | (val & 0x10);
old = svga->crtc[idx];
svga->crtc[idx] = val;
if (old != val) {
if ((idx < 0x0e) || (idx > 0x10)) {
if (idx == 0x0c || idx == 0x0d) {
svga->fullchange = 3;
svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
} else {
svga->fullchange = changeframecount;
svga_recalctimings(svga);
}
}
}
break;
case 0x3DE:
if (oti->chip_id)
oti->index = val & 0x1f;
else
oti->index = val;
return;
case 0x3DF:
idx = oti->index;
if (!oti->chip_id)
idx &= 0x1f;
oti->regs[idx] = val;
switch (idx) {
case 0xD:
if (oti->chip_id == OTI_067) {
svga->vram_display_mask = (val & 0x0c) ? oti->vram_mask : 0x3ffff;
switch ((val & 0x80) >> 7) {
case 0x00: /* 256 kB of memory */
default:
enable = (oti->vram_size >= 256);
if (val & 0x0c)
svga->vram_display_mask = MIN(oti->vram_mask, 0x3ffff);
break;
case 0x01: /* 512 kB of memory */
enable = (oti->vram_size >= 512);
if (val & 0x0c)
svga->vram_display_mask = MIN(oti->vram_mask, 0x7ffff);
break;
}
if (enable)
mem_mapping_enable(&svga->mapping);
else
mem_mapping_disable(&svga->mapping);
} else if (oti->chip_id == OTI_077) {
svga->vram_display_mask = (val & 0x0c) ? oti->vram_mask : 0x3ffff;
switch ((val & 0xc0) >> 6) {
default:
case 0x00: /* 256 kB of memory */
enable = (oti->vram_size >= 256);
if (val & 0x0c)
svga->vram_display_mask = MIN(oti->vram_mask, 0x3ffff);
break;
case 0x01: /* 1 MB of memory */
case 0x03:
enable = (oti->vram_size >= 1024);
if (val & 0x0c)
svga->vram_display_mask = MIN(oti->vram_mask, 0xfffff);
break;
case 0x02: /* 512 kB of memory */
enable = (oti->vram_size >= 512);
if (val & 0x0c)
svga->vram_display_mask = MIN(oti->vram_mask, 0x7ffff);
break;
}
} else {
if (val & 0x80)
mem_mapping_disable(&svga->mapping);
else
mem_mapping_enable(&svga->mapping);
}
break;
case 0x11:
if (oti->chip_id >= OTI_067) {
page = (((uint16_t) oti->regs[0x14] & 0x40) >> 6);
if (oti->chip_id == OTI_077)
page |= (((uint16_t) oti->regs[0x16] & 0x40) >> 5);
page <<= 18;
}
svga->read_bank = ((uint16_t) oti->regs[0x11] & 0xf) << 14;
svga->write_bank = ((uint16_t) oti->regs[0x11] >> 4) << 14;
svga->read_bank |= page;
svga->write_bank |= page;
break;
case 0x14:
if (oti->chip_id >= OTI_067) {
page = (((uint16_t) oti->regs[0x14] & 0x40) >> 6);
if (oti->chip_id == OTI_077)
page |= (((uint16_t) oti->regs[0x16] & 0x40) >> 5);
page <<= 18;
svga->read_bank = ((uint16_t) oti->regs[0x11] & 0xf) << 14;
svga->write_bank = ((uint16_t) oti->regs[0x11] >> 4) << 14;
svga->read_bank |= page;
svga->write_bank |= page;
}
break;
case 0x16:
if (oti->chip_id == OTI_077) {
page = (((uint16_t) oti->regs[0x14] & 0x40) >> 6);
page |= (((uint16_t) oti->regs[0x16] & 0x40) >> 5);
page <<= 18;
svga->read_bank = ((uint16_t) oti->regs[0x11] & 0xf) << 14;
svga->write_bank = ((uint16_t) oti->regs[0x11] >> 4) << 14;
svga->read_bank |= page;
svga->write_bank |= page;
}
break;
default:
break;
}
return;
default:
break;
}
svga_out(addr, val, svga);
}
static uint8_t
oti_in(uint16_t addr, void *priv)
{
oti_t *oti = (oti_t *) priv;
svga_t *svga = &oti->svga;
uint8_t idx;
uint8_t temp;
if (!oti->chip_id && !(oti->enable_register & 1) && (addr != 0x3C3))
return 0xff;
if ((((addr & 0xFFF0) == 0x3D0 || (addr & 0xFFF0) == 0x3B0) && addr < 0x3de) && !(svga->miscout & 1))
addr ^= 0x60;
switch (addr) {
case 0x3C2:
if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x50)
temp = 0;
else
temp = 0x10;
break;
case 0x3C3:
if (oti->chip_id)
temp = svga_in(addr, svga);
else
temp = oti->enable_register;
break;
case 0x3c6:
case 0x3c7:
case 0x3c8:
case 0x3c9:
if (oti->chip_id == OTI_077)
return sc1148x_ramdac_in(addr, 0, svga->ramdac, svga);
return svga_in(addr, svga);
case 0x3CF:
return svga->gdcreg[svga->gdcaddr & 0xf];
case 0x3D4:
temp = svga->crtcreg;
break;
case 0x3D5:
if (oti->chip_id) {
if (svga->crtcreg & 0x20)
temp = 0xff;
else
temp = svga->crtc[svga->crtcreg];
} else
temp = svga->crtc[svga->crtcreg & 0x1f];
break;
case 0x3DA:
if (oti->chip_id) {
temp = svga_in(addr, svga);
break;
}
svga->attrff = 0;
/*The OTI-037C BIOS waits for bits 0 and 3 in 0x3da to go low, then reads 0x3da again
and expects the diagnostic bits to equal the current border colour. As I understand
it, the 0x3da active enable status does not include the border time, so this may be
an area where OTI-037C is not entirely VGA compatible.*/
svga->cgastat &= ~0x30;
/* copy color diagnostic info from the overscan color register */
switch (svga->attrregs[0x12] & 0x30) {
case 0x00: /* P0 and P2 */
if (svga->attrregs[0x11] & 0x01)
svga->cgastat |= 0x10;
if (svga->attrregs[0x11] & 0x04)
svga->cgastat |= 0x20;
break;
case 0x10: /* P4 and P5 */
if (svga->attrregs[0x11] & 0x10)
svga->cgastat |= 0x10;
if (svga->attrregs[0x11] & 0x20)
svga->cgastat |= 0x20;
break;
case 0x20: /* P1 and P3 */
if (svga->attrregs[0x11] & 0x02)
svga->cgastat |= 0x10;
if (svga->attrregs[0x11] & 0x08)
svga->cgastat |= 0x20;
break;
case 0x30: /* P6 and P7 */
if (svga->attrregs[0x11] & 0x40)
svga->cgastat |= 0x10;
if (svga->attrregs[0x11] & 0x80)
svga->cgastat |= 0x20;
break;
default:
break;
}
temp = svga->cgastat;
break;
case 0x3DE:
temp = oti->index;
if (oti->chip_id)
temp |= (oti->chip_id << 5);
break;
case 0x3DF:
idx = oti->index;
if (!oti->chip_id)
idx &= 0x1f;
if (idx == 0x10)
temp = oti->dipswitch_val;
else
temp = oti->regs[idx];
break;
default:
temp = svga_in(addr, svga);
break;
}
return temp;
}
static void
oti_pos_out(UNUSED(uint16_t addr), uint8_t val, void *priv)
{
oti_t *oti = (oti_t *) priv;
if ((val ^ oti->pos) & 8) {
if (val & 8)
io_sethandler(0x03c0, 32, oti_in, NULL, NULL,
oti_out, NULL, NULL, oti);
else
io_removehandler(0x03c0, 32, oti_in, NULL, NULL,
oti_out, NULL, NULL, oti);
}
oti->pos = val;
}
static uint8_t
oti_pos_in(UNUSED(uint16_t addr), void *priv)
{
const oti_t *oti = (oti_t *) priv;
return (oti->pos);
}
static float
oti_getclock(int clock)
{
float ret = 0.0;
switch (clock) {
default:
case 0:
ret = 25175000.0;
break;
case 1:
ret = 28322000.0;
break;
case 4:
ret = 14318000.0;
break;
case 5:
ret = 16257000.0;
break;
case 7:
ret = 35500000.0;
break;
}
return ret;
}
static void
oti_recalctimings(svga_t *svga)
{
const oti_t *oti = (oti_t *) svga->priv;
int clk_sel = ((svga->miscout >> 2) & 3) | ((oti->regs[0x0d] & 0x20) >> 3);
svga->clock = (cpuclock * (double) (1ULL << 32)) / oti_getclock(clk_sel);
if (oti->chip_id > 0) {
if (oti->regs[0x14] & 0x08)
svga->ma_latch |= 0x10000;
if (oti->regs[0x16] & 0x08)
svga->ma_latch |= 0x20000;
if (oti->regs[0x14] & 0x01)
svga->vtotal += 0x400;
if (oti->regs[0x14] & 0x02)
svga->dispend += 0x400;
if (oti->regs[0x14] & 0x04)
svga->vsyncstart += 0x400;
svga->interlace = oti->regs[0x14] & 0x80;
}
if ((oti->regs[0x0d] & 0x0c) && !(oti->regs[0x0d] & 0x10))
svga->rowoffset <<= 1;
if (svga->bpp == 16) {
svga->render = svga_render_16bpp_highres;
svga->hdisp >>= 1;
} else if (svga->bpp == 15) {
svga->render = svga_render_15bpp_highres;
svga->hdisp >>= 1;
}
}
static void *
oti_init(const device_t *info)
{
oti_t *oti = malloc(sizeof(oti_t));
const char *romfn = NULL;
memset(oti, 0x00, sizeof(oti_t));
oti->chip_id = info->local;
oti->dipswitch_val = 0x18;
switch (oti->chip_id) {
case OTI_037C:
romfn = BIOS_037C_PATH;
oti->vram_size = 256;
oti->regs[0] = 0x08; /* FIXME: The BIOS wants to read this at index 0? This index is undocumented. */
#if 0
io_sethandler(0x03c0, 32,
oti_in, NULL, NULL, oti_out, NULL, NULL, oti);
#endif
break;
case OTI_067_AMA932J:
romfn = BIOS_067_AMA932J_PATH;
oti->chip_id = 2;
oti->vram_size = device_get_config_int("memory");
oti->dipswitch_val |= 0x20;
oti->pos = 0x08; /* Tell the BIOS the I/O ports are already enabled to avoid a double I/O handler mess. */
io_sethandler(0x46e8, 1, oti_pos_in, NULL, NULL, oti_pos_out, NULL, NULL, oti);
break;
case OTI_067_M300:
if (rom_present(BIOS_067_M300_15_PATH))
romfn = BIOS_067_M300_15_PATH;
else
romfn = BIOS_067_M300_08_PATH;
oti->vram_size = device_get_config_int("memory");
oti->pos = 0x08; /* Tell the BIOS the I/O ports are already enabled to avoid a double I/O handler mess. */
io_sethandler(0x46e8, 1, oti_pos_in, NULL, NULL, oti_pos_out, NULL, NULL, oti);
break;
case OTI_067:
case OTI_077:
romfn = BIOS_077_PATH;
oti->vram_size = device_get_config_int("memory");
oti->pos = 0x08; /* Tell the BIOS the I/O ports are already enabled to avoid a double I/O handler mess. */
io_sethandler(0x46e8, 1, oti_pos_in, NULL, NULL, oti_pos_out, NULL, NULL, oti);
break;
default:
break;
}
if (romfn != NULL) {
rom_init(&oti->bios_rom, romfn,
0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
}
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_oti);
svga_init(info, &oti->svga, oti, oti->vram_size << 10,
oti_recalctimings, oti_in, oti_out, NULL, NULL);
oti->vram_mask = (oti->vram_size << 10) - 1;
if (oti->chip_id == OTI_077)
oti->svga.ramdac = device_add(&sc11487_ramdac_device); /*Actually a 82c487, probably a clone.*/
io_sethandler(0x03c0, 32,
oti_in, NULL, NULL, oti_out, NULL, NULL, oti);
oti->svga.miscout = 1;
oti->svga.packed_chain4 = 1;
return oti;
}
static void
oti_close(void *priv)
{
oti_t *oti = (oti_t *) priv;
svga_close(&oti->svga);
free(oti);
}
static void
oti_speed_changed(void *priv)
{
oti_t *oti = (oti_t *) priv;
svga_recalctimings(&oti->svga);
}
static void
oti_force_redraw(void *priv)
{
oti_t *oti = (oti_t *) priv;
oti->svga.fullchange = changeframecount;
}
static int
oti037c_available(void)
{
return (rom_present(BIOS_037C_PATH));
}
static int
oti067_ama932j_available(void)
{
return (rom_present(BIOS_067_AMA932J_PATH));
}
static int
oti067_077_available(void)
{
return (rom_present(BIOS_077_PATH));
}
static int
oti067_m300_available(void)
{
if (rom_present(BIOS_067_M300_15_PATH))
return (rom_present(BIOS_067_M300_15_PATH));
else
return (rom_present(BIOS_067_M300_08_PATH));
}
// clang-format off
static const device_config_t oti067_config[] = {
{
.name = "memory",
.description = "Memory size",
.type = CONFIG_SELECTION,
.default_int = 512,
.selection = {
{
.description = "256 kB",
.value = 256
},
{
.description = "512 kB",
.value = 512
},
{
.description = ""
}
}
},
{
.type = CONFIG_END
}
};
static const device_config_t oti067_ama932j_config[] = {
{
.name = "memory",
.description = "Memory size",
.type = CONFIG_SELECTION,
.default_int = 256,
.selection = {
{
.description = "256 kB",
.value = 256
},
{
.description = "512 kB",
.value = 512
},
{
.description = ""
}
}
},
{
.type = CONFIG_END
}
};
static const device_config_t oti077_config[] = {
{
.name = "memory",
.description = "Memory size",
.type = CONFIG_SELECTION,
.default_int = 1024,
.selection = {
{
.description = "256 kB",
.value = 256
},
{
.description = "512 kB",
.value = 512
},
{
.description = "1 MB",
.value = 1024
},
{
.description = ""
}
}
},
{
.type = CONFIG_END
}
};
// clang-format on
const device_t oti037c_device = {
.name = "Oak OTI-037C",
.internal_name = "oti037c",
.flags = DEVICE_ISA,
.local = 0,
.init = oti_init,
.close = oti_close,
.reset = NULL,
{ .available = oti037c_available },
.speed_changed = oti_speed_changed,
.force_redraw = oti_force_redraw,
.config = NULL
};
const device_t oti067_device = {
.name = "Oak OTI-067",
.internal_name = "oti067",
.flags = DEVICE_ISA,
.local = 2,
.init = oti_init,
.close = oti_close,
.reset = NULL,
{ .available = oti067_077_available },
.speed_changed = oti_speed_changed,
.force_redraw = oti_force_redraw,
.config = oti067_config
};
const device_t oti067_m300_device = {
.name = "Oak OTI-067 (Olivetti M300-08/15)",
.internal_name = "oti067_m300",
.flags = DEVICE_ISA,
.local = 4,
.init = oti_init,
.close = oti_close,
.reset = NULL,
{ .available = oti067_m300_available },
.speed_changed = oti_speed_changed,
.force_redraw = oti_force_redraw,
.config = oti067_config
};
const device_t oti067_ama932j_device = {
.name = "Oak OTI-067 (AMA-932J)",
.internal_name = "oti067_ama932j",
.flags = DEVICE_ISA,
.local = 3,
.init = oti_init,
.close = oti_close,
.reset = NULL,
{ .available = oti067_ama932j_available },
.speed_changed = oti_speed_changed,
.force_redraw = oti_force_redraw,
.config = oti067_ama932j_config
};
const device_t oti077_device = {
.name = "Oak OTI-077",
.internal_name = "oti077",
.flags = DEVICE_ISA,
.local = 5,
.init = oti_init,
.close = oti_close,
.reset = NULL,
{ .available = oti067_077_available },
.speed_changed = oti_speed_changed,
.force_redraw = oti_force_redraw,
.config = oti077_config
};