Merge branch '86Box:master' into master

This commit is contained in:
dob205 2021-09-04 15:04:08 +02:00 committed by GitHub
commit a387303630
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 2027 additions and 611 deletions

View file

@ -37,10 +37,13 @@ jobs:
build:
- name: Regular
preset: regular
target: install/strip
- name: Debug
preset: debug
target: install
- name: Dev
preset: experimental
target: install
environment:
- msystem: MINGW32
prefix: mingw-w64-i686
@ -74,7 +77,7 @@ jobs:
-D CMAKE_INSTALL_PREFIX=./build/artifacts
-D VNC=OFF
- name: Build
run: cmake --build build --target install
run: cmake --build build --target ${{ matrix.build.target }}
- uses: actions/upload-artifact@v2
with:
name: '86Box-${{ matrix.build.name }}-MSYS2-${{ matrix.environment.msystem }}-${{ github.sha }}'

View file

@ -39,7 +39,7 @@ include(CPack)
include(CMakeDependentOption)
add_compile_definitions(CMAKE)
add_compile_definitions("$<$<CONFIG:DEBUG>:DEBUG>")
add_compile_definitions("$<$<CONFIG:Debug>:DEBUG>")
if(WIN32)
# Disables *_s function warnings

View file

@ -19,7 +19,8 @@
"CMAKE_C_FLAGS_OPTIMIZED": "-march=native -mtune=native -O3 -ffp-contract=last -flto",
"CMAKE_CXX_FLAGS_OPTIMIZED": "-march=native -mtune=native -O3 -ffp-contract=last -flto"
},
"hidden": true
"hidden": true,
"binaryDir": "build"
},
{
"name": "regular",
@ -70,4 +71,4 @@
}
}
]
}
}

View file

