mirror of
https://github.com/86Box/86Box.git
synced 2026-02-24 02:18:20 -07:00
Merge branch '86Box:master' into master
This commit is contained in:
1
.github/workflows/c-cpp.yml
vendored
1
.github/workflows/c-cpp.yml
vendored
@@ -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
|
||||
|
||||
70
.github/workflows/cmake.yml
vendored
70
.github/workflows/cmake.yml
vendored
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
406
src/chipset/82c100.c
Normal 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
|
||||
};
|
||||
@@ -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
|
||||
|
||||
@@ -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*/
|
||||
|
||||
|
||||
14
src/config.c
14
src/config.c
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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},
|
||||
|
||||
@@ -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*/
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 *);
|
||||
|
||||
|
||||
@@ -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*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
97
src/machine/m_v86p.c
Normal 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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
190
src/thread.c
Normal 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);
|
||||
}
|
||||
@@ -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()
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
672
src/video/vid_f82c425.c
Normal 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
|
||||
};
|
||||
@@ -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 */
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
1576
src/video/vid_s3.c
1576
src/video/vid_s3.c
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
"freetype",
|
||||
"libpng",
|
||||
"openal-soft",
|
||||
"sdl2"
|
||||
"sdl2",
|
||||
"pthreads"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user