Merge branch '86Box:master' into master

This commit is contained in:
Ompronce
2021-09-18 21:46:22 -04:00
committed by GitHub
79 changed files with 3336 additions and 1263 deletions

View File

@@ -57,6 +57,7 @@ jobs:
${{ matrix.environment.prefix }}-zlib
${{ matrix.environment.prefix }}-libpng
${{ matrix.environment.prefix }}-libvncserver
${{ matrix.environment.prefix }}-winpthreads
- uses: actions/checkout@v2
- name: make
run: make -fwin/makefile.mingw -j DEV_BUILD=${{ matrix.dev-build }} NEW_DYNAREC=${{ matrix.new-dynarec }} X64=${{ matrix.environment.x64 }} CLANG=${{ matrix.clang }} VNC=n

View File

@@ -62,13 +62,16 @@ jobs:
msystem: ${{ matrix.environment.msystem }}
install: >-
${{ matrix.environment.prefix }}-ninja
${{ matrix.environment.prefix }}-toolchain
${{ matrix.environment.prefix }}-gcc
${{ matrix.environment.prefix }}-clang
${{ matrix.environment.prefix }}-pkg-config
${{ matrix.environment.prefix }}-openal
${{ matrix.environment.prefix }}-freetype
${{ matrix.environment.prefix }}-SDL2
${{ matrix.environment.prefix }}-zlib
${{ matrix.environment.prefix }}-libpng
${{ matrix.environment.prefix }}-libvncserver
${{ matrix.environment.prefix }}-winpthreads
- uses: actions/checkout@v2
- name: Configure CMake
run: >-
@@ -128,3 +131,68 @@ jobs:
with:
name: '86Box-${{ matrix.build.name }}-VS2019-${{ matrix.target-arch }}-${{ matrix.toolset }}-${{ github.sha }}'
path: build/artifacts/bin/**
linux:
name: "Linux GCC 11"
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
build:
- name: Debug
dev-build: off
new-dynarec: off
type: Debug
- name: Dev
dev-build: on
new-dynarec: on
type: Debug
steps:
- uses: actions/checkout@v2
- name: Install dependencies
run: sudo apt install gcc-11 g++-11 libfreetype-dev libsdl2-dev libpng-dev libopenal-dev libc6-dev
- name: Configure CMake
run: >-
cmake -S . -B build
-D CMAKE_INSTALL_PREFIX=./build/artifacts
-D DEV_BRANCH=${{ matrix.build.dev-build }}
-D NEW_DYNAREC=${{ matrix.build.new-dynarec }}
-D VNC=OFF
-D CMAKE_BUILD_TYPE=${{ matrix.build.type }}
-D CMAKE_C_COMPILER=gcc-11 -D CMAKE_CXX_COMPILER=g++-11
- name: Build
run: cmake --build build --target install
macos:
name: "macOS 11"
runs-on: macos-11
strategy:
fail-fast: false
matrix:
build:
- name: Debug
dev-build: off
new-dynarec: off
type: Debug
- name: Dev
dev-build: on
new-dynarec: on
type: Debug
steps:
- uses: actions/checkout@v2
- name: Install dependencies
run: brew install freetype sdl2 libpng openal-soft
- name: Configure CMake
run: >-
cmake -S . -B build
-D CMAKE_INSTALL_PREFIX=./build/artifacts
-D DEV_BRANCH=${{ matrix.build.dev-build }}
-D NEW_DYNAREC=${{ matrix.build.new-dynarec }}
-D VNC=OFF
-D CMAKE_BUILD_TYPE=${{ matrix.build.type }}
- name: Build
run: cmake --build build --target install

View File

@@ -88,6 +88,10 @@ CMAKE_DEPENDENT_OPTION(VNC "VNC renderer" ON "DEV_BRANCH" OFF)
CMAKE_DEPENDENT_OPTION(XL24 "ATI VGA Wonder XL24 (ATI-28800-6)" ON "DEV_BRANCH" OFF)
CMAKE_DEPENDENT_OPTION(VECT486VL "HP Vectra 486VL" ON "DEV_BRANCH" OFF)
if(WIN32)
option(PTHREAD "Use POSIX threads (pthreads) instead of Win32 threads" ON)
endif()
# HACK: Avoid a MSVC2019 compiler bug on ARM64 Debug builds
if(MSVC_TOOLSET_VERSION GREATER_EQUAL 142 AND ARCH STREQUAL "arm64")
# Define a cache option in case somebody wants to disable this workaround
@@ -100,4 +104,11 @@ if(MSVC_TOOLSET_VERSION GREATER_EQUAL 142 AND ARCH STREQUAL "arm64")
endif()
endif()
# HACK: MinGW and macOS <10.15 does not have `timespec_get`
include(CheckSymbolExists)
check_symbol_exists(timespec_get time.h HAS_TIMESPEC_GET)
if(HAS_TIMESPEC_GET)
add_compile_definitions(HAS_TIMESPEC_GET)
endif()
add_subdirectory(src)

View File

@@ -44,6 +44,22 @@ if(VNC)
target_link_libraries(86Box vnc vncserver ws2_32)
endif()
if(NOT WIN32 OR PTHREAD)
target_sources(86Box PRIVATE thread.c)
if(WIN32 AND VCPKG_TOOLCHAIN)
find_package(pthreads REQUIRED)
if (PThreads4W_FOUND)
target_link_libraries(86Box PThreads4W::PThreads4W)
else()
target_link_libraries(86Box pthreads)
endif()
else()
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
find_package(Threads REQUIRED)
target_link_libraries(86Box Threads::Threads)
endif()
endif()
target_link_libraries(86Box cpu chipset mch dev mem fdd game cdrom zip mo hdd
net print scsi sio snd vid voodoo plat ui)
@@ -71,8 +87,10 @@ find_package(SDL2 REQUIRED)
include_directories(${SDL2_INCLUDE_DIRS})
if(MINGW)
target_link_libraries(86Box SDL2::SDL2-static)
else()
elseif(WIN32)
target_link_libraries(86Box SDL2::SDL2)
else()
target_link_libraries(86Box ${SDL2_LIBRARIES})
endif()
find_package(PNG REQUIRED)

406
src/chipset/82c100.c Normal file
View File

@@ -0,0 +1,406 @@
/*
* 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 Chips&Technology's 82C100 chipset.
*
*
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2021 Miran Grca.
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include <86box/device.h>
#include "cpu.h"
#include "x86.h"
#include <86box/io.h>
#include <86box/mem.h>
#include <86box/nmi.h>
#include <86box/port_92.h>
#include <86box/rom.h>
#include <86box/chipset.h>
typedef struct
{
int enabled;
uint32_t virt, phys;
} ems_page_t;
typedef struct
{
uint8_t index, access;
uint16_t ems_io_base;
uint32_t ems_window_base;
uint8_t ems_page_regs[4],
regs[256];
ems_page_t ems_pages[4];
mem_mapping_t ems_mappings[4];
} ct_82c100_t;
#ifdef ENABLE_CT_82C100_LOG
int ct_82c100_do_log = ENABLE_CT82C100_LOG;
static void
ct_82c100_log(const char *fmt, ...)
{
va_list ap;
if (ct_82c100_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define ct_82c100_log(fmt, ...)
#endif
static void
ct_82c100_ems_pages_recalc(ct_82c100_t *dev)
{
int i;
uint32_t page_base;
for (i = 0; i < 4; i++) {
page_base = dev->ems_window_base + (i << 14);
if ((i == 1) || (i == 2))
page_base ^= 0xc000;
if (dev->ems_page_regs[i] & 0x80) {
dev->ems_pages[i].virt = page_base;
dev->ems_pages[i].phys = 0xa0000 + (((uint32_t) (dev->ems_page_regs[i] & 0x7f)) << 14);
ct_82c100_log("Enabling EMS page %i: %08X-%08X -> %08X-%08X\n", i,
dev->ems_pages[i].virt, dev->ems_pages[i].virt + 0x00003fff,
dev->ems_pages[i].phys, dev->ems_pages[i].phys + 0x00003fff);
mem_mapping_set_addr(&(dev->ems_mappings[i]), dev->ems_pages[i].virt, 0x4000);
mem_mapping_set_exec(&(dev->ems_mappings[i]), &(ram[dev->ems_pages[i].phys]));
mem_set_mem_state_both(page_base, 0x00004000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
} else {
ct_82c100_log("Disabling EMS page %i\n", i);
mem_mapping_disable(&(dev->ems_mappings[i]));
mem_set_mem_state_both(page_base, 0x00004000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
}
}
flushmmucache_nopc();
}
static void
ct_82c100_ems_out(uint16_t port, uint8_t val, void *priv)
{
ct_82c100_t *dev = (ct_82c100_t *) priv;
ct_82c100_log("[%04X] dev->ems_page_regs[%i] = %02X\n", port, port >> 14, val);
dev->ems_page_regs[port >> 14] = val;
ct_82c100_ems_pages_recalc(dev);
}
static uint8_t
ct_82c100_ems_in(uint16_t port, void *priv)
{
ct_82c100_t *dev = (ct_82c100_t *) priv;
uint8_t ret = 0xff;
ret = dev->ems_page_regs[port >> 14];
return ret;
}
static void
ct_82c100_ems_update(ct_82c100_t *dev)
{
int i;
for (i = 0; i < 4; i++) {
ct_82c100_log("Disabling EMS I/O handler %i at %04X\n", i, dev->ems_io_base + (i << 14));
io_handler(0, dev->ems_io_base + (i << 14), 1,
ct_82c100_ems_in, NULL, NULL, ct_82c100_ems_out, NULL, NULL, dev);
}
dev->ems_io_base = 0x0208 + (dev->regs[0x4c] & 0xf0);
for (i = 0; i < 4; i++) {
ct_82c100_log("Enabling EMS I/O handler %i at %04X\n", i, dev->ems_io_base + (i << 14));
io_handler(1, dev->ems_io_base + (i << 14), 1,
ct_82c100_ems_in, NULL, NULL, ct_82c100_ems_out, NULL, NULL, dev);
}
dev->ems_window_base = 0xc0000 + (((uint32_t) (dev->regs[0x4c] & 0x0f)) << 14);
ct_82c100_ems_pages_recalc(dev);
}
static void
ct_82c100_reset(void *priv)
{
ct_82c100_t *dev = (ct_82c100_t *) priv;
ct_82c100_log("Reset\n");
memset(dev->regs, 0x00, sizeof(dev->regs));
memset(dev->ems_page_regs, 0x00, sizeof(dev->ems_page_regs));
dev->index = dev->access = 0x00;
/* INTERNAL CONFIGURATION/CONTROL REGISTERS */
dev->regs[0x40] = 0x01; /* Defaults to 8086/V30 mode. */
dev->regs[0x43] = 0x30;
dev->regs[0x48] = 0x01;
use_custom_nmi_vector = 0;
ct_82c100_ems_update(dev);
/* ADDITIONAL I/O REGISTERS */
}
static void
ct_82c100_out(uint16_t port, uint8_t val, void *priv)
{
ct_82c100_t *dev = (ct_82c100_t *) priv;
if (port == 0x0022) {
dev->index = val;
dev->access = 1;
} else if (port == 0x0023) {
if (dev->access) {
switch (dev->index) {
/* INTERNAL CONFIGURATION/CONTROL REGISTERS */
case 0x40:
dev->regs[0x40] = val & 0xc7;
/* TODO: Clock stuff - needs CPU speed change functionality that's
going to be implemented in 86box v4.0.
Bit 0 is 0 for 8088/V20 and 1 for 8086/V30. */
break;
case 0x41:
dev->regs[0x41] = val & 0xed;
/* TODO: Where is the Software Reset Function that's enabled by
setting bit 6 to 1? */
break;
case 0x42:
dev->regs[0x42] = val & 0x01;
break;
case 0x43:
dev->regs[0x43] = val;
break;
case 0x44:
dev->regs[0x44] = val;
custom_nmi_vector = (custom_nmi_vector & 0xffffff00) | ((uint32_t) val);
break;
case 0x45:
dev->regs[0x45] = val;
custom_nmi_vector = (custom_nmi_vector & 0xffff00ff) | (((uint32_t) val) << 8);
break;
case 0x46:
dev->regs[0x46] = val;
custom_nmi_vector = (custom_nmi_vector & 0xff00ffff) | (((uint32_t) val) << 16);
break;
case 0x47:
dev->regs[0x47] = val;
custom_nmi_vector = (custom_nmi_vector & 0x00ffffff) | (((uint32_t) val) << 24);
break;
case 0x48: case 0x49:
dev->regs[dev->index] = val;
break;
case 0x4b:
dev->regs[0x4b] = val;
use_custom_nmi_vector = !!(val & 0x40);
break;
case 0x4c:
ct_82c100_log("CS4C: %02X\n", val);
dev->regs[0x4c] = val;
ct_82c100_ems_update(dev);
break;
}
dev->access = 0;
}
} else if (port == 0x72)
dev->regs[0x72] = val & 0x7e;
else if (port == 0x7e)
dev->regs[0x7e] = val;
else if (port == 0x7f) {
/* Bit 3 is Software Controlled Reset, asserted if set. Will be
done in the feature/machine_and_kb branch using hardresetx86(). */
dev->regs[0x7f] = val;
if ((dev->regs[0x41] & 0x40) && (val & 0x08)) {
softresetx86();
cpu_set_edx();
ct_82c100_reset(dev);
}
}
}
static uint8_t
ct_82c100_in(uint16_t port, void *priv)
{
ct_82c100_t *dev = (ct_82c100_t *) priv;
uint8_t ret = 0xff;
if (port == 0x0022)
ret = dev->index;
else if (port == 0x0023) {
if (dev->access) {
switch (dev->index) {
/* INTERNAL CONFIGURATION/CONTROL REGISTERS */
case 0x40 ... 0x49:
case 0x4b: case 0x4c:
ret = dev->regs[dev->index];
break;
}
dev->access = 0;
}
} else if (port == 0x72)
ret = dev->regs[0x72];
else if (port == 0x7e)
ret = dev->regs[0x7e];
else if (port == 0x7f)
ret = dev->regs[0x7f];
return ret;
}
static uint8_t
mem_read_emsb(uint32_t addr, void *priv)
{
ems_page_t *page = (ems_page_t *)priv;
uint8_t ret = 0xff;
#ifdef ENABLE_CT_82C100_LOG
uint32_t old_addr = addr;
#endif
addr = addr - page->virt + page->phys;
if (addr < ((uint32_t)mem_size << 10))
ret = ram[addr];
ct_82c100_log("mem_read_emsb(%08X = %08X): %02X\n", old_addr, addr, ret);
return ret;
}
static uint16_t
mem_read_emsw(uint32_t addr, void *priv)
{
ems_page_t *page = (ems_page_t *)priv;
uint16_t ret = 0xffff;
#ifdef ENABLE_CT_82C100_LOG
uint32_t old_addr = addr;
#endif
addr = addr - page->virt + page->phys;
if (addr < ((uint32_t)mem_size << 10))
ret = *(uint16_t *)&ram[addr];
ct_82c100_log("mem_read_emsw(%08X = %08X): %04X\n", old_addr, addr, ret);
return ret;
}
static void
mem_write_emsb(uint32_t addr, uint8_t val, void *priv)
{
ems_page_t *page = (ems_page_t *)priv;
#ifdef ENABLE_CT_82C100_LOG
uint32_t old_addr = addr;
#endif
addr = addr - page->virt + page->phys;
if (addr < ((uint32_t)mem_size << 10))
ram[addr] = val;
ct_82c100_log("mem_write_emsb(%08X = %08X, %02X)\n", old_addr, addr, val);
}
static void
mem_write_emsw(uint32_t addr, uint16_t val, void *priv)
{
ems_page_t *page = (ems_page_t *)priv;
#ifdef ENABLE_CT_82C100_LOG
uint32_t old_addr = addr;
#endif
addr = addr - page->virt + page->phys;
if (addr < ((uint32_t)mem_size << 10))
*(uint16_t *)&ram[addr] = val;
ct_82c100_log("mem_write_emsw(%08X = %08X, %04X)\n", old_addr, addr, val);
}
static void
ct_82c100_close(void *priv)
{
ct_82c100_t *dev = (ct_82c100_t *) priv;
free(dev);
}
static void *
ct_82c100_init(const device_t *info)
{
ct_82c100_t *dev;
uint32_t i;
dev = (ct_82c100_t *)malloc(sizeof(ct_82c100_t));
memset(dev, 0x00, sizeof(ct_82c100_t));
ct_82c100_reset(dev);
io_sethandler(0x0022, 2,
ct_82c100_in, NULL, NULL, ct_82c100_out, NULL, NULL, dev);
io_sethandler(0x0072, 1,
ct_82c100_in, NULL, NULL, ct_82c100_out, NULL, NULL, dev);
io_sethandler(0x007e, 2,
ct_82c100_in, NULL, NULL, ct_82c100_out, NULL, NULL, dev);
for (i = 0; i < 4; i++) {
mem_mapping_add(&(dev->ems_mappings[i]), (i + 28) << 14, 0x04000,
mem_read_emsb, mem_read_emsw, NULL,
mem_write_emsb, mem_write_emsw, NULL,
ram + 0xa0000 + (i << 14), MEM_MAPPING_INTERNAL, &dev->ems_pages[i]);
mem_mapping_disable(&(dev->ems_mappings[i]));
}
mem_mapping_disable(&ram_mid_mapping);
device_add(&port_92_device);
return(dev);
}
const device_t ct_82c100_device = {
"C&T 82C100",
0,
0,
ct_82c100_init, ct_82c100_close, ct_82c100_reset,
{ NULL }, NULL, NULL,
NULL
};

View File

