Merge branch 'master' into experimental

This commit is contained in:
Melissa Goad
2017-06-07 13:37:10 -05:00
284 changed files with 13342 additions and 6497 deletions

View File

@@ -1,7 +1,42 @@
/* Copyright holders: Tenshi
see COPYING for more details
*/
#define emulator_version "1.20"
#define emulator_version_w L"1.20"
/*
* 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.
*
* Main emulator include file.
*
* Version: @(#)86box.h 1.0.2 2017/06/04
*
* Author: Miran Grca, <mgrca8@gmail.com>
* Copyright 2016-2017 Miran Grca.
*/
#ifndef BOX_H
# define BOX_H
#define CONFIG_FILE L"86box.cfg"
#if defined(ENABLE_BUSLOGIC_LOG) || \
defined(ENABLE_CDROM_LOG) || \
defined(ENABLE_D86F_LOG) || \
defined(ENABLE_FDC_LOG) || \
defined(ENABLE_IDE_LOG) || \
defined(ENABLE_NIC_LOG)
# define ENABLE_LOG_TOGGLES 1
#endif
#if defined(ENABLE_LOG_BREAKPOINT) || defined(ENABLE_VRAM_DUMP)
# define ENABLE_LOG_COMMANDS 1
#endif
#define EMU_VERSION "2.00"
#define EMU_VERSION_W L"2.00"
#define EMU_NAME "86Box"
#define EMU_NAME_W L"86Box"
#define CONFIG_FILE_W L"86box.cfg"
#endif /*BOX_H*/

View File

@@ -28,6 +28,13 @@ uint32_t oldpc2;
int trap;
uint16_t flags,eflags;
uint32_t oldds,oldss,olddslimit,oldsslimit,olddslimitw,oldsslimitw;
x86seg gdt,ldt,idt,tr;
x86seg _cs,_ds,_es,_ss,_fs,_gs;
x86seg _oldds;
extern int cpl_override;
@@ -40,6 +47,8 @@ uint16_t ea_rseg;
int is486;
int cgate32;
uint32_t cr2, cr3, cr4;
uint32_t dr[8];
uint8_t romext[32768];

View File

@@ -1,6 +1,21 @@
/* Copyright holders: Sarah Walker, Tenshi
see COPYING for more details
*/
/*
* 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.
*
* Common 386 CPU code.
*
* Version: @(#)386_common.h 1.0.0 2017/05/30
*
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016-2017 Miran Grca.
*/
extern uint16_t ea_rseg;
#undef readmemb
@@ -8,39 +23,15 @@ extern uint16_t ea_rseg;
#define readmemb(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF)?readmemb386l(s,a): *(uint8_t *)(readlookup2[(uint32_t)((s)+(a))>>12] + (uint32_t)((s) + (a))) )
#define readmemq(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a))&0xFFF)>0xFF8)?readmemql(s,a):*(uint64_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a))))
#define readmemq(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a)) & 7))?readmemql(s,a):*(uint64_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a))))
#define writememb(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF) writememb386l(s,a,v); else *(uint8_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
#define writememw(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a))&0xFFF)>0xFFE) writememwl(s,a,v); else *(uint16_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
#define writememl(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a))&0xFFF)>0xFFC) writememll(s,a,v); else *(uint32_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
#define writememq(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a))&0xFFF)>0xFF8) writememql(s,a,v); else *(uint64_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
#define writememw(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a)) & 1)) writememwl(s,a,v); else *(uint16_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
#define writememl(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a)) & 3)) writememll(s,a,v); else *(uint32_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
#define writememq(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a)) & 7)) writememql(s,a,v); else *(uint64_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
#if 0
#define check_io_perm(port) if (!IOPLp || (eflags&VM_FLAG)) \
{ \
int tempi = checkio(port); \
if (cpu_state.abrt) return 1; \
if (tempi) \
{ \
x86gpf("check_io_perm(): no permission",0); \
return 1; \
} \
}
#define checkio_perm(port) if (!IOPLp || (eflags&VM_FLAG)) \
{ \
tempi = checkio(port); \
if (cpu_state.abrt) break; \
if (tempi) \
{ \
x86gpf("checkio_perm(): no permission",0); \
break; \
} \
}
#endif
#define check_io_perm(port) if (msw&1 && ((CPL > IOPL) || (eflags&VM_FLAG))) \
{ \
int tempi = checkio(port); \
@@ -138,8 +129,8 @@ static __inline uint16_t fastreadw(uint32_t a)
uint16_t val;
if ((a&0xFFF)>0xFFE)
{
val = readmemb(0, a);
val |= (readmemb(0, a + 1) << 8);
val = fastreadb(a);
val |= (fastreadb(a + 1) << 8);
return val;
}
if ((a>>12)==pccache) return *((uint16_t *)&pccache2[a]);
@@ -169,10 +160,8 @@ static __inline uint32_t fastreadl(uint32_t a)
}
return *((uint32_t *)&pccache2[a]);
}
val =readmemb(0,a);
val |=(readmemb(0,a+1)<<8);
val |=(readmemb(0,a+2)<<16);
val |=(readmemb(0,a+3)<<24);
val = fastreadw(a);
val |= (fastreadw(a + 2) << 16);
return val;
}

View File

