Merge branch 'master' of https://github.com/starfrost013/86box
@@ -1293,6 +1293,8 @@ pc_reset_hard_init(void)
|
||||
* modules that are.
|
||||
*/
|
||||
|
||||
keyboard_init();
|
||||
|
||||
/* Reset the IDE and SCSI presences */
|
||||
other_ide_present = other_scsi_present = 0;
|
||||
|
||||
|
||||
@@ -723,7 +723,11 @@ host_x86_MOV8_REG_ABS(codeblock_t *block, int dst_reg, void *p)
|
||||
codegen_addbyte4(block, 0x41, 0x8a, 0x84 | ((dst_reg & 7) << 3), 0x24); /*MOV dst_reg, ram_offset[R12]*/
|
||||
codegen_addlong(block, ram_offset);
|
||||
} else {
|
||||
fatal("host_x86_MOV8_REG_ABS - out of range\n");
|
||||
codegen_alloc_bytes(block, 10);
|
||||
codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, p*/
|
||||
codegen_addquad(block, (uintptr_t) p);
|
||||
codegen_alloc_bytes(block, 3);
|
||||
codegen_addbyte3(block, 0x41, 0x8a, 0x01 | ((dst_reg & 7) << 3)); /*MOV dst_reg, [R9]*/
|
||||
}
|
||||
}
|
||||
void
|
||||
|
||||
11
src/config.c
@@ -192,12 +192,6 @@ load_general(void)
|
||||
else if (mouse_sensitivity > 2.0)
|
||||
mouse_sensitivity = 2.0;
|
||||
|
||||
p = ini_section_get_string(cat, "iconset", NULL);
|
||||
if (p != NULL)
|
||||
strcpy(icon_set, p);
|
||||
else
|
||||
strcpy(icon_set, "");
|
||||
|
||||
enable_discord = !!ini_section_get_int(cat, "enable_discord", 0);
|
||||
|
||||
open_dir_usr_path = ini_section_get_int(cat, "open_dir_usr_path", 0);
|
||||
@@ -2038,11 +2032,6 @@ save_general(void)
|
||||
ini_section_set_string(cat, "language", buffer);
|
||||
}
|
||||
|
||||
if (!strcmp(icon_set, ""))
|
||||
ini_section_delete_var(cat, "iconset");
|
||||
else
|
||||
ini_section_set_string(cat, "iconset", icon_set);
|
||||
|
||||
if (enable_discord)
|
||||
ini_section_set_int(cat, "enable_discord", enable_discord);
|
||||
else
|
||||
|
||||
290
src/cpu/8080.c
@@ -1,290 +0,0 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* 8080 CPU emulation.
|
||||
*
|
||||
* Authors: Cacodemon345
|
||||
*
|
||||
* Copyright 2022 Cacodemon345
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "cpu.h"
|
||||
#include <86box/timer.h>
|
||||
#include <86box/i8080.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/plat_unused.h>
|
||||
|
||||
static int completed = 1;
|
||||
static int in_rep = 0;
|
||||
static int repeating = 0;
|
||||
static int rep_c_flag = 0;
|
||||
static int oldc;
|
||||
static int cycdiff;
|
||||
#ifdef UNUSED_8080_VARS
|
||||
static int prefetching = 1;
|
||||
static int refresh = 0;
|
||||
static int clear_lock = 0;
|
||||
|
||||
static uint32_t cpu_src = 0;
|
||||
static uint32_t cpu_dest = 0;
|
||||
static uint32_t cpu_data = 0;
|
||||
#endif
|
||||
|
||||
static void
|
||||
clock_start(void)
|
||||
{
|
||||
cycdiff = cycles;
|
||||
}
|
||||
|
||||
static void
|
||||
clock_end(void)
|
||||
{
|
||||
int diff = cycdiff - cycles;
|
||||
|
||||
/* On 808x systems, clock speed is usually crystal frequency divided by an integer. */
|
||||
tsc += (uint64_t) diff * (xt_cpu_multi >> 32ULL); /* Shift xt_cpu_multi by 32 bits to the right and then multiply. */
|
||||
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc))
|
||||
timer_process();
|
||||
}
|
||||
|
||||
static void
|
||||
i8080_wait(int c, int bus)
|
||||
{
|
||||
cycles -= c;
|
||||
if (bus < 2) {
|
||||
clock_end();
|
||||
clock_start();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UNUSED_8080_FUNCS
|
||||
static uint8_t
|
||||
readmemb(uint32_t a)
|
||||
{
|
||||
uint8_t ret;
|
||||
|
||||
i8080_wait(4, 1);
|
||||
ret = read_mem_b(a);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
ins_fetch(i8080 *cpu)
|
||||
{
|
||||
uint8_t ret = cpu->readmembyte(cpu->pmembase + cpu->pc);
|
||||
|
||||
cpu->pc++;
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
transfer_from_808x(i8080 *cpu)
|
||||
{
|
||||
cpu->hl = BX;
|
||||
cpu->bc = CX;
|
||||
cpu->de = DX;
|
||||
cpu->a = AL;
|
||||
cpu->flags = cpu_state.flags & 0xFF;
|
||||
cpu->sp = BP;
|
||||
cpu->pc = cpu_state.pc;
|
||||
cpu->oldpc = cpu_state.oldpc;
|
||||
cpu->pmembase = cs;
|
||||
cpu->dmembase = ds;
|
||||
}
|
||||
|
||||
void
|
||||
transfer_to_808x(i8080 *cpu)
|
||||
{
|
||||
BX = cpu->hl;
|
||||
CX = cpu->bc;
|
||||
DX = cpu->de;
|
||||
AL = cpu->a;
|
||||
cpu_state.flags &= 0xFF00;
|
||||
cpu_state.flags |= cpu->flags & 0xFF;
|
||||
BP = cpu->sp;
|
||||
cpu_state.pc = cpu->pc;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
getreg_i8080(i8080 *cpu, uint8_t reg)
|
||||
{
|
||||
uint8_t ret = 0xFF;
|
||||
switch (reg) {
|
||||
case 0x0:
|
||||
ret = cpu->b;
|
||||
break;
|
||||
case 0x1:
|
||||
ret = cpu->c;
|
||||
break;
|
||||
case 0x2:
|
||||
ret = cpu->d;
|
||||
break;
|
||||
case 0x3:
|
||||
ret = cpu->e;
|
||||
break;
|
||||
case 0x4:
|
||||
ret = cpu->h;
|
||||
break;
|
||||
case 0x5:
|
||||
ret = cpu->l;
|
||||
break;
|
||||
case 0x6:
|
||||
ret = cpu->readmembyte(cpu->dmembase + cpu->sp);
|
||||
break;
|
||||
case 0x7:
|
||||
ret = cpu->a;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
getreg_i8080_emu(i8080 *cpu, uint8_t reg)
|
||||
{
|
||||
uint8_t ret = 0xFF;
|
||||
switch (reg) {
|
||||
case 0x0:
|
||||
ret = CH;
|
||||
break;
|
||||
case 0x1:
|
||||
ret = CL;
|
||||
break;
|
||||
case 0x2:
|
||||
ret = DH;
|
||||
break;
|
||||
case 0x3:
|
||||
ret = DL;
|
||||
break;
|
||||
case 0x4:
|
||||
ret = BH;
|
||||
break;
|
||||
case 0x5:
|
||||
ret = BL;
|
||||
break;
|
||||
case 0x6:
|
||||
ret = cpu->readmembyte(cpu->dmembase + BP);
|
||||
break;
|
||||
case 0x7:
|
||||
ret = AL;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
setreg_i8080_emu(i8080 *cpu, uint8_t reg, uint8_t val)
|
||||
{
|
||||
switch (reg) {
|
||||
case 0x0:
|
||||
CH = val;
|
||||
break;
|
||||
case 0x1:
|
||||
CL = val;
|
||||
break;
|
||||
case 0x2:
|
||||
DH = val;
|
||||
break;
|
||||
case 0x3:
|
||||
DL = val;
|
||||
break;
|
||||
case 0x4:
|
||||
BH = val;
|
||||
break;
|
||||
case 0x5:
|
||||
BL = val;
|
||||
break;
|
||||
case 0x6:
|
||||
cpu->writemembyte(cpu->dmembase + BP, val);
|
||||
break;
|
||||
case 0x7:
|
||||
AL = val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
setreg_i8080(i8080 *cpu, uint8_t reg, uint8_t val)
|
||||
{
|
||||
switch (reg) {
|
||||
case 0x0:
|
||||
cpu->b = val;
|
||||
break;
|
||||
case 0x1:
|
||||
cpu->c = val;
|
||||
break;
|
||||
case 0x2:
|
||||
cpu->d = val;
|
||||
break;
|
||||
case 0x3:
|
||||
cpu->e = val;
|
||||
break;
|
||||
case 0x4:
|
||||
cpu->h = val;
|
||||
break;
|
||||
case 0x5:
|
||||
cpu->l = val;
|
||||
break;
|
||||
case 0x6:
|
||||
cpu->writemembyte(cpu->dmembase + cpu->sp, val);
|
||||
break;
|
||||
case 0x7:
|
||||
cpu->a = val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
interpret_exec8080(UNUSED(i8080 *cpu), uint8_t opcode)
|
||||
{
|
||||
switch (opcode) {
|
||||
case 0x00:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Actually implement i8080 emulation. */
|
||||
void
|
||||
exec8080(i8080 *cpu, int cycs)
|
||||
{
|
||||
#ifdef UNUSED_8080_VARS
|
||||
uint8_t temp = 0, temp2;
|
||||
uint8_t old_af;
|
||||
uint8_t handled = 0;
|
||||
uint16_t addr, tempw;
|
||||
uint16_t new_ip;
|
||||
int bits;
|
||||
#endif
|
||||
|
||||
cycles += cycs;
|
||||
|
||||
while (cycles > 0) {
|
||||
cpu->startclock();
|
||||
|
||||
if (!repeating) {
|
||||
cpu->oldpc = cpu->pc;
|
||||
opcode = cpu->fetchinstruction(cpu);
|
||||
oldc = cpu->flags & C_FLAG_I8080;
|
||||
i8080_wait(1, 0);
|
||||
}
|
||||
completed = 1;
|
||||
if (completed) {
|
||||
repeating = 0;
|
||||
in_rep = 0;
|
||||
rep_c_flag = 0;
|
||||
cpu->endclock();
|
||||
if (cpu->checkinterrupts)
|
||||
cpu->checkinterrupts();
|
||||
}
|
||||
}
|
||||
}
|
||||
186
src/cpu/808x.c
@@ -18,10 +18,13 @@
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "i8080.h"
|
||||
|
||||
#define HAVE_STDARG_H
|
||||
#include <86box/86box.h>
|
||||
#include "cpu.h"
|
||||
@@ -70,6 +73,9 @@ static int in_rep = 0, repeating = 0, rep_c_flag = 0;
|
||||
static int oldc, clear_lock = 0;
|
||||
static int refresh = 0, cycdiff;
|
||||
|
||||
static i8080 emulated_processor;
|
||||
static bool cpu_md_write_disable = 1;
|
||||
|
||||
/* Various things needed for 8087. */
|
||||
#define OP_TABLE(name) ops_##name
|
||||
|
||||
@@ -195,6 +201,56 @@ prefetch_queue_get_size(void)
|
||||
{
|
||||
return pfq_size;
|
||||
}
|
||||
static void set_if(int cond);
|
||||
|
||||
void
|
||||
sync_from_i8080(void)
|
||||
{
|
||||
AL = emulated_processor.a;
|
||||
BH = emulated_processor.h;
|
||||
BL = emulated_processor.l;
|
||||
CH = emulated_processor.b;
|
||||
CL = emulated_processor.c;
|
||||
DH = emulated_processor.d;
|
||||
DL = emulated_processor.e;
|
||||
BP = emulated_processor.sp;
|
||||
|
||||
cpu_state.pc = emulated_processor.pc;
|
||||
cpu_state.flags &= 0xFF00;
|
||||
cpu_state.flags |= emulated_processor.sf << 7;
|
||||
cpu_state.flags |= emulated_processor.zf << 6;
|
||||
cpu_state.flags |= emulated_processor.hf << 4;
|
||||
cpu_state.flags |= emulated_processor.pf << 2;
|
||||
cpu_state.flags |= 1 << 1;
|
||||
cpu_state.flags |= emulated_processor.cf << 0;
|
||||
set_if(emulated_processor.iff);
|
||||
}
|
||||
|
||||
void
|
||||
sync_to_i8080(void)
|
||||
{
|
||||
if (!is_nec)
|
||||
return;
|
||||
emulated_processor.a = AL;
|
||||
emulated_processor.h = BH;
|
||||
emulated_processor.l = BL;
|
||||
emulated_processor.b = CH;
|
||||
emulated_processor.c = CL;
|
||||
emulated_processor.d = DH;
|
||||
emulated_processor.e = DL;
|
||||
emulated_processor.sp = BP;
|
||||
emulated_processor.pc = cpu_state.pc;
|
||||
emulated_processor.iff = !!(cpu_state.flags & I_FLAG);
|
||||
|
||||
emulated_processor.sf = (cpu_state.flags >> 7) & 1;
|
||||
emulated_processor.zf = (cpu_state.flags >> 6) & 1;
|
||||
emulated_processor.hf = (cpu_state.flags >> 4) & 1;
|
||||
emulated_processor.pf = (cpu_state.flags >> 2) & 1;
|
||||
emulated_processor.cf = (cpu_state.flags >> 0) & 1;
|
||||
|
||||
emulated_processor.interrupt_delay = noint;
|
||||
}
|
||||
|
||||
|
||||
uint16_t
|
||||
get_last_addr(void)
|
||||
@@ -582,6 +638,33 @@ load_seg(uint16_t seg, x86seg *s)
|
||||
s->seg = seg & 0xffff;
|
||||
}
|
||||
|
||||
uint8_t fetch_i8080_opcode(UNUSED(void* priv), uint16_t addr)
|
||||
{
|
||||
return readmemb(cs + addr);
|
||||
}
|
||||
|
||||
uint8_t fetch_i8080_data(UNUSED(void* priv), uint16_t addr)
|
||||
{
|
||||
return readmemb(ds + addr);
|
||||
}
|
||||
|
||||
void put_i8080_data(UNUSED(void* priv), uint16_t addr, uint8_t val)
|
||||
{
|
||||
writememb(ds, addr, val);
|
||||
}
|
||||
|
||||
static uint8_t i8080_port_in(UNUSED(void* priv), uint8_t port)
|
||||
{
|
||||
cpu_io(8, 0, port);
|
||||
return AL;
|
||||
}
|
||||
|
||||
static void i8080_port_out(UNUSED(void* priv), uint8_t port, uint8_t val)
|
||||
{
|
||||
AL = val;
|
||||
cpu_io(8, 1, port);
|
||||
}
|
||||
|
||||
void
|
||||
reset_808x(int hard)
|
||||
{
|
||||
@@ -619,6 +702,14 @@ reset_808x(int hard)
|
||||
|
||||
use_custom_nmi_vector = 0x00;
|
||||
custom_nmi_vector = 0x00000000;
|
||||
|
||||
cpu_md_write_disable = 1;
|
||||
i8080_init(&emulated_processor);
|
||||
emulated_processor.write_byte = put_i8080_data;
|
||||
emulated_processor.read_byte = fetch_i8080_data;
|
||||
emulated_processor.read_byte_seg = fetch_i8080_opcode;
|
||||
emulated_processor.port_in = i8080_port_in;
|
||||
emulated_processor.port_out = i8080_port_out;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -994,6 +1085,11 @@ interrupt(uint16_t addr)
|
||||
uint16_t new_cs, new_ip;
|
||||
uint16_t tempf;
|
||||
|
||||
if (!(cpu_state.flags & MD_FLAG) && is_nec) {
|
||||
sync_from_i8080();
|
||||
x808x_log("CALLN/INT#/NMI#\n");
|
||||
}
|
||||
|
||||
addr <<= 2;
|
||||
cpu_state.eaaddr = addr;
|
||||
old_cs = CS;
|
||||
@@ -1010,6 +1106,8 @@ interrupt(uint16_t addr)
|
||||
tempf = cpu_state.flags & (is_nec ? 0x8fd7 : 0x0fd7);
|
||||
push(&tempf);
|
||||
cpu_state.flags &= ~(I_FLAG | T_FLAG);
|
||||
if (is_nec)
|
||||
cpu_state.flags |= MD_FLAG;
|
||||
access(40, 16);
|
||||
push(&old_cs);
|
||||
old_ip = cpu_state.pc;
|
||||
@@ -1020,6 +1118,65 @@ interrupt(uint16_t addr)
|
||||
push(&old_ip);
|
||||
}
|
||||
|
||||
/* Ditto, but for breaking into emulation mode. */
|
||||
static void
|
||||
interrupt_brkem(uint16_t addr)
|
||||
{
|
||||
uint16_t old_cs, old_ip;
|
||||
uint16_t new_cs, new_ip;
|
||||
uint16_t tempf;
|
||||
|
||||
addr <<= 2;
|
||||
cpu_state.eaaddr = addr;
|
||||
old_cs = CS;
|
||||
access(5, 16);
|
||||
new_ip = readmemw(0, cpu_state.eaaddr);
|
||||
wait(1, 0);
|
||||
cpu_state.eaaddr = (cpu_state.eaaddr + 2) & 0xffff;
|
||||
access(6, 16);
|
||||
new_cs = readmemw(0, cpu_state.eaaddr);
|
||||
prefetching = 0;
|
||||
pfq_clear();
|
||||
ovr_seg = NULL;
|
||||
access(39, 16);
|
||||
tempf = cpu_state.flags & (is_nec ? 0x8fd7 : 0x0fd7);
|
||||
push(&tempf);
|
||||
cpu_state.flags &= ~(MD_FLAG);
|
||||
cpu_md_write_disable = 0;
|
||||
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);
|
||||
sync_to_i8080();
|
||||
x808x_log("BRKEM mode\n");
|
||||
}
|
||||
|
||||
void
|
||||
retem_i8080(void)
|
||||
{
|
||||
sync_from_i8080();
|
||||
|
||||
prefetching = 0;
|
||||
pfq_clear();
|
||||
|
||||
set_ip(pop());
|
||||
load_cs(pop());
|
||||
cpu_state.flags = pop();
|
||||
|
||||
emulated_processor.iff = !!(cpu_state.flags & I_FLAG);
|
||||
|
||||
cpu_md_write_disable = 1;
|
||||
|
||||
noint = 1;
|
||||
nmi_enable = 1;
|
||||
|
||||
x808x_log("RETEM mode\n");
|
||||
}
|
||||
|
||||
void
|
||||
interrupt_808x(uint16_t addr)
|
||||
{
|
||||
@@ -1033,6 +1190,11 @@ custom_nmi(void)
|
||||
uint16_t new_cs, new_ip;
|
||||
uint16_t tempf;
|
||||
|
||||
if (!(cpu_state.flags & MD_FLAG) && is_nec) {
|
||||
sync_from_i8080();
|
||||
pclog("NMI# (CUTSOM)\n");
|
||||
}
|
||||
|
||||
cpu_state.eaaddr = 0x0002;
|
||||
old_cs = CS;
|
||||
access(5, 16);
|
||||
@@ -1050,6 +1212,8 @@ custom_nmi(void)
|
||||
tempf = cpu_state.flags & (is_nec ? 0x8fd7 : 0x0fd7);
|
||||
push(&tempf);
|
||||
cpu_state.flags &= ~(I_FLAG | T_FLAG);
|
||||
if (is_nec)
|
||||
cpu_state.flags |= MD_FLAG;
|
||||
access(40, 16);
|
||||
push(&old_cs);
|
||||
old_ip = cpu_state.pc;
|
||||
@@ -1771,6 +1935,15 @@ execx86(int cycs)
|
||||
while (cycles > 0) {
|
||||
clock_start();
|
||||
|
||||
if (is_nec && !(cpu_state.flags & MD_FLAG)) {
|
||||
i8080_step(&emulated_processor);
|
||||
set_if(emulated_processor.iff);
|
||||
cycles -= emulated_processor.cyc;
|
||||
emulated_processor.cyc = 0;
|
||||
completed = 1;
|
||||
goto exec_completed;
|
||||
}
|
||||
|
||||
if (!repeating) {
|
||||
cpu_state.oldpc = cpu_state.pc;
|
||||
opcode = pfq_fetchb();
|
||||
@@ -2344,8 +2517,8 @@ execx86(int cycs)
|
||||
break;
|
||||
|
||||
case 0xFF: /* BRKEM */
|
||||
/* Unimplemented for now. */
|
||||
fatal("808x: Unsupported 8080 emulation mode attempted to enter into!");
|
||||
interrupt_brkem(pfq_fetchb());
|
||||
handled = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -2857,11 +3030,12 @@ execx86(int cycs)
|
||||
break;
|
||||
case 0x9D: /*POPF*/
|
||||
access(25, 16);
|
||||
if (is_nec)
|
||||
if (is_nec && cpu_md_write_disable)
|
||||
cpu_state.flags = pop() | 0x8002;
|
||||
else
|
||||
cpu_state.flags = pop() | 0x0002;
|
||||
wait(1, 0);
|
||||
sync_to_i8080();
|
||||
break;
|
||||
case 0x9E: /*SAHF*/
|
||||
wait(1, 0);
|
||||
@@ -3127,13 +3301,15 @@ execx86(int cycs)
|
||||
access(62, 8);
|
||||
set_ip(new_ip);
|
||||
access(45, 8);
|
||||
if (is_nec)
|
||||
if (is_nec && cpu_md_write_disable)
|
||||
cpu_state.flags = pop() | 0x8002;
|
||||
else
|
||||
cpu_state.flags = pop() | 0x0002;
|
||||
wait(5, 0);
|
||||
noint = 1;
|
||||
nmi_enable = 1;
|
||||
if (is_nec && !(cpu_state.flags & MD_FLAG))
|
||||
sync_to_i8080();
|
||||
break;
|
||||
|
||||
case 0xD0:
|
||||
@@ -3659,7 +3835,7 @@ execx86(int cycs)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
exec_completed:
|
||||
if (completed) {
|
||||
repeating = 0;
|
||||
ovr_seg = NULL;
|
||||
|
||||
@@ -29,7 +29,7 @@ add_library(cpu OBJECT
|
||||
x86seg_2386.c
|
||||
x87.c
|
||||
x87_timings.c
|
||||
8080.c
|
||||
i8080.c
|
||||
)
|
||||
|
||||
if(AMD_K5)
|
||||
|
||||
826
src/cpu/i8080.c
Normal file
@@ -0,0 +1,826 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Intel 8080 CPU emulation
|
||||
*
|
||||
* Authors: Cacodemon345
|
||||
* Nicolas Allemand
|
||||
*
|
||||
* Copyright (c) 2018 Nicolas Allemand
|
||||
* Copyright (c) 2024 Cacodemon345
|
||||
*
|
||||
*/
|
||||
|
||||
#include "i8080.h"
|
||||
#include <stdint.h>
|
||||
|
||||
// Changes from upstream:
|
||||
// Add CALLN and RETEM instructions.
|
||||
// Add code for instruction fetches.
|
||||
|
||||
// this array defines the number of cycles one opcode takes.
|
||||
// note that there are some special cases: conditional RETs and CALLs
|
||||
// add +6 cycles if the condition is met
|
||||
// clang-format off
|
||||
static const uint8_t OPCODES_CYCLES[256] = {
|
||||
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
4, 10, 7, 5, 5, 5, 7, 4, 4, 10, 7, 5, 5, 5, 7, 4, // 0
|
||||
4, 10, 7, 5, 5, 5, 7, 4, 4, 10, 7, 5, 5, 5, 7, 4, // 1
|
||||
4, 10, 16, 5, 5, 5, 7, 4, 4, 10, 16, 5, 5, 5, 7, 4, // 2
|
||||
4, 10, 13, 5, 10, 10, 10, 4, 4, 10, 13, 5, 5, 5, 7, 4, // 3
|
||||
5, 5, 5, 5, 5, 5, 7, 5, 5, 5, 5, 5, 5, 5, 7, 5, // 4
|
||||
5, 5, 5, 5, 5, 5, 7, 5, 5, 5, 5, 5, 5, 5, 7, 5, // 5
|
||||
5, 5, 5, 5, 5, 5, 7, 5, 5, 5, 5, 5, 5, 5, 7, 5, // 6
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 5, 5, 5, 5, 5, 5, 7, 5, // 7
|
||||
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 8
|
||||
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 9
|
||||
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // A
|
||||
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // B
|
||||
5, 10, 10, 10, 11, 11, 7, 11, 5, 10, 10, 10, 11, 17, 7, 11, // C
|
||||
5, 10, 10, 10, 11, 11, 7, 11, 5, 10, 10, 10, 11, 17, 7, 11, // D
|
||||
5, 10, 10, 18, 11, 11, 7, 11, 5, 5, 10, 4, 11, 17, 7, 11, // E
|
||||
5, 10, 10, 4, 11, 11, 7, 11, 5, 5, 10, 4, 11, 17, 7, 11 // F
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
static const char* DISASSEMBLE_TABLE[] = {"nop", "lxi b,#", "stax b", "inx b",
|
||||
"inr b", "dcr b", "mvi b,#", "rlc", "ill", "dad b", "ldax b", "dcx b",
|
||||
"inr c", "dcr c", "mvi c,#", "rrc", "ill", "lxi d,#", "stax d", "inx d",
|
||||
"inr d", "dcr d", "mvi d,#", "ral", "ill", "dad d", "ldax d", "dcx d",
|
||||
"inr e", "dcr e", "mvi e,#", "rar", "ill", "lxi h,#", "shld", "inx h",
|
||||
"inr h", "dcr h", "mvi h,#", "daa", "ill", "dad h", "lhld", "dcx h",
|
||||
"inr l", "dcr l", "mvi l,#", "cma", "ill", "lxi sp,#", "sta $", "inx sp",
|
||||
"inr M", "dcr M", "mvi M,#", "stc", "ill", "dad sp", "lda $", "dcx sp",
|
||||
"inr a", "dcr a", "mvi a,#", "cmc", "mov b,b", "mov b,c", "mov b,d",
|
||||
"mov b,e", "mov b,h", "mov b,l", "mov b,M", "mov b,a", "mov c,b", "mov c,c",
|
||||
"mov c,d", "mov c,e", "mov c,h", "mov c,l", "mov c,M", "mov c,a", "mov d,b",
|
||||
"mov d,c", "mov d,d", "mov d,e", "mov d,h", "mov d,l", "mov d,M", "mov d,a",
|
||||
"mov e,b", "mov e,c", "mov e,d", "mov e,e", "mov e,h", "mov e,l", "mov e,M",
|
||||
"mov e,a", "mov h,b", "mov h,c", "mov h,d", "mov h,e", "mov h,h", "mov h,l",
|
||||
"mov h,M", "mov h,a", "mov l,b", "mov l,c", "mov l,d", "mov l,e", "mov l,h",
|
||||
"mov l,l", "mov l,M", "mov l,a", "mov M,b", "mov M,c", "mov M,d", "mov M,e",
|
||||
"mov M,h", "mov M,l", "hlt", "mov M,a", "mov a,b", "mov a,c", "mov a,d",
|
||||
"mov a,e", "mov a,h", "mov a,l", "mov a,M", "mov a,a", "add b", "add c",
|
||||
"add d", "add e", "add h", "add l", "add M", "add a", "adc b", "adc c",
|
||||
"adc d", "adc e", "adc h", "adc l", "adc M", "adc a", "sub b", "sub c",
|
||||
"sub d", "sub e", "sub h", "sub l", "sub M", "sub a", "sbb b", "sbb c",
|
||||
"sbb d", "sbb e", "sbb h", "sbb l", "sbb M", "sbb a", "ana b", "ana c",
|
||||
"ana d", "ana e", "ana h", "ana l", "ana M", "ana a", "xra b", "xra c",
|
||||
"xra d", "xra e", "xra h", "xra l", "xra M", "xra a", "ora b", "ora c",
|
||||
"ora d", "ora e", "ora h", "ora l", "ora M", "ora a", "cmp b", "cmp c",
|
||||
"cmp d", "cmp e", "cmp h", "cmp l", "cmp M", "cmp a", "rnz", "pop b",
|
||||
"jnz $", "jmp $", "cnz $", "push b", "adi #", "rst 0", "rz", "ret", "jz $",
|
||||
"ill", "cz $", "call $", "aci #", "rst 1", "rnc", "pop d", "jnc $", "out p",
|
||||
"cnc $", "push d", "sui #", "rst 2", "rc", "ill", "jc $", "in p", "cc $",
|
||||
"ill", "sbi #", "rst 3", "rpo", "pop h", "jpo $", "xthl", "cpo $", "push h",
|
||||
"ani #", "rst 4", "rpe", "pchl", "jpe $", "xchg", "cpe $", "ill", "xri #",
|
||||
"rst 5", "rp", "pop psw", "jp $", "di", "cp $", "push psw", "ori #",
|
||||
"rst 6", "rm", "sphl", "jm $", "ei", "cm $", "ill", "cpi #", "rst 7"};
|
||||
|
||||
#define SET_ZSP(c, val) \
|
||||
do { \
|
||||
c->zf = (val) == 0; \
|
||||
c->sf = (val) >> 7; \
|
||||
c->pf = parity(val); \
|
||||
} while (0)
|
||||
|
||||
// memory helpers (the only four to use `read_byte` and `write_byte` function
|
||||
// pointers)
|
||||
|
||||
// reads a byte from memory
|
||||
static inline uint8_t i8080_rb(i8080* const c, uint16_t addr) {
|
||||
return c->read_byte(c->userdata, addr);
|
||||
}
|
||||
|
||||
// writes a byte to memory
|
||||
static inline void i8080_wb(i8080* const c, uint16_t addr, uint8_t val) {
|
||||
c->write_byte(c->userdata, addr, val);
|
||||
}
|
||||
|
||||
// reads a word from memory
|
||||
static inline uint16_t i8080_rw(i8080* const c, uint16_t addr) {
|
||||
return c->read_byte(c->userdata, addr + 1) << 8 |
|
||||
c->read_byte(c->userdata, addr);
|
||||
}
|
||||
|
||||
// writes a word to memory
|
||||
static inline void i8080_ww(i8080* const c, uint16_t addr, uint16_t val) {
|
||||
c->write_byte(c->userdata, addr, val & 0xFF);
|
||||
c->write_byte(c->userdata, addr + 1, val >> 8);
|
||||
}
|
||||
|
||||
// returns the next byte in memory (and updates the program counter)
|
||||
static inline uint8_t i8080_next_byte(i8080* const c) {
|
||||
return c->read_byte_seg ? (c->read_byte_seg(c->userdata, c->pc++)) : i8080_rb(c, c->pc++);
|
||||
}
|
||||
|
||||
// returns the next word in memory (and updates the program counter)
|
||||
static inline uint16_t i8080_next_word(i8080* const c) {
|
||||
uint16_t result = 0;
|
||||
if (c->read_byte_seg)
|
||||
result = c->read_byte_seg(c, c->pc) | (c->read_byte_seg(c, c->pc + 1) << 8);
|
||||
else
|
||||
result = i8080_rw(c, c->pc);
|
||||
c->pc += 2;
|
||||
return result;
|
||||
}
|
||||
|
||||
// paired registers helpers (setters and getters)
|
||||
static inline void i8080_set_bc(i8080* const c, uint16_t val) {
|
||||
c->b = val >> 8;
|
||||
c->c = val & 0xFF;
|
||||
}
|
||||
|
||||
static inline void i8080_set_de(i8080* const c, uint16_t val) {
|
||||
c->d = val >> 8;
|
||||
c->e = val & 0xFF;
|
||||
}
|
||||
|
||||
static inline void i8080_set_hl(i8080* const c, uint16_t val) {
|
||||
c->h = val >> 8;
|
||||
c->l = val & 0xFF;
|
||||
}
|
||||
|
||||
static inline uint16_t i8080_get_bc(i8080* const c) {
|
||||
return (c->b << 8) | c->c;
|
||||
}
|
||||
|
||||
static inline uint16_t i8080_get_de(i8080* const c) {
|
||||
return (c->d << 8) | c->e;
|
||||
}
|
||||
|
||||
static inline uint16_t i8080_get_hl(i8080* const c) {
|
||||
return (c->h << 8) | c->l;
|
||||
}
|
||||
|
||||
// stack helpers
|
||||
|
||||
// pushes a value into the stack and updates the stack pointer
|
||||
static inline void i8080_push_stack(i8080* const c, uint16_t val) {
|
||||
c->sp -= 2;
|
||||
i8080_ww(c, c->sp, val);
|
||||
}
|
||||
|
||||
// pops a value from the stack and updates the stack pointer
|
||||
static inline uint16_t i8080_pop_stack(i8080* const c) {
|
||||
uint16_t val = i8080_rw(c, c->sp);
|
||||
c->sp += 2;
|
||||
return val;
|
||||
}
|
||||
|
||||
// opcodes
|
||||
|
||||
// returns the parity of byte: 0 if number of 1 bits in `val` is odd, else 1
|
||||
static inline bool parity(uint8_t val) {
|
||||
uint8_t nb_one_bits = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
nb_one_bits += ((val >> i) & 1);
|
||||
}
|
||||
|
||||
return (nb_one_bits & 1) == 0;
|
||||
}
|
||||
|
||||
// returns if there was a carry between bit "bit_no" and "bit_no - 1" when
|
||||
// executing "a + b + cy"
|
||||
static inline bool carry(int bit_no, uint8_t a, uint8_t b, bool cy) {
|
||||
int16_t result = a + b + cy;
|
||||
int16_t carry = result ^ a ^ b;
|
||||
return carry & (1 << bit_no);
|
||||
}
|
||||
|
||||
// adds a value (+ an optional carry flag) to a register
|
||||
static inline void i8080_add(
|
||||
i8080* const c, uint8_t* const reg, uint8_t val, bool cy) {
|
||||
uint8_t result = *reg + val + cy;
|
||||
c->cf = carry(8, *reg, val, cy);
|
||||
c->hf = carry(4, *reg, val, cy);
|
||||
SET_ZSP(c, result);
|
||||
*reg = result;
|
||||
}
|
||||
|
||||
// substracts a byte (+ an optional carry flag) from a register
|
||||
// see https://stackoverflow.com/a/8037485
|
||||
static inline void i8080_sub(
|
||||
i8080* const c, uint8_t* const reg, uint8_t val, bool cy) {
|
||||
i8080_add(c, reg, ~val, !cy);
|
||||
c->cf = !c->cf;
|
||||
}
|
||||
|
||||
// adds a word to HL
|
||||
static inline void i8080_dad(i8080* const c, uint16_t val) {
|
||||
c->cf = ((i8080_get_hl(c) + val) >> 16) & 1;
|
||||
i8080_set_hl(c, i8080_get_hl(c) + val);
|
||||
}
|
||||
|
||||
// increments a byte
|
||||
static inline uint8_t i8080_inr(i8080* const c, uint8_t val) {
|
||||
uint8_t result = val + 1;
|
||||
c->hf = (result & 0xF) == 0;
|
||||
SET_ZSP(c, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// decrements a byte
|
||||
static inline uint8_t i8080_dcr(i8080* const c, uint8_t val) {
|
||||
uint8_t result = val - 1;
|
||||
c->hf = !((result & 0xF) == 0xF);
|
||||
SET_ZSP(c, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// executes a logic "and" between register A and a byte, then stores the
|
||||
// result in register A
|
||||
static inline void i8080_ana(i8080* const c, uint8_t val) {
|
||||
uint8_t result = c->a & val;
|
||||
c->cf = 0;
|
||||
c->hf = ((c->a | val) & 0x08) != 0;
|
||||
SET_ZSP(c, result);
|
||||
c->a = result;
|
||||
}
|
||||
|
||||
// executes a logic "xor" between register A and a byte, then stores the
|
||||
// result in register A
|
||||
static inline void i8080_xra(i8080* const c, uint8_t val) {
|
||||
c->a ^= val;
|
||||
c->cf = 0;
|
||||
c->hf = 0;
|
||||
SET_ZSP(c, c->a);
|
||||
}
|
||||
|
||||
// executes a logic "or" between register A and a byte, then stores the
|
||||
// result in register A
|
||||
static inline void i8080_ora(i8080* const c, uint8_t val) {
|
||||
c->a |= val;
|
||||
c->cf = 0;
|
||||
c->hf = 0;
|
||||
SET_ZSP(c, c->a);
|
||||
}
|
||||
|
||||
// compares the register A to another byte
|
||||
static inline void i8080_cmp(i8080* const c, uint8_t val) {
|
||||
int16_t result = c->a - val;
|
||||
c->cf = result >> 8;
|
||||
c->hf = ~(c->a ^ result ^ val) & 0x10;
|
||||
SET_ZSP(c, result & 0xFF);
|
||||
}
|
||||
|
||||
// sets the program counter to a given address
|
||||
static inline void i8080_jmp(i8080* const c, uint16_t addr) {
|
||||
c->pc = addr;
|
||||
}
|
||||
|
||||
// jumps to next address pointed by the next word in memory if a condition
|
||||
// is met
|
||||
static inline void i8080_cond_jmp(i8080* const c, bool condition) {
|
||||
uint16_t addr = i8080_next_word(c);
|
||||
if (condition) {
|
||||
c->pc = addr;
|
||||
}
|
||||
}
|
||||
|
||||
// pushes the current pc to the stack, then jumps to an address
|
||||
static inline void i8080_call(i8080* const c, uint16_t addr) {
|
||||
i8080_push_stack(c, c->pc);
|
||||
i8080_jmp(c, addr);
|
||||
}
|
||||
|
||||
// calls to next word in memory if a condition is met
|
||||
static inline void i8080_cond_call(i8080* const c, bool condition) {
|
||||
uint16_t addr = i8080_next_word(c);
|
||||
if (condition) {
|
||||
i8080_call(c, addr);
|
||||
c->cyc += 6;
|
||||
}
|
||||
}
|
||||
|
||||
// returns from subroutine
|
||||
static inline void i8080_ret(i8080* const c) {
|
||||
c->pc = i8080_pop_stack(c);
|
||||
}
|
||||
|
||||
// returns from subroutine if a condition is met
|
||||
static inline void i8080_cond_ret(i8080* const c, bool condition) {
|
||||
if (condition) {
|
||||
i8080_ret(c);
|
||||
c->cyc += 6;
|
||||
}
|
||||
}
|
||||
|
||||
// pushes register A and the flags into the stack
|
||||
static inline void i8080_push_psw(i8080* const c) {
|
||||
// note: bit 3 and 5 are always 0
|
||||
uint8_t psw = 0;
|
||||
psw |= c->sf << 7;
|
||||
psw |= c->zf << 6;
|
||||
psw |= c->hf << 4;
|
||||
psw |= c->pf << 2;
|
||||
psw |= 1 << 1; // bit 1 is always 1
|
||||
psw |= c->cf << 0;
|
||||
i8080_push_stack(c, c->a << 8 | psw);
|
||||
}
|
||||
|
||||
// pops register A and the flags from the stack
|
||||
static inline void i8080_pop_psw(i8080* const c) {
|
||||
uint16_t af = i8080_pop_stack(c);
|
||||
c->a = af >> 8;
|
||||
uint8_t psw = af & 0xFF;
|
||||
|
||||
c->sf = (psw >> 7) & 1;
|
||||
c->zf = (psw >> 6) & 1;
|
||||
c->hf = (psw >> 4) & 1;
|
||||
c->pf = (psw >> 2) & 1;
|
||||
c->cf = (psw >> 0) & 1;
|
||||
}
|
||||
|
||||
// rotate register A left
|
||||
static inline void i8080_rlc(i8080* const c) {
|
||||
c->cf = c->a >> 7;
|
||||
c->a = (c->a << 1) | c->cf;
|
||||
}
|
||||
|
||||
// rotate register A right
|
||||
static inline void i8080_rrc(i8080* const c) {
|
||||
c->cf = c->a & 1;
|
||||
c->a = (c->a >> 1) | (c->cf << 7);
|
||||
}
|
||||
|
||||
// rotate register A left with the carry flag
|
||||
static inline void i8080_ral(i8080* const c) {
|
||||
bool cy = c->cf;
|
||||
c->cf = c->a >> 7;
|
||||
c->a = (c->a << 1) | cy;
|
||||
}
|
||||
|
||||
// rotate register A right with the carry flag
|
||||
static inline void i8080_rar(i8080* const c) {
|
||||
bool cy = c->cf;
|
||||
c->cf = c->a & 1;
|
||||
c->a = (c->a >> 1) | (cy << 7);
|
||||
}
|
||||
|
||||
// Decimal Adjust Accumulator: the eight-bit number in register A is adjusted
|
||||
// to form two four-bit binary-coded-decimal digits.
|
||||
// For example, if A=$2B and DAA is executed, A becomes $31.
|
||||
static inline void i8080_daa(i8080* const c) {
|
||||
bool cy = c->cf;
|
||||
uint8_t correction = 0;
|
||||
|
||||
uint8_t lsb = c->a & 0x0F;
|
||||
uint8_t msb = c->a >> 4;
|
||||
|
||||
if (c->hf || lsb > 9) {
|
||||
correction += 0x06;
|
||||
}
|
||||
|
||||
if (c->cf || msb > 9 || (msb >= 9 && lsb > 9)) {
|
||||
correction += 0x60;
|
||||
cy = 1;
|
||||
}
|
||||
|
||||
i8080_add(c, &c->a, correction, 0);
|
||||
c->cf = cy;
|
||||
}
|
||||
|
||||
// switches the value of registers DE and HL
|
||||
static inline void i8080_xchg(i8080* const c) {
|
||||
uint16_t de = i8080_get_de(c);
|
||||
i8080_set_de(c, i8080_get_hl(c));
|
||||
i8080_set_hl(c, de);
|
||||
}
|
||||
|
||||
// switches the value of a word at (sp) and HL
|
||||
static inline void i8080_xthl(i8080* const c) {
|
||||
uint16_t val = i8080_rw(c, c->sp);
|
||||
i8080_ww(c, c->sp, i8080_get_hl(c));
|
||||
i8080_set_hl(c, val);
|
||||
}
|
||||
|
||||
extern void interrupt_808x(uint16_t addr);
|
||||
extern void retem_i8080(void);
|
||||
// executes one opcode
|
||||
static inline void i8080_execute(i8080* const c, uint8_t opcode) {
|
||||
c->cyc += OPCODES_CYCLES[opcode];
|
||||
|
||||
// when DI is executed, interrupts won't be serviced
|
||||
// until the end of next instruction:
|
||||
if (c->interrupt_delay > 0) {
|
||||
c->interrupt_delay -= 1;
|
||||
}
|
||||
|
||||
switch (opcode) {
|
||||
case 0x7F: c->a = c->a; break; // MOV A,A
|
||||
case 0x78: c->a = c->b; break; // MOV A,B
|
||||
case 0x79: c->a = c->c; break; // MOV A,C
|
||||
case 0x7A: c->a = c->d; break; // MOV A,D
|
||||
case 0x7B: c->a = c->e; break; // MOV A,E
|
||||
case 0x7C: c->a = c->h; break; // MOV A,H
|
||||
case 0x7D: c->a = c->l; break; // MOV A,L
|
||||
case 0x7E: c->a = i8080_rb(c, i8080_get_hl(c)); break; // MOV A,M
|
||||
|
||||
case 0x0A: c->a = i8080_rb(c, i8080_get_bc(c)); break; // LDAX B
|
||||
case 0x1A: c->a = i8080_rb(c, i8080_get_de(c)); break; // LDAX D
|
||||
case 0x3A: c->a = i8080_rb(c, i8080_next_word(c)); break; // LDA word
|
||||
|
||||
case 0x47: c->b = c->a; break; // MOV B,A
|
||||
case 0x40: c->b = c->b; break; // MOV B,B
|
||||
case 0x41: c->b = c->c; break; // MOV B,C
|
||||
case 0x42: c->b = c->d; break; // MOV B,D
|
||||
case 0x43: c->b = c->e; break; // MOV B,E
|
||||
case 0x44: c->b = c->h; break; // MOV B,H
|
||||
case 0x45: c->b = c->l; break; // MOV B,L
|
||||
case 0x46: c->b = i8080_rb(c, i8080_get_hl(c)); break; // MOV B,M
|
||||
|
||||
case 0x4F: c->c = c->a; break; // MOV C,A
|
||||
case 0x48: c->c = c->b; break; // MOV C,B
|
||||
case 0x49: c->c = c->c; break; // MOV C,C
|
||||
case 0x4A: c->c = c->d; break; // MOV C,D
|
||||
case 0x4B: c->c = c->e; break; // MOV C,E
|
||||
case 0x4C: c->c = c->h; break; // MOV C,H
|
||||
case 0x4D: c->c = c->l; break; // MOV C,L
|
||||
case 0x4E: c->c = i8080_rb(c, i8080_get_hl(c)); break; // MOV C,M
|
||||
|
||||
case 0x57: c->d = c->a; break; // MOV D,A
|
||||
case 0x50: c->d = c->b; break; // MOV D,B
|
||||
case 0x51: c->d = c->c; break; // MOV D,C
|
||||
case 0x52: c->d = c->d; break; // MOV D,D
|
||||
case 0x53: c->d = c->e; break; // MOV D,E
|
||||
case 0x54: c->d = c->h; break; // MOV D,H
|
||||
case 0x55: c->d = c->l; break; // MOV D,L
|
||||
case 0x56: c->d = i8080_rb(c, i8080_get_hl(c)); break; // MOV D,M
|
||||
|
||||
case 0x5F: c->e = c->a; break; // MOV E,A
|
||||
case 0x58: c->e = c->b; break; // MOV E,B
|
||||
case 0x59: c->e = c->c; break; // MOV E,C
|
||||
case 0x5A: c->e = c->d; break; // MOV E,D
|
||||
case 0x5B: c->e = c->e; break; // MOV E,E
|
||||
case 0x5C: c->e = c->h; break; // MOV E,H
|
||||
case 0x5D: c->e = c->l; break; // MOV E,L
|
||||
case 0x5E: c->e = i8080_rb(c, i8080_get_hl(c)); break; // MOV E,M
|
||||
|
||||
case 0x67: c->h = c->a; break; // MOV H,A
|
||||
case 0x60: c->h = c->b; break; // MOV H,B
|
||||
case 0x61: c->h = c->c; break; // MOV H,C
|
||||
case 0x62: c->h = c->d; break; // MOV H,D
|
||||
case 0x63: c->h = c->e; break; // MOV H,E
|
||||
case 0x64: c->h = c->h; break; // MOV H,H
|
||||
case 0x65: c->h = c->l; break; // MOV H,L
|
||||
case 0x66: c->h = i8080_rb(c, i8080_get_hl(c)); break; // MOV H,M
|
||||
|
||||
case 0x6F: c->l = c->a; break; // MOV L,A
|
||||
case 0x68: c->l = c->b; break; // MOV L,B
|
||||
case 0x69: c->l = c->c; break; // MOV L,C
|
||||
case 0x6A: c->l = c->d; break; // MOV L,D
|
||||
case 0x6B: c->l = c->e; break; // MOV L,E
|
||||
case 0x6C: c->l = c->h; break; // MOV L,H
|
||||
case 0x6D: c->l = c->l; break; // MOV L,L
|
||||
case 0x6E: c->l = i8080_rb(c, i8080_get_hl(c)); break; // MOV L,M
|
||||
|
||||
case 0x77: i8080_wb(c, i8080_get_hl(c), c->a); break; // MOV M,A
|
||||
case 0x70: i8080_wb(c, i8080_get_hl(c), c->b); break; // MOV M,B
|
||||
case 0x71: i8080_wb(c, i8080_get_hl(c), c->c); break; // MOV M,C
|
||||
case 0x72: i8080_wb(c, i8080_get_hl(c), c->d); break; // MOV M,D
|
||||
case 0x73: i8080_wb(c, i8080_get_hl(c), c->e); break; // MOV M,E
|
||||
case 0x74: i8080_wb(c, i8080_get_hl(c), c->h); break; // MOV M,H
|
||||
case 0x75: i8080_wb(c, i8080_get_hl(c), c->l); break; // MOV M,L
|
||||
|
||||
case 0x3E: c->a = i8080_next_byte(c); break; // MVI A,byte
|
||||
case 0x06: c->b = i8080_next_byte(c); break; // MVI B,byte
|
||||
case 0x0E: c->c = i8080_next_byte(c); break; // MVI C,byte
|
||||
case 0x16: c->d = i8080_next_byte(c); break; // MVI D,byte
|
||||
case 0x1E: c->e = i8080_next_byte(c); break; // MVI E,byte
|
||||
case 0x26: c->h = i8080_next_byte(c); break; // MVI H,byte
|
||||
case 0x2E: c->l = i8080_next_byte(c); break; // MVI L,byte
|
||||
case 0x36:
|
||||
i8080_wb(c, i8080_get_hl(c), i8080_next_byte(c));
|
||||
break; // MVI M,byte
|
||||
|
||||
case 0x02: i8080_wb(c, i8080_get_bc(c), c->a); break; // STAX B
|
||||
case 0x12: i8080_wb(c, i8080_get_de(c), c->a); break; // STAX D
|
||||
case 0x32: i8080_wb(c, i8080_next_word(c), c->a); break; // STA word
|
||||
|
||||
case 0x01: i8080_set_bc(c, i8080_next_word(c)); break; // LXI B,word
|
||||
case 0x11: i8080_set_de(c, i8080_next_word(c)); break; // LXI D,word
|
||||
case 0x21: i8080_set_hl(c, i8080_next_word(c)); break; // LXI H,word
|
||||
case 0x31: c->sp = i8080_next_word(c); break; // LXI SP,word
|
||||
case 0x2A: i8080_set_hl(c, i8080_rw(c, i8080_next_word(c))); break; // LHLD
|
||||
case 0x22: i8080_ww(c, i8080_next_word(c), i8080_get_hl(c)); break; // SHLD
|
||||
case 0xF9: c->sp = i8080_get_hl(c); break; // SPHL
|
||||
|
||||
case 0xEB: i8080_xchg(c); break; // XCHG
|
||||
case 0xE3: i8080_xthl(c); break; // XTHL
|
||||
|
||||
case 0x87: i8080_add(c, &c->a, c->a, 0); break; // ADD A
|
||||
case 0x80: i8080_add(c, &c->a, c->b, 0); break; // ADD B
|
||||
case 0x81: i8080_add(c, &c->a, c->c, 0); break; // ADD C
|
||||
case 0x82: i8080_add(c, &c->a, c->d, 0); break; // ADD D
|
||||
case 0x83: i8080_add(c, &c->a, c->e, 0); break; // ADD E
|
||||
case 0x84: i8080_add(c, &c->a, c->h, 0); break; // ADD H
|
||||
case 0x85: i8080_add(c, &c->a, c->l, 0); break; // ADD L
|
||||
case 0x86:
|
||||
i8080_add(c, &c->a, i8080_rb(c, i8080_get_hl(c)), 0);
|
||||
break; // ADD M
|
||||
case 0xC6: i8080_add(c, &c->a, i8080_next_byte(c), 0); break; // ADI byte
|
||||
|
||||
case 0x8F: i8080_add(c, &c->a, c->a, c->cf); break; // ADC A
|
||||
case 0x88: i8080_add(c, &c->a, c->b, c->cf); break; // ADC B
|
||||
case 0x89: i8080_add(c, &c->a, c->c, c->cf); break; // ADC C
|
||||
case 0x8A: i8080_add(c, &c->a, c->d, c->cf); break; // ADC D
|
||||
case 0x8B: i8080_add(c, &c->a, c->e, c->cf); break; // ADC E
|
||||
case 0x8C: i8080_add(c, &c->a, c->h, c->cf); break; // ADC H
|
||||
case 0x8D: i8080_add(c, &c->a, c->l, c->cf); break; // ADC L
|
||||
case 0x8E:
|
||||
i8080_add(c, &c->a, i8080_rb(c, i8080_get_hl(c)), c->cf);
|
||||
break; // ADC M
|
||||
case 0xCE: i8080_add(c, &c->a, i8080_next_byte(c), c->cf); break; // ACI byte
|
||||
|
||||
case 0x97: i8080_sub(c, &c->a, c->a, 0); break; // SUB A
|
||||
case 0x90: i8080_sub(c, &c->a, c->b, 0); break; // SUB B
|
||||
case 0x91: i8080_sub(c, &c->a, c->c, 0); break; // SUB C
|
||||
case 0x92: i8080_sub(c, &c->a, c->d, 0); break; // SUB D
|
||||
case 0x93: i8080_sub(c, &c->a, c->e, 0); break; // SUB E
|
||||
case 0x94: i8080_sub(c, &c->a, c->h, 0); break; // SUB H
|
||||
case 0x95: i8080_sub(c, &c->a, c->l, 0); break; // SUB L
|
||||
case 0x96:
|
||||
i8080_sub(c, &c->a, i8080_rb(c, i8080_get_hl(c)), 0);
|
||||
break; // SUB M
|
||||
case 0xD6: i8080_sub(c, &c->a, i8080_next_byte(c), 0); break; // SUI byte
|
||||
|
||||
case 0x9F: i8080_sub(c, &c->a, c->a, c->cf); break; // SBB A
|
||||
case 0x98: i8080_sub(c, &c->a, c->b, c->cf); break; // SBB B
|
||||
case 0x99: i8080_sub(c, &c->a, c->c, c->cf); break; // SBB C
|
||||
case 0x9A: i8080_sub(c, &c->a, c->d, c->cf); break; // SBB D
|
||||
case 0x9B: i8080_sub(c, &c->a, c->e, c->cf); break; // SBB E
|
||||
case 0x9C: i8080_sub(c, &c->a, c->h, c->cf); break; // SBB H
|
||||
case 0x9D: i8080_sub(c, &c->a, c->l, c->cf); break; // SBB L
|
||||
case 0x9E:
|
||||
i8080_sub(c, &c->a, i8080_rb(c, i8080_get_hl(c)), c->cf);
|
||||
break; // SBB M
|
||||
case 0xDE: i8080_sub(c, &c->a, i8080_next_byte(c), c->cf); break; // SBI byte
|
||||
|
||||
case 0x09: i8080_dad(c, i8080_get_bc(c)); break; // DAD B
|
||||
case 0x19: i8080_dad(c, i8080_get_de(c)); break; // DAD D
|
||||
case 0x29: i8080_dad(c, i8080_get_hl(c)); break; // DAD H
|
||||
case 0x39: i8080_dad(c, c->sp); break; // DAD SP
|
||||
|
||||
case 0xF3: c->iff = 0; break; // DI
|
||||
case 0xFB:
|
||||
c->iff = 1;
|
||||
c->interrupt_delay = 1;
|
||||
break; // EI
|
||||
case 0x00: break; // NOP
|
||||
case 0x76: c->halted = 1; break; // HLT
|
||||
|
||||
case 0x3C: c->a = i8080_inr(c, c->a); break; // INR A
|
||||
case 0x04: c->b = i8080_inr(c, c->b); break; // INR B
|
||||
case 0x0C: c->c = i8080_inr(c, c->c); break; // INR C
|
||||
case 0x14: c->d = i8080_inr(c, c->d); break; // INR D
|
||||
case 0x1C: c->e = i8080_inr(c, c->e); break; // INR E
|
||||
case 0x24: c->h = i8080_inr(c, c->h); break; // INR H
|
||||
case 0x2C: c->l = i8080_inr(c, c->l); break; // INR L
|
||||
case 0x34:
|
||||
i8080_wb(c, i8080_get_hl(c), i8080_inr(c, i8080_rb(c, i8080_get_hl(c))));
|
||||
break; // INR M
|
||||
|
||||
case 0x3D: c->a = i8080_dcr(c, c->a); break; // DCR A
|
||||
case 0x05: c->b = i8080_dcr(c, c->b); break; // DCR B
|
||||
case 0x0D: c->c = i8080_dcr(c, c->c); break; // DCR C
|
||||
case 0x15: c->d = i8080_dcr(c, c->d); break; // DCR D
|
||||
case 0x1D: c->e = i8080_dcr(c, c->e); break; // DCR E
|
||||
case 0x25: c->h = i8080_dcr(c, c->h); break; // DCR H
|
||||
case 0x2D: c->l = i8080_dcr(c, c->l); break; // DCR L
|
||||
case 0x35:
|
||||
i8080_wb(c, i8080_get_hl(c), i8080_dcr(c, i8080_rb(c, i8080_get_hl(c))));
|
||||
break; // DCR M
|
||||
|
||||
case 0x03: i8080_set_bc(c, i8080_get_bc(c) + 1); break; // INX B
|
||||
case 0x13: i8080_set_de(c, i8080_get_de(c) + 1); break; // INX D
|
||||
case 0x23: i8080_set_hl(c, i8080_get_hl(c) + 1); break; // INX H
|
||||
case 0x33: c->sp += 1; break; // INX SP
|
||||
|
||||
case 0x0B: i8080_set_bc(c, i8080_get_bc(c) - 1); break; // DCX B
|
||||
case 0x1B: i8080_set_de(c, i8080_get_de(c) - 1); break; // DCX D
|
||||
case 0x2B: i8080_set_hl(c, i8080_get_hl(c) - 1); break; // DCX H
|
||||
case 0x3B: c->sp -= 1; break; // DCX SP
|
||||
|
||||
case 0x27: i8080_daa(c); break; // DAA
|
||||
case 0x2F: c->a = ~c->a; break; // CMA
|
||||
case 0x37: c->cf = 1; break; // STC
|
||||
case 0x3F: c->cf = !c->cf; break; // CMC
|
||||
|
||||
case 0x07: i8080_rlc(c); break; // RLC (rotate left)
|
||||
case 0x0F: i8080_rrc(c); break; // RRC (rotate right)
|
||||
case 0x17: i8080_ral(c); break; // RAL
|
||||
case 0x1F: i8080_rar(c); break; // RAR
|
||||
|
||||
case 0xA7: i8080_ana(c, c->a); break; // ANA A
|
||||
case 0xA0: i8080_ana(c, c->b); break; // ANA B
|
||||
case 0xA1: i8080_ana(c, c->c); break; // ANA C
|
||||
case 0xA2: i8080_ana(c, c->d); break; // ANA D
|
||||
case 0xA3: i8080_ana(c, c->e); break; // ANA E
|
||||
case 0xA4: i8080_ana(c, c->h); break; // ANA H
|
||||
case 0xA5: i8080_ana(c, c->l); break; // ANA L
|
||||
case 0xA6: i8080_ana(c, i8080_rb(c, i8080_get_hl(c))); break; // ANA M
|
||||
case 0xE6: i8080_ana(c, i8080_next_byte(c)); break; // ANI byte
|
||||
|
||||
case 0xAF: i8080_xra(c, c->a); break; // XRA A
|
||||
case 0xA8: i8080_xra(c, c->b); break; // XRA B
|
||||
case 0xA9: i8080_xra(c, c->c); break; // XRA C
|
||||
case 0xAA: i8080_xra(c, c->d); break; // XRA D
|
||||
case 0xAB: i8080_xra(c, c->e); break; // XRA E
|
||||
case 0xAC: i8080_xra(c, c->h); break; // XRA H
|
||||
case 0xAD: i8080_xra(c, c->l); break; // XRA L
|
||||
case 0xAE: i8080_xra(c, i8080_rb(c, i8080_get_hl(c))); break; // XRA M
|
||||
case 0xEE: i8080_xra(c, i8080_next_byte(c)); break; // XRI byte
|
||||
|
||||
case 0xB7: i8080_ora(c, c->a); break; // ORA A
|
||||
case 0xB0: i8080_ora(c, c->b); break; // ORA B
|
||||
case 0xB1: i8080_ora(c, c->c); break; // ORA C
|
||||
case 0xB2: i8080_ora(c, c->d); break; // ORA D
|
||||
case 0xB3: i8080_ora(c, c->e); break; // ORA E
|
||||
case 0xB4: i8080_ora(c, c->h); break; // ORA H
|
||||
case 0xB5: i8080_ora(c, c->l); break; // ORA L
|
||||
case 0xB6: i8080_ora(c, i8080_rb(c, i8080_get_hl(c))); break; // ORA M
|
||||
case 0xF6: i8080_ora(c, i8080_next_byte(c)); break; // ORI byte
|
||||
|
||||
case 0xBF: i8080_cmp(c, c->a); break; // CMP A
|
||||
case 0xB8: i8080_cmp(c, c->b); break; // CMP B
|
||||
case 0xB9: i8080_cmp(c, c->c); break; // CMP C
|
||||
case 0xBA: i8080_cmp(c, c->d); break; // CMP D
|
||||
case 0xBB: i8080_cmp(c, c->e); break; // CMP E
|
||||
case 0xBC: i8080_cmp(c, c->h); break; // CMP H
|
||||
case 0xBD: i8080_cmp(c, c->l); break; // CMP L
|
||||
case 0xBE: i8080_cmp(c, i8080_rb(c, i8080_get_hl(c))); break; // CMP M
|
||||
case 0xFE: i8080_cmp(c, i8080_next_byte(c)); break; // CPI byte
|
||||
|
||||
case 0xC3: i8080_jmp(c, i8080_next_word(c)); break; // JMP
|
||||
case 0xC2: i8080_cond_jmp(c, c->zf == 0); break; // JNZ
|
||||
case 0xCA: i8080_cond_jmp(c, c->zf == 1); break; // JZ
|
||||
case 0xD2: i8080_cond_jmp(c, c->cf == 0); break; // JNC
|
||||
case 0xDA: i8080_cond_jmp(c, c->cf == 1); break; // JC
|
||||
case 0xE2: i8080_cond_jmp(c, c->pf == 0); break; // JPO
|
||||
case 0xEA: i8080_cond_jmp(c, c->pf == 1); break; // JPE
|
||||
case 0xF2: i8080_cond_jmp(c, c->sf == 0); break; // JP
|
||||
case 0xFA: i8080_cond_jmp(c, c->sf == 1); break; // JM
|
||||
|
||||
case 0xE9: c->pc = i8080_get_hl(c); break; // PCHL
|
||||
case 0xCD: i8080_call(c, i8080_next_word(c)); break; // CALL
|
||||
|
||||
case 0xC4: i8080_cond_call(c, c->zf == 0); break; // CNZ
|
||||
case 0xCC: i8080_cond_call(c, c->zf == 1); break; // CZ
|
||||
case 0xD4: i8080_cond_call(c, c->cf == 0); break; // CNC
|
||||
case 0xDC: i8080_cond_call(c, c->cf == 1); break; // CC
|
||||
case 0xE4: i8080_cond_call(c, c->pf == 0); break; // CPO
|
||||
case 0xEC: i8080_cond_call(c, c->pf == 1); break; // CPE
|
||||
case 0xF4: i8080_cond_call(c, c->sf == 0); break; // CP
|
||||
case 0xFC: i8080_cond_call(c, c->sf == 1); break; // CM
|
||||
|
||||
case 0xC9: i8080_ret(c); break; // RET
|
||||
case 0xC0: i8080_cond_ret(c, c->zf == 0); break; // RNZ
|
||||
case 0xC8: i8080_cond_ret(c, c->zf == 1); break; // RZ
|
||||
case 0xD0: i8080_cond_ret(c, c->cf == 0); break; // RNC
|
||||
case 0xD8: i8080_cond_ret(c, c->cf == 1); break; // RC
|
||||
case 0xE0: i8080_cond_ret(c, c->pf == 0); break; // RPO
|
||||
case 0xE8: i8080_cond_ret(c, c->pf == 1); break; // RPE
|
||||
case 0xF0: i8080_cond_ret(c, c->sf == 0); break; // RP
|
||||
case 0xF8: i8080_cond_ret(c, c->sf == 1); break; // RM
|
||||
|
||||
case 0xC7: i8080_call(c, 0x00); break; // RST 0
|
||||
case 0xCF: i8080_call(c, 0x08); break; // RST 1
|
||||
case 0xD7: i8080_call(c, 0x10); break; // RST 2
|
||||
case 0xDF: i8080_call(c, 0x18); break; // RST 3
|
||||
case 0xE7: i8080_call(c, 0x20); break; // RST 4
|
||||
case 0xEF: i8080_call(c, 0x28); break; // RST 5
|
||||
case 0xF7: i8080_call(c, 0x30); break; // RST 6
|
||||
case 0xFF: i8080_call(c, 0x38); break; // RST 7
|
||||
|
||||
case 0xC5: i8080_push_stack(c, i8080_get_bc(c)); break; // PUSH B
|
||||
case 0xD5: i8080_push_stack(c, i8080_get_de(c)); break; // PUSH D
|
||||
case 0xE5: i8080_push_stack(c, i8080_get_hl(c)); break; // PUSH H
|
||||
case 0xF5: i8080_push_psw(c); break; // PUSH PSW
|
||||
case 0xC1: i8080_set_bc(c, i8080_pop_stack(c)); break; // POP B
|
||||
case 0xD1: i8080_set_de(c, i8080_pop_stack(c)); break; // POP D
|
||||
case 0xE1: i8080_set_hl(c, i8080_pop_stack(c)); break; // POP H
|
||||
case 0xF1: i8080_pop_psw(c); break; // POP PSW
|
||||
|
||||
case 0xDB: c->a = c->port_in(c->userdata, i8080_next_byte(c)); break; // IN
|
||||
case 0xD3: c->port_out(c->userdata, i8080_next_byte(c), c->a); break; // OUT
|
||||
|
||||
case 0x08:
|
||||
case 0x10:
|
||||
case 0x18:
|
||||
case 0x20:
|
||||
case 0x28:
|
||||
case 0x30:
|
||||
case 0x38: break; // undocumented NOPs
|
||||
|
||||
case 0xD9: i8080_ret(c); break; // undocumented RET
|
||||
|
||||
case 0xDD:
|
||||
case 0xED:
|
||||
{
|
||||
if (opcode == 0xED) {
|
||||
uint8_t data = i8080_next_byte(c);
|
||||
if (data == 0xED) {
|
||||
interrupt_808x(i8080_next_byte(c));
|
||||
break;
|
||||
} else if (data == 0xFD) {
|
||||
retem_i8080();
|
||||
break;
|
||||
}
|
||||
else {
|
||||
i8080_call(c, (i8080_next_byte(c) << 8) | data); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
case 0xFD: i8080_call(c, i8080_next_word(c)); break; // undocumented CALLs
|
||||
|
||||
case 0xCB: i8080_jmp(c, i8080_next_word(c)); break; // undocumented JMP
|
||||
}
|
||||
}
|
||||
|
||||
// initialises the emulator with default values
|
||||
void i8080_init(i8080* const c) {
|
||||
c->read_byte = NULL;
|
||||
c->write_byte = NULL;
|
||||
c->port_in = NULL;
|
||||
c->port_out = NULL;
|
||||
c->userdata = NULL;
|
||||
|
||||
c->cyc = 0;
|
||||
|
||||
c->pc = 0;
|
||||
c->sp = 0;
|
||||
|
||||
c->a = 0;
|
||||
c->b = 0;
|
||||
c->c = 0;
|
||||
c->d = 0;
|
||||
c->e = 0;
|
||||
c->h = 0;
|
||||
c->l = 0;
|
||||
|
||||
c->sf = 0;
|
||||
c->zf = 0;
|
||||
c->hf = 0;
|
||||
c->pf = 0;
|
||||
c->cf = 0;
|
||||
c->iff = 0;
|
||||
|
||||
c->halted = 0;
|
||||
c->interrupt_pending = 0;
|
||||
c->interrupt_vector = 0;
|
||||
c->interrupt_delay = 0;
|
||||
}
|
||||
|
||||
// executes one instruction
|
||||
void i8080_step(i8080* const c) {
|
||||
// interrupt processing: if an interrupt is pending and IFF is set,
|
||||
// we execute the interrupt vector passed by the user.
|
||||
if (c->interrupt_pending && c->iff && c->interrupt_delay == 0) {
|
||||
c->interrupt_pending = 0;
|
||||
c->iff = 0;
|
||||
c->halted = 0;
|
||||
|
||||
i8080_execute(c, c->interrupt_vector);
|
||||
} else if (!c->halted) {
|
||||
i8080_execute(c, i8080_next_byte(c));
|
||||
}
|
||||
}
|
||||
|
||||
// asks for an interrupt to be serviced
|
||||
void i8080_interrupt(i8080* const c, uint8_t opcode) {
|
||||
c->interrupt_pending = 1;
|
||||
c->interrupt_vector = opcode;
|
||||
}
|
||||
|
||||
// outputs a debug trace of the emulator state to the standard output,
|
||||
// including registers and flags
|
||||
void i8080_debug_output(i8080* const c, bool print_disassembly) {
|
||||
uint8_t f = 0;
|
||||
f |= c->sf << 7;
|
||||
f |= c->zf << 6;
|
||||
f |= c->hf << 4;
|
||||
f |= c->pf << 2;
|
||||
f |= 1 << 1; // bit 1 is always 1
|
||||
f |= c->cf << 0;
|
||||
|
||||
printf("PC: %04X, AF: %04X, BC: %04X, DE: %04X, HL: %04X, SP: %04X, CYC: %lu",
|
||||
c->pc, c->a << 8 | f, i8080_get_bc(c), i8080_get_de(c), i8080_get_hl(c),
|
||||
c->sp, c->cyc);
|
||||
|
||||
printf("\t(%02X %02X %02X %02X)", i8080_rb(c, c->pc), i8080_rb(c, c->pc + 1),
|
||||
i8080_rb(c, c->pc + 2), i8080_rb(c, c->pc + 3));
|
||||
|
||||
if (print_disassembly) {
|
||||
printf(" - %s", DISASSEMBLE_TABLE[i8080_rb(c, c->pc)]);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
#undef SET_ZSP
|
||||
35
src/cpu/i8080.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#ifndef I8080_I8080_H_
|
||||
#define I8080_I8080_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct i8080 {
|
||||
// memory + io interface
|
||||
uint8_t (*read_byte)(void*, uint16_t); // user function to read from memory
|
||||
void (*write_byte)(void*, uint16_t, uint8_t); // same for writing to memory
|
||||
uint8_t (*read_byte_seg)(void*, uint16_t); // user function to read from memory (Code segment)
|
||||
uint8_t (*port_in)(void*, uint8_t); // user function to read from port
|
||||
void (*port_out)(void*, uint8_t, uint8_t); // same for writing to port
|
||||
void* userdata; // user custom pointer
|
||||
|
||||
unsigned long cyc; // cycle count
|
||||
|
||||
uint16_t pc, sp; // program counter, stack pointer
|
||||
uint8_t a, b, c, d, e, h, l; // registers
|
||||
// flags: sign, zero, half-carry, parity, carry, interrupt flip-flop
|
||||
bool sf : 1, zf : 1, hf : 1, pf : 1, cf : 1, iff : 1;
|
||||
bool halted : 1;
|
||||
|
||||
bool interrupt_pending : 1;
|
||||
uint8_t interrupt_vector;
|
||||
uint8_t interrupt_delay;
|
||||
} i8080;
|
||||
|
||||
void i8080_init(i8080* const c);
|
||||
void i8080_step(i8080* const c);
|
||||
void i8080_interrupt(i8080* const c, uint8_t opcode);
|
||||
void i8080_debug_output(i8080* const c, bool print_disassembly);
|
||||
|
||||
#endif // I8080_I8080_H_
|
||||
@@ -113,7 +113,17 @@ static scconvtbl scconv55_8a[18 + 1] =
|
||||
void
|
||||
keyboard_init(void)
|
||||
{
|
||||
num_lock = 0;
|
||||
caps_lock = 0;
|
||||
scroll_lock = 0;
|
||||
shift = 0;
|
||||
|
||||
memset(recv_key, 0x00, sizeof(recv_key));
|
||||
memset(recv_key_ui, 0x00, sizeof(recv_key));
|
||||
memset(oldkey, 0x00, sizeof(recv_key));
|
||||
#if 0
|
||||
memset(key_delay, 0x00, sizeof(recv_key));
|
||||
#endif
|
||||
|
||||
keyboard_scan = 1;
|
||||
scan_table = NULL;
|
||||
|
||||
@@ -999,7 +999,8 @@ void
|
||||
serial_standalone_init(void)
|
||||
{
|
||||
while (next_inst < SERIAL_MAX)
|
||||
device_add_inst(&ns8250_device, next_inst + 1);
|
||||
device_add_inst(!strcmp(machine_get_internal_name(), "if386sx") ? &ns16450_device :
|
||||
&ns8250_device, next_inst + 1);
|
||||
};
|
||||
|
||||
const device_t ns8250_device = {
|
||||
|
||||
@@ -88,18 +88,20 @@ static const joystick_if_t joystick_none = {
|
||||
static const struct {
|
||||
const joystick_if_t *joystick;
|
||||
} joysticks[] = {
|
||||
{ &joystick_none },
|
||||
{ &joystick_2axis_2button },
|
||||
{ &joystick_2axis_4button },
|
||||
{ &joystick_2axis_6button },
|
||||
{ &joystick_2axis_8button },
|
||||
{ &joystick_3axis_2button },
|
||||
{ &joystick_3axis_4button },
|
||||
{ &joystick_4axis_4button },
|
||||
{ &joystick_ch_flightstick_pro },
|
||||
{ &joystick_sw_pad },
|
||||
{ &joystick_tm_fcs },
|
||||
{ NULL }
|
||||
{ &joystick_none },
|
||||
{ &joystick_2axis_2button },
|
||||
{ &joystick_2axis_4button },
|
||||
{ &joystick_2axis_6button },
|
||||
{ &joystick_2axis_8button },
|
||||
{ &joystick_3axis_2button },
|
||||
{ &joystick_3axis_4button },
|
||||
{ &joystick_4axis_4button },
|
||||
{ &joystick_ch_flightstick_pro },
|
||||
{ &joystick_ch_flightstick_pro_ch_pedals },
|
||||
{ &joystick_sw_pad },
|
||||
{ &joystick_tm_fcs },
|
||||
{ &joystick_tm_fcs_rcs },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static joystick_instance_t *joystick_instance[GAMEPORT_MAX] = { NULL, NULL };
|
||||
|
||||
@@ -112,6 +112,26 @@ ch_flightstick_pro_read_axis(UNUSED(void *priv), int axis)
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
ch_flightstick_pro_ch_pedals_read_axis(UNUSED(void *priv), int axis)
|
||||
{
|
||||
if (!JOYSTICK_PRESENT(0, 0))
|
||||
return AXIS_NOT_PRESENT;
|
||||
|
||||
switch (axis) {
|
||||
case 0:
|
||||
return joystick_state[0][0].axis[0];
|
||||
case 1:
|
||||
return joystick_state[0][0].axis[1];
|
||||
case 2:
|
||||
return joystick_state[0][0].axis[3];
|
||||
case 3:
|
||||
return joystick_state[0][0].axis[2];
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ch_flightstick_pro_a0_over(UNUSED(void *priv))
|
||||
{
|
||||
@@ -135,3 +155,21 @@ const joystick_if_t joystick_ch_flightstick_pro = {
|
||||
.button_names = { "Button 1", "Button 2", "Button 3", "Button 4" },
|
||||
.pov_names = { "POV" }
|
||||
};
|
||||
|
||||
const joystick_if_t joystick_ch_flightstick_pro_ch_pedals = {
|
||||
.name = "CH Flightstick Pro + CH Pedals",
|
||||
.internal_name = "ch_flightstick_pro_ch_pedals",
|
||||
.init = ch_flightstick_pro_init,
|
||||
.close = ch_flightstick_pro_close,
|
||||
.read = ch_flightstick_pro_read,
|
||||
.write = ch_flightstick_pro_write,
|
||||
.read_axis = ch_flightstick_pro_ch_pedals_read_axis,
|
||||
.a0_over = ch_flightstick_pro_a0_over,
|
||||
.axis_count = 4,
|
||||
.button_count = 4,
|
||||
.pov_count = 1,
|
||||
.max_joysticks = 1,
|
||||
.axis_names = { "X axis", "Y axis", "Throttle", "Rudder" },
|
||||
.button_names = { "Button 1", "Button 2", "Button 3", "Button 4" },
|
||||
.pov_names = { "POV" }
|
||||
};
|
||||
|
||||
@@ -112,6 +112,36 @@ tm_fcs_read_axis(UNUSED(void *priv), int axis)
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
tm_fcs_rcs_read_axis(UNUSED(void *priv), int axis)
|
||||
{
|
||||
if (!JOYSTICK_PRESENT(0, 0))
|
||||
return AXIS_NOT_PRESENT;
|
||||
|
||||
switch (axis) {
|
||||
case 0:
|
||||
return joystick_state[0][0].axis[0];
|
||||
case 1:
|
||||
return joystick_state[0][0].axis[1];
|
||||
case 2:
|
||||
return joystick_state[0][0].axis[2];
|
||||
case 3:
|
||||
if (joystick_state[0][0].pov[0] == -1)
|
||||
return 32767;
|
||||
if (joystick_state[0][0].pov[0] > 315 || joystick_state[0][0].pov[0] < 45)
|
||||
return -32768;
|
||||
if (joystick_state[0][0].pov[0] >= 45 && joystick_state[0][0].pov[0] < 135)
|
||||
return -16384;
|
||||
if (joystick_state[0][0].pov[0] >= 135 && joystick_state[0][0].pov[0] < 225)
|
||||
return 0;
|
||||
if (joystick_state[0][0].pov[0] >= 225 && joystick_state[0][0].pov[0] < 315)
|
||||
return 16384;
|
||||
return 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tm_fcs_a0_over(UNUSED(void *priv))
|
||||
{
|
||||
@@ -135,3 +165,21 @@ const joystick_if_t joystick_tm_fcs = {
|
||||
.button_names = { "Button 1", "Button 2", "Button 3", "Button 4" },
|
||||
.pov_names = { "POV" }
|
||||
};
|
||||
|
||||
const joystick_if_t joystick_tm_fcs_rcs = {
|
||||
.name = "Thrustmaster FCS + Rudder Control System",
|
||||
.internal_name = "thrustmaster_fcs_rcs",
|
||||
.init = tm_fcs_init,
|
||||
.close = tm_fcs_close,
|
||||
.read = tm_fcs_read,
|
||||
.write = tm_fcs_write,
|
||||
.read_axis = tm_fcs_rcs_read_axis,
|
||||
.a0_over = tm_fcs_a0_over,
|
||||
.axis_count = 3,
|
||||
.button_count = 4,
|
||||
.pov_count = 1,
|
||||
.max_joysticks = 1,
|
||||
.axis_names = { "X axis", "Y axis", "Rudder" },
|
||||
.button_names = { "Button 1", "Button 2", "Button 3", "Button 4" },
|
||||
.pov_names = { "POV" }
|
||||
};
|
||||
|
||||
@@ -118,7 +118,6 @@ extern int vid_resize; /* (C) allow resizing */
|
||||
extern int invert_display; /* (C) invert the display */
|
||||
extern int suppress_overscan; /* (C) suppress overscans */
|
||||
extern uint32_t lang_id; /* (C) language code identifier */
|
||||
extern char icon_set[256]; /* (C) iconset identifier */
|
||||
extern int scale; /* (C) screen scale factor */
|
||||
extern int dpi_scale; /* (C) DPI scaling of the emulated screen */
|
||||
extern int vid_api; /* (C) video renderer */
|
||||
|
||||
@@ -179,10 +179,12 @@ extern const joystick_if_t joystick_2axis_6button;
|
||||
extern const joystick_if_t joystick_2axis_8button;
|
||||
|
||||
extern const joystick_if_t joystick_ch_flightstick_pro;
|
||||
extern const joystick_if_t joystick_ch_flightstick_pro_ch_pedals;
|
||||
|
||||
extern const joystick_if_t joystick_sw_pad;
|
||||
|
||||
extern const joystick_if_t joystick_tm_fcs;
|
||||
extern const joystick_if_t joystick_tm_fcs_rcs;
|
||||
|
||||
extern int gameport_available(int);
|
||||
extern int gameport_has_config(int);
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* 8080 CPU emulation (header).
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Cacodemon345
|
||||
*
|
||||
* Copyright 2022 Cacodemon345
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct i8080 {
|
||||
union {
|
||||
uint16_t af; /* Intended in case we also go for μPD9002 emulation, which also has a Z80 emulation mode. */
|
||||
struct {
|
||||
uint8_t a;
|
||||
uint8_t flags;
|
||||
};
|
||||
};
|
||||
union {
|
||||
uint16_t bc;
|
||||
struct {
|
||||
uint8_t b;
|
||||
uint8_t c;
|
||||
};
|
||||
};
|
||||
union {
|
||||
uint16_t de;
|
||||
struct {
|
||||
uint8_t d;
|
||||
uint8_t e;
|
||||
};
|
||||
};
|
||||
union {
|
||||
uint16_t hl;
|
||||
struct {
|
||||
uint8_t h;
|
||||
uint8_t l;
|
||||
};
|
||||
};
|
||||
uint16_t pc;
|
||||
uint16_t sp;
|
||||
uint16_t oldpc;
|
||||
uint16_t ei;
|
||||
uint32_t pmembase;
|
||||
uint32_t dmembase; /* Base from where i8080 starts. */
|
||||
uint8_t emulated; /* 0 = not emulated, use separate registers, 1 = emulated, use x86 registers. */
|
||||
uint16_t *cpu_flags;
|
||||
void (*writemembyte)(uint32_t, uint8_t);
|
||||
uint8_t (*readmembyte)(uint32_t);
|
||||
void (*startclock)(void);
|
||||
void (*endclock)(void);
|
||||
void (*checkinterrupts)(void);
|
||||
uint8_t (*fetchinstruction)(void *);
|
||||
} i8080;
|
||||
|
||||
#define C_FLAG_I8080 (1 << 0)
|
||||
#define P_FLAG_I8080 (1 << 2)
|
||||
#define AC_FLAG_I8080 (1 << 4)
|
||||
#define Z_FLAG_I8080 (1 << 6)
|
||||
#define S_FLAG_I8080 (1 << 7)
|
||||
@@ -18,6 +18,12 @@
|
||||
#ifndef VIDEO_8514A_H
|
||||
#define VIDEO_8514A_H
|
||||
|
||||
#define INT_VSY (1 << 0)
|
||||
#define INT_GE_BSY (1 << 1)
|
||||
#define INT_FIFO_OVR (1 << 2)
|
||||
#define INT_FIFO_EMP (1 << 3)
|
||||
#define INT_MASK 0xf
|
||||
|
||||
typedef struct hwcursor8514_t {
|
||||
int ena;
|
||||
int x;
|
||||
@@ -61,6 +67,7 @@ typedef struct ibm8514_t {
|
||||
uint32_t vram_mask;
|
||||
uint32_t pallook[512];
|
||||
uint32_t bios_addr;
|
||||
uint32_t ma_latch;
|
||||
|
||||
PALETTE vgapal;
|
||||
uint8_t hwcursor_oddeven;
|
||||
@@ -85,8 +92,8 @@ typedef struct ibm8514_t {
|
||||
uint16_t advfunc_cntl;
|
||||
uint16_t cur_y;
|
||||
uint16_t cur_x;
|
||||
int16_t destx;
|
||||
int16_t desty;
|
||||
uint16_t destx;
|
||||
uint16_t desty;
|
||||
int16_t desty_axstp;
|
||||
int16_t destx_distp;
|
||||
int16_t err_term;
|
||||
@@ -117,6 +124,8 @@ typedef struct ibm8514_t {
|
||||
int y1;
|
||||
int y2;
|
||||
int temp_cnt;
|
||||
int16_t dx_ibm;
|
||||
int16_t dy_ibm;
|
||||
int16_t cx;
|
||||
int16_t cx_back;
|
||||
int16_t cy;
|
||||
@@ -216,10 +225,9 @@ typedef struct ibm8514_t {
|
||||
uint16_t subsys_cntl;
|
||||
uint8_t subsys_stat;
|
||||
|
||||
atomic_int fifo_idx;
|
||||
atomic_int ext_fifo_idx;
|
||||
atomic_int force_busy;
|
||||
atomic_int force_busy2;
|
||||
atomic_int fifo_idx;
|
||||
|
||||
int blitter_busy;
|
||||
uint64_t blitter_time;
|
||||
@@ -235,6 +243,11 @@ typedef struct ibm8514_t {
|
||||
PALETTE _8514pal;
|
||||
|
||||
latch8514_t latch;
|
||||
|
||||
void (*vblank_start)(void *priv);
|
||||
void (*accel_out_fifo)(void *priv, uint16_t port, uint16_t val, int len);
|
||||
void (*update_irqs)(void *priv);
|
||||
|
||||
} ibm8514_t;
|
||||
|
||||
#endif /*VIDEO_8514A_H*/
|
||||
|
||||
@@ -25,6 +25,7 @@ typedef struct mach_t {
|
||||
rom_t bios_rom;
|
||||
rom_t bios_rom2;
|
||||
mem_mapping_t mmio_linear_mapping;
|
||||
mem_mapping_t banked_mapping;
|
||||
|
||||
int mca_bus;
|
||||
int pci_bus;
|
||||
@@ -71,7 +72,12 @@ typedef struct mach_t {
|
||||
uint8_t bank_r;
|
||||
uint16_t shadow_set;
|
||||
uint16_t shadow_cntl;
|
||||
int override_resolution;
|
||||
uint8_t overscan_col_8;
|
||||
uint8_t overscan_b_col_24;
|
||||
uint8_t overscan_g_col_24;
|
||||
uint8_t overscan_r_col_24;
|
||||
uint16_t fifo_test_data[17];
|
||||
int resolution_crt;
|
||||
|
||||
struct {
|
||||
uint8_t line_idx;
|
||||
@@ -79,9 +85,9 @@ typedef struct mach_t {
|
||||
uint8_t patt_idx;
|
||||
uint8_t patt_len;
|
||||
uint8_t pix_trans[2];
|
||||
uint8_t eeprom_control;
|
||||
uint8_t alu_bg_fn;
|
||||
uint8_t alu_fg_fn;
|
||||
uint16_t eeprom_control;
|
||||
uint16_t clip_left;
|
||||
uint16_t clip_right;
|
||||
uint16_t clip_top;
|
||||
@@ -92,6 +98,7 @@ typedef struct mach_t {
|
||||
uint16_t src_x_end;
|
||||
uint16_t src_x_start;
|
||||
uint16_t src_x;
|
||||
uint16_t r_src_x;
|
||||
uint16_t src_y;
|
||||
int16_t bres_count;
|
||||
uint16_t clock_sel;
|
||||
@@ -100,6 +107,8 @@ typedef struct mach_t {
|
||||
uint16_t dest_cmp_fn;
|
||||
uint16_t dp_config;
|
||||
uint16_t ext_ge_config;
|
||||
uint16_t crt_offset_lo;
|
||||
uint16_t crt_offset_hi;
|
||||
uint16_t ge_offset_lo;
|
||||
uint16_t ge_offset_hi;
|
||||
uint16_t linedraw_opt;
|
||||
@@ -159,6 +168,7 @@ typedef struct mach_t {
|
||||
} accel;
|
||||
|
||||
atomic_int force_busy;
|
||||
atomic_int fifo_test_idx;
|
||||
} mach_t;
|
||||
|
||||
#endif /*VIDEO_ATI_MACH8_H*/
|
||||
|
||||
@@ -144,10 +144,10 @@ typedef struct ega_t {
|
||||
uint32_t (*remap_func)(struct ega_t *ega, uint32_t in_addr);
|
||||
void (*render)(struct ega_t *svga);
|
||||
|
||||
/*If set then another device is driving the monitor output and the EGA
|
||||
card should not attempt to display anything */
|
||||
void (*render_override)(void *priv);
|
||||
void *priv_parent;
|
||||
/* If set then another device is driving the monitor output and the EGA
|
||||
card should not attempt to display anything. */
|
||||
void (*render_override)(void *priv);
|
||||
void * priv_parent;
|
||||
} ega_t;
|
||||
#endif
|
||||
|
||||
@@ -159,6 +159,7 @@ extern const device_t atiega800p_device;
|
||||
extern const device_t iskra_ega_device;
|
||||
extern const device_t et2000_device;
|
||||
extern const device_t jega_device;
|
||||
extern const device_t jvga_device;
|
||||
#endif
|
||||
|
||||
extern int update_overscan;
|
||||
|
||||
@@ -310,6 +310,11 @@ typedef struct svga_t {
|
||||
void * ext8514;
|
||||
void * clock_gen8514;
|
||||
void * xga;
|
||||
|
||||
/* If set then another device is driving the monitor output and the EGA
|
||||
card should not attempt to display anything. */
|
||||
void (*render_override)(void *priv);
|
||||
void * priv_parent;
|
||||
} svga_t;
|
||||
|
||||
extern void ibm8514_set_poll(svga_t *svga);
|
||||
|
||||
@@ -25,14 +25,19 @@
|
||||
typedef struct vga_t {
|
||||
svga_t svga;
|
||||
|
||||
rom_t bios_rom;
|
||||
rom_t bios_rom;
|
||||
} vga_t;
|
||||
|
||||
extern void vga_out(uint16_t addr, uint8_t val, void *priv);
|
||||
extern void vga_out(uint16_t addr, uint8_t val, void *priv);
|
||||
extern uint8_t vga_in(uint16_t addr, void *priv);
|
||||
|
||||
void vga_disable(void* p);
|
||||
void vga_enable(void* p);
|
||||
int vga_isenabled(void* p);
|
||||
extern void vga_init(const device_t *info, vga_t *vga, int enabled);
|
||||
|
||||
extern void vga_disable(void* p);
|
||||
extern void vga_enable(void* p);
|
||||
|
||||
extern int vga_isenabled(void* p);
|
||||
|
||||
extern video_timings_t timing_vga;
|
||||
|
||||
#endif /*VIDEO_VGA_H*/
|
||||
|
||||
@@ -6981,46 +6981,6 @@ const machine_t machines[] = {
|
||||
.snd_device = NULL,
|
||||
.net_device = NULL
|
||||
},
|
||||
/* has a Phoenix PLCC Multikey copyrighted 1993, version unknown. */
|
||||
{
|
||||
.name = "[OPTi 895] Packard Bell PB450",
|
||||
.internal_name = "pb450",
|
||||
.type = MACHINE_TYPE_486_S3_PCI,
|
||||
.chipset = MACHINE_CHIPSET_OPTI_895_802G,
|
||||
.init = machine_at_pb450_init,
|
||||
.p1_handler = NULL,
|
||||
.gpio_handler = NULL,
|
||||
.available_flag = MACHINE_AVAILABLE,
|
||||
.gpio_acpi_handler = NULL,
|
||||
.cpu = {
|
||||
.package = CPU_PKG_SOCKET3,
|
||||
.block = CPU_BLOCK_NONE,
|
||||
.min_bus = 0,
|
||||
.max_bus = 0,
|
||||
.min_voltage = 0,
|
||||
.max_voltage = 0,
|
||||
.min_multi = 0,
|
||||
.max_multi = 0
|
||||
},
|
||||
.bus_flags = MACHINE_PS2_PCI,
|
||||
.flags = MACHINE_SUPER_IO | MACHINE_IDE_DUAL | MACHINE_VIDEO,
|
||||
.ram = {
|
||||
.min = 1024,
|
||||
.max = 65536,
|
||||
.step = 1024
|
||||
},
|
||||
.nvrmask = 255,
|
||||
.kbc_device = NULL,
|
||||
.kbc_p1 = 0xff,
|
||||
.gpio = 0xffffffff,
|
||||
.gpio_acpi = 0xffffffff,
|
||||
.device = &pb450_device,
|
||||
.fdc_device = NULL,
|
||||
.sio_device = NULL,
|
||||
.vid_device = &gd5428_vlb_onboard_device,
|
||||
.snd_device = NULL,
|
||||
.net_device = NULL
|
||||
},
|
||||
/* Uses an NEC 90M002A (UPD82C42C, 8042 clone) with unknown firmware. */
|
||||
{
|
||||
.name = "[SiS 461] Acer V10",
|
||||
@@ -7915,6 +7875,46 @@ const machine_t machines[] = {
|
||||
.snd_device = NULL,
|
||||
.net_device = NULL
|
||||
},
|
||||
/* has a Phoenix PLCC Multikey copyrighted 1993, version unknown. */
|
||||
{
|
||||
.name = "[OPTi 895] Packard Bell PB450",
|
||||
.internal_name = "pb450",
|
||||
.type = MACHINE_TYPE_486_S3_PCI,
|
||||
.chipset = MACHINE_CHIPSET_OPTI_895_802G,
|
||||
.init = machine_at_pb450_init,
|
||||
.p1_handler = NULL,
|
||||
.gpio_handler = NULL,
|
||||
.available_flag = MACHINE_AVAILABLE,
|
||||
.gpio_acpi_handler = NULL,
|
||||
.cpu = {
|
||||
.package = CPU_PKG_SOCKET3,
|
||||
.block = CPU_BLOCK_NONE,
|
||||
.min_bus = 0,
|
||||
.max_bus = 0,
|
||||
.min_voltage = 0,
|
||||
.max_voltage = 0,
|
||||
.min_multi = 0,
|
||||
.max_multi = 0
|
||||
},
|
||||
.bus_flags = MACHINE_PS2_PCI,
|
||||
.flags = MACHINE_SUPER_IO | MACHINE_IDE_DUAL | MACHINE_VIDEO,
|
||||
.ram = {
|
||||
.min = 1024,
|
||||
.max = 65536,
|
||||
.step = 1024
|
||||
},
|
||||
.nvrmask = 255,
|
||||
.kbc_device = NULL,
|
||||
.kbc_p1 = 0xff,
|
||||
.gpio = 0xffffffff,
|
||||
.gpio_acpi = 0xffffffff,
|
||||
.device = &pb450_device,
|
||||
.fdc_device = NULL,
|
||||
.sio_device = NULL,
|
||||
.vid_device = &gd5428_vlb_onboard_device,
|
||||
.snd_device = NULL,
|
||||
.net_device = NULL
|
||||
},
|
||||
/* This has an AMIKey-2, which is an updated version of type 'H'. */
|
||||
{
|
||||
.name = "[i420EX] ASUS PVI-486AP4",
|
||||
@@ -8902,7 +8902,7 @@ const machine_t machines[] = {
|
||||
.min_multi = 0,
|
||||
.max_multi = 0
|
||||
},
|
||||
.bus_flags = MACHINE_PCI,
|
||||
.bus_flags = MACHINE_PS2_PCI,
|
||||
.flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_SOUND | MACHINE_APM,
|
||||
.ram = {
|
||||
.min = 1024,
|
||||
@@ -9358,7 +9358,7 @@ const machine_t machines[] = {
|
||||
.min_multi = MACHINE_MULTIPLIER_FIXED,
|
||||
.max_multi = MACHINE_MULTIPLIER_FIXED
|
||||
},
|
||||
.bus_flags = MACHINE_PCI,
|
||||
.bus_flags = MACHINE_PS2_PCI,
|
||||
.flags = MACHINE_IDE | MACHINE_APM,
|
||||
.ram = {
|
||||
.min = 2048,
|
||||
|
||||
@@ -194,6 +194,9 @@ add_library(ui STATIC
|
||||
qt_openglshaderconfig.hpp
|
||||
qt_openglshaderconfig.cpp
|
||||
qt_openglshaderconfig.ui
|
||||
|
||||
qt_iconindicators.hpp
|
||||
qt_iconindicators.cpp
|
||||
)
|
||||
|
||||
if(RTMIDI)
|
||||
|
||||
BIN
src/qt/icons/active.ico
Normal file
|
After Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
BIN
src/qt/icons/disabled.ico
Normal file
|
After Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
@@ -35,8 +35,6 @@ qt_nvr_save(void)
|
||||
return nvr_save();
|
||||
}
|
||||
|
||||
char icon_set[256] = ""; /* name of the iconset to be used */
|
||||
|
||||
int
|
||||
plat_vidapi(const char *api)
|
||||
{
|
||||
|
||||
33
src/qt/qt_iconindicators.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
#include <QSize>
|
||||
#include <QPainter>
|
||||
#include "qt_iconindicators.hpp"
|
||||
|
||||
QIcon
|
||||
getIndicatorIcon(IconIndicator indicator)
|
||||
{
|
||||
switch (indicator) {
|
||||
case Active:
|
||||
return QIcon(":/settings/qt/icons/active.ico");
|
||||
case Disabled:
|
||||
return QIcon(":/settings/qt/icons/disabled.ico");
|
||||
default:
|
||||
return QIcon();
|
||||
}
|
||||
}
|
||||
|
||||
QPixmap
|
||||
getIconWithIndicator(const QIcon &icon, const QSize &size, QIcon::Mode iconMode, IconIndicator indicator)
|
||||
{
|
||||
auto iconPixmap = icon.pixmap(size, iconMode);
|
||||
|
||||
if (indicator == None)
|
||||
return iconPixmap;
|
||||
|
||||
auto painter = QPainter(&iconPixmap);
|
||||
auto indicatorPixmap = getIndicatorIcon(indicator).pixmap(size);
|
||||
|
||||
painter.drawPixmap(0, 0, indicatorPixmap);
|
||||
painter.end();
|
||||
|
||||
return iconPixmap;
|
||||
}
|
||||
15
src/qt/qt_iconindicators.hpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef QT_ICONINDICATORS_HPP
|
||||
# define QT_INDICATORS_HPP
|
||||
|
||||
#include <QPixmap>
|
||||
#include <QIcon>
|
||||
|
||||
enum IconIndicator {
|
||||
None,
|
||||
Active,
|
||||
Disabled,
|
||||
};
|
||||
|
||||
QPixmap getIconWithIndicator(const QIcon &icon, const QSize &size, QIcon::Mode iconMode, IconIndicator indicator);
|
||||
|
||||
#endif
|
||||
@@ -54,6 +54,7 @@ extern "C" {
|
||||
#include "qt_mainwindow.hpp"
|
||||
#include "qt_soundgain.hpp"
|
||||
#include "qt_progsettings.hpp"
|
||||
#include "qt_iconindicators.hpp"
|
||||
|
||||
#include <array>
|
||||
|
||||
@@ -65,19 +66,24 @@ namespace {
|
||||
struct PixmapSetActive {
|
||||
QPixmap normal;
|
||||
QPixmap active;
|
||||
void load(const QString &basePath);
|
||||
void load(const QIcon &icon);
|
||||
};
|
||||
struct PixmapSetDisabled {
|
||||
QPixmap normal;
|
||||
QPixmap disabled;
|
||||
void load(const QIcon &icon);
|
||||
};
|
||||
struct PixmapSetEmpty {
|
||||
QPixmap normal;
|
||||
QPixmap empty;
|
||||
void load(const QString &basePath);
|
||||
void load(const QIcon &icon);
|
||||
};
|
||||
struct PixmapSetEmptyActive {
|
||||
QPixmap normal;
|
||||
QPixmap active;
|
||||
QPixmap empty;
|
||||
QPixmap empty_active;
|
||||
void load(QString basePath);
|
||||
void load(const QIcon &icon);
|
||||
};
|
||||
struct Pixmaps {
|
||||
PixmapSetEmpty cartridge;
|
||||
@@ -90,7 +96,7 @@ struct Pixmaps {
|
||||
PixmapSetEmptyActive mo;
|
||||
PixmapSetActive hd;
|
||||
PixmapSetEmptyActive net;
|
||||
QPixmap sound, soundMuted;
|
||||
PixmapSetDisabled sound;
|
||||
};
|
||||
|
||||
struct StateActive {
|
||||
@@ -170,30 +176,35 @@ struct StateEmptyActive {
|
||||
};
|
||||
|
||||
static QSize pixmap_size(16, 16);
|
||||
static const QString pixmap_empty = QStringLiteral("_empty");
|
||||
static const QString pixmap_active = QStringLiteral("_active");
|
||||
static const QString pixmap_empty_active = QStringLiteral("_empty_active");
|
||||
|
||||
void
|
||||
PixmapSetEmpty::load(const QString &basePath)
|
||||
PixmapSetEmpty::load(const QIcon &icon)
|
||||
{
|
||||
normal = ProgSettings::loadIcon(basePath.arg(QStringLiteral(""))).pixmap(pixmap_size);
|
||||
empty = ProgSettings::loadIcon(basePath.arg(pixmap_empty)).pixmap(pixmap_size);
|
||||
normal = getIconWithIndicator(icon, pixmap_size, QIcon::Normal, None);
|
||||
empty = getIconWithIndicator(icon, pixmap_size, QIcon::Disabled, None);
|
||||
}
|
||||
|
||||
void
|
||||
PixmapSetActive::load(const QString &basePath)
|
||||
PixmapSetActive::load(const QIcon &icon)
|
||||
{
|
||||
normal = ProgSettings::loadIcon(basePath.arg(QStringLiteral(""))).pixmap(pixmap_size);
|
||||
active = ProgSettings::loadIcon(basePath.arg(pixmap_active)).pixmap(pixmap_size);
|
||||
normal = getIconWithIndicator(icon, pixmap_size, QIcon::Normal, None);
|
||||
active = getIconWithIndicator(icon, pixmap_size, QIcon::Normal, Active);
|
||||
}
|
||||
|
||||
void
|
||||
PixmapSetEmptyActive::load(QString basePath)
|
||||
PixmapSetDisabled::load(const QIcon &icon)
|
||||
{
|
||||
normal = ProgSettings::loadIcon(basePath.arg(QStringLiteral(""))).pixmap(pixmap_size);
|
||||
active = ProgSettings::loadIcon(basePath.arg(pixmap_active)).pixmap(pixmap_size);
|
||||
empty = ProgSettings::loadIcon(basePath.arg(pixmap_empty)).pixmap(pixmap_size);
|
||||
empty_active = ProgSettings::loadIcon(basePath.arg(pixmap_empty_active)).pixmap(pixmap_size);
|
||||
normal = getIconWithIndicator(icon, pixmap_size, QIcon::Normal, None);
|
||||
disabled = getIconWithIndicator(icon, pixmap_size, QIcon::Disabled, Disabled);
|
||||
}
|
||||
|
||||
void
|
||||
PixmapSetEmptyActive::load(const QIcon &icon)
|
||||
{
|
||||
normal = getIconWithIndicator(icon, pixmap_size, QIcon::Normal, None);
|
||||
active = getIconWithIndicator(icon, pixmap_size, QIcon::Normal, Active);
|
||||
empty = getIconWithIndicator(icon, pixmap_size, QIcon::Disabled, None);
|
||||
empty_active = getIconWithIndicator(icon, pixmap_size, QIcon::Disabled, Active);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,21 +213,20 @@ struct MachineStatus::States {
|
||||
|
||||
States(QObject *parent)
|
||||
{
|
||||
pixmaps.cartridge.load("/cartridge%1.ico");
|
||||
pixmaps.cassette.load("/cassette%1.ico");
|
||||
pixmaps.floppy_disabled.normal = ProgSettings::loadIcon(QStringLiteral("/floppy_disabled.ico")).pixmap(pixmap_size);
|
||||
pixmaps.cartridge.load(QIcon(":/settings/qt/icons/cartridge.ico"));
|
||||
pixmaps.cassette.load(QIcon(":/settings/qt/icons/cassette.ico"));
|
||||
pixmaps.floppy_disabled.normal = QIcon(":/settings/qt/icons/floppy_disabled.ico").pixmap(pixmap_size);
|
||||
pixmaps.floppy_disabled.active = pixmaps.floppy_disabled.normal;
|
||||
pixmaps.floppy_disabled.empty = pixmaps.floppy_disabled.normal;
|
||||
pixmaps.floppy_disabled.empty_active = pixmaps.floppy_disabled.normal;
|
||||
pixmaps.floppy_525.load("/floppy_525%1.ico");
|
||||
pixmaps.floppy_35.load("/floppy_35%1.ico");
|
||||
pixmaps.cdrom.load("/cdrom%1.ico");
|
||||
pixmaps.zip.load("/zip%1.ico");
|
||||
pixmaps.mo.load("/mo%1.ico");
|
||||
pixmaps.hd.load("/hard_disk%1.ico");
|
||||
pixmaps.net.load("/network%1.ico");
|
||||
pixmaps.sound = ProgSettings::loadIcon("/sound.ico").pixmap(pixmap_size);
|
||||
pixmaps.soundMuted = ProgSettings::loadIcon("/sound_mute.ico").pixmap(pixmap_size);
|
||||
pixmaps.floppy_525.load(QIcon(":/settings/qt/icons/floppy_525.ico"));
|
||||
pixmaps.floppy_35.load(QIcon(":/settings/qt/icons/floppy_35.ico"));
|
||||
pixmaps.cdrom.load(QIcon(":/settings/qt/icons/cdrom.ico"));
|
||||
pixmaps.zip.load(QIcon(":/settings/qt/icons/zip.ico"));
|
||||
pixmaps.mo.load(QIcon(":/settings/qt/icons/mo.ico"));
|
||||
pixmaps.hd.load(QIcon(":/settings/qt/icons/hard_disk.ico"));
|
||||
pixmaps.net.load(QIcon(":/settings/qt/icons/network.ico"));
|
||||
pixmaps.sound.load(QIcon(":/settings/qt/icons/sound.ico"));
|
||||
|
||||
cartridge[0].pixmaps = &pixmaps.cartridge;
|
||||
cartridge[1].pixmaps = &pixmaps.cartridge;
|
||||
@@ -510,8 +520,8 @@ MachineStatus::refresh(QStatusBar *sbar)
|
||||
sound_muted ^= 1;
|
||||
config_save();
|
||||
if (d->sound)
|
||||
d->sound->setPixmap(sound_muted ? d->pixmaps.soundMuted : d->pixmaps.sound);
|
||||
|
||||
d->sound->setPixmap(sound_muted ? d->pixmaps.sound.disabled : d->pixmaps.sound.normal);
|
||||
|
||||
muteUnmuteAction->setText(sound_muted ? tr("&Unmute") : tr("&Mute"));
|
||||
});
|
||||
}
|
||||
@@ -694,10 +704,10 @@ MachineStatus::refresh(QStatusBar *sbar)
|
||||
}
|
||||
|
||||
d->sound = std::make_unique<ClickableLabel>();
|
||||
d->sound->setPixmap(sound_muted ? d->pixmaps.soundMuted : d->pixmaps.sound);
|
||||
d->sound->setPixmap(sound_muted ? d->pixmaps.sound.disabled : d->pixmaps.sound.normal);
|
||||
if (muteUnmuteAction)
|
||||
muteUnmuteAction->setText(sound_muted ? tr("&Unmute") : tr("&Mute"));
|
||||
|
||||
|
||||
connect(d->sound.get(), &ClickableLabel::clicked, this, [this](QPoint pos) {
|
||||
this->soundMenu->popup(pos - QPoint(0, this->soundMenu->sizeHint().height()));
|
||||
});
|
||||
|
||||
@@ -94,6 +94,8 @@ extern int qt_nvr_save(void);
|
||||
bool cpu_thread_running = false;
|
||||
}
|
||||
|
||||
#include <locale.h>
|
||||
|
||||
void qt_set_sequence_auto_mnemonic(bool b);
|
||||
|
||||
#ifdef Q_OS_WINDOWS
|
||||
@@ -525,6 +527,7 @@ main(int argc, char *argv[])
|
||||
|
||||
QApplication app(argc, argv);
|
||||
QLocale::setDefault(QLocale::C);
|
||||
setlocale(LC_NUMERIC, "C");
|
||||
|
||||
#ifdef Q_OS_WINDOWS
|
||||
Q_INIT_RESOURCE(darkstyle);
|
||||
|
||||
@@ -154,10 +154,10 @@ MediaMenu::refresh(QMenu *parentMenu)
|
||||
MachineStatus::iterateCDROM([this, parentMenu](int i) {
|
||||
auto *menu = parentMenu->addMenu("");
|
||||
cdromMutePos = menu->children().count();
|
||||
menu->addAction(ProgSettings::loadIcon("/cdrom_mute.ico"), tr("&Mute"), [this, i]() { cdromMute(i); })->setCheckable(true);
|
||||
menu->addAction(QIcon(":/settings/qt/icons/cdrom_mute.ico"), tr("&Mute"), [this, i]() { cdromMute(i); })->setCheckable(true);
|
||||
menu->addSeparator();
|
||||
menu->addAction(ProgSettings::loadIcon("/cdrom_image.ico"), tr("&Image..."), [this, i]() { cdromMount(i, 0, nullptr); })->setCheckable(false);
|
||||
menu->addAction(ProgSettings::loadIcon("/cdrom_folder.ico"), tr("&Folder..."), [this, i]() { cdromMount(i, 1, nullptr); })->setCheckable(false);
|
||||
menu->addAction(QIcon(":/settings/qt/icons/cdrom_image.ico"), tr("&Image..."), [this, i]() { cdromMount(i, 0, nullptr); })->setCheckable(false);
|
||||
menu->addAction(QIcon(":/settings/qt/icons/cdrom_folder.ico"), tr("&Folder..."), [this, i]() { cdromMount(i, 1, nullptr); })->setCheckable(false);
|
||||
menu->addSeparator();
|
||||
for (int slot = 0; slot < MAX_PREV_IMAGES; slot++) {
|
||||
cdromImageHistoryPos[slot] = menu->children().count();
|
||||
@@ -170,7 +170,7 @@ MediaMenu::refresh(QMenu *parentMenu)
|
||||
for (const auto &letter : driveLetters) {
|
||||
auto drive = QString("%1:\\").arg(letter);
|
||||
if (GetDriveType(drive.toUtf8().constData()) == DRIVE_CDROM)
|
||||
menu->addAction(ProgSettings::loadIcon("/cdrom_host.ico"), tr("Host CD/DVD Drive (%1:)").arg(letter), [this, i, letter] { cdromMount(i, 2, QString(R"(\\.\%1:)").arg(letter)); })->setCheckable(false);
|
||||
menu->addAction(QIcon(":/settings/qt/icons/cdrom_host.ico"), tr("Host CD/DVD Drive (%1:)").arg(letter), [this, i, letter] { cdromMount(i, 2, QString(R"(\\.\%1:)").arg(letter)); })->setCheckable(false);
|
||||
}
|
||||
menu->addSeparator();
|
||||
#endif // Q_OS_WINDOWS
|
||||
@@ -666,7 +666,7 @@ MediaMenu::updateImageHistory(int index, int slot, ui::MediaType type)
|
||||
children = menu->children();
|
||||
imageHistoryUpdatePos = dynamic_cast<QAction *>(children[cdromImageHistoryPos[slot]]);
|
||||
if (fn.left(8) == "ioctl://") {
|
||||
menu_icon = ProgSettings::loadIcon("/cdrom_host.ico");
|
||||
menu_icon = QIcon(":/settings/qt/icons/cdrom_host.ico");
|
||||
#ifdef Q_OS_WINDOWS
|
||||
menu_item_name = tr("Host CD/DVD Drive (%1)").arg(fn.right(2)).toUtf8().constData();
|
||||
#else
|
||||
@@ -674,7 +674,7 @@ MediaMenu::updateImageHistory(int index, int slot, ui::MediaType type)
|
||||
#endif
|
||||
} else {
|
||||
fi.setFile(fn);
|
||||
menu_icon = fi.isDir() ? ProgSettings::loadIcon("/cdrom_folder.ico") : ProgSettings::loadIcon("/cdrom_image.ico");
|
||||
menu_icon = fi.isDir() ? QIcon(":/settings/qt/icons/cdrom_folder.ico") : QIcon(":/settings/qt/icons/cdrom_image.ico");
|
||||
menu_item_name = fn.isEmpty() ? tr("previous image").toUtf8().constData() : fn.toUtf8().constData();
|
||||
}
|
||||
imageHistoryUpdatePos->setIcon(menu_icon);
|
||||
@@ -727,7 +727,7 @@ MediaMenu::cdromUpdateMenu(int i)
|
||||
auto childs = menu->children();
|
||||
|
||||
auto *muteMenu = dynamic_cast<QAction *>(childs[cdromMutePos]);
|
||||
muteMenu->setIcon(ProgSettings::loadIcon((cdrom[i].sound_on == 0) ? "/cdrom_unmute.ico" : "/cdrom_mute.ico"));
|
||||
muteMenu->setIcon(QIcon((cdrom[i].sound_on == 0) ? ":/settings/qt/icons/cdrom_unmute.ico" : ":/settings/qt/icons/cdrom_mute.ico"));
|
||||
muteMenu->setText((cdrom[i].sound_on == 0) ? tr("&Unmute") : tr("&Mute"));
|
||||
|
||||
auto *imageMenu = dynamic_cast<QAction *>(childs[cdromImagePos]);
|
||||
@@ -740,13 +740,13 @@ MediaMenu::cdromUpdateMenu(int i)
|
||||
menu_item_name = tr("Host CD/DVD Drive (%1)").arg(name.right(name.length() - 8));
|
||||
#endif
|
||||
name2 = menu_item_name;
|
||||
menu_icon = ProgSettings::loadIcon("/cdrom_host.ico");
|
||||
menu_icon = QIcon(":/settings/qt/icons/cdrom_host.ico");
|
||||
} else {
|
||||
QFileInfo fi(cdrom[i].image_path);
|
||||
|
||||
menu_item_name = name.isEmpty() ? QString().toUtf8().constData() : name.toUtf8().constData();
|
||||
name2 = name;
|
||||
menu_icon = fi.isDir() ? ProgSettings::loadIcon("/cdrom_folder.ico") : ProgSettings::loadIcon("/cdrom_image.ico");
|
||||
menu_icon = fi.isDir() ? QIcon(":/settings/qt/icons/cdrom_folder.ico") : QIcon(":/settings/qt/icons/cdrom_image.ico");
|
||||
}
|
||||
imageMenu->setIcon(menu_icon);
|
||||
imageMenu->setText(QString::asprintf(tr("Eject %s").toUtf8().constData(), menu_item_name.toUtf8().constData()));
|
||||
|
||||
@@ -36,71 +36,16 @@ extern "C" {
|
||||
#include <86box/rom.h>
|
||||
}
|
||||
|
||||
static QMap<QString, QString> iconset_to_qt;
|
||||
extern MainWindow *main_window;
|
||||
|
||||
ProgSettings::CustomTranslator *ProgSettings::translator = nullptr;
|
||||
QTranslator *ProgSettings::qtTranslator = nullptr;
|
||||
QString
|
||||
ProgSettings::getIconSetPath()
|
||||
{
|
||||
if (iconset_to_qt.isEmpty()) {
|
||||
// Always include default bundled icons
|
||||
iconset_to_qt.insert("", ":/settings/qt/icons");
|
||||
// Walk rom_paths to get the candidates
|
||||
for (rom_path_t *emu_rom_path = &rom_paths; emu_rom_path != nullptr; emu_rom_path = emu_rom_path->next) {
|
||||
// Check for icons subdir in each candidate
|
||||
QDir roms_icons_dir(QString(emu_rom_path->path) + "/icons");
|
||||
if (roms_icons_dir.isReadable()) {
|
||||
auto dirList = roms_icons_dir.entryList(QDir::AllDirs | QDir::Executable | QDir::Readable);
|
||||
for (auto &curIconSet : dirList) {
|
||||
if (curIconSet == "." || curIconSet == "..") {
|
||||
continue;
|
||||
}
|
||||
iconset_to_qt.insert(curIconSet, (roms_icons_dir.canonicalPath() + '/') + curIconSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return iconset_to_qt[icon_set];
|
||||
}
|
||||
|
||||
QIcon
|
||||
ProgSettings::loadIcon(QString file)
|
||||
{
|
||||
(void) getIconSetPath();
|
||||
if (!QFile::exists(iconset_to_qt[icon_set] + file))
|
||||
return QIcon(iconset_to_qt[""] + file);
|
||||
return QIcon(iconset_to_qt[icon_set] + file);
|
||||
}
|
||||
|
||||
ProgSettings::ProgSettings(QWidget *parent)
|
||||
: QDialog(parent)
|
||||
, ui(new Ui::ProgSettings)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
(void) getIconSetPath();
|
||||
ui->comboBox->setItemData(0, "");
|
||||
ui->comboBox->setCurrentIndex(0);
|
||||
for (auto i = iconset_to_qt.begin(); i != iconset_to_qt.end(); i++) {
|
||||
if (i.key() == "")
|
||||
continue;
|
||||
QFile iconfile(i.value() + "/iconinfo.txt");
|
||||
iconfile.open(QFile::ReadOnly);
|
||||
QString friendlyName;
|
||||
QString iconsetinfo(iconfile.readAll());
|
||||
iconfile.close();
|
||||
if (iconsetinfo.isEmpty())
|
||||
friendlyName = i.key();
|
||||
else
|
||||
friendlyName = iconsetinfo.split('\n')[0];
|
||||
ui->comboBox->addItem(friendlyName, i.key());
|
||||
if (strcmp(icon_set, i.key().toUtf8().data()) == 0) {
|
||||
ui->comboBox->setCurrentIndex(ui->comboBox->findData(i.key()));
|
||||
}
|
||||
}
|
||||
ui->comboBox->setItemData(0, '(' + tr("Default") + ')', Qt::DisplayRole);
|
||||
|
||||
ui->comboBoxLanguage->setItemData(0, 0xFFFF);
|
||||
for (auto i = lcid_langcode.begin(); i != lcid_langcode.end(); i++) {
|
||||
if (i.key() == 0xFFFF)
|
||||
@@ -129,7 +74,6 @@ ProgSettings::ProgSettings(QWidget *parent)
|
||||
void
|
||||
ProgSettings::accept()
|
||||
{
|
||||
strcpy(icon_set, ui->comboBox->currentData().toString().toUtf8().data());
|
||||
lang_id = ui->comboBoxLanguage->currentData().toUInt();
|
||||
open_dir_usr_path = ui->openDirUsrPath->isChecked() ? 1 : 0;
|
||||
confirm_exit = ui->checkBoxConfirmExit->isChecked() ? 1 : 0;
|
||||
@@ -161,12 +105,6 @@ ProgSettings::~ProgSettings()
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void
|
||||
ProgSettings::on_pushButton_released()
|
||||
{
|
||||
ui->comboBox->setCurrentIndex(0);
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WINDOWS
|
||||
/* Return the standard font name on Windows, which is overridden per-language
|
||||
to prevent CJK fonts with embedded bitmaps being chosen as a fallback. */
|
||||
|
||||
@@ -14,8 +14,6 @@ class ProgSettings : public QDialog {
|
||||
public:
|
||||
explicit ProgSettings(QWidget *parent = nullptr);
|
||||
~ProgSettings();
|
||||
static QString getIconSetPath();
|
||||
static QIcon loadIcon(QString file);
|
||||
#ifdef Q_OS_WINDOWS
|
||||
static QString getFontName(uint32_t lcid);
|
||||
#endif
|
||||
@@ -56,7 +54,6 @@ public:
|
||||
protected slots:
|
||||
void accept() override;
|
||||
private slots:
|
||||
void on_pushButton_released();
|
||||
void on_pushButtonLanguage_released();
|
||||
|
||||
void on_horizontalSlider_valueChanged(int value);
|
||||
|
||||
@@ -29,21 +29,14 @@
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SizeConstraint::SetFixedSize</enum>
|
||||
</property>
|
||||
<item row="5" column="1">
|
||||
<item row="2" column="1">
|
||||
<widget class="QPushButton" name="pushButtonLanguage">
|
||||
<property name="text">
|
||||
<string>Default</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Icon set:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<item row="5" column="0">
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
@@ -56,7 +49,7 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QComboBox" name="comboBoxLanguage">
|
||||
<property name="maxVisibleItems">
|
||||
<number>30</number>
|
||||
@@ -68,7 +61,7 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<item row="6" column="0">
|
||||
<widget class="QCheckBox" name="openDirUsrPath">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>When selecting media images (CD-ROM, floppy, etc.) the open dialog will start in the same directory as the 86Box configuration file. This setting will likely only make a difference on macOS.</p></body></html></string>
|
||||
@@ -78,14 +71,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<property name="text">
|
||||
<string>Default</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<item row="2" column="0">
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
@@ -98,14 +84,14 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<item row="5" column="1">
|
||||
<widget class="QPushButton" name="pushButton_2">
|
||||
<property name="text">
|
||||
<string>Default</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="3">
|
||||
<item row="4" column="0" colspan="3">
|
||||
<widget class="QSlider" name="horizontalSlider">
|
||||
<property name="minimum">
|
||||
<number>10</number>
|
||||
@@ -127,21 +113,21 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Language:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<item row="8" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxConfirmSave">
|
||||
<property name="text">
|
||||
<string>Ask for confirmation before saving settings</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="16" column="0" colspan="2">
|
||||
<item row="13" column="0" colspan="2">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
@@ -151,63 +137,35 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<item row="7" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxMultimediaKeys">
|
||||
<property name="text">
|
||||
<string>Inhibit multimedia keys on Windows</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QComboBox" name="comboBox">
|
||||
<property name="editable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="maxVisibleItems">
|
||||
<number>30</number>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>(Default)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Mouse sensitivity:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="0">
|
||||
<item row="10" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxConfirmHardReset">
|
||||
<property name="text">
|
||||
<string>Ask for confirmation before hard resetting</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<item row="9" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxConfirmExit">
|
||||
<property name="text">
|
||||
<string>Ask for confirmation before quitting</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="0">
|
||||
<item row="11" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxFullscreenFirst">
|
||||
<property name="text">
|
||||
<string>Display hotkey message when entering full-screen mode</string>
|
||||
|
||||
@@ -95,7 +95,7 @@ SettingsModel::data(const QModelIndex &index, int role) const
|
||||
case Qt::DisplayRole:
|
||||
return tr(pages.at(index.row()).toUtf8().data());
|
||||
case Qt::DecorationRole:
|
||||
return QIcon(QString("%1/%2.ico").arg(ProgSettings::getIconSetPath(), page_icons[index.row()]));
|
||||
return QIcon(QString(":/settings/qt/icons/%1.ico").arg(page_icons[index.row()]));
|
||||
case Qt::SizeHintRole:
|
||||
return QSize(-1, fontHeight * 2);
|
||||
default:
|
||||
|
||||
@@ -46,11 +46,11 @@ setFloppyType(QAbstractItemModel *model, const QModelIndex &idx, int type)
|
||||
{
|
||||
QIcon icon;
|
||||
if (type == 0)
|
||||
icon = ProgSettings::loadIcon("/floppy_disabled.ico");
|
||||
icon = QIcon(":/settings/qt/icons/floppy_disabled.ico");
|
||||
else if (type >= 1 && type <= 6)
|
||||
icon = ProgSettings::loadIcon("/floppy_525.ico");
|
||||
icon = QIcon(":/settings/qt/icons/floppy_525.ico");
|
||||
else
|
||||
icon = ProgSettings::loadIcon("/floppy_35.ico");
|
||||
icon = QIcon(":/settings/qt/icons/floppy_35.ico");
|
||||
|
||||
model->setData(idx, QObject::tr(fdd_getname(type)));
|
||||
model->setData(idx, type, Qt::UserRole);
|
||||
@@ -64,12 +64,12 @@ setCDROMBus(QAbstractItemModel *model, const QModelIndex &idx, uint8_t bus, uint
|
||||
|
||||
switch (bus) {
|
||||
case CDROM_BUS_DISABLED:
|
||||
icon = ProgSettings::loadIcon("/cdrom_disabled.ico");
|
||||
icon = QIcon(":/settings/qt/icons/cdrom_disabled.ico");
|
||||
break;
|
||||
case CDROM_BUS_ATAPI:
|
||||
case CDROM_BUS_SCSI:
|
||||
case CDROM_BUS_MITSUMI:
|
||||
icon = ProgSettings::loadIcon("/cdrom.ico");
|
||||
icon = QIcon(":/settings/qt/icons/cdrom.ico");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ addRow(QAbstractItemModel *model, hard_disk_t *hd)
|
||||
|
||||
QString busName = Harddrives::BusChannelName(hd->bus_type, hd->channel);
|
||||
model->setData(model->index(row, ColumnBus), busName);
|
||||
model->setData(model->index(row, ColumnBus), ProgSettings::loadIcon("/hard_disk.ico"), Qt::DecorationRole);
|
||||
model->setData(model->index(row, ColumnBus), QIcon(":/settings/qt/icons/hard_disk.ico"), Qt::DecorationRole);
|
||||
model->setData(model->index(row, ColumnBus), hd->bus_type, DataBus);
|
||||
model->setData(model->index(row, ColumnBus), hd->bus_type, DataBusPrevious);
|
||||
model->setData(model->index(row, ColumnBus), hd->channel, DataBusChannel);
|
||||
|
||||
@@ -88,20 +88,31 @@ SettingsMachine::SettingsMachine(QWidget *parent)
|
||||
ui->comboBoxPitMode->setCurrentIndex(-1);
|
||||
ui->comboBoxPitMode->setCurrentIndex(pit_mode + 1);
|
||||
|
||||
int selectedMachineType = 0;
|
||||
auto *machineTypesModel = ui->comboBoxMachineType->model();
|
||||
for (int i = 1; i < MACHINE_TYPE_MAX; ++i) {
|
||||
int j = 0;
|
||||
while (machine_get_internal_name_ex(j) != nullptr) {
|
||||
if (machine_available(j) && (machine_get_type(j) == i)) {
|
||||
int selectedMachineType = 0;
|
||||
auto * machineTypesModel = ui->comboBoxMachineType->model();
|
||||
int i = -1;
|
||||
int j = 0;
|
||||
int cur_j = 0;
|
||||
const void *miname;
|
||||
do {
|
||||
miname = machine_get_internal_name_ex(j);
|
||||
|
||||
if ((miname == nullptr) || (machine_get_type(j) != i)) {
|
||||
if ((i != -1) && (cur_j != 0)) {
|
||||
int row = Models::AddEntry(machineTypesModel, machine_types[i].name, machine_types[i].id);
|
||||
if (machine_types[i].id == machine_get_type(machine))
|
||||
selectedMachineType = row;
|
||||
break;
|
||||
}
|
||||
j++;
|
||||
|
||||
i = machine_get_type(j);
|
||||
cur_j = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (machine_available(j))
|
||||
cur_j++;
|
||||
|
||||
j++;
|
||||
} while (miname != nullptr);
|
||||
|
||||
ui->comboBoxMachineType->setCurrentIndex(-1);
|
||||
ui->comboBoxMachineType->setCurrentIndex(selectedMachineType);
|
||||
|
||||
@@ -35,25 +35,58 @@ SettingsNetwork::enableElements(Ui::SettingsNetwork *ui)
|
||||
for (int i = 0; i < NET_CARD_MAX; ++i) {
|
||||
auto *nic_cbox = findChild<QComboBox *>(QString("comboBoxNIC%1").arg(i + 1));
|
||||
auto *net_type_cbox = findChild<QComboBox *>(QString("comboBoxNet%1").arg(i + 1));
|
||||
|
||||
auto *intf_label = findChild<QLabel *>(QString("interfaceLabel%1").arg(i + 1));
|
||||
auto *intf_cbox = findChild<QComboBox *>(QString("comboBoxIntf%1").arg(i + 1));
|
||||
|
||||
auto *conf_btn = findChild<QPushButton *>(QString("pushButtonConf%1").arg(i + 1));
|
||||
// auto *net_type_conf_btn = findChild<QPushButton *>(QString("pushButtonNetTypeConf%1").arg(i + 1));
|
||||
|
||||
auto *vde_socket_label = findChild<QLabel *>(QString("socketVDELabel%1").arg(i + 1));
|
||||
auto *socket_line = findChild<QLineEdit *>(QString("socketVDENIC%1").arg(i + 1));
|
||||
|
||||
int netType = net_type_cbox->currentData().toInt();
|
||||
bool adaptersEnabled = netType == NET_TYPE_NONE
|
||||
|| netType == NET_TYPE_SLIRP
|
||||
|| netType == NET_TYPE_VDE
|
||||
|| (netType == NET_TYPE_PCAP && intf_cbox->currentData().toInt() > 0);
|
||||
auto *option_list_label = findChild<QLabel *>(QString("optionListLabel%1").arg(i + 1));
|
||||
auto *option_list_line = findChild<QWidget *>(QString("optionListLine%1").arg(i + 1));
|
||||
|
||||
intf_cbox->setEnabled(net_type_cbox->currentData().toInt() == NET_TYPE_PCAP);
|
||||
nic_cbox->setEnabled(adaptersEnabled);
|
||||
int netCard = nic_cbox->currentData().toInt();
|
||||
if ((i == 0) && (netCard == NET_INTERNAL))
|
||||
conf_btn->setEnabled(adaptersEnabled && machine_has_flags(machineId, MACHINE_NIC) &&
|
||||
device_has_config(machine_get_net_device(machineId)));
|
||||
else
|
||||
conf_btn->setEnabled(adaptersEnabled && network_card_has_config(nic_cbox->currentData().toInt()));
|
||||
socket_line->setEnabled(net_type_cbox->currentData().toInt() == NET_TYPE_VDE);
|
||||
conf_btn->setEnabled(network_card_has_config(nic_cbox->currentData().toInt()));
|
||||
// net_type_conf_btn->setEnabled(network_type_has_config(netType));
|
||||
|
||||
// Option list label and line
|
||||
option_list_label->setVisible(false);
|
||||
option_list_line->setVisible(false);
|
||||
|
||||
|
||||
// VDE
|
||||
vde_socket_label->setVisible(false);
|
||||
socket_line->setVisible(false);
|
||||
|
||||
// PCAP
|
||||
intf_cbox->setVisible(false);
|
||||
intf_label->setVisible(false);
|
||||
|
||||
// Don't enable anything unless there's a nic selected
|
||||
if(nic_cbox->currentData().toInt() != 0) {
|
||||
// Then only enable as needed based on network type
|
||||
switch (net_type_cbox->currentData().toInt()) {
|
||||
case NET_TYPE_VDE:
|
||||
// option_list_label->setText("VDE Options");
|
||||
option_list_label->setVisible(true);
|
||||
option_list_line->setVisible(true);
|
||||
|
||||
vde_socket_label->setVisible(true);
|
||||
socket_line->setVisible(true);
|
||||
break;
|
||||
case NET_TYPE_PCAP:
|
||||
// option_list_label->setText("PCAP Options");
|
||||
option_list_label->setVisible(true);
|
||||
option_list_line->setVisible(true);
|
||||
|
||||
intf_cbox->setVisible(true);
|
||||
intf_label->setVisible(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,7 +187,7 @@ SettingsNetwork::onCurrentMachineChanged(int machineId)
|
||||
}
|
||||
|
||||
model->removeRows(0, removeRows);
|
||||
cbox->setCurrentIndex(net_cards_conf[i].net_type);
|
||||
cbox->setCurrentIndex(cbox->findData(net_cards_conf[i].net_type));
|
||||
|
||||
selectedRow = 0;
|
||||
|
||||
|
||||
@@ -36,20 +36,7 @@
|
||||
<string>Network Card #1</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="2">
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="comboBoxNet1">
|
||||
<property name="maxVisibleItems">
|
||||
<number>30</number>
|
||||
@@ -63,32 +50,6 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Interface</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="2">
|
||||
<widget class="QComboBox" name="comboBoxIntf1">
|
||||
<property name="maxVisibleItems">
|
||||
<number>30</number>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
@@ -101,23 +62,40 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="comboBoxNIC1">
|
||||
<property name="maxVisibleItems">
|
||||
<number>30</number>
|
||||
<item row="6" column="1">
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToContents</enum>
|
||||
<property name="text">
|
||||
<string>Mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<item row="2" column="1" colspan="2">
|
||||
<widget class="Line" name="optionListLine1">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="pushButtonConf1">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
@@ -130,21 +108,74 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="optionListLabel1">
|
||||
<property name="text">
|
||||
<string>Options</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<widget class="QLabel" name="interfaceLabel1">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Interface</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="socketVDELabel1">
|
||||
<property name="text">
|
||||
<string>VDE Socket</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" colspan="2">
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="comboBoxNIC1">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToContents</enum>
|
||||
</property>
|
||||
<property name="maxVisibleItems">
|
||||
<number>30</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLineEdit" name="socketVDENIC1">
|
||||
<property name="maxLength">
|
||||
<number>127</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="comboBoxIntf1">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_2">
|
||||
<attribute name="title">
|
||||
<string>Network Card #2</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="6" column="1">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
@@ -157,13 +188,26 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_2">
|
||||
<attribute name="title">
|
||||
<string>Network Card #2</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="interfaceLabel2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Interface</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="optionListLabel2">
|
||||
<property name="text">
|
||||
<string>Options</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="sizePolicy">
|
||||
@@ -177,7 +221,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="2">
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="comboBoxNet2">
|
||||
<property name="maxVisibleItems">
|
||||
<number>30</number>
|
||||
@@ -190,33 +234,21 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="socketVDELabel2">
|
||||
<property name="text">
|
||||
<string>Interface</string>
|
||||
<string>VDE Socket</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="2">
|
||||
<widget class="QComboBox" name="comboBoxIntf2">
|
||||
<property name="maxVisibleItems">
|
||||
<number>30</number>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
<item row="2" column="1" colspan="2">
|
||||
<widget class="Line" name="optionListLine2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
@@ -229,7 +261,20 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="pushButtonConf2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="comboBoxNIC2">
|
||||
<property name="maxVisibleItems">
|
||||
<number>30</number>
|
||||
@@ -245,40 +290,19 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QPushButton" name="pushButtonConf2">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLineEdit" name="socketVDENIC2"/>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="comboBoxIntf2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>VDE Socket</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" colspan="2">
|
||||
<widget class="QLineEdit" name="socketVDENIC2">
|
||||
<property name="maxLength">
|
||||
<number>127</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_3">
|
||||
@@ -286,6 +310,69 @@
|
||||
<string>Network Card #3</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="comboBoxNet3">
|
||||
<property name="maxVisibleItems">
|
||||
<number>30</number>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="socketVDELabel3">
|
||||
<property name="text">
|
||||
<string>VDE Socket</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="optionListLabel3">
|
||||
<property name="text">
|
||||
<string>Options</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="comboBoxNIC3">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToContents</enum>
|
||||
</property>
|
||||
<property name="maxVisibleItems">
|
||||
<number>30</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="interfaceLabel3">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Interface</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" colspan="2">
|
||||
<widget class="Line" name="optionListLine3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="sizePolicy">
|
||||
@@ -299,75 +386,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="2">
|
||||
<widget class="QComboBox" name="comboBoxNet3">
|
||||
<property name="maxVisibleItems">
|
||||
<number>30</number>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Interface</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="2">
|
||||
<widget class="QComboBox" name="comboBoxIntf3">
|
||||
<property name="maxVisibleItems">
|
||||
<number>30</number>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Adapter</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="comboBoxNIC3">
|
||||
<property name="maxVisibleItems">
|
||||
<number>30</number>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToContents</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="pushButtonConf3">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
@@ -380,21 +399,33 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>VDE Socket</string>
|
||||
<string>Adapter</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" colspan="2">
|
||||
<widget class="QLineEdit" name="socketVDENIC3">
|
||||
<property name="maxLength">
|
||||
<number>127</number>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLineEdit" name="socketVDENIC3"/>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="comboBoxIntf3">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<item row="6" column="1">
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
@@ -414,6 +445,13 @@
|
||||
<string>Network Card #4</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="optionListLabel4">
|
||||
<property name="text">
|
||||
<string>Options</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="sizePolicy">
|
||||
@@ -427,102 +465,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="2">
|
||||
<widget class="QComboBox" name="comboBoxNet4">
|
||||
<property name="maxVisibleItems">
|
||||
<number>30</number>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Interface</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="2">
|
||||
<widget class="QComboBox" name="comboBoxIntf4">
|
||||
<property name="maxVisibleItems">
|
||||
<number>30</number>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_16">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Adapter</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="comboBoxNIC4">
|
||||
<property name="maxVisibleItems">
|
||||
<number>30</number>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToContents</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QPushButton" name="pushButtonConf4">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" colspan="2">
|
||||
<widget class="QLineEdit" name="socketVDENIC4">
|
||||
<property name="maxLength">
|
||||
<number>127</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>VDE Socket</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<item row="6" column="1">
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
@@ -535,6 +478,101 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="socketVDELabel4">
|
||||
<property name="text">
|
||||
<string>VDE Socket</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_16">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Adapter</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" colspan="2">
|
||||
<widget class="Line" name="optionListLine4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="interfaceLabel4">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Interface</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="comboBoxNIC4">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToContents</enum>
|
||||
</property>
|
||||
<property name="maxVisibleItems">
|
||||
<number>30</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="comboBoxNet4">
|
||||
<property name="maxVisibleItems">
|
||||
<number>30</number>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="pushButtonConf4">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLineEdit" name="socketVDENIC4"/>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="comboBoxIntf4">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
|
||||
@@ -46,11 +46,11 @@ setMOBus(QAbstractItemModel *model, const QModelIndex &idx, uint8_t bus, uint8_t
|
||||
QIcon icon;
|
||||
switch (bus) {
|
||||
case MO_BUS_DISABLED:
|
||||
icon = ProgSettings::loadIcon("/mo_disabled.ico");
|
||||
icon = QIcon(":/settings/qt/icons/mo_disabled.ico");
|
||||
break;
|
||||
case MO_BUS_ATAPI:
|
||||
case MO_BUS_SCSI:
|
||||
icon = ProgSettings::loadIcon("/mo.ico");
|
||||
icon = QIcon(":/settings/qt/icons/mo.ico");
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -81,11 +81,11 @@ setZIPBus(QAbstractItemModel *model, const QModelIndex &idx, uint8_t bus, uint8_
|
||||
QIcon icon;
|
||||
switch (bus) {
|
||||
case ZIP_BUS_DISABLED:
|
||||
icon = ProgSettings::loadIcon("/zip_disabled.ico");
|
||||
icon = QIcon(":/settings/qt/icons/zip_disabled.ico");
|
||||
break;
|
||||
case ZIP_BUS_ATAPI:
|
||||
case ZIP_BUS_SCSI:
|
||||
icon = ProgSettings::loadIcon("/zip.ico");
|
||||
icon = QIcon(":/settings/qt/icons/zip.ico");
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QAbstractItemView>
|
||||
#include <QPixmap>
|
||||
#include <QIcon>
|
||||
#include <QStyleOption>
|
||||
|
||||
#ifdef Q_OS_WINDOWS
|
||||
#include <dwmapi.h>
|
||||
@@ -66,3 +69,40 @@ StyleOverride::polish(QWidget *widget)
|
||||
qobject_cast<QComboBox *>(widget)->view()->setMinimumWidth(widget->minimumSizeHint().width());
|
||||
}
|
||||
}
|
||||
|
||||
QPixmap
|
||||
StyleOverride::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, const QStyleOption *option) const
|
||||
{
|
||||
if (iconMode != QIcon::Disabled) {
|
||||
return QProxyStyle::generatedIconPixmap(iconMode, pixmap, option);
|
||||
}
|
||||
|
||||
auto image = pixmap.toImage();
|
||||
|
||||
for (int y = 0; y < image.height(); y++) {
|
||||
for (int x = 0; x < image.width(); x++) {
|
||||
// checkerboard transparency
|
||||
if (((x ^ y) & 1) == 0) {
|
||||
image.setPixelColor(x, y, Qt::transparent);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto color = image.pixelColor(x, y);
|
||||
|
||||
// convert to grayscale using the NTSC formula
|
||||
auto avg = 0.0;
|
||||
avg += color.blueF() * 0.114;
|
||||
avg += color.greenF() * 0.587;
|
||||
avg += color.redF() * 0.299;
|
||||
|
||||
color.setRedF(avg);
|
||||
color.setGreenF(avg);
|
||||
color.setBlueF(avg);
|
||||
|
||||
image.setPixelColor(x, y, color);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return QPixmap::fromImage(image);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
#include <QProxyStyle>
|
||||
#include <QWidget>
|
||||
#include <QLayout>
|
||||
#include <QPixmap>
|
||||
#include <QIcon>
|
||||
#include <QStyleOption>
|
||||
|
||||
class StyleOverride : public QProxyStyle {
|
||||
public:
|
||||
@@ -14,6 +17,7 @@ public:
|
||||
QStyleHintReturn *returnData = nullptr) const override;
|
||||
|
||||
void polish(QWidget *widget) override;
|
||||
QPixmap generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, const QStyleOption *option) const override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,16 +1,9 @@
|
||||
<RCC>
|
||||
<qresource prefix="/settings">
|
||||
<file>qt/icons/cartridge.ico</file>
|
||||
<file>qt/icons/cartridge_empty.ico</file>
|
||||
<file>qt/icons/cassette.ico</file>
|
||||
<file>qt/icons/cassette_active.ico</file>
|
||||
<file>qt/icons/cassette_empty.ico</file>
|
||||
<file>qt/icons/cassette_empty_active.ico</file>
|
||||
<file>qt/icons/cdrom.ico</file>
|
||||
<file>qt/icons/cdrom_active.ico</file>
|
||||
<file>qt/icons/cdrom_disabled.ico</file>
|
||||
<file>qt/icons/cdrom_empty.ico</file>
|
||||
<file>qt/icons/cdrom_empty_active.ico</file>
|
||||
<file>qt/icons/cdrom_mute.ico</file>
|
||||
<file>qt/icons/cdrom_unmute.ico</file>
|
||||
<file>qt/icons/cdrom_image.ico</file>
|
||||
@@ -18,38 +11,24 @@
|
||||
<file>qt/icons/cdrom_host.ico</file>
|
||||
<file>qt/icons/display.ico</file>
|
||||
<file>qt/icons/floppy_35.ico</file>
|
||||
<file>qt/icons/floppy_35_active.ico</file>
|
||||
<file>qt/icons/floppy_35_empty.ico</file>
|
||||
<file>qt/icons/floppy_35_empty_active.ico</file>
|
||||
<file>qt/icons/floppy_525.ico</file>
|
||||
<file>qt/icons/floppy_525_active.ico</file>
|
||||
<file>qt/icons/floppy_525_empty.ico</file>
|
||||
<file>qt/icons/floppy_525_empty_active.ico</file>
|
||||
<file>qt/icons/floppy_and_cdrom_drives.ico</file>
|
||||
<file>qt/icons/floppy_disabled.ico</file>
|
||||
<file>qt/icons/hard_disk.ico</file>
|
||||
<file>qt/icons/hard_disk_active.ico</file>
|
||||
<file>qt/icons/input_devices.ico</file>
|
||||
<file>qt/icons/machine.ico</file>
|
||||
<file>qt/icons/mo.ico</file>
|
||||
<file>qt/icons/mo_active.ico</file>
|
||||
<file>qt/icons/mo_disabled.ico</file>
|
||||
<file>qt/icons/mo_empty.ico</file>
|
||||
<file>qt/icons/mo_empty_active.ico</file>
|
||||
<file>qt/icons/network.ico</file>
|
||||
<file>qt/icons/network_active.ico</file>
|
||||
<file>qt/icons/network_empty.ico</file>
|
||||
<file>qt/icons/other_peripherals.ico</file>
|
||||
<file>qt/icons/other_removable_devices.ico</file>
|
||||
<file>qt/icons/ports.ico</file>
|
||||
<file>qt/icons/sound.ico</file>
|
||||
<file>qt/icons/sound_mute.ico</file>
|
||||
<file>qt/icons/storage_controllers.ico</file>
|
||||
<file>qt/icons/zip.ico</file>
|
||||
<file>qt/icons/zip_active.ico</file>
|
||||
<file>qt/icons/zip_disabled.ico</file>
|
||||
<file>qt/icons/zip_empty.ico</file>
|
||||
<file>qt/icons/zip_empty_active.ico</file>
|
||||
<file>qt/icons/active.ico</file>
|
||||
<file>qt/icons/disabled.ico</file>
|
||||
<file>qt/icons/86Box-gray.ico</file>
|
||||
<file>qt/icons/86Box-green.ico</file>
|
||||
<file>qt/icons/86Box-red.ico</file>
|
||||
|
||||
@@ -95,9 +95,6 @@ ncr5380_reset(ncr_t *ncr)
|
||||
|
||||
ncr->timer(ncr->priv, 0.0);
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
scsi_device_reset(&scsi_devices[ncr->bus][i]);
|
||||
|
||||
scsi_bus->state = STATE_IDLE;
|
||||
scsi_bus->clear_req = 0;
|
||||
scsi_bus->wait_complete = 0;
|
||||
|
||||
@@ -29,11 +29,11 @@
|
||||
#define HAVE_STDARG_H
|
||||
#include <86box/86box.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/dma.h>
|
||||
#include <86box/pic.h>
|
||||
#include <86box/mca.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/rom.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/nvr.h>
|
||||
@@ -41,6 +41,7 @@
|
||||
#include <86box/scsi.h>
|
||||
#include <86box/scsi_device.h>
|
||||
#include <86box/scsi_ncr5380.h>
|
||||
#include "cpu.h"
|
||||
|
||||
#define LCS6821N_ROM "roms/scsi/ncr5380/Longshine LCS-6821N - BIOS version 1.04.bin"
|
||||
#define COREL_LS2000_ROM "roms/scsi/ncr5380/Corel LS2000 - BIOS ROM - Ver 1.65.bin"
|
||||
@@ -80,6 +81,7 @@ typedef struct ncr53c400_t {
|
||||
int buffer_host_pos;
|
||||
|
||||
int busy;
|
||||
int reset;
|
||||
uint8_t pos_regs[8];
|
||||
|
||||
pc_timer_t timer;
|
||||
@@ -126,6 +128,9 @@ ncr53c400_write(uint32_t addr, uint8_t val, void *priv)
|
||||
|
||||
addr &= 0x3fff;
|
||||
|
||||
if (addr >= 0x3880)
|
||||
ncr53c400_log("%04X:%08X: memio_write(%04x)=%02x\n", CS, cpu_state.pc, addr, val);
|
||||
|
||||
if (addr >= 0x3a00)
|
||||
ncr400->ext_ram[addr - 0x3a00] = val;
|
||||
else {
|
||||
@@ -147,6 +152,8 @@ ncr53c400_write(uint32_t addr, uint8_t val, void *priv)
|
||||
if (ncr400->buffer_host_pos == MIN(128, dev->buffer_length)) {
|
||||
ncr400->status_ctrl |= STATUS_BUFFER_NOT_READY;
|
||||
ncr400->busy = 1;
|
||||
if (ncr400->type != ROM_T130B)
|
||||
timer_on_auto(&ncr400->timer, 1.0);
|
||||
}
|
||||
} else
|
||||
ncr53c400_log("No Write.\n");
|
||||
@@ -155,6 +162,19 @@ ncr53c400_write(uint32_t addr, uint8_t val, void *priv)
|
||||
case 0x3980:
|
||||
switch (addr) {
|
||||
case 0x3980: /* Control */
|
||||
/*Parity bits*/
|
||||
/*This is to avoid RTBios 8.10R BIOS problems with the hard disk and detection.*/
|
||||
/*If the parity bits are set, bit 0 of the 53c400 status port should be set as well.*/
|
||||
/*Required by RTASPI10.SYS otherwise it won't initialize.*/
|
||||
if (val & 0x80) {
|
||||
if (ncr->mode & 0x30) {
|
||||
if (!(ncr->mode & MODE_DMA)) {
|
||||
ncr->mode = 0x00;
|
||||
ncr400->reset = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ncr53c400_log("NCR 53c400 control=%02x, mode=%02x.\n", val, ncr->mode);
|
||||
if ((val & CTRL_DATA_DIR) && !(ncr400->status_ctrl & CTRL_DATA_DIR)) {
|
||||
ncr400->buffer_host_pos = MIN(128, dev->buffer_length);
|
||||
@@ -180,10 +200,7 @@ ncr53c400_write(uint32_t addr, uint8_t val, void *priv)
|
||||
}
|
||||
if ((ncr->mode & MODE_DMA) && (dev->buffer_length > 0)) {
|
||||
memset(ncr400->buffer, 0, MIN(128, dev->buffer_length));
|
||||
if (ncr400->type == ROM_T130B)
|
||||
timer_on_auto(&ncr400->timer, 10.0);
|
||||
else
|
||||
timer_on_auto(&ncr400->timer, scsi_bus->period);
|
||||
timer_on_auto(&ncr400->timer, 10.0);
|
||||
ncr53c400_log("DMA timer on=%02x, callback=%lf, scsi buflen=%d, waitdata=%d, waitcomplete=%d, clearreq=%d, p=%lf enabled=%d.\n",
|
||||
ncr->mode & MODE_MONITOR_BUSY, scsi_device_get_callback(dev), dev->buffer_length, scsi_bus->wait_data, scsi_bus->wait_complete, scsi_bus->clear_req, scsi_bus->period, timer_is_enabled(&ncr400->timer));
|
||||
} else
|
||||
@@ -241,6 +258,20 @@ ncr53c400_read(uint32_t addr, void *priv)
|
||||
|
||||
if (ncr400->buffer_host_pos == MIN(128, dev->buffer_length)) {
|
||||
ncr400->status_ctrl |= STATUS_BUFFER_NOT_READY;
|
||||
if (ncr400->type != ROM_T130B) {
|
||||
if (!ncr400->block_count_loaded) {
|
||||
scsi_bus->tx_mode = PIO_TX_BUS;
|
||||
ncr53c400_log("IO End of read transfer\n");
|
||||
ncr->isr |= STATUS_END_OF_DMA;
|
||||
if (ncr->mode & MODE_ENA_EOP_INT) {
|
||||
ncr53c400_log("NCR read irq\n");
|
||||
ncr5380_irq(ncr, 1);
|
||||
}
|
||||
} else if (!timer_is_enabled(&ncr400->timer)) {
|
||||
ncr53c400_log("Timer re-enabled.\n");
|
||||
timer_on_auto(&ncr400->timer, 1.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -252,11 +283,10 @@ ncr53c400_read(uint32_t addr, void *priv)
|
||||
ncr53c400_log("NCR status ctrl read=%02x.\n", ncr400->status_ctrl & STATUS_BUFFER_NOT_READY);
|
||||
if (!ncr400->busy)
|
||||
ret |= STATUS_5380_ACCESSIBLE;
|
||||
if (ncr->mode & 0x30) { /*Parity bits*/
|
||||
if (!(ncr->mode & MODE_DMA)) { /*This is to avoid RTBios 8.10R BIOS problems with the hard disk and detection.*/
|
||||
ret |= 0x01; /*If the parity bits are set, bit 0 of the 53c400 status port should be set as well.*/
|
||||
ncr->mode = 0x00; /*Required by RTASPI10.SYS otherwise it won't initialize.*/
|
||||
}
|
||||
|
||||
if (ncr400->reset) {
|
||||
ncr400->reset = 0;
|
||||
ret |= 0x01;
|
||||
}
|
||||
ncr53c400_log("NCR 53c400 status=%02x.\n", ret);
|
||||
break;
|
||||
@@ -267,7 +297,10 @@ ncr53c400_read(uint32_t addr, void *priv)
|
||||
break;
|
||||
|
||||
case 0x3982: /* switch register read */
|
||||
ret = 0xff;
|
||||
if (ncr->irq != -1) {
|
||||
ret = 0xf8;
|
||||
ret += ncr->irq;
|
||||
}
|
||||
ncr53c400_log("Switches read=%02x.\n", ret);
|
||||
break;
|
||||
|
||||
@@ -282,7 +315,7 @@ ncr53c400_read(uint32_t addr, void *priv)
|
||||
}
|
||||
|
||||
if (addr >= 0x3880)
|
||||
ncr53c400_log("memio_read(%08x)=%02x\n", addr, ret);
|
||||
ncr53c400_log("%04X:%08X: memio_read(%04x)=%02x\n", CS, cpu_state.pc, addr, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -424,11 +457,8 @@ ncr53c400_callback(void *priv)
|
||||
uint8_t status;
|
||||
|
||||
if (scsi_bus->tx_mode != PIO_TX_BUS) {
|
||||
if (ncr400->type == ROM_T130B) {
|
||||
ncr53c400_log("PERIOD T130B DMA=%lf.\n", scsi_bus->period / 225.0);
|
||||
timer_on_auto(&ncr400->timer, scsi_bus->period / 225.0);
|
||||
} else
|
||||
timer_on_auto(&ncr400->timer, 1.0);
|
||||
ncr53c400_log("PERIOD T130B DMA=%lf.\n", scsi_bus->period / 225.0);
|
||||
timer_on_auto(&ncr400->timer, scsi_bus->period / 225.0);
|
||||
}
|
||||
|
||||
if (scsi_bus->data_wait & 1) {
|
||||
@@ -538,14 +568,17 @@ ncr53c400_callback(void *priv)
|
||||
ncr400->block_count = (ncr400->block_count - 1) & 0xff;
|
||||
ncr53c400_log("NCR 53c400 Remaining blocks to be read=%d\n", ncr400->block_count);
|
||||
if (!ncr400->block_count) {
|
||||
scsi_bus->tx_mode = PIO_TX_BUS;
|
||||
ncr400->block_count_loaded = 0;
|
||||
ncr53c400_log("IO End of read transfer\n");
|
||||
ncr->isr |= STATUS_END_OF_DMA;
|
||||
if (ncr->mode & MODE_ENA_EOP_INT) {
|
||||
ncr53c400_log("NCR read irq\n");
|
||||
ncr5380_irq(ncr, 1);
|
||||
}
|
||||
if (ncr400->type == ROM_T130B) {
|
||||
scsi_bus->tx_mode = PIO_TX_BUS;
|
||||
ncr53c400_log("IO End of read transfer\n");
|
||||
ncr->isr |= STATUS_END_OF_DMA;
|
||||
if (ncr->mode & MODE_ENA_EOP_INT) {
|
||||
ncr53c400_log("NCR read irq\n");
|
||||
ncr5380_irq(ncr, 1);
|
||||
}
|
||||
} else
|
||||
timer_on_auto(&ncr400->timer, 1.0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -732,8 +765,17 @@ ncr53c400_init(const device_t *info)
|
||||
|
||||
scsi_bus_set_speed(ncr->bus, 5000000.0);
|
||||
scsi_bus->speed = 0.2;
|
||||
scsi_bus->divider = 2.0;
|
||||
scsi_bus->multi = 1.750;
|
||||
if (ncr400->type == ROM_T130B) {
|
||||
scsi_bus->divider = 2.0;
|
||||
scsi_bus->multi = 1.750;
|
||||
} else {
|
||||
scsi_bus->divider = 1.0;
|
||||
scsi_bus->multi = 1.0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
scsi_device_reset(&scsi_devices[ncr->bus][i]);
|
||||
|
||||
return ncr400;
|
||||
}
|
||||
|
||||
|
||||
@@ -95,9 +95,10 @@ t128_write(uint32_t addr, uint8_t val, void *priv)
|
||||
t128->status, scsi_bus->period, timer_is_enabled(&t128->timer), t128->block_loaded);
|
||||
|
||||
t128->status &= ~0x04;
|
||||
timer_on_auto(&t128->timer, 10.0);
|
||||
timer_on_auto(&t128->timer, 1.0);
|
||||
}
|
||||
}
|
||||
} else
|
||||
t128_log("Write not allowed.\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,20 +137,18 @@ t128_read(uint32_t addr, void *priv)
|
||||
t128_log("T128 Transfer busy read, status=%02x, period=%lf, enabled=%d.\n",
|
||||
t128->status, scsi_bus->period, timer_is_enabled(&t128->timer));
|
||||
|
||||
t128->status &= ~0x04;
|
||||
if (!t128->block_loaded) {
|
||||
ncr->isr |= STATUS_END_OF_DMA;
|
||||
if (ncr->mode & MODE_ENA_EOP_INT) {
|
||||
t128_log("T128 read irq\n");
|
||||
ncr5380_irq(ncr, 1);
|
||||
}
|
||||
t128->status &= ~0x04;
|
||||
scsi_bus->bus_out |= BUS_CD;
|
||||
scsi_bus->tx_mode = PIO_TX_BUS;
|
||||
timer_stop(&t128->timer);
|
||||
} else if (!timer_is_enabled(&t128->timer))
|
||||
timer_on_auto(&t128->timer, 10.0);
|
||||
else
|
||||
t128->status &= ~0x04;
|
||||
timer_on_auto(&t128->timer, 1.0);
|
||||
}
|
||||
} else {
|
||||
/*According to the WinNT DDK sources, just get the status timeout bit from here.*/
|
||||
@@ -522,6 +521,10 @@ t128_init(const device_t *info)
|
||||
scsi_bus->speed = 0.2;
|
||||
scsi_bus->divider = 1.0;
|
||||
scsi_bus->multi = 1.0;
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
scsi_device_reset(&scsi_devices[ncr->bus][i]);
|
||||
|
||||
return t128;
|
||||
}
|
||||
|
||||
|
||||
@@ -73,7 +73,6 @@ static int exit_event = 0;
|
||||
static int fullscreen_pending = 0;
|
||||
uint32_t lang_id = 0x0409; // Multilangual UI variables, for now all set to LCID of en-US
|
||||
uint32_t lang_sys = 0x0409; // Multilangual UI variables, for now all set to LCID of en-US
|
||||
char icon_set[256] = ""; /* name of the iconset to be used */
|
||||
|
||||
static const uint16_t sdl_to_xt[0x200] = {
|
||||
[SDL_SCANCODE_ESCAPE] = 0x01,
|
||||
|
||||
@@ -756,8 +756,9 @@ double
|
||||
ini_section_get_double(ini_section_t self, const char *name, double def)
|
||||
{
|
||||
section_t *section = (section_t *) self;
|
||||
const entry_t *entry;
|
||||
double value = 0;
|
||||
entry_t *entry;
|
||||
double value = 0;
|
||||
int res = 0;
|
||||
|
||||
if (section == NULL)
|
||||
return def;
|
||||
@@ -766,7 +767,17 @@ ini_section_get_double(ini_section_t self, const char *name, double def)
|
||||
if (entry == NULL)
|
||||
return def;
|
||||
|
||||
sscanf(entry->data, "%lg", &value);
|
||||
res = sscanf(entry->data, "%lg", &value);
|
||||
if (res == EOF || res <= 0) {
|
||||
int i = 0;
|
||||
for (i = 0; i < strlen(entry->data); i++) {
|
||||
if (entry->data[i] == ',') {
|
||||
entry->data[i] = '.';
|
||||
entry->wdata[i] = L'.';
|
||||
}
|
||||
}
|
||||
(void)sscanf(entry->data, "%lg", &value);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -112,10 +112,13 @@ ega_out(uint16_t addr, uint8_t val, void *priv)
|
||||
ega->fullchange = changeframecount;
|
||||
if (ega->attraddr == 0x10 || ega->attraddr == 0x14 || ega->attraddr < 0x10) {
|
||||
for (uint8_t c = 0; c < 16; c++) {
|
||||
if (ega->attrregs[0x10] & 0x80)
|
||||
ega->egapal[c] = (ega->attrregs[c] & 0xf) | ((ega->attrregs[0x14] & 0xf) << 4);
|
||||
else
|
||||
ega->egapal[c] = (ega->attrregs[c] & 0x3f) | ((ega->attrregs[0x14] & 0xc) << 4);
|
||||
if (ega->chipset) {
|
||||
if (ega->attrregs[0x10] & 0x80)
|
||||
ega->egapal[c] = (ega->attrregs[c] & 0xf) | ((ega->attrregs[0x14] & 0xf) << 4);
|
||||
else
|
||||
ega->egapal[c] = (ega->attrregs[c] & 0x3f) | ((ega->attrregs[0x14] & 0xc) << 4);
|
||||
} else
|
||||
ega->egapal[c] = ega->attrregs[c] & 0x3f;
|
||||
}
|
||||
ega->fullchange = changeframecount;
|
||||
}
|
||||
@@ -780,7 +783,7 @@ ega_poll(void *priv)
|
||||
ega->y_add *= ega->vres + 1;
|
||||
for (y = 0; y <= ega->vres; y++) {
|
||||
/* Render scanline */
|
||||
if(ega->render_override)
|
||||
if (ega->render_override)
|
||||
ega->render_override(ega->priv_parent);
|
||||
else
|
||||
ega->render(ega);
|
||||
|
||||
@@ -172,15 +172,20 @@ ega_render_text(ega_t *ega)
|
||||
|
||||
uint32_t dat = ega->vram[charaddr + (ega->sc << 2)];
|
||||
dat <<= 1;
|
||||
if ((chr & ~0x1F) == 0xC0 && attrlinechars)
|
||||
if (((chr & ~0x1f) == 0xc0) && attrlinechars)
|
||||
dat |= (dat >> 1) & 1;
|
||||
|
||||
for (int xx = 0; xx < charwidth; xx++) {
|
||||
if (monoattrs) {
|
||||
int bit = (dat & (0x100 >> (xx >> dwshift))) ? 1 : 0;
|
||||
int blink = (!drawcursor && (attr & 0x80) && attrblink && blinked);
|
||||
if ((ega->sc == ega->crtc[0x14]) && ((attr & 7) == 1))
|
||||
p[xx] = ega->mdacols[attr][attrblink][1];
|
||||
p[xx] = ega->mdacols[attr][blink][1];
|
||||
else
|
||||
p[xx] = ega->mdacols[attr][attrblink][dat & (0x100 >> (xx >> dwshift))];
|
||||
p[xx] = ega->mdacols[attr][blink][bit];
|
||||
if (drawcursor)
|
||||
p[xx] ^= ega->mdacols[attr][0][1];
|
||||
p[xx] = ega->pallook[ega->egapal[p[xx] & 0x0f]];
|
||||
} else
|
||||
p[xx] = (dat & (0x100 >> (xx >> dwshift))) ? fg : bg;
|
||||
}
|
||||
@@ -189,9 +194,6 @@ ega_render_text(ega_t *ega)
|
||||
p += charwidth;
|
||||
}
|
||||
ega->ma &= 0x3ffff;
|
||||
|
||||
if (monoattrs)
|
||||
video_process_8(ega->hdisp + ega->scrollcache, ega->displine);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,11 +29,14 @@
|
||||
#include <86box/pic.h>
|
||||
#include <86box/pit.h>
|
||||
#include <86box/plat.h>
|
||||
#include <86box/plat_fallthrough.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/rom.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/video.h>
|
||||
#include <86box/vid_ega.h>
|
||||
#include <86box/vid_svga.h>
|
||||
#include <86box/vid_vga.h>
|
||||
|
||||
/* JEGA internal registers */
|
||||
#define RPESL 0x09 /* End Scan Line */
|
||||
@@ -63,6 +66,8 @@
|
||||
#define JEGA_PATH_BIOS "roms/video/jega/JEGABIOS.BIN"
|
||||
#define JEGA_PATH_FONTDBCS "roms/video/jega/JPNZN16X.FNT"
|
||||
#define IF386_PATH_VBIOS "roms/machines/if386sx/OKI_IF386SX_VBIOS.bin"
|
||||
#define JVGA_PATH_BIOS "roms/video/jega/OKI_JVGT(AXVGAH)_BIOS_011993.BIN"
|
||||
#define JVGA_PATH_FONTDBCS "roms/video/jega/JWPCE.FNT"
|
||||
#define SBCS19_FILESIZE (256 * 19 * 2) /* 8 x 19 x 256 chr x 2 pages */
|
||||
#define DBCS16_CHARS 0x2c10
|
||||
#define DBCS16_FILESIZE (DBCS16_CHARS * 16 * 2)
|
||||
@@ -96,29 +101,31 @@ jega_log(const char *fmt, ...)
|
||||
static video_timings_t timing_ega = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 };
|
||||
|
||||
typedef struct jega_t {
|
||||
rom_t bios_rom;
|
||||
ega_t ega;
|
||||
uint8_t regs_index; /* 3D4/3D5 index B9-BF, D9-DF */
|
||||
uint8_t regs[0x31];
|
||||
uint8_t egapal[16];
|
||||
uint8_t attrregs[32];
|
||||
uint8_t attraddr;
|
||||
uint8_t attrff;
|
||||
uint8_t attr_palette_enable;
|
||||
rom_t bios_rom;
|
||||
ega_t ega;
|
||||
vga_t vga;
|
||||
uint8_t regs_index; /* 3D4/3D5 index B9-BF, D9-DF */
|
||||
uint8_t regs[0x31];
|
||||
uint8_t egapal[16];
|
||||
uint8_t attrregs[32];
|
||||
uint8_t attraddr;
|
||||
uint8_t attrff;
|
||||
uint8_t attr_palette_enable;
|
||||
uint32_t *pallook;
|
||||
int con;
|
||||
int cursoron;
|
||||
int cursorblink_disable;
|
||||
int ca;
|
||||
int font_index;
|
||||
int sbcsbank_inv;
|
||||
int attr3_sbcsbank;
|
||||
int start_scan_lower;
|
||||
int start_scan_upper;
|
||||
int start_scan_count;
|
||||
uint8_t *vram;
|
||||
uint8_t jfont_sbcs_19[SBCS19_FILESIZE]; /* 8 x 19 font */
|
||||
uint8_t jfont_dbcs_16[DBCS16_FILESIZE]; /* 16 x 16 font. Use dbcs_read/write to access it. */
|
||||
int is_vga;
|
||||
int con;
|
||||
int cursoron;
|
||||
int cursorblink_disable;
|
||||
int ca;
|
||||
int font_index;
|
||||
int sbcsbank_inv;
|
||||
int attr3_sbcsbank;
|
||||
int start_scan_lower;
|
||||
int start_scan_upper;
|
||||
int start_scan_count;
|
||||
uint8_t * vram;
|
||||
uint8_t jfont_sbcs_19[SBCS19_FILESIZE]; /* 8 x 19 font */
|
||||
uint8_t jfont_dbcs_16[DBCS16_FILESIZE]; /* 16 x 16 font. Use dbcs_read/write to access it. */
|
||||
} jega_t;
|
||||
|
||||
static void jega_recalctimings(void *priv);
|
||||
@@ -127,16 +134,16 @@ static void jega_recalctimings(void *priv);
|
||||
#define FONTX_LEN_FN 8
|
||||
|
||||
typedef struct {
|
||||
char id[FONTX_LEN_ID];
|
||||
char name[FONTX_LEN_FN];
|
||||
unsigned char width;
|
||||
unsigned char height;
|
||||
unsigned char type;
|
||||
char id[FONTX_LEN_ID];
|
||||
char name[FONTX_LEN_FN];
|
||||
uint8_t width;
|
||||
uint8_t height;
|
||||
uint8_t type;
|
||||
} fontx_h;
|
||||
|
||||
typedef struct {
|
||||
uint16_t start;
|
||||
uint16_t end;
|
||||
uint16_t start;
|
||||
uint16_t end;
|
||||
} fontx_tbl;
|
||||
|
||||
extern uint32_t pallook16[256];
|
||||
@@ -147,22 +154,32 @@ static bool is_SJIS_2(uint8_t chr) { return (chr >= 0x40 && chr <= 0x7e) || (chr
|
||||
static uint16_t
|
||||
SJIS_to_SEQ(uint16_t sjis)
|
||||
{
|
||||
uint32_t chr1 = (sjis >> 8) & 0xff;
|
||||
uint32_t chr2 = sjis & 0xff;
|
||||
if (!is_SJIS_1(chr1) || !is_SJIS_2(chr2)) return INVALIDACCESS16;
|
||||
chr1 -= 0x81;
|
||||
if (chr1 > 0x5E) chr1 -= 0x40;
|
||||
chr2 -= 0x40;
|
||||
if (chr2 > 0x3F) chr2--;
|
||||
chr1 *= 0xBC;
|
||||
return (chr1 + chr2);
|
||||
uint32_t chr1 = (sjis >> 8) & 0xff;
|
||||
uint32_t chr2 = sjis & 0xff;
|
||||
|
||||
if (!is_SJIS_1(chr1) || !is_SJIS_2(chr2))
|
||||
return INVALIDACCESS16;
|
||||
|
||||
chr1 -= 0x81;
|
||||
|
||||
if (chr1 > 0x5e)
|
||||
chr1 -= 0x40;
|
||||
|
||||
chr2 -= 0x40;
|
||||
|
||||
if (chr2 > 0x3f)
|
||||
chr2--;
|
||||
|
||||
chr1 *= 0xbc;
|
||||
|
||||
return (chr1 + chr2);
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
dbcs_read(uint16_t sjis, int index, void *priv) {
|
||||
jega_t *jega = (jega_t *) priv;
|
||||
int seq = SJIS_to_SEQ(sjis);
|
||||
if (seq >= DBCS16_CHARS || index >= 32)
|
||||
if ((seq >= DBCS16_CHARS) || (index >= 32))
|
||||
return INVALIDACCESS8;
|
||||
return jega->jfont_dbcs_16[seq * 32 + index];
|
||||
}
|
||||
@@ -171,7 +188,7 @@ static void
|
||||
dbcs_write(uint16_t sjis, int index, uint8_t val, void *priv) {
|
||||
jega_t *jega = (jega_t *) priv;
|
||||
int seq = SJIS_to_SEQ(sjis);
|
||||
if (seq >= DBCS16_CHARS || index >= 32)
|
||||
if ((seq >= DBCS16_CHARS) || (index >= 32))
|
||||
return;
|
||||
jega->jfont_dbcs_16[seq * 32 + index] = val;
|
||||
}
|
||||
@@ -180,38 +197,81 @@ dbcs_write(uint16_t sjis, int index, uint8_t val, void *priv) {
|
||||
void
|
||||
jega_render_text(void *priv)
|
||||
{
|
||||
jega_t *jega = (jega_t *) priv;
|
||||
if (jega->ega.firstline_draw == 2000)
|
||||
jega->ega.firstline_draw = jega->ega.displine;
|
||||
jega->ega.lastline_draw = jega->ega.displine;
|
||||
jega_t * jega = (jega_t *) priv;
|
||||
#ifdef USE_DOUBLE_WIDTH_AND_LINE_CHARS
|
||||
uint8_t * seqregs = jega->is_vga ? jega->vga.svga.seqregs :
|
||||
jega->ega.seqregs;
|
||||
uint8_t * attrregs = jega->is_vga ? jega->vga.svga.attrregs :
|
||||
jega->ega.attrregs;
|
||||
#endif
|
||||
uint8_t * crtc = jega->is_vga ? jega->vga.svga.crtc :
|
||||
jega->ega.crtc;
|
||||
uint8_t * vram = jega->is_vga ? jega->vga.svga.vram :
|
||||
jega->ega.vram;
|
||||
int * firstline_draw = jega->is_vga ? &jega->vga.svga.firstline_draw :
|
||||
&jega->ega.firstline_draw;
|
||||
int * lastline_draw = jega->is_vga ? &jega->vga.svga.lastline_draw :
|
||||
&jega->ega.lastline_draw;
|
||||
int * displine = jega->is_vga ? &jega->vga.svga.displine :
|
||||
&jega->ega.displine;
|
||||
int * fullchange = jega->is_vga ? &jega->vga.svga.fullchange :
|
||||
&jega->ega.fullchange;
|
||||
int * blink = jega->is_vga ? &jega->vga.svga.blink :
|
||||
&jega->ega.blink;
|
||||
int * x_add = jega->is_vga ? &jega->vga.svga.x_add :
|
||||
&jega->ega.x_add;
|
||||
int * y_add = jega->is_vga ? &jega->vga.svga.y_add :
|
||||
&jega->ega.y_add;
|
||||
int * sc = jega->is_vga ? &jega->vga.svga.sc :
|
||||
&jega->ega.sc;
|
||||
int * hdisp = jega->is_vga ? &jega->vga.svga.hdisp :
|
||||
&jega->ega.hdisp;
|
||||
int * scrollcache = jega->is_vga ? &jega->vga.svga.scrollcache :
|
||||
&jega->ega.scrollcache;
|
||||
uint32_t *ma = jega->is_vga ? &jega->vga.svga.ma :
|
||||
&jega->ega.ma;
|
||||
uint8_t mask = jega->is_vga ? jega->vga.svga.dac_mask : 0xff;
|
||||
|
||||
if (jega->ega.fullchange) {
|
||||
// const bool doublewidth = ((jega->ega.seqregs[1] & 8) != 0);
|
||||
const bool attrblink = ((jega->regs[RMOD2] & 0x20) == 0); /* JEGA specific */
|
||||
// const bool attrlinechars = (jega->ega.attrregs[0x10] & 4);
|
||||
const bool crtcreset = ((jega->ega.crtc[0x17] & 0x80) == 0) || ((jega->regs[RMOD1] & 0x80) == 0);
|
||||
const int charwidth = 8;
|
||||
const bool blinked = jega->ega.blink & 0x10;
|
||||
uint32_t *p = &buffer32->line[jega->ega.displine + jega->ega.y_add][jega->ega.x_add];
|
||||
bool chr_wide = false;
|
||||
int sc_wide = jega->ega.sc - jega->start_scan_count;
|
||||
const bool cursoron = (blinked || jega->cursorblink_disable)
|
||||
&& (jega->ega.sc >= jega->regs[RCCSL]) && (jega->ega.sc <= jega->regs[RCCEL]);
|
||||
uint32_t chr_first;
|
||||
uint32_t attr_basic;
|
||||
int fg;
|
||||
int bg;
|
||||
if (*firstline_draw == 2000)
|
||||
*firstline_draw = *displine;
|
||||
*lastline_draw = *displine;
|
||||
|
||||
for (int x = 0; x < (jega->ega.hdisp + jega->ega.scrollcache); x += charwidth) {
|
||||
uint32_t addr = jega->ega.remap_func(&jega->ega, jega->ega.ma) & jega->ega.vrammask;
|
||||
if (*fullchange) {
|
||||
#ifdef USE_DOUBLE_WIDTH_AND_LINE_CHARS
|
||||
const bool doublewidth = ((seqregs[1] & 8) != 0);
|
||||
const bool attrlinechars = (attrregs[0x10] & 4);
|
||||
#endif
|
||||
const bool attrblink = ((jega->regs[RMOD2] & 0x20) == 0); /* JEGA specific */
|
||||
const bool crtcreset = ((crtc[0x17] & 0x80) == 0) || ((jega->regs[RMOD1] & 0x80) == 0);
|
||||
const int charwidth = 8;
|
||||
const bool blinked = *blink & 0x10;
|
||||
uint32_t *p = &buffer32->line[*displine + *y_add][*x_add];
|
||||
bool chr_wide = false;
|
||||
int sc_wide = *sc - jega->start_scan_count;
|
||||
const bool cursoron = (blinked || jega->cursorblink_disable) &&
|
||||
(*sc >= jega->regs[RCCSL]) && (*sc <= jega->regs[RCCEL]);
|
||||
uint32_t attr_basic = 0;
|
||||
uint32_t chr_first;
|
||||
int fg = 0;
|
||||
int bg;
|
||||
|
||||
int drawcursor = ((jega->ega.ma == jega->ca) && cursoron);
|
||||
for (int x = 0; x < (*hdisp + *scrollcache); x += charwidth) {
|
||||
uint32_t addr = 0;
|
||||
|
||||
if (jega->is_vga) {
|
||||
if (!jega->vga.svga.force_old_addr)
|
||||
addr = jega->vga.svga.remap_func(&jega->vga.svga, jega->vga.svga.ma) &
|
||||
jega->vga.svga.vram_display_mask;
|
||||
} else
|
||||
addr = jega->ega.remap_func(&jega->ega, *ma) & jega->ega.vrammask;
|
||||
|
||||
int drawcursor = ((*ma == jega->ca) && cursoron);
|
||||
|
||||
uint32_t chr;
|
||||
uint32_t attr;
|
||||
if (!crtcreset) {
|
||||
chr = jega->ega.vram[addr];
|
||||
attr = jega->ega.vram[addr + 1];
|
||||
chr = vram[addr];
|
||||
attr = vram[addr + 1];
|
||||
} else
|
||||
chr = attr = 0;
|
||||
if (chr_wide) {
|
||||
@@ -222,13 +282,13 @@ jega_render_text(void *priv)
|
||||
/* Bold | 2x width | 2x height | U/L select | R/L select | - | - | - */
|
||||
attr_ext = attr;
|
||||
if ((attr_ext & 0x30) == 0x30)
|
||||
sc_wide = jega->ega.sc - jega->start_scan_lower; /* Set top padding of lower 2x character */
|
||||
sc_wide = *sc - jega->start_scan_lower; /* Set top padding of lower 2x character */
|
||||
else if ((attr_ext & 0x30) == 0x20)
|
||||
sc_wide = jega->ega.sc - jega->start_scan_upper; /* Set top padding of upper 2x character */
|
||||
sc_wide = *sc - jega->start_scan_upper; /* Set top padding of upper 2x character */
|
||||
else
|
||||
sc_wide = jega->ega.sc - jega->start_scan_count;
|
||||
sc_wide = *sc - jega->start_scan_count;
|
||||
}
|
||||
if (is_SJIS_2(chr) && sc_wide >= 0 && sc_wide < 16 && jega->ega.sc <= jega->regs[RPESL]) {
|
||||
if (is_SJIS_2(chr) && sc_wide >= 0 && sc_wide < 16 && *sc <= jega->regs[RPESL]) {
|
||||
chr_first <<= 8;
|
||||
chr |= chr_first;
|
||||
/* Vertical wide font (Extended Attribute) */
|
||||
@@ -269,7 +329,7 @@ jega_render_text(void *priv)
|
||||
if (attr_basic & 0x20) { /* vertical line */
|
||||
p[0] = fg;
|
||||
}
|
||||
if ((jega->ega.sc == jega->regs[RPULP]) && (attr_basic & 0x10)) { /* underline */
|
||||
if ((*sc == jega->regs[RPULP]) && (attr_basic & 0x10)) { /* underline */
|
||||
for (int xx = 0; xx < charwidth * 2; xx++)
|
||||
p[xx] = fg;
|
||||
}
|
||||
@@ -298,13 +358,13 @@ jega_render_text(void *priv)
|
||||
/* Parse attribute as EGA */
|
||||
/* BInt/Blink | BR | BG | BB | Int/Group | R | G | B */
|
||||
if (drawcursor) {
|
||||
bg = jega->pallook[jega->egapal[attr & 0x0f]];
|
||||
fg = jega->pallook[jega->egapal[attr >> 4]];
|
||||
bg = jega->pallook[jega->egapal[attr & 0x0f] & mask];
|
||||
fg = jega->pallook[jega->egapal[attr >> 4] & mask];
|
||||
} else {
|
||||
fg = jega->pallook[jega->egapal[attr & 0x0f]];
|
||||
bg = jega->pallook[jega->egapal[attr >> 4]];
|
||||
fg = jega->pallook[jega->egapal[attr & 0x0f] & mask];
|
||||
bg = jega->pallook[jega->egapal[attr >> 4] & mask];
|
||||
if ((attr & 0x80) && attrblink) {
|
||||
bg = jega->pallook[jega->egapal[(attr >> 4) & 7]];
|
||||
bg = jega->pallook[jega->egapal[(attr >> 4) & 7] & mask];
|
||||
if (blinked)
|
||||
fg = bg;
|
||||
}
|
||||
@@ -325,32 +385,35 @@ jega_render_text(void *priv)
|
||||
// charaddr ^= 0x100;
|
||||
charaddr *= 19;
|
||||
|
||||
uint32_t dat = jega->jfont_sbcs_19[charaddr + jega->ega.sc];
|
||||
uint32_t dat = jega->jfont_sbcs_19[charaddr + *sc];
|
||||
for (int xx = 0; xx < charwidth; xx++)
|
||||
p[xx] = (dat & (0x80 >> xx)) ? fg : bg;
|
||||
|
||||
if (attr_basic & 0x20) { /* vertical line */
|
||||
p[0] = fg;
|
||||
}
|
||||
if ((jega->ega.sc == jega->regs[RPULP]) && (attr_basic & 0x10)) { /* underline */
|
||||
if ((*sc == jega->regs[RPULP]) && (attr_basic & 0x10)) { /* underline */
|
||||
for (int xx = 0; xx < charwidth; xx++)
|
||||
p[xx] = fg;
|
||||
}
|
||||
p += charwidth;
|
||||
}
|
||||
}
|
||||
jega->ega.ma += 4;
|
||||
*ma += 4;
|
||||
}
|
||||
jega->ega.ma &= 0x3ffff;
|
||||
*ma &= 0x3ffff;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
jega_out(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
jega_t *jega = (jega_t *) priv;
|
||||
uint16_t chr;
|
||||
jega_t *jega = (jega_t *) priv;
|
||||
uint8_t pal4to16[16] = { 0, 7, 0x38, 0x3f, 0, 3, 4, 0x3f, 0, 2, 4, 0x3e, 0, 3, 5, 0x3f };
|
||||
uint16_t chr;
|
||||
|
||||
// jega_log("JEGA Out %04X %02X(%d) %04X:%04X\n", addr, val, val, cs >> 4, cpu_state.pc);
|
||||
|
||||
switch (addr) {
|
||||
case 0x3c0:
|
||||
case 0x3c1:
|
||||
@@ -367,9 +430,20 @@ jega_out(uint16_t addr, uint8_t val, void *priv)
|
||||
jega->attrregs[jega->attraddr & 31] = val;
|
||||
if (jega->attraddr < 0x10) {
|
||||
for (uint8_t c = 0; c < 16; c++) {
|
||||
if (jega->is_vga) {
|
||||
if (jega->attrregs[0x10] & 0x80)
|
||||
jega->egapal[c] = (jega->attrregs[c] & 0xf) | ((jega->attrregs[0x14] & 0xf) << 4);
|
||||
else if (jega->vga.svga.ati_4color)
|
||||
jega->egapal[c] = pal4to16[(c & 0x03) | ((val >> 2) & 0xc)];
|
||||
else
|
||||
jega->egapal[c] = (jega->attrregs[c] & 0x3f) | ((jega->attrregs[0x14] & 0xc) << 4);
|
||||
} else
|
||||
jega->egapal[c] = jega->attrregs[c] & 0x3f;
|
||||
}
|
||||
jega->ega.fullchange = changeframecount;
|
||||
if (jega->is_vga)
|
||||
jega->vga.svga.fullchange = changeframecount;
|
||||
else
|
||||
jega->ega.fullchange = changeframecount;
|
||||
}
|
||||
}
|
||||
jega->attrff ^= 1;
|
||||
@@ -395,12 +469,17 @@ jega_out(uint16_t addr, uint8_t val, void *priv)
|
||||
switch (jega->regs_index) {
|
||||
case RMOD1:
|
||||
/* if the value is changed */
|
||||
// if (jega->regs[jega->regs_index] != val) {
|
||||
if (val & 0x40)
|
||||
jega->ega.render_override = NULL;
|
||||
else
|
||||
jega->ega.render_override = jega_render_text;
|
||||
// }
|
||||
if (jega->is_vga) {
|
||||
if (val & 0x40)
|
||||
jega->vga.svga.render_override = NULL;
|
||||
else
|
||||
jega->vga.svga.render_override = jega_render_text;
|
||||
} else {
|
||||
if (val & 0x40)
|
||||
jega->ega.render_override = NULL;
|
||||
else
|
||||
jega->ega.render_override = jega_render_text;
|
||||
}
|
||||
break;
|
||||
case RDAGS:
|
||||
switch (val & 0x03) {
|
||||
@@ -470,8 +549,14 @@ jega_out(uint16_t addr, uint8_t val, void *priv)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (jega->regs[RMOD1] & 0x0C) /* Accessing to Slave EGA is redirected to Master in AX-1. */
|
||||
ega_out(addr, val, &jega->ega);
|
||||
|
||||
/* Accessing to Slave EGA is redirected to Master in AX-1. */
|
||||
if (jega->regs[RMOD1] & 0x0c) {
|
||||
if (jega->is_vga)
|
||||
vga_out(addr, val, &jega->vga);
|
||||
else
|
||||
ega_out(addr, val, &jega->ega);
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
@@ -480,6 +565,7 @@ jega_in(uint16_t addr, void *priv)
|
||||
jega_t *jega = (jega_t *) priv;
|
||||
uint8_t ret = INVALIDACCESS8;
|
||||
uint16_t chr;
|
||||
|
||||
switch (addr) {
|
||||
case 0x3b5:
|
||||
case 0x3d5:
|
||||
@@ -508,15 +594,26 @@ jega_in(uint16_t addr, void *priv)
|
||||
break;
|
||||
}
|
||||
jega_log("JEGA In %04X(%02X) %02X %04X:%04X\n", addr, jega->regs_index, ret, cs >> 4, cpu_state.pc);
|
||||
} else if (jega->regs[RMOD1] & 0x0C) /* Accessing to Slave EGA is redirected to Master in AX-1. */
|
||||
ret = ega_in(addr, &jega->ega);
|
||||
} else if (jega->regs[RMOD1] & 0x0c) {
|
||||
/* Accessing to Slave EGA is redirected to Master in AX-1. */
|
||||
if (jega->is_vga)
|
||||
ret = vga_in(addr, &jega->vga);
|
||||
else
|
||||
ret = ega_in(addr, &jega->ega);
|
||||
}
|
||||
break;
|
||||
case 0x3ba:
|
||||
case 0x3da:
|
||||
jega->attrff = 0;
|
||||
fallthrough;
|
||||
default:
|
||||
if (jega->regs[RMOD1] & 0x0C) /* Accessing to Slave is redirected to Master in AX-1. */
|
||||
ret = ega_in(addr, &jega->ega);
|
||||
/* Accessing to Slave is redirected to Master in AX-1. */
|
||||
if (jega->regs[RMOD1] & 0x0c) {
|
||||
if (jega->is_vga)
|
||||
ret = vga_in(addr, &jega->vga);
|
||||
else
|
||||
ret = ega_in(addr, &jega->ega);
|
||||
}
|
||||
break;
|
||||
}
|
||||
// jega_log("JEGA In %04X(%02X) %02X %04X:%04X\n", addr, jega->regs_index, ret, cs >> 4, cpu_state.pc);
|
||||
@@ -619,19 +716,29 @@ LoadFontxFile(const char *fn, void *priv)
|
||||
}
|
||||
|
||||
static void
|
||||
jega_commoninit(void *priv)
|
||||
jega_commoninit(const device_t *info, void *priv, int vga)
|
||||
{
|
||||
jega_t *jega = (jega_t *) priv;
|
||||
for (int c = 0; c < 256; c++) {
|
||||
pallook64[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa);
|
||||
pallook64[c] += makecol32(((c >> 5) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 3) & 1) * 0x55);
|
||||
jega->is_vga = vga;
|
||||
if (vga) {
|
||||
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_vga);
|
||||
vga_init(info, &jega->vga, 1);
|
||||
jega->vga.svga.priv_parent = jega;
|
||||
jega->pallook = jega->vga.svga.pallook;
|
||||
} else {
|
||||
for (int c = 0; c < 256; c++) {
|
||||
pallook64[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa);
|
||||
pallook64[c] += makecol32(((c >> 5) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 3) & 1) * 0x55);
|
||||
}
|
||||
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ega);
|
||||
jega->pallook = pallook64;
|
||||
ega_init(&jega->ega, 9, 0);
|
||||
ega_set_type(&jega->ega, EGA_SUPEREGA);
|
||||
jega->ega.priv_parent = jega;
|
||||
mem_mapping_add(&jega->ega.mapping, 0xa0000, 0x20000,
|
||||
ega_read, NULL, NULL, ega_write, NULL, NULL,
|
||||
NULL, MEM_MAPPING_EXTERNAL, &jega->ega);
|
||||
}
|
||||
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ega);
|
||||
jega->pallook = pallook64;
|
||||
ega_init(&jega->ega, 9, 0);
|
||||
ega_set_type(&jega->ega, EGA_SUPEREGA);
|
||||
jega->ega.priv_parent = jega;
|
||||
mem_mapping_add(&jega->ega.mapping, 0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, &jega->ega);
|
||||
/* I/O 3DD and 3DE are used by Oki if386 */
|
||||
io_sethandler(0x03b0, 0x002c, jega_in, NULL, NULL, jega_out, NULL, NULL, jega);
|
||||
jega->regs[RMOD1] = 0x48;
|
||||
@@ -646,7 +753,21 @@ jega_standalone_init(const device_t *info)
|
||||
memset(&jega->jfont_dbcs_16, 0, DBCS16_FILESIZE);
|
||||
LoadFontxFile(JEGA_PATH_FONTDBCS, jega);
|
||||
|
||||
jega_commoninit(jega);
|
||||
jega_commoninit(info, jega, 0);
|
||||
|
||||
return jega;
|
||||
}
|
||||
|
||||
static void *
|
||||
jvga_standalone_init(const device_t *info)
|
||||
{
|
||||
jega_t *jega = calloc(1, sizeof(jega_t));
|
||||
|
||||
rom_init(&jega->bios_rom, JVGA_PATH_BIOS, 0xc0000, 0x8000, 0x7fff, 0, 0);
|
||||
memset(&jega->jfont_dbcs_16, 0, DBCS16_FILESIZE);
|
||||
LoadFontxFile(JVGA_PATH_FONTDBCS, jega);
|
||||
|
||||
jega_commoninit(info, jega, 1);
|
||||
|
||||
return jega;
|
||||
}
|
||||
@@ -693,9 +814,15 @@ jega_close(void *priv)
|
||||
}
|
||||
pclog("jeclosed %04X:%04X DS %04X\n", cs >> 4, cpu_state.pc, DS);
|
||||
#endif
|
||||
if (jega->ega.eeprom)
|
||||
free(jega->ega.eeprom);
|
||||
free(jega->ega.vram);
|
||||
|
||||
if (jega->is_vga)
|
||||
svga_close(&jega->vga.svga);
|
||||
else {
|
||||
if (jega->ega.eeprom)
|
||||
free(jega->ega.eeprom);
|
||||
free(jega->ega.vram);
|
||||
}
|
||||
|
||||
free(jega);
|
||||
}
|
||||
|
||||
@@ -703,8 +830,13 @@ static void
|
||||
jega_recalctimings(void *priv)
|
||||
{
|
||||
jega_t *jega = (jega_t *) priv;
|
||||
ega_recalctimings(&jega->ega);
|
||||
|
||||
if (jega->is_vga)
|
||||
svga_recalctimings(&jega->vga.svga);
|
||||
else
|
||||
ega_recalctimings(&jega->ega);
|
||||
}
|
||||
|
||||
static void
|
||||
jega_speed_changed(void *priv)
|
||||
{
|
||||
@@ -733,6 +865,20 @@ const device_t jega_device = {
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t jvga_device = {
|
||||
.name = "OKIVGA/H-2 (JVGA/H)",
|
||||
.internal_name = "jvga",
|
||||
.flags = DEVICE_ISA,
|
||||
.local = 0,
|
||||
.init = jvga_standalone_init,
|
||||
.close = jega_close,
|
||||
.reset = NULL,
|
||||
.available = jega_standalone_available,
|
||||
.speed_changed = jega_speed_changed,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
static uint8_t p65idx = 0;
|
||||
// static uint8_t p3de_idx = 0;
|
||||
static uint8_t p65[6];
|
||||
@@ -770,6 +916,8 @@ if386_p6x_read(uint16_t port, void *priv)
|
||||
Bit 4: Shutdown? (caused by POST rebooting and POWER OFF command in DOS 3.21)
|
||||
Bit 3: ?
|
||||
*/
|
||||
static uint32_t lcd_cols[8] = { 0x001024, 0x747d8a, 0x8c96a4, 0xa0abbb,
|
||||
0xb1bece, 0xc0cee0, 0xceddf0, 0xdbebff };
|
||||
static void
|
||||
if386_p6x_write(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
@@ -793,19 +941,31 @@ if386_p6x_write(uint16_t port, uint8_t val, void *priv)
|
||||
} else { /* Monochrome LCD */
|
||||
for (int c = 0; c < 256; c++) {
|
||||
int cval = 0;
|
||||
#ifdef SIMPLE_BW
|
||||
if (c & 0x0f)
|
||||
cval = ((c & 0x0e) * 0x10) + 0x1f;
|
||||
pallook64[c] = makecol32(cval, cval, cval);
|
||||
pallook16[c] = makecol32(cval, cval, cval);
|
||||
#else
|
||||
if (c & 0x3f) {
|
||||
cval = (c & 0x10) >> 2;
|
||||
cval |= (c & 0x06) >> 1;
|
||||
}
|
||||
pallook64[c] = lcd_cols[cval];
|
||||
cval = 0;
|
||||
if (c & 0x0f)
|
||||
cval = (c & 0x0e) >> 1;
|
||||
pallook16[c] = lcd_cols[cval];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
jega_recalctimings(jega);
|
||||
} else if (p65idx == 0x05) {
|
||||
if (val & 0x10)
|
||||
if (val & 0x10) {
|
||||
/* Power off (instead this call hardware reset here) */
|
||||
device_reset_all(DEVICE_ALL);
|
||||
resetx86();
|
||||
/* Actually, power off - we have a function for that! */
|
||||
// plat_power_off();
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
@@ -820,7 +980,7 @@ if386jega_init(const device_t *info)
|
||||
memset(&jega->jfont_dbcs_16, 0, DBCS16_FILESIZE);
|
||||
LoadFontxFile(JEGA_PATH_FONTDBCS, jega);
|
||||
|
||||
jega_commoninit(jega);
|
||||
jega_commoninit(info, jega, 0);
|
||||
|
||||
io_sethandler(0x0063, 1, if386_p6x_read, NULL, NULL, if386_p6x_write, NULL, NULL, jega);
|
||||
io_sethandler(0x0065, 1, if386_p6x_read, NULL, NULL, if386_p6x_write, NULL, NULL, jega);
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
* Notes: There are some known issues that should be corrected.
|
||||
* - Incorrect foreground text color appears on an active window in OS/2 J1.3.
|
||||
* - Glitches some part of graphics on the Control Panel in OS/2 J2.1 beta.
|
||||
* - The screen resolution and blanking interval time maybe not correct.
|
||||
*
|
||||
* The code should be tested with following cases.
|
||||
* - Execute MODE 0, 1, 3 and 4 commands in DOS K3.3 to test various video modes.
|
||||
@@ -30,7 +29,6 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#include <stdatomic.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
@@ -41,7 +39,6 @@
|
||||
#include <86box/mca.h>
|
||||
#include <86box/rom.h>
|
||||
#include <86box/plat.h>
|
||||
#include <86box/thread.h>
|
||||
#include <86box/video.h>
|
||||
#include <86box/vid_ps55da2.h>
|
||||
#include <86box/vid_svga.h>
|
||||
@@ -257,8 +254,9 @@
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_DA2_LOG
|
||||
// # define ENABLE_DA2_DEBUGIO 1
|
||||
// # define ENABLE_DA2_DEBUGBLT 1
|
||||
# define ENABLE_DA2_DEBUGVRAM 1
|
||||
// # define ENABLE_DA2_DEBUGVRAM 1
|
||||
// # define ENABLE_DA2_DEBUGFULLSCREEN 1
|
||||
// # define ENABLE_DA2_DEBUGMONWAIT 1
|
||||
int da2_do_log = ENABLE_DA2_LOG;
|
||||
@@ -277,6 +275,11 @@ da2_log(const char *fmt, ...)
|
||||
#else
|
||||
# define da2_log(fmt, ...)
|
||||
#endif
|
||||
#ifdef ENABLE_DA2_DEBUGIO
|
||||
# define da2_iolog da2_log
|
||||
#else
|
||||
# define da2_iolog(fmt, ...)
|
||||
#endif
|
||||
#ifdef ENABLE_DA2_DEBUGBLT
|
||||
# define da2_bltlog da2_log
|
||||
#else
|
||||
@@ -284,10 +287,8 @@ da2_log(const char *fmt, ...)
|
||||
#endif
|
||||
|
||||
typedef struct da2_t {
|
||||
// mem_mapping_t vmapping;
|
||||
mem_mapping_t cmapping;
|
||||
|
||||
// uint8_t crtcreg;
|
||||
uint8_t ioctl[16];
|
||||
uint8_t fctl[32];
|
||||
uint16_t crtc[128];
|
||||
@@ -297,7 +298,6 @@ typedef struct da2_t {
|
||||
uint8_t attrc[0x40];
|
||||
int attraddr, attrff;
|
||||
int attr_palette_enable;
|
||||
// uint8_t seqregs[64];
|
||||
int outflipflop;
|
||||
int inflipflop;
|
||||
int iolatch;
|
||||
@@ -306,13 +306,9 @@ typedef struct da2_t {
|
||||
int fctladdr;
|
||||
int crtcaddr;
|
||||
|
||||
uint32_t decode_mask;
|
||||
uint32_t vram_max;
|
||||
|
||||
uint32_t gdcla[8];
|
||||
uint32_t gdcinput[8];
|
||||
uint32_t gdcsrc[8];
|
||||
uint32_t debug_vramold[8];
|
||||
|
||||
uint8_t dac_mask, dac_status;
|
||||
int dac_read, dac_write, dac_pos;
|
||||
@@ -322,20 +318,15 @@ typedef struct da2_t {
|
||||
|
||||
uint8_t plane_mask;
|
||||
|
||||
int fb_only;
|
||||
|
||||
int fast;
|
||||
uint8_t colourcompare, colournocare;
|
||||
int readmode, writemode, readplane;
|
||||
int writemode, readplane;
|
||||
uint8_t planemask;
|
||||
uint32_t charseta, charsetb;
|
||||
|
||||
uint8_t egapal[16];
|
||||
uint32_t pallook[512];
|
||||
PALETTE vgapal;
|
||||
|
||||
int vtotal, dispend, vsyncstart, split, vblankstart;
|
||||
int hdisp, hdisp_old, htotal, hdisp_time, rowoffset;
|
||||
int hdisp, htotal, hdisp_time, rowoffset;
|
||||
int lowres, interlace;
|
||||
int rowcount;
|
||||
double clock;
|
||||
@@ -362,13 +353,9 @@ typedef struct da2_t {
|
||||
|
||||
/* Attribute Buffer E0000-E0FFFh (4 KB) */
|
||||
uint8_t *cram;
|
||||
/* (cram size - 1) >> 3 = 0xFFF */
|
||||
// uint32_t cram_display_mask;
|
||||
/* APA Buffer A0000-BFFFFh (128 KB) */
|
||||
uint8_t *vram;
|
||||
/* xxh */
|
||||
uint8_t *changedvram;
|
||||
/* (vram size - 1) >> 3 = 0x1FFFF */
|
||||
uint32_t vram_display_mask;
|
||||
|
||||
int fullchange;
|
||||
@@ -379,7 +366,6 @@ typedef struct da2_t {
|
||||
card should not attempt to display anything */
|
||||
int override;
|
||||
|
||||
/* end VGA compatible regs*/
|
||||
struct
|
||||
{
|
||||
int enable;
|
||||
@@ -436,13 +422,13 @@ typedef struct da2_t {
|
||||
int old_pos2;
|
||||
} da2_t;
|
||||
|
||||
void da2_recalctimings(da2_t *da2);
|
||||
static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p);
|
||||
void da2_bitblt_exec(void *p);
|
||||
void da2_updatevidselector(da2_t *da2);
|
||||
void da2_reset_ioctl(da2_t *da2);
|
||||
static void da2_reset(void *priv);
|
||||
uint16_t rightRotate(uint16_t data, uint8_t count);
|
||||
static void da2_recalctimings(da2_t *da2);
|
||||
static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p);
|
||||
static void da2_bitblt_exec(void *p);
|
||||
static void da2_updatevidselector(da2_t *da2);
|
||||
static void da2_reset_ioctl(da2_t *da2);
|
||||
static void da2_reset(void *priv);
|
||||
static uint16_t rightRotate(uint16_t data, uint8_t count);
|
||||
|
||||
typedef union {
|
||||
uint32_t d;
|
||||
@@ -454,7 +440,7 @@ typedef struct {
|
||||
} pixel32;
|
||||
|
||||
/* safety read for internal functions */
|
||||
uint32_t
|
||||
static uint32_t
|
||||
DA2_vram_r(uint32_t addr, da2_t *da2)
|
||||
{
|
||||
if (addr & ~DA2_MASK_VRAM)
|
||||
@@ -462,7 +448,7 @@ DA2_vram_r(uint32_t addr, da2_t *da2)
|
||||
return da2->vram[addr];
|
||||
}
|
||||
/* safety write for internal functions */
|
||||
void
|
||||
static void
|
||||
DA2_vram_w(uint32_t addr, uint8_t val, da2_t *da2)
|
||||
{
|
||||
if (addr & ~DA2_MASK_VRAM)
|
||||
@@ -471,7 +457,7 @@ DA2_vram_w(uint32_t addr, uint8_t val, da2_t *da2)
|
||||
return;
|
||||
}
|
||||
/* write pixel data with rop (Note: bitmask must be in big endian) */
|
||||
void
|
||||
static void
|
||||
DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32 *srcpx, da2_t *da2)
|
||||
{
|
||||
uint32_t writepx[8];
|
||||
@@ -521,7 +507,7 @@ DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32 *s
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
DA2_DrawColorWithBitmask(uint32_t destaddr, uint8_t color, uint16_t mask, da2_t *da2)
|
||||
{
|
||||
pixel32 srcpx;
|
||||
@@ -559,7 +545,7 @@ Param Desc
|
||||
33 Size W
|
||||
35 Size H
|
||||
*/
|
||||
void
|
||||
static void
|
||||
DA2_CopyPlaneDataWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, da2_t *da2)
|
||||
{
|
||||
pixel32 srcpx;
|
||||
@@ -573,7 +559,7 @@ DA2_CopyPlaneDataWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask,
|
||||
|
||||
DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2);
|
||||
}
|
||||
void
|
||||
static void
|
||||
DA2_PutcharWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, da2_t *da2)
|
||||
{
|
||||
pixel32 srcpx;
|
||||
@@ -660,7 +646,7 @@ IBMJtoSJIS(uint16_t knj)
|
||||
return knj;
|
||||
}
|
||||
#endif
|
||||
void
|
||||
static void
|
||||
da2_bitblt_load(da2_t *da2)
|
||||
{
|
||||
uint32_t value32;
|
||||
@@ -897,7 +883,7 @@ da2_bitblt_load(da2_t *da2)
|
||||
}
|
||||
}
|
||||
}
|
||||
void
|
||||
static void
|
||||
da2_bitblt_exec(void *p)
|
||||
{
|
||||
da2_t *da2 = (da2_t *) p;
|
||||
@@ -1104,7 +1090,7 @@ da2_bitblt_exec(void *p)
|
||||
break;
|
||||
}
|
||||
}
|
||||
void
|
||||
static void
|
||||
da2_bitblt_dopayload(void *priv)
|
||||
{
|
||||
da2_t *da2 = (da2_t *) priv;
|
||||
@@ -1121,7 +1107,7 @@ da2_bitblt_dopayload(void *priv)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
da2_out(uint16_t addr, uint16_t val, void *p)
|
||||
{
|
||||
da2_t *da2 = (da2_t *) p;
|
||||
@@ -1147,7 +1133,7 @@ da2_out(uint16_t addr, uint16_t val, void *p)
|
||||
da2->dac_pos = 0;
|
||||
break;
|
||||
case 0x3C9: /* Data */
|
||||
// da2_log("DA2 Out addr %03X idx %d:%d val %02X %04X:%04X esdi %04X:%04X\n", addr, da2->dac_write, da2->dac_pos, val, cs >> 4, cpu_state.pc, ES, DI);
|
||||
// da2_iolog("DA2 Out addr %03X idx %d:%d val %02X %04X:%04X esdi %04X:%04X\n", addr, da2->dac_write, da2->dac_pos, val, cs >> 4, cpu_state.pc, ES, DI);
|
||||
da2->dac_status = 0;
|
||||
da2->fullchange = changeframecount;
|
||||
switch (da2->dac_pos) {
|
||||
@@ -1176,11 +1162,11 @@ da2_out(uint16_t addr, uint16_t val, void *p)
|
||||
da2->ioctladdr = val;
|
||||
break;
|
||||
case LS_DATA:
|
||||
// da2_log("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->ioctladdr, val, cs >> 4, cpu_state.pc);
|
||||
// da2_iolog("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->ioctladdr, val, cs >> 4, cpu_state.pc);
|
||||
if (da2->ioctladdr > 0xf)
|
||||
return;
|
||||
if (da2->ioctl[da2->ioctladdr & 15] != val)
|
||||
da2_log("ioctl changed %x: %x -> %x %04X:%04X\n", da2->ioctladdr & 15, da2->ioctl[da2->ioctladdr & 15], val, cs >> 4, cpu_state.pc);
|
||||
da2_iolog("ioctl changed %x: %x -> %x %04X:%04X\n", da2->ioctladdr & 15, da2->ioctl[da2->ioctladdr & 15], val, cs >> 4, cpu_state.pc);
|
||||
oldval = da2->ioctl[da2->ioctladdr];
|
||||
da2->ioctl[da2->ioctladdr] = val;
|
||||
if (oldval != val) {
|
||||
@@ -1197,15 +1183,15 @@ da2_out(uint16_t addr, uint16_t val, void *p)
|
||||
da2->fctladdr = val;
|
||||
break;
|
||||
case LF_DATA:
|
||||
// da2_log("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->fctladdr, val, cs >> 4, cpu_state.pc);
|
||||
// da2_iolog("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->fctladdr, val, cs >> 4, cpu_state.pc);
|
||||
if (da2->fctladdr > 0x1f)
|
||||
return;
|
||||
if (da2->fctl[da2->fctladdr & 0x1f] != val)
|
||||
da2_log("fctl changed %x: %x -> %x %04X:%04X\n", da2->fctladdr & 0x1f, da2->fctl[da2->fctladdr & 0x1f], val, cs >> 4, cpu_state.pc);
|
||||
da2_iolog("fctl changed %x: %x -> %x %04X:%04X\n", da2->fctladdr & 0x1f, da2->fctl[da2->fctladdr & 0x1f], val, cs >> 4, cpu_state.pc);
|
||||
oldval = da2->fctl[da2->fctladdr];
|
||||
da2->fctl[da2->fctladdr] = val;
|
||||
if (da2->fctladdr == 0 && oldval != val) {
|
||||
da2_log("DA2 Out FCTL addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->fctladdr, val, cs >> 4, cpu_state.pc);
|
||||
da2_iolog("DA2 Out FCTL addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->fctladdr, val, cs >> 4, cpu_state.pc);
|
||||
}
|
||||
break;
|
||||
case LC_INDEX:
|
||||
@@ -1215,7 +1201,7 @@ da2_out(uint16_t addr, uint16_t val, void *p)
|
||||
if (da2->crtcaddr > 0x1f)
|
||||
return;
|
||||
if (!(da2->crtcaddr == LC_CURSOR_LOC_HIGH || da2->crtcaddr == LC_CURSOR_LOC_LOWJ))
|
||||
da2_log("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->crtcaddr, val, cs >> 4, cpu_state.pc);
|
||||
da2_iolog("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->crtcaddr, val, cs >> 4, cpu_state.pc);
|
||||
if (!(da2->crtc[da2->crtcaddr] ^ val))
|
||||
return;
|
||||
switch (da2->crtcaddr) {
|
||||
@@ -1256,7 +1242,8 @@ da2_out(uint16_t addr, uint16_t val, void *p)
|
||||
case LC_VERTICAL_SYNC_START:
|
||||
case LC_V_DISPLAY_ENABLE_END:
|
||||
case LC_START_VERTICAL_BLANK:
|
||||
case LC_END_VERTICAL_BLANK:
|
||||
case LC_START_H_DISPLAY_ENAB:
|
||||
case LC_START_V_DISPLAY_ENAB:
|
||||
case LC_VIEWPORT_PRIORITY:
|
||||
da2->fullchange = changeframecount;
|
||||
da2_recalctimings(da2);
|
||||
@@ -1266,7 +1253,7 @@ da2_out(uint16_t addr, uint16_t val, void *p)
|
||||
}
|
||||
break;
|
||||
case LV_PORT:
|
||||
// da2_log("DA2 Out addr %03X val %02X ff %d %04X:%04X\n", addr, val, da2->attrff,cs >> 4, cpu_state.pc);
|
||||
// da2_iolog("DA2 Out addr %03X val %02X ff %d %04X:%04X\n", addr, val, da2->attrff,cs >> 4, cpu_state.pc);
|
||||
if (!da2->attrff) {
|
||||
// da2->attraddr = val & 31;
|
||||
da2->attraddr = val & 0x3f;
|
||||
@@ -1275,14 +1262,14 @@ da2_out(uint16_t addr, uint16_t val, void *p)
|
||||
da2->attr_palette_enable = val & 0x20;
|
||||
da2_recalctimings(da2);
|
||||
}
|
||||
// da2_log("set attraddr: %X\n", da2->attraddr);
|
||||
// da2_iolog("set attraddr: %X\n", da2->attraddr);
|
||||
} else {
|
||||
if ((da2->attraddr == LV_PANNING) && (da2->attrc[LV_PANNING] != val))
|
||||
da2->fullchange = changeframecount;
|
||||
if (da2->attrc[da2->attraddr & 0x3f] != val)
|
||||
da2_log("attr changed %x: %x -> %x\n", da2->attraddr & 0x3f, da2->attrc[da2->attraddr & 0x3f], val);
|
||||
da2_iolog("attr changed %x: %x -> %x\n", da2->attraddr & 0x3f, da2->attrc[da2->attraddr & 0x3f], val);
|
||||
da2->attrc[da2->attraddr & 0x3f] = val;
|
||||
// da2_log("set attrc %x: %x\n", da2->attraddr & 31, val);
|
||||
// da2_iolog("set attrc %x: %x\n", da2->attraddr & 31, val);
|
||||
if (da2->attraddr < 16)
|
||||
da2->fullchange = changeframecount;
|
||||
if (da2->attraddr == LV_MODE_CONTROL || da2->attraddr < 0x10) {
|
||||
@@ -1330,12 +1317,12 @@ da2_out(uint16_t addr, uint16_t val, void *p)
|
||||
da2->attrc[da2->attraddr & 0x3f] = val;
|
||||
break;
|
||||
case LG_INDEX:
|
||||
da2_log("DA2 Out addr %03X val %02X\n", addr, val);
|
||||
da2_iolog("DA2 Out addr %03X val %02X\n", addr, val);
|
||||
da2->gdcaddr = val;
|
||||
break;
|
||||
case LG_DATA:
|
||||
// if(da2->gdcaddr != 8 && da2->gdcaddr != 9) da2_log("DA2 GCOut idx %X val %02X %04X:%04X esdi %04X:%04X\n", da2->gdcaddr, val, cs >> 4, cpu_state.pc, ES, DI);
|
||||
da2_log("DA2 Out addr %03X idx %02X val %02X\n", addr, da2->gdcaddr, val);
|
||||
// if(da2->gdcaddr != 8 && da2->gdcaddr != 9) da2_iolog("DA2 GCOut idx %X val %02X %04X:%04X esdi %04X:%04X\n", da2->gdcaddr, val, cs >> 4, cpu_state.pc, ES, DI);
|
||||
da2_iolog("DA2 Out addr %03X idx %02X val %02X\n", addr, da2->gdcaddr, val);
|
||||
da2->gdcreg[da2->gdcaddr & 0x0f] = val & 0xff;
|
||||
switch (da2->gdcaddr & 0x1f) {
|
||||
case LG_READ_MAP_SELECT:
|
||||
@@ -1355,7 +1342,7 @@ da2_out(uint16_t addr, uint16_t val, void *p)
|
||||
case LG_COMMAND:
|
||||
break;
|
||||
case LG_SET_RESET_2:
|
||||
da2_log("!!!DA2 GC Out addr %03X idx 10 val %02X\n", addr, val);
|
||||
da2_iolog("!!!DA2 GC Out addr %03X idx 10 val %02X\n", addr, val);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@@ -1363,12 +1350,12 @@ da2_out(uint16_t addr, uint16_t val, void *p)
|
||||
// da2->gdcreg[5] = val & 0xff;
|
||||
// break;
|
||||
default:
|
||||
da2_log("DA2? Out addr %03X val %02X\n", addr, val);
|
||||
da2_iolog("DA2? Out addr %03X val %02X\n", addr, val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t
|
||||
static uint16_t
|
||||
da2_in(uint16_t addr, void *p)
|
||||
{
|
||||
da2_t *da2 = (da2_t *) p;
|
||||
@@ -1436,17 +1423,17 @@ da2_in(uint16_t addr, void *p)
|
||||
// if (da2->bitblt.indata) /* for OS/2 J1.3 command prompt scrolling */
|
||||
// da2_bitblt_dopayload(da2);
|
||||
if (da2->bitblt.exec != DA2_BLT_CIDLE) {
|
||||
// da2_log("exec:%x\n", da2->bitblt.exec);
|
||||
// da2_iolog("exec:%x\n", da2->bitblt.exec);
|
||||
temp |= 0x01; /* wait (bit 3 + bit 0) ? need verify */
|
||||
// if (!da2->bitblt.timer.enabled)
|
||||
//{
|
||||
// da2_log("bitblt timer restarted!! %04X:%04X\n", cs >> 4, cpu_state.pc);
|
||||
// da2_iolog("bitblt timer restarted!! %04X:%04X\n", cs >> 4, cpu_state.pc);
|
||||
// timer_advance_u64(&da2->bitblt.timer, da2->bitblt.timerspeed);
|
||||
// }
|
||||
}
|
||||
if (da2->bitblt.indata) temp |= 0x08;
|
||||
#ifdef ENABLE_DA2_DEBUGMONWAIT
|
||||
da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr, temp, cs >> 4, cpu_state.pc);
|
||||
da2_iolog("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr, temp, cs >> 4, cpu_state.pc);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
@@ -1479,7 +1466,7 @@ da2_in(uint16_t addr, void *p)
|
||||
temp = da2->cgastat;
|
||||
} else
|
||||
temp = da2->attrc[da2->attraddr];
|
||||
// da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->attraddr, temp, cs >> 4, cpu_state.pc);
|
||||
// da2_iolog("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->attraddr, temp, cs >> 4, cpu_state.pc);
|
||||
da2->attrff = 0; /* reset flipflop (VGA does not reset flipflop) */
|
||||
break;
|
||||
case LG_INDEX:
|
||||
@@ -1487,10 +1474,10 @@ da2_in(uint16_t addr, void *p)
|
||||
break;
|
||||
case LG_DATA:
|
||||
temp = da2->gdcreg[da2->gdcaddr & 0x1f];
|
||||
// da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->gdcaddr, temp, cs >> 4, cpu_state.pc);
|
||||
// da2_iolog("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->gdcaddr, temp, cs >> 4, cpu_state.pc);
|
||||
break;
|
||||
}
|
||||
// da2_log("DA2 In %04X %04X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc);
|
||||
// da2_iolog("DA2 In %04X %04X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc);
|
||||
return temp;
|
||||
}
|
||||
/*
|
||||
@@ -1504,11 +1491,11 @@ da2_in(uint16_t addr, void *p)
|
||||
* out b(idx), in b, in b(data)
|
||||
* out b(idx), in w(data)
|
||||
*/
|
||||
void
|
||||
static void
|
||||
da2_outb(uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
da2_t *da2 = (da2_t *) p;
|
||||
// da2_log("DA2 Outb addr %03X val %02X %04X:%04X es:di=%x:%x ds:si=%x:%x\n", addr, val, cs >> 4, cpu_state.pc, ES, DI, DS, SI);
|
||||
// da2_iolog("DA2 Outb addr %03X val %02X %04X:%04X es:di=%x:%x ds:si=%x:%x\n", addr, val, cs >> 4, cpu_state.pc, ES, DI, DS, SI);
|
||||
da2->inflipflop = 0;
|
||||
switch (addr) {
|
||||
case LS_DATA:
|
||||
@@ -1538,7 +1525,7 @@ da2_outb(uint16_t addr, uint8_t val, void *p)
|
||||
void
|
||||
da2_outw(uint16_t addr, uint16_t val, void *p)
|
||||
{
|
||||
da2_log("DA2 Outw addr %03X val %04X\n", addr, val);
|
||||
da2_iolog("DA2 Outw addr %03X val %04X\n", addr, val);
|
||||
da2_t *da2 = (da2_t *) p;
|
||||
da2->inflipflop = 0;
|
||||
switch (addr) {
|
||||
@@ -1558,8 +1545,8 @@ da2_outw(uint16_t addr, uint16_t val, void *p)
|
||||
da2->outflipflop = 0;
|
||||
break;
|
||||
case 0x3EC:
|
||||
// da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc);
|
||||
da2_log(" ");
|
||||
// da2_iolog("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc);
|
||||
da2_iolog(" ");
|
||||
// val = rightRotate(val, 8);
|
||||
// da2_out(LG_DATA, val, da2);
|
||||
da2_out(LG_DATA, val >> 8, da2);
|
||||
@@ -1585,12 +1572,12 @@ da2_outw(uint16_t addr, uint16_t val, void *p)
|
||||
break;
|
||||
case AC_REG:
|
||||
/* no register is revealed */
|
||||
da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc);
|
||||
da2_iolog("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc);
|
||||
da2->reg3ee[val & 0x0f] = val >> 8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
uint8_t
|
||||
static uint8_t
|
||||
da2_inb(uint16_t addr, void *p)
|
||||
{
|
||||
uint8_t temp;
|
||||
@@ -1620,10 +1607,10 @@ da2_inb(uint16_t addr, void *p)
|
||||
da2->inflipflop = 0;
|
||||
break;
|
||||
}
|
||||
// da2_log("DA2 Inb %04X %02X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc);
|
||||
// da2_iolog("DA2 Inb %04X %02X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc);
|
||||
return temp;
|
||||
}
|
||||
uint16_t
|
||||
static uint16_t
|
||||
da2_inw(uint16_t addr, void *p)
|
||||
{
|
||||
uint16_t temp;
|
||||
@@ -1631,11 +1618,11 @@ da2_inw(uint16_t addr, void *p)
|
||||
da2->inflipflop = 0;
|
||||
da2->outflipflop = 0;
|
||||
temp = da2_in(addr, da2);
|
||||
da2_log("DA2 Inw addr %03X val %04X\n", addr, temp);
|
||||
da2_iolog("DA2 Inw addr %03X val %04X\n", addr, temp);
|
||||
return temp;
|
||||
}
|
||||
/* IO 03DAh : Input Status Register 2 for DOSSHELL used by DOS J4.0 */
|
||||
uint8_t
|
||||
static uint8_t
|
||||
da2_in_ISR(uint16_t addr, void *p)
|
||||
{
|
||||
da2_t *da2 = (da2_t *) p;
|
||||
@@ -1647,15 +1634,15 @@ da2_in_ISR(uint16_t addr, void *p)
|
||||
da2->cgastat ^= 0x30;
|
||||
temp = da2->cgastat;
|
||||
}
|
||||
// da2_log("DA2D In %04X %04X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc);
|
||||
// da2_iolog("DA2D In %04X %04X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc);
|
||||
return temp;
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
da2_out_ISR(uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
// da2_t* da2 = (da2_t*)p;
|
||||
da2_log("DA2D Out %04X %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc);
|
||||
da2_iolog("DA2D Out %04X %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1759,7 +1746,7 @@ The Font ROM can be accessed via 128 KB memory window located at A0000-BFFFFh.
|
||||
*/
|
||||
|
||||
/* Get character line pattern from jfont rom or gaiji volatile memory */
|
||||
uint32_t
|
||||
static uint32_t
|
||||
getfont_ps55dbcs(int32_t code, int32_t line, void *p)
|
||||
{
|
||||
da2_t *da2 = (da2_t *) p;
|
||||
@@ -1797,14 +1784,14 @@ getfont_ps55dbcs(int32_t code, int32_t line, void *p)
|
||||
}
|
||||
|
||||
/* Reverse the bit order of attribute code IRGB to BGRI(used in Mode 3 and Cursor Color) */
|
||||
uint8_t
|
||||
static int8_t
|
||||
IRGBtoBGRI(uint8_t attr)
|
||||
{
|
||||
attr = ((attr & 0x01) << 7) | ((attr & 0x02) << 5) | ((attr & 0x04) << 3) | ((attr & 0x08) << 1);
|
||||
return attr >>= 4;
|
||||
}
|
||||
/* Get the foreground color from the attribute byte */
|
||||
uint8_t
|
||||
static uint8_t
|
||||
getPS55ForeColor(uint8_t attr, da2_t *da2)
|
||||
{
|
||||
uint8_t foreground = ~attr & 0x08; /* 0000 1000 */
|
||||
@@ -1816,7 +1803,7 @@ getPS55ForeColor(uint8_t attr, da2_t *da2)
|
||||
return foreground;
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
da2_render_blank(da2_t *da2)
|
||||
{
|
||||
int x, xx;
|
||||
@@ -1850,12 +1837,13 @@ da2_render_text(da2_t *da2)
|
||||
int fg, bg;
|
||||
uint32_t chr_dbcs;
|
||||
int chr_wide = 0;
|
||||
int colormode = ((da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) == 0x80);
|
||||
// da2_log("\nda2ma: %x, da2sc: %x\n", da2->ma, da2->sc);
|
||||
for (x = 0; x < da2->hdisp; x += 13) {
|
||||
chr = da2->cram[(da2->ma) & DA2_MASK_CRAM];
|
||||
attr = da2->cram[(da2->ma + 1) & DA2_MASK_CRAM];
|
||||
// if(chr!=0x20) da2_log("chr: %x, attr: %x ", chr, attr);
|
||||
if (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) /* IO 3E8h, Index 1Dh */
|
||||
if (colormode) /* IO 3E8h, Index 1Dh */
|
||||
{ /* --Parse attribute byte in color mode-- */
|
||||
bg = 0; /* bg color is always black (the only way to change background color is programming PAL) */
|
||||
fg = getPS55ForeColor(attr, da2);
|
||||
@@ -1932,24 +1920,24 @@ da2_render_text(da2_t *da2)
|
||||
chr_wide = 0;
|
||||
}
|
||||
/* Line 28 (Underscore) Note: Draw this first to display blink + vertical + underline correctly. */
|
||||
if (da2->sc == 27 && attr & 0x40 && ~da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) { /* Underscore only in monochrome mode */
|
||||
if (da2->sc == da2->crtc[LC_UNDERLINE_LOCATION] && attr & 0x40 && !colormode) { /* Underscore only in monochrome mode */
|
||||
for (uint32_t n = 0; n < 13; n++)
|
||||
p[n] = da2->pallook[da2->egapal[fg]]; /* under line (white) */
|
||||
}
|
||||
/* Column 1 (Vertical Line) */
|
||||
if (attr & 0x10) {
|
||||
p[0] = da2->pallook[da2->egapal[(da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[LV_GRID_COLOR_0]) : 2]]; /* vertical line (white) */
|
||||
p[0] = da2->pallook[da2->egapal[(colormode) ? IRGBtoBGRI(da2->attrc[LV_GRID_COLOR_0]) : 2]]; /* vertical line (white) */
|
||||
}
|
||||
if (da2->sc == 0 && attr & 0x20 && ~da2->attrc[LV_PAS_STATUS_CNTRL]) { /* HGrid */
|
||||
for (uint32_t n = 0; n < 13; n++)
|
||||
p[n] = da2->pallook[da2->egapal[(da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[LV_GRID_COLOR_0]) : 2]]; /* horizontal line (white) */
|
||||
p[n] = da2->pallook[da2->egapal[(colormode) ? IRGBtoBGRI(da2->attrc[LV_GRID_COLOR_0]) : 2]]; /* horizontal line (white) */
|
||||
}
|
||||
/* Drawing text cursor */
|
||||
drawcursor = ((da2->ma == da2->ca) && da2->con && da2->cursoron);
|
||||
if (drawcursor && da2->sc >= da2->crtc[LC_CURSOR_ROW_START] && da2->sc <= da2->crtc[LC_CURSOR_ROW_END]) {
|
||||
int cursorwidth = (da2->crtc[LC_COMPATIBILITY] & 0x20 ? 26 : 13);
|
||||
int cursorcolor = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[LV_CURSOR_COLOR]) : 2; /* Choose color 2 if mode 8 */
|
||||
fg = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? getPS55ForeColor(attr, da2) : ((attr & 0x08) ? 3 : 2);
|
||||
int cursorcolor = (colormode) ? IRGBtoBGRI(da2->attrc[LV_CURSOR_COLOR]) : 2; /* Choose color 2 if mode 8 */
|
||||
fg = (colormode) ? getPS55ForeColor(attr, da2) : ((attr & 0x08) ? 3 : 2);
|
||||
bg = 0;
|
||||
if (attr & 0x04) { /* Color 0 if reverse */
|
||||
bg = fg;
|
||||
@@ -2048,8 +2036,8 @@ da2_render_textm3(da2_t *da2)
|
||||
drawcursor = ((da2->ma == da2->ca) && da2->con && da2->cursoron);
|
||||
if (drawcursor && da2->sc >= da2->crtc[LC_CURSOR_ROW_START] && da2->sc <= da2->crtc[LC_CURSOR_ROW_END]) {
|
||||
// int cursorwidth = (da2->crtc[0x1f] & 0x20 ? 26 : 13);
|
||||
// int cursorcolor = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[0x1a]) : 2;/* Choose color 2 if mode 8 */
|
||||
// fg = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? getPS55ForeColor(attr, da2) : (attr & 0x08) ? 3 : 2;
|
||||
// int cursorcolor = (colormode) ? IRGBtoBGRI(da2->attrc[0x1a]) : 2;/* Choose color 2 if mode 8 */
|
||||
// fg = (colormode) ? getPS55ForeColor(attr, da2) : (attr & 0x08) ? 3 : 2;
|
||||
// bg = 0;
|
||||
// if (attr & 0x04) {/* Color 0 if reverse */
|
||||
// bg = fg;
|
||||
@@ -2066,7 +2054,7 @@ da2_render_textm3(da2_t *da2)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
da2_render_color_4bpp(da2_t *da2)
|
||||
{
|
||||
int changed_offset = da2->ma >> 9;
|
||||
@@ -2115,7 +2103,7 @@ da2_render_color_4bpp(da2_t *da2)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
da2_render_color_8bpp(da2_t *da2)
|
||||
{
|
||||
int changed_offset = da2->ma >> 9;
|
||||
@@ -2164,23 +2152,25 @@ da2_render_color_8bpp(da2_t *da2)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
da2_updatevidselector_tick(void *priv)
|
||||
{
|
||||
da2_t *da2 = (da2_t *) priv;
|
||||
if (da2->ioctl[LS_MODE] & 0x02) {
|
||||
/* VGA passthrough mode */
|
||||
da2->override = 1;
|
||||
timer_disable(&da2->timer);
|
||||
svga_set_override(da2->mb_vga, 0);
|
||||
da2_log("DA2 selector: VGA\n");
|
||||
} else {
|
||||
svga_set_override(da2->mb_vga, 1);
|
||||
timer_enable(&da2->timer);
|
||||
da2->override = 0;
|
||||
da2_log("DA2 selector: DA2\n");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
da2_updatevidselector(da2_t *da2)
|
||||
{
|
||||
timer_set_delay_u64(&da2->timer_vidupd, 100000ull * TIMER_USEC);
|
||||
@@ -2189,15 +2179,16 @@ da2_updatevidselector(da2_t *da2)
|
||||
/*
|
||||
INT 10h video modes supported in DOS J4.0 (The DA-2 doesn't have a video BIOS on its card.)
|
||||
Mode Type Colors Text Base Address PELs Render
|
||||
3 A/N/K 16 80 x 25 B0000h/B8000h 1040 x 725 textm3
|
||||
3 A/N/K 16 80 x 25 B0000h/B8000h 1040 x 754 textm3
|
||||
8 A/N/K 2 80 x 25 E0000h 1040 x 725 text
|
||||
Ah APA 1 78 x 25 A0000h 1024 x 768 color_4bpp
|
||||
Dh APA 16 78 x 25 A0000h 1024 x 768 color_4bpp
|
||||
Eh A/N/K 16 80 x 25 E0000h 1040 x 725 text
|
||||
Fh APA 256 NA A0000h 1024 x 768 color_8bpp
|
||||
45h(undoc) APA 16 NA A0000h 1040 x 768 color_4bpp
|
||||
46h(undoc) APA 16 ? A0000h 1040 x 768 color_4bpp
|
||||
*/
|
||||
void
|
||||
static void
|
||||
da2_recalctimings(da2_t *da2)
|
||||
{
|
||||
double crtcconst;
|
||||
@@ -2217,10 +2208,10 @@ da2_recalctimings(da2_t *da2)
|
||||
da2->vblankstart = da2->crtc[LC_START_VERTICAL_BLANK] & 0xfff;
|
||||
da2->hdisp = da2->crtc[LC_H_DISPLAY_ENABLE_END];
|
||||
|
||||
if (da2->crtc[LC_START_H_DISPLAY_ENAB] & 1) {
|
||||
da2->hdisp--;
|
||||
da2->dispend -= 29;
|
||||
}
|
||||
/* In the video mode 3, you'll see a blank below the screen. It's NOT a bug. */
|
||||
da2->hdisp -= da2->crtc[LC_START_H_DISPLAY_ENAB];
|
||||
da2->dispend -= da2->crtc[LC_START_V_DISPLAY_ENAB];
|
||||
da2->dispend += 1;
|
||||
|
||||
da2->htotal = da2->crtc[LC_HORIZONTAL_TOTAL];
|
||||
da2->htotal += 1;
|
||||
@@ -2246,15 +2237,14 @@ da2_recalctimings(da2_t *da2)
|
||||
if (!(da2->ioctl[LS_MODE] & 0x01)) {
|
||||
da2->hdisp *= 16;
|
||||
da2->char_width = 13;
|
||||
da2->hdisp_old = da2->hdisp;
|
||||
if (da2->crtc[LC_VIEWPORT_PRIORITY] & 0x80) {
|
||||
da2_log("Set videomode to PS/55 8 bpp graphics.\n");
|
||||
da2->render = da2_render_color_8bpp;
|
||||
da2->vram_display_mask = DA2_MASK_A000;
|
||||
} else { /* PS/55 8-color */
|
||||
da2_log("Set videomode to PS/55 4 bpp graphics.\n");
|
||||
da2->vram_display_mask = DA2_MASK_A000;
|
||||
da2->render = da2_render_color_4bpp;
|
||||
da2->vram_display_mask = DA2_MASK_A000;
|
||||
}
|
||||
} else {
|
||||
/* text mode */
|
||||
@@ -2268,7 +2258,6 @@ da2_recalctimings(da2_t *da2)
|
||||
da2->vram_display_mask = DA2_MASK_CRAM;
|
||||
}
|
||||
da2->hdisp *= 13;
|
||||
da2->hdisp_old = da2->hdisp;
|
||||
da2->char_width = 13;
|
||||
}
|
||||
// if (!da2->scrblank && da2->attr_palette_enable)
|
||||
@@ -2303,8 +2292,7 @@ da2_recalctimings(da2_t *da2)
|
||||
da2->dispofftime = TIMER_USEC;
|
||||
da2_log("da2 horiz total %i display end %i vidclock %f\n", da2->crtc[0], da2->crtc[1], da2->clock);
|
||||
da2_log("da2 vert total %i display end %i max row %i vsync %i\n",da2->vtotal,da2->dispend,(da2->crtc[9]&31)+1,da2->vsyncstart);
|
||||
da2_log("total %f on %i cycles off %i cycles frame %i sec %i\n",disptime*crtcconst,da2->dispontime,da2->dispofftime,(da2->dispontime+da2->dispofftime)*da2->vtotal,(da2->dispontime+da2->dispofftime)*da2->vtotal*70);
|
||||
|
||||
da2_log("da2 dispon %lu dispoff %lu on(us) %f off(us) %f\n",da2->dispontime, da2->dispofftime, (double)da2->dispontime / (double)cpuclock / (double) (1ULL << 32) * 1000000.0, (double)da2->dispofftime / (double)cpuclock / (double) (1ULL << 32) * 1000000.0);
|
||||
// da2_log("da2->render %08X\n", da2->render);
|
||||
}
|
||||
|
||||
@@ -2325,12 +2313,10 @@ da2_mapping_update(da2_t *da2)
|
||||
io_sethandler(0x03d0, 0x000b, da2_in_ISR, NULL, NULL, da2_out_ISR, NULL, NULL, da2);
|
||||
mem_mapping_enable(&da2->cmapping);
|
||||
mem_mapping_enable(&da2->mmio.mapping);
|
||||
timer_enable(&da2->timer);
|
||||
timer_enable(&da2->bitblt.timer);
|
||||
} else {
|
||||
da2_log("DA2 disable registers\n");
|
||||
timer_disable(&da2->bitblt.timer);
|
||||
timer_disable(&da2->timer);
|
||||
mem_mapping_disable(&da2->cmapping);
|
||||
mem_mapping_disable(&da2->mmio.mapping);
|
||||
io_removehandler(0x03c0, 0x000a, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, da2);
|
||||
@@ -2339,14 +2325,14 @@ da2_mapping_update(da2_t *da2)
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t
|
||||
static uint8_t
|
||||
da2_mca_read(int port, void *p)
|
||||
{
|
||||
da2_t *da2 = (da2_t *) p;
|
||||
return da2->pos_regs[port & 7];
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
da2_mca_write(int port, uint8_t val, void *p)
|
||||
{
|
||||
da2_t *da2 = (da2_t *) p;
|
||||
@@ -2642,9 +2628,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p)
|
||||
da2->mmdbg_vidaddr = addr;
|
||||
//}
|
||||
#endif
|
||||
|
||||
cycles -= video_timing_write_b;
|
||||
|
||||
da2->changedvram[addr >> 9] = changeframecount;/* 0x1FFFF -> 0x1F */
|
||||
addr <<= 3;
|
||||
|
||||
@@ -2685,27 +2669,13 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p)
|
||||
da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0;
|
||||
else
|
||||
da2->gdcinput[i] = val;
|
||||
|
||||
// for (int i = 0; i < 8; i++)
|
||||
// da2->debug_vramold[i] = da2->vram[addr | i]; /* use latch */
|
||||
da2_gdcropB(addr, bitmask, da2);
|
||||
// for (int i = 0; i < 8; i++)
|
||||
// da2_log("\tsrc %02x in %02x bitm %02x mod %x rop %x: %02x -> %02x\n", da2->gdcsrc[i], da2->gdcinput[i], bitmask, da2->gdcreg[5],da2->gdcreg[LG_COMMAND], da2->debug_vramold[i], da2->vram[addr | i]);//use latch
|
||||
////da2_log("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr);
|
||||
}
|
||||
break;
|
||||
case 1:/* equiv to vga write mode 2 */
|
||||
// if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) {
|
||||
// for (int i = 0; i < 8; i++)
|
||||
// if (da2->planemask & (1 << i))
|
||||
// DA2_vram_w(addr | i, (((val & (1 << i)) ? 0xff : 0) & bitmask) | (da2->gdcsrc[i] & ~bitmask), da2);
|
||||
// //fprintf(da2->mmdbg_fp, "m1-1");
|
||||
// } else {
|
||||
for (int i = 0; i < 8; i++)
|
||||
da2->gdcinput[i] = ((val & (1 << i)) ? 0xff : 0);
|
||||
da2_gdcropB(addr, bitmask, da2);
|
||||
//fprintf(da2->mmdbg_fp, "m1-2");
|
||||
// }
|
||||
break;
|
||||
case 3:/* equiv to vga write mode 3 */
|
||||
if (da2->gdcreg[LG_DATA_ROTATION] & 7)
|
||||
@@ -2717,14 +2687,13 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p)
|
||||
da2_gdcropB(addr, bitmask, da2);
|
||||
break;
|
||||
}
|
||||
// da2_log("%02x%02x%02x%02x\n", da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3]);
|
||||
} else { /* mode 3h text */
|
||||
cycles -= video_timing_write_b;
|
||||
DA2_vram_w(addr, val, da2);
|
||||
da2->fullchange = 2;
|
||||
}
|
||||
}
|
||||
uint16_t
|
||||
static uint16_t
|
||||
rightRotate(uint16_t data, uint8_t count)
|
||||
{
|
||||
return (data >> count) | (data << (sizeof(data) * 8 - count));
|
||||
@@ -2741,8 +2710,7 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p)
|
||||
#ifdef ENABLE_DA2_DEBUGVRAM
|
||||
da2_log("da2_wW %x %d %d %02x\n", addr,
|
||||
addr % (da2->rowoffset * 2) * 8, addr / (da2->rowoffset * 2), val);
|
||||
// if (!(da2->gdcreg[LG_COMMAND] & 0x08))
|
||||
//{
|
||||
|
||||
if (((int) addr - (int) da2->mmdbg_vidaddr) > 2 || (((int) da2->mmdbg_vidaddr - (int) addr) > 2) || da2->mmdbg_vidaddr == addr) {
|
||||
fprintf(da2->mmdbg_fp, "\nW %x %x ", addr, val);
|
||||
for (int i = 0; i <= 0xb; i++)
|
||||
@@ -2755,7 +2723,6 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p)
|
||||
fprintf(da2->mmdbg_fp, "%X", pixeldata);
|
||||
}
|
||||
da2->mmdbg_vidaddr = addr;
|
||||
//}
|
||||
#endif
|
||||
cycles -= video_timing_write_w;
|
||||
|
||||
@@ -2763,7 +2730,6 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p)
|
||||
// da2_log("da2_gcW %05X %02X %04X:%04X esdi %04X:%04X dssi %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc, ES, DI, DS, SI);
|
||||
|
||||
da2->changedvram[addr >> 9] = changeframecount;
|
||||
// da2->changedvram[(addr + 1) >> 12] = changeframecount;
|
||||
addr <<= 3;
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
@@ -2900,7 +2866,7 @@ da2_code_readw(uint32_t addr, void *p)
|
||||
return da2_code_read(addr, da2) | (da2_code_read(addr + 1, da2) << 8);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
da2_doblit(int y1, int y2, int wx, int wy, da2_t *da2)
|
||||
{
|
||||
if (wx != xsize || wy != ysize) {
|
||||
@@ -2919,7 +2885,7 @@ da2_doblit(int y1, int y2, int wx, int wy, da2_t *da2)
|
||||
video_bpp = 8;
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
da2_poll(void *priv)
|
||||
{
|
||||
da2_t *da2 = (da2_t *) priv;
|
||||
@@ -3024,9 +2990,6 @@ da2_poll(void *priv)
|
||||
da2->cgastat |= 8;
|
||||
x = da2->hdisp;
|
||||
|
||||
// if (da2->interlace && !da2->oddeven) da2->lastline++;
|
||||
// if (da2->interlace && da2->oddeven) da2->firstline--;
|
||||
|
||||
wx = x;
|
||||
wy = da2->lastline - da2->firstline;
|
||||
|
||||
@@ -3043,17 +3006,9 @@ da2_poll(void *priv)
|
||||
changeframecount = da2->interlace ? 3 : 2;
|
||||
da2->vslines = 0;
|
||||
|
||||
// if (da2->interlace && da2->oddeven) da2->ma = da2->maback = da2->ma_latch + (da2->rowoffset << 1) + ((da2->crtc[5] & 0x60) >> 5);
|
||||
// else da2->ma = da2->maback = da2->ma_latch + ((da2->crtc[5] & 0x60) >> 5);
|
||||
// da2->ca = ((da2->crtc[0xe] << 8) | da2->crtc[0xf]) + ((da2->crtc[0xb] & 0x60) >> 5) + da2->ca_adj;
|
||||
/* if (da2->interlace && da2->oddeven) da2->ma = da2->maback = da2->ma_latch;
|
||||
else*/
|
||||
da2->ma
|
||||
= da2->maback = da2->ma_latch;
|
||||
da2->ca = ((da2->crtc[LC_CURSOR_LOC_HIGH] << 8) | da2->crtc[LC_CURSOR_LOC_LOWJ]) + da2->ca_adj;
|
||||
|
||||
// da2->ma <<= 1;
|
||||
// da2->maback <<= 1;
|
||||
da2->ca <<= 1;
|
||||
|
||||
// da2_log("Addr %08X vson %03X vsoff %01X\n",da2->ma,da2->vsyncstart,da2->crtc[0x11]&0xF);
|
||||
@@ -3070,9 +3025,6 @@ da2_poll(void *priv)
|
||||
if (da2->sc == (da2->crtc[LC_CURSOR_ROW_START] & 31))
|
||||
da2->con = 1;
|
||||
}
|
||||
// printf("2 %i\n",da2_vsyncstart);
|
||||
// da2_log("da2_poll %i %i %i %i %i %i %i\n", ins, da2->dispofftime, da2->dispontime, da2->vidtime, cyc_total, da2->linepos, da2->vc);
|
||||
// da2_log("r");
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -3129,7 +3081,7 @@ static uint8_t ps55_palette_color[64][3] = {
|
||||
{ 0x3F, 0x15, 0x15 }, { 0x3F, 0x15, 0x3F }, { 0x3F, 0x3F, 0x15 }, { 0x3F, 0x3F, 0x3F }
|
||||
};
|
||||
|
||||
void
|
||||
static void
|
||||
da2_reset_ioctl(da2_t *da2)
|
||||
{
|
||||
da2->ioctl[LS_RESET] = 0x00; /* Bit 0: Reset sequencer */
|
||||
@@ -3243,7 +3195,7 @@ da2_available(void)
|
||||
return (rom_present(DA2_FONTROM_PATH_HANT) || rom_present(DA2_FONTROM_PATH_JPAN));
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
da2_close(void *p)
|
||||
{
|
||||
da2_t *da2 = (da2_t *) p;
|
||||
@@ -3331,7 +3283,7 @@ da2_close(void *p)
|
||||
free(da2);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
da2_speed_changed(void *p)
|
||||
{
|
||||
da2_t *da2 = (da2_t *) p;
|
||||
@@ -3339,7 +3291,7 @@ da2_speed_changed(void *p)
|
||||
da2_recalctimings(da2);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
da2_force_redraw(void *p)
|
||||
{
|
||||
da2_t *da2 = (da2_t *) p;
|
||||
|
||||
@@ -3519,34 +3519,6 @@ s3_recalctimings(svga_t *svga)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef OLD_CODE_REFERENCE
|
||||
if (s3->card_type == S3_MIROCRYSTAL10SD_805 || s3->card_type == S3_MIROCRYSTAL20SD_864 || s3->card_type == S3_MIROCRYSTAL20SV_964 || s3->card_type == S3_SPEA_MIRAGE_86C801 || s3->card_type == S3_SPEA_MIRAGE_86C805 || s3->card_type == S3_MIROCRYSTAL8S_805 || s3->card_type == S3_NUMBER9_9FX_531 || s3->card_type == S3_SPEA_MERCURY_LITE_PCI) {
|
||||
if (!(svga->crtc[0x5e] & 0x04))
|
||||
svga->vblankstart = svga->dispend;
|
||||
if (svga->bpp != 32) {
|
||||
if (svga->crtc[0x31] & 2)
|
||||
s3->width = 2048;
|
||||
else {
|
||||
if (s3->card_type == S3_MIROCRYSTAL10SD_805) {
|
||||
if (svga->hdisp == 1280 && s3->width == 1024) {
|
||||
s3->width = 1280;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (s3->card_type == S3_NUMBER9_9FX_531) {
|
||||
if ((svga->hdisp == 1600) && (s3->width == 1600))
|
||||
s3->width = 800;
|
||||
}
|
||||
}
|
||||
} else if (s3->chip == S3_86C928) {
|
||||
if (svga->bpp == 15) {
|
||||
if (s3->width == 800)
|
||||
s3->width = 1024;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((svga->crtc[0x3a] & 0x10) && !svga->lowres) {
|
||||
s3_log("BPP=%d, pitch=%d, width=%02x, double?=%x, 16bit?=%d, highres?=%d, "
|
||||
"attr=%02x, hdisp=%d.\n", svga->bpp, s3->width, svga->crtc[0x50],
|
||||
@@ -3665,29 +3637,6 @@ s3_recalctimings(svga_t *svga)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#ifdef OLD_CODE_REFERENCE
|
||||
if (s3->chip != S3_VISION868) {
|
||||
if (s3->chip == S3_86C928) {
|
||||
if (s3->width == 2048 || s3->width == 1280 || s3->width == 1600) {
|
||||
if ((s3->width != 1600) && (svga->dispend == 1024) && (svga->hdisp != 1280))
|
||||
svga->hdisp <<= 2;
|
||||
else
|
||||
svga->hdisp <<= 1;
|
||||
}
|
||||
} else if ((s3->chip != S3_86C801) && (s3->chip != S3_86C805) && (s3->chip != S3_TRIO32) && (s3->chip != S3_TRIO64) && (s3->chip != S3_VISION964) && (s3->chip != S3_VISION968)) {
|
||||
if (s3->width == 1280 || s3->width == 1600)
|
||||
svga->hdisp <<= 1;
|
||||
} else if ((s3->card_type == S3_ELSAWIN2KPROX_964) || (s3->card_type == S3_ELSAWIN2KPROX)) {
|
||||
if (s3->width == 1280 || s3->width == 1600)
|
||||
svga->hdisp <<= 1;
|
||||
} else if (s3->card_type == S3_SPEA_MERCURY_P64V) {
|
||||
if (s3->width == 1280 || s3->width == 1600)
|
||||
svga->hdisp <<= 1;
|
||||
}
|
||||
} else if (s3->card_type == S3_NUMBER9_9FX_771)
|
||||
svga->hdisp <<= 1;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 15:
|
||||
svga->render = svga_render_15bpp_highres;
|
||||
@@ -3856,29 +3805,6 @@ s3_recalctimings(svga_t *svga)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#ifdef OLD_CODE_REFERENCE
|
||||
if ((s3->chip != S3_VISION964) && (s3->card_type != S3_SPEA_MIRAGE_86C801) && (s3->card_type != S3_SPEA_MIRAGE_86C805)) {
|
||||
if (s3->chip == S3_86C928)
|
||||
svga->hdisp <<= 1;
|
||||
else if (s3->chip != S3_VISION968)
|
||||
svga->hdisp >>= 1;
|
||||
}
|
||||
if ((s3->chip != S3_VISION868) && (s3->chip != S3_TRIO32) && (s3->chip != S3_TRIO64) && (s3->chip != S3_VISION964)) {
|
||||
if (s3->width == 1280 || s3->width == 1600)
|
||||
svga->hdisp <<= 1;
|
||||
else if (s3->card_type == S3_NUMBER9_9FX_771)
|
||||
svga->hdisp <<= 1;
|
||||
}
|
||||
if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_PHOENIX_VISION968 || s3->card_type == S3_SPEA_MERCURY_P64V) {
|
||||
if (svga->hdisp == (1408 * 2))
|
||||
svga->hdisp >>= 1;
|
||||
else
|
||||
svga->hdisp = s3->width;
|
||||
}
|
||||
|
||||
if (s3->card_type == S3_SPEA_MIRAGE_86C801 || s3->card_type == S3_SPEA_MIRAGE_86C805 || s3->card_type == S3_SPEA_MERCURY_LITE_PCI)
|
||||
svga->hdisp = s3->width;
|
||||
#endif
|
||||
break;
|
||||
case 16:
|
||||
svga->render = svga_render_16bpp_highres;
|
||||
@@ -4044,35 +3970,6 @@ s3_recalctimings(svga_t *svga)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef OLD_CODE_REFERENCE
|
||||
if ((s3->card_type == S3_ELSAWIN2KPROX_964) || (s3->card_type == S3_ELSAWIN2KPROX)) {
|
||||
if (s3->width == 1280 || s3->width == 1600)
|
||||
svga->hdisp <<= 1;
|
||||
}
|
||||
if ((s3->chip != S3_VISION964) && (s3->card_type != S3_SPEA_MIRAGE_86C801) && (s3->card_type != S3_SPEA_MIRAGE_86C805)) {
|
||||
if (s3->chip == S3_86C928)
|
||||
svga->hdisp <<= 1;
|
||||
else if (s3->chip != S3_VISION968)
|
||||
svga->hdisp >>= 1;
|
||||
} else if ((s3->card_type == S3_SPEA_MIRAGE_86C801) || (s3->card_type == S3_SPEA_MIRAGE_86C805))
|
||||
svga->hdisp >>= 1;
|
||||
if ((s3->chip != S3_VISION868) && (s3->chip != S3_TRIO32) && (s3->chip != S3_TRIO64) && (s3->chip != S3_VISION964)) {
|
||||
if (s3->width == 1280 || s3->width == 1600)
|
||||
svga->hdisp <<= 1;
|
||||
else if (s3->card_type == S3_NUMBER9_9FX_771)
|
||||
svga->hdisp <<= 1;
|
||||
}
|
||||
if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_PHOENIX_VISION968 || s3->card_type == S3_SPEA_MERCURY_P64V) {
|
||||
if (svga->hdisp == (1408 << 1))
|
||||
svga->hdisp >>= 1;
|
||||
else
|
||||
svga->hdisp = s3->width;
|
||||
}
|
||||
|
||||
if (s3->card_type == S3_SPEA_MIRAGE_86C801 || s3->card_type == S3_SPEA_MIRAGE_86C805 || s3->card_type == S3_SPEA_MERCURY_LITE_PCI)
|
||||
svga->hdisp = s3->width;
|
||||
#endif
|
||||
break;
|
||||
case 24:
|
||||
svga->render = svga_render_24bpp_highres;
|
||||
@@ -4150,34 +4047,6 @@ s3_recalctimings(svga_t *svga)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#ifdef OLD_CODE_REFERENCE
|
||||
if (s3->chip != S3_VISION968) {
|
||||
if (s3->chip != S3_86C928 && s3->chip != S3_86C801 && s3->chip != S3_86C805)
|
||||
svga->hdisp /= 3;
|
||||
else
|
||||
svga->hdisp = (svga->hdisp * 2) / 3;
|
||||
|
||||
if (s3->card_type == S3_SPEA_MERCURY_LITE_PCI) {
|
||||
if (s3->width == 2048) {
|
||||
switch (svga->dispend) {
|
||||
case 480:
|
||||
svga->hdisp = 640;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (s3->chip == S3_86C924) {
|
||||
if (svga->dispend == 480)
|
||||
svga->hdisp = 640;
|
||||
}
|
||||
} else {
|
||||
if ((s3->card_type == S3_MIROVIDEO40SV_ERGO_968) ||
|
||||
(s3->card_type == S3_PHOENIX_VISION968) || (s3->card_type == S3_SPEA_MERCURY_P64V))
|
||||
svga->hdisp = s3->width;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 32:
|
||||
svga->render = svga_render_32bpp_highres;
|
||||
@@ -4262,48 +4131,6 @@ s3_recalctimings(svga_t *svga)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#ifdef OLD_CODE_REFERENCE
|
||||
if ((s3->chip < S3_TRIO32) && (s3->chip != S3_VISION964) && (s3->chip != S3_VISION968) && (s3->chip != S3_86C928)) {
|
||||
if (s3->chip == S3_VISION868)
|
||||
svga->hdisp >>= 1;
|
||||
else
|
||||
svga->hdisp >>= 2;
|
||||
}
|
||||
if (s3->width == 1280 || s3->width == 1600 || (s3->card_type == S3_SPEA_MERCURY_P64V || s3->card_type == S3_NUMBER9_9FX_771))
|
||||
svga->hdisp <<= 1;
|
||||
if (s3->card_type == S3_NUMBER9_9FX_771) {
|
||||
if (svga->hdisp == 832)
|
||||
svga->hdisp -= 32;
|
||||
}
|
||||
if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_MIROCRYSTAL20SV_964 || s3->card_type == S3_MIROCRYSTAL20SD_864 || s3->card_type == S3_PHOENIX_VISION968 || s3->card_type == S3_SPEA_MERCURY_P64V) {
|
||||
svga->hdisp = s3->width;
|
||||
if (s3->card_type == S3_MIROCRYSTAL20SD_864 || s3->card_type == S3_MIROCRYSTAL20SV_964) {
|
||||
if (s3->width == 800 || s3->width == 1024 || s3->width == 1600) {
|
||||
switch (svga->dispend) {
|
||||
case 400:
|
||||
case 480:
|
||||
svga->hdisp = 640;
|
||||
break;
|
||||
|
||||
case 576:
|
||||
if (s3->width == 1600)
|
||||
s3->width = 800;
|
||||
svga->hdisp = 768;
|
||||
break;
|
||||
|
||||
case 600:
|
||||
if (s3->width == 1600)
|
||||
s3->width = 800;
|
||||
svga->hdisp = 800;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -4362,7 +4189,7 @@ s3_trio64v_recalctimings(svga_t *svga)
|
||||
svga->htotal |= 0x100;
|
||||
if (svga->crtc[0x5d] & 0x02) {
|
||||
svga->hdisp_time |= 0x100;
|
||||
svga->hdisp |= 0x100 * svga->dots_per_clock;
|
||||
svga->hdisp |= (0x100 * svga->dots_per_clock);
|
||||
}
|
||||
if (svga->crtc[0x5e] & 0x01)
|
||||
svga->vtotal |= 0x400;
|
||||
@@ -4681,6 +4508,7 @@ s3_trio64_getclock(int clock, void *priv)
|
||||
return 25175000.0;
|
||||
if (clock == 1)
|
||||
return 28322000.0;
|
||||
|
||||
m = svga->seqregs[0x13] + 2;
|
||||
n1 = (svga->seqregs[0x12] & 0x1f) + 2;
|
||||
n2 = ((svga->seqregs[0x12] >> 5) & 0x07);
|
||||
@@ -9523,7 +9351,6 @@ s3_disable_handlers(s3_t *s3)
|
||||
reset_state->bios_rom.mapping = s3->bios_rom.mapping;
|
||||
|
||||
reset_state->svga.timer = s3->svga.timer;
|
||||
reset_state->svga.timer8514 = s3->svga.timer8514;
|
||||
|
||||
memset(s3->svga.vram, 0x00, s3->svga.vram_max + 8);
|
||||
memset(s3->svga.changedvram, 0x00, (s3->svga.vram_max >> 12) + 1);
|
||||
|
||||
@@ -739,7 +739,8 @@ svga_recalctimings(svga_t *svga)
|
||||
svga->vblankstart++;
|
||||
|
||||
svga->hdisp = svga->crtc[1];
|
||||
svga->hdisp++;
|
||||
if (svga->crtc[1] & 1)
|
||||
svga->hdisp++;
|
||||
|
||||
svga->htotal = svga->crtc[0];
|
||||
/* +5 has been verified by Sergi to be correct - +6 must have been an off by one error. */
|
||||
@@ -944,7 +945,7 @@ svga_recalctimings(svga_t *svga)
|
||||
if (dev->on) {
|
||||
uint32_t dot8514 = dev->h_blankstart;
|
||||
uint32_t adj_dot8514 = dev->h_blankstart;
|
||||
uint32_t eff_mask8514 = 0x0000003f;
|
||||
uint32_t eff_mask8514 = 0x0000001f;
|
||||
dev->hblank_sub = 0;
|
||||
|
||||
while (adj_dot8514 < (dev->h_total << 1)) {
|
||||
@@ -1029,8 +1030,9 @@ svga_recalctimings(svga_t *svga)
|
||||
|
||||
if (ibm8514_active && (svga->dev8514 != NULL)) {
|
||||
if (dev->on) {
|
||||
disptime8514 = dev->h_total ? dev->h_total : TIMER_USEC;
|
||||
_dispontime8514 = dev->hdisped;
|
||||
disptime8514 = dev->h_total;
|
||||
_dispontime8514 = (dev->hdisped + 1) * 8;
|
||||
svga_log("HDISPED 8514=%d, htotal=%02x.\n", (dev->hdisped + 1) << 3, dev->h_total);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1174,7 +1176,10 @@ svga_do_render(svga_t *svga)
|
||||
}
|
||||
|
||||
if (!svga->override) {
|
||||
svga->render(svga);
|
||||
if (svga->render_override)
|
||||
svga->render_override(svga->priv_parent);
|
||||
else
|
||||
svga->render(svga);
|
||||
|
||||
svga->x_add = (svga->monitor->mon_overscan_x >> 1);
|
||||
svga_render_overscan_left(svga);
|
||||
|
||||
@@ -96,6 +96,7 @@ video_cards[] = {
|
||||
{ .device = &genius_device, .flags = VIDEO_FLAG_TYPE_NONE },
|
||||
{ .device = &nga_device, .flags = VIDEO_FLAG_TYPE_NONE },
|
||||
{ .device = &ogc_device, .flags = VIDEO_FLAG_TYPE_NONE },
|
||||
{ .device = &jvga_device, .flags = VIDEO_FLAG_TYPE_NONE },
|
||||
{ .device = &oti037c_device, .flags = VIDEO_FLAG_TYPE_NONE },
|
||||
{ .device = &oti067_device, .flags = VIDEO_FLAG_TYPE_NONE },
|
||||
{ .device = &oti077_device, .flags = VIDEO_FLAG_TYPE_NONE },
|
||||
|
||||
@@ -31,7 +31,8 @@
|
||||
#include <86box/vid_svga.h>
|
||||
#include <86box/vid_vga.h>
|
||||
|
||||
static video_timings_t timing_vga = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 };
|
||||
video_timings_t timing_vga = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 };
|
||||
|
||||
static video_timings_t timing_ps1_svga_isa = { .type = VIDEO_ISA, .write_b = 6, .write_w = 8, .write_l = 16, .read_b = 6, .read_w = 8, .read_l = 16 };
|
||||
static video_timings_t timing_ps1_svga_mca = { .type = VIDEO_MCA, .write_b = 6, .write_w = 8, .write_l = 16, .read_b = 6, .read_w = 8, .read_l = 16 };
|
||||
|
||||
@@ -135,27 +136,34 @@ int vga_isenabled(void* p)
|
||||
return svga->vga_enabled;
|
||||
}
|
||||
|
||||
static void *
|
||||
vga_init(const device_t *info)
|
||||
void
|
||||
vga_init(const device_t *info, vga_t *vga, int enabled)
|
||||
{
|
||||
vga_t *vga = malloc(sizeof(vga_t));
|
||||
memset(vga, 0, sizeof(vga_t));
|
||||
|
||||
rom_init(&vga->bios_rom, "roms/video/vga/ibm_vga.bin", 0xc0000, 0x8000, 0x7fff, 0x2000, MEM_MAPPING_EXTERNAL);
|
||||
|
||||
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_vga);
|
||||
|
||||
svga_init(info, &vga->svga, vga, 1 << 18, /*256kb*/
|
||||
NULL,
|
||||
vga_in, vga_out,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
io_sethandler(0x03c0, 0x0020, vga_in, NULL, NULL, vga_out, NULL, NULL, vga);
|
||||
|
||||
vga->svga.bpp = 8;
|
||||
vga->svga.miscout = 1;
|
||||
|
||||
vga->svga.vga_enabled = enabled;
|
||||
}
|
||||
|
||||
static void *
|
||||
vga_standalone_init(const device_t *info)
|
||||
{
|
||||
vga_t *vga = calloc(1, sizeof(vga_t));
|
||||
|
||||
rom_init(&vga->bios_rom, "roms/video/vga/ibm_vga.bin", 0xc0000, 0x8000, 0x7fff, 0x2000, MEM_MAPPING_EXTERNAL);
|
||||
|
||||
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_vga);
|
||||
|
||||
vga_init(info, vga, 0);
|
||||
|
||||
io_sethandler(0x03c0, 0x0020, vga_in, NULL, NULL, vga_out, NULL, NULL, vga);
|
||||
|
||||
return vga;
|
||||
}
|
||||
|
||||
@@ -163,26 +171,17 @@ vga_init(const device_t *info)
|
||||
void *
|
||||
ps1vga_init(const device_t *info)
|
||||
{
|
||||
vga_t *vga = malloc(sizeof(vga_t));
|
||||
memset(vga, 0, sizeof(vga_t));
|
||||
vga_t *vga = calloc(1, sizeof(vga_t));
|
||||
|
||||
if (info->flags & DEVICE_MCA)
|
||||
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ps1_svga_mca);
|
||||
else
|
||||
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ps1_svga_isa);
|
||||
|
||||
svga_init(info, &vga->svga, vga, 1 << 18, /*256kb*/
|
||||
NULL,
|
||||
vga_in, vga_out,
|
||||
NULL,
|
||||
NULL);
|
||||
vga_init(info, vga, 1);
|
||||
|
||||
io_sethandler(0x03c0, 0x0020, vga_in, NULL, NULL, vga_out, NULL, NULL, vga);
|
||||
|
||||
vga->svga.bpp = 8;
|
||||
vga->svga.miscout = 1;
|
||||
vga->svga.vga_enabled = 1;
|
||||
|
||||
return vga;
|
||||
}
|
||||
|
||||
@@ -223,7 +222,7 @@ const device_t vga_device = {
|
||||
.internal_name = "vga",
|
||||
.flags = DEVICE_ISA,
|
||||
.local = 0,
|
||||
.init = vga_init,
|
||||
.init = vga_standalone_init,
|
||||
.close = vga_close,
|
||||
.reset = NULL,
|
||||
.available = vga_available,
|
||||
|
||||