@ -26,6 +26,13 @@
#include <string.h>
#include <time.h>
#include <wchar.h>
#ifdef __APPLE__
#include <string.h>
#include <dispatch/dispatch.h>
#ifdef __aarch64__
#include <pthread.h>
#endif
#endif
#define HAVE_STDARG_H
#include <86box/86box.h>
@ -109,6 +116,7 @@ int confirm_exit_cmdl = 1; /* (O) do not ask for confirmation on quit if set t
uint64_t unique_id = 0;
uint64_t source_hwnd = 0;
#endif
char rom_path[1024] = { '\0'}; /* (O) full path to ROMs */
char log_path[1024] = { '\0'}; /* (O) full path of logfile */
char vm_name[1024] = { '\0'}; /* (O) display name of the VM */
@ -379,12 +387,13 @@ pc_log(const char *fmt, ...)
int
pc_init(int argc, char *argv[])
{
char path[2048];
char path[2048], path2[2048];
char *cfg = NULL, *p;
char temp[128];
struct tm *info;
time_t now;
int c;
int c, vmrp = 0;
int ng = 0, lvmp = 0;
uint32_t *uid, *shwnd;
/* Grab the executable's full path. */
@ -401,7 +410,10 @@ pc_init(int argc, char *argv[])
* could have been set to something else.
*/
plat_getcwd(usr_path, sizeof(usr_path) - 1);
plat_getcwd(rom_path, sizeof(rom_path) - 1);
memset(path, 0x00, sizeof(path));
memset(path2, 0x00, sizeof(path));
for (c=1; c<argc; c++) {
if (argv[c][0] != '-') break;
@ -411,30 +423,49 @@ usage:
printf("\nUsage: 86box [options] [cfg-file]\n\n");
printf("Valid options are:\n\n");
printf("-? or --help - show this information\n");
printf("-C or --dumpcfg - dump config file after loading\n");
#ifdef _WIN32
printf("-A or --crashdump - enables crashdump on exception\n");
#endif
printf("-C or --config path - set 'path' to be config file\n");
#ifdef _WIN32
printf("-D or --debug - force debug output logging\n");
printf("-E or --nographic - forces the old behavior\n");
#endif
printf("-F or --fullscreen - start in fullscreen mode\n");
printf("-L or --logfile path - set 'path' to be the logfile\n");
printf("-P or --vmpath path - set 'path' to be root for vm\n");
printf("-V or --vmname name - overrides the name of the running VM.\n");
printf("-S or --settings - show only the settings dialog\n");
printf("-N or --noconfirm - do not ask for confirmation on quit\n");
#ifdef _WIN32
printf("-H or --hwnd id,hwnd - sends back the main dialog's hwnd\n");
#endif
printf("-R or --crashdump - enables crashdump on exception\n");
printf("-L or --logfile path - set 'path' to be the logfile\n");
printf("-M or --vmrompath - ROM path is roms subdirectory inside the userfiles path\n");
printf("-N or --noconfirm - do not ask for confirmation on quit\n");
printf("-O or --dumpcfg - dump config file after loading\n");
printf("-P or --vmpath path - set 'path' to be root for vm\n");
printf("-R or --rompath path - set 'path' to be ROM path\n");
printf("-S or --settings - show only the settings dialog\n");
printf("-V or --vmname name - overrides the name of the running VM\n");
printf("-Z or --lastvmpath - the last parameter is VM path rather than config\n");
printf("\nA config file can be specified. If none is, the default file will be used.\n");
return(0);
} else if (!strcasecmp(argv[c], "--vmrompath") ||
!strcasecmp(argv[c], "-M")) {
vmrp = 1;
} else if (!strcasecmp(argv[c], "--lastvmpath") ||
!strcasecmp(argv[c], "-Z")) {
lvmp = 1;
} else if (!strcasecmp(argv[c], "--dumpcfg") ||
!strcasecmp(argv[c], "-C")) {
!strcasecmp(argv[c], "-O")) {
do_dump_config = 1;
#ifdef _WIN32
} else if (!strcasecmp(argv[c], "--debug") ||
!strcasecmp(argv[c], "-D")) {
force_debug = 1;
#endif
} else if (!strcasecmp(argv[c], "--nographic") ||
!strcasecmp(argv[c], "-E")) {
/* Currently does nothing, but if/when we implement a built-in manager,
it's going to force the manager not to run, allowing the old usage
without parameter. */
ng = 1;
} else if (!strcasecmp(argv[c], "--fullscreen") ||
!strcasecmp(argv[c], "-F")) {
start_in_fullscreen = 1;
@ -448,6 +479,16 @@ usage:
if ((c+1) == argc) goto usage;
strcpy(path, argv[++c]);
} else if (!strcasecmp(argv[c], "--rompath") ||
!strcasecmp(argv[c], "-R")) {
if ((c+1) == argc) goto usage;
strcpy(path2, argv[++c]);
} else if (!strcasecmp(argv[c], "--config") ||
!strcasecmp(argv[c], "-C")) {
if ((c+1) == argc) goto usage;
cfg = argv[++c];
} else if (!strcasecmp(argv[c], "--vmname") ||
!strcasecmp(argv[c], "-V")) {
if ((c+1) == argc) goto usage;
@ -459,10 +500,10 @@ usage:
} else if (!strcasecmp(argv[c], "--noconfirm") ||
!strcasecmp(argv[c], "-N")) {
confirm_exit_cmdl = 0;
} else if (!strcasecmp(argv[c], "--crashdump") ||
!strcasecmp(argv[c], "-R")) {
enable_crashdump = 1;
#ifdef _WIN32
} else if (!strcasecmp(argv[c], "--crashdump") ||
!strcasecmp(argv[c], "-A")) {
enable_crashdump = 1;
} else if (!strcasecmp(argv[c], "--hwnd") ||
!strcasecmp(argv[c], "-H")) {
@ -484,18 +525,25 @@ usage:
}
/* One argument (config file) allowed. */
if (c < argc)
cfg = argv[c++];
if (c < argc) {
if (lvmp)
strcpy(path, argv[c++]);
else
cfg = argv[c++];
}
if (c != argc) goto usage;
plat_path_slash(usr_path);
plat_path_slash(rom_path);
/*
* If the user provided a path for files, use that
* instead of the current working directory. We do
* make sure that if that was a relative path, we
* make it absolute.
*/
if (path[0] != L'\0') {
if (path[0] != '\0') {
if (! plat_path_abs(path)) {
/*
* This looks like a relative path.
@ -503,7 +551,6 @@ usage:
* Add it to the current working directory
* to convert it (back) to an absolute path.
*/
plat_path_slash(usr_path);
strcat(usr_path, path);
} else {
/*
@ -519,6 +566,43 @@ usage:
plat_dir_create(usr_path);
}
if (vmrp && (path2[0] == '\0')) {
strcpy(path2, usr_path);
plat_path_slash(path2);
strcat(path2, "roms");
plat_path_slash(path2);
}
/*
* If the user provided a path for ROMs, use that
* instead of the current working directory. We do
* make sure that if that was a relative path, we
* make it absolute.
*/
if (path2[0] != '\0') {
if (! plat_path_abs(path2)) {
/*
* This looks like a relative path.
*
* Add it to the current working directory
* to convert it (back) to an absolute path.
*/
strcat(rom_path, path2);
} else {
/*
* The user-provided path seems like an
* absolute path, so just use that.
*/
strcpy(rom_path, path2);
}
/* If the specified path does not yet exist,
create it. */
if (! plat_dir_check(rom_path))
plat_dir_create(rom_path);
} else
rom_path[0] = '\0';
/* Grab the name of the configuration file. */
if (cfg == NULL)
cfg = CONFIG_FILE;
@ -554,19 +638,20 @@ usage:
/* Make sure we have a trailing backslash. */
plat_path_slash(usr_path);
if (rom_path[0] != '\0')
plat_path_slash(rom_path);
/* At this point, we can safely create the full path name. */
plat_append_filename(cfg_path, usr_path, p);
/*
* Get the current directory's name
* Get the current directory's name
*
* At this point usr_path is perfectly initialized.
* If no --vmname parameter specified we'll use the
* working directory name as the VM's name.
*/
if (strlen(vm_name) == 0)
{
if (strlen(vm_name) == 0) {
char ltemp[1024] = { '\0'};
plat_get_dirname(ltemp, usr_path);
strcpy(vm_name, plat_get_filename(ltemp));
@ -581,15 +666,14 @@ usage:
strftime(temp, sizeof(temp), "%Y/%m/%d %H:%M:%S", info);
pclog("#\n# %ls v%ls logfile, created %s\n#\n",
EMU_NAME_W, EMU_VERSION_W, temp);
#ifdef _WIN32
pclog("# Emulator path: %ls\n", exe_path);
pclog("# Userfiles path: %ls\n", usr_path);
pclog("# Configuration file: %ls\n#\n\n", cfg_path);
#else
pclog("# VM: %s\n#\n", vm_name);
pclog("# Emulator path: %s\n", exe_path);
pclog("# Userfiles path: %s\n", usr_path);
if (rom_path[0] != '\0')
pclog("# ROM path: %s\n", rom_path);
else
pclog("# ROM path: %sroms\\\n", exe_path);
pclog("# Configuration file: %s\n#\n\n", cfg_path);
#endif
/*
* We are about to read the configuration file, which MAY
* put data into global variables (the hard- and floppy
@ -703,7 +787,13 @@ pc_init_modules(void)
mem_init();
#ifdef USE_DYNAREC
#if defined(__APPLE__) && defined(__aarch64__)
pthread_jit_write_protect_np(0);
#endif
codegen_init();
#if defined(__APPLE__) && defined(__aarch64__)
pthread_jit_write_protect_np(1);
#endif
#endif
keyboard_init();
@ -999,6 +1089,15 @@ pc_close(thread_t *ptr)
}
#ifdef __APPLE__
static void _ui_window_title(void *s)
{
ui_window_title((const wchar_t *) s);
free(s);
}
#endif
void
pc_run(void)
{
@ -1027,7 +1126,12 @@ pc_run(void)
if (title_update) {
swprintf(temp, sizeof_w(temp), mouse_msg[!!mouse_capture], fps);
#ifdef __APPLE__
/* Needed due to modifying the UI on the non-main thread is a big no-no. */
dispatch_async_f(dispatch_get_main_queue(), wcsdup((const wchar_t *) temp), _ui_window_title);
#else
ui_window_title(temp);
#endif
title_update = 0;
}
}

View file

@ -47,22 +47,7 @@ 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)
find_package(Freetype REQUIRED)
include_directories(${FREETYPE_INCLUDE_DIRS})
find_package(OpenAL REQUIRED)
include_directories(${OPENAL_INCLUDE_DIR})
target_link_libraries(86Box ${OPENAL_LIBRARY})
find_package(SDL2 CONFIG REQUIRED)
include_directories(${SDL2_INCLUDE_DIRS})
target_link_libraries(86Box SDL2::SDL2)
find_package(PNG REQUIRED)
include_directories(${PNG_INCLUDE_DIRS})
target_link_libraries(86Box PNG::PNG)
if(ARCH STREQUAL "i386")
if(WIN32 AND ARCH STREQUAL "i386")
if(MSVC)
target_link_options(86Box PRIVATE "/LARGEADDRESSAWARE")
else()
@ -70,10 +55,30 @@ if(ARCH STREQUAL "i386")
endif()
endif()
if(NOT MSVC AND NOT UNIX AND NOT APPLE)
if(MINGW)
target_link_options(86Box PRIVATE "-static")
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a" ".dll.a")
endif()
find_package(Freetype REQUIRED)
include_directories(${FREETYPE_INCLUDE_DIRS})
find_package(OpenAL REQUIRED)
include_directories(${OPENAL_INCLUDE_DIR})
target_link_libraries(86Box ${OPENAL_LIBRARY})
find_package(SDL2 REQUIRED)
include_directories(${SDL2_INCLUDE_DIRS})
if(MINGW)
target_link_libraries(86Box SDL2::SDL2-static)
else()
target_link_libraries(86Box SDL2::SDL2)
endif()
find_package(PNG REQUIRED)
include_directories(${PNG_INCLUDE_DIRS})
target_link_libraries(86Box PNG::PNG)
configure_file(include/86box/version.h.in include/86box/version.h @ONLY)
include_directories(${CMAKE_CURRENT_BINARY_DIR}/include)
@ -123,7 +128,7 @@ add_subdirectory(sio)
add_subdirectory(scsi)
add_subdirectory(sound)
add_subdirectory(video)
if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
if (WIN32)
add_subdirectory(win)
else()
add_subdirectory(unix)

View file

@ -238,6 +238,16 @@ cdrom_seek(cdrom_t *dev, uint32_t pos)
}
int
cdrom_is_pre(cdrom_t *dev, uint32_t lba)
{
if (dev->ops && dev->ops->is_track_pre)
return dev->ops->is_track_pre(dev, lba);
return 0;
}
int
cdrom_audio_callback(cdrom_t *dev, int16_t *output, int len)
{

View file

@ -155,12 +155,28 @@ image_is_track_audio(cdrom_t *dev, uint32_t pos, int ismsf)
if (track == -1)
return 0;
else {
cdi_get_audio_track_info(img, 0, cdi_get_track(img, pos), &number, &tmsf, &attr);
cdi_get_audio_track_info(img, 0, track, &number, &tmsf, &attr);
return attr == AUDIO_TRACK;
}
}
static int
image_is_track_pre(cdrom_t *dev, uint32_t lba)
{
cd_img_t *img = (cd_img_t *)dev->image;
int track;
/* GetTrack requires LBA. */
track = cdi_get_track(img, lba);
if (track != -1)
return cdi_get_audio_track_pre(img, track);
return 0;
}
static int
image_sector_size(struct cdrom *dev, uint32_t lba)
{
@ -231,6 +247,7 @@ static const cdrom_ops_t cdrom_image_ops = {
image_get_tracks,
image_get_track_info,
image_get_subchannel,
image_is_track_pre,
image_sector_size,
image_read_sector,
image_track_type,

View file

@ -272,6 +272,18 @@ cdi_get_audio_tracks_lba(cd_img_t *cdi, int *st_track, int *end, uint32_t *lead_
}
int
cdi_get_audio_track_pre(cd_img_t *cdi, int track)
{
track_t *trk = &cdi->tracks[track - 1];
if ((track < 1) || (track > cdi->tracks_num))
return 0;
return trk->pre;
}
/* This replaces both Info and EndInfo, they are specified by a variable. */
int
cdi_get_audio_track_info(cd_img_t *cdi, int end, int track, int *track_num, TMSF *start, uint8_t *attr)
@ -709,6 +721,25 @@ cdi_cue_get_frame(uint64_t *frames, char **line)
}
static int
cdi_cue_get_flags(track_t *cur, char **line)
{
char temp[128], temp2[128];
int success;
success = cdi_cue_get_buffer(temp, line, 0);
if (! success) return 0;
memset(temp2, 0x00, sizeof(temp2));
success = sscanf(temp, "%s", temp2) == 1;
if (! success) return 0;
cur->pre = (strstr(temp2, "PRE") != NULL);
return 1;
}
static int
cdi_add_track(cd_img_t *cdi, track_t *cur, uint64_t *shift, uint64_t prestart, uint64_t *total_pregap, uint64_t cur_pregap)
{
@ -850,6 +881,8 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile)
trk.form = 0;
trk.mode2 = 0;
trk.pre = 0;
if (!strcmp(type, "AUDIO")) {
trk.sector_size = RAW_SECTOR_SIZE;
trk.attr = AUDIO_TRACK;
@ -964,7 +997,9 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile)
}
} else if (!strcmp(command, "PREGAP"))
success = cdi_cue_get_frame(&cur_pregap, &line);
else if (!strcmp(command, "CATALOG") || !strcmp(command, "CDTEXTFILE") || !strcmp(command, "FLAGS") || !strcmp(command, "ISRC") ||
else if (!strcmp(command, "FLAGS"))
success = cdi_cue_get_flags(&trk, &line);
else if (!strcmp(command, "CATALOG") || !strcmp(command, "CDTEXTFILE") || !strcmp(command, "ISRC") ||
!strcmp(command, "PERFORMER") || !strcmp(command, "POSTGAP") || !strcmp(command, "REM") ||
!strcmp(command, "SONGWRITER") || !strcmp(command, "TITLE") || !strcmp(command, "")) {
/* Ignored commands. */

View file

@ -37,6 +37,7 @@
#include <86box/timer.h>
#include <86box/nvr.h>
#include <86box/acpi.h>
#include <86box/ddma.h>
#include <86box/pci.h>
#include <86box/pic.h>
#include <86box/port_92.h>
@ -79,6 +80,7 @@ typedef struct
sff8038i_t *bm[2];
nvr_t *nvr;
int nvr_enabled, slot;
ddma_t *ddma;
smbus_piix4_t *smbus;
usb_t *usb[2];
acpi_t *acpi;
@ -708,6 +710,19 @@ usb_update_io_mapping(pipc_t *dev, int func)
}
static void
pipc_ddma_update(pipc_t *dev, int addr)
{
uint32_t base;
if (dev->local >= VIA_PIPC_8231)
return;
base = (dev->pci_isa_regs[addr] & 0xf0) | (((uint32_t) dev->pci_isa_regs[addr | 0x01]) << 8);
ddma_update_io_mapping(dev->ddma, (addr & 0x0e) >> 1, (dev->pci_isa_regs[addr] & 0xf0), dev->pci_isa_regs[addr | 0x01], (dev->pci_isa_regs[addr] & 0x08) && (base != 0x0000));
}
static void
pipc_write(int func, int addr, uint8_t val, void *priv)
{
@ -854,19 +869,13 @@ pipc_write(int func, int addr, uint8_t val, void *priv)
case 0x60: case 0x62: case 0x64: case 0x66:
case 0x6a: case 0x6c: case 0x6e:
c = (addr & 0x0e) >> 1;
dma[c].ab = (dma[c].ab & 0xffffff0f) | (val & 0xf0);
dma[c].ac = (dma[c].ac & 0xffffff0f) | (val & 0xf0);
if (val & 0x08)
dma_e |= (1 << c);
else
dma_e &= ~(1 << c);
dev->pci_isa_regs[addr] = val & 0xf8;
pipc_ddma_update(dev, addr);
break;
case 0x61: case 0x63: case 0x65: case 0x67:
case 0x6b: case 0x6d: case 0x6f:
c = (addr & 0x0e) >> 1;
dma[c].ab = (dma[c].ab & 0xffff00ff) | (val << 8);
dma[c].ac = (dma[c].ac & 0xffff00ff) | (val << 8);
dev->pci_isa_regs[addr] = val;
pipc_ddma_update(dev, addr & 0xfe);
break;
case 0x70: case 0x71: case 0x72: case 0x73:
@ -1353,6 +1362,9 @@ pipc_init(const device_t *info)
pci_enable_mirq(2);
}
if (dev->local < VIA_PIPC_8231)
dev->ddma = device_add(&ddma_device);
if (dev->acpi) {
acpi_set_slot(dev->acpi, dev->slot);
acpi_set_nvr(dev->acpi, dev->nvr);

View file

@ -2578,12 +2578,12 @@ save_storage_controllers(void)
else
config_set_int(cat, "cassette_enabled", cassette_enable);
if (cassette_fname == NULL)
if (strlen(cassette_fname) == 0)
config_delete_var(cat, "cassette_file");
else
config_set_string(cat, "cassette_file", cassette_fname);
if (cassette_mode == NULL)
if (strlen(cassette_mode) == 0)
config_delete_var(cat, "cassette_mode");
else
config_set_string(cat, "cassette_mode", cassette_mode);

View file

@ -195,10 +195,14 @@ exec386(int cycs)
cpu_state.oldpc = cpu_state.pc;
x86_int(2);
nmi_enable = 0;
#ifdef OLD_NMI_BEHAVIOR
if (nmi_auto_clear) {
nmi_auto_clear = 0;
nmi = 0;
}
#else
nmi = 0;
#endif
} else if ((cpu_state.flags & I_FLAG) && pic.int_pending && !cpu_end_block_after_ins) {
vector = picinterrupt();
if (vector != -1) {

View file

@ -3,6 +3,9 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#if defined(__APPLE__) && defined(__aarch64__)
#include <pthread.h>
#endif
#include <wchar.h>
#include <math.h>
#ifndef INFINITY
@ -31,6 +34,9 @@
#endif
#include "386_common.h"
#if defined(__APPLE__) && defined(__aarch64__)
#include <pthread.h>
#endif
#define CPU_BLOCK_END() cpu_block_end = 1
@ -797,10 +803,14 @@ exec386_dynarec(int cycs)
cpu_state.oldpc = cpu_state.pc;
x86_int(2);
nmi_enable = 0;
#ifdef OLD_NMI_BEHAVIOR
if (nmi_auto_clear) {
nmi_auto_clear = 0;
nmi = 0;
}
#else
nmi = 0;
#endif
} else if ((cpu_state.flags & I_FLAG) && pic.int_pending) {
vector = picinterrupt();
if (vector != -1) {

View file

@ -968,6 +968,9 @@ check_interrupts(void)
if (nmi && nmi_enable && nmi_mask) {
nmi_enable = 0;
interrupt(2);
#ifndef OLD_NMI_BEHAVIOR
nmi = 0;
#endif
return;
}
if ((cpu_state.flags & I_FLAG) && pic.int_pending && !noint) {

View file

@ -79,6 +79,7 @@ extern int confirm_exit_cmdl; /* (O) do not ask for confirmation on quit if set
extern uint64_t unique_id;
extern uint64_t source_hwnd;
#endif
extern char rom_path[1024]; /* (O) full path to ROMs */
extern char log_path[1024]; /* (O) full path of logfile */
extern char vm_name[1024]; /* (O) display name of the VM */

View file

@ -83,6 +83,7 @@ typedef struct {
void (*get_tracks)(struct cdrom *dev, int *first, int *last);
void (*get_track_info)(struct cdrom *dev, uint32_t track, int end, track_info_t *ti);
void (*get_subchannel)(struct cdrom *dev, uint32_t lba, subchannel_t *subc);
int (*is_track_pre)(struct cdrom *dev, uint32_t lba);
int (*sector_size)(struct cdrom *dev, uint32_t lba);
int (*read_sector)(struct cdrom *dev, int type, uint8_t *b, uint32_t lba);
int (*track_type)(struct cdrom *dev, uint32_t lba);
@ -136,6 +137,7 @@ extern cdrom_t cdrom[CDROM_NUM];
extern int cdrom_lba_to_msf_accurate(int lba);
extern double cdrom_seek_time(cdrom_t *dev);
extern void cdrom_stop(cdrom_t *dev);
extern int cdrom_is_pre(cdrom_t *dev, uint32_t lba);
extern int cdrom_audio_callback(cdrom_t *dev, int16_t *output, int len);
extern uint8_t cdrom_audio_play(cdrom_t *dev, uint32_t pos, uint32_t len, int ismsf);
extern uint8_t cdrom_audio_track_search(cdrom_t *dev, uint32_t pos, int type, uint8_t playbit);

View file

@ -58,7 +58,7 @@ typedef struct {
typedef struct {
int number, track_number, attr, sector_size,
mode2, form;
mode2, form, pre, pad;
uint64_t start, length,
skip;
track_file_t *file;
@ -75,6 +75,7 @@ extern void cdi_close(cd_img_t *cdi);
extern int cdi_set_device(cd_img_t *cdi, const char *path);
extern int cdi_get_audio_tracks(cd_img_t *cdi, int *st_track, int *end, TMSF *lead_out);
extern int cdi_get_audio_tracks_lba(cd_img_t *cdi, int *st_track, int *end, uint32_t *lead_out);
extern int cdi_get_audio_track_pre(cd_img_t *cdi, int track);
extern int cdi_get_audio_track_info(cd_img_t *cdi, int end, int track, int *track_num, TMSF *start, uint8_t *attr);
extern int cdi_get_audio_track_info_lba(cd_img_t *cdi, int end, int track, int *track_num, uint32_t *start, uint8_t *attr);
extern int cdi_get_track(cd_img_t *cdi, uint32_t sector);

View file

@ -126,7 +126,7 @@ typedef struct svga_t
int override;
void *p;
uint8_t crtc[256], gdcreg[64], attrregs[32], seqregs[256],
uint8_t crtc[256], gdcreg[256], attrregs[32], seqregs[256],
egapal[16],
*vram, *changedvram;
@ -264,6 +264,10 @@ extern float stg_getclock(int clock, void *p);
extern void tkd8001_ramdac_out(uint16_t addr, uint8_t val, void *p, svga_t *svga);
extern uint8_t tkd8001_ramdac_in(uint16_t addr, void *p, svga_t *svga);
extern void tvp3026_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *p, svga_t *svga);
extern uint8_t tvp3026_ramdac_in(uint16_t addr, int rs2, int rs3, void *p, svga_t *svga);
extern void tvp3026_recalctimings(void *p, svga_t *svga);
extern void tvp3026_hwcursor_draw(svga_t *svga, int displine);
#ifdef EMU_DEVICE_H
extern const device_t ati68860_ramdac_device;
@ -292,4 +296,5 @@ extern const device_t stg_ramdac_device;
extern const device_t tkd8001_ramdac_device;
extern const device_t tseng_ics5301_ramdac_device;
extern const device_t tseng_ics5341_ramdac_device;
extern const device_t tvp3026_ramdac_device;
#endif

View file

@ -325,7 +325,10 @@ extern const device_t s3_diamond_stealth_vram_isa_device;
extern const device_t s3_ami_86c924_isa_device;
extern const device_t s3_metheus_86c928_isa_device;
extern const device_t s3_metheus_86c928_vlb_device;
extern const device_t s3_v7mirage_86c801_isa_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_10sd_805_vlb_device;
extern const device_t s3_phoenix_86c801_isa_device;
extern const device_t s3_phoenix_86c805_vlb_device;
extern const device_t s3_bahamas64_vlb_device;
extern const device_t s3_bahamas64_pci_device;
@ -335,10 +338,10 @@ extern const device_t s3_phoenix_trio32_vlb_device;
extern const device_t s3_phoenix_trio32_pci_device;
extern const device_t s3_diamond_stealth_se_vlb_device;
extern const device_t s3_diamond_stealth_se_pci_device;
extern const device_t s3_spea_mirage_p64_vlb_device;
extern const device_t s3_phoenix_trio64_vlb_device;
extern const device_t s3_phoenix_trio64_onboard_pci_device;
extern const device_t s3_phoenix_trio64_pci_device;
extern const device_t s3_phoenix_trio64vplus_vlb_device;
extern const device_t s3_phoenix_trio64vplus_pci_device;
extern const device_t s3_phoenix_trio64vplus_onboard_pci_device;
extern const device_t s3_phoenix_vision864_pci_device;
@ -349,10 +352,11 @@ 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_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_964_vlb_device;
extern const device_t s3_elsa_winner2000_pro_x_pci_device;
extern const device_t s3_elsa_winner2000_pro_x_vlb_device;
extern const device_t s3_trio64v2_dx_pci_device;
/* S3 ViRGE */

View file

@ -1643,8 +1643,6 @@ vid_init_200(amstrad_t *ams)
memset(vid, 0x00, sizeof(amsvid_t));
vid->emulation = device_get_config_int("video_emulation");
cga_palette = (device_get_config_int("display_type") << 1);
ams_inform(vid);
/* Default to CGA */
vid->dipswitches = 0x10;
@ -1677,6 +1675,9 @@ vid_init_200(amstrad_t *ams)
cga_init(cga);
mda_init(mda);
cga_palette = (device_get_config_int("display_type") << 1);
ams_inform(vid);
/* Attribute 8 is white on black (on a real MDA it's black on black) */
mda_setcol(0x08, 0, 1, 15);
mda_setcol(0x88, 0, 1, 15);

View file

@ -62,10 +62,35 @@ FILE *
rom_fopen(char *fn, char *mode)
{
char temp[1024];
char *fn2;
plat_append_filename(temp, exe_path, fn);
if ((strstr(fn, "roms/") == fn) || (strstr(fn, "roms\\") == fn)) {
/* Relative path */
fn2 = (char *) malloc(strlen(fn) + 1);
memcpy(fn2, fn, strlen(fn) + 1);
return(plat_fopen(temp, mode));
if (rom_path[0] != '\0') {
memset(fn2, 0x00, strlen(fn) + 1);
memcpy(fn2, &(fn[5]), strlen(fn) - 4);
plat_append_filename(temp, rom_path, fn2);
} else {
/* Make sure to make it a backslash, just in case there's malformed
code calling us that assumes Windows. */
if (fn2[4] == '\\')
fn2[4] = '/';
plat_append_filename(temp, exe_path, fn2);
}
free(fn2);
fn2 = NULL;
return(plat_fopen(temp, mode));
} else {
/* Absolute path */
return(plat_fopen(fn, mode));
}
}

View file

@ -110,20 +110,20 @@ ctr_decrease_count(ctr_t *ctr)
{
if (ctr->bcd) {
ctr->units--;
if (ctr->units == 0xff) {
ctr->units = 9;
if (ctr->units == -1) {
ctr->units = -7;
ctr->tens--;
if (ctr->tens == 0xff) {
ctr->tens = 9;
if (ctr->tens == -1) {
ctr->tens = -7;
ctr->hundreds--;
if (ctr->hundreds == 0xff) {
ctr->hundreds = 9;
if (ctr->hundreds == -1) {
ctr->hundreds = -7;
ctr->thousands--;
if (ctr->thousands == 0xff) {
ctr->thousands = 9;
if (ctr->thousands == -1) {
ctr->thousands = -7;
ctr->myriads--;
if (ctr->myriads == 0xff)
ctr->myriads = 0; /* 0 - 1 should wrap around to 9999. */
if (ctr->myriads == -1)
ctr->myriads = -7; /* 0 - 1 should wrap around to 9999. */
}
}
}

View file

@ -692,7 +692,7 @@ ncr_write(uint16_t port, uint8_t val, void *priv)
ncr_dev->t128.host_pos = MIN(512, dev->buffer_length);
ncr_dev->t128.status |= 0x04;
timer_on_auto(&ncr_dev->timer, 0.2);
timer_on_auto(&ncr_dev->timer, 0.02);
} else {
if ((ncr->mode & MODE_DMA) && !timer_is_enabled(&ncr_dev->timer)) {
memset(ncr_dev->buffer, 0, MIN(128, dev->buffer_length));

View file

@ -212,7 +212,8 @@ sound_cd_clean_buffers(void)
static void
sound_cd_thread(void *param)
{
int c, r, i, channel_select[2];
uint32_t lba;
int c, r, i, pre, channel_select[2];
double audio_vol_l, audio_vol_r;
double cd_buffer_temp[2] = {0.0, 0.0};
@ -231,9 +232,11 @@ sound_cd_thread(void *param)
if ((cdrom[i].bus_type == CDROM_BUS_DISABLED) ||
(cdrom[i].cd_status == CD_STATUS_EMPTY))
continue;
lba = cdrom[i].seek_pos;
r = cdrom_audio_callback(&(cdrom[i]), cd_buffer[i], CD_BUFLEN * 2);
if (!cdrom[i].bus_type || !cdrom[i].sound_on || !r)
continue;
pre = cdrom_is_pre(&(cdrom[i]), lba);
if (cdrom[i].get_volume) {
audio_vol_l = (float) (cdrom[i].get_volume(cdrom[i].priv, 0));
@ -277,6 +280,9 @@ sound_cd_thread(void *param)
cd_buffer_temp[0] += ((double) cd_buffer[i][c + 1]); /* Channel 1 => Port 0 */
cd_buffer_temp[0] *= audio_vol_l; /* Multiply Port 0 by Port 0 volume */
if (pre)
cd_buffer_temp[0] = deemph_iir(0, cd_buffer_temp[0]); /* De-emphasize if necessary */
}
if ((audio_vol_r != 0.0) && (channel_select[1] != 0)) {
@ -286,6 +292,9 @@ sound_cd_thread(void *param)
cd_buffer_temp[1] += ((double) cd_buffer[i][c + 1]); /* Channel 1 => Port 1 */
cd_buffer_temp[1] *= audio_vol_r; /* Multiply Port 1 by Port 1 volume */
if (pre)
cd_buffer_temp[1] = deemph_iir(1, cd_buffer_temp[1]); /* De-emphasize if necessary */
}
/* Apply sound card CD volume and filters */

View file

@ -198,7 +198,8 @@ sdl_destroy_texture(void)
void
sdl_close(void)
{
SDL_LockMutex(sdl_mutex);
if (sdl_mutex != NULL)
SDL_LockMutex(sdl_mutex);
/* Unregister our renderer! */
video_setblit(NULL);

View file

@ -24,7 +24,7 @@ add_library(vid OBJECT video.c vid_table.c vid_cga.c vid_cga_comp.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_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_sdac_ramdac.c vid_ogc.c vid_nga.c vid_tvp3026_ramdac.c)
if(MGA)
target_compile_definitions(vid PRIVATE USE_MGA)

File diff suppressed because it is too large Load diff

View file

@ -53,7 +53,6 @@ static const VIDEO_CARD
video_cards[] = {
{ "none", NULL },
{ "internal", NULL },
{ "ami_s3_924", &s3_ami_86c924_isa_device },
{ "egawonder800", &atiega_device },
{ "mach64gx_isa", &mach64gx_isa_device },
{ "ati28800k", &ati28800k_device },
@ -79,7 +78,6 @@ video_cards[] = {
{ "compaq_cga", &compaq_cga_device },
{ "compaq_cga_2", &compaq_cga_2_device },
{ "compaq_ega", &cpqega_device },
{ "stealthvram_isa", &s3_diamond_stealth_vram_isa_device },
{ "ega", &ega_device },
{ "g2_gc205", &g2_gc205_device },
{ "hercules", &hercules_device },
@ -90,13 +88,11 @@ video_cards[] = {
{ "kasan16vga", &et4000_kasan_isa_device },
{ "mda", &mda_device },
{ "genius", &genius_device },
{ "metheus928_isa", &s3_metheus_86c928_isa_device },
{ "nga", &nga_device },
{ "ogc", &ogc_device },
{ "oti037c", &oti037c_device },
{ "oti067", &oti067_device },
{ "oti077", &oti077_device },
{ "orchid_s3_911", &s3_orchid_86c911_isa_device },
{ "pvga1a", &paradise_pvga1a_device },
{ "wd90c11", &paradise_wd90c11_device },
{ "wd90c30", &paradise_wd90c30_device },
@ -104,8 +100,13 @@ video_cards[] = {
{ "pgc", &pgc_device },
{ "radius_isa", &radius_svga_multiview_isa_device },
{ "rtg3106", &realtek_rtg3106_device },
{ "stealthvram_isa", &s3_diamond_stealth_vram_isa_device },
{ "orchid_s3_911", &s3_orchid_86c911_isa_device },
{ "ami_s3_924", &s3_ami_86c924_isa_device },
{ "metheus928_isa", &s3_metheus_86c928_isa_device },
{ "px_86c801_isa", &s3_phoenix_86c801_isa_device },
{ "px_s3_v7_801_isa", &s3_spea_mirage_86c801_isa_device },
{ "sigma400", &sigma_device },
{ "px_s3_v7_801_isa", &s3_v7mirage_86c801_isa_device },
{ "tvga8900b", &tvga8900b_device },
{ "tvga8900d", &tvga8900d_device },
{ "tvga9000b", &tvga9000b_device },
@ -133,28 +134,30 @@ video_cards[] = {
{ "cl_gd5480_pci", &gd5480_pci_device },
{ "ctl3d_banshee_pci", &creative_voodoo_banshee_device },
{ "stealth32_pci", &et4000w32p_pci_device },
{ "stealth64v_pci", &s3_diamond_stealth64_964_pci_device },
{ "elsawin2kprox_964_pci", &s3_elsa_winner2000_pro_x_964_pci_device },
{ "bahamas64_pci", &s3_bahamas64_pci_device },
{ "px_vision864_pci", &s3_phoenix_vision864_pci_device },
{ "stealthse_pci", &s3_diamond_stealth_se_pci_device },
{ "px_trio32_pci", &s3_phoenix_trio32_pci_device },
{ "stealth64d_pci", &s3_diamond_stealth64_pci_device },
{ "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 },
{ "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 },
{ "trio64v2dx_pci", &s3_trio64v2_dx_pci_device },
{ "stealth3d_2000_pci", &s3_virge_pci_device },
{ "stealth3d_3000_pci", &s3_virge_988_pci_device },
{ "stealth64d_pci", &s3_diamond_stealth64_pci_device },
{ "stealth64v_pci", &s3_diamond_stealth64_964_pci_device },
{ "stealthse_pci", &s3_diamond_stealth_se_pci_device },
{ "elsawin2kprox_964_pci", &s3_elsa_winner2000_pro_x_964_pci_device },
{ "elsawin2kprox_pci", &s3_elsa_winner2000_pro_x_pci_device },
#if defined(DEV_BRANCH) && defined(USE_MGA)
{ "mystique", &mystique_device },
{ "mystique_220", &mystique_220_device },
#endif
{ "n9_9fx_pci", &s3_9fx_pci_device },
{ "bahamas64_pci", &s3_bahamas64_pci_device },
{ "px_vision864_pci", &s3_phoenix_vision864_pci_device },
{ "px_vision868_pci", &s3_phoenix_vision868_pci_device },
{ "px_trio32_pci", &s3_phoenix_trio32_pci_device },
{ "px_trio64_pci", &s3_phoenix_trio64_pci_device },
{ "px_trio64vplus_pci", &s3_phoenix_trio64vplus_pci_device },
#if defined(DEV_BRANCH) && defined(USE_S3TRIO3D2X)
{ "trio3d2x", &s3_trio3d_2x_pci_device },
#endif
{ "trio64v2dx_pci", &s3_trio64v2_dx_pci_device },
{ "virge325_pci", &s3_virge_325_pci_device },
{ "virge375_pci", &s3_virge_375_pci_device },
{ "virge375_vbe20_pci", &s3_virge_375_4_pci_device },
@ -179,21 +182,20 @@ video_cards[] = {
{ "cl_gd5430_vlb", &gd5430_vlb_device },
{ "stealth3d_2000_vlb", &s3_virge_vlb_device },
{ "stealth3d_3000_vlb", &s3_virge_988_vlb_device },
{ "stealth64d_vlb", &s3_diamond_stealth64_vlb_device },
{ "stealth64v_vlb", &s3_diamond_stealth64_964_vlb_device },
{ "stealthse_vlb", &s3_diamond_stealth_se_vlb_device },
{ "elsawin2kprox_964_vlb", &s3_elsa_winner2000_pro_x_964_vlb_device },
{ "elsawin2kprox_vlb", &s3_elsa_winner2000_pro_x_vlb_device },
{ "ht216_32", &ht216_32_standalone_device },
{ "metheus928_vlb", &s3_metheus_86c928_vlb_device },
{ "n9_9fx_vlb", &s3_9fx_vlb_device },
{ "bahamas64_vlb", &s3_bahamas64_vlb_device },
{ "mirocrystal10sd_vlb", &s3_mirocrystal_10sd_805_vlb_device },
{ "px_86c805_vlb", &s3_phoenix_86c805_vlb_device },
{ "stealth64v_vlb", &s3_diamond_stealth64_964_vlb_device },
{ "bahamas64_vlb", &s3_bahamas64_vlb_device },
{ "px_vision864_vlb", &s3_phoenix_vision864_vlb_device },
{ "px_vision868_vlb", &s3_phoenix_vision868_vlb_device },
{ "stealthse_vlb", &s3_diamond_stealth_se_vlb_device },
{ "px_trio32_vlb", &s3_phoenix_trio32_vlb_device },
{ "stealth64d_vlb", &s3_diamond_stealth64_vlb_device },
{ "n9_9fx_vlb", &s3_9fx_vlb_device },
{ "px_trio64_vlb", &s3_phoenix_trio64_vlb_device },
{ "px_trio64vplus_vlb", &s3_phoenix_trio64vplus_vlb_device },
{ "spea_miragep64_vlb", &s3_spea_mirage_p64_vlb_device },
{ "px_vision868_vlb", &s3_phoenix_vision868_vlb_device },
{ "ht216_32", &ht216_32_standalone_device },
{ "virge325_vlb", &s3_virge_325_vlb_device },
{ "virge375_vlb", &s3_virge_375_vlb_device },
{ "virge375_vbe20_vlb", &s3_virge_375_4_vlb_device },

View file

@ -115,6 +115,7 @@ typedef struct tgui_t
int16_t dst_x, dst_y;
int16_t dst_y_clip, dst_x_clip;
int16_t size_x, size_y;
uint16_t sv_size_y;
uint16_t patloc;
uint32_t fg_col, bg_col;
uint32_t style, ckey;
@ -131,7 +132,7 @@ typedef struct tgui_t
int pat_x, pat_y;
int use_src;
int src_pitch, dst_pitch, bpp;
int pitch, bpp;
uint32_t fill_pattern[8*8];
uint32_t mono_pattern[8*8];
uint32_t pattern_8[8*8];
@ -144,8 +145,9 @@ typedef struct tgui_t
uint8_t tgui_3d8, tgui_3d9;
int oldmode;
uint8_t oldctrl1;
uint8_t oldctrl2,newctrl2;
uint8_t oldctrl1, newctrl1;
uint8_t oldctrl2, newctrl2;
uint8_t oldgr0e, newgr0e;
uint32_t linear_base, linear_size, ge_base,
mmio_base;
@ -292,23 +294,21 @@ tgui_out(uint16_t addr, uint8_t val, void *p)
{
tgui_t *tgui = (tgui_t *)p;
svga_t *svga = &tgui->svga;
uint8_t old, mask;
mask = (tgui->type >= TGUI_9660) ? 0x3f : 0x1f;
uint8_t old;
if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout & 1)) addr ^= 0x60;
switch (addr)
{
case 0x3C5:
switch (svga->seqaddr & 0xf)
switch (svga->seqaddr)
{
case 0xB:
tgui->oldmode=1;
tgui->oldmode = 1;
break;
case 0xC:
if (svga->seqregs[0xe] & 0x80)
svga->seqregs[0xc] = val;
if (svga->seqregs[0x0e] & 0x80)
svga->seqregs[0x0c] = val;
break;
case 0xd:
if (tgui->oldmode)
@ -320,12 +320,13 @@ tgui_out(uint16_t addr, uint8_t val, void *p)
if (tgui->oldmode) {
tgui->oldctrl1 = val;
tgui_update_irqs(tgui);
} else {
svga->seqregs[0xe] = (val ^ 2);
svga->write_bank = (svga->seqregs[0xe] & 0xf) * 65536;
if (!(svga->gdcreg[0xf] & 1))
svga->read_bank = svga->write_bank;
svga->write_bank = (tgui->oldctrl1) * 65536;
} else {
svga->seqregs[0xe] = val ^ 2;
svga->write_bank = (svga->seqregs[0xe]) * 65536;
}
if (!(svga->gdcreg[0xf] & 1))
svga->read_bank = svga->write_bank;
return;
}
break;
@ -340,16 +341,16 @@ tgui_out(uint16_t addr, uint8_t val, void *p)
{
tgui->ramdac_state = 0;
tgui->ramdac_ctrl = val;
switch (tgui->ramdac_ctrl & 0xf0)
switch ((tgui->ramdac_ctrl >> 4) & 0x0f)
{
case 0x10:
case 1:
svga->bpp = 15;
break;
case 0x30:
case 3:
svga->bpp = 16;
break;
case 0xd0:
svga->bpp = ((svga->crtc[0x38] & 0x08) == 0x08 && (tgui->type == TGUI_9440)) ? 24 : 32;
case 0x0d:
svga->bpp = (tgui->type >= TGUI_9660) ? 32 : 24;
break;
default:
svga->bpp = 8;
@ -366,7 +367,7 @@ tgui_out(uint16_t addr, uint8_t val, void *p)
tkd8001_ramdac_out(addr, val, svga->ramdac, svga);
return;
}
tgui->ramdac_state = 0;
tgui->ramdac_state = 0;
break;
case 0x3CF:
@ -383,26 +384,45 @@ tgui_out(uint16_t addr, uint8_t val, void *p)
tgui_recalcmapping(tgui);
return;
}
switch (svga->gdcaddr & 15)
switch (svga->gdcaddr)
{
case 0x6:
if (svga->gdcreg[6] != val)
{
svga->gdcreg[6] = val;
tgui_recalcmapping(tgui);
}
return;
case 0x6:
if (svga->gdcreg[6] != val)
{
svga->gdcreg[6] = val;
tgui_recalcmapping(tgui);
}
return;
case 0xE:
case 0x0e:
svga->gdcreg[0xe] = val ^ 2;
if ((svga->gdcreg[0xf] & 1) == 1)
svga->read_bank = (svga->gdcreg[0xe] & 0xf) * 65536;
svga->read_bank = (svga->gdcreg[0xe]) * 65536;
break;
case 0xF:
if (val & 1) svga->read_bank = (svga->gdcreg[0xe] & 0xf) *65536;
else svga->read_bank = (svga->seqregs[0xe] & 0xf) *65536;
svga->write_bank = (svga->seqregs[0xe] & 0xf) * 65536;
case 0x0f:
if (val & 1)
svga->read_bank = (svga->gdcreg[0xe]) * 65536;
else {
if (tgui->oldmode)
svga->read_bank = (tgui->oldctrl1) * 65536;
else
svga->read_bank = (svga->seqregs[0xe]) * 65536;
}
if (tgui->oldmode)
svga->write_bank = (tgui->oldctrl1) * 65536;
else
svga->write_bank = (svga->seqregs[0xe]) * 65536;
break;
case 0x5a:
case 0x5b:
case 0x5c:
case 0x5d:
case 0x5e:
case 0x5f:
svga->gdcreg[svga->gdcaddr] = val;
break;
}
break;
case 0x3D4:
@ -430,7 +450,7 @@ tgui_out(uint16_t addr, uint8_t val, void *p)
}
}
switch (svga->crtcreg) {
case 0x1e:
case 0x1e:
svga->vram_display_mask = (val & 0x80) ? tgui->vram_mask : 0x3ffff;
break;
@ -441,6 +461,7 @@ tgui_out(uint16_t addr, uint8_t val, void *p)
tgui->linear_size = (val & 0x10) ? 0x200000 : 0x100000;
svga->decode_mask = (val & 0x10) ? 0x1fffff : 0xfffff;
}
pclog("Linear base = %08x, size = %08x, mask = %08x\n", tgui->linear_base, tgui->linear_size, svga->decode_mask);
tgui_recalcmapping(tgui);
}
break;
@ -457,11 +478,6 @@ tgui_out(uint16_t addr, uint8_t val, void *p)
case 0x39:
tgui_recalcmapping(tgui);
break;
case 0x37:
if (tgui->type >= TGUI_9660)
i2c_gpio_set(tgui->i2c, !!(val & 0x02), (val & 0x01));
break;
case 0x40: case 0x41: case 0x42: case 0x43:
case 0x44: case 0x45: case 0x46: case 0x47:
@ -486,19 +502,20 @@ tgui_out(uint16_t addr, uint8_t val, void *p)
}
return;
case 0x3D8:
tgui->tgui_3d8 = val;
if (svga->gdcreg[0xf] & 4) {
svga->write_bank = (val & mask) * 65536;
if (!(svga->gdcreg[0xf] & 1))
svga->read_bank = (val & mask) * 65536;
}
return;
case 0x3D8:
tgui->tgui_3d8 = val;
if (svga->gdcreg[0xf] & 4) {
svga->write_bank = (val & 0x3f) * 65536;
if (!(svga->gdcreg[0xf] & 1)) {
svga->read_bank = (val & 0x3f) * 65536;
}
}
return;
case 0x3D9:
tgui->tgui_3d9 = val;
if ((svga->gdcreg[0xf] & 5) == 5)
svga->read_bank = (val & mask) * 65536;
return;
tgui->tgui_3d9 = val;
if ((svga->gdcreg[0xf] & 5) == 5)
svga->read_bank = (val & 0x3f) * 65536;
return;
case 0x43c8:
tgui->clock_n = val & 0x7f;
@ -524,11 +541,11 @@ tgui_in(uint16_t addr, void *p)
switch (addr)
{
case 0x3C5:
if ((svga->seqaddr & 0xf) == 9) {
if (svga->seqaddr == 9) {
if (tgui->type == TGUI_9680)
return 0x01; /*TGUI9680XGi*/
}
if ((svga->seqaddr & 0xf) == 0xb)
if (svga->seqaddr == 0x0b)
{
tgui->oldmode = 0;
switch (tgui->type)
@ -542,16 +559,22 @@ tgui_in(uint16_t addr, void *p)
return 0xd3; /*TGUI9660XGi*/
}
}
if ((svga->seqaddr & 0xf) == 0xd)
if (svga->seqaddr == 0x0d)
{
if (tgui->oldmode)
return tgui->oldctrl2;
return tgui->newctrl2;
}
if ((svga->seqaddr & 0xf) == 0xe)
if (svga->seqaddr == 0x0c)
{
if (svga->seqregs[0x0e] & 0x80)
return svga->seqregs[0x0c];
}
if (svga->seqaddr == 0x0e)
{
if (tgui->oldmode)
return tgui->oldctrl1;
return tgui->oldctrl1 | 0x88;
return svga->seqregs[0x0e];
}
break;
@ -572,19 +595,13 @@ tgui_in(uint16_t addr, void *p)
case 0x3CF:
if (tgui->type == TGUI_9400CXI && svga->gdcaddr >= 16 && svga->gdcaddr < 32)
return tgui->ext_gdc_regs[svga->gdcaddr & 15];
break;
if (svga->gdcaddr >= 0x5a && svga->gdcaddr <= 0x5f)
return svga->gdcreg[svga->gdcaddr];
break;
case 0x3D4:
return svga->crtcreg;
case 0x3D5:
temp = svga->crtc[svga->crtcreg];
if (svga->crtcreg == 0x37) {
if (tgui->type >= TGUI_9660) {
if ((svga->crtc[0x37] & 0x02) && i2c_gpio_get_scl(tgui->i2c))
temp |= 0x02;
if ((svga->crtc[0x37] & 0x01) && i2c_gpio_get_sda(tgui->i2c))
temp |= 0x01;
}
}
return temp;
case 0x3d8:
return tgui->tgui_3d8;
@ -611,14 +628,17 @@ void tgui_recalctimings(svga_t *svga)
svga->rowoffset <<= 1;
}
if ((svga->crtc[0x1e] & 0xa0) == 0xa0)
if ((svga->crtc[0x1e] & 0xA0) == 0xA0)
svga->ma_latch |= 0x10000;
if (svga->crtc[0x27] & 0x01)
if ((svga->crtc[0x27] & 0x01) == 0x01)
svga->ma_latch |= 0x20000;
if (svga->crtc[0x27] & 0x02)
if ((svga->crtc[0x27] & 0x02) == 0x02)
svga->ma_latch |= 0x40000;
if (svga->crtc[0x27] & 0x04)
if ((svga->crtc[0x27] & 0x04) == 0x04)
svga->ma_latch |= 0x80000;
if (svga->crtc[0x27] & 0x08)
svga->split |= 0x400;
if (svga->crtc[0x27] & 0x10)
@ -635,7 +655,7 @@ void tgui_recalctimings(svga_t *svga)
svga->lowres = 0;
}
if (((tgui->oldctrl2 & 0x10) && (svga->crtc[0x1e] & 0x20) && (tgui->oldctrl1 & 1)) || (svga->crtc[0x2a] & 0x40)) /*According to vgadoc*/
if ((tgui->oldctrl2 & 0x10) || (svga->crtc[0x2a] & 0x40))
svga->ma_latch <<= 1;
svga->lowres = !(svga->crtc[0x2a] & 0x40);
@ -711,6 +731,11 @@ void tgui_recalctimings(svga_t *svga)
break;
case 32:
svga->render = svga_render_32bpp_highres;
if (tgui->type >= TGUI_9660) {
if (svga->hdisp == 1024) {
svga->rowoffset <<= 1;
}
}
break;
}
}
@ -888,7 +913,7 @@ uint8_t tgui_pci_read(int func, int addr, void *p)
case 0x02: return (tgui->type == TGUI_9440) ? 0x40 : 0x60; /*TGUI9440AGi or TGUI9660XGi*/
case 0x03: return (tgui->type == TGUI_9440) ? 0x94 : 0x96;
case PCI_REG_COMMAND: return tgui->pci_regs[PCI_REG_COMMAND] & 0x23; /*Respond to IO and memory accesses*/
case PCI_REG_COMMAND: return tgui->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/
case 0x07: return 1 << 1; /*Medium DEVSEL timing*/
@ -942,7 +967,6 @@ void tgui_pci_write(int func, int addr, uint8_t val, void *p)
tgui->linear_base = (tgui->linear_base & 0xff000000) | ((val & 0xe0) << 16);
tgui->linear_size = tgui->vram_size;
svga->decode_mask = tgui->vram_mask;
svga->crtc[0x21] = (svga->crtc[0x21] & ~0xf) | (val >> 4);
tgui_recalcmapping(tgui);
break;
case 0x13:
@ -952,7 +976,6 @@ void tgui_pci_write(int func, int addr, uint8_t val, void *p)
tgui->linear_base = (tgui->linear_base & 0xe00000) | (val << 24);
tgui->linear_size = tgui->vram_size;
svga->decode_mask = tgui->vram_mask;
svga->crtc[0x21] = (svga->crtc[0x21] & ~0xc0) | (val >> 6);
tgui_recalcmapping(tgui);
break;
@ -1204,7 +1227,8 @@ enum
{
TGUI_BITBLT = 1,
TGUI_SCANLINE = 3,
TGUI_BRESENHAMLINE = 4
TGUI_BRESENHAMLINE = 4,
TGUI_SHORTVECTOR = 5
};
enum
@ -1333,62 +1357,88 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui)
}
/*Other than mode stuff, this bit is undocumented*/
pclog("TGUI ger22 = %04x, cmd = %i, hdisp = %i, svga = %i, bpp = %i\n", tgui->accel.ger22, tgui->accel.command, svga->hdisp, svga->bpp, tgui->accel.bpp);
switch (tgui->accel.ger22 & 0xff) {
case 0:
switch (tgui->accel.ger22 >> 8) {
case 0x41:
tgui->accel.pitch = 640;
break;
}
break;
case 4:
tgui->accel.src_pitch = 1024;
tgui->accel.dst_pitch = 1024;
if (svga->hdisp == 800) {
if ((tgui->accel.ger22 >> 8) > 0) {
tgui->accel.src_pitch = 832;
tgui->accel.dst_pitch = 832;
}
}
break;
case 8:
tgui->accel.src_pitch = 2048;
tgui->accel.dst_pitch = 2048;
if (tgui->type >= TGUI_9660) {
tgui->accel.src_pitch = 1280;
tgui->accel.dst_pitch = 1280;
}
break;
case 9:
tgui->accel.src_pitch = 1024;
tgui->accel.dst_pitch = 1024;
if (tgui->type >= TGUI_9660) {
tgui->accel.src_pitch = svga->hdisp;
tgui->accel.dst_pitch = svga->hdisp;
if (svga->hdisp == 800) {
tgui->accel.src_pitch = 832;
tgui->accel.dst_pitch = 832;
}
}
break;
case 14:
tgui->accel.src_pitch = svga->hdisp;
tgui->accel.dst_pitch = svga->hdisp;
switch (tgui->svga.bpp) {
case 32:
if (svga->hdisp == 800) {
tgui->accel.src_pitch = 832;
tgui->accel.dst_pitch = 832;
switch (tgui->accel.ger22 >> 8) {
case 0:
tgui->accel.pitch = 1024;
break;
case 0x40:
tgui->accel.pitch = 640;
break;
case 0x50:
tgui->accel.pitch = 832;
break;
}
break;
case 8:
switch (tgui->accel.ger22 >> 8) {
case 0:
tgui->accel.pitch = 2048;
break;
case 0x60:
tgui->accel.pitch = 1280;
break;
}
break;
case 9:
switch (tgui->accel.ger22 >> 8) {
case 0:
tgui->accel.pitch = svga->hdisp;
if (tgui->type == TGUI_9440)
tgui->accel.pitch = 1024;
break;
case 0x40:
tgui->accel.pitch = 640;
break;
case 0x50:
tgui->accel.pitch = 832;
break;
}
break;
case 13:
switch (tgui->accel.ger22 >> 8) {
case 0x60:
tgui->accel.pitch = 2048;
if (tgui->type >= TGUI_9660) {
if (svga->hdisp == 1280)
tgui->accel.pitch = svga->hdisp;
}
break;
}
break;
case 14:
switch (tgui->accel.ger22 >> 8) {
case 0:
tgui->accel.pitch = 1024;
break;
case 0x40:
tgui->accel.pitch = 640;
break;
case 0x50:
tgui->accel.pitch = 832;
break;
}
break;
}
break;
}
switch (tgui->accel.command)
{
case TGUI_BITBLT:
if (count == -1) {
tgui->accel.src_old = tgui->accel.src_x + (tgui->accel.src_y * tgui->accel.src_pitch);
tgui->accel.src_old = tgui->accel.src_x + (tgui->accel.src_y * tgui->accel.pitch);
tgui->accel.src = tgui->accel.src_old;
tgui->accel.dst_old = tgui->accel.dst_x + (tgui->accel.dst_y * tgui->accel.dst_pitch);
tgui->accel.dst_old = tgui->accel.dst_x + (tgui->accel.dst_y * tgui->accel.pitch);
tgui->accel.dst = tgui->accel.dst_old;
tgui->accel.pat_x = tgui->accel.dst_x;
@ -1473,8 +1523,8 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui)
tgui->accel.dy += ydir;
}
tgui->accel.src_old += (ydir * tgui->accel.src_pitch);
tgui->accel.dst_old += (ydir * tgui->accel.dst_pitch);
tgui->accel.src_old += (ydir * tgui->accel.pitch);
tgui->accel.dst_old += (ydir * tgui->accel.pitch);
tgui->accel.src = tgui->accel.src_old;
tgui->accel.dst = tgui->accel.dst_old;
@ -1535,8 +1585,8 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui)
tgui->accel.pat_x = tgui->accel.dst_x;
tgui->accel.pat_y += ydir;
tgui->accel.src = tgui->accel.src_old = tgui->accel.src_old + (ydir * tgui->accel.src_pitch);
tgui->accel.dst = tgui->accel.dst_old = tgui->accel.dst_old + (ydir * tgui->accel.dst_pitch);
tgui->accel.src = tgui->accel.src_old = tgui->accel.src_old + (ydir * tgui->accel.pitch);
tgui->accel.dst = tgui->accel.dst_old = tgui->accel.dst_old + (ydir * tgui->accel.pitch);
tgui->accel.y++;
@ -1582,8 +1632,8 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui)
tgui->accel.pat_x = tgui->accel.dst_x;
tgui->accel.pat_y += ydir;
tgui->accel.src = tgui->accel.src_old = tgui->accel.src_old + (ydir * tgui->accel.src_pitch);
tgui->accel.dst = tgui->accel.dst_old = tgui->accel.dst_old + (ydir * tgui->accel.dst_pitch);
tgui->accel.src = tgui->accel.src_old = tgui->accel.src_old + (ydir * tgui->accel.pitch);
tgui->accel.dst = tgui->accel.dst_old = tgui->accel.dst_old + (ydir * tgui->accel.pitch);
if (tgui->accel.y > tgui->accel.size_y)
return;
@ -1596,10 +1646,10 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui)
case TGUI_SCANLINE:
{
if (count == -1) {
tgui->accel.src_old = tgui->accel.src_x + (tgui->accel.src_y * tgui->accel.src_pitch);
tgui->accel.src_old = tgui->accel.src_x + (tgui->accel.src_y * tgui->accel.pitch);
tgui->accel.src = tgui->accel.src_old;
tgui->accel.dst_old = tgui->accel.dst_x + (tgui->accel.dst_y * tgui->accel.dst_pitch);
tgui->accel.dst_old = tgui->accel.dst_x + (tgui->accel.dst_y * tgui->accel.pitch);
tgui->accel.dst = tgui->accel.dst_old;
tgui->accel.pat_x = tgui->accel.dst_x;
@ -1633,8 +1683,8 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui)
tgui->accel.x = 0;
tgui->accel.pat_x = tgui->accel.dst_x;
tgui->accel.src = tgui->accel.src_old = tgui->accel.src_old + (ydir * tgui->accel.src_pitch);
tgui->accel.dst = tgui->accel.dst_old = tgui->accel.dst_old + (ydir * tgui->accel.dst_pitch);
tgui->accel.src = tgui->accel.src_old = tgui->accel.src_old + (ydir * tgui->accel.pitch);
tgui->accel.dst = tgui->accel.dst_old = tgui->accel.dst_old + (ydir * tgui->accel.pitch);
tgui->accel.pat_y += ydir;
return;
}
@ -1691,13 +1741,13 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui)
}
while (count--) {
READ(tgui->accel.src_x + (tgui->accel.src_y * tgui->accel.src_pitch), src_dat);
READ(tgui->accel.src_x + (tgui->accel.src_y * tgui->accel.pitch), src_dat);
/*Note by TC1995: I suppose the x/y clipping max is always more than 0 in the TGUI 96xx, but the TGUI 9440 lacks clipping*/
if (steep) {
if ((tgui->type == TGUI_9440) || ((tgui->type >= TGUI_9660) && dx >= tgui->accel.left && dx <= tgui->accel.right &&
dy >= tgui->accel.top && dy <= tgui->accel.bottom)) {
READ(dx + (dy * tgui->accel.dst_pitch), dst_dat);
READ(dx + (dy * tgui->accel.pitch), dst_dat);
pat_dat = tgui->accel.fg_col;
@ -1708,12 +1758,12 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui)
MIX();
WRITE(dx + (dy * tgui->accel.dst_pitch), out);
WRITE(dx + (dy * tgui->accel.pitch), out);
}
} else {
if ((tgui->type == TGUI_9440) || ((tgui->type >= TGUI_9660) && dy >= tgui->accel.left && dy <= tgui->accel.right &&
dx >= tgui->accel.top && dx <= tgui->accel.bottom)) {
READ(dy + (dx * tgui->accel.dst_pitch), dst_dat);
dx >= tgui->accel.top && dx <= tgui->accel.bottom)) {
READ(dy + (dx * tgui->accel.pitch), dst_dat);
pat_dat = tgui->accel.fg_col;
@ -1724,7 +1774,7 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui)
MIX();
WRITE(dy + (dx * tgui->accel.dst_pitch), out);
WRITE(dy + (dx * tgui->accel.pitch), out);
}
}
@ -1742,13 +1792,92 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui)
}
}
break;
case TGUI_SHORTVECTOR:
{
int16_t dx, dy;
dx = tgui->accel.dst_x & 0xfff;
dy = tgui->accel.dst_y & 0xfff;
tgui->accel.left = tgui->accel.src_x_clip & 0xfff;
tgui->accel.right = tgui->accel.dst_x_clip & 0xfff;
tgui->accel.top = tgui->accel.src_y_clip & 0xfff;
tgui->accel.bottom = tgui->accel.dst_y_clip & 0xfff;
if (tgui->accel.bpp == 1) {
tgui->accel.left >>= 1;
tgui->accel.right >>= 1;
} else if (tgui->accel.bpp == 3) {
tgui->accel.left >>= 2;
tgui->accel.right >>= 2;
}
while (count--) {
READ(tgui->accel.src_x + (tgui->accel.src_y * tgui->accel.pitch), src_dat);
/*Note by TC1995: I suppose the x/y clipping max is always more than 0 in the TGUI 96xx, but the TGUI 9440 lacks clipping*/
if ((tgui->type == TGUI_9440) || ((tgui->type >= TGUI_9660) && dx >= tgui->accel.left && dx <= tgui->accel.right &&
dy >= tgui->accel.top && dy <= tgui->accel.bottom)) {
READ(dx + (dy * tgui->accel.pitch), dst_dat);
pat_dat = tgui->accel.fg_col;
if (tgui->accel.bpp == 0)
pat_dat &= 0xff;
else if (tgui->accel.bpp == 1)
pat_dat &= 0xffff;
MIX();
WRITE(dx + (dy * tgui->accel.pitch), out);
}
if (tgui->accel.y == (tgui->accel.sv_size_y & 0xfff))
break;
switch ((tgui->accel.sv_size_y >> 8) & 0xe0) {
case 0x00:
dx++;
break;
case 0x20:
dx++;
dy--;
break;
case 0x40:
dy--;
break;
case 0x60:
dx--;
dy--;
break;
case 0x80:
dx--;
break;
case 0xa0:
dx--;
dy++;
break;
case 0xc0:
dy++;
break;
case 0xe0:
dx++;
dy++;
break;
}
tgui->accel.y++;
}
}
break;
}
}
static void
tgui_accel_out(uint16_t addr, uint8_t val, void *p)
{
tgui_t *tgui = (tgui_t *)p;
tgui_t *tgui = (tgui_t *)p;
switch (addr)
{
@ -1764,6 +1893,7 @@ tgui_accel_out(uint16_t addr, uint8_t val, void *p)
tgui->accel.bpp = 1;
break;
case 13:
case 14:
switch (tgui->svga.bpp) {
case 15:
@ -1885,9 +2015,11 @@ tgui_accel_out(uint16_t addr, uint8_t val, void *p)
break;
case 0x2142: /*Size Y*/
tgui->accel.size_y = (tgui->accel.size_y & 0xff00) | val;
tgui->accel.sv_size_y = (tgui->accel.sv_size_y & 0xff00) | val;
break;
case 0x2143: /*Size Y*/
tgui->accel.size_y = (tgui->accel.size_y & 0xff) | (val << 8);
tgui->accel.sv_size_y = (tgui->accel.sv_size_y & 0xff) | (val << 8);
break;
case 0x2144: /*Style*/
@ -2186,8 +2318,8 @@ tgui_accel_in_l(uint16_t addr, void *p)
static void
tgui_accel_write(uint32_t addr, uint8_t val, void *p)
{
tgui_t *tgui = (tgui_t *)p;
svga_t *svga = &tgui->svga;
tgui_t *tgui = (tgui_t *)p;
svga_t *svga = &tgui->svga;
if ((svga->crtc[0x36] & 0x03) == 0x02) {
if ((addr & ~0xff) != 0xbff00)
@ -2211,6 +2343,7 @@ tgui_accel_write(uint32_t addr, uint8_t val, void *p)
tgui->accel.bpp = 1;
break;
case 13:
case 14:
switch (tgui->svga.bpp) {
case 15:
@ -2332,9 +2465,11 @@ tgui_accel_write(uint32_t addr, uint8_t val, void *p)
break;
case 0x42: /*Size Y*/
tgui->accel.size_y = (tgui->accel.size_y & 0xff00) | val;
tgui->accel.sv_size_y = (tgui->accel.sv_size_y & 0xff00) | val;
break;
case 0x43: /*Size Y*/
tgui->accel.size_y = (tgui->accel.size_y & 0xff) | (val << 8);
tgui->accel.sv_size_y = (tgui->accel.sv_size_y & 0xff) | (val << 8);
break;
case 0x44: /*Style*/
@ -2858,7 +2993,7 @@ static void *tgui_init(const device_t *info)
if (tgui->pci && (tgui->type >= TGUI_9440))
tgui->card = pci_add_card(PCI_ADD_VIDEO, tgui_pci_read, tgui_pci_write, tgui);
tgui->pci_regs[PCI_REG_COMMAND] = 3;
tgui->pci_regs[PCI_REG_COMMAND] = 7;
tgui->pci_regs[0x30] = 0x00;
tgui->pci_regs[0x32] = 0x0c;
@ -2866,11 +3001,6 @@ static void *tgui_init(const device_t *info)
if (tgui->type >= TGUI_9440)
svga->packed_chain4 = 1;
if (tgui->type >= TGUI_9660) {
tgui->i2c = i2c_gpio_init("ddc_tgui");
tgui->ddc = ddc_init(i2c_gpio_get_bus(tgui->i2c));
}
return tgui;
}
@ -2896,11 +3026,6 @@ void tgui_close(void *p)
svga_close(&tgui->svga);
if (tgui->type >= TGUI_9660) {
ddc_close(tgui->ddc);
i2c_gpio_close(tgui->i2c);
}
free(tgui);
}

View file

@ -0,0 +1,472 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Emulation of the Texas Instruments TVP3026 true colour RAMDAC
* family.
*
*
* TODO: Clock and other parts.
*
* Authors: TheCollector1995,
*
* Copyright 2021 TheCollector1995.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/mem.h>
#include <86box/timer.h>
#include <86box/video.h>
#include <86box/vid_svga.h>
typedef struct
{
PALETTE extpal;
uint32_t extpallook[256];
uint8_t cursor64_data[1024];
int hwc_y, hwc_x;
uint8_t ind_idx;
uint8_t dcc, dc_init;
uint8_t ccr;
uint8_t true_color;
uint8_t latch_cntl;
uint8_t mcr;
uint8_t ppr;
uint8_t general_cntl;
uint8_t mclk;
uint8_t misc;
uint8_t type;
uint8_t mode;
} tvp3026_ramdac_t;
static void
tvp3026_set_bpp(tvp3026_ramdac_t *ramdac, svga_t *svga)
{
if ((ramdac->true_color & 0x80) == 0x80) {
if (ramdac->mcr & 0x08)
svga->bpp = 8;
else
svga->bpp = 4;
} else {
switch (ramdac->true_color & 0x0f) {
case 0x01:
case 0x03:
case 0x05:
svga->bpp = 16;
break;
case 0x04:
svga->bpp = 15;
break;
case 0x06:
case 0x07:
if (ramdac->true_color & 0x10)
svga->bpp = 24;
else
svga->bpp = 32;
break;
case 0x0e:
case 0x0f:
svga->bpp = 24;
break;
}
}
svga_recalctimings(svga);
}
void
tvp3026_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *p, svga_t *svga)
{
tvp3026_ramdac_t *ramdac = (tvp3026_ramdac_t *) p;
uint32_t o32;
uint8_t *cd;
uint16_t index;
uint8_t rs = (addr & 0x03);
uint16_t da_mask = 0x03ff;
rs |= (!!rs2 << 2);
rs |= (!!rs3 << 3);
switch (rs) {
case 0x00: /* Palette Write Index Register (RS value = 0000) */
ramdac->ind_idx = val;
case 0x04: /* Ext Palette Write Index Register (RS value = 0100) */
case 0x03:
case 0x07: /* Ext Palette Read Index Register (RS value = 0111) */
svga->dac_pos = 0;
svga->dac_status = addr & 0x03;
svga->dac_addr = val;
if (svga->dac_status)
svga->dac_addr = (svga->dac_addr + 1) & da_mask;
break;
case 0x01: /* Palette Data Register (RS value = 0001) */
case 0x02: /* Pixel Read Mask Register (RS value = 0010) */
svga_out(addr, val, svga);
break;
case 0x05: /* Ext Palette Data Register (RS value = 0101) */
svga->dac_status = 0;
svga->fullchange = changeframecount;
switch (svga->dac_pos) {
case 0:
svga->dac_r = val;
svga->dac_pos++;
break;
case 1:
svga->dac_g = val;
svga->dac_pos++;
break;
case 2:
index = svga->dac_addr & 3;
ramdac->extpal[index].r = svga->dac_r;
ramdac->extpal[index].g = svga->dac_g;
ramdac->extpal[index].b = val;
if (svga->ramdac_type == RAMDAC_8BIT)
ramdac->extpallook[index] = makecol32(ramdac->extpal[index].r, ramdac->extpal[index].g, ramdac->extpal[index].b);
else
ramdac->extpallook[index] = makecol32(video_6to8[ramdac->extpal[index].r & 0x3f], video_6to8[ramdac->extpal[index].g & 0x3f], video_6to8[ramdac->extpal[index].b & 0x3f]);
if (svga->ext_overscan && !index) {
o32 = svga->overscan_color;
svga->overscan_color = ramdac->extpallook[0];
if (o32 != svga->overscan_color)
svga_recalctimings(svga);
}
svga->dac_addr = (svga->dac_addr + 1) & 0xff;
svga->dac_pos = 0;
break;
}
break;
case 0x09: /* Direct Cursor Control (RS value = 1001) */
ramdac->dcc = val;
if (ramdac->ccr & 0x80) {
svga->dac_hwcursor.xsize = svga->dac_hwcursor.ysize = 64;
svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.xsize;
svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.ysize;
svga->dac_hwcursor.ena = ((val & 0x03) != 0);
ramdac->mode = val & 0x03;
}
break;
case 0x0a: /* Indexed Data (RS value = 1010) */
switch (ramdac->ind_idx) {
case 0x06: /* Indirect Cursor Control */
ramdac->ccr = val;
svga->dac_hwcursor.xsize = svga->dac_hwcursor.ysize = 64;
svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.xsize;
svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.ysize;
svga->dac_hwcursor.ena = ((val & 0x03) != 0);
ramdac->mode = val & 0x03;
break;
case 0x0f: /* Latch Control */
ramdac->latch_cntl = val;
break;
case 0x18: /* True Color Control */
ramdac->true_color = val;
tvp3026_set_bpp(ramdac, svga);
break;
case 0x19: /* Multiplex Control */
ramdac->mcr = val;
tvp3026_set_bpp(ramdac, svga);
break;
case 0x1c: /* Palette-Page Register */
ramdac->ppr = val;
break;
case 0x1d: /* General Control Register */
ramdac->general_cntl = val;
break;
case 0x1e: /* Miscellaneous Control */
ramdac->misc = val;
svga->ramdac_type = (val & 0x08) ? RAMDAC_8BIT : RAMDAC_6BIT;
break;
case 0x39: /* MCLK/Loop Clock Control */
ramdac->mclk = val;
break;
}
break;
case 0x0b: /* Cursor RAM Data Register (RS value = 1011) */
index = svga->dac_addr & da_mask;
cd = (uint8_t *) ramdac->cursor64_data;
cd[index] = val;
svga->dac_addr = (svga->dac_addr + 1) & da_mask;
break;
case 0x0c: /* Cursor X Low Register (RS value = 1100) */
ramdac->hwc_x = (ramdac->hwc_x & 0x0f00) | val;
svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.xsize;
break;
case 0x0d: /* Cursor X High Register (RS value = 1101) */
ramdac->hwc_x = (ramdac->hwc_x & 0x00ff) | ((val & 0x0f) << 8);
svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.xsize;
break;
case 0x0e: /* Cursor Y Low Register (RS value = 1110) */
ramdac->hwc_y = (ramdac->hwc_y & 0x0f00) | val;
svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.ysize;
break;
case 0x0f: /* Cursor Y High Register (RS value = 1111) */
ramdac->hwc_y = (ramdac->hwc_y & 0x00ff) | ((val & 0x0f) << 8);
svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.ysize;
break;
}
return;
}
uint8_t
tvp3026_ramdac_in(uint16_t addr, int rs2, int rs3, void *p, svga_t *svga)
{
tvp3026_ramdac_t *ramdac = (tvp3026_ramdac_t *) p;
uint8_t temp = 0xff;
uint8_t *cd;
uint16_t index;
uint8_t rs = (addr & 0x03);
uint16_t da_mask = 0x03ff;
rs |= (!!rs2 << 2);
rs |= (!!rs3 << 3);
switch (rs) {
case 0x00: /* Palette Write Index Register (RS value = 0000) */
case 0x01: /* Palette Data Register (RS value = 0001) */
case 0x02: /* Pixel Read Mask Register (RS value = 0010) */
case 0x04: /* Ext Palette Write Index Register (RS value = 0100) */
temp = svga_in(addr, svga);
break;
case 0x03: /* Palette Read Index Register (RS value = 0011) */
case 0x07: /* Ext Palette Read Index Register (RS value = 0111) */
temp = svga->dac_addr & 0xff;
break;
case 0x05: /* Ext Palette Data Register (RS value = 0101) */
index = (svga->dac_addr - 1) & 3;
svga->dac_status = 3;
switch (svga->dac_pos) {
case 0:
svga->dac_pos++;
if (svga->ramdac_type == RAMDAC_8BIT)
temp = ramdac->extpal[index].r;
else
temp = ramdac->extpal[index].r & 0x3f;
break;
case 1:
svga->dac_pos++;
if (svga->ramdac_type == RAMDAC_8BIT)
temp = ramdac->extpal[index].g;
else
temp = ramdac->extpal[index].g & 0x3f;
break;
case 2:
svga->dac_pos=0;
svga->dac_addr = svga->dac_addr + 1;
if (svga->ramdac_type == RAMDAC_8BIT)
temp = ramdac->extpal[index].b;
else
temp = ramdac->extpal[index].b & 0x3f;
break;
}
break;
case 0x09: /* Direct Cursor Control (RS value = 1001) */
temp = ramdac->dcc;
break;
case 0x0a: /* Indexed Data (RS value = 1010) */
switch (ramdac->ind_idx) {
case 0x01: /* Silicon Revision */
temp = 0x00;
break;
case 0x06: /* Indirect Cursor Control */
temp = ramdac->ccr;
break;
case 0x0f: /* Latch Control */
temp = ramdac->latch_cntl;
break;
case 0x18: /* True Color Control */
temp = ramdac->true_color;
break;
case 0x19: /* Multiplex Control */
temp = ramdac->mcr;
break;
case 0x1c: /* Palette-Page Register */
temp = ramdac->ppr;
break;
case 0x1d: /* General Control Register */
temp = ramdac->general_cntl;
break;
case 0x1e: /* Miscellaneous Control */
temp = ramdac->misc;
break;
case 0x39: /* MCLK/Loop Clock Control */
temp = ramdac->mclk;
break;
case 0x3f: /* ID */
temp = 0x26;
break;
}
break;
case 0x0b: /* Cursor RAM Data Register (RS value = 1011) */
index = (svga->dac_addr - 1) & da_mask;
cd = (uint8_t *) ramdac->cursor64_data;
temp = cd[index];
svga->dac_addr = (svga->dac_addr + 1) & da_mask;
break;
case 0x0c: /* Cursor X Low Register (RS value = 1100) */
temp = ramdac->hwc_x & 0xff;
break;
case 0x0d: /* Cursor X High Register (RS value = 1101) */
temp = (ramdac->hwc_x >> 8) & 0xff;
break;
case 0x0e: /* Cursor Y Low Register (RS value = 1110) */
temp = ramdac->hwc_y & 0xff;
break;
case 0x0f: /* Cursor Y High Register (RS value = 1111) */
temp = (ramdac->hwc_y >> 8) & 0xff;
break;
}
return temp;
}
void
tvp3026_recalctimings(void *p, svga_t *svga)
{
tvp3026_ramdac_t *ramdac = (tvp3026_ramdac_t *) p;
svga->interlace = (ramdac->ccr & 0x40);
}
void
tvp3026_hwcursor_draw(svga_t *svga, int displine)
{
int x, xx, comb, b0, b1;
uint16_t dat[2];
int offset = svga->dac_hwcursor_latch.x + svga->dac_hwcursor_latch.xoff;
int pitch, bppl, mode, x_pos, y_pos;
uint32_t clr1, clr2, clr3, *p;
uint8_t *cd;
tvp3026_ramdac_t *ramdac = (tvp3026_ramdac_t *) svga->ramdac;
clr1 = ramdac->extpallook[1];
clr2 = ramdac->extpallook[2];
clr3 = ramdac->extpallook[3];
/* The planes come in two parts, and each plane is 1bpp,
so a 32x32 cursor has 4 bytes per line, and a 64x64
cursor has 8 bytes per line. */
pitch = (svga->dac_hwcursor_latch.xsize >> 3); /* Bytes per line. */
/* A 32x32 cursor has 128 bytes per line, and a 64x64
cursor has 512 bytes per line. */
bppl = (pitch * svga->dac_hwcursor_latch.ysize); /* Bytes per plane. */
mode = ramdac->mode;
if (svga->interlace && svga->dac_hwcursor_oddeven)
svga->dac_hwcursor_latch.addr += pitch;
cd = (uint8_t *) ramdac->cursor64_data;
for (x = 0; x < svga->dac_hwcursor_latch.xsize; x += 16) {
dat[0] = (cd[svga->dac_hwcursor_latch.addr] << 8) |
cd[svga->dac_hwcursor_latch.addr + 1];
dat[1] = (cd[svga->dac_hwcursor_latch.addr + bppl] << 8) |
cd[svga->dac_hwcursor_latch.addr + bppl + 1];
for (xx = 0; xx < 16; xx++) {
b0 = (dat[0] >> (15 - xx)) & 1;
b1 = (dat[1] >> (15 - xx)) & 1;
comb = (b0 | (b1 << 1));
y_pos = displine;
x_pos = offset + svga->x_add;
p = buffer32->line[y_pos];
if (offset >= svga->dac_hwcursor_latch.x) {
switch (mode) {
case 1: /* Three Color */
switch (comb) {
case 1:
p[x_pos] = clr1;
break;
case 2:
p[x_pos] = clr2;
break;
case 3:
p[x_pos] = clr3;
break;
}
break;
case 2: /* XGA */
switch (comb) {
case 0:
p[x_pos] = clr1;
break;
case 1:
p[x_pos] = clr2;
break;
case 3:
p[x_pos] ^= 0xffffff;
break;
}
break;
case 3: /* X-Windows */
switch (comb) {
case 2:
p[x_pos] = clr1;
break;
case 3:
p[x_pos] = clr2;
break;
}
break;
}
}
offset++;
}
svga->dac_hwcursor_latch.addr += 2;
}
if (svga->interlace && !svga->dac_hwcursor_oddeven)
svga->dac_hwcursor_latch.addr += pitch;
}
void *
tvp3026_ramdac_init(const device_t *info)
{
tvp3026_ramdac_t *ramdac = (tvp3026_ramdac_t *) malloc(sizeof(tvp3026_ramdac_t));
memset(ramdac, 0, sizeof(tvp3026_ramdac_t));
ramdac->type = info->local;
ramdac->latch_cntl = 0x06;
ramdac->true_color = 0x80;
ramdac->mcr = 0x98;
ramdac->mclk = 0x18;
return ramdac;
}
static void
tvp3026_ramdac_close(void *priv)
{
tvp3026_ramdac_t *ramdac = (tvp3026_ramdac_t *) priv;
if (ramdac)
free(ramdac);
}
const device_t tvp3026_ramdac_device =
{
"TI TVP3026 RAMDAC",
0, 0,
tvp3026_ramdac_init, tvp3026_ramdac_close,
NULL, { NULL }, NULL, NULL
};

View file

@ -1237,23 +1237,7 @@ void *voodoo_init()
void voodoo_card_close(voodoo_t *voodoo)
{
/* #ifndef RELEASE_BUILD
FILE *f;
#endif */
int c;
/* #ifndef RELEASE_BUILD
f = rom_fopen("texram.dmp", "wb");
fwrite(voodoo->tex_mem[0], voodoo->texture_size*1024*1024, 1, f);
fclose(f);
if (voodoo->dual_tmus)
{
f = rom_fopen("texram2.dmp", "wb");
fwrite(voodoo->tex_mem[1], voodoo->texture_size*1024*1024, 1, f);
fclose(f);
}
#endif */
voodoo->fifo_thread_run = 0;
thread_set_event(voodoo->wake_fifo_thread);

View file

@ -779,7 +779,8 @@ VIDOBJ := video.o \
vid_s3.o vid_s3_virge.o \
vid_ibm_rgb528_ramdac.o vid_sdac_ramdac.o \
vid_ogc.o \
vid_nga.o
vid_nga.o \
vid_tvp3026_ramdac.o
VOODOOOBJ := vid_voodoo.o vid_voodoo_banshee.o \
vid_voodoo_banshee_blitter.o \
@ -838,7 +839,7 @@ LIBS += -static
ifeq ($(AUTODEP), y)
%.o: %.c
@echo $<
$(CC) $(CFLAGS) $(DEPS) -c $<
@$(CC) $(CFLAGS) $(DEPS) -c $<
%.o: %.cc
@echo $<

View file

@ -288,7 +288,8 @@ sdl_destroy_texture(void)
void
sdl_close(void)
{
SDL_LockMutex(sdl_mutex);
if (sdl_mutex != NULL)
SDL_LockMutex(sdl_mutex);
/* Unregister our renderer! */
video_setblit(NULL);