mirror of
https://github.com/86Box/86Box.git
synced 2026-02-22 17:45:31 -07:00
Merge branch 'master' of https://github.com/86Box/86Box
This commit is contained in:
9
.github/workflows/cmake.yml
vendored
9
.github/workflows/cmake.yml
vendored
@@ -74,7 +74,7 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
build:
|
||||
- name: Regular
|
||||
- name: Debug
|
||||
dev-build: off
|
||||
new-dynarec: off
|
||||
type: Debug
|
||||
@@ -82,17 +82,12 @@ jobs:
|
||||
dev-build: on
|
||||
new-dynarec: on
|
||||
type: Debug
|
||||
target-arch: ['Win32', 'x64', 'ARM', 'ARM64']
|
||||
target-arch: ['Win32', 'x64', 'ARM64']
|
||||
toolset: ['clangcl', 'v142']
|
||||
exclude:
|
||||
- target-arch: 'ARM'
|
||||
build:
|
||||
new-dynarec: off
|
||||
- target-arch: 'ARM64'
|
||||
build:
|
||||
new-dynarec: off
|
||||
- target-arch: 'ARM'
|
||||
toolset: 'clangcl'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
@@ -45,6 +45,8 @@ option(DISCORD "Discord integration" ON)
|
||||
|
||||
option(NEW_DYNAREC "Use the PCem v15 (\"new\") dynamic recompiler" OFF)
|
||||
|
||||
option(MINITRACE "Enable Chrome tracing using the modified minitrace library" OFF)
|
||||
|
||||
option(DEV_BRANCH "Development branch" OFF)
|
||||
CMAKE_DEPENDENT_OPTION(AMD_K5 "AMD K5" ON "DEV_BRANCH" OFF)
|
||||
CMAKE_DEPENDENT_OPTION(CL5422 "Cirrus Logic CL-GD 5402/5420/5422" ON "DEV_BRANCH" OFF)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
operating systems and software designed for IBM PC systems and compatibles
|
||||
from 1981 through fairly recent system designs based on the PCI bus.
|
||||
|
||||
86Box is released under the GNU General Public License, version 2 or later.
|
||||
86Box is released under the GNU General Public License, version 2 only.
|
||||
For more information, see the `COPYING` file.
|
||||
|
||||
The project maintainer is [OBattler](https://github.com/OBattler).
|
||||
|
||||
@@ -90,11 +90,23 @@ else()
|
||||
add_subdirectory(codegen)
|
||||
endif()
|
||||
|
||||
if(MINITRACE)
|
||||
add_compile_definitions(MTR_ENABLED)
|
||||
add_library(minitrace OBJECT minitrace/minitrace.c)
|
||||
target_link_libraries(86Box minitrace)
|
||||
endif()
|
||||
|
||||
install(TARGETS 86Box)
|
||||
if(VCPKG_TOOLCHAIN)
|
||||
x_vcpkg_install_local_dependencies(TARGETS 86Box DESTINATION "bin")
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
install(FILES $<TARGET_PDB_FILE:86Box>
|
||||
CONFIGURATIONS Debug RelWithDebInfo
|
||||
DESTINATION "bin")
|
||||
endif()
|
||||
|
||||
add_subdirectory(device)
|
||||
add_subdirectory(disk)
|
||||
add_subdirectory(floppy)
|
||||
|
||||
@@ -17,7 +17,8 @@ add_library(chipset OBJECT acc2168.c cs8230.c ali1217.c ali1429.c headland.c int
|
||||
cs4031.c intel_420ex.c intel_4x0.c intel_sio.c intel_piix.c ../ioapic.c
|
||||
neat.c opti495.c opti895.c opti5x7.c scamp.c scat.c via_vt82c49x.c
|
||||
via_vt82c505.c sis_85c310.c sis_85c4xx.c sis_85c496.c sis_85c50x.c
|
||||
stpc.c opti283.c opti291.c via_apollo.c via_pipc.c wd76c10.c
|
||||
gc100.c olivetti_eva.c stpc.c
|
||||
opti283.c opti291.c via_apollo.c via_pipc.c wd76c10.c
|
||||
vl82c480.c)
|
||||
|
||||
if(M1489)
|
||||
|
||||
256
src/chipset/gc100.c
Normal file
256
src/chipset/gc100.c
Normal file
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Implementation of the G2 GC100/GC100A chipset.
|
||||
* NOTE: As documentation is currently available only for the
|
||||
* CG100 chipset, the GC100A chipset has been reverese-engineered.
|
||||
* Thus, its behavior may not be fully accurate.
|
||||
*
|
||||
* Authors: EngiNerd <webmaster.crrc@yahoo.it>
|
||||
*
|
||||
* Copyright 2020-2021 EngiNerd
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include <86box/86box.h>
|
||||
#include <86box/nmi.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/pit.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/fdd.h>
|
||||
#include <86box/fdc.h>
|
||||
#include <86box/fdc_ext.h>
|
||||
#include <86box/hdc.h>
|
||||
#include <86box/gameport.h>
|
||||
#include <86box/ibm_5161.h>
|
||||
#include <86box/keyboard.h>
|
||||
#include <86box/rom.h>
|
||||
#include <86box/machine.h>
|
||||
#include <86box/chipset.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/video.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t reg[0x10];
|
||||
} gc100_t;
|
||||
|
||||
#define ENABLE_GC100_LOG 1
|
||||
|
||||
#ifdef ENABLE_GC100_LOG
|
||||
int gc100_do_log = ENABLE_GC100_LOG;
|
||||
static void
|
||||
gc100_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (gc100_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define gc100_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
static uint8_t
|
||||
get_fdd_switch_settings(){
|
||||
|
||||
int i, fdd_count = 0;
|
||||
|
||||
for (i = 0; i < FDD_NUM; i++) {
|
||||
if (fdd_get_flags(i))
|
||||
fdd_count++;
|
||||
}
|
||||
|
||||
if (!fdd_count)
|
||||
return 0x00;
|
||||
else
|
||||
return ((fdd_count - 1) << 6) | 0x01;
|
||||
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
get_videomode_switch_settings(){
|
||||
|
||||
if (video_is_mda())
|
||||
return 0x30;
|
||||
else if (video_is_cga())
|
||||
return 0x20; /* 0x10 would be 40x25 */
|
||||
else
|
||||
return 0x00;
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
gc100_write(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
gc100_t *dev = (gc100_t *) priv;
|
||||
|
||||
uint16_t addr = port & 0xf;
|
||||
|
||||
dev->reg[addr] = val;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
/* addr 0x2
|
||||
* bits 5-7: not used
|
||||
* bit 4: intenal memory wait states
|
||||
* bits 2-3: external memory wait states
|
||||
* bits 0-1: i/o access wait states
|
||||
*/
|
||||
case 0x2:
|
||||
break;
|
||||
|
||||
/* addr 0x3
|
||||
* bits 1-7: not used
|
||||
* bit 0: turbo 0 xt 1
|
||||
*/
|
||||
case 0x3:
|
||||
if (val & 0x1)
|
||||
cpu_dynamic_switch(0);
|
||||
else
|
||||
cpu_dynamic_switch(cpu);
|
||||
break;
|
||||
|
||||
/* addr 0x5
|
||||
* programmable dip-switches
|
||||
* bits 6-7: floppy drive number
|
||||
* bits 4-5: video mode
|
||||
* bits 2-3: memory size
|
||||
* bit 1: fpu
|
||||
* bit 0: not used
|
||||
*/
|
||||
|
||||
/* addr 0x6 */
|
||||
|
||||
/* addr 0x7 */
|
||||
|
||||
}
|
||||
|
||||
gc100_log("GC100: Write %02x at %02x\n", val, port);
|
||||
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
gc100_read(uint16_t port, void *priv)
|
||||
{
|
||||
gc100_t *dev = (gc100_t *) priv;
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
uint16_t addr = port & 0xf;
|
||||
|
||||
ret = dev->reg[addr];
|
||||
|
||||
gc100_log("GC100: Read %02x at %02x\n", ret, port);
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
/* addr 0x2
|
||||
* bits 5-7: not used
|
||||
* bit 4: intenal memory wait states
|
||||
* bits 2-3: external memory wait states
|
||||
* bits 0-1: i/o access wait states
|
||||
*/
|
||||
case 0x2:
|
||||
break;
|
||||
|
||||
/* addr 0x3
|
||||
* bits 1-7: not used
|
||||
* bit 0: turbo 0 xt 1
|
||||
*/
|
||||
case 0x3:
|
||||
break;
|
||||
|
||||
/* addr 0x5
|
||||
* programmable dip-switches
|
||||
* bits 6-7: floppy drive number
|
||||
* bits 4-5: video mode
|
||||
* bits 2-3: memory size
|
||||
* bit 1: fpu
|
||||
* bit 0: not used
|
||||
*/
|
||||
case 0x5:
|
||||
ret = ret & 0x0c;
|
||||
ret |= get_fdd_switch_settings();
|
||||
ret |= get_videomode_switch_settings();
|
||||
if (hasfpu)
|
||||
ret |= 0x02;
|
||||
|
||||
break;
|
||||
|
||||
/* addr 0x6 */
|
||||
|
||||
/* addr 0x7 */
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gc100_close(void *priv)
|
||||
{
|
||||
gc100_t *dev = (gc100_t *) priv;
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
static void *
|
||||
gc100_init(const device_t *info)
|
||||
{
|
||||
gc100_t *dev = (gc100_t *) malloc(sizeof(gc100_t));
|
||||
memset(dev, 0, sizeof(gc100_t));
|
||||
|
||||
dev->reg[0x2] = 0xff;
|
||||
dev->reg[0x3] = 0x0;
|
||||
dev->reg[0x5] = 0x0;
|
||||
dev->reg[0x6] = 0x0;
|
||||
dev->reg[0x7] = 0x0;
|
||||
|
||||
/* GC100A */
|
||||
if(info->local) {
|
||||
io_sethandler(0x0c2, 0x02, gc100_read, NULL, NULL, gc100_write, NULL, NULL, dev);
|
||||
io_sethandler(0x0c5, 0x03, gc100_read, NULL, NULL, gc100_write, NULL, NULL, dev);
|
||||
}
|
||||
/* GC100 */
|
||||
else {
|
||||
io_sethandler(0x022, 0x02, gc100_read, NULL, NULL, gc100_write, NULL, NULL, dev);
|
||||
io_sethandler(0x025, 0x01, gc100_read, NULL, NULL, gc100_write, NULL, NULL, dev);
|
||||
}
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
const device_t gc100_device = {
|
||||
"G2 GC100",
|
||||
0,
|
||||
0,
|
||||
gc100_init, gc100_close, NULL,
|
||||
{ NULL }, NULL, NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
const device_t gc100a_device = {
|
||||
"G2 GC100A",
|
||||
0,
|
||||
1,
|
||||
gc100_init, gc100_close, NULL,
|
||||
{ NULL }, NULL, NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Implementation of the Intel 82335(KU82335) chipset.
|
||||
*
|
||||
* Copyright 2020 Tiseno100
|
||||
* Copyright 2021 Tiseno100
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -24,10 +24,7 @@
|
||||
#include <86box/timer.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/keyboard.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/fdd.h>
|
||||
#include <86box/fdc.h>
|
||||
#include <86box/chipset.h>
|
||||
|
||||
/* Shadow capabilities */
|
||||
@@ -38,7 +35,7 @@
|
||||
|
||||
/* Granularity Register Enable & Recalc */
|
||||
#define EXTENDED_GRANULARITY_ENABLED (dev->regs[0x2c] & 0x01)
|
||||
#define GRANULARITY_RECALC ((dev->regs[0x2e] & (1 << (i+8))) ? ((dev->regs[0x2e] & (1 << i)) ? RO_SHADOW : RW_SHADOW) : DISABLED_SHADOW)
|
||||
#define GRANULARITY_RECALC ((dev->regs[0x2e] & (1 << (i + 8))) ? ((dev->regs[0x2e] & (1 << i)) ? RO_SHADOW : RW_SHADOW) : DISABLED_SHADOW)
|
||||
|
||||
/* R/W operator for the Video RAM region */
|
||||
#define DETERMINE_VIDEO_RAM_WRITE_ACCESS ((dev->regs[0x22] & (0x08 << 8)) ? RW_SHADOW : RO_SHADOW)
|
||||
@@ -61,8 +58,8 @@ typedef struct
|
||||
{
|
||||
|
||||
uint16_t regs[256],
|
||||
|
||||
cfg_locked;
|
||||
|
||||
cfg_locked;
|
||||
|
||||
} intel_82335_t;
|
||||
|
||||
@@ -73,10 +70,11 @@ intel_82335_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (intel_82335_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
if (intel_82335_do_log)
|
||||
{
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
@@ -86,92 +84,90 @@ intel_82335_log(const char *fmt, ...)
|
||||
static void
|
||||
intel_82335_write(uint16_t addr, uint16_t val, void *priv)
|
||||
{
|
||||
intel_82335_t *dev = (intel_82335_t *) priv;
|
||||
intel_82335_t *dev = (intel_82335_t *)priv;
|
||||
uint32_t romsize = 0, base = 0, i = 0, rc1_remap = 0, rc2_remap = 0;
|
||||
|
||||
dev->regs[addr] = val;
|
||||
|
||||
if(!dev->cfg_locked)
|
||||
if (!dev->cfg_locked)
|
||||
{
|
||||
|
||||
intel_82335_log("Register %02x: Write %04x\n", addr, val);
|
||||
intel_82335_log("Register %02x: Write %04x\n", addr, val);
|
||||
|
||||
switch (addr) {
|
||||
case 0x22: /* Memory Controller */
|
||||
switch (addr)
|
||||
{
|
||||
case 0x22: /* Memory Controller */
|
||||
|
||||
/* Check if the ROM chips are 256 or 512Kbit (Just for Shadowing sanity) */
|
||||
romsize = ROM_SIZE;
|
||||
/* Check if the ROM chips are 256 or 512Kbit (Just for Shadowing sanity) */
|
||||
romsize = ROM_SIZE;
|
||||
|
||||
if (!EXTENDED_GRANULARITY_ENABLED)
|
||||
{
|
||||
shadowbios = !!(dev->regs[0x22] & 0x01);
|
||||
shadowbios_write = !!(dev->regs[0x22] & 0x01);
|
||||
if (!EXTENDED_GRANULARITY_ENABLED)
|
||||
{
|
||||
shadowbios = !!(dev->regs[0x22] & 0x01);
|
||||
shadowbios_write = !!(dev->regs[0x22] & 0x01);
|
||||
|
||||
/* Base System 512/640KB set */
|
||||
mem_set_mem_state_both(0x80000, 0x20000, (dev->regs[0x22] & 0x08) ? ENABLE_TOP_128KB : DISABLE_TOP_128KB);
|
||||
/* Base System 512/640KB set */
|
||||
mem_set_mem_state_both(0x80000, 0x20000, (dev->regs[0x22] & 0x08) ? ENABLE_TOP_128KB : DISABLE_TOP_128KB);
|
||||
|
||||
/* Video RAM shadow*/
|
||||
mem_set_mem_state_both(0xa0000, 0x20000, (dev->regs[0x22] & (0x04 << 8)) ? DETERMINE_VIDEO_RAM_WRITE_ACCESS : DISABLED_SHADOW);
|
||||
/* Video RAM shadow*/
|
||||
mem_set_mem_state_both(0xa0000, 0x20000, (dev->regs[0x22] & (0x04 << 8)) ? DETERMINE_VIDEO_RAM_WRITE_ACCESS : DISABLED_SHADOW);
|
||||
|
||||
/* Option ROM shadow */
|
||||
mem_set_mem_state_both(0xc0000, 0x20000, (dev->regs[0x22] & (0x02 << 8)) ? ENABLED_SHADOW : DISABLED_SHADOW);
|
||||
/* Option ROM shadow */
|
||||
mem_set_mem_state_both(0xc0000, 0x20000, (dev->regs[0x22] & (0x02 << 8)) ? ENABLED_SHADOW : DISABLED_SHADOW);
|
||||
|
||||
/* System ROM shadow */
|
||||
mem_set_mem_state_both(0xe0000, 0x20000, (dev->regs[0x22] & 0x01) ? ENABLED_SHADOW : DISABLED_SHADOW);
|
||||
}
|
||||
break;
|
||||
/* System ROM shadow */
|
||||
mem_set_mem_state_both(0xe0000, 0x20000, (dev->regs[0x22] & 0x01) ? ENABLED_SHADOW : DISABLED_SHADOW);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x24: /* Roll Compare (Just top remapping. Not followed according to datasheet!) */
|
||||
case 0x26:
|
||||
rc1_remap = (dev->regs[0x24] & 0x01) ? DEFINE_RC1_REMAP_SIZE : 0;
|
||||
rc2_remap = (dev->regs[0x26] & 0x01) ? DEFINE_RC2_REMAP_SIZE : 0;
|
||||
mem_remap_top(rc1_remap+rc2_remap);
|
||||
break;
|
||||
case 0x24: /* Roll Compare (Just top remapping. Not followed according to datasheet!) */
|
||||
case 0x26:
|
||||
rc1_remap = (dev->regs[0x24] & 0x01) ? DEFINE_RC1_REMAP_SIZE : 0;
|
||||
rc2_remap = (dev->regs[0x26] & 0x01) ? DEFINE_RC2_REMAP_SIZE : 0;
|
||||
mem_remap_top(rc1_remap + rc2_remap);
|
||||
break;
|
||||
|
||||
case 0x2e: /* Extended Granularity (Enabled if Bit 0 in Register 2Ch is set) */
|
||||
if(EXTENDED_GRANULARITY_ENABLED)
|
||||
{
|
||||
for(i=0; i<8; i++)
|
||||
{
|
||||
base = 0xc0000 + (i << 15);
|
||||
shadowbios = (dev->regs[0x2e] & (1 << (i+8))) && (base == romsize);
|
||||
shadowbios_write = (dev->regs[0x2e] & (1 << i)) && (base == romsize);
|
||||
mem_set_mem_state_both(base, 0x8000, GRANULARITY_RECALC);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
case 0x2e: /* Extended Granularity (Enabled if Bit 0 in Register 2Ch is set) */
|
||||
if (EXTENDED_GRANULARITY_ENABLED)
|
||||
{
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
base = 0xc0000 + (i << 15);
|
||||
shadowbios = (dev->regs[0x2e] & (1 << (i + 8))) && (base == romsize);
|
||||
shadowbios_write = (dev->regs[0x2e] & (1 << i)) && (base == romsize);
|
||||
mem_set_mem_state_both(base, 0x8000, GRANULARITY_RECALC);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Unlock/Lock configuration registers */
|
||||
dev->cfg_locked = LOCK_STATUS;
|
||||
}
|
||||
|
||||
|
||||
static uint16_t
|
||||
intel_82335_read(uint16_t addr, void *priv)
|
||||
{
|
||||
intel_82335_t *dev = (intel_82335_t *) priv;
|
||||
intel_82335_t *dev = (intel_82335_t *)priv;
|
||||
|
||||
intel_82335_log("Register %02x: Read %04x\n", addr, dev->regs[addr]);
|
||||
|
||||
return dev->regs[addr];
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
intel_82335_close(void *priv)
|
||||
{
|
||||
intel_82335_t *dev = (intel_82335_t *) priv;
|
||||
intel_82335_t *dev = (intel_82335_t *)priv;
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
intel_82335_init(const device_t *info)
|
||||
{
|
||||
intel_82335_t *dev = (intel_82335_t *) malloc(sizeof(intel_82335_t));
|
||||
intel_82335_t *dev = (intel_82335_t *)malloc(sizeof(intel_82335_t));
|
||||
memset(dev, 0, sizeof(intel_82335_t));
|
||||
|
||||
memset(dev->regs, 0, sizeof(dev->regs));
|
||||
@@ -195,17 +191,19 @@ intel_82335_init(const device_t *info)
|
||||
io_sethandler(0x002c, 0x0001, NULL, intel_82335_read, NULL, NULL, intel_82335_write, NULL, dev);
|
||||
|
||||
/* Extended Granularity */
|
||||
io_sethandler(0x002e, 0x0001, NULL, intel_82335_read, NULL, NULL, intel_82335_write, NULL, dev);
|
||||
|
||||
io_sethandler(0x002e, 0x0001, NULL, intel_82335_read, NULL, NULL, intel_82335_write, NULL, dev);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
||||
const device_t intel_82335_device = {
|
||||
"Intel 82335",
|
||||
0,
|
||||
0,
|
||||
intel_82335_init, intel_82335_close, NULL,
|
||||
{ NULL }, NULL, NULL,
|
||||
NULL
|
||||
};
|
||||
intel_82335_init,
|
||||
intel_82335_close,
|
||||
NULL,
|
||||
{NULL},
|
||||
NULL,
|
||||
NULL,
|
||||
NULL};
|
||||
|
||||
166
src/chipset/olivetti_eva.c
Normal file
166
src/chipset/olivetti_eva.c
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Implementation of the Olivetti EVA (98/86) Gate Array.
|
||||
*
|
||||
* Note: This chipset has no datasheet, everything were done via
|
||||
* reverse engineering the BIOS of various machines using it.
|
||||
*
|
||||
* Authors: EngiNerd <webmaster.crrc@yahoo.it>
|
||||
*
|
||||
* Copyright 2020-2021 EngiNerd
|
||||
*/
|
||||
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include <86box/86box.h>
|
||||
#include "cpu.h"
|
||||
#include <86box/timer.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/chipset.h>
|
||||
#include <86box/video.h>
|
||||
#include <86box/mem.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t reg_065;
|
||||
uint8_t reg_067;
|
||||
uint8_t reg_069;
|
||||
} olivetti_eva_t;
|
||||
|
||||
#ifdef ENABLE_OLIVETTI_EVA_LOG
|
||||
int olivetti_eva_do_log = ENABLE_OLIVETTI_EVA_LOG;
|
||||
static void
|
||||
olivetti_eva_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (olivetti_eva_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define olivetti_eva_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
static void
|
||||
olivetti_eva_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
olivetti_eva_t *dev = (olivetti_eva_t *) priv;
|
||||
olivetti_eva_log("Olivetti EVA Gate Array: Write %02x at %02x\n", val, addr);
|
||||
|
||||
switch (addr) {
|
||||
case 0x065:
|
||||
dev->reg_065 = val;
|
||||
break;
|
||||
case 0x067:
|
||||
dev->reg_067 = val;
|
||||
break;
|
||||
case 0x069:
|
||||
dev->reg_069 = val;
|
||||
/*
|
||||
* Unfortunately, if triggered, the BIOS remapping function fails causing
|
||||
* a fatal error. Therefore, this code section is currently commented.
|
||||
*/
|
||||
// if (val & 1){
|
||||
// /*
|
||||
// * Set the register to 7 or above for the BIOS to trigger the
|
||||
// * memory remapping function if shadowing is active.
|
||||
// */
|
||||
// dev->reg_069 = 0x7;
|
||||
// }
|
||||
// if (val & 8) {
|
||||
// /*
|
||||
// * Activate shadowing for region e0000-fffff
|
||||
// */
|
||||
// mem_remap_top(256);
|
||||
// mem_set_mem_state_both(0xa0000, 0x60000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
|
||||
// }
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
olivetti_eva_read(uint16_t addr, void *priv)
|
||||
{
|
||||
olivetti_eva_t *dev = (olivetti_eva_t *) priv;
|
||||
uint8_t ret = 0xff;
|
||||
switch (addr) {
|
||||
case 0x065:
|
||||
ret = dev->reg_065;
|
||||
break;
|
||||
case 0x067:
|
||||
/* never happens */
|
||||
ret = dev->reg_067;
|
||||
break;
|
||||
case 0x069:
|
||||
ret = dev->reg_069;
|
||||
break;
|
||||
}
|
||||
olivetti_eva_log("Olivetti EVA Gate Array: Read %02x at %02x\n", ret, addr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
olivetti_eva_close(void *priv)
|
||||
{
|
||||
olivetti_eva_t *dev = (olivetti_eva_t *) priv;
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
static void *
|
||||
olivetti_eva_init(const device_t *info)
|
||||
{
|
||||
olivetti_eva_t *dev = (olivetti_eva_t *) malloc(sizeof(olivetti_eva_t));
|
||||
memset(dev, 0, sizeof(olivetti_eva_t));
|
||||
|
||||
/* GA98 registers */
|
||||
dev->reg_065 = 0x00;
|
||||
|
||||
/* RAM page registers: never read, only set */
|
||||
dev->reg_067 = 0x00;
|
||||
|
||||
/* RAM enable registers */
|
||||
dev->reg_069 = 0x0;
|
||||
|
||||
io_sethandler(0x0065, 0x0001, olivetti_eva_read, NULL, NULL, olivetti_eva_write, NULL, NULL, dev);
|
||||
io_sethandler(0x0067, 0x0001, olivetti_eva_read, NULL, NULL, olivetti_eva_write, NULL, NULL, dev);
|
||||
io_sethandler(0x0069, 0x0001, olivetti_eva_read, NULL, NULL, olivetti_eva_write, NULL, NULL, dev);
|
||||
|
||||
/* When shadowing is not enabled in BIOS, all upper memory is available as XMS */
|
||||
mem_remap_top(384);
|
||||
|
||||
/*
|
||||
* Default settings when NVRAM is cleared activate shadowing.
|
||||
* Thus, to avoid boot errors, remap only 256k from UMB to XMS.
|
||||
* Remove this block once BIOS memory remapping works.
|
||||
*/
|
||||
mem_remap_top(256);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
const device_t olivetti_eva_device = {
|
||||
"Olivetti EVA Gate Array",
|
||||
0,
|
||||
0,
|
||||
olivetti_eva_init, olivetti_eva_close, NULL,
|
||||
{ NULL }, NULL, NULL,
|
||||
NULL
|
||||
};
|
||||
@@ -6,13 +6,15 @@
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the OPTi 82C546/82C547 & 82C596/82C597 chipsets.
|
||||
* Implementation of the OPTi 82C546/82C547(Python) & 82C596/82C597(Cobra) chipsets.
|
||||
|
||||
* Authors: plant/nerd73
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Authors: plant/nerd73,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Tiseno100
|
||||
*
|
||||
* Copyright 2020 plant/nerd73.
|
||||
* Copyright 2020 Miran Grca.
|
||||
* Copyright 2020 plant/nerd73.
|
||||
* Copyright 2020 Miran Grca.
|
||||
* Copyright 2021 Tiseno100.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
@@ -26,142 +28,156 @@
|
||||
#include <86box/timer.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/keyboard.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/fdd.h>
|
||||
#include <86box/fdc.h>
|
||||
#include <86box/port_92.h>
|
||||
#include <86box/chipset.h>
|
||||
|
||||
/* Shadow RAM */
|
||||
|
||||
/* Register 4h: C0000-CFFFF range | Register 5h: D0000-DFFFF range */
|
||||
#define CURRENT_REGISTER dev->regs[4 + !!(i & 4)]
|
||||
|
||||
/*
|
||||
Bits 7-6: xC000-xFFFF
|
||||
Bits 5-4: x8000-xBFFF
|
||||
Bits 3-2: x4000-x7FFF
|
||||
Bits 0-1: x0000-x3FFF
|
||||
|
||||
x-y
|
||||
0 0 Read/Write AT bus
|
||||
1 0 Read from AT - Write to DRAM
|
||||
1 1 Read from DRAM - Write to DRAM
|
||||
0 1 Read from DRAM (write protected)
|
||||
*/
|
||||
#define CAN_READ (1 << (i - (4 * !!(i & 4))) * 2)
|
||||
#define CAN_WRITE (1 << ((i - (4 * !!(i & 4))) * 2 + 1))
|
||||
|
||||
/* Shadow Recalc for the C/D segments */
|
||||
#define SHADOW_RECALC (((CURRENT_REGISTER & CAN_READ) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((CURRENT_REGISTER & CAN_WRITE) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY))
|
||||
|
||||
/* Shadow Recalc for the E/F segments */
|
||||
#define SHADOW_EF_RECALC (((dev->regs[6] & CAN_READ) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[6] & CAN_WRITE) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY))
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t idx,
|
||||
regs[16];
|
||||
port_92_t *port_92;
|
||||
uint8_t idx, regs[16];
|
||||
} opti5x7_t;
|
||||
|
||||
|
||||
#ifdef ENABLE_OPTI5X7_LOG
|
||||
int opti5x7_do_log = ENABLE_OPTI5X7_LOG;
|
||||
|
||||
|
||||
static void
|
||||
opti5x7_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (opti5x7_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
if (opti5x7_do_log)
|
||||
{
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define opti5x7_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
opti5x7_recalc(opti5x7_t *dev)
|
||||
shadow_map(opti5x7_t *dev)
|
||||
{
|
||||
uint32_t base;
|
||||
uint32_t i, shflags = 0;
|
||||
uint32_t reg, lowest_bit;
|
||||
|
||||
shadowbios = 0;
|
||||
shadowbios_write = 0;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
base = 0xc0000 + (i << 14);
|
||||
|
||||
lowest_bit = (i << 1) & 0x07;
|
||||
reg = 0x04 + ((base >> 16) & 0x01);
|
||||
|
||||
shflags = (dev->regs[reg] & (1 << lowest_bit)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
|
||||
shflags |= (dev->regs[reg] & (1 << (lowest_bit + 1))) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
|
||||
mem_set_mem_state(base, 0x4000, shflags);
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
mem_set_mem_state_both(0xc0000 + (i << 14), 0x4000, SHADOW_RECALC);
|
||||
if (i < 2)
|
||||
mem_set_mem_state_both(0xe0000 + (i << 16), 0x10000, SHADOW_EF_RECALC);
|
||||
}
|
||||
|
||||
shadowbios |= !!(dev->regs[0x06] & 0x05);
|
||||
shadowbios_write |= !!(dev->regs[0x06] & 0x0a);
|
||||
|
||||
shflags = (dev->regs[0x06] & 0x01) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
|
||||
shflags |= (dev->regs[0x06] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
|
||||
mem_set_mem_state(0xe0000, 0x10000, shflags);
|
||||
|
||||
shflags = (dev->regs[0x06] & 0x04) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
|
||||
shflags |= (dev->regs[0x06] & 0x08) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
|
||||
mem_set_mem_state(0xf0000, 0x10000, shflags);
|
||||
|
||||
shadowbios = !!(dev->regs[0x06] & 5);
|
||||
shadowbios_write = !!(dev->regs[0x06] & 0x0a);
|
||||
flushmmucache();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
opti5x7_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
opti5x7_t *dev = (opti5x7_t *) priv;
|
||||
opti5x7_log("Write %02x to OPTi 5x7 address %02x\n", val, addr);
|
||||
|
||||
switch (addr) {
|
||||
case 0x22:
|
||||
dev->idx = val;
|
||||
break;
|
||||
case 0x24:
|
||||
dev->regs[dev->idx] = val;
|
||||
switch(dev->idx) {
|
||||
case 0x02:
|
||||
cpu_cache_ext_enabled = !!(dev->regs[0x02] & 0x04 & 0x08);
|
||||
break;
|
||||
{
|
||||
opti5x7_t *dev = (opti5x7_t *)priv;
|
||||
|
||||
case 0x04:
|
||||
case 0x05:
|
||||
case 0x06:
|
||||
opti5x7_recalc(dev);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
switch (addr)
|
||||
{
|
||||
case 0x22:
|
||||
dev->idx = val;
|
||||
break;
|
||||
case 0x24:
|
||||
opti5x7_log("OPTi 5x7: dev->regs[%02x] = %02x\n", dev->idx, val);
|
||||
switch (dev->idx)
|
||||
{
|
||||
case 0x00: /* DRAM Configuration Register #1 */
|
||||
dev->regs[dev->idx] = val & 0x7f;
|
||||
break;
|
||||
case 0x01: /* DRAM Control Register #1 */
|
||||
dev->regs[dev->idx] = val;
|
||||
break;
|
||||
case 0x02: /* Cache Control Register #1 */
|
||||
dev->regs[dev->idx] = val;
|
||||
cpu_cache_ext_enabled = !!(dev->regs[0x02] & 0x0c);
|
||||
cpu_update_waitstates();
|
||||
break;
|
||||
case 0x03: /* Cache Control Register #2 */
|
||||
dev->regs[dev->idx] = val;
|
||||
break;
|
||||
case 0x04: /* Shadow RAM Control Register #1 */
|
||||
case 0x05: /* Shadow RAM Control Register #2 */
|
||||
case 0x06: /* Shadow RAM Control Register #3 */
|
||||
dev->regs[dev->idx] = val;
|
||||
shadow_map(dev);
|
||||
break;
|
||||
case 0x07: /* Tag Test Register */
|
||||
case 0x08: /* CPU Cache Control Register #1 */
|
||||
case 0x09: /* System Memory Function Register #1 */
|
||||
case 0x0a: /* System Memory Address Decode Register #1 */
|
||||
case 0x0b: /* System Memory Address Decode Register #2 */
|
||||
dev->regs[dev->idx] = val;
|
||||
break;
|
||||
case 0x0c: /* Extended DMA Register */
|
||||
dev->regs[dev->idx] = val & 0xcf;
|
||||
break;
|
||||
case 0x0d: /* ROMCS# Register */
|
||||
case 0x0e: /* Local Master Preemption Register */
|
||||
case 0x0f: /* Deturbo Control Register #1 */
|
||||
case 0x10: /* Cache Write-Hit Control Register */
|
||||
case 0x11: /* Master Cycle Control Register */
|
||||
dev->regs[dev->idx] = val;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
opti5x7_read(uint16_t addr, void *priv)
|
||||
{
|
||||
uint8_t ret = 0xff;
|
||||
opti5x7_t *dev = (opti5x7_t *) priv;
|
||||
opti5x7_t *dev = (opti5x7_t *)priv;
|
||||
|
||||
switch (addr) {
|
||||
case 0x24:
|
||||
opti5x7_log("Read from OPTi 5x7 register %02x\n", dev->idx);
|
||||
ret = dev->regs[dev->idx];
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return (addr == 0x24) ? dev->regs[dev->idx] : 0xff;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
opti5x7_close(void *priv)
|
||||
{
|
||||
opti5x7_t *dev = (opti5x7_t *) priv;
|
||||
opti5x7_t *dev = (opti5x7_t *)priv;
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
opti5x7_init(const device_t *info)
|
||||
{
|
||||
opti5x7_t *dev = (opti5x7_t *) malloc(sizeof(opti5x7_t));
|
||||
opti5x7_t *dev = (opti5x7_t *)malloc(sizeof(opti5x7_t));
|
||||
memset(dev, 0, sizeof(opti5x7_t));
|
||||
|
||||
io_sethandler(0x0022, 0x0001, opti5x7_read, NULL, NULL, opti5x7_write, NULL, NULL, dev);
|
||||
io_sethandler(0x0024, 0x0001, opti5x7_read, NULL, NULL, opti5x7_write, NULL, NULL, dev);
|
||||
|
||||
dev->port_92 = device_add(&port_92_device);
|
||||
device_add(&port_92_device);
|
||||
|
||||
return dev;
|
||||
}
|
||||
@@ -170,7 +186,10 @@ const device_t opti5x7_device = {
|
||||
"OPTi 82C5x6/82C5x7",
|
||||
0,
|
||||
0,
|
||||
opti5x7_init, opti5x7_close, NULL,
|
||||
{ NULL }, NULL, NULL,
|
||||
NULL
|
||||
};
|
||||
opti5x7_init,
|
||||
opti5x7_close,
|
||||
NULL,
|
||||
{NULL},
|
||||
NULL,
|
||||
NULL,
|
||||
NULL};
|
||||
|
||||
@@ -537,7 +537,7 @@ cpu_set(void)
|
||||
is_p6 = (cpu_s->cpu_type == CPU_PENTIUMPRO) || (cpu_s->cpu_type == CPU_PENTIUM2) ||
|
||||
(cpu_s->cpu_type == CPU_PENTIUM2D);
|
||||
/* The Samuel 2 datasheet claims it's Celeron-compatible. */
|
||||
is_p6 |= (cpu_s->cpu_type == CPU_CYRIX3S);
|
||||
is_p6 |= (cpu_s->cpu_type == CPU_CYRIX3S) || (cpu_s->cpu_type == CPU_EDEN);
|
||||
#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86)
|
||||
is_cx6x86 = (cpu_s->cpu_type == CPU_Cx6x86) || (cpu_s->cpu_type == CPU_Cx6x86MX) ||
|
||||
(cpu_s->cpu_type == CPU_Cx6x86L) || (cpu_s->cpu_type == CPU_CxGX1);
|
||||
@@ -1807,6 +1807,7 @@ cpu_set(void)
|
||||
break;
|
||||
|
||||
case CPU_CYRIX3S:
|
||||
case CPU_EDEN: /* This till proper timings get discovered */
|
||||
#ifdef USE_DYNAREC
|
||||
x86_setopcodes(ops_386, ops_winchip2_0f, dynarec_ops_386, dynarec_ops_winchip2_0f);
|
||||
#else
|
||||
@@ -2600,6 +2601,65 @@ cpu_CPUID(void)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case CPU_EDEN:
|
||||
switch (EAX)
|
||||
{
|
||||
case 0:
|
||||
EAX = 1;
|
||||
if (msr.fcr2 & (1 << 14))
|
||||
{
|
||||
EBX = msr.fcr3 >> 32;
|
||||
ECX = msr.fcr3 & 0xffffffff;
|
||||
EDX = msr.fcr2 >> 32;
|
||||
}
|
||||
else
|
||||
{
|
||||
EBX = 0x746e6543; /*CentaurHauls*/
|
||||
ECX = 0x736c7561;
|
||||
EDX = 0x48727561;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
EAX = CPUID;
|
||||
EBX = ECX = 0;
|
||||
EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MMX | CPUID_MTRR;
|
||||
if (cpu_has_feature(CPU_FEATURE_CX8))
|
||||
EDX |= CPUID_CMPXCHG8B;
|
||||
break;
|
||||
case 0x80000000:
|
||||
EAX = 0x80000006;
|
||||
break;
|
||||
case 0x80000001:
|
||||
EAX = CPUID;
|
||||
EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MMX | CPUID_MTRR | CPUID_3DNOW;
|
||||
if (cpu_has_feature(CPU_FEATURE_CX8))
|
||||
EDX |= CPUID_CMPXCHG8B;
|
||||
break;
|
||||
case 0x80000002: /*Processor name string*/
|
||||
case 0x80000003:
|
||||
case 0x80000004:
|
||||
EAX = 0x20414956; /*VIA Samuel 2*/
|
||||
EBX = 0x756d6153;
|
||||
ECX = 0x32206c65;
|
||||
EDX = 0x00000000;
|
||||
break;
|
||||
|
||||
case 0x80000005: /*Cache information*/
|
||||
EBX = 0x08800880; /*TLBs*/
|
||||
ECX = 0x40040120; /*L1 data cache*/
|
||||
EDX = 0x40020120; /*L1 instruction cache*/
|
||||
break;
|
||||
|
||||
case 0x80000006:
|
||||
ECX = 0x40040120; /*L2 data cache*/
|
||||
break;
|
||||
|
||||
default:
|
||||
EAX = EBX = ECX = EDX = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2714,6 +2774,7 @@ void cpu_RDMSR()
|
||||
break;
|
||||
|
||||
case CPU_CYRIX3S:
|
||||
case CPU_EDEN:
|
||||
EAX = EDX = 0;
|
||||
switch (ECX)
|
||||
{
|
||||
@@ -3318,6 +3379,7 @@ void cpu_WRMSR()
|
||||
}
|
||||
break;
|
||||
case CPU_CYRIX3S:
|
||||
case CPU_EDEN:
|
||||
switch (ECX)
|
||||
{
|
||||
case 0x10:
|
||||
|
||||
@@ -81,6 +81,7 @@ enum {
|
||||
CPU_K6_2P,
|
||||
CPU_K6_3P,
|
||||
CPU_CYRIX3S,
|
||||
CPU_EDEN,
|
||||
CPU_PENTIUMPRO, /* 686 class CPUs */
|
||||
CPU_PENTIUM2,
|
||||
CPU_PENTIUM2D
|
||||
@@ -108,7 +109,8 @@ enum {
|
||||
CPU_PKG_SOCKET8 = (1 << 18),
|
||||
CPU_PKG_SLOT1 = (1 << 19),
|
||||
CPU_PKG_SLOT2 = (1 << 20),
|
||||
CPU_PKG_SOCKET370 = (1 << 21)
|
||||
CPU_PKG_SOCKET370 = (1 << 21),
|
||||
CPU_PKG_EBGA368 = (1 << 22)
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -967,6 +967,16 @@ const cpu_family_t cpu_families[] = {
|
||||
{"733", CPU_CYRIX3S, fpus_internal, 733333333, 5.5, 2050, 0x663, 0x663, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 66, 66, 18, 18, 88},
|
||||
{"", 0}
|
||||
}
|
||||
}, {
|
||||
.package = CPU_PKG_EBGA368,
|
||||
.manufacturer = "VIA",
|
||||
.name = "Eden(Model 7)",
|
||||
.internal_name = "c3_eden",
|
||||
.cpus = (const CPU[]) {
|
||||
{"100", CPU_EDEN, fpus_internal, 100000000, 1.5, 2050, 0x673, 0x673, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 9, 9, 4, 4, 12}, /* out of spec */
|
||||
{"400", CPU_EDEN, fpus_internal, 400000000, 6.0, 2050, 0x673, 0x673, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 36, 36, 17, 17, 48},
|
||||
{"600", CPU_EDEN, fpus_internal, 600000000, 6.0, 2050, 0x673, 0x673, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 54, 54, 18, 18, 72},
|
||||
}
|
||||
}, {
|
||||
.package = 0,
|
||||
}
|
||||
|
||||
@@ -1207,9 +1207,12 @@ write64_generic(void *priv, uint8_t val)
|
||||
* bit 6: display type (0 color, 1 mono)
|
||||
* bit 5: power-on default speed (0 high, 1 low)
|
||||
* bit 4: sense RAM size (0 unsupported, 1 512k on system board)
|
||||
* bits 0-3: unused
|
||||
* bit 3: coprocessor detect
|
||||
* bit 2: unused
|
||||
* bit 1: high/auto speed
|
||||
* bit 0: dma mode
|
||||
*/
|
||||
add_to_kbc_queue_front(dev, (dev->input_port | fixed_bits | (video_is_mda() ? 0x40 : 0x00)) & 0xdf);
|
||||
add_to_kbc_queue_front(dev, (dev->input_port | fixed_bits | (video_is_mda() ? 0x40 : 0x00) | (hasfpu ? 0x08 : 0x00)) & 0xdf);
|
||||
dev->input_port = ((dev->input_port + 1) & 3) |
|
||||
(dev->input_port & 0xfc);
|
||||
} else {
|
||||
@@ -1507,6 +1510,29 @@ write60_quadtel(void *priv, uint8_t val)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
write64_olivetti(void *priv, uint8_t val)
|
||||
{
|
||||
atkbd_t *dev = (atkbd_t *)priv;
|
||||
|
||||
switch (val) {
|
||||
case 0x80: /* Olivetti-specific command */
|
||||
/*
|
||||
* bit 7: bus expansion board present (M300) / keyboard unlocked (M290)
|
||||
* bits 4-6: ???
|
||||
* bit 3: fast ram check (if inactive keyboard works erratically)
|
||||
* bit 2: keyboard fuse present
|
||||
* bits 0-1: ???
|
||||
*/
|
||||
add_to_kbc_queue_front(dev, (0x0c | ((is386) ? 0x00 : 0x80)) & 0xdf);
|
||||
dev->input_port = ((dev->input_port + 1) & 3) |
|
||||
(dev->input_port & 0xfc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return write64_generic(dev, val);
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
write64_quadtel(void *priv, uint8_t val)
|
||||
@@ -2137,7 +2163,6 @@ kbd_read(uint16_t port, void *priv)
|
||||
ret |= 0x2; /* 0x10 would be 40x25 */
|
||||
else
|
||||
ret |= 0x0;
|
||||
ret = 0xff;
|
||||
} else {
|
||||
/* bit 2 always on */
|
||||
ret |= 0x4;
|
||||
@@ -2291,13 +2316,16 @@ kbd_init(const device_t *info)
|
||||
switch(dev->flags & KBC_VEN_MASK) {
|
||||
case KBC_VEN_ACER:
|
||||
case KBC_VEN_GENERIC:
|
||||
case KBC_VEN_OLIVETTI:
|
||||
case KBC_VEN_NCR:
|
||||
case KBC_VEN_IBM_PS1:
|
||||
case KBC_VEN_XI8088:
|
||||
dev->write64_ven = write64_generic;
|
||||
break;
|
||||
|
||||
case KBC_VEN_OLIVETTI:
|
||||
dev->write64_ven = write64_olivetti;
|
||||
break;
|
||||
|
||||
case KBC_VEN_AMI:
|
||||
case KBC_VEN_INTEL_AMI:
|
||||
case KBC_VEN_SAMSUNG:
|
||||
@@ -2447,6 +2475,16 @@ const device_t keyboard_ps2_ami_device = {
|
||||
{ NULL }, NULL, NULL, NULL
|
||||
};
|
||||
|
||||
const device_t keyboard_ps2_olivetti_device = {
|
||||
"PS/2 Keyboard (Olivetti)",
|
||||
0,
|
||||
KBC_TYPE_PS2_NOREF | KBC_VEN_OLIVETTI,
|
||||
kbd_init,
|
||||
kbd_close,
|
||||
kbd_reset,
|
||||
{ NULL }, NULL, NULL, NULL
|
||||
};
|
||||
|
||||
const device_t keyboard_ps2_mca_device = {
|
||||
"PS/2 Keyboard",
|
||||
0,
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include <wchar.h>
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
@@ -598,7 +600,7 @@ kbd_read(uint16_t port, void *priv)
|
||||
ret = ((mem_size-64) / 32) >> 4;
|
||||
}
|
||||
else if (kbd->type == 8 || kbd->type == 9) {
|
||||
/* Olivetti M19 or Zenith Data Systems Z-151*/
|
||||
/* Olivetti M19 or Zenith Data Systems Z-151 */
|
||||
if (kbd->pb & 0x04)
|
||||
ret = kbd->pd & 0xbf;
|
||||
else
|
||||
|
||||
@@ -484,14 +484,16 @@ serial_write(uint16_t addr, uint8_t val, void *p)
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
dev->lsr = val;
|
||||
if (dev->lsr & 0x01)
|
||||
dev->int_status |= SERIAL_INT_RECEIVE;
|
||||
if (dev->lsr & 0x1e)
|
||||
dev->int_status |= SERIAL_INT_LSR;
|
||||
if (dev->lsr & 0x20)
|
||||
dev->int_status |= SERIAL_INT_TRANSMIT;
|
||||
serial_update_ints(dev);
|
||||
if (dev->mctrl & 0x10) {
|
||||
dev->lsr = (dev->lsr & 0xe3) | (val & 0x1c);
|
||||
if (dev->lsr & 0x01)
|
||||
dev->int_status |= SERIAL_INT_RECEIVE;
|
||||
if (dev->lsr & 0x1e)
|
||||
dev->int_status |= SERIAL_INT_LSR;
|
||||
if (dev->lsr & 0x20)
|
||||
dev->int_status |= SERIAL_INT_TRANSMIT;
|
||||
serial_update_ints(dev);
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
dev->msr = val;
|
||||
|
||||
@@ -1245,7 +1245,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
}
|
||||
return;
|
||||
case 7:
|
||||
if (!(fdc->flags & FDC_FLAG_TOSHIBA) && !(fdc->flags & FDC_FLAG_AT))
|
||||
if (!(fdc->flags & FDC_FLAG_TOSHIBA) && !(fdc->flags & FDC_FLAG_AT) && !(fdc->flags & FDC_FLAG_UMC))
|
||||
return;
|
||||
fdc->rate = val & 0x03;
|
||||
if (fdc->flags & FDC_FLAG_PS1)
|
||||
@@ -1294,7 +1294,7 @@ fdc_read(uint16_t addr, void *priv)
|
||||
ret = 0x00;
|
||||
/* -Drive 2 Installed */
|
||||
if (!fdd_get_type(1))
|
||||
ret |= 80;
|
||||
ret |= 0x80;
|
||||
/* -Drive Select 1,0 */
|
||||
switch (drive) {
|
||||
case 0:
|
||||
@@ -1313,6 +1313,12 @@ fdc_read(uint16_t addr, void *priv)
|
||||
} else {
|
||||
if (is486 || !fdc->enable_3f1)
|
||||
ret = 0xff;
|
||||
else{
|
||||
if(fdc->flags & FDC_FLAG_UMC)
|
||||
{
|
||||
drive = real_drive(fdc, fdc->dor & 1);
|
||||
ret = !fdd_is_dd(drive) ? ((fdc->dor & 1) ? 2 : 1) : 0;
|
||||
}
|
||||
else {
|
||||
ret = 0x70;
|
||||
|
||||
@@ -1328,6 +1334,7 @@ fdc_read(uint16_t addr, void *priv)
|
||||
if (fdc->dor & 0x20)
|
||||
ret |= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
@@ -2166,6 +2173,11 @@ fdc_set_base(fdc_t *fdc, int base)
|
||||
{
|
||||
int super_io = (fdc->flags & FDC_FLAG_SUPERIO);
|
||||
|
||||
if (fdc->flags & FDC_FLAG_NSC) {
|
||||
io_sethandler(base + 2, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
io_sethandler(base + 4, 0x0002, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
io_sethandler(base + 7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
} else {
|
||||
if ((fdc->flags & FDC_FLAG_AT) || (fdc->flags & FDC_FLAG_AMSTRAD)) {
|
||||
io_sethandler(base + (super_io ? 2 : 0), super_io ? 0x0004 : 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
io_sethandler(base + 7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
@@ -2173,13 +2185,16 @@ fdc_set_base(fdc_t *fdc, int base)
|
||||
if (fdc->flags & FDC_FLAG_PCJR)
|
||||
io_sethandler(base, 0x0010, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
else {
|
||||
if(fdc->flags & FDC_FLAG_UMC)
|
||||
io_sethandler(base + 0x0001, 0x0001, fdc_read, NULL, NULL, NULL, NULL, NULL, fdc);
|
||||
io_sethandler(base + 0x0002, 0x0001, NULL, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
io_sethandler(base + 0x0004, 0x0001, fdc_read, NULL, NULL, NULL, NULL, NULL, fdc);
|
||||
io_sethandler(base + 0x0005, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
if (fdc->flags & FDC_FLAG_TOSHIBA)
|
||||
if ((fdc->flags & FDC_FLAG_TOSHIBA) || (fdc->flags & FDC_FLAG_UMC))
|
||||
io_sethandler(base + 0x0007, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
}
|
||||
}
|
||||
}
|
||||
fdc->base_address = base;
|
||||
fdc_log("FDC Base address set%s (%04X)\n", super_io ? " for Super I/O" : "", fdc->base_address);
|
||||
}
|
||||
@@ -2191,6 +2206,11 @@ fdc_remove(fdc_t *fdc)
|
||||
int super_io = (fdc->flags & FDC_FLAG_SUPERIO);
|
||||
|
||||
fdc_log("FDC Removed (%04X)\n", fdc->base_address);
|
||||
if (fdc->flags & FDC_FLAG_NSC) {
|
||||
io_removehandler(fdc->base_address + 2, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
io_removehandler(fdc->base_address + 4, 0x0002, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
io_removehandler(fdc->base_address + 7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
} else {
|
||||
if ((fdc->flags & FDC_FLAG_AT) || (fdc->flags & FDC_FLAG_AMSTRAD)) {
|
||||
io_removehandler(fdc->base_address + (super_io ? 2 : 0), super_io ? 0x0004 : 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
io_removehandler(fdc->base_address + 7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
@@ -2198,14 +2218,17 @@ fdc_remove(fdc_t *fdc)
|
||||
if (fdc->flags & FDC_FLAG_PCJR)
|
||||
io_removehandler(fdc->base_address, 0x0010, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
else {
|
||||
if(fdc->flags & FDC_FLAG_UMC)
|
||||
io_removehandler(fdc->base_address + 0x0001, 0x0001, fdc_read, NULL, NULL, NULL, NULL, NULL, fdc);
|
||||
io_removehandler(fdc->base_address + 0x0002, 0x0001, NULL, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
io_removehandler(fdc->base_address + 0x0004, 0x0001, fdc_read, NULL, NULL, NULL, NULL, NULL, fdc);
|
||||
io_removehandler(fdc->base_address + 0x0005, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
if (fdc->flags & FDC_FLAG_TOSHIBA)
|
||||
if ((fdc->flags & FDC_FLAG_TOSHIBA) || (fdc->flags & FDC_FLAG_UMC))
|
||||
io_removehandler(fdc->base_address + 0x0007, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
@@ -2433,3 +2456,13 @@ const device_t fdc_dp8473_device = {
|
||||
fdc_reset,
|
||||
{ NULL }, NULL, NULL
|
||||
};
|
||||
|
||||
const device_t fdc_um8398_device = {
|
||||
"UMC UM8398 Floppy Drive Controller",
|
||||
0,
|
||||
FDC_FLAG_UMC,
|
||||
fdc_init,
|
||||
fdc_close,
|
||||
fdc_reset,
|
||||
{ NULL }, NULL, NULL
|
||||
};
|
||||
|
||||
@@ -34,12 +34,56 @@
|
||||
#define ROM_B215 L"roms/floppy/magitronic/Magitronic B215 - BIOS ROM.bin"
|
||||
#define ROM_ADDR (uint32_t)(device_get_config_hex20("bios_addr") & 0x000fffff)
|
||||
|
||||
#define DRIVE_SELECT (int)(real_drive(dev->fdc_controller, i))
|
||||
typedef struct
|
||||
{
|
||||
fdc_t *fdc_controller;
|
||||
rom_t rom;
|
||||
} b215_t;
|
||||
|
||||
static uint8_t
|
||||
b215_read(uint16_t addr, void *priv)
|
||||
{
|
||||
b215_t *dev = (b215_t *)priv;
|
||||
|
||||
/*
|
||||
Register 3F0h
|
||||
|
||||
Bit (3-2) for Drive B:
|
||||
Bit (1-0) for Drive A:
|
||||
0: 360KB
|
||||
1: 1.2MB
|
||||
2: 720KB
|
||||
3: 1.44MB
|
||||
4:
|
||||
*/
|
||||
int drive_spec[2];
|
||||
|
||||
for (int i = 0; i <= 1; i++)
|
||||
{
|
||||
if (fdd_is_525(DRIVE_SELECT))
|
||||
{
|
||||
if (!fdd_is_dd(DRIVE_SELECT))
|
||||
drive_spec[i] = 1;
|
||||
else if (fdd_doublestep_40(DRIVE_SELECT))
|
||||
drive_spec[i] = 2;
|
||||
else
|
||||
drive_spec[i] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fdd_is_dd(DRIVE_SELECT) && !fdd_is_double_sided(DRIVE_SELECT))
|
||||
drive_spec[i] = 0;
|
||||
else if (fdd_is_dd(DRIVE_SELECT) && fdd_is_double_sided(DRIVE_SELECT))
|
||||
drive_spec[i] = 2;
|
||||
else
|
||||
drive_spec[i] = 3;
|
||||
}
|
||||
}
|
||||
|
||||
return ((drive_spec[1] << 2) | drive_spec[0]) & 0x0f;
|
||||
}
|
||||
|
||||
static void
|
||||
b215_close(void *priv)
|
||||
{
|
||||
@@ -56,7 +100,8 @@ b215_init(const device_t *info)
|
||||
|
||||
rom_init(&dev->rom, ROM_B215, ROM_ADDR, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
|
||||
device_add(&fdc_at_device);
|
||||
dev->fdc_controller = device_add(&fdc_um8398_device);
|
||||
io_sethandler(0x03f0, 1, b215_read, NULL, NULL, NULL, NULL, NULL, dev);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ MiniMicro 4 uses a Zilog Z0765A08PSC(Clone of the NEC 765)
|
||||
MiniMicro 1 uses a National Semiconductor DP8473(Clone of the NEC 765 with additional NSC commands)
|
||||
|
||||
Issues:
|
||||
MiniMicro 4 WON'T WORK with XT machines. This statement has to be confirmed by someone with the real card itself.
|
||||
MiniMicro 4 works only with a few XT machines. This statement has to be confirmed by someone with the real card itself.
|
||||
MiniMicro 4 also won't work with the XT FDC which the Zilog claims to be.
|
||||
*/
|
||||
|
||||
@@ -77,7 +77,7 @@ MiniMicro 4 also won't work with the XT FDC which the Zilog claims to be.
|
||||
#include <86box/fdc_ext.h>
|
||||
|
||||
#define DTK_VARIANT ((info->local == 158) ? ROM_PII_158B : ROM_PII_151B)
|
||||
#define DTK_CHIP ((info->local == 158) ? &fdc_at_device : &fdc_dp8473_device)
|
||||
#define DTK_CHIP ((info->local == 158) ? &fdc_xt_device : &fdc_dp8473_device)
|
||||
#define BIOS_ADDR (uint32_t)(device_get_config_hex20("bios_addr") & 0x000fffff)
|
||||
#define ROM_PII_151B L"roms/floppy/dtk/pii-151b.rom"
|
||||
#define ROM_PII_158B L"roms/floppy/dtk/pii-158b.rom"
|
||||
|
||||
@@ -46,6 +46,10 @@ extern const device_t scat_sx_device;
|
||||
extern const device_t cs8230_device;
|
||||
extern const device_t cs4031_device;
|
||||
|
||||
/* G2 */
|
||||
extern const device_t gc100_device;
|
||||
extern const device_t gc100a_device;
|
||||
|
||||
/* Headland */
|
||||
extern const device_t headland_gc10x_device;
|
||||
extern const device_t headland_ht18a_device;
|
||||
@@ -141,4 +145,7 @@ extern const device_t wd76c10_device;
|
||||
extern const device_t phoenix_486_jumper_device;
|
||||
extern const device_t vpc2007_device;
|
||||
|
||||
#if defined(DEV_BRANCH) && defined(USE_OLIVETTI)
|
||||
extern const device_t olivetti_eva_device;
|
||||
#endif
|
||||
#endif /*EMU_CHIPSET_H*/
|
||||
|
||||
@@ -34,6 +34,7 @@ extern int fdc_type;
|
||||
#define FDC_FLAG_NSC 0x80 /* PC87306, PC87309 */
|
||||
#define FDC_FLAG_TOSHIBA 0x100 /* T1000, T1200 */
|
||||
#define FDC_FLAG_AMSTRAD 0x200 /* Non-AT Amstrad machines */
|
||||
#define FDC_FLAG_UMC 0x400 /* UMC UM8398 */
|
||||
|
||||
|
||||
typedef struct {
|
||||
@@ -179,6 +180,7 @@ extern const device_t fdc_at_smc_device;
|
||||
extern const device_t fdc_at_winbond_device;
|
||||
extern const device_t fdc_at_nsc_device;
|
||||
extern const device_t fdc_dp8473_device;
|
||||
extern const device_t fdc_um8398_device;
|
||||
#endif
|
||||
|
||||
#endif /*EMU_FDC_H*/
|
||||
|
||||
@@ -82,6 +82,7 @@ extern const device_t keyboard_ps2_ps1_pci_device;
|
||||
extern const device_t keyboard_ps2_ps2_device;
|
||||
extern const device_t keyboard_ps2_xi8088_device;
|
||||
extern const device_t keyboard_ps2_ami_device;
|
||||
extern const device_t keyboard_ps2_olivetti_device;
|
||||
extern const device_t keyboard_ps2_mca_device;
|
||||
extern const device_t keyboard_ps2_mca_2_device;
|
||||
extern const device_t keyboard_ps2_quadtel_device;
|
||||
|
||||
@@ -106,6 +106,7 @@ enum {
|
||||
MACHINE_TYPE_SLOT1,
|
||||
MACHINE_TYPE_SLOT2,
|
||||
MACHINE_TYPE_SOCKET370,
|
||||
MACHINE_TYPE_EBGA368,
|
||||
MACHINE_TYPE_MISC,
|
||||
MACHINE_TYPE_MAX
|
||||
};
|
||||
@@ -255,6 +256,13 @@ extern int machine_at_spc4620p_init(const machine_t *);
|
||||
extern int machine_at_kmxc02_init(const machine_t *);
|
||||
extern int machine_at_deskmaster286_init(const machine_t *);
|
||||
|
||||
extern int machine_at_ncrpc8_init(const machine_t *);
|
||||
extern int machine_at_ncr3302_init(const machine_t *);
|
||||
|
||||
#if defined(DEV_BRANCH) && defined(USE_OLIVETTI)
|
||||
extern int machine_at_olim290_init(const machine_t *);
|
||||
#endif
|
||||
|
||||
extern int machine_at_shuttle386sx_init(const machine_t *);
|
||||
extern int machine_at_adi386sx_init(const machine_t *);
|
||||
extern int machine_at_commodore_sl386sx16_init(const machine_t *);
|
||||
@@ -263,22 +271,24 @@ extern int machine_at_spc6033p_init(const machine_t *);
|
||||
extern int machine_at_wd76c10_init(const machine_t *);
|
||||
extern int machine_at_flytech386_init(const machine_t *);
|
||||
|
||||
extern int machine_at_olim290_init(const machine_t *);
|
||||
extern int machine_at_ncrpc8_init(const machine_t *);
|
||||
extern int machine_at_ncr3302_init(const machine_t *);
|
||||
|
||||
extern int machine_at_awardsx_init(const machine_t *);
|
||||
#if defined(DEV_BRANCH) && defined(USE_M6117)
|
||||
extern int machine_at_arb1375_init(const machine_t *);
|
||||
extern int machine_at_pja511m_init(const machine_t *);
|
||||
#endif
|
||||
|
||||
extern int machine_at_ncrpc916sx_init(const machine_t *);
|
||||
|
||||
extern int machine_at_olim300_08_init(const machine_t *);
|
||||
extern int machine_at_olim300_15_init(const machine_t *);
|
||||
|
||||
#ifdef EMU_DEVICE_H
|
||||
extern const device_t *at_ama932j_get_device(void);
|
||||
extern const device_t *at_flytech386_get_device(void);
|
||||
extern const device_t *at_commodore_sl386sx25_get_device(void);
|
||||
extern const device_t *at_spc4620p_get_device(void);
|
||||
extern const device_t *at_spc6033p_get_device(void);
|
||||
extern const device_t *at_m300_08_get_device(void);
|
||||
#endif
|
||||
|
||||
/* m_at_386dx_486.c */
|
||||
@@ -523,6 +533,9 @@ extern int machine_at_603tcf_init(const machine_t *);
|
||||
extern int machine_at_trinity371_init(const machine_t *);
|
||||
extern int machine_at_p6bap_init(const machine_t *);
|
||||
|
||||
/* m_at_ebga368.c */
|
||||
extern int machine_at_arb9673_init(const machine_t *);
|
||||
|
||||
/* m_at_misc.c */
|
||||
extern int machine_at_vpc2007_init(const machine_t *);
|
||||
|
||||
@@ -611,8 +624,6 @@ extern int machine_xt_ncrpc4i_init(const machine_t *);
|
||||
extern int machine_xt_mpc1600_init(const machine_t *);
|
||||
extern int machine_xt_eaglepcspirit_init(const machine_t *);
|
||||
extern int machine_xt_multitechpc700_init(const machine_t *);
|
||||
extern int machine_xt_p3105_init(const machine_t *);
|
||||
extern int machine_xt_p3120_init(const machine_t *);
|
||||
|
||||
extern int machine_xt_iskra3104_init(const machine_t *);
|
||||
|
||||
@@ -630,6 +641,9 @@ extern int machine_xt_laserxt_init(const machine_t *);
|
||||
extern int machine_xt_lxt3_init(const machine_t *);
|
||||
#endif
|
||||
|
||||
/* m_xt_philips.c */
|
||||
extern int machine_xt_p3105_init(const machine_t *);
|
||||
extern int machine_xt_p3120_init(const machine_t *);
|
||||
/* m_xt_t1000.c */
|
||||
extern int machine_xt_t1000_init(const machine_t *);
|
||||
extern int machine_xt_t1200_init(const machine_t *);
|
||||
|
||||
@@ -66,6 +66,11 @@ extern int dopause, /* system is paused */
|
||||
doresize, /* screen resize requested */
|
||||
quited, /* system exit requested */
|
||||
mouse_capture; /* mouse is captured in app */
|
||||
|
||||
#ifdef MTR_ENABLED
|
||||
extern int tracing_on;
|
||||
#endif
|
||||
|
||||
extern uint64_t timer_freq;
|
||||
extern int infocus;
|
||||
extern char emu_version[200]; /* version ID string */
|
||||
@@ -165,6 +170,11 @@ extern void startblit(void);
|
||||
extern void endblit(void);
|
||||
extern void take_screenshot(void);
|
||||
|
||||
#ifdef MTR_ENABLED
|
||||
extern void init_trace(void);
|
||||
extern void shutdown_trace(void);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -287,6 +287,11 @@
|
||||
#define IDM_ACTION_EXIT 40014
|
||||
#define IDM_ACTION_CTRL_ALT_ESC 40015
|
||||
#define IDM_ACTION_PAUSE 40016
|
||||
#ifdef MTR_ENABLED
|
||||
#define IDM_ACTION_BEGIN_TRACE 40017
|
||||
#define IDM_ACTION_END_TRACE 40018
|
||||
#define IDM_ACTION_TRACE 40019
|
||||
#endif
|
||||
#define IDM_CONFIG 40020
|
||||
#define IDM_CONFIG_LOAD 40021
|
||||
#define IDM_CONFIG_SAVE 40022
|
||||
|
||||
@@ -43,6 +43,8 @@ extern const device_t pc87307_15c_device;
|
||||
extern const device_t pc87307_both_device;
|
||||
extern const device_t pc87309_device;
|
||||
extern const device_t pc87309_15c_device;
|
||||
extern const device_t pc87310_device;
|
||||
extern const device_t pc87310_ide_device;
|
||||
extern const device_t pc87311_device;
|
||||
extern const device_t pc87311_ide_device;
|
||||
extern const device_t pc87332_device;
|
||||
|
||||
@@ -77,6 +77,7 @@ extern const device_t cpqega_device;
|
||||
extern const device_t sega_device;
|
||||
extern const device_t atiega_device;
|
||||
extern const device_t iskra_ega_device;
|
||||
extern const device_t et2000_device;
|
||||
#endif
|
||||
|
||||
extern int update_overscan;
|
||||
|
||||
@@ -292,9 +292,11 @@ extern const device_t oti037c_device;
|
||||
extern const device_t oti067_device;
|
||||
extern const device_t oti067_acer386_device;
|
||||
extern const device_t oti067_ama932j_device;
|
||||
extern const device_t oti067_m300_device;
|
||||
extern const device_t oti077_device;
|
||||
|
||||
/* Paradise/WD (S)VGA */
|
||||
extern const device_t paradise_pvga1a_ncr3302_device;
|
||||
extern const device_t paradise_pvga1a_pc2086_device;
|
||||
extern const device_t paradise_pvga1a_pc3086_device;
|
||||
extern const device_t paradise_pvga1a_device;
|
||||
|
||||
270
src/include/minitrace/minitrace.h
Normal file
270
src/include/minitrace/minitrace.h
Normal file
@@ -0,0 +1,270 @@
|
||||
// Minitrace
|
||||
//
|
||||
// Copyright 2014 by Henrik Rydgård
|
||||
// http://www.github.com/hrydgard/minitrace
|
||||
// Released under the MIT license.
|
||||
//
|
||||
// Ultra-light dependency free library for performance tracing C/C++ applications.
|
||||
// Produces traces compatible with Google Chrome's trace viewer.
|
||||
// Simply open "about:tracing" in Chrome and load the produced JSON.
|
||||
//
|
||||
// This contains far less template magic than the original libraries from Chrome
|
||||
// because this is meant to be usable from C.
|
||||
//
|
||||
// See README.md for a tutorial.
|
||||
//
|
||||
// The trace format is documented here:
|
||||
// https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/edit
|
||||
// More:
|
||||
// http://www.altdevblogaday.com/2012/08/21/using-chrometracing-to-view-your-inline-profiling-data/
|
||||
|
||||
#ifndef MINITRACE_H
|
||||
#define MINITRACE_H
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
// If MTR_ENABLED is not defined, Minitrace does nothing and has near zero overhead.
|
||||
// Preferably, set this flag in your build system. If you can't just uncomment this line.
|
||||
// #define MTR_ENABLED
|
||||
|
||||
// By default, will collect up to 1000000 events, then you must flush.
|
||||
// It's recommended that you simply call mtr_flush on a background thread
|
||||
// occasionally. It's safe...ish.
|
||||
#define INTERNAL_MINITRACE_BUFFER_SIZE 1000000
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Initializes Minitrace. Must be called very early during startup of your executable,
|
||||
// before any MTR_ statements.
|
||||
void mtr_init(const char *json_file);
|
||||
// Same as above, but allows passing in a custom stream (FILE *), as returned by
|
||||
// fopen(). It should be opened for writing, preferably in binary mode to avoid
|
||||
// processing of line endings (i.e. the "wb" mode).
|
||||
void mtr_init_from_stream(void *stream);
|
||||
|
||||
// Shuts down minitrace cleanly, flushing the trace buffer.
|
||||
void mtr_shutdown(void);
|
||||
|
||||
// Lets you enable and disable Minitrace at runtime.
|
||||
// May cause strange discontinuities in the output.
|
||||
// Minitrace is enabled on startup by default.
|
||||
void mtr_start(void);
|
||||
void mtr_stop(void);
|
||||
|
||||
// Flushes the collected data to disk, clearing the buffer for new data.
|
||||
void mtr_flush(void);
|
||||
|
||||
// Returns the current time in seconds. Used internally by Minitrace. No caching.
|
||||
double mtr_time_s(void);
|
||||
|
||||
// Registers a handler that will flush the trace on Ctrl+C.
|
||||
// Works on Linux and MacOSX, and in Win32 console applications.
|
||||
void mtr_register_sigint_handler(void);
|
||||
|
||||
// Utility function that should rarely be used.
|
||||
// If str is semi dynamic, store it permanently in a small pool so we don't need to malloc it.
|
||||
// The pool fills up fast though and performance isn't great.
|
||||
// Returns a fixed string if the pool is full.
|
||||
const char *mtr_pool_string(const char *str);
|
||||
|
||||
// Commented-out types will be supported in the future.
|
||||
typedef enum {
|
||||
MTR_ARG_TYPE_NONE = 0,
|
||||
MTR_ARG_TYPE_INT = 1, // I
|
||||
// MTR_ARG_TYPE_FLOAT = 2, // TODO
|
||||
// MTR_ARG_TYPE_DOUBLE = 3, // TODO
|
||||
MTR_ARG_TYPE_STRING_CONST = 8, // C
|
||||
MTR_ARG_TYPE_STRING_COPY = 9,
|
||||
// MTR_ARG_TYPE_JSON_COPY = 10,
|
||||
} mtr_arg_type;
|
||||
|
||||
// TODO: Add support for more than one argument (metadata) per event
|
||||
// Having more costs speed and memory.
|
||||
#define MTR_MAX_ARGS 1
|
||||
|
||||
// Only use the macros to call these.
|
||||
void internal_mtr_raw_event(const char *category, const char *name, char ph, void *id);
|
||||
void internal_mtr_raw_event_arg(const char *category, const char *name, char ph, void *id, mtr_arg_type arg_type, const char *arg_name, void *arg_value);
|
||||
|
||||
#ifdef MTR_ENABLED
|
||||
|
||||
// c - category. Can be filtered by in trace viewer (or at least that's the intention).
|
||||
// A good use is to pass __FILE__, there are macros further below that will do it for you.
|
||||
// n - name. Pass __FUNCTION__ in most cases, unless you are marking up parts of one.
|
||||
|
||||
// Scopes. In C++, use MTR_SCOPE. In C, always match them within the same scope.
|
||||
#define MTR_BEGIN(c, n) internal_mtr_raw_event(c, n, 'B', 0)
|
||||
#define MTR_END(c, n) internal_mtr_raw_event(c, n, 'E', 0)
|
||||
#define MTR_SCOPE(c, n) MTRScopedTrace ____mtr_scope(c, n)
|
||||
#define MTR_SCOPE_LIMIT(c, n, l) MTRScopedTraceLimit ____mtr_scope(c, n, l)
|
||||
|
||||
// Async events. Can span threads. ID identifies which events to connect in the view.
|
||||
#define MTR_START(c, n, id) internal_mtr_raw_event(c, n, 'S', (void *)(id))
|
||||
#define MTR_STEP(c, n, id, step) internal_mtr_raw_event_arg(c, n, 'T', (void *)(id), MTR_ARG_TYPE_STRING_CONST, "step", (void *)(step))
|
||||
#define MTR_FINISH(c, n, id) internal_mtr_raw_event(c, n, 'F', (void *)(id))
|
||||
|
||||
// Flow events. Like async events, but displayed in a more fancy way in the viewer.
|
||||
#define MTR_FLOW_START(c, n, id) internal_mtr_raw_event(c, n, 's', (void *)(id))
|
||||
#define MTR_FLOW_STEP(c, n, id, step) internal_mtr_raw_event_arg(c, n, 't', (void *)(id), MTR_ARG_TYPE_STRING_CONST, "step", (void *)(step))
|
||||
#define MTR_FLOW_FINISH(c, n, id) internal_mtr_raw_event(c, n, 'f', (void *)(id))
|
||||
|
||||
// The same macros, but with a single named argument which shows up as metadata in the viewer.
|
||||
// _I for int.
|
||||
// _C is for a const string arg.
|
||||
// _S will copy the string, freeing on flush (expensive but sometimes necessary).
|
||||
// but required if the string was generated dynamically.
|
||||
|
||||
// Note that it's fine to match BEGIN_S with END and BEGIN with END_S, etc.
|
||||
#define MTR_BEGIN_C(c, n, aname, astrval) internal_mtr_raw_event_arg(c, n, 'B', 0, MTR_ARG_TYPE_STRING_CONST, aname, (void *)(astrval))
|
||||
#define MTR_END_C(c, n, aname, astrval) internal_mtr_raw_event_arg(c, n, 'E', 0, MTR_ARG_TYPE_STRING_CONST, aname, (void *)(astrval))
|
||||
#define MTR_SCOPE_C(c, n, aname, astrval) MTRScopedTraceArg ____mtr_scope(c, n, MTR_ARG_TYPE_STRING_CONST, aname, (void *)(astrval))
|
||||
|
||||
#define MTR_BEGIN_S(c, n, aname, astrval) internal_mtr_raw_event_arg(c, n, 'B', 0, MTR_ARG_TYPE_STRING_COPY, aname, (void *)(astrval))
|
||||
#define MTR_END_S(c, n, aname, astrval) internal_mtr_raw_event_arg(c, n, 'E', 0, MTR_ARG_TYPE_STRING_COPY, aname, (void *)(astrval))
|
||||
#define MTR_SCOPE_S(c, n, aname, astrval) MTRScopedTraceArg ____mtr_scope(c, n, MTR_ARG_TYPE_STRING_COPY, aname, (void *)(astrval))
|
||||
|
||||
#define MTR_BEGIN_I(c, n, aname, aintval) internal_mtr_raw_event_arg(c, n, 'B', 0, MTR_ARG_TYPE_INT, aname, (void*)(intptr_t)(aintval))
|
||||
#define MTR_END_I(c, n, aname, aintval) internal_mtr_raw_event_arg(c, n, 'E', 0, MTR_ARG_TYPE_INT, aname, (void*)(intptr_t)(aintval))
|
||||
#define MTR_SCOPE_I(c, n, aname, aintval) MTRScopedTraceArg ____mtr_scope(c, n, MTR_ARG_TYPE_INT, aname, (void*)(intptr_t)(aintval))
|
||||
|
||||
// Instant events. For things with no duration.
|
||||
#define MTR_INSTANT(c, n) internal_mtr_raw_event(c, n, 'I', 0)
|
||||
#define MTR_INSTANT_C(c, n, aname, astrval) internal_mtr_raw_event_arg(c, n, 'I', 0, MTR_ARG_TYPE_STRING_CONST, aname, (void *)(astrval))
|
||||
#define MTR_INSTANT_I(c, n, aname, aintval) internal_mtr_raw_event_arg(c, n, 'I', 0, MTR_ARG_TYPE_INT, aname, (void *)(aintval))
|
||||
|
||||
// Counters (can't do multi-value counters yet)
|
||||
#define MTR_COUNTER(c, n, val) internal_mtr_raw_event_arg(c, n, 'C', 0, MTR_ARG_TYPE_INT, n, (void *)(intptr_t)(val))
|
||||
|
||||
// Metadata. Call at the start preferably. Must be const strings.
|
||||
|
||||
#define MTR_META_PROCESS_NAME(n) internal_mtr_raw_event_arg("", "process_name", 'M', 0, MTR_ARG_TYPE_STRING_COPY, "name", (void *)(n))
|
||||
#define MTR_META_THREAD_NAME(n) internal_mtr_raw_event_arg("", "thread_name", 'M', 0, MTR_ARG_TYPE_STRING_COPY, "name", (void *)(n))
|
||||
#define MTR_META_THREAD_SORT_INDEX(i) internal_mtr_raw_event_arg("", "thread_sort_index", 'M', 0, MTR_ARG_TYPE_INT, "sort_index", (void *)(i))
|
||||
|
||||
#else
|
||||
|
||||
#define MTR_BEGIN(c, n)
|
||||
#define MTR_END(c, n)
|
||||
#define MTR_SCOPE(c, n)
|
||||
#define MTR_START(c, n, id)
|
||||
#define MTR_STEP(c, n, id, step)
|
||||
#define MTR_FINISH(c, n, id)
|
||||
#define MTR_FLOW_START(c, n, id)
|
||||
#define MTR_FLOW_STEP(c, n, id, step)
|
||||
#define MTR_FLOW_FINISH(c, n, id)
|
||||
#define MTR_INSTANT(c, n)
|
||||
|
||||
#define MTR_BEGIN_C(c, n, aname, astrval)
|
||||
#define MTR_END_C(c, n, aname, astrval)
|
||||
#define MTR_SCOPE_C(c, n, aname, astrval)
|
||||
|
||||
#define MTR_BEGIN_S(c, n, aname, astrval)
|
||||
#define MTR_END_S(c, n, aname, astrval)
|
||||
#define MTR_SCOPE_S(c, n, aname, astrval)
|
||||
|
||||
#define MTR_BEGIN_I(c, n, aname, aintval)
|
||||
#define MTR_END_I(c, n, aname, aintval)
|
||||
#define MTR_SCOPE_I(c, n, aname, aintval)
|
||||
|
||||
#define MTR_INSTANT(c, n)
|
||||
#define MTR_INSTANT_C(c, n, aname, astrval)
|
||||
#define MTR_INSTANT_I(c, n, aname, aintval)
|
||||
|
||||
// Counters (can't do multi-value counters yet)
|
||||
#define MTR_COUNTER(c, n, val)
|
||||
|
||||
// Metadata. Call at the start preferably. Must be const strings.
|
||||
|
||||
#define MTR_META_PROCESS_NAME(n)
|
||||
|
||||
#define MTR_META_THREAD_NAME(n)
|
||||
#define MTR_META_THREAD_SORT_INDEX(i)
|
||||
|
||||
#endif
|
||||
|
||||
// Shortcuts for simple function timing with automatic categories and names.
|
||||
|
||||
#define MTR_BEGIN_FUNC() MTR_BEGIN(__FILE__, __FUNCTION__)
|
||||
#define MTR_END_FUNC() MTR_END(__FILE__, __FUNCTION__)
|
||||
#define MTR_SCOPE_FUNC() MTR_SCOPE(__FILE__, __FUNCTION__)
|
||||
#define MTR_INSTANT_FUNC() MTR_INSTANT(__FILE__, __FUNCTION__)
|
||||
#define MTR_SCOPE_FUNC_LIMIT_S(l) MTRScopedTraceLimit ____mtr_scope(__FILE__, __FUNCTION__, l)
|
||||
#define MTR_SCOPE_FUNC_LIMIT_MS(l) MTRScopedTraceLimit ____mtr_scope(__FILE__, __FUNCTION__, (double)l * 0.000001)
|
||||
|
||||
// Same, but with a single argument of the usual types.
|
||||
#define MTR_BEGIN_FUNC_S(aname, arg) MTR_BEGIN_S(__FILE__, __FUNCTION__, aname, arg)
|
||||
#define MTR_END_FUNC_S(aname, arg) MTR_END_S(__FILE__, __FUNCTION__, aname, arg)
|
||||
#define MTR_SCOPE_FUNC_S(aname, arg) MTR_SCOPE_S(__FILE__, __FUNCTION__, aname, arg)
|
||||
|
||||
#define MTR_BEGIN_FUNC_C(aname, arg) MTR_BEGIN_C(__FILE__, __FUNCTION__, aname, arg)
|
||||
#define MTR_END_FUNC_C(aname, arg) MTR_END_C(__FILE__, __FUNCTION__, aname, arg)
|
||||
#define MTR_SCOPE_FUNC_C(aname, arg) MTR_SCOPE_C(__FILE__, __FUNCTION__, aname, arg)
|
||||
|
||||
#define MTR_BEGIN_FUNC_I(aname, arg) MTR_BEGIN_I(__FILE__, __FUNCTION__, aname, arg)
|
||||
#define MTR_END_FUNC_I(aname, arg) MTR_END_I(__FILE__, __FUNCTION__, aname, arg)
|
||||
#define MTR_SCOPE_FUNC_I(aname, arg) MTR_SCOPE_I(__FILE__, __FUNCTION__, aname, arg)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
#ifdef MTR_ENABLED
|
||||
// These are optimized to use X events (combined B and E). Much easier to do in C++ than in C.
|
||||
class MTRScopedTrace {
|
||||
public:
|
||||
MTRScopedTrace(const char *category, const char *name)
|
||||
: category_(category), name_(name) {
|
||||
start_time_ = mtr_time_s();
|
||||
}
|
||||
~MTRScopedTrace() {
|
||||
internal_mtr_raw_event(category_, name_, 'X', &start_time_);
|
||||
}
|
||||
|
||||
private:
|
||||
const char *category_;
|
||||
const char *name_;
|
||||
double start_time_;
|
||||
};
|
||||
|
||||
// Only outputs a block if execution time exceeded the limit.
|
||||
// TODO: This will effectively call mtr_time_s twice at the end, which is bad.
|
||||
class MTRScopedTraceLimit {
|
||||
public:
|
||||
MTRScopedTraceLimit(const char *category, const char *name, double limit_s)
|
||||
: category_(category), name_(name), limit_(limit_s) {
|
||||
start_time_ = mtr_time_s();
|
||||
}
|
||||
~MTRScopedTraceLimit() {
|
||||
double end_time = mtr_time_s();
|
||||
if (end_time - start_time_ >= limit_) {
|
||||
internal_mtr_raw_event(category_, name_, 'X', &start_time_);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const char *category_;
|
||||
const char *name_;
|
||||
double start_time_;
|
||||
double limit_;
|
||||
};
|
||||
|
||||
class MTRScopedTraceArg {
|
||||
public:
|
||||
MTRScopedTraceArg(const char *category, const char *name, mtr_arg_type arg_type, const char *arg_name, void *arg_value)
|
||||
: category_(category), name_(name) {
|
||||
internal_mtr_raw_event_arg(category, name, 'B', 0, arg_type, arg_name, arg_value);
|
||||
}
|
||||
~MTRScopedTraceArg() {
|
||||
internal_mtr_raw_event(category_, name_, 'E', 0);
|
||||
}
|
||||
|
||||
private:
|
||||
const char *category_;
|
||||
const char *name_;
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -14,12 +14,14 @@
|
||||
#
|
||||
|
||||
add_library(mch OBJECT machine.c machine_table.c m_xt.c m_xt_compaq.c
|
||||
m_xt_philips.c
|
||||
m_xt_t1000.c m_xt_t1000_vid.c m_xt_xi8088.c m_xt_zenith.c m_pcjr.c
|
||||
m_amstrad.c m_europc.c m_xt_olivetti.c m_tandy.c m_at.c m_at_commodore.c
|
||||
m_at_t3100e.c m_at_t3100e_vid.c m_ps1.c m_ps1_hdc.c m_ps2_isa.c
|
||||
m_ps2_mca.c m_at_compaq.c m_at_286_386sx.c m_at_386dx_486.c
|
||||
m_at_socket4_5.c m_at_socket7.c m_at_sockets7.c m_at_socket8.c
|
||||
m_at_slot1.c m_at_slot2.c m_at_socket370.c m_at_misc.c)
|
||||
m_at_slot1.c m_at_slot2.c m_at_socket370.c m_at_ebga368.c
|
||||
m_at_misc.c)
|
||||
|
||||
if(HEDAKA)
|
||||
target_compile_definitions(mch PRIVATE USE_HEDAKA)
|
||||
|
||||
@@ -35,10 +35,12 @@
|
||||
#include <86box/rom.h>
|
||||
#include <86box/fdd.h>
|
||||
#include <86box/fdc.h>
|
||||
#include <86box/fdc_ext.h>
|
||||
#include <86box/hdc.h>
|
||||
#include <86box/sio.h>
|
||||
#include <86box/serial.h>
|
||||
#include <86box/video.h>
|
||||
#include <86box/vid_cga.h>
|
||||
#include <86box/flash.h>
|
||||
#include <86box/machine.h>
|
||||
|
||||
@@ -56,6 +58,8 @@ machine_at_mr286_init(const machine_t *model)
|
||||
|
||||
machine_at_common_ide_init(model);
|
||||
device_add(&keyboard_at_device);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
return ret;
|
||||
@@ -66,6 +70,8 @@ static void
|
||||
machine_at_headland_common_init(int ht386)
|
||||
{
|
||||
device_add(&keyboard_at_ami_device);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
if (ht386)
|
||||
@@ -136,7 +142,10 @@ machine_at_quadt286_init(const machine_t *model)
|
||||
|
||||
machine_at_common_init(model);
|
||||
device_add(&keyboard_at_device);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
device_add(&headland_gc10x_device);
|
||||
|
||||
return ret;
|
||||
@@ -157,6 +166,8 @@ machine_at_neat_init(const machine_t *model)
|
||||
machine_at_init(model);
|
||||
|
||||
device_add(&neat_device);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
return ret;
|
||||
@@ -177,6 +188,8 @@ machine_at_neat_ami_init(const machine_t *model)
|
||||
machine_at_common_init(model);
|
||||
|
||||
device_add(&neat_device);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
device_add(&keyboard_at_ami_device);
|
||||
@@ -198,7 +211,10 @@ machine_at_px286_init(const machine_t *model)
|
||||
|
||||
machine_at_common_init(model);
|
||||
device_add(&keyboard_at_device);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
device_add(&neat_device);
|
||||
|
||||
return ret;
|
||||
@@ -219,6 +235,8 @@ machine_at_micronics386_init(const machine_t *model)
|
||||
machine_at_init(model);
|
||||
|
||||
device_add(&neat_device);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
return ret;
|
||||
@@ -230,6 +248,8 @@ machine_at_scat_init(const machine_t *model, int is_v4)
|
||||
{
|
||||
machine_at_common_init(model);
|
||||
device_add(&keyboard_at_ami_device);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
if (is_v4)
|
||||
@@ -245,6 +265,8 @@ machine_at_scatsx_init(const machine_t *model)
|
||||
machine_at_common_init(model);
|
||||
|
||||
device_add(&keyboard_at_ami_device);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
device_add(&scat_sx_device);
|
||||
@@ -434,6 +456,8 @@ machine_at_shuttle386sx_init(const machine_t *model)
|
||||
|
||||
device_add(&intel_82335_device);
|
||||
device_add(&keyboard_at_ami_device);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
return ret;
|
||||
@@ -456,6 +480,8 @@ machine_at_adi386sx_init(const machine_t *model)
|
||||
|
||||
device_add(&intel_82335_device);
|
||||
device_add(&keyboard_at_ami_device);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
return ret;
|
||||
@@ -502,7 +528,10 @@ machine_at_commodore_sl386sx16_init(const machine_t *model)
|
||||
machine_at_common_ide_init(model);
|
||||
|
||||
device_add(&keyboard_at_device);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
device_add(&neat_device);
|
||||
/* Two serial ports - on the real hardware SL386SX-16, they are on the single UMC UM82C452. */
|
||||
device_add_inst(&ns16450_device, 1);
|
||||
@@ -518,7 +547,10 @@ machine_at_scamp_common_init(const machine_t *model)
|
||||
machine_at_common_ide_init(model);
|
||||
|
||||
device_add(&keyboard_ps2_ami_device);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
device_add(&vlsi_scamp_device);
|
||||
}
|
||||
|
||||
@@ -591,6 +623,8 @@ machine_at_awardsx_init(const machine_t *model)
|
||||
machine_at_init(model);
|
||||
|
||||
device_add(&opti291_device);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
return ret;
|
||||
@@ -671,47 +705,6 @@ machine_at_pja511m_init(const machine_t *model)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
static uint8_t
|
||||
m290_read(uint16_t port, void *priv)
|
||||
{
|
||||
uint8_t ret = 0x0;
|
||||
switch (port) {
|
||||
/*
|
||||
* port 69:
|
||||
* dip-switch bank on mainboard (off=1)
|
||||
* bit 3 - use OCG/CGA display adapter (off) / other display adapter (on)
|
||||
*/
|
||||
case 0x69:
|
||||
if(video_is_cga())
|
||||
ret |= 0x8|0x4;
|
||||
ret |= 0x1|0x2;
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int
|
||||
machine_at_olim290_init(const machine_t *model)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = bios_load_linear(L"roms/machines/olivetti_m290/m290_pep3_1.25.bin",
|
||||
0x000f0000, 65536, 0);
|
||||
|
||||
if (bios_only || !ret)
|
||||
return ret;
|
||||
|
||||
machine_at_common_init(model);
|
||||
device_add(&keyboard_at_device);
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
io_sethandler(0x069, 1, m290_read, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Current bugs:
|
||||
* - ctrl-alt-del produces an 8042 error
|
||||
@@ -730,6 +723,8 @@ machine_at_ncrpc8_init(const machine_t *model)
|
||||
|
||||
machine_at_common_init(model);
|
||||
device_add(&keyboard_at_ncr_device);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
return ret;
|
||||
@@ -758,10 +753,118 @@ machine_at_ncr3302_init(const machine_t *model)
|
||||
machine_at_common_ide_init(model);
|
||||
device_add(&neat_device);
|
||||
device_add(&keyboard_at_ncr_device);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
if (gfxcard == VID_INTERNAL)
|
||||
device_add(¶dise_pvga1a_device);
|
||||
device_add(¶dise_pvga1a_ncr3302_device);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Current bugs:
|
||||
* - soft-reboot after saving CMOS settings/pressing ctrl-alt-del produces an 8042 error
|
||||
*/
|
||||
int
|
||||
machine_at_ncrpc916sx_init(const machine_t *model)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = bios_load_interleaved(L"roms/machines/ncr_pc916sx/ncr_386sx_u46-17_7.3.bin",
|
||||
L"roms/machines/ncr_pc916sx/ncr_386sx_u12-19_7.3.bin",
|
||||
0x000f0000, 65536, 0);
|
||||
|
||||
if (bios_only || !ret)
|
||||
return ret;
|
||||
|
||||
machine_at_common_init(model);
|
||||
|
||||
device_add(&keyboard_at_ncr_device);
|
||||
mem_remap_top(384);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined(DEV_BRANCH) && defined(USE_OLIVETTI)
|
||||
int
|
||||
machine_at_olim290_init(const machine_t *model)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = bios_load_linear(L"roms/machines/olivetti_m290/m290_pep3_1.25.bin",
|
||||
0x000f0000, 65536, 0);
|
||||
|
||||
if (bios_only || !ret)
|
||||
return ret;
|
||||
|
||||
machine_at_common_init(model);
|
||||
device_add(&keyboard_at_olivetti_device);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
device_add(&olivetti_eva_device);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
const device_t *
|
||||
at_m300_08_get_device(void)
|
||||
{
|
||||
return &oti067_m300_device;
|
||||
}
|
||||
|
||||
int
|
||||
machine_at_olim300_08_init(const machine_t *model)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = bios_load_linear(L"roms/machines/olivetti_m300_08/BIOS.ROM",
|
||||
0x000f0000, 65536, 0);
|
||||
|
||||
if (bios_only || !ret)
|
||||
return ret;
|
||||
|
||||
machine_at_common_init(model);
|
||||
|
||||
device_add(&opti283_device);
|
||||
device_add(&keyboard_ps2_olivetti_device);
|
||||
device_add(&pc87310_ide_device);
|
||||
|
||||
if (gfxcard == VID_INTERNAL)
|
||||
device_add(&oti067_m300_device);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Almost identical to M300-08, save for CPU speed, VRAM, and BIOS identification string */
|
||||
int
|
||||
machine_at_olim300_15_init(const machine_t *model)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = bios_load_linear(L"roms/machines/olivetti_m300_15/BIOS.ROM",
|
||||
0x000f0000, 65536, 0);
|
||||
|
||||
if (bios_only || !ret)
|
||||
return ret;
|
||||
|
||||
machine_at_common_init(model);
|
||||
|
||||
device_add(&opti283_device);
|
||||
device_add(&keyboard_ps2_olivetti_device);
|
||||
device_add(&pc87310_ide_device);
|
||||
|
||||
/* Stock VRAM is maxed out, so no need to expose video card config */
|
||||
if (gfxcard == VID_INTERNAL)
|
||||
device_add(&oti067_m300_device);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <86box/pci.h>
|
||||
#include <86box/fdd.h>
|
||||
#include <86box/fdc.h>
|
||||
#include <86box/fdc_ext.h>
|
||||
#include <86box/rom.h>
|
||||
#include <86box/sio.h>
|
||||
#include <86box/hdc.h>
|
||||
@@ -57,6 +58,8 @@ machine_at_acc386_init(const machine_t *model)
|
||||
machine_at_common_init(model);
|
||||
device_add(&acc2168_device);
|
||||
device_add(&keyboard_at_ami_device);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
return ret;
|
||||
@@ -77,6 +80,8 @@ machine_at_asus386_init(const machine_t *model)
|
||||
machine_at_common_init(model);
|
||||
device_add(&rabbit_device);
|
||||
device_add(&keyboard_at_ami_device);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
return ret;
|
||||
@@ -97,6 +102,8 @@ machine_at_sis401_init(const machine_t *model)
|
||||
machine_at_common_ide_init(model);
|
||||
device_add(&sis_85c401_device);
|
||||
device_add(&keyboard_at_ami_device);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
return ret;
|
||||
@@ -117,6 +124,8 @@ machine_at_av4_init(const machine_t *model)
|
||||
machine_at_common_ide_init(model);
|
||||
device_add(&sis_85c460_device);
|
||||
device_add(&keyboard_at_ami_device);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
return ret;
|
||||
@@ -137,6 +146,8 @@ machine_at_valuepoint433_init(const machine_t *model) // hangs without the PS/2
|
||||
machine_at_common_ide_init(model);
|
||||
device_add(&sis_85c461_device);
|
||||
device_add(&keyboard_ps2_device);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
return ret;
|
||||
@@ -157,7 +168,10 @@ machine_at_ecs386_init(const machine_t *model)
|
||||
|
||||
machine_at_common_init(model);
|
||||
device_add(&cs8230_device);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
device_add(&keyboard_at_ami_device);
|
||||
|
||||
return ret;
|
||||
@@ -178,7 +192,10 @@ machine_at_spc6000a_init(const machine_t *model)
|
||||
|
||||
machine_at_common_init_ex(model, 1);
|
||||
device_add(&cs8230_device);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
device_add(&keyboard_at_samsung_device);
|
||||
|
||||
return ret;
|
||||
@@ -200,6 +217,8 @@ machine_at_rycleopardlx_init(const machine_t *model)
|
||||
|
||||
device_add(&opti283_device);
|
||||
device_add(&keyboard_at_ami_device);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
return ret;
|
||||
@@ -221,6 +240,8 @@ machine_at_486vchd_init(const machine_t *model)
|
||||
|
||||
device_add(&via_vt82c49x_device);
|
||||
device_add(&keyboard_at_device);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
return ret;
|
||||
@@ -241,6 +262,8 @@ machine_at_cs4031_init(const machine_t *model)
|
||||
machine_at_common_init(model);
|
||||
device_add(&cs4031_device);
|
||||
device_add(&keyboard_at_ami_device);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
return ret;
|
||||
@@ -326,9 +349,11 @@ machine_at_acera1g_init(const machine_t *model)
|
||||
|
||||
device_add(&ali1429_device);
|
||||
device_add(&keyboard_ps2_acer_pci_device);
|
||||
device_add(&fdc_at_device);
|
||||
device_add(&ide_isa_2ch_device);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -348,6 +373,8 @@ machine_at_ali1429_common_init(const machine_t *model)
|
||||
device_add(&ali1429_device);
|
||||
|
||||
device_add(&keyboard_at_ami_device);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
}
|
||||
|
||||
@@ -402,6 +429,8 @@ machine_at_opti495_init(const machine_t *model)
|
||||
device_add(&opti495_device);
|
||||
|
||||
device_add(&keyboard_at_device);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
return ret;
|
||||
@@ -416,6 +445,8 @@ machine_at_opti495_ami_common_init(const machine_t *model)
|
||||
device_add(&opti495_device);
|
||||
|
||||
device_add(&keyboard_at_ami_device);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
}
|
||||
|
||||
@@ -469,6 +500,8 @@ machine_at_403tg_init(const machine_t *model)
|
||||
device_add(&opti895_device);
|
||||
|
||||
device_add(&keyboard_at_device);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
return ret;
|
||||
@@ -522,6 +555,8 @@ static void
|
||||
machine_at_sis_85c471_common_init(const machine_t *model)
|
||||
{
|
||||
machine_at_common_init(model);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
device_add(&sis_85c471_device);
|
||||
@@ -884,6 +919,8 @@ machine_at_486ap4_init(const machine_t *model)
|
||||
pci_register_slot(0x0b, PCI_CARD_NORMAL, 3, 4, 1, 2); /* 0b = Slot 3 */
|
||||
pci_register_slot(0x0c, PCI_CARD_NORMAL, 4, 1, 2, 3); /* 0c = Slot 4 */
|
||||
device_add(&keyboard_ps2_ami_pci_device); /* Uses the AMIKEY KBC */
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
device_add(&i420ex_device);
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include <86box/timer.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/fdc_ext.h>
|
||||
#include <86box/lpt.h>
|
||||
#include <86box/rom.h>
|
||||
#include <86box/serial.h>
|
||||
@@ -108,7 +109,9 @@ machine_at_cmdpc_init(const machine_t *model)
|
||||
|
||||
mem_remap_top(384);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
cmd_uart = device_add(&i8250_device);
|
||||
|
||||
cbm_io_init();
|
||||
|
||||
71
src/machine/m_at_ebga368.c
Normal file
71
src/machine/m_at_ebga368.c
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Implementation of VIA EBGA368 Based Single Board Computers.
|
||||
*
|
||||
* Note: 86Box doesn't emulate all the components a SBC may have.
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Tiseno100
|
||||
*
|
||||
* Copyright 2016-2019 Miran Grca.
|
||||
* Copyright 2021 Tiseno100.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <86box/86box.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/rom.h>
|
||||
#include <86box/pci.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/chipset.h>
|
||||
#include <86box/hdc.h>
|
||||
#include <86box/hdc_ide.h>
|
||||
#include <86box/keyboard.h>
|
||||
#include <86box/flash.h>
|
||||
#include <86box/sio.h>
|
||||
#include <86box/hwm.h>
|
||||
#include <86box/spd.h>
|
||||
#include <86box/video.h>
|
||||
#include "cpu.h"
|
||||
#include <86box/machine.h>
|
||||
|
||||
int
|
||||
machine_at_arb9673_init(const machine_t *model)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = bios_load_linear(L"roms/machines/arb9673/W9673.v12",
|
||||
0x00080000, 524288, 0);
|
||||
|
||||
if (bios_only || !ret)
|
||||
return ret;
|
||||
|
||||
machine_at_common_init_ex(model, 2);
|
||||
|
||||
pci_init(PCI_CONFIG_TYPE_1);
|
||||
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
|
||||
pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4);
|
||||
pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4);
|
||||
pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1);
|
||||
pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4);
|
||||
device_add(&via_vt8601_device);
|
||||
device_add(&via_vt82c686b_device);
|
||||
device_add(&via_vt82c686_sio_device);
|
||||
device_add(&via_vt82c686_hwm_device);
|
||||
device_add(&keyboard_ps2_ami_pci_device);
|
||||
device_add(&sst_flash_39sf040_device);
|
||||
spd_register(SPD_TYPE_SDRAM, 0xf, 32);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <86box/pci.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/chipset.h>
|
||||
#include <86box/fdc_ext.h>
|
||||
#include <86box/hdc.h>
|
||||
#include <86box/hdc_ide.h>
|
||||
#include <86box/timer.h>
|
||||
@@ -98,7 +99,10 @@ machine_at_award_common_init(const machine_t *model)
|
||||
pci_register_slot(0x06, PCI_CARD_NORMAL, 4, 1, 2, 3); /* 06 = Slot 4 */
|
||||
pci_register_slot(0x07, PCI_CARD_SCSI, 1, 2, 3, 4); /* 07 = SCSI */
|
||||
pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
device_add(&keyboard_ps2_pci_device);
|
||||
}
|
||||
|
||||
|
||||
@@ -163,6 +163,7 @@
|
||||
#include "cpu.h"
|
||||
#include <86box/fdd.h>
|
||||
#include <86box/fdc.h>
|
||||
#include <86box/fdc_ext.h>
|
||||
#include <86box/machine.h>
|
||||
#include <86box/m_at_t3100e.h>
|
||||
|
||||
@@ -761,8 +762,12 @@ int machine_at_t3100e_init(const machine_t *model)
|
||||
machine_at_common_ide_init(model);
|
||||
|
||||
device_add(&keyboard_at_toshiba_device);
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
{
|
||||
device_add(&fdc_at_device);
|
||||
}
|
||||
|
||||
/* Hook up system control port */
|
||||
io_sethandler(0x8084, 0x0001,
|
||||
t3100e_sys_in, NULL, NULL,
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
#include <86box/device.h>
|
||||
#include <86box/fdd.h>
|
||||
#include <86box/fdc.h>
|
||||
#include <86box/fdc_ext.h>
|
||||
#include <86box/nvr.h>
|
||||
#include <86box/nvr_ps2.h>
|
||||
#include <86box/keyboard.h>
|
||||
@@ -1259,6 +1260,8 @@ static void
|
||||
machine_ps2_common_init(const machine_t *model)
|
||||
{
|
||||
machine_common_init(model);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
dma16_init();
|
||||
|
||||
@@ -11,12 +11,13 @@
|
||||
#include <86box/fdd.h>
|
||||
#include <86box/fdc.h>
|
||||
#include <86box/fdc_ext.h>
|
||||
#include <86box/hdc.h>
|
||||
#include <86box/gameport.h>
|
||||
#include <86box/ibm_5161.h>
|
||||
#include <86box/keyboard.h>
|
||||
#include <86box/rom.h>
|
||||
#include <86box/machine.h>
|
||||
|
||||
#include <86box/chipset.h>
|
||||
|
||||
static void
|
||||
machine_xt_common_init(const machine_t *model)
|
||||
@@ -399,58 +400,3 @@ machine_xt_multitechpc700_init(const machine_t *model)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Current bugs and limitations:
|
||||
* - 640-768 conventional memory not usable (should be mapped at address d0000-effff)
|
||||
*/
|
||||
int
|
||||
machine_xt_p3105_init(const machine_t *model)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = bios_load_linear(L"roms/machines/philips_p3105/philipsnms9100.bin",
|
||||
0x000fc000, 16384, 0);
|
||||
|
||||
if (bios_only || !ret)
|
||||
return ret;
|
||||
|
||||
device_add(&keyboard_pc_device);
|
||||
|
||||
machine_xt_common_init(model);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Current bugs and limitations:
|
||||
* - 640-768 conventional memory not usable (should be mapped at address d0000-effff)
|
||||
* - BIOS detects 4 fdds, so hdd letter is E instead of C
|
||||
*/
|
||||
int
|
||||
machine_xt_p3120_init(const machine_t *model)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = bios_load_linear(L"roms/machines/philips_p3120/philips_p3120.bin",
|
||||
0x000f8000, 32768, 0);
|
||||
|
||||
if (bios_only || !ret)
|
||||
return ret;
|
||||
|
||||
device_add(&keyboard_pc_device);
|
||||
|
||||
machine_common_init(model);
|
||||
|
||||
pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
nmi_init();
|
||||
|
||||
if (joystick_type)
|
||||
device_add(&gameport_device);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <86box/timer.h>
|
||||
#include <86box/fdd.h>
|
||||
#include <86box/fdc.h>
|
||||
#include <86box/fdc_ext.h>
|
||||
#include <86box/gameport.h>
|
||||
#include <86box/keyboard.h>
|
||||
|
||||
@@ -169,6 +170,8 @@ machine_xt_lxt3_init(const machine_t *model)
|
||||
pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt);
|
||||
|
||||
device_add(&keyboard_xt_lxt3_device);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_xt_device);
|
||||
nmi_init();
|
||||
if (joystick_type)
|
||||
|
||||
@@ -724,6 +724,9 @@ machine_xt_olim24_init(const machine_t *model)
|
||||
memset(m24_kbd, 0x00, sizeof(olim24_kbd_t));
|
||||
|
||||
machine_common_init(model);
|
||||
|
||||
/* On-board FDC can be disabled only on M24SP */
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_xt_device);
|
||||
|
||||
/* Address 66-67 = mainboard dip-switch settings */
|
||||
@@ -771,7 +774,7 @@ machine_xt_olim240_init(const machine_t *model)
|
||||
*/
|
||||
device_add(&keyboard_at_olivetti_device);
|
||||
|
||||
/* FIXME: make sure this is correct?? */
|
||||
/* FIXME: make sure this is correct?? */
|
||||
device_add(&at_nvr_device);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
@@ -790,6 +793,7 @@ machine_xt_olim240_init(const machine_t *model)
|
||||
* Current bugs:
|
||||
* - 640x400x2 graphics mode not supported (bit 0 of register 0x3de cannot be set)
|
||||
* - optional mouse emulation missing
|
||||
* - setting CPU speed at 4.77MHz sometimes throws a timer error. If the machine is hard-resetted, the error disappears.
|
||||
*/
|
||||
int
|
||||
machine_xt_olim19_init(const machine_t *model)
|
||||
@@ -809,6 +813,8 @@ machine_xt_olim19_init(const machine_t *model)
|
||||
memset(vid, 0x00, sizeof(olim19_vid_t));
|
||||
|
||||
machine_common_init(model);
|
||||
|
||||
/* On-board FDC cannot be disabled */
|
||||
device_add(&fdc_xt_device);
|
||||
|
||||
m19_vid_init(vid);
|
||||
@@ -821,39 +827,3 @@ machine_xt_olim19_init(const machine_t *model)
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* not working, returns timer error */
|
||||
/* it appears to be a rebadged Hitachi HL 320 laptop */
|
||||
int
|
||||
machine_xt_olim15_init(const machine_t *model)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = bios_load_linear(L"roms/machines/olivetti_m15/oliv_m15.bin",
|
||||
0x000fc000, 16384, 0);
|
||||
|
||||
if (bios_only || !ret)
|
||||
return ret;
|
||||
|
||||
machine_common_init(model);
|
||||
|
||||
pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt);
|
||||
|
||||
device_add(&keyboard_xt_olivetti_device);
|
||||
|
||||
device_add(&cga_device);
|
||||
|
||||
/* FIXME: make sure this is correct?? */
|
||||
//device_add(&at_nvr_device);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_xt_device);
|
||||
|
||||
if (joystick_type)
|
||||
device_add(&gameport_device);
|
||||
|
||||
nmi_init();
|
||||
|
||||
return ret;
|
||||
}
|
||||
203
src/machine/m_xt_philips.c
Normal file
203
src/machine/m_xt_philips.c
Normal file
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* 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 Philips XT-compatible machines.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: EngiNerd <webmaster.crrc@yahoo.it>
|
||||
*
|
||||
* Copyright 2020-2021 EngiNerd.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include <86box/86box.h>
|
||||
#include <86box/nmi.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/pit.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/fdd.h>
|
||||
#include <86box/fdc.h>
|
||||
#include <86box/fdc_ext.h>
|
||||
#include <86box/hdc.h>
|
||||
#include <86box/gameport.h>
|
||||
#include <86box/ibm_5161.h>
|
||||
#include <86box/keyboard.h>
|
||||
#include <86box/rom.h>
|
||||
#include <86box/machine.h>
|
||||
#include <86box/chipset.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/video.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t reg;
|
||||
} philips_t;
|
||||
|
||||
#ifdef ENABLE_philips_LOG
|
||||
int philips_do_log = ENABLE_philips_LOG;
|
||||
static void
|
||||
philips_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (philips_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define philips_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
static void
|
||||
philips_write(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
philips_t *dev = (philips_t *) priv;
|
||||
|
||||
switch (port)
|
||||
{
|
||||
/* port 0xc0
|
||||
* bit 7: turbo
|
||||
* bits 4-5: rtc read/set (I2C Bus SDA/SCL?)
|
||||
* bit 2: parity disabled
|
||||
*/
|
||||
case 0xc0:
|
||||
dev->reg = val;
|
||||
if (val & 0x80)
|
||||
cpu_dynamic_switch(cpu);
|
||||
else
|
||||
cpu_dynamic_switch(0);
|
||||
break;
|
||||
}
|
||||
|
||||
philips_log("Philips XT Mainboard: Write %02x at %02x\n", val, port);
|
||||
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
philips_read(uint16_t port, void *priv)
|
||||
{
|
||||
philips_t *dev = (philips_t *) priv;
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
switch (port)
|
||||
{
|
||||
/* port 0xc0
|
||||
* bit 7: turbo
|
||||
* bits 4-5: rtc read/set
|
||||
* bit 2: parity disabled
|
||||
*/
|
||||
case 0xc0:
|
||||
ret = dev->reg;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
philips_log("Philips XT Mainboard: Read %02x at %02x\n", ret, port);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
philips_close(void *priv)
|
||||
{
|
||||
philips_t *dev = (philips_t *) priv;
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
static void *
|
||||
philips_init(const device_t *info)
|
||||
{
|
||||
philips_t *dev = (philips_t *) malloc(sizeof(philips_t));
|
||||
memset(dev, 0, sizeof(philips_t));
|
||||
|
||||
dev->reg = 0x40;
|
||||
|
||||
io_sethandler(0x0c0, 0x01, philips_read, NULL, NULL, philips_write, NULL, NULL, dev);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
const device_t philips_device = {
|
||||
"Philips XT Mainboard",
|
||||
0,
|
||||
0,
|
||||
philips_init, philips_close, NULL,
|
||||
{ NULL }, NULL, NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
machine_xt_philips_common_init(const machine_t *model)
|
||||
{
|
||||
machine_common_init(model);
|
||||
|
||||
pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt);
|
||||
|
||||
/* On-board FDC cannot be disabled */
|
||||
device_add(&fdc_xt_device);
|
||||
|
||||
nmi_init();
|
||||
|
||||
if (joystick_type)
|
||||
device_add(&gameport_device);
|
||||
|
||||
device_add(&keyboard_pc_device);
|
||||
|
||||
device_add(&philips_device);
|
||||
|
||||
device_add(&xta_hd20_device);
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
machine_xt_p3105_init(const machine_t *model)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = bios_load_linear(L"roms/machines/philips_p3105/philipsnms9100.bin",
|
||||
0x000fc000, 16384, 0);
|
||||
|
||||
if (bios_only || !ret)
|
||||
return ret;
|
||||
|
||||
machine_xt_philips_common_init(model);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
machine_xt_p3120_init(const machine_t *model)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = bios_load_linear(L"roms/machines/philips_p3120/philips_p3120.bin",
|
||||
0x000f8000, 32768, 0);
|
||||
|
||||
if (bios_only || !ret)
|
||||
return ret;
|
||||
|
||||
machine_xt_philips_common_init(model);
|
||||
|
||||
device_add(&gc100a_device);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <86box/device.h>
|
||||
#include <86box/fdd.h>
|
||||
#include <86box/fdc.h>
|
||||
#include <86box/fdc_ext.h>
|
||||
#include <86box/nmi.h>
|
||||
#include <86box/nvr.h>
|
||||
#include <86box/gameport.h>
|
||||
@@ -172,7 +173,10 @@ machine_xt_xi8088_init(const machine_t *model)
|
||||
|
||||
/* TODO: set UMBs? See if PCem always sets when we have > 640KB ram and avoids conflicts when a peripheral uses the same memory space */
|
||||
machine_common_init(model);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
device_add(&keyboard_ps2_xi8088_device);
|
||||
nmi_init();
|
||||
device_add(&ibmat_nvr_device);
|
||||
|
||||
@@ -50,6 +50,7 @@ const machine_type_t machine_types[] = {
|
||||
{ "Slot 1", MACHINE_TYPE_SLOT1 },
|
||||
{ "Slot 2", MACHINE_TYPE_SLOT2 },
|
||||
{ "Socket 370", MACHINE_TYPE_SOCKET370 },
|
||||
{ "EBGA 368", MACHINE_TYPE_EBGA368 },
|
||||
{ "Miscellaneous", MACHINE_TYPE_MISC }
|
||||
};
|
||||
|
||||
@@ -73,8 +74,7 @@ const machine_t machines[] = {
|
||||
{ "[8088] NCR PC4i", "pc4i", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 640, 256, 0, machine_xt_ncrpc4i_init, NULL },
|
||||
{ "[8088] Olivetti M19", "m19", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED, 256, 640, 256, 0, machine_xt_olim19_init, NULL },
|
||||
{ "[8088] OpenXT", "openxt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_open_xt_init, NULL },
|
||||
{ "[8088] Philips P3105/NMS9100", "p3105", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 768, 256, 0, machine_xt_p3105_init, NULL },
|
||||
{ "[8088] Philips P3120", "p3120", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 768, 256, 0, machine_xt_p3120_init, NULL },
|
||||
{ "[8088] Philips P3105/NMS9100", "p3105", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_XTA, 256, 768, 256, 0, machine_xt_p3105_init, NULL },
|
||||
{ "[8088] Phoenix XT clone", "pxxt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_pxxt_init, NULL },
|
||||
{ "[8088] Schneider EuroPC", "europc", MACHINE_TYPE_8088, CPU_PKG_8088_EUROPC, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_XTA | MACHINE_MOUSE, 512, 640, 128, 15, machine_europc_init, NULL },
|
||||
{ "[8088] Tandy 1000", "tandy", MACHINE_TYPE_8088, CPU_PKG_8088_EUROPC, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED, 128, 640, 128, 0, machine_tandy_init, tandy1k_get_device },
|
||||
@@ -87,6 +87,7 @@ const machine_t machines[] = {
|
||||
{ "[8088] Zenith Data Systems Z-151/152/161", "zdsz151", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_z151_init, NULL },
|
||||
{ "[8088] Zenith Data Systems Z-159", "zdsz159", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_z159_init, NULL },
|
||||
{ "[8088] Zenith Data Systems SupersPort (Z-184)", "zdsupers", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED, 128, 640, 128, 0, machine_xt_z184_init, z184_get_device },
|
||||
{ "[GC100A] Philips P3120", "p3120", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_XTA, 256, 768, 256, 0, machine_xt_p3120_init, NULL },
|
||||
|
||||
/* 8086 Machines */
|
||||
{ "[8086] Amstrad PC1512", "pc1512", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 8000000, 8000000, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED | MACHINE_MOUSE, 512, 640, 128, 63, machine_pc1512_init, pc1512_get_device },
|
||||
@@ -122,7 +123,9 @@ const machine_t machines[] = {
|
||||
{ "[ISA] Compaq Portable III", "portableiii", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_VIDEO, 640, 16384, 128, 127, machine_at_portableiii_init, at_cpqiii_get_device },
|
||||
{ "[ISA] MR 286 clone", "mr286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 512, 16384, 128, 127, machine_at_mr286_init, NULL },
|
||||
{ "[ISA] NCR PC8/810/710/3390/3392", "pc8", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_ncrpc8_init, NULL },
|
||||
#if defined(DEV_BRANCH) && defined(USE_OLIVETTI)
|
||||
{ "[ISA] Olivetti M290", "m290", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 640, 16384, 128, 127, machine_at_olim290_init, NULL },
|
||||
#endif
|
||||
#if defined(DEV_BRANCH) && defined(USE_OPEN_AT)
|
||||
{ "[ISA] OpenAT", "open_at", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 256, 15872, 128, 63, machine_at_open_at_init, NULL },
|
||||
#endif
|
||||
@@ -143,13 +146,14 @@ const machine_t machines[] = {
|
||||
{ "[SCAT] Samsung SPC-4216P", "spc4216p", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2, 1024, 5120,1024, 127, machine_at_spc4216p_init, NULL },
|
||||
{ "[SCAT] Samsung SPC-4620P", "spc4620p", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_VIDEO, 1024, 5120,1024, 127, machine_at_spc4620p_init, NULL },
|
||||
{ "[SCAT] Samsung Deskmaster 286", "deskmaster286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_deskmaster286_init, NULL },
|
||||
|
||||
|
||||
/* 286 machines that utilize the MCA bus */
|
||||
{ "[MCA] IBM PS/2 model 50", "ibmps2_m50", MACHINE_TYPE_286, CPU_PKG_286 | CPU_PKG_486SLC_IBM, 0, 10000000, 0, 0, 0, 0, 0, MACHINE_MCA | MACHINE_BUS_PS2 | MACHINE_VIDEO, 1024, 10240,1024, 63, machine_ps2_model_50_init, NULL },
|
||||
|
||||
/* 386SX machines */
|
||||
{ "[ISA] IBM PS/1 model 2121", "ibmps1_2121", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO_FIXED, 2048, 6144,1024, 63, machine_ps1_m2121_init, NULL },
|
||||
{ "[ISA] IBM PS/1 m.2121+ISA", "ibmps1_2121_isa", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 6144,1024, 63, machine_ps1_m2121_init, NULL },
|
||||
{ "[ISA] NCR PC916SX", "ncr_pc916sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 128, 127, machine_at_ncrpc916sx_init, NULL },
|
||||
#if defined(DEV_BRANCH) && defined(USE_M6117)
|
||||
{ "[ALi M6117D] Acrosser AR-B1375", "arb1375", MACHINE_TYPE_386SX, CPU_PKG_M6117, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 32768,1024, 127, machine_at_arb1375_init, NULL },
|
||||
{ "[ALi M6117D] Acrosser PJ-A511M", "pja511m", MACHINE_TYPE_386SX, CPU_PKG_M6117, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 32768,1024, 127, machine_at_pja511m_init, NULL },
|
||||
@@ -160,6 +164,8 @@ const machine_t machines[] = {
|
||||
{ "[Intel 82335] Shuttle 386SX", "shuttle386sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_shuttle386sx_init, NULL },
|
||||
{ "[NEAT] Commodore SL386SX-16", "cmdsl386sx16", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 8192, 512, 127, machine_at_commodore_sl386sx16_init, NULL },
|
||||
{ "[NEAT] DTK 386SX clone", "dtk386", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_neat_init, NULL },
|
||||
{ "[OPTi 283] Olivetti M300-08", "olivetti_m300_08", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 20000000, 20000000, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 16384, 2048, 127, machine_at_olim300_08_init, at_m300_08_get_device },
|
||||
{ "[OPTi 283] Olivetti M300-15", "olivetti_m300_15", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 25000000, 25000000, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 16384, 2048, 127, machine_at_olim300_15_init, NULL },
|
||||
{ "[OPTi 291] DTK PPM-3333P", "awardsx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 1024, 127, machine_at_awardsx_init, NULL },
|
||||
{ "[SCAMP] Commodore SL386SX-25", "cmdsl386sx16", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 1024, 8192, 512, 127, machine_at_commodore_sl386sx25_init, at_commodore_sl386sx25_get_device },
|
||||
{ "[SCAMP] Samsung SPC-6033P", "spc6033p", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 12288, 2048, 127, machine_at_spc6033p_init, at_spc6033p_get_device },
|
||||
@@ -428,6 +434,10 @@ const machine_t machines[] = {
|
||||
{ "[VIA Apollo Pro133A] Acorp 6VIA90AP", "6via90ap", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 150000000, 1300, 3500, MACHINE_MULTIPLIER_FIXED, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1572864, 8192, 255, machine_at_6via90ap_init, NULL },
|
||||
{ "[VIA Apollo ProMedia] Jetway 603TCF", "603tcf", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 150000000, 1300, 3500, 2.0, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_603tcf_init, NULL },
|
||||
|
||||
/* EBGA368 machines */
|
||||
/* VIA Apollo Pro */
|
||||
{ "[VIA Apollo ProMedia] Acrosser AR-B9673", "arb9673", MACHINE_TYPE_EBGA368, CPU_PKG_EBGA368, 0, 66666667, 150000000, 1300, 3500, 2.0, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 131072,131072, 0, 31, machine_at_arb9673_init, NULL },
|
||||
|
||||
/* Miscellaneous/Fake/Hypervisor machines */
|
||||
{ "[i440BX] Microsoft Virtual PC 2007", "vpc2007", MACHINE_TYPE_MISC, CPU_PKG_SLOT1, CPU_BLOCK(CPU_PENTIUM2, CPU_CYRIX3S), 0, 0, 0, 0, 0, 0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_vpc2007_init, NULL },
|
||||
|
||||
|
||||
541
src/minitrace/minitrace.c
Normal file
541
src/minitrace/minitrace.c
Normal file
@@ -0,0 +1,541 @@
|
||||
// minitrace
|
||||
// Copyright 2014 by Henrik Rydgård
|
||||
// http://www.github.com/hrydgard/minitrace
|
||||
// Released under the MIT license.
|
||||
|
||||
// See minitrace.h for basic documentation.
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma warning (disable:4996)
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#ifndef __MINGW32__
|
||||
#define __thread __declspec(thread)
|
||||
#endif
|
||||
#define pthread_cond_t CONDITION_VARIABLE
|
||||
#define pthread_cond_init(a) InitializeConditionVariable(a)
|
||||
#define pthread_cond_wait(a, b) SleepConditionVariableCS(a, b, INFINITE)
|
||||
#define pthread_cond_signal(a) WakeConditionVariable(a)
|
||||
#define pthread_mutex_t CRITICAL_SECTION
|
||||
#define pthread_mutex_init(a, b) InitializeCriticalSection(a)
|
||||
#define pthread_mutex_lock(a) EnterCriticalSection(a)
|
||||
#define pthread_mutex_unlock(a) LeaveCriticalSection(a)
|
||||
#define pthread_mutex_destroy(a) DeleteCriticalSection(a)
|
||||
#else
|
||||
#include <signal.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <minitrace/minitrace.h>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define ATTR_NORETURN __attribute__((noreturn))
|
||||
#else
|
||||
#define ATTR_NORETURN
|
||||
#endif
|
||||
|
||||
#define ARRAY_SIZE(x) sizeof(x)/sizeof(x[0])
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
// Ugh, this struct is already pretty heavy.
|
||||
// Will probably need to move arguments to a second buffer to support more than one.
|
||||
typedef struct raw_event {
|
||||
const char *name;
|
||||
const char *cat;
|
||||
void *id;
|
||||
int64_t ts;
|
||||
uint32_t pid;
|
||||
uint32_t tid;
|
||||
char ph;
|
||||
mtr_arg_type arg_type;
|
||||
const char *arg_name;
|
||||
union {
|
||||
const char *a_str;
|
||||
int a_int;
|
||||
double a_double;
|
||||
};
|
||||
} raw_event_t;
|
||||
|
||||
static raw_event_t *event_buffer;
|
||||
static raw_event_t *flush_buffer;
|
||||
static volatile int event_count;
|
||||
static __attribute__ ((aligned (32))) volatile long is_tracing = FALSE;
|
||||
static __attribute__ ((aligned (32))) volatile long stop_flushing_requested = FALSE;
|
||||
static int is_flushing = FALSE;
|
||||
static int events_in_progress = 0;
|
||||
static int64_t time_offset;
|
||||
static int first_line = 1;
|
||||
static FILE *f;
|
||||
static __thread int cur_thread_id; // Thread local storage
|
||||
static int cur_process_id;
|
||||
static pthread_mutex_t mutex;
|
||||
static pthread_mutex_t event_mutex;
|
||||
static pthread_cond_t buffer_not_full_cond;
|
||||
static pthread_cond_t buffer_full_cond;
|
||||
|
||||
#define STRING_POOL_SIZE 100
|
||||
static char *str_pool[100];
|
||||
|
||||
// forward declaration
|
||||
void mtr_flush_with_state(int);
|
||||
|
||||
// Tiny portability layer.
|
||||
// Exposes:
|
||||
// get_cur_thread_id()
|
||||
// get_cur_process_id()
|
||||
// mtr_time_s()
|
||||
// pthread basics
|
||||
#ifdef _WIN32
|
||||
#define atomic_load(a) InterlockedOr((a), 0)
|
||||
#define atomic_store(a, b) InterlockedExchange((a), b)
|
||||
|
||||
static int get_cur_thread_id() {
|
||||
return (int)GetCurrentThreadId();
|
||||
}
|
||||
static int get_cur_process_id() {
|
||||
return (int)GetCurrentProcessId();
|
||||
}
|
||||
|
||||
static uint64_t _frequency = 0;
|
||||
static uint64_t _starttime = 0;
|
||||
double mtr_time_s() {
|
||||
if (_frequency == 0) {
|
||||
QueryPerformanceFrequency((LARGE_INTEGER*)&_frequency);
|
||||
QueryPerformanceCounter((LARGE_INTEGER*)&_starttime);
|
||||
}
|
||||
__int64 time;
|
||||
QueryPerformanceCounter((LARGE_INTEGER*)&time);
|
||||
return ((double) (time - _starttime) / (double) _frequency);
|
||||
}
|
||||
|
||||
// Ctrl+C handling for Windows console apps
|
||||
static BOOL WINAPI CtrlHandler(DWORD fdwCtrlType) {
|
||||
if (atomic_load(&is_tracing) && fdwCtrlType == CTRL_C_EVENT) {
|
||||
printf("Ctrl-C detected! Flushing trace and shutting down.\n\n");
|
||||
mtr_flush();
|
||||
mtr_shutdown();
|
||||
}
|
||||
ExitProcess(1);
|
||||
}
|
||||
|
||||
void mtr_register_sigint_handler() {
|
||||
// For console apps:
|
||||
SetConsoleCtrlHandler(&CtrlHandler, TRUE);
|
||||
}
|
||||
|
||||
HANDLE thread_handle;
|
||||
|
||||
static DWORD WINAPI thread_flush_proc(void* param) {
|
||||
while(TRUE) {
|
||||
mtr_flush_with_state(FALSE);
|
||||
if(atomic_load(&stop_flushing_requested)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void init_flushing_thread(void) {
|
||||
pthread_mutex_lock(&mutex);
|
||||
is_flushing = FALSE;
|
||||
pthread_mutex_unlock(&mutex);
|
||||
thread_handle = CreateThread(NULL, 0, thread_flush_proc, (void*)0, 0, NULL);
|
||||
}
|
||||
|
||||
static void join_flushing_thread(void) {
|
||||
WaitForSingleObject(thread_handle, INFINITE);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline int get_cur_thread_id() {
|
||||
return (int)(intptr_t)pthread_self();
|
||||
}
|
||||
static inline int get_cur_process_id() {
|
||||
return (int)getpid();
|
||||
}
|
||||
|
||||
#if defined(BLACKBERRY)
|
||||
double mtr_time_s() {
|
||||
struct timespec time;
|
||||
clock_gettime(CLOCK_MONOTONIC, &time); // Linux must use CLOCK_MONOTONIC_RAW due to time warps
|
||||
return time.tv_sec + time.tv_nsec / 1.0e9;
|
||||
}
|
||||
#else
|
||||
double mtr_time_s() {
|
||||
static time_t start;
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
if (start == 0) {
|
||||
start = tv.tv_sec;
|
||||
}
|
||||
tv.tv_sec -= start;
|
||||
return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0;
|
||||
}
|
||||
#endif // !BLACKBERRY
|
||||
|
||||
static void termination_handler(int signum) ATTR_NORETURN;
|
||||
static void termination_handler(int signum) {
|
||||
(void) signum;
|
||||
if (is_tracing) {
|
||||
printf("Ctrl-C detected! Flushing trace and shutting down.\n\n");
|
||||
mtr_flush();
|
||||
fwrite("\n]}\n", 1, 4, f);
|
||||
fclose(f);
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void mtr_register_sigint_handler() {
|
||||
#ifndef MTR_ENABLED
|
||||
return;
|
||||
#endif
|
||||
// Avoid altering set-to-be-ignored handlers while registering.
|
||||
if (signal(SIGINT, &termination_handler) == SIG_IGN)
|
||||
signal(SIGINT, SIG_IGN);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void mtr_init_from_stream(void *stream) {
|
||||
#ifndef MTR_ENABLED
|
||||
return;
|
||||
#endif
|
||||
event_buffer = (raw_event_t *)malloc(INTERNAL_MINITRACE_BUFFER_SIZE * sizeof(raw_event_t));
|
||||
flush_buffer = (raw_event_t *)malloc(INTERNAL_MINITRACE_BUFFER_SIZE * sizeof(raw_event_t));
|
||||
event_count = 0;
|
||||
f = (FILE *)stream;
|
||||
const char *header = "{\"traceEvents\":[\n";
|
||||
fwrite(header, 1, strlen(header), f);
|
||||
time_offset = (uint64_t)(mtr_time_s() * 1000000);
|
||||
first_line = 1;
|
||||
pthread_mutex_init(&mutex, 0);
|
||||
pthread_mutex_init(&event_mutex, 0);
|
||||
}
|
||||
|
||||
void mtr_init(const char *json_file) {
|
||||
#ifndef MTR_ENABLED
|
||||
return;
|
||||
#endif
|
||||
mtr_init_from_stream(fopen(json_file, "wb"));
|
||||
}
|
||||
|
||||
void mtr_shutdown() {
|
||||
int i;
|
||||
#ifndef MTR_ENABLED
|
||||
return;
|
||||
#endif
|
||||
|
||||
mtr_flush_with_state(TRUE);
|
||||
|
||||
fwrite("\n]}\n", 1, 4, f);
|
||||
fclose(f);
|
||||
pthread_mutex_destroy(&mutex);
|
||||
pthread_mutex_destroy(&event_mutex);
|
||||
f = 0;
|
||||
free(event_buffer);
|
||||
event_buffer = 0;
|
||||
for (i = 0; i < STRING_POOL_SIZE; i++) {
|
||||
if (str_pool[i]) {
|
||||
free(str_pool[i]);
|
||||
str_pool[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char *mtr_pool_string(const char *str) {
|
||||
int i;
|
||||
for (i = 0; i < STRING_POOL_SIZE; i++) {
|
||||
if (!str_pool[i]) {
|
||||
str_pool[i] = (char*)malloc(strlen(str) + 1);
|
||||
strcpy(str_pool[i], str);
|
||||
return str_pool[i];
|
||||
} else {
|
||||
if (!strcmp(str, str_pool[i]))
|
||||
return str_pool[i];
|
||||
}
|
||||
}
|
||||
return "string pool full";
|
||||
}
|
||||
|
||||
void mtr_start() {
|
||||
#ifndef MTR_ENABLED
|
||||
return;
|
||||
#endif
|
||||
pthread_cond_init(&buffer_not_full_cond);
|
||||
pthread_cond_init(&buffer_full_cond);
|
||||
atomic_store(&is_tracing, TRUE);
|
||||
init_flushing_thread();
|
||||
}
|
||||
|
||||
void mtr_stop() {
|
||||
#ifndef MTR_ENABLED
|
||||
return;
|
||||
#endif
|
||||
atomic_store(&is_tracing, FALSE);
|
||||
atomic_store(&stop_flushing_requested, TRUE);
|
||||
pthread_cond_signal(&buffer_not_full_cond);
|
||||
pthread_cond_signal(&buffer_full_cond);
|
||||
join_flushing_thread();
|
||||
atomic_store(&stop_flushing_requested, FALSE);
|
||||
}
|
||||
|
||||
// TODO: fwrite more than one line at a time.
|
||||
// Flushing is thread safe and process async
|
||||
// using double-buffering mechanism.
|
||||
// Aware: only one flushing process may be
|
||||
// running at any point of time
|
||||
void mtr_flush_with_state(int is_last) {
|
||||
#ifndef MTR_ENABLED
|
||||
return;
|
||||
#endif
|
||||
int i = 0;
|
||||
char linebuf[1024];
|
||||
char arg_buf[1024];
|
||||
char id_buf[256];
|
||||
int event_count_copy = 0;
|
||||
int events_in_progress_copy = 1;
|
||||
raw_event_t *event_buffer_tmp = NULL;
|
||||
|
||||
// small critical section to swap buffers
|
||||
// - no any new events can be spawn while
|
||||
// swapping since they tied to the same mutex
|
||||
// - checks for any flushing in process
|
||||
pthread_mutex_lock(&mutex);
|
||||
// if not flushing already
|
||||
if (is_flushing) {
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return;
|
||||
}
|
||||
is_flushing = TRUE;
|
||||
if(!is_last) {
|
||||
while(event_count < INTERNAL_MINITRACE_BUFFER_SIZE && atomic_load(&is_tracing)) {
|
||||
pthread_cond_wait(&buffer_full_cond, &mutex);
|
||||
}
|
||||
}
|
||||
event_count_copy = event_count;
|
||||
event_buffer_tmp = flush_buffer;
|
||||
flush_buffer = event_buffer;
|
||||
event_buffer = event_buffer_tmp;
|
||||
event_count = 0;
|
||||
// waiting for any unfinished events before swap
|
||||
while (events_in_progress_copy != 0) {
|
||||
pthread_mutex_lock(&event_mutex);
|
||||
events_in_progress_copy = events_in_progress;
|
||||
pthread_mutex_unlock(&event_mutex);
|
||||
}
|
||||
pthread_mutex_unlock(&mutex);
|
||||
pthread_cond_signal(&buffer_not_full_cond);
|
||||
|
||||
for (i = 0; i < event_count_copy; i++) {
|
||||
raw_event_t *raw = &flush_buffer[i];
|
||||
int len;
|
||||
switch (raw->arg_type) {
|
||||
case MTR_ARG_TYPE_INT:
|
||||
snprintf(arg_buf, ARRAY_SIZE(arg_buf), "\"%s\":%i", raw->arg_name, raw->a_int);
|
||||
break;
|
||||
case MTR_ARG_TYPE_STRING_CONST:
|
||||
snprintf(arg_buf, ARRAY_SIZE(arg_buf), "\"%s\":\"%s\"", raw->arg_name, raw->a_str);
|
||||
break;
|
||||
case MTR_ARG_TYPE_STRING_COPY:
|
||||
if (strlen(raw->a_str) > 700) {
|
||||
snprintf(arg_buf, ARRAY_SIZE(arg_buf), "\"%s\":\"%.*s\"", raw->arg_name, 700, raw->a_str);
|
||||
} else {
|
||||
snprintf(arg_buf, ARRAY_SIZE(arg_buf), "\"%s\":\"%s\"", raw->arg_name, raw->a_str);
|
||||
}
|
||||
break;
|
||||
case MTR_ARG_TYPE_NONE:
|
||||
arg_buf[0] = '\0';
|
||||
break;
|
||||
}
|
||||
if (raw->id) {
|
||||
switch (raw->ph) {
|
||||
case 'S':
|
||||
case 'T':
|
||||
case 'F':
|
||||
// TODO: Support full 64-bit pointers
|
||||
snprintf(id_buf, ARRAY_SIZE(id_buf), ",\"id\":\"0x%08x\"", (uint32_t)(uintptr_t)raw->id);
|
||||
break;
|
||||
case 'X':
|
||||
snprintf(id_buf, ARRAY_SIZE(id_buf), ",\"dur\":%i", (int)raw->a_double);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
id_buf[0] = 0;
|
||||
}
|
||||
const char *cat = raw->cat;
|
||||
#ifdef _WIN32
|
||||
// On Windows, we often end up with backslashes in category.
|
||||
char temp[256];
|
||||
{
|
||||
int len = (int)strlen(cat);
|
||||
int i;
|
||||
if (len > 255) len = 255;
|
||||
for (i = 0; i < len; i++) {
|
||||
temp[i] = cat[i] == '\\' ? '/' : cat[i];
|
||||
}
|
||||
temp[len] = 0;
|
||||
cat = temp;
|
||||
}
|
||||
#endif
|
||||
|
||||
len = snprintf(linebuf, ARRAY_SIZE(linebuf), "%s{\"cat\":\"%s\",\"pid\":%i,\"tid\":%i,\"ts\":%" PRId64 ",\"ph\":\"%c\",\"name\":\"%s\",\"args\":{%s}%s}",
|
||||
first_line ? "" : ",\n",
|
||||
cat, raw->pid, raw->tid, raw->ts - time_offset, raw->ph, raw->name, arg_buf, id_buf);
|
||||
fwrite(linebuf, 1, len, f);
|
||||
first_line = 0;
|
||||
|
||||
if (raw->arg_type == MTR_ARG_TYPE_STRING_COPY) {
|
||||
free((void*)raw->a_str);
|
||||
}
|
||||
#ifdef MTR_COPY_EVENT_CATEGORY_AND_NAME
|
||||
free(raw->name);
|
||||
free(raw->cat);
|
||||
#endif
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
is_flushing = is_last;
|
||||
pthread_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
void mtr_flush() {
|
||||
mtr_flush_with_state(FALSE);
|
||||
}
|
||||
|
||||
void internal_mtr_raw_event(const char *category, const char *name, char ph, void *id) {
|
||||
#ifndef MTR_ENABLED
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (!atomic_load(&is_tracing)) {
|
||||
return;
|
||||
}
|
||||
pthread_mutex_lock(&mutex);
|
||||
while(event_count >= INTERNAL_MINITRACE_BUFFER_SIZE && atomic_load(&is_tracing)) {
|
||||
pthread_cond_wait(&buffer_not_full_cond, &mutex);
|
||||
}
|
||||
raw_event_t *ev = &event_buffer[event_count];
|
||||
++event_count;
|
||||
pthread_mutex_lock(&event_mutex);
|
||||
++events_in_progress;
|
||||
pthread_mutex_unlock(&event_mutex);
|
||||
int local_event_count = event_count;
|
||||
pthread_mutex_unlock(&mutex);
|
||||
if(local_event_count >= INTERNAL_MINITRACE_BUFFER_SIZE) {
|
||||
pthread_cond_signal(&buffer_full_cond);
|
||||
}
|
||||
|
||||
double ts = mtr_time_s();
|
||||
|
||||
if (!cur_thread_id) {
|
||||
cur_thread_id = get_cur_thread_id();
|
||||
}
|
||||
if (!cur_process_id) {
|
||||
cur_process_id = get_cur_process_id();
|
||||
}
|
||||
|
||||
#ifdef MTR_COPY_EVENT_CATEGORY_AND_NAME
|
||||
const size_t category_len = strlen(category);
|
||||
ev->cat = malloc(category_len + 1);
|
||||
strcpy(ev->cat, category);
|
||||
|
||||
const size_t name_len = strlen(name);
|
||||
ev->name = malloc(name_len + 1);
|
||||
strcpy(ev->name, name);
|
||||
|
||||
#else
|
||||
ev->cat = category;
|
||||
ev->name = name;
|
||||
#endif
|
||||
|
||||
ev->id = id;
|
||||
ev->ph = ph;
|
||||
if (ev->ph == 'X') {
|
||||
double x;
|
||||
memcpy(&x, id, sizeof(double));
|
||||
ev->ts = (int64_t)(x * 1000000);
|
||||
ev->a_double = (ts - x) * 1000000;
|
||||
} else {
|
||||
ev->ts = (int64_t)(ts * 1000000);
|
||||
}
|
||||
ev->tid = cur_thread_id;
|
||||
ev->pid = cur_process_id;
|
||||
ev->arg_type = MTR_ARG_TYPE_NONE;
|
||||
|
||||
pthread_mutex_lock(&event_mutex);
|
||||
--events_in_progress;
|
||||
pthread_mutex_unlock(&event_mutex);
|
||||
}
|
||||
|
||||
void internal_mtr_raw_event_arg(const char *category, const char *name, char ph, void *id, mtr_arg_type arg_type, const char *arg_name, void *arg_value) {
|
||||
#ifndef MTR_ENABLED
|
||||
return;
|
||||
#endif
|
||||
if (!atomic_load(&is_tracing)) {
|
||||
return;
|
||||
}
|
||||
pthread_mutex_lock(&mutex);
|
||||
while(event_count >= INTERNAL_MINITRACE_BUFFER_SIZE && atomic_load(&is_tracing)) {
|
||||
pthread_cond_wait(&buffer_not_full_cond, &mutex);
|
||||
}
|
||||
raw_event_t *ev = &event_buffer[event_count];
|
||||
++event_count;
|
||||
pthread_mutex_lock(&event_mutex);
|
||||
++events_in_progress;
|
||||
pthread_mutex_unlock(&event_mutex);
|
||||
int local_event_count = event_count;
|
||||
pthread_mutex_unlock(&mutex);
|
||||
if(local_event_count >= INTERNAL_MINITRACE_BUFFER_SIZE) {
|
||||
pthread_cond_signal(&buffer_full_cond);
|
||||
}
|
||||
|
||||
|
||||
if (!cur_thread_id) {
|
||||
cur_thread_id = get_cur_thread_id();
|
||||
}
|
||||
if (!cur_process_id) {
|
||||
cur_process_id = get_cur_process_id();
|
||||
}
|
||||
double ts = mtr_time_s();
|
||||
|
||||
#ifdef MTR_COPY_EVENT_CATEGORY_AND_NAME
|
||||
const size_t category_len = strlen(category);
|
||||
ev->cat = malloc(category_len + 1);
|
||||
strcpy(ev->cat, category);
|
||||
|
||||
const size_t name_len = strlen(name);
|
||||
ev->name = malloc(name_len + 1);
|
||||
strcpy(ev->name, name);
|
||||
|
||||
#else
|
||||
ev->cat = category;
|
||||
ev->name = name;
|
||||
#endif
|
||||
|
||||
ev->id = id;
|
||||
ev->ts = (int64_t)(ts * 1000000);
|
||||
ev->ph = ph;
|
||||
ev->tid = cur_thread_id;
|
||||
ev->pid = cur_process_id;
|
||||
ev->arg_type = arg_type;
|
||||
ev->arg_name = arg_name;
|
||||
switch (arg_type) {
|
||||
case MTR_ARG_TYPE_INT: ev->a_int = (int)(uintptr_t)arg_value; break;
|
||||
case MTR_ARG_TYPE_STRING_CONST: ev->a_str = (const char*)arg_value; break;
|
||||
case MTR_ARG_TYPE_STRING_COPY: ev->a_str = strdup((const char*)arg_value); break;
|
||||
case MTR_ARG_TYPE_NONE: break;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&event_mutex);
|
||||
--events_in_progress;
|
||||
pthread_mutex_unlock(&event_mutex);
|
||||
}
|
||||
|
||||
3
src/pc.c
3
src/pc.c
@@ -89,6 +89,9 @@ int dopause, /* system is paused */
|
||||
uint64_t timer_freq;
|
||||
char emu_version[200]; /* version ID string */
|
||||
|
||||
#ifdef MTR_ENABLED
|
||||
int tracing_on = 0;
|
||||
#endif
|
||||
|
||||
/* Commandline options. */
|
||||
int dump_on_exit = 0; /* (O) dump regs on exit */
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
#define SYM53C860_SDMS4_ROM L"roms/scsi/ncr53c8xx/860/8XX_64.ROM"
|
||||
#define NCR53C875_SDMS3_ROM L"roms/scsi/ncr53c8xx/875/NCR307.BIN"
|
||||
#define SYM53C875_SDMS4_ROM L"roms/scsi/ncr53c8xx/875/8XX_64.ROM"
|
||||
// #define SYM53C875_SDMS4_ROM L"roms/scsi/ncr53c8xx/875/8xx_64.rom.419"
|
||||
|
||||
#define HA_ID 7
|
||||
|
||||
@@ -217,7 +218,7 @@ typedef enum
|
||||
typedef struct {
|
||||
wchar_t *nvr_path;
|
||||
uint8_t pci_slot;
|
||||
uint8_t chip;
|
||||
uint8_t chip, wide;
|
||||
int has_bios;
|
||||
int BIOSBase;
|
||||
rom_t bios;
|
||||
@@ -314,6 +315,8 @@ typedef struct {
|
||||
uint8_t regop;
|
||||
uint32_t adder;
|
||||
|
||||
uint32_t bios_mask;
|
||||
|
||||
pc_timer_t timer;
|
||||
|
||||
#ifdef USE_WDTR
|
||||
@@ -412,7 +415,7 @@ ncr53c8xx_soft_reset(ncr53c8xx_t *dev)
|
||||
dev->scntl0 = 0xc0;
|
||||
dev->scntl1 = 0;
|
||||
dev->scntl2 = 0;
|
||||
if (dev->chip >= CHIP_825)
|
||||
if (dev->wide)
|
||||
dev->scntl3 = 8;
|
||||
else
|
||||
dev->scntl3 = 0;
|
||||
@@ -439,7 +442,7 @@ ncr53c8xx_soft_reset(ncr53c8xx_t *dev)
|
||||
dev->sstop = 1;
|
||||
dev->gpcntl = 0x03;
|
||||
|
||||
if (dev->chip >= CHIP_825) {
|
||||
if (dev->wide) {
|
||||
/* This *IS* a wide SCSI controller, so reset all SCSI
|
||||
devices. */
|
||||
for (i = 0; i < 16; i++) {
|
||||
@@ -1671,7 +1674,7 @@ ncr53c8xx_reg_writeb(ncr53c8xx_t *dev, uint32_t offset, uint8_t val)
|
||||
dev->respid0 = val;
|
||||
break;
|
||||
case 0x4b: /* RESPID1 */
|
||||
if (dev->chip >= CHIP_825)
|
||||
if (dev->wide)
|
||||
dev->respid1 = val;
|
||||
break;
|
||||
case 0x4d: /* STEST1 */
|
||||
@@ -1723,19 +1726,19 @@ ncr53c8xx_reg_readb(ncr53c8xx_t *dev, uint32_t offset)
|
||||
case addr + 3: return (dev->name >> 24) & 0xff;
|
||||
|
||||
#define CASE_GET_REG32_COND(name, addr) \
|
||||
case addr: if (dev->chip >= CHIP_825) \
|
||||
case addr: if (dev->wide) \
|
||||
return dev->name & 0xff; \
|
||||
else \
|
||||
return 0x00; \
|
||||
case addr + 1: if (dev->chip >= CHIP_825) \
|
||||
case addr + 1: if (dev->wide) \
|
||||
return (dev->name >> 8) & 0xff; \
|
||||
else \
|
||||
return 0x00; \
|
||||
case addr + 2: if (dev->chip >= CHIP_825) \
|
||||
case addr + 2: if (dev->wide) \
|
||||
return (dev->name >> 16) & 0xff; \
|
||||
else \
|
||||
return 0x00; \
|
||||
case addr + 3: if (dev->chip >= CHIP_825) \
|
||||
case addr + 3: if (dev->wide) \
|
||||
return (dev->name >> 24) & 0xff; \
|
||||
else \
|
||||
return 0x00;
|
||||
@@ -1819,12 +1822,12 @@ ncr53c8xx_reg_readb(ncr53c8xx_t *dev, uint32_t offset)
|
||||
tmp = dev->istat;
|
||||
return tmp;
|
||||
case 0x16: /* MBOX0 */
|
||||
if (dev->chip >= CHIP_825)
|
||||
if (dev->wide)
|
||||
return 0x00;
|
||||
ncr53c8xx_log("NCR 810: Read MBOX0 %02X\n", dev->mbox0);
|
||||
return dev->mbox0;
|
||||
case 0x17: /* MBOX1 */
|
||||
if (dev->chip >= CHIP_825)
|
||||
if (dev->wide)
|
||||
return 0x00;
|
||||
ncr53c8xx_log("NCR 810: Read MBOX1 %02X\n", dev->mbox1);
|
||||
return dev->mbox1;
|
||||
@@ -1899,12 +1902,12 @@ ncr53c8xx_reg_readb(ncr53c8xx_t *dev, uint32_t offset)
|
||||
ncr53c8xx_log("NCR 810: Read SIST1 %02X\n", tmp);
|
||||
return tmp;
|
||||
case 0x44: /* SLPAR */
|
||||
if (dev->chip < CHIP_825)
|
||||
if (!dev->wide)
|
||||
return 0x00;
|
||||
ncr53c8xx_log("NCR 810: Read SLPAR %02X\n", dev->stime0);
|
||||
return dev->slpar;
|
||||
case 0x45: /* SWIDE */
|
||||
if (dev->chip < CHIP_825)
|
||||
if (!dev->wide)
|
||||
return 0x00;
|
||||
ncr53c8xx_log("NCR 810: Read SWIDE %02X\n", dev->stime0);
|
||||
return dev->swide;
|
||||
@@ -1918,13 +1921,14 @@ ncr53c8xx_reg_readb(ncr53c8xx_t *dev, uint32_t offset)
|
||||
ncr53c8xx_log("NCR 810: Read STIME0 %02X\n", dev->stime0);
|
||||
return dev->stime0;
|
||||
case 0x4a: /* RESPID0 */
|
||||
if (dev->chip >= CHIP_825)
|
||||
if (dev->wide) {
|
||||
ncr53c8xx_log("NCR 810: Read RESPID0 %02X\n", dev->respid0);
|
||||
else
|
||||
} else {
|
||||
ncr53c8xx_log("NCR 810: Read RESPID %02X\n", dev->respid0);
|
||||
}
|
||||
return dev->respid0;
|
||||
case 0x4b: /* RESPID1 */
|
||||
if (dev->chip < CHIP_825)
|
||||
if (!dev->wide)
|
||||
return 0x00;
|
||||
ncr53c8xx_log("NCR 810: Read RESPID1 %02X\n", dev->respid1);
|
||||
return dev->respid1;
|
||||
@@ -1943,13 +1947,14 @@ ncr53c8xx_reg_readb(ncr53c8xx_t *dev, uint32_t offset)
|
||||
case 0x50: /* SIDL0 */
|
||||
/* This is needed by the linux drivers. We currently only update it
|
||||
during the MSG IN phase. */
|
||||
if (dev->chip >= CHIP_825)
|
||||
if (dev->wide) {
|
||||
ncr53c8xx_log("NCR 810: Read SIDL0 %02X\n", dev->sidl0);
|
||||
else
|
||||
} else {
|
||||
ncr53c8xx_log("NCR 810: Read SIDL %02X\n", dev->sidl0);
|
||||
}
|
||||
return dev->sidl0;
|
||||
case 0x51: /* SIDL1 */
|
||||
if (dev->chip < CHIP_825)
|
||||
if (!dev->wide)
|
||||
return 0x00;
|
||||
ncr53c8xx_log("NCR 810: Read SIDL1 %02X\n", dev->sidl1);
|
||||
return dev->sidl1;
|
||||
@@ -2241,7 +2246,10 @@ ncr53c8xx_ram_set_addr(ncr53c8xx_t *dev, uint32_t base)
|
||||
static void
|
||||
ncr53c8xx_bios_set_addr(ncr53c8xx_t *dev, uint32_t base)
|
||||
{
|
||||
mem_mapping_set_addr(&dev->bios.mapping, base, 0x10000);
|
||||
if (dev->has_bios == 2)
|
||||
mem_mapping_set_addr(&dev->bios.mapping, base, 0x10000);
|
||||
else if (dev->has_bios == 1)
|
||||
mem_mapping_set_addr(&dev->bios.mapping, base, 0x04000);
|
||||
}
|
||||
|
||||
|
||||
@@ -2327,25 +2335,25 @@ ncr53c8xx_pci_read(int func, int addr, void *p)
|
||||
case 0x18:
|
||||
return 0; /*Memory space*/
|
||||
case 0x19:
|
||||
if (dev->chip == CHIP_815 || dev->chip < CHIP_825)
|
||||
if (!dev->wide)
|
||||
return 0;
|
||||
return ncr53c8xx_pci_bar[2].addr_regs[1];
|
||||
case 0x1A:
|
||||
if (dev->chip == CHIP_815 || dev->chip < CHIP_825)
|
||||
if (!dev->wide)
|
||||
return 0;
|
||||
return ncr53c8xx_pci_bar[2].addr_regs[2];
|
||||
case 0x1B:
|
||||
if (dev->chip == CHIP_815 || dev->chip < CHIP_825)
|
||||
if (!dev->wide)
|
||||
return 0;
|
||||
return ncr53c8xx_pci_bar[2].addr_regs[3];
|
||||
case 0x2C:
|
||||
return 0x00;
|
||||
case 0x2D:
|
||||
if (dev->chip >= CHIP_825 || dev->chip != CHIP_815)
|
||||
if (dev->wide)
|
||||
return 0;
|
||||
return 0x10;
|
||||
case 0x2E:
|
||||
if (dev->chip >= CHIP_825 || dev->chip != CHIP_815)
|
||||
if (dev->wide)
|
||||
return 0;
|
||||
return 0x01;
|
||||
case 0x2F:
|
||||
@@ -2398,7 +2406,7 @@ ncr53c8xx_pci_write(int func, int addr, uint8_t val, void *p)
|
||||
ncr53c8xx_mem_disable(dev);
|
||||
if ((dev->MMIOBase != 0) && (val & PCI_COMMAND_MEM))
|
||||
ncr53c8xx_mem_set_addr(dev, dev->MMIOBase);
|
||||
if (dev->chip != CHIP_815 || dev->chip >= CHIP_825) {
|
||||
if (dev->wide) {
|
||||
ncr53c8xx_ram_disable(dev);
|
||||
if ((dev->RAMBase != 0) && (val & PCI_COMMAND_MEM))
|
||||
ncr53c8xx_ram_set_addr(dev, dev->RAMBase);
|
||||
@@ -2442,8 +2450,8 @@ ncr53c8xx_pci_write(int func, int addr, uint8_t val, void *p)
|
||||
/* Then let's set the PCI regs. */
|
||||
ncr53c8xx_pci_bar[1].addr_regs[addr & 3] = val;
|
||||
/* Then let's calculate the new I/O base. */
|
||||
ncr53c8xx_pci_bar[1].addr &= 0xfffcf000;
|
||||
dev->MMIOBase = ncr53c8xx_pci_bar[1].addr & 0xfffcf000;
|
||||
ncr53c8xx_pci_bar[1].addr &= 0xffffc000;
|
||||
dev->MMIOBase = ncr53c8xx_pci_bar[1].addr & 0xffffc000;
|
||||
/* Log the new base. */
|
||||
ncr53c8xx_log("NCR53c8xx: New MMIO base is %08X\n" , dev->MMIOBase);
|
||||
/* We're done, so get out of the here. */
|
||||
@@ -2454,7 +2462,7 @@ ncr53c8xx_pci_write(int func, int addr, uint8_t val, void *p)
|
||||
return;
|
||||
|
||||
case 0x19: case 0x1A: case 0x1B:
|
||||
if (dev->chip == CHIP_815 || dev->chip < CHIP_825)
|
||||
if (!dev->wide)
|
||||
return;
|
||||
/* RAM Base set. */
|
||||
/* First, remove the old I/O. */
|
||||
@@ -2462,8 +2470,8 @@ ncr53c8xx_pci_write(int func, int addr, uint8_t val, void *p)
|
||||
/* Then let's set the PCI regs. */
|
||||
ncr53c8xx_pci_bar[2].addr_regs[addr & 3] = val;
|
||||
/* Then let's calculate the new I/O base. */
|
||||
ncr53c8xx_pci_bar[2].addr &= 0xfffcf000;
|
||||
dev->RAMBase = ncr53c8xx_pci_bar[2].addr & 0xfffcf000;
|
||||
ncr53c8xx_pci_bar[2].addr &= 0xfffff000;
|
||||
dev->RAMBase = ncr53c8xx_pci_bar[2].addr & 0xfffff000;
|
||||
/* Log the new base. */
|
||||
ncr53c8xx_log("NCR53c8xx: New RAM base is %08X\n" , dev->RAMBase);
|
||||
/* We're done, so get out of the here. */
|
||||
@@ -2482,14 +2490,14 @@ ncr53c8xx_pci_write(int func, int addr, uint8_t val, void *p)
|
||||
/* Then let's set the PCI regs. */
|
||||
ncr53c8xx_pci_bar[3].addr_regs[addr & 3] = val;
|
||||
/* Then let's calculate the new I/O base. */
|
||||
ncr53c8xx_pci_bar[3].addr &= 0xfffcf001;
|
||||
dev->BIOSBase = ncr53c8xx_pci_bar[3].addr & 0xfffcf000;
|
||||
ncr53c8xx_pci_bar[3].addr &= (dev->bios_mask | 0x00000001);
|
||||
dev->BIOSBase = ncr53c8xx_pci_bar[3].addr & dev->bios_mask;
|
||||
pclog("BIOS BAR: %08X\n", dev->BIOSBase | ncr53c8xx_pci_bar[3].addr_regs[0]);
|
||||
/* Log the new base. */
|
||||
ncr53c8xx_log("NCR53c8xx: New BIOS base is %08X\n" , dev->BIOSBase);
|
||||
/* We're done, so get out of the here. */
|
||||
if (ncr53c8xx_pci_bar[3].addr_regs[0] & 0x01) {
|
||||
if (ncr53c8xx_pci_bar[3].addr_regs[0] & 0x01)
|
||||
ncr53c8xx_bios_set_addr(dev, dev->BIOSBase);
|
||||
}
|
||||
return;
|
||||
|
||||
case 0x3C:
|
||||
@@ -2513,54 +2521,63 @@ ncr53c8xx_init(const device_t *info)
|
||||
|
||||
dev->chip = info->local & 0xff;
|
||||
|
||||
if (info->local & 0x8000)
|
||||
dev->has_bios = 0;
|
||||
else
|
||||
if ((dev->chip != CHIP_810) && (dev->chip != CHIP_820) && !(info->local & 0x8000))
|
||||
dev->has_bios = device_get_config_int("bios");
|
||||
else
|
||||
dev->has_bios = 0;
|
||||
if (dev->chip == CHIP_875) {
|
||||
if (dev->has_bios == 2)
|
||||
rom_init(&dev->bios, SYM53C875_SDMS4_ROM, 0xc8000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL);
|
||||
rom_init(&dev->bios, SYM53C875_SDMS4_ROM, 0xd0000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL);
|
||||
else if (dev->has_bios == 1)
|
||||
rom_init(&dev->bios, NCR53C875_SDMS3_ROM, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
dev->chip_rev = 0x04;
|
||||
dev->nvr_path = L"ncr53c875.nvr";
|
||||
dev->wide = 1;
|
||||
} else if (dev->chip == CHIP_860) {
|
||||
if (dev->has_bios == 2)
|
||||
rom_init(&dev->bios, SYM53C860_SDMS4_ROM, 0xc8000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL);
|
||||
rom_init(&dev->bios, SYM53C860_SDMS4_ROM, 0xd0000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL);
|
||||
else if (dev->has_bios == 1)
|
||||
rom_init(&dev->bios, NCR53C860_SDMS3_ROM, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
dev->chip_rev = 0x04;
|
||||
dev->nvr_path = L"ncr53c860.nvr";
|
||||
dev->wide = 1;
|
||||
} else if (dev->chip == CHIP_820) {
|
||||
dev->nvr_path = L"ncr53c820.nvr";
|
||||
dev->wide = 1;
|
||||
} else if (dev->chip == CHIP_825) {
|
||||
if (dev->has_bios == 2)
|
||||
rom_init(&dev->bios, SYM53C825A_SDMS4_ROM, 0xc8000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL);
|
||||
rom_init(&dev->bios, SYM53C825A_SDMS4_ROM, 0xd0000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL);
|
||||
else if (dev->has_bios == 1)
|
||||
rom_init(&dev->bios, NCR53C825A_SDMS3_ROM, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
dev->chip_rev = 0x26;
|
||||
dev->nvr_path = L"ncr53c825a.nvr";
|
||||
dev->wide = 1;
|
||||
} else if (dev->chip == CHIP_810) {
|
||||
if (dev->has_bios == 2)
|
||||
rom_init(&dev->bios, SYM53C810_SDMS4_ROM, 0xc8000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL);
|
||||
else if (dev->has_bios == 1)
|
||||
rom_init(&dev->bios, NCR53C810_SDMS3_ROM, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
dev->nvr_path = L"ncr53c810.nvr";
|
||||
dev->wide = 0;
|
||||
} else if (dev->chip == CHIP_815) {
|
||||
if (dev->has_bios == 2)
|
||||
rom_init(&dev->bios, SYM53C815_SDMS4_ROM, 0xc8000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL);
|
||||
rom_init(&dev->bios, SYM53C815_SDMS4_ROM, 0xd0000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL);
|
||||
else if (dev->has_bios == 1)
|
||||
rom_init(&dev->bios, NCR53C815_SDMS3_ROM, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
dev->chip_rev = 0x04;
|
||||
dev->nvr_path = L"ncr53c815.nvr";
|
||||
dev->wide = 0;
|
||||
}
|
||||
|
||||
ncr53c8xx_pci_bar[0].addr_regs[0] = 1;
|
||||
ncr53c8xx_pci_bar[1].addr_regs[0] = 0;
|
||||
ncr53c8xx_pci_regs[0x04] = 3;
|
||||
|
||||
if (dev->has_bios) {
|
||||
if (dev->has_bios == 2) {
|
||||
ncr53c8xx_pci_bar[3].addr = 0xffff0000;
|
||||
dev->bios_mask = 0xffff0000;
|
||||
} else if (dev->has_bios == 1) {
|
||||
ncr53c8xx_pci_bar[3].addr = 0xffffc000;
|
||||
dev->bios_mask = 0xffffc000;
|
||||
} else {
|
||||
ncr53c8xx_pci_bar[3].addr = 0;
|
||||
ncr53c8xx_pci_bar[3].addr = 0x00000000;
|
||||
dev->bios_mask = 0x00000000;
|
||||
}
|
||||
|
||||
ncr53c8xx_mem_init(dev, 0x0fffff00);
|
||||
@@ -2568,10 +2585,8 @@ ncr53c8xx_init(const device_t *info)
|
||||
|
||||
ncr53c8xx_pci_bar[2].addr_regs[0] = 0;
|
||||
|
||||
if (dev->chip >= CHIP_825 || (dev->chip != CHIP_815)) {
|
||||
/* Need to make it align on a 16k boundary as that's this emulator's
|
||||
memory mapping granularity. */
|
||||
ncr53c8xx_ram_init(dev, 0x0fffc000);
|
||||
if (dev->wide) {
|
||||
ncr53c8xx_ram_init(dev, 0x0ffff000);
|
||||
ncr53c8xx_ram_disable(dev);
|
||||
}
|
||||
|
||||
@@ -2643,7 +2658,7 @@ const device_t ncr53c810_pci_device =
|
||||
CHIP_810,
|
||||
ncr53c8xx_init, ncr53c8xx_close, NULL,
|
||||
{ NULL }, NULL, NULL,
|
||||
ncr53c8xx_pci_config
|
||||
NULL
|
||||
};
|
||||
|
||||
const device_t ncr53c810_onboard_pci_device =
|
||||
@@ -2666,6 +2681,16 @@ const device_t ncr53c815_pci_device =
|
||||
ncr53c8xx_pci_config
|
||||
};
|
||||
|
||||
const device_t ncr53c820_pci_device =
|
||||
{
|
||||
"NCR 53c820",
|
||||
DEVICE_PCI,
|
||||
CHIP_820,
|
||||
ncr53c8xx_init, ncr53c8xx_close, NULL,
|
||||
{ NULL }, NULL, NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
const device_t ncr53c825a_pci_device =
|
||||
{
|
||||
"NCR 53c825A",
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
add_library(sio OBJECT sio_acc3221.c sio_f82c710.c sio_82091aa.c sio_fdc37c661.c
|
||||
sio_fdc37c66x.c sio_fdc37c669.c sio_fdc37c93x.c sio_fdc37m60x.c
|
||||
sio_pc87306.c sio_pc87307.c sio_pc87309.c sio_pc87311.c sio_pc87332.c
|
||||
sio_pc87306.c sio_pc87307.c sio_pc87309.c sio_pc87310.c sio_pc87311.c sio_pc87332.c
|
||||
sio_prime3b.c sio_prime3c.c
|
||||
sio_w83787f.c sio_w83877f.c sio_w83977f.c sio_um8669f.c
|
||||
sio_vt82c686.c)
|
||||
|
||||
283
src/sio/sio_pc87310.c
Normal file
283
src/sio/sio_pc87310.c
Normal file
@@ -0,0 +1,283 @@
|
||||
/*
|
||||
* 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 NatSemi PC87310 Super I/O chip.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Author: Miran Grca, <mgrca8@gmail.com>
|
||||
* Tiseno100
|
||||
* EngiNerd <webmaster.crrc@yahoo.it>
|
||||
*
|
||||
* Copyright 2020 Miran Grca.
|
||||
* Copyright 2020 Tiseno100
|
||||
* Copyright 2021 EngiNerd.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include <86box/86box.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/lpt.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/nvr.h>
|
||||
#include <86box/pci.h>
|
||||
#include <86box/rom.h>
|
||||
#include <86box/serial.h>
|
||||
#include <86box/hdc.h>
|
||||
#include <86box/hdc_ide.h>
|
||||
#include <86box/fdd.h>
|
||||
#include <86box/fdc.h>
|
||||
#include <86box/sio.h>
|
||||
|
||||
#define HAS_IDE_FUNCTIONALITY dev->ide_function
|
||||
|
||||
#ifdef ENABLE_PC87310_LOG
|
||||
int pc87310_do_log = ENABLE_PC87310_LOG;
|
||||
static void
|
||||
pc87310_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (pc87310_do_log)
|
||||
{
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define pc87310_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint8_t tries, ide_function,
|
||||
reg;
|
||||
fdc_t *fdc;
|
||||
serial_t *uart[2];
|
||||
} pc87310_t;
|
||||
|
||||
|
||||
static void
|
||||
lpt1_handler(pc87310_t *dev)
|
||||
{
|
||||
int temp;
|
||||
uint16_t lpt_port = 0x378;
|
||||
uint8_t lpt_irq = 7;
|
||||
|
||||
/* bits 0-1:
|
||||
* 00 378h
|
||||
* 01 3bch
|
||||
* 10 278h
|
||||
* 11 disabled
|
||||
*/
|
||||
temp = dev->reg & 3;
|
||||
|
||||
switch (temp) {
|
||||
case 0:
|
||||
lpt_port = 0x378;
|
||||
break;
|
||||
case 1:
|
||||
lpt_port = 0x3bc;
|
||||
break;
|
||||
case 2:
|
||||
lpt_port = 0x278;
|
||||
break;
|
||||
case 3:
|
||||
lpt_port = 0x000;
|
||||
lpt_irq = 0xff;
|
||||
break;
|
||||
}
|
||||
|
||||
if (lpt_port)
|
||||
lpt1_init(lpt_port);
|
||||
|
||||
lpt1_irq(lpt_irq);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
serial_handler(pc87310_t *dev, int uart)
|
||||
{
|
||||
int temp;
|
||||
/* bit 2: disable serial port 1
|
||||
* bit 3: disable serial port 2
|
||||
* bit 4: swap serial ports
|
||||
*/
|
||||
temp = (dev->reg >> (2 + uart)) & 1;
|
||||
|
||||
//current serial port is enabled
|
||||
if (!temp){
|
||||
//configure serial port as COM2
|
||||
if (((dev->reg >> 4) & 1) ^ uart)
|
||||
serial_setup(dev->uart[uart], 0x2f8, 3);
|
||||
// configure serial port as COM1
|
||||
else
|
||||
serial_setup(dev->uart[uart], 0x3f8, 4);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pc87310_write(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
pc87310_t *dev = (pc87310_t *) priv;
|
||||
uint8_t valxor;
|
||||
|
||||
// second write to config register
|
||||
if (dev->tries) {
|
||||
valxor = val ^ dev->reg;
|
||||
dev->tries = 0;
|
||||
dev->reg = val;
|
||||
// first write to config register
|
||||
} else {
|
||||
dev->tries++;
|
||||
return;
|
||||
}
|
||||
|
||||
pc87310_log("SIO: written %01X\n", val);
|
||||
|
||||
/* reconfigure parallel port */
|
||||
if (valxor & 0x03) {
|
||||
lpt1_remove();
|
||||
/* bits 0-1: 11 disable parallel port */
|
||||
if (!((val & 1) && (val & 2)))
|
||||
lpt1_handler(dev);
|
||||
}
|
||||
/* reconfigure serial ports */
|
||||
if (valxor & 0x1c) {
|
||||
serial_remove(dev->uart[0]);
|
||||
serial_remove(dev->uart[1]);
|
||||
/* bit 2: 1 disable first serial port */
|
||||
if (!(val & 4))
|
||||
serial_handler(dev, 0);
|
||||
/* bit 3: 1 disable second serial port */
|
||||
if (!(val & 8))
|
||||
serial_handler(dev, 1);
|
||||
}
|
||||
/* reconfigure IDE controller */
|
||||
if (valxor & 0x20) {
|
||||
pc87310_log("SIO: HDC disabled\n");
|
||||
ide_pri_disable();
|
||||
/* bit 5: 1 disable ide controller */
|
||||
if (!(val & 0x20) && HAS_IDE_FUNCTIONALITY) {
|
||||
pc87310_log("SIO: HDC enabled\n");
|
||||
ide_set_base(0, 0x1f0);
|
||||
ide_set_side(0, 0x3f6);
|
||||
ide_pri_enable();
|
||||
}
|
||||
}
|
||||
/* reconfigure floppy disk controller */
|
||||
if (valxor & 0x40) {
|
||||
pc87310_log("SIO: FDC disabled\n");
|
||||
fdc_remove(dev->fdc);
|
||||
/* bit 6: 1 disable fdc */
|
||||
if (!(val & 0x40)) {
|
||||
pc87310_log("SIO: FDC enabled\n");
|
||||
fdc_set_base(dev->fdc, 0x3f0);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
uint8_t
|
||||
pc87310_read(uint16_t port, void *priv)
|
||||
{
|
||||
pc87310_t *dev = (pc87310_t *) priv;
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
dev->tries = 0;
|
||||
|
||||
ret = dev->reg;
|
||||
|
||||
pc87310_log("SIO: read %01X\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
pc87310_reset(pc87310_t *dev)
|
||||
{
|
||||
dev->reg = 0x0;
|
||||
dev->tries = 0;
|
||||
/*
|
||||
0 = 360 rpm @ 500 kbps for 3.5"
|
||||
1 = Default, 300 rpm @ 500,300,250,1000 kbps for 3.5"
|
||||
*/
|
||||
lpt1_remove();
|
||||
lpt1_handler(dev);
|
||||
serial_remove(dev->uart[0]);
|
||||
serial_remove(dev->uart[1]);
|
||||
serial_handler(dev, 0);
|
||||
serial_handler(dev, 1);
|
||||
fdc_reset(dev->fdc);
|
||||
//ide_pri_enable();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pc87310_close(void *priv)
|
||||
{
|
||||
pc87310_t *dev = (pc87310_t *) priv;
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
pc87310_init(const device_t *info)
|
||||
{
|
||||
pc87310_t *dev = (pc87310_t *) malloc(sizeof(pc87310_t));
|
||||
memset(dev, 0, sizeof(pc87310_t));
|
||||
|
||||
/* Avoid conflicting with machines that make no use of the PC87310 Internal IDE */
|
||||
HAS_IDE_FUNCTIONALITY = info->local;
|
||||
|
||||
dev->fdc = device_add(&fdc_at_nsc_device);
|
||||
|
||||
dev->uart[0] = device_add_inst(&ns16550_device, 1);
|
||||
dev->uart[1] = device_add_inst(&ns16550_device, 2);
|
||||
|
||||
if (HAS_IDE_FUNCTIONALITY)
|
||||
device_add(&ide_isa_device);
|
||||
|
||||
pc87310_reset(dev);
|
||||
|
||||
io_sethandler(0x3f3, 0x0001,
|
||||
pc87310_read, NULL, NULL, pc87310_write, NULL, NULL, dev);
|
||||
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
||||
const device_t pc87310_device = {
|
||||
"National Semiconductor PC87310 Super I/O",
|
||||
0,
|
||||
0,
|
||||
pc87310_init, pc87310_close, NULL,
|
||||
{ NULL }, NULL, NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
const device_t pc87310_ide_device = {
|
||||
"National Semiconductor PC87310 Super I/O with IDE functionality",
|
||||
0,
|
||||
1,
|
||||
pc87310_init, pc87310_close, NULL,
|
||||
{ NULL }, NULL, NULL,
|
||||
NULL
|
||||
};
|
||||
@@ -33,10 +33,6 @@ if(NOT MSVC)
|
||||
target_compile_options(vid PRIVATE "-msse2")
|
||||
endif()
|
||||
|
||||
if(CL5422)
|
||||
target_compile_definitions(vid PRIVATE USE_CL5422)
|
||||
endif()
|
||||
|
||||
if(MGA)
|
||||
target_compile_definitions(vid PRIVATE USE_MGA)
|
||||
target_sources(vid PRIVATE vid_mga.c)
|
||||
|
||||
@@ -138,7 +138,6 @@ cga_write(uint32_t addr, uint8_t val, void *p)
|
||||
cga->charbuffer[offset] = cga->vram[addr & 0x3fff];
|
||||
cga->charbuffer[offset | 1] = cga->vram[addr & 0x3fff];
|
||||
}
|
||||
egawrites++;
|
||||
cga_waitstates(cga);
|
||||
}
|
||||
|
||||
@@ -154,7 +153,6 @@ cga_read(uint32_t addr, void *p)
|
||||
cga->charbuffer[offset] = cga->vram[addr & 0x3fff];
|
||||
cga->charbuffer[offset | 1] = cga->vram[addr & 0x3fff];
|
||||
}
|
||||
egareads++;
|
||||
return cga->vram[addr & 0x3fff];
|
||||
}
|
||||
|
||||
|
||||
@@ -99,7 +99,6 @@ void colorplus_write(uint32_t addr, uint8_t val, void *p)
|
||||
colorplus->cga.charbuffer[offset] = colorplus->cga.vram[addr & 0x7fff];
|
||||
colorplus->cga.charbuffer[offset | 1] = colorplus->cga.vram[addr & 0x7fff];
|
||||
}
|
||||
egawrites++;
|
||||
cycles -= 4;
|
||||
}
|
||||
|
||||
@@ -124,7 +123,6 @@ uint8_t colorplus_read(uint32_t addr, void *p)
|
||||
colorplus->cga.charbuffer[offset] = colorplus->cga.vram[addr & 0x7fff];
|
||||
colorplus->cga.charbuffer[offset | 1] = colorplus->cga.vram[addr & 0x7fff];
|
||||
}
|
||||
egareads++;
|
||||
return colorplus->cga.vram[addr & 0x7fff];
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ void ega_doblit(int y1, int y2, int wx, int wy, ega_t *ega);
|
||||
#define BIOS_SEGA_PATH L"roms/video/ega/lega.vbi"
|
||||
#define BIOS_ATIEGA_PATH L"roms/video/ega/ATI EGA Wonder 800+ N1.00.BIN"
|
||||
#define BIOS_ISKRA_PATH L"roms/video/ega/143-02.bin", L"roms/video/ega/143-03.bin"
|
||||
#define BIOS_TSENG_PATH L"roms/video/ega/EGA ET2000.BIN"
|
||||
|
||||
|
||||
enum {
|
||||
@@ -50,14 +51,15 @@ enum {
|
||||
EGA_COMPAQ,
|
||||
EGA_SUPEREGA,
|
||||
EGA_ATI,
|
||||
EGA_ISKRA
|
||||
EGA_ISKRA,
|
||||
EGA_TSENG
|
||||
};
|
||||
|
||||
|
||||
static video_timings_t timing_ega = {VIDEO_ISA, 8, 16, 32, 8, 16, 32};
|
||||
static uint8_t ega_rotate[8][256];
|
||||
static uint32_t pallook16[256], pallook64[256];
|
||||
static int old_overscan_color = 0;
|
||||
static int ega_type = 0, old_overscan_color = 0;
|
||||
|
||||
extern uint8_t edatlookup[4][4];
|
||||
|
||||
@@ -256,38 +258,48 @@ uint8_t ega_in(uint16_t addr, void *p)
|
||||
break;
|
||||
|
||||
case 0x3c0:
|
||||
ret = ega->attraddr | ega->attr_palette_enable;
|
||||
if (ega_type)
|
||||
ret = ega->attraddr | ega->attr_palette_enable;
|
||||
break;
|
||||
case 0x3c1:
|
||||
ret = ega->attrregs[ega->attraddr];
|
||||
if (ega_type)
|
||||
ret = ega->attrregs[ega->attraddr];
|
||||
break;
|
||||
case 0x3c2:
|
||||
ret = (egaswitches & (8 >> egaswitchread)) ? 0x10 : 0x00;
|
||||
break;
|
||||
case 0x3c4:
|
||||
ret = ega->seqaddr;
|
||||
if (ega_type)
|
||||
ret = ega->seqaddr;
|
||||
break;
|
||||
case 0x3c5:
|
||||
ret = ega->seqregs[ega->seqaddr & 0xf];
|
||||
if (ega_type)
|
||||
ret = ega->seqregs[ega->seqaddr & 0xf];
|
||||
break;
|
||||
case 0x3c8:
|
||||
ret = 2;
|
||||
if (ega_type)
|
||||
ret = 2;
|
||||
break;
|
||||
case 0x3cc:
|
||||
ret = ega->miscout;
|
||||
if (ega_type)
|
||||
ret = ega->miscout;
|
||||
break;
|
||||
case 0x3ce:
|
||||
ret = ega->gdcaddr;
|
||||
if (ega_type)
|
||||
ret = ega->gdcaddr;
|
||||
break;
|
||||
case 0x3cf:
|
||||
ret = ega->gdcreg[ega->gdcaddr & 0xf];
|
||||
if (ega_type)
|
||||
ret = ega->gdcreg[ega->gdcaddr & 0xf];
|
||||
break;
|
||||
case 0x3d0: case 0x3d4:
|
||||
ret = ega->crtcreg;
|
||||
if (ega_type)
|
||||
ret = ega->crtcreg;
|
||||
break;
|
||||
case 0x3d1:
|
||||
case 0x3d5:
|
||||
ret = ega->crtc[ega->crtcreg];
|
||||
if (ega_type)
|
||||
ret = ega->crtc[ega->crtcreg];
|
||||
break;
|
||||
case 0x3da:
|
||||
ega->attrff = 0;
|
||||
@@ -731,7 +743,6 @@ ega_write(uint32_t addr, uint8_t val, void *p)
|
||||
uint8_t vala, valb, valc, vald;
|
||||
int writemask2 = ega->writemask;
|
||||
|
||||
egawrites++;
|
||||
cycles -= video_timing_write_b;
|
||||
|
||||
if (addr >= 0xB0000) addr &= 0x7fff;
|
||||
@@ -858,7 +869,6 @@ ega_read(uint32_t addr, void *p)
|
||||
uint8_t temp, temp2, temp3, temp4;
|
||||
int readplane = ega->readplane;
|
||||
|
||||
egareads++;
|
||||
cycles -= video_timing_read_b;
|
||||
if (addr >= 0xb0000) addr &= 0x7fff;
|
||||
else addr &= 0xffff;
|
||||
@@ -1021,6 +1031,12 @@ ega_standalone_init(const device_t *info)
|
||||
ega->x_add = 8;
|
||||
ega->y_add = 14;
|
||||
|
||||
if ((info->local == EGA_IBM) || (info->local == EGA_ISKRA) ||
|
||||
(info->local == EGA_TSENG))
|
||||
ega_type = 0;
|
||||
else
|
||||
ega_type = 1;
|
||||
|
||||
switch(info->local) {
|
||||
case EGA_IBM:
|
||||
default:
|
||||
@@ -1043,6 +1059,10 @@ ega_standalone_init(const device_t *info)
|
||||
rom_init_interleaved(&ega->bios_rom, BIOS_ISKRA_PATH,
|
||||
0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
break;
|
||||
case EGA_TSENG:
|
||||
rom_init(&ega->bios_rom, BIOS_TSENG_PATH,
|
||||
0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((ega->bios_rom.rom[0x3ffe] == 0xaa) && (ega->bios_rom.rom[0x3fff] == 0x55)) {
|
||||
@@ -1101,6 +1121,20 @@ atiega_standalone_available(void)
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
iskra_ega_standalone_available(void)
|
||||
{
|
||||
return rom_present(L"roms/video/ega/143-02.bin") && rom_present(L"roms/video/ega/143-03.bin");
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
et2000_standalone_available(void)
|
||||
{
|
||||
return rom_present(BIOS_TSENG_PATH);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ega_close(void *p)
|
||||
{
|
||||
@@ -1250,8 +1284,20 @@ const device_t iskra_ega_device =
|
||||
DEVICE_ISA,
|
||||
EGA_ISKRA,
|
||||
ega_standalone_init, ega_close, NULL,
|
||||
{ ega_standalone_available },
|
||||
{ iskra_ega_standalone_available },
|
||||
ega_speed_changed,
|
||||
NULL,
|
||||
ega_config
|
||||
};
|
||||
};
|
||||
|
||||
const device_t et2000_device =
|
||||
{
|
||||
"Tseng Labs ET2000",
|
||||
DEVICE_ISA,
|
||||
EGA_TSENG,
|
||||
ega_standalone_init, ega_close, NULL,
|
||||
{ et2000_standalone_available },
|
||||
ega_speed_changed,
|
||||
NULL,
|
||||
ega_config
|
||||
};
|
||||
|
||||
@@ -261,7 +261,6 @@ void
|
||||
genius_write(uint32_t addr, uint8_t val, void *p)
|
||||
{
|
||||
genius_t *genius = (genius_t *)p;
|
||||
egawrites++;
|
||||
genius_waitstates();
|
||||
|
||||
if (genius->genius_control & 1) {
|
||||
@@ -288,7 +287,6 @@ genius_read(uint32_t addr, void *p)
|
||||
{
|
||||
genius_t *genius = (genius_t *)p;
|
||||
uint8_t ret;
|
||||
egareads++;
|
||||
genius_waitstates();
|
||||
|
||||
if (genius->genius_control & 1) {
|
||||
|
||||
@@ -53,8 +53,12 @@ typedef struct ht216_t
|
||||
uint32_t read_banks[2], write_banks[2];
|
||||
|
||||
uint8_t bg_latch[8];
|
||||
uint8_t fg_latch[4];
|
||||
uint8_t bg_plane_sel, fg_plane_sel;
|
||||
|
||||
uint8_t ht_regs[256];
|
||||
|
||||
uint8_t pos_regs[8];
|
||||
} ht216_t;
|
||||
|
||||
|
||||
@@ -94,7 +98,7 @@ uint8_t ht216_in(uint16_t addr, void *p);
|
||||
#define BIOS_VIDEO7_VGA_1024I_PATH L"roms/video/video7/Video Seven VGA 1024i - BIOS - v2.19 - 435-0062-05 - U17 - 27C256.BIN"
|
||||
|
||||
static video_timings_t timing_v7vga_isa = {VIDEO_ISA, 3, 3, 6, 5, 5, 10};
|
||||
static video_timings_t timing_v7vga_vlb = {VIDEO_ISA, 5, 5, 9, 20, 20, 30};
|
||||
static video_timings_t timing_v7vga_vlb = {VIDEO_BUS, 5, 5, 9, 20, 20, 30};
|
||||
|
||||
|
||||
#ifdef ENABLE_HT216_LOG
|
||||
@@ -140,6 +144,10 @@ ht216_out(uint16_t addr, uint8_t val, void *p)
|
||||
svga_recalctimings(svga);
|
||||
break;
|
||||
|
||||
case 0x3c4:
|
||||
svga->seqaddr = val;
|
||||
break;
|
||||
|
||||
case 0x3c5:
|
||||
if (svga->seqaddr == 4) {
|
||||
svga->chain4 = val & 8;
|
||||
@@ -152,6 +160,7 @@ ht216_out(uint16_t addr, uint8_t val, void *p)
|
||||
} else if (svga->seqaddr >= 0x80 && ht216->ext_reg_enable) {
|
||||
old = ht216->ht_regs[svga->seqaddr & 0xff];
|
||||
ht216->ht_regs[svga->seqaddr & 0xff] = val;
|
||||
|
||||
switch (svga->seqaddr & 0xff) {
|
||||
case 0x83:
|
||||
svga->attraddr = val & 0x1f;
|
||||
@@ -161,6 +170,8 @@ ht216_out(uint16_t addr, uint8_t val, void *p)
|
||||
case 0x94:
|
||||
case 0xff:
|
||||
svga->hwcursor.addr = ((ht216->ht_regs[0x94] << 6) | (3 << 14) | ((ht216->ht_regs[0xff] & 0x60) << 11)) << 2;
|
||||
if (svga->crtc[0x17] == 0xeb) /*Looks like that 1024x768 mono mode expects 512K of video memory*/
|
||||
svga->hwcursor.addr += 0x40000;
|
||||
break;
|
||||
case 0x9c: case 0x9d:
|
||||
svga->hwcursor.x = ht216->ht_regs[0x9d] | ((ht216->ht_regs[0x9c] & 7) << 8);
|
||||
@@ -203,14 +214,41 @@ ht216_out(uint16_t addr, uint8_t val, void *p)
|
||||
case 0xe9:
|
||||
ht216_remap(ht216);
|
||||
break;
|
||||
|
||||
case 0xec:
|
||||
ht216->fg_latch[0] = val;
|
||||
break;
|
||||
case 0xed:
|
||||
ht216->fg_latch[1] = val;
|
||||
break;
|
||||
case 0xee:
|
||||
ht216->fg_latch[2] = val;
|
||||
break;
|
||||
case 0xef:
|
||||
ht216->fg_latch[3] = val;
|
||||
break;
|
||||
|
||||
case 0xf0:
|
||||
ht216->fg_latch[ht216->fg_plane_sel] = val;
|
||||
ht216->fg_plane_sel = (ht216->fg_plane_sel + 1) & 3;
|
||||
break;
|
||||
|
||||
case 0xf1:
|
||||
ht216->bg_plane_sel = val & 3;
|
||||
ht216->fg_plane_sel = (val & 0x30) >> 4;
|
||||
break;
|
||||
|
||||
case 0xf2:
|
||||
svga->latch.b[ht216->bg_plane_sel] = val;
|
||||
ht216->bg_plane_sel = (ht216->bg_plane_sel + 1) & 3;
|
||||
break;
|
||||
|
||||
case 0xf6:
|
||||
svga->vram_display_mask = (val & 0x40) ? ht216->vram_mask : 0x3ffff;
|
||||
/*Bits 18 and 19 of the display memory address*/
|
||||
ht216_log("HT216 reg 0xf6 write = %02x, vram mask = %08x\n", val & 0x40, svga->vram_display_mask);
|
||||
ht216_log("HT216 reg 0xf6 write = %02x, vram mask = %08x, cr17 = %02x\n", val & 0x40, svga->vram_display_mask, svga->crtc[0x17]);
|
||||
ht216_remap(ht216);
|
||||
svga->fullchange = changeframecount;
|
||||
svga_recalctimings(svga);
|
||||
svga_recalctimings(svga);
|
||||
break;
|
||||
|
||||
case 0xf9:
|
||||
@@ -218,10 +256,10 @@ ht216_out(uint16_t addr, uint8_t val, void *p)
|
||||
ht216_log("HT216 reg 0xf9 write = %02x\n", val & HT_REG_F9_XPSEL);
|
||||
ht216_remap(ht216);
|
||||
break;
|
||||
|
||||
|
||||
case 0xfc:
|
||||
svga->fullchange = changeframecount;
|
||||
svga_recalctimings(svga);
|
||||
svga_recalctimings(svga);
|
||||
break;
|
||||
}
|
||||
switch (svga->seqaddr & 0xff) {
|
||||
@@ -239,14 +277,14 @@ ht216_out(uint16_t addr, uint8_t val, void *p)
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x3cf:
|
||||
if (svga->gdcaddr == 6) {
|
||||
if (val & 8)
|
||||
svga->banked_mask = 0x7fff;
|
||||
else
|
||||
svga->banked_mask = 0xffff;
|
||||
}
|
||||
break;
|
||||
case 0x3cf:
|
||||
if (svga->gdcaddr == 6) {
|
||||
if (val & 8)
|
||||
svga->banked_mask = 0x7fff;
|
||||
else
|
||||
svga->banked_mask = 0xffff;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x3D4:
|
||||
svga->crtcreg = val & 0x3f;
|
||||
@@ -263,7 +301,7 @@ ht216_out(uint16_t addr, uint8_t val, void *p)
|
||||
if (old != val) {
|
||||
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) {
|
||||
svga->fullchange = changeframecount;
|
||||
svga_recalctimings(&ht216->svga);
|
||||
svga_recalctimings(svga);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -289,6 +327,7 @@ ht216_in(uint16_t addr, void *p)
|
||||
{
|
||||
ht216_t *ht216 = (ht216_t *)p;
|
||||
svga_t *svga = &ht216->svga;
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
|
||||
addr ^= 0x60;
|
||||
@@ -296,11 +335,14 @@ ht216_in(uint16_t addr, void *p)
|
||||
switch (addr) {
|
||||
case 0x3c2:
|
||||
break;
|
||||
|
||||
case 0x3c4:
|
||||
return svga->seqaddr;
|
||||
|
||||
case 0x3c5:
|
||||
if (svga->seqaddr == 6)
|
||||
if (svga->seqaddr == 6) {
|
||||
return ht216->ext_reg_enable;
|
||||
if (svga->seqaddr >= 0x80) {
|
||||
} else if (svga->seqaddr >= 0x80) {
|
||||
if (ht216->ext_reg_enable) {
|
||||
switch (svga->seqaddr & 0xff) {
|
||||
case 0x83:
|
||||
@@ -319,6 +361,16 @@ ht216_in(uint16_t addr, void *p)
|
||||
return svga->latch.b[2];
|
||||
case 0xa3:
|
||||
return svga->latch.b[3];
|
||||
|
||||
case 0xf0:
|
||||
ret = ht216->fg_latch[ht216->fg_plane_sel];
|
||||
ht216->fg_plane_sel = 0;
|
||||
return ret;
|
||||
|
||||
case 0xf2:
|
||||
ret = svga->latch.b[ht216->bg_plane_sel];
|
||||
ht216->bg_plane_sel = 0;
|
||||
return ret;
|
||||
}
|
||||
return ht216->ht_regs[svga->seqaddr & 0xff];
|
||||
} else
|
||||
@@ -326,6 +378,9 @@ ht216_in(uint16_t addr, void *p)
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x3cc:
|
||||
return ht216->misc;
|
||||
|
||||
case 0x3D4:
|
||||
return svga->crtcreg;
|
||||
case 0x3D5:
|
||||
@@ -406,9 +461,16 @@ ht216_remap(ht216_t *ht216)
|
||||
} else {
|
||||
/*One bank used*/
|
||||
/*Bit 17 of the video memory address*/
|
||||
if (ht216->misc & HT_MISC_PAGE_SEL) {
|
||||
ht216->read_bank_reg[0] |= 0x20;
|
||||
ht216->write_bank_reg[0] |= 0x20;
|
||||
if ((ht216->misc & HT_MISC_PAGE_SEL)) {
|
||||
ht216_log("MISC = %02x, lowres = %02x, CR17 = %02x\n", ht216->misc, svga->lowres, svga->crtc[0x17]);
|
||||
if ((ht216->misc == 0x63 && svga->crtc[0x17] != 0xa3 && ((svga->crtc[0x17] != 0xe3 && !(ht216->ht_regs[0xfc] & HT_REG_FC_ECOLRE)) ||
|
||||
(ht216->ht_regs[0xfc] & HT_REG_FC_ECOLRE))) || (ht216->misc != 0x63)) {
|
||||
ht216->read_bank_reg[0] |= 0x20;
|
||||
ht216->write_bank_reg[0] |= 0x20;
|
||||
} else {
|
||||
ht216->read_bank_reg[0] &= ~0x20;
|
||||
ht216->write_bank_reg[0] &= ~0x20;
|
||||
}
|
||||
} else {
|
||||
ht216->read_bank_reg[0] &= ~0x20;
|
||||
ht216->write_bank_reg[0] &= ~0x20;
|
||||
@@ -439,12 +501,12 @@ ht216_remap(ht216_t *ht216)
|
||||
if (bank & 4)
|
||||
ht216->read_bank_reg[0] |= 0x40;
|
||||
else
|
||||
ht216->read_bank_reg[0] &= ~0x40;
|
||||
ht216->read_bank_reg[0] &= ~0x40;
|
||||
|
||||
if (bank & 8)
|
||||
ht216->read_bank_reg[0] |= 0x80;
|
||||
else
|
||||
ht216->read_bank_reg[0] &= ~0x80;
|
||||
ht216->read_bank_reg[0] &= ~0x80;
|
||||
|
||||
if (svga->chain4) {
|
||||
/*Bit 16 of the video memory address*/
|
||||
@@ -456,30 +518,109 @@ ht216_remap(ht216_t *ht216)
|
||||
ht216->write_bank_reg[0] &= ~0x10;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!svga->chain4) {
|
||||
/*In linear modes, bits 4 and 5 are ignored*/
|
||||
ht216->read_bank_reg[0] &= ~0x30;
|
||||
ht216->write_bank_reg[0] &= ~0x30;
|
||||
}
|
||||
|
||||
if (svga->chain4) {
|
||||
ht216->read_bank_reg[0] |= ht216->ht_regs[0xe8];
|
||||
ht216->write_bank_reg[0] |= ht216->ht_regs[0xe8];
|
||||
}
|
||||
|
||||
ht216->read_banks[0] = ht216->read_bank_reg[0] << 12;
|
||||
ht216->write_banks[0] = ht216->write_bank_reg[0] << 12;
|
||||
ht216->write_banks[0] = ht216->write_bank_reg[0] << 12;
|
||||
ht216->read_banks[1] = ht216->read_banks[0] + (svga->chain4 ? 0x8000 : 0x20000);
|
||||
ht216->write_banks[1] = ht216->write_banks[0] + (svga->chain4 ? 0x8000 : 0x20000);
|
||||
|
||||
|
||||
if (!svga->chain4) {
|
||||
ht216->read_banks[0] >>= 2;
|
||||
ht216->read_banks[1] >>= 2;
|
||||
ht216->write_banks[0] >>= 2;
|
||||
ht216->write_banks[1] >>= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ht216_log("ReadBank0 = %06x, ReadBank1 = %06x, Misc Page Sel = %02x, F6 reg = %02x, F9 Sel = %02x, FC = %02x, E0 split = %02x, E8 = %02x, E9 = %02x, chain4 = %02x, banked mask = %04x\n", ht216->read_banks[0], ht216->read_banks[1], ht216->misc & HT_MISC_PAGE_SEL, bank, ht216->ht_regs[0xf9] & HT_REG_F9_XPSEL, ht216->ht_regs[0xfc] & (HT_REG_FC_ECOLRE | 2), ht216->ht_regs[0xe0] & HT_REG_E0_SBAE, ht216->ht_regs[0xe8], ht216->ht_regs[0xe9], svga->chain4, svga->banked_mask);
|
||||
ht216_log("ReadBank0 = %06x, ReadBank1 = %06x, Misc Page Sel = %02x, FF DRAM/VRAM = %02x, F6 reg = %02x, F9 Sel = %02x, FC = %02x, E0 split = %02x, E8 = %02x, E9 = %02x, chain4 = %02x, lowres = %02x, banked mask = %04x\n", ht216->read_banks[0], ht216->read_banks[1], ht216->misc & HT_MISC_PAGE_SEL, ht216->ht_regs[0xff] & 0x10, bank, ht216->ht_regs[0xf9] & HT_REG_F9_XPSEL, ht216->ht_regs[0xfc] & (HT_REG_FC_ECOLRE | 2), ht216->ht_regs[0xe0] & HT_REG_E0_SBAE, ht216->ht_regs[0xe8], ht216->ht_regs[0xe9], svga->chain4, svga->lowres, svga->banked_mask);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ht216_1_2bpp_highres(svga_t *svga)
|
||||
{
|
||||
int changed_offset, x;
|
||||
int oddeven;
|
||||
uint32_t addr, *p;
|
||||
uint8_t edat[4];
|
||||
uint8_t dat;
|
||||
|
||||
if ((svga->displine + svga->y_add) < 0)
|
||||
return;
|
||||
|
||||
changed_offset = (svga->ma + (svga->sc & ~svga->crtc[0x17] & 3) * 0x8000) >> 12;
|
||||
|
||||
if (svga->changedvram[changed_offset] || svga->changedvram[changed_offset + 1] || svga->fullchange) {
|
||||
p = &buffer32->line[svga->displine + svga->y_add][svga->x_add];
|
||||
|
||||
if (svga->firstline_draw == 2000)
|
||||
svga->firstline_draw = svga->displine;
|
||||
svga->lastline_draw = svga->displine;
|
||||
|
||||
for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) {
|
||||
addr = svga->ma;
|
||||
oddeven = 0;
|
||||
|
||||
if (!(svga->crtc[0x17] & 0x40)) {
|
||||
addr = (addr << 1) & svga->vram_mask;
|
||||
|
||||
if (svga->seqregs[1] & 4)
|
||||
oddeven = (addr & 4) ? 1 : 0;
|
||||
|
||||
addr &= ~7;
|
||||
|
||||
if ((svga->crtc[0x17] & 0x20) && (svga->ma & 0x20000))
|
||||
addr |= 4;
|
||||
if (!(svga->crtc[0x17] & 0x20) && (svga->ma & 0x8000))
|
||||
addr |= 4;
|
||||
}
|
||||
|
||||
if (!(svga->crtc[0x17] & 0x01))
|
||||
addr = (addr & ~0x8000) | ((svga->sc & 1) ? 0x8000 : 0);
|
||||
if (!(svga->crtc[0x17] & 0x02))
|
||||
addr = (addr & ~0x10000) | ((svga->sc & 2) ? 0x10000 : 0);
|
||||
|
||||
if (svga->seqregs[1] & 4) {
|
||||
edat[0] = svga->vram[addr | oddeven];
|
||||
edat[2] = svga->vram[addr | oddeven | 0x2];
|
||||
edat[1] = edat[3] = 0;
|
||||
} else {
|
||||
*(uint32_t *)(&edat[0]) = *(uint32_t *)(&svga->vram[addr]);
|
||||
}
|
||||
svga->ma += 4;
|
||||
svga->ma &= svga->vram_mask;
|
||||
|
||||
if (svga->crtc[0x17] & 0x80) {
|
||||
dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2);
|
||||
p[0] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
|
||||
p[1] = svga->pallook[svga->egapal[dat & svga->plane_mask]];
|
||||
dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2);
|
||||
p[2] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
|
||||
p[3] = svga->pallook[svga->egapal[dat & svga->plane_mask]];
|
||||
dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2);
|
||||
p[4] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
|
||||
p[5] = svga->pallook[svga->egapal[dat & svga->plane_mask]];
|
||||
dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2);
|
||||
p[6] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
|
||||
p[7] = svga->pallook[svga->egapal[dat & svga->plane_mask]];
|
||||
} else
|
||||
memset(p, 0x00, 8 * sizeof(uint32_t));
|
||||
|
||||
p += 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ht216_recalctimings(svga_t *svga)
|
||||
@@ -492,8 +633,7 @@ ht216_recalctimings(svga_t *svga)
|
||||
case 6: svga->clock = (cpuclock * (double)(1ull << 32)) / 40000000.0; break;
|
||||
case 10: svga->clock = (cpuclock * (double)(1ull << 32)) / 80000000.0; break;
|
||||
}
|
||||
svga->lowres = !(ht216->ht_regs[0xc8] & HT_REG_C8_E256);
|
||||
|
||||
|
||||
svga->ma_latch |= ((ht216->ht_regs[0xf6] & 0x30) << 12);
|
||||
|
||||
svga->interlace = ht216->ht_regs[0xe0] & 1;
|
||||
@@ -504,13 +644,34 @@ ht216_recalctimings(svga_t *svga)
|
||||
high_res_256 = (svga->htotal * 8) > (svga->vtotal * 2);
|
||||
|
||||
ht216->adjust_cursor = 0;
|
||||
if ((svga->bpp == 8) && (!svga->lowres || high_res_256)) {
|
||||
if (high_res_256) {
|
||||
svga->hdisp /= 2;
|
||||
ht216->adjust_cursor = 1;
|
||||
}
|
||||
svga->render = svga_render_8bpp_highres;
|
||||
|
||||
if (svga->crtc[0x17] == 0xeb) {
|
||||
svga->rowoffset <<= 1;
|
||||
svga->render = ht216_1_2bpp_highres;
|
||||
}
|
||||
|
||||
if (svga->bpp == 8) {
|
||||
if (((ht216->ht_regs[0xc8] & HT_REG_C8_E256) || (svga->gdcreg[5] & 0x40)) && (!svga->lowres || (ht216->ht_regs[0xf6] & 0x80))) {
|
||||
if (high_res_256) {
|
||||
svga->hdisp >>= 1;
|
||||
ht216->adjust_cursor = 1;
|
||||
}
|
||||
svga->render = svga_render_8bpp_highres;
|
||||
} else if (svga->lowres) {
|
||||
if (high_res_256) {
|
||||
svga->hdisp >>= 1;
|
||||
ht216->adjust_cursor = 1;
|
||||
svga->render = svga_render_8bpp_highres;
|
||||
} else {
|
||||
svga->render = svga_render_8bpp_lowres;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (svga->crtc[0x17] == 0xeb) /*Looks like that 1024x768 mono mode expects 512K of video memory*/
|
||||
svga->vram_display_mask = 0x7ffff;
|
||||
else
|
||||
svga->vram_display_mask = (ht216->ht_regs[0xf6] & 0x40) ? ht216->vram_mask : 0x3ffff;
|
||||
}
|
||||
|
||||
|
||||
@@ -581,7 +742,6 @@ extalu(int op, uint8_t input_a, uint8_t input_b)
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ht216_dm_write(ht216_t *ht216, uint32_t addr, uint8_t cpu_dat, uint8_t cpu_dat_unexpanded)
|
||||
{
|
||||
@@ -603,7 +763,7 @@ ht216_dm_write(ht216_t *ht216, uint32_t addr, uint8_t cpu_dat, uint8_t cpu_dat_u
|
||||
else if ((svga->chain4 || svga->fb_only) && (svga->writemode < 4)) {
|
||||
writemask2 = 1 << (addr & 3);
|
||||
addr &= ~3;
|
||||
} else if (svga->chain2_write) {
|
||||
} else if (svga->chain2_write && (svga->crtc[0x17] != 0xeb)) {
|
||||
writemask2 &= ~0xa;
|
||||
if (addr & 1)
|
||||
writemask2 <<= 1;
|
||||
@@ -651,7 +811,7 @@ ht216_dm_write(ht216_t *ht216, uint32_t addr, uint8_t cpu_dat, uint8_t cpu_dat_u
|
||||
case 0x08:
|
||||
case 0x0c:
|
||||
for (i = 0; i < count; i++)
|
||||
fg_data[i] = ht216->ht_regs[0xec + i];
|
||||
fg_data[i] = ht216->fg_latch[i];
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -805,7 +965,7 @@ ht216_dm_extalu_write(ht216_t *ht216, uint32_t addr, uint8_t cpu_dat, uint8_t bi
|
||||
input_a = (ht216->ht_regs[0xf5] & (1 << ((addr & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb];
|
||||
break;
|
||||
case 0x08:
|
||||
input_a = ht216->ht_regs[0xec + (addr & 3)];
|
||||
input_a = ht216->fg_latch[addr & 3];
|
||||
break;
|
||||
case 0x0c:
|
||||
input_a = ht216->bg_latch[addr & 7];
|
||||
@@ -904,8 +1064,6 @@ ht216_write_common(ht216_t *ht216, uint32_t addr, uint8_t val)
|
||||
|
||||
cycles -= video_timing_write_b;
|
||||
|
||||
egawrites++;
|
||||
|
||||
addr &= 0xfffff;
|
||||
|
||||
val = ((val >> (svga->gdcreg[3] & 7)) | (val << (8 - (svga->gdcreg[3] & 7))));
|
||||
@@ -964,13 +1122,17 @@ ht216_write(uint32_t addr, uint8_t val, void *p)
|
||||
{
|
||||
ht216_t *ht216 = (ht216_t *)p;
|
||||
svga_t *svga = &ht216->svga;
|
||||
uint32_t prev_addr = addr;
|
||||
|
||||
addr &= svga->banked_mask;
|
||||
addr = (addr & 0x7fff) + ht216->write_banks[(addr >> 15) & 1];
|
||||
|
||||
if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe] && !ht216->ht_regs[0xf3])
|
||||
svga_write_linear(addr, val, svga);
|
||||
else
|
||||
if (svga->crtc[0x17] == 0xeb && !(svga->gdcreg[6] & 0xc) && prev_addr >= 0xb0000)
|
||||
addr += 0x10000;
|
||||
|
||||
if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe] && !ht216->ht_regs[0xf3] && svga->crtc[0x17] != 0xeb) {
|
||||
svga_write_linear(addr, val, svga);
|
||||
} else
|
||||
ht216_write_common(ht216, addr, val);
|
||||
}
|
||||
|
||||
@@ -980,11 +1142,15 @@ ht216_writew(uint32_t addr, uint16_t val, void *p)
|
||||
{
|
||||
ht216_t *ht216 = (ht216_t *)p;
|
||||
svga_t *svga = &ht216->svga;
|
||||
|
||||
uint32_t prev_addr = addr;
|
||||
|
||||
addr &= svga->banked_mask;
|
||||
addr = (addr & 0x7fff) + ht216->write_banks[(addr >> 15) & 1];
|
||||
|
||||
if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe] && !ht216->ht_regs[0xf3])
|
||||
if (svga->crtc[0x17] == 0xeb && !(svga->gdcreg[6] & 0xc) && prev_addr >= 0xb0000)
|
||||
addr += 0x10000;
|
||||
|
||||
if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe] && !ht216->ht_regs[0xf3] && svga->crtc[0x17] != 0xeb)
|
||||
svga_writew_linear(addr, val, svga);
|
||||
else {
|
||||
ht216_write_common(ht216, addr, val);
|
||||
@@ -998,11 +1164,15 @@ ht216_writel(uint32_t addr, uint32_t val, void *p)
|
||||
{
|
||||
ht216_t *ht216 = (ht216_t *)p;
|
||||
svga_t *svga = &ht216->svga;
|
||||
uint32_t prev_addr = addr;
|
||||
|
||||
addr &= svga->banked_mask;
|
||||
addr = (addr & 0x7fff) + ht216->write_banks[(addr >> 15) & 1];
|
||||
addr = (addr & 0x7fff) + ht216->write_banks[(addr >> 15) & 1];
|
||||
|
||||
if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe] && !ht216->ht_regs[0xf3])
|
||||
if (svga->crtc[0x17] == 0xeb && !(svga->gdcreg[6] & 0xc) && prev_addr >= 0xb0000)
|
||||
addr += 0x10000;
|
||||
|
||||
if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe] && !ht216->ht_regs[0xf3] && svga->crtc[0x17] != 0xeb)
|
||||
svga_writel_linear(addr, val, svga);
|
||||
else {
|
||||
ht216_write_common(ht216, addr, val);
|
||||
@@ -1084,8 +1254,6 @@ ht216_read_common(ht216_t *ht216, uint32_t addr)
|
||||
|
||||
cycles -= video_timing_read_b;
|
||||
|
||||
egareads++;
|
||||
|
||||
addr &= 0xfffff;
|
||||
|
||||
count = 2;
|
||||
@@ -1105,7 +1273,7 @@ ht216_read_common(ht216_t *ht216, uint32_t addr)
|
||||
for (i = 0; i < 8; i++)
|
||||
ht216->bg_latch[i] = svga->vram[latch_addr | i];
|
||||
return svga->vram[addr & svga->vram_mask];
|
||||
} else if (svga->chain2_read) {
|
||||
} else if (svga->chain2_read && (svga->crtc[0x17] != 0xeb)) {
|
||||
readplane = (readplane & 2) | (addr & 1);
|
||||
addr &= ~1;
|
||||
addr <<= 2;
|
||||
@@ -1132,9 +1300,10 @@ ht216_read_common(ht216_t *ht216, uint32_t addr)
|
||||
or = addr & 4;
|
||||
svga->latch.d[0] = ht216->bg_latch[0 | or] | (ht216->bg_latch[1 | or] << 8) |
|
||||
(ht216->bg_latch[2 | or] << 16) | (ht216->bg_latch[3 | or] << 24);
|
||||
|
||||
if (svga->readmode) {
|
||||
temp = 0xff;
|
||||
|
||||
|
||||
for (pixel = 0; pixel < 8; pixel++) {
|
||||
for (plane = 0; plane < 4; plane++) {
|
||||
if (svga->colournocare & (1 << plane)) {
|
||||
@@ -1158,10 +1327,14 @@ ht216_read(uint32_t addr, void *p)
|
||||
{
|
||||
ht216_t *ht216 = (ht216_t *)p;
|
||||
svga_t *svga = &ht216->svga;
|
||||
|
||||
uint32_t prev_addr = addr;
|
||||
|
||||
addr &= svga->banked_mask;
|
||||
addr = (addr & 0x7fff) + ht216->read_banks[(addr >> 15) & 1];
|
||||
|
||||
if (svga->crtc[0x17] == 0xeb && !(svga->gdcreg[6] & 0xc) && prev_addr >= 0xb0000)
|
||||
addr += 0x10000;
|
||||
|
||||
return ht216_read_common(ht216, addr);
|
||||
}
|
||||
|
||||
@@ -1177,7 +1350,6 @@ ht216_read_linear(uint32_t addr, void *p)
|
||||
return ht216_read_common(ht216, (addr & 0xffff) | ((addr & 0xc0000) >> 2));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
*ht216_init(const device_t *info, uint32_t mem_size, int has_rom)
|
||||
{
|
||||
@@ -1358,7 +1530,7 @@ const device_t g2_gc205_device =
|
||||
|
||||
const device_t v7_vga_1024i_device =
|
||||
{
|
||||
"Video 7 VGA 1024i",
|
||||
"Video 7 VGA 1024i (HT208)",
|
||||
DEVICE_ISA,
|
||||
0x7140,
|
||||
v7_vga_1024i_init,
|
||||
|
||||
@@ -79,14 +79,12 @@ uint8_t mda_in(uint16_t addr, void *p)
|
||||
void mda_write(uint32_t addr, uint8_t val, void *p)
|
||||
{
|
||||
mda_t *mda = (mda_t *)p;
|
||||
egawrites++;
|
||||
mda->vram[addr & 0xfff] = val;
|
||||
}
|
||||
|
||||
uint8_t mda_read(uint32_t addr, void *p)
|
||||
{
|
||||
mda_t *mda = (mda_t *)p;
|
||||
egareads++;
|
||||
return mda->vram[addr & 0xfff];
|
||||
}
|
||||
|
||||
|
||||
@@ -2130,8 +2130,6 @@ mystique_readb_linear(uint32_t addr, void *p)
|
||||
{
|
||||
svga_t *svga = (svga_t *)p;
|
||||
|
||||
egareads++;
|
||||
|
||||
cycles -= video_timing_read_b;
|
||||
|
||||
addr &= svga->decode_mask;
|
||||
@@ -2147,8 +2145,6 @@ mystique_readw_linear(uint32_t addr, void *p)
|
||||
{
|
||||
svga_t *svga = (svga_t *)p;
|
||||
|
||||
egareads += 2;
|
||||
|
||||
cycles -= video_timing_read_w;
|
||||
|
||||
addr &= svga->decode_mask;
|
||||
@@ -2164,8 +2160,6 @@ mystique_readl_linear(uint32_t addr, void *p)
|
||||
{
|
||||
svga_t *svga = (svga_t *)p;
|
||||
|
||||
egareads += 4;
|
||||
|
||||
cycles -= video_timing_read_l;
|
||||
|
||||
addr &= svga->decode_mask;
|
||||
@@ -2181,8 +2175,6 @@ mystique_writeb_linear(uint32_t addr, uint8_t val, void *p)
|
||||
{
|
||||
svga_t *svga = (svga_t *)p;
|
||||
|
||||
egawrites++;
|
||||
|
||||
cycles -= video_timing_write_b;
|
||||
|
||||
addr &= svga->decode_mask;
|
||||
@@ -2199,8 +2191,6 @@ mystique_writew_linear(uint32_t addr, uint16_t val, void *p)
|
||||
{
|
||||
svga_t *svga = (svga_t *)p;
|
||||
|
||||
egawrites += 2;
|
||||
|
||||
cycles -= video_timing_write_w;
|
||||
|
||||
addr &= svga->decode_mask;
|
||||
@@ -2217,8 +2207,6 @@ mystique_writel_linear(uint32_t addr, uint32_t val, void *p)
|
||||
{
|
||||
svga_t *svga = (svga_t *)p;
|
||||
|
||||
egawrites += 4;
|
||||
|
||||
cycles -= video_timing_write_l;
|
||||
|
||||
addr &= svga->decode_mask;
|
||||
|
||||
@@ -118,7 +118,6 @@ nga_write(uint32_t addr, uint8_t val, void *priv)
|
||||
nga->cga.charbuffer[offset] = nga->cga.vram[addr & 0x7fff];
|
||||
nga->cga.charbuffer[offset | 1] = nga->cga.vram[addr & 0x7fff];
|
||||
}
|
||||
egawrites++;
|
||||
nga_waitstates(&nga->cga);
|
||||
}
|
||||
|
||||
@@ -144,7 +143,6 @@ nga_read(uint32_t addr, void *priv)
|
||||
nga->cga.charbuffer[offset | 1] = nga->cga.vram[addr & 0x7fff];
|
||||
}
|
||||
|
||||
egareads++;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,9 @@
|
||||
#include <86box/vid_svga.h>
|
||||
|
||||
#define BIOS_037C_PATH L"roms/video/oti/bios.bin"
|
||||
#define BIOS_067_AMA932J_PATH L"roms/machines/ama932j/oti067.bin"
|
||||
#define BIOS_067_AMA932J_PATH L"roms/machines/ama932j/oti067.bin"
|
||||
#define BIOS_067_M300_08_PATH L"roms/machines/olivetti_m300_08/EVC_BIOS.ROM"
|
||||
#define BIOS_067_M300_15_PATH L"roms/machines/olivetti_m300_15/EVC_BIOS.ROM"
|
||||
#define BIOS_077_PATH L"roms/video/oti/oti077.vbi"
|
||||
|
||||
|
||||
@@ -38,6 +40,7 @@ enum {
|
||||
OTI_037C,
|
||||
OTI_067 = 2,
|
||||
OTI_067_AMA932J,
|
||||
OTI_067_M300 = 4,
|
||||
OTI_077 = 5
|
||||
};
|
||||
|
||||
@@ -362,6 +365,16 @@ oti_init(const device_t *info)
|
||||
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;
|
||||
@@ -439,6 +452,15 @@ 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));
|
||||
}
|
||||
|
||||
|
||||
static const device_config_t oti067_config[] =
|
||||
{
|
||||
@@ -531,6 +553,18 @@ const device_t oti067_device =
|
||||
oti067_config
|
||||
};
|
||||
|
||||
const device_t oti067_m300_device =
|
||||
{
|
||||
"Oak OTI-067 (Olivetti M300-08/15)",
|
||||
DEVICE_ISA,
|
||||
4,
|
||||
oti_init, oti_close, NULL,
|
||||
{ oti067_m300_available },
|
||||
oti_speed_changed,
|
||||
oti_force_redraw,
|
||||
oti067_config
|
||||
};
|
||||
|
||||
const device_t oti067_ama932j_device =
|
||||
{
|
||||
"Oak OTI-067 (AMA-932J)",
|
||||
|
||||
@@ -166,7 +166,6 @@ ogc_write(uint32_t addr, uint8_t val, void *priv)
|
||||
ogc->cga.charbuffer[offset] = ogc->cga.vram[addr & 0x7fff];
|
||||
ogc->cga.charbuffer[offset | 1] = ogc->cga.vram[addr & 0x7fff];
|
||||
}
|
||||
egawrites++;
|
||||
ogc_waitstates(&ogc->cga);
|
||||
}
|
||||
|
||||
@@ -186,7 +185,6 @@ ogc_read(uint32_t addr, void *priv)
|
||||
ogc->cga.charbuffer[offset | 1] = ogc->cga.vram[addr & 0x7fff];
|
||||
}
|
||||
|
||||
egareads++;
|
||||
return(ogc->cga.vram[addr & 0x7FFF]);
|
||||
}
|
||||
|
||||
|
||||
@@ -352,6 +352,16 @@ void *paradise_init(const device_t *info, uint32_t memsize)
|
||||
return paradise;
|
||||
}
|
||||
|
||||
static void *paradise_pvga1a_ncr3302_init(const device_t *info)
|
||||
{
|
||||
paradise_t *paradise = paradise_init(info, 1 << 18);
|
||||
|
||||
if (paradise)
|
||||
rom_init(¶dise->bios_rom, L"roms/machines/ncr_3302/c000-wd_1987-1989-740011-003058-019c.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
|
||||
return paradise;
|
||||
}
|
||||
|
||||
static void *paradise_pvga1a_pc2086_init(const device_t *info)
|
||||
{
|
||||
paradise_t *paradise = paradise_init(info, 1 << 18);
|
||||
@@ -361,6 +371,7 @@ static void *paradise_pvga1a_pc2086_init(const device_t *info)
|
||||
|
||||
return paradise;
|
||||
}
|
||||
|
||||
static void *paradise_pvga1a_pc3086_init(const device_t *info)
|
||||
{
|
||||
paradise_t *paradise = paradise_init(info, 1 << 18);
|
||||
@@ -464,7 +475,6 @@ void paradise_force_redraw(void *p)
|
||||
paradise->svga.fullchange = changeframecount;
|
||||
}
|
||||
|
||||
|
||||
const device_t paradise_pvga1a_pc2086_device =
|
||||
{
|
||||
"Paradise PVGA1A (Amstrad PC2086)",
|
||||
@@ -478,6 +488,7 @@ const device_t paradise_pvga1a_pc2086_device =
|
||||
paradise_force_redraw,
|
||||
NULL
|
||||
};
|
||||
|
||||
const device_t paradise_pvga1a_pc3086_device =
|
||||
{
|
||||
"Paradise PVGA1A (Amstrad PC3086)",
|
||||
@@ -516,6 +527,20 @@ static const device_config_t paradise_pvga1a_config[] =
|
||||
}
|
||||
};
|
||||
|
||||
const device_t paradise_pvga1a_ncr3302_device =
|
||||
{
|
||||
"Paradise PVGA1A (NCR 3302)",
|
||||
0,
|
||||
PVGA1A,
|
||||
paradise_pvga1a_ncr3302_init,
|
||||
paradise_close,
|
||||
NULL,
|
||||
{ NULL },
|
||||
paradise_speed_changed,
|
||||
paradise_force_redraw,
|
||||
paradise_pvga1a_config
|
||||
};
|
||||
|
||||
const device_t paradise_pvga1a_device =
|
||||
{
|
||||
"Paradise PVGA1A",
|
||||
|
||||
@@ -343,7 +343,6 @@ sigma_write(uint32_t addr, uint8_t val, void *p)
|
||||
sigma_t *sigma = (sigma_t *)p;
|
||||
|
||||
sigma->vram[sigma->plane * 0x8000 + (addr & 0x7fff)] = val;
|
||||
egawrites++;
|
||||
cycles -= 4;
|
||||
}
|
||||
|
||||
@@ -354,7 +353,6 @@ sigma_read(uint32_t addr, void *p)
|
||||
sigma_t *sigma = (sigma_t *)p;
|
||||
|
||||
cycles -= 4;
|
||||
egareads++;
|
||||
return sigma->vram[sigma->plane * 0x8000 + (addr & 0x7fff)];
|
||||
}
|
||||
|
||||
|
||||
@@ -108,6 +108,7 @@ video_cards[] = {
|
||||
{ "tvga8900d", &tvga8900d_device },
|
||||
{ "tvga9000b", &tvga9000b_device },
|
||||
{ "tgkorvga", &et4000k_isa_device },
|
||||
{ "et2000", &et2000_device },
|
||||
{ "et4000ax", &et4000_isa_device },
|
||||
{ "vga", &vga_device },
|
||||
{ "v7_vga_1024i", &v7_vga_1024i_device },
|
||||
|
||||
@@ -69,8 +69,13 @@ void vga_out(uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10)
|
||||
{
|
||||
svga->fullchange = changeframecount;
|
||||
svga_recalctimings(svga);
|
||||
if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) {
|
||||
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;
|
||||
|
||||
@@ -1424,7 +1424,6 @@ static uint8_t banshee_read_linear(uint32_t addr, void *p)
|
||||
if (addr >= svga->vram_max)
|
||||
return 0xff;
|
||||
|
||||
egareads++;
|
||||
cycles -= video_timing_read_b;
|
||||
|
||||
// banshee_log("read_linear: addr=%08x val=%02x\n", addr, svga->vram[addr & svga->vram_mask]);
|
||||
@@ -1457,7 +1456,6 @@ static uint16_t banshee_read_linear_w(uint32_t addr, void *p)
|
||||
if (addr >= svga->vram_max)
|
||||
return 0xff;
|
||||
|
||||
egareads++;
|
||||
cycles -= video_timing_read_w;
|
||||
|
||||
// banshee_log("read_linear: addr=%08x val=%02x\n", addr, svga->vram[addr & svga->vram_mask]);
|
||||
@@ -1491,7 +1489,6 @@ static uint32_t banshee_read_linear_l(uint32_t addr, void *p)
|
||||
if (addr >= svga->vram_max)
|
||||
return 0xff;
|
||||
|
||||
egareads++;
|
||||
cycles -= video_timing_read_l;
|
||||
|
||||
// banshee_log("read_linear: addr=%08x val=%02x\n", addr, svga->vram[addr & svga->vram_mask]);
|
||||
@@ -1523,8 +1520,6 @@ static void banshee_write_linear(uint32_t addr, uint8_t val, void *p)
|
||||
if (addr >= svga->vram_max)
|
||||
return;
|
||||
|
||||
egawrites++;
|
||||
|
||||
cycles -= video_timing_write_b;
|
||||
|
||||
svga->changedvram[addr >> 12] = changeframecount;
|
||||
@@ -1561,8 +1556,6 @@ static void banshee_write_linear_w(uint32_t addr, uint16_t val, void *p)
|
||||
if (addr >= svga->vram_max)
|
||||
return;
|
||||
|
||||
egawrites++;
|
||||
|
||||
cycles -= video_timing_write_w;
|
||||
|
||||
svga->changedvram[addr >> 12] = changeframecount;
|
||||
@@ -1607,8 +1600,6 @@ static void banshee_write_linear_l(uint32_t addr, uint32_t val, void *p)
|
||||
if (addr >= svga->vram_max)
|
||||
return;
|
||||
|
||||
egawrites += 4;
|
||||
|
||||
cycles -= video_timing_write_l;
|
||||
|
||||
svga->changedvram[addr >> 12] = changeframecount;
|
||||
|
||||
@@ -1071,7 +1071,6 @@ void voodoo_reg_writel(uint32_t addr, uint32_t val, void *p)
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SST_nccTable0_I2:
|
||||
if (!(val & (1 << 31)))
|
||||
{
|
||||
@@ -1087,7 +1086,6 @@ void voodoo_reg_writel(uint32_t addr, uint32_t val, void *p)
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SST_nccTable0_Q0:
|
||||
if (!(val & (1 << 31)))
|
||||
{
|
||||
@@ -1103,7 +1101,6 @@ void voodoo_reg_writel(uint32_t addr, uint32_t val, void *p)
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SST_nccTable0_Q2:
|
||||
if (!(val & (1 << 31)))
|
||||
{
|
||||
@@ -1150,7 +1147,6 @@ void voodoo_reg_writel(uint32_t addr, uint32_t val, void *p)
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SST_nccTable0_I3:
|
||||
if (!(val & (1 << 31)))
|
||||
{
|
||||
@@ -1166,7 +1162,6 @@ void voodoo_reg_writel(uint32_t addr, uint32_t val, void *p)
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SST_nccTable0_Q1:
|
||||
if (!(val & (1 << 31)))
|
||||
{
|
||||
@@ -1182,7 +1177,6 @@ void voodoo_reg_writel(uint32_t addr, uint32_t val, void *p)
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SST_nccTable0_Q3:
|
||||
if (!(val & (1 << 31)))
|
||||
{
|
||||
|
||||
@@ -459,7 +459,6 @@ void wy700_checkchanges(wy700_t *wy700)
|
||||
void wy700_write(uint32_t addr, uint8_t val, void *p)
|
||||
{
|
||||
wy700_t *wy700 = (wy700_t *)p;
|
||||
egawrites++;
|
||||
|
||||
if (wy700->wy700_mode & 0x80) /* High-res mode. */
|
||||
{
|
||||
@@ -483,7 +482,6 @@ void wy700_write(uint32_t addr, uint8_t val, void *p)
|
||||
uint8_t wy700_read(uint32_t addr, void *p)
|
||||
{
|
||||
wy700_t *wy700 = (wy700_t *)p;
|
||||
egareads++;
|
||||
if (wy700->wy700_mode & 0x80) /* High-res mode. */
|
||||
{
|
||||
addr &= 0xFFFF;
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
#include <86box/video.h>
|
||||
#include <86box/vid_svga.h>
|
||||
|
||||
#include <minitrace/minitrace.h>
|
||||
|
||||
volatile int screenshots = 0;
|
||||
bitmap_t *buffer32 = NULL;
|
||||
@@ -84,6 +85,7 @@ dbcs_font_t *fontdatksc5601_user = NULL; /* Korean KSC-5601 user defined font */
|
||||
uint32_t pal_lookup[256];
|
||||
int xsize = 1,
|
||||
ysize = 1;
|
||||
int egareads = 0, egawrites = 0;
|
||||
int cga_palette = 0,
|
||||
herc_blend = 0;
|
||||
uint32_t *video_6to8 = NULL,
|
||||
@@ -91,9 +93,7 @@ uint32_t *video_6to8 = NULL,
|
||||
*video_8to32 = NULL,
|
||||
*video_15to32 = NULL,
|
||||
*video_16to32 = NULL;
|
||||
int egareads = 0,
|
||||
egawrites = 0,
|
||||
changeframecount = 2;
|
||||
int changeframecount = 2;
|
||||
int frames = 0;
|
||||
int fullchange = 0;
|
||||
uint8_t edatlookup[4][4];
|
||||
@@ -285,6 +285,7 @@ void blit_thread(void *param)
|
||||
while (1) {
|
||||
thread_wait_event(blit_data.wake_blit_thread, -1);
|
||||
thread_reset_event(blit_data.wake_blit_thread);
|
||||
MTR_BEGIN("video", "blit_thread");
|
||||
|
||||
if (blit_func)
|
||||
blit_func(blit_data.x, blit_data.y,
|
||||
@@ -292,6 +293,7 @@ void blit_thread(void *param)
|
||||
blit_data.w, blit_data.h);
|
||||
|
||||
blit_data.busy = 0;
|
||||
MTR_END("video", "blit_thread");
|
||||
thread_set_event(blit_data.blit_complete);
|
||||
}
|
||||
}
|
||||
@@ -448,6 +450,7 @@ void
|
||||
video_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h)
|
||||
{
|
||||
int yy;
|
||||
MTR_BEGIN("video", "video_blit_memtoscreen");
|
||||
|
||||
if (y2 > 0) {
|
||||
for (yy = y1; yy < y2; yy++) {
|
||||
@@ -482,6 +485,7 @@ video_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h)
|
||||
blit_data.h = h;
|
||||
|
||||
thread_set_event(blit_data.wake_blit_thread);
|
||||
MTR_END("video", "video_blit_memtoscreen");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -122,6 +122,11 @@ BEGIN
|
||||
# endif
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Take s&creenshot\tCtrl+F11", IDM_ACTION_SCREENSHOT
|
||||
#ifdef MTR_ENABLED
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Begin trace\tCtrl+T", IDM_ACTION_BEGIN_TRACE
|
||||
MENUITEM "End trace\tCtrl+T", IDM_ACTION_END_TRACE
|
||||
#endif
|
||||
END
|
||||
#if defined(ENABLE_LOG_TOGGLES) || defined(ENABLE_LOG_COMMANDS)
|
||||
POPUP "&Logging"
|
||||
@@ -262,6 +267,9 @@ BEGIN
|
||||
#endif
|
||||
#ifdef ENABLE_LOG_BREAKPOINT
|
||||
VK_F10, IDM_LOG_BREAKPOINT, CONTROL, VIRTKEY
|
||||
#endif
|
||||
#ifdef MTR_ENABLED
|
||||
"T", IDM_ACTION_TRACE, CONTROL, VIRTKEY
|
||||
#endif
|
||||
VK_PRIOR,IDM_VID_FULLSCREEN, VIRTKEY, CONTROL , ALT
|
||||
VK_F11, IDM_ACTION_SCREENSHOT, VIRTKEY, CONTROL
|
||||
|
||||
@@ -99,6 +99,9 @@ ifeq ($(DEV_BUILD), y)
|
||||
ifndef USE_VECT486VL
|
||||
USE_VECT486VL := y
|
||||
endif
|
||||
ifndef OLIVETTI
|
||||
OLIVETTI := y
|
||||
endif
|
||||
else
|
||||
ifndef DEBUG
|
||||
DEBUG := n
|
||||
@@ -172,6 +175,9 @@ else
|
||||
ifndef USE_VECT486VL
|
||||
USE_VECT486VL := n
|
||||
endif
|
||||
ifndef OLIVETTI
|
||||
OLIVETTI := n
|
||||
endif
|
||||
endif
|
||||
|
||||
# Defaults for several build options (possibly defined in a chained file.)
|
||||
@@ -284,7 +290,7 @@ endif
|
||||
#########################################################################
|
||||
# Nothing should need changing from here on.. #
|
||||
#########################################################################
|
||||
VPATH := $(EXPATH) . $(CODEGEN) cpu \
|
||||
VPATH := $(EXPATH) . $(CODEGEN) minitrace cpu \
|
||||
cdrom chipset device disk disk/minivhd floppy \
|
||||
game machine mem printer \
|
||||
sio sound \
|
||||
@@ -482,6 +488,12 @@ RFLAGS += -DUSE_DISCORD
|
||||
DISCORDOBJ := win_discord.o
|
||||
endif
|
||||
|
||||
ifeq ($(MINITRACE), y)
|
||||
OPTS += -DMTR_ENABLED
|
||||
RFLAGS += -DMTR_ENABLED
|
||||
MINITRACEOBJ := minitrace.o
|
||||
endif
|
||||
|
||||
# Options for the DEV branch.
|
||||
ifeq ($(DEV_BRANCH), y)
|
||||
OPTS += -DDEV_BRANCH
|
||||
@@ -575,6 +587,11 @@ ifeq ($(USE_VECT486VL), y)
|
||||
OPTS += -DUSE_VECT486VL
|
||||
endif
|
||||
|
||||
ifeq ($(OLIVETTI), y)
|
||||
OPTS += -DUSE_OLIVETTI
|
||||
endif
|
||||
|
||||
|
||||
endif
|
||||
|
||||
|
||||
@@ -607,11 +624,13 @@ CPUOBJ := cpu.o cpu_table.o \
|
||||
CHIPSETOBJ := acc2168.o cs8230.o ali1217.o ali1429.o headland.o intel_82335.o cs4031.o \
|
||||
intel_420ex.o intel_4x0.o intel_sio.o intel_piix.o ioapic.o \
|
||||
neat.o opti495.o opti895.o opti5x7.o scamp.o scat.o via_vt82c49x.o via_vt82c505.o \
|
||||
gc100.o olivetti_eva.o \
|
||||
sis_85c310.o sis_85c4xx.o sis_85c496.o sis_85c50x.o stpc.o opti283.o opti291.o \
|
||||
via_apollo.o via_pipc.o wd76c10.o vl82c480.o
|
||||
|
||||
MCHOBJ := machine.o machine_table.o \
|
||||
m_xt.o m_xt_compaq.o \
|
||||
m_xt_philips.o \
|
||||
m_xt_t1000.o m_xt_t1000_vid.o \
|
||||
m_xt_xi8088.o m_xt_zenith.o \
|
||||
m_pcjr.o \
|
||||
@@ -625,6 +644,7 @@ MCHOBJ := machine.o machine_table.o \
|
||||
m_at_286_386sx.o m_at_386dx_486.o \
|
||||
m_at_socket4_5.o m_at_socket7.o m_at_sockets7.o \
|
||||
m_at_socket8.o m_at_slot1.o m_at_slot2.o m_at_socket370.o \
|
||||
m_at_ebga368.o \
|
||||
m_at_misc.o
|
||||
|
||||
DEVOBJ := bugger.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o ibm_5161.o isamem.o isartc.o \
|
||||
@@ -633,14 +653,14 @@ DEVOBJ := bugger.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o ibm
|
||||
keyboard.o \
|
||||
keyboard_xt.o keyboard_at.o \
|
||||
mouse.o \
|
||||
mouse_bus.o \
|
||||
mouse_bus.o \
|
||||
mouse_serial.o mouse_ps2.o \
|
||||
phoenix_486_jumper.o
|
||||
|
||||
SIOOBJ := sio_acc3221.o \
|
||||
sio_f82c710.o sio_82091aa.o \
|
||||
sio_fdc37c661.o sio_fdc37c66x.o sio_fdc37c669.o sio_fdc37c93x.o sio_fdc37m60x.o \
|
||||
sio_pc87306.o sio_pc87307.o sio_pc87309.o sio_pc87311.o sio_pc87332.o \
|
||||
sio_pc87306.o sio_pc87307.o sio_pc87309.o sio_pc87310.o sio_pc87311.o sio_pc87332.o \
|
||||
sio_prime3b.o sio_prime3c.o \
|
||||
sio_w83787f.o \
|
||||
sio_w83877f.o sio_w83977f.o \
|
||||
@@ -781,7 +801,7 @@ OBJ := $(MAINOBJ) $(CPUOBJ) $(CHIPSETOBJ) $(MCHOBJ) $(DEVOBJ) $(MEMOBJ) \
|
||||
$(FDDOBJ) $(GAMEOBJ) $(CDROMOBJ) $(ZIPOBJ) $(MOOBJ) $(HDDOBJ) $(MINIVHDOBJ) \
|
||||
$(NETOBJ) $(PRINTOBJ) $(SCSIOBJ) $(SIOOBJ) $(SNDOBJ) $(VIDOBJ) \
|
||||
$(PLATOBJ) $(UIOBJ) $(FSYNTHOBJ) $(MUNTOBJ) $(DEVBROBJ) \
|
||||
$(DISCORDOBJ)
|
||||
$(DISCORDOBJ) $(MINITRACEOBJ)
|
||||
ifdef EXOBJ
|
||||
OBJ += $(EXOBJ)
|
||||
endif
|
||||
|
||||
@@ -49,7 +49,9 @@
|
||||
#include <86box/win_sdl.h>
|
||||
#include <86box/win.h>
|
||||
#include <86box/version.h>
|
||||
|
||||
#ifdef MTR_ENABLED
|
||||
#include <minitrace/minitrace.h>
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
WCHAR str[512];
|
||||
@@ -217,6 +219,21 @@ plat_get_string(int i)
|
||||
return((wchar_t *)str);
|
||||
}
|
||||
|
||||
#ifdef MTR_ENABLED
|
||||
void
|
||||
init_trace(void)
|
||||
{
|
||||
mtr_init("trace.json");
|
||||
mtr_start();
|
||||
}
|
||||
|
||||
void
|
||||
shutdown_trace(void)
|
||||
{
|
||||
mtr_stop();
|
||||
mtr_shutdown();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Create a console if we don't already have one. */
|
||||
static void
|
||||
|
||||
149
src/win/win_ui.c
149
src/win/win_ui.c
@@ -48,6 +48,9 @@
|
||||
# include <86box/win_discord.h>
|
||||
#endif
|
||||
|
||||
#ifdef MTR_ENABLED
|
||||
#include <minitrace/minitrace.h>
|
||||
#endif
|
||||
|
||||
#define TIMER_1SEC 1 /* ID of the one-second timer */
|
||||
|
||||
@@ -294,6 +297,9 @@ ResetAllMenus(void)
|
||||
else
|
||||
EnableMenuItem(menuMain, IDM_DISCORD, MF_DISABLED);
|
||||
#endif
|
||||
#ifdef MTR_ENABLED
|
||||
EnableMenuItem(menuMain, IDM_ACTION_END_TRACE, MF_DISABLED);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -378,6 +384,19 @@ plat_power_off(void)
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
#ifdef MTR_ENABLED
|
||||
static void
|
||||
handle_trace(HMENU hmenu, int trace)
|
||||
{
|
||||
EnableMenuItem(hmenu, IDM_ACTION_BEGIN_TRACE, trace? MF_GRAYED : MF_ENABLED);
|
||||
EnableMenuItem(hmenu, IDM_ACTION_END_TRACE, trace? MF_ENABLED : MF_GRAYED);
|
||||
if (trace) {
|
||||
init_trace();
|
||||
} else {
|
||||
shutdown_trace();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Catch WM_INPUT messages for 'current focus' window. */
|
||||
#if defined(__amd64__) || defined(__aarch64__)
|
||||
@@ -466,6 +485,8 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
int i;
|
||||
RECT rect, *rect_p;
|
||||
|
||||
WINDOWPOS *pos;
|
||||
|
||||
int temp_x, temp_y;
|
||||
|
||||
if (input_proc(hwnd, message, wParam, lParam) == 0)
|
||||
@@ -489,6 +510,15 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
take_screenshot();
|
||||
break;
|
||||
|
||||
#ifdef MTR_ENABLED
|
||||
case IDM_ACTION_BEGIN_TRACE:
|
||||
case IDM_ACTION_END_TRACE:
|
||||
case IDM_ACTION_TRACE:
|
||||
tracing_on = !tracing_on;
|
||||
handle_trace(hmenu, tracing_on);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case IDM_ACTION_HRESET:
|
||||
win_notify_dlg_open();
|
||||
if (confirm_reset)
|
||||
@@ -581,16 +611,9 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
temp_x = unscaled_size_x;
|
||||
temp_y = unscaled_size_y;
|
||||
}
|
||||
/* Main Window. */
|
||||
|
||||
ResizeWindowByClientArea(hwnd, temp_x, temp_y + sbar_height);
|
||||
|
||||
/* Render window. */
|
||||
MoveWindow(hwndRender, 0, 0, temp_x, temp_y, TRUE);
|
||||
GetWindowRect(hwndRender, &rect);
|
||||
|
||||
/* Status bar. */
|
||||
MoveWindow(hwndSBAR, 0, rect.bottom, temp_x, 17, TRUE);
|
||||
|
||||
if (mouse_capture) {
|
||||
ClipCursor(&rect);
|
||||
}
|
||||
@@ -812,70 +835,53 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
doresize = 1;
|
||||
break;
|
||||
|
||||
case WM_SIZE:
|
||||
if (user_resize && !vid_resize)
|
||||
break;
|
||||
case WM_WINDOWPOSCHANGED:
|
||||
pos = (WINDOWPOS*)lParam;
|
||||
GetClientRect(hwndMain, &rect);
|
||||
|
||||
temp_x = (lParam & 0xFFFF);
|
||||
temp_y = (lParam >> 16);
|
||||
|
||||
if ((temp_x <= 0) || (temp_y <= 0)) {
|
||||
if (IsIconic(hwndMain)) {
|
||||
plat_vidapi_enable(0);
|
||||
minimized = 1;
|
||||
break;
|
||||
} else if (minimized == 1) {
|
||||
return(0);
|
||||
} else if (minimized) {
|
||||
minimized = 0;
|
||||
video_force_resize_set(1);
|
||||
}
|
||||
|
||||
plat_vidapi_enable(0);
|
||||
temp_y -= sbar_height;
|
||||
if (temp_y < 1)
|
||||
temp_y = 1;
|
||||
|
||||
if (vid_resize && ((temp_x != scrnsz_x) || (temp_y != scrnsz_y))) {
|
||||
scrnsz_x = temp_x;
|
||||
scrnsz_y = temp_y;
|
||||
doresize = 1;
|
||||
}
|
||||
|
||||
MoveWindow(hwndRender, 0, 0, temp_x, temp_y, TRUE);
|
||||
|
||||
GetWindowRect(hwndRender, &rect);
|
||||
|
||||
/* Status bar. */
|
||||
MoveWindow(hwndSBAR, 0, rect.bottom, temp_x, 17, TRUE);
|
||||
|
||||
plat_vidsize(temp_x, temp_y);
|
||||
|
||||
if (mouse_capture) {
|
||||
ClipCursor(&rect);
|
||||
}
|
||||
|
||||
if (window_remember) {
|
||||
GetWindowRect(hwnd, &rect);
|
||||
window_x = rect.left;
|
||||
window_y = rect.top;
|
||||
window_w = rect.right - rect.left;
|
||||
window_h = rect.bottom - rect.top;
|
||||
window_x = pos->x;
|
||||
window_y = pos->y;
|
||||
window_w = pos->cx;
|
||||
window_h = pos->cy;
|
||||
save_window_pos = 1;
|
||||
config_save();
|
||||
}
|
||||
plat_vidapi_enable(2);
|
||||
|
||||
config_save();
|
||||
break;
|
||||
if (!(pos->flags & SWP_NOSIZE)) {
|
||||
plat_vidapi_enable(0);
|
||||
|
||||
case WM_MOVE:
|
||||
if (window_remember) {
|
||||
GetWindowRect(hwnd, &rect);
|
||||
window_x = rect.left;
|
||||
window_y = rect.top;
|
||||
window_w = rect.right - rect.left;
|
||||
window_h = rect.bottom - rect.top;
|
||||
save_window_pos = 1;
|
||||
MoveWindow(hwndSBAR, 0, rect.bottom - sbar_height, sbar_height, rect.right, TRUE);
|
||||
MoveWindow(hwndRender, 0, 0, rect.right, rect.bottom - sbar_height, TRUE);
|
||||
|
||||
GetClientRect(hwndRender, &rect);
|
||||
if (rect.right != scrnsz_x || rect.bottom != scrnsz_y) {
|
||||
scrnsz_x = rect.right;
|
||||
scrnsz_y = rect.bottom;
|
||||
doresize = 1;
|
||||
}
|
||||
|
||||
plat_vidsize(rect.right, rect.bottom);
|
||||
|
||||
if (mouse_capture) {
|
||||
GetWindowRect(hwndRender, &rect);
|
||||
ClipCursor(&rect);
|
||||
}
|
||||
|
||||
plat_vidapi_enable(2);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
return(0);
|
||||
|
||||
case WM_TIMER:
|
||||
if (wParam == TIMER_1SEC)
|
||||
pc_onesec();
|
||||
@@ -1231,9 +1237,16 @@ ui_init(int nCmdShow)
|
||||
SetWindowLongPtr(hwnd, GWL_STYLE,
|
||||
(WS_OVERLAPPEDWINDOW&~WS_SIZEBOX&~WS_THICKFRAME&~WS_MAXIMIZEBOX));
|
||||
|
||||
/* Move to the last-saved position if needed. */
|
||||
/* Create the Machine Rendering window. */
|
||||
hwndRender = CreateWindow(/*L"STATIC"*/ SUB_CLASS_NAME, NULL, WS_CHILD|SS_BITMAP,
|
||||
0, 0, 1, 1, hwnd, NULL, hinstance, NULL);
|
||||
|
||||
/* Initiate a resize in order to properly arrange all controls.
|
||||
Move to the last-saved position if needed. */
|
||||
if (window_remember)
|
||||
MoveWindow(hwnd, window_x, window_y, window_w, window_h, TRUE);
|
||||
else
|
||||
ResizeWindowByClientArea(hwndMain, scrnsz_x, scrnsz_y + sbar_height);
|
||||
|
||||
/* Reset all menus to their defaults. */
|
||||
ResetAllMenus();
|
||||
@@ -1274,11 +1287,6 @@ ui_init(int nCmdShow)
|
||||
*/
|
||||
ghMutex = CreateMutex(NULL, FALSE, NULL);
|
||||
|
||||
/* Create the Machine Rendering window. */
|
||||
hwndRender = CreateWindow(/*L"STATIC"*/ SUB_CLASS_NAME, NULL, WS_CHILD|SS_BITMAP,
|
||||
0, 0, 1, 1, hwnd, NULL, hinstance, NULL);
|
||||
MoveWindow(hwndRender, 0, 0, scrnsz_x, scrnsz_y, TRUE);
|
||||
|
||||
/* All done, fire up the actual emulated machine. */
|
||||
if (! pc_init_modules()) {
|
||||
/* Dang, no ROMs found at all! */
|
||||
@@ -1463,8 +1471,6 @@ plat_pause(int p)
|
||||
void
|
||||
plat_resize(int x, int y)
|
||||
{
|
||||
RECT r;
|
||||
|
||||
/* First, see if we should resize the UI window. */
|
||||
if (!vid_resize) {
|
||||
|
||||
@@ -1474,15 +1480,6 @@ plat_resize(int x, int y)
|
||||
y = MulDiv(y, dpi, 96);
|
||||
}
|
||||
ResizeWindowByClientArea(hwndMain, x, y + sbar_height);
|
||||
|
||||
MoveWindow(hwndRender, 0, 0, x, y, TRUE);
|
||||
GetWindowRect(hwndRender, &r);
|
||||
|
||||
MoveWindow(hwndSBAR, 0, y, x, 17, TRUE);
|
||||
|
||||
if (mouse_capture) {
|
||||
ClipCursor(&r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"version-string": "3.0",
|
||||
"homepage": "https://86box.net/",
|
||||
"documentation": "http://86box.readthedocs.io/",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"license": "GPL-2.0-only",
|
||||
"dependencies": [
|
||||
"freetype",
|
||||
"libpng",
|
||||
|
||||
Reference in New Issue
Block a user