@@ -13,7 +13,7 @@
# Copyright 2020,2021 David Hrdlička.
#
add_library(chipset OBJECT acc2168.c cs8230.c ali1217.c ali1429.c ali1489.c et6000.c headland.c
add_library(chipset OBJECT 82c100.c acc2168.c cs8230.c ali1217.c ali1429.c ali1489.c et6000.c headland.c
intel_82335.c cs4031.c intel_420ex.c intel_4x0.c intel_sio.c intel_piix.c ../ioapic.c
neat.c opti283.c opti291.c opti495.c opti822.c opti895.c opti5x7.c scamp.c scat.c
sis_85c310.c sis_85c4xx.c sis_85c496.c sis_85c50x.c sis_5511.c sis_5571.c sis_5598.c

View File

@@ -4314,6 +4314,56 @@ static inline void FP_LOAD_REG_D(int reg, int *host_reg1, int *host_reg2)
*host_reg1 = REG_EBX;
}
static inline int64_t x87_fround16_64(double b)
{
int16_t a, c;
switch ((cpu_state.npxc >> 10) & 3)
{
case 0: /*Nearest*/
a = (int16_t)floor(b);
c = (int16_t)floor(b + 1.0);
if ((b - a) < (c - b))
return (int64_t) a;
else if ((b - a) > (c - b))
return (int64_t) c;
else
return (a & 1) ? c : a;
case 1: /*Down*/
return (int64_t)((int16_t)floor(b));
case 2: /*Up*/
return (int64_t)((int16_t)ceil(b));
case 3: /*Chop*/
return (int64_t)((int16_t)b);
}
return 0;
}
static inline int64_t x87_fround32_64(double b)
{
int32_t a, c;
switch ((cpu_state.npxc >> 10) & 3)
{
case 0: /*Nearest*/
a = (int32_t)floor(b);
c = (int32_t)floor(b + 1.0);
if ((b - a) < (c - b))
return (int64_t) a;
else if ((b - a) > (c - b))
return (int64_t) c;
else
return (a & 1) ? c : a;
case 1: /*Down*/
return (int64_t)((int32_t)floor(b));
case 2: /*Up*/
return (int64_t)((int32_t)ceil(b));
case 3: /*Chop*/
return (int64_t)((int32_t)b);
}
return 0;
}
static inline int64_t x87_fround(double b)
{
int64_t a, c;
@@ -4363,7 +4413,7 @@ static inline int FP_LOAD_REG_INT_W(int reg)
addbyte(0xc5);
addbyte((uint8_t)cpu_state_offset(ST));
CALL_FUNC((uintptr_t)x87_fround);
CALL_FUNC((uintptr_t)x87_fround16_64);
addbyte(0x93); /*XCHG EBX, EAX*/
@@ -4393,7 +4443,7 @@ static inline int FP_LOAD_REG_INT(int reg)
addbyte(0xc5);
addbyte((uint8_t)cpu_state_offset(ST));
CALL_FUNC((uintptr_t)x87_fround);
CALL_FUNC((uintptr_t)x87_fround32_64);
addbyte(0x93); /*XCHG EBX, EAX*/

View File

@@ -505,7 +505,7 @@ load_general(void)
video_fullscreen_scale = config_get_int(cat, "video_fullscreen_scale", 0);
video_fullscreen_first = config_get_int(cat, "video_fullscreen_first", 1);
video_fullscreen_first = config_get_int(cat, "video_fullscreen_first", 0);
video_filter_method = config_get_int(cat, "video_filter_method", 1);
@@ -524,7 +524,10 @@ load_general(void)
update_icons = config_get_int(cat, "update_icons", 1);
window_remember = config_get_int(cat, "window_remember", 0);
if (window_remember) {
if (window_remember || (vid_resize & 2)) {
if (!window_remember)
config_delete_var(cat, "window_remember");
p = config_get_string(cat, "window_coordinates", NULL);
if (p == NULL)
p = "0, 0, 0, 0";
@@ -2156,8 +2159,11 @@ save_general(void)
else
config_set_int(cat, "update_icons", update_icons);
if (window_remember) {
config_set_int(cat, "window_remember", window_remember);
if (window_remember || (vid_resize & 2)) {
if (window_remember)
config_set_int(cat, "window_remember", window_remember);
else
config_delete_var(cat, "window_remember");
sprintf(temp, "%i, %i, %i, %i", window_w, window_h, window_x, window_y);
config_set_string(cat, "window_coordinates", temp);

View File

@@ -38,6 +38,10 @@
/* Is the CPU 8088 or 8086. */
int is8086 = 0;
uint8_t use_custom_nmi_vector = 0;
uint32_t custom_nmi_vector = 0x00000000;
/* The prefetch queue (4 bytes for 8088, 6 bytes for 8086). */
static uint8_t pfq[6];
@@ -578,6 +582,9 @@ reset_808x(int hard)
prefetching = 1;
cpu_alu_op = 0;
use_custom_nmi_vector = 0x00;
custom_nmi_vector = 0x00000000;
}
@@ -943,6 +950,41 @@ interrupt(uint16_t addr)
}
static void
custom_nmi(void)
{
uint16_t old_cs, old_ip;
uint16_t new_cs, new_ip;
uint16_t tempf;
cpu_state.eaaddr = 0x0002;
old_cs = CS;
access(5, 16);
(void) readmemw(0, cpu_state.eaaddr);
new_ip = custom_nmi_vector & 0xffff;
wait(1, 0);
cpu_state.eaaddr = (cpu_state.eaaddr + 2) & 0xffff;
access(6, 16);
(void) readmemw(0, cpu_state.eaaddr);
new_cs = custom_nmi_vector >> 16;
prefetching = 0;
pfq_clear();
ovr_seg = NULL;
access(39, 16);
tempf = cpu_state.flags & 0x0fd7;
push(&tempf);
cpu_state.flags &= ~(I_FLAG | T_FLAG);
access(40, 16);
push(&old_cs);
old_ip = cpu_state.pc;
load_cs(new_cs);
access(68, 16);
set_ip(new_ip);
access(41, 16);
push(&old_ip);
}
static int
irq_pending(void)
{
@@ -967,7 +1009,10 @@ check_interrupts(void)
}
if (nmi && nmi_enable && nmi_mask) {
nmi_enable = 0;
interrupt(2);
if (use_custom_nmi_vector)
custom_nmi();
else
interrupt(2);
#ifndef OLD_NMI_BEHAVIOR
nmi = 0;
#endif

View File

@@ -715,6 +715,9 @@ extern int reset_on_hlt, hlt_reset_pending;
extern cyrix_t cyrix;
extern uint8_t use_custom_nmi_vector;
extern uint32_t custom_nmi_vector;
extern void (*cpu_exec)(int cycs);
extern uint8_t do_translate, do_translate2;

View File

@@ -15,12 +15,14 @@
* Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
* RichardG, <richardg867@gmail.com>
* dob205,
*
* Copyright 2008-2019 Sarah Walker.
* Copyright 2016-2019 leilei.
* Copyright 2016-2019 Miran Grca.
* Copyright 2017-2019 Fred N. van Kempen.
* Copyright 2020 RichardG.
* Copyright 2021 dob205.
*/
#include <stdio.h>
#include <stdint.h>
@@ -760,6 +762,9 @@ const cpu_family_t cpu_families[] = {
.name = "K6 (Model 6)",
.internal_name = "k6_m6",
.cpus = (const CPU[]) {
{"66", CPU_K6, fpus_internal, 66666666, 1.0, 2900, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 8}, /* out of spec */
{"100", CPU_K6, fpus_internal, 100000000, 1.5, 2900, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, /* out of spec */
{"133", CPU_K6, fpus_internal, 133333333, 2.0, 2900, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, /* out of spec */
{"166", CPU_K6, fpus_internal, 166666666, 2.5, 2900, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
{"200", CPU_K6, fpus_internal, 200000000, 3.0, 2900, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
{"233", CPU_K6, fpus_internal, 233333333, 3.5, 3200, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28},
@@ -1513,6 +1518,9 @@ static const cpu_legacy_table_t cpus_K5[] = {
};
static const cpu_legacy_table_t cpus_K56[] = {
{"k6_m6", 66666666, 1.0},
{"k6_m6", 100000000, 1.5},
{"k6_m6", 133333333, 2.0},
{"k6_m6", 166666666, 2.5},
{"k6_m6", 200000000, 3.0},
{"k6_m6", 233333333, 3.5},

View File

@@ -152,10 +152,72 @@ static __inline double x87_pop()
return t;
}
static __inline int16_t x87_fround16(double b)
{
int16_t a, c;
switch ((cpu_state.npxc >> 10) & 3)
{
case 0: /*Nearest*/
a = (int16_t)floor(b);
c = (int16_t)floor(b + 1.0);
if ((b - a) < (c - b))
return a;
else if ((b - a) > (c - b))
return c;
else
return (a & 1) ? c : a;
case 1: /*Down*/
return (int16_t)floor(b);
case 2: /*Up*/
return (int16_t)ceil(b);
case 3: /*Chop*/
return (int16_t)b;
}
return 0;
}
static __inline int64_t x87_fround16_64(double b)
{
return (int64_t) x87_fround16(b);
}
static __inline int32_t x87_fround32(double b)
{
int32_t a, c;
switch ((cpu_state.npxc >> 10) & 3)
{
case 0: /*Nearest*/
a = (int32_t)floor(b);
c = (int32_t)floor(b + 1.0);
if ((b - a) < (c - b))
return a;
else if ((b - a) > (c - b))
return c;
else
return (a & 1) ? c : a;
case 1: /*Down*/
return (int32_t)floor(b);
case 2: /*Up*/
return (int32_t)ceil(b);
case 3: /*Chop*/
return (int32_t)b;
}
return 0;
}
static __inline int64_t x87_fround32_64(double b)
{
return (int64_t) x87_fround32(b);
}
static __inline int64_t x87_fround(double b)
{
int64_t a, c;
switch ((cpu_state.npxc >> 10) & 3)
{
case 0: /*Nearest*/

View File

@@ -42,24 +42,20 @@ static int opFILDiw_a32(uint32_t fetchdat)
static int opFISTiw_a16(uint32_t fetchdat)
{
int64_t temp64;
FP_ENTER();
fetch_ea_16(fetchdat);
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp64 = x87_fround(ST(0));
seteaw((int16_t)temp64);
seteaw(x87_fround16(ST(0)));
CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_16) : (x87_timings.fist_16 * cpu_multi));
return cpu_state.abrt;
}
#ifndef FPU_8087
static int opFISTiw_a32(uint32_t fetchdat)
{
int64_t temp64;
FP_ENTER();
fetch_ea_32(fetchdat);
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp64 = x87_fround(ST(0));
seteaw((int16_t)temp64);
seteaw(x87_fround16(ST(0)));
CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_16) : (x87_timings.fist_16 * cpu_multi));
return cpu_state.abrt;
}
@@ -67,12 +63,10 @@ static int opFISTiw_a32(uint32_t fetchdat)
static int opFISTPiw_a16(uint32_t fetchdat)
{
int64_t temp64;
FP_ENTER();
fetch_ea_16(fetchdat);
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp64 = x87_fround(ST(0));
seteaw((int16_t)temp64); if (cpu_state.abrt) return 1;
seteaw(x87_fround16(ST(0))); if (cpu_state.abrt) return 1;
x87_pop();
CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_16) : (x87_timings.fist_16 * cpu_multi));
return 0;
@@ -80,12 +74,10 @@ static int opFISTPiw_a16(uint32_t fetchdat)
#ifndef FPU_8087
static int opFISTPiw_a32(uint32_t fetchdat)
{
int64_t temp64;
FP_ENTER();
fetch_ea_32(fetchdat);
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp64 = x87_fround(ST(0));
seteaw((int16_t)temp64); if (cpu_state.abrt) return 1;
seteaw(x87_fround16(ST(0))); if (cpu_state.abrt) return 1;
x87_pop();
CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_16) : (x87_timings.fist_16 * cpu_multi));
return 0;
@@ -240,24 +232,20 @@ static int opFILDil_a32(uint32_t fetchdat)
static int opFISTil_a16(uint32_t fetchdat)
{
int64_t temp64;
FP_ENTER();
fetch_ea_16(fetchdat);
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp64 = x87_fround(ST(0));
seteal((int32_t)temp64);
seteal(x87_fround32(ST(0)));
CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_32) : (x87_timings.fist_32 * cpu_multi));
return cpu_state.abrt;
}
#ifndef FPU_8087
static int opFISTil_a32(uint32_t fetchdat)
{
int64_t temp64;
FP_ENTER();
fetch_ea_32(fetchdat);
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp64 = x87_fround(ST(0));
seteal((int32_t)temp64);
seteal(x87_fround32(ST(0)));
CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_32) : (x87_timings.fist_32 * cpu_multi));
return cpu_state.abrt;
}
@@ -265,12 +253,10 @@ static int opFISTil_a32(uint32_t fetchdat)
static int opFISTPil_a16(uint32_t fetchdat)
{
int64_t temp64;
FP_ENTER();
fetch_ea_16(fetchdat);
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp64 = x87_fround(ST(0));
seteal((int32_t)temp64); if (cpu_state.abrt) return 1;
seteal(x87_fround32(ST(0))); if (cpu_state.abrt) return 1;
x87_pop();
CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_32) : (x87_timings.fist_32 * cpu_multi));
return 0;
@@ -278,12 +264,10 @@ static int opFISTPil_a16(uint32_t fetchdat)
#ifndef FPU_8087
static int opFISTPil_a32(uint32_t fetchdat)
{
int64_t temp64;
FP_ENTER();
fetch_ea_32(fetchdat);
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp64 = x87_fround(ST(0));
seteal((int32_t)temp64); if (cpu_state.abrt) return 1;
seteal(x87_fround32(ST(0))); if (cpu_state.abrt) return 1;
x87_pop();
CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_32) : (x87_timings.fist_32 * cpu_multi));
return 0;

View File

@@ -128,7 +128,7 @@ serial_update_ints(serial_t *dev)
dev->iir = 0;
}
if (stat && ((dev->mctrl & 8) || (dev->type == SERIAL_8250_PCJR))) {
if (stat && (dev->irq != 0xff) && ((dev->mctrl & 8) || (dev->type == SERIAL_8250_PCJR))) {
if (dev->type >= SERIAL_NS16450)
picintlevel(1 << dev->irq);
else
@@ -615,7 +615,7 @@ serial_remove(serial_t *dev)
void
serial_setup(serial_t *dev, uint16_t addr, int irq)
serial_setup(serial_t *dev, uint16_t addr, uint8_t irq)
{
serial_log("Adding serial port %i at %04X...\n", dev->inst, addr);

View File

@@ -1892,9 +1892,10 @@ fdc_is_verify(fdc_t *fdc)
int
fdc_data(fdc_t *fdc, uint8_t data)
fdc_data(fdc_t *fdc, uint8_t data, int last)
{
int result = 0;
int i, result = 0;
int n;
if (fdc->deleted & 2) {
/* We're in a VERIFY command, so return with 0. */
@@ -1924,27 +1925,41 @@ fdc_data(fdc_t *fdc, uint8_t data)
}
}
} else {
result = dma_channel_write(fdc->dma_ch, data);
if (fdc->tc)
return -1;
if (result & DMA_OVER) {
fdc->data_ready = 1;
fdc->stat = 0xd0;
fdc->tc = 1;
return -1;
}
if (!fdc->fifo || (fdc->tfifo < 1)) {
fdc->data_ready = 1;
fdc->stat = 0xd0;
fdc->fifobufpos = 0;
result = dma_channel_write(fdc->dma_ch, data);
if (result & DMA_OVER) {
fdc->tc = 1;
return -1;
}
} else {
fdc_fifo_buf_advance(fdc);
if (fdc->fifobufpos == 0) {
/* FIFO enabled */
fdc_fifo_buf_write(fdc, data);
if (last || (fdc->fifobufpos == 0)) {
/* We have wrapped around, means FIFO is over */
fdc->data_ready = 1;
fdc->stat = 0xd0;
n = (fdc->fifobufpos > 0) ? (fdc->fifobufpos - 1) : fdc->tfifo;
if (fdc->fifobufpos > 0)
fdc->fifobufpos = 0;
for (i = 0; i <= n; i++) {
result = dma_channel_write(fdc->dma_ch, fdc->fifobuf[i]);
if (result & DMA_OVER) {
fdc->tc = 1;
return -1;
}
}
}
}
}
@@ -2057,10 +2072,10 @@ fdc_writeprotect(fdc_t *fdc)
int fdc_getdata(fdc_t *fdc, int last)
{
int data;
int i, data = 0;
if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->dma) {
if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->fifo) {
if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->fifo || (fdc->tfifo < 1)) {
data = fdc->dat;
if (!last)
@@ -2072,20 +2087,32 @@ int fdc_getdata(fdc_t *fdc, int last)
fdc->stat = 0xb0;
}
} else {
data = dma_channel_read(fdc->dma_ch);
if (!fdc->fifo || (fdc->tfifo < 1)) {
data = dma_channel_read(fdc->dma_ch);
if (data & DMA_OVER)
fdc->tc = 1;
if (!fdc->fifo) {
if (!last)
fdc->stat = 0x90;
} else {
fdc_fifo_buf_advance(fdc);
if (fdc->fifobufpos == 0) {
for (i = 0; i <= fdc->tfifo; i++) {
data = dma_channel_read(fdc->dma_ch);
fdc->fifobuf[i] = data;
if (data & DMA_OVER) {
fdc->tc = 1;
break;
}
}
}
data = fdc_fifo_buf_read(fdc);
if (!last && (fdc->fifobufpos == 0))
fdc->stat = 0x90;
}
if (data & DMA_OVER)
fdc->tc = 1;
}
return data & 0xff;

View File

@@ -235,7 +235,6 @@ static d86f_t *d86f[FDD_NUM];
static uint16_t CRCTable[256];
static fdc_t *d86f_fdc;
uint64_t poly = 0x42F0E1EBA9EA3693ll; /* ECMA normal */
uint64_t table[256];
uint16_t d86f_side_flags(int drive);
@@ -1499,10 +1498,15 @@ uint8_t
d86f_get_data(int drive, int base)
{
d86f_t *dev = d86f[drive];
int data;
int data, byte_count;
if (dev->data_find.bytes_obtained < (d86f_get_data_len(drive) + base)) {
data = fdc_getdata(d86f_fdc, dev->data_find.bytes_obtained == (d86f_get_data_len(drive) + base - 1));
if (fdd_get_turbo(drive) && (dev->version == 0x0063))
byte_count = dev->turbo_pos;
else
byte_count = dev->data_find.bytes_obtained;
if (byte_count < (d86f_get_data_len(drive) + base)) {
data = fdc_getdata(d86f_fdc, byte_count == (d86f_get_data_len(drive) + base - 1));
if ((data & DMA_OVER) || (data == -1)) {
dev->dma_over++;
if (data == -1)
@@ -1578,7 +1582,7 @@ d86f_read_sector_data(int drive, int side)
} else {
if (dev->data_find.bytes_obtained < d86f_get_data_len(drive)) {
if (dev->state != STATE_16_VERIFY_DATA) {
read_status = fdc_data(d86f_fdc, data);
read_status = fdc_data(d86f_fdc, data, dev->data_find.bytes_obtained == (d86f_get_data_len(drive) - 1));
if (read_status == -1)
dev->dma_over++;
}
@@ -2131,23 +2135,24 @@ d86f_turbo_read(int drive, int side)
dat = d86f_handler[drive].read_data(drive, side, dev->turbo_pos);
else
dat = (random_generate() & 0xff);
dev->turbo_pos++;
if (dev->state == STATE_11_SCAN_DATA) {
/* Scan/compare command. */
recv_data = d86f_get_data(drive, 0);
d86f_compare_byte(drive, recv_data, dat);
} else {
if (dev->data_find.bytes_obtained < (128UL << dev->last_sector.id.n)) {
if (dev->turbo_pos < (128UL << dev->req_sector.id.n)) {
if (dev->state != STATE_16_VERIFY_DATA) {
read_status = fdc_data(d86f_fdc, dat);
read_status = fdc_data(d86f_fdc, dat, dev->turbo_pos == ((128UL << dev->req_sector.id.n) - 1));
if (read_status == -1)
dev->dma_over++;
}
}
}
if (dev->turbo_pos >= (128 << dev->last_sector.id.n)) {
dev->turbo_pos++;
if (dev->turbo_pos >= (128UL << dev->req_sector.id.n)) {
dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0;
if ((flags & SECTOR_CRC_ERROR) && (dev->state != STATE_02_READ_DATA)) {
#ifdef ENABLE_D86F_LOG

View File

@@ -37,6 +37,7 @@ extern const device_t ali6117d_device;
extern const device_t amd640_device;
/* C&T */
extern const device_t ct_82c100_device;
extern const device_t neat_device;
extern const device_t scat_device;
extern const device_t scat_4_device;
@@ -65,6 +66,7 @@ extern const device_t i420zx_device;
extern const device_t i430lx_device;
extern const device_t i430nx_device;
extern const device_t i430fx_device;
extern const device_t i430fx_old_device;
extern const device_t i430fx_rev02_device;
extern const device_t i430hx_device;
extern const device_t i430vx_device;
@@ -84,6 +86,7 @@ extern const device_t sio_device;
extern const device_t sio_zb_device;
extern const device_t piix_device;
extern const device_t piix_old_device;
extern const device_t piix_rev02_device;
extern const device_t piix3_device;
extern const device_t piix4_device;

View File

@@ -157,7 +157,7 @@ extern void fdc_set_base(fdc_t *fdc, int base);
extern void fdc_set_irq(fdc_t *fdc, int irq);
extern void fdc_set_dma_ch(fdc_t *fdc, int dma_ch);
extern int fdc_getdata(fdc_t *fdc, int last);
extern int fdc_data(fdc_t *fdc, uint8_t data);
extern int fdc_data(fdc_t *fdc, uint8_t data, int last);
extern void fdc_sectorid(fdc_t *fdc, uint8_t track, uint8_t side,
uint8_t sector, uint8_t size, uint8_t crc1,

View File

@@ -622,6 +622,9 @@ extern int machine_tandy_init(const machine_t *);
extern int machine_tandy1000hx_init(const machine_t *);
extern int machine_tandy1000sl2_init(const machine_t *);
/* m_v86p.c */
extern int machine_v86p_init(const machine_t *);
#ifdef EMU_DEVICE_H
extern const device_t *tandy1k_get_device(void);
extern const device_t *tandy1k_hx_get_device(void);
@@ -648,6 +651,7 @@ extern int machine_xt_pc4i_init(const machine_t *);
extern int machine_xt_mpc1600_init(const machine_t *);
extern int machine_xt_pcspirit_init(const machine_t *);
extern int machine_xt_pc700_init(const machine_t *);
extern int machine_xt_multitechpc500_init(const machine_t *);
extern int machine_xt_iskra3104_init(const machine_t *);

View File

@@ -121,6 +121,7 @@ extern void nvr_wp_set(int set, int h, nvr_t *nvr);
extern void nvr_via_wp_set(int set, int reg, nvr_t *nvr);
extern void nvr_bank_set(int base, uint8_t bank, nvr_t *nvr);
extern void nvr_lock_set(int base, int size, int lock, nvr_t *nvr);
extern void nvr_irq_set(int irq, nvr_t *nvr);
#endif /*EMU_NVR_H*/

View File

@@ -36,7 +36,7 @@ extern int stricmp(const char* s1, const char* s2);
extern int strnicmp(const char* s1, const char* s2, size_t n);
#endif
#if defined(UNIX) && defined(FREEBSD) || defined(__APPLE__)
#if (defined(__unix__) || defined(__APPLE__)) && !defined(__linux__)
/* FreeBSD has largefile by default. */
# define fopen64 fopen
# define fseeko64 fseeko

View File

@@ -77,7 +77,7 @@ extern serial_t * serial_attach(int port,
void *priv);
extern void serial_remove(serial_t *dev);
extern void serial_set_type(serial_t *dev, int type);
extern void serial_setup(serial_t *dev, uint16_t addr, int irq);
extern void serial_setup(serial_t *dev, uint16_t addr, uint8_t irq);
extern void serial_clear_fifo(serial_t *dev);
extern void serial_write_fifo(serial_t *dev, uint8_t dat);
extern void serial_set_next_inst(int ni);

View File

@@ -20,6 +20,7 @@ extern void vt82c686_sio_write(uint8_t addr, uint8_t val, void *priv);
extern const device_t acc3221_device;
extern const device_t f82c710_device;
extern const device_t f82c606_device;
extern const device_t fdc37c651_device;
extern const device_t fdc37c661_device;
extern const device_t fdc37c663_device;

View File

@@ -153,6 +153,7 @@ typedef struct svga_t
/*Force CRTC to dword mode, regardless of CR14/CR17. Required for S3 enhanced mode*/
int force_dword_mode;
int force_byte_mode;
int remap_required;
uint32_t (*remap_func)(struct svga_t *svga, uint32_t in_addr);
@@ -201,7 +202,7 @@ void svga_close(svga_t *svga);
uint32_t svga_mask_addr(uint32_t addr, svga_t *svga);
uint32_t svga_mask_changedaddr(uint32_t addr, svga_t *svga);
void svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga);
void svga_doblit(int wx, int wy, svga_t *svga);
enum {

View File

@@ -101,7 +101,7 @@ void svga_recalc_remap_func(svga_t *svga)
{
int func_nr;
if (svga->fb_only)
if (svga->fb_only || svga->force_byte_mode)
func_nr = 0;
else {
if (svga->force_dword_mode)

View File

@@ -84,7 +84,7 @@ typedef rgb_t PALETTE[256];
extern int changeframecount;
extern volatile int screenshots;
extern bitmap_t *buffer32, *render_buffer;
extern bitmap_t *buffer32;
extern PALETTE cgapal,
cgapal_mono[6];
extern uint32_t pal_lookup[256];
@@ -150,10 +150,10 @@ extern void video_inform(int type, const video_timings_t *ptr);
extern int video_get_type(void);
extern void video_setblit(void(*blit)(int,int,int,int,int,int));
extern void video_setblit(void(*blit)(int,int,int,int));
extern void video_blend(int x, int y);
extern void video_blit_memtoscreen_8(int x, int y, int y1, int y2, int w, int h);
extern void video_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h);
extern void video_blit_memtoscreen_8(int x, int y, int w, int h);
extern void video_blit_memtoscreen(int x, int y, int w, int h);
extern void video_blit_complete(void);
extern void video_wait_for_blit(void);
extern void video_wait_for_buffer(void);
@@ -249,6 +249,9 @@ extern const device_t compaq_cga_2_device;
extern const device_t ogc_device;
extern const device_t ogc_m24_device;
/* Chips & Technologies 82C425 */
extern const device_t f82c425_video_device;
/* NCR NGA */
extern const device_t nga_device;
@@ -327,6 +330,7 @@ extern const device_t s3_metheus_86c928_isa_device;
extern const device_t s3_metheus_86c928_vlb_device;
extern const device_t s3_spea_mirage_86c801_isa_device;
extern const device_t s3_spea_mirage_86c805_vlb_device;
extern const device_t s3_mirocrystal_8s_805_vlb_device;
extern const device_t s3_mirocrystal_10sd_805_vlb_device;
extern const device_t s3_phoenix_86c801_isa_device;
extern const device_t s3_phoenix_86c805_vlb_device;
@@ -346,6 +350,7 @@ extern const device_t s3_phoenix_trio64vplus_pci_device;
extern const device_t s3_phoenix_trio64vplus_onboard_pci_device;
extern const device_t s3_mirocrystal_20sv_964_vlb_device;
extern const device_t s3_mirocrystal_20sv_964_pci_device;
extern const device_t s3_mirocrystal_20sd_864_vlb_device;
extern const device_t s3_phoenix_vision864_pci_device;
extern const device_t s3_phoenix_vision864_vlb_device;
extern const device_t s3_phoenix_vision868_pci_device;
@@ -354,8 +359,9 @@ extern const device_t s3_diamond_stealth64_pci_device;
extern const device_t s3_diamond_stealth64_vlb_device;
extern const device_t s3_diamond_stealth64_964_pci_device;
extern const device_t s3_diamond_stealth64_964_vlb_device;
extern const device_t s3_mirovideo_40sv_968_pci_device;
extern const device_t s3_mirovideo_40sv_968_vlb_device;
extern const device_t s3_mirovideo_40sv_ergo_968_pci_device;
extern const device_t s3_phoenix_vision968_pci_device;
extern const device_t s3_phoenix_vision968_vlb_device;
extern const device_t s3_spea_mercury_p64v_pci_device;
extern const device_t s3_elsa_winner2000_pro_x_964_pci_device;
extern const device_t s3_elsa_winner2000_pro_x_pci_device;

View File

@@ -16,7 +16,8 @@
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_amstrad.c m_europc.c m_xt_olivetti.c m_tandy.c m_v86p.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

View File

@@ -577,10 +577,10 @@ vid_poll_1512(void *priv)
}
if (enable_overscan) {
video_blit_memtoscreen_8(0, (vid->firstline - 4) << 1, 0, ((vid->lastline - vid->firstline) + 8) << 1,
video_blit_memtoscreen_8(0, (vid->firstline - 4) << 1,
xsize, ((vid->lastline - vid->firstline) + 8) << 1);
} else {
video_blit_memtoscreen_8(8, vid->firstline << 1, 0, (vid->lastline - vid->firstline) << 1,
video_blit_memtoscreen_8(8, vid->firstline << 1,
xsize, (vid->lastline - vid->firstline) << 1);
}
}
@@ -1403,7 +1403,7 @@ lcdm_poll(amsvid_t *vid)
if (video_force_resize_get())
video_force_resize_set(0);
}
video_blit_memtoscreen(0, mda->firstline, 0, ysize, xsize, ysize);
video_blit_memtoscreen(0, mda->firstline, xsize, ysize);
frames++;
video_res_x = mda->crtc[1];
video_res_y = mda->crtc[6];
@@ -1571,7 +1571,7 @@ lcdc_poll(amsvid_t *vid)
video_force_resize_set(0);
}
video_blit_memtoscreen(0, cga->firstline << 1, 0, (cga->lastline - cga->firstline) << 1,
video_blit_memtoscreen(0, cga->firstline << 1,
xsize, (cga->lastline - cga->firstline) << 1);
}

View File

@@ -514,7 +514,7 @@ compaq_plasma_poll(void *p)
if (video_force_resize_get())
video_force_resize_set(0);
}
video_blit_memtoscreen(0, 0, 0, ysize, xsize, ysize);
video_blit_memtoscreen(0, 0, xsize, ysize);
frames++;
/* Fixed 640x400 resolution */

View File

@@ -590,7 +590,7 @@ void t3100e_poll(void *p)
if (video_force_resize_get())
video_force_resize_set(0);
}
video_blit_memtoscreen(0, 0, 0, ysize, xsize, ysize);
video_blit_memtoscreen(0, 0, xsize, ysize);
frames++;
/* Fixed 640x400 resolution */

View File

@@ -566,17 +566,17 @@ vid_poll(void *p)
if (enable_overscan) {
if (pcjr->composite)
video_blit_memtoscreen(0, (pcjr->firstline - 4) << 1, 0, ((pcjr->lastline - pcjr->firstline) + 8) << 1,
video_blit_memtoscreen(0, (pcjr->firstline - 4) << 1,
xsize, ((pcjr->lastline - pcjr->firstline) + 8) << 1);
else
video_blit_memtoscreen_8(0, (pcjr->firstline - 4) << 1, 0, ((pcjr->lastline - pcjr->firstline) + 8) << 1,
video_blit_memtoscreen_8(0, (pcjr->firstline - 4) << 1,
xsize, ((pcjr->lastline - pcjr->firstline) + 8) << 1);
} else {
if (pcjr->composite)
video_blit_memtoscreen(8, pcjr->firstline << 1, 0, (pcjr->lastline - pcjr->firstline) << 1,
video_blit_memtoscreen(8, pcjr->firstline << 1,
xsize, (pcjr->lastline - pcjr->firstline) << 1);
else
video_blit_memtoscreen_8(8, pcjr->firstline << 1, 0, (pcjr->lastline - pcjr->firstline) << 1,
video_blit_memtoscreen_8(8, pcjr->firstline << 1,
xsize, (pcjr->lastline - pcjr->firstline) << 1);
}
}

View File

@@ -1032,17 +1032,17 @@ vid_poll(void *priv)
if (enable_overscan) {
if (!dev->is_sl2 && vid->composite)
video_blit_memtoscreen(0, (vid->firstline - 4) << 1, 0, ((vid->lastline - vid->firstline) + 8) << 1,
video_blit_memtoscreen(0, (vid->firstline - 4) << 1,
xsize, ((vid->lastline - vid->firstline) + 8) << 1);
else
video_blit_memtoscreen_8(0, (vid->firstline - 4) << 1, 0, ((vid->lastline - vid->firstline) + 8) << 1,
video_blit_memtoscreen_8(0, (vid->firstline - 4) << 1,
xsize, ((vid->lastline - vid->firstline) + 8) << 1);
} else {
if (!dev->is_sl2 && vid->composite)
video_blit_memtoscreen(8, vid->firstline << 1, 0, (vid->lastline - vid->firstline) << 1,
video_blit_memtoscreen(8, vid->firstline << 1,
xsize, (vid->lastline - vid->firstline) << 1);
else
video_blit_memtoscreen_8(8, vid->firstline << 1, 0, (vid->lastline - vid->firstline) << 1,
video_blit_memtoscreen_8(8, vid->firstline << 1,
xsize, (vid->lastline - vid->firstline) << 1);
}
}

97
src/machine/m_v86p.c Normal file
View File

@@ -0,0 +1,97 @@
/*
* 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.
*
* Victor V86P portable computer emulation.
*
* Author: Lubomir Rintel, <lkundrak@v3.sk>
*
* Copyright 2021 Lubomir Rintel.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the:
*
* Free Software Foundation, Inc.
* 59 Temple Place - Suite 330
* Boston, MA 02111-1307
* USA.
*/
#include <stdio.h>
#include <stdint.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/mem.h>
#include <86box/timer.h>
#include <86box/rom.h>
#include <86box/machine.h>
#include <86box/device.h>
#include <86box/fdd.h>
#include <86box/fdc.h>
#include <86box/fdc_ext.h>
#include <86box/keyboard.h>
#include <86box/chipset.h>
#include <86box/sio.h>
#include <86box/video.h>
int
machine_v86p_init(const machine_t *model)
{
int ret, rom = 0;
ret = bios_load_interleavedr("roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_122089_Even.rom",
"roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_122089_Odd.rom",
0x000f8000, 65536, 0);
if (!ret) {
/* Try an older version of the BIOS. */
rom = 1;
ret = bios_load_interleavedr("roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_090489_Even.rom",
"roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_090489_Odd.rom",
0x000f8000, 65536, 0);
}
if (!ret) {
/* Try JVERNET's BIOS. */
rom = 2;
ret = bios_load_linear("roms/machines/v86p/V86P.ROM",
0x000f0000, 65536, 0);
}
if (bios_only || !ret)
return ret;
if (rom == 2)
loadfont("roms/machines/v86p/V86P.FON", 8);
else
loadfont("roms/machines/v86p/v86pfont.rom", 8);
machine_common_init(model);
device_add(&ct_82c100_device);
device_add(&f82c606_device);
device_add(&keyboard_xt_device);
if (fdc_type == FDC_INTERNAL)
device_add(&fdc_xt_device);
if (gfxcard == VID_INTERNAL)
device_add(&f82c425_video_device);
return ret;
}

View File

@@ -424,3 +424,22 @@ machine_xt_pc700_init(const machine_t *model)
return ret;
}
int
machine_xt_multitechpc500_init(const machine_t* model)
{
int ret;
ret = bios_load_linear("roms/machines/multitech_pc500/rom404.bin",
0x000f8000, 32768, 0);
if (bios_only || !ret)
return ret;
device_add(&keyboard_pc_device);
machine_xt_common_init(model);
return ret;
}

View File

@@ -556,7 +556,7 @@ static void t1000_poll(void *p)
if (video_force_resize_get())
video_force_resize_set(0);
}
video_blit_memtoscreen(0, 0, 0, ysize, xsize, ysize);
video_blit_memtoscreen(0, 0, xsize, ysize);
frames++;
/* Fixed 640x200 resolution */

View File

@@ -72,7 +72,8 @@ const machine_t machines[] = {
{ "[8088] DTK XT clone", "dtk", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_dtk_init, NULL },
{ "[8088] Eagle PC Spirit", "pcspirit", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_pcspirit_init, NULL },
{ "[8088] Generic XT clone", "genxt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_genxt_init, NULL },
{ "[8088] Juko XT clone", "jukopc", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_jukopc_init, NULL },
{ "[8088] Juko ST", "jukopc", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_jukopc_init, NULL },
{ "[8088] Multitech PC-500", "multitech_pc500", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_multitechpc500_init, NULL },
{ "[8088] Multitech PC-700", "pc700", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_pc700_init, NULL },
{ "[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_pc4i_init, NULL },
{ "[8088] Olivetti M19", "m19", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 4772728, 7159092, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED, 256, 640, 256, 0, machine_xt_m19_init, m19_get_device },
@@ -105,6 +106,7 @@ const machine_t machines[] = {
{ "[8086] Olivetti M240", "m240", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 128, 0, machine_xt_m240_init, NULL },
{ "[8086] Schetmash Iskra-3104", "iskra3104", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 128, 0, machine_xt_iskra3104_init, NULL },
{ "[8086] Tandy 1000 SL/2", "tandy1000sl2", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED, 512, 768, 128, 0, machine_tandy1000sl2_init, tandy1k_sl_get_device },
{ "[8086] Victor V86P", "v86p", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO, 512, 1024, 128, 127, machine_v86p_init, NULL },
{ "[8086] Toshiba T1200", "t1200", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO, 1024, 2048,1024, 63, machine_xt_t1200_init, t1200_get_device },
#if defined(DEV_BRANCH) && defined(USE_LASERXT)

View File

@@ -20,6 +20,6 @@ void nmi_write(uint16_t port, uint8_t val, void *p)
void nmi_init(void)
{
io_sethandler(0x00a0, 0x0001, NULL, NULL, NULL, nmi_write, NULL, NULL, NULL);
io_sethandler(0x00a0, 0x000f, NULL, NULL, NULL, nmi_write, NULL, NULL, NULL);
nmi_mask = 0;
}

View File

@@ -922,6 +922,13 @@ nvr_lock_set(int base, int size, int lock, nvr_t *nvr)
}
void
nvr_irq_set(int irq, nvr_t *nvr)
{
nvr->irq = irq;
}
static void
nvr_at_reset(void *priv)
{

View File

@@ -1362,7 +1362,7 @@ t128_read(uint32_t addr, void *priv)
if (ncr_dev->t128.host_pos == MIN(512, dev->buffer_length)) {
ncr_dev->t128.status &= ~0x04;
ncr_log("Transfer busy read, status = %02x, period = %lf\n", ncr_dev->t128.status, ncr_dev->period);
if (ncr_dev->period == 0.2)
if (ncr_dev->period == 0.2 || ncr_dev->period == 0.02)
timer_on_auto(&ncr_dev->timer, 40.2);
}
}

View File

@@ -6,13 +6,23 @@
*
* This file is part of the 86Box distribution.
*
* Implementation of the Chips & Technologies F82C710 Universal Peripheral Controller (UPC).
* Implementation of the Chips & Technologies F82C710 Universal Peripheral
* Controller (UPC) and 82C606 CHIPSpak Multifunction Controller.
*
* Relevant literature:
*
* [1] Chips and Technologies, Inc.,
* 82C605/82C606 CHIPSpak/CHIPSport MULTIFUNCTION CONTROLLERS,
* PRELIMINARY Data Sheet, Revision 1, May 1987.
* <https://archive.org/download/82C606/82C606.pdf>
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Eluan Costa Miranda <eluancm@gmail.com>
* Lubomir Rintel <lkundrak@v3.sk>
*
* Copyright 2020 Sarah Walker.
* Copyright 2020 Eluan Costa Miranda.
* Copyright 2021 Lubomir Rintel.
*/
#include <stdio.h>
#include <stdint.h>
@@ -25,213 +35,326 @@
#include <86box/device.h>
#include <86box/lpt.h>
#include <86box/serial.h>
#include <86box/gameport.h>
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
#include <86box/fdd.h>
#include <86box/fdc.h>
#include <86box/nvr.h>
#include <86box/sio.h>
typedef struct upc_t
{
int configuration_state; /* state of algorithm to enter configuration mode */
int configuration_mode;
uint16_t cri_addr; /* cri = configuration index register, addr is even */
uint16_t cap_addr; /* cap = configuration access port, addr is odd and is cri_addr + 1 */
uint8_t cri; /* currently indexed register */
uint32_t local;
int configuration_state; /* state of algorithm to enter configuration mode */
int configuration_mode;
uint16_t cri_addr; /* cri = configuration index register, addr is even */
uint16_t cap_addr; /* cap = configuration access port, addr is odd and is cri_addr + 1 */
uint8_t cri; /* currently indexed register */
uint8_t last_write;
/* these regs are not affected by reset */
uint8_t regs[15]; /* there are 16 indexes, but there is no need to store the last one which is: R = cri_addr / 4, W = exit config mode */
fdc_t *fdc;
serial_t *uart[2];
/* these regs are not affected by reset */
uint8_t regs[15]; /* there are 16 indexes, but there is no need to store the last one which is: R = cri_addr / 4, W = exit config mode */
fdc_t * fdc;
nvr_t * nvr;
void * gameport;
serial_t * uart[2];
} upc_t;
static void
f82c710_update_ports(upc_t *upc)
f82c710_update_ports(upc_t *dev, int set)
{
uint16_t com_addr = 0;
uint16_t lpt_addr = 0;
serial_remove(upc->uart[0]);
serial_remove(upc->uart[1]);
lpt1_remove();
lpt2_remove();
fdc_remove(upc->fdc);
ide_pri_disable();
uint16_t com_addr = 0;
uint16_t lpt_addr = 0;
if (upc->regs[0] & 4) {
com_addr = upc->regs[4] * 4;
if (com_addr == SERIAL1_ADDR) {
serial_setup(upc->uart[0], com_addr, 4);
} else if (com_addr == SERIAL2_ADDR) {
serial_setup(upc->uart[1], com_addr, 3);
}
}
serial_remove(dev->uart[0]);
serial_remove(dev->uart[1]);
lpt1_remove();
lpt2_remove();
fdc_remove(dev->fdc);
ide_pri_disable();
if (upc->regs[0] & 8) {
lpt_addr = upc->regs[6] * 4;
lpt1_init(lpt_addr);
if ((lpt_addr == 0x378) || (lpt_addr == 0x3bc)) {
lpt1_irq(7);
} else if (lpt_addr == 0x278) {
lpt1_irq(5);
}
}
if (!set)
return;
if (upc->regs[12] & 0x80) {
ide_pri_enable();
}
if (dev->regs[0] & 4) {
com_addr = dev->regs[4] * 4;
if (com_addr == SERIAL1_ADDR)
serial_setup(dev->uart[0], com_addr, 4);
else if (com_addr == SERIAL2_ADDR)
serial_setup(dev->uart[1], com_addr, 3);
}
if (upc->regs[12] & 0x20) {
fdc_set_base(upc->fdc, 0x03f0);
}
if (dev->regs[0] & 8) {
lpt_addr = dev->regs[6] * 4;
lpt1_init(lpt_addr);
if ((lpt_addr == 0x378) || (lpt_addr == 0x3bc))
lpt1_irq(7);
else if (lpt_addr == 0x278)
lpt1_irq(5);
}
if (dev->regs[12] & 0x80)
ide_pri_enable();
if (dev->regs[12] & 0x20)
fdc_set_base(dev->fdc, 0x03f0);
}
static void
f82c606_update_ports(upc_t *dev, int set)
{
uint8_t uart1_int = 0xff;
uint8_t uart2_int = 0xff;
uint8_t lpt1_int = 0xff;
int nvr_int = -1;
serial_remove(dev->uart[0]);
serial_remove(dev->uart[1]);
lpt1_remove();
lpt2_remove();
nvr_at_handler(0, ((uint16_t) dev->regs[3]) << 2, dev->nvr);
nvr_at_handler(0, 0x70, dev->nvr);
gameport_remap(dev->gameport, 0);
if (!set)
return;
switch (dev->regs[8] & 0xc0) {
case 0x40: nvr_int = 3; break;
case 0x80: uart1_int = 3; break;
case 0xc0: uart2_int = 3; break;
}
switch (dev->regs[8] & 0x30) {
case 0x10: nvr_int = 4; break;
case 0x20: uart1_int = 4; break;
case 0x30: uart2_int = 4; break;
}
switch (dev->regs[8] & 0x0c) {
case 0x04: nvr_int = 5; break;
case 0x08: uart1_int = 5; break;
case 0x0c: lpt1_int = 5; break;
}
switch (dev->regs[8] & 0x03) {
case 0x01: nvr_int = 7; break;
case 0x02: uart2_int = 7; break;
case 0x03: lpt1_int = 7; break;
}
if (dev->regs[0] & 1) {
gameport_remap(dev->gameport, ((uint16_t) dev->regs[7]) << 2);
pclog("Game port at %04X\n", ((uint16_t) dev->regs[7]) << 2);
}
if (dev->regs[0] & 2) {
serial_setup(dev->uart[0], ((uint16_t) dev->regs[4]) << 2, uart1_int);
pclog("UART 1 at %04X, IRQ %i\n", ((uint16_t) dev->regs[4]) << 2, uart1_int);
}
if (dev->regs[0] & 4) {
serial_setup(dev->uart[1], ((uint16_t) dev->regs[5]) << 2, uart2_int);
pclog("UART 2 at %04X, IRQ %i\n", ((uint16_t) dev->regs[5]) << 2, uart2_int);
}
if (dev->regs[0] & 8) {
lpt1_init(((uint16_t) dev->regs[6]) << 2);
lpt1_irq(lpt1_int);
pclog("LPT1 at %04X, IRQ %i\n", ((uint16_t) dev->regs[6]) << 2, lpt1_int);
}
nvr_at_handler(1, ((uint16_t) dev->regs[3]) << 2, dev->nvr);
nvr_irq_set(nvr_int, dev->nvr);
pclog("RTC at %04X, IRQ %i\n", ((uint16_t) dev->regs[3]) << 2, nvr_int);
}
static uint8_t
f82c710_config_read(uint16_t port, void *priv)
{
upc_t *upc = (upc_t *)priv;
uint8_t temp = 0xff;
upc_t *dev = (upc_t *) priv;
uint8_t temp = 0xff;
if (upc->configuration_mode) {
if (port == upc->cri_addr) {
temp = upc->cri;
} else if (port == upc->cap_addr) {
if (upc->cri == 0xf)
temp = upc->cri_addr / 4;
else
temp = upc->regs[upc->cri];
}
}
if (dev->configuration_mode) {
if (port == dev->cri_addr) {
temp = dev->cri;
} else if (port == dev->cap_addr) {
if (dev->cri == 0xf)
temp = dev->cri_addr / 4;
else
temp = dev->regs[dev->cri];
}
}
return temp;
return temp;
}
static void
f82c710_config_write(uint16_t port, uint8_t val, void *priv)
{
upc_t *upc = (upc_t *)priv;
int configuration_state_event = 0;
upc_t *dev = (upc_t *) priv;
int configuration_state_event = 0;
switch(port) {
case 0x2fa:
if (upc->configuration_state == 0 && val == 0x55)
configuration_state_event = 1;
else if (upc->configuration_state == 4) {
uint8_t addr_verify = upc->cri_addr / 4;
addr_verify += val;
if (addr_verify == 0xff) {
upc->configuration_mode = 1;
/* TODO: is the value of cri reset here or when exiting configuration mode? */
io_sethandler(upc->cri_addr, 0x0002, f82c710_config_read, NULL, NULL, f82c710_config_write, NULL, NULL, upc);
} else {
upc->configuration_mode = 0;
}
}
break;
case 0x3fa:
if (upc->configuration_state == 1 && val == 0xaa)
configuration_state_event = 1;
else if (upc->configuration_state == 2 && val == 0x36)
configuration_state_event = 1;
else if (upc->configuration_state == 3) {
upc->cri_addr = val * 4;
upc->cap_addr = upc->cri_addr + 1;
configuration_state_event = 1;
}
break;
default:
break;
}
if (upc->configuration_mode) {
if (port == upc->cri_addr) {
upc->cri = val & 0xf;
} else if (port == upc->cap_addr) {
if (upc->cri == 0xf) {
upc->configuration_mode = 0;
io_removehandler(upc->cri_addr, 0x0002, f82c710_config_read, NULL, NULL, f82c710_config_write, NULL, NULL, upc);
f82c710_update_ports(upc); /* TODO: any benefit in updating at each register write instead of when exiting config mode? */
} else {
upc->regs[upc->cri] = val;
}
}
}
switch (port) {
case 0x2fa:
if ((dev->configuration_state == 0) && (val != 0x00) && (val != 0xff) && (dev->local == 606)) {
configuration_state_event = 1;
dev->last_write = val;
} else if ((dev->configuration_state == 0) && (val == 0x55) && (dev->local == 710))
configuration_state_event = 1;
else if (dev->configuration_state == 4) {
if ((val | dev->last_write) == 0xff) {
dev->cri_addr = ((uint16_t) dev->last_write) << 2;
dev->cap_addr = dev->cri_addr + 1;
dev->configuration_mode = 1;
if (dev->local == 606)
f82c606_update_ports(dev, 0);
else if (dev->local == 710)
f82c710_update_ports(dev, 0);
/* TODO: is the value of cri reset here or when exiting configuration mode? */
io_sethandler(dev->cri_addr, 0x0002, f82c710_config_read, NULL, NULL, f82c710_config_write, NULL, NULL, dev);
} else
dev->configuration_mode = 0;
}
break;
case 0x3fa:
if ((dev->configuration_state == 1) && ((val | dev->last_write) == 0xff) && (dev->local == 606))
configuration_state_event = 1;
else if ((dev->configuration_state == 1) && (val == 0xaa) && (dev->local == 710))
configuration_state_event = 1;
else if ((dev->configuration_state == 2) && (val == 0x36))
configuration_state_event = 1;
else if (dev->configuration_state == 3) {
dev->last_write = val;
configuration_state_event = 1;
}
break;
default:
break;
}
/* TODO: is the state only reset when accessing 0x2fa and 0x3fa wrongly? */
if ((port == 0x2fa || port == 0x3fa) && configuration_state_event)
upc->configuration_state++;
else
upc->configuration_state = 0;
if (dev->configuration_mode) {
if (port == dev->cri_addr) {
dev->cri = val & 0xf;
} else if (port == dev->cap_addr) {
if (dev->cri == 0xf) {
dev->configuration_mode = 0;
io_removehandler(dev->cri_addr, 0x0002, f82c710_config_read, NULL, NULL, f82c710_config_write, NULL, NULL, dev);
/* TODO: any benefit in updating at each register write instead of when exiting config mode? */
if (dev->local == 606)
f82c606_update_ports(dev, 1);
else if (dev->local == 710)
f82c710_update_ports(dev, 1);
} else
dev->regs[dev->cri] = val;
}
}
/* TODO: is the state only reset when accessing 0x2fa and 0x3fa wrongly? */
if ((port == 0x2fa || port == 0x3fa) && configuration_state_event)
dev->configuration_state++;
else
dev->configuration_state = 0;
}
static void
f82c710_reset(upc_t *upc)
f82c710_reset(void *priv)
{
serial_remove(upc->uart[0]);
serial_setup(upc->uart[0], SERIAL1_ADDR, SERIAL1_IRQ);
upc_t *dev = (upc_t *) priv;
serial_remove(upc->uart[1]);
serial_setup(upc->uart[1], SERIAL2_ADDR, SERIAL2_IRQ);
lpt1_remove();
lpt1_init(0x378);
lpt1_irq(7);
/* Set power-on defaults. */
if (dev->local == 606) {
dev->regs[0] = 0x00; /* Enable */
dev->regs[1] = 0x00; /* Configuration Register */
dev->regs[2] = 0x00; /* Ext Baud Rate Select */
dev->regs[3] = 0xb0; /* RTC Base */
dev->regs[4] = 0xfe; /* UART1 Base */
dev->regs[5] = 0xbe; /* UART2 Base */
dev->regs[6] = 0x9e; /* Parallel Base */
dev->regs[7] = 0x80; /* Game Base */
dev->regs[8] = 0xec; /* Interrupt Select */
} else if (dev->local == 710) {
dev->regs[0] = 0x0c;
dev->regs[1] = 0x00;
dev->regs[2] = 0x00;
dev->regs[3] = 0x00;
dev->regs[4] = 0xfe;
dev->regs[5] = 0x00;
dev->regs[6] = 0x9e;
dev->regs[7] = 0x00;
dev->regs[8] = 0x00;
dev->regs[9] = 0xb0;
dev->regs[10] = 0x00;
dev->regs[11] = 0x00;
dev->regs[12] = 0xa0;
dev->regs[13] = 0x00;
dev->regs[14] = 0x00;
}
fdc_reset(upc->fdc);
if (dev->local == 606)
f82c606_update_ports(dev, 1);
else if (dev->local == 710)
f82c710_update_ports(dev, 1);
}
static void *
f82c710_init(const device_t *info)
{
upc_t *upc = (upc_t *) malloc(sizeof(upc_t));
memset(upc, 0, sizeof(upc_t));
upc->fdc = device_add(&fdc_at_device);
upc->uart[0] = device_add_inst(&ns16450_device, 1);
upc->uart[1] = device_add_inst(&ns16450_device, 2);
io_sethandler(0x02fa, 0x0001, NULL, NULL, NULL, f82c710_config_write, NULL, NULL, upc);
io_sethandler(0x03fa, 0x0001, NULL, NULL, NULL, f82c710_config_write, NULL, NULL, upc);
upc->regs[0] = 0x0c;
upc->regs[1] = 0x00;
upc->regs[2] = 0x00;
upc->regs[3] = 0x00;
upc->regs[4] = 0xfe;
upc->regs[5] = 0x00;
upc->regs[6] = 0x9e;
upc->regs[7] = 0x00;
upc->regs[8] = 0x00;
upc->regs[9] = 0xb0;
upc->regs[10] = 0x00;
upc->regs[11] = 0x00;
upc->regs[12] = 0xa0;
upc->regs[13] = 0x00;
upc->regs[14] = 0x00;
f82c710_reset(upc);
f82c710_update_ports(upc);
return upc;
}
static void
f82c710_close(void *priv)
{
upc_t *upc = (upc_t *)priv;
upc_t *dev = (upc_t *) priv;
free(upc);
free(dev);
}
const device_t f82c710_device = {
"F82C710 UPC Super I/O",
0,
0,
f82c710_init, f82c710_close, NULL,
{ NULL }, NULL, NULL,
NULL
static void *
f82c710_init(const device_t *info)
{
upc_t *dev = (upc_t *) malloc(sizeof(upc_t));
memset(dev, 0, sizeof(upc_t));
dev->local = info->local;
if (dev->local == 606) {
dev->nvr = device_add(&at_nvr_old_device);
dev->gameport = gameport_add(&gameport_sio_device);
} else if (dev->local == 710)
dev->fdc = device_add(&fdc_at_device);
dev->uart[0] = device_add_inst(&ns16450_device, 1);
dev->uart[1] = device_add_inst(&ns16450_device, 2);
io_sethandler(0x02fa, 0x0001, NULL, NULL, NULL, f82c710_config_write, NULL, NULL, dev);
io_sethandler(0x03fa, 0x0001, NULL, NULL, NULL, f82c710_config_write, NULL, NULL, dev);
f82c710_reset(dev);
return dev;
}
const device_t f82c606_device = {
"82C606 CHIPSpak Multifunction Controller",
0,
606,
f82c710_init, f82c710_close, f82c710_reset,
{ NULL }, NULL, NULL,
NULL
};
const device_t f82c710_device = {
"F82C710 UPC Super I/O",
0,
710,
f82c710_init, f82c710_close, f82c710_reset,
{ NULL }, NULL, NULL,
NULL
};

190
src/thread.c Normal file
View File

@@ -0,0 +1,190 @@
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <pthread.h>
#include <inttypes.h>
#include <86box/86box.h>
#include <86box/plat.h>
typedef struct event_pthread_t
{
pthread_cond_t cond;
pthread_mutex_t mutex;
int state;
} event_pthread_t;
typedef struct thread_param
{
void (*thread_rout)(void*);
void * param;
} thread_param;
typedef struct pt_mutex_t
{
pthread_mutex_t mutex;
} pt_mutex_t;
void *
thread_run_wrapper(thread_param* arg)
{
thread_param localparam = *arg;
free(arg);
localparam.thread_rout(localparam.param);
return NULL;
}
thread_t *
thread_create(void (*thread_rout)(void *param), void *param)
{
pthread_t *thread = malloc(sizeof(pthread_t));
thread_param *thrparam = malloc(sizeof(thread_param));
thrparam->thread_rout = thread_rout;
thrparam->param = param;
pthread_create(thread, NULL, (void* (*)(void*))thread_run_wrapper, thrparam);
return thread;
}
int
thread_wait(thread_t *arg, int timeout)
{
return pthread_join(*(pthread_t*)(arg), NULL) != 0;
}
event_t *
thread_create_event()
{
event_pthread_t *event = malloc(sizeof(event_pthread_t));
pthread_cond_init(&event->cond, NULL);
pthread_mutex_init(&event->mutex, NULL);
event->state = 0;
return (event_t *)event;
}
void
thread_set_event(event_t *handle)
{
event_pthread_t *event = (event_pthread_t *)handle;
pthread_mutex_lock(&event->mutex);
event->state = 1;
pthread_cond_broadcast(&event->cond);
pthread_mutex_unlock(&event->mutex);
}
void
thread_reset_event(event_t *handle)
{
event_pthread_t *event = (event_pthread_t *)handle;
pthread_mutex_lock(&event->mutex);
event->state = 0;
pthread_mutex_unlock(&event->mutex);
}
int
thread_wait_event(event_t *handle, int timeout)
{
event_pthread_t *event = (event_pthread_t *)handle;
struct timespec abstime;
#ifdef HAS_TIMESPEC_GET
timespec_get(&abstime, TIME_UTC);
#else
clock_gettime(CLOCK_REALTIME, &abstime);
#endif
abstime.tv_nsec += (timeout % 1000) * 1000000;
abstime.tv_sec += (timeout / 1000);
if (abstime.tv_nsec > 1000000000) {
abstime.tv_nsec -= 1000000000;
abstime.tv_sec++;
}
pthread_mutex_lock(&event->mutex);
if (timeout == -1) {
while (!event->state)
pthread_cond_wait(&event->cond, &event->mutex);
} else if (!event->state)
pthread_cond_timedwait(&event->cond, &event->mutex, &abstime);
pthread_mutex_unlock(&event->mutex);
return 0;
}
void
thread_destroy_event(event_t *handle)
{
event_pthread_t *event = (event_pthread_t *)handle;
pthread_cond_destroy(&event->cond);
pthread_mutex_destroy(&event->mutex);
free(event);
}
mutex_t *
thread_create_mutex(void)
{
pt_mutex_t *mutex = malloc(sizeof(pt_mutex_t));
pthread_mutex_init(&mutex->mutex, NULL);
return mutex;
}
mutex_t *
thread_create_mutex_with_spin_count(unsigned int spin_count)
{
/* Setting spin count of a mutex is not possible with pthreads. */
return thread_create_mutex();
}
int
thread_wait_mutex(mutex_t *_mutex)
{
if (_mutex == NULL)
return(0);
pt_mutex_t *mutex = (pt_mutex_t *)_mutex;
return
pthread_mutex_lock(&mutex->mutex) != 0;
}
int
thread_release_mutex(mutex_t *_mutex)
{
if (_mutex == NULL)
return(0);
pt_mutex_t *mutex = (pt_mutex_t *)_mutex;
return pthread_mutex_unlock(&mutex->mutex) != 0;
}
void
thread_close_mutex(mutex_t *_mutex)
{
pt_mutex_t *mutex = (pt_mutex_t *)_mutex;
pthread_mutex_destroy(&mutex->mutex);
free(mutex);
}

View File

@@ -1,19 +1,17 @@
set(PLAT_SOURCES unix_thread.c)
if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
find_package(ALSA)
if (ALSA_FOUND)
set(PLAT_SOURCES ${PLAT_SOURCES} linux_midi_alsa.c)
set(PLAT_SOURCES linux_midi_alsa.c)
else()
set(PLAT_SOURCES ${PLAT_SOURCES} unix_midi.c)
set(PLAT_SOURCES unix_midi.c)
endif()
else()
set(PLAT_SOURCES ${PLAT_SOURCES} unix_midi.c)
set(PLAT_SOURCES unix_midi.c)
endif()
add_library(plat STATIC ${PLAT_SOURCES})
add_library(ui STATIC unix.c unix_sdl.c unix_cdrom.c)
target_compile_definitions(ui PUBLIC _FILE_OFFSET_BITS=64)
target_link_libraries(ui dl)
target_link_libraries(plat pthread)
if (ALSA_FOUND)
target_link_libraries(plat ALSA::ALSA)
endif()

View File

@@ -298,14 +298,17 @@ void plat_midi_input_init(void)
void plat_midi_input_close(void)
{
thread_wait_mutex(midiinmtx);
if (midiinmtx) thread_wait_mutex(midiinmtx);
if (midiin != NULL)
{
snd_rawmidi_close(midiin);
midiin = NULL;
}
thread_release_mutex(midiinmtx);
thread_close_mutex(midiinmtx);
if (midiinmtx)
{
thread_release_mutex(midiinmtx);
thread_close_mutex(midiinmtx);
}
midiinmtx = NULL;
}

View File

@@ -2,10 +2,7 @@
#define _FILE_OFFSET_BITS 64
#define _LARGEFILE64_SOURCE 1
#endif
#define _POSIX_C_SOURCE 200809L
#ifdef __APPLE__
#define _DARWIN_C_SOURCE 1
#endif
#include <SDL.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdio.h>
@@ -20,7 +17,7 @@
#include <inttypes.h>
#include <dlfcn.h>
#include <wchar.h>
#include <SDL.h>
#include <86box/86box.h>
#include <86box/keyboard.h>
#include <86box/mouse.h>
@@ -154,15 +151,20 @@ static const uint16_t sdl_to_xt[0x200] =
[SDL_SCANCODE_KP_2] = 0x50,
[SDL_SCANCODE_KP_1] = 0x4F,
[SDL_SCANCODE_KP_0] = 0x52,
[SDL_SCANCODE_KP_PERIOD] = 0x53
[SDL_SCANCODE_KP_PERIOD] = 0x53,
[SDL_SCANCODE_LGUI] = 0x15B,
[SDL_SCANCODE_RGUI] = 0x15C,
[SDL_SCANCODE_APPLICATION] = 0x15D,
[SDL_SCANCODE_PRINTSCREEN] = 0x137
};
typedef struct sdl_blit_params
{
int x, y, y1, y2, w, h;
int x, y, w, h;
} sdl_blit_params;
sdl_blit_params params = { 0, 0, 0, 0, 0, 0 };
sdl_blit_params params = { 0, 0, 0, 0 };
int blitreq = 0;
void* dynld_module(const char *name, dllimp_t *table)
@@ -605,7 +607,7 @@ void ui_sb_bugui(char *str)
}
extern void sdl_blit(int x, int y, int y1, int y2, int w, int h);
extern void sdl_blit(int x, int y, int w, int h);
typedef struct mouseinputdata
{
@@ -755,7 +757,26 @@ void monitor_thread(void* param)
xargv[cmdargc++] = local_strsep(&linecpy, " ");
if (xargv[cmdargc - 1] == NULL || cmdargc >= 512) break;
}
if (strncasecmp(xargv[0], "exit", 4) == 0)
cmdargc--;
if (strncasecmp(xargv[0], "help", 4) == 0)
{
printf(
"fddload <id> <filename> <wp> - Load floppy disk image into drive <id>.\n"
"cdload <id> <filename> - Load CD-ROM image into drive <id>.\n"
"zipload <id> <filename> <wp> - Load ZIP image into ZIP drive <id>.\n"
"cartload <id> <filename> <wp> - Load cartridge image into cartridge drive <id>.\n"
"moload <id> <filename> <wp> - Load MO image into MO drive <id>.\n\n"
"fddeject <id> - eject disk from floppy drive <id>.\n"
"cdeject <id> - eject disc from CD-ROM drive <id>.\n"
"zipeject <id> - eject ZIP image from ZIP drive <id>.\n"
"carteject <id> - eject cartridge from drive <id>.\n"
"moeject <id> - eject image from MO drive <id>.\n\n"
"hardreset - hard reset the emulated system.\n"
"pause - pause the the emulated system.\n"
"fullscreen - toggle fullscreen.\n"
"exit - exit 86Box.\n");
}
else if (strncasecmp(xargv[0], "exit", 4) == 0)
{
exit_event = 1;
}
@@ -1101,8 +1122,8 @@ int main(int argc, char** argv)
}
if (blitreq)
{
extern void sdl_blit(int x, int y, int y1, int y2, int w, int h);
sdl_blit(params.x, params.y, params.y1, params.y2, params.w, params.h);
extern void sdl_blit(int x, int y, int w, int h);
sdl_blit(params.x, params.y, params.w, params.h);
}
if (title_set)
{

View File

@@ -23,7 +23,7 @@
typedef struct sdl_blit_params
{
int x, y, y1, y2, w, h;
int x, y, w, h;
} sdl_blit_params;
extern sdl_blit_params params;
extern int blitreq;
@@ -121,26 +121,24 @@ sdl_stretch(int *w, int *h, int *x, int *y)
void
sdl_blit_shim(int x, int y, int y1, int y2, int w, int h)
sdl_blit_shim(int x, int y, int w, int h)
{
params.x = x;
params.y = y;
params.w = w;
params.h = h;
params.y1 = y1;
params.y2 = y2;
blitreq = 1;
}
void ui_window_title_real();
void
sdl_blit(int x, int y, int y1, int y2, int w, int h)
sdl_blit(int x, int y, int w, int h)
{
SDL_Rect r_src;
int ret;
if (!sdl_enabled || (y1 == y2) || (h <= 0) || (render_buffer == NULL) || (sdl_render == NULL) || (sdl_tex == NULL)) {
if (!sdl_enabled || (h <= 0) || (buffer32 == NULL) || (sdl_render == NULL) || (sdl_tex == NULL)) {
video_blit_complete();
return;
}
@@ -153,17 +151,17 @@ sdl_blit(int x, int y, int y1, int y2, int w, int h)
else sdl_resize(resize_w, resize_h);
resize_pending = 0;
}
r_src.x = 0;
r_src.y = y1;
r_src.x = x;
r_src.y = y;
r_src.w = w;
r_src.h = y2 - y1;
SDL_UpdateTexture(sdl_tex, &r_src, &(render_buffer->dat)[y1 * w], w * 4);
r_src.h = h;
SDL_UpdateTexture(sdl_tex, &r_src, &(buffer32->line[y][x]), (2048 + 64) * 4);
video_blit_complete();
SDL_RenderClear(sdl_render);
r_src.x = 0;
r_src.y = 0;
r_src.x = x;
r_src.y = y;
r_src.w = w;
r_src.h = h;
@@ -367,7 +365,7 @@ sdl_init_common(int flags)
}
sdl_mutex = SDL_CreateMutex();
sdl_win = SDL_CreateWindow("86Box", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, scrnsz_x, scrnsz_y, SDL_WINDOW_OPENGL);
sdl_win = SDL_CreateWindow("86Box", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, scrnsz_x, scrnsz_y, SDL_WINDOW_OPENGL | (vid_resize & 1 ? SDL_WINDOW_RESIZABLE : 0));
sdl_set_fs(video_fullscreen);
if (!(video_fullscreen & 1))
{

View File

@@ -1,174 +0,0 @@
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <pthread.h>
#include <sys/param.h>
#include <unistd.h>
#include <inttypes.h>
#include <86box/86box.h>
#include <86box/plat.h>
typedef struct event_pthread_t
{
pthread_cond_t cond;
pthread_mutex_t mutex;
int state;
} event_pthread_t;
typedef struct thread_param
{
void (*thread_rout)(void*);
void* param;
} thread_param;
void* thread_run_wrapper(thread_param* arg)
{
thread_param localparam = *arg;
free(arg);
localparam.thread_rout(localparam.param);
return NULL;
}
thread_t *thread_create(void (*thread_rout)(void *param), void *param)
{
pthread_t *thread = malloc(sizeof(pthread_t));
thread_param *thrparam = malloc(sizeof(thread_param));
thrparam->thread_rout = thread_rout;
thrparam->param = param;
pthread_create(thread, NULL, (void* (*)(void*))thread_run_wrapper, thrparam);
return thread;
}
int
thread_wait(thread_t *arg, int timeout)
{
return pthread_join(*(pthread_t*)(arg), NULL) != 0;
}
event_t *thread_create_event()
{
event_pthread_t *event = malloc(sizeof(event_pthread_t));
pthread_cond_init(&event->cond, NULL);
pthread_mutex_init(&event->mutex, NULL);
event->state = 0;
return (event_t *)event;
}
void thread_set_event(event_t *handle)
{
event_pthread_t *event = (event_pthread_t *)handle;
pthread_mutex_lock(&event->mutex);
event->state = 1;
pthread_cond_broadcast(&event->cond);
pthread_mutex_unlock(&event->mutex);
}
void thread_reset_event(event_t *handle)
{
event_pthread_t *event = (event_pthread_t *)handle;
pthread_mutex_lock(&event->mutex);
event->state = 0;
pthread_mutex_unlock(&event->mutex);
}
int thread_wait_event(event_t *handle, int timeout)
{
event_pthread_t *event = (event_pthread_t *)handle;
struct timespec abstime;
#if defined __linux__ || defined BSD
clock_gettime(CLOCK_REALTIME, &abstime);
#else
struct timeval now;
gettimeofday(&now, 0);
abstime.tv_sec = now.tv_sec;
abstime.tv_nsec = now.tv_usec*1000UL;
#endif
abstime.tv_nsec += (timeout % 1000) * 1000000;
abstime.tv_sec += (timeout / 1000);
if (abstime.tv_nsec > 1000000000)
{
abstime.tv_nsec -= 1000000000;
abstime.tv_sec++;
}
pthread_mutex_lock(&event->mutex);
if (timeout == -1)
{
while (!event->state)
pthread_cond_wait(&event->cond, &event->mutex);
}
else if (!event->state)
pthread_cond_timedwait(&event->cond, &event->mutex, &abstime);
pthread_mutex_unlock(&event->mutex);
return 0;
}
void thread_destroy_event(event_t *handle)
{
event_pthread_t *event = (event_pthread_t *)handle;
pthread_cond_destroy(&event->cond);
pthread_mutex_destroy(&event->mutex);
free(event);
}
void thread_sleep(int t)
{
usleep(t * 1000);
}
typedef struct pt_mutex_t
{
pthread_mutex_t mutex;
} pt_mutex_t;
mutex_t *thread_create_mutex(void)
{
pt_mutex_t *mutex = malloc(sizeof(pt_mutex_t));
pthread_mutex_init(&mutex->mutex, NULL);
return mutex;
}
mutex_t *
thread_create_mutex_with_spin_count(unsigned int spin_count)
{
/* Setting spin count of a mutex is not possible with pthreads. */
return thread_create_mutex();
}
int thread_wait_mutex(mutex_t *_mutex)
{
if (_mutex == NULL) return(0);
pt_mutex_t *mutex = (pt_mutex_t *)_mutex;
return pthread_mutex_lock(&mutex->mutex) != 0;
}
int thread_release_mutex(mutex_t *_mutex)
{
if (_mutex == NULL) return(0);
pt_mutex_t *mutex = (pt_mutex_t *)_mutex;
return pthread_mutex_unlock(&mutex->mutex) != 0;
}
void thread_close_mutex(mutex_t *_mutex)
{
pt_mutex_t *mutex = (pt_mutex_t *)_mutex;
pthread_mutex_destroy(&mutex->mutex);
free(mutex);
}

View File

@@ -22,7 +22,7 @@ add_library(vid OBJECT video.c vid_table.c vid_cga.c vid_cga_comp.c
vid_av9194.c vid_icd2061.c vid_ics2494.c vid_ics2595.c vid_cl54xx.c
vid_et4000.c vid_sc1148x_ramdac.c vid_sc1502x_ramdac.c vid_et4000w32.c
vid_stg_ramdac.c vid_ht216.c vid_oak_oti.c vid_paradise.c vid_rtg310x.c
vid_ti_cf62011.c vid_tvga.c vid_tgui9440.c vid_tkd8001_ramdac.c
vid_f82c425.c vid_ti_cf62011.c vid_tvga.c vid_tgui9440.c vid_tkd8001_ramdac.c
vid_att20c49x_ramdac.c vid_s3.c vid_s3_virge.c vid_ibm_rgb528_ramdac.c
vid_sdac_ramdac.c vid_ogc.c vid_nga.c vid_tvp3026_ramdac.c)

View File

@@ -463,17 +463,17 @@ cga_poll(void *p)
if (enable_overscan) {
if (cga->composite)
video_blit_memtoscreen(0, (cga->firstline - 4) << 1, 0, ((cga->lastline - cga->firstline) + 8) << 1,
video_blit_memtoscreen(0, (cga->firstline - 4) << 1,
xsize, ((cga->lastline - cga->firstline) + 8) << 1);
else
video_blit_memtoscreen_8(0, (cga->firstline - 4) << 1, 0, ((cga->lastline - cga->firstline) + 8) << 1,
video_blit_memtoscreen_8(0, (cga->firstline - 4) << 1,
xsize, ((cga->lastline - cga->firstline) + 8) << 1);
} else {
if (cga->composite)
video_blit_memtoscreen(8, cga->firstline << 1, 0, (cga->lastline - cga->firstline) << 1,
video_blit_memtoscreen(8, cga->firstline << 1,
xsize, (cga->lastline - cga->firstline) << 1);
else
video_blit_memtoscreen_8(8, cga->firstline << 1, 0, (cga->lastline - cga->firstline) << 1,
video_blit_memtoscreen_8(8, cga->firstline << 1,
xsize, (cga->lastline - cga->firstline) << 1);
}
}

View File

@@ -326,9 +326,9 @@ void colorplus_poll(void *p)
}
if (colorplus->cga.composite)
video_blit_memtoscreen(0, colorplus->cga.firstline - 4, 0, (colorplus->cga.lastline - colorplus->cga.firstline) + 8, xsize, (colorplus->cga.lastline - colorplus->cga.firstline) + 8);
video_blit_memtoscreen(0, colorplus->cga.firstline - 4, xsize, (colorplus->cga.lastline - colorplus->cga.firstline) + 8);
else
video_blit_memtoscreen_8(0, colorplus->cga.firstline - 4, 0, (colorplus->cga.lastline - colorplus->cga.firstline) + 8, xsize, (colorplus->cga.lastline - colorplus->cga.firstline) + 8);
video_blit_memtoscreen_8(0, colorplus->cga.firstline - 4, xsize, (colorplus->cga.lastline - colorplus->cga.firstline) + 8);
frames++;
video_res_x = xsize - 16;

View File

@@ -340,14 +340,14 @@ compaq_cga_poll(void *p)
if (enable_overscan) {
if (self->cga.composite)
video_blit_memtoscreen(0, self->cga.firstline - 8, 0, (self->cga.lastline - self->cga.firstline) + 16, xsize, (self->cga.lastline - self->cga.firstline) + 16);
video_blit_memtoscreen(0, self->cga.firstline - 8, xsize, (self->cga.lastline - self->cga.firstline) + 16);
else
video_blit_memtoscreen_8(0, self->cga.firstline - 8, 0, (self->cga.lastline - self->cga.firstline) + 16, xsize, (self->cga.lastline - self->cga.firstline) + 16);
video_blit_memtoscreen_8(0, self->cga.firstline - 8, xsize, (self->cga.lastline - self->cga.firstline) + 16);
} else {
if (self->cga.composite)
video_blit_memtoscreen(8, self->cga.firstline, 0, self->cga.lastline - self->cga.firstline, xsize, self->cga.lastline - self->cga.firstline);
video_blit_memtoscreen(8, self->cga.firstline, xsize, self->cga.lastline - self->cga.firstline);
else
video_blit_memtoscreen_8(8, self->cga.firstline, 0, self->cga.lastline - self->cga.firstline, xsize, self->cga.lastline - self->cga.firstline);
video_blit_memtoscreen_8(8, self->cga.firstline, xsize, self->cga.lastline - self->cga.firstline);
}
}

View File

@@ -35,7 +35,7 @@
#include <86box/vid_ega.h>
void ega_doblit(int y1, int y2, int wx, int wy, ega_t *ega);
void ega_doblit(int wx, int wy, ega_t *ega);
#define BIOS_IBM_PATH "roms/video/ega/ibm_6277356_ega_card_u44_27128.bin"
@@ -597,10 +597,10 @@ ega_poll(void *p)
if (ega->vres) {
wy = (ega->lastline - ega->firstline) << 1;
ega_doblit(ega->firstline_draw << 1, (ega->lastline_draw + 1) << 1, wx, wy, ega);
ega_doblit(wx, wy, ega);
} else {
wy = ega->lastline - ega->firstline;
ega_doblit(ega->firstline_draw, ega->lastline_draw + 1, wx, wy, ega);
ega_doblit(wx, wy, ega);
}
frames++;
@@ -658,7 +658,7 @@ ega_poll(void *p)
void
ega_doblit(int y1, int y2, int wx, int wy, ega_t *ega)
ega_doblit(int wx, int wy, ega_t *ega)
{
int y_add = (enable_overscan) ? overscan_y : 0;
int x_add = (enable_overscan) ? overscan_x : 0;
@@ -675,15 +675,8 @@ ega_doblit(int y1, int y2, int wx, int wy, ega_t *ega)
bottom <<= 1;
}
if ((wx <= 0) || (wy <= 0)) {
video_blit_memtoscreen(x_start, y_start, 0, 0, 0, 0);
if ((wx <= 0) || (wy <= 0))
return;
}
if (y1 > y2) {
video_blit_memtoscreen(x_start, y_start, 0, 0, xsize + x_add, ysize + y_add);
return;
}
if (ega->vres)
ega->y_add <<= 1;
@@ -734,7 +727,7 @@ ega_doblit(int y1, int y2, int wx, int wy, ega_t *ega)
}
}
video_blit_memtoscreen(x_start, y_start, y1, y2 + y_add, xsize + x_add, ysize + y_add);
video_blit_memtoscreen(x_start, y_start, xsize + x_add, ysize + y_add);
if (ega->vres)
ega->y_add >>= 1;

672
src/video/vid_f82c425.c Normal file
View File

@@ -0,0 +1,672 @@
/*
* 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.
*
* Chips & Technologies 82C425 display controller emulation,
* with support for 640x200 LCD and SMARTMAP text contrast
* enhancement.
*
* Relevant literature:
*
* [1] Chips and Technologies, Inc., 82C425 CGA LCD/CRT Controller,
* Data Sheet, Revision No. 2.2, September 1991.
* <https://archive.org/download/82C425/82C425.pdf>
*
* [2] Pleva et al., COLOR TO MONOCHROME CONVERSION,
* U.S. Patent 4,977,398, Dec. 11, 1990.
* <https://pimg-fpiw.uspto.gov/fdd/98/773/049/0.pdf>
*
* Based on Toshiba T1000 plasma display emulation code.
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
* Sarah Walker, <tommowalker@tommowalker.co.uk>
* Lubomir Rintel, <lkundrak@v3.sk>
*
* Copyright 2018,2019 Fred N. van Kempen.
* Copyright 2018,2019 Miran Grca.
* Copyright 2018,2019 Sarah Walker.
* Copyright 2021 Lubomir Rintel.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the:
*
* Free Software Foundation, Inc.
* 59 Temple Place - Suite 330
* Boston, MA 02111-1307
* USA.
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/io.h>
#include <86box/mem.h>
#include <86box/timer.h>
#include "cpu.h"
#include <86box/video.h>
#include <86box/vid_cga.h>
#define F82C425_XSIZE 640
#define F82C425_YSIZE 200
/* Mapping of attributes to colours */
static uint32_t smartmap[256][2];
static uint32_t colormap[4];
static video_timings_t timing_f82c425 = {VIDEO_ISA, 8,16,32, 8,16,32};
static uint8_t st_video_options;
static uint8_t st_enabled = 1;
static int8_t st_display_internal = -1;
void f82c425_video_options_set(uint8_t options)
{
st_video_options = options;
}
void f82c425_video_enable(uint8_t enabled)
{
st_enabled = enabled;
}
void f82c425_display_set(uint8_t internal)
{
st_display_internal = (int8_t)internal;
}
uint8_t f82c425_display_get()
{
return (uint8_t)st_display_internal;
}
typedef struct f82c425_t
{
mem_mapping_t mapping;
cga_t cga;
uint8_t crtcreg;
uint64_t dispontime, dispofftime;
int linepos, displine;
int dispon;
uint8_t video_options;
uint8_t *vram;
/* Registers specific to 82C425. */
uint8_t ac_limit;
uint8_t threshold;
uint8_t shift;
uint8_t hsync;
uint8_t vsync_blink;
uint8_t timing;
uint8_t function;
} f82c425_t;
/* Convert IRGB representation to RGBI,
* useful in SMARTMAP calculations. */
static inline uint8_t f82c425_rgbi(uint8_t irgb)
{
return ((irgb & 0x7) << 1) | (irgb >> 3);
}
/* Convert IRGB SMARTMAP output to a RGB representation of one of 4/8 grey
* shades we'd see on an actual V86P display: with some bias toward lighter
* shades and a backlight with yellow/green-ish tint. */
static inline uint32_t f82c425_makecol(uint8_t rgbi, int gs4, int inv)
{
uint8_t c;
gs4 = 1 + !!gs4;
if (!inv)
{
rgbi = 15 - rgbi;
}
c = 0x10 * gs4 * ((rgbi >> gs4) + 2);
#ifdef NO_BLUE
return makecol(c, c + 0x08, c - 0x20);
#else
return makecol(c, c + 0x08, 0x70);
#endif
}
/* Saturating/non-saturating addition for SMARTMAP(see below). */
static inline int f82c425_smartmap_add(int a, int b, int sat)
{
int c = a + b;
/* (SATURATING OR NON SATURATING) */
if (sat)
{
if (c < 0)
c = 0;
else if (c > 15)
c = 15;
}
return c & 0xf;
}
/* Calculate and cache mapping of CGA text color attribute to a
* shade of gray enhanced via the SMARTMAP algorithm.
*
* This is a straightforward implementation of the algorithm as described
* in U.S. Patent 4,977,398 [2]. The comments in capitals refer to portions
* of a figure on page 4. */
static void f82c425_smartmap(f82c425_t *f82c425)
{
int i;
for (i = 0; i < 256; i++) {
uint8_t bg = f82c425_rgbi(i >> 4);
uint8_t fg = f82c425_rgbi(i & 0xf);
/* FIG._4. */
if (abs(bg - fg) <= (f82c425->threshold & 0x0f))
{
/* FOREGROUND=BACKGROUND */
if (bg == fg)
{
/* SPECIAL CASE */
if (f82c425->shift == 0xff)
{
/* CHECK MOST SIGNIFICANT BIT */
if (fg & 0x8)
{
/* FULL WHITE */
fg = bg = 15;
}
else
{
/* FULL BLACK */
fg = bg = 0;
}
}
}
else
{
uint8_t sat = f82c425->threshold & 0x10;
/* DETERMINE WHICH IS LIGHT */
if (fg > bg)
{
fg = f82c425_smartmap_add(fg, f82c425->shift & 0x0f, sat);
bg = f82c425_smartmap_add(bg, -(f82c425->shift >> 4), sat);
}
else
{
fg = f82c425_smartmap_add(fg, -(f82c425->shift & 0x0f), sat);
bg = f82c425_smartmap_add(bg, f82c425->shift >> 4, sat);
}
}
}
smartmap[i][0] = f82c425_makecol(bg, f82c425->threshold & 0x20, f82c425->function & 0x80);
smartmap[i][1] = f82c425_makecol(fg, f82c425->threshold & 0x20, f82c425->function & 0x80);
}
}
/* Calculate mapping of 320x200 graphical mode colors. */
static void f82c425_colormap(f82c425_t *f82c425)
{
int i;
for (i = 0; i < 4; i++)
colormap[i] = f82c425_makecol(5 * i, 0, f82c425->function & 0x80);
}
static void f82c425_out(uint16_t addr, uint8_t val, void *p)
{
f82c425_t *f82c425 = (f82c425_t *)p;
if (addr == 0x3d4)
f82c425->crtcreg = val;
if (((f82c425->function & 0x01) == 0) && ((f82c425->crtcreg != 0xdf) || (addr != 0x3d5)))
return;
if (addr != 0x3d5 || f82c425->crtcreg <= 31)
{
cga_out(addr, val, &f82c425->cga);
return;
}
switch (f82c425->crtcreg)
{
case 0xd9:
f82c425->ac_limit = val;
break;
case 0xda:
f82c425->threshold = val;
f82c425_smartmap(f82c425);
break;
case 0xdb:
f82c425->shift = val;
f82c425_smartmap(f82c425);
break;
case 0xdc:
f82c425->hsync = val;
break;
case 0xdd:
f82c425->vsync_blink = val;
break;
case 0xde:
f82c425->timing = val;
break;
case 0xdf:
f82c425->function = val;
f82c425_smartmap(f82c425);
f82c425_colormap(f82c425);
break;
}
}
static uint8_t f82c425_in(uint16_t addr, void *p)
{
f82c425_t *f82c425 = (f82c425_t *)p;
if ((f82c425->function & 0x01) == 0)
return 0xff;
if (addr == 0x3d4)
return f82c425->crtcreg;
if (addr != 0x3d5 || f82c425->crtcreg <= 31)
return cga_in(addr, &f82c425->cga);
switch (f82c425->crtcreg)
{
case 0xd9:
return f82c425->ac_limit;
case 0xda:
return f82c425->threshold;
case 0xdb:
return f82c425->shift;
case 0xdc:
return f82c425->hsync;
case 0xdd:
return f82c425->vsync_blink;
case 0xde:
return f82c425->timing;
case 0xdf:
return f82c425->function;
}
return 0xff;
}
static void f82c425_write(uint32_t addr, uint8_t val, void *p)
{
f82c425_t *f82c425 = (f82c425_t *)p;
f82c425->vram[addr & 0x3fff] = val;
cycles -= 4;
}
static uint8_t f82c425_read(uint32_t addr, void *p)
{
f82c425_t *f82c425 = (f82c425_t *)p;
cycles -= 4;
return f82c425->vram[addr & 0x3fff];
}
static void f82c425_recalctimings(f82c425_t *f82c425)
{
double disptime;
double _dispontime, _dispofftime;
if (f82c425->function & 0x08)
{
cga_recalctimings(&f82c425->cga);
return;
}
disptime = 651;
_dispontime = 640;
_dispofftime = disptime - _dispontime;
f82c425->dispontime = (uint64_t)(_dispontime * xt_cpu_multi);
f82c425->dispofftime = (uint64_t)(_dispofftime * xt_cpu_multi);
}
/* Draw a row of text. */
static void f82c425_text_row(f82c425_t *f82c425)
{
uint32_t colors[2];
int x, c;
uint8_t chr, attr;
int drawcursor;
int cursorline;
int blink;
uint16_t addr;
uint8_t sc;
uint16_t ma = (f82c425->cga.crtc[0x0d] | (f82c425->cga.crtc[0x0c] << 8)) & 0x3fff;
uint16_t ca = (f82c425->cga.crtc[0x0f] | (f82c425->cga.crtc[0x0e] << 8)) & 0x3fff;
uint8_t sl = f82c425->cga.crtc[9] + 1;
int columns = f82c425->cga.crtc[1];
sc = (f82c425->displine) & 7;
addr = ((ma & ~1) + (f82c425->displine >> 3) * columns) * 2;
ma += (f82c425->displine >> 3) * columns;
if ((f82c425->cga.crtc[0x0a] & 0x60) == 0x20)
{
cursorline = 0;
}
else
{
cursorline = ((f82c425->cga.crtc[0x0a] & 0x0F) <= sc) &&
((f82c425->cga.crtc[0x0b] & 0x0F) >= sc);
}
for (x = 0; x < columns; x++)
{
chr = f82c425->vram[(addr + 2 * x) & 0x3FFF];
attr = f82c425->vram[(addr + 2 * x + 1) & 0x3FFF];
drawcursor = ((ma == ca) && cursorline &&
(f82c425->cga.cgamode & 0x8) && (f82c425->cga.cgablink & 0x10));
blink = ((f82c425->cga.cgablink & 0x10) && (f82c425->cga.cgamode & 0x20) &&
(attr & 0x80) && !drawcursor);
if (drawcursor)
{
colors[0] = smartmap[~attr & 0xff][0];
colors[1] = smartmap[~attr & 0xff][1];
}
else
{
colors[0] = smartmap[attr][0];
colors[1] = smartmap[attr][1];
}
if (blink)
colors[1] = colors[0];
if (f82c425->cga.cgamode & 0x01)
{
/* High resolution (80 cols) */
for (c = 0; c < sl; c++)
{
((uint32_t *)buffer32->line[f82c425->displine])[(x << 3) + c] =
colors[(fontdat[chr][sc] & (1 <<(c ^ 7))) ? 1 : 0];
}
}
else
{
/* Low resolution (40 columns, stretch pixels horizontally) */
for (c = 0; c < sl; c++)
{
((uint32_t *)buffer32->line[f82c425->displine])[(x << 4) + c*2] =
((uint32_t *)buffer32->line[f82c425->displine])[(x << 4) + c*2+1] =
colors[(fontdat[chr][sc] & (1 <<(c ^ 7))) ? 1 : 0];
}
}
++ma;
}
}
/* Draw a line in CGA 640x200 mode */
static void f82c425_cgaline6(f82c425_t *f82c425)
{
int x, c;
uint8_t dat;
uint16_t addr;
uint16_t ma = (f82c425->cga.crtc[0x0d] | (f82c425->cga.crtc[0x0c] << 8)) & 0x3fff;
addr = ((f82c425->displine) & 1) * 0x2000 +
(f82c425->displine >> 1) * 80 +
((ma & ~1) << 1);
for (x = 0; x < 80; x++)
{
dat = f82c425->vram[addr & 0x3FFF];
addr++;
for (c = 0; c < 8; c++)
{
((uint32_t *)buffer32->line[f82c425->displine])[x*8+c] =
colormap[dat & 0x80 ? 3 : 0];
dat = dat << 1;
}
}
}
/* Draw a line in CGA 320x200 mode. */
static void f82c425_cgaline4(f82c425_t *f82c425)
{
int x, c;
uint8_t dat, pattern;
uint16_t addr;
uint16_t ma = (f82c425->cga.crtc[0x0d] | (f82c425->cga.crtc[0x0c] << 8)) & 0x3fff;
addr = ((f82c425->displine) & 1) * 0x2000 +
(f82c425->displine >> 1) * 80 +
((ma & ~1) << 1);
for (x = 0; x < 80; x++)
{
dat = f82c425->vram[addr & 0x3FFF];
addr++;
for (c = 0; c < 4; c++)
{
pattern = (dat & 0xC0) >> 6;
if (!(f82c425->cga.cgamode & 0x08)) pattern = 0;
((uint32_t *)buffer32->line[f82c425->displine])[x*8+2*c] =
((uint32_t *)buffer32->line[f82c425->displine])[x*8+2*c+1] =
colormap[pattern & 3];
dat = dat << 2;
}
}
}
static void f82c425_poll(void *p)
{
f82c425_t *f82c425 = (f82c425_t *)p;
if (f82c425->video_options != st_video_options ||
!!(f82c425->function & 1) != st_enabled)
{
f82c425->video_options = st_video_options;
f82c425->function &= ~1;
f82c425->function |= st_enabled ? 1 : 0;
if (f82c425->function & 0x01)
mem_mapping_enable(&f82c425->mapping);
else
mem_mapping_disable(&f82c425->mapping);
}
/* Switch between internal LCD and external CRT display. */
if (st_display_internal != -1 && st_display_internal != !!(f82c425->function & 0x08))
{
if (st_display_internal)
{
f82c425->function &= ~0x08;
f82c425->timing &= ~0x20;
}
else
{
f82c425->function |= 0x08;
f82c425->timing |= 0x20;
}
f82c425_recalctimings(f82c425);
}
if (f82c425->function & 0x08)
{
cga_poll(&f82c425->cga);
return;
}
if (!f82c425->linepos)
{
timer_advance_u64(&f82c425->cga.timer, f82c425->dispofftime);
f82c425->cga.cgastat |= 1;
f82c425->linepos = 1;
if (f82c425->dispon)
{
if (f82c425->displine == 0)
{
video_wait_for_buffer();
}
switch (f82c425->cga.cgamode & 0x13)
{
case 0x12:
f82c425_cgaline6(f82c425);
break;
case 0x02:
f82c425_cgaline4(f82c425);
break;
case 0x00:
case 0x01:
f82c425_text_row(f82c425);
break;
}
}
f82c425->displine++;
/* Hardcode a fixed refresh rate and VSYNC timing */
if (f82c425->displine >= 216)
{
/* End of VSYNC */
f82c425->displine = 0;
f82c425->cga.cgastat &= ~8;
f82c425->dispon = 1;
}
else
if (f82c425->displine == (f82c425->cga.crtc[9] + 1) * f82c425->cga.crtc[6])
{
/* Start of VSYNC */
f82c425->cga.cgastat |= 8;
f82c425->dispon = 0;
}
}
else
{
if (f82c425->dispon)
f82c425->cga.cgastat &= ~1;
timer_advance_u64(&f82c425->cga.timer, f82c425->dispontime);
f82c425->linepos = 0;
if (f82c425->displine == 200)
{
/* Hardcode 640x200 window size */
if ((F82C425_XSIZE != xsize) || (F82C425_YSIZE != ysize) || video_force_resize_get())
{
xsize = F82C425_XSIZE;
ysize = F82C425_YSIZE;
set_screen_size(xsize, ysize);
if (video_force_resize_get())
video_force_resize_set(0);
}
video_blit_memtoscreen(0, 0, xsize, ysize);
frames++;
/* Fixed 640x200 resolution */
video_res_x = F82C425_XSIZE;
video_res_y = F82C425_YSIZE;
switch (f82c425->cga.cgamode & 0x12)
{
case 0x12:
video_bpp = 1;
break;
case 0x02:
video_bpp = 2;
break;
default:
video_bpp = 0;
}
f82c425->cga.cgablink++;
}
}
}
static void *f82c425_init(const device_t *info)
{
f82c425_t *f82c425 = malloc(sizeof(f82c425_t));
memset(f82c425, 0, sizeof(f82c425_t));
cga_init(&f82c425->cga);
video_inform(VIDEO_FLAG_TYPE_CGA, &timing_f82c425);
/* Initialize registers that don't default to zero. */
f82c425->hsync = 0x40;
f82c425->vsync_blink = 0x72;
/* 16k video RAM */
f82c425->vram = malloc(0x4000);
timer_set_callback(&f82c425->cga.timer, f82c425_poll);
timer_set_p(&f82c425->cga.timer, f82c425);
/* Occupy memory between 0xB8000 and 0xBFFFF */
mem_mapping_add(&f82c425->mapping, 0xb8000, 0x8000, f82c425_read, NULL, NULL, f82c425_write, NULL, NULL, NULL, 0, f82c425);
/* Respond to CGA I/O ports */
io_sethandler(0x03d0, 0x000c, f82c425_in, NULL, NULL, f82c425_out, NULL, NULL, f82c425);
/* Initialize color maps for text & graphic modes */
f82c425_smartmap(f82c425);
f82c425_colormap(f82c425);
/* Start off in 80x25 text mode */
f82c425->cga.cgastat = 0xF4;
f82c425->cga.vram = f82c425->vram;
f82c425->video_options = 0x01;
return f82c425;
}
static void f82c425_close(void *p)
{
f82c425_t *f82c425 = (f82c425_t *)p;
free(f82c425->vram);
free(f82c425);
}
static void f82c425_speed_changed(void *p)
{
f82c425_t *f82c425 = (f82c425_t *)p;
f82c425_recalctimings(f82c425);
}
const device_t f82c425_video_device = {
"82C425 CGA LCD/CRT Controller",
0, 0,
f82c425_init, f82c425_close, NULL,
{ NULL },
f82c425_speed_changed,
NULL,
NULL
};

View File

@@ -689,7 +689,7 @@ genius_poll(void *p)
video_force_resize_set(0);
}
video_blit_memtoscreen_8(0, 0, 0, ysize, xsize, ysize);
video_blit_memtoscreen_8(0, 0, xsize, ysize);
frames++;
/* Fixed 728x1008 resolution */

View File

@@ -279,11 +279,17 @@ static void
hercules_render_overscan_left(hercules_t *dev)
{
int i;
uint32_t width;
if (dev->ctrl & 0x02)
width = (((uint32_t) dev->crtc[1]) << 4);
else
width = (((uint32_t) dev->crtc[1]) * 9);
if ((dev->displine + 14) < 0)
return;
if ((((uint32_t) dev->crtc[1]) * 9) == 0)
if (width == 0)
return;
for (i = 0; i < 8; i++)
@@ -295,15 +301,21 @@ static void
hercules_render_overscan_right(hercules_t *dev)
{
int i;
uint32_t width;
if (dev->ctrl & 0x02)
width = (((uint32_t) dev->crtc[1]) << 4);
else
width = (((uint32_t) dev->crtc[1]) * 9);
if ((dev->displine + 14) < 0)
return;
if ((((uint32_t) dev->crtc[1]) * 9) == 0)
if (width == 0)
return;
for (i = 0; i < 8; i++)
buffer32->line[dev->displine + 14][8 + (((uint32_t) dev->crtc[1]) * 9) + i] = 0x00000000;
buffer32->line[dev->displine + 14][8 + width + i] = 0x00000000;
}
@@ -505,9 +517,9 @@ hercules_poll(void *priv)
}
if (enable_overscan)
video_blit_memtoscreen_8(0, dev->firstline, 0, ysize + 28, xsize + 16, ysize + 28);
video_blit_memtoscreen_8(0, dev->firstline, xsize + 16, ysize + 28);
else
video_blit_memtoscreen_8(8, dev->firstline + 14, 0, ysize + 14, xsize, ysize);
video_blit_memtoscreen_8(8, dev->firstline + 14, xsize, ysize);
frames++;
// if ((dev->ctrl & 2) && (dev->ctrl2 & 1)) {
if (dev->ctrl & 0x02) {

View File

@@ -581,7 +581,7 @@ herculesplus_poll(void *priv)
if (video_force_resize_get())
video_force_resize_set(0);
}
video_blit_memtoscreen_8(0, dev->firstline, 0, dev->lastline - dev->firstline, xsize, dev->lastline - dev->firstline);
video_blit_memtoscreen_8(0, dev->firstline, xsize, dev->lastline - dev->firstline);
frames++;
if ((dev->ctrl & HERCULESPLUS_CTRL_GRAPH) && (dev->ctrl2 & HERCULESPLUS_CTRL2_GRAPH)) {
video_res_x = dev->crtc[1] * 16;

View File

@@ -649,7 +649,9 @@ ht216_recalctimings(svga_t *svga)
svga->hdisp *= (svga->seqregs[1] & 8) ? 16 : 8;
svga->rowoffset <<= 1;
if ((svga->crtc[0x17] & 0x60) == 0x20) /*Would result in a garbled screen with trailing cursor glitches*/
svga->crtc[0x17] |= 0x40;
svga->force_byte_mode = 1;
else
svga->force_byte_mode = 0;
}
svga->render = svga_render_8bpp_highres;
}

View File

@@ -998,7 +998,7 @@ incolor_poll(void *priv)
if (video_force_resize_get())
video_force_resize_set(0);
}
video_blit_memtoscreen(0, dev->firstline, 0, dev->lastline - dev->firstline, xsize, dev->lastline - dev->firstline);
video_blit_memtoscreen(0, dev->firstline, xsize, dev->lastline - dev->firstline);
frames++;
if ((dev->ctrl & INCOLOR_CTRL_GRAPH) && (dev->ctrl2 & INCOLOR_CTRL2_GRAPH)) {
video_res_x = dev->crtc[1] * 16;

View File

@@ -230,7 +230,7 @@ void mda_poll(void *p)
if (video_force_resize_get())
video_force_resize_set(0);
}
video_blit_memtoscreen_8(0, mda->firstline, 0, ysize, xsize, ysize);
video_blit_memtoscreen_8(0, mda->firstline, xsize, ysize);
frames++;
video_res_x = mda->crtc[1];
video_res_y = mda->crtc[6];

View File

@@ -474,17 +474,17 @@ nga_poll(void *priv)
/* nga specific */
if (enable_overscan) {
if (nga->cga.composite)
video_blit_memtoscreen(0, (nga->cga.firstline - 8), 0, (nga->cga.lastline - nga->cga.firstline) + 16,
video_blit_memtoscreen(0, (nga->cga.firstline - 8),
xsize, (nga->cga.lastline - nga->cga.firstline) + 16);
else
video_blit_memtoscreen_8(0, (nga->cga.firstline - 8), 0, (nga->cga.lastline - nga->cga.firstline) + 16,
video_blit_memtoscreen_8(0, (nga->cga.firstline - 8),
xsize, (nga->cga.lastline - nga->cga.firstline) + 16);
} else {
if (nga->cga.composite)
video_blit_memtoscreen(8, nga->cga.firstline, 0, (nga->cga.lastline - nga->cga.firstline),
video_blit_memtoscreen(8, nga->cga.firstline,
xsize, (nga->cga.lastline - nga->cga.firstline));
else
video_blit_memtoscreen_8(8, nga->cga.firstline, 0, (nga->cga.lastline - nga->cga.firstline),
video_blit_memtoscreen_8(8, nga->cga.firstline,
xsize, (nga->cga.lastline - nga->cga.firstline));
}
}

View File

@@ -489,17 +489,17 @@ ogc_poll(void *priv)
/* ogc specific */
if (enable_overscan) {
if (ogc->cga.composite)
video_blit_memtoscreen(0, (ogc->cga.firstline - 8), 0, (ogc->cga.lastline - ogc->cga.firstline) + 16,
video_blit_memtoscreen(0, (ogc->cga.firstline - 8),
xsize, (ogc->cga.lastline - ogc->cga.firstline) + 16);
else
video_blit_memtoscreen_8(0, (ogc->cga.firstline - 8), 0, (ogc->cga.lastline - ogc->cga.firstline) + 16,
video_blit_memtoscreen_8(0, (ogc->cga.firstline - 8),
xsize, (ogc->cga.lastline - ogc->cga.firstline) + 16);
} else {
if (ogc->cga.composite)
video_blit_memtoscreen(8, ogc->cga.firstline, 0, (ogc->cga.lastline - ogc->cga.firstline),
video_blit_memtoscreen(8, ogc->cga.firstline,
xsize, (ogc->cga.lastline - ogc->cga.firstline));
else
video_blit_memtoscreen_8(8, ogc->cga.firstline, 0, (ogc->cga.lastline - ogc->cga.firstline),
video_blit_memtoscreen_8(8, ogc->cga.firstline,
xsize, (ogc->cga.lastline - ogc->cga.firstline));
}
}

View File

@@ -2493,7 +2493,7 @@ pgc_cga_poll(pgc_t *dev)
if (video_force_resize_get())
video_force_resize_set(0);
}
video_blit_memtoscreen_8(0, 0, 0, ysize, xsize, ysize);
video_blit_memtoscreen_8(0, 0, xsize, ysize);
frames++;
/* We have a fixed 640x400 screen for CGA modes. */
@@ -2578,7 +2578,7 @@ pgc_poll(void *priv)
if (video_force_resize_get())
video_force_resize_set(0);
}
video_blit_memtoscreen(0, 0, 0, ysize, xsize, ysize);
video_blit_memtoscreen(0, 0, xsize, ysize);
frames++;
video_res_x = dev->screenw;

File diff suppressed because it is too large Load Diff

View File

@@ -758,7 +758,7 @@ sigma_poll(void *p)
video_force_resize_set(0);
}
video_blit_memtoscreen_8(0, sigma->firstline - 4, 0, (sigma->lastline - sigma->firstline) + 8, xsize, (sigma->lastline - sigma->firstline) + 8);
video_blit_memtoscreen_8(0, sigma->firstline - 4, xsize, (sigma->lastline - sigma->firstline) + 8);
frames++;
video_res_x = xsize - 16;

View File

@@ -41,7 +41,7 @@
#include <86box/vid_svga_render.h>
void svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga);
void svga_doblit(int wx, int wy, svga_t *svga);
extern int cyc_total;
extern uint8_t edatlookup[4][4];
@@ -823,10 +823,10 @@ svga_poll(void *p)
if (!svga->override) {
if (svga->vertical_linedbl) {
wy = (svga->lastline - svga->firstline) << 1;
svga_doblit(svga->firstline_draw << 1, (svga->lastline_draw + 1) << 1, wx, wy, svga);
svga_doblit(wx, wy, svga);
} else {
wy = svga->lastline - svga->firstline;
svga_doblit(svga->firstline_draw, svga->lastline_draw + 1, wx, wy, svga);
svga_doblit(wx, wy, svga);
}
}
@@ -1342,7 +1342,7 @@ svga_read_linear(uint32_t addr, void *p)
void
svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga)
svga_doblit(int wx, int wy, svga_t *svga)
{
int y_add, x_add, y_start, x_start, bottom;
uint32_t *p;
@@ -1361,15 +1361,8 @@ svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga)
bottom <<= 1;
}
if ((wx <= 0) || (wy <= 0)) {
video_blit_memtoscreen(x_start, y_start, 0, 0, 0, 0);
if ((wx <= 0) || (wy <= 0))
return;
}
if (y1 > y2) {
video_blit_memtoscreen(x_start, y_start, 0, 0, xsize + x_add, ysize + y_add);
return;
}
if (svga->vertical_linedbl)
svga->y_add <<= 1;
@@ -1423,7 +1416,7 @@ svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga)
}
}
video_blit_memtoscreen(x_start, y_start, y1, y2 + y_add, xsize + x_add, ysize + y_add);
video_blit_memtoscreen(x_start, y_start, xsize + x_add, ysize + y_add);
if (svga->vertical_linedbl)
svga->vertical_linedbl >>= 1;

View File

@@ -145,7 +145,8 @@ video_cards[] = {
{ "n9_9fx_pci", &s3_9fx_pci_device },
{ "px_trio64_pci", &s3_phoenix_trio64_pci_device },
{ "elsawin2kprox_pci", &s3_elsa_winner2000_pro_x_pci_device },
{ "mirovideo40sv_pci", &s3_mirovideo_40sv_968_pci_device },
{ "mirovideo40sv_pci", &s3_mirovideo_40sv_ergo_968_pci_device },
{ "px_vision968_pci", &s3_phoenix_vision968_pci_device },
{ "spea_mercury64p_pci", &s3_spea_mercury_p64v_pci_device },
{ "px_vision868_pci", &s3_phoenix_vision868_pci_device },
{ "px_trio64vplus_pci", &s3_phoenix_trio64vplus_pci_device },
@@ -184,11 +185,13 @@ video_cards[] = {
{ "stealth3d_2000_vlb", &s3_virge_vlb_device },
{ "stealth3d_3000_vlb", &s3_virge_988_vlb_device },
{ "metheus928_vlb", &s3_metheus_86c928_vlb_device },
{ "mirocrystal8s_vlb", &s3_mirocrystal_8s_805_vlb_device },
{ "mirocrystal10sd_vlb", &s3_mirocrystal_10sd_805_vlb_device },
{ "px_86c805_vlb", &s3_phoenix_86c805_vlb_device },
{ "px_s3_v7_805_vlb", &s3_spea_mirage_86c805_vlb_device },
{ "stealth64v_vlb", &s3_diamond_stealth64_964_vlb_device },
{ "mirocrystal20sv_vlb", &s3_mirocrystal_20sv_964_vlb_device },
{ "mirocrystal20sd_vlb", &s3_mirocrystal_20sd_864_vlb_device },
{ "bahamas64_vlb", &s3_bahamas64_vlb_device },
{ "px_vision864_vlb", &s3_phoenix_vision864_vlb_device },
{ "stealthse_vlb", &s3_diamond_stealth_se_vlb_device },
@@ -197,6 +200,7 @@ video_cards[] = {
{ "n9_9fx_vlb", &s3_9fx_vlb_device },
{ "px_trio64_vlb", &s3_phoenix_trio64_vlb_device },
{ "spea_miragep64_vlb", &s3_spea_mirage_p64_vlb_device },
{ "px_vision968_vlb", &s3_phoenix_vision968_vlb_device },
{ "px_vision868_vlb", &s3_phoenix_vision868_vlb_device },
{ "ht216_32", &ht216_32_standalone_device },
{ "virge325_vlb", &s3_virge_325_vlb_device },

View File

@@ -2407,7 +2407,7 @@ static uint8_t banshee_pci_read(int func, int addr, void *p)
case 0x00: ret = 0x1a; break; /*3DFX*/
case 0x01: ret = 0x12; break;
case 0x02: ret = (banshee->type == TYPE_BANSHEE) ? 0x03 : ((banshee->type == TYPE_VELOCITY100) ? 0x04 : 0x05); break;
case 0x02: ret = (banshee->type == TYPE_BANSHEE) ? 0x03 : 0x05; break;
case 0x03: ret = 0x00; break;
case 0x04: ret = banshee->pci_regs[0x04] & 0x27; break;
@@ -2858,7 +2858,14 @@ static void *banshee_init_common(const device_t *info, char *fn, int has_sgram,
banshee->pci_regs[0x2e] = 0x3a;
banshee->pci_regs[0x2f] = 0x00;
break;
}
case TYPE_VELOCITY100:
banshee->pci_regs[0x2c] = 0x1a;
banshee->pci_regs[0x2d] = 0x12;
banshee->pci_regs[0x2e] = 0x4b;
banshee->pci_regs[0x2f] = 0x00;
break;
}
video_inform(VIDEO_FLAG_TYPE_SPECIAL, banshee->agp ? &timing_banshee_agp : &timing_banshee);

View File

@@ -655,7 +655,7 @@ skip_draw:
thread_release_mutex(voodoo->force_blit_mutex);
if (voodoo->dirty_line_high > voodoo->dirty_line_low || force_blit)
svga_doblit(0, voodoo->v_disp, voodoo->h_disp, voodoo->v_disp-1, voodoo->svga);
svga_doblit(voodoo->h_disp, voodoo->v_disp-1, voodoo->svga);
if (voodoo->clutData_dirty)
{
voodoo->clutData_dirty = 0;

View File

@@ -870,7 +870,7 @@ void wy700_poll(void *p)
if (video_force_resize_get())
video_force_resize_set(0);
}
video_blit_memtoscreen_8(0, 0, 0, ysize, xsize, ysize);
video_blit_memtoscreen_8(0, 0, xsize, ysize);
frames++;
/* Fixed 1280x800 resolution */

View File

@@ -74,7 +74,6 @@
volatile int screenshots = 0;
bitmap_t *buffer32 = NULL;
bitmap_t *render_buffer = NULL;
uint8_t fontdat[2048][8]; /* IBM CGA font */
uint8_t fontdatm[2048][16]; /* IBM MDA font */
uint8_t fontdatw[512][32]; /* Wyse700 font */
@@ -245,7 +244,7 @@ const uint32_t shade[5][256] =
static struct {
int x, y, y1, y2, w, h;
int x, y, w, h;
int busy;
int buffer_in_use;
@@ -256,7 +255,7 @@ static struct {
} blit_data;
static void (*blit_func)(int x, int y, int y1, int y2, int w, int h);
static void (*blit_func)(int x, int y, int w, int h);
#ifdef ENABLE_VIDEO_LOG
@@ -280,7 +279,7 @@ video_log(const char *fmt, ...)
void
video_setblit(void(*blit)(int,int,int,int,int,int))
video_setblit(void(*blit)(int,int,int,int))
{
blit_func = blit;
}
@@ -318,7 +317,7 @@ static png_infop info_ptr;
static void
video_take_screenshot(const char *fn, int startx, int starty, int y1, int y2, int w, int h)
video_take_screenshot(const char *fn)
{
int i, x, y;
png_bytep *b_rgb = NULL;
@@ -350,25 +349,28 @@ video_take_screenshot(const char *fn, int startx, int starty, int y1, int y2, in
png_init_io(png_ptr, fp);
png_set_IHDR(png_ptr, info_ptr, w, h,
png_set_IHDR(png_ptr, info_ptr, blit_data.w, blit_data.h,
8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
b_rgb = (png_bytep *) malloc(sizeof(png_bytep) * h);
b_rgb = (png_bytep *) malloc(sizeof(png_bytep) * blit_data.h);
if (b_rgb == NULL) {
video_log("[video_take_screenshot] Unable to Allocate RGB Bitmap Memory");
fclose(fp);
return;
}
for (y = 0; y < h; ++y) {
for (y = 0; y < blit_data.h; ++y) {
b_rgb[y] = (png_byte *) malloc(png_get_rowbytes(png_ptr, info_ptr));
for (x = 0; x < w; ++x) {
temp = render_buffer->dat[(y * w) + x];
b_rgb[y][(x) * 3 + 0] = (temp >> 16) & 0xff;
b_rgb[y][(x) * 3 + 1] = (temp >> 8) & 0xff;
b_rgb[y][(x) * 3 + 2] = temp & 0xff;
for (x = 0; x < blit_data.w; ++x) {
if (buffer32 == NULL)
memset(&(b_rgb[y][x * 3]), 0x00, 3);
else {
temp = buffer32->line[blit_data.y + y][blit_data.x + x];
b_rgb[y][x * 3] = (temp >> 16) & 0xff;
b_rgb[y][(x * 3) + 1] = (temp >> 8) & 0xff;
b_rgb[y][(x * 3) + 2] = temp & 0xff;
}
}
}
@@ -379,7 +381,7 @@ video_take_screenshot(const char *fn, int startx, int starty, int y1, int y2, in
png_write_end(png_ptr, NULL);
/* cleanup heap allocation */
for (i = 0; i < h; i++)
for (i = 0; i < blit_data.h; i++)
if (b_rgb[i]) free(b_rgb[i]);
if (b_rgb) free(b_rgb);
@@ -389,7 +391,7 @@ video_take_screenshot(const char *fn, int startx, int starty, int y1, int y2, in
static void
video_screenshot(int x, int y, int y1, int y2, int w, int h)
video_screenshot(void)
{
char path[1024], fn[128];
@@ -408,7 +410,7 @@ video_screenshot(int x, int y, int y1, int y2, int w, int h)
video_log("taking screenshot to: %s\n", path);
video_take_screenshot((const char *) path, x, y, y1, y2, w, h);
video_take_screenshot((const char *) path);
png_destroy_write_struct(&png_ptr, &info_ptr);
}
@@ -418,10 +420,12 @@ video_transform_copy(uint32_t *dst, uint32_t *src, int len)
{
int i;
for (i = 0; i < len; i++) {
*dst = video_color_transform(*src);
dst++;
src++;
if ((dst != NULL) && (src != NULL)) {
for (i = 0; i < len; i++) {
*dst = video_color_transform(*src);
dst++;
src++;
}
}
}
@@ -436,28 +440,22 @@ void blit_thread(void *param)
thread_reset_event(blit_data.wake_blit_thread);
MTR_BEGIN("video", "blit_thread");
if (blit_data.y2 > 0) {
for (yy = blit_data.y1; yy < blit_data.y2; yy++) {
if ((video_grayscale || invert_display) && (blit_data.h > 0)) {
for (yy = 0; yy < blit_data.h; yy++) {
if (((blit_data.y + yy) >= 0) && ((blit_data.y + yy) < buffer32->h)) {
if (video_grayscale || invert_display)
video_transform_copy(&(render_buffer->dat)[yy * blit_data.w], &(buffer32->line[blit_data.y + yy][blit_data.x]), blit_data.w);
else
memcpy(&(render_buffer->dat)[yy * blit_data.w], &(buffer32->line[blit_data.y + yy][blit_data.x]), blit_data.w << 2);
video_transform_copy(&(buffer32->line[blit_data.y + yy][blit_data.x]), &(buffer32->line[blit_data.y + yy][blit_data.x]), blit_data.w);
}
}
}
if (screenshots) {
if (render_buffer != NULL)
video_screenshot(blit_data.x, blit_data.y, blit_data.y1, blit_data.y2, blit_data.w, blit_data.h);
video_screenshot();
screenshots--;
video_log("screenshot taken, %i left\n", screenshots);
}
if (blit_func)
blit_func(blit_data.x, blit_data.y,
blit_data.y1, blit_data.y2,
blit_data.w, blit_data.h);
blit_func(blit_data.x, blit_data.y, blit_data.w, blit_data.h);
blit_data.busy = 0;
@@ -468,7 +466,7 @@ void blit_thread(void *param)
void
video_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h)
video_blit_memtoscreen(int x, int y, int w, int h)
{
MTR_BEGIN("video", "video_blit_memtoscreen");
@@ -481,8 +479,6 @@ video_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h)
blit_data.buffer_in_use = 1;
blit_data.x = x;
blit_data.y = y;
blit_data.y1 = y1;
blit_data.y2 = y2;
blit_data.w = w;
blit_data.h = h;
@@ -546,7 +542,7 @@ video_blend(int x, int y)
void
video_blit_memtoscreen_8(int x, int y, int y1, int y2, int w, int h)
video_blit_memtoscreen_8(int x, int y, int w, int h)
{
int yy, xx;
@@ -563,7 +559,7 @@ video_blit_memtoscreen_8(int x, int y, int y1, int y2, int w, int h)
}
}
video_blit_memtoscreen(x, y, y1, y2, w, h);
video_blit_memtoscreen(x, y, w, h);
}
@@ -833,7 +829,6 @@ video_init(void)
/* Account for overscan. */
buffer32 = create_bitmap(2048 + 64, 2048 + 64);
render_buffer = create_bitmap(2048 + 64, 2048 + 64);
for (c = 0; c < 64; c++) {
cgapal[c + 64].r = (((c & 4) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21;
@@ -902,7 +897,6 @@ video_close(void)
free(video_8togs);
free(video_6to8);
destroy_bitmap(render_buffer);
destroy_bitmap(buffer32);
if (fontdatksc5601) {

View File

@@ -167,16 +167,19 @@ vnc_display(rfbClientPtr cl)
static void
vnc_blit(int x, int y, int y1, int y2, int w, int h)
vnc_blit(int x, int y, int w, int h)
{
uint32_t *p;
int yy;
for (yy=y1; yy<y2; yy++) {
if (h <= 0)
return;
for (yy=0; yy<h; yy++) {
p = (uint32_t *)&(((uint32_t *)rfb->frameBuffer)[yy*VNC_MAX_X]);
if ((y+yy) >= 0 && (y+yy) < VNC_MAX_Y)
memcpy(p, &(render_buffer->dat[yy * w]), w*4);
memcpy(p, &(buffer32->line[yy]), w*sizeof(uint32_t));
}
video_blit_complete();

View File

@@ -32,4 +32,18 @@
<activeCodePage xmlns="http://schemas.microsoft.com/SMI/2019/WindowsSettings">UTF-8</activeCodePage>
</windowsSettings>
</application>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
<!-- Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!-- Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<!-- Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!-- Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
</application>
</compatibility>
</assembly>

View File

@@ -15,7 +15,7 @@
enable_language(RC)
add_library(plat OBJECT win.c win_dynld.c win_thread.c win_cdrom.c
add_library(plat OBJECT win.c win_dynld.c win_cdrom.c
win_keyboard.c win_crashdump.c win_midi.c win_mouse.c)
add_library(ui OBJECT win_ui.c win_stbar.c win_sdl.c win_dialog.c win_about.c
@@ -58,5 +58,9 @@ if(OPENGL)
target_sources(ui PRIVATE glad.c win_opengl.c win_opengl_glslp.c)
endif()
if(NOT PTHREAD)
target_sources(plat PRIVATE win_thread.c)
endif()
target_link_libraries(86Box advapi32 comctl32 comdlg32 gdi32 shell32 iphlpapi
dxguid imm32 hid setupapi uxtheme version winmm psapi)

View File

@@ -26,6 +26,10 @@ ifndef DEV_BUILD
DEV_BUILD := n
endif
ifneq ($(PTHREAD), n)
PTHREAD := y
endif
ifeq ($(DEV_BUILD), y)
ifndef DEBUG
DEBUG := y
@@ -607,10 +611,17 @@ CXXFLAGS := $(CFLAGS)
#########################################################################
# Create the (final) list of objects to build. #
#########################################################################
ifeq ($(PTHREAD), y)
MAINOBJ := 86box.o config.o random.o timer.o io.o acpi.o apm.o dma.o ddma.o \
nmi.o pic.o pit.o port_92.o ppi.o pci.o mca.o \
usb.o device.o nvr.o nvr_at.o nvr_ps2.o thread.o \
$(VNCOBJ)
else
MAINOBJ := 86box.o config.o random.o timer.o io.o acpi.o apm.o dma.o ddma.o \
nmi.o pic.o pit.o port_92.o ppi.o pci.o mca.o \
usb.o device.o nvr.o nvr_at.o nvr_ps2.o \
$(VNCOBJ)
endif
MEMOBJ := catalyst_flash.o i2c_eeprom.o intel_flash.o mem.o rom.o smram.o spd.o sst_flash.o
@@ -620,7 +631,7 @@ CPUOBJ := $(DYNARECOBJ) \
808x.o 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o \
x86seg.o x87.o x87_timings.o
CHIPSETOBJ := acc2168.o cs8230.o ali1217.o ali1429.o ali1489.o et6000.o headland.o intel_82335.o cs4031.o \
CHIPSETOBJ := 82c100.o acc2168.o cs8230.o ali1217.o ali1429.o ali1489.o et6000.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 opti822.o opti895.o opti5x7.o scamp.o scat.o via_vt82c49x.o via_vt82c505.o \
gc100.o \
@@ -635,7 +646,7 @@ MCHOBJ := machine.o machine_table.o \
m_xt_xi8088.o m_xt_zenith.o \
m_pcjr.o \
m_amstrad.o m_europc.o \
m_xt_olivetti.o m_tandy.o \
m_xt_olivetti.o m_tandy.o m_v86p.o \
m_at.o m_at_commodore.o \
m_at_t3100e.o m_at_t3100e_vid.o \
m_ps1.o m_ps1_hdc.o \
@@ -773,6 +784,7 @@ VIDOBJ := video.o \
vid_paradise.o \
vid_rtg310x.o \
vid_ti_cf62011.o \
vid_f82c425.o \
vid_tvga.o \
vid_tgui9440.o vid_tkd8001_ramdac.o \
vid_att20c49x_ramdac.o \
@@ -790,11 +802,19 @@ VOODOOOBJ := vid_voodoo.o vid_voodoo_banshee.o \
vid_voodoo_render.o vid_voodoo_setup.o \
vid_voodoo_texture.o
ifeq ($(PTHREAD), y)
PLATOBJ := win.o \
win_dynld.o \
win_cdrom.o win_keyboard.o \
win_crashdump.o win_midi.o \
win_mouse.o
else
PLATOBJ := win.o \
win_dynld.o win_thread.o \
win_cdrom.o win_keyboard.o \
win_crashdump.o win_midi.o \
win_mouse.o
endif
ifeq ($(DINPUT), y)
PLATOBJ += win_joystick.o
@@ -820,7 +840,11 @@ endif
ifneq ($(WX), n)
LIBS += $(WX_LIBS) -lm
endif
ifeq ($(PTHREAD), y)
LIBS += -lpng -lz -lwsock32 -lshell32 -liphlpapi -lpsapi -lSDL2 -limm32 -lhid -lsetupapi -loleaut32 -luxtheme -lversion -lwinmm -static -lstdc++ -lpthread
else
LIBS += -lpng -lz -lwsock32 -lshell32 -liphlpapi -lpsapi -lSDL2 -limm32 -lhid -lsetupapi -loleaut32 -luxtheme -lversion -lwinmm -static -lstdc++
endif
ifneq ($(X64), y)
ifneq ($(ARM64), y)
LIBS += -Wl,--large-address-aware

View File

@@ -1047,10 +1047,10 @@ plat_setfullscreen(int on)
int dpi = win_get_dpi(hwndMain);
/* Are we changing from the same state to the same state? */
if ((!!on) == (!!video_fullscreen))
if ((!!(on & 1)) == (!!video_fullscreen))
return;
if (on && video_fullscreen_first) {
if (on && (start_in_fullscreen || video_fullscreen_first)) {
video_fullscreen |= 2;
if (ui_msgbox_header(MBX_INFO | MBX_DONTASK, (wchar_t *) IDS_2134, (wchar_t *) IDS_2052) == 10) {
video_fullscreen_first = 0;
@@ -1060,13 +1060,14 @@ plat_setfullscreen(int on)
}
/* OK, claim the video. */
win_mouse_close();
if (!(on & 2))
win_mouse_close();
/* Close the current mode, and open the new one. */
video_fullscreen = on | 2;
video_fullscreen = (on & 1) | 2;
if (vid_apis[vid_api].set_fs)
vid_apis[vid_api].set_fs(on);
if (!on) {
vid_apis[vid_api].set_fs(on & 1);
if (!(on & 1)) {
plat_resize(scrnsz_x, scrnsz_y);
if (vid_resize) {
/* scale the screen base on DPI */
@@ -1089,6 +1090,9 @@ plat_setfullscreen(int on)
}
/* Main Window. */
if (vid_resize >= 2)
MoveWindow(hwndMain, window_x, window_y, window_w, window_h, TRUE);
if (hide_status_bar)
ResizeWindowByClientArea(hwndMain, temp_x, temp_y);
else
@@ -1111,26 +1115,31 @@ plat_setfullscreen(int on)
}
video_fullscreen &= 1;
video_force_resize_set(1);
if (!on)
if (!(on & 1))
doresize = 1;
win_mouse_init();
/* Release video and make it redraw the screen. */
device_force_redraw();
if (!(on & 2)) {
/* Release video and make it redraw the screen. */
device_force_redraw();
/* Send a CTRL break code so CTRL does not get stuck. */
keyboard_input(0, 0x01D);
/* Send a CTRL break code so CTRL does not get stuck. */
keyboard_input(0, 0x01D);
}
/* Finally, handle the host's mouse cursor. */
/* win_log("%s full screen, %s cursor\n", on ? "enter" : "leave", on ? "hide" : "show"); */
show_cursor(video_fullscreen ? 0 : -1);
/* This is needed for OpenGL. */
plat_vidapi_enable(0);
plat_vidapi_enable(1);
if (!(on & 2)) {
/* This is needed for OpenGL. */
plat_vidapi_enable(0);
plat_vidapi_enable(1);
}
}
void
plat_vid_reload_options(void)
{

View File

@@ -64,6 +64,7 @@ static const int INIT_HEIGHT = 400;
static const int BUFFERPIXELS = 4460544; /* Same size as render_buffer, pow(2048+64,2). */
static const int BUFFERBYTES = 17842176; /* Pixel is 4 bytes. */
static const int BUFFERCOUNT = 3; /* How many buffers to use for pixel transfer (2-3 is commonly recommended). */
static const int ROW_LENGTH = 2112; /* Source buffer row lenght (including padding) */
/**
* @brief A dedicated OpenGL thread.
@@ -106,7 +107,7 @@ static union
*/
typedef struct
{
int y1, y2, w, h;
int w, h;
void* buffer; /* Buffer for pixel transfer, allocated by gpu driver. */
volatile atomic_flag in_use; /* Is buffer currently in use. */
GLsync sync; /* Fence sync object used by opengl thread to track pixel transfer completion. */
@@ -641,18 +642,16 @@ static void opengl_main(void* param)
SetEvent(sync_objects.resize);
}
/* Clip to height. y2 can be out-of-bounds. */
int sub_height = MIN(info->y2, info->h) - info->y1;
if (!GLAD_GL_ARB_buffer_storage)
{
/* Fallback method, copy data to pixel buffer. */
glBufferSubData(GL_PIXEL_UNPACK_BUFFER, BUFFERBYTES * read_pos, info->w * sub_height * sizeof(uint32_t), info->buffer);
glBufferSubData(GL_PIXEL_UNPACK_BUFFER, BUFFERBYTES * read_pos, info->h * ROW_LENGTH * sizeof(uint32_t), info->buffer);
}
/* Update texture from pixel buffer. */
glPixelStorei(GL_UNPACK_SKIP_PIXELS, BUFFERPIXELS * read_pos);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, info->y1, info->w, sub_height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
glPixelStorei(GL_UNPACK_ROW_LENGTH, ROW_LENGTH);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, info->w, info->h, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
/* Add fence to track when above gl commands are complete. */
info->sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
@@ -808,21 +807,21 @@ static void opengl_main(void* param)
CoUninitialize();
}
static void opengl_blit(int x, int y, int y1, int y2, int w, int h)
static void opengl_blit(int x, int y, int w, int h)
{
if (y1 == y2 || h <= 0 || render_buffer == NULL || thread == NULL ||
int yy;
if ((h <= 0) || (buffer32 == NULL) || (thread == NULL) ||
atomic_flag_test_and_set(&blit_info[write_pos].in_use))
{
video_blit_complete();
return;
}
memcpy(blit_info[write_pos].buffer, &(render_buffer->dat)[y1 * w], w * (y2 - y1) * sizeof(uint32_t));
memcpy(blit_info[write_pos].buffer, &(buffer32->line[y][x]), h * ROW_LENGTH * sizeof(uint32_t));
video_blit_complete();
blit_info[write_pos].y1 = y1;
blit_info[write_pos].y2 = y2;
blit_info[write_pos].w = w;
blit_info[write_pos].h = h;

View File

@@ -229,29 +229,29 @@ sdl_stretch(int *w, int *h, int *x, int *y)
static void
sdl_blit(int x, int y, int y1, int y2, int w, int h)
sdl_blit(int x, int y, int w, int h)
{
SDL_Rect r_src;
int ret;
if (!sdl_enabled || (y1 == y2) || (h <= 0) || (render_buffer == NULL) || (sdl_render == NULL) || (sdl_tex == NULL)) {
if (!sdl_enabled || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL) || (sdl_render == NULL) || (sdl_tex == NULL)) {
video_blit_complete();
return;
}
SDL_LockMutex(sdl_mutex);
r_src.x = 0;
r_src.y = y1;
r_src.x = x;
r_src.y = y;
r_src.w = w;
r_src.h = y2 - y1;
SDL_UpdateTexture(sdl_tex, &r_src, &(render_buffer->dat)[y1 * w], w * 4);
r_src.h = h;
SDL_UpdateTexture(sdl_tex, &r_src, &(buffer32->line[y][x]), (2048 + 64) * sizeof(uint32_t));
video_blit_complete();
SDL_RenderClear(sdl_render);
r_src.x = 0;
r_src.y = 0;
r_src.x = x;
r_src.y = y;
r_src.w = w;
r_src.h = h;
@@ -277,6 +277,11 @@ sdl_destroy_window(void)
static void
sdl_destroy_texture(void)
{
if (sdl_tex != NULL) {
SDL_DestroyTexture(sdl_tex);
sdl_tex = NULL;
}
/* SDL_DestroyRenderer also automatically destroys all associated textures. */
if (sdl_render != NULL) {
SDL_DestroyRenderer(sdl_render);
@@ -339,13 +344,8 @@ sdl_select_best_hw_driver(void)
static void
sdl_reinit_texture(void)
sdl_init_texture(void)
{
if (sdl_flags == -1)
return;
sdl_destroy_texture();
if (sdl_flags & RENDERER_HARDWARE) {
sdl_render = SDL_CreateRenderer(sdl_win, -1, SDL_RENDERER_ACCELERATED);
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, video_filter_method ? "1" : "0");
@@ -357,6 +357,17 @@ sdl_reinit_texture(void)
}
static void
sdl_reinit_texture(void)
{
if (sdl_flags == -1)
return;
sdl_destroy_texture();
sdl_init_texture();
}
void
sdl_set_fs(int fs)
{
@@ -365,7 +376,6 @@ sdl_set_fs(int fs)
SDL_LockMutex(sdl_mutex);
sdl_enabled = 0;
sdl_destroy_texture();
if (fs) {
ShowWindow(sdl_parent_hwnd, TRUE);
@@ -408,7 +418,7 @@ sdl_set_fs(int fs)
else
sdl_flags &= ~RENDERER_FULL_SCREEN;
sdl_reinit_texture();
// sdl_reinit_texture();
sdl_enabled = 1;
SDL_UnlockMutex(sdl_mutex);
}
@@ -456,6 +466,7 @@ sdl_init_common(int flags)
}
sdl_win = SDL_CreateWindowFrom((void *)hwndRender);
sdl_init_texture();
sdl_set_fs(video_fullscreen & 1);
/* Make sure we get a clean exit. */
@@ -554,16 +565,16 @@ sdl_enable(int enable)
SDL_UnlockMutex(sdl_mutex);
}
void
sdl_reload(void)
{
if (sdl_flags & RENDERER_HARDWARE)
{
SDL_LockMutex(sdl_mutex);
if (sdl_flags & RENDERER_HARDWARE) {
SDL_LockMutex(sdl_mutex);
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, video_filter_method ? "1" : "0");
sdl_reinit_texture();
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, video_filter_method ? "1" : "0");
sdl_reinit_texture();
SDL_UnlockMutex(sdl_mutex);
}
}
SDL_UnlockMutex(sdl_mutex);
}
}

View File

@@ -140,11 +140,13 @@ SpecifyDimensionsDialogProcedure(HWND hdlg, UINT message, WPARAM wParam, LPARAM
if (mouse_capture)
ClipCursor(&r);
if (!(vid_resize & 2) && window_remember) {
if (window_remember || (vid_resize & 2)) {
window_x = r.left;
window_y = r.top;
window_w = r.right - r.left;
window_h = r.bottom - r.top;
if (!(vid_resize & 2)) {
window_w = r.right - r.left;
window_h = r.bottom - r.top;
}
}
config_save();

View File

@@ -697,11 +697,13 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
window_remember = !window_remember;
CheckMenuItem(hmenu, IDM_VID_REMEMBER, window_remember ? MF_CHECKED : MF_UNCHECKED);
GetWindowRect(hwnd, &rect);
if (!(vid_resize & 2) && window_remember) {
if (window_remember || (vid_resize & 2)) {
window_x = rect.left;
window_y = rect.top;
window_w = rect.right - rect.left;
window_h = rect.bottom - rect.top;
if (!(vid_resize & 2)) {
window_w = rect.right - rect.left;
window_h = rect.bottom - rect.top;
}
}
config_save();
break;
@@ -978,11 +980,13 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
video_force_resize_set(1);
}
if (window_remember) {
if (!(pos->flags & SWP_NOSIZE) && (window_remember || (vid_resize & 2))) {
window_x = pos->x;
window_y = pos->y;
window_w = pos->cx;
window_h = pos->cy;
if (!(vid_resize & 2)) {
window_w = pos->cx;
window_h = pos->cy;
}
save_window_pos = 1;
config_save();
}
@@ -1375,6 +1379,7 @@ ui_init(int nCmdShow)
MoveWindow(hwnd, window_x, window_y, window_w, window_h, TRUE);
else {
if (vid_resize >= 2) {
MoveWindow(hwnd, window_x, window_y, window_w, window_h, TRUE);
scrnsz_x = fixed_size_x;
scrnsz_y = fixed_size_y;
}
@@ -1422,7 +1427,8 @@ ui_init(int nCmdShow)
}
/* Initialize the mouse module. */
win_mouse_init();
if (!start_in_fullscreen && !video_fullscreen_first)
win_mouse_init();
/*
* Before we can create the Render window, we first have
@@ -1452,16 +1458,16 @@ ui_init(int nCmdShow)
else
plat_resize(scrnsz_x, scrnsz_y);
/* Initialize the rendering window, or fullscreen. */
if (start_in_fullscreen || video_fullscreen_first)
plat_setfullscreen(3);
/* Fire up the machine. */
pc_reset_hard_init();
/* Set the PAUSE mode depending on the renderer. */
plat_pause(0);
/* Initialize the rendering window, or fullscreen. */
if (start_in_fullscreen)
plat_setfullscreen(1);
/* If so requested via the command line, inform the
* application that started us of our HWND, using the
* the hWnd and unique ID the application has given

View File

@@ -8,6 +8,7 @@
"freetype",
"libpng",
"openal-soft",
"sdl2"
"sdl2",
"pthreads"
]
}