@@ -21,6 +21,8 @@
#define CPU_BLOCK_END() cpu_block_end = 1
uint32_t cpu_cur_status = 0;
int cpu_reps, cpu_reps_latched;
int cpu_notreps, cpu_notreps_latched;
@@ -1278,6 +1280,19 @@ int dontprint=0;
#define CACHE_ON() (!(cr0 & (1 << 30)) /*&& (cr0 & 1)*/ && !(flags & T_FLAG))
static int cpu_cycle_period(void)
{
switch(cpu_pci_speed)
{
case 333333333:
return is_pentium ? 1000 : 1333;
break;
default:
return 1000;
break;
}
}
static int cycles_main = 0;
void exec386_dynarec(int cycs)
{
@@ -1292,8 +1307,42 @@ void exec386_dynarec(int cycs)
while (cycles_main > 0)
{
int cycles_start;
cycles += 1000;
#if 0
switch(cpu_pci_speed)
{
case 16000000:
cycles += 640;
break;
case 20000000:
cycles += 800;
break;
case 25000000:
default:
cycles += 1000;
break;
case 27500000:
cycles += 1100;
break;
case 30000000:
cycles += 1200;
break;
case 333333333:
cycles += 1333;
break;
case 37500000:
cycles += 1500;
break;
case 40000000:
cycles += 1600;
break;
case 41666667:
cycles += 1666;
break;
}
#endif
cycles += cpu_cycle_period();
cycles_start = cycles;
timer_start_period(cycles << TIMER_SHIFT);
@@ -1372,7 +1421,7 @@ void exec386_dynarec(int cycs)
and physical address. The physical address check will
also catch any page faults at this stage*/
valid_block = (block->pc == cs + cpu_state.pc) && (block->_cs == cs) &&
(block->use32 == use32) && (block->phys == phys_addr) && (block->stack32 == stack32);
(block->phys == phys_addr) && (block->status == cpu_cur_status);
if (!valid_block)
{
uint64_t mask = (uint64_t)1 << ((phys_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK);
@@ -1384,7 +1433,7 @@ void exec386_dynarec(int cycs)
if (new_block)
{
valid_block = (new_block->pc == cs + cpu_state.pc) && (new_block->_cs == cs) &&
(new_block->use32 == use32) && (new_block->phys == phys_addr) && (new_block->stack32 == stack32);
(new_block->phys == phys_addr) && (new_block->status == cpu_cur_status);
if (valid_block)
block = new_block;
}

View File

@@ -1,6 +1,23 @@
/* Copyright holders: Sarah Walker, Tenshi, leilei
see COPYING for more details
*/
/*
* 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.
*
* 286/386+ instruction handlers list.
*
* Version: @(#)386_ops.h 1.0.0 2017/05/30
*
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
* leilei,
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016-2017 leilei.
* Copyright 2016-2017 Miran Grca.
*/
#include "x86_ops.h"

View File

@@ -1,6 +1,21 @@
/* Copyright holders: Sarah Walker, Tenshi
see COPYING for more details
*/
/*
* 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.
*
* 808x CPU emulation.
*
* Version: @(#)808x.c 1.0.0 2017/05/30
*
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016-2017 Miran Grca.
*/
/*SHR AX,1
4 clocks - fetch opcode
@@ -46,12 +61,14 @@ void writememll(uint32_t seg, uint32_t addr, uint32_t val);
uint8_t readmemb(uint32_t a)
{
if (a!=(cs+cpu_state.pc)) memcycs+=4;
if (readlookup2 == NULL) return readmembl(a);
if (readlookup2[(a)>>12]==-1) return readmembl(a);
else return *(uint8_t *)(readlookup2[(a) >> 12] + (a));
}
uint8_t readmembf(uint32_t a)
{
if (readlookup2 == NULL) return readmembl(a);
if (readlookup2[(a)>>12]==-1) return readmembl(a);
else return *(uint8_t *)(readlookup2[(a) >> 12] + (a));
}
@@ -59,6 +76,7 @@ uint8_t readmembf(uint32_t a)
uint16_t readmemw(uint32_t s, uint16_t a)
{
if (a!=(cs+cpu_state.pc)) memcycs+=(8>>is8086);
if (readlookup2 == NULL) return readmemwl(s,a);
if ((readlookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF)) return readmemwl(s,a);
else return *(uint16_t *)(readlookup2[(s + a) >> 12] + s + a);
}
@@ -76,6 +94,7 @@ void writemembl(uint32_t addr, uint8_t val);
void writememb(uint32_t a, uint8_t v)
{
memcycs+=4;
if (writelookup2 == NULL) writemembl(a,v);
if (writelookup2[(a)>>12]==-1) writemembl(a,v);
else *(uint8_t *)(writelookup2[a >> 12] + a) = v;
}
@@ -83,12 +102,14 @@ void writememwl(uint32_t seg, uint32_t addr, uint16_t val);
void writememw(uint32_t s, uint32_t a, uint16_t v)
{
memcycs+=(8>>is8086);
if (writelookup2 == NULL) writememwl(s,a,v);
if (writelookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF) writememwl(s,a,v);
else *(uint16_t *)(writelookup2[(s + a) >> 12] + s + a) = v;
}
void writememll(uint32_t seg, uint32_t addr, uint32_t val);
void writememl(uint32_t s, uint32_t a, uint32_t v)
{
if (writelookup2 == NULL) writememll(s,a,v);
if (writelookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF) writememll(s,a,v);
else *(uint32_t *)(writelookup2[(s + a) >> 12] + s + a) = v;
}
@@ -546,6 +567,7 @@ void resetx86()
resets++;
ins = 0;
use32=0;
cpu_cur_status = 0;
stack32=0;
cpu_state.pc=0;
msw=0;
@@ -583,6 +605,7 @@ void softresetx86()
{
use32=0;
stack32=0;
cpu_cur_status = 0;
cpu_state.pc=0;
msw=0;
cr0=0;

View File

@@ -35,6 +35,9 @@
typedef struct codeblock_t
{
uint64_t page_mask, page_mask2;
uint64_t cmp;
/*Previous and next pointers, for the codeblock list associated with
each physical page. Two sets of pointers, as a codeblock can be
present in two pages.*/
@@ -45,22 +48,19 @@ typedef struct codeblock_t
fails.*/
struct codeblock_t *parent, *left, *right;
int pnt;
int ins;
int was_recompiled;
int TOP;
uint32_t pc;
uint32_t _cs;
uint32_t endpc;
uint32_t phys, phys_2;
uint32_t use32;
int stack32;
int pnt;
int ins;
uint64_t page_mask, page_mask2;
int was_recompiled;
uint32_t status;
uint32_t flags;
int TOP;
uint64_t cmp;
uint8_t data[2048];
} codeblock_t;

View File

@@ -866,6 +866,8 @@ static void CHECK_SEG_READ(x86seg *seg)
return;
if (seg->checked)
return;
if ((seg == &_ds) && codegen_flat_ds)
return;
if (IS_32_ADDR(&seg->base))
{
@@ -900,6 +902,8 @@ static void CHECK_SEG_WRITE(x86seg *seg)
return;
if (seg->checked)
return;
if ((seg == &_ds) && codegen_flat_ds)
return;
if (IS_32_ADDR(&seg->base))
{
@@ -926,6 +930,9 @@ static void CHECK_SEG_WRITE(x86seg *seg)
}
static void CHECK_SEG_LIMITS(x86seg *seg, int end_offset)
{
if ((seg == &_ds && codegen_flat_ds) || (seg == &_ss && codegen_flat_ss))
return;
if (IS_32_ADDR(&seg->base))
{
addbyte(0xb8 | REG_ESI); /*MOV ESI, &addr*/
@@ -962,7 +969,12 @@ static void CHECK_SEG_LIMITS(x86seg *seg, int end_offset)
static void MEM_LOAD_ADDR_EA_B(x86seg *seg)
{
if (IS_32_ADDR(&seg->base))
if ((seg == &_ds && codegen_flat_ds) || (seg == &_ss && codegen_flat_ss))
{
addbyte(0x31); /*XOR ECX, ECX*/
addbyte(0xc9);
}
else if (IS_32_ADDR(&seg->base))
{
addbyte(0x8b); /*MOVL ECX, seg->base*/
addbyte(0x0c);
@@ -1030,7 +1042,12 @@ static void MEM_LOAD_ADDR_EA_B(x86seg *seg)
}
static void MEM_LOAD_ADDR_EA_W(x86seg *seg)
{
if (IS_32_ADDR(&seg->base))
if ((seg == &_ds && codegen_flat_ds) || (seg == &_ss && codegen_flat_ss))
{
addbyte(0x31); /*XOR ECX, ECX*/
addbyte(0xc9);
}
else if (IS_32_ADDR(&seg->base))
{
addbyte(0x8b); /*MOVL ECX, seg->base*/
addbyte(0x0c);
@@ -1049,16 +1066,14 @@ static void MEM_LOAD_ADDR_EA_W(x86seg *seg)
addbyte(0x8d);
addbyte(0x34);
addbyte(0x08);
addbyte(0x67); /*LEA EDI, 1[ESI]*/
addbyte(0x8d);
addbyte(0x7e);
addbyte(0x01);
addbyte(0x89); /*MOV EDI, ESI*/
addbyte(0xf7);
addbyte(0xc1); /*SHR ESI, 12*/
addbyte(0xe8 | REG_ESI);
addbyte(12);
addbyte(0xf7); /*TEST EDI, 0xfff*/
addbyte(0xf7); /*TEST EDI, 1*/
addbyte(0xc7);
addlong(0xfff);
addlong(1);
if (IS_32_ADDR(readlookup2))
{
addbyte(0x67); /*MOV RSI, readlookup2[ESI*8]*/
@@ -1078,18 +1093,17 @@ static void MEM_LOAD_ADDR_EA_W(x86seg *seg)
addbyte(0x34);
addbyte(0xf2);
}
addbyte(0x74); /*JE slowpath*/
addbyte(3+2+5+2);
addbyte(0x75); /*JNE slowpath*/
addbyte(3+2+4+2);
addbyte(0x83); /*CMP ESI, -1*/
addbyte(0xf8 | REG_ESI);
addbyte(-1);
addbyte(0x74); /*JE slowpath*/
addbyte(5+2);
addbyte(0x66); /*MOV AX,-1[RDI+RSI]*/
addbyte(4+2);
addbyte(0x66); /*MOV AX,[RDI+RSI]*/
addbyte(0x8b);
addbyte(0x44);
addbyte(0x04);
addbyte(REG_EDI | (REG_ESI << 3));
addbyte(-1);
addbyte(0xeb); /*JMP done*/
addbyte(2+2+12+4+6);
/*slowpath:*/
@@ -1114,7 +1128,12 @@ static void MEM_LOAD_ADDR_EA_W_OFFSET(x86seg *seg, int offset)
}
static void MEM_LOAD_ADDR_EA_L(x86seg *seg)
{
if (IS_32_ADDR(&seg->base))
if ((seg == &_ds && codegen_flat_ds) || (seg == &_ss && codegen_flat_ss))
{
addbyte(0x31); /*XOR ECX, ECX*/
addbyte(0xc9);
}
else if (IS_32_ADDR(&seg->base))
{
addbyte(0x8b); /*MOVL ECX, seg->base*/
addbyte(0x0c);
@@ -1133,16 +1152,14 @@ static void MEM_LOAD_ADDR_EA_L(x86seg *seg)
addbyte(0x8d);
addbyte(0x34);
addbyte(0x08);
addbyte(0x67); /*LEA EDI, 3[ESI]*/
addbyte(0x8d);
addbyte(0x7e);
addbyte(0x03);
addbyte(0x89); /*MOV EDI, ESI*/
addbyte(0xf7);
addbyte(0xc1); /*SHR ESI, 12*/
addbyte(0xe8 | REG_ESI);
addbyte(12);
addbyte(0xf7); /*TEST EDI, 0xffc*/
addbyte(0xf7); /*TEST EDI, 3*/
addbyte(0xc7);
addlong(0xffc);
addlong(3);
if (IS_32_ADDR(readlookup2))
{
addbyte(0x67); /*MOV RSI, readlookup2[ESI*8]*/
@@ -1162,17 +1179,16 @@ static void MEM_LOAD_ADDR_EA_L(x86seg *seg)
addbyte(0x34);
addbyte(0xf2);
}
addbyte(0x74); /*JE slowpath*/
addbyte(3+2+4+2);
addbyte(0x75); /*JNE slowpath*/
addbyte(3+2+3+2);
addbyte(0x83); /*CMP ESI, -1*/
addbyte(0xf8 | REG_ESI);
addbyte(-1);
addbyte(0x74); /*JE slowpath*/
addbyte(4+2);
addbyte(0x8b); /*MOV EAX,-3[RDI+RSI]*/
addbyte(0x44);
addbyte(3+2);
addbyte(0x8b); /*MOV EAX,[RDI+RSI]*/
addbyte(0x04);
addbyte(REG_EDI | (REG_ESI << 3));
addbyte(-3);
addbyte(0xeb); /*JMP done*/
addbyte(2+2+12+4+6);
/*slowpath:*/
@@ -1190,7 +1206,12 @@ static void MEM_LOAD_ADDR_EA_L(x86seg *seg)
}
static void MEM_LOAD_ADDR_EA_Q(x86seg *seg)
{
if (IS_32_ADDR(&seg->base))
if ((seg == &_ds && codegen_flat_ds) || (seg == &_ss && codegen_flat_ss))
{
addbyte(0x31); /*XOR ECX, ECX*/
addbyte(0xc9);
}
else if (IS_32_ADDR(&seg->base))
{
addbyte(0x8b); /*MOVL ECX, seg->base*/
addbyte(0x0c);
@@ -1209,16 +1230,14 @@ static void MEM_LOAD_ADDR_EA_Q(x86seg *seg)
addbyte(0x8d);
addbyte(0x34);
addbyte(0x08);
addbyte(0x67); /*LEA EDI, 7[ESI]*/
addbyte(0x8d);
addbyte(0x7e);
addbyte(0x07);
addbyte(0x89); /*MOV EDI, ESI*/
addbyte(0xf7);
addbyte(0xc1); /*SHR ESI, 12*/
addbyte(0xe8 | REG_ESI);
addbyte(12);
addbyte(0xf7); /*TEST EDI, 0xff8*/
addbyte(0xf7); /*TEST EDI, 7*/
addbyte(0xc7);
addlong(0xff8);
addlong(7);
if (IS_32_ADDR(readlookup2))
{
addbyte(0x67); /*MOV RSI, readlookup2[ESI*8]*/
@@ -1238,18 +1257,17 @@ static void MEM_LOAD_ADDR_EA_Q(x86seg *seg)
addbyte(0x34);
addbyte(0xf2);
}
addbyte(0x74); /*JE slowpath*/
addbyte(3+2+5+2);
addbyte(0x75); /*JNE slowpath*/
addbyte(3+2+4+2);
addbyte(0x83); /*CMP ESI, -1*/
addbyte(0xf8 | REG_ESI);
addbyte(-1);
addbyte(0x74); /*JE slowpath*/
addbyte(5+2);
addbyte(0x48); /*MOV RAX,-7[RDI+RSI]*/
addbyte(4+2);
addbyte(0x48); /*MOV RAX,[RDI+RSI]*/
addbyte(0x8b);
addbyte(0x44);
addbyte(0x04);
addbyte(REG_EDI | (REG_ESI << 3));
addbyte(-7);
addbyte(0xeb); /*JMP done*/
addbyte(2+2+12+4+6);
/*slowpath:*/
@@ -1309,7 +1327,12 @@ static void MEM_STORE_ADDR_EA_B(x86seg *seg, int host_reg)
addbyte(8);
host_reg = 8;
}
if (IS_32_ADDR(&seg->base))
if ((seg == &_ds && codegen_flat_ds) || (seg == &_ss && codegen_flat_ss))
{
addbyte(0x31); /*XOR ECX, ECX*/
addbyte(0xc9);
}
else if (IS_32_ADDR(&seg->base))
{
addbyte(0x8b); /*MOVL ECX, seg->base*/
addbyte(0x0c);
@@ -1388,7 +1411,12 @@ static void MEM_STORE_ADDR_EA_B(x86seg *seg, int host_reg)
}
static void MEM_STORE_ADDR_EA_W(x86seg *seg, int host_reg)
{
if (IS_32_ADDR(&seg->base))
if ((seg == &_ds && codegen_flat_ds) || (seg == &_ss && codegen_flat_ss))
{
addbyte(0x31); /*XOR ECX, ECX*/
addbyte(0xc9);
}
else if (IS_32_ADDR(&seg->base))
{
addbyte(0x8b); /*MOVL ECX, seg->base*/
addbyte(0x0c);
@@ -1407,16 +1435,14 @@ static void MEM_STORE_ADDR_EA_W(x86seg *seg, int host_reg)
addbyte(0x8d);
addbyte(0x34);
addbyte(0x08);
addbyte(0x67); /*LEA EDI, 1[ESI]*/
addbyte(0x8d);
addbyte(0x7e);
addbyte(0x01);
addbyte(0x89); /*MOV EDI, ESI*/
addbyte(0xf7);
addbyte(0xc1); /*SHR ESI, 12*/
addbyte(0xe8 | REG_ESI);
addbyte(12);
addbyte(0xf7); /*TEST EDI, 0xfff*/
addbyte(0xf7); /*TEST EDI, 1*/
addbyte(0xc7);
addlong(0xfff);
addlong(1);
if (IS_32_ADDR(writelookup2))
{
addbyte(0x67); /*MOV RSI, writelookup2[ESI*8]*/
@@ -1436,29 +1462,27 @@ static void MEM_STORE_ADDR_EA_W(x86seg *seg, int host_reg)
addbyte(0x34);
addbyte(0xf2);
}
addbyte(0x74); /*JE slowpath*/
addbyte(3+2+((host_reg & 8) ? 6:5)+2);
addbyte(0x75); /*JNE slowpath*/
addbyte(3+2+((host_reg & 8) ? 5:4)+2);
addbyte(0x83); /*CMP ESI, -1*/
addbyte(0xf8 | REG_ESI);
addbyte(-1);
addbyte(0x74); /*JE slowpath*/
addbyte(((host_reg & 8) ? 6:5)+2);
addbyte(((host_reg & 8) ? 5:4)+2);
if (host_reg & 8)
{
addbyte(0x66); /*MOV -1[RDI+RSI],host_reg*/
addbyte(0x66); /*MOV [RDI+RSI],host_reg*/
addbyte(0x44);
addbyte(0x89);
addbyte(0x44 | ((host_reg & 7) << 3));
addbyte(0x04 | ((host_reg & 7) << 3));
addbyte(REG_EDI | (REG_ESI << 3));
addbyte(-1);
}
else
{
addbyte(0x66); /*MOV -1[RDI+RSI],host_reg*/
addbyte(0x66); /*MOV [RDI+RSI],host_reg*/
addbyte(0x89);
addbyte(0x44 | (host_reg << 3));
addbyte(0x04 | (host_reg << 3));
addbyte(REG_EDI | (REG_ESI << 3));
addbyte(-1);
}
addbyte(0xeb); /*JMP done*/
addbyte(2+2+3+12+4+6);
@@ -1478,7 +1502,12 @@ static void MEM_STORE_ADDR_EA_W(x86seg *seg, int host_reg)
}
static void MEM_STORE_ADDR_EA_L(x86seg *seg, int host_reg)
{
if (IS_32_ADDR(&seg->base))
if ((seg == &_ds && codegen_flat_ds) || (seg == &_ss && codegen_flat_ss))
{
addbyte(0x31); /*XOR ECX, ECX*/
addbyte(0xc9);
}
else if (IS_32_ADDR(&seg->base))
{
addbyte(0x8b); /*MOVL ECX, seg->base*/
addbyte(0x0c);
@@ -1497,16 +1526,14 @@ static void MEM_STORE_ADDR_EA_L(x86seg *seg, int host_reg)
addbyte(0x8d);
addbyte(0x34);
addbyte(0x08);
addbyte(0x67); /*LEA EDI, 3[ESI]*/
addbyte(0x8d);
addbyte(0x7e);
addbyte(0x03);
addbyte(0x89); /*MOV EDI, ESI*/
addbyte(0xf7);
addbyte(0xc1); /*SHR ESI, 12*/
addbyte(0xe8 | REG_ESI);
addbyte(12);
addbyte(0xf7); /*TEST EDI, 0xffc*/
addbyte(0xf7); /*TEST EDI, 3*/
addbyte(0xc7);
addlong(0xffc);
addlong(3);
if (IS_32_ADDR(writelookup2))
{
addbyte(0x67); /*MOV RSI, writelookup2[ESI*8]*/
@@ -1526,27 +1553,25 @@ static void MEM_STORE_ADDR_EA_L(x86seg *seg, int host_reg)
addbyte(0x34);
addbyte(0xf2);
}
addbyte(0x74); /*JE slowpath*/
addbyte(3+2+((host_reg & 8) ? 5:4)+2);
addbyte(0x75); /*JNE slowpath*/
addbyte(3+2+((host_reg & 8) ? 4:3)+2);
addbyte(0x83); /*CMP ESI, -1*/
addbyte(0xf8 | REG_ESI);
addbyte(-1);
addbyte(0x74); /*JE slowpath*/
addbyte(((host_reg & 8) ? 5:4)+2);
addbyte(((host_reg & 8) ? 4:3)+2);
if (host_reg & 8)
{
addbyte(0x44); /*MOV -3[RDI+RSI],host_reg*/
addbyte(0x89);
addbyte(0x44 | ((host_reg & 7) << 3));
addbyte(0x04 | ((host_reg & 7) << 3));
addbyte(REG_EDI | (REG_ESI << 3));
addbyte(-3);
}
else
{
addbyte(0x89); /*MOV -3[RDI+RSI],host_reg*/
addbyte(0x44 | (host_reg << 3));
addbyte(0x04 | (host_reg << 3));
addbyte(REG_EDI | (REG_ESI << 3));
addbyte(-3);
}
addbyte(0xeb); /*JMP done*/
addbyte(2+2+3+12+4+6);
@@ -1566,7 +1591,12 @@ static void MEM_STORE_ADDR_EA_L(x86seg *seg, int host_reg)
}
static void MEM_STORE_ADDR_EA_Q(x86seg *seg, int host_reg, int host_reg2)
{
if (IS_32_ADDR(&seg->base))
if ((seg == &_ds && codegen_flat_ds) || (seg == &_ss && codegen_flat_ss))
{
addbyte(0x31); /*XOR ECX, ECX*/
addbyte(0xc9);
}
else if (IS_32_ADDR(&seg->base))
{
addbyte(0x8b); /*MOVL ECX, seg->base*/
addbyte(0x0c);
@@ -1585,16 +1615,14 @@ static void MEM_STORE_ADDR_EA_Q(x86seg *seg, int host_reg, int host_reg2)
addbyte(0x8d);
addbyte(0x34);
addbyte(0x08);
addbyte(0x67); /*LEA EDI, 7[ESI]*/
addbyte(0x8d);
addbyte(0x7e);
addbyte(0x07);
addbyte(0x89); /*MOV EDI, ESI*/
addbyte(0xf7);
addbyte(0xc1); /*SHR ESI, 12*/
addbyte(0xe8 | REG_ESI);
addbyte(12);
addbyte(0xf7); /*TEST EDI, 0xff8*/
addbyte(0xf7); /*TEST EDI, 7*/
addbyte(0xc7);
addlong(0xff8);
addlong(7);
if (IS_32_ADDR(writelookup2))
{
addbyte(0x67); /*MOV RSI, writelookup2[ESI*8]*/
@@ -1614,28 +1642,26 @@ static void MEM_STORE_ADDR_EA_Q(x86seg *seg, int host_reg, int host_reg2)
addbyte(0x34);
addbyte(0xf2);
}
addbyte(0x74); /*JE slowpath*/
addbyte(3+2+5+2);
addbyte(0x75); /*JNE slowpath*/
addbyte(3+2+4+2);
addbyte(0x83); /*CMP ESI, -1*/
addbyte(0xf8 | REG_ESI);
addbyte(-1);
addbyte(0x74); /*JE slowpath*/
addbyte(5+2);
addbyte(4+2);
if (host_reg & 8)
{
addbyte(0x4c); /*MOV -7[RDI+RSI],host_reg*/
addbyte(0x4c); /*MOV [RDI+RSI],host_reg*/
addbyte(0x89);
addbyte(0x44 | ((host_reg & 7) << 3));
addbyte(0x04 | ((host_reg & 7) << 3));
addbyte(REG_EDI | (REG_ESI << 3));
addbyte(-7);
}
else
{
addbyte(0x48); /*MOV -3[RDI+RSI],host_reg*/
addbyte(0x48); /*MOV [RDI+RSI],host_reg*/
addbyte(0x89);
addbyte(0x44 | (host_reg << 3));
addbyte(0x04 | (host_reg << 3));
addbyte(REG_EDI | (REG_ESI << 3));
addbyte(-7);
}
addbyte(0xeb); /*JMP done*/
addbyte(2+2+3+12+4+6);
@@ -5252,7 +5278,12 @@ static void MEM_CHECK_WRITE(x86seg *seg)
CHECK_SEG_WRITE(seg);
if (IS_32_ADDR(&seg->base))
if ((seg == &_ds && codegen_flat_ds) || (seg == &_ss && codegen_flat_ss))
{
addbyte(0x31); /*XOR ESI, ESI*/
addbyte(0xf6);
}
else if (IS_32_ADDR(&seg->base))
{
addbyte(0x8b); /*MOV ESI, seg->base*/
addbyte(0x34);
@@ -5299,12 +5330,15 @@ static void MEM_CHECK_WRITE(x86seg *seg)
addbyte(0xc1); /*SHR EDI, 12*/
addbyte(0xef);
addbyte(12);
addbyte(0x83); /*CMP ESI, -1*/
addbyte(0xfe);
addbyte(-1);
addbyte(0x74); /*JE slowpath*/
jump3 = &codeblock[block_current].data[block_pos];
addbyte(0);
if (!(seg == &_ds && codegen_flat_ds) && !(seg == &_ss && codegen_flat_ss))
{
addbyte(0x83); /*CMP ESI, -1*/
addbyte(0xfe);
addbyte(-1);
addbyte(0x74); /*JE slowpath*/
jump3 = &codeblock[block_current].data[block_pos];
addbyte(0);
}
if (IS_32_ADDR(writelookup2))
{
addbyte(0x83); /*CMP writelookup2[RDI*8],-1*/
@@ -5328,7 +5362,8 @@ static void MEM_CHECK_WRITE(x86seg *seg)
addbyte(0);
// addbyte(0xc3); /*RET*/
*jump3 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump3 - 1;
if (!(seg == &_ds && codegen_flat_ds) && !(seg == &_ss && codegen_flat_ss))
*jump3 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump3 - 1;
/*slowpath:*/
addbyte(0x67); /*LEA EDI, [EAX+ESI]*/
addbyte(0x8d);
@@ -5373,7 +5408,12 @@ static void MEM_CHECK_WRITE_W(x86seg *seg)
CHECK_SEG_WRITE(seg);
if (IS_32_ADDR(&seg->base))
if ((seg == &_ds && codegen_flat_ds) || (seg == &_ss && codegen_flat_ss))
{
addbyte(0x31); /*XOR ESI, ESI*/
addbyte(0xf6);
}
else if (IS_32_ADDR(&seg->base))
{
addbyte(0x8b); /*MOV ESI, seg->base*/
addbyte(0x34);
@@ -5416,15 +5456,21 @@ static void MEM_CHECK_WRITE_W(x86seg *seg)
addbyte(0x79); /*JNS +*/
jump1 = &codeblock[block_current].data[block_pos];
addbyte(0);
addbyte(0x83); /*CMP ESI, -1*/
addbyte(0xfe);
addbyte(-1);
if (!(seg == &_ds && codegen_flat_ds) && !(seg == &_ss && codegen_flat_ss))
{
addbyte(0x83); /*CMP ESI, -1*/
addbyte(0xfe);
addbyte(-1);
}
addbyte(0x8d); /*LEA ESI, 1[EDI]*/
addbyte(0x77);
addbyte(0x01);
addbyte(0x74); /*JE slowpath*/
jump4 = &codeblock[block_current].data[block_pos];
addbyte(0);
if (!(seg == &_ds && codegen_flat_ds) && !(seg == &_ss && codegen_flat_ss))
{
addbyte(0x74); /*JE slowpath*/
jump4 = &codeblock[block_current].data[block_pos];
addbyte(0);
}
addbyte(0x89); /*MOV EBX, EDI*/
addbyte(0xfb);
addbyte(0xc1); /*SHR EDI, 12*/
@@ -5475,7 +5521,8 @@ static void MEM_CHECK_WRITE_W(x86seg *seg)
/*slowpath:*/
*jump2 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump2 - 1;
*jump4 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump4 - 1;
if (!(seg == &_ds && codegen_flat_ds) && !(seg == &_ss && codegen_flat_ss))
*jump4 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump4 - 1;
jump_pos = block_pos;
load_param_1_reg_32(REG_EBX);
load_param_2_32(&codeblock[block_current], 1);
@@ -5510,7 +5557,12 @@ static void MEM_CHECK_WRITE_L(x86seg *seg)
CHECK_SEG_WRITE(seg);
if (IS_32_ADDR(&seg->base))
if ((seg == &_ds && codegen_flat_ds) || (seg == &_ss && codegen_flat_ss))
{
addbyte(0x31); /*XOR ESI, ESI*/
addbyte(0xf6);
}
else if (IS_32_ADDR(&seg->base))
{
addbyte(0x8b); /*MOV ESI, seg->base*/
addbyte(0x34);
@@ -5553,15 +5605,21 @@ static void MEM_CHECK_WRITE_L(x86seg *seg)
addbyte(0x79); /*JNS +*/
jump1 = &codeblock[block_current].data[block_pos];
addbyte(0);
addbyte(0x83); /*CMP ESI, -1*/
addbyte(0xfe);
addbyte(-1);
if (!(seg == &_ds && codegen_flat_ds) && !(seg == &_ss && codegen_flat_ss))
{
addbyte(0x83); /*CMP ESI, -1*/
addbyte(0xfe);
addbyte(-1);
}
addbyte(0x8d); /*LEA ESI, 3[EDI]*/
addbyte(0x77);
addbyte(0x03);
addbyte(0x74); /*JE slowpath*/
jump4 = &codeblock[block_current].data[block_pos];
addbyte(0);
if (!(seg == &_ds && codegen_flat_ds) && !(seg == &_ss && codegen_flat_ss))
{
addbyte(0x74); /*JE slowpath*/
jump4 = &codeblock[block_current].data[block_pos];
addbyte(0);
}
addbyte(0x89); /*MOV EBX, EDI*/
addbyte(0xfb);
addbyte(0xc1); /*SHR EDI, 12*/
@@ -5612,7 +5670,8 @@ static void MEM_CHECK_WRITE_L(x86seg *seg)
/*slowpath:*/
*jump2 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump2 - 1;
*jump4 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump4 - 1;
if (!(seg == &_ds && codegen_flat_ds) && !(seg == &_ss && codegen_flat_ss))
*jump4 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump4 - 1;
jump_pos = block_pos;
load_param_1_reg_32(REG_EBX);
load_param_2_32(&codeblock[block_current], 1);
@@ -5642,7 +5701,12 @@ static void MEM_CHECK_WRITE_L(x86seg *seg)
static int MEM_LOAD_ADDR_EA_B_NO_ABRT(x86seg *seg)
{
if (IS_32_ADDR(&seg->base))
if ((seg == &_ds && codegen_flat_ds) || (seg == &_ss && codegen_flat_ss))
{
addbyte(0x31); /*XOR ECX, ECX*/
addbyte(0xc9);
}
else if (IS_32_ADDR(&seg->base))
{
addbyte(0x8b); /*MOVL ECX, seg->base*/
addbyte(0x0c);
@@ -5709,7 +5773,12 @@ static int MEM_LOAD_ADDR_EA_B_NO_ABRT(x86seg *seg)
}
static int MEM_LOAD_ADDR_EA_W_NO_ABRT(x86seg *seg)
{
if (IS_32_ADDR(&seg->base))
if ((seg == &_ds && codegen_flat_ds) || (seg == &_ss && codegen_flat_ss))
{
addbyte(0x31); /*XOR ECX, ECX*/
addbyte(0xc9);
}
else if (IS_32_ADDR(&seg->base))
{
addbyte(0x8b); /*MOVL ECX, seg->base*/
addbyte(0x0c);
@@ -5728,16 +5797,14 @@ static int MEM_LOAD_ADDR_EA_W_NO_ABRT(x86seg *seg)
addbyte(0x8d);
addbyte(0x34);
addbyte(0x08);
addbyte(0x67); /*LEA EDI, 1[ESI]*/
addbyte(0x8d);
addbyte(0x7e);
addbyte(0x01);
addbyte(0x89); /*MOV EDI, ESI*/
addbyte(0xf7);
addbyte(0xc1); /*SHR ESI, 12*/
addbyte(0xe8 | REG_ESI);
addbyte(12);
addbyte(0xf7); /*TEST EDI, 0xfff*/
addbyte(0xf7); /*TEST EDI, 1*/
addbyte(0xc7);
addlong(0xfff);
addlong(1);
if (IS_32_ADDR(readlookup2))
{
addbyte(0x67); /*MOV RSI, readlookup2[ESI*8]*/
@@ -5757,18 +5824,17 @@ static int MEM_LOAD_ADDR_EA_W_NO_ABRT(x86seg *seg)
addbyte(0x34);
addbyte(0xf2);
}
addbyte(0x74); /*JE slowpath*/
addbyte(3+2+5+2);
addbyte(0x75); /*JE slowpath*/
addbyte(3+2+4+2);
addbyte(0x83); /*CMP ESI, -1*/
addbyte(0xf8 | REG_ESI);
addbyte(-1);
addbyte(0x74); /*JE slowpath*/
addbyte(5+2);
addbyte(0x66); /*MOV AX,-1[RDI+RSI]*/
addbyte(4+2);
addbyte(0x66); /*MOV AX,[RDI+RSI]*/
addbyte(0x8b);
addbyte(0x44);
addbyte(0x04);
addbyte(REG_EDI | (REG_ESI << 3));
addbyte(-1);
addbyte(0xeb); /*JMP done*/
addbyte(2+2+12);
/*slowpath:*/
@@ -5785,7 +5851,12 @@ static int MEM_LOAD_ADDR_EA_W_NO_ABRT(x86seg *seg)
}
static int MEM_LOAD_ADDR_EA_L_NO_ABRT(x86seg *seg)
{
if (IS_32_ADDR(&seg->base))
if ((seg == &_ds && codegen_flat_ds) || (seg == &_ss && codegen_flat_ss))
{
addbyte(0x31); /*XOR ECX, ECX*/
addbyte(0xc9);
}
else if (IS_32_ADDR(&seg->base))
{
addbyte(0x8b); /*MOVL ECX, seg->base*/
addbyte(0x0c);
@@ -5804,16 +5875,14 @@ static int MEM_LOAD_ADDR_EA_L_NO_ABRT(x86seg *seg)
addbyte(0x8d);
addbyte(0x34);
addbyte(0x08);
addbyte(0x67); /*LEA EDI, 3[ESI]*/
addbyte(0x8d);
addbyte(0x7e);
addbyte(0x03);
addbyte(0x89); /*MOV EDI, ESI*/
addbyte(0xf7);
addbyte(0xc1); /*SHR ESI, 12*/
addbyte(0xe8 | REG_ESI);
addbyte(12);
addbyte(0xf7); /*TEST EDI, 0xffc*/
addbyte(0xf7); /*TEST EDI, 3*/
addbyte(0xc7);
addlong(0xffc);
addlong(3);
if (IS_32_ADDR(readlookup2))
{
addbyte(0x67); /*MOV RSI, readlookup2[ESI*8]*/
@@ -5833,17 +5902,16 @@ static int MEM_LOAD_ADDR_EA_L_NO_ABRT(x86seg *seg)
addbyte(0x34);
addbyte(0xf2);
}
addbyte(0x74); /*JE slowpath*/
addbyte(3+2+4+2);
addbyte(0x54); /*JNE slowpath*/
addbyte(3+2+3+2);
addbyte(0x83); /*CMP ESI, -1*/
addbyte(0xf8 | REG_ESI);
addbyte(-1);
addbyte(0x74); /*JE slowpath*/
addbyte(4+2);
addbyte(3+2);
addbyte(0x8b); /*MOV EAX,-3[RDI+RSI]*/
addbyte(0x44);
addbyte(0x04);
addbyte(REG_EDI | (REG_ESI << 3));
addbyte(-3);
addbyte(0xeb); /*JMP done*/
addbyte(2+2+12);
/*slowpath:*/
@@ -5883,7 +5951,13 @@ static void MEM_STORE_ADDR_EA_B_NO_ABRT(x86seg *seg, int host_reg)
addbyte(8);
host_reg = 8;
}
if (IS_32_ADDR(&seg->base))
if (((seg == &_ds) && (cpu_cur_status & CPU_STATUS_FLATDS)) ||
((seg == &_ss) && (cpu_cur_status & CPU_STATUS_FLATSS)))
{
addbyte(0x31); /*XOR EBX, EBX*/
addbyte(0xdb);
}
else if (IS_32_ADDR(&seg->base))
{
addbyte(0x8b); /*MOVL EBX, seg->base*/
addbyte(0x1c);
@@ -5955,7 +6029,13 @@ static void MEM_STORE_ADDR_EA_B_NO_ABRT(x86seg *seg, int host_reg)
}
static void MEM_STORE_ADDR_EA_W_NO_ABRT(x86seg *seg, int host_reg)
{
if (IS_32_ADDR(&seg->base))
if (((seg == &_ds) && (cpu_cur_status & CPU_STATUS_FLATDS)) ||
((seg == &_ss) && (cpu_cur_status & CPU_STATUS_FLATSS)))
{
addbyte(0x31); /*XOR EBX, EBX*/
addbyte(0xdb);
}
else if (IS_32_ADDR(&seg->base))
{
addbyte(0x8b); /*MOVL EBX, seg->base*/
addbyte(0x1c);
@@ -5974,16 +6054,14 @@ static void MEM_STORE_ADDR_EA_W_NO_ABRT(x86seg *seg, int host_reg)
addbyte(0x8d);
addbyte(0x34);
addbyte(0x18);
addbyte(0x67); /*LEA EDI, 1[ESI]*/
addbyte(0x8d);
addbyte(0x7e);
addbyte(0x01);
addbyte(0x89); /*MOV EDI, ESI*/
addbyte(0xf7);
addbyte(0xc1); /*SHR ESI, 12*/
addbyte(0xe8 | REG_ESI);
addbyte(12);
addbyte(0xf7); /*TEST EDI, 0xfff*/
addbyte(0xf7); /*TEST EDI, 1*/
addbyte(0xc7);
addlong(0xfff);
addlong(1);
if (IS_32_ADDR(writelookup2))
{
addbyte(0x67); /*MOV RSI, writelookup2[ESI*8]*/
@@ -6003,29 +6081,27 @@ static void MEM_STORE_ADDR_EA_W_NO_ABRT(x86seg *seg, int host_reg)
addbyte(0x34);
addbyte(0xf2);
}
addbyte(0x74); /*JE slowpath*/
addbyte(3+2+((host_reg & 8) ? 6:5)+2);
addbyte(0x75); /*JNE slowpath*/
addbyte(3+2+((host_reg & 8) ? 5:4)+2);
addbyte(0x83); /*CMP ESI, -1*/
addbyte(0xf8 | REG_ESI);
addbyte(-1);
addbyte(0x74); /*JE slowpath*/
addbyte(((host_reg & 8) ? 6:5)+2);
addbyte(((host_reg & 8) ? 5:4)+2);
if (host_reg & 8)
{
addbyte(0x66); /*MOV -1[RDI+RSI],host_reg*/
addbyte(0x66); /*MOV [RDI+RSI],host_reg*/
addbyte(0x44);
addbyte(0x89);
addbyte(0x44 | ((host_reg & 7) << 3));
addbyte(0x04 | ((host_reg & 7) << 3));
addbyte(REG_EDI | (REG_ESI << 3));
addbyte(-1);
}
else
{
addbyte(0x66); /*MOV -1[RDI+RSI],host_reg*/
addbyte(0x66); /*MOV [RDI+RSI],host_reg*/
addbyte(0x89);
addbyte(0x44 | (host_reg << 3));
addbyte(0x04 | (host_reg << 3));
addbyte(REG_EDI | (REG_ESI << 3));
addbyte(-1);
}
addbyte(0xeb); /*JMP done*/
addbyte(2+2+3+12);
@@ -6038,7 +6114,13 @@ static void MEM_STORE_ADDR_EA_W_NO_ABRT(x86seg *seg, int host_reg)
}
static void MEM_STORE_ADDR_EA_L_NO_ABRT(x86seg *seg, int host_reg)
{
if (IS_32_ADDR(&seg->base))
if (((seg == &_ds) && (cpu_cur_status & CPU_STATUS_FLATDS)) ||
((seg == &_ss) && (cpu_cur_status & CPU_STATUS_FLATSS)))
{
addbyte(0x31); /*XOR EBX, EBX*/
addbyte(0xdb);
}
else if (IS_32_ADDR(&seg->base))
{
addbyte(0x8b); /*MOVL EBX, seg->base*/
addbyte(0x1c);
@@ -6057,16 +6139,14 @@ static void MEM_STORE_ADDR_EA_L_NO_ABRT(x86seg *seg, int host_reg)
addbyte(0x8d);
addbyte(0x34);
addbyte(0x18);
addbyte(0x67); /*LEA EDI, 3[ESI]*/
addbyte(0x8d);
addbyte(0x7e);
addbyte(0x03);
addbyte(0x89); /*MOV EDI, ESI*/
addbyte(0xf7);
addbyte(0xc1); /*SHR ESI, 12*/
addbyte(0xe8 | REG_ESI);
addbyte(12);
addbyte(0xf7); /*TEST EDI, 0xffc*/
addbyte(0xf7); /*TEST EDI, 3*/
addbyte(0xc7);
addlong(0xffc);
addlong(3);
if (IS_32_ADDR(writelookup2))
{
addbyte(0x67); /*MOV RSI, writelookup2[ESI*8]*/
@@ -6086,27 +6166,25 @@ static void MEM_STORE_ADDR_EA_L_NO_ABRT(x86seg *seg, int host_reg)
addbyte(0x34);
addbyte(0xf2);
}
addbyte(0x74); /*JE slowpath*/
addbyte(3+2+((host_reg & 8) ? 5:4)+2);
addbyte(0x75); /*JNE slowpath*/
addbyte(3+2+((host_reg & 8) ? 4:3)+2);
addbyte(0x83); /*CMP ESI, -1*/
addbyte(0xf8 | REG_ESI);
addbyte(-1);
addbyte(0x74); /*JE slowpath*/
addbyte(((host_reg & 8) ? 5:4)+2);
addbyte(((host_reg & 8) ? 4:3)+2);
if (host_reg & 8)
{
addbyte(0x44); /*MOV -3[RDI+RSI],host_reg*/
addbyte(0x44); /*MOV [RDI+RSI],host_reg*/
addbyte(0x89);
addbyte(0x44 | ((host_reg & 7) << 3));
addbyte(0x04 | ((host_reg & 7) << 3));
addbyte(REG_EDI | (REG_ESI << 3));
addbyte(-3);
}
else
{
addbyte(0x89); /*MOV -3[RDI+RSI],host_reg*/
addbyte(0x44 | (host_reg << 3));
addbyte(0x89); /*MOV [RDI+RSI],host_reg*/
addbyte(0x04 | (host_reg << 3));
addbyte(REG_EDI | (REG_ESI << 3));
addbyte(-3);
}
addbyte(0xeb); /*JMP done*/
addbyte(2+2+3+12);

View File

@@ -616,6 +616,8 @@ static void CHECK_SEG_READ(x86seg *seg)
return;
if (seg->checked)
return;
if (seg == &_ds && codegen_flat_ds)
return;
addbyte(0x83); /*CMP seg->base, -1*/
addbyte(0x05|0x38);
@@ -637,6 +639,8 @@ static void CHECK_SEG_WRITE(x86seg *seg)
return;
if (seg->checked)
return;
if (seg == &_ds && codegen_flat_ds)
return;
addbyte(0x83); /*CMP seg->base, -1*/
addbyte(0x05|0x38);
@@ -650,6 +654,9 @@ static void CHECK_SEG_WRITE(x86seg *seg)
}
static void CHECK_SEG_LIMITS(x86seg *seg, int end_offset)
{
if ((seg == &_ds && codegen_flat_ds) || (seg == &_ss && codegen_flat_ss))
return;
addbyte(0x3b); /*CMP EAX, seg->limit_low*/
addbyte(0x05);
addlong((uint32_t)&seg->limit_low);
@@ -675,9 +682,18 @@ static void CHECK_SEG_LIMITS(x86seg *seg, int end_offset)
static void MEM_LOAD_ADDR_EA_B(x86seg *seg)
{
addbyte(0x8b); /*MOVL EDX, seg->base*/
addbyte(0x05 | (REG_EDX << 3));
addlong((uint32_t)&seg->base);
if (((seg == &_ds) && (cpu_cur_status & CPU_STATUS_FLATDS)) ||
((seg == &_ss) && (cpu_cur_status & CPU_STATUS_FLATSS)))
{
addbyte(0x31); /*XOR EDX, EDX*/
addbyte(0xd2);
}
else
{
addbyte(0x8b); /*MOVL EDX, seg->base*/
addbyte(0x05 | (REG_EDX << 3));
addlong((uint32_t)&seg->base);
}
addbyte(0xe8); /*CALL mem_load_addr_ea_b*/
addlong(mem_load_addr_ea_b - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
@@ -685,9 +701,17 @@ static void MEM_LOAD_ADDR_EA_B(x86seg *seg)
}
static int MEM_LOAD_ADDR_EA_B_NO_ABRT(x86seg *seg)
{
addbyte(0x8b); /*MOVL EDX, seg->base*/
addbyte(0x05 | (REG_EDX << 3));
addlong((uint32_t)&seg->base);
if ((seg == &_ds && codegen_flat_ds) || (seg == &_ss && codegen_flat_ss))
{
addbyte(0x31); /*XOR EDX, EDX*/
addbyte(0xd2);
}
else
{
addbyte(0x8b); /*MOVL EDX, seg->base*/
addbyte(0x05 | (REG_EDX << 3));
addlong((uint32_t)&seg->base);
}
addbyte(0xe8); /*CALL mem_load_addr_ea_b_no_abrt*/
addlong(mem_load_addr_ea_b_no_abrt - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
@@ -697,9 +721,17 @@ static int MEM_LOAD_ADDR_EA_B_NO_ABRT(x86seg *seg)
}
static void MEM_LOAD_ADDR_EA_W(x86seg *seg)
{
addbyte(0x8b); /*MOVL EDX, seg->base*/
addbyte(0x05 | (REG_EDX << 3));
addlong((uint32_t)&seg->base);
if ((seg == &_ds && codegen_flat_ds) || (seg == &_ss && codegen_flat_ss))
{
addbyte(0x31); /*XOR EDX, EDX*/
addbyte(0xd2);
}
else
{
addbyte(0x8b); /*MOVL EDX, seg->base*/
addbyte(0x05 | (REG_EDX << 3));
addlong((uint32_t)&seg->base);
}
addbyte(0xe8); /*CALL mem_load_addr_ea_w*/
addlong(mem_load_addr_ea_w - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
@@ -707,9 +739,17 @@ static void MEM_LOAD_ADDR_EA_W(x86seg *seg)
}
static void MEM_LOAD_ADDR_EA_W_OFFSET(x86seg *seg, int offset)
{
addbyte(0x8b); /*MOVL EDX, seg->base*/
addbyte(0x05 | (REG_EDX << 3));
addlong((uint32_t)&seg->base);
if ((seg == &_ds && codegen_flat_ds) || (seg == &_ss && codegen_flat_ss))
{
addbyte(0x31); /*XOR EDX, EDX*/
addbyte(0xd2);
}
else
{
addbyte(0x8b); /*MOVL EDX, seg->base*/
addbyte(0x05 | (REG_EDX << 3));
addlong((uint32_t)&seg->base);
}
addbyte(0x83); /*ADD EAX, offset*/
addbyte(0xc0);
addbyte(offset);
@@ -720,9 +760,17 @@ static void MEM_LOAD_ADDR_EA_W_OFFSET(x86seg *seg, int offset)
}
static int MEM_LOAD_ADDR_EA_W_NO_ABRT(x86seg *seg)
{
addbyte(0x8b); /*MOVL EDX, seg->base*/
addbyte(0x05 | (REG_EDX << 3));
addlong((uint32_t)&seg->base);
if ((seg == &_ds && codegen_flat_ds) || (seg == &_ss && codegen_flat_ss))
{
addbyte(0x31); /*XOR EDX, EDX*/
addbyte(0xd2);
}
else
{
addbyte(0x8b); /*MOVL EDX, seg->base*/
addbyte(0x05 | (REG_EDX << 3));
addlong((uint32_t)&seg->base);
}
addbyte(0xe8); /*CALL mem_load_addr_ea_w_no_abrt*/
addlong(mem_load_addr_ea_w_no_abrt - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
@@ -732,9 +780,17 @@ static int MEM_LOAD_ADDR_EA_W_NO_ABRT(x86seg *seg)
}
static void MEM_LOAD_ADDR_EA_L(x86seg *seg)
{
addbyte(0x8b); /*MOVL EDX, seg->base*/
addbyte(0x05 | (REG_EDX << 3));
addlong((uint32_t)&seg->base);
if ((seg == &_ds && codegen_flat_ds) || (seg == &_ss && codegen_flat_ss))
{
addbyte(0x31); /*XOR EDX, EDX*/
addbyte(0xd2);
}
else
{
addbyte(0x8b); /*MOVL EDX, seg->base*/
addbyte(0x05 | (REG_EDX << 3));
addlong((uint32_t)&seg->base);
}
addbyte(0xe8); /*CALL mem_load_addr_ea_l*/
addlong(mem_load_addr_ea_l - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
@@ -743,9 +799,17 @@ static void MEM_LOAD_ADDR_EA_L(x86seg *seg)
}
static int MEM_LOAD_ADDR_EA_L_NO_ABRT(x86seg *seg)
{
addbyte(0x8b); /*MOVL EDX, seg->base*/
addbyte(0x05 | (REG_EDX << 3));
addlong((uint32_t)&seg->base);
if ((seg == &_ds && codegen_flat_ds) || (seg == &_ss && codegen_flat_ss))
{
addbyte(0x31); /*XOR EDX, EDX*/
addbyte(0xd2);
}
else
{
addbyte(0x8b); /*MOVL EDX, seg->base*/
addbyte(0x05 | (REG_EDX << 3));
addlong((uint32_t)&seg->base);
}
addbyte(0xe8); /*CALL mem_load_addr_ea_l_no_abrt*/
addlong(mem_load_addr_ea_l_no_abrt - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
@@ -756,9 +820,17 @@ static int MEM_LOAD_ADDR_EA_L_NO_ABRT(x86seg *seg)
static void MEM_LOAD_ADDR_EA_Q(x86seg *seg)
{
addbyte(0x8b); /*MOVL EDX, seg->base*/
addbyte(0x05 | (REG_EDX << 3));
addlong((uint32_t)&seg->base);
if ((seg == &_ds && codegen_flat_ds) || (seg == &_ss && codegen_flat_ss))
{
addbyte(0x31); /*XOR EDX, EDX*/
addbyte(0xd2);
}
else
{
addbyte(0x8b); /*MOVL EDX, seg->base*/
addbyte(0x05 | (REG_EDX << 3));
addlong((uint32_t)&seg->base);
}
addbyte(0xe8); /*CALL mem_load_addr_ea_q*/
addlong(mem_load_addr_ea_q - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
@@ -786,9 +858,17 @@ static void MEM_LOAD_ADDR_IMM_L(x86seg *seg, uint32_t addr)
static void MEM_STORE_ADDR_EA_B(x86seg *seg, int host_reg)
{
addbyte(0x8b); /*MOVL ESI, seg->base*/
addbyte(0x05 | (REG_ESI << 3));
addlong((uint32_t)&seg->base);
if ((seg == &_ds && codegen_flat_ds) || (seg == &_ss && codegen_flat_ss))
{
addbyte(0x31); /*XOR ESI, ESI*/
addbyte(0xf6);
}
else
{
addbyte(0x8b); /*MOVL ESI, seg->base*/
addbyte(0x05 | (REG_ESI << 3));
addlong((uint32_t)&seg->base);
}
if (host_reg != REG_ECX)
{
addbyte(0x89); /*MOV ECX, host_reg*/
@@ -799,9 +879,17 @@ static void MEM_STORE_ADDR_EA_B(x86seg *seg, int host_reg)
}
static void MEM_STORE_ADDR_EA_B_NO_ABRT(x86seg *seg, int host_reg)
{
addbyte(0x8b); /*MOVL ESI, seg->base*/
addbyte(0x05 | (REG_ESI << 3));
addlong((uint32_t)&seg->base);
if ((seg == &_ds && codegen_flat_ds) || (seg == &_ss && codegen_flat_ss))
{
addbyte(0x31); /*XOR ESI, ESI*/
addbyte(0xf6);
}
else
{
addbyte(0x8b); /*MOVL ESI, seg->base*/
addbyte(0x05 | (REG_ESI << 3));
addlong((uint32_t)&seg->base);
}
if (host_reg != REG_ECX)
{
addbyte(0x89); /*MOV ECX, host_reg*/
@@ -812,9 +900,17 @@ static void MEM_STORE_ADDR_EA_B_NO_ABRT(x86seg *seg, int host_reg)
}
static void MEM_STORE_ADDR_EA_W(x86seg *seg, int host_reg)
{
addbyte(0x8b); /*MOVL ESI, seg->base*/
addbyte(0x05 | (REG_ESI << 3));
addlong((uint32_t)&seg->base);
if ((seg == &_ds && codegen_flat_ds) || (seg == &_ss && codegen_flat_ss))
{
addbyte(0x31); /*XOR ESI, ESI*/
addbyte(0xf6);
}
else
{
addbyte(0x8b); /*MOVL ESI, seg->base*/
addbyte(0x05 | (REG_ESI << 3));
addlong((uint32_t)&seg->base);
}
if (host_reg != REG_ECX)
{
addbyte(0x89); /*MOV ECX, host_reg*/
@@ -825,9 +921,17 @@ static void MEM_STORE_ADDR_EA_W(x86seg *seg, int host_reg)
}
static void MEM_STORE_ADDR_EA_W_NO_ABRT(x86seg *seg, int host_reg)
{
addbyte(0x8b); /*MOVL ESI, seg->base*/
addbyte(0x05 | (REG_ESI << 3));
addlong((uint32_t)&seg->base);
if ((seg == &_ds && codegen_flat_ds) || (seg == &_ss && codegen_flat_ss))
{
addbyte(0x31); /*XOR ESI, ESI*/
addbyte(0xf6);
}
else
{
addbyte(0x8b); /*MOVL ESI, seg->base*/
addbyte(0x05 | (REG_ESI << 3));
addlong((uint32_t)&seg->base);
}
if (host_reg != REG_ECX)
{
addbyte(0x89); /*MOV ECX, host_reg*/
@@ -838,9 +942,17 @@ static void MEM_STORE_ADDR_EA_W_NO_ABRT(x86seg *seg, int host_reg)
}
static void MEM_STORE_ADDR_EA_L(x86seg *seg, int host_reg)
{
addbyte(0x8b); /*MOVL ESI, seg->base*/
addbyte(0x05 | (REG_ESI << 3));
addlong((uint32_t)&seg->base);
if ((seg == &_ds && codegen_flat_ds) || (seg == &_ss && codegen_flat_ss))
{
addbyte(0x31); /*XOR ESI, ESI*/
addbyte(0xf6);
}
else
{
addbyte(0x8b); /*MOVL ESI, seg->base*/
addbyte(0x05 | (REG_ESI << 3));
addlong((uint32_t)&seg->base);
}
if (host_reg != REG_ECX)
{
addbyte(0x89); /*MOV ECX, host_reg*/
@@ -851,9 +963,17 @@ static void MEM_STORE_ADDR_EA_L(x86seg *seg, int host_reg)
}
static void MEM_STORE_ADDR_EA_L_NO_ABRT(x86seg *seg, int host_reg)
{
addbyte(0x8b); /*MOVL ESI, seg->base*/
addbyte(0x05 | (REG_ESI << 3));
addlong((uint32_t)&seg->base);
if ((seg == &_ds && codegen_flat_ds) || (seg == &_ss && codegen_flat_ss))
{
addbyte(0x31); /*XOR ESI, ESI*/
addbyte(0xf6);
}
else
{
addbyte(0x8b); /*MOVL ESI, seg->base*/
addbyte(0x05 | (REG_ESI << 3));
addlong((uint32_t)&seg->base);
}
if (host_reg != REG_ECX)
{
addbyte(0x89); /*MOV ECX, host_reg*/
@@ -874,9 +994,17 @@ static void MEM_STORE_ADDR_EA_Q(x86seg *seg, int host_reg, int host_reg2)
addbyte(0x89); /*MOV ECX, host_reg2*/
addbyte(0xc0 | REG_ECX | (host_reg2 << 3));
}
addbyte(0x8b); /*MOVL ESI, seg->base*/
addbyte(0x05 | (REG_ESI << 3));
addlong((uint32_t)&seg->base);
if ((seg == &_ds && codegen_flat_ds) || (seg == &_ss && codegen_flat_ss))
{
addbyte(0x31); /*XOR ESI, ESI*/
addbyte(0xf6);
}
else
{
addbyte(0x8b); /*MOVL ESI, seg->base*/
addbyte(0x05 | (REG_ESI << 3));
addlong((uint32_t)&seg->base);
}
addbyte(0xe8); /*CALL mem_store_addr_ea_q*/
addlong(mem_store_addr_ea_q - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
}
@@ -3792,9 +3920,17 @@ static void LOAD_EA()
static void MEM_CHECK_WRITE(x86seg *seg)
{
CHECK_SEG_WRITE(seg);
addbyte(0x8b); /*MOVL ESI, seg->base*/
addbyte(0x05 | (REG_ESI << 3));
addlong((uint32_t)&seg->base);
if ((seg == &_ds && codegen_flat_ds) || (seg == &_ss && codegen_flat_ss))
{
addbyte(0x31); /*XOR ESI, ESI*/
addbyte(0xf6);
}
else
{
addbyte(0x8b); /*MOVL ESI, seg->base*/
addbyte(0x05 | (REG_ESI << 3));
addlong((uint32_t)&seg->base);
}
addbyte(0xe8); /*CALL mem_check_write*/
addlong(mem_check_write - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
LOAD_EA();
@@ -3802,9 +3938,17 @@ static void MEM_CHECK_WRITE(x86seg *seg)
static void MEM_CHECK_WRITE_W(x86seg *seg)
{
CHECK_SEG_WRITE(seg);
addbyte(0x8b); /*MOVL ESI, seg->base*/
addbyte(0x05 | (REG_ESI << 3));
addlong((uint32_t)&seg->base);
if ((seg == &_ds && codegen_flat_ds) || (seg == &_ss && codegen_flat_ss))
{
addbyte(0x31); /*XOR ESI, ESI*/
addbyte(0xf6);
}
else
{
addbyte(0x8b); /*MOVL ESI, seg->base*/
addbyte(0x05 | (REG_ESI << 3));
addlong((uint32_t)&seg->base);
}
addbyte(0xe8); /*CALL mem_check_write_w*/
addlong(mem_check_write_w - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
LOAD_EA();
@@ -3812,9 +3956,17 @@ static void MEM_CHECK_WRITE_W(x86seg *seg)
static void MEM_CHECK_WRITE_L(x86seg *seg)
{
CHECK_SEG_WRITE(seg);
addbyte(0x8b); /*MOVL ESI, seg->base*/
addbyte(0x05 | (REG_ESI << 3));
addlong((uint32_t)&seg->base);
if ((seg == &_ds && codegen_flat_ds) || (seg == &_ss && codegen_flat_ss))
{
addbyte(0x31); /*XOR ESI, ESI*/
addbyte(0xf6);
}
else
{
addbyte(0x8b); /*MOVL ESI, seg->base*/
addbyte(0x05 | (REG_ESI << 3));
addlong((uint32_t)&seg->base);
}
addbyte(0xe8); /*CALL mem_check_write_l*/
addlong(mem_check_write_l - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
LOAD_EA();

View File

@@ -22,6 +22,7 @@
#endif
int codegen_flat_ds, codegen_flat_ss;
int codegen_flags_changed = 0;
int codegen_fpu_entered = 0;
int codegen_fpu_loaded_iq[8];
@@ -274,13 +275,13 @@ void codegen_block_init(uint32_t phys_addr)
block->_cs = cs;
block->pnt = block_current;
block->phys = phys_addr;
block->use32 = use32;
block->stack32 = stack32;
block->next = block->prev = NULL;
block->next_2 = block->prev_2 = NULL;
block->page_mask = 0;
block->flags = 0;
block->status = cpu_cur_status;
block->was_recompiled = 0;
recomp_page = block->phys & ~0xfff;
@@ -386,6 +387,9 @@ void codegen_block_start_recompile(codeblock_t *block)
codegen_reg_loaded[4] = codegen_reg_loaded[5] = codegen_reg_loaded[6] = codegen_reg_loaded[7] = 0;
block->was_recompiled = 1;
codegen_flat_ds = cpu_cur_status & CPU_STATUS_FLATDS;
codegen_flat_ss = cpu_cur_status & CPU_STATUS_FLATSS;
}
void codegen_block_remove()

View File

@@ -22,6 +22,7 @@
#include <windows.h>
#endif
int codegen_flat_ds, codegen_flat_ss;
int mmx_ebx_ecx_loaded;
int codegen_flags_changed = 0;
int codegen_fpu_entered = 0;
@@ -135,31 +136,29 @@ static uint32_t gen_MEM_LOAD_ADDR_EA_W()
addbyte(0xd6);
addbyte(0x01); /*ADDL EDX, EAX*/
addbyte(0xc2);
addbyte(0x8d); /*LEA EDI, 1[EDX]*/
addbyte(0x7a);
addbyte(0x01);
addbyte(0x89); /*MOV EDI, EDX*/
addbyte(0xd7);
addbyte(0xc1); /*SHR EDX, 12*/
addbyte(0xea);
addbyte(12);
addbyte(0xf7); /*TEST EDI, 0xfff*/
addbyte(0xf7); /*TEST EDI, 1*/
addbyte(0xc7);
addlong(0xfff);
addlong(1);
addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/
addbyte(0x14);
addbyte(0x95);
addlong((uint32_t)readlookup2);
addbyte(0x74); /*JE slowpath*/
addbyte(3+2+5+1);
addbyte(0x75); /*JNE slowpath*/
addbyte(3+2+4+1);
addbyte(0x83); /*CMP EDX, -1*/
addbyte(0xfa);
addbyte(-1);
addbyte(0x74); /*JE slowpath*/
addbyte(5+1);
addbyte(0x0f); /*MOVZX EAX, -1[EDX+EDI]W*/
addbyte(4+1);
addbyte(0x0f); /*MOVZX EAX, [EDX+EDI]W*/
addbyte(0xb7);
addbyte(0x44);
addbyte(0x04);
addbyte(0x3a);
addbyte(-1);
addbyte(0xc3); /*RET*/
addbyte(0x50); /*slowpath: PUSH EAX*/
@@ -192,30 +191,28 @@ static uint32_t gen_MEM_LOAD_ADDR_EA_L()
addbyte(0xd6);
addbyte(0x01); /*ADDL EDX, EAX*/
addbyte(0xc2);
addbyte(0x8d); /*LEA EDI, 3[EDX]*/
addbyte(0x7a);
addbyte(0x03);
addbyte(0x89); /*MOV EDI, EDX*/
addbyte(0xd7);
addbyte(0xc1); /*SHR EDX, 12*/
addbyte(0xea);
addbyte(12);
addbyte(0xf7); /*TEST EDI, 0xffc*/
addbyte(0xf7); /*TEST EDI, 3*/
addbyte(0xc7);
addlong(0xffc);
addlong(3);
addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/
addbyte(0x14);
addbyte(0x95);
addlong((uint32_t)readlookup2);
addbyte(0x74); /*JE slowpath*/
addbyte(3+2+4+1);
addbyte(0x75); /*JNE slowpath*/
addbyte(3+2+3+1);
addbyte(0x83); /*CMP EDX, -1*/
addbyte(0xfa);
addbyte(-1);
addbyte(0x74); /*JE slowpath*/
addbyte(4+1);
addbyte(0x8b); /*MOV EAX, -3[EDX+EDI]*/
addbyte(0x44);
addbyte(3+1);
addbyte(0x8b); /*MOV EAX, [EDX+EDI]*/
addbyte(0x04);
addbyte(0x3a);
addbyte(-3);
addbyte(0xc3); /*RET*/
addbyte(0x50); /*slowpath: PUSH EAX*/
@@ -245,34 +242,32 @@ static uint32_t gen_MEM_LOAD_ADDR_EA_Q()
addbyte(0xd6);
addbyte(0x01); /*ADDL EDX, EAX*/
addbyte(0xc2);
addbyte(0x8d); /*LEA EDI, 7[EDX]*/
addbyte(0x7a);
addbyte(0x07);
addbyte(0x89); /*MOV EDI, EDX*/
addbyte(0xd7);
addbyte(0xc1); /*SHR EDX, 12*/
addbyte(0xea);
addbyte(12);
addbyte(0xf7); /*TEST EDI, 0xff8*/
addbyte(0xf7); /*TEST EDI, 7*/
addbyte(0xc7);
addlong(0xff8);
addlong(7);
addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/
addbyte(0x14);
addbyte(0x95);
addlong((uint32_t)readlookup2);
addbyte(0x74); /*JE slowpath*/
addbyte(3+2+4+4+1);
addbyte(0x75); /*JNE slowpath*/
addbyte(3+2+3+4+1);
addbyte(0x83); /*CMP EDX, -1*/
addbyte(0xfa);
addbyte(-1);
addbyte(0x74); /*JE slowpath*/
addbyte(4+4+1);
addbyte(3+4+1);
addbyte(0x8b); /*MOV EAX, [EDX+EDI]*/
addbyte(0x44);
addbyte(0x04);
addbyte(0x3a);
addbyte(-7);
addbyte(0x8b); /*MOV EDX, [EDX+EDI+4]*/
addbyte(0x54);
addbyte(0x3a);
addbyte(-7+4);
addbyte(4);
addbyte(0xc3); /*RET*/
addbyte(0x50); /*slowpath: PUSH EAX*/
@@ -351,31 +346,29 @@ static uint32_t gen_MEM_STORE_ADDR_EA_W()
addbyte(0xf3);
addbyte(0x01); /*ADDL ESI, EAX*/
addbyte(0xc0 | (REG_EAX << 3) | REG_ESI);
addbyte(0x8d); /*LEA EDI, 1[ESI]*/
addbyte(0x7e);
addbyte(0x01);
addbyte(0x89); /*MOV EDI, ESI*/
addbyte(0xf7);
addbyte(0xc1); /*SHR ESI, 12*/
addbyte(0xe8 | REG_ESI);
addbyte(12);
addbyte(0xf7); /*TEST EDI, 0xfff*/
addbyte(0xf7); /*TEST EDI, 1*/
addbyte(0xc7);
addlong(0xfff);
addlong(1);
addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/
addbyte(0x04 | (REG_ESI << 3));
addbyte(0x85 | (REG_ESI << 3));
addlong((uint32_t)writelookup2);
addbyte(0x74); /*JE slowpath*/
addbyte(3+2+5+1);
addbyte(0x75); /*JNE slowpath*/
addbyte(3+2+4+1);
addbyte(0x83); /*CMP ESI, -1*/
addbyte(0xf8 | REG_ESI);
addbyte(-1);
addbyte(0x74); /*JE slowpath*/
addbyte(5+1);
addbyte(0x66); /*MOV -1[EDI+ESI],CX*/
addbyte(4+1);
addbyte(0x66); /*MOV [EDI+ESI],CX*/
addbyte(0x89);
addbyte(0x44 | (REG_CX << 3));
addbyte(0x04 | (REG_CX << 3));
addbyte(REG_EDI | (REG_ESI << 3));
addbyte(-1);
addbyte(0xc3); /*RET*/
addbyte(0x51); /*slowpath: PUSH ECX*/
@@ -407,30 +400,28 @@ static uint32_t gen_MEM_STORE_ADDR_EA_L()
addbyte(0xf3);
addbyte(0x01); /*ADDL ESI, EAX*/
addbyte(0xc0 | (REG_EAX << 3) | REG_ESI);
addbyte(0x8d); /*LEA EDI, 3[ESI]*/
addbyte(0x7e);
addbyte(0x03);
addbyte(0x89); /*MOV EDI, ESI*/
addbyte(0xf7);
addbyte(0xc1); /*SHR ESI, 12*/
addbyte(0xe8 | REG_ESI);
addbyte(12);
addbyte(0xf7); /*TEST EDI, 0xffc*/
addbyte(0xf7); /*TEST EDI, 3*/
addbyte(0xc7);
addlong(0xffc);
addlong(3);
addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/
addbyte(0x04 | (REG_ESI << 3));
addbyte(0x85 | (REG_ESI << 3));
addlong((uint32_t)writelookup2);
addbyte(0x74); /*JE slowpath*/
addbyte(3+2+4+1);
addbyte(0x75); /*JNE slowpath*/
addbyte(3+2+3+1);
addbyte(0x83); /*CMP ESI, -1*/
addbyte(0xf8 | REG_ESI);
addbyte(-1);
addbyte(0x74); /*JE slowpath*/
addbyte(4+1);
addbyte(0x89); /*MOV -3[EDI+ESI],ECX*/
addbyte(0x44 | (REG_ECX << 3));
addbyte(3+1);
addbyte(0x89); /*MOV [EDI+ESI],ECX*/
addbyte(0x04 | (REG_ECX << 3));
addbyte(REG_EDI | (REG_ESI << 3));
addbyte(-3);
addbyte(0xc3); /*RET*/
addbyte(0x51); /*slowpath: PUSH ECX*/
@@ -462,34 +453,32 @@ static uint32_t gen_MEM_STORE_ADDR_EA_Q()
addbyte(0xf2);
addbyte(0x01); /*ADDL ESI, EAX*/
addbyte(0xc0 | (REG_EAX << 3) | REG_ESI);
addbyte(0x8d); /*LEA EDI, 7[ESI]*/
addbyte(0x7e);
addbyte(0x07);
addbyte(0x89); /*MOV EDI, ESI*/
addbyte(0xf7);
addbyte(0xc1); /*SHR ESI, 12*/
addbyte(0xe8 | REG_ESI);
addbyte(12);
addbyte(0xf7); /*TEST EDI, 0xff8*/
addbyte(0xf7); /*TEST EDI, 7*/
addbyte(0xc7);
addlong(0xff8);
addlong(7);
addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/
addbyte(0x04 | (REG_ESI << 3));
addbyte(0x85 | (REG_ESI << 3));
addlong((uint32_t)writelookup2);
addbyte(0x74); /*JE slowpath*/
addbyte(3+2+4+4+1);
addbyte(0x75); /*JNE slowpath*/
addbyte(3+2+3+4+1);
addbyte(0x83); /*CMP ESI, -1*/
addbyte(0xf8 | REG_ESI);
addbyte(-1);
addbyte(0x74); /*JE slowpath*/
addbyte(4+4+1);
addbyte(0x89); /*MOV -7[EDI+ESI],EBX*/
addbyte(0x44 | (REG_EBX << 3));
addbyte(3+4+1);
addbyte(0x89); /*MOV [EDI+ESI],EBX*/
addbyte(0x04 | (REG_EBX << 3));
addbyte(REG_EDI | (REG_ESI << 3));
addbyte(-7);
addbyte(0x89); /*MOV -7[EDI+ESI],EBX*/
addbyte(0x89); /*MOV 4[EDI+ESI],EBX*/
addbyte(0x44 | (REG_ECX << 3));
addbyte(REG_EDI | (REG_ESI << 3));
addbyte(-7+4);
addbyte(4);
addbyte(0xc3); /*RET*/
addbyte(0x51); /*slowpath: PUSH ECX*/
@@ -513,7 +502,9 @@ static uint32_t gen_MEM_STORE_ADDR_EA_Q()
return addr;
}
#ifndef RELEASE_BUILD
static char gen_MEM_LOAD_ADDR_EA_B_NO_ABRT_err[] = "gen_MEM_LOAD_ADDR_EA_B_NO_ABRT aborted\n";
#endif
static uint32_t gen_MEM_LOAD_ADDR_EA_B_NO_ABRT()
{
uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos];
@@ -575,7 +566,9 @@ static uint32_t gen_MEM_LOAD_ADDR_EA_B_NO_ABRT()
return addr;
}
#ifndef RELEASE_BUILD
static char gen_MEM_LOAD_ADDR_EA_W_NO_ABRT_err[] = "gen_MEM_LOAD_ADDR_EA_W_NO_ABRT aborted\n";
#endif
static uint32_t gen_MEM_LOAD_ADDR_EA_W_NO_ABRT()
{
uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos];
@@ -584,31 +577,29 @@ static uint32_t gen_MEM_LOAD_ADDR_EA_W_NO_ABRT()
addbyte(0xd6);
addbyte(0x01); /*ADDL EDX, EAX*/
addbyte(0xc2);
addbyte(0x8d); /*LEA EDI, 1[EDX]*/
addbyte(0x7a);
addbyte(0x01);
addbyte(0x89); /*MOV EDI, EDX*/
addbyte(0xd7);
addbyte(0xc1); /*SHR EDX, 12*/
addbyte(0xea);
addbyte(12);
addbyte(0xf7); /*TEST EDI, 0xfff*/
addbyte(0xf7); /*TEST EDI, 1*/
addbyte(0xc7);
addlong(0xfff);
addlong(1);
addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/
addbyte(0x14);
addbyte(0x95);
addlong((uint32_t)readlookup2);
addbyte(0x74); /*JE slowpath*/
addbyte(3+2+5+1);
addbyte(0x75); /*JNE slowpath*/
addbyte(3+2+4+1);
addbyte(0x83); /*CMP EDX, -1*/
addbyte(0xfa);
addbyte(-1);
addbyte(0x74); /*JE slowpath*/
addbyte(5+1);
addbyte(0x0f); /*MOVZX EEX, -1[EDX+EDI]W*/
addbyte(4+1);
addbyte(0x0f); /*MOVZX ECX, [EDX+EDI]W*/
addbyte(0xb7);
addbyte(0x4c);
addbyte(0x0c);
addbyte(0x3a);
addbyte(-1);
addbyte(0xc3); /*RET*/
addbyte(0x50); /*slowpath: PUSH EAX*/
@@ -644,7 +635,9 @@ static uint32_t gen_MEM_LOAD_ADDR_EA_W_NO_ABRT()
return addr;
}
#ifndef RELEASE_BUILD
static char gen_MEM_LOAD_ADDR_EA_L_NO_ABRT_err[] = "gen_MEM_LOAD_ADDR_EA_L_NO_ABRT aborted\n";
#endif
static uint32_t gen_MEM_LOAD_ADDR_EA_L_NO_ABRT()
{
uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos];
@@ -653,30 +646,28 @@ static uint32_t gen_MEM_LOAD_ADDR_EA_L_NO_ABRT()
addbyte(0xd6);
addbyte(0x01); /*ADDL EDX, EAX*/
addbyte(0xc2);
addbyte(0x8d); /*LEA EDI, 3[EDX]*/
addbyte(0x7a);
addbyte(0x03);
addbyte(0x89); /*MOV EDI, EDX*/
addbyte(0xd7);
addbyte(0xc1); /*SHR EDX, 12*/
addbyte(0xea);
addbyte(12);
addbyte(0xf7); /*TEST EDI, 0xffc*/
addbyte(0xf7); /*TEST EDI, 3*/
addbyte(0xc7);
addlong(0xffc);
addlong(3);
addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/
addbyte(0x14);
addbyte(0x95);
addlong((uint32_t)readlookup2);
addbyte(0x74); /*JE slowpath*/
addbyte(3+2+4+1);
addbyte(0x75); /*JNE slowpath*/
addbyte(3+2+3+1);
addbyte(0x83); /*CMP EDX, -1*/
addbyte(0xfa);
addbyte(-1);
addbyte(0x74); /*JE slowpath*/
addbyte(4+1);
addbyte(0x8b); /*MOV ECX, -3[EDX+EDI]*/
addbyte(0x4c);
addbyte(3+1);
addbyte(0x8b); /*MOV ECX, [EDX+EDI]*/
addbyte(0x0c);
addbyte(0x3a);
addbyte(-3);
addbyte(0xc3); /*RET*/
addbyte(0x50); /*slowpath: PUSH EAX*/
@@ -712,7 +703,9 @@ static uint32_t gen_MEM_LOAD_ADDR_EA_L_NO_ABRT()
return addr;
}
#ifndef RELEASE_BUILD
static char gen_MEM_STORE_ADDR_EA_B_NO_ABRT_err[] = "gen_MEM_STORE_ADDR_EA_B_NO_ABRT aborted\n";
#endif
static uint32_t gen_MEM_STORE_ADDR_EA_B_NO_ABRT()
{
uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos];
@@ -770,7 +763,9 @@ static uint32_t gen_MEM_STORE_ADDR_EA_B_NO_ABRT()
return addr;
}
#ifndef RELEASE_BUILD
static char gen_MEM_STORE_ADDR_EA_W_NO_ABRT_err[] = "gen_MEM_STORE_ADDR_EA_W_NO_ABRT aborted\n";
#endif
static uint32_t gen_MEM_STORE_ADDR_EA_W_NO_ABRT()
{
uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos];
@@ -780,31 +775,29 @@ static uint32_t gen_MEM_STORE_ADDR_EA_W_NO_ABRT()
addbyte(0xf3);
addbyte(0x01); /*ADDL ESI, EAX*/
addbyte(0xc0 | (REG_EAX << 3) | REG_ESI);
addbyte(0x8d); /*LEA EDI, 1[ESI]*/
addbyte(0x7e);
addbyte(0x01);
addbyte(0x89); /*MOV EDI, ESI*/
addbyte(0xf7);
addbyte(0xc1); /*SHR ESI, 12*/
addbyte(0xe8 | REG_ESI);
addbyte(12);
addbyte(0xf7); /*TEST EDI, 0xfff*/
addbyte(0xf7); /*TEST EDI, 1*/
addbyte(0xc7);
addlong(0xfff);
addlong(1);
addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/
addbyte(0x04 | (REG_ESI << 3));
addbyte(0x85 | (REG_ESI << 3));
addlong((uint32_t)writelookup2);
addbyte(0x74); /*JE slowpath*/
addbyte(3+2+5+1);
addbyte(0x75); /*JNE slowpath*/
addbyte(3+2+4+1);
addbyte(0x83); /*CMP ESI, -1*/
addbyte(0xf8 | REG_ESI);
addbyte(-1);
addbyte(0x74); /*JE slowpath*/
addbyte(5+1);
addbyte(0x66); /*MOV -1[EDI+ESI],CX*/
addbyte(4+1);
addbyte(0x66); /*MOV [EDI+ESI],CX*/
addbyte(0x89);
addbyte(0x44 | (REG_CX << 3));
addbyte(0x04 | (REG_CX << 3));
addbyte(REG_EDI | (REG_ESI << 3));
addbyte(-1);
addbyte(0xc3); /*RET*/
addbyte(0x51); /*slowpath: PUSH ECX*/
@@ -836,7 +829,9 @@ static uint32_t gen_MEM_STORE_ADDR_EA_W_NO_ABRT()
return addr;
}
#ifndef RELEASE_BUILD
static char gen_MEM_STORE_ADDR_EA_L_NO_ABRT_err[] = "gen_MEM_STORE_ADDR_EA_L_NO_ABRT aborted\n";
#endif
static uint32_t gen_MEM_STORE_ADDR_EA_L_NO_ABRT()
{
uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos];
@@ -846,30 +841,28 @@ static uint32_t gen_MEM_STORE_ADDR_EA_L_NO_ABRT()
addbyte(0xf3);
addbyte(0x01); /*ADDL ESI, EAX*/
addbyte(0xc0 | (REG_EAX << 3) | REG_ESI);
addbyte(0x8d); /*LEA EDI, 3[ESI]*/
addbyte(0x7e);
addbyte(0x03);
addbyte(0x89); /*MOV EDI, ESI*/
addbyte(0xf7);
addbyte(0xc1); /*SHR ESI, 12*/
addbyte(0xe8 | REG_ESI);
addbyte(12);
addbyte(0xf7); /*TEST EDI, 0xffc*/
addbyte(0xf7); /*TEST EDI, 3*/
addbyte(0xc7);
addlong(0xffc);
addlong(3);
addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/
addbyte(0x04 | (REG_ESI << 3));
addbyte(0x85 | (REG_ESI << 3));
addlong((uint32_t)writelookup2);
addbyte(0x74); /*JE slowpath*/
addbyte(3+2+4+1);
addbyte(0x75); /*JNE slowpath*/
addbyte(3+2+3+1);
addbyte(0x83); /*CMP ESI, -1*/
addbyte(0xf8 | REG_ESI);
addbyte(-1);
addbyte(0x74); /*JE slowpath*/
addbyte(4+1);
addbyte(0x89); /*MOV -3[EDI+ESI],ECX*/
addbyte(0x44 | (REG_ECX << 3));
addbyte(3+1);
addbyte(0x89); /*MOV [EDI+ESI],ECX*/
addbyte(0x04 | (REG_ECX << 3));
addbyte(REG_EDI | (REG_ESI << 3));
addbyte(-3);
addbyte(0xc3); /*RET*/
addbyte(0x51); /*slowpath: PUSH ECX*/
@@ -1401,12 +1394,11 @@ void codegen_block_init(uint32_t phys_addr)
block->_cs = cs;
block->pnt = block_current;
block->phys = phys_addr;
block->use32 = use32;
block->stack32 = stack32;
block->next = block->prev = NULL;
block->next_2 = block->prev_2 = NULL;
block->page_mask = 0;
block->flags = CODEBLOCK_STATIC_TOP;
block->status = cpu_cur_status;
block->was_recompiled = 0;
@@ -1487,6 +1479,9 @@ void codegen_block_start_recompile(codeblock_t *block)
block->TOP = cpu_state.TOP;
block->was_recompiled = 1;
codegen_flat_ds = cpu_cur_status & CPU_STATUS_FLATDS;
codegen_flat_ss = cpu_cur_status & CPU_STATUS_FLATSS;
}
void codegen_block_remove()

View File

@@ -1,8 +1,25 @@
/* Copyright holders: Sarah Walker, Tenshi, leilei
see COPYING for more details
*/
/*
* 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.
*
* CPU type handler.
*
* Version: @(#)cpu.c 1.0.1 2017/06/03
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* leilei,
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016-2017 leilei.
* Copyright 2016-2017 Miran Grca.
*/
#include "../ibm.h"
#include "cpu.h"
#include "../device.h"
#include "../model.h"
#include "../io.h"
#include "x86_ops.h"
@@ -74,6 +91,9 @@ int cpu_hasrdtsc;
int cpu_hasMMX, cpu_hasMSR;
int cpu_hasCR4;
int cpu_use_dynarec;
int cpu_cyrix_alignment;
int hasfpu;
uint64_t cpu_CR4_mask;
@@ -81,6 +101,7 @@ int cpu_cycles_read, cpu_cycles_read_l, cpu_cycles_write, cpu_cycles_write_l;
int cpu_prefetch_cycles, cpu_prefetch_width;
int cpu_waitstates;
int cpu_cache_int_enabled, cpu_cache_ext_enabled;
int cpu_pci_speed;
int is286, is386;
int israpidcad, is_pentium;
@@ -132,6 +153,7 @@ int timing_iret_rm, timing_iret_v86, timing_iret_pm, timing_iret_pm_outer;
int timing_call_rm, timing_call_pm, timing_call_pm_gate, timing_call_pm_gate_inner;
int timing_retf_rm, timing_retf_pm, timing_retf_pm_outer;
int timing_jmp_rm, timing_jmp_pm, timing_jmp_pm_gate;
int timing_misaligned;
static struct
{
@@ -183,6 +205,15 @@ CPU cpus_pcjr[] =
{"", -1, 0, 0, 0, 0, 0,0,0,0}
};
CPU cpus_europc[] =
{
/*8088 EuroPC*/
{"8088/4.77", CPU_8088, 0, 4772728, 1, 0, 0, 0, 0, 0, 0,0,0,0},
{"8088/7.16", CPU_8088, 1, 14318184/2, 1, 0, 0, 0, 0, 0, 0,0,0,0},
{"8088/9.54", CPU_8088, 1, 4772728*2, 1, 0, 0, 0, 0, 0, 0,0,0,0},
{"", -1, 0, 0, 0, 0}
};
CPU cpus_8086[] =
{
/*8086 standard*/
@@ -405,7 +436,7 @@ CPU cpus_Cx486[] =
{"6x86MX-PR300", CPU_Cx6x86MX, 18, 233333333, 3, 33333333, 0x600, 0x600, 0x0454, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,7,7},
{"6x86MX-PR333", CPU_Cx6x86MX, 18, 250000000, 3, 41666667, 0x600, 0x600, 0x0453, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 20,20,9,9},
{"6x86MX-PR366", CPU_Cx6x86MX, 18, 250000000, 3, 33333333, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12},
{"6x86MX-PR400", CPU_Cx6x86MX, 18, 285000000, 3, 31666667, 0x600, 0x600, 0x0453, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9},
{"6x86MX-PR400", CPU_Cx6x86MX, 18, 285000000, 3, 41666667, 0x600, 0x600, 0x0453, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9},
{"", -1, 0, 0, 0}
};
@@ -617,11 +648,6 @@ void cpu_set()
if (enable_external_fpu)
{
hasfpu = 1;
if (cpu_s->cpu_type == CPU_i486SX)
{
/* The 487SX is a full implementation of the 486DX and takes over the entire CPU's operation. */
cpu_s->cpu_type = CPU_i486DX;
}
}
}
@@ -731,7 +757,10 @@ void cpu_set()
}
memset(&msr, 0, sizeof(msr));
timing_misaligned = 0;
cpu_cyrix_alignment = 0;
switch (cpu_s->cpu_type)
{
case CPU_8088:
@@ -925,6 +954,7 @@ void cpu_set()
timing_jmp_rm = 9;
timing_jmp_pm = 26;
timing_jmp_pm_gate = 37;
timing_misaligned = 3;
break;
case CPU_486DLC:
@@ -958,6 +988,7 @@ void cpu_set()
timing_jmp_rm = 9;
timing_jmp_pm = 26;
timing_jmp_pm_gate = 37;
timing_misaligned = 3;
break;
case CPU_i486SX:
@@ -991,6 +1022,7 @@ void cpu_set()
timing_jmp_rm = 17;
timing_jmp_pm = 19;
timing_jmp_pm_gate = 32;
timing_misaligned = 3;
break;
case CPU_Am486SX:
@@ -1025,6 +1057,7 @@ void cpu_set()
timing_jmp_rm = 17;
timing_jmp_pm = 19;
timing_jmp_pm_gate = 32;
timing_misaligned = 3;
break;
case CPU_Cx486S:
@@ -1058,6 +1091,7 @@ void cpu_set()
timing_jmp_rm = 9;
timing_jmp_pm = 26;
timing_jmp_pm_gate = 37;
timing_misaligned = 3;
break;
case CPU_Cx5x86:
@@ -1090,6 +1124,8 @@ void cpu_set()
timing_jmp_rm = 5;
timing_jmp_pm = 7;
timing_jmp_pm_gate = 17;
timing_misaligned = 2;
cpu_cyrix_alignment = 1;
break;
case CPU_WINCHIP:
@@ -1128,6 +1164,8 @@ void cpu_set()
timing_jmp_pm = 7;
timing_jmp_pm_gate = 17;
codegen_timing_set(&codegen_timing_winchip);
timing_misaligned = 2;
cpu_cyrix_alignment = 1;
break;
case CPU_PENTIUM:
@@ -1160,6 +1198,7 @@ void cpu_set()
timing_jmp_rm = 3;
timing_jmp_pm = 3;
timing_jmp_pm_gate = 18;
timing_misaligned = 3;
cpu_hasrdtsc = 1;
msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
cpu_hasMMX = 0;
@@ -1199,6 +1238,7 @@ void cpu_set()
timing_jmp_rm = 3;
timing_jmp_pm = 3;
timing_jmp_pm_gate = 18;
timing_misaligned = 3;
cpu_hasrdtsc = 1;
msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
cpu_hasMMX = 1;
@@ -1237,6 +1277,8 @@ void cpu_set()
timing_jmp_rm = 1;
timing_jmp_pm = 4;
timing_jmp_pm_gate = 14;
timing_misaligned = 2;
cpu_cyrix_alignment = 1;
cpu_hasrdtsc = 1;
msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
cpu_hasMMX = 0;
@@ -1275,6 +1317,8 @@ void cpu_set()
timing_jmp_rm = 1;
timing_jmp_pm = 4;
timing_jmp_pm_gate = 14;
timing_misaligned = 2;
cpu_cyrix_alignment = 1;
cpu_hasrdtsc = 1;
msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
cpu_hasMMX = 0;
@@ -1296,6 +1340,8 @@ void cpu_set()
timing_mml = 2;
timing_bt = 5-1; /*branch taken*/
timing_bnt = 1; /*branch not taken*/
timing_misaligned = 2;
cpu_cyrix_alignment = 1;
cpu_hasrdtsc = 1;
msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
cpu_hasMMX = 0;
@@ -1347,6 +1393,8 @@ void cpu_set()
timing_jmp_rm = 1;
timing_jmp_pm = 4;
timing_jmp_pm_gate = 14;
timing_misaligned = 2;
cpu_cyrix_alignment = 1;
cpu_hasrdtsc = 1;
msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
cpu_hasMMX = 1;
@@ -1369,6 +1417,7 @@ void cpu_set()
timing_mml = 3;
timing_bt = 0; /*branch taken*/
timing_bnt = 1; /*branch not taken*/
timing_misaligned = 3;
cpu_hasrdtsc = 1;
msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
cpu_hasMMX = 1;
@@ -1388,6 +1437,7 @@ void cpu_set()
timing_mml = 3;
timing_bt = 0; /*branch taken*/
timing_bnt = 1; /*branch not taken*/
timing_misaligned = 3;
cpu_hasrdtsc = 1;
msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
cpu_hasMMX = 1;
@@ -1420,6 +1470,7 @@ void cpu_set()
timing_mml = 1;
timing_bt = 0; /*branch taken*/
timing_bnt = 1; /*branch not taken*/
timing_misaligned = 3;
cpu_hasrdtsc = 1;
msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
cpu_hasMMX = 0;
@@ -1453,6 +1504,7 @@ void cpu_set()
timing_mml = 1;
timing_bt = 0; /*branch taken*/
timing_bnt = 1; /*branch not taken*/
timing_misaligned = 3;
cpu_hasrdtsc = 1;
msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
cpu_hasMMX = 1;
@@ -1486,6 +1538,7 @@ void cpu_set()
timing_mml = 1;
timing_bt = 0; /*branch taken*/
timing_bnt = 1; /*branch not taken*/
timing_misaligned = 3;
cpu_hasrdtsc = 1;
msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
cpu_hasMMX = 1;

View File

@@ -1,6 +1,23 @@
/* Copyright holders: Sarah Walker, Tenshi, leilei
see COPYING for more details
*/
/*
* 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.
*
* CPU type handler.
*
* Version: @(#)cpu.h 1.0.0 2017/05/30
*
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
* leilei,
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016-2017 leilei.
* Copyright 2016-2017 Miran Grca.
*/
#ifndef _CPU_H_
#define _CPU_H_
@@ -65,6 +82,8 @@ extern int timing_call_rm, timing_call_pm, timing_call_pm_gate, timing_call_pm_g
extern int timing_retf_rm, timing_retf_pm, timing_retf_pm_outer;
extern int timing_jmp_rm, timing_jmp_pm, timing_jmp_pm_gate;
extern int timing_misaligned;
typedef struct
{
@@ -107,6 +126,7 @@ extern CPU cpus_Pentium2[];
extern CPU cpus_Pentium2D[];
extern CPU cpus_pcjr[];
extern CPU cpus_europc[];
extern CPU cpus_pc1512[];
extern CPU cpus_ibmat[];
extern CPU cpus_ps1_m2011[];
@@ -117,6 +137,8 @@ extern int cpu_iscyrix;
extern int cpu_16bitbus;
extern int cpu_busspeed;
extern int cpu_multi;
/*Cyrix 5x86/6x86 only has data misalignment penalties when crossing 8-byte boundaries*/
extern int cpu_cyrix_alignment;
extern int cpu_hasrdtsc;
extern int cpu_hasMSR;
@@ -138,6 +160,7 @@ extern int cpu_cycles_read, cpu_cycles_read_l, cpu_cycles_write, cpu_cycles_writ
extern int cpu_prefetch_cycles, cpu_prefetch_width;
extern int cpu_waitstates;
extern int cpu_cache_int_enabled, cpu_cache_ext_enabled;
extern int cpu_pci_speed;
extern uint64_t tsc;

View File

@@ -102,3 +102,6 @@ void x86gpf(char *s, uint16_t error);
extern uint16_t zero;
extern int x86_was_reset;
extern int codegen_flat_ds;
extern int codegen_flat_ss;

View File

@@ -1,6 +1,19 @@
/* Copyright holders: Sarah Walker, Tenshi
see COPYING for more details
*/
/*
* 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.
*
* x86 i686 (Pentium Pro/Pentium II) CPU Instructions.
*
* Version: @(#)x86_ops_i686.h 1.0.0 2017/05/30
*
* Author: Miran Grca, <mgrca8@gmail.com>
* Copyright 2016-2017 Miran Grca.
*/
static int internal_illegal(char *s)
{
cpu_state.pc = cpu_state.oldpc;

View File

@@ -1,3 +1,21 @@
/*
* 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.
*
* Miscellaneous x86 CPU Instructions.
*
* Version: @(#)x86_ops_misc.h 1.0.0 2017/05/30
*
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016-2017 Miran Grca.
*/
static int opCBW(uint32_t fetchdat)
{
AH = (AL & 0x80) ? 0xff : 0;
@@ -755,9 +773,17 @@ static int opLOADALL(uint32_t fetchdat)
ss = readmemw(0, 0x842) | (readmemb(0, 0x844) << 16);
_ss.access = readmemb(0, 0x845);
_ss.limit = readmemw(0, 0x846);
if (_ss.base == 0 && _ss.limit_low == 0 && _ss.limit_high == 0xffffffff)
cpu_cur_status |= CPU_STATUS_FLATSS;
else
cpu_cur_status &= ~CPU_STATUS_FLATSS;
ds = readmemw(0, 0x848) | (readmemb(0, 0x84A) << 16);
_ds.access = readmemb(0, 0x84B);
_ds.limit = readmemw(0, 0x84C);
if (_ds.base == 0 && _ds.limit_low == 0 && _ds.limit_high == 0xffffffff)
cpu_cur_status |= CPU_STATUS_FLATDS;
else
cpu_cur_status &= ~CPU_STATUS_FLATDS;
gdt.base = readmemw(0, 0x84E) | (readmemb(0, 0x850) << 16);
gdt.limit = readmemw(0, 0x852);
ldt.base = readmemw(0, 0x854) | (readmemb(0, 0x856) << 16);
@@ -797,8 +823,29 @@ static void loadall_load_segment(uint32_t addr, x86seg *s)
if (s == &_cs) use32 = (segdat3 & 0x40) ? 0x300 : 0;
if (s == &_ss) stack32 = (segdat3 & 0x40) ? 1 : 0;
cpu_cur_status &= ~(CPU_STATUS_USE32 | CPU_STATUS_STACK32);
if (use32)
cpu_cur_status |= CPU_STATUS_USE32;
if (stack32)
cpu_cur_status |= CPU_STATUS_STACK32;
set_segment_limit(s, segdat3);
if (s == &_ds)
{
if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff)
cpu_cur_status |= CPU_STATUS_FLATDS;
else
cpu_cur_status &= ~CPU_STATUS_FLATDS;
}
if (s == &_ss)
{
if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff)
cpu_cur_status |= CPU_STATUS_FLATSS;
else
cpu_cur_status &= ~CPU_STATUS_FLATSS;
}
}
static int opLOADALL386(uint32_t fetchdat)

View File

@@ -1,6 +1,21 @@
/* Copyright holders: Sarah Walker, SA1988
see COPYING for more details
*/
/*
* 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.
*
* x86 CPU segment emulation.
*
* Version: @(#)x86seg.c 1.0.0 2017/05/30
*
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016-2017 Miran Grca.
*/
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
@@ -159,6 +174,29 @@ void x86np(char *s, uint16_t error)
}
static void set_stack32(int s)
{
stack32 = s;
if (stack32)
cpu_cur_status |= CPU_STATUS_STACK32;
else
cpu_cur_status &= ~CPU_STATUS_STACK32;
}
static void set_use32(int u)
{
if (u)
{
use32 = 0x300;
cpu_cur_status |= CPU_STATUS_USE32;
}
else
{
use32 = 0;
cpu_cur_status &= ~CPU_STATUS_USE32;
}
}
void do_seg_load(x86seg *s, uint16_t *segdat)
{
s->limit = segdat[0] | ((segdat[3] & 0xF) << 16);
@@ -179,6 +217,21 @@ void do_seg_load(x86seg *s, uint16_t *segdat)
s->limit_high = (segdat[3] & 0x40) ? 0xffffffff : 0xffff;
s->limit_low = s->limit + 1;
}
if (s == &_ds)
{
if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff)
cpu_cur_status |= CPU_STATUS_FLATDS;
else
cpu_cur_status &= ~CPU_STATUS_FLATDS;
}
if (s == &_ss)
{
if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff)
cpu_cur_status |= CPU_STATUS_FLATSS;
else
cpu_cur_status &= ~CPU_STATUS_FLATSS;
}
}
static void do_seg_v86_init(x86seg *s)
@@ -251,6 +304,8 @@ void loadseg(uint16_t seg, x86seg *s)
s->seg=0;
s->access = 0x80;
s->base=-1;
if (s == &_ds)
cpu_cur_status &= ~CPU_STATUS_FLATDS;
return;
}
addr=seg&~7;
@@ -303,7 +358,7 @@ void loadseg(uint16_t seg, x86seg *s)
x86ss(NULL,seg&~3);
return;
}
stack32 = (segdat[3] & 0x40) ? 1 : 0;
set_stack32((segdat[3] & 0x40) ? 1 : 0);
}
else if (s!=&_cs)
{
@@ -349,6 +404,10 @@ void loadseg(uint16_t seg, x86seg *s)
}
#endif
s->checked = 0;
if (s == &_ds)
codegen_flat_ds = 0;
if (s == &_ss)
codegen_flat_ss = 0;
}
else
{
@@ -358,6 +417,26 @@ void loadseg(uint16_t seg, x86seg *s)
if (s == &_ss)
stack32 = 0;
s->checked = 1;
if (s == &_ds)
codegen_flat_ds = 0;
if (s == &_ss)
codegen_flat_ss = 0;
}
if (s == &_ds)
{
if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff)
cpu_cur_status |= CPU_STATUS_FLATDS;
else
cpu_cur_status &= ~CPU_STATUS_FLATDS;
}
if (s == &_ss)
{
if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff)
cpu_cur_status |= CPU_STATUS_FLATSS;
else
cpu_cur_status &= ~CPU_STATUS_FLATSS;
}
}
@@ -426,8 +505,7 @@ void loadcs(uint16_t seg)
x86np("Load CS not present", seg & 0xfffc);
return;
}
if (segdat[3]&0x40) use32=0x300;
else use32=0;
set_use32(segdat[3] & 0x40);
CS=(seg&~3)|CPL;
do_seg_load(&_cs, segdat);
use32=(segdat[3]&0x40)?0x300:0;
@@ -530,8 +608,7 @@ void loadcsjmp(uint16_t seg, uint32_t oxpc)
x86np("Load CS JMP not present\n", seg & 0xfffc);
return;
}
if (segdat[3]&0x40) use32=0x300;
else use32=0;
set_use32(segdat[3]&0x40);
#ifdef CS_ACCESSED
cpl_override = 1;
@@ -544,7 +621,6 @@ void loadcsjmp(uint16_t seg, uint32_t oxpc)
do_seg_load(&_cs, segdat);
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
use32=(segdat[3]&0x40)?0x300:0;
cycles -= timing_jmp_pm;
}
else /*System segment*/
@@ -642,8 +718,8 @@ void loadcsjmp(uint16_t seg, uint32_t oxpc)
CS=seg2;
do_seg_load(&_cs, segdat);
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
use32=(segdat[3]&0x40)?0x300:0;
cpu_state.pc=newpc;
set_use32(segdat[3]&0x40);
cpu_state.pc=newpc;
#ifdef CS_ACCESSED
cpl_override = 1;
@@ -828,8 +904,7 @@ void loadcscall(uint16_t seg)
x86np("Load CS call not present", seg & 0xfffc);
return;
}
if (segdat[3]&0x40) use32=0x300;
else use32=0;
set_use32(segdat[3]&0x40);
#ifdef CS_ACCESSED
cpl_override = 1;
@@ -848,7 +923,6 @@ void loadcscall(uint16_t seg)
CS=seg;
do_seg_load(&_cs, segdat);
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
use32=(segdat[3]&0x40)?0x300:0;
if (csout) pclog("Complete\n");
cycles -= timing_call_pm;
}
@@ -1005,7 +1079,7 @@ void loadcscall(uint16_t seg)
}
if (!stack32) oldsp &= 0xFFFF;
SS=newss;
stack32 = (segdat2[3] & 0x40) ? 1 : 0;
set_stack32((segdat2[3] & 0x40) ? 1 : 0);
if (stack32) ESP=newsp;
else SP=newsp;
@@ -1022,7 +1096,7 @@ void loadcscall(uint16_t seg)
CS=seg2;
do_seg_load(&_cs, segdat);
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
use32=(segdat[3]&0x40)?0x300:0;
set_use32(segdat[3]&0x40);
cpu_state.pc=newpc;
if (output) pclog("Set access 2\n");
@@ -1101,8 +1175,8 @@ void loadcscall(uint16_t seg)
CS=seg2;
do_seg_load(&_cs, segdat);
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
use32=(segdat[3]&0x40)?0x300:0;
cpu_state.pc=newpc;
set_use32(segdat[3]&0x40);
cpu_state.pc=newpc;
#ifdef CS_ACCESSED
cpl_override = 1;
@@ -1245,8 +1319,8 @@ void pmoderetf(int is32, uint16_t off)
do_seg_load(&_cs, segdat);
_cs.access = (_cs.access & ~(3 << 5)) | ((CS & 3) << 5);
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
use32=(segdat[3]&0x40)?0x300:0;
set_use32(segdat[3] & 0x40);
cycles -= timing_retf_pm;
}
else
@@ -1353,7 +1427,7 @@ void pmoderetf(int is32, uint16_t off)
return;
}
SS=newss;
stack32 = (segdat2[3] & 0x40) ? 1 : 0;
set_stack32((segdat2[3] & 0x40) ? 1 : 0);
if (stack32) ESP=newsp;
else SP=newsp;
do_seg_load(&_ss, segdat2);
@@ -1375,7 +1449,7 @@ void pmoderetf(int is32, uint16_t off)
CS=seg;
do_seg_load(&_cs, segdat);
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
use32=(segdat[3]&0x40)?0x300:0;
set_use32(segdat[3] & 0x40);
if (stack32) ESP+=off;
else SP+=off;
@@ -1570,7 +1644,7 @@ void pmodeint(int num, int soft)
return;
}
SS=newss;
stack32 = (segdat3[3] & 0x40) ? 1 : 0;
set_stack32((segdat3[3] & 0x40) ? 1 : 0);
if (stack32) ESP=newsp;
else SP=newsp;
do_seg_load(&_ss, segdat3);
@@ -1655,7 +1729,7 @@ void pmodeint(int num, int soft)
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
if (type>0x800) cpu_state.pc=segdat[0]|(segdat[3]<<16);
else cpu_state.pc=segdat[0];
use32=(segdat2[3]&0x40)?0x300:0;
set_use32(segdat2[3]&0x40);
#ifdef CS_ACCESSED
cpl_override = 1;
@@ -1809,6 +1883,7 @@ void pmodeiret(int is32)
do_seg_v86_init(&_es);
loadseg(segs[1],&_ds);
do_seg_v86_init(&_ds);
cpu_cur_status &= ~CPU_STATUS_FLATDS;
loadseg(segs[2],&_fs);
do_seg_v86_init(&_fs);
loadseg(segs[3],&_gs);
@@ -1826,7 +1901,9 @@ void pmodeiret(int is32)
ESP=newsp;
loadseg(newss,&_ss);
do_seg_v86_init(&_ss);
cpu_cur_status &= ~CPU_STATUS_FLATSS;
use32=0;
cpu_cur_status &= ~CPU_STATUS_USE32;
flags=(tempflags&0xFFD5)|2;
cycles -= timing_iret_v86;
return;
@@ -1913,7 +1990,7 @@ void pmodeiret(int is32)
do_seg_load(&_cs, segdat);
_cs.access = (_cs.access & ~(3 << 5)) | ((CS & 3) << 5);
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
use32=(segdat[3]&0x40)?0x300:0;
set_use32(segdat[3]&0x40);
#ifdef CS_ACCESSED
cpl_override = 1;
@@ -1996,7 +2073,7 @@ void pmodeiret(int is32)
return;
}
SS=newss;
stack32 = (segdat2[3] & 0x40) ? 1 : 0;
set_stack32((segdat2[3] & 0x40) ? 1 : 0);
if (stack32) ESP=newsp;
else SP=newsp;
do_seg_load(&_ss, segdat2);
@@ -2018,7 +2095,7 @@ void pmodeiret(int is32)
do_seg_load(&_cs, segdat);
_cs.access = (_cs.access & ~(3 << 5)) | ((CS & 3) << 5);
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
use32=(segdat[3]&0x40)?0x300:0;
set_use32(segdat[3] & 0x40);
check_seg_valid(&_ds);
check_seg_valid(&_es);
@@ -2208,7 +2285,7 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32)
CS=new_cs;
do_seg_load(&_cs, segdat2);
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
use32=(segdat2[3]&0x40)?0x300:0;
set_use32(segdat2[3] & 0x40);
EAX=new_eax;
ECX=new_ecx;

View File

@@ -1,4 +1,17 @@
/* Copyright holders: Tenshi
see COPYING for more details
*/
/*
* 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.
*
* x86 CPU segment emulation.
*
* Version: @(#)x86seg.h 1.0.0 2017/05/30
*
* Author: Miran Grca, <mgrca8@gmail.com>
* Copyright 2016-2017 Miran Grca.
*/
void do_seg_load(x86seg *s, uint16_t *segdat);

View File

@@ -1,3 +1,23 @@
/*
* 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.
*
* x87 FPU instructions core.
*
* Version: @(#)x87_ops.h 1.0.0 2017/05/30
*
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
* leilei,
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016-2017 leilei.
* Copyright 2016-2017 Miran Grca.
*/
#include <math.h>
#include <fenv.h>

View File

@@ -1,3 +1,21 @@
/*
* 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.
*
* x87 FPU instructions core.
*
* Version: @(#)x87_ops_loadstore.h 1.0.0 2017/05/30
*
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016-2017 Miran Grca.
*/
static int opFILDiw_a16(uint32_t fetchdat)
{
int16_t temp;

View File

@@ -6,11 +6,11 @@
#
# This file is part of the 86Box distribution.
#
# Modified Makefile for Win32 MinGW 32-bit environment.
# Modified Makefile for Win32 (MinGW32) environment.
#
# Version: @(#)Makefile.mingw 1.0.16 2017/05/23
# Version: @(#)Makefile.mingw 1.0.25 2017/06/04
#
# Authors: Kotori, <oubattler@gmail.com>
# Authors: Miran Grca, <mgrca8@gmail.com>
# Fred N. van Kempen, <decwiz@yahoo.com>
# Sarah Walker,
# Richard G.,
@@ -33,7 +33,16 @@ endif
>>>>>>> master
# Add feature selections here.
# -DBUGGER adds the ISA BusBugger emulation.
# -DANSI_CFG forces the config file to ANSI encoding.
# -DENABLE_VRAM_DUMP enables Video Ram dumping.
# -DENABLE_LOG_BREAKPOINT enables extra logging.
# -DENABLE_BUSLOGIC_LOG enables extra logging.
# -DENABLE_CDROM_LOG enables extra logging.
# -DENABLE_D86F_LOG enables extra logging.
# -DENABLE_FDC_LOG enables extra logging.
# -DENABLE_IDE_LOG enables extra logging.
# -DENABLE_SERIAL_LOG enables extra logging.
# -DENABLE_NIC_LOG enables extra logging.
ifndef EXTRAS
EXTRAS =
endif
@@ -43,7 +52,13 @@ ifndef DEBUG
DEBUG = n
endif
ifndef OPTIM
OPTIM = y
OPTIM = n
endif
ifndef RELEASE
RELEASE = n
endif
ifndef USB
USB = n
endif
ifndef X64
X64 = n
@@ -133,7 +148,8 @@ SYSOBJ = model.o \
sis496.o \
wd76c10.o \
acer386sx.o acerm3a.o amstrad.o \
compaq.o olivetti_m24.o jim.o ps1.o ps2.o ps2_mca.o \
compaq.o laserxt.o jim.o \
olivetti_m24.o ps1.o ps2.o ps2_mca.o \
tandy_eeprom.o tandy_rom.o
DEVOBJ = bugger.o lpt.o serial.o \
um8669f.o pc87306.o sis85c471.o w83877f.o \
@@ -153,7 +169,9 @@ DEVOBJ = bugger.o lpt.o serial.o \
disc_random.o disc_td0.o \
cdrom.o \
cdrom_dosbox.o cdrom_image.o cdrom_ioctl.o cdrom_null.o
ifdef USB
USBOBJ = usb.o
endif
NETOBJ = network.o \
net_pcap.o net_slirp.o \
net_ne2000.o
@@ -173,7 +191,8 @@ SNDOBJ = sound.o \
snd_sn76489.o snd_ssi2001.o snd_wss.o \
snd_ym7128.o
VIDOBJ = video.o \
vid_cga.o vid_cga_comp.o vid_mda.o vid_ega.o \
vid_cga.o vid_cga_comp.o vid_mda.o \
vid_ega.o vid_ega_render.o \
vid_vga.o vid_svga.o vid_svga_render.o \
vid_hercules.o vid_herculesplus.o vid_incolor.o \
vid_colorplus.o \
@@ -200,8 +219,8 @@ WINOBJ = win.o \
win_ddraw.o win_ddraw_fs.o win_ddraw_screenshot.o \
win_d3d.o win_d3d_fs.o \
win_language.o win_status.o win_opendir.o win_dynld.o \
win_video.o win_serial.o win_mouse.o \
win_joystick.o win_midi.o \
win_video.o win_serial.o win_keyboard.o win_mouse.o \
win_iodev.o win_joystick.o win_midi.o \
win_settings.o win_deviceconfig.o win_joystickconfig.o \
86Box.res
OBJ = $(MAINOBJ) $(CPUOBJ) $(SYSOBJ) $(DEVOBJ) $(USBOBJ) \
@@ -212,9 +231,9 @@ SLIRPOBJ= bootp.o ip_icmp.o misc.o socket.o tcp_timer.o cksum.o \
ip_input.o queue.o tcp_input.o debug.o ip_output.o \
sbuf.o tcp_output.o udp.o if.o mbuf.o slirp.o tcp_subr.o
LIBS = -mwindows -lcomctl32 -lwinmm -lopenal.dll -lopenal -lddraw \
-ldinput8 -ldxguid -ld3d9 -ld3dx9 -lwsock32 -liphlpapi \
-lstdc++ -lpsapi -static-libstdc++ -static-libgcc
LIBS = -lddraw -ldinput8 -ldxguid -ld3d9 -ld3dx9 -lopenal.dll \
-mwindows -lcomctl32 -lwinmm -lwsock32 -liphlpapi -lpsapi \
-static-libstdc++ -static -lstdc++ -static-libgcc -static -lgcc
# Build rules.
@@ -235,17 +254,14 @@ all: $(PROG).exe pcap_if.exe
$(PROG).exe: $(OBJ) $(LZFOBJ) $(SLIRPOBJ)
@echo Linking $(PROG).exe ..
@$(CC) -o $(PROG).exe \
$(OBJ) $(LZFOBJ) $(SLIRPOBJ) \
$(LIBS) #-static -Lpcap -lwpcapdelay
@$(CC) -o $(PROG).exe $(OBJ) $(LZFOBJ) $(SLIRPOBJ) $(LIBS)
ifneq ($(DEBUG), y)
@strip $(PROG).exe
endif
pcap_if.exe: pcap_if.o pcap_if.res
pcap_if.exe: pcap_if.o win_dynld.o pcap_if.res
@echo Linking pcap_if.exe ..
@$(CC) -o pcap_if.exe \
pcap_if.o pcap_if.res -static -Lpcap -lwpcapdelay
@$(CC) -o pcap_if.exe pcap_if.o win_dynld.o pcap_if.res
ifneq ($(DEBUG), y)
@strip pcap_if.exe
endif
@@ -253,13 +269,13 @@ endif
clean:
rm *.o
rm *.exe
rm *.res
-rm *.o
-rm *.exe
-rm *.res
86Box.res: 86Box.rc
@echo Processing $<
@$(WINDRES) $(RFLAGS) -i win/86Box.rc -o 86Box.res
@$(WINDRES) $(RFLAGS) $(EXTRAS) -i win/86Box.rc -o 86Box.res
pcap_if.res: pcap_if.rc
@echo Processing $<

View File

@@ -1,2 +0,0 @@
include Makefile.mingw
CFLAGS = -O3 -march=amdfam10 -mtune=amdfam10 -fbranch-probabilities -fvpt -funroll-loops -fpeel-loops -ftracer -fomit-frame-pointer -ffast-math -msse -msse2 -msse3 -mfpmath=sse -mstackrealign

View File

@@ -1,2 +0,0 @@
include Makefile.mingw64
CFLAGS = -O3 -march=amdfam10 -mtune=amdfam10 -fbranch-probabilities -fvpt -funroll-loops -fpeel-loops -ftracer -fomit-frame-pointer -ffast-math -msse -msse2 -msse3 -mfpmath=sse -mstackrealign

View File

@@ -131,10 +131,10 @@ static __inline float high_cut_iir(int i, float NewSample) {
#undef NCoef
#define NCoef 1
#define NCoef 2
static __inline float sb_iir(int i, float NewSample) {
/* float ACoef[NCoef+1] = {
float ACoef[NCoef+1] = {
0.03356837051492005100,
0.06713674102984010200,
0.03356837051492005100
@@ -144,9 +144,9 @@ static __inline float sb_iir(int i, float NewSample) {
1.00000000000000000000,
-1.41898265221812010000,
0.55326988968868285000
};*/
};
float ACoef[NCoef+1] = {
/* float ACoef[NCoef+1] = {
0.17529642630084405000,
0.17529642630084405000
};
@@ -154,7 +154,8 @@ static __inline float sb_iir(int i, float NewSample) {
float BCoef[NCoef+1] = {
1.00000000000000000000,
-0.64940759319751051000
};
};*/
static float y[2][NCoef+1]; /* output samples */
static float x[2][NCoef+1]; /* input samples */
int n;

View File

@@ -88,7 +88,7 @@ void opl_write(int nr, uint16_t addr, uint8_t val)
if (!(addr & 1))
{
if (!opl[nr].is_opl3 || !opl3_type)
opl[nr].addr = (int)opl[nr].chip.WriteAddr(addr, val) & 0xff;
opl[nr].addr = (int)opl[nr].chip.WriteAddr(addr, val) & (opl[nr].is_opl3 ? 0x1ff : 0xff);
else
opl[nr].addr = (int)OPL3_WriteAddr(&opl[nr].opl3chip, addr, val) & 0x1ff;
}

View File

@@ -547,7 +547,7 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8);
uint8_t readgus(uint16_t addr, void *p)
{
gus_t *gus = (gus_t *)p;
uint8_t val;
uint8_t val = 0xff;
switch (addr)
{
case 0x340: /*MIDI status*/

View File

@@ -1,10 +1,35 @@
/*
* 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.
*
* Roland MPU-401 emulation.
*
* Version: @(#)sound_mpu401.c 1.0.0 2017/05/30
*
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
* DOSBox Team,
* Miran Grca, <mgrca8@gmail.com>
* TheCollector1995, <mariogplayer@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2008-2017 DOSBox Team.
* Copyright 2016-2017 Miran Grca.
* Copyright 2016-2017 TheCollector1995.
*/
#include "../ibm.h"
#include "../device.h"
#include "../io.h"
#include "../pic.h"
#include "../timer.h"
#include "../win/plat_midi.h" /*YUCK*/
#include "sound.h"
#include "snd_mpu401.h"
#include <malloc.h>
#include <stdarg.h>
enum
@@ -16,6 +41,8 @@ enum
static void MPU401_WriteCommand(mpu_t *mpu, uint8_t val);
static void MPU401_EOIHandlerDispatch(void *p);
int mpu401_standalone_enable = 0;
static int mpu401_event_callback = 0;
static int mpu401_eoi_callback = 0;
static int mpu401_reset_callback = 0;
@@ -135,7 +162,7 @@ static void MPU401_ResetDone(void *p)
static void MPU401_WriteCommand(mpu_t *mpu, uint8_t val)
{
uint8_t i;
if (mpu->state.reset)
{
mpu->state.cmd_pending=val+1;
@@ -274,7 +301,9 @@ static void MPU401_WriteCommand(mpu_t *mpu, uint8_t val)
mpu401_reset_callback = MPU401_RESETBUSY * 33 * TIMER_USEC;
mpu->state.reset=1;
MPU401_Reset(mpu);
#if 0
if (mpu->mode==M_UART) return;//do not send ack in UART mode
#endif
break;
case 0x3f: /* UART mode */
pclog("MPU-401:Set UART mode %X\n",val);
@@ -706,6 +735,14 @@ next_event:
void mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode)
{
#if 0
if (mode != M_INTELLIGENT)
{
mpu401_uart_init(mpu, addr);
return;
}
#endif
mpu->status = STATUS_INPUT_NOT_READY;
mpu->irq = irq;
mpu->queue_used = 0;
@@ -727,3 +764,118 @@ void mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode)
MPU401_Reset(mpu);
}
void mpu401_device_add(void)
{
char *n;
if (!mpu401_standalone_enable)
{
return;
}
n = sound_card_get_internal_name(sound_card_current);
if (n != NULL)
{
if (!strcmp(n, "sb16") || !strcmp(n, "sbawe32"))
{
return;
}
}
device_add(&mpu401_device);
}
void *mpu401_standalone_init()
{
mpu_t *mpu;
mpu = malloc(sizeof(mpu_t));
memset(mpu, 0, sizeof(mpu_t));
pclog("mpu_init\n");
mpu401_init(mpu, device_get_config_hex16("base"), device_get_config_int("irq"), device_get_config_int("mode"));
return mpu;
}
void mpu401_standalone_close(void *p)
{
mpu_t *mpu = (mpu_t *)p;
free(mpu);
}
static device_config_t mpu401_standalone_config[] =
{
{
"base", "MPU-401 Address", CONFIG_HEX16, "", 0x330,
{
{
"0x300", 0x300
},
{
"0x330", 0x330
},
{
""
}
}
},
{
"irq", "MPU-401 IRQ", CONFIG_SELECTION, "", 9,
{
{
"IRQ 9", 9
},
{
"IRQ 3", 3
},
{
"IRQ 4", 4
},
{
"IRQ 5", 5
},
{
"IRQ 7", 7
},
{
"IRQ 10", 10
},
{
""
}
}
},
{
"mode", "Mode", CONFIG_SELECTION, "", 1,
{
{
"UART", M_UART
},
{
"Intelligent", M_INTELLIGENT
},
{
""
}
}
},
{
"", "", -1
}
};
device_t mpu401_device =
{
"MPU-401 (Standalone)",
0,
mpu401_standalone_init,
mpu401_standalone_close,
NULL,
NULL,
NULL,
NULL,
mpu401_standalone_config
};

View File

@@ -1,3 +1,25 @@
/*
* 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.
*
* Roland MPU-401 emulation.
*
* Version: @(#)sound_mpu401.h 1.0.0 2017/05/30
*
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
* DOSBox Team,
* Miran Grca, <mgrca8@gmail.com>
* TheCollector1995, <mariogplayer@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2008-2017 DOSBox Team.
* Copyright 2016-2017 Miran Grca.
* Copyright 2016-2017 TheCollector1995.
*/
#define MPU401_VERSION 0x15
#define MPU401_REVISION 0x01
#define MPU401_QUEUE 32
@@ -21,6 +43,8 @@ typedef enum MpuDataType {T_OVERFLOW,T_MARK,T_MIDI_SYS,T_MIDI_NORM,T_COMMAND} Mp
typedef struct mpu_t
{
int uart_mode;
uint8_t rx_data;
int intelligent;
MpuMode mode;
int irq;
@@ -61,3 +85,10 @@ typedef struct mpu_t
uint8_t MPU401_ReadData(mpu_t *mpu);
void mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode);
extern int mpu401_standalone_enable;
void mpu401_device_add(void);
device_t mpu401_device;
void mpu401_uart_init(mpu_t *mpu, uint16_t addr);

View File

@@ -88,8 +88,8 @@ void opl2_update2(opl_t *opl)
opl2_update(1, &opl->buffer[opl->pos*2 + 1], sound_pos_global - opl->pos);
for (; opl->pos < sound_pos_global; opl->pos++)
{
opl->filtbuf[0] = opl->buffer[opl->pos*2] = (opl->buffer[opl->pos*2] / 4) + ((opl->filtbuf[0] * 11) / 16);
opl->filtbuf[1] = opl->buffer[opl->pos*2+1] = (opl->buffer[opl->pos*2+1] / 4) + ((opl->filtbuf[1] * 11) / 16);
opl->filtbuf[0] = opl->buffer[opl->pos*2] = (opl->buffer[opl->pos*2] / 2);
opl->filtbuf[1] = opl->buffer[opl->pos*2+1] = (opl->buffer[opl->pos*2+1] / 2);
}
}
}
@@ -101,8 +101,8 @@ void opl3_update2(opl_t *opl)
opl3_update(0, &opl->buffer[opl->pos*2], sound_pos_global - opl->pos);
for (; opl->pos < sound_pos_global; opl->pos++)
{
opl->filtbuf[0] = opl->buffer[opl->pos*2] = (opl->buffer[opl->pos*2] / 4) + ((opl->filtbuf[0] * 11) / 16);
opl->filtbuf[1] = opl->buffer[opl->pos*2+1] = (opl->buffer[opl->pos*2+1] / 4) + ((opl->filtbuf[1] * 11) / 16);
opl->filtbuf[0] = opl->buffer[opl->pos*2] = (opl->buffer[opl->pos*2] / 2);
opl->filtbuf[1] = opl->buffer[opl->pos*2+1] = (opl->buffer[opl->pos*2+1] / 2);
}
}
}

View File

@@ -1,3 +1,23 @@
/*
* 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.
*
* Sound Blaster emulation.
*
* Version: @(#)sound_sb.c 1.0.0 2017/05/30
*
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* TheCollector1995, <mariogplayer@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016-2017 Miran Grca.
* Copyright 2016-2017 TheCollector1995.
*/
#include <stdlib.h>
#include "../ibm.h"
#include "../io.h"
@@ -6,6 +26,7 @@
#include "../rom.h"
#include "../device.h"
#include "sound.h"
#include "snd_dbopl.h"
#include "snd_emu8k.h"
#include "snd_mpu401.h"
#include "snd_opl.h"
@@ -43,9 +64,9 @@ typedef struct sb_t
static int sb_att[]=
{
310,368,437,520,618,735,873,1038,1234,1467,1743,2072,2463,2927,3479,
4134,4914,5840,6941,8250,9805,11653,13850,16461,19564,23252,27635,32845,
39036,46395,55140,65535
50,65,82,103,130,164,207,260,328,413,520,655,825,1038,1307,
1645,2072,2608,3283,4134,5205,6553,8250,10385,13075,16461,20724,26089,
32845,41349,52055,65535
};
static void sb_get_buffer_opl2(int32_t *buffer, int len, void *p)
@@ -61,8 +82,8 @@ static void sb_get_buffer_opl2(int32_t *buffer, int len, void *p)
{
int32_t out_l, out_r;
out_l = ((sb->opl.buffer[c] * mixer->fm_l) >> 16);
out_r = ((sb->opl.buffer[c + 1] * mixer->fm_r) >> 16);
out_l = ((((sb->opl.buffer[c] * mixer->fm_l) >> 16) * 51000) >> 16);
out_r = ((((sb->opl.buffer[c + 1] * mixer->fm_r) >> 16) * 51000) >> 16);
if (sb->mixer.filter)
{
@@ -112,8 +133,8 @@ static void sb_get_buffer_opl3(int32_t *buffer, int len, void *p)
{
int32_t out_l, out_r;
out_l = ((sb->opl.buffer[c] * mixer->fm_l) >> 16);
out_r = ((sb->opl.buffer[c + 1] * mixer->fm_r) >> 16);
out_l = ((((sb->opl.buffer[c] * mixer->fm_l) >> 16) * (opl3_type ? 47000 : 51000)) >> 16);
out_r = ((((sb->opl.buffer[c + 1] * mixer->fm_r) >> 16) * (opl3_type ? 47000 : 51000)) >> 16);
if (sb->mixer.filter)
{
@@ -245,7 +266,14 @@ uint8_t sb_pro_mixer_read(uint16_t addr, void *p)
if (!(addr & 1))
return mixer->index;
return mixer->regs[mixer->index];
switch (mixer->index)
{
case 0x00: case 0x04: case 0x0a: case 0x0c: case 0x0e:
case 0x22: case 0x26: case 0x28: case 0x2e:
return mixer->regs[mixer->index];
}
return 0xff;
}
void sb_16_mixer_write(uint16_t addr, uint8_t val, void *p)
@@ -322,10 +350,10 @@ uint8_t sb_16_mixer_read(uint16_t addr, void *p)
case 0x80:
switch (sb->dsp.sb_irqnum)
{
case 2: return 1; /*IRQ 7*/
case 5: return 2; /*IRQ 7*/
case 2: return 1; /*IRQ 2*/
case 5: return 2; /*IRQ 5*/
case 7: return 4; /*IRQ 7*/
case 10: return 8; /*IRQ 7*/
case 10: return 8; /*IRQ 10*/
}
break;
case 0x81:
@@ -465,7 +493,7 @@ void sb_pro_mcv_write(int port, uint8_t val, void *p)
void *sb_1_init()
{
sb_t *sb = malloc(sizeof(sb_t));
uint16_t addr = device_get_config_int("addr");
uint16_t addr = device_get_config_hex16("base");
memset(sb, 0, sizeof(sb_t));
opl2_init(&sb->opl);
@@ -482,7 +510,7 @@ void *sb_1_init()
void *sb_15_init()
{
sb_t *sb = malloc(sizeof(sb_t));
uint16_t addr = device_get_config_int("addr");
uint16_t addr = device_get_config_hex16("base");
memset(sb, 0, sizeof(sb_t));
opl2_init(&sb->opl);
@@ -517,7 +545,7 @@ void *sb_mcv_init()
void *sb_2_init()
{
sb_t *sb = malloc(sizeof(sb_t));
uint16_t addr = device_get_config_int("addr");
uint16_t addr = device_get_config_hex16("base");
memset(sb, 0, sizeof(sb_t));
opl2_init(&sb->opl);
@@ -535,7 +563,7 @@ void *sb_2_init()
void *sb_pro_v1_init()
{
sb_t *sb = malloc(sizeof(sb_t));
uint16_t addr = device_get_config_int("addr");
uint16_t addr = device_get_config_hex16("base");
memset(sb, 0, sizeof(sb_t));
opl2_init(&sb->opl);
@@ -563,7 +591,7 @@ void *sb_pro_v1_init()
void *sb_pro_v2_init()
{
sb_t *sb = malloc(sizeof(sb_t));
uint16_t addr = device_get_config_int("addr");
uint16_t addr = device_get_config_hex16("base");
memset(sb, 0, sizeof(sb_t));
opl3_init(&sb->opl);
@@ -594,9 +622,6 @@ void *sb_pro_mcv_init()
opl3_init(&sb->opl);
sb_dsp_init(&sb->dsp, SBPRO2);
/*sb_dsp_setaddr(&sb->dsp, addr);
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));*/
sb_mixer_init(&sb->mixer);
io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl);
sound_add_handler(sb_get_buffer_opl3, sb);
@@ -616,7 +641,7 @@ void *sb_pro_mcv_init()
void *sb_16_init()
{
sb_t *sb = malloc(sizeof(sb_t));
uint16_t addr = device_get_config_int("addr");
uint16_t addr = device_get_config_hex16("base");
memset(sb, 0, sizeof(sb_t));
opl3_init(&sb->opl);
@@ -631,7 +656,7 @@ void *sb_16_init()
io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl);
io_sethandler(addr + 4, 0x0002, sb_16_mixer_read, NULL, NULL, sb_16_mixer_write, NULL, NULL, sb);
sound_add_handler(sb_get_buffer_opl3, sb);
mpu401_init(&sb->mpu, device_get_config_int("addr401"), device_get_config_int("irq401"), device_get_config_int("mode401"));
mpu401_init(&sb->mpu, device_get_config_hex16("base401"), device_get_config_int("irq401"), device_get_config_int("mode401"));
sb->mixer.regs[0x30] = 31 << 3;
sb->mixer.regs[0x31] = 31 << 3;
@@ -661,7 +686,7 @@ int sb_awe32_available()
void *sb_awe32_init()
{
sb_t *sb = malloc(sizeof(sb_t));
uint16_t addr = device_get_config_int("addr");
uint16_t addr = device_get_config_hex16("base");
int onboard_ram = device_get_config_int("onboard_ram");
memset(sb, 0, sizeof(sb_t));
@@ -677,7 +702,7 @@ void *sb_awe32_init()
io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl);
io_sethandler(addr + 4, 0x0002, sb_16_mixer_read, NULL, NULL, sb_16_mixer_write, NULL, NULL, sb);
sound_add_handler(sb_get_buffer_emu8k, sb);
mpu401_init(&sb->mpu, device_get_config_int("addr401"), device_get_config_int("irq401"), device_get_config_int("mode401"));
mpu401_init(&sb->mpu, device_get_config_hex16("base401"), device_get_config_int("irq401"), device_get_config_int("mode401"));
emu8k_init(&sb->emu8k, onboard_ram);
sb->mixer.regs[0x30] = 31 << 3;
@@ -733,7 +758,7 @@ void sb_add_status_info(char *s, int max_len, void *p)
static device_config_t sb_config[] =
{
{
"addr", "Address", CONFIG_SELECTION, "", 0x220,
"base", "Address", CONFIG_HEX16, "", 0x220,
{
{
"0x220", 0x220
@@ -826,7 +851,7 @@ static device_config_t sb_mcv_config[] =
static device_config_t sb_pro_config[] =
{
{
"addr", "Address", CONFIG_SELECTION, "", 0x220,
"base", "Address", CONFIG_HEX16, "", 0x220,
{
{
"0x220", 0x220
@@ -881,7 +906,7 @@ static device_config_t sb_pro_config[] =
static device_config_t sb_16_config[] =
{
{
"addr", "Address", CONFIG_SELECTION, "", 0x220,
"base", "Address", CONFIG_HEX16, "", 0x220,
{
{
"0x220", 0x220
@@ -901,7 +926,7 @@ static device_config_t sb_16_config[] =
}
},
{
"addr401", "MPU-401 Address", CONFIG_SELECTION, "", 0x330,
"base401", "MPU-401 Address", CONFIG_HEX16, "", 0x330,
{
{
"0x300", 0x300
@@ -1016,7 +1041,7 @@ static device_config_t sb_16_config[] =
static device_config_t sb_awe32_config[] =
{
{
"addr", "Address", CONFIG_SELECTION, "", 0x220,
"base", "Address", CONFIG_HEX16, "", 0x220,
{
{
"0x220", 0x220
@@ -1036,7 +1061,7 @@ static device_config_t sb_awe32_config[] =
}
},
{
"addr401", "MPU-401 Address", CONFIG_SELECTION, "", 0x330,
"base401", "MPU-401 Address", CONFIG_HEX16, "", 0x330,
{
{
"0x300", 0x300

View File

@@ -1,3 +1,23 @@
/*
* 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.
*
* Sound Blaster emulation.
*
* Version: @(#)sound_sb.h 1.0.0 2017/05/30
*
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* TheCollector1995, <mariogplayer@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016-2017 Miran Grca.
* Copyright 2016-2017 TheCollector1995.
*/
extern device_t sb_1_device;
extern device_t sb_15_device;
extern device_t sb_mcv_device;

View File

@@ -11,6 +11,7 @@
#include "../dma.h"
#include "../win/plat_midi.h" /*YUCK*/
#include "../timer.h"
#include "../device.h"
#include "sound.h"
#include "snd_mpu401.h"
#include "snd_sb_dsp.h"
@@ -514,6 +515,10 @@ void sb_exec_command(sb_dsp_t *dsp)
if (dsp->sb_type < SB16) break;
sb_add_data(dsp, dsp->sb_asp_regs[dsp->sb_data[0]]);
break;
case 0xF8:
if (dsp->sb_type >= SB16) break;
sb_add_data(dsp, 0);
break;
case 0xF9:
if (dsp->sb_type < SB16) break;
if (dsp->sb_data[0] == 0x0e) sb_add_data(dsp, 0xff);

View File

@@ -8,6 +8,9 @@ int speaker_gated = 0;
int speaker_enable = 0, was_speaker_enable = 0;
int gated,speakval,speakon;
static int16_t speaker_buffer[SOUNDBUFLEN];
static int speaker_pos = 0;

View File

@@ -1,16 +1,35 @@
/*
* 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.
*
* Sound emulation core.
*
* Version: @(#)sound.c 1.0.1 2017/06/04
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016-2017 Miran Grca.
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "../ibm.h"
#include "../device.h"
#include "../timer.h"
#include "../thread.h"
#include "../cdrom.h"
#include "../win/plat_thread.h"
#include "sound.h"
#include "snd_opl.h"
#include "snd_adlib.h"
#include "snd_adlibgold.h"
#if 0
#include "snd_pas16.h"
#endif
#include "snd_sb.h"
#include "snd_sb_dsp.h"
#include "snd_wss.h"
@@ -30,24 +49,27 @@ typedef struct
static SOUND_CARD sound_cards[] =
{
{"None", "none", NULL},
{"Adlib", "adlib", &adlib_device},
{"Adlib MCA", "adlib_mca", &adlib_mca_device},
{"Sound Blaster 1.0", "sb", &sb_1_device},
{"Sound Blaster 1.5", "sb1.5", &sb_15_device},
{"Sound Blaster MCV", "sbmcv", &sb_mcv_device},
{"Sound Blaster 2.0", "sb2.0", &sb_2_device},
{"Sound Blaster Pro v1", "sbprov1", &sb_pro_v1_device},
{"Sound Blaster Pro v2", "sbprov2", &sb_pro_v2_device},
{"Sound Blaster Pro MCV", "sbpromcv", &sb_pro_mcv_device},
{"Sound Blaster 16", "sb16", &sb_16_device},
{"Sound Blaster AWE32", "sbawe32", &sb_awe32_device},
{"Adlib Gold", "adlibgold", &adgold_device},
{"Windows Sound System", "wss", &wss_device},
{"Pro Audio Spectrum 16", "pas16", &pas16_device},
{"", "", NULL}
{ "None", "none", NULL },
{ "Adlib", "adlib", &adlib_device },
{ "Adlib MCA", "adlib_mca", &adlib_mca_device },
{ "Sound Blaster 1.0", "sb", &sb_1_device },
{ "Sound Blaster 1.5", "sb1.5", &sb_15_device },
{ "Sound Blaster MCV", "sbmcv", &sb_mcv_device },
{ "Sound Blaster 2.0", "sb2.0", &sb_2_device },
{ "Sound Blaster Pro v1", "sbprov1", &sb_pro_v1_device },
{ "Sound Blaster Pro v2", "sbprov2", &sb_pro_v2_device },
{ "Sound Blaster Pro MCV", "sbpromcv", &sb_pro_mcv_device },
{ "Sound Blaster 16", "sb16", &sb_16_device },
{ "Sound Blaster AWE32", "sbawe32", &sb_awe32_device },
{ "Adlib Gold", "adlibgold", &adgold_device },
{ "Windows Sound System", "wss", &wss_device },
#if 0
{ "Pro Audio Spectrum 16", "pas16", &pas16_device },
#endif
{ "", "", NULL }
};
int sound_card_available(int card)
{
if (sound_cards[card].device)
@@ -92,7 +114,7 @@ int sound_card_get_from_internal_name(char *s)
return 0;
}
void sound_card_init()
void sound_card_init(void)
{
if (sound_cards[sound_card_current].device)
device_add(sound_cards[sound_card_current].device);
@@ -215,7 +237,7 @@ static float *outbuffer_ex;
static int cd_thread_enable = 0;
void sound_init()
void sound_init(void)
{
int i = 0;
int available_cdrom_drives = 0;
@@ -228,7 +250,7 @@ void sound_init()
for (i = 0; i < CDROM_NUM; i++)
{
if (cdrom_drives[i].bus_type && cdrom_drives[i].sound_on)
if (cdrom_drives[i].bus_type != CDROM_BUS_DISABLED)
{
available_cdrom_drives++;
}
@@ -286,12 +308,12 @@ void sound_poll(void *priv)
}
}
void sound_speed_changed()
void sound_speed_changed(void)
{
sound_poll_latch = (int)((double)TIMER_USEC * (1000000.0 / 48000.0));
}
void sound_reset()
void sound_reset(void)
{
int i = 0;
@@ -310,14 +332,14 @@ void sound_reset()
}
}
void sound_cd_thread_reset()
void sound_cd_thread_reset(void)
{
int i = 0;
int available_cdrom_drives = 0;
for (i = 0; i < CDROM_NUM; i++)
{
if (cdrom_drives[i].bus_type && cdrom_drives[i].sound_on)
if (cdrom_drives[i].bus_type != CDROM_BUS_DISABLED)
{
available_cdrom_drives++;
}

View File

@@ -1,3 +1,21 @@
/*
* 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.
*
* Sound emulation core.
*
* Version: @(#)sound.h 1.0.0 2017/05/30
*
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016-2017 Miran Grca.
*/
void sound_add_handler(void (*get_buffer)(int32_t *buffer, int len, void *p), void *p);
extern int sound_card_current;

View File

@@ -1,12 +1,28 @@
/*ATI Mach64 emulation*/
/*
* 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.
*
* ATi Mach64 graphics card emulation.
*
* Version: @(#)vid_ati_mach64.c 1.0.1 2017/06/04
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016-2017 Miran Grca.
*/
#include <stdlib.h>
#include "../ibm.h"
#include "../device.h"
#include "../io.h"
#include "../mem.h"
#include "../pci.h"
#include "../rom.h"
#include "../thread.h"
#include "../device.h"
#include "../win/plat_thread.h"
#include "video.h"
#include "vid_svga.h"
#include "vid_svga_render.h"
@@ -14,6 +30,9 @@
#include "vid_ati_eeprom.h"
#include "vid_ics2595.h"
#ifdef CLAMP
#undef CLAMP
#endif
#define FIFO_SIZE 65536
#define FIFO_MASK (FIFO_SIZE - 1)
@@ -62,10 +81,12 @@ typedef struct mach64_t
uint8_t regs[256];
int index;
int type;
int type;
uint8_t pci_regs[256];
uint8_t int_line;
int card;
int bank_r[2];
int bank_w[2];
@@ -192,6 +213,7 @@ typedef struct mach64_t
uint16_t pci_id;
uint32_t config_chip_id;
uint32_t block_decoded_io;
int use_block_decoded_io;
int pll_addr;
uint8_t pll_regs[16];
@@ -466,7 +488,7 @@ void mach64_updatemapping(mach64_t *mach64)
if (!(mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM))
{
pclog("Update mapping - PCI disabled\n");
/* pclog("Update mapping - PCI disabled\n"); */
mem_mapping_disable(&svga->mapping);
mem_mapping_disable(&mach64->linear_mapping);
mem_mapping_disable(&mach64->mmio_mapping);
@@ -481,7 +503,7 @@ void mach64_updatemapping(mach64_t *mach64)
case 0x0: /*128k at A0000*/
mem_mapping_set_handler(&mach64->svga.mapping, mach64_read, NULL, NULL, mach64_write, NULL, NULL);
mem_mapping_set_p(&mach64->svga.mapping, mach64);
mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x1fc00);
mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000);
mem_mapping_enable(&mach64->mmio_mapping);
svga->banked_mask = 0xffff;
break;
@@ -500,37 +522,35 @@ void mach64_updatemapping(mach64_t *mach64)
case 0xC: /*32k at B8000*/
mem_mapping_set_handler(&mach64->svga.mapping, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel);
mem_mapping_set_p(&mach64->svga.mapping, svga);
mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x07c00);
mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000);
svga->banked_mask = 0x7fff;
break;
}
if (mach64->linear_base)
{
if (mach64->type == MACH64_GX)
{
if ((mach64->config_cntl & 3) == 2)
{
/*8 MB aperture*/
pclog("8 MB aperture\n");
mem_mapping_set_addr(&mach64->linear_mapping, mach64->linear_base, 0x007FFC00);
mem_mapping_set_addr(&mach64->mmio_linear_mapping, mach64->linear_base + 0x007FFC00, 0x400);
}
else
{
/*4 MB aperture*/
pclog("4 MB aperture\n");
mem_mapping_set_addr(&mach64->linear_mapping, mach64->linear_base, 0x003FFC00);
mem_mapping_set_addr(&mach64->mmio_linear_mapping, mach64->linear_base + 0x003FFC00, 0x400);
}
svga->linear_base = mach64->linear_base;
}
else
{
if (mach64->type == MACH64_GX)
{
if ((mach64->config_cntl & 3) == 2)
{
/*8 MB aperture*/
mem_mapping_set_addr(&mach64->linear_mapping, mach64->linear_base, (8 << 20) - 0x4000);
mem_mapping_set_addr(&mach64->mmio_linear_mapping, mach64->linear_base + ((8 << 20) - 0x4000), 0x4000);
}
else
{
/*4 MB aperture*/
mem_mapping_set_addr(&mach64->linear_mapping, mach64->linear_base, (4 << 20) - 0x4000);
mem_mapping_set_addr(&mach64->mmio_linear_mapping, mach64->linear_base + ((4 << 20) - 0x4000), 0x4000);
}
}
else
{
/*2*8 MB aperture*/
mem_mapping_set_addr(&mach64->linear_mapping, mach64->linear_base, (8 << 20) - 0x4000);
mem_mapping_set_addr(&mach64->mmio_linear_mapping, mach64->linear_base + ((8 << 20) - 0x4000), 0x4000);
mem_mapping_set_addr(&mach64->mmio_linear_mapping_2, mach64->linear_base + ((16 << 20) - 0x4000), 0x4000);
}
}
svga->linear_base = mach64->linear_base;
}
else
{
@@ -540,6 +560,14 @@ void mach64_updatemapping(mach64_t *mach64)
}
}
static void mach64_update_irqs(mach64_t *mach64)
{
if ((mach64->crtc_int_cntl & 0xaa0024) & ((mach64->crtc_int_cntl << 1) & 0xaa0024))
pci_set_irq(mach64->card, PCI_INTA);
else
pci_clear_irq(mach64->card, PCI_INTA);
}
static __inline void wake_fifo_thread(mach64_t *mach64)
{
thread_set_event(mach64->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/
@@ -594,8 +622,8 @@ static void mach64_accel_write_fifo(mach64_t *mach64, uint32_t addr, uint8_t val
case 0x11e: case 0x11f:
WRITE8(addr, mach64->dst_height_width, val);
case 0x113:
if (((addr & 0x3ff) == 0x11b) || ((addr & 0x3ff) == 0x11f) ||
(((addr & 0x3ff) == 0x113) && !(val & 0x80)))
if (((addr & 0x3ff) == 0x11b || (addr & 0x3ff) == 0x11f ||
(addr & 0x3ff) == 0x113) && !(val & 0x80))
{
mach64_start_fill(mach64);
#ifdef MACH64_DEBUG
@@ -837,10 +865,6 @@ static void mach64_accel_write_fifo_l(mach64_t *mach64, uint32_t addr, uint32_t
static void fifo_thread(void *param)
{
mach64_t *mach64 = (mach64_t *)param;
fifo_entry_t *fifo;
uint64_t start_time = 0;
uint64_t end_time = 0;
while (1)
{
@@ -850,8 +874,9 @@ static void fifo_thread(void *param)
mach64->blitter_busy = 1;
while (!FIFO_EMPTY)
{
start_time = timer_read();
fifo = &mach64->fifo[mach64->fifo_read_idx & FIFO_MASK];
uint64_t start_time = timer_read();
uint64_t end_time;
fifo_entry_t *fifo = &mach64->fifo[mach64->fifo_read_idx & FIFO_MASK];
switch (fifo->addr_type & FIFO_TYPE)
{
@@ -903,8 +928,7 @@ static void mach64_queue(mach64_t *mach64, uint32_t addr, uint32_t val, uint32_t
void mach64_cursor_dump(mach64_t *mach64)
{
/* pclog("Mach64 cursor :\n");
pclog("Ena = %i X = %i Y = %i Addr = %05X Xoff = %i Yoff = %i\n", svga->hwcursor.ena, svga->hwcursor.x, svga->hwcursor.y, svga->hwcursor.addr, svga->hwcursor.xoff, svga->hwcursor.yoff);*/
return;
}
void mach64_start_fill(mach64_t *mach64)
@@ -967,7 +991,7 @@ void mach64_start_fill(mach64_t *mach64)
mach64->accel.dst_size = mach64_width[mach64->accel.dst_pix_width];
mach64->accel.src_size = mach64_width[mach64->accel.src_pix_width];
mach64->accel.host_size = mach64_width[mach64->accel.host_pix_width];
if (mach64->accel.src_size == WIDTH_1BIT)
mach64->accel.src_offset <<= 3;
else
@@ -978,11 +1002,12 @@ void mach64_start_fill(mach64_t *mach64)
else
mach64->accel.dst_offset >>= mach64->accel.dst_size;
mach64->accel.xinc = (mach64->dst_cntl & DST_X_DIR) ? 1 : -1;
mach64->accel.yinc = (mach64->dst_cntl & DST_Y_DIR) ? 1 : -1;
mach64->accel.xinc = (mach64->dst_cntl & DST_X_DIR) ? 1 : -1;
mach64->accel.yinc = (mach64->dst_cntl & DST_Y_DIR) ? 1 : -1;
mach64->accel.source_host = ((mach64->dp_src & 7) == SRC_HOST) || (((mach64->dp_src >> 8) & 7) == SRC_HOST);
for (y = 0; y < 8; y++)
{
for (x = 0; x < 8; x++)
@@ -996,6 +1021,9 @@ void mach64_start_fill(mach64_t *mach64)
mach64->accel.sc_right = (mach64->sc_left_right >> 16) & 0x1fff;
mach64->accel.sc_top = mach64->sc_top_bottom & 0x7fff;
mach64->accel.sc_bottom = (mach64->sc_top_bottom >> 16) & 0x7fff;
/* mach64->accel.sc_left *= mach64_inc[mach64->accel.dst_pix_width];
mach64->accel.sc_right *= mach64_inc[mach64->accel.dst_pix_width];*/
mach64->accel.dp_frgd_clr = mach64->dp_frgd_clr;
mach64->accel.dp_bkgd_clr = mach64->dp_bkgd_clr;
@@ -1159,8 +1187,8 @@ void mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64)
while (count)
{
uint32_t src_dat, dest_dat;
uint32_t host_dat;
int mix;
uint32_t host_dat = 0;
int mix = 0;
int dst_x = (mach64->accel.dst_x + mach64->accel.dst_x_start) & 0xfff;
int dst_y = (mach64->accel.dst_y + mach64->accel.dst_y_start) & 0xfff;
int src_x;
@@ -1363,9 +1391,9 @@ void mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64)
case OP_LINE:
while (count)
{
uint32_t src_dat, dest_dat;
uint32_t host_dat;
int mix;
uint32_t src_dat = 0, dest_dat;
uint32_t host_dat = 0;
int mix = 0;
int draw_pixel = !(mach64->dst_cntl & DST_POLYGON_EN);
if (mach64->accel.source_host)
@@ -1440,7 +1468,7 @@ void mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64)
}
READ(mach64->accel.dst_offset + (mach64->accel.dst_y * mach64->accel.dst_pitch) + mach64->accel.dst_x, dest_dat, mach64->accel.dst_size);
switch (mach64->accel.clr_cmp_fn)
{
case 1: /*TRUE*/
@@ -1611,18 +1639,18 @@ static void pll_write(mach64_t *mach64, uint32_t addr, uint8_t val)
break;
case 2: /*Data*/
mach64->pll_regs[mach64->pll_addr] = val;
pclog("pll_write %02x,%02x\n", mach64->pll_addr, val);
/* pclog("pll_write %02x,%02x\n", mach64->pll_addr, val); */
for (c = 0; c < 4; c++)
for (c = 0; c < 4; c++)
{
double m = (double)mach64->pll_regs[PLL_REF_DIV];
double n = (double)mach64->pll_regs[VCLK0_FB_DIV+c];
double r = 14318184.0;
double p = (double)(1 << ((mach64->pll_regs[VCLK_POST_DIV] >> (c*2)) & 3));
pclog("PLLfreq %i = %g %g m=%02x n=%02x p=%02x\n", c, (2.0 * r * n) / (m * p), p, mach64->pll_regs[PLL_REF_DIV], mach64->pll_regs[VCLK0_FB_DIV+c], mach64->pll_regs[VCLK_POST_DIV]);
/* pclog("PLLfreq %i = %g %g m=%02x n=%02x p=%02x\n", c, (2.0 * r * n) / (m * p), p, mach64->pll_regs[PLL_REF_DIV], mach64->pll_regs[VCLK0_FB_DIV+c], mach64->pll_regs[VCLK_POST_DIV]); */
mach64->pll_freq[c] = (2.0 * r * n) / (m * p);
pclog(" %g\n", mach64->pll_freq[c]);
/* pclog(" %g\n", mach64->pll_freq[c]); */
}
break;
}
@@ -1633,8 +1661,9 @@ static void mach64_vblank_start(svga_t *svga)
{
mach64_t *mach64 = (mach64_t *)svga->p;
int overlay_cmp_mix = (mach64->overlay_key_cntl >> 8) & 0xf;
mach64->crtc_int_cntl |= 4;
mach64_update_irqs(mach64);
svga->overlay.x = (mach64->overlay_y_x_start >> 16) & 0x7ff;
svga->overlay.y = mach64->overlay_y_x_start & 0x7ff;
@@ -1657,7 +1686,10 @@ uint8_t mach64_ext_readb(uint32_t addr, void *p)
uint8_t ret;
if (!(addr & 0x400))
{
switch (addr & 0x3ff)
#ifdef MACH64_DEBUG
pclog("nmach64_ext_readb: addr=%04x %04x(%08x):%08x\n", addr, CS, cs, cpu_state.pc);
#endif
switch (addr & 0x3ff)
{
case 0x00: case 0x01: case 0x02: case 0x03:
READ8(addr, mach64->overlay_y_x_start);
@@ -1756,6 +1788,10 @@ uint8_t mach64_ext_readb(uint32_t addr, void *p)
READ8(addr, mach64->cur_horz_vert_off);
break;
case 0x79:
ret = 0x30;
break;
case 0x80: case 0x81: case 0x82: case 0x83:
READ8(addr, mach64->scratch_reg0);
break;
@@ -1763,10 +1799,6 @@ uint8_t mach64_ext_readb(uint32_t addr, void *p)
READ8(addr, mach64->scratch_reg1);
break;
case 0x79:
ret = 0x30;
break;
case 0x90: case 0x91: case 0x92: case 0x93:
READ8(addr, mach64->clock_cntl);
break;
@@ -2056,7 +2088,10 @@ uint32_t mach64_ext_readl(uint32_t addr, void *p)
uint32_t ret;
if (!(addr & 0x400))
{
ret = 0xffffffff;
#ifdef MACH64_DEBUG
pclog("nmach64_ext_readl: addr=%04x %04x(%08x):%08x\n", addr, CS, cs, cpu_state.pc);
#endif
ret = 0xffffffff;
}
else switch (addr & 0x3ff)
{
@@ -2186,6 +2221,7 @@ void mach64_ext_writeb(uint32_t addr, uint8_t val, void *p)
mach64->crtc_int_cntl = (mach64->crtc_int_cntl & 0x75) | (val & ~0x75);
if (val & 4)
mach64->crtc_int_cntl &= ~4;
mach64_update_irqs(mach64);
break;
case 0x1c: case 0x1d: case 0x1e: case 0x1f:
@@ -2492,6 +2528,7 @@ uint8_t mach64_ext_inb(uint16_t port, void *p)
case 0x72ec: case 0x72ed: case 0x72ee: case 0x72ef:
ret = mach64_ext_readb(0x400 | 0xe4 | (port & 3), p);
break;
default:
ret = 0;
@@ -2678,7 +2715,7 @@ void mach64_ext_outw(uint16_t port, uint16_t val, void *p)
}
void mach64_ext_outl(uint16_t port, uint32_t val, void *p)
{
pclog("mach64_ext_outl : port %04X val %08X\n", port, val);
/* pclog("mach64_ext_outl : port %04X val %08X\n", port, val); */
switch (port)
{
default:
@@ -2980,7 +3017,7 @@ void mach64_overlay_draw(svga_t *svga, int displine)
break;
default:
pclog("Unknown Mach64 scaler format %x\n", mach64->scaler_format);
/* pclog("Unknown Mach64 scaler format %x\n", mach64->scaler_format); */
/*Fill buffer with something recognisably wrong*/
for (x = 0; x < mach64->svga.overlay_latch.xsize; x++)
mach64->overlay_dat[x] = 0xff00ff;
@@ -3097,17 +3134,20 @@ static void mach64_io_set(mach64_t *mach64)
io_sethandler(0x03c0, 0x0020, mach64_in, NULL, NULL, mach64_out, NULL, NULL, mach64);
for (c = 0; c < 8; c++)
if (!mach64->use_block_decoded_io)
{
io_sethandler((c * 0x1000) + 0x2ec, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64);
io_sethandler((c * 0x1000) + 0x6ec, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64);
io_sethandler((c * 0x1000) + 0xaec, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64);
io_sethandler((c * 0x1000) + 0xeec, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64);
for (c = 0; c < 8; c++)
{
io_sethandler((c * 0x1000) + 0x2ec, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64);
io_sethandler((c * 0x1000) + 0x6ec, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64);
io_sethandler((c * 0x1000) + 0xaec, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64);
io_sethandler((c * 0x1000) + 0xeec, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64);
}
}
io_sethandler(0x01ce, 0x0002, mach64_in, NULL, NULL, mach64_out, NULL, NULL, mach64);
if (mach64->block_decoded_io && mach64->block_decoded_io < 0x10000)
if (mach64->use_block_decoded_io && mach64->block_decoded_io && mach64->block_decoded_io < 0x10000)
io_sethandler(mach64->block_decoded_io, 0x0400, mach64_block_inb, mach64_block_inw, mach64_block_inl, mach64_block_outb, mach64_block_outw, mach64_block_outl, mach64);
}
@@ -3135,12 +3175,12 @@ uint8_t mach64_pci_read(int func, int addr, void *p)
case 0x09: return 0; /*Programming interface*/
case 0x0a: return 0x00;
case 0x0a: return 0x01; /*Supports VGA interface, XGA compatible*/
case 0x0b: return 0x03;
case 0x10: return 0x00; /*Linear frame buffer address*/
case 0x11: return 0x00;
case 0x12: return 0x00;
case 0x12: return mach64->linear_base >> 16;
case 0x13: return mach64->linear_base >> 24;
case 0x14: return 0x01; /*Block decoded IO address*/
@@ -3152,39 +3192,38 @@ uint8_t mach64_pci_read(int func, int addr, void *p)
case 0x31: return 0x00;
case 0x32: return mach64->pci_regs[0x32];
case 0x33: return mach64->pci_regs[0x33];
case 0x3c: return mach64->int_line;
case 0x3d: return PCI_INTA;
case 0x40: return mach64->use_block_decoded_io;
}
return 0;
}
uint32_t bios_base = 0x000c0000;
void mach64_pci_write(int func, int addr, uint8_t val, void *p)
{
mach64_t *mach64 = (mach64_t *)p;
switch (addr)
{
case PCI_REG_COMMAND:
mach64->pci_regs[PCI_REG_COMMAND] = val & 0x27;
if (val & PCI_COMMAND_IO)
mach64_io_set(mach64);
else
mach64_io_remove(mach64);
mach64_updatemapping(mach64);
break;
case 0x12:
if (mach64->type == MACH64_VT2)
val = 0;
break;
/* case 0x12:
case 0x12:
if (mach64->type == MACH64_VT2)
val = 0;
mach64->linear_base = (mach64->linear_base & 0xff000000) | ((val & 0x80) << 16);
mach64_updatemapping(mach64);
break; */
break;
case 0x13:
mach64->linear_base = (val << 24);
mach64->linear_base = (mach64->linear_base & 0x800000) | (val << 24);
mach64_updatemapping(mach64);
break;
@@ -3224,16 +3263,30 @@ void mach64_pci_write(int func, int addr, uint8_t val, void *p)
if (mach64->pci_regs[0x30] & 0x01)
{
uint32_t addr = (mach64->pci_regs[0x32] << 16) | (mach64->pci_regs[0x33] << 24);
bios_base = addr;
pclog("Mach64 bios_rom enabled at %08x\n", addr);
/* pclog("Mach64 bios_rom enabled at %08x\n", addr); */
mem_mapping_set_addr(&mach64->bios_rom.mapping, addr, 0x8000);
}
else
{
pclog("Mach64 bios_rom disabled\n");
/* pclog("Mach64 bios_rom disabled\n"); */
mem_mapping_disable(&mach64->bios_rom.mapping);
}
return;
case 0x3c:
mach64->int_line = val;
break;
case 0x40:
if (mach64->type == MACH64_VT2)
{
if (mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO)
mach64_io_remove(mach64);
mach64->use_block_decoded_io = val & 0x04;
if (mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO)
mach64_io_set(mach64);
}
break;
}
}
@@ -3262,7 +3315,7 @@ static void *mach64_common_init()
mach64_io_set(mach64);
pci_add(mach64_pci_read, mach64_pci_write, mach64);
mach64->card = pci_add(mach64_pci_read, mach64_pci_write, mach64);
mach64->pci_regs[PCI_REG_COMMAND] = 3;
mach64->pci_regs[0x30] = 0x00;
@@ -3270,7 +3323,7 @@ static void *mach64_common_init()
mach64->pci_regs[0x33] = 0x00;
ati68860_ramdac_init(&mach64->ramdac);
mach64->dst_cntl = 3;
mach64->wake_fifo_thread = thread_create_event();
@@ -3310,7 +3363,8 @@ static void *mach64vt2_init()
mach64->config_chip_id = 0x40005654;
mach64->dac_cntl = 1 << 16; /*Internal 24-bit DAC*/
mach64->config_stat0 = 4;
mach64->use_block_decoded_io = PCI ? 4 : 0;
ati_eeprom_load(&mach64->eeprom, L"mach64vt.nvr", 1);
rom_init(&mach64->bios_rom, L"roms/atimach64vt2pci.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
@@ -3324,7 +3378,6 @@ int mach64gx_available()
{
return rom_present(L"roms/mach64gx/bios.bin");
}
int mach64vt2_available()
{
return rom_present(L"roms/atimach64vt2pci.bin");
@@ -3462,7 +3515,6 @@ device_t mach64gx_device =
mach64_add_status_info,
mach64gx_config
};
device_t mach64vt2_device =
{
"ATI Mach64VT2",

View File

@@ -1,2 +1,20 @@
/*
* 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.
*
* ATi Mach64 graphics card emulation.
*
* Version: @(#)vid_ati_mach64.h 1.0.0 2017/05/30
*
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016-2017 Miran Grca.
*/
extern device_t mach64gx_device;
extern device_t mach64vt2_device;

View File

@@ -1,6 +1,21 @@
/* Copyright holders: Sarah Walker, Tenshi
see COPYING for more details
*/
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Emulation of the old and new IBM CGA graphics cards.
*
* Version: @(#)vid_cga.c 1.0.0 2017/05/30
*
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016-2017 Miran Grca.
*/
/*CGA emulation*/
#include <stdlib.h>
#include <math.h>
@@ -62,10 +77,6 @@ void cga_out(uint16_t addr, uint8_t val, void *p)
if ((cga->cgamode ^ val) & 1)
{
cga_palette = (cga->rgb_type << 1);
if (!(val & 1) && (cga_palette > 0) && (cga_palette < 8))
{
cga_palette--;
}
cgapal_rebuild();
}
#endif

View File

@@ -1,6 +1,21 @@
/* Copyright holders: Sarah Walker, Tenshi
see COPYING for more details
*/
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Emulation of the old and new IBM CGA graphics cards.
*
* Version: @(#)vid_cga.h 1.0.0 2017/05/30
*
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016-2017 Miran Grca.
*/
typedef struct cga_t
{
mem_mapping_t mapping;

View File

@@ -1,5 +1,21 @@
/* Code borrowed from DOSBox and adapted by OBattler.
Original author: reenigne. */
/*
* 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.
*
* IBM CGA composite filter, borrowed from reenigne's DOSBox
* patch and ported to C.
*
* Version: @(#)vid_cga.c 1.0.0 2017/05/30
*
* Author: reenigne,
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2015-2017 reenigne.
* Copyright 2015-2017 Miran Grca.
*/
#include <stdlib.h>
#include <stdint.h>

View File

@@ -1,3 +1,22 @@
/*
* 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.
*
* IBM CGA composite filter, borrowed from reenigne's DOSBox
* patch and ported to C.
*
* Version: @(#)vid_cga.h 1.0.0 2017/05/30
*
* Author: reenigne,
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2015-2017 reenigne.
* Copyright 2015-2017 Miran Grca.
*/
#define Bit8u uint8_t
#define Bit32u uint32_t
#define Bitu unsigned int

View File

@@ -1,4 +1,25 @@
/*EGA emulation*/
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Emulation of the EGA, Chips & Technologies SuperEGA, and
* AX JEGA graphics cards.
*
* Version: @(#)vid_ega.c 1.0.1 2017/06/01
*
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* akm,
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016-2017 Miran Grca.
* Copyright 2017-2017 akm.
*/
#include <stdint.h>
#include <stdlib.h>
#include "../ibm.h"
#include "../io.h"
@@ -8,6 +29,7 @@
#include "../device.h"
#include "video.h"
#include "vid_ega.h"
#include "vid_ega_render.h"
extern uint8_t edatlookup[4][4];
@@ -23,11 +45,111 @@ static int old_overscan_color = 0;
int update_overscan = 0;
#define SBCS 0
#define DBCS 1
#define ID_LEN 6
#define NAME_LEN 8
#define SBCS19_LEN 256 * 19
#define DBCS16_LEN 65536 * 32
uint8_t jfont_sbcs_19[SBCS19_LEN];//256 * 19( * 8)
uint8_t jfont_dbcs_16[DBCS16_LEN];//65536 * 16 * 2 (* 8)
typedef struct {
char id[ID_LEN];
char name[NAME_LEN];
unsigned char width;
unsigned char height;
unsigned char type;
} fontx_h;
typedef struct {
uint16_t start;
uint16_t end;
} fontxTbl;
void ega_jega_write_font(ega_t *ega)
{
unsigned int chr = ega->RDFFB;
unsigned int chr_2 = ega->RDFSB;
ega->RSTAT &= ~0x02;
/* Check if the character code is in the Wide character set of Shift-JIS */
if (((chr >= 0x40) && (chr <= 0x7e)) || ((chr >= 0x80) && (chr <= 0xfc)))
{
if (ega->font_index >= 32)
{
ega->font_index = 0;
}
chr <<= 8;
/* Fix vertical character position */
chr |= chr_2;
if (ega->font_index < 16)
{
jfont_dbcs_16[(chr * 32) + (ega->font_index * 2)] = ega->RDFAP; /* 16x16 font */
}
else
{
jfont_dbcs_16[(chr * 32) + ((ega->font_index - 16) * 2) + 1] = ega->RDFAP; /* 16x16 font */
}
}
else
{
if (ega->font_index >= 19)
{
ega->font_index = 0;
}
jfont_sbcs_19[(chr * 19) + ega->font_index] = ega->RDFAP; /* 8x19 font */
}
ega->font_index++;
ega->RSTAT |= 0x02;
}
void ega_jega_read_font(ega_t *ega)
{
unsigned int chr = ega->RDFFB;
unsigned int chr_2 = ega->RDFSB;
ega->RSTAT &= ~0x02;
/* Check if the character code is in the Wide character set of Shift-JIS */
if (((chr >= 0x40) && (chr <= 0x7e)) || ((chr >= 0x80) && (chr <= 0xfc)))
{
if (ega->font_index >= 32)
{
ega->font_index = 0;
}
chr <<= 8;
/* Fix vertical character position */
chr |= chr_2;
if (ega->font_index < 16)
{
ega->RDFAP = jfont_dbcs_16[(chr * 32) + (ega->font_index * 2)]; /* 16x16 font */
}
else
{
ega->RDFAP = jfont_dbcs_16[(chr * 32) + ((ega->font_index - 16) * 2) + 1]; /* 16x16 font */
}
}
else
{
if (ega->font_index >= 19)
{
ega->font_index = 0;
}
ega->RDFAP = jfont_sbcs_19[(chr * 19) + ega->font_index]; /* 8x19 font */
}
ega->font_index++;
ega->RSTAT |= 0x02;
}
void ega_out(uint16_t addr, uint8_t val, void *p)
{
ega_t *ega = (ega_t *)p;
int c;
uint8_t o, old;
uint8_t crtcreg;
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(ega->miscout & 1))
addr ^= 0x60;
@@ -130,21 +252,82 @@ void ega_out(uint16_t addr, uint8_t val, void *p)
break;
case 0x3d0:
case 0x3d4:
ega->crtcreg = val & 31;
ega->crtcreg = val;
return;
case 0x3d1:
case 0x3d5:
if (ega->crtcreg <= 7 && ega->crtc[0x11] & 0x80) return;
old = ega->crtc[ega->crtcreg];
ega->crtc[ega->crtcreg] = val;
if (old != val)
{
if (ega->crtcreg < 0xe || ega->crtcreg > 0x10)
{
fullchange = changeframecount;
ega_recalctimings(ega);
}
}
if ((ega->crtcreg < 0xb9) || !ega->is_jega)
{
crtcreg = ega->crtcreg & 0x1f;
if (crtcreg <= 7 && ega->crtc[0x11] & 0x80) return;
old = ega->crtc[crtcreg];
ega->crtc[crtcreg] = val;
if (old != val)
{
if (crtcreg < 0xe || crtcreg > 0x10)
{
fullchange = changeframecount;
ega_recalctimings(ega);
}
}
}
else
{
switch(ega->crtcreg)
{
case 0xb9: /* Mode register 1 */
ega->RMOD1 = val;
break;
case 0xba: /* Mode register 2 */
ega->RMOD2 = val;
break;
case 0xbb: /* ANK Group sel */
ega->RDAGS = val;
break;
case 0xbc: /* Font access first byte */
if (ega->RDFFB != val)
{
ega->RDFFB = val;
ega->font_index = 0;
}
break;
case 0xbd: /* Font access Second Byte */
if (ega->RDFSB != val)
{
ega->RDFSB = val;
ega->font_index = 0;
}
break;
case 0xbe: /* Font Access Pattern */
ega->RDFAP = val;
ega_jega_write_font(ega);
break;
case 0xdb:
ega->RPSSC = val;
break;
case 0xd9:
ega->RPSSU = val;
break;
case 0xda:
ega->RPSSL = val;
break;
case 0xdc: /* Superimposed mode (only AX-2 system, not implemented) */
ega->RPPAJ = val;
break;
case 0xdd:
ega->RCMOD = val;
break;
case 0xde: /* Cursor Skew control */
ega->RCSKW = val;
break;
case 0xdf: /* Font R/W register */
ega->RSTAT = val;
break;
default:
pclog("JEGA: Write to illegal index %02X\n", ega->crtcreg);
break;
}
}
break;
}
}
@@ -174,6 +357,7 @@ static uint8_t ega_get_input_status_0(ega_t *ega)
uint8_t ega_in(uint16_t addr, void *p)
{
ega_t *ega = (ega_t *)p;
int crtcreg;
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(ega->miscout & 1))
addr ^= 0x60;
@@ -204,7 +388,49 @@ uint8_t ega_in(uint16_t addr, void *p)
return ega->crtcreg;
case 0x3d1:
case 0x3d5:
return ega->crtc[ega->crtcreg];
if ((ega->crtcreg < 0xb9) || !ega->is_jega)
{
crtcreg = ega->crtcreg & 0x1f;
return ega->crtc[crtcreg];
}
else
{
switch(ega->crtcreg)
{
case 0xb9:
return ega->RMOD1;
case 0xba:
return ega->RMOD2;
case 0xbb:
return ega->RDAGS;
case 0xbc: /* BCh RDFFB Font access First Byte */
return ega->RDFFB;
case 0xbd: /* BDh RDFFB Font access Second Byte */
return ega->RDFSB;
case 0xbe: /* BEh RDFAP Font Access Pattern */
ega_jega_read_font(ega);
return ega->RDFAP;
case 0xdb:
return ega->RPSSC;
case 0xd9:
return ega->RPSSU;
case 0xda:
return ega->RPSSL;
case 0xdc:
return ega->RPPAJ;
case 0xdd:
return ega->RCMOD;
case 0xde:
return ega->RCSKW;
case 0xdf:
return ega->ROMSL;
case 0xbf:
return 0x03; /* The font is always readable and writable */
default:
pclog("JEGA: Read from illegal index %02X\n", ega->crtcreg);
return 0x00;
}
}
case 0x3da:
ega->attrff = 0;
ega->stat ^= 0x30; /*Fools IBM EGA video BIOS self-test*/
@@ -270,28 +496,10 @@ void ega_recalctimings(ega_t *ega)
ega->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT));
}
int ega_display_line(ega_t *ega)
{
int y_add = (enable_overscan) ? (overscan_y >> 1) : 0;
unsigned int dl = ega->displine;
if (ega->crtc[9] & 0x1f)
{
dl -= (ega->crtc[8] & 0x1f);
}
dl += y_add;
dl &= 0x7ff;
return dl;
}
void ega_poll(void *p)
{
ega_t *ega = (ega_t *)p;
uint8_t chr, dat, attr;
uint32_t charaddr;
int x, xx;
uint32_t fg, bg;
int offset;
uint8_t edat[4];
int x;
int drawcursor = 0;
int y_add = enable_overscan ? (overscan_y >> 1) : 0;
int x_add = enable_overscan ? 8 : 0;
@@ -299,7 +507,6 @@ void ega_poll(void *p)
int x_add_ex = enable_overscan ? 16 : 0;
uint32_t *q, i, j;
int wx = 640, wy = 350;
int dl = ega_display_line(ega);
if (!ega->linepos)
{
@@ -318,204 +525,36 @@ void ega_poll(void *p)
if (ega->scrblank)
{
for (x = 0; x < ega->hdisp; x++)
{
switch (ega->seqregs[1] & 9)
{
case 0:
for (xx = 0; xx < 9; xx++) ((uint32_t *)buffer32->line[dl])[(x * 9) + xx + 32 + x_add] = 0;
break;
case 1:
for (xx = 0; xx < 8; xx++) ((uint32_t *)buffer32->line[dl])[(x * 8) + xx + 32 + x_add] = 0;
break;
case 8:
for (xx = 0; xx < 18; xx++) ((uint32_t *)buffer32->line[dl])[(x * 18) + xx + 32 + x_add] = 0;
break;
case 9:
for (xx = 0; xx < 16; xx++) ((uint32_t *)buffer32->line[dl])[(x * 16) + xx + 32 + x_add] = 0;
break;
}
}
ega_render_blank(ega);
}
else if (!(ega->gdcreg[6] & 1))
{
if (fullchange)
{
for (x = 0; x < ega->hdisp; x++)
{
drawcursor = ((ega->ma == ega->ca) && ega->con && ega->cursoron);
chr = ega->vram[(ega->ma << 1) & ega->vrammask];
attr = ega->vram[((ega->ma << 1) + 1) & ega->vrammask];
if (attr & 8) charaddr = ega->charsetb + (chr * 128);
else charaddr = ega->charseta + (chr * 128);
if (drawcursor)
{
bg = ega->pallook[ega->egapal[attr & 15]];
fg = ega->pallook[ega->egapal[attr >> 4]];
}
else
{
fg = ega->pallook[ega->egapal[attr & 15]];
bg = ega->pallook[ega->egapal[attr >> 4]];
if (attr & 0x80 && ega->attrregs[0x10] & 8)
{
bg = ega->pallook[ega->egapal[(attr >> 4) & 7]];
if (ega->blink & 16)
fg = bg;
}
}
dat = ega->vram[charaddr + (ega->sc << 2)];
if (ega->seqregs[1] & 8)
{
if (ega->seqregs[1] & 1)
{
for (xx = 0; xx < 8; xx++)
((uint32_t *)buffer32->line[dl])[(((x << 4) + 32 + (xx << 1)) & 2047) + x_add] =
((uint32_t *)buffer32->line[dl])[(((x << 4) + 33 + (xx << 1)) & 2047) + x_add] = (dat & (0x80 >> xx)) ? fg : bg;
}
else
{
for (xx = 0; xx < 8; xx++)
((uint32_t *)buffer32->line[dl])[(((x * 18) + 32 + (xx << 1)) & 2047) + x_add] =
((uint32_t *)buffer32->line[dl])[(((x * 18) + 33 + (xx << 1)) & 2047) + x_add] = (dat & (0x80 >> xx)) ? fg : bg;
if ((chr & ~0x1f) != 0xc0 || !(ega->attrregs[0x10] & 4))
((uint32_t *)buffer32->line[dl])[(((x * 18) + 32 + 16) & 2047) + x_add] =
((uint32_t *)buffer32->line[dl])[(((x * 18) + 32 + 17) & 2047) + x_add] = bg;
else
((uint32_t *)buffer32->line[dl])[(((x * 18) + 32 + 16) & 2047) + x_add] =
((uint32_t *)buffer32->line[dl])[(((x * 18) + 32 + 17) & 2047) + x_add] = (dat & 1) ? fg : bg;
}
}
else
{
if (ega->seqregs[1] & 1)
{
for (xx = 0; xx < 8; xx++)
((uint32_t *)buffer32->line[dl])[(((x << 3) + 32 + xx) & 2047) + x_add] = (dat & (0x80 >> xx)) ? fg : bg;
}
else
{
for (xx = 0; xx < 8; xx++)
((uint32_t *)buffer32->line[dl])[(((x * 9) + 32 + xx) & 2047) + x_add] = (dat & (0x80 >> xx)) ? fg : bg;
if ((chr & ~0x1f) != 0xc0 || !(ega->attrregs[0x10] & 4))
((uint32_t *)buffer32->line[dl])[(((x * 9) + 32 + 8) & 2047) + x_add] = bg;
else
((uint32_t *)buffer32->line[dl])[(((x * 9) + 32 + 8) & 2047) + x_add] = (dat & 1) ? fg : bg;
}
}
ega->ma += 4;
ega->ma &= ega->vrammask;
}
}
ega_render_text_standard(ega, drawcursor);
}
else
{
switch (ega->gdcreg[5] & 0x20)
{
case 0x00:
if (ega->seqregs[1] & 8)
{
offset = ((8 - ega->scrollcache) << 1) + 16;
for (x = 0; x <= ega->hdisp; x++)
{
if (ega->sc & 1 && !(ega->crtc[0x17] & 1))
{
edat[0] = ega->vram[ega->ma | 0x8000];
edat[1] = ega->vram[ega->ma | 0x8001];
edat[2] = ega->vram[ega->ma | 0x8002];
edat[3] = ega->vram[ega->ma | 0x8003];
}
else
{
edat[0] = ega->vram[ega->ma];
edat[1] = ega->vram[ega->ma | 0x1];
edat[2] = ega->vram[ega->ma | 0x2];
edat[3] = ega->vram[ega->ma | 0x3];
}
ega->ma += 4;
ega->ma &= ega->vrammask;
dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2);
((uint32_t *)buffer32->line[dl])[(x << 4) + 14 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 15 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
((uint32_t *)buffer32->line[dl])[(x << 4) + 12 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 13 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2);
((uint32_t *)buffer32->line[dl])[(x << 4) + 10 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 11 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
((uint32_t *)buffer32->line[dl])[(x << 4) + 8 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 9 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2);
((uint32_t *)buffer32->line[dl])[(x << 4) + 6 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 7 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
((uint32_t *)buffer32->line[dl])[(x << 4) + 4 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 5 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2);
((uint32_t *)buffer32->line[dl])[(x << 4) + 2 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 3 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
((uint32_t *)buffer32->line[dl])[(x << 4) + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 1 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
}
}
else
{
offset = (8 - ega->scrollcache) + 24;
for (x = 0; x <= ega->hdisp; x++)
{
if (ega->sc & 1 && !(ega->crtc[0x17] & 1))
{
edat[0] = ega->vram[ega->ma | 0x8000];
edat[1] = ega->vram[ega->ma | 0x8001];
edat[2] = ega->vram[ega->ma | 0x8002];
edat[3] = ega->vram[ega->ma | 0x8003];
}
else
{
edat[0] = ega->vram[ega->ma];
edat[1] = ega->vram[ega->ma | 0x1];
edat[2] = ega->vram[ega->ma | 0x2];
edat[3] = ega->vram[ega->ma | 0x3];
}
ega->ma += 4;
ega->ma &= ega->vrammask;
dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2);
((uint32_t *)buffer32->line[dl])[(x << 3) + 7 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
((uint32_t *)buffer32->line[dl])[(x << 3) + 6 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2);
((uint32_t *)buffer32->line[dl])[(x << 3) + 5 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
((uint32_t *)buffer32->line[dl])[(x << 3) + 4 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2);
((uint32_t *)buffer32->line[dl])[(x << 3) + 3 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
((uint32_t *)buffer32->line[dl])[(x << 3) + 2 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2);
((uint32_t *)buffer32->line[dl])[(x << 3) + 1 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
((uint32_t *)buffer32->line[dl])[(x << 3) + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
}
}
break;
if (ega->seqregs[1] & 8)
{
ega_render_4bpp_lowres(ega);
}
else
{
ega_render_4bpp_highres(ega);
}
break;
case 0x20:
offset = ((8 - ega->scrollcache) << 1) + 16;
for (x = 0; x <= ega->hdisp; x++)
{
if (ega->sc & 1 && !(ega->crtc[0x17] & 1))
{
edat[0] = ega->vram[(ega->ma << 1) + 0x8000];
edat[1] = ega->vram[(ega->ma << 1) + 0x8001];
}
else
{
edat[0] = ega->vram[(ega->ma << 1)];
edat[1] = ega->vram[(ega->ma << 1) + 1];
}
ega->ma += 4;
ega->ma &= ega->vrammask;
((uint32_t *)buffer32->line[dl])[(x << 4) + 14 + offset + x_add]= ((uint32_t *)buffer32->line[dl])[(x << 4) + 15 + offset + x_add] = ega->pallook[ega->egapal[edat[1] & 3]];
((uint32_t *)buffer32->line[dl])[(x << 4) + 12 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 13 + offset + x_add] = ega->pallook[ega->egapal[(edat[1] >> 2) & 3]];
((uint32_t *)buffer32->line[dl])[(x << 4) + 10 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 11 + offset + x_add] = ega->pallook[ega->egapal[(edat[1] >> 4) & 3]];
((uint32_t *)buffer32->line[dl])[(x << 4) + 8 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 9 + offset + x_add] = ega->pallook[ega->egapal[(edat[1] >> 6) & 3]];
((uint32_t *)buffer32->line[dl])[(x << 4) + 6 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 7 + offset + x_add] = ega->pallook[ega->egapal[(edat[0] >> 0) & 3]];
((uint32_t *)buffer32->line[dl])[(x << 4) + 4 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 5 + offset + x_add] = ega->pallook[ega->egapal[(edat[0] >> 2) & 3]];
((uint32_t *)buffer32->line[dl])[(x << 4) + 2 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 3 + offset + x_add] = ega->pallook[ega->egapal[(edat[0] >> 4) & 3]];
((uint32_t *)buffer32->line[dl])[(x << 4) + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 1 + offset + x_add] = ega->pallook[ega->egapal[(edat[0] >> 6) & 3]];
}
break;
if (ega->seqregs[1] & 8)
{
ega_render_2bpp_lowres(ega);
}
else
{
ega_render_2bpp_highres(ega);
}
break;
}
}
if (ega->lastline < ega->displine)
@@ -678,7 +717,8 @@ void ega_poll(void *p)
else
{
if (ega->crtc[9] & 0x80)
ega->video_res_y /= 2; if (!(ega->crtc[0x17] & 1))
ega->video_res_y /= 2;
if (!(ega->crtc[0x17] & 1))
ega->video_res_y *= 2;
ega->video_res_y /= (ega->crtc[9] & 31) + 1;
if (ega->seqregs[1] & 8)
@@ -686,7 +726,6 @@ void ega_poll(void *p)
ega->video_bpp = (ega->gdcreg[5] & 0x20) ? 2 : 4;
}
readflash=0;
ega->firstline = 2000;
ega->lastline = 0;
@@ -937,6 +976,8 @@ void ega_common_defaults(ega_t *ega)
ega->extvram = 1;
update_overscan = 0;
ega->is_jega = 0;
}
void *ega_standalone_init()
@@ -1049,6 +1090,112 @@ void *sega_standalone_init()
return ega;
}
uint16_t chrtosht(FILE *fp)
{
uint16_t i, j;
i = (uint8_t) getc(fp);
j = (uint8_t) getc(fp) << 8;
return (i | j);
}
unsigned int getfontx2header(FILE *fp, fontx_h *header)
{
fread(header->id, ID_LEN, 1, fp);
if (strncmp(header->id, "FONTX2", ID_LEN) != 0)
{
return 1;
}
fread(header->name, NAME_LEN, 1, fp);
header->width = (uint8_t)getc(fp);
header->height = (uint8_t)getc(fp);
header->type = (uint8_t)getc(fp);
return 0;
}
void readfontxtbl(fontxTbl *table, unsigned int size, FILE *fp)
{
while (size > 0)
{
table->start = chrtosht(fp);
table->end = chrtosht(fp);
++table;
--size;
}
}
static void LoadFontxFile(wchar_t *fname)
{
fontx_h head;
fontxTbl *table;
unsigned int code;
uint8_t size;
unsigned int i;
if (!fname) return;
if(*fname=='\0') return;
FILE * mfile=romfopen(fname,L"rb");
if (!mfile)
{
pclog("MSG: Can't open FONTX2 file: %s\n",fname);
return;
}
if (getfontx2header(mfile, &head) != 0)
{
fclose(mfile);
pclog("MSG: FONTX2 header is incorrect\n");
return;
}
/* switch whether the font is DBCS or not */
if (head.type == DBCS)
{
if (head.width == 16 && head.height == 16)
{
size = getc(mfile);
table = (fontxTbl *)calloc(size, sizeof(fontxTbl));
readfontxtbl(table, size, mfile);
for (i = 0; i < size; i++)
{
for (code = table[i].start; code <= table[i].end; code++)
{
fread(&jfont_dbcs_16[(code * 32)], sizeof(uint8_t), 32, mfile);
}
}
}
else
{
fclose(mfile);
pclog("MSG: FONTX2 DBCS font size is not correct\n");
return;
}
}
else
{
if (head.width == 8 && head.height == 19)
{
fread(jfont_sbcs_19, sizeof(uint8_t), SBCS19_LEN, mfile);
}
else
{
fclose(mfile);
pclog("MSG: FONTX2 SBCS font size is not correct\n");
return;
}
}
fclose(mfile);
}
void *jega_standalone_init()
{
ega_t *ega = (ega_t *) sega_standalone_init();
LoadFontxFile(L"roms/JPNHN19X.FNT");
LoadFontxFile(L"roms/JPNZN16X.FNT");
ega->is_jega = 1;
return ega;
}
static int ega_standalone_available()
{
return rom_present(L"roms/ibm_6277356_ega_card_u44_27128.bin");
@@ -1114,3 +1261,15 @@ device_t sega_device =
NULL,
NULL
};
device_t jega_device =
{
"AX JEGA",
0,
jega_standalone_init,
ega_close,
sega_standalone_available,
ega_speed_changed,
NULL,
NULL
};

View File

@@ -1,6 +1,26 @@
/* Copyright holders: Sarah Walker, Tenshi
see COPYING for more details
*/
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Emulation of the EGA, Chips & Technologies SuperEGA, and
* AX JEGA graphics cards.
*
* Version: @(#)vid_ega.h 1.0.0 2017/05/30
*
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* akm,
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016-2017 Miran Grca.
* Copyright 2017-2017 akm.
*/
#include <stdint.h>
typedef struct ega_t
{
mem_mapping_t mapping;
@@ -68,6 +88,12 @@ typedef struct ega_t
int vrammask;
int video_res_x, video_res_y, video_bpp;
uint8_t RMOD1, RMOD2, RDAGS, RDFFB, RDFSB, RDFAP, RPESL, RPULP, RPSSC, RPSSU, RPSSL;
uint8_t RPPAJ;
uint8_t RCMOD, RCCLH, RCCLL, RCCSL, RCCEL, RCSKW, ROMSL, RSTAT;
int is_jega, font_index;
int chr_left, chr_wide;
} ega_t;
extern int update_overscan;

305
src/VIDEO/vid_ega_render.c Normal file
View File

@@ -0,0 +1,305 @@
/*
* 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.
*
* EGA renderers.
*
* Version: @(#)vid_ega_render.c 1.0.0 2017/05/30
*
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016-2017 Miran Grca.
*/
#include <stdio.h>
#include "../ibm.h"
#include "../device.h"
#include "../mem.h"
#include "../rom.h"
#include "video.h"
#include "vid_ega.h"
#include "vid_ega_render.h"
int ega_display_line(ega_t *ega)
{
int y_add = (enable_overscan) ? (overscan_y >> 1) : 0;
unsigned int dl = ega->displine;
if (ega->crtc[9] & 0x1f)
{
dl -= (ega->crtc[8] & 0x1f);
}
dl += y_add;
dl &= 0x7ff;
return dl;
}
void ega_render_blank(ega_t *ega)
{
int x_add = (enable_overscan) ? 8 : 0;
int dl = ega_display_line(ega);
int x, xx;
for (x = 0; x < ega->hdisp; x++)
{
switch (ega->seqregs[1] & 9)
{
case 0:
for (xx = 0; xx < 9; xx++) ((uint32_t *)buffer32->line[dl])[(x * 9) + xx + 32 + x_add] = 0;
break;
case 1:
for (xx = 0; xx < 8; xx++) ((uint32_t *)buffer32->line[dl])[(x * 8) + xx + 32 + x_add] = 0;
break;
case 8:
for (xx = 0; xx < 18; xx++) ((uint32_t *)buffer32->line[dl])[(x * 18) + xx + 32 + x_add] = 0;
break;
case 9:
for (xx = 0; xx < 16; xx++) ((uint32_t *)buffer32->line[dl])[(x * 16) + xx + 32 + x_add] = 0;
break;
}
}
}
void ega_render_text_standard(ega_t *ega, int drawcursor)
{
int x_add = (enable_overscan) ? 8 : 0;
int dl = ega_display_line(ega);
uint8_t chr, dat, attr;
uint32_t charaddr;
int x, xx;
uint32_t fg, bg;
if (fullchange)
{
for (x = 0; x < ega->hdisp; x++)
{
drawcursor = ((ega->ma == ega->ca) && ega->con && ega->cursoron);
chr = ega->vram[(ega->ma << 1) & ega->vrammask];
attr = ega->vram[((ega->ma << 1) + 1) & ega->vrammask];
if (attr & 8) charaddr = ega->charsetb + (chr * 128);
else charaddr = ega->charseta + (chr * 128);
if (drawcursor)
{
bg = ega->pallook[ega->egapal[attr & 15]];
fg = ega->pallook[ega->egapal[attr >> 4]];
}
else
{
fg = ega->pallook[ega->egapal[attr & 15]];
bg = ega->pallook[ega->egapal[attr >> 4]];
if (attr & 0x80 && ega->attrregs[0x10] & 8)
{
bg = ega->pallook[ega->egapal[(attr >> 4) & 7]];
if (ega->blink & 16)
fg = bg;
}
}
dat = ega->vram[charaddr + (ega->sc << 2)];
if (ega->seqregs[1] & 8)
{
if (ega->seqregs[1] & 1)
{
for (xx = 0; xx < 8; xx++)
((uint32_t *)buffer32->line[dl])[(((x << 4) + 32 + (xx << 1)) & 2047) + x_add] =
((uint32_t *)buffer32->line[dl])[(((x << 4) + 33 + (xx << 1)) & 2047) + x_add] = (dat & (0x80 >> xx)) ? fg : bg;
}
else
{
for (xx = 0; xx < 8; xx++)
((uint32_t *)buffer32->line[dl])[(((x * 18) + 32 + (xx << 1)) & 2047) + x_add] =
((uint32_t *)buffer32->line[dl])[(((x * 18) + 33 + (xx << 1)) & 2047) + x_add] = (dat & (0x80 >> xx)) ? fg : bg;
if ((chr & ~0x1f) != 0xc0 || !(ega->attrregs[0x10] & 4))
((uint32_t *)buffer32->line[dl])[(((x * 18) + 32 + 16) & 2047) + x_add] =
((uint32_t *)buffer32->line[dl])[(((x * 18) + 32 + 17) & 2047) + x_add] = bg;
else
((uint32_t *)buffer32->line[dl])[(((x * 18) + 32 + 16) & 2047) + x_add] =
((uint32_t *)buffer32->line[dl])[(((x * 18) + 32 + 17) & 2047) + x_add] = (dat & 1) ? fg : bg;
}
}
else
{
if (ega->seqregs[1] & 1)
{
for (xx = 0; xx < 8; xx++)
((uint32_t *)buffer32->line[dl])[(((x << 3) + 32 + xx) & 2047) + x_add] = (dat & (0x80 >> xx)) ? fg : bg;
}
else
{
for (xx = 0; xx < 8; xx++)
((uint32_t *)buffer32->line[dl])[(((x * 9) + 32 + xx) & 2047) + x_add] = (dat & (0x80 >> xx)) ? fg : bg;
if ((chr & ~0x1f) != 0xc0 || !(ega->attrregs[0x10] & 4))
((uint32_t *)buffer32->line[dl])[(((x * 9) + 32 + 8) & 2047) + x_add] = bg;
else
((uint32_t *)buffer32->line[dl])[(((x * 9) + 32 + 8) & 2047) + x_add] = (dat & 1) ? fg : bg;
}
}
ega->ma += 4;
ega->ma &= ega->vrammask;
}
}
}
void ega_render_2bpp_lowres(ega_t *ega)
{
int x_add = (enable_overscan) ? 8 : 0;
int dl = ega_display_line(ega);
int x;
int offset;
uint8_t edat[4];
offset = ((8 - ega->scrollcache) << 1) + 16;
for (x = 0; x <= ega->hdisp; x++)
{
if (ega->sc & 1 && !(ega->crtc[0x17] & 1))
{
edat[0] = ega->vram[(ega->ma << 1) + 0x8000];
edat[1] = ega->vram[(ega->ma << 1) + 0x8001];
}
else
{
edat[0] = ega->vram[(ega->ma << 1)];
edat[1] = ega->vram[(ega->ma << 1) + 1];
}
ega->ma += 4;
ega->ma &= ega->vrammask;
((uint32_t *)buffer32->line[dl])[(x << 4) + 14 + offset + x_add]= ((uint32_t *)buffer32->line[dl])[(x << 4) + 15 + offset + x_add] = ega->pallook[ega->egapal[edat[1] & 3]];
((uint32_t *)buffer32->line[dl])[(x << 4) + 12 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 13 + offset + x_add] = ega->pallook[ega->egapal[(edat[1] >> 2) & 3]];
((uint32_t *)buffer32->line[dl])[(x << 4) + 10 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 11 + offset + x_add] = ega->pallook[ega->egapal[(edat[1] >> 4) & 3]];
((uint32_t *)buffer32->line[dl])[(x << 4) + 8 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 9 + offset + x_add] = ega->pallook[ega->egapal[(edat[1] >> 6) & 3]];
((uint32_t *)buffer32->line[dl])[(x << 4) + 6 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 7 + offset + x_add] = ega->pallook[ega->egapal[(edat[0] >> 0) & 3]];
((uint32_t *)buffer32->line[dl])[(x << 4) + 4 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 5 + offset + x_add] = ega->pallook[ega->egapal[(edat[0] >> 2) & 3]];
((uint32_t *)buffer32->line[dl])[(x << 4) + 2 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 3 + offset + x_add] = ega->pallook[ega->egapal[(edat[0] >> 4) & 3]];
((uint32_t *)buffer32->line[dl])[(x << 4) + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 1 + offset + x_add] = ega->pallook[ega->egapal[(edat[0] >> 6) & 3]];
}
}
void ega_render_2bpp_highres(ega_t *ega)
{
int x_add = (enable_overscan) ? 8 : 0;
int dl = ega_display_line(ega);
int x;
int offset;
uint8_t edat[4];
offset = ((8 - ega->scrollcache) << 1) + 16;
for (x = 0; x <= ega->hdisp; x++)
{
if (ega->sc & 1 && !(ega->crtc[0x17] & 1))
{
edat[0] = ega->vram[(ega->ma << 1) + 0x8000];
edat[1] = ega->vram[(ega->ma << 1) + 0x8001];
}
else
{
edat[0] = ega->vram[(ega->ma << 1)];
edat[1] = ega->vram[(ega->ma << 1) + 1];
}
ega->ma += 4;
ega->ma &= ega->vrammask;
((uint32_t *)buffer32->line[dl])[(x << 4) + 7 + offset + x_add] = ega->pallook[ega->egapal[edat[1] & 3]];
((uint32_t *)buffer32->line[dl])[(x << 4) + 6 + offset + x_add] = ega->pallook[ega->egapal[(edat[1] >> 2) & 3]];
((uint32_t *)buffer32->line[dl])[(x << 4) + 5 + offset + x_add] = ega->pallook[ega->egapal[(edat[1] >> 4) & 3]];
((uint32_t *)buffer32->line[dl])[(x << 4) + 4 + offset + x_add] = ega->pallook[ega->egapal[(edat[1] >> 6) & 3]];
((uint32_t *)buffer32->line[dl])[(x << 4) + 3 + offset + x_add] = ega->pallook[ega->egapal[(edat[0] >> 0) & 3]];
((uint32_t *)buffer32->line[dl])[(x << 4) + 2 + offset + x_add] = ega->pallook[ega->egapal[(edat[0] >> 2) & 3]];
((uint32_t *)buffer32->line[dl])[(x << 4) + 1 + offset + x_add] = ega->pallook[ega->egapal[(edat[0] >> 4) & 3]];
((uint32_t *)buffer32->line[dl])[(x << 4) + offset + x_add] = ega->pallook[ega->egapal[(edat[0] >> 6) & 3]];
}
}
void ega_render_4bpp_lowres(ega_t *ega)
{
int x_add = (enable_overscan) ? 8 : 0;
int dl = ega_display_line(ega);
uint8_t dat;
int x;
int offset;
uint8_t edat[4];
offset = ((8 - ega->scrollcache) << 1) + 16;
for (x = 0; x <= ega->hdisp; x++)
{
if (ega->sc & 1 && !(ega->crtc[0x17] & 1))
{
edat[0] = ega->vram[ega->ma | 0x8000];
edat[1] = ega->vram[ega->ma | 0x8001];
edat[2] = ega->vram[ega->ma | 0x8002];
edat[3] = ega->vram[ega->ma | 0x8003];
}
else
{
edat[0] = ega->vram[ega->ma];
edat[1] = ega->vram[ega->ma | 0x1];
edat[2] = ega->vram[ega->ma | 0x2];
edat[3] = ega->vram[ega->ma | 0x3];
}
ega->ma += 4;
ega->ma &= ega->vrammask;
dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2);
((uint32_t *)buffer32->line[dl])[(x << 4) + 14 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 15 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
((uint32_t *)buffer32->line[dl])[(x << 4) + 12 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 13 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2);
((uint32_t *)buffer32->line[dl])[(x << 4) + 10 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 11 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
((uint32_t *)buffer32->line[dl])[(x << 4) + 8 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 9 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2);
((uint32_t *)buffer32->line[dl])[(x << 4) + 6 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 7 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
((uint32_t *)buffer32->line[dl])[(x << 4) + 4 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 5 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2);
((uint32_t *)buffer32->line[dl])[(x << 4) + 2 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 3 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
((uint32_t *)buffer32->line[dl])[(x << 4) + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 1 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
}
}
void ega_render_4bpp_highres(ega_t *ega)
{
int x_add = (enable_overscan) ? 8 : 0;
int dl = ega_display_line(ega);
uint8_t dat;
int x;
int offset;
uint8_t edat[4];
offset = (8 - ega->scrollcache) + 24;
for (x = 0; x <= ega->hdisp; x++)
{
if (ega->sc & 1 && !(ega->crtc[0x17] & 1))
{
edat[0] = ega->vram[ega->ma | 0x8000];
edat[1] = ega->vram[ega->ma | 0x8001];
edat[2] = ega->vram[ega->ma | 0x8002];
edat[3] = ega->vram[ega->ma | 0x8003];
}
else
{
edat[0] = ega->vram[ega->ma];
edat[1] = ega->vram[ega->ma | 0x1];
edat[2] = ega->vram[ega->ma | 0x2];
edat[3] = ega->vram[ega->ma | 0x3];
}
ega->ma += 4;
ega->ma &= ega->vrammask;
dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2);
((uint32_t *)buffer32->line[dl])[(x << 3) + 7 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
((uint32_t *)buffer32->line[dl])[(x << 3) + 6 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2);
((uint32_t *)buffer32->line[dl])[(x << 3) + 5 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
((uint32_t *)buffer32->line[dl])[(x << 3) + 4 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2);
((uint32_t *)buffer32->line[dl])[(x << 3) + 3 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
((uint32_t *)buffer32->line[dl])[(x << 3) + 2 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2);
((uint32_t *)buffer32->line[dl])[(x << 3) + 1 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
((uint32_t *)buffer32->line[dl])[(x << 3) + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
}
}

View File

@@ -0,0 +1,37 @@
/*
* 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.
*
* EGA renderers.
*
* Version: @(#)vid_ega_render.h 1.0.0 2017/05/30
*
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016-2017 Miran Grca.
*/
extern int firstline_draw, lastline_draw;
extern int displine;
extern int sc;
extern uint32_t ma, ca;
extern int con, cursoron, cgablink;
extern int scrollcache;
extern uint8_t edatlookup[4][4];
void ega_render_blank(ega_t *ega);
void ega_render_text_standard(ega_t *ega, int drawcursor);
void ega_render_text_jega(ega_t *ega);
void ega_render_2bpp_lowres(ega_t *ega);
void ega_render_2bpp_highres(ega_t *ega);
void ega_render_4bpp_lowres(ega_t *ega);
void ega_render_4bpp_highres(ega_t *ega);

View File

@@ -10,7 +10,7 @@
#include "../pci.h"
#include "../rom.h"
#include "../device.h"
#include "../thread.h"
#include "../win/plat_thread.h"
#include "video.h"
#include "vid_svga.h"
#include "vid_icd2061.h"
@@ -235,14 +235,6 @@ uint8_t et4000w32p_in(uint16_t addr, void *p)
return svga->crtcreg;
case 0x3D5:
return svga->crtc[svga->crtcreg];
case 0x3DA:
svga->attrff = 0;
svga->cgastat ^= 0x30;
temp = svga->cgastat & 0x39;
if (svga->hdisp_on) temp |= 2;
if (!(svga->cgastat & 8)) temp |= 0x80;
return temp;
case 0x210A: case 0x211A: case 0x212A: case 0x213A:
case 0x214A: case 0x215A: case 0x216A: case 0x217A:

View File

@@ -9,9 +9,9 @@
#include "../pci.h"
#include "../pic.h"
#include "../rom.h"
#include "../thread.h"
#include "../timer.h"
#include "../device.h"
#include "../win/plat_thread.h"
#include "video.h"
#include "vid_nv_riva128.h"
#include "vid_svga.h"

View File

@@ -1,12 +1,29 @@
/*S3 emulation*/
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Emulation of the S3 Trio32, S3 Trio64, and S3 Vision864
* graphics cards.
*
* Version: @(#)vid_s3.c 1.0.1 2017/06/04
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016-2017 Miran Grca.
*/
#include <stdlib.h>
#include "../ibm.h"
#include "../io.h"
#include "../mem.h"
#include "../pci.h"
#include "../rom.h"
#include "../thread.h"
#include "../device.h"
#include "../win/plat_thread.h"
#include "video.h"
#include "vid_s3.h"
#include "vid_svga.h"
@@ -76,12 +93,15 @@ typedef struct s3_t
int chip;
uint8_t id, id_ext, id_ext_pci;
uint8_t int_line;
int packed_mmio;
uint32_t linear_base, linear_size;
uint8_t pci_regs[256];
int card;
uint32_t vram_mask;
@@ -132,8 +152,17 @@ typedef struct s3_t
int blitter_busy;
uint64_t blitter_time;
uint64_t status_time;
uint8_t subsys_cntl, subsys_stat;
uint8_t status_9ae9;
} s3_t;
#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
void s3_updatemapping();
void s3_accel_write(uint32_t addr, uint8_t val, void *p);
@@ -155,6 +184,19 @@ static void s3_wait_fifo_idle(s3_t *s3)
}
}
static void s3_update_irqs(s3_t *s3)
{
if (!PCI)
{
return;
}
if (s3->subsys_cntl & s3->subsys_stat & INT_MASK)
pci_set_irq(s3->card, PCI_INTA);
else
pci_clear_irq(s3->card, PCI_INTA);
}
void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3);
#define WRITE8(addr, var, val) switch ((addr) & 3) \
@@ -402,70 +444,88 @@ static void s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
static void s3_accel_out_fifo_w(s3_t *s3, uint16_t port, uint16_t val)
{
if (s3->accel.cmd & 0x100)
{
if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)
{
if (s3->accel.cmd & 0x1000)
val = (val >> 8) | (val << 8);
if ((s3->accel.cmd & 0x600) == 0x000)
s3_accel_start(8, 1, val | (val << 16), 0, s3);
else
s3_accel_start(16, 1, val | (val << 16), 0, s3);
}
else
{
if ((s3->accel.cmd & 0x600) == 0x000)
s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3);
else
s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3);
}
}
if (port & 0x8000)
{
s3_accel_out_fifo(s3, port, val);
s3_accel_out_fifo(s3, port + 1, val >> 8);
}
else
{
if (s3->accel.cmd & 0x100)
{
if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)
{
if (s3->accel.cmd & 0x1000)
val = (val >> 8) | (val << 8);
if ((s3->accel.cmd & 0x600) == 0x000)
s3_accel_start(8, 1, val | (val << 16), 0, s3);
else
s3_accel_start(16, 1, val | (val << 16), 0, s3);
}
else
{
if ((s3->accel.cmd & 0x600) == 0x000)
s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3);
else
s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3);
}
}
}
}
static void s3_accel_out_fifo_l(s3_t *s3, uint16_t port, uint32_t val)
{
if (s3->accel.cmd & 0x100)
{
if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)
{
if (s3->accel.cmd & 0x400)
{
if (s3->accel.cmd & 0x1000)
val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24);
s3_accel_start(32, 1, val, 0, s3);
}
else if ((s3->accel.cmd & 0x600) == 0x200)
{
if (s3->accel.cmd & 0x1000)
val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8);
s3_accel_start(16, 1, val, 0, s3);
s3_accel_start(16, 1, val >> 16, 0, s3);
}
else
{
if (s3->accel.cmd & 0x1000)
val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8);
s3_accel_start(8, 1, val, 0, s3);
s3_accel_start(8, 1, val >> 16, 0, s3);
}
}
else
{
if (s3->accel.cmd & 0x400)
s3_accel_start(4, 1, 0xffffffff, val, s3);
else if ((s3->accel.cmd & 0x600) == 0x200)
{
s3_accel_start(2, 1, 0xffffffff, val, s3);
s3_accel_start(2, 1, 0xffffffff, val >> 16, s3);
}
else
{
s3_accel_start(1, 1, 0xffffffff, val, s3);
s3_accel_start(1, 1, 0xffffffff, val >> 16, s3);
}
}
}
if (port & 0x8000)
{
s3_accel_out_fifo(s3, port, val);
s3_accel_out_fifo(s3, port + 1, val >> 8);
s3_accel_out_fifo(s3, port + 2, val >> 16);
s3_accel_out_fifo(s3, port + 3, val >> 24);
}
else
{
if (s3->accel.cmd & 0x100)
{
if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)
{
if (s3->accel.cmd & 0x400)
{
if (s3->accel.cmd & 0x1000)
val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24);
s3_accel_start(32, 1, val, 0, s3);
}
else if ((s3->accel.cmd & 0x600) == 0x200)
{
if (s3->accel.cmd & 0x1000)
val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8);
s3_accel_start(16, 1, val, 0, s3);
s3_accel_start(16, 1, val >> 16, 0, s3);
}
else
{
if (s3->accel.cmd & 0x1000)
val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8);
s3_accel_start(8, 1, val, 0, s3);
s3_accel_start(8, 1, val >> 16, 0, s3);
}
}
else
{
if (s3->accel.cmd & 0x400)
s3_accel_start(4, 1, 0xffffffff, val, s3);
else if ((s3->accel.cmd & 0x600) == 0x200)
{
s3_accel_start(2, 1, 0xffffffff, val, s3);
s3_accel_start(2, 1, 0xffffffff, val >> 16, s3);
}
else
{
s3_accel_start(1, 1, 0xffffffff, val, s3);
s3_accel_start(1, 1, 0xffffffff, val >> 16, s3);
}
}
}
}
}
static void s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val)
@@ -707,9 +767,19 @@ static void fifo_thread(void *param)
s3->blitter_time += end_time - start_time;
}
s3->blitter_busy = 0;
s3->subsys_stat |= INT_FIFO_EMP;
s3_update_irqs(s3);
}
}
static void s3_vblank_start(svga_t *svga)
{
s3_t *s3 = (s3_t *)svga->p;
s3->subsys_stat |= INT_VSY;
s3_update_irqs(s3);
}
static void s3_queue(s3_t *s3, uint32_t addr, uint32_t val, uint32_t type)
{
fifo_entry_t *fifo = &s3->fifo[s3->fifo_write_idx & FIFO_MASK];
@@ -1111,9 +1181,12 @@ void s3_accel_out(uint16_t port, uint8_t val, void *p)
else switch (port)
{
case 0x42e8:
s3->subsys_stat &= ~val;
s3_update_irqs(s3);
break;
case 0x42e9:
s3->accel.subsys_cntl = val;
s3->subsys_cntl = val;
s3_update_irqs(s3);
break;
case 0x46e8:
s3->accel.setup_md = val;
@@ -1143,9 +1216,9 @@ uint8_t s3_accel_in(uint16_t port, void *p)
switch (port)
{
case 0x42e8:
return 0;
return s3->subsys_stat;
case 0x42e9:
return 0;
return s3->subsys_cntl;
case 0x82e8:
s3_wait_fifo_idle(s3);
@@ -1202,7 +1275,7 @@ uint8_t s3_accel_in(uint16_t port, void *p)
if (!FIFO_EMPTY)
temp |= 0x02; /*Hardware busy*/
else
temp |= 0x04; /*FIFO empty*/
temp |= s3->status_9ae9; /*FIFO empty*/
if (FIFO_FULL)
temp |= 0xf8; /*FIFO full*/
return temp;
@@ -1587,6 +1660,15 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
s3->accel.dest = s3->accel.cy * s3->width;
}
s3->status_9ae9 = 4; /*To avoid the spam from OS/2's drivers*/
if ((s3->accel.cmd & 0x100) && !cpu_input)
{
s3->status_9ae9 = 2; /*To avoid the spam from OS/2's drivers*/
return; /*Wait for data from CPU*/
}
if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/
frgd_mix = (s3->accel.frgd_mix >> 5) & 3;
@@ -2042,6 +2124,9 @@ uint8_t s3_pci_read(int func, int addr, void *p)
case 0x31: return 0x00;
case 0x32: return s3->pci_regs[0x32];
case 0x33: return s3->pci_regs[0x33];
case 0x3c: return s3->int_line;
case 0x3d: return PCI_INTA;
}
return 0;
}
@@ -2054,7 +2139,7 @@ void s3_pci_write(int func, int addr, uint8_t val, void *p)
switch (addr)
{
case PCI_REG_COMMAND:
s3->pci_regs[PCI_REG_COMMAND] = val & 0x27;
s3->pci_regs[PCI_REG_COMMAND] = val & 0x23;
if (val & PCI_COMMAND_IO)
s3_io_set(s3);
else
@@ -2083,6 +2168,10 @@ void s3_pci_write(int func, int addr, uint8_t val, void *p)
mem_mapping_disable(&s3->bios_rom.mapping);
}
return;
case 0x3c:
s3->int_line = val;
return;
}
}
@@ -2135,6 +2224,8 @@ static void *s3_init(wchar_t *bios_fn, int chip)
svga->crtc[0x36] = 1 | (3 << 2) | (1 << 4) | (vram_sizes[vram] << 5);
svga->crtc[0x37] = 1 | (7 << 5);
svga->vblank_start = s3_vblank_start;
svga->crtc[0x53] = 1 << 3;
svga->crtc[0x59] = 0x70;
@@ -2142,9 +2233,9 @@ static void *s3_init(wchar_t *bios_fn, int chip)
if (PCI)
{
pci_add(s3_pci_read, s3_pci_write, s3);
s3->card = pci_add(s3_pci_read, s3_pci_write, s3);
}
s3->pci_regs[0x04] = 3;
s3->pci_regs[0x30] = 0x00;
@@ -2156,6 +2247,8 @@ static void *s3_init(wchar_t *bios_fn, int chip)
s3->wake_fifo_thread = thread_create_event();
s3->fifo_not_full_event = thread_create_event();
s3->fifo_thread = thread_create(fifo_thread, s3);
s3->int_line = 0;
return s3;
}

View File

@@ -1,6 +1,22 @@
/* Copyright holders: Sarah Walker
see COPYING for more details
*/
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Emulation of the S3 Trio32, S3 Trio64, and S3 Vision864
* graphics cards.
*
* Version: @(#)vid_s3.h 1.0.0 2017/05/30
*
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016-2017 Miran Grca.
*/
device_t s3_bahamas64_device;
device_t s3_9fx_device;
device_t s3_phoenix_trio32_device;

View File

@@ -9,7 +9,7 @@
#include "../pci.h"
#include "../rom.h"
#include "../device.h"
#include "../thread.h"
#include "../win/plat_thread.h"
#include "video.h"
#include "vid_s3_virge.h"
#include "vid_svga.h"
@@ -121,6 +121,7 @@ typedef struct virge_t
uint32_t linear_base, linear_size;
uint8_t pci_regs[256];
int card;
int is_375;
@@ -228,6 +229,8 @@ typedef struct virge_t
event_t *fifo_not_full_event;
int virge_busy;
uint8_t subsys_stat, subsys_cntl;
} virge_t;
static __inline void wake_fifo_thread(virge_t *virge)
@@ -292,6 +295,26 @@ enum
CMD_SET_COMMAND_NOP = (15 << 27)
};
#define INT_VSY (1 << 0)
#define INT_S3D_DONE (1 << 1)
#define INT_FIFO_OVF (1 << 2)
#define INT_FIFO_EMP (1 << 3)
#define INT_3DF_EMP (1 << 6)
#define INT_MASK 0xff
static void s3_virge_update_irqs(virge_t *virge)
{
if (!PCI)
{
return;
}
if ((virge->svga.crtc[0x32] & 0x10) && (virge->subsys_stat & virge->subsys_cntl & INT_MASK))
pci_set_irq(virge->card, PCI_INTA);
else
pci_clear_irq(virge->card, PCI_INTA);
}
static void s3_virge_out(uint16_t addr, uint8_t val, void *p)
{
virge_t *virge = (virge_t *)p;
@@ -339,6 +362,7 @@ static void s3_virge_out(uint16_t addr, uint8_t val, void *p)
case 0x32:
if ((svga->crtc[0x67] & 0xc) != 0xc)
svga->vrammask = (val & 0x40) ? 0x3ffff : ((virge->memory_size << 20) - 1);
s3_virge_update_irqs(virge);
break;
case 0x50:
@@ -691,6 +715,14 @@ static void s3_virge_updatemapping(virge_t *virge)
}
static void s3_virge_vblank_start(svga_t *svga)
{
virge_t *virge = (virge_t *)svga->p;
virge->subsys_stat |= INT_VSY;
s3_virge_update_irqs(virge);
}
static void s3_virge_wait_fifo_idle(virge_t *virge)
{
while (!FIFO_EMPTY)
@@ -822,6 +854,7 @@ static uint32_t s3_virge_mmio_read_l(uint32_t addr, void *p)
ret = (0x10 << 8);
else
ret = (0x10 << 8) | (1 << 13);
ret |= virge->subsys_stat;
if (!virge->virge_busy)
wake_fifo_thread(virge);
break;
@@ -1441,6 +1474,12 @@ static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p)
svga_recalctimings(svga);
svga->fullchange = changeframecount;
break;
case 0x8504:
virge->subsys_stat &= ~(val & 0xff);
virge->subsys_cntl = (val >> 8);
s3_virge_update_irqs(virge);
break;
case 0xa000: case 0xa004: case 0xa008: case 0xa00c:
case 0xa010: case 0xa014: case 0xa018: case 0xa01c:
@@ -3248,6 +3287,8 @@ static void render_thread(void *param)
thread_set_event(virge->not_full_event);
}
virge->s3d_busy = 0;
virge->subsys_stat |= INT_S3D_DONE;
s3_virge_update_irqs(virge);
}
}
@@ -3687,9 +3728,9 @@ static void s3_virge_pci_write(int func, int addr, uint8_t val, void *p)
mem_mapping_disable(&virge->bios_rom.mapping);
}
return;
/* case 0x3c:
case 0x3c:
virge->pci_regs[0x3c] = val;
return; */
return;
}
}
@@ -3707,6 +3748,7 @@ static void *s3_virge_init()
s3_virge_in, s3_virge_out,
s3_virge_hwcursor_draw,
s3_virge_overlay_draw);
virge->svga.vblank_start = s3_virge_vblank_start;
rom_init(&virge->bios_rom, L"roms/s3virge.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
if (PCI)
@@ -3774,7 +3816,7 @@ static void *s3_virge_init()
virge->is_375 = 0;
pci_add(s3_virge_pci_read, s3_virge_pci_write, virge);
virge->card = pci_add(s3_virge_pci_read, s3_virge_pci_write, virge);
virge->wake_render_thread = thread_create_event();
virge->wake_main_thread = thread_create_event();
@@ -3883,7 +3925,7 @@ static void *s3_virge_988_init()
return virge;
}
static void *s3_virge_375_init()
static void *s3_virge_375_init(wchar_t *romfn)
{
virge_t *virge = malloc(sizeof(virge_t));
memset(virge, 0, sizeof(virge_t));
@@ -3898,7 +3940,7 @@ static void *s3_virge_375_init()
s3_virge_hwcursor_draw,
s3_virge_overlay_draw);
rom_init(&virge->bios_rom, L"roms/86c375_1.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
rom_init(&virge->bios_rom, romfn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
if (PCI)
mem_mapping_disable(&virge->bios_rom.mapping);
@@ -3979,6 +4021,16 @@ static void *s3_virge_375_init()
return virge;
}
static void *s3_virge_375_1_init()
{
return s3_virge_375_init(L"roms/86c375_1.bin");
}
static void *s3_virge_375_4_init()
{
return s3_virge_375_init(L"roms/86c375_4.bin");
}
static void s3_virge_close(void *p)
{
virge_t *virge = (virge_t *)p;
@@ -4012,11 +4064,16 @@ static int s3_virge_988_available()
return rom_present(L"roms/diamondstealth3000.VBI");
}
static int s3_virge_375_available()
static int s3_virge_375_1_available()
{
return rom_present(L"roms/86c375_1.bin");
}
static int s3_virge_375_4_available()
{
return rom_present(L"roms/86c375_4.bin");
}
static void s3_virge_speed_changed(void *p)
{
virge_t *virge = (virge_t *)p;
@@ -4148,9 +4205,22 @@ device_t s3_virge_375_device =
{
"S3 ViRGE/DX",
0,
s3_virge_375_init,
s3_virge_375_1_init,
s3_virge_close,
s3_virge_375_available,
s3_virge_375_1_available,
s3_virge_speed_changed,
s3_virge_force_redraw,
s3_virge_add_status_info,
s3_virge_config
};
device_t s3_virge_375_4_device =
{
"S3 ViRGE/DX (VBE 2.0)",
0,
s3_virge_375_4_init,
s3_virge_close,
s3_virge_375_4_available,
s3_virge_speed_changed,
s3_virge_force_redraw,
s3_virge_add_status_info,

View File

@@ -4,3 +4,4 @@
extern device_t s3_virge_device;
extern device_t s3_virge_988_device;
extern device_t s3_virge_375_device;
extern device_t s3_virge_375_4_device;

View File

@@ -1,7 +1,21 @@
/* Copyright holders: Sarah Walker, Tenshi
see COPYING for more details
*/
/*Generic SVGA handling*/
/*
* 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.
*
* Generic SVGA handling.
*
* Version: @(#)vid_svga.c 1.0.0 2017/05/30
*
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016-2017 Miran Grca.
*/
/*This is intended to be used by another SVGA driver, and not as a card in it's own right*/
#include <stdio.h>
#include <stdlib.h>
@@ -870,8 +884,6 @@ void svga_poll(void *p)
if (!svga->override)
svga_doblit(svga->firstline_draw, svga->lastline_draw + 1, wx, wy, svga);
readflash = 0;
svga->firstline = 2000;
svga->lastline = 0;

View File

@@ -1,6 +1,21 @@
/* Copyright holders: Sarah Walker, Tenshi
see COPYING for more details
*/
/*
* 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.
*
* Generic SVGA handling.
*
* Version: @(#)vid_svga.h 1.0.0 2017/05/30
*
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016-2017 Miran Grca.
*/
typedef struct svga_t
{
mem_mapping_t mapping;

View File

@@ -1,6 +1,21 @@
/* Copyright holders: Sarah Walker
see COPYING for more details
*/
/*
* 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.
*
* SVGA renderers.
*
* Version: @(#)vid_svga_render.c 1.0.0 2017/05/30
*
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016-2017 Miran Grca.
*/
#include <stdio.h>
#include "../ibm.h"
#include "../mem.h"
@@ -43,10 +58,75 @@ int svga_display_line(svga_t *svga)
void svga_render_blank(svga_t *svga)
{
#if 0
int x, xx;
int y_add = (enable_overscan) ? 16 : 0;
int x_add = y_add >> 1;
int dl = svga_display_line(svga);
uint32_t *p;
if (svga->firstline_draw == 2000)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
if (dl >= 2046)
{
return;
}
for (x = 0; x < svga->hdisp; x++)
{
switch (svga->seqregs[1] & 9)
{
case 0:
for (xx = 0; xx < 9; xx++)
{
p = ((uint32_t *)buffer32->line[dl]);
if (&(p[(x * 9) + xx + 32 + x_add]) != NULL)
{
p[(x * 9) + xx + 32 + x_add] = svga_color_transform(0);
}
}
break;
case 1:
for (xx = 0; xx < 8; xx++)
{
p = ((uint32_t *)buffer32->line[dl]);
if (&(p[(x * 8) + xx + 32 + x_add]) != NULL)
{
p[(x * 8) + xx + 32 + x_add] = svga_color_transform(0);
}
}
break;
case 8:
for (xx = 0; xx < 18; xx++)
{
p = ((uint32_t *)buffer32->line[dl]);
if (&(p[(x * 18) + xx + 32 + x_add]) != NULL)
{
p[(x * 18) + xx + 32 + x_add] = svga_color_transform(0);
}
}
break;
case 9:
for (xx = 0; xx < 16; xx++)
{
p = ((uint32_t *)buffer32->line[dl]);
if (&(p[(x * 16) + xx + 32 + x_add]) != NULL)
{
p[(x * 16) + xx + 32 + x_add] = svga_color_transform(0);
}
}
break;
}
}
#endif
int x, xx;
int y_add = (enable_overscan) ? 16 : 0;
int x_add = y_add >> 1;
if (svga->firstline_draw == 2000)
svga->firstline_draw = svga->displine;
@@ -57,16 +137,16 @@ void svga_render_blank(svga_t *svga)
switch (svga->seqregs[1] & 9)
{
case 0:
for (xx = 0; xx < 9; xx++) ((uint32_t *)buffer32->line[dl])[(x * 9) + xx + 32 + x_add] = svga_color_transform(0);
for (xx = 0; xx < 9; xx++) ((uint32_t *)buffer32->line[svga->displine + y_add])[(x * 9) + xx + 32 + x_add] = svga_color_transform(0);
break;
case 1:
for (xx = 0; xx < 8; xx++) ((uint32_t *)buffer32->line[dl])[(x * 8) + xx + 32 + x_add] = svga_color_transform(0);
for (xx = 0; xx < 8; xx++) ((uint32_t *)buffer32->line[svga->displine + y_add])[(x * 8) + xx + 32 + x_add] = svga_color_transform(0);
break;
case 8:
for (xx = 0; xx < 18; xx++) ((uint32_t *)buffer32->line[dl])[(x * 18) + xx + 32 + x_add] = svga_color_transform(0);
for (xx = 0; xx < 18; xx++) ((uint32_t *)buffer32->line[svga->displine + y_add])[(x * 18) + xx + 32 + x_add] = svga_color_transform(0);
break;
case 9:
for (xx = 0; xx < 16; xx++) ((uint32_t *)buffer32->line[dl])[(x * 16) + xx + 32 + x_add] = svga_color_transform(0);
for (xx = 0; xx < 16; xx++) ((uint32_t *)buffer32->line[svga->displine + y_add])[(x * 16) + xx + 32 + x_add] = svga_color_transform(0);
break;
}
}

View File

@@ -1,6 +1,21 @@
/* Copyright holders: Sarah Walker
see COPYING for more details
*/
/*
* 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.
*
* SVGA renderers.
*
* Version: @(#)vid_svga_render.h 1.0.0 2017/05/30
*
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016-2017 Miran Grca.
*/
extern int firstline_draw, lastline_draw;
extern int displine;
extern int sc;

View File

@@ -9,7 +9,7 @@
#include "../pci.h"
#include "../rom.h"
#include "../device.h"
#include "../thread.h"
#include "../win/plat_thread.h"
#include "video.h"
#include "vid_svga.h"
#include "vid_svga_render.h"

View File

@@ -6,9 +6,9 @@
#include "../mem.h"
#include "../rom.h"
#include "../pci.h"
#include "../thread.h"
#include "../timer.h"
#include "../device.h"
#include "../win/plat_thread.h"
#include "video.h"
#include "vid_svga.h"
#include "vid_voodoo.h"

View File

@@ -12,8 +12,8 @@
#include "../rom.h"
#include "../config.h"
#include "../device.h"
#include "../thread.h"
#include "../timer.h"
#include "../win/plat_thread.h"
#include "video.h"
#include "vid_svga.h"
#ifndef __unix
@@ -59,6 +59,7 @@
#include "vid_wy700.h"
int vid_cga_contrast = 0;
int cga_palette = 0;
typedef struct
@@ -104,6 +105,7 @@ static VIDEO_CARD video_cards[] =
{"Phoenix S3 Trio64", "px_trio64", &s3_phoenix_trio64_device, GFX_PHOENIX_TRIO64},
{"Plantronics ColorPlus", "plantronics", &colorplus_device, GFX_COLORPLUS},
{"S3 ViRGE/DX", "virge375", &s3_virge_375_device, GFX_VIRGEDX},
{"S3 ViRGE/DX (VBE 2.0)", "virge375_vbe20", &s3_virge_375_4_device, GFX_VIRGEDX4},
{"Trident TGUI9440", "tgui9440", &tgui9440_device, GFX_TGUI9440},
{"Trident TVGA8900D", "tvga8900d", &tvga8900d_device, GFX_TVGA},
{"Tseng ET4000AX", "et4000ax", &et4000_device, GFX_ET4000},
@@ -203,8 +205,8 @@ uint8_t edatlookup[4][4];
int enable_overscan;
int overscan_x, overscan_y;
int force_43;
int enable_flash;
/*Video timing settings -

View File

@@ -81,10 +81,9 @@ extern void (*video_blit_memtoscreen_8_func)(int x, int y, int w, int h);
/* Enable EGA/(S)VGA overscan border. */
extern int enable_overscan;
extern int overscan_x, overscan_y;
/* Forcibly stretch emulated video output to 4:3 or not. */
extern int force_43;
/* Enable disk activity flash. */
extern int enable_flash;
extern int video_timing_b, video_timing_w, video_timing_l;
extern int video_speed;
@@ -112,6 +111,7 @@ void ddraw_fs_take_screenshot(wchar_t *fn);
#endif
extern int cga_palette;
extern int vid_cga_contrast;
void loadfont(wchar_t *s, int format);
void initvideo();

File diff suppressed because it is too large Load Diff

View File

Before

Width:  |  Height:  |  Size: 385 KiB

After

Width:  |  Height:  |  Size: 385 KiB

View File

Before

Width:  |  Height:  |  Size: 385 KiB

After

Width:  |  Height:  |  Size: 385 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Some files were not shown because too many files have changed in this diff Show More