From 719534c518c817f850391d355d84f1ce4473f9b4 Mon Sep 17 00:00:00 2001 From: nerd73 Date: Mon, 16 Dec 2019 13:54:59 -0700 Subject: [PATCH 001/177] IBM 386SLC/486SLC/486BL emulation --- src/cpu_new/808x.c | 5 ++- src/cpu_new/cpu.c | 82 ++++++++++++++++++++++++++++++++-- src/cpu_new/cpu.h | 63 ++++++++++++++------------ src/cpu_new/cpu_table.c | 28 ++++++++++++ src/cpu_new/x86_ops_mov_ctrl.h | 8 ++-- 5 files changed, 151 insertions(+), 35 deletions(-) diff --git a/src/cpu_new/808x.c b/src/cpu_new/808x.c index 285f9644b..818174b01 100644 --- a/src/cpu_new/808x.c +++ b/src/cpu_new/808x.c @@ -909,7 +909,10 @@ reset_common(int hard) cr0 = 1 << 30; else cr0 = 0; - cpu_cache_int_enabled = 0; + if (isibmcpu) + cpu_cache_int_enabled = 1; + else + cpu_cache_int_enabled = 0; cpu_update_waitstates(); cr4 = 0; cpu_state.eflags = 0; diff --git a/src/cpu_new/cpu.c b/src/cpu_new/cpu.c index 4dde87a96..8ed4a5937 100644 --- a/src/cpu_new/cpu.c +++ b/src/cpu_new/cpu.c @@ -151,6 +151,7 @@ int is286, is386, is486 = 1, cpu_iscyrix, + isibmcpu, israpidcad, is_pentium; @@ -259,12 +260,13 @@ cpu_set(void) is8086 = (cpu_s->cpu_type > CPU_8088); is286 = (cpu_s->cpu_type >= CPU_286); is386 = (cpu_s->cpu_type >= CPU_386SX); + isibmcpu = (cpu_s->cpu_type == CPU_IBM386SLC || cpu_s->cpu_type == CPU_IBM486SLC || cpu_s->cpu_type == CPU_IBM486BL); israpidcad = (cpu_s->cpu_type == CPU_RAPIDCAD); - is486 = (cpu_s->cpu_type >= CPU_i486SX) || (cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_486DLC || cpu_s->cpu_type == CPU_RAPIDCAD); + is486 = (cpu_s->cpu_type >= CPU_i486SX) || (cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_486DLC || cpu_s->cpu_type == CPU_RAPIDCAD || cpu_s->cpu_type == CPU_IBM486SLC || cpu_s->cpu_type == CPU_IBM486BL ); is_pentium = (cpu_s->cpu_type >= CPU_WINCHIP); hasfpu = (cpu_s->cpu_type >= CPU_i486DX) || (cpu_s->cpu_type == CPU_RAPIDCAD); cpu_iscyrix = (cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_486DLC || cpu_s->cpu_type == CPU_Cx486S || cpu_s->cpu_type == CPU_Cx486DX || cpu_s->cpu_type == CPU_Cx5x86 || cpu_s->cpu_type == CPU_Cx6x86 || cpu_s->cpu_type == CPU_Cx6x86MX || cpu_s->cpu_type == CPU_Cx6x86L || cpu_s->cpu_type == CPU_CxGX1); - cpu_16bitbus = (cpu_s->cpu_type == CPU_286 || cpu_s->cpu_type == CPU_386SX || cpu_s->cpu_type == CPU_486SLC); + cpu_16bitbus = (cpu_s->cpu_type == CPU_286 || cpu_s->cpu_type == CPU_386SX || cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_IBM386SLC || cpu_s->cpu_type == CPU_IBM486SLC ); if (cpu_s->multi) { if (cpu_s->pci_speed) cpu_busspeed = cpu_s->pci_speed; @@ -484,7 +486,8 @@ cpu_set(void) timing_jmp_pm = 23; timing_jmp_pm_gate = 38; break; - + + case CPU_IBM386SLC: case CPU_386SX: timing_rr = 2; /*register dest - register src*/ timing_rm = 6; /*register dest - memory src*/ @@ -546,6 +549,79 @@ cpu_set(void) timing_jmp_pm = 27; timing_jmp_pm_gate = 45; break; + + case CPU_IBM486SLC: +#ifdef USE_DYNAREC + x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f); +#else + x86_setopcodes(ops_386, ops_486_0f); +#endif + timing_rr = 1; /*register dest - register src*/ + timing_rm = 2; /*register dest - memory src*/ + timing_mr = 5; /*memory dest - register src*/ + timing_mm = 3; + timing_rml = 4; /*register dest - memory src long*/ + timing_mrl = 5; /*memory dest - register src long*/ + timing_mml = 5; + timing_bt = 3-1; /*branch taken*/ + timing_bnt = 1; /*branch not taken*/ + timing_int = 4; + timing_int_rm = 26; + timing_int_v86 = 82; + timing_int_pm = 44; + timing_int_pm_outer = 71; + timing_iret_rm = 15; + timing_iret_v86 = 36; /*unknown*/ + timing_iret_pm = 20; + timing_iret_pm_outer = 36; + timing_call_rm = 18; + timing_call_pm = 20; + timing_call_pm_gate = 35; + timing_call_pm_gate_inner = 69; + timing_retf_rm = 13; + timing_retf_pm = 17; + timing_retf_pm_outer = 35; + timing_jmp_rm = 17; + timing_jmp_pm = 19; + timing_jmp_pm_gate = 32; + timing_misaligned = 3; + break; + case CPU_IBM486BL: +#ifdef USE_DYNAREC + x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f); +#else + x86_setopcodes(ops_386, ops_486_0f); +#endif + timing_rr = 1; /*register dest - register src*/ + timing_rm = 2; /*register dest - memory src*/ + timing_mr = 3; /*memory dest - register src*/ + timing_mm = 3; + timing_rml = 2; /*register dest - memory src long*/ + timing_mrl = 3; /*memory dest - register src long*/ + timing_mml = 3; + timing_bt = 3-1; /*branch taken*/ + timing_bnt = 1; /*branch not taken*/ + timing_int = 4; + timing_int_rm = 26; + timing_int_v86 = 82; + timing_int_pm = 44; + timing_int_pm_outer = 71; + timing_iret_rm = 15; + timing_iret_v86 = 36; /*unknown*/ + timing_iret_pm = 20; + timing_iret_pm_outer = 36; + timing_call_rm = 18; + timing_call_pm = 20; + timing_call_pm_gate = 35; + timing_call_pm_gate_inner = 69; + timing_retf_rm = 13; + timing_retf_pm = 17; + timing_retf_pm_outer = 35; + timing_jmp_rm = 17; + timing_jmp_pm = 19; + timing_jmp_pm_gate = 32; + timing_misaligned = 3; + break; case CPU_RAPIDCAD: #ifdef USE_DYNAREC diff --git a/src/cpu_new/cpu.h b/src/cpu_new/cpu.h index 953f0bee1..0e868d99a 100644 --- a/src/cpu_new/cpu.h +++ b/src/cpu_new/cpu.h @@ -27,34 +27,37 @@ #define CPU_286 2 /* 286 class CPUs */ #define CPU_386SX 3 /* 386 class CPUs */ #define CPU_386DX 4 -#define CPU_RAPIDCAD 5 -#define CPU_486SLC 6 -#define CPU_486DLC 7 -#define CPU_i486SX 8 /* 486 class CPUs */ -#define CPU_Am486SX 9 -#define CPU_Cx486S 10 -#define CPU_i486DX 11 -#define CPU_Am486DX 12 -#define CPU_Cx486DX 13 -#define CPU_iDX4 14 -#define CPU_Cx5x86 15 -#define CPU_WINCHIP 16 /* 586 class CPUs */ -#define CPU_WINCHIP2 17 -#define CPU_PENTIUM 18 -#define CPU_PENTIUMMMX 19 -#define CPU_Cx6x86 20 -#define CPU_Cx6x86MX 21 -#define CPU_Cx6x86L 22 -#define CPU_CxGX1 23 -#define CPU_K5 24 -#define CPU_5K86 25 -#define CPU_K6 26 -#define CPU_K6_2 27 -#define CPU_K6_3 28 -#define CPU_K6_2P 29 -#define CPU_K6_3P 30 -#define CPU_PENTIUMPRO 31 /* 686 class CPUs */ -#define CPU_PENTIUM2D 32 +#define CPU_IBM386SLC 5 +#define CPU_IBM486SLC 6 +#define CPU_IBM486BL 7 +#define CPU_RAPIDCAD 8 +#define CPU_486SLC 9 +#define CPU_486DLC 10 +#define CPU_i486SX 11 /* 486 class CPUs */ +#define CPU_Am486SX 12 +#define CPU_Cx486S 13 +#define CPU_i486DX 14 +#define CPU_Am486DX 15 +#define CPU_Cx486DX 16 +#define CPU_iDX4 17 +#define CPU_Cx5x86 18 +#define CPU_WINCHIP 19 /* 586 class CPUs */ +#define CPU_WINCHIP2 20 +#define CPU_PENTIUM 21 +#define CPU_PENTIUMMMX 22 +#define CPU_Cx6x86 23 +#define CPU_Cx6x86MX 24 +#define CPU_Cx6x86L 25 +#define CPU_CxGX1 26 +#define CPU_K5 27 +#define CPU_5K86 28 +#define CPU_K6 29 +#define CPU_K6_2 30 +#define CPU_K6_3 31 +#define CPU_K6_2P 32 +#define CPU_K6_3P 33 +#define CPU_PENTIUMPRO 34 /* 686 class CPUs */ +#define CPU_PENTIUM2D 35 #define MANU_INTEL 0 #define MANU_AMD 1 @@ -90,6 +93,9 @@ extern CPU cpus_Am386SX[]; extern CPU cpus_Am386DX[]; extern CPU cpus_486SLC[]; extern CPU cpus_486DLC[]; +extern CPU cpus_IBM386SLC[]; +extern CPU cpus_IBM486SLC[]; +extern CPU cpus_IBM486BL[]; extern CPU cpus_i486[]; extern CPU cpus_Am486[]; extern CPU cpus_Cx486[]; @@ -324,6 +330,7 @@ extern int cpu_cyrix_alignment; /*Cyrix 5x86/6x86 only has data misalignment penalties when crossing 8-byte boundaries*/ extern int is8086, is286, is386, is486; +extern int isibmcpu; extern int is_rapidcad; extern int hasfpu; #define CPU_FEATURE_RDTSC (1 << 0) diff --git a/src/cpu_new/cpu_table.c b/src/cpu_new/cpu_table.c index ee1d4d2ec..feee2e2b4 100644 --- a/src/cpu_new/cpu_table.c +++ b/src/cpu_new/cpu_table.c @@ -186,6 +186,34 @@ CPU cpus_486SLC[] = { {"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0} }; +CPU cpus_IBM386SLC[] = { + /*IBM 386SLC*/ + {"386SLC/16", CPU_IBM386SLC, 16000000, 1, 0, 0x300, 0, 0, 0, 3,3,3,3, 2}, + {"386SLC/20", CPU_IBM386SLC, 20000000, 1, 0, 0x300, 0, 0, 0, 4,4,3,3, 3}, + {"386SLC/25", CPU_IBM386SLC, 25000000, 1, 0, 0x300, 0, 0, 0, 4,4,3,3, 3}, + {"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0} +}; + +CPU cpus_IBM486SLC[] = { + /*IBM 486SLC*/ + {"486SLC/33", CPU_IBM486SLC, 33333333, 1, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4}, + {"486SLC2/50", CPU_IBM486SLC, 50000000, 2, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 6}, + {"486SLC2/66", CPU_IBM486SLC, 66666666, 2, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8}, + {"486SLC3/60", CPU_IBM486SLC, 60000000, 3, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 7}, + {"486SLC3/75", CPU_IBM486SLC, 75000000, 3, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9}, + {"486SLC3/100", CPU_IBM486SLC, 100000000, 3, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 12}, + {"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0} +}; + +CPU cpus_IBM486BL[] = { + /*IBM Blue Lightning*/ + {"486BL2/50", CPU_IBM486BL, 50000000, 2, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 6}, + {"486BL2/66", CPU_IBM486BL, 66666666, 2, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8}, + {"486BL3/75", CPU_IBM486BL, 75000000, 3, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9}, + {"486BL3/100", CPU_IBM486BL, 100000000, 3, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 12}, + {"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0} +}; + CPU cpus_486DLC[] = { /*Cx486DLC*/ {"Cx486DLC/25", CPU_486DLC, 25000000, 1, 0, 0x401, 0, 0x0001, 0, 4, 4,3,3, 3}, diff --git a/src/cpu_new/x86_ops_mov_ctrl.h b/src/cpu_new/x86_ops_mov_ctrl.h index 55326dfe1..06a89884b 100644 --- a/src/cpu_new/x86_ops_mov_ctrl.h +++ b/src/cpu_new/x86_ops_mov_ctrl.h @@ -120,9 +120,11 @@ static int opMOV_CRx_r_a16(uint32_t fetchdat) mmu_perm=4; if (is486 && !(cr0 & (1 << 30))) cpu_cache_int_enabled = 1; - else - cpu_cache_int_enabled = 0; - if (is486 && ((cr0 ^ old_cr0) & (1 << 30))) + else if (isibmcpu) + cpu_cache_int_enabled = 1; + else + cpu_cache_int_enabled = 0; + if (is486 && ((cr0 ^ old_cr0) & (1 << 30))) cpu_update_waitstates(); if (cr0 & 1) cpu_cur_status |= CPU_STATUS_PMODE; From 2ce2ea23d05a3e18ac159560aa3d8ce93442bf0f Mon Sep 17 00:00:00 2001 From: nerd73 Date: Mon, 16 Dec 2019 13:58:30 -0700 Subject: [PATCH 002/177] Added the new CPUs to various PS/2 machines. --- src/machine/machine_table_new.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/machine/machine_table_new.c b/src/machine/machine_table_new.c index e78648c70..d96604f8c 100644 --- a/src/machine/machine_table_new.c +++ b/src/machine/machine_table_new.c @@ -86,7 +86,7 @@ const machine_t machines[] = { { "[286 ISA] Quadtel IBM AT", "ibmatquadtel", {{"", cpus_ibmat}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 63, machine_at_ibmatquadtel_init, NULL }, { "[286 ISA] Phoenix IBM AT", "ibmatpx", {{"", cpus_ibmat}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 63, machine_at_ibmatpx_init, NULL }, { "[286 ISA] IBM PS/1 model 2011", "ibmps1es", {{"", cpus_ps1_m2011}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_VIDEO | MACHINE_VIDEO_FIXED | MACHINE_HDC | MACHINE_PS2, 512,16384, 512, 63, machine_ps1_m2011_init, NULL }, - { "[286 ISA] IBM PS/2 model 30-286", "ibmps2_m30_286", {{"", cpus_ps2_m30_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_VIDEO | MACHINE_VIDEO_FIXED | MACHINE_HDC | MACHINE_PS2, 1, 16, 1, 127, machine_ps2_m30_286_init, NULL }, + { "[286 ISA] IBM PS/2 model 30-286", "ibmps2_m30_286", {{"Intel", cpus_ps2_m30_286}, {"IBM", cpus_IBM486SLC}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_VIDEO | MACHINE_VIDEO_FIXED | MACHINE_HDC | MACHINE_PS2, 1, 16, 1, 127, machine_ps2_m30_286_init, NULL }, { "[286 ISA] IBM XT Model 286", "ibmxt286", {{"", cpus_ibmxt286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 127, machine_at_ibmxt286_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_OPEN_AT) { "[286 ISA] OpenAT", "open_at", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 63, machine_at_open_at_init, NULL }, @@ -101,7 +101,7 @@ const machine_t machines[] = { { "[286 ISA] Headland IQS", "iqs", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 512, 8192, 128, 127, machine_at_iqs_init, NULL }, { "[286 ISA] Samsung Deskmaster 286", "deskmaster286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_deskmaster286_init, NULL }, - { "[286 MCA] IBM PS/2 model 50", "ibmps2_m50", {{"", cpus_ps2_m30_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 1, 10, 1, 63, machine_ps2_model_50_init, NULL }, + { "[286 MCA] IBM PS/2 model 50", "ibmps2_m50", {{"Intel", cpus_ps2_m30_286}, {"IBM", cpus_IBM486SLC}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 1, 10, 1, 63, machine_ps2_model_50_init, NULL }, { "[386SX ISA] AMA-932J", "ama932j", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_HDC | MACHINE_VIDEO, 512, 8192, 128, 127, machine_at_ama932j_init, at_ama932j_get_device }, #if defined(DEV_BRANCH) && defined(USE_AMI386SX) @@ -117,7 +117,7 @@ const machine_t machines[] = { { "[386SX ISA] Unknown Micronics 386 Board", "micronics386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512, 8192, 128, 127, machine_at_micronics386_init, NULL }, #endif - { "[386SX MCA] IBM PS/2 model 55SX", "ibmps2_m55sx", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 1, 8, 1, 63, machine_ps2_model_55sx_init, NULL }, + { "[386SX MCA] IBM PS/2 model 55SX", "ibmps2_m55sx", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"IBM", cpus_IBM486SLC}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 1, 8, 1, 63, machine_ps2_model_55sx_init, NULL }, { "[386DX ISA] AMI 386DX clone", "ami386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_ami_init, NULL }, { "[386DX ISA] Award 386DX clone", "award386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_init, NULL }, @@ -128,8 +128,8 @@ const machine_t machines[] = { { "[386DX ISA] Compaq Portable III (386)", "portableiii386", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_HDC | MACHINE_VIDEO | MACHINE_VIDEO_FIXED, 1, 14, 1, 127, machine_at_portableiii386_init, NULL }, #endif - { "[386DX MCA] IBM PS/2 model 70 (type 3)", "ibmps2_m70_type3", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 2, 16, 2, 63, machine_ps2_model_70_type3_init, NULL }, - { "[386DX MCA] IBM PS/2 model 80", "ibmps2_m80", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 1, 12, 1, 63, machine_ps2_model_80_init, NULL }, + { "[386DX MCA] IBM PS/2 model 70 (type 3)", "ibmps2_m70_type3", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"IBM", cpus_IBM486BL}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 2, 16, 2, 63, machine_ps2_model_70_type3_init, NULL }, + { "[386DX MCA] IBM PS/2 model 80", "ibmps2_m80", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"IBM", cpus_IBM486BL}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 1, 12, 1, 63, machine_ps2_model_80_init, NULL }, { "[486 ISA] AMI 486 clone", "ami486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_ami_init, NULL }, { "[486 ISA] AMI ALi 1429", "ali1429", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_ali1429_init, NULL }, From 4e8bcfd6ad582c65288b95cb46ac1b31fa994d2f Mon Sep 17 00:00:00 2001 From: nerd73 Date: Mon, 16 Dec 2019 18:10:19 -0700 Subject: [PATCH 003/177] Add files via upload --- src/cpu/808x.c | 5 ++- src/cpu/cpu.c | 82 +++++++++++++++++++++++++++++++++++++- src/cpu/cpu.h | 57 ++++++++++++++------------ src/cpu/cpu_table.c | 26 ++++++++++++ src/cpu/x86_ops_mov_ctrl.h | 4 +- 5 files changed, 145 insertions(+), 29 deletions(-) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 9d4e318f6..979363c02 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -915,7 +915,10 @@ reset_common(int hard) cr0 = 1 << 30; else cr0 = 0; - cpu_cache_int_enabled = 0; + if (isibmcpu) + cpu_cache_int_enabled = 1; + else + cpu_cache_int_enabled = 0; cpu_update_waitstates(); cr4 = 0; cpu_state.eflags = 0; diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index dc068d62f..484b979cf 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -145,6 +145,7 @@ int is286, is386, is486, cpu_iscyrix, + isibmcpu, israpidcad, is_pentium; @@ -255,8 +256,9 @@ cpu_set(void) is8086 = (cpu_s->cpu_type > CPU_8088); is286 = (cpu_s->cpu_type >= CPU_286); is386 = (cpu_s->cpu_type >= CPU_386SX); + isibmcpu = (cpu_s->cpu_type == CPU_IBM386SLC || cpu_s->cpu_type == CPU_IBM486SLC || cpu_s->cpu_type == CPU_IBM486BL); israpidcad = (cpu_s->cpu_type == CPU_RAPIDCAD); - is486 = (cpu_s->cpu_type >= CPU_i486SX) || (cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_486DLC || cpu_s->cpu_type == CPU_RAPIDCAD); + is486 = (cpu_s->cpu_type >= CPU_i486SX) || (cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_486DLC || cpu_s->cpu_type == CPU_RAPIDCAD || cpu_s->cpu_type == CPU_IBM486SLC || cpu_s->cpu_type == CPU_IBM486BL ); is_pentium = (cpu_s->cpu_type >= CPU_WINCHIP); hasfpu = (cpu_s->cpu_type >= CPU_i486DX) || (cpu_s->cpu_type == CPU_RAPIDCAD); #if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) @@ -265,7 +267,8 @@ cpu_set(void) cpu_iscyrix = (cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_486DLC || cpu_s->cpu_type == CPU_Cx486S || cpu_s->cpu_type == CPU_Cx486DX || cpu_s->cpu_type == CPU_Cx5x86); #endif - cpu_16bitbus = (cpu_s->cpu_type == CPU_286 || cpu_s->cpu_type == CPU_386SX || cpu_s->cpu_type == CPU_486SLC); + cpu_16bitbus = (cpu_s->cpu_type == CPU_286 || cpu_s->cpu_type == CPU_386SX || cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_IBM386SLC || cpu_s->cpu_type == CPU_IBM486SLC ); + if (cpu_s->multi) { if (cpu_s->pci_speed) cpu_busspeed = cpu_s->pci_speed; @@ -484,6 +487,7 @@ cpu_set(void) timing_jmp_pm_gate = 38; break; + case CPU_IBM386SLC: case CPU_386SX: timing_rr = 2; /*register dest - register src*/ timing_rm = 6; /*register dest - memory src*/ @@ -546,6 +550,80 @@ cpu_set(void) timing_jmp_pm_gate = 45; break; + case CPU_IBM486SLC: +#ifdef USE_DYNAREC + x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f); +#else + x86_setopcodes(ops_386, ops_486_0f); +#endif + timing_rr = 1; /*register dest - register src*/ + timing_rm = 2; /*register dest - memory src*/ + timing_mr = 5; /*memory dest - register src*/ + timing_mm = 3; + timing_rml = 4; /*register dest - memory src long*/ + timing_mrl = 5; /*memory dest - register src long*/ + timing_mml = 5; + timing_bt = 3-1; /*branch taken*/ + timing_bnt = 1; /*branch not taken*/ + timing_int = 4; + timing_int_rm = 26; + timing_int_v86 = 82; + timing_int_pm = 44; + timing_int_pm_outer = 71; + timing_iret_rm = 15; + timing_iret_v86 = 36; /*unknown*/ + timing_iret_pm = 20; + timing_iret_pm_outer = 36; + timing_call_rm = 18; + timing_call_pm = 20; + timing_call_pm_gate = 35; + timing_call_pm_gate_inner = 69; + timing_retf_rm = 13; + timing_retf_pm = 17; + timing_retf_pm_outer = 35; + timing_jmp_rm = 17; + timing_jmp_pm = 19; + timing_jmp_pm_gate = 32; + timing_misaligned = 3; + break; + + case CPU_IBM486BL: +#ifdef USE_DYNAREC + x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f); +#else + x86_setopcodes(ops_386, ops_486_0f); +#endif + timing_rr = 1; /*register dest - register src*/ + timing_rm = 2; /*register dest - memory src*/ + timing_mr = 3; /*memory dest - register src*/ + timing_mm = 3; + timing_rml = 2; /*register dest - memory src long*/ + timing_mrl = 3; /*memory dest - register src long*/ + timing_mml = 3; + timing_bt = 3-1; /*branch taken*/ + timing_bnt = 1; /*branch not taken*/ + timing_int = 4; + timing_int_rm = 26; + timing_int_v86 = 82; + timing_int_pm = 44; + timing_int_pm_outer = 71; + timing_iret_rm = 15; + timing_iret_v86 = 36; /*unknown*/ + timing_iret_pm = 20; + timing_iret_pm_outer = 36; + timing_call_rm = 18; + timing_call_pm = 20; + timing_call_pm_gate = 35; + timing_call_pm_gate_inner = 69; + timing_retf_rm = 13; + timing_retf_pm = 17; + timing_retf_pm_outer = 35; + timing_jmp_rm = 17; + timing_jmp_pm = 19; + timing_jmp_pm_gate = 32; + timing_misaligned = 3; + break; + case CPU_RAPIDCAD: timing_rr = 1; /*register dest - register src*/ timing_rm = 2; /*register dest - memory src*/ diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 17ffebae8..f895dc8e1 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -31,39 +31,42 @@ #define CPU_286 2 /* 286 class CPUs */ #define CPU_386SX 3 /* 386 class CPUs */ #define CPU_386DX 4 -#define CPU_RAPIDCAD 5 -#define CPU_486SLC 6 -#define CPU_486DLC 7 -#define CPU_i486SX 8 /* 486 class CPUs */ -#define CPU_Am486SX 9 -#define CPU_Cx486S 10 -#define CPU_i486DX 11 -#define CPU_Am486DX 12 -#define CPU_Cx486DX 13 -#define CPU_iDX4 14 -#define CPU_Cx5x86 15 -#define CPU_WINCHIP 16 /* 586 class CPUs */ -#define CPU_PENTIUM 17 -#define CPU_PENTIUMMMX 18 -#define CPU_Cx6x86 19 -#define CPU_Cx6x86MX 20 -#define CPU_Cx6x86L 21 -#define CPU_CxGX1 22 +#define CPU_IBM386SLC 5 +#define CPU_IBM486SLC 6 +#define CPU_IBM486BL 7 +#define CPU_RAPIDCAD 8 +#define CPU_486SLC 9 +#define CPU_486DLC 10 +#define CPU_i486SX 11 /* 486 class CPUs */ +#define CPU_Am486SX 12 +#define CPU_Cx486S 13 +#define CPU_i486DX 14 +#define CPU_Am486DX 15 +#define CPU_Cx486DX 16 +#define CPU_iDX4 17 +#define CPU_Cx5x86 18 +#define CPU_WINCHIP 19 /* 586 class CPUs */ +#define CPU_PENTIUM 20 +#define CPU_PENTIUMMMX 21 +#define CPU_Cx6x86 22 +#define CPU_Cx6x86MX 23 +#define CPU_Cx6x86L 24 +#define CPU_CxGX1 25 #ifdef DEV_BRANCH #ifdef USE_AMD_K -#define CPU_K5 23 -#define CPU_5K86 24 -#define CPU_K6 25 +#define CPU_K5 26 +#define CPU_5K86 27 +#define CPU_K6 28 #endif #endif #ifdef DEV_BRANCH #ifdef USE_I686 -#define CPU_PENTIUMPRO 26 /* 686 class CPUs */ +#define CPU_PENTIUMPRO 29 /* 686 class CPUs */ #if 0 -# define CPU_PENTIUM2 27 -# define CPU_PENTIUM2D 28 +# define CPU_PENTIUM2 30 +# define CPU_PENTIUM2D 31 #else -# define CPU_PENTIUM2D 27 +# define CPU_PENTIUM2D 30 #endif #endif #endif @@ -102,6 +105,9 @@ extern CPU cpus_Am386SX[]; extern CPU cpus_Am386DX[]; extern CPU cpus_486SLC[]; extern CPU cpus_486DLC[]; +extern CPU cpus_IBM386SLC[]; +extern CPU cpus_IBM486SLC[]; +extern CPU cpus_IBM486BL[]; extern CPU cpus_i486[]; extern CPU cpus_Am486[]; extern CPU cpus_Cx486[]; @@ -329,6 +335,7 @@ extern int cpu_cyrix_alignment; /*Cyrix 5x86/6x86 only has data misalignment penalties when crossing 8-byte boundaries*/ extern int is8086, is286, is386, is486; +extern int isibmcpu; extern int is_rapidcad; extern int hasfpu; #define CPU_FEATURE_RDTSC (1 << 0) diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index e82afef28..f1a724ccd 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -173,7 +173,33 @@ CPU cpus_Am386DX[] = { {"Am386DX/40", CPU_386DX, 40000000, 1, 0, 0x0308, 0, 0, 0, 7,7,3,3, 5}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0} }; +CPU cpus_IBM386SLC[] = { + /*IBM 386SLC*/ + {"386SLC/16", CPU_IBM386SLC, 16000000, 1, 0, 0x300, 0, 0, 0, 3,3,3,3, 2}, + {"386SLC/20", CPU_IBM386SLC, 20000000, 1, 0, 0x300, 0, 0, 0, 4,4,3,3, 3}, + {"386SLC/25", CPU_IBM386SLC, 25000000, 1, 0, 0x300, 0, 0, 0, 4,4,3,3, 3}, + {"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0} +}; +CPU cpus_IBM486SLC[] = { + /*IBM 486SLC*/ + {"486SLC/33", CPU_IBM486SLC, 33333333, 1, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4}, + {"486SLC2/50", CPU_IBM486SLC, 50000000, 2, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 6}, + {"486SLC2/66", CPU_IBM486SLC, 66666666, 2, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8}, + {"486SLC3/60", CPU_IBM486SLC, 60000000, 3, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 7}, + {"486SLC3/75", CPU_IBM486SLC, 75000000, 3, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9}, + {"486SLC3/100", CPU_IBM486SLC, 100000000, 3, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 12}, + {"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0} +}; + +CPU cpus_IBM486BL[] = { + /*IBM Blue Lightning*/ + {"486BL2/50", CPU_IBM486BL, 50000000, 2, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 6}, + {"486BL2/66", CPU_IBM486BL, 66666666, 2, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8}, + {"486BL3/75", CPU_IBM486BL, 75000000, 3, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9}, + {"486BL3/100", CPU_IBM486BL, 100000000, 3, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 12}, + {"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0} +}; CPU cpus_486SLC[] = { /*Cx486SLC*/ {"Cx486SLC/20", CPU_486SLC, 20000000, 1, 0, 0x400, 0, 0x0000, 0, 4,4,3,3, 3}, diff --git a/src/cpu/x86_ops_mov_ctrl.h b/src/cpu/x86_ops_mov_ctrl.h index 1b5e7db71..becb0e095 100644 --- a/src/cpu/x86_ops_mov_ctrl.h +++ b/src/cpu/x86_ops_mov_ctrl.h @@ -127,7 +127,9 @@ static int opMOV_CRx_r_a16(uint32_t fetchdat) mmu_perm=4; if (is486 && !(cr0 & (1 << 30))) cpu_cache_int_enabled = 1; - else + else if (isibmcpu) + cpu_cache_int_enabled = 1; + else cpu_cache_int_enabled = 0; if (is486 && ((cr0 ^ old_cr0) & (1 << 30))) cpu_update_waitstates(); From 07613ce5201e9732729dd6a9925f5f1739bedf6a Mon Sep 17 00:00:00 2001 From: nerd73 Date: Mon, 16 Dec 2019 18:10:47 -0700 Subject: [PATCH 004/177] Add files via upload --- src/machine/machine_table.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 643c7f2dd..5332b6fd6 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -99,7 +99,7 @@ const machine_t machines[] = { { "[286 ISA] Quadtel IBM AT", "ibmatquadtel", {{"", cpus_ibmat}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 63, machine_at_ibmatquadtel_init, NULL }, { "[286 ISA] Phoenix IBM AT", "ibmatpx", {{"", cpus_ibmat}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 63, machine_at_ibmatpx_init, NULL }, { "[286 ISA] IBM PS/1 model 2011", "ibmps1es", {{"", cpus_ps1_m2011}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_VIDEO | MACHINE_VIDEO_FIXED | MACHINE_HDC | MACHINE_PS2, 512,16384, 512, 63, machine_ps1_m2011_init, NULL }, - { "[286 ISA] IBM PS/2 model 30-286", "ibmps2_m30_286", {{"", cpus_ps2_m30_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_VIDEO | MACHINE_VIDEO_FIXED | MACHINE_HDC | MACHINE_PS2, 1, 16, 1, 127, machine_ps2_m30_286_init, NULL }, + { "[286 ISA] IBM PS/2 model 30-286", "ibmps2_m30_286", {{"Intel", cpus_ps2_m30_286}, {"IBM", cpus_IBM486SLC}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_VIDEO | MACHINE_VIDEO_FIXED | MACHINE_HDC | MACHINE_PS2, 1, 16, 1, 127, machine_ps2_m30_286_init, NULL }, { "[286 ISA] IBM XT Model 286", "ibmxt286", {{"", cpus_ibmxt286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 127, machine_at_ibmxt286_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_OPEN_AT) { "[286 ISA] OpenAT", "open_at", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 63, machine_at_open_at_init, NULL }, @@ -114,7 +114,7 @@ const machine_t machines[] = { { "[286 ISA] Headland IQS", "iqs", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 512, 8192, 128, 127, machine_at_iqs_init, NULL }, { "[286 ISA] Samsung Deskmaster 286", "deskmaster286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_deskmaster286_init, NULL }, - { "[286 MCA] IBM PS/2 model 50", "ibmps2_m50", {{"", cpus_ps2_m30_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 1, 10, 1, 63, machine_ps2_model_50_init, NULL }, + { "[286 MCA] IBM PS/2 model 50", "ibmps2_m50", {{"Intel", cpus_ps2_m30_286}, {"IBM", cpus_IBM486SLC}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 1, 10, 1, 63, machine_ps2_model_50_init, NULL }, { "[386SX ISA] AMA-932J", "ama932j", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_HDC | MACHINE_VIDEO, 512, 8192, 128, 127, machine_at_ama932j_init, at_ama932j_get_device }, #if defined(DEV_BRANCH) && defined(USE_AMI386SX) @@ -126,7 +126,7 @@ const machine_t machines[] = { { "[386SX ISA] IBM PS/1 m.2121+ISA", "ibmps1_2121_isa", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 1, 6, 1, 63, machine_ps1_m2121_init, NULL }, { "[386SX ISA] KMX-C-02", "kmxc02", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 512,16384, 512, 127, machine_at_kmxc02_init, NULL }, - { "[386SX MCA] IBM PS/2 model 55SX", "ibmps2_m55sx", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 1, 8, 1, 63, machine_ps2_model_55sx_init, NULL }, + { "[386SX MCA] IBM PS/2 model 55SX", "ibmps2_m55sx", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"IBM", cpus_IBM486SLC}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 1, 8, 1, 63, machine_ps2_model_55sx_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_MICRONICS386) { "[386SX ISA] Unknown Micronics 386 Board", "micronics386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512, 8192, 128, 127, machine_at_micronics386_init, NULL }, @@ -141,8 +141,8 @@ const machine_t machines[] = { { "[386DX ISA] Compaq Portable III (386)", "portableiii386", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_HDC | MACHINE_VIDEO | MACHINE_VIDEO_FIXED, 1, 14, 1, 127, machine_at_portableiii386_init, NULL }, #endif - { "[386DX MCA] IBM PS/2 model 70 (type 3)", "ibmps2_m70_type3", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 2, 16, 2, 63, machine_ps2_model_70_type3_init, NULL }, - { "[386DX MCA] IBM PS/2 model 80", "ibmps2_m80", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 1, 12, 1, 63, machine_ps2_model_80_init, NULL }, + { "[386DX MCA] IBM PS/2 model 70 (type 3)", "ibmps2_m70_type3", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"IBM", cpus_IBM486BL}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 2, 16, 2, 63, machine_ps2_model_70_type3_init, NULL }, + { "[386DX MCA] IBM PS/2 model 80", "ibmps2_m80", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"IBM", cpus_IBM486BL}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 1, 12, 1, 63, machine_ps2_model_80_init, NULL }, { "[486 ISA] AMI 486 clone", "ami486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_ami_init, NULL }, { "[486 ISA] AMI ALi 1429", "ali1429", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_ali1429_init, NULL }, From 82f918a36f6940fd1a050444f3285011385dc875 Mon Sep 17 00:00:00 2001 From: nerd73 Date: Tue, 17 Dec 2019 06:35:25 -0700 Subject: [PATCH 005/177] Indenting fixes --- src/cpu_new/cpu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cpu_new/cpu.c b/src/cpu_new/cpu.c index 8ed4a5937..16edc0af7 100644 --- a/src/cpu_new/cpu.c +++ b/src/cpu_new/cpu.c @@ -260,7 +260,7 @@ cpu_set(void) is8086 = (cpu_s->cpu_type > CPU_8088); is286 = (cpu_s->cpu_type >= CPU_286); is386 = (cpu_s->cpu_type >= CPU_386SX); - isibmcpu = (cpu_s->cpu_type == CPU_IBM386SLC || cpu_s->cpu_type == CPU_IBM486SLC || cpu_s->cpu_type == CPU_IBM486BL); + isibmcpu = (cpu_s->cpu_type == CPU_IBM386SLC || cpu_s->cpu_type == CPU_IBM486SLC || cpu_s->cpu_type == CPU_IBM486BL); israpidcad = (cpu_s->cpu_type == CPU_RAPIDCAD); is486 = (cpu_s->cpu_type >= CPU_i486SX) || (cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_486DLC || cpu_s->cpu_type == CPU_RAPIDCAD || cpu_s->cpu_type == CPU_IBM486SLC || cpu_s->cpu_type == CPU_IBM486BL ); is_pentium = (cpu_s->cpu_type >= CPU_WINCHIP); @@ -487,7 +487,7 @@ cpu_set(void) timing_jmp_pm_gate = 38; break; - case CPU_IBM386SLC: + case CPU_IBM386SLC: case CPU_386SX: timing_rr = 2; /*register dest - register src*/ timing_rm = 6; /*register dest - memory src*/ From 4ac2769e3e1267e4aaae8e193a47877cd5c5308a Mon Sep 17 00:00:00 2001 From: nerd73 Date: Tue, 17 Dec 2019 06:37:57 -0700 Subject: [PATCH 006/177] Indenting fixes --- src/cpu/cpu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 484b979cf..dd5c7b40b 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -256,7 +256,7 @@ cpu_set(void) is8086 = (cpu_s->cpu_type > CPU_8088); is286 = (cpu_s->cpu_type >= CPU_286); is386 = (cpu_s->cpu_type >= CPU_386SX); - isibmcpu = (cpu_s->cpu_type == CPU_IBM386SLC || cpu_s->cpu_type == CPU_IBM486SLC || cpu_s->cpu_type == CPU_IBM486BL); + isibmcpu = (cpu_s->cpu_type == CPU_IBM386SLC || cpu_s->cpu_type == CPU_IBM486SLC || cpu_s->cpu_type == CPU_IBM486BL); israpidcad = (cpu_s->cpu_type == CPU_RAPIDCAD); is486 = (cpu_s->cpu_type >= CPU_i486SX) || (cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_486DLC || cpu_s->cpu_type == CPU_RAPIDCAD || cpu_s->cpu_type == CPU_IBM486SLC || cpu_s->cpu_type == CPU_IBM486BL ); is_pentium = (cpu_s->cpu_type >= CPU_WINCHIP); @@ -487,7 +487,7 @@ cpu_set(void) timing_jmp_pm_gate = 38; break; - case CPU_IBM386SLC: + case CPU_IBM386SLC: case CPU_386SX: timing_rr = 2; /*register dest - register src*/ timing_rm = 6; /*register dest - memory src*/ From 3d112cc2db1304c498864824e986449e024c5fc3 Mon Sep 17 00:00:00 2001 From: nerd73 Date: Tue, 17 Dec 2019 06:41:23 -0700 Subject: [PATCH 007/177] Update cpu.h --- src/cpu/cpu.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index f895dc8e1..9fbd2b56a 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -335,7 +335,7 @@ extern int cpu_cyrix_alignment; /*Cyrix 5x86/6x86 only has data misalignment penalties when crossing 8-byte boundaries*/ extern int is8086, is286, is386, is486; -extern int isibmcpu; +extern int isibmcpu; extern int is_rapidcad; extern int hasfpu; #define CPU_FEATURE_RDTSC (1 << 0) @@ -493,4 +493,4 @@ extern void cpu_dynamic_switch(int new_cpu); #endif /*EMU_CPU_H*/ -#endif \ No newline at end of file +#endif From d1a1f031d9b28bdbd94a8906fab857dbb40b1c94 Mon Sep 17 00:00:00 2001 From: nerd73 Date: Tue, 17 Dec 2019 06:42:13 -0700 Subject: [PATCH 008/177] Indenting fixes --- src/cpu_new/cpu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpu_new/cpu.h b/src/cpu_new/cpu.h index 0e868d99a..578c25f18 100644 --- a/src/cpu_new/cpu.h +++ b/src/cpu_new/cpu.h @@ -330,7 +330,7 @@ extern int cpu_cyrix_alignment; /*Cyrix 5x86/6x86 only has data misalignment penalties when crossing 8-byte boundaries*/ extern int is8086, is286, is386, is486; -extern int isibmcpu; +extern int isibmcpu; extern int is_rapidcad; extern int hasfpu; #define CPU_FEATURE_RDTSC (1 << 0) From fb050149e33e41c43d944479c05987b009be2d56 Mon Sep 17 00:00:00 2001 From: nerd73 Date: Tue, 17 Dec 2019 06:45:53 -0700 Subject: [PATCH 009/177] Update 808x.c --- src/cpu/808x.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 979363c02..bf028eeaa 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -915,9 +915,9 @@ reset_common(int hard) cr0 = 1 << 30; else cr0 = 0; - if (isibmcpu) - cpu_cache_int_enabled = 1; - else + if (isibmcpu) + cpu_cache_int_enabled = 1; + else cpu_cache_int_enabled = 0; cpu_update_waitstates(); cr4 = 0; From 6fc060ded1433be66aacb3a54197a623884394e5 Mon Sep 17 00:00:00 2001 From: nerd73 Date: Tue, 17 Dec 2019 06:46:54 -0700 Subject: [PATCH 010/177] Update 808x.c --- src/cpu_new/808x.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cpu_new/808x.c b/src/cpu_new/808x.c index 818174b01..266c48c63 100644 --- a/src/cpu_new/808x.c +++ b/src/cpu_new/808x.c @@ -909,10 +909,10 @@ reset_common(int hard) cr0 = 1 << 30; else cr0 = 0; - if (isibmcpu) - cpu_cache_int_enabled = 1; - else - cpu_cache_int_enabled = 0; + if (isibmcpu) + cpu_cache_int_enabled = 1; + else + cpu_cache_int_enabled = 0; cpu_update_waitstates(); cr4 = 0; cpu_state.eflags = 0; From 0a20ac95702cb5daf30970fb3b41ccb7d73a12df Mon Sep 17 00:00:00 2001 From: nerd73 Date: Tue, 17 Dec 2019 06:51:07 -0700 Subject: [PATCH 011/177] Update cpu_table.c --- src/cpu/cpu_table.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index f1a724ccd..12a63f2a7 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -183,20 +183,20 @@ CPU cpus_IBM386SLC[] = { CPU cpus_IBM486SLC[] = { /*IBM 486SLC*/ - {"486SLC/33", CPU_IBM486SLC, 33333333, 1, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4}, - {"486SLC2/50", CPU_IBM486SLC, 50000000, 2, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 6}, - {"486SLC2/66", CPU_IBM486SLC, 66666666, 2, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8}, - {"486SLC3/60", CPU_IBM486SLC, 60000000, 3, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 7}, - {"486SLC3/75", CPU_IBM486SLC, 75000000, 3, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9}, + {"486SLC/33", CPU_IBM486SLC, 33333333, 1, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4}, + {"486SLC2/50", CPU_IBM486SLC, 50000000, 2, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 6}, + {"486SLC2/66", CPU_IBM486SLC, 66666666, 2, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8}, + {"486SLC3/60", CPU_IBM486SLC, 60000000, 3, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 7}, + {"486SLC3/75", CPU_IBM486SLC, 75000000, 3, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9}, {"486SLC3/100", CPU_IBM486SLC, 100000000, 3, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 12}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0} }; CPU cpus_IBM486BL[] = { /*IBM Blue Lightning*/ - {"486BL2/50", CPU_IBM486BL, 50000000, 2, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 6}, - {"486BL2/66", CPU_IBM486BL, 66666666, 2, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8}, - {"486BL3/75", CPU_IBM486BL, 75000000, 3, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9}, + {"486BL2/50", CPU_IBM486BL, 50000000, 2, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 6}, + {"486BL2/66", CPU_IBM486BL, 66666666, 2, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8}, + {"486BL3/75", CPU_IBM486BL, 75000000, 3, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9}, {"486BL3/100", CPU_IBM486BL, 100000000, 3, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 12}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0} }; From a660f8fc4f4dcc74cd0a38d53d2d14695daf0d4d Mon Sep 17 00:00:00 2001 From: nerd73 Date: Tue, 17 Dec 2019 06:52:22 -0700 Subject: [PATCH 012/177] Update cpu_table.c --- src/cpu_new/cpu_table.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/cpu_new/cpu_table.c b/src/cpu_new/cpu_table.c index feee2e2b4..8062fb68b 100644 --- a/src/cpu_new/cpu_table.c +++ b/src/cpu_new/cpu_table.c @@ -196,20 +196,20 @@ CPU cpus_IBM386SLC[] = { CPU cpus_IBM486SLC[] = { /*IBM 486SLC*/ - {"486SLC/33", CPU_IBM486SLC, 33333333, 1, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4}, - {"486SLC2/50", CPU_IBM486SLC, 50000000, 2, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 6}, - {"486SLC2/66", CPU_IBM486SLC, 66666666, 2, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8}, - {"486SLC3/60", CPU_IBM486SLC, 60000000, 3, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 7}, - {"486SLC3/75", CPU_IBM486SLC, 75000000, 3, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9}, + {"486SLC/33", CPU_IBM486SLC, 33333333, 1, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4}, + {"486SLC2/50", CPU_IBM486SLC, 50000000, 2, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 6}, + {"486SLC2/66", CPU_IBM486SLC, 66666666, 2, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8}, + {"486SLC3/60", CPU_IBM486SLC, 60000000, 3, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 7}, + {"486SLC3/75", CPU_IBM486SLC, 75000000, 3, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9}, {"486SLC3/100", CPU_IBM486SLC, 100000000, 3, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 12}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0} }; CPU cpus_IBM486BL[] = { /*IBM Blue Lightning*/ - {"486BL2/50", CPU_IBM486BL, 50000000, 2, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 6}, - {"486BL2/66", CPU_IBM486BL, 66666666, 2, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8}, - {"486BL3/75", CPU_IBM486BL, 75000000, 3, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9}, + {"486BL2/50", CPU_IBM486BL, 50000000, 2, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 6}, + {"486BL2/66", CPU_IBM486BL, 66666666, 2, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8}, + {"486BL3/75", CPU_IBM486BL, 75000000, 3, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9}, {"486BL3/100", CPU_IBM486BL, 100000000, 3, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 12}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0} }; From ccd1a8dde22849ff011114b1683361db5e1bdf3a Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 21 Dec 2019 20:03:07 +0100 Subject: [PATCH 013/177] Cleaned up the Sound Blaster DSP code. --- src/sound/snd_sb_dsp.c | 2045 +++++++++++++++++++++------------------- 1 file changed, 1068 insertions(+), 977 deletions(-) diff --git a/src/sound/snd_sb_dsp.c b/src/sound/snd_sb_dsp.c index a5f36886e..35aeb7ee7 100644 --- a/src/sound/snd_sb_dsp.c +++ b/src/sound/snd_sb_dsp.c @@ -25,6 +25,11 @@ #include "snd_sb.h" #include "snd_sb_dsp.h" + +#define ADPCM_4 1 +#define ADPCM_26 2 +#define ADPCM_2 3 + /*The recording safety margin is intended for uneven "len" calls to the get_buffer mixer calls on sound_sb*/ #define SB_DSP_REC_SAFEFTY_MARGIN 4096 @@ -60,53 +65,58 @@ static int sb_commands[256]= -1,-1, 0,-1,-1,-1,-1,-1,-1, 1, 2,-1,-1,-1,-1, 0 }; + char sb16_copyright[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992."; uint16_t sb_dsp_versions[] = {0, 0, 0x105, 0x200, 0x201, 0x300, 0x302, 0x405, 0x40d}; + /*These tables were 'borrowed' from DOSBox*/ - int8_t scaleMap4[64] = { - 0, 1, 2, 3, 4, 5, 6, 7, 0, -1, -2, -3, -4, -5, -6, -7, - 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, -11, -13, -15, - 2, 6, 10, 14, 18, 22, 26, 30, -2, -6, -10, -14, -18, -22, -26, -30, - 4, 12, 20, 28, 36, 44, 52, 60, -4, -12, -20, -28, -36, -44, -52, -60 - }; - uint8_t adjustMap4[64] = { - 0, 0, 0, 0, 0, 16, 16, 16, - 0, 0, 0, 0, 0, 16, 16, 16, - 240, 0, 0, 0, 0, 16, 16, 16, - 240, 0, 0, 0, 0, 16, 16, 16, - 240, 0, 0, 0, 0, 16, 16, 16, - 240, 0, 0, 0, 0, 16, 16, 16, - 240, 0, 0, 0, 0, 0, 0, 0, - 240, 0, 0, 0, 0, 0, 0, 0 - }; +int8_t scaleMap4[64] = { + 0, 1, 2, 3, 4, 5, 6, 7, 0, -1, -2, -3, -4, -5, -6, -7, + 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, -11, -13, -15, + 2, 6, 10, 14, 18, 22, 26, 30, -2, -6, -10, -14, -18, -22, -26, -30, + 4, 12, 20, 28, 36, 44, 52, 60, -4, -12, -20, -28, -36, -44, -52, -60 +}; - int8_t scaleMap26[40] = { - 0, 1, 2, 3, 0, -1, -2, -3, - 1, 3, 5, 7, -1, -3, -5, -7, - 2, 6, 10, 14, -2, -6, -10, -14, - 4, 12, 20, 28, -4, -12, -20, -28, - 5, 15, 25, 35, -5, -15, -25, -35 - }; - uint8_t adjustMap26[40] = { - 0, 0, 0, 8, 0, 0, 0, 8, - 248, 0, 0, 8, 248, 0, 0, 8, - 248, 0, 0, 8, 248, 0, 0, 8, - 248, 0, 0, 8, 248, 0, 0, 8, - 248, 0, 0, 0, 248, 0, 0, 0 - }; +uint8_t adjustMap4[64] = { + 0, 0, 0, 0, 0, 16, 16, 16, + 0, 0, 0, 0, 0, 16, 16, 16, + 240, 0, 0, 0, 0, 16, 16, 16, + 240, 0, 0, 0, 0, 16, 16, 16, + 240, 0, 0, 0, 0, 16, 16, 16, + 240, 0, 0, 0, 0, 16, 16, 16, + 240, 0, 0, 0, 0, 0, 0, 0, + 240, 0, 0, 0, 0, 0, 0, 0 +}; - int8_t scaleMap2[24] = { - 0, 1, 0, -1, 1, 3, -1, -3, - 2, 6, -2, -6, 4, 12, -4, -12, - 8, 24, -8, -24, 6, 48, -16, -48 - }; - uint8_t adjustMap2[24] = { - 0, 4, 0, 4, - 252, 4, 252, 4, 252, 4, 252, 4, - 252, 4, 252, 4, 252, 4, 252, 4, - 252, 0, 252, 0 - }; +int8_t scaleMap26[40] = { + 0, 1, 2, 3, 0, -1, -2, -3, + 1, 3, 5, 7, -1, -3, -5, -7, + 2, 6, 10, 14, -2, -6, -10, -14, + 4, 12, 20, 28, -4, -12, -20, -28, + 5, 15, 25, 35, -5, -15, -25, -35 +}; + +uint8_t adjustMap26[40] = { + 0, 0, 0, 8, 0, 0, 0, 8, + 248, 0, 0, 8, 248, 0, 0, 8, + 248, 0, 0, 8, 248, 0, 0, 8, + 248, 0, 0, 8, 248, 0, 0, 8, + 248, 0, 0, 0, 248, 0, 0, 0 +}; + +int8_t scaleMap2[24] = { + 0, 1, 0, -1, 1, 3, -1, -3, + 2, 6, -2, -6, 4, 12, -4, -12, + 8, 24, -8, -24, 6, 48, -16, -48 +}; + +uint8_t adjustMap2[24] = { + 0, 4, 0, 4, + 252, 4, 252, 4, 252, 4, 252, 4, + 252, 4, 252, 4, 252, 4, 252, 4, + 252, 0, 252, 0 +}; float low_fir_sb16_coef[SB16_NCoef]; @@ -131,1019 +141,1100 @@ sb_dsp_log(const char *fmt, ...) #endif -static inline double sinc(double x) +static __inline double +sinc(double x) { - return sin(M_PI * x) / (M_PI * x); -} - -static void recalc_sb16_filter(int playback_freq) -{ - /*Cutoff frequency = playback / 2*/ - float fC = ((float)playback_freq / 2.0) / 48000.0; - float gain; - int n; - - for (n = 0; n < SB16_NCoef; n++) - { - /*Blackman window*/ - double w = 0.42 - (0.5 * cos((2.0*n*M_PI)/(double)(SB16_NCoef-1))) + (0.08 * cos((4.0*n*M_PI)/(double)(SB16_NCoef-1))); - /*Sinc filter*/ - double h = sinc(2.0 * fC * ((double)n - ((double)(SB16_NCoef-1) / 2.0))); - - /*Create windowed-sinc filter*/ - low_fir_sb16_coef[n] = w * h; - } - - low_fir_sb16_coef[(SB16_NCoef - 1) / 2] = 1.0; - - gain = 0.0; - for (n = 0; n < SB16_NCoef; n++) - gain += low_fir_sb16_coef[n]; - - /*Normalise filter, to produce unity gain*/ - for (n = 0; n < SB16_NCoef; n++) - low_fir_sb16_coef[n] /= gain; + return sin(M_PI * x) / (M_PI * x); } -void sb_irq(sb_dsp_t *dsp, int irq8) +static void +recalc_sb16_filter(int playback_freq) { - sb_dsp_log("IRQ %i %02X\n",irq8,pic.mask); - if (irq8) dsp->sb_irq8 = 1; - else dsp->sb_irq16 = 1; - picint(1 << dsp->sb_irqnum); -} -void sb_irqc(sb_dsp_t *dsp, int irq8) -{ - if (irq8) dsp->sb_irq8 = 0; - else dsp->sb_irq16 = 0; - picintc(1 << dsp->sb_irqnum); + /* Cutoff frequency = playback / 2 */ + float fC = ((float)playback_freq / 2.0) / 48000.0; + float gain; + int n; + double w, h; + + for (n = 0; n < SB16_NCoef; n++) { + /* Blackman window */ + w = 0.42 - (0.5 * cos((2.0*n*M_PI)/(double)(SB16_NCoef-1))) + (0.08 * cos((4.0*n*M_PI)/(double)(SB16_NCoef-1))); + /* Sinc filter */ + h = sinc(2.0 * fC * ((double)n - ((double)(SB16_NCoef-1) / 2.0))); + + /* Create windowed-sinc filter */ + low_fir_sb16_coef[n] = w * h; + } + + low_fir_sb16_coef[(SB16_NCoef - 1) / 2] = 1.0; + + gain = 0.0; + for (n = 0; n < SB16_NCoef; n++) + gain += low_fir_sb16_coef[n]; + + /* Normalise filter, to produce unity gain */ + for (n = 0; n < SB16_NCoef; n++) + low_fir_sb16_coef[n] /= gain; } -void sb_dsp_reset(sb_dsp_t *dsp) + +void +sb_irq(sb_dsp_t *dsp, int irq8) { - timer_disable(&dsp->output_timer); - timer_disable(&dsp->input_timer); + sb_dsp_log("IRQ %i %02X\n", irq8, pic.mask); + if (irq8) + dsp->sb_irq8 = 1; + else + dsp->sb_irq16 = 1; - dsp->sb_command = 0; - - dsp->sb_8_length = 0xffff; - dsp->sb_8_autolen = 0xffff; - - sb_irqc(dsp, 0); - sb_irqc(dsp, 1); - dsp->sb_16_pause = 0; - dsp->sb_read_wp = dsp->sb_read_rp = 0; - dsp->sb_data_stat = -1; - dsp->sb_speaker = 0; - dsp->sb_pausetime = -1LL; - dsp->sbe2 = 0xAA; - dsp->sbe2count = 0; - - dsp->sbreset = 0; - - dsp->record_pos_read=0; - dsp->record_pos_write=SB_DSP_REC_SAFEFTY_MARGIN; - - picintc(1 << dsp->sb_irqnum); - - dsp->asp_data_len = 0; + picint(1 << dsp->sb_irqnum); } -void sb_doreset(sb_dsp_t *dsp) + +void +sb_irqc(sb_dsp_t *dsp, int irq8) { - int c; - - sb_dsp_reset(dsp); - - if (dsp->sb_type==SB16) sb_commands[8] = 1; - else sb_commands[8] = -1; - - for (c = 0; c < 256; c++) - dsp->sb_asp_regs[c] = 0; - dsp->sb_asp_regs[5] = 0x01; - dsp->sb_asp_regs[9] = 0xf8; + if (irq8) + dsp->sb_irq8 = 0; + else + dsp->sb_irq16 = 0; + + picintc(1 << dsp->sb_irqnum); } -void sb_dsp_speed_changed(sb_dsp_t *dsp) -{ - if (dsp->sb_timeo < 256) - dsp->sblatcho = TIMER_USEC * (256 - dsp->sb_timeo); - else - dsp->sblatcho = (uint64_t)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_timeo - 256))); - if (dsp->sb_timei < 256) - dsp->sblatchi = TIMER_USEC * (256 - dsp->sb_timei); - else - dsp->sblatchi = (uint64_t)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_timei - 256))); +void +sb_dsp_reset(sb_dsp_t *dsp) +{ + timer_disable(&dsp->output_timer); + timer_disable(&dsp->input_timer); + + dsp->sb_command = 0; + + dsp->sb_8_length = 0xffff; + dsp->sb_8_autolen = 0xffff; + + sb_irqc(dsp, 0); + sb_irqc(dsp, 1); + dsp->sb_16_pause = 0; + dsp->sb_read_wp = dsp->sb_read_rp = 0; + dsp->sb_data_stat = -1; + dsp->sb_speaker = 0; + dsp->sb_pausetime = -1LL; + dsp->sbe2 = 0xAA; + dsp->sbe2count = 0; + + dsp->sbreset = 0; + + dsp->record_pos_read = 0; + dsp->record_pos_write = SB_DSP_REC_SAFEFTY_MARGIN; + + picintc(1 << dsp->sb_irqnum); + + dsp->asp_data_len = 0; } -void sb_add_data(sb_dsp_t *dsp, uint8_t v) + +void +sb_doreset(sb_dsp_t *dsp) { - dsp->sb_read_data[dsp->sb_read_wp++] = v; - dsp->sb_read_wp &= 0xff; + int c; + + sb_dsp_reset(dsp); + + if (dsp->sb_type==SB16) + sb_commands[8] = 1; + else + sb_commands[8] = -1; + + for (c = 0; c < 256; c++) + dsp->sb_asp_regs[c] = 0; + + dsp->sb_asp_regs[5] = 0x01; + dsp->sb_asp_regs[9] = 0xf8; } -#define ADPCM_4 1 -#define ADPCM_26 2 -#define ADPCM_2 3 -void sb_start_dma(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int len) +void +sb_dsp_speed_changed(sb_dsp_t *dsp) { - dsp->sb_pausetime = -1; - if (dma8) - { - dsp->sb_8_length = len; - dsp->sb_8_format = format; - dsp->sb_8_autoinit = autoinit; - dsp->sb_8_pause = 0; - dsp->sb_8_enable = 1; - if (dsp->sb_16_enable && dsp->sb_16_output) dsp->sb_16_enable = 0; - dsp->sb_8_output = 1; - if (!timer_is_enabled(&dsp->output_timer)) - timer_set_delay_u64(&dsp->output_timer, dsp->sblatcho); - dsp->sbleftright = 0; - dsp->sbdacpos = 0; - } - else - { - dsp->sb_16_length = len; - dsp->sb_16_format = format; - dsp->sb_16_autoinit = autoinit; - dsp->sb_16_pause = 0; - dsp->sb_16_enable = 1; - if (dsp->sb_8_enable && dsp->sb_8_output) dsp->sb_8_enable = 0; - dsp->sb_16_output = 1; - if (!timer_is_enabled(&dsp->output_timer)) - timer_set_delay_u64(&dsp->output_timer, dsp->sblatcho); - } + if (dsp->sb_timeo < 256) + dsp->sblatcho = TIMER_USEC * (256 - dsp->sb_timeo); + else + dsp->sblatcho = (uint64_t)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_timeo - 256))); + + if (dsp->sb_timei < 256) + dsp->sblatchi = TIMER_USEC * (256 - dsp->sb_timei); + else + dsp->sblatchi = (uint64_t)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_timei - 256))); } -void sb_start_dma_i(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int len) + +void +sb_add_data(sb_dsp_t *dsp, uint8_t v) { - if (dma8) - { - dsp->sb_8_length = len; - dsp->sb_8_format = format; - dsp->sb_8_autoinit = autoinit; - dsp->sb_8_pause = 0; - dsp->sb_8_enable = 1; - if (dsp->sb_16_enable && !dsp->sb_16_output) dsp->sb_16_enable = 0; - dsp->sb_8_output = 0; - if (!timer_is_enabled(&dsp->input_timer)) - timer_set_delay_u64(&dsp->input_timer, dsp->sblatchi); - } - else - { - dsp->sb_16_length = len; - dsp->sb_16_format = format; - dsp->sb_16_autoinit = autoinit; - dsp->sb_16_pause = 0; - dsp->sb_16_enable = 1; - if (dsp->sb_8_enable && !dsp->sb_8_output) dsp->sb_8_enable = 0; - dsp->sb_16_output = 0; - if (!timer_is_enabled(&dsp->input_timer)) - timer_set_delay_u64(&dsp->input_timer, dsp->sblatchi); - } - memset(dsp->record_buffer,0,sizeof(dsp->record_buffer)); + dsp->sb_read_data[dsp->sb_read_wp++] = v; + dsp->sb_read_wp &= 0xff; } -int sb_8_read_dma(sb_dsp_t *dsp) + +void +sb_start_dma(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int len) { - return dma_channel_read(dsp->sb_8_dmanum); -} -void sb_8_write_dma(sb_dsp_t *dsp, uint8_t val) -{ - dma_channel_write(dsp->sb_8_dmanum, val); -} -int sb_16_read_dma(sb_dsp_t *dsp) -{ - return dma_channel_read(dsp->sb_16_dmanum); -} -int sb_16_write_dma(sb_dsp_t *dsp, uint16_t val) -{ - int ret = dma_channel_write(dsp->sb_16_dmanum, val); - return (ret == DMA_NODATA); + dsp->sb_pausetime = -1; + + if (dma8) { + dsp->sb_8_length = len; + dsp->sb_8_format = format; + dsp->sb_8_autoinit = autoinit; + dsp->sb_8_pause = 0; + dsp->sb_8_enable = 1; + + if (dsp->sb_16_enable && dsp->sb_16_output) + dsp->sb_16_enable = 0; + dsp->sb_8_output = 1; + if (!timer_is_enabled(&dsp->output_timer)) + timer_set_delay_u64(&dsp->output_timer, dsp->sblatcho); + dsp->sbleftright = 0; + dsp->sbdacpos = 0; + } else { + dsp->sb_16_length = len; + dsp->sb_16_format = format; + dsp->sb_16_autoinit = autoinit; + dsp->sb_16_pause = 0; + dsp->sb_16_enable = 1; + if (dsp->sb_8_enable && dsp->sb_8_output) dsp->sb_8_enable = 0; + dsp->sb_16_output = 1; + if (!timer_is_enabled(&dsp->output_timer)) + timer_set_delay_u64(&dsp->output_timer, dsp->sblatcho); + } } -void sb_dsp_setirq(sb_dsp_t *dsp, int irq) + +void +sb_start_dma_i(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int len) { - dsp->sb_irqnum = irq; + if (dma8) { + dsp->sb_8_length = len; + dsp->sb_8_format = format; + dsp->sb_8_autoinit = autoinit; + dsp->sb_8_pause = 0; + dsp->sb_8_enable = 1; + if (dsp->sb_16_enable && !dsp->sb_16_output) + dsp->sb_16_enable = 0; + dsp->sb_8_output = 0; + if (!timer_is_enabled(&dsp->input_timer)) + timer_set_delay_u64(&dsp->input_timer, dsp->sblatchi); + } else { + dsp->sb_16_length = len; + dsp->sb_16_format = format; + dsp->sb_16_autoinit = autoinit; + dsp->sb_16_pause = 0; + dsp->sb_16_enable = 1; + if (dsp->sb_8_enable && !dsp->sb_8_output) + dsp->sb_8_enable = 0; + dsp->sb_16_output = 0; + if (!timer_is_enabled(&dsp->input_timer)) + timer_set_delay_u64(&dsp->input_timer, dsp->sblatchi); + } + + memset(dsp->record_buffer,0,sizeof(dsp->record_buffer)); } -void sb_dsp_setdma8(sb_dsp_t *dsp, int dma) + +int +sb_8_read_dma(sb_dsp_t *dsp) { - dsp->sb_8_dmanum = dma; + return dma_channel_read(dsp->sb_8_dmanum); } -void sb_dsp_setdma16(sb_dsp_t *dsp, int dma) + +void +sb_8_write_dma(sb_dsp_t *dsp, uint8_t val) { - dsp->sb_16_dmanum = dma; + dma_channel_write(dsp->sb_8_dmanum, val); } -void sb_exec_command(sb_dsp_t *dsp) + + +int +sb_16_read_dma(sb_dsp_t *dsp) { - int temp,c; - sb_dsp_log("sb_exec_command : SB command %02X\n", dsp->sb_command); - switch (dsp->sb_command) - { - case 0x01: /*???*/ - if (dsp->sb_type < SB16) break; - dsp->asp_data_len = dsp->sb_data[0] + (dsp->sb_data[1] << 8) + 1; - break; - case 0x03: /*ASP status*/ - sb_add_data(dsp, 0); - break; - case 0x10: /*8-bit direct mode*/ - sb_dsp_update(dsp); - dsp->sbdat = dsp->sbdatl = dsp->sbdatr = (dsp->sb_data[0] ^ 0x80) << 8; - break; - case 0x14: /*8-bit single cycle DMA output*/ - sb_start_dma(dsp, 1, 0, 0, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); - break; - case 0x17: /*2-bit ADPCM output with reference*/ - dsp->sbref = sb_8_read_dma(dsp); - dsp->sbstep = 0; - case 0x16: /*2-bit ADPCM output*/ - sb_start_dma(dsp, 1, 0, ADPCM_2, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); - dsp->sbdat2 = sb_8_read_dma(dsp); - dsp->sb_8_length--; - if (dsp->sb_command == 0x17) - dsp->sb_8_length--; - break; - case 0x1C: /*8-bit autoinit DMA output*/ - if (dsp->sb_type < SB15) break; - sb_start_dma(dsp, 1, 1, 0, dsp->sb_8_autolen); - break; - case 0x1F: /*2-bit ADPCM autoinit output*/ - if (dsp->sb_type < SB15) break; - sb_start_dma(dsp, 1, 1, ADPCM_2, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); - dsp->sbdat2 = sb_8_read_dma(dsp); - dsp->sb_8_length--; - break; - case 0x20: /*8-bit direct input*/ - sb_add_data(dsp, (dsp->record_buffer[dsp->record_pos_read]>>8) ^0x80); - /*Due to the current implementation, I need to emulate a samplerate, even if this - * mode does not imply such samplerate. Position is increased in sb_poll_i*/ - if (!timer_is_enabled(&dsp->input_timer)) - { - dsp->sb_timei = 256 - 22; - dsp->sblatchi = TIMER_USEC * 22; - temp = 1000000 / 22; - dsp->sb_freq = temp; - timer_set_delay_u64(&dsp->input_timer, dsp->sblatchi); - } - break; - case 0x24: /*8-bit single cycle DMA input*/ - sb_start_dma_i(dsp, 1, 0, 0, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); - break; - case 0x2C: /*8-bit autoinit DMA input*/ - if (dsp->sb_type < SB15) break; - sb_start_dma_i(dsp, 1, 1, 0, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); - break; - case 0x30: - case 0x31: + return dma_channel_read(dsp->sb_16_dmanum); +} + + +int +sb_16_write_dma(sb_dsp_t *dsp, uint16_t val) +{ + int ret = dma_channel_write(dsp->sb_16_dmanum, val); + + return (ret == DMA_NODATA); +} + + +void +sb_dsp_setirq(sb_dsp_t *dsp, int irq) +{ + dsp->sb_irqnum = irq; +} + + +void +sb_dsp_setdma8(sb_dsp_t *dsp, int dma) +{ + dsp->sb_8_dmanum = dma; +} + + +void +sb_dsp_setdma16(sb_dsp_t *dsp, int dma) +{ + dsp->sb_16_dmanum = dma; +} + + +void +sb_exec_command(sb_dsp_t *dsp) +{ + int temp, c; + + sb_dsp_log("sb_exec_command : SB command %02X\n", dsp->sb_command); + + switch (dsp->sb_command) { + case 0x01: /* ???? */ + if (dsp->sb_type >= SB16) + dsp->asp_data_len = dsp->sb_data[0] + (dsp->sb_data[1] << 8) + 1; break; - case 0x34: + case 0x03: /* ASP status */ + sb_add_data(dsp, 0); + break; + case 0x10: /* 8-bit direct mode */ + sb_dsp_update(dsp); + dsp->sbdat = dsp->sbdatl = dsp->sbdatr = (dsp->sb_data[0] ^ 0x80) << 8; + break; + case 0x14: /* 8-bit single cycle DMA output */ + sb_start_dma(dsp, 1, 0, 0, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); + break; + case 0x17: /* 2-bit ADPCM output with reference */ + dsp->sbref = sb_8_read_dma(dsp); + dsp->sbstep = 0; + /* Fall through */ + case 0x16: /* 2-bit ADPCM output */ + sb_start_dma(dsp, 1, 0, ADPCM_2, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); + dsp->sbdat2 = sb_8_read_dma(dsp); + dsp->sb_8_length--; + if (dsp->sb_command == 0x17) + dsp->sb_8_length--; + break; + case 0x1C: /* 8-bit autoinit DMA output */ + if (dsp->sb_type >= SB15) + sb_start_dma(dsp, 1, 1, 0, dsp->sb_8_autolen); + break; + case 0x1F: /* 2-bit ADPCM autoinit output */ + if (dsp->sb_type >= SB15) { + sb_start_dma(dsp, 1, 1, ADPCM_2, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); + dsp->sbdat2 = sb_8_read_dma(dsp); + dsp->sb_8_length--; + } + break; + case 0x20: /* 8-bit direct input */ + sb_add_data(dsp, (dsp->record_buffer[dsp->record_pos_read]>>8) ^0x80); + /* Due to the current implementation, I need to emulate a samplerate, even if this + mode does not imply such samplerate. Position is increased in sb_poll_i(). */ + if (!timer_is_enabled(&dsp->input_timer)) { + dsp->sb_timei = 256 - 22; + dsp->sblatchi = TIMER_USEC * 22; + temp = 1000000 / 22; + dsp->sb_freq = temp; + timer_set_delay_u64(&dsp->input_timer, dsp->sblatchi); + } + break; + case 0x24: /* 8-bit single cycle DMA input */ + sb_start_dma_i(dsp, 1, 0, 0, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); + break; + case 0x2C: /* 8-bit autoinit DMA input */ + if (dsp->sb_type >= SB15) + sb_start_dma_i(dsp, 1, 1, 0, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); + break; + case 0x30: case 0x31: + break; + case 0x34: /* MIDI (UART mode) */ dsp->uart_midi = 1; dsp->uart_irq = 0; break; - case 0x35: + case 0x35: /* MIDI (UART mode) */ dsp->uart_midi = 1; dsp->uart_irq = 1; break; - case 0x36: - case 0x37: + case 0x36: case 0x37: break; - case 0x38: + case 0x38: /* MIDI (Normal mode) */ dsp->onebyte_midi = 1; break; - case 0x40: /*Set time constant*/ - dsp->sb_timei = dsp->sb_timeo = dsp->sb_data[0]; - dsp->sblatcho = dsp->sblatchi = TIMER_USEC * (256 - dsp->sb_data[0]); - temp = 256 - dsp->sb_data[0]; - temp = 1000000 / temp; - sb_dsp_log("Sample rate - %ihz (%i)\n",temp, dsp->sblatcho); - if (dsp->sb_freq != temp && dsp->sb_type >= SB16) - recalc_sb16_filter(temp); - dsp->sb_freq = temp; + case 0x40: /* Set time constant */ + dsp->sb_timei = dsp->sb_timeo = dsp->sb_data[0]; + dsp->sblatcho = dsp->sblatchi = TIMER_USEC * (256 - dsp->sb_data[0]); + temp = 256 - dsp->sb_data[0]; + temp = 1000000 / temp; + sb_dsp_log("Sample rate - %ihz (%i)\n",temp, dsp->sblatcho); + if ((dsp->sb_freq != temp) && (dsp->sb_type >= SB16)) + recalc_sb16_filter(temp); + dsp->sb_freq = temp; + break; + case 0x41: /* Set output sampling rate */ + case 0x42: /* Set input sampling rate */ + if (dsp->sb_type >= SB16) { + dsp->sblatcho = (uint64_t)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_data[1] + (dsp->sb_data[0] << 8)))); + sb_dsp_log("Sample rate - %ihz (%i)\n",dsp->sb_data[1]+(dsp->sb_data[0]<<8), dsp->sblatcho); + temp = dsp->sb_freq; + dsp->sb_freq = dsp->sb_data[1] + (dsp->sb_data[0] << 8); + dsp->sb_timeo = 256LL + dsp->sb_freq; + dsp->sblatchi = dsp->sblatcho; + dsp->sb_timei = dsp->sb_timeo; + if (dsp->sb_freq != temp && dsp->sb_type >= SB16) + recalc_sb16_filter(dsp->sb_freq); + } break; - case 0x41: /*Set output sampling rate*/ - case 0x42: /*Set input sampling rate*/ - if (dsp->sb_type < SB16) break; - dsp->sblatcho = (uint64_t)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_data[1] + (dsp->sb_data[0] << 8)))); - sb_dsp_log("Sample rate - %ihz (%i)\n",dsp->sb_data[1]+(dsp->sb_data[0]<<8), dsp->sblatcho); - temp = dsp->sb_freq; - dsp->sb_freq = dsp->sb_data[1] + (dsp->sb_data[0] << 8); - dsp->sb_timeo = 256LL + dsp->sb_freq; - dsp->sblatchi = dsp->sblatcho; - dsp->sb_timei = dsp->sb_timeo; - if (dsp->sb_freq != temp && dsp->sb_type >= SB16) - recalc_sb16_filter(dsp->sb_freq); - break; - case 0x48: /*Set DSP block transfer size*/ - dsp->sb_8_autolen = dsp->sb_data[0] + (dsp->sb_data[1] << 8); - break; - case 0x75: /*4-bit ADPCM output with reference*/ - dsp->sbref = sb_8_read_dma(dsp); - dsp->sbstep = 0; - case 0x74: /*4-bit ADPCM output*/ - sb_start_dma(dsp, 1, 0, ADPCM_4, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); - dsp->sbdat2 = sb_8_read_dma(dsp); - dsp->sb_8_length--; - if (dsp->sb_command == 0x75) - dsp->sb_8_length--; - break; - case 0x77: /*2.6-bit ADPCM output with reference*/ - dsp->sbref = sb_8_read_dma(dsp); - dsp->sbstep = 0; - case 0x76: /*2.6-bit ADPCM output*/ - sb_start_dma(dsp, 1, 0, ADPCM_26, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); - dsp->sbdat2 = sb_8_read_dma(dsp); - dsp->sb_8_length--; - if (dsp->sb_command == 0x77) - dsp->sb_8_length--; - break; - case 0x7D: /*4-bit ADPCM autoinit output*/ - if (dsp->sb_type < SB15) break; - sb_start_dma(dsp, 1, 1, ADPCM_4, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); - dsp->sbdat2 = sb_8_read_dma(dsp); - dsp->sb_8_length--; - break; - case 0x7F: /*2.6-bit ADPCM autoinit output*/ - if (dsp->sb_type < SB15) break; - sb_start_dma(dsp, 1, 1, ADPCM_26, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); - dsp->sbdat2 = sb_8_read_dma(dsp); - dsp->sb_8_length--; - break; - case 0x80: /*Pause DAC*/ - dsp->sb_pausetime = dsp->sb_data[0] + (dsp->sb_data[1] << 8); + case 0x48: /* Set DSP block transfer size */ + dsp->sb_8_autolen = dsp->sb_data[0] + (dsp->sb_data[1] << 8); + break; + case 0x75: /* 4-bit ADPCM output with reference */ + dsp->sbref = sb_8_read_dma(dsp); + dsp->sbstep = 0; + /* Fall through */ + case 0x74: /* 4-bit ADPCM output */ + sb_start_dma(dsp, 1, 0, ADPCM_4, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); + dsp->sbdat2 = sb_8_read_dma(dsp); + dsp->sb_8_length--; + if (dsp->sb_command == 0x75) + dsp->sb_8_length--; + break; + case 0x77: /* 2.6-bit ADPCM output with reference */ + dsp->sbref = sb_8_read_dma(dsp); + dsp->sbstep = 0; + /* Fall through */ + case 0x76: /* 2.6-bit ADPCM output */ + sb_start_dma(dsp, 1, 0, ADPCM_26, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); + dsp->sbdat2 = sb_8_read_dma(dsp); + dsp->sb_8_length--; + if (dsp->sb_command == 0x77) + dsp->sb_8_length--; + break; + case 0x7D: /* 4-bit ADPCM autoinit output */ + if (dsp->sb_type >= SB15) { + sb_start_dma(dsp, 1, 1, ADPCM_4, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); + dsp->sbdat2 = sb_8_read_dma(dsp); + dsp->sb_8_length--; + } + break; + case 0x7F: /* 2.6-bit ADPCM autoinit output */ + if (dsp->sb_type >= SB15) { + sb_start_dma(dsp, 1, 1, ADPCM_26, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); + dsp->sbdat2 = sb_8_read_dma(dsp); + dsp->sb_8_length--; + } + break; + case 0x80: /* Pause DAC */ + dsp->sb_pausetime = dsp->sb_data[0] + (dsp->sb_data[1] << 8); if (!timer_is_enabled(&dsp->output_timer)) timer_set_delay_u64(&dsp->output_timer, dsp->sblatcho); - break; - case 0x90: /*High speed 8-bit autoinit DMA output*/ - if (dsp->sb_type < SB2) break; - sb_start_dma(dsp, 1, 1, 0, dsp->sb_8_autolen); - break; - case 0x91: /*High speed 8-bit single cycle DMA output*/ - if (dsp->sb_type < SB2) break; - sb_start_dma(dsp, 1, 0, 0, dsp->sb_8_autolen); - break; - case 0x98: /*High speed 8-bit autoinit DMA input*/ - if (dsp->sb_type < SB2) break; - sb_start_dma_i(dsp, 1, 1, 0, dsp->sb_8_autolen); - break; - case 0x99: /*High speed 8-bit single cycle DMA input*/ - if (dsp->sb_type < SB2) break; - sb_start_dma_i(dsp, 1, 0, 0, dsp->sb_8_autolen); - break; - case 0xA0: /*Set input mode to mono*/ - case 0xA8: /*Set input mode to stereo*/ - if (dsp->sb_type < SB2 || dsp->sb_type > SBPRO2) break; + break; + case 0x90: /* High speed 8-bit autoinit DMA output */ + if (dsp->sb_type >= SB2) + sb_start_dma(dsp, 1, 1, 0, dsp->sb_8_autolen); + break; + case 0x91: /* High speed 8-bit single cycle DMA output */ + if (dsp->sb_type >= SB2) + sb_start_dma(dsp, 1, 0, 0, dsp->sb_8_autolen); + break; + case 0x98: /* High speed 8-bit autoinit DMA input */ + if (dsp->sb_type >= SB2) + sb_start_dma_i(dsp, 1, 1, 0, dsp->sb_8_autolen); + break; + case 0x99: /* High speed 8-bit single cycle DMA input */ + if (dsp->sb_type >= SB2) + sb_start_dma_i(dsp, 1, 0, 0, dsp->sb_8_autolen); + break; + case 0xA0: /* Set input mode to mono */ + case 0xA8: /* Set input mode to stereo */ + if ((dsp->sb_type < SB2) || (dsp->sb_type > SBPRO2)) + break; /* TODO: Implement. 3.xx-only command. */ - break; - case 0xB0: case 0xB1: case 0xB2: case 0xB3: - case 0xB4: case 0xB5: case 0xB6: case 0xB7: /*16-bit DMA output*/ - if (dsp->sb_type < SB16) break; - sb_start_dma(dsp, 0, dsp->sb_command & 4, dsp->sb_data[0], dsp->sb_data[1] + (dsp->sb_data[2] << 8)); - dsp->sb_16_autolen = dsp->sb_data[1] + (dsp->sb_data[2] << 8); - break; - case 0xB8: case 0xB9: case 0xBA: case 0xBB: - case 0xBC: case 0xBD: case 0xBE: case 0xBF: /*16-bit DMA input*/ - if (dsp->sb_type < SB16) break; - sb_start_dma_i(dsp, 0, dsp->sb_command & 4, dsp->sb_data[0], dsp->sb_data[1] + (dsp->sb_data[2] << 8)); - dsp->sb_16_autolen = dsp->sb_data[1] + (dsp->sb_data[2] << 8); - break; - case 0xC0: case 0xC1: case 0xC2: case 0xC3: - case 0xC4: case 0xC5: case 0xC6: case 0xC7: /*8-bit DMA output*/ - if (dsp->sb_type < SB16) break; - sb_start_dma(dsp, 1, dsp->sb_command & 4, dsp->sb_data[0], dsp->sb_data[1] + (dsp->sb_data[2] << 8)); - dsp->sb_8_autolen = dsp->sb_data[1] + (dsp->sb_data[2] << 8); - break; - case 0xC8: case 0xC9: case 0xCA: case 0xCB: - case 0xCC: case 0xCD: case 0xCE: case 0xCF: /*8-bit DMA input*/ - if (dsp->sb_type < SB16) break; - sb_start_dma_i(dsp, 1, dsp->sb_command & 4, dsp->sb_data[0], dsp->sb_data[1] + (dsp->sb_data[2] << 8)); - dsp->sb_8_autolen = dsp->sb_data[1] + (dsp->sb_data[2] << 8); - break; - case 0xD0: /*Pause 8-bit DMA*/ - dsp->sb_8_pause = 1; - break; - case 0xD1: /*Speaker on*/ - if (dsp->sb_type < SB15 ) - dsp->sb_8_pause = 1; - else if ( dsp->sb_type < SB16 ) - dsp->muted = 0; - dsp->sb_speaker = 1; - break; - case 0xD3: /*Speaker off*/ - if (dsp->sb_type < SB15 ) - dsp->sb_8_pause = 1; - else if ( dsp->sb_type < SB16 ) - dsp->muted = 1; - dsp->sb_speaker = 0; - break; - case 0xD4: /*Continue 8-bit DMA*/ - dsp->sb_8_pause = 0; - break; - case 0xD5: /*Pause 16-bit DMA*/ - if (dsp->sb_type < SB16) break; - dsp->sb_16_pause = 1; - break; - case 0xD6: /*Continue 16-bit DMA*/ - if (dsp->sb_type < SB16) break; - dsp->sb_16_pause = 0; - break; - case 0xD8: /*Get speaker status*/ - sb_add_data(dsp, dsp->sb_speaker ? 0xff : 0); - break; - case 0xD9: /*Exit 16-bit auto-init mode*/ - if (dsp->sb_type < SB16) break; - dsp->sb_16_autoinit = 0; - break; - case 0xDA: /*Exit 8-bit auto-init mode*/ - dsp->sb_8_autoinit = 0; - break; - case 0xE0: /*DSP identification*/ - sb_add_data(dsp, ~dsp->sb_data[0]); - break; - case 0xE1: /*Get DSP version*/ - sb_add_data(dsp, sb_dsp_versions[dsp->sb_type] >> 8); - sb_add_data(dsp, sb_dsp_versions[dsp->sb_type] & 0xff); - break; - case 0xE2: /*Stupid ID/protection*/ - for (c = 0; c < 8; c++) - if (dsp->sb_data[0] & (1 << c)) dsp->sbe2 += sbe2dat[dsp->sbe2count & 3][c]; - dsp->sbe2 += sbe2dat[dsp->sbe2count & 3][8]; - dsp->sbe2count++; - sb_8_write_dma(dsp, dsp->sbe2); - break; - case 0xE3: /*DSP copyright*/ - if (dsp->sb_type < SB16) break; - c = 0; - while (sb16_copyright[c]) - sb_add_data(dsp, sb16_copyright[c++]); - sb_add_data(dsp, 0); - break; - case 0xE4: /*Write test register*/ - dsp->sb_test = dsp->sb_data[0]; - break; - case 0xE8: /*Read test register*/ - sb_add_data(dsp, dsp->sb_test); - break; - case 0xF2: /*Trigger 8-bit IRQ*/ - sb_dsp_log("Trigger IRQ\n"); - sb_irq(dsp, 1); - break; - case 0xF3: /*Trigger 16-bit IRQ*/ - sb_dsp_log("Trigger IRQ\n"); - sb_irq(dsp, 0); - break; - case 0xE7: /*???*/ - case 0xFA: /*???*/ - break; - case 0x07: /*No, that's not how you program auto-init DMA*/ - case 0xFF: - break; - case 0x08: /*ASP get version*/ - if (dsp->sb_type < SB16) break; - sb_add_data(dsp, 0x18); - break; - case 0x0E: /*ASP set register*/ - if (dsp->sb_type < SB16) break; - dsp->sb_asp_regs[dsp->sb_data[0]] = dsp->sb_data[1]; - break; - case 0x0F: /*ASP get register*/ - 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); - else if (dsp->sb_data[0] == 0x0f) sb_add_data(dsp, 0x07); - else if (dsp->sb_data[0] == 0x37) sb_add_data(dsp, 0x38); - else sb_add_data(dsp, 0x00); - case 0x04: - case 0x05: - break; - - /*TODO: Some more data about the DSP registeres - * http://the.earth.li/~tfm/oldpage/sb_dsp.html - * http://www.synchrondata.com/pheaven/www/area19.htm - * http://www.dcee.net/Files/Programm/Sound/ - 0E3h DSP Copyright SBPro2??? - 0F0h Sine Generator SB - 0F1h DSP Auxiliary Status (Obsolete) SB-Pro2 - 0F2h IRQ Request, 8-bit SB - 0F3h IRQ Request, 16-bit SB16 - 0FBh DSP Status SB16 - 0FCh DSP Auxiliary Status SB16 - 0FDh DSP Command Status SB16 - */ - - } -} - -void sb_write(uint16_t a, uint8_t v, void *priv) -{ - sb_dsp_t *dsp = (sb_dsp_t *)priv; - switch (a&0xF) - { - case 6: /*Reset*/ - if (!(v & 1) && (dsp->sbreset & 1)) - { - sb_dsp_reset(dsp); - sb_add_data(dsp, 0xAA); - } - dsp->sbreset = v; - return; - case 0xC: /*Command/data write*/ - if (dsp->uart_midi || dsp->onebyte_midi) - { - midi_write(v); - dsp->onebyte_midi = 0; - return; - } - timer_set_delay_u64(&dsp->wb_timer, TIMER_USEC * 1); - if (dsp->asp_data_len) - { - sb_dsp_log("ASP data %i\n", dsp->asp_data_len); - dsp->asp_data_len--; - if (!dsp->asp_data_len) - sb_add_data(dsp, 0); - return; - } - if (dsp->sb_data_stat == -1) - { - dsp->sb_command = v; - if (v == 0x01) - sb_add_data(dsp, 0); - dsp->sb_data_stat++; - } - else - dsp->sb_data[dsp->sb_data_stat++] = v; - if (dsp->sb_data_stat == sb_commands[dsp->sb_command] || sb_commands[dsp->sb_command] == -1) - { - sb_exec_command(dsp); - dsp->sb_data_stat = -1; - } - break; - } -} - -uint8_t sb_read(uint16_t a, void *priv) -{ - sb_dsp_t *dsp = (sb_dsp_t *)priv; - switch (a & 0xf) - { - case 0xA: /*Read data*/ - if (mpu && dsp->uart_midi) - { - return MPU401_ReadData(mpu); + break; + case 0xB0: case 0xB1: case 0xB2: case 0xB3: + case 0xB4: case 0xB5: case 0xB6: case 0xB7: /* 16-bit DMA output */ + if (dsp->sb_type >= SB16) { + sb_start_dma(dsp, 0, dsp->sb_command & 4, dsp->sb_data[0], dsp->sb_data[1] + (dsp->sb_data[2] << 8)); + dsp->sb_16_autolen = dsp->sb_data[1] + (dsp->sb_data[2] << 8); } - dsp->sbreaddat = dsp->sb_read_data[dsp->sb_read_rp]; - if (dsp->sb_read_rp != dsp->sb_read_wp) - { - dsp->sb_read_rp++; - dsp->sb_read_rp &= 0xFF; - } - return dsp->sbreaddat; - case 0xC: /*Write data ready*/ - if (dsp->sb_8_enable || dsp->sb_type >= SB16) - dsp->busy_count = (dsp->busy_count + 1) & 3; - else - dsp->busy_count = 0; - if (dsp->wb_full || (dsp->busy_count & 2)) - { - dsp->wb_full = timer_is_enabled(&dsp->wb_timer); - return 0xff; - } - return 0x7f; - case 0xE: /*Read data ready*/ - picintc(1 << dsp->sb_irqnum); - dsp->sb_irq8 = dsp->sb_irq16 = 0; - return (dsp->sb_read_rp == dsp->sb_read_wp) ? 0x7f : 0xff; - case 0xF: /*16-bit ack*/ - dsp->sb_irq16 = 0; - if (!dsp->sb_irq8) picintc(1 << dsp->sb_irqnum); - return 0xff; + break; + case 0xB8: case 0xB9: case 0xBA: case 0xBB: + case 0xBC: case 0xBD: case 0xBE: case 0xBF: /* 16-bit DMA input */ + if (dsp->sb_type >= SB16) { + sb_start_dma_i(dsp, 0, dsp->sb_command & 4, dsp->sb_data[0], dsp->sb_data[1] + (dsp->sb_data[2] << 8)); + dsp->sb_16_autolen = dsp->sb_data[1] + (dsp->sb_data[2] << 8); + } + break; + case 0xC0: case 0xC1: case 0xC2: case 0xC3: + case 0xC4: case 0xC5: case 0xC6: case 0xC7: /* 8-bit DMA output */ + if (dsp->sb_type >= SB16) { + sb_start_dma(dsp, 1, dsp->sb_command & 4, dsp->sb_data[0], dsp->sb_data[1] + (dsp->sb_data[2] << 8)); + dsp->sb_8_autolen = dsp->sb_data[1] + (dsp->sb_data[2] << 8); + } + break; + case 0xC8: case 0xC9: case 0xCA: case 0xCB: + case 0xCC: case 0xCD: case 0xCE: case 0xCF: /* 8-bit DMA input */ + if (dsp->sb_type >= SB16) { + sb_start_dma_i(dsp, 1, dsp->sb_command & 4, dsp->sb_data[0], dsp->sb_data[1] + (dsp->sb_data[2] << 8)); + dsp->sb_8_autolen = dsp->sb_data[1] + (dsp->sb_data[2] << 8); + } + break; + case 0xD0: /* Pause 8-bit DMA */ + dsp->sb_8_pause = 1; + break; + case 0xD1: /* Speaker on */ + if (dsp->sb_type < SB15) + dsp->sb_8_pause = 1; + else if (dsp->sb_type < SB16) + dsp->muted = 0; + dsp->sb_speaker = 1; + break; + case 0xD3: /* Speaker off */ + if (dsp->sb_type < SB15 ) + dsp->sb_8_pause = 1; + else if (dsp->sb_type < SB16) + dsp->muted = 1; + dsp->sb_speaker = 0; + break; + case 0xD4: /* Continue 8-bit DMA */ + dsp->sb_8_pause = 0; + break; + case 0xD5: /* Pause 16-bit DMA */ + if (dsp->sb_type >= SB16) + dsp->sb_16_pause = 1; + break; + case 0xD6: /* Continue 16-bit DMA */ + if (dsp->sb_type >= SB16) + dsp->sb_16_pause = 0; + break; + case 0xD8: /* Get speaker status */ + sb_add_data(dsp, dsp->sb_speaker ? 0xff : 0); + break; + case 0xD9: /* Exit 16-bit auto-init mode */ + if (dsp->sb_type >= SB16) + dsp->sb_16_autoinit = 0; + break; + case 0xDA: /* Exit 8-bit auto-init mode */ + dsp->sb_8_autoinit = 0; + break; + case 0xE0: /* DSP identification */ + sb_add_data(dsp, ~dsp->sb_data[0]); + break; + case 0xE1: /* Get DSP version */ + sb_add_data(dsp, sb_dsp_versions[dsp->sb_type] >> 8); + sb_add_data(dsp, sb_dsp_versions[dsp->sb_type] & 0xff); + break; + case 0xE2: /* Stupid ID/protection */ + for (c = 0; c < 8; c++) { + if (dsp->sb_data[0] & (1 << c)) + dsp->sbe2 += sbe2dat[dsp->sbe2count & 3][c]; + } + dsp->sbe2 += sbe2dat[dsp->sbe2count & 3][8]; + dsp->sbe2count++; + sb_8_write_dma(dsp, dsp->sbe2); + break; + case 0xE3: /* DSP copyright */ + if (dsp->sb_type >= SB16) { + c = 0; + while (sb16_copyright[c]) + sb_add_data(dsp, sb16_copyright[c++]); + sb_add_data(dsp, 0); + } + break; + case 0xE4: /* Write test register */ + dsp->sb_test = dsp->sb_data[0]; + break; + case 0xE8: /* Read test register */ + sb_add_data(dsp, dsp->sb_test); + break; + case 0xF2: /* Trigger 8-bit IRQ */ + sb_dsp_log("Trigger IRQ\n"); + sb_irq(dsp, 1); + break; + case 0xF3: /* Trigger 16-bit IRQ */ + sb_dsp_log("Trigger IRQ\n"); + sb_irq(dsp, 0); + break; + case 0xE7: case 0xFA: /* ???? */ + break; + case 0x07: case 0xFF: /* No, that's not how you program auto-init DMA */ + break; + case 0x08: /* ASP get version */ + if (dsp->sb_type >= SB16) + sb_add_data(dsp, 0x18); + break; + case 0x0E: /* ASP set register */ + if (dsp->sb_type >= SB16) + dsp->sb_asp_regs[dsp->sb_data[0]] = dsp->sb_data[1]; + break; + case 0x0F: /* ASP get register */ + if (dsp->sb_type >= SB16) + sb_add_data(dsp, dsp->sb_asp_regs[dsp->sb_data[0]]); + break; + case 0xF8: + if (dsp->sb_type < SB16) + sb_add_data(dsp, 0); + break; + case 0xF9: + if (dsp->sb_type >= SB16) { + if (dsp->sb_data[0] == 0x0e) + sb_add_data(dsp, 0xff); + else if (dsp->sb_data[0] == 0x0f) + sb_add_data(dsp, 0x07); + else if (dsp->sb_data[0] == 0x37) + sb_add_data(dsp, 0x38); + else + sb_add_data(dsp, 0x00); + } + case 0x04: case 0x05: + break; + + /* TODO: Some more data about the DSP registeres + * http://the.earth.li/~tfm/oldpage/sb_dsp.html + * http://www.synchrondata.com/pheaven/www/area19.htm + * http://www.dcee.net/Files/Programm/Sound/ + * 0E3h DSP Copyright SBPro2??? + * 0F0h Sine Generator SB + * 0F1h DSP Auxiliary Status (Obsolete) SB-Pro2 + * 0F2h IRQ Request, 8-bit SB + * 0F3h IRQ Request, 16-bit SB16 + * 0FBh DSP Status SB16 + * 0FCh DSP Auxiliary Status SB16 + * 0FDh DSP Command Status SB16 + */ + } +} + + +void +sb_write(uint16_t a, uint8_t v, void *priv) +{ + sb_dsp_t *dsp = (sb_dsp_t *) priv; + + switch (a & 0xF) { + case 6: /* Reset */ + if (!(v & 1) && (dsp->sbreset & 1)) { + sb_dsp_reset(dsp); + sb_add_data(dsp, 0xAA); + } + dsp->sbreset = v; + return; + case 0xC: /* Command/data write */ + if (dsp->uart_midi || dsp->onebyte_midi) { + midi_write(v); + dsp->onebyte_midi = 0; + return; + } + timer_set_delay_u64(&dsp->wb_timer, TIMER_USEC * 1); + if (dsp->asp_data_len) { + sb_dsp_log("ASP data %i\n", dsp->asp_data_len); + dsp->asp_data_len--; + if (!dsp->asp_data_len) + sb_add_data(dsp, 0); + return; + } + if (dsp->sb_data_stat == -1) { + dsp->sb_command = v; + if (v == 0x01) + sb_add_data(dsp, 0); + dsp->sb_data_stat++; + } else + dsp->sb_data[dsp->sb_data_stat++] = v; + if (dsp->sb_data_stat == sb_commands[dsp->sb_command] || sb_commands[dsp->sb_command] == -1) { + sb_exec_command(dsp); + dsp->sb_data_stat = -1; + } + break; + } +} + + +uint8_t +sb_read(uint16_t a, void *priv) +{ + sb_dsp_t *dsp = (sb_dsp_t *) priv; + uint8_t ret = 0x00; + + switch (a & 0xf) { + case 0xA: /* Read data */ + if (mpu && dsp->uart_midi) + ret = MPU401_ReadData(mpu); + else { + dsp->sbreaddat = dsp->sb_read_data[dsp->sb_read_rp]; + if (dsp->sb_read_rp != dsp->sb_read_wp) { + dsp->sb_read_rp++; + dsp->sb_read_rp &= 0xff; + } + return dsp->sbreaddat; + } + break; + case 0xC: /* Write data ready */ + if (dsp->sb_8_enable || dsp->sb_type >= SB16) + dsp->busy_count = (dsp->busy_count + 1) & 3; + else + dsp->busy_count = 0; + if (dsp->wb_full || (dsp->busy_count & 2)) { + dsp->wb_full = timer_is_enabled(&dsp->wb_timer); + return 0xff; + } + ret = 0x7f; + break; + case 0xE: /* Read data ready */ + picintc(1 << dsp->sb_irqnum); + dsp->sb_irq8 = dsp->sb_irq16 = 0; + ret = (dsp->sb_read_rp == dsp->sb_read_wp) ? 0x7f : 0xff; + break; + case 0xF: /* 16-bit ack */ + dsp->sb_irq16 = 0; + if (!dsp->sb_irq8) + picintc(1 << dsp->sb_irqnum); + ret = 0xff; + break; } - return 0; + + return ret; } -static void sb_wb_clear(void *p) + +/* This should not even be needed. */ +void +sb_dsp_set_mpu(mpu_t *src_mpu) { + mpu = src_mpu; } -void sb_dsp_set_mpu(mpu_t *src_mpu) + +void +sb_dsp_init(sb_dsp_t *dsp, int type) { - mpu = src_mpu; + dsp->sb_type = type; + + /* Default values. Use sb_dsp_setxxx() methods to change. */ + dsp->sb_irqnum = 7; + dsp->sb_8_dmanum = 1; + dsp->sb_16_dmanum = 5; + mpu = NULL; + + sb_doreset(dsp); + + timer_add(&dsp->output_timer, pollsb, dsp, 0); + timer_add(&dsp->input_timer, sb_poll_i, dsp, 0); + timer_add(&dsp->wb_timer, NULL, dsp, 0); + + /* Initialise SB16 filter to same cutoff as 8-bit SBs (3.2 kHz). This will be recalculated when + a set frequency command is sent. */ + recalc_sb16_filter(3200*2); } -void sb_dsp_init(sb_dsp_t *dsp, int type) + +void +sb_dsp_setaddr(sb_dsp_t *dsp, uint16_t addr) { - dsp->sb_type = type; - - // Default values. Use sb_dsp_setxxx() methods to change. - dsp->sb_irqnum = 7; - dsp->sb_8_dmanum = 1; - dsp->sb_16_dmanum = 5; - mpu = NULL; - - sb_doreset(dsp); - - timer_add(&dsp->output_timer, pollsb, dsp, 0); - timer_add(&dsp->input_timer, sb_poll_i, dsp, 0); - timer_add(&dsp->wb_timer, sb_wb_clear, dsp, 0); - - /*Initialise SB16 filter to same cutoff as 8-bit SBs (3.2 kHz). This will be recalculated when - a set frequency command is sent.*/ - recalc_sb16_filter(3200*2); + sb_dsp_log("sb_dsp_setaddr : %04X\n", addr); + if (dsp->sb_addr != 0) { + io_removehandler(dsp->sb_addr + 6, 0x0002, sb_read, NULL, NULL, sb_write, NULL, NULL, dsp); + io_removehandler(dsp->sb_addr + 0xa, 0x0006, sb_read, NULL, NULL, sb_write, NULL, NULL, dsp); + } + dsp->sb_addr = addr; + if (dsp->sb_addr != 0) { + io_sethandler(dsp->sb_addr + 6, 0x0002, sb_read, NULL, NULL, sb_write, NULL, NULL, dsp); + io_sethandler(dsp->sb_addr + 0xa, 0x0006, sb_read, NULL, NULL, sb_write, NULL, NULL, dsp); + } } -void sb_dsp_setaddr(sb_dsp_t *dsp, uint16_t addr) + +void +sb_dsp_set_stereo(sb_dsp_t *dsp, int stereo) { - sb_dsp_log("sb_dsp_setaddr : %04X\n", addr); - if (dsp->sb_addr != 0) { - io_removehandler(dsp->sb_addr + 6, 0x0002, sb_read, NULL, NULL, sb_write, NULL, NULL, dsp); - io_removehandler(dsp->sb_addr + 0xa, 0x0006, sb_read, NULL, NULL, sb_write, NULL, NULL, dsp); + dsp->stereo = stereo; +} + + +void +pollsb(void *p) +{ + sb_dsp_t *dsp = (sb_dsp_t *) p; + int tempi, ref; + int data[2]; + + timer_advance_u64(&dsp->output_timer, dsp->sblatcho); + if (dsp->sb_8_enable && !dsp->sb_8_pause && dsp->sb_pausetime < 0 && dsp->sb_8_output) { + sb_dsp_update(dsp); + + switch (dsp->sb_8_format) { + case 0x00: /* Mono unsigned */ + data[0] = sb_8_read_dma(dsp); + /* Needed to prevent clicking in Worms, which programs the DSP to + auto-init DMA but programs the DMA controller to single cycle */ + if (data[0] == DMA_NODATA) + break; + dsp->sbdat = (data[0] ^ 0x80) << 8; + if ((dsp->sb_type >= SBPRO) && (dsp->sb_type < SB16) && dsp->stereo) { + pclog("pollsb: Mono unsigned, dsp->stereo, %s channel, %04X\n", + dsp->sbleftright ? "left" : "right", dsp->sbdat); + if (dsp->sbleftright) + dsp->sbdatl = dsp->sbdat; + else + dsp->sbdatr = dsp->sbdat; + dsp->sbleftright = !dsp->sbleftright; + } else + dsp->sbdatl = dsp->sbdatr = dsp->sbdat; + dsp->sb_8_length--; + break; + case 0x10: /* Mono signed */ + data[0] = sb_8_read_dma(dsp); + if (data[0] == DMA_NODATA) + break; + dsp->sbdat = data[0] << 8; + if ((dsp->sb_type >= SBPRO) && (dsp->sb_type < SB16) && dsp->stereo) { + pclog("pollsb: Mono signed, dsp->stereo, %s channel, %04X\n", + dsp->sbleftright ? "left" : "right", data[0], dsp->sbdat); + if (dsp->sbleftright) + dsp->sbdatl = dsp->sbdat; + else + dsp->sbdatr = dsp->sbdat; + dsp->sbleftright = !dsp->sbleftright; + } else + dsp->sbdatl = dsp->sbdatr = dsp->sbdat; + dsp->sb_8_length--; + break; + case 0x20: /* Stereo unsigned */ + data[0] = sb_8_read_dma(dsp); + data[1] = sb_8_read_dma(dsp); + if ((data[0] == DMA_NODATA) || (data[1] == DMA_NODATA)) + break; + dsp->sbdatl = (data[0] ^ 0x80) << 8; + dsp->sbdatr = (data[1] ^ 0x80) << 8; + dsp->sb_8_length -= 2; + break; + case 0x30: /* Stereo signed */ + data[0] = sb_8_read_dma(dsp); + data[1] = sb_8_read_dma(dsp); + if ((data[0] == DMA_NODATA) || (data[1] == DMA_NODATA)) + break; + dsp->sbdatl = data[0] << 8; + dsp->sbdatr = data[1] << 8; + dsp->sb_8_length -= 2; + break; + + case ADPCM_4: + if (dsp->sbdacpos) + tempi = (dsp->sbdat2 & 0xF) + dsp->sbstep; + else + tempi = (dsp->sbdat2 >> 4) + dsp->sbstep; + if (tempi < 0) + tempi = 0; + if (tempi > 63) + tempi = 63; + + ref = dsp->sbref + scaleMap4[tempi]; + if (ref > 0xff) + dsp->sbref = 0xff; + else if (ref < 0x00) + dsp->sbref = 0x00; + else + dsp->sbref = ref; + + dsp->sbstep = (dsp->sbstep + adjustMap4[tempi]) & 0xff; + dsp->sbdat = (dsp->sbref ^ 0x80) << 8; + + dsp->sbdacpos++; + + if (dsp->sbdacpos >= 2) { + dsp->sbdacpos = 0; + dsp->sbdat2 = sb_8_read_dma(dsp); + dsp->sb_8_length--; + } + + if ((dsp->sb_type >= SBPRO) && (dsp->sb_type < SB16) && dsp->stereo) { + pclog("pollsb: ADPCM 4, dsp->stereo, %s channel, %04X\n", + dsp->sbleftright ? "left" : "right", dsp->sbdat); + if (dsp->sbleftright) + dsp->sbdatl = dsp->sbdat; + else + dsp->sbdatr = dsp->sbdat; + dsp->sbleftright = !dsp->sbleftright; + } else + dsp->sbdatl = dsp->sbdatr = dsp->sbdat; + break; + + case ADPCM_26: + if (!dsp->sbdacpos) + tempi = (dsp->sbdat2 >> 5) + dsp->sbstep; + else if (dsp->sbdacpos == 1) + tempi = ((dsp->sbdat2 >> 2) & 7) + dsp->sbstep; + else + tempi = ((dsp->sbdat2 << 1) & 7) + dsp->sbstep; + + if (tempi < 0) + tempi = 0; + if (tempi > 39) + tempi = 39; + + ref = dsp->sbref + scaleMap26[tempi]; + if (ref > 0xff) + dsp->sbref = 0xff; + else if (ref < 0x00) + dsp->sbref = 0x00; + else + dsp->sbref = ref; + dsp->sbstep = (dsp->sbstep + adjustMap26[tempi]) & 0xff; + + dsp->sbdat = (dsp->sbref ^ 0x80) << 8; + + dsp->sbdacpos++; + if (dsp->sbdacpos >= 3) { + dsp->sbdacpos = 0; + dsp->sbdat2 = sb_8_read_dma(dsp); + dsp->sb_8_length--; + } + + if ((dsp->sb_type >= SBPRO) && (dsp->sb_type < SB16) && dsp->stereo) { + pclog("pollsb: ADPCM 26, dsp->stereo, %s channel, %04X\n", + dsp->sbleftright ? "left" : "right", dsp->sbdat); + if (dsp->sbleftright) + dsp->sbdatl = dsp->sbdat; + else + dsp->sbdatr = dsp->sbdat; + dsp->sbleftright = !dsp->sbleftright; + } else + dsp->sbdatl = dsp->sbdatr = dsp->sbdat; + break; + + case ADPCM_2: + tempi = ((dsp->sbdat2 >> ((3 - dsp->sbdacpos) * 2)) & 3) + dsp->sbstep; + if (tempi < 0) + tempi = 0; + if (tempi > 23) + tempi = 23; + + ref = dsp->sbref + scaleMap2[tempi]; + if (ref > 0xff) + dsp->sbref = 0xff; + else if (ref < 0x00) + dsp->sbref = 0x00; + else + dsp->sbref = ref; + dsp->sbstep = (dsp->sbstep + adjustMap2[tempi]) & 0xff; + + dsp->sbdat = (dsp->sbref ^ 0x80) << 8; + + dsp->sbdacpos++; + if (dsp->sbdacpos >= 4) { + dsp->sbdacpos = 0; + dsp->sbdat2 = sb_8_read_dma(dsp); + } + + if ((dsp->sb_type >= SBPRO) && (dsp->sb_type < SB16) && dsp->stereo) { + pclog("pollsb: ADPCM 2, dsp->stereo, %s channel, %04X\n", + dsp->sbleftright ? "left" : "right", dsp->sbdat); + if (dsp->sbleftright) + dsp->sbdatl = dsp->sbdat; + else + dsp->sbdatr = dsp->sbdat; + dsp->sbleftright = !dsp->sbleftright; + } else + dsp->sbdatl = dsp->sbdatr = dsp->sbdat; + break; } - dsp->sb_addr = addr; - if (dsp->sb_addr != 0) { - io_sethandler(dsp->sb_addr + 6, 0x0002, sb_read, NULL, NULL, sb_write, NULL, NULL, dsp); - io_sethandler(dsp->sb_addr + 0xa, 0x0006, sb_read, NULL, NULL, sb_write, NULL, NULL, dsp); - } + + if (dsp->sb_8_length < 0) { + if (dsp->sb_8_autoinit) + dsp->sb_8_length = dsp->sb_8_autolen; + else { + dsp->sb_8_enable = 0; + timer_disable(&dsp->output_timer); + } + sb_irq(dsp, 1); + } + } if (dsp->sb_16_enable && !dsp->sb_16_pause && (dsp->sb_pausetime < 0LL) && dsp->sb_16_output) { + sb_dsp_update(dsp); + + switch (dsp->sb_16_format) { + case 0x00: /* Mono unsigned */ + data[0] = sb_16_read_dma(dsp); + if (data[0] == DMA_NODATA) + break; + dsp->sbdatl = dsp->sbdatr = data[0] ^ 0x8000; + dsp->sb_16_length--; + break; + case 0x10: /* Mono signed */ + data[0] = sb_16_read_dma(dsp); + if (data[0] == DMA_NODATA) + break; + dsp->sbdatl = dsp->sbdatr = data[0]; + dsp->sb_16_length--; + break; + case 0x20: /* Stereo unsigned */ + data[0] = sb_16_read_dma(dsp); + data[1] = sb_16_read_dma(dsp); + if ((data[0] == DMA_NODATA) || (data[1] == DMA_NODATA)) + break; + dsp->sbdatl = data[0] ^ 0x8000; + dsp->sbdatr = data[1] ^ 0x8000; + dsp->sb_16_length -= 2; + break; + case 0x30: /* Stereo signed */ + data[0] = sb_16_read_dma(dsp); + data[1] = sb_16_read_dma(dsp); + if ((data[0] == DMA_NODATA) || (data[1] == DMA_NODATA)) + break; + dsp->sbdatl = data[0]; + dsp->sbdatr = data[1]; + dsp->sb_16_length -= 2; + break; + } + + if (dsp->sb_16_length < 0) { + sb_dsp_log("16DMA over %i\n", dsp->sb_16_autoinit); + if (dsp->sb_16_autoinit) + dsp->sb_16_length = dsp->sb_16_autolen; + else { + dsp->sb_16_enable = 0; + timer_disable(&dsp->output_timer); + } + sb_irq(dsp, 0); + } + } + if (dsp->sb_pausetime > -1) { + dsp->sb_pausetime--; + if (dsp->sb_pausetime < 0) { + sb_irq(dsp, 1); + if (!dsp->sb_8_enable) + timer_disable(&dsp->output_timer); + sb_dsp_log("SB pause over\n"); + } + } } -void sb_dsp_set_stereo(sb_dsp_t *dsp, int stereo) + +void +sb_poll_i(void *p) { - dsp->stereo = stereo; + sb_dsp_t *dsp = (sb_dsp_t *) p; + int processed = 0; + + timer_advance_u64(&dsp->input_timer, dsp->sblatchi); + + if (dsp->sb_8_enable && !dsp->sb_8_pause && dsp->sb_pausetime < 0 && !dsp->sb_8_output) { + switch (dsp->sb_8_format) { + case 0x00: /* Mono unsigned As the manual says, only the left channel is recorded */ + sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read]>>8) ^0x80); + dsp->sb_8_length--; + dsp->record_pos_read += 2; + dsp->record_pos_read &= 0xFFFF; + break; + case 0x10: /* Mono signed As the manual says, only the left channel is recorded */ + sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read]>>8)); + dsp->sb_8_length--; + dsp->record_pos_read += 2; + dsp->record_pos_read &= 0xFFFF; + break; + case 0x20: /* Stereo unsigned */ + sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read]>>8)^0x80); + sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read+1]>>8)^0x80); + dsp->sb_8_length -= 2; + dsp->record_pos_read += 2; + dsp->record_pos_read &= 0xFFFF; + break; + case 0x30: /* Stereo signed */ + sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read]>>8)); + sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read+1]>>8)); + dsp->sb_8_length -= 2; + dsp->record_pos_read += 2; + dsp->record_pos_read &= 0xFFFF; + break; + } + + if (dsp->sb_8_length < 0) { + if (dsp->sb_8_autoinit) + dsp->sb_8_length = dsp->sb_8_autolen; + else { + dsp->sb_8_enable = 0; + timer_disable(&dsp->input_timer); + } + sb_irq(dsp, 1); + } + processed = 1; + } + if (dsp->sb_16_enable && !dsp->sb_16_pause && (dsp->sb_pausetime < 0LL) && !dsp->sb_16_output) { + switch (dsp->sb_16_format) { + case 0x00: /* Unsigned mono. As the manual says, only the left channel is recorded */ + if (sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read]^0x8000)) + return; + dsp->sb_16_length--; + dsp->record_pos_read += 2; + dsp->record_pos_read &= 0xFFFF; + break; + case 0x10: /* Signed mono. As the manual says, only the left channel is recorded */ + if (sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read])) + return; + dsp->sb_16_length--; + dsp->record_pos_read += 2; + dsp->record_pos_read &= 0xFFFF; + break; + case 0x20: /* Unsigned stereo */ + if (sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read]^0x8000)) + return; + sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read+1]^0x8000); + dsp->sb_16_length -= 2; + dsp->record_pos_read += 2; + dsp->record_pos_read &= 0xFFFF; + break; + case 0x30: /* Signed stereo */ + if (sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read])) + return; + sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read+1]); + dsp->sb_16_length -= 2; + dsp->record_pos_read += 2; + dsp->record_pos_read &= 0xFFFF; + break; + } + + if (dsp->sb_16_length < 0) { + if (dsp->sb_16_autoinit) + dsp->sb_16_length = dsp->sb_16_autolen; + else { + dsp->sb_16_enable = 0; + timer_disable(&dsp->input_timer); + } + sb_irq(dsp, 0); + } + processed = 1; + } + /* Assume this is direct mode */ + if (!processed) { + dsp->record_pos_read += 2; + dsp->record_pos_read &= 0xFFFF; + } } -void pollsb(void *p) -{ - sb_dsp_t *dsp = (sb_dsp_t *)p; - int tempi,ref; - - timer_advance_u64(&dsp->output_timer, dsp->sblatcho); - if (dsp->sb_8_enable && !dsp->sb_8_pause && dsp->sb_pausetime < 0 && dsp->sb_8_output) - { - int data[2]; - - sb_dsp_update(dsp); - switch (dsp->sb_8_format) - { - case 0x00: /*Mono unsigned*/ - data[0] = sb_8_read_dma(dsp); - /*Needed to prevent clicking in Worms, which programs the DSP to - auto-init DMA but programs the DMA controller to single cycle*/ - if (data[0] == DMA_NODATA) - break; - dsp->sbdat = (data[0] ^ 0x80) << 8; - if (dsp->sb_type >= SBPRO && dsp->sb_type < SB16 && dsp->stereo) - { - if (dsp->sbleftright) dsp->sbdatl = dsp->sbdat; - else dsp->sbdatr = dsp->sbdat; - dsp->sbleftright = !dsp->sbleftright; - } - else - dsp->sbdatl = dsp->sbdatr = dsp->sbdat; - dsp->sb_8_length--; - break; - case 0x10: /*Mono signed*/ - data[0] = sb_8_read_dma(dsp); - if (data[0] == DMA_NODATA) - break; - dsp->sbdat = data[0] << 8; - if (dsp->sb_type >= SBPRO && dsp->sb_type < SB16 && dsp->stereo) - { - if (dsp->sbleftright) dsp->sbdatl = dsp->sbdat; - else dsp->sbdatr = dsp->sbdat; - dsp->sbleftright = !dsp->sbleftright; - } - else - dsp->sbdatl = dsp->sbdatr = dsp->sbdat; - dsp->sb_8_length--; - break; - case 0x20: /*Stereo unsigned*/ - data[0] = sb_8_read_dma(dsp); - data[1] = sb_8_read_dma(dsp); - if (data[0] == DMA_NODATA || data[1] == DMA_NODATA) - break; - dsp->sbdatl = (data[0] ^ 0x80) << 8; - dsp->sbdatr = (data[1] ^ 0x80) << 8; - dsp->sb_8_length -= 2; - break; - case 0x30: /*Stereo signed*/ - data[0] = sb_8_read_dma(dsp); - data[1] = sb_8_read_dma(dsp); - if (data[0] == DMA_NODATA || data[1] == DMA_NODATA) - break; - dsp->sbdatl = data[0] << 8; - dsp->sbdatr = data[1] << 8; - dsp->sb_8_length -= 2; - break; - - case ADPCM_4: - if (dsp->sbdacpos) tempi = (dsp->sbdat2 & 0xF) + dsp->sbstep; - else tempi = (dsp->sbdat2 >> 4) + dsp->sbstep; - if (tempi < 0) tempi = 0; - if (tempi > 63) tempi = 63; - - ref = dsp->sbref + scaleMap4[tempi]; - if (ref > 0xff) dsp->sbref = 0xff; - else if (ref < 0x00) dsp->sbref = 0x00; - else dsp->sbref = ref; - - dsp->sbstep = (dsp->sbstep + adjustMap4[tempi]) & 0xff; - - dsp->sbdat = (dsp->sbref ^ 0x80) << 8; - - dsp->sbdacpos++; - if (dsp->sbdacpos >= 2) - { - dsp->sbdacpos = 0; - dsp->sbdat2 = sb_8_read_dma(dsp); - dsp->sb_8_length--; - } - - if (dsp->sb_type >= SBPRO && dsp->sb_type < SB16 && dsp->stereo) - { - if (dsp->sbleftright) dsp->sbdatl = dsp->sbdat; - else dsp->sbdatr = dsp->sbdat; - dsp->sbleftright = !dsp->sbleftright; - } - else - dsp->sbdatl = dsp->sbdatr = dsp->sbdat; - break; - - case ADPCM_26: - if (!dsp->sbdacpos) tempi = (dsp->sbdat2 >> 5) + dsp->sbstep; - else if (dsp->sbdacpos == 1) tempi = ((dsp->sbdat2 >> 2) & 7) + dsp->sbstep; - else tempi = ((dsp->sbdat2 << 1) & 7) + dsp->sbstep; - - if (tempi < 0) tempi = 0; - if (tempi > 39) tempi = 39; - - ref = dsp->sbref + scaleMap26[tempi]; - if (ref > 0xff) dsp->sbref = 0xff; - else if (ref < 0x00) dsp->sbref = 0x00; - else dsp->sbref = ref; - dsp->sbstep = (dsp->sbstep + adjustMap26[tempi]) & 0xff; - - dsp->sbdat = (dsp->sbref ^ 0x80) << 8; - - dsp->sbdacpos++; - if (dsp->sbdacpos>=3) - { - dsp->sbdacpos = 0; - dsp->sbdat2 = sb_8_read_dma(dsp); - dsp->sb_8_length--; - } - - if (dsp->sb_type >= SBPRO && dsp->sb_type < SB16 && dsp->stereo) - { - if (dsp->sbleftright) dsp->sbdatl = dsp->sbdat; - else dsp->sbdatr = dsp->sbdat; - dsp->sbleftright = !dsp->sbleftright; - } - else - dsp->sbdatl = dsp->sbdatr = dsp->sbdat; - break; - - case ADPCM_2: - tempi = ((dsp->sbdat2 >> ((3 - dsp->sbdacpos) * 2)) & 3) + dsp->sbstep; - if (tempi < 0) tempi = 0; - if (tempi > 23) tempi = 23; - - ref = dsp->sbref + scaleMap2[tempi]; - if (ref > 0xff) dsp->sbref = 0xff; - else if (ref < 0x00) dsp->sbref = 0x00; - else dsp->sbref = ref; - dsp->sbstep = (dsp->sbstep + adjustMap2[tempi]) & 0xff; - - dsp->sbdat = (dsp->sbref ^ 0x80) << 8; - - dsp->sbdacpos++; - if (dsp->sbdacpos >= 4) - { - dsp->sbdacpos = 0; - dsp->sbdat2 = sb_8_read_dma(dsp); - } - - if (dsp->sb_type >= SBPRO && dsp->sb_type < SB16 && dsp->stereo) - { - if (dsp->sbleftright) dsp->sbdatl = dsp->sbdat; - else dsp->sbdatr = dsp->sbdat; - dsp->sbleftright = !dsp->sbleftright; - } - else - dsp->sbdatl = dsp->sbdatr = dsp->sbdat; - break; - -// default: - //fatal("Unrecognised SB 8-bit format %02X\n",sb_8_format); - } - - if (dsp->sb_8_length < 0) - { - if (dsp->sb_8_autoinit) - dsp->sb_8_length = dsp->sb_8_autolen; - else { - dsp->sb_8_enable = 0; - timer_disable(&dsp->output_timer); - } - sb_irq(dsp, 1); - } - } - if (dsp->sb_16_enable && !dsp->sb_16_pause && dsp->sb_pausetime < 0LL && dsp->sb_16_output) - { - int data[2]; - - sb_dsp_update(dsp); - - switch (dsp->sb_16_format) - { - case 0x00: /*Mono unsigned*/ - data[0] = sb_16_read_dma(dsp); - if (data[0] == DMA_NODATA) - break; - dsp->sbdatl = dsp->sbdatr = data[0] ^ 0x8000; - dsp->sb_16_length--; - break; - case 0x10: /*Mono signed*/ - data[0] = sb_16_read_dma(dsp); - if (data[0] == DMA_NODATA) - break; - dsp->sbdatl = dsp->sbdatr = data[0]; - dsp->sb_16_length--; - break; - case 0x20: /*Stereo unsigned*/ - data[0] = sb_16_read_dma(dsp); - data[1] = sb_16_read_dma(dsp); - if (data[0] == DMA_NODATA || data[1] == DMA_NODATA) - break; - dsp->sbdatl = data[0] ^ 0x8000; - dsp->sbdatr = data[1] ^ 0x8000; - dsp->sb_16_length -= 2; - break; - case 0x30: /*Stereo signed*/ - data[0] = sb_16_read_dma(dsp); - data[1] = sb_16_read_dma(dsp); - if (data[0] == DMA_NODATA || data[1] == DMA_NODATA) - break; - dsp->sbdatl = data[0]; - dsp->sbdatr = data[1]; - dsp->sb_16_length -= 2; - break; - } - - if (dsp->sb_16_length < 0) - { - sb_dsp_log("16DMA over %i\n",dsp->sb_16_autoinit); - if (dsp->sb_16_autoinit) dsp->sb_16_length = dsp->sb_16_autolen; - else { - dsp->sb_16_enable = 0; - timer_disable(&dsp->output_timer); - } - sb_irq(dsp, 0); - } - } - if (dsp->sb_pausetime > -1) - { - dsp->sb_pausetime--; - if (dsp->sb_pausetime < 0) - { - sb_irq(dsp, 1); - if (!dsp->sb_8_enable) - timer_disable(&dsp->output_timer); - sb_dsp_log("SB pause over\n"); - } - } -} - -void sb_poll_i(void *p) -{ - sb_dsp_t *dsp = (sb_dsp_t *)p; - int processed=0; - timer_advance_u64(&dsp->input_timer, dsp->sblatchi); - if (dsp->sb_8_enable && !dsp->sb_8_pause && dsp->sb_pausetime < 0 && !dsp->sb_8_output) - { - switch (dsp->sb_8_format) - { - case 0x00: /*Mono unsigned As the manual says, only the left channel is recorded*/ - sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read]>>8) ^0x80); - dsp->sb_8_length--; - dsp->record_pos_read+=2; - dsp->record_pos_read&=0xFFFF; - break; - case 0x10: /*Mono signed As the manual says, only the left channel is recorded*/ - sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read]>>8)); - dsp->sb_8_length--; - dsp->record_pos_read+=2; - dsp->record_pos_read&=0xFFFF; - break; - case 0x20: /*Stereo unsigned*/ - sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read]>>8)^0x80); - sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read+1]>>8)^0x80); - dsp->sb_8_length -= 2; - dsp->record_pos_read+=2; - dsp->record_pos_read&=0xFFFF; - break; - case 0x30: /*Stereo signed*/ - sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read]>>8)); - sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read+1]>>8)); - dsp->sb_8_length -= 2; - dsp->record_pos_read+=2; - dsp->record_pos_read&=0xFFFF; - break; - } - - if (dsp->sb_8_length < 0) - { - if (dsp->sb_8_autoinit) - dsp->sb_8_length = dsp->sb_8_autolen; - else { - dsp->sb_8_enable = 0; - timer_disable(&dsp->input_timer); - } - sb_irq(dsp, 1); - } - processed=1; - } - if (dsp->sb_16_enable && !dsp->sb_16_pause && dsp->sb_pausetime < 0LL && !dsp->sb_16_output) - { - switch (dsp->sb_16_format) - { - case 0x00: /*Unsigned mono. As the manual says, only the left channel is recorded*/ - if (sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read]^0x8000)) - return; - dsp->sb_16_length--; - dsp->record_pos_read+=2; - dsp->record_pos_read&=0xFFFF; - break; - case 0x10: /*Signed mono. As the manual says, only the left channel is recorded*/ - if (sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read])) - return; - dsp->sb_16_length--; - dsp->record_pos_read+=2; - dsp->record_pos_read&=0xFFFF; - break; - case 0x20: /*Unsigned stereo*/ - if (sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read]^0x8000)) - return; - sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read+1]^0x8000); - dsp->sb_16_length -= 2; - dsp->record_pos_read+=2; - dsp->record_pos_read&=0xFFFF; - break; - case 0x30: /*Signed stereo*/ - if (sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read])) - return; - sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read+1]); - dsp->sb_16_length -= 2; - dsp->record_pos_read+=2; - dsp->record_pos_read&=0xFFFF; - break; - } - - if (dsp->sb_16_length < 0) - { - if (dsp->sb_16_autoinit) - dsp->sb_16_length = dsp->sb_16_autolen; - else { - dsp->sb_16_enable = 0; - timer_disable(&dsp->input_timer); - } - sb_irq(dsp, 0); - } - processed=1; - } - /* Assume this is direct mode */ - if (!processed) - { - dsp->record_pos_read+=2; - dsp->record_pos_read&=0xFFFF; - } -} void sb_dsp_update(sb_dsp_t *dsp) { - if (dsp->muted) - { - dsp->sbdatl=0; - dsp->sbdatr=0; - } - for (; dsp->pos < sound_pos_global; dsp->pos++) - { - dsp->buffer[dsp->pos*2] = dsp->sbdatl; - dsp->buffer[dsp->pos*2 + 1] = dsp->sbdatr; - } + if (dsp->muted) { + dsp->sbdatl = 0; + dsp->sbdatr = 0; + } + for (; dsp->pos < sound_pos_global; dsp->pos++) { + dsp->buffer[dsp->pos*2] = dsp->sbdatl; + dsp->buffer[dsp->pos*2 + 1] = dsp->sbdatr; + } } -void sb_dsp_close(sb_dsp_t *dsp) + +void +sb_dsp_close(sb_dsp_t *dsp) { } From 6881b6ec64474f87dcb14e8cdfe621f1e950ef6c Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 21 Dec 2019 20:04:18 +0100 Subject: [PATCH 014/177] The CD-ROM READ SUBCHANNEL command in header only mode now correctly returns the disc status and header type, fixes DOS CD players with OAKCDROM.SYS. --- src/scsi/scsi_cdrom.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index 045c78fa9..abfd8a6ef 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -9,7 +9,7 @@ * Implementation of the CD-ROM drive with SCSI(-like) * commands, for both ATAPI and SCSI usage. * - * Version: @(#)scsi_cdrom.c 1.0.72 2019/11/19 + * Version: @(#)scsi_cdrom.c 1.0.73 2019/12/13 * * Author: Miran Grca, * @@ -2076,10 +2076,13 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) dev->buffer[pos++] = 0; dev->buffer[pos++] = 0; /*Subchannel length*/ /* Mode 0 = Q subchannel mode, first 16 bytes are indentical to mode 1 (current position), the rest are stuff like ISRC etc., which can be all zeroes. */ - if ((cdb[3] <= 3) && (alloc_length != 4)) { + if (cdb[3] <= 3) { dev->buffer[pos++] = cdb[3]; /*Format code*/ - dev->buffer[1] = cdrom_get_current_subchannel(dev->drv, &dev->buffer[4], msf); - dev->buffer[2] = alloc_length - 4; + + if (alloc_length != 4) { + dev->buffer[1] = cdrom_get_current_subchannel(dev->drv, &dev->buffer[4], msf); + dev->buffer[2] = alloc_length - 4; + } switch(dev->drv->cd_status) { case CD_STATUS_PLAYING: From 51b06be28cf82509c1c84e039d9b15dc59091354 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 21 Dec 2019 20:06:34 +0100 Subject: [PATCH 015/177] Removed DOSBox OPL code, and made NukedOPL, the CD-ROM image code (incl. former cdrom_dosbox.cpp/h), and Raw Input mouse code C instead of C++, and fixed OPL2 emulation with NukedOPL. --- src/cdrom/cdrom.c | 4 +- src/cdrom/cdrom_dosbox.cpp | 884 ---------- src/cdrom/cdrom_dosbox.h | 200 --- src/cdrom/{cdrom_image.cc => cdrom_image.c} | 66 +- src/cdrom/cdrom_image_backend.c | 937 ++++++++++ src/cdrom/cdrom_image_backend.h | 94 + src/config.c | 18 +- src/scsi/scsi_device.h | 2 +- src/sound/dbopl.cpp | 1512 ----------------- src/sound/dbopl.h | 259 --- src/sound/{nukedopl.cpp => nukedopl.c} | 72 +- src/sound/nukedopl.h | 31 +- src/sound/snd_dbopl.cc | 187 -- src/sound/snd_opl.c | 274 +-- src/sound/snd_opl.h | 40 +- src/sound/snd_opl_backend.c | 147 ++ src/sound/{snd_dbopl.h => snd_opl_backend.h} | 4 +- src/sound/snd_sb.c | 5 +- src/win/86Box.rc | 8 +- src/win/Makefile.mingw | 16 +- src/win/Makefile_ndr.mingw | 16 +- src/win/resource.h | 13 +- .../{win_mouse_rawinput.cpp => win_mouse.c} | 7 +- src/win/win_mouse.cpp | 103 -- src/win/win_settings.c | 14 +- 25 files changed, 1476 insertions(+), 3437 deletions(-) delete mode 100644 src/cdrom/cdrom_dosbox.cpp delete mode 100644 src/cdrom/cdrom_dosbox.h rename src/cdrom/{cdrom_image.cc => cdrom_image.c} (75%) create mode 100644 src/cdrom/cdrom_image_backend.c create mode 100644 src/cdrom/cdrom_image_backend.h delete mode 100644 src/sound/dbopl.cpp delete mode 100644 src/sound/dbopl.h rename src/sound/{nukedopl.cpp => nukedopl.c} (94%) delete mode 100644 src/sound/snd_dbopl.cc create mode 100644 src/sound/snd_opl_backend.c rename src/sound/{snd_dbopl.h => snd_opl_backend.h} (77%) rename src/win/{win_mouse_rawinput.cpp => win_mouse.c} (98%) delete mode 100644 src/win/win_mouse.cpp diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index 1947b1573..6c19233a7 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -8,7 +8,7 @@ * * Generic CD-ROM drive core. * - * Version: @(#)cdrom.c 1.0.8 2019/09/26 + * Version: @(#)cdrom.c 1.0.9 2019/12/13 * * Author: Miran Grca, * @@ -332,7 +332,7 @@ cdrom_audio_play(cdrom_t *dev, uint32_t pos, uint32_t len, int ismsf) /* Do this at this point, since it's at this point that we know the actual LBA position to start playing from. */ if (!(dev->ops->track_type(dev, pos) & CD_TRACK_AUDIO)) { - pclog("CD-ROM %i: LBA %08X not on an audio track\n", dev->id, pos); + cdrom_log("CD-ROM %i: LBA %08X not on an audio track\n", dev->id, pos); cdrom_stop(dev); return 0; } diff --git a/src/cdrom/cdrom_dosbox.cpp b/src/cdrom/cdrom_dosbox.cpp deleted file mode 100644 index 95ee86e3d..000000000 --- a/src/cdrom/cdrom_dosbox.cpp +++ /dev/null @@ -1,884 +0,0 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * CD-ROM image file handling module. - * - * Re-hacked to remove the dirname() function, and to have this - * code using stdio instead of C++ fstream - fstream cannot deal - * with Unicode pathnames, and we need those. --FvK - * - * **NOTE** This code will very soon be replaced with a C variant, so - * no more changes will be done. - * - * Version: @(#)cdrom_dosbox.cpp 1.0.12 2019/10/22 - * - * Authors: Fred N. van Kempen, - * Miran Grca, - * The DOSBox Team, - * - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2016-2019 Miran Grca. - * Copyright 2002-2019 The DOSBox Team. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ -#define _LARGEFILE_SOURCE -#define _LARGEFILE64_SOURCE -#define __STDC_FORMAT_MACROS -#include -#include -#include -#include -#include -#include -#ifdef _WIN32 -# include -#else -# include -#endif -#include -#include -#define HAVE_STDARG_H -#include "../86box.h" -#include "../plat.h" -#include "cdrom_dosbox.h" - -using namespace std; - - -#define MAX_LINE_LENGTH 512 -#define MAX_FILENAME_LENGTH 256 -#define CROSS_LEN 512 - - - -#ifdef ENABLE_CDROM_DOSBOX_LOG -int cdrom_dosbox_do_log = ENABLE_CDROM_DOSBOX_LOG; - - -void -cdrom_dosbox_log(const char *fmt, ...) -{ - va_list ap; - - if (cdrom_dosbox_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -} -#else -#define cdrom_dosbox_log(fmt, ...) -#endif - - -CDROM_Interface_Image::BinaryFile::BinaryFile(const wchar_t *filename, bool &error) -{ - memset(fn, 0x00, sizeof(fn)); - wcscpy(fn, filename); - file = plat_fopen64(fn, L"rb"); - cdrom_dosbox_log("CDROM: binary_open(%ls) = %08lx\n", fn, file); - - if (file == NULL) - error = true; - else - error = false; -} - - -CDROM_Interface_Image::BinaryFile::~BinaryFile(void) -{ - if (file != NULL) { - fclose(file); - file = NULL; - } - memset(fn, 0x00, sizeof(fn)); -} - - -bool -CDROM_Interface_Image::BinaryFile::read(uint8_t *buffer, uint64_t seek, size_t count) -{ - cdrom_dosbox_log("CDROM: binary_read(%08lx, pos=%" PRIu64 " count=%lu\n", - file, seek, count); - if (file == NULL) return 0; - - fseeko64(file, seek, SEEK_SET); - if (fread(buffer, count, 1, file) != 1) { -#ifdef ENABLE_CDROM_DOSBOX_LOG - cdrom_dosbox_log("CDROM: binary_read failed!\n"); -#endif - return 0; - } - - return 1; -} - - -uint64_t -CDROM_Interface_Image::BinaryFile::getLength(void) -{ - off64_t len; - - cdrom_dosbox_log("CDROM: binary_length(%08lx)\n", file); - if (file == NULL) return 0; - - fseeko64(file, 0, SEEK_END); - len = ftello64(file); - cdrom_dosbox_log("CDROM: binary_length(%08lx) = %" PRIu64 "\n", file, len); - - return len; -} - - -CDROM_Interface_Image::CDROM_Interface_Image(void) -{ -} - - -CDROM_Interface_Image::~CDROM_Interface_Image(void) -{ - ClearTracks(); -} - - -void -CDROM_Interface_Image::InitNewMedia(void) -{ -} - - -bool -CDROM_Interface_Image::SetDevice(const wchar_t *path, int forceCD) -{ - (void)forceCD; - - if (CueLoadSheet(path)) return true; - - if (IsoLoadFile(path)) return true; - - return false; -} - - -bool -CDROM_Interface_Image::GetUPC(uint8_t& attr, char* upc) -{ - attr = 0; - strcpy(upc, this->mcn.c_str()); - - return true; -} - - -bool -CDROM_Interface_Image::GetAudioTracks(int& stTrack, int& end, TMSF& leadOut) -{ - stTrack = 1; - end = (int)(tracks.size() - 1); - FRAMES_TO_MSF(tracks[tracks.size() - 1].start + 150, &leadOut.min, &leadOut.sec, &leadOut.fr); - - return true; -} - - -bool -CDROM_Interface_Image::GetAudioTrackInfo(int track, int& track_number, TMSF& start, uint8_t& attr) -{ - if (track < 1 || track > (int)tracks.size()) return false; - - FRAMES_TO_MSF(tracks[track - 1].start + 150, &start.min, &start.sec, &start.fr); - track_number = tracks[track - 1].track_number; - attr = tracks[track - 1].attr; - - return true; -} - - -bool -CDROM_Interface_Image::GetAudioTrackEndInfo(int track, int& track_number, TMSF& start, unsigned char& attr) -{ - if (track < 1 || track > (int)tracks.size()) return false; - - FRAMES_TO_MSF(tracks[track - 1].start + tracks[track - 1].length + 150, &start.min, &start.sec, &start.fr); - track_number = tracks[track - 1].track_number; - attr = tracks[track - 1].attr; - - return true; -} - - -bool -CDROM_Interface_Image::GetAudioSub(int sector, uint8_t& attr, uint8_t& track, uint8_t& index, TMSF& relPos, TMSF& absPos) -{ - int cur_track = GetTrack(sector); - - if (cur_track < 1) return false; - - track = (uint8_t)cur_track; - attr = tracks[track - 1].attr; - index = 1; - - FRAMES_TO_MSF(sector + 150, &absPos.min, &absPos.sec, &absPos.fr); - - /* Absolute position should be adjusted by 150, not the relative ones. */ - FRAMES_TO_MSF(sector - tracks[track - 1].start, &relPos.min, &relPos.sec, &relPos.fr); - - return true; -} - - -bool -CDROM_Interface_Image::GetMediaTrayStatus(bool& mediaPresent, bool& mediaChanged, bool& trayOpen) -{ - mediaPresent = true; - mediaChanged = false; - trayOpen = false; - - return true; -} - - -bool -CDROM_Interface_Image::ReadSectors(PhysPt buffer, bool raw, uint32_t sector, uint32_t num) -{ - int sectorSize = raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE; - uint8_t buflen = num * sectorSize; - uint8_t* buf = new uint8_t[buflen]; - bool success = true; /* reading 0 sectors is OK */ - uint32_t i; - - for (i = 0; i < num; i++) { - success = ReadSector(&buf[i * sectorSize], raw, sector + i); - if (! success) break; - } - - memcpy((void*)buffer, buf, buflen); - delete[] buf; - - return success; -} - - -bool -CDROM_Interface_Image::LoadUnloadMedia(bool unload) -{ - (void)unload; - - return true; -} - - -int -CDROM_Interface_Image::GetTrack(unsigned int sector) -{ - vector::iterator i = tracks.begin(); - vector::iterator end = tracks.end() - 1; - - while (i != end) { - Track &curr = *i; - Track &next = *(i + 1); - if (curr.start <= sector && sector < next.start) - return curr.number; - i++; - } - - return -1; -} - - -bool -CDROM_Interface_Image::ReadSector(uint8_t *buffer, bool raw, uint32_t sector) -{ - size_t length; - - int track = GetTrack(sector) - 1; - if (track < 0) return false; - - uint64_t s = (uint64_t) sector; - uint64_t seek = tracks[track].skip + ((s - tracks[track].start) * tracks[track].sectorSize); - if (tracks[track].mode2) - length = (raw ? RAW_SECTOR_SIZE : 2336); - else - length = (raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE); - if (tracks[track].sectorSize != RAW_SECTOR_SIZE && raw) return false; - if (tracks[track].sectorSize == RAW_SECTOR_SIZE && !tracks[track].mode2 && !raw) seek += 16; - if (tracks[track].mode2 && !raw) seek += 24; - - return tracks[track].file->read(buffer, seek, length); -} - - -bool -CDROM_Interface_Image::ReadSectorSub(uint8_t *buffer, uint32_t sector) -{ - int track = GetTrack(sector) - 1; - if (track < 0) return false; - - uint64_t s = (uint64_t) sector; - uint64_t seek = tracks[track].skip + ((s - tracks[track].start) * tracks[track].sectorSize); - if (tracks[track].sectorSize != 2448) return false; - - return tracks[track].file->read(buffer, seek, 2448); -} - - -int -CDROM_Interface_Image::GetSectorSize(uint32_t sector) -{ - int track = GetTrack(sector) - 1; - if (track < 0) return 0; - - return tracks[track].sectorSize; -} - - -bool -CDROM_Interface_Image::IsMode2(uint32_t sector) -{ - int track = GetTrack(sector) - 1; - - if (track < 0) return false; - - if (tracks[track].mode2) - return true; - - return false; -} - - -int -CDROM_Interface_Image::GetMode2Form(uint32_t sector) -{ - int track = GetTrack(sector) - 1; - - if (track < 0) return false; - - return tracks[track].form; -} - - -bool -CDROM_Interface_Image::CanReadPVD(TrackFile *file, uint64_t sectorSize, bool mode2) -{ - uint8_t pvd[COOKED_SECTOR_SIZE]; - uint64_t seek = 16 * sectorSize; // first vd is located at sector 16 - - if (sectorSize == RAW_SECTOR_SIZE && !mode2) seek += 16; - if (mode2) seek += 24; - - file->read(pvd, seek, COOKED_SECTOR_SIZE); - -#if 0 - pvd[0] = descriptor type, pvd[1..5] = standard identifier, pvd[6] = iso version (+8 for High Sierra) -#endif - - return ((pvd[0] == 1 && !strncmp((char*)(&pvd[1]), "CD001", 5) && pvd[6] == 1) || - (pvd[8] == 1 && !strncmp((char*)(&pvd[9]), "CDROM", 5) && pvd[14] == 1)); -} - - -bool -CDROM_Interface_Image::IsoLoadFile(const wchar_t *filename) -{ - tracks.clear(); - - // data track - Track track = {0, 0, 0, 0, 0, 0, 0, 0, false, NULL}; - bool error; - track.file = new BinaryFile(filename, error); - if (error) { - delete track.file; - return false; - } - track.number = 1; - track.track_number = 1; //IMPORTANT: This is needed. - track.attr = DATA_TRACK; //data - track.form = 0; - - // try to detect iso type - if (CanReadPVD(track.file, COOKED_SECTOR_SIZE, false)) { - track.sectorSize = COOKED_SECTOR_SIZE; - track.mode2 = false; - } else if (CanReadPVD(track.file, RAW_SECTOR_SIZE, false)) { - track.sectorSize = RAW_SECTOR_SIZE; - track.mode2 = false; - } else if (CanReadPVD(track.file, 2336, true)) { - track.sectorSize = 2336; - track.mode2 = true; - } else if (CanReadPVD(track.file, 2324, true)) { - track.sectorSize = 2324; - track.form = 2; - track.mode2 = true; - } else if (CanReadPVD(track.file, RAW_SECTOR_SIZE, true)) { - track.sectorSize = RAW_SECTOR_SIZE; - track.mode2 = true; - } else { - /* Unknown mode: Assume regular 2048-byte sectors, this is needed so Apple Rhapsody ISO's can be mounted. */ - track.sectorSize = COOKED_SECTOR_SIZE; - track.mode2 = false; - } - - track.length = track.file->getLength() / track.sectorSize; - tracks.push_back(track); - - // leadout track - track.number = 2; - track.track_number = 0xAA; - track.attr = 0x16; /* Was 0x00 but I believe 0x16 is appropriate. */ - track.start = track.length; - track.length = 0; - track.file = NULL; - tracks.push_back(track); - - return true; -} - - -bool -CDROM_Interface_Image::CueGetBuffer(char *str, char **line, bool up) -{ - char *s = *line; - char *p = str; - int quote = 0; - int done = 0; - int space = 1; - - /* Copy to local buffer until we have end of string or whitespace. */ - while (! done) { - switch(*s) { - case '\0': - if (quote) { - /* Ouch, unterminated string.. */ - return false; - } - done = 1; - break; - - case '\"': - quote ^= 1; - break; - - case ' ': - case '\t': - if (space) - break; - - if (! quote) { - done = 1; - break; - } - /*FALLTHROUGH*/ - - default: - if (up && islower((int) *s)) - *p++ = toupper((int) *s); - else - *p++ = *s; - space = 0; - break; - } - - if (! done) - s++; - } - *p = '\0'; - - *line = s; - - return true; -} - - -/* Get a filename string from the input line. */ -bool -CDROM_Interface_Image::CueGetString(string &dest, char **line) -{ - char temp[1024]; - bool success; - - success = CueGetBuffer(temp, line, false); - if (success) - dest = temp; - - return success; -} - - -bool -CDROM_Interface_Image::CueGetKeyword(string &dest, char **line) -{ - char temp[1024]; - bool success; - - success = CueGetBuffer(temp, line, true); - if (success) - dest = temp; - - return success; -} - - -/* Get a string from the input line, handling quotes properly. */ -uint64_t -CDROM_Interface_Image::CueGetNumber(char **line) -{ - char temp[128]; - uint64_t num; - - if (! CueGetBuffer(temp, line, false)) - return 0; - - if (sscanf(temp, "%" PRIu64, &num) != 1) - return 0; - - return num; -} - - -bool -CDROM_Interface_Image::CueGetFrame(uint64_t &frames, char **line) -{ - char temp[128]; - int min, sec, fr; - bool success; - - success = CueGetBuffer(temp, line, false); - if (! success) return false; - - success = sscanf(temp, "%d:%d:%d", &min, &sec, &fr) == 3; - if (! success) return false; - - frames = MSF_TO_FRAMES(min, sec, fr); - - return true; -} - - -bool -CDROM_Interface_Image::CueLoadSheet(const wchar_t *cuefile) -{ - Track track = {0, 0, 0, 0, 0, 0, 0, 0, false, NULL}; - wchar_t pathname[MAX_FILENAME_LENGTH]; - uint64_t shift = 0; - uint64_t currPregap = 0; - uint64_t totalPregap = 0; - uint64_t prestart = 0; - int i; - bool canAddTrack = false; - bool success; - FILE *fp; - wstring name(L"r"); - - tracks.clear(); - - /* Get a copy of the filename into pathname, we need it later. */ - memset(pathname, 0, MAX_FILENAME_LENGTH * sizeof(wchar_t)); - plat_get_dirname(pathname, cuefile); - - /* Open the file. */ - fp = plat_fopen((wchar_t *) cuefile, (wchar_t *) name.c_str()); - if (fp == NULL) - return false; - - success = false; - - for (;;) { - char buf[MAX_LINE_LENGTH]; - char *line = buf; - - /* Read a line from the cuesheet file. */ - if (feof(fp) || fgets(buf, sizeof(buf), fp) == NULL || ferror(fp)) - break; - - /* Do two iterations to make sure to nuke even if it's \r\n or \n\r, - but do checks to make sure we're not nuking other bytes. */ - for (i = 0; i < 2; i++) { - if (strlen(buf) > 0) { - if (buf[strlen(buf) - 1] == '\n') - buf[strlen(buf) - 1] = '\0'; /* nuke trailing newline */ - else if (buf[strlen(buf) - 1] == '\r') - buf[strlen(buf) - 1] = '\0'; /* nuke trailing newline */ - } - } - - string command; - success = CueGetKeyword(command, &line); - - if (command == "TRACK") { - if (canAddTrack) - success = AddTrack(track, shift, prestart, totalPregap, currPregap); - else - success = true; - - track.start = 0; - track.skip = 0; - currPregap = 0; - prestart = 0; - - track.number = CueGetNumber(&line); - track.track_number = track.number; - string type; - success = CueGetKeyword(type, &line); - if (! success) break; - - track.form = 0; - - if (type == "AUDIO") { - track.sectorSize = RAW_SECTOR_SIZE; - track.attr = AUDIO_TRACK; - track.mode2 = false; - } else if (type == "MODE1/2048") { - track.sectorSize = COOKED_SECTOR_SIZE; - track.attr = DATA_TRACK; - track.mode2 = false; - } else if (type == "MODE1/2352") { - track.sectorSize = RAW_SECTOR_SIZE; - track.attr = DATA_TRACK; - track.mode2 = false; - } else if (type == "MODE2/2048") { - track.form = 1; - track.sectorSize = 2048; - track.attr = DATA_TRACK; - track.mode2 = true; - } else if (type == "MODE2/2324") { - track.form = 2; - track.sectorSize = 2324; - track.attr = DATA_TRACK; - track.mode2 = true; - } else if (type == "MODE2/2336") { - track.sectorSize = 2336; - track.attr = DATA_TRACK; - track.mode2 = true; - } else if (type == "MODE2/2352") { - track.form = 1; /* Assume this is XA Mode 2 Form 1. */ - track.sectorSize = RAW_SECTOR_SIZE; - track.attr = DATA_TRACK; - track.mode2 = true; - } else if (type == "CDG/2448") { - track.sectorSize = 2448; - track.attr = DATA_TRACK; - track.mode2 = true; - } else if (type == "CDI/2336") { - track.sectorSize = 2336; - track.attr = DATA_TRACK; - track.mode2 = true; - } else if (type == "CDI/2352") { - track.sectorSize = RAW_SECTOR_SIZE; - track.attr = DATA_TRACK; - track.mode2 = true; - } else - success = false; - - canAddTrack = true; - } else if (command == "INDEX") { - uint64_t frame = 0ULL, index; - index = CueGetNumber(&line); - success = CueGetFrame(frame, &line); - - switch(index) { - case 0: - prestart = frame; - break; - - case 1: - track.start = frame; - break; - - default: - /* ignore other indices */ - break; - } - } else if (command == "FILE") { - if (canAddTrack) - success = AddTrack(track, shift, prestart, totalPregap, currPregap); - else - success = true; - canAddTrack = false; - - char ansi[MAX_FILENAME_LENGTH]; - wchar_t filename[MAX_FILENAME_LENGTH]; - string type; - memset(ansi, 0, MAX_FILENAME_LENGTH); - memset(filename, 0, MAX_FILENAME_LENGTH * sizeof(wchar_t)); - - success = CueGetBuffer(ansi, &line, false); - if (! success) break; - success = CueGetKeyword(type, &line); - if (! success) break; - - track.file = NULL; - bool error = true; - - if (type == "BINARY") { - wchar_t temp[MAX_FILENAME_LENGTH]; - memset(temp, 0, MAX_FILENAME_LENGTH * sizeof(wchar_t)); - mbstowcs(temp, ansi, sizeof_w(temp)); - plat_append_filename(filename, pathname, temp); - track.file = new BinaryFile(filename, error); - } - if (error) { -#ifdef ENABLE_CDROM_DOSBOX_LOG - cdrom_dosbox_log("CUE: cannot open fille '%ls' in cue sheet!\n", - filename); -#endif - delete track.file; - track.file = NULL; - success = false; - } - } else if (command == "PREGAP") - success = CueGetFrame(currPregap, &line); - else if (command == "CATALOG") { - success = CueGetString(mcn, &line); - // ignored commands - } else if (command == "CDTEXTFILE" || command == "FLAGS" || command == "ISRC" - || command == "PERFORMER" || command == "POSTGAP" || command == "REM" - || command == "SONGWRITER" || command == "TITLE" || command == "") success = true; - // failure - else { -#ifdef ENABLE_CDROM_DOSBOX_LOG - cdrom_dosbox_log("CUE: unsupported command '%s' in cue sheet!\n", - command.c_str()); -#endif - success = false; - } - - if (! success) - break; - } - - fclose(fp); - if (! success) - return false; - - // add last track - if (! AddTrack(track, shift, prestart, totalPregap, currPregap)) - return false; - - // add leadout track - track.number++; - track.track_number = 0xAA; - // track.attr = 0;//sync with load iso - track.attr = 0x16; /* Was 0x00 but I believe 0x16 is appropriate. */ - track.start = 0; - track.length = 0; - track.file = NULL; - if (! AddTrack(track, shift, 0, totalPregap, 0)) - return false; - - return true; -} - - -bool -CDROM_Interface_Image::AddTrack(Track &curr, uint64_t &shift, uint64_t prestart, uint64_t &totalPregap, uint64_t currPregap) -{ - // frames between index 0(prestart) and 1(curr.start) must be skipped - uint64_t skip; - - if (prestart > 0) { - if (prestart > curr.start) return false; - skip = curr.start - prestart; - } else skip = 0; - - // first track (track number must be 1) - if (tracks.empty()) { - if (curr.number != 1) return false; - curr.skip = skip * curr.sectorSize; - curr.start += currPregap; - totalPregap = currPregap; - tracks.push_back(curr); - return true; - } - - Track &prev = *(tracks.end() - 1); - - // current track consumes data from the same file as the previous - if (prev.file == curr.file) { - curr.start += shift; - prev.length = curr.start + totalPregap - prev.start - skip; - curr.skip += prev.skip + (prev.length * prev.sectorSize) + (skip * curr.sectorSize); - totalPregap += currPregap; - curr.start += totalPregap; - // current track uses a different file as the previous track - } else { - uint64_t tmp = prev.file->getLength() - ((uint64_t) prev.skip); - prev.length = tmp / ((uint64_t) prev.sectorSize); - if (tmp % prev.sectorSize != 0) prev.length++; // padding - - curr.start += prev.start + prev.length + currPregap; - curr.skip = skip * curr.sectorSize; - shift += prev.start + prev.length; - totalPregap = currPregap; - } - - // error checks - if (curr.number <= 1) return false; - if (prev.number + 1 != curr.number) return false; - if (curr.start < prev.start + prev.length) return false; - - tracks.push_back(curr); - - return true; -} - - -bool -CDROM_Interface_Image::HasDataTrack(void) -{ - //Data track has attribute 0x14 - for (track_it it = tracks.begin(); it != tracks.end(); it++) { - if ((*it).attr == DATA_TRACK) return true; - } - return false; -} - - -bool -CDROM_Interface_Image::HasAudioTracks(void) -{ - for (track_it it = tracks.begin(); it != tracks.end(); it++) { - if ((*it).attr == AUDIO_TRACK) return true; - } - return false; -} - - -void -CDROM_Interface_Image::ClearTracks(void) -{ - vector::iterator i = tracks.begin(); - vector::iterator end = tracks.end(); - - TrackFile* last = NULL; - while(i != end) { - Track &curr = *i; - if (curr.file != last) { - delete curr.file; - last = curr.file; - } - i++; - } - tracks.clear(); -} diff --git a/src/cdrom/cdrom_dosbox.h b/src/cdrom/cdrom_dosbox.h deleted file mode 100644 index 93b80340f..000000000 --- a/src/cdrom/cdrom_dosbox.h +++ /dev/null @@ -1,200 +0,0 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * Definitions for the CD-ROM image file handling module. - * - * Version: @(#)cdrom_dosbox.h 1.0.3 2019/03/05 - * - * Authors: Fred N. van Kempen, - * Miran Grca, - * The DOSBox Team, - * - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * Copyright 2002-2015 The DOSBox Team. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ -#ifndef CDROM_INTERFACE -# define CDROM_INTERFACE - -#include -#include -#include -#include -#include -#include -#include - -//typedef signed int Bits; -//typedef unsigned int Bitu; -//typedef int8_t Bit8s; -//typedef int16_t Bit16s; -//typedef uint16_t Bit16u; -//typedef int32_t Bit32s; -//typedef uint32_t Bit32u; - -typedef size_t PhysPt; - - -#define RAW_SECTOR_SIZE 2352 -#define COOKED_SECTOR_SIZE 2048 - -#define DATA_TRACK 0x14 -#define AUDIO_TRACK 0x10 - -#define CD_FPS 75 -#define FRAMES_TO_MSF(f, M,S,F) { \ - uint64_t value = f; \ - *(F) = (value%CD_FPS) & 0xff; \ - value /= CD_FPS; \ - *(S) = (value%60) & 0xff; \ - value /= 60; \ - *(M) = value & 0xff; \ -} -#define MSF_TO_FRAMES(M, S, F) ((M)*60*CD_FPS+(S)*CD_FPS+(F)) - - -typedef struct SMSF { - uint8_t min; - uint8_t sec; - uint8_t fr; -} TMSF; - -typedef struct SCtrl { - uint8_t out[4]; // output channel - uint8_t vol[4]; // channel volume -} TCtrl; - - -class CDROM_Interface { -public: -// CDROM_Interface(void); - - virtual ~CDROM_Interface(void) {}; - - virtual bool SetDevice(const wchar_t *path, int forceCD) = 0; - - virtual bool GetUPC(uint8_t& attr, char* upc) = 0; - - virtual bool GetAudioTracks(int& stTrack, int& end, TMSF& leadOut) = 0; - virtual bool GetAudioTrackInfo(int track, int& number, TMSF& start, uint8_t& attr) = 0; - virtual bool GetAudioTrackEndInfo(int track, int& number, TMSF& start, unsigned char& attr) = 0; - virtual bool GetAudioSub(int sector, uint8_t& attr, uint8_t& track, uint8_t& index, TMSF& relPos, TMSF& absPos) = 0; - virtual bool GetMediaTrayStatus(bool& mediaPresent, bool& mediaChanged, bool& trayOpen) = 0; - - virtual bool ReadSectors(PhysPt buffer, bool raw, uint32_t sector, uint32_t num) = 0; - - virtual bool LoadUnloadMedia(bool unload) = 0; - - virtual void InitNewMedia(void) {}; -}; - - -class CDROM_Interface_Image : public CDROM_Interface { -private: - class TrackFile { - public: - virtual bool read(uint8_t *buffer, uint64_t seek, size_t count) = 0; - virtual uint64_t getLength() = 0; - virtual ~TrackFile() { }; - }; - - class BinaryFile : public TrackFile { - public: - BinaryFile(const wchar_t *filename, bool &error); - ~BinaryFile(); - bool read(uint8_t *buffer, uint64_t seek, size_t count); - uint64_t getLength(); - private: - BinaryFile(); - wchar_t fn[260]; - FILE *file; - }; - - struct Track { - int number; - int track_number; - int attr; - int form; - uint64_t start; - uint64_t length; - uint64_t skip; - int sectorSize; - bool mode2; - TrackFile *file; - }; - -public: - CDROM_Interface_Image(); - virtual ~CDROM_Interface_Image(void); - void InitNewMedia(void); - bool SetDevice(const wchar_t* path, int forceCD); - bool GetUPC(uint8_t& attr, char* upc); - bool GetAudioTracks(int& stTrack, int& end, TMSF& leadOut); - bool GetAudioTrackInfo(int track, int& number, TMSF& start, uint8_t& attr); - bool GetAudioTrackEndInfo(int track, int& number, TMSF& start, unsigned char& attr); - bool GetAudioSub(int sector, uint8_t& attr, uint8_t& track, uint8_t& index, TMSF& relPos, TMSF& absPos); - bool GetMediaTrayStatus(bool& mediaPresent, bool& mediaChanged, bool& trayOpen); - bool ReadSectors(PhysPt buffer, bool raw, uint32_t sector, uint32_t num); - bool LoadUnloadMedia(bool unload); - bool ReadSector(uint8_t *buffer, bool raw, uint32_t sector); - bool ReadSectorSub(uint8_t *buffer, uint32_t sector); - int GetSectorSize(uint32_t sector); - bool IsMode2(uint32_t sector); - int GetMode2Form(uint32_t sector); - bool HasDataTrack(void); - bool HasAudioTracks(void); - - int GetTrack(unsigned int sector); - -private: - // player - static void CDAudioCallBack(unsigned int len); - - void ClearTracks(); - bool IsoLoadFile(const wchar_t *filename); - bool CanReadPVD(TrackFile *file, uint64_t sectorSize, bool mode2); - - // cue sheet processing - bool CueGetBuffer(char *str, char **line, bool up); - bool CueGetString(std::string &str, char **line); - bool CueGetKeyword(std::string &keyword, char **line); - uint64_t CueGetNumber(char **line); - bool CueGetFrame(uint64_t &frames, char **line); - bool CueLoadSheet(const wchar_t *cuefile); - bool AddTrack(Track &curr, uint64_t &shift, uint64_t prestart, uint64_t &totalPregap, uint64_t currPregap); - - std::vector tracks; -typedef std::vector::iterator track_it; - std::string mcn; -}; - - -extern int CDROM_GetMountType(char* path, int force); - -extern void cdrom_image_log(const char *format, ...); - - -#endif /* __CDROM_INTERFACE__ */ diff --git a/src/cdrom/cdrom_image.cc b/src/cdrom/cdrom_image.c similarity index 75% rename from src/cdrom/cdrom_image.cc rename to src/cdrom/cdrom_image.c index 4eb6c6499..34a2dcc29 100644 --- a/src/cdrom/cdrom_image.cc +++ b/src/cdrom/cdrom_image.c @@ -8,7 +8,7 @@ * * CD-ROM image support. * - * Version: @(#)cdrom_image.cc 1.0.10 2019/03/06 + * Version: @(#)cdrom_image.c 1.0.11 2019/03/06 * * Author: RichardG867, * Miran Grca, @@ -32,7 +32,7 @@ #include "../config.h" #include "../plat.h" #include "../scsi/scsi_device.h" -#include "cdrom_dosbox.h" +#include "cdrom_image_backend.h" #include "cdrom.h" #include "cdrom_image.h" @@ -60,29 +60,26 @@ cdrom_image_log(const char *fmt, ...) /* The addresses sent from the guest are absolute, ie. a LBA of 0 corresponds to a MSF of 00:00:00. Otherwise, the counter displayed by the guest is wrong: there is a seeming 2 seconds in which audio plays but counter does not move, while a data track before audio jumps to 2 seconds before the actual start of the audio while audio still plays. With an absolute conversion, the counter is fine. */ -#define MSFtoLBA(m,s,f) ((((m*60)+s)*75)+f) +#define MSFtoLBA(m,s,f) ((((m * 60) + s) * 75) + f) static void image_get_tracks(cdrom_t *dev, int *first, int *last) { - CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image; + cd_img_t *img = (cd_img_t *)dev->image; TMSF tmsf; - img->GetAudioTracks(*first, *last, tmsf); + cdi_get_audio_tracks(img, first, last, &tmsf); } static void image_get_track_info(cdrom_t *dev, uint32_t track, int end, track_info_t *ti) { - CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image; + cd_img_t *img = (cd_img_t *)dev->image; TMSF tmsf; - if (end) - img->GetAudioTrackEndInfo(track, ti->number, tmsf, ti->attr); - else - img->GetAudioTrackInfo(track, ti->number, tmsf, ti->attr); + cdi_get_audio_track_info(img, end, track, &ti->number, &tmsf, &ti->attr); ti->m = tmsf.min; ti->s = tmsf.sec; @@ -93,11 +90,11 @@ image_get_track_info(cdrom_t *dev, uint32_t track, int end, track_info_t *ti) static void image_get_subchannel(cdrom_t *dev, uint32_t lba, subchannel_t *subc) { - CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image; + cd_img_t *img = (cd_img_t *)dev->image; TMSF rel_pos, abs_pos; - img->GetAudioSub(lba, subc->attr, subc->track, subc->index, - rel_pos, abs_pos); + cdi_get_audio_sub(img, lba, &subc->attr, &subc->track, &subc->index, + &rel_pos, &abs_pos); subc->abs_m = abs_pos.min; subc->abs_s = abs_pos.sec; @@ -112,7 +109,7 @@ image_get_subchannel(cdrom_t *dev, uint32_t lba, subchannel_t *subc) static int image_get_capacity(cdrom_t *dev) { - CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image; + cd_img_t *img = (cd_img_t *)dev->image; int first_track, last_track; int number, c; unsigned char attr; @@ -123,10 +120,10 @@ image_get_capacity(cdrom_t *dev) if (!img) return 0; - img->GetAudioTracks(first_track, last_track, tmsf); + cdi_get_audio_tracks(img, &first_track, &last_track, &tmsf); for (c = 0; c <= last_track; c++) { - img->GetAudioTrackInfo(c+1, number, tmsf, attr); + cdi_get_audio_track_info(img, 0, c + 1, &number, &tmsf, &attr); address = MSFtoLBA(tmsf.min, tmsf.sec, tmsf.fr) - 150; /* Do the - 150 here as well. */ if (address > lb) lb = address; @@ -139,7 +136,7 @@ image_get_capacity(cdrom_t *dev) static int image_is_track_audio(cdrom_t *dev, uint32_t pos, int ismsf) { - CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image; + cd_img_t *img = (cd_img_t *)dev->image; uint8_t attr; TMSF tmsf; int m, s, f; @@ -156,7 +153,7 @@ image_is_track_audio(cdrom_t *dev, uint32_t pos, int ismsf) } /* GetTrack requires LBA. */ - img->GetAudioTrackInfo(img->GetTrack(pos), number, tmsf, attr); + cdi_get_audio_track_info(img, 0, cdi_get_track(img, pos), &number, &tmsf, &attr); return attr == AUDIO_TRACK; } @@ -165,27 +162,27 @@ image_is_track_audio(cdrom_t *dev, uint32_t pos, int ismsf) static int image_sector_size(struct cdrom *dev, uint32_t lba) { - CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image; + cd_img_t *img = (cd_img_t *)dev->image; - return img->GetSectorSize(lba); + return cdi_get_sector_size(img, lba); } static int image_read_sector(struct cdrom *dev, int type, uint8_t *b, uint32_t lba) { - CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image; + cd_img_t *img = (cd_img_t *)dev->image; switch (type) { case CD_READ_DATA: - return img->ReadSector(b, false, lba); + return cdi_read_sector(img, b, 0, lba); case CD_READ_AUDIO: - return img->ReadSector(b, true, lba); + return cdi_read_sector(img, b, 1, lba); case CD_READ_RAW: - if (img->GetSectorSize(lba) == 2352) - return img->ReadSector(b, true, lba); + if (cdi_get_sector_size(img, lba) == 2352) + return cdi_read_sector(img, b, 1, lba); else - return img->ReadSectorSub(b, lba); + return cdi_read_sector_sub(img, b, lba); default: cdrom_image_log("CD-ROM %i: Unknown CD read type\n", dev->id); return 0; @@ -196,14 +193,14 @@ image_read_sector(struct cdrom *dev, int type, uint8_t *b, uint32_t lba) static int image_track_type(cdrom_t *dev, uint32_t lba) { - CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image; + cd_img_t *img = (cd_img_t *)dev->image; if (img) { if (image_is_track_audio(dev, lba, 0)) return CD_TRACK_AUDIO; else { - if (img->IsMode2(lba)) - return CD_TRACK_MODE2 | img->GetMode2Form(lba); + if (cdi_is_mode2(img, lba)) + return CD_TRACK_MODE2 | cdi_get_mode2_form(img, lba); } } @@ -214,13 +211,13 @@ image_track_type(cdrom_t *dev, uint32_t lba) static void image_exit(cdrom_t *dev) { - CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image; + cd_img_t *img = (cd_img_t *)dev->image; cdrom_image_log("CDROM: image_exit(%ls)\n", dev->image_path); dev->cd_status = CD_STATUS_EMPTY; if (img) { - delete img; + cdi_close(img); dev->image = NULL; } @@ -252,22 +249,23 @@ image_open_abort(cdrom_t *dev) int cdrom_image_open(cdrom_t *dev, const wchar_t *fn) { - CDROM_Interface_Image *img; + cd_img_t *img; wcscpy(dev->image_path, fn); /* Create new instance of the CDROM_Image class. */ - img = new CDROM_Interface_Image(); + img = (cd_img_t *) malloc(sizeof(cd_img_t)); /* This guarantees that if ops is not NULL, then neither is the image pointer. */ if (!img) return image_open_abort(dev); + memset(img, 0, sizeof(cd_img_t)); dev->image = img; /* Open the image. */ - if (! img->SetDevice(fn, false)) + if (!cdi_set_device(img, fn)) return image_open_abort(dev); /* All good, reset state. */ diff --git a/src/cdrom/cdrom_image_backend.c b/src/cdrom/cdrom_image_backend.c new file mode 100644 index 000000000..669989fc6 --- /dev/null +++ b/src/cdrom/cdrom_image_backend.c @@ -0,0 +1,937 @@ +/* + * 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. + * + * CD-ROM image file handling module, translated to C from + * cdrom_dosbox.cpp. + * + * Version: @(#)cdrom_image_backend.c 1.0.0 2019/12/19 + * + * Authors: Miran Grca, + * Fred N. van Kempen, + * The DOSBox Team, + * + * Copyright 2016-2019 Miran Grca. + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2002-2019 The DOSBox Team. + */ +#define _LARGEFILE_SOURCE +#define _LARGEFILE64_SOURCE +#define __STDC_FORMAT_MACROS +#include +#include +#include +#include +#include +#include +#ifdef _WIN32 +# include +#else +# include +#endif +#include +#define HAVE_STDARG_H +#include "../86box.h" +#include "../plat.h" +#include "cdrom_image_backend.h" + + +#define MAX_LINE_LENGTH 512 +#define MAX_FILENAME_LENGTH 256 +#define CROSS_LEN 512 + + +#ifdef ENABLE_CDROM_IMAGE_BACKEND_LOG +int cdrom_image_backend_do_log = ENABLE_CDROM_IMAGE_BACKEND_LOG; + + +void +cdrom_image_backend_log(const char *fmt, ...) +{ + va_list ap; + + if (cdrom_image_backend_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define cdrom_image_backend_log(fmt, ...) +#endif + + +/* Binary file functions. */ +static int +bin_read(void *p, uint8_t *buffer, uint64_t seek, size_t count) +{ + track_file_t *tf = (track_file_t *) p; + + cdrom_image_backend_log("CDROM: binary_read(%08lx, pos=%" PRIu64 " count=%lu\n", + tf->file, seek, count); + + if (tf->file == NULL) + return 0; + + fseeko64(tf->file, seek, SEEK_SET); + + if (fread(buffer, count, 1, tf->file) != 1) { +#ifdef ENABLE_cdrom_image_backend_log + cdrom_image_backend_log("CDROM: binary_read failed!\n"); +#endif + return 0; + } + + return 1; +} + + +static uint64_t +bin_get_length(void *p) +{ + off64_t len; + track_file_t *tf = (track_file_t *) p; + + cdrom_image_backend_log("CDROM: binary_length(%08lx)\n", bf->file); + + if (tf->file == NULL) + return 0; + + fseeko64(tf->file, 0, SEEK_END); + len = ftello64(tf->file); + cdrom_image_backend_log("CDROM: binary_length(%08lx) = %" PRIu64 "\n", tf->file, len); + + return len; +} + + +static void +bin_close(void *p) +{ + track_file_t *tf = (track_file_t *) p; + + if (tf == NULL) + return; + + if (tf->file != NULL) { + fclose(tf->file); + tf->file = NULL; + } + + memset(tf->fn, 0x00, sizeof(tf->fn)); + + free(p); +} + + +static track_file_t * +bin_init(const wchar_t *filename, int *error) +{ + track_file_t *tf = (track_file_t *) malloc(sizeof(track_file_t)); + + memset(tf->fn, 0x00, sizeof(tf->fn)); + wcscpy(tf->fn, filename); + tf->file = plat_fopen64(tf->fn, L"rb"); + cdrom_image_backend_log("CDROM: binary_open(%ls) = %08lx\n", tf->fn, tf->file); + + *error = (tf->file == NULL); + + /* Set the function pointers. */ + if (!*error) { + tf->read = bin_read; + tf->get_length = bin_get_length; + tf->close = bin_close; + } + + return tf; +} + + +static track_file_t * +track_file_init(const wchar_t *filename, int *error) +{ + /* Current we only support .BIN files, either combined or one per + track. In the future, more is planned. */ + return bin_init(filename, error); +} + + +static void +track_file_close(track_t *trk) +{ + if (trk == NULL) + return; + + if (trk->file == NULL) + return; + + trk->file->close(trk->file); + trk->file = NULL; +} + + +/* Root functions. */ +static void +cdi_clear_tracks(cd_img_t *cdi) +{ + int i; + track_file_t *last = NULL; + track_t *cur = NULL; + + if ((cdi->tracks == NULL) || (cdi->tracks_num == 0)) + return; + + for (i = 0; i < cdi->tracks_num; i++) { + cur = &cdi->tracks[i]; + + if (cur->file != last) { + track_file_close(cur); + last = cur->file; + } + } + + /* Now free the array. */ + free(cdi->tracks); + cdi->tracks = NULL; + + /* Mark that there's no tracks. */ + cdi->tracks_num = 0; +} + + +void +cdi_close(cd_img_t *cdi) +{ + cdi_clear_tracks(cdi); + free(cdi); +} + + +int +cdi_set_device(cd_img_t *cdi, const wchar_t *path) +{ + if (cdi_load_cue(cdi, path)) + return 1; + + if (cdi_load_iso(cdi, path)) + return 1; + + return 0; +} + + +/* TODO: This never returns anything other than 1, should it even be an int? */ +int +cdi_get_audio_tracks(cd_img_t *cdi, int *st_track, int *end, TMSF *lead_out) +{ + *st_track = 1; + *end = cdi->tracks_num - 1; + FRAMES_TO_MSF(cdi->tracks[*end].start + 150, &lead_out->min, &lead_out->sec, &lead_out->fr); + + return 1; +} + + +/* This replaces both Info and EndInfo, they are specified by a variable. */ +int +cdi_get_audio_track_info(cd_img_t *cdi, int end, int track, int *track_num, TMSF *start, uint8_t *attr) +{ + track_t *trk = &cdi->tracks[track - 1]; + int pos = trk->start + 150; + + if ((track < 1) || (track > cdi->tracks_num)) + return 0; + + pos = trk->start + 150; + + FRAMES_TO_MSF(pos, &start->min, &start->sec, &start->fr); + *track_num = trk->track_number; + *attr = trk->attr; + + return 1; +} + + +int +cdi_get_track(cd_img_t *cdi, uint32_t sector) +{ + int i; + track_t *cur, *next; + + /* There must be at least two tracks - data and lead out. */ + if (cdi->tracks_num < 2) + return -1; + + /* This has a problem - the code skips the last track, which is + lead out - is that correct? */ + for (i = 0; i < (cdi->tracks_num - 1); i++) { + cur = &cdi->tracks[i]; + next = &cdi->tracks[i + 1]; + if ((cur->start <= sector) && (sector < next->start)) + return cur->number; + } + + return -1; +} + + +/* TODO: See if track start is adjusted by 150 or not. */ +int +cdi_get_audio_sub(cd_img_t *cdi, uint32_t sector, uint8_t *attr, uint8_t *track, uint8_t *index, TMSF *rel_pos, TMSF *abs_pos) +{ + int cur_track = cdi_get_track(cdi, sector); + track_t *trk; + + if (cur_track < 1) + return 0; + + *track = (uint8_t) cur_track; + trk = &cdi->tracks[*track - 1]; + *attr = trk->attr; + *index = 1; + + FRAMES_TO_MSF(sector + 150, &abs_pos->min, &abs_pos->sec, &abs_pos->fr); + + /* Absolute position should be adjusted by 150, not the relative ones. */ + FRAMES_TO_MSF(sector - trk->start, &rel_pos->min, &rel_pos->sec, &rel_pos->fr); + + return 1; +} + + +int +cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector) +{ + size_t length; + int track = cdi_get_track(cdi, sector) - 1; + uint64_t s = (uint64_t) sector, seek; + track_t *trk; + + if (track < 0) + return 0; + + trk = &cdi->tracks[track]; + seek = trk->skip + ((s - trk->start) * trk->sector_size); + + /* TODO: Is this correct? Is cooked sector size 2336 for all Mode 2 variants? */ + if (trk->mode2 && (trk->form != 1)) { + if (trk->form == 2) + length = (raw ? RAW_SECTOR_SIZE : 2324); + else + length = (raw ? RAW_SECTOR_SIZE : 2336); + } else + length = (raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE); + + if (raw && (trk->sector_size != RAW_SECTOR_SIZE)) + return 0; + if (!raw && !trk->mode2 && (trk->sector_size == RAW_SECTOR_SIZE)) + seek += 16ULL; + /* TODO: See if Mode 2 is handled correctly here. */ + if (!raw && trk->mode2) + seek += 24ULL; + + return trk->file->read(trk->file, buffer, seek, length); +} + + +int +cdi_read_sectors(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector, uint32_t num) +{ + int sector_size, success = 1; + uint8_t buf_len, *buf; + uint32_t i; + + /* TODO: This fails to account for Mode 2. Shouldn't we have a function + to get sector size? */ + sector_size = raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE; + buf_len = num * sector_size; + buf = (uint8_t *) malloc(buf_len * sizeof(uint8_t)); + + for (i = 0; i < num; i++) { + success = cdi_read_sector(cdi, &buf[i * sector_size], raw, sector + i); + if (!success) + break; + } + + memcpy((void *) buffer, buf, buf_len); + free(buf); + buf = NULL; + + return success; +} + + +/* TODO: Do CUE+BIN images with a sector size of 2448 even exist? */ +int +cdi_read_sector_sub(cd_img_t *cdi, uint8_t *buffer, uint32_t sector) +{ + int track = cdi_get_track(cdi, sector) - 1; + track_t *trk; + uint64_t s = (uint64_t) sector, seek; + + if (track < 0) + return 0; + + trk = &cdi->tracks[track]; + seek = trk->skip + ((s - trk->start) * trk->sector_size); + if (trk->sector_size != 2448) + return 0; + + return trk->file->read(trk->file, buffer, seek, 2448); +} + + +int +cdi_get_sector_size(cd_img_t *cdi, uint32_t sector) +{ + int track = cdi_get_track(cdi, sector) - 1; + track_t *trk; + + if (track < 0) + return 0; + + trk = &cdi->tracks[track]; + return trk->sector_size; +} + + +int +cdi_is_mode2(cd_img_t *cdi, uint32_t sector) +{ + int track = cdi_get_track(cdi, sector) - 1; + track_t *trk; + + if (track < 0) + return 0; + + trk = &cdi->tracks[track]; + + return !!(trk->mode2); +} + + +int +cdi_get_mode2_form(cd_img_t *cdi, uint32_t sector) +{ + int track = cdi_get_track(cdi, sector) - 1; + track_t *trk; + + if (track < 0) + return 0; + + trk = &cdi->tracks[track]; + + return trk->form; +} + + +int +cdi_can_read_pvd(track_file_t *file, uint64_t sector_size, int mode2) +{ + uint8_t pvd[COOKED_SECTOR_SIZE]; + uint64_t seek = 16ULL * sector_size; /* First VD is located at sector 16. */ + + if (!mode2 && (sector_size == RAW_SECTOR_SIZE)) + seek += 16; + if (mode2) + seek += 24; + + file->read(file, pvd, seek, COOKED_SECTOR_SIZE); + + return ((pvd[0] == 1 && !strncmp((char*)(&pvd[1]), "CD001", 5) && pvd[6] == 1) || + (pvd[8] == 1 && !strncmp((char*)(&pvd[9]), "CDROM", 5) && pvd[14] == 1)); +} + + +/* This reallocates the array and returns the pointer to the last track. */ +static void +cdi_track_push_back(cd_img_t *cdi, track_t *trk) +{ + /* This has to be done so situations in which realloc would misbehave + can be detected and reported to the user. */ + if ((cdi->tracks != NULL) && (cdi->tracks_num == 0)) + fatal("CD-ROM Image: Non-null tracks array at 0 loaded tracks\n"); + if ((cdi->tracks == NULL) && (cdi->tracks_num != 0)) + fatal("CD-ROM Image: Null tracks array at non-zero loaded tracks\n"); + + cdi->tracks = realloc(cdi->tracks, (cdi->tracks_num + 1) * sizeof(track_t)); + memcpy(&(cdi->tracks[cdi->tracks_num]), trk, sizeof(track_t)); + cdi->tracks_num++; +} + + +int +cdi_load_iso(cd_img_t *cdi, const wchar_t *filename) +{ + int error; + track_t trk; + + cdi->tracks = NULL; + cdi->tracks_num = 0; + + memset(&trk, 0, sizeof(track_t)); + + /* Data track (shouldn't there be a lead in track?). */ + trk.file = bin_init(filename, &error); + if (error) { + if (trk.file != NULL) + trk.file->close(trk.file); + return 0; + } + trk.number = 1; + trk.track_number = 1; + trk.attr = DATA_TRACK; + + /* Try to detect ISO type. */ + trk.form = 0; + trk.mode2 = 0; + /* TODO: Merge the first and last cases since they result in the same thing. */ + if (cdi_can_read_pvd(trk.file, RAW_SECTOR_SIZE, 0)) + trk.sector_size = RAW_SECTOR_SIZE; + else if (cdi_can_read_pvd(trk.file, 2336, 1)) { + trk.sector_size = 2336; + trk.mode2 = 1; + } else if (cdi_can_read_pvd(trk.file, 2324, 1)) { + trk.sector_size = 2324; + trk.mode2 = 1; + trk.form = 2; + } else if (cdi_can_read_pvd(trk.file, RAW_SECTOR_SIZE, 1)) { + trk.sector_size = RAW_SECTOR_SIZE; + trk.mode2 = 1; + } else { + /* We use 2048 mode 1 as the default. */ + trk.sector_size = COOKED_SECTOR_SIZE; + } + + trk.length = trk.file->get_length(trk.file) / trk.sector_size; + cdi_track_push_back(cdi, &trk); + + /* Lead out track. */ + trk.number = 2; + trk.track_number = 0xAA; + trk.attr = 0x16; /* Was originally 0x00, but I believe 0x16 is appropriate. */ + trk.start = trk.length; + trk.length = 0; + trk.file = NULL; + cdi_track_push_back(cdi, &trk); + + return 1; +} + + +static int +cdi_cue_get_buffer(char *str, char **line, int up) +{ + char *s = *line; + char *p = str; + int quote = 0; + int done = 0; + int space = 1; + + /* Copy to local buffer until we have end of string or whitespace. */ + while (! done) { + switch(*s) { + case '\0': + if (quote) { + /* Ouch, unterminated string.. */ + return 0; + } + done = 1; + break; + + case '\"': + quote ^= 1; + break; + + case ' ': + case '\t': + if (space) + break; + + if (! quote) { + done = 1; + break; + } + /*FALLTHROUGH*/ + + default: + if (up && islower((int) *s)) + *p++ = toupper((int) *s); + else + *p++ = *s; + space = 0; + break; + } + + if (! done) + s++; + } + *p = '\0'; + + *line = s; + + return 1; +} + + +static int +cdi_cue_get_keyword(char **dest, char **line) +{ + char temp[1024]; + int success; + + success = cdi_cue_get_buffer(temp, line, 1); + if (success) + *dest = temp; + + return success; +} + + +/* Get a string from the input line, handling quotes properly. */ +static uint64_t +cdi_cue_get_number(char **line) +{ + char temp[128]; + uint64_t num; + + if (!cdi_cue_get_buffer(temp, line, 0)) + return 0; + + if (sscanf(temp, "%" PRIu64, &num) != 1) + return 0; + + return num; +} + + +static int +cdi_cue_get_frame(uint64_t *frames, char **line) +{ + char temp[128]; + int min, sec, fr; + int success; + + success = cdi_cue_get_buffer(temp, line, 0); + if (! success) return 0; + + success = sscanf(temp, "%d:%d:%d", &min, &sec, &fr) == 3; + if (! success) return 0; + + *frames = MSF_TO_FRAMES(min, sec, fr); + + return 1; +} + + +static int +cdi_add_track(cd_img_t *cdi, track_t *cur, uint64_t *shift, uint64_t prestart, uint64_t *total_pregap, uint64_t cur_pregap) +{ + /* Frames between index 0 (prestart) and 1 (current track start) must be skipped. */ + uint64_t skip, temp; + track_t *prev = NULL; + + if (prestart > 0) { + if (prestart > cur->start) + return 0; + skip = cur->start - prestart; + } else + skip = 0ULL; + + if ((cdi->tracks != NULL) && (cdi->tracks_num != 0)) + prev = &cdi->tracks[cdi->tracks_num - 1]; + + /* First track (track number must be 1). */ + if (cdi->tracks_num == 0) { + /* I guess this makes sure the structure is not filled with invalid data. */ + if (cur->number != 1) + return 0; + cur->skip = skip * cur->sector_size; + cur->start += cur_pregap; + *total_pregap = cur_pregap; + cdi_track_push_back(cdi, cur); + return 1; + } + + /* Current track consumes data from the same file as the previous. */ + if (prev->file == cur->file) { + cur->start += *shift; + prev->length = cur->start + *total_pregap - prev->start - skip; + cur->skip += prev->skip + (prev->length * prev->sector_size) + (skip * cur->sector_size); + *total_pregap += cur_pregap; + cur->start += *total_pregap; + } else { + temp = prev->file->get_length(prev->file) - ((uint64_t) prev->skip); + prev->length = temp / ((uint64_t) prev->sector_size); + if ((temp % prev->sector_size) != 0) + prev->length++; /* Padding. */ + + cur->start += prev->start + prev->length + cur_pregap; + cur->skip = skip * cur->sector_size; + *shift += prev->start + prev->length; + *total_pregap = cur_pregap; + } + + /* Error checks. */ + if (cur->number <= 1) + return 0; + if ((prev->number + 1) != cur->number) + return 0; + if (cur->start < (prev->start + prev->length)) + return 0; + + cdi_track_push_back(cdi, cur); + + return 1; +} + + +int +cdi_load_cue(cd_img_t *cdi, const wchar_t *cuefile) +{ + track_t trk; + wchar_t pathname[MAX_FILENAME_LENGTH], filename[MAX_FILENAME_LENGTH]; + wchar_t temp[MAX_FILENAME_LENGTH]; + uint64_t shift = 0ULL, prestart = 0ULL; + uint64_t cur_pregap = 0ULL, total_pregap = 0ULL; + uint64_t frame = 0ULL, index; + int i, success; + int error, can_add_track = 0; + FILE *fp; + char buf[MAX_LINE_LENGTH], ansi[MAX_FILENAME_LENGTH]; + char *line, *command; + char *type; + + cdi->tracks = NULL; + cdi->tracks_num = 0; + + memset(&trk, 0, sizeof(track_t)); + + /* Get a copy of the filename into pathname, we need it later. */ + memset(pathname, 0, MAX_FILENAME_LENGTH * sizeof(wchar_t)); + plat_get_dirname(pathname, cuefile); + + /* Open the file. */ + fp = plat_fopen((wchar_t *) cuefile, L"r"); + if (fp == NULL) + return 0; + + success = 0; + + for (;;) { + line = buf; + + /* Read a line from the cuesheet file. */ + if (feof(fp) || fgets(buf, sizeof(buf), fp) == NULL || ferror(fp)) + break; + + /* Do two iterations to make sure to nuke even if it's \r\n or \n\r, + but do checks to make sure we're not nuking other bytes. */ + for (i = 0; i < 2; i++) { + if (strlen(buf) > 0) { + if (buf[strlen(buf) - 1] == '\n') + buf[strlen(buf) - 1] = '\0'; /* nuke trailing newline */ + else if (buf[strlen(buf) - 1] == '\r') + buf[strlen(buf) - 1] = '\0'; /* nuke trailing newline */ + } + } + + success = cdi_cue_get_keyword(&command, &line); + + if (!strcmp(command, "TRACK")) { + if (can_add_track) + success = cdi_add_track(cdi, &trk, &shift, prestart, &total_pregap, cur_pregap); + else + success = 1; + + trk.start = 0; + trk.skip = 0; + cur_pregap = 0; + prestart = 0; + + trk.number = cdi_cue_get_number(&line); + trk.track_number = trk.number; + success = cdi_cue_get_keyword(&type, &line); + if (!success) + break; + + trk.form = 0; + trk.mode2 = 0; + + if (!strcmp(type, "AUDIO")) { + trk.sector_size = RAW_SECTOR_SIZE; + trk.attr = AUDIO_TRACK; + } else if (!strcmp(type, "MODE1/2048")) { + trk.sector_size = COOKED_SECTOR_SIZE; + trk.attr = DATA_TRACK; + } else if (!strcmp(type, "MODE1/2352")) { + trk.sector_size = RAW_SECTOR_SIZE; + trk.attr = DATA_TRACK; + } else if (!strcmp(type, "MODE2/2048")) { + trk.form = 1; + trk.sector_size = COOKED_SECTOR_SIZE; + trk.attr = DATA_TRACK; + trk.mode2 = 1; + } else if (!strcmp(type, "MODE2/2324")) { + trk.form = 2; + trk.sector_size = 2324; + trk.attr = DATA_TRACK; + trk.mode2 = 1; + } else if (!strcmp(type, "MODE2/2336")) { + trk.sector_size = 2336; + trk.attr = DATA_TRACK; + trk.mode2 = 1; + } else if (!strcmp(type, "MODE2/2352")) { + trk.form = 1; /* Assume this is XA Mode 2 Form 1. */ + trk.sector_size = RAW_SECTOR_SIZE; + trk.attr = DATA_TRACK; + trk.mode2 = 1; + } else if (!strcmp(type, "CDG/2448")) { + trk.sector_size = 2448; + trk.attr = DATA_TRACK; + trk.mode2 = 1; + } else if (!strcmp(type, "CDI/2336")) { + trk.sector_size = 2336; + trk.attr = DATA_TRACK; + trk.mode2 = 1; + } else if (!strcmp(type, "CDI/2352")) { + trk.sector_size = RAW_SECTOR_SIZE; + trk.attr = DATA_TRACK; + trk.mode2 = 1; + } else + success = 0; + + can_add_track = 1; + } else if (!strcmp(command, "INDEX")) { + index = cdi_cue_get_number(&line); + success = cdi_cue_get_frame(&frame, &line); + + switch(index) { + case 0: + prestart = frame; + break; + + case 1: + trk.start = frame; + break; + + default: + /* ignore other indices */ + break; + } + } else if (!strcmp(command, "FILE")) { + if (can_add_track) + success = cdi_add_track(cdi, &trk, &shift, prestart, &total_pregap, cur_pregap); + else + success = 1; + can_add_track = 0; + + memset(ansi, 0, MAX_FILENAME_LENGTH * sizeof(char)); + memset(filename, 0, MAX_FILENAME_LENGTH * sizeof(wchar_t)); + + success = cdi_cue_get_buffer(ansi, &line, 0); + if (!success) + break; + success = cdi_cue_get_keyword(&type, &line); + if (!success) + break; + + trk.file = NULL; + error = 1; + + if (!strcmp(type, "BINARY")) { + memset(temp, 0, MAX_FILENAME_LENGTH * sizeof(wchar_t)); + mbstowcs(temp, ansi, sizeof_w(temp)); + plat_append_filename(filename, pathname, temp); + trk.file = track_file_init(filename, &error); + } + if (error) { +#ifdef ENABLE_cdrom_image_backend_log + cdrom_image_backend_log("CUE: cannot open fille '%ls' in cue sheet!\n", + filename); +#endif + if (trk.file != NULL) { + trk.file->close(trk.file); + trk.file = NULL; + } + success = 0; + } + } else if (!strcmp(command, "FILE")) + success = cdi_cue_get_frame(&cur_pregap, &line); + else if (!strcmp(command, "CATALOG") || !strcmp(command, "CDTEXTFILE") || !strcmp(command, "FLAGS") || !strcmp(command, "ISRC") || + !strcmp(command, "PERFORMER") || !strcmp(command, "POSTGAP") || !strcmp(command, "REM") || + !strcmp(command, "SONGWRITER") || !strcmp(command, "TITLE") || !strcmp(command, "")) { + /* Ignored commands. */ + success = 1; + } else { +#ifdef ENABLE_cdrom_image_backend_log + cdrom_image_backend_log("CUE: unsupported command '%s' in cue sheet!\n", + command.c_str()); +#endif + success = 0; + } + + if (!success) + break; + } + + fclose(fp); + if (!success) + return 0; + + /* Add last track. */ + if (!cdi_add_track(cdi, &trk, &shift, prestart, &total_pregap, cur_pregap)) + return 0; + + /* Add lead out track. */ + trk.number++; + trk.track_number = 0xAA; + trk.attr = 0x16; /* Was 0x00 but I believe 0x16 is appropriate. */ + trk.start = 0; + trk.length = 0; + trk.file = NULL; + if (!cdi_add_track(cdi, &trk, &shift, 0, &total_pregap, 0)) + return 0; + + return 1; +} + + +int +cdi_has_data_track(cd_img_t *cdi) +{ + int i; + + if ((cdi == NULL) || (cdi->tracks == NULL)) + return 0; + + /* Data track has attribute 0x14. */ + for (i = 0; i < cdi->tracks_num; i++) { + if (cdi->tracks[i].attr == DATA_TRACK) + return 1; + } + + return 0; +} + + +int +cdi_has_audio_track(cd_img_t *cdi) +{ + int i; + + if ((cdi == NULL) || (cdi->tracks == NULL)) + return 0; + + /* Audio track has attribute 0x14. */ + for (i = 0; i < cdi->tracks_num; i++) { + if (cdi->tracks[i].attr == AUDIO_TRACK) + return 1; + } + + return 0; +} diff --git a/src/cdrom/cdrom_image_backend.h b/src/cdrom/cdrom_image_backend.h new file mode 100644 index 000000000..39d5b701d --- /dev/null +++ b/src/cdrom/cdrom_image_backend.h @@ -0,0 +1,94 @@ +/* + * 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. + * + * CD-ROM image file handling module header , translated to C + * from cdrom_dosbox.h. + * + * Version: @(#)cdrom_image_backend.h 1.0.0 2019/12/19 + * + * Authors: Miran Grca, + * Fred N. van Kempen, + * The DOSBox Team, + * + * Copyright 2016-2019 Miran Grca. + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2002-2019 The DOSBox Team. + */ +#ifndef CDROM_IMAGE_BACKEND_H +#define CDROM_IMAGE_BACKEND_H + +#define RAW_SECTOR_SIZE 2352 +#define COOKED_SECTOR_SIZE 2048 + +#define DATA_TRACK 0x14 +#define AUDIO_TRACK 0x10 + +#define CD_FPS 75 +#define FRAMES_TO_MSF(f, M,S,F) { \ + uint64_t value = f; \ + *(F) = (value%CD_FPS) & 0xff; \ + value /= CD_FPS; \ + *(S) = (value%60) & 0xff; \ + value /= 60; \ + *(M) = value & 0xff; \ +} +#define MSF_TO_FRAMES(M, S, F) ((M)*60*CD_FPS+(S)*CD_FPS+(F)) + + +typedef struct SMSF { + uint8_t min; + uint8_t sec; + uint8_t fr; +} TMSF; + +/* Track file struct. */ +typedef struct { + int (*read)(void *p, uint8_t *buffer, uint64_t seek, size_t count); + uint64_t (*get_length)(void *p); + void (*close)(void *p); + + wchar_t fn[260]; + FILE *file; +} track_file_t; + +typedef struct { + int number, track_number, attr, sector_size, + mode2, form; + uint64_t start, length, + skip; + track_file_t *file; +} track_t; + +typedef struct { + int tracks_num; + track_t *tracks; +} cd_img_t; + + +/* Binary file functions. */ +extern void cdi_close(cd_img_t *cdi); +extern int cdi_set_device(cd_img_t *cdi, const wchar_t *path); +extern int cdi_get_audio_tracks(cd_img_t *cdi, int *st_track, int *end, TMSF *lead_out); +extern int cdi_get_audio_track_info(cd_img_t *cdi, int end, int track, int *track_num, TMSF *start, uint8_t *attr); +extern int cdi_get_track(cd_img_t *cdi, uint32_t sector); +extern int cdi_get_audio_sub(cd_img_t *cdi, uint32_t sector, uint8_t *attr, uint8_t *track, uint8_t *index, TMSF *rel_pos, TMSF *abs_pos); +extern int cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector); +extern int cdi_read_sectors(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector, uint32_t num); +extern int cdi_read_sector_sub(cd_img_t *cdi, uint8_t *buffer, uint32_t sector); +extern int cdi_get_sector_size(cd_img_t *cdi, uint32_t sector); +extern int cdi_is_mode2(cd_img_t *cdi, uint32_t sector); +extern int cdi_get_mode2_form(cd_img_t *cdi, uint32_t sector); +extern int cdi_can_read_pvd(track_file_t *file, uint64_t sector_size, int mode2); +extern int cdi_load_iso(cd_img_t *cdi, const wchar_t *filename); +extern int cdi_load_cue(cd_img_t *cdi, const wchar_t *cuefile); +extern int cdi_has_data_track(cd_img_t *cdi); +extern int cdi_has_audio_track(cd_img_t *cdi); + + + +#endif /* ! CDROM_IMAGE_BACKEND_H */ diff --git a/src/config.c b/src/config.c index 9b09e7a8f..583605583 100644 --- a/src/config.c +++ b/src/config.c @@ -8,7 +8,7 @@ * * Configuration file handler. * - * Version: @(#)config.c 1.0.65 2019/12/05 + * Version: @(#)config.c 1.0.66 2019/12/21 * * Authors: Sarah Walker, * Miran Grca, @@ -57,9 +57,7 @@ #include "disk/zip.h" #include "sound/sound.h" #include "sound/midi.h" -#include "sound/snd_dbopl.h" #include "sound/snd_mpu401.h" -#include "sound/snd_opl.h" #include "sound/sound.h" #include "video/video.h" #include "plat.h" @@ -657,14 +655,6 @@ load_sound(void) GAMEBLASTER = !!config_get_int(cat, "gameblaster", 0); GUS = !!config_get_int(cat, "gus", 0); - memset(temp, '\0', sizeof(temp)); - p = config_get_string(cat, "opl_type", "dbopl"); - strcpy(temp, p); - if (!strcmp(temp, "nukedopl") || !strcmp(temp, "1")) - opl_type = 1; - else - opl_type = 0; - memset(temp, '\0', sizeof(temp)); p = config_get_string(cat, "sound_type", "float"); strcpy(temp, p); @@ -1271,7 +1261,6 @@ config_load(void) fdd_set_check_bpb(i, 1); } mem_size = 640; - opl_type = 0; isartc_type = 0; for (i = 0; i < ISAMEM_MAX; i++) isamem_type[i] = 0; @@ -1562,11 +1551,6 @@ save_sound(void) else config_set_int(cat, "gus", GUS); - if (opl_type == 0) - config_delete_var(cat, "opl_type"); - else - config_set_string(cat, "opl_type", (opl_type == 1) ? "nukedopl" : "dbopl"); - if (sound_is_float == 1) config_delete_var(cat, "sound_type"); else diff --git a/src/scsi/scsi_device.h b/src/scsi/scsi_device.h index f989d7423..5527dae0e 100644 --- a/src/scsi/scsi_device.h +++ b/src/scsi/scsi_device.h @@ -248,7 +248,7 @@ #define CHECK_READY 2 #define ALLOW_UA 1 -#define MSFtoLBA(m,s,f) ((((m*60)+s)*75)+f) +#define MSFtoLBA(m,s,f) ((((m * 60) + s) * 75) + f) #define MSG_COMMAND_COMPLETE 0x00 diff --git a/src/sound/dbopl.cpp b/src/sound/dbopl.cpp deleted file mode 100644 index 85228ae10..000000000 --- a/src/sound/dbopl.cpp +++ /dev/null @@ -1,1512 +0,0 @@ -/* Copyright holders: The DOSBox Team - see COPYING for more details -*/ - -/* - DOSBox implementation of a combined Yamaha YMF262 and Yamaha YM3812 emulator. - Enabling the opl3 bit will switch the emulator to stereo opl3 output instead of regular mono opl2 - Except for the table generation it's all integer math - Can choose different types of generators, using muls and bigger tables, try different ones for slower platforms - The generation was based on the MAME implementation but tried to have it use less memory and be faster in general - MAME uses much bigger envelope tables and this will be the biggest cause of it sounding different at times - - //TODO Don't delay first operator 1 sample in opl3 mode - //TODO Maybe not use class method pointers but a regular function pointers with operator as first parameter - //TODO Fix panning for the Percussion channels, would any opl3 player use it and actually really change it though? - //TODO Check if having the same accuracy in all frequency multipliers sounds better or not - - //DUNNO Keyon in 4op, switch to 2op without keyoff. -*/ - -/* $Id: dbopl.cpp,v 1.10 2009-06-10 19:54:51 harekiet Exp $ */ - -#include -#include -#include -#include "dbopl.h" - - -#ifndef PI -#define PI 3.14159265358979323846 -#endif - -namespace DBOPL { - -#define OPLRATE ((double)(14318180.0 / 288.0)) -#define TREMOLO_TABLE 52 - -//Try to use most precision for frequencies -//Else try to keep different waves in synch -//#define WAVE_PRECISION 1 -#ifndef WAVE_PRECISION -//Wave bits available in the top of the 32bit range -//Original adlib uses 10.10, we use 10.22 -#define WAVE_BITS 10 -#else -//Need some extra bits at the top to have room for octaves and frequency multiplier -//We support to 8 times lower rate -//128 * 15 * 8 = 15350, 2^13.9, so need 14 bits -#define WAVE_BITS 14 -#endif -#define WAVE_SH ( 32 - WAVE_BITS ) -#define WAVE_MASK ( ( 1 << WAVE_SH ) - 1 ) - -//Use the same accuracy as the waves -#define LFO_SH ( WAVE_SH - 10 ) -//LFO is controlled by our tremolo 256 sample limit -#define LFO_MAX ( 256 << ( LFO_SH ) ) - - -//Maximum amount of attenuation bits -//Envelope goes to 511, 9 bits -#if (DBOPL_WAVE == WAVE_TABLEMUL ) -//Uses the value directly -#define ENV_BITS ( 9 ) -#else -//Add 3 bits here for more accuracy and would have to be shifted up either way -#define ENV_BITS ( 9 ) -#endif -//Limits of the envelope with those bits and when the envelope goes silent -#define ENV_MIN 0 -#define ENV_EXTRA ( ENV_BITS - 9 ) -#define ENV_MAX ( 511 << ENV_EXTRA ) -#define ENV_LIMIT ( ( 12 * 256) >> ( 3 - ENV_EXTRA ) ) -#define ENV_SILENT( _X_ ) ( (_X_) >= ENV_LIMIT ) - -//Attack/decay/release rate counter shift -#define RATE_SH 24 -#define RATE_MASK ( ( 1 << RATE_SH ) - 1 ) -//Has to fit within 16bit lookuptable -#define MUL_SH 16 - -//Check some ranges -#if ENV_EXTRA > 3 -#error Too many envelope bits -#endif - - -//How much to substract from the base value for the final attenuation -static const Bit8u KslCreateTable[16] = { - //0 will always be be lower than 7 * 8 - 64, 32, 24, 19, - 16, 12, 11, 10, - 8, 6, 5, 4, - 3, 2, 1, 0, -}; - -#define M(_X_) ((Bit8u)( (_X_) * 2)) -static const Bit8u FreqCreateTable[16] = { - M(0.5), M(1 ), M(2 ), M(3 ), M(4 ), M(5 ), M(6 ), M(7 ), - M(8 ), M(9 ), M(10), M(10), M(12), M(12), M(15), M(15) -}; -#undef M - -//We're not including the highest attack rate, that gets a special value -static const Bit8u AttackSamplesTable[13] = { - 69, 55, 46, 40, - 35, 29, 23, 20, - 19, 15, 11, 10, - 9 -}; -//On a real opl these values take 8 samples to reach and are based upon larger tables -static const Bit8u EnvelopeIncreaseTable[13] = { - 4, 5, 6, 7, - 8, 10, 12, 14, - 16, 20, 24, 28, - 32, -}; - -#if ( DBOPL_WAVE == WAVE_HANDLER ) || ( DBOPL_WAVE == WAVE_TABLELOG ) -static Bit16u ExpTable[ 256 ]; -#endif - -#if ( DBOPL_WAVE == WAVE_HANDLER ) -//PI table used by WAVEHANDLER -static Bit16u SinTable[ 512 ]; -#endif - -#if ( DBOPL_WAVE > WAVE_HANDLER ) -//Layout of the waveform table in 512 entry intervals -//With overlapping waves we reduce the table to half it's size - -// | |//\\|____|WAV7|//__|/\ |____|/\/\| -// |\\//| | |WAV7| | \/| | | -// |06 |0126|17 |7 |3 |4 |4 5 |5 | - -//6 is just 0 shifted and masked - -static Bit16s WaveTable[ 8 * 512 ]; -//Distance into WaveTable the wave starts -static const Bit16u WaveBaseTable[8] = { - 0x000, 0x200, 0x200, 0x800, - 0xa00, 0xc00, 0x100, 0x400, - -}; -//Mask the counter with this -static const Bit16u WaveMaskTable[8] = { - 1023, 1023, 511, 511, - 1023, 1023, 512, 1023, -}; - -//Where to start the counter on at keyon -static const Bit16u WaveStartTable[8] = { - 512, 0, 0, 0, - 0, 512, 512, 256, -}; -#endif - -#if ( DBOPL_WAVE == WAVE_TABLEMUL ) -static Bit16u MulTable[ 384 ]; -#endif - -static Bit8u KslTable[ 8 * 16 ]; -static Bit8u TremoloTable[ TREMOLO_TABLE ]; -//Start of a channel behind the chip struct start -static Bit16u ChanOffsetTable[32]; -//Start of an operator behind the chip struct start -static Bit16u OpOffsetTable[64]; - -//The lower bits are the shift of the operator vibrato value -//The highest bit is right shifted to generate -1 or 0 for negation -//So taking the highest input value of 7 this gives 3, 7, 3, 0, -3, -7, -3, 0 -static const Bit8s VibratoTable[ 8 ] = { - 1 - 0x00, 0 - 0x00, 1 - 0x00, 30 - 0x00, - 1 - 0x80, 0 - 0x80, 1 - 0x80, 30 - 0x80 -}; - -//Shift strength for the ksl value determined by ksl strength -static const Bit8u KslShiftTable[4] = { - 31,1,2,0 -}; - -//Generate a table index and table shift value using input value from a selected rate -static void EnvelopeSelect( Bit8u val, Bit8u& index, Bit8u& shift ) { - if ( val < 13 * 4 ) { //Rate 0 - 12 - shift = 12 - ( val >> 2 ); - index = val & 3; - } else if ( val < 15 * 4 ) { //rate 13 - 14 - shift = 0; - index = val - 12 * 4; - } else { //rate 15 and up - shift = 0; - index = 12; - } -} - -#if ( DBOPL_WAVE == WAVE_HANDLER ) -/* - Generate the different waveforms out of the sine/exponetial table using handlers -*/ -static inline Bits MakeVolume( Bitu wave, Bitu volume ) { - Bitu total = wave + volume; - Bitu index = total & 0xff; - Bitu sig = ExpTable[ index ]; - Bitu exp = total >> 8; -#if 0 - //Check if we overflow the 31 shift limit - if ( exp >= 32 ) { - LOG_MSG( "WTF %d %d", total, exp ); - } -#endif - return (sig >> exp); -}; - -static Bits DB_FASTCALL WaveForm0( Bitu i, Bitu volume ) { - Bits neg = 0 - (( i >> 9) & 1);//Create ~0 or 0 - Bitu wave = SinTable[i & 511]; - return (MakeVolume( wave, volume ) ^ neg) - neg; -} -static Bits DB_FASTCALL WaveForm1( Bitu i, Bitu volume ) { - Bit32u wave = SinTable[i & 511]; - wave |= ( ( (i ^ 512 ) & 512) - 1) >> ( 32 - 12 ); - return MakeVolume( wave, volume ); -} -static Bits DB_FASTCALL WaveForm2( Bitu i, Bitu volume ) { - Bitu wave = SinTable[i & 511]; - return MakeVolume( wave, volume ); -} -static Bits DB_FASTCALL WaveForm3( Bitu i, Bitu volume ) { - Bitu wave = SinTable[i & 255]; - wave |= ( ( (i ^ 256 ) & 256) - 1) >> ( 32 - 12 ); - return MakeVolume( wave, volume ); -} -static Bits DB_FASTCALL WaveForm4( Bitu i, Bitu volume ) { - //Twice as fast - i <<= 1; - Bits neg = 0 - (( i >> 9) & 1);//Create ~0 or 0 - Bitu wave = SinTable[i & 511]; - wave |= ( ( (i ^ 512 ) & 512) - 1) >> ( 32 - 12 ); - return (MakeVolume( wave, volume ) ^ neg) - neg; -} -static Bits DB_FASTCALL WaveForm5( Bitu i, Bitu volume ) { - //Twice as fast - i <<= 1; - Bitu wave = SinTable[i & 511]; - wave |= ( ( (i ^ 512 ) & 512) - 1) >> ( 32 - 12 ); - return MakeVolume( wave, volume ); -} -static Bits DB_FASTCALL WaveForm6( Bitu i, Bitu volume ) { - Bits neg = 0 - (( i >> 9) & 1);//Create ~0 or 0 - return (MakeVolume( 0, volume ) ^ neg) - neg; -} -static Bits DB_FASTCALL WaveForm7( Bitu i, Bitu volume ) { - //Negative is reversed here - Bits neg = (( i >> 9) & 1) - 1; - Bitu wave = (i << 3); - //When negative the volume also runs backwards - wave = ((wave ^ neg) - neg) & 4095; - return (MakeVolume( wave, volume ) ^ neg) - neg; -} - -static const WaveHandler WaveHandlerTable[8] = { - WaveForm0, WaveForm1, WaveForm2, WaveForm3, - WaveForm4, WaveForm5, WaveForm6, WaveForm7 -}; - -#endif - -/* - Operator -*/ - -//We zero out when rate == 0 -inline void Operator::UpdateAttack( const Chip* chip ) { - Bit8u rate = reg60 >> 4; - if ( rate ) { - Bit8u val = (rate << 2) + ksr; - attackAdd = chip->attackRates[ val ]; - rateZero &= ~(1 << ATTACK); - } else { - attackAdd = 0; - rateZero |= (1 << ATTACK); - } -} -inline void Operator::UpdateDecay( const Chip* chip ) { - Bit8u rate = reg60 & 0xf; - if ( rate ) { - Bit8u val = (rate << 2) + ksr; - decayAdd = chip->linearRates[ val ]; - rateZero &= ~(1 << DECAY); - } else { - decayAdd = 0; - rateZero |= (1 << DECAY); - } -} -inline void Operator::UpdateRelease( const Chip* chip ) { - Bit8u rate = reg80 & 0xf; - if ( rate ) { - Bit8u val = (rate << 2) + ksr; - releaseAdd = chip->linearRates[ val ]; - rateZero &= ~(1 << RELEASE); - if ( !(reg20 & MASK_SUSTAIN ) ) { - rateZero &= ~( 1 << SUSTAIN ); - } - } else { - rateZero |= (1 << RELEASE); - releaseAdd = 0; - if ( !(reg20 & MASK_SUSTAIN ) ) { - rateZero |= ( 1 << SUSTAIN ); - } - } -} - -inline void Operator::UpdateAttenuation( ) { - Bit8u kslBase = (Bit8u)((chanData >> SHIFT_KSLBASE) & 0xff); - Bit32u tl = reg40 & 0x3f; - Bit8u kslShift = KslShiftTable[ reg40 >> 6 ]; - //Make sure the attenuation goes to the right bits - totalLevel = tl << ( ENV_BITS - 7 ); //Total level goes 2 bits below max - totalLevel += ( kslBase << ENV_EXTRA ) >> kslShift; -} - -void Operator::UpdateFrequency( ) { - Bit32u freq = chanData & (( 1 << 10 ) - 1); - Bit32u block = (chanData >> 10) & 0xff; -#ifdef WAVE_PRECISION - block = 7 - block; - waveAdd = ( freq * freqMul ) >> block; -#else - waveAdd = ( freq << block ) * freqMul; -#endif - if ( reg20 & MASK_VIBRATO ) { - vibStrength = (Bit8u)(freq >> 7); - -#ifdef WAVE_PRECISION - vibrato = ( vibStrength * freqMul ) >> block; -#else - vibrato = ( vibStrength << block ) * freqMul; -#endif - } else { - vibStrength = 0; - vibrato = 0; - } -} - -void Operator::UpdateRates( const Chip* chip ) { - //Mame seems to reverse this where enabling ksr actually lowers - //the rate, but pdf manuals says otherwise? - Bit8u newKsr = (Bit8u)((chanData >> SHIFT_KEYCODE) & 0xff); - if ( !( reg20 & MASK_KSR ) ) { - newKsr >>= 2; - } - if ( ksr == newKsr ) - return; - ksr = newKsr; - UpdateAttack( chip ); - UpdateDecay( chip ); - UpdateRelease( chip ); -} - -INLINE Bit32s Operator::RateForward( Bit32u add ) { - rateIndex += add; - Bit32s ret = rateIndex >> RATE_SH; - rateIndex = rateIndex & RATE_MASK; - return ret; -} - -template< Operator::State yes> -Bits Operator::TemplateVolume( ) { - Bit32s vol = volume; - Bit32s change; - switch ( yes ) { - case OFF: - return ENV_MAX; - case ATTACK: - change = RateForward( attackAdd ); - if ( !change ) - return vol; - vol += ( (~vol) * change ) >> 3; - if ( vol < ENV_MIN ) { - volume = ENV_MIN; - rateIndex = 0; - SetState( DECAY ); - return ENV_MIN; - } - break; - case DECAY: - vol += RateForward( decayAdd ); - if ( GCC_UNLIKELY(vol >= sustainLevel) ) { - //Check if we didn't overshoot max attenuation, then just go off - if ( GCC_UNLIKELY(vol >= ENV_MAX) ) { - volume = ENV_MAX; - SetState( OFF ); - return ENV_MAX; - } - //Continue as sustain - rateIndex = 0; - SetState( SUSTAIN ); - } - break; - case SUSTAIN: - if ( reg20 & MASK_SUSTAIN ) { - return vol; - } - //In sustain phase, but not sustaining, do regular release - case RELEASE: - vol += RateForward( releaseAdd );; - if ( GCC_UNLIKELY(vol >= ENV_MAX) ) { - volume = ENV_MAX; - SetState( OFF ); - return ENV_MAX; - } - break; - } - volume = vol; - return vol; -} - -static const VolumeHandler VolumeHandlerTable[5] = { - &Operator::TemplateVolume< Operator::OFF >, - &Operator::TemplateVolume< Operator::RELEASE >, - &Operator::TemplateVolume< Operator::SUSTAIN >, - &Operator::TemplateVolume< Operator::DECAY >, - &Operator::TemplateVolume< Operator::ATTACK > -}; - -INLINE Bitu Operator::ForwardVolume() { - return currentLevel + (this->*volHandler)(); -} - - -INLINE Bitu Operator::ForwardWave() { - waveIndex += waveCurrent; - return waveIndex >> WAVE_SH; -} - -void Operator::Write20( const Chip* chip, Bit8u val ) { - Bit8u change = (reg20 ^ val ); - if ( !change ) - return; - reg20 = val; - //Shift the tremolo bit over the entire register, saved a branch, YES! - tremoloMask = (Bit8s)(val) >> 7; - tremoloMask &= ~(( 1 << ENV_EXTRA ) -1); - //Update specific features based on changes - if ( change & MASK_KSR ) { - UpdateRates( chip ); - } - //With sustain enable the volume doesn't change - if ( reg20 & MASK_SUSTAIN || ( !releaseAdd ) ) { - rateZero |= ( 1 << SUSTAIN ); - } else { - rateZero &= ~( 1 << SUSTAIN ); - } - //Frequency multiplier or vibrato changed - if ( change & (0xf | MASK_VIBRATO) ) { - freqMul = chip->freqMul[ val & 0xf ]; - UpdateFrequency(); - } -} - -void Operator::Write40( const Chip* /*chip*/, Bit8u val ) { - if (!(reg40 ^ val )) - return; - reg40 = val; - UpdateAttenuation( ); -} - -void Operator::Write60( const Chip* chip, Bit8u val ) { - Bit8u change = reg60 ^ val; - reg60 = val; - if ( change & 0x0f ) { - UpdateDecay( chip ); - } - if ( change & 0xf0 ) { - UpdateAttack( chip ); - } -} - -void Operator::Write80( const Chip* chip, Bit8u val ) { - Bit8u change = (reg80 ^ val ); - if ( !change ) - return; - reg80 = val; - Bit8u sustain = val >> 4; - //Turn 0xf into 0x1f - sustain |= ( sustain + 1) & 0x10; - sustainLevel = sustain << ( ENV_BITS - 5 ); - if ( change & 0x0f ) { - UpdateRelease( chip ); - } -} - -void Operator::WriteE0( const Chip* chip, Bit8u val ) { - if ( !(regE0 ^ val) ) - return; - //in opl3 mode you can always selet 7 waveforms regardless of waveformselect - Bit8u waveForm = val & ( ( 0x3 & chip->waveFormMask ) | (0x7 & chip->opl3Active ) ); - regE0 = val; -#if ( DBOPL_WAVE == WAVE_HANDLER ) - waveHandler = WaveHandlerTable[ waveForm ]; -#else - waveBase = WaveTable + WaveBaseTable[ waveForm ]; - waveStart = WaveStartTable[ waveForm ] << WAVE_SH; - waveMask = WaveMaskTable[ waveForm ]; -#endif -} - -INLINE void Operator::SetState( Bit8u s ) { - state = s; - volHandler = VolumeHandlerTable[ s ]; -} - -INLINE bool Operator::Silent() const { - if ( !ENV_SILENT( totalLevel + volume ) ) - return false; - if ( !(rateZero & ( 1 << state ) ) ) - return false; - return true; -} - -INLINE void Operator::Prepare( const Chip* chip ) { - currentLevel = totalLevel + (chip->tremoloValue & tremoloMask); - waveCurrent = waveAdd; - if ( vibStrength >> chip->vibratoShift ) { - Bit32s add = vibrato >> chip->vibratoShift; - //Sign extend over the shift value - Bit32s neg = chip->vibratoSign; - //Negate the add with -1 or 0 - add = ( add ^ neg ) - neg; - waveCurrent += add; - } -} - -void Operator::KeyOn( Bit8u mask ) { - if ( !keyOn ) { - //Restart the frequency generator -#if ( DBOPL_WAVE > WAVE_HANDLER ) - waveIndex = waveStart; -#else - waveIndex = 0; -#endif - rateIndex = 0; - SetState( ATTACK ); - } - keyOn |= mask; -} - -void Operator::KeyOff( Bit8u mask ) { - keyOn &= ~mask; - if ( !keyOn ) { - if ( state != OFF ) { - SetState( RELEASE ); - } - } -} - -INLINE Bits Operator::GetWave( Bitu index, Bitu vol ) { -#if ( DBOPL_WAVE == WAVE_HANDLER ) - return waveHandler( index, vol << ( 3 - ENV_EXTRA ) ); -#elif ( DBOPL_WAVE == WAVE_TABLEMUL ) - return (waveBase[ index & waveMask ] * MulTable[ vol >> ENV_EXTRA ]) >> MUL_SH; -#elif ( DBOPL_WAVE == WAVE_TABLELOG ) - Bit32s wave = waveBase[ index & waveMask ]; - Bit32u total = ( wave & 0x7fff ) + vol << ( 3 - ENV_EXTRA ); - Bit32s sig = ExpTable[ total & 0xff ]; - Bit32u exp = total >> 8; - Bit32s neg = wave >> 16; - return ((sig ^ neg) - neg) >> exp; -#else -#error "No valid wave routine" -#endif -} - -Bits INLINE Operator::GetSample( Bits modulation ) { - Bitu vol = ForwardVolume(); - if ( ENV_SILENT( vol ) ) { - //Simply forward the wave - waveIndex += waveCurrent; - return 0; - } else { - Bitu index = ForwardWave(); - index += modulation; - return GetWave( index, vol ); - } -} - -Operator::Operator() { - chanData = 0; - freqMul = 0; - waveIndex = 0; - waveAdd = 0; - waveCurrent = 0; - keyOn = 0; - ksr = 0; - reg20 = 0; - reg40 = 0; - reg60 = 0; - reg80 = 0; - regE0 = 0; - SetState( OFF ); - rateZero = (1 << OFF); - sustainLevel = ENV_MAX; - currentLevel = ENV_MAX; - totalLevel = ENV_MAX; - volume = ENV_MAX; - releaseAdd = 0; -} - -/* - Channel -*/ - -Channel::Channel() { - old[0] = old[1] = 0; - chanData = 0; - regB0 = 0; - regC0 = 0; - maskLeft = -1; - maskRight = -1; - feedback = 31; - fourMask = 0; - synthHandler = &Channel::BlockTemplate< sm2FM >; -}; - -void Channel::SetChanData( const Chip* chip, Bit32u data ) { - Bit32u change = chanData ^ data; - chanData = data; - Op( 0 )->chanData = data; - Op( 1 )->chanData = data; - //Since a frequency update triggered this, always update frequency - Op( 0 )->UpdateFrequency(); - Op( 1 )->UpdateFrequency(); - if ( change & ( 0xff << SHIFT_KSLBASE ) ) { - Op( 0 )->UpdateAttenuation(); - Op( 1 )->UpdateAttenuation(); - } - if ( change & ( 0xff << SHIFT_KEYCODE ) ) { - Op( 0 )->UpdateRates( chip ); - Op( 1 )->UpdateRates( chip ); - } -} - -void Channel::UpdateFrequency( const Chip* chip, Bit8u fourOp ) { - //Extrace the frequency bits - Bit32u data = chanData & 0xffff; - Bit32u kslBase = KslTable[ data >> 6 ]; - Bit32u keyCode = ( data & 0x1c00) >> 9; - if ( chip->reg08 & 0x40 ) { - keyCode |= ( data & 0x100)>>8; /* notesel == 1 */ - } else { - keyCode |= ( data & 0x200)>>9; /* notesel == 0 */ - } - //Add the keycode and ksl into the highest bits of chanData - data |= (keyCode << SHIFT_KEYCODE) | ( kslBase << SHIFT_KSLBASE ); - ( this + 0 )->SetChanData( chip, data ); - if ( fourOp & 0x3f ) { - ( this + 1 )->SetChanData( chip, data ); - } -} - -void Channel::WriteA0( const Chip* chip, Bit8u val ) { - Bit8u fourOp = chip->reg104 & chip->opl3Active & fourMask; - //Don't handle writes to silent fourop channels - if ( fourOp > 0x80 ) - return; - Bit32u change = (chanData ^ val ) & 0xff; - if ( change ) { - chanData ^= change; - UpdateFrequency( chip, fourOp ); - } -} - -void Channel::WriteB0( const Chip* chip, Bit8u val ) { - Bit8u fourOp = chip->reg104 & chip->opl3Active & fourMask; - //Don't handle writes to silent fourop channels - if ( fourOp > 0x80 ) - return; - Bitu change = (chanData ^ ( val << 8 ) ) & 0x1f00; - if ( change ) { - chanData ^= change; - UpdateFrequency( chip, fourOp ); - } - //Check for a change in the keyon/off state - if ( !(( val ^ regB0) & 0x20)) - return; - regB0 = val; - if ( val & 0x20 ) { - Op(0)->KeyOn( 0x1 ); - Op(1)->KeyOn( 0x1 ); - if ( fourOp & 0x3f ) { - ( this + 1 )->Op(0)->KeyOn( 1 ); - ( this + 1 )->Op(1)->KeyOn( 1 ); - } - } else { - Op(0)->KeyOff( 0x1 ); - Op(1)->KeyOff( 0x1 ); - if ( fourOp & 0x3f ) { - ( this + 1 )->Op(0)->KeyOff( 1 ); - ( this + 1 )->Op(1)->KeyOff( 1 ); - } - } -} - -void Channel::WriteC0( const Chip* chip, Bit8u val ) { - Bit8u change = val ^ regC0; - if ( !change ) - return; - regC0 = val; - feedback = ( val >> 1 ) & 7; - if ( feedback ) { - //We shift the input to the right 10 bit wave index value - feedback = 9 - feedback; - } else { - feedback = 31; - } - //Select the new synth mode - if ( chip->opl3Active ) { - //4-op mode enabled for this channel - if ( (chip->reg104 & fourMask) & 0x3f ) { - Channel* chan0, *chan1; - //Check if it's the 2nd channel in a 4-op - if ( !(fourMask & 0x80 ) ) { - chan0 = this; - chan1 = this + 1; - } else { - chan0 = this - 1; - chan1 = this; - } - - Bit8u synth = ( (chan0->regC0 & 1) << 0 )| (( chan1->regC0 & 1) << 1 ); - switch ( synth ) { - case 0: - chan0->synthHandler = &Channel::BlockTemplate< sm3FMFM >; - break; - case 1: - chan0->synthHandler = &Channel::BlockTemplate< sm3AMFM >; - break; - case 2: - chan0->synthHandler = &Channel::BlockTemplate< sm3FMAM >; - break; - case 3: - chan0->synthHandler = &Channel::BlockTemplate< sm3AMAM >; - break; - } - //Disable updating percussion channels - } else if ((fourMask & 0x40) && ( chip->regBD & 0x20) ) { - - //Regular dual op, am or fm - } else if ( val & 1 ) { - synthHandler = &Channel::BlockTemplate< sm3AM >; - } else { - synthHandler = &Channel::BlockTemplate< sm3FM >; - } - maskLeft = ( val & 0x10 ) ? -1 : 0; - maskRight = ( val & 0x20 ) ? -1 : 0; - //opl2 active - } else { - //Disable updating percussion channels - if ( (fourMask & 0x40) && ( chip->regBD & 0x20 ) ) { - - //Regular dual op, am or fm - } else if ( val & 1 ) { - synthHandler = &Channel::BlockTemplate< sm2AM >; - } else { - synthHandler = &Channel::BlockTemplate< sm2FM >; - } - } -} - -void Channel::ResetC0( const Chip* chip ) { - Bit8u val = regC0; - regC0 ^= 0xff; - WriteC0( chip, val ); -}; - -template< bool opl3Mode> -INLINE void Channel::GeneratePercussion( Chip* chip, Bit32s* output ) { - Channel* chan = this; - - //BassDrum - Bit32s mod = (Bit32u)((old[0] + old[1])) >> feedback; - old[0] = old[1]; - old[1] = Op(0)->GetSample( mod ); - - //When bassdrum is in AM mode first operator is ignoed - if ( chan->regC0 & 1 ) { - mod = 0; - } else { - mod = old[0]; - } - Bit32s sample = Op(1)->GetSample( mod ); - - - //Precalculate stuff used by other outputs - Bit32u noiseBit = chip->ForwardNoise() & 0x1; - Bit32u c2 = Op(2)->ForwardWave(); - Bit32u c5 = Op(5)->ForwardWave(); - Bit32u phaseBit = (((c2 & 0x88) ^ ((c2<<5) & 0x80)) | ((c5 ^ (c5<<2)) & 0x20)) ? 0x02 : 0x00; - - //Hi-Hat - Bit32u hhVol = Op(2)->ForwardVolume(); - if ( !ENV_SILENT( hhVol ) ) { - Bit32u hhIndex = (phaseBit<<8) | (0x34 << ( phaseBit ^ (noiseBit << 1 ))); - sample += Op(2)->GetWave( hhIndex, hhVol ); - } - //Snare Drum - Bit32u sdVol = Op(3)->ForwardVolume(); - if ( !ENV_SILENT( sdVol ) ) { - Bit32u sdIndex = ( 0x100 + (c2 & 0x100) ) ^ ( noiseBit << 8 ); - sample += Op(3)->GetWave( sdIndex, sdVol ); - } - //Tom-tom - sample += Op(4)->GetSample( 0 ); - - //Top-Cymbal - Bit32u tcVol = Op(5)->ForwardVolume(); - if ( !ENV_SILENT( tcVol ) ) { - Bit32u tcIndex = (1 + phaseBit) << 8; - sample += Op(5)->GetWave( tcIndex, tcVol ); - } - sample <<= 1; - if ( opl3Mode ) { - output[0] += sample; - output[1] += sample; - } else { - output[0] += sample; - } -} - -template -Channel* Channel::BlockTemplate( Chip* chip, Bit32u samples, Bit32s* output ) { - switch( mode ) { - case sm2AM: - case sm3AM: - if ( Op(0)->Silent() && Op(1)->Silent() ) { - old[0] = old[1] = 0; - return (this + 1); - } - break; - case sm2FM: - case sm3FM: - if ( Op(1)->Silent() ) { - old[0] = old[1] = 0; - return (this + 1); - } - break; - case sm3FMFM: - if ( Op(3)->Silent() ) { - old[0] = old[1] = 0; - return (this + 2); - } - break; - case sm3AMFM: - if ( Op(0)->Silent() && Op(3)->Silent() ) { - old[0] = old[1] = 0; - return (this + 2); - } - break; - case sm3FMAM: - if ( Op(1)->Silent() && Op(3)->Silent() ) { - old[0] = old[1] = 0; - return (this + 2); - } - break; - case sm3AMAM: - if ( Op(0)->Silent() && Op(2)->Silent() && Op(3)->Silent() ) { - old[0] = old[1] = 0; - return (this + 2); - } - break; - case sm2Percussion: - case sm3Percussion: - break; - } - //Init the operators with the the current vibrato and tremolo values - Op( 0 )->Prepare( chip ); - Op( 1 )->Prepare( chip ); - if ( mode > sm4Start ) { - Op( 2 )->Prepare( chip ); - Op( 3 )->Prepare( chip ); - } - if ( mode > sm6Start ) { - Op( 4 )->Prepare( chip ); - Op( 5 )->Prepare( chip ); - } - for ( Bitu i = 0; i < samples; i++ ) { - //Early out for percussion handlers - if ( mode == sm2Percussion ) { - GeneratePercussion( chip, output + i ); - continue; //Prevent some unitialized value bitching - } else if ( mode == sm3Percussion ) { - GeneratePercussion( chip, output + i * 2 ); - continue; //Prevent some unitialized value bitching - } - - //Do unsigned shift so we can shift out all bits but still stay in 10 bit range otherwise - Bit32s mod = (Bit32u)((old[0] + old[1])) >> feedback; - old[0] = old[1]; - old[1] = Op(0)->GetSample( mod ); - Bit32s sample; - Bit32s out0 = old[0]; - if ( mode == sm2AM || mode == sm3AM ) { - sample = out0 + Op(1)->GetSample( 0 ); - } else if ( mode == sm2FM || mode == sm3FM ) { - sample = Op(1)->GetSample( out0 ); - } else if ( mode == sm3FMFM ) { - Bits next = Op(1)->GetSample( out0 ); - next = Op(2)->GetSample( next ); - sample = Op(3)->GetSample( next ); - } else if ( mode == sm3AMFM ) { - sample = out0; - Bits next = Op(1)->GetSample( 0 ); - next = Op(2)->GetSample( next ); - sample += Op(3)->GetSample( next ); - } else if ( mode == sm3FMAM ) { - sample = Op(1)->GetSample( out0 ); - Bits next = Op(2)->GetSample( 0 ); - sample += Op(3)->GetSample( next ); - } else if ( mode == sm3AMAM ) { - sample = out0; - Bits next = Op(1)->GetSample( 0 ); - sample += Op(2)->GetSample( next ); - sample += Op(3)->GetSample( 0 ); - } - switch( mode ) { - case sm2AM: - case sm2FM: - if (chip->is_opl3) - { - output[ i * 2 + 0 ] += sample; - output[ i * 2 + 1 ] += sample; - } - else - output[ i ] += sample; - break; - case sm3AM: - case sm3FM: - case sm3FMFM: - case sm3AMFM: - case sm3FMAM: - case sm3AMAM: - output[ i * 2 + 0 ] += sample & maskLeft; - output[ i * 2 + 1 ] += sample & maskRight; - break; - case sm2Percussion: - case sm3Percussion: - break; - } - } - switch( mode ) { - case sm2AM: - case sm2FM: - case sm3AM: - case sm3FM: - return ( this + 1 ); - case sm3FMFM: - case sm3AMFM: - case sm3FMAM: - case sm3AMAM: - return( this + 2 ); - case sm2Percussion: - case sm3Percussion: - return( this + 3 ); - } - return 0; -} - -/* - Chip -*/ - -Chip::Chip() { - reg08 = 0; - reg04 = 0; - regBD = 0; - reg104 = 0; - opl3Active = 0; -} - -INLINE Bit32u Chip::ForwardNoise() { - noiseCounter += noiseAdd; - Bitu count = noiseCounter >> LFO_SH; - noiseCounter &= WAVE_MASK; - for ( ; count > 0; --count ) { - //Noise calculation from mame - noiseValue ^= ( 0x800302 ) & ( 0 - (noiseValue & 1 ) ); - noiseValue >>= 1; - } - return noiseValue; -} - -INLINE Bit32u Chip::ForwardLFO( Bit32u samples ) { - //Current vibrato value, runs 4x slower than tremolo - vibratoSign = ( VibratoTable[ vibratoIndex >> 2] ) >> 7; - vibratoShift = ( VibratoTable[ vibratoIndex >> 2] & 7) + vibratoStrength; - tremoloValue = TremoloTable[ tremoloIndex ] >> tremoloStrength; - - //Check hom many samples there can be done before the value changes - Bit32u todo = LFO_MAX - lfoCounter; - Bit32u count = (todo + lfoAdd - 1) / lfoAdd; - if ( count > samples ) { - count = samples; - lfoCounter += count * lfoAdd; - } else { - lfoCounter += count * lfoAdd; - lfoCounter &= (LFO_MAX - 1); - //Maximum of 7 vibrato value * 4 - vibratoIndex = ( vibratoIndex + 1 ) & 31; - //Clip tremolo to the the table size - if ( tremoloIndex + 1 < TREMOLO_TABLE ) - ++tremoloIndex; - else - tremoloIndex = 0; - } - return count; -} - - -void Chip::WriteBD( Bit8u val ) { - Bit8u change = regBD ^ val; - if ( !change ) - return; - regBD = val; - //TODO could do this with shift and xor? - vibratoStrength = (val & 0x40) ? 0x00 : 0x01; - tremoloStrength = (val & 0x80) ? 0x00 : 0x02; - if ( val & 0x20 ) { - //Drum was just enabled, make sure channel 6 has the right synth - if ( change & 0x20 ) { - // if ( opl3Active ) { - if ( is_opl3 ) { - chan[6].synthHandler = &Channel::BlockTemplate< sm3Percussion >; - } else { - chan[6].synthHandler = &Channel::BlockTemplate< sm2Percussion >; - } - } - //Bass Drum - if ( val & 0x10 ) { - chan[6].op[0].KeyOn( 0x2 ); - chan[6].op[1].KeyOn( 0x2 ); - } else { - chan[6].op[0].KeyOff( 0x2 ); - chan[6].op[1].KeyOff( 0x2 ); - } - //Hi-Hat - if ( val & 0x1 ) { - chan[7].op[0].KeyOn( 0x2 ); - } else { - chan[7].op[0].KeyOff( 0x2 ); - } - //Snare - if ( val & 0x8 ) { - chan[7].op[1].KeyOn( 0x2 ); - } else { - chan[7].op[1].KeyOff( 0x2 ); - } - //Tom-Tom - if ( val & 0x4 ) { - chan[8].op[0].KeyOn( 0x2 ); - } else { - chan[8].op[0].KeyOff( 0x2 ); - } - //Top Cymbal - if ( val & 0x2 ) { - chan[8].op[1].KeyOn( 0x2 ); - } else { - chan[8].op[1].KeyOff( 0x2 ); - } - //Toggle keyoffs when we turn off the percussion - } else if ( change & 0x20 ) { - //Trigger a reset to setup the original synth handler - chan[6].ResetC0( this ); - chan[6].op[0].KeyOff( 0x2 ); - chan[6].op[1].KeyOff( 0x2 ); - chan[7].op[0].KeyOff( 0x2 ); - chan[7].op[1].KeyOff( 0x2 ); - chan[8].op[0].KeyOff( 0x2 ); - chan[8].op[1].KeyOff( 0x2 ); - } -} - - -#define REGOP( _FUNC_ ) \ - index = ( ( reg >> 3) & 0x20 ) | ( reg & 0x1f ); \ - if ( OpOffsetTable[ index ] ) { \ - Operator* regOp = (Operator*)( ((char *)this ) + OpOffsetTable[ index ] ); \ - regOp->_FUNC_( this, val ); \ - } - -#define REGCHAN( _FUNC_ ) \ - index = ( ( reg >> 4) & 0x10 ) | ( reg & 0xf ); \ - if ( ChanOffsetTable[ index ] ) { \ - Channel* regChan = (Channel*)( ((char *)this ) + ChanOffsetTable[ index ] ); \ - regChan->_FUNC_( this, val ); \ - } - -void Chip::WriteReg( Bit32u reg, Bit8u val ) { - Bitu index; - switch ( (reg & 0xf0) >> 4 ) { - case 0x00 >> 4: - if ( reg == 0x01 ) { - waveFormMask = ( val & 0x20 ) ? 0x7 : 0x0; - } else if ( reg == 0x104 ) { - //Only detect changes in lowest 6 bits - if ( !((reg104 ^ val) & 0x3f) ) - return; - //Always keep the highest bit enabled, for checking > 0x80 - reg104 = 0x80 | ( val & 0x3f ); - } else if ( reg == 0x105 ) { - //MAME says the real opl3 doesn't reset anything on opl3 disable/enable till the next write in another register - if ( !((opl3Active ^ val) & 1 ) ) - return; - opl3Active = ( val & 1 ) ? 0xff : 0; - //Update the 0xc0 register for all channels to signal the switch to mono/stereo handlers - for ( int i = 0; i < 18;i++ ) { - chan[i].ResetC0( this ); - } - } else if ( reg == 0x08 ) { - reg08 = val; - } - case 0x10 >> 4: - break; - case 0x20 >> 4: - case 0x30 >> 4: - REGOP( Write20 ); - break; - case 0x40 >> 4: - case 0x50 >> 4: - REGOP( Write40 ); - break; - case 0x60 >> 4: - case 0x70 >> 4: - REGOP( Write60 ); - break; - case 0x80 >> 4: - case 0x90 >> 4: - REGOP( Write80 ); - break; - case 0xa0 >> 4: - REGCHAN( WriteA0 ); - break; - case 0xb0 >> 4: - if ( reg == 0xbd ) { - WriteBD( val ); - } else { - REGCHAN( WriteB0 ); - } - break; - case 0xc0 >> 4: - REGCHAN( WriteC0 ); - case 0xd0 >> 4: - break; - case 0xe0 >> 4: - case 0xf0 >> 4: - REGOP( WriteE0 ); - break; - } -} - - -Bit32u Chip::WriteAddr( Bit32u port, Bit8u val ) { - switch ( port & 3 ) { - case 0: - return val; - case 2: - if ( opl3Active || (val == 0x05) ) - return 0x100 | val; - else - return val; - } - return 0; -} - -void Chip::GenerateBlock2( Bitu total, Bit32s* output ) { - while ( total > 0 ) { - Bit32u samples = ForwardLFO( total ); - memset(output, 0, sizeof(Bit32s) * samples); - int count = 0; - for( Channel* ch = chan; ch < chan + 9; ) { - count++; - ch = (ch->*(ch->synthHandler))( this, samples, output ); - } - total -= samples; - output += samples; - } -} - -void Chip::GenerateBlock3( Bitu total, Bit32s* output ) { - while ( total > 0 ) { - Bit32u samples = ForwardLFO( total ); - memset(output, 0, sizeof(Bit32s) * samples *2); - int count = 0; - for( Channel* ch = chan; ch < chan + 18; ) { - count++; - ch = (ch->*(ch->synthHandler))( this, samples, output ); - } - total -= samples; - output += samples * 2; - } -} - -void Chip::Setup( Bit32u rate, int chip_is_opl3 ) { - double original = OPLRATE; -// double original = rate; - double scale = original / (double)rate; - - is_opl3 = chip_is_opl3; - - //Noise counter is run at the same precision as general waves - noiseAdd = (Bit32u)( 0.5 + scale * ( 1 << LFO_SH ) ); - noiseCounter = 0; - noiseValue = 1; //Make sure it triggers the noise xor the first time - //The low frequency oscillation counter - //Every time his overflows vibrato and tremoloindex are increased - lfoAdd = (Bit32u)( 0.5 + scale * ( 1 << LFO_SH ) ); - lfoCounter = 0; - vibratoIndex = 0; - tremoloIndex = 0; - - //With higher octave this gets shifted up - //-1 since the freqCreateTable = *2 -#ifdef WAVE_PRECISION - double freqScale = ( 1 << 7 ) * scale * ( 1 << ( WAVE_SH - 1 - 10)); - for ( int i = 0; i < 16; i++ ) { - freqMul[i] = (Bit32u)( 0.5 + freqScale * FreqCreateTable[ i ] ); - } -#else - Bit32u freqScale = (Bit32u)( 0.5 + scale * ( 1 << ( WAVE_SH - 1 - 10))); - for ( int i = 0; i < 16; i++ ) { - freqMul[i] = freqScale * FreqCreateTable[ i ]; - } -#endif - - //-3 since the real envelope takes 8 steps to reach the single value we supply - for ( Bit8u i = 0; i < 76; i++ ) { - Bit8u index, shift; - EnvelopeSelect( i, index, shift ); - linearRates[i] = (Bit32u)( scale * (EnvelopeIncreaseTable[ index ] << ( RATE_SH + ENV_EXTRA - shift - 3 ))); - } - //Generate the best matching attack rate - for ( Bit8u i = 0; i < 62; i++ ) { - Bit8u index, shift; - EnvelopeSelect( i, index, shift ); - //Original amount of samples the attack would take - Bit32s original = (Bit32u)( (AttackSamplesTable[ index ] << shift) / scale); - - Bit32s guessAdd = (Bit32u)( scale * (EnvelopeIncreaseTable[ index ] << ( RATE_SH - shift - 3 ))); - Bit32s bestAdd = guessAdd; - Bit32u bestDiff = 1 << 30; - for( Bit32u passes = 0; passes < 16; passes ++ ) { - Bit32s volume = ENV_MAX; - Bit32s samples = 0; - Bit32u count = 0; - while ( volume > 0 && samples < original * 2 ) { - count += guessAdd; - Bit32s change = count >> RATE_SH; - count &= RATE_MASK; - if ( GCC_UNLIKELY(change) ) { // less than 1 % - volume += ( ~volume * change ) >> 3; - } - samples++; - - } - Bit32s diff = original - samples; - Bit32u lDiff = labs( diff ); - //Init last on first pass - if ( lDiff < bestDiff ) { - bestDiff = lDiff; - bestAdd = guessAdd; - if ( !bestDiff ) - break; - } - //Below our target - if ( diff < 0 ) { - //Better than the last time - Bit32s mul = ((original - diff) << 12) / original; - guessAdd = ((guessAdd * mul) >> 12); - guessAdd++; - } else if ( diff > 0 ) { - Bit32s mul = ((original - diff) << 12) / original; - guessAdd = (guessAdd * mul) >> 12; - guessAdd--; - } - } - attackRates[i] = bestAdd; - } - for ( Bit8u i = 62; i < 76; i++ ) { - //This should provide instant volume maximizing - attackRates[i] = 8 << RATE_SH; - } - //Setup the channels with the correct four op flags - //Channels are accessed through a table so they appear linear here - chan[ 0].fourMask = 0x00 | ( 1 << 0 ); - chan[ 1].fourMask = 0x80 | ( 1 << 0 ); - chan[ 2].fourMask = 0x00 | ( 1 << 1 ); - chan[ 3].fourMask = 0x80 | ( 1 << 1 ); - chan[ 4].fourMask = 0x00 | ( 1 << 2 ); - chan[ 5].fourMask = 0x80 | ( 1 << 2 ); - - chan[ 9].fourMask = 0x00 | ( 1 << 3 ); - chan[10].fourMask = 0x80 | ( 1 << 3 ); - chan[11].fourMask = 0x00 | ( 1 << 4 ); - chan[12].fourMask = 0x80 | ( 1 << 4 ); - chan[13].fourMask = 0x00 | ( 1 << 5 ); - chan[14].fourMask = 0x80 | ( 1 << 5 ); - - //mark the percussion channels - chan[ 6].fourMask = 0x40; - chan[ 7].fourMask = 0x40; - chan[ 8].fourMask = 0x40; - - //Clear Everything in opl3 mode - WriteReg( 0x105, 0x1 ); - for ( int i = 0; i < 512; i++ ) { - if ( i == 0x105 ) - continue; - WriteReg( i, 0xff ); - WriteReg( i, 0x0 ); - } - WriteReg( 0x105, 0x0 ); - //Clear everything in opl2 mode - for ( int i = 0; i < 255; i++ ) { - WriteReg( i, 0xff ); - WriteReg( i, 0x0 ); - } -} - -static bool doneTables = false; -void InitTables( void ) { - if ( doneTables ) - return; - doneTables = true; -#if ( DBOPL_WAVE == WAVE_HANDLER ) || ( DBOPL_WAVE == WAVE_TABLELOG ) - //Exponential volume table, same as the real adlib - for ( int i = 0; i < 256; i++ ) { - //Save them in reverse - ExpTable[i] = (int)( 0.5 + ( pow(2.0, ( 255 - i) * ( 1.0 /256 ) )-1) * 1024 ); - ExpTable[i] += 1024; //or remove the -1 oh well :) - //Preshift to the left once so the final volume can shift to the right - ExpTable[i] *= 2; - } -#endif -#if ( DBOPL_WAVE == WAVE_HANDLER ) - //Add 0.5 for the trunc rounding of the integer cast - //Do a PI sinetable instead of the original 0.5 PI - for ( int i = 0; i < 512; i++ ) { - SinTable[i] = (Bit16s)( 0.5 - log10( sin( (i + 0.5) * (PI / 512.0) ) ) / log10(2.0)*256 ); - } -#endif -#if ( DBOPL_WAVE == WAVE_TABLEMUL ) - //Multiplication based tables - for ( int i = 0; i < 384; i++ ) { - int s = i * 8; - //TODO maybe keep some of the precision errors of the original table? - double val = ( 0.5 + ( pow(2.0, -1.0 + ( 255 - s) * ( 1.0 /256 ) )) * ( 1 << MUL_SH )); - MulTable[i] = (Bit16u)(val); - } - - //Sine Wave Base - for ( int i = 0; i < 512; i++ ) { - WaveTable[ 0x0200 + i ] = (Bit16s)(sin( (i + 0.5) * (PI / 512.0) ) * 4084); - WaveTable[ 0x0000 + i ] = -WaveTable[ 0x200 + i ]; - } - //Exponential wave - for ( int i = 0; i < 256; i++ ) { - WaveTable[ 0x700 + i ] = (Bit16s)( 0.5 + ( pow(2.0, -1.0 + ( 255 - i * 8) * ( 1.0 /256 ) ) ) * 4085 ); - WaveTable[ 0x6ff - i ] = -WaveTable[ 0x700 + i ]; - } -#endif -#if ( DBOPL_WAVE == WAVE_TABLELOG ) - //Sine Wave Base - for ( int i = 0; i < 512; i++ ) { - WaveTable[ 0x0200 + i ] = (Bit16s)( 0.5 - log10( sin( (i + 0.5) * (PI / 512.0) ) ) / log10(2.0)*256 ); - WaveTable[ 0x0000 + i ] = ((Bit16s)0x8000) | WaveTable[ 0x200 + i]; - } - //Exponential wave - for ( int i = 0; i < 256; i++ ) { - WaveTable[ 0x700 + i ] = i * 8; - WaveTable[ 0x6ff - i ] = ((Bit16s)0x8000) | i * 8; - } -#endif - - // | |//\\|____|WAV7|//__|/\ |____|/\/\| - // |\\//| | |WAV7| | \/| | | - // |06 |0126|27 |7 |3 |4 |4 5 |5 | - -#if (( DBOPL_WAVE == WAVE_TABLELOG ) || ( DBOPL_WAVE == WAVE_TABLEMUL )) - for ( int i = 0; i < 256; i++ ) { - //Fill silence gaps - WaveTable[ 0x400 + i ] = WaveTable[0]; - WaveTable[ 0x500 + i ] = WaveTable[0]; - WaveTable[ 0x900 + i ] = WaveTable[0]; - WaveTable[ 0xc00 + i ] = WaveTable[0]; - WaveTable[ 0xd00 + i ] = WaveTable[0]; - //Replicate sines in other pieces - WaveTable[ 0x800 + i ] = WaveTable[ 0x200 + i ]; - //double speed sines - WaveTable[ 0xa00 + i ] = WaveTable[ 0x200 + i * 2 ]; - WaveTable[ 0xb00 + i ] = WaveTable[ 0x000 + i * 2 ]; - WaveTable[ 0xe00 + i ] = WaveTable[ 0x200 + i * 2 ]; - WaveTable[ 0xf00 + i ] = WaveTable[ 0x200 + i * 2 ]; - } -#endif - - //Create the ksl table - for ( int oct = 0; oct < 8; oct++ ) { - int base = oct * 8; - for ( int i = 0; i < 16; i++ ) { - int val = base - KslCreateTable[i]; - if ( val < 0 ) - val = 0; - //*4 for the final range to match attenuation range - KslTable[ oct * 16 + i ] = val * 4; - } - } - //Create the Tremolo table, just increase and decrease a triangle wave - for ( Bit8u i = 0; i < TREMOLO_TABLE / 2; i++ ) { - Bit8u val = i << ENV_EXTRA; - TremoloTable[i] = val; - TremoloTable[TREMOLO_TABLE - 1 - i] = val; - } - //Create a table with offsets of the channels from the start of the chip - DBOPL::Chip* chip = 0; - for ( Bitu i = 0; i < 32; i++ ) { - Bitu index = i & 0xf; - if ( index >= 9 ) { - ChanOffsetTable[i] = 0; - continue; - } - //Make sure the four op channels follow eachother - if ( index < 6 ) { - index = (index % 3) * 2 + ( index / 3 ); - } - //Add back the bits for highest ones - if ( i >= 16 ) - index += 9; - intptr_t blah = reinterpret_cast( &(chip->chan[ index ]) ); - ChanOffsetTable[i] = blah; - } - //Same for operators - for ( Bitu i = 0; i < 64; i++ ) { - if ( i % 8 >= 6 || ( (i / 8) % 4 == 3 ) ) { - OpOffsetTable[i] = 0; - continue; - } - Bitu chNum = (i / 8) * 3 + (i % 8) % 3; - //Make sure we use 16 and up for the 2nd range to match the chanoffset gap - if ( chNum >= 12 ) - chNum += 16 - 12; - Bitu opNum = ( i % 8 ) / 3; - DBOPL::Channel* chan = 0; - intptr_t blah = reinterpret_cast( &(chan->op[opNum]) ); - OpOffsetTable[i] = ChanOffsetTable[ chNum ] + blah; - } -#if 0 - //Stupid checks if table's are correct - for ( Bitu i = 0; i < 18; i++ ) { - Bit32u find = (Bit16u)( &(chip->chan[ i ]) ); - for ( Bitu c = 0; c < 32; c++ ) { - if ( ChanOffsetTable[c] == find ) { - find = 0; - break; - } - } - if ( find ) { - find = find; - } - } - for ( Bitu i = 0; i < 36; i++ ) { - Bit32u find = (Bit16u)( &(chip->chan[ i / 2 ].op[i % 2]) ); - for ( Bitu c = 0; c < 64; c++ ) { - if ( OpOffsetTable[c] == find ) { - find = 0; - break; - } - } - if ( find ) { - find = find; - } - } -#endif -} - -/*Bit32u Handler::WriteAddr( Bit32u port, Bit8u val ) { - return chip.WriteAddr( port, val ); - -} -void Handler::WriteReg( Bit32u addr, Bit8u val ) { - chip.WriteReg( addr, val ); -} - -void Handler::Generate( MixerChannel* chan, Bitu samples ) { - Bit32s buffer[ 512 * 2 ]; - if ( GCC_UNLIKELY(samples > 512) ) - samples = 512; - if ( !chip.opl3Active ) { - chip.GenerateBlock2( samples, buffer ); - chan->AddSamples_m32( samples, buffer ); - } else { - chip.GenerateBlock3( samples, buffer ); - chan->AddSamples_s32( samples, buffer ); - } -} - -void Handler::Init( Bitu rate ) { - InitTables(); - chip.Setup( rate ); -}*/ - - -}; //Namespace DBOPL - diff --git a/src/sound/dbopl.h b/src/sound/dbopl.h deleted file mode 100644 index 7507dd1a4..000000000 --- a/src/sound/dbopl.h +++ /dev/null @@ -1,259 +0,0 @@ -/* Copyright holders: The DOSBox Team - see COPYING for more details -*/ - -//#include "adlib.h" -//#include "dosbox.h" -#include -typedef signed int Bits; -typedef unsigned int Bitu; -typedef int8_t Bit8s; -typedef uint8_t Bit8u; -typedef int16_t Bit16s; -typedef uint16_t Bit16u; -typedef int32_t Bit32s; -typedef uint32_t Bit32u; - -#define INLINE inline - -#define GCC_UNLIKELY(x) (x) - -//Use 8 handlers based on a small logatirmic wavetabe and an exponential table for volume -#define WAVE_HANDLER 10 -//Use a logarithmic wavetable with an exponential table for volume -#define WAVE_TABLELOG 11 -//Use a linear wavetable with a multiply table for volume -#define WAVE_TABLEMUL 12 - -//Select the type of wave generator routine -#define DBOPL_WAVE WAVE_TABLEMUL - -namespace DBOPL { - -struct Chip; -struct Operator; -struct Channel; - -#if (DBOPL_WAVE == WAVE_HANDLER) -typedef Bits ( DB_FASTCALL *WaveHandler) ( Bitu i, Bitu volume ); -#endif - -typedef Bits ( DBOPL::Operator::*VolumeHandler) ( ); -typedef Channel* ( DBOPL::Channel::*SynthHandler) ( Chip* chip, Bit32u samples, Bit32s* output ); - -//Different synth modes that can generate blocks of data -typedef enum { - sm2AM, - sm2FM, - sm3AM, - sm3FM, - sm4Start, - sm3FMFM, - sm3AMFM, - sm3FMAM, - sm3AMAM, - sm6Start, - sm2Percussion, - sm3Percussion, -} SynthMode; - -//Shifts for the values contained in chandata variable -enum { - SHIFT_KSLBASE = 16, - SHIFT_KEYCODE = 24, -}; - -struct Operator { -public: - //Masks for operator 20 values - enum { - MASK_KSR = 0x10, - MASK_SUSTAIN = 0x20, - MASK_VIBRATO = 0x40, - MASK_TREMOLO = 0x80, - }; - - typedef enum { - OFF, - RELEASE, - SUSTAIN, - DECAY, - ATTACK, - } State; - - VolumeHandler volHandler; - -#if (DBOPL_WAVE == WAVE_HANDLER) - WaveHandler waveHandler; //Routine that generate a wave -#else - Bit16s* waveBase; - Bit32u waveMask; - Bit32u waveStart; -#endif - Bit32u waveIndex; //WAVE_BITS shifted counter of the frequency index - Bit32u waveAdd; //The base frequency without vibrato - Bit32u waveCurrent; //waveAdd + vibratao - - Bit32u chanData; //Frequency/octave and derived data coming from whatever channel controls this - Bit32u freqMul; //Scale channel frequency with this, TODO maybe remove? - Bit32u vibrato; //Scaled up vibrato strength - Bit32s sustainLevel; //When stopping at sustain level stop here - Bit32s totalLevel; //totalLevel is added to every generated volume - Bit32u currentLevel; //totalLevel + tremolo - Bit32s volume; //The currently active volume - - Bit32u attackAdd; //Timers for the different states of the envelope - Bit32u decayAdd; - Bit32u releaseAdd; - Bit32u rateIndex; //Current position of the evenlope - - Bit8u rateZero; //Bits for the different states of the envelope having no changes - Bit8u keyOn; //Bitmask of different values that can generate keyon - //Registers, also used to check for changes - Bit8u reg20, reg40, reg60, reg80, regE0; - //Active part of the envelope we're in - Bit8u state; - //0xff when tremolo is enabled - Bit8u tremoloMask; - //Strength of the vibrato - Bit8u vibStrength; - //Keep track of the calculated KSR so we can check for changes - Bit8u ksr; -private: - void SetState( Bit8u s ); - void UpdateAttack( const Chip* chip ); - void UpdateRelease( const Chip* chip ); - void UpdateDecay( const Chip* chip ); -public: - void UpdateAttenuation(); - void UpdateRates( const Chip* chip ); - void UpdateFrequency( ); - - void Write20( const Chip* chip, Bit8u val ); - void Write40( const Chip* chip, Bit8u val ); - void Write60( const Chip* chip, Bit8u val ); - void Write80( const Chip* chip, Bit8u val ); - void WriteE0( const Chip* chip, Bit8u val ); - - bool Silent() const; - void Prepare( const Chip* chip ); - - void KeyOn( Bit8u mask); - void KeyOff( Bit8u mask); - - template< State state> - Bits TemplateVolume( ); - - Bit32s RateForward( Bit32u add ); - Bitu ForwardWave(); - Bitu ForwardVolume(); - - Bits GetSample( Bits modulation ); - Bits GetWave( Bitu index, Bitu vol ); -public: - Operator(); -}; - -struct Channel { - Operator op[2]; - inline Operator* Op( Bitu index ) { - return &( ( this + (index >> 1) )->op[ index & 1 ]); - } - SynthHandler synthHandler; - Bit32u chanData; //Frequency/octave and derived values - Bit32s old[2]; //Old data for feedback - - Bit8u feedback; //Feedback shift - Bit8u regB0; //Register values to check for changes - Bit8u regC0; - //This should correspond with reg104, bit 6 indicates a Percussion channel, bit 7 indicates a silent channel - Bit8u fourMask; - Bit8s maskLeft; //Sign extended values for both channel's panning - Bit8s maskRight; - - //Forward the channel data to the operators of the channel - void SetChanData( const Chip* chip, Bit32u data ); - //Change in the chandata, check for new values and if we have to forward to operators - void UpdateFrequency( const Chip* chip, Bit8u fourOp ); - void WriteA0( const Chip* chip, Bit8u val ); - void WriteB0( const Chip* chip, Bit8u val ); - void WriteC0( const Chip* chip, Bit8u val ); - void ResetC0( const Chip* chip ); - - //call this for the first channel - template< bool opl3Mode > - void GeneratePercussion( Chip* chip, Bit32s* output ); - - //Generate blocks of data in specific modes - template - Channel* BlockTemplate( Chip* chip, Bit32u samples, Bit32s* output ); - Channel(); -}; - -struct Chip { - //This is used as the base counter for vibrato and tremolo - Bit32u lfoCounter; - Bit32u lfoAdd; - - - Bit32u noiseCounter; - Bit32u noiseAdd; - Bit32u noiseValue; - - //Frequency scales for the different multiplications - Bit32u freqMul[16]; - //Rates for decay and release for rate of this chip - Bit32u linearRates[76]; - //Best match attack rates for the rate of this chip - Bit32u attackRates[76]; - - //18 channels with 2 operators each - Channel chan[18]; - - Bit8u reg104; - Bit8u reg08; - Bit8u reg04; - Bit8u regBD; - Bit8u vibratoIndex; - Bit8u tremoloIndex; - Bit8s vibratoSign; - Bit8u vibratoShift; - Bit8u tremoloValue; - Bit8u vibratoStrength; - Bit8u tremoloStrength; - //Mask for allowed wave forms - Bit8u waveFormMask; - //0 or -1 when enabled - Bit8s opl3Active; - - int is_opl3; - - //Return the maximum amount of samples before and LFO change - Bit32u ForwardLFO( Bit32u samples ); - Bit32u ForwardNoise(); - - void WriteBD( Bit8u val ); - void WriteReg(Bit32u reg, Bit8u val ); - - Bit32u WriteAddr( Bit32u port, Bit8u val ); - - void GenerateBlock2( Bitu samples, Bit32s* output ); - void GenerateBlock3( Bitu samples, Bit32s* output ); - - void Generate( Bit32u samples ); - void Setup( Bit32u r, int chip_is_opl3 ); - - Chip(); -}; - -/*struct Handler : public Adlib::Handler { - DBOPL::Chip chip; - virtual Bit32u WriteAddr( Bit32u port, Bit8u val ); - virtual void WriteReg( Bit32u addr, Bit8u val ); - virtual void Generate( MixerChannel* chan, Bitu samples ); - virtual void Init( Bitu rate ); -};*/ - -void InitTables( void ); - -}; //Namespace diff --git a/src/sound/nukedopl.cpp b/src/sound/nukedopl.c similarity index 94% rename from src/sound/nukedopl.cpp rename to src/sound/nukedopl.c index 0039a63bc..a2bc192c5 100644 --- a/src/sound/nukedopl.cpp +++ b/src/sound/nukedopl.c @@ -179,7 +179,7 @@ static const Bit8u ch_slot[18] = { // typedef Bit16s(*envelope_sinfunc)(Bit16u phase, Bit16u envelope); -typedef void(*envelope_genfunc)(opl3_slot *slott); +typedef void(*envelope_genfunc)(struct opl3_slot *slott); static Bit16s OPL3_EnvelopeCalcExp(Bit32u level) { @@ -346,7 +346,7 @@ enum envelope_gen_num envelope_gen_num_release = 3 }; -static void OPL3_EnvelopeUpdateKSL(opl3_slot *slot) +static void OPL3_EnvelopeUpdateKSL(struct opl3_slot *slot) { Bit16s ksl = (kslrom[slot->channel->f_num >> 6] << 2) - ((0x08 - slot->channel->block) << 5); @@ -357,7 +357,7 @@ static void OPL3_EnvelopeUpdateKSL(opl3_slot *slot) slot->eg_ksl = (Bit8u)ksl; } -static void OPL3_EnvelopeCalc(opl3_slot *slot) +static void OPL3_EnvelopeCalc(struct opl3_slot *slot) { Bit8u nonzero; Bit8u rate; @@ -504,12 +504,12 @@ static void OPL3_EnvelopeCalc(opl3_slot *slot) } } -static void OPL3_EnvelopeKeyOn(opl3_slot *slot, Bit8u type) +static void OPL3_EnvelopeKeyOn(struct opl3_slot *slot, Bit8u type) { slot->key |= type; } -static void OPL3_EnvelopeKeyOff(opl3_slot *slot, Bit8u type) +static void OPL3_EnvelopeKeyOff(struct opl3_slot *slot, Bit8u type) { slot->key &= ~type; } @@ -518,9 +518,9 @@ static void OPL3_EnvelopeKeyOff(opl3_slot *slot, Bit8u type) // Phase Generator // -static void OPL3_PhaseGenerate(opl3_slot *slot) +static void OPL3_PhaseGenerate(struct opl3_slot *slot) { - opl3_chip *chip; + struct opl3_chip *chip; Bit16u f_num; Bit32u basefreq; Bit8u rm_xor, n_bit; @@ -612,7 +612,7 @@ static void OPL3_PhaseGenerate(opl3_slot *slot) // Slot // -static void OPL3_SlotWrite20(opl3_slot *slot, Bit8u data) +static void OPL3_SlotWrite20(struct opl3_slot *slot, Bit8u data) { if ((data >> 7) & 0x01) { @@ -628,20 +628,20 @@ static void OPL3_SlotWrite20(opl3_slot *slot, Bit8u data) slot->reg_mult = data & 0x0f; } -static void OPL3_SlotWrite40(opl3_slot *slot, Bit8u data) +static void OPL3_SlotWrite40(struct opl3_slot *slot, Bit8u data) { slot->reg_ksl = (data >> 6) & 0x03; slot->reg_tl = data & 0x3f; OPL3_EnvelopeUpdateKSL(slot); } -static void OPL3_SlotWrite60(opl3_slot *slot, Bit8u data) +static void OPL3_SlotWrite60(struct opl3_slot *slot, Bit8u data) { slot->reg_ar = (data >> 4) & 0x0f; slot->reg_dr = data & 0x0f; } -static void OPL3_SlotWrite80(opl3_slot *slot, Bit8u data) +static void OPL3_SlotWrite80(struct opl3_slot *slot, Bit8u data) { slot->reg_sl = (data >> 4) & 0x0f; if (slot->reg_sl == 0x0f) @@ -651,7 +651,7 @@ static void OPL3_SlotWrite80(opl3_slot *slot, Bit8u data) slot->reg_rr = data & 0x0f; } -static void OPL3_SlotWriteE0(opl3_slot *slot, Bit8u data) +static void OPL3_SlotWriteE0(struct opl3_slot *slot, Bit8u data) { slot->reg_wf = data & 0x07; if (slot->chip->newm == 0x00) @@ -660,12 +660,12 @@ static void OPL3_SlotWriteE0(opl3_slot *slot, Bit8u data) } } -static void OPL3_SlotGenerate(opl3_slot *slot) +static void OPL3_SlotGenerate(struct opl3_slot *slot) { slot->out = envelope_sin[slot->reg_wf](slot->pg_phase_out + *slot->mod, slot->eg_out); } -static void OPL3_SlotCalcFB(opl3_slot *slot) +static void OPL3_SlotCalcFB(struct opl3_slot *slot) { if (slot->channel->fb != 0x00) { @@ -682,13 +682,13 @@ static void OPL3_SlotCalcFB(opl3_slot *slot) // Channel // -static void OPL3_ChannelSetupAlg(opl3_channel *channel); +static void OPL3_ChannelSetupAlg(struct opl3_channel *channel); -static void OPL3_ChannelUpdateRhythm(opl3_chip *chip, Bit8u data) +static void OPL3_ChannelUpdateRhythm(struct opl3_chip *chip, Bit8u data) { - opl3_channel *channel6; - opl3_channel *channel7; - opl3_channel *channel8; + struct opl3_channel *channel6; + struct opl3_channel *channel7; + struct opl3_channel *channel8; Bit8u chnum; chip->rhy = data & 0x3f; @@ -776,7 +776,7 @@ static void OPL3_ChannelUpdateRhythm(opl3_chip *chip, Bit8u data) } } -static void OPL3_ChannelWriteA0(opl3_channel *channel, Bit8u data) +static void OPL3_ChannelWriteA0(struct opl3_channel *channel, Bit8u data) { if (channel->chip->newm && channel->chtype == ch_4op2) { @@ -796,7 +796,7 @@ static void OPL3_ChannelWriteA0(opl3_channel *channel, Bit8u data) } } -static void OPL3_ChannelWriteB0(opl3_channel *channel, Bit8u data) +static void OPL3_ChannelWriteB0(struct opl3_channel *channel, Bit8u data) { if (channel->chip->newm && channel->chtype == ch_4op2) { @@ -818,7 +818,7 @@ static void OPL3_ChannelWriteB0(opl3_channel *channel, Bit8u data) } } -static void OPL3_ChannelSetupAlg(opl3_channel *channel) +static void OPL3_ChannelSetupAlg(struct opl3_channel *channel) { if (channel->chtype == ch_drum) { @@ -919,7 +919,7 @@ static void OPL3_ChannelSetupAlg(opl3_channel *channel) } } -static void OPL3_ChannelWriteC0(opl3_channel *channel, Bit8u data) +static void OPL3_ChannelWriteC0(struct opl3_channel *channel, Bit8u data) { channel->fb = (data & 0x0e) >> 1; channel->con = data & 0x01; @@ -958,7 +958,7 @@ static void OPL3_ChannelWriteC0(opl3_channel *channel, Bit8u data) } } -static void OPL3_ChannelKeyOn(opl3_channel *channel) +static void OPL3_ChannelKeyOn(struct opl3_channel *channel) { if (channel->chip->newm) { @@ -982,7 +982,7 @@ static void OPL3_ChannelKeyOn(opl3_channel *channel) } } -static void OPL3_ChannelKeyOff(opl3_channel *channel) +static void OPL3_ChannelKeyOff(struct opl3_channel *channel) { if (channel->chip->newm) { @@ -1006,7 +1006,7 @@ static void OPL3_ChannelKeyOff(opl3_channel *channel) } } -static void OPL3_ChannelSet4Op(opl3_chip *chip, Bit8u data) +static void OPL3_ChannelSet4Op(struct opl3_chip *chip, Bit8u data) { Bit8u bit; Bit8u chnum; @@ -1043,7 +1043,7 @@ static Bit16s OPL3_ClipSample(Bit32s sample) return (Bit16s)sample; } -void OPL3_Generate(opl3_chip *chip, Bit16s *buf) +void OPL3_Generate(struct opl3_chip *chip, Bit16s *buf) { Bit8u ii; Bit8u jj; @@ -1175,7 +1175,7 @@ void OPL3_Generate(opl3_chip *chip, Bit16s *buf) chip->writebuf_samplecnt++; } -void OPL3_GenerateResampled(opl3_chip *chip, Bit16s *buf) +void OPL3_GenerateResampled(struct opl3_chip *chip, Bit32s *buf) { while (chip->samplecnt >= chip->rateratio) { @@ -1184,19 +1184,19 @@ void OPL3_GenerateResampled(opl3_chip *chip, Bit16s *buf) OPL3_Generate(chip, chip->samples); chip->samplecnt -= chip->rateratio; } - buf[0] = (Bit16s)((chip->oldsamples[0] * (chip->rateratio - chip->samplecnt) + buf[0] = (Bit32s)((chip->oldsamples[0] * (chip->rateratio - chip->samplecnt) + chip->samples[0] * chip->samplecnt) / chip->rateratio); - buf[1] = (Bit16s)((chip->oldsamples[1] * (chip->rateratio - chip->samplecnt) + buf[1] = (Bit32s)((chip->oldsamples[1] * (chip->rateratio - chip->samplecnt) + chip->samples[1] * chip->samplecnt) / chip->rateratio); chip->samplecnt += 1 << RSM_FRAC; } -void OPL3_Reset(opl3_chip *chip, Bit32u samplerate) +void OPL3_Reset(struct opl3_chip *chip, Bit32u samplerate) { Bit8u slotnum; Bit8u channum; - memset(chip, 0, sizeof(opl3_chip)); + memset(chip, 0, sizeof(struct opl3_chip)); for (slotnum = 0; slotnum < 36; slotnum++) { chip->slot[slotnum].chip = chip; @@ -1238,7 +1238,7 @@ void OPL3_Reset(opl3_chip *chip, Bit32u samplerate) chip->vibshift = 1; } -Bit32u OPL3_WriteAddr(opl3_chip *chip, Bit32u port, Bit8u val) +Bit32u OPL3_WriteAddr(struct opl3_chip *chip, Bit32u port, Bit8u val) { Bit16u addr; addr = val; @@ -1248,7 +1248,7 @@ Bit32u OPL3_WriteAddr(opl3_chip *chip, Bit32u port, Bit8u val) return addr; } -void OPL3_WriteReg(opl3_chip *chip, Bit16u reg, Bit8u v) +void OPL3_WriteReg(struct opl3_chip *chip, Bit16u reg, Bit8u v) { Bit8u high = (reg >> 8) & 0x01; Bit8u regm = reg & 0xff; @@ -1347,7 +1347,7 @@ void OPL3_WriteReg(opl3_chip *chip, Bit16u reg, Bit8u v) } } -void OPL3_WriteRegBuffered(opl3_chip *chip, Bit16u reg, Bit8u v) +void OPL3_WriteRegBuffered(struct opl3_chip *chip, Bit16u reg, Bit8u v) { Bit64u time1, time2; @@ -1375,7 +1375,7 @@ void OPL3_WriteRegBuffered(opl3_chip *chip, Bit16u reg, Bit8u v) chip->writebuf_last = (chip->writebuf_last + 1) % OPL_WRITEBUF_SIZE; } -void OPL3_GenerateStream(opl3_chip *chip, Bit16s *sndptr, Bit32u numsamples) +void OPL3_GenerateStream(struct opl3_chip *chip, Bit32s *sndptr, Bit32u numsamples) { Bit32u i; diff --git a/src/sound/nukedopl.h b/src/sound/nukedopl.h index 9570298fb..6b3f09228 100644 --- a/src/sound/nukedopl.h +++ b/src/sound/nukedopl.h @@ -46,11 +46,12 @@ typedef uint64_t Bit64u; struct opl3_slot; struct opl3_channel; +struct opl3_writebuf; struct opl3_chip; struct opl3_slot { - opl3_channel *channel; - opl3_chip *chip; + struct opl3_channel *channel; + struct opl3_chip *chip; Bit16s out; Bit16s fbmod; Bit16s *mod; @@ -81,9 +82,9 @@ struct opl3_slot { }; struct opl3_channel { - opl3_slot *slots[2]; - opl3_channel *pair; - opl3_chip *chip; + struct opl3_slot *slots[2]; + struct opl3_channel *pair; + struct opl3_chip *chip; Bit16s *out[4]; Bit8u chtype; Bit16u f_num; @@ -103,8 +104,8 @@ struct opl3_writebuf { }; struct opl3_chip { - opl3_channel channel[18]; - opl3_slot slot[36]; + struct opl3_channel channel[18]; + struct opl3_slot slot[36]; Bit16u timer; Bit64u eg_timer; Bit8u eg_timerrem; @@ -137,14 +138,14 @@ struct opl3_chip { Bit32u writebuf_cur; Bit32u writebuf_last; Bit64u writebuf_lasttime; - opl3_writebuf writebuf[OPL_WRITEBUF_SIZE]; + struct opl3_writebuf writebuf[OPL_WRITEBUF_SIZE]; }; -void OPL3_Generate(opl3_chip *chip, Bit16s *buf); -void OPL3_GenerateResampled(opl3_chip *chip, Bit16s *buf); -void OPL3_Reset(opl3_chip *chip, Bit32u samplerate); -Bit32u OPL3_WriteAddr(opl3_chip *chip, Bit32u port, Bit8u val); -void OPL3_WriteReg(opl3_chip *chip, Bit16u reg, Bit8u v); -void OPL3_WriteRegBuffered(opl3_chip *chip, Bit16u reg, Bit8u v); -void OPL3_GenerateStream(opl3_chip *chip, Bit16s *sndptr, Bit32u numsamples); +void OPL3_Generate(struct opl3_chip *chip, Bit16s *buf); +void OPL3_GenerateResampled(struct opl3_chip *chip, Bit32s *buf); +void OPL3_Reset(struct opl3_chip *chip, Bit32u samplerate); +Bit32u OPL3_WriteAddr(struct opl3_chip *chip, Bit32u port, Bit8u val); +void OPL3_WriteReg(struct opl3_chip *chip, Bit16u reg, Bit8u v); +void OPL3_WriteRegBuffered(struct opl3_chip *chip, Bit16u reg, Bit8u v); +void OPL3_GenerateStream(struct opl3_chip *chip, Bit32s *sndptr, Bit32u numsamples); #endif diff --git a/src/sound/snd_dbopl.cc b/src/sound/snd_dbopl.cc deleted file mode 100644 index 2ccc9e56c..000000000 --- a/src/sound/snd_dbopl.cc +++ /dev/null @@ -1,187 +0,0 @@ -/* Copyright holders: Sarah Walker, SA1988 - see COPYING for more details -*/ -#include "dbopl.h" -#include "nukedopl.h" -#include "sound.h" -#include "snd_dbopl.h" - - -int opl_type = 0; - - -static struct -{ - DBOPL::Chip chip; - opl3_chip opl3chip; - int addr; - int timer[2]; - uint8_t timer_ctrl; - uint8_t status_mask; - uint8_t status; - int is_opl3; - - void (*timer_callback)(void *param, int timer, uint64_t period); - void *timer_param; -} opl[2]; - -enum -{ - STATUS_TIMER_1 = 0x40, - STATUS_TIMER_2 = 0x20, - STATUS_TIMER_ALL = 0x80 -}; - -enum -{ - CTRL_IRQ_RESET = 0x80, - CTRL_TIMER1_MASK = 0x40, - CTRL_TIMER2_MASK = 0x20, - CTRL_TIMER2_CTRL = 0x02, - CTRL_TIMER1_CTRL = 0x01 -}; - -void opl_init(void (*timer_callback)(void *param, int timer, uint64_t period), void *timer_param, int nr, int is_opl3) -{ - opl[nr].timer_callback = timer_callback; - opl[nr].timer_param = timer_param; - opl[nr].is_opl3 = is_opl3; - - if (!opl_type) - { - DBOPL::InitTables(); - opl[nr].chip.Setup(48000, is_opl3); - } - else - { - opl[nr].opl3chip.newm = 0; - OPL3_Reset(&opl[nr].opl3chip, 48000); - } -} - -void opl_status_update(int nr) -{ - if (opl[nr].status & (STATUS_TIMER_1 | STATUS_TIMER_2) & opl[nr].status_mask) - opl[nr].status |= STATUS_TIMER_ALL; - else - opl[nr].status &= ~STATUS_TIMER_ALL; -} - -void opl_timer_over(int nr, int timer) -{ - if (!timer) - { - opl[nr].status |= STATUS_TIMER_1; - opl[nr].timer_callback(opl[nr].timer_param, 0, opl[nr].timer[0] * 4); - } - else - { - opl[nr].status |= STATUS_TIMER_2; - opl[nr].timer_callback(opl[nr].timer_param, 1, opl[nr].timer[1] * 16); - } - - opl_status_update(nr); -} - -void opl_write(int nr, uint16_t addr, uint8_t val) -{ - if (!(addr & 1)) - { - if (!opl_type) - opl[nr].addr = (int)opl[nr].chip.WriteAddr(addr, val) & 0x1ff; - else - opl[nr].addr = (int)OPL3_WriteAddr(&opl[nr].opl3chip, addr, val) & 0x1ff; - if (!opl[nr].is_opl3) - opl[nr].addr &= 0xff; - } - else - { - if (!opl_type) - opl[nr].chip.WriteReg(opl[nr].addr, val); - else { - OPL3_WriteRegBuffered(&opl[nr].opl3chip, (uint16_t) opl[nr].addr, val); - if (opl[nr].addr == 0x105) - opl[nr].opl3chip.newm = opl[nr].addr & 0x01; - } - - switch (opl[nr].addr) - { - case 0x02: /*Timer 1*/ - opl[nr].timer[0] = 256 - val; - break; - case 0x03: /*Timer 2*/ - opl[nr].timer[1] = 256 - val; - break; - case 0x04: /*Timer control*/ - if (val & CTRL_IRQ_RESET) /*IRQ reset*/ - { - opl[nr].status &= ~(STATUS_TIMER_1 | STATUS_TIMER_2); - opl_status_update(nr); - return; - } - if ((val ^ opl[nr].timer_ctrl) & CTRL_TIMER1_CTRL) - { - if (val & CTRL_TIMER1_CTRL) - opl[nr].timer_callback(opl[nr].timer_param, 0, opl[nr].timer[0] * 4); - else - opl[nr].timer_callback(opl[nr].timer_param, 0, 0); - } - if ((val ^ opl[nr].timer_ctrl) & CTRL_TIMER2_CTRL) - { - if (val & CTRL_TIMER2_CTRL) - opl[nr].timer_callback(opl[nr].timer_param, 1, opl[nr].timer[1] * 16); - else - opl[nr].timer_callback(opl[nr].timer_param, 1, 0); - } - opl[nr].status_mask = (~val & (CTRL_TIMER1_MASK | CTRL_TIMER2_MASK)) | 0x80; - opl[nr].timer_ctrl = val; - break; - } - } - -} - -uint8_t opl_read(int nr, uint16_t addr) -{ - if (!(addr & 1)) - { - return (opl[nr].status & opl[nr].status_mask) | (opl[nr].is_opl3 ? 0 : 0x06); - } - return opl[nr].is_opl3 ? 0 : 0xff; -} - -void opl2_update(int nr, int16_t *buffer, int samples) -{ - int c; - Bit32s buffer_32[samples]; - - if (opl_type) - { - OPL3_GenerateStream(&opl[nr].opl3chip, buffer, samples); - } - else - { - opl[nr].chip.GenerateBlock2(samples, buffer_32); - - for (c = 0; c < samples; c++) - buffer[c*2] = (int16_t)buffer_32[c]; - } -} - -void opl3_update(int nr, int16_t *buffer, int samples) -{ - int c; - Bit32s buffer_32[samples*2]; - - if (opl_type) - { - OPL3_GenerateStream(&opl[nr].opl3chip, buffer, samples); - } - else - { - opl[nr].chip.GenerateBlock3(samples, buffer_32); - - for (c = 0; c < samples*2; c++) - buffer[c] = (int16_t)buffer_32[c]; - } -} diff --git a/src/sound/snd_opl.c b/src/sound/snd_opl.c index f89a81a04..437ea62b5 100644 --- a/src/sound/snd_opl.c +++ b/src/sound/snd_opl.c @@ -12,70 +12,93 @@ #include "../timer.h" #include "sound.h" #include "snd_opl.h" -#include "snd_dbopl.h" +#include "snd_opl_backend.h" /*Interfaces between 86Box and the actual OPL emulator*/ -uint8_t opl2_read(uint16_t a, void *priv) +uint8_t +opl2_read(uint16_t a, void *priv) { - opl_t *opl = (opl_t *)priv; + opl_t *opl = (opl_t *)priv; - sub_cycles((int)(isa_timing * 8)); - opl2_update2(opl); - return opl_read(0, a); -} -void opl2_write(uint16_t a, uint8_t v, void *priv) -{ - opl_t *opl = (opl_t *)priv; + sub_cycles((int) (isa_timing * 8)); + opl2_update2(opl); - opl2_update2(opl); - opl_write(0, a, v); - opl_write(1, a, v); + return opl_read(0, a); } -uint8_t opl2_l_read(uint16_t a, void *priv) -{ - opl_t *opl = (opl_t *)priv; - sub_cycles((int)(isa_timing * 8)); - opl2_update2(opl); - return opl_read(0, a); -} -void opl2_l_write(uint16_t a, uint8_t v, void *priv) +void +opl2_write(uint16_t a, uint8_t v, void *priv) { - opl_t *opl = (opl_t *)priv; + opl_t *opl = (opl_t *)priv; - opl2_update2(opl); - opl_write(0, a, v); + opl2_update2(opl); + opl_write(0, a, v); + opl_write(1, a, v); } -uint8_t opl2_r_read(uint16_t a, void *priv) -{ - opl_t *opl = (opl_t *)priv; - sub_cycles((int)(isa_timing * 8)); - opl2_update2(opl); - return opl_read(1, a); -} -void opl2_r_write(uint16_t a, uint8_t v, void *priv) +uint8_t +opl2_l_read(uint16_t a, void *priv) { - opl_t *opl = (opl_t *)priv; + opl_t *opl = (opl_t *)priv; - opl2_update2(opl); - opl_write(1, a, v); + sub_cycles((int)(isa_timing * 8)); + opl2_update2(opl); + + return opl_read(0, a); } -uint8_t opl3_read(uint16_t a, void *priv) -{ - opl_t *opl = (opl_t *)priv; - sub_cycles((int)(isa_timing * 8)); - opl3_update2(opl); - return opl_read(0, a); +void +opl2_l_write(uint16_t a, uint8_t v, void *priv) +{ + opl_t *opl = (opl_t *)priv; + + opl2_update2(opl); + opl_write(0, a, v); } -void opl3_write(uint16_t a, uint8_t v, void *priv) + + +uint8_t +opl2_r_read(uint16_t a, void *priv) +{ + opl_t *opl = (opl_t *)priv; + + sub_cycles((int)(isa_timing * 8)); + opl2_update2(opl); + + return opl_read(1, a); +} + + +void +opl2_r_write(uint16_t a, uint8_t v, void *priv) +{ + opl_t *opl = (opl_t *)priv; + + opl2_update2(opl); + opl_write(1, a, v); +} + + +uint8_t +opl3_read(uint16_t a, void *priv) +{ + opl_t *opl = (opl_t *)priv; + + sub_cycles((int)(isa_timing * 8)); + opl3_update2(opl); + + return opl_read(0, a); +} + + +void +opl3_write(uint16_t a, uint8_t v, void *priv) { opl_t *opl = (opl_t *)priv; @@ -84,93 +107,116 @@ void opl3_write(uint16_t a, uint8_t v, void *priv) } -void opl2_update2(opl_t *opl) +void +opl2_update2(opl_t *opl) { - if (opl->pos < sound_pos_global) - { - opl2_update(0, &opl->buffer[opl->pos*2], sound_pos_global - opl->pos); - 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] / 2); - opl->filtbuf[1] = opl->buffer[opl->pos*2+1] = (opl->buffer[opl->pos*2+1] / 2); - } - } + if (opl->pos < sound_pos_global) { + opl2_update(0, &opl->buffer[opl->pos << 1], sound_pos_global - opl->pos); + opl2_update(1, &opl->buffer2[opl->pos << 1], sound_pos_global - opl->pos); + for (; opl->pos < sound_pos_global; opl->pos++) { + opl->buffer[(opl->pos << 1) + 1] = opl->buffer2[(opl->pos << 1) + 1]; + opl->filtbuf[0] = opl->buffer[opl->pos << 1] = (opl->buffer[opl->pos << 1] / 2); + opl->filtbuf[1] = opl->buffer[(opl->pos << 1) + 1] = (opl->buffer[(opl->pos << 1) + 1] / 2); + } + } } -void opl3_update2(opl_t *opl) + +void +opl3_update2(opl_t *opl) { - if (opl->pos < sound_pos_global) - { - 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] / 2); - opl->filtbuf[1] = opl->buffer[opl->pos*2+1] = (opl->buffer[opl->pos*2+1] / 2); - } - } + if (opl->pos < sound_pos_global) { + opl3_update(0, &opl->buffer[(opl->pos << 1)], sound_pos_global - opl->pos); + for (; opl->pos < sound_pos_global; opl->pos++) { + opl->filtbuf[0] = opl->buffer[opl->pos << 1] = (opl->buffer[opl->pos << 1] / 2); + opl->filtbuf[1] = opl->buffer[(opl->pos << 1) + 1] = (opl->buffer[(opl->pos << 1) + 1] / 2); + } + } } -void ym3812_timer_set_0(void *param, int timer, uint64_t period) -{ - opl_t *opl = (opl_t *)param; - - if (period) - timer_set_delay_u64(&opl->timers[0][timer], period * TIMER_USEC * 20); - else - timer_disable(&opl->timers[0][timer]); -} -void ym3812_timer_set_1(void *param, int timer, uint64_t period) -{ - opl_t *opl = (opl_t *)param; - if (period) - timer_set_delay_u64(&opl->timers[1][timer], period * TIMER_USEC * 20); - else - timer_disable(&opl->timers[1][timer]); +void +ym3812_timer_set_0(void *param, int timer, uint64_t period) +{ + opl_t *opl = (opl_t *)param; + + if (period) + timer_set_delay_u64(&opl->timers[0][timer], period * TIMER_USEC * 20); + else + timer_disable(&opl->timers[0][timer]); } -void ymf262_timer_set(void *param, int timer, uint64_t period) -{ - opl_t *opl = (opl_t *)param; - if (period) - timer_set_delay_u64(&opl->timers[0][timer], period * TIMER_USEC * 20); - else - timer_disable(&opl->timers[0][timer]); +void +ym3812_timer_set_1(void *param, int timer, uint64_t period) +{ + opl_t *opl = (opl_t *)param; + + if (period) + timer_set_delay_u64(&opl->timers[1][timer], period * TIMER_USEC * 20); + else + timer_disable(&opl->timers[1][timer]); } -static void opl_timer_callback00(void *p) + +void +ymf262_timer_set(void *param, int timer, uint64_t period) { - opl_timer_over(0, 0); -} -static void opl_timer_callback01(void *p) -{ - opl_timer_over(0, 1); -} -static void opl_timer_callback10(void *p) -{ - opl_timer_over(1, 0); -} -static void opl_timer_callback11(void *p) -{ - opl_timer_over(1, 1); -} - -void opl2_init(opl_t *opl) -{ - opl_init(ym3812_timer_set_0, opl, 0, 0); - opl_init(ym3812_timer_set_1, opl, 1, 0); - timer_add(&opl->timers[0][0], opl_timer_callback00, (void *)opl, 0); - timer_add(&opl->timers[0][1], opl_timer_callback01, (void *)opl, 0); - timer_add(&opl->timers[1][0], opl_timer_callback10, (void *)opl, 0); - timer_add(&opl->timers[1][1], opl_timer_callback11, (void *)opl, 0); + opl_t *opl = (opl_t *)param; + + if (period) + timer_set_delay_u64(&opl->timers[0][timer], period * TIMER_USEC * 20); + else + timer_disable(&opl->timers[0][timer]); } -void opl3_init(opl_t *opl) + +static void +opl_timer_callback00(void *p) { - opl_init(ymf262_timer_set, opl, 0, 1); - timer_add(&opl->timers[0][0], opl_timer_callback00, (void *)opl, 0); - timer_add(&opl->timers[0][1], opl_timer_callback01, (void *)opl, 0); + opl_timer_over(0, 0); } + +static void +opl_timer_callback01(void *p) +{ + opl_timer_over(0, 1); +} + + +static void +opl_timer_callback10(void *p) +{ + opl_timer_over(1, 0); +} + + +static void +opl_timer_callback11(void *p) +{ + opl_timer_over(1, 1); +} + + +void +opl2_init(opl_t *opl) +{ + opl_init(ym3812_timer_set_0, opl, 0, 0); + opl_init(ym3812_timer_set_1, opl, 1, 0); + + timer_add(&opl->timers[0][0], opl_timer_callback00, (void *)opl, 0); + timer_add(&opl->timers[0][1], opl_timer_callback01, (void *)opl, 0); + timer_add(&opl->timers[1][0], opl_timer_callback10, (void *)opl, 0); + timer_add(&opl->timers[1][1], opl_timer_callback11, (void *)opl, 0); +} + + +void +opl3_init(opl_t *opl) +{ + opl_init(ymf262_timer_set, opl, 0, 1); + + timer_add(&opl->timers[0][0], opl_timer_callback00, (void *)opl, 0); + timer_add(&opl->timers[0][1], opl_timer_callback01, (void *)opl, 0); +} diff --git a/src/sound/snd_opl.h b/src/sound/snd_opl.h index 628d8b55f..aff429e77 100644 --- a/src/sound/snd_opl.h +++ b/src/sound/snd_opl.h @@ -3,30 +3,30 @@ */ typedef struct opl_t { - int chip_nr[2]; - - pc_timer_t timers[2][2]; + int pos, chip_nr[2]; - int16_t filtbuf[2]; + int32_t filtbuf[2], + buffer[SOUNDBUFLEN * 2], + buffer2[SOUNDBUFLEN * 2]; - int16_t buffer[SOUNDBUFLEN * 2]; - int pos; + pc_timer_t timers[2][2]; } opl_t; -uint8_t opl2_read(uint16_t a, void *priv); -void opl2_write(uint16_t a, uint8_t v, void *priv); -uint8_t opl2_l_read(uint16_t a, void *priv); -void opl2_l_write(uint16_t a, uint8_t v, void *priv); -uint8_t opl2_r_read(uint16_t a, void *priv); -void opl2_r_write(uint16_t a, uint8_t v, void *priv); -uint8_t opl3_read(uint16_t a, void *priv); -void opl3_write(uint16_t a, uint8_t v, void *priv); -void opl2_poll(opl_t *opl, int16_t *bufl, int16_t *bufr); -void opl3_poll(opl_t *opl, int16_t *bufl, int16_t *bufr); +extern uint8_t opl2_read(uint16_t a, void *priv); +extern void opl2_write(uint16_t a, uint8_t v, void *priv); +extern uint8_t opl2_l_read(uint16_t a, void *priv); +extern void opl2_l_write(uint16_t a, uint8_t v, void *priv); +extern uint8_t opl2_r_read(uint16_t a, void *priv); +extern void opl2_r_write(uint16_t a, uint8_t v, void *priv); +extern uint8_t opl3_read(uint16_t a, void *priv); +extern void opl3_write(uint16_t a, uint8_t v, void *priv); -void opl2_init(opl_t *opl); -void opl3_init(opl_t *opl); +extern void opl2_poll(opl_t *opl, int16_t *bufl, int16_t *bufr); +extern void opl3_poll(opl_t *opl, int16_t *bufl, int16_t *bufr); -void opl2_update2(opl_t *opl); -void opl3_update2(opl_t *opl); +extern void opl2_init(opl_t *opl); +extern void opl3_init(opl_t *opl); + +extern void opl2_update2(opl_t *opl); +extern void opl3_update2(opl_t *opl); diff --git a/src/sound/snd_opl_backend.c b/src/sound/snd_opl_backend.c new file mode 100644 index 000000000..0a0e08d8e --- /dev/null +++ b/src/sound/snd_opl_backend.c @@ -0,0 +1,147 @@ +/* Copyright holders: Sarah Walker, SA1988 + see COPYING for more details +*/ +#include "nukedopl.h" +#include "sound.h" +#include "snd_opl_backend.h" + + +int opl_type = 0; + + +static struct +{ + struct opl3_chip opl3chip; + int addr; + int timer[2]; + uint8_t timer_ctrl; + uint8_t status_mask; + uint8_t status; + int is_opl3; + + void (*timer_callback)(void *param, int timer, uint64_t period); + void *timer_param; +} opl[2]; + + +enum +{ + STATUS_TIMER_1 = 0x40, + STATUS_TIMER_2 = 0x20, + STATUS_TIMER_ALL = 0x80 +}; + +enum +{ + CTRL_IRQ_RESET = 0x80, + CTRL_TIMER1_MASK = 0x40, + CTRL_TIMER2_MASK = 0x20, + CTRL_TIMER2_CTRL = 0x02, + CTRL_TIMER1_CTRL = 0x01 +}; + + +void +opl_init(void (*timer_callback)(void *param, int timer, uint64_t period), void *timer_param, int nr, int is_opl3) +{ + opl[nr].timer_callback = timer_callback; + opl[nr].timer_param = timer_param; + opl[nr].is_opl3 = is_opl3; + + opl[nr].opl3chip.newm = 0; + OPL3_Reset(&opl[nr].opl3chip, 48000); +} + + +void +opl_status_update(int nr) +{ + if (opl[nr].status & (STATUS_TIMER_1 | STATUS_TIMER_2) & opl[nr].status_mask) + opl[nr].status |= STATUS_TIMER_ALL; + else + opl[nr].status &= ~STATUS_TIMER_ALL; +} + + +void +opl_timer_over(int nr, int timer) +{ + if (!timer) { + opl[nr].status |= STATUS_TIMER_1; + opl[nr].timer_callback(opl[nr].timer_param, 0, opl[nr].timer[0] * 4); + } else { + opl[nr].status |= STATUS_TIMER_2; + opl[nr].timer_callback(opl[nr].timer_param, 1, opl[nr].timer[1] * 16); + } + + opl_status_update(nr); +} + + +void +opl_write(int nr, uint16_t addr, uint8_t val) +{ + if (!(addr & 1)) { + opl[nr].addr = (int)OPL3_WriteAddr(&opl[nr].opl3chip, addr, val) & 0x1ff; + if (!opl[nr].is_opl3) + opl[nr].addr &= 0xff; + } else { + OPL3_WriteRegBuffered(&opl[nr].opl3chip, (uint16_t) opl[nr].addr, val); + if (opl[nr].addr == 0x105) + opl[nr].opl3chip.newm = opl[nr].addr & 0x01; + + switch (opl[nr].addr) { + case 0x02: /*Timer 1*/ + opl[nr].timer[0] = 256 - val; + break; + case 0x03: /*Timer 2*/ + opl[nr].timer[1] = 256 - val; + break; + case 0x04: /*Timer control*/ + if (val & CTRL_IRQ_RESET) { /*IRQ reset*/ + opl[nr].status &= ~(STATUS_TIMER_1 | STATUS_TIMER_2); + opl_status_update(nr); + return; + } + if ((val ^ opl[nr].timer_ctrl) & CTRL_TIMER1_CTRL) { + if (val & CTRL_TIMER1_CTRL) + opl[nr].timer_callback(opl[nr].timer_param, 0, opl[nr].timer[0] * 4); + else + opl[nr].timer_callback(opl[nr].timer_param, 0, 0); + } + if ((val ^ opl[nr].timer_ctrl) & CTRL_TIMER2_CTRL) { + if (val & CTRL_TIMER2_CTRL) + opl[nr].timer_callback(opl[nr].timer_param, 1, opl[nr].timer[1] * 16); + else + opl[nr].timer_callback(opl[nr].timer_param, 1, 0); + } + opl[nr].status_mask = (~val & (CTRL_TIMER1_MASK | CTRL_TIMER2_MASK)) | 0x80; + opl[nr].timer_ctrl = val; + break; + } + } +} + + +uint8_t +opl_read(int nr, uint16_t addr) +{ + if (!(addr & 1)) + return (opl[nr].status & opl[nr].status_mask) | (opl[nr].is_opl3 ? 0 : 0x06); + + return opl[nr].is_opl3 ? 0 : 0xff; +} + + +void +opl2_update(int nr, int32_t *buffer, int samples) +{ + OPL3_GenerateStream(&opl[nr].opl3chip, buffer, samples); +} + + +void +opl3_update(int nr, int32_t *buffer, int samples) +{ + OPL3_GenerateStream(&opl[nr].opl3chip, buffer, samples); +} diff --git a/src/sound/snd_dbopl.h b/src/sound/snd_opl_backend.h similarity index 77% rename from src/sound/snd_dbopl.h rename to src/sound/snd_opl_backend.h index e95a2becd..24120d036 100644 --- a/src/sound/snd_dbopl.h +++ b/src/sound/snd_opl_backend.h @@ -8,8 +8,8 @@ extern "C" { void opl_write(int nr, uint16_t addr, uint8_t val); uint8_t opl_read(int nr, uint16_t addr); void opl_timer_over(int nr, int timer); - void opl2_update(int nr, int16_t *buffer, int samples); - void opl3_update(int nr, int16_t *buffer, int samples); + void opl2_update(int nr, int32_t *buffer, int samples); + void opl3_update(int nr, int32_t *buffer, int samples); extern int opl_type; #ifdef __cplusplus diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index b16078467..b927e54e4 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -33,7 +33,6 @@ #include "../device.h" #include "sound.h" #include "filters.h" -#include "snd_dbopl.h" #include "snd_emu8k.h" #include "snd_mpu401.h" #include "snd_opl.h" @@ -203,7 +202,7 @@ static void sb_get_buffer_sb2(int32_t *buffer, int len, void *p) { int32_t out = 0; if (sb->opl_enabled) - out = ((sb->opl.buffer[c] * 51000) >> 16); + out = ((sb->opl.buffer[c] * (sb->opl_emu ? 47000 : 51000)) >> 16); //TODO: Recording: Mic and line In with AGC out += (int32_t)(((sb_iir(0, (float)sb->dsp.buffer[c]) / 1.3) * 65536) / 3) >> 16; @@ -231,7 +230,7 @@ static void sb_get_buffer_sb2_mixer(int32_t *buffer, int len, void *p) int32_t out = 0; if (sb->opl_enabled) - out = ((((sb->opl.buffer[c] * mixer->fm) >> 16) * 51000) >> 15); + out = ((((sb->opl.buffer[c] * mixer->fm) >> 16) * (sb->opl_emu ? 47000 : 51000)) >> 15); /* TODO: Recording : I assume it has direct mic and line in like sb2 */ /* It is unclear from the docs if it has a filter, but it probably does */ out += (int32_t)(((sb_iir(0, (float)sb->dsp.buffer[c]) / 1.3) * mixer->voice) / 3) >> 15; diff --git a/src/win/86Box.rc b/src/win/86Box.rc index d9f73af4b..294e813b9 100644 --- a/src/win/86Box.rc +++ b/src/win/86Box.rc @@ -8,7 +8,7 @@ * * Application resource script for Windows. * - * Version: @(#)86Box.rc 1.0.55 2019/12/05 + * Version: @(#)86Box.rc 1.0.56 2019/12/21 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -391,11 +391,8 @@ BEGIN CONTROL "Gravis Ultrasound",IDC_CHECK_GUS,"Button", BS_AUTOCHECKBOX | WS_TABSTOP,7,81,94,10 - CONTROL "Use Nuked OPL",IDC_CHECK_NUKEDOPL,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,147,81,94,10 - CONTROL "Use FLOAT32 sound",IDC_CHECK_FLOAT,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,7,99,94,10 + BS_AUTOCHECKBOX | WS_TABSTOP,147,81,94,10 END DLG_CFG_NETWORK DIALOG DISCARDABLE 97, 0, 267, 63 @@ -903,7 +900,6 @@ BEGIN IDS_2120 "Unable to initialize SDL, SDL2.dll is required" IDS_2121 "Are you sure you want to hard reset the emulated machine?" IDS_2122 "Are you sure you want to quit 86Box?" - IDS_2123 "Unable to initialize Ghostscript, gsdll32.dll is required for automatic convertion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript files (.ps)." END STRINGTABLE DISCARDABLE diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index a05863a35..79647a697 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -8,7 +8,7 @@ # # Makefile for Win32 (MinGW32) environment. # -# Version: @(#)Makefile.mingw 1.0.139 2019/12/05 +# Version: @(#)Makefile.mingw 1.0.140 2019/12/21 # # Authors: Miran Grca, # Fred N. van Kempen, @@ -604,7 +604,7 @@ HDDOBJ := hdd.o \ hdc_ide_sff8038i.o CDROMOBJ := cdrom.o \ - cdrom_dosbox.o cdrom_image.o + cdrom_image_backend.o cdrom_image.o ZIPOBJ := zip.o @@ -633,8 +633,8 @@ PRINTOBJ := png.o prt_cpmap.o \ SNDOBJ := sound.o \ openal.o \ - snd_opl.o snd_dbopl.o \ - dbopl.o nukedopl.o \ + snd_opl.o snd_opl_backend.o \ + nukedopl.o \ snd_resid.o \ convolve.o convolve-sse.o envelope.o extfilt.o \ filter.o pot.o sid.o voice.o wave6581__ST.o \ @@ -691,12 +691,8 @@ VIDOBJ := video.o \ PLATOBJ := win.o \ win_dynld.o win_thread.o \ win_cdrom.o win_keyboard.o \ - win_midi.o -ifeq ($(DINPUT), y) - PLATOBJ += win_mouse.o win_joystick.o -else - PLATOBJ += win_mouse_rawinput.o win_joystick.o -endif + win_midi.o \ + win_mouse.o win_joystick.o OBJ := $(MAINOBJ) $(INTELOBJ) $(CPUOBJ) $(CHIPSETOBJ) $(MCHOBJ) \ $(DEVOBJ) $(FDDOBJ) $(CDROMOBJ) $(ZIPOBJ) $(HDDOBJ) \ diff --git a/src/win/Makefile_ndr.mingw b/src/win/Makefile_ndr.mingw index fa175ca60..560d6fdbb 100644 --- a/src/win/Makefile_ndr.mingw +++ b/src/win/Makefile_ndr.mingw @@ -8,7 +8,7 @@ # # Makefile for Win32 (MinGW32) environment. # -# Version: @(#)Makefile.mingw 1.0.139 2019/12/05 +# Version: @(#)Makefile.mingw 1.0.140 2019/12/21 # # Authors: Miran Grca, # Fred N. van Kempen, @@ -610,7 +610,7 @@ HDDOBJ := hdd.o \ hdc_ide_sff8038i.o CDROMOBJ := cdrom.o \ - cdrom_dosbox.o cdrom_image.o + cdrom_image_backend.o cdrom_image.o ZIPOBJ := zip.o @@ -639,8 +639,8 @@ PRINTOBJ := png.o prt_cpmap.o \ SNDOBJ := sound.o \ openal.o \ - snd_opl.o snd_dbopl.o \ - dbopl.o nukedopl.o \ + snd_opl.o snd_opl_backend.o \ + nukedopl.o \ snd_resid.o \ convolve.o convolve-sse.o envelope.o extfilt.o \ filter.o pot.o sid.o voice.o wave6581__ST.o \ @@ -697,12 +697,8 @@ VIDOBJ := video.o \ PLATOBJ := win.o \ win_dynld.o win_thread.o \ win_cdrom.o win_keyboard.o \ - win_midi.o -ifeq ($(DINPUT), y) - PLATOBJ += win_mouse.o win_joystick.o -else - PLATOBJ += win_mouse_rawinput.o win_joystick.o -endif + win_midi.o \ + win_mouse.o win_joystick.o OBJ := $(MAINOBJ) $(INTELOBJ) $(CPUOBJ) $(CHIPSETOBJ) $(MCHOBJ) \ $(DEVOBJ) $(FDDOBJ) $(CDROMOBJ) $(ZIPOBJ) $(HDDOBJ) \ diff --git a/src/win/resource.h b/src/win/resource.h index 4922df81b..e34f6a1be 100644 --- a/src/win/resource.h +++ b/src/win/resource.h @@ -8,7 +8,7 @@ * * Windows resource defines. * - * Version: @(#)resource.h 1.0.31 2019/12/05 + * Version: @(#)resource.h 1.0.32 2019/12/21 * * Authors: Sarah Walker, * Miran Grca, @@ -144,12 +144,11 @@ #define IDC_CHECK_SSI 1072 #define IDC_CHECK_CMS 1073 #define IDC_CHECK_GUS 1074 -#define IDC_CHECK_NUKEDOPL 1075 -#define IDC_COMBO_MIDI 1076 -#define IDC_CHECK_MPU401 1077 -#define IDC_CONFIGURE_MPU401 1078 -#define IDC_CHECK_FLOAT 1079 -#define IDC_CHECK_GUSMAX 1080 +#define IDC_COMBO_MIDI 1075 +#define IDC_CHECK_MPU401 1076 +#define IDC_CONFIGURE_MPU401 1077 +#define IDC_CHECK_FLOAT 1078 +#define IDC_CHECK_GUSMAX 1079 #define IDC_COMBO_NET_TYPE 1090 /* network config */ #define IDC_COMBO_PCAP 1091 diff --git a/src/win/win_mouse_rawinput.cpp b/src/win/win_mouse.c similarity index 98% rename from src/win/win_mouse_rawinput.cpp rename to src/win/win_mouse.c index fc983d24d..2ca004e9f 100644 --- a/src/win/win_mouse_rawinput.cpp +++ b/src/win/win_mouse.c @@ -63,8 +63,9 @@ win_mouse_handle(LPARAM lParam, int infocus) uint32_t ri_size = 0; UINT size; RAWINPUT *raw; - RAWMOUSE state; - + RAWMOUSE state; + static int x, y; + if (! infocus) return; GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, @@ -109,7 +110,7 @@ win_mouse_handle(LPARAM lParam, int infocus) * seems to work fine for RDP on Windows 10 * Not sure about other environments. */ - static int x=state.lLastX, y=state.lLastY; + x=state.lLastX, y=state.lLastY; mousestate.dx += (state.lLastX - x)/100; mousestate.dy += (state.lLastY - y)/100; x=state.lLastX; diff --git a/src/win/win_mouse.cpp b/src/win/win_mouse.cpp deleted file mode 100644 index a57969196..000000000 --- a/src/win/win_mouse.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * Mouse interface to host device. - * - * Version: @(#)win_mouse.cpp 1.0.6 2017/11/25 - * - * Authors: Sarah Walker, - * Miran Grca, - * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. - */ -#define DIRECTINPUT_VERSION 0x0800 -#include -#include -#include -#include "../86box.h" -#include "../mouse.h" -#include "../plat.h" -#include "win.h" - - -int mouse_capture; - - -static LPDIRECTINPUT8 lpdi; -static LPDIRECTINPUTDEVICE8 lpdi_mouse = NULL; -static DIMOUSESTATE mousestate; - - -void -win_mouse_init(void) -{ - atexit(win_mouse_close); - - mouse_capture = 0; - - if (FAILED(DirectInput8Create(hinstance, DIRECTINPUT_VERSION, - IID_IDirectInput8A, (void **) &lpdi, NULL))) - fatal("plat_mouse_init: DirectInputCreate failed\n"); - - if (FAILED(lpdi->CreateDevice(GUID_SysMouse, &lpdi_mouse, NULL))) - fatal("plat_mouse_init: CreateDevice failed\n"); - - if (FAILED(lpdi_mouse->SetCooperativeLevel(hwndMain, - DISCL_FOREGROUND | (video_fullscreen ? DISCL_EXCLUSIVE : DISCL_NONEXCLUSIVE)))) - fatal("plat_mouse_init: SetCooperativeLevel failed\n"); - - if (FAILED(lpdi_mouse->SetDataFormat(&c_dfDIMouse))) - fatal("plat_mouse_init: SetDataFormat failed\n"); -} - - -void -win_mouse_close(void) -{ - if (lpdi_mouse != NULL) { - lpdi_mouse->Release(); - lpdi_mouse = NULL; - } -} - - -void -mouse_poll(void) -{ - static int buttons = 0; - static int x = 0, y = 0, z = 0; - int b; - - if (FAILED(lpdi_mouse->GetDeviceState(sizeof(DIMOUSESTATE), - (LPVOID)&mousestate))) { - lpdi_mouse->Acquire(); - lpdi_mouse->GetDeviceState(sizeof(DIMOUSESTATE), (LPVOID)&mousestate); - } - - if (mouse_capture || video_fullscreen) { - if (x != mousestate.lX || y != mousestate.lY || z != mousestate.lZ) { - mouse_x += mousestate.lX; - mouse_y += mousestate.lY; - mouse_z += mousestate.lZ/120; - - x = mousestate.lX; - y = mousestate.lY; - z = mousestate.lZ/120; - } - - b = 0; - if (mousestate.rgbButtons[0] & 0x80) b |= 1; - if (mousestate.rgbButtons[1] & 0x80) b |= 2; - if (mousestate.rgbButtons[2] & 0x80) b |= 4; - if (buttons != b) { - mouse_buttons = b; - buttons = b; - } - } -} diff --git a/src/win/win_settings.c b/src/win/win_settings.c index ed6747d5a..f2a716a8c 100644 --- a/src/win/win_settings.c +++ b/src/win/win_settings.c @@ -8,7 +8,7 @@ * * Windows 86Box Settings dialog handler. * - * Version: @(#)win_settings.c 1.0.62 2019/11/19 + * Version: @(#)win_settings.c 1.0.63 2019/12/21 * * Authors: Miran Grca, * David HrdliÄka, @@ -55,7 +55,6 @@ #include "../network/network.h" #include "../sound/sound.h" #include "../sound/midi.h" -#include "../sound/snd_dbopl.h" #include "../sound/snd_mpu401.h" #include "../video/video.h" #include "../video/vid_voodoo.h" @@ -85,7 +84,7 @@ static int temp_gfxcard, temp_voodoo; static int temp_mouse, temp_joystick; /* Sound category */ -static int temp_sound_card, temp_midi_device, temp_mpu401, temp_SSI2001, temp_GAMEBLASTER, temp_GUS, temp_opl_type; +static int temp_sound_card, temp_midi_device, temp_mpu401, temp_SSI2001, temp_GAMEBLASTER, temp_GUS; static int temp_float; /* Network category */ @@ -223,7 +222,6 @@ win_settings_init(void) temp_SSI2001 = SSI2001; temp_GAMEBLASTER = GAMEBLASTER; temp_GUS = GUS; - temp_opl_type = opl_type; temp_float = sound_is_float; /* Network category */ @@ -335,7 +333,6 @@ win_settings_changed(void) i = i || (SSI2001 != temp_SSI2001); i = i || (GAMEBLASTER != temp_GAMEBLASTER); i = i || (GUS != temp_GUS); - i = i || (opl_type != temp_opl_type); i = i || (sound_is_float != temp_float); /* Network category */ @@ -438,7 +435,6 @@ win_settings_save(void) SSI2001 = temp_SSI2001; GAMEBLASTER = temp_GAMEBLASTER; GUS = temp_GUS; - opl_type = temp_opl_type; sound_is_float = temp_float; /* Network category */ @@ -1215,9 +1211,6 @@ win_settings_sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) h=GetDlgItem(hdlg, IDC_CHECK_SSI); SendMessage(h, BM_SETCHECK, temp_SSI2001, 0); - h=GetDlgItem(hdlg, IDC_CHECK_NUKEDOPL); - SendMessage(h, BM_SETCHECK, temp_opl_type, 0); - h=GetDlgItem(hdlg, IDC_CHECK_FLOAT); SendMessage(h, BM_SETCHECK, temp_float, 0); @@ -1311,9 +1304,6 @@ win_settings_sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) h = GetDlgItem(hdlg, IDC_CHECK_SSI); temp_SSI2001 = SendMessage(h, BM_GETCHECK, 0, 0); - h = GetDlgItem(hdlg, IDC_CHECK_NUKEDOPL); - temp_opl_type = SendMessage(h, BM_GETCHECK, 0, 0); - h = GetDlgItem(hdlg, IDC_CHECK_FLOAT); temp_float = SendMessage(h, BM_GETCHECK, 0, 0); From 4957a9f86780c164887260e8a026bba2bf1db07c Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 21 Dec 2019 21:01:43 +0100 Subject: [PATCH 016/177] Fixed Mode 2 handling again and added support for reading raw sectors from non-raw images with reconstructed headers. --- src/cdrom/cdrom_image_backend.c | 89 ++++++++++++++++++++++++--------- src/cdrom/cdrom_image_backend.h | 3 +- 2 files changed, 67 insertions(+), 25 deletions(-) diff --git a/src/cdrom/cdrom_image_backend.c b/src/cdrom/cdrom_image_backend.c index 669989fc6..cb7c14a98 100644 --- a/src/cdrom/cdrom_image_backend.c +++ b/src/cdrom/cdrom_image_backend.c @@ -9,7 +9,7 @@ * CD-ROM image file handling module, translated to C from * cdrom_dosbox.cpp. * - * Version: @(#)cdrom_image_backend.c 1.0.0 2019/12/19 + * Version: @(#)cdrom_image_backend.c 1.0.1 2019/12/21 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -40,6 +40,8 @@ #include "cdrom_image_backend.h" +#define CDROM_BCD(x) (((x) % 10) | (((x) / 10) << 4)) + #define MAX_LINE_LENGTH 512 #define MAX_FILENAME_LENGTH 256 #define CROSS_LEN 512 @@ -308,33 +310,61 @@ cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector) { size_t length; int track = cdi_get_track(cdi, sector) - 1; - uint64_t s = (uint64_t) sector, seek; + uint64_t sect = (uint64_t) sector, seek; track_t *trk; + int track_is_raw, ret; + int raw_size, cooked_size; + uint64_t offset = 0ULL; + int m = 0, s = 0, f = 0; if (track < 0) return 0; trk = &cdi->tracks[track]; - seek = trk->skip + ((s - trk->start) * trk->sector_size); + track_is_raw = ((trk->sector_size == RAW_SECTOR_SIZE) || (trk->sector_size == 2448)); + if (raw && !track_is_raw) + return 0; + seek = trk->skip + ((sect - trk->start) * trk->sector_size); + + if (track_is_raw) + raw_size = trk->sector_size; + else + raw_size = 2448; - /* TODO: Is this correct? Is cooked sector size 2336 for all Mode 2 variants? */ if (trk->mode2 && (trk->form != 1)) { if (trk->form == 2) - length = (raw ? RAW_SECTOR_SIZE : 2324); + cooked_size = (track_is_raw ? 2328 : trk->sector_size); /* Both 2324 + ECC and 2328 variants are valid. */ else - length = (raw ? RAW_SECTOR_SIZE : 2336); + cooked_size = 2336; } else - length = (raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE); + cooked_size = COOKED_SECTOR_SIZE; - if (raw && (trk->sector_size != RAW_SECTOR_SIZE)) - return 0; - if (!raw && !trk->mode2 && (trk->sector_size == RAW_SECTOR_SIZE)) - seek += 16ULL; - /* TODO: See if Mode 2 is handled correctly here. */ - if (!raw && trk->mode2) - seek += 24ULL; + length = (raw ? raw_size : cooked_size); - return trk->file->read(trk->file, buffer, seek, length); + if (trk->mode2 && (trk->form >= 1)) + offset = 24ULL; + else + offset = 16ULL; + + if (raw && !track_is_raw) { + memset(buffer, 0x00, 2448); + ret = trk->file->read(trk->file, buffer + offset, seek, length); + if (!ret) + return 0; + /* Construct the rest of the raw sector. */ + memset(buffer + 1, 0xff, 10); + buffer += 12; + FRAMES_TO_MSF(sector + 150, &m, &s, &f); + /* These have to be BCD. */ + buffer[12] = CDROM_BCD(m & 0xff); + buffer[13] = CDROM_BCD(s & 0xff); + buffer[14] = CDROM_BCD(f & 0xff); + buffer[15] = trk->mode2 ? 2 : 1; /* Data, should reflect the actual sector type. */ + return 1; + } else if (!raw && track_is_raw) + return trk->file->read(trk->file, buffer, seek + offset, length); + else + return trk->file->read(trk->file, buffer, seek, length); } @@ -429,15 +459,15 @@ cdi_get_mode2_form(cd_img_t *cdi, uint32_t sector) } -int -cdi_can_read_pvd(track_file_t *file, uint64_t sector_size, int mode2) +static int +cdi_can_read_pvd(track_file_t *file, uint64_t sector_size, int mode2, int form) { uint8_t pvd[COOKED_SECTOR_SIZE]; uint64_t seek = 16ULL * sector_size; /* First VD is located at sector 16. */ - if (!mode2 && (sector_size == RAW_SECTOR_SIZE)) + if ((!mode2 || (form == 0)) && (sector_size == RAW_SECTOR_SIZE)) seek += 16; - if (mode2) + if (mode2 && (form >= 1)) seek += 24; file->read(file, pvd, seek, COOKED_SECTOR_SIZE); @@ -490,16 +520,16 @@ cdi_load_iso(cd_img_t *cdi, const wchar_t *filename) trk.form = 0; trk.mode2 = 0; /* TODO: Merge the first and last cases since they result in the same thing. */ - if (cdi_can_read_pvd(trk.file, RAW_SECTOR_SIZE, 0)) + if (cdi_can_read_pvd(trk.file, RAW_SECTOR_SIZE, 0, 0)) trk.sector_size = RAW_SECTOR_SIZE; - else if (cdi_can_read_pvd(trk.file, 2336, 1)) { + else if (cdi_can_read_pvd(trk.file, 2336, 1, 0)) { trk.sector_size = 2336; trk.mode2 = 1; - } else if (cdi_can_read_pvd(trk.file, 2324, 1)) { + } else if (cdi_can_read_pvd(trk.file, 2324, 1, 2)) { trk.sector_size = 2324; trk.mode2 = 1; trk.form = 2; - } else if (cdi_can_read_pvd(trk.file, RAW_SECTOR_SIZE, 1)) { + } else if (cdi_can_read_pvd(trk.file, RAW_SECTOR_SIZE, 1, 0)) { trk.sector_size = RAW_SECTOR_SIZE; trk.mode2 = 1; } else { @@ -771,6 +801,9 @@ cdi_load_cue(cd_img_t *cdi, const wchar_t *cuefile) } else if (!strcmp(type, "MODE1/2352")) { trk.sector_size = RAW_SECTOR_SIZE; trk.attr = DATA_TRACK; + } else if (!strcmp(type, "MODE1/2448")) { + trk.sector_size = 2448; + trk.attr = DATA_TRACK; } else if (!strcmp(type, "MODE2/2048")) { trk.form = 1; trk.sector_size = COOKED_SECTOR_SIZE; @@ -781,6 +814,11 @@ cdi_load_cue(cd_img_t *cdi, const wchar_t *cuefile) trk.sector_size = 2324; trk.attr = DATA_TRACK; trk.mode2 = 1; + } else if (!strcmp(type, "MODE2/2328")) { + trk.form = 2; + trk.sector_size = 2328; + trk.attr = DATA_TRACK; + trk.mode2 = 1; } else if (!strcmp(type, "MODE2/2336")) { trk.sector_size = 2336; trk.attr = DATA_TRACK; @@ -790,6 +828,11 @@ cdi_load_cue(cd_img_t *cdi, const wchar_t *cuefile) trk.sector_size = RAW_SECTOR_SIZE; trk.attr = DATA_TRACK; trk.mode2 = 1; + } else if (!strcmp(type, "MODE2/2448")) { + trk.form = 1; /* Assume this is XA Mode 2 Form 1. */ + trk.sector_size = 2448; + trk.attr = DATA_TRACK; + trk.mode2 = 1; } else if (!strcmp(type, "CDG/2448")) { trk.sector_size = 2448; trk.attr = DATA_TRACK; diff --git a/src/cdrom/cdrom_image_backend.h b/src/cdrom/cdrom_image_backend.h index 39d5b701d..b58b54d7b 100644 --- a/src/cdrom/cdrom_image_backend.h +++ b/src/cdrom/cdrom_image_backend.h @@ -9,7 +9,7 @@ * CD-ROM image file handling module header , translated to C * from cdrom_dosbox.h. * - * Version: @(#)cdrom_image_backend.h 1.0.0 2019/12/19 + * Version: @(#)cdrom_image_backend.h 1.0.1 2019/12/21 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -83,7 +83,6 @@ extern int cdi_read_sector_sub(cd_img_t *cdi, uint8_t *buffer, uint32_t sector); extern int cdi_get_sector_size(cd_img_t *cdi, uint32_t sector); extern int cdi_is_mode2(cd_img_t *cdi, uint32_t sector); extern int cdi_get_mode2_form(cd_img_t *cdi, uint32_t sector); -extern int cdi_can_read_pvd(track_file_t *file, uint64_t sector_size, int mode2); extern int cdi_load_iso(cd_img_t *cdi, const wchar_t *filename); extern int cdi_load_cue(cd_img_t *cdi, const wchar_t *cuefile); extern int cdi_has_data_track(cd_img_t *cdi); From 1d41f99dcfcce92268408f4f9d3e71f3422d45bd Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 28 Dec 2019 05:50:22 +0100 Subject: [PATCH 017/177] Fixed the ATi Mach64 hardware cursor. --- src/video/vid_ati_mach64.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c index d8fe8b8ef..03f7309f3 100644 --- a/src/video/vid_ati_mach64.c +++ b/src/video/vid_ati_mach64.c @@ -2798,14 +2798,14 @@ void mach64_hwcursor_draw(svga_t *svga, int displine) if (!(dat & 2)) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add] = (dat & 1) ? col1 : col0; else if ((dat & 3) == 3) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add] ^= 0xFFFFFF; dat >>= 2; - if (!(dat & 2)) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add] = (dat & 1) ? col1 : col0; - else if ((dat & 3) == 3) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add] ^= 0xFFFFFF; + if (!(dat & 2)) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add + 1] = (dat & 1) ? col1 : col0; + else if ((dat & 3) == 3) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add + 1] ^= 0xFFFFFF; dat >>= 2; - if (!(dat & 2)) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add] = (dat & 1) ? col1 : col0; - else if ((dat & 3) == 3) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add] ^= 0xFFFFFF; + if (!(dat & 2)) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add + 2] = (dat & 1) ? col1 : col0; + else if ((dat & 3) == 3) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add + 2] ^= 0xFFFFFF; dat >>= 2; - if (!(dat & 2)) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add] = (dat & 1) ? col1 : col0; - else if ((dat & 3) == 3) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add] ^= 0xFFFFFF; + if (!(dat & 2)) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add + 3] = (dat & 1) ? col1 : col0; + else if ((dat & 3) == 3) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add + 3] ^= 0xFFFFFF; dat >>= 2; offset += 4; } From 8cad1a3c4c9320102113e21e66dbab89b474f911 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 28 Dec 2019 05:50:55 +0100 Subject: [PATCH 018/177] Fixed the Tandy 320x200x4 modes. --- src/machine/m_tandy.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/machine/m_tandy.c b/src/machine/m_tandy.c index e4eb3fbd3..3dbc65748 100644 --- a/src/machine/m_tandy.c +++ b/src/machine/m_tandy.c @@ -8,7 +8,7 @@ * * Emulation of Tandy models 1000, 1000HX and 1000SL2. * - * Version: @(#)m_tandy.c 1.0.10 2019/10/20 + * Version: @(#)m_tandy.c 1.0.11 2019/12/28 * * Authors: Sarah Walker, * Miran Grca, @@ -74,11 +74,7 @@ typedef struct { int crtcreg; int array_index; -#if 0 - uint8_t array[32]; -#else uint8_t array[256]; -#endif int memctrl; uint8_t mode, col; uint8_t stat; @@ -95,13 +91,13 @@ typedef struct { int con, coff, cursoron, blink; - int vsynctime; + int vsynctime; int vadj; uint16_t ma, maback; uint64_t dispontime, dispofftime; - pc_timer_t timer; + pc_timer_t timer; int firstline, lastline; @@ -857,8 +853,8 @@ vid_poll(void *priv) } } } else if (! (vid->mode & 16)) { - cols[0] = (vid->col & 15) | 16; - col = (vid->col & 16) ? 24 : 16; + cols[0] = (vid->col & 15); + col = (vid->col & 16) ? 8 : 0; if (vid->mode & 4) { cols[1] = col | 3; cols[2] = col | 4; @@ -872,6 +868,10 @@ vid_poll(void *priv) cols[2] = col | 4; cols[3] = col | 6; } + cols[0] = vid->array[(cols[0] & vid->array[1]) + 16] + 16; + cols[1] = vid->array[(cols[1] & vid->array[1]) + 16] + 16; + cols[2] = vid->array[(cols[2] & vid->array[1]) + 16] + 16; + cols[3] = vid->array[(cols[3] & vid->array[1]) + 16] + 16; for (x = 0; x < vid->crtc[1]; x++) { dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1]; From f12d9c14db02e8761ea2028cc84d29796ee0b4dd Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 28 Dec 2019 05:51:22 +0100 Subject: [PATCH 019/177] Ported the (S)VGA linear read latch fix from PCem. --- src/video/vid_svga.c | 34 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 5de05c59e..a07764f12 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -11,7 +11,7 @@ * This is intended to be used by another SVGA driver, * and not as a card in it's own right. * - * Version: @(#)vid_svga.c 1.0.39 2019/12/03 + * Version: @(#)vid_svga.c 1.0.40 2019/12/28 * * Authors: Sarah Walker, * Miran Grca, @@ -1119,31 +1119,21 @@ svga_read_common(uint32_t addr, uint8_t linear, void *p) addr &= svga->decode_mask; /* standard VGA latched access */ - if (linear) { - if (addr >= svga->vram_max) - return 0xff; - - addr &= svga->vram_mask; + if (latch_addr >= svga->vram_max) { + for (i = 0; i < count; i++) + svga->latch.b[i] = 0xff; + } else { + latch_addr &= svga->vram_mask; for (i = 0; i < count; i++) - svga->latch.b[i] = svga->vram[addr | i]; - } else { - if (latch_addr >= svga->vram_max) { - for (i = 0; i < count; i++) - svga->latch.b[i] = 0xff; - } else { - latch_addr &= svga->vram_mask; - - for (i = 0; i < count; i++) - svga->latch.b[i] = svga->vram[latch_addr | i]; - } - - if (addr >= svga->vram_max) - return 0xff; - - addr &= svga->vram_mask; + svga->latch.b[i] = svga->vram[latch_addr | i]; } + if (addr >= svga->vram_max) + return 0xff; + + addr &= svga->vram_mask; + if (svga->readmode) { temp = 0xff; From 5715a4fa1246253d29fd6cf71b255afbf632fa67 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 30 Dec 2019 10:33:47 +0100 Subject: [PATCH 020/177] Updated the Discord invite in README.md. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5f823de0e..781cf3786 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ to retro computing and, of course, 86Box. We look forward to hearing from you! [![Visit our IRC channel](https://kiwiirc.com/buttons/irc.ringoflightning.net/softhistory.png)](https://kiwiirc.com/client/irc.ringoflightning.net/?nick=86box|?#softhistory) -[![Visit our Discord server](https://discordapp.com/api/guilds/262614059009048590/embed.png)](https://discord.gg/myzwyfX) +[![Visit our Discord server](https://discordapp.com/api/guilds/262614059009048590/embed.png)](https://discord.gg/QXK9XTv) Getting started --------------- From 4431331ae4612a123ca7efa02e186cff6b8bf8e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Simuni=C4=8D?= <33632722+daviunic@users.noreply.github.com> Date: Tue, 31 Dec 2019 16:27:08 +0100 Subject: [PATCH 021/177] Update README.md Added an extra step to install the missing packages until the current dev environment is replaced by a better alternative. --- README.md | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 781cf3786..772872305 100644 --- a/README.md +++ b/README.md @@ -42,20 +42,25 @@ guide: Depending on the state of the downloaded DE, you may need to run it twice (once initially, and then again after re-entering the environment). Make sure to keep the enviroment up-to-date by re-running the command periodically. -4. Once the environment is fully updated, `cd` into your cloned `86box\src` +4. Run the following commands to install the missing packages: + * `pacman -S mingw-w64-i686-libpng` + * `pacman -S mingw-w64-i686-freetype` + * `pacman -S mingw-w64-i686-ghostscript` + * `pacman -S mingw-w64-i686-SDL2` +5. Once the environment is fully updated, `cd` into your cloned `86box\src` directory. -5. Run `make -jN -f win/makefile.mingw` to start the actual compilation process. +6. Run `make -jN -f win/makefile.mingw` to start the actual compilation process. Substitute `N` with the number of threads you want to use for the compilation process. The optimal number depends entirely on your processor, and it is up to you to determine the optimal number. A good starting point is the total number of threads (AKA Logical Processors) you have available. -6. If the compilation succeeded (which it almost always should), you will find +7. If the compilation succeeded (which it almost always should), you will find `86Box.exe` in the src directory. -7. In order to test your fresh build, replace the `86Box.exe` in your current +8. In order to test your fresh build, replace the `86Box.exe` in your current 86Box enviroment with your freshly built one. If you do not have a pre-existing 86Box environment, download the latest successful build from http://ci.86box.net, and the ROM set from https://tinyurl.com/rs20191022. -8. Enjoy using and testing the emulator! :) +9. Enjoy using and testing the emulator! :) If you encounter issues at any step or have additional questions, please join the IRC channel and wait patiently for someone to help you. From 9562a20a6365aa2e7f99309398aa20116386d7f3 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Wed, 1 Jan 2020 20:20:16 +0100 Subject: [PATCH 022/177] Initial commit of MIDI IN. --- src/config.c | 11 + src/device.h | 1 + src/plat_midi.h | 6 + src/sound/midi.c | 173 +++++- src/sound/midi.h | 40 +- src/sound/midi_input.h | 1 + src/sound/midi_system.c | 78 +++ src/sound/snd_audiopci.c | 120 +++- src/sound/snd_mpu401.c | 1173 ++++++++++++++++++++++++++++++-------- src/sound/snd_mpu401.h | 64 ++- src/sound/snd_sb.c | 47 ++ src/sound/snd_sb_dsp.c | 98 +++- src/sound/snd_sb_dsp.h | 18 +- src/sound/sound.c | 2 +- src/win/86Box.rc | 33 +- src/win/resource.h | 15 +- src/win/win_devconf.c | 34 ++ src/win/win_midi.c | 125 +++- src/win/win_settings.c | 72 ++- 19 files changed, 1752 insertions(+), 359 deletions(-) create mode 100644 src/sound/midi_input.h diff --git a/src/config.c b/src/config.c index 583605583..2b9026989 100644 --- a/src/config.c +++ b/src/config.c @@ -649,6 +649,12 @@ load_sound(void) else midi_device_current = 0; + p = config_get_string(cat, "midi_in_device", NULL); + if (p != NULL) + midi_input_device_current = midi_in_device_get_from_internal_name(p); + else + midi_input_device_current = 0; + mpu401_standalone_enable = !!config_get_int(cat, "mpu401_standalone", 0); SSI2001 = !!config_get_int(cat, "ssi2001", 0); @@ -1531,6 +1537,11 @@ save_sound(void) else config_set_string(cat, "midi_device", midi_device_get_internal_name(midi_device_current)); + if (!strcmp(midi_in_device_get_internal_name(midi_input_device_current), "none")) + config_delete_var(cat, "midi_in_device"); + else + config_set_string(cat, "midi_in_device", midi_in_device_get_internal_name(midi_input_device_current)); + if (mpu401_standalone_enable == 0) config_delete_var(cat, "mpu401_standalone"); else diff --git a/src/device.h b/src/device.h index e59952205..dbf9976a2 100644 --- a/src/device.h +++ b/src/device.h @@ -50,6 +50,7 @@ #define CONFIG_HEX16 7 #define CONFIG_HEX20 8 #define CONFIG_MAC 9 +#define CONFIG_MIDI_IN 10 enum { diff --git a/src/plat_midi.h b/src/plat_midi.h index 5070de68a..933e49ee6 100644 --- a/src/plat_midi.h +++ b/src/plat_midi.h @@ -7,3 +7,9 @@ extern int plat_midi_write(uint8_t val); extern int plat_midi_get_num_devs(void); extern void plat_midi_get_dev_name(int num, char *s); + +extern void plat_midi_input_init(void); +extern void plat_midi_input_close(void); + +extern int plat_midi_in_get_num_devs(void); +extern void plat_midi_in_get_dev_name(int num, char *s); diff --git a/src/sound/midi.c b/src/sound/midi.c index 1f5f0ed47..7648c8c92 100644 --- a/src/sound/midi.c +++ b/src/sound/midi.c @@ -8,7 +8,7 @@ * * MIDI device core module. * - * Version: @(#)midi.c 1.0.1 2018/10/10 + * Version: @(#)midi.c 1.0.2 2018/12/31 * * Authors: Sarah Walker, * Miran Grca, @@ -37,28 +37,22 @@ #ifdef USE_MUNT # include "midi_mt32.h" #endif +#include "midi_input.h" -#define SYSEX_SIZE 1024 -#define RAWBUF 1024 - int midi_device_current = 0; static int midi_device_last = 0; +int midi_input_device_current = 0; +static int midi_input_device_last = 0; +midi_t *midi = NULL; -typedef struct -{ - uint8_t midi_rt_buf[1024], midi_cmd_buf[1024], - midi_status, midi_sysex_data[1026]; - int midi_cmd_pos, midi_cmd_len; - unsigned int midi_sysex_start, midi_sysex_delay, - midi_pos; - midi_device_t* m_device; -} midi_t; +void (*input_msg)(uint8_t *msg); +int (*input_sysex)(uint8_t *buffer, uint32_t len, int abort); -static midi_t *midi = NULL; +uint8_t MIDI_InSysexBuf[SYSEX_SIZE]; -static uint8_t MIDI_evt_len[256] = { +uint8_t MIDI_evt_len[256] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x00 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x10 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x20 */ @@ -85,7 +79,7 @@ typedef struct { const char *name, *internal_name; const device_t *device; -} MIDI_DEVICE; +} MIDI_DEVICE, MIDI_IN_DEVICE; static const MIDI_DEVICE devices[] = { @@ -101,6 +95,12 @@ static const MIDI_DEVICE devices[] = {"", "", NULL} }; +static const MIDI_IN_DEVICE midi_in_devices[] = +{ + {"None", "none", NULL}, + {MIDI_INPUT_NAME, MIDI_INPUT_INTERNAL_NAME, &midi_input_device}, + {"", "", NULL} +}; int midi_device_available(int card) @@ -172,16 +172,39 @@ midi_init(midi_device_t* device) midi = (midi_t *) malloc(sizeof(midi_t)); memset(midi, 0, sizeof(midi_t)); - midi->m_device = device; + midi->m_out_device = device; +} + +void +midi_in_init(midi_device_t* device, midi_t **mididev) +{ + *mididev = (midi_t *)malloc(sizeof(midi_t)); + memset(*mididev, 0, sizeof(midi_t)); + + (*mididev)->m_in_device = device; } void midi_close(void) { - if (midi && midi->m_device) { - free(midi->m_device); - midi->m_device = NULL; + if (midi && midi->m_out_device) { + free(midi->m_out_device); + midi->m_out_device = NULL; + } + + if (midi) { + free(midi); + midi = NULL; + } +} + +void +midi_in_close(void) +{ + if (midi && midi->m_in_device) { + free(midi->m_in_device); + midi->m_in_device = NULL; } if (midi) { @@ -194,36 +217,119 @@ midi_close(void) void midi_poll(void) { - if (midi && midi->m_device && midi->m_device->poll) - midi->m_device->poll(); + if (midi && midi->m_out_device && midi->m_out_device->poll) + midi->m_out_device->poll(); } void play_msg(uint8_t *msg) { - if (midi->m_device->play_msg) - midi->m_device->play_msg(msg); + if (midi->m_out_device->play_msg) + midi->m_out_device->play_msg(msg); } void play_sysex(uint8_t *sysex, unsigned int len) { - if (midi->m_device->play_sysex) - midi->m_device->play_sysex(sysex, len); + if (midi->m_out_device->play_sysex) + midi->m_out_device->play_sysex(sysex, len); } +int +midi_in_device_available(int card) +{ + if (midi_in_devices[card].device) + return device_available(midi_in_devices[card].device); + + return 1; +} + +char * +midi_in_device_getname(int card) +{ + return (char *) midi_in_devices[card].name; +} + +const device_t * +midi_in_device_getdevice(int card) +{ + return midi_in_devices[card].device; +} + +int +midi_in_device_has_config(int card) +{ + if (!midi_in_devices[card].device) + return 0; + return midi_in_devices[card].device->config ? 1 : 0; +} + + +char * +midi_in_device_get_internal_name(int card) +{ + return (char *) midi_in_devices[card].internal_name; +} + + +int +midi_in_device_get_from_internal_name(char *s) +{ + int c = 0; + + while (strlen(midi_in_devices[c].internal_name)) { + if (!strcmp(midi_in_devices[c].internal_name, s)) + return c; + c++; + } + + return 0; +} + void -midi_write(uint8_t val) +midi_in_device_init() +{ + if (midi_in_devices[midi_input_device_current].device) + device_add(midi_in_devices[midi_input_device_current].device); + midi_input_device_last = midi_input_device_current; +} + +void +midi_raw_out_rt_byte(uint8_t val) +{ + if (!midi || !midi->m_out_device || !midi->m_in_device) + return; + + if (!midi->midi_realtime) + return; + + if ((!midi->midi_clockout && (val == 0xf8))) + return; + + midi->midi_cmd_r = val << 24; + pclog("Play RT Byte msg\n"); + play_msg((uint8_t *)&midi->midi_cmd_r); +} + +void +midi_raw_out_thru_rt_byte(uint8_t val) +{ + if (midi->thruchan) + midi_raw_out_rt_byte(val); +} + +void +midi_raw_out_byte(uint8_t val) { uint32_t passed_ticks; - if (!midi || !midi->m_device) + if (!midi || !midi->m_out_device) return; - if (midi->m_device->write && midi->m_device->write(val)) + if ((midi->m_out_device->write && midi->m_out_device->write(val))) return; if (midi->midi_sysex_start) { @@ -289,3 +395,12 @@ midi_write(uint8_t val) } } } + +void +midi_clear_buffer(void) +{ + midi->midi_pos = 0; + midi->midi_status = 0x00; + midi->midi_cmd_pos = 0; + midi->midi_cmd_len = 0; +} \ No newline at end of file diff --git a/src/sound/midi.h b/src/sound/midi.h index 6268a0e0c..21441646c 100644 --- a/src/sound/midi.h +++ b/src/sound/midi.h @@ -2,18 +2,34 @@ # define EMU_SOUND_MIDI_H -extern int midi_device_current; +#define SYSEX_SIZE 8192 +extern uint8_t MIDI_InSysexBuf[SYSEX_SIZE]; +extern uint8_t MIDI_evt_len[256]; + +extern int midi_device_current; +extern int midi_input_device_current; + +extern void (*input_msg)(uint8_t *msg); +extern int (*input_sysex)(uint8_t *buffer, uint32_t len, int abort); int midi_device_available(int card); +int midi_in_device_available(int card); char *midi_device_getname(int card); +char *midi_in_device_getname(int card); #ifdef EMU_DEVICE_H const device_t *midi_device_getdevice(int card); +const device_t *midi_in_device_getdevice(int card); #endif int midi_device_has_config(int card); +int midi_in_device_has_config(int card); char *midi_device_get_internal_name(int card); +char *midi_in_device_get_internal_name(int card); int midi_device_get_from_internal_name(char *s); +int midi_in_device_get_from_internal_name(char *s); void midi_device_init(); +void midi_in_device_init(); + typedef struct midi_device_t { @@ -23,9 +39,27 @@ typedef struct midi_device_t int (*write)(uint8_t val); } midi_device_t; +typedef struct midi_t +{ + uint8_t midi_rt_buf[8], midi_cmd_buf[8], + midi_status, midi_sysex_data[SYSEX_SIZE]; + int midi_cmd_pos, midi_cmd_len, midi_cmd_r, + midi_realtime, thruchan, midi_clockout; + unsigned int midi_sysex_start, midi_sysex_delay, + midi_pos; + midi_device_t *m_out_device, *m_in_device; +} midi_t; + +extern midi_t *midi; + void midi_init(midi_device_t* device); +void midi_in_init(midi_device_t* device, midi_t **mididev); void midi_close(); -void midi_write(uint8_t val); +void midi_in_close(void); +void midi_raw_out_rt_byte(uint8_t val); +void midi_raw_out_thru_rt_byte(uint8_t val); +void midi_raw_out_byte(uint8_t val); +void midi_clear_buffer(void); void midi_poll(); #if 0 @@ -41,5 +75,7 @@ void midi_poll(); #define SYSTEM_MIDI_INTERNAL_NAME "system_midi" #endif +#define MIDI_INPUT_NAME "MIDI Input Device" +#define MIDI_INPUT_INTERNAL_NAME "midi_in" #endif /*EMU_SOUND_MIDI_H*/ diff --git a/src/sound/midi_input.h b/src/sound/midi_input.h new file mode 100644 index 000000000..163d6fa91 --- /dev/null +++ b/src/sound/midi_input.h @@ -0,0 +1 @@ +extern const device_t midi_input_device; diff --git a/src/sound/midi_system.c b/src/sound/midi_system.c index d9a15c6a9..f3ace5c69 100644 --- a/src/sound/midi_system.c +++ b/src/sound/midi_system.c @@ -9,6 +9,7 @@ #include "../plat_midi.h" #include "midi.h" #include "midi_system.h" +#include "midi_input.h" void* system_midi_init(const device_t *info) @@ -16,6 +17,8 @@ void* system_midi_init(const device_t *info) midi_device_t* dev = malloc(sizeof(midi_device_t)); memset(dev, 0, sizeof(midi_device_t)); + pclog("MIDI Output\n"); + dev->play_msg = plat_midi_play_msg; dev->play_sysex = plat_midi_play_sysex; dev->write = plat_midi_write; @@ -27,6 +30,24 @@ void* system_midi_init(const device_t *info) return dev; } +void* midi_input_init(const device_t *info) +{ + midi_device_t* dev = malloc(sizeof(midi_device_t)); + memset(dev, 0, sizeof(midi_device_t)); + + pclog("MIDI Input\n"); + + plat_midi_input_init(); + + midi_in_init(dev, &midi); + + midi->midi_realtime = device_get_config_int("realtime"); + midi->thruchan = device_get_config_int("thruchan"); + midi->midi_clockout = device_get_config_int("clockout"); + + return dev; +} + void system_midi_close(void* p) { plat_midi_close(); @@ -34,11 +55,23 @@ void system_midi_close(void* p) midi_close(); } +void midi_input_close(void* p) +{ + plat_midi_input_close(); + + midi_close(); +} + int system_midi_available(void) { return plat_midi_get_num_devs(); } +int midi_input_available(void) +{ + return plat_midi_in_get_num_devs(); +} + static const device_config_t system_midi_config[] = { { @@ -52,6 +85,37 @@ static const device_config_t system_midi_config[] = } }; +static const device_config_t midi_input_config[] = +{ + { + .name = "midi_input", + .description = "MIDI in device", + .type = CONFIG_MIDI_IN, + .default_int = 0 + }, + { + .name = "realtime", + .description = "MIDI Real time", + .type = CONFIG_BINARY, + .default_int = 0 + }, + { + .name = "thruchan", + .description = "MIDI Thru", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { + .name = "clockout", + .description = "MIDI Clockout", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { + .type = -1 + } +}; + const device_t system_midi_device = { SYSTEM_MIDI_NAME, @@ -64,3 +128,17 @@ const device_t system_midi_device = NULL, system_midi_config }; + + +const device_t midi_input_device = +{ + MIDI_INPUT_NAME, + 0, 0, + midi_input_init, + midi_input_close, + NULL, + midi_input_available, + NULL, + NULL, + midi_input_config +}; \ No newline at end of file diff --git a/src/sound/snd_audiopci.c b/src/sound/snd_audiopci.c index c6bbefc6b..f24a383d3 100644 --- a/src/sound/snd_audiopci.c +++ b/src/sound/snd_audiopci.c @@ -13,6 +13,8 @@ #include "../pci.h" #include "../timer.h" #include "sound.h" +#include "midi.h" +#include "snd_mpu401.h" #include "snd_audiopci.h" @@ -23,6 +25,8 @@ static float low_fir_es1371_coef[ES1371_NCoef]; typedef struct { + mpu_t mpu; + uint8_t pci_command, pci_serr; uint32_t base_addr; @@ -116,14 +120,21 @@ typedef struct { #define INT_DAC1_EN (1<<6) #define INT_DAC2_EN (1<<5) +#define INT_UART_EN (1<<3) #define SI_P2_INTR_EN (1<<9) #define SI_P1_INTR_EN (1<<8) #define INT_STATUS_INTR (1<<31) +#define INT_STATUS_UART (1<<3) #define INT_STATUS_DAC1 (1<<2) #define INT_STATUS_DAC2 (1<<1) +#define UART_CTRL_TXINTEN (1<<5) + +#define UART_STATUS_TXINT (1<<2) +#define UART_STATUS_TXRDY (1<<1) + #define FORMAT_MONO_8 0 #define FORMAT_STEREO_8 1 #define FORMAT_MONO_16 2 @@ -164,8 +175,13 @@ static void es1371_update_irqs(es1371_t *es1371) if ((es1371->int_status & INT_STATUS_DAC1) && (es1371->si_cr & SI_P1_INTR_EN)) irq = 1; - if ((es1371->int_status & INT_STATUS_DAC2) && (es1371->si_cr & SI_P2_INTR_EN)) + if ((es1371->int_status & INT_STATUS_DAC2) && (es1371->si_cr & SI_P2_INTR_EN)) { irq = 1; + } + /*MIDI input is unsupported for now*/ + if ((es1371->int_status & INT_STATUS_UART) && (es1371->uart_status & UART_STATUS_TXINT)) { + irq = 1; + } if (irq) es1371->int_status |= INT_STATUS_INTR; @@ -219,10 +235,10 @@ static uint8_t es1371_inb(uint16_t port, void *p) case 0x07: ret = (es1371->int_status >> 24) & 0xff; break; - - + case 0x09: - ret = es1371->uart_status; + ret = es1371->uart_status & 0xc7; + audiopci_log("ES1371 UART Status = %02x\n", es1371->uart_status); break; case 0x0c: @@ -253,7 +269,7 @@ static uint8_t es1371_inb(uint16_t port, void *p) audiopci_log("Bad es1371_inb: port=%04x\n", port); } -// audiopci_log("es1371_inb: port=%04x ret=%02x\n", port, ret); + audiopci_log("es1371_inb: port=%04x ret=%02x\n", port, ret); // output = 3; return ret; } @@ -340,31 +356,51 @@ static uint32_t es1371_inl(uint16_t port, void *p) ret |= CODEC_READY; break; - case 0x34: - switch (es1371->mem_page) - { + case 0x30: + switch (es1371->mem_page) { + case 0xe: case 0xf: + audiopci_log("ES1371 0x30 read UART FIFO: val = %02x\n", ret & 0xff); + break; + } + break; + case 0x34: + switch (es1371->mem_page) { case 0xc: ret = es1371->dac[0].size | (es1371->dac[0].count << 16); break; case 0xd: - ret = es1371->adc.size | (es1371->adc.count << 16); break; + case 0xe: case 0xf: + audiopci_log("ES1371 0x34 read UART FIFO: val = %02x\n", ret & 0xff); + break; + default: audiopci_log("Bad es1371_inl: mem_page=%x port=%04x\n", es1371->mem_page, port); } break; + case 0x38: + switch (es1371->mem_page) { + case 0xe: case 0xf: + audiopci_log("ES1371 0x38 read UART FIFO: val = %02x\n", ret & 0xff); + break; + } + break; + case 0x3c: - switch (es1371->mem_page) - { + switch (es1371->mem_page) { case 0xc: ret = es1371->dac[1].size | (es1371->dac[1].count << 16); break; - + + case 0xe: case 0xf: + audiopci_log("ES1371 0x3c read UART FIFO: val = %02x\n", ret & 0xff); + break; + default: audiopci_log("Bad es1371_inl: mem_page=%x port=%04x\n", es1371->mem_page, port); } @@ -374,7 +410,7 @@ static uint32_t es1371_inl(uint16_t port, void *p) audiopci_log("Bad es1371_inl: port=%04x\n", port); } -// audiopci_log("es1371_inl: port=%04x ret=%08x %08x\n", port, ret, cpu_state.pc); + audiopci_log("es1371_inl: port=%04x ret=%08x\n", port, ret); return ret; } @@ -382,7 +418,7 @@ static void es1371_outb(uint16_t port, uint8_t val, void *p) { es1371_t *es1371 = (es1371_t *)p; -// audiopci_log("es1371_outb: port=%04x val=%02x %04x:%08x\n", port, val, cs, cpu_state.pc); + audiopci_log("es1371_outb: port=%04x val=%02x\n", port, val); switch (port & 0x3f) { case 0x00: @@ -412,8 +448,13 @@ static void es1371_outb(uint16_t port, uint8_t val, void *p) es1371->int_ctrl = (es1371->int_ctrl & 0x00ffffff) | (val << 24); break; + case 0x08: + midi_raw_out_byte(val); + break; + case 0x09: - es1371->uart_ctrl = val; + es1371->uart_ctrl = val & 0xe3; + audiopci_log("ES1371 UART Cntrl = %02x\n", es1371->uart_ctrl); break; case 0x0c: @@ -481,7 +522,7 @@ static void es1371_outl(uint16_t port, uint32_t val, void *p) { es1371_t *es1371 = (es1371_t *)p; -// audiopci_log("es1371_outl: port=%04x val=%08x %04x:%08x\n", port, val, CS, cpu_state.pc); + audiopci_log("es1371_outl: port=%04x val=%08x\n", port, val); switch (port & 0x3f) { case 0x04: @@ -593,6 +634,10 @@ static void es1371_outl(uint16_t port, uint32_t val, void *p) // audiopci_log("DAC1 addr %08x\n", val); break; + case 0xe: case 0xf: + audiopci_log("ES1371 0x30 write UART FIFO: val = %02x\n", val & 0xff); + break; + default: audiopci_log("Bad es1371_outl: mem_page=%x port=%04x val=%08x\n", es1371->mem_page, port, val); } @@ -615,6 +660,10 @@ static void es1371_outl(uint16_t port, uint32_t val, void *p) es1371->adc.count = val >> 16; break; + case 0xe: case 0xf: + audiopci_log("ES1371 0x34 write UART FIFO: val = %02x\n", val & 0xff); + break; + default: audiopci_log("Bad es1371_outl: mem_page=%x port=%04x val=%08x\n", es1371->mem_page, port, val); } @@ -633,6 +682,10 @@ static void es1371_outl(uint16_t port, uint32_t val, void *p) case 0xd: break; + + case 0xe: case 0xf: + audiopci_log("ES1371 0x38 write UART FIFO: val = %02x\n", val & 0xff); + break; default: audiopci_log("Bad es1371_outl: mem_page=%x port=%04x val=%08x\n", es1371->mem_page, port, val); @@ -649,6 +702,10 @@ static void es1371_outl(uint16_t port, uint32_t val, void *p) case 0xc: es1371->dac[1].size = val & 0xffff; es1371->dac[1].count = val >> 16; + break; + + case 0xe: case 0xf: + audiopci_log("ES1371 0x3c write UART FIFO: val = %02x\n", val & 0xff); break; default: @@ -1107,10 +1164,33 @@ static void es1371_poll(void *p) timer_advance_u64(&es1371->dac[1].timer, es1371->dac[1].latch); - es1371_update(es1371); - - if (es1371->int_ctrl & INT_DAC1_EN) - { + es1371_update(es1371); + + if (es1371->int_ctrl & INT_UART_EN) { + audiopci_log("UART INT Enabled\n"); + if (es1371->uart_ctrl & 0x80) { /*We currently don't implement MIDI Input.*/ + /*But if anything sets MIDI Input and Output together we'd have to take account + of the MIDI Output case, and disable IRQ's and RX bits when MIDI Input is enabled as well but not in the MIDI Output portion*/ + if (es1371->uart_ctrl & UART_CTRL_TXINTEN) + es1371->int_status |= INT_STATUS_UART; + else + es1371->int_status &= ~INT_STATUS_UART; + } else if (!(es1371->uart_ctrl & 0x80) && ((es1371->uart_ctrl & UART_CTRL_TXINTEN))) { /*Or enable the UART IRQ and the respective TX bits only when the MIDI Output is enabled*/ + es1371->int_status |= INT_STATUS_UART; + } + + if (es1371->uart_ctrl & 0x80) { + if (es1371->uart_ctrl & UART_CTRL_TXINTEN) + es1371->uart_status |= (UART_STATUS_TXINT | UART_STATUS_TXRDY); + else + es1371->uart_status &= ~(UART_STATUS_TXINT | UART_STATUS_TXRDY); + } else + es1371->uart_status |= (UART_STATUS_TXINT | UART_STATUS_TXRDY); + + es1371_update_irqs(es1371); + } + + if (es1371->int_ctrl & INT_DAC1_EN) { int frac = es1371->dac[0].ac & 0x7fff; int idx = es1371->dac[0].ac >> 15; int samp1_l = es1371->dac[0].filtered_l[idx]; diff --git a/src/sound/snd_mpu401.c b/src/sound/snd_mpu401.c index 15105268f..f30517a2c 100644 --- a/src/sound/snd_mpu401.c +++ b/src/sound/snd_mpu401.c @@ -29,6 +29,7 @@ #define HAVE_STDARG_H #include "../86box.h" #include "../device.h" +#include "../plat.h" #include "../io.h" #include "../machine/machine.h" #include "../mca.h" @@ -38,6 +39,8 @@ #include "snd_mpu401.h" #include "midi.h" +static uint32_t MPUClockBase[8] = {48,72,96,120,144,168,192}; +static uint8_t cth_data[16] = {0,0,0,0,1,0,0,0,1,0,1,0,1,1,1,0}; enum { STATUS_OUTPUT_NOT_READY = 0x40, @@ -48,8 +51,13 @@ enum { int mpu401_standalone_enable = 0; static void MPU401_WriteCommand(mpu_t *mpu, uint8_t val); +static void MPU401_IntelligentOut(mpu_t *mpu, uint8_t track); +static void MPU401_EOIHandler(void *priv); static void MPU401_EOIHandlerDispatch(void *p); +static void MPU401_NotesOff(mpu_t *mpu, int i); +static mpu_t *mpuin; +static mutex_t *mpu_lock; #ifdef ENABLE_MPU401_LOG int mpu401_do_log = ENABLE_MPU401_LOG; @@ -71,8 +79,69 @@ mpu401_log(const char *fmt, ...) #endif +void +mpu401_set_midi_in(mpu_t *src_mpu_in) +{ + mpuin = src_mpu_in; +} + static void -QueueByte(mpu_t *mpu, uint8_t data) +MPU401_ReCalcClock(mpu_t *mpu) +{ + int32_t maxtempo = 240, mintempo = 16; + + if (mpu->clock.timebase >= 168) + maxtempo = 179; + if (mpu->clock.timebase == 144) + maxtempo = 208; + if (mpu->clock.timebase >= 120) + maxtempo = 8; + + mpu->clock.freq = ((uint32_t)(mpu->clock.tempo * 2 * mpu->clock.tempo_rel)) >> 6; + mpu->clock.freq = mpu->clock.timebase * (mpu->clock.freq < (mintempo * 2) ? mintempo : + ((mpu->clock.freq / 2) < maxtempo ? (mpu->clock.freq / 2) : maxtempo)); + + if (mpu->state.sync_in) { + int32_t freq = (int32_t)((float)(mpu->clock.freq) * mpu->clock.freq_mod); + if ((freq > (mpu->clock.timebase * mintempo)) && (freq < (mpu->clock.timebase * maxtempo))) + mpu->clock.freq = freq; + } +} + +static void +MPU401_StartClock(mpu_t *mpu) +{ + if (mpu->clock.active) + return; + if (!(mpu->state.clock_to_host || mpu->state.playing || (mpu->state.rec == M_RECON))) + return; + + mpu->clock.active = 1; + timer_set_delay_u64(&mpu->mpu401_event_callback, (MPU401_TIMECONSTANT / mpu->clock.freq) * 1000 * TIMER_USEC); +} + +static void +MPU401_StopClock(mpu_t *mpu) +{ + if (mpu->state.clock_to_host || mpu->state.playing || (mpu->state.rec == M_RECON)) + return; + mpu->clock.active = 0; + timer_disable(&mpu->mpu401_event_callback); +} + +static void +MPU401_RunClock(mpu_t *mpu) +{ + if (!mpu->clock.active) { + timer_disable(&mpu->mpu401_event_callback); + return; + } + timer_set_delay_u64(&mpu->mpu401_event_callback, (MPU401_TIMECONSTANT / mpu->clock.freq) * 1000 * TIMER_USEC); + mpu401_log("Next event after %i us (time constant: %i)\n", (uint64_t) ((MPU401_TIMECONSTANT/mpu->clock.freq) * 1000 * TIMER_USEC), (int) MPU401_TIMECONSTANT); +} + +static void +MPU401_QueueByte(mpu_t *mpu, uint8_t data) { if (mpu->state.block_ack) { mpu->state.block_ack = 0; @@ -88,22 +157,73 @@ QueueByte(mpu_t *mpu, uint8_t data) if (mpu->queue_pos >= MPU401_QUEUE) mpu->queue_pos -= MPU401_QUEUE; - if (pos>=MPU401_QUEUE) pos-=MPU401_QUEUE; mpu->queue_used++; mpu->queue[pos] = data; - } else - mpu401_log("MPU401:Data queue full\n"); + } } +static void +MPU401_RecQueueBuffer(mpu_t *mpu, uint8_t *buf, uint32_t len, int block) +{ + uint32_t cnt; + + if (block) { + if (mpu_lock) + thread_wait_mutex(mpu_lock); + else + return; + } + + cnt = 0; + while (cnt < len) { + if (mpu->rec_queue_used < MPU401_INPUT_QUEUE) { + int pos = mpu->rec_queue_used + mpu->rec_queue_pos; + if (pos >= MPU401_INPUT_QUEUE) + pos -= MPU401_INPUT_QUEUE; + mpu->rec_queue[pos] = buf[cnt]; + mpu->rec_queue_used++; + if ((!mpu->state.sysex_in_finished) && (buf[cnt] == MSG_EOX)) { /*finish sysex*/ + mpu->state.sysex_in_finished = 1; + break; + } + cnt++; + } + } + + if (mpu->queue_used == 0) { + if (mpu->state.rec_copy || mpu->state.irq_pending) { + if (block && mpu_lock) + thread_release_mutex(mpu_lock); + if (mpu->state.irq_pending) { + picintc(1 << mpu->irq); + mpu->state.irq_pending = 0; + } + return; + } + mpu->state.rec_copy = 1; + if (mpu->rec_queue_pos >= MPU401_INPUT_QUEUE) + mpu->rec_queue_pos -= MPU401_INPUT_QUEUE; + MPU401_QueueByte(mpu, mpu->rec_queue[mpu->rec_queue_pos]); + mpu->rec_queue_used--; + mpu->rec_queue_pos++; + } + + if (block && mpu_lock) + thread_release_mutex(mpu_lock); +} static void -ClrQueue(mpu_t *mpu) +MPU401_ClrQueue(mpu_t *mpu) { - mpu->queue_used=0; - mpu->queue_pos=0; + mpu->queue_used = 0; + mpu->queue_pos = 0; + mpu->rec_queue_used = 0; + mpu->rec_queue_pos = 0; + mpu->state.sysex_in_finished = 1; + mpu->state.irq_pending = 0; } @@ -116,8 +236,10 @@ MPU401_Reset(mpu_t *mpu) picintc(1 << mpu->irq); mpu->state.irq_pending = 0; } - + mpu->mode = M_INTELLIGENT; + mpu->midi_thru = 0; + mpu->state.rec = M_RECOFF; mpu->state.eoi_scheduled = 0; mpu->state.wsd = 0; mpu->state.wsm = 0; @@ -129,27 +251,64 @@ MPU401_Reset(mpu_t *mpu) mpu->state.cmask = 0xff; mpu->state.amask = mpu->state.tmask = 0; mpu->state.midi_mask = 0xffff; - mpu->state.data_onoff = 0; mpu->state.command_byte = 0; mpu->state.block_ack = 0; mpu->clock.tempo = mpu->clock.old_tempo = 100; mpu->clock.timebase = mpu->clock.old_timebase = 120; - mpu->clock.tempo_rel = mpu->clock.old_tempo_rel = 40; + mpu->clock.tempo_rel = mpu->clock.old_tempo_rel = 0x40; + mpu->clock.freq_mod = 1.0; mpu->clock.tempo_grad = 0; - mpu->clock.clock_to_host = 0; - mpu->clock.cth_rate = 60; + MPU401_StopClock(mpu); + MPU401_ReCalcClock(mpu); + + for (i = 0; i < 4; i++) + mpu->clock.cth_rate[i] = 60; + mpu->clock.cth_counter = 0; + mpu->clock.midimetro = 12; + mpu->clock.metromeas = 8; + mpu->filter.rec_measure_end = 1; + mpu->filter.rt_out = 1; + mpu->filter.rt_affection = 1; + mpu->filter.allnotesoff_out = 1; + mpu->filter.all_thru = 1; + mpu->filter.midi_thru = 1; + mpu->filter.commonmsgs_thru = 1; - ClrQueue(mpu); + /*reset channel reference and input tables*/ + for (i = 0; i < 4; i++) { + mpu->chanref[i].on = 1; + mpu->chanref[i].chan = i; + mpu->ch_toref[i] = i; + } + + for (i = 0; i < 16; i++) { + mpu->inputref[i].on = 1; + mpu->inputref[i].chan = i; + if (i > 3) + mpu->ch_toref[i] = 4;/*dummy reftable*/ + } + + MPU401_ClrQueue(mpu); + mpu->state.data_onoff = -1; mpu->state.req_mask = 0; - mpu->condbuf.counter = 0; + mpu->condbuf.counter = 0; mpu->condbuf.type = T_OVERFLOW; for (i=0;i<8;i++) { mpu->playbuf[i].type = T_OVERFLOW; mpu->playbuf[i].counter = 0; } + + /*clear MIDI buffers, terminate notes*/ + midi_clear_buffer(); + + for (i = 0xb0; i <= 0xbf; i++) { + midi_raw_out_byte(i); + midi_raw_out_byte(0x7b); + midi_raw_out_byte(0); + } } @@ -163,6 +322,7 @@ MPU401_ResetDone(void *priv) timer_disable(&mpu->mpu401_reset_callback); mpu->state.reset = 0; + if (mpu->state.cmd_pending) { MPU401_WriteCommand(mpu, mpu->state.cmd_pending - 1); mpu->state.cmd_pending = 0; @@ -173,160 +333,281 @@ MPU401_ResetDone(void *priv) static void MPU401_WriteCommand(mpu_t *mpu, uint8_t val) { - uint8_t i, was_uart; + uint8_t i, j, was_uart; if (mpu->state.reset) mpu->state.cmd_pending = val + 1; if ((val != 0x3f) && (val != 0xff) && !mpu->intelligent) - return; + return; - if (val <= 0x2f) { - switch (val&3) { /* MIDI stop, start, continue */ - case 1: - midi_write(0xfc); - break; + thread_wait_mutex(mpu_lock); - case 2: - midi_write(0xfa); - break; + /*hack:enable midi through after the first mpu401 command is written*/ + mpu->midi_thru = 1; - case 3: - midi_write(0xfb); - break; + if (val <= 0x2f) { /* Sequencer state */ + int send_prchg = 0; + if ((val & 0xf) < 0xc) { + switch (val & 3) { /* MIDI realtime messages */ + case 1: + mpu->state.last_rtcmd = 0xfc; + if (mpu->filter.rt_out) + midi_raw_out_rt_byte(0xfc); + mpu->clock.meas_old = mpu->clock.measure_counter; + mpu->clock.cth_old = mpu->clock.cth_counter; + break; + case 2: + mpu->state.last_rtcmd = 0xfa; + if (mpu->filter.rt_out) + midi_raw_out_rt_byte(0xfb); + mpu->clock.measure_counter = mpu->clock.meas_old = 0; + mpu->clock.cth_counter = mpu->clock.cth_old = 0; + break; + case 3: + mpu->state.last_rtcmd = 0xfc; + if (mpu->filter.rt_out) + midi_raw_out_rt_byte(0xfa); + mpu->clock.measure_counter = mpu->clock.meas_old; + mpu->clock.cth_counter = mpu->clock.cth_old; + break; + } + switch (val & 0xc) { /* Playing */ + case 0x4: /* Stop */ + mpu->state.playing = 0; + MPU401_StopClock(mpu); + for (i = 0; i < 16; i++) + MPU401_NotesOff(mpu, i); + mpu->filter.prchg_mask = 0; + break; + case 0x8: /* Start */ + mpu->state.playing = 1; + MPU401_StartClock(mpu); + break; + } + switch (val & 0x30) { /* Recording */ + case 0: /* check if it waited for MIDI RT command */ + if (((val & 3) < 2) || !mpu->filter.rt_affection || (mpu->state.rec != M_RECSTB)) + break; + mpu->state.rec = M_RECON; + MPU401_StartClock(mpu); + if (mpu->filter.prchg_mask) + send_prchg = 1; + break; + case 0x10: /* Stop */ + mpu->state.rec = M_RECOFF; + MPU401_StopClock(mpu); + MPU401_QueueByte(mpu, MSG_MPU_ACK); + MPU401_QueueByte(mpu, mpu->clock.rec_counter); + MPU401_QueueByte(mpu, MSG_MPU_END); + mpu->filter.prchg_mask = 0; + mpu->clock.rec_counter = 0; + thread_release_mutex(mpu_lock); + return; + case 0x20: /* Start */ + if (!(mpu->state.rec == M_RECON)) { + mpu->clock.rec_counter = 0; + mpu->state.rec = M_RECSTB; + } + if ((mpu->state.last_rtcmd == 0xfa) || (mpu->state.last_rtcmd == 0xfb)) { + mpu->clock.rec_counter = 0; + mpu->state.rec = M_RECON; + if (mpu->filter.prchg_mask) + send_prchg = 1; + MPU401_StartClock(mpu); + } + } } - - switch (val & 0xc) { - case 0x4: /* Stop */ - mpu->state.playing = 0; - timer_disable(&mpu->mpu401_event_callback); - - for (i = 0xb0; i < 0xbf; i++) { - /* All notes off */ - midi_write(i); - midi_write(0x7b); - midi_write(0); - } - break; - - case 0x8: /* Play */ - mpu->state.playing = 1; - timer_set_delay_u64(&mpu->mpu401_event_callback, (MPU401_TIMECONSTANT / (mpu->clock.tempo*mpu->clock.timebase)) * 1000 * TIMER_USEC); - ClrQueue(mpu); - break; + MPU401_QueueByte(mpu, MSG_MPU_ACK); + /* record counter hack: needed by Prism, but sent only on cmd 0x20/0x26 (or breaks Ballade) */ + uint8_t rec_cnt = mpu->clock.rec_counter; + if (((val == 0x20) || (val == 0x26)) && (mpu->state.rec == M_RECON)) + MPU401_RecQueueBuffer(mpu, &rec_cnt, 1, 0); + + if (send_prchg) for (i = 0; i < 16; i++) + if (mpu->filter.prchg_mask & (1 << i)) { + uint8_t recmsg[3] = {mpu->clock.rec_counter, 0xc0 | i, mpu->filter.prchg_buf[i]}; + MPU401_RecQueueBuffer(mpu, recmsg, 3, 0); + mpu->filter.prchg_mask &= ~(1 << i); } + thread_release_mutex(mpu_lock); } else if ((val >= 0xa0) && (val <= 0xa7)) { /* Request play counter */ - if (mpu->state.cmask & (1 << (val&7))) - QueueByte(mpu, mpu->playbuf[val&7].counter); + MPU401_QueueByte(mpu, mpu->playbuf[val & 7].counter); } else if ((val >= 0xd0) && (val <= 0xd7)) { /* Send data */ - mpu->state.old_chan = mpu->state.channel; - mpu->state.channel= val & 7; + mpu->state.old_track = mpu->state.track; + mpu->state.track= val & 7; mpu->state.wsd = 1; mpu->state.wsm = 0; mpu->state.wsd_start = 1; + } else if ((val < 0x80) && (val >= 0x40)) { /* Set reference table channel */ + mpu->chanref[(val >> 4) - 4].on = 1; + mpu->chanref[(val >> 4) - 4].chan = val & 0x0f; + mpu->chanref[(val >> 4) - 4].trmask = 0; + for (i = 0; i < 4; i++) + mpu->chanref[(val >> 4) - 4].key[i] = 0; + for (i = 0; i < 16; i++) { + if (mpu->ch_toref[i] == ((val >> 4) - 4)) + mpu->ch_toref[i] = 4; + } + mpu->ch_toref[val & 0x0f] = (val >> 4) - 4; } else switch (val) { - case 0xdf: /* Send system message */ - mpu->state.wsd = 0; - mpu->state.wsm = 1; - mpu->state.wsd_start = 1; + case 0x30: /* Configuration 0x30 - 0x39 */ + mpu->filter.allnotesoff_out = 0; break; - - case 0x8e: /* Conductor */ - mpu->state.cond_set = 0; + case 0x32: + mpu->filter.rt_out = 0; break; - - case 0x8f: - mpu->state.cond_set = 1; + case 0x33: + mpu->filter.all_thru = 0; + mpu->filter.commonmsgs_thru = 0; + mpu->filter.midi_thru = 0; + for (i = 0; i < 16; i++) { + mpu->inputref[i].on = 0; + for (j = 0; i < 4; j++) + mpu->inputref[i].key[j] = 0; + } + break; + case 0x34: + mpu->filter.timing_in_stop = 1; + break; + case 0x35: + mpu->filter.modemsgs_in = 1; + break; + case 0x37: + mpu->filter.sysex_thru = 1; + break; + case 0x38: + mpu->filter.commonmsgs_in = 1; + break; + case 0x39: + mpu->filter.rt_in = 1; + break; + case 0x3f: /* UART mode */ + mpu401_log("MPU-401:Set UART mode %X\n",val); + MPU401_QueueByte(mpu, MSG_MPU_ACK); + mpu->mode = M_UART; + return; + case 0x80: /* Internal clock */ + if (mpu->clock.active && mpu->state.sync_in) { + timer_set_delay_u64(&mpu->mpu401_event_callback, (MPU401_TIMECONSTANT / mpu->clock.freq) * 1000 * TIMER_USEC); + mpu->clock.freq_mod = 1.0; + } + mpu->state.sync_in = 0; + break; + case 0x81: /* Sync to tape signal */ + case 0x82: /* Sync to MIDI */ + mpu->clock.ticks_in = 0; + mpu->state.sync_in = 1; + break; + case 0x86: case 0x87: /* Bender */ + mpu->filter.bender_in = !!(val & 1); + break; + case 0x88: case 0x89: /* MIDI through */ + mpu->filter.midi_thru = !!(val & 1); + for (i = 0; i < 16; i++) { + mpu->inputref[i].on = mpu->filter.midi_thru; + if (!(val & 1)) { + for (j = 0; j < 4; j++) + mpu->inputref[i].key[j] = 0; + } + } + break; + case 0x8a: case 0x8b: /* Data in stop */ + mpu->filter.data_in_stop = !!(val & 1); + break; + case 0x8c: case 0x8d: /* Send measure end */ + mpu->filter.rec_measure_end = !!(val & 1); + break; + case 0x8e: case 0x8f: /* Conductor */ + mpu->state.cond_set = !!(val & 1); + break; + case 0x90: case 0x91: /* Realtime affection */ + mpu->filter.rt_affection = !!(val & 1); break; - case 0x94: /* Clock to host */ - mpu->clock.clock_to_host = 0; + mpu->state.clock_to_host = 0; + MPU401_StopClock(mpu); break; - case 0x95: - mpu->clock.clock_to_host = 1; + mpu->state.clock_to_host = 1; + MPU401_StartClock(mpu); break; - - case 0xc2: /* Internal timebase */ - mpu->clock.timebase = 48; + case 0x96: case 0x97: /* Sysex input allow */ + mpu->filter.sysex_in = !!(val & 1); + if (val & 1) + mpu->filter.sysex_thru = 0; break; - - case 0xc3: - mpu->clock.timebase = 72; + case 0x98: case 0x99: case 0x9a: case 0x9b: /* Reference tables on/off */ + case 0x9c: case 0x9d: case 0x9e: case 0x9f: + mpu->chanref[(val - 0x98) / 2].on = !!(val & 1); break; - - case 0xc4: - mpu->clock.timebase = 96; - break; - - case 0xc5: - mpu->clock.timebase = 120; - break; - - case 0xc6: - mpu->clock.timebase = 144; - break; - - case 0xc7: - mpu->clock.timebase = 168; - break; - case 0xc8: - mpu->clock.timebase = 192; - break; - - /* Commands with data byte */ - case 0xe0: case 0xe1: case 0xe2: case 0xe4: case 0xe6: - case 0xe7: case 0xec: case 0xed: case 0xee: case 0xef: - mpu->state.command_byte = val; - break; - /* Commands 0xa# returning data */ case 0xab: /* Request and clear recording counter */ - QueueByte(mpu, MSG_MPU_ACK); - QueueByte(mpu, 0); + MPU401_QueueByte(mpu, MSG_MPU_ACK); + MPU401_QueueByte(mpu, 0); + thread_release_mutex(mpu_lock); return; - case 0xac: /* Request version */ - QueueByte(mpu, MSG_MPU_ACK); - QueueByte(mpu, MPU401_VERSION); + MPU401_QueueByte(mpu, MSG_MPU_ACK); + MPU401_QueueByte(mpu, MPU401_VERSION); + thread_release_mutex(mpu_lock); return; - case 0xad: /* Request revision */ - QueueByte(mpu, MSG_MPU_ACK); - QueueByte(mpu, MPU401_REVISION); + MPU401_QueueByte(mpu, MSG_MPU_ACK); + MPU401_QueueByte(mpu, MPU401_REVISION); + thread_release_mutex(mpu_lock); return; - case 0xaf: /* Request tempo */ - QueueByte(mpu, MSG_MPU_ACK); - QueueByte(mpu, mpu->clock.tempo); + MPU401_QueueByte(mpu, MSG_MPU_ACK); + MPU401_QueueByte(mpu, mpu->clock.tempo); + thread_release_mutex(mpu_lock); return; - case 0xb1: /* Reset relative tempo */ mpu->clock.old_tempo_rel = mpu->clock.tempo_rel; - mpu->clock.tempo_rel = 40; + mpu->clock.tempo_rel = 0x40; break; - - case 0xb9: /* Clear play map */ case 0xb8: /* Clear play counters */ - for (i = 0xb0; i < 0xbf; i++) { - /* All notes off */ - midi_write(i); - midi_write(0x7b); - midi_write(0); - } + mpu->state.last_rtcmd = 0; for (i = 0; i < 8; i++) { mpu->playbuf[i].counter = 0; mpu->playbuf[i].type = T_OVERFLOW; } mpu->condbuf.counter = 0; mpu->condbuf.type = T_OVERFLOW; - if (!(mpu->state.conductor=mpu->state.cond_set)) - mpu->state.cond_req = 0; mpu->state.amask = mpu->state.tmask; - mpu->state.req_mask = 0; - mpu->state.irq_pending = 1; + mpu->state.conductor = mpu->state.cond_set; + mpu->clock.cth_counter = mpu->clock.cth_old = 0; + mpu->clock.measure_counter = mpu->clock.meas_old = 0; + break; + case 0xb9: /* Clear play map */ + for (i = 0; i < 16; i++) + MPU401_NotesOff(mpu, i); + for (i = 0; i < 8; i++) { + mpu->playbuf[i].counter = 0; + mpu->playbuf[i].type = T_OVERFLOW; + } + mpu->state.last_rtcmd = 0; + mpu->clock.cth_counter = mpu->clock.cth_old = 0; + mpu->clock.measure_counter = mpu->clock.meas_old = 0; + break; + case 0xba: /* Clear record counter */ + mpu->clock.rec_counter = 0; + break; + case 0xc2: case 0xc3: case 0xc4: /* Internal timebase */ + case 0xc5: case 0xc6: case 0xc7: case 0xc8: + mpu->clock.timebase = MPUClockBase[val-0xc2]; + MPU401_ReCalcClock(mpu); + break; + case 0xdf: /* Send system message */ + mpu->state.wsd = 0; + mpu->state.wsm = 1; + mpu->state.wsd_start = 1; + break; + /* Commands with data byte */ + case 0xe0: case 0xe1: case 0xe2: case 0xe4: case 0xe6: + case 0xe7: case 0xec: case 0xed: case 0xee: case 0xef: + mpu->state.command_byte = val; break; - case 0xff: /* Reset MPU-401 */ mpu401_log("MPU-401:Reset %X\n",val); timer_set_delay_u64(&mpu->mpu401_reset_callback, MPU401_RESETBUSY * 33LL * TIMER_USEC); @@ -337,27 +618,23 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) return; /* do not send ack in UART mode */ break; - case 0x3f: /* UART mode */ - mpu401_log("MPU-401:Set UART mode %X\n",val); - QueueByte(mpu, MSG_MPU_ACK); - mpu->mode = M_UART; - return; - /* default: mpu401_log("MPU-401:Unhandled command %X",val); */ } - QueueByte(mpu, MSG_MPU_ACK); + MPU401_QueueByte(mpu, MSG_MPU_ACK); + thread_release_mutex(mpu_lock); } static void MPU401_WriteData(mpu_t *mpu, uint8_t val) { - static int length, cnt, posd; + static int length, cnt; + uint8_t i; if (mpu->mode == M_UART) { - midi_write(val); + midi_raw_out_byte(val); return; } @@ -369,39 +646,55 @@ MPU401_WriteData(mpu_t *mpu, uint8_t val) switch (mpu->state.command_byte) { /* 0xe# command data */ case 0x00: break; - case 0xe0: /* Set tempo */ mpu->state.command_byte = 0; - mpu->clock.tempo = val; + if (mpu->clock.tempo < 8) + mpu->clock.tempo = 8; + else if (mpu->clock.tempo > 250) + mpu->clock.tempo = 250; + else + mpu->clock.tempo = val; + MPU401_ReCalcClock(mpu); return; - case 0xe1: /* Set relative tempo */ mpu->state.command_byte = 0; mpu->clock.old_tempo_rel = mpu->clock.tempo_rel; mpu->clock.tempo_rel = val; + MPU401_ReCalcClock(mpu); return; - + case 0xe2: /* Set gradation for relative tempo */ + mpu->clock.tempo_grad = val; + MPU401_ReCalcClock(mpu); + return; + case 0xe4: /* Set MIDI clocks for metronome ticks */ + mpu->state.command_byte = 0; + mpu->clock.midimetro = val; + return; + case 0xe6: /* Set metronome ticks per measure */ + mpu->state.command_byte = 0; + mpu->clock.metromeas = val; + return; case 0xe7: /* Set internal clock to host interval */ mpu->state.command_byte = 0; - mpu->clock.cth_rate = val >> 2; + if (!val) + val = 64; + for (i = 0; i < 4; i++) + mpu->clock.cth_rate[i] = (val >> 2) + cth_data[(val & 3) * 4 + i]; + mpu->clock.cth_mode = 0; return; - case 0xec: /* Set active track mask */ mpu->state.command_byte = 0; mpu->state.tmask = val; return; - case 0xed: /* Set play counter mask */ mpu->state.command_byte = 0; mpu->state.cmask = val; return; - case 0xee: /* Set 1-8 MIDI channel mask */ mpu->state.command_byte = 0; mpu->state.midi_mask &= 0xff00; mpu->state.midi_mask |= val; return; - case 0xef: /* Set 9-16 MIDI channel mask */ mpu->state.command_byte = 0; mpu->state.midi_mask &= 0x00ff; @@ -413,53 +706,49 @@ MPU401_WriteData(mpu_t *mpu, uint8_t val) return; } - if (mpu->state.wsd) { + if (mpu->state.wsd && !mpu->state.track_req && !mpu->state.cond_req) { /* Directly send MIDI message */ if (mpu->state.wsd_start) { mpu->state.wsd_start = 0; cnt = 0; switch (val & 0xf0) { case 0xc0: case 0xd0: - mpu->playbuf[mpu->state.channel].value[0] = val; - length = 2; + length = mpu->playbuf[mpu->state.track].length = 2; + mpu->playbuf[mpu->state.track].type = T_MIDI_NORM; break; - case 0x80: case 0x90: case 0xa0: case 0xb0:case 0xe0: - mpu->playbuf[mpu->state.channel].value[0] = val; - length = 3; + length = mpu->playbuf[mpu->state.track].length = 3; + mpu->playbuf[mpu->state.track].type = T_MIDI_NORM; break; case 0xf0: /* mpu401_log("MPU-401:Illegal WSD byte\n"); */ mpu->state.wsd = 0; - mpu->state.channel = mpu->state.old_chan; + mpu->state.track = mpu->state.old_track; return; default: /* MIDI with running status */ cnt++; - midi_write(mpu->playbuf[mpu->state.channel].value[0]); + length = mpu->playbuf[mpu->state.track].length; + mpu->playbuf[mpu->state.track].type = T_MIDI_NORM; } } if (cnt < length) { - midi_write(val); + mpu->playbuf[mpu->state.track].value[cnt] = val; cnt++; } if (cnt == length) { + MPU401_IntelligentOut(mpu, mpu->state.track); mpu->state.wsd = 0; - mpu->state.channel = mpu->state.old_chan; + mpu->state.track = mpu->state.old_track; } return; } - if (mpu->state.wsm) { /* Directly send system message */ - if (val == MSG_EOX) { - midi_write(MSG_EOX); - mpu->state.wsm = 0; - return; - } + if (mpu->state.wsm && !mpu->state.track_req && !mpu->state.cond_req) { /* Send system message */ if (mpu->state.wsd_start) { mpu->state.wsd_start = 0; cnt = 0; @@ -481,12 +770,17 @@ MPU401_WriteData(mpu_t *mpu, uint8_t val) break; default: - length = 0; + mpu->state.wsm = 0; + return; } + } else if (val & 0x80) { + midi_raw_out_byte(MSG_EOX); + mpu->state.wsm = 0; + return; } if (!length || (cnt < length)) { - midi_write(val); + midi_raw_out_byte(val); cnt++; } @@ -496,130 +790,179 @@ MPU401_WriteData(mpu_t *mpu, uint8_t val) return; } + thread_wait_mutex(mpu_lock); + if (mpu->state.cond_req) { /* Command */ switch (mpu->state.data_onoff) { case -1: + thread_release_mutex(mpu_lock); return; - case 0: /* Timing byte */ - mpu->condbuf.vlength = 0; + mpu->condbuf.length = 0; if (val < 0xf0) mpu->state.data_onoff++; else { + mpu->state.cond_req = 0; mpu->state.data_onoff = -1; MPU401_EOIHandlerDispatch(mpu); - return; + break; } - mpu->state.send_now = !val ? 1 : 0; mpu->condbuf.counter = val; break; - case 1: /* Command byte #1 */ mpu->condbuf.type = T_COMMAND; - if ((val == 0xf8) || (val == 0xf9)) + if ((val == 0xf8) || (val == 0xf9) || (val == 0xfc)) mpu->condbuf.type = T_OVERFLOW; - mpu->condbuf.value[mpu->condbuf.vlength] = val; - mpu->condbuf.vlength++; - if ((val & 0xf0) != 0xe0) - MPU401_EOIHandlerDispatch(mpu); - else + mpu->condbuf.value[mpu->condbuf.length] = val; + mpu->condbuf.length++; + if ((val & 0xf0) != 0xe0) { /*no cmd data byte*/ + MPU401_EOIHandler(mpu); + mpu->state.data_onoff = -1; + mpu->state.cond_req = 0; + } else mpu->state.data_onoff++; break; case 2:/* Command byte #2 */ - mpu->condbuf.value[mpu->condbuf.vlength]=val; - mpu->condbuf.vlength++; - MPU401_EOIHandlerDispatch(mpu); + mpu->condbuf.value[mpu->condbuf.length]=val; + mpu->condbuf.length++; + MPU401_EOIHandler(mpu); + mpu->state.data_onoff = -1; + mpu->state.cond_req = 0; break; } + thread_release_mutex(mpu_lock); return; } switch (mpu->state.data_onoff) { /* Data */ case -1: - return; - + break; case 0: /* Timing byte */ if (val < 0xf0) - mpu->state.data_onoff = 1; + mpu->state.data_onoff++; else { mpu->state.data_onoff = -1; MPU401_EOIHandlerDispatch(mpu); + mpu->state.track_req = 0; + thread_release_mutex(mpu_lock); return; } mpu->state.send_now = !val ? 1 : 0; - mpu->playbuf[mpu->state.channel].counter = val; + mpu->playbuf[mpu->state.track].counter = val; break; - case 1: /* MIDI */ - mpu->playbuf[mpu->state.channel].vlength++; - posd=mpu->playbuf[mpu->state.channel].vlength; - if (posd == 1) switch (val&0xf0) { + cnt = 0; + mpu->state.data_onoff++; + switch (val & 0xf0) { + case 0xc0: case 0xd0: /* MIDI Message */ + length = mpu->playbuf[mpu->state.track].length = 2; + mpu->playbuf[mpu->state.track].type = T_MIDI_NORM; + break; + case 0x80: case 0x90: case 0xa0: case 0xb0: case 0xe0: + length = mpu->playbuf[mpu->state.track].length = 3; + mpu->playbuf[mpu->state.track].type = T_MIDI_NORM; + break; case 0xf0: /* System message or mark */ + mpu->playbuf[mpu->state.track].sys_val = val; if (val > 0xf7) { - mpu->playbuf[mpu->state.channel].type = T_MARK; - mpu->playbuf[mpu->state.channel].sys_val = val; + mpu->playbuf[mpu->state.track].type = T_MARK; + if (val == 0xf9) + mpu->clock.measure_counter = 0; } else { /* mpu401_log("MPU-401:Illegal message"); */ - mpu->playbuf[mpu->state.channel].type = T_MIDI_SYS; - mpu->playbuf[mpu->state.channel].sys_val = val; + mpu->playbuf[mpu->state.track].type = T_OVERFLOW; } - length = 1; - break; - - case 0xc0: case 0xd0: /* MIDI Message */ - mpu->playbuf[mpu->state.channel].type = T_MIDI_NORM; - length = mpu->playbuf[mpu->state.channel].length = 2; - break; - - case 0x80: case 0x90: case 0xa0: case 0xb0: case 0xe0: - mpu->playbuf[mpu->state.channel].type = T_MIDI_NORM; - length = mpu->playbuf[mpu->state.channel].length = 3; - break; - - default: /* MIDI data with running status */ - posd++; - mpu->playbuf[mpu->state.channel].vlength++; - mpu->playbuf[mpu->state.channel].type = T_MIDI_NORM; - length = mpu->playbuf[mpu->state.channel].length; + mpu->state.data_onoff = -1; + MPU401_EOIHandler(mpu); + mpu->state.track_req = 0; + thread_release_mutex(mpu_lock); + return; + default: /* MIDI with running status */ + cnt++; + length = mpu->playbuf[mpu->state.track].length; + mpu->playbuf[mpu->state.track].type = T_MIDI_NORM; break; } - - if (!((posd == 1) && (val >= 0xf0))) - mpu->playbuf[mpu->state.channel].value[posd-1] = val; - if (posd == length) - MPU401_EOIHandlerDispatch(mpu); + break; + case 2: + if (cnt < length) { + mpu->playbuf[mpu->state.track].value[cnt] = val; + cnt++; + } + if (cnt == length) { + mpu->state.data_onoff = -1; + mpu->state.track_req = 0; + MPU401_EOIHandler(mpu); + } + break; } + + thread_release_mutex(mpu_lock); + return; } static void -MPU401_IntelligentOut(mpu_t *mpu, uint8_t chan) +MPU401_IntelligentOut(mpu_t *mpu, uint8_t track) { - uint8_t val; + uint8_t chan, chrefnum, key, msg; + int send, retrigger; uint8_t i; - switch (mpu->playbuf[chan].type) { + switch (mpu->playbuf[track].type) { case T_OVERFLOW: break; case T_MARK: - val=mpu->playbuf[chan].sys_val; - if (val==0xfc) { - midi_write(val); - mpu->state.amask &= ~(1<state.req_mask &= ~(1<playbuf[track].sys_val == 0xfc) { + midi_raw_out_rt_byte(mpu->playbuf[track].sys_val); + mpu->state.amask&=~(1<playbuf[chan].vlength; i++) - midi_write(mpu->playbuf[chan].value[i]); + chan = mpu->playbuf[track].value[0] & 0xf; + key = mpu->playbuf[track].value[1] & 0x7f; + chrefnum = mpu->ch_toref[chan]; + send = 1; + retrigger = 0; + switch (msg = mpu->playbuf[track].value[0] & 0xf0) { + case 0x80: /* note off */ + if (mpu->inputref[chan].on && (mpu->inputref[chan].M_GETKEY)) + send = 0; + if (mpu->chanref[chrefnum].on && (!(mpu->chanref[chrefnum].M_GETKEY))) + send = 0; + mpu->chanref[chrefnum].M_DELKEY; + break; + case 0x90: /* note on */ + if (mpu->inputref[chan].on && (mpu->inputref[chan].M_GETKEY)) + retrigger = 1; + if (mpu->chanref[chrefnum].on && (!(mpu->chanref[chrefnum].M_GETKEY))) + retrigger = 1; + mpu->chanref[chrefnum].M_SETKEY; + break; + case 0xb0: + if (mpu->playbuf[track].value[1] == 123) { /* All notes off */ + MPU401_NotesOff(mpu, mpu->playbuf[track].value[0] & 0xf); + return; + } + break; + } + if (retrigger) { + midi_raw_out_byte(0x80 | chan); + midi_raw_out_byte(key); + midi_raw_out_byte(0); + } + if (send) { + for (i = 0; i < mpu->playbuf[track].length; i++) + midi_raw_out_byte(mpu->playbuf[track].value[i]); + } break; - + default: break; } @@ -627,15 +970,14 @@ MPU401_IntelligentOut(mpu_t *mpu, uint8_t chan) static void -UpdateTrack(mpu_t *mpu, uint8_t chan) +UpdateTrack(mpu_t *mpu, uint8_t track) { - MPU401_IntelligentOut(mpu, chan); + MPU401_IntelligentOut(mpu, track); - if (mpu->state.amask&(1<playbuf[chan].vlength = 0; - mpu->playbuf[chan].type = T_OVERFLOW; - mpu->playbuf[chan].counter = 0xf0; - mpu->state.req_mask |= (1 << chan); + if (mpu->state.amask&(1<playbuf[track].type = T_OVERFLOW; + mpu->playbuf[track].counter = 0xf0; + mpu->state.req_mask |= (1 << track); } else { if ((mpu->state.amask == 0) && !mpu->state.conductor) mpu->state.req_mask |= (1 << 12); @@ -643,6 +985,7 @@ UpdateTrack(mpu_t *mpu, uint8_t chan) } +#if 0 static void UpdateConductor(mpu_t *mpu) { @@ -659,6 +1002,7 @@ UpdateConductor(mpu_t *mpu) mpu->condbuf.counter = 0xf0; mpu->state.req_mask |= (1 << 9); } +#endif /* Updates counters and requests new data on "End of Input" */ @@ -674,19 +1018,24 @@ MPU401_EOIHandler(void *priv) mpu->state.eoi_scheduled = 0; if (mpu->state.send_now) { mpu->state.send_now = 0; - if (mpu->state.cond_req) UpdateConductor(mpu); - else UpdateTrack(mpu, mpu->state.channel); + if (mpu->state.cond_req) { + mpu->condbuf.counter = 0xf0; + mpu->state.req_mask |= (1 << 9); + } else UpdateTrack(mpu, mpu->state.track); } + if (mpu->state.rec_copy || !mpu->state.sysex_in_finished) + return; + mpu->state.irq_pending = 0; - if (!mpu->state.playing || !mpu->state.req_mask) + if (!(mpu->state.req_mask && mpu->clock.active)) return; i = 0; do { if (mpu->state.req_mask & (1 << i)) { - QueueByte(mpu, 0xf0 + i); + MPU401_QueueByte(mpu, 0xf0 + i); mpu->state.req_mask &= ~(1 << i); break; } @@ -702,7 +1051,7 @@ MPU401_EOIHandlerDispatch(void *priv) mpu401_log("EOI handler dispatch\n"); if (mpu->state.send_now) { mpu->state.eoi_scheduled = 1; - timer_advance_u64(&mpu->mpu401_eoi_callback, 60 * TIMER_USEC); /* Possibly a bit longer */ + timer_advance_u64(&mpu->mpu401_eoi_callback, 60LL * TIMER_USEC); /* Possibly a bit longer */ } else if (!mpu->state.eoi_scheduled) MPU401_EOIHandler(mpu); } @@ -721,6 +1070,8 @@ MPU401_ReadData(mpu_t *mpu) uint8_t ret; ret = MSG_MPU_ACK; + thread_wait_mutex(mpu_lock); + if (mpu->queue_used) { if (mpu->queue_pos >= MPU401_QUEUE) mpu->queue_pos -= MPU401_QUEUE; @@ -734,11 +1085,29 @@ MPU401_ReadData(mpu_t *mpu) if (mpu->state.irq_pending) { picintc(1 << mpu->irq); mpu->state.irq_pending = 0; + thread_release_mutex(mpu_lock); } return ret; } + if (mpu->state.rec_copy && !mpu->rec_queue_used) { + mpu->state.rec_copy = 0; + MPU401_EOIHandler(mpu); + thread_release_mutex(mpu_lock); + return ret; + } + + /*copy from recording buffer*/ + if (!mpu->queue_used && mpu->rec_queue_used) { + mpu->state.rec_copy = 1; + if (mpu->rec_queue_pos >= MPU401_INPUT_QUEUE) + mpu->rec_queue_pos -= MPU401_INPUT_QUEUE; + MPU401_QueueByte(mpu, mpu->rec_queue[mpu->rec_queue_pos]); + mpu->rec_queue_pos++; + mpu->rec_queue_used--; + } + if (mpu->queue_used == 0) { picintc(1 << mpu->irq); mpu->state.irq_pending = 0; @@ -746,9 +1115,10 @@ MPU401_ReadData(mpu_t *mpu) if ((ret >= 0xf0) && (ret <= 0xf7)) { /* MIDI data request */ - mpu->state.channel = ret & 7; + mpu->state.track = ret & 7; mpu->state.data_onoff = 0; mpu->state.cond_req = 0; + mpu->state.track_req = 1; } if (ret == MSG_MPU_COMMAND_REQ) { @@ -759,15 +1129,16 @@ MPU401_ReadData(mpu_t *mpu) MPU401_WriteCommand(mpu, mpu->condbuf.value[0]); if (mpu->state.command_byte) MPU401_WriteData(mpu, mpu->condbuf.value[1]); + mpu->condbuf.type = T_OVERFLOW; } - mpu->condbuf.type = T_OVERFLOW; } - if ((ret == MSG_MPU_END) || (ret == MSG_MPU_CLOCK) || (ret == MSG_MPU_ACK)) { - mpu->state.data_onoff = -1; + if ((ret == MSG_MPU_END) || (ret == MSG_MPU_CLOCK) || (ret == MSG_MPU_ACK) || (ret == MSG_MPU_OVERFLOW)) { MPU401_EOIHandlerDispatch(mpu); } + thread_release_mutex(mpu_lock); + return(ret); } @@ -822,7 +1193,6 @@ static void MPU401_Event(void *priv) { mpu_t *mpu = (mpu_t *)priv; - int new_time; uint8_t i; mpu401_log("MPU-401 event callback\n"); @@ -833,7 +1203,8 @@ MPU401_Event(void *priv) } if (mpu->state.irq_pending) goto next_event; - + + if (mpu->state.playing) { for (i = 0; i < 8; i++) { /* Decrease counters */ if (mpu->state.amask & (1 << i)) { mpu->playbuf[i].counter--; @@ -843,29 +1214,326 @@ MPU401_Event(void *priv) if (mpu->state.conductor) { mpu->condbuf.counter--; - if (mpu->condbuf.counter <= 0) UpdateConductor(mpu); + if (mpu->condbuf.counter <= 0) { + mpu->condbuf.counter = 0xf0; + mpu->state.req_mask |= (1 << 9); + } } + } - if (mpu->clock.clock_to_host) { + if (mpu->state.clock_to_host) { mpu->clock.cth_counter++; - if (mpu->clock.cth_counter >= mpu->clock.cth_rate) { + if (mpu->clock.cth_counter >= mpu->clock.cth_rate[mpu->clock.cth_mode]) { mpu->clock.cth_counter = 0; + mpu->clock.cth_mode= (++mpu->clock.cth_mode) % 4; mpu->state.req_mask |= (1 << 13); } } - if (!mpu->state.irq_pending && mpu->state.req_mask) + if (mpu->state.rec==M_RECON) { /* recording */ + mpu->clock.rec_counter++; + if (mpu->clock.rec_counter>=240) { + mpu->clock.rec_counter=0; + mpu->state.req_mask|=(1<<8); + } + } + + if (mpu->state.playing || (mpu->state.rec == M_RECON)) { + int max_meascnt = (mpu->clock.timebase * mpu->clock.midimetro * mpu->clock.metromeas) / 24; + if (max_meascnt != 0) { /* measure end */ + if (++mpu->clock.measure_counter >= max_meascnt) { + if (mpu->filter.rt_out) + midi_raw_out_rt_byte(0xf8); + mpu->clock.measure_counter = 0; + if (mpu->filter.rec_measure_end && (mpu->state.rec == M_RECON)) + mpu->state.req_mask |= (1 << 12); + } + } + } + if (!mpu->state.irq_pending && mpu->state.req_mask) { + thread_wait_mutex(mpu_lock); MPU401_EOIHandler(mpu); + thread_release_mutex(mpu_lock); + } next_event: - new_time = ((mpu->clock.tempo * mpu->clock.timebase * mpu->clock.tempo_rel) / 0x40); - if (new_time == 0) { - timer_disable(&mpu->mpu401_event_callback); - return; - } else { - timer_advance_u64(&mpu->mpu401_event_callback, (MPU401_TIMECONSTANT / new_time) * 1000 * TIMER_USEC); - mpu401_log("Next event after %i us (time constant: %i)\n", (uint64_t) ((MPU401_TIMECONSTANT/new_time) * 1000 * TIMER_USEC), (int) MPU401_TIMECONSTANT); - } + MPU401_RunClock(mpu); + if (mpu->state.sync_in) + mpu->clock.ticks_in++; +} + +static void +MPU401_NotesOff(mpu_t *mpu, int i) +{ + int j; + uint8_t key; + + if (mpu->filter.allnotesoff_out && !(mpu->inputref[i].on && + (mpu->inputref[i].key[0]|mpu->inputref[i].key[1]| + mpu->inputref[i].key[2]|mpu->inputref[i].key[3]))) { + for (j=0;j<4;j++) + mpu->chanref[mpu->ch_toref[i]].key[j]=0; + midi_raw_out_byte(0xb0|i); + midi_raw_out_byte(123); + midi_raw_out_byte(0); + } else if (mpu->chanref[mpu->ch_toref[i]].on) { + for (key=0;key<128;key++) { + if ((mpu->chanref[mpu->ch_toref[i]].M_GETKEY) && + !(mpu->inputref[i].on && (mpu->inputref[i].M_GETKEY))) { + midi_raw_out_byte(0x80|i); + midi_raw_out_byte(key); + midi_raw_out_byte(0); + } + mpu->chanref[mpu->ch_toref[i]].M_DELKEY; + } + } +} + +/*Input handler for SysEx */ +static int +MPU401_InputSysex(uint8_t *buffer, uint32_t len, int abort) +{ + pclog("MPU401 Input Sysex\n"); + + int i; + + if (mpuin->filter.sysex_in) { + if (abort) { + mpuin->state.sysex_in_finished=1; + mpuin->rec_queue_used=0;/*reset also the input queue*/ + return 0; + } + if (mpuin->state.sysex_in_finished) { + if (mpuin->rec_queue_used>=MPU401_INPUT_QUEUE) + return len; + uint8_t val_ff=0xff; + MPU401_RecQueueBuffer(mpuin,&val_ff,1,1); + mpuin->state.sysex_in_finished=0; + mpuin->clock.rec_counter=0; + } + if (mpuin->rec_queue_used>=MPU401_INPUT_QUEUE) + return len; + int available=MPU401_INPUT_QUEUE-mpuin->rec_queue_used; + + if (available>=len) { + MPU401_RecQueueBuffer(mpuin,buffer,len,1); + return 0; + } + else { + MPU401_RecQueueBuffer(mpuin,buffer,available,1); + if (mpuin->state.sysex_in_finished) + return 0; + return (len-available); + } + } + else if (mpuin->filter.sysex_thru && mpuin->midi_thru) { + midi_raw_out_byte(0xf0); + for (i=0;istate.sysex_in_finished) { + pclog("SYSEX in progress\n"); + return; + } + + int i; + static uint8_t old_msg=0; + uint8_t len=msg[3]; + int send=1; + int send_thru=0; + int retrigger_thru=0; + int midistatus=0; + if (mpuin->mode==M_INTELLIGENT) { + if (msg[0]<0x80) { /* Expand running status */ + midistatus=1; + msg[2]=msg[1];msg[1]=msg[0];msg[0]=old_msg; + } + old_msg=msg[0]; + int chan=msg[0]&0xf; + int chrefnum=mpuin->ch_toref[chan]; + uint8_t key=msg[1]&0x7f; + if (msg[0]<0xf0) { //if non-system msg + if (!(mpuin->state.midi_mask&(1<filter.all_thru) + send_thru=1; + else if (mpuin->filter.midi_thru) + send_thru=1; + switch (msg[0]&0xf0) { + case 0x80: /*note off*/ + if (send_thru) { + if (mpuin->chanref[chrefnum].on && (mpuin->chanref[chrefnum].M_GETKEY)) + send_thru=0; + if (!mpuin->filter.midi_thru) + break; + if (!(mpuin->inputref[chan].M_GETKEY)) + send_thru=0; + mpuin->inputref[chan].M_DELKEY; + } + break; + case 0x90: /*note on*/ + if (send_thru) { + if (mpuin->chanref[chrefnum].on && (mpuin->chanref[chrefnum].M_GETKEY)) + retrigger_thru=1; + if (!mpuin->filter.midi_thru) + break; + if (mpuin->inputref[chan].M_GETKEY) + retrigger_thru=1; + mpuin->inputref[chan].M_SETKEY; + } + break; + case 0xb0: + if (msg[1]>=120) { + send_thru=0; + if (msg[1]==123) { /* All notes off */ + for (key=0;key<128;key++) { + if (!(mpuin->chanref[chrefnum].on && (mpuin->chanref[chrefnum].M_GETKEY))) + if (mpuin->inputref[chan].on && mpuin->inputref[chan].M_GETKEY) { + midi_raw_out_byte(0x80|chan); + midi_raw_out_byte(key); + midi_raw_out_byte(0); + } + mpuin->inputref[chan].M_DELKEY; + } + } + } + break; + } + } + if (msg[0]>=0xf0 || (mpuin->state.midi_mask&(1<filter.bender_in) + send=0; + break; + case 0xb0: /*control change*/ + if (!mpuin->filter.bender_in && msg[1]<64) + send=0; + if (msg[1]>=120) { + if (mpuin->filter.modemsgs_in) + send=1; + } + break; + case 0xc0: /*program change*/ + if ((mpuin->state.rec!=M_RECON) && !mpuin->filter.data_in_stop) { + mpuin->filter.prchg_buf[chan]=msg[1]; + mpuin->filter.prchg_mask|=1<filter.bender_in) + send=0; + break; + case 0xf0: //system message + if (msg[0]==0xf8) { + send=0; + if (mpuin->clock.active && mpuin->state.sync_in) { + send = 0;/*don't pass to host in this mode?*/ + int tick=mpuin->clock.timebase/24; + if (mpuin->clock.ticks_in!=tick) { + if (!mpuin->clock.ticks_in || (mpuin->clock.ticks_in>tick*2)) + mpuin->clock.freq_mod*=2.0; + else { + if (ABS(mpuin->clock.ticks_in-tick)==1) + mpuin->clock.freq_mod/=mpuin->clock.ticks_in/(float)(tick*2); + else + mpuin->clock.freq_mod/=mpuin->clock.ticks_in/(float)(tick); + } + MPU401_ReCalcClock(mpuin); + } + mpuin->clock.ticks_in=0; + } + } + else if (msg[0]>0xf8) { /*realtime*/ + if (!(mpuin->filter.rt_in && msg[0]<=0xfc && msg[0]>=0xfa)) { + uint8_t recdata[2]={0xff,msg[0]}; + MPU401_RecQueueBuffer(mpuin,recdata,2,1); + send=0; + } + } + else { /*common or system*/ + send=0; + if (msg[0]==0xf2 || msg[0]==0xf3 || msg[0]==0xf6) { + if (mpuin->filter.commonmsgs_in) + send=1; + if (mpuin->filter.commonmsgs_thru) + for (i=0;ifilter.rt_affection) switch(msg[0]) { + case 0xf2:case 0xf3: + mpuin->state.block_ack=1; + MPU401_WriteCommand(mpuin,0xb8);/*clear play counters*/ + break; + case 0xfa: + mpuin->state.block_ack=1; + MPU401_WriteCommand(mpuin,0xa);/*start,play*/ + if (mpuin->filter.rt_out) + midi_raw_out_rt_byte(msg[0]); + break; + case 0xfb: + mpuin->state.block_ack=1; + MPU401_WriteCommand(mpuin,0xb);/*continue,play*/ + if (mpuin->filter.rt_out) + midi_raw_out_rt_byte(msg[0]); + break; + case 0xfc: + mpuin->state.block_ack=1; + MPU401_WriteCommand(mpuin,0xd);/*stop: play,rec,midi*/ + if (mpuin->filter.rt_out) + midi_raw_out_rt_byte(msg[0]); + break; + } + return; + } + if (send_thru && mpuin->midi_thru) { + if (retrigger_thru) { + midi_raw_out_byte(0x80|(msg[0]&0xf)); + midi_raw_out_byte(msg[1]); + midi_raw_out_byte(msg[2]); + } + for (i=0/*((midistatus && !retrigger_thru)? 1:0)*/;istate.rec==M_RECON) { + uint8_t recmsg[4]={mpuin->clock.rec_counter,msg[0],msg[1],msg[2]}; + MPU401_RecQueueBuffer(mpuin,recmsg,len+1,1); + mpuin->clock.rec_counter=0; + } + else if (mpuin->filter.data_in_stop) { + if (mpuin->filter.timing_in_stop) { + uint8_t recmsg[4]={0,msg[0],msg[1],msg[2]}; + MPU401_RecQueueBuffer(mpuin,recmsg,len+1,1); + } + else { + uint8_t recmsg[4]={msg[0],msg[1],msg[2],0}; + MPU401_RecQueueBuffer(mpuin,recmsg,len,1); + } + } + } + return; + } + /*UART mode input*/ + thread_wait_mutex(mpu_lock); + for (i=0;i * DOSBox Team, @@ -22,10 +22,16 @@ #define MPU401_VERSION 0x15 #define MPU401_REVISION 0x01 -#define MPU401_QUEUE 32 +#define MPU401_QUEUE 64 +#define MPU401_INPUT_QUEUE 1024 #define MPU401_TIMECONSTANT (60000000/1000.0f) #define MPU401_RESETBUSY 27.0f +/*helpers*/ +#define M_GETKEY key[key/32]&(1<<(key%32)) +#define M_SETKEY key[key/32]|=(1<<(key%32)) +#define M_DELKEY key[key/32]&=~(1<<(key%32)) + typedef enum MpuMode { M_UART, @@ -43,6 +49,13 @@ typedef enum MpuDataType T_COMMAND } MpuDataType; +typedef enum RecState +{ + M_RECOFF, + M_RECSTB, + M_RECON +} RecState; + /* Messages sent to MPU-401 from host */ #define MSG_EOX 0xf7 #define MSG_OVERFLOW 0xf8 @@ -57,6 +70,7 @@ typedef enum MpuDataType typedef struct mpu_t { + int midi_thru; int uart_mode, intelligent, irq, queue_pos, queue_used; @@ -64,10 +78,13 @@ typedef struct mpu_t status, queue[MPU401_QUEUE], pos_regs[8]; MpuMode mode; + uint8_t rec_queue[MPU401_INPUT_QUEUE]; + int rec_queue_pos, rec_queue_used; + uint32_t ch_toref[16]; struct track { int counter; - uint8_t value[8], sys_val, + uint8_t value[3], sys_val, vlength,length; MpuDataType type; } playbuf[8], condbuf; @@ -77,23 +94,50 @@ typedef struct mpu_t playing, reset, wsd, wsm, wsd_start, run_irq, irq_pending, + track_req, send_now, eoi_scheduled, - data_onoff; + data_onoff, clock_to_host, + sync_in, sysex_in_finished, + rec_copy; + RecState rec; uint8_t tmask, cmask, amask, - channel, old_chan; + last_rtcmd; uint16_t midi_mask, req_mask; - uint32_t command_byte, cmd_pending; + uint32_t command_byte, cmd_pending, + track, old_track; } state; struct { uint8_t timebase, old_timebase, tempo, old_tempo, tempo_rel, old_tempo_rel, - tempo_grad, - cth_rate, cth_counter; - int clock_to_host,cth_active; + tempo_grad, cth_rate[4], + cth_mode, midimetro, + metromeas; + uint32_t cth_counter, cth_old, + rec_counter; + int32_t measure_counter, meas_old, + freq; + int ticks_in, active; + float freq_mod; } clock; - + struct { + int all_thru, midi_thru, + sysex_thru, commonmsgs_thru, + modemsgs_in, commonmsgs_in, + bender_in, sysex_in, + allnotesoff_out, rt_affection, + rt_out, rt_in, + timing_in_stop, data_in_stop, + rec_measure_end; + uint8_t prchg_buf[16]; + uint16_t prchg_mask; + } filter; + struct { + int on; + uint8_t chan, trmask; + uint32_t key[4]; + } chanref[5], inputref[16]; pc_timer_t mpu401_event_callback, mpu401_eoi_callback, mpu401_reset_callback; } mpu_t; diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index b927e54e4..23f5812a9 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -32,6 +32,7 @@ #include "../rom.h" #include "../device.h" #include "sound.h" +#include "midi.h" #include "filters.h" #include "snd_emu8k.h" #include "snd_mpu401.h" @@ -188,6 +189,12 @@ sb_log(const char *fmt, ...) #endif +static void +sb_dsp_set_midi_in(sb_dsp_t *src_dsp_midi_in) +{ + dspin = src_dsp_midi_in; +} + /* sb 1, 1.5, 2, 2 mvc do not have a mixer, so signal is hardwired */ static void sb_get_buffer_sb2(int32_t *buffer, int len, void *p) { @@ -1041,6 +1048,11 @@ void *sb_1_init() io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); } sound_add_handler(sb_get_buffer_sb2, sb); + + sb_dsp_set_midi_in(&sb->dsp); + input_msg = sb_dsp_input_msg; + input_sysex = sb_dsp_input_sysex; + return sb; } void *sb_15_init() @@ -1067,6 +1079,11 @@ void *sb_15_init() io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); } sound_add_handler(sb_get_buffer_sb2, sb); + + sb_dsp_set_midi_in(&sb->dsp); + input_msg = sb_dsp_input_msg; + input_sysex = sb_dsp_input_sysex; + return sb; } @@ -1090,6 +1107,11 @@ void *sb_mcv_init() mca_add(sb_mcv_read, sb_mcv_write, sb_mcv_feedb, sb); sb->pos_regs[0] = 0x84; sb->pos_regs[1] = 0x50; + + sb_dsp_set_midi_in(&sb->dsp); + input_msg = sb_dsp_input_msg; + input_sysex = sb_dsp_input_sysex; + return sb; } void *sb_2_init() @@ -1137,6 +1159,10 @@ void *sb_2_init() else sound_add_handler(sb_get_buffer_sb2, sb); + sb_dsp_set_midi_in(&sb->dsp); + input_msg = sb_dsp_input_msg; + input_sysex = sb_dsp_input_sysex; + return sb; } @@ -1170,6 +1196,10 @@ void *sb_pro_v1_init() io_sethandler(addr+4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, sb); sound_add_handler(sb_get_buffer_sbpro, sb); + sb_dsp_set_midi_in(&sb->dsp); + input_msg = sb_dsp_input_msg; + input_sysex = sb_dsp_input_sysex; + return sb; } @@ -1202,6 +1232,10 @@ void *sb_pro_v2_init() io_sethandler(addr+4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, sb); sound_add_handler(sb_get_buffer_sbpro, sb); + sb_dsp_set_midi_in(&sb->dsp); + input_msg = sb_dsp_input_msg; + input_sysex = sb_dsp_input_sysex; + return sb; } @@ -1227,6 +1261,10 @@ void *sb_pro_mcv_init() sb->pos_regs[0] = 0x03; sb->pos_regs[1] = 0x51; + sb_dsp_set_midi_in(&sb->dsp); + input_msg = sb_dsp_input_msg; + input_sysex = sb_dsp_input_sysex; + return sb; } @@ -1261,6 +1299,11 @@ void *sb_16_init() } else sb->mpu = NULL; + + sb_dsp_set_midi_in(&sb->dsp); + input_msg = sb_dsp_input_msg; + input_sysex = sb_dsp_input_sysex; + return sb; } @@ -1305,6 +1348,10 @@ void *sb_awe32_init() sb->mpu = NULL; emu8k_init(&sb->emu8k, emu_addr, onboard_ram); + sb_dsp_set_midi_in(&sb->dsp); + input_msg = sb_dsp_input_msg; + input_sysex = sb_dsp_input_sysex; + return sb; } diff --git a/src/sound/snd_sb_dsp.c b/src/sound/snd_sb_dsp.c index 35aeb7ee7..51188ee03 100644 --- a/src/sound/snd_sb_dsp.c +++ b/src/sound/snd_sb_dsp.c @@ -119,7 +119,7 @@ uint8_t adjustMap2[24] = { }; float low_fir_sb16_coef[SB16_NCoef]; - +sb_dsp_t *dspin; #ifdef ENABLE_SB_DSP_LOG int sb_dsp_do_log = ENABLE_SB_DSP_LOG; @@ -147,7 +147,6 @@ sinc(double x) return sin(M_PI * x) / (M_PI * x); } - static void recalc_sb16_filter(int playback_freq) { @@ -207,6 +206,8 @@ sb_irqc(sb_dsp_t *dsp, int irq8) void sb_dsp_reset(sb_dsp_t *dsp) { + midi_clear_buffer(); + timer_disable(&dsp->output_timer); timer_disable(&dsp->input_timer); @@ -218,7 +219,7 @@ sb_dsp_reset(sb_dsp_t *dsp) sb_irqc(dsp, 0); sb_irqc(dsp, 1); dsp->sb_16_pause = 0; - dsp->sb_read_wp = dsp->sb_read_rp = 0; + dsp->sb_read_wp = dsp->sb_read_rp = 0; dsp->sb_data_stat = -1; dsp->sb_speaker = 0; dsp->sb_pausetime = -1LL; @@ -393,7 +394,6 @@ sb_dsp_setdma16(sb_dsp_t *dsp, int dma) dsp->sb_16_dmanum = dma; } - void sb_exec_command(sb_dsp_t *dsp) { @@ -457,19 +457,35 @@ sb_exec_command(sb_dsp_t *dsp) if (dsp->sb_type >= SB15) sb_start_dma_i(dsp, 1, 1, 0, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); break; - case 0x30: case 0x31: + case 0x30: /* MIDI Polling mode input */ + pclog("MIDI polling mode input\n"); + dsp->midi_in_poll = 1; + dsp->uart_irq = 0; break; - case 0x34: /* MIDI (UART mode) */ + case 0x31: /* MIDI Interrupt mode input */ + pclog("MIDI interrupt mode input\n"); + dsp->midi_in_poll = 0; + dsp->uart_irq = 1; + break; + case 0x34: /* MIDI In poll */ + if (dsp->sb_type < SB2) + break; + pclog("MIDI poll in\n"); + dsp->midi_in_poll = 1; dsp->uart_midi = 1; dsp->uart_irq = 0; break; - case 0x35: /* MIDI (UART mode) */ + case 0x35: /* MIDI In irq */ + if (dsp->sb_type < SB2) + break; + pclog("MIDI irq in\n"); + dsp->midi_in_poll = 0; dsp->uart_midi = 1; dsp->uart_irq = 1; break; - case 0x36: case 0x37: + case 0x36: case 0x37: /* MIDI timestamps */ break; - case 0x38: /* MIDI (Normal mode) */ + case 0x38: /* Write to SB MIDI Output (Raw) */ dsp->onebyte_midi = 1; break; case 0x40: /* Set time constant */ @@ -724,17 +740,22 @@ sb_write(uint16_t a, uint8_t v, void *priv) switch (a & 0xF) { case 6: /* Reset */ - if (!(v & 1) && (dsp->sbreset & 1)) { - sb_dsp_reset(dsp); - sb_add_data(dsp, 0xAA); + if (!dsp->uart_midi) { + if (!(v & 1) && (dsp->sbreset & 1)) { + sb_dsp_reset(dsp); + sb_add_data(dsp, 0xAA); + } + dsp->sbreset = v; } - dsp->sbreset = v; + dsp->uart_midi = 0; + dsp->uart_irq = 0; + dsp->onebyte_midi = 0; return; case 0xC: /* Command/data write */ - if (dsp->uart_midi || dsp->onebyte_midi) { - midi_write(v); + if (dsp->uart_midi || dsp->onebyte_midi ) { + midi_raw_out_byte(v); dsp->onebyte_midi = 0; - return; + return; } timer_set_delay_u64(&dsp->wb_timer, TIMER_USEC * 1); if (dsp->asp_data_len) { @@ -768,9 +789,9 @@ sb_read(uint16_t a, void *priv) switch (a & 0xf) { case 0xA: /* Read data */ - if (mpu && dsp->uart_midi) + if (mpu && dsp->uart_midi) { ret = MPU401_ReadData(mpu); - else { + } else { dsp->sbreaddat = dsp->sb_read_data[dsp->sb_read_rp]; if (dsp->sb_read_rp != dsp->sb_read_wp) { dsp->sb_read_rp++; @@ -814,6 +835,47 @@ sb_dsp_set_mpu(mpu_t *src_mpu) mpu = src_mpu; } +void +sb_dsp_input_msg(uint8_t *msg) +{ + pclog("MIDI in sysex = %d, uart irq = %d, midi in = %d\n", dspin->midi_in_sysex, dspin->uart_irq, dspin->midi_in_poll); + + if (dspin->midi_in_sysex) { + return; + } + + uint8_t len = msg[3]; + uint8_t i = 0; + if (dspin->uart_irq) { + for (i=0;isb_irq8) sb_irq(dspin, 1); + } else if (dspin->midi_in_poll) { + for (i=0;imidi_in_sysex = 0; + return 0; + } + dspin->midi_in_sysex = 1; + for (i=0;isb_read_rp == dspin->sb_read_wp) { + pclog("Length sysex SB = %d\n", len-i); + return (len-i); + } + sb_add_data(dspin, buffer[i]); + } + dspin->midi_in_sysex = 0; + return 0; +} void sb_dsp_init(sb_dsp_t *dsp, int type) diff --git a/src/sound/snd_sb_dsp.h b/src/sound/snd_sb_dsp.h index 2772e2254..2c7022912 100644 --- a/src/sound/snd_sb_dsp.h +++ b/src/sound/snd_sb_dsp.h @@ -9,14 +9,18 @@ typedef struct sb_dsp_t int sb_pausetime; uint8_t sb_read_data[256]; - int sb_read_wp, sb_read_rp; + int sb_read_wp, sb_read_rp; int sb_speaker; int muted; int sb_data_stat; - int uart_midi; - int uart_irq; - int onebyte_midi; + + int midi_in_sysex; + int midi_in_poll; + int uart_midi; + int uart_irq; + int onebyte_midi; + int midi_in_timestamp; int sb_irqnum; @@ -72,6 +76,12 @@ typedef struct sb_dsp_t int pos; } sb_dsp_t; +extern sb_dsp_t *dspin; + +void sb_dsp_input_msg(uint8_t *msg); + +int sb_dsp_input_sysex(uint8_t *buffer, uint32_t len, int abort); + void sb_dsp_set_mpu(mpu_t *src_mpu); void sb_dsp_init(sb_dsp_t *dsp, int type); diff --git a/src/sound/sound.c b/src/sound/sound.c index 12875f4f1..d3de46351 100644 --- a/src/sound/sound.c +++ b/src/sound/sound.c @@ -107,7 +107,6 @@ static const SOUND_CARD sound_cards[] = { "[MCA] Sound Blaster MCV", "sbmcv", &sb_mcv_device }, { "[MCA] Sound Blaster Pro MCV", "sbpromcv", &sb_pro_mcv_device }, { "[PCI] Ensoniq AudioPCI (ES1371)", "es1371", &es1371_device }, - { "[PCI] Sound Blaster PCI 128", "sbpci128", &es1371_device }, { "", "", NULL } }; @@ -442,6 +441,7 @@ sound_reset(void) sound_realloc_buffers(); midi_device_init(); + midi_in_device_init(); inital(); timer_add(&sound_poll_timer, sound_poll, NULL, 1); diff --git a/src/win/86Box.rc b/src/win/86Box.rc index 294e813b9..43c2c0f7c 100644 --- a/src/win/86Box.rc +++ b/src/win/86Box.rc @@ -380,34 +380,39 @@ BEGIN LTEXT "MIDI Out Device:",IDT_1712,7,26,59,10 PUSHBUTTON "Configure",IDC_CONFIGURE_MIDI,214,25,46,12 + COMBOBOX IDC_COMBO_MIDI_IN,71,43,140,120,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + LTEXT "MIDI In Device:",IDT_1713,7,44,59,10 + PUSHBUTTON "Configure",IDC_CONFIGURE_MIDI_IN,214,43,46,12 + CONTROL "Standalone MPU-401",IDC_CHECK_MPU401,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,7,45,199,10 - PUSHBUTTON "Configure",IDC_CONFIGURE_MPU401,214,44,46,12 + BS_AUTOCHECKBOX | WS_TABSTOP,7,65,199,10 + PUSHBUTTON "Configure",IDC_CONFIGURE_MPU401,214,64,46,12 CONTROL "Innovation SSI-2001",IDC_CHECK_SSI,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,7,63,94,10 + BS_AUTOCHECKBOX | WS_TABSTOP,7,83,94,10 CONTROL "CMS / Game Blaster",IDC_CHECK_CMS,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,147,63,94,10 + BS_AUTOCHECKBOX | WS_TABSTOP,147,83,94,10 CONTROL "Gravis Ultrasound",IDC_CHECK_GUS,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,7,81,94,10 + BS_AUTOCHECKBOX | WS_TABSTOP,7,101,94,10 CONTROL "Use FLOAT32 sound",IDC_CHECK_FLOAT,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,147,81,94,10 + BS_AUTOCHECKBOX | WS_TABSTOP,147,101,94,10 END DLG_CFG_NETWORK DIALOG DISCARDABLE 97, 0, 267, 63 STYLE DS_CONTROL | WS_CHILD FONT 9, "Segoe UI" BEGIN - LTEXT "Network type:",IDT_1713,7,8,59,10 + LTEXT "Network type:",IDT_1714,7,8,59,10 COMBOBOX IDC_COMBO_NET_TYPE,71,7,189,120,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT "PCap device:",IDT_1714,7,26,59,10 + LTEXT "PCap device:",IDT_1715,7,26,59,10 COMBOBOX IDC_COMBO_PCAP,71,25,189,120,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT "Network adapter:",IDT_1715,7,44,59,10 + LTEXT "Network adapter:",IDT_1716,7,44,59,10 COMBOBOX IDC_COMBO_NET,71,43,140,120,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP PUSHBUTTON "Configure",IDC_CONFIGURE_NET,214,43,46,12 @@ -417,15 +422,15 @@ DLG_CFG_PORTS DIALOG DISCARDABLE 97, 0, 267, 117 STYLE DS_CONTROL | WS_CHILD FONT 9, "Segoe UI" BEGIN - LTEXT "LPT1 Device:",IDT_1716,7,8,61,10 + LTEXT "LPT1 Device:",IDT_1717,7,8,61,10 COMBOBOX IDC_COMBO_LPT1,71,7,189,120,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT "LPT2 Device:",IDT_1717,7,27,61,10 + LTEXT "LPT2 Device:",IDT_1718,7,27,61,10 COMBOBOX IDC_COMBO_LPT2,71,26,189,120,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT "LPT3 Device:",IDT_1718,7,46,61,10 + LTEXT "LPT3 Device:",IDT_1719,7,46,61,10 COMBOBOX IDC_COMBO_LPT3,71,45,189,120,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP @@ -446,12 +451,12 @@ DLG_CFG_PERIPHERALS DIALOG DISCARDABLE 97, 0, 267, 200 STYLE DS_CONTROL | WS_CHILD FONT 9, "Segoe UI" BEGIN - LTEXT "SCSI Controller:",IDT_1716,7,8,48,10 + LTEXT "SCSI Controller:",IDT_1717,7,8,48,10 COMBOBOX IDC_COMBO_SCSI,64,7,155,120,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP PUSHBUTTON "Configure",IDC_CONFIGURE_SCSI,222,7,38,12 - LTEXT "HD Controller:",IDT_1717,7,26,48,10 + LTEXT "HD Controller:",IDT_1718,7,26,48,10 COMBOBOX IDC_COMBO_HDC,64,25,155,120,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP PUSHBUTTON "Configure",IDC_CONFIGURE_HDC,222,25,38,12 diff --git a/src/win/resource.h b/src/win/resource.h index e34f6a1be..49ba9679e 100644 --- a/src/win/resource.h +++ b/src/win/resource.h @@ -54,12 +54,13 @@ #define IDT_1710 1710 /* Joystick: */ #define IDT_1711 1711 /* Sound card: */ #define IDT_1712 1712 /* MIDI Out Device: */ -#define IDT_1713 1713 /* Network type: */ -#define IDT_1714 1714 /* PCap device: */ -#define IDT_1715 1715 /* Network adapter: */ -#define IDT_1716 1716 /* SCSI Controller: */ -#define IDT_1717 1717 /* HD Controller: */ -#define IDT_1718 1718 +#define IDT_1713 1713 /* MIDI In Device: */ +#define IDT_1714 1714 /* Network type: */ +#define IDT_1715 1715 /* PCap device: */ +#define IDT_1716 1716 /* Network adapter: */ +#define IDT_1717 1717 /* SCSI Controller: */ +#define IDT_1718 1718 /* HD Controller: */ +#define IDT_1719 1719 #define IDT_1720 1720 /* Hard disks: */ #define IDT_1721 1721 /* Bus: */ #define IDT_1722 1722 /* Channel: */ @@ -149,6 +150,7 @@ #define IDC_CONFIGURE_MPU401 1077 #define IDC_CHECK_FLOAT 1078 #define IDC_CHECK_GUSMAX 1079 +#define IDC_COMBO_MIDI_IN 1080 #define IDC_COMBO_NET_TYPE 1090 /* network config */ #define IDC_COMBO_PCAP 1091 @@ -241,6 +243,7 @@ #define IDC_CONFIGURE_PCAP 1306 #define IDC_CONFIGURE_NET 1307 #define IDC_CONFIGURE_MIDI 1308 +#define IDC_CONFIGURE_MIDI_IN 1309 #define IDC_JOY1 1310 #define IDC_JOY2 1311 #define IDC_JOY3 1312 diff --git a/src/win/win_devconf.c b/src/win/win_devconf.c index a0a1e5018..e5e379d6c 100644 --- a/src/win/win_devconf.c +++ b/src/win/win_devconf.c @@ -108,6 +108,21 @@ deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) id += 2; break; + case CONFIG_MIDI_IN: + val_int = config_get_int((char *) config_device.name, + (char *) config->name, config->default_int); + + num = plat_midi_in_get_num_devs(); + for (c = 0; c < num; c++) { + plat_midi_in_get_dev_name(c, s); + mbstowcs(lptsTemp, s, strlen(s) + 1); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)lptsTemp); + if (val_int == c) + SendMessage(h, CB_SETCURSEL, c, 0); + } + + id += 2; + break; case CONFIG_SPINNER: val_int = config_get_int((char *) config_device.name, (char *) config->name, config->default_int); @@ -205,6 +220,17 @@ deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) c = SendMessage(h, CB_GETCURSEL, 0, 0); + if (val_int != c) + changed = 1; + + id += 2; + break; + case CONFIG_MIDI_IN: + val_int = config_get_int((char *) config_device.name, + (char *) config->name, config->default_int); + + c = SendMessage(h, CB_GETCURSEL, 0, 0); + if (val_int != c) changed = 1; @@ -302,6 +328,12 @@ deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) c = SendMessage(h, CB_GETCURSEL, 0, 0); config_set_int((char *) config_device.name, (char *) config->name, c); + id += 2; + break; + case CONFIG_MIDI_IN: + c = SendMessage(h, CB_GETCURSEL, 0, 0); + config_set_int((char *) config_device.name, (char *) config->name, c); + id += 2; break; case CONFIG_FNAME: @@ -358,6 +390,7 @@ deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) break; case CONFIG_SELECTION: case CONFIG_MIDI: + case CONFIG_MIDI_IN: case CONFIG_SPINNER: id += 2; break; @@ -478,6 +511,7 @@ deviceconfig_inst_open(HWND hwnd, const device_t *device, int inst) case CONFIG_SELECTION: case CONFIG_MIDI: + case CONFIG_MIDI_IN: case CONFIG_HEX16: case CONFIG_HEX20: /*Combo box*/ diff --git a/src/win/win_midi.c b/src/win/win_midi.c index 706db3acb..239fd7a77 100644 --- a/src/win/win_midi.c +++ b/src/win/win_midi.c @@ -13,13 +13,15 @@ typedef struct { - int midi_id; + int midi_id, midi_input_id; HANDLE m_event; + HANDLE m_callback; HMIDIOUT midi_out_device; + HMIDIIN midi_in_device; - MIDIHDR m_hdr; + MIDIHDR m_hdr, m_hdr_in; } plat_midi_t; plat_midi_t *pm = NULL; @@ -39,6 +41,7 @@ plat_midi_init(void) pm->m_event = CreateEvent(NULL, TRUE, TRUE, NULL); + pclog("Plat MIDI Out init\n"); hr = midiOutOpen(&pm->midi_out_device, pm->midi_id, (uintptr_t) pm->m_event, 0, CALLBACK_EVENT); if (hr != MMSYSERR_NOERROR) { @@ -65,7 +68,7 @@ plat_midi_close(void) midiOutClose(pm->midi_out_device); CloseHandle(pm->m_event); } - + free(pm); pm = NULL; } @@ -135,3 +138,119 @@ plat_midi_write(uint8_t val) { return 0; } + +void CALLBACK +plat_midi_in_callback(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) { + pclog("MIDI: wMsg:%x %x %x\n",wMsg, dwParam1, dwParam2); + uint8_t msg[4] = {((dwParam1&0xff)),(((dwParam1&0xff00)>>8)), + (((dwParam1&0xff0000)>>16)),MIDI_evt_len[((dwParam1&0xff))]}; + uint8_t *sysex; + int len; + int cnt; + MIDIHDR *t_hdr; + switch (wMsg) { + case MM_MIM_DATA: /* 0x3C3 - midi message */ + input_msg(msg); + break; + case MM_MIM_OPEN: /* 0x3C1 */ + break; + case MM_MIM_CLOSE: /* 0x3C2 */ + break; + case MM_MIM_LONGDATA: /* 0x3C4 - sysex */ + pclog("MIDI sysex\n"); + t_hdr = (MIDIHDR *)dwParam1; + sysex = (uint8_t *)t_hdr->lpData; + len = (unsigned int)t_hdr->dwBytesRecorded; + cnt = 5; + while (cnt) { /*abort if timed out*/ + int ret = input_sysex(sysex, len, 0); + if (!ret) { + len = 0; + break; + } + if (len==ret) + cnt--; + else + cnt = 5; + sysex += len-ret; + len = ret; + Sleep(5);/*msec*/ + } + if (len) + input_sysex(sysex, 0, 0); + + midiInUnprepareHeader(hMidiIn, t_hdr, sizeof(*t_hdr)); + t_hdr->dwBytesRecorded = 0; + midiInPrepareHeader(hMidiIn, t_hdr, sizeof(*t_hdr)); + break; + case MM_MIM_ERROR: + case MM_MIM_LONGERROR: + break; + default: + break; + } +} + +void +plat_midi_input_init(void) +{ + MMRESULT hr; + + pm = (plat_midi_t *) malloc(sizeof(plat_midi_t)); + memset(pm, 0, sizeof(plat_midi_t)); + + pclog("Plat MIDI Input init\n"); + + pm->midi_input_id = config_get_int(MIDI_INPUT_NAME, "midi_input", 0); + + hr = midiInOpen(&pm->midi_in_device, pm->midi_input_id, + (uintptr_t) plat_midi_in_callback, 0, CALLBACK_FUNCTION); + if (hr != MMSYSERR_NOERROR) { + pclog("midiInOpen error - %08X\n", hr); + pm->midi_input_id = 0; + hr = midiInOpen(&pm->midi_in_device, pm->midi_input_id, + (uintptr_t) plat_midi_in_callback, 0, CALLBACK_FUNCTION); + if (hr != MMSYSERR_NOERROR) { + pclog("midiInOpen error - %08X\n", hr); + return; + } + } + + pm->m_hdr_in.lpData = (char*)&MIDI_InSysexBuf[0]; + pm->m_hdr_in.dwBufferLength = SYSEX_SIZE; + pm->m_hdr_in.dwBytesRecorded = 0 ; + pm->m_hdr_in.dwUser = 0; + pclog("Prepare MIDI In\n"); + midiInPrepareHeader(pm->midi_in_device,&pm->m_hdr_in,sizeof(pm->m_hdr_in)); + midiInStart(pm->midi_in_device); +} + +void +plat_midi_input_close(void) +{ + if (pm) { + if (pm->midi_in_device != NULL) { + midiInStop(pm->midi_in_device); + midiInClose(pm->midi_in_device); + } + + free(pm); + pm = NULL; + } +} + +int +plat_midi_in_get_num_devs(void) +{ + return midiInGetNumDevs(); +} + + +void +plat_midi_in_get_dev_name(int num, char *s) +{ + MIDIINCAPS caps; + + midiInGetDevCaps(num, &caps, sizeof(caps)); + strcpy(s, caps.szPname); +} \ No newline at end of file diff --git a/src/win/win_settings.c b/src/win/win_settings.c index f2a716a8c..1a2605a07 100644 --- a/src/win/win_settings.c +++ b/src/win/win_settings.c @@ -84,7 +84,7 @@ static int temp_gfxcard, temp_voodoo; static int temp_mouse, temp_joystick; /* Sound category */ -static int temp_sound_card, temp_midi_device, temp_mpu401, temp_SSI2001, temp_GAMEBLASTER, temp_GUS; +static int temp_sound_card, temp_midi_device, temp_midi_input_device, temp_mpu401, temp_SSI2001, temp_GAMEBLASTER, temp_GUS; static int temp_float; /* Network category */ @@ -123,6 +123,7 @@ extern int is486; static int listtomachine[256], machinetolist[256]; static int settings_device_to_list[2][20], settings_list_to_device[2][20]; static int settings_midi_to_list[20], settings_list_to_midi[20]; +static int settings_midi_in_to_list[20], settings_list_to_midi_in[20]; static int max_spt = 63, max_hpc = 255, max_tracks = 266305; static uint64_t mfm_tracking, esdi_tracking, xta_tracking, ide_tracking, scsi_tracking[2]; @@ -218,6 +219,7 @@ win_settings_init(void) /* Sound category */ temp_sound_card = sound_card_current; temp_midi_device = midi_device_current; + temp_midi_input_device = midi_input_device_current; temp_mpu401 = mpu401_standalone_enable; temp_SSI2001 = SSI2001; temp_GAMEBLASTER = GAMEBLASTER; @@ -329,6 +331,7 @@ win_settings_changed(void) /* Sound category */ i = i || (sound_card_current != temp_sound_card); i = i || (midi_device_current != temp_midi_device); + i = i || (midi_input_device_current != temp_midi_input_device); i = i || (mpu401_standalone_enable != temp_mpu401); i = i || (SSI2001 != temp_SSI2001); i = i || (GAMEBLASTER != temp_GAMEBLASTER); @@ -431,6 +434,7 @@ win_settings_save(void) /* Sound category */ sound_card_current = temp_sound_card; midi_device_current = temp_midi_device; + midi_input_device_current = temp_midi_input_device; mpu401_standalone_enable = temp_mpu401; SSI2001 = temp_SSI2001; GAMEBLASTER = temp_GAMEBLASTER; @@ -1100,12 +1104,13 @@ mpu401_present(void) int mpu401_standalone_allow(void) { - char *md; + char *md, *mdin; md = midi_device_get_internal_name(temp_midi_device); + mdin = midi_in_device_get_internal_name(temp_midi_input_device); if (md != NULL) { - if (!strcmp(md, "none")) + if (!strcmp(md, "none") && !strcmp(mdin, "none")) return 0; } @@ -1195,12 +1200,45 @@ win_settings_sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) else EnableWindow(h, FALSE); + h = GetDlgItem(hdlg, IDC_COMBO_MIDI_IN); + c = d = 0; + while (1) { + s = midi_in_device_getname(c); + + if (!s[0]) + break; + + settings_midi_in_to_list[c] = d; + + if (midi_in_device_available(c)) { + if (c == 0) + SendMessage(h, CB_ADDSTRING, 0, win_get_string(IDS_2112)); + else { + mbstowcs(lptsTemp, s, strlen(s) + 1); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); + } + settings_list_to_midi_in[d] = c; + d++; + } + + c++; + } + SendMessage(h, CB_SETCURSEL, settings_midi_in_to_list[temp_midi_input_device], 0); + + h = GetDlgItem(hdlg, IDC_CONFIGURE_MIDI_IN); + if (midi_in_device_has_config(temp_midi_input_device)) + EnableWindow(h, TRUE); + else + EnableWindow(h, FALSE); + + h = GetDlgItem(hdlg, IDC_CHECK_MPU401); SendMessage(h, BM_SETCHECK, temp_mpu401, 0); EnableWindow(h, mpu401_standalone_allow() ? TRUE : FALSE); h = GetDlgItem(hdlg, IDC_CONFIGURE_MPU401); EnableWindow(h, (mpu401_standalone_allow() && temp_mpu401) ? TRUE : FALSE); + h=GetDlgItem(hdlg, IDC_CHECK_CMS); SendMessage(h, BM_SETCHECK, temp_GAMEBLASTER, 0); @@ -1270,6 +1308,31 @@ win_settings_sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) temp_deviceconfig |= deviceconfig_open(hdlg, (void *)midi_device_getdevice(temp_midi_device)); break; + case IDC_COMBO_MIDI_IN: + h = GetDlgItem(hdlg, IDC_COMBO_MIDI_IN); + temp_midi_input_device = settings_list_to_midi_in[SendMessage(h, CB_GETCURSEL, 0, 0)]; + + h = GetDlgItem(hdlg, IDC_CONFIGURE_MIDI_IN); + if (midi_in_device_has_config(temp_midi_input_device)) + EnableWindow(h, TRUE); + else + EnableWindow(h, FALSE); + + h = GetDlgItem(hdlg, IDC_CHECK_MPU401); + SendMessage(h, BM_SETCHECK, temp_mpu401, 0); + EnableWindow(h, mpu401_standalone_allow() ? TRUE : FALSE); + + h = GetDlgItem(hdlg, IDC_CONFIGURE_MPU401); + EnableWindow(h, (mpu401_standalone_allow() && temp_mpu401) ? TRUE : FALSE); + break; + + case IDC_CONFIGURE_MIDI_IN: + h = GetDlgItem(hdlg, IDC_COMBO_MIDI_IN); + temp_midi_input_device = settings_list_to_midi_in[SendMessage(h, CB_GETCURSEL, 0, 0)]; + + temp_deviceconfig |= deviceconfig_open(hdlg, (void *)midi_in_device_getdevice(temp_midi_input_device)); + break; + case IDC_CHECK_MPU401: h = GetDlgItem(hdlg, IDC_CHECK_MPU401); temp_mpu401 = SendMessage(h, BM_GETCHECK, 0, 0); @@ -1292,6 +1355,9 @@ win_settings_sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) h = GetDlgItem(hdlg, IDC_COMBO_MIDI); temp_midi_device = settings_list_to_midi[SendMessage(h, CB_GETCURSEL, 0, 0)]; + h = GetDlgItem(hdlg, IDC_COMBO_MIDI_IN); + temp_midi_input_device = settings_list_to_midi_in[SendMessage(h, CB_GETCURSEL, 0, 0)]; + h = GetDlgItem(hdlg, IDC_CHECK_MPU401); temp_mpu401 = SendMessage(h, BM_GETCHECK, 0, 0); From e8dd8c377450077a76369c2d345c5f1e72e9c989 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Thu, 2 Jan 2020 18:19:22 +0100 Subject: [PATCH 023/177] Fixed midi input code. Currently only MPU401 (standalone) and SB cards have MIDI Input capabilities, es1371 and GUS will be done for a later time. --- src/sound/midi.c | 38 +++---- src/sound/midi.h | 7 +- src/sound/midi_system.c | 12 +-- src/sound/snd_mpu401.c | 222 ++++++++++++++++------------------------ src/sound/snd_sb.c | 30 +++--- src/sound/snd_sb_dsp.c | 56 +++++----- src/sound/snd_sb_dsp.h | 5 +- src/win/win_midi.c | 78 +++++++------- 8 files changed, 199 insertions(+), 249 deletions(-) diff --git a/src/sound/midi.c b/src/sound/midi.c index 7648c8c92..98c5100a0 100644 --- a/src/sound/midi.c +++ b/src/sound/midi.c @@ -45,10 +45,11 @@ static int midi_device_last = 0; int midi_input_device_current = 0; static int midi_input_device_last = 0; -midi_t *midi = NULL; +midi_t *midi = NULL, *midi_in = NULL; -void (*input_msg)(uint8_t *msg); -int (*input_sysex)(uint8_t *buffer, uint32_t len, int abort); +void (*input_msg)(void *p, uint8_t *msg); +int (*input_sysex)(void *p, uint8_t *buffer, uint32_t len, int abort); +void *midi_in_p; uint8_t MIDI_InSysexBuf[SYSEX_SIZE]; @@ -202,14 +203,14 @@ midi_close(void) void midi_in_close(void) { - if (midi && midi->m_in_device) { - free(midi->m_in_device); - midi->m_in_device = NULL; + if (midi_in && midi_in->m_in_device) { + free(midi_in->m_in_device); + midi_in->m_in_device = NULL; } - if (midi) { - free(midi); - midi = NULL; + if (midi_in) { + free(midi_in); + midi_in = NULL; } } @@ -300,24 +301,21 @@ midi_in_device_init() void midi_raw_out_rt_byte(uint8_t val) { - if (!midi || !midi->m_out_device || !midi->m_in_device) + if (!midi_in->midi_realtime) return; - if (!midi->midi_realtime) - return; - - if ((!midi->midi_clockout && (val == 0xf8))) + if ((!midi_in->midi_clockout && (val == 0xf8))) return; - midi->midi_cmd_r = val << 24; + midi_in->midi_cmd_r = val << 24; pclog("Play RT Byte msg\n"); - play_msg((uint8_t *)&midi->midi_cmd_r); + play_msg((uint8_t *)&midi_in->midi_cmd_r); } void midi_raw_out_thru_rt_byte(uint8_t val) { - if (midi->thruchan) + if (midi_in->thruchan) midi_raw_out_rt_byte(val); } @@ -326,11 +324,13 @@ midi_raw_out_byte(uint8_t val) { uint32_t passed_ticks; - if (!midi || !midi->m_out_device) + if (!midi || !midi->m_out_device) { return; + } - if ((midi->m_out_device->write && midi->m_out_device->write(val))) + if ((midi->m_out_device->write && midi->m_out_device->write(val))) { return; + } if (midi->midi_sysex_start) { passed_ticks = plat_get_ticks() - midi->midi_sysex_start; diff --git a/src/sound/midi.h b/src/sound/midi.h index 21441646c..8e516c2a3 100644 --- a/src/sound/midi.h +++ b/src/sound/midi.h @@ -10,8 +10,9 @@ extern uint8_t MIDI_evt_len[256]; extern int midi_device_current; extern int midi_input_device_current; -extern void (*input_msg)(uint8_t *msg); -extern int (*input_sysex)(uint8_t *buffer, uint32_t len, int abort); +extern void (*input_msg)(void *p, uint8_t *msg); +extern int (*input_sysex)(void *p, uint8_t *buffer, uint32_t len, int abort); +extern void *midi_in_p; int midi_device_available(int card); int midi_in_device_available(int card); @@ -50,7 +51,7 @@ typedef struct midi_t midi_device_t *m_out_device, *m_in_device; } midi_t; -extern midi_t *midi; +extern midi_t *midi, *midi_in; void midi_init(midi_device_t* device); void midi_in_init(midi_device_t* device, midi_t **mididev); diff --git a/src/sound/midi_system.c b/src/sound/midi_system.c index f3ace5c69..6ee56b01a 100644 --- a/src/sound/midi_system.c +++ b/src/sound/midi_system.c @@ -17,8 +17,6 @@ void* system_midi_init(const device_t *info) midi_device_t* dev = malloc(sizeof(midi_device_t)); memset(dev, 0, sizeof(midi_device_t)); - pclog("MIDI Output\n"); - dev->play_msg = plat_midi_play_msg; dev->play_sysex = plat_midi_play_sysex; dev->write = plat_midi_write; @@ -35,15 +33,13 @@ void* midi_input_init(const device_t *info) midi_device_t* dev = malloc(sizeof(midi_device_t)); memset(dev, 0, sizeof(midi_device_t)); - pclog("MIDI Input\n"); - plat_midi_input_init(); - midi_in_init(dev, &midi); + midi_in_init(dev, &midi_in); - midi->midi_realtime = device_get_config_int("realtime"); - midi->thruchan = device_get_config_int("thruchan"); - midi->midi_clockout = device_get_config_int("clockout"); + midi_in->midi_realtime = device_get_config_int("realtime"); + midi_in->thruchan = device_get_config_int("thruchan"); + midi_in->midi_clockout = device_get_config_int("clockout"); return dev; } diff --git a/src/sound/snd_mpu401.c b/src/sound/snd_mpu401.c index f30517a2c..33fbe16b4 100644 --- a/src/sound/snd_mpu401.c +++ b/src/sound/snd_mpu401.c @@ -56,8 +56,6 @@ static void MPU401_EOIHandler(void *priv); static void MPU401_EOIHandlerDispatch(void *p); static void MPU401_NotesOff(mpu_t *mpu, int i); -static mpu_t *mpuin; -static mutex_t *mpu_lock; #ifdef ENABLE_MPU401_LOG int mpu401_do_log = ENABLE_MPU401_LOG; @@ -79,12 +77,6 @@ mpu401_log(const char *fmt, ...) #endif -void -mpu401_set_midi_in(mpu_t *src_mpu_in) -{ - mpuin = src_mpu_in; -} - static void MPU401_ReCalcClock(mpu_t *mpu) { @@ -169,14 +161,7 @@ static void MPU401_RecQueueBuffer(mpu_t *mpu, uint8_t *buf, uint32_t len, int block) { uint32_t cnt; - - if (block) { - if (mpu_lock) - thread_wait_mutex(mpu_lock); - else - return; - } - + cnt = 0; while (cnt < len) { if (mpu->rec_queue_used < MPU401_INPUT_QUEUE) { @@ -195,8 +180,6 @@ MPU401_RecQueueBuffer(mpu_t *mpu, uint8_t *buf, uint32_t len, int block) if (mpu->queue_used == 0) { if (mpu->state.rec_copy || mpu->state.irq_pending) { - if (block && mpu_lock) - thread_release_mutex(mpu_lock); if (mpu->state.irq_pending) { picintc(1 << mpu->irq); mpu->state.irq_pending = 0; @@ -210,9 +193,6 @@ MPU401_RecQueueBuffer(mpu_t *mpu, uint8_t *buf, uint32_t len, int block) mpu->rec_queue_used--; mpu->rec_queue_pos++; } - - if (block && mpu_lock) - thread_release_mutex(mpu_lock); } static void @@ -341,8 +321,6 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) if ((val != 0x3f) && (val != 0xff) && !mpu->intelligent) return; - thread_wait_mutex(mpu_lock); - /*hack:enable midi through after the first mpu401 command is written*/ mpu->midi_thru = 1; @@ -402,7 +380,6 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) MPU401_QueueByte(mpu, MSG_MPU_END); mpu->filter.prchg_mask = 0; mpu->clock.rec_counter = 0; - thread_release_mutex(mpu_lock); return; case 0x20: /* Start */ if (!(mpu->state.rec == M_RECON)) { @@ -430,7 +407,6 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) MPU401_RecQueueBuffer(mpu, recmsg, 3, 0); mpu->filter.prchg_mask &= ~(1 << i); } - thread_release_mutex(mpu_lock); } else if ((val >= 0xa0) && (val <= 0xa7)) { /* Request play counter */ MPU401_QueueByte(mpu, mpu->playbuf[val & 7].counter); } else if ((val >= 0xd0) && (val <= 0xd7)) { /* Send data */ @@ -545,22 +521,18 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) case 0xab: /* Request and clear recording counter */ MPU401_QueueByte(mpu, MSG_MPU_ACK); MPU401_QueueByte(mpu, 0); - thread_release_mutex(mpu_lock); return; case 0xac: /* Request version */ MPU401_QueueByte(mpu, MSG_MPU_ACK); MPU401_QueueByte(mpu, MPU401_VERSION); - thread_release_mutex(mpu_lock); return; case 0xad: /* Request revision */ MPU401_QueueByte(mpu, MSG_MPU_ACK); MPU401_QueueByte(mpu, MPU401_REVISION); - thread_release_mutex(mpu_lock); return; case 0xaf: /* Request tempo */ MPU401_QueueByte(mpu, MSG_MPU_ACK); MPU401_QueueByte(mpu, mpu->clock.tempo); - thread_release_mutex(mpu_lock); return; case 0xb1: /* Reset relative tempo */ mpu->clock.old_tempo_rel = mpu->clock.tempo_rel; @@ -623,7 +595,6 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) } MPU401_QueueByte(mpu, MSG_MPU_ACK); - thread_release_mutex(mpu_lock); } @@ -790,13 +761,10 @@ MPU401_WriteData(mpu_t *mpu, uint8_t val) return; } - thread_wait_mutex(mpu_lock); - if (mpu->state.cond_req) { /* Command */ switch (mpu->state.data_onoff) { case -1: - thread_release_mutex(mpu_lock); return; case 0: /* Timing byte */ mpu->condbuf.length = 0; @@ -833,7 +801,6 @@ MPU401_WriteData(mpu_t *mpu, uint8_t val) mpu->state.cond_req = 0; break; } - thread_release_mutex(mpu_lock); return; } @@ -848,7 +815,6 @@ MPU401_WriteData(mpu_t *mpu, uint8_t val) mpu->state.data_onoff = -1; MPU401_EOIHandlerDispatch(mpu); mpu->state.track_req = 0; - thread_release_mutex(mpu_lock); return; } mpu->state.send_now = !val ? 1 : 0; @@ -879,7 +845,6 @@ MPU401_WriteData(mpu_t *mpu, uint8_t val) mpu->state.data_onoff = -1; MPU401_EOIHandler(mpu); mpu->state.track_req = 0; - thread_release_mutex(mpu_lock); return; default: /* MIDI with running status */ cnt++; @@ -901,7 +866,6 @@ MPU401_WriteData(mpu_t *mpu, uint8_t val) break; } - thread_release_mutex(mpu_lock); return; } @@ -1070,8 +1034,7 @@ MPU401_ReadData(mpu_t *mpu) uint8_t ret; ret = MSG_MPU_ACK; - thread_wait_mutex(mpu_lock); - + if (mpu->queue_used) { if (mpu->queue_pos >= MPU401_QUEUE) mpu->queue_pos -= MPU401_QUEUE; @@ -1085,7 +1048,6 @@ MPU401_ReadData(mpu_t *mpu) if (mpu->state.irq_pending) { picintc(1 << mpu->irq); mpu->state.irq_pending = 0; - thread_release_mutex(mpu_lock); } return ret; @@ -1094,7 +1056,6 @@ MPU401_ReadData(mpu_t *mpu) if (mpu->state.rec_copy && !mpu->rec_queue_used) { mpu->state.rec_copy = 0; MPU401_EOIHandler(mpu); - thread_release_mutex(mpu_lock); return ret; } @@ -1137,8 +1098,6 @@ MPU401_ReadData(mpu_t *mpu) MPU401_EOIHandlerDispatch(mpu); } - thread_release_mutex(mpu_lock); - return(ret); } @@ -1251,9 +1210,7 @@ MPU401_Event(void *priv) } } if (!mpu->state.irq_pending && mpu->state.req_mask) { - thread_wait_mutex(mpu_lock); MPU401_EOIHandler(mpu); - thread_release_mutex(mpu_lock); } next_event: @@ -1291,42 +1248,44 @@ MPU401_NotesOff(mpu_t *mpu, int i) /*Input handler for SysEx */ static int -MPU401_InputSysex(uint8_t *buffer, uint32_t len, int abort) +MPU401_InputSysex(void *p, uint8_t *buffer, uint32_t len, int abort) { - pclog("MPU401 Input Sysex\n"); + mpu_t *mpu = (mpu_t *)p; + + mpu401_log("MPU401 Input Sysex\n"); int i; - if (mpuin->filter.sysex_in) { + if (mpu->filter.sysex_in) { if (abort) { - mpuin->state.sysex_in_finished=1; - mpuin->rec_queue_used=0;/*reset also the input queue*/ + mpu->state.sysex_in_finished=1; + mpu->rec_queue_used=0;/*reset also the input queue*/ return 0; } - if (mpuin->state.sysex_in_finished) { - if (mpuin->rec_queue_used>=MPU401_INPUT_QUEUE) + if (mpu->state.sysex_in_finished) { + if (mpu->rec_queue_used>=MPU401_INPUT_QUEUE) return len; uint8_t val_ff=0xff; - MPU401_RecQueueBuffer(mpuin,&val_ff,1,1); - mpuin->state.sysex_in_finished=0; - mpuin->clock.rec_counter=0; + MPU401_RecQueueBuffer(mpu,&val_ff,1,1); + mpu->state.sysex_in_finished=0; + mpu->clock.rec_counter=0; } - if (mpuin->rec_queue_used>=MPU401_INPUT_QUEUE) + if (mpu->rec_queue_used>=MPU401_INPUT_QUEUE) return len; - int available=MPU401_INPUT_QUEUE-mpuin->rec_queue_used; + int available=MPU401_INPUT_QUEUE-mpu->rec_queue_used; if (available>=len) { - MPU401_RecQueueBuffer(mpuin,buffer,len,1); + MPU401_RecQueueBuffer(mpu,buffer,len,1); return 0; } else { - MPU401_RecQueueBuffer(mpuin,buffer,available,1); - if (mpuin->state.sysex_in_finished) + MPU401_RecQueueBuffer(mpu,buffer,available,1); + if (mpu->state.sysex_in_finished) return 0; return (len-available); } } - else if (mpuin->filter.sysex_thru && mpuin->midi_thru) { + else if (mpu->filter.sysex_thru && mpu->midi_thru) { midi_raw_out_byte(0xf0); for (i=0;istate.sysex_in_finished) { - pclog("SYSEX in progress\n"); + if (!mpu->state.sysex_in_finished) { + mpu401_log("SYSEX in progress\n"); return; } + + mpu401_log("MPU401 Input Msg\n"); int i; static uint8_t old_msg=0; @@ -1354,41 +1315,41 @@ MPU401_InputMsg(uint8_t *msg) int send_thru=0; int retrigger_thru=0; int midistatus=0; - if (mpuin->mode==M_INTELLIGENT) { + if (mpu->mode==M_INTELLIGENT) { if (msg[0]<0x80) { /* Expand running status */ midistatus=1; msg[2]=msg[1];msg[1]=msg[0];msg[0]=old_msg; } old_msg=msg[0]; int chan=msg[0]&0xf; - int chrefnum=mpuin->ch_toref[chan]; + int chrefnum=mpu->ch_toref[chan]; uint8_t key=msg[1]&0x7f; if (msg[0]<0xf0) { //if non-system msg - if (!(mpuin->state.midi_mask&(1<filter.all_thru) + if (!(mpu->state.midi_mask&(1<filter.all_thru) send_thru=1; - else if (mpuin->filter.midi_thru) + else if (mpu->filter.midi_thru) send_thru=1; switch (msg[0]&0xf0) { case 0x80: /*note off*/ if (send_thru) { - if (mpuin->chanref[chrefnum].on && (mpuin->chanref[chrefnum].M_GETKEY)) + if (mpu->chanref[chrefnum].on && (mpu->chanref[chrefnum].M_GETKEY)) send_thru=0; - if (!mpuin->filter.midi_thru) + if (!mpu->filter.midi_thru) break; - if (!(mpuin->inputref[chan].M_GETKEY)) + if (!(mpu->inputref[chan].M_GETKEY)) send_thru=0; - mpuin->inputref[chan].M_DELKEY; + mpu->inputref[chan].M_DELKEY; } break; case 0x90: /*note on*/ if (send_thru) { - if (mpuin->chanref[chrefnum].on && (mpuin->chanref[chrefnum].M_GETKEY)) + if (mpu->chanref[chrefnum].on && (mpu->chanref[chrefnum].M_GETKEY)) retrigger_thru=1; - if (!mpuin->filter.midi_thru) + if (!mpu->filter.midi_thru) break; - if (mpuin->inputref[chan].M_GETKEY) + if (mpu->inputref[chan].M_GETKEY) retrigger_thru=1; - mpuin->inputref[chan].M_SETKEY; + mpu->inputref[chan].M_SETKEY; } break; case 0xb0: @@ -1396,112 +1357,112 @@ MPU401_InputMsg(uint8_t *msg) send_thru=0; if (msg[1]==123) { /* All notes off */ for (key=0;key<128;key++) { - if (!(mpuin->chanref[chrefnum].on && (mpuin->chanref[chrefnum].M_GETKEY))) - if (mpuin->inputref[chan].on && mpuin->inputref[chan].M_GETKEY) { + if (!(mpu->chanref[chrefnum].on && (mpu->chanref[chrefnum].M_GETKEY))) + if (mpu->inputref[chan].on && mpu->inputref[chan].M_GETKEY) { midi_raw_out_byte(0x80|chan); midi_raw_out_byte(key); midi_raw_out_byte(0); } - mpuin->inputref[chan].M_DELKEY; + mpu->inputref[chan].M_DELKEY; } } } break; } } - if (msg[0]>=0xf0 || (mpuin->state.midi_mask&(1<=0xf0 || (mpu->state.midi_mask&(1<filter.bender_in) + if (!mpu->filter.bender_in) send=0; break; case 0xb0: /*control change*/ - if (!mpuin->filter.bender_in && msg[1]<64) + if (!mpu->filter.bender_in && msg[1]<64) send=0; if (msg[1]>=120) { - if (mpuin->filter.modemsgs_in) + if (mpu->filter.modemsgs_in) send=1; } break; case 0xc0: /*program change*/ - if ((mpuin->state.rec!=M_RECON) && !mpuin->filter.data_in_stop) { - mpuin->filter.prchg_buf[chan]=msg[1]; - mpuin->filter.prchg_mask|=1<state.rec!=M_RECON) && !mpu->filter.data_in_stop) { + mpu->filter.prchg_buf[chan]=msg[1]; + mpu->filter.prchg_mask|=1<filter.bender_in) + if (!mpu->filter.bender_in) send=0; break; case 0xf0: //system message if (msg[0]==0xf8) { send=0; - if (mpuin->clock.active && mpuin->state.sync_in) { + if (mpu->clock.active && mpu->state.sync_in) { send = 0;/*don't pass to host in this mode?*/ - int tick=mpuin->clock.timebase/24; - if (mpuin->clock.ticks_in!=tick) { - if (!mpuin->clock.ticks_in || (mpuin->clock.ticks_in>tick*2)) - mpuin->clock.freq_mod*=2.0; + int tick=mpu->clock.timebase/24; + if (mpu->clock.ticks_in!=tick) { + if (!mpu->clock.ticks_in || (mpu->clock.ticks_in>tick*2)) + mpu->clock.freq_mod*=2.0; else { - if (ABS(mpuin->clock.ticks_in-tick)==1) - mpuin->clock.freq_mod/=mpuin->clock.ticks_in/(float)(tick*2); + if (ABS(mpu->clock.ticks_in-tick)==1) + mpu->clock.freq_mod/=mpu->clock.ticks_in/(float)(tick*2); else - mpuin->clock.freq_mod/=mpuin->clock.ticks_in/(float)(tick); + mpu->clock.freq_mod/=mpu->clock.ticks_in/(float)(tick); } - MPU401_ReCalcClock(mpuin); + MPU401_ReCalcClock(mpu); } - mpuin->clock.ticks_in=0; + mpu->clock.ticks_in=0; } } else if (msg[0]>0xf8) { /*realtime*/ - if (!(mpuin->filter.rt_in && msg[0]<=0xfc && msg[0]>=0xfa)) { + if (!(mpu->filter.rt_in && msg[0]<=0xfc && msg[0]>=0xfa)) { uint8_t recdata[2]={0xff,msg[0]}; - MPU401_RecQueueBuffer(mpuin,recdata,2,1); + MPU401_RecQueueBuffer(mpu,recdata,2,1); send=0; } } else { /*common or system*/ send=0; if (msg[0]==0xf2 || msg[0]==0xf3 || msg[0]==0xf6) { - if (mpuin->filter.commonmsgs_in) + if (mpu->filter.commonmsgs_in) send=1; - if (mpuin->filter.commonmsgs_thru) + if (mpu->filter.commonmsgs_thru) for (i=0;ifilter.rt_affection) switch(msg[0]) { + if (mpu->filter.rt_affection) switch(msg[0]) { case 0xf2:case 0xf3: - mpuin->state.block_ack=1; - MPU401_WriteCommand(mpuin,0xb8);/*clear play counters*/ + mpu->state.block_ack=1; + MPU401_WriteCommand(mpu,0xb8);/*clear play counters*/ break; case 0xfa: - mpuin->state.block_ack=1; - MPU401_WriteCommand(mpuin,0xa);/*start,play*/ - if (mpuin->filter.rt_out) + mpu->state.block_ack=1; + MPU401_WriteCommand(mpu,0xa);/*start,play*/ + if (mpu->filter.rt_out) midi_raw_out_rt_byte(msg[0]); break; case 0xfb: - mpuin->state.block_ack=1; - MPU401_WriteCommand(mpuin,0xb);/*continue,play*/ - if (mpuin->filter.rt_out) + mpu->state.block_ack=1; + MPU401_WriteCommand(mpu,0xb);/*continue,play*/ + if (mpu->filter.rt_out) midi_raw_out_rt_byte(msg[0]); break; case 0xfc: - mpuin->state.block_ack=1; - MPU401_WriteCommand(mpuin,0xd);/*stop: play,rec,midi*/ - if (mpuin->filter.rt_out) + mpu->state.block_ack=1; + MPU401_WriteCommand(mpu,0xd);/*stop: play,rec,midi*/ + if (mpu->filter.rt_out) midi_raw_out_rt_byte(msg[0]); break; } return; } - if (send_thru && mpuin->midi_thru) { + if (send_thru && mpu->midi_thru) { if (retrigger_thru) { midi_raw_out_byte(0x80|(msg[0]&0xf)); midi_raw_out_byte(msg[1]); @@ -1511,29 +1472,29 @@ MPU401_InputMsg(uint8_t *msg) midi_raw_out_byte(msg[i]); } if (send) { - if (mpuin->state.rec==M_RECON) { - uint8_t recmsg[4]={mpuin->clock.rec_counter,msg[0],msg[1],msg[2]}; - MPU401_RecQueueBuffer(mpuin,recmsg,len+1,1); - mpuin->clock.rec_counter=0; + if (mpu->state.rec==M_RECON) { + uint8_t recmsg[4]={mpu->clock.rec_counter,msg[0],msg[1],msg[2]}; + MPU401_RecQueueBuffer(mpu,recmsg,len+1,1); + mpu->clock.rec_counter=0; } - else if (mpuin->filter.data_in_stop) { - if (mpuin->filter.timing_in_stop) { + else if (mpu->filter.data_in_stop) { + if (mpu->filter.timing_in_stop) { uint8_t recmsg[4]={0,msg[0],msg[1],msg[2]}; - MPU401_RecQueueBuffer(mpuin,recmsg,len+1,1); + MPU401_RecQueueBuffer(mpu,recmsg,len+1,1); } else { uint8_t recmsg[4]={msg[0],msg[1],msg[2],0}; - MPU401_RecQueueBuffer(mpuin,recmsg,len,1); + MPU401_RecQueueBuffer(mpu,recmsg,len,1); } } } return; } /*UART mode input*/ - thread_wait_mutex(mpu_lock); - for (i=0;iirq); + } } @@ -1644,10 +1605,9 @@ mpu401_standalone_init(const device_t *info) irq = device_get_config_int("irq"); } - mpu401_set_midi_in(mpu); - mpu_lock = thread_create_mutex(L"86Box.MPU401Mutex"); input_msg = MPU401_InputMsg; input_sysex = MPU401_InputSysex; + midi_in_p = mpu; mpu401_init(mpu, base, irq, M_INTELLIGENT); @@ -1660,8 +1620,6 @@ mpu401_standalone_close(void *priv) { mpu_t *mpu = (mpu_t *)priv; - thread_close_mutex(mpu_lock); - free(mpu); } diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index 23f5812a9..f86e85cd9 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -189,12 +189,6 @@ sb_log(const char *fmt, ...) #endif -static void -sb_dsp_set_midi_in(sb_dsp_t *src_dsp_midi_in) -{ - dspin = src_dsp_midi_in; -} - /* sb 1, 1.5, 2, 2 mvc do not have a mixer, so signal is hardwired */ static void sb_get_buffer_sb2(int32_t *buffer, int len, void *p) { @@ -1049,9 +1043,9 @@ void *sb_1_init() } sound_add_handler(sb_get_buffer_sb2, sb); - sb_dsp_set_midi_in(&sb->dsp); input_msg = sb_dsp_input_msg; - input_sysex = sb_dsp_input_sysex; + input_sysex = sb_dsp_input_sysex; + midi_in_p = &sb->dsp; return sb; } @@ -1080,9 +1074,9 @@ void *sb_15_init() } sound_add_handler(sb_get_buffer_sb2, sb); - sb_dsp_set_midi_in(&sb->dsp); input_msg = sb_dsp_input_msg; - input_sysex = sb_dsp_input_sysex; + input_sysex = sb_dsp_input_sysex; + midi_in_p = &sb->dsp; return sb; } @@ -1108,9 +1102,9 @@ void *sb_mcv_init() sb->pos_regs[0] = 0x84; sb->pos_regs[1] = 0x50; - sb_dsp_set_midi_in(&sb->dsp); input_msg = sb_dsp_input_msg; - input_sysex = sb_dsp_input_sysex; + input_sysex = sb_dsp_input_sysex; + midi_in_p = &sb->dsp; return sb; } @@ -1159,9 +1153,9 @@ void *sb_2_init() else sound_add_handler(sb_get_buffer_sb2, sb); - sb_dsp_set_midi_in(&sb->dsp); input_msg = sb_dsp_input_msg; input_sysex = sb_dsp_input_sysex; + midi_in_p = &sb->dsp; return sb; } @@ -1196,9 +1190,9 @@ void *sb_pro_v1_init() io_sethandler(addr+4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, sb); sound_add_handler(sb_get_buffer_sbpro, sb); - sb_dsp_set_midi_in(&sb->dsp); input_msg = sb_dsp_input_msg; input_sysex = sb_dsp_input_sysex; + midi_in_p = &sb->dsp; return sb; } @@ -1232,9 +1226,9 @@ void *sb_pro_v2_init() io_sethandler(addr+4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, sb); sound_add_handler(sb_get_buffer_sbpro, sb); - sb_dsp_set_midi_in(&sb->dsp); input_msg = sb_dsp_input_msg; input_sysex = sb_dsp_input_sysex; + midi_in_p = &sb->dsp; return sb; } @@ -1261,9 +1255,9 @@ void *sb_pro_mcv_init() sb->pos_regs[0] = 0x03; sb->pos_regs[1] = 0x51; - sb_dsp_set_midi_in(&sb->dsp); input_msg = sb_dsp_input_msg; input_sysex = sb_dsp_input_sysex; + midi_in_p = &sb->dsp; return sb; } @@ -1300,9 +1294,9 @@ void *sb_16_init() sb->mpu = NULL; - sb_dsp_set_midi_in(&sb->dsp); input_msg = sb_dsp_input_msg; input_sysex = sb_dsp_input_sysex; + midi_in_p = &sb->dsp; return sb; } @@ -1348,9 +1342,9 @@ void *sb_awe32_init() sb->mpu = NULL; emu8k_init(&sb->emu8k, emu_addr, onboard_ram); - sb_dsp_set_midi_in(&sb->dsp); input_msg = sb_dsp_input_msg; input_sysex = sb_dsp_input_sysex; + midi_in_p = &sb->dsp; return sb; } diff --git a/src/sound/snd_sb_dsp.c b/src/sound/snd_sb_dsp.c index 51188ee03..dc40de587 100644 --- a/src/sound/snd_sb_dsp.c +++ b/src/sound/snd_sb_dsp.c @@ -119,7 +119,7 @@ uint8_t adjustMap2[24] = { }; float low_fir_sb16_coef[SB16_NCoef]; -sb_dsp_t *dspin; + #ifdef ENABLE_SB_DSP_LOG int sb_dsp_do_log = ENABLE_SB_DSP_LOG; @@ -458,19 +458,19 @@ sb_exec_command(sb_dsp_t *dsp) sb_start_dma_i(dsp, 1, 1, 0, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); break; case 0x30: /* MIDI Polling mode input */ - pclog("MIDI polling mode input\n"); + sb_dsp_log("MIDI polling mode input\n"); dsp->midi_in_poll = 1; dsp->uart_irq = 0; break; case 0x31: /* MIDI Interrupt mode input */ - pclog("MIDI interrupt mode input\n"); + sb_dsp_log("MIDI interrupt mode input\n"); dsp->midi_in_poll = 0; dsp->uart_irq = 1; break; case 0x34: /* MIDI In poll */ if (dsp->sb_type < SB2) break; - pclog("MIDI poll in\n"); + sb_dsp_log("MIDI poll in\n"); dsp->midi_in_poll = 1; dsp->uart_midi = 1; dsp->uart_irq = 0; @@ -478,7 +478,7 @@ sb_exec_command(sb_dsp_t *dsp) case 0x35: /* MIDI In irq */ if (dsp->sb_type < SB2) break; - pclog("MIDI irq in\n"); + sb_dsp_log("MIDI irq in\n"); dsp->midi_in_poll = 0; dsp->uart_midi = 1; dsp->uart_irq = 1; @@ -836,44 +836,50 @@ sb_dsp_set_mpu(mpu_t *src_mpu) } void -sb_dsp_input_msg(uint8_t *msg) +sb_dsp_input_msg(void *p, uint8_t *msg) { - pclog("MIDI in sysex = %d, uart irq = %d, midi in = %d\n", dspin->midi_in_sysex, dspin->uart_irq, dspin->midi_in_poll); + sb_dsp_t *dsp = (sb_dsp_t *) p; - if (dspin->midi_in_sysex) { + sb_dsp_log("MIDI in sysex = %d, uart irq = %d, msg = %d\n", dsp->midi_in_sysex, dsp->uart_irq, msg[3]); + + if (dsp->midi_in_sysex) { return; } uint8_t len = msg[3]; uint8_t i = 0; - if (dspin->uart_irq) { + if (dsp->uart_irq) { for (i=0;isb_irq8) sb_irq(dspin, 1); - } else if (dspin->midi_in_poll) { + sb_add_data(dsp, msg[i]); + sb_dsp_log("SB IRQ8 = %d\n", dsp->sb_irq8); + if (!dsp->sb_irq8) + picint(1 << dsp->sb_irqnum); + } else if (dsp->midi_in_poll) { for (i=0;imidi_in_sysex = 0; + dsp->midi_in_sysex = 0; return 0; } - dspin->midi_in_sysex = 1; + dsp->midi_in_sysex = 1; for (i=0;isb_read_rp == dspin->sb_read_wp) { - pclog("Length sysex SB = %d\n", len-i); + if (dsp->sb_read_rp == dsp->sb_read_wp) { + sb_dsp_log("Length sysex SB = %d\n", len-i); return (len-i); } - sb_add_data(dspin, buffer[i]); + sb_add_data(dsp, buffer[i]); } - dspin->midi_in_sysex = 0; + dsp->midi_in_sysex = 0; return 0; } @@ -943,7 +949,7 @@ pollsb(void *p) break; dsp->sbdat = (data[0] ^ 0x80) << 8; if ((dsp->sb_type >= SBPRO) && (dsp->sb_type < SB16) && dsp->stereo) { - pclog("pollsb: Mono unsigned, dsp->stereo, %s channel, %04X\n", + sb_dsp_log("pollsb: Mono unsigned, dsp->stereo, %s channel, %04X\n", dsp->sbleftright ? "left" : "right", dsp->sbdat); if (dsp->sbleftright) dsp->sbdatl = dsp->sbdat; @@ -960,7 +966,7 @@ pollsb(void *p) break; dsp->sbdat = data[0] << 8; if ((dsp->sb_type >= SBPRO) && (dsp->sb_type < SB16) && dsp->stereo) { - pclog("pollsb: Mono signed, dsp->stereo, %s channel, %04X\n", + sb_dsp_log("pollsb: Mono signed, dsp->stereo, %s channel, %04X\n", dsp->sbleftright ? "left" : "right", data[0], dsp->sbdat); if (dsp->sbleftright) dsp->sbdatl = dsp->sbdat; @@ -1020,7 +1026,7 @@ pollsb(void *p) } if ((dsp->sb_type >= SBPRO) && (dsp->sb_type < SB16) && dsp->stereo) { - pclog("pollsb: ADPCM 4, dsp->stereo, %s channel, %04X\n", + sb_dsp_log("pollsb: ADPCM 4, dsp->stereo, %s channel, %04X\n", dsp->sbleftright ? "left" : "right", dsp->sbdat); if (dsp->sbleftright) dsp->sbdatl = dsp->sbdat; @@ -1063,7 +1069,7 @@ pollsb(void *p) } if ((dsp->sb_type >= SBPRO) && (dsp->sb_type < SB16) && dsp->stereo) { - pclog("pollsb: ADPCM 26, dsp->stereo, %s channel, %04X\n", + sb_dsp_log("pollsb: ADPCM 26, dsp->stereo, %s channel, %04X\n", dsp->sbleftright ? "left" : "right", dsp->sbdat); if (dsp->sbleftright) dsp->sbdatl = dsp->sbdat; @@ -1099,7 +1105,7 @@ pollsb(void *p) } if ((dsp->sb_type >= SBPRO) && (dsp->sb_type < SB16) && dsp->stereo) { - pclog("pollsb: ADPCM 2, dsp->stereo, %s channel, %04X\n", + sb_dsp_log("pollsb: ADPCM 2, dsp->stereo, %s channel, %04X\n", dsp->sbleftright ? "left" : "right", dsp->sbdat); if (dsp->sbleftright) dsp->sbdatl = dsp->sbdat; diff --git a/src/sound/snd_sb_dsp.h b/src/sound/snd_sb_dsp.h index 2c7022912..9e60dfaac 100644 --- a/src/sound/snd_sb_dsp.h +++ b/src/sound/snd_sb_dsp.h @@ -76,11 +76,10 @@ typedef struct sb_dsp_t int pos; } sb_dsp_t; -extern sb_dsp_t *dspin; -void sb_dsp_input_msg(uint8_t *msg); +void sb_dsp_input_msg(void *p, uint8_t *msg); -int sb_dsp_input_sysex(uint8_t *buffer, uint32_t len, int abort); +int sb_dsp_input_sysex(void *p, uint8_t *buffer, uint32_t len, int abort); void sb_dsp_set_mpu(mpu_t *src_mpu); diff --git a/src/win/win_midi.c b/src/win/win_midi.c index 239fd7a77..256ab6a5e 100644 --- a/src/win/win_midi.c +++ b/src/win/win_midi.c @@ -16,15 +16,14 @@ typedef struct int midi_id, midi_input_id; HANDLE m_event; - HANDLE m_callback; HMIDIOUT midi_out_device; HMIDIIN midi_in_device; - MIDIHDR m_hdr, m_hdr_in; + MIDIHDR m_hdr; } plat_midi_t; -plat_midi_t *pm = NULL; +plat_midi_t *pm = NULL, *pm_in = NULL; void @@ -41,7 +40,6 @@ plat_midi_init(void) pm->m_event = CreateEvent(NULL, TRUE, TRUE, NULL); - pclog("Plat MIDI Out init\n"); hr = midiOutOpen(&pm->midi_out_device, pm->midi_id, (uintptr_t) pm->m_event, 0, CALLBACK_EVENT); if (hr != MMSYSERR_NOERROR) { @@ -140,30 +138,29 @@ plat_midi_write(uint8_t val) } void CALLBACK -plat_midi_in_callback(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) { - pclog("MIDI: wMsg:%x %x %x\n",wMsg, dwParam1, dwParam2); +plat_midi_in_callback(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) +{ uint8_t msg[4] = {((dwParam1&0xff)),(((dwParam1&0xff00)>>8)), (((dwParam1&0xff0000)>>16)),MIDI_evt_len[((dwParam1&0xff))]}; uint8_t *sysex; - int len; + uint32_t len; int cnt; - MIDIHDR *t_hdr; + MIDIHDR *hdr; switch (wMsg) { case MM_MIM_DATA: /* 0x3C3 - midi message */ - input_msg(msg); + input_msg(midi_in_p, msg); break; case MM_MIM_OPEN: /* 0x3C1 */ break; case MM_MIM_CLOSE: /* 0x3C2 */ break; case MM_MIM_LONGDATA: /* 0x3C4 - sysex */ - pclog("MIDI sysex\n"); - t_hdr = (MIDIHDR *)dwParam1; - sysex = (uint8_t *)t_hdr->lpData; - len = (unsigned int)t_hdr->dwBytesRecorded; + hdr = (MIDIHDR *)dwParam1; + sysex = (uint8_t *)hdr->lpData; + len = (uint32_t)hdr->dwBytesRecorded; cnt = 5; while (cnt) { /*abort if timed out*/ - int ret = input_sysex(sysex, len, 0); + int ret = input_sysex(midi_in_p, sysex, len, 0); if (!ret) { len = 0; break; @@ -177,11 +174,11 @@ plat_midi_in_callback(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance, DWORD_PT Sleep(5);/*msec*/ } if (len) - input_sysex(sysex, 0, 0); + input_sysex(midi_in_p, sysex, 0, 0); - midiInUnprepareHeader(hMidiIn, t_hdr, sizeof(*t_hdr)); - t_hdr->dwBytesRecorded = 0; - midiInPrepareHeader(hMidiIn, t_hdr, sizeof(*t_hdr)); + midiInUnprepareHeader(hMidiIn, hdr, sizeof(*hdr)); + hdr->dwBytesRecorded = 0; + midiInPrepareHeader(hMidiIn, hdr, sizeof(*hdr)); break; case MM_MIM_ERROR: case MM_MIM_LONGERROR: @@ -196,46 +193,45 @@ plat_midi_input_init(void) { MMRESULT hr; - pm = (plat_midi_t *) malloc(sizeof(plat_midi_t)); - memset(pm, 0, sizeof(plat_midi_t)); + pm_in = (plat_midi_t *) malloc(sizeof(plat_midi_t)); + memset(pm_in, 0, sizeof(plat_midi_t)); - pclog("Plat MIDI Input init\n"); - - pm->midi_input_id = config_get_int(MIDI_INPUT_NAME, "midi_input", 0); + pm_in->midi_input_id = config_get_int(MIDI_INPUT_NAME, "midi_input", 0); - hr = midiInOpen(&pm->midi_in_device, pm->midi_input_id, + hr = MMSYSERR_NOERROR; + + hr = midiInOpen(&pm_in->midi_in_device, pm_in->midi_input_id, (uintptr_t) plat_midi_in_callback, 0, CALLBACK_FUNCTION); if (hr != MMSYSERR_NOERROR) { - pclog("midiInOpen error - %08X\n", hr); - pm->midi_input_id = 0; - hr = midiInOpen(&pm->midi_in_device, pm->midi_input_id, + printf("midiInOpen error - %08X\n", hr); + pm_in->midi_input_id = 0; + hr = midiInOpen(&pm_in->midi_in_device, pm_in->midi_input_id, (uintptr_t) plat_midi_in_callback, 0, CALLBACK_FUNCTION); if (hr != MMSYSERR_NOERROR) { - pclog("midiInOpen error - %08X\n", hr); + printf("midiInOpen error - %08X\n", hr); return; } } - pm->m_hdr_in.lpData = (char*)&MIDI_InSysexBuf[0]; - pm->m_hdr_in.dwBufferLength = SYSEX_SIZE; - pm->m_hdr_in.dwBytesRecorded = 0 ; - pm->m_hdr_in.dwUser = 0; - pclog("Prepare MIDI In\n"); - midiInPrepareHeader(pm->midi_in_device,&pm->m_hdr_in,sizeof(pm->m_hdr_in)); - midiInStart(pm->midi_in_device); + pm_in->m_hdr.lpData = (char*)&MIDI_InSysexBuf[0]; + pm_in->m_hdr.dwBufferLength = SYSEX_SIZE; + pm_in->m_hdr.dwBytesRecorded = 0; + pm_in->m_hdr.dwUser = 0; + midiInPrepareHeader(pm_in->midi_in_device,&pm_in->m_hdr,sizeof(pm_in->m_hdr)); + midiInStart(pm_in->midi_in_device); } void plat_midi_input_close(void) { - if (pm) { - if (pm->midi_in_device != NULL) { - midiInStop(pm->midi_in_device); - midiInClose(pm->midi_in_device); + if (pm_in) { + if (pm_in->midi_in_device != NULL) { + midiInStop(pm_in->midi_in_device); + midiInClose(pm_in->midi_in_device); } - free(pm); - pm = NULL; + free(pm_in); + pm_in = NULL; } } From f7ffe8a2479d06afd9a4d87a40856bea2552a689 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 4 Jan 2020 03:32:20 +0100 Subject: [PATCH 024/177] Fixed coding style and IRQ handling per the spec. Also made commands other than 0xFF ignored in UART mode, also per the spec. --- src/sound/snd_mpu401.c | 852 ++++++++++++++++++++++------------------- 1 file changed, 452 insertions(+), 400 deletions(-) diff --git a/src/sound/snd_mpu401.c b/src/sound/snd_mpu401.c index 33fbe16b4..5b4d2635b 100644 --- a/src/sound/snd_mpu401.c +++ b/src/sound/snd_mpu401.c @@ -80,58 +80,63 @@ mpu401_log(const char *fmt, ...) static void MPU401_ReCalcClock(mpu_t *mpu) { - int32_t maxtempo = 240, mintempo = 16; - - if (mpu->clock.timebase >= 168) - maxtempo = 179; - if (mpu->clock.timebase == 144) - maxtempo = 208; - if (mpu->clock.timebase >= 120) - maxtempo = 8; - - mpu->clock.freq = ((uint32_t)(mpu->clock.tempo * 2 * mpu->clock.tempo_rel)) >> 6; - mpu->clock.freq = mpu->clock.timebase * (mpu->clock.freq < (mintempo * 2) ? mintempo : - ((mpu->clock.freq / 2) < maxtempo ? (mpu->clock.freq / 2) : maxtempo)); + int32_t maxtempo = 240, mintempo = 16; + int32_t freq; - if (mpu->state.sync_in) { - int32_t freq = (int32_t)((float)(mpu->clock.freq) * mpu->clock.freq_mod); + if (mpu->clock.timebase >= 168) + maxtempo = 179; + if (mpu->clock.timebase == 144) + maxtempo = 208; + if (mpu->clock.timebase >= 120) + maxtempo = 8; + + mpu->clock.freq = ((uint32_t)(mpu->clock.tempo * 2 * mpu->clock.tempo_rel)) >> 6; + mpu->clock.freq = mpu->clock.timebase * (mpu->clock.freq < (mintempo * 2) ? mintempo : + ((mpu->clock.freq / 2) < maxtempo ? (mpu->clock.freq / 2) : maxtempo)); + + if (mpu->state.sync_in) { + freq = (int32_t)((float)(mpu->clock.freq) * mpu->clock.freq_mod); if ((freq > (mpu->clock.timebase * mintempo)) && (freq < (mpu->clock.timebase * maxtempo))) - mpu->clock.freq = freq; - } + mpu->clock.freq = freq; + } } + static void MPU401_StartClock(mpu_t *mpu) { - if (mpu->clock.active) - return; - if (!(mpu->state.clock_to_host || mpu->state.playing || (mpu->state.rec == M_RECON))) - return; - - mpu->clock.active = 1; - timer_set_delay_u64(&mpu->mpu401_event_callback, (MPU401_TIMECONSTANT / mpu->clock.freq) * 1000 * TIMER_USEC); + if (mpu->clock.active) + return; + if (!(mpu->state.clock_to_host || mpu->state.playing || (mpu->state.rec == M_RECON))) + return; + + mpu->clock.active = 1; + timer_set_delay_u64(&mpu->mpu401_event_callback, (MPU401_TIMECONSTANT / mpu->clock.freq) * 1000 * TIMER_USEC); } + static void MPU401_StopClock(mpu_t *mpu) { - if (mpu->state.clock_to_host || mpu->state.playing || (mpu->state.rec == M_RECON)) - return; - mpu->clock.active = 0; - timer_disable(&mpu->mpu401_event_callback); + if (mpu->state.clock_to_host || mpu->state.playing || (mpu->state.rec == M_RECON)) + return; + mpu->clock.active = 0; + timer_disable(&mpu->mpu401_event_callback); } + static void MPU401_RunClock(mpu_t *mpu) { - if (!mpu->clock.active) { - timer_disable(&mpu->mpu401_event_callback); - return; - } - timer_set_delay_u64(&mpu->mpu401_event_callback, (MPU401_TIMECONSTANT / mpu->clock.freq) * 1000 * TIMER_USEC); - mpu401_log("Next event after %i us (time constant: %i)\n", (uint64_t) ((MPU401_TIMECONSTANT/mpu->clock.freq) * 1000 * TIMER_USEC), (int) MPU401_TIMECONSTANT); + if (!mpu->clock.active) { + timer_disable(&mpu->mpu401_event_callback); + return; + } + timer_set_delay_u64(&mpu->mpu401_event_callback, (MPU401_TIMECONSTANT / mpu->clock.freq) * 1000 * TIMER_USEC); + mpu401_log("Next event after %i us (time constant: %i)\n", (uint64_t) ((MPU401_TIMECONSTANT/mpu->clock.freq) * 1000 * TIMER_USEC), (int) MPU401_TIMECONSTANT); } + static void MPU401_QueueByte(mpu_t *mpu, uint8_t data) { @@ -139,11 +144,12 @@ MPU401_QueueByte(mpu_t *mpu, uint8_t data) mpu->state.block_ack = 0; return; } - - if ((mpu->queue_used == 0) && (mpu->mode == M_INTELLIGENT)) { + + if (mpu->queue_used == 0) { mpu->state.irq_pending = 1; picint(1 << mpu->irq); } + if (mpu->queue_used < MPU401_QUEUE) { int pos = mpu->queue_used+mpu->queue_pos; @@ -157,33 +163,35 @@ MPU401_QueueByte(mpu_t *mpu, uint8_t data) } } + static void MPU401_RecQueueBuffer(mpu_t *mpu, uint8_t *buf, uint32_t len, int block) { - uint32_t cnt; + uint32_t cnt = 0; + int pos; - cnt = 0; - while (cnt < len) { + while (cnt < len) { if (mpu->rec_queue_used < MPU401_INPUT_QUEUE) { - int pos = mpu->rec_queue_used + mpu->rec_queue_pos; - if (pos >= MPU401_INPUT_QUEUE) - pos -= MPU401_INPUT_QUEUE; - mpu->rec_queue[pos] = buf[cnt]; - mpu->rec_queue_used++; - if ((!mpu->state.sysex_in_finished) && (buf[cnt] == MSG_EOX)) { /*finish sysex*/ - mpu->state.sysex_in_finished = 1; - break; + pos = mpu->rec_queue_used + mpu->rec_queue_pos; + if (pos >= MPU401_INPUT_QUEUE) + pos -= MPU401_INPUT_QUEUE; + mpu->rec_queue[pos] = buf[cnt]; + mpu->rec_queue_used++; + if ((!mpu->state.sysex_in_finished) && (buf[cnt] == MSG_EOX)) { + /* finish sysex */ + mpu->state.sysex_in_finished = 1; + break; + } + cnt++; } - cnt++; - } - } - - if (mpu->queue_used == 0) { + } + + if (mpu->queue_used == 0) { if (mpu->state.rec_copy || mpu->state.irq_pending) { if (mpu->state.irq_pending) { - picintc(1 << mpu->irq); - mpu->state.irq_pending = 0; - } + picintc(1 << mpu->irq); + mpu->state.irq_pending = 0; + } return; } mpu->state.rec_copy = 1; @@ -192,18 +200,19 @@ MPU401_RecQueueBuffer(mpu_t *mpu, uint8_t *buf, uint32_t len, int block) MPU401_QueueByte(mpu, mpu->rec_queue[mpu->rec_queue_pos]); mpu->rec_queue_used--; mpu->rec_queue_pos++; - } + } } + static void MPU401_ClrQueue(mpu_t *mpu) { mpu->queue_used = 0; mpu->queue_pos = 0; - mpu->rec_queue_used = 0; - mpu->rec_queue_pos = 0; - mpu->state.sysex_in_finished = 1; - mpu->state.irq_pending = 0; + mpu->rec_queue_used = 0; + mpu->rec_queue_pos = 0; + mpu->state.sysex_in_finished = 1; + mpu->state.irq_pending = 0; } @@ -218,8 +227,8 @@ MPU401_Reset(mpu_t *mpu) } mpu->mode = M_INTELLIGENT; - mpu->midi_thru = 0; - mpu->state.rec = M_RECOFF; + mpu->midi_thru = 0; + mpu->state.rec = M_RECOFF; mpu->state.eoi_scheduled = 0; mpu->state.wsd = 0; mpu->state.wsm = 0; @@ -236,38 +245,38 @@ MPU401_Reset(mpu_t *mpu) mpu->clock.tempo = mpu->clock.old_tempo = 100; mpu->clock.timebase = mpu->clock.old_timebase = 120; mpu->clock.tempo_rel = mpu->clock.old_tempo_rel = 0x40; - mpu->clock.freq_mod = 1.0; + mpu->clock.freq_mod = 1.0; mpu->clock.tempo_grad = 0; - MPU401_StopClock(mpu); - MPU401_ReCalcClock(mpu); - - for (i = 0; i < 4; i++) - mpu->clock.cth_rate[i] = 60; - - mpu->clock.cth_counter = 0; - mpu->clock.midimetro = 12; - mpu->clock.metromeas = 8; - mpu->filter.rec_measure_end = 1; - mpu->filter.rt_out = 1; - mpu->filter.rt_affection = 1; - mpu->filter.allnotesoff_out = 1; - mpu->filter.all_thru = 1; - mpu->filter.midi_thru = 1; - mpu->filter.commonmsgs_thru = 1; + MPU401_StopClock(mpu); + MPU401_ReCalcClock(mpu); - /*reset channel reference and input tables*/ - for (i = 0; i < 4; i++) { + for (i = 0; i < 4; i++) + mpu->clock.cth_rate[i] = 60; + + mpu->clock.cth_counter = 0; + mpu->clock.midimetro = 12; + mpu->clock.metromeas = 8; + mpu->filter.rec_measure_end = 1; + mpu->filter.rt_out = 1; + mpu->filter.rt_affection = 1; + mpu->filter.allnotesoff_out = 1; + mpu->filter.all_thru = 1; + mpu->filter.midi_thru = 1; + mpu->filter.commonmsgs_thru = 1; + + /* Reset channel reference and input tables. */ + for (i = 0; i < 4; i++) { mpu->chanref[i].on = 1; mpu->chanref[i].chan = i; mpu->ch_toref[i] = i; - } - - for (i = 0; i < 16; i++) { + } + + for (i = 0; i < 16; i++) { mpu->inputref[i].on = 1; mpu->inputref[i].chan = i; if (i > 3) - mpu->ch_toref[i] = 4;/*dummy reftable*/ - } + mpu->ch_toref[i] = 4; /* Dummy reftable. */ + } MPU401_ClrQueue(mpu); mpu->state.data_onoff = -1; @@ -276,19 +285,19 @@ MPU401_Reset(mpu_t *mpu) mpu->condbuf.counter = 0; mpu->condbuf.type = T_OVERFLOW; - for (i=0;i<8;i++) { + for (i = 0; i < 8; i++) { mpu->playbuf[i].type = T_OVERFLOW; mpu->playbuf[i].counter = 0; } - - /*clear MIDI buffers, terminate notes*/ - midi_clear_buffer(); - - for (i = 0xb0; i <= 0xbf; i++) { - midi_raw_out_byte(i); - midi_raw_out_byte(0x7b); - midi_raw_out_byte(0); - } + + /* Clear MIDI buffers, terminate notes. */ + midi_clear_buffer(); + + for (i = 0xb0; i <= 0xbf; i++) { + midi_raw_out_byte(i); + midi_raw_out_byte(0x7b); + midi_raw_out_byte(0); + } } @@ -313,16 +322,21 @@ MPU401_ResetDone(void *priv) static void MPU401_WriteCommand(mpu_t *mpu, uint8_t val) { - uint8_t i, j, was_uart; + uint8_t i, j, was_uart, recmsg[3]; if (mpu->state.reset) mpu->state.cmd_pending = val + 1; - if ((val != 0x3f) && (val != 0xff) && !mpu->intelligent) - return; + /* The only command recognized in UART mode is 0xFF: Reset and return to Intelligent mode. */ + if ((val != 0xff) && (mpu->mode == M_UART)) + return; - /*hack:enable midi through after the first mpu401 command is written*/ - mpu->midi_thru = 1; + /* In Intelligent mode, UART-only variants of the MPU-401 only support commands 0x3F and 0xFF. */ + if ((val != 0x3f) && (val != 0xff) && !mpu->intelligent) + return; + + /* Hack: Enable midi through after the first mpu401 command is written. */ + mpu->midi_thru = 1; if (val <= 0x2f) { /* Sequencer state */ int send_prchg = 0; @@ -383,16 +397,17 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) return; case 0x20: /* Start */ if (!(mpu->state.rec == M_RECON)) { - mpu->clock.rec_counter = 0; - mpu->state.rec = M_RECSTB; + mpu->clock.rec_counter = 0; + mpu->state.rec = M_RECSTB; } if ((mpu->state.last_rtcmd == 0xfa) || (mpu->state.last_rtcmd == 0xfb)) { - mpu->clock.rec_counter = 0; - mpu->state.rec = M_RECON; - if (mpu->filter.prchg_mask) - send_prchg = 1; - MPU401_StartClock(mpu); + mpu->clock.rec_counter = 0; + mpu->state.rec = M_RECON; + if (mpu->filter.prchg_mask) + send_prchg = 1; + MPU401_StartClock(mpu); } + break; } } MPU401_QueueByte(mpu, MSG_MPU_ACK); @@ -401,21 +416,26 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) if (((val == 0x20) || (val == 0x26)) && (mpu->state.rec == M_RECON)) MPU401_RecQueueBuffer(mpu, &rec_cnt, 1, 0); - if (send_prchg) for (i = 0; i < 16; i++) - if (mpu->filter.prchg_mask & (1 << i)) { - uint8_t recmsg[3] = {mpu->clock.rec_counter, 0xc0 | i, mpu->filter.prchg_buf[i]}; - MPU401_RecQueueBuffer(mpu, recmsg, 3, 0); - mpu->filter.prchg_mask &= ~(1 << i); + if (send_prchg) { + for (i = 0; i < 16; i++) { + if (mpu->filter.prchg_mask & (1 << i)) { + recmsg[0] = mpu->clock.rec_counter; + recmsg[1] = 0xc0 | i; + recmsg[2] = mpu->filter.prchg_buf[i]; + MPU401_RecQueueBuffer(mpu, recmsg, 3, 0); + mpu->filter.prchg_mask &= ~(1 << i); + } + } } - } else if ((val >= 0xa0) && (val <= 0xa7)) { /* Request play counter */ + } else if ((val >= 0xa0) && (val <= 0xa7)) /* Request play counter */ MPU401_QueueByte(mpu, mpu->playbuf[val & 7].counter); - } else if ((val >= 0xd0) && (val <= 0xd7)) { /* Send data */ + else if ((val >= 0xd0) && (val <= 0xd7)) { /* Send data */ mpu->state.old_track = mpu->state.track; mpu->state.track= val & 7; mpu->state.wsd = 1; mpu->state.wsm = 0; mpu->state.wsd_start = 1; - } else if ((val < 0x80) && (val >= 0x40)) { /* Set reference table channel */ + } else if ((val < 0x80) && (val >= 0x40)) { /* Set reference table channel */ mpu->chanref[(val >> 4) - 4].on = 1; mpu->chanref[(val >> 4) - 4].chan = val & 0x0f; mpu->chanref[(val >> 4) - 4].trmask = 0; @@ -438,9 +458,9 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) mpu->filter.commonmsgs_thru = 0; mpu->filter.midi_thru = 0; for (i = 0; i < 16; i++) { - mpu->inputref[i].on = 0; - for (j = 0; i < 4; j++) - mpu->inputref[i].key[j] = 0; + mpu->inputref[i].on = 0; + for (j = 0; i < 4; j++) + mpu->inputref[i].key[j] = 0; } break; case 0x34: @@ -459,7 +479,7 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) mpu->filter.rt_in = 1; break; case 0x3f: /* UART mode */ - mpu401_log("MPU-401:Set UART mode %X\n",val); + mpu401_log("MPU-401: Set UART mode %X\n",val); MPU401_QueueByte(mpu, MSG_MPU_ACK); mpu->mode = M_UART; return; @@ -481,11 +501,11 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) case 0x88: case 0x89: /* MIDI through */ mpu->filter.midi_thru = !!(val & 1); for (i = 0; i < 16; i++) { - mpu->inputref[i].on = mpu->filter.midi_thru; - if (!(val & 1)) { - for (j = 0; j < 4; j++) - mpu->inputref[i].key[j] = 0; - } + mpu->inputref[i].on = mpu->filter.midi_thru; + if (!(val & 1)) { + for (j = 0; j < 4; j++) + mpu->inputref[i].key[j] = 0; + } } break; case 0x8a: case 0x8b: /* Data in stop */ @@ -581,7 +601,7 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) mpu->state.command_byte = val; break; case 0xff: /* Reset MPU-401 */ - mpu401_log("MPU-401:Reset %X\n",val); + mpu401_log("MPU-401: Reset %X\n", val); timer_set_delay_u64(&mpu->mpu401_reset_callback, MPU401_RESETBUSY * 33LL * TIMER_USEC); mpu->state.reset = 1; was_uart = (mpu->mode == M_UART); @@ -1028,6 +1048,21 @@ imf_write(uint16_t addr, uint8_t val, void *priv) } +void +MPU401_ReadRaiseIRQ(mpu_t *mpu) +{ + /* Clear IRQ. */ + picintc(1 << mpu->irq); + mpu->state.irq_pending = 0; + + if (mpu->queue_used) { + /* Bytes remaining in queue, raise IRQ again. */ + mpu->state.irq_pending = 1; + picint(1 << mpu->irq); + } +} + + uint8_t MPU401_ReadData(mpu_t *mpu) { @@ -1045,35 +1080,28 @@ MPU401_ReadData(mpu_t *mpu) /* Shouldn't this check mpu->mode? */ if (mpu->mode == M_UART) { - if (mpu->state.irq_pending) { - picintc(1 << mpu->irq); - mpu->state.irq_pending = 0; - } - + MPU401_ReadRaiseIRQ(mpu); return ret; } - if (mpu->state.rec_copy && !mpu->rec_queue_used) { + if (mpu->state.rec_copy && !mpu->rec_queue_used) { mpu->state.rec_copy = 0; MPU401_EOIHandler(mpu); return ret; - } + } - /*copy from recording buffer*/ - if (!mpu->queue_used && mpu->rec_queue_used) { + /* Copy from recording buffer. */ + if (!mpu->queue_used && mpu->rec_queue_used) { mpu->state.rec_copy = 1; if (mpu->rec_queue_pos >= MPU401_INPUT_QUEUE) mpu->rec_queue_pos -= MPU401_INPUT_QUEUE; MPU401_QueueByte(mpu, mpu->rec_queue[mpu->rec_queue_pos]); mpu->rec_queue_pos++; mpu->rec_queue_used--; - } - - if (mpu->queue_used == 0) { - picintc(1 << mpu->irq); - mpu->state.irq_pending = 0; } + MPU401_ReadRaiseIRQ(mpu); + if ((ret >= 0xf0) && (ret <= 0xf7)) { /* MIDI data request */ mpu->state.track = ret & 7; @@ -1094,11 +1122,10 @@ MPU401_ReadData(mpu_t *mpu) } } - if ((ret == MSG_MPU_END) || (ret == MSG_MPU_CLOCK) || (ret == MSG_MPU_ACK) || (ret == MSG_MPU_OVERFLOW)) { + if ((ret == MSG_MPU_END) || (ret == MSG_MPU_CLOCK) || (ret == MSG_MPU_ACK) || (ret == MSG_MPU_OVERFLOW)) MPU401_EOIHandlerDispatch(mpu); - } - return(ret); + return ret; } @@ -1135,8 +1162,10 @@ mpu401_read(uint16_t addr, void *priv) break; case 1: /* Read Status */ - if (mpu->state.cmd_pending) ret=STATUS_OUTPUT_NOT_READY; - if (!mpu->queue_used) ret=STATUS_INPUT_NOT_READY; + if (mpu->state.cmd_pending) + ret = STATUS_OUTPUT_NOT_READY; + if (!mpu->queue_used) + ret = STATUS_INPUT_NOT_READY; ret |= 0x3f; mpu401_log("Read Status (0x331) %x\n", ret); @@ -1153,6 +1182,7 @@ MPU401_Event(void *priv) { mpu_t *mpu = (mpu_t *)priv; uint8_t i; + int max_meascnt; mpu401_log("MPU-401 event callback\n"); @@ -1163,22 +1193,24 @@ MPU401_Event(void *priv) if (mpu->state.irq_pending) goto next_event; - if (mpu->state.playing) { - for (i = 0; i < 8; i++) { /* Decrease counters */ - if (mpu->state.amask & (1 << i)) { - mpu->playbuf[i].counter--; - if (mpu->playbuf[i].counter <= 0) UpdateTrack(mpu, i); - } - } + if (mpu->state.playing) { + for (i = 0; i < 8; i++) { + /* Decrease counters. */ + if (mpu->state.amask & (1 << i)) { + mpu->playbuf[i].counter--; + if (mpu->playbuf[i].counter <= 0) + UpdateTrack(mpu, i); + } + } - if (mpu->state.conductor) { - mpu->condbuf.counter--; - if (mpu->condbuf.counter <= 0) { - mpu->condbuf.counter = 0xf0; - mpu->state.req_mask |= (1 << 9); + if (mpu->state.conductor) { + mpu->condbuf.counter--; + if (mpu->condbuf.counter <= 0) { + mpu->condbuf.counter = 0xf0; + mpu->state.req_mask |= (1 << 9); + } } } - } if (mpu->state.clock_to_host) { mpu->clock.cth_counter++; @@ -1189,108 +1221,108 @@ MPU401_Event(void *priv) } } - if (mpu->state.rec==M_RECON) { /* recording */ - mpu->clock.rec_counter++; - if (mpu->clock.rec_counter>=240) { - mpu->clock.rec_counter=0; - mpu->state.req_mask|=(1<<8); - } + if (mpu->state.rec == M_RECON) { + /* Recording. */ + mpu->clock.rec_counter++; + if (mpu->clock.rec_counter>=240) { + mpu->clock.rec_counter=0; + mpu->state.req_mask|=(1<<8); } + } - if (mpu->state.playing || (mpu->state.rec == M_RECON)) { - int max_meascnt = (mpu->clock.timebase * mpu->clock.midimetro * mpu->clock.metromeas) / 24; - if (max_meascnt != 0) { /* measure end */ - if (++mpu->clock.measure_counter >= max_meascnt) { - if (mpu->filter.rt_out) - midi_raw_out_rt_byte(0xf8); - mpu->clock.measure_counter = 0; - if (mpu->filter.rec_measure_end && (mpu->state.rec == M_RECON)) - mpu->state.req_mask |= (1 << 12); - } + if (mpu->state.playing || (mpu->state.rec == M_RECON)) { + max_meascnt = (mpu->clock.timebase * mpu->clock.midimetro * mpu->clock.metromeas) / 24; + if (max_meascnt != 0) { + /* Measure end. */ + if (++mpu->clock.measure_counter >= max_meascnt) { + if (mpu->filter.rt_out) + midi_raw_out_rt_byte(0xf8); + mpu->clock.measure_counter = 0; + if (mpu->filter.rec_measure_end && (mpu->state.rec == M_RECON)) + mpu->state.req_mask |= (1 << 12); } } - if (!mpu->state.irq_pending && mpu->state.req_mask) { + } + if (!mpu->state.irq_pending && mpu->state.req_mask) MPU401_EOIHandler(mpu); - } next_event: - MPU401_RunClock(mpu); - if (mpu->state.sync_in) - mpu->clock.ticks_in++; + MPU401_RunClock(mpu); + if (mpu->state.sync_in) + mpu->clock.ticks_in++; } + static void MPU401_NotesOff(mpu_t *mpu, int i) { - int j; - uint8_t key; - - if (mpu->filter.allnotesoff_out && !(mpu->inputref[i].on && - (mpu->inputref[i].key[0]|mpu->inputref[i].key[1]| - mpu->inputref[i].key[2]|mpu->inputref[i].key[3]))) { - for (j=0;j<4;j++) - mpu->chanref[mpu->ch_toref[i]].key[j]=0; - midi_raw_out_byte(0xb0|i); - midi_raw_out_byte(123); - midi_raw_out_byte(0); - } else if (mpu->chanref[mpu->ch_toref[i]].on) { - for (key=0;key<128;key++) { - if ((mpu->chanref[mpu->ch_toref[i]].M_GETKEY) && - !(mpu->inputref[i].on && (mpu->inputref[i].M_GETKEY))) { - midi_raw_out_byte(0x80|i); - midi_raw_out_byte(key); - midi_raw_out_byte(0); - } - mpu->chanref[mpu->ch_toref[i]].M_DELKEY; + int j; + uint8_t key; + + if (mpu->filter.allnotesoff_out && !(mpu->inputref[i].on && + (mpu->inputref[i].key[0] | mpu->inputref[i].key[1] | + mpu->inputref[i].key[2] | mpu->inputref[i].key[3]))) { + for (j=0;j<4;j++) + mpu->chanref[mpu->ch_toref[i]].key[j]=0; + midi_raw_out_byte(0xb0 | i); + midi_raw_out_byte(123); + midi_raw_out_byte(0); + } else if (mpu->chanref[mpu->ch_toref[i]].on) { + for (key = 0; key < 128; key++) { + if ((mpu->chanref[mpu->ch_toref[i]].M_GETKEY) && + !(mpu->inputref[i].on && (mpu->inputref[i].M_GETKEY))) { + midi_raw_out_byte(0x80|i); + midi_raw_out_byte(key); + midi_raw_out_byte(0); } + mpu->chanref[mpu->ch_toref[i]].M_DELKEY; } + } } + /*Input handler for SysEx */ static int MPU401_InputSysex(void *p, uint8_t *buffer, uint32_t len, int abort) { - mpu_t *mpu = (mpu_t *)p; - - mpu401_log("MPU401 Input Sysex\n"); - - int i; - - if (mpu->filter.sysex_in) { - if (abort) { - mpu->state.sysex_in_finished=1; - mpu->rec_queue_used=0;/*reset also the input queue*/ - return 0; - } - if (mpu->state.sysex_in_finished) { - if (mpu->rec_queue_used>=MPU401_INPUT_QUEUE) - return len; - uint8_t val_ff=0xff; - MPU401_RecQueueBuffer(mpu,&val_ff,1,1); - mpu->state.sysex_in_finished=0; - mpu->clock.rec_counter=0; - } + mpu_t *mpu = (mpu_t *)p; + int i; + uint8_t val_ff = 0xff; + + mpu401_log("MPU401 Input Sysex\n"); + + if (mpu->filter.sysex_in) { + if (abort) { + mpu->state.sysex_in_finished=1; + mpu->rec_queue_used=0;/*reset also the input queue*/ + return 0; + } + if (mpu->state.sysex_in_finished) { if (mpu->rec_queue_used>=MPU401_INPUT_QUEUE) return len; - int available=MPU401_INPUT_QUEUE-mpu->rec_queue_used; + MPU401_RecQueueBuffer(mpu, &val_ff, 1, 1); + mpu->state.sysex_in_finished=0; + mpu->clock.rec_counter=0; + } + if (mpu->rec_queue_used>=MPU401_INPUT_QUEUE) + return len; + int available = MPU401_INPUT_QUEUE - mpu->rec_queue_used; - if (available>=len) { - MPU401_RecQueueBuffer(mpu,buffer,len,1); + if (available >= len) { + MPU401_RecQueueBuffer(mpu, buffer, len, 1); + return 0; + } else { + MPU401_RecQueueBuffer(mpu,buffer, available, 1); + if (mpu->state.sysex_in_finished) return 0; - } - else { - MPU401_RecQueueBuffer(mpu,buffer,available,1); - if (mpu->state.sysex_in_finished) - return 0; - return (len-available); - } + return (len - available); } - else if (mpu->filter.sysex_thru && mpu->midi_thru) { - midi_raw_out_byte(0xf0); - for (i=0;ifilter.sysex_thru && mpu->midi_thru) { + midi_raw_out_byte(0xf0); + for (i = 0; i < len; i++) + midi_raw_out_byte(*(buffer+i)); + } + return 0; } @@ -1298,203 +1330,222 @@ MPU401_InputSysex(void *p, uint8_t *buffer, uint32_t len, int abort) static void MPU401_InputMsg(void *p, uint8_t *msg) { - mpu_t *mpu = (mpu_t *)p; + mpu_t *mpu = (mpu_t *)p; + int i, tick; + static uint8_t old_msg = 0; + uint8_t len = msg[3], key; + uint8_t recdata[2], recmsg[4]; + int send = 1, send_thru = 0; + int retrigger_thru = 0, midistatus = 0, chan, chrefnum; - /*abort if sysex transfer is in progress*/ - if (!mpu->state.sysex_in_finished) { - mpu401_log("SYSEX in progress\n"); - return; + /* Abort if sysex transfer is in progress. */ + if (!mpu->state.sysex_in_finished) { + mpu401_log("SYSEX in progress\n"); + return; + } + + mpu401_log("MPU401 Input Msg\n"); + + if (mpu->mode == M_INTELLIGENT) { + if (msg[0] < 0x80) { + /* Expand running status */ + midistatus = 1; + msg[2] = msg[1]; + msg[1] = msg[0]; + msg[0] = old_msg; } - - mpu401_log("MPU401 Input Msg\n"); - - int i; - static uint8_t old_msg=0; - uint8_t len=msg[3]; - int send=1; - int send_thru=0; - int retrigger_thru=0; - int midistatus=0; - if (mpu->mode==M_INTELLIGENT) { - if (msg[0]<0x80) { /* Expand running status */ - midistatus=1; - msg[2]=msg[1];msg[1]=msg[0];msg[0]=old_msg; - } - old_msg=msg[0]; - int chan=msg[0]&0xf; - int chrefnum=mpu->ch_toref[chan]; - uint8_t key=msg[1]&0x7f; - if (msg[0]<0xf0) { //if non-system msg - if (!(mpu->state.midi_mask&(1<filter.all_thru) - send_thru=1; - else if (mpu->filter.midi_thru) - send_thru=1; - switch (msg[0]&0xf0) { - case 0x80: /*note off*/ - if (send_thru) { - if (mpu->chanref[chrefnum].on && (mpu->chanref[chrefnum].M_GETKEY)) - send_thru=0; - if (!mpu->filter.midi_thru) - break; - if (!(mpu->inputref[chan].M_GETKEY)) - send_thru=0; - mpu->inputref[chan].M_DELKEY; - } - break; - case 0x90: /*note on*/ - if (send_thru) { - if (mpu->chanref[chrefnum].on && (mpu->chanref[chrefnum].M_GETKEY)) - retrigger_thru=1; - if (!mpu->filter.midi_thru) - break; - if (mpu->inputref[chan].M_GETKEY) - retrigger_thru=1; - mpu->inputref[chan].M_SETKEY; - } - break; - case 0xb0: - if (msg[1]>=120) { - send_thru=0; - if (msg[1]==123) { /* All notes off */ - for (key=0;key<128;key++) { - if (!(mpu->chanref[chrefnum].on && (mpu->chanref[chrefnum].M_GETKEY))) - if (mpu->inputref[chan].on && mpu->inputref[chan].M_GETKEY) { - midi_raw_out_byte(0x80|chan); - midi_raw_out_byte(key); - midi_raw_out_byte(0); - } + old_msg = msg[0]; + chan = msg[0] & 0xf; + chrefnum = mpu->ch_toref[chan]; + key = msg[1] & 0x7f; + if (msg[0] < 0xf0) { + /* If non-system msg. */ + if (!(mpu->state.midi_mask & (1 << chan)) && mpu->filter.all_thru) + send_thru = 1; + else if (mpu->filter.midi_thru) + send_thru = 1; + switch (msg[0] & 0xf0) { + case 0x80: /* Note off. */ + if (send_thru) { + if (mpu->chanref[chrefnum].on && (mpu->chanref[chrefnum].M_GETKEY)) + send_thru = 0; + if (!mpu->filter.midi_thru) + break; + if (!(mpu->inputref[chan].M_GETKEY)) + send_thru = 0; + mpu->inputref[chan].M_DELKEY; + } + break; + case 0x90: /* Note on. */ + if (send_thru) { + if (mpu->chanref[chrefnum].on && (mpu->chanref[chrefnum].M_GETKEY)) + retrigger_thru = 1; + if (!mpu->filter.midi_thru) + break; + if (mpu->inputref[chan].M_GETKEY) + retrigger_thru = 1; + mpu->inputref[chan].M_SETKEY; + } + break; + case 0xb0: + if (msg[1] >= 120) { + send_thru = 0; + if (msg[1] == 123) { + /* All notes off. */ + for (key = 0; key < 128; key++) { + if (!(mpu->chanref[chrefnum].on && (mpu->chanref[chrefnum].M_GETKEY))) + if (mpu->inputref[chan].on && mpu->inputref[chan].M_GETKEY) { + midi_raw_out_byte(0x80 | chan); + midi_raw_out_byte(key); + midi_raw_out_byte(0); + } mpu->inputref[chan].M_DELKEY; } } } break; - } + } } - if (msg[0]>=0xf0 || (mpu->state.midi_mask&(1<filter.bender_in) - send=0; - break; - case 0xb0: /*control change*/ - if (!mpu->filter.bender_in && msg[1]<64) - send=0; - if (msg[1]>=120) { - if (mpu->filter.modemsgs_in) - send=1; - } - break; - case 0xc0: /*program change*/ - if ((mpu->state.rec!=M_RECON) && !mpu->filter.data_in_stop) { - mpu->filter.prchg_buf[chan]=msg[1]; - mpu->filter.prchg_mask|=1<filter.bender_in) - send=0; - break; - case 0xf0: //system message - if (msg[0]==0xf8) { - send=0; - if (mpu->clock.active && mpu->state.sync_in) { - send = 0;/*don't pass to host in this mode?*/ - int tick=mpu->clock.timebase/24; - if (mpu->clock.ticks_in!=tick) { - if (!mpu->clock.ticks_in || (mpu->clock.ticks_in>tick*2)) - mpu->clock.freq_mod*=2.0; - else { - if (ABS(mpu->clock.ticks_in-tick)==1) - mpu->clock.freq_mod/=mpu->clock.ticks_in/(float)(tick*2); - else - mpu->clock.freq_mod/=mpu->clock.ticks_in/(float)(tick); - } - MPU401_ReCalcClock(mpu); + } + if ((msg[0] >= 0xf0) || (mpu->state.midi_mask & (1 << chan))) { + switch (msg[0] & 0xf0) { + case 0xa0: /* Aftertouch. */ + if (!mpu->filter.bender_in) + send = 0; + break; + case 0xb0: /* Control change. */ + if (!mpu->filter.bender_in && (msg[1] < 64)) + send = 0; + if (msg[1] >= 120) { + if (mpu->filter.modemsgs_in) + send = 1; + } + break; + case 0xc0: /* Program change. */ + if ((mpu->state.rec != M_RECON) && !mpu->filter.data_in_stop) { + mpu->filter.prchg_buf[chan] = msg[1]; + mpu->filter.prchg_mask |= 1 << chan; + } + break; + case 0xd0: /* Ch pressure. */ + case 0xe0: /* Pitch wheel. */ + if (!mpu->filter.bender_in) + send = 0; + break; + case 0xf0: /* System message. */ + if (msg[0] == 0xf8) { + send = 0; + if (mpu->clock.active && mpu->state.sync_in) { + send = 0; /* Don't pass to host in this mode? */ + tick = mpu->clock.timebase / 24; + if (mpu->clock.ticks_in != tick) { + if (!mpu->clock.ticks_in || (mpu->clock.ticks_in > (tick * 2))) + mpu->clock.freq_mod *= 2.0; + else { + if (ABS(mpu->clock.ticks_in-tick) == 1) + mpu->clock.freq_mod /= mpu->clock.ticks_in / (float) (tick * 2); + else + mpu->clock.freq_mod /= mpu->clock.ticks_in / (float) (tick); } - mpu->clock.ticks_in=0; + MPU401_ReCalcClock(mpu); } + mpu->clock.ticks_in = 0; } - else if (msg[0]>0xf8) { /*realtime*/ - if (!(mpu->filter.rt_in && msg[0]<=0xfc && msg[0]>=0xfa)) { - uint8_t recdata[2]={0xff,msg[0]}; - MPU401_RecQueueBuffer(mpu,recdata,2,1); - send=0; - } + } else if (msg[0] > 0xf8) { /* Realtime. */ + if (!(mpu->filter.rt_in && (msg[0] <= 0xfc) && (msg[0] >= 0xfa))) { + recdata[0] = 0xff; + recdata[1] = msg[0]; + MPU401_RecQueueBuffer(mpu, recdata, 2, 1); + send = 0; } - else { /*common or system*/ - send=0; - if (msg[0]==0xf2 || msg[0]==0xf3 || msg[0]==0xf6) { - if (mpu->filter.commonmsgs_in) - send=1; - if (mpu->filter.commonmsgs_thru) - for (i=0;ifilter.commonmsgs_in) + send = 1; + if (mpu->filter.commonmsgs_thru) + for (i = 0; i < len; i++) + midi_raw_out_byte(msg[i]); } - if (send) { - uint8_t recmsg[4]={0xff,msg[0],msg[1],msg[2]}; - MPU401_RecQueueBuffer(mpu,recmsg,len+1,1); - } - if (mpu->filter.rt_affection) switch(msg[0]) { - case 0xf2:case 0xf3: - mpu->state.block_ack=1; - MPU401_WriteCommand(mpu,0xb8);/*clear play counters*/ + } + if (send) { + recmsg[0] = 0xff; + recmsg[1] = msg[0]; + recmsg[2] = msg[1]; + recmsg[3] = msg[2]; + MPU401_RecQueueBuffer(mpu, recmsg, len + 1, 1); + } + if (mpu->filter.rt_affection) { + switch(msg[0]) { + case 0xf2: case 0xf3: + mpu->state.block_ack = 1; + MPU401_WriteCommand(mpu, 0xb8); /* Clear play counters. */ break; case 0xfa: - mpu->state.block_ack=1; - MPU401_WriteCommand(mpu,0xa);/*start,play*/ + mpu->state.block_ack = 1; + MPU401_WriteCommand(mpu, 0xa); /* Start, play. */ if (mpu->filter.rt_out) midi_raw_out_rt_byte(msg[0]); break; case 0xfb: - mpu->state.block_ack=1; - MPU401_WriteCommand(mpu,0xb);/*continue,play*/ + mpu->state.block_ack = 1; + MPU401_WriteCommand(mpu, 0xb); /* Continue, play. */ if (mpu->filter.rt_out) midi_raw_out_rt_byte(msg[0]); break; case 0xfc: - mpu->state.block_ack=1; - MPU401_WriteCommand(mpu,0xd);/*stop: play,rec,midi*/ + mpu->state.block_ack = 1; + MPU401_WriteCommand(mpu, 0xd) ;/* Stop: Play, rec, midi */ if (mpu->filter.rt_out) midi_raw_out_rt_byte(msg[0]); break; } return; - } - if (send_thru && mpu->midi_thru) { - if (retrigger_thru) { - midi_raw_out_byte(0x80|(msg[0]&0xf)); - midi_raw_out_byte(msg[1]); - midi_raw_out_byte(msg[2]); - } - for (i=0/*((midistatus && !retrigger_thru)? 1:0)*/;istate.rec==M_RECON) { - uint8_t recmsg[4]={mpu->clock.rec_counter,msg[0],msg[1],msg[2]}; - MPU401_RecQueueBuffer(mpu,recmsg,len+1,1); - mpu->clock.rec_counter=0; - } - else if (mpu->filter.data_in_stop) { - if (mpu->filter.timing_in_stop) { - uint8_t recmsg[4]={0,msg[0],msg[1],msg[2]}; - MPU401_RecQueueBuffer(mpu,recmsg,len+1,1); - } - else { - uint8_t recmsg[4]={msg[0],msg[1],msg[2],0}; - MPU401_RecQueueBuffer(mpu,recmsg,len,1); - } + } + if (send_thru && mpu->midi_thru) { + if (retrigger_thru) { + midi_raw_out_byte(0x80 | (msg[0] & 0xf)); + midi_raw_out_byte(msg[1]); + midi_raw_out_byte(msg[2]); + } + for (i = 0; i < len; i++) + midi_raw_out_byte(msg[i]); + } + if (send) { + if (mpu->state.rec == M_RECON) { + recmsg[0] = mpu->clock.rec_counter; + recmsg[1] = msg[0]; + recmsg[2] = msg[1]; + recmsg[3] = msg[2]; + MPU401_RecQueueBuffer(mpu, recmsg, len + 1, 1); + mpu->clock.rec_counter = 0; + } + else if (mpu->filter.data_in_stop) { + if (mpu->filter.timing_in_stop) { + recmsg[0] = 0; + recmsg[1] = msg[0]; + recmsg[2] = msg[1]; + recmsg[3] = msg[2]; + MPU401_RecQueueBuffer(mpu, recmsg, len + 1, 1); + } else { + recmsg[0] = msg[0]; + recmsg[1] = msg[1]; + recmsg[2] = msg[2]; + recmsg[3] = 0; + MPU401_RecQueueBuffer(mpu, recmsg, len, 1); } } - return; - } - /*UART mode input*/ - for (i=0;iirq); } + return; + } + + /* UART mode input. */ + for (i = 0; i < len; i++) { + MPU401_QueueByte(mpu, msg[i]); + picint(1 << mpu->irq); + } } @@ -1530,7 +1581,8 @@ mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode) void mpu401_device_add(void) { - if (!mpu401_standalone_enable) return; + if (!mpu401_standalone_enable) + return; if (machines[machine].flags & MACHINE_MCA) device_add(&mpu401_mca_device); From 8e1c0f5337c11d949f3abb376d280ae4c725b1e5 Mon Sep 17 00:00:00 2001 From: nerd73 Date: Fri, 3 Jan 2020 22:59:49 -0700 Subject: [PATCH 025/177] CPU table revamp - Added IBM 486SLC2/40 because somehow I didn't know it existed - Revoked Dynarec support on the IBM 486 CPUs after several PS/2 machines were buggy with it - Disallowed Pentium OverDrive and 3.3V 486 CPUs on the AMI 486 clone, Award 486 clone, IBM PS/1 2133, and IBM PS/2 model 70 Type 4 due to discovery that they used either Socket 1 or the original 486 socket - Disallowed split-rail voltage CPUs (P55C, 6x86L/6x86MX, K6) on all Socket 7 FX and some HX motherboards that don't support it - Fixed a lot of wrong multipliers on 5th-generation CPUs - Added mem and cache cycles for the faster K6-2s/K6-3s above 300 MHz --- src/cpu/cpu.h | 11 +- src/cpu/cpu_table.c | 438 ++++++++++++++--------- src/cpu_new/cpu.h | 8 +- src/cpu_new/cpu_table.c | 613 +++++++++++++++++++------------- src/machine/machine_table.c | 28 +- src/machine/machine_table_new.c | 27 +- 6 files changed, 685 insertions(+), 440 deletions(-) diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 9fbd2b56a..52b5fb41f 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -108,6 +108,9 @@ extern CPU cpus_486DLC[]; extern CPU cpus_IBM386SLC[]; extern CPU cpus_IBM486SLC[]; extern CPU cpus_IBM486BL[]; +extern CPU cpus_i486S1[]; +extern CPU cpus_Am486S1[]; +extern CPU cpus_Cx486S1[]; extern CPU cpus_i486[]; extern CPU cpus_Am486[]; extern CPU cpus_Cx486[]; @@ -115,14 +118,20 @@ extern CPU cpus_WinChip[]; extern CPU cpus_Pentium5V[]; extern CPU cpus_Pentium5V50[]; extern CPU cpus_PentiumS5[]; +extern CPU cpus_Pentium3V[]; +extern CPU cpus_Pentium[]; #ifdef DEV_BRANCH #ifdef USE_AMD_K extern CPU cpus_K5[]; extern CPU cpus_K56[]; #endif #endif -extern CPU cpus_Pentium[]; +#ifdef DEV_BRANCH +#ifdef USE_CYRIX_6X86 +extern CPU cpus_6x863V[]; extern CPU cpus_6x86[]; +#endif +#endif #ifdef DEV_BRANCH #ifdef USE_I686 extern CPU cpus_PentiumPro[]; diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index 12a63f2a7..d097afc24 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -97,7 +97,7 @@ CPU cpus_286[] = { {"286/6", CPU_286, 6000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1}, {"286/8", CPU_286, 8000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1}, {"286/10", CPU_286, 10000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1}, - {"286/12", CPU_286, 12000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2}, + {"286/12", CPU_286, 12500000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2}, {"286/16", CPU_286, 16000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2}, {"286/20", CPU_286, 20000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3}, {"286/25", CPU_286, 25000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3}, @@ -126,7 +126,7 @@ CPU cpus_ps1_m2011[] = { CPU cpus_ps2_m30_286[] = { /*286*/ {"286/10", CPU_286, 10000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1}, - {"286/12", CPU_286, 12000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2}, + {"286/12", CPU_286, 12500000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2}, {"286/16", CPU_286, 16000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2}, {"286/20", CPU_286, 20000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3}, {"286/25", CPU_286, 25000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3}, @@ -183,21 +183,22 @@ CPU cpus_IBM386SLC[] = { CPU cpus_IBM486SLC[] = { /*IBM 486SLC*/ - {"486SLC/33", CPU_IBM486SLC, 33333333, 1, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4}, - {"486SLC2/50", CPU_IBM486SLC, 50000000, 2, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 6}, - {"486SLC2/66", CPU_IBM486SLC, 66666666, 2, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8}, - {"486SLC3/60", CPU_IBM486SLC, 60000000, 3, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 7}, - {"486SLC3/75", CPU_IBM486SLC, 75000000, 3, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9}, - {"486SLC3/100", CPU_IBM486SLC, 100000000, 3, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 12}, + {"486SLC/33", CPU_IBM486SLC, 33333333, 1, 0, 0x400, 0, 0, 0, 6,6,3,3, 4}, + {"486SLC2/40", CPU_IBM486SLC, 40000000, 2, 0, 0x400, 0, 0, 0, 7,7,6,6, 5}, + {"486SLC2/50", CPU_IBM486SLC, 50000000, 2, 0, 0x400, 0, 0, 0, 8,8,6,6, 6}, + {"486SLC2/66", CPU_IBM486SLC, 66666666, 2, 0, 0x400, 0, 0, 0, 12,12,6,6, 8}, + {"486SLC3/60", CPU_IBM486SLC, 60000000, 3, 0, 0x400, 0, 0, 0, 12,12,9,9, 7}, + {"486SLC3/75", CPU_IBM486SLC, 75000000, 3, 0, 0x400, 0, 0, 0, 12,12,9,9, 9}, + {"486SLC3/100", CPU_IBM486SLC, 100000000, 3, 0, 0x400, 0, 0, 0, 18,18,9,9, 12}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0} }; CPU cpus_IBM486BL[] = { /*IBM Blue Lightning*/ - {"486BL2/50", CPU_IBM486BL, 50000000, 2, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 6}, - {"486BL2/66", CPU_IBM486BL, 66666666, 2, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8}, - {"486BL3/75", CPU_IBM486BL, 75000000, 3, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9}, - {"486BL3/100", CPU_IBM486BL, 100000000, 3, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 12}, + {"486BL2/50", CPU_IBM486BL, 50000000, 2, 0, 0x400, 0, 0, 0, 8,8,6,6, 6}, + {"486BL2/66", CPU_IBM486BL, 66666666, 2, 0, 0x400, 0, 0, 0, 12,12,6,6, 8}, + {"486BL3/75", CPU_IBM486BL, 75000000, 3, 0, 0x400, 0, 0, 0, 12,12,9,9, 9}, + {"486BL3/100", CPU_IBM486BL, 100000000, 3, 0, 0x400, 0, 0, 0, 18,18,9,9, 12}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0} }; CPU cpus_486SLC[] = { @@ -223,91 +224,149 @@ CPU cpus_486DLC[] = { {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0, 0} }; -CPU cpus_i486[] = { +CPU cpus_i486S1[] = { /*i486*/ - {"i486SX/16", CPU_i486SX, 16000000, 1, 16000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 3, 3,3,3, 2}, - {"i486SX/20", CPU_i486SX, 20000000, 1, 20000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3}, - {"i486SX/25", CPU_i486SX, 25000000, 1, 25000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3}, - {"i486SX/33", CPU_i486SX, 33333333, 1, 33333333, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4}, - {"i486SX2/50", CPU_i486SX, 50000000, 2, 25000000, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6}, - {"i486SX2/66 (Q0569)", CPU_i486SX, 66666666, 2, 33333333, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 8}, - {"i486DX/25", CPU_i486DX, 25000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3}, - {"i486DX/33", CPU_i486DX, 33333333, 1, 33333333, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4}, - {"i486DX/50", CPU_i486DX, 50000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,4,4, 6}, - {"i486DX2/40", CPU_i486DX, 40000000, 2, 20000000, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6}, - {"i486DX2/50", CPU_i486DX, 50000000, 2, 25000000, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6}, - {"i486DX2/66", CPU_i486DX, 66666666, 2, 33333333, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8}, - {"iDX4/75", CPU_iDX4, 75000000, 3, 25000000, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9}, /*CPUID available on DX4, >= 75 MHz*/ - {"iDX4/100", CPU_iDX4, 100000000, 3, 33333333, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 12}, /*Is on some real Intel DX2s, limit here is pretty arbitary*/ - {"Pentium OverDrive/63", CPU_PENTIUM, 62500000, 3, 25000000, 0x1531, 0x1531, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,7,7, 15/2}, - {"Pentium OverDrive/83", CPU_PENTIUM, 83333333, 3, 33333333, 0x1532, 0x1532, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,8,8, 10}, + {"i486SX/16", CPU_i486SX, 16000000, 1, 16000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 3, 3,3,3, 2}, + {"i486SX/20", CPU_i486SX, 20000000, 1, 20000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3}, + {"i486SX/25", CPU_i486SX, 25000000, 1, 25000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3}, + {"i486SX/33", CPU_i486SX, 33333333, 1, 33333333, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4}, + {"i486SX2/50", CPU_i486SX, 50000000, 2, 25000000, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6}, + {"i486SX2/66 (Q0569)", CPU_i486SX, 66666666, 2, 33333333, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 8}, + {"i486DX/25", CPU_i486DX, 25000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3}, + {"i486DX/33", CPU_i486DX, 33333333, 1, 33333333, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4}, + {"i486DX/50", CPU_i486DX, 50000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,4,4, 6}, + {"i486DX2/40", CPU_i486DX, 40000000, 2, 20000000, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 7, 7,6,6, 5}, + {"i486DX2/50", CPU_i486DX, 50000000, 2, 25000000, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6}, + {"i486DX2/66", CPU_i486DX, 66666666, 2, 33333333, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8}, + {"iDX4 OverDrive 75", CPU_iDX4, 75000000, 3, 25000000, 0x1480, 0x1480, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9}, /*Only added the DX4 OverDrive as the others would be redundant*/ + {"iDX4 OverDrive 100", CPU_iDX4, 100000000, 3, 33333333, 0x1480, 0x1480, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 12}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0, 0} }; - -CPU cpus_Am486[] = { - /*Am486/5x86*/ +CPU cpus_Am486S1[] = { + /*Am486*/ {"Am486SX/33", CPU_Am486SX, 33333333, 1, 33333333, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4}, - {"Am486SX/40", CPU_Am486SX, 40000000, 1, 20000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, + {"Am486SX/40", CPU_Am486SX, 40000000, 1, 40000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, {"Am486SX2/50", CPU_Am486SX, 50000000, 2, 25000000, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6}, /*CPUID available on SX2, DX2, DX4, 5x86, >= 50 MHz*/ {"Am486SX2/66", CPU_Am486SX, 66666666, 2, 33333333, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8}, /*Isn't on all real AMD SX2s and DX2s, availability here is pretty arbitary (and distinguishes them from the Intel chips)*/ {"Am486DX/33", CPU_Am486DX, 33333333, 1, 33333333, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4}, - {"Am486DX/40", CPU_Am486DX, 40000000, 1, 20000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, + {"Am486DX/40", CPU_Am486DX, 40000000, 1, 40000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, {"Am486DX2/50", CPU_Am486DX, 50000000, 2, 25000000, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6}, {"Am486DX2/66", CPU_Am486DX, 66666666, 2, 33333333, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8}, - {"Am486DX2/80", CPU_Am486DX, 80000000, 2, 20000000, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, + {"Am486DX2/80", CPU_Am486DX, 80000000, 2, 40000000, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, + {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +}; +CPU cpus_Cx486S1[] = { + /*Cyrix 486*/ + {"Cx486S/25", CPU_Cx486S, 25000000, 1, 25000000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 4, 4, 3, 3, 3}, + {"Cx486S/33", CPU_Cx486S, 33333333, 1, 33333333, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4}, + {"Cx486S/40", CPU_Cx486S, 40000000, 1, 40000000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, + {"Cx486DX/33", CPU_Cx486DX, 33333333, 1, 33333333, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4}, + {"Cx486DX/40", CPU_Cx486DX, 40000000, 1, 40000000, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, + {"Cx486DX2/50", CPU_Cx486DX, 50000000, 2, 25000000, 0x430, 0, 0x081b, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6}, + {"Cx486DX2/66", CPU_Cx486DX, 66666666, 2, 33333333, 0x430, 0, 0x0b1b, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8}, + {"Cx486DX2/80", CPU_Cx486DX, 80000000, 2, 40000000, 0x430, 0, 0x311b, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, + {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +}; + +CPU cpus_i486[] = { + /*i486/P24T*/ + {"i486SX/16", CPU_i486SX, 16000000, 1, 16000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 3, 3,3,3, 2}, + {"i486SX/20", CPU_i486SX, 20000000, 1, 20000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3}, + {"i486SX/25", CPU_i486SX, 25000000, 1, 25000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3}, + {"i486SX/33", CPU_i486SX, 33333333, 1, 33333333, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4}, + {"i486SX2/50", CPU_i486SX, 50000000, 2, 25000000, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6}, + {"i486SX2/66 (Q0569)", CPU_i486SX, 66666666, 2, 33333333, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 8}, + {"i486DX/25", CPU_i486DX, 25000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3}, + {"i486DX/33", CPU_i486DX, 33333333, 1, 33333333, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4}, + {"i486DX/50", CPU_i486DX, 50000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,4,4, 6}, + {"i486DX2/40", CPU_i486DX, 40000000, 2, 20000000, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 7, 7,6,6, 5}, + {"i486DX2/50", CPU_i486DX, 50000000, 2, 25000000, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6}, + {"i486DX2/66", CPU_i486DX, 66666666, 2, 33333333, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8}, + {"iDX4/75", CPU_iDX4, 75000000, 3, 25000000, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9}, /*CPUID available on DX4, >= 75 MHz*/ + {"iDX4/100", CPU_iDX4, 100000000, 3, 33333333, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 12}, /*Is on some real Intel DX2s, limit here is pretty arbitary*/ + {"iDX4 OverDrive 75", CPU_iDX4, 75000000, 3, 25000000, 0x1480, 0x1480, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9}, + {"iDX4 OverDrive 100", CPU_iDX4, 100000000, 3, 33333333, 0x1480, 0x1480, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 12}, + {"Pentium OverDrive 63", CPU_PENTIUM, 62500000, 5/2, 25000000, 0x1531, 0x1531, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,7,7, 15/2}, + {"Pentium OverDrive 83", CPU_PENTIUM, 83333333, 5/2, 33333333, 0x1532, 0x1532, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,8,8, 10}, + {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0, 0} +}; +CPU cpus_Am486[] = { + /*Am486/5x86*/ + {"Am486SX/33", CPU_Am486SX, 33333333, 1, 33333333, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4}, + {"Am486SX/40", CPU_Am486SX, 40000000, 1, 40000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, + {"Am486SX2/50", CPU_Am486SX, 50000000, 2, 25000000, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6}, /*CPUID available on SX2, DX2, DX4, 5x86, >= 50 MHz*/ + {"Am486SX2/66", CPU_Am486SX, 66666666, 2, 33333333, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8}, + {"Am486DX/33", CPU_Am486DX, 33333333, 1, 33333333, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4}, + {"Am486DX/40", CPU_Am486DX, 40000000, 1, 40000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, + {"Am486DX2/50", CPU_Am486DX, 50000000, 2, 25000000, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6}, + {"Am486DX2/66", CPU_Am486DX, 66666666, 2, 33333333, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8}, + {"Am486DX2/80", CPU_Am486DX, 80000000, 2, 40000000, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, {"Am486DX4/75", CPU_Am486DX, 75000000, 3, 25000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 12,12, 9, 9, 9}, {"Am486DX4/90", CPU_Am486DX, 90000000, 3, 30000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12}, {"Am486DX4/100", CPU_Am486DX, 100000000, 3, 33333333, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12}, - {"Am486DX4/120", CPU_Am486DX, 120000000, 3, 20000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 21,21, 9, 9, 15}, + {"Am486DX4/120", CPU_Am486DX, 120000000, 3, 40000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 21,21, 9, 9, 15}, {"Am5x86/P75", CPU_Am486DX, 133333333, 4, 33333333, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 16}, - {"Am5x86/P75+", CPU_Am486DX, 160000000, 4, 20000000, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12, 20}, + {"Am5x86/P75+", CPU_Am486DX, 150000000, 3, 25000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12, 20},/*The rare P75+ was indeed a triple-clocked 150 MHz according to research*/ + {"Am5x86/P90", CPU_Am486DX, 160000000, 4, 40000000, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12, 20},/*160 MHz on a 40 MHz bus was a common overclock and "5x86/P90" was used by a number of BIOSes to refer to that configuration*/ {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; CPU cpus_Cx486[] = { - /*Cx486/5x86*/ + /*Cyrix 486*/ {"Cx486S/25", CPU_Cx486S, 25000000, 1, 25000000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 4, 4, 3, 3, 3}, {"Cx486S/33", CPU_Cx486S, 33333333, 1, 33333333, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4}, - {"Cx486S/40", CPU_Cx486S, 40000000, 1, 20000000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, + {"Cx486S/40", CPU_Cx486S, 40000000, 1, 40000000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, {"Cx486DX/33", CPU_Cx486DX, 33333333, 1, 33333333, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4}, - {"Cx486DX/40", CPU_Cx486DX, 40000000, 1, 20000000, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, + {"Cx486DX/40", CPU_Cx486DX, 40000000, 1, 40000000, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, {"Cx486DX2/50", CPU_Cx486DX, 50000000, 2, 25000000, 0x430, 0, 0x081b, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6}, {"Cx486DX2/66", CPU_Cx486DX, 66666666, 2, 33333333, 0x430, 0, 0x0b1b, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8}, - {"Cx486DX2/80", CPU_Cx486DX, 80000000, 2, 20000000, 0x430, 0, 0x311b, CPU_SUPPORTS_DYNAREC, 14,14,16,16, 10}, + {"Cx486DX2/80", CPU_Cx486DX, 80000000, 2, 40000000, 0x430, 0, 0x311b, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, {"Cx486DX4/75", CPU_Cx486DX, 75000000, 3, 25000000, 0x480, 0, 0x361f, CPU_SUPPORTS_DYNAREC, 12,12, 9, 9, 9}, {"Cx486DX4/100", CPU_Cx486DX, 100000000, 3, 33333333, 0x480, 0, 0x361f, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12}, + + /*Cyrix 5x86*/ + {"Cx5x86/80", CPU_Cx5x86, 80000000, 2, 40000000, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, /*If we're including the Pentium 50, might as well include this*/ {"Cx5x86/100", CPU_Cx5x86, 100000000, 3, 33333333, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12}, - {"Cx5x86/120", CPU_Cx5x86, 120000000, 3, 20000000, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 21,21, 9, 9, 15}, + {"Cx5x86/120", CPU_Cx5x86, 120000000, 3, 40000000, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 21,21, 9, 9, 15}, {"Cx5x86/133", CPU_Cx5x86, 133333333, 4, 33333333, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 16}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; #ifdef DEV_BRANCH #ifdef USE_CYRIX_6X86 +CPU cpus_6x863V[] = { + /*Cyrix 6x86*/ + {"Cx6x86/P90", CPU_Cx6x86, 80000000, 2, 40000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8, 8, 6, 6, 10}, + {"Cx6x86/PR120+", CPU_Cx6x86, 100000000, 2, 25000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12}, + {"Cx6x86/PR133+", CPU_Cx6x86, 110000000, 2, 27500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14}, + {"Cx6x86/PR150+", CPU_Cx6x86, 120000000, 2, 30000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, + {"Cx6x86/PR166+", CPU_Cx6x86, 133333333, 2, 33333333, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, + {"Cx6x86/PR200+", CPU_Cx6x86, 150000000, 2, 37500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18}, + {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + }; + CPU cpus_6x86[] = { /*Cyrix 6x86*/ - {"6x86-P90", CPU_Cx6x86, 80000000, 3, 40000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8, 8, 6, 6, 10}, - {"6x86-PR120+", CPU_Cx6x86, 100000000, 3, 25000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12}, - {"6x86-PR133+", CPU_Cx6x86, 110000000, 3, 27500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14}, - {"6x86-PR150+", CPU_Cx6x86, 120000000, 3, 30000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, - {"6x86-PR166+", CPU_Cx6x86, 133333333, 3, 33333333, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, - {"6x86-PR200+", CPU_Cx6x86, 150000000, 3, 37500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18}, + {"Cx6x86/P90", CPU_Cx6x86, 80000000, 2, 40000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8, 8, 6, 6, 10}, + {"Cx6x86/PR120+", CPU_Cx6x86, 100000000, 2, 25000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12}, + {"Cx6x86/PR133+", CPU_Cx6x86, 110000000, 2, 27500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14}, + {"Cx6x86/PR150+", CPU_Cx6x86, 120000000, 2, 30000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, + {"Cx6x86/PR166+", CPU_Cx6x86, 133333333, 2, 33333333, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, + {"Cx6x86/PR200+", CPU_Cx6x86, 150000000, 2, 37500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18}, /*Cyrix 6x86L*/ - {"6x86L-PR133+", CPU_Cx6x86L, 110000000, 3, 27500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14}, - {"6x86L-PR150+", CPU_Cx6x86L, 120000000, 3, 30000000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, - {"6x86L-PR166+", CPU_Cx6x86L, 133333333, 3, 33333333, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, - {"6x86L-PR200+", CPU_Cx6x86L, 150000000, 3, 37500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18}, + {"Cx6x86L/PR133+", CPU_Cx6x86L, 110000000, 2, 27500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14}, + {"Cx6x86L/PR150+", CPU_Cx6x86L, 120000000, 2, 30000000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, + {"Cx6x86L/PR166+", CPU_Cx6x86L, 133333333, 2, 33333333, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, + {"Cx6x86L/PR200+", CPU_Cx6x86L, 150000000, 2, 37500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18}, - /*Cyrix 6x86MX*/ - {"6x86MX-PR166", CPU_Cx6x86MX, 133333333, 3, 33333333, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, - {"6x86MX-PR200", CPU_Cx6x86MX, 166666666, 3, 33333333, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, - {"6x86MX-PR233", CPU_Cx6x86MX, 188888888, 3, 37500000, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 45/2}, - {"6x86MX-PR266", CPU_Cx6x86MX, 207500000, 3, 41666667, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25}, - {"6x86MX-PR300", CPU_Cx6x86MX, 233333333, 3, 33333333, 0x600, 0x600, 0x0454, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21, 7, 7, 28}, - {"6x86MX-PR333", CPU_Cx6x86MX, 250000000, 3, 41666667, 0x600, 0x600, 0x0453, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 20,20, 9, 9, 30}, - {"6x86MX-PR366", CPU_Cx6x86MX, 250000000, 3, 33333333, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 30}, - {"6x86MX-PR400", CPU_Cx6x86MX, 285000000, 3, 41666667, 0x600, 0x600, 0x0453, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 33}, + /*Cyrix 6x86MX/MII*/ + {"Cx6x86MX/PR166", CPU_Cx6x86MX, 133333333, 2, 33333333, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, + {"Cx6x86MX/PR200", CPU_Cx6x86MX, 166666666, 5/2, 33333333, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"Cx6x86MX/PR233", CPU_Cx6x86MX, 187500000, 5/2, 37500000, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 45/2}, + {"Cx6x86MX/PR266", CPU_Cx6x86MX, 208333333, 5/2, 41666666, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25}, + {"MII/PR300", CPU_Cx6x86MX, 233333333, 7/2, 33333333, 0x601, 0x601, 0x0852, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21, 7, 7, 28}, + {"MII/PR333", CPU_Cx6x86MX, 250000000, 3, 41666666, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 20,20, 9, 9, 30}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; #endif @@ -315,24 +374,24 @@ CPU cpus_6x86[] = { CPU cpus_WinChip[] = { /*IDT WinChip*/ - {"WinChip 75", CPU_WINCHIP, 75000000, 2, 25000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 4, 4, 9}, - {"WinChip 90", CPU_WINCHIP, 90000000, 2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9, 9, 4, 4, 21/2}, - {"WinChip 100", CPU_WINCHIP, 100000000, 2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9, 9, 4, 4, 12}, - {"WinChip 120", CPU_WINCHIP, 120000000, 2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 14}, - {"WinChip 133", CPU_WINCHIP, 133333333, 2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 16}, - {"WinChip 150", CPU_WINCHIP, 150000000, 3, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15,15, 7, 7, 35/2}, - {"WinChip 166", CPU_WINCHIP, 166666666, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15,15, 7, 7, 40}, - {"WinChip 180", CPU_WINCHIP, 180000000, 3, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18, 9, 9, 21}, - {"WinChip 200", CPU_WINCHIP, 200000000, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18, 9, 9, 24}, - {"WinChip 225", CPU_WINCHIP, 225000000, 3, 37500000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18, 9, 9, 27}, - {"WinChip 240", CPU_WINCHIP, 240000000, 6, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 28}, + {"WinChip 75", CPU_WINCHIP, 75000000, 3/2, 25000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 4, 4, 9}, + {"WinChip 90", CPU_WINCHIP, 90000000, 3/2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9, 9, 4, 4, 21/2}, + {"WinChip 100", CPU_WINCHIP, 100000000, 3/2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9, 9, 4, 4, 12}, + {"WinChip 120", CPU_WINCHIP, 120000000, 2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12, 12, 6, 6, 14}, + {"WinChip 133", CPU_WINCHIP, 133333333, 2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12, 12, 6, 6, 16}, + {"WinChip 150", CPU_WINCHIP, 150000000, 5/2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15, 15, 7, 7, 35/2}, + {"WinChip 166", CPU_WINCHIP, 166666666, 5/2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15, 15, 7, 7, 40}, + {"WinChip 180", CPU_WINCHIP, 180000000, 3, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 21}, + {"WinChip 200", CPU_WINCHIP, 200000000, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 24}, + {"WinChip 225", CPU_WINCHIP, 225000000, 3, 37500000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 27}, + {"WinChip 240", CPU_WINCHIP, 240000000, 4, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 28}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; CPU cpus_Pentium5V[] = { /*Intel Pentium (5V, socket 4)*/ - {"Pentium 60", CPU_PENTIUM, 60000000, 1, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6,3,3, 7}, - {"Pentium 66", CPU_PENTIUM, 66666666, 1, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6,3,3, 8}, + {"Pentium 60", CPU_PENTIUM, 60000000, 1, 30000000, 0x517, 0x517, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6,3,3, 7}, + {"Pentium 66", CPU_PENTIUM, 66666666, 1, 33333333, 0x517, 0x517, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6,3,3, 8}, {"Pentium OverDrive 120", CPU_PENTIUM, 120000000, 2, 30000000, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14}, {"Pentium OverDrive 133", CPU_PENTIUM, 133333333, 2, 33333333, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0, 0} @@ -341,8 +400,8 @@ CPU cpus_Pentium5V[] = { CPU cpus_Pentium5V50[] = { /*Intel Pentium (5V, socket 4, including 50 MHz FSB)*/ {"Pentium 50 (Q0399)", CPU_PENTIUM, 50000000, 1, 25000000, 0x513, 0x513, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 4, 4,3,3, 6}, - {"Pentium 60", CPU_PENTIUM, 60000000, 1, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6,3,3, 7}, - {"Pentium 66", CPU_PENTIUM, 66666666, 1, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6,3,3, 8}, + {"Pentium 60", CPU_PENTIUM, 60000000, 1, 30000000, 0x517, 0x517, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6,3,3, 7}, + {"Pentium 66", CPU_PENTIUM, 66666666, 1, 33333333, 0x517, 0x517, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6,3,3, 8}, {"Pentium OverDrive 100", CPU_PENTIUM, 100000000, 2, 25000000, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8, 8,6,6, 12}, {"Pentium OverDrive 120", CPU_PENTIUM, 120000000, 2, 30000000, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14}, {"Pentium OverDrive 133", CPU_PENTIUM, 133333333, 2, 33333333, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16}, @@ -351,54 +410,85 @@ CPU cpus_Pentium5V50[] = { CPU cpus_PentiumS5[] = { /*Intel Pentium (Socket 5)*/ - {"Pentium 75", CPU_PENTIUM, 75000000, 2, 25000000, 0x522, 0x522, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9}, - {"Pentium OverDrive MMX 75", CPU_PENTIUMMMX, 75000000, 2, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9}, - {"Pentium 90", CPU_PENTIUM, 90000000, 2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 21/2}, - {"Pentium 100/50", CPU_PENTIUM, 100000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 12}, - {"Pentium 100/66", CPU_PENTIUM, 100000000, 2, 33333333, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12}, - {"Pentium 120", CPU_PENTIUM, 120000000, 2, 30000000, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14}, - {"Pentium OverDrive 125", CPU_PENTIUM, 125000000, 3, 25000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, 16}, - {"Pentium OverDrive 150", CPU_PENTIUM, 150000000, 3, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2}, - {"Pentium OverDrive 166", CPU_PENTIUM, 166666666, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 40}, - {"Pentium OverDrive MMX 125", CPU_PENTIUMMMX, 125000000, 3, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, 15}, - {"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX, 150000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2}, - {"Pentium OverDrive MMX 166", CPU_PENTIUMMMX, 166000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20}, - {"Pentium OverDrive MMX 180", CPU_PENTIUMMMX, 180000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 21}, - {"Pentium OverDrive MMX 200", CPU_PENTIUMMMX, 200000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24}, + {"Pentium 75", CPU_PENTIUM, 75000000, 3/2, 25000000, 0x522, 0x522, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9}, + {"Pentium OverDrive MMX 75", CPU_PENTIUMMMX, 75000000, 3/2, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9}, + {"Pentium 90", CPU_PENTIUM, 90000000, 3/2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 21/2}, + {"Pentium 100/50", CPU_PENTIUM, 100000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 12}, + {"Pentium 100/66", CPU_PENTIUM, 100000000, 3/2, 33333333, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12}, + {"Pentium 120", CPU_PENTIUM, 120000000, 2, 30000000, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14}, + + /*Intel Pentium OverDrive*/ + {"Pentium OverDrive 125", CPU_PENTIUM, 125000000, 3, 25000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, 16}, + {"Pentium OverDrive 150", CPU_PENTIUM, 150000000, 5/2, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2}, + {"Pentium OverDrive 166", CPU_PENTIUM, 166666666, 5/2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 40}, + {"Pentium OverDrive MMX 125", CPU_PENTIUMMMX, 125000000, 5/2, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, 15}, + {"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX, 150000000, 5/2, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2}, + {"Pentium OverDrive MMX 166", CPU_PENTIUMMMX, 166000000, 5/2, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20}, + {"Pentium OverDrive MMX 180", CPU_PENTIUMMMX, 180000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 21}, + {"Pentium OverDrive MMX 200", CPU_PENTIUMMMX, 200000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0, 0} }; +CPU cpus_Pentium3V[] = { + /*Intel Pentium*/ + {"Pentium 75", CPU_PENTIUM, 75000000, 3/2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9}, + {"Pentium OverDrive MMX 75", CPU_PENTIUMMMX, 75000000, 3/2, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9}, + {"Pentium 90", CPU_PENTIUM, 90000000, 3/2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2}, + {"Pentium 100/50", CPU_PENTIUM, 100000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12}, + {"Pentium 100/66", CPU_PENTIUM, 100000000, 3/2, 33333333, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, + {"Pentium 120", CPU_PENTIUM, 120000000, 2, 30000000, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, + {"Pentium 133", CPU_PENTIUM, 133333333, 2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, + {"Pentium 150", CPU_PENTIUM, 150000000, 5/2, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, + {"Pentium 166", CPU_PENTIUM, 166666666, 5/2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"Pentium 200", CPU_PENTIUM, 200000000, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, + + /*Intel Pentium OverDrive*/ + {"Pentium OverDrive 125", CPU_PENTIUM, 125000000, 5/2, 25000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 7, 7, 15}, + {"Pentium OverDrive 150", CPU_PENTIUM, 150000000, 5/2, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, + {"Pentium OverDrive 166", CPU_PENTIUM, 166666666, 5/2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"Pentium OverDrive MMX 125", CPU_PENTIUMMMX, 125000000, 5/2, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 7, 7, 15}, + {"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX, 150000000, 5/2, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, + {"Pentium OverDrive MMX 166", CPU_PENTIUMMMX, 166000000, 5/2, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"Pentium OverDrive MMX 180", CPU_PENTIUMMMX, 180000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 21}, + {"Pentium OverDrive MMX 200", CPU_PENTIUMMMX, 200000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, + {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +}; + CPU cpus_Pentium[] = { /*Intel Pentium*/ - {"Pentium 75", CPU_PENTIUM, 75000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9}, - {"Pentium OverDrive MMX 75", CPU_PENTIUMMMX, 75000000, 2, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9}, - {"Pentium 90", CPU_PENTIUM, 90000000, 2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2}, - {"Pentium 100/50", CPU_PENTIUM, 100000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12}, - {"Pentium 100/66", CPU_PENTIUM, 100000000, 2, 33333333, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, - {"Pentium 120", CPU_PENTIUM, 120000000, 2, 30000000, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, - {"Pentium 133", CPU_PENTIUM, 133333333, 2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, - {"Pentium 150", CPU_PENTIUM, 150000000, 3, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, - {"Pentium 166", CPU_PENTIUM, 166666666, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, - {"Pentium 200", CPU_PENTIUM, 200000000, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, - {"Pentium MMX 166", CPU_PENTIUMMMX, 166666666, 3, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, - {"Pentium MMX 200", CPU_PENTIUMMMX, 200000000, 3, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, - {"Pentium MMX 233", CPU_PENTIUMMMX, 233333333, 4, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, - {"Mobile Pentium MMX 120", CPU_PENTIUMMMX, 120000000, 2, 30000000, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, - {"Mobile Pentium MMX 133", CPU_PENTIUMMMX, 133333333, 2, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, - {"Mobile Pentium MMX 150", CPU_PENTIUMMMX, 150000000, 3, 30000000, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, - {"Mobile Pentium MMX 166", CPU_PENTIUMMMX, 166666666, 3, 33333333, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, - {"Mobile Pentium MMX 200", CPU_PENTIUMMMX, 200000000, 3, 33333333, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, - {"Mobile Pentium MMX 233", CPU_PENTIUMMMX, 233333333, 4, 33333333, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, - {"Mobile Pentium MMX 266", CPU_PENTIUMMMX, 266666666, 4, 33333333, 0x582, 0x582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, - {"Mobile Pentium MMX 300", CPU_PENTIUMMMX, 300000000, 5, 33333333, 0x582, 0x582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36}, - {"Pentium OverDrive 125", CPU_PENTIUM, 125000000, 3, 25000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 7, 7, 15}, - {"Pentium OverDrive 150", CPU_PENTIUM, 150000000, 3, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, - {"Pentium OverDrive 166", CPU_PENTIUM, 166666666, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, - {"Pentium OverDrive MMX 125", CPU_PENTIUMMMX, 125000000, 3, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 7, 7, 15}, - {"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX, 150000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, - {"Pentium OverDrive MMX 166", CPU_PENTIUMMMX, 166000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, - {"Pentium OverDrive MMX 180", CPU_PENTIUMMMX, 180000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 21}, - {"Pentium OverDrive MMX 200", CPU_PENTIUMMMX, 200000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, + {"Pentium 75", CPU_PENTIUM, 75000000, 3/2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9}, + {"Pentium OverDrive MMX 75", CPU_PENTIUMMMX, 75000000, 3/2, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9}, + {"Pentium 90", CPU_PENTIUM, 90000000, 3/2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2}, + {"Pentium 100/50", CPU_PENTIUM, 100000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12}, + {"Pentium 100/66", CPU_PENTIUM, 100000000, 3/2, 33333333, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, + {"Pentium 120", CPU_PENTIUM, 120000000, 2, 30000000, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, + {"Pentium 133", CPU_PENTIUM, 133333333, 2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, + {"Pentium 150", CPU_PENTIUM, 150000000, 5/2, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, + {"Pentium 166", CPU_PENTIUM, 166666666, 5/2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"Pentium 200", CPU_PENTIUM, 200000000, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, + {"Pentium MMX 166", CPU_PENTIUMMMX, 166666666, 5/2, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"Pentium MMX 200", CPU_PENTIUMMMX, 200000000, 3, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, + {"Pentium MMX 233", CPU_PENTIUMMMX, 233333333, 7/2, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, + + /*Mobile Pentium*/ + {"Mobile Pentium MMX 120", CPU_PENTIUMMMX, 120000000, 2, 30000000, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, + {"Mobile Pentium MMX 133", CPU_PENTIUMMMX, 133333333, 2, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, + {"Mobile Pentium MMX 150", CPU_PENTIUMMMX, 150000000, 5/2, 30000000, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, + {"Mobile Pentium MMX 166", CPU_PENTIUMMMX, 166666666, 5/2, 33333333, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"Mobile Pentium MMX 200", CPU_PENTIUMMMX, 200000000, 3, 33333333, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, + {"Mobile Pentium MMX 233", CPU_PENTIUMMMX, 233333333, 7/2, 33333333, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, + {"Mobile Pentium MMX 266", CPU_PENTIUMMMX, 266666666, 4, 33333333, 0x582, 0x582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, + {"Mobile Pentium MMX 300", CPU_PENTIUMMMX, 300000000, 9/2, 33333333, 0x582, 0x582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36}, + + /*Intel Pentium OverDrive*/ + {"Pentium OverDrive 125", CPU_PENTIUM, 125000000, 5/2, 25000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 7, 7, 15}, + {"Pentium OverDrive 150", CPU_PENTIUM, 150000000, 5/2, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, + {"Pentium OverDrive 166", CPU_PENTIUM, 166666666, 5/2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"Pentium OverDrive MMX 125", CPU_PENTIUMMMX, 125000000, 5/2, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 7, 7, 15}, + {"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX, 150000000, 5/2, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, + {"Pentium OverDrive MMX 166", CPU_PENTIUMMMX, 166000000, 5/2, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"Pentium OverDrive MMX 180", CPU_PENTIUMMMX, 180000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 21}, + {"Pentium OverDrive MMX 200", CPU_PENTIUMMMX, 200000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; @@ -406,69 +496,73 @@ CPU cpus_Pentium[] = { #ifdef USE_AMD_K CPU cpus_K5[] = { /*AMD K5 (Socket 5)*/ - {"K5 (5k86) 75 (P75)", CPU_K5, 75000000, 2, 25000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9}, - {"K5 (SSA/5) 75 (PR75)", CPU_K5, 75000000, 2, 25000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9}, - {"K5 (5k86) 90 (P90)", CPU_K5, 90000000, 2, 30000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 21/2}, - {"K5 (SSA/5) 90 (PR90)", CPU_K5, 90000000, 2, 30000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 21/2}, - {"K5 (5k86) 100 (P100)", CPU_K5, 100000000, 2, 33333333, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12}, - {"K5 (SSA/5) 100 (PR100)", CPU_K5, 100000000, 2, 33333333, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12}, - {"K5 (5k86) 90 (PR120)", CPU_5K86, 120000000, 2, 30000000, 0x511, 0x511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14}, - {"K5 (5k86) 100 (PR133)", CPU_5K86, 133333333, 2, 33333333, 0x514, 0x514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16}, - {"K5 (5k86) 105 (PR150)", CPU_5K86, 150000000, 3, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2}, - {"K5 (5k86) 116.5 (PR166)", CPU_5K86, 166666666, 3, 33333333, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20}, - {"K5 (5k86) 133 (PR200)", CPU_5K86, 200000000, 3, 33333333, 0x534, 0x534, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24}, + {"K5 (5k86) 75 (P75)", CPU_K5, 75000000, 3/2, 25000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9}, + {"K5 (SSA/5) 75 (PR75)", CPU_K5, 75000000, 3/2, 25000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9}, + {"K5 (5k86) 90 (P90)", CPU_K5, 90000000, 3/2, 30000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 21/2}, + {"K5 (SSA/5) 90 (PR90)", CPU_K5, 90000000, 3/2, 30000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 21/2}, + {"K5 (5k86) 100 (P100)", CPU_K5, 100000000, 3/2, 33333333, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12}, + {"K5 (SSA/5) 100 (PR100)", CPU_K5, 100000000, 3/2, 33333333, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12}, + {"K5 (5k86) 90 (PR120)", CPU_5K86, 120000000, 2, 30000000, 0x511, 0x511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14}, + {"K5 (5k86) 100 (PR133)", CPU_5K86, 133333333, 2, 33333333, 0x514, 0x514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16}, + {"K5 (5k86) 105 (PR150)", CPU_5K86, 150000000, 5/2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2}, + {"K5 (5k86) 116.5 (PR166)", CPU_5K86, 166666666, 5/2, 33333333, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20}, + {"K5 (5k86) 133 (PR200)", CPU_5K86, 200000000, 3, 33333333, 0x534, 0x534, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0, 0} }; CPU cpus_K56[] = { - /*AMD K5 and K6 (Socket 7)*/ - {"K5 (5k86) 75 (P75)", CPU_K5, 75000000, 2, 25000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9}, - {"K5 (SSA/5) 75 (PR75)", CPU_K5, 75000000, 2, 25000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9}, - {"K5 (5k86) 90 (P90)", CPU_K5, 90000000, 2, 30000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2}, - {"K5 (SSA/5) 90 (PR90)", CPU_K5, 90000000, 2, 30000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2}, - {"K5 (5k86) 100 (P100)", CPU_K5, 100000000, 2, 33333333, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, - {"K5 (SSA/5) 100 (PR100)", CPU_K5, 100000000, 2, 33333333, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, - {"K5 (5k86) 90 (PR120)", CPU_5K86, 120000000, 2, 30000000, 0x511, 0x511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, - {"K5 (5k86) 100 (PR133)", CPU_5K86, 133333333, 2, 33333333, 0x514, 0x514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, - {"K5 (5k86) 105 (PR150)", CPU_5K86, 150000000, 3, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, - {"K5 (5k86) 116.5 (PR166)", CPU_5K86, 166666666, 3, 33333333, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, - {"K5 (5k86) 133 (PR200)", CPU_5K86, 200000000, 3, 33333333, 0x534, 0x534, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, - {"K6 (Model 6) 166", CPU_K6, 166666666, 3, 33333333, 0x562, 0x562, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, - {"K6 (Model 6) 200", CPU_K6, 200000000, 3, 33333333, 0x562, 0x562, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, - {"K6 (Model 6) 233", CPU_K6, 233333333, 4, 33333333, 0x562, 0x562, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, - {"K6 (Model 7) 200", CPU_K6, 200000000, 3, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, - {"K6 (Model 7) 233", CPU_K6, 233333333, 4, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, - {"K6 (Model 7) 266", CPU_K6, 266666666, 4, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, - {"K6 (Model 7) 300", CPU_K6, 300000000, 5, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36}, - {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} -}; + /*AMD K5 (Socket 7)*/ + {"K5 (5k86) 75 (P75)", CPU_K5, 75000000, 3/2, 25000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9}, + {"K5 (SSA/5) 75 (PR75)", CPU_K5, 75000000, 3/2, 25000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9}, + {"K5 (5k86) 90 (P90)", CPU_K5, 90000000, 3/2, 30000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2}, + {"K5 (SSA/5) 90 (PR90)", CPU_K5, 90000000, 3/2, 30000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2}, + {"K5 (5k86) 100 (P100)", CPU_K5, 100000000, 3/2, 33333333, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, + {"K5 (SSA/5) 100 (PR100)", CPU_K5, 100000000, 3/2, 33333333, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, + {"K5 (5k86) 90 (PR120)", CPU_5K86, 120000000, 2, 30000000, 0x511, 0x511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, + {"K5 (5k86) 100 (PR133)", CPU_5K86, 133333333, 2, 33333333, 0x514, 0x514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, + {"K5 (5k86) 105 (PR150)", CPU_5K86, 150000000, 5/2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, + {"K5 (5k86) 116.5 (PR166)", CPU_5K86, 166666666, 5/2, 33333333, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"K5 (5k86) 133 (PR200)", CPU_5K86, 200000000, 3, 33333333, 0x534, 0x534, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, + + /*AMD K6 (Socket 7*/ + {"K6 (Model 6) 166", CPU_K6, 166666666, 5/2, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"K6 (Model 6) 200", CPU_K6, 200000000, 3, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, + {"K6 (Model 6) 233", CPU_K6, 233333333, 7/2, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21, 10, 10, 28}, + {"K6 (Model 7) 200", CPU_K6, 200000000, 3, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, + {"K6 (Model 7) 233", CPU_K6, 233333333, 7/2, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21, 10, 10, 28}, + {"K6 (Model 7) 266", CPU_K6, 266666666, 4, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24, 12, 12, 32}, + {"K6 (Model 7) 300", CPU_K6, 300000000, 9/2, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 13, 13, 36}, + {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0, 0} +}; #endif #endif #ifdef DEV_BRANCH #ifdef USE_I686 CPU cpus_PentiumPro[] = { - /*Intel Pentium Pro and II Overdrive*/ - {"Pentium Pro 50", CPU_PENTIUMPRO, 50000000, 1, 25000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 4, 4, 3, 3, 6}, - {"Pentium Pro 60" , CPU_PENTIUMPRO, 60000000, 1, 30000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 7}, - {"Pentium Pro 66" , CPU_PENTIUMPRO, 66666666, 1, 33333333, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 8}, - {"Pentium Pro 75", CPU_PENTIUMPRO, 75000000, 2, 25000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9}, - {"Pentium Pro 150", CPU_PENTIUMPRO, 150000000, 3, 30000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, - {"Pentium Pro 166", CPU_PENTIUMPRO, 166666666, 3, 33333333, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, - {"Pentium Pro 180", CPU_PENTIUMPRO, 180000000, 3, 30000000, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 21}, - {"Pentium Pro 200", CPU_PENTIUMPRO, 200000000, 3, 33333333, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, - {"Pentium II Overdrive 50", CPU_PENTIUM2D, 50000000, 1, 25000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 4, 4, 3, 3, 6}, - {"Pentium II Overdrive 60", CPU_PENTIUM2D, 60000000, 1, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 7}, - {"Pentium II Overdrive 66", CPU_PENTIUM2D, 66666666, 1, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 8}, - {"Pentium II Overdrive 75", CPU_PENTIUM2D, 75000000, 2, 25000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9}, - {"Pentium II Overdrive 210", CPU_PENTIUM2D, 210000000, 4, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25}, - {"Pentium II Overdrive 233", CPU_PENTIUM2D, 233333333, 4, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, - {"Pentium II Overdrive 240", CPU_PENTIUM2D, 240000000, 4, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 29}, - {"Pentium II Overdrive 266", CPU_PENTIUM2D, 266666666, 4, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, - {"Pentium II Overdrive 270", CPU_PENTIUM2D, 270000000, 5, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 25,25,12,12, 33}, - {"Pentium II Overdrive 300/66", CPU_PENTIUM2D, 300000000, 5, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 25,25,12,12, 36}, - {"Pentium II Overdrive 300/60", CPU_PENTIUM2D, 300000000, 5, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36}, - {"Pentium II Overdrive 333", CPU_PENTIUM2D, 333333333, 5, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 40}, + /*Intel Pentium Pro*/ + {"Pentium Pro 50", CPU_PENTIUMPRO, 50000000, 1, 25000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 4, 4, 3, 3, 6}, + {"Pentium Pro 60" , CPU_PENTIUMPRO, 60000000, 1, 30000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 7}, + {"Pentium Pro 66" , CPU_PENTIUMPRO, 66666666, 1, 33333333, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 8}, + {"Pentium Pro 75", CPU_PENTIUMPRO, 75000000, 3/2, 25000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9}, + {"Pentium Pro 150", CPU_PENTIUMPRO, 150000000, 5/2, 30000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, + {"Pentium Pro 166", CPU_PENTIUMPRO, 166666666, 5/2, 33333333, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"Pentium Pro 180", CPU_PENTIUMPRO, 180000000, 3, 30000000, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 21}, + {"Pentium Pro 200", CPU_PENTIUMPRO, 200000000, 3, 33333333, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, + + /*Intel Pentium II OverDrive*/ + {"Pentium II Overdrive 50", CPU_PENTIUM2D, 50000000, 1, 25000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 4, 4, 3, 3, 6}, + {"Pentium II Overdrive 60", CPU_PENTIUM2D, 60000000, 1, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 7}, + {"Pentium II Overdrive 66", CPU_PENTIUM2D, 66666666, 1, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 8}, + {"Pentium II Overdrive 75", CPU_PENTIUM2D, 75000000, 3/2, 25000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9}, + {"Pentium II Overdrive 210", CPU_PENTIUM2D, 210000000, 7/2, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25}, + {"Pentium II Overdrive 233", CPU_PENTIUM2D, 233333333, 7/2, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, + {"Pentium II Overdrive 240", CPU_PENTIUM2D, 240000000, 4, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 29}, + {"Pentium II Overdrive 266", CPU_PENTIUM2D, 266666666, 4, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, + {"Pentium II Overdrive 270", CPU_PENTIUM2D, 270000000, 9/2, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 25,25,12,12, 33}, + {"Pentium II Overdrive 300/66", CPU_PENTIUM2D, 300000000, 9/2, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 25,25,12,12, 36}, + {"Pentium II Overdrive 300/60", CPU_PENTIUM2D, 300000000, 5, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36}, + {"Pentium II Overdrive 333", CPU_PENTIUM2D, 333333333, 5, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 40}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; #endif diff --git a/src/cpu_new/cpu.h b/src/cpu_new/cpu.h index 578c25f18..4de1f428b 100644 --- a/src/cpu_new/cpu.h +++ b/src/cpu_new/cpu.h @@ -33,7 +33,7 @@ #define CPU_RAPIDCAD 8 #define CPU_486SLC 9 #define CPU_486DLC 10 -#define CPU_i486SX 11 /* 486 class CPUs */ +#define CPU_i486SX 11 /* 486 class CPUs */ #define CPU_Am486SX 12 #define CPU_Cx486S 13 #define CPU_i486DX 14 @@ -96,6 +96,9 @@ extern CPU cpus_486DLC[]; extern CPU cpus_IBM386SLC[]; extern CPU cpus_IBM486SLC[]; extern CPU cpus_IBM486BL[]; +extern CPU cpus_i486S1[]; +extern CPU cpus_Am486S1[]; +extern CPU cpus_Cx486S1[]; extern CPU cpus_i486[]; extern CPU cpus_Am486[]; extern CPU cpus_Cx486[]; @@ -104,11 +107,14 @@ extern CPU cpus_WinChip_SS7[]; extern CPU cpus_Pentium5V[]; extern CPU cpus_Pentium5V50[]; extern CPU cpus_PentiumS5[]; +extern CPU cpus_Pentium3V[]; extern CPU cpus_K5[]; extern CPU cpus_K56[]; extern CPU cpus_K56_SS7[]; extern CPU cpus_Pentium[]; +extern CPU cpus_6x863V[]; extern CPU cpus_6x86[]; +extern CPU cpus_6x86SS7[]; #ifdef DEV_BRANCH #ifdef USE_I686 extern CPU cpus_PentiumPro[]; diff --git a/src/cpu_new/cpu_table.c b/src/cpu_new/cpu_table.c index 8062fb68b..93f65c107 100644 --- a/src/cpu_new/cpu_table.c +++ b/src/cpu_new/cpu_table.c @@ -97,7 +97,7 @@ CPU cpus_286[] = { {"286/6", CPU_286, 6000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1}, {"286/8", CPU_286, 8000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1}, {"286/10", CPU_286, 10000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1}, - {"286/12", CPU_286, 12000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2}, + {"286/12", CPU_286, 12500000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2}, {"286/16", CPU_286, 16000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2}, {"286/20", CPU_286, 20000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3}, {"286/25", CPU_286, 25000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3}, @@ -126,7 +126,7 @@ CPU cpus_ps1_m2011[] = { CPU cpus_ps2_m30_286[] = { /*286*/ {"286/10", CPU_286, 10000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1}, - {"286/12", CPU_286, 12000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2}, + {"286/12", CPU_286, 12500000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2}, {"286/16", CPU_286, 16000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2}, {"286/20", CPU_286, 20000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3}, {"286/25", CPU_286, 25000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3}, @@ -144,7 +144,7 @@ CPU cpus_i386SX[] = { }; CPU cpus_i386DX[] = { - /*i386DX*/ + /*i386DX/RapidCAD*/ {"i386DX/16", CPU_386DX, 16000000, 1, 0, 0x0308, 0, 0, 0, 3,3,3,3, 2}, {"i386DX/20", CPU_386DX, 20000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3, 3}, {"i386DX/25", CPU_386DX, 25000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3, 3}, @@ -158,7 +158,7 @@ CPU cpus_i386DX[] = { }; CPU cpus_Am386SX[] = { - /*Am386*/ + /*Am386SX*/ {"Am386SX/16", CPU_386SX, 16000000, 1, 0, 0x2308, 0, 0, 0, 3,3,3,3, 2}, {"Am386SX/20", CPU_386SX, 20000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3}, {"Am386SX/25", CPU_386SX, 25000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3}, @@ -168,7 +168,7 @@ CPU cpus_Am386SX[] = { }; CPU cpus_Am386DX[] = { - /*Am386*/ + /*Am386DX*/ {"Am386DX/25", CPU_386DX, 25000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3, 3}, {"Am386DX/33", CPU_386DX, 33333333, 1, 0, 0x0308, 0, 0, 0, 6,6,3,3, 4}, {"Am386DX/40", CPU_386DX, 40000000, 1, 0, 0x0308, 0, 0, 0, 7,7,3,3, 5}, @@ -195,22 +195,23 @@ CPU cpus_IBM386SLC[] = { }; CPU cpus_IBM486SLC[] = { - /*IBM 486SLC*/ - {"486SLC/33", CPU_IBM486SLC, 33333333, 1, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4}, - {"486SLC2/50", CPU_IBM486SLC, 50000000, 2, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 6}, - {"486SLC2/66", CPU_IBM486SLC, 66666666, 2, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8}, - {"486SLC3/60", CPU_IBM486SLC, 60000000, 3, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 7}, - {"486SLC3/75", CPU_IBM486SLC, 75000000, 3, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9}, - {"486SLC3/100", CPU_IBM486SLC, 100000000, 3, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 12}, + /*IBM 486SLC*/ + {"486SLC/33", CPU_IBM486SLC, 33333333, 1, 0, 0x400, 0, 0, 0, 6,6,3,3, 4}, + {"486SLC2/40", CPU_IBM486SLC, 40000000, 2, 0, 0x400, 0, 0, 0, 7,7,6,6, 5}, + {"486SLC2/50", CPU_IBM486SLC, 50000000, 2, 0, 0x400, 0, 0, 0, 8,8,6,6, 6}, + {"486SLC2/66", CPU_IBM486SLC, 66666666, 2, 0, 0x400, 0, 0, 0, 12,12,6,6, 8}, + {"486SLC3/60", CPU_IBM486SLC, 60000000, 3, 0, 0x400, 0, 0, 0, 12,12,9,9, 7}, + {"486SLC3/75", CPU_IBM486SLC, 75000000, 3, 0, 0x400, 0, 0, 0, 12,12,9,9, 9}, + {"486SLC3/100", CPU_IBM486SLC, 100000000, 3, 0, 0x400, 0, 0, 0, 18,18,9,9, 12}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0} }; CPU cpus_IBM486BL[] = { /*IBM Blue Lightning*/ - {"486BL2/50", CPU_IBM486BL, 50000000, 2, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 6}, - {"486BL2/66", CPU_IBM486BL, 66666666, 2, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8}, - {"486BL3/75", CPU_IBM486BL, 75000000, 3, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9}, - {"486BL3/100", CPU_IBM486BL, 100000000, 3, 0, 0x400, 0, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 12}, + {"486BL2/50", CPU_IBM486BL, 50000000, 2, 0, 0x400, 0, 0, 0, 8,8,6,6, 6}, + {"486BL2/66", CPU_IBM486BL, 66666666, 2, 0, 0x400, 0, 0, 0, 12,12,6,6, 8}, + {"486BL3/75", CPU_IBM486BL, 75000000, 3, 0, 0x400, 0, 0, 0, 12,12,9,9, 9}, + {"486BL3/100", CPU_IBM486BL, 100000000, 3, 0, 0x400, 0, 0, 0, 18,18,9,9, 12}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0} }; @@ -225,140 +226,229 @@ CPU cpus_486DLC[] = { {"Cx486DRx2/66", CPU_486DLC, 66666666, 2, 0, 0x407, 0, 0x0007, 0, 12,12,6,6, 8}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0, 0} }; +CPU cpus_i486S1[] = { + /*i486*/ + {"i486SX/16", CPU_i486SX, 16000000, 1, 16000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 3, 3,3,3, 2}, + {"i486SX/20", CPU_i486SX, 20000000, 1, 20000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3}, + {"i486SX/25", CPU_i486SX, 25000000, 1, 25000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3}, + {"i486SX/33", CPU_i486SX, 33333333, 1, 33333333, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4}, + {"i486SX2/50", CPU_i486SX, 50000000, 2, 25000000, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6}, + {"i486SX2/66 (Q0569)", CPU_i486SX, 66666666, 2, 33333333, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 8}, + {"i486DX/25", CPU_i486DX, 25000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3}, + {"i486DX/33", CPU_i486DX, 33333333, 1, 33333333, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4}, + {"i486DX/50", CPU_i486DX, 50000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,4,4, 6}, + {"i486DX2/40", CPU_i486DX, 40000000, 2, 20000000, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 7, 7,6,6, 5}, + {"i486DX2/50", CPU_i486DX, 50000000, 2, 25000000, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6}, + {"i486DX2/66", CPU_i486DX, 66666666, 2, 33333333, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8}, + {"iDX4 OverDrive 75", CPU_iDX4, 75000000, 3, 25000000, 0x1480, 0x1480, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9}, /*Only added the DX4 OverDrive as the others would be redundant*/ + {"iDX4 OverDrive 100", CPU_iDX4, 100000000, 3, 33333333, 0x1480, 0x1480, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 12}, + {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0, 0} +}; +CPU cpus_Am486S1[] = { + /*Am486*/ + {"Am486SX/33", CPU_Am486SX, 33333333, 1, 33333333, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4}, + {"Am486SX/40", CPU_Am486SX, 40000000, 1, 40000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, + {"Am486SX2/50", CPU_Am486SX, 50000000, 2, 25000000, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6}, /*CPUID available on SX2, DX2, DX4, 5x86, >= 50 MHz*/ + {"Am486SX2/66", CPU_Am486SX, 66666666, 2, 33333333, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8}, + {"Am486DX/33", CPU_Am486DX, 33333333, 1, 33333333, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4}, + {"Am486DX/40", CPU_Am486DX, 40000000, 1, 40000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, + {"Am486DX2/50", CPU_Am486DX, 50000000, 2, 25000000, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6}, + {"Am486DX2/66", CPU_Am486DX, 66666666, 2, 33333333, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8}, + {"Am486DX2/80", CPU_Am486DX, 80000000, 2, 40000000, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, + {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +}; +CPU cpus_Cx486S1[] = { + /*Cyrix 486*/ + {"Cx486S/25", CPU_Cx486S, 25000000, 1, 25000000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 4, 4, 3, 3, 3}, + {"Cx486S/33", CPU_Cx486S, 33333333, 1, 33333333, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4}, + {"Cx486S/40", CPU_Cx486S, 40000000, 1, 40000000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, + {"Cx486DX/33", CPU_Cx486DX, 33333333, 1, 33333333, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4}, + {"Cx486DX/40", CPU_Cx486DX, 40000000, 1, 40000000, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, + {"Cx486DX2/50", CPU_Cx486DX, 50000000, 2, 25000000, 0x430, 0, 0x081b, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6}, + {"Cx486DX2/66", CPU_Cx486DX, 66666666, 2, 33333333, 0x430, 0, 0x0b1b, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8}, + {"Cx486DX2/80", CPU_Cx486DX, 80000000, 2, 40000000, 0x430, 0, 0x311b, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, + {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +}; CPU cpus_i486[] = { - /*i486*/ - {"i486SX/16", CPU_i486SX, 16000000, 1, 16000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 3, 3,3,3, 2}, - {"i486SX/20", CPU_i486SX, 20000000, 1, 20000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3}, - {"i486SX/25", CPU_i486SX, 25000000, 1, 25000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3}, - {"i486SX/33", CPU_i486SX, 33333333, 1, 33333333, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4}, - {"i486SX2/50", CPU_i486SX, 50000000, 2, 25000000, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6}, - {"i486SX2/66 (Q0569)", CPU_i486SX, 66666666, 2, 33333333, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 8}, - {"i486DX/25", CPU_i486DX, 25000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3}, - {"i486DX/33", CPU_i486DX, 33333333, 1, 33333333, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4}, - {"i486DX/50", CPU_i486DX, 50000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,4,4, 6}, - {"i486DX2/40", CPU_i486DX, 40000000, 2, 20000000, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6}, - {"i486DX2/50", CPU_i486DX, 50000000, 2, 25000000, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6}, - {"i486DX2/66", CPU_i486DX, 66666666, 2, 33333333, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8}, - {"iDX4/75", CPU_iDX4, 75000000, 3, 25000000, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9}, /*CPUID available on DX4, >= 75 MHz*/ - {"iDX4/100", CPU_iDX4, 100000000, 3, 33333333, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 12}, /*Is on some real Intel DX2s, limit here is pretty arbitary*/ - {"Pentium OverDrive/63", CPU_PENTIUM, 62500000, 3, 25000000, 0x1531, 0x1531, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,7,7, 15/2}, - {"Pentium OverDrive/83", CPU_PENTIUM, 83333333, 3, 33333333, 0x1532, 0x1532, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,8,8, 10}, + /*i486/P24T*/ + {"i486SX/16", CPU_i486SX, 16000000, 1, 16000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 3, 3,3,3, 2}, + {"i486SX/20", CPU_i486SX, 20000000, 1, 20000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3}, + {"i486SX/25", CPU_i486SX, 25000000, 1, 25000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3}, + {"i486SX/33", CPU_i486SX, 33333333, 1, 33333333, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4}, + {"i486SX2/50", CPU_i486SX, 50000000, 2, 25000000, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6}, + {"i486SX2/66 (Q0569)", CPU_i486SX, 66666666, 2, 33333333, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 8}, + {"i486DX/25", CPU_i486DX, 25000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3}, + {"i486DX/33", CPU_i486DX, 33333333, 1, 33333333, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4}, + {"i486DX/50", CPU_i486DX, 50000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,4,4, 6}, + {"i486DX2/40", CPU_i486DX, 40000000, 2, 20000000, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 7, 7,6,6, 5}, /*CPUID available on DX2, DX4, P24T, >= 40 MHz*/ + {"i486DX2/50", CPU_i486DX, 50000000, 2, 25000000, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6}, + {"i486DX2/66", CPU_i486DX, 66666666, 2, 33333333, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8}, + {"iDX4/75", CPU_iDX4, 75000000, 3, 25000000, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9}, + {"iDX4/100", CPU_iDX4, 100000000, 3, 33333333, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 12}, + {"iDX4 OverDrive 75", CPU_iDX4, 75000000, 3, 25000000, 0x1480, 0x1480, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9}, + {"iDX4 OverDrive 100", CPU_iDX4, 100000000, 3, 33333333, 0x1480, 0x1480, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 12}, + {"Pentium OverDrive 63", CPU_PENTIUM, 62500000, 5/2, 25000000, 0x1531, 0x1531, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,7,7, 15/2}, + {"Pentium OverDrive 83", CPU_PENTIUM, 83333333, 5/2, 33333333, 0x1532, 0x1532, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,8,8, 10}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0, 0} }; CPU cpus_Am486[] = { /*Am486/5x86*/ {"Am486SX/33", CPU_Am486SX, 33333333, 1, 33333333, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4}, - {"Am486SX/40", CPU_Am486SX, 40000000, 1, 20000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, + {"Am486SX/40", CPU_Am486SX, 40000000, 1, 40000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, {"Am486SX2/50", CPU_Am486SX, 50000000, 2, 25000000, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6}, /*CPUID available on SX2, DX2, DX4, 5x86, >= 50 MHz*/ - {"Am486SX2/66", CPU_Am486SX, 66666666, 2, 33333333, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8}, /*Isn't on all real AMD SX2s and DX2s, availability here is pretty arbitary (and distinguishes them from the Intel chips)*/ + {"Am486SX2/66", CPU_Am486SX, 66666666, 2, 33333333, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8}, {"Am486DX/33", CPU_Am486DX, 33333333, 1, 33333333, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4}, - {"Am486DX/40", CPU_Am486DX, 40000000, 1, 20000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, + {"Am486DX/40", CPU_Am486DX, 40000000, 1, 40000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, {"Am486DX2/50", CPU_Am486DX, 50000000, 2, 25000000, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6}, {"Am486DX2/66", CPU_Am486DX, 66666666, 2, 33333333, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8}, - {"Am486DX2/80", CPU_Am486DX, 80000000, 2, 20000000, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, + {"Am486DX2/80", CPU_Am486DX, 80000000, 2, 40000000, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, {"Am486DX4/75", CPU_Am486DX, 75000000, 3, 25000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 12,12, 9, 9, 9}, {"Am486DX4/90", CPU_Am486DX, 90000000, 3, 30000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12}, {"Am486DX4/100", CPU_Am486DX, 100000000, 3, 33333333, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12}, - {"Am486DX4/120", CPU_Am486DX, 120000000, 3, 20000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 21,21, 9, 9, 15}, + {"Am486DX4/120", CPU_Am486DX, 120000000, 3, 40000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 21,21, 9, 9, 15}, {"Am5x86/P75", CPU_Am486DX, 133333333, 4, 33333333, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 16}, - {"Am5x86/P75+", CPU_Am486DX, 160000000, 4, 20000000, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12, 20}, + {"Am5x86/P75+", CPU_Am486DX, 150000000, 3, 25000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12, 20},/*The rare P75+ was indeed a triple-clocked 150 MHz according to research*/ + {"Am5x86/P90", CPU_Am486DX, 160000000, 4, 40000000, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12, 20},/*160 MHz on a 40 MHz bus was a common overclock and "5x86/P90" was used by a number of BIOSes to refer to that configuration*/ {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; CPU cpus_Cx486[] = { - /*Cx486/5x86*/ + /*Cyrix 486*/ {"Cx486S/25", CPU_Cx486S, 25000000, 1, 25000000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 4, 4, 3, 3, 3}, {"Cx486S/33", CPU_Cx486S, 33333333, 1, 33333333, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4}, - {"Cx486S/40", CPU_Cx486S, 40000000, 1, 20000000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, + {"Cx486S/40", CPU_Cx486S, 40000000, 1, 40000000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, {"Cx486DX/33", CPU_Cx486DX, 33333333, 1, 33333333, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4}, - {"Cx486DX/40", CPU_Cx486DX, 40000000, 1, 20000000, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, + {"Cx486DX/40", CPU_Cx486DX, 40000000, 1, 40000000, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, {"Cx486DX2/50", CPU_Cx486DX, 50000000, 2, 25000000, 0x430, 0, 0x081b, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6}, {"Cx486DX2/66", CPU_Cx486DX, 66666666, 2, 33333333, 0x430, 0, 0x0b1b, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8}, - {"Cx486DX2/80", CPU_Cx486DX, 80000000, 2, 20000000, 0x430, 0, 0x311b, CPU_SUPPORTS_DYNAREC, 14,14,16,16, 10}, + {"Cx486DX2/80", CPU_Cx486DX, 80000000, 2, 40000000, 0x430, 0, 0x311b, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, {"Cx486DX4/75", CPU_Cx486DX, 75000000, 3, 25000000, 0x480, 0, 0x361f, CPU_SUPPORTS_DYNAREC, 12,12, 9, 9, 9}, {"Cx486DX4/100", CPU_Cx486DX, 100000000, 3, 33333333, 0x480, 0, 0x361f, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12}, + + /*Cyrix 5x86*/ + {"Cx5x86/80", CPU_Cx5x86, 80000000, 2, 40000000, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, {"Cx5x86/100", CPU_Cx5x86, 100000000, 3, 33333333, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12}, - {"Cx5x86/120", CPU_Cx5x86, 120000000, 3, 20000000, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 21,21, 9, 9, 15}, + {"Cx5x86/120", CPU_Cx5x86, 120000000, 3, 40000000, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 21,21, 9, 9, 15}, {"Cx5x86/133", CPU_Cx5x86, 133333333, 4, 33333333, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 16}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; +CPU cpus_6x863V[] = { + /*Cyrix 6x86*/ + {"Cx6x86/P90", CPU_Cx6x86, 80000000, 2, 40000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8, 8, 6, 6, 10}, + {"Cx6x86/PR120+", CPU_Cx6x86, 100000000, 2, 25000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12}, + {"Cx6x86/PR133+", CPU_Cx6x86, 110000000, 2, 27500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14}, + {"Cx6x86/PR150+", CPU_Cx6x86, 120000000, 2, 30000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, + {"Cx6x86/PR166+", CPU_Cx6x86, 133333333, 2, 33333333, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, + {"Cx6x86/PR200+", CPU_Cx6x86, 150000000, 2, 37500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18}, + {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + }; + CPU cpus_6x86[] = { /*Cyrix 6x86*/ - {"6x86-P90", CPU_Cx6x86, 80000000, 3, 40000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8, 8, 6, 6, 10}, - {"6x86-PR120+", CPU_Cx6x86, 100000000, 3, 25000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12}, - {"6x86-PR133+", CPU_Cx6x86, 110000000, 3, 27500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14}, - {"6x86-PR150+", CPU_Cx6x86, 120000000, 3, 30000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, - {"6x86-PR166+", CPU_Cx6x86, 133333333, 3, 33333333, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, - {"6x86-PR200+", CPU_Cx6x86, 150000000, 3, 37500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18}, + {"Cx6x86/P90", CPU_Cx6x86, 80000000, 2, 40000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8, 8, 6, 6, 10}, + {"Cx6x86/PR120+", CPU_Cx6x86, 100000000, 2, 25000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12}, + {"Cx6x86/PR133+", CPU_Cx6x86, 110000000, 2, 27500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14}, + {"Cx6x86/PR150+", CPU_Cx6x86, 120000000, 2, 30000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, + {"Cx6x86/PR166+", CPU_Cx6x86, 133333333, 2, 33333333, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, + {"Cx6x86/PR200+", CPU_Cx6x86, 150000000, 2, 37500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18}, /*Cyrix 6x86L*/ - {"6x86L-PR133+", CPU_Cx6x86L, 110000000, 3, 27500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14}, - {"6x86L-PR150+", CPU_Cx6x86L, 120000000, 3, 30000000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, - {"6x86L-PR166+", CPU_Cx6x86L, 133333333, 3, 33333333, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, - {"6x86L-PR200+", CPU_Cx6x86L, 150000000, 3, 37500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18}, + {"Cx6x86L/PR133+", CPU_Cx6x86L, 110000000, 2, 27500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14}, + {"Cx6x86L/PR150+", CPU_Cx6x86L, 120000000, 2, 30000000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, + {"Cx6x86L/PR166+", CPU_Cx6x86L, 133333333, 2, 33333333, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, + {"Cx6x86L/PR200+", CPU_Cx6x86L, 150000000, 2, 37500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18}, - /*Cyrix 6x86MX*/ - {"6x86MX-PR166", CPU_Cx6x86MX, 133333333, 3, 33333333, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, - {"6x86MX-PR200", CPU_Cx6x86MX, 166666666, 3, 33333333, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, - {"6x86MX-PR233", CPU_Cx6x86MX, 188888888, 3, 37500000, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 45/2}, - {"6x86MX-PR266", CPU_Cx6x86MX, 207500000, 3, 41666667, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25}, - {"6x86MX-PR300", CPU_Cx6x86MX, 233333333, 3, 33333333, 0x600, 0x600, 0x0454, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21, 7, 7, 28}, - {"6x86MX-PR333", CPU_Cx6x86MX, 250000000, 3, 41666667, 0x600, 0x600, 0x0453, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 20,20, 9, 9, 30}, - {"6x86MX-PR366", CPU_Cx6x86MX, 250000000, 3, 33333333, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 30}, - {"6x86MX-PR400", CPU_Cx6x86MX, 285000000, 3, 41666667, 0x600, 0x600, 0x0453, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 33}, + /*Cyrix 6x86MX/MII*/ + {"Cx6x86MX/PR166", CPU_Cx6x86MX, 133333333, 2, 33333333, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, + {"Cx6x86MX/PR200", CPU_Cx6x86MX, 166666666, 5/2, 33333333, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"Cx6x86MX/PR233", CPU_Cx6x86MX, 187500000, 5/2, 37500000, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 45/2}, + {"Cx6x86MX/PR266", CPU_Cx6x86MX, 208333333, 5/2, 41666666, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25}, + {"MII/PR300", CPU_Cx6x86MX, 233333333, 7/2, 33333333, 0x601, 0x601, 0x0852, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21, 7, 7, 28}, + {"MII/PR333", CPU_Cx6x86MX, 250000000, 3, 41666666, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 20,20, 9, 9, 30}, + {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + }; + + CPU cpus_6x86SS7[] = { + /*Cyrix 6x86*/ + {"Cx6x86/P90", CPU_Cx6x86, 80000000, 2, 40000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8, 8, 6, 6, 10}, + {"Cx6x86/PR120+", CPU_Cx6x86, 100000000, 2, 25000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12}, + {"Cx6x86/PR133+", CPU_Cx6x86, 110000000, 2, 27500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14}, + {"Cx6x86/PR150+", CPU_Cx6x86, 120000000, 2, 30000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, + {"Cx6x86/PR166+", CPU_Cx6x86, 133333333, 2, 33333333, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, + {"Cx6x86/PR200+", CPU_Cx6x86, 150000000, 2, 37500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18}, + + /*Cyrix 6x86L*/ + {"Cx6x86L/PR133+", CPU_Cx6x86L, 110000000, 2, 27500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14}, + {"Cx6x86L/PR150+", CPU_Cx6x86L, 120000000, 2, 30000000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, + {"Cx6x86L/PR166+", CPU_Cx6x86L, 133333333, 2, 33333333, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, + {"Cx6x86L/PR200+", CPU_Cx6x86L, 150000000, 2, 37500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18}, + + /*Cyrix 6x86MX/MII*/ + {"Cx6x86MX/PR166", CPU_Cx6x86MX, 133333333, 2, 33333333, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, + {"Cx6x86MX/PR200", CPU_Cx6x86MX, 166666666, 5/2, 33333333, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"Cx6x86MX/PR233", CPU_Cx6x86MX, 187500000, 5/2, 37500000, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 45/2}, + {"Cx6x86MX/PR266", CPU_Cx6x86MX, 208333333, 5/2, 41666666, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25}, + {"MII/PR300", CPU_Cx6x86MX, 233333333, 7/2, 33333333, 0x601, 0x601, 0x0852, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21, 7, 7, 28}, + {"MII/PR333", CPU_Cx6x86MX, 250000000, 3, 41666666, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 20,20, 9, 9, 30}, + {"MII/PR366", CPU_Cx6x86MX, 250000000, 5/2, 33333333, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 20,20, 9, 9, 30}, + {"MII/PR400", CPU_Cx6x86MX, 285000000, 3, 31666666, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 20,20, 9, 9, 30}, + {"MII/PR433", CPU_Cx6x86MX, 300000000, 3, 33333333, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 20,20, 9, 9, 30}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; CPU cpus_WinChip[] = { /*IDT WinChip*/ - {"WinChip 75", CPU_WINCHIP, 75000000, 2, 25000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 4, 4, 9}, - {"WinChip 90", CPU_WINCHIP, 90000000, 2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9, 9, 4, 4, 21/2}, - {"WinChip 100", CPU_WINCHIP, 100000000, 2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9, 9, 4, 4, 12}, - {"WinChip 120", CPU_WINCHIP, 120000000, 2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12, 12, 6, 6, 14}, - {"WinChip 133", CPU_WINCHIP, 133333333, 2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12, 12, 6, 6, 16}, - {"WinChip 150", CPU_WINCHIP, 150000000, 3, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15, 15, 7, 7, 35/2}, - {"WinChip 166", CPU_WINCHIP, 166666666, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15, 15, 7, 7, 40}, - {"WinChip 180", CPU_WINCHIP, 180000000, 3, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 21}, - {"WinChip 200", CPU_WINCHIP, 200000000, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 24}, - {"WinChip 240", CPU_WINCHIP, 240000000, 6, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 28}, - {"WinChip 2/200", CPU_WINCHIP2, 200000000, 3, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 3*8}, - {"WinChip 2/240", CPU_WINCHIP2, 240000000, 6, 30000000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 30}, - {"WinChip 2A/200", CPU_WINCHIP2, 200000000, 3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 3*8}, - {"WinChip 2A/233", CPU_WINCHIP2, 233333333, 3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, (7*8)/2}, + {"WinChip 75", CPU_WINCHIP, 75000000, 3/2, 25000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 4, 4, 9}, + {"WinChip 90", CPU_WINCHIP, 90000000, 3/2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9, 9, 4, 4, 21/2}, + {"WinChip 100", CPU_WINCHIP, 100000000, 3/2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9, 9, 4, 4, 12}, + {"WinChip 120", CPU_WINCHIP, 120000000, 2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12, 12, 6, 6, 14}, + {"WinChip 133", CPU_WINCHIP, 133333333, 2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12, 12, 6, 6, 16}, + {"WinChip 150", CPU_WINCHIP, 150000000, 5/2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15, 15, 7, 7, 35/2}, + {"WinChip 166", CPU_WINCHIP, 166666666, 5/2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15, 15, 7, 7, 40}, + {"WinChip 180", CPU_WINCHIP, 180000000, 3, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 21}, + {"WinChip 200", CPU_WINCHIP, 200000000, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 24}, + {"WinChip 225", CPU_WINCHIP, 225000000, 3, 37500000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 27}, + {"WinChip 240", CPU_WINCHIP, 240000000, 4, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 28}, + {"WinChip 2/200", CPU_WINCHIP2, 200000000, 3, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 24}, + {"WinChip 2/225", CPU_WINCHIP2, 225000000, 3, 37500000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 27}, + {"WinChip 2/240", CPU_WINCHIP2, 240000000, 4, 30000000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 30}, + {"WinChip 2/250", CPU_WINCHIP2, 250000000, 3, 41666667, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 30}, + {"WinChip 2A/200", CPU_WINCHIP2, 200000000, 3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 24}, + {"WinChip 2A/233", CPU_WINCHIP2, 233333333, 7/2, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, (7*8)/2}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; CPU cpus_WinChip_SS7[] = { /*IDT WinChip*/ - {"WinChip 75", CPU_WINCHIP, 75000000, 2, 25000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 4, 4, 9}, - {"WinChip 90", CPU_WINCHIP, 90000000, 2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9, 9, 4, 4, 21/2}, - {"WinChip 100", CPU_WINCHIP, 100000000, 2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9, 9, 4, 4, 12}, - {"WinChip 120", CPU_WINCHIP, 120000000, 2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12, 12, 6, 6, 14}, - {"WinChip 133", CPU_WINCHIP, 133333333, 2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12, 12, 6, 6, 16}, - {"WinChip 150", CPU_WINCHIP, 150000000, 3, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15, 15, 7, 7, 35/2}, - {"WinChip 166", CPU_WINCHIP, 166666666, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15, 15, 7, 7, 40}, - {"WinChip 180", CPU_WINCHIP, 180000000, 3, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 21}, - {"WinChip 200", CPU_WINCHIP, 200000000, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 24}, - {"WinChip 225", CPU_WINCHIP, 225000000, 3, 37500000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 27}, - {"WinChip 240", CPU_WINCHIP, 240000000, 6, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 28}, - {"WinChip 2/200", CPU_WINCHIP2, 200000000, 3, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 3*8}, - {"WinChip 2/225", CPU_WINCHIP2, 225000000, 3, 37500000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 3*9}, - {"WinChip 2/240", CPU_WINCHIP2, 240000000, 6, 30000000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 30}, - {"WinChip 2/250", CPU_WINCHIP2, 250000000, 6, 41666667, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 30}, - {"WinChip 2A/200", CPU_WINCHIP2, 200000000, 3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 3*8}, - {"WinChip 2A/233", CPU_WINCHIP2, 233333333, 3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, (7*8)/2}, - {"WinChip 2A/266", CPU_WINCHIP2, 233333333, 6, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 28}, - {"WinChip 2A/300", CPU_WINCHIP2, 250000000, 6, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 30}, + {"WinChip 75", CPU_WINCHIP, 75000000, 3/2, 25000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 4, 4, 9}, + {"WinChip 90", CPU_WINCHIP, 90000000, 3/2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9, 9, 4, 4, 21/2}, + {"WinChip 100", CPU_WINCHIP, 100000000, 3/2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9, 9, 4, 4, 12}, + {"WinChip 120", CPU_WINCHIP, 120000000, 2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12, 12, 6, 6, 14}, + {"WinChip 133", CPU_WINCHIP, 133333333, 2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12, 12, 6, 6, 16}, + {"WinChip 150", CPU_WINCHIP, 150000000, 5/2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15, 15, 7, 7, 35/2}, + {"WinChip 166", CPU_WINCHIP, 166666666, 5/2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15, 15, 7, 7, 40}, + {"WinChip 180", CPU_WINCHIP, 180000000, 3, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 21}, + {"WinChip 200", CPU_WINCHIP, 200000000, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 24}, + {"WinChip 225", CPU_WINCHIP, 225000000, 3, 37500000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 27}, + {"WinChip 240", CPU_WINCHIP, 240000000, 4, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 28}, + {"WinChip 2/200", CPU_WINCHIP2, 200000000, 3, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 3*8}, + {"WinChip 2/225", CPU_WINCHIP2, 225000000, 3, 37500000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 3*9}, + {"WinChip 2/240", CPU_WINCHIP2, 240000000, 4, 30000000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 30}, + {"WinChip 2/250", CPU_WINCHIP2, 250000000, 3, 41666667, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 30}, + {"WinChip 2A/200", CPU_WINCHIP2, 200000000, 3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 3*8}, + {"WinChip 2A/233", CPU_WINCHIP2, 233333333, 7/2, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 21, 21, 9, 9, (7*8)/2}, + {"WinChip 2A/266", CPU_WINCHIP2, 233333333, 7/3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 21, 21, 7, 7, 28}, + {"WinChip 2A/300", CPU_WINCHIP2, 250000000, 5/2, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 8, 8, 30}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; CPU cpus_Pentium5V[] = { /*Intel Pentium (5V, socket 4)*/ - {"Pentium 60", CPU_PENTIUM, 60000000, 1, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6,3,3, 7}, - {"Pentium 66", CPU_PENTIUM, 66666666, 1, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6,3,3, 8}, + {"Pentium 60", CPU_PENTIUM, 60000000, 1, 30000000, 0x517, 0x517, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6,3,3, 7}, + {"Pentium 66", CPU_PENTIUM, 66666666, 1, 33333333, 0x517, 0x517, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6,3,3, 8}, {"Pentium OverDrive 120", CPU_PENTIUM, 120000000, 2, 30000000, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14}, {"Pentium OverDrive 133", CPU_PENTIUM, 133333333, 2, 33333333, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0, 0} @@ -367,8 +457,8 @@ CPU cpus_Pentium5V[] = { CPU cpus_Pentium5V50[] = { /*Intel Pentium (5V, socket 4, including 50 MHz FSB)*/ {"Pentium 50 (Q0399)", CPU_PENTIUM, 50000000, 1, 25000000, 0x513, 0x513, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 4, 4,3,3, 6}, - {"Pentium 60", CPU_PENTIUM, 60000000, 1, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6,3,3, 7}, - {"Pentium 66", CPU_PENTIUM, 66666666, 1, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6,3,3, 8}, + {"Pentium 60", CPU_PENTIUM, 60000000, 1, 30000000, 0x517, 0x517, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6,3,3, 7}, + {"Pentium 66", CPU_PENTIUM, 66666666, 1, 33333333, 0x517, 0x517, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6,3,3, 8}, {"Pentium OverDrive 100", CPU_PENTIUM, 100000000, 2, 25000000, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8, 8,6,6, 12}, {"Pentium OverDrive 120", CPU_PENTIUM, 120000000, 2, 30000000, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14}, {"Pentium OverDrive 133", CPU_PENTIUM, 133333333, 2, 33333333, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16}, @@ -377,170 +467,211 @@ CPU cpus_Pentium5V50[] = { CPU cpus_PentiumS5[] = { /*Intel Pentium (Socket 5)*/ - {"Pentium 75", CPU_PENTIUM, 75000000, 2, 25000000, 0x522, 0x522, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9}, - {"Pentium OverDrive MMX 75", CPU_PENTIUMMMX, 75000000, 2, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9}, - {"Pentium 90", CPU_PENTIUM, 90000000, 2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 21/2}, - {"Pentium 100/50", CPU_PENTIUM, 100000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 12}, - {"Pentium 100/66", CPU_PENTIUM, 100000000, 2, 33333333, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12}, - {"Pentium 120", CPU_PENTIUM, 120000000, 2, 30000000, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14}, - {"Pentium OverDrive 125", CPU_PENTIUM, 125000000, 3, 25000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, 16}, - {"Pentium OverDrive 150", CPU_PENTIUM, 150000000, 3, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2}, - {"Pentium OverDrive 166", CPU_PENTIUM, 166666666, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 40}, - {"Pentium OverDrive MMX 125", CPU_PENTIUMMMX, 125000000, 3, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, 15}, - {"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX, 150000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2}, - {"Pentium OverDrive MMX 166", CPU_PENTIUMMMX, 166000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20}, - {"Pentium OverDrive MMX 180", CPU_PENTIUMMMX, 180000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 21}, - {"Pentium OverDrive MMX 200", CPU_PENTIUMMMX, 200000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24}, + {"Pentium 75", CPU_PENTIUM, 75000000, 3/2, 25000000, 0x522, 0x522, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9}, + {"Pentium OverDrive MMX 75", CPU_PENTIUMMMX, 75000000, 3/2, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9}, + {"Pentium 90", CPU_PENTIUM, 90000000, 3/2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 21/2}, + {"Pentium 100/50", CPU_PENTIUM, 100000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 12}, + {"Pentium 100/66", CPU_PENTIUM, 100000000, 3/2, 33333333, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12}, + {"Pentium 120", CPU_PENTIUM, 120000000, 2, 30000000, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14}, + + /*Intel Pentium OverDrive*/ + {"Pentium OverDrive 125", CPU_PENTIUM, 125000000, 3, 25000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, 16}, + {"Pentium OverDrive 150", CPU_PENTIUM, 150000000, 5/2, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2}, + {"Pentium OverDrive 166", CPU_PENTIUM, 166666666, 5/2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 40}, + {"Pentium OverDrive MMX 125", CPU_PENTIUMMMX, 125000000, 5/2, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, 15}, + {"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX, 150000000, 5/2, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2}, + {"Pentium OverDrive MMX 166", CPU_PENTIUMMMX, 166000000, 5/2, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20}, + {"Pentium OverDrive MMX 180", CPU_PENTIUMMMX, 180000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 21}, + {"Pentium OverDrive MMX 200", CPU_PENTIUMMMX, 200000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0, 0} }; +CPU cpus_Pentium3V[] = { + /*Intel Pentium*/ + {"Pentium 75", CPU_PENTIUM, 75000000, 3/2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9}, + {"Pentium OverDrive MMX 75", CPU_PENTIUMMMX, 75000000, 3/2, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9}, + {"Pentium 90", CPU_PENTIUM, 90000000, 3/2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2}, + {"Pentium 100/50", CPU_PENTIUM, 100000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12}, + {"Pentium 100/66", CPU_PENTIUM, 100000000, 3/2, 33333333, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, + {"Pentium 120", CPU_PENTIUM, 120000000, 2, 30000000, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, + {"Pentium 133", CPU_PENTIUM, 133333333, 2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, + {"Pentium 150", CPU_PENTIUM, 150000000, 5/2, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, + {"Pentium 166", CPU_PENTIUM, 166666666, 5/2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"Pentium 200", CPU_PENTIUM, 200000000, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, + + /*Intel Pentium OverDrive*/ + {"Pentium OverDrive 125", CPU_PENTIUM, 125000000, 5/2, 25000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 7, 7, 15}, + {"Pentium OverDrive 150", CPU_PENTIUM, 150000000, 5/2, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, + {"Pentium OverDrive 166", CPU_PENTIUM, 166666666, 5/2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"Pentium OverDrive MMX 125", CPU_PENTIUMMMX, 125000000, 5/2, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 7, 7, 15}, + {"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX, 150000000, 5/2, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, + {"Pentium OverDrive MMX 166", CPU_PENTIUMMMX, 166000000, 5/2, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"Pentium OverDrive MMX 180", CPU_PENTIUMMMX, 180000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 21}, + {"Pentium OverDrive MMX 200", CPU_PENTIUMMMX, 200000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, + {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +}; + CPU cpus_Pentium[] = { /*Intel Pentium*/ - {"Pentium 75", CPU_PENTIUM, 75000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9}, - {"Pentium OverDrive MMX 75", CPU_PENTIUMMMX, 75000000, 2, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9}, - {"Pentium 90", CPU_PENTIUM, 90000000, 2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2}, - {"Pentium 100/50", CPU_PENTIUM, 100000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12}, - {"Pentium 100/66", CPU_PENTIUM, 100000000, 2, 33333333, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, - {"Pentium 120", CPU_PENTIUM, 120000000, 2, 30000000, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, - {"Pentium 133", CPU_PENTIUM, 133333333, 2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, - {"Pentium 150", CPU_PENTIUM, 150000000, 3, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, - {"Pentium 166", CPU_PENTIUM, 166666666, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, - {"Pentium 200", CPU_PENTIUM, 200000000, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, - {"Pentium MMX 166", CPU_PENTIUMMMX, 166666666, 3, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, - {"Pentium MMX 200", CPU_PENTIUMMMX, 200000000, 3, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, - {"Pentium MMX 233", CPU_PENTIUMMMX, 233333333, 4, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, - {"Mobile Pentium MMX 120", CPU_PENTIUMMMX, 120000000, 2, 30000000, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, - {"Mobile Pentium MMX 133", CPU_PENTIUMMMX, 133333333, 2, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, - {"Mobile Pentium MMX 150", CPU_PENTIUMMMX, 150000000, 3, 30000000, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, - {"Mobile Pentium MMX 166", CPU_PENTIUMMMX, 166666666, 3, 33333333, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, - {"Mobile Pentium MMX 200", CPU_PENTIUMMMX, 200000000, 3, 33333333, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, - {"Mobile Pentium MMX 233", CPU_PENTIUMMMX, 233333333, 4, 33333333, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, - {"Mobile Pentium MMX 266", CPU_PENTIUMMMX, 266666666, 4, 33333333, 0x582, 0x582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, - {"Mobile Pentium MMX 300", CPU_PENTIUMMMX, 300000000, 5, 33333333, 0x582, 0x582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36}, - {"Pentium OverDrive 125", CPU_PENTIUM, 125000000, 3, 25000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 7, 7, 15}, - {"Pentium OverDrive 150", CPU_PENTIUM, 150000000, 3, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, - {"Pentium OverDrive 166", CPU_PENTIUM, 166666666, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, - {"Pentium OverDrive MMX 125", CPU_PENTIUMMMX, 125000000, 3, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 7, 7, 15}, - {"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX, 150000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, - {"Pentium OverDrive MMX 166", CPU_PENTIUMMMX, 166000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, - {"Pentium OverDrive MMX 180", CPU_PENTIUMMMX, 180000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 21}, - {"Pentium OverDrive MMX 200", CPU_PENTIUMMMX, 200000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, + {"Pentium 75", CPU_PENTIUM, 75000000, 3/2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9}, + {"Pentium OverDrive MMX 75", CPU_PENTIUMMMX, 75000000, 3/2, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9}, + {"Pentium 90", CPU_PENTIUM, 90000000, 3/2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2}, + {"Pentium 100/50", CPU_PENTIUM, 100000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12}, + {"Pentium 100/66", CPU_PENTIUM, 100000000, 3/2, 33333333, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, + {"Pentium 120", CPU_PENTIUM, 120000000, 2, 30000000, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, + {"Pentium 133", CPU_PENTIUM, 133333333, 2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, + {"Pentium 150", CPU_PENTIUM, 150000000, 5/2, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, + {"Pentium 166", CPU_PENTIUM, 166666666, 5/2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"Pentium 200", CPU_PENTIUM, 200000000, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, + + /*Intel Pentium MMX*/ + {"Pentium MMX 166", CPU_PENTIUMMMX, 166666666, 5/2, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"Pentium MMX 200", CPU_PENTIUMMMX, 200000000, 3, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, + {"Pentium MMX 233", CPU_PENTIUMMMX, 233333333, 7/2, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, + {"Mobile Pentium MMX 120", CPU_PENTIUMMMX, 120000000, 2, 30000000, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, + {"Mobile Pentium MMX 133", CPU_PENTIUMMMX, 133333333, 2, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, + {"Mobile Pentium MMX 150", CPU_PENTIUMMMX, 150000000, 5/2, 30000000, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, + {"Mobile Pentium MMX 166", CPU_PENTIUMMMX, 166666666, 5/2, 33333333, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"Mobile Pentium MMX 200", CPU_PENTIUMMMX, 200000000, 3, 33333333, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, + {"Mobile Pentium MMX 233", CPU_PENTIUMMMX, 233333333, 7/2, 33333333, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, + {"Mobile Pentium MMX 266", CPU_PENTIUMMMX, 266666666, 4, 33333333, 0x582, 0x582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, + {"Mobile Pentium MMX 300", CPU_PENTIUMMMX, 300000000, 9/2, 33333333, 0x582, 0x582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36}, + + /*Intel Pentium OverDrive*/ + {"Pentium OverDrive 125", CPU_PENTIUM, 125000000, 5/2, 25000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 7, 7, 15}, + {"Pentium OverDrive 150", CPU_PENTIUM, 150000000, 5/2, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, + {"Pentium OverDrive 166", CPU_PENTIUM, 166666666, 5/2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"Pentium OverDrive MMX 125", CPU_PENTIUMMMX, 125000000, 5/2, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 7, 7, 15}, + {"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX, 150000000, 5/2, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, + {"Pentium OverDrive MMX 166", CPU_PENTIUMMMX, 166000000, 5/2, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"Pentium OverDrive MMX 180", CPU_PENTIUMMMX, 180000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 21}, + {"Pentium OverDrive MMX 200", CPU_PENTIUMMMX, 200000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; - CPU cpus_K5[] = { /*AMD K5 (Socket 5)*/ - {"K5 (5k86) 75 (P75)", CPU_K5, 75000000, 2, 25000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9}, - {"K5 (SSA/5) 75 (PR75)", CPU_K5, 75000000, 2, 25000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9}, - {"K5 (5k86) 90 (P90)", CPU_K5, 90000000, 2, 30000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 21/2}, - {"K5 (SSA/5) 90 (PR90)", CPU_K5, 90000000, 2, 30000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 21/2}, - {"K5 (5k86) 100 (P100)", CPU_K5, 100000000, 2, 33333333, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12}, - {"K5 (SSA/5) 100 (PR100)", CPU_K5, 100000000, 2, 33333333, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12}, - {"K5 (5k86) 90 (PR120)", CPU_5K86, 120000000, 2, 30000000, 0x511, 0x511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14}, - {"K5 (5k86) 100 (PR133)", CPU_5K86, 133333333, 2, 33333333, 0x514, 0x514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16}, - {"K5 (5k86) 105 (PR150)", CPU_5K86, 150000000, 3, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2}, - {"K5 (5k86) 116.5 (PR166)", CPU_5K86, 166666666, 3, 33333333, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20}, - {"K5 (5k86) 133 (PR200)", CPU_5K86, 200000000, 3, 33333333, 0x534, 0x534, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24}, + {"K5 (5k86) 75 (P75)", CPU_K5, 75000000, 3/2, 25000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9}, + {"K5 (SSA/5) 75 (PR75)", CPU_K5, 75000000, 3/2, 25000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9}, + {"K5 (5k86) 90 (P90)", CPU_K5, 90000000, 3/2, 30000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 21/2}, + {"K5 (SSA/5) 90 (PR90)", CPU_K5, 90000000, 3/2, 30000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 21/2}, + {"K5 (5k86) 100 (P100)", CPU_K5, 100000000, 3/2, 33333333, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12}, + {"K5 (SSA/5) 100 (PR100)", CPU_K5, 100000000, 3/2, 33333333, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12}, + {"K5 (5k86) 90 (PR120)", CPU_5K86, 120000000, 2, 30000000, 0x511, 0x511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14}, + {"K5 (5k86) 100 (PR133)", CPU_5K86, 133333333, 2, 33333333, 0x514, 0x514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16}, + {"K5 (5k86) 105 (PR150)", CPU_5K86, 150000000, 5/2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2}, + {"K5 (5k86) 116.5 (PR166)", CPU_5K86, 166666666, 5/2, 33333333, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20}, + {"K5 (5k86) 133 (PR200)", CPU_5K86, 200000000, 3, 33333333, 0x534, 0x534, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0, 0} }; CPU cpus_K56[] = { - /*AMD K5 and K6 (Socket 7)*/ - {"K5 (5k86) 75 (P75)", CPU_K5, 75000000, 2, 25000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9}, - {"K5 (SSA/5) 75 (PR75)", CPU_K5, 75000000, 2, 25000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9}, - {"K5 (5k86) 90 (P90)", CPU_K5, 90000000, 2, 30000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2}, - {"K5 (SSA/5) 90 (PR90)", CPU_K5, 90000000, 2, 30000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2}, - {"K5 (5k86) 100 (P100)", CPU_K5, 100000000, 2, 33333333, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, - {"K5 (SSA/5) 100 (PR100)", CPU_K5, 100000000, 2, 33333333, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, - {"K5 (5k86) 90 (PR120)", CPU_5K86, 120000000, 2, 30000000, 0x511, 0x511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, - {"K5 (5k86) 100 (PR133)", CPU_5K86, 133333333, 2, 33333333, 0x514, 0x514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, - {"K5 (5k86) 105 (PR150)", CPU_5K86, 150000000, 3, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, - {"K5 (5k86) 116.5 (PR166)", CPU_5K86, 166666666, 3, 33333333, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, - {"K5 (5k86) 133 (PR200)", CPU_5K86, 200000000, 3, 33333333, 0x534, 0x534, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, - {"K6 (Model 6) 166", CPU_K6, 166666666, 3, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, - {"K6 (Model 6) 200", CPU_K6, 200000000, 3, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, - {"K6 (Model 6) 233", CPU_K6, 233333333, 4, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, - {"K6 (Model 7) 200", CPU_K6, 200000000, 3, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, - {"K6 (Model 7) 233", CPU_K6, 233333333, 4, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, - {"K6 (Model 7) 266", CPU_K6, 266666666, 4, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, - {"K6 (Model 7) 300", CPU_K6, 300000000, 5, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36}, - {"K6-2/233", CPU_K6_2, 233333333, 4, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, - {"K6-2/266", CPU_K6_2, 266666666, 4, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, - {"K6-2/300 AFR-66", CPU_K6_2, 300000000, 5, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36}, + /*AMD K5 (Socket 7)*/ + {"K5 (5k86) 75 (P75)", CPU_K5, 75000000, 3/2, 25000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9}, + {"K5 (SSA/5) 75 (PR75)", CPU_K5, 75000000, 3/2, 25000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9}, + {"K5 (5k86) 90 (P90)", CPU_K5, 90000000, 3/2, 30000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2}, + {"K5 (SSA/5) 90 (PR90)", CPU_K5, 90000000, 3/2, 30000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2}, + {"K5 (5k86) 100 (P100)", CPU_K5, 100000000, 3/2, 33333333, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, + {"K5 (SSA/5) 100 (PR100)", CPU_K5, 100000000, 3/2, 33333333, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, + {"K5 (5k86) 90 (PR120)", CPU_5K86, 120000000, 2, 30000000, 0x511, 0x511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, + {"K5 (5k86) 100 (PR133)", CPU_5K86, 133333333, 2, 33333333, 0x514, 0x514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, + {"K5 (5k86) 105 (PR150)", CPU_5K86, 150000000, 5/2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, + {"K5 (5k86) 116.5 (PR166)", CPU_5K86, 166666666, 5/2, 33333333, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"K5 (5k86) 133 (PR200)", CPU_5K86, 200000000, 3, 33333333, 0x534, 0x534, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, + + /*AMD K6 (Socket 7*/ + {"K6 (Model 6) 166", CPU_K6, 166666666, 5/2, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"K6 (Model 6) 200", CPU_K6, 200000000, 3, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, + {"K6 (Model 6) 233", CPU_K6, 233333333, 7/2, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21, 10, 10, 28}, + {"K6 (Model 7) 200", CPU_K6, 200000000, 3, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, + {"K6 (Model 7) 233", CPU_K6, 233333333, 7/2, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21, 10, 10, 28}, + {"K6 (Model 7) 266", CPU_K6, 266666666, 4, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24, 12, 12, 32}, + {"K6 (Model 7) 300", CPU_K6, 300000000, 9/2, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 13, 13, 36}, + {"K6-2/233", CPU_K6_2, 233333333, 7/2, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21, 10, 10, 28}, + {"K6-2/266", CPU_K6_2, 266666666, 4, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24, 12, 12, 32}, + {"K6-2/300 AFR-66", CPU_K6_2, 300000000, 9/2, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 13, 13, 36}, + {"K6-2/366", CPU_K6_2, 366666666, 11/2, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 33,33,33/2,33/2, 44}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; CPU cpus_K56_SS7[] = { - /*AMD K5 and K6 (Socket 7)*/ - {"K5 (5k86) 75 (P75)", CPU_K5, 75000000, 2, 25000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9}, - {"K5 (SSA/5) 75 (PR75)", CPU_K5, 75000000, 2, 25000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9}, - {"K5 (5k86) 90 (P90)", CPU_K5, 90000000, 2, 30000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2}, - {"K5 (SSA/5) 90 (PR90)", CPU_K5, 90000000, 2, 30000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2}, - {"K5 (5k86) 100 (P100)", CPU_K5, 100000000, 2, 33333333, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, - {"K5 (SSA/5) 100 (PR100)", CPU_K5, 100000000, 2, 33333333, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, - {"K5 (5k86) 90 (PR120)", CPU_5K86, 120000000, 2, 30000000, 0x511, 0x511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, - {"K5 (5k86) 100 (PR133)", CPU_5K86, 133333333, 2, 33333333, 0x514, 0x514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, - {"K5 (5k86) 105 (PR150)", CPU_5K86, 150000000, 3, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, - {"K5 (5k86) 116.5 (PR166)", CPU_5K86, 166666666, 3, 33333333, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, - {"K5 (5k86) 133 (PR200)", CPU_5K86, 200000000, 3, 33333333, 0x534, 0x534, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, - {"K6 (Model 6) 166", CPU_K6, 166666666, 3, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, - {"K6 (Model 6) 200", CPU_K6, 200000000, 3, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, - {"K6 (Model 6) 233", CPU_K6, 233333333, 4, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, - {"K6 (Model 7) 200", CPU_K6, 200000000, 3, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, - {"K6 (Model 7) 233", CPU_K6, 233333333, 4, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, - {"K6 (Model 7) 266", CPU_K6, 266666666, 4, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, - {"K6 (Model 7) 300", CPU_K6, 300000000, 5, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36}, - {"K6-2/233", CPU_K6_2, 233333333, 4, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, - {"K6-2/266", CPU_K6_2, 266666666, 4, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, - {"K6-2/300", CPU_K6_2, 300000000, 5, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36}, - {"K6-2/333", CPU_K6_2, 333333333, 5, 31666667, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 40}, - {"K6-2/350", CPU_K6_2, 350000000, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 42}, - {"K6-2/366", CPU_K6_2, 366666666, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 44}, - {"K6-2/380", CPU_K6_2, 380000000, 5, 31666667, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 46}, - {"K6-2/400", CPU_K6_2, 400000000, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 48}, - {"K6-2/450", CPU_K6_2, 450000000, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 54}, - {"K6-2/475", CPU_K6_2, 475000000, 5, 31666667, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 57}, - {"K6-2/500", CPU_K6_2, 500000000, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 60}, - {"K6-2/533", CPU_K6_2, 533333333, 5, 31666667, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 64}, - {"K6-2/550", CPU_K6_2, 550000000, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 66}, - {"K6-2+/450", CPU_K6_2P, 450000000, 5, 33333333, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 54}, - {"K6-2+/475", CPU_K6_2P, 475000000, 5, 31666667, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 57}, - {"K6-2+/500", CPU_K6_2P, 500000000, 5, 33333333, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 60}, - {"K6-2+/533", CPU_K6_2P, 533333333, 5, 31666667, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 64}, - {"K6-2+/550", CPU_K6_2P, 550000000, 5, 33333333, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 66}, - {"K6-III/400", CPU_K6_3, 400000000, 5, 33333333, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 48}, - {"K6-III/450", CPU_K6_3, 450000000, 5, 33333333, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 54}, - {"K6-III+/400", CPU_K6_3P, 400000000, 5, 33333333, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 48}, - {"K6-III+/450", CPU_K6_3P, 450000000, 5, 33333333, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 54}, - {"K6-III+/475", CPU_K6_3P, 475000000, 5, 31666667, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 57}, - {"K6-III+/500", CPU_K6_3P, 500000000, 5, 33333333, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 60}, + /*AMD K5 (Socket 7)*/ + {"K5 (5k86) 75 (P75)", CPU_K5, 75000000, 3/2, 25000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9}, + {"K5 (SSA/5) 75 (PR75)", CPU_K5, 75000000, 3/2, 25000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9}, + {"K5 (5k86) 90 (P90)", CPU_K5, 90000000, 3/2, 30000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2}, + {"K5 (SSA/5) 90 (PR90)", CPU_K5, 90000000, 3/2, 30000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2}, + {"K5 (5k86) 100 (P100)", CPU_K5, 100000000, 3/2, 33333333, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, + {"K5 (SSA/5) 100 (PR100)", CPU_K5, 100000000, 3/2, 33333333, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, + {"K5 (5k86) 90 (PR120)", CPU_5K86, 120000000, 2, 30000000, 0x511, 0x511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, + {"K5 (5k86) 100 (PR133)", CPU_5K86, 133333333, 2, 33333333, 0x514, 0x514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, + {"K5 (5k86) 105 (PR150)", CPU_5K86, 150000000, 5/2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, + {"K5 (5k86) 116.5 (PR166)", CPU_5K86, 166666666, 5/2, 33333333, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"K5 (5k86) 133 (PR200)", CPU_5K86, 200000000, 3, 33333333, 0x534, 0x534, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, + + /*AMD K6 (Socket 7)*/ + {"K6 (Model 6) 166", CPU_K6, 166666666, 5/2, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"K6 (Model 6) 200", CPU_K6, 200000000, 3, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, + {"K6 (Model 6) 233", CPU_K6, 233333333, 7/2, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, + {"K6 (Model 7) 200", CPU_K6, 200000000, 3, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, + {"K6 (Model 7) 233", CPU_K6, 233333333, 7/2, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, + {"K6 (Model 7) 266", CPU_K6, 266666666, 4, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, + {"K6 (Model 7) 300", CPU_K6, 300000000, 9/2, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36}, + + /*AMD K6-2 (Socket 7/Super Socket 7)*/ + {"K6-2/233", CPU_K6_2, 233333333, 7/2, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21, 21, 10, 10, 28}, + {"K6-2/266", CPU_K6_2, 266666666, 4, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24, 24, 12, 12, 32}, + {"K6-2/300", CPU_K6_2, 300000000, 3, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27, 27, 9, 9, 36}, + {"K6-2/333", CPU_K6_2, 332500000, 7/2, 31666667, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 30, 30,21/2,21/2, 40}, + {"K6-2/350", CPU_K6_2, 350000000, 7/2, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 63/2, 63/2,21/2,21/2, 42}, + {"K6-2/366", CPU_K6_2, 366666666, 11/2, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 33, 33,33/2,33/2, 44}, + {"K6-2/380", CPU_K6_2, 380000000, 4, 31666667, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 34, 34, 12, 12, 46}, + {"K6-2/400", CPU_K6_2, 400000000, 4, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48}, + {"K6-2/450", CPU_K6_2, 450000000, 9/2, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 81/2, 81/2,27/2,27/2, 54}, + {"K6-2/475", CPU_K6_2, 475000000, 5, 31666667, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 171/4,171/4, 15, 15, 57}, + {"K6-2/500", CPU_K6_2, 500000000, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 45, 45, 15, 15, 60}, + {"K6-2/533", CPU_K6_2, 533333333, 11/2, 32323232, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 48, 48,33/2,33/2, 64}, + {"K6-2/550", CPU_K6_2, 550000000, 11/2, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 99/2, 99/2,33/2,33/2, 66}, + + /*AMD K6-2+/K6-3/K6-3+ (Super Socket 7)*/ + {"K6-2+/450", CPU_K6_2P, 450000000, 9/2, 33333333, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 81/2, 81/2,27/2,27/2, 54}, + {"K6-2+/475", CPU_K6_2P, 475000000, 5, 31666667, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 171/4,171/4, 15, 15, 57}, + {"K6-2+/500", CPU_K6_2P, 500000000, 5, 33333333, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 45, 45, 15, 15, 60}, + {"K6-2+/533", CPU_K6_2P, 533333333, 11/2, 32323232, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 48, 48,33/2,33/2, 64}, + {"K6-2+/550", CPU_K6_2P, 550000000, 11/2, 32333333, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 99/2, 99/2,33/2,33/2, 66}, + {"K6-III/400", CPU_K6_3, 400000000, 4, 33333333, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48}, + {"K6-III/450", CPU_K6_3, 450000000, 9/2, 33333333, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 81/2, 81/2,27/2,27/2, 54}, + {"K6-III+/400", CPU_K6_3P, 400000000, 4, 33333333, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48}, + {"K6-III+/450", CPU_K6_3P, 450000000, 9/2, 33333333, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 81/2, 81/2,27/2,27/2, 54}, + {"K6-III+/475", CPU_K6_3P, 475000000, 5, 31666667, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 171/4,171/4, 15, 15, 57}, + {"K6-III+/500", CPU_K6_3P, 500000000, 5, 33333333, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 45, 45, 15, 15, 60}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; #ifdef DEV_BRANCH #ifdef USE_I686 CPU cpus_PentiumPro[] = { - /*Intel Pentium Pro and II Overdrive*/ - {"Pentium Pro 50", CPU_PENTIUMPRO, 50000000, 1, 25000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 4, 4, 3, 3, 6}, - {"Pentium Pro 60" , CPU_PENTIUMPRO, 60000000, 1, 30000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 7}, - {"Pentium Pro 66" , CPU_PENTIUMPRO, 66666666, 1, 33333333, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 8}, - {"Pentium Pro 75", CPU_PENTIUMPRO, 75000000, 2, 25000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9}, - {"Pentium Pro 150", CPU_PENTIUMPRO, 150000000, 3, 30000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, - {"Pentium Pro 166", CPU_PENTIUMPRO, 166666666, 3, 33333333, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, - {"Pentium Pro 180", CPU_PENTIUMPRO, 180000000, 3, 30000000, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 21}, - {"Pentium Pro 200", CPU_PENTIUMPRO, 200000000, 3, 33333333, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, - {"Pentium II Overdrive 50", CPU_PENTIUM2D, 50000000, 1, 25000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 4, 4, 3, 3, 6}, - {"Pentium II Overdrive 60", CPU_PENTIUM2D, 60000000, 1, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 7}, - {"Pentium II Overdrive 66", CPU_PENTIUM2D, 66666666, 1, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 8}, - {"Pentium II Overdrive 75", CPU_PENTIUM2D, 75000000, 2, 25000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9}, - {"Pentium II Overdrive 210", CPU_PENTIUM2D, 210000000, 4, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25}, - {"Pentium II Overdrive 233", CPU_PENTIUM2D, 233333333, 4, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, - {"Pentium II Overdrive 240", CPU_PENTIUM2D, 240000000, 4, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 29}, - {"Pentium II Overdrive 266", CPU_PENTIUM2D, 266666666, 4, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, - {"Pentium II Overdrive 270", CPU_PENTIUM2D, 270000000, 5, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 25,25,12,12, 33}, - {"Pentium II Overdrive 300/66", CPU_PENTIUM2D, 300000000, 5, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 25,25,12,12, 36}, - {"Pentium II Overdrive 300/60", CPU_PENTIUM2D, 300000000, 5, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36}, - {"Pentium II Overdrive 333", CPU_PENTIUM2D, 333333333, 5, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 40}, + /*Intel Pentium Pro*/ + {"Pentium Pro 50", CPU_PENTIUMPRO, 50000000, 1, 25000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 4, 4, 3, 3, 6}, + {"Pentium Pro 60" , CPU_PENTIUMPRO, 60000000, 1, 30000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 7}, + {"Pentium Pro 66" , CPU_PENTIUMPRO, 66666666, 1, 33333333, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 8}, + {"Pentium Pro 75", CPU_PENTIUMPRO, 75000000, 3/2, 25000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9}, + {"Pentium Pro 150", CPU_PENTIUMPRO, 150000000, 5/2, 30000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, + {"Pentium Pro 166", CPU_PENTIUMPRO, 166666666, 5/2, 33333333, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"Pentium Pro 180", CPU_PENTIUMPRO, 180000000, 3, 30000000, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 21}, + {"Pentium Pro 200", CPU_PENTIUMPRO, 200000000, 3, 33333333, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, + + /*Intel Pentium II OverDrive*/ + {"Pentium II Overdrive 50", CPU_PENTIUM2D, 50000000, 1, 25000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 4, 4, 3, 3, 6}, + {"Pentium II Overdrive 60", CPU_PENTIUM2D, 60000000, 1, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 7}, + {"Pentium II Overdrive 66", CPU_PENTIUM2D, 66666666, 1, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 8}, + {"Pentium II Overdrive 75", CPU_PENTIUM2D, 75000000, 3/2, 25000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9}, + {"Pentium II Overdrive 210", CPU_PENTIUM2D, 210000000, 7/2, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25}, + {"Pentium II Overdrive 233", CPU_PENTIUM2D, 233333333, 7/2, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, + {"Pentium II Overdrive 240", CPU_PENTIUM2D, 240000000, 4, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 29}, + {"Pentium II Overdrive 266", CPU_PENTIUM2D, 266666666, 4, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, + {"Pentium II Overdrive 270", CPU_PENTIUM2D, 270000000, 9/2, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 25,25,12,12, 33}, + {"Pentium II Overdrive 300/66", CPU_PENTIUM2D, 300000000, 9/2, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 25,25,12,12, 36}, + {"Pentium II Overdrive 300/60", CPU_PENTIUM2D, 300000000, 5, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36}, + {"Pentium II Overdrive 333", CPU_PENTIUM2D, 333333333, 5, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 40}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; #endif diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 5332b6fd6..e9c4227be 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -36,15 +36,19 @@ #if defined(DEV_BRANCH) && defined(USE_AMD_K) #define MACHINE_CPUS_PENTIUM_S5 {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}} #if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) -#define MACHINE_CPUS_PENTIUM_S7 {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}} +#define MACHINE_CPUS_PENTIUM_S73V {{"Intel", cpus_Pentium3V}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"Cyrix", cpus_6x863V},{"", NULL}} +#define MACHINE_CPUS_PENTIUM_S7 {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}} #else +#define MACHINE_CPUS_PENTIUM_S73V {{ "Intel", cpus_Pentium3V}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}} #define MACHINE_CPUS_PENTIUM_S7 {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"", NULL}, {"", NULL}} #endif #else #define MACHINE_CPUS_PENTIUM_S5 {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}} #if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) +#define MACHINE_CPUS_PENTIUM_S73V {{"Intel", cpus_Pentium3V}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x863V}, {"", NULL}, {"", NULL}} #define MACHINE_CPUS_PENTIUM_S7 {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}} #else +#define MACHINE_CPUS_PENTIUM_S73V {{"Intel", cpus_Pentium3V}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}} #define MACHINE_CPUS_PENTIUM_S7 {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}} #endif #endif @@ -144,15 +148,15 @@ const machine_t machines[] = { { "[386DX MCA] IBM PS/2 model 70 (type 3)", "ibmps2_m70_type3", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"IBM", cpus_IBM486BL}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 2, 16, 2, 63, machine_ps2_model_70_type3_init, NULL }, { "[386DX MCA] IBM PS/2 model 80", "ibmps2_m80", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"IBM", cpus_IBM486BL}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 1, 12, 1, 63, machine_ps2_model_80_init, NULL }, - { "[486 ISA] AMI 486 clone", "ami486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_ami_init, NULL }, + { "[486 ISA] AMI 486 clone", "ami486", {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_ami_init, NULL }, { "[486 ISA] AMI ALi 1429", "ali1429", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_ali1429_init, NULL }, { "[486 ISA] AMI SiS 471", "ami471", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_ami471_init, NULL }, { "[486 ISA] AMI WinBIOS 486", "win486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_winbios1429_init, NULL }, { "[486 ISA] AMI WinBIOS SiS 471", "win471", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_win471_init, NULL }, - { "[486 ISA] Award 486 clone", "award486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_init, NULL }, + { "[486 ISA] Award 486 clone", "award486", {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_init, NULL }, { "[486 ISA] DTK PKM-0038S E-2", "dtk486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_dtk486_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_PS1M2133) - { "[486 ISA] IBM PS/1 model 2133", "ibmps1_2133", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_NONMI, 1, 64, 1, 127, machine_ps1_m2133_init, NULL }, + { "[486 ISA] IBM PS/1 model 2133", "ibmps1_2133", {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_NONMI, 1, 64, 1, 127, machine_ps1_m2133_init, NULL }, #endif #if defined(DEV_BRANCH) && defined(USE_MR495) { "[486 ISA] MR 486 clone", "mr486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_mr_init, NULL }, @@ -161,7 +165,7 @@ const machine_t machines[] = { { "[486 ISA] Phoenix SiS 471", "px471", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 128, 1, 127, machine_at_px471_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_PS2M70T4) - { "[486 MCA] IBM PS/2 model 70 (type 4)", "ibmps2_m70_type4", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 2, 16, 2, 63, machine_ps2_model_70_type4_init, NULL }, + { "[486 MCA] IBM PS/2 model 70 (type 4)", "ibmps2_m70_type4", {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 2, 16, 2, 63, machine_ps2_model_70_type4_init, NULL }, #endif { "[486 PCI] Intel Classic/PCI", "alfredo", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_alfredo_init, NULL }, @@ -183,18 +187,18 @@ const machine_t machines[] = { { "[Socket 5 FX] PC Partner MB500N", "mb500n", MACHINE_CPUS_PENTIUM_S5, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_mb500n_init, NULL }, { "[Socket 5 FX] President Award 430FX PCI","president", MACHINE_CPUS_PENTIUM_S5, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_president_init, NULL }, - { "[Socket 7 FX] Intel Advanced/ATX", "thor", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_thor_init, NULL }, + { "[Socket 7 FX] Intel Advanced/ATX", "thor", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_thor_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_MRTHOR) - { "[Socket 7 FX] MR Intel Advanced/ATX", "mrthor", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_mrthor_init, NULL }, + { "[Socket 7 FX] MR Intel Advanced/ATX", "mrthor", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_mrthor_init, NULL }, #endif - { "[Socket 7 FX] Intel Advanced/EV", "endeavor", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 8, 128, 8, 127, machine_at_endeavor_init, at_endeavor_get_device }, - { "[Socket 7 FX] Packard Bell PB640", "pb640", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 8, 128, 8, 127, machine_at_pb640_init, at_pb640_get_device }, + { "[Socket 7 FX] Intel Advanced/EV", "endeavor", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 8, 128, 8, 127, machine_at_endeavor_init, at_endeavor_get_device }, + { "[Socket 7 FX] Packard Bell PB640", "pb640", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 8, 128, 8, 127, machine_at_pb640_init, at_pb640_get_device }, - { "[Socket 7 HX] Acer M3a", "acerm3a", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 192, 8, 127, machine_at_acerm3a_init, NULL }, + { "[Socket 7 HX] Acer M3a", "acerm3a", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 192, 8, 127, machine_at_acerm3a_init, NULL }, { "[Socket 7 HX] Acer V35n", "acerv35n", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 192, 8, 127, machine_at_acerv35n_init, NULL }, - { "[Socket 7 HX] AOpen AP53", "ap53", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 127, machine_at_ap53_init, NULL }, + { "[Socket 7 HX] AOpen AP53", "ap53", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 127, machine_at_ap53_init, NULL }, { "[Socket 7 HX] ASUS P/I-P55T2P4", "p55t2p4", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 256, 8, 127, machine_at_p55t2p4_init, NULL }, - { "[Socket 7 HX] SuperMicro Super P55T2S", "p55t2s", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 127, machine_at_p55t2s_init, NULL }, + { "[Socket 7 HX] SuperMicro Super P55T2S", "p55t2s", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 127, machine_at_p55t2s_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_TC430HX) { "[Socket 7 HX] TC430HX", "tc430hx", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_tc430hx_init, NULL }, #endif diff --git a/src/machine/machine_table_new.c b/src/machine/machine_table_new.c index d96604f8c..a3e5e6619 100644 --- a/src/machine/machine_table_new.c +++ b/src/machine/machine_table_new.c @@ -33,8 +33,9 @@ #include "machine.h" -#define MACHINE_CPUS_PENTIUM_S5 {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}} -#define MACHINE_CPUS_PENTIUM_S7 {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}} +#define MACHINE_CPUS_PENTIUM_S5 {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}} +#define MACHINE_CPUS_PENTIUM_S73V {{ "Intel", cpus_Pentium3V}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"Cyrix", cpus_6x863V},{"", NULL}} +#define MACHINE_CPUS_PENTIUM_S7 {{ "Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}} const machine_t machines[] = { { "[8088] AMI XT clone", "amixt", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA, 64, 640, 64, 0, machine_xt_amixt_init, NULL }, @@ -131,15 +132,15 @@ const machine_t machines[] = { { "[386DX MCA] IBM PS/2 model 70 (type 3)", "ibmps2_m70_type3", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"IBM", cpus_IBM486BL}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 2, 16, 2, 63, machine_ps2_model_70_type3_init, NULL }, { "[386DX MCA] IBM PS/2 model 80", "ibmps2_m80", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"IBM", cpus_IBM486BL}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 1, 12, 1, 63, machine_ps2_model_80_init, NULL }, - { "[486 ISA] AMI 486 clone", "ami486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_ami_init, NULL }, + { "[486 ISA] AMI 486 clone", "ami486", {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_ami_init, NULL }, { "[486 ISA] AMI ALi 1429", "ali1429", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_ali1429_init, NULL }, { "[486 ISA] AMI SiS 471", "ami471", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_ami471_init, NULL }, { "[486 ISA] AMI WinBIOS 486", "win486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_winbios1429_init, NULL }, { "[486 ISA] AMI WinBIOS SiS 471", "win471", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_win471_init, NULL }, - { "[486 ISA] Award 486 clone", "award486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_init, NULL }, + { "[486 ISA] Award 486 clone", "award486", {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_init, NULL }, { "[486 ISA] DTK PKM-0038S E-2", "dtk486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_dtk486_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_PS1M2133) - { "[486 ISA] IBM PS/1 model 2133", "ibmps1_2133", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_NONMI, 1, 64, 1, 127, machine_ps1_m2133_init, NULL }, + { "[486 ISA] IBM PS/1 model 2133", "ibmps1_2133", {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_NONMI, 1, 64, 1, 127, machine_ps1_m2133_init, NULL }, #endif #if defined(DEV_BRANCH) && defined(USE_MR495) { "[486 ISA] MR 486 clone", "mr486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_mr_init, NULL }, @@ -148,7 +149,7 @@ const machine_t machines[] = { { "[486 ISA] Phoenix SiS 471", "px471", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 128, 1, 127, machine_at_px471_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_PS2M70T4) - { "[486 MCA] IBM PS/2 model 70 (type 4)", "ibmps2_m70_type4", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 2, 16, 2, 63, machine_ps2_model_70_type4_init, NULL }, + { "[486 MCA] IBM PS/2 model 70 (type 4)", "ibmps2_m70_type4", {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 2, 16, 2, 63, machine_ps2_model_70_type4_init, NULL }, #endif { "[486 PCI] Intel Classic/PCI", "alfredo", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_alfredo_init, NULL }, @@ -170,18 +171,18 @@ const machine_t machines[] = { { "[Socket 5 FX] PC Partner MB500N", "mb500n", MACHINE_CPUS_PENTIUM_S5, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_mb500n_init, NULL }, { "[Socket 5 FX] President Award 430FX PCI","president", MACHINE_CPUS_PENTIUM_S5, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_president_init, NULL }, - { "[Socket 7 FX] Intel Advanced/ATX", "thor", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_thor_init, NULL }, + { "[Socket 7 FX] Intel Advanced/ATX", "thor", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_thor_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_MRTHOR) - { "[Socket 7 FX] MR Intel Advanced/ATX", "mrthor", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_mrthor_init, NULL }, + { "[Socket 7 FX] MR Intel Advanced/ATX", "mrthor", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_mrthor_init, NULL }, #endif - { "[Socket 7 FX] Intel Advanced/EV", "endeavor", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 8, 128, 8, 127, machine_at_endeavor_init, at_endeavor_get_device }, - { "[Socket 7 FX] Packard Bell PB640", "pb640", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 8, 128, 8, 127, machine_at_pb640_init, at_pb640_get_device }, + { "[Socket 7 FX] Intel Advanced/EV", "endeavor", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 8, 128, 8, 127, machine_at_endeavor_init, at_endeavor_get_device }, + { "[Socket 7 FX] Packard Bell PB640", "pb640", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 8, 128, 8, 127, machine_at_pb640_init, at_pb640_get_device }, - { "[Socket 7 HX] Acer M3a", "acerm3a", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 192, 8, 127, machine_at_acerm3a_init, NULL }, + { "[Socket 7 HX] Acer M3a", "acerm3a", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 192, 8, 127, machine_at_acerm3a_init, NULL }, { "[Socket 7 HX] Acer V35n", "acerv35n", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 192, 8, 127, machine_at_acerv35n_init, NULL }, - { "[Socket 7 HX] AOpen AP53", "ap53", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 127, machine_at_ap53_init, NULL }, + { "[Socket 7 HX] AOpen AP53", "ap53", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 127, machine_at_ap53_init, NULL }, { "[Socket 7 HX] ASUS P/I-P55T2P4", "p55t2p4", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 256, 8, 127, machine_at_p55t2p4_init, NULL }, - { "[Socket 7 HX] SuperMicro Super P55T2S", "p55t2s", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 127, machine_at_p55t2s_init, NULL }, + { "[Socket 7 HX] SuperMicro Super P55T2S", "p55t2s", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 127, machine_at_p55t2s_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_TC430HX) { "[Socket 7 HX] TC430HX", "tc430hx", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_tc430hx_init, NULL }, #endif From 43816991b613f491f027364daa644deb117b8818 Mon Sep 17 00:00:00 2001 From: nerd73 Date: Sun, 5 Jan 2020 15:56:52 -0700 Subject: [PATCH 026/177] Patch for the revamp - Delinked CPU bus speed from PCI speed - Changed the CPU multiplier from an integer to a double - Changed the CPU cache/mem cycles on the K6-2s from fractions to integers - Fixed cache/mem cycles on the faster Cyrix MIIs - Fixed some spacing issues that I created --- src/cpu/cpu.c | 3 -- src/cpu/cpu.h | 24 ++++++++-------- src/cpu/cpu_table.c | 10 +++---- src/cpu_new/cpu.c | 3 -- src/cpu_new/cpu.h | 24 ++++++++-------- src/cpu_new/cpu_table.c | 56 ++++++++++++++++++------------------- src/machine/machine_table.c | 20 ++++++------- 7 files changed, 67 insertions(+), 73 deletions(-) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index dd5c7b40b..8d2df9bbd 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -270,9 +270,6 @@ cpu_set(void) cpu_16bitbus = (cpu_s->cpu_type == CPU_286 || cpu_s->cpu_type == CPU_386SX || cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_IBM386SLC || cpu_s->cpu_type == CPU_IBM486SLC ); if (cpu_s->multi) { - if (cpu_s->pci_speed) - cpu_busspeed = cpu_s->pci_speed; - else cpu_busspeed = cpu_s->rspeed / cpu_s->multi; } cpu_multi = cpu_s->multi; diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 52b5fb41f..ef800c070 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -82,18 +82,18 @@ typedef struct { - const char *name; - int cpu_type; - int rspeed; - int multi; - int pci_speed; - uint32_t edx_reset; - uint32_t cpuid_model; - uint16_t cyrix_id; - uint8_t cpu_flags; - int8_t mem_read_cycles, mem_write_cycles; - int8_t cache_read_cycles, cache_write_cycles; - int8_t atclk_div; + const char *name; + int cpu_type; + int rspeed; + double multi; + int pci_speed; + uint32_t edx_reset; + uint32_t cpuid_model; + uint16_t cyrix_id; + uint8_t cpu_flags; + int8_t mem_read_cycles, mem_write_cycles; + int8_t cache_read_cycles, cache_write_cycles; + int8_t atclk_div; } CPU; extern CPU cpus_8088[]; diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index d097afc24..a0e77f414 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -361,12 +361,12 @@ CPU cpus_6x86[] = { {"Cx6x86L/PR200+", CPU_Cx6x86L, 150000000, 2, 37500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18}, /*Cyrix 6x86MX/MII*/ - {"Cx6x86MX/PR166", CPU_Cx6x86MX, 133333333, 2, 33333333, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, - {"Cx6x86MX/PR200", CPU_Cx6x86MX, 166666666, 5/2, 33333333, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"Cx6x86MX/PR166", CPU_Cx6x86MX, 133333333, 2, 33333333, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, + {"Cx6x86MX/PR200", CPU_Cx6x86MX, 166666666, 5/2, 33333333, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, {"Cx6x86MX/PR233", CPU_Cx6x86MX, 187500000, 5/2, 37500000, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 45/2}, - {"Cx6x86MX/PR266", CPU_Cx6x86MX, 208333333, 5/2, 41666666, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25}, - {"MII/PR300", CPU_Cx6x86MX, 233333333, 7/2, 33333333, 0x601, 0x601, 0x0852, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21, 7, 7, 28}, - {"MII/PR333", CPU_Cx6x86MX, 250000000, 3, 41666666, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 20,20, 9, 9, 30}, + {"Cx6x86MX/PR266", CPU_Cx6x86MX, 208333333, 5/2, 41666666, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25}, + {"MII/PR300", CPU_Cx6x86MX, 233333333, 7/2, 33333333, 0x601, 0x601, 0x0852, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,11,11, 28}, + {"MII/PR333", CPU_Cx6x86MX, 250000000, 3, 41666666, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 23,23, 9, 9, 30}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; #endif diff --git a/src/cpu_new/cpu.c b/src/cpu_new/cpu.c index 16edc0af7..be3490c17 100644 --- a/src/cpu_new/cpu.c +++ b/src/cpu_new/cpu.c @@ -268,9 +268,6 @@ cpu_set(void) cpu_iscyrix = (cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_486DLC || cpu_s->cpu_type == CPU_Cx486S || cpu_s->cpu_type == CPU_Cx486DX || cpu_s->cpu_type == CPU_Cx5x86 || cpu_s->cpu_type == CPU_Cx6x86 || cpu_s->cpu_type == CPU_Cx6x86MX || cpu_s->cpu_type == CPU_Cx6x86L || cpu_s->cpu_type == CPU_CxGX1); cpu_16bitbus = (cpu_s->cpu_type == CPU_286 || cpu_s->cpu_type == CPU_386SX || cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_IBM386SLC || cpu_s->cpu_type == CPU_IBM486SLC ); if (cpu_s->multi) { - if (cpu_s->pci_speed) - cpu_busspeed = cpu_s->pci_speed; - else cpu_busspeed = cpu_s->rspeed / cpu_s->multi; } cpu_multi = cpu_s->multi; diff --git a/src/cpu_new/cpu.h b/src/cpu_new/cpu.h index 4de1f428b..1a3f37fc3 100644 --- a/src/cpu_new/cpu.h +++ b/src/cpu_new/cpu.h @@ -70,18 +70,18 @@ typedef struct { - const char *name; - int cpu_type; - int rspeed; - int multi; - int pci_speed; - uint32_t edx_reset; - uint32_t cpuid_model; - uint16_t cyrix_id; - uint8_t cpu_flags; - int8_t mem_read_cycles, mem_write_cycles; - int8_t cache_read_cycles, cache_write_cycles; - int8_t atclk_div; + const char*name; + int cpu_type; + int rspeed; + double multi; + int pci_speed; + uint32_t edx_reset; + uint32_t cpuid_model; + uint16_t cyrix_id; + uint8_t cpu_flags; + int8_t mem_read_cycles, mem_write_cycles; + int8_t cache_read_cycles, cache_write_cycles; + int8_t atclk_div; } CPU; extern CPU cpus_8088[]; diff --git a/src/cpu_new/cpu_table.c b/src/cpu_new/cpu_table.c index 93f65c107..b6795074c 100644 --- a/src/cpu_new/cpu_table.c +++ b/src/cpu_new/cpu_table.c @@ -362,12 +362,12 @@ CPU cpus_6x86[] = { {"Cx6x86L/PR200+", CPU_Cx6x86L, 150000000, 2, 37500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18}, /*Cyrix 6x86MX/MII*/ - {"Cx6x86MX/PR166", CPU_Cx6x86MX, 133333333, 2, 33333333, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, - {"Cx6x86MX/PR200", CPU_Cx6x86MX, 166666666, 5/2, 33333333, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"Cx6x86MX/PR166", CPU_Cx6x86MX, 133333333, 2, 33333333, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, + {"Cx6x86MX/PR200", CPU_Cx6x86MX, 166666666, 5/2, 33333333, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, {"Cx6x86MX/PR233", CPU_Cx6x86MX, 187500000, 5/2, 37500000, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 45/2}, - {"Cx6x86MX/PR266", CPU_Cx6x86MX, 208333333, 5/2, 41666666, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25}, - {"MII/PR300", CPU_Cx6x86MX, 233333333, 7/2, 33333333, 0x601, 0x601, 0x0852, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21, 7, 7, 28}, - {"MII/PR333", CPU_Cx6x86MX, 250000000, 3, 41666666, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 20,20, 9, 9, 30}, + {"Cx6x86MX/PR266", CPU_Cx6x86MX, 208333333, 5/2, 41666666, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25}, + {"MII/PR300", CPU_Cx6x86MX, 233333333, 7/2, 33333333, 0x601, 0x601, 0x0852, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,11,11, 28}, + {"MII/PR333", CPU_Cx6x86MX, 250000000, 3, 41666666, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 23,23, 9, 9, 30}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; @@ -387,15 +387,15 @@ CPU cpus_6x86[] = { {"Cx6x86L/PR200+", CPU_Cx6x86L, 150000000, 2, 37500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18}, /*Cyrix 6x86MX/MII*/ - {"Cx6x86MX/PR166", CPU_Cx6x86MX, 133333333, 2, 33333333, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, - {"Cx6x86MX/PR200", CPU_Cx6x86MX, 166666666, 5/2, 33333333, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"Cx6x86MX/PR166", CPU_Cx6x86MX, 133333333, 2, 33333333, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, + {"Cx6x86MX/PR200", CPU_Cx6x86MX, 166666666, 5/2, 33333333, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, {"Cx6x86MX/PR233", CPU_Cx6x86MX, 187500000, 5/2, 37500000, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 45/2}, - {"Cx6x86MX/PR266", CPU_Cx6x86MX, 208333333, 5/2, 41666666, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25}, - {"MII/PR300", CPU_Cx6x86MX, 233333333, 7/2, 33333333, 0x601, 0x601, 0x0852, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21, 7, 7, 28}, - {"MII/PR333", CPU_Cx6x86MX, 250000000, 3, 41666666, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 20,20, 9, 9, 30}, - {"MII/PR366", CPU_Cx6x86MX, 250000000, 5/2, 33333333, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 20,20, 9, 9, 30}, - {"MII/PR400", CPU_Cx6x86MX, 285000000, 3, 31666666, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 20,20, 9, 9, 30}, - {"MII/PR433", CPU_Cx6x86MX, 300000000, 3, 33333333, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 20,20, 9, 9, 30}, + {"Cx6x86MX/PR266", CPU_Cx6x86MX, 208333333, 5/2, 41666666, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25}, + {"MII/PR300", CPU_Cx6x86MX, 233333333, 7/2, 33333333, 0x601, 0x601, 0x0852, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,11,11, 28}, + {"MII/PR333", CPU_Cx6x86MX, 250000000, 3, 41666666, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 23,23, 9, 9, 30}, + {"MII/PR366", CPU_Cx6x86MX, 250000000, 5/2, 33333333, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 23,23, 7, 7, 30}, + {"MII/PR400", CPU_Cx6x86MX, 285000000, 3, 31666666, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 9, 9, 34}, + {"MII/PR433", CPU_Cx6x86MX, 300000000, 3, 33333333, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 9, 9, 36}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; @@ -589,7 +589,7 @@ CPU cpus_K56[] = { {"K6-2/233", CPU_K6_2, 233333333, 7/2, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21, 10, 10, 28}, {"K6-2/266", CPU_K6_2, 266666666, 4, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24, 12, 12, 32}, {"K6-2/300 AFR-66", CPU_K6_2, 300000000, 9/2, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 13, 13, 36}, - {"K6-2/366", CPU_K6_2, 366666666, 11/2, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 33,33,33/2,33/2, 44}, + {"K6-2/366", CPU_K6_2, 366666666, 11/2, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 33,33, 17, 17, 44}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; @@ -620,28 +620,28 @@ CPU cpus_K56_SS7[] = { {"K6-2/233", CPU_K6_2, 233333333, 7/2, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21, 21, 10, 10, 28}, {"K6-2/266", CPU_K6_2, 266666666, 4, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24, 24, 12, 12, 32}, {"K6-2/300", CPU_K6_2, 300000000, 3, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27, 27, 9, 9, 36}, - {"K6-2/333", CPU_K6_2, 332500000, 7/2, 31666667, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 30, 30,21/2,21/2, 40}, - {"K6-2/350", CPU_K6_2, 350000000, 7/2, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 63/2, 63/2,21/2,21/2, 42}, - {"K6-2/366", CPU_K6_2, 366666666, 11/2, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 33, 33,33/2,33/2, 44}, + {"K6-2/333", CPU_K6_2, 332500000, 7/2, 31666667, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 30, 30, 11, 11, 40}, + {"K6-2/350", CPU_K6_2, 350000000, 7/2, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 32, 32, 11, 11, 42}, + {"K6-2/366", CPU_K6_2, 366666666, 11/2, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 33, 33, 17, 17, 44}, {"K6-2/380", CPU_K6_2, 380000000, 4, 31666667, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 34, 34, 12, 12, 46}, {"K6-2/400", CPU_K6_2, 400000000, 4, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48}, - {"K6-2/450", CPU_K6_2, 450000000, 9/2, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 81/2, 81/2,27/2,27/2, 54}, - {"K6-2/475", CPU_K6_2, 475000000, 5, 31666667, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 171/4,171/4, 15, 15, 57}, + {"K6-2/450", CPU_K6_2, 450000000, 9/2, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41, 41, 14, 14, 54}, + {"K6-2/475", CPU_K6_2, 475000000, 5, 31666667, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 43, 43, 15, 15, 57}, {"K6-2/500", CPU_K6_2, 500000000, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 45, 45, 15, 15, 60}, - {"K6-2/533", CPU_K6_2, 533333333, 11/2, 32323232, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 48, 48,33/2,33/2, 64}, - {"K6-2/550", CPU_K6_2, 550000000, 11/2, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 99/2, 99/2,33/2,33/2, 66}, + {"K6-2/533", CPU_K6_2, 533333333, 11/2, 32323232, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 48, 48, 17, 17, 64}, + {"K6-2/550", CPU_K6_2, 550000000, 11/2, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 50, 50, 17, 17, 66}, /*AMD K6-2+/K6-3/K6-3+ (Super Socket 7)*/ - {"K6-2+/450", CPU_K6_2P, 450000000, 9/2, 33333333, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 81/2, 81/2,27/2,27/2, 54}, - {"K6-2+/475", CPU_K6_2P, 475000000, 5, 31666667, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 171/4,171/4, 15, 15, 57}, + {"K6-2+/450", CPU_K6_2P, 450000000, 9/2, 33333333, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41, 41, 14, 14, 54}, + {"K6-2+/475", CPU_K6_2P, 475000000, 5, 31666667, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 43, 43, 15, 15, 57}, {"K6-2+/500", CPU_K6_2P, 500000000, 5, 33333333, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 45, 45, 15, 15, 60}, - {"K6-2+/533", CPU_K6_2P, 533333333, 11/2, 32323232, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 48, 48,33/2,33/2, 64}, - {"K6-2+/550", CPU_K6_2P, 550000000, 11/2, 32333333, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 99/2, 99/2,33/2,33/2, 66}, + {"K6-2+/533", CPU_K6_2P, 533333333, 11/2, 32323232, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 48, 48, 17, 17, 64}, + {"K6-2+/550", CPU_K6_2P, 550000000, 11/2, 32333333, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 50, 50, 17, 17, 66}, {"K6-III/400", CPU_K6_3, 400000000, 4, 33333333, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48}, - {"K6-III/450", CPU_K6_3, 450000000, 9/2, 33333333, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 81/2, 81/2,27/2,27/2, 54}, + {"K6-III/450", CPU_K6_3, 450000000, 9/2, 33333333, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41, 41, 14, 14, 54}, {"K6-III+/400", CPU_K6_3P, 400000000, 4, 33333333, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48}, - {"K6-III+/450", CPU_K6_3P, 450000000, 9/2, 33333333, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 81/2, 81/2,27/2,27/2, 54}, - {"K6-III+/475", CPU_K6_3P, 475000000, 5, 31666667, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 171/4,171/4, 15, 15, 57}, + {"K6-III+/450", CPU_K6_3P, 450000000, 9/2, 33333333, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41, 41, 14, 14, 54}, + {"K6-III+/475", CPU_K6_3P, 475000000, 5, 31666667, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 43, 43, 15, 15, 57}, {"K6-III+/500", CPU_K6_3P, 500000000, 5, 33333333, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 45, 45, 15, 15, 60}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index e9c4227be..893b37e7a 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -34,22 +34,22 @@ #if defined(DEV_BRANCH) && defined(USE_AMD_K) -#define MACHINE_CPUS_PENTIUM_S5 {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}} +#define MACHINE_CPUS_PENTIUM_S5 {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}} #if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) -#define MACHINE_CPUS_PENTIUM_S73V {{"Intel", cpus_Pentium3V}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"Cyrix", cpus_6x863V},{"", NULL}} -#define MACHINE_CPUS_PENTIUM_S7 {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}} +#define MACHINE_CPUS_PENTIUM_S73V {{"Intel", cpus_Pentium3V}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"Cyrix", cpus_6x863V},{"", NULL}} +#define MACHINE_CPUS_PENTIUM_S7 {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}} #else -#define MACHINE_CPUS_PENTIUM_S73V {{ "Intel", cpus_Pentium3V}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}} -#define MACHINE_CPUS_PENTIUM_S7 {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"", NULL}, {"", NULL}} +#define MACHINE_CPUS_PENTIUM_S73V {{ "Intel", cpus_Pentium3V}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}} +#define MACHINE_CPUS_PENTIUM_S7 {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"", NULL}, {"", NULL}} #endif #else -#define MACHINE_CPUS_PENTIUM_S5 {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}} +#define MACHINE_CPUS_PENTIUM_S5 {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}} #if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) -#define MACHINE_CPUS_PENTIUM_S73V {{"Intel", cpus_Pentium3V}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x863V}, {"", NULL}, {"", NULL}} -#define MACHINE_CPUS_PENTIUM_S7 {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}} +#define MACHINE_CPUS_PENTIUM_S73V {{"Intel", cpus_Pentium3V}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x863V}, {"", NULL}, {"", NULL}} +#define MACHINE_CPUS_PENTIUM_S7 {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}} #else -#define MACHINE_CPUS_PENTIUM_S73V {{"Intel", cpus_Pentium3V}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}} -#define MACHINE_CPUS_PENTIUM_S7 {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}} +#define MACHINE_CPUS_PENTIUM_S73V {{"Intel", cpus_Pentium3V}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}} +#define MACHINE_CPUS_PENTIUM_S7 {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}} #endif #endif From dc7164e1468efc91a5ceffae1c9def79031be3ba Mon Sep 17 00:00:00 2001 From: nerd73 Date: Tue, 7 Jan 2020 15:10:26 -0700 Subject: [PATCH 027/177] Final revamp patch - Added the proper names for the AMI 386DX/486 clone and the AMI ALi 1429. - Moved AMI ALi 1429 to Socket 1 because of the identified motherboard not supporting the Pentium OverDrive --- src/machine/machine_table_new.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/machine/machine_table_new.c b/src/machine/machine_table_new.c index a3e5e6619..a46e7175c 100644 --- a/src/machine/machine_table_new.c +++ b/src/machine/machine_table_new.c @@ -120,7 +120,7 @@ const machine_t machines[] = { { "[386SX MCA] IBM PS/2 model 55SX", "ibmps2_m55sx", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"IBM", cpus_IBM486SLC}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 1, 8, 1, 63, machine_ps2_model_55sx_init, NULL }, - { "[386DX ISA] AMI 386DX clone", "ami386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_ami_init, NULL }, + { "[386DX ISA] Dataexpert SX495 (386DX)", "ami386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_ami_init, NULL }, { "[386DX ISA] Award 386DX clone", "award386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_MR495) { "[386DX ISA] MR 386DX clone", "mr386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_mr_init, NULL }, @@ -132,8 +132,8 @@ const machine_t machines[] = { { "[386DX MCA] IBM PS/2 model 70 (type 3)", "ibmps2_m70_type3", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"IBM", cpus_IBM486BL}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 2, 16, 2, 63, machine_ps2_model_70_type3_init, NULL }, { "[386DX MCA] IBM PS/2 model 80", "ibmps2_m80", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"IBM", cpus_IBM486BL}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 1, 12, 1, 63, machine_ps2_model_80_init, NULL }, - { "[486 ISA] AMI 486 clone", "ami486", {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_ami_init, NULL }, - { "[486 ISA] AMI ALi 1429", "ali1429", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_ali1429_init, NULL }, + { "[486 ISA] Dataexpert SX495 (486)", "ami486", {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_ami_init, NULL }, + { "[486 ISA] Olystar LIL1429", "ali1429", {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_ali1429_init, NULL }, { "[486 ISA] AMI SiS 471", "ami471", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_ami471_init, NULL }, { "[486 ISA] AMI WinBIOS 486", "win486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_winbios1429_init, NULL }, { "[486 ISA] AMI WinBIOS SiS 471", "win471", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_win471_init, NULL }, From c11ffd5222247d3978ddd1cf573c7c100baa1c02 Mon Sep 17 00:00:00 2001 From: Daniel Gurney Date: Wed, 8 Jan 2020 17:42:38 +0200 Subject: [PATCH 028/177] Various readme changes - Mention Discord in build instructions - Technically speaking dev builds are optimized, but not for maximum performance. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 772872305..114a9073f 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ guide: 9. Enjoy using and testing the emulator! :) If you encounter issues at any step or have additional questions, please join -the IRC channel and wait patiently for someone to help you. +the IRC channel or the appropriate channel on our Discord server and wait patiently for someone to help you. Nightly builds -------------- @@ -83,7 +83,7 @@ Jenkins instance. optimized for every modern Intel and AMD processor architecture, which might improve the emulator's performance in certain scenarios. * **Experimental (Dev)** builds are similar to regular builds but are compiled - with certain unfinished features enabled. These builds are not optimized. + with certain unfinished features enabled. These builds are not optimized for maximum performance. Donations --------- From bb4e4e10c3875185062d47ad4a3ff48d18e7aa1b Mon Sep 17 00:00:00 2001 From: TC1995 Date: Wed, 8 Jan 2020 17:11:13 +0100 Subject: [PATCH 029/177] Added Gravis Ultrasound MIDI Input. --- src/sound/snd_gus.c | 287 +++++++++++++++++++++++++++++--------------- 1 file changed, 188 insertions(+), 99 deletions(-) diff --git a/src/sound/snd_gus.c b/src/sound/snd_gus.c index 46bd3408d..05840a7f6 100644 --- a/src/sound/snd_gus.c +++ b/src/sound/snd_gus.c @@ -13,6 +13,7 @@ #include "../timer.h" #include "../device.h" #include "sound.h" +#include "midi.h" #include "snd_gus.h" @@ -68,9 +69,9 @@ typedef struct gus_t uint8_t ad_status, ad_data; uint8_t ad_timer_ctrl; - uint8_t midi_ctrl, midi_status; - uint8_t midi_data; - int midi_loopback; + uint8_t uart_queue[64]; + int uart_pos, uart_used; + int uart_in, uart_out, sysex; uint8_t gp1, gp2; uint16_t gp1_addr, gp2_addr; @@ -79,7 +80,6 @@ typedef struct gus_t } gus_t; static int gus_irqs[8] = {-1, 2, 5, 3, 7, 11, 12, 15}; -static int gus_irqs_midi[8] = {-1, 2, 5, 3, 7, 11, 12, 15}; static int gus_dmas[8] = {-1, 1, 3, 5, 6, 7, -1, -1}; int gusfreqs[]= @@ -144,68 +144,45 @@ enum GUS_TIMER_CTRL_AUTO = 0x01 }; -void gus_midi_update_int_status(gus_t *gus) -{ - gus->midi_status &= ~MIDI_INT_MASTER; - if ((gus->midi_ctrl & MIDI_CTRL_TRANSMIT_MASK) == MIDI_CTRL_TRANSMIT && (gus->midi_status & MIDI_INT_TRANSMIT)) - { - gus->midi_status |= MIDI_INT_MASTER; - gus->irqstatus |= GUS_INT_MIDI_TRANSMIT; - } - else - gus->irqstatus &= ~GUS_INT_MIDI_TRANSMIT; - - if ((gus->midi_ctrl & MIDI_CTRL_RECEIVE) && (gus->midi_status & MIDI_INT_RECEIVE)) - { - gus->midi_status |= MIDI_INT_MASTER; - gus->irqstatus |= GUS_INT_MIDI_RECEIVE; - } - else - gus->irqstatus &= ~GUS_INT_MIDI_RECEIVE; - if ((gus->midi_status & MIDI_INT_MASTER) && (gus->irq_midi != -1)) - { - picint(1 << gus->irq_midi); - } -} - void writegus(uint16_t addr, uint8_t val, void *p) { gus_t *gus = (gus_t *)p; int c, d; int old; - if (gus->latch_enable && addr != 0x24b) - gus->latch_enable = 0; switch (addr) { case 0x340: /*MIDI control*/ - old = gus->midi_ctrl; - gus->midi_ctrl = val; - - if ((val & 3) == 3) - gus->midi_status = 0; - else if ((old & 3) == 3) - { - gus->midi_status |= MIDI_INT_TRANSMIT; - } - gus_midi_update_int_status(gus); + gus->uart_out = 1; + if (val == 3 || !val) { + gus->uart_in = 0; + gus->irqstatus &= ~0x03; + gus->uart_used = 0; + return; + } + + if (val & 0x20) { + gus->irqstatus |= 0x01; + } else { + gus->irqstatus &= ~0x01; + } + + if (val & 0x80) + gus->uart_in = 1; + else + gus->uart_in = 0; break; - case 0x341: /*MIDI data*/ - if (gus->midi_loopback) - { - gus->midi_status |= MIDI_INT_RECEIVE; - gus->midi_data = val; + if (gus->uart_out) { + midi_raw_out_byte(val); + picint(1 << gus->irq_midi); } - else - gus->midi_status |= MIDI_INT_TRANSMIT; break; - case 0x342: /*Voice select*/ - gus->voice=val&31; + gus->voice = val & 31; break; case 0x343: /*Global select*/ - gus->global=val; + gus->global = val; break; case 0x344: /*Global low*/ switch (gus->global) @@ -231,11 +208,11 @@ void writegus(uint16_t addr, uint8_t val, void *p) gus->end[gus->voice]=(gus->end[gus->voice]&0x1FFFFF00)|val; break; - case 0x6: /*Ramp frequency*/ + case 6: /*Ramp frequency*/ gus->rfreq[gus->voice] = (int)( (double)((val & 63)*512)/(double)(1 << (3*(val >> 6)))); break; - case 0x9: /*Current volume*/ + case 9: /*Current volume*/ gus->curvol[gus->voice] = gus->rcur[gus->voice] = (gus->rcur[gus->voice] & ~(0xff << 6)) | (val << 6); break; @@ -263,10 +240,6 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xF807F00)|((val<<7)<<8); switch (gus->global) { case 0: /*Voice control*/ - if (!(val&1) && gus->ctrl[gus->voice]&1) - { - } - gus->ctrl[gus->voice] = val & 0x7f; old = gus->waveirqs[gus->voice]; @@ -294,16 +267,16 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xF807F00)|((val<<7)<<8); gus->end[gus->voice]=(gus->end[gus->voice]&0x1FFF00FF)|(val<<8); break; - case 0x6: /*Ramp frequency*/ + case 6: /*Ramp frequency*/ gus->rfreq[gus->voice] = (int)( (double)((val & 63) * (1 << 10))/(double)(1 << (3 * (val >> 6)))); break; - case 0x7: /*Ramp start*/ + case 7: /*Ramp start*/ gus->rstart[gus->voice] = val << 14; break; - case 0x8: /*Ramp end*/ + case 8: /*Ramp end*/ gus->rend[gus->voice] = val << 14; break; - case 0x9: /*Current volume*/ + case 9: /*Current volume*/ gus->curvol[gus->voice] = gus->rcur[gus->voice] = (gus->rcur[gus->voice] & ~(0xff << 14)) | (val << 14); break; @@ -494,33 +467,75 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8); break; case 0x240: - gus->midi_loopback = val & 0x20; - gus->latch_enable = (val & 0x40) ? 2 : 1; + gus->latch_enable = val; break; case 0x24b: switch (gus->reg_ctrl & 0x07) { case 0: - if (gus->latch_enable == 1) - gus->dma = gus_dmas[val & 7]; - if (gus->latch_enable == 2) - { - gus->irq = gus_irqs[val & 7]; - - if (val & 0x40) - { - if (gus->irq == -1) - gus->irq = gus->irq_midi = gus_irqs[(val >> 3) & 7]; - else - gus->irq_midi = gus->irq; - } - else - gus->irq_midi = gus_irqs_midi[(val >> 3) & 7]; - - gus->sb_nmi = val & 0x80; - } - gus->latch_enable = 0; + if (gus->latch_enable & 0x40) { + // GUS SDK: IRQ Control Register + // Channel 1 GF1 IRQ selector (bits 2-0) + // 0=reserved, do not use + // 1=IRQ2 + // 2=IRQ5 + // 3=IRQ3 + // 4=IRQ7 + // 5=IRQ11 + // 6=IRQ12 + // 7=IRQ15 + // Channel 2 MIDI IRQ selector (bits 5-3) + // 0=no interrupt + // 1=IRQ2 + // 2=IRQ5 + // 3=IRQ3 + // 4=IRQ7 + // 5=IRQ11 + // 6=IRQ12 + // 7=IRQ15 + // Combine both IRQs using channel 1 (bit 6) + // Reserved (bit 7) + // + // "If both channels are sharing an IRQ, channel 2's IRQ must be set to 0 and turn on bit 6. A + // bus conflict will occur if both latches are programmed with the same IRQ #." + if (gus_irqs[val & 7] != -1) + gus->irq = gus_irqs[val & 7]; + + if (val & 0x40) // "Combine both IRQs" + gus->irq_midi = gus->irq; + else + gus->irq_midi = gus_irqs[(val >> 3) & 7]; + + gus->sb_nmi = val & 0x80; + } else { + // GUS SDK: DMA Control Register + // Channel 1 (bits 2-0) + // 0=NO DMA + // 1=DMA1 + // 2=DMA3 + // 3=DMA5 + // 4=DMA6 + // 5=DMA7 + // 6=? + // 7=? + // Channel 2 (bits 5-3) + // 0=NO DMA + // 1=DMA1 + // 2=DMA3 + // 3=DMA5 + // 4=DMA6 + // 5=DMA7 + // 6=? + // 7=? + // Combine both DMA channels using channel 1 (bit 6) + // Reserved (bit 7) + // + // "If both channels are sharing an DMA, channel 2's DMA must be set to 0 and turn on bit 6. A + // bus conflict will occur if both latches are programmed with the same DMA #." + if (gus_dmas[val & 7] != -1) + gus->dma = gus_dmas[val & 7]; + } break; case 1: gus->gp1 = val; @@ -543,13 +558,12 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8); break; case 0x246: - gus->ad_status |= 0x08; - if (gus->sb_ctrl & 0x20) - { + if (gus->sb_ctrl & 0x20) { + gus->ad_status |= 0x08; if (gus->sb_nmi) - nmi = 1; + nmi = 1; else if (gus->irq != -1) - picint(1 << gus->irq); + picint(1 << gus->irq); } break; case 0x24a: @@ -583,26 +597,49 @@ uint8_t readgus(uint16_t addr, void *p) switch (addr) { case 0x340: /*MIDI status*/ - val = gus->midi_status; + val = ((gus->irqstatus & 0x03 ? 0x80 : 0) | + (gus->uart_in && gus->uart_used >= 64 ? 0x20:0) | + ((gus->uart_used && gus->uart_in) ? 1 : 0) | (gus->uart_out ? 2 : 0)); break; case 0x341: /*MIDI data*/ - val = gus->midi_data; - gus->midi_status &= ~MIDI_INT_RECEIVE; - gus_midi_update_int_status(gus); + val = 0; + if (gus->uart_in) { + if (gus->uart_used) { + if (gus->uart_pos >= 64) + gus->uart_pos -= 64; + val = gus->uart_queue[gus->uart_pos]; + gus->uart_pos++; + gus->uart_used--; + } + if (!gus->uart_used) + gus->irqstatus &= ~0x02; + } break; - case 0x240: return 0; - case 0x246: /*IRQ status*/ + case 0x240: + val = 0xff; + break; + + case 0x246: /*IRQ status*/ val = gus->irqstatus & ~0x10; if (gus->ad_status & 0x19) val |= 0x10; - return val; + break; - case 0x24F: return 0; - case 0x342: return gus->voice; - case 0x343: return gus->global; - case 0x344: /*Global low*/ + case 0x24F: + val = 0; + break; + + case 0x342: + val = gus->voice; + break; + + case 0x343: + val = gus->global; + break; + + case 0x344: /*Global low*/ switch (gus->global) { case 0x82: /*Start addr high*/ @@ -770,7 +807,6 @@ void gus_poll_timer_1(void *p) if (gus->irq != -1) picint(1 << gus->irq); } - gus_midi_update_int_status(gus); } void gus_poll_timer_2(void *p) @@ -998,6 +1034,55 @@ static void gus_get_buffer(int32_t *buffer, int len, void *p) gus->pos = 0; } +static void gus_queue(gus_t *gus, uint8_t val) +{ + int pos; + + if (gus->uart_used < 64) { + pos = gus->uart_used + gus->uart_pos; + if (pos >= 64) + pos -= 64; + gus->uart_queue[pos] = val; + gus->uart_used++; + } +} + +static void gus_input_msg(void *p, uint8_t *msg) +{ + gus_t *gus = (gus_t *)p; + uint8_t i; + + if (gus->sysex) + return; + + if (gus->uart_in) { + gus->irqstatus |= 0x02; + for (i=0;iirq_midi); + } +} + +static int gus_input_sysex(void *p, uint8_t *buffer, uint32_t len, int abort) +{ + gus_t *gus = (gus_t *)p; + uint32_t i; + + if (abort) { + gus->uart_used = 0; + gus->sysex = 0; + return 0; + } + gus->sysex = 1; + for (i=0;iuart_used >= 64) { + return (len-i); + } + gus_queue(gus, buffer[i]); + } + gus->sysex = 0; + return 0; +} void *gus_init(const device_t *info) { @@ -1026,7 +1111,7 @@ void *gus_init(const device_t *info) gus->samp_latch = (uint64_t)(TIMER_USEC * (1000000.0 / 44100.0)); gus->t1l = gus->t2l = 0xff; - + io_sethandler(0x0240, 0x0010, readgus, NULL, NULL, writegus, NULL, NULL, gus); io_sethandler(0x0340, 0x0010, readgus, NULL, NULL, writegus, NULL, NULL, gus); io_sethandler(0x0746, 0x0001, readgus, NULL, NULL, writegus, NULL, NULL, gus); @@ -1037,6 +1122,10 @@ void *gus_init(const device_t *info) sound_add_handler(gus_get_buffer, gus); + input_msg = gus_input_msg; + input_sysex = gus_input_sysex; + midi_in_p = gus; + return gus; } From 3bdec705e574ff28033c3f673f7bf28b4e777658 Mon Sep 17 00:00:00 2001 From: Altheos Date: Wed, 8 Jan 2020 17:49:06 +0100 Subject: [PATCH 030/177] GUS soundcard improvements : IO address flexibility 256kb, 512kb or 1Mb total memory variant --- src/sound/snd_gus.c | 247 ++++++++++++++++++++++++++++------------- src/win/86Box.rc | 6 +- src/win/resource.h | 4 +- src/win/win_settings.c | 19 +++- 4 files changed, 195 insertions(+), 81 deletions(-) diff --git a/src/sound/snd_gus.c b/src/sound/snd_gus.c index 46bd3408d..235bd9ca9 100644 --- a/src/sound/snd_gus.c +++ b/src/sound/snd_gus.c @@ -15,6 +15,36 @@ #include "sound.h" #include "snd_gus.h" +enum +{ + MIDI_INT_RECEIVE = 0x01, + MIDI_INT_TRANSMIT = 0x02, + MIDI_INT_MASTER = 0x80 +}; + +enum +{ + MIDI_CTRL_TRANSMIT_MASK = 0x60, + MIDI_CTRL_TRANSMIT = 0x20, + MIDI_CTRL_RECEIVE = 0x80 +}; + +enum +{ + GUS_INT_MIDI_TRANSMIT = 0x01, + GUS_INT_MIDI_RECEIVE = 0x02 +}; + +enum +{ + GUS_TIMER_CTRL_AUTO = 0x01 +}; + +enum +{ + GUS_CLASSIC = 0, + GUS_MAX = 1, +}; typedef struct gus_t { @@ -51,12 +81,14 @@ typedef struct gus_t uint64_t samp_latch; uint8_t *ram; + uint32_t gus_end_ram; int irqnext; pc_timer_t timer_1, timer_2; int irq, dma, irq_midi; + uint16_t base; int latch_enable; uint8_t sb_2xa, sb_2xc, sb_2xe; @@ -119,31 +151,6 @@ void pollgusirqs(gus_t *gus) if (!gus->irqstatus && gus->irq != -1) picintc(1 << gus->irq); } -enum -{ - MIDI_INT_RECEIVE = 0x01, - MIDI_INT_TRANSMIT = 0x02, - MIDI_INT_MASTER = 0x80 -}; - -enum -{ - MIDI_CTRL_TRANSMIT_MASK = 0x60, - MIDI_CTRL_TRANSMIT = 0x20, - MIDI_CTRL_RECEIVE = 0x80 -}; - -enum -{ - GUS_INT_MIDI_TRANSMIT = 0x01, - GUS_INT_MIDI_RECEIVE = 0x02 -}; - -enum -{ - GUS_TIMER_CTRL_AUTO = 0x01 -}; - void gus_midi_update_int_status(gus_t *gus) { gus->midi_status &= ~MIDI_INT_MASTER; @@ -174,11 +181,19 @@ void writegus(uint16_t addr, uint8_t val, void *p) gus_t *gus = (gus_t *)p; int c, d; int old; - if (gus->latch_enable && addr != 0x24b) + uint16_t port; + + if ((addr == 0x388) || (addr == 0x389)) + port = addr; + else + port = addr & 0xf0f; + + if (gus->latch_enable && port != 0x20b) gus->latch_enable = 0; - switch (addr) + + switch (port) { - case 0x340: /*MIDI control*/ + case 0x300: /*MIDI control*/ old = gus->midi_ctrl; gus->midi_ctrl = val; @@ -191,7 +206,7 @@ void writegus(uint16_t addr, uint8_t val, void *p) gus_midi_update_int_status(gus); break; - case 0x341: /*MIDI data*/ + case 0x301: /*MIDI data*/ if (gus->midi_loopback) { gus->midi_status |= MIDI_INT_RECEIVE; @@ -201,13 +216,13 @@ void writegus(uint16_t addr, uint8_t val, void *p) gus->midi_status |= MIDI_INT_TRANSMIT; break; - case 0x342: /*Voice select*/ + case 0x302: /*Voice select*/ gus->voice=val&31; break; - case 0x343: /*Global select*/ + case 0x303: /*Global select*/ gus->global=val; break; - case 0x344: /*Global low*/ + case 0x304: /*Global low*/ switch (gus->global) { case 0: /*Voice control*/ @@ -259,7 +274,7 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xF807F00)|((val<<7)<<8); break; } break; - case 0x345: /*Global high*/ + case 0x305: /*Global high*/ switch (gus->global) { case 0: /*Voice control*/ @@ -449,11 +464,12 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8); break; } break; - case 0x347: /*DRAM access*/ - gus->ram[gus->addr]=val; + case 0x307: /*DRAM access*/ gus->addr&=0xFFFFF; + if (gus->addr < gus->gus_end_ram) + gus->ram[gus->addr]=val; break; - case 0x248: case 0x388: + case 0x208: case 0x388: gus->adcommand = val; break; @@ -493,12 +509,12 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8); } break; - case 0x240: + case 0x200: gus->midi_loopback = val & 0x20; gus->latch_enable = (val & 0x40) ? 2 : 1; break; - case 0x24b: + case 0x20b: switch (gus->reg_ctrl & 0x07) { case 0: @@ -542,7 +558,7 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8); } break; - case 0x246: + case 0x206: gus->ad_status |= 0x08; if (gus->sb_ctrl & 0x20) { @@ -552,10 +568,10 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8); picint(1 << gus->irq); } break; - case 0x24a: + case 0x20a: gus->sb_2xa = val; break; - case 0x24c: + case 0x20c: gus->ad_status |= 0x10; if (gus->sb_ctrl & 0x20) { @@ -564,45 +580,53 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8); else if (gus->irq != -1) picint(1 << gus->irq); } - case 0x24d: + case 0x20d: gus->sb_2xc = val; break; - case 0x24e: + case 0x20e: gus->sb_2xe = val; break; - case 0x24f: + case 0x20f: gus->reg_ctrl = val; break; } } + uint8_t readgus(uint16_t addr, void *p) { gus_t *gus = (gus_t *)p; uint8_t val = 0xff; - switch (addr) + uint16_t port; + + if ((addr == 0x388) || (addr == 0x389)) + port = addr; + else + port = addr & 0xf0f; + + switch (port) { - case 0x340: /*MIDI status*/ + case 0x300: /*MIDI status*/ val = gus->midi_status; break; - case 0x341: /*MIDI data*/ + case 0x301: /*MIDI data*/ val = gus->midi_data; gus->midi_status &= ~MIDI_INT_RECEIVE; gus_midi_update_int_status(gus); break; - case 0x240: return 0; - case 0x246: /*IRQ status*/ + case 0x200: return 0; + case 0x206: /*IRQ status*/ val = gus->irqstatus & ~0x10; if (gus->ad_status & 0x19) val |= 0x10; return val; - case 0x24F: return 0; - case 0x342: return gus->voice; - case 0x343: return gus->global; - case 0x344: /*Global low*/ + case 0x20F: return 0; + case 0x302: return gus->voice; + case 0x303: return gus->global; + case 0x304: /*Global low*/ switch (gus->global) { case 0x82: /*Start addr high*/ @@ -632,7 +656,7 @@ uint8_t readgus(uint16_t addr, void *p) break; } break; - case 0x345: /*Global high*/ + case 0x305: /*Global high*/ switch (gus->global) { case 0x80: /*Voice control*/ @@ -681,16 +705,20 @@ uint8_t readgus(uint16_t addr, void *p) break; } break; - case 0x346: return 0xff; - case 0x347: /*DRAM access*/ + case 0x306: case 0x706: /*Revision level*/ + val = 0xff; + break; + case 0x307: /*DRAM access*/ val=gus->ram[gus->addr]; gus->addr&=0xFFFFF; - return val; - case 0x349: return 0; - case 0x746: /*Revision level*/ - return 0xff; /*Pre 3.7 - no mixer*/ + if (gus->addr < gus->gus_end_ram) + val = gus->ram[gus->addr]; + else + val = 0; + break; + case 0x309: return 0; - case 0x24b: + case 0x20b: switch (gus->reg_ctrl & 0x07) { case 1: @@ -708,15 +736,15 @@ uint8_t readgus(uint16_t addr, void *p) } break; - case 0x24c: + case 0x20c: val = gus->sb_2xc; if (gus->reg_ctrl & 0x20) gus->sb_2xc &= 0x80; break; - case 0x24e: + case 0x20e: return gus->sb_2xe; - case 0x248: case 0x388: + case 0x208: case 0x388: if (gus->tctrl & GUS_TIMER_CTRL_AUTO) val = gus->sb_2xa; else @@ -727,14 +755,14 @@ uint8_t readgus(uint16_t addr, void *p) } break; - case 0x249: + case 0x209: gus->ad_status &= ~0x01; nmi = 0; case 0x389: val = gus->ad_data; break; - case 0x24A: + case 0x20A: val = gus->adcommand; break; @@ -1003,11 +1031,13 @@ void *gus_init(const device_t *info) { int c; double out = 1.0; + uint8_t gus_ram = device_get_config_int("gus_ram"); gus_t *gus = malloc(sizeof(gus_t)); memset(gus, 0, sizeof(gus_t)); - gus->ram = malloc(1 << 20); - memset(gus->ram, 0, 1 << 20); + gus->gus_end_ram = 1 << (18 + gus_ram); + gus->ram = (uint8_t *)malloc(gus->gus_end_ram); + memset(gus->ram, 0x00, (gus->gus_end_ram)); for (c=0;c<32;c++) { @@ -1026,10 +1056,12 @@ void *gus_init(const device_t *info) gus->samp_latch = (uint64_t)(TIMER_USEC * (1000000.0 / 44100.0)); gus->t1l = gus->t2l = 0xff; + + gus->base = device_get_config_hex16("base"); - io_sethandler(0x0240, 0x0010, readgus, NULL, NULL, writegus, NULL, NULL, gus); - io_sethandler(0x0340, 0x0010, readgus, NULL, NULL, writegus, NULL, NULL, gus); - io_sethandler(0x0746, 0x0001, readgus, NULL, NULL, writegus, NULL, NULL, gus); + io_sethandler(gus->base, 0x0010, readgus, NULL, NULL, writegus, NULL, NULL, gus); + io_sethandler(0x0100+gus->base, 0x0010, readgus, NULL, NULL, writegus, NULL, NULL, gus); + io_sethandler(0x0506+gus->base, 0x0001, readgus, NULL, NULL, writegus, NULL, NULL, gus); io_sethandler(0x0388, 0x0002, readgus, NULL, NULL, writegus, NULL, NULL, gus); timer_add(&gus->samp_timer, gus_poll_wave, gus, 1); timer_add(&gus->timer_1, gus_poll_timer_1, gus, 1); @@ -1058,11 +1090,76 @@ void gus_speed_changed(void *p) gus->samp_latch = (uint64_t)(TIMER_USEC * (1000000.0 / gusfreqs[gus->voices - 14])); } +static const device_config_t gus_config[] = { + { + "type", "GUS type", CONFIG_SELECTION, "", 0, + { + { + "Classic", GUS_CLASSIC + }, +#if 0 + { + "MAX", GUS_MAX + }, +#endif + { + NULL + } + }, + }, + { + "base", "Address", CONFIG_HEX16, "", 0x220, + { + { + "210H", 0x210 + }, + { + "220H", 0x220 + }, + { + "230H", 0x230 + }, + { + "240H", 0x240 + }, + { + "250H", 0x250 + }, + { + "260H", 0x260 + }, + }, + }, + { + "gus_ram", "Onboard RAM", CONFIG_SELECTION, "", 0, + { + { + "256 KB", 0 + }, + { + "512 KB", 1 + }, + { + "1 MB", 2 + }, + { + NULL + } + } + }, + { + "", "", -1 + } +}; + const device_t gus_device = { "Gravis UltraSound", - 0, 0, - gus_init, gus_close, NULL, NULL, - gus_speed_changed, NULL, - NULL + DEVICE_ISA, + 0, + gus_init, gus_close, NULL, + NULL, + gus_speed_changed, + NULL, + gus_config }; diff --git a/src/win/86Box.rc b/src/win/86Box.rc index 43c2c0f7c..69d53a69a 100644 --- a/src/win/86Box.rc +++ b/src/win/86Box.rc @@ -395,9 +395,11 @@ BEGIN BS_AUTOCHECKBOX | WS_TABSTOP,147,83,94,10 CONTROL "Gravis Ultrasound",IDC_CHECK_GUS,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,7,101,94,10 + BS_AUTOCHECKBOX | WS_TABSTOP,7,81,94,10 + PUSHBUTTON "Configure",IDC_CONFIGURE_GUS,214,81,46,12 + CONTROL "Use FLOAT32 sound",IDC_CHECK_FLOAT,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,147,101,94,10 + BS_AUTOCHECKBOX | WS_TABSTOP,7,99,94,10 END DLG_CFG_NETWORK DIALOG DISCARDABLE 97, 0, 267, 63 diff --git a/src/win/resource.h b/src/win/resource.h index 49ba9679e..8e11ed62a 100644 --- a/src/win/resource.h +++ b/src/win/resource.h @@ -149,8 +149,8 @@ #define IDC_CHECK_MPU401 1076 #define IDC_CONFIGURE_MPU401 1077 #define IDC_CHECK_FLOAT 1078 -#define IDC_CHECK_GUSMAX 1079 -#define IDC_COMBO_MIDI_IN 1080 +#define IDC_CONFIGURE_GUS 1079 +#define IDC_COMBO_MIDI_IN 1080 #define IDC_COMBO_NET_TYPE 1090 /* network config */ #define IDC_COMBO_PCAP 1091 diff --git a/src/win/win_settings.c b/src/win/win_settings.c index 1a2605a07..f47f4f4b1 100644 --- a/src/win/win_settings.c +++ b/src/win/win_settings.c @@ -56,6 +56,7 @@ #include "../sound/sound.h" #include "../sound/midi.h" #include "../sound/snd_mpu401.h" +#include "../sound/snd_gus.h" #include "../video/video.h" #include "../video/vid_voodoo.h" #include "../plat.h" @@ -1117,7 +1118,6 @@ mpu401_standalone_allow(void) return 1; } - #if defined(__amd64__) || defined(__aarch64__) static LRESULT CALLBACK #else @@ -1245,7 +1245,10 @@ win_settings_sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) h=GetDlgItem(hdlg, IDC_CHECK_GUS); SendMessage(h, BM_SETCHECK, temp_GUS, 0); - + + h = GetDlgItem(hdlg, IDC_CONFIGURE_GUS); + EnableWindow(h, (temp_GUS) ? TRUE : FALSE); + h=GetDlgItem(hdlg, IDC_CHECK_SSI); SendMessage(h, BM_SETCHECK, temp_SSI2001, 0); @@ -1345,6 +1348,18 @@ win_settings_sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) temp_deviceconfig |= deviceconfig_open(hdlg, (machines[temp_machine].flags & MACHINE_MCA) ? (void *)&mpu401_mca_device : (void *)&mpu401_device); break; + + case IDC_CHECK_GUS: + h = GetDlgItem(hdlg, IDC_CHECK_GUS); + temp_GUS = SendMessage(h, BM_GETCHECK, 0, 0); + + h = GetDlgItem(hdlg, IDC_CONFIGURE_GUS); + EnableWindow(h, temp_GUS ? TRUE : FALSE); + break; + + case IDC_CONFIGURE_GUS: + temp_deviceconfig |= deviceconfig_open(hdlg, (void *)&gus_device); + break; } return FALSE; From c524a62c4069e16e20b361845cb7351414118d15 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 8 Jan 2020 19:01:24 +0100 Subject: [PATCH 031/177] Fixed an intance of undefined behavior in sb_mpu401.c. --- src/sound/snd_mpu401.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sound/snd_mpu401.c b/src/sound/snd_mpu401.c index 5b4d2635b..03916ae3e 100644 --- a/src/sound/snd_mpu401.c +++ b/src/sound/snd_mpu401.c @@ -1216,7 +1216,8 @@ MPU401_Event(void *priv) mpu->clock.cth_counter++; if (mpu->clock.cth_counter >= mpu->clock.cth_rate[mpu->clock.cth_mode]) { mpu->clock.cth_counter = 0; - mpu->clock.cth_mode= (++mpu->clock.cth_mode) % 4; + mpu->clock.cth_mode++; + mpu->clock.cth_mode %= 4; mpu->state.req_mask |= (1 << 13); } } From 04931767e78a42393b2ebcb6a7ebeffbf0d1bcec Mon Sep 17 00:00:00 2001 From: TC1995 Date: Wed, 8 Jan 2020 19:05:21 +0100 Subject: [PATCH 032/177] Fixed compile error. --- src/sound/snd_mpu401.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sound/snd_mpu401.c b/src/sound/snd_mpu401.c index 03916ae3e..1ffc067f1 100644 --- a/src/sound/snd_mpu401.c +++ b/src/sound/snd_mpu401.c @@ -1394,7 +1394,7 @@ MPU401_InputMsg(void *p, uint8_t *msg) if (msg[1] == 123) { /* All notes off. */ for (key = 0; key < 128; key++) { - if (!(mpu->chanref[chrefnum].on && (mpu->chanref[chrefnum].M_GETKEY))) + if (!(mpu->chanref[chrefnum].on && (mpu->chanref[chrefnum].M_GETKEY))) { if (mpu->inputref[chan].on && mpu->inputref[chan].M_GETKEY) { midi_raw_out_byte(0x80 | chan); midi_raw_out_byte(key); From 480f7b5903d0a2e8580f127235545c4cb971d791 Mon Sep 17 00:00:00 2001 From: Daniel Gurney Date: Wed, 8 Jan 2020 20:03:50 +0200 Subject: [PATCH 033/177] Update readme with new build instructions --- README.md | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 114a9073f..c825e0c57 100644 --- a/README.md +++ b/README.md @@ -30,24 +30,11 @@ Building -------- In order to compile 86Box from this repository, please follow this step-by-step guide: -1. Download the development environment from http://tinyurl.com/de86box. - Afterwards, extract it to your desired location. Of course, also clone - the repository in your desired location. Downloading ZIPs is not recommended, - as it makes it more inconvenient to keep the code up-to-date. To avoid - issues, make sure neither path has spaces in it. -2. In the extracted environment folder, you will find a script called - `mingw32_shell.bat`. Launch it. There are other shell launching scripts - in there, but you should not use them. -3. Once launched, run `pacman -Syuu` in order to update the environment. - Depending on the state of the downloaded DE, you may need to run it twice - (once initially, and then again after re-entering the environment). Make sure - to keep the enviroment up-to-date by re-running the command periodically. -4. Run the following commands to install the missing packages: - * `pacman -S mingw-w64-i686-libpng` - * `pacman -S mingw-w64-i686-freetype` - * `pacman -S mingw-w64-i686-ghostscript` - * `pacman -S mingw-w64-i686-SDL2` -5. Once the environment is fully updated, `cd` into your cloned `86box\src` +1. Install the [MSYS2](https://www.msys2.org/) environment. The rest of the guide will refer to the directory that you install it to (C:\msys32 or C:\msys64 by default) as the MSYS2 root. +2. Launch your MSYS2 environment using the `MSYS2 MinGW 32-bit` shortcut. +3. Once launched, run `pacman -Syu` in order to update the environment. You may need to do this twice, just follow the on-screen instructions. Make sure you re-run `pacman -Syu` periodically to keep the environment up-to-date. +4. Run the following command to install all of the dependencies: `pacman -S gdb make git mingw-w64-i686-toolchain mingw-w64-i686-openal mingw-w64-i686-freetype mingw-w64-i686-SDL2 mingw-w64-i686-zlib mingw-w64-i686-libpng mingw-w64-i686-ghostscript`. Additionally, you will need to download the developer's pack of WinPcap [from here](https://www.winpcap.org/devel.htm), and extract it into `\mingw32\`. +5. Once the environment is fully updated and all dependencies are installed, `cd` into your cloned `86box\src` directory. 6. Run `make -jN -f win/makefile.mingw` to start the actual compilation process. Substitute `N` with the number of threads you want to use for the compilation From 405030abd4a7f6da96012c5df169928219f721aa Mon Sep 17 00:00:00 2001 From: TC1995 Date: Fri, 10 Jan 2020 01:13:38 +0100 Subject: [PATCH 034/177] Made MIDI Input reset properly with midi data set to 0xaa (required by the GUS Installation MIDI IRQ tests) and initialize with data set to 0x00 when a master reset is not used (required by midi input from Sound Club). --- src/sound/snd_gus.c | 168 +++++++++++++++++++++++++------------------- 1 file changed, 95 insertions(+), 73 deletions(-) diff --git a/src/sound/snd_gus.c b/src/sound/snd_gus.c index 05840a7f6..3fbbfa5e0 100644 --- a/src/sound/snd_gus.c +++ b/src/sound/snd_gus.c @@ -69,8 +69,8 @@ typedef struct gus_t uint8_t ad_status, ad_data; uint8_t ad_timer_ctrl; - uint8_t uart_queue[64]; - int uart_pos, uart_used; + uint8_t midi_ctrl, midi_status, midi_queue[64], midi_data; + int midi_r, midi_w; int uart_in, uart_out, sysex; uint8_t gp1, gp2; @@ -79,7 +79,8 @@ typedef struct gus_t uint8_t usrr; } gus_t; -static int gus_irqs[8] = {-1, 2, 5, 3, 7, 11, 12, 15}; +static int gus_gf1_irqs[8] = {0, 2, 5, 3, 7, 11, 12, 15}; +static int gus_midi_irqs[8] = {0, 2, 5, 3, 7, 11, 12, 15}; static int gus_dmas[8] = {-1, 1, 3, 5, 6, 7, -1, -1}; int gusfreqs[]= @@ -102,21 +103,24 @@ void pollgusirqs(gus_t *gus) gus->irqstatus2=0x60|c; if (gus->rampirqs[c]) gus->irqstatus2 |= 0x80; gus->irqstatus|=0x20; - if (gus->irq != -1) - picint(1 << gus->irq); + if (gus->irq != 0) + picint(1 << gus->irq); return; } if (gus->rampirqs[c]) { gus->irqstatus2=0xA0|c; gus->irqstatus|=0x40; - if (gus->irq != -1) - picint(1 << gus->irq); + if (gus->irq != 0) + picint(1 << gus->irq); return; } } gus->irqstatus2=0xE0; - if (!gus->irqstatus && gus->irq != -1) picintc(1 << gus->irq); + if (!gus->irqstatus) { + if (gus->irq != 0) + picintc(1 << gus->irq); + } } enum @@ -144,6 +148,30 @@ enum GUS_TIMER_CTRL_AUTO = 0x01 }; +void gus_midi_update_int_status(gus_t *gus) +{ + gus->midi_status &= ~MIDI_INT_MASTER; + if ((gus->midi_ctrl & MIDI_CTRL_TRANSMIT_MASK) == MIDI_CTRL_TRANSMIT && (gus->midi_status & MIDI_INT_TRANSMIT)) + { + gus->midi_status |= MIDI_INT_MASTER; + gus->irqstatus |= GUS_INT_MIDI_TRANSMIT; + } + else + gus->irqstatus &= ~GUS_INT_MIDI_TRANSMIT; + + if ((gus->midi_ctrl & MIDI_CTRL_RECEIVE) && (gus->midi_status & MIDI_INT_RECEIVE)) + { + gus->midi_status |= MIDI_INT_MASTER; + gus->irqstatus |= GUS_INT_MIDI_RECEIVE; + } + else + gus->irqstatus &= ~GUS_INT_MIDI_RECEIVE; + + if ((gus->midi_status & MIDI_INT_MASTER) && (gus->irq_midi != 0)) + { + picint(1 << gus->irq_midi); + } +} void writegus(uint16_t addr, uint8_t val, void *p) { @@ -153,30 +181,30 @@ void writegus(uint16_t addr, uint8_t val, void *p) switch (addr) { case 0x340: /*MIDI control*/ + gus->midi_ctrl = val; gus->uart_out = 1; - if (val == 3 || !val) { + + if (((gus->midi_ctrl & 3) == 3) || !gus->midi_ctrl) { /*Master reset*/ gus->uart_in = 0; - gus->irqstatus &= ~0x03; - gus->uart_used = 0; - return; - } - - if (val & 0x20) { - gus->irqstatus |= 0x01; - } else { - gus->irqstatus &= ~0x01; - } - - if (val & 0x80) + gus->midi_status = 0; + gus->midi_r = 0; + gus->midi_w = 0; + } else if (gus->midi_ctrl & MIDI_CTRL_TRANSMIT) { + gus->midi_status |= MIDI_INT_TRANSMIT; + } else if (gus->midi_ctrl & MIDI_CTRL_RECEIVE) { gus->uart_in = 1; - else - gus->uart_in = 0; + } + gus_midi_update_int_status(gus); break; case 0x341: /*MIDI data*/ + gus->midi_data = val; if (gus->uart_out) { midi_raw_out_byte(val); - picint(1 << gus->irq_midi); } + if (gus->latch_enable & 0x20) { + gus->midi_status |= MIDI_INT_RECEIVE; + } else + gus->midi_status |= MIDI_INT_TRANSMIT; break; case 0x342: /*Voice select*/ gus->voice = val & 31; @@ -439,7 +467,7 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8); { if (gus->sb_nmi) nmi = 1; - else if (gus->irq != -1) + else picint(1 << gus->irq); } } @@ -499,14 +527,14 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8); // // "If both channels are sharing an IRQ, channel 2's IRQ must be set to 0 and turn on bit 6. A // bus conflict will occur if both latches are programmed with the same IRQ #." - if (gus_irqs[val & 7] != -1) - gus->irq = gus_irqs[val & 7]; - + if ((val & 7) != 0) + gus->irq = gus_gf1_irqs[val & 7]; + if (val & 0x40) // "Combine both IRQs" gus->irq_midi = gus->irq; else - gus->irq_midi = gus_irqs[(val >> 3) & 7]; - + gus->irq_midi = gus_midi_irqs[(val >> 3) & 7]; + gus->sb_nmi = val & 0x80; } else { // GUS SDK: DMA Control Register @@ -562,7 +590,7 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8); gus->ad_status |= 0x08; if (gus->sb_nmi) nmi = 1; - else if (gus->irq != -1) + else if (gus->irq != 0) picint(1 << gus->irq); } break; @@ -575,7 +603,7 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8); { if (gus->sb_nmi) nmi = 1; - else if (gus->irq != -1) + else if (gus->irq != 0) picint(1 << gus->irq); } case 0x24d: @@ -597,23 +625,23 @@ uint8_t readgus(uint16_t addr, void *p) switch (addr) { case 0x340: /*MIDI status*/ - val = ((gus->irqstatus & 0x03 ? 0x80 : 0) | - (gus->uart_in && gus->uart_used >= 64 ? 0x20:0) | - ((gus->uart_used && gus->uart_in) ? 1 : 0) | (gus->uart_out ? 2 : 0)); + val = gus->midi_status; break; case 0x341: /*MIDI data*/ val = 0; if (gus->uart_in) { - if (gus->uart_used) { - if (gus->uart_pos >= 64) - gus->uart_pos -= 64; - val = gus->uart_queue[gus->uart_pos]; - gus->uart_pos++; - gus->uart_used--; + if ((gus->midi_data == 0xaa) && (gus->midi_ctrl & MIDI_CTRL_RECEIVE)) /*Handle master reset*/ + val = gus->midi_data; + else { + val = gus->midi_queue[gus->midi_r]; + if (gus->midi_r != gus->midi_w) { + gus->midi_r++; + gus->midi_r &= 63; + } } - if (!gus->uart_used) - gus->irqstatus &= ~0x02; + gus->midi_status &= ~MIDI_INT_RECEIVE; + gus_midi_update_int_status(gus); } break; @@ -793,9 +821,9 @@ void gus_poll_timer_1(void *p) gus->ad_status |= 0x40; if (gus->tctrl&4) { - if (gus->irq != -1) - picint(1 << gus->irq); - gus->ad_status |= 0x04; + if (gus->irq != 0) + picint(1 << gus->irq); + gus->ad_status |= 0x04; gus->irqstatus |= 0x04; } } @@ -804,9 +832,11 @@ void gus_poll_timer_1(void *p) { gus->irqnext=0; gus->irqstatus|=0x80; - if (gus->irq != -1) - picint(1 << gus->irq); + if (gus->irq != 0) + picint(1 << gus->irq); } + + gus_midi_update_int_status(gus); } void gus_poll_timer_2(void *p) @@ -823,8 +853,8 @@ void gus_poll_timer_2(void *p) gus->ad_status |= 0x20; if (gus->tctrl&8) { - if (gus->irq != -1) - picint(1 << gus->irq); + if (gus->irq != 0) + picint(1 << gus->irq); gus->ad_status |= 0x02; gus->irqstatus |= 0x08; } @@ -834,8 +864,8 @@ void gus_poll_timer_2(void *p) { gus->irqnext=0; gus->irqstatus|=0x80; - if (gus->irq != -1) - picint(1 << gus->irq); + if (gus->irq != 0) + picint(1 << gus->irq); } } @@ -1034,19 +1064,6 @@ static void gus_get_buffer(int32_t *buffer, int len, void *p) gus->pos = 0; } -static void gus_queue(gus_t *gus, uint8_t val) -{ - int pos; - - if (gus->uart_used < 64) { - pos = gus->uart_used + gus->uart_pos; - if (pos >= 64) - pos -= 64; - gus->uart_queue[pos] = val; - gus->uart_used++; - } -} - static void gus_input_msg(void *p, uint8_t *msg) { gus_t *gus = (gus_t *)p; @@ -1056,10 +1073,14 @@ static void gus_input_msg(void *p, uint8_t *msg) return; if (gus->uart_in) { - gus->irqstatus |= 0x02; - for (i=0;iirq_midi); + gus->midi_status |= MIDI_INT_RECEIVE; + + for (i=0;imidi_queue[gus->midi_w++] = msg[i]; + gus->midi_w &= 63; + } + + gus_midi_update_int_status(gus); } } @@ -1069,16 +1090,15 @@ static int gus_input_sysex(void *p, uint8_t *buffer, uint32_t len, int abort) uint32_t i; if (abort) { - gus->uart_used = 0; gus->sysex = 0; return 0; } gus->sysex = 1; for (i=0;iuart_used >= 64) { + if (gus->midi_r == gus->midi_w) return (len-i); - } - gus_queue(gus, buffer[i]); + gus->midi_queue[gus->midi_w++] = buffer[i]; + gus->midi_w &= 63; } gus->sysex = 0; return 0; @@ -1112,6 +1132,8 @@ void *gus_init(const device_t *info) gus->t1l = gus->t2l = 0xff; + gus->uart_out = 1; + io_sethandler(0x0240, 0x0010, readgus, NULL, NULL, writegus, NULL, NULL, gus); io_sethandler(0x0340, 0x0010, readgus, NULL, NULL, writegus, NULL, NULL, gus); io_sethandler(0x0746, 0x0001, readgus, NULL, NULL, writegus, NULL, NULL, gus); From d0a8b1211ab53d9460e5aa3ee62296f83a5e9a5b Mon Sep 17 00:00:00 2001 From: Altheos Date: Fri, 10 Jan 2020 12:22:49 +0100 Subject: [PATCH 035/177] Fix wrong 86Box.rc --- src/win/86Box.rc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/win/86Box.rc b/src/win/86Box.rc index 69d53a69a..851b7d287 100644 --- a/src/win/86Box.rc +++ b/src/win/86Box.rc @@ -366,7 +366,7 @@ BEGIN PUSHBUTTON "Joystick 4...",IDC_JOY4,209,44,50,14 END -DLG_CFG_SOUND DIALOG DISCARDABLE 97, 0, 267, 116 +DLG_CFG_SOUND DIALOG DISCARDABLE 97, 0, 267, 199 STYLE DS_CONTROL | WS_CHILD FONT 9, "Segoe UI" BEGIN @@ -395,11 +395,11 @@ BEGIN BS_AUTOCHECKBOX | WS_TABSTOP,147,83,94,10 CONTROL "Gravis Ultrasound",IDC_CHECK_GUS,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,7,81,94,10 - PUSHBUTTON "Configure",IDC_CONFIGURE_GUS,214,81,46,12 + BS_AUTOCHECKBOX | WS_TABSTOP,7,99,94,10 + PUSHBUTTON "Configure",IDC_CONFIGURE_GUS,214,99,46,12 CONTROL "Use FLOAT32 sound",IDC_CHECK_FLOAT,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,7,99,94,10 + BS_AUTOCHECKBOX | WS_TABSTOP,7,115,94,10 END DLG_CFG_NETWORK DIALOG DISCARDABLE 97, 0, 267, 63 From e0be29af062f53feb61c4a5f0c960e9978bf87a1 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Fri, 10 Jan 2020 12:33:20 +0100 Subject: [PATCH 036/177] Fixed GUS MIDI Out. --- src/sound/snd_gus.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/sound/snd_gus.c b/src/sound/snd_gus.c index 3fbbfa5e0..9399c3dc5 100644 --- a/src/sound/snd_gus.c +++ b/src/sound/snd_gus.c @@ -181,15 +181,16 @@ void writegus(uint16_t addr, uint8_t val, void *p) switch (addr) { case 0x340: /*MIDI control*/ + old = gus->midi_ctrl; gus->midi_ctrl = val; gus->uart_out = 1; - if (((gus->midi_ctrl & 3) == 3) || !gus->midi_ctrl) { /*Master reset*/ + if ((val & 3) == 3) { /*Master reset*/ gus->uart_in = 0; gus->midi_status = 0; gus->midi_r = 0; gus->midi_w = 0; - } else if (gus->midi_ctrl & MIDI_CTRL_TRANSMIT) { + } else if ((old & 3) == 3) { gus->midi_status |= MIDI_INT_TRANSMIT; } else if (gus->midi_ctrl & MIDI_CTRL_RECEIVE) { gus->uart_in = 1; From 1b8017640eb26ca216ae39679a8363261bf655f7 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 11 Jan 2020 22:30:28 +0100 Subject: [PATCH 037/177] Fixed parsing of PREGAP clauses in CUE sheets. --- src/cdrom/cdrom_image_backend.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/cdrom/cdrom_image_backend.c b/src/cdrom/cdrom_image_backend.c index cb7c14a98..983a75efa 100644 --- a/src/cdrom/cdrom_image_backend.c +++ b/src/cdrom/cdrom_image_backend.c @@ -9,15 +9,15 @@ * CD-ROM image file handling module, translated to C from * cdrom_dosbox.cpp. * - * Version: @(#)cdrom_image_backend.c 1.0.1 2019/12/21 + * Version: @(#)cdrom_image_backend.c 1.0.2 2020/01/11 * * Authors: Miran Grca, * Fred N. van Kempen, * The DOSBox Team, * - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2002-2019 The DOSBox Team. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2002-2020 The DOSBox Team. */ #define _LARGEFILE_SOURCE #define _LARGEFILE64_SOURCE @@ -903,7 +903,7 @@ cdi_load_cue(cd_img_t *cdi, const wchar_t *cuefile) } success = 0; } - } else if (!strcmp(command, "FILE")) + } else if (!strcmp(command, "PREGAP")) success = cdi_cue_get_frame(&cur_pregap, &line); else if (!strcmp(command, "CATALOG") || !strcmp(command, "CDTEXTFILE") || !strcmp(command, "FLAGS") || !strcmp(command, "ISRC") || !strcmp(command, "PERFORMER") || !strcmp(command, "POSTGAP") || !strcmp(command, "REM") || From 57341754e25998177b77a7c0d9d09caf3f06b956 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 11 Jan 2020 22:31:18 +0100 Subject: [PATCH 038/177] Decreased keyboard AT period to 100 us (was 1000 us) and made out_delay correctly initialized to -1. --- src/keyboard_at.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/keyboard_at.c b/src/keyboard_at.c index b001b1815..d174585c6 100644 --- a/src/keyboard_at.c +++ b/src/keyboard_at.c @@ -623,7 +623,7 @@ kbd_poll(void *priv) { atkbd_t *dev = (atkbd_t *)priv; - timer_advance_u64(&dev->send_delay_timer, (1000 * TIMER_USEC)); + timer_advance_u64(&dev->send_delay_timer, (100ULL * TIMER_USEC)); if ((dev->out_new != -1) && !dev->last_irq) { dev->wantirq = 0; @@ -658,17 +658,17 @@ kbd_poll(void *priv) dev->out_new = key_ctrl_queue[key_ctrl_queue_start] | 0x200; key_ctrl_queue_start = (key_ctrl_queue_start + 1) & 0xf; } else if (!(dev->status & STAT_OFULL) && dev->out_new == -1 && dev->out_delayed != -1) { - dev->out_new = dev->out_delayed; - dev->out_delayed = -1; + dev->out_new = dev->out_delayed; + dev->out_delayed = -1; } else if (!(dev->status & STAT_OFULL) && dev->out_new == -1 && !(dev->mem[0] & 0x10) && dev->out_delayed != -1) { - dev->out_new = dev->out_delayed; - dev->out_delayed = -1; + dev->out_new = dev->out_delayed; + dev->out_delayed = -1; } else if (!(dev->status & STAT_OFULL) && dev->out_new == -1/* && !(dev->mem[0] & 0x20)*/ && (mouse_queue_start != mouse_queue_end)) { dev->out_new = mouse_queue[mouse_queue_start] | 0x100; mouse_queue_start = (mouse_queue_start + 1) & 0xf; } else if (!(dev->status&STAT_OFULL) && dev->out_new == -1 && - !(dev->mem[0]&0x10) && (key_queue_start != key_queue_end)) { + !(dev->mem[0]&0x10) && (key_queue_start != key_queue_end) && !kbc_busy) { dev->out_new = key_queue[key_queue_start]; key_queue_start = (key_queue_start + 1) & 0xf; } @@ -1931,6 +1931,8 @@ do_command: #ifdef ENABLE_KEYBOARD_AT_LOG kbd_log("ATkbd: set defaults\n"); #endif + dev->out_new = -1; + dev->out_delayed = -1; add_data_kbd(0xfa); keyboard_set3_all_break = 0; @@ -2273,6 +2275,7 @@ kbd_reset(void *priv) dev->wantirq = 0; write_output(dev, 0xcf); dev->out_new = -1; + dev->out_delayed = -1; dev->last_irq = 0; dev->secr_phase = 0; dev->key_wantdata = 0; From 6cfa5c5c046f47f30aa00cc97f7b4fe0b775420e Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 11 Jan 2020 22:31:50 +0100 Subject: [PATCH 039/177] Changes to PCI and two new functions to accomodate the VIA MVP3 chipset. --- src/pci.c | 69 ++++++++++++++++++++++++++++++++++++------------------- src/pci.h | 10 ++++---- 2 files changed, 51 insertions(+), 28 deletions(-) diff --git a/src/pci.c b/src/pci.c index 05519cc2e..082361c36 100644 --- a/src/pci.c +++ b/src/pci.c @@ -8,15 +8,15 @@ * * Implementation the PCI bus. * - * Version: @(#)pci.c 1.0.4 2019/11/06 + * Version: @(#)pci.c 1.0.6 2020/01/11 * * Authors: Miran Grca, * Fred N. van Kempen, * Sarah Walker, * - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2008-2020 Sarah Walker. */ #include #include @@ -58,7 +58,7 @@ static pci_card_t pci_cards[32]; static uint8_t last_pci_card = 0; static uint8_t pci_card_to_slot_mapping[32]; static uint8_t elcr[2] = { 0, 0 }; -static uint8_t pci_irqs[4]; +static uint8_t pci_irqs[4], pci_irq_level[4]; static uint64_t pci_irq_hold[16]; static pci_mirq_t pci_mirqs[3]; static int pci_type, @@ -68,7 +68,7 @@ static int pci_type, pci_bus, pci_enable, pci_key; -static int trc_reg = 0; +static int trc_reg = 0, elcr_enabled = 1; #ifdef ENABLE_PCI_LOG @@ -278,6 +278,13 @@ pci_set_irq_routing(int pci_int, int irq) } +void +pci_set_irq_level(int pci_int, int level) +{ + pci_irq_level[pci_int - 1] = !!level; +} + + void pci_enable_mirq(int mirq) { @@ -297,13 +304,20 @@ pci_irq_is_level(int irq) { int real_irq = irq & 7; - if ((irq <= 2) || (irq == 8) || (irq == 13)) - return 0; + if (elcr_enabled) { + if ((irq <= 2) || (irq == 8) || (irq == 13)) + return 0; - if (irq > 7) - return !!(elcr[1] & (1 << real_irq)); + if (irq > 7) + return !!(elcr[1] & (1 << real_irq)); - return !!(elcr[0] & (1 << real_irq)); + return !!(elcr[0] & (1 << real_irq)); + } else { + if (irq < 8) + return (pic.icw1 & 8) ? 1 : 0; + else + return (pic2.icw1 & 8) ? 1 : 0; + } } @@ -401,6 +415,7 @@ pci_set_irq(uint8_t card, uint8_t pci_int) pci_log("pci_set_irq(%02X, %02X): IRQ routing for this slot and INT pin combination: %02X\n", card, pci_int, irq_routing); irq_line = pci_irqs[irq_routing]; + level = pci_irq_level[irq_routing]; } if (irq_line > 0x0f) { @@ -416,10 +431,6 @@ pci_set_irq(uint8_t card, uint8_t pci_int) } pci_log("pci_set_irq(%02X, %02X): Card not yet holding the IRQ\n", card, pci_int); - if (pci_type & PCI_NO_IRQ_STEERING) - level = 0; /* PCI without IRQ steering - IRQ always edge. */ - else - level = 1; /* PCI with IRQ steering - IRQ always level per the Intel datasheets. */ if (!level || !pci_irq_hold[irq_line]) { pci_log("pci_set_irq(%02X, %02X): Issuing %s-triggered IRQ (%sheld)\n", card, pci_int, level ? "level" : "edge", pci_irq_hold[irq_line] ? "" : "not "); @@ -433,7 +444,7 @@ pci_set_irq(uint8_t card, uint8_t pci_int) } /* If the IRQ is level-triggered, mark that this card is holding it. */ - if (pci_irq_is_level(irq_line)) { + if (level) { pci_log("pci_set_irq(%02X, %02X): Marking that this card is holding the IRQ\n", card, pci_int); pci_irq_hold[irq_line] |= (1ULL << card); } else { @@ -522,6 +533,7 @@ pci_clear_irq(uint8_t card, uint8_t pci_int) pci_log("pci_clear_irq(%02X, %02X): IRQ routing for this slot and INT pin combination: %02X\n", card, pci_int, irq_routing); irq_line = pci_irqs[irq_routing]; + level = pci_irq_level[irq_routing]; } if (irq_line > 0x0f) { @@ -531,17 +543,12 @@ pci_clear_irq(uint8_t card, uint8_t pci_int) pci_log("pci_clear_irq(%02X, %02X): Using IRQ %i\n", card, pci_int, irq_line); - if (pci_irq_is_level(irq_line) && - !(pci_irq_hold[irq_line] & (1ULL << card))) { + if (level && !(pci_irq_hold[irq_line] & (1ULL << card))) { /* IRQ not held, do nothing. */ pci_log("pci_clear_irq(%02X, %02X): Card is not holding the IRQ\n", card, pci_int); return; } - if (pci_type & PCI_NO_IRQ_STEERING) - level = 0; /* PCI without IRQ steering - IRQ always edge. */ - else - level = 1; /* PCI with IRQ steering - IRQ always level per the Intel datasheets. */ if (level) { pci_log("pci_clear_irq(%02X, %02X): Releasing this card's hold on the IRQ\n", card, pci_int); pci_irq_hold[irq_line] &= ~(1 << card); @@ -559,6 +566,13 @@ pci_clear_irq(uint8_t card, uint8_t pci_int) } +void +pci_elcr_set_enabled(int enabled) +{ + elcr_enabled = enabled; +} + + void pci_reset(void) { @@ -635,7 +649,10 @@ trc_write(uint16_t port, uint8_t val, void *priv) if (!(trc_reg & 4) && (val & 4)) trc_reset(val); - trc_reg = val & 0xfb; + trc_reg = val & 0xfd; + + if (val & 2) + trc_reg &= 0xfb; } @@ -681,13 +698,17 @@ pci_init(int type) pci_type2_read,NULL,NULL, pci_type2_write,NULL,NULL, NULL); } - for (c = 0; c < 4; c++) + for (c = 0; c < 4; c++) { pci_irqs[c] = PCI_IRQ_DISABLED; + pci_irq_level[c] = (type & PCI_NO_IRQ_STEERING) ? 0 : 1; + } for (c = 0; c < 3; c++) { pci_mirqs[c].enabled = 0; pci_mirqs[c].irq_line = PCI_IRQ_DISABLED; } + + elcr_enabled = 1; } diff --git a/src/pci.h b/src/pci.h index be7347757..18a93d9fb 100644 --- a/src/pci.h +++ b/src/pci.h @@ -8,15 +8,15 @@ * * Definitions for the PCI handler module. * - * Version: @(#)pci.h 1.0.1 2019/10/30 + * Version: @(#)pci.h 1.0.2 2020/01/11 * * Authors: Miran Grca, * Fred N. van Kempen, * Sarah Walker, * - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2008-2020 Sarah Walker. */ #ifndef EMU_PCI_H # define EMU_PCI_H @@ -68,6 +68,7 @@ extern int pci_burst_time, extern void pci_set_irq_routing(int pci_int, int irq); +extern void pci_set_irq_level(int pci_int, int level); extern void pci_enable_mirq(int mirq); extern void pci_set_mirq_routing(int mirq, int irq); @@ -89,6 +90,7 @@ extern void pci_close(void); extern uint8_t pci_add_card(uint8_t add_type, uint8_t (*read)(int func, int addr, void *priv), void (*write)(int func, int addr, uint8_t val, void *priv), void *priv); extern void trc_init(void); +extern void pci_elcr_set_enabled(int enabled); #endif /*EMU_PCI_H*/ From 329a38be8f3c678e860429bb326b4a75bb2170d1 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 11 Jan 2020 22:32:19 +0100 Subject: [PATCH 040/177] Added FDC enable/disable to the SMC FDC73C66x family of Super I/O chips. --- src/sio_fdc37c66x.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/sio_fdc37c66x.c b/src/sio_fdc37c66x.c index 21003e648..c1560f920 100644 --- a/src/sio_fdc37c66x.c +++ b/src/sio_fdc37c66x.c @@ -9,13 +9,13 @@ * Implementation of the SMC FDC37C663 and FDC37C665 Super * I/O Chips. * - * Version: @(#)sio_fdc37c66x.c 1.0.14 2018/11/12 + * Version: @(#)sio_fdc37c66x.c 1.0.15 2020/01/11 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -129,7 +129,17 @@ lpt1_handler(fdc37c66x_t *dev) } -static void fdc37c66x_write(uint16_t port, uint8_t val, void *priv) +static void +fdc_handler(fdc37c66x_t *dev) +{ + fdc_remove(dev->fdc); + if (dev->regs[0] & 0x10) + fdc_set_base(dev->fdc, (dev->regs[5] & 0x01) ? 0x0370 : 0x03f0); +} + + +static void +fdc37c66x_write(uint16_t port, uint8_t val, void *priv) { fdc37c66x_t *dev = (fdc37c66x_t *) priv; uint8_t valxor = 0; @@ -148,6 +158,10 @@ static void fdc37c66x_write(uint16_t port, uint8_t val, void *priv) dev->regs[dev->cur_reg] = val; switch(dev->cur_reg) { + case 0: + if (valxor & 0x10) + fdc_handler(dev); + break; case 1: if (valxor & 3) lpt1_handler(dev); @@ -173,7 +187,9 @@ static void fdc37c66x_write(uint16_t port, uint8_t val, void *priv) if (valxor & 2) fdc_update_enh_mode(dev->fdc, (dev->regs[3] & 2) ? 1 : 0); break; - case 5: + case 5: + if (valxor & 0x01) + fdc_handler(dev); if (valxor & 0x18) fdc_update_densel_force(dev->fdc, (dev->regs[5] & 0x18) >> 3); if (valxor & 0x20) From 92e90982a0872912eef0c5c047c785335d54d914 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 11 Jan 2020 22:32:57 +0100 Subject: [PATCH 041/177] Fixed legacy mode on the Winbond W83877F and TF Super I/O chips. --- src/sio_w83877f.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/sio_w83877f.c b/src/sio_w83877f.c index 98d514c32..69ad67286 100644 --- a/src/sio_w83877f.c +++ b/src/sio_w83877f.c @@ -11,10 +11,10 @@ * Winbond W83877F Super I/O Chip * Used by the Award 430HX * - * Version: @(#)sio_w83877f.c 1.0.15 2019/05/17 + * Version: @(#)sio_w83877f.c 1.0.16 2020/01/11 * * Author: Miran Grca, - * Copyright 2016-2018 Miran Grca. + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -167,12 +167,21 @@ static void w83877f_write(uint16_t port, uint8_t val, void *priv) { w83877f_t *dev = (w83877f_t *) priv; - uint8_t index = (port & 1) ? 0 : 1; uint8_t valxor = 0; uint8_t max = 0x2A; uint8_t lpt_irq; - if (index) { + if (port == 0x250) { + if (val == dev->key) + dev->locked = 1; + else + dev->locked = 0; + return; + } else if (port == 0x251) { + if (val <= max) + dev->cur_reg = val; + return; + } else if (port == 0x03f0) { if ((val == dev->key) && !dev->locked) { if (dev->key_times == 2) { if (dev->tries) { @@ -196,7 +205,7 @@ w83877f_write(uint16_t port, uint8_t val, void *priv) } } return; - } else { + } else if ((port == 0x252) || (port == 0x3f1)) { if (dev->locked) { if (dev->rw_locked) return; @@ -214,7 +223,7 @@ w83877f_write(uint16_t port, uint8_t val, void *priv) switch (dev->cur_reg) { case 0: - if (valxor & 0xc0) { + if (valxor & 0x0c) { lpt1_remove(); if (!(dev->regs[4] & 0x80)) lpt1_init(make_port(dev, 0x23)); @@ -340,12 +349,11 @@ w83877f_read(uint16_t port, void *priv) { w83877f_t *dev = (w83877f_t *) priv; uint8_t ret = 0xff; - uint8_t index = (port & 1) ? 0 : 1; if (dev->locked) { - if (index) + if ((port == 0x3f0) || (port == 0x251)) ret = dev->cur_reg; - else { + else if ((port == 0x3f1) || (port == 0x252)) { if (dev->cur_reg == 7) ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2)); else if ((dev->cur_reg >= 0x18) || !dev->rw_locked) From 4076f4b6713725ce9dec5e51df0902674c929c4e Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 11 Jan 2020 22:33:34 +0100 Subject: [PATCH 042/177] Fixed a mistake in the Cirrus Logic CL-GD 54xx code that was preventing the CL-GD 5446 from working on NT 5.x. --- src/video/vid_cl54xx.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 615e3cf5b..0ca557bd8 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -9,13 +9,13 @@ * Emulation of select Cirrus Logic cards (CL-GD 5428, * CL-GD 5429, CL-GD 5430, CL-GD 5434 and CL-GD 5436 are supported). * - * Version: @(#)vid_cl_54xx.c 1.0.31 2019/12/03 + * Version: @(#)vid_cl_54xx.c 1.0.32 2020/01/11 * * Authors: TheCollector1995, * Miran Grca, * - * Copyright 2016-2019 TheCollector1995. - * Copyright 2016-2019 Miran Grca. + * Copyright 2016-2020 TheCollector1995. + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -334,7 +334,7 @@ gd54xx_out(uint16_t addr, uint8_t val, void *p) if (val == 0x12) svga->seqregs[6] = 0x12; else - svga->seqregs[6] = (svga->crtc[0x27] >= CIRRUS_ID_CLGD5446) ? 0xff : 0x0f; + svga->seqregs[6] = 0x0f; if (svga->crtc[0x27] < CIRRUS_ID_CLGD5429) gd54xx->unlocked = (svga->seqregs[6] == 0x12); break; From f0755c1d98b57142784455b6eb8912bf386a4d4c Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 11 Jan 2020 22:36:18 +0100 Subject: [PATCH 043/177] Fixed a compile-breaking mistake in keyboard_at.c. --- src/keyboard_at.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/keyboard_at.c b/src/keyboard_at.c index d174585c6..7da1c4380 100644 --- a/src/keyboard_at.c +++ b/src/keyboard_at.c @@ -8,15 +8,15 @@ * * Intel 8042 (AT keyboard controller) emulation. * - * Version: @(#)keyboard_at.c 1.0.45 2019/11/15 + * Version: @(#)keyboard_at.c 1.0.46 2020/01/11 * * Authors: Sarah Walker, * Miran Grca, * Fred N. van Kempen, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. */ #include #include @@ -668,7 +668,7 @@ kbd_poll(void *priv) dev->out_new = mouse_queue[mouse_queue_start] | 0x100; mouse_queue_start = (mouse_queue_start + 1) & 0xf; } else if (!(dev->status&STAT_OFULL) && dev->out_new == -1 && - !(dev->mem[0]&0x10) && (key_queue_start != key_queue_end) && !kbc_busy) { + !(dev->mem[0]&0x10) && (key_queue_start != key_queue_end)) { dev->out_new = key_queue[key_queue_start]; key_queue_start = (key_queue_start + 1) & 0xf; } From 391e71c236de84f7a10606a506a6fe8a735bd80b Mon Sep 17 00:00:00 2001 From: Melissa Goad Date: Sun, 12 Jan 2020 01:04:05 -0600 Subject: [PATCH 044/177] Initial SMM (System Management Mode) emulation --- src/apm_new.c | 121 ++++++++++++++++++++ src/cpu_new/386_dynarec.c | 229 ++++++++++++++++++++++++++++++++++++- src/cpu_new/386_ops.h | 64 +++++------ src/cpu_new/cpu.c | 3 + src/cpu_new/cpu.h | 5 + src/cpu_new/x86_ops_misc.h | 12 ++ src/mem.h | 2 + src/mem_new.c | 40 ++++++- src/win/Makefile_ndr.mingw | 2 +- 9 files changed, 441 insertions(+), 37 deletions(-) create mode 100644 src/apm_new.c diff --git a/src/apm_new.c b/src/apm_new.c new file mode 100644 index 000000000..a0963cade --- /dev/null +++ b/src/apm_new.c @@ -0,0 +1,121 @@ +/* + * 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. + * + * Advanced Power Management emulation. + * + * Version: @(#)apm.c 1.0.0 2019/05/12 + * + * Authors: Miran Grca, + * + * Copyright 2019 Miran Grca. + */ +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include "86box.h" +#include "cpu_new/cpu.h" +#include "device.h" +#include "io.h" + + +typedef struct +{ + uint8_t cmd, + stat; +} apm_t; + + +#ifdef ENABLE_APM_LOG +int apm_do_log = ENABLE_APM_LOG; + + +static void +apm_log(const char *fmt, ...) +{ + va_list ap; + + if (apm_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define apm_log(fmt, ...) +#endif + + +static void +apm_out(uint16_t port, uint8_t val, void *p) +{ + apm_t *apm = (apm_t *) p; + + apm_log("[%04X:%08X] APM write: %04X = %02X (BX = %04X, CX = %04X)\n", CS, cpu_state.pc, port, val, BX, CX); + + port &= 0x0001; + + if (port == 0x0000) apm->cmd = val; + else apm->stat = val; + + smi_line = 1; +} + + +static uint8_t +apm_in(uint16_t port, void *p) +{ + apm_t *apm = (apm_t *) p; + + apm_log("[%04X:%08X] APM read: %04X = FF\n", CS, cpu_state.pc, port); + + port &= 0x0001; + + if (port == 0x0000) + return apm->cmd; + else + return apm->stat; +} + + +static void +apm_close(void *p) +{ + apm_t *dev = (apm_t *)p; + + free(dev); +} + + +static void +*apm_init(const device_t *info) +{ + apm_t *apm = (apm_t *) malloc(sizeof(apm_t)); + memset(apm, 0, sizeof(apm_t)); + + io_sethandler(0x00b2, 0x0002, apm_in, NULL, NULL, apm_out, NULL, NULL, apm); + + return apm; +} + + +const device_t apm_device = +{ + "Advanced Power Management", + 0, + 0, + apm_init, + apm_close, + NULL, + NULL, + NULL, + NULL, + NULL +}; diff --git a/src/cpu_new/386_dynarec.c b/src/cpu_new/386_dynarec.c index cbd8f063e..0081aceb8 100644 --- a/src/cpu_new/386_dynarec.c +++ b/src/cpu_new/386_dynarec.c @@ -260,13 +260,222 @@ static void prefetch_flush() #define PREFETCH_FLUSH() prefetch_flush() +void enter_smm() +{ + uint32_t smram_state = smbase + 0xfe00; + uint32_t old_cr0 = cr0; + uint32_t old_flags = cpu_state.flags | ((uint32_t)cpu_state.eflags << 16); + + cr0 &= ~0x8000000d; + cpu_state.flags = 2; + cpu_state.eflags = 0; + + in_smm = 1; + smi_latched = 1; + + mem_writel_phys(smram_state + 0xf8, smbase); + mem_writel_phys(smram_state + 0x128, cr4); + mem_writel_phys(smram_state + 0x130, cpu_state.seg_es.limit); + mem_writel_phys(smram_state + 0x134, cpu_state.seg_es.base); + mem_writel_phys(smram_state + 0x138, cpu_state.seg_es.access); + mem_writel_phys(smram_state + 0x13c, cpu_state.seg_cs.limit); + mem_writel_phys(smram_state + 0x140, cpu_state.seg_cs.base); + mem_writel_phys(smram_state + 0x144, cpu_state.seg_cs.access); + mem_writel_phys(smram_state + 0x148, cpu_state.seg_ss.limit); + mem_writel_phys(smram_state + 0x14c, cpu_state.seg_ss.base); + mem_writel_phys(smram_state + 0x150, cpu_state.seg_ss.access); + mem_writel_phys(smram_state + 0x154, cpu_state.seg_ds.limit); + mem_writel_phys(smram_state + 0x158, cpu_state.seg_ds.base); + mem_writel_phys(smram_state + 0x15c, cpu_state.seg_ds.access); + mem_writel_phys(smram_state + 0x160, cpu_state.seg_fs.limit); + mem_writel_phys(smram_state + 0x164, cpu_state.seg_fs.base); + mem_writel_phys(smram_state + 0x168, cpu_state.seg_fs.access); + mem_writel_phys(smram_state + 0x16c, cpu_state.seg_gs.limit); + mem_writel_phys(smram_state + 0x170, cpu_state.seg_gs.base); + mem_writel_phys(smram_state + 0x174, cpu_state.seg_gs.access); + mem_writel_phys(smram_state + 0x178, ldt.limit); + mem_writel_phys(smram_state + 0x17c, ldt.base); + mem_writel_phys(smram_state + 0x180, ldt.access); + mem_writel_phys(smram_state + 0x184, gdt.limit); + mem_writel_phys(smram_state + 0x188, gdt.base); + mem_writel_phys(smram_state + 0x18c, gdt.access); + mem_writel_phys(smram_state + 0x190, idt.limit); + mem_writel_phys(smram_state + 0x194, idt.base); + mem_writel_phys(smram_state + 0x198, idt.access); + mem_writel_phys(smram_state + 0x19c, tr.limit); + mem_writel_phys(smram_state + 0x1a0, tr.base); + mem_writel_phys(smram_state + 0x1a4, tr.access); + + mem_writel_phys(smram_state + 0x1a8, cpu_state.seg_es.seg); + mem_writel_phys(smram_state + 0x1ac, cpu_state.seg_cs.seg); + mem_writel_phys(smram_state + 0x1b0, cpu_state.seg_ss.seg); + mem_writel_phys(smram_state + 0x1b4, cpu_state.seg_ds.seg); + mem_writel_phys(smram_state + 0x1b8, cpu_state.seg_fs.seg); + mem_writel_phys(smram_state + 0x1bc, cpu_state.seg_gs.seg); + mem_writel_phys(smram_state + 0x1c0, ldt.seg); + mem_writel_phys(smram_state + 0x1c4, tr.seg); + + mem_writel_phys(smram_state + 0x1c8, dr[7]); + mem_writel_phys(smram_state + 0x1cc, dr[6]); + mem_writel_phys(smram_state + 0x1d0, EAX); + mem_writel_phys(smram_state + 0x1d4, ECX); + mem_writel_phys(smram_state + 0x1d8, EDX); + mem_writel_phys(smram_state + 0x1dc, EBX); + mem_writel_phys(smram_state + 0x1e0, ESP); + mem_writel_phys(smram_state + 0x1e4, EBP); + mem_writel_phys(smram_state + 0x1e8, ESI); + mem_writel_phys(smram_state + 0x1ec, EDI); + mem_writel_phys(smram_state + 0x1f0, cpu_state.pc); + mem_writel_phys(smram_state + 0x1d0, old_flags); + mem_writel_phys(smram_state + 0x1f8, cr3); + mem_writel_phys(smram_state + 0x1fc, old_cr0); + + ds = es = fs_seg = gs = ss = 0; + + DS = ES = FS = GS = SS = 0; + + cpu_state.seg_ds.limit = cpu_state.seg_es.limit = cpu_state.seg_fs.limit = cpu_state.seg_gs.limit + = cpu_state.seg_ss.limit = 0xffffffff; + + cpu_state.seg_ds.limit_high = cpu_state.seg_es.limit_high = cpu_state.seg_fs.limit_high + = cpu_state.seg_gs.limit_high = cpu_state.seg_ss.limit_high = 0xffffffff; + + cpu_state.seg_ds.limit_low = cpu_state.seg_es.limit_low = cpu_state.seg_fs.limit_low + = cpu_state.seg_gs.limit_low = cpu_state.seg_ss.limit_low = 0; + + cpu_state.seg_ds.access = cpu_state.seg_es.access = cpu_state.seg_fs.access + = cpu_state.seg_gs.access = cpu_state.seg_ss.access = 0x93; + + cpu_state.seg_ds.checked = cpu_state.seg_es.checked = cpu_state.seg_fs.checked + = cpu_state.seg_gs.checked = cpu_state.seg_ss.checked = 1; + + CS = 0x3000; + cs = smbase; + cpu_state.seg_cs.limit = cpu_state.seg_cs.limit_high = 0xffffffff; + cpu_state.seg_cs.limit_low = 0; + cpu_state.seg_cs.access = 0x93; + cpu_state.seg_cs.checked = 1; + + cr4 = 0; + dr[7] = 0x400; + cpu_state.pc = 0x8000; + + nmi_mask = 0; +} + +void leave_smm() +{ + uint32_t smram_state = smbase + 0xfe00; + + smbase = mem_readl_phys(smram_state + 0xf8); + cr4 = mem_readl_phys(smram_state + 0x128); + + cpu_state.seg_es.limit = cpu_state.seg_es.limit_high = mem_readl_phys(smram_state + 0x130); + cpu_state.seg_es.base = mem_readl_phys(smram_state + 0x134); + cpu_state.seg_es.limit_low = cpu_state.seg_es.base; + cpu_state.seg_es.access = mem_readl_phys(smram_state + 0x138); + + cpu_state.seg_cs.limit = cpu_state.seg_cs.limit_high = mem_readl_phys(smram_state + 0x13c); + cpu_state.seg_cs.base = mem_readl_phys(smram_state + 0x140); + cpu_state.seg_cs.limit_low = cpu_state.seg_cs.base; + cpu_state.seg_cs.access = mem_readl_phys(smram_state + 0x144); + + cpu_state.seg_ss.limit = cpu_state.seg_ss.limit_high = mem_readl_phys(smram_state + 0x148); + cpu_state.seg_ss.base = mem_readl_phys(smram_state + 0x14c); + cpu_state.seg_ss.limit_low = cpu_state.seg_ss.base; + cpu_state.seg_ss.access = mem_readl_phys(smram_state + 0x150); + + cpu_state.seg_ds.limit = cpu_state.seg_ds.limit_high = mem_readl_phys(smram_state + 0x154); + cpu_state.seg_ds.base = mem_readl_phys(smram_state + 0x158); + cpu_state.seg_ds.limit_low = cpu_state.seg_ds.base; + cpu_state.seg_ds.access = mem_readl_phys(smram_state + 0x15c); + + cpu_state.seg_fs.limit = cpu_state.seg_fs.limit_high = mem_readl_phys(smram_state + 0x160); + cpu_state.seg_fs.base = mem_readl_phys(smram_state + 0x164); + cpu_state.seg_fs.limit_low = cpu_state.seg_fs.base; + cpu_state.seg_fs.access = mem_readl_phys(smram_state + 0x168); + + cpu_state.seg_gs.limit = cpu_state.seg_gs.limit_high = mem_readl_phys(smram_state + 0x16c); + cpu_state.seg_gs.base = mem_readl_phys(smram_state + 0x170); + cpu_state.seg_gs.limit_low = cpu_state.seg_gs.base; + cpu_state.seg_gs.access = mem_readl_phys(smram_state + 0x174); + + ldt.limit = ldt.limit_high = mem_readl_phys(smram_state + 0x178); + ldt.base = mem_readl_phys(smram_state + 0x17c); + ldt.limit_low = ldt.base; + ldt.access = mem_readl_phys(smram_state + 0x180); + + gdt.limit = gdt.limit_high = mem_readl_phys(smram_state + 0x184); + gdt.base = mem_readl_phys(smram_state + 0x188); + gdt.limit_low = gdt.base; + gdt.access = mem_readl_phys(smram_state + 0x18c); + + idt.limit = idt.limit_high = mem_readl_phys(smram_state + 0x190); + idt.base = mem_readl_phys(smram_state + 0x194); + idt.limit_low = idt.base; + idt.access = mem_readl_phys(smram_state + 0x198); + + tr.limit = tr.limit_high = mem_readl_phys(smram_state + 0x19c); + tr.base = mem_readl_phys(smram_state + 0x1a0); + tr.limit_low = tr.base; + tr.access = mem_readl_phys(smram_state + 0x1a4); + + ES = mem_readl_phys(smram_state + 0x1a8); + CS = mem_readl_phys(smram_state + 0x1ac); + SS = mem_readl_phys(smram_state + 0x1b0); + DS = mem_readl_phys(smram_state + 0x1b4); + FS = mem_readl_phys(smram_state + 0x1b8); + GS = mem_readl_phys(smram_state + 0x1bc); + ldt.seg = mem_readl_phys(smram_state + 0x1c0); + tr.seg = mem_readl_phys(smram_state + 0x1c4); + + dr[7] = mem_readl_phys(smram_state + 0x1c8); + dr[6] = mem_readl_phys(smram_state + 0x1cc); + EAX = mem_readl_phys(smram_state + 0x1d0); + ECX = mem_readl_phys(smram_state + 0x1d4); + EDX = mem_readl_phys(smram_state + 0x1d8); + EBX = mem_readl_phys(smram_state + 0x1dc); + ESP = mem_readl_phys(smram_state + 0x1e0); + EBP = mem_readl_phys(smram_state + 0x1e4); + ESI = mem_readl_phys(smram_state + 0x1e8); + EDI = mem_readl_phys(smram_state + 0x1ec); + + cpu_state.pc = mem_readl_phys(smram_state + 0x1f0); + uint32_t new_flags = mem_readl_phys(smram_state + 0x1f4); + cpu_state.flags = new_flags & 0xffff; + cpu_state.eflags = new_flags >> 16; + cr3 = mem_readl_phys(smram_state + 0x1f8); + cr0 = mem_readl_phys(smram_state + 0x1fc); + + cpu_state.seg_cs.access &= ~0x60; + cpu_state.seg_cs.access |= cpu_state.seg_ss.access & 0x60; //cpl is dpl of ss + + if((cr0 & 1) && !(cpu_state.eflags&VM_FLAG)) + { + cpu_state.seg_cs.checked = CS ? 1 : 0; + cpu_state.seg_ds.checked = DS ? 1 : 0; + cpu_state.seg_es.checked = ES ? 1 : 0; + cpu_state.seg_fs.checked = FS ? 1 : 0; + cpu_state.seg_gs.checked = GS ? 1 : 0; + cpu_state.seg_ss.checked = SS ? 1 : 0; + } + else + { + cpu_state.seg_cs.checked = cpu_state.seg_ds.checked = cpu_state.seg_es.checked + = cpu_state.seg_fs.checked = cpu_state.seg_gs.checked = cpu_state.seg_ss.checked = 1; + } + + in_smm = 0; + + nmi_mask = 1; +} + #define OP_TABLE(name) ops_ ## name #define CLOCK_CYCLES(c) cycles -= (c) #define CLOCK_CYCLES_ALWAYS(c) cycles -= (c) #include "386_ops.h" - #define CACHE_ON() (!(cr0 & (1 << 30)) && !(cpu_state.flags & T_FLAG)) #ifdef USE_DYNAREC @@ -320,6 +529,9 @@ void exec386_dynarec(int cycs) if (((cs + cpu_state.pc) >> 12) != pccache) CPU_BLOCK_END(); + if (in_smm && smi_line && is_pentium) + CPU_BLOCK_END(); + if (cpu_state.abrt) CPU_BLOCK_END(); if (trap) @@ -473,6 +685,9 @@ void exec386_dynarec(int cycs) hit, as host block size is only 2kB*/ if (((cs+cpu_state.pc) - start_pc) >= max_block_size) CPU_BLOCK_END(); + + if (in_smm && smi_line && is_pentium) + CPU_BLOCK_END(); if (trap) CPU_BLOCK_END(); @@ -540,6 +755,9 @@ void exec386_dynarec(int cycs) hit, as host block size is only 2kB*/ if (((cs+cpu_state.pc) - start_pc) >= max_block_size) CPU_BLOCK_END(); + + if (in_smm && smi_line && is_pentium) + CPU_BLOCK_END(); if (trap) CPU_BLOCK_END(); @@ -593,8 +811,13 @@ void exec386_dynarec(int cycs) } } } - - if (trap) + + if (in_smm && smi_line && is_pentium) + { + enter_smm(); + } + + else if (trap) { trap = 0; flags_rebuild(); diff --git a/src/cpu_new/386_ops.h b/src/cpu_new/386_ops.h index f2c54c0ce..b3d331423 100644 --- a/src/cpu_new/386_ops.h +++ b/src/cpu_new/386_ops.h @@ -739,7 +739,7 @@ const OpFn OP_TABLE(pentium_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, /*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -761,7 +761,7 @@ const OpFn OP_TABLE(pentium_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, /*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -783,7 +783,7 @@ const OpFn OP_TABLE(pentium_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, /*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -805,7 +805,7 @@ const OpFn OP_TABLE(pentium_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, /*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -830,7 +830,7 @@ const OpFn OP_TABLE(pentiummmx_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, /*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -852,7 +852,7 @@ const OpFn OP_TABLE(pentiummmx_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, /*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -874,7 +874,7 @@ const OpFn OP_TABLE(pentiummmx_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, /*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -896,7 +896,7 @@ const OpFn OP_TABLE(pentiummmx_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, /*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -921,7 +921,7 @@ const OpFn OP_TABLE(k6_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, /*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -943,7 +943,7 @@ const OpFn OP_TABLE(k6_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, /*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -965,7 +965,7 @@ const OpFn OP_TABLE(k6_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, /*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -987,7 +987,7 @@ const OpFn OP_TABLE(k6_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, /*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -1012,7 +1012,7 @@ const OpFn OP_TABLE(k62_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, /*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -1034,7 +1034,7 @@ const OpFn OP_TABLE(k62_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, /*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -1056,7 +1056,7 @@ const OpFn OP_TABLE(k62_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, /*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -1078,7 +1078,7 @@ const OpFn OP_TABLE(k62_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, /*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -1103,7 +1103,7 @@ const OpFn OP_TABLE(c6x86mx_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, /*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -1125,7 +1125,7 @@ const OpFn OP_TABLE(c6x86mx_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, /*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -1147,7 +1147,7 @@ const OpFn OP_TABLE(c6x86mx_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, /*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -1169,7 +1169,7 @@ const OpFn OP_TABLE(c6x86mx_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, /*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -1196,7 +1196,7 @@ const OpFn OP_TABLE(pentiumpro_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, /*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -1218,7 +1218,7 @@ const OpFn OP_TABLE(pentiumpro_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, /*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -1240,7 +1240,7 @@ const OpFn OP_TABLE(pentiumpro_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, /*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -1262,7 +1262,7 @@ const OpFn OP_TABLE(pentiumpro_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, /*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -1288,7 +1288,7 @@ const OpFn OP_TABLE(pentium2_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, /*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -1310,7 +1310,7 @@ const OpFn OP_TABLE(pentium2_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, /*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -1332,7 +1332,7 @@ const OpFn OP_TABLE(pentium2_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, /*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -1354,7 +1354,7 @@ const OpFn OP_TABLE(pentium2_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, /*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -1380,7 +1380,7 @@ const OpFn OP_TABLE(pentium2d_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,opFXSAVESTOR_a16,opIMUL_w_w_a16, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,opFXSAVESTOR_a16,opIMUL_w_w_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, /*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -1402,7 +1402,7 @@ const OpFn OP_TABLE(pentium2d_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,opFXSAVESTOR_a16,opIMUL_l_l_a16, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,opFXSAVESTOR_a16,opIMUL_l_l_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, /*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -1424,7 +1424,7 @@ const OpFn OP_TABLE(pentium2d_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,opFXSAVESTOR_a32,opIMUL_w_w_a32, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,opFXSAVESTOR_a32,opIMUL_w_w_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, /*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -1446,7 +1446,7 @@ const OpFn OP_TABLE(pentium2d_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,opFXSAVESTOR_a32,opIMUL_l_l_a32, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,opFXSAVESTOR_a32,opIMUL_l_l_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, /*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, diff --git a/src/cpu_new/cpu.c b/src/cpu_new/cpu.c index 16edc0af7..a92d77307 100644 --- a/src/cpu_new/cpu.c +++ b/src/cpu_new/cpu.c @@ -128,6 +128,9 @@ const OpFn *x86_opcodes_REPE; const OpFn *x86_opcodes_REPNE; const OpFn *x86_opcodes_3DNOW; +int in_smm = 0, smi_line = 0, smi_latched = 0; +uint32_t smbase = 0x30000; + CPU *cpu_s; int cpu_effective; int cpu_multi; diff --git a/src/cpu_new/cpu.h b/src/cpu_new/cpu.h index 578c25f18..949aba2ef 100644 --- a/src/cpu_new/cpu.h +++ b/src/cpu_new/cpu.h @@ -343,6 +343,9 @@ extern int hasfpu; extern uint32_t cpu_features; +extern int in_smm, smi_line, smi_latched; +extern uint32_t smbase; + extern uint16_t cpu_cur_status; extern uint64_t cpu_CR4_mask; extern uint64_t tsc; @@ -457,6 +460,8 @@ extern void codegen_reset(void); extern void cpu_set_edx(void); extern int divl(uint32_t val); extern void execx86(int cycs); +extern void enter_smm(); +extern void leave_smm(); extern void exec386(int cycs); extern void exec386_dynarec(int cycs); extern int idivl(int32_t val); diff --git a/src/cpu_new/x86_ops_misc.h b/src/cpu_new/x86_ops_misc.h index 6ecfe268a..f8db6c592 100644 --- a/src/cpu_new/x86_ops_misc.h +++ b/src/cpu_new/x86_ops_misc.h @@ -957,3 +957,15 @@ static int opWRMSR(uint32_t fetchdat) return 1; } +static int opRSM(uint32_t fetchdat) +{ + if(!in_smm) + { + leave_smm(); + if(smi_latched) enter_smm(); + return 0; + } + cpu_state.pc = cpu_state.oldpc; + x86illegal(); + return 1; +} \ No newline at end of file diff --git a/src/mem.h b/src/mem.h index 64d851b30..6b5641ee6 100644 --- a/src/mem.h +++ b/src/mem.h @@ -265,7 +265,9 @@ extern void mem_set_mem_state(uint32_t base, uint32_t size, int state); extern uint8_t mem_readb_phys(uint32_t addr); extern uint16_t mem_readw_phys(uint32_t addr); +extern uint32_t mem_readl_phys(uint32_t addr); extern void mem_writeb_phys(uint32_t addr, uint8_t val); +extern void mem_writel_phys(uint32_t addr, uint32_t val); extern uint8_t mem_read_ram(uint32_t addr, void *priv); extern uint16_t mem_read_ramw(uint32_t addr, void *priv); diff --git a/src/mem_new.c b/src/mem_new.c index 199c7cd20..4fd4dbc91 100644 --- a/src/mem_new.c +++ b/src/mem_new.c @@ -870,6 +870,26 @@ mem_readw_phys(uint32_t addr) return temp; } +uint32_t +mem_readl_phys(uint32_t addr) +{ + mem_mapping_t *map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + uint32_t temp; + + if (_mem_exec[addr >> MEM_GRANULARITY_BITS]) + return ((uint32_t *) _mem_exec[addr >> MEM_GRANULARITY_BITS])[(addr >> 1) & MEM_GRANULARITY_HMASK]; + else if (map && map->read_l) + return map->read_l(addr, map->p); + else { + temp = mem_readb_phys(addr + 3) << 24; + temp |= mem_readb_phys(addr + 2) << 16; + temp |= mem_readb_phys(addr + 1) << 8; + temp |= mem_readb_phys(addr); + } + + return temp; +} + void mem_writeb_phys(uint32_t addr, uint8_t val) @@ -882,6 +902,23 @@ mem_writeb_phys(uint32_t addr, uint8_t val) map->write_b(addr, val, map->p); } +void +mem_writel_phys(uint32_t addr, uint32_t val) +{ + mem_mapping_t *map = write_mapping[addr >> MEM_GRANULARITY_BITS]; + + if (_mem_exec[addr >> MEM_GRANULARITY_BITS]) + _mem_exec[addr >> MEM_GRANULARITY_BITS][addr & MEM_GRANULARITY_MASK] = val; + else if (map && map->write_l) + map->write_l(addr, val, map->p); + else + { + mem_writeb_phys(addr, val & 0xff); + mem_writeb_phys(addr + 1, (val >> 8) & 0xff); + mem_writeb_phys(addr + 2, (val >> 16) & 0xff); + mem_writeb_phys(addr + 3, (val >> 24) & 0xff); + } +} uint8_t mem_read_ram(uint32_t addr, void *priv) @@ -1574,7 +1611,8 @@ mem_log("MEM: reset: new pages=%08lx, pages_sz=%i\n", pages, pages_sz); memset(page_lookup, 0x00, (1 << 20) * sizeof(page_t *)); #endif - memset(pages, 0x00, pages_sz*sizeof(page_t)); + memset(pages, 0x00, pages_sz*sizeof(page_t)); + if (byte_dirty_mask) { free(byte_dirty_mask); diff --git a/src/win/Makefile_ndr.mingw b/src/win/Makefile_ndr.mingw index 560d6fdbb..facc55327 100644 --- a/src/win/Makefile_ndr.mingw +++ b/src/win/Makefile_ndr.mingw @@ -547,7 +547,7 @@ CXXFLAGS := $(CFLAGS) ######################################################################### # Create the (final) list of objects to build. # ######################################################################### -MAINOBJ := pc.o config.o random.o timer.o io.o apm.o dma.o nmi.o \ +MAINOBJ := pc.o config.o random.o timer.o io.o apm_new.o dma.o nmi.o \ pic.o pit.o port_92.o ppi.o pci.o mca.o mcr.o mem_new.o \ rom.o device.o nvr.o nvr_at.o nvr_ps2.o $(VNCOBJ) $(RDPOBJ) From fa6adf3b900d712f80df3d83f089c1a5eaf182f4 Mon Sep 17 00:00:00 2001 From: Melissa Goad Date: Sun, 12 Jan 2020 10:10:13 -0600 Subject: [PATCH 045/177] Make it work for the old dynarec too --- src/cpu/386_dynarec.c | 227 ++++++++++++++++++++++++++++++++++++++++- src/cpu/386_ops.h | 56 +++++----- src/cpu/cpu.c | 3 + src/cpu/cpu.h | 5 + src/cpu/x86_ops_misc.h | 97 ++++++++---------- src/mem.c | 42 +++++++- src/win/Makefile.mingw | 2 +- 7 files changed, 348 insertions(+), 84 deletions(-) diff --git a/src/cpu/386_dynarec.c b/src/cpu/386_dynarec.c index fab7e429c..7a26ae37d 100644 --- a/src/cpu/386_dynarec.c +++ b/src/cpu/386_dynarec.c @@ -499,6 +499,216 @@ int oldi; uint32_t testr[9]; int dontprint=0; +void enter_smm() +{ + uint32_t smram_state = smbase + 0xfe00; + uint32_t old_cr0 = cr0; + uint32_t old_flags = cpu_state.flags | ((uint32_t)cpu_state.eflags << 16); + + cr0 &= ~0x8000000d; + cpu_state.flags = 2; + cpu_state.eflags = 0; + + in_smm = 1; + smi_latched = 1; + + mem_writel_phys(smram_state + 0xf8, smbase); + mem_writel_phys(smram_state + 0x128, cr4); + mem_writel_phys(smram_state + 0x130, cpu_state.seg_es.limit); + mem_writel_phys(smram_state + 0x134, cpu_state.seg_es.base); + mem_writel_phys(smram_state + 0x138, cpu_state.seg_es.access); + mem_writel_phys(smram_state + 0x13c, cpu_state.seg_cs.limit); + mem_writel_phys(smram_state + 0x140, cpu_state.seg_cs.base); + mem_writel_phys(smram_state + 0x144, cpu_state.seg_cs.access); + mem_writel_phys(smram_state + 0x148, cpu_state.seg_ss.limit); + mem_writel_phys(smram_state + 0x14c, cpu_state.seg_ss.base); + mem_writel_phys(smram_state + 0x150, cpu_state.seg_ss.access); + mem_writel_phys(smram_state + 0x154, cpu_state.seg_ds.limit); + mem_writel_phys(smram_state + 0x158, cpu_state.seg_ds.base); + mem_writel_phys(smram_state + 0x15c, cpu_state.seg_ds.access); + mem_writel_phys(smram_state + 0x160, cpu_state.seg_fs.limit); + mem_writel_phys(smram_state + 0x164, cpu_state.seg_fs.base); + mem_writel_phys(smram_state + 0x168, cpu_state.seg_fs.access); + mem_writel_phys(smram_state + 0x16c, cpu_state.seg_gs.limit); + mem_writel_phys(smram_state + 0x170, cpu_state.seg_gs.base); + mem_writel_phys(smram_state + 0x174, cpu_state.seg_gs.access); + mem_writel_phys(smram_state + 0x178, ldt.limit); + mem_writel_phys(smram_state + 0x17c, ldt.base); + mem_writel_phys(smram_state + 0x180, ldt.access); + mem_writel_phys(smram_state + 0x184, gdt.limit); + mem_writel_phys(smram_state + 0x188, gdt.base); + mem_writel_phys(smram_state + 0x18c, gdt.access); + mem_writel_phys(smram_state + 0x190, idt.limit); + mem_writel_phys(smram_state + 0x194, idt.base); + mem_writel_phys(smram_state + 0x198, idt.access); + mem_writel_phys(smram_state + 0x19c, tr.limit); + mem_writel_phys(smram_state + 0x1a0, tr.base); + mem_writel_phys(smram_state + 0x1a4, tr.access); + + mem_writel_phys(smram_state + 0x1a8, cpu_state.seg_es.seg); + mem_writel_phys(smram_state + 0x1ac, cpu_state.seg_cs.seg); + mem_writel_phys(smram_state + 0x1b0, cpu_state.seg_ss.seg); + mem_writel_phys(smram_state + 0x1b4, cpu_state.seg_ds.seg); + mem_writel_phys(smram_state + 0x1b8, cpu_state.seg_fs.seg); + mem_writel_phys(smram_state + 0x1bc, cpu_state.seg_gs.seg); + mem_writel_phys(smram_state + 0x1c0, ldt.seg); + mem_writel_phys(smram_state + 0x1c4, tr.seg); + + mem_writel_phys(smram_state + 0x1c8, dr[7]); + mem_writel_phys(smram_state + 0x1cc, dr[6]); + mem_writel_phys(smram_state + 0x1d0, EAX); + mem_writel_phys(smram_state + 0x1d4, ECX); + mem_writel_phys(smram_state + 0x1d8, EDX); + mem_writel_phys(smram_state + 0x1dc, EBX); + mem_writel_phys(smram_state + 0x1e0, ESP); + mem_writel_phys(smram_state + 0x1e4, EBP); + mem_writel_phys(smram_state + 0x1e8, ESI); + mem_writel_phys(smram_state + 0x1ec, EDI); + mem_writel_phys(smram_state + 0x1f0, cpu_state.pc); + mem_writel_phys(smram_state + 0x1d0, old_flags); + mem_writel_phys(smram_state + 0x1f8, cr3); + mem_writel_phys(smram_state + 0x1fc, old_cr0); + + ds = es = fs_seg = gs = ss = 0; + + DS = ES = FS = GS = SS = 0; + + cpu_state.seg_ds.limit = cpu_state.seg_es.limit = cpu_state.seg_fs.limit = cpu_state.seg_gs.limit + = cpu_state.seg_ss.limit = 0xffffffff; + + cpu_state.seg_ds.limit_high = cpu_state.seg_es.limit_high = cpu_state.seg_fs.limit_high + = cpu_state.seg_gs.limit_high = cpu_state.seg_ss.limit_high = 0xffffffff; + + cpu_state.seg_ds.limit_low = cpu_state.seg_es.limit_low = cpu_state.seg_fs.limit_low + = cpu_state.seg_gs.limit_low = cpu_state.seg_ss.limit_low = 0; + + cpu_state.seg_ds.access = cpu_state.seg_es.access = cpu_state.seg_fs.access + = cpu_state.seg_gs.access = cpu_state.seg_ss.access = 0x93; + + cpu_state.seg_ds.checked = cpu_state.seg_es.checked = cpu_state.seg_fs.checked + = cpu_state.seg_gs.checked = cpu_state.seg_ss.checked = 1; + + CS = 0x3000; + cs = smbase; + cpu_state.seg_cs.limit = cpu_state.seg_cs.limit_high = 0xffffffff; + cpu_state.seg_cs.limit_low = 0; + cpu_state.seg_cs.access = 0x93; + cpu_state.seg_cs.checked = 1; + + cr4 = 0; + dr[7] = 0x400; + cpu_state.pc = 0x8000; + + nmi_mask = 0; +} + +void leave_smm() +{ + uint32_t smram_state = smbase + 0xfe00; + + smbase = mem_readl_phys(smram_state + 0xf8); + cr4 = mem_readl_phys(smram_state + 0x128); + + cpu_state.seg_es.limit = cpu_state.seg_es.limit_high = mem_readl_phys(smram_state + 0x130); + cpu_state.seg_es.base = mem_readl_phys(smram_state + 0x134); + cpu_state.seg_es.limit_low = cpu_state.seg_es.base; + cpu_state.seg_es.access = mem_readl_phys(smram_state + 0x138); + + cpu_state.seg_cs.limit = cpu_state.seg_cs.limit_high = mem_readl_phys(smram_state + 0x13c); + cpu_state.seg_cs.base = mem_readl_phys(smram_state + 0x140); + cpu_state.seg_cs.limit_low = cpu_state.seg_cs.base; + cpu_state.seg_cs.access = mem_readl_phys(smram_state + 0x144); + + cpu_state.seg_ss.limit = cpu_state.seg_ss.limit_high = mem_readl_phys(smram_state + 0x148); + cpu_state.seg_ss.base = mem_readl_phys(smram_state + 0x14c); + cpu_state.seg_ss.limit_low = cpu_state.seg_ss.base; + cpu_state.seg_ss.access = mem_readl_phys(smram_state + 0x150); + + cpu_state.seg_ds.limit = cpu_state.seg_ds.limit_high = mem_readl_phys(smram_state + 0x154); + cpu_state.seg_ds.base = mem_readl_phys(smram_state + 0x158); + cpu_state.seg_ds.limit_low = cpu_state.seg_ds.base; + cpu_state.seg_ds.access = mem_readl_phys(smram_state + 0x15c); + + cpu_state.seg_fs.limit = cpu_state.seg_fs.limit_high = mem_readl_phys(smram_state + 0x160); + cpu_state.seg_fs.base = mem_readl_phys(smram_state + 0x164); + cpu_state.seg_fs.limit_low = cpu_state.seg_fs.base; + cpu_state.seg_fs.access = mem_readl_phys(smram_state + 0x168); + + cpu_state.seg_gs.limit = cpu_state.seg_gs.limit_high = mem_readl_phys(smram_state + 0x16c); + cpu_state.seg_gs.base = mem_readl_phys(smram_state + 0x170); + cpu_state.seg_gs.limit_low = cpu_state.seg_gs.base; + cpu_state.seg_gs.access = mem_readl_phys(smram_state + 0x174); + + ldt.limit = ldt.limit_high = mem_readl_phys(smram_state + 0x178); + ldt.base = mem_readl_phys(smram_state + 0x17c); + ldt.limit_low = ldt.base; + ldt.access = mem_readl_phys(smram_state + 0x180); + + gdt.limit = gdt.limit_high = mem_readl_phys(smram_state + 0x184); + gdt.base = mem_readl_phys(smram_state + 0x188); + gdt.limit_low = gdt.base; + gdt.access = mem_readl_phys(smram_state + 0x18c); + + idt.limit = idt.limit_high = mem_readl_phys(smram_state + 0x190); + idt.base = mem_readl_phys(smram_state + 0x194); + idt.limit_low = idt.base; + idt.access = mem_readl_phys(smram_state + 0x198); + + tr.limit = tr.limit_high = mem_readl_phys(smram_state + 0x19c); + tr.base = mem_readl_phys(smram_state + 0x1a0); + tr.limit_low = tr.base; + tr.access = mem_readl_phys(smram_state + 0x1a4); + + ES = mem_readl_phys(smram_state + 0x1a8); + CS = mem_readl_phys(smram_state + 0x1ac); + SS = mem_readl_phys(smram_state + 0x1b0); + DS = mem_readl_phys(smram_state + 0x1b4); + FS = mem_readl_phys(smram_state + 0x1b8); + GS = mem_readl_phys(smram_state + 0x1bc); + ldt.seg = mem_readl_phys(smram_state + 0x1c0); + tr.seg = mem_readl_phys(smram_state + 0x1c4); + + dr[7] = mem_readl_phys(smram_state + 0x1c8); + dr[6] = mem_readl_phys(smram_state + 0x1cc); + EAX = mem_readl_phys(smram_state + 0x1d0); + ECX = mem_readl_phys(smram_state + 0x1d4); + EDX = mem_readl_phys(smram_state + 0x1d8); + EBX = mem_readl_phys(smram_state + 0x1dc); + ESP = mem_readl_phys(smram_state + 0x1e0); + EBP = mem_readl_phys(smram_state + 0x1e4); + ESI = mem_readl_phys(smram_state + 0x1e8); + EDI = mem_readl_phys(smram_state + 0x1ec); + + cpu_state.pc = mem_readl_phys(smram_state + 0x1f0); + uint32_t new_flags = mem_readl_phys(smram_state + 0x1f4); + cpu_state.flags = new_flags & 0xffff; + cpu_state.eflags = new_flags >> 16; + cr3 = mem_readl_phys(smram_state + 0x1f8); + cr0 = mem_readl_phys(smram_state + 0x1fc); + + cpu_state.seg_cs.access &= ~0x60; + cpu_state.seg_cs.access |= cpu_state.seg_ss.access & 0x60; //cpl is dpl of ss + + if((cr0 & 1) && !(cpu_state.eflags&VM_FLAG)) + { + cpu_state.seg_cs.checked = CS ? 1 : 0; + cpu_state.seg_ds.checked = DS ? 1 : 0; + cpu_state.seg_es.checked = ES ? 1 : 0; + cpu_state.seg_fs.checked = FS ? 1 : 0; + cpu_state.seg_gs.checked = GS ? 1 : 0; + cpu_state.seg_ss.checked = SS ? 1 : 0; + } + else + { + cpu_state.seg_cs.checked = cpu_state.seg_ds.checked = cpu_state.seg_es.checked + = cpu_state.seg_fs.checked = cpu_state.seg_gs.checked = cpu_state.seg_ss.checked = 1; + } + + in_smm = 0; + + nmi_mask = 1; +} + #define OP_TABLE(name) ops_ ## name #define CLOCK_CYCLES(c) cycles -= (c) #define CLOCK_CYCLES_ALWAYS(c) cycles -= (c) @@ -576,6 +786,10 @@ void exec386_dynarec(int cycs) ss=oldss; ssegs=0; }*/ + + if (in_smm && smi_line && is_pentium) + CPU_BLOCK_END(); + if (cpu_state.abrt) CPU_BLOCK_END(); if (trap) @@ -726,6 +940,9 @@ inrecomp=0; hit, as host block size is only 2kB*/ if ((cpu_state.pc - start_pc) > 1000) CPU_BLOCK_END(); + + if (in_smm && smi_line && is_pentium) + CPU_BLOCK_END(); if (trap) CPU_BLOCK_END(); @@ -796,7 +1013,10 @@ inrecomp=0; hit, as host block size is only 2kB*/ if ((cpu_state.pc - start_pc) > 1000) CPU_BLOCK_END(); - + + if (in_smm && smi_line && is_pentium) + CPU_BLOCK_END(); + if (trap) CPU_BLOCK_END(); @@ -851,6 +1071,11 @@ inrecomp=0; } } + if (in_smm && smi_line && is_pentium) + { + enter_smm(); + } + if (trap) { flags_rebuild(); diff --git a/src/cpu/386_ops.h b/src/cpu/386_ops.h index 55d7d72f3..fa2ed4d83 100644 --- a/src/cpu/386_ops.h +++ b/src/cpu/386_ops.h @@ -651,7 +651,7 @@ const OpFn OP_TABLE(pentium_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, /*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -673,7 +673,7 @@ const OpFn OP_TABLE(pentium_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, /*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -695,7 +695,7 @@ const OpFn OP_TABLE(pentium_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, /*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -717,7 +717,7 @@ const OpFn OP_TABLE(pentium_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, /*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -742,7 +742,7 @@ const OpFn OP_TABLE(pentiummmx_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, /*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -764,7 +764,7 @@ const OpFn OP_TABLE(pentiummmx_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, /*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -786,7 +786,7 @@ const OpFn OP_TABLE(pentiummmx_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, /*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -808,7 +808,7 @@ const OpFn OP_TABLE(pentiummmx_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, /*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -834,7 +834,7 @@ const OpFn OP_TABLE(k6_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, /*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -856,7 +856,7 @@ const OpFn OP_TABLE(k6_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, /*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -878,7 +878,7 @@ const OpFn OP_TABLE(k6_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, /*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -900,7 +900,7 @@ const OpFn OP_TABLE(k6_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, /*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -927,7 +927,7 @@ const OpFn OP_TABLE(c6x86mx_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, /*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -949,7 +949,7 @@ const OpFn OP_TABLE(c6x86mx_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, /*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -971,7 +971,7 @@ const OpFn OP_TABLE(c6x86mx_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, /*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -993,7 +993,7 @@ const OpFn OP_TABLE(c6x86mx_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, /*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -1021,7 +1021,7 @@ const OpFn OP_TABLE(pentiumpro_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, /*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -1043,7 +1043,7 @@ const OpFn OP_TABLE(pentiumpro_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, /*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -1065,7 +1065,7 @@ const OpFn OP_TABLE(pentiumpro_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, /*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -1087,7 +1087,7 @@ const OpFn OP_TABLE(pentiumpro_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, /*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -1113,7 +1113,7 @@ const OpFn OP_TABLE(pentium2_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, /*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -1135,7 +1135,7 @@ const OpFn OP_TABLE(pentium2_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, /*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -1157,7 +1157,7 @@ const OpFn OP_TABLE(pentium2_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, /*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -1179,7 +1179,7 @@ const OpFn OP_TABLE(pentium2_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, /*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -1205,7 +1205,7 @@ const OpFn OP_TABLE(pentium2d_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,opFXSAVESTOR_a16,opIMUL_w_w_a16, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,opFXSAVESTOR_a16,opIMUL_w_w_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, /*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -1227,7 +1227,7 @@ const OpFn OP_TABLE(pentium2d_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,opFXSAVESTOR_a16,opIMUL_l_l_a16, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,opFXSAVESTOR_a16,opIMUL_l_l_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, /*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -1249,7 +1249,7 @@ const OpFn OP_TABLE(pentium2d_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,opFXSAVESTOR_a32,opIMUL_w_w_a32, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,opFXSAVESTOR_a32,opIMUL_w_w_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, /*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -1271,7 +1271,7 @@ const OpFn OP_TABLE(pentium2d_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,opFXSAVESTOR_a32,opIMUL_l_l_a32, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,opFXSAVESTOR_a32,opIMUL_l_l_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, /*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index dd5c7b40b..62a736082 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -122,6 +122,9 @@ const OpFn *x86_opcodes_df_a32; const OpFn *x86_opcodes_REPE; const OpFn *x86_opcodes_REPNE; +int in_smm = 0, smi_line = 0, smi_latched = 0; +uint32_t smbase = 0x30000; + CPU *cpu_s; int cpu_effective; int cpu_multi; diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 9fbd2b56a..a0ea98d65 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -348,6 +348,9 @@ extern int hasfpu; extern uint32_t cpu_features; +extern int in_smm, smi_line, smi_latched; +extern uint32_t smbase; + extern uint32_t cpu_cur_status; extern uint64_t cpu_CR4_mask; extern uint64_t tsc; @@ -461,6 +464,8 @@ extern void codegen_reset(void); extern void cpu_set_edx(void); extern int divl(uint32_t val); extern void execx86(int cycs); +extern void enter_smm(); +extern void leave_smm(); extern void exec386(int cycs); extern void exec386_dynarec(int cycs); extern int idivl(int32_t val); diff --git a/src/cpu/x86_ops_misc.h b/src/cpu/x86_ops_misc.h index b9d35a73c..08abe6790 100644 --- a/src/cpu/x86_ops_misc.h +++ b/src/cpu/x86_ops_misc.h @@ -1,21 +1,3 @@ -/* - * 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.2 2018/10/17 - * - * Author: Sarah Walker, - * Miran Grca, - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - */ - static int opCBW(uint32_t fetchdat) { AH = (AL & 0x80) ? 0xff : 0; @@ -71,14 +53,14 @@ static int opF6_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); if (cpu_mod != 3) { - SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(cpu_state.ea_seg); CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr); } dst = geteab(); if (cpu_state.abrt) return 1; switch (rmdat & 0x38) { case 0x00: /*TEST b,#8*/ - case 0x08: + case 0x08: src = readmemb(cs, cpu_state.pc); cpu_state.pc++; if (cpu_state.abrt) return 1; setznp8(src & dst); if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); @@ -128,7 +110,7 @@ static int opF6_a16(uint32_t fetchdat) { flags_rebuild(); cpu_state.flags |= 0x8D5; /*Not a Cyrix*/ - cpu_state.flags &= ~1; + cpu_state.flags &= ~1; } } else @@ -151,7 +133,7 @@ static int opF6_a16(uint32_t fetchdat) { flags_rebuild(); cpu_state.flags|=0x8D5; /*Not a Cyrix*/ - cpu_state.flags &= ~1; + cpu_state.flags &= ~1; } } else @@ -164,7 +146,6 @@ static int opF6_a16(uint32_t fetchdat) break; default: - x386_dynarec_log("Bad F6 opcode %02X\n", rmdat & 0x38); x86illegal(); } return 0; @@ -183,7 +164,7 @@ static int opF6_a32(uint32_t fetchdat) switch (rmdat & 0x38) { case 0x00: /*TEST b,#8*/ - case 0x08: + case 0x08: src = readmemb(cs, cpu_state.pc); cpu_state.pc++; if (cpu_state.abrt) return 1; setznp8(src & dst); if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); @@ -233,7 +214,7 @@ static int opF6_a32(uint32_t fetchdat) { flags_rebuild(); cpu_state.flags |= 0x8D5; /*Not a Cyrix*/ - cpu_state.flags &= ~1; + cpu_state.flags &= ~1; } } else @@ -255,8 +236,8 @@ static int opF6_a32(uint32_t fetchdat) if (!cpu_iscyrix) { flags_rebuild(); - cpu_state.flags|=0x8D5; /*Not a Cyrix*/ - cpu_state.flags &= ~1; + cpu_state.flags |= 0x8D5; /*Not a Cyrix*/ + cpu_state.flags &= ~1; } } else @@ -269,7 +250,6 @@ static int opF6_a32(uint32_t fetchdat) break; default: - x386_dynarec_log("Bad F6 opcode %02X\n", rmdat & 0x38); x86illegal(); } return 0; @@ -291,7 +271,7 @@ static int opF7_w_a16(uint32_t fetchdat) switch (rmdat & 0x38) { case 0x00: /*TEST w*/ - case 0x08: + case 0x08: src = getword(); if (cpu_state.abrt) return 1; setznp16(src & dst); if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); @@ -370,7 +350,6 @@ static int opF7_w_a16(uint32_t fetchdat) break; default: - x386_dynarec_log("Bad F7 opcode %02X\n", rmdat & 0x38); x86illegal(); } return 0; @@ -389,7 +368,7 @@ static int opF7_w_a32(uint32_t fetchdat) switch (rmdat & 0x38) { case 0x00: /*TEST w*/ - case 0x08: + case 0x08: src = getword(); if (cpu_state.abrt) return 1; setznp16(src & dst); if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); @@ -442,6 +421,7 @@ static int opF7_w_a32(uint32_t fetchdat) } else { +// fatal("DIVw BY 0 %04X:%04X %i\n",cs>>4,pc,ins); x86_int(0); return 1; } @@ -468,7 +448,6 @@ static int opF7_w_a32(uint32_t fetchdat) break; default: - x386_dynarec_log("Bad F7 opcode %02X\n", rmdat & 0x38); x86illegal(); } return 0; @@ -487,7 +466,7 @@ static int opF7_l_a16(uint32_t fetchdat) switch (rmdat & 0x38) { case 0x00: /*TEST l*/ - case 0x08: + case 0x08: src = getlong(); if (cpu_state.abrt) return 1; setznp32(src & dst); if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); @@ -545,7 +524,6 @@ static int opF7_l_a16(uint32_t fetchdat) break; default: - x386_dynarec_log("Bad F7 opcode %02X\n", rmdat & 0x38); x86illegal(); } return 0; @@ -563,7 +541,7 @@ static int opF7_l_a32(uint32_t fetchdat) switch (rmdat & 0x38) { case 0x00: /*TEST l*/ - case 0x08: + case 0x08: src = getlong(); if (cpu_state.abrt) return 1; setznp32(src & dst); if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); @@ -621,7 +599,6 @@ static int opF7_l_a32(uint32_t fetchdat) break; default: - x386_dynarec_log("Bad F7 opcode %02X\n", rmdat & 0x38); x86illegal(); } return 0; @@ -635,7 +612,7 @@ static int opHLT(uint32_t fetchdat) x86gpf(NULL,0); return 1; } - if (!((cpu_state.flags&I_FLAG) && pic_intpending)) + if (!((cpu_state.flags & I_FLAG) && pic_intpending)) { CLOCK_CYCLES_ALWAYS(100); cpu_state.pc--; @@ -655,8 +632,8 @@ static int opLOCK(uint32_t fetchdat) fetchdat = fastreadl(cs + cpu_state.pc); if (cpu_state.abrt) return 0; cpu_state.pc++; - - ILLEGAL_ON((fetchdat & 0xff) == 0x90); + + ILLEGAL_ON((fetchdat & 0xff) == 0x90); CLOCK_CYCLES(4); PREFETCH_PREFIX(); @@ -671,7 +648,7 @@ static int opBOUND_w_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); ILLEGAL_ON(cpu_mod == 3); - SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(cpu_state.ea_seg); low = geteaw(); high = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; @@ -691,7 +668,7 @@ static int opBOUND_w_a32(uint32_t fetchdat) fetch_ea_32(fetchdat); ILLEGAL_ON(cpu_mod == 3); - SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(cpu_state.ea_seg); low = geteaw(); high = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; @@ -712,7 +689,7 @@ static int opBOUND_l_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); ILLEGAL_ON(cpu_mod == 3); - SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(cpu_state.ea_seg); low = geteal(); high = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; @@ -732,7 +709,7 @@ static int opBOUND_l_a32(uint32_t fetchdat) fetch_ea_32(fetchdat); ILLEGAL_ON(cpu_mod == 3); - SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(cpu_state.ea_seg); low = geteal(); high = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; @@ -752,7 +729,6 @@ static int opCLTS(uint32_t fetchdat) { if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1)) { - x386_dynarec_log("Can't CLTS\n"); x86gpf(NULL,0); return 1; } @@ -867,8 +843,11 @@ static void loadall_load_segment(uint32_t addr, x86seg *s) s->base = readmeml(0, addr + 4); s->limit = readmeml(0, addr + 8); - if (s == &cpu_state.seg_cs) use32 = (segdat3 & 0x40) ? 0x300 : 0; - if (s == &cpu_state.seg_ss) stack32 = (segdat3 & 0x40) ? 1 : 0; + if (s == &cpu_state.seg_cs) + use32 = (segdat3 & 0x40) ? 0x300 : 0; + if (s == &cpu_state.seg_ss) + stack32 = (segdat3 & 0x40) ? 1 : 0; + cpu_cur_status &= ~(CPU_STATUS_USE32 | CPU_STATUS_STACK32); if (use32) cpu_cur_status |= CPU_STATUS_USE32; @@ -880,16 +859,16 @@ static void loadall_load_segment(uint32_t addr, x86seg *s) if (s == &cpu_state.seg_ds) { if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff) - cpu_cur_status &= ~CPU_STATUS_NOTFLATDS; - else - cpu_cur_status |= CPU_STATUS_NOTFLATDS; + cpu_cur_status &= ~CPU_STATUS_NOTFLATDS; + else + cpu_cur_status |= CPU_STATUS_NOTFLATDS; } if (s == &cpu_state.seg_ss) { if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff) - cpu_cur_status &= ~CPU_STATUS_NOTFLATSS; - else - cpu_cur_status |= CPU_STATUS_NOTFLATSS; + cpu_cur_status &= ~CPU_STATUS_NOTFLATSS; + else + cpu_cur_status |= CPU_STATUS_NOTFLATSS; } } @@ -933,6 +912,7 @@ static int opLOADALL386(uint32_t fetchdat) loadall_load_segment(la_addr + 0xc0, &cpu_state.seg_es); if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); + oldcpl = CPL; CLOCK_CYCLES(350); return 0; @@ -977,3 +957,16 @@ static int opWRMSR(uint32_t fetchdat) return 1; } +static int opRSM(uint32_t fetchdat) +{ + if(!in_smm) + { + leave_smm(); + if(smi_latched) enter_smm(); + CPU_BLOCK_END(); + return 0; + } + cpu_state.pc = cpu_state.oldpc; + x86illegal(); + return 1; +} \ No newline at end of file diff --git a/src/mem.c b/src/mem.c index 4610e7ee2..0741e18d5 100644 --- a/src/mem.c +++ b/src/mem.c @@ -512,7 +512,8 @@ writemembl(uint32_t addr, uint8_t val) mem_mapping_t *map; mem_logical_addr = addr; - if (page_lookup[addr>>12]) { + if (page_lookup[addr>>12]) + { page_lookup[addr>>12]->write_b(addr, val, page_lookup[addr>>12]); return; @@ -893,6 +894,25 @@ mem_readw_phys(uint32_t addr) return temp; } +uint32_t +mem_readl_phys(uint32_t addr) +{ + mem_mapping_t *map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + uint32_t temp; + + if (_mem_exec[addr >> MEM_GRANULARITY_BITS]) + return ((uint32_t *) _mem_exec[addr >> MEM_GRANULARITY_BITS])[(addr >> 1) & MEM_GRANULARITY_HMASK]; + else if (map && map->read_l) + return map->read_l(addr, map->p); + else { + temp = mem_readb_phys(addr + 3) << 24; + temp |= mem_readb_phys(addr + 2) << 16; + temp |= mem_readb_phys(addr + 1) << 8; + temp |= mem_readb_phys(addr); + } + + return temp; +} void mem_writeb_phys(uint32_t addr, uint8_t val) @@ -905,6 +925,23 @@ mem_writeb_phys(uint32_t addr, uint8_t val) map->write_b(addr, val, map->p); } +void +mem_writel_phys(uint32_t addr, uint32_t val) +{ + mem_mapping_t *map = write_mapping[addr >> MEM_GRANULARITY_BITS]; + + if (_mem_exec[addr >> MEM_GRANULARITY_BITS]) + _mem_exec[addr >> MEM_GRANULARITY_BITS][addr & MEM_GRANULARITY_MASK] = val; + else if (map && map->write_l) + map->write_l(addr, val, map->p); + else + { + mem_writeb_phys(addr, val & 0xff); + mem_writeb_phys(addr + 1, (val >> 8) & 0xff); + mem_writeb_phys(addr + 2, (val >> 16) & 0xff); + mem_writeb_phys(addr + 3, (val >> 24) & 0xff); + } +} uint8_t mem_read_ram(uint32_t addr, void *priv) @@ -1533,7 +1570,8 @@ mem_log("MEM: reset: new pages=%08lx, pages_sz=%i\n", pages, pages_sz); memset(page_lookup, 0x00, (1 << 20) * sizeof(page_t *)); #endif - memset(pages, 0x00, pages_sz*sizeof(page_t)); + memset(pages, 0x00, pages_sz*sizeof(page_t)); + for (c = 0; c < pages_sz; c++) { pages[c].mem = &ram[c << 12]; diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 79647a697..901ac9215 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -541,7 +541,7 @@ CXXFLAGS := $(CFLAGS) ######################################################################### # Create the (final) list of objects to build. # ######################################################################### -MAINOBJ := pc.o config.o random.o timer.o io.o apm.o dma.o nmi.o \ +MAINOBJ := pc.o config.o random.o timer.o io.o apm_new.o dma.o nmi.o \ pic.o pit.o port_92.o ppi.o pci.o mca.o mcr.o mem.o \ rom.o device.o nvr.o nvr_at.o nvr_ps2.o $(VNCOBJ) $(RDPOBJ) From 419c0ba6a4f778e0a60a5861c5aa09f64e50bcb3 Mon Sep 17 00:00:00 2001 From: nerd73 Date: Sun, 12 Jan 2020 11:05:57 -0700 Subject: [PATCH 046/177] Fix AMI ALi 1429's CPU list on old dynarec --- src/machine/machine_table.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 893b37e7a..bdf616382 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -136,7 +136,7 @@ const machine_t machines[] = { { "[386SX ISA] Unknown Micronics 386 Board", "micronics386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512, 8192, 128, 127, machine_at_micronics386_init, NULL }, #endif - { "[386DX ISA] AMI 386DX clone", "ami386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_ami_init, NULL }, + { "[386DX ISA] Dataexpert SX495 (386DX)", "ami386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_ami_init, NULL }, { "[386DX ISA] Award 386DX clone", "award386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_MR495) { "[386DX ISA] MR 386DX clone", "mr386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_mr_init, NULL }, @@ -148,12 +148,12 @@ const machine_t machines[] = { { "[386DX MCA] IBM PS/2 model 70 (type 3)", "ibmps2_m70_type3", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"IBM", cpus_IBM486BL}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 2, 16, 2, 63, machine_ps2_model_70_type3_init, NULL }, { "[386DX MCA] IBM PS/2 model 80", "ibmps2_m80", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"IBM", cpus_IBM486BL}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 1, 12, 1, 63, machine_ps2_model_80_init, NULL }, - { "[486 ISA] AMI 486 clone", "ami486", {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_ami_init, NULL }, - { "[486 ISA] AMI ALi 1429", "ali1429", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_ali1429_init, NULL }, - { "[486 ISA] AMI SiS 471", "ami471", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_ami471_init, NULL }, - { "[486 ISA] AMI WinBIOS 486", "win486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_winbios1429_init, NULL }, + { "[486 ISA] Dataexpert SX495 (486)", "ami486", {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_ami_init, NULL }, + { "[486 ISA] Olystar LIL1429", "ali1429", {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_ali1429_init, NULL }, + { "[486 ISA] AMI SiS 471", "ami471", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_ami471_init, NULL }, + { "[486 ISA] AMI WinBIOS 486", "win486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_winbios1429_init, NULL }, { "[486 ISA] AMI WinBIOS SiS 471", "win471", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_win471_init, NULL }, - { "[486 ISA] Award 486 clone", "award486", {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_init, NULL }, + { "[486 ISA] Award 486 clone", "award486", {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_init, NULL }, { "[486 ISA] DTK PKM-0038S E-2", "dtk486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_dtk486_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_PS1M2133) { "[486 ISA] IBM PS/1 model 2133", "ibmps1_2133", {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_NONMI, 1, 64, 1, 127, machine_ps1_m2133_init, NULL }, From 80ce5b1de135f8ae0f2c79ef0873c352bc54e0b5 Mon Sep 17 00:00:00 2001 From: nerd73 Date: Sun, 12 Jan 2020 11:10:59 -0700 Subject: [PATCH 047/177] fix spacing --- src/machine/machine_table.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index bdf616382..949267ab6 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -148,13 +148,13 @@ const machine_t machines[] = { { "[386DX MCA] IBM PS/2 model 70 (type 3)", "ibmps2_m70_type3", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"IBM", cpus_IBM486BL}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 2, 16, 2, 63, machine_ps2_model_70_type3_init, NULL }, { "[386DX MCA] IBM PS/2 model 80", "ibmps2_m80", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"IBM", cpus_IBM486BL}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 1, 12, 1, 63, machine_ps2_model_80_init, NULL }, - { "[486 ISA] Dataexpert SX495 (486)", "ami486", {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_ami_init, NULL }, - { "[486 ISA] Olystar LIL1429", "ali1429", {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_ali1429_init, NULL }, - { "[486 ISA] AMI SiS 471", "ami471", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_ami471_init, NULL }, - { "[486 ISA] AMI WinBIOS 486", "win486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_winbios1429_init, NULL }, - { "[486 ISA] AMI WinBIOS SiS 471", "win471", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_win471_init, NULL }, - { "[486 ISA] Award 486 clone", "award486", {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_init, NULL }, - { "[486 ISA] DTK PKM-0038S E-2", "dtk486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_dtk486_init, NULL }, + { "[486 ISA] Dataexpert SX495 (486)", "ami486", {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_ami_init, NULL }, + { "[486 ISA] Olystar LIL1429", "ali1429", {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_ali1429_init, NULL }, + { "[486 ISA] AMI SiS 471", "ami471", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_ami471_init, NULL }, + { "[486 ISA] AMI WinBIOS 486", "win486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_winbios1429_init, NULL }, + { "[486 ISA] AMI WinBIOS SiS 471", "win471", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_win471_init, NULL }, + { "[486 ISA] Award 486 clone", "award486", {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_init, NULL }, + { "[486 ISA] DTK PKM-0038S E-2", "dtk486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_dtk486_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_PS1M2133) { "[486 ISA] IBM PS/1 model 2133", "ibmps1_2133", {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_NONMI, 1, 64, 1, 127, machine_ps1_m2133_init, NULL }, #endif From 59b31a0232a939c3264fc35d6156034139021d4c Mon Sep 17 00:00:00 2001 From: Melissa Goad Date: Sun, 12 Jan 2020 13:47:42 -0600 Subject: [PATCH 048/177] Fix adding a sound card --- src/sound/midi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sound/midi.c b/src/sound/midi.c index 98c5100a0..31a8b86bf 100644 --- a/src/sound/midi.c +++ b/src/sound/midi.c @@ -399,6 +399,7 @@ midi_raw_out_byte(uint8_t val) void midi_clear_buffer(void) { + if (!midi) return; midi->midi_pos = 0; midi->midi_status = 0x00; midi->midi_cmd_pos = 0; From 72f932ce79ad604c0d8767098755c9ce08c644bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hrdli=C4=8Dka?= Date: Mon, 13 Jan 2020 18:16:22 +0100 Subject: [PATCH 049/177] Update feature_request.md --- .github/ISSUE_TEMPLATE/feature_request.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 11fc491ef..e301d68ce 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -2,7 +2,7 @@ name: Feature request about: Suggest an idea for this project title: '' -labels: enhancement +labels: feature request assignees: '' --- From be9b57fcad65b7d46890fc6ab5fb7d817d2ca556 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 13 Jan 2020 21:03:58 +0100 Subject: [PATCH 050/177] Added some sanity checks and pointer frees / NULL'ings to the CD-ROM image code, fixes #543. --- src/cdrom/cdrom_image_backend.c | 993 ++++++++++++++++++++++++++++++++ 1 file changed, 993 insertions(+) diff --git a/src/cdrom/cdrom_image_backend.c b/src/cdrom/cdrom_image_backend.c index 983a75efa..a888c882e 100644 --- a/src/cdrom/cdrom_image_backend.c +++ b/src/cdrom/cdrom_image_backend.c @@ -46,6 +46,999 @@ #define MAX_FILENAME_LENGTH 256 #define CROSS_LEN 512 +/* + * 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. + * + * CD-ROM image file handling module, translated to C from + * cdrom_dosbox.cpp. + * + * Version: @(#)cdrom_image_backend.c 1.0.3 2020/01/13 + * + * Authors: Miran Grca, + * Fred N. van Kempen, + * The DOSBox Team, + * + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2002-2020 The DOSBox Team. + */ +#define _LARGEFILE_SOURCE +#define _LARGEFILE64_SOURCE +#define __STDC_FORMAT_MACROS +#include +#include +#include +#include +#include +#include +#ifdef _WIN32 +# include +#else +# include +#endif +#include +#define HAVE_STDARG_H +#include "../86box.h" +#include "../plat.h" +#include "cdrom_image_backend.h" + + +#define CDROM_BCD(x) (((x) % 10) | (((x) / 10) << 4)) + +#define MAX_LINE_LENGTH 512 +#define MAX_FILENAME_LENGTH 256 +#define CROSS_LEN 512 + + +#ifdef ENABLE_CDROM_IMAGE_BACKEND_LOG +int cdrom_image_backend_do_log = ENABLE_CDROM_IMAGE_BACKEND_LOG; + + +void +cdrom_image_backend_log(const char *fmt, ...) +{ + va_list ap; + + if (cdrom_image_backend_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define cdrom_image_backend_log(fmt, ...) +#endif + + +/* Binary file functions. */ +static int +bin_read(void *p, uint8_t *buffer, uint64_t seek, size_t count) +{ + track_file_t *tf = (track_file_t *) p; + + cdrom_image_backend_log("CDROM: binary_read(%08lx, pos=%" PRIu64 " count=%lu\n", + tf->file, seek, count); + + if (tf->file == NULL) + return 0; + + fseeko64(tf->file, seek, SEEK_SET); + + if (fread(buffer, count, 1, tf->file) != 1) { +#ifdef ENABLE_cdrom_image_backend_log + cdrom_image_backend_log("CDROM: binary_read failed!\n"); +#endif + return 0; + } + + return 1; +} + + +static uint64_t +bin_get_length(void *p) +{ + off64_t len; + track_file_t *tf = (track_file_t *) p; + + cdrom_image_backend_log("CDROM: binary_length(%08lx)\n", bf->file); + + if (tf->file == NULL) + return 0; + + fseeko64(tf->file, 0, SEEK_END); + len = ftello64(tf->file); + cdrom_image_backend_log("CDROM: binary_length(%08lx) = %" PRIu64 "\n", tf->file, len); + + return len; +} + + +static void +bin_close(void *p) +{ + track_file_t *tf = (track_file_t *) p; + + if (tf == NULL) + return; + + if (tf->file != NULL) { + fclose(tf->file); + tf->file = NULL; + } + + memset(tf->fn, 0x00, sizeof(tf->fn)); + + free(p); +} + + +static track_file_t * +bin_init(const wchar_t *filename, int *error) +{ + track_file_t *tf = (track_file_t *) malloc(sizeof(track_file_t)); + + if (tf == NULL) { + tf->read = NULL; + tf->get_length = NULL; + tf->close = NULL; + return NULL; + } + + memset(tf->fn, 0x00, sizeof(tf->fn)); + wcscpy(tf->fn, filename); + tf->file = plat_fopen64(tf->fn, L"rb"); + cdrom_image_backend_log("CDROM: binary_open(%ls) = %08lx\n", tf->fn, tf->file); + + *error = (tf->file == NULL); + + /* Set the function pointers. */ + if (!*error) { + tf->read = bin_read; + tf->get_length = bin_get_length; + tf->close = bin_close; + } else { + free(tf); + tf = NULL; + tf->read = NULL; + tf->get_length = NULL; + tf->close = NULL; + } + + return tf; +} + + +static track_file_t * +track_file_init(const wchar_t *filename, int *error) +{ + /* Current we only support .BIN files, either combined or one per + track. In the future, more is planned. */ + return bin_init(filename, error); +} + + +static void +track_file_close(track_t *trk) +{ + if (trk == NULL) + return; + + if (trk->file == NULL) + return; + + trk->file->close(trk->file); + trk->file = NULL; +} + + +/* Root functions. */ +static void +cdi_clear_tracks(cd_img_t *cdi) +{ + int i; + track_file_t *last = NULL; + track_t *cur = NULL; + + if ((cdi->tracks == NULL) || (cdi->tracks_num == 0)) + return; + + for (i = 0; i < cdi->tracks_num; i++) { + cur = &cdi->tracks[i]; + + if (cur->file != last) { + track_file_close(cur); + last = cur->file; + } + } + + /* Now free the array. */ + free(cdi->tracks); + cdi->tracks = NULL; + + /* Mark that there's no tracks. */ + cdi->tracks_num = 0; +} + + +void +cdi_close(cd_img_t *cdi) +{ + cdi_clear_tracks(cdi); + free(cdi); +} + + +int +cdi_set_device(cd_img_t *cdi, const wchar_t *path) +{ + if (cdi_load_cue(cdi, path)) + return 1; + + if (cdi_load_iso(cdi, path)) + return 1; + + return 0; +} + + +/* TODO: This never returns anything other than 1, should it even be an int? */ +int +cdi_get_audio_tracks(cd_img_t *cdi, int *st_track, int *end, TMSF *lead_out) +{ + *st_track = 1; + *end = cdi->tracks_num - 1; + FRAMES_TO_MSF(cdi->tracks[*end].start + 150, &lead_out->min, &lead_out->sec, &lead_out->fr); + + return 1; +} + + +/* This replaces both Info and EndInfo, they are specified by a variable. */ +int +cdi_get_audio_track_info(cd_img_t *cdi, int end, int track, int *track_num, TMSF *start, uint8_t *attr) +{ + track_t *trk = &cdi->tracks[track - 1]; + int pos = trk->start + 150; + + if ((track < 1) || (track > cdi->tracks_num)) + return 0; + + pos = trk->start + 150; + + FRAMES_TO_MSF(pos, &start->min, &start->sec, &start->fr); + *track_num = trk->track_number; + *attr = trk->attr; + + return 1; +} + + +int +cdi_get_track(cd_img_t *cdi, uint32_t sector) +{ + int i; + track_t *cur, *next; + + /* There must be at least two tracks - data and lead out. */ + if (cdi->tracks_num < 2) + return -1; + + /* This has a problem - the code skips the last track, which is + lead out - is that correct? */ + for (i = 0; i < (cdi->tracks_num - 1); i++) { + cur = &cdi->tracks[i]; + next = &cdi->tracks[i + 1]; + if ((cur->start <= sector) && (sector < next->start)) + return cur->number; + } + + return -1; +} + + +/* TODO: See if track start is adjusted by 150 or not. */ +int +cdi_get_audio_sub(cd_img_t *cdi, uint32_t sector, uint8_t *attr, uint8_t *track, uint8_t *index, TMSF *rel_pos, TMSF *abs_pos) +{ + int cur_track = cdi_get_track(cdi, sector); + track_t *trk; + + if (cur_track < 1) + return 0; + + *track = (uint8_t) cur_track; + trk = &cdi->tracks[*track - 1]; + *attr = trk->attr; + *index = 1; + + FRAMES_TO_MSF(sector + 150, &abs_pos->min, &abs_pos->sec, &abs_pos->fr); + + /* Absolute position should be adjusted by 150, not the relative ones. */ + FRAMES_TO_MSF(sector - trk->start, &rel_pos->min, &rel_pos->sec, &rel_pos->fr); + + return 1; +} + + +int +cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector) +{ + size_t length; + int track = cdi_get_track(cdi, sector) - 1; + uint64_t sect = (uint64_t) sector, seek; + track_t *trk; + int track_is_raw, ret; + int raw_size, cooked_size; + uint64_t offset = 0ULL; + int m = 0, s = 0, f = 0; + + if (track < 0) + return 0; + + trk = &cdi->tracks[track]; + track_is_raw = ((trk->sector_size == RAW_SECTOR_SIZE) || (trk->sector_size == 2448)); + if (raw && !track_is_raw) + return 0; + seek = trk->skip + ((sect - trk->start) * trk->sector_size); + + if (track_is_raw) + raw_size = trk->sector_size; + else + raw_size = 2448; + + if (trk->mode2 && (trk->form != 1)) { + if (trk->form == 2) + cooked_size = (track_is_raw ? 2328 : trk->sector_size); /* Both 2324 + ECC and 2328 variants are valid. */ + else + cooked_size = 2336; + } else + cooked_size = COOKED_SECTOR_SIZE; + + length = (raw ? raw_size : cooked_size); + + if (trk->mode2 && (trk->form >= 1)) + offset = 24ULL; + else + offset = 16ULL; + + if (raw && !track_is_raw) { + memset(buffer, 0x00, 2448); + ret = trk->file->read(trk->file, buffer + offset, seek, length); + if (!ret) + return 0; + /* Construct the rest of the raw sector. */ + memset(buffer + 1, 0xff, 10); + buffer += 12; + FRAMES_TO_MSF(sector + 150, &m, &s, &f); + /* These have to be BCD. */ + buffer[12] = CDROM_BCD(m & 0xff); + buffer[13] = CDROM_BCD(s & 0xff); + buffer[14] = CDROM_BCD(f & 0xff); + buffer[15] = trk->mode2 ? 2 : 1; /* Data, should reflect the actual sector type. */ + return 1; + } else if (!raw && track_is_raw) + return trk->file->read(trk->file, buffer, seek + offset, length); + else + return trk->file->read(trk->file, buffer, seek, length); +} + + +int +cdi_read_sectors(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector, uint32_t num) +{ + int sector_size, success = 1; + uint8_t buf_len, *buf; + uint32_t i; + + /* TODO: This fails to account for Mode 2. Shouldn't we have a function + to get sector size? */ + sector_size = raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE; + buf_len = num * sector_size; + buf = (uint8_t *) malloc(buf_len * sizeof(uint8_t)); + + for (i = 0; i < num; i++) { + success = cdi_read_sector(cdi, &buf[i * sector_size], raw, sector + i); + if (!success) + break; + } + + memcpy((void *) buffer, buf, buf_len); + free(buf); + buf = NULL; + + return success; +} + + +/* TODO: Do CUE+BIN images with a sector size of 2448 even exist? */ +int +cdi_read_sector_sub(cd_img_t *cdi, uint8_t *buffer, uint32_t sector) +{ + int track = cdi_get_track(cdi, sector) - 1; + track_t *trk; + uint64_t s = (uint64_t) sector, seek; + + if (track < 0) + return 0; + + trk = &cdi->tracks[track]; + seek = trk->skip + ((s - trk->start) * trk->sector_size); + if (trk->sector_size != 2448) + return 0; + + return trk->file->read(trk->file, buffer, seek, 2448); +} + + +int +cdi_get_sector_size(cd_img_t *cdi, uint32_t sector) +{ + int track = cdi_get_track(cdi, sector) - 1; + track_t *trk; + + if (track < 0) + return 0; + + trk = &cdi->tracks[track]; + return trk->sector_size; +} + + +int +cdi_is_mode2(cd_img_t *cdi, uint32_t sector) +{ + int track = cdi_get_track(cdi, sector) - 1; + track_t *trk; + + if (track < 0) + return 0; + + trk = &cdi->tracks[track]; + + return !!(trk->mode2); +} + + +int +cdi_get_mode2_form(cd_img_t *cdi, uint32_t sector) +{ + int track = cdi_get_track(cdi, sector) - 1; + track_t *trk; + + if (track < 0) + return 0; + + trk = &cdi->tracks[track]; + + return trk->form; +} + + +static int +cdi_can_read_pvd(track_file_t *file, uint64_t sector_size, int mode2, int form) +{ + uint8_t pvd[COOKED_SECTOR_SIZE]; + uint64_t seek = 16ULL * sector_size; /* First VD is located at sector 16. */ + + if ((!mode2 || (form == 0)) && (sector_size == RAW_SECTOR_SIZE)) + seek += 16; + if (mode2 && (form >= 1)) + seek += 24; + + file->read(file, pvd, seek, COOKED_SECTOR_SIZE); + + return ((pvd[0] == 1 && !strncmp((char*)(&pvd[1]), "CD001", 5) && pvd[6] == 1) || + (pvd[8] == 1 && !strncmp((char*)(&pvd[9]), "CDROM", 5) && pvd[14] == 1)); +} + + +/* This reallocates the array and returns the pointer to the last track. */ +static void +cdi_track_push_back(cd_img_t *cdi, track_t *trk) +{ + /* This has to be done so situations in which realloc would misbehave + can be detected and reported to the user. */ + if ((cdi->tracks != NULL) && (cdi->tracks_num == 0)) + fatal("CD-ROM Image: Non-null tracks array at 0 loaded tracks\n"); + if ((cdi->tracks == NULL) && (cdi->tracks_num != 0)) + fatal("CD-ROM Image: Null tracks array at non-zero loaded tracks\n"); + + cdi->tracks = realloc(cdi->tracks, (cdi->tracks_num + 1) * sizeof(track_t)); + memcpy(&(cdi->tracks[cdi->tracks_num]), trk, sizeof(track_t)); + cdi->tracks_num++; +} + + +int +cdi_load_iso(cd_img_t *cdi, const wchar_t *filename) +{ + int error; + track_t trk; + + cdi->tracks = NULL; + cdi->tracks_num = 0; + + memset(&trk, 0, sizeof(track_t)); + + /* Data track (shouldn't there be a lead in track?). */ + trk.file = bin_init(filename, &error); + if (error) { + if ((trk.file != NULL) && (trk.file->close != NULL)) + trk.file->close(trk.file); + return 0; + } + trk.number = 1; + trk.track_number = 1; + trk.attr = DATA_TRACK; + + /* Try to detect ISO type. */ + trk.form = 0; + trk.mode2 = 0; + /* TODO: Merge the first and last cases since they result in the same thing. */ + if (cdi_can_read_pvd(trk.file, RAW_SECTOR_SIZE, 0, 0)) + trk.sector_size = RAW_SECTOR_SIZE; + else if (cdi_can_read_pvd(trk.file, 2336, 1, 0)) { + trk.sector_size = 2336; + trk.mode2 = 1; + } else if (cdi_can_read_pvd(trk.file, 2324, 1, 2)) { + trk.sector_size = 2324; + trk.mode2 = 1; + trk.form = 2; + } else if (cdi_can_read_pvd(trk.file, RAW_SECTOR_SIZE, 1, 0)) { + trk.sector_size = RAW_SECTOR_SIZE; + trk.mode2 = 1; + } else { + /* We use 2048 mode 1 as the default. */ + trk.sector_size = COOKED_SECTOR_SIZE; + } + + trk.length = trk.file->get_length(trk.file) / trk.sector_size; + cdi_track_push_back(cdi, &trk); + + /* Lead out track. */ + trk.number = 2; + trk.track_number = 0xAA; + trk.attr = 0x16; /* Was originally 0x00, but I believe 0x16 is appropriate. */ + trk.start = trk.length; + trk.length = 0; + trk.file = NULL; + cdi_track_push_back(cdi, &trk); + + return 1; +} + + +static int +cdi_cue_get_buffer(char *str, char **line, int up) +{ + char *s = *line; + char *p = str; + int quote = 0; + int done = 0; + int space = 1; + + /* Copy to local buffer until we have end of string or whitespace. */ + while (! done) { + switch(*s) { + case '\0': + if (quote) { + /* Ouch, unterminated string.. */ + return 0; + } + done = 1; + break; + + case '\"': + quote ^= 1; + break; + + case ' ': + case '\t': + if (space) + break; + + if (! quote) { + done = 1; + break; + } + /*FALLTHROUGH*/ + + default: + if (up && islower((int) *s)) + *p++ = toupper((int) *s); + else + *p++ = *s; + space = 0; + break; + } + + if (! done) + s++; + } + *p = '\0'; + + *line = s; + + return 1; +} + + +static int +cdi_cue_get_keyword(char **dest, char **line) +{ + char temp[1024]; + int success; + + success = cdi_cue_get_buffer(temp, line, 1); + if (success) + *dest = temp; + + return success; +} + + +/* Get a string from the input line, handling quotes properly. */ +static uint64_t +cdi_cue_get_number(char **line) +{ + char temp[128]; + uint64_t num; + + if (!cdi_cue_get_buffer(temp, line, 0)) + return 0; + + if (sscanf(temp, "%" PRIu64, &num) != 1) + return 0; + + return num; +} + + +static int +cdi_cue_get_frame(uint64_t *frames, char **line) +{ + char temp[128]; + int min, sec, fr; + int success; + + success = cdi_cue_get_buffer(temp, line, 0); + if (! success) return 0; + + success = sscanf(temp, "%d:%d:%d", &min, &sec, &fr) == 3; + if (! success) return 0; + + *frames = MSF_TO_FRAMES(min, sec, fr); + + return 1; +} + + +static int +cdi_add_track(cd_img_t *cdi, track_t *cur, uint64_t *shift, uint64_t prestart, uint64_t *total_pregap, uint64_t cur_pregap) +{ + /* Frames between index 0 (prestart) and 1 (current track start) must be skipped. */ + uint64_t skip, temp; + track_t *prev = NULL; + + if (prestart > 0) { + if (prestart > cur->start) + return 0; + skip = cur->start - prestart; + } else + skip = 0ULL; + + if ((cdi->tracks != NULL) && (cdi->tracks_num != 0)) + prev = &cdi->tracks[cdi->tracks_num - 1]; + + /* First track (track number must be 1). */ + if (cdi->tracks_num == 0) { + /* I guess this makes sure the structure is not filled with invalid data. */ + if (cur->number != 1) + return 0; + cur->skip = skip * cur->sector_size; + cur->start += cur_pregap; + *total_pregap = cur_pregap; + cdi_track_push_back(cdi, cur); + return 1; + } + + /* Current track consumes data from the same file as the previous. */ + if (prev->file == cur->file) { + cur->start += *shift; + prev->length = cur->start + *total_pregap - prev->start - skip; + cur->skip += prev->skip + (prev->length * prev->sector_size) + (skip * cur->sector_size); + *total_pregap += cur_pregap; + cur->start += *total_pregap; + } else { + temp = prev->file->get_length(prev->file) - ((uint64_t) prev->skip); + prev->length = temp / ((uint64_t) prev->sector_size); + if ((temp % prev->sector_size) != 0) + prev->length++; /* Padding. */ + + cur->start += prev->start + prev->length + cur_pregap; + cur->skip = skip * cur->sector_size; + *shift += prev->start + prev->length; + *total_pregap = cur_pregap; + } + + /* Error checks. */ + if (cur->number <= 1) + return 0; + if ((prev->number + 1) != cur->number) + return 0; + if (cur->start < (prev->start + prev->length)) + return 0; + + cdi_track_push_back(cdi, cur); + + return 1; +} + + +int +cdi_load_cue(cd_img_t *cdi, const wchar_t *cuefile) +{ + track_t trk; + wchar_t pathname[MAX_FILENAME_LENGTH], filename[MAX_FILENAME_LENGTH]; + wchar_t temp[MAX_FILENAME_LENGTH]; + uint64_t shift = 0ULL, prestart = 0ULL; + uint64_t cur_pregap = 0ULL, total_pregap = 0ULL; + uint64_t frame = 0ULL, index; + int i, success; + int error, can_add_track = 0; + FILE *fp; + char buf[MAX_LINE_LENGTH], ansi[MAX_FILENAME_LENGTH]; + char *line, *command; + char *type; + + cdi->tracks = NULL; + cdi->tracks_num = 0; + + memset(&trk, 0, sizeof(track_t)); + + /* Get a copy of the filename into pathname, we need it later. */ + memset(pathname, 0, MAX_FILENAME_LENGTH * sizeof(wchar_t)); + plat_get_dirname(pathname, cuefile); + + /* Open the file. */ + fp = plat_fopen((wchar_t *) cuefile, L"r"); + if (fp == NULL) + return 0; + + success = 0; + + for (;;) { + line = buf; + + /* Read a line from the cuesheet file. */ + if (feof(fp) || fgets(buf, sizeof(buf), fp) == NULL || ferror(fp)) + break; + + /* Do two iterations to make sure to nuke even if it's \r\n or \n\r, + but do checks to make sure we're not nuking other bytes. */ + for (i = 0; i < 2; i++) { + if (strlen(buf) > 0) { + if (buf[strlen(buf) - 1] == '\n') + buf[strlen(buf) - 1] = '\0'; /* nuke trailing newline */ + else if (buf[strlen(buf) - 1] == '\r') + buf[strlen(buf) - 1] = '\0'; /* nuke trailing newline */ + } + } + + success = cdi_cue_get_keyword(&command, &line); + + if (!strcmp(command, "TRACK")) { + if (can_add_track) + success = cdi_add_track(cdi, &trk, &shift, prestart, &total_pregap, cur_pregap); + else + success = 1; + + trk.start = 0; + trk.skip = 0; + cur_pregap = 0; + prestart = 0; + + trk.number = cdi_cue_get_number(&line); + trk.track_number = trk.number; + success = cdi_cue_get_keyword(&type, &line); + if (!success) + break; + + trk.form = 0; + trk.mode2 = 0; + + if (!strcmp(type, "AUDIO")) { + trk.sector_size = RAW_SECTOR_SIZE; + trk.attr = AUDIO_TRACK; + } else if (!strcmp(type, "MODE1/2048")) { + trk.sector_size = COOKED_SECTOR_SIZE; + trk.attr = DATA_TRACK; + } else if (!strcmp(type, "MODE1/2352")) { + trk.sector_size = RAW_SECTOR_SIZE; + trk.attr = DATA_TRACK; + } else if (!strcmp(type, "MODE1/2448")) { + trk.sector_size = 2448; + trk.attr = DATA_TRACK; + } else if (!strcmp(type, "MODE2/2048")) { + trk.form = 1; + trk.sector_size = COOKED_SECTOR_SIZE; + trk.attr = DATA_TRACK; + trk.mode2 = 1; + } else if (!strcmp(type, "MODE2/2324")) { + trk.form = 2; + trk.sector_size = 2324; + trk.attr = DATA_TRACK; + trk.mode2 = 1; + } else if (!strcmp(type, "MODE2/2328")) { + trk.form = 2; + trk.sector_size = 2328; + trk.attr = DATA_TRACK; + trk.mode2 = 1; + } else if (!strcmp(type, "MODE2/2336")) { + trk.sector_size = 2336; + trk.attr = DATA_TRACK; + trk.mode2 = 1; + } else if (!strcmp(type, "MODE2/2352")) { + trk.form = 1; /* Assume this is XA Mode 2 Form 1. */ + trk.sector_size = RAW_SECTOR_SIZE; + trk.attr = DATA_TRACK; + trk.mode2 = 1; + } else if (!strcmp(type, "MODE2/2448")) { + trk.form = 1; /* Assume this is XA Mode 2 Form 1. */ + trk.sector_size = 2448; + trk.attr = DATA_TRACK; + trk.mode2 = 1; + } else if (!strcmp(type, "CDG/2448")) { + trk.sector_size = 2448; + trk.attr = DATA_TRACK; + trk.mode2 = 1; + } else if (!strcmp(type, "CDI/2336")) { + trk.sector_size = 2336; + trk.attr = DATA_TRACK; + trk.mode2 = 1; + } else if (!strcmp(type, "CDI/2352")) { + trk.sector_size = RAW_SECTOR_SIZE; + trk.attr = DATA_TRACK; + trk.mode2 = 1; + } else + success = 0; + + can_add_track = 1; + } else if (!strcmp(command, "INDEX")) { + index = cdi_cue_get_number(&line); + success = cdi_cue_get_frame(&frame, &line); + + switch(index) { + case 0: + prestart = frame; + break; + + case 1: + trk.start = frame; + break; + + default: + /* ignore other indices */ + break; + } + } else if (!strcmp(command, "FILE")) { + if (can_add_track) + success = cdi_add_track(cdi, &trk, &shift, prestart, &total_pregap, cur_pregap); + else + success = 1; + can_add_track = 0; + + memset(ansi, 0, MAX_FILENAME_LENGTH * sizeof(char)); + memset(filename, 0, MAX_FILENAME_LENGTH * sizeof(wchar_t)); + + success = cdi_cue_get_buffer(ansi, &line, 0); + if (!success) + break; + success = cdi_cue_get_keyword(&type, &line); + if (!success) + break; + + trk.file = NULL; + error = 1; + + if (!strcmp(type, "BINARY")) { + memset(temp, 0, MAX_FILENAME_LENGTH * sizeof(wchar_t)); + mbstowcs(temp, ansi, sizeof_w(temp)); + plat_append_filename(filename, pathname, temp); + trk.file = track_file_init(filename, &error); + } + if (error) { +#ifdef ENABLE_cdrom_image_backend_log + cdrom_image_backend_log("CUE: cannot open fille '%ls' in cue sheet!\n", + filename); +#endif + if (trk.file != NULL) { + trk.file->close(trk.file); + trk.file = NULL; + } + success = 0; + } + } else if (!strcmp(command, "PREGAP")) + success = cdi_cue_get_frame(&cur_pregap, &line); + else if (!strcmp(command, "CATALOG") || !strcmp(command, "CDTEXTFILE") || !strcmp(command, "FLAGS") || !strcmp(command, "ISRC") || + !strcmp(command, "PERFORMER") || !strcmp(command, "POSTGAP") || !strcmp(command, "REM") || + !strcmp(command, "SONGWRITER") || !strcmp(command, "TITLE") || !strcmp(command, "")) { + /* Ignored commands. */ + success = 1; + } else { +#ifdef ENABLE_cdrom_image_backend_log + cdrom_image_backend_log("CUE: unsupported command '%s' in cue sheet!\n", + command.c_str()); +#endif + success = 0; + } + + if (!success) + break; + } + + fclose(fp); + if (!success) + return 0; + + /* Add last track. */ + if (!cdi_add_track(cdi, &trk, &shift, prestart, &total_pregap, cur_pregap)) + return 0; + + /* Add lead out track. */ + trk.number++; + trk.track_number = 0xAA; + trk.attr = 0x16; /* Was 0x00 but I believe 0x16 is appropriate. */ + trk.start = 0; + trk.length = 0; + trk.file = NULL; + if (!cdi_add_track(cdi, &trk, &shift, 0, &total_pregap, 0)) + return 0; + + return 1; +} + + +int +cdi_has_data_track(cd_img_t *cdi) +{ + int i; + + if ((cdi == NULL) || (cdi->tracks == NULL)) + return 0; + + /* Data track has attribute 0x14. */ + for (i = 0; i < cdi->tracks_num; i++) { + if (cdi->tracks[i].attr == DATA_TRACK) + return 1; + } + + return 0; +} + + +int +cdi_has_audio_track(cd_img_t *cdi) +{ + int i; + + if ((cdi == NULL) || (cdi->tracks == NULL)) + return 0; + + /* Audio track has attribute 0x14. */ + for (i = 0; i < cdi->tracks_num; i++) { + if (cdi->tracks[i].attr == AUDIO_TRACK) + return 1; + } + + return 0; +} #ifdef ENABLE_CDROM_IMAGE_BACKEND_LOG int cdrom_image_backend_do_log = ENABLE_CDROM_IMAGE_BACKEND_LOG; From dcf06f4ba9d51249bae843672f7b2bcf71ee3c6d Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 13 Jan 2020 21:06:32 +0100 Subject: [PATCH 051/177] Fixed the mess in cdrom/cdrom_image_backend.c. --- src/cdrom/cdrom_image_backend.c | 980 -------------------------------- 1 file changed, 980 deletions(-) diff --git a/src/cdrom/cdrom_image_backend.c b/src/cdrom/cdrom_image_backend.c index a888c882e..61260b44d 100644 --- a/src/cdrom/cdrom_image_backend.c +++ b/src/cdrom/cdrom_image_backend.c @@ -1,51 +1,3 @@ -/* - * 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. - * - * CD-ROM image file handling module, translated to C from - * cdrom_dosbox.cpp. - * - * Version: @(#)cdrom_image_backend.c 1.0.2 2020/01/11 - * - * Authors: Miran Grca, - * Fred N. van Kempen, - * The DOSBox Team, - * - * Copyright 2016-2020 Miran Grca. - * Copyright 2017-2020 Fred N. van Kempen. - * Copyright 2002-2020 The DOSBox Team. - */ -#define _LARGEFILE_SOURCE -#define _LARGEFILE64_SOURCE -#define __STDC_FORMAT_MACROS -#include -#include -#include -#include -#include -#include -#ifdef _WIN32 -# include -#else -# include -#endif -#include -#define HAVE_STDARG_H -#include "../86box.h" -#include "../plat.h" -#include "cdrom_image_backend.h" - - -#define CDROM_BCD(x) (((x) % 10) | (((x) / 10) << 4)) - -#define MAX_LINE_LENGTH 512 -#define MAX_FILENAME_LENGTH 256 -#define CROSS_LEN 512 - /* * 86Box A hypervisor and IBM PC system emulator that specializes in * running old operating systems and software designed for IBM @@ -1023,938 +975,6 @@ cdi_has_data_track(cd_img_t *cdi) } -int -cdi_has_audio_track(cd_img_t *cdi) -{ - int i; - - if ((cdi == NULL) || (cdi->tracks == NULL)) - return 0; - - /* Audio track has attribute 0x14. */ - for (i = 0; i < cdi->tracks_num; i++) { - if (cdi->tracks[i].attr == AUDIO_TRACK) - return 1; - } - - return 0; -} - -#ifdef ENABLE_CDROM_IMAGE_BACKEND_LOG -int cdrom_image_backend_do_log = ENABLE_CDROM_IMAGE_BACKEND_LOG; - - -void -cdrom_image_backend_log(const char *fmt, ...) -{ - va_list ap; - - if (cdrom_image_backend_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -} -#else -#define cdrom_image_backend_log(fmt, ...) -#endif - - -/* Binary file functions. */ -static int -bin_read(void *p, uint8_t *buffer, uint64_t seek, size_t count) -{ - track_file_t *tf = (track_file_t *) p; - - cdrom_image_backend_log("CDROM: binary_read(%08lx, pos=%" PRIu64 " count=%lu\n", - tf->file, seek, count); - - if (tf->file == NULL) - return 0; - - fseeko64(tf->file, seek, SEEK_SET); - - if (fread(buffer, count, 1, tf->file) != 1) { -#ifdef ENABLE_cdrom_image_backend_log - cdrom_image_backend_log("CDROM: binary_read failed!\n"); -#endif - return 0; - } - - return 1; -} - - -static uint64_t -bin_get_length(void *p) -{ - off64_t len; - track_file_t *tf = (track_file_t *) p; - - cdrom_image_backend_log("CDROM: binary_length(%08lx)\n", bf->file); - - if (tf->file == NULL) - return 0; - - fseeko64(tf->file, 0, SEEK_END); - len = ftello64(tf->file); - cdrom_image_backend_log("CDROM: binary_length(%08lx) = %" PRIu64 "\n", tf->file, len); - - return len; -} - - -static void -bin_close(void *p) -{ - track_file_t *tf = (track_file_t *) p; - - if (tf == NULL) - return; - - if (tf->file != NULL) { - fclose(tf->file); - tf->file = NULL; - } - - memset(tf->fn, 0x00, sizeof(tf->fn)); - - free(p); -} - - -static track_file_t * -bin_init(const wchar_t *filename, int *error) -{ - track_file_t *tf = (track_file_t *) malloc(sizeof(track_file_t)); - - memset(tf->fn, 0x00, sizeof(tf->fn)); - wcscpy(tf->fn, filename); - tf->file = plat_fopen64(tf->fn, L"rb"); - cdrom_image_backend_log("CDROM: binary_open(%ls) = %08lx\n", tf->fn, tf->file); - - *error = (tf->file == NULL); - - /* Set the function pointers. */ - if (!*error) { - tf->read = bin_read; - tf->get_length = bin_get_length; - tf->close = bin_close; - } - - return tf; -} - - -static track_file_t * -track_file_init(const wchar_t *filename, int *error) -{ - /* Current we only support .BIN files, either combined or one per - track. In the future, more is planned. */ - return bin_init(filename, error); -} - - -static void -track_file_close(track_t *trk) -{ - if (trk == NULL) - return; - - if (trk->file == NULL) - return; - - trk->file->close(trk->file); - trk->file = NULL; -} - - -/* Root functions. */ -static void -cdi_clear_tracks(cd_img_t *cdi) -{ - int i; - track_file_t *last = NULL; - track_t *cur = NULL; - - if ((cdi->tracks == NULL) || (cdi->tracks_num == 0)) - return; - - for (i = 0; i < cdi->tracks_num; i++) { - cur = &cdi->tracks[i]; - - if (cur->file != last) { - track_file_close(cur); - last = cur->file; - } - } - - /* Now free the array. */ - free(cdi->tracks); - cdi->tracks = NULL; - - /* Mark that there's no tracks. */ - cdi->tracks_num = 0; -} - - -void -cdi_close(cd_img_t *cdi) -{ - cdi_clear_tracks(cdi); - free(cdi); -} - - -int -cdi_set_device(cd_img_t *cdi, const wchar_t *path) -{ - if (cdi_load_cue(cdi, path)) - return 1; - - if (cdi_load_iso(cdi, path)) - return 1; - - return 0; -} - - -/* TODO: This never returns anything other than 1, should it even be an int? */ -int -cdi_get_audio_tracks(cd_img_t *cdi, int *st_track, int *end, TMSF *lead_out) -{ - *st_track = 1; - *end = cdi->tracks_num - 1; - FRAMES_TO_MSF(cdi->tracks[*end].start + 150, &lead_out->min, &lead_out->sec, &lead_out->fr); - - return 1; -} - - -/* This replaces both Info and EndInfo, they are specified by a variable. */ -int -cdi_get_audio_track_info(cd_img_t *cdi, int end, int track, int *track_num, TMSF *start, uint8_t *attr) -{ - track_t *trk = &cdi->tracks[track - 1]; - int pos = trk->start + 150; - - if ((track < 1) || (track > cdi->tracks_num)) - return 0; - - pos = trk->start + 150; - - FRAMES_TO_MSF(pos, &start->min, &start->sec, &start->fr); - *track_num = trk->track_number; - *attr = trk->attr; - - return 1; -} - - -int -cdi_get_track(cd_img_t *cdi, uint32_t sector) -{ - int i; - track_t *cur, *next; - - /* There must be at least two tracks - data and lead out. */ - if (cdi->tracks_num < 2) - return -1; - - /* This has a problem - the code skips the last track, which is - lead out - is that correct? */ - for (i = 0; i < (cdi->tracks_num - 1); i++) { - cur = &cdi->tracks[i]; - next = &cdi->tracks[i + 1]; - if ((cur->start <= sector) && (sector < next->start)) - return cur->number; - } - - return -1; -} - - -/* TODO: See if track start is adjusted by 150 or not. */ -int -cdi_get_audio_sub(cd_img_t *cdi, uint32_t sector, uint8_t *attr, uint8_t *track, uint8_t *index, TMSF *rel_pos, TMSF *abs_pos) -{ - int cur_track = cdi_get_track(cdi, sector); - track_t *trk; - - if (cur_track < 1) - return 0; - - *track = (uint8_t) cur_track; - trk = &cdi->tracks[*track - 1]; - *attr = trk->attr; - *index = 1; - - FRAMES_TO_MSF(sector + 150, &abs_pos->min, &abs_pos->sec, &abs_pos->fr); - - /* Absolute position should be adjusted by 150, not the relative ones. */ - FRAMES_TO_MSF(sector - trk->start, &rel_pos->min, &rel_pos->sec, &rel_pos->fr); - - return 1; -} - - -int -cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector) -{ - size_t length; - int track = cdi_get_track(cdi, sector) - 1; - uint64_t sect = (uint64_t) sector, seek; - track_t *trk; - int track_is_raw, ret; - int raw_size, cooked_size; - uint64_t offset = 0ULL; - int m = 0, s = 0, f = 0; - - if (track < 0) - return 0; - - trk = &cdi->tracks[track]; - track_is_raw = ((trk->sector_size == RAW_SECTOR_SIZE) || (trk->sector_size == 2448)); - if (raw && !track_is_raw) - return 0; - seek = trk->skip + ((sect - trk->start) * trk->sector_size); - - if (track_is_raw) - raw_size = trk->sector_size; - else - raw_size = 2448; - - if (trk->mode2 && (trk->form != 1)) { - if (trk->form == 2) - cooked_size = (track_is_raw ? 2328 : trk->sector_size); /* Both 2324 + ECC and 2328 variants are valid. */ - else - cooked_size = 2336; - } else - cooked_size = COOKED_SECTOR_SIZE; - - length = (raw ? raw_size : cooked_size); - - if (trk->mode2 && (trk->form >= 1)) - offset = 24ULL; - else - offset = 16ULL; - - if (raw && !track_is_raw) { - memset(buffer, 0x00, 2448); - ret = trk->file->read(trk->file, buffer + offset, seek, length); - if (!ret) - return 0; - /* Construct the rest of the raw sector. */ - memset(buffer + 1, 0xff, 10); - buffer += 12; - FRAMES_TO_MSF(sector + 150, &m, &s, &f); - /* These have to be BCD. */ - buffer[12] = CDROM_BCD(m & 0xff); - buffer[13] = CDROM_BCD(s & 0xff); - buffer[14] = CDROM_BCD(f & 0xff); - buffer[15] = trk->mode2 ? 2 : 1; /* Data, should reflect the actual sector type. */ - return 1; - } else if (!raw && track_is_raw) - return trk->file->read(trk->file, buffer, seek + offset, length); - else - return trk->file->read(trk->file, buffer, seek, length); -} - - -int -cdi_read_sectors(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector, uint32_t num) -{ - int sector_size, success = 1; - uint8_t buf_len, *buf; - uint32_t i; - - /* TODO: This fails to account for Mode 2. Shouldn't we have a function - to get sector size? */ - sector_size = raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE; - buf_len = num * sector_size; - buf = (uint8_t *) malloc(buf_len * sizeof(uint8_t)); - - for (i = 0; i < num; i++) { - success = cdi_read_sector(cdi, &buf[i * sector_size], raw, sector + i); - if (!success) - break; - } - - memcpy((void *) buffer, buf, buf_len); - free(buf); - buf = NULL; - - return success; -} - - -/* TODO: Do CUE+BIN images with a sector size of 2448 even exist? */ -int -cdi_read_sector_sub(cd_img_t *cdi, uint8_t *buffer, uint32_t sector) -{ - int track = cdi_get_track(cdi, sector) - 1; - track_t *trk; - uint64_t s = (uint64_t) sector, seek; - - if (track < 0) - return 0; - - trk = &cdi->tracks[track]; - seek = trk->skip + ((s - trk->start) * trk->sector_size); - if (trk->sector_size != 2448) - return 0; - - return trk->file->read(trk->file, buffer, seek, 2448); -} - - -int -cdi_get_sector_size(cd_img_t *cdi, uint32_t sector) -{ - int track = cdi_get_track(cdi, sector) - 1; - track_t *trk; - - if (track < 0) - return 0; - - trk = &cdi->tracks[track]; - return trk->sector_size; -} - - -int -cdi_is_mode2(cd_img_t *cdi, uint32_t sector) -{ - int track = cdi_get_track(cdi, sector) - 1; - track_t *trk; - - if (track < 0) - return 0; - - trk = &cdi->tracks[track]; - - return !!(trk->mode2); -} - - -int -cdi_get_mode2_form(cd_img_t *cdi, uint32_t sector) -{ - int track = cdi_get_track(cdi, sector) - 1; - track_t *trk; - - if (track < 0) - return 0; - - trk = &cdi->tracks[track]; - - return trk->form; -} - - -static int -cdi_can_read_pvd(track_file_t *file, uint64_t sector_size, int mode2, int form) -{ - uint8_t pvd[COOKED_SECTOR_SIZE]; - uint64_t seek = 16ULL * sector_size; /* First VD is located at sector 16. */ - - if ((!mode2 || (form == 0)) && (sector_size == RAW_SECTOR_SIZE)) - seek += 16; - if (mode2 && (form >= 1)) - seek += 24; - - file->read(file, pvd, seek, COOKED_SECTOR_SIZE); - - return ((pvd[0] == 1 && !strncmp((char*)(&pvd[1]), "CD001", 5) && pvd[6] == 1) || - (pvd[8] == 1 && !strncmp((char*)(&pvd[9]), "CDROM", 5) && pvd[14] == 1)); -} - - -/* This reallocates the array and returns the pointer to the last track. */ -static void -cdi_track_push_back(cd_img_t *cdi, track_t *trk) -{ - /* This has to be done so situations in which realloc would misbehave - can be detected and reported to the user. */ - if ((cdi->tracks != NULL) && (cdi->tracks_num == 0)) - fatal("CD-ROM Image: Non-null tracks array at 0 loaded tracks\n"); - if ((cdi->tracks == NULL) && (cdi->tracks_num != 0)) - fatal("CD-ROM Image: Null tracks array at non-zero loaded tracks\n"); - - cdi->tracks = realloc(cdi->tracks, (cdi->tracks_num + 1) * sizeof(track_t)); - memcpy(&(cdi->tracks[cdi->tracks_num]), trk, sizeof(track_t)); - cdi->tracks_num++; -} - - -int -cdi_load_iso(cd_img_t *cdi, const wchar_t *filename) -{ - int error; - track_t trk; - - cdi->tracks = NULL; - cdi->tracks_num = 0; - - memset(&trk, 0, sizeof(track_t)); - - /* Data track (shouldn't there be a lead in track?). */ - trk.file = bin_init(filename, &error); - if (error) { - if (trk.file != NULL) - trk.file->close(trk.file); - return 0; - } - trk.number = 1; - trk.track_number = 1; - trk.attr = DATA_TRACK; - - /* Try to detect ISO type. */ - trk.form = 0; - trk.mode2 = 0; - /* TODO: Merge the first and last cases since they result in the same thing. */ - if (cdi_can_read_pvd(trk.file, RAW_SECTOR_SIZE, 0, 0)) - trk.sector_size = RAW_SECTOR_SIZE; - else if (cdi_can_read_pvd(trk.file, 2336, 1, 0)) { - trk.sector_size = 2336; - trk.mode2 = 1; - } else if (cdi_can_read_pvd(trk.file, 2324, 1, 2)) { - trk.sector_size = 2324; - trk.mode2 = 1; - trk.form = 2; - } else if (cdi_can_read_pvd(trk.file, RAW_SECTOR_SIZE, 1, 0)) { - trk.sector_size = RAW_SECTOR_SIZE; - trk.mode2 = 1; - } else { - /* We use 2048 mode 1 as the default. */ - trk.sector_size = COOKED_SECTOR_SIZE; - } - - trk.length = trk.file->get_length(trk.file) / trk.sector_size; - cdi_track_push_back(cdi, &trk); - - /* Lead out track. */ - trk.number = 2; - trk.track_number = 0xAA; - trk.attr = 0x16; /* Was originally 0x00, but I believe 0x16 is appropriate. */ - trk.start = trk.length; - trk.length = 0; - trk.file = NULL; - cdi_track_push_back(cdi, &trk); - - return 1; -} - - -static int -cdi_cue_get_buffer(char *str, char **line, int up) -{ - char *s = *line; - char *p = str; - int quote = 0; - int done = 0; - int space = 1; - - /* Copy to local buffer until we have end of string or whitespace. */ - while (! done) { - switch(*s) { - case '\0': - if (quote) { - /* Ouch, unterminated string.. */ - return 0; - } - done = 1; - break; - - case '\"': - quote ^= 1; - break; - - case ' ': - case '\t': - if (space) - break; - - if (! quote) { - done = 1; - break; - } - /*FALLTHROUGH*/ - - default: - if (up && islower((int) *s)) - *p++ = toupper((int) *s); - else - *p++ = *s; - space = 0; - break; - } - - if (! done) - s++; - } - *p = '\0'; - - *line = s; - - return 1; -} - - -static int -cdi_cue_get_keyword(char **dest, char **line) -{ - char temp[1024]; - int success; - - success = cdi_cue_get_buffer(temp, line, 1); - if (success) - *dest = temp; - - return success; -} - - -/* Get a string from the input line, handling quotes properly. */ -static uint64_t -cdi_cue_get_number(char **line) -{ - char temp[128]; - uint64_t num; - - if (!cdi_cue_get_buffer(temp, line, 0)) - return 0; - - if (sscanf(temp, "%" PRIu64, &num) != 1) - return 0; - - return num; -} - - -static int -cdi_cue_get_frame(uint64_t *frames, char **line) -{ - char temp[128]; - int min, sec, fr; - int success; - - success = cdi_cue_get_buffer(temp, line, 0); - if (! success) return 0; - - success = sscanf(temp, "%d:%d:%d", &min, &sec, &fr) == 3; - if (! success) return 0; - - *frames = MSF_TO_FRAMES(min, sec, fr); - - return 1; -} - - -static int -cdi_add_track(cd_img_t *cdi, track_t *cur, uint64_t *shift, uint64_t prestart, uint64_t *total_pregap, uint64_t cur_pregap) -{ - /* Frames between index 0 (prestart) and 1 (current track start) must be skipped. */ - uint64_t skip, temp; - track_t *prev = NULL; - - if (prestart > 0) { - if (prestart > cur->start) - return 0; - skip = cur->start - prestart; - } else - skip = 0ULL; - - if ((cdi->tracks != NULL) && (cdi->tracks_num != 0)) - prev = &cdi->tracks[cdi->tracks_num - 1]; - - /* First track (track number must be 1). */ - if (cdi->tracks_num == 0) { - /* I guess this makes sure the structure is not filled with invalid data. */ - if (cur->number != 1) - return 0; - cur->skip = skip * cur->sector_size; - cur->start += cur_pregap; - *total_pregap = cur_pregap; - cdi_track_push_back(cdi, cur); - return 1; - } - - /* Current track consumes data from the same file as the previous. */ - if (prev->file == cur->file) { - cur->start += *shift; - prev->length = cur->start + *total_pregap - prev->start - skip; - cur->skip += prev->skip + (prev->length * prev->sector_size) + (skip * cur->sector_size); - *total_pregap += cur_pregap; - cur->start += *total_pregap; - } else { - temp = prev->file->get_length(prev->file) - ((uint64_t) prev->skip); - prev->length = temp / ((uint64_t) prev->sector_size); - if ((temp % prev->sector_size) != 0) - prev->length++; /* Padding. */ - - cur->start += prev->start + prev->length + cur_pregap; - cur->skip = skip * cur->sector_size; - *shift += prev->start + prev->length; - *total_pregap = cur_pregap; - } - - /* Error checks. */ - if (cur->number <= 1) - return 0; - if ((prev->number + 1) != cur->number) - return 0; - if (cur->start < (prev->start + prev->length)) - return 0; - - cdi_track_push_back(cdi, cur); - - return 1; -} - - -int -cdi_load_cue(cd_img_t *cdi, const wchar_t *cuefile) -{ - track_t trk; - wchar_t pathname[MAX_FILENAME_LENGTH], filename[MAX_FILENAME_LENGTH]; - wchar_t temp[MAX_FILENAME_LENGTH]; - uint64_t shift = 0ULL, prestart = 0ULL; - uint64_t cur_pregap = 0ULL, total_pregap = 0ULL; - uint64_t frame = 0ULL, index; - int i, success; - int error, can_add_track = 0; - FILE *fp; - char buf[MAX_LINE_LENGTH], ansi[MAX_FILENAME_LENGTH]; - char *line, *command; - char *type; - - cdi->tracks = NULL; - cdi->tracks_num = 0; - - memset(&trk, 0, sizeof(track_t)); - - /* Get a copy of the filename into pathname, we need it later. */ - memset(pathname, 0, MAX_FILENAME_LENGTH * sizeof(wchar_t)); - plat_get_dirname(pathname, cuefile); - - /* Open the file. */ - fp = plat_fopen((wchar_t *) cuefile, L"r"); - if (fp == NULL) - return 0; - - success = 0; - - for (;;) { - line = buf; - - /* Read a line from the cuesheet file. */ - if (feof(fp) || fgets(buf, sizeof(buf), fp) == NULL || ferror(fp)) - break; - - /* Do two iterations to make sure to nuke even if it's \r\n or \n\r, - but do checks to make sure we're not nuking other bytes. */ - for (i = 0; i < 2; i++) { - if (strlen(buf) > 0) { - if (buf[strlen(buf) - 1] == '\n') - buf[strlen(buf) - 1] = '\0'; /* nuke trailing newline */ - else if (buf[strlen(buf) - 1] == '\r') - buf[strlen(buf) - 1] = '\0'; /* nuke trailing newline */ - } - } - - success = cdi_cue_get_keyword(&command, &line); - - if (!strcmp(command, "TRACK")) { - if (can_add_track) - success = cdi_add_track(cdi, &trk, &shift, prestart, &total_pregap, cur_pregap); - else - success = 1; - - trk.start = 0; - trk.skip = 0; - cur_pregap = 0; - prestart = 0; - - trk.number = cdi_cue_get_number(&line); - trk.track_number = trk.number; - success = cdi_cue_get_keyword(&type, &line); - if (!success) - break; - - trk.form = 0; - trk.mode2 = 0; - - if (!strcmp(type, "AUDIO")) { - trk.sector_size = RAW_SECTOR_SIZE; - trk.attr = AUDIO_TRACK; - } else if (!strcmp(type, "MODE1/2048")) { - trk.sector_size = COOKED_SECTOR_SIZE; - trk.attr = DATA_TRACK; - } else if (!strcmp(type, "MODE1/2352")) { - trk.sector_size = RAW_SECTOR_SIZE; - trk.attr = DATA_TRACK; - } else if (!strcmp(type, "MODE1/2448")) { - trk.sector_size = 2448; - trk.attr = DATA_TRACK; - } else if (!strcmp(type, "MODE2/2048")) { - trk.form = 1; - trk.sector_size = COOKED_SECTOR_SIZE; - trk.attr = DATA_TRACK; - trk.mode2 = 1; - } else if (!strcmp(type, "MODE2/2324")) { - trk.form = 2; - trk.sector_size = 2324; - trk.attr = DATA_TRACK; - trk.mode2 = 1; - } else if (!strcmp(type, "MODE2/2328")) { - trk.form = 2; - trk.sector_size = 2328; - trk.attr = DATA_TRACK; - trk.mode2 = 1; - } else if (!strcmp(type, "MODE2/2336")) { - trk.sector_size = 2336; - trk.attr = DATA_TRACK; - trk.mode2 = 1; - } else if (!strcmp(type, "MODE2/2352")) { - trk.form = 1; /* Assume this is XA Mode 2 Form 1. */ - trk.sector_size = RAW_SECTOR_SIZE; - trk.attr = DATA_TRACK; - trk.mode2 = 1; - } else if (!strcmp(type, "MODE2/2448")) { - trk.form = 1; /* Assume this is XA Mode 2 Form 1. */ - trk.sector_size = 2448; - trk.attr = DATA_TRACK; - trk.mode2 = 1; - } else if (!strcmp(type, "CDG/2448")) { - trk.sector_size = 2448; - trk.attr = DATA_TRACK; - trk.mode2 = 1; - } else if (!strcmp(type, "CDI/2336")) { - trk.sector_size = 2336; - trk.attr = DATA_TRACK; - trk.mode2 = 1; - } else if (!strcmp(type, "CDI/2352")) { - trk.sector_size = RAW_SECTOR_SIZE; - trk.attr = DATA_TRACK; - trk.mode2 = 1; - } else - success = 0; - - can_add_track = 1; - } else if (!strcmp(command, "INDEX")) { - index = cdi_cue_get_number(&line); - success = cdi_cue_get_frame(&frame, &line); - - switch(index) { - case 0: - prestart = frame; - break; - - case 1: - trk.start = frame; - break; - - default: - /* ignore other indices */ - break; - } - } else if (!strcmp(command, "FILE")) { - if (can_add_track) - success = cdi_add_track(cdi, &trk, &shift, prestart, &total_pregap, cur_pregap); - else - success = 1; - can_add_track = 0; - - memset(ansi, 0, MAX_FILENAME_LENGTH * sizeof(char)); - memset(filename, 0, MAX_FILENAME_LENGTH * sizeof(wchar_t)); - - success = cdi_cue_get_buffer(ansi, &line, 0); - if (!success) - break; - success = cdi_cue_get_keyword(&type, &line); - if (!success) - break; - - trk.file = NULL; - error = 1; - - if (!strcmp(type, "BINARY")) { - memset(temp, 0, MAX_FILENAME_LENGTH * sizeof(wchar_t)); - mbstowcs(temp, ansi, sizeof_w(temp)); - plat_append_filename(filename, pathname, temp); - trk.file = track_file_init(filename, &error); - } - if (error) { -#ifdef ENABLE_cdrom_image_backend_log - cdrom_image_backend_log("CUE: cannot open fille '%ls' in cue sheet!\n", - filename); -#endif - if (trk.file != NULL) { - trk.file->close(trk.file); - trk.file = NULL; - } - success = 0; - } - } else if (!strcmp(command, "PREGAP")) - success = cdi_cue_get_frame(&cur_pregap, &line); - else if (!strcmp(command, "CATALOG") || !strcmp(command, "CDTEXTFILE") || !strcmp(command, "FLAGS") || !strcmp(command, "ISRC") || - !strcmp(command, "PERFORMER") || !strcmp(command, "POSTGAP") || !strcmp(command, "REM") || - !strcmp(command, "SONGWRITER") || !strcmp(command, "TITLE") || !strcmp(command, "")) { - /* Ignored commands. */ - success = 1; - } else { -#ifdef ENABLE_cdrom_image_backend_log - cdrom_image_backend_log("CUE: unsupported command '%s' in cue sheet!\n", - command.c_str()); -#endif - success = 0; - } - - if (!success) - break; - } - - fclose(fp); - if (!success) - return 0; - - /* Add last track. */ - if (!cdi_add_track(cdi, &trk, &shift, prestart, &total_pregap, cur_pregap)) - return 0; - - /* Add lead out track. */ - trk.number++; - trk.track_number = 0xAA; - trk.attr = 0x16; /* Was 0x00 but I believe 0x16 is appropriate. */ - trk.start = 0; - trk.length = 0; - trk.file = NULL; - if (!cdi_add_track(cdi, &trk, &shift, 0, &total_pregap, 0)) - return 0; - - return 1; -} - - -int -cdi_has_data_track(cd_img_t *cdi) -{ - int i; - - if ((cdi == NULL) || (cdi->tracks == NULL)) - return 0; - - /* Data track has attribute 0x14. */ - for (i = 0; i < cdi->tracks_num; i++) { - if (cdi->tracks[i].attr == DATA_TRACK) - return 1; - } - - return 0; -} - - int cdi_has_audio_track(cd_img_t *cdi) { From fb088329e10664ded7f6b179edaf607735a5dca2 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 13 Jan 2020 21:46:45 +0100 Subject: [PATCH 052/177] Fixed NULL pointer dereferences in the CD-ROM image code. --- src/cdrom/cdrom_image_backend.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/cdrom/cdrom_image_backend.c b/src/cdrom/cdrom_image_backend.c index 61260b44d..f39dfe01f 100644 --- a/src/cdrom/cdrom_image_backend.c +++ b/src/cdrom/cdrom_image_backend.c @@ -9,7 +9,7 @@ * CD-ROM image file handling module, translated to C from * cdrom_dosbox.cpp. * - * Version: @(#)cdrom_image_backend.c 1.0.3 2020/01/13 + * Version: @(#)cdrom_image_backend.c 1.0.4 2020/01/13 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -136,9 +136,7 @@ bin_init(const wchar_t *filename, int *error) track_file_t *tf = (track_file_t *) malloc(sizeof(track_file_t)); if (tf == NULL) { - tf->read = NULL; - tf->get_length = NULL; - tf->close = NULL; + *error = 1; return NULL; } @@ -157,9 +155,6 @@ bin_init(const wchar_t *filename, int *error) } else { free(tf); tf = NULL; - tf->read = NULL; - tf->get_length = NULL; - tf->close = NULL; } return tf; From aa73f2215f94184e32ec891d2854a4f53e6ce290 Mon Sep 17 00:00:00 2001 From: Melissa Goad Date: Sat, 11 Jan 2020 18:06:57 -0600 Subject: [PATCH 053/177] Preliminary port of PCem's FIC VA-503P motherboard --- src/chipset/chipset.h | 5 + src/chipset/via_mvp3.c | 295 +++++++++++++++++++++ src/machine/m_at_socket7_s7.c | 38 ++- src/machine/machine.h | 4 + src/machine/machine_table_new.c | 4 + src/sst_flash.c | 301 ++++++++++++++++++++++ src/sst_flash.h | 19 ++ src/via_mvp3_sb.c | 444 ++++++++++++++++++++++++++++++++ src/via_mvp3_sb.h | 22 ++ src/win/Makefile_ndr.mingw | 11 + 10 files changed, 1141 insertions(+), 2 deletions(-) create mode 100644 src/chipset/via_mvp3.c create mode 100644 src/sst_flash.c create mode 100644 src/sst_flash.h create mode 100644 src/via_mvp3_sb.c create mode 100644 src/via_mvp3_sb.h diff --git a/src/chipset/chipset.h b/src/chipset/chipset.h index bf2cda160..50f3536f7 100644 --- a/src/chipset/chipset.h +++ b/src/chipset/chipset.h @@ -61,6 +61,11 @@ extern const device_t sis_85c496_device; extern const device_t sis_85c50x_device; #endif +#if defined(DEV_BRANCH) && defined(USE_SS7) +/* VIA */ +extern const device_t via_mvp3_device; +#endif + /* WD */ extern const device_t wd76c10_device; diff --git a/src/chipset/via_mvp3.c b/src/chipset/via_mvp3.c new file mode 100644 index 000000000..dfeba12c2 --- /dev/null +++ b/src/chipset/via_mvp3.c @@ -0,0 +1,295 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the VIA MVP3 chip. + * + * Version: @(#)via_mvp3.c 1.0.1 2019/10/19 + * + * Authors: Sarah Walker, + * Miran Grca, + * Melissa Goad, + * + * Copyright 2020 Miran Grca, Melissa Goad. + */ +#include +#include +#include +#include +#include +#include "../86box.h" +#include "../mem.h" +#include "../io.h" +#include "../rom.h" +#include "../pci.h" +#include "../device.h" +#include "../keyboard.h" +#include "chipset.h" + +typedef struct via_mvp3_t +{ + uint8_t pci_conf[2][256]; +} via_mvp3_t; + +static void +via_mvp3_recalcmapping(via_mvp3_t *dev) +{ + int c, d; + uint32_t base; + + for (c = 0; c < 2; c++) { + for (d = 0; d < 4; d++) { + base = 0xc0000 + (d << 14); + switch (dev->pci_conf[0][0x61 + c] & (3 << (d << 1))) { + case 0x00: + mem_set_mem_state(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + break; + case 0x01: + mem_set_mem_state(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + break; + case 0x02: + mem_set_mem_state(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_EXTANY); + break; + case 0x03: + mem_set_mem_state(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + } + } + } + + for(d = 0; d < 2; d++) + { + base = 0xe0000 + (d << 16); + switch (dev->pci_conf[0][0x63] & (3 << (d << 1))) { + case 0x00: + mem_set_mem_state(base, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + break; + case 0x01: + mem_set_mem_state(base, 0x10000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + break; + case 0x02: + mem_set_mem_state(base, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_EXTANY); + break; + case 0x03: + mem_set_mem_state(base, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + } + } + + flushmmucache_nopc(); + shadowbios = 1; +} + +static void +via_mvp3_setup(via_mvp3_t *dev) +{ + memset(dev, 0, sizeof(via_mvp3_t)); + + /* Host Bridge */ + dev->pci_conf[0][0x00] = 0x06; /*VIA*/ + dev->pci_conf[0][0x01] = 0x11; + dev->pci_conf[0][0x02] = 0x98; /*VT82C598MVP*/ + dev->pci_conf[0][0x03] = 0x05; + + dev->pci_conf[0][0x04] = 6; + dev->pci_conf[0][0x05] = 0; + + dev->pci_conf[0][0x06] = 0x90; + dev->pci_conf[0][0x07] = 0x02; + + dev->pci_conf[0][0x09] = 0; + dev->pci_conf[0][0x0a] = 0; + dev->pci_conf[0][0x0b] = 6; + dev->pci_conf[0][0x0c] = 0; + dev->pci_conf[0][0x0d] = 0; + dev->pci_conf[0][0x0e] = 0; + dev->pci_conf[0][0x0f] = 0; + dev->pci_conf[0][0x10] = 0x08; + dev->pci_conf[0][0x34] = 0xa0; + + dev->pci_conf[0][0x5a] = 0x01; + dev->pci_conf[0][0x5b] = 0x01; + dev->pci_conf[0][0x5c] = 0x01; + dev->pci_conf[0][0x5d] = 0x01; + dev->pci_conf[0][0x5e] = 0x01; + dev->pci_conf[0][0x5f] = 0x01; + + dev->pci_conf[0][0x64] = 0xec; + dev->pci_conf[0][0x65] = 0xec; + dev->pci_conf[0][0x66] = 0xec; + dev->pci_conf[0][0x6b] = 0x01; + + dev->pci_conf[0][0xa0] = 0x02; + dev->pci_conf[0][0xa2] = 0x10; + dev->pci_conf[0][0xa4] = 0x03; + dev->pci_conf[0][0xa5] = 0x02; + dev->pci_conf[0][0xa7] = 0x07; + + /* PCI-to-PCI Bridge */ + + dev->pci_conf[1][0x00] = 0x06; /*VIA*/ + dev->pci_conf[1][0x01] = 0x11; + dev->pci_conf[1][0x02] = 0x98; /*VT82C598MVP*/ + dev->pci_conf[1][0x03] = 0x85; + + dev->pci_conf[1][0x04] = 7; + dev->pci_conf[1][0x05] = 0; + + dev->pci_conf[1][0x06] = 0x20; + dev->pci_conf[1][0x07] = 0x02; + + dev->pci_conf[1][0x09] = 0; + dev->pci_conf[1][0x0a] = 4; + dev->pci_conf[1][0x0b] = 6; + dev->pci_conf[1][0x0c] = 0; + dev->pci_conf[1][0x0d] = 0; + dev->pci_conf[1][0x0e] = 1; + dev->pci_conf[1][0x0f] = 0; + + dev->pci_conf[1][0x1c] = 0xf0; + + dev->pci_conf[1][0x20] = 0xf0; + dev->pci_conf[1][0x21] = 0xff; + dev->pci_conf[1][0x24] = 0xf0; + dev->pci_conf[1][0x25] = 0xff; +} + +static void +via_mvp3_host_bridge_write(int func, int addr, uint8_t val, void *priv) +{ + via_mvp3_t *dev = (via_mvp3_t *) priv; + + if (func) + return; + + /*Read-only addresses*/ + if ((addr < 4) || (addr >= 5 && addr < 7) + || (addr >= 8 && addr < 0xd) + || (addr >= 0xe && addr < 0x12) + || (addr >= 0x14 && addr < 0x50) + || (addr >= 0x79 && addr < 0x7e) + || (addr >= 0x85 && addr < 0x88) + || (addr >= 0x8c && addr < 0xa8) + || (addr >= 0xad && addr < 0xfd)) + return; + + switch(addr) + { + case 0x04: + dev->pci_conf[0][0x04] = (dev->pci_conf[0][0x04] & ~0x40) | (val & 0x40); + break; + case 0x07: + dev->pci_conf[0][0x07] &= ~(val & 0xb0); + case 0x61: case 0x62: case 0x63: + dev->pci_conf[0][addr] = val; + via_mvp3_recalcmapping(dev); + break; + default: + dev->pci_conf[0][addr] = val; + break; + } +} + +static void +via_mvp3_pci_bridge_write(int func, int addr, uint8_t val, void *priv) +{ + via_mvp3_t *dev = (via_mvp3_t *) priv; + + if(func != 1) return; + + /*Read-only addresses*/ + + if ((addr < 4) || (addr >= 5 && addr < 7) + || (addr >= 8 && addr < 0x18) + || (addr == 0x1b) + || (addr >= 0x1e && addr < 0x20) + || (addr >= 0x28 && addr < 0x3e) + || (addr >= 0x43)) + return; + + switch(addr) + { + case 0x04: + dev->pci_conf[1][0x04] = (dev->pci_conf[1][0x04] & ~0x47) | (val & 0x47); + break; + case 0x07: + dev->pci_conf[1][0x07] &= ~(val & 0x30); + default: + dev->pci_conf[1][addr] = val; + break; + } +} + +static uint8_t +via_mvp3_read(int func, int addr, void *priv) +{ + via_mvp3_t *dev = (via_mvp3_t *) priv; + + switch(func) + { + case 0: return dev->pci_conf[0][addr]; + case 1: return dev->pci_conf[1][addr]; + default: return 0xff; + } +} + + +static void +via_mvp3_write(int func, int addr, uint8_t val, void *priv) +{ + switch(func) + { + case 0: + via_mvp3_host_bridge_write(func, addr, val, priv); + break; + case 1: + via_mvp3_pci_bridge_write(func, addr, val, priv); + break; + } +} + +static void +via_mvp3_reset(void *priv) +{ + via_mvp3_t *dev = (via_mvp3_t *) priv; + + via_mvp3_setup(dev); +} + +static void * +via_mvp3_init(const device_t *info) +{ + via_mvp3_t *dev = (via_mvp3_t *) malloc(sizeof(via_mvp3_t)); + + pci_add_card(0, via_mvp3_read, via_mvp3_write, dev); + + via_mvp3_setup(dev); + + return dev; +} + +static void +via_mvp3_close(void *priv) +{ + via_mvp3_t *dev = (via_mvp3_t *) priv; + + free(dev); +} + +const device_t via_mvp3_device = +{ + "VIA MVP3", + DEVICE_PCI, + 0, + via_mvp3_init, + via_mvp3_close, + via_mvp3_reset, + NULL, + NULL, + NULL, + NULL +}; diff --git a/src/machine/m_at_socket7_s7.c b/src/machine/m_at_socket7_s7.c index 377a37bd5..9dfd1515a 100644 --- a/src/machine/m_at_socket7_s7.c +++ b/src/machine/m_at_socket7_s7.c @@ -12,9 +12,11 @@ * * Authors: Sarah Walker, * Miran Grca, + * Melissa Goad, * - * Copyright 2010-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2010-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2020 Melissa Goad. */ #include #include @@ -35,6 +37,8 @@ #include "../intel_sio.h" #include "../piix.h" #include "../sio.h" +#include "../sst_flash.h" +#include "../via_mvp3_sb.h" #include "../video/video.h" #include "../video/vid_cl54xx.h" #include "../video/vid_s3.h" @@ -451,3 +455,33 @@ machine_at_j656vxd_init(const machine_t *model) return ret; } + +#if defined(DEV_BRANCH) && defined(USE_SS7) +int +machine_at_mvp3_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/ficva503p/je4333.bin", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0a, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + device_add(&via_mvp3_device); + device_add(&via_mvp3_sb_device); + device_add(&keyboard_ps2_pci_device); + device_add(&w83877tf_device); + device_add(&sst_flash_39sf010_device); + + return ret; +} +#endif \ No newline at end of file diff --git a/src/machine/machine.h b/src/machine/machine.h index 7d4b52ab7..fdbc4bbe1 100644 --- a/src/machine/machine.h +++ b/src/machine/machine.h @@ -276,6 +276,10 @@ extern int machine_at_i430vx_init(const machine_t *); extern int machine_at_p55va_init(const machine_t *); extern int machine_at_j656vxd_init(const machine_t *); +#if defined(DEV_BRANCH) && defined(USE_SS7) +extern int machine_at_mvp3_init(const machine_t *); +#endif + #ifdef EMU_DEVICE_H extern const device_t *at_pb640_get_device(void); #endif diff --git a/src/machine/machine_table_new.c b/src/machine/machine_table_new.c index a46e7175c..c9ae1d598 100644 --- a/src/machine/machine_table_new.c +++ b/src/machine/machine_table_new.c @@ -192,6 +192,10 @@ const machine_t machines[] = { { "[Socket 7 VX] Jetway J656VXD", "j656vxd", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_j656vxd_init, NULL }, { "[Socket 7 VX] Shuttle HOT-557", "430vx", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_i430vx_init, NULL }, +#if defined(DEV_BRANCH) && defined(USE_SS7) + { "[Super Socket 7] FIC VA503P", "ficva503p", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 127, machine_at_mvp3_init, NULL }, +#endif + #if defined(DEV_BRANCH) && defined(USE_I686) { "[Socket 8 FX] Tyan Titan-Pro AT", "440fx", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 127, machine_at_i440fx_init, NULL }, { "[Socket 8 FX] Tyan Titan-Pro ATX", "tpatx", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 127, machine_at_s1668_init, NULL }, diff --git a/src/sst_flash.c b/src/sst_flash.c new file mode 100644 index 000000000..b5666659f --- /dev/null +++ b/src/sst_flash.c @@ -0,0 +1,301 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of an SST flash chip. + * + * Version: @(#)sst_flash.c 1.0.19 2019/06/25 + * + * Authors: Sarah Walker, + * Miran Grca, + * Melissa Goad, + * + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2020 Melissa Goad. + */ +#include +#include +#include +#include +#include +#include "86box.h" +#include "device.h" +#include "mem.h" +#include "machine/machine.h" +#include "timer.h" +#include "nvr.h" +#include "plat.h" + +typedef struct sst_t +{ + int command_state, id_mode, + erase, dirty; + + uint8_t *array; + + mem_mapping_t mapping[2], mapping_h[2]; +} sst_t; + + +static wchar_t flash_path[1024]; + + +#define SST_CHIP_ERASE 0x10 +#define SST_SECTOR_ERASE 0x30 +#define SST_ERASE 0x80 +#define SST_SET_ID_MODE 0x90 +#define SST_BYTE_PROGRAM 0xa0 +#define SST_CLEAR_ID_MODE 0xf0 + + +static void +sst_new_command(sst_t *dev, uint8_t val) +{ + switch (val) { + case SST_CHIP_ERASE: + if (dev->erase) + memset(dev->array, 0xff, 0x20000); + dev->command_state = 0; + dev->erase = 0; + break; + + case SST_ERASE: + dev->command_state = 0; + dev->erase = 1; + break; + + case SST_SET_ID_MODE: + if (!dev->id_mode) + dev->id_mode = 1; + dev->command_state = 0; + dev->erase = 0; + break; + + case SST_BYTE_PROGRAM: + dev->command_state = 3; + dev->erase = 0; + break; + + case SST_CLEAR_ID_MODE: + if (dev->id_mode) + dev->id_mode = 0; + dev->command_state = 0; + dev->erase = 0; + break; + + default: + dev->command_state = 0; + dev->erase = 0; + } +} + + +static void +sst_sector_erase(sst_t *dev, uint32_t addr) +{ + memset(&dev->array[addr & 0x1f000], 0xff, 4096); + dev->dirty = 1; +} + + +static uint8_t +sst_read_id(uint32_t addr, void *p) +{ + if ((addr & 0xffff) == 0) + return 0xbf; /* SST */ + else if ((addr & 0xffff) == 1) + return 0xb5; /* 39SF010 */ + else + return 0xff; +} + + +static void +sst_write(uint32_t addr, uint8_t val, void *p) +{ + sst_t *dev = (sst_t *) p; + + switch (dev->command_state) { + case 0: + if (val == 0xf0) { + if (dev->id_mode) + dev->id_mode = 0; + } else if ((addr & 0xffff) == 0x5555 && val == 0xaa) + dev->command_state = 1; + else + dev->command_state = 0; + break; + case 1: + if ((addr & 0xffff) == 0x2aaa && val == 0x55) + dev->command_state = 2; + else + dev->command_state = 0; + break; + case 2: + if ((addr & 0xffff) == 0x5555) + sst_new_command(dev, val); + else if ((val == SST_SECTOR_ERASE) && dev->erase) { + sst_sector_erase(dev, addr); + dev->command_state = 0; + } else + dev->command_state = 0; + break; + case 3: + dev->array[addr & 0x1ffff] = val; + dev->command_state = 0; + dev->dirty = 1; + break; + } +} + + +static uint8_t +sst_read(uint32_t addr, void *p) +{ + sst_t *dev = (sst_t *) p; + uint8_t ret = 0xff; + + addr &= 0x000fffff; + + if (dev->id_mode) + ret = sst_read_id(addr, p); + else { + if ((addr >= biosaddr) && (addr <= (biosaddr + biosmask))) + ret = dev->array[addr - biosaddr]; + } + + return ret; +} + + +static uint16_t +sst_readw(uint32_t addr, void *p) +{ + sst_t *dev = (sst_t *) p; + uint16_t ret = 0xffff; + + addr &= 0x000fffff; + + if (dev->id_mode) + ret = sst_read(addr, p) | (sst_read(addr + 1, p) << 8); + else { + if ((addr >= biosaddr) && (addr <= (biosaddr + biosmask))) + ret = *(uint16_t *)&dev->array[addr - biosaddr]; + } + + return ret; +} + + +static uint32_t +sst_readl(uint32_t addr, void *p) +{ + sst_t *dev = (sst_t *) p; + uint32_t ret = 0xffffffff; + + addr &= 0x000fffff; + + if (dev->id_mode) + ret = sst_readw(addr, p) | (sst_readw(addr + 2, p) << 16); + else { + if ((addr >= biosaddr) && (addr <= (biosaddr + biosmask))) + ret = *(uint32_t *)&dev->array[addr - biosaddr]; + } + + return ret; +} + + +static void +sst_add_mappings(sst_t *dev) +{ + int max = 2, i = 0; + uint32_t base, fbase; + + for (i = 0; i < 2; i++) { + base = 0xe0000 + (i << 16); + fbase = base & biosmask; + + memcpy(&dev->array[fbase], &rom[base & biosmask], 0x10000); + + mem_mapping_add(&(dev->mapping[i]), base, 0x10000, + sst_read, sst_readw, sst_readl, + sst_write, NULL, NULL, + dev->array + fbase, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROMCS, (void *) dev); + mem_mapping_add(&(dev->mapping_h[i]), (base | 0xfff00000) - 0x40000, 0x10000, + sst_read, sst_readw, sst_readl, + sst_write, NULL, NULL, + dev->array + fbase, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROMCS, (void *) dev); + } +} + + +static void * +sst_39sf010_init(const device_t *info) +{ + FILE *f; + sst_t *dev = malloc(sizeof(sst_t)); + memset(dev, 0, sizeof(sst_t)); + + size_t l = strlen(machine_get_internal_name_ex(machine))+1; + wchar_t *machine_name = (wchar_t *) malloc(l * sizeof(wchar_t)); + mbstowcs(machine_name, machine_get_internal_name_ex(machine), l); + l = wcslen(machine_name)+5; + wchar_t *flash_name = (wchar_t *)malloc(l*sizeof(wchar_t)); + swprintf(flash_name, l, L"%ls.bin", machine_name); + + wcscpy(flash_path, flash_name); + + mem_mapping_disable(&bios_mapping); + mem_mapping_disable(&bios_high_mapping); + + dev->array = (uint8_t *) malloc(biosmask + 1); + memset(dev->array, 0xff, biosmask + 1); + + sst_add_mappings(dev); + + f = nvr_fopen(flash_path, L"rb"); + if (f) { + fread(&(dev->array[0x00000]), 0x20000, 1, f); + fclose(f); + } + + free(flash_name); + free(machine_name); + + return dev; +} + + +static void +sst_39sf010_close(void *p) +{ + FILE *f; + sst_t *dev = (sst_t *)p; + + f = nvr_fopen(flash_path, L"wb"); + fwrite(&(dev->array[0x00000]), 0x20000, 1, f); + fclose(f); + + free(dev->array); + dev->array = NULL; + + free(dev); +} + + +const device_t sst_flash_39sf010_device = +{ + "SST 39SF010 Flash BIOS", + 0, + 0, + sst_39sf010_init, + sst_39sf010_close, + NULL, + NULL, NULL, NULL, NULL +}; \ No newline at end of file diff --git a/src/sst_flash.h b/src/sst_flash.h new file mode 100644 index 000000000..f919e73d1 --- /dev/null +++ b/src/sst_flash.h @@ -0,0 +1,19 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of an SST flash chip. + * + * Version: @(#)sst_flash.h 1.0.2 2019/06/25 + * + * Author: Melissa Goad, + * Copyright 2020 Melissa Goad. + */ + +#if defined(DEV_BRANCH) && defined(USE_SS7) +extern const device_t sst_flash_39sf010_device; +#endif \ No newline at end of file diff --git a/src/via_mvp3_sb.c b/src/via_mvp3_sb.c new file mode 100644 index 000000000..1fa42889c --- /dev/null +++ b/src/via_mvp3_sb.c @@ -0,0 +1,444 @@ +/* + * 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. + * + * Emulation of the VIA Apollo MVP3 southbridge + * + * Version: @(#)via_mvp3_sb.c 1.0.22 2018/10/31 + * + * Authors: Sarah Walker, + * Miran Grca, + * Melissa Goad, + * + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2020 Melissa Goad. + */ + +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include "86box.h" +#include "cdrom/cdrom.h" +#include "cpu/cpu.h" +#include "scsi/scsi_device.h" +#include "scsi/scsi_cdrom.h" +#include "dma.h" +#include "io.h" +#include "device.h" +#include "apm.h" +#include "keyboard.h" +#include "mem.h" +#include "pci.h" +#include "pic.h" +#include "port_92.h" +#include "disk/hdc.h" +#include "disk/hdc_ide.h" +#include "disk/hdc_ide_sff8038i.h" +#include "disk/zip.h" +#include "machine/machine.h" +#include "via_mvp3_sb.h" + +typedef struct +{ + uint8_t pci_isa_regs[256]; + uint8_t ide_regs[256]; + uint8_t usb_regs[256]; + uint8_t power_regs[256]; + sff8038i_t *bm[2]; +} via_mvp3_sb_t; + +static void +via_mvp3_sb_reset_hard(void *priv) +{ + via_mvp3_sb_t *via_mvp3_sb = (via_mvp3_sb_t *) priv; + + uint16_t old_base = (via_mvp3_sb->ide_regs[0x20] & 0xf0) | (via_mvp3_sb->ide_regs[0x21] << 8); + + sff_bus_master_reset(via_mvp3_sb->bm[0], old_base); + sff_bus_master_reset(via_mvp3_sb->bm[1], old_base + 8); + + memset(via_mvp3_sb->pci_isa_regs, 0, 256); + memset(via_mvp3_sb->ide_regs, 0, 256); + memset(via_mvp3_sb->usb_regs, 0, 256); + memset(via_mvp3_sb->power_regs, 0, 256); + + via_mvp3_sb->pci_isa_regs[0x00] = 0x06; via_mvp3_sb->pci_isa_regs[0x01] = 0x11; /*VIA*/ + via_mvp3_sb->pci_isa_regs[0x02] = 0x86; via_mvp3_sb->pci_isa_regs[0x03] = 0x05; /*VT82C586B*/ + via_mvp3_sb->pci_isa_regs[0x04] = 0x0f; + via_mvp3_sb->pci_isa_regs[0x07] = 0x02; + via_mvp3_sb->pci_isa_regs[0x0a] = 0x01; + via_mvp3_sb->pci_isa_regs[0x0b] = 0x06; + via_mvp3_sb->pci_isa_regs[0x0e] = 0x80; + + via_mvp3_sb->pci_isa_regs[0x48] = 0x01; + via_mvp3_sb->pci_isa_regs[0x4a] = 0x04; + via_mvp3_sb->pci_isa_regs[0x4f] = 0x03; + + via_mvp3_sb->pci_isa_regs[0x50] = 0x24; + via_mvp3_sb->pci_isa_regs[0x59] = 0x04; + + //IDE registers + via_mvp3_sb->ide_regs[0x00] = 0x06; via_mvp3_sb->ide_regs[0x01] = 0x11; /*VIA*/ + via_mvp3_sb->ide_regs[0x02] = 0x71; via_mvp3_sb->ide_regs[0x03] = 0x05; /*VT82C586B*/ + via_mvp3_sb->ide_regs[0x04] = 0x80; + via_mvp3_sb->ide_regs[0x06] = 0x80; via_mvp3_sb->ide_regs[0x07] = 0x02; + via_mvp3_sb->ide_regs[0x09] = 0x85; + via_mvp3_sb->ide_regs[0x0a] = 0x01; + via_mvp3_sb->ide_regs[0x0b] = 0x01; + + via_mvp3_sb->ide_regs[0x10] = 0xf0; via_mvp3_sb->ide_regs[0x11] = 0x01; + via_mvp3_sb->ide_regs[0x14] = 0xf4; via_mvp3_sb->ide_regs[0x15] = 0x03; + via_mvp3_sb->ide_regs[0x18] = 0x70; via_mvp3_sb->ide_regs[0x19] = 0x01; + via_mvp3_sb->ide_regs[0x1c] = 0x74; via_mvp3_sb->ide_regs[0x1d] = 0x03; + via_mvp3_sb->ide_regs[0x20] = 0x01; via_mvp3_sb->ide_regs[0x21] = 0xcc; + + via_mvp3_sb->ide_regs[0x3c] = 0x0e; + + via_mvp3_sb->ide_regs[0x40] = 0x08; + via_mvp3_sb->ide_regs[0x41] = 0x02; + via_mvp3_sb->ide_regs[0x42] = 0x09; + via_mvp3_sb->ide_regs[0x43] = 0x3a; + via_mvp3_sb->ide_regs[0x44] = 0x68; + via_mvp3_sb->ide_regs[0x46] = 0xc0; + via_mvp3_sb->ide_regs[0x48] = 0xa8; via_mvp3_sb->ide_regs[0x49] = 0xa8; + via_mvp3_sb->ide_regs[0x4a] = 0xa8; via_mvp3_sb->ide_regs[0x4b] = 0xa8; + via_mvp3_sb->ide_regs[0x4c] = 0xff; + via_mvp3_sb->ide_regs[0x4e] = 0xff; + via_mvp3_sb->ide_regs[0x4f] = 0xff; + via_mvp3_sb->ide_regs[0x50] = 0x03; via_mvp3_sb->ide_regs[0x51] = 0x03; + via_mvp3_sb->ide_regs[0x52] = 0x03; via_mvp3_sb->ide_regs[0x53] = 0x03; + + via_mvp3_sb->ide_regs[0x61] = 0x02; + via_mvp3_sb->ide_regs[0x69] = 0x02; + + via_mvp3_sb->usb_regs[0x00] = 0x06; via_mvp3_sb->usb_regs[0x01] = 0x11; /*VIA*/ + via_mvp3_sb->usb_regs[0x02] = 0x38; via_mvp3_sb->usb_regs[0x03] = 0x30; + via_mvp3_sb->usb_regs[0x04] = 0x00; via_mvp3_sb->usb_regs[0x05] = 0x00; + via_mvp3_sb->usb_regs[0x06] = 0x00; via_mvp3_sb->usb_regs[0x07] = 0x02; + via_mvp3_sb->usb_regs[0x0a] = 0x03; + via_mvp3_sb->usb_regs[0x0b] = 0x0c; + via_mvp3_sb->usb_regs[0x0d] = 0x16; + via_mvp3_sb->usb_regs[0x20] = 0x01; + via_mvp3_sb->usb_regs[0x21] = 0x03; + via_mvp3_sb->usb_regs[0x3d] = 0x04; + + via_mvp3_sb->usb_regs[0x60] = 0x10; + via_mvp3_sb->usb_regs[0xc1] = 0x20; + + via_mvp3_sb->power_regs[0x00] = 0x06; via_mvp3_sb->power_regs[0x01] = 0x11; /*VIA*/ + via_mvp3_sb->power_regs[0x02] = 0x40; via_mvp3_sb->power_regs[0x03] = 0x30; + via_mvp3_sb->power_regs[0x04] = 0x00; via_mvp3_sb->power_regs[0x05] = 0x00; + via_mvp3_sb->power_regs[0x06] = 0x80; via_mvp3_sb->power_regs[0x07] = 0x02; + via_mvp3_sb->power_regs[0x08] = 0x10; /*Production version (3041)*/ + via_mvp3_sb->power_regs[0x48] = 0x01; + + pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); + + pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED); + pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED); + pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED); + + ide_pri_disable(); + ide_sec_disable(); +} + +static void +via_mvp3_sb_bus_master_handlers(via_mvp3_sb_t *dev, uint16_t old_base) +{ + uint16_t base; + + base = (dev->ide_regs[0x20] & 0xf0) | (dev->ide_regs[0x21] << 8); + + sff_bus_master_handlers(dev->bm[0], old_base, base, (dev->ide_regs[0x04] & 1)); + sff_bus_master_handlers(dev->bm[1], old_base + 8, base + 8, (dev->ide_regs[0x04] & 1)); +} + +static uint8_t +via_mvp3_sb_read(int func, int addr, void *priv) +{ + via_mvp3_sb_t *dev = (via_mvp3_sb_t *) priv; + + switch(func) + { + case 0: + { + return dev->pci_isa_regs[addr]; + } + case 1: + { + return dev->ide_regs[addr]; + } + case 2: + { + return dev->usb_regs[addr]; + } + case 3: + { + return dev->power_regs[addr]; + } + default: + { + return 0xff; + } + } +} + +static void +via_mvp3_sb_write(int func, int addr, uint8_t val, void *priv) +{ + via_mvp3_sb_t *dev = (via_mvp3_sb_t *) priv; + uint16_t old_base; + + if(func > 3) return; + + old_base = (dev->ide_regs[0x20] & 0xf0) | (dev->ide_regs[0x21] << 8); + + switch(func) + { + case 0: //PCI-ISA bridge + { + /*Read-only addresses*/ + if ((addr < 4) || (addr == 5) || (addr == 6) + || (addr >= 8 && addr < 0x40) + || (addr == 0x49) + || (addr == 0x4b) + || (addr >= 0x51 && addr < 0x54) + || (addr >= 0x5d && addr < 0x60) + || (addr >= 0x68 && addr < 0x6a) + || (addr >= 0x71)) + return; + + switch(addr) + { + case 0x04: + dev->pci_isa_regs[0x04] = (val & 8) | 7; + break; + case 0x06: + dev->pci_isa_regs[0x06] &= ~(val & 0xb0); + break; + + case 0x47: + if((val & 0x81) == 0x81) resetx86(); + if(val & 0x20) pci_elcr_set_enabled(1); + else pci_elcr_set_enabled(0); + dev->pci_isa_regs[0x47] = val & 0xfe; + break; + + case 0x54: + if(val & 8) pci_set_irq_level(PCI_INTA, 0); + else pci_set_irq_level(PCI_INTA, 1); + if(val & 4) pci_set_irq_level(PCI_INTB, 0); + else pci_set_irq_level(PCI_INTB, 1); + if(val & 2) pci_set_irq_level(PCI_INTC, 0); + else pci_set_irq_level(PCI_INTC, 1); + if(val & 1) pci_set_irq_level(PCI_INTD, 0); + else pci_set_irq_level(PCI_INTD, 1); + break; + + case 0x55: + if(!(val & 0xf0)) pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); + else pci_set_irq_routing(PCI_INTD, val >> 4); + + if(!(val & 0x0f)) pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED); + else pci_set_mirq_routing(PCI_MIRQ0, val & 0xf); + dev->pci_isa_regs[0x55] = val; + break; + + case 0x56: + if(!(val & 0xf0)) pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); + else pci_set_irq_routing(PCI_INTA, val >> 4); + + if(!(val & 0x0f)) pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); + else pci_set_irq_routing(PCI_INTB, val & 0xf); + dev->pci_isa_regs[0x56] = val; + break; + + case 0x57: + if(!(val & 0xf0)) pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); + else pci_set_irq_routing(PCI_INTC, val >> 4); + + if(!(val & 0x0f)) pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED); + else pci_set_mirq_routing(PCI_MIRQ1, val & 0xf); + dev->pci_isa_regs[0x57] = val; + break; + + case 0x58: + if(!(val & 0x0f)) pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED); + else pci_set_mirq_routing(PCI_MIRQ2, val & 0xf); + dev->pci_isa_regs[0x58] = val; + } + break; + } + case 1: /*IDE regs*/ + { + /*Read-only addresses*/ + if ((addr < 4) || (addr == 5) || (addr == 8) + || (addr >= 0xa && addr < 0x0d) + || (addr >= 0x0e && addr < 0x20) + || (addr >= 0x22 && addr < 0x3c) + || (addr >= 0x3d && addr < 0x40) + || (addr >= 0x54 && addr < 0x60) + || (addr >= 0x52 && addr < 0x68) + || (addr >= 0x62)) + return; + + switch(addr) + { + case 0x04: + { + uint16_t base = (dev->ide_regs[0x20] & 0xf0) | (dev->ide_regs[0x21] << 8); + ide_pri_disable(); + ide_sec_disable(); + if(val & PCI_COMMAND_IO) + { + if(dev->ide_regs[0x40] & 0x02) ide_pri_enable(); + if(dev->ide_regs[0x40] & 0x01) ide_sec_enable(); + } + via_mvp3_sb_bus_master_handlers(dev, base); + dev->ide_regs[0x04] = val & 0x85; + break; + } + case 0x06: + dev->ide_regs[0x06] &= ~(val & 0xb0); + break; + + case 0x09: + dev->ide_regs[0x09] = (dev->pci_isa_regs[0x09] & ~0x70) | 0x8a; + break; + + case 0x20: + { + dev->ide_regs[0x20] = (val & 0xf0) | 1; + via_mvp3_sb_bus_master_handlers(dev, old_base); + break; + } + + case 0x21: + { + dev->ide_regs[0x21] = val; + via_mvp3_sb_bus_master_handlers(dev, old_base); + break; + } + + case 0x40: + { + dev->ide_regs[0x40] = val; + ide_pri_disable(); + ide_sec_disable(); + if(val & PCI_COMMAND_IO) + { + if(dev->ide_regs[0x40] & 0x02) ide_pri_enable(); + if(dev->ide_regs[0x40] & 0x01) ide_sec_enable(); + } + break; + } + + default: + dev->ide_regs[addr] = val; + break; + } + break; + } + case 2: + { + /*Read-only addresses*/ + if ((addr < 4) || (addr == 5) || (addr == 6) + || (addr >= 8 && addr < 0xd) + || (addr >= 0xe && addr < 0x20) + || (addr >= 0x22 && addr < 0x3c) + || (addr >= 0x3e && addr < 0x40) + || (addr >= 0x42 && addr < 0x44) + || (addr >= 0x46 && addr < 0xc0) + || (addr >= 0xc2)) + return; + + switch(addr) + { + case 0x04: + dev->usb_regs[0x04] = val & 0x97; + break; + case 0x07: + dev->usb_regs[0x07] = val & 0x7f; + break; + + case 0x20: + dev->usb_regs[0x20] = (val & ~0x1f) | 1; + break; + + default: + dev->usb_regs[addr] = val; + break; + } + break; + } + case 3: + { + /*Read-only addresses*/ + if ((addr < 0xd) || (addr >= 0xe && addr < 0x40) + || (addr == 0x43) + || (addr == 0x48) + || (addr >= 0x4a && addr < 0x50) + || (addr >= 0x54)) + return; + + dev->power_regs[addr] = val; + break; + } + } +} + +static void +*via_mvp3_sb_init(const device_t *info) +{ + via_mvp3_sb_t *via_mvp3_sb = (via_mvp3_sb_t *) malloc(sizeof(via_mvp3_sb_t)); + memset(via_mvp3_sb, 0, sizeof(via_mvp3_sb_t)); + + pci_add_card(7, via_mvp3_sb_read, via_mvp3_sb_write, via_mvp3_sb); + + via_mvp3_sb->bm[0] = device_add_inst(&sff8038i_device, 1); + via_mvp3_sb->bm[1] = device_add_inst(&sff8038i_device, 2); + + via_mvp3_sb_reset_hard(via_mvp3_sb); + + device_add(&port_92_pci_device); + + dma_alias_set(); + + pci_enable_mirq(0); + pci_enable_mirq(1); + pci_enable_mirq(2); + + return via_mvp3_sb; +} + +static void +via_mvp3_sb_close(void *p) +{ + via_mvp3_sb_t *via_mvp3_sb = (via_mvp3_sb_t *)p; + + free(via_mvp3_sb); +} + +const device_t via_mvp3_sb_device = +{ + "VIA VT82C586B", + DEVICE_PCI, + 0, + via_mvp3_sb_init, + via_mvp3_sb_close, + NULL, + NULL, + NULL, + NULL, + NULL +}; \ No newline at end of file diff --git a/src/via_mvp3_sb.h b/src/via_mvp3_sb.h new file mode 100644 index 000000000..2e9ab7967 --- /dev/null +++ b/src/via_mvp3_sb.h @@ -0,0 +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. + * + * Emulation of the VIA Apollo MVP3 southbridge + * + * Version: @(#)via_mvp3_sb.c 1.0.22 2018/10/31 + * + * Authors: Sarah Walker, + * Miran Grca, + * Melissa Goad, + * + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2020 Melissa Goad. + */ + +#if defined(DEV_BRANCH) && defined(USE_SS7) +extern const device_t via_mvp3_sb_device; +#endif \ No newline at end of file diff --git a/src/win/Makefile_ndr.mingw b/src/win/Makefile_ndr.mingw index facc55327..3ee85ba09 100644 --- a/src/win/Makefile_ndr.mingw +++ b/src/win/Makefile_ndr.mingw @@ -74,6 +74,9 @@ ifeq ($(DEV_BUILD), y) ifndef PS2M70T4 PS2M70T4 := y endif + ifndef SS7 + SS7 := y + endif ifndef TI TI := y endif @@ -138,6 +141,9 @@ else ifndef PS2M70T4 PS2M70T4 := n endif + ifndef SS7 + SS7 := n + endif ifndef TI TI := n endif @@ -500,6 +506,11 @@ ifeq ($(PS2M70T4), y) OPTS += -DUSE_PS2M70T4 endif +ifeq ($(SS7),y) +OPTS += -DUSE_SS7 +DEVBROBJ += via_mvp3.o via_mvp3_sb.o sst_flash.o +endif + ifeq ($(TI), y) OPTS += -DUSE_TI endif From 199db4acbe54cf6610d354f12b14133350e66b02 Mon Sep 17 00:00:00 2001 From: Melissa Goad Date: Sun, 12 Jan 2020 20:36:38 -0600 Subject: [PATCH 054/177] Fixes from OBattler --- src/chipset/via_mvp3.c | 231 +++++++++++++++++++++++------------------ 1 file changed, 130 insertions(+), 101 deletions(-) diff --git a/src/chipset/via_mvp3.c b/src/chipset/via_mvp3.c index dfeba12c2..d9ffc01a6 100644 --- a/src/chipset/via_mvp3.c +++ b/src/chipset/via_mvp3.c @@ -30,60 +30,35 @@ #include "../keyboard.h" #include "chipset.h" + typedef struct via_mvp3_t { uint8_t pci_conf[2][256]; } via_mvp3_t; + static void -via_mvp3_recalcmapping(via_mvp3_t *dev) +mvp3_map(uint32_t addr, uint32_t size, int state) { - int c, d; - uint32_t base; - - for (c = 0; c < 2; c++) { - for (d = 0; d < 4; d++) { - base = 0xc0000 + (d << 14); - switch (dev->pci_conf[0][0x61 + c] & (3 << (d << 1))) { - case 0x00: - mem_set_mem_state(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - break; - case 0x01: - mem_set_mem_state(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); - break; - case 0x02: - mem_set_mem_state(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_EXTANY); - break; - case 0x03: - mem_set_mem_state(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - break; - } - } - } - - for(d = 0; d < 2; d++) - { - base = 0xe0000 + (d << 16); - switch (dev->pci_conf[0][0x63] & (3 << (d << 1))) { - case 0x00: - mem_set_mem_state(base, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - break; - case 0x01: - mem_set_mem_state(base, 0x10000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); - break; - case 0x02: - mem_set_mem_state(base, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_EXTANY); - break; - case 0x03: - mem_set_mem_state(base, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - break; - } + switch (state & 3) { + case 0: + mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + break; + case 1: + mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + break; + case 2: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY); + break; + case 3: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; } flushmmucache_nopc(); - shadowbios = 1; } + static void via_mvp3_setup(via_mvp3_t *dev) { @@ -158,108 +133,160 @@ via_mvp3_setup(via_mvp3_t *dev) dev->pci_conf[1][0x25] = 0xff; } + static void via_mvp3_host_bridge_write(int func, int addr, uint8_t val, void *priv) { via_mvp3_t *dev = (via_mvp3_t *) priv; if (func) - return; + return; /*Read-only addresses*/ - if ((addr < 4) || (addr >= 5 && addr < 7) - || (addr >= 8 && addr < 0xd) - || (addr >= 0xe && addr < 0x12) - || (addr >= 0x14 && addr < 0x50) - || (addr >= 0x79 && addr < 0x7e) - || (addr >= 0x85 && addr < 0x88) - || (addr >= 0x8c && addr < 0xa8) - || (addr >= 0xad && addr < 0xfd)) - return; + if ((addr < 4) || ((addr >= 5) && (addr < 7)) || ((addr >= 8) && (addr < 0xd)) || + ((addr >= 0xe) && (addr < 0x12)) || ((addr >= 0x14) && (addr < 0x50)) || + ((addr >= 0x79) && (addr < 0x7e)) || ((addr >= 0x85) && (addr < 0x88)) || + ((addr >= 0x8c) && (addr < 0xa8)) || ((addr >= 0xad) && (addr < 0xfd))) + return; - switch(addr) - { - case 0x04: - dev->pci_conf[0][0x04] = (dev->pci_conf[0][0x04] & ~0x40) | (val & 0x40); - break; - case 0x07: - dev->pci_conf[0][0x07] &= ~(val & 0xb0); - case 0x61: case 0x62: case 0x63: - dev->pci_conf[0][addr] = val; - via_mvp3_recalcmapping(dev); - break; - default: - dev->pci_conf[0][addr] = val; - break; + switch(addr) { + case 0x04: + dev->pci_conf[0][0x04] = (dev->pci_conf[0][0x04] & ~0x40) | (val & 0x40); + break; + case 0x07: + dev->pci_conf[0][0x07] &= ~(val & 0xb0); + break; + + case 0x12: /* Graphics Aperture Base */ + dev->pci_conf[0][0x12] = (val & 0xf0); + break; + case 0x13: /* Graphics Aperture Base */ + dev->pci_conf[0][0x13] = val; + break; + + case 0x61: /* Shadow RAM Control 1 */ + if ((dev->pci_conf[0][0x61] ^ val) & 0x03) + mvp3_map(0xc0000, 0x04000, val & 0x03); + if ((dev->pci_conf[0][0x61] ^ val) & 0x0c) + mvp3_map(0xc4000, 0x04000, (val & 0x0c) >> 2); + if ((dev->pci_conf[0][0x61] ^ val) & 0x30) + mvp3_map(0xc8000, 0x04000, (val & 0x30) >> 4); + if ((dev->pci_conf[0][0x61] ^ val) & 0xc0) + mvp3_map(0xcc000, 0x04000, (val & 0xc0) >> 6); + dev->pci_conf[0][0x61] = val; + return; + case 0x62: /* Shadow RAM Control 2 */ + if ((dev->pci_conf[0][0x62] ^ val) & 0x03) + mvp3_map(0xd0000, 0x04000, val & 0x03); + if ((dev->pci_conf[0][0x62] ^ val) & 0x0c) + mvp3_map(0xd4000, 0x04000, (val & 0x0c) >> 2); + if ((dev->pci_conf[0][0x62] ^ val) & 0x30) + mvp3_map(0xd8000, 0x04000, (val & 0x30) >> 4); + if ((dev->pci_conf[0][0x62] ^ val) & 0xc0) + mvp3_map(0xdc000, 0x04000, (val & 0xc0) >> 6); + dev->pci_conf[0][0x62] = val; + return; + case 0x63: /* Shadow RAM Control 3 */ + if ((dev->pci_conf[0][0x63] ^ val) & 0x30) { + mvp3_map(0xf0000, 0x10000, (val & 0x30) >> 4); + shadowbios = (((val & 0x30) >> 4) & 0x02); + } + if ((dev->pci_conf[0][0x63] ^ val) & 0xc0) + mvp3_map(0xe0000, 0x10000, (val & 0xc0) >> 6); + dev->pci_conf[0][0x63] = val; + return; + + default: + dev->pci_conf[0][addr] = val; + break; } } + static void via_mvp3_pci_bridge_write(int func, int addr, uint8_t val, void *priv) { via_mvp3_t *dev = (via_mvp3_t *) priv; - if(func != 1) return; + if (func != 1) + return; /*Read-only addresses*/ - if ((addr < 4) || (addr >= 5 && addr < 7) - || (addr >= 8 && addr < 0x18) - || (addr == 0x1b) - || (addr >= 0x1e && addr < 0x20) - || (addr >= 0x28 && addr < 0x3e) - || (addr >= 0x43)) - return; - - switch(addr) - { - case 0x04: - dev->pci_conf[1][0x04] = (dev->pci_conf[1][0x04] & ~0x47) | (val & 0x47); - break; - case 0x07: - dev->pci_conf[1][0x07] &= ~(val & 0x30); - default: - dev->pci_conf[1][addr] = val; - break; + if ((addr < 4) || ((addr >= 5) && (addr < 7)) || + ((addr >= 8) && (addr < 0x18)) || (addr == 0x1b) || + ((addr >= 0x1e) && (addr < 0x20)) || ((addr >= 0x28) && (addr < 0x3e)) || + (addr >= 0x43)) + return; + + switch(addr) { + case 0x04: + dev->pci_conf[1][0x04] = (dev->pci_conf[1][0x04] & ~0x47) | (val & 0x47); + break; + case 0x07: + dev->pci_conf[1][0x07] &= ~(val & 0x30); + break; + + case 0x20: /* Memory Base */ + dev->pci_conf[1][0x20] = val & 0xf0; + break; + case 0x22: /* Memory Limit */ + dev->pci_conf[1][0x22] = val & 0xf0; + break; + case 0x24: /* Prefetchable Memory Base */ + dev->pci_conf[1][0x24] = val & 0xf0; + break; + case 0x26: /* Prefetchable Memory Limit */ + dev->pci_conf[1][0x26] = val & 0xf0; + break; + + default: + dev->pci_conf[1][addr] = val; + break; } } + static uint8_t via_mvp3_read(int func, int addr, void *priv) { via_mvp3_t *dev = (via_mvp3_t *) priv; + uint8_t ret = 0xff; - switch(func) - { - case 0: return dev->pci_conf[0][addr]; - case 1: return dev->pci_conf[1][addr]; - default: return 0xff; + switch(func) { + case 0: + ret = dev->pci_conf[0][addr]; + break; + case 1: + ret = dev->pci_conf[1][addr]; + break; } + + return ret; } static void via_mvp3_write(int func, int addr, uint8_t val, void *priv) { - switch(func) - { - case 0: - via_mvp3_host_bridge_write(func, addr, val, priv); - break; - case 1: - via_mvp3_pci_bridge_write(func, addr, val, priv); - break; + switch(func) { + case 0: + via_mvp3_host_bridge_write(func, addr, val, priv); + break; + case 1: + via_mvp3_pci_bridge_write(func, addr, val, priv); + break; } } + static void via_mvp3_reset(void *priv) { - via_mvp3_t *dev = (via_mvp3_t *) priv; - - via_mvp3_setup(dev); + via_mvp3_write(0, 0x63, via_mvp3_read(0, 0x63, priv) & 0xcf, priv); } + static void * via_mvp3_init(const device_t *info) { @@ -272,6 +299,7 @@ via_mvp3_init(const device_t *info) return dev; } + static void via_mvp3_close(void *priv) { @@ -280,6 +308,7 @@ via_mvp3_close(void *priv) free(dev); } + const device_t via_mvp3_device = { "VIA MVP3", From 426bf8c46e93794e03966ace25476f9a4a5663c2 Mon Sep 17 00:00:00 2001 From: Melissa Goad Date: Mon, 13 Jan 2020 11:56:24 -0600 Subject: [PATCH 055/177] Fix the name of the VT82C586B southbridge --- src/machine/m_at_socket7_s7.c | 4 +- src/{via_mvp3_sb.c => vt82c586b.c} | 186 ++++++++++++++--------------- src/{via_mvp3_sb.h => vt82c586b.h} | 2 +- src/win/Makefile_ndr.mingw | 2 +- 4 files changed, 97 insertions(+), 97 deletions(-) rename src/{via_mvp3_sb.c => vt82c586b.c} (63%) rename src/{via_mvp3_sb.h => vt82c586b.h} (91%) diff --git a/src/machine/m_at_socket7_s7.c b/src/machine/m_at_socket7_s7.c index 9dfd1515a..36960af3e 100644 --- a/src/machine/m_at_socket7_s7.c +++ b/src/machine/m_at_socket7_s7.c @@ -38,7 +38,7 @@ #include "../piix.h" #include "../sio.h" #include "../sst_flash.h" -#include "../via_mvp3_sb.h" +#include "../vt82c586b.h" #include "../video/video.h" #include "../video/vid_cl54xx.h" #include "../video/vid_s3.h" @@ -477,7 +477,7 @@ machine_at_mvp3_init(const machine_t *model) pci_register_slot(0x0a, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); device_add(&via_mvp3_device); - device_add(&via_mvp3_sb_device); + device_add(&vt82c586b_device); device_add(&keyboard_ps2_pci_device); device_add(&w83877tf_device); device_add(&sst_flash_39sf010_device); diff --git a/src/via_mvp3_sb.c b/src/vt82c586b.c similarity index 63% rename from src/via_mvp3_sb.c rename to src/vt82c586b.c index 1fa42889c..f53e1ed61 100644 --- a/src/via_mvp3_sb.c +++ b/src/vt82c586b.c @@ -4,9 +4,9 @@ * PC systems and compatibles from 1981 through fairly recent * system designs based on the PCI bus. * - * Emulation of the VIA Apollo MVP3 southbridge + * Emulation of the VIA VT82C586B southbridge * - * Version: @(#)via_mvp3_sb.c 1.0.22 2018/10/31 + * Version: @(#)vt82c586b.c 1.0.22 2018/10/31 * * Authors: Sarah Walker, * Miran Grca, @@ -43,7 +43,7 @@ #include "disk/hdc_ide_sff8038i.h" #include "disk/zip.h" #include "machine/machine.h" -#include "via_mvp3_sb.h" +#include "vt82c586b.h" typedef struct { @@ -52,92 +52,92 @@ typedef struct uint8_t usb_regs[256]; uint8_t power_regs[256]; sff8038i_t *bm[2]; -} via_mvp3_sb_t; +} vt82c586b_t; static void -via_mvp3_sb_reset_hard(void *priv) +vt82c586b_reset_hard(void *priv) { - via_mvp3_sb_t *via_mvp3_sb = (via_mvp3_sb_t *) priv; + vt82c586b_t *vt82c586b = (vt82c586b_t *) priv; - uint16_t old_base = (via_mvp3_sb->ide_regs[0x20] & 0xf0) | (via_mvp3_sb->ide_regs[0x21] << 8); + uint16_t old_base = (vt82c586b->ide_regs[0x20] & 0xf0) | (vt82c586b->ide_regs[0x21] << 8); - sff_bus_master_reset(via_mvp3_sb->bm[0], old_base); - sff_bus_master_reset(via_mvp3_sb->bm[1], old_base + 8); + sff_bus_master_reset(vt82c586b->bm[0], old_base); + sff_bus_master_reset(vt82c586b->bm[1], old_base + 8); - memset(via_mvp3_sb->pci_isa_regs, 0, 256); - memset(via_mvp3_sb->ide_regs, 0, 256); - memset(via_mvp3_sb->usb_regs, 0, 256); - memset(via_mvp3_sb->power_regs, 0, 256); + memset(vt82c586b->pci_isa_regs, 0, 256); + memset(vt82c586b->ide_regs, 0, 256); + memset(vt82c586b->usb_regs, 0, 256); + memset(vt82c586b->power_regs, 0, 256); - via_mvp3_sb->pci_isa_regs[0x00] = 0x06; via_mvp3_sb->pci_isa_regs[0x01] = 0x11; /*VIA*/ - via_mvp3_sb->pci_isa_regs[0x02] = 0x86; via_mvp3_sb->pci_isa_regs[0x03] = 0x05; /*VT82C586B*/ - via_mvp3_sb->pci_isa_regs[0x04] = 0x0f; - via_mvp3_sb->pci_isa_regs[0x07] = 0x02; - via_mvp3_sb->pci_isa_regs[0x0a] = 0x01; - via_mvp3_sb->pci_isa_regs[0x0b] = 0x06; - via_mvp3_sb->pci_isa_regs[0x0e] = 0x80; + vt82c586b->pci_isa_regs[0x00] = 0x06; vt82c586b->pci_isa_regs[0x01] = 0x11; /*VIA*/ + vt82c586b->pci_isa_regs[0x02] = 0x86; vt82c586b->pci_isa_regs[0x03] = 0x05; /*VT82C586B*/ + vt82c586b->pci_isa_regs[0x04] = 0x0f; + vt82c586b->pci_isa_regs[0x07] = 0x02; + vt82c586b->pci_isa_regs[0x0a] = 0x01; + vt82c586b->pci_isa_regs[0x0b] = 0x06; + vt82c586b->pci_isa_regs[0x0e] = 0x80; - via_mvp3_sb->pci_isa_regs[0x48] = 0x01; - via_mvp3_sb->pci_isa_regs[0x4a] = 0x04; - via_mvp3_sb->pci_isa_regs[0x4f] = 0x03; + vt82c586b->pci_isa_regs[0x48] = 0x01; + vt82c586b->pci_isa_regs[0x4a] = 0x04; + vt82c586b->pci_isa_regs[0x4f] = 0x03; - via_mvp3_sb->pci_isa_regs[0x50] = 0x24; - via_mvp3_sb->pci_isa_regs[0x59] = 0x04; + vt82c586b->pci_isa_regs[0x50] = 0x24; + vt82c586b->pci_isa_regs[0x59] = 0x04; //IDE registers - via_mvp3_sb->ide_regs[0x00] = 0x06; via_mvp3_sb->ide_regs[0x01] = 0x11; /*VIA*/ - via_mvp3_sb->ide_regs[0x02] = 0x71; via_mvp3_sb->ide_regs[0x03] = 0x05; /*VT82C586B*/ - via_mvp3_sb->ide_regs[0x04] = 0x80; - via_mvp3_sb->ide_regs[0x06] = 0x80; via_mvp3_sb->ide_regs[0x07] = 0x02; - via_mvp3_sb->ide_regs[0x09] = 0x85; - via_mvp3_sb->ide_regs[0x0a] = 0x01; - via_mvp3_sb->ide_regs[0x0b] = 0x01; + vt82c586b->ide_regs[0x00] = 0x06; vt82c586b->ide_regs[0x01] = 0x11; /*VIA*/ + vt82c586b->ide_regs[0x02] = 0x71; vt82c586b->ide_regs[0x03] = 0x05; /*VT82C586B*/ + vt82c586b->ide_regs[0x04] = 0x80; + vt82c586b->ide_regs[0x06] = 0x80; vt82c586b->ide_regs[0x07] = 0x02; + vt82c586b->ide_regs[0x09] = 0x85; + vt82c586b->ide_regs[0x0a] = 0x01; + vt82c586b->ide_regs[0x0b] = 0x01; - via_mvp3_sb->ide_regs[0x10] = 0xf0; via_mvp3_sb->ide_regs[0x11] = 0x01; - via_mvp3_sb->ide_regs[0x14] = 0xf4; via_mvp3_sb->ide_regs[0x15] = 0x03; - via_mvp3_sb->ide_regs[0x18] = 0x70; via_mvp3_sb->ide_regs[0x19] = 0x01; - via_mvp3_sb->ide_regs[0x1c] = 0x74; via_mvp3_sb->ide_regs[0x1d] = 0x03; - via_mvp3_sb->ide_regs[0x20] = 0x01; via_mvp3_sb->ide_regs[0x21] = 0xcc; + vt82c586b->ide_regs[0x10] = 0xf0; vt82c586b->ide_regs[0x11] = 0x01; + vt82c586b->ide_regs[0x14] = 0xf4; vt82c586b->ide_regs[0x15] = 0x03; + vt82c586b->ide_regs[0x18] = 0x70; vt82c586b->ide_regs[0x19] = 0x01; + vt82c586b->ide_regs[0x1c] = 0x74; vt82c586b->ide_regs[0x1d] = 0x03; + vt82c586b->ide_regs[0x20] = 0x01; vt82c586b->ide_regs[0x21] = 0xcc; - via_mvp3_sb->ide_regs[0x3c] = 0x0e; + vt82c586b->ide_regs[0x3c] = 0x0e; - via_mvp3_sb->ide_regs[0x40] = 0x08; - via_mvp3_sb->ide_regs[0x41] = 0x02; - via_mvp3_sb->ide_regs[0x42] = 0x09; - via_mvp3_sb->ide_regs[0x43] = 0x3a; - via_mvp3_sb->ide_regs[0x44] = 0x68; - via_mvp3_sb->ide_regs[0x46] = 0xc0; - via_mvp3_sb->ide_regs[0x48] = 0xa8; via_mvp3_sb->ide_regs[0x49] = 0xa8; - via_mvp3_sb->ide_regs[0x4a] = 0xa8; via_mvp3_sb->ide_regs[0x4b] = 0xa8; - via_mvp3_sb->ide_regs[0x4c] = 0xff; - via_mvp3_sb->ide_regs[0x4e] = 0xff; - via_mvp3_sb->ide_regs[0x4f] = 0xff; - via_mvp3_sb->ide_regs[0x50] = 0x03; via_mvp3_sb->ide_regs[0x51] = 0x03; - via_mvp3_sb->ide_regs[0x52] = 0x03; via_mvp3_sb->ide_regs[0x53] = 0x03; + vt82c586b->ide_regs[0x40] = 0x08; + vt82c586b->ide_regs[0x41] = 0x02; + vt82c586b->ide_regs[0x42] = 0x09; + vt82c586b->ide_regs[0x43] = 0x3a; + vt82c586b->ide_regs[0x44] = 0x68; + vt82c586b->ide_regs[0x46] = 0xc0; + vt82c586b->ide_regs[0x48] = 0xa8; vt82c586b->ide_regs[0x49] = 0xa8; + vt82c586b->ide_regs[0x4a] = 0xa8; vt82c586b->ide_regs[0x4b] = 0xa8; + vt82c586b->ide_regs[0x4c] = 0xff; + vt82c586b->ide_regs[0x4e] = 0xff; + vt82c586b->ide_regs[0x4f] = 0xff; + vt82c586b->ide_regs[0x50] = 0x03; vt82c586b->ide_regs[0x51] = 0x03; + vt82c586b->ide_regs[0x52] = 0x03; vt82c586b->ide_regs[0x53] = 0x03; - via_mvp3_sb->ide_regs[0x61] = 0x02; - via_mvp3_sb->ide_regs[0x69] = 0x02; + vt82c586b->ide_regs[0x61] = 0x02; + vt82c586b->ide_regs[0x69] = 0x02; - via_mvp3_sb->usb_regs[0x00] = 0x06; via_mvp3_sb->usb_regs[0x01] = 0x11; /*VIA*/ - via_mvp3_sb->usb_regs[0x02] = 0x38; via_mvp3_sb->usb_regs[0x03] = 0x30; - via_mvp3_sb->usb_regs[0x04] = 0x00; via_mvp3_sb->usb_regs[0x05] = 0x00; - via_mvp3_sb->usb_regs[0x06] = 0x00; via_mvp3_sb->usb_regs[0x07] = 0x02; - via_mvp3_sb->usb_regs[0x0a] = 0x03; - via_mvp3_sb->usb_regs[0x0b] = 0x0c; - via_mvp3_sb->usb_regs[0x0d] = 0x16; - via_mvp3_sb->usb_regs[0x20] = 0x01; - via_mvp3_sb->usb_regs[0x21] = 0x03; - via_mvp3_sb->usb_regs[0x3d] = 0x04; + vt82c586b->usb_regs[0x00] = 0x06; vt82c586b->usb_regs[0x01] = 0x11; /*VIA*/ + vt82c586b->usb_regs[0x02] = 0x38; vt82c586b->usb_regs[0x03] = 0x30; + vt82c586b->usb_regs[0x04] = 0x00; vt82c586b->usb_regs[0x05] = 0x00; + vt82c586b->usb_regs[0x06] = 0x00; vt82c586b->usb_regs[0x07] = 0x02; + vt82c586b->usb_regs[0x0a] = 0x03; + vt82c586b->usb_regs[0x0b] = 0x0c; + vt82c586b->usb_regs[0x0d] = 0x16; + vt82c586b->usb_regs[0x20] = 0x01; + vt82c586b->usb_regs[0x21] = 0x03; + vt82c586b->usb_regs[0x3d] = 0x04; - via_mvp3_sb->usb_regs[0x60] = 0x10; - via_mvp3_sb->usb_regs[0xc1] = 0x20; + vt82c586b->usb_regs[0x60] = 0x10; + vt82c586b->usb_regs[0xc1] = 0x20; - via_mvp3_sb->power_regs[0x00] = 0x06; via_mvp3_sb->power_regs[0x01] = 0x11; /*VIA*/ - via_mvp3_sb->power_regs[0x02] = 0x40; via_mvp3_sb->power_regs[0x03] = 0x30; - via_mvp3_sb->power_regs[0x04] = 0x00; via_mvp3_sb->power_regs[0x05] = 0x00; - via_mvp3_sb->power_regs[0x06] = 0x80; via_mvp3_sb->power_regs[0x07] = 0x02; - via_mvp3_sb->power_regs[0x08] = 0x10; /*Production version (3041)*/ - via_mvp3_sb->power_regs[0x48] = 0x01; + vt82c586b->power_regs[0x00] = 0x06; vt82c586b->power_regs[0x01] = 0x11; /*VIA*/ + vt82c586b->power_regs[0x02] = 0x40; vt82c586b->power_regs[0x03] = 0x30; + vt82c586b->power_regs[0x04] = 0x00; vt82c586b->power_regs[0x05] = 0x00; + vt82c586b->power_regs[0x06] = 0x80; vt82c586b->power_regs[0x07] = 0x02; + vt82c586b->power_regs[0x08] = 0x10; /*Production version (3041)*/ + vt82c586b->power_regs[0x48] = 0x01; pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); @@ -153,7 +153,7 @@ via_mvp3_sb_reset_hard(void *priv) } static void -via_mvp3_sb_bus_master_handlers(via_mvp3_sb_t *dev, uint16_t old_base) +vt82c586b_bus_master_handlers(vt82c586b_t *dev, uint16_t old_base) { uint16_t base; @@ -164,9 +164,9 @@ via_mvp3_sb_bus_master_handlers(via_mvp3_sb_t *dev, uint16_t old_base) } static uint8_t -via_mvp3_sb_read(int func, int addr, void *priv) +vt82c586b_read(int func, int addr, void *priv) { - via_mvp3_sb_t *dev = (via_mvp3_sb_t *) priv; + vt82c586b_t *dev = (vt82c586b_t *) priv; switch(func) { @@ -194,9 +194,9 @@ via_mvp3_sb_read(int func, int addr, void *priv) } static void -via_mvp3_sb_write(int func, int addr, uint8_t val, void *priv) +vt82c586b_write(int func, int addr, uint8_t val, void *priv) { - via_mvp3_sb_t *dev = (via_mvp3_sb_t *) priv; + vt82c586b_t *dev = (vt82c586b_t *) priv; uint16_t old_base; if(func > 3) return; @@ -304,7 +304,7 @@ via_mvp3_sb_write(int func, int addr, uint8_t val, void *priv) if(dev->ide_regs[0x40] & 0x02) ide_pri_enable(); if(dev->ide_regs[0x40] & 0x01) ide_sec_enable(); } - via_mvp3_sb_bus_master_handlers(dev, base); + vt82c586b_bus_master_handlers(dev, base); dev->ide_regs[0x04] = val & 0x85; break; } @@ -319,14 +319,14 @@ via_mvp3_sb_write(int func, int addr, uint8_t val, void *priv) case 0x20: { dev->ide_regs[0x20] = (val & 0xf0) | 1; - via_mvp3_sb_bus_master_handlers(dev, old_base); + vt82c586b_bus_master_handlers(dev, old_base); break; } case 0x21: { dev->ide_regs[0x21] = val; - via_mvp3_sb_bus_master_handlers(dev, old_base); + vt82c586b_bus_master_handlers(dev, old_base); break; } @@ -398,17 +398,17 @@ via_mvp3_sb_write(int func, int addr, uint8_t val, void *priv) } static void -*via_mvp3_sb_init(const device_t *info) +*vt82c586b_init(const device_t *info) { - via_mvp3_sb_t *via_mvp3_sb = (via_mvp3_sb_t *) malloc(sizeof(via_mvp3_sb_t)); - memset(via_mvp3_sb, 0, sizeof(via_mvp3_sb_t)); + vt82c586b_t *vt82c586b = (vt82c586b_t *) malloc(sizeof(vt82c586b_t)); + memset(vt82c586b, 0, sizeof(vt82c586b_t)); - pci_add_card(7, via_mvp3_sb_read, via_mvp3_sb_write, via_mvp3_sb); + pci_add_card(7, vt82c586b_read, vt82c586b_write, vt82c586b); - via_mvp3_sb->bm[0] = device_add_inst(&sff8038i_device, 1); - via_mvp3_sb->bm[1] = device_add_inst(&sff8038i_device, 2); + vt82c586b->bm[0] = device_add_inst(&sff8038i_device, 1); + vt82c586b->bm[1] = device_add_inst(&sff8038i_device, 2); - via_mvp3_sb_reset_hard(via_mvp3_sb); + vt82c586b_reset_hard(vt82c586b); device_add(&port_92_pci_device); @@ -418,24 +418,24 @@ static void pci_enable_mirq(1); pci_enable_mirq(2); - return via_mvp3_sb; + return vt82c586b; } static void -via_mvp3_sb_close(void *p) +vt82c586b_close(void *p) { - via_mvp3_sb_t *via_mvp3_sb = (via_mvp3_sb_t *)p; + vt82c586b_t *vt82c586b = (vt82c586b_t *)p; - free(via_mvp3_sb); + free(vt82c586b); } -const device_t via_mvp3_sb_device = +const device_t vt82c586b_device = { "VIA VT82C586B", DEVICE_PCI, 0, - via_mvp3_sb_init, - via_mvp3_sb_close, + vt82c586b_init, + vt82c586b_close, NULL, NULL, NULL, diff --git a/src/via_mvp3_sb.h b/src/vt82c586b.h similarity index 91% rename from src/via_mvp3_sb.h rename to src/vt82c586b.h index 2e9ab7967..cfec19e9f 100644 --- a/src/via_mvp3_sb.h +++ b/src/vt82c586b.h @@ -18,5 +18,5 @@ */ #if defined(DEV_BRANCH) && defined(USE_SS7) -extern const device_t via_mvp3_sb_device; +extern const device_t vt82c586b_device; #endif \ No newline at end of file diff --git a/src/win/Makefile_ndr.mingw b/src/win/Makefile_ndr.mingw index 3ee85ba09..10d6aa481 100644 --- a/src/win/Makefile_ndr.mingw +++ b/src/win/Makefile_ndr.mingw @@ -508,7 +508,7 @@ endif ifeq ($(SS7),y) OPTS += -DUSE_SS7 -DEVBROBJ += via_mvp3.o via_mvp3_sb.o sst_flash.o +DEVBROBJ += via_mvp3.o vt82c586b.o sst_flash.o endif ifeq ($(TI), y) From da82e6a5eb416496f962014ad5380cf1a8234d3a Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 02:14:39 +0100 Subject: [PATCH 056/177] Finished the VIA machine. --- src/chipset/chipset.h | 6 +- src/disk/hdc_ide.c | 56 +-- src/disk/hdc_ide_sff8038i.c | 38 +- src/disk/hdc_ide_sff8038i.h | 15 +- src/dma.c | 15 +- src/dma.h | 9 +- src/machine/m_at.c | 14 +- src/machine/m_at_socket7_s7.c | 11 +- src/machine/machine.h | 12 +- src/machine/machine_table.c | 10 +- src/machine/machine_table_new.c | 19 +- src/nvr.h | 9 +- src/nvr_at.c | 84 +++- src/sst_flash.c | 2 +- src/sst_flash.h | 4 +- src/via_vt82c586b.c | 639 +++++++++++++++++++++++++++ src/{vt82c586b.h => via_vt82c586b.h} | 42 +- src/vt82c586b.c | 444 ------------------- src/win/Makefile.mingw | 6 +- src/win/Makefile_ndr.mingw | 17 +- 20 files changed, 863 insertions(+), 589 deletions(-) create mode 100644 src/via_vt82c586b.c rename src/{vt82c586b.h => via_vt82c586b.h} (65%) delete mode 100644 src/vt82c586b.c diff --git a/src/chipset/chipset.h b/src/chipset/chipset.h index 50f3536f7..f61cdcd3e 100644 --- a/src/chipset/chipset.h +++ b/src/chipset/chipset.h @@ -8,11 +8,11 @@ * * Handling of the emulated chipsets. * - * Version: @(#)machine.h 1.0.0 2019/05/13 + * Version: @(#)machine.h 1.0.1 2020/01/14 * * Authors: Miran Grca, * - * Copyright 2019 Miran Grca. + * Copyright 2019,2020 Miran Grca. */ #ifndef EMU_CHIPSET_H # define EMU_CHIPSET_H @@ -61,10 +61,8 @@ extern const device_t sis_85c496_device; extern const device_t sis_85c50x_device; #endif -#if defined(DEV_BRANCH) && defined(USE_SS7) /* VIA */ extern const device_t via_mvp3_device; -#endif /* WD */ extern const device_t wd76c10_device; diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index a9d1e8e59..6dba893c2 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -9,13 +9,13 @@ * Implementation of the IDE emulation for hard disks and ATAPI * CD-ROM devices. * - * Version: @(#)hdc_ide.c 1.0.65 2019/11/19 + * Version: @(#)hdc_ide.c 1.0.66 2020/01/14 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. */ #define __USE_LARGEFILE64 #define _LARGEFILE_SOURCE @@ -2315,7 +2315,7 @@ ide_set_handlers(uint8_t board) if (ide_boards[board] == NULL) return; - if (ide_boards[board]->base_main & 0x300) { + if (ide_boards[board]->base_main) { if (ide_boards[board]->bit32) { io_sethandler(ide_boards[board]->base_main, 1, ide_readb, ide_readw, ide_readl, @@ -2332,7 +2332,7 @@ ide_set_handlers(uint8_t board) ide_writeb, NULL, NULL, ide_boards[board]); } - if (ide_boards[board]->side_main & 0x300) { + if (ide_boards[board]->side_main) { io_sethandler(ide_boards[board]->side_main, 1, ide_read_alt_status, NULL, NULL, ide_write_devctl, NULL, NULL, @@ -2347,25 +2347,29 @@ ide_remove_handlers(uint8_t board) if (ide_boards[board] == NULL) return; - if (ide_boards[board]->bit32) { - io_removehandler(ide_boards[board]->base_main, 1, - ide_readb, ide_readw, ide_readl, - ide_writeb, ide_writew, ide_writel, - ide_boards[board]); - } else { - io_removehandler(ide_boards[board]->base_main, 1, - ide_readb, ide_readw, NULL, - ide_writeb, ide_writew, NULL, + if (ide_boards[board]->base_main) { + if (ide_boards[board]->bit32) { + io_removehandler(ide_boards[board]->base_main, 1, + ide_readb, ide_readw, ide_readl, + ide_writeb, ide_writew, ide_writel, + ide_boards[board]); + } else { + io_removehandler(ide_boards[board]->base_main, 1, + ide_readb, ide_readw, NULL, + ide_writeb, ide_writew, NULL, + ide_boards[board]); + } + io_removehandler(ide_boards[board]->base_main + 1, 7, + ide_readb, NULL, NULL, + ide_writeb, NULL, NULL, + ide_boards[board]); + } + if (ide_boards[board]->side_main) { + io_removehandler(ide_boards[board]->side_main, 1, + ide_read_alt_status, NULL, NULL, + ide_write_devctl, NULL, NULL, ide_boards[board]); } - io_removehandler(ide_boards[board]->base_main + 1, 7, - ide_readb, NULL, NULL, - ide_writeb, NULL, NULL, - ide_boards[board]); - io_removehandler(ide_boards[board]->side_main, 1, - ide_read_alt_status, NULL, NULL, - ide_write_devctl, NULL, NULL, - ide_boards[board]); } @@ -2556,10 +2560,8 @@ ide_board_init(int board, int irq, int base_main, int side_main, int type) ide_boards[board]->cur_dev = board << 1; if (type & 6) ide_boards[board]->bit32 = 1; - if (base_main != -1) - ide_boards[board]->base_main = base_main; - if (side_main != -1) - ide_boards[board]->side_main = side_main; + ide_boards[board]->base_main = base_main; + ide_boards[board]->side_main = side_main; ide_set_handlers(board); timer_add(&ide_boards[board]->timer, ide_callback, ide_boards[board], 0); @@ -2607,7 +2609,7 @@ ide_qua_close(void *priv) void * ide_xtide_init(void) { - ide_board_init(0, -1, -1, -1, 0); + ide_board_init(0, -1, 0, 0, 0); return ide_boards[0]; } diff --git a/src/disk/hdc_ide_sff8038i.c b/src/disk/hdc_ide_sff8038i.c index bf712bcc8..96d6bb0fc 100644 --- a/src/disk/hdc_ide_sff8038i.c +++ b/src/disk/hdc_ide_sff8038i.c @@ -10,13 +10,13 @@ * word 0 - base address * word 1 - bits 1-15 = byte count, bit 31 = end of transfer * - * Version: @(#)hdc_ide_sff8038i.c 1.0.1 2019/10/30 + * Version: @(#)hdc_ide_sff8038i.c 1.0.1 2020/01/14 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -370,13 +370,17 @@ sff_bus_master_set_irq(int channel, void *priv) channel &= 0x01; if (dev->status & 0x04) { - if (channel && pci_use_mirq(0)) + if ((dev->irq_mode == 2) && (channel & 1) && pci_use_mirq(0)) pci_set_mirq(0, 0); + else if (dev->irq_mode == 1) + pci_set_irq(dev->slot, dev->irq_pin); else picint(1 << (14 + channel)); } else { - if ((channel & 1) && pci_use_mirq(0)) + if ((dev->irq_mode == 2) && (channel & 1) && pci_use_mirq(0)) pci_clear_mirq(0, 0); + else if (dev->irq_mode == 1) + pci_clear_irq(dev->slot, dev->irq_pin); else picintc(1 << (14 + channel)); } @@ -401,6 +405,9 @@ sff_bus_master_reset(sff8038i_t *dev, uint16_t old_base) dev->addr = 0x00000000; dev->ptr0 = 0x00; dev->count = dev->eot = 0x00000000; + dev->slot = 7; + dev->irq_mode = 2; + dev->irq_pin = PCI_INTA; ide_pri_disable(); ide_sec_disable(); @@ -425,6 +432,27 @@ sff_reset(void *p) } +void +sff_set_slot(sff8038i_t *dev, int slot) +{ + dev->slot = slot; +} + + +void +sff_set_irq_mode(sff8038i_t *dev, int irq_mode) +{ + dev->irq_mode = irq_mode; +} + + +void +sff_set_irq_pin(sff8038i_t *dev, int irq_pin) +{ + dev->irq_pin = irq_pin; +} + + static void sff_close(void *p) { diff --git a/src/disk/hdc_ide_sff8038i.h b/src/disk/hdc_ide_sff8038i.h index 0be341eff..16b6ce524 100644 --- a/src/disk/hdc_ide_sff8038i.h +++ b/src/disk/hdc_ide_sff8038i.h @@ -8,12 +8,12 @@ * * Emulation core dispatcher. * - * Version: @(#)hdc_ide_sff8038i.h 1.0.0 2019/05/12 + * Version: @(#)hdc_ide_sff8038i.h 1.0.1 2020/01/14 * * Authors: Sarah Walker, * Miran Grca, - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. */ typedef struct @@ -22,7 +22,9 @@ typedef struct ptr0, enabled; uint32_t ptr, ptr_cur, addr; - int count, eot; + int count, eot, + slot, + irq_mode, irq_pin; } sff8038i_t; @@ -36,3 +38,8 @@ extern int sff_bus_master_dma_write(int channel, uint8_t *data, int transfer_len extern void sff_bus_master_set_irq(int channel, void *priv); extern void sff_bus_master_reset(sff8038i_t *dev, uint16_t old_base); + +extern void sff_set_slot(sff8038i_t *dev, int slot); + +extern void sff_set_irq_mode(sff8038i_t *dev, int irq_mode); +extern void sff_set_irq_pin(sff8038i_t *dev, int irq_pin); diff --git a/src/dma.c b/src/dma.c index 7322f471e..f9a02f365 100644 --- a/src/dma.c +++ b/src/dma.c @@ -8,15 +8,15 @@ * * Implementation of the Intel DMA controllers. * - * Version: @(#)dma.c 1.0.7 2019/09/28 + * Version: @(#)dma.c 1.0.8 2020/01/14 * * Authors: Sarah Walker, * Miran Grca, * Fred N. van Kempen, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. */ #include #include @@ -38,6 +38,7 @@ dma_t dma[8]; +uint8_t dma_e; static uint8_t dmaregs[16]; @@ -615,6 +616,8 @@ dma_reset(void) dma_wp = dma16_wp = 0; dma_m = 0; + dma_e = 0xff; + for (c = 0; c < 16; c++) dmaregs[c] = dma16regs[c] = 0; for (c = 0; c < 8; c++) { @@ -736,6 +739,8 @@ dma_channel_read(int channel) return(DMA_NODATA); } + if (!(dma_e & (1 << channel))) + return(DMA_NODATA); if ((dma_m & (1 << channel)) && !dma_req_is_soft) return(DMA_NODATA); if ((dma_c->mode & 0xC) != 8) @@ -809,6 +814,8 @@ dma_channel_write(int channel, uint16_t val) return(DMA_NODATA); } + if (!(dma_e & (1 << channel))) + return(DMA_NODATA); if ((dma_m & (1 << channel)) && !dma_req_is_soft) return(DMA_NODATA); if ((dma_c->mode & 0xC) != 4) diff --git a/src/dma.h b/src/dma.h index 75f923e66..5340ba2ea 100644 --- a/src/dma.h +++ b/src/dma.h @@ -8,15 +8,15 @@ * * Definitions for the Intel DMA controller. * - * Version: @(#)dma.h 1.0.2 2018/03/12 + * Version: @(#)dma.h 1.0.3 2020/01/14 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. + * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2016-2020 Miran Grca. + * Copyright 2008-2020 Sarah Walker. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -63,6 +63,7 @@ typedef struct { extern dma_t dma[8]; +extern uint8_t dma_e; extern void dma_init(void); diff --git a/src/machine/m_at.c b/src/machine/m_at.c index 773ac6126..2697bbf24 100644 --- a/src/machine/m_at.c +++ b/src/machine/m_at.c @@ -8,15 +8,15 @@ * * Standard PC/AT implementation. * - * Version: @(#)m_at.c 1.0.11 2019/11/15 + * Version: @(#)m_at.c 1.0.12 2020/01/13 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2016-2019 Miran Grca. - * Copyright 2008-2019 Sarah Walker. + * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2016-2020 Miran Grca. + * Copyright 2008-2020 Sarah Walker. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -59,7 +59,7 @@ void -machine_at_common_init_ex(const machine_t *model, int is_ibm) +machine_at_common_init_ex(const machine_t *model, int type) { machine_common_init(model); @@ -67,9 +67,9 @@ machine_at_common_init_ex(const machine_t *model, int is_ibm) pic2_init(); dma16_init(); - if (is_ibm) + if (type == 1) device_add(&ibmat_nvr_device); - else + else if (type == 0) device_add(&at_nvr_device); if (joystick_type != 7) diff --git a/src/machine/m_at_socket7_s7.c b/src/machine/m_at_socket7_s7.c index 36960af3e..e0a221104 100644 --- a/src/machine/m_at_socket7_s7.c +++ b/src/machine/m_at_socket7_s7.c @@ -38,7 +38,7 @@ #include "../piix.h" #include "../sio.h" #include "../sst_flash.h" -#include "../vt82c586b.h" +#include "../via_vt82c586b.h" #include "../video/video.h" #include "../video/vid_cl54xx.h" #include "../video/vid_s3.h" @@ -456,7 +456,6 @@ machine_at_j656vxd_init(const machine_t *model) return ret; } -#if defined(DEV_BRANCH) && defined(USE_SS7) int machine_at_mvp3_init(const machine_t *model) { @@ -468,20 +467,20 @@ machine_at_mvp3_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init(model); + machine_at_common_init_ex(model, 2); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_ONBOARD, 1, 2, 3, 4); pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x0a, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 1, 2, 3, 4); device_add(&via_mvp3_device); - device_add(&vt82c586b_device); + device_add(&via_vt82c586b_device); device_add(&keyboard_ps2_pci_device); device_add(&w83877tf_device); device_add(&sst_flash_39sf010_device); return ret; } -#endif \ No newline at end of file diff --git a/src/machine/machine.h b/src/machine/machine.h index fdbc4bbe1..689ec98c9 100644 --- a/src/machine/machine.h +++ b/src/machine/machine.h @@ -8,15 +8,15 @@ * * Handling of the emulated machines. * - * Version: @(#)machine.h 1.0.34 2019/03/08 + * Version: @(#)machine.h 1.0.35 2020/01/13 * * Authors: Sarah Walker, * Miran Grca, * Fred N. van Kempen, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. */ #ifndef EMU_MACHINE_H # define EMU_MACHINE_H @@ -151,7 +151,7 @@ extern const device_t *pc3086_get_device(void); #endif /* m_at.c */ -extern void machine_at_common_init_ex(const machine_t *, int is_ibm); +extern void machine_at_common_init_ex(const machine_t *, int type); extern void machine_at_common_init(const machine_t *); extern void machine_at_init(const machine_t *); extern void machine_at_ps2_init(const machine_t *); @@ -276,9 +276,7 @@ extern int machine_at_i430vx_init(const machine_t *); extern int machine_at_p55va_init(const machine_t *); extern int machine_at_j656vxd_init(const machine_t *); -#if defined(DEV_BRANCH) && defined(USE_SS7) extern int machine_at_mvp3_init(const machine_t *); -#endif #ifdef EMU_DEVICE_H extern const device_t *at_pb640_get_device(void); diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 893b37e7a..457d4da3d 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -11,15 +11,15 @@ * NOTES: OpenAT wip for 286-class machine with open BIOS. * PS2_M80-486 wip, pending receipt of TRM's for machine. * - * Version: @(#)machine_table.c 1.0.50 2019/11/19 + * Version: @(#)machine_table.c 1.0.51 2020/01/14 * * Authors: Sarah Walker, * Miran Grca, * Fred N. van Kempen, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. */ #include #include @@ -208,6 +208,8 @@ const machine_t machines[] = { { "[Socket 7 VX] Jetway J656VXD", "j656vxd", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_j656vxd_init, NULL }, { "[Socket 7 VX] Shuttle HOT-557", "430vx", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_i430vx_init, NULL }, + { "[Super Socket 7] FIC VA503P", "ficva503p", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 127, machine_at_mvp3_init, NULL }, + #if defined(DEV_BRANCH) && defined(USE_I686) { "[Socket 8 FX] Tyan Titan-Pro AT", "440fx", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 127, machine_at_i440fx_init, NULL }, { "[Socket 8 FX] Tyan Titan-Pro ATX", "tpatx", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 127, machine_at_s1668_init, NULL }, diff --git a/src/machine/machine_table_new.c b/src/machine/machine_table_new.c index c9ae1d598..d072a92c6 100644 --- a/src/machine/machine_table_new.c +++ b/src/machine/machine_table_new.c @@ -11,15 +11,15 @@ * NOTES: OpenAT wip for 286-class machine with open BIOS. * PS2_M80-486 wip, pending receipt of TRM's for machine. * - * Version: @(#)machine_table.c 1.0.50 2019/11/19 + * Version: @(#)machine_table.c 1.0.51 2020/01/14 * * Authors: Sarah Walker, * Miran Grca, * Fred N. van Kempen, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. */ #include #include @@ -33,9 +33,10 @@ #include "machine.h" -#define MACHINE_CPUS_PENTIUM_S5 {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}} -#define MACHINE_CPUS_PENTIUM_S73V {{ "Intel", cpus_Pentium3V}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"Cyrix", cpus_6x863V},{"", NULL}} -#define MACHINE_CPUS_PENTIUM_S7 {{ "Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}} +#define MACHINE_CPUS_PENTIUM_S5 {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}} +#define MACHINE_CPUS_PENTIUM_S73V {{ "Intel", cpus_Pentium3V}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"Cyrix", cpus_6x863V}, {"", NULL}} +#define MACHINE_CPUS_PENTIUM_S7 {{ "Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}} +#define MACHINE_CPUS_PENTIUM_SS7 {{ "Intel", cpus_Pentium}, {"IDT", cpus_WinChip_SS7}, {"AMD", cpus_K56_SS7}, {"Cyrix", cpus_6x86SS7}, {"", NULL}} const machine_t machines[] = { { "[8088] AMI XT clone", "amixt", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA, 64, 640, 64, 0, machine_xt_amixt_init, NULL }, @@ -192,9 +193,7 @@ const machine_t machines[] = { { "[Socket 7 VX] Jetway J656VXD", "j656vxd", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_j656vxd_init, NULL }, { "[Socket 7 VX] Shuttle HOT-557", "430vx", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_i430vx_init, NULL }, -#if defined(DEV_BRANCH) && defined(USE_SS7) - { "[Super Socket 7] FIC VA503P", "ficva503p", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 127, machine_at_mvp3_init, NULL }, -#endif + { "[Super Socket 7] FIC VA503P", "ficva503p", MACHINE_CPUS_PENTIUM_SS7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 127, machine_at_mvp3_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_I686) { "[Socket 8 FX] Tyan Titan-Pro AT", "440fx", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 127, machine_at_i440fx_init, NULL }, diff --git a/src/nvr.h b/src/nvr.h index f315b7a51..7929ce642 100644 --- a/src/nvr.h +++ b/src/nvr.h @@ -8,13 +8,13 @@ * * Definitions for the generic NVRAM/CMOS driver. * - * Version: @(#)nvr.h 1.0.11 2019/03/16 + * Version: @(#)nvr.h 1.0.12 2020/01/13 * * Author: Fred N. van Kempen, , * David HrdliÄka, * - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2018,2019 David HrdliÄka. + * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2018-2020 David HrdliÄka. * * Redistribution and use in source and binary forms, with * or without modification, are permitted provided that the @@ -91,6 +91,7 @@ extern const device_t at_nvr_device; extern const device_t ps_nvr_device; extern const device_t amstrad_nvr_device; extern const device_t ibmat_nvr_device; +extern const device_t via_nvr_device; #endif @@ -109,5 +110,7 @@ extern int nvr_get_days(int month, int year); extern void nvr_time_get(struct tm *); extern void nvr_time_set(struct tm *); +extern void nvr_at_handler(int set, uint16_t base, nvr_t *nvr); + #endif /*EMU_NVR_H*/ diff --git a/src/nvr_at.c b/src/nvr_at.c index 967f14018..d4b1cfde1 100644 --- a/src/nvr_at.c +++ b/src/nvr_at.c @@ -189,16 +189,16 @@ * including the later update (DS12887A) which implemented a * "century" register to be compatible with Y2K. * - * Version: @(#)nvr_at.c 1.0.16 2019/11/19 + * Version: @(#)nvr_at.c 1.0.17 2020/01/13 * * Authors: Fred N. van Kempen, * Miran Grca, * Mahod, * Sarah Walker, * - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2016-2019 Miran Grca. - * Copyright 2008-2019 Sarah Walker. + * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2016-2020 Miran Grca. + * Copyright 2008-2020 Sarah Walker. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -281,6 +281,9 @@ # define REGD_VRT 0x80 #define RTC_CENTURY_AT 0x32 /* century register for AT etc */ #define RTC_CENTURY_PS 0x37 /* century register for PS/1 PS/2 */ +#define RTC_ALDAY 0x7D /* VIA VT82C586B - alarm day */ +#define RTC_ALMONTH 0x7E /* VIA VT82C586B - alarm month */ +#define RTC_CENTURY_VIA 0x7F /* century register for VIA VT82C586B */ #define RTC_REGS 14 /* number of registers */ @@ -290,7 +293,7 @@ typedef struct { uint8_t cent; uint8_t def; - uint8_t addr; + uint8_t addr[8]; int16_t count, state; @@ -402,6 +405,20 @@ check_alarm(nvr_t *nvr, int8_t addr) } +/* Check for VIA stuff. */ +static int8_t +check_alarm_via(nvr_t *nvr, int8_t addr, int8_t addr_2) +{ + local_t *local = (local_t *)nvr->data; + + if (local->cent == RTC_CENTURY_VIA) { + return((nvr->regs[addr_2] == nvr->regs[addr]) || + ((nvr->regs[addr_2] & AL_DONTCARE) == AL_DONTCARE)); + } else + return 0; +} + + /* Update the NVR registers from the internal clock. */ static void timer_update(void *priv) @@ -425,7 +442,9 @@ timer_update(void *priv) /* Check for any alarms we need to handle. */ if (check_alarm(nvr, RTC_SECONDS) && check_alarm(nvr, RTC_MINUTES) && - check_alarm(nvr, RTC_HOURS)) { + check_alarm(nvr, RTC_HOURS) && + check_alarm_via(nvr, RTC_DOM, RTC_ALDAY) && + check_alarm_via(nvr, RTC_MONTH, RTC_ALMONTH)) { nvr->regs[RTC_REGC] |= REGC_AF; if (nvr->regs[RTC_REGB] & REGB_AIE) { nvr->regs[RTC_REGC] |= REGC_IRQF; @@ -535,12 +554,13 @@ nvr_write(uint16_t addr, uint8_t val, void *priv) local_t *local = (local_t *)nvr->data; struct tm tm; uint8_t old; + uint8_t addr_id = (addr & 0x0e) >> 1; sub_cycles(ISA_CYCLES(8)); if (addr & 1) { - old = nvr->regs[local->addr]; - switch(local->addr) { + old = nvr->regs[local->addr[addr_id]]; + switch(local->addr[addr_id]) { case RTC_REGA: nvr->regs[RTC_REGA] = val; timer_load_count(nvr); @@ -560,15 +580,15 @@ nvr_write(uint16_t addr, uint8_t val, void *priv) break; default: /* non-RTC registers are just NVRAM */ - if (nvr->regs[local->addr] != val) { - nvr->regs[local->addr] = val; + if (nvr->regs[local->addr[addr_id]] != val) { + nvr->regs[local->addr[addr_id]] = val; nvr_dosave = 1; } break; } - if ((local->addr < RTC_REGA) || ((local->cent != 0xff) && (local->addr == local->cent))) { - if ((local->addr != 1) && (local->addr != 3) && (local->addr != 5)) { + if ((local->addr[addr_id] < RTC_REGA) || ((local->cent != 0xff) && (local->addr[addr_id] == local->cent))) { + if ((local->addr[addr_id] != 1) && (local->addr[addr_id] != 3) && (local->addr[addr_id] != 5)) { if ((old != val) && !(time_sync & TIME_SYNC_ENABLED)) { /* Update internal clock. */ time_get(nvr, &tm); @@ -578,7 +598,10 @@ nvr_write(uint16_t addr, uint8_t val, void *priv) } } } else { - local->addr = (val & (nvr->size - 1)); + local->addr[addr_id] = (val & (nvr->size - 1)); + /* Some chipsets use a 256 byte NVRAM but ports 70h and 71h always access only 128 bytes. */ + if (addr_id == 0x0) + local->addr[addr_id] &= 0x7f; if (!(machines[machine].flags & MACHINE_MCA) && !(machines[machine].flags & MACHINE_NONMI)) nmi_mask = (~val & 0x80); @@ -593,10 +616,11 @@ nvr_read(uint16_t addr, void *priv) nvr_t *nvr = (nvr_t *)priv; local_t *local = (local_t *)nvr->data; uint8_t ret; + uint8_t addr_id = (addr & 0x0e) >> 1; sub_cycles(ISA_CYCLES(8)); - if (addr & 1) switch(local->addr) { + if (addr & 1) switch(local->addr[addr_id]) { case RTC_REGA: ret = (nvr->regs[RTC_REGA] & 0x7f) | local->stat; break; @@ -613,10 +637,10 @@ nvr_read(uint16_t addr, void *priv) break; default: - ret = nvr->regs[local->addr]; + ret = nvr->regs[local->addr[addr_id]]; break; } else - ret = local->addr; + ret = local->addr[addr_id]; return(ret); } @@ -692,6 +716,14 @@ nvr_at_speed_changed(void *priv) } +void +nvr_at_handler(int set, uint16_t base, nvr_t *nvr) +{ + io_handler(set, base, 2, + nvr_read,NULL,NULL, nvr_write,NULL,NULL, nvr); +} + + static void * nvr_at_init(const device_t *info) { @@ -710,7 +742,7 @@ nvr_at_init(const device_t *info) /* This is machine specific. */ nvr->size = machines[machine].nvrmask + 1; local->def = 0x00; - switch(info->local) { + switch(info->local & 7) { case 0: /* standard AT, no century register */ nvr->irq = 8; local->cent = 0xff; @@ -738,6 +770,10 @@ nvr_at_init(const device_t *info) local->def = 0xff; break; + case 5: /* VIA VT82C586B */ + nvr->irq = 8; + local->cent = RTC_CENTURY_VIA; + break; } /* Set up any local handlers here. */ @@ -758,6 +794,10 @@ nvr_at_init(const device_t *info) /* Set up the I/O handler for this device. */ io_sethandler(0x0070, 2, nvr_read,NULL,NULL, nvr_write,NULL,NULL, nvr); + if (info->local & 8) { + io_sethandler(0x0072, 2, + nvr_read,NULL,NULL, nvr_write,NULL,NULL, nvr); + } return(nvr); } @@ -829,3 +869,13 @@ const device_t ibmat_nvr_device = { NULL, nvr_at_speed_changed, NULL }; + +const device_t via_nvr_device = { + "VIA PC/AT NVRAM", + DEVICE_ISA | DEVICE_AT, + 9, + nvr_at_init, nvr_at_close, NULL, + NULL, nvr_at_speed_changed, + NULL +}; + diff --git a/src/sst_flash.c b/src/sst_flash.c index b5666659f..7dfc26f1b 100644 --- a/src/sst_flash.c +++ b/src/sst_flash.c @@ -214,7 +214,7 @@ sst_readl(uint32_t addr, void *p) static void sst_add_mappings(sst_t *dev) { - int max = 2, i = 0; + int i = 0; uint32_t base, fbase; for (i = 0; i < 2; i++) { diff --git a/src/sst_flash.h b/src/sst_flash.h index f919e73d1..809fc0c44 100644 --- a/src/sst_flash.h +++ b/src/sst_flash.h @@ -8,12 +8,10 @@ * * Implementation of an SST flash chip. * - * Version: @(#)sst_flash.h 1.0.2 2019/06/25 + * Version: @(#)sst_flash.h 1.0.3 2020/01/14 * * Author: Melissa Goad, * Copyright 2020 Melissa Goad. */ -#if defined(DEV_BRANCH) && defined(USE_SS7) extern const device_t sst_flash_39sf010_device; -#endif \ No newline at end of file diff --git a/src/via_vt82c586b.c b/src/via_vt82c586b.c new file mode 100644 index 000000000..501175d23 --- /dev/null +++ b/src/via_vt82c586b.c @@ -0,0 +1,639 @@ +/* + * 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. + * + * Emulation of the VIA Apollo MVP3 southbridge + * + * Version: @(#)via_vt82c586b.c 1.0.0 2020/01/14 + * + * Authors: Sarah Walker, + * Miran Grca, + * Melissa Goad, + * + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2020 Melissa Goad. + */ + +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include "86box.h" +#include "cdrom/cdrom.h" +#include "cpu/cpu.h" +#include "scsi/scsi_device.h" +#include "scsi/scsi_cdrom.h" +#include "dma.h" +#include "io.h" +#include "device.h" +#include "apm.h" +#include "keyboard.h" +#include "mem.h" +#include "timer.h" +#include "nvr.h" +#include "pci.h" +#include "pic.h" +#include "port_92.h" +#include "disk/hdc.h" +#include "disk/hdc_ide.h" +#include "disk/hdc_ide_sff8038i.h" +#include "disk/zip.h" +#include "machine/machine.h" +#include "via_vt82c586b.h" + + +#define ACPI_TIMER_FREQ 3579545 + +#define ACPI_IO_ENABLE (1 << 7) +#define ACPI_TIMER_32BIT (1 << 3) + + +typedef struct +{ + uint8_t pci_isa_regs[256]; + uint8_t ide_regs[256]; + uint8_t usb_regs[256]; + uint8_t power_regs[256]; + sff8038i_t * bm[2]; + nvr_t * nvr; + int nvr_enabled; + + struct + { + uint16_t io_base; + } usb; + + struct + { + uint16_t io_base; + } power; +} via_vt82c586b_t; + + +static void +via_vt82c586b_reset_hard(void *priv) +{ + int i; + + via_vt82c586b_t *via_vt82c586b = (via_vt82c586b_t *) priv; + uint16_t old_base = (via_vt82c586b->ide_regs[0x20] & 0xf0) | (via_vt82c586b->ide_regs[0x21] << 8); + + sff_bus_master_reset(via_vt82c586b->bm[0], old_base); + sff_bus_master_reset(via_vt82c586b->bm[1], old_base + 8); + + memset(via_vt82c586b->pci_isa_regs, 0, 256); + memset(via_vt82c586b->ide_regs, 0, 256); + memset(via_vt82c586b->usb_regs, 0, 256); + memset(via_vt82c586b->power_regs, 0, 256); + + via_vt82c586b->pci_isa_regs[0x00] = 0x06; via_vt82c586b->pci_isa_regs[0x01] = 0x11; /*VIA*/ + via_vt82c586b->pci_isa_regs[0x02] = 0x86; via_vt82c586b->pci_isa_regs[0x03] = 0x05; /*VT82C586B*/ + via_vt82c586b->pci_isa_regs[0x04] = 0x0f; + via_vt82c586b->pci_isa_regs[0x07] = 0x02; + via_vt82c586b->pci_isa_regs[0x0a] = 0x01; + via_vt82c586b->pci_isa_regs[0x0b] = 0x06; + via_vt82c586b->pci_isa_regs[0x0e] = 0x80; + + via_vt82c586b->pci_isa_regs[0x48] = 0x01; + via_vt82c586b->pci_isa_regs[0x4a] = 0x04; + via_vt82c586b->pci_isa_regs[0x4f] = 0x03; + + via_vt82c586b->pci_isa_regs[0x50] = 0x24; + via_vt82c586b->pci_isa_regs[0x59] = 0x04; + + dma_e = 0x00; + for (i = 0; i < 8; i++) { + dma[i].ab &= 0xffff000f; + dma[i].ac &= 0xffff000f; + } + + /* IDE registers */ + via_vt82c586b->ide_regs[0x00] = 0x06; via_vt82c586b->ide_regs[0x01] = 0x11; /*VIA*/ + via_vt82c586b->ide_regs[0x02] = 0x71; via_vt82c586b->ide_regs[0x03] = 0x05; /*VT82C586B*/ + via_vt82c586b->ide_regs[0x04] = 0x80; + via_vt82c586b->ide_regs[0x06] = 0x80; via_vt82c586b->ide_regs[0x07] = 0x02; + via_vt82c586b->ide_regs[0x09] = 0x85; + via_vt82c586b->ide_regs[0x0a] = 0x01; + via_vt82c586b->ide_regs[0x0b] = 0x01; + + via_vt82c586b->ide_regs[0x10] = 0xf1; via_vt82c586b->ide_regs[0x11] = 0x01; + via_vt82c586b->ide_regs[0x14] = 0xf5; via_vt82c586b->ide_regs[0x15] = 0x03; + via_vt82c586b->ide_regs[0x18] = 0x71; via_vt82c586b->ide_regs[0x19] = 0x01; + via_vt82c586b->ide_regs[0x1c] = 0x75; via_vt82c586b->ide_regs[0x1d] = 0x03; + via_vt82c586b->ide_regs[0x20] = 0x01; via_vt82c586b->ide_regs[0x21] = 0xcc; + via_vt82c586b->ide_regs[0x3c] = 0x0e; + + via_vt82c586b->ide_regs[0x40] = 0x08; + via_vt82c586b->ide_regs[0x41] = 0x02; + via_vt82c586b->ide_regs[0x42] = 0x09; + via_vt82c586b->ide_regs[0x43] = 0x3a; + via_vt82c586b->ide_regs[0x44] = 0x68; + via_vt82c586b->ide_regs[0x46] = 0xc0; + via_vt82c586b->ide_regs[0x48] = 0xa8; via_vt82c586b->ide_regs[0x49] = 0xa8; + via_vt82c586b->ide_regs[0x4a] = 0xa8; via_vt82c586b->ide_regs[0x4b] = 0xa8; + via_vt82c586b->ide_regs[0x4c] = 0xff; + via_vt82c586b->ide_regs[0x4e] = 0xff; + via_vt82c586b->ide_regs[0x4f] = 0xff; + via_vt82c586b->ide_regs[0x50] = 0x03; via_vt82c586b->ide_regs[0x51] = 0x03; + via_vt82c586b->ide_regs[0x52] = 0x03; via_vt82c586b->ide_regs[0x53] = 0x03; + + via_vt82c586b->ide_regs[0x61] = 0x02; + via_vt82c586b->ide_regs[0x69] = 0x02; + + via_vt82c586b->usb_regs[0x00] = 0x06; via_vt82c586b->usb_regs[0x01] = 0x11; /*VIA*/ + via_vt82c586b->usb_regs[0x02] = 0x38; via_vt82c586b->usb_regs[0x03] = 0x30; + via_vt82c586b->usb_regs[0x04] = 0x00; via_vt82c586b->usb_regs[0x05] = 0x00; + via_vt82c586b->usb_regs[0x06] = 0x00; via_vt82c586b->usb_regs[0x07] = 0x02; + via_vt82c586b->usb_regs[0x0a] = 0x03; + via_vt82c586b->usb_regs[0x0b] = 0x0c; + via_vt82c586b->usb_regs[0x0d] = 0x16; + via_vt82c586b->usb_regs[0x20] = 0x01; + via_vt82c586b->usb_regs[0x21] = 0x03; + via_vt82c586b->usb_regs[0x3d] = 0x04; + + via_vt82c586b->usb_regs[0x60] = 0x10; + via_vt82c586b->usb_regs[0xc1] = 0x20; + + via_vt82c586b->power_regs[0x00] = 0x06; via_vt82c586b->power_regs[0x01] = 0x11; /*VIA*/ + via_vt82c586b->power_regs[0x02] = 0x40; via_vt82c586b->power_regs[0x03] = 0x30; + via_vt82c586b->power_regs[0x04] = 0x00; via_vt82c586b->power_regs[0x05] = 0x00; + via_vt82c586b->power_regs[0x06] = 0x80; via_vt82c586b->power_regs[0x07] = 0x02; + via_vt82c586b->power_regs[0x08] = 0x10; /*Production version (3041)*/ + via_vt82c586b->power_regs[0x48] = 0x01; + + pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); + + pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED); + pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED); + pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED); + + ide_pri_disable(); + ide_sec_disable(); +} + + +static void +via_vt82c586b_ide_handlers(via_vt82c586b_t *dev) +{ + uint16_t main, side; + + ide_pri_disable(); + ide_sec_disable(); + + if (dev->ide_regs[0x09] & 0x01) { + main = (dev->ide_regs[0x11] << 8) | (dev->ide_regs[0x10] & 0xf8); + side = ((dev->ide_regs[0x15] << 8) | (dev->ide_regs[0x14] & 0xfc)) + 2; + } else { + main = 0x1f0; + side = 0x3f6; + } + ide_set_base(0, main); + ide_set_side(0, side); + + if (dev->ide_regs[0x09] & 0x04) { + main = (dev->ide_regs[0x19] << 8) | (dev->ide_regs[0x18] & 0xf8); + side = ((dev->ide_regs[0x1d] << 8) | (dev->ide_regs[0x1c] & 0xfc)) + 2; + } else { + main = 0x170; + side = 0x376; + } + ide_set_base(1, main); + ide_set_side(1, side); + + if (dev->ide_regs[0x04] & PCI_COMMAND_IO) { + if (dev->ide_regs[0x40] & 0x02) + ide_pri_enable(); + if (dev->ide_regs[0x40] & 0x01) + ide_sec_enable(); + } +} + + +static void +via_vt82c586b_bus_master_handlers(via_vt82c586b_t *dev, uint16_t old_base) +{ + uint16_t base; + base = (dev->ide_regs[0x20] & 0xf0) | (dev->ide_regs[0x21] << 8); + + sff_bus_master_handlers(dev->bm[0], old_base, base, (dev->ide_regs[0x04] & 1)); + sff_bus_master_handlers(dev->bm[1], old_base + 8, base + 8, (dev->ide_regs[0x04] & 1)); +} + + +static uint8_t +via_vt82c586b_read(int func, int addr, void *priv) +{ + via_vt82c586b_t *dev = (via_vt82c586b_t *) priv; + + uint8_t ret = 0xff; + int c; + + switch(func) { + case 0: + if ((addr >= 0x60) && (addr <= 0x6f)) { + c = (addr & 0x0e) >> 1; + if (addr & 0x01) + ret = (dma[c].ab & 0x0000ff00) >> 8; + else { + ret = (dma[c].ab & 0x000000f0); + ret |= (!!(dma_e & (1 << c)) << 3); + } + } else + ret = dev->pci_isa_regs[addr]; + break; + case 1: + ret = dev->ide_regs[addr]; + break; + case 2: + ret = dev->usb_regs[addr]; + break; + case 3: + ret = dev->power_regs[addr]; + break; + } + + return ret; +} + + +static uint8_t +usb_reg_read(uint16_t addr, void *p) +{ + uint8_t ret = 0xff; + + switch (addr & 0x1f) { + case 0x10: case 0x11: case 0x12: case 0x13: + /* Port status */ + ret = 0x00; + break; + } + + return ret; +} + + +static void +usb_reg_write(uint16_t addr, uint8_t val, void *p) +{ +} + + +static void +nvr_update_io_mapping(via_vt82c586b_t *dev) +{ + if (dev->nvr_enabled) + nvr_at_handler(0, 0x0074, dev->nvr); + + if ((dev->pci_isa_regs[0x5b] & 0x02) && (dev->pci_isa_regs[0x48] & 0x08)) + nvr_at_handler(1, 0x0074, dev->nvr); +} + + +static void +usb_update_io_mapping(via_vt82c586b_t *dev) +{ + if (dev->usb.io_base != 0x0000) + io_removehandler(dev->usb.io_base, 0x20, usb_reg_read, NULL, NULL, usb_reg_write, NULL, NULL, dev); + + dev->usb.io_base = (dev->usb_regs[0x20] & ~0x1f) | (dev->usb_regs[0x21] << 8); + + if ((dev->usb_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) && (dev->usb.io_base != 0x0000)) + io_sethandler(dev->usb.io_base, 0x20, usb_reg_read, NULL, NULL, usb_reg_write, NULL, NULL, dev); +} + + +static uint8_t +power_reg_read(uint16_t addr, void *p) +{ + via_vt82c586b_t *dev = (via_vt82c586b_t *) p; + + uint32_t timer; + uint8_t ret = 0xff; + + switch (addr & 0xff) { + case 0x08: case 0x09: case 0x0a: case 0x0b: + /* ACPI timer */ + timer = (tsc * ACPI_TIMER_FREQ) / machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed; + if (!(dev->power_regs[0x41] & ACPI_TIMER_32BIT)) + timer &= 0x00ffffff; + ret = (timer >> (8 * (addr & 3))) & 0xff; + break; + } + + return ret; +} + + +static void +power_reg_write(uint16_t addr, uint8_t val, void *p) +{ +} + + +static void +power_update_io_mapping(via_vt82c586b_t *dev) +{ + if (dev->power.io_base != 0x0000) + io_removehandler(dev->power.io_base, 0x100, power_reg_read, NULL, NULL, power_reg_write, NULL, NULL, dev); + + dev->power.io_base = dev->power_regs[0x41] | (dev->power_regs[0x49] << 8); + + if ((dev->power_regs[0x41] & ACPI_IO_ENABLE) && (dev->power.io_base != 0x0000)) + io_sethandler(dev->power.io_base, 0x100, power_reg_read, NULL, NULL, power_reg_write, NULL, NULL, dev); +} + + +static void +via_vt82c586b_write(int func, int addr, uint8_t val, void *priv) +{ + via_vt82c586b_t *dev = (via_vt82c586b_t *) priv; + + uint16_t old_base, base; + int c; + + if (func > 3) + return; + + old_base = (dev->ide_regs[0x20] & 0xf0) | (dev->ide_regs[0x21] << 8); + + switch(func) { + case 0: /* PCI-ISA bridge */ + /* Read-only addresses */ + if ((addr < 4) || (addr == 5) || (addr == 6) || ((addr >= 8) && (addr < 0x40)) || + (addr == 0x49) || (addr == 0x4b) || ((addr >= 0x51) && (addr < 0x54)) || ((addr >= 0x5d) && (addr < 0x60)) || + ((addr >= 0x68) && (addr < 0x6a)) || (addr >= 0x73)) + return; + + switch (addr) { + case 0x04: + dev->pci_isa_regs[0x04] = (val & 8) | 7; + break; + case 0x06: + dev->pci_isa_regs[0x06] &= ~(val & 0xb0); + break; + + case 0x47: + if ((val & 0x81) == 0x81) + resetx86(); + pci_elcr_set_enabled(!!(val & 0x20)); + dev->pci_isa_regs[0x47] = val & 0xfe; + break; + case 0x48: + dev->pci_isa_regs[0x48] = val; + nvr_update_io_mapping(dev); + break; + + case 0x54: + pci_set_irq_level(PCI_INTA, !(val & 8)); + pci_set_irq_level(PCI_INTB, !(val & 4)); + pci_set_irq_level(PCI_INTC, !(val & 2)); + pci_set_irq_level(PCI_INTD, !(val & 1)); + break; + case 0x55: + pci_set_irq_routing(PCI_INTD, (val & 0xf0) ? (val >> 4) : PCI_IRQ_DISABLED); + pci_set_mirq_routing(PCI_MIRQ0, (val & 0x0f) ? (val & 0x0f) : PCI_IRQ_DISABLED); + dev->pci_isa_regs[0x55] = val; + break; + case 0x56: + pci_set_irq_routing(PCI_INTA, (val & 0xf0) ? (val >> 4) : PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTB, (val & 0x0f) ? (val & 0x0f) : PCI_IRQ_DISABLED); + dev->pci_isa_regs[0x56] = val; + break; + case 0x57: + pci_set_irq_routing(PCI_INTC, (val & 0xf0) ? (val >> 4) : PCI_IRQ_DISABLED); + pci_set_mirq_routing(PCI_MIRQ1, (val & 0x0f) ? (val & 0x0f) : PCI_IRQ_DISABLED); + dev->pci_isa_regs[0x57] = val; + break; + case 0x58: + pci_set_mirq_routing(PCI_MIRQ2, (val & 0x0f) ? (val & 0x0f) : PCI_IRQ_DISABLED); + dev->pci_isa_regs[0x58] = val; + break; + case 0x5b: + dev->pci_isa_regs[0x5b] = val; + nvr_update_io_mapping(dev); + break; + + case 0x60: case 0x62: case 0x64: case 0x66: + case 0x68: case 0x6a: case 0x6c: case 0x6e: + c = (addr & 0x0e) >> 1; + dma[c].ab = (dma[c].ab & 0xffffff0f) | (val & 0xf0); + dma[c].ac = (dma[c].ac & 0xffffff0f) | (val & 0xf0); + if (val & 0x08) + dma_e |= (1 << c); + else + dma_e &= ~(1 << c); + break; + case 0x61: case 0x63: case 0x65: case 0x67: + case 0x69: case 0x6b: case 0x6d: case 0x6f: + c = (addr & 0x0e) >> 1; + dma[c].ab = (dma[c].ab & 0xffff00ff) | (val << 8); + dma[c].ac = (dma[c].ac & 0xffff00ff) | (val << 8); + break; + + case 0x70: case 0x71: case 0x72: case 0x73: + dev->pci_isa_regs[(addr - 0x44)] = val; + break; + } + break; + + case 1: /* IDE regs */ + /* Read-only addresses */ + if ((addr < 4) || (addr == 5) || (addr == 8) || ((addr >= 0xa) && (addr < 0x0d)) || + ((addr >= 0x0e) && (addr < 0x10)) || ((addr >= 0x12) && (addr < 0x13)) || + ((addr >= 0x16) && (addr < 0x17)) || ((addr >= 0x1a) && (addr < 0x1b)) || + ((addr >= 0x1e) && (addr < 0x1f)) || ((addr >= 0x22) && (addr < 0x3c)) || + ((addr >= 0x3e) && (addr < 0x40)) || ((addr >= 0x54) && (addr < 0x60)) || + ((addr >= 0x52) && (addr < 0x68)) || (addr >= 0x62)) + return; + + switch (addr) { + case 0x04: + base = (dev->ide_regs[0x20] & 0xf0) | (dev->ide_regs[0x21] << 8); + dev->ide_regs[0x04] = val & 0x85; + via_vt82c586b_ide_handlers(dev); + via_vt82c586b_bus_master_handlers(dev, base); + break; + case 0x06: + dev->ide_regs[0x06] &= ~(val & 0xb0); + break; + + case 0x09: + dev->ide_regs[0x09] = (val & 0x05) | 0x8a; + via_vt82c586b_ide_handlers(dev); + break; + + case 0x10: + dev->ide_regs[0x10] = (val & 0xf8) | 1; + via_vt82c586b_ide_handlers(dev); + break; + case 0x11: + dev->ide_regs[0x11] = val; + via_vt82c586b_ide_handlers(dev); + break; + + case 0x14: + dev->ide_regs[0x14] = (val & 0xfc) | 1; + via_vt82c586b_ide_handlers(dev); + break; + case 0x15: + dev->ide_regs[0x15] = val; + via_vt82c586b_ide_handlers(dev); + break; + + case 0x18: + dev->ide_regs[0x18] = (val & 0xf8) | 1; + via_vt82c586b_ide_handlers(dev); + break; + case 0x19: + dev->ide_regs[0x19] = val; + via_vt82c586b_ide_handlers(dev); + break; + + case 0x1c: + dev->ide_regs[0x1c] = (val & 0xfc) | 1; + via_vt82c586b_ide_handlers(dev); + break; + case 0x1d: + dev->ide_regs[0x1d] = val; + via_vt82c586b_ide_handlers(dev); + break; + + case 0x20: + dev->ide_regs[0x20] = (val & 0xf0) | 1; + via_vt82c586b_bus_master_handlers(dev, old_base); + break; + case 0x21: + dev->ide_regs[0x21] = val; + via_vt82c586b_bus_master_handlers(dev, old_base); + break; + + case 0x3d: + sff_set_irq_mode(dev->bm[0], val); + sff_set_irq_mode(dev->bm[1], val); + break; + + case 0x40: + dev->ide_regs[0x40] = val; + via_vt82c586b_ide_handlers(dev); + break; + + default: + dev->ide_regs[addr] = val; + break; + } + break; + + case 2: + /* Read-only addresses */ + if ((addr < 4) || (addr == 5) || (addr == 6) || ((addr >= 8) && (addr < 0xd)) || + ((addr >= 0xe) && (addr < 0x20)) || ((addr >= 0x22) && (addr < 0x3c)) || + ((addr >= 0x3e) && (addr < 0x40)) || ((addr >= 0x42) && (addr < 0x44)) || + ((addr >= 0x46) && (addr < 0xc0)) || (addr >= 0xc2)) + return; + + switch (addr) { + case 0x04: + dev->usb_regs[0x04] = val & 0x97; + break; + case 0x07: + dev->usb_regs[0x07] = val & 0x7f; + break; + + case 0x20: + dev->usb_regs[0x20] = (val & ~0x1f) | 1; + usb_update_io_mapping(dev); + break; + case 0x21: + dev->usb_regs[0x21] = val; + usb_update_io_mapping(dev); + break; + + default: + dev->usb_regs[addr] = val; + break; + } + break; + + case 3: + /* Read-only addresses */ + if ((addr < 0xd) || ((addr >= 0xe && addr < 0x40)) || (addr == 0x43) || (addr == 0x48) || + ((addr >= 0x4a) && (addr < 0x50)) || (addr >= 0x54)) + return; + + switch (addr) { + case 0x41: case 0x49: + dev->power_regs[addr] = val; + power_update_io_mapping(dev); + break; + + default: + dev->power_regs[addr] = val; + break; + } + } +} + + +static void +*via_vt82c586b_init(const device_t *info) +{ + via_vt82c586b_t *dev = (via_vt82c586b_t *) malloc(sizeof(via_vt82c586b_t)); + memset(dev, 0, sizeof(via_vt82c586b_t)); + + pci_add_card(7, via_vt82c586b_read, via_vt82c586b_write, dev); + + dev->bm[0] = device_add_inst(&sff8038i_device, 1); + sff_set_slot(dev->bm[0], 7); + sff_set_irq_mode(dev->bm[0], 0); + sff_set_irq_pin(dev->bm[0], PCI_INTA); + + dev->bm[1] = device_add_inst(&sff8038i_device, 2); + sff_set_slot(dev->bm[1], 7); + sff_set_irq_mode(dev->bm[1], 0); + sff_set_irq_pin(dev->bm[1], PCI_INTA); + + dev->nvr = device_add(&via_nvr_device); + + via_vt82c586b_reset_hard(dev); + + device_add(&port_92_pci_device); + + dma_alias_set(); + + pci_enable_mirq(0); + pci_enable_mirq(1); + pci_enable_mirq(2); + + return dev; +} + +static void +via_vt82c586b_close(void *p) +{ + via_vt82c586b_t *via_vt82c586b = (via_vt82c586b_t *)p; + + free(via_vt82c586b); +} + +const device_t via_vt82c586b_device = +{ + "VIA VT82C586B", + DEVICE_PCI, + 0, + via_vt82c586b_init, + via_vt82c586b_close, + NULL, + NULL, + NULL, + NULL, + NULL +}; diff --git a/src/vt82c586b.h b/src/via_vt82c586b.h similarity index 65% rename from src/vt82c586b.h rename to src/via_vt82c586b.h index cfec19e9f..c2fd06a57 100644 --- a/src/vt82c586b.h +++ b/src/via_vt82c586b.h @@ -1,22 +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. - * - * Emulation of the VIA Apollo MVP3 southbridge - * - * Version: @(#)via_mvp3_sb.c 1.0.22 2018/10/31 - * - * Authors: Sarah Walker, - * Miran Grca, - * Melissa Goad, - * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. - * Copyright 2020 Melissa Goad. - */ - -#if defined(DEV_BRANCH) && defined(USE_SS7) -extern const device_t vt82c586b_device; -#endif \ No newline at end of file +/* + * 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. + * + * Emulation of the VIA Apollo MVP3 southbridge + * + * Version: @(#)via_vt82c586b.c 1.0.0 2020/01/14 + * + * Authors: Sarah Walker, + * Miran Grca, + * Melissa Goad, + * + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2020 Melissa Goad. + */ + +extern const device_t via_vt82c586b_device; diff --git a/src/vt82c586b.c b/src/vt82c586b.c deleted file mode 100644 index f53e1ed61..000000000 --- a/src/vt82c586b.c +++ /dev/null @@ -1,444 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * Emulation of the VIA VT82C586B southbridge - * - * Version: @(#)vt82c586b.c 1.0.22 2018/10/31 - * - * Authors: Sarah Walker, - * Miran Grca, - * Melissa Goad, - * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. - * Copyright 2020 Melissa Goad. - */ - -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include "86box.h" -#include "cdrom/cdrom.h" -#include "cpu/cpu.h" -#include "scsi/scsi_device.h" -#include "scsi/scsi_cdrom.h" -#include "dma.h" -#include "io.h" -#include "device.h" -#include "apm.h" -#include "keyboard.h" -#include "mem.h" -#include "pci.h" -#include "pic.h" -#include "port_92.h" -#include "disk/hdc.h" -#include "disk/hdc_ide.h" -#include "disk/hdc_ide_sff8038i.h" -#include "disk/zip.h" -#include "machine/machine.h" -#include "vt82c586b.h" - -typedef struct -{ - uint8_t pci_isa_regs[256]; - uint8_t ide_regs[256]; - uint8_t usb_regs[256]; - uint8_t power_regs[256]; - sff8038i_t *bm[2]; -} vt82c586b_t; - -static void -vt82c586b_reset_hard(void *priv) -{ - vt82c586b_t *vt82c586b = (vt82c586b_t *) priv; - - uint16_t old_base = (vt82c586b->ide_regs[0x20] & 0xf0) | (vt82c586b->ide_regs[0x21] << 8); - - sff_bus_master_reset(vt82c586b->bm[0], old_base); - sff_bus_master_reset(vt82c586b->bm[1], old_base + 8); - - memset(vt82c586b->pci_isa_regs, 0, 256); - memset(vt82c586b->ide_regs, 0, 256); - memset(vt82c586b->usb_regs, 0, 256); - memset(vt82c586b->power_regs, 0, 256); - - vt82c586b->pci_isa_regs[0x00] = 0x06; vt82c586b->pci_isa_regs[0x01] = 0x11; /*VIA*/ - vt82c586b->pci_isa_regs[0x02] = 0x86; vt82c586b->pci_isa_regs[0x03] = 0x05; /*VT82C586B*/ - vt82c586b->pci_isa_regs[0x04] = 0x0f; - vt82c586b->pci_isa_regs[0x07] = 0x02; - vt82c586b->pci_isa_regs[0x0a] = 0x01; - vt82c586b->pci_isa_regs[0x0b] = 0x06; - vt82c586b->pci_isa_regs[0x0e] = 0x80; - - vt82c586b->pci_isa_regs[0x48] = 0x01; - vt82c586b->pci_isa_regs[0x4a] = 0x04; - vt82c586b->pci_isa_regs[0x4f] = 0x03; - - vt82c586b->pci_isa_regs[0x50] = 0x24; - vt82c586b->pci_isa_regs[0x59] = 0x04; - - //IDE registers - vt82c586b->ide_regs[0x00] = 0x06; vt82c586b->ide_regs[0x01] = 0x11; /*VIA*/ - vt82c586b->ide_regs[0x02] = 0x71; vt82c586b->ide_regs[0x03] = 0x05; /*VT82C586B*/ - vt82c586b->ide_regs[0x04] = 0x80; - vt82c586b->ide_regs[0x06] = 0x80; vt82c586b->ide_regs[0x07] = 0x02; - vt82c586b->ide_regs[0x09] = 0x85; - vt82c586b->ide_regs[0x0a] = 0x01; - vt82c586b->ide_regs[0x0b] = 0x01; - - vt82c586b->ide_regs[0x10] = 0xf0; vt82c586b->ide_regs[0x11] = 0x01; - vt82c586b->ide_regs[0x14] = 0xf4; vt82c586b->ide_regs[0x15] = 0x03; - vt82c586b->ide_regs[0x18] = 0x70; vt82c586b->ide_regs[0x19] = 0x01; - vt82c586b->ide_regs[0x1c] = 0x74; vt82c586b->ide_regs[0x1d] = 0x03; - vt82c586b->ide_regs[0x20] = 0x01; vt82c586b->ide_regs[0x21] = 0xcc; - - vt82c586b->ide_regs[0x3c] = 0x0e; - - vt82c586b->ide_regs[0x40] = 0x08; - vt82c586b->ide_regs[0x41] = 0x02; - vt82c586b->ide_regs[0x42] = 0x09; - vt82c586b->ide_regs[0x43] = 0x3a; - vt82c586b->ide_regs[0x44] = 0x68; - vt82c586b->ide_regs[0x46] = 0xc0; - vt82c586b->ide_regs[0x48] = 0xa8; vt82c586b->ide_regs[0x49] = 0xa8; - vt82c586b->ide_regs[0x4a] = 0xa8; vt82c586b->ide_regs[0x4b] = 0xa8; - vt82c586b->ide_regs[0x4c] = 0xff; - vt82c586b->ide_regs[0x4e] = 0xff; - vt82c586b->ide_regs[0x4f] = 0xff; - vt82c586b->ide_regs[0x50] = 0x03; vt82c586b->ide_regs[0x51] = 0x03; - vt82c586b->ide_regs[0x52] = 0x03; vt82c586b->ide_regs[0x53] = 0x03; - - vt82c586b->ide_regs[0x61] = 0x02; - vt82c586b->ide_regs[0x69] = 0x02; - - vt82c586b->usb_regs[0x00] = 0x06; vt82c586b->usb_regs[0x01] = 0x11; /*VIA*/ - vt82c586b->usb_regs[0x02] = 0x38; vt82c586b->usb_regs[0x03] = 0x30; - vt82c586b->usb_regs[0x04] = 0x00; vt82c586b->usb_regs[0x05] = 0x00; - vt82c586b->usb_regs[0x06] = 0x00; vt82c586b->usb_regs[0x07] = 0x02; - vt82c586b->usb_regs[0x0a] = 0x03; - vt82c586b->usb_regs[0x0b] = 0x0c; - vt82c586b->usb_regs[0x0d] = 0x16; - vt82c586b->usb_regs[0x20] = 0x01; - vt82c586b->usb_regs[0x21] = 0x03; - vt82c586b->usb_regs[0x3d] = 0x04; - - vt82c586b->usb_regs[0x60] = 0x10; - vt82c586b->usb_regs[0xc1] = 0x20; - - vt82c586b->power_regs[0x00] = 0x06; vt82c586b->power_regs[0x01] = 0x11; /*VIA*/ - vt82c586b->power_regs[0x02] = 0x40; vt82c586b->power_regs[0x03] = 0x30; - vt82c586b->power_regs[0x04] = 0x00; vt82c586b->power_regs[0x05] = 0x00; - vt82c586b->power_regs[0x06] = 0x80; vt82c586b->power_regs[0x07] = 0x02; - vt82c586b->power_regs[0x08] = 0x10; /*Production version (3041)*/ - vt82c586b->power_regs[0x48] = 0x01; - - pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); - pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); - pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); - pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); - - pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED); - pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED); - pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED); - - ide_pri_disable(); - ide_sec_disable(); -} - -static void -vt82c586b_bus_master_handlers(vt82c586b_t *dev, uint16_t old_base) -{ - uint16_t base; - - base = (dev->ide_regs[0x20] & 0xf0) | (dev->ide_regs[0x21] << 8); - - sff_bus_master_handlers(dev->bm[0], old_base, base, (dev->ide_regs[0x04] & 1)); - sff_bus_master_handlers(dev->bm[1], old_base + 8, base + 8, (dev->ide_regs[0x04] & 1)); -} - -static uint8_t -vt82c586b_read(int func, int addr, void *priv) -{ - vt82c586b_t *dev = (vt82c586b_t *) priv; - - switch(func) - { - case 0: - { - return dev->pci_isa_regs[addr]; - } - case 1: - { - return dev->ide_regs[addr]; - } - case 2: - { - return dev->usb_regs[addr]; - } - case 3: - { - return dev->power_regs[addr]; - } - default: - { - return 0xff; - } - } -} - -static void -vt82c586b_write(int func, int addr, uint8_t val, void *priv) -{ - vt82c586b_t *dev = (vt82c586b_t *) priv; - uint16_t old_base; - - if(func > 3) return; - - old_base = (dev->ide_regs[0x20] & 0xf0) | (dev->ide_regs[0x21] << 8); - - switch(func) - { - case 0: //PCI-ISA bridge - { - /*Read-only addresses*/ - if ((addr < 4) || (addr == 5) || (addr == 6) - || (addr >= 8 && addr < 0x40) - || (addr == 0x49) - || (addr == 0x4b) - || (addr >= 0x51 && addr < 0x54) - || (addr >= 0x5d && addr < 0x60) - || (addr >= 0x68 && addr < 0x6a) - || (addr >= 0x71)) - return; - - switch(addr) - { - case 0x04: - dev->pci_isa_regs[0x04] = (val & 8) | 7; - break; - case 0x06: - dev->pci_isa_regs[0x06] &= ~(val & 0xb0); - break; - - case 0x47: - if((val & 0x81) == 0x81) resetx86(); - if(val & 0x20) pci_elcr_set_enabled(1); - else pci_elcr_set_enabled(0); - dev->pci_isa_regs[0x47] = val & 0xfe; - break; - - case 0x54: - if(val & 8) pci_set_irq_level(PCI_INTA, 0); - else pci_set_irq_level(PCI_INTA, 1); - if(val & 4) pci_set_irq_level(PCI_INTB, 0); - else pci_set_irq_level(PCI_INTB, 1); - if(val & 2) pci_set_irq_level(PCI_INTC, 0); - else pci_set_irq_level(PCI_INTC, 1); - if(val & 1) pci_set_irq_level(PCI_INTD, 0); - else pci_set_irq_level(PCI_INTD, 1); - break; - - case 0x55: - if(!(val & 0xf0)) pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); - else pci_set_irq_routing(PCI_INTD, val >> 4); - - if(!(val & 0x0f)) pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED); - else pci_set_mirq_routing(PCI_MIRQ0, val & 0xf); - dev->pci_isa_regs[0x55] = val; - break; - - case 0x56: - if(!(val & 0xf0)) pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); - else pci_set_irq_routing(PCI_INTA, val >> 4); - - if(!(val & 0x0f)) pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); - else pci_set_irq_routing(PCI_INTB, val & 0xf); - dev->pci_isa_regs[0x56] = val; - break; - - case 0x57: - if(!(val & 0xf0)) pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); - else pci_set_irq_routing(PCI_INTC, val >> 4); - - if(!(val & 0x0f)) pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED); - else pci_set_mirq_routing(PCI_MIRQ1, val & 0xf); - dev->pci_isa_regs[0x57] = val; - break; - - case 0x58: - if(!(val & 0x0f)) pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED); - else pci_set_mirq_routing(PCI_MIRQ2, val & 0xf); - dev->pci_isa_regs[0x58] = val; - } - break; - } - case 1: /*IDE regs*/ - { - /*Read-only addresses*/ - if ((addr < 4) || (addr == 5) || (addr == 8) - || (addr >= 0xa && addr < 0x0d) - || (addr >= 0x0e && addr < 0x20) - || (addr >= 0x22 && addr < 0x3c) - || (addr >= 0x3d && addr < 0x40) - || (addr >= 0x54 && addr < 0x60) - || (addr >= 0x52 && addr < 0x68) - || (addr >= 0x62)) - return; - - switch(addr) - { - case 0x04: - { - uint16_t base = (dev->ide_regs[0x20] & 0xf0) | (dev->ide_regs[0x21] << 8); - ide_pri_disable(); - ide_sec_disable(); - if(val & PCI_COMMAND_IO) - { - if(dev->ide_regs[0x40] & 0x02) ide_pri_enable(); - if(dev->ide_regs[0x40] & 0x01) ide_sec_enable(); - } - vt82c586b_bus_master_handlers(dev, base); - dev->ide_regs[0x04] = val & 0x85; - break; - } - case 0x06: - dev->ide_regs[0x06] &= ~(val & 0xb0); - break; - - case 0x09: - dev->ide_regs[0x09] = (dev->pci_isa_regs[0x09] & ~0x70) | 0x8a; - break; - - case 0x20: - { - dev->ide_regs[0x20] = (val & 0xf0) | 1; - vt82c586b_bus_master_handlers(dev, old_base); - break; - } - - case 0x21: - { - dev->ide_regs[0x21] = val; - vt82c586b_bus_master_handlers(dev, old_base); - break; - } - - case 0x40: - { - dev->ide_regs[0x40] = val; - ide_pri_disable(); - ide_sec_disable(); - if(val & PCI_COMMAND_IO) - { - if(dev->ide_regs[0x40] & 0x02) ide_pri_enable(); - if(dev->ide_regs[0x40] & 0x01) ide_sec_enable(); - } - break; - } - - default: - dev->ide_regs[addr] = val; - break; - } - break; - } - case 2: - { - /*Read-only addresses*/ - if ((addr < 4) || (addr == 5) || (addr == 6) - || (addr >= 8 && addr < 0xd) - || (addr >= 0xe && addr < 0x20) - || (addr >= 0x22 && addr < 0x3c) - || (addr >= 0x3e && addr < 0x40) - || (addr >= 0x42 && addr < 0x44) - || (addr >= 0x46 && addr < 0xc0) - || (addr >= 0xc2)) - return; - - switch(addr) - { - case 0x04: - dev->usb_regs[0x04] = val & 0x97; - break; - case 0x07: - dev->usb_regs[0x07] = val & 0x7f; - break; - - case 0x20: - dev->usb_regs[0x20] = (val & ~0x1f) | 1; - break; - - default: - dev->usb_regs[addr] = val; - break; - } - break; - } - case 3: - { - /*Read-only addresses*/ - if ((addr < 0xd) || (addr >= 0xe && addr < 0x40) - || (addr == 0x43) - || (addr == 0x48) - || (addr >= 0x4a && addr < 0x50) - || (addr >= 0x54)) - return; - - dev->power_regs[addr] = val; - break; - } - } -} - -static void -*vt82c586b_init(const device_t *info) -{ - vt82c586b_t *vt82c586b = (vt82c586b_t *) malloc(sizeof(vt82c586b_t)); - memset(vt82c586b, 0, sizeof(vt82c586b_t)); - - pci_add_card(7, vt82c586b_read, vt82c586b_write, vt82c586b); - - vt82c586b->bm[0] = device_add_inst(&sff8038i_device, 1); - vt82c586b->bm[1] = device_add_inst(&sff8038i_device, 2); - - vt82c586b_reset_hard(vt82c586b); - - device_add(&port_92_pci_device); - - dma_alias_set(); - - pci_enable_mirq(0); - pci_enable_mirq(1); - pci_enable_mirq(2); - - return vt82c586b; -} - -static void -vt82c586b_close(void *p) -{ - vt82c586b_t *vt82c586b = (vt82c586b_t *)p; - - free(vt82c586b); -} - -const device_t vt82c586b_device = -{ - "VIA VT82C586B", - DEVICE_PCI, - 0, - vt82c586b_init, - vt82c586b_close, - NULL, - NULL, - NULL, - NULL, - NULL -}; \ No newline at end of file diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 901ac9215..a2f5b3329 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -8,7 +8,7 @@ # # Makefile for Win32 (MinGW32) environment. # -# Version: @(#)Makefile.mingw 1.0.140 2019/12/21 +# Version: @(#)Makefile.mingw 1.0.141 2020/01/14 # # Authors: Miran Grca, # Fred N. van Kempen, @@ -543,7 +543,7 @@ CXXFLAGS := $(CFLAGS) ######################################################################### MAINOBJ := pc.o config.o random.o timer.o io.o apm_new.o dma.o nmi.o \ pic.o pit.o port_92.o ppi.o pci.o mca.o mcr.o mem.o \ - rom.o device.o nvr.o nvr_at.o nvr_ps2.o $(VNCOBJ) $(RDPOBJ) + rom.o device.o nvr.o nvr_at.o nvr_ps2.o sst_flash.o via_vt82c586b.o $(VNCOBJ) $(RDPOBJ) INTELOBJ := intel_flash.o \ intel_sio.o intel_piix.o @@ -557,7 +557,7 @@ CPUOBJ := cpu.o cpu_table.o \ CHIPSETOBJ := acc2168.o acer_m3a.o ali1429.o headland.o \ intel_4x0.o neat.o opti495.o scat.o \ sis_85c471.o sis_85c496.o \ - wd76c10.o + via_mvp3.o wd76c10.o MCHOBJ := machine.o machine_table.o \ m_xt.o m_xt_compaq.o \ diff --git a/src/win/Makefile_ndr.mingw b/src/win/Makefile_ndr.mingw index 10d6aa481..fee58bd0c 100644 --- a/src/win/Makefile_ndr.mingw +++ b/src/win/Makefile_ndr.mingw @@ -8,7 +8,7 @@ # # Makefile for Win32 (MinGW32) environment. # -# Version: @(#)Makefile.mingw 1.0.140 2019/12/21 +# Version: @(#)Makefile.mingw 1.0.141 2020/01/14 # # Authors: Miran Grca, # Fred N. van Kempen, @@ -74,9 +74,6 @@ ifeq ($(DEV_BUILD), y) ifndef PS2M70T4 PS2M70T4 := y endif - ifndef SS7 - SS7 := y - endif ifndef TI TI := y endif @@ -141,9 +138,6 @@ else ifndef PS2M70T4 PS2M70T4 := n endif - ifndef SS7 - SS7 := n - endif ifndef TI TI := n endif @@ -506,11 +500,6 @@ ifeq ($(PS2M70T4), y) OPTS += -DUSE_PS2M70T4 endif -ifeq ($(SS7),y) -OPTS += -DUSE_SS7 -DEVBROBJ += via_mvp3.o vt82c586b.o sst_flash.o -endif - ifeq ($(TI), y) OPTS += -DUSE_TI endif @@ -560,7 +549,7 @@ CXXFLAGS := $(CFLAGS) ######################################################################### MAINOBJ := pc.o config.o random.o timer.o io.o apm_new.o dma.o nmi.o \ pic.o pit.o port_92.o ppi.o pci.o mca.o mcr.o mem_new.o \ - rom.o device.o nvr.o nvr_at.o nvr_ps2.o $(VNCOBJ) $(RDPOBJ) + rom.o device.o nvr.o nvr_at.o nvr_ps2.o sst_flash.o via_vt82c586b.o $(VNCOBJ) $(RDPOBJ) INTELOBJ := intel_flash.o \ intel_sio.o intel_piix.o @@ -574,7 +563,7 @@ CPUOBJ := cpu.o cpu_table.o \ CHIPSETOBJ := acc2168.o acer_m3a.o ali1429.o headland.o \ intel_4x0.o neat.o opti495.o scat.o \ sis_85c471.o sis_85c496.o \ - wd76c10.o + via_mvp3.o wd76c10.o MCHOBJ := machine.o machine_table_new.o \ m_xt.o m_xt_compaq.o \ From f5bc638fec96bd89ac5588d99237ed534fa29d7b Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 02:52:21 +0100 Subject: [PATCH 057/177] Fixed a bug that was causing the VIA chipset to put ACPI onto the wrong base address. --- src/via_vt82c586b.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/via_vt82c586b.c b/src/via_vt82c586b.c index 501175d23..936f8704c 100644 --- a/src/via_vt82c586b.c +++ b/src/via_vt82c586b.c @@ -345,7 +345,7 @@ power_update_io_mapping(via_vt82c586b_t *dev) if (dev->power.io_base != 0x0000) io_removehandler(dev->power.io_base, 0x100, power_reg_read, NULL, NULL, power_reg_write, NULL, NULL, dev); - dev->power.io_base = dev->power_regs[0x41] | (dev->power_regs[0x49] << 8); + dev->power.io_base = (dev->power_regs[0x49] << 8); if ((dev->power_regs[0x41] & ACPI_IO_ENABLE) && (dev->power.io_base != 0x0000)) io_sethandler(dev->power.io_base, 0x100, power_reg_read, NULL, NULL, power_reg_write, NULL, NULL, dev); @@ -565,7 +565,7 @@ via_vt82c586b_write(int func, int addr, uint8_t val, void *priv) case 3: /* Read-only addresses */ - if ((addr < 0xd) || ((addr >= 0xe && addr < 0x40)) || (addr == 0x43) || (addr == 0x48) || + if ((addr < 0xd) || ((addr >= 0xe) && (addr < 0x40)) || (addr == 0x43) || (addr == 0x48) || ((addr >= 0x4a) && (addr < 0x50)) || (addr >= 0x54)) return; From d9461a3fcec9f1af373a0b978706ab70764903de Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 03:00:35 +0100 Subject: [PATCH 058/177] Moved PCI IDE Bus Master slot, etc. initialization from reset() to init(), should fix them being reset to invalid values on the VIA chipset. --- src/disk/hdc_ide_sff8038i.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/disk/hdc_ide_sff8038i.c b/src/disk/hdc_ide_sff8038i.c index 96d6bb0fc..1e6fce712 100644 --- a/src/disk/hdc_ide_sff8038i.c +++ b/src/disk/hdc_ide_sff8038i.c @@ -405,9 +405,6 @@ sff_bus_master_reset(sff8038i_t *dev, uint16_t old_base) dev->addr = 0x00000000; dev->ptr0 = 0x00; dev->count = dev->eot = 0x00000000; - dev->slot = 7; - dev->irq_mode = 2; - dev->irq_pin = PCI_INTA; ide_pri_disable(); ide_sec_disable(); @@ -478,6 +475,10 @@ static void ide_set_bus_master(next_id, sff_bus_master_dma, sff_bus_master_set_irq, dev); + dev->slot = 7; + dev->irq_mode = 2; + dev->irq_pin = PCI_INTA; + next_id++; return dev; From 33ab4036359d9376efbd895448e5559ebc51dfe6 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 19:06:34 +0100 Subject: [PATCH 059/177] Sanitized the VIA southbridge code a bit. --- src/via_vt82c586b.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/via_vt82c586b.c b/src/via_vt82c586b.c index 936f8704c..904438ba9 100644 --- a/src/via_vt82c586b.c +++ b/src/via_vt82c586b.c @@ -368,7 +368,7 @@ via_vt82c586b_write(int func, int addr, uint8_t val, void *priv) switch(func) { case 0: /* PCI-ISA bridge */ /* Read-only addresses */ - if ((addr < 4) || (addr == 5) || (addr == 6) || ((addr >= 8) && (addr < 0x40)) || + if ((addr < 4) || (addr == 5) || ((addr >= 8) && (addr < 0x40)) || (addr == 0x49) || (addr == 0x4b) || ((addr >= 0x51) && (addr < 0x54)) || ((addr >= 0x5d) && (addr < 0x60)) || ((addr >= 0x68) && (addr < 0x6a)) || (addr >= 0x73)) return; @@ -423,7 +423,7 @@ via_vt82c586b_write(int func, int addr, uint8_t val, void *priv) break; case 0x60: case 0x62: case 0x64: case 0x66: - case 0x68: case 0x6a: case 0x6c: case 0x6e: + case 0x6a: case 0x6c: case 0x6e: c = (addr & 0x0e) >> 1; dma[c].ab = (dma[c].ab & 0xffffff0f) | (val & 0xf0); dma[c].ac = (dma[c].ac & 0xffffff0f) | (val & 0xf0); @@ -433,7 +433,7 @@ via_vt82c586b_write(int func, int addr, uint8_t val, void *priv) dma_e &= ~(1 << c); break; case 0x61: case 0x63: case 0x65: case 0x67: - case 0x69: case 0x6b: case 0x6d: case 0x6f: + case 0x6b: case 0x6d: case 0x6f: c = (addr & 0x0e) >> 1; dma[c].ab = (dma[c].ab & 0xffff00ff) | (val << 8); dma[c].ac = (dma[c].ac & 0xffff00ff) | (val << 8); From d97a1f9c17fd808f8a00aca28cb00e34a4925343 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 19:09:04 +0100 Subject: [PATCH 060/177] Fixed some minor bugs in config.c. --- src/config.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/config.c b/src/config.c index 2b9026989..1b1ce3a23 100644 --- a/src/config.c +++ b/src/config.c @@ -2096,7 +2096,7 @@ config_set_int(char *head, char *name, int val) ent = create_entry(section, name); sprintf(ent->data, "%i", val); - mbstowcs(ent->wdata, ent->data, sizeof_w(ent->wdata)); + mbstowcs(ent->wdata, ent->data, sizeof(ent->wdata)); } @@ -2115,7 +2115,7 @@ config_set_hex16(char *head, char *name, int val) ent = create_entry(section, name); sprintf(ent->data, "%04X", val); - mbstowcs(ent->wdata, ent->data, sizeof_w(ent->wdata)); + mbstowcs(ent->wdata, ent->data, sizeof(ent->wdata)); } @@ -2173,7 +2173,7 @@ config_set_string(char *head, char *name, char *val) ent = create_entry(section, name); memcpy(ent->data, val, sizeof(ent->data)); - mbstowcs(ent->wdata, ent->data, sizeof_w(ent->wdata)); + mbstowcs(ent->wdata, ent->data, sizeof(ent->wdata)); } From 520e234d5a9905467bcbc8a0f2b55d3e0a49e51f Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 19:10:13 +0100 Subject: [PATCH 061/177] Fixed a bug in scsi/scsi_cdrom.c. --- src/scsi/scsi_cdrom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index abfd8a6ef..3ea4bd169 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -1891,7 +1891,7 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) } gesn_event_header->len = used_len - sizeof(*gesn_event_header); - memcpy(dev->buffer, gesn_event_header, 4); + memmove(dev->buffer, gesn_event_header, 4); scsi_cdrom_set_buf_len(dev, BufLen, &used_len); From 1b7da93aa31d3fff58b6ac561700550f242e5ec4 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 19:11:40 +0100 Subject: [PATCH 062/177] Fixed a minor bug in the MPU-401 code. --- src/sound/snd_mpu401.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sound/snd_mpu401.c b/src/sound/snd_mpu401.c index 1ffc067f1..4fb9bea30 100644 --- a/src/sound/snd_mpu401.c +++ b/src/sound/snd_mpu401.c @@ -459,7 +459,7 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) mpu->filter.midi_thru = 0; for (i = 0; i < 16; i++) { mpu->inputref[i].on = 0; - for (j = 0; i < 4; j++) + for (j = 0; j < 4; j++) mpu->inputref[i].key[j] = 0; } break; From c7cfc06285ce0b71cf31dd917663b10e7fe4ac89 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 19:18:18 +0100 Subject: [PATCH 063/177] Added a NULL pointer check to zip_bus_speed(). --- src/disk/zip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/disk/zip.c b/src/disk/zip.c index 60c775810..5e0b63c77 100644 --- a/src/disk/zip.c +++ b/src/disk/zip.c @@ -859,7 +859,7 @@ zip_bus_speed(zip_t *dev) { double ret = -1.0; - if (dev->drv->bus_type == ZIP_BUS_SCSI) { + if (dev && dev->drv && dev->drv->bus_type == ZIP_BUS_SCSI) { dev->callback = -1.0; /* Speed depends on SCSI controller */ return 0.0; } else { From fea96d6b679e2e9356681af494b69923bc3de093 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 19:26:27 +0100 Subject: [PATCH 064/177] Fixed some bugs in the CD-ROM image backend code. --- src/cdrom/cdrom_image_backend.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/cdrom/cdrom_image_backend.c b/src/cdrom/cdrom_image_backend.c index f39dfe01f..c0bebd9bb 100644 --- a/src/cdrom/cdrom_image_backend.c +++ b/src/cdrom/cdrom_image_backend.c @@ -141,7 +141,10 @@ bin_init(const wchar_t *filename, int *error) } memset(tf->fn, 0x00, sizeof(tf->fn)); - wcscpy(tf->fn, filename); + if (wcslen(tf->fn) > 260) + wcsncpy(tf->fn, filename, 260); + else + wcscpy(tf->fn, filename); tf->file = plat_fopen64(tf->fn, L"rb"); cdrom_image_backend_log("CDROM: binary_open(%ls) = %08lx\n", tf->fn, tf->file); @@ -682,6 +685,10 @@ cdi_add_track(cd_img_t *cdi, track_t *cur, uint64_t *shift, uint64_t prestart, u if ((cdi->tracks != NULL) && (cdi->tracks_num != 0)) prev = &cdi->tracks[cdi->tracks_num - 1]; + else if ((cdi->tracks != NULL) && (cdi->tracks_num == 0)) { + fatal("Non-NULL cdi->tracks with tracks_num being 0\n"); + return 0; + } /* First track (track number must be 1). */ if (cdi->tracks_num == 0) { From 1861d8cb0dc4c1f17c9b6c04af58a371746d0207 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 19:30:33 +0100 Subject: [PATCH 065/177] Changed the fatal condition in the CD-ROM image backend code. --- src/cdrom/cdrom_image_backend.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cdrom/cdrom_image_backend.c b/src/cdrom/cdrom_image_backend.c index c0bebd9bb..1cb210825 100644 --- a/src/cdrom/cdrom_image_backend.c +++ b/src/cdrom/cdrom_image_backend.c @@ -685,8 +685,8 @@ cdi_add_track(cd_img_t *cdi, track_t *cur, uint64_t *shift, uint64_t prestart, u if ((cdi->tracks != NULL) && (cdi->tracks_num != 0)) prev = &cdi->tracks[cdi->tracks_num - 1]; - else if ((cdi->tracks != NULL) && (cdi->tracks_num == 0)) { - fatal("Non-NULL cdi->tracks with tracks_num being 0\n"); + else if ((cdi->tracks == NULL) && (cdi->tracks_num != 0)) { + fatal("NULL cdi->tracks with non-zero cdi->tracks_num\n"); return 0; } From c0946552bce0ab7bb18b15eff21ac7199e71178c Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 19:33:17 +0100 Subject: [PATCH 066/177] Fixed a string copy in the SST flash code. --- src/sst_flash.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/sst_flash.c b/src/sst_flash.c index 7dfc26f1b..5f0fc27f8 100644 --- a/src/sst_flash.c +++ b/src/sst_flash.c @@ -249,7 +249,10 @@ sst_39sf010_init(const device_t *info) wchar_t *flash_name = (wchar_t *)malloc(l*sizeof(wchar_t)); swprintf(flash_name, l, L"%ls.bin", machine_name); - wcscpy(flash_path, flash_name); + if (wcslen(flash_name) <= 1024) + wcscpy(flash_path, flash_name); + else + wcsncpy(flash_path, flash_name, 1024); mem_mapping_disable(&bios_mapping); mem_mapping_disable(&bios_high_mapping); @@ -298,4 +301,4 @@ const device_t sst_flash_39sf010_device = sst_39sf010_close, NULL, NULL, NULL, NULL, NULL -}; \ No newline at end of file +}; From c09acf597da7ecf50dd05017384ac766fd4157e4 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 19:42:11 +0100 Subject: [PATCH 067/177] Fixed the size of the bitmap_t.line array, fixes out-of-bounds acceses. --- src/video/video.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/video.h b/src/video/video.h index 427b0e5c9..a82993cfd 100644 --- a/src/video/video.h +++ b/src/video/video.h @@ -65,7 +65,7 @@ typedef struct { typedef struct { int w, h; uint32_t *dat; - uint32_t *line[2048]; + uint32_t *line[2112]; } bitmap_t; typedef struct { From c3a440e19ba295a3db9d5b5c2f1816a856111d1e Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 19:44:10 +0100 Subject: [PATCH 068/177] Fixed a hard-coding of the hard disk bus speed that should not have been there. --- src/disk/hdc_ide.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index 6dba893c2..d6a52702f 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -249,8 +249,6 @@ ide_get_period(ide_t *ide, int size) break; } - period = (10.0 / 3.0); - period = (1.0 / period); /* get us for 1 byte */ return period * ((double) size); /* multiply by bytes to get period for the entire transfer */ } From ad47659fd6d476f7d3e0fc214308ac3f985bfee1 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 19:46:02 +0100 Subject: [PATCH 069/177] The CD-ROM image backed code no longer returns the pointer of a stack variable. --- src/cdrom/cdrom_image_backend.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/cdrom/cdrom_image_backend.c b/src/cdrom/cdrom_image_backend.c index 1cb210825..437c94a87 100644 --- a/src/cdrom/cdrom_image_backend.c +++ b/src/cdrom/cdrom_image_backend.c @@ -47,6 +47,9 @@ #define CROSS_LEN 512 +static char temp_keyword[1024]; + + #ifdef ENABLE_CDROM_IMAGE_BACKEND_LOG int cdrom_image_backend_do_log = ENABLE_CDROM_IMAGE_BACKEND_LOG; @@ -622,12 +625,11 @@ cdi_cue_get_buffer(char *str, char **line, int up) static int cdi_cue_get_keyword(char **dest, char **line) { - char temp[1024]; int success; - success = cdi_cue_get_buffer(temp, line, 1); + success = cdi_cue_get_buffer(temp_keyword, line, 1); if (success) - *dest = temp; + *dest = temp_keyword; return success; } From 69b84765ba044fdbf5ea72da3b39f4fa00b6fd0e Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 19:49:14 +0100 Subject: [PATCH 070/177] Made the buffer position of the PostScript printer 32-bit as it should have been. --- src/printer/prt_ps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/printer/prt_ps.c b/src/printer/prt_ps.c index effb2d07e..0c75d914e 100644 --- a/src/printer/prt_ps.c +++ b/src/printer/prt_ps.c @@ -86,7 +86,7 @@ typedef struct wchar_t filename[260]; char buffer[POSTSCRIPT_BUFFER_LENGTH]; - uint16_t buffer_pos; + uint32_t buffer_pos; } ps_t; static void From 93111b3a24989bc5de1fee59f758b3ee2f9154f2 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 19:52:13 +0100 Subject: [PATCH 071/177] Removed an always true comparison from the NCR 5380 code. --- src/scsi/scsi_ncr5380.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scsi/scsi_ncr5380.c b/src/scsi/scsi_ncr5380.c index a2991cce8..c361c2d14 100644 --- a/src/scsi/scsi_ncr5380.c +++ b/src/scsi/scsi_ncr5380.c @@ -430,7 +430,7 @@ ncr_bus_update(void *priv, int bus) ncr_log("Command pos=%i, output data=%02x\n", ncr->command_pos, BUS_GETDATA(bus)); if (ncr->command_pos == cmd_len[(ncr->command[0] >> 5) & 7]) { - if (ncr->msglun >= 0 && ncr->is_msgout) { + if (ncr->is_msgout) { ncr->is_msgout = 0; ncr->command[1] &= ~(0x80 | 0x40 | 0x20); ncr->command[1] |= ncr->msglun << 5; From 2d46b870885f8736e9421da12b5db78e01bfeddc Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 20:04:47 +0100 Subject: [PATCH 072/177] Removed a dead while block from the PCnet code. --- src/network/net_pcnet.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/network/net_pcnet.c b/src/network/net_pcnet.c index fa5cab9d6..3b53da687 100644 --- a/src/network/net_pcnet.c +++ b/src/network/net_pcnet.c @@ -1263,22 +1263,18 @@ pcnetReceiveNoSync(void *priv, uint8_t *buf, int size) /* In loopback mode, Runt Packed Accept is always enabled internally; * don't do any padding because guest may be looping back very short packets. */ - if (!CSR_LOOP(dev)) - while (size < 60) - src[size++] = 0; + uint32_t fcs = UINT32_MAX; + uint8_t *p = src; - uint32_t fcs = UINT32_MAX; - uint8_t *p = src; + while (p != &src[size]) + CRC(fcs, *p++); - while (p != &src[size]) - CRC(fcs, *p++); + /* FCS at the end of the packet */ + ((uint32_t *)&src[size])[0] = htonl(fcs); + size += 4; + } - /* FCS at the end of the packet */ - ((uint32_t *)&src[size])[0] = htonl(fcs); - size += 4; - } - - cbPacket = size; + cbPacket = size; pcnetRmdLoad(dev, &rmd, PHYSADDR(dev, crda), 0); /* if (!CSR_LAPPEN(dev)) */ From 8d1daf602f649270ea7a6ce1f205123bccdf38a0 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 20:06:51 +0100 Subject: [PATCH 073/177] Changed the buffer position on the PostScript printer to size_t. --- src/printer/prt_ps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/printer/prt_ps.c b/src/printer/prt_ps.c index 0c75d914e..4a14f4378 100644 --- a/src/printer/prt_ps.c +++ b/src/printer/prt_ps.c @@ -86,7 +86,7 @@ typedef struct wchar_t filename[260]; char buffer[POSTSCRIPT_BUFFER_LENGTH]; - uint32_t buffer_pos; + size_t buffer_pos; } ps_t; static void From f04983f1dd0212d729553ed4cd39038ca2b63952 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 20:08:23 +0100 Subject: [PATCH 074/177] Added some sanity check to the CD-ROM bus speed code. --- src/disk/zip.c | 2 +- src/scsi/scsi_cdrom.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/disk/zip.c b/src/disk/zip.c index 5e0b63c77..ccc2fd1c2 100644 --- a/src/disk/zip.c +++ b/src/disk/zip.c @@ -859,7 +859,7 @@ zip_bus_speed(zip_t *dev) { double ret = -1.0; - if (dev && dev->drv && dev->drv->bus_type == ZIP_BUS_SCSI) { + if (dev && dev->drv && (dev->drv->bus_type == ZIP_BUS_SCSI)) { dev->callback = -1.0; /* Speed depends on SCSI controller */ return 0.0; } else { diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index 3ea4bd169..72d3b2e2a 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -606,7 +606,7 @@ scsi_cdrom_bus_speed(scsi_cdrom_t *dev) { double ret = -1.0; - if (dev->drv->bus_type == CDROM_BUS_SCSI) { + if (dev && dev->drv && (dev->drv->bus_type == CDROM_BUS_SCSI)) { dev->callback = -1.0; /* Speed depends on SCSI controller */ return 0.0; } else { From a0216072288cd2fe774d6996821b6366c741db79 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 20:10:01 +0100 Subject: [PATCH 075/177] Fixed a bug in the CD-ROM image backend code. --- src/cdrom/cdrom_image_backend.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cdrom/cdrom_image_backend.c b/src/cdrom/cdrom_image_backend.c index 437c94a87..b5c770b29 100644 --- a/src/cdrom/cdrom_image_backend.c +++ b/src/cdrom/cdrom_image_backend.c @@ -888,6 +888,8 @@ cdi_load_cue(cd_img_t *cdi, const wchar_t *cuefile) success = cdi_add_track(cdi, &trk, &shift, prestart, &total_pregap, cur_pregap); else success = 1; + if (!success) + break; can_add_track = 0; memset(ansi, 0, MAX_FILENAME_LENGTH * sizeof(char)); From cce388cee9c68cede964cd2a68fa1697ada921fd Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 20:14:08 +0100 Subject: [PATCH 076/177] Added a anity check to the Discord support code. --- src/win/win_discord.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/win/win_discord.c b/src/win/win_discord.c index b402f10e8..4a2cb3e63 100644 --- a/src/win/win_discord.c +++ b/src/win/win_discord.c @@ -74,6 +74,7 @@ discord_update_activity(int paused) struct DiscordActivity activity; wchar_t config_name_w[1024]; char config_name[128]; + char *temp; if(discord_activities == NULL) return; @@ -90,7 +91,11 @@ discord_update_activity(int paused) } else { - strcpy(activity.details, strchr(machine_getname(), ']') + 2); + temp = strchr(machine_getname(), ']') + 2; + if (strlen(temp) <= 128) + strcpy(activity.details, temp); + else + strncpy(activity.details, temp, 128); strcpy(activity.state, machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].name); } From 0139c44b7d80af7a67081936f10876b0280a8fd0 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 20:43:04 +0100 Subject: [PATCH 077/177] Removed an obsolete return with error in the CD-ROM image backend code. --- src/cdrom/cdrom_image_backend.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/cdrom/cdrom_image_backend.c b/src/cdrom/cdrom_image_backend.c index b5c770b29..9170bfc76 100644 --- a/src/cdrom/cdrom_image_backend.c +++ b/src/cdrom/cdrom_image_backend.c @@ -336,8 +336,7 @@ cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector) trk = &cdi->tracks[track]; track_is_raw = ((trk->sector_size == RAW_SECTOR_SIZE) || (trk->sector_size == 2448)); - if (raw && !track_is_raw) - return 0; + seek = trk->skip + ((sect - trk->start) * trk->sector_size); if (track_is_raw) From 04247f266499c430d283449537c17a803022d46b Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 20:45:20 +0100 Subject: [PATCH 078/177] The CD-ROM image code function to check if a track is audio now simply returns with a false condition if the track number obtained from the sector is -1. --- src/cdrom/cdrom_image.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/cdrom/cdrom_image.c b/src/cdrom/cdrom_image.c index 34a2dcc29..0b803eef0 100644 --- a/src/cdrom/cdrom_image.c +++ b/src/cdrom/cdrom_image.c @@ -140,7 +140,7 @@ image_is_track_audio(cdrom_t *dev, uint32_t pos, int ismsf) uint8_t attr; TMSF tmsf; int m, s, f; - int number; + int number, track; if (!img || (dev->cd_status == CD_STATUS_DATA_ONLY)) return 0; @@ -153,9 +153,13 @@ image_is_track_audio(cdrom_t *dev, uint32_t pos, int ismsf) } /* GetTrack requires LBA. */ - cdi_get_audio_track_info(img, 0, cdi_get_track(img, pos), &number, &tmsf, &attr); - - return attr == AUDIO_TRACK; + track = cdi_get_track(img, pos); + if (track == -1) + return 0; + else { + cdi_get_audio_track_info(img, 0, cdi_get_track(img, pos), &number, &tmsf, &attr); + return attr == AUDIO_TRACK; + } } From 30a8e248fbfa8421523b4c336823fe02e4e9ead9 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 20:46:43 +0100 Subject: [PATCH 079/177] Removed a dead code block and redundant if check from the JSON floppy image code. --- src/floppy/fdd_json.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/floppy/fdd_json.c b/src/floppy/fdd_json.c index d194b811d..cfc0e43e3 100644 --- a/src/floppy/fdd_json.c +++ b/src/floppy/fdd_json.c @@ -438,13 +438,9 @@ json_seek(int drive, int track) pos = d86f_prepare_pretrack(drive, side, 0); for (sector=0; sectorspt[track][side]; sector++) { - if (interleave_type == 0) { - rsec = dev->sects[track][side][sector].sector; - asec = sector; - } else { - rsec = fdd_dmf_r[sector]; - asec = dev->interleave_ordered[rsec][side]; - } + rsec = dev->sects[track][side][sector].sector; + asec = sector; + id[0] = track; id[1] = side; id[2] = rsec; From 70ccf03f2d571ddfd64c9048983603a9fab34893 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 20:49:01 +0100 Subject: [PATCH 080/177] The CD-ROM image code now returns with error if a seek has failed. --- src/cdrom/cdrom_image_backend.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/cdrom/cdrom_image_backend.c b/src/cdrom/cdrom_image_backend.c index 9170bfc76..de6f83f12 100644 --- a/src/cdrom/cdrom_image_backend.c +++ b/src/cdrom/cdrom_image_backend.c @@ -82,11 +82,16 @@ bin_read(void *p, uint8_t *buffer, uint64_t seek, size_t count) if (tf->file == NULL) return 0; - fseeko64(tf->file, seek, SEEK_SET); + if (fseeko64(tf->file, seek, SEEK_SET) == -1) { +#ifdef ENABLE_cdrom_image_backend_log + cdrom_image_backend_log("CDROM: binary_read failed during seek!\n"); +#endif + return 0; + } if (fread(buffer, count, 1, tf->file) != 1) { #ifdef ENABLE_cdrom_image_backend_log - cdrom_image_backend_log("CDROM: binary_read failed!\n"); + cdrom_image_backend_log("CDROM: binary_read failed during read!\n"); #endif return 0; } From 0371dc96647f594b403557bd85298a934f110976 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 20:51:06 +0100 Subject: [PATCH 081/177] The OAK OTi graphic card code no longer loads the ROM if the ROM file name pointer is NULL. --- src/video/vid_oak_oti.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/video/vid_oak_oti.c b/src/video/vid_oak_oti.c index 467d2a67c..2addd8b32 100644 --- a/src/video/vid_oak_oti.c +++ b/src/video/vid_oak_oti.c @@ -372,8 +372,10 @@ oti_init(const device_t *info) break; } - rom_init(&oti->bios_rom, romfn, - 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + if (romfn != NULL) { + rom_init(&oti->bios_rom, romfn, + 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + } oti->vram_mask = (oti->vram_size << 10) - 1; From 989ee3b138d69e9180570805267ef56dc8da2754 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 20:52:02 +0100 Subject: [PATCH 082/177] Added a sanity check to config.c. --- src/config.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/config.c b/src/config.c index 1b1ce3a23..a3a069cc7 100644 --- a/src/config.c +++ b/src/config.c @@ -707,7 +707,10 @@ load_network(void) strcpy(network_host, "none"); } else { - strcpy(network_host, p); + if (strlen(p) <= 522) + strcpy(network_host, p); + else + strncpy(network_host, p, 522); } } else strcpy(network_host, "none"); From f2beb0bc56fa574ef2252b781aa8236dc661cb67 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 20:53:39 +0100 Subject: [PATCH 083/177] Added a sanity check to the FDI2RAW code. --- src/floppy/fdi2raw.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/floppy/fdi2raw.c b/src/floppy/fdi2raw.c index b42ca2f1d..ffb3c3a53 100644 --- a/src/floppy/fdi2raw.c +++ b/src/floppy/fdi2raw.c @@ -2029,6 +2029,10 @@ FDI *fdi2raw_header(FILE *f) memset (fdi, 0, sizeof (FDI)); fdi->file = f; oldseek = ftell (fdi->file); + if (oldseek == -1) { + fdi_free(fdi); + return NULL; + } fseek (fdi->file, 0, SEEK_SET); fread (fdi->header, 2048, 1, fdi->file); fseek (fdi->file, oldseek, SEEK_SET); From 19345158a6690c1b318bf822d5ef8e40f0958a7e Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 20:55:13 +0100 Subject: [PATCH 084/177] Added a sanity fatal() to the hard disk image code. --- src/disk/hdd_image.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/disk/hdd_image.c b/src/disk/hdd_image.c index a34f2b5cb..ec48e24e5 100644 --- a/src/disk/hdd_image.c +++ b/src/disk/hdd_image.c @@ -750,7 +750,10 @@ hdd_image_read(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer) { int i; - fseeko64(hdd_images[id].file, ((uint64_t)(sector) << 9LL) + hdd_images[id].base, SEEK_SET); + if (fseeko64(hdd_images[id].file, ((uint64_t)(sector) << 9LL) + hdd_images[id].base, SEEK_SET) == -1) { + fatal("Hard disk image %i: Error during seek\n", id); + return; + } for (i = 0; i < count; i++) { if (feof(hdd_images[id].file)) From 41ba2e4e34ba3aef31e04bb162f474337ac98101 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 20:56:08 +0100 Subject: [PATCH 085/177] Removed a piece of dead code from the CL-GD 54xx code. --- src/video/vid_cl54xx.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 0ca557bd8..1ba5b7a38 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -1845,9 +1845,6 @@ gd54xx_writel_linear(uint32_t addr, uint32_t val, void *p) case 3: return; } - - if (svga->fast) - sub_cycles(video_timing_write_l); } else { switch(ap) { case 0: From f45419d7968a86b1f71e0a1565a50ce186a6f4f9 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 20:59:54 +0100 Subject: [PATCH 086/177] Added another sanity fatal() to the hard disk image code. --- src/disk/hdd_image.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/disk/hdd_image.c b/src/disk/hdd_image.c index ec48e24e5..b5d943fdd 100644 --- a/src/disk/hdd_image.c +++ b/src/disk/hdd_image.c @@ -751,7 +751,7 @@ hdd_image_read(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer) int i; if (fseeko64(hdd_images[id].file, ((uint64_t)(sector) << 9LL) + hdd_images[id].base, SEEK_SET) == -1) { - fatal("Hard disk image %i: Error during seek\n", id); + fatal("Hard disk image %i: Read error during seek\n", id); return; } @@ -795,7 +795,10 @@ hdd_image_write(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer) { int i; - fseeko64(hdd_images[id].file, ((uint64_t)(sector) << 9LL) + hdd_images[id].base, SEEK_SET); + if (fseeko64(hdd_images[id].file, ((uint64_t)(sector) << 9LL) + hdd_images[id].base, SEEK_SET) == -1) { + fatal("Hard disk image %i: Write error during seek\n", id); + return; + } for (i = 0; i < count; i++) { if (feof(hdd_images[id].file)) From 1a770142bd92a5c0b11f33b12d47e0f43ea825ef Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 21:00:45 +0100 Subject: [PATCH 087/177] And another one. --- src/disk/hdd_image.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/disk/hdd_image.c b/src/disk/hdd_image.c index b5d943fdd..21fdf00c6 100644 --- a/src/disk/hdd_image.c +++ b/src/disk/hdd_image.c @@ -834,7 +834,10 @@ hdd_image_zero(uint8_t id, uint32_t sector, uint32_t count) memset(empty_sector, 0, 512); - fseeko64(hdd_images[id].file, ((uint64_t)(sector) << 9LL) + hdd_images[id].base, SEEK_SET); + if (fseeko64(hdd_images[id].file, ((uint64_t)(sector) << 9LL) + hdd_images[id].base, SEEK_SET) == -1) { + fatal("Hard disk image %i: Zero error during seek\n", id); + return; + } for (i = 0; i < count; i++) { if (feof(hdd_images[id].file)) From e8835770692b7d0a5f6248402ca63367cade2ed4 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 21:01:46 +0100 Subject: [PATCH 088/177] Removed a useless unsigned compare from the ATi 28800 code. --- src/video/vid_ati28800.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/video/vid_ati28800.c b/src/video/vid_ati28800.c index a0c883c33..28081efe9 100644 --- a/src/video/vid_ati28800.c +++ b/src/video/vid_ati28800.c @@ -190,8 +190,7 @@ ati28800_out(uint16_t addr, uint8_t val, void *p) return; if ((ati28800->regs[0xb4] & 0x20) && ((svga->crtc[0x08] & 0x7f) && (svga->crtc[0x14] & 0x1f))) return; - if ((ati28800->regs[0xb4] & 0x40) && (((svga->crtcreg >= 0x00) && (svga->crtcreg <= 0x06)) && - (svga->crtc[0x07] & 0x10) != 0x10)) + if ((ati28800->regs[0xb4] & 0x40) && ((svga->crtcreg <= 0x06) && (svga->crtc[0x07] & 0x10) != 0x10)) return; old = svga->crtc[svga->crtcreg]; From f8222dc780bdf19452978cc05f67186c6e48d7ff Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 21:04:07 +0100 Subject: [PATCH 089/177] Sanitized a part of the SCAT code. --- src/chipset/scat.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/chipset/scat.c b/src/chipset/scat.c index 0c3223486..271d4626a 100644 --- a/src/chipset/scat.c +++ b/src/chipset/scat.c @@ -1338,13 +1338,20 @@ static void mem_write_scatb(uint32_t addr, uint8_t val, void *priv) { ems_page_t *page = (ems_page_t *)priv; - scat_t *dev = (scat_t *)page->scat; + scat_t *dev; uint32_t oldaddr = addr, chkaddr; - addr = get_addr(dev, addr, page); - chkaddr = page ? addr : oldaddr; + if (dev == NULL) + chkaddr = oldaddr; + else { + dev = (scat_t *)page->scat; + addr = get_addr(dev, addr, page); + chkaddr = addr; + } + if (chkaddr >= 0xc0000 && chkaddr < 0x100000) { - if (dev->regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xc0000) >> 15))) return; + if (dev->regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xc0000) >> 15))) + return; } if (addr < ((uint32_t)mem_size << 10)) From a502e44f177cbb629f1b1eac6611e0e390352481 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 21:05:15 +0100 Subject: [PATCH 090/177] Added a sanity check to the Iomega ZIP code. --- src/disk/zip.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/disk/zip.c b/src/disk/zip.c index ccc2fd1c2..5e962115c 100644 --- a/src/disk/zip.c +++ b/src/disk/zip.c @@ -1173,7 +1173,8 @@ zip_blocks(zip_t *dev, int32_t *len, int first_batch, int out) *len = dev->requested_blocks << 9; for (i = 0; i < dev->requested_blocks; i++) { - fseek(dev->drv->f, dev->drv->base + (dev->sector_pos << 9) + (i << 9), SEEK_SET); + if (fseek(dev->drv->f, dev->drv->base + (dev->sector_pos << 9) + (i << 9), SEEK_SET) == 1) + break; if (feof(dev->drv->f)) break; From 94fee31e52a3ddd4e48d19b1cb89042e9fc340e9 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 22:12:02 +0100 Subject: [PATCH 091/177] Fixed a resource leak in the PGC code. --- src/video/vid_pgc.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/video/vid_pgc.c b/src/video/vid_pgc.c index e8ccbee4b..8556500e0 100644 --- a/src/video/vid_pgc.c +++ b/src/video/vid_pgc.c @@ -867,7 +867,21 @@ pgc_fill_polygon(pgc_t *dev, unsigned corners, int32_t *x, int32_t *y) nodex = (double *)malloc(corners * sizeof(double)); dx = (double *)malloc(corners * sizeof(double)); dy = (double *)malloc(corners * sizeof(double)); - if (!nodex || !dx || !dy) return; + if (!nodex || !dx || !dy) { + if (nodex) { + free(nodex); + nodex = NULL; + } + if (dx) { + free(dx); + dx = NULL; + } + if (dy) { + free(dy); + dy = NULL; + } + return; + } ymin = ymax = y[0] / 65536.0; for (n = 0; n < corners; n++) { From e0218694a3a0f4172cfeee38e2cbcf396f63bea0 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 22:14:08 +0100 Subject: [PATCH 092/177] Fixed a bug with ET4000/W32p linear base address. --- src/video/vid_et4000w32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index 66250d248..c4480abbc 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -257,7 +257,7 @@ void et4000w32p_out(uint16_t addr, uint8_t val, void *p) if (et4000->pci) { et4000->linearbase &= 0xc0000000; - et4000->linearbase = (val & 0xfc) << 22; + et4000->linearbase |= (val & 0xfc) << 22; } else { From e733ac2cf89c338903b054d3f747d6be4675d9a2 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 22:16:54 +0100 Subject: [PATCH 093/177] Doubled the size of fd_file_name in win/win_new_floppy.c, fixes array overrun in zip_load(). --- src/win/win_new_floppy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/win/win_new_floppy.c b/src/win/win_new_floppy.c index 0dff080c9..ab41d7df3 100644 --- a/src/win/win_new_floppy.c +++ b/src/win/win_new_floppy.c @@ -515,7 +515,7 @@ create_zip_sector_image(WCHAR *file_name, disk_size_t disk_size, uint8_t is_zdi, static int fdd_id, sb_part; static int file_type = 0; /* 0 = IMG, 1 = Japanese FDI, 2 = 86F */ -static wchar_t fd_file_name[512]; +static wchar_t fd_file_name[1024]; /* Show a MessageBox dialog. This is nasty, I know. --FvK */ From 3e720fdd96acdc27cb6e3c2a7f353a00aaaa4784 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 22:19:15 +0100 Subject: [PATCH 094/177] Added two more sanity checks into the FDI2RAW code. --- src/floppy/fdi2raw.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/floppy/fdi2raw.c b/src/floppy/fdi2raw.c index ffb3c3a53..5cbbd9a0c 100644 --- a/src/floppy/fdi2raw.c +++ b/src/floppy/fdi2raw.c @@ -187,10 +187,14 @@ static uae_u8 temp, temp2; static uae_u8 *expand_tree (uae_u8 *stream, NODE *node) { if (temp & temp2) { - fdi_free (node->left); - node->left = 0; - fdi_free (node->right); - node->right = 0; + if (node->left) { + fdi_free (node->left); + node->left = 0; + } + if (node->right) { + fdi_free (node->right); + node->right = 0; + } temp2 >>= 1; if (!temp2) { temp = *stream++; From b9f3fdc5483668c68e21ed9cb18bfe63fb54c8ed Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 22:21:24 +0100 Subject: [PATCH 095/177] Removed a redundant if block from win/win_ui.c. --- src/win/win_ui.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/win/win_ui.c b/src/win/win_ui.c index 4e99eebb4..1632ea27a 100644 --- a/src/win/win_ui.c +++ b/src/win/win_ui.c @@ -628,8 +628,6 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) plat_vidapi_enable(0); temp_y -= sbar_height; - if (temp_x < 1) - temp_x = 1; if (temp_y < 1) temp_y = 1; From 2d5a8dc49c76f7550c6f81de5f71eaf6f33d44f3 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 22:23:56 +0100 Subject: [PATCH 096/177] Fixed a resource leak in win/win.c. --- src/win/win.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/win/win.c b/src/win/win.c index 2f421412b..5175d65e3 100644 --- a/src/win/win.c +++ b/src/win/win.c @@ -267,6 +267,11 @@ CreateConsole(int init) } } } + + if (fp != NULL) { + fclose(fp); + fp = NULL; + } } From f710954c6f765a077012c46921c9cef78fd563ef Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 22:24:56 +0100 Subject: [PATCH 097/177] Doubled the data array in config.c, fixes an array overrun. --- src/config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.c b/src/config.c index a3a069cc7..e526a3c3b 100644 --- a/src/config.c +++ b/src/config.c @@ -81,7 +81,7 @@ typedef struct { list_t list; char name[128]; - char data[256]; + char data[512]; wchar_t wdata[512]; } entry_t; From 79a10c06b0a919c7bf72659b7966e01320e24901 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 22:26:22 +0100 Subject: [PATCH 098/177] Fixed an unintentional integer overflow in win/win_settings.c. --- src/win/win_settings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/win/win_settings.c b/src/win/win_settings.c index f47f4f4b1..1b9379306 100644 --- a/src/win/win_settings.c +++ b/src/win/win_settings.c @@ -2532,7 +2532,7 @@ static int hdconf_initialize_hdt_combo(HWND hdlg) h = GetDlgItem(hdlg, IDC_COMBO_HD_TYPE); for (i = 0; i < 127; i++) { - temp_size = hdd_table[i][0] * hdd_table[i][1] * hdd_table[i][2]; + temp_size = ((uint64_t) hdd_table[i][0]) * hdd_table[i][1] * hdd_table[i][2]; size_mb = (uint32_t) (temp_size >> 11LL); wsprintf(szText, plat_get_string(IDS_2116), size_mb, hdd_table[i][0], hdd_table[i][1], hdd_table[i][2]); SendMessage(h, CB_ADDSTRING, 0, (LPARAM) szText); From cbcb53f7ee241f6a1b044dc58b17e1596ccc7f6c Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 22:29:07 +0100 Subject: [PATCH 099/177] Fixed a bug in the 486, WinChip, WinChip 2, Pentium, and 686 timings for the new recompiler. --- src/cpu_new/codegen_timing_486.c | 2 +- src/cpu_new/codegen_timing_686.c | 2 +- src/cpu_new/codegen_timing_pentium.c | 2 +- src/cpu_new/codegen_timing_winchip.c | 2 +- src/cpu_new/codegen_timing_winchip2.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/cpu_new/codegen_timing_486.c b/src/cpu_new/codegen_timing_486.c index 6b744472b..b4054b32f 100644 --- a/src/cpu_new/codegen_timing_486.c +++ b/src/cpu_new/codegen_timing_486.c @@ -358,7 +358,7 @@ void codegen_timing_486_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, uin { case 0x80: case 0x82: case 0x83: timings = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; - deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x_mod3; + deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; opcode = (fetchdat >> 3) & 7; break; case 0x81: diff --git a/src/cpu_new/codegen_timing_686.c b/src/cpu_new/codegen_timing_686.c index 6bcb7c44d..609a5e068 100644 --- a/src/cpu_new/codegen_timing_686.c +++ b/src/cpu_new/codegen_timing_686.c @@ -885,7 +885,7 @@ void codegen_timing_686_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, uin { case 0x80: case 0x82: case 0x83: timings = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; - deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x_mod3; + deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; opcode = (fetchdat >> 3) & 7; break; case 0x81: diff --git a/src/cpu_new/codegen_timing_pentium.c b/src/cpu_new/codegen_timing_pentium.c index ee893a361..1e4c104fd 100644 --- a/src/cpu_new/codegen_timing_pentium.c +++ b/src/cpu_new/codegen_timing_pentium.c @@ -1136,7 +1136,7 @@ void codegen_timing_pentium_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, { case 0x80: case 0x82: case 0x83: timings = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; - deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x_mod3; + deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; opcode = (fetchdat >> 3) & 7; break; case 0x81: diff --git a/src/cpu_new/codegen_timing_winchip.c b/src/cpu_new/codegen_timing_winchip.c index 90982349f..f488078a5 100644 --- a/src/cpu_new/codegen_timing_winchip.c +++ b/src/cpu_new/codegen_timing_winchip.c @@ -358,7 +358,7 @@ void codegen_timing_winchip_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, { case 0x80: case 0x82: case 0x83: timings = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; - deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x_mod3; + deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; opcode = (fetchdat >> 3) & 7; break; case 0x81: diff --git a/src/cpu_new/codegen_timing_winchip2.c b/src/cpu_new/codegen_timing_winchip2.c index 9da156b82..e7294b917 100644 --- a/src/cpu_new/codegen_timing_winchip2.c +++ b/src/cpu_new/codegen_timing_winchip2.c @@ -626,7 +626,7 @@ static void codegen_timing_winchip2_opcode(uint8_t opcode, uint32_t fetchdat, in { case 0x80: case 0x82: case 0x83: timings = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; - deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x_mod3; + deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; opcode = (fetchdat >> 3) & 7; break; case 0x81: From 2fcf79ec8ddacd4aa9f069ef8d7119a2bb078acc Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 22:33:13 +0100 Subject: [PATCH 100/177] Fixed an if block in the Intel SIO code. --- src/intel_sio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/intel_sio.c b/src/intel_sio.c index b9e3a07d3..45cdf2975 100644 --- a/src/intel_sio.c +++ b/src/intel_sio.c @@ -123,7 +123,7 @@ sio_write(int func, int addr, uint8_t val, void *priv) if (func > 0) return; - if (addr >= 0x0f && addr < 0x4c) + if (((addr >= 0x0f) && (addr < 0x4c)) && (addr != 0x40)) return; /* The IB (original) variant of the SIO has no PCI IRQ steering. */ From a219d48061333b36aa149de225bc914dc31a924b Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 22:40:14 +0100 Subject: [PATCH 101/177] Fixed an IF block in the PS/1 code. --- src/machine/m_ps1.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/machine/m_ps1.c b/src/machine/m_ps1.c index 2bfd6e7f7..30a610b8b 100644 --- a/src/machine/m_ps1.c +++ b/src/machine/m_ps1.c @@ -459,12 +459,6 @@ ps1_setup(int model) lpt2_remove(); - /* Enable the PS/1 VGA controller. */ - if (model == 2011) - device_add(&ps1vga_device); - else - device_add(&ibm_ps1_2121_device); - device_add(&snd_device); device_add(&fdc_at_actlow_device); @@ -505,6 +499,12 @@ ps1_setup(int model) device_add(&ide_isa_device); } #endif + + /* Enable the PS/1 VGA controller. */ + if (model == 2011) + device_add(&ps1vga_device); + else + device_add(&ibm_ps1_2121_device); } From 6217904ac927aa1267cc744b140af8cddef25752 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 22:41:37 +0100 Subject: [PATCH 102/177] Fixed another resource leak in the PGC code. --- src/video/vid_pgc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/video/vid_pgc.c b/src/video/vid_pgc.c index 8556500e0..e0bceb8dd 100644 --- a/src/video/vid_pgc.c +++ b/src/video/vid_pgc.c @@ -2033,7 +2033,10 @@ pgc_parse_words(pgc_t *dev, pgc_cl_t *cl, int count) } for (n = 0; n < count; n++) { - if (! pgc_param_word(dev, ¶m[n])) return 0; + if (! pgc_param_word(dev, ¶m[n])) { + free(param); + return 0; + } if (!pgc_cl_append(cl, param[n] & 0xff) || !pgc_cl_append(cl, param[n] >> 8)) { From 100aaa0115b0512bc6f11b33dd8594168d7fbea8 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 22:44:08 +0100 Subject: [PATCH 103/177] Fixed the initialization of GPIO ports at the SMC FDC37C93x family of Super I/O chips. --- src/sio_fdc37c93x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sio_fdc37c93x.c b/src/sio_fdc37c93x.c index e93ffea54..ef3380ee4 100644 --- a/src/sio_fdc37c93x.c +++ b/src/sio_fdc37c93x.c @@ -203,7 +203,7 @@ static void fdc37c93x_gpio_handler(fdc37c93x_t *dev) break; } dev->gpio_base = ld_port; - if ((ld_port >= 0x0100) && (ld_port <= 0x0FFE)) + if (ld_port > 0x0000) io_sethandler(dev->gpio_base, 0x0002, fdc37c93x_gpio_read, NULL, NULL, fdc37c93x_gpio_write, NULL, NULL, dev); } From a8a67364d830f49a11b9ac3a43fca7c680c8f087 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 23:04:38 +0100 Subject: [PATCH 104/177] Fixed resource leaks in the Image Manager 1024 code. --- src/video/vid_im1024.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/video/vid_im1024.c b/src/video/vid_im1024.c index 0a8ca6e6c..d1ef0bdcf 100644 --- a/src/video/vid_im1024.c +++ b/src/video/vid_im1024.c @@ -544,8 +544,20 @@ hndl_poly(pgc_t *pgc) } for (n = 0; n < count; n++) { - if (! pgc_param_word(pgc, &xw)) return; - if (! pgc_param_word(pgc, &yw)) return; + if (! pgc_param_word(pgc, &xw)) { + if (x) + free(x); + if (y) + free(y); + return; + } + if (! pgc_param_word(pgc, &yw)) { + if (x) + free(x); + if (y) + free(y); + return; + } /* Skip degenerate line segments. */ if (realcount > 0 && From a2f8162500a8dba662ecec7c813d4eb422df5535 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 23:05:10 +0100 Subject: [PATCH 105/177] Removed a useless if block from the XTA code. --- src/disk/hdc_xta.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/disk/hdc_xta.c b/src/disk/hdc_xta.c index 9aa8f8faf..43a615ba6 100644 --- a/src/disk/hdc_xta.c +++ b/src/disk/hdc_xta.c @@ -385,9 +385,6 @@ do_seek(hdc_t *dev, drive_t *drive, int cyl) drive->cur_cyl = (drive->tracks - 1); else drive->cur_cyl = dev->track; - - if (drive->cur_cyl < 0) - drive->cur_cyl = 0; } From 93695b15b3a0c594a3b5d25e4a41d8239ba38023 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 23:07:10 +0100 Subject: [PATCH 106/177] Fixed another potential overrun in win/win_settings.c. --- src/win/win_settings.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/win/win_settings.c b/src/win/win_settings.c index 1b9379306..6e2583336 100644 --- a/src/win/win_settings.c +++ b/src/win/win_settings.c @@ -3467,7 +3467,7 @@ win_settings_floppy_drives_recalc_list(HWND hwndList) { LVITEM lvI; int i = 0; - char s[256]; + char s[256], t; WCHAR szText[256]; lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; @@ -3476,7 +3476,11 @@ win_settings_floppy_drives_recalc_list(HWND hwndList) for (i = 0; i < 4; i++) { lvI.iSubItem = 0; if (temp_fdd_types[i] > 0) { - strcpy(s, fdd_getname(temp_fdd_types[i])); + t = fdd_getname(temp_fdd_types[i]); + if (strlen(t) <= 256) + strcpy(s, t); + else + strncpy(s, t, 256); mbstowcs(szText, s, strlen(s) + 1); lvI.pszText = szText; } else From 84659f6b01bdc37e71a15d017ccc080022a0f5b6 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 23:08:13 +0100 Subject: [PATCH 107/177] Fixed a resource leak in the hard disk image code. --- src/disk/hdd_image.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/disk/hdd_image.c b/src/disk/hdd_image.c index 21fdf00c6..9d5671fae 100644 --- a/src/disk/hdd_image.c +++ b/src/disk/hdd_image.c @@ -128,8 +128,11 @@ image_is_hdx(const wchar_t *s, int check_signature) fseeko64(f, 0, SEEK_END); filelen = ftello64(f); fseeko64(f, 0, SEEK_SET); - if (filelen < 44) + if (filelen < 44) { + if (f != NULL) + fclose(f); return 0; + } fread(&signature, 1, 8, f); fclose(f); if (signature == 0xD778A82044445459ll) From 7787c638bbd6c8828b7e3027cf5b06f30a50e27f Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 23:10:03 +0100 Subject: [PATCH 108/177] Fixed another resource leak in the Image Manager 1024 code. --- src/video/vid_im1024.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/video/vid_im1024.c b/src/video/vid_im1024.c index d1ef0bdcf..6a297d9ca 100644 --- a/src/video/vid_im1024.c +++ b/src/video/vid_im1024.c @@ -527,7 +527,13 @@ hndl_poly(pgc_t *pgc) } while (parsing) { - if (! pgc_param_byte(pgc, &count)) return; + if (! pgc_param_byte(pgc, &count)) { + if (x) + free(x); + if (y) + free(y); + return; + } if (count + realcount >= as) { nx = (int32_t *)realloc(x, 2 * as * sizeof(int32_t)); From 82f24f36e2838f2b4b1161688694166abc11006d Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Jan 2020 23:14:29 +0100 Subject: [PATCH 109/177] Fixed a bad dereference in the text printer code. --- src/printer/prt_text.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/printer/prt_text.c b/src/printer/prt_text.c index aa56ae2e1..404e27c86 100644 --- a/src/printer/prt_text.c +++ b/src/printer/prt_text.c @@ -465,13 +465,14 @@ prnt_close(void *priv) { prnt_t *dev = (prnt_t *)priv; - if (dev == NULL) return; + if (dev == NULL) + return; - /* print last page if it contains data */ - if (dev->page->dirty) - dump_page(dev); + if (dev->page) { + /* print last page if it contains data */ + if (dev->page->dirty) + dump_page(dev); - if (dev->page != NULL) { if (dev->page->chars != NULL) free(dev->page->chars); free(dev->page); From 11097eb6215e623b1caefc31bd2c43eccb3897f3 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 00:17:46 +0100 Subject: [PATCH 110/177] Added a sanity check to the XT ST-506 code. --- src/disk/hdc_st506_xt.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/disk/hdc_st506_xt.c b/src/disk/hdc_st506_xt.c index a49e866fe..5831fee88 100644 --- a/src/disk/hdc_st506_xt.c +++ b/src/disk/hdc_st506_xt.c @@ -1310,6 +1310,13 @@ loadrom(hdc_t *dev, const wchar_t *fn) uint32_t size; FILE *fp; + if (fn == NULL) { +#ifdef ENABLE_ST506_XT_LOG + st506_xt_log("ST506: NULL BIOS ROM file pointer!\n"); +#endif + return; + } + if ((fp = rom_fopen((wchar_t *) fn, L"rb")) == NULL) { st506_xt_log("ST506: BIOS ROM '%ls' not found!\n", fn); return; From 2058c12e03ed2e6b1bfb41cf1543f01059bbe8ff Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 00:19:47 +0100 Subject: [PATCH 111/177] Removed a useless if block from the XTA code. --- src/disk/hdc_xta.c | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/src/disk/hdc_xta.c b/src/disk/hdc_xta.c index 43a615ba6..c821ef98d 100644 --- a/src/disk/hdc_xta.c +++ b/src/disk/hdc_xta.c @@ -625,12 +625,6 @@ do_send: } break; -#if 0 - case CMD_WRITE_VERIFY: - no_data = 1; - /*FALLTHROUGH*/ -#endif - case CMD_WRITE_SECTORS: if (! drive->present) { dev->comp |= COMP_ERR; @@ -663,19 +657,14 @@ do_recv: /* Ready to transfer the data in. */ dev->state = STATE_RDATA; dev->buf_idx = 0; - if (no_data) { - /* Delay a bit, no actual transfer. */ + if (dev->intr & DMA_ENA) { + /* DMA enabled. */ + dev->buf_ptr = dev->sector_buf; xta_set_callback(dev, HDC_TIME); } else { - if (dev->intr & DMA_ENA) { - /* DMA enabled. */ - dev->buf_ptr = dev->sector_buf; - xta_set_callback(dev, HDC_TIME); - } else { - /* No DMA, do PIO. */ - dev->buf_ptr = dev->data; - dev->status |= STAT_REQ; - } + /* No DMA, do PIO. */ + dev->buf_ptr = dev->data; + dev->status |= STAT_REQ; } break; From 0c02679ac42732d5415461de221e6a4b5255885d Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 00:21:49 +0100 Subject: [PATCH 112/177] Fixed some variables in cpu_new/codegen_ops_jump.c to make them signed. --- src/cpu_new/codegen_ops_jump.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cpu_new/codegen_ops_jump.c b/src/cpu_new/codegen_ops_jump.c index 4363c9040..a4d2b8847 100644 --- a/src/cpu_new/codegen_ops_jump.c +++ b/src/cpu_new/codegen_ops_jump.c @@ -13,7 +13,7 @@ uint32_t ropJMP_r8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc); + int32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc); uint32_t dest_addr = op_pc+1+offset; if (!(op_32 & 0x100)) @@ -26,7 +26,7 @@ uint32_t ropJMP_r8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f } uint32_t ropJMP_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint32_t offset = (int32_t)(int16_t)fastreadw(cs + op_pc); + int32_t offset = (int32_t)(int16_t)fastreadw(cs + op_pc); uint32_t dest_addr = op_pc+2+offset; dest_addr &= 0xffff; @@ -38,7 +38,7 @@ uint32_t ropJMP_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t } uint32_t ropJMP_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint32_t offset = fastreadl(cs + op_pc); + int32_t offset = fastreadl(cs + op_pc); uint32_t dest_addr = op_pc+4+offset; if (offset < 0) From be041ae94d6cf84748f08e8d1fc961af12fb3630 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 00:30:01 +0100 Subject: [PATCH 113/177] Removed some useless code (including a dead code block) in the 86F image creation code. --- src/win/win_new_floppy.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/win/win_new_floppy.c b/src/win/win_new_floppy.c index ab41d7df3..e773e54e2 100644 --- a/src/win/win_new_floppy.c +++ b/src/win/win_new_floppy.c @@ -80,7 +80,7 @@ create_86f(WCHAR *file_name, disk_size_t disk_size, uint8_t rpm_mode) uint16_t tflags = 0; uint32_t index_hole_pos = 0; uint32_t tarray[512]; - uint32_t array_size, array_size2; + uint32_t array_size; uint32_t track_base, track_size; int i; uint32_t shift = 0; @@ -133,11 +133,6 @@ create_86f(WCHAR *file_name, disk_size_t disk_size, uint8_t rpm_mode) break; } - array_size2 = (array_size << 3); - array_size = (array_size2 >> 4) << 1; - if (array_size2 & 15) - array_size += 2; - empty = (unsigned char *) malloc(array_size); memset(tarray, 0, 2048); From 2fe6ea0e648c7053aceafac9194772294e7f3d71 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 00:32:52 +0100 Subject: [PATCH 114/177] Fixed the EEPROM/registers array size mess in the AdLib Gold code. --- src/sound/snd_adlibgold.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sound/snd_adlibgold.c b/src/sound/snd_adlibgold.c index 06a4fcee5..1322221d6 100644 --- a/src/sound/snd_adlibgold.c +++ b/src/sound/snd_adlibgold.c @@ -20,11 +20,11 @@ typedef struct adgold_t { int adgold_irq_status; - uint8_t adgold_eeprom[0x19]; + uint8_t adgold_eeprom[0x1a]; uint8_t adgold_status; int adgold_38x_state, adgold_38x_addr; - uint8_t adgold_38x_regs[0x19]; + uint8_t adgold_38x_regs[0x1a]; int adgold_mma_addr; uint8_t adgold_mma_regs[2][0xe]; @@ -211,9 +211,9 @@ void adgold_write(uint16_t addr, uint8_t val, void *p) { case 0x00: /*Control/ID*/ if (val & 1) - memcpy(adgold->adgold_38x_regs, adgold->adgold_eeprom, 0x19); + memcpy(adgold->adgold_38x_regs, adgold->adgold_eeprom, 0x1a); if (val & 2) - memcpy(adgold->adgold_eeprom, adgold->adgold_38x_regs, 0x19); + memcpy(adgold->adgold_eeprom, adgold->adgold_38x_regs, 0x1a); break; case 0x04: /*Final output volume left*/ @@ -774,7 +774,7 @@ void *adgold_init(const device_t *info) f = nvr_fopen(L"adgold.bin", L"rb"); if (f) { - fread(adgold->adgold_eeprom, 0x18, 1, f); + fread(adgold->adgold_eeprom, 0x1a, 1, f); fclose(f); } From dfc4347e9a5b09d50e2b955b4a2498a12a926748 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 00:34:28 +0100 Subject: [PATCH 115/177] Fixed a potential overrun in the ATi EEPROM code. --- src/video/vid_ati_eeprom.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/video/vid_ati_eeprom.c b/src/video/vid_ati_eeprom.c index 3a01bfedd..f1fb0753f 100644 --- a/src/video/vid_ati_eeprom.c +++ b/src/video/vid_ati_eeprom.c @@ -59,7 +59,10 @@ void ati_eeprom_load(ati_eeprom_t *eeprom, wchar_t *fn, int type) { FILE *f; eeprom->type = type; - wcscpy(eeprom->fn, fn); + if (wcslen(fn) <= 256) + wcscpy(eeprom->fn, fn); + else + wcsncpy(eeprom->fn, fn, 256); f = nvr_fopen(eeprom->fn, L"rb"); if (!f) { From 8fdc175883e334b63272983712619af053cf88a3 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 00:36:12 +0100 Subject: [PATCH 116/177] Turned a variable in the ESC/P code into signed. --- src/printer/prt_escp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/printer/prt_escp.c b/src/printer/prt_escp.c index 597105cd4..a3ee36cad 100644 --- a/src/printer/prt_escp.c +++ b/src/printer/prt_escp.c @@ -228,7 +228,7 @@ typedef struct { double horizontal_tabs[32]; uint8_t num_horizontal_tabs; double vertical_tabs[16]; - uint8_t num_vertical_tabs; + int8_t num_vertical_tabs; /* bit graphics data */ uint16_t bg_h_density; /* in dpi */ From 2b5425de79cef16ca985c802ba6df26d4117b4ec Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 00:38:29 +0100 Subject: [PATCH 117/177] Removed a block of dead code from win/win_settings.c. --- src/win/win_settings.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/win/win_settings.c b/src/win/win_settings.c index 6e2583336..133103107 100644 --- a/src/win/win_settings.c +++ b/src/win/win_settings.c @@ -539,13 +539,9 @@ win_settings_machine_recalc_cpu(HWND hdlg) h = GetDlgItem(hdlg, IDC_CHECK_FPU); cpu_type = machines[temp_machine].cpu[temp_cpu_m].cpus[temp_cpu].cpu_type; - // if ((cpu_type < CPU_i486DX) && (cpu_type >= CPU_286)) if (cpu_type < CPU_i486DX) EnableWindow(h, TRUE); - else if (cpu_type < CPU_286) { - temp_fpu = 0; - EnableWindow(h, FALSE); - } else { + else { temp_fpu = 1; EnableWindow(h, FALSE); } From 1f4927cdce61b3905e45a11cb1cab04fe198f0e3 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 00:39:55 +0100 Subject: [PATCH 118/177] Fixed a potential overrun in the ROM code. --- src/rom.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/rom.c b/src/rom.c index 204fd0eee..17dd9ef8f 100644 --- a/src/rom.c +++ b/src/rom.c @@ -62,7 +62,10 @@ rom_fopen(wchar_t *fn, wchar_t *mode) { wchar_t temp[1024]; - wcscpy(temp, exe_path); + if (wcslen(exe_path) <= 1024) + wcscpy(temp, exe_path); + else + wcsncpy(temp, exe_path, 1024); plat_put_backslash(temp); wcscat(temp, fn); From a39bb1db2b6780f1728b9790a78b30ae10166ec3 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 00:41:02 +0100 Subject: [PATCH 119/177] Fixed another resource leak in win/win.c. --- src/win/win.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/win/win.c b/src/win/win.c index 5175d65e3..a9aec2a81 100644 --- a/src/win/win.c +++ b/src/win/win.c @@ -336,6 +336,9 @@ ProcessCommandLine(wchar_t ***argw) args[argc] = NULL; *argw = args; + if (argbuf != NULL) + free(argbuf); + return(argc); } From d5100ec287e82511dc54d52990e0a2f64771a486 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 00:42:43 +0100 Subject: [PATCH 120/177] Applied a mask to the return values of the two calls to fgetc() in the ROM code. --- src/rom.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rom.c b/src/rom.c index 17dd9ef8f..cbb43a82b 100644 --- a/src/rom.c +++ b/src/rom.c @@ -263,8 +263,8 @@ rom_load_interleaved(wchar_t *fnl, wchar_t *fnh, uint32_t addr, int sz, int off, (void)fseek(fl, off, SEEK_SET); (void)fseek(fh, off, SEEK_SET); for (c=0; c Date: Wed, 15 Jan 2020 00:43:51 +0100 Subject: [PATCH 121/177] Fixed a potential overrun in the Intel flash code. --- src/intel_flash.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/intel_flash.c b/src/intel_flash.c index 4dd041a48..faddf4ec4 100644 --- a/src/intel_flash.c +++ b/src/intel_flash.c @@ -330,7 +330,10 @@ intel_flash_init(const device_t *info) flash_name = (wchar_t *)malloc(l*sizeof(wchar_t)); swprintf(flash_name, l, L"%ls.bin", machine_name); - wcscpy(flash_path, flash_name); + if (wcslen(flash_name) <= 1024) + wcscpy(flash_path, flash_name); + else + wcsncpy(flash_path, flash_name, 1024); dev->flags = info->local & 0xff; From 34bf074e8df70070cbf49acbe939025418bb2c0b Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 00:45:15 +0100 Subject: [PATCH 122/177] Fixed a resource leak in the VHD part of the hard disk image code. --- src/disk/hdd_image.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/disk/hdd_image.c b/src/disk/hdd_image.c index 9d5671fae..63d140014 100644 --- a/src/disk/hdd_image.c +++ b/src/disk/hdd_image.c @@ -167,8 +167,11 @@ image_is_vhd(const wchar_t *s, int check_signature) fseeko64(f, 0, SEEK_END); filelen = ftello64(f); fseeko64(f, -512, SEEK_END); - if (filelen < 512) + if (filelen < 512) { + if (f != NULL) + fclose(f); return 0; + } fread(&signature, 1, 8, f); fclose(f); if (signature == 0x78697463656E6F63ll) From 2b94cd2b9670cd65e99dbcd796bdf98ca11798a7 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 00:49:42 +0100 Subject: [PATCH 123/177] Fixed potential SCSI ID overruns in the SCSI hard diks, CD-ROM, and Iomega ZIP codes. --- src/disk/zip.c | 2 +- src/scsi/scsi_cdrom.c | 2 +- src/scsi/scsi_disk.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/disk/zip.c b/src/disk/zip.c index 5e962115c..8c03f861a 100644 --- a/src/disk/zip.c +++ b/src/disk/zip.c @@ -2368,7 +2368,7 @@ zip_hard_reset(void) zip_log("ZIP hard_reset drive=%d\n", c); /* Make sure to ignore any SCSI ZIP drive that has an out of range ID. */ - if ((zip_drives[c].bus_type == ZIP_BUS_SCSI) && (zip_drives[c].scsi_device_id > SCSI_ID_MAX)) + if ((zip_drives[c].bus_type == ZIP_BUS_SCSI) && (zip_drives[c].scsi_device_id >= SCSI_ID_MAX)) continue; /* Make sure to ignore any ATAPI ZIP drive that has an out of range IDE channel. */ diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index 72d3b2e2a..3667567fc 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -2545,7 +2545,7 @@ scsi_cdrom_drive_reset(int c) ide_t *id; /* Make sure to ignore any SCSI CD-ROM drive that has an out of range ID. */ - if ((drv->bus_type == CDROM_BUS_SCSI) && (drv->scsi_device_id > SCSI_ID_MAX)) + if ((drv->bus_type == CDROM_BUS_SCSI) && (drv->scsi_device_id >= SCSI_ID_MAX)) return; /* Make sure to ignore any ATAPI CD-ROM drive that has an out of range IDE channel. */ diff --git a/src/scsi/scsi_disk.c b/src/scsi/scsi_disk.c index 91256b4dc..6203a7ac4 100644 --- a/src/scsi/scsi_disk.c +++ b/src/scsi/scsi_disk.c @@ -1212,7 +1212,7 @@ scsi_disk_hard_reset(void) scsi_disk_log("SCSI disk hard_reset drive=%d\n", c); /* Make sure to ignore any SCSI disk that has an out of range ID. */ - if (hdd[c].scsi_id > SCSI_ID_MAX) + if (hdd[c].scsi_id >= SCSI_ID_MAX) continue; /* Make sure to ignore any SCSI disk whose image file name is empty. */ From 50dd49547bdc8e6e89ef8085360ef6292daae0d9 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 00:51:22 +0100 Subject: [PATCH 124/177] Increased the size of an array in config.c to fix an overrun. --- src/config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.c b/src/config.c index e526a3c3b..c9816e170 100644 --- a/src/config.c +++ b/src/config.c @@ -1698,7 +1698,7 @@ static void save_hard_disks(void) { char *cat = "Hard disks"; - char temp[32], tmp2[64]; + char temp[32], tmp2[256]; char *p; int c; From 7d551af78b495240b964a6b1b614b8e710476943 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 00:52:14 +0100 Subject: [PATCH 125/177] Fixed a bug in the IDE code. --- src/disk/hdc_ide.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index d6a52702f..b86605761 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -448,7 +448,7 @@ static void ide_hd_identify(ide_t *ide) char device_identify[9] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', 0 }; uint32_t d_hpc, d_spt, d_tracks; - uint64_t full_size = (hdd[ide->hdd_num].tracks * hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt); + uint64_t full_size = (((uint64_t) hdd[ide->hdd_num].tracks) * hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt); device_identify[6] = (ide->hdd_num / 10) + 0x30; device_identify[7] = (ide->hdd_num % 10) + 0x30; From 8928ef3f66ee57e658cd5c85aaedcd41b3c4aa9c Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 01:03:54 +0100 Subject: [PATCH 126/177] Fixed an overrun in win/win_ui.c, a few newly introduced bugs, and a warning in the MPU-401 code. --- src/chipset/scat.c | 6 +++++- src/plat.h | 2 +- src/sound/snd_mpu401.c | 3 +-- src/win/win_new_floppy.c | 2 +- src/win/win_settings.c | 2 +- 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/chipset/scat.c b/src/chipset/scat.c index 271d4626a..5ffa3722a 100644 --- a/src/chipset/scat.c +++ b/src/chipset/scat.c @@ -1341,10 +1341,14 @@ mem_write_scatb(uint32_t addr, uint8_t val, void *priv) scat_t *dev; uint32_t oldaddr = addr, chkaddr; + if (page == NULL) + dev = NULL; + else + dev = (scat_t *)page->scat; + if (dev == NULL) chkaddr = oldaddr; else { - dev = (scat_t *)page->scat; addr = get_addr(dev, addr, page); chkaddr = addr; } diff --git a/src/plat.h b/src/plat.h index 065d50aa0..ec5391bae 100644 --- a/src/plat.h +++ b/src/plat.h @@ -58,7 +58,7 @@ GLOBAL int dopause, /* system is paused */ mouse_capture; /* mouse is captured in app */ GLOBAL uint64_t timer_freq; GLOBAL int infocus; -GLOBAL char emu_version[128]; /* version ID string */ +GLOBAL char emu_version[200]; /* version ID string */ GLOBAL int rctrl_is_lalt; GLOBAL int update_icons; diff --git a/src/sound/snd_mpu401.c b/src/sound/snd_mpu401.c index 4fb9bea30..b2be5e1cd 100644 --- a/src/sound/snd_mpu401.c +++ b/src/sound/snd_mpu401.c @@ -1337,7 +1337,7 @@ MPU401_InputMsg(void *p, uint8_t *msg) uint8_t len = msg[3], key; uint8_t recdata[2], recmsg[4]; int send = 1, send_thru = 0; - int retrigger_thru = 0, midistatus = 0, chan, chrefnum; + int retrigger_thru = 0, chan, chrefnum; /* Abort if sysex transfer is in progress. */ if (!mpu->state.sysex_in_finished) { @@ -1350,7 +1350,6 @@ MPU401_InputMsg(void *p, uint8_t *msg) if (mpu->mode == M_INTELLIGENT) { if (msg[0] < 0x80) { /* Expand running status */ - midistatus = 1; msg[2] = msg[1]; msg[1] = msg[0]; msg[0] = old_msg; diff --git a/src/win/win_new_floppy.c b/src/win/win_new_floppy.c index e773e54e2..b06e41834 100644 --- a/src/win/win_new_floppy.c +++ b/src/win/win_new_floppy.c @@ -551,7 +551,7 @@ NewFloppyDialogProcedure(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) switch (message) { case WM_INITDIALOG: plat_pause(1); - memset(fd_file_name, 0, 512 * sizeof(wchar_t)); + memset(fd_file_name, 0, 1024 * sizeof(wchar_t)); h = GetDlgItem(hdlg, IDC_COMBO_DISK_SIZE); if (is_zip) { zip_types = zip_drives[fdd_id].is_250 ? 2 : 1; diff --git a/src/win/win_settings.c b/src/win/win_settings.c index 133103107..8b9dff3c8 100644 --- a/src/win/win_settings.c +++ b/src/win/win_settings.c @@ -3463,7 +3463,7 @@ win_settings_floppy_drives_recalc_list(HWND hwndList) { LVITEM lvI; int i = 0; - char s[256], t; + char s[256], *t; WCHAR szText[256]; lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; From 21974c5fc5ad02000c2920503bfde003d2f30bde Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 01:05:54 +0100 Subject: [PATCH 127/177] Fixed an uninitialized variable in the Toshiba T1x00 code. --- src/machine/m_xt_t1000.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/machine/m_xt_t1000.c b/src/machine/m_xt_t1000.c index 3471b0c12..fc0205552 100644 --- a/src/machine/m_xt_t1000.c +++ b/src/machine/m_xt_t1000.c @@ -240,6 +240,7 @@ tc8521_time_get(uint8_t *regs, struct tm *tm) tm->tm_hour = ((nibbles(TC8521_HOUR) % 12) + (regs[TC8521_HOUR10] & 0x02) ? 12 : 0); //FIXME: wday + tm->tm_wday = 1; /* Dummy value so it is not uninitialized. */ tm->tm_mday = nibbles(TC8521_DAY); tm->tm_mon = (nibbles(TC8521_MONTH) - 1); tm->tm_year = (nibbles(TC8521_YEAR) + 1980); From 171cc75b1ec175125a8aaea61935a7b25fa77dd2 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 01:07:06 +0100 Subject: [PATCH 128/177] Fixed another potential overrun in win/win_settings.c. --- src/win/win_settings.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/win/win_settings.c b/src/win/win_settings.c index 8b9dff3c8..84d257b34 100644 --- a/src/win/win_settings.c +++ b/src/win/win_settings.c @@ -3731,7 +3731,7 @@ static void win_settings_floppy_drives_update_item(HWND hwndList, int i) { LVITEM lvI; - char s[256]; + char s[256], *t; WCHAR szText[256]; lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; @@ -3741,7 +3741,11 @@ win_settings_floppy_drives_update_item(HWND hwndList, int i) lvI.iItem = i; if (temp_fdd_types[i] > 0) { - strcpy(s, fdd_getname(temp_fdd_types[i])); + t = fdd_getname(temp_fdd_types[i]); + if (strlen(t) <= 256) + strcpy(s, t); + else + strncpy(s, t, 256); mbstowcs(szText, s, strlen(s) + 1); lvI.pszText = szText; } else From 47b61d5c42c4557e18df6d520cd9328a61617aa4 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 01:09:23 +0100 Subject: [PATCH 129/177] Added a sanity fatal() to the x54x SCSI controller famility code. --- src/scsi/scsi_x54x.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/scsi/scsi_x54x.c b/src/scsi/scsi_x54x.c index cd4edbf79..4bced9593 100644 --- a/src/scsi/scsi_x54x.c +++ b/src/scsi/scsi_x54x.c @@ -260,6 +260,11 @@ x54x_bios_scsi_command(scsi_device_t *dev, uint8_t *cdb, uint8_t *buf, int len, return(completion_code(scsi_device_sense(dev))); if (len > 0) { + if (dev->buffer_length == -1) { + fatal("Buffer length -1 when doing SCSI DMA\n"); + return(0xff); + } + if (dev->phase == SCSI_PHASE_DATA_IN) { if (buf) memcpy(buf, dev->sc->temp_buffer, dev->buffer_length); From 9347986ebee3d88b6b932a54c1fce572ee008428 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 01:10:41 +0100 Subject: [PATCH 130/177] Fixed the dynamic DLL load code to use the correct API call to free the library. --- src/win/win_dynld.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/win/win_dynld.c b/src/win/win_dynld.c index 6043e36d6..e258ebe19 100644 --- a/src/win/win_dynld.c +++ b/src/win/win_dynld.c @@ -65,7 +65,7 @@ dynld_module(const char *name, dllimp_t *table) if (func == NULL) { dynld_log("DynLd(\"%s\"): function '%s' not found!\n", name, imp->name); - CloseHandle(h); + FreeLibrary(h); return(NULL); } From cdac8c1c11f4744c27bf5db20ecc1613da82dd91 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 02:10:52 +0100 Subject: [PATCH 131/177] Fixed win/win.c to not NULL-check that which is not NULL. --- src/win/win.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/win/win.c b/src/win/win.c index a9aec2a81..57d3412fd 100644 --- a/src/win/win.c +++ b/src/win/win.c @@ -336,8 +336,7 @@ ProcessCommandLine(wchar_t ***argw) args[argc] = NULL; *argw = args; - if (argbuf != NULL) - free(argbuf); + free(argbuf); return(argc); } From d861198960c72bebe3e7c0f31a326fe1e50884b6 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 02:12:29 +0100 Subject: [PATCH 132/177] Fixed an overrun in config.c. --- src/config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.c b/src/config.c index c9816e170..e8a9992b7 100644 --- a/src/config.c +++ b/src/config.c @@ -2176,7 +2176,7 @@ config_set_string(char *head, char *name, char *val) ent = create_entry(section, name); memcpy(ent->data, val, sizeof(ent->data)); - mbstowcs(ent->wdata, ent->data, sizeof(ent->wdata)); + mbstowcs(ent->wdata, ent->data, sizeof_w(ent->wdata)); } From 030059701b89290cec998190821ef03fab8373d3 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 02:14:44 +0100 Subject: [PATCH 133/177] Fixed an overrun in the PostScript printer code. --- src/printer/prt_ps.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/printer/prt_ps.c b/src/printer/prt_ps.c index 4a14f4378..92ce3d83c 100644 --- a/src/printer/prt_ps.c +++ b/src/printer/prt_ps.c @@ -271,13 +271,13 @@ static void process_data(ps_t *dev) { if (dev->data < 0x20 || dev->data == 0x7F) { - if (process_nonprintable(dev)) { + if (process_nonprintable(dev)) return; - } } if (dev->buffer_pos == POSTSCRIPT_BUFFER_LENGTH) { write_buffer(dev, false); + dev->buffer_pos = 0; } dev->buffer[dev->buffer_pos++] = dev->data; From d21ea095550c560758c4cb5e07b60a4284e7a3dd Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 02:15:42 +0100 Subject: [PATCH 134/177] Fixed two more overruns in config.c. --- src/config.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config.c b/src/config.c index e8a9992b7..e33eabac8 100644 --- a/src/config.c +++ b/src/config.c @@ -2099,7 +2099,7 @@ config_set_int(char *head, char *name, int val) ent = create_entry(section, name); sprintf(ent->data, "%i", val); - mbstowcs(ent->wdata, ent->data, sizeof(ent->wdata)); + mbstowcs(ent->wdata, ent->data, sizeof_w(ent->wdata)); } @@ -2118,7 +2118,7 @@ config_set_hex16(char *head, char *name, int val) ent = create_entry(section, name); sprintf(ent->data, "%04X", val); - mbstowcs(ent->wdata, ent->data, sizeof(ent->wdata)); + mbstowcs(ent->wdata, ent->data, sizeof_w(ent->wdata)); } From 9f9883f8da5fd599b40c85536794f8da1aa424ce Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 02:16:25 +0100 Subject: [PATCH 135/177] Fixed a maintainability issue in the CD-ROM image backend code. --- src/cdrom/cdrom_image_backend.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cdrom/cdrom_image_backend.c b/src/cdrom/cdrom_image_backend.c index de6f83f12..c0f57e810 100644 --- a/src/cdrom/cdrom_image_backend.c +++ b/src/cdrom/cdrom_image_backend.c @@ -798,6 +798,8 @@ cdi_load_cue(cd_img_t *cdi, const wchar_t *cuefile) success = cdi_add_track(cdi, &trk, &shift, prestart, &total_pregap, cur_pregap); else success = 1; + if (!success) + break; trk.start = 0; trk.skip = 0; From 1464c0631bf15473c30ad955e6de59cfbd307e77 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 02:18:28 +0100 Subject: [PATCH 136/177] Fixed potential NULL pointer dereferences in the CD-ROM and Iomega ZIP codes. --- src/disk/zip.c | 3 ++- src/scsi/scsi_cdrom.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/disk/zip.c b/src/disk/zip.c index 8c03f861a..85f4e677f 100644 --- a/src/disk/zip.c +++ b/src/disk/zip.c @@ -866,7 +866,8 @@ zip_bus_speed(zip_t *dev) if (dev && dev->drv) ret = ide_atapi_get_period(dev->drv->ide_channel); if (ret == -1.0) { - dev->callback = -1.0; + if (dev) + dev->callback = -1.0; return 0.0; } else return ret * 1000000.0; diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index 3667567fc..cb3895a4c 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -613,7 +613,8 @@ scsi_cdrom_bus_speed(scsi_cdrom_t *dev) if (dev && dev->drv) ret = ide_atapi_get_period(dev->drv->ide_channel); if (ret == -1.0) { - dev->callback = -1.0; + if (dev) + dev->callback = -1.0; return 0.0; } else return ret * 1000000.0; From f5794eba11c91411ae3a0469b3a60faca8d1e5dd Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 02:19:38 +0100 Subject: [PATCH 137/177] Fixed code resulting in potentially non-NULL-terminated strings in the Discord support code. --- src/win/win_discord.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/win/win_discord.c b/src/win/win_discord.c index 4a2cb3e63..926c20df2 100644 --- a/src/win/win_discord.c +++ b/src/win/win_discord.c @@ -92,10 +92,10 @@ discord_update_activity(int paused) else { temp = strchr(machine_getname(), ']') + 2; - if (strlen(temp) <= 128) + if (strlen(temp) <= 127) strcpy(activity.details, temp); else - strncpy(activity.details, temp, 128); + strncpy(activity.details, temp, 127); strcpy(activity.state, machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].name); } From ae9f8fb639f7459cc5c270750f27b8fe2e1ccef7 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 02:20:55 +0100 Subject: [PATCH 138/177] Fixed a potential NULL pointer dereference in the SCAT code. --- src/chipset/scat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chipset/scat.c b/src/chipset/scat.c index 5ffa3722a..fce0e772b 100644 --- a/src/chipset/scat.c +++ b/src/chipset/scat.c @@ -1354,7 +1354,7 @@ mem_write_scatb(uint32_t addr, uint8_t val, void *priv) } if (chkaddr >= 0xc0000 && chkaddr < 0x100000) { - if (dev->regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xc0000) >> 15))) + if ((dev == NULL) || (dev->regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xc0000) >> 15)))) return; } From bb3c5a6f521b9aa0ab95d57dfb97cd777609fb07 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 02:22:30 +0100 Subject: [PATCH 139/177] Fixed a potential overrun in the CD-ROM image backend code. --- src/cdrom/cdrom_image_backend.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cdrom/cdrom_image_backend.c b/src/cdrom/cdrom_image_backend.c index c0f57e810..cb6fd5f82 100644 --- a/src/cdrom/cdrom_image_backend.c +++ b/src/cdrom/cdrom_image_backend.c @@ -149,10 +149,10 @@ bin_init(const wchar_t *filename, int *error) } memset(tf->fn, 0x00, sizeof(tf->fn)); - if (wcslen(tf->fn) > 260) - wcsncpy(tf->fn, filename, 260); - else + if (wcslen(filename) <= 260) wcscpy(tf->fn, filename); + else + wcsncpy(tf->fn, filename, 260); tf->file = plat_fopen64(tf->fn, L"rb"); cdrom_image_backend_log("CDROM: binary_open(%ls) = %08lx\n", tf->fn, tf->file); From f3317c9d9591f4febe02dde120f35dc977aebaee Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 02:24:12 +0100 Subject: [PATCH 140/177] Fixed another potential overrun in the Discord support code. --- src/win/win_discord.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/win/win_discord.c b/src/win/win_discord.c index 926c20df2..c174413a8 100644 --- a/src/win/win_discord.c +++ b/src/win/win_discord.c @@ -92,11 +92,16 @@ discord_update_activity(int paused) else { temp = strchr(machine_getname(), ']') + 2; + if (strlen(temp) <= 127) strcpy(activity.details, temp); else strncpy(activity.details, temp, 127); - strcpy(activity.state, machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].name); + + if (strlen(machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].name) <= 127) + strcpy(activity.state, machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].name); + else + strncpy(activity.state, machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].name, 127); } activity.timestamps.start = time(NULL); From d8e9d19cf4684a98f9cebf168712b833d47348b0 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 02:26:28 +0100 Subject: [PATCH 141/177] Added a sanity fatal() to the SST Flash code. --- src/sst_flash.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sst_flash.c b/src/sst_flash.c index 5f0fc27f8..3dc151294 100644 --- a/src/sst_flash.c +++ b/src/sst_flash.c @@ -264,7 +264,8 @@ sst_39sf010_init(const device_t *info) f = nvr_fopen(flash_path, L"rb"); if (f) { - fread(&(dev->array[0x00000]), 0x20000, 1, f); + if (fread(&(dev->array[0x00000]), 1, 0x20000, f) != 0x20000) + fatal("Less than 131072 bytes read from the SST Flash ROM file\n"); fclose(f); } From c5ac252eb165b8ebf3da30944505af78b5679cbf Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 02:28:24 +0100 Subject: [PATCH 142/177] Fixed two integer handling issues in the AMD PCnet code. --- src/network/net_pcnet.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/network/net_pcnet.c b/src/network/net_pcnet.c index 3b53da687..49de94317 100644 --- a/src/network/net_pcnet.c +++ b/src/network/net_pcnet.c @@ -907,6 +907,24 @@ pcnetInit(nic_t *dev) dev->GCTDRA = PHYSADDR(dev, initblk.tdra); \ } while (0) +#define PCNET_INIT16() do { \ + DMAPageRead(PHYSADDR(dev, CSR_IADR(dev)), \ + (uint8_t *)&initblk, sizeof(initblk)); \ + dev->aCSR[15] = le32_to_cpu(initblk.mode); \ + CSR_RCVRL(dev) = (1 << initblk.rlen); \ + CSR_XMTRL(dev) = (1 << initblk.tlen); \ + dev->aCSR[ 6] = (initblk.tlen << 12) | (initblk.rlen << 8); \ + dev->aCSR[ 8] = le32_to_cpu(initblk.ladrf1); \ + dev->aCSR[ 9] = le32_to_cpu(initblk.ladrf2); \ + dev->aCSR[10] = le32_to_cpu(initblk.ladrf3); \ + dev->aCSR[11] = le32_to_cpu(initblk.ladrf4); \ + dev->aCSR[12] = le32_to_cpu(initblk.padr1); \ + dev->aCSR[13] = le32_to_cpu(initblk.padr2); \ + dev->aCSR[14] = le32_to_cpu(initblk.padr3); \ + dev->GCRDRA = PHYSADDR(dev, initblk.rdra); \ + dev->GCTDRA = PHYSADDR(dev, initblk.tdra); \ +} while (0) + if (BCR_SSIZE32(dev)) { struct INITBLK32 initblk; dev->GCUpperPhys = 0; @@ -916,7 +934,7 @@ pcnetInit(nic_t *dev) } else { struct INITBLK16 initblk; dev->GCUpperPhys = (0xff00 & (uint32_t)dev->aCSR[2]) << 16; - PCNET_INIT(); + PCNET_INIT16(); pcnetlog(3, "%s: initblk.rlen=%#04x, initblk.tlen=%#04x\n", dev->name, initblk.rlen, initblk.tlen); } From 05515187ee346b80001b9436251ce4c2490605d5 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 02:31:52 +0100 Subject: [PATCH 143/177] Various sanity measures in the Floppy image and TeleDisk codes. --- src/floppy/fdd_img.c | 3 ++- src/floppy/fdd_td0.c | 17 +++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/floppy/fdd_img.c b/src/floppy/fdd_img.c index 5e0bfaacd..f040d2086 100644 --- a/src/floppy/fdd_img.c +++ b/src/floppy/fdd_img.c @@ -1103,7 +1103,8 @@ jump_if_fdf: /* The BPB readings appear to be valid, so let's set the values. */ if (fdi) { /* The image is a Japanese FDI, therefore we read the number of tracks from the header. */ - fseek(dev->f, 0x1C, SEEK_SET); + if (fseek(dev->f, 0x1C, SEEK_SET) == -1) + fatal("Japanese FDI: Failed when seeking to 0x1C\n"); fread(&(dev->tracks), 1, 4, dev->f); } else { if (!cqm && !fdf) { diff --git a/src/floppy/fdd_td0.c b/src/floppy/fdd_td0.c index fd4d4419f..6762f78f5 100644 --- a/src/floppy/fdd_td0.c +++ b/src/floppy/fdd_td0.c @@ -260,7 +260,8 @@ state_data_read(td0dsk_t *state, uint8_t *buf, uint16_t size) image_size = ftell(state->fdd_file); if (size > image_size - state->fdd_file_offset) size = (image_size - state->fdd_file_offset) & 0xffff; - fseek(state->fdd_file, state->fdd_file_offset, SEEK_SET); + if (fseek(state->fdd_file, state->fdd_file_offset, SEEK_SET) == -1) + fatal("TD0: Failed to seek in state_data_read()\n"); fread(buf, 1, size, state->fdd_file); state->fdd_file_offset += size; @@ -904,15 +905,15 @@ static void set_sector(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n) { td0_t *dev = td0[drive]; - int i = 0; + int i = 0, cyl = c; dev->current_sector_index[side] = 0; - if (c != dev->track) return; - for (i = 0; i < dev->track_spt[c][side]; i++) { - if ((dev->sects[c][side][i].track == c) && - (dev->sects[c][side][i].head == h) && - (dev->sects[c][side][i].sector == r) && - (dev->sects[c][side][i].size == n)) { + if (cyl != dev->track) return; + for (i = 0; i < dev->track_spt[cyl][side]; i++) { + if ((dev->sects[cyl][side][i].track == c) && + (dev->sects[cyl][side][i].head == h) && + (dev->sects[cyl][side][i].sector == r) && + (dev->sects[cyl][side][i].size == n)) { dev->current_sector_index[side] = i; } } From 772a62827839a7e6055c9065ab7e267182d6c373 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 02:34:50 +0100 Subject: [PATCH 144/177] Added a sanity check to the PGC code. --- src/video/vid_pgc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/video/vid_pgc.c b/src/video/vid_pgc.c index e0bceb8dd..954157b18 100644 --- a/src/video/vid_pgc.c +++ b/src/video/vid_pgc.c @@ -862,7 +862,8 @@ pgc_fill_polygon(pgc_t *dev, unsigned corners, int32_t *x, int32_t *y) pgc_log("PGC: fill_polygon(%i corners)\n", corners); - if (corners < 2) return; /* Degenerate polygon */ + if (!x || !y || (corners < 2)) + return; /* Degenerate polygon */ nodex = (double *)malloc(corners * sizeof(double)); dx = (double *)malloc(corners * sizeof(double)); From df1617f4ef5f0ae3406dd7ae49685d341347ed4d Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 02:35:47 +0100 Subject: [PATCH 145/177] Added a sanity check to the MFM image code. --- src/floppy/fdd_mfm.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/floppy/fdd_mfm.c b/src/floppy/fdd_mfm.c index 879bc200e..c2062baad 100644 --- a/src/floppy/fdd_mfm.c +++ b/src/floppy/fdd_mfm.c @@ -338,7 +338,7 @@ mfm_read_side(int drive, int side) { mfm_t *dev = mfm[drive]; int track_index, track_size; - int track_bytes; + int track_bytes, ret; if (dev->hdr.if_type & 0x80) track_index = get_adv_track_index(drive, side, dev->cur_track); @@ -354,9 +354,11 @@ mfm_read_side(int drive, int side) memset(dev->track_data[side], 0x00, track_bytes); else { if (dev->hdr.if_type & 0x80) - fseek(dev->f, dev->adv_tracks[track_index].track_offset, SEEK_SET); + ret = fseek(dev->f, dev->adv_tracks[track_index].track_offset, SEEK_SET); else - fseek(dev->f, dev->tracks[track_index].track_offset, SEEK_SET); + ret = fseek(dev->f, dev->tracks[track_index].track_offset, SEEK_SET); + if (ret == -1) + fatal("MFM: Error seeking in mfm_read_side()\n"); fread(dev->track_data[side], 1, track_bytes, dev->f); } From e60b74e33b861b3781e88a5c48dd0fc9fbb75bda Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 02:37:36 +0100 Subject: [PATCH 146/177] Added a sanity check to the video code. --- src/video/video.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/video/video.c b/src/video/video.c index 7d87c5382..35ca81a33 100644 --- a/src/video/video.c +++ b/src/video/video.c @@ -910,7 +910,7 @@ void loadfont(wchar_t *s, int format) { FILE *f; - int c,d; + int c, d; f = rom_fopen(s, L"rb"); if (f == NULL) @@ -1013,8 +1013,10 @@ loadfont(wchar_t *s, int format) fseek(f, 8, SEEK_CUR); } /* The second 4k holds an 8x16 font */ - for (c = 0; c < 256; c++) - fread(&fontdatm[c][0], 1, 16, f); + for (c = 0; c < 256; c++) { + if (fread(&fontdatm[c][0], 1, 16, f) != 16) + fatal("loadfont(): Error reading font file in Sigma Coloar 400 mdoe, c = %i\n", c); + } break; case 8: /* Amstrad PC1512, Toshiba T1000/T1200 */ From a2867e697898edd0486d266ce6d70d9462c8109a Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 02:43:25 +0100 Subject: [PATCH 147/177] Added fall-through comments to several fall-throughs. --- src/cpu/cpu.c | 1 + src/cpu_new/cpu.c | 1 + src/disk/hdc_ide.c | 2 ++ src/scsi/scsi_buslogic.c | 1 + src/scsi/scsi_cdrom.c | 2 ++ src/scsi/scsi_disk.c | 1 + src/sound/snd_gus.c | 2 ++ src/video/vid_ati_mach64.c | 1 + 8 files changed, 11 insertions(+) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 891790823..3e6f9b0e8 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -734,6 +734,7 @@ cpu_set(void) case CPU_iDX4: cpu_features = CPU_FEATURE_CR4 | CPU_FEATURE_VME; cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_VME; + /*FALLTHROUGH*/ case CPU_i486SX: case CPU_i486DX: #ifdef USE_DYNAREC diff --git a/src/cpu_new/cpu.c b/src/cpu_new/cpu.c index 26b790dc4..1d2c0fb19 100644 --- a/src/cpu_new/cpu.c +++ b/src/cpu_new/cpu.c @@ -739,6 +739,7 @@ cpu_set(void) case CPU_iDX4: cpu_features = CPU_FEATURE_CR4 | CPU_FEATURE_VME; cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_VME; + /*FALLTHROUGH*/ case CPU_i486SX: case CPU_i486DX: #ifdef USE_DYNAREC diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index b86605761..c0250adc6 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -1459,6 +1459,7 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) /* Turn on the activity indicator *here* so that it gets turned on less times. */ ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); + /*FALLTHROUGH*/ case WIN_READ: case WIN_READ_NORETRY: @@ -1492,6 +1493,7 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) /* Turn on the activity indicator *here* so that it gets turned on less times. */ ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); + /*FALLTHROUGH*/ case WIN_WRITE: case WIN_WRITE_NORETRY: diff --git a/src/scsi/scsi_buslogic.c b/src/scsi/scsi_buslogic.c index 15a4dc7d4..0f3141485 100644 --- a/src/scsi/scsi_buslogic.c +++ b/src/scsi/scsi_buslogic.c @@ -1250,6 +1250,7 @@ BuslogicPCIWrite(int func, int addr, uint8_t val, void *p) case 0x14: val &= 0xe0; + /*FALLTHROUGH*/ case 0x15: case 0x16: case 0x17: /* MMIO Base set. */ diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index cb3895a4c..cbe32f15a 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -1537,6 +1537,8 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) /* IMPORTANT: Convert the command to new read CD for pass through purposes. */ dev->current_cdb[0] = 0xbe; + /*FALLTHROUGH*/ + case GPCMD_READ_6: case GPCMD_READ_10: case GPCMD_READ_12: diff --git a/src/scsi/scsi_disk.c b/src/scsi/scsi_disk.c index 6203a7ac4..741fc04d4 100644 --- a/src/scsi/scsi_disk.c +++ b/src/scsi/scsi_disk.c @@ -613,6 +613,7 @@ scsi_disk_command(scsi_common_t *sc, uint8_t *cdb) scsi_disk_invalid_field(dev); return; } + /*FALLTHROUGH*/ case GPCMD_SCSI_RESERVE: case GPCMD_SCSI_RELEASE: case GPCMD_TEST_UNIT_READY: diff --git a/src/sound/snd_gus.c b/src/sound/snd_gus.c index 1f8fcfd3b..3df40d2a0 100644 --- a/src/sound/snd_gus.c +++ b/src/sound/snd_gus.c @@ -619,6 +619,7 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8); else if (gus->irq != 0) picint(1 << gus->irq); } + /*FALLTHROUGH*/ case 0x20d: gus->sb_2xc = val; break; @@ -820,6 +821,7 @@ uint8_t readgus(uint16_t addr, void *p) case 0x209: gus->ad_status &= ~0x01; nmi = 0; + /*FALLTHROUGH*/ case 0x389: val = gus->ad_data; break; diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c index 03f7309f3..9f29c162b 100644 --- a/src/video/vid_ati_mach64.c +++ b/src/video/vid_ati_mach64.c @@ -1993,6 +1993,7 @@ uint8_t mach64_ext_readb(uint32_t addr, void *p) break; case 0x2a4: case 0x2a5: addr += 2; + /*FALLTHROUGH*/ case 0x2aa: case 0x2ab: mach64_wait_fifo_idle(mach64); READ8(addr, mach64->sc_left_right); From 714d77deddd72cd6efa2af024af0a0340e616816 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 02:46:16 +0100 Subject: [PATCH 148/177] Fixed a double free in the FDI2RAW code. --- src/floppy/fdi2raw.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/floppy/fdi2raw.c b/src/floppy/fdi2raw.c index 5cbbd9a0c..03ddf460f 100644 --- a/src/floppy/fdi2raw.c +++ b/src/floppy/fdi2raw.c @@ -326,7 +326,9 @@ static void fdi_decode (uae_u8 *stream, int size, uae_u8 *out) ((uae_u32*)out)[i] = v; } free_nodes (root.left); + root.left = 0; free_nodes (root.right); + root.right = 0; } } From 874977614411a0e1cd0e60ff57d49e21819ff3d5 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 03:04:59 +0100 Subject: [PATCH 149/177] Fixed the first batch of problems. --- src/config.c | 12 +++++++++++- src/disk/hdd_image.c | 5 ++++- src/floppy/fdd_86f.c | 18 ++++++++++++------ src/floppy/fdd_img.c | 20 ++++++++++++++------ src/machine/m_tandy.c | 3 ++- src/machine/m_xt.c | 8 ++++---- src/nvr_ps2.c | 3 ++- src/video/vid_ati_eeprom.c | 10 ++++++---- src/video/vid_pgc.c | 8 ++++++-- src/video/vid_tgui9440.c | 1 + 10 files changed, 62 insertions(+), 26 deletions(-) diff --git a/src/config.c b/src/config.c index e33eabac8..3bcd6dbea 100644 --- a/src/config.c +++ b/src/config.c @@ -566,6 +566,7 @@ load_video(void) { char *cat = "Video"; char *p; + int free_p = 0; if (machines[machine].flags & MACHINE_VIDEO_FIXED) { config_delete_var(cat, "gfxcard"); @@ -580,8 +581,11 @@ load_video(void) p = (char *)malloc((strlen("none")+1)*sizeof(char)); strcpy(p, "none"); } + free_p = 1; } gfxcard = video_get_video_from_internal_name(p); + if (free_p) + free(p); } voodoo_enabled = !!config_get_int(cat, "voodoo", 0); @@ -763,7 +767,7 @@ load_other_peripherals(void) char *cat = "Other peripherals"; char *p; char temp[512]; - int c; + int c, free_p = 0; p = config_get_string(cat, "scsicard", NULL); if (p != NULL) @@ -780,6 +784,7 @@ load_other_peripherals(void) p = (char *)malloc((strlen("none")+1)*sizeof(char)); strcpy(p, "none"); } + free_p = 1; } if (!strcmp(p, "mfm_xt")) hdc_current = hdc_get_from_internal_name("st506_xt"); @@ -790,6 +795,11 @@ load_other_peripherals(void) else hdc_current = hdc_get_from_internal_name(p); + if (free_p) { + free(p); + p = NULL; + } + ide_ter_enabled = !!config_get_int(cat, "ide_ter", 0); ide_qua_enabled = !!config_get_int(cat, "ide_qua", 0); diff --git a/src/disk/hdd_image.c b/src/disk/hdd_image.c index 63d140014..5a84116eb 100644 --- a/src/disk/hdd_image.c +++ b/src/disk/hdd_image.c @@ -166,7 +166,10 @@ image_is_vhd(const wchar_t *s, int check_signature) return 0; fseeko64(f, 0, SEEK_END); filelen = ftello64(f); - fseeko64(f, -512, SEEK_END); + if (fseeko64(f, -512, SEEK_END) == -1) { + fclose(f); + fatal("image_is_vhd(): Error seeking\n"); + } if (filelen < 512) { if (f != NULL) fclose(f); diff --git a/src/floppy/fdd_86f.c b/src/floppy/fdd_86f.c index 4fb68c606..797d6bf80 100644 --- a/src/floppy/fdd_86f.c +++ b/src/floppy/fdd_86f.c @@ -3779,10 +3779,13 @@ d86f_load(int drive, wchar_t *fn) } /* Load track 0 flags as default. */ - fseek(dev->f, dev->track_offset[0], SEEK_SET); - fread(&(dev->side_flags[0]), 2, 1, dev->f); + if (fseek(dev->f, dev->track_offset[0], SEEK_SET) == -1) + fatal("d86f_load(): Track 0: Error seeking to the beginning of the file\n"); + if (fread(&(dev->side_flags[0]), 1, 2, dev->f) != 2) + fatal("d86f_load(): Track 0: Error reading side flags\n"); if (dev->disk_flags & 0x80) { - fread(&(dev->extra_bit_cells[0]), 4, 1, dev->f); + if (fread(&(dev->extra_bit_cells[0]), 1, 4, dev->f) != 4) + fatal("d86f_load(): Track 0: Error reading the amount of extra bit cells\n"); if ((dev->disk_flags & 0x1060) != 0x1000) { if (dev->extra_bit_cells[0] < -32768) dev->extra_bit_cells[0] = -32768; if (dev->extra_bit_cells[0] > 32768) dev->extra_bit_cells[0] = 32768; @@ -3792,10 +3795,13 @@ d86f_load(int drive, wchar_t *fn) } if (d86f_get_sides(drive) == 2) { - fseek(dev->f, dev->track_offset[1], SEEK_SET); - fread(&(dev->side_flags[1]), 2, 1, dev->f); + if (fseek(dev->f, dev->track_offset[1], SEEK_SET) == -1) + fatal("d86f_load(): Track 1: Error seeking to the beginning of the file\n"); + if (fread(&(dev->side_flags[1]), 1, 2, dev->f) != 2) + fatal("d86f_load(): Track 1: Error reading side flags\n"); if (dev->disk_flags & 0x80) { - fread(&(dev->extra_bit_cells[1]), 4, 1, dev->f); + if (fread(&(dev->extra_bit_cells[1]), 1, 4, dev->f) != 4) + fatal("d86f_load(): Track 4: Error reading the amount of extra bit cells\n"); if ((dev->disk_flags & 0x1060) != 0x1000) { if (dev->extra_bit_cells[1] < -32768) dev->extra_bit_cells[1] = -32768; if (dev->extra_bit_cells[1] > 32768) dev->extra_bit_cells[1] = 32768; diff --git a/src/floppy/fdd_img.c b/src/floppy/fdd_img.c index f040d2086..6d0c626dc 100644 --- a/src/floppy/fdd_img.c +++ b/src/floppy/fdd_img.c @@ -393,15 +393,19 @@ write_back(int drive) { img_t *dev = img[drive]; int ssize = 128 << ((int) dev->sector_size); - int side; + int side, size; if (dev->f == NULL) return; if (dev->disk_at_once) return; - fseek(dev->f, dev->base + (dev->track * dev->sectors * ssize * dev->sides), SEEK_SET); - for (side = 0; side < dev->sides; side++) - fwrite(dev->track_data[side], dev->sectors * ssize, 1, dev->f); + if (fseek(dev->f, dev->base + (dev->track * dev->sectors * ssize * dev->sides), SEEK_SET) == -1) + pclog("IMG write_back(): Error seeking to the beginning of the file\n"); + for (side = 0; side < dev->sides; side++) { + size = dev->sectors * ssize; + if (fwrite(dev->track_data[side], 1, size, dev->f) != size) + fatal("IMG write_back(): Error writing data\n"); + } } @@ -1156,8 +1160,12 @@ jump_if_fdf: dev->gap2_size = (temp_rate == 3) ? 41 : 22; if (dev->dmf) dev->gap3_size = 8; - else - dev->gap3_size = gap3_sizes[temp_rate][dev->sector_size][dev->sectors]; + else { + if (dev->sectors == -1) + dev->gap3_size = 8; + else + dev->gap3_size = gap3_sizes[temp_rate][dev->sector_size][dev->sectors]; + } if (! dev->gap3_size) { img_log("ERROR: Floppy image of unknown format was inserted into drive %c:!\n", drive + 0x41); fclose(dev->f); diff --git a/src/machine/m_tandy.c b/src/machine/m_tandy.c index 3dbc65748..4a578d3b6 100644 --- a/src/machine/m_tandy.c +++ b/src/machine/m_tandy.c @@ -1293,7 +1293,8 @@ eep_init(const device_t *info) f = nvr_fopen(eep->path, L"rb"); if (f != NULL) { - fread(eep->store, 128, 1, f); + if (fread(eep->store, 1, 128, f) != 128) + fatal("eep_init(): Error reading Tandy EEPROM\n"); (void)fclose(f); } diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index 22a01c882..0366517d1 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -157,10 +157,10 @@ machine_xt86_init(const machine_t *model) ret = bios_load_linear(L"roms/machines/ibmxt86/BIOS_5160_09MAY86_U18_59X7268_62X0890_27256_F800.BIN", 0x000fe000, 65536, 0x6000); if (ret) { - bios_load_aux_linear(L"roms/machines/ibmxt86/BIOS_5160_09MAY86_U18_59X7268_62X0890_27256_F800.BIN", - 0x000f8000, 24576, 0); - bios_load_aux_linear(L"roms/machines/ibmxt86/BIOS_5160_09MAY86_U19_62X0819_68X4370_27256_F000.BIN", - 0x000f0000, 32768, 0); + (void) bios_load_aux_linear(L"roms/machines/ibmxt86/BIOS_5160_09MAY86_U18_59X7268_62X0890_27256_F800.BIN", + 0x000f8000, 24576, 0); + (void) bios_load_aux_linear(L"roms/machines/ibmxt86/BIOS_5160_09MAY86_U19_62X0819_68X4370_27256_F000.BIN", + 0x000f0000, 32768, 0); } if (bios_only || !ret) diff --git a/src/nvr_ps2.c b/src/nvr_ps2.c index 5c943a0eb..c98d12e77 100644 --- a/src/nvr_ps2.c +++ b/src/nvr_ps2.c @@ -128,7 +128,8 @@ ps2_nvr_init(const device_t *info) memset(nvr->ram, 0xff, 8192); if (f != NULL) { - (void)fread(nvr->ram, 8192, 1, f); + if (fread(nvr->ram, 1, 8192, f) != 8192) + fatal("ps2_nvr_init(): Error reading EEPROM data\n"); fclose(f); } diff --git a/src/video/vid_ati_eeprom.c b/src/video/vid_ati_eeprom.c index f1fb0753f..00e193913 100644 --- a/src/video/vid_ati_eeprom.c +++ b/src/video/vid_ati_eeprom.c @@ -58,18 +58,20 @@ enum void ati_eeprom_load(ati_eeprom_t *eeprom, wchar_t *fn, int type) { FILE *f; + int size; eeprom->type = type; if (wcslen(fn) <= 256) wcscpy(eeprom->fn, fn); else wcsncpy(eeprom->fn, fn, 256); f = nvr_fopen(eeprom->fn, L"rb"); - if (!f) - { - memset(eeprom->data, 0, eeprom->type ? 512 : 128); + int size = eeprom->type ? 512 : 128; + if (!f) { + memset(eeprom->data, 0, size); return; } - fread(eeprom->data, 1, eeprom->type ? 512 : 128, f); + if (fread(eeprom->data, 1, size, f) != size) + memset(eeprom->data, 0, size); fclose(f); } diff --git a/src/video/vid_pgc.c b/src/video/vid_pgc.c index 954157b18..4ffb62a30 100644 --- a/src/video/vid_pgc.c +++ b/src/video/vid_pgc.c @@ -2065,8 +2065,12 @@ pgc_parse_coords(pgc_t *dev, pgc_cl_t *cl, int count) return 0; } - for (n = 0; n < count; n++) - if (! pgc_param_coord(dev, ¶m[n])) return 0; + for (n = 0; n < count; n++) { + if (! pgc_param_coord(dev, ¶m[n])) { + free(param); + return 0; + } + } /* Here is how the real PGC serializes coords: * diff --git a/src/video/vid_tgui9440.c b/src/video/vid_tgui9440.c index c366fae12..a80ea293f 100644 --- a/src/video/vid_tgui9440.c +++ b/src/video/vid_tgui9440.c @@ -308,6 +308,7 @@ void tgui_out(uint16_t addr, uint8_t val, void *p) } return; } + /*FALLTHROUGH*/ case 0x3C7: case 0x3C8: case 0x3C9: if (tgui->type == TGUI_9400CXI) { From fab0a368f1ce4ad39354fdbfd2c3877d1562b5a3 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 03:06:16 +0100 Subject: [PATCH 150/177] Fixed a newly introduced bug. --- src/video/vid_ati_eeprom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vid_ati_eeprom.c b/src/video/vid_ati_eeprom.c index 00e193913..c7debfcf2 100644 --- a/src/video/vid_ati_eeprom.c +++ b/src/video/vid_ati_eeprom.c @@ -65,7 +65,7 @@ void ati_eeprom_load(ati_eeprom_t *eeprom, wchar_t *fn, int type) else wcsncpy(eeprom->fn, fn, 256); f = nvr_fopen(eeprom->fn, L"rb"); - int size = eeprom->type ? 512 : 128; + size = eeprom->type ? 512 : 128; if (!f) { memset(eeprom->data, 0, size); return; From af023ff5dd0d791d70792e9a0dfd7152c5edf7bf Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 03:48:33 +0100 Subject: [PATCH 151/177] Fixed the second batch of problems --- src/chipset/scat.c | 13 ++++----- src/disk/hdc_st506_xt.c | 3 +- src/disk/hdd_image.c | 60 ++++++++++++++++++++++++++-------------- src/disk/zip.c | 15 ++++++---- src/floppy/fdd_86f.c | 19 +++++++++---- src/floppy/fdd_imd.c | 15 ++++++---- src/floppy/fdd_mfm.c | 14 +++++++--- src/floppy/fdd_td0.c | 3 +- src/floppy/fdi2raw.c | 8 ++++-- src/rom.c | 15 ++++++---- src/scsi/scsi_cdrom.c | 3 +- src/video/vid_ati18800.c | 1 + src/video/vid_im1024.c | 4 +++ src/video/video.c | 14 ++++++---- 14 files changed, 123 insertions(+), 64 deletions(-) diff --git a/src/chipset/scat.c b/src/chipset/scat.c index fce0e772b..79f18d396 100644 --- a/src/chipset/scat.c +++ b/src/chipset/scat.c @@ -1056,17 +1056,14 @@ scat_out(uint16_t port, uint8_t val, void *priv) break; case SCAT_EMS_CONTROL: + io_removehandler(0x0208, 0x0003, scat_in, NULL, NULL, scat_out, NULL, NULL, dev); + io_removehandler(0x0218, 0x0003, scat_in, NULL, NULL, scat_out, NULL, NULL, dev); + if (val & 0x40) { - if (val & 1) { + if (val & 1) io_sethandler(0x0218, 3, scat_in, NULL, NULL, scat_out, NULL, NULL, dev); - io_removehandler(0x0208, 3, scat_in, NULL, NULL, scat_out, NULL, NULL, dev); - } else { + else io_sethandler(0x0208, 3, scat_in, NULL, NULL, scat_out, NULL, NULL, dev); - io_removehandler(0x0218, 3, scat_in, NULL, NULL, scat_out, NULL, NULL, dev); - } - } else { - io_removehandler(0x0208, 0x0003, scat_in, NULL, NULL, scat_out, NULL, NULL, dev); - io_removehandler(0x0218, 0x0003, scat_in, NULL, NULL, scat_out, NULL, NULL, dev); } set_global_EMS_state(dev, val & 0x80); reg_valid = 1; diff --git a/src/disk/hdc_st506_xt.c b/src/disk/hdc_st506_xt.c index 5831fee88..a980ec6e8 100644 --- a/src/disk/hdc_st506_xt.c +++ b/src/disk/hdc_st506_xt.c @@ -1333,7 +1333,8 @@ loadrom(hdc_t *dev, const wchar_t *fn) /* Load the ROM data. */ dev->bios_rom.rom = (uint8_t *)malloc(size); memset(dev->bios_rom.rom, 0xff, size); - (void)fread(dev->bios_rom.rom, size, 1, fp); + if (fread(dev->bios_rom.rom, 1, size, fp) != size) + fatal("ST-506 XT loadrom(): Error reading data\n"); (void)fclose(fp); /* Set up an address mask for this memory. */ diff --git a/src/disk/hdd_image.c b/src/disk/hdd_image.c index 5a84116eb..26c312824 100644 --- a/src/disk/hdd_image.c +++ b/src/disk/hdd_image.c @@ -641,13 +641,19 @@ hdd_image_load(int id) } } else { if (image_is_hdi(fn)) { - fseeko64(hdd_images[id].file, 0x8, SEEK_SET); - fread(&(hdd_images[id].base), 1, 4, hdd_images[id].file); - fseeko64(hdd_images[id].file, 0xC, SEEK_SET); + if (fseeko64(hdd_images[id].file, 0x8, SEEK_SET) == -1) + fatal("hdd_image_load(): HDI: Error seeking to offset 0x8\n"); + if (fread(&(hdd_images[id].base), 1, 4, hdd_images[id].file) != 4) + fatal("hdd_image_load(): HDI: Error reading base offset\n"); + if (fseeko64(hdd_images[id].file, 0xC, SEEK_SET) == -1) + fatal("hdd_image_load(): HDI: Error seeking to offest 0xC\n"); full_size = 0LL; - fread(&full_size, 1, 4, hdd_images[id].file); - fseeko64(hdd_images[id].file, 0x10, SEEK_SET); - fread(§or_size, 1, 4, hdd_images[id].file); + if (fread(&full_size, 1, 4, hdd_images[id].file) != 4) + fatal("hdd_image_load(): HDI: Error reading full size\n"); + if (fseeko64(hdd_images[id].file, 0x10, SEEK_SET) == -1) + fatal("hdd_image_load(): HDI: Error seeking to offset 0x10\n"); + if (fread(§or_size, 1, 4, hdd_images[id].file) != 4) + fatal("hdd_image_load(): HDI: Error reading sector size\n"); if (sector_size != 512) { /* Sector size is not 512 */ hdd_image_log("HDI: Sector size is not 512\n"); @@ -656,19 +662,26 @@ hdd_image_load(int id) memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); return 0; } - fread(&spt, 1, 4, hdd_images[id].file); - fread(&hpc, 1, 4, hdd_images[id].file); - fread(&tracks, 1, 4, hdd_images[id].file); + if (fread(&spt, 1, 4, hdd_images[id].file) != 4) + fatal("hdd_image_load(): HDI: Error reading sectors per track\n"); + if (fread(&hpc, 1, 4, hdd_images[id].file) != 4) + fatal("hdd_image_load(): HDI: Error reading heads per cylinder\n"); + if (fread(&tracks, 1, 4, hdd_images[id].file) != 4) + fatal("hdd_image_load(): HDI: Error reading number of tracks\n"); hdd[id].spt = spt; hdd[id].hpc = hpc; hdd[id].tracks = tracks; hdd_images[id].type = 1; } else if (is_hdx[1]) { hdd_images[id].base = 0x28; - fseeko64(hdd_images[id].file, 8, SEEK_SET); - fread(&full_size, 1, 8, hdd_images[id].file); - fseeko64(hdd_images[id].file, 0x10, SEEK_SET); - fread(§or_size, 1, 4, hdd_images[id].file); + if (fseeko64(hdd_images[id].file, 8, SEEK_SET) == -1) + fatal("hdd_image_load(): HDX: Error seeking to offset 0x8\n"); + if (fread(&full_size, 1, 8, hdd_images[id].file) != 8) + fatal("hdd_image_load(): HDX: Error reading full size\n"); + if (fseeko64(hdd_images[id].file, 0x10, SEEK_SET) == -1) + fatal("hdd_image_load(): HDX: Error seeking to offset 0x10\n"); + if (fread(§or_size, 1, 4, hdd_images[id].file) != 4) + fatal("hdd_image_load(): HDX: Error reading sector size\n"); if (sector_size != 512) { /* Sector size is not 512 */ hdd_image_log("HDX: Sector size is not 512\n"); @@ -677,16 +690,21 @@ hdd_image_load(int id) memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); return 0; } - fread(&spt, 1, 4, hdd_images[id].file); - fread(&hpc, 1, 4, hdd_images[id].file); - fread(&tracks, 1, 4, hdd_images[id].file); + if (fread(&spt, 1, 4, hdd_images[id].file) != 4) + fatal("hdd_image_load(): HDI: Error reading sectors per track\n"); + if (fread(&hpc, 1, 4, hdd_images[id].file) != 4) + fatal("hdd_image_load(): HDI: Error reading heads per cylinder\n"); + if (fread(&tracks, 1, 4, hdd_images[id].file) != 4) + fatal("hdd_image_load(): HDX: Error reading number of tracks\n"); hdd[id].spt = spt; hdd[id].hpc = hpc; hdd[id].tracks = tracks; hdd_images[id].type = 2; } else if (is_vhd[1]) { - fseeko64(hdd_images[id].file, -512, SEEK_END); - fread(empty_sector, 1, 512, hdd_images[id].file); + if (fseeko64(hdd_images[id].file, -512, SEEK_END) == -1) + fatal("hdd_image_load(): VHD: Error seeking to 512 bytes before the end of file\n"); + if (fread(empty_sector, 1, 512, hdd_images[id].file) != 512) + fatal("hdd_image_load(): HDX: Error reading the footer\n"); new_vhd_footer(&vft); vhd_footer_from_bytes(vft, (uint8_t *) empty_sector); if (vft->type != 2) { @@ -720,7 +738,8 @@ hdd_image_load(int id) } } - fseeko64(hdd_images[id].file, 0, SEEK_END); + if (fseeko64(hdd_images[id].file, 0, SEEK_END) == -1) + fatal("hdd_image_load(): Error seeking to the end of file\n"); s = ftello64(hdd_images[id].file); if (s < (full_size + hdd_images[id].base)) ret = prepare_new_hard_disk(id, full_size); @@ -731,7 +750,8 @@ hdd_image_load(int id) } if (is_vhd[0]) { - fseeko64(hdd_images[id].file, 0, SEEK_END); + if (fseeko64(hdd_images[id].file, 0, SEEK_END) == -1) + fatal("hdd_image_load(): VHD: Error seeking to the end of file\n"); s = ftello64(hdd_images[id].file); if (s == (full_size + hdd_images[id].base)) { /* VHD image. */ diff --git a/src/disk/zip.c b/src/disk/zip.c index 85f4e677f..9185aafae 100644 --- a/src/disk/zip.c +++ b/src/disk/zip.c @@ -527,7 +527,8 @@ zip_load(zip_t *dev, wchar_t *fn) dev->drv->medium_size = size >> 9; - fseek(dev->drv->f, dev->drv->base, SEEK_SET); + if (fseek(dev->drv->f, dev->drv->base, SEEK_SET) == -1) + fatal("zip_load(): Error seeking to the beginning of the file\n"); memcpy(dev->drv->image_path, fn, sizeof(dev->drv->image_path)); @@ -1180,10 +1181,13 @@ zip_blocks(zip_t *dev, int32_t *len, int first_batch, int out) if (feof(dev->drv->f)) break; - if (out) - fwrite(dev->buffer + (i << 9), 1, 512, dev->drv->f); - else - fread(dev->buffer + (i << 9), 1, 512, dev->drv->f); + if (out) { + if (fwrite(dev->buffer + (i << 9), 1, 512, dev->drv->f) != 512) + fatal("zip_blocks(): Error writing data\n"); + } else { + if (fread(dev->buffer + (i << 9), 1, 512, dev->drv->f) != 512) + fatal("zip_blocks(): Error reading data\n"); + } } zip_log("%s %i bytes of blocks...\n", out ? "Written" : "Read", *len); @@ -1444,6 +1448,7 @@ zip_command(scsi_common_t *sc, uint8_t *cdb) zip_invalid_field(dev); return; } + /*FALLTHROUGH*/ case GPCMD_SCSI_RESERVE: case GPCMD_SCSI_RELEASE: case GPCMD_TEST_UNIT_READY: diff --git a/src/floppy/fdd_86f.c b/src/floppy/fdd_86f.c index 797d6bf80..70540105b 100644 --- a/src/floppy/fdd_86f.c +++ b/src/floppy/fdd_86f.c @@ -3161,7 +3161,7 @@ d86f_writeback(int drive) { d86f_t *dev = d86f[drive]; uint8_t header[32]; - int header_size; + int header_size, size; #ifdef D86F_COMPRESS uint32_t len; int ret = 0; @@ -3172,11 +3172,16 @@ d86f_writeback(int drive) if (! dev->f) return; /* First write the track offsets table. */ - fseek(dev->f, 0, SEEK_SET); - fread(header, 1, header_size, dev->f); + if (fseek(dev->f, 0, SEEK_SET) == -1) + fatal("86F write_back(): Error seeking to the beginning of the file\n"); + if (fread(header, 1, header_size, dev->f) != header_size) + fatal("86F write_back(): Error reading header size\n"); - fseek(dev->f, 8, SEEK_SET); - fwrite(dev->track_offset, 1, d86f_get_track_table_size(drive), dev->f); + if (fseek(dev->f, 8, SEEK_SET) == -1) + fatal("86F write_back(): Error seeking\n"); + size = d86f_get_track_table_size(drive); + if (fwrite(dev->track_offset, 1, size, dev->f) != size) + fatal("86F write_back(): Error writing data\n"); d86f_write_tracks(drive, &dev->f, NULL); @@ -3586,7 +3591,9 @@ d86f_load(int drive, wchar_t *fn) return; } - fread(&(dev->version), 2, 1, dev->f); + if (fread(&(dev->version), 1, 2, dev->f) != 2) + fatal("d86f_load(): Error reading format version\n"); + if (dev->version != D86FVER) { /* File is not of a recognized format version, abort. */ if (dev->version == 0x0063) { diff --git a/src/floppy/fdd_imd.c b/src/floppy/fdd_imd.c index 421e339cf..c892e24c5 100644 --- a/src/floppy/fdd_imd.c +++ b/src/floppy/fdd_imd.c @@ -638,8 +638,10 @@ imd_load(int drive, wchar_t *fn) writeprot[drive] = 1; fwriteprot[drive] = writeprot[drive]; - fseek(dev->f, 0, SEEK_SET); - fread(&magic, 1, 4, dev->f); + if (fseek(dev->f, 0, SEEK_SET) == -1) + fatal("imd_load(): Error seeking to the beginning of the file\n"); + if (fread(&magic, 1, 4, dev->f) != 4) + fatal("imd_load(): Error reading the magic number\n"); if (magic != 0x20444D49) { imd_log("IMD: Not a valid ImageDisk image\n"); fclose(dev->f); @@ -649,11 +651,14 @@ imd_load(int drive, wchar_t *fn) } else imd_log("IMD: Valid ImageDisk image\n"); - fseek(dev->f, 0, SEEK_END); + if (fseek(dev->f, 0, SEEK_END) == -1) + fatal("imd_load(): Error seeking to the end of the file\n"); fsize = ftell(dev->f); - fseek(dev->f, 0, SEEK_SET); + if (fseek(dev->f, 0, SEEK_SET) == -1) + fatal("imd_load(): Error seeking to the beginning of the file again\n"); dev->buffer = malloc(fsize); - fread(dev->buffer, 1, fsize, dev->f); + if (fread(dev->buffer, 1, fsize, dev->f) != fsize) + fatal("imd_load(): Error reading data\n"); buffer = dev->buffer; buffer2 = strchr(buffer, 0x1A); diff --git a/src/floppy/fdd_mfm.c b/src/floppy/fdd_mfm.c index c2062baad..6da06f48d 100644 --- a/src/floppy/fdd_mfm.c +++ b/src/floppy/fdd_mfm.c @@ -401,7 +401,7 @@ mfm_load(int drive, wchar_t *fn) { mfm_t *dev; double dbr; - int i; + int i, size; writeprot[drive] = fwriteprot[drive] = 1; @@ -419,16 +419,22 @@ mfm_load(int drive, wchar_t *fn) d86f_unregister(drive); /* Read the header. */ - fread(&dev->hdr, 1, sizeof(mfm_header_t), dev->f); + size = sizeof(mfm_header_t); + if (fread(&dev->hdr, 1, size, dev->f) != size) + fatal("mfm_load(): Error reading header\n"); /* Calculate tracks * sides, allocate the tracks array, and read it. */ dev->total_tracks = dev->hdr.tracks_no * dev->hdr.sides_no; if (dev->hdr.if_type & 0x80) { dev->adv_tracks = (mfm_adv_track_t *) malloc(dev->total_tracks * sizeof(mfm_adv_track_t)); - fread(dev->adv_tracks, 1, dev->total_tracks * sizeof(mfm_adv_track_t), dev->f); + size = dev->total_tracks * sizeof(mfm_adv_track_t); + if (fread(dev->adv_tracks, 1, size, dev->f) != size) + fatal("mfm_load(): Error reading advanced tracks\n"); } else { dev->tracks = (mfm_track_t *) malloc(dev->total_tracks * sizeof(mfm_track_t)); - fread(dev->tracks, 1, dev->total_tracks * sizeof(mfm_track_t), dev->f); + size = dev->total_tracks * sizeof(mfm_track_t); + if (fread(dev->tracks, 1, size, dev->f) != size) + fatal("mfm_load(): Error reading tracks\n"); } /* The chances of finding a HxC MFM image of a single-sided thin track diff --git a/src/floppy/fdd_td0.c b/src/floppy/fdd_td0.c index 6762f78f5..2326b2aa4 100644 --- a/src/floppy/fdd_td0.c +++ b/src/floppy/fdd_td0.c @@ -262,7 +262,8 @@ state_data_read(td0dsk_t *state, uint8_t *buf, uint16_t size) size = (image_size - state->fdd_file_offset) & 0xffff; if (fseek(state->fdd_file, state->fdd_file_offset, SEEK_SET) == -1) fatal("TD0: Failed to seek in state_data_read()\n"); - fread(buf, 1, size, state->fdd_file); + if (fread(buf, 1, size, state->fdd_file) != size) + fatal("TD0: Error reading data in state_data_read()\n"); state->fdd_file_offset += size; return(size); diff --git a/src/floppy/fdi2raw.c b/src/floppy/fdi2raw.c index 03ddf460f..feb597ef9 100644 --- a/src/floppy/fdi2raw.c +++ b/src/floppy/fdi2raw.c @@ -2137,8 +2137,10 @@ int fdi2raw_loadtrack (FDI *fdi, uae_u16 *mfmbuf, uae_u16 *tracktiming, int trac fdi->err = 0; fdi->track_src_len = fdi->track_offsets[track + 1] - fdi->track_offsets[track]; - fseek (fdi->file, fdi->track_offsets[track], SEEK_SET); - fread (fdi->track_src_buffer, fdi->track_src_len, 1, fdi->file); + if (fseek (fdi->file, fdi->track_offsets[track], SEEK_SET) == -1) + fatal("fdi2raw_loadtrack(): Error seeking to the beginning of the file\n"); + if (fread (fdi->track_src_buffer, 1, fdi->track_src_len, fdi->file) != fdi->track_src_len) + fatal("fdi2raw_loadtrack(): Error reading data\n"); memset (fdi->track_dst_buffer, 0, MAX_DST_BUFFER); fdi->track_dst_buffer_timing[0] = 0; @@ -2177,7 +2179,7 @@ int fdi2raw_loadtrack (FDI *fdi, uae_u16 *mfmbuf, uae_u16 *tracktiming, int trac zxx (fdi); outlen = -1; - } else if (fdi->track_type < 0x10) { + } else if (fdi->track_type < 0x0f) { decode_normal_track[fdi->track_type](fdi); fix_mfm_sync (fdi); diff --git a/src/rom.c b/src/rom.c index cbb43a82b..17c31e3ba 100644 --- a/src/rom.c +++ b/src/rom.c @@ -183,8 +183,10 @@ rom_load_linear(wchar_t *fn, uint32_t addr, int sz, int off, uint8_t *ptr) } if (ptr != NULL) { - (void)fseek(f, off, SEEK_SET); - (void)fread(ptr+addr, sz, 1, f); + if (fseek(f, off, SEEK_SET) == -1) + fatal("rom_load_linear(): Error seeking to the beginning of the file\n"); + if (fread(ptr+addr, 1, sz, f) != sz) + fatal("rom_load_linear(): Error reading data\n"); } (void)fclose(f); @@ -221,9 +223,12 @@ rom_load_linear_inverted(wchar_t *fn, uint32_t addr, int sz, int off, uint8_t *p } if (ptr != NULL) { - (void)fseek(f, off, SEEK_SET); - (void)fread(ptr+addr+0x10000, sz >> 1, 1, f); - (void)fread(ptr+addr, sz >> 1, 1, f); + if (fseek(f, off, SEEK_SET) == -1) + fatal("rom_load_linear_inverted(): Error seeking to the beginning of the file\n"); + if (fread(ptr+addr+0x10000, 1, sz >> 1, f) > (sz >> 1)) + fatal("rom_load_linear_inverted(): Error reading the upper half of the data\n"); + if (fread(ptr+addr, sz >> 1, 1, f) > (sz >> 1)) + fatal("rom_load_linear_inverted(): Error reading the lower half of the data\n"); } (void)fclose(f); diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index cbe32f15a..201d597d2 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -450,7 +450,8 @@ scsi_cdrom_mode_sense_load(scsi_cdrom_t *dev) swprintf(file_name, 512, L"cdrom_%02i_mode_sense_bin", dev->id); f = plat_fopen(nvr_path(file_name), L"rb"); if (f) { - fread(dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE], 1, 0x10, f); + if (fread(dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE], 1, 0x10, f) != 0x10) + fatal("scsi_cdrom_mode_sense_load(): Error reading data\n"); fclose(f); } } diff --git a/src/video/vid_ati18800.c b/src/video/vid_ati18800.c index 648772c77..fa4b22044 100644 --- a/src/video/vid_ati18800.c +++ b/src/video/vid_ati18800.c @@ -86,6 +86,7 @@ static void ati18800_out(uint16_t addr, uint8_t val, void *p) { case 0xb0: svga_recalctimings(svga); + break; case 0xb2: case 0xbe: if (ati18800->regs[0xbe] & 8) /*Read/write bank mode*/ diff --git a/src/video/vid_im1024.c b/src/video/vid_im1024.c index 6a297d9ca..00954e2d6 100644 --- a/src/video/vid_im1024.c +++ b/src/video/vid_im1024.c @@ -523,6 +523,10 @@ hndl_poly(pgc_t *pgc) #ifdef ENABLE_IM1024_LOG im1024_log("IM1024: POLY: out of memory\n"); #endif + if (x) + free(x); + if (y) + free(y); return; } diff --git a/src/video/video.c b/src/video/video.c index 35ca81a33..1cbdfdac4 100644 --- a/src/video/video.c +++ b/src/video/video.c @@ -933,11 +933,15 @@ loadfont(wchar_t *s, int format) case 1: /* PC200 */ for (d = 0; d < 4; d++) { /* There are 4 fonts in the ROM */ - for (c = 0; c < 256; c++) /* 8x14 MDA in 8x16 cell */ - fread(&fontdatm[256*d + c][0], 1, 16, f); + for (c = 0; c < 256; c++) { /* 8x14 MDA in 8x16 cell */ + if (fread(&fontdatm[256*d + c][0], 1, 16, f) != 16) + fatal("loadfont(): Error reading 8x16 font in PC200 mode, c = %i\n", c); + } for (c = 0; c < 256; c++) { /* 8x8 CGA in 8x16 cell */ - fread(&fontdat[256*d + c][0], 1, 8, f); - fseek(f, 8, SEEK_CUR); + if (fread(&fontdat[256*d + c][0], 1, 8, f) != 8) + fatal("loadfont(): Error reading 8x8 font in PC200 mode, c = %i\n", c); + if (fseek(f, 8, SEEK_CUR) == -1) + fatal("loadfont(): Error seeking in PC200 mode, c = %i\n", c); } } break; @@ -1015,7 +1019,7 @@ loadfont(wchar_t *s, int format) /* The second 4k holds an 8x16 font */ for (c = 0; c < 256; c++) { if (fread(&fontdatm[c][0], 1, 16, f) != 16) - fatal("loadfont(): Error reading font file in Sigma Coloar 400 mdoe, c = %i\n", c); + fatal("loadfont(): Error reading 8x16 font in Sigma Color 400 mode, c = %i\n", c); } break; From 932ad5595a0fa412ddcb0e8f36cc84640fa26c90 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 04:58:28 +0100 Subject: [PATCH 152/177] Fixed the third batch of problems. --- src/86box.h | 2 +- src/chipset/neat.c | 2 +- src/config.c | 8 ++++---- src/cpu/x86seg.c | 3 +++ src/cpu_new/x86seg.c | 3 +++ src/disk/hdc_esdi_at.c | 2 ++ src/disk/hdc_ide.c | 1 + src/disk/hdd_image.c | 9 ++++++--- src/floppy/fdc.c | 1 + src/floppy/fdd.c | 3 ++- src/floppy/fdd_86f.c | 23 ++++++++++------------- src/floppy/fdd_fdi.c | 8 +++++--- src/floppy/fdd_imd.c | 10 +++++++++- src/floppy/fdd_mfm.c | 5 +++-- src/floppy/fdd_td0.c | 6 ++++-- src/floppy/fdi2raw.c | 9 ++++++--- src/machine/m_at_t3100e.c | 3 +++ src/machine/m_xt_t1000.c | 23 ++++++++++++++++++----- src/mouse_serial.c | 1 + src/nvr.c | 3 ++- src/nvr_ps2.c | 2 -- src/pc.c | 4 ++-- src/printer/prt_escp.c | 8 +++++--- src/scsi/scsi_aha154x.c | 3 ++- src/scsi/scsi_buslogic.c | 4 +++- src/scsi/scsi_disk.c | 3 ++- src/scsi/scsi_x54x.c | 8 -------- src/sound/snd_adlibgold.c | 8 +++++--- src/sound/snd_emu8k.c | 3 ++- src/video/vid_ati_mach64.c | 4 ++++ src/video/vid_et4000w32.c | 2 +- src/video/vid_pgc.c | 3 ++- src/video/vid_s3.c | 10 ++-------- src/win/win.c | 2 ++ src/win/win.h | 4 ++-- src/win/win_dialog.c | 4 ++-- src/win/win_new_floppy.c | 1 + src/win/win_settings.c | 5 +++-- src/win/win_ui.c | 4 ++-- 39 files changed, 127 insertions(+), 80 deletions(-) diff --git a/src/86box.h b/src/86box.h index 477051461..ce915f8ae 100644 --- a/src/86box.h +++ b/src/86box.h @@ -133,7 +133,7 @@ extern int serial_do_log; extern int nic_do_log; #endif -extern wchar_t exe_path[1024]; /* path (dir) of executable */ +extern wchar_t exe_path[2048]; /* path (dir) of executable */ extern wchar_t usr_path[1024]; /* path (dir) of user data */ extern wchar_t cfg_path[1024]; /* full path of config file */ #ifndef USE_NEW_DYNAREC diff --git a/src/chipset/neat.c b/src/chipset/neat.c index 4f2524db9..cc641c0d5 100644 --- a/src/chipset/neat.c +++ b/src/chipset/neat.c @@ -565,7 +565,7 @@ neat_write(uint16_t port, uint8_t val, void *priv) case REG_RB7: val &= RB7_MASK; - *reg = (*reg & ~RB7_MASK) | val; + *reg = val; #if NEAT_DEBUG > 1 neat_log("NEAT: RB7=%02x(%02x)\n", val, *reg); #endif diff --git a/src/config.c b/src/config.c index 3bcd6dbea..2a333f952 100644 --- a/src/config.c +++ b/src/config.c @@ -339,7 +339,7 @@ config_read(wchar_t *fn) /* Allocate a new variable entry.. */ ne = malloc(sizeof(entry_t)); memset(ne, 0x00, sizeof(entry_t)); - strncpy(ne->name, ename, sizeof(ne->name)); + strncpy(ne->name, ename, sizeof(ne->name) - 1); wcsncpy(ne->wdata, &buff[d], sizeof_w(ne->wdata)-1); ne->wdata[sizeof_w(ne->wdata)-1] = L'\0'; wcstombs(ne->data, ne->wdata, sizeof(ne->data)); @@ -395,7 +395,7 @@ config_write(wchar_t *fn) ent = (entry_t *)sec->entry_head.next; while (ent != NULL) { if (ent->name[0] != '\0') { - mbstowcs(wtemp, ent->name, sizeof_w(wtemp)); + mbstowcs(wtemp, ent->name, 128); if (ent->wdata[0] == L'\0') fwprintf(f, L"%ls = \n", wtemp); else @@ -1708,7 +1708,7 @@ static void save_hard_disks(void) { char *cat = "Hard disks"; - char temp[32], tmp2[256]; + char temp[32], tmp2[512]; char *p; int c; @@ -2167,7 +2167,7 @@ config_set_mac(char *head, char *name, int val) sprintf(ent->data, "%02x:%02x:%02x", (val>>16)&0xff, (val>>8)&0xff, val&0xff); - mbstowcs(ent->wdata, ent->data, sizeof_w(ent->wdata)); + mbstowcs(ent->wdata, ent->data, 512); } diff --git a/src/cpu/x86seg.c b/src/cpu/x86seg.c index d2dd5e8ad..036dfcfe4 100644 --- a/src/cpu/x86seg.c +++ b/src/cpu/x86seg.c @@ -765,6 +765,7 @@ void loadcsjmp(uint16_t seg, uint32_t old_pc) x86gpf(NULL,seg2&~3); return; } + /*FALLTHROUGH*/ case 0x1C00: case 0x1D00: case 0x1E00: case 0x1F00: /*Conforming*/ CS=seg2; do_seg_load(&cpu_state.seg_cs, segdat); @@ -1235,6 +1236,7 @@ void loadcscall(uint16_t seg) x86gpf(NULL,seg2&~3); return; } + /*FALLTHROUGH*/ case 0x1C00: case 0x1D00: case 0x1E00: case 0x1F00: /*Conforming*/ CS=seg2; do_seg_load(&cpu_state.seg_cs, segdat); @@ -1766,6 +1768,7 @@ void pmodeint(int num, int soft) x86gpf(NULL,seg&~3); return; } + /*FALLTHROUGH*/ case 0x1C00: case 0x1D00: case 0x1E00: case 0x1F00: /*Conforming*/ if (!(segdat2[2]&0x8000)) { diff --git a/src/cpu_new/x86seg.c b/src/cpu_new/x86seg.c index 2a438d862..c07f002ea 100644 --- a/src/cpu_new/x86seg.c +++ b/src/cpu_new/x86seg.c @@ -761,6 +761,7 @@ void loadcsjmp(uint16_t seg, uint32_t old_pc) x86gpf(NULL,seg2&~3); return; } + /*FALLTHROUGH*/ case 0x1C00: case 0x1D00: case 0x1E00: case 0x1F00: /*Conforming*/ CS=seg2; do_seg_load(&cpu_state.seg_cs, segdat); @@ -1228,6 +1229,7 @@ void loadcscall(uint16_t seg, uint32_t old_pc) x86gpf(NULL,seg2&~3); return; } + /*FALLTHROUGH*/ case 0x1C00: case 0x1D00: case 0x1E00: case 0x1F00: /*Conforming*/ CS=seg2; do_seg_load(&cpu_state.seg_cs, segdat); @@ -1762,6 +1764,7 @@ void pmodeint(int num, int soft) x86gpf(NULL,seg&~3); return; } + /*FALLTHROUGH*/ case 0x1C00: case 0x1D00: case 0x1E00: case 0x1F00: /*Conforming*/ if (!(segdat2[2]&0x8000)) { diff --git a/src/disk/hdc_esdi_at.c b/src/disk/hdc_esdi_at.c index 6e3946a80..920c087d5 100644 --- a/src/disk/hdc_esdi_at.c +++ b/src/disk/hdc_esdi_at.c @@ -304,6 +304,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv) esdi->command &= ~0x03; if (val & 0x02) fatal("Read with ECC\n"); + /*FALLTHROUGH*/ case 0xa0: esdi->status = STAT_BUSY; @@ -351,6 +352,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv) default: esdi_at_log("WD1007: bad command %02X\n", val); + /*FALLTHROUGH*/ case 0xe8: /*???*/ esdi->status = STAT_BUSY; timer_set_delay_u64(&esdi->callback_timer, 200 * HDC_TIME); diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index c0250adc6..5fedee57d 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -757,6 +757,7 @@ ide_set_features(ide_t *ide) default: return 0; } + break; case FEATURE_ENABLE_IRQ_OVERLAPPED: case FEATURE_ENABLE_IRQ_SERVICE: diff --git a/src/disk/hdd_image.c b/src/disk/hdd_image.c index 26c312824..dbffb16d3 100644 --- a/src/disk/hdd_image.c +++ b/src/disk/hdd_image.c @@ -133,7 +133,8 @@ image_is_hdx(const wchar_t *s, int check_signature) fclose(f); return 0; } - fread(&signature, 1, 8, f); + if (fread(&signature, 1, 8, f) != 8) + fatal("image_is_hdx(): Error reading signature\n"); fclose(f); if (signature == 0xD778A82044445459ll) return 1; @@ -175,7 +176,8 @@ image_is_vhd(const wchar_t *s, int check_signature) fclose(f); return 0; } - fread(&signature, 1, 8, f); + if (fread(&signature, 1, 8, f) != 8) + fatal("image_is_vhd(): Error reading signature\n"); fclose(f); if (signature == 0x78697463656E6F63ll) return 1; @@ -770,7 +772,8 @@ hdd_image_seek(uint8_t id, uint32_t sector) addr = (uint64_t)sector << 9LL; hdd_images[id].pos = sector; - fseeko64(hdd_images[id].file, addr + hdd_images[id].base, SEEK_SET); + if (fseeko64(hdd_images[id].file, addr + hdd_images[id].base, SEEK_SET) == -1) + fatal("hdd_image_seek(): Error seeking\n"); } diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 401093ef0..495f8c3d1 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -994,6 +994,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) case 0x16: /* Verify */ if (fdc->params[0] & 0x80) fdc->sc = fdc->params[7]; + /*FALLTHROUGH*/ case 0x06: /* Read data */ case 0x0c: /* Read deleted data */ fdc_io_command_phase1(fdc, 0); diff --git a/src/floppy/fdd.c b/src/floppy/fdd.c index 92bffd9be..24bd46313 100644 --- a/src/floppy/fdd.c +++ b/src/floppy/fdd.c @@ -491,7 +491,8 @@ fdd_load(int drive, wchar_t *fn) f = plat_fopen(fn, L"rb"); if (!f) return; - fseek(f, -1, SEEK_END); + if (fseek(f, -1, SEEK_END) == -1) + fatal("fdd_load(): Error seeking to the end of the file\n"); size = ftell(f) + 1; fclose(f); while (loaders[c].ext) { diff --git a/src/floppy/fdd_86f.c b/src/floppy/fdd_86f.c index 70540105b..02341193a 100644 --- a/src/floppy/fdd_86f.c +++ b/src/floppy/fdd_86f.c @@ -1174,15 +1174,8 @@ d86f_put_bit(int drive, int side, int bit) if (d86f_has_surface_desc(drive)) { surface_bit = (surface_data >> track_bit) & 1; if (! surface_bit) { - if (! current_bit) { - /* Bit is 0 and is not set to fuzzy, we overwrite it as is. */ - dev->last_word[side] |= bit; - current_bit = bit; - } else { - /* Bit is 1 and is not set to fuzzy, we overwrite it as is. */ - dev->last_word[side] |= bit; - current_bit = bit; - } + dev->last_word[side] |= bit; + current_bit = bit; } else { if (current_bit) { /* Bit is 1 and is set to fuzzy, we overwrite it with a non-fuzzy bit. */ @@ -2949,10 +2942,13 @@ d86f_read_track(int drive, int track, int thin_track, int side, uint16_t *da, ui if (dev->track_offset[logical_track]) { if (! thin_track) { - fseek(dev->f, dev->track_offset[logical_track], SEEK_SET); - fread(&(dev->side_flags[side]), 2, 1, dev->f); + if (fseek(dev->f, dev->track_offset[logical_track], SEEK_SET) == -1) + fatal("d86f_read_track(): Error seeking to offset dev->track_offset[logical_track]\n"); + if (fread(&(dev->side_flags[side]), 1, 2, dev->f) != 2) + fatal("d86f_read_track(): Error reading side flags\n"); if (d86f_has_extra_bit_cells(drive)) { - fread(&(dev->extra_bit_cells[side]), 4, 1, dev->f); + if (fread(&(dev->extra_bit_cells[side]), 1, 4, dev->f) != 4) + fatal("d86f_read_track(): Error reading number of extra bit cells\n"); /* If RPM shift is 0% and direction is 1, do not adjust extra bit cells, as that is the whole track length. */ if (d86f_get_rpm_mode(drive) || !d86f_get_speed_shift_dir(drive)) { @@ -3146,7 +3142,8 @@ d86f_write_tracks(int drive, FILE **f, uint32_t *track_table) } if (tbl[logical_track]) { - fseek(*f, tbl[logical_track], SEEK_SET); + if (fseek(*f, tbl[logical_track], SEEK_SET) == -1) + fatal("d86f_write_tracks(): Error seeking to offset tbl[logical_track]\n"); d86f_write_track(drive, f, side, d86f_handler[drive].encoded_data(drive, side), dev->track_surface_data[side]); } } diff --git a/src/floppy/fdd_fdi.c b/src/floppy/fdd_fdi.c index d49c851a5..fdb5af532 100644 --- a/src/floppy/fdd_fdi.c +++ b/src/floppy/fdd_fdi.c @@ -331,7 +331,6 @@ fdi_load(int drive, wchar_t *fn) dev = (fdi_t *)malloc(sizeof(fdi_t)); memset(dev, 0x00, sizeof(fdi_t)); - dev->f = plat_fopen(fn, L"rb"); if (dev == NULL) { free(dev); memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); @@ -340,8 +339,11 @@ fdi_load(int drive, wchar_t *fn) d86f_unregister(drive); - fread(header, 1, 25, dev->f); - fseek(dev->f, 0, SEEK_SET); + dev->f = plat_fopen(fn, L"rb"); + if (fread(header, 1, 25, dev->f) != 25) + fatal("fdi_load(): Error reading header\n"); + if (fseek(dev->f, 0, SEEK_SET) == -1) + fatal("fdi_load(): Error seeking to the beginning of the file\n"); header[25] = 0; if (strcmp(header, "Formatted Disk Image file") != 0) { /* This is a Japanese FDI file. */ diff --git a/src/floppy/fdd_imd.c b/src/floppy/fdd_imd.c index c892e24c5..1ff63ac6d 100644 --- a/src/floppy/fdd_imd.c +++ b/src/floppy/fdd_imd.c @@ -629,6 +629,7 @@ imd_load(int drive, wchar_t *fn) dev->f = plat_fopen(fn, L"rb"); if (dev->f == NULL) { memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + free(dev); return; } writeprot[drive] = 1; @@ -654,6 +655,13 @@ imd_load(int drive, wchar_t *fn) if (fseek(dev->f, 0, SEEK_END) == -1) fatal("imd_load(): Error seeking to the end of the file\n"); fsize = ftell(dev->f); + if (fsize <= 0) { + imd_log("IMD: Too small ImageDisk image\n"); + fclose(dev->f); + free(dev); + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + return; + } if (fseek(dev->f, 0, SEEK_SET) == -1) fatal("imd_load(): Error seeking to the beginning of the file again\n"); dev->buffer = malloc(fsize); @@ -661,7 +669,7 @@ imd_load(int drive, wchar_t *fn) fatal("imd_load(): Error reading data\n"); buffer = dev->buffer; - buffer2 = strchr(buffer, 0x1A); + buffer2 = memchr(buffer, 0x1A, fsize); if (buffer2 == NULL) { imd_log("IMD: No ASCII EOF character\n"); fclose(dev->f); diff --git a/src/floppy/fdd_mfm.c b/src/floppy/fdd_mfm.c index 6da06f48d..507a0c0a2 100644 --- a/src/floppy/fdd_mfm.c +++ b/src/floppy/fdd_mfm.c @@ -358,8 +358,9 @@ mfm_read_side(int drive, int side) else ret = fseek(dev->f, dev->tracks[track_index].track_offset, SEEK_SET); if (ret == -1) - fatal("MFM: Error seeking in mfm_read_side()\n"); - fread(dev->track_data[side], 1, track_bytes, dev->f); + fatal("mfm_read_side(): Error seeking to the beginning of the file\n"); + if (fread(dev->track_data[side], 1, track_bytes, dev->f) != track_bytes) + fatal("mfm_read_side(): Error reading track bytes\n"); } mfm_log("drive = %i, side = %i, dev->cur_track = %i, track_index = %i, track_size = %i\n", diff --git a/src/floppy/fdd_td0.c b/src/floppy/fdd_td0.c index 2326b2aa4..dd2499bee 100644 --- a/src/floppy/fdd_td0.c +++ b/src/floppy/fdd_td0.c @@ -231,8 +231,10 @@ fdd_image_read(int drive, char *buffer, uint32_t offset, uint32_t len) { td0_t *dev = td0[drive]; - fseek(dev->f, offset, SEEK_SET); - fread(buffer, 1, len, dev->f); + if (fseek(dev->f, offset, SEEK_SET) == -1) + fatal("fdd_image_read(): Error seeking to the beginning of the file\n"); + if (fread(buffer, 1, len, dev->f) != len) + fatal("fdd_image_read(): Error reading data\n"); } diff --git a/src/floppy/fdi2raw.c b/src/floppy/fdi2raw.c index feb597ef9..d01054e97 100644 --- a/src/floppy/fdi2raw.c +++ b/src/floppy/fdi2raw.c @@ -2039,9 +2039,12 @@ FDI *fdi2raw_header(FILE *f) fdi_free(fdi); return NULL; } - fseek (fdi->file, 0, SEEK_SET); - fread (fdi->header, 2048, 1, fdi->file); - fseek (fdi->file, oldseek, SEEK_SET); + if (fseek (fdi->file, 0, SEEK_SET) == -1) + fatal("fdi2raw_header(): Error seeking to the beginning of the file\n"); + if (fread (fdi->header, 1, 2048, fdi->file) != 2048) + fatal("fdi2raw_header(): Error reading header\n"); + if (fseek (fdi->file, oldseek, SEEK_SET) == -1) + fatal("fdi2raw_header(): Error seeking to offset oldseek\n"); if (memcmp (fdiid, fdi->header, strlen ((char *)fdiid)) ) { fdi_free(fdi); return NULL; diff --git a/src/machine/m_at_t3100e.c b/src/machine/m_at_t3100e.c index 8f69fc951..2288b1051 100644 --- a/src/machine/m_at_t3100e.c +++ b/src/machine/m_at_t3100e.c @@ -581,6 +581,9 @@ void t3100e_ems_out(uint16_t addr, uint8_t val, void *p) struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)p; int pg = port_to_page(addr); + if (pg == -1) + return; + regs->page_exec[pg & 3] = t3100e_ems_execaddr(regs, pg, val); t3100e_log("EMS: page %d %02x -> %02x [%06x]\n", pg, regs->page[pg], val, regs->page_exec[pg & 3]); diff --git a/src/machine/m_xt_t1000.c b/src/machine/m_xt_t1000.c index fc0205552..ee9bb8cd0 100644 --- a/src/machine/m_xt_t1000.c +++ b/src/machine/m_xt_t1000.c @@ -882,7 +882,8 @@ machine_xt_t1000_init(const machine_t *model) t1000.romdrive = malloc(T1000_ROMSIZE); if (t1000.romdrive) { memset(t1000.romdrive, 0xff, T1000_ROMSIZE); - fread(t1000.romdrive, T1000_ROMSIZE, 1, f); + if (fread(t1000.romdrive, 1, T1000_ROMSIZE, f) != T1000_ROMSIZE) + fatal("machine_xt_t1000_init(): Error reading DOS ROM data\n"); } fclose(f); } @@ -1016,11 +1017,14 @@ static void t1000_configsys_load(void) { FILE *f; + int size; memset(t1000.t1000_nvram, 0x1a, sizeof(t1000.t1000_nvram)); f = plat_fopen(nvr_path(L"t1000_config.nvr"), L"rb"); if (f != NULL) { - fread(t1000.t1000_nvram, sizeof(t1000.t1000_nvram), 1, f); + size = sizeof(t1000.t1000_nvram); + if (fread(t1000.t1000_nvram, size, 1, f) != size) + fatal("t1000_configsys_load(): Error reading data\n"); fclose(f); } } @@ -1030,10 +1034,13 @@ static void t1000_configsys_save(void) { FILE *f; + int size; f = plat_fopen(nvr_path(L"t1000_config.nvr"), L"wb"); if (f != NULL) { - fwrite(t1000.t1000_nvram, sizeof(t1000.t1000_nvram), 1, f); + size = sizeof(t1000.t1000_nvram); + if (fwrite(t1000.t1000_nvram, 1, size, f) != size) + fatal("t1000_configsys_save(): Error writing data\n"); fclose(f); } } @@ -1043,11 +1050,14 @@ static void t1200_state_load(void) { FILE *f; + int size; memset(t1000.t1200_nvram, 0, sizeof(t1000.t1200_nvram)); f = plat_fopen(nvr_path(L"t1200_state.nvr"), L"rb"); if (f != NULL) { - fread(t1000.t1200_nvram, sizeof(t1000.t1200_nvram), 1, f); + size = sizeof(t1000.t1200_nvram); + if (fread(t1000.t1200_nvram, 1, size, f) != size) + fatal("t1200_state_load(): Error reading data\n"); fclose(f); } } @@ -1057,10 +1067,13 @@ static void t1200_state_save(void) { FILE *f; + int size; f = plat_fopen(nvr_path(L"t1200_state.nvr"), L"wb"); if (f != NULL) { - fwrite(t1000.t1200_nvram, sizeof(t1000.t1200_nvram), 1, f); + size = sizeof(t1000.t1200_nvram); + if (fwrite(t1000.t1200_nvram, 1, size, f) != size) + fatal("t1200_state_save(): Error writing data\n"); fclose(f); } } diff --git a/src/mouse_serial.c b/src/mouse_serial.c index c96a7598d..b306e1252 100644 --- a/src/mouse_serial.c +++ b/src/mouse_serial.c @@ -623,6 +623,7 @@ ltsermouse_write(struct serial_s *serial, void *priv, uint8_t data) switch (data) { default: mouse_serial_log("Serial mouse: Invalid period %02X, using 1200 bps\n", data); + /*FALLTHROUGH*/ case 0x6E: dev->transmit_period = sermouse_transmit_period(dev, 1200, -1); break; diff --git a/src/nvr.c b/src/nvr.c index 53376295f..bb72ebf2d 100644 --- a/src/nvr.c +++ b/src/nvr.c @@ -264,7 +264,8 @@ nvr_load(void) fp = plat_fopen(path, L"rb"); if (fp != NULL) { /* Read NVR contents from file. */ - (void)fread(saved_nvr->regs, saved_nvr->size, 1, fp); + if (fread(saved_nvr->regs, 1, saved_nvr->size, fp) != saved_nvr->size) + fatal("nvr_load(): Error reading data\n"); (void)fclose(fp); } } diff --git a/src/nvr_ps2.c b/src/nvr_ps2.c index c98d12e77..483d67529 100644 --- a/src/nvr_ps2.c +++ b/src/nvr_ps2.c @@ -150,8 +150,6 @@ ps2_nvr_close(void *priv) fclose(f); } - free(nvr->ram); - free(nvr); } diff --git a/src/pc.c b/src/pc.c index 9f0bcc926..8e9160b78 100644 --- a/src/pc.c +++ b/src/pc.c @@ -149,7 +149,7 @@ int output; int atfullspeed; int clockrate; -wchar_t exe_path[1024]; /* path (dir) of executable */ +wchar_t exe_path[2048]; /* path (dir) of executable */ wchar_t usr_path[1024]; /* path (dir) of user data */ wchar_t cfg_path[1024]; /* full path of config file */ FILE *stdlog = NULL; /* file to log output to */ @@ -554,8 +554,8 @@ pc_init_modules(void) /* Load the ROMs for the selected machine. */ if (! machine_available(machine)) { c = 0; + machine = -1; while (machine_get_internal_name_ex(c) != NULL) { - machine = -1; if (machine_available(c)) { ui_msgbox(MBX_INFO, (wchar_t *)IDS_2063); machine = c; diff --git a/src/printer/prt_escp.c b/src/printer/prt_escp.c index a3ee36cad..f89cbc621 100644 --- a/src/printer/prt_escp.c +++ b/src/printer/prt_escp.c @@ -410,15 +410,17 @@ static void new_page(escp_t *dev, int8_t save, int8_t resetx) { /* Dump the current page if needed. */ - if (save) + if (save && dev->page) dump_page(dev); if (resetx) dev->curr_x = dev->left_margin; /* Clear page. */ dev->curr_y = dev->top_margin; - dev->page->dirty = 0; - memset(dev->page->pixels, 0x00, dev->page->pitch * dev->page->h); + if (dev->page) { + dev->page->dirty = 0; + memset(dev->page->pixels, 0x00, dev->page->pitch * dev->page->h); + } /* Make the page's file name. */ plat_tempfile(dev->page_fn, NULL, L".png"); diff --git a/src/scsi/scsi_aha154x.c b/src/scsi/scsi_aha154x.c index a33d35f07..ef7921a35 100644 --- a/src/scsi/scsi_aha154x.c +++ b/src/scsi/scsi_aha154x.c @@ -729,7 +729,8 @@ aha_setnvr(x54x_t *dev) f = nvr_fopen(dev->nvr_path, L"rb"); if (f) { - fread(dev->nvr, 1, NVR_SIZE, f); + if (fread(dev->nvr, 1, NVR_SIZE, f) != NVR_SIZE) + fatal("aha_setnvr(): Error reading data\n"); fclose(f); f = NULL; } else diff --git a/src/scsi/scsi_buslogic.c b/src/scsi/scsi_buslogic.c index 0f3141485..182cd2282 100644 --- a/src/scsi/scsi_buslogic.c +++ b/src/scsi/scsi_buslogic.c @@ -410,7 +410,8 @@ BuslogicInitializeAutoSCSIRam(x54x_t *dev) f = nvr_fopen(BuslogicGetNVRFileName(bl), L"rb"); if (f) { - fread(&(bl->LocalRAM.structured.autoSCSIData), 1, 64, f); + if (fread(&(bl->LocalRAM.structured.autoSCSIData), 1, 64, f) != 64) + fatal("BuslogicInitializeAutoSCSIRam(): Error reading data\n"); fclose(f); f = NULL; if (bl->chip == CHIP_BUSLOGIC_PCI) { @@ -1229,6 +1230,7 @@ BuslogicPCIWrite(int func, int addr, uint8_t val, void *p) case 0x10: val &= 0xe0; val |= 1; + /*FALLTHROUGH*/ case 0x11: case 0x12: case 0x13: /* I/O Base set. */ diff --git a/src/scsi/scsi_disk.c b/src/scsi/scsi_disk.c index 741fc04d4..61ee5c43f 100644 --- a/src/scsi/scsi_disk.c +++ b/src/scsi/scsi_disk.c @@ -155,7 +155,8 @@ scsi_disk_mode_sense_load(scsi_disk_t *dev) swprintf(file_name, 512, L"scsi_disk_%02i_mode_sense.bin", dev->id); f = plat_fopen(nvr_path(file_name), L"rb"); if (f) { - fread(dev->ms_pages_saved.pages[0x30], 1, 0x18, f); + if (fread(dev->ms_pages_saved.pages[0x30], 1, 0x18, f) != 0x18) + fatal("scsi_disk_mode_sense_load(): Error reading data\n"); fclose(f); } } diff --git a/src/scsi/scsi_x54x.c b/src/scsi/scsi_x54x.c index 4bced9593..e395923c6 100644 --- a/src/scsi/scsi_x54x.c +++ b/src/scsi/scsi_x54x.c @@ -1096,14 +1096,6 @@ x54x_req_setup(x54x_t *dev, uint32_t CCBPointer, Mailbox32_t *Mailbox32) return; } - if (req->CmdBlock.common.ControlByte > 0x03) { - x54x_log("Invalid control byte: %02X\n", - req->CmdBlock.common.ControlByte); - x54x_mbi_setup(dev, CCBPointer, &req->CmdBlock, CCB_INVALID_DIRECTION, SCSI_STATUS_OK, MBI_ERROR); - dev->callback_sub_phase = 4; - return; - } - dev->callback_sub_phase = 1; } } diff --git a/src/sound/snd_adlibgold.c b/src/sound/snd_adlibgold.c index 1322221d6..828ea518d 100644 --- a/src/sound/snd_adlibgold.c +++ b/src/sound/snd_adlibgold.c @@ -384,7 +384,7 @@ void adgold_write(uint16_t addr, uint8_t val, void *p) adgold->adgold_mma_regs[0][adgold->adgold_mma_addr] = val; break; case 7: - if (adgold->adgold_mma_addr >= 0xf) break; + if (adgold->adgold_mma_addr >= 0xe) break; switch (adgold->adgold_mma_addr) { case 0x9: @@ -503,8 +503,10 @@ uint8_t adgold_read(uint16_t addr, void *p) } break; case 7: - if (adgold->adgold_mma_addr >= 0xf) temp = 0xff; - temp = adgold->adgold_mma_regs[1][adgold->adgold_mma_addr]; + if (adgold->adgold_mma_addr >= 0xf) + temp = 0xff; + else + temp = adgold->adgold_mma_regs[1][adgold->adgold_mma_addr]; break; } return temp; diff --git a/src/sound/snd_emu8k.c b/src/sound/snd_emu8k.c index f5d19daac..9be46bb4c 100644 --- a/src/sound/snd_emu8k.c +++ b/src/sound/snd_emu8k.c @@ -2143,7 +2143,8 @@ void emu8k_init(emu8k_t *emu8k, uint16_t emu_addr, int onboard_ram) fatal("AWE32.RAW not found\n"); emu8k->rom = malloc(1024 * 1024); - fread(emu8k->rom, 1024 * 1024, 1, f); + if (fread(emu8k->rom, 1, 1048576, f) != 1048576) + fatal("emu8k_init(): Error reading data\n"); fclose(f); /*AWE-DUMP creates ROM images offset by 2 bytes, so if we detect this then correct it*/ diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c index 9f29c162b..c6c422a9d 100644 --- a/src/video/vid_ati_mach64.c +++ b/src/video/vid_ati_mach64.c @@ -668,6 +668,7 @@ static void mach64_accel_write_fifo(mach64_t *mach64, uint32_t addr, uint8_t val case 0x118: case 0x119: case 0x11a: case 0x11b: case 0x11e: case 0x11f: WRITE8(addr, mach64->dst_height_width, val); + /*FALLTHROUGH*/ case 0x113: if (((addr & 0x3ff) == 0x11b || (addr & 0x3ff) == 0x11f || (addr & 0x3ff) == 0x113) && !(val & 0x80)) @@ -797,6 +798,7 @@ static void mach64_accel_write_fifo(mach64_t *mach64, uint32_t addr, uint8_t val break; case 0x2b0: case 0x2b1: addr += 2; + /*FALLTHROUGH*/ case 0x2b6: case 0x2b7: WRITE8(addr, mach64->sc_top_bottom, val); break; @@ -1886,6 +1888,7 @@ uint8_t mach64_ext_readb(uint32_t addr, void *p) break; case 0x110: case 0x111: addr += 2; + /*FALLTHROUGH*/ case 0x114: case 0x115: case 0x118: case 0x119: case 0x11a: case 0x11b: case 0x11e: case 0x11f: @@ -2005,6 +2008,7 @@ uint8_t mach64_ext_readb(uint32_t addr, void *p) break; case 0x2b0: case 0x2b1: addr += 2; + /*FALLTHROUGH*/ case 0x2b6: case 0x2b7: mach64_wait_fifo_idle(mach64); READ8(addr, mach64->sc_top_bottom); diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index c4480abbc..167a3ad05 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -1249,7 +1249,7 @@ void et4000w32p_pci_write(int func, int addr, uint8_t val, void *p) et4000->linearbase &= 0x00c00000; et4000->linearbase = (et4000->pci_regs[0x13] << 24); svga->crtc[0x30] &= 3; - svga->crtc[0x30] = ((et4000->linearbase & 0x3f000000) >> 22); + svga->crtc[0x30] |= ((et4000->linearbase & 0x3f000000) >> 22); et4000w32p_recalcmapping(et4000); break; diff --git a/src/video/vid_pgc.c b/src/video/vid_pgc.c index 4ffb62a30..98fd7b87b 100644 --- a/src/video/vid_pgc.c +++ b/src/video/vid_pgc.c @@ -112,7 +112,8 @@ static const char *pgc_err_msgs[] = { "Stack \r", "Too long\r", "Area \r", - "Missing \r" + "Missing \r", + "Unknown \r" }; diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 7915e5544..9da5c1ea7 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -2076,15 +2076,9 @@ uint8_t s3_accel_in(uint16_t port, void *p) break; temp = s3->accel.pix_trans[1]; if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (s3->accel.cmd & 0x600) == 0x200 && (s3->accel.cmd & 0x100)) - { - if (s3->accel.cmd & 0x1000) s3_accel_start(16, 1, 0xffffffff, 0, s3); - else s3_accel_start(16, 1, 0xffffffff, 0, s3); - } + s3_accel_start(16, 1, 0xffffffff, 0, s3); else if ((s3->accel.cmd & 0x600) == 0x200 && (s3->accel.cmd & 0x100)) - { - if (s3->accel.cmd & 0x1000) s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3); - else s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3); - } + s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3); return temp; case 0xe14a: case 0xe2ea: if (!s3_cpu_dest(s3)) diff --git a/src/win/win.c b/src/win/win.c index 57d3412fd..7fc83249b 100644 --- a/src/win/win.c +++ b/src/win/win.c @@ -383,6 +383,7 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszArg, int nCmdShow) if (source_hwnd) PostMessage((HWND) (uintptr_t) source_hwnd, WM_HAS_SHUTDOWN, (WPARAM) 0, (LPARAM) hwndMain); + free(argw); return(1); } @@ -393,6 +394,7 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszArg, int nCmdShow) /* Handle our GUI. */ i = ui_init(nCmdShow); + free(argw); return(i); } diff --git a/src/win/win.h b/src/win/win.h index c3717e72b..6c8444a33 100644 --- a/src/win/win.h +++ b/src/win/win.h @@ -88,8 +88,8 @@ extern HICON hIcon[256]; // extern int status_is_open; -extern char openfilestring[260]; -extern WCHAR wopenfilestring[260]; +extern char openfilestring[512]; +extern WCHAR wopenfilestring[512]; extern uint8_t filterindex; diff --git a/src/win/win_dialog.c b/src/win/win_dialog.c index 729be881e..bd870ca15 100644 --- a/src/win/win_dialog.c +++ b/src/win/win_dialog.c @@ -34,8 +34,8 @@ #include "win.h" -WCHAR wopenfilestring[260]; -char openfilestring[260]; +WCHAR wopenfilestring[512]; +char openfilestring[512]; uint8_t filterindex = 0; diff --git a/src/win/win_new_floppy.c b/src/win/win_new_floppy.c index b06e41834..4bb7b30f9 100644 --- a/src/win/win_new_floppy.c +++ b/src/win/win_new_floppy.c @@ -608,6 +608,7 @@ NewFloppyDialogProcedure(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) new_floppy_msgbox(hdlg, MBX_ERROR, (wchar_t *)IDS_4108); return TRUE; } + /*FALLTHROUGH*/ case IDCANCEL: EndDialog(hdlg, 0); plat_pause(0); diff --git a/src/win/win_settings.c b/src/win/win_settings.c index 84d257b34..17dbe27c0 100644 --- a/src/win/win_settings.c +++ b/src/win/win_settings.c @@ -2924,8 +2924,9 @@ hdd_add_file_open_error: chs_enabled = 1; no_update = 0; - } else - fclose(f); + } + + fclose(f); } h = GetDlgItem(hdlg, IDC_EDIT_HD_FILE_NAME); diff --git a/src/win/win_ui.c b/src/win/win_ui.c index 1632ea27a..f15dd1069 100644 --- a/src/win/win_ui.c +++ b/src/win/win_ui.c @@ -59,8 +59,8 @@ int infocus = 1; int rctrl_is_lalt = 0; int user_resize = 0; -char openfilestring[260]; -WCHAR wopenfilestring[260]; +char openfilestring[512]; +WCHAR wopenfilestring[512]; /* Local data. */ From e44e60c660367dac89088366f96f362785cda268 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Jan 2020 05:24:33 +0100 Subject: [PATCH 153/177] Fixed the fourth batch of problems. --- src/chipset/scat.c | 41 +++++++++++++++++++++++++++++--------- src/config.c | 7 +++++-- src/cpu/808x.c | 2 +- src/cpu_new/808x.c | 2 +- src/disk/zip.c | 6 ++++-- src/floppy/fdd_86f.c | 4 ++-- src/floppy/fdd_fdi.c | 4 ++-- src/floppy/fdd_imd.c | 2 +- src/floppy/fdd_img.c | 6 ++++-- src/floppy/fdd_td0.c | 6 ++++-- src/network/net_pcap.c | 14 +++++++++---- src/scsi/scsi_buslogic.c | 4 ---- src/scsi/scsi_x54x.c | 2 +- src/sound/snd_adlibgold.c | 3 ++- src/video/vid_ati_mach64.c | 1 + src/video/vid_et4000w32.c | 2 +- src/video/vid_pgc.c | 2 -- src/video/video.c | 16 +++++++-------- src/win/win_ui.c | 17 +++++++++++----- 19 files changed, 91 insertions(+), 50 deletions(-) diff --git a/src/chipset/scat.c b/src/chipset/scat.c index 79f18d396..24b701c75 100644 --- a/src/chipset/scat.c +++ b/src/chipset/scat.c @@ -1364,13 +1364,24 @@ static void mem_write_scatw(uint32_t addr, uint16_t val, void *priv) { ems_page_t *page = (ems_page_t *)priv; - scat_t *dev = (scat_t *)page->scat; + scat_t *dev; uint32_t oldaddr = addr, chkaddr; - addr = get_addr(dev, addr, page); - chkaddr = page ? addr : oldaddr; + if (page == NULL) + dev = NULL; + else + dev = (scat_t *)page->scat; + + if (dev == NULL) + chkaddr = oldaddr; + else { + addr = get_addr(dev, addr, page); + chkaddr = addr; + } + if (chkaddr >= 0xc0000 && chkaddr < 0x100000) { - if (dev->regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xc0000) >> 15))) return; + if (dev->regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xc0000) >> 15))) + return; } if (addr < ((uint32_t)mem_size << 10)) @@ -1382,14 +1393,26 @@ static void mem_write_scatl(uint32_t addr, uint32_t val, void *priv) { ems_page_t *page = (ems_page_t *)priv; - scat_t *dev = (scat_t *)page->scat; + scat_t *dev; uint32_t oldaddr = addr, chkaddr; - addr = get_addr(dev, addr, page); - chkaddr = page ? addr : oldaddr; - if (chkaddr >= 0xc0000 && chkaddr < 0x100000) { - if (dev->regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xc0000) >> 15))) return; + if (page == NULL) + dev = NULL; + else + dev = (scat_t *)page->scat; + + if (dev == NULL) + chkaddr = oldaddr; + else { + addr = get_addr(dev, addr, page); + chkaddr = addr; } + + if (chkaddr >= 0xc0000 && chkaddr < 0x100000) { + if (dev->regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xc0000) >> 15))) + return; + } + if (addr < ((uint32_t)mem_size << 10)) *(uint32_t *)&ram[addr] = val; } diff --git a/src/config.c b/src/config.c index 2a333f952..98b0774ef 100644 --- a/src/config.c +++ b/src/config.c @@ -667,7 +667,10 @@ load_sound(void) memset(temp, '\0', sizeof(temp)); p = config_get_string(cat, "sound_type", "float"); - strcpy(temp, p); + if (strlen(p) <= 511) + strcpy(temp, p); + else + strncpy(temp, p, 511); if (!strcmp(temp, "float") || !strcmp(temp, "1")) sound_is_float = 1; else @@ -2109,7 +2112,7 @@ config_set_int(char *head, char *name, int val) ent = create_entry(section, name); sprintf(ent->data, "%i", val); - mbstowcs(ent->wdata, ent->data, sizeof_w(ent->wdata)); + mbstowcs(ent->wdata, ent->data, 512); } diff --git a/src/cpu/808x.c b/src/cpu/808x.c index bf028eeaa..fb077d046 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -1215,7 +1215,7 @@ jcc(uint8_t opcode, int cond) wait(1, 0); cpu_data = pfq_fetchb(); wait(1, 0); - if ((!cond) == (opcode & 0x01)) + if ((!cond) == !!(opcode & 0x01)) jump_short(); } diff --git a/src/cpu_new/808x.c b/src/cpu_new/808x.c index 266c48c63..060f3f1a3 100644 --- a/src/cpu_new/808x.c +++ b/src/cpu_new/808x.c @@ -1208,7 +1208,7 @@ jcc(uint8_t opcode, int cond) wait(1, 0); cpu_data = pfq_fetchb(); wait(1, 0); - if ((!cond) == (opcode & 0x01)) + if ((!cond) == !!(opcode & 0x01)) jump_short(); } diff --git a/src/disk/zip.c b/src/disk/zip.c index 9185aafae..d265fbc8b 100644 --- a/src/disk/zip.c +++ b/src/disk/zip.c @@ -2130,8 +2130,10 @@ zip_phase_data_out(scsi_common_t *sc) dev->buffer[6] = (s >> 8) & 0xff; dev->buffer[7] = s & 0xff; } - fseek(dev->drv->f, dev->drv->base + (i << 9), SEEK_SET); - fwrite(dev->buffer, 1, 512, dev->drv->f); + if (fseek(dev->drv->f, dev->drv->base + (i << 9), SEEK_SET) == -1) + fatal("zip_phase_data_out(): Error seeking\n"); + if (fwrite(dev->buffer, 1, 512, dev->drv->f) != 512) + fatal("zip_phase_data_out(): Error writing data\n"); } break; case GPCMD_MODE_SELECT_6: diff --git a/src/floppy/fdd_86f.c b/src/floppy/fdd_86f.c index 02341193a..860c424c2 100644 --- a/src/floppy/fdd_86f.c +++ b/src/floppy/fdd_86f.c @@ -3175,10 +3175,10 @@ d86f_writeback(int drive) fatal("86F write_back(): Error reading header size\n"); if (fseek(dev->f, 8, SEEK_SET) == -1) - fatal("86F write_back(): Error seeking\n"); + fatal("86F write_back(): Error seeking\n"); size = d86f_get_track_table_size(drive); if (fwrite(dev->track_offset, 1, size, dev->f) != size) - fatal("86F write_back(): Error writing data\n"); + fatal("86F write_back(): Error writing data\n"); d86f_write_tracks(drive, &dev->f, NULL); diff --git a/src/floppy/fdd_fdi.c b/src/floppy/fdd_fdi.c index fdb5af532..f9e42ed6b 100644 --- a/src/floppy/fdd_fdi.c +++ b/src/floppy/fdd_fdi.c @@ -329,14 +329,14 @@ fdi_load(int drive, wchar_t *fn) /* Allocate a drive block. */ dev = (fdi_t *)malloc(sizeof(fdi_t)); - memset(dev, 0x00, sizeof(fdi_t)); if (dev == NULL) { - free(dev); memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); return; } + memset(dev, 0x00, sizeof(fdi_t)); + d86f_unregister(drive); dev->f = plat_fopen(fn, L"rb"); diff --git a/src/floppy/fdd_imd.c b/src/floppy/fdd_imd.c index 1ff63ac6d..a9c9c21fa 100644 --- a/src/floppy/fdd_imd.c +++ b/src/floppy/fdd_imd.c @@ -190,8 +190,8 @@ track_is_xdf(int drive, int side, int track) dev->current_side_flags[side] = (dev->tracks[track][side].params[3] == 19) ? 0x08 : 0x28; return((dev->tracks[track][side].params[3] == 19) ? 2 : 1); } - return(0); } + return(0); } else { if (dev->tracks[track][side].params[4] != 0xFF) return(0); diff --git a/src/floppy/fdd_img.c b/src/floppy/fdd_img.c index 6d0c626dc..e1417254a 100644 --- a/src/floppy/fdd_img.c +++ b/src/floppy/fdd_img.c @@ -490,8 +490,10 @@ img_seek(int drive, int track) is_t0 = (track == 0) ? 1 : 0; - if (! dev->disk_at_once) - fseek(dev->f, dev->base + (track * dev->sectors * ssize * dev->sides), SEEK_SET); + if (! dev->disk_at_once) { + if (fseek(dev->f, dev->base + (track * dev->sectors * ssize * dev->sides), SEEK_SET) == -1) + fatal("img_seek(): Error seeking\n"); + } for (side = 0; side < dev->sides; side++) { if (dev->disk_at_once) { diff --git a/src/floppy/fdd_td0.c b/src/floppy/fdd_td0.c index dd2499bee..a230a7ae8 100644 --- a/src/floppy/fdd_td0.c +++ b/src/floppy/fdd_td0.c @@ -656,8 +656,10 @@ td0_initialize(int drive) state_Decode(&disk_decode, dev->imagebuf, TD0_MAX_BUFSZ); } else { td0_log("TD0: File is uncompressed\n"); - fseek(dev->f, 12, SEEK_SET); - fread(dev->imagebuf, 1, file_size - 12, dev->f); + if (fseek(dev->f, 12, SEEK_SET) == -1) + fatal("td0_initialize(): Error seeking to offet 12\n"); + if (fread(dev->imagebuf, 1, file_size - 12, dev->f) != (file_size - 12)) + fatal("td0_initialize(): Error reading image buffer\n"); } if (header[7] & 0x80) diff --git a/src/network/net_pcap.c b/src/network/net_pcap.c index 5acc9c170..771b55e8e 100644 --- a/src/network/net_pcap.c +++ b/src/network/net_pcap.c @@ -260,10 +260,16 @@ net_pcap_prepare(netdev_t *list) } for (dev=devlist; dev!=NULL; dev=dev->next) { - strcpy(list->device, dev->name); - if (dev->description) - strcpy(list->description, dev->description); - else + if (strlen(dev->name) <= 127) + strcpy(list->device, dev->name); + else + strncpy(list->device, dev->name, 127); + if (dev->description) { + if (strlen(dev->description) <= 127) + strcpy(list->description, dev->description); + else + strncpy(list->description, dev->description, 127); + } else memset(list->description, '\0', sizeof(list->description)); list++; i++; } diff --git a/src/scsi/scsi_buslogic.c b/src/scsi/scsi_buslogic.c index 182cd2282..28ecdb612 100644 --- a/src/scsi/scsi_buslogic.c +++ b/src/scsi/scsi_buslogic.c @@ -625,10 +625,6 @@ BuslogicSCSIBIOSRequestSetup(x54x_t *dev, uint8_t *CmdBuf, uint8_t *DataInBuf, u buslogic_log("Transfer Control %02X\n", ESCSICmd->DataDirection); buslogic_log("CDB Length %i\n", ESCSICmd->CDBLength); - if (ESCSICmd->DataDirection > 0x03) { - buslogic_log("Invalid control byte: %02X\n", - ESCSICmd->DataDirection); - } } target_cdb_len = 12; diff --git a/src/scsi/scsi_x54x.c b/src/scsi/scsi_x54x.c index e395923c6..8c8a5985d 100644 --- a/src/scsi/scsi_x54x.c +++ b/src/scsi/scsi_x54x.c @@ -415,7 +415,7 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba) x54x_log("BIOS Command = 0x%02X\n", cmd->command); - if ((cmd->id > max_id) || (cmd->lun > 7)) { + if (cmd->id > max_id) { x54x_log("BIOS Target ID %i or LUN %i are above maximum\n", cmd->id, cmd->lun); ret = 0x80; diff --git a/src/sound/snd_adlibgold.c b/src/sound/snd_adlibgold.c index 828ea518d..d4a29412d 100644 --- a/src/sound/snd_adlibgold.c +++ b/src/sound/snd_adlibgold.c @@ -776,7 +776,8 @@ void *adgold_init(const device_t *info) f = nvr_fopen(L"adgold.bin", L"rb"); if (f) { - fread(adgold->adgold_eeprom, 0x1a, 1, f); + if (fread(adgold->adgold_eeprom, 1, 0x1a, f) != 0x1a) + fatal("adgold_init(): Error reading data\n"); fclose(f); } diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c index c6c422a9d..a27621dde 100644 --- a/src/video/vid_ati_mach64.c +++ b/src/video/vid_ati_mach64.c @@ -789,6 +789,7 @@ static void mach64_accel_write_fifo(mach64_t *mach64, uint32_t addr, uint8_t val break; case 0x2a4: case 0x2a5: addr += 2; + /*FALLTHROUGH*/ case 0x2aa: case 0x2ab: WRITE8(addr, mach64->sc_left_right, val); break; diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index 167a3ad05..c941d85fd 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -1247,7 +1247,7 @@ void et4000w32p_pci_write(int func, int addr, uint8_t val, void *p) case 0x13: et4000->linearbase &= 0x00c00000; - et4000->linearbase = (et4000->pci_regs[0x13] << 24); + et4000->linearbase |= (et4000->pci_regs[0x13] << 24); svga->crtc[0x30] &= 3; svga->crtc[0x30] |= ((et4000->linearbase & 0x3f000000) >> 22); et4000w32p_recalcmapping(et4000); diff --git a/src/video/vid_pgc.c b/src/video/vid_pgc.c index 98fd7b87b..0dbaa9595 100644 --- a/src/video/vid_pgc.c +++ b/src/video/vid_pgc.c @@ -1680,7 +1680,6 @@ pgc_wake(pgc_t *dev) void pgc_sleep(pgc_t *dev) { - uint8_t *n = NULL; pgc_log("PGC: sleeping on %i %i %i %i 0x%02x 0x%02x\n", dev->stopped, dev->waiting_input_fifo, dev->waiting_output_fifo, @@ -1690,7 +1689,6 @@ pgc_sleep(pgc_t *dev) if (dev->stopped) { dev->waiting_input_fifo = 0; dev->waiting_output_fifo = 0; - *n = 0; return; } diff --git a/src/video/video.c b/src/video/video.c index 1cbdfdac4..e7504f4b5 100644 --- a/src/video/video.c +++ b/src/video/video.c @@ -920,14 +920,14 @@ loadfont(wchar_t *s, int format) case 0: /* MDA */ for (c=0; c<256; c++) for (d=0; d<8; d++) - fontdatm[c][d] = fgetc(f); + fontdatm[c][d] = fgetc(f) & 0xff; for (c=0; c<256; c++) for (d=0; d<8; d++) - fontdatm[c][d+8] = fgetc(f); + fontdatm[c][d+8] = fgetc(f) & 0xff; (void)fseek(f, 4096+2048, SEEK_SET); for (c=0; c<256; c++) for (d=0; d<8; d++) - fontdat[c][d] = fgetc(f); + fontdat[c][d] = fgetc(f) & 0xff; break; case 1: /* PC200 */ @@ -950,19 +950,19 @@ loadfont(wchar_t *s, int format) case 2: /* CGA */ for (c=0; c<256; c++) for (d=0; d<8; d++) - fontdat[c][d] = fgetc(f); + fontdat[c][d] = fgetc(f) & 0xff; break; case 3: /* Wyse 700 */ for (c=0; c<512; c++) for (d=0; d<32; d++) - fontdatw[c][d] = fgetc(f); + fontdatw[c][d] = fgetc(f) & 0xff; break; case 4: /* MDSI Genius */ for (c=0; c<256; c++) for (d=0; d<16; d++) - fontdat8x12[c][d] = fgetc(f); + fontdat8x12[c][d] = fgetc(f) & 0xff; break; case 5: /* Toshiba 3100e */ @@ -1006,7 +1006,7 @@ loadfont(wchar_t *s, int format) for (c = 0; c < 16384; c++) { for (d = 0; d < 32; d++) - fontdatksc5601[c].chr[d]=getc(f); + fontdatksc5601[c].chr[d]=fgetc(f) & 0xff; } break; @@ -1026,7 +1026,7 @@ loadfont(wchar_t *s, int format) case 8: /* Amstrad PC1512, Toshiba T1000/T1200 */ for (c = 0; c < 2048; c++) /* Allow up to 2048 chars */ for (d=0; d<8; d++) - fontdat[c][d] = fgetc(f); + fontdat[c][d] = fgetc(f) & 0xff; break; case 9: /* Image Manager 1024 native font */ diff --git a/src/win/win_ui.c b/src/win/win_ui.c index f15dd1069..a189fa87b 100644 --- a/src/win/win_ui.c +++ b/src/win/win_ui.c @@ -1077,9 +1077,12 @@ wchar_t * ui_window_title(wchar_t *s) { if (! video_fullscreen) { - if (s != NULL) - wcscpy(wTitle, s); - else + if (s != NULL) { + if (wcslen(s) <= 512) + wcscpy(wTitle, s); + else + wcsncpy(wTitle, s, 512); + } else s = wTitle; SetWindowText(hwndMain, s); @@ -1097,7 +1100,7 @@ void plat_pause(int p) { static wchar_t oldtitle[512]; - wchar_t title[512]; + wchar_t title[512], *t; /* If un-pausing, as the renderer if that's OK. */ if (p == 0) @@ -1113,7 +1116,11 @@ plat_pause(int p) } if (p) { - wcscpy(oldtitle, ui_window_title(NULL)); + t = ui_window_title(NULL); + if (wcslen(t) <= 511) + wcscpy(oldtitle, ui_window_title(NULL)); + else + wcsncpy(oldtitle, ui_window_title(NULL), 511); wcscpy(title, oldtitle); wcscat(title, L" - PAUSED -"); ui_window_title(title); From 94ba8ec38cd56bb20467ad9bd27698f7ebbb5c5d Mon Sep 17 00:00:00 2001 From: Melissa Goad Date: Wed, 15 Jan 2020 09:42:14 -0600 Subject: [PATCH 154/177] Fix XTIDE ROM loading (#547) --- src/disk/hdc_xtide.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/disk/hdc_xtide.c b/src/disk/hdc_xtide.c index 3a6cf6656..2e7a5b359 100644 --- a/src/disk/hdc_xtide.c +++ b/src/disk/hdc_xtide.c @@ -135,7 +135,7 @@ xtide_init(const device_t *info) memset(xtide, 0x00, sizeof(xtide_t)); rom_init(&xtide->bios_rom, ROM_PATH_XT, - 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + 0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); xtide->ide_board = ide_xtide_init(); @@ -162,7 +162,7 @@ xtide_at_init(const device_t *info) memset(xtide, 0x00, sizeof(xtide_t)); rom_init(&xtide->bios_rom, ROM_PATH_AT, - 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + 0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); device_add(&ide_isa_2ch_device); @@ -185,7 +185,7 @@ xtide_acculogic_init(const device_t *info) memset(xtide, 0x00, sizeof(xtide_t)); rom_init(&xtide->bios_rom, ROM_PATH_PS2, - 0xc8000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + 0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); xtide->ide_board = ide_xtide_init(); @@ -223,7 +223,7 @@ xtide_at_ps2_init(const device_t *info) memset(xtide, 0x00, sizeof(xtide_t)); rom_init(&xtide->bios_rom, ROM_PATH_PS2AT, - 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + 0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); device_add(&ide_isa_2ch_device); From a575bd7e8b571408e66ef8c78b389aa72db50943 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hrdli=C4=8Dka?= Date: Wed, 15 Jan 2020 18:48:22 +0100 Subject: [PATCH 155/177] fix more issues reported by coverity --- src/chipset/scat.c | 4 ++-- src/config.c | 2 +- src/disk/hdd_image.c | 6 ++++-- src/disk/zip.c | 2 +- src/machine/m_at_t3100e.c | 7 +++++-- src/pc.c | 2 +- src/printer/prt_escp.c | 9 +++++++-- src/win/win_dialog.c | 2 +- src/win/win_settings.c | 2 +- 9 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/chipset/scat.c b/src/chipset/scat.c index 24b701c75..d5712a98c 100644 --- a/src/chipset/scat.c +++ b/src/chipset/scat.c @@ -1380,7 +1380,7 @@ mem_write_scatw(uint32_t addr, uint16_t val, void *priv) } if (chkaddr >= 0xc0000 && chkaddr < 0x100000) { - if (dev->regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xc0000) >> 15))) + if (dev != NULL && (dev->regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xc0000) >> 15)))) return; } @@ -1409,7 +1409,7 @@ mem_write_scatl(uint32_t addr, uint32_t val, void *priv) } if (chkaddr >= 0xc0000 && chkaddr < 0x100000) { - if (dev->regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xc0000) >> 15))) + if (dev != NULL && (dev->regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xc0000) >> 15)))) return; } diff --git a/src/config.c b/src/config.c index 98b0774ef..a174c2c89 100644 --- a/src/config.c +++ b/src/config.c @@ -309,7 +309,7 @@ config_read(wchar_t *fn) /* Create a new section and insert it. */ ns = malloc(sizeof(section_t)); memset(ns, 0x00, sizeof(section_t)); - strncpy(ns->name, sname, sizeof(ns->name)); + strncpy(ns->name, sname, sizeof(ns->name) - 1); list_add(&ns->list, &config_head); /* New section is now the current one. */ diff --git a/src/disk/hdd_image.c b/src/disk/hdd_image.c index dbffb16d3..6a6e4ee02 100644 --- a/src/disk/hdd_image.c +++ b/src/disk/hdd_image.c @@ -125,9 +125,11 @@ image_is_hdx(const wchar_t *s, int check_signature) f = plat_fopen((wchar_t *)s, L"rb"); if (!f) return 0; - fseeko64(f, 0, SEEK_END); + if (fseeko64(f, 0, SEEK_END)) + fatal("image_is_hdx(): Error while seeking"); filelen = ftello64(f); - fseeko64(f, 0, SEEK_SET); + if (fseeko64(f, 0, SEEK_SET)) + fatal("image_is_hdx(): Error while seeking"); if (filelen < 44) { if (f != NULL) fclose(f); diff --git a/src/disk/zip.c b/src/disk/zip.c index d265fbc8b..1bbec776b 100644 --- a/src/disk/zip.c +++ b/src/disk/zip.c @@ -530,7 +530,7 @@ zip_load(zip_t *dev, wchar_t *fn) if (fseek(dev->drv->f, dev->drv->base, SEEK_SET) == -1) fatal("zip_load(): Error seeking to the beginning of the file\n"); - memcpy(dev->drv->image_path, fn, sizeof(dev->drv->image_path)); + wcsncpy(dev->drv->image_path, fn, sizeof_w(dev->drv->image_path)); return 1; } diff --git a/src/machine/m_at_t3100e.c b/src/machine/m_at_t3100e.c index 2288b1051..9455aebb8 100644 --- a/src/machine/m_at_t3100e.c +++ b/src/machine/m_at_t3100e.c @@ -571,8 +571,11 @@ uint8_t t3100e_ems_in(uint16_t addr, void *p) { struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)p; - return regs->page[port_to_page(addr)]; - + int page = port_to_page(addr); + if(page >= 0) + return regs->page[page]; + else + fatal("t3100e_ems_in(): invalid address"); } /* Write EMS page register */ diff --git a/src/pc.c b/src/pc.c index 8e9160b78..e2bb17f1a 100644 --- a/src/pc.c +++ b/src/pc.c @@ -323,7 +323,7 @@ pc_init(int argc, wchar_t *argv[]) uint32_t *uid, *shwnd; /* Grab the executable's full path. */ - plat_get_exe_name(exe_path, sizeof(exe_path)-1); + plat_get_exe_name(exe_path, sizeof_w(exe_path)-1); p = plat_get_filename(exe_path); *p = L'\0'; diff --git a/src/printer/prt_escp.c b/src/printer/prt_escp.c index f89cbc621..c74449ba6 100644 --- a/src/printer/prt_escp.c +++ b/src/printer/prt_escp.c @@ -10,12 +10,12 @@ * * Version: @(#)prt_escp.c 1.0.7 2019/09/23 * - * Authors: Michael Drüing, + * Authors: Michael Dr�ing, * Fred N. van Kempen, * * Based on code by Frederic Weymann (originally for DosBox.) * - * Copyright 2018,2019 Michael Drüing. + * Copyright 2018,2019 Michael Dr�ing. * Copyright 2019,2019 Fred N. van Kempen. * * Redistribution and use in source and binary forms, with @@ -2058,6 +2058,11 @@ escp_init(void *lpt) dev->lpt = lpt; /* Create a full pathname for the font files. */ + if(wcslen(exe_path) >= sizeof_w(dev->fontpath)) { + free(dev); + return(NULL); + } + wcscpy(dev->fontpath, exe_path); plat_path_slash(dev->fontpath); wcscat(dev->fontpath, L"roms/printer/fonts/"); diff --git a/src/win/win_dialog.c b/src/win/win_dialog.c index bd870ca15..bf93b474c 100644 --- a/src/win/win_dialog.c +++ b/src/win/win_dialog.c @@ -139,7 +139,7 @@ file_dlg_w(HWND hwnd, WCHAR *f, WCHAR *fn, int save) * not use the contents of szFile to initialize itself. */ memcpy(ofn.lpstrFile, fn, (wcslen(fn) << 1) + 2); - ofn.nMaxFile = 259; + ofn.nMaxFile = sizeof_w(wopenfilestring); ofn.lpstrFilter = f; ofn.nFilterIndex = 1; ofn.lpstrFileTitle = NULL; diff --git a/src/win/win_settings.c b/src/win/win_settings.c index 17dbe27c0..f72ee200d 100644 --- a/src/win/win_settings.c +++ b/src/win/win_settings.c @@ -2846,6 +2846,7 @@ win_settings_hard_disks_add_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM f = _wfopen(wopenfilestring, (existing & 1) ? L"rb" : L"wb"); if (f == NULL) { hdd_add_file_open_error: + fclose(f); settings_msgbox(MBX_ERROR, (existing & 1) ? (wchar_t *)IDS_4107 : (wchar_t *)IDS_4108); return TRUE; } @@ -2876,7 +2877,6 @@ hdd_add_file_open_error: } else { fseeko64(f, 0, SEEK_END); size = ftello64(f); - fclose(f); if (((size % 17) == 0) && (size <= 142606336)) { spt = 17; if (size <= 26738688) From 9b80d4b1511fc649a21b21a1f4ca6ab89b3b2c66 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 16 Jan 2020 00:40:42 +0100 Subject: [PATCH 156/177] Made the sanity fatal() milder in rom_load_linear() as well. --- src/rom.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/rom.c b/src/rom.c index 17c31e3ba..8d8c23e99 100644 --- a/src/rom.c +++ b/src/rom.c @@ -174,18 +174,14 @@ rom_load_linear(wchar_t *fn, uint32_t addr, int sz, int off, uint8_t *ptr) /* Make sure we only look at the base-256K offset. */ if (addr >= 0x40000) - { addr = 0; - } else - { addr &= 0x03ffff; - } if (ptr != NULL) { if (fseek(f, off, SEEK_SET) == -1) fatal("rom_load_linear(): Error seeking to the beginning of the file\n"); - if (fread(ptr+addr, 1, sz, f) != sz) + if (fread(ptr+addr, 1, sz, f) > sz) fatal("rom_load_linear(): Error reading data\n"); } From d516716b38abf33b24c1cd49713bad884c5be066 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 16 Jan 2020 05:48:36 +0100 Subject: [PATCH 157/177] Changed the way device timers are run, fixes DesqView/X. --- src/cpu/386.c | 8 ++++++-- src/cpu/386_dynarec.c | 8 ++++++-- src/cpu/386_dynarec_ops.c | 8 +++++--- src/cpu_new/386.c | 8 ++++++-- src/cpu_new/386_dynarec.c | 8 ++++++-- src/cpu_new/386_dynarec_ops.c | 5 ++++- 6 files changed, 33 insertions(+), 12 deletions(-) diff --git a/src/cpu/386.c b/src/cpu/386.c index 7694a0be4..5c7273e04 100644 --- a/src/cpu/386.c +++ b/src/cpu/386.c @@ -73,8 +73,12 @@ extern int dontprint; #define OP_TABLE(name) ops_ ## name -#define CLOCK_CYCLES(c) cycles -= (c) -#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c) +#define CLOCK_CYCLES(c) do { cycles -= (c); \ + if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc)) \ + timer_process(); } while(0) +#define CLOCK_CYCLES_ALWAYS(c) do { cycles -= (c); \ + if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc)) \ + timer_process(); } while(0) #include "x86_ops.h" diff --git a/src/cpu/386_dynarec.c b/src/cpu/386_dynarec.c index 7a26ae37d..91a9eeeeb 100644 --- a/src/cpu/386_dynarec.c +++ b/src/cpu/386_dynarec.c @@ -710,8 +710,12 @@ void leave_smm() } #define OP_TABLE(name) ops_ ## name -#define CLOCK_CYCLES(c) cycles -= (c) -#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c) +#define CLOCK_CYCLES(c) do { cycles -= (c); \ + if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc)) \ + timer_process(); } while(0) +#define CLOCK_CYCLES_ALWAYS(c) do { cycles -= (c); \ + if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc)) \ + timer_process(); } while(0) #include "386_ops.h" diff --git a/src/cpu/386_dynarec_ops.c b/src/cpu/386_dynarec_ops.c index aa4784ba8..ade318301 100644 --- a/src/cpu/386_dynarec_ops.c +++ b/src/cpu/386_dynarec_ops.c @@ -9,6 +9,7 @@ #endif #include "../86box.h" #include "cpu.h" +#include "../timer.h" #include "x86.h" #include "x86_ops.h" #include "x87.h" @@ -63,7 +64,8 @@ static __inline void fetch_ea_16_long(uint32_t rmdat) #define PREFETCH_FLUSH() #define OP_TABLE(name) dynarec_ops_ ## name -#define CLOCK_CYCLES(c) -#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c) - +#define CLOCK_CYCLES(c) +#define CLOCK_CYCLES_ALWAYS(c) do { cycles -= (c); \ + if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc)) \ + timer_process(); } while(0) #include "386_ops.h" diff --git a/src/cpu_new/386.c b/src/cpu_new/386.c index 2b2268920..f70424b10 100644 --- a/src/cpu_new/386.c +++ b/src/cpu_new/386.c @@ -175,8 +175,12 @@ fetch_ea_16_long(uint32_t rmdat) #define OP_TABLE(name) ops_ ## name -#define CLOCK_CYCLES(c) cycles -= (c) -#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c) +#define CLOCK_CYCLES(c) do { cycles -= (c); \ + if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc)) \ + timer_process(); } while(0) +#define CLOCK_CYCLES_ALWAYS(c) do { cycles -= (c); \ + if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc)) \ + timer_process(); } while(0) #include "x86_ops.h" diff --git a/src/cpu_new/386_dynarec.c b/src/cpu_new/386_dynarec.c index 0081aceb8..27d706061 100644 --- a/src/cpu_new/386_dynarec.c +++ b/src/cpu_new/386_dynarec.c @@ -471,8 +471,12 @@ void leave_smm() } #define OP_TABLE(name) ops_ ## name -#define CLOCK_CYCLES(c) cycles -= (c) -#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c) +#define CLOCK_CYCLES(c) do { cycles -= (c); \ + if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc)) \ + timer_process(); } while(0) +#define CLOCK_CYCLES_ALWAYS(c) do { cycles -= (c); \ + if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc)) \ + timer_process(); } while(0) #include "386_ops.h" diff --git a/src/cpu_new/386_dynarec_ops.c b/src/cpu_new/386_dynarec_ops.c index 343ab13c3..f5224c257 100644 --- a/src/cpu_new/386_dynarec_ops.c +++ b/src/cpu_new/386_dynarec_ops.c @@ -9,6 +9,7 @@ #endif #include "../86box.h" #include "cpu.h" +#include "../timer.h" #include "x86.h" #include "x86_ops.h" #include "x87.h" @@ -63,6 +64,8 @@ static inline void fetch_ea_16_long(uint32_t rmdat) #define OP_TABLE(name) dynarec_ops_ ## name /*Temporary*/ #define CLOCK_CYCLES(c) -#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c) +#define CLOCK_CYCLES_ALWAYS(c) do { cycles -= (c); \ + if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc)) \ + timer_process(); } while(0) #include "386_ops.h" From 4401a8d0297e001802d72109f4d1a1c680824b11 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 16 Jan 2020 05:48:56 +0100 Subject: [PATCH 158/177] Ported some small fixes from PCem that only apply to the new recompiler. --- src/cpu_new/codegen_backend_x86-64_ops.c | 2 +- src/cpu_new/codegen_backend_x86_ops.c | 2 +- src/cpu_new/codegen_backend_x86_ops_sse.c | 2 +- src/mem_new.c | 3 +++ 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/cpu_new/codegen_backend_x86-64_ops.c b/src/cpu_new/codegen_backend_x86-64_ops.c index 74173e626..8bb91da1c 100644 --- a/src/cpu_new/codegen_backend_x86-64_ops.c +++ b/src/cpu_new/codegen_backend_x86-64_ops.c @@ -1018,7 +1018,7 @@ void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_d codegen_addbyte3(block, 0xc7, 0x04, 0x24); /*MOV [ESP], imm_data*/ codegen_addlong(block, imm_data); } - else if (offset >= -80 || offset < 0x80) + else if (offset >= -0x80 && offset < 0x80) { codegen_alloc_bytes(block, 8); codegen_addbyte4(block, 0xc7, 0x44, 0x24, offset & 0xff); /*MOV offset[ESP], imm_data*/ diff --git a/src/cpu_new/codegen_backend_x86_ops.c b/src/cpu_new/codegen_backend_x86_ops.c index 18f0171a5..f5010e356 100644 --- a/src/cpu_new/codegen_backend_x86_ops.c +++ b/src/cpu_new/codegen_backend_x86_ops.c @@ -763,7 +763,7 @@ void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_d codegen_addbyte3(block, 0xc7, 0x04, 0x24); /*MOV [ESP], imm_data*/ codegen_addlong(block, imm_data); } - else if (offset >= -80 || offset < 0x80) + else if (offset >= -0x80 && offset < 0x80) { codegen_alloc_bytes(block, 8); codegen_addbyte4(block, 0xc7, 0x44, 0x24, offset & 0xff); /*MOV offset[ESP], imm_data*/ diff --git a/src/cpu_new/codegen_backend_x86_ops_sse.c b/src/cpu_new/codegen_backend_x86_ops_sse.c index 641d16532..d829e4097 100644 --- a/src/cpu_new/codegen_backend_x86_ops_sse.c +++ b/src/cpu_new/codegen_backend_x86_ops_sse.c @@ -204,7 +204,7 @@ void host_x86_MOVQ_STACK_OFFSET_XREG(codeblock_t *block, int offset, int src_reg codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ [ESP], src_reg*/ codegen_addbyte(block, 0x24); } - else if (offset >= -80 || offset < 0x80) + else if (offset >= -0x80 && offset < 0x80) { codegen_alloc_bytes(block, 6); codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ offset[ESP], src_reg*/ diff --git a/src/mem_new.c b/src/mem_new.c index 4fd4dbc91..84f3aa597 100644 --- a/src/mem_new.c +++ b/src/mem_new.c @@ -1688,6 +1688,9 @@ mem_log("MEM: reset: new pages=%08lx, pages_sz=%i\n", pages, pages_sz); mem_mapping_disable(&ram_remapped_mapping); mem_a20_init(); + + purgable_page_list_head = 0; + purgeable_page_count = 0; } From 8f17d4ed8d3b19c5a163bc042e2f41541822bacc Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 16 Jan 2020 20:48:10 +0100 Subject: [PATCH 159/177] Fixed two warnings. --- src/floppy/fdd_json.c | 3 --- src/machine/m_at_t3100e.c | 6 ++++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/floppy/fdd_json.c b/src/floppy/fdd_json.c index cfc0e43e3..465e1d6a0 100644 --- a/src/floppy/fdd_json.c +++ b/src/floppy/fdd_json.c @@ -395,7 +395,6 @@ json_seek(int drive, int track) int side, sector; int rate, gap2, gap3, pos; int ssize, rsec, asec; - int interleave_type; if (dev->f == NULL) { json_log("JSON: seek: no file loaded!\n"); @@ -415,8 +414,6 @@ json_seek(int drive, int track) d86f_reset_index_hole_pos(drive, 1); d86f_destroy_linked_lists(drive, 1); - interleave_type = 0; - if (track > dev->tracks) { d86f_zero_track(drive); return; diff --git a/src/machine/m_at_t3100e.c b/src/machine/m_at_t3100e.c index 9455aebb8..6d25453b6 100644 --- a/src/machine/m_at_t3100e.c +++ b/src/machine/m_at_t3100e.c @@ -572,10 +572,12 @@ uint8_t t3100e_ems_in(uint16_t addr, void *p) struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)p; int page = port_to_page(addr); - if(page >= 0) + if (page >= 0) return regs->page[page]; - else + else { fatal("t3100e_ems_in(): invalid address"); + return 0xff; + } } /* Write EMS page register */ From ebf0d1ef3af11852a4a5caff096a7686ccaa474b Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 16 Jan 2020 20:49:58 +0100 Subject: [PATCH 160/177] Fixed MSR's on AMD CPU's - the VIA machine now works without issues with the high-speed AMD CPU's. --- src/cpu/808x.c | 2 + src/cpu/cpu.c | 118 +++++++++-- src/cpu/cpu.h | 2 + src/cpu_new/808x.c | 2 + src/cpu_new/cpu.c | 419 ++++++++++++++++++++++++++++++++++++++-- src/cpu_new/cpu.h | 13 +- src/cpu_new/cpu_table.c | 18 +- 7 files changed, 530 insertions(+), 44 deletions(-) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index fb077d046..929d08bb6 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -964,6 +964,8 @@ reset_common(int hard) prefetching = 1; takeint = 0; + + cpu_ven_reset(); } diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 3e6f9b0e8..23289d056 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -191,8 +191,9 @@ uint64_t ecx570_msr = 0; #if defined(DEV_BRANCH) && defined(USE_AMD_K) uint64_t ecx83_msr = 0; /* AMD K5 and K6 MSR's. */ -uint64_t star = 0; /* These are K6-only. */ -uint64_t sfmask = 0; +uint64_t star = 0; /* AMD K6-2+. */ + +uint64_t amd_efer = 0, amd_whcr = 0; /* AMD K6-2+ registers. */ #endif int timing_rr; @@ -1193,9 +1194,9 @@ cpu_set(void) case CPU_K5: case CPU_5K86: #ifdef USE_DYNAREC - x86_setopcodes(ops_386, ops_k6_0f, dynarec_ops_386, dynarec_ops_k6_0f); + x86_setopcodes(ops_386, ops_pentiummmx_0f, dynarec_ops_386, dynarec_ops_pentiummmx_0f); #else - x86_setopcodes(ops_386, ops_k6_0f); + x86_setopcodes(ops_386, ops_pentiummmx_0f); #endif timing_rr = 1; /*register dest - register src*/ timing_rm = 2; /*register dest - memory src*/ @@ -1214,9 +1215,9 @@ cpu_set(void) case CPU_K6: #ifdef USE_DYNAREC - x86_setopcodes(ops_386, ops_k6_0f, dynarec_ops_386, dynarec_ops_k6_0f); + x86_setopcodes(ops_386, ops_pentiummmx_0f, dynarec_ops_386, dynarec_ops_pentiummmx_0f); #else - x86_setopcodes(ops_386, ops_k6_0f); + x86_setopcodes(ops_386, ops_pentiummmx_0f); #endif timing_rr = 1; /*register dest - register src*/ timing_rm = 2; /*register dest - memory src*/ @@ -1801,6 +1802,24 @@ cpu_CPUID(void) } } +void cpu_ven_reset(void) +{ +#if defined(DEV_BRANCH) && defined(USE_AMD_K) + switch (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type) + { + case CPU_K5: + case CPU_5K86: + case CPU_K6: + amd_efer = amd_whcr = 0ULL; + break; + case CPU_K6_2: + amd_efer = amd_whcr = 0ULL; + star = 0ULL; + break; + } +#endif +} + void cpu_RDMSR() { switch (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type) @@ -1842,24 +1861,57 @@ void cpu_RDMSR() EAX = EDX = 0; switch (ECX) { - case 0x0e: + case 0x0000000e: EAX = msr.tr12; break; - case 0x10: + case 0x00000010: EAX = tsc & 0xffffffff; EDX = tsc >> 32; break; - case 0x83: + case 0x00000083: EAX = ecx83_msr & 0xffffffff; EDX = ecx83_msr >> 32; break; + case 0xC0000080: + EAX = amd_efer & 0xffffffff; + EDX = amd_efer >> 32; + break; + case 0xC0000082: + EAX = amd_whcr & 0xffffffff; + EDX = amd_whcr >> 32; + break; + default: + x86gpf(NULL, 0); + break; + } + break; + + case CPU_K6_2: + EAX = EDX = 0; + switch (ECX) + { + case 0x0000000e: + EAX = msr.tr12; + break; + case 0x00000010: + EAX = tsc & 0xffffffff; + EDX = tsc >> 32; + break; + case 0x00000083: + EAX = ecx83_msr & 0xffffffff; + EDX = ecx83_msr >> 32; + break; + case 0xC0000080: + EAX = amd_efer & 0xffffffff; + EDX = amd_efer >> 32; + break; case 0xC0000081: EAX = star & 0xffffffff; EDX = star >> 32; break; - case 0xC0000084: - EAX = sfmask & 0xffffffff; - EDX = sfmask >> 32; + case 0xC0000082: + EAX = amd_whcr & 0xffffffff; + EDX = amd_whcr >> 32; break; default: x86gpf(NULL, 0); @@ -2082,11 +2134,49 @@ void cpu_WRMSR() case 0x83: ecx83_msr = EAX | ((uint64_t)EDX << 32); break; + case 0xC0000080: + temp = EAX | ((uint64_t)EDX << 32); + if (temp & ~1ULL) + x86gpf(NULL, 0); + else + amd_efer = temp; + break; + case 0xC0000082: + amd_whcr = EAX | ((uint64_t)EDX << 32); + break; + default: + x86gpf(NULL, 0); + break; + } + break; + + case CPU_K6_2: + switch (ECX) + { + case 0x0e: + msr.tr12 = EAX & 0x228; + break; + case 0x10: + tsc = EAX | ((uint64_t)EDX << 32); + break; + case 0x83: + ecx83_msr = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000080: + temp = EAX | ((uint64_t)EDX << 32); + if (temp & ~1ULL) + x86gpf(NULL, 0); + else + amd_efer = temp; + break; case 0xC0000081: star = EAX | ((uint64_t)EDX << 32); break; - case 0xC0000084: - sfmask = EAX | ((uint64_t)EDX << 32); + case 0xC0000082: + amd_whcr = EAX | ((uint64_t)EDX << 32); + break; + default: + x86gpf(NULL, 0); break; } break; diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 62557bbd5..12a50473b 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -505,6 +505,8 @@ extern void x87_reset(void); extern int cpu_effective, cpu_alt_reset; extern void cpu_dynamic_switch(int new_cpu); +extern void cpu_ven_reset(void); + #endif /*EMU_CPU_H*/ #endif diff --git a/src/cpu_new/808x.c b/src/cpu_new/808x.c index 060f3f1a3..686ea9e0c 100644 --- a/src/cpu_new/808x.c +++ b/src/cpu_new/808x.c @@ -957,6 +957,8 @@ reset_common(int hard) prefetching = 1; takeint = 0; + + cpu_ven_reset(); } diff --git a/src/cpu_new/cpu.c b/src/cpu_new/cpu.c index 1d2c0fb19..0c1b212c3 100644 --- a/src/cpu_new/cpu.c +++ b/src/cpu_new/cpu.c @@ -196,8 +196,12 @@ uint64_t ecx570_msr = 0; #endif uint64_t ecx83_msr = 0; /* AMD K5 and K6 MSR's. */ -uint64_t star = 0; /* These are K6-only. */ -uint64_t sfmask = 0; +uint64_t star = 0; /* AMD K6-2+. */ + +uint64_t amd_efer = 0, amd_whcr = 0, /* AMD K6-2+ registers. */ + amd_uwccr = 0, amd_epmr = 0, + amd_psor = 0, amd_pfir = 0, + amd_l2aar = 0; int timing_rr; int timing_mr, timing_mrl; @@ -1280,9 +1284,9 @@ cpu_set(void) case CPU_K6: #ifdef USE_DYNAREC - x86_setopcodes(ops_386, ops_k6_0f, dynarec_ops_386, dynarec_ops_k6_0f); + x86_setopcodes(ops_386, ops_pentiummmx_0f, dynarec_ops_386, dynarec_ops_pentiummmx_0f); #else - x86_setopcodes(ops_386, ops_k6_0f); + x86_setopcodes(ops_386, ops_pentiummmx_0f); #endif timing_rr = 1; /*register dest - register src*/ timing_rm = 2; /*register dest - memory src*/ @@ -1322,6 +1326,7 @@ cpu_set(void) break; case CPU_K6_2: + case CPU_K6_2C: case CPU_K6_3: case CPU_K6_2P: case CPU_K6_3P: @@ -1870,6 +1875,7 @@ cpu_CPUID(void) break; case CPU_K6_2: + case CPU_K6_2C: switch (EAX) { case 0: @@ -2200,6 +2206,44 @@ cpu_CPUID(void) } } +void cpu_ven_reset(void) +{ + switch (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type) + { + case CPU_K5: + case CPU_5K86: + case CPU_K6: + amd_efer = amd_whcr = 0ULL; + break; + case CPU_K6_2: + amd_efer = amd_whcr = 0ULL; + star = 0ULL; + break; + case CPU_K6_2C: + amd_efer = 2ULL; + amd_whcr = star = 0ULL; + amd_psor = 0x018cULL; + amd_uwccr = 0ULL; + break; + case CPU_K6_3: + amd_efer = 2ULL; + amd_whcr = star = 0ULL; + amd_psor = 0x008cULL; + amd_uwccr = 0ULL; + amd_pfir = amd_l2aar = 0ULL; + break; + case CPU_K6_2P: + case CPU_K6_3P: + amd_efer = 2ULL; + amd_whcr = star = 0ULL; + amd_psor = 0x008cULL; + amd_uwccr = 0ULL; + amd_pfir = amd_l2aar = 0ULL; + amd_epmr = 0ULL; + break; + } +} + void cpu_RDMSR() { switch (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type) @@ -2238,31 +2282,208 @@ void cpu_RDMSR() case CPU_K5: case CPU_5K86: case CPU_K6: - case CPU_K6_2: - case CPU_K6_3: - case CPU_K6_2P: - case CPU_K6_3P: EAX = EDX = 0; switch (ECX) { - case 0x0e: + case 0x0000000e: EAX = msr.tr12; break; - case 0x10: + case 0x00000010: EAX = tsc & 0xffffffff; EDX = tsc >> 32; break; - case 0x83: + case 0x00000083: EAX = ecx83_msr & 0xffffffff; EDX = ecx83_msr >> 32; break; + case 0xC0000080: + EAX = amd_efer & 0xffffffff; + EDX = amd_efer >> 32; + break; + case 0xC0000082: + EAX = amd_whcr & 0xffffffff; + EDX = amd_whcr >> 32; + break; + default: + x86gpf(NULL, 0); + break; + } + break; + + case CPU_K6_2: + EAX = EDX = 0; + switch (ECX) + { + case 0x0000000e: + EAX = msr.tr12; + break; + case 0x00000010: + EAX = tsc & 0xffffffff; + EDX = tsc >> 32; + break; + case 0x00000083: + EAX = ecx83_msr & 0xffffffff; + EDX = ecx83_msr >> 32; + break; + case 0xC0000080: + EAX = amd_efer & 0xffffffff; + EDX = amd_efer >> 32; + break; case 0xC0000081: EAX = star & 0xffffffff; EDX = star >> 32; break; - case 0xC0000084: - EAX = sfmask & 0xffffffff; - EDX = sfmask >> 32; + case 0xC0000082: + EAX = amd_whcr & 0xffffffff; + EDX = amd_whcr >> 32; + break; + default: + x86gpf(NULL, 0); + break; + } + break; + + case CPU_K6_2C: + EAX = EDX = 0; + switch (ECX) + { + case 0x0000000e: + EAX = msr.tr12; + break; + case 0x00000010: + EAX = tsc & 0xffffffff; + EDX = tsc >> 32; + break; + case 0x00000083: + EAX = ecx83_msr & 0xffffffff; + EDX = ecx83_msr >> 32; + break; + case 0xC0000080: + EAX = amd_efer & 0xffffffff; + EDX = amd_efer >> 32; + break; + case 0xC0000081: + EAX = star & 0xffffffff; + EDX = star >> 32; + break; + case 0xC0000082: + EAX = amd_whcr & 0xffffffff; + EDX = amd_whcr >> 32; + break; + case 0xC0000085: + EAX = amd_uwccr & 0xffffffff; + EDX = amd_uwccr >> 32; + break; + case 0xC0000087: + EAX = amd_psor & 0xffffffff; + EDX = amd_psor >> 32; + break; + case 0xC0000088: + EAX = amd_pfir & 0xffffffff; + EDX = amd_pfir >> 32; + break; + default: + x86gpf(NULL, 0); + break; + } + break; + + case CPU_K6_3: + EAX = EDX = 0; + switch (ECX) + { + case 0x0000000e: + EAX = msr.tr12; + break; + case 0x00000010: + EAX = tsc & 0xffffffff; + EDX = tsc >> 32; + break; + case 0x00000083: + EAX = ecx83_msr & 0xffffffff; + EDX = ecx83_msr >> 32; + break; + case 0xC0000080: + EAX = amd_efer & 0xffffffff; + EDX = amd_efer >> 32; + break; + case 0xC0000081: + EAX = star & 0xffffffff; + EDX = star >> 32; + break; + case 0xC0000082: + EAX = amd_whcr & 0xffffffff; + EDX = amd_whcr >> 32; + break; + case 0xC0000085: + EAX = amd_uwccr & 0xffffffff; + EDX = amd_uwccr >> 32; + break; + case 0xC0000087: + EAX = amd_psor & 0xffffffff; + EDX = amd_psor >> 32; + break; + case 0xC0000088: + EAX = amd_pfir & 0xffffffff; + EDX = amd_pfir >> 32; + break; + case 0xC0000089: + EAX = amd_l2aar & 0xffffffff; + EDX = amd_l2aar >> 32; + break; + default: + x86gpf(NULL, 0); + break; + } + break; + + case CPU_K6_2P: + case CPU_K6_3P: + EAX = EDX = 0; + switch (ECX) + { + case 0x0000000e: + EAX = msr.tr12; + break; + case 0x00000010: + EAX = tsc & 0xffffffff; + EDX = tsc >> 32; + break; + case 0x00000083: + EAX = ecx83_msr & 0xffffffff; + EDX = ecx83_msr >> 32; + break; + case 0xC0000080: + EAX = amd_efer & 0xffffffff; + EDX = amd_efer >> 32; + break; + case 0xC0000081: + EAX = star & 0xffffffff; + EDX = star >> 32; + break; + case 0xC0000082: + EAX = amd_whcr & 0xffffffff; + EDX = amd_whcr >> 32; + break; + case 0xC0000085: + EAX = amd_uwccr & 0xffffffff; + EDX = amd_uwccr >> 32; + break; + case 0xC0000086: + EAX = amd_epmr & 0xffffffff; + EDX = amd_epmr >> 32; + break; + case 0xC0000087: + EAX = amd_psor & 0xffffffff; + EDX = amd_psor >> 32; + break; + case 0xC0000088: + EAX = amd_pfir & 0xffffffff; + EDX = amd_pfir >> 32; + break; + case 0xC0000089: + EAX = amd_l2aar & 0xffffffff; + EDX = amd_l2aar >> 32; break; default: x86gpf(NULL, 0); @@ -2425,6 +2646,8 @@ i686_invalid_rdmsr: void cpu_WRMSR() { + uint64_t temp; + switch (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type) { case CPU_WINCHIP: @@ -2474,8 +2697,147 @@ void cpu_WRMSR() case CPU_K5: case CPU_5K86: case CPU_K6: + switch (ECX) + { + case 0x0e: + msr.tr12 = EAX & 0x228; + break; + case 0x10: + tsc = EAX | ((uint64_t)EDX << 32); + break; + case 0x83: + ecx83_msr = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000080: + temp = EAX | ((uint64_t)EDX << 32); + if (temp & ~1ULL) + x86gpf(NULL, 0); + else + amd_efer = temp; + break; + case 0xC0000082: + amd_whcr = EAX | ((uint64_t)EDX << 32); + break; + default: + x86gpf(NULL, 0); + break; + } + break; + case CPU_K6_2: + switch (ECX) + { + case 0x0e: + msr.tr12 = EAX & 0x228; + break; + case 0x10: + tsc = EAX | ((uint64_t)EDX << 32); + break; + case 0x83: + ecx83_msr = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000080: + temp = EAX | ((uint64_t)EDX << 32); + if (temp & ~1ULL) + x86gpf(NULL, 0); + else + amd_efer = temp; + break; + case 0xC0000081: + star = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000082: + amd_whcr = EAX | ((uint64_t)EDX << 32); + break; + default: + x86gpf(NULL, 0); + break; + } + break; + + case CPU_K6_2C: + switch (ECX) + { + case 0x0e: + msr.tr12 = EAX & 0x228; + break; + case 0x10: + tsc = EAX | ((uint64_t)EDX << 32); + break; + case 0x83: + ecx83_msr = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000080: + temp = EAX | ((uint64_t)EDX << 32); + if (temp & ~0xfULL) + x86gpf(NULL, 0); + else + amd_efer = temp; + break; + case 0xC0000081: + star = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000082: + amd_whcr = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000085: + amd_uwccr = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000087: + amd_psor = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000088: + amd_pfir = EAX | ((uint64_t)EDX << 32); + break; + default: + x86gpf(NULL, 0); + break; + } + break; + case CPU_K6_3: + switch (ECX) + { + case 0x0e: + msr.tr12 = EAX & 0x228; + break; + case 0x10: + tsc = EAX | ((uint64_t)EDX << 32); + break; + case 0x83: + ecx83_msr = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000080: + temp = EAX | ((uint64_t)EDX << 32); + if (temp & ~0x1fULL) + x86gpf(NULL, 0); + else + amd_efer = temp; + break; + case 0xC0000081: + star = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000082: + amd_whcr = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000085: + amd_uwccr = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000087: + amd_psor = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000088: + amd_pfir = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000089: + amd_l2aar = EAX | ((uint64_t)EDX << 32); + break; + default: + x86gpf(NULL, 0); + break; + } + break; + case CPU_K6_2P: case CPU_K6_3P: switch (ECX) @@ -2489,11 +2851,36 @@ void cpu_WRMSR() case 0x83: ecx83_msr = EAX | ((uint64_t)EDX << 32); break; + case 0xC0000080: + temp = EAX | ((uint64_t)EDX << 32); + if (temp & ~0x1fULL) + x86gpf(NULL, 0); + else + amd_efer = temp; + break; case 0xC0000081: star = EAX | ((uint64_t)EDX << 32); break; - case 0xC0000084: - sfmask = EAX | ((uint64_t)EDX << 32); + case 0xC0000082: + amd_whcr = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000085: + amd_uwccr = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000086: + amd_epmr = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000087: + amd_psor = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000088: + amd_pfir = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000089: + amd_l2aar = EAX | ((uint64_t)EDX << 32); + break; + default: + x86gpf(NULL, 0); break; } break; diff --git a/src/cpu_new/cpu.h b/src/cpu_new/cpu.h index 6bf8c9a58..185250319 100644 --- a/src/cpu_new/cpu.h +++ b/src/cpu_new/cpu.h @@ -53,11 +53,12 @@ #define CPU_5K86 28 #define CPU_K6 29 #define CPU_K6_2 30 -#define CPU_K6_3 31 -#define CPU_K6_2P 32 -#define CPU_K6_3P 33 -#define CPU_PENTIUMPRO 34 /* 686 class CPUs */ -#define CPU_PENTIUM2D 35 +#define CPU_K6_2C 31 +#define CPU_K6_3 32 +#define CPU_K6_2P 33 +#define CPU_K6_3P 34 +#define CPU_PENTIUMPRO 35 /* 686 class CPUs */ +#define CPU_PENTIUM2D 36 #define MANU_INTEL 0 #define MANU_AMD 1 @@ -500,5 +501,7 @@ extern void x87_reset(void); extern int cpu_effective, cpu_alt_reset; extern void cpu_dynamic_switch(int new_cpu); +extern void cpu_ven_reset(void); + #endif /*EMU_CPU_H*/ diff --git a/src/cpu_new/cpu_table.c b/src/cpu_new/cpu_table.c index b6795074c..34767b870 100644 --- a/src/cpu_new/cpu_table.c +++ b/src/cpu_new/cpu_table.c @@ -621,15 +621,15 @@ CPU cpus_K56_SS7[] = { {"K6-2/266", CPU_K6_2, 266666666, 4, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24, 24, 12, 12, 32}, {"K6-2/300", CPU_K6_2, 300000000, 3, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27, 27, 9, 9, 36}, {"K6-2/333", CPU_K6_2, 332500000, 7/2, 31666667, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 30, 30, 11, 11, 40}, - {"K6-2/350", CPU_K6_2, 350000000, 7/2, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 32, 32, 11, 11, 42}, - {"K6-2/366", CPU_K6_2, 366666666, 11/2, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 33, 33, 17, 17, 44}, - {"K6-2/380", CPU_K6_2, 380000000, 4, 31666667, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 34, 34, 12, 12, 46}, - {"K6-2/400", CPU_K6_2, 400000000, 4, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48}, - {"K6-2/450", CPU_K6_2, 450000000, 9/2, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41, 41, 14, 14, 54}, - {"K6-2/475", CPU_K6_2, 475000000, 5, 31666667, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 43, 43, 15, 15, 57}, - {"K6-2/500", CPU_K6_2, 500000000, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 45, 45, 15, 15, 60}, - {"K6-2/533", CPU_K6_2, 533333333, 11/2, 32323232, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 48, 48, 17, 17, 64}, - {"K6-2/550", CPU_K6_2, 550000000, 11/2, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 50, 50, 17, 17, 66}, + {"K6-2/350", CPU_K6_2C, 350000000, 7/2, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 32, 32, 11, 11, 42}, + {"K6-2/366", CPU_K6_2C, 366666666, 11/2, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 33, 33, 17, 17, 44}, + {"K6-2/380", CPU_K6_2C, 380000000, 4, 31666667, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 34, 34, 12, 12, 46}, + {"K6-2/400", CPU_K6_2C, 400000000, 4, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48}, + {"K6-2/450", CPU_K6_2C, 450000000, 9/2, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41, 41, 14, 14, 54}, + {"K6-2/475", CPU_K6_2C, 475000000, 5, 31666667, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 43, 43, 15, 15, 57}, + {"K6-2/500", CPU_K6_2C, 500000000, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 45, 45, 15, 15, 60}, + {"K6-2/533", CPU_K6_2C, 533333333, 11/2, 32323232, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 48, 48, 17, 17, 64}, + {"K6-2/550", CPU_K6_2C, 550000000, 11/2, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 50, 50, 17, 17, 66}, /*AMD K6-2+/K6-3/K6-3+ (Super Socket 7)*/ {"K6-2+/450", CPU_K6_2P, 450000000, 9/2, 33333333, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41, 41, 14, 14, 54}, From 6750e8b2874079c1d36f661038efdb436e2ccdc7 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 16 Jan 2020 20:50:28 +0100 Subject: [PATCH 161/177] Optimized builds no longer unroll loops, produces smaller (by ~300k) and slightly faster binaries. --- src/win/Makefile.mingw | 2 +- src/win/Makefile_ndr.mingw | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index a2f5b3329..1a8fc061b 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -530,7 +530,7 @@ endif # Final versions of the toolchain flags. CFLAGS := $(WX_FLAGS) $(OPTS) $(DFLAGS) $(COPTIM) $(AOPTIM) \ $(AFLAGS) -fomit-frame-pointer -mstackrealign -Wall \ - -fno-strict-aliasing -funroll-loops + -fno-strict-aliasing # Add freetyp2 references through pkgconfig CFLAGS := $(CFLAGS) `pkg-config.exe --cflags freetype2` diff --git a/src/win/Makefile_ndr.mingw b/src/win/Makefile_ndr.mingw index fee58bd0c..227707181 100644 --- a/src/win/Makefile_ndr.mingw +++ b/src/win/Makefile_ndr.mingw @@ -536,7 +536,7 @@ endif # Final versions of the toolchain flags. CFLAGS := $(WX_FLAGS) $(OPTS) $(DFLAGS) $(COPTIM) $(AOPTIM) \ $(AFLAGS) -fomit-frame-pointer -mstackrealign -Wall \ - -fno-strict-aliasing -funroll-loops + -fno-strict-aliasing # Add freetyp2 references through pkgconfig CFLAGS := $(CFLAGS) `pkg-config.exe --cflags freetype2` From 7c15df1fd76a9bd9544e1d2868f2e31f848fcd89 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Fri, 17 Jan 2020 00:24:18 +0100 Subject: [PATCH 162/177] Added Matrox MGA (Mystique) emulation from PCem. --- src/video/vid_mga.c | 4908 ++++++++++++++++++++++++++++++++++++ src/video/vid_mga.h | 17 + src/video/vid_svga.c | 18 +- src/video/vid_svga.h | 5 + src/win/Makefile.mingw | 1 + src/win/Makefile_ndr.mingw | 1 + 6 files changed, 4945 insertions(+), 5 deletions(-) create mode 100644 src/video/vid_mga.c create mode 100644 src/video/vid_mga.h diff --git a/src/video/vid_mga.c b/src/video/vid_mga.c new file mode 100644 index 000000000..6f0a988c9 --- /dev/null +++ b/src/video/vid_mga.c @@ -0,0 +1,4908 @@ +/* + * 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. + * + * Matrox MGA graphics card emulation. + * + * Version: @(#)vid_mga.c 1.0.0 2020/01/16 + * + * Author: Sarah Walker, + * Copyright 2008-2020 Sarah Walker. + */ +#include +#include +#include +#include +#include +#include "../86box.h" +#include "../io.h" +#include "../timer.h" +#include "../mem.h" +#include "../pci.h" +#include "../rom.h" +#include "../device.h" +#include "../plat.h" +#include "video.h" +#include "vid_mga.h" +#include "vid_svga.h" +#include "vid_svga_render.h" + +#define FIFO_SIZE 65536 +#define FIFO_MASK (FIFO_SIZE - 1) +#define FIFO_ENTRY_SIZE (1 << 31) +#define FIFO_THRESHOLD 0xe000 + +#define WAKE_DELAY (100 * TIMER_USEC) /*100us*/ + +#define FIFO_ENTRIES (mystique->fifo_write_idx - mystique->fifo_read_idx) +#define FIFO_FULL ((mystique->fifo_write_idx - mystique->fifo_read_idx) >= (FIFO_SIZE-1)) +#define FIFO_EMPTY (mystique->fifo_read_idx == mystique->fifo_write_idx) + +#define FIFO_TYPE 0xff000000 +#define FIFO_ADDR 0x00ffffff + +enum +{ + FIFO_INVALID = (0x00 << 24), + FIFO_WRITE_CTRL_BYTE = (0x01 << 24), + FIFO_WRITE_CTRL_LONG = (0x02 << 24), + FIFO_WRITE_ILOAD_LONG = (0x03 << 24) +}; + +typedef struct +{ + uint32_t addr_type; + uint32_t val; +} fifo_entry_t; + +typedef struct mystique_t +{ + svga_t svga; + + rom_t bios_rom; + + mem_mapping_t lfb_mapping; + mem_mapping_t ctrl_mapping; + mem_mapping_t iload_mapping; + + uint8_t pci_regs[256]; + uint8_t int_line; + int card; + + int vram_size; + uint32_t vram_mask, vram_mask_w, vram_mask_l; + + uint32_t lfb_base, ctrl_base, iload_base; + + uint8_t crtcext_regs[6]; + int crtcext_idx; + + uint8_t xreg_regs[256]; + int xreg_idx; + + uint32_t ma_latch_old; + + uint32_t maccess, mctlwtst; + uint32_t maccess_running; + + uint32_t status; + + uint8_t xcurctrl; + + uint8_t xsyspllm, xsysplln, xsyspllp; + struct + { + int m, n, p, s; + } xpixpll[3]; + + uint8_t xgenioctrl; + uint8_t xgeniodata; + uint8_t xmulctrl; + uint8_t xgenctrl; + uint8_t xmiscctrl; + uint8_t xpixclkctrl; + uint8_t xvrefctrl; + int xzoomctrl; + + uint8_t ien; + + struct + { + uint8_t funcnt, stylelen; + int xoff, yoff; + + uint16_t cxleft, cxright; + int16_t fxleft, fxright; + uint16_t length; + + uint32_t dwgctrl; + uint32_t dwgctrl_running; + uint32_t bcol, fcol; + uint32_t pitch; + uint32_t plnwt; + uint32_t ybot; + uint32_t ydstorg; + uint32_t ytop; + int selline; + + uint32_t src[4]; + uint32_t ar[7]; + uint32_t dr[16]; + + int pattern[8][8]; + + struct + { + int sdydxl; + int scanleft; + int sdxl; + int sdy; + int sdxr; + } sgn; + + uint32_t tmr[9]; + uint32_t texorg, texwidth, texheight; + uint32_t texctl, textrans; + uint32_t zorg; + + int ydst; + uint32_t ydst_lin; + + int length_cur; + int16_t xdst; + uint32_t src_addr; + uint32_t z_base; + + int iload_rem_count; + uint32_t iload_rem_data; + int idump_end_of_line; + + int words; + + int ta_key, ta_mask; + + int lastpix_r, lastpix_g, lastpix_b; + + int highv_line; + uint32_t highv_data; + + int beta; + + int dither; + + uint8_t dmamod; + } dwgreg; + + struct + { + uint8_t r, g, b; + } lut[256]; + + struct + { + uint16_t pos_x, pos_y; + uint16_t addr; + uint32_t col[3]; + } cursor; + + uint8_t dmamod, dmadatasiz, dirdatasiz; + struct + { + uint32_t primaddress, primend; + uint32_t secaddress, secend; + + int pri_pos, sec_pos, iload_pos; + uint32_t pri_header, sec_header, iload_header; + + int pri_state, sec_state, iload_state; + + int state; + + mutex_t *lock; + } dma; + + uint8_t dmamap[16]; + + volatile int busy; + volatile int blitter_submit_refcount; + volatile int blitter_submit_dma_refcount; + volatile int blitter_complete_refcount; + + volatile int endprdmasts_pending; + volatile int softrap_pending; + uint32_t softrap_pending_val; + + pc_timer_t softrap_pending_timer; + + uint64_t blitter_time; + uint64_t status_time; + + int pixel_count, trap_count; + + fifo_entry_t fifo[FIFO_SIZE]; + volatile int fifo_read_idx, fifo_write_idx; + + thread_t *fifo_thread; + event_t *wake_fifo_thread; + event_t *fifo_not_full_event; + + pc_timer_t wake_timer; +} mystique_t; + +static void mystique_start_blit(mystique_t *mystique); +static void mystique_update_irqs(mystique_t *mystique); + +static void wake_fifo_thread(mystique_t *mystique); +static void wait_fifo_idle(mystique_t *mystique); +static void mystique_queue(mystique_t *mystique, uint32_t addr, uint32_t val, uint32_t type); + +static const uint8_t trans_masks[16][16] = +{ + { + 1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1 + }, + { + 1, 0, 1, 0, + 0, 1, 0, 1, + 1, 0, 1, 0, + 0, 1, 0, 1 + }, + { + 0, 1, 0, 1, + 1, 0, 1, 0, + 0, 1, 0, 1, + 1, 0, 1, 0 + }, + { + 1, 0, 1, 0, + 0, 0, 0, 0, + 1, 0, 1, 0, + 0, 0, 0, 0 + }, + { + 0, 1, 0, 1, + 0, 0, 0, 0, + 0, 1, 0, 1, + 0, 0, 0, 0 + }, + { + 0, 0, 0, 0, + 1, 0, 1, 0, + 0, 0, 0, 0, + 1, 0, 1, 0 + }, + { + 0, 0, 0, 0, + 0, 1, 0, 1, + 0, 0, 0, 0, + 0, 1, 0, 1 + }, + { + 1, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 0 + }, + { + 0, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 + }, + { + 0, 0, 0, 1, + 0, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 0, 0 + }, + { + 0, 0, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 0, + 1, 0, 0, 0 + }, + { + 0, 0, 0, 0, + 1, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 1, 0 + }, + { + 0, 1, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1, + 0, 0, 0, 0 + }, + { + 0, 0, 0, 0, + 0, 0, 0, 1, + 0, 0, 0, 0, + 0, 1, 0, 0 + }, + { + 0, 0, 1, 0, + 0, 0, 0, 0, + 1, 0, 0, 0, + 0, 0, 0, 0 + }, + { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 + } +}; + +static int8_t dither5[256][2][2]; +static int8_t dither6[256][2][2]; + +enum +{ + DMA_STATE_IDLE = 0, + DMA_STATE_PRI, + DMA_STATE_SEC +}; + +#define DMA_POLL_TIME_US 100 /*100us*/ +#define DMA_MAX_WORDS 256 /*256 quad words per 100us poll*/ + +/*These registers are also mirrored into 0x1dxx, with the mirrored versions starting + the blitter*/ +#define REG_DWGCTL 0x1c00 +#define REG_MACCESS 0x1c04 +#define REG_MCTLWTST 0x1c08 +#define REG_ZORG 0x1c0c +#define REG_PAT0 0x1c10 +#define REG_PAT1 0x1c14 +#define REG_PLNWT 0x1c1c +#define REG_BCOL 0x1c20 +#define REG_FCOL 0x1c24 +#define REG_SRC0 0x1c30 +#define REG_SRC1 0x1c34 +#define REG_SRC2 0x1c38 +#define REG_SRC3 0x1c3c +#define REG_XYSTRT 0x1c40 +#define REG_XYEND 0x1c44 +#define REG_SHIFT 0x1c50 +#define REG_DMAPAD 0x1c54 +#define REG_SGN 0x1c58 +#define REG_LEN 0x1c5c +#define REG_AR0 0x1c60 +#define REG_AR1 0x1c64 +#define REG_AR2 0x1c68 +#define REG_AR3 0x1c6c +#define REG_AR4 0x1c70 +#define REG_AR5 0x1c74 +#define REG_AR6 0x1c78 +#define REG_CXBNDRY 0x1c80 +#define REG_FXBNDRY 0x1c84 +#define REG_YDSTLEN 0x1c88 +#define REG_PITCH 0x1c8c +#define REG_YDST 0x1c90 +#define REG_YDSTORG 0x1c94 +#define REG_YTOP 0x1c98 +#define REG_YBOT 0x1c9c +#define REG_CXLEFT 0x1ca0 +#define REG_CXRIGHT 0x1ca4 +#define REG_FXLEFT 0x1ca8 +#define REG_FXRIGHT 0x1cac +#define REG_XDST 0x1cb0 +#define REG_DR0 0x1cc0 +#define REG_DR2 0x1cc8 +#define REG_DR3 0x1ccc +#define REG_DR4 0x1cd0 +#define REG_DR6 0x1cd8 +#define REG_DR7 0x1cdc +#define REG_DR8 0x1ce0 +#define REG_DR10 0x1ce8 +#define REG_DR11 0x1cec +#define REG_DR12 0x1cf0 +#define REG_DR14 0x1cf8 +#define REG_DR15 0x1cfc + +#define REG_FIFOSTATUS 0x1e10 +#define REG_STATUS 0x1e14 +#define REG_ICLEAR 0x1e18 +#define REG_IEN 0x1e1c +#define REG_VCOUNT 0x1e20 +#define REG_DMAMAP 0x1e30 +#define REG_RST 0x1e40 +#define REG_OPMODE 0x1e54 +#define REG_PRIMADDRESS 0x1e58 +#define REG_PRIMEND 0x1e5c +#define REG_DWG_INDIR_WT 0x1e80 + +#define REG_INSTS0 0x1fc2 +#define REG_MISC 0x1fc2 +#define REG_SEQ_IDX 0x1fc4 +#define REG_SEQ_DATA 0x1fc5 +#define REG_MISCREAD 0x1fcc +#define REG_CRTC_IDX 0x1fd4 +#define REG_CRTC_DATA 0x1fd5 +#define REG_INSTS1 0x1fda +#define REG_CRTCEXT_IDX 0x1fde +#define REG_CRTCEXT_DATA 0x1fdf +#define REG_CACHEFLUSH 0x1fff + +#define REG_TMR0 0x2c00 +#define REG_TMR1 0x2c04 +#define REG_TMR2 0x2c08 +#define REG_TMR3 0x2c0c +#define REG_TMR4 0x2c10 +#define REG_TMR5 0x2c14 +#define REG_TMR6 0x2c18 +#define REG_TMR7 0x2c1c +#define REG_TMR8 0x2c20 +#define REG_TEXORG 0x2c24 +#define REG_TEXWIDTH 0x2c28 +#define REG_TEXHEIGHT 0x2c2c +#define REG_TEXCTL 0x2c30 +#define REG_TEXTRANS 0x2c34 +#define REG_SECADDRESS 0x2c40 +#define REG_SECEND 0x2c44 +#define REG_SOFTRAP 0x2c48 + +#define REG_PALWTADD 0x3c00 +#define REG_PALDATA 0x3c01 +#define REG_PIXRDMSK 0x3c02 +#define REG_PALRDADD 0x3c03 +#define REG_X_DATAREG 0x3c0a +#define REG_CURPOSX 0x3c0c +#define REG_CURPOSY 0x3c0e + +#define REG_STATUS_VSYNCSTS (1 << 3) + +#define CRTCX_R0_STARTADD_MASK (0xf << 0) +#define CRTCX_R0_OFFSET_MASK (3 << 4) + +#define CRTCX_R1_HTOTAL8 (1 << 0) + +#define CRTCX_R2_VTOTAL10 (1 << 0) +#define CRTCX_R2_VTOTAL11 (1 << 1) +#define CRTCX_R2_VDISPEND10 (1 << 2) +#define CRTCX_R2_VBLKSTR10 (1 << 3) +#define CRTCX_R2_VBLKSTR11 (1 << 4) +#define CRTCX_R2_VSYNCSTR10 (1 << 5) +#define CRTCX_R2_VSYNCSTR11 (1 << 6) +#define CRTCX_R2_LINECOMP10 (1 << 7) + +#define CRTCX_R3_MGAMODE (1 << 7) + +#define XREG_XCURADDL 0x04 +#define XREG_XCURADDH 0x05 +#define XREG_XCURCTRL 0x06 + +#define XREG_XCURCOL0R 0x08 +#define XREG_XCURCOL0G 0x09 +#define XREG_XCURCOL0B 0x0a + +#define XREG_XCURCOL1R 0x0c +#define XREG_XCURCOL1G 0x0d +#define XREG_XCURCOL1B 0x0e + +#define XREG_XCURCOL2R 0x10 +#define XREG_XCURCOL2G 0x11 +#define XREG_XCURCOL2B 0x12 + +#define XREG_XVREFCTRL 0x18 +#define XREG_XMULCTRL 0x19 +#define XREG_XPIXCLKCTRL 0x1a +#define XREG_XGENCTRL 0x1d +#define XREG_XMISCCTRL 0x1e + +#define XREG_XGENIOCTRL 0x2a +#define XREG_XGENIODATA 0x2b + +#define XREG_XSYSPLLM 0x2c +#define XREG_XSYSPLLN 0x2d +#define XREG_XSYSPLLP 0x2e +#define XREG_XSYSPLLSTAT 0x2f + +#define XREG_XZOOMCTRL 0x38 + +#define XREG_XPIXPLLCM 0x4c +#define XREG_XPIXPLLCN 0x4d +#define XREG_XPIXPLLCP 0x4e +#define XREG_XPIXPLLSTAT 0x4f + +#define XMISCCTRL_VGA8DAC (1 << 3) + +#define XMULCTRL_DEPTH_MASK (7 << 0) +#define XMULCTRL_DEPTH_8 (0 << 0) +#define XMULCTRL_DEPTH_15 (1 << 0) +#define XMULCTRL_DEPTH_16 (2 << 0) +#define XMULCTRL_DEPTH_24 (3 << 0) +#define XMULCTRL_DEPTH_32_OVERLAYED (4 << 0) +#define XMULCTRL_DEPTH_2G8V16 (5 << 0) +#define XMULCTRL_DEPTH_G16V16 (6 << 0) +#define XMULCTRL_DEPTH_32 (7 << 0) + +#define XSYSPLLSTAT_SYSLOCK (1 << 6) + +#define XPIXPLLSTAT_SYSLOCK (1 << 6) + +#define DWGCTRL_OPCODE_MASK (0xf << 0) +#define DWGCTRL_OPCODE_LINE_OPEN (0x0 << 0) +#define DWGCTRL_OPCODE_AUTOLINE_OPEN (0x1 << 0) +#define DWGCTRL_OPCODE_AUTOLINE_CLOSE (0x3 << 0) +#define DWGCTRL_OPCODE_TRAP (0x4 << 0) +#define DWGCTRL_OPCODE_TEXTURE_TRAP (0x6 << 0) +#define DWGCTRL_OPCODE_ILOAD_HIGH (0x7 << 0) +#define DWGCTRL_OPCODE_BITBLT (0x8 << 0) +#define DWGCTRL_OPCODE_ILOAD (0x9 << 0) +#define DWGCTRL_OPCODE_IDUMP (0xa << 0) +#define DWGCTRL_OPCODE_ILOAD_SCALE (0xd << 0) +#define DWGCTRL_OPCODE_ILOAD_HIGHV (0xe << 0) +#define DWGCTRL_ATYPE_MASK (7 << 4) +#define DWGCTRL_ATYPE_RPL (0 << 4) +#define DWGCTRL_ATYPE_RSTR (1 << 4) +#define DWGCTRL_ATYPE_ZI (3 << 4) +#define DWGCTRL_ATYPE_BLK (4 << 4) +#define DWGCTRL_ATYPE_I (7 << 4) +#define DWGCTRL_LINEAR (1 << 7) +#define DWGCTRL_ZMODE_MASK (7 << 8) +#define DWGCTRL_ZMODE_NOZCMP (0 << 8) +#define DWGCTRL_ZMODE_ZE (2 << 8) +#define DWGCTRL_ZMODE_ZNE (3 << 8) +#define DWGCTRL_ZMODE_ZLT (4 << 8) +#define DWGCTRL_ZMODE_ZLTE (5 << 8) +#define DWGCTRL_ZMODE_ZGT (6 << 8) +#define DWGCTRL_ZMODE_ZGTE (7 << 8) +#define DWGCTRL_SOLID (1 << 11) +#define DWGCTRL_ARZERO (1 << 12) +#define DWGCTRL_SGNZERO (1 << 13) +#define DWGCTRL_SHTZERO (1 << 14) +#define DWGCTRL_BOP_MASK (0xf << 16) +#define DWGCTRL_TRANS_SHIFT (20) +#define DWGCTRL_TRANS_MASK (0xf << DWGCTRL_TRANS_SHIFT) +#define DWGCTRL_BLTMOD_MASK (0xf << 25) +#define DWGCTRL_BLTMOD_BMONOLEF (0x0 << 25) +#define DWGCTRL_BLTMOD_BFCOL (0x2 << 25) +#define DWGCTRL_BLTMOD_BMONOWF (0x4 << 25) +#define DWGCTRL_BLTMOD_BU32RGB (0x7 << 25) +#define DWGCTRL_BLTMOD_BUYUV (0xe << 25) +#define DWGCTRL_BLTMOD_BU24RGB (0xf << 25) +#define DWGCTRL_PATTERN (1 << 29) +#define DWGCTRL_TRANSC (1 << 30) +#define BOP(x) ((x) << 16) + +#define MACCESS_PWIDTH_MASK (3 << 0) +#define MACCESS_PWIDTH_8 (0 << 0) +#define MACCESS_PWIDTH_16 (1 << 0) +#define MACCESS_PWIDTH_32 (2 << 0) +#define MACCESS_PWIDTH_24 (3 << 0) +#define MACCESS_TLUTLOAD (1 << 29) +#define MACCESS_NODITHER (1 << 30) +#define MACCESS_DIT555 (1 << 31) + +#define PITCH_MASK 0x7e0 +#define PITCH_YLIN (1 << 15) + +#define SGN_SDYDXL (1 << 0) +#define SGN_SCANLEFT (1 << 0) +#define SGN_SDXL (1 << 1) +#define SGN_SDY (1 << 2) +#define SGN_SDXR (1 << 5) + +#define DMA_ADDR_MASK 0xfffffffc +#define DMA_MODE_MASK 3 + +#define DMA_MODE_REG 0 +#define DMA_MODE_BLIT 1 +#define DMA_MODE_VECTOR 2 + +#define STATUS_SOFTRAPEN (1 << 0) +#define STATUS_VLINEPEN (1 << 5) +#define STATUS_DWGENGSTS (1 << 16) +#define STATUS_ENDPRDMASTS (1 << 17) + +#define ICLEAR_SOFTRAPICLR (1 << 0) +#define ICLEAR_VLINEICLR (1 << 5) + +#define IEN_SOFTRAPEN (1 << 0) + +#define TEXCTL_TEXFORMAT_MASK (7 << 0) +#define TEXCTL_TEXFORMAT_TW4 (0 << 0) +#define TEXCTL_TEXFORMAT_TW8 (1 << 0) +#define TEXCTL_TEXFORMAT_TW15 (2 << 0) +#define TEXCTL_TEXFORMAT_TW16 (3 << 0) +#define TEXCTL_TEXFORMAT_TW12 (4 << 0) +#define TEXCTL_PALSEL_MASK (0xf << 4) +#define TEXCTL_TPITCH_SHIFT (16) +#define TEXCTL_TPITCH_MASK (7 << TEXCTL_TPITCH_SHIFT) +#define TEXCTL_NPCEN (1 << 21) +#define TEXCTL_DECALCKEY (1 << 24) +#define TEXCTL_TAKEY (1 << 25) +#define TEXCTL_TAMASK (1 << 26) +#define TEXCTL_CLAMPV (1 << 27) +#define TEXCTL_CLAMPU (1 << 28) +#define TEXCTL_TMODULATE (1 << 29) +#define TEXCTL_STRANS (1 << 30) +#define TEXCTL_ITRANS (1 << 31) + +#define TEXHEIGHT_TH_MASK (0x3f << 0) +#define TEXHEIGHT_THMASK_SHIFT (18) +#define TEXHEIGHT_THMASK_MASK (0x7ff << TEXHEIGHT_THMASK_SHIFT) + +#define TEXWIDTH_TW_MASK (0x3f << 0) +#define TEXWIDTH_TWMASK_SHIFT (18) +#define TEXWIDTH_TWMASK_MASK (0x7ff << TEXWIDTH_TWMASK_SHIFT) + +#define TEXTRANS_TCKEY_MASK (0xffff) +#define TEXTRANS_TKMASK_SHIFT (16) +#define TEXTRANS_TKMASK_MASK (0xffff << TEXTRANS_TKMASK_SHIFT) + +#define DITHER_565 0 +#define DITHER_NONE_565 1 +#define DITHER_555 2 +#define DITHER_NONE_555 3 + +static void mystique_recalc_mapping(mystique_t *mystique); +static int mystique_line_compare(svga_t *svga); + +static uint8_t mystique_iload_read_b(uint32_t addr, void *p); +static uint32_t mystique_iload_read_l(uint32_t addr, void *p); +static void mystique_iload_write_b(uint32_t addr, uint8_t val, void *p); +static void mystique_iload_write_l(uint32_t addr, uint32_t val, void *p); + +static uint32_t blit_idump_read(mystique_t *mystique); +static void blit_iload_write(mystique_t *mystique, uint32_t data, int size); + +static video_timings_t timing_matrox_mystique = {VIDEO_BUS, 4, 4, 4, 10, 10, 10}; + +void mystique_out(uint16_t addr, uint8_t val, void *p) +{ + mystique_t *mystique = (mystique_t *)p; + svga_t *svga = &mystique->svga; + uint8_t old; + + if ((((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && addr < 0x3de) && !(svga->miscout & 1)) + addr ^= 0x60; + + switch (addr) + { + case 0x3c8: + mystique->xreg_idx = val; + break; + + case 0x3cf: + if ((svga->gdcaddr & 15) == 6 && svga->gdcreg[6] != val) { + svga->gdcreg[svga->gdcaddr & 15] = val; + mystique_recalc_mapping(mystique); + return; + } + break; + + case 0x3D4: + svga->crtcreg = val & 0x3f; + return; + case 0x3D5: + if (((svga->crtcreg & 31) < 7) && (svga->crtc[0x11] & 0x80)) + return; + if (((svga->crtcreg & 31) == 7) && (svga->crtc[0x11] & 0x80)) + val = (svga->crtc[7] & ~0x10) | (val & 0x10); + old = svga->crtc[svga->crtcreg & 0x3f]; + svga->crtc[svga->crtcreg & 31] = val; + if (old != val) { + if ((svga->crtcreg & 31) < 0xE || (svga->crtcreg & 31) > 0x10) { + svga->fullchange = changeframecount; + svga_recalctimings(svga); + } + } + break; + + case 0x3de: + mystique->crtcext_idx = val; + break; + case 0x3df: + if (mystique->crtcext_idx < 6) + mystique->crtcext_regs[mystique->crtcext_idx] = val; + if (mystique->crtcext_idx < 4) { + svga->fullchange = changeframecount; + svga_recalctimings(svga); + } + if (mystique->crtcext_idx == 3) { + if (val & CRTCX_R3_MGAMODE) + svga->fb_only = 1; + else + svga->fb_only = 0; + svga_recalctimings(svga); + } + if (mystique->crtcext_idx == 4) { + if (svga->gdcreg[6] & 0xc) { + /*64k banks*/ + svga->read_bank = (val & 0x7f) << 16; + svga->write_bank = (val & 0x7f) << 16; + } else { + /*128k banks*/ + svga->read_bank = (val & 0x7e) << 16; + svga->write_bank = (val & 0x7e) << 16; + } + } + break; + } + svga_out(addr, val, svga); +} + +uint8_t mystique_in(uint16_t addr, void *p) +{ + mystique_t *mystique = (mystique_t *)p; + svga_t *svga = &mystique->svga; + uint8_t temp = 0xff; + + if ((((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && addr < 0x3de) && !(svga->miscout & 1)) + addr ^= 0x60; + + switch (addr) + { + case 0x3D4: + temp = svga->crtcreg; + break; + case 0x3D5: + temp = svga->crtc[svga->crtcreg & 0x3f]; + break; + + case 0x3df: + if (mystique->crtcext_idx < 6) + temp = mystique->crtcext_regs[mystique->crtcext_idx]; + break; + + default: + temp = svga_in(addr, svga); + break; + } + + return temp; +} + +static int mystique_line_compare(svga_t *svga) +{ + mystique_t *mystique = (mystique_t *)svga->p; + + mystique->status |= STATUS_VLINEPEN; + mystique_update_irqs(mystique); + + return 0; +} + +void mystique_recalctimings(svga_t *svga) +{ + mystique_t *mystique = (mystique_t *)svga->p; + int clk_sel = (svga->miscout >> 2) & 3; + + if (clk_sel & 2) { + int m = mystique->xpixpll[2].m; + int n = mystique->xpixpll[2].n; + int p = mystique->xpixpll[2].p; + + double fvco = 14318181.0 * (n + 1) / (m + 1); + double fo = fvco / (p + 1); + +// pclog("m=%i n=%i p=%i fo=%g\n", m, n, p, fo); + svga->clock = (cpuclock * (float)(1ull << 32)) / fo; + } + + if (mystique->crtcext_regs[1] & CRTCX_R1_HTOTAL8) + svga->htotal += 0x100; + if (mystique->crtcext_regs[2] & CRTCX_R2_VTOTAL10) + svga->vtotal += 0x400; + if (mystique->crtcext_regs[2] & CRTCX_R2_VTOTAL11) + svga->vtotal += 0x800; + if (mystique->crtcext_regs[2] & CRTCX_R2_VDISPEND10) + svga->dispend += 0x400; + if (mystique->crtcext_regs[2] & CRTCX_R2_VBLKSTR10) + svga->vblankstart += 0x400; + if (mystique->crtcext_regs[2] & CRTCX_R2_VBLKSTR11) + svga->vblankstart += 0x800; + if (mystique->crtcext_regs[2] & CRTCX_R2_VSYNCSTR10) + svga->vsyncstart += 0x400; + if (mystique->crtcext_regs[2] & CRTCX_R2_VSYNCSTR11) + svga->vsyncstart += 0x800; + if (mystique->crtcext_regs[2] & CRTCX_R2_LINECOMP10) + svga->split += 0x400; + + if (mystique->crtcext_regs[3] & CRTCX_R3_MGAMODE) { + int row_offset = svga->crtc[0x13] | ((mystique->crtcext_regs[0] & CRTCX_R0_OFFSET_MASK) << 4); + +// svga->split = 99999; + svga->lowres = 0; + svga->rowoffset = row_offset * 2; + svga->ma_latch = ((mystique->crtcext_regs[0] & CRTCX_R0_STARTADD_MASK) << 17) | + (svga->crtc[0xc] << 9) | (svga->crtc[0xd] << 1); + + /*Mystique, unlike most SVGA cards, allows display start to take + effect mid-screen*/ + if (svga->ma_latch != mystique->ma_latch_old) { +// pclog("ma_latch change: old=%08x new=%08x ma=%08x ", mystique->ma_latch_old, svga->ma_latch, svga->maback); + svga->ma = svga->maback = (svga->maback - (mystique->ma_latch_old << 2)) + (svga->ma_latch << 2); +// pclog("ma_new=%08x\n", svga->maback); + mystique->ma_latch_old = svga->ma_latch; + } + + switch (mystique->xmulctrl & XMULCTRL_DEPTH_MASK) + { + case XMULCTRL_DEPTH_8: + case XMULCTRL_DEPTH_2G8V16: + svga->render = svga_render_8bpp_highres; + svga->bpp = 8; + break; + case XMULCTRL_DEPTH_15: + case XMULCTRL_DEPTH_G16V16: + svga->render = svga_render_15bpp_highres; + svga->bpp = 15; + break; + case XMULCTRL_DEPTH_16: + svga->render = svga_render_16bpp_highres; + svga->bpp = 16; + break; + case XMULCTRL_DEPTH_24: + svga->render = svga_render_24bpp_highres; + svga->bpp = 24; + break; + case XMULCTRL_DEPTH_32: + case XMULCTRL_DEPTH_32_OVERLAYED: + svga->render = svga_render_32bpp_highres; + svga->bpp = 32; + break; + } + + svga->line_compare = mystique_line_compare; +// pclog("recalc: htotal=%i vtotal=%i dispend=%i\n", svga->htotal, svga->vtotal, svga->dispend); + } else { + svga->line_compare = NULL; + svga->bpp = 8; + } +} + +static void mystique_recalc_mapping(mystique_t *mystique) +{ + svga_t *svga = &mystique->svga; + + io_removehandler(0x03c0, 0x0020, mystique_in, NULL, NULL, mystique_out, NULL, NULL, mystique); + if ((mystique->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) && (mystique->pci_regs[0x41] & 1)) + io_sethandler(0x03c0, 0x0020, mystique_in, NULL, NULL, mystique_out, NULL, NULL, mystique); + + if (!(mystique->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) { + mem_mapping_disable(&svga->mapping); + mem_mapping_disable(&mystique->ctrl_mapping); + mem_mapping_disable(&mystique->lfb_mapping); + mem_mapping_disable(&mystique->iload_mapping); + return; + } + + if (mystique->ctrl_base) + mem_mapping_set_addr(&mystique->ctrl_mapping, mystique->ctrl_base, 0x4000); + else + mem_mapping_disable(&mystique->ctrl_mapping); + if (mystique->lfb_base) + mem_mapping_set_addr(&mystique->lfb_mapping, mystique->lfb_base, 0x800000); + else + mem_mapping_disable(&mystique->lfb_mapping); + if (mystique->iload_base) + mem_mapping_set_addr(&mystique->iload_mapping, mystique->iload_base, 0x800000); + else + mem_mapping_disable(&mystique->iload_mapping); + + if (mystique->pci_regs[0x41] & 1) { + switch (svga->gdcreg[6] & 0x0C) + { + case 0x0: /*128k at A0000*/ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + svga->banked_mask = 0x1ffff; + break; + case 0x4: /*64k at A0000*/ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + svga->banked_mask = 0xffff; + break; + case 0x8: /*32k at B0000*/ + mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); + svga->banked_mask = 0x7fff; + break; + case 0xC: /*32k at B8000*/ + mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); + svga->banked_mask = 0x7fff; + break; + } + if (svga->gdcreg[6] & 0xc) { + /*64k banks*/ + svga->read_bank = (mystique->crtcext_regs[4] & 0x7f) << 16; + svga->write_bank = (mystique->crtcext_regs[4] & 0x7f) << 16; + } else { + /*128k banks*/ + svga->read_bank = (mystique->crtcext_regs[4] & 0x7e) << 16; + svga->write_bank = (mystique->crtcext_regs[4] & 0x7e) << 16; + } + } else + mem_mapping_disable(&svga->mapping); +} + +static void mystique_update_irqs(mystique_t *mystique) +{ + int irq = 0; + + if ((mystique->status & mystique->ien) & STATUS_SOFTRAPEN) + irq = 1; + + if (irq) + pci_set_irq(mystique->card, PCI_INTA); + else + pci_clear_irq(mystique->card, PCI_INTA); +} + +#define READ8(addr, var) switch ((addr) & 3) \ + { \ + case 0: ret = (var) & 0xff; break; \ + case 1: ret = ((var) >> 8) & 0xff; break; \ + case 2: ret = ((var) >> 16) & 0xff; break; \ + case 3: ret = ((var) >> 24) & 0xff; break; \ + } + +#define WRITE8(addr, var, val) switch ((addr) & 3) \ + { \ + case 0: var = (var & 0xffffff00) | (val); break; \ + case 1: var = (var & 0xffff00ff) | ((val) << 8); break; \ + case 2: var = (var & 0xff00ffff) | ((val) << 16); break; \ + case 3: var = (var & 0x00ffffff) | ((val) << 24); break; \ + } + +static uint8_t mystique_read_xreg(mystique_t *mystique, int reg) +{ + uint8_t ret = 0xff; + + switch (reg) + { + case XREG_XCURADDL: + ret = mystique->cursor.addr & 0xff; + break; + case XREG_XCURADDH: + ret = mystique->cursor.addr >> 8; + break; + case XREG_XCURCTRL: + ret = mystique->xcurctrl; + break; + + case XREG_XCURCOL0R: case XREG_XCURCOL0G: case XREG_XCURCOL0B: + READ8(reg, mystique->cursor.col[0]); + break; + case XREG_XCURCOL1R: case XREG_XCURCOL1G: case XREG_XCURCOL1B: + READ8(reg, mystique->cursor.col[1]); + break; + case XREG_XCURCOL2R: case XREG_XCURCOL2G: case XREG_XCURCOL2B: + READ8(reg, mystique->cursor.col[2]); + break; + + case XREG_XMULCTRL: + ret = mystique->xmulctrl; + break; + + case XREG_XMISCCTRL: + ret = mystique->xmiscctrl; + break; + + case XREG_XGENCTRL: + ret = mystique->xgenctrl; + break; + + case XREG_XGENIOCTRL: + ret = mystique->xgenioctrl; + break; + case XREG_XGENIODATA: + ret = mystique->xgeniodata; + break; + + case XREG_XSYSPLLM: + ret = mystique->xsyspllm; + break; + case XREG_XSYSPLLN: + ret = mystique->xsysplln; + break; + case XREG_XSYSPLLP: + ret = mystique->xsyspllp; + break; + + case XREG_XZOOMCTRL: + ret = mystique->xzoomctrl; + break; + + case XREG_XPIXCLKCTRL: + ret = mystique->xpixclkctrl; + break; + + case XREG_XSYSPLLSTAT: + ret = XSYSPLLSTAT_SYSLOCK; + break; + + case XREG_XPIXPLLSTAT: + ret = XPIXPLLSTAT_SYSLOCK; + break; + + case XREG_XPIXPLLCM: + ret = mystique->xpixpll[2].m; + break; + case XREG_XPIXPLLCN: + ret = mystique->xpixpll[2].n; + break; + case XREG_XPIXPLLCP: + ret = mystique->xpixpll[2].p | (mystique->xpixpll[2].s << 3); + break; + + case 0x00: case 0x20: case 0x3f: + ret = 0xff; + break; + + default: + if (reg >= 0x50) + ret = 0xff; + break; + } + return ret; +} + +static void mystique_write_xreg(mystique_t *mystique, int reg, uint8_t val) +{ + svga_t *svga = &mystique->svga; + + switch (reg) + { + case XREG_XCURADDL: + mystique->cursor.addr = (mystique->cursor.addr & 0x1f00) | val; + svga->hwcursor.addr = mystique->cursor.addr << 10; + break; + case XREG_XCURADDH: + mystique->cursor.addr = (mystique->cursor.addr & 0x00ff) | ((val & 0x1f) << 8); + svga->hwcursor.addr = mystique->cursor.addr << 10; + break; + + case XREG_XCURCTRL: + mystique->xcurctrl = val; + svga->hwcursor.ena = (val & 3) ? 1 : 0; + break; + + case XREG_XCURCOL0R: case XREG_XCURCOL0G: case XREG_XCURCOL0B: + WRITE8(reg, mystique->cursor.col[0], val); + break; + case XREG_XCURCOL1R: case XREG_XCURCOL1G: case XREG_XCURCOL1B: + WRITE8(reg, mystique->cursor.col[1], val); + break; + case XREG_XCURCOL2R: case XREG_XCURCOL2G: case XREG_XCURCOL2B: + WRITE8(reg, mystique->cursor.col[2], val); + break; + + case XREG_XMULCTRL: + mystique->xmulctrl = val; + break; + + case XREG_XMISCCTRL: + mystique->xmiscctrl = val; + svga_set_ramdac_type(svga, (val & XMISCCTRL_VGA8DAC) ? RAMDAC_8BIT : RAMDAC_6BIT); + break; + + case XREG_XGENCTRL: + mystique->xgenctrl = val; + break; + + case XREG_XVREFCTRL: + mystique->xvrefctrl = val; + break; + + case XREG_XGENIOCTRL: + mystique->xgenioctrl = val; + break; + case XREG_XGENIODATA: + mystique->xgeniodata = val; + break; + + case XREG_XSYSPLLM: + mystique->xsyspllm = val; + break; + case XREG_XSYSPLLN: + mystique->xsysplln = val; + break; + case XREG_XSYSPLLP: + mystique->xsyspllp = val; + break; + + case XREG_XZOOMCTRL: + mystique->xzoomctrl = val & 3; + break; + + case XREG_XPIXCLKCTRL: + mystique->xpixclkctrl = val; + break; + + case XREG_XPIXPLLCM: + mystique->xpixpll[2].m = val; + break; + case XREG_XPIXPLLCN: + mystique->xpixpll[2].n = val; + break; + case XREG_XPIXPLLCP: + mystique->xpixpll[2].p = val & 7; + mystique->xpixpll[2].s = (val >> 3) & 3; + break; + + case 0x00: case 0x01: case 0x02: case 0x03: + case 0x07: case 0x0b: case 0x0f: + case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: + case 0x1b: case 0x1c: case 0x20: case 0x39: case 0x3b: case 0x3f: + case 0x47: case 0x4b: + break; + + default: + break; + } +} + +static uint8_t mystique_ctrl_read_b(uint32_t addr, void *p) +{ + mystique_t *mystique = (mystique_t *)p; + svga_t *svga = &mystique->svga; + uint8_t ret = 0xff; + int fifocount; + +// pclog("mystique read %04x %08x\n", addr & 0x3fff, cpu_state.pc); + + switch (addr & 0x3fff) + { + case REG_FIFOSTATUS: + fifocount = FIFO_SIZE - FIFO_ENTRIES; + if (fifocount > 64) + fifocount = 64; + ret = fifocount; + break; + case REG_FIFOSTATUS+1: + if (FIFO_EMPTY) + ret |= 2; + else if (FIFO_ENTRIES >= 64) + ret |= 1; +// ret = 2; /*Empty*/ + break; + case REG_FIFOSTATUS+2: case REG_FIFOSTATUS+3: + ret = 0; + break; + + case REG_STATUS: + ret = mystique->status & 0xff; + if (svga->cgastat & 8) + ret |= REG_STATUS_VSYNCSTS; +// pclog("REG_STATUS %02x\n", ret); + break; + case REG_STATUS+1: + ret = (mystique->status >> 8) & 0xff; + break; + case REG_STATUS+2: + ret = (mystique->status >> 16) & 0xff; + if (mystique->busy || + ((mystique->blitter_submit_refcount + mystique->blitter_submit_dma_refcount) != mystique->blitter_complete_refcount) || + !FIFO_EMPTY) + ret |= (STATUS_DWGENGSTS >> 16); + break; + case REG_STATUS+3: + ret = (mystique->status >> 24) & 0xff; + break; + + case REG_IEN: + ret = mystique->ien & 0x64; + break; + case REG_IEN+1: case REG_IEN+2: case REG_IEN+3: + ret = 0; + break; + + case REG_OPMODE: + ret = mystique->dmamod << 2; + break; + case REG_OPMODE+1: + ret = mystique->dmadatasiz; + break; + case REG_OPMODE+2: + ret = mystique->dirdatasiz; + break; + case REG_OPMODE+3: + break; + + case REG_PRIMADDRESS: case REG_PRIMADDRESS+1: case REG_PRIMADDRESS+2: case REG_PRIMADDRESS+3: + READ8(addr, mystique->dma.primaddress); + break; + case REG_PRIMEND: case REG_PRIMEND+1: case REG_PRIMEND+2: case REG_PRIMEND+3: + READ8(addr, mystique->dma.primend); + break; + + case REG_SECADDRESS: case REG_SECADDRESS+1: case REG_SECADDRESS+2: case REG_SECADDRESS+3: + READ8(addr, mystique->dma.secaddress); + break; + + case REG_VCOUNT: case REG_VCOUNT+1: case REG_VCOUNT+2: case REG_VCOUNT+3: + READ8(addr, svga->vc); + break; + + case REG_INSTS0: + ret = svga_in(0x3c2, svga); + break; + + case REG_SEQ_IDX: + ret = svga_in(0x3c4, svga); + break; + case REG_SEQ_DATA: + ret = svga_in(0x3c5, svga); + break; + + case REG_MISCREAD: + ret = svga_in(0x3cc, svga); + break; + + case REG_CRTC_IDX: + ret = mystique_in(0x3d4, mystique); + break; + case REG_CRTC_DATA: + ret = mystique_in(0x3d5, mystique); + break; + + case REG_INSTS1: + ret = mystique_in(0x3da, mystique); + break; + + case REG_CRTCEXT_IDX: + ret = mystique_in(0x3de, mystique); + break; + case REG_CRTCEXT_DATA: + ret = mystique_in(0x3df, mystique); + break; + + case REG_PALWTADD: + ret = svga_in(0x3c8, svga); + break; + case REG_PALDATA: + ret = svga_in(0x3c9, svga); + break; + case REG_PIXRDMSK: + ret = svga_in(0x3c6, svga); + break; + case REG_PALRDADD: + ret = svga_in(0x3c7, svga); + break; + + case REG_X_DATAREG: + ret = mystique_read_xreg(mystique, mystique->xreg_idx); + break; + + case REG_ICLEAR: case REG_ICLEAR+1: case REG_ICLEAR+2: case REG_ICLEAR+3: + case 0x2c30: case 0x2c31: case 0x2c32: case 0x2c33: + case 0x3e08: + break; + + default: + if ((addr & 0x3fff) >= 0x2c00 && (addr & 0x3fff) < 0x2c40) + break; + break; + } + +// pclog("mcrb: addr=%08x ret=%02x\n", addr, ret); + return ret; +} + +static void mystique_accel_ctrl_write_b(uint32_t addr, uint8_t val, void *p) +{ + mystique_t *mystique = (mystique_t *)p; + int start_blit = 0; + int x; + +// pclog("mystique accel addr=%04x val=%02x\n", addr & 0x3fff, val); + + if ((addr & 0x300) == 0x100) { + addr &= ~0x100; + start_blit = 1; + } + + switch (addr & 0x3fff) + { + case REG_MACCESS: case REG_MACCESS+1: case REG_MACCESS+2: case REG_MACCESS+3: + WRITE8(addr, mystique->maccess, val); + mystique->dwgreg.dither = mystique->maccess >> 30; + break; + + case REG_MCTLWTST: case REG_MCTLWTST+1: case REG_MCTLWTST+2: case REG_MCTLWTST+3: + WRITE8(addr, mystique->mctlwtst, val); + break; + + + case REG_PAT0: case REG_PAT0+1: case REG_PAT0+2: case REG_PAT0+3: + case REG_PAT1: case REG_PAT1+1: case REG_PAT1+2: case REG_PAT1+3: + for (x = 0; x < 8; x++) + mystique->dwgreg.pattern[addr & 7][x] = val & (1 << (7-x)); + break; + + case REG_XYSTRT: case REG_XYSTRT+1: + WRITE8(addr&1, mystique->dwgreg.ar[5], val); + if (mystique->dwgreg.ar[5] & 0x8000) + mystique->dwgreg.ar[5] |= 0xffff8000; + else + mystique->dwgreg.ar[5] &= ~0xffff8000; + WRITE8(addr&1, mystique->dwgreg.xdst, val); + break; + case REG_XYSTRT+2: case REG_XYSTRT+3: + WRITE8(addr & 1, mystique->dwgreg.ar[6], val); + if (mystique->dwgreg.ar[6] & 0x8000) + mystique->dwgreg.ar[6] |= 0xffff8000; + else + mystique->dwgreg.ar[6] &= ~0xffff8000; + WRITE8(addr & 1, mystique->dwgreg.ydst, val); + mystique->dwgreg.ydst_lin = ((int32_t)(int16_t)mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; + break; + + case REG_XYEND: case REG_XYEND+1: + WRITE8(addr&1, mystique->dwgreg.ar[0], val); + if (mystique->dwgreg.ar[0] & 0x8000) + mystique->dwgreg.ar[0] |= 0xffff8000; + else + mystique->dwgreg.ar[0] &= ~0xffff8000; +// pclog("XYEND AR[0]=%08x\n", mystique->dwgreg.ar[0]); + break; + case REG_XYEND+2: case REG_XYEND+3: + WRITE8(addr & 1, mystique->dwgreg.ar[2], val); + if (mystique->dwgreg.ar[2] & 0x8000) + mystique->dwgreg.ar[2] |= 0xffff8000; + else + mystique->dwgreg.ar[2] &= ~0xffff8000; + break; + + case REG_SGN: + mystique->dwgreg.sgn.sdydxl = val & SGN_SDYDXL; + mystique->dwgreg.sgn.scanleft = val & SGN_SCANLEFT; + mystique->dwgreg.sgn.sdxl = val & SGN_SDXL; + mystique->dwgreg.sgn.sdy = val & SGN_SDY; + mystique->dwgreg.sgn.sdxr = val & SGN_SDXR; + break; + case REG_SGN+1: case REG_SGN+2: case REG_SGN+3: + break; + + case REG_LEN: case REG_LEN+1: + WRITE8(addr, mystique->dwgreg.length, val); + break; + case REG_LEN+2: + break; + case REG_LEN+3: + mystique->dwgreg.beta = val >> 4; + if (!mystique->dwgreg.beta) + mystique->dwgreg.beta = 16; + break; + + case REG_CXBNDRY: case REG_CXBNDRY+1: + WRITE8(addr, mystique->dwgreg.cxleft, val); + break; + case REG_CXBNDRY+2: case REG_CXBNDRY+3: + WRITE8(addr & 1, mystique->dwgreg.cxright, val); + break; + case REG_FXBNDRY: case REG_FXBNDRY+1: + WRITE8(addr, mystique->dwgreg.fxleft, val); + break; + case REG_FXBNDRY+2: case REG_FXBNDRY+3: + WRITE8(addr & 1, mystique->dwgreg.fxright, val); + break; + + case REG_YDSTLEN: case REG_YDSTLEN+1: + WRITE8(addr, mystique->dwgreg.length, val); +// pclog("Write YDSTLEN+%i %i\n", addr&1, mystique->dwgreg.length); + break; + case REG_YDSTLEN+2: + mystique->dwgreg.ydst = (mystique->dwgreg.ydst & ~0xff) | val; + if (mystique->dwgreg.pitch & PITCH_YLIN) + mystique->dwgreg.ydst_lin = (mystique->dwgreg.ydst << 5) + mystique->dwgreg.ydstorg; + else { + mystique->dwgreg.ydst_lin = ((int32_t)(int16_t)mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; + mystique->dwgreg.selline = val & 7; + } +// pclog("Write YDSTLEN+2 %i %08x\n", mystique->dwgreg.ydst, mystique->dwgreg.ydst_lin); + break; + case REG_YDSTLEN+3: + mystique->dwgreg.ydst = (mystique->dwgreg.ydst & 0xff) | (((int32_t)(int8_t)val) << 8); + if (mystique->dwgreg.pitch & PITCH_YLIN) + mystique->dwgreg.ydst_lin = (mystique->dwgreg.ydst << 5) + mystique->dwgreg.ydstorg; + else + mystique->dwgreg.ydst_lin = ((int32_t)(int16_t)mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; +// pclog("Write YDSTLEN+3 %i %08x\n", mystique->dwgreg.ydst, mystique->dwgreg.ydst_lin); + break; + + case REG_XDST: case REG_XDST+1: + WRITE8(addr & 1, mystique->dwgreg.xdst, val); + break; + case REG_XDST+2: case REG_XDST+3: + break; + + case REG_YDSTORG: case REG_YDSTORG+1: case REG_YDSTORG+2: case REG_YDSTORG+3: + WRITE8(addr, mystique->dwgreg.ydstorg, val); + mystique->dwgreg.z_base = mystique->dwgreg.ydstorg*2 + mystique->dwgreg.zorg; +// pclog("ydstorg=%06x z_base=%06x\n", mystique->dwgreg.ydstorg, mystique->dwgreg.z_base); + break; + case REG_YTOP: case REG_YTOP+1: case REG_YTOP+2: case REG_YTOP+3: + WRITE8(addr, mystique->dwgreg.ytop, val); + break; + case REG_YBOT: case REG_YBOT+1: case REG_YBOT+2: case REG_YBOT+3: + WRITE8(addr, mystique->dwgreg.ybot, val); + break; + + case REG_CXLEFT: case REG_CXLEFT+1: + WRITE8(addr, mystique->dwgreg.cxleft, val); + break; + case REG_CXLEFT+2: case REG_CXLEFT+3: + break; + case REG_CXRIGHT: case REG_CXRIGHT+1: + WRITE8(addr, mystique->dwgreg.cxright, val); + break; + case REG_CXRIGHT+2: case REG_CXRIGHT+3: + break; + + case REG_FXLEFT: case REG_FXLEFT+1: + WRITE8(addr, mystique->dwgreg.fxleft, val); + break; + case REG_FXLEFT+2: case REG_FXLEFT+3: + break; + case REG_FXRIGHT: case REG_FXRIGHT+1: + WRITE8(addr, mystique->dwgreg.fxright, val); + break; + case REG_FXRIGHT+2: case REG_FXRIGHT+3: + break; + + case REG_SECADDRESS: case REG_SECADDRESS+1: case REG_SECADDRESS+2: case REG_SECADDRESS+3: + WRITE8(addr, mystique->dma.secaddress, val); + mystique->dma.sec_state = 0; + break; + + case REG_TMR0: case REG_TMR0+1: case REG_TMR0+2: case REG_TMR0+3: + WRITE8(addr, mystique->dwgreg.tmr[0], val); + break; + case REG_TMR1: case REG_TMR1+1: case REG_TMR1+2: case REG_TMR1+3: + WRITE8(addr, mystique->dwgreg.tmr[1], val); + break; + case REG_TMR2: case REG_TMR2+1: case REG_TMR2+2: case REG_TMR2+3: + WRITE8(addr, mystique->dwgreg.tmr[2], val); + break; + case REG_TMR3: case REG_TMR3+1: case REG_TMR3+2: case REG_TMR3+3: + WRITE8(addr, mystique->dwgreg.tmr[3], val); + break; + case REG_TMR4: case REG_TMR4+1: case REG_TMR4+2: case REG_TMR4+3: + WRITE8(addr, mystique->dwgreg.tmr[4], val); + break; + case REG_TMR5: case REG_TMR5+1: case REG_TMR5+2: case REG_TMR5+3: + WRITE8(addr, mystique->dwgreg.tmr[5], val); + break; + case REG_TMR6: case REG_TMR6+1: case REG_TMR6+2: case REG_TMR6+3: + WRITE8(addr, mystique->dwgreg.tmr[6], val); + break; + case REG_TMR7: case REG_TMR7+1: case REG_TMR7+2: case REG_TMR7+3: + WRITE8(addr, mystique->dwgreg.tmr[7], val); + break; + case REG_TMR8: case REG_TMR8+1: case REG_TMR8+2: case REG_TMR8+3: + WRITE8(addr, mystique->dwgreg.tmr[8], val); + break; + + case REG_TEXORG: case REG_TEXORG+1: case REG_TEXORG+2: case REG_TEXORG+3: + WRITE8(addr, mystique->dwgreg.texorg, val); +// if ((addr & 3) == 3) pclog("texorg=%08x\n", mystique->dwgreg.texorg); + break; + case REG_TEXWIDTH: case REG_TEXWIDTH+1: case REG_TEXWIDTH+2: case REG_TEXWIDTH+3: + WRITE8(addr, mystique->dwgreg.texwidth, val); +// if ((addr & 3) == 3) pclog("texwith=%08x\n", mystique->dwgreg.texwidth); + break; + case REG_TEXHEIGHT: case REG_TEXHEIGHT+1: case REG_TEXHEIGHT+2: case REG_TEXHEIGHT+3: + WRITE8(addr, mystique->dwgreg.texheight, val); +// if ((addr & 3) == 3) pclog("texheight=%08x %i %i\n", mystique->dwgreg.texheight, mystique->dwgreg.texheight&0x3f, (int)(((mystique->dwgreg.texheight >> 9) & 0x3f) | ((mystique->dwgreg.texheight & (1 << 14)) ? 0xffffffc0 : 0))); + break; + case REG_TEXCTL: case REG_TEXCTL+1: case REG_TEXCTL+2: case REG_TEXCTL+3: + WRITE8(addr, mystique->dwgreg.texctl, val); +// if ((addr & 3) == 3) pclog("texctl=%08x\n", mystique->dwgreg.texctl); + mystique->dwgreg.ta_key = (mystique->dwgreg.texctl & TEXCTL_TAKEY) ? 1 : 0; + mystique->dwgreg.ta_mask = (mystique->dwgreg.texctl & TEXCTL_TAMASK) ? 1 : 0; + break; + case REG_TEXTRANS: case REG_TEXTRANS+1: case REG_TEXTRANS+2: case REG_TEXTRANS+3: + WRITE8(addr, mystique->dwgreg.textrans, val); +// /*if ((addr & 3) == 3) */pclog("textrans=%08x\n", mystique->dwgreg.textrans); + break; + + case 0x1c28: case 0x1c29: case 0x1c2a: case 0x1c2b: + case 0x1c2c: case 0x1c2d: case 0x1c2e: case 0x1c2f: + case 0x1cc4: case 0x1cc5: case 0x1cc6: case 0x1cc7: + case 0x1cd4: case 0x1cd5: case 0x1cd6: case 0x1cd7: + case 0x1ce4: case 0x1ce5: case 0x1ce6: case 0x1ce7: + case 0x1cf4: case 0x1cf5: case 0x1cf6: case 0x1cf7: + break; + + case REG_OPMODE: + mystique->dwgreg.dmamod = (val >> 2) & 3; + mystique->dma.iload_state = 0; + break; + + default: + if ((addr & 0x3fff) >= 0x2c4c && (addr & 0x3fff) <= 0x2cff) + break; +// pclog("Write MGA accel control %08x %02x\n", addr & 0x3fff, val); + break; + } + + if (start_blit) + mystique_start_blit(mystique); +} + +static void mystique_ctrl_write_b(uint32_t addr, uint8_t val, void *p) +{ + mystique_t *mystique = (mystique_t *)p; + svga_t *svga = &mystique->svga; + +// pclog("mystique addr=%04x val=%02x\n", addr & 0x3fff, val); + + if ((addr & 0x3fff) < 0x1c00) { + mystique_iload_write_b(addr, val, p); + return; + } + if ((addr & 0x3e00) == 0x1c00 || (addr & 0x3e00) == 0x2c00) { + if ((addr & 0x300) == 0x100) + mystique->blitter_submit_refcount++; +// pclog("mystique queue addr=%04x val=%02x\n", addr & 0x3fff, val); + mystique_queue(mystique, addr & 0x3fff, val, FIFO_WRITE_CTRL_BYTE); + return; + } + + switch (addr & 0x3fff) + { + case REG_ICLEAR: +// pclog("ICLEAR %02x\n", val); + if (val & ICLEAR_SOFTRAPICLR) { + mystique->status &= ~STATUS_SOFTRAPEN; + mystique_update_irqs(mystique); + } + if (val & ICLEAR_VLINEICLR) { + mystique->status &= ~STATUS_VLINEPEN; + mystique_update_irqs(mystique); + } + break; + case REG_ICLEAR+1: case REG_ICLEAR+2: case REG_ICLEAR+3: + break; + + case REG_IEN: + mystique->ien = val & 0x65; +// pclog("Write IEN %02x\n", val); + break; + case REG_IEN+1: case REG_IEN+2: case REG_IEN+3: + break; + + case REG_OPMODE: + mystique->dmamod = (val >> 2) & 3; +// pclog("OPMODE\n"); + mystique_queue(mystique, addr & 0x3fff, val, FIFO_WRITE_CTRL_BYTE); + break; + case REG_OPMODE+1: + mystique->dmadatasiz = val & 3; + break; + case REG_OPMODE+2: + mystique->dirdatasiz = val & 3; + break; + case REG_OPMODE+3: + break; + + case REG_PRIMADDRESS: case REG_PRIMADDRESS+1: case REG_PRIMADDRESS+2: case REG_PRIMADDRESS+3: + thread_wait_mutex(mystique->dma.lock); + WRITE8(addr, mystique->dma.primaddress, val); + mystique->dma.pri_state = 0; +// pclog("PRIMADDRESS write %04x %08x\n", addr, mystique->dma.primaddress); + thread_release_mutex(mystique->dma.lock); + break; + + case REG_DMAMAP: case REG_DMAMAP+0x1: case REG_DMAMAP+0x2: case REG_DMAMAP+0x3: + case REG_DMAMAP+0x4: case REG_DMAMAP+0x5: case REG_DMAMAP+0x6: case REG_DMAMAP+0x7: + case REG_DMAMAP+0x8: case REG_DMAMAP+0x9: case REG_DMAMAP+0xa: case REG_DMAMAP+0xb: + case REG_DMAMAP+0xc: case REG_DMAMAP+0xd: case REG_DMAMAP+0xe: case REG_DMAMAP+0xf: + mystique->dmamap[addr & 0xf] = val; + break; + + case REG_RST: case REG_RST+1: case REG_RST+2: case REG_RST+3: +// pclog("Write REG_RST\n"); + wait_fifo_idle(mystique); + mystique->busy = 0; + mystique->blitter_submit_refcount = 0; + mystique->blitter_submit_dma_refcount = 0; + mystique->blitter_complete_refcount = 0; + mystique->dwgreg.iload_rem_count = 0; + mystique->status = STATUS_ENDPRDMASTS; + break; + + case REG_MISC: + svga_out(0x3c2, val, svga); + break; + + case REG_SEQ_IDX: + svga_out(0x3c4, val, svga); + break; + case REG_SEQ_DATA: + svga_out(0x3c5, val, svga); + break; + + case REG_CRTC_IDX: + mystique_out(0x3d4, val, mystique); + break; + case REG_CRTC_DATA: + mystique_out(0x3d5, val, mystique); + break; + + case REG_CRTCEXT_IDX: + mystique_out(0x3de, val, mystique); + break; + case REG_CRTCEXT_DATA: + mystique_out(0x3df, val, mystique); + break; + + case REG_CACHEFLUSH: + break; + + case REG_PALWTADD: + svga_out(0x3c8, val, svga); + mystique->xreg_idx = val; + break; + case REG_PALDATA: + svga_out(0x3c9, val, svga); + break; + case REG_PIXRDMSK: + svga_out(0x3c6, val, svga); + break; + case REG_PALRDADD: + svga_out(0x3c7, val, svga); + break; + + case REG_X_DATAREG: + mystique_write_xreg(mystique, mystique->xreg_idx, val); + break; + + case REG_CURPOSX: case REG_CURPOSX+1: + WRITE8(addr, mystique->cursor.pos_x, val); + svga->hwcursor.x = mystique->cursor.pos_x - 64; + break; + case REG_CURPOSY: case REG_CURPOSY+1: + WRITE8(addr & 1, mystique->cursor.pos_y, val); + svga->hwcursor.y = mystique->cursor.pos_y - 64; + break; + + case 0x1e50: case 0x1e51: case 0x1e52: case 0x1e53: + case 0x3c0b: case 0x3e02: case 0x3e08: + break; + + default: + if ((addr & 0x3fff) >= 0x2c4c && (addr & 0x3fff) <= 0x2cff) + break; +// pclog("Write MGA control %08x %02x\n", addr & 0x3fff, val); + break; + } +} + +static uint32_t mystique_ctrl_read_l(uint32_t addr, void *p) +{ + uint32_t ret; + +// pclog("mystique_ctrl_read_l: addr=%08x %08x\n", addr, cpu_state.pc); + if ((addr & 0x3fff) < 0x1c00) + return mystique_iload_read_l(addr, p); + + ret = mystique_ctrl_read_b(addr, p); + ret |= mystique_ctrl_read_b(addr+1, p) << 8; + ret |= mystique_ctrl_read_b(addr+2, p) << 16; + ret |= mystique_ctrl_read_b(addr+3, p) << 24; +// pclog("mcrl: addr=%08x ret=%08x %08x\n", addr, ret, mystique->status); + + return ret; +} + +static void mystique_accel_ctrl_write_l(uint32_t addr, uint32_t val, void *p) +{ + mystique_t *mystique = (mystique_t *)p; + int start_blit = 0; + +// pclog("mystique accel addr=%04x val=%08x\n", addr & 0x3fff, val); + if ((addr & 0x300) == 0x100) { + addr &= ~0x100; + start_blit = 1; + } + + switch (addr & 0x3ffc) + { + case REG_DWGCTL: +// pclog(" dwgctrl write %08x %08x\n", addr2, val); + mystique->dwgreg.dwgctrl = val; + break; + + case REG_ZORG: + mystique->dwgreg.zorg = val; + mystique->dwgreg.z_base = mystique->dwgreg.ydstorg*2 + mystique->dwgreg.zorg; +// pclog("zorg=%08x z_base=%08x\n", mystique->dwgreg.zorg, mystique->dwgreg.z_base); + break; + + case REG_PLNWT: + mystique->dwgreg.plnwt = val; + break; + + case REG_SHIFT: + mystique->dwgreg.funcnt = val & 0xff; + mystique->dwgreg.xoff = val & 7; + mystique->dwgreg.yoff = (val >> 4) & 7; + mystique->dwgreg.stylelen = (val >> 16) & 0xff; + break; + + case REG_PITCH: + mystique->dwgreg.pitch = val & 0xffff; + if (mystique->dwgreg.pitch & PITCH_YLIN) + mystique->dwgreg.ydst_lin = (mystique->dwgreg.ydst << 5) + mystique->dwgreg.ydstorg; + else + mystique->dwgreg.ydst_lin = ((int32_t)(int16_t)mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; +// pclog("pitch=%04x %i\n", mystique->dwgreg.pitch, addr&1); + break; + + case REG_YDST: + mystique->dwgreg.ydst = val & 0x3fffff; + if (mystique->dwgreg.pitch & PITCH_YLIN) { + mystique->dwgreg.ydst_lin = (mystique->dwgreg.ydst << 5) + mystique->dwgreg.ydstorg; + mystique->dwgreg.selline = val >> 29; + } else { + mystique->dwgreg.ydst_lin = ((int32_t)(int16_t)mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; + mystique->dwgreg.selline = val & 7; + } +// pclog("ydst=%i ydsth=%08x %08x pitch=%08x\n", mystique->dwgreg.ydst, mystique->dwgreg.ydst, mystique->dwgreg.ydst_lin, mystique->dwgreg.pitch); + break; + case REG_BCOL: + mystique->dwgreg.bcol = val; +// pclog("BCOL %i %02x\n", addr & 3, val); + break; + case REG_FCOL: + mystique->dwgreg.fcol = val; +// pclog("FCOL %i %02x\n", addr & 3, val); + break; + + case REG_SRC0: + mystique->dwgreg.src[0] = val; + if ((mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) == DWGCTRL_OPCODE_ILOAD) + blit_iload_write(mystique, mystique->dwgreg.src[0], 32); + break; + case REG_SRC1: + mystique->dwgreg.src[1] = val; + if ((mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) == DWGCTRL_OPCODE_ILOAD) + blit_iload_write(mystique, mystique->dwgreg.src[1], 32); + break; + case REG_SRC2: + mystique->dwgreg.src[2] = val; + if ((mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) == DWGCTRL_OPCODE_ILOAD) + blit_iload_write(mystique, mystique->dwgreg.src[2], 32); + break; + case REG_SRC3: + mystique->dwgreg.src[3] = val; + if ((mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) == DWGCTRL_OPCODE_ILOAD) + blit_iload_write(mystique, mystique->dwgreg.src[3], 32); + break; + + case REG_DMAPAD: + break; + + case REG_AR0: + mystique->dwgreg.ar[0] = val; +// pclog("AR[0]=%08x\n", mystique->dwgreg.ar[0]); + break; + case REG_AR1: + mystique->dwgreg.ar[1] = val; + break; + case REG_AR2: + mystique->dwgreg.ar[2] = val; + break; + case REG_AR3: + mystique->dwgreg.ar[3] = val; +// pclog("AR[3]=%08x\n", mystique->dwgreg.ar[3]); + break; + case REG_AR4: + mystique->dwgreg.ar[4] = val; + break; + case REG_AR5: + mystique->dwgreg.ar[5] = val; + break; + case REG_AR6: + mystique->dwgreg.ar[6] = val; + break; + + case REG_DR0: + mystique->dwgreg.dr[0] = val; + break; + case REG_DR2: + mystique->dwgreg.dr[2] = val; + break; + case REG_DR3: + mystique->dwgreg.dr[3] = val; + break; + case REG_DR4: + mystique->dwgreg.dr[4] = val; +// if ((addr & 3) == 3) pclog("DR[4]=%08x\n", mystique->dwgreg.dr[4]); + break; + case REG_DR6: + mystique->dwgreg.dr[6] = val; +// if ((addr & 3) == 3) pclog("DR[6]=%08x\n", mystique->dwgreg.dr[6]); + break; + case REG_DR7: + mystique->dwgreg.dr[7] = val; +// if ((addr & 3) == 3) pclog("DR[7]=%08x\n", mystique->dwgreg.dr[7]); + break; + case REG_DR8: + mystique->dwgreg.dr[8] = val; + break; + case REG_DR10: + mystique->dwgreg.dr[10] = val; + break; + case REG_DR11: + mystique->dwgreg.dr[11] = val; + break; + case REG_DR12: + mystique->dwgreg.dr[12] = val; + break; + case REG_DR14: + mystique->dwgreg.dr[14] = val; + break; + case REG_DR15: + mystique->dwgreg.dr[15] = val; + break; + + case REG_SECEND: +// pclog("SECEND write %08x\n", val); + mystique->dma.secend = val; + if (mystique->dma.state != DMA_STATE_SEC && (mystique->dma.secaddress & DMA_ADDR_MASK) != (mystique->dma.secend & DMA_ADDR_MASK)) { +// pclog(" DMA state STATE_SEC\n"); + mystique->dma.state = DMA_STATE_SEC; + } + break; + + case REG_SOFTRAP: +// pclog("SOFTRAP\n"); +/* mystique->dma.secaddress = val;*/ + mystique->dma.state = DMA_STATE_IDLE; + mystique->endprdmasts_pending = 1; + mystique->softrap_pending_val = val; + mystique->softrap_pending = 1; +// pclog("SOFTRAP DMA state STATE_IDLE\n"); +/* mystique->status |= STATUS_SOFTRAPEN; + mystique_update_irqs(mystique);*/ + break; + + default: + mystique_accel_ctrl_write_b(addr, val & 0xff, p); + mystique_accel_ctrl_write_b(addr+1, (val >> 8) & 0xff, p); + mystique_accel_ctrl_write_b(addr+2, (val >> 16) & 0xff, p); + mystique_accel_ctrl_write_b(addr+3, (val >> 24) & 0xff, p); + break; + } + + if (start_blit) + mystique_start_blit(mystique); +} + +static void mystique_ctrl_write_l(uint32_t addr, uint32_t val, void *p) +{ + mystique_t *mystique = (mystique_t *)p; + uint32_t reg_addr; + +// pclog("mystique addr=%04x val=%08x\n", addr & 0x3fff, val); + if ((addr & 0x3fff) < 0x1c00) { + mystique_iload_write_l(addr, val, p); + return; + } + + if ((addr & 0x3e00) == 0x1c00 || (addr & 0x3e00) == 0x2c00) { + if ((addr & 0x300) == 0x100) + mystique->blitter_submit_refcount++; +// pclog("mystique queue addr=%04x val=%08x\n", addr & 0x3fff, val); + mystique_queue(mystique, addr & 0x3fff, val, FIFO_WRITE_CTRL_LONG); + return; + } + + switch (addr & 0x3ffc) + { + case REG_PRIMEND: + thread_wait_mutex(mystique->dma.lock); +// pclog("PRIMEND write %08x\n", val); + mystique->dma.primend = val; + if (mystique->dma.state == DMA_STATE_IDLE && (mystique->dma.primaddress & DMA_ADDR_MASK) != (mystique->dma.primend & DMA_ADDR_MASK)) { +// pclog("Clear DMA end flag\n"); + mystique->endprdmasts_pending = 0; + mystique->status &= ~STATUS_ENDPRDMASTS; + + mystique->dma.state = DMA_STATE_PRI; +// pclog(" DMA state STATE_PRI\n"); + mystique->dma.pri_state = 0; + wake_fifo_thread(mystique); + } + thread_release_mutex(mystique->dma.lock); + break; + + case REG_DWG_INDIR_WT: case REG_DWG_INDIR_WT+0x04: case REG_DWG_INDIR_WT+0x08: case REG_DWG_INDIR_WT+0x0c: + case REG_DWG_INDIR_WT+0x10: case REG_DWG_INDIR_WT+0x14: case REG_DWG_INDIR_WT+0x18: case REG_DWG_INDIR_WT+0x1c: + case REG_DWG_INDIR_WT+0x20: case REG_DWG_INDIR_WT+0x24: case REG_DWG_INDIR_WT+0x28: case REG_DWG_INDIR_WT+0x2c: + case REG_DWG_INDIR_WT+0x30: case REG_DWG_INDIR_WT+0x34: case REG_DWG_INDIR_WT+0x38: case REG_DWG_INDIR_WT+0x3c: + reg_addr = (mystique->dmamap[(addr >> 2) & 0xf] & 0x7f) << 2; + if (mystique->dmamap[(addr >> 2) & 0xf] & 0x80) + reg_addr += 0x2c00; + else + reg_addr += 0x1c00; + + if ((reg_addr & 0x300) == 0x100) + mystique->blitter_submit_refcount++; + +// pclog("mystique queue dwg addr=%04x val=%08x\n", reg_addr, val); + mystique_queue(mystique, reg_addr, val, FIFO_WRITE_CTRL_LONG); + break; + + default: + mystique_ctrl_write_b(addr, val & 0xff, p); + mystique_ctrl_write_b(addr+1, (val >> 8) & 0xff, p); + mystique_ctrl_write_b(addr+2, (val >> 16) & 0xff, p); + mystique_ctrl_write_b(addr+3, (val >> 24) & 0xff, p); + break; + } +} + +static uint8_t mystique_iload_read_b(uint32_t addr, void *p) +{ + mystique_t *mystique = (mystique_t *)p; + + wait_fifo_idle(mystique); + + if (!mystique->busy) + return 0xff; + +// pclog("Readb MGA ILOAD %08x\n", addr); + return blit_idump_read(mystique); +} + +static uint32_t mystique_iload_read_l(uint32_t addr, void *p) +{ + mystique_t *mystique = (mystique_t *)p; + + wait_fifo_idle(mystique); + + if (!mystique->busy) + return 0xffffffff; + +// pclog("Readl MGA ILOAD %08x %i\n", addr, mystique->dwgreg.words); + mystique->dwgreg.words++; + return blit_idump_read(mystique); +} + +static void mystique_iload_write_b(uint32_t addr, uint8_t val, void *p) +{ + +} + +static void mystique_iload_write_l(uint32_t addr, uint32_t val, void *p) +{ + mystique_t *mystique = (mystique_t *)p; + +// pclog("mystique queue iload addr=%04x val=%08x\n", addr, val); + mystique_queue(mystique, 0, val, FIFO_WRITE_ILOAD_LONG); +} + +static void mystique_accel_iload_write_l(uint32_t addr, uint32_t val, void *p) +{ + mystique_t *mystique = (mystique_t *)p; + +// pclog(" Write ILOAD %08x %i %i\n", val, mystique->dwgreg.dmamod, mystique->dma.iload_state); + switch (mystique->dwgreg.dmamod) + { + case DMA_MODE_REG: + if (mystique->dma.iload_state == 0) { +// pclog(" ILOAD header\n"); + mystique->dma.iload_header = val; + mystique->dma.iload_state = 1; + } else { + uint32_t reg_addr = (mystique->dma.iload_header & 0x7f) << 2; + if (mystique->dma.iload_header & 0x80) + reg_addr += 0x2c00; + else + reg_addr += 0x1c00; + +// pclog(" ILOAD write %08x to %02x %04x\n", val, mystique->dma.iload_header & 0xff, reg_addr); + if ((reg_addr & 0x300) == 0x100) + mystique->blitter_submit_dma_refcount++; + mystique_accel_ctrl_write_l(reg_addr, val, mystique); + + mystique->dma.iload_header >>= 8; + mystique->dma.iload_state = (mystique->dma.iload_state == 4) ? 0 : (mystique->dma.iload_state+1); + } + break; + + case DMA_MODE_BLIT: + if (!mystique->busy) + fatal("mystique_iload_write_l: !busy\n"); + blit_iload_write(mystique, val, 32); + break; + + default: + pclog("ILOAD write DMAMOD %i\n", mystique->dwgreg.dmamod); + } +} + +static void run_dma(mystique_t *mystique) +{ + int words_transferred = 0; + + thread_wait_mutex(mystique->dma.lock); + + if (mystique->dma.state == DMA_STATE_IDLE) { + thread_release_mutex(mystique->dma.lock); + return; + } + + while (words_transferred < DMA_MAX_WORDS && mystique->dma.state != DMA_STATE_IDLE) { + switch (mystique->dma.state)// != DMA_STATE_IDLE) + { + case DMA_STATE_PRI: + switch (mystique->dma.primaddress & DMA_MODE_MASK) + { + case DMA_MODE_REG: + if (mystique->dma.pri_state == 0) { + mystique->dma.pri_header = *(uint32_t *)&ram[mystique->dma.primaddress & DMA_ADDR_MASK]; +// pclog("DMA pri read header %08x from %08x %08x\n", mystique->dma.pri_header, mystique->dma.primaddress, mystique->dma.primend); + mystique->dma.primaddress += 4; + } + +// if ((mystique->dma.pri_header & 0xff) != 0x15) + { + uint32_t val = *(uint32_t *)&ram[mystique->dma.primaddress & DMA_ADDR_MASK]; + uint32_t reg_addr; + + mystique->dma.primaddress += 4; + + reg_addr = (mystique->dma.pri_header & 0x7f) << 2; + if (mystique->dma.pri_header & 0x80) + reg_addr += 0x2c00; + else + reg_addr += 0x1c00; + +// pclog(" DMA pri write %08x to %02x %04x %08x %08x\n", val, mystique->dma.pri_header & 0xff, reg_addr, (mystique->dma.primaddress & DMA_ADDR_MASK), (mystique->dma.primend & DMA_ADDR_MASK)); + if ((reg_addr & 0x300) == 0x100) + mystique->blitter_submit_dma_refcount++; + + mystique_accel_ctrl_write_l(reg_addr, val, mystique); + } + + mystique->dma.pri_header >>= 8; + mystique->dma.pri_state = (mystique->dma.pri_state + 1) & 3; + + words_transferred++; + if (mystique->dma.state == DMA_STATE_SEC) + mystique->dma.pri_state = 0; + else if ((mystique->dma.primaddress & DMA_ADDR_MASK) == (mystique->dma.primend & DMA_ADDR_MASK)) { +// pclog("DMA pri end\n"); + mystique->endprdmasts_pending = 1; + mystique->dma.state = DMA_STATE_IDLE; + } + break; + + default: + fatal("DMA_STATE_PRI: mode %i\n", mystique->dma.primaddress & DMA_MODE_MASK); + } + break; + + case DMA_STATE_SEC: + switch (mystique->dma.secaddress & DMA_MODE_MASK) + { + case DMA_MODE_REG: + if (mystique->dma.sec_state == 0) { + mystique->dma.sec_header = *(uint32_t *)&ram[mystique->dma.secaddress & DMA_ADDR_MASK]; +// pclog("DMA sec read header %08x from %08x %08x\n", mystique->dma.sec_header, mystique->dma.secaddress, mystique->dma.secend); + mystique->dma.secaddress += 4; + } + +// if ((mystique->dma.sec_header & 0xff) != 0x15) + { + uint32_t val = *(uint32_t *)&ram[mystique->dma.secaddress & DMA_ADDR_MASK]; + uint32_t reg_addr; + + mystique->dma.secaddress += 4; + + reg_addr = (mystique->dma.sec_header & 0x7f) << 2; + if (mystique->dma.sec_header & 0x80) + reg_addr += 0x2c00; + else + reg_addr += 0x1c00; + +// pclog(" DMA sec write %08x to %02x %04x %08x %08x\n", val, mystique->dma.sec_header & 0xff, reg_addr, (mystique->dma.secaddress & DMA_ADDR_MASK), (mystique->dma.secend & DMA_ADDR_MASK)); + if ((reg_addr & 0x300) == 0x100) + mystique->blitter_submit_dma_refcount++; + + mystique_accel_ctrl_write_l(reg_addr, val, mystique); + } + + mystique->dma.sec_header >>= 8; + mystique->dma.sec_state = (mystique->dma.sec_state + 1) & 3; + + words_transferred++; + if ((mystique->dma.secaddress & DMA_ADDR_MASK) == (mystique->dma.secend & DMA_ADDR_MASK)) { +// pclog("DMA sec end\n"); + if ((mystique->dma.primaddress & DMA_ADDR_MASK) == (mystique->dma.primend & DMA_ADDR_MASK)) { +// pclog("DMA pri end\n"); + mystique->endprdmasts_pending = 1; + mystique->dma.state = DMA_STATE_IDLE; + } else { +// pclog("DMA pri resume\n"); + mystique->dma.state = DMA_STATE_PRI; + } + } + break; + + case DMA_MODE_BLIT: + { + uint32_t val = *(uint32_t *)&ram[mystique->dma.secaddress & DMA_ADDR_MASK]; +// pclog(" DMA_MODE_BLIT %08x %08x %08x %08x\n", mystique->dma.secaddress & DMA_ADDR_MASK, mystique->dma.secend & DMA_ADDR_MASK, mystique->dwgreg.dwgctrl_running, mystique->maccess_running); + mystique->dma.secaddress += 4; + + if (!mystique->busy) + fatal("mystique_iload_write_l: !busy\n"); + + blit_iload_write(mystique, val, 32); + + words_transferred++; + if ((mystique->dma.secaddress & DMA_ADDR_MASK) == (mystique->dma.secend & DMA_ADDR_MASK)) { +// pclog("DMA sec end\n"); + if ((mystique->dma.primaddress & DMA_ADDR_MASK) == (mystique->dma.primend & DMA_ADDR_MASK)) { +// pclog("DMA pri end\n"); + mystique->endprdmasts_pending = 1; + mystique->dma.state = DMA_STATE_IDLE; + } else { +// pclog("DMA pri resume\n"); + mystique->dma.state = DMA_STATE_PRI; + } + } + } + break; + + default: + fatal("DMA_STATE_SEC: mode %i\n", mystique->dma.secaddress & DMA_MODE_MASK); + } + break; + } + } + thread_release_mutex(mystique->dma.lock); +} + +static void fifo_thread(void *p) +{ + mystique_t *mystique = (mystique_t *)p; + + while (1) { + thread_set_event(mystique->fifo_not_full_event); + thread_wait_event(mystique->wake_fifo_thread, -1); + thread_reset_event(mystique->wake_fifo_thread); + + while (!FIFO_EMPTY || mystique->dma.state != DMA_STATE_IDLE) { + int words_transferred = 0; + + while (!FIFO_EMPTY && words_transferred < 100) { + fifo_entry_t *fifo = &mystique->fifo[mystique->fifo_read_idx & FIFO_MASK]; + + switch (fifo->addr_type & FIFO_TYPE) + { + case FIFO_WRITE_CTRL_BYTE: + mystique_accel_ctrl_write_b(fifo->addr_type & FIFO_ADDR, fifo->val, mystique); + break; + case FIFO_WRITE_CTRL_LONG: + mystique_accel_ctrl_write_l(fifo->addr_type & FIFO_ADDR, fifo->val, mystique); + break; + case FIFO_WRITE_ILOAD_LONG: + mystique_accel_iload_write_l(fifo->addr_type & FIFO_ADDR, fifo->val, mystique); + break; + } + + fifo->addr_type = FIFO_INVALID; + mystique->fifo_read_idx++; + + if (FIFO_ENTRIES > FIFO_THRESHOLD) + thread_set_event(mystique->fifo_not_full_event); + + words_transferred++; + } + /*Only run DMA once the FIFO is empty. Required by + Screamer 2 / Rally which will incorrectly clip an ILOAD + if DMA runs ahead*/ + if (!words_transferred) + run_dma(mystique); + } + } +} + +static void wake_fifo_thread(mystique_t *mystique) +{ + if (!timer_is_enabled(&mystique->wake_timer)) { + /*Don't wake FIFO thread immediately - if we do that it will probably + process one word and go back to sleep, requiring it to be woken on + almost every write. Instead, wait a short while so that the CPU + emulation writes more data so we have more batched-up work.*/ + timer_set_delay_u64(&mystique->wake_timer, WAKE_DELAY); + } +} + +static void wake_fifo_thread_now(mystique_t *mystique) +{ + thread_set_event(mystique->wake_fifo_thread); +} + +static void mystique_wake_timer(void *p) +{ + mystique_t *mystique = (mystique_t *)p; + + thread_set_event(mystique->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ +} + +static void wait_fifo_idle(mystique_t *mystique) +{ + while (!FIFO_EMPTY) { + wake_fifo_thread_now(mystique); + thread_wait_event(mystique->fifo_not_full_event, 1); + } +} + +/*IRQ code (PCI & PIC) is not currently thread safe. SOFTRAP IRQ requests must + therefore be submitted from the main emulation thread, in this case via a timer + callback. End-of-DMA status is also deferred here to prevent races between + SOFTRAP IRQs and code reading the status register. Croc will get into an IRQ + loop and triple fault if the ENDPRDMASTS flag is seen before the IRQ is taken*/ +static void mystique_softrap_pending_timer(void *p) +{ + mystique_t *mystique = (mystique_t *)p; + + timer_advance_u64(&mystique->softrap_pending_timer, TIMER_USEC * 100); + + if (mystique->endprdmasts_pending) { + mystique->endprdmasts_pending = 0; + mystique->status |= STATUS_ENDPRDMASTS; + } + if (mystique->softrap_pending) { + mystique->softrap_pending = 0; + +// pclog("Take SOFTRAP %08x\n", cpu_state.pc); + mystique->dma.secaddress = mystique->softrap_pending_val; + mystique->status |= STATUS_SOFTRAPEN; + mystique_update_irqs(mystique); + } +} + +static void mystique_queue(mystique_t *mystique, uint32_t addr, uint32_t val, uint32_t type) +{ + fifo_entry_t *fifo = &mystique->fifo[mystique->fifo_write_idx & FIFO_MASK]; + + if (FIFO_FULL) { + thread_reset_event(mystique->fifo_not_full_event); + if (FIFO_FULL) { + thread_wait_event(mystique->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/ + } + } + + fifo->val = val; + fifo->addr_type = (addr & FIFO_ADDR) | type; + + mystique->fifo_write_idx++; + + if (FIFO_ENTRIES > FIFO_THRESHOLD || FIFO_ENTRIES < 8) + wake_fifo_thread(mystique); + +// wait_fifo_idle(mystique); +} + +static uint32_t bitop(uint32_t src, uint32_t dst, uint32_t dwgctrl) +{ + switch (dwgctrl & DWGCTRL_BOP_MASK) + { + case BOP(0x0): return 0; + case BOP(0x1): return ~(dst | src); + case BOP(0x2): return dst & ~src; + case BOP(0x3): return ~src; + case BOP(0x4): return ~dst & src; + case BOP(0x5): return ~dst; + case BOP(0x6): return dst ^ src; + case BOP(0x7): return ~(dst & src); + case BOP(0x8): return dst & src; + case BOP(0x9): return ~(dst ^ src); + case BOP(0xa): return dst; + case BOP(0xb): return dst | ~src; + case BOP(0xc): return src; + case BOP(0xd): return ~dst | src; + case BOP(0xe): return dst | src; + case BOP(0xf): return ~0; + } + return 0; +} + +static uint16_t dither(mystique_t *mystique, int r, int g, int b, int x, int y) +{ + switch (mystique->dwgreg.dither) + { + case DITHER_NONE_555: + return (b >> 3) | ((g >> 3) << 5) | ((r >> 3) << 10); + + case DITHER_NONE_565: + return (b >> 3) | ((g >> 2) << 5) | ((r >> 3) << 11); + + case DITHER_555: + return dither5[b][y][x] | (dither5[g][y][x] << 5) | (dither5[r][y][x] << 10); + + case DITHER_565: + default: + return dither5[b][y][x] | (dither6[g][y][x] << 5) | (dither5[r][y][x] << 11); + } +} + +static uint32_t blit_idump_idump(mystique_t *mystique) +{ + svga_t *svga = &mystique->svga; + uint64_t val64 = 0; + uint32_t val = 0; + int count = 0; + + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) + { + case DWGCTRL_ATYPE_RPL: + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) + { + case DWGCTRL_BLTMOD_BU32RGB: + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) + { + case MACCESS_PWIDTH_8: +// pclog(" IDUMP %08x\n", mystique->dwgreg.src_addr); + while (count < 32) { + val |= (svga->vram[mystique->dwgreg.src_addr & mystique->vram_mask] << count); + + if (mystique->dwgreg.src_addr == mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; + mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; + mystique->dwgreg.src_addr = mystique->dwgreg.ar[3]; + } else + mystique->dwgreg.src_addr++; + + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + break; + } + break; + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + + count += 8; + } + break; + + case MACCESS_PWIDTH_16: +// pclog(" IDUMP %08x\n", mystique->dwgreg.src_addr); + while (count < 32) { + val |= (((uint16_t *)svga->vram)[mystique->dwgreg.src_addr & mystique->vram_mask_w] << count); + + if (mystique->dwgreg.src_addr == mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; + mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; + mystique->dwgreg.src_addr = mystique->dwgreg.ar[3]; + } else + mystique->dwgreg.src_addr++; + + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + break; + } + break; + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + + count += 16; + } + break; + + case MACCESS_PWIDTH_24: + if (mystique->dwgreg.idump_end_of_line) { + mystique->dwgreg.idump_end_of_line = 0; + val = mystique->dwgreg.iload_rem_data; + mystique->dwgreg.iload_rem_count = 0; + mystique->dwgreg.iload_rem_data = 0; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + } + break; + } + + count += mystique->dwgreg.iload_rem_count; + val64 = mystique->dwgreg.iload_rem_data; + +// pclog(" IDUMP %08x\n", mystique->dwgreg.src_addr); + while ((count < 32) && !mystique->dwgreg.idump_end_of_line) { + val64 |= (uint64_t)((*(uint32_t *)&svga->vram[(mystique->dwgreg.src_addr * 3) & mystique->vram_mask]) & 0xffffff) << count; +/* pclog(" %i %i %i %016llx\n", count, mystique->dwgreg.xdst, + mystique->dwgreg.length_cur, val64);*/ + + if (mystique->dwgreg.src_addr == mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; + mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; + mystique->dwgreg.src_addr = mystique->dwgreg.ar[3]; + } else + mystique->dwgreg.src_addr++; + + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + if (count > 8) + mystique->dwgreg.idump_end_of_line = 1; + else { + count = 32; + mystique->busy = 0; + mystique->blitter_complete_refcount++; + } + break; + } + if (!(mystique->dwgreg.dwgctrl_running & DWGCTRL_LINEAR)) { + if (count > 8) + mystique->dwgreg.idump_end_of_line = 1; + else { + count = 32; + break; + } + } + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + + count += 24; + } + if (count > 32) + mystique->dwgreg.iload_rem_count = count - 32; + else + mystique->dwgreg.iload_rem_count = 0; + mystique->dwgreg.iload_rem_data = (uint32_t)(val64 >> 32); + val = val64 & 0xffffffff; + break; + + case MACCESS_PWIDTH_32: +// pclog(" IDUMP %08x\n", mystique->dwgreg.src_addr); + + val = (((uint32_t *)svga->vram)[mystique->dwgreg.src_addr & mystique->vram_mask_l] << count); + + if (mystique->dwgreg.src_addr == mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; + mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; + mystique->dwgreg.src_addr = mystique->dwgreg.ar[3]; + } else + mystique->dwgreg.src_addr++; + + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + break; + } + break; + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + break; + + default: + fatal("IDUMP DWGCTRL_BLTMOD_BU32RGB %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->maccess_running); + } + break; + + default: + fatal("IDUMP DWGCTRL_ATYPE_RPL %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running); + break; + } + break; + + default: + fatal("Unknown IDUMP atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + } + + return val; +} + +static uint32_t blit_idump_read(mystique_t *mystique) +{ + uint32_t ret = 0xffffffff; + + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) + { + case DWGCTRL_OPCODE_IDUMP: + ret = blit_idump_idump(mystique); + break; + + default: + pclog("blit_idump_read: bad opcode %08x\n", mystique->dwgreg.dwgctrl_running); + break; + } + +// pclog(" idump returned %08x\n", ret); + return ret; +} + +static void blit_iload_iload(mystique_t *mystique, uint32_t data, int size) +{ + svga_t *svga = &mystique->svga; + uint32_t src, dst; + uint64_t data64; + int min_size; + uint32_t bltckey = mystique->dwgreg.fcol, bltcmsk = mystique->dwgreg.bcol; + const int transc = mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC; + const int trans_sel = (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANS_MASK) >> DWGCTRL_TRANS_SHIFT; + uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; + + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) + { + case MACCESS_PWIDTH_8: + bltckey &= 0xff; + bltcmsk &= 0xff; + break; + case MACCESS_PWIDTH_16: + bltckey &= 0xffff; + bltcmsk &= 0xffff; + break; + } + + mystique->dwgreg.words++; +// pclog("blit_iload_iload: %08x %06x %02x %i %08x words=%i %08x %08x\n", data, mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst, data, (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) == DWGCTRL_BLTMOD_BMONOWF, mystique->dwgreg.dwgctrl_running, mystique->dwgreg.words,mystique->dwgreg.words, mystique->maccess_running); + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { + case DWGCTRL_ATYPE_RPL: + if (mystique->maccess_running & MACCESS_TLUTLOAD) { + while ((mystique->dwgreg.length_cur > 0) && (size >= 16)) { + uint16_t src = data & 0xffff; +// pclog(" LUT[%02x]=%04x\n", mystique->dwgreg.ydst & 0xff, src); + + mystique->lut[mystique->dwgreg.ydst & 0xff].r = (src >> 11) << 3; + mystique->lut[mystique->dwgreg.ydst & 0xff].g = ((src >> 5) & 0x3f) << 2; + mystique->lut[mystique->dwgreg.ydst & 0xff].b = (src & 0x1f) << 3; + mystique->dwgreg.ydst++; + mystique->dwgreg.length_cur--; + data >>= 16; + size -= 16; + } + + if (!mystique->dwgreg.length_cur) + { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + } + break; + } + case DWGCTRL_ATYPE_RSTR: + case DWGCTRL_ATYPE_BLK: + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) + { + case DWGCTRL_BLTMOD_BFCOL: + size += mystique->dwgreg.iload_rem_count; +// pclog(" size=%i xdst=%i cur=%i data= %08x %08x ", size, mystique->dwgreg.xdst, mystique->dwgreg.length_cur, mystique->dwgreg.iload_rem_data, data); + data64 = mystique->dwgreg.iload_rem_data | ((uint64_t)data << mystique->dwgreg.iload_rem_count); +// pclog("%016llx words=%i\n", data64, mystique->dwgreg.words); + + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) + { + case MACCESS_PWIDTH_8: + min_size = 8; + break; + case MACCESS_PWIDTH_16: + min_size = 16; + break; + case MACCESS_PWIDTH_24: + min_size = 24; + break; + case MACCESS_PWIDTH_32: + min_size = 32; + break; + } + + while (size >= min_size) { + int draw = (!transc || (data & bltcmsk) != bltckey) && trans[mystique->dwgreg.xdst & 3]; + + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) + { + case MACCESS_PWIDTH_8: + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && draw) { + dst = svga->vram[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask]; + + dst = bitop(data & 0xff, dst, mystique->dwgreg.dwgctrl_running); +// pclog(" 8 %06x=%04x\n", mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst, dst); + svga->vram[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask) >> 12] = changeframecount; + } +/* else + pclog(" Clipped %i,%i %i %08x,%08x %08x\n", + mystique->dwgreg.cxleft, mystique->dwgreg.cxright, mystique->dwgreg.xdst, + mystique->dwgreg.ytop, mystique->dwgreg.ybot, mystique->dwgreg.ydst_lin);*/ + + data >>= 8; + size -= 8; + break; + + case MACCESS_PWIDTH_16: + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && draw) { + dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w]; + + dst = bitop(data & 0xffff, dst, mystique->dwgreg.dwgctrl_running); +// pclog(" 16 %06x=%04x\n", mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst, dst); + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w) >> 11] = changeframecount; + } + + data >>= 16; + size -= 16; + break; + + case MACCESS_PWIDTH_24: + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { + uint32_t old_dst = *((uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask]); + + dst = bitop(data64, old_dst, mystique->dwgreg.dwgctrl_running); + *((uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask]) = (dst & 0xffffff) | (old_dst & 0xff000000); + svga->changedvram[(((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask) >> 12] = changeframecount; + } + + data64 >>= 24; + size -= 24; + break; + + case MACCESS_PWIDTH_32: + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && draw) { + dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; + + dst = bitop(data, dst, mystique->dwgreg.dwgctrl_running); +// pclog(" 32 %06x=%04x\n", mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst, dst); + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount; + } + + size = 0; + break; + + default: + fatal("ILOAD RSTR/RPL BFCOL pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); + } + + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7; + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + break; + } + data64 = 0; + size = 0; + break; + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + } + mystique->dwgreg.iload_rem_count = size; + mystique->dwgreg.iload_rem_data = data64; + break; + + case DWGCTRL_BLTMOD_BMONOWF: + data = (data >> 24) | ((data & 0x00ff0000) >> 8) | ((data & 0x0000ff00) << 8) | (data << 24); + while (size) { + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && + ((data & 0x80000000) || !(mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC)) && + trans[mystique->dwgreg.xdst & 3]) { + uint32_t old_dst; + + src = (data & 0x80000000) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) + { + case MACCESS_PWIDTH_8: + dst = svga->vram[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask]; + +// pclog(" %02x %02x %06x ", src, dst, mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst); + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); +// pclog("%02x\n", dst); + + svga->vram[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_16: + dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w]; + +// pclog(" %02x %02x %06x ", src, dst, mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst); + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); +// pclog("%02x\n", dst); + + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w) >> 11] = changeframecount; + break; + + case MACCESS_PWIDTH_24: + old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask]; + +// pclog(" %02x %02x %06x ", src, old_dst, mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst); + dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running); +// pclog("%02x %08x %08x %08x %i\n", dst, data, mystique->dwgreg.fcol, mystique->dwgreg.bcol, mystique->dwgreg.xdst); + + *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000); + svga->changedvram[(((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_32: + dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; + +// pclog(" %02x %02x %06x ", src, dst, mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst); + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); +// pclog("%02x %08x %08x %08x %i\n", dst, data, mystique->dwgreg.fcol, mystique->dwgreg.bcol, mystique->dwgreg.xdst); + + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount; + break; + + default: + fatal("ILOAD RSTR/RPL BMONOWF pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); + } + } + + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + break; + } + if (!(mystique->dwgreg.dwgctrl_running & DWGCTRL_LINEAR)) + break; + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + data <<= 1; + size--; + } + break; + + case DWGCTRL_BLTMOD_BU24RGB: + size += mystique->dwgreg.iload_rem_count; +// pclog(" size=%i data= %08x %08x ", size, mystique->dwgreg.iload_rem_data, data); + data64 = mystique->dwgreg.iload_rem_data | ((uint64_t)data << mystique->dwgreg.iload_rem_count); +// pclog("%016llx\n", data64); + + while (size >= 24) { + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) + { + case MACCESS_PWIDTH_32: + dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; + +// pclog(" %06llx %02x %06x ", data64 & 0xffffff, dst, mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst); +// pclog("x=%i l=%i ", mystique->dwgreg.xdst, mystique->dwgreg.length_cur); + dst = bitop(data64 & 0xffffff, dst, mystique->dwgreg.dwgctrl_running); +// pclog("%02x\n", dst); + + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount; + break; + + default: + fatal("ILOAD RSTR/RPL BU24RGB pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); + } + } + + data64 >>= 24; + size -= 24; + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + break; + } + data64 = 0; + size = 0; + break; + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + } + + mystique->dwgreg.iload_rem_count = size; + mystique->dwgreg.iload_rem_data = data64; + break; + + default: + fatal("ILOAD DWGCTRL_ATYPE_RPL\n"); + break; + } + break; + + default: + fatal("Unknown ILOAD iload atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + } +} + +#define CLAMP(x) do \ + { \ + if ((x) & ~0xff) \ + x = ((x) < 0) ? 0 : 0xff; \ + } \ + while (0) + +static void blit_iload_iload_scale(mystique_t *mystique, uint32_t data, int size) +{ + svga_t *svga = &mystique->svga; + uint64_t data64 = 0; + int y0, y1; + int u, v; + int dR, dG, dB; + int r0, g0, b0; + int r1, g1, b1; + +// pclog(" iload_scale: data=%08x\n", data); + + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) + { + case DWGCTRL_BLTMOD_BUYUV: + y0 = (298 * ((int)(data & 0xff) - 16)) >> 8; + u = ((data >> 8) & 0xff) - 0x80; + y1 = (298 * ((int)((data >> 16) & 0xff) - 16)) >> 8; + v = ((data >> 24) & 0xff) - 0x80; + + dR = (309*v) >> 8; + dG = (100*u + 208*v) >> 8; + dB = (516*u) >> 8; + + r0 = y0 + dR; + CLAMP(r0); + g0 = y0 - dG; + CLAMP(g0); + b0 = y0 + dB; + CLAMP(b0); + r1 = y1 + dR; + CLAMP(r1); + g1 = y1 - dG; + CLAMP(g1); + b1 = y1 + dB; + CLAMP(b1); + + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) + { + case MACCESS_PWIDTH_16: + data = (b0 >> 3) | ((g0 >> 2) << 5) | ((r0 >> 3) << 11); + data |= (((b1 >> 3) | ((g1 >> 2) << 5) | ((r1 >> 3) << 11)) << 16); + size = 32; + break; + case MACCESS_PWIDTH_32: + data64 = b0 | (g0 << 8) | (r0 << 16); + data64 |= ((uint64_t)b0 << 32) | ((uint64_t)g0 << 40) | ((uint64_t)r0 << 48); + size = 64; + break; + + default: + fatal("blit_iload_iload_scale BUYUV pwidth %i\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); + } + break; + + default: + fatal("blit_iload_iload_scale bltmod %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK); + break; + } + + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) + { + case MACCESS_PWIDTH_16: + while (size >= 16) { +// pclog(" Write %i %i %08x\n", mystique->dwgreg.xdst, mystique->dwgreg.fxright, mystique->dwgreg.ar[6]); + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { + uint16_t dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w]; + dst = bitop(data & 0xffff, dst, mystique->dwgreg.dwgctrl_running); + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w) >> 11] = changeframecount; + } + + mystique->dwgreg.ar[6] += mystique->dwgreg.ar[2]; + if ((int32_t)mystique->dwgreg.ar[6] >= 0) { + mystique->dwgreg.ar[6] -= (mystique->dwgreg.fxright - mystique->dwgreg.fxleft); + data >>= 16; + size -= 16; + } + + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + mystique->dwgreg.ar[6] = mystique->dwgreg.ar[2] - (mystique->dwgreg.fxright - mystique->dwgreg.fxleft); + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + break; + } + break; + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + } + break; + + case MACCESS_PWIDTH_32: + while (size >= 32) { +// pclog(" Write %i %i %08x\n", mystique->dwgreg.xdst, mystique->dwgreg.fxright, mystique->dwgreg.ar[6]); + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { + uint32_t dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; + dst = bitop(data64, dst, mystique->dwgreg.dwgctrl_running); + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount; + } + + mystique->dwgreg.ar[6] += mystique->dwgreg.ar[2]; + if ((int32_t)mystique->dwgreg.ar[6] >= 0) { + mystique->dwgreg.ar[6] -= (mystique->dwgreg.fxright - mystique->dwgreg.fxleft); + data64 >>= 32; + size -= 32; + } + + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + mystique->dwgreg.ar[6] = mystique->dwgreg.ar[2] - (mystique->dwgreg.fxright - mystique->dwgreg.fxleft); + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + break; + } + break; + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + } + break; + + default: + fatal("ILOAD_SCALE pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); + } +} + +static void blit_iload_iload_high(mystique_t *mystique, uint32_t data, int size) +{ + svga_t *svga = &mystique->svga; + uint32_t out_data; + int y0, y1, u, v; + int dR, dG, dB; + int r = 0, g = 0, b = 0; + int next_r = 0, next_g = 0, next_b = 0; + +// pclog(" iload_high: data=%08x\n", data); + + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) + { + case DWGCTRL_BLTMOD_BUYUV: + y0 = (298 * ((int)(data & 0xff) - 16)) >> 8; + u = ((data >> 8) & 0xff) - 0x80; + y1 = (298 * ((int)((data >> 16) & 0xff) - 16)) >> 8; + v = ((data >> 24) & 0xff) - 0x80; + + dR = (309*v) >> 8; + dG = (100*u + 208*v) >> 8; + dB = (516*u) >> 8; + + r = y0 + dR; + CLAMP(r); + g = y0 - dG; + CLAMP(g); + b = y0 + dB; + CLAMP(b); + + next_r = y1 + dR; + CLAMP(next_r); + next_g = y1 - dG; + CLAMP(next_g); + next_b = y1 + dB; + CLAMP(next_b); + + size = 32; + break; + + default: + fatal("blit_iload_iload_high bltmod %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK); + break; + } + + while (size >= 16) { + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { + uint32_t dst; + int f1 = (mystique->dwgreg.ar[6] >> 12) & 0xf; + int f0 = 0x10 - f1; + int out_r = ((mystique->dwgreg.lastpix_r * f0) + (r * f1)) >> 4; + int out_g = ((mystique->dwgreg.lastpix_g * f0) + (g * f1)) >> 4; + int out_b = ((mystique->dwgreg.lastpix_b * f0) + (b * f1)) >> 4; + +// pclog(" Write %i %i %08x %i %i %i %i %i\n", mystique->dwgreg.xdst, mystique->dwgreg.fxright, mystique->dwgreg.ar[6], mystique->dwgreg.lastpix_r, r, f0, f1, out_r); + + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) + { + case MACCESS_PWIDTH_16: + out_data = (out_b >> 3) | ((out_g >> 2) << 5) | ((out_r >> 3) << 11); + dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w]; + dst = bitop(out_data, dst, mystique->dwgreg.dwgctrl_running); + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w) >> 11] = changeframecount; + break; + case MACCESS_PWIDTH_32: + out_data = out_b | (out_g << 8) | (out_r << 16); + dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; + dst = bitop(out_data, dst, mystique->dwgreg.dwgctrl_running); + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount; + break; + + default: + fatal("ILOAD_SCALE_HIGH RSTR/RPL BUYUV pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); + } + } + + mystique->dwgreg.ar[6] += mystique->dwgreg.ar[2]; + if ((int32_t)mystique->dwgreg.ar[6] >= 0) { + mystique->dwgreg.ar[6] -= 65536; + size -= 16; + + mystique->dwgreg.lastpix_r = r; + mystique->dwgreg.lastpix_g = g; + mystique->dwgreg.lastpix_b = b; + r = next_r; + g = next_g; + b = next_b; + } + + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + mystique->dwgreg.ar[6] = mystique->dwgreg.ar[2] - (mystique->dwgreg.fxright - mystique->dwgreg.fxleft); + mystique->dwgreg.lastpix_r = 0; + mystique->dwgreg.lastpix_g = 0; + mystique->dwgreg.lastpix_b = 0; + + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + break; + } + break; + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + } +} + +static void blit_iload_iload_highv(mystique_t *mystique, uint32_t data, int size) +{ + uint8_t *src0, *src1; + +// pclog(" iload_highv: data=%08x\n", data); + + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) + { + case DWGCTRL_BLTMOD_BUYUV: + if (!mystique->dwgreg.highv_line) { + mystique->dwgreg.highv_data = data; + mystique->dwgreg.highv_line = 1; + return; + } + mystique->dwgreg.highv_line = 0; + + src0 = (uint8_t *)&mystique->dwgreg.highv_data; + src1 = (uint8_t *)&data; + + src1[0] = ((src0[0] * mystique->dwgreg.beta) + (src1[0] * (16 - mystique->dwgreg.beta))) >> 4; + src1[1] = ((src0[1] * mystique->dwgreg.beta) + (src1[1] * (16 - mystique->dwgreg.beta))) >> 4; + src1[2] = ((src0[2] * mystique->dwgreg.beta) + (src1[2] * (16 - mystique->dwgreg.beta))) >> 4; + src1[3] = ((src0[3] * mystique->dwgreg.beta) + (src1[3] * (16 - mystique->dwgreg.beta))) >> 4; + blit_iload_iload_high(mystique, data, 32); + break; + + default: + fatal("blit_iload_iload_highv bltmod %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK); + break; + } +} + +static void blit_iload_write(mystique_t *mystique, uint32_t data, int size) +{ +// pclog(" ILOAD %08x %08x\n", data, mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK); + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) + { + case DWGCTRL_OPCODE_ILOAD: + blit_iload_iload(mystique, data, size); + break; + + case DWGCTRL_OPCODE_ILOAD_SCALE: + blit_iload_iload_scale(mystique, data, size); + break; + + case DWGCTRL_OPCODE_ILOAD_HIGH: + blit_iload_iload_high(mystique, data, size); + break; + + case DWGCTRL_OPCODE_ILOAD_HIGHV: + blit_iload_iload_highv(mystique, data, size); + break; + + default: + fatal("blit_iload_write: bad opcode %08x\n", mystique->dwgreg.dwgctrl_running); + } +} + +static int z_check(uint16_t z, uint16_t old_z, uint32_t z_mode)//mystique->dwgreg.dwgctrl & DWGCTRL_ZMODE_MASK) +{ + switch (z_mode) + { + case DWGCTRL_ZMODE_ZE: + return (z == old_z); + case DWGCTRL_ZMODE_ZNE: + return (z != old_z); + case DWGCTRL_ZMODE_ZLT: + return (z < old_z); + case DWGCTRL_ZMODE_ZLTE: + return (z <= old_z); + case DWGCTRL_ZMODE_ZGT: + return (z > old_z); + case DWGCTRL_ZMODE_ZGTE: + return (z >= old_z); + + case DWGCTRL_ZMODE_NOZCMP: + default: + return 1; + } +} + +static void blit_line(mystique_t *mystique, int closed) +{ + svga_t *svga = &mystique->svga; + uint32_t src, dst, old_dst; + int x; + int z_write; + + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) + { + case DWGCTRL_ATYPE_RSTR: + case DWGCTRL_ATYPE_RPL: + x = mystique->dwgreg.xdst; + while (mystique->dwgreg.length > 0) { + if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) + { + case MACCESS_PWIDTH_8: + src = mystique->dwgreg.fcol; + dst = svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask]; + +// pclog(" LINE %i %08x %08x\n", x, mystique->dwgreg.ydst_lin, mystique->dwgreg.ar[1]); + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_16: + src = mystique->dwgreg.fcol; + dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w]; + +// pclog(" LINE %i %08x %08x\n", x, mystique->dwgreg.ydst_lin, mystique->dwgreg.ar[1]); + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount; + break; + + case MACCESS_PWIDTH_24: + src = mystique->dwgreg.fcol; + old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask]; + +// pclog(" LINE %i %08x %08x\n", x, mystique->dwgreg.ydst_lin, mystique->dwgreg.ar[1]); + dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running); + *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000); + svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_32: + src = mystique->dwgreg.fcol; + dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l]; + +// pclog(" LINE %i %08x %08x\n", x, mystique->dwgreg.ydst_lin, mystique->dwgreg.ar[1]); + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l) >> 10] = changeframecount; + break; + + default: + fatal("LINE RSTR/RPL PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); + } + } + + if (mystique->dwgreg.sgn.sdydxl) + x += (mystique->dwgreg.sgn.sdxl ? -1 : 1); + else + mystique->dwgreg.ydst_lin += (mystique->dwgreg.sgn.sdy ? -(mystique->dwgreg.pitch & PITCH_MASK) : (mystique->dwgreg.pitch & PITCH_MASK)); + + if ((int32_t)mystique->dwgreg.ar[1] >= 0) { + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; + if (mystique->dwgreg.sgn.sdydxl) + mystique->dwgreg.ydst_lin += (mystique->dwgreg.sgn.sdy ? -(mystique->dwgreg.pitch & PITCH_MASK) : (mystique->dwgreg.pitch & PITCH_MASK)); + else + x += (mystique->dwgreg.sgn.sdxl ? -1 : 1); + } else + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; + + mystique->dwgreg.length--; + } + break; + + case DWGCTRL_ATYPE_I: + case DWGCTRL_ATYPE_ZI: + z_write = ((mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) == DWGCTRL_ATYPE_ZI); + x = mystique->dwgreg.xdst; + while (mystique->dwgreg.length > 0) { + if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { + uint16_t z = ((int32_t)mystique->dwgreg.dr[0] < 0) ? 0 : (mystique->dwgreg.dr[0] >> 15); + uint16_t *z_p = (uint16_t *)&svga->vram[(mystique->dwgreg.ydst_lin*2 + mystique->dwgreg.zorg) & mystique->vram_mask]; + uint16_t old_z = z_p[x]; + + if (z_check(z, old_z, mystique->dwgreg.dwgctrl_running & DWGCTRL_ZMODE_MASK)) { + int r = 0, g = 0, b = 0; + + if (z_write) + z_p[x] = z; + + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) + { + case MACCESS_PWIDTH_16: + if (!(mystique->dwgreg.dr[4] & (1 << 23))) + r = (mystique->dwgreg.dr[4] >> 18) & 0x1f; + if (!(mystique->dwgreg.dr[8] & (1 << 23))) + g = (mystique->dwgreg.dr[8] >> 17) & 0x3f; + if (!(mystique->dwgreg.dr[12] & (1 << 23))) + b = (mystique->dwgreg.dr[12] >> 18) & 0x1f; + dst = (r << 11) | (g << 5) | b; + + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount; + break; + + default: + fatal("LINE I/ZI PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); + } + } + } + + if (mystique->dwgreg.sgn.sdydxl) + x += (mystique->dwgreg.sgn.sdxl ? -1 : 1); + else + mystique->dwgreg.ydst_lin += (mystique->dwgreg.sgn.sdy ? -(mystique->dwgreg.pitch & PITCH_MASK) : (mystique->dwgreg.pitch & PITCH_MASK)); + + mystique->dwgreg.dr[0] += mystique->dwgreg.dr[2]; + mystique->dwgreg.dr[4] += mystique->dwgreg.dr[6]; + mystique->dwgreg.dr[8] += mystique->dwgreg.dr[10]; + mystique->dwgreg.dr[12] += mystique->dwgreg.dr[14]; + + if ((int32_t)mystique->dwgreg.ar[1] >= 0) { + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; + + if (mystique->dwgreg.sgn.sdydxl) + mystique->dwgreg.ydst_lin += (mystique->dwgreg.sgn.sdy ? -(mystique->dwgreg.pitch & PITCH_MASK) : (mystique->dwgreg.pitch & PITCH_MASK)); + else + x += (mystique->dwgreg.sgn.sdxl ? -1 : 1); + + mystique->dwgreg.dr[0] += mystique->dwgreg.dr[3]; + mystique->dwgreg.dr[4] += mystique->dwgreg.dr[7]; + mystique->dwgreg.dr[8] += mystique->dwgreg.dr[11]; + mystique->dwgreg.dr[12] += mystique->dwgreg.dr[15]; + } else + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; + + mystique->dwgreg.length--; + } + break; + + + default: + fatal("Unknown atype %03x %08x LINE\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + } + mystique->blitter_complete_refcount++; +} + +static void blit_autoline(mystique_t *mystique, int closed) +{ + int start_x = (int32_t)mystique->dwgreg.ar[5]; + int start_y = (int32_t)mystique->dwgreg.ar[6]; + int end_x = (int32_t)mystique->dwgreg.ar[0]; + int end_y = (int32_t)mystique->dwgreg.ar[2]; + int dx = end_x - start_x; + int dy = end_y - start_y; + + if (ABS(dx) > ABS(dy)) { + mystique->dwgreg.sgn.sdydxl = 1; + mystique->dwgreg.ar[0] = 2*ABS(dy); + mystique->dwgreg.ar[1] = 2*ABS(dy) - ABS(dx) - ((start_y > end_y) ? 1 : 0); + mystique->dwgreg.ar[2] = 2*ABS(dy) - 2*ABS(dx); + mystique->dwgreg.length = ABS(end_x - start_x); + } else { + mystique->dwgreg.sgn.sdydxl = 0; + mystique->dwgreg.ar[0] = 2*ABS(dx); + mystique->dwgreg.ar[1] = 2*ABS(dx) - ABS(dy) - ((start_y > end_y) ? 1 : 0); + mystique->dwgreg.ar[2] = 2*ABS(dx) - 2*ABS(dy); + mystique->dwgreg.length = ABS(end_y - start_y); + } + mystique->dwgreg.sgn.sdxl = (start_x > end_x) ? 1 : 0; + mystique->dwgreg.sgn.sdy = (start_y > end_y) ? 1 : 0; + + +/* pclog("Autoline %s\n", closed ? "closed" : "open"); + pclog("Start %i,%i\n", start_x, start_y); + pclog("End %i,%i\n", end_x, end_y); + pclog("SGN=%x\n", mystique->dwgreg.sgn); + pclog("AR0=%08x AR1=%08x AR2=%08x\n", mystique->dwgreg.ar[0], + mystique->dwgreg.ar[1], + mystique->dwgreg.ar[2]); + pclog("Length %i\n", mystique->dwgreg.length);*/ + blit_line(mystique, closed); + + mystique->dwgreg.ar[5] = end_x; + mystique->dwgreg.xdst = end_x; + mystique->dwgreg.ar[6] = end_y; + mystique->dwgreg.ydst = end_y; + mystique->dwgreg.ydst_lin = ((int32_t)(int16_t)mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; +} + +static void blit_trap(mystique_t *mystique) +{ + svga_t *svga = &mystique->svga; + uint32_t z_back, r_back, g_back, b_back; + int z_write; + int y; + const int trans_sel = (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANS_MASK) >> DWGCTRL_TRANS_SHIFT; + + mystique->trap_count++; + + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) + { + case DWGCTRL_ATYPE_BLK: + case DWGCTRL_ATYPE_RPL: + //fxleft, fxright + //fcol +/* pclog("fxleft=%i fxright=%i\n", mystique->dwgreg.fxleft, mystique->dwgreg.fxright); + pclog("fcol=%08x\n", mystique->dwgreg.fcol); + pclog("ytop=%i length=%i\n", mystique->dwgreg.ytop, mystique->dwgreg.length); + pclog("pitch=%08x\n", mystique->dwgreg.pitch); + pclog("ydst_lin=%08x\n", mystique->dwgreg.ydst_lin);*/ +// if (!(mystique->dwgreg.dwgctrl_running & DWGCTRL_SGNZERO)) +// fatal("Not rectangle\n"); + + for (y = 0; y < mystique->dwgreg.length; y++) { + uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; + int x_l = mystique->dwgreg.fxleft & 0xffff; + int x_r = mystique->dwgreg.fxright & 0xffff; + int yoff = (mystique->dwgreg.yoff + mystique->dwgreg.ydst) & 7; + +// pclog(" line %03i: %08x\n", y, mystique->dwgreg.ydst_lin); + while (x_l != x_r) { + if (x_l >= mystique->dwgreg.cxleft && x_l <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && + trans[x_l & 3]) { + int xoff = (mystique->dwgreg.xoff + x_l) & 7; + int pattern = mystique->dwgreg.pattern[yoff][xoff]; + uint32_t dst; + +// pclog(" %06x %02x\n", mystique->dwgreg.ydst_lin + x, mystique->dwgreg.fcol & 0xff); + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) + { + case MACCESS_PWIDTH_8: + svga->vram[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask] = + (pattern ? mystique->dwgreg.fcol : mystique->dwgreg.bcol) & 0xff; + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_16: + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w] = + (pattern ? mystique->dwgreg.fcol : mystique->dwgreg.bcol) & 0xffff; + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w) >> 11] = changeframecount; + break; + + case MACCESS_PWIDTH_24: + dst = *(uint32_t *)(&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask]) & 0xff000000; + *(uint32_t *)(&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask]) = + ((pattern ? mystique->dwgreg.fcol : mystique->dwgreg.bcol) & 0xffffff) | dst; + svga->changedvram[(((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_32: + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l] = + pattern ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l) >> 10] = changeframecount; + break; + + default: + fatal("TRAP BLK/RPL PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); + } + } + x_l = (x_l + 1) & 0xffff; + mystique->pixel_count++; + } + + if ((int32_t)mystique->dwgreg.ar[1] < 0) { + while ((int32_t)mystique->dwgreg.ar[1] < 0 && mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; + mystique->dwgreg.fxleft += (mystique->dwgreg.sgn.sdxl ? -1 : 1); + } + } else + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; + + if ((int32_t)mystique->dwgreg.ar[4] < 0) { + while ((int32_t)mystique->dwgreg.ar[4] < 0 && mystique->dwgreg.ar[6]) { + mystique->dwgreg.ar[4] += mystique->dwgreg.ar[6]; + mystique->dwgreg.fxright += (mystique->dwgreg.sgn.sdxr ? -1 : 1); + } + } else + mystique->dwgreg.ar[4] += mystique->dwgreg.ar[5]; + + mystique->dwgreg.ydst++; + mystique->dwgreg.ydst &= 0x7fffff; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + + mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7; + } + break; + + case DWGCTRL_ATYPE_RSTR: + for (y = 0; y < mystique->dwgreg.length; y++) { + uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; + int x_l = mystique->dwgreg.fxleft & 0xffff; + int x_r = mystique->dwgreg.fxright & 0xffff; + int yoff = (mystique->dwgreg.yoff + mystique->dwgreg.ydst) & 7; + +// pclog(" line %03i: %08x\n", y, mystique->dwgreg.ydst_lin); + while (x_l != x_r) { + if (x_l >= mystique->dwgreg.cxleft && x_l <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && + trans[x_l & 3]) { + int xoff = (mystique->dwgreg.xoff + x_l) & 7; + int pattern = mystique->dwgreg.pattern[yoff][xoff]; + uint32_t src = pattern ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; + uint32_t dst, old_dst; + + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) + { + case MACCESS_PWIDTH_8: + dst = svga->vram[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask]; + + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); +// pclog(" %06x %02x\n", mystique->dwgreg.ydst_lin + x, mystique->dwgreg.fcol & 0xff); + svga->vram[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_16: + dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w]; + + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); +// pclog(" %06x %02x\n", mystique->dwgreg.ydst_lin + x, mystique->dwgreg.fcol & 0xff); + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w) >> 11] = changeframecount; + break; + + case MACCESS_PWIDTH_24: + old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask]; + + dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running); +// pclog(" %06x %02x\n", mystique->dwgreg.ydst_lin + x, mystique->dwgreg.fcol & 0xff); + *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000); + svga->changedvram[(((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_32: + dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l]; + + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); +// pclog(" %06x %02x\n", mystique->dwgreg.ydst_lin + x, mystique->dwgreg.fcol & 0xff); + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l) >> 10] = changeframecount; + break; + + default: + fatal("TRAP RSTR PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); + } + } + x_l = (x_l + 1) & 0xffff; + mystique->pixel_count++; + } + + if ((int32_t)mystique->dwgreg.ar[1] < 0) { + while ((int32_t)mystique->dwgreg.ar[1] < 0 && mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; + mystique->dwgreg.fxleft += (mystique->dwgreg.sgn.sdxl ? -1 : 1); + } + } else + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; + + if ((int32_t)mystique->dwgreg.ar[4] < 0) { + while ((int32_t)mystique->dwgreg.ar[4] < 0 && mystique->dwgreg.ar[6]) { + mystique->dwgreg.ar[4] += mystique->dwgreg.ar[6]; + mystique->dwgreg.fxright += (mystique->dwgreg.sgn.sdxr ? -1 : 1); + } + } else + mystique->dwgreg.ar[4] += mystique->dwgreg.ar[5]; + + mystique->dwgreg.ydst++; + mystique->dwgreg.ydst &= 0x7fffff; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + + mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7; + } + break; + + case DWGCTRL_ATYPE_I: + case DWGCTRL_ATYPE_ZI: + z_write = ((mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) == DWGCTRL_ATYPE_ZI); +/* pclog("fxleft=%i fxright=%i\n", mystique->dwgreg.fxleft, mystique->dwgreg.fxright); + pclog("fcol=%08x\n", mystique->dwgreg.fcol); + pclog("ytop=%i length=%i\n", mystique->dwgreg.ytop, mystique->dwgreg.length); + pclog("pitch=%08x\n", mystique->dwgreg.pitch); + pclog("ydst_lin=%08x\n", mystique->dwgreg.ydst_lin); + pclog("trap! maccess=%08x %08x %08x %08x\n", mystique->maccess_running, mystique->dwgreg.dr[4], mystique->dwgreg.dr[8], mystique->dwgreg.dr[12]);*/ + + for (y = 0; y < mystique->dwgreg.length; y++) { + uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; + uint16_t *z_p = (uint16_t *)&svga->vram[(mystique->dwgreg.ydst_lin*2 + mystique->dwgreg.zorg) & mystique->vram_mask]; + int x_l = mystique->dwgreg.fxleft & 0xffff; + int x_r = mystique->dwgreg.fxright & 0xffff; + int old_x_l = x_l; + int dx; + + z_back = mystique->dwgreg.dr[0]; + r_back = mystique->dwgreg.dr[4]; + g_back = mystique->dwgreg.dr[8]; + b_back = mystique->dwgreg.dr[12]; + +// pclog(" line %03i: %08x\n", y, mystique->dwgreg.ydst_lin); + while (x_l != x_r) { + if (x_l >= mystique->dwgreg.cxleft && x_l <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && + trans[x_l & 3]) { + uint16_t z = ((int32_t)mystique->dwgreg.dr[0] < 0) ? 0 : (mystique->dwgreg.dr[0] >> 15); + uint16_t old_z = z_p[x_l]; + + if (z_check(z, old_z, mystique->dwgreg.dwgctrl_running & DWGCTRL_ZMODE_MASK)) { + uint32_t dst = 0, old_dst; + int r = 0, g = 0, b = 0; + + if (!(mystique->dwgreg.dr[4] & (1 << 23))) + r = (mystique->dwgreg.dr[4] >> 15) & 0xff; + if (!(mystique->dwgreg.dr[8] & (1 << 23))) + g = (mystique->dwgreg.dr[8] >> 15) & 0xff; + if (!(mystique->dwgreg.dr[12] & (1 << 23))) + b = (mystique->dwgreg.dr[12] >> 15) & 0xff; + + if (z_write) + z_p[x_l] = z; + +// pclog(" %06x %02x\n", mystique->dwgreg.ydst_lin + x, mystique->dwgreg.fcol & 0xff); + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) + { + case MACCESS_PWIDTH_8: + svga->vram[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_16: + dst = dither(mystique, r, g, b, x_l & 1, mystique->dwgreg.selline & 1); +// pclog(" %08x %08x %08x %04x\n", mystique->dwgreg.dr[4], mystique->dwgreg.dr[8], mystique->dwgreg.dr[12], dst); + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w) >> 11] = changeframecount; + break; + + case MACCESS_PWIDTH_24: + old_dst = *(uint32_t *)(&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask]) & 0xff000000; + *(uint32_t *)(&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask]) = old_dst | dst; + svga->changedvram[(((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_32: + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l] = b | (g << 8) | (r << 16); + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l) >> 10] = changeframecount; + break; + + default: + fatal("TRAP BLK/RPL PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); + } + } + } + + mystique->dwgreg.dr[0] += mystique->dwgreg.dr[2]; + mystique->dwgreg.dr[4] += mystique->dwgreg.dr[6]; + mystique->dwgreg.dr[8] += mystique->dwgreg.dr[10]; + mystique->dwgreg.dr[12] += mystique->dwgreg.dr[14]; + + x_l = (x_l + 1) & 0xffff; + mystique->pixel_count++; + } + + mystique->dwgreg.dr[0] = z_back + mystique->dwgreg.dr[3]; + mystique->dwgreg.dr[4] = r_back + mystique->dwgreg.dr[7]; + mystique->dwgreg.dr[8] = g_back + mystique->dwgreg.dr[11]; + mystique->dwgreg.dr[12] = b_back + mystique->dwgreg.dr[15]; + + while ((int32_t)mystique->dwgreg.ar[1] < 0 && mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; + mystique->dwgreg.fxleft += (mystique->dwgreg.sgn.sdxl ? -1 : 1); + } + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; + + while ((int32_t)mystique->dwgreg.ar[4] < 0 && mystique->dwgreg.ar[6]) { + mystique->dwgreg.ar[4] += mystique->dwgreg.ar[6]; + mystique->dwgreg.fxright += (mystique->dwgreg.sgn.sdxr ? -1 : 1); + } + mystique->dwgreg.ar[4] += mystique->dwgreg.ar[5]; + + dx = (int16_t)((mystique->dwgreg.fxleft - old_x_l) & 0xffff); + mystique->dwgreg.dr[0] += dx*mystique->dwgreg.dr[2]; + mystique->dwgreg.dr[4] += dx*mystique->dwgreg.dr[6]; + mystique->dwgreg.dr[8] += dx*mystique->dwgreg.dr[10]; + mystique->dwgreg.dr[12] += dx*mystique->dwgreg.dr[14]; + + mystique->dwgreg.ydst++; + mystique->dwgreg.ydst &= 0x7fffff; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + + mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7; + } + break; + + default: + fatal("Unknown atype %03x %08x TRAP\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + } + + mystique->blitter_complete_refcount++; +} + +static int texture_read(mystique_t *mystique, int *tex_r, int *tex_g, int *tex_b, int *atransp) +{ + svga_t *svga = &mystique->svga; + const int tex_shift = 3 + ((mystique->dwgreg.texctl & TEXCTL_TPITCH_MASK) >> TEXCTL_TPITCH_SHIFT); + const unsigned int palsel = mystique->dwgreg.texctl & TEXCTL_PALSEL_MASK; + const uint16_t tckey = mystique->dwgreg.textrans & TEXTRANS_TCKEY_MASK; + const uint16_t tkmask = (mystique->dwgreg.textrans & TEXTRANS_TKMASK_MASK) >> TEXTRANS_TKMASK_SHIFT; + const unsigned int w_mask = (mystique->dwgreg.texwidth & TEXWIDTH_TWMASK_MASK) >> TEXWIDTH_TWMASK_SHIFT; + const unsigned int h_mask = (mystique->dwgreg.texheight & TEXHEIGHT_THMASK_MASK) >> TEXHEIGHT_THMASK_SHIFT; + uint16_t src = 0; + int s, t; + + if (mystique->dwgreg.texctl & TEXCTL_NPCEN) { + const int s_shift = 20 - (mystique->dwgreg.texwidth & TEXWIDTH_TW_MASK); + const int t_shift = 20 - (mystique->dwgreg.texheight & TEXHEIGHT_TH_MASK); + + s = (int32_t)mystique->dwgreg.tmr[6] >> s_shift; + t = (int32_t)mystique->dwgreg.tmr[7] >> t_shift; + } else { + const int s_shift = (20 + 16) - (mystique->dwgreg.texwidth & TEXWIDTH_TW_MASK); + const int t_shift = (20 + 16) - (mystique->dwgreg.texheight & TEXHEIGHT_TH_MASK); + int64_t q = mystique->dwgreg.tmr[8] ? ((0x100000000ll / (int64_t)(int32_t)mystique->dwgreg.tmr[8]) /*>> 16*/) : 0; + + s = (((int64_t)(int32_t)mystique->dwgreg.tmr[6] * q) /*<< 8*/) >> s_shift;/*((16+20)-12);*/ + t = (((int64_t)(int32_t)mystique->dwgreg.tmr[7] * q) /*<< 8*/) >> t_shift;/*((16+20)-9);*/ + } + + if (mystique->dwgreg.texctl & TEXCTL_CLAMPU) { + if (s < 0) + s = 0; + else if (s > w_mask) + s = w_mask; + } else + s &= w_mask; + + if (mystique->dwgreg.texctl & TEXCTL_CLAMPV) { + if (t < 0) + t = 0; + else if (t > h_mask) + t = h_mask; + } else + t &= h_mask; + + switch (mystique->dwgreg.texctl & TEXCTL_TEXFORMAT_MASK) + { + case TEXCTL_TEXFORMAT_TW4: + src = svga->vram[(mystique->dwgreg.texorg + (((t << tex_shift) + s) >> 1)) & mystique->vram_mask]; + if (s & 1) + src >>= 4; + else + src &= 0xf; + *tex_r = mystique->lut[src | palsel].r; + *tex_g = mystique->lut[src | palsel].g; + *tex_b = mystique->lut[src | palsel].b; + *atransp = 0; + break; + case TEXCTL_TEXFORMAT_TW8: + src = svga->vram[(mystique->dwgreg.texorg + (t << tex_shift) + s) & mystique->vram_mask]; + *tex_r = mystique->lut[src].r; + *tex_g = mystique->lut[src].g; + *tex_b = mystique->lut[src].b; + *atransp = 0; + break; + case TEXCTL_TEXFORMAT_TW15: + src = ((uint16_t *)svga->vram)[((mystique->dwgreg.texorg >> 1) + (t << tex_shift) + s) & mystique->vram_mask_w]; + *tex_r = ((src >> 10) & 0x1f) << 3; + *tex_g = ((src >> 5) & 0x1f) << 3; + *tex_b = (src & 0x1f) << 3; + if (((src >> 15) & mystique->dwgreg.ta_mask) == mystique->dwgreg.ta_key) + *atransp = 1; + else + *atransp = 0; + break; + case TEXCTL_TEXFORMAT_TW16: + src = ((uint16_t *)svga->vram)[((mystique->dwgreg.texorg >> 1) + (t << tex_shift) + s) & mystique->vram_mask_w]; + *tex_r = (src >> 11) << 3; + *tex_g = ((src >> 5) & 0x3f) << 2; + *tex_b = (src & 0x1f) << 3; + *atransp = 0; + break; + default: + fatal("Unknown texture format %i\n", mystique->dwgreg.texctl & TEXCTL_TEXFORMAT_MASK); + break; + } + + return ((src & tkmask) == tckey); +} + +static void blit_texture_trap(mystique_t *mystique) +{ + svga_t *svga = &mystique->svga; + int y; + int z_write; + const int trans_sel = (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANS_MASK) >> DWGCTRL_TRANS_SHIFT; + const int dest32 = ((mystique->maccess_running & MACCESS_PWIDTH_MASK) == MACCESS_PWIDTH_32); + + mystique->trap_count++; + + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) + { + case DWGCTRL_ATYPE_I: + case DWGCTRL_ATYPE_ZI: + z_write = ((mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) == DWGCTRL_ATYPE_ZI); +// pclog("fxleft=%i fxright=%i texctl=%08x texorg=%08x ydst=%i len=%i\n", mystique->dwgreg.fxleft, mystique->dwgreg.fxright, mystique->dwgreg.texctl, mystique->dwgreg.texorg, mystique->dwgreg.ydst, mystique->dwgreg.length); +/* pclog("fcol=%08x\n", mystique->dwgreg.fcol); + pclog("ytop=%i length=%i\n", mystique->dwgreg.ytop, mystique->dwgreg.length); + pclog("pitch=%08x\n", mystique->dwgreg.pitch); + pclog("ydst=%i ydst_lin=%08x\n", mystique->dwgreg.ydst, mystique->dwgreg.ydst_lin); + pclog("dYl =%08x errl =%08x -|dXl|=%08x\n", mystique->dwgreg.ar[0], mystique->dwgreg.ar[1], mystique->dwgreg.ar[2]); + pclog("errr=%08x -|dXr|=%08x dYr =%08x\n", mystique->dwgreg.ar[4], mystique->dwgreg.ar[5], mystique->dwgreg.ar[6]); + pclog(" q/wc=%08x q/wc/dX=%08x q/wc/dY=%08x\n", + mystique->dwgreg.tmr[8], mystique->dwgreg.tmr[4], mystique->dwgreg.tmr[5]); + pclog(" s/wc=%08x s/wc/dX=%08x s/wc/dY=%08x\n", + mystique->dwgreg.tmr[6], mystique->dwgreg.tmr[0], mystique->dwgreg.tmr[1]); + pclog(" t/wc=%08x t/wc/dX=%08x t/wc/dY=%08x\n", + mystique->dwgreg.tmr[7], mystique->dwgreg.tmr[2], mystique->dwgreg.tmr[3]);*/ + + for (y = 0; y < mystique->dwgreg.length; y++) { + uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; + uint16_t *z_p = (uint16_t *)&svga->vram[(mystique->dwgreg.ydst_lin*2 + mystique->dwgreg.zorg) & mystique->vram_mask]; + int x_l = mystique->dwgreg.fxleft & 0xffff; + int x_r = mystique->dwgreg.fxright & 0xffff; + int old_x_l = x_l; + int dx; + + uint32_t z_back = mystique->dwgreg.dr[0]; + uint32_t r_back = mystique->dwgreg.dr[4]; + uint32_t g_back = mystique->dwgreg.dr[8]; + uint32_t b_back = mystique->dwgreg.dr[12]; + uint32_t s_back = mystique->dwgreg.tmr[6]; + uint32_t t_back = mystique->dwgreg.tmr[7]; + uint32_t q_back = mystique->dwgreg.tmr[8]; + +// pclog(" line %i: %i %i %08x %08x %08x %08x %i\n", __y, x_l, x_r, mystique->dwgreg.dr[0],mystique->dwgreg.dr[2],mystique->dwgreg.dr[3], mystique->dwgreg.ydst_lin*2 + mystique->dwgreg.zorg, z_write); +// pclog(" %08x %08x %08x\n", mystique->dwgreg.tmr[4],mystique->dwgreg.tmr[5], mystique->dwgreg.tmr[8]); +// pclog(" %08x %08x %08x\n", mystique->dwgreg.ar[4], mystique->dwgreg.ar[5], mystique->dwgreg.ar[6]); + + while (x_l != x_r) { + if (x_l >= mystique->dwgreg.cxleft && x_l <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && + trans[x_l & 3]) { + uint16_t z = ((int32_t)mystique->dwgreg.dr[0] < 0) ? 0 : (mystique->dwgreg.dr[0] >> 15); + uint16_t old_z = z_p[x_l]; + + if (z_check(z, old_z, mystique->dwgreg.dwgctrl_running & DWGCTRL_ZMODE_MASK)) { + int tex_r = 0, tex_g = 0, tex_b = 0; + int ctransp, atransp = 0; + int i_r = 0, i_g = 0, i_b = 0; + + if (!(mystique->dwgreg.dr[4] & (1 << 23))) + i_r = (mystique->dwgreg.dr[4] >> 15) & 0xff; + if (!(mystique->dwgreg.dr[8] & (1 << 23))) + i_g = (mystique->dwgreg.dr[8] >> 15) & 0xff; + if (!(mystique->dwgreg.dr[12] & (1 << 23))) + i_b = (mystique->dwgreg.dr[12] >> 15) & 0xff; + + ctransp = texture_read(mystique, &tex_r, &tex_g, &tex_b, &atransp); + + switch (mystique->dwgreg.texctl & (TEXCTL_TMODULATE | TEXCTL_STRANS | TEXCTL_ITRANS | TEXCTL_DECALCKEY)) + { + case 0: + if (ctransp) + goto skip_pixel; + if (atransp) { + tex_r = i_r; + tex_g = i_g; + tex_b = i_b; + } + break; + + case TEXCTL_DECALCKEY: + if (ctransp) { + tex_r = i_r; + tex_g = i_g; + tex_b = i_b; + } + break; + + case (TEXCTL_STRANS | TEXCTL_DECALCKEY): + if (ctransp) + goto skip_pixel; + break; + + case TEXCTL_TMODULATE: + if (ctransp) + goto skip_pixel; + if (mystique->dwgreg.texctl & TEXCTL_TMODULATE) { + tex_r = (tex_r * i_r) >> 8; + tex_g = (tex_g * i_g) >> 8; + tex_b = (tex_b * i_b) >> 8; + } + break; + + case (TEXCTL_TMODULATE | TEXCTL_STRANS): + if (ctransp || atransp) + goto skip_pixel; + if (mystique->dwgreg.texctl & TEXCTL_TMODULATE) { + tex_r = (tex_r * i_r) >> 8; + tex_g = (tex_g * i_g) >> 8; + tex_b = (tex_b * i_b) >> 8; + } + break; + + + default: + fatal("Bad TEXCTL %08x %08x\n", mystique->dwgreg.texctl, mystique->dwgreg.texctl & (TEXCTL_TMODULATE | TEXCTL_STRANS | TEXCTL_ITRANS | TEXCTL_DECALCKEY)); + } + + if (dest32) { + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l] = tex_b | (tex_g << 8) | (tex_r << 16); + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l) >> 10] = changeframecount; + } else { + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w] = dither(mystique, tex_r, tex_g, tex_b, x_l & 1, mystique->dwgreg.selline & 1); + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w) >> 11] = changeframecount; + } + if (z_write) + z_p[x_l] = z; + } + } +skip_pixel: + x_l = (x_l + 1) & 0xffff; + mystique->pixel_count++; + + mystique->dwgreg.dr[0] += mystique->dwgreg.dr[2]; + mystique->dwgreg.dr[4] += mystique->dwgreg.dr[6]; + mystique->dwgreg.dr[8] += mystique->dwgreg.dr[10]; + mystique->dwgreg.dr[12] += mystique->dwgreg.dr[14]; + mystique->dwgreg.tmr[6] += mystique->dwgreg.tmr[0]; + mystique->dwgreg.tmr[7] += mystique->dwgreg.tmr[2]; + mystique->dwgreg.tmr[8] += mystique->dwgreg.tmr[4]; + } + + mystique->dwgreg.dr[0] = z_back + mystique->dwgreg.dr[3]; + mystique->dwgreg.dr[4] = r_back + mystique->dwgreg.dr[7]; + mystique->dwgreg.dr[8] = g_back + mystique->dwgreg.dr[11]; + mystique->dwgreg.dr[12] = b_back + mystique->dwgreg.dr[15]; + mystique->dwgreg.tmr[6] = s_back + mystique->dwgreg.tmr[1]; + mystique->dwgreg.tmr[7] = t_back + mystique->dwgreg.tmr[3]; + mystique->dwgreg.tmr[8] = q_back + mystique->dwgreg.tmr[5]; + + while ((int32_t)mystique->dwgreg.ar[1] < 0 && mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; + mystique->dwgreg.fxleft += (mystique->dwgreg.sgn.sdxl ? -1 : 1); + } + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; + + while ((int32_t)mystique->dwgreg.ar[4] < 0 && mystique->dwgreg.ar[6]) { + mystique->dwgreg.ar[4] += mystique->dwgreg.ar[6]; + mystique->dwgreg.fxright += (mystique->dwgreg.sgn.sdxr ? -1 : 1); + } + mystique->dwgreg.ar[4] += mystique->dwgreg.ar[5]; + + dx = (int16_t)((mystique->dwgreg.fxleft - old_x_l) & 0xffff); + mystique->dwgreg.dr[0] += dx*mystique->dwgreg.dr[2]; + mystique->dwgreg.dr[4] += dx*mystique->dwgreg.dr[6]; + mystique->dwgreg.dr[8] += dx*mystique->dwgreg.dr[10]; + mystique->dwgreg.dr[12] += dx*mystique->dwgreg.dr[14]; + mystique->dwgreg.tmr[6] += dx*mystique->dwgreg.tmr[0]; + mystique->dwgreg.tmr[7] += dx*mystique->dwgreg.tmr[2]; + mystique->dwgreg.tmr[8] += dx*mystique->dwgreg.tmr[4]; + + mystique->dwgreg.ydst++; + mystique->dwgreg.ydst &= 0x7fffff; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + + mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7; + } + break; + + default: + fatal("Unknown atype %03x %08x TEXTURE_TRAP\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + } + + mystique->blitter_complete_refcount++; +} + +static void blit_bitblt(mystique_t *mystique) +{ + svga_t *svga = &mystique->svga; + uint32_t src_addr; + int y; + int x_dir = mystique->dwgreg.sgn.scanleft ? -1 : 1; + int x_start = mystique->dwgreg.sgn.scanleft ? mystique->dwgreg.fxright : mystique->dwgreg.fxleft; + int x_end = mystique->dwgreg.sgn.scanleft ? mystique->dwgreg.fxleft : mystique->dwgreg.fxright; + const int trans_sel = (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANS_MASK) >> DWGCTRL_TRANS_SHIFT; + + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) + { + case DWGCTRL_ATYPE_BLK: +// if (mystique->maccess_running & MACCESS_TLUTLOAD) +// fatal("Bitblt TLUTLOAD BLK\n"); +// if (mystique->dwgreg.dwgctrl_running & DWGCTRL_PATTERN) +// fatal("BITBLT BLK with pattern\n"); + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) + { + case DWGCTRL_BLTMOD_BMONOLEF: +// pclog("ar0=%08x ar3=%08x ar5=%08x dwgctrl=%08x\n", mystique->dwgreg.ar[0], mystique->dwgreg.ar[3], mystique->dwgreg.ar[5], mystique->dwgreg.dwgctrl_running); +// pclog("fxleft=%i fxright=%i ydst=%i fcol=%08x bcol=%08x\n", mystique->dwgreg.fxleft, mystique->dwgreg.fxright, mystique->dwgreg.ydst, mystique->dwgreg.fcol, mystique->dwgreg.bcol); + + src_addr = mystique->dwgreg.ar[3]; +// mystique->dwgreg.bit_offset = 0; + + for (y = 0; y < mystique->dwgreg.length; y++) { + int x = x_start; + +// pclog(" line %03i: %08x %08x %02x\n", y, mystique->dwgreg.ydst_lin, src_addr, svga->vram[0x2eba3]); + while (1) { + if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { + uint32_t byte_addr = (src_addr >> 3) & mystique->vram_mask; + int bit_offset = src_addr & 7; + uint32_t old_dst; + + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) + { + case MACCESS_PWIDTH_8: +// pclog(" pix %i %02x %i %i %06x\n", x, svga->vram[byte_addr], svga->vram[byte_addr] & (1 << bit_offset), mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC, byte_addr); + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC) { + if (svga->vram[byte_addr] & (1 << bit_offset)) + svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = mystique->dwgreg.fcol; + } else + svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = + (svga->vram[byte_addr] & (1 << bit_offset)) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_16: +// pclog(" pix %i %02x %i %i %06x\n", x, svga->vram[byte_addr], svga->vram[byte_addr] & (1 << bit_offset), mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC, byte_addr); + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC) { + if (svga->vram[byte_addr] & (1 << bit_offset)) + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = mystique->dwgreg.fcol; + } else + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = + (svga->vram[byte_addr] & (1 << bit_offset)) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount; + break; + + case MACCESS_PWIDTH_24: + old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask]; +// pclog(" pix %i %02x %i %i %06x\n", x, svga->vram[byte_addr], svga->vram[byte_addr] & (1 << bit_offset), mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC, byte_addr); + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC) { + if (svga->vram[byte_addr] & (1 << bit_offset)) + *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = + (old_dst & 0xff000000) | (mystique->dwgreg.fcol & 0xffffff); + } else + *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = + (old_dst & 0xff000000) | (((svga->vram[byte_addr] & (1 << bit_offset)) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol) & 0xffffff); + svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_32: +// pclog(" pix %i %02x %i %i %06x\n", x, svga->vram[byte_addr], svga->vram[byte_addr] & (1 << bit_offset), mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC, byte_addr); + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC) + { + if (svga->vram[byte_addr] & (1 << bit_offset)) + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & 0xfffff] = mystique->dwgreg.fcol; + } + else + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & 0xfffff] = + (svga->vram[byte_addr] & (1 << bit_offset)) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l) >> 10] = changeframecount; + break; + + default: + fatal("BITBLT DWGCTRL_ATYPE_BLK unknown MACCESS %i\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); + } + } + + if (src_addr == mystique->dwgreg.ar[0]) + { + mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; + mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; + src_addr = mystique->dwgreg.ar[3]; + } + else + src_addr += x_dir; + + if (x != x_end) + x = (x + x_dir) & 0xffff; + else + break; + } + + if (mystique->dwgreg.sgn.sdy) + mystique->dwgreg.ydst_lin -= (mystique->dwgreg.pitch & PITCH_MASK); + else + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + } + break; + + default: + fatal("BITBLT BLK %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK); + break; + } + break; + + + case DWGCTRL_ATYPE_RPL: +// pclog(" bitblt RPL\n"); + if (mystique->maccess_running & MACCESS_TLUTLOAD) + { +// pclog("TLUTLOAD!\n"); + src_addr = mystique->dwgreg.ar[3]; + + y = mystique->dwgreg.ydst; + + while (mystique->dwgreg.length) + { + uint16_t src = ((uint16_t *)svga->vram)[src_addr & mystique->vram_mask_w]; +// pclog(" LUT[%02x]=VRAM[%05X]=%04x\n", y & 0xff, src_addr, src); + + mystique->lut[y & 0xff].r = (src >> 11) << 3; + mystique->lut[y & 0xff].g = ((src >> 5) & 0x3f) << 2; + mystique->lut[y & 0xff].b = (src & 0x1f) << 3; + src_addr++; + y++; + mystique->dwgreg.length--; + } + break; + } + case DWGCTRL_ATYPE_RSTR: +// pclog(" bitblt RPL or RSTR\n"); +// if (mystique->maccess_running & MACCESS_TLUTLOAD) +// fatal("Bitblt TLUTLOAD RSTR\n"); + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) + { + case DWGCTRL_BLTMOD_BMONOLEF: +// pclog("ar0=%08x ar3=%08x ar5=%08x\n", mystique->dwgreg.ar[0], mystique->dwgreg.ar[3], mystique->dwgreg.ar[5]); +// pclog("fxleft=%i fxright=%i\n", mystique->dwgreg.fxleft, mystique->dwgreg.fxright); + + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_PATTERN) + fatal("BITBLT RPL/RSTR BMONOLEF with pattern\n"); + + src_addr = mystique->dwgreg.ar[3]; + + for (y = 0; y < mystique->dwgreg.length; y++) + { + uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; + int x = x_start; + +// pclog(" line %03i: %08x %08x\n", y, mystique->dwgreg.ydst_lin, src_addr); + while (1) + { + uint32_t byte_addr = (src_addr >> 3) & mystique->vram_mask; + int bit_offset = src_addr & 7; + + if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && + ((svga->vram[byte_addr] & (1 << bit_offset)) || !(mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC)) && + trans[x & 3]) + { + uint32_t src = (svga->vram[byte_addr] & (1 << bit_offset)) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; + uint32_t dst, old_dst; + + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) + { + case MACCESS_PWIDTH_8: + dst = svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask]; + +// pclog(" %02x %02x ", src, dst); + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running);// & DWGCTRL_BOP_MASK +// pclog("%08x %08x %i dst=%02x\n", src_addr, mystique->dwgreg.ydst_lin + x, mystique->dwgreg.sgn.scanleft, dst); + + svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_16: + dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w]; + +// pclog(" %02x %02x ", src, dst); + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running);// & DWGCTRL_BOP_MASK +// pclog("%08x %08x %i dst=%02x\n", src_addr, mystique->dwgreg.ydst_lin + x, mystique->dwgreg.sgn.scanleft, dst); + + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount; + break; + + case MACCESS_PWIDTH_24: + old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask]; + +// pclog(" %02x %02x ", src, old_dst); + dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running);// & DWGCTRL_BOP_MASK +// pclog("%08x %08x %i dst=%02x\n", src_addr, mystique->dwgreg.ydst_lin + x, mystique->dwgreg.sgn.scanleft, dst); + + *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000); + svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount; + break; + + default: + fatal("BITBLT RPL BMONOLEF PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); + } + } + + if (src_addr == mystique->dwgreg.ar[0]) + { + mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; + mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; + src_addr = mystique->dwgreg.ar[3]; + } + else + src_addr += x_dir; + + if (x != x_end) + x = (x + x_dir) & 0xffff; + else + break; + } + + if (mystique->dwgreg.sgn.sdy) + mystique->dwgreg.ydst_lin -= (mystique->dwgreg.pitch & PITCH_MASK); + else + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + } + break; + + + case DWGCTRL_BLTMOD_BFCOL: + case DWGCTRL_BLTMOD_BU32RGB: +// pclog("ar0=%08x ar3=%08x ar5=%08x\n", mystique->dwgreg.ar[0], mystique->dwgreg.ar[3], mystique->dwgreg.ar[5]); +// pclog("fxleft=%i fxright=%i\n", mystique->dwgreg.fxleft, mystique->dwgreg.fxright); + + src_addr = mystique->dwgreg.ar[3]; + + for (y = 0; y < mystique->dwgreg.length; y++) + { + uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; + uint32_t old_src_addr = src_addr; + int x = x_start; + +// pclog(" line %03i: %08x %08x\n", y, mystique->dwgreg.ydst_lin, src_addr); + while (1) + { + if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && + trans[x & 3]) + { + uint32_t src, dst, old_dst; + + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) + { + case MACCESS_PWIDTH_8: + src = svga->vram[src_addr & mystique->vram_mask]; + dst = svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask]; + +// pclog(" %02x %02x ", src, dst); + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running);// & DWGCTRL_BOP_MASK +// pclog("%08x %08x %i dst=%02x\n", src_addr, mystique->dwgreg.ydst_lin + x, mystique->dwgreg.sgn.scanleft, dst); + + svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_16: + src = ((uint16_t *)svga->vram)[src_addr & mystique->vram_mask_w]; + dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w]; + +// pclog(" %02x %02x ", src, dst); + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running);// & DWGCTRL_BOP_MASK +// pclog("%08x %08x %i dst=%02x\n", src_addr, mystique->dwgreg.ydst_lin + x, mystique->dwgreg.sgn.scanleft, dst); + + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount; + break; + + case MACCESS_PWIDTH_24: + src = *(uint32_t *)&svga->vram[(src_addr * 3) & mystique->vram_mask]; + old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask]; + +// pclog(" %02x %02x ", src, old_dst); + dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running);// & DWGCTRL_BOP_MASK +// pclog("%08x %08x %i dst=%02x\n", src_addr, mystique->dwgreg.ydst_lin + x, mystique->dwgreg.sgn.scanleft, dst); + + *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000); + svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_32: + src = ((uint32_t *)svga->vram)[src_addr & mystique->vram_mask_l]; + dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l]; + +// pclog(" %02x %02x ", src, dst); + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running);// & DWGCTRL_BOP_MASK +// pclog("%08x %08x %i dst=%02x\n", src_addr, mystique->dwgreg.ydst_lin + x, mystique->dwgreg.sgn.scanleft, dst); + + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l) >> 10] = changeframecount; + break; + + default: + fatal("BITBLT RPL BFCOL PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); + } + } + + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_PATTERN) + src_addr = ((src_addr + x_dir) & 7) | (src_addr & ~7); + else if (src_addr == mystique->dwgreg.ar[0]) + { + mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; + mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; + src_addr = mystique->dwgreg.ar[3]; + } + else + src_addr += x_dir; + + if (x != x_end) + x = (x + x_dir) & 0xffff; + else + break; + } + + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_PATTERN) + { + src_addr = old_src_addr; + if (mystique->dwgreg.sgn.sdy) + src_addr = ((src_addr - 32) & 0xe0) | (src_addr & ~0xe0); + else + src_addr = ((src_addr + 32) & 0xe0) | (src_addr & ~0xe0); + } + + if (mystique->dwgreg.sgn.sdy) + mystique->dwgreg.ydst_lin -= (mystique->dwgreg.pitch & PITCH_MASK); + else + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + } + break; + + default: + fatal("BITBLT DWGCTRL_ATYPE_RPL unknown BLTMOD %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running); + } + break; + + default: + fatal("Unknown BITBLT atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + } + mystique->blitter_complete_refcount++; +} + +static void blit_iload(mystique_t *mystique) +{ +// if (mystique->maccess_running & MACCESS_TLUTLOAD) +// fatal("ILOAD TLUTLOAD\n"); + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) + { + case DWGCTRL_ATYPE_RPL: + case DWGCTRL_ATYPE_RSTR: + case DWGCTRL_ATYPE_BLK: + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) + { + case DWGCTRL_BLTMOD_BFCOL: + case DWGCTRL_BLTMOD_BMONOWF: + case DWGCTRL_BLTMOD_BU24RGB: +// pclog("fxleft=%i fxright=%i\n", mystique->dwgreg.fxleft, mystique->dwgreg.fxright); +// pclog("ytop=%i length=%i\n", mystique->dwgreg.ytop, mystique->dwgreg.length); + mystique->dwgreg.length_cur = mystique->dwgreg.length; + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.iload_rem_data = 0; + mystique->dwgreg.iload_rem_count = 0; + mystique->busy = 1; + mystique->dwgreg.words = 0; + break; + + default: + fatal("ILOAD DWGCTRL_ATYPE_RPL %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running); + break; + } + break; + + default: + fatal("Unknown ILOAD atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + } +} + +static void blit_idump(mystique_t *mystique) +{ + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) + { + case DWGCTRL_ATYPE_RPL: +// pclog("ar0=%08x ar3=%08x ar5=%08x\n", mystique->dwgreg.ar[0], mystique->dwgreg.ar[3], mystique->dwgreg.ar[5]); +// pclog("fxleft=%i fxright=%i\n", mystique->dwgreg.fxleft, mystique->dwgreg.fxright); + mystique->dwgreg.length_cur = mystique->dwgreg.length; + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.src_addr = mystique->dwgreg.ar[3]; + mystique->dwgreg.words = 0; + mystique->dwgreg.iload_rem_count = 0; + mystique->dwgreg.iload_rem_data = 0; + mystique->dwgreg.idump_end_of_line = 0; + mystique->busy = 1; + break; + + default: + fatal("Unknown IDUMP atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + } +} + +static void blit_iload_scale(mystique_t *mystique) +{ + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) + { + case DWGCTRL_ATYPE_RPL: + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) + { + case DWGCTRL_BLTMOD_BUYUV: +/* pclog("fxleft=%i fxright=%i\n", mystique->dwgreg.fxleft, mystique->dwgreg.fxright); + pclog("ytop=%i length=%i\n", mystique->dwgreg.ytop, mystique->dwgreg.length); + pclog("ar0=%08x\n", mystique->dwgreg.ar[0]); + pclog("ar2=%08x\n", mystique->dwgreg.ar[2]); + pclog("ar3=%08x\n", mystique->dwgreg.ar[3]); + pclog("ar5=%08x\n", mystique->dwgreg.ar[5]); + pclog("ar6=%08x\n", mystique->dwgreg.ar[6]);*/ + mystique->dwgreg.length_cur = mystique->dwgreg.length; + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.iload_rem_data = 0; + mystique->dwgreg.iload_rem_count = 0; + mystique->busy = 1; + mystique->dwgreg.words = 0; + break; + + default: + fatal("ILOAD_SCALE DWGCTRL_ATYPE_RPL %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running); + break; + } + break; + + default: + fatal("Unknown ILOAD_SCALE atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + } +} + +static void blit_iload_high(mystique_t *mystique) +{ + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) + { + case DWGCTRL_ATYPE_RPL: + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) + { + case DWGCTRL_BLTMOD_BUYUV: +/* pclog("fxleft=%i fxright=%i\n", mystique->dwgreg.fxleft, mystique->dwgreg.fxright); + pclog("ytop=%i length=%i\n", mystique->dwgreg.ytop, mystique->dwgreg.length); + pclog("ar0=%08x\n", mystique->dwgreg.ar[0]); + pclog("ar2=%08x\n", mystique->dwgreg.ar[2]); + pclog("ar3=%08x\n", mystique->dwgreg.ar[3]); + pclog("ar5=%08x\n", mystique->dwgreg.ar[5]); + pclog("ar6=%08x\n", mystique->dwgreg.ar[6]);*/ + mystique->dwgreg.length_cur = mystique->dwgreg.length; + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.iload_rem_data = 0; + mystique->dwgreg.iload_rem_count = 0; + mystique->busy = 1; + mystique->dwgreg.words = 0; + break; + + default: + fatal("ILOAD_HIGH DWGCTRL_ATYPE_RPL %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running); + break; + } + break; + + default: + fatal("Unknown ILOAD_HIGH atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + } +} +static void blit_iload_highv(mystique_t *mystique) +{ + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) + { + case DWGCTRL_ATYPE_RPL: + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) + { + case DWGCTRL_BLTMOD_BUYUV: +/* pclog("fxleft=%i fxright=%i\n", mystique->dwgreg.fxleft, mystique->dwgreg.fxright); + pclog("ytop=%i length=%i\n", mystique->dwgreg.ytop, mystique->dwgreg.length); + pclog("ar0=%08x\n", mystique->dwgreg.ar[0]); + pclog("ar2=%08x\n", mystique->dwgreg.ar[2]); + pclog("ar3=%08x\n", mystique->dwgreg.ar[3]); + pclog("ar5=%08x\n", mystique->dwgreg.ar[5]); + pclog("ar6=%08x\n", mystique->dwgreg.ar[6]);*/ + mystique->dwgreg.length_cur = mystique->dwgreg.length; + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.iload_rem_data = 0; + mystique->dwgreg.iload_rem_count = 0; + mystique->busy = 1; + mystique->dwgreg.words = 0; + mystique->dwgreg.highv_line = 0; + mystique->dwgreg.lastpix_r = 0; + mystique->dwgreg.lastpix_g = 0; + mystique->dwgreg.lastpix_b = 0; + break; + + default: + fatal("ILOAD_HIGHV DWGCTRL_ATYPE_RPL %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running); + break; + } + break; + + default: + fatal("Unknown ILOAD_HIGHV atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + } +} + +static void mystique_start_blit(mystique_t *mystique) +{ + uint64_t start_time = plat_timer_read(); + uint64_t end_time; + + mystique->dwgreg.dwgctrl_running = mystique->dwgreg.dwgctrl; + mystique->maccess_running = mystique->maccess; +// pclog("start_blit %08x length=%i fxleft=%i fxright=%i %02x %i %i %i ylin=%08x ytop=%08x ybot=%08x\n", mystique->dwgreg.dwgctrl_running, mystique->dwgreg.length, mystique->dwgreg.fxleft, mystique->dwgreg.fxright, mystique->svga.vram[0x5c056], mystique->blitter_submit_refcount, mystique->blitter_submit_dma_refcount, mystique->blitter_complete_refcount, mystique->dwgreg.ydst_lin, mystique->dwgreg.ytop, mystique->dwgreg.ybot); + if (mystique->busy) { + fatal("Mystique still busy!\n"); + } + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_SOLID) + { + int x, y; + + for (y = 0; y < 8; y++) + { + for (x = 0; x < 8; x++) + mystique->dwgreg.pattern[y][x] = 1; + } + mystique->dwgreg.src[0] = 0xffffffff; + mystique->dwgreg.src[1] = 0xffffffff; + mystique->dwgreg.src[2] = 0xffffffff; + mystique->dwgreg.src[3] = 0xffffffff; + } + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_ARZERO) + { + mystique->dwgreg.ar[0] = 0; + mystique->dwgreg.ar[1] = 0; + mystique->dwgreg.ar[2] = 0; + mystique->dwgreg.ar[4] = 0; + mystique->dwgreg.ar[5] = 0; + mystique->dwgreg.ar[6] = 0; + } + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_SGNZERO) + { + mystique->dwgreg.sgn.sdydxl = 0; + mystique->dwgreg.sgn.scanleft = 0; + mystique->dwgreg.sgn.sdxl = 0; + mystique->dwgreg.sgn.sdy = 0; + mystique->dwgreg.sgn.sdxr = 0; + } + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_SHTZERO) + { + mystique->dwgreg.funcnt = 0; + mystique->dwgreg.stylelen = 0; + mystique->dwgreg.xoff = 0; + mystique->dwgreg.yoff = 0; + } + + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) + { + case DWGCTRL_OPCODE_LINE_OPEN: + blit_line(mystique, 0); + break; + + case DWGCTRL_OPCODE_AUTOLINE_OPEN: + blit_autoline(mystique, 0); + break; + + case DWGCTRL_OPCODE_AUTOLINE_CLOSE: + blit_autoline(mystique, 1); + break; + + case DWGCTRL_OPCODE_TRAP: + blit_trap(mystique); + break; + + case DWGCTRL_OPCODE_TEXTURE_TRAP: + blit_texture_trap(mystique); + break; + + case DWGCTRL_OPCODE_ILOAD_HIGH: + blit_iload_high(mystique); + break; + + case DWGCTRL_OPCODE_BITBLT: + blit_bitblt(mystique); + break; + + case DWGCTRL_OPCODE_ILOAD: + blit_iload(mystique); + break; + + case DWGCTRL_OPCODE_IDUMP: + blit_idump(mystique); + break; + + case DWGCTRL_OPCODE_ILOAD_SCALE: + blit_iload_scale(mystique); + break; + + case DWGCTRL_OPCODE_ILOAD_HIGHV: + blit_iload_highv(mystique); + break; + + default: + fatal("mystique_start_blit: unknown blit %08x\n", mystique->dwgreg.dwgctrl_running); + } +// pclog("blit done\n"); + + end_time = plat_timer_read(); + mystique->blitter_time += end_time - start_time; +} + + +static void mystique_hwcursor_draw(svga_t *svga, int displine) +{ + int x; + uint64_t dat[2]; + int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; + + dat[0] = *(uint64_t *)(&svga->vram[svga->hwcursor_latch.addr]); + dat[1] = *(uint64_t *)(&svga->vram[svga->hwcursor_latch.addr + 8]); + svga->hwcursor_latch.addr += 16; + for (x = 0; x < 64; x ++) + { + if (!(dat[1] & (1ull << 63))) + buffer32->line[displine][offset + svga->x_add] = (dat[0] & (1ull << 63)) ? 0xffffff : 0; + else if (dat[0] & (1ull << 63)) + buffer32->line[displine][offset + svga->x_add] ^= 0xffffff; + + offset++; + dat[0] <<= 1; + dat[1] <<= 1; + } +} + + +static uint8_t mystique_pci_read(int func, int addr, void *p) +{ + mystique_t *mystique = (mystique_t *)p; + +// pclog("mystique PCI read %08X\n", addr); + switch (addr) + { + case 0x00: return 0x2b; /*Matrox*/ + case 0x01: return 0x10; + + case 0x02: return 0x1a; /*MGA-1064SG*/ + case 0x03: return 0x05; + + case PCI_REG_COMMAND: + return mystique->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ + + case 0x07: return 0 << 1; /*Fast DEVSEL timing*/ + + case 0x08: return 0; /*Revision ID*/ + case 0x09: return 0; /*Programming interface*/ + + case 0x0a: return 0x00; /*Supports VGA interface*/ + case 0x0b: return 0x03; + + case 0x10: return 0x00; /*Control aperture*/ + case 0x11: return (mystique->ctrl_base >> 8) & 0xc0; + case 0x12: return mystique->ctrl_base >> 16; + case 0x13: return mystique->ctrl_base >> 24; + + case 0x14: return 0x00; /*Linear frame buffer*/ + case 0x16: return (mystique->lfb_base >> 16) & 0x80; + case 0x17: return mystique->lfb_base >> 24; + + case 0x18: return 0x00; /*Pseudo-DMA (ILOAD)*/ + case 0x1a: return (mystique->iload_base >> 16) & 0x80; + case 0x1b: return mystique->iload_base >> 24; + + case 0x30: return mystique->pci_regs[0x30] & 0x01; /*BIOS ROM address*/ + case 0x31: return 0x00; + case 0x32: return mystique->pci_regs[0x32]; + case 0x33: return mystique->pci_regs[0x33]; + + case 0x3c: return mystique->int_line; + case 0x3d: return PCI_INTA; + + case 0x40: return mystique->pci_regs[0x40]; + case 0x41: return mystique->pci_regs[0x41]; + case 0x42: return mystique->pci_regs[0x42]; + case 0x43: return mystique->pci_regs[0x43]; + + case 0x44: return mystique->pci_regs[0x44]; + case 0x45: return mystique->pci_regs[0x45]; + + case 0x48: case 0x49: case 0x4a: case 0x4b: + addr = (mystique->pci_regs[0x44] & 0xfc) | + ((mystique->pci_regs[0x45] & 0x3f) << 8) | + (addr & 3); + return mystique_ctrl_read_b(addr, mystique); + } + return 0; +} + +static void mystique_pci_write(int func, int addr, uint8_t val, void *p) +{ + mystique_t *mystique = (mystique_t *)p; + +// pclog("mystique_pci_write: func=%i addr=%02x val=%02x\n", func, addr, val); + switch (addr) + { + case PCI_REG_COMMAND: + mystique->pci_regs[PCI_REG_COMMAND] = val & 0x23; + mystique_recalc_mapping(mystique); + break; + + case 0x11: + mystique->ctrl_base = (mystique->ctrl_base & 0xffff0000) | ((val & 0xc0) << 8); + mystique_recalc_mapping(mystique); + break; + case 0x12: + mystique->ctrl_base = (mystique->ctrl_base & 0xff00c000) | (val << 16); + mystique_recalc_mapping(mystique); + break; + case 0x13: + mystique->ctrl_base = (mystique->ctrl_base & 0x00ffc000) | (val << 24); + mystique_recalc_mapping(mystique); + break; + + case 0x16: + mystique->lfb_base = (mystique->lfb_base & 0xff000000) | ((val & 0x80) << 16); + mystique_recalc_mapping(mystique); + break; + case 0x17: + mystique->lfb_base = (mystique->lfb_base & 0x00800000) | (val << 24); + mystique_recalc_mapping(mystique); + break; + + case 0x1a: + mystique->iload_base = (mystique->iload_base & 0xff000000) | ((val & 0x80) << 16); + mystique_recalc_mapping(mystique); + break; + case 0x1b: + mystique->iload_base = (mystique->iload_base & 0x00800000) | (val << 24); + mystique_recalc_mapping(mystique); + break; + + case 0x30: case 0x32: case 0x33: + mystique->pci_regs[addr] = val; + if (mystique->pci_regs[0x30] & 0x01) + { + uint32_t addr = (mystique->pci_regs[0x32] << 16) | (mystique->pci_regs[0x33] << 24); + mem_mapping_set_addr(&mystique->bios_rom.mapping, addr, 0x8000); + } + else + mem_mapping_disable(&mystique->bios_rom.mapping); + return; + + case 0x3c: + mystique->int_line = val; + return; + + case 0x40: case 0x41: case 0x42: case 0x43: + mystique->pci_regs[addr] = val; + break; + + case 0x4c: case 0x4d: case 0x4e: case 0x4f: + mystique->pci_regs[addr-0x20] = val; + break; + + case 0x44: case 0x45: + mystique->pci_regs[addr] = val; + break; + + case 0x48: case 0x49: case 0x4a: case 0x4b: + addr = (mystique->pci_regs[0x44] & 0xfc) | + ((mystique->pci_regs[0x45] & 0x3f) << 8) | + (addr & 3); + mystique_ctrl_write_b(addr, val, mystique); + break; + } +} + +static void * +mystique_init(const device_t *info) +{ + int c; + mystique_t *mystique = malloc(sizeof(mystique_t)); + memset(mystique, 0, sizeof(mystique_t)); + + rom_init(&mystique->bios_rom, L"roms/video/matrox/MYSTIQUE.VBI", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + + mystique->vram_size = device_get_config_int("memory"); + mystique->vram_mask = (mystique->vram_size << 20) - 1; + mystique->vram_mask_w = mystique->vram_mask >> 1; + mystique->vram_mask_l = mystique->vram_mask >> 2; + + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_matrox_mystique); + + svga_init(&mystique->svga, mystique, mystique->vram_size << 20, + mystique_recalctimings, + mystique_in, mystique_out, + mystique_hwcursor_draw, + NULL); + + io_sethandler(0x03c0, 0x0020, mystique_in, NULL, NULL, mystique_out, NULL, NULL, mystique); + mem_mapping_add(&mystique->ctrl_mapping, 0, 0, + mystique_ctrl_read_b, NULL, mystique_ctrl_read_l, + mystique_ctrl_write_b, NULL, mystique_ctrl_write_l, + NULL, 0, mystique); + mem_mapping_add(&mystique->lfb_mapping, 0, 0, + svga_read_linear, svga_readw_linear, svga_readl_linear, + svga_write_linear, svga_writew_linear, svga_writel_linear, + NULL, 0, mystique); + mem_mapping_add(&mystique->iload_mapping, 0, 0, + mystique_iload_read_b, NULL, mystique_iload_read_l, + mystique_iload_write_b, NULL, mystique_iload_write_l, + NULL, 0, mystique); + + + mystique->card = pci_add_card(PCI_ADD_VIDEO, mystique_pci_read, mystique_pci_write, mystique); + mystique->pci_regs[0x2c] = mystique->bios_rom.rom[0x7ff8]; + mystique->pci_regs[0x2d] = mystique->bios_rom.rom[0x7ff8]; + mystique->pci_regs[0x2e] = mystique->bios_rom.rom[0x7ff8]; + mystique->pci_regs[0x2f] = mystique->bios_rom.rom[0x7ff8]; + + mystique->svga.miscout = 1; + mystique->pci_regs[0x41] = 0x01; /*vgaboot=1*/ + + for (c = 0; c < 256; c++) + { + dither5[c][0][0] = c >> 3; + dither5[c][1][1] = (c + 2) >> 3; + dither5[c][1][0] = (c + 4) >> 3; + dither5[c][0][1] = (c + 6) >> 3; + + if (dither5[c][1][1] > 31) + dither5[c][1][1] = 31; + if (dither5[c][1][0] > 31) + dither5[c][1][0] = 31; + if (dither5[c][0][1] > 31) + dither5[c][0][1] = 31; + + dither6[c][0][0] = c >> 2; + dither6[c][1][1] = (c + 1) >> 2; + dither6[c][1][0] = (c + 2) >> 2; + dither6[c][0][1] = (c + 3) >> 2; + + if (dither6[c][1][1] > 63) + dither6[c][1][1] = 63; + if (dither6[c][1][0] > 63) + dither6[c][1][0] = 63; + if (dither6[c][0][1] > 63) + dither6[c][0][1] = 63; + } + + mystique->wake_fifo_thread = thread_create_event(); + mystique->fifo_not_full_event = thread_create_event(); + mystique->fifo_thread = thread_create(fifo_thread, mystique); + mystique->dma.lock = thread_create_mutex(L"86Box.MGAMutex"); + + timer_add(&mystique->wake_timer, mystique_wake_timer, (void *)mystique, 0); + timer_add(&mystique->softrap_pending_timer, mystique_softrap_pending_timer, (void *)mystique, 1); + + mystique->status = STATUS_ENDPRDMASTS; + + return mystique; +} + +static void mystique_close(void *p) +{ + mystique_t *mystique = (mystique_t *)p; + + thread_kill(mystique->fifo_thread); + thread_destroy_event(mystique->wake_fifo_thread); + thread_destroy_event(mystique->fifo_not_full_event); + thread_close_mutex(mystique->dma.lock); + + svga_close(&mystique->svga); + + free(mystique); +} + +static int mystique_available(void) +{ + return rom_present(L"roms/video/matrox/MYSTIQUE.VBI"); +} + +static void mystique_speed_changed(void *p) +{ + mystique_t *mystique = (mystique_t *)p; + + svga_recalctimings(&mystique->svga); +} + +static void mystique_force_redraw(void *p) +{ + mystique_t *mystique = (mystique_t *)p; + + mystique->svga.fullchange = changeframecount; +} + +static const device_config_t mystique_config[] = +{ + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .selection = + { + { + .description = "2 MB", + .value = 2 + }, + { + .description = "4 MB", + .value = 4 + }, + { + .description = "" + } + }, + .default_int = 4 + }, + { + .type = -1 + } +}; + +const device_t mystique_device = +{ + "Matrox Mystique", + DEVICE_PCI, + 0, + mystique_init, + mystique_close, + NULL, + mystique_available, + mystique_speed_changed, + mystique_force_redraw, + mystique_config +}; diff --git a/src/video/vid_mga.h b/src/video/vid_mga.h new file mode 100644 index 000000000..50c72d3ae --- /dev/null +++ b/src/video/vid_mga.h @@ -0,0 +1,17 @@ +/* + * 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. + * + * Matrox MGA graphics card emulation. + * + * Version: @(#)vid_mga.h 1.0.0 2020/01/16 + * + * Author: Sarah Walker, + * Copyright 2008-2020 Sarah Walker. + */ + +extern const device_t mystique_device; \ No newline at end of file diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index a07764f12..8978135f9 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -570,6 +570,7 @@ svga_poll(void *p) uint32_t x, blink_delay; int wx, wy; int skip = (svga->crtc[8] >> 5) & 0x03; + int ret; if (!svga->linepos) { if (svga->displine == svga->hwcursor_latch.y && svga->hwcursor_latch.ena) { @@ -701,11 +702,18 @@ svga_poll(void *p) svga->vc &= 2047; if (svga->vc == svga->split) { - svga->ma = svga->maback = 0; - svga->sc = 0; - if (svga->attrregs[0x10] & 0x20) { - svga->scrollcache = 0; - svga->x_add = (overscan_x >> 1); + ret = 1; + + if (svga->line_compare) + ret = svga->line_compare(svga); + + if (ret) { + svga->ma = svga->maback = 0; + svga->sc = 0; + if (svga->attrregs[0x10] & 0x20) { + svga->scrollcache = 0; + svga->x_add = (overscan_x >> 1); + } } } if (svga->vc == svga->dispend) { diff --git a/src/video/vid_svga.h b/src/video/vid_svga.h index 589039d3d..895313a29 100644 --- a/src/video/vid_svga.h +++ b/src/video/vid_svga.h @@ -109,6 +109,11 @@ typedef struct svga_t void (*ven_write)(struct svga_t *svga, uint8_t val, uint32_t addr); float (*getclock)(int clock, void *p); + /*Called when VC=R18 and friends. If this returns zero then MA resetting + is skipped. Matrox Mystique in Power mode reuses this counter for + vertical line interrupt*/ + int (*line_compare)(struct svga_t *svga); + /*If set then another device is driving the monitor output and the SVGA card should not attempt to display anything */ int override; diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 1a8fc061b..1d9de528c 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -678,6 +678,7 @@ VIDOBJ := video.o \ vid_et4000.o vid_sc1502x_ramdac.o \ vid_et4000w32.o vid_stg_ramdac.o \ vid_ht216.o \ + vid_mga.o \ vid_oak_oti.o \ vid_paradise.o \ vid_ti_cf62011.o \ diff --git a/src/win/Makefile_ndr.mingw b/src/win/Makefile_ndr.mingw index 227707181..63cdf0b33 100644 --- a/src/win/Makefile_ndr.mingw +++ b/src/win/Makefile_ndr.mingw @@ -684,6 +684,7 @@ VIDOBJ := video.o \ vid_et4000.o vid_sc1502x_ramdac.o \ vid_et4000w32.o vid_stg_ramdac.o \ vid_ht216.o \ + vid_mga.o \ vid_oak_oti.o \ vid_paradise.o \ vid_ti_cf62011.o \ From cf31b00d34d601606a491c6bdeca8dcd6fc8d7f0 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 17 Jan 2020 00:36:19 +0100 Subject: [PATCH 163/177] Fixed a bug in the SST Flash code that was causing the high Flash mapping to not be visible at all. --- src/sst_flash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sst_flash.c b/src/sst_flash.c index 3dc151294..9826742f5 100644 --- a/src/sst_flash.c +++ b/src/sst_flash.c @@ -227,7 +227,7 @@ sst_add_mappings(sst_t *dev) sst_read, sst_readw, sst_readl, sst_write, NULL, NULL, dev->array + fbase, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROMCS, (void *) dev); - mem_mapping_add(&(dev->mapping_h[i]), (base | 0xfff00000) - 0x40000, 0x10000, + mem_mapping_add(&(dev->mapping_h[i]), (base | 0xfff00000), 0x10000, sst_read, sst_readw, sst_readl, sst_write, NULL, NULL, dev->array + fbase, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROMCS, (void *) dev); From 3a8b89af6334e696cd17cb03d8a4be6540a5a56a Mon Sep 17 00:00:00 2001 From: horkthane <37665479+horkthane@users.noreply.github.com> Date: Thu, 16 Jan 2020 19:23:54 -0500 Subject: [PATCH 164/177] Assorted Joystick fixes Implemented use of DirectInput sliders. They were previously lumped in with axis and then not read or used at all. Lots of use of joystick_type == 7 or joystick_type != 7 to detect if the joystick_type was none. Changed this to a define. The text to enumerate the types of joysticks was contained in a numbered LPARAM sheet. Switched to using the name listed in the joystick struct. Joysticks with more than 32 buttons would overflow the plat_joystick_state button array. Added overflow checks. Added a 4 axis 4 button joystick type that Win98 can pick up as a generic 4 axis 4 button controller. --- src/config.c | 6 +-- src/game/gameport.c | 5 ++- src/game/gameport.h | 10 +++++ src/game/joystick_standard.c | 37 +++++++++++++++ src/game/joystick_standard.h | 1 + src/machine/m_amstrad.c | 2 +- src/machine/m_at.c | 2 +- src/machine/m_europc.c | 2 +- src/machine/m_olivetti_m24.c | 2 +- src/machine/m_ps1.c | 2 +- src/machine/m_tandy.c | 2 +- src/machine/m_xt.c | 2 +- src/machine/m_xt_compaq.c | 2 +- src/machine/m_xt_laserxt.c | 2 +- src/machine/m_xt_xi8088.c | 2 +- src/pc.c | 2 +- src/win/win_joystick.cpp | 79 ++++++++++++++++++++++----------- src/win/win_joystick_xinput.cpp | 2 +- src/win/win_jsconf.c | 29 +++++++++--- src/win/win_settings.c | 11 ++++- 20 files changed, 151 insertions(+), 51 deletions(-) diff --git a/src/config.c b/src/config.c index a174c2c89..f2b6076c1 100644 --- a/src/config.c +++ b/src/config.c @@ -607,7 +607,7 @@ load_input_devices(void) else mouse_type = 0; - joystick_type = config_get_int(cat, "joystick_type", 7); + joystick_type = config_get_int(cat, "joystick_type", JOYSTICK_TYPE_NONE); for (c=0; cmouse, 2); /* Configure the port for (Bus Mouse Compatible) Mouse. */ b |= 0x01; - } else if (joystick_type != 7) + } else if (joystick_type != JOYSTICK_TYPE_NONE) b |= 0x02; /* enable port as joysticks */ sys->nvr.regs[MRTC_CONF_C] = b; diff --git a/src/machine/m_olivetti_m24.c b/src/machine/m_olivetti_m24.c index 694fec24c..9bb84198f 100644 --- a/src/machine/m_olivetti_m24.c +++ b/src/machine/m_olivetti_m24.c @@ -892,7 +892,7 @@ machine_olim24_init(const machine_t *model) keyboard_set_table(scancode_xt); - if (joystick_type != 7) + if (joystick_type != JOYSTICK_TYPE_NONE) device_add(&gameport_device); /* FIXME: make sure this is correct?? */ diff --git a/src/machine/m_ps1.c b/src/machine/m_ps1.c index 30a610b8b..9ff547d45 100644 --- a/src/machine/m_ps1.c +++ b/src/machine/m_ps1.c @@ -525,7 +525,7 @@ ps1_common_init(const machine_t *model) device_add(&keyboard_ps2_ps1_device); /* Audio uses ports 200h and 202-207h, so only initialize gameport on 201h. */ - if (joystick_type != 7) + if (joystick_type != JOYSTICK_TYPE_NONE) device_add(&gameport_201_device); } diff --git a/src/machine/m_tandy.c b/src/machine/m_tandy.c index 4a578d3b6..bbcf7786c 100644 --- a/src/machine/m_tandy.c +++ b/src/machine/m_tandy.c @@ -1527,7 +1527,7 @@ machine_tandy1k_init(const machine_t *model, int type) device_add(&eep_1000sl2_device); } - if (joystick_type != 7) + if (joystick_type != JOYSTICK_TYPE_NONE) device_add(&gameport_device); eep_data_out = 0x0000; diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index 0366517d1..c3bf07897 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -26,7 +26,7 @@ machine_xt_common_init(const machine_t *model) device_add(&fdc_xt_device); nmi_init(); - if (joystick_type != 7) + if (joystick_type != JOYSTICK_TYPE_NONE) device_add(&gameport_device); } diff --git a/src/machine/m_xt_compaq.c b/src/machine/m_xt_compaq.c index 6af9079fa..1e312fe10 100644 --- a/src/machine/m_xt_compaq.c +++ b/src/machine/m_xt_compaq.c @@ -55,7 +55,7 @@ machine_xt_compaq_init(const machine_t *model) device_add(&keyboard_xt_compaq_device); device_add(&fdc_xt_device); nmi_init(); - if (joystick_type != 7) + if (joystick_type != JOYSTICK_TYPE_NONE) device_add(&gameport_device); lpt1_remove(); diff --git a/src/machine/m_xt_laserxt.c b/src/machine/m_xt_laserxt.c index 0b06a238b..f8408952e 100644 --- a/src/machine/m_xt_laserxt.c +++ b/src/machine/m_xt_laserxt.c @@ -171,7 +171,7 @@ machine_xt_lxt3_init(const machine_t *model) device_add(&keyboard_xt_lxt3_device); device_add(&fdc_xt_device); nmi_init(); - if (joystick_type != 7) + if (joystick_type != JOYSTICK_TYPE_NONE) device_add(&gameport_device); laserxt_init(1); diff --git a/src/machine/m_xt_xi8088.c b/src/machine/m_xt_xi8088.c index 101e8a0ae..bd832e96c 100644 --- a/src/machine/m_xt_xi8088.c +++ b/src/machine/m_xt_xi8088.c @@ -175,7 +175,7 @@ machine_xt_xi8088_init(const machine_t *model) nmi_init(); device_add(&ibmat_nvr_device); pic2_init(); - if (joystick_type != 7) + if (joystick_type != JOYSTICK_TYPE_NONE) device_add(&gameport_device); return ret; diff --git a/src/pc.c b/src/pc.c index e2bb17f1a..c1218ac7a 100644 --- a/src/pc.c +++ b/src/pc.c @@ -767,7 +767,7 @@ pc_reset_hard_init(void) /* Reset and reconfigure the Network Card layer. */ network_reset(); - if (joystick_type != 7) + if (joystick_type != JOYSTICK_TYPE_NONE) gameport_update_joystick_type(); ui_sb_update_panes(); diff --git a/src/win/win_joystick.cpp b/src/win/win_joystick.cpp index d073cd37c..499f19903 100644 --- a/src/win/win_joystick.cpp +++ b/src/win/win_joystick.cpp @@ -82,37 +82,54 @@ BOOL CALLBACK DIEnumDeviceObjectsCallback( plat_joystick_t *state = (plat_joystick_t *)pvRef; if (lpddoi->guidType == GUID_XAxis || lpddoi->guidType == GUID_YAxis || lpddoi->guidType == GUID_ZAxis || - lpddoi->guidType == GUID_RxAxis || lpddoi->guidType == GUID_RyAxis || lpddoi->guidType == GUID_RzAxis || - lpddoi->guidType == GUID_Slider) + lpddoi->guidType == GUID_RxAxis || lpddoi->guidType == GUID_RyAxis || lpddoi->guidType == GUID_RzAxis) { - memcpy(state->axis[state->nr_axes].name, lpddoi->tszName, strlen(lpddoi->tszName) + 1); - joystick_log("Axis %i : %s %x %x\n", state->nr_axes, state->axis[state->nr_axes].name, lpddoi->dwOfs, lpddoi->dwType); - if (lpddoi->guidType == GUID_XAxis) - state->axis[state->nr_axes].id = 0; - else if (lpddoi->guidType == GUID_YAxis) - state->axis[state->nr_axes].id = 1; - else if (lpddoi->guidType == GUID_ZAxis) - state->axis[state->nr_axes].id = 2; - else if (lpddoi->guidType == GUID_RxAxis) - state->axis[state->nr_axes].id = 3; - else if (lpddoi->guidType == GUID_RyAxis) - state->axis[state->nr_axes].id = 4; - else if (lpddoi->guidType == GUID_RzAxis) - state->axis[state->nr_axes].id = 5; - state->nr_axes++; + if (state->nr_axes < 8) + {memcpy(state->axis[state->nr_axes].name, lpddoi->tszName, strlen(lpddoi->tszName) + 1); + joystick_log("Axis %i : %s %x %x\n", state->nr_axes, state->axis[state->nr_axes].name, lpddoi->dwOfs, lpddoi->dwType); + if (lpddoi->guidType == GUID_XAxis) + state->axis[state->nr_axes].id = 0; + else if (lpddoi->guidType == GUID_YAxis) + state->axis[state->nr_axes].id = 1; + else if (lpddoi->guidType == GUID_ZAxis) + state->axis[state->nr_axes].id = 2; + else if (lpddoi->guidType == GUID_RxAxis) + state->axis[state->nr_axes].id = 3; + else if (lpddoi->guidType == GUID_RyAxis) + state->axis[state->nr_axes].id = 4; + else if (lpddoi->guidType == GUID_RzAxis) + state->axis[state->nr_axes].id = 5; + state->nr_axes++; + } } else if (lpddoi->guidType == GUID_Button) { - memcpy(state->button[state->nr_buttons].name, lpddoi->tszName, strlen(lpddoi->tszName) + 1); - joystick_log("Button %i : %s %x %x\n", state->nr_buttons, state->button[state->nr_buttons].name, lpddoi->dwOfs, lpddoi->dwType); - state->nr_buttons++; + if (state->nr_buttons < 32) + { + memcpy(state->button[state->nr_buttons].name, lpddoi->tszName, strlen(lpddoi->tszName) + 1); + joystick_log("Button %i : %s %x %x\n", state->nr_buttons, state->button[state->nr_buttons].name, lpddoi->dwOfs, lpddoi->dwType); + state->nr_buttons++; + } } else if (lpddoi->guidType == GUID_POV) { - memcpy(state->pov[state->nr_povs].name, lpddoi->tszName, strlen(lpddoi->tszName) + 1); - joystick_log("POV %i : %s %x %x\n", state->nr_povs, state->pov[state->nr_povs].name, lpddoi->dwOfs, lpddoi->dwType); - state->nr_povs++; - } + if (state->nr_povs < 4) + { + memcpy(state->pov[state->nr_povs].name, lpddoi->tszName, strlen(lpddoi->tszName) + 1); + joystick_log("POV %i : %s %x %x\n", state->nr_povs, state->pov[state->nr_povs].name, lpddoi->dwOfs, lpddoi->dwType); + state->nr_povs++; + } + } + else if (lpddoi->guidType == GUID_Slider) + { + if (state->nr_sliders < 2) + { + memcpy(state->slider[state->nr_sliders].name, lpddoi->tszName, strlen(lpddoi->tszName) + 1); + state->slider[state->nr_sliders].id = state->nr_sliders | SLIDER; + joystick_log("Slider %i : %s %x %x\n", state->nr_sliders, state->slider[state->nr_sliders].name, lpddoi->dwOfs, lpddoi->dwType); + state->nr_sliders++; + } + } return DIENUM_CONTINUE; } @@ -187,7 +204,11 @@ void joystick_init() lpdi_joystick[c]->SetProperty(DIPROP_RANGE, &joy_axis_range.diph); joy_axis_range.diph.dwObj = DIJOFS_RZ; lpdi_joystick[c]->SetProperty(DIPROP_RANGE, &joy_axis_range.diph); - + joy_axis_range.diph.dwObj = DIJOFS_SLIDER(0); + lpdi_joystick[c]->SetProperty(DIPROP_RANGE, &joy_axis_range.diph); + joy_axis_range.diph.dwObj = DIJOFS_SLIDER(1); + lpdi_joystick[c]->SetProperty(DIPROP_RANGE, &joy_axis_range.diph); + if (FAILED(lpdi_joystick[c]->Acquire())) fatal("joystick_init : Acquire failed\n"); } @@ -226,6 +247,10 @@ static int joystick_get_axis(int joystick_nr, int mapping) return 0; else return -cos((2*M_PI * (double)pov) / 36000.0) * 32767; + } + else if (mapping & SLIDER) + { + return plat_joystick_state[joystick_nr].s[mapping & 3]; } else return plat_joystick_state[joystick_nr].a[plat_joystick_state[joystick_nr].axis[mapping].id]; @@ -235,7 +260,7 @@ void joystick_process(void) { int c, d; - if (joystick_type == 7) return; + if (joystick_type == JOYSTICK_TYPE_NONE) return; for (c = 0; c < joysticks_present; c++) { @@ -260,6 +285,8 @@ void joystick_process(void) plat_joystick_state[c].a[3] = joystate.lRx; plat_joystick_state[c].a[4] = joystate.lRy; plat_joystick_state[c].a[5] = joystate.lRz; + plat_joystick_state[c].s[0] = joystate.rglSlider[0]; + plat_joystick_state[c].s[1] = joystate.rglSlider[1]; for (b = 0; b < 16; b++) plat_joystick_state[c].b[b] = joystate.rgbButtons[b] & 0x80; diff --git a/src/win/win_joystick_xinput.cpp b/src/win/win_joystick_xinput.cpp index 6be292c13..237cab23c 100644 --- a/src/win/win_joystick_xinput.cpp +++ b/src/win/win_joystick_xinput.cpp @@ -216,7 +216,7 @@ void joystick_process(void) { int c, d; - if (joystick_type == 7) return; + if (joystick_type == JOYSTICK_TYPE_NONE) return; joystick_poll(); diff --git a/src/win/win_jsconf.c b/src/win/win_jsconf.c index 1ca6f5ef8..0d7474f59 100644 --- a/src/win/win_jsconf.c +++ b/src/win/win_jsconf.c @@ -58,6 +58,10 @@ static void rebuild_axis_button_selections(HWND hdlg) SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)s); sprintf(s, "%s (Y axis)", plat_joystick_state[joystick-1].pov[d].name); SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)s); + } + for (d = 0; d < plat_joystick_state[joystick - 1].nr_sliders; d++) + { + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)plat_joystick_state[joystick - 1].slider[d].name); } SendMessage(h, CB_SETCURSEL, sel, 0); EnableWindow(h, TRUE); @@ -122,15 +126,23 @@ static int get_axis(HWND hdlg, int id) HWND h = GetDlgItem(hdlg, id); int axis_sel = SendMessage(h, CB_GETCURSEL, 0, 0); int nr_axes = plat_joystick_state[joystick_state[joystick_nr].plat_joystick_nr-1].nr_axes; - + int nr_povs = plat_joystick_state[joystick_state[joystick_nr].plat_joystick_nr - 1].nr_povs; + int nr_sliders = plat_joystick_state[joystick_state[joystick_nr].plat_joystick_nr - 1].nr_sliders; + if (axis_sel < nr_axes) return axis_sel; axis_sel -= nr_axes; - if (axis_sel & 1) - return POV_Y | (axis_sel >> 1); - else - return POV_X | (axis_sel >> 1); + if (axis_sel < nr_povs * 2) + { + if (axis_sel & 1) + return POV_Y | (axis_sel >> 1); + else + return POV_X | (axis_sel >> 1); + } + axis_sel -= nr_povs; + + return SLIDER | (axis_sel >> 1); } static int get_pov(HWND hdlg, int id) @@ -163,6 +175,7 @@ joystickconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) int joystick; int nr_axes; int nr_povs; + int nr_sliders; int mapping; switch (message) @@ -186,6 +199,8 @@ joystickconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { nr_axes = plat_joystick_state[joystick-1].nr_axes; nr_povs = plat_joystick_state[joystick-1].nr_povs; + nr_sliders = plat_joystick_state[joystick - 1].nr_sliders; + for (c = 0; c < joystick_get_axis_count(joystick_config_type); c++) { int mapping = joystick_state[joystick_nr].axis_mapping[c]; @@ -195,7 +210,9 @@ joystickconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) SendMessage(h, CB_SETCURSEL, nr_axes + (mapping & 3)*2, 0); else if (mapping & POV_Y) SendMessage(h, CB_SETCURSEL, nr_axes + (mapping & 3)*2 + 1, 0); - else + else if (mapping & SLIDER) + SendMessage(h, CB_SETCURSEL, nr_axes + nr_povs * 2 + (mapping & 3), 0); + else SendMessage(h, CB_SETCURSEL, mapping, 0); id += 2; } diff --git a/src/win/win_settings.c b/src/win/win_settings.c index f72ee200d..69f054acd 100644 --- a/src/win/win_settings.c +++ b/src/win/win_settings.c @@ -971,6 +971,7 @@ static BOOL CALLBACK win_settings_input_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { wchar_t str[128]; + char *joy_name; HWND h; int c, d; @@ -1000,9 +1001,15 @@ win_settings_input_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) h = GetDlgItem(hdlg, IDC_COMBO_JOYSTICK); c = 0; - while (joystick_get_name(c)) { - SendMessage(h, CB_ADDSTRING, 0, win_get_string(2105 + c)); + joy_name = joystick_get_name(c); + while (joy_name) + { + mbstowcs(str, joy_name, strlen(joy_name) + 1); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)str); + + // SendMessage(h, CB_ADDSTRING, 0, win_get_string(2105 + c)); c++; + joy_name = joystick_get_name(c); } EnableWindow(h, TRUE); SendMessage(h, CB_SETCURSEL, temp_joystick, 0); From 2d02d941f868fd8206154d95a9400533a461b852 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 17 Jan 2020 03:02:12 +0100 Subject: [PATCH 165/177] Fixed for DVD-related stuff, DVD images should now be better readable on 86Box. --- src/cdrom/cdrom_image.c | 12 ++++---- src/cdrom/cdrom_image_backend.c | 32 ++++++++++++++++++++- src/cdrom/cdrom_image_backend.h | 12 ++++---- src/scsi/scsi_cdrom.c | 51 ++++++++++++++++++--------------- 4 files changed, 71 insertions(+), 36 deletions(-) diff --git a/src/cdrom/cdrom_image.c b/src/cdrom/cdrom_image.c index 0b803eef0..84dff1f98 100644 --- a/src/cdrom/cdrom_image.c +++ b/src/cdrom/cdrom_image.c @@ -21,6 +21,7 @@ #define __USE_LARGEFILE64 #define _LARGEFILE_SOURCE #define _LARGEFILE64_SOURCE +#include #include #include #include @@ -113,18 +114,15 @@ image_get_capacity(cdrom_t *dev) int first_track, last_track; int number, c; unsigned char attr; - TMSF tmsf; - uint32_t lb = 0; - uint32_t address; + uint32_t address = 0, lb = 0; if (!img) return 0; - cdi_get_audio_tracks(img, &first_track, &last_track, &tmsf); + cdi_get_audio_tracks_lba(img, &first_track, &last_track, &lb); for (c = 0; c <= last_track; c++) { - cdi_get_audio_track_info(img, 0, c + 1, &number, &tmsf, &attr); - address = MSFtoLBA(tmsf.min, tmsf.sec, tmsf.fr) - 150; /* Do the - 150 here as well. */ + cdi_get_audio_track_info_lba(img, 0, c + 1, &number, &address, &attr); if (address > lb) lb = address; } @@ -280,7 +278,7 @@ cdrom_image_open(cdrom_t *dev, const wchar_t *fn) dev->seek_pos = 0; dev->cd_buflen = 0; dev->cdrom_capacity = image_get_capacity(dev); - cdrom_image_log("CD-ROM capacity: %i sectors (%i bytes)\n", dev->cdrom_capacity, dev->cdrom_capacity << 11); + cdrom_image_log("CD-ROM capacity: %i sectors (%" PRIi64 " bytes)\n", dev->cdrom_capacity, ((uint64_t) dev->cdrom_capacity) << 11ULL); /* Attach this handler to the drive. */ dev->ops = &cdrom_image_ops; diff --git a/src/cdrom/cdrom_image_backend.c b/src/cdrom/cdrom_image_backend.c index cb6fd5f82..556c0e954 100644 --- a/src/cdrom/cdrom_image_backend.c +++ b/src/cdrom/cdrom_image_backend.c @@ -9,7 +9,7 @@ * CD-ROM image file handling module, translated to C from * cdrom_dosbox.cpp. * - * Version: @(#)cdrom_image_backend.c 1.0.4 2020/01/13 + * Version: @(#)cdrom_image_backend.c 1.0.5 2020/01/17 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -257,6 +257,17 @@ cdi_get_audio_tracks(cd_img_t *cdi, int *st_track, int *end, TMSF *lead_out) } +int +cdi_get_audio_tracks_lba(cd_img_t *cdi, int *st_track, int *end, uint32_t *lead_out) +{ + *st_track = 1; + *end = cdi->tracks_num - 1; + *lead_out = cdi->tracks[*end].start; + + return 1; +} + + /* This replaces both Info and EndInfo, they are specified by a variable. */ int cdi_get_audio_track_info(cd_img_t *cdi, int end, int track, int *track_num, TMSF *start, uint8_t *attr) @@ -270,6 +281,24 @@ cdi_get_audio_track_info(cd_img_t *cdi, int end, int track, int *track_num, TMSF pos = trk->start + 150; FRAMES_TO_MSF(pos, &start->min, &start->sec, &start->fr); + + *track_num = trk->track_number; + *attr = trk->attr; + + return 1; +} + + +int +cdi_get_audio_track_info_lba(cd_img_t *cdi, int end, int track, int *track_num, uint32_t *start, uint8_t *attr) +{ + track_t *trk = &cdi->tracks[track - 1]; + + if ((track < 1) || (track > cdi->tracks_num)) + return 0; + + *start = (uint32_t) trk->start; + *track_num = trk->track_number; *attr = trk->attr; @@ -556,6 +585,7 @@ cdi_load_iso(cd_img_t *cdi, const wchar_t *filename) } trk.length = trk.file->get_length(trk.file) / trk.sector_size; + cdrom_image_backend_log("ISO: Data track: length = %" PRIu64 ", sector_size = %i\n", trk.length, trk.sector_size); cdi_track_push_back(cdi, &trk); /* Lead out track. */ diff --git a/src/cdrom/cdrom_image_backend.h b/src/cdrom/cdrom_image_backend.h index b58b54d7b..69a59031c 100644 --- a/src/cdrom/cdrom_image_backend.h +++ b/src/cdrom/cdrom_image_backend.h @@ -9,15 +9,15 @@ * CD-ROM image file handling module header , translated to C * from cdrom_dosbox.h. * - * Version: @(#)cdrom_image_backend.h 1.0.1 2019/12/21 + * Version: @(#)cdrom_image_backend.h 1.0.2 2020/01/17 * * Authors: Miran Grca, * Fred N. van Kempen, * The DOSBox Team, * - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2002-2019 The DOSBox Team. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2002-2020 The DOSBox Team. */ #ifndef CDROM_IMAGE_BACKEND_H #define CDROM_IMAGE_BACKEND_H @@ -41,7 +41,7 @@ typedef struct SMSF { - uint8_t min; + uint16_t min; uint8_t sec; uint8_t fr; } TMSF; @@ -74,7 +74,9 @@ typedef struct { extern void cdi_close(cd_img_t *cdi); extern int cdi_set_device(cd_img_t *cdi, const wchar_t *path); extern int cdi_get_audio_tracks(cd_img_t *cdi, int *st_track, int *end, TMSF *lead_out); +extern int cdi_get_audio_tracks_lba(cd_img_t *cdi, int *st_track, int *end, uint32_t *lead_out); extern int cdi_get_audio_track_info(cd_img_t *cdi, int end, int track, int *track_num, TMSF *start, uint8_t *attr); +extern int cdi_get_audio_track_info_lba(cd_img_t *cdi, int end, int track, int *track_num, uint32_t *start, uint8_t *attr); extern int cdi_get_track(cd_img_t *cdi, uint32_t sector); extern int cdi_get_audio_sub(cd_img_t *cdi, uint32_t sector, uint8_t *attr, uint8_t *track, uint8_t *index, TMSF *rel_pos, TMSF *abs_pos); extern int cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector); diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index 201d597d2..2f87dac04 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -9,11 +9,11 @@ * Implementation of the CD-ROM drive with SCSI(-like) * commands, for both ATAPI and SCSI usage. * - * Version: @(#)scsi_cdrom.c 1.0.73 2019/12/13 + * Version: @(#)scsi_cdrom.c 1.0.74 2020/01/17 * * Author: Miran Grca, * - * Copyright 2016-2019 Miran Grca. + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -1080,29 +1080,31 @@ scsi_cdrom_read_dvd_structure(scsi_cdrom_t *dev, int format, const uint8_t *pack return 0; } - buf[4] = 1; /* DVD-ROM, part version 1 */ - buf[5] = 0xf; /* 120mm disc, minimum rate unspecified */ - buf[6] = 1; /* one layer, read-only (per MMC-2 spec) */ - buf[7] = 0; /* default densities */ + buf[4] = 18; /* Length of Layer Information */ + buf[5] = 0; + + buf[6] = 1; /* DVD-ROM, part version 1 */ + buf[7] = 0xf; /* 120mm disc, minimum rate unspecified */ + buf[8] = 1; /* one layer, read-only (per MMC-2 spec) */ + buf[9] = 0; /* default densities */ /* FIXME: 0x30000 per spec? */ - buf[8] = buf[9] = buf[10] = buf[11] = 0; /* start sector */ - buf[12] = (total_sectors >> 24) & 0xff; /* end sector */ - buf[13] = (total_sectors >> 16) & 0xff; - buf[14] = (total_sectors >> 8) & 0xff; - buf[15] = total_sectors & 0xff; + buf[10] = 0x00; + buf[11] = 0x03; + buf[12] = buf[13] = 0; /* start sector */ - buf[16] = (total_sectors >> 24) & 0xff; /* l0 end sector */ - buf[17] = (total_sectors >> 16) & 0xff; - buf[18] = (total_sectors >> 8) & 0xff; - buf[19] = total_sectors & 0xff; + buf[14] = 0x00; + buf[15] = (total_sectors >> 16) & 0xff; /* end sector */ + buf[16] = (total_sectors >> 8) & 0xff; + buf[17] = total_sectors & 0xff; - /* Size of buffer, not including 2 byte size field */ - buf[0] = ((2048 +2 ) >> 8) & 0xff; - buf[1] = (2048 + 2) & 0xff; + buf[18] = 0x00; + buf[19] = (total_sectors >> 16) & 0xff; /* l0 end sector */ + buf[20] = (total_sectors >> 8) & 0xff; + buf[21] = total_sectors & 0xff; - /* 2k data + 4 byte header */ - return (2048 + 4); + /* 20 bytes of data + 4 byte header */ + return (20 + 4); case 0x01: /* DVD copyright information */ buf[4] = 0; /* no copyright data */ @@ -1135,8 +1137,8 @@ scsi_cdrom_read_dvd_structure(scsi_cdrom_t *dev, int format, const uint8_t *pack buf[4] = 0x00; /* Physical format */ buf[5] = 0x40; /* Not writable, is readable */ - buf[6] = ((2048 + 4) >> 8) & 0xff; - buf[7] = (2048 + 4) & 0xff; + buf[6] = ((20 + 4) >> 8) & 0xff; + buf[7] = (20 + 4) & 0xff; buf[8] = 0x01; /* Copyright info */ buf[9] = 0x40; /* Not writable, is readable */ @@ -2130,7 +2132,10 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) if ((cdb[7] <= 0x7f) || (cdb[7] == 0xff)) { if (cdb[1] == 0) { ret = scsi_cdrom_read_dvd_structure(dev, format, cdb, dev->buffer); - if (ret) { + dev->buffer[0] = (ret >> 8); + dev->buffer[1] = (ret & 0xff); + dev->buffer[2] = dev->buffer[3] = 0x00; + if (ret) { scsi_cdrom_set_buf_len(dev, BufLen, &alloc_length); scsi_cdrom_data_command_finish(dev, alloc_length, alloc_length, alloc_length, 0); From 2b890e290cdba1c0622edda884632a0dc2170451 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 17 Jan 2020 03:56:05 +0100 Subject: [PATCH 166/177] Removed K6_2 stuff from cpu/cpu.c. --- src/cpu/cpu.c | 72 +-------------------------------------------------- 1 file changed, 1 insertion(+), 71 deletions(-) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 23289d056..22cbd78a2 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -191,9 +191,7 @@ uint64_t ecx570_msr = 0; #if defined(DEV_BRANCH) && defined(USE_AMD_K) uint64_t ecx83_msr = 0; /* AMD K5 and K6 MSR's. */ -uint64_t star = 0; /* AMD K6-2+. */ - -uint64_t amd_efer = 0, amd_whcr = 0; /* AMD K6-2+ registers. */ +uint64_t amd_efer = 0, amd_whcr = 0; #endif int timing_rr; @@ -1812,10 +1810,6 @@ void cpu_ven_reset(void) case CPU_K6: amd_efer = amd_whcr = 0ULL; break; - case CPU_K6_2: - amd_efer = amd_whcr = 0ULL; - star = 0ULL; - break; } #endif } @@ -1885,39 +1879,6 @@ void cpu_RDMSR() break; } break; - - case CPU_K6_2: - EAX = EDX = 0; - switch (ECX) - { - case 0x0000000e: - EAX = msr.tr12; - break; - case 0x00000010: - EAX = tsc & 0xffffffff; - EDX = tsc >> 32; - break; - case 0x00000083: - EAX = ecx83_msr & 0xffffffff; - EDX = ecx83_msr >> 32; - break; - case 0xC0000080: - EAX = amd_efer & 0xffffffff; - EDX = amd_efer >> 32; - break; - case 0xC0000081: - EAX = star & 0xffffffff; - EDX = star >> 32; - break; - case 0xC0000082: - EAX = amd_whcr & 0xffffffff; - EDX = amd_whcr >> 32; - break; - default: - x86gpf(NULL, 0); - break; - } - break; #endif case CPU_PENTIUM: @@ -2149,37 +2110,6 @@ void cpu_WRMSR() break; } break; - - case CPU_K6_2: - switch (ECX) - { - case 0x0e: - msr.tr12 = EAX & 0x228; - break; - case 0x10: - tsc = EAX | ((uint64_t)EDX << 32); - break; - case 0x83: - ecx83_msr = EAX | ((uint64_t)EDX << 32); - break; - case 0xC0000080: - temp = EAX | ((uint64_t)EDX << 32); - if (temp & ~1ULL) - x86gpf(NULL, 0); - else - amd_efer = temp; - break; - case 0xC0000081: - star = EAX | ((uint64_t)EDX << 32); - break; - case 0xC0000082: - amd_whcr = EAX | ((uint64_t)EDX << 32); - break; - default: - x86gpf(NULL, 0); - break; - } - break; #endif case CPU_PENTIUM: From 6678ac1c83173e96c9cfd87689b99eb09d0237d5 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 17 Jan 2020 04:00:46 +0100 Subject: [PATCH 167/177] Fixed an undeclared variable. --- src/cpu/cpu.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 22cbd78a2..599c90e6e 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -2039,6 +2039,10 @@ i686_invalid_rdmsr: void cpu_WRMSR() { +#if defined(DEV_BRANCH) && defined(USE_AMD_K) + uint64_t temp; +#endif + switch (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type) { case CPU_WINCHIP: From 124347b72a9f41e121514cba1034d714e1515e5f Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 17 Jan 2020 04:06:03 +0100 Subject: [PATCH 168/177] Removed some stuff, hopefully the K6 with the old recompiler can compile now. --- src/cpu/386_ops.h | 96 --------------------- src/cpu/x86_ops.h | 8 -- src/cpu/x86_ops_amd.h | 192 ------------------------------------------ 3 files changed, 296 deletions(-) delete mode 100644 src/cpu/x86_ops_amd.h diff --git a/src/cpu/386_ops.h b/src/cpu/386_ops.h index fa2ed4d83..c66b3d0b4 100644 --- a/src/cpu/386_ops.h +++ b/src/cpu/386_ops.h @@ -185,9 +185,6 @@ extern void x386_dynarec_log(const char *fmt, ...); #endif #include "x86seg.h" -#if defined(DEV_BRANCH) && defined(USE_AMD_K) -# include "x86_ops_amd.h" -#endif #include "x86_ops_arith.h" #include "x86_ops_atomic.h" #include "x86_ops_bcd.h" @@ -817,99 +814,6 @@ const OpFn OP_TABLE(pentiummmx_0f)[1024] = /*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL, }; -#if defined(DEV_BRANCH) && defined(USE_AMD_K) -const OpFn OP_TABLE(k6_0f)[1024] = -{ - /*16-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, opSYSCALL, opCLTS, opSYSRET, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16, -/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a16,opMOVQ_mm_q_a16, - -/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, -/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, -/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, - -/*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, opPSRLW_a16, opPSRLD_a16, opPSRLQ_a16, ILLEGAL, opPMULLW_a16, ILLEGAL, ILLEGAL, opPSUBUSB_a16, opPSUBUSW_a16, NULL, opPAND_a16, opPADDUSB_a16, opPADDUSW_a16, NULL, opPANDN_a16, -/*e0*/ ILLEGAL, opPSRAW_a16, opPSRAD_a16, ILLEGAL, ILLEGAL, opPMULHW_a16, ILLEGAL, ILLEGAL, opPSUBSB_a16, opPSUBSW_a16, NULL, opPOR_a16, opPADDSB_a16, opPADDSW_a16, NULL, opPXOR_a16, -/*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL, - - /*32-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, opSYSCALL, opCLTS, opSYSRET, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16, -/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a16,opMOVQ_mm_q_a16, - -/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, -/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, -/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, - -/*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, opPSRLW_a16, opPSRLD_a16, opPSRLQ_a16, ILLEGAL, opPMULLW_a16, ILLEGAL, ILLEGAL, opPSUBUSB_a16, opPSUBUSW_a16, NULL, opPAND_a16, opPADDUSB_a16, opPADDUSW_a16, NULL, opPANDN_a16, -/*e0*/ ILLEGAL, opPSRAW_a16, opPSRAD_a16, ILLEGAL, ILLEGAL, opPMULHW_a16, ILLEGAL, ILLEGAL, opPSUBSB_a16, opPSUBSW_a16, NULL, opPOR_a16, opPADDSB_a16, opPADDSW_a16, NULL, opPXOR_a16, -/*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL, - - /*16-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, opSYSCALL, opCLTS, opSYSRET, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ opPUNPCKLBW_a32,opPUNPCKLWD_a32,opPUNPCKLDQ_a32,opPACKSSWB_a32, opPCMPGTB_a32, opPCMPGTW_a32, opPCMPGTD_a32, opPACKUSWB_a32, opPUNPCKHBW_a32,opPUNPCKHWD_a32,opPUNPCKHDQ_a32,opPACKSSDW_a32, ILLEGAL, ILLEGAL, opMOVD_l_mm_a32,opMOVQ_q_mm_a32, -/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a32,opMOVQ_mm_q_a32, - -/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, -/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, -/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, - -/*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32, -/*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32, -/*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL, - - /*32-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, opSYSCALL, opCLTS, opSYSRET, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ opPUNPCKLBW_a32,opPUNPCKLWD_a32,opPUNPCKLDQ_a32,opPACKSSWB_a32, opPCMPGTB_a32, opPCMPGTW_a32, opPCMPGTD_a32, opPACKUSWB_a32, opPUNPCKHBW_a32,opPUNPCKHWD_a32,opPUNPCKHDQ_a32,opPACKSSDW_a32, ILLEGAL, ILLEGAL, opMOVD_l_mm_a32,opMOVQ_q_mm_a32, -/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a32,opMOVQ_mm_q_a32, - -/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, -/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, -/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, - -/*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32, -/*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32, -/*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL, -}; -#endif - #if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) const OpFn OP_TABLE(c6x86mx_0f)[1024] = { diff --git a/src/cpu/x86_ops.h b/src/cpu/x86_ops.h index 12a7e96bc..2c4a2f3e5 100644 --- a/src/cpu/x86_ops.h +++ b/src/cpu/x86_ops.h @@ -87,10 +87,6 @@ extern const OpFn dynarec_ops_pentiummmx_0f[1024]; extern const OpFn dynarec_ops_c6x86mx_0f[1024]; #endif -#if defined(DEV_BRANCH) && defined(USE_AMD_K) -extern const OpFn dynarec_ops_k6_0f[1024]; -#endif - #if defined(DEV_BRANCH) && defined(USE_I686) extern const OpFn dynarec_ops_pentiumpro_0f[1024]; extern const OpFn dynarec_ops_pentium2d_0f[1024]; @@ -181,10 +177,6 @@ extern const OpFn ops_pentiummmx_0f[1024]; extern const OpFn ops_c6x86mx_0f[1024]; #endif -#if defined(DEV_BRANCH) && defined(USE_AMD_K) -extern const OpFn ops_k6_0f[1024]; -#endif - #if defined(DEV_BRANCH) && defined(USE_I686) extern const OpFn ops_pentiumpro_0f[1024]; extern const OpFn ops_pentium2d_0f[1024]; diff --git a/src/cpu/x86_ops_amd.h b/src/cpu/x86_ops_amd.h deleted file mode 100644 index 8f003e1fb..000000000 --- a/src/cpu/x86_ops_amd.h +++ /dev/null @@ -1,192 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * AMD SYSCALL and SYSRET CPU Instructions. - * - * Version: @(#)x86_ops_amd.h 1.0.4 2018/10/17 - * - * Author: Miran Grca, - * Copyright 2016-2018 Miran Grca. - */ - -/* 0 = Limit 0-15 - 1 = Base 0-15 - 2 = Base 16-23 (bits 0-7), Access rights - 8-11 Type - 12 S - 13, 14 DPL - 15 P - 3 = Limit 16-19 (bits 0-3), Base 24-31 (bits 8-15), granularity, etc. - 4 A - 6 DB - 7 G */ - -#define AMD_SYSCALL_EIP (star & 0xFFFFFFFF) -#define AMD_SYSCALL_SB ((star >> 32) & 0xFFFF) -#define AMD_SYSRET_SB ((star >> 48) & 0xFFFF) - -/* 0F 05 */ -static int opSYSCALL(uint32_t fetchdat) -{ - uint16_t syscall_cs_seg_data[4] = {0, 0, 0, 0}; - uint16_t syscall_ss_seg_data[4] = {0, 0, 0, 0}; - - if (!(cr0 & 1)) return internal_illegal("SYSCALL: CPU not in protected mode"); - if (!AMD_SYSCALL_SB) return internal_illegal("SYSCALL: AMD SYSCALL SB MSR is zero"); - - /* Set VM, IF, RF to 0. */ - /* cpu_state.eflags &= ~0x00030200; - cpu_state.flags &= ~0x0200; */ - - /* Let's do this by the AMD spec. */ - ECX = cpu_state.pc; - - cpu_state.eflags &= ~0x0002; - cpu_state.flags &= ~0x0200; - - /* CS */ - cpu_state.seg_cs.seg = AMD_SYSCALL_SB & ~7; - if (AMD_SYSCALL_SB & 4) - { - if (cpu_state.seg_cs.seg >= ldt.limit) - { - x386_dynarec_log("Bigger than LDT limit %04X %04X CS\n",AMD_SYSCALL_SB,ldt.limit); - x86gpf(NULL, AMD_SYSCALL_SB & ~3); - return 1; - } - cpu_state.seg_cs.seg +=ldt.base; - } - else - { - if (cpu_state.seg_cs.seg >= gdt.limit) - { - x386_dynarec_log("Bigger than GDT limit %04X %04X CS\n",AMD_SYSCALL_SB,gdt.limit); - x86gpf(NULL, AMD_SYSCALL_SB & ~3); - return 1; - } - cpu_state.seg_cs.seg += gdt.base; - } - cpl_override = 1; - - syscall_cs_seg_data[0] = 0xFFFF; - syscall_cs_seg_data[1] = 0; - syscall_cs_seg_data[2] = 0x9B00; - syscall_cs_seg_data[3] = 0xC0; - - cpl_override = 0; - - use32 = 0x300; - CS = (AMD_SYSCALL_SB & ~3) | 0; - - do_seg_load(&cpu_state.seg_cs, syscall_cs_seg_data); - use32 = 0x300; - - CS = (CS & 0xFFFC) | 0; - - cpu_state.seg_cs.limit = 0xFFFFFFFF; - cpu_state.seg_cs.limit_high = 0xFFFFFFFF; - - /* SS */ - syscall_ss_seg_data[0] = 0xFFFF; - syscall_ss_seg_data[1] = 0; - syscall_ss_seg_data[2] = 0x9300; - syscall_ss_seg_data[3] = 0xC0; - do_seg_load(&cpu_state.seg_ss, syscall_ss_seg_data); - cpu_state.seg_ss.seg = (AMD_SYSCALL_SB + 8) & 0xFFFC; - stack32 = 1; - - cpu_state.seg_ss.limit = 0xFFFFFFFF; - cpu_state.seg_ss.limit_high = 0xFFFFFFFF; - - cpu_state.seg_ss.checked = 0; - - cpu_state.pc = AMD_SYSCALL_EIP; - - CLOCK_CYCLES(20); - - CPU_BLOCK_END(); - - return 0; -} - -/* 0F 07 */ -static int opSYSRET(uint32_t fetchdat) -{ - uint16_t sysret_cs_seg_data[4] = {0, 0, 0, 0}; - uint16_t sysret_ss_seg_data[4] = {0, 0, 0, 0}; - - if (!AMD_SYSRET_SB) return internal_illegal("SYSRET: CS MSR is zero"); - if (!(cr0 & 1)) return internal_illegal("SYSRET: CPU not in protected mode"); - - cpu_state.pc = ECX; - - cpu_state.eflags |= (1 << 1); - - /* CS */ - cpu_state.seg_cs.seg = AMD_SYSRET_SB & ~7; - if (AMD_SYSRET_SB & 4) - { - if (cpu_state.seg_cs.seg >= ldt.limit) - { - x386_dynarec_log("Bigger than LDT limit %04X %04X CS\n",AMD_SYSRET_SB,ldt.limit); - x86gpf(NULL, AMD_SYSRET_SB & ~3); - return 1; - } - cpu_state.seg_cs.seg +=ldt.base; - } - else - { - if (cpu_state.seg_cs.seg >= gdt.limit) - { - x386_dynarec_log("Bigger than GDT limit %04X %04X CS\n",AMD_SYSRET_SB,gdt.limit); - x86gpf(NULL, AMD_SYSRET_SB & ~3); - return 1; - } - cpu_state.seg_cs.seg += gdt.base; - } - cpl_override = 1; - - sysret_cs_seg_data[0] = 0xFFFF; - sysret_cs_seg_data[1] = 0; - sysret_cs_seg_data[2] = 0xFB00; - sysret_cs_seg_data[3] = 0xC0; - - cpl_override = 0; - - use32 = 0x300; - CS = (AMD_SYSRET_SB & ~3) | 3; - - do_seg_load(&cpu_state.seg_cs, sysret_cs_seg_data); - flushmmucache_cr3(); - use32 = 0x300; - - CS = (CS & 0xFFFC) | 3; - - cpu_state.seg_cs.limit = 0xFFFFFFFF; - cpu_state.seg_cs.limit_high = 0xFFFFFFFF; - - /* SS */ - sysret_ss_seg_data[0] = 0xFFFF; - sysret_ss_seg_data[1] = 0; - sysret_ss_seg_data[2] = 0xF300; - sysret_ss_seg_data[3] = 0xC0; - do_seg_load(&cpu_state.seg_ss, sysret_ss_seg_data); - cpu_state.seg_ss.seg = ((AMD_SYSRET_SB + 8) & 0xFFFC) | 3; - stack32 = 1; - - cpu_state.seg_ss.limit = 0xFFFFFFFF; - cpu_state.seg_ss.limit_high = 0xFFFFFFFF; - - cpu_state.seg_ss.checked = 0; - - CLOCK_CYCLES(20); - - CPU_BLOCK_END(); - - return 0; -} From 7bef50b782307cd0005eda920c249a2890328b60 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 17 Jan 2020 05:44:38 +0100 Subject: [PATCH 169/177] Fixed a mess in win.c that was causing a corruption of the command lime parameters array. --- src/win/win.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/win/win.c b/src/win/win.c index 7fc83249b..cfbdab264 100644 --- a/src/win/win.c +++ b/src/win/win.c @@ -73,6 +73,7 @@ static rc_str_t *lpRCstr2048, *lpRCstr6144, *lpRCstr7168; static int vid_api_inited = 0; +static wchar_t *argbuf; static const struct { @@ -280,7 +281,6 @@ static int ProcessCommandLine(wchar_t ***argw) { WCHAR *cmdline; - wchar_t *argbuf; wchar_t **args; int argc_max; int i, q, argc; @@ -336,8 +336,6 @@ ProcessCommandLine(wchar_t ***argw) args[argc] = NULL; *argw = args; - free(argbuf); - return(argc); } @@ -383,6 +381,7 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszArg, int nCmdShow) if (source_hwnd) PostMessage((HWND) (uintptr_t) source_hwnd, WM_HAS_SHUTDOWN, (WPARAM) 0, (LPARAM) hwndMain); + free(argbuf); free(argw); return(1); } @@ -394,6 +393,7 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszArg, int nCmdShow) /* Handle our GUI. */ i = ui_init(nCmdShow); + free(argbuf); free(argw); return(i); } From 0f7699d0370df22af68435fff3e221aff7cec783 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 17 Jan 2020 06:36:15 +0100 Subject: [PATCH 170/177] Split PIT timer from the counter CLOCK input handling, exposed a function to set a counter's CLOCK input, and implemented BCD mode. --- src/pit.c | 133 ++++++++++++++++++++++++++++++++++++++---------------- src/pit.h | 13 ++++-- 2 files changed, 104 insertions(+), 42 deletions(-) diff --git a/src/pit.c b/src/pit.c index 3fe4fb1dd..eaab7a4e3 100644 --- a/src/pit.c +++ b/src/pit.c @@ -57,8 +57,9 @@ int io_delay = 5; int64_t firsttime = 1; -#define PIT_PS2 16 -#define PIT_EXT_IO 32 +#define PIT_PS2 16 /* The PIT is the PS/2's second PIT. */ +#define PIT_EXT_IO 32 /* The PIT has externally specified port I/O. */ +#define PIT_CUSTOM_CLOCK 64 /* The PIT uses custom clock inputs provided by another provider. */ enum { @@ -99,6 +100,55 @@ ctr_set_out(ctr_t *ctr, int out) } +static void +ctr_decrease_count(ctr_t *ctr) +{ + uint8_t units, tens, hundreds, thousands, myriads; + int dec_cnt = 1; + + if (ctr->ctrl & 0x01) { + units = ctr->count & 0x0f; + tens = (ctr->count >> 4) & 0x0f; + hundreds = (ctr->count >> 8) & 0x0f; + thousands = (ctr->count >> 12) & 0x0f; + myriads = (ctr->count >> 16) & 0x0f; + + dec_cnt -= units; + units = (10 - dec_cnt % 10) % 10; + + dec_cnt = (dec_cnt + 9) / 10; /* The +9 is so we get a carry if dec_cnt % 10 was not a 0. */ + if (dec_cnt <= tens) + tens -= dec_cnt; + else { + dec_cnt -= tens; + tens = (10 - dec_cnt % 10) % 10; + + dec_cnt = (dec_cnt + 9) / 10; + if (dec_cnt <= hundreds) + hundreds -= dec_cnt; + else { + dec_cnt -= hundreds; + hundreds = (10 - dec_cnt % 10) % 10; + + dec_cnt = (dec_cnt + 9) / 10; + if (dec_cnt <= thousands) + thousands -= dec_cnt; + else { + dec_cnt -= thousands; + thousands = (10 - dec_cnt % 10) % 10; + + dec_cnt = (dec_cnt + 9) / 10; + myriads = (10 + myriads - dec_cnt % 10) % 10; + } + } + } + + ctr->count = (myriads << 16) | (thousands << 12) | (hundreds << 8) | (tens << 4) | units; + } else + ctr->count = (ctr->count - 1) & 0xffff; +} + + static void ctr_load_count(ctr_t *ctr) { @@ -124,7 +174,7 @@ ctr_tick(ctr_t *ctr) break; case 2: if (ctr->gate && (ctr->count >= 1)) { - ctr->count--; + ctr_decrease_count(ctr); if (ctr->count < 1) { ctr->state = 3; ctr_set_out(ctr, 1); @@ -132,7 +182,7 @@ ctr_tick(ctr_t *ctr) } break; case 3: - ctr->count = (ctr->count - 1) & 0xffff; + ctr_decrease_count(ctr); break; } break; @@ -146,7 +196,7 @@ ctr_tick(ctr_t *ctr) break; case 2: if (ctr->count >= 1) { - ctr->count--; + ctr_decrease_count(ctr); if (ctr->count < 1) { ctr->state = 3; ctr_set_out(ctr, 1); @@ -154,7 +204,7 @@ ctr_tick(ctr_t *ctr) } break; case 3: - ctr->count = (ctr->count - 1) & 0xffff; + ctr_decrease_count(ctr); break; } break; @@ -171,7 +221,7 @@ ctr_tick(ctr_t *ctr) if (ctr->gate == 0) break; else if (ctr->count >= 2) { - ctr->count--; + ctr_decrease_count(ctr); if (ctr->count < 2) { ctr->state = 3; ctr_set_out(ctr, 0); @@ -221,7 +271,7 @@ ctr_tick(ctr_t *ctr) if ((ctr->gate != 0) || (ctr->m != 4)) { switch(ctr->state) { case 0: - ctr->count--; + ctr_decrease_count(ctr); break; case 1: ctr_load_count(ctr); @@ -229,7 +279,7 @@ ctr_tick(ctr_t *ctr) break; case 2: if (ctr->count >= 1) { - ctr->count--; + ctr_decrease_count(ctr); if (ctr->count < 1) { ctr->state = 3; ctr_set_out(ctr, 0); @@ -406,6 +456,38 @@ pit_ctr_set_gate(ctr_t *ctr, int gate) } +void +pit_ctr_set_clock(ctr_t *ctr, int clock) +{ + int old = ctr->clock; + + ctr->clock = clock; + + if (ctr->using_timer && ctr->latch) { + if (old && !ctr->clock) { + ctr_set_state_1(ctr); + ctr->latch = 0; + } + } else if (ctr->using_timer && !ctr->latch) { + if (ctr->state == 1) { + if (!old && ctr->clock) + ctr->s1_det = 1; /* Rising edge. */ + else if (old && !ctr->clock) { + ctr->s1_det++; /* Falling edge. */ + if (ctr->s1_det != 2) + ctr->s1_det = 0; + } + + if (ctr->s1_det == 2) { + ctr->s1_det = 0; + ctr_tick(ctr); + } + } else if (old && !ctr->clock) + ctr_tick(ctr); + } +} + + void pit_ctr_set_using_timer(ctr_t *ctr, int using_timer) { @@ -420,38 +502,11 @@ pit_timer_over(void *p) { pit_t *dev = (pit_t *) p; int i; - ctr_t *ctr; - int old; - old = dev->clock; dev->clock ^= 1; - for (i = 0; i < 3; i++) { - ctr = &dev->counters[i]; - - if (ctr->using_timer && ctr->latch) { - if (old && !dev->clock) { - ctr_set_state_1(ctr); - ctr->latch = 0; - } - } else if (ctr->using_timer && !ctr->latch) { - if (ctr->state == 1) { - if (!old && dev->clock) - ctr->s1_det = 1; /* Rising edge. */ - else if (old && !dev->clock) { - ctr->s1_det++; /* Falling edge. */ - if (ctr->s1_det != 2) - ctr->s1_det = 0; - } - - if (ctr->s1_det == 2) { - ctr->s1_det = 0; - ctr_tick(ctr); - } - } else if (old && !dev->clock) - ctr_tick(ctr); - } - } + for (i = 0; i < 3; i++) + pit_ctr_set_clock(&dev->counters[i], dev->clock); timer_advance_u64(&dev->callback_timer, PITCONST >> 1ULL); } @@ -780,7 +835,7 @@ pit_init(const device_t *info) pit_t *dev = (pit_t *) malloc(sizeof(pit_t)); pit_reset(dev); - if (!(dev->flags & PIT_PS2)) { + if (!(dev->flags & PIT_PS2) && !(dev->flags & PIT_CUSTOM_CLOCK)) { timer_add(&dev->callback_timer, pit_timer_over, (void *) dev, 0); timer_set_delay_u64(&dev->callback_timer, PITCONST >> 1ULL); } diff --git a/src/pit.h b/src/pit.h index e0a4a42ff..f019327a6 100644 --- a/src/pit.h +++ b/src/pit.h @@ -9,10 +9,10 @@ * Header of the implementation of the Intel 8253/8254 * Programmable Interval Timer. * - * Version: @(#)pit.h 1.0.0 2019/12/02 + * Version: @(#)pit.h 1.0.1 2020/01/17 * * Author: Miran Grca, - * Copyright 2019 Miran Grca. + * Copyright 2019,2020 Miran Grca. */ #ifndef EMU_PIT_H # define EMU_PIT_H @@ -27,7 +27,7 @@ typedef struct { int rm, wm, gate, out, newcount, count, using_timer, latched, - state, null_count, do_read_status, pad1; + state, null_count, do_read_status, clock; uint32_t l; @@ -60,10 +60,17 @@ extern uint64_t PITCONST, ISACONST, RTCCONST; +/* Gets a counter's count. */ extern uint16_t pit_ctr_get_count(ctr_t *ctr); +/* Sets a counter's load count handler. */ extern void pit_ctr_set_load_func(ctr_t *ctr, void (*func)(uint8_t new_m, int new_count)); +/* Sets a counter's OUT output handler. */ extern void pit_ctr_set_out_func(ctr_t *ctr, void (*func)(int new_out, int old_out)); +/* Sets a counter's GATE input. */ extern void pit_ctr_set_gate(ctr_t *ctr, int gate); +/* Sets a counter's CLOCK input. */ +extern void pit_ctr_set_clock(ctr_t *ctr, int clock); +/* Sets if a counter's CLOCK input is from the timer or not - used by PCjr. */ extern void pit_ctr_set_using_timer(ctr_t *ctr, int using_timer); extern pit_t * pit_common_init(int type, void (*out0)(int new_out, int old_out), void (*out1)(int new_out, int old_out)); From 4d7724d82d3221b6d8c8c64bfe7bda882ff849cb Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 17 Jan 2020 06:57:45 +0100 Subject: [PATCH 171/177] Implemented the VIA chipset's PIC shadow mode. --- src/pic.c | 94 ++++++++++++++++++++++++++++++--------------- src/pic.h | 7 ++-- src/via_vt82c586b.c | 5 ++- 3 files changed, 71 insertions(+), 35 deletions(-) diff --git a/src/pic.c b/src/pic.c index 60297734c..4ed1d4315 100644 --- a/src/pic.c +++ b/src/pic.c @@ -8,11 +8,11 @@ * * Implementation of the Intel PIC chip emulation. * - * Version: @(#)pic.c 1.0.5 2019/09/20 + * Version: @(#)pic.c 1.0.6 2020/01/17 * * Author: Miran Grca, * - * Copyright 2016-2018 Miran Grca. + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -30,12 +30,15 @@ #include "pit.h" -int output; -int intclear; -int keywaiting=0; -int pic_intpending; -PIC pic, pic2; -uint16_t pic_current; +int output; +int intclear; +int keywaiting = 0; +int pic_intpending; +PIC pic, pic2; +uint16_t pic_current; + + +static int shadow = 0; #ifdef ENABLE_PIC_LOG @@ -98,6 +101,13 @@ pic_reset() } +void +pic_set_shadow(int sh) +{ + shadow = sh; +} + + void pic_update_mask(uint8_t *mask, uint8_t ins) { @@ -198,6 +208,7 @@ pic_write(uint16_t addr, uint8_t val, void *priv) pic_updatepending(); } else if (!(val & 8)) { /*OCW2*/ + pic.ocw2 = val; if ((val & 0xE0) == 0x60) { pic.ins &= ~(1 << (val & 7)); pic_update_mask(&pic.mask2, pic.ins); @@ -226,6 +237,7 @@ pic_write(uint16_t addr, uint8_t val, void *priv) } } } else { /*OCW3*/ + pic.ocw3 = val; if (val & 2) pic.read=(val & 1); } @@ -236,27 +248,36 @@ pic_write(uint16_t addr, uint8_t val, void *priv) uint8_t pic_read(uint16_t addr, void *priv) { - addr &= ~0x06; + uint8_t ret = 0xff; - if (addr & 1) { - pic_log("Read PIC mask %02X\n", pic.mask); - pic_log("%04X:%04X: Read PIC mask %02X\n", CS, cpu_state.pc, pic.mask); - return pic.mask; - } - if (pic.read) { - pic_log("Read PIC ins %02X\n", pic.ins); + if ((addr == 0x20) && shadow) { + ret = ((pic.ocw3 & 0x20) >> 5) << 4; + ret |= ((pic.ocw2 & 0x80) >> 7) << 3; + ret |= ((pic.icw4 & 0x10) >> 4) << 2; + ret |= ((pic.icw4 & 0x02) >> 1) << 1; + ret |= ((pic.icw4 & 0x08) >> 3) << 0; + } else if ((addr == 0x21) && shadow) + ret = ((pic.vector & 0xf8) >> 3) << 0; + else if (addr & 1) + ret = pic.mask; + else if (pic.read) { if (AT) - return pic.ins | (pic2.ins ? 4 : 0); + ret = pic.ins | (pic2.ins ? 4 : 0); else - return pic.ins; - } - return pic.pend; + ret = pic.ins; + } else + ret = pic.pend; + + pic_log("%04X:%04X: Read PIC 1 port %04X, value %02X\n", CS, cpu_state.pc, addr, val); + + return ret; } void pic_init() { + shadow = 0; io_sethandler(0x0020, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, NULL); } @@ -264,6 +285,7 @@ pic_init() void pic_init_pcjr() { + shadow = 0; io_sethandler(0x0020, 0x0008, pic_read, NULL, NULL, pic_write, NULL, NULL, NULL); } @@ -323,6 +345,7 @@ pic2_write(uint16_t addr, uint8_t val, void *priv) pic.pend &= ~4; pic_updatepending(); } else if (!(val & 8)) { /*OCW2*/ + pic2.ocw2 = val; if ((val & 0xE0) == 0x60) { pic2.ins &= ~(1 << (val & 7)); pic_update_mask(&pic2.mask2, pic2.ins); @@ -339,6 +362,7 @@ pic2_write(uint16_t addr, uint8_t val, void *priv) } } } else { /*OCW3*/ + pic2.ocw3 = val; if (val & 2) pic2.read=(val & 1); } @@ -349,16 +373,26 @@ pic2_write(uint16_t addr, uint8_t val, void *priv) uint8_t pic2_read(uint16_t addr, void *priv) { - if (addr&1) { - pic_log("Read PIC2 mask %02X\n", pic2.mask); - return pic2.mask; - } - if (pic2.read) { - pic_log("Read PIC2 ins %02X\n", pic2.ins); - return pic2.ins; - } - pic_log("Read PIC2 pend %02X\n", pic2.pend); - return pic2.pend; + uint8_t ret = 0xff; + + if ((addr == 0x20) && shadow) { + ret = ((pic2.ocw3 & 0x20) >> 5) << 4; + ret |= ((pic2.ocw2 & 0x80) >> 7) << 3; + ret |= ((pic2.icw4 & 0x10) >> 4) << 2; + ret |= ((pic2.icw4 & 0x02) >> 1) << 1; + ret |= ((pic2.icw4 & 0x08) >> 3) << 0; + } else if ((addr == 0x21) && shadow) + ret = ((pic2.vector & 0xf8) >> 3) << 0; + else if (addr & 1) + ret = pic2.mask; + else if (pic.read) + ret = pic2.ins; + else + ret = pic2.pend; + + pic_log("%04X:%04X: Read PIC 2 port %04X, value %02X\n", CS, cpu_state.pc, addr, val); + + return ret; } diff --git a/src/pic.h b/src/pic.h index c164a0aa9..10684958a 100644 --- a/src/pic.h +++ b/src/pic.h @@ -3,10 +3,8 @@ typedef struct PIC { - uint8_t icw1,icw3,icw4,mask,ins,pend,mask2; - int icw; - uint8_t vector; - int read; + uint8_t icw1, icw3, icw4, mask, ins, pend, mask2, vector, ocw2, ocw3; + int icw, read; } PIC; @@ -14,6 +12,7 @@ extern PIC pic, pic2; extern int pic_intpending; +extern void pic_set_shadow(int sh); extern void pic_init(void); extern void pic_init_pcjr(void); extern void pic2_init(void); diff --git a/src/via_vt82c586b.c b/src/via_vt82c586b.c index 904438ba9..a4eba54f4 100644 --- a/src/via_vt82c586b.c +++ b/src/via_vt82c586b.c @@ -6,7 +6,7 @@ * * Emulation of the VIA Apollo MVP3 southbridge * - * Version: @(#)via_vt82c586b.c 1.0.0 2020/01/14 + * Version: @(#)via_vt82c586b.c 1.0.1 2020/01/17 * * Authors: Sarah Walker, * Miran Grca, @@ -113,6 +113,8 @@ via_vt82c586b_reset_hard(void *priv) dma[i].ac &= 0xffff000f; } + pic_set_shadow(0); + /* IDE registers */ via_vt82c586b->ide_regs[0x00] = 0x06; via_vt82c586b->ide_regs[0x01] = 0x11; /*VIA*/ via_vt82c586b->ide_regs[0x02] = 0x71; via_vt82c586b->ide_regs[0x03] = 0x05; /*VT82C586B*/ @@ -384,6 +386,7 @@ via_vt82c586b_write(int func, int addr, uint8_t val, void *priv) case 0x47: if ((val & 0x81) == 0x81) resetx86(); + pic_set_shadow(!!(val & 0x10)); pci_elcr_set_enabled(!!(val & 0x20)); dev->pci_isa_regs[0x47] = val & 0xfe; break; From 756fabadd727d4a9a76df9947304133c3613b8db Mon Sep 17 00:00:00 2001 From: Daniel Gurney Date: Fri, 17 Jan 2020 15:25:29 +0200 Subject: [PATCH 172/177] Add instructions for not using the shortcut (#555) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c825e0c57..7984a775f 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ Building In order to compile 86Box from this repository, please follow this step-by-step guide: 1. Install the [MSYS2](https://www.msys2.org/) environment. The rest of the guide will refer to the directory that you install it to (C:\msys32 or C:\msys64 by default) as the MSYS2 root. -2. Launch your MSYS2 environment using the `MSYS2 MinGW 32-bit` shortcut. +2. Launch your MSYS2 environment using the `MSYS2 MinGW 32-bit` shortcut. If you do not want to use the shortcut, launch it with `\mingw32.exe`. 3. Once launched, run `pacman -Syu` in order to update the environment. You may need to do this twice, just follow the on-screen instructions. Make sure you re-run `pacman -Syu` periodically to keep the environment up-to-date. 4. Run the following command to install all of the dependencies: `pacman -S gdb make git mingw-w64-i686-toolchain mingw-w64-i686-openal mingw-w64-i686-freetype mingw-w64-i686-SDL2 mingw-w64-i686-zlib mingw-w64-i686-libpng mingw-w64-i686-ghostscript`. Additionally, you will need to download the developer's pack of WinPcap [from here](https://www.winpcap.org/devel.htm), and extract it into `\mingw32\`. 5. Once the environment is fully updated and all dependencies are installed, `cd` into your cloned `86box\src` From 7f94aed206aa0db845c55911c64172523cb8b2aa Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 17 Jan 2020 21:03:26 +0100 Subject: [PATCH 173/177] Added the Mystique to video/vid_table.c. --- src/video/vid_table.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/video/vid_table.c b/src/video/vid_table.c index d86e61686..4db6190ba 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -8,13 +8,13 @@ * * Define all known video cards. * - * Version: @(#)vid_table.c 1.0.44 2019/10/01 + * Version: @(#)vid_table.c 1.0.45 2020/01/17 * * Authors: Miran Grca, * Fred N. van Kempen, * - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. */ #include #include @@ -49,6 +49,7 @@ #include "vid_incolor.h" #include "vid_colorplus.h" #include "vid_mda.h" +#include "vid_mga.h" #include "vid_oak_oti.h" #include "vid_paradise.h" #include "vid_pgc.h" @@ -148,6 +149,7 @@ video_cards[] = { { "[PCI] Diamond Stealth 3D 3000 (S3 ViRGE/VX)", "stealth3d_3000_pci", &s3_virge_988_pci_device }, { "[PCI] Diamond Stealth 64 DRAM (S3 Trio64)", "stealth64d_pci", &s3_diamond_stealth64_pci_device }, { "[PCI] Diamond Stealth 64 VRAM (S3 Vision964)", "stealth64v_pci", &s3_diamond_stealth64_964_pci_device }, + { "[PCI] Matrox Mystique", "mystique", &mystique_device }, { "[PCI] Number Nine 9FX (S3 Trio64)", "n9_9fx_pci", &s3_9fx_pci_device }, { "[PCI] Paradise Bahamas 64 (S3 Vision864)", "bahamas64_pci", &s3_bahamas64_pci_device }, { "[PCI] Phoenix S3 Vision864", "px_vision864_pci", &s3_phoenix_vision864_pci_device }, From 6ec5d9bcbc732c669ccc68fd178341cf5456c6f1 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 18 Jan 2020 02:47:57 +0100 Subject: [PATCH 174/177] Cleaned up the Matrox code, added a dummy ILOAD FILTER opcode to make AMIDIAG no longer hang, added the 8 MB memory option, and fixed 32-bit blits with 8 MB is set. --- src/video/vid_mga.c | 7436 +++++++++++++++++++++---------------------- 1 file changed, 3603 insertions(+), 3833 deletions(-) diff --git a/src/video/vid_mga.c b/src/video/vid_mga.c index 6f0a988c9..340c15560 100644 --- a/src/video/vid_mga.c +++ b/src/video/vid_mga.c @@ -540,6 +540,7 @@ enum #define DWGCTRL_OPCODE_IDUMP (0xa << 0) #define DWGCTRL_OPCODE_ILOAD_SCALE (0xd << 0) #define DWGCTRL_OPCODE_ILOAD_HIGHV (0xe << 0) +#define DWGCTRL_OPCODE_ILOAD_FILTER (0xf << 0) /* Not implemented. */ #define DWGCTRL_ATYPE_MASK (7 << 4) #define DWGCTRL_ATYPE_RPL (0 << 4) #define DWGCTRL_ATYPE_RSTR (1 << 4) @@ -657,1593 +658,1546 @@ static void blit_iload_write(mystique_t *mystique, uint32_t data, int size); static video_timings_t timing_matrox_mystique = {VIDEO_BUS, 4, 4, 4, 10, 10, 10}; -void mystique_out(uint16_t addr, uint8_t val, void *p) + +void +mystique_out(uint16_t addr, uint8_t val, void *p) { - mystique_t *mystique = (mystique_t *)p; - svga_t *svga = &mystique->svga; - uint8_t old; + mystique_t *mystique = (mystique_t *)p; + svga_t *svga = &mystique->svga; + uint8_t old; - if ((((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && addr < 0x3de) && !(svga->miscout & 1)) - addr ^= 0x60; + if ((((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && addr < 0x3de) && !(svga->miscout & 1)) + addr ^= 0x60; - switch (addr) - { - case 0x3c8: - mystique->xreg_idx = val; - break; - - case 0x3cf: - if ((svga->gdcaddr & 15) == 6 && svga->gdcreg[6] != val) { - svga->gdcreg[svga->gdcaddr & 15] = val; - mystique_recalc_mapping(mystique); - return; - } - break; + switch (addr) { + case 0x3c8: + mystique->xreg_idx = val; + break; - case 0x3D4: - svga->crtcreg = val & 0x3f; - return; - case 0x3D5: - if (((svga->crtcreg & 31) < 7) && (svga->crtc[0x11] & 0x80)) - return; - if (((svga->crtcreg & 31) == 7) && (svga->crtc[0x11] & 0x80)) - val = (svga->crtc[7] & ~0x10) | (val & 0x10); - old = svga->crtc[svga->crtcreg & 0x3f]; - svga->crtc[svga->crtcreg & 31] = val; - if (old != val) { - if ((svga->crtcreg & 31) < 0xE || (svga->crtcreg & 31) > 0x10) { - svga->fullchange = changeframecount; - svga_recalctimings(svga); - } - } - break; - - case 0x3de: - mystique->crtcext_idx = val; - break; - case 0x3df: - if (mystique->crtcext_idx < 6) - mystique->crtcext_regs[mystique->crtcext_idx] = val; - if (mystique->crtcext_idx < 4) { - svga->fullchange = changeframecount; - svga_recalctimings(svga); - } - if (mystique->crtcext_idx == 3) { - if (val & CRTCX_R3_MGAMODE) - svga->fb_only = 1; - else - svga->fb_only = 0; - svga_recalctimings(svga); - } - if (mystique->crtcext_idx == 4) { - if (svga->gdcreg[6] & 0xc) { - /*64k banks*/ - svga->read_bank = (val & 0x7f) << 16; - svga->write_bank = (val & 0x7f) << 16; - } else { - /*128k banks*/ - svga->read_bank = (val & 0x7e) << 16; - svga->write_bank = (val & 0x7e) << 16; - } - } - break; - } - svga_out(addr, val, svga); -} - -uint8_t mystique_in(uint16_t addr, void *p) -{ - mystique_t *mystique = (mystique_t *)p; - svga_t *svga = &mystique->svga; - uint8_t temp = 0xff; - - if ((((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && addr < 0x3de) && !(svga->miscout & 1)) - addr ^= 0x60; - - switch (addr) - { - case 0x3D4: - temp = svga->crtcreg; - break; - case 0x3D5: - temp = svga->crtc[svga->crtcreg & 0x3f]; - break; - - case 0x3df: - if (mystique->crtcext_idx < 6) - temp = mystique->crtcext_regs[mystique->crtcext_idx]; - break; - - default: - temp = svga_in(addr, svga); - break; - } - - return temp; -} - -static int mystique_line_compare(svga_t *svga) -{ - mystique_t *mystique = (mystique_t *)svga->p; - - mystique->status |= STATUS_VLINEPEN; - mystique_update_irqs(mystique); - - return 0; -} - -void mystique_recalctimings(svga_t *svga) -{ - mystique_t *mystique = (mystique_t *)svga->p; - int clk_sel = (svga->miscout >> 2) & 3; - - if (clk_sel & 2) { - int m = mystique->xpixpll[2].m; - int n = mystique->xpixpll[2].n; - int p = mystique->xpixpll[2].p; - - double fvco = 14318181.0 * (n + 1) / (m + 1); - double fo = fvco / (p + 1); - -// pclog("m=%i n=%i p=%i fo=%g\n", m, n, p, fo); - svga->clock = (cpuclock * (float)(1ull << 32)) / fo; - } - - if (mystique->crtcext_regs[1] & CRTCX_R1_HTOTAL8) - svga->htotal += 0x100; - if (mystique->crtcext_regs[2] & CRTCX_R2_VTOTAL10) - svga->vtotal += 0x400; - if (mystique->crtcext_regs[2] & CRTCX_R2_VTOTAL11) - svga->vtotal += 0x800; - if (mystique->crtcext_regs[2] & CRTCX_R2_VDISPEND10) - svga->dispend += 0x400; - if (mystique->crtcext_regs[2] & CRTCX_R2_VBLKSTR10) - svga->vblankstart += 0x400; - if (mystique->crtcext_regs[2] & CRTCX_R2_VBLKSTR11) - svga->vblankstart += 0x800; - if (mystique->crtcext_regs[2] & CRTCX_R2_VSYNCSTR10) - svga->vsyncstart += 0x400; - if (mystique->crtcext_regs[2] & CRTCX_R2_VSYNCSTR11) - svga->vsyncstart += 0x800; - if (mystique->crtcext_regs[2] & CRTCX_R2_LINECOMP10) - svga->split += 0x400; - - if (mystique->crtcext_regs[3] & CRTCX_R3_MGAMODE) { - int row_offset = svga->crtc[0x13] | ((mystique->crtcext_regs[0] & CRTCX_R0_OFFSET_MASK) << 4); - -// svga->split = 99999; - svga->lowres = 0; - svga->rowoffset = row_offset * 2; - svga->ma_latch = ((mystique->crtcext_regs[0] & CRTCX_R0_STARTADD_MASK) << 17) | - (svga->crtc[0xc] << 9) | (svga->crtc[0xd] << 1); - - /*Mystique, unlike most SVGA cards, allows display start to take - effect mid-screen*/ - if (svga->ma_latch != mystique->ma_latch_old) { -// pclog("ma_latch change: old=%08x new=%08x ma=%08x ", mystique->ma_latch_old, svga->ma_latch, svga->maback); - svga->ma = svga->maback = (svga->maback - (mystique->ma_latch_old << 2)) + (svga->ma_latch << 2); -// pclog("ma_new=%08x\n", svga->maback); - mystique->ma_latch_old = svga->ma_latch; - } - - switch (mystique->xmulctrl & XMULCTRL_DEPTH_MASK) - { - case XMULCTRL_DEPTH_8: - case XMULCTRL_DEPTH_2G8V16: - svga->render = svga_render_8bpp_highres; - svga->bpp = 8; - break; - case XMULCTRL_DEPTH_15: - case XMULCTRL_DEPTH_G16V16: - svga->render = svga_render_15bpp_highres; - svga->bpp = 15; - break; - case XMULCTRL_DEPTH_16: - svga->render = svga_render_16bpp_highres; - svga->bpp = 16; - break; - case XMULCTRL_DEPTH_24: - svga->render = svga_render_24bpp_highres; - svga->bpp = 24; - break; - case XMULCTRL_DEPTH_32: - case XMULCTRL_DEPTH_32_OVERLAYED: - svga->render = svga_render_32bpp_highres; - svga->bpp = 32; - break; - } - - svga->line_compare = mystique_line_compare; -// pclog("recalc: htotal=%i vtotal=%i dispend=%i\n", svga->htotal, svga->vtotal, svga->dispend); - } else { - svga->line_compare = NULL; - svga->bpp = 8; - } -} - -static void mystique_recalc_mapping(mystique_t *mystique) -{ - svga_t *svga = &mystique->svga; - - io_removehandler(0x03c0, 0x0020, mystique_in, NULL, NULL, mystique_out, NULL, NULL, mystique); - if ((mystique->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) && (mystique->pci_regs[0x41] & 1)) - io_sethandler(0x03c0, 0x0020, mystique_in, NULL, NULL, mystique_out, NULL, NULL, mystique); - - if (!(mystique->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) { - mem_mapping_disable(&svga->mapping); - mem_mapping_disable(&mystique->ctrl_mapping); - mem_mapping_disable(&mystique->lfb_mapping); - mem_mapping_disable(&mystique->iload_mapping); + case 0x3cf: + if ((svga->gdcaddr & 15) == 6 && svga->gdcreg[6] != val) { + svga->gdcreg[svga->gdcaddr & 15] = val; + mystique_recalc_mapping(mystique); return; - } + } + break; - if (mystique->ctrl_base) - mem_mapping_set_addr(&mystique->ctrl_mapping, mystique->ctrl_base, 0x4000); - else - mem_mapping_disable(&mystique->ctrl_mapping); - if (mystique->lfb_base) - mem_mapping_set_addr(&mystique->lfb_mapping, mystique->lfb_base, 0x800000); - else - mem_mapping_disable(&mystique->lfb_mapping); - if (mystique->iload_base) - mem_mapping_set_addr(&mystique->iload_mapping, mystique->iload_base, 0x800000); - else - mem_mapping_disable(&mystique->iload_mapping); - - if (mystique->pci_regs[0x41] & 1) { - switch (svga->gdcreg[6] & 0x0C) - { - case 0x0: /*128k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); - svga->banked_mask = 0x1ffff; - break; - case 0x4: /*64k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); - svga->banked_mask = 0xffff; - break; - case 0x8: /*32k at B0000*/ - mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); - svga->banked_mask = 0x7fff; - break; - case 0xC: /*32k at B8000*/ - mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); - svga->banked_mask = 0x7fff; - break; + case 0x3D4: + svga->crtcreg = val & 0x3f; + return; + case 0x3D5: + if (((svga->crtcreg & 31) < 7) && (svga->crtc[0x11] & 0x80)) + return; + if (((svga->crtcreg & 31) == 7) && (svga->crtc[0x11] & 0x80)) + val = (svga->crtc[7] & ~0x10) | (val & 0x10); + old = svga->crtc[svga->crtcreg & 0x3f]; + svga->crtc[svga->crtcreg & 31] = val; + if (old != val) { + if ((svga->crtcreg & 31) < 0xE || (svga->crtcreg & 31) > 0x10) { + svga->fullchange = changeframecount; + svga_recalctimings(svga); } + } + break; + + case 0x3de: + mystique->crtcext_idx = val; + break; + case 0x3df: + if (mystique->crtcext_idx < 6) + mystique->crtcext_regs[mystique->crtcext_idx] = val; + if (mystique->crtcext_idx < 4) { + svga->fullchange = changeframecount; + svga_recalctimings(svga); + } + if (mystique->crtcext_idx == 3) { + if (val & CRTCX_R3_MGAMODE) + svga->fb_only = 1; + else + svga->fb_only = 0; + svga_recalctimings(svga); + } + if (mystique->crtcext_idx == 4) { if (svga->gdcreg[6] & 0xc) { /*64k banks*/ - svga->read_bank = (mystique->crtcext_regs[4] & 0x7f) << 16; - svga->write_bank = (mystique->crtcext_regs[4] & 0x7f) << 16; + svga->read_bank = (val & 0x7f) << 16; + svga->write_bank = (val & 0x7f) << 16; } else { /*128k banks*/ - svga->read_bank = (mystique->crtcext_regs[4] & 0x7e) << 16; - svga->write_bank = (mystique->crtcext_regs[4] & 0x7e) << 16; + svga->read_bank = (val & 0x7e) << 16; + svga->write_bank = (val & 0x7e) << 16; } - } else - mem_mapping_disable(&svga->mapping); + } + break; + } + + svga_out(addr, val, svga); } -static void mystique_update_irqs(mystique_t *mystique) + +uint8_t +mystique_in(uint16_t addr, void *p) { - int irq = 0; - - if ((mystique->status & mystique->ien) & STATUS_SOFTRAPEN) - irq = 1; - - if (irq) - pci_set_irq(mystique->card, PCI_INTA); - else - pci_clear_irq(mystique->card, PCI_INTA); + mystique_t *mystique = (mystique_t *)p; + svga_t *svga = &mystique->svga; + uint8_t temp = 0xff; + + if ((((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && addr < 0x3de) && !(svga->miscout & 1)) + addr ^= 0x60; + + switch (addr) { + case 0x3D4: + temp = svga->crtcreg; + break; + case 0x3D5: + temp = svga->crtc[svga->crtcreg & 0x3f]; + break; + + case 0x3df: + if (mystique->crtcext_idx < 6) + temp = mystique->crtcext_regs[mystique->crtcext_idx]; + break; + + default: + temp = svga_in(addr, svga); + break; + } + + return temp; } -#define READ8(addr, var) switch ((addr) & 3) \ - { \ - case 0: ret = (var) & 0xff; break; \ - case 1: ret = ((var) >> 8) & 0xff; break; \ - case 2: ret = ((var) >> 16) & 0xff; break; \ - case 3: ret = ((var) >> 24) & 0xff; break; \ + +static int +mystique_line_compare(svga_t *svga) +{ + mystique_t *mystique = (mystique_t *)svga->p; + + mystique->status |= STATUS_VLINEPEN; + mystique_update_irqs(mystique); + + return 0; +} + + +void +mystique_recalctimings(svga_t *svga) +{ + mystique_t *mystique = (mystique_t *)svga->p; + int clk_sel = (svga->miscout >> 2) & 3; + + if (clk_sel & 2) { + int m = mystique->xpixpll[2].m; + int n = mystique->xpixpll[2].n; + int p = mystique->xpixpll[2].p; + + double fvco = 14318181.0 * (n + 1) / (m + 1); + double fo = fvco / (p + 1); + + svga->clock = (cpuclock * (float)(1ull << 32)) / fo; + } + + if (mystique->crtcext_regs[1] & CRTCX_R1_HTOTAL8) + svga->htotal += 0x100; + if (mystique->crtcext_regs[2] & CRTCX_R2_VTOTAL10) + svga->vtotal += 0x400; + if (mystique->crtcext_regs[2] & CRTCX_R2_VTOTAL11) + svga->vtotal += 0x800; + if (mystique->crtcext_regs[2] & CRTCX_R2_VDISPEND10) + svga->dispend += 0x400; + if (mystique->crtcext_regs[2] & CRTCX_R2_VBLKSTR10) + svga->vblankstart += 0x400; + if (mystique->crtcext_regs[2] & CRTCX_R2_VBLKSTR11) + svga->vblankstart += 0x800; + if (mystique->crtcext_regs[2] & CRTCX_R2_VSYNCSTR10) + svga->vsyncstart += 0x400; + if (mystique->crtcext_regs[2] & CRTCX_R2_VSYNCSTR11) + svga->vsyncstart += 0x800; + if (mystique->crtcext_regs[2] & CRTCX_R2_LINECOMP10) + svga->split += 0x400; + + if (mystique->crtcext_regs[3] & CRTCX_R3_MGAMODE) { + int row_offset = svga->crtc[0x13] | ((mystique->crtcext_regs[0] & CRTCX_R0_OFFSET_MASK) << 4); + + svga->lowres = 0; + svga->rowoffset = row_offset * 2; + svga->ma_latch = ((mystique->crtcext_regs[0] & CRTCX_R0_STARTADD_MASK) << 17) | + (svga->crtc[0xc] << 9) | (svga->crtc[0xd] << 1); + + /*Mystique, unlike most SVGA cards, allows display start to take + effect mid-screen*/ + if (svga->ma_latch != mystique->ma_latch_old) { + svga->ma = svga->maback = (svga->maback - (mystique->ma_latch_old << 2)) + (svga->ma_latch << 2); + mystique->ma_latch_old = svga->ma_latch; + } + + switch (mystique->xmulctrl & XMULCTRL_DEPTH_MASK) { + case XMULCTRL_DEPTH_8: + case XMULCTRL_DEPTH_2G8V16: + svga->render = svga_render_8bpp_highres; + svga->bpp = 8; + break; + case XMULCTRL_DEPTH_15: + case XMULCTRL_DEPTH_G16V16: + svga->render = svga_render_15bpp_highres; + svga->bpp = 15; + break; + case XMULCTRL_DEPTH_16: + svga->render = svga_render_16bpp_highres; + svga->bpp = 16; + break; + case XMULCTRL_DEPTH_24: + svga->render = svga_render_24bpp_highres; + svga->bpp = 24; + break; + case XMULCTRL_DEPTH_32: + case XMULCTRL_DEPTH_32_OVERLAYED: + svga->render = svga_render_32bpp_highres; + svga->bpp = 32; + break; + } + + svga->line_compare = mystique_line_compare; + } else { + svga->line_compare = NULL; + svga->bpp = 8; + } +} + + +static +void mystique_recalc_mapping(mystique_t *mystique) +{ + svga_t *svga = &mystique->svga; + + io_removehandler(0x03c0, 0x0020, mystique_in, NULL, NULL, mystique_out, NULL, NULL, mystique); + if ((mystique->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) && (mystique->pci_regs[0x41] & 1)) + io_sethandler(0x03c0, 0x0020, mystique_in, NULL, NULL, mystique_out, NULL, NULL, mystique); + + if (!(mystique->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) { + mem_mapping_disable(&svga->mapping); + mem_mapping_disable(&mystique->ctrl_mapping); + mem_mapping_disable(&mystique->lfb_mapping); + mem_mapping_disable(&mystique->iload_mapping); + return; + } + + if (mystique->ctrl_base) + mem_mapping_set_addr(&mystique->ctrl_mapping, mystique->ctrl_base, 0x4000); + else + mem_mapping_disable(&mystique->ctrl_mapping); + + if (mystique->lfb_base) + mem_mapping_set_addr(&mystique->lfb_mapping, mystique->lfb_base, 0x800000); + else + mem_mapping_disable(&mystique->lfb_mapping); + + if (mystique->iload_base) + mem_mapping_set_addr(&mystique->iload_mapping, mystique->iload_base, 0x800000); + else + mem_mapping_disable(&mystique->iload_mapping); + + if (mystique->pci_regs[0x41] & 1) { + switch (svga->gdcreg[6] & 0x0C) { + case 0x0: /*128k at A0000*/ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + svga->banked_mask = 0x1ffff; + break; + case 0x4: /*64k at A0000*/ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + svga->banked_mask = 0xffff; + break; + case 0x8: /*32k at B0000*/ + mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); + svga->banked_mask = 0x7fff; + break; + case 0xC: /*32k at B8000*/ + mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); + svga->banked_mask = 0x7fff; + break; + } + if (svga->gdcreg[6] & 0xc) { + /*64k banks*/ + svga->read_bank = (mystique->crtcext_regs[4] & 0x7f) << 16; + svga->write_bank = (mystique->crtcext_regs[4] & 0x7f) << 16; + } else { + /*128k banks*/ + svga->read_bank = (mystique->crtcext_regs[4] & 0x7e) << 16; + svga->write_bank = (mystique->crtcext_regs[4] & 0x7e) << 16; + } + } else + mem_mapping_disable(&svga->mapping); +} + + +static void +mystique_update_irqs(mystique_t *mystique) +{ + int irq = 0; + + if ((mystique->status & mystique->ien) & STATUS_SOFTRAPEN) + irq = 1; + + if (irq) + pci_set_irq(mystique->card, PCI_INTA); + else + pci_clear_irq(mystique->card, PCI_INTA); +} + + +#define READ8(addr, var) switch ((addr) & 3) { \ + case 0: ret = (var) & 0xff; break; \ + case 1: ret = ((var) >> 8) & 0xff; break; \ + case 2: ret = ((var) >> 16) & 0xff; break; \ + case 3: ret = ((var) >> 24) & 0xff; break; \ + } + +#define WRITE8(addr, var, val) switch ((addr) & 3) { \ + case 0: var = (var & 0xffffff00) | (val); break; \ + case 1: var = (var & 0xffff00ff) | ((val) << 8); break; \ + case 2: var = (var & 0xff00ffff) | ((val) << 16); break; \ + case 3: var = (var & 0x00ffffff) | ((val) << 24); break; \ } -#define WRITE8(addr, var, val) switch ((addr) & 3) \ - { \ - case 0: var = (var & 0xffffff00) | (val); break; \ - case 1: var = (var & 0xffff00ff) | ((val) << 8); break; \ - case 2: var = (var & 0xff00ffff) | ((val) << 16); break; \ - case 3: var = (var & 0x00ffffff) | ((val) << 24); break; \ - } -static uint8_t mystique_read_xreg(mystique_t *mystique, int reg) +static uint8_t +mystique_read_xreg(mystique_t *mystique, int reg) { - uint8_t ret = 0xff; - - switch (reg) - { - case XREG_XCURADDL: - ret = mystique->cursor.addr & 0xff; - break; - case XREG_XCURADDH: - ret = mystique->cursor.addr >> 8; - break; - case XREG_XCURCTRL: - ret = mystique->xcurctrl; - break; - - case XREG_XCURCOL0R: case XREG_XCURCOL0G: case XREG_XCURCOL0B: - READ8(reg, mystique->cursor.col[0]); - break; - case XREG_XCURCOL1R: case XREG_XCURCOL1G: case XREG_XCURCOL1B: - READ8(reg, mystique->cursor.col[1]); - break; - case XREG_XCURCOL2R: case XREG_XCURCOL2G: case XREG_XCURCOL2B: - READ8(reg, mystique->cursor.col[2]); - break; + uint8_t ret = 0xff; - case XREG_XMULCTRL: - ret = mystique->xmulctrl; - break; - - case XREG_XMISCCTRL: - ret = mystique->xmiscctrl; - break; + switch (reg) { + case XREG_XCURADDL: + ret = mystique->cursor.addr & 0xff; + break; + case XREG_XCURADDH: + ret = mystique->cursor.addr >> 8; + break; + case XREG_XCURCTRL: + ret = mystique->xcurctrl; + break; - case XREG_XGENCTRL: - ret = mystique->xgenctrl; - break; - - case XREG_XGENIOCTRL: - ret = mystique->xgenioctrl; - break; - case XREG_XGENIODATA: - ret = mystique->xgeniodata; - break; + case XREG_XCURCOL0R: case XREG_XCURCOL0G: case XREG_XCURCOL0B: + READ8(reg, mystique->cursor.col[0]); + break; + case XREG_XCURCOL1R: case XREG_XCURCOL1G: case XREG_XCURCOL1B: + READ8(reg, mystique->cursor.col[1]); + break; + case XREG_XCURCOL2R: case XREG_XCURCOL2G: case XREG_XCURCOL2B: + READ8(reg, mystique->cursor.col[2]); + break; - case XREG_XSYSPLLM: - ret = mystique->xsyspllm; - break; - case XREG_XSYSPLLN: - ret = mystique->xsysplln; - break; - case XREG_XSYSPLLP: - ret = mystique->xsyspllp; - break; + case XREG_XMULCTRL: + ret = mystique->xmulctrl; + break; - case XREG_XZOOMCTRL: - ret = mystique->xzoomctrl; - break; + case XREG_XMISCCTRL: + ret = mystique->xmiscctrl; + break; - case XREG_XPIXCLKCTRL: - ret = mystique->xpixclkctrl; - break; + case XREG_XGENCTRL: + ret = mystique->xgenctrl; + break; - case XREG_XSYSPLLSTAT: - ret = XSYSPLLSTAT_SYSLOCK; - break; + case XREG_XGENIOCTRL: + ret = mystique->xgenioctrl; + break; + case XREG_XGENIODATA: + ret = mystique->xgeniodata; + break; - case XREG_XPIXPLLSTAT: - ret = XPIXPLLSTAT_SYSLOCK; - break; - - case XREG_XPIXPLLCM: - ret = mystique->xpixpll[2].m; - break; - case XREG_XPIXPLLCN: - ret = mystique->xpixpll[2].n; - break; - case XREG_XPIXPLLCP: - ret = mystique->xpixpll[2].p | (mystique->xpixpll[2].s << 3); - break; + case XREG_XSYSPLLM: + ret = mystique->xsyspllm; + break; + case XREG_XSYSPLLN: + ret = mystique->xsysplln; + break; + case XREG_XSYSPLLP: + ret = mystique->xsyspllp; + break; - case 0x00: case 0x20: case 0x3f: - ret = 0xff; - break; + case XREG_XZOOMCTRL: + ret = mystique->xzoomctrl; + break; - default: - if (reg >= 0x50) - ret = 0xff; - break; - } - return ret; + case XREG_XPIXCLKCTRL: + ret = mystique->xpixclkctrl; + break; + + case XREG_XSYSPLLSTAT: + ret = XSYSPLLSTAT_SYSLOCK; + break; + + case XREG_XPIXPLLSTAT: + ret = XPIXPLLSTAT_SYSLOCK; + break; + + case XREG_XPIXPLLCM: + ret = mystique->xpixpll[2].m; + break; + case XREG_XPIXPLLCN: + ret = mystique->xpixpll[2].n; + break; + case XREG_XPIXPLLCP: + ret = mystique->xpixpll[2].p | (mystique->xpixpll[2].s << 3); + break; + + case 0x00: case 0x20: case 0x3f: + ret = 0xff; + break; + + default: + if (reg >= 0x50) + ret = 0xff; + break; + } + + return ret; } -static void mystique_write_xreg(mystique_t *mystique, int reg, uint8_t val) + +static void +mystique_write_xreg(mystique_t *mystique, int reg, uint8_t val) { - svga_t *svga = &mystique->svga; - - switch (reg) - { - case XREG_XCURADDL: - mystique->cursor.addr = (mystique->cursor.addr & 0x1f00) | val; - svga->hwcursor.addr = mystique->cursor.addr << 10; - break; - case XREG_XCURADDH: - mystique->cursor.addr = (mystique->cursor.addr & 0x00ff) | ((val & 0x1f) << 8); - svga->hwcursor.addr = mystique->cursor.addr << 10; - break; - - case XREG_XCURCTRL: - mystique->xcurctrl = val; - svga->hwcursor.ena = (val & 3) ? 1 : 0; - break; + svga_t *svga = &mystique->svga; - case XREG_XCURCOL0R: case XREG_XCURCOL0G: case XREG_XCURCOL0B: - WRITE8(reg, mystique->cursor.col[0], val); - break; - case XREG_XCURCOL1R: case XREG_XCURCOL1G: case XREG_XCURCOL1B: - WRITE8(reg, mystique->cursor.col[1], val); - break; - case XREG_XCURCOL2R: case XREG_XCURCOL2G: case XREG_XCURCOL2B: - WRITE8(reg, mystique->cursor.col[2], val); - break; + switch (reg) { + case XREG_XCURADDL: + mystique->cursor.addr = (mystique->cursor.addr & 0x1f00) | val; + svga->hwcursor.addr = mystique->cursor.addr << 10; + break; + case XREG_XCURADDH: + mystique->cursor.addr = (mystique->cursor.addr & 0x00ff) | ((val & 0x1f) << 8); + svga->hwcursor.addr = mystique->cursor.addr << 10; + break; - case XREG_XMULCTRL: - mystique->xmulctrl = val; - break; + case XREG_XCURCTRL: + mystique->xcurctrl = val; + svga->hwcursor.ena = (val & 3) ? 1 : 0; + break; - case XREG_XMISCCTRL: - mystique->xmiscctrl = val; - svga_set_ramdac_type(svga, (val & XMISCCTRL_VGA8DAC) ? RAMDAC_8BIT : RAMDAC_6BIT); - break; - - case XREG_XGENCTRL: - mystique->xgenctrl = val; - break; + case XREG_XCURCOL0R: case XREG_XCURCOL0G: case XREG_XCURCOL0B: + WRITE8(reg, mystique->cursor.col[0], val); + break; + case XREG_XCURCOL1R: case XREG_XCURCOL1G: case XREG_XCURCOL1B: + WRITE8(reg, mystique->cursor.col[1], val); + break; + case XREG_XCURCOL2R: case XREG_XCURCOL2G: case XREG_XCURCOL2B: + WRITE8(reg, mystique->cursor.col[2], val); + break; - case XREG_XVREFCTRL: - mystique->xvrefctrl = val; - break; + case XREG_XMULCTRL: + mystique->xmulctrl = val; + break; - case XREG_XGENIOCTRL: - mystique->xgenioctrl = val; - break; - case XREG_XGENIODATA: - mystique->xgeniodata = val; - break; + case XREG_XMISCCTRL: + mystique->xmiscctrl = val; + svga_set_ramdac_type(svga, (val & XMISCCTRL_VGA8DAC) ? RAMDAC_8BIT : RAMDAC_6BIT); + break; - case XREG_XSYSPLLM: - mystique->xsyspllm = val; - break; - case XREG_XSYSPLLN: - mystique->xsysplln = val; - break; - case XREG_XSYSPLLP: - mystique->xsyspllp = val; - break; + case XREG_XGENCTRL: + mystique->xgenctrl = val; + break; - case XREG_XZOOMCTRL: - mystique->xzoomctrl = val & 3; - break; - - case XREG_XPIXCLKCTRL: - mystique->xpixclkctrl = val; - break; - - case XREG_XPIXPLLCM: - mystique->xpixpll[2].m = val; - break; - case XREG_XPIXPLLCN: - mystique->xpixpll[2].n = val; - break; - case XREG_XPIXPLLCP: - mystique->xpixpll[2].p = val & 7; - mystique->xpixpll[2].s = (val >> 3) & 3; - break; - - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x07: case 0x0b: case 0x0f: - case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: - case 0x1b: case 0x1c: case 0x20: case 0x39: case 0x3b: case 0x3f: - case 0x47: case 0x4b: - break; + case XREG_XVREFCTRL: + mystique->xvrefctrl = val; + break; - default: - break; - } + case XREG_XGENIOCTRL: + mystique->xgenioctrl = val; + break; + case XREG_XGENIODATA: + mystique->xgeniodata = val; + break; + + case XREG_XSYSPLLM: + mystique->xsyspllm = val; + break; + case XREG_XSYSPLLN: + mystique->xsysplln = val; + break; + case XREG_XSYSPLLP: + mystique->xsyspllp = val; + break; + + case XREG_XZOOMCTRL: + mystique->xzoomctrl = val & 3; + break; + + case XREG_XPIXCLKCTRL: + mystique->xpixclkctrl = val; + break; + + case XREG_XPIXPLLCM: + mystique->xpixpll[2].m = val; + break; + case XREG_XPIXPLLCN: + mystique->xpixpll[2].n = val; + break; + case XREG_XPIXPLLCP: + mystique->xpixpll[2].p = val & 7; + mystique->xpixpll[2].s = (val >> 3) & 3; + break; + + case 0x00: case 0x01: case 0x02: case 0x03: + case 0x07: case 0x0b: case 0x0f: + case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: + case 0x1b: case 0x1c: case 0x20: case 0x39: case 0x3b: case 0x3f: + case 0x47: case 0x4b: + break; + + default: + break; + } } -static uint8_t mystique_ctrl_read_b(uint32_t addr, void *p) + +static uint8_t +mystique_ctrl_read_b(uint32_t addr, void *p) { - mystique_t *mystique = (mystique_t *)p; - svga_t *svga = &mystique->svga; - uint8_t ret = 0xff; - int fifocount; - -// pclog("mystique read %04x %08x\n", addr & 0x3fff, cpu_state.pc); + mystique_t *mystique = (mystique_t *)p; + svga_t *svga = &mystique->svga; + uint8_t ret = 0xff; + int fifocount; - switch (addr & 0x3fff) - { - case REG_FIFOSTATUS: - fifocount = FIFO_SIZE - FIFO_ENTRIES; - if (fifocount > 64) - fifocount = 64; - ret = fifocount; - break; - case REG_FIFOSTATUS+1: - if (FIFO_EMPTY) - ret |= 2; - else if (FIFO_ENTRIES >= 64) - ret |= 1; -// ret = 2; /*Empty*/ - break; - case REG_FIFOSTATUS+2: case REG_FIFOSTATUS+3: - ret = 0; - break; + switch (addr & 0x3fff) { + case REG_FIFOSTATUS: + fifocount = FIFO_SIZE - FIFO_ENTRIES; + if (fifocount > 64) + fifocount = 64; + ret = fifocount; + break; + case REG_FIFOSTATUS+1: + if (FIFO_EMPTY) + ret |= 2; + else if (FIFO_ENTRIES >= 64) + ret |= 1; + break; + case REG_FIFOSTATUS+2: case REG_FIFOSTATUS+3: + ret = 0; + break; - case REG_STATUS: - ret = mystique->status & 0xff; - if (svga->cgastat & 8) - ret |= REG_STATUS_VSYNCSTS; -// pclog("REG_STATUS %02x\n", ret); - break; - case REG_STATUS+1: - ret = (mystique->status >> 8) & 0xff; - break; - case REG_STATUS+2: - ret = (mystique->status >> 16) & 0xff; - if (mystique->busy || - ((mystique->blitter_submit_refcount + mystique->blitter_submit_dma_refcount) != mystique->blitter_complete_refcount) || - !FIFO_EMPTY) - ret |= (STATUS_DWGENGSTS >> 16); - break; - case REG_STATUS+3: - ret = (mystique->status >> 24) & 0xff; - break; + case REG_STATUS: + ret = mystique->status & 0xff; + if (svga->cgastat & 8) + ret |= REG_STATUS_VSYNCSTS; + break; + case REG_STATUS+1: + ret = (mystique->status >> 8) & 0xff; + break; + case REG_STATUS+2: + ret = (mystique->status >> 16) & 0xff; + if (mystique->busy || + ((mystique->blitter_submit_refcount + mystique->blitter_submit_dma_refcount) != mystique->blitter_complete_refcount) || + !FIFO_EMPTY) + ret |= (STATUS_DWGENGSTS >> 16); + break; + case REG_STATUS+3: + ret = (mystique->status >> 24) & 0xff; + break; - case REG_IEN: - ret = mystique->ien & 0x64; - break; - case REG_IEN+1: case REG_IEN+2: case REG_IEN+3: - ret = 0; - break; + case REG_IEN: + ret = mystique->ien & 0x64; + break; + case REG_IEN+1: case REG_IEN+2: case REG_IEN+3: + ret = 0; + break; - case REG_OPMODE: - ret = mystique->dmamod << 2; - break; - case REG_OPMODE+1: - ret = mystique->dmadatasiz; - break; - case REG_OPMODE+2: - ret = mystique->dirdatasiz; - break; - case REG_OPMODE+3: - break; + case REG_OPMODE: + ret = mystique->dmamod << 2; + break; + case REG_OPMODE+1: + ret = mystique->dmadatasiz; + break; + case REG_OPMODE+2: + ret = mystique->dirdatasiz; + break; + case REG_OPMODE+3: + break; - case REG_PRIMADDRESS: case REG_PRIMADDRESS+1: case REG_PRIMADDRESS+2: case REG_PRIMADDRESS+3: - READ8(addr, mystique->dma.primaddress); - break; - case REG_PRIMEND: case REG_PRIMEND+1: case REG_PRIMEND+2: case REG_PRIMEND+3: - READ8(addr, mystique->dma.primend); - break; + case REG_PRIMADDRESS: case REG_PRIMADDRESS+1: case REG_PRIMADDRESS+2: case REG_PRIMADDRESS+3: + READ8(addr, mystique->dma.primaddress); + break; + case REG_PRIMEND: case REG_PRIMEND+1: case REG_PRIMEND+2: case REG_PRIMEND+3: + READ8(addr, mystique->dma.primend); + break; - case REG_SECADDRESS: case REG_SECADDRESS+1: case REG_SECADDRESS+2: case REG_SECADDRESS+3: - READ8(addr, mystique->dma.secaddress); - break; + case REG_SECADDRESS: case REG_SECADDRESS+1: case REG_SECADDRESS+2: case REG_SECADDRESS+3: + READ8(addr, mystique->dma.secaddress); + break; - case REG_VCOUNT: case REG_VCOUNT+1: case REG_VCOUNT+2: case REG_VCOUNT+3: - READ8(addr, svga->vc); - break; - - case REG_INSTS0: - ret = svga_in(0x3c2, svga); - break; + case REG_VCOUNT: case REG_VCOUNT+1: case REG_VCOUNT+2: case REG_VCOUNT+3: + READ8(addr, svga->vc); + break; - case REG_SEQ_IDX: - ret = svga_in(0x3c4, svga); - break; - case REG_SEQ_DATA: - ret = svga_in(0x3c5, svga); - break; + case REG_INSTS0: + ret = svga_in(0x3c2, svga); + break; - case REG_MISCREAD: - ret = svga_in(0x3cc, svga); - break; + case REG_SEQ_IDX: + ret = svga_in(0x3c4, svga); + break; + case REG_SEQ_DATA: + ret = svga_in(0x3c5, svga); + break; - case REG_CRTC_IDX: - ret = mystique_in(0x3d4, mystique); - break; - case REG_CRTC_DATA: - ret = mystique_in(0x3d5, mystique); - break; + case REG_MISCREAD: + ret = svga_in(0x3cc, svga); + break; - case REG_INSTS1: - ret = mystique_in(0x3da, mystique); - break; + case REG_CRTC_IDX: + ret = mystique_in(0x3d4, mystique); + break; + case REG_CRTC_DATA: + ret = mystique_in(0x3d5, mystique); + break; - case REG_CRTCEXT_IDX: - ret = mystique_in(0x3de, mystique); - break; - case REG_CRTCEXT_DATA: - ret = mystique_in(0x3df, mystique); - break; - - case REG_PALWTADD: - ret = svga_in(0x3c8, svga); - break; - case REG_PALDATA: - ret = svga_in(0x3c9, svga); - break; - case REG_PIXRDMSK: - ret = svga_in(0x3c6, svga); - break; - case REG_PALRDADD: - ret = svga_in(0x3c7, svga); - break; + case REG_INSTS1: + ret = mystique_in(0x3da, mystique); + break; - case REG_X_DATAREG: - ret = mystique_read_xreg(mystique, mystique->xreg_idx); - break; - - case REG_ICLEAR: case REG_ICLEAR+1: case REG_ICLEAR+2: case REG_ICLEAR+3: - case 0x2c30: case 0x2c31: case 0x2c32: case 0x2c33: - case 0x3e08: - break; + case REG_CRTCEXT_IDX: + ret = mystique_in(0x3de, mystique); + break; + case REG_CRTCEXT_DATA: + ret = mystique_in(0x3df, mystique); + break; - default: - if ((addr & 0x3fff) >= 0x2c00 && (addr & 0x3fff) < 0x2c40) + case REG_PALWTADD: + ret = svga_in(0x3c8, svga); + break; + case REG_PALDATA: + ret = svga_in(0x3c9, svga); + break; + case REG_PIXRDMSK: + ret = svga_in(0x3c6, svga); + break; + case REG_PALRDADD: + ret = svga_in(0x3c7, svga); + break; + + case REG_X_DATAREG: + ret = mystique_read_xreg(mystique, mystique->xreg_idx); + break; + + case REG_ICLEAR: case REG_ICLEAR+1: case REG_ICLEAR+2: case REG_ICLEAR+3: + case 0x2c30: case 0x2c31: case 0x2c32: case 0x2c33: + case 0x3e08: + break; + + default: + if ((addr & 0x3fff) >= 0x2c00 && (addr & 0x3fff) < 0x2c40) + break; + break; + } + + return ret; +} + + +static void +mystique_accel_ctrl_write_b(uint32_t addr, uint8_t val, void *p) +{ + mystique_t *mystique = (mystique_t *)p; + int start_blit = 0; + int x; + + if ((addr & 0x300) == 0x100) { + addr &= ~0x100; + start_blit = 1; + } + + switch (addr & 0x3fff) { + case REG_MACCESS: case REG_MACCESS+1: case REG_MACCESS+2: case REG_MACCESS+3: + WRITE8(addr, mystique->maccess, val); + mystique->dwgreg.dither = mystique->maccess >> 30; + break; + + case REG_MCTLWTST: case REG_MCTLWTST+1: case REG_MCTLWTST+2: case REG_MCTLWTST+3: + WRITE8(addr, mystique->mctlwtst, val); + break; + + case REG_PAT0: case REG_PAT0+1: case REG_PAT0+2: case REG_PAT0+3: + case REG_PAT1: case REG_PAT1+1: case REG_PAT1+2: case REG_PAT1+3: + for (x = 0; x < 8; x++) + mystique->dwgreg.pattern[addr & 7][x] = val & (1 << (7-x)); + break; + + case REG_XYSTRT: case REG_XYSTRT+1: + WRITE8(addr&1, mystique->dwgreg.ar[5], val); + if (mystique->dwgreg.ar[5] & 0x8000) + mystique->dwgreg.ar[5] |= 0xffff8000; + else + mystique->dwgreg.ar[5] &= ~0xffff8000; + WRITE8(addr&1, mystique->dwgreg.xdst, val); + break; + case REG_XYSTRT+2: case REG_XYSTRT+3: + WRITE8(addr & 1, mystique->dwgreg.ar[6], val); + if (mystique->dwgreg.ar[6] & 0x8000) + mystique->dwgreg.ar[6] |= 0xffff8000; + else + mystique->dwgreg.ar[6] &= ~0xffff8000; + WRITE8(addr & 1, mystique->dwgreg.ydst, val); + mystique->dwgreg.ydst_lin = ((int32_t)(int16_t)mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; + break; + + case REG_XYEND: case REG_XYEND+1: + WRITE8(addr&1, mystique->dwgreg.ar[0], val); + if (mystique->dwgreg.ar[0] & 0x8000) + mystique->dwgreg.ar[0] |= 0xffff8000; + else + mystique->dwgreg.ar[0] &= ~0xffff8000; + break; + case REG_XYEND+2: case REG_XYEND+3: + WRITE8(addr & 1, mystique->dwgreg.ar[2], val); + if (mystique->dwgreg.ar[2] & 0x8000) + mystique->dwgreg.ar[2] |= 0xffff8000; + else + mystique->dwgreg.ar[2] &= ~0xffff8000; + break; + + case REG_SGN: + mystique->dwgreg.sgn.sdydxl = val & SGN_SDYDXL; + mystique->dwgreg.sgn.scanleft = val & SGN_SCANLEFT; + mystique->dwgreg.sgn.sdxl = val & SGN_SDXL; + mystique->dwgreg.sgn.sdy = val & SGN_SDY; + mystique->dwgreg.sgn.sdxr = val & SGN_SDXR; + break; + case REG_SGN+1: case REG_SGN+2: case REG_SGN+3: + break; + + case REG_LEN: case REG_LEN+1: + WRITE8(addr, mystique->dwgreg.length, val); + break; + case REG_LEN+2: + break; + case REG_LEN+3: + mystique->dwgreg.beta = val >> 4; + if (!mystique->dwgreg.beta) + mystique->dwgreg.beta = 16; + break; + + case REG_CXBNDRY: case REG_CXBNDRY+1: + WRITE8(addr, mystique->dwgreg.cxleft, val); + break; + case REG_CXBNDRY+2: case REG_CXBNDRY+3: + WRITE8(addr & 1, mystique->dwgreg.cxright, val); + break; + case REG_FXBNDRY: case REG_FXBNDRY+1: + WRITE8(addr, mystique->dwgreg.fxleft, val); + break; + case REG_FXBNDRY+2: case REG_FXBNDRY+3: + WRITE8(addr & 1, mystique->dwgreg.fxright, val); + break; + + case REG_YDSTLEN: case REG_YDSTLEN+1: + WRITE8(addr, mystique->dwgreg.length, val); + /* pclog("Write YDSTLEN+%i %i\n", addr&1, mystique->dwgreg.length); */ + break; + case REG_YDSTLEN+2: + mystique->dwgreg.ydst = (mystique->dwgreg.ydst & ~0xff) | val; + if (mystique->dwgreg.pitch & PITCH_YLIN) + mystique->dwgreg.ydst_lin = (mystique->dwgreg.ydst << 5) + mystique->dwgreg.ydstorg; + else { + mystique->dwgreg.ydst_lin = ((int32_t)(int16_t)mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; + mystique->dwgreg.selline = val & 7; + } + break; + case REG_YDSTLEN+3: + mystique->dwgreg.ydst = (mystique->dwgreg.ydst & 0xff) | (((int32_t)(int8_t)val) << 8); + if (mystique->dwgreg.pitch & PITCH_YLIN) + mystique->dwgreg.ydst_lin = (mystique->dwgreg.ydst << 5) + mystique->dwgreg.ydstorg; + else + mystique->dwgreg.ydst_lin = ((int32_t)(int16_t)mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; + break; + + case REG_XDST: case REG_XDST+1: + WRITE8(addr & 1, mystique->dwgreg.xdst, val); + break; + case REG_XDST+2: case REG_XDST+3: + break; + + case REG_YDSTORG: case REG_YDSTORG+1: case REG_YDSTORG+2: case REG_YDSTORG+3: + WRITE8(addr, mystique->dwgreg.ydstorg, val); + mystique->dwgreg.z_base = mystique->dwgreg.ydstorg*2 + mystique->dwgreg.zorg; + break; + case REG_YTOP: case REG_YTOP+1: case REG_YTOP+2: case REG_YTOP+3: + WRITE8(addr, mystique->dwgreg.ytop, val); + break; + case REG_YBOT: case REG_YBOT+1: case REG_YBOT+2: case REG_YBOT+3: + WRITE8(addr, mystique->dwgreg.ybot, val); + break; + + case REG_CXLEFT: case REG_CXLEFT+1: + WRITE8(addr, mystique->dwgreg.cxleft, val); + break; + case REG_CXLEFT+2: case REG_CXLEFT+3: + break; + case REG_CXRIGHT: case REG_CXRIGHT+1: + WRITE8(addr, mystique->dwgreg.cxright, val); + break; + case REG_CXRIGHT+2: case REG_CXRIGHT+3: + break; + + case REG_FXLEFT: case REG_FXLEFT+1: + WRITE8(addr, mystique->dwgreg.fxleft, val); + break; + case REG_FXLEFT+2: case REG_FXLEFT+3: + break; + case REG_FXRIGHT: case REG_FXRIGHT+1: + WRITE8(addr, mystique->dwgreg.fxright, val); + break; + case REG_FXRIGHT+2: case REG_FXRIGHT+3: + break; + + case REG_SECADDRESS: case REG_SECADDRESS+1: case REG_SECADDRESS+2: case REG_SECADDRESS+3: + WRITE8(addr, mystique->dma.secaddress, val); + mystique->dma.sec_state = 0; + break; + + case REG_TMR0: case REG_TMR0+1: case REG_TMR0+2: case REG_TMR0+3: + WRITE8(addr, mystique->dwgreg.tmr[0], val); + break; + case REG_TMR1: case REG_TMR1+1: case REG_TMR1+2: case REG_TMR1+3: + WRITE8(addr, mystique->dwgreg.tmr[1], val); + break; + case REG_TMR2: case REG_TMR2+1: case REG_TMR2+2: case REG_TMR2+3: + WRITE8(addr, mystique->dwgreg.tmr[2], val); + break; + case REG_TMR3: case REG_TMR3+1: case REG_TMR3+2: case REG_TMR3+3: + WRITE8(addr, mystique->dwgreg.tmr[3], val); + break; + case REG_TMR4: case REG_TMR4+1: case REG_TMR4+2: case REG_TMR4+3: + WRITE8(addr, mystique->dwgreg.tmr[4], val); + break; + case REG_TMR5: case REG_TMR5+1: case REG_TMR5+2: case REG_TMR5+3: + WRITE8(addr, mystique->dwgreg.tmr[5], val); + break; + case REG_TMR6: case REG_TMR6+1: case REG_TMR6+2: case REG_TMR6+3: + WRITE8(addr, mystique->dwgreg.tmr[6], val); + break; + case REG_TMR7: case REG_TMR7+1: case REG_TMR7+2: case REG_TMR7+3: + WRITE8(addr, mystique->dwgreg.tmr[7], val); + break; + case REG_TMR8: case REG_TMR8+1: case REG_TMR8+2: case REG_TMR8+3: + WRITE8(addr, mystique->dwgreg.tmr[8], val); + break; + + case REG_TEXORG: case REG_TEXORG+1: case REG_TEXORG+2: case REG_TEXORG+3: + WRITE8(addr, mystique->dwgreg.texorg, val); + break; + case REG_TEXWIDTH: case REG_TEXWIDTH+1: case REG_TEXWIDTH+2: case REG_TEXWIDTH+3: + WRITE8(addr, mystique->dwgreg.texwidth, val); + break; + case REG_TEXHEIGHT: case REG_TEXHEIGHT+1: case REG_TEXHEIGHT+2: case REG_TEXHEIGHT+3: + WRITE8(addr, mystique->dwgreg.texheight, val); + break; + case REG_TEXCTL: case REG_TEXCTL+1: case REG_TEXCTL+2: case REG_TEXCTL+3: + WRITE8(addr, mystique->dwgreg.texctl, val); + mystique->dwgreg.ta_key = (mystique->dwgreg.texctl & TEXCTL_TAKEY) ? 1 : 0; + mystique->dwgreg.ta_mask = (mystique->dwgreg.texctl & TEXCTL_TAMASK) ? 1 : 0; + break; + case REG_TEXTRANS: case REG_TEXTRANS+1: case REG_TEXTRANS+2: case REG_TEXTRANS+3: + WRITE8(addr, mystique->dwgreg.textrans, val); + break; + + case 0x1c28: case 0x1c29: case 0x1c2a: case 0x1c2b: + case 0x1c2c: case 0x1c2d: case 0x1c2e: case 0x1c2f: + case 0x1cc4: case 0x1cc5: case 0x1cc6: case 0x1cc7: + case 0x1cd4: case 0x1cd5: case 0x1cd6: case 0x1cd7: + case 0x1ce4: case 0x1ce5: case 0x1ce6: case 0x1ce7: + case 0x1cf4: case 0x1cf5: case 0x1cf6: case 0x1cf7: + break; + + case REG_OPMODE: + mystique->dwgreg.dmamod = (val >> 2) & 3; + mystique->dma.iload_state = 0; + break; + + default: + if ((addr & 0x3fff) >= 0x2c4c && (addr & 0x3fff) <= 0x2cff) + break; + break; + } + + if (start_blit) + mystique_start_blit(mystique); +} + + +static void +mystique_ctrl_write_b(uint32_t addr, uint8_t val, void *p) +{ + mystique_t *mystique = (mystique_t *)p; + svga_t *svga = &mystique->svga; + + if ((addr & 0x3fff) < 0x1c00) { + mystique_iload_write_b(addr, val, p); + return; + } + if ((addr & 0x3e00) == 0x1c00 || (addr & 0x3e00) == 0x2c00) { + if ((addr & 0x300) == 0x100) + mystique->blitter_submit_refcount++; + mystique_queue(mystique, addr & 0x3fff, val, FIFO_WRITE_CTRL_BYTE); + return; + } + + switch (addr & 0x3fff) { + case REG_ICLEAR: + if (val & ICLEAR_SOFTRAPICLR) { + mystique->status &= ~STATUS_SOFTRAPEN; + mystique_update_irqs(mystique); + } + if (val & ICLEAR_VLINEICLR) { + mystique->status &= ~STATUS_VLINEPEN; + mystique_update_irqs(mystique); + } + break; + case REG_ICLEAR+1: case REG_ICLEAR+2: case REG_ICLEAR+3: + break; + + case REG_IEN: + mystique->ien = val & 0x65; + break; + case REG_IEN+1: case REG_IEN+2: case REG_IEN+3: + break; + + case REG_OPMODE: + mystique->dmamod = (val >> 2) & 3; + mystique_queue(mystique, addr & 0x3fff, val, FIFO_WRITE_CTRL_BYTE); + break; + case REG_OPMODE+1: + mystique->dmadatasiz = val & 3; + break; + case REG_OPMODE+2: + mystique->dirdatasiz = val & 3; + break; + case REG_OPMODE+3: + break; + + case REG_PRIMADDRESS: case REG_PRIMADDRESS+1: case REG_PRIMADDRESS+2: case REG_PRIMADDRESS+3: + thread_wait_mutex(mystique->dma.lock); + WRITE8(addr, mystique->dma.primaddress, val); + mystique->dma.pri_state = 0; + thread_release_mutex(mystique->dma.lock); + break; + + case REG_DMAMAP: case REG_DMAMAP+0x1: case REG_DMAMAP+0x2: case REG_DMAMAP+0x3: + case REG_DMAMAP+0x4: case REG_DMAMAP+0x5: case REG_DMAMAP+0x6: case REG_DMAMAP+0x7: + case REG_DMAMAP+0x8: case REG_DMAMAP+0x9: case REG_DMAMAP+0xa: case REG_DMAMAP+0xb: + case REG_DMAMAP+0xc: case REG_DMAMAP+0xd: case REG_DMAMAP+0xe: case REG_DMAMAP+0xf: + mystique->dmamap[addr & 0xf] = val; + break; + + case REG_RST: case REG_RST+1: case REG_RST+2: case REG_RST+3: + wait_fifo_idle(mystique); + mystique->busy = 0; + mystique->blitter_submit_refcount = 0; + mystique->blitter_submit_dma_refcount = 0; + mystique->blitter_complete_refcount = 0; + mystique->dwgreg.iload_rem_count = 0; + mystique->status = STATUS_ENDPRDMASTS; + break; + + case REG_MISC: + svga_out(0x3c2, val, svga); + break; + + case REG_SEQ_IDX: + svga_out(0x3c4, val, svga); + break; + case REG_SEQ_DATA: + svga_out(0x3c5, val, svga); + break; + + case REG_CRTC_IDX: + mystique_out(0x3d4, val, mystique); + break; + case REG_CRTC_DATA: + mystique_out(0x3d5, val, mystique); + break; + + case REG_CRTCEXT_IDX: + mystique_out(0x3de, val, mystique); + break; + case REG_CRTCEXT_DATA: + mystique_out(0x3df, val, mystique); + break; + + case REG_CACHEFLUSH: + break; + + case REG_PALWTADD: + svga_out(0x3c8, val, svga); + mystique->xreg_idx = val; + break; + case REG_PALDATA: + svga_out(0x3c9, val, svga); + break; + case REG_PIXRDMSK: + svga_out(0x3c6, val, svga); + break; + case REG_PALRDADD: + svga_out(0x3c7, val, svga); + break; + + case REG_X_DATAREG: + mystique_write_xreg(mystique, mystique->xreg_idx, val); + break; + + case REG_CURPOSX: case REG_CURPOSX+1: + WRITE8(addr, mystique->cursor.pos_x, val); + svga->hwcursor.x = mystique->cursor.pos_x - 64; + break; + case REG_CURPOSY: case REG_CURPOSY+1: + WRITE8(addr & 1, mystique->cursor.pos_y, val); + svga->hwcursor.y = mystique->cursor.pos_y - 64; + break; + + case 0x1e50: case 0x1e51: case 0x1e52: case 0x1e53: + case 0x3c0b: case 0x3e02: case 0x3e08: + break; + + default: + if ((addr & 0x3fff) >= 0x2c4c && (addr & 0x3fff) <= 0x2cff) + break; + break; + } +} + + +static uint32_t +mystique_ctrl_read_l(uint32_t addr, void *p) +{ + uint32_t ret; + + if ((addr & 0x3fff) < 0x1c00) + return mystique_iload_read_l(addr, p); + + ret = mystique_ctrl_read_b(addr, p); + ret |= mystique_ctrl_read_b(addr+1, p) << 8; + ret |= mystique_ctrl_read_b(addr+2, p) << 16; + ret |= mystique_ctrl_read_b(addr+3, p) << 24; + + return ret; +} + + +static void +mystique_accel_ctrl_write_l(uint32_t addr, uint32_t val, void *p) +{ + mystique_t *mystique = (mystique_t *)p; + int start_blit = 0; + + if ((addr & 0x300) == 0x100) { + addr &= ~0x100; + start_blit = 1; + } + + switch (addr & 0x3ffc) { + case REG_DWGCTL: + mystique->dwgreg.dwgctrl = val; + break; + + case REG_ZORG: + mystique->dwgreg.zorg = val; + mystique->dwgreg.z_base = mystique->dwgreg.ydstorg*2 + mystique->dwgreg.zorg; + break; + + case REG_PLNWT: + mystique->dwgreg.plnwt = val; + break; + + case REG_SHIFT: + mystique->dwgreg.funcnt = val & 0xff; + mystique->dwgreg.xoff = val & 7; + mystique->dwgreg.yoff = (val >> 4) & 7; + mystique->dwgreg.stylelen = (val >> 16) & 0xff; + break; + + case REG_PITCH: + mystique->dwgreg.pitch = val & 0xffff; + if (mystique->dwgreg.pitch & PITCH_YLIN) + mystique->dwgreg.ydst_lin = (mystique->dwgreg.ydst << 5) + mystique->dwgreg.ydstorg; + else + mystique->dwgreg.ydst_lin = ((int32_t)(int16_t)mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; + break; + + case REG_YDST: + mystique->dwgreg.ydst = val & 0x3fffff; + if (mystique->dwgreg.pitch & PITCH_YLIN) { + mystique->dwgreg.ydst_lin = (mystique->dwgreg.ydst << 5) + mystique->dwgreg.ydstorg; + mystique->dwgreg.selline = val >> 29; + } else { + mystique->dwgreg.ydst_lin = ((int32_t)(int16_t)mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; + mystique->dwgreg.selline = val & 7; + } + break; + case REG_BCOL: + mystique->dwgreg.bcol = val; + break; + case REG_FCOL: + mystique->dwgreg.fcol = val; + break; + + case REG_SRC0: + mystique->dwgreg.src[0] = val; + if ((mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) == DWGCTRL_OPCODE_ILOAD) + blit_iload_write(mystique, mystique->dwgreg.src[0], 32); + break; + case REG_SRC1: + mystique->dwgreg.src[1] = val; + if ((mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) == DWGCTRL_OPCODE_ILOAD) + blit_iload_write(mystique, mystique->dwgreg.src[1], 32); + break; + case REG_SRC2: + mystique->dwgreg.src[2] = val; + if ((mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) == DWGCTRL_OPCODE_ILOAD) + blit_iload_write(mystique, mystique->dwgreg.src[2], 32); + break; + case REG_SRC3: + mystique->dwgreg.src[3] = val; + if ((mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) == DWGCTRL_OPCODE_ILOAD) + blit_iload_write(mystique, mystique->dwgreg.src[3], 32); + break; + + case REG_DMAPAD: + break; + + case REG_AR0: + mystique->dwgreg.ar[0] = val; + break; + case REG_AR1: + mystique->dwgreg.ar[1] = val; + break; + case REG_AR2: + mystique->dwgreg.ar[2] = val; + break; + case REG_AR3: + mystique->dwgreg.ar[3] = val; + break; + case REG_AR4: + mystique->dwgreg.ar[4] = val; + break; + case REG_AR5: + mystique->dwgreg.ar[5] = val; + break; + case REG_AR6: + mystique->dwgreg.ar[6] = val; + break; + + case REG_DR0: + mystique->dwgreg.dr[0] = val; + break; + case REG_DR2: + mystique->dwgreg.dr[2] = val; + break; + case REG_DR3: + mystique->dwgreg.dr[3] = val; + break; + case REG_DR4: + mystique->dwgreg.dr[4] = val; + break; + case REG_DR6: + mystique->dwgreg.dr[6] = val; + break; + case REG_DR7: + mystique->dwgreg.dr[7] = val; + break; + case REG_DR8: + mystique->dwgreg.dr[8] = val; + break; + case REG_DR10: + mystique->dwgreg.dr[10] = val; + break; + case REG_DR11: + mystique->dwgreg.dr[11] = val; + break; + case REG_DR12: + mystique->dwgreg.dr[12] = val; + break; + case REG_DR14: + mystique->dwgreg.dr[14] = val; + break; + case REG_DR15: + mystique->dwgreg.dr[15] = val; + break; + + case REG_SECEND: + mystique->dma.secend = val; + if (mystique->dma.state != DMA_STATE_SEC && (mystique->dma.secaddress & DMA_ADDR_MASK) != (mystique->dma.secend & DMA_ADDR_MASK)) + mystique->dma.state = DMA_STATE_SEC; + break; + + case REG_SOFTRAP: + mystique->dma.state = DMA_STATE_IDLE; + mystique->endprdmasts_pending = 1; + mystique->softrap_pending_val = val; + mystique->softrap_pending = 1; + break; + + default: + mystique_accel_ctrl_write_b(addr, val & 0xff, p); + mystique_accel_ctrl_write_b(addr+1, (val >> 8) & 0xff, p); + mystique_accel_ctrl_write_b(addr+2, (val >> 16) & 0xff, p); + mystique_accel_ctrl_write_b(addr+3, (val >> 24) & 0xff, p); + break; + } + + if (start_blit) + mystique_start_blit(mystique); +} + + +static void +mystique_ctrl_write_l(uint32_t addr, uint32_t val, void *p) +{ + mystique_t *mystique = (mystique_t *)p; + uint32_t reg_addr; + + if ((addr & 0x3fff) < 0x1c00) { + mystique_iload_write_l(addr, val, p); + return; + } + + if ((addr & 0x3e00) == 0x1c00 || (addr & 0x3e00) == 0x2c00) { + if ((addr & 0x300) == 0x100) + mystique->blitter_submit_refcount++; + mystique_queue(mystique, addr & 0x3fff, val, FIFO_WRITE_CTRL_LONG); + return; + } + + switch (addr & 0x3ffc) { + case REG_PRIMEND: + thread_wait_mutex(mystique->dma.lock); + mystique->dma.primend = val; + if (mystique->dma.state == DMA_STATE_IDLE && (mystique->dma.primaddress & DMA_ADDR_MASK) != (mystique->dma.primend & DMA_ADDR_MASK)) { + mystique->endprdmasts_pending = 0; + mystique->status &= ~STATUS_ENDPRDMASTS; + + mystique->dma.state = DMA_STATE_PRI; + mystique->dma.pri_state = 0; + wake_fifo_thread(mystique); + } + thread_release_mutex(mystique->dma.lock); + break; + + case REG_DWG_INDIR_WT: case REG_DWG_INDIR_WT+0x04: case REG_DWG_INDIR_WT+0x08: case REG_DWG_INDIR_WT+0x0c: + case REG_DWG_INDIR_WT+0x10: case REG_DWG_INDIR_WT+0x14: case REG_DWG_INDIR_WT+0x18: case REG_DWG_INDIR_WT+0x1c: + case REG_DWG_INDIR_WT+0x20: case REG_DWG_INDIR_WT+0x24: case REG_DWG_INDIR_WT+0x28: case REG_DWG_INDIR_WT+0x2c: + case REG_DWG_INDIR_WT+0x30: case REG_DWG_INDIR_WT+0x34: case REG_DWG_INDIR_WT+0x38: case REG_DWG_INDIR_WT+0x3c: + reg_addr = (mystique->dmamap[(addr >> 2) & 0xf] & 0x7f) << 2; + if (mystique->dmamap[(addr >> 2) & 0xf] & 0x80) + reg_addr += 0x2c00; + else + reg_addr += 0x1c00; + + if ((reg_addr & 0x300) == 0x100) + mystique->blitter_submit_refcount++; + + mystique_queue(mystique, reg_addr, val, FIFO_WRITE_CTRL_LONG); + break; + + default: + mystique_ctrl_write_b(addr, val & 0xff, p); + mystique_ctrl_write_b(addr+1, (val >> 8) & 0xff, p); + mystique_ctrl_write_b(addr+2, (val >> 16) & 0xff, p); + mystique_ctrl_write_b(addr+3, (val >> 24) & 0xff, p); + break; + } +} + + +static uint8_t +mystique_iload_read_b(uint32_t addr, void *p) +{ + mystique_t *mystique = (mystique_t *)p; + + wait_fifo_idle(mystique); + + if (!mystique->busy) + return 0xff; + + return blit_idump_read(mystique); +} + + +static uint32_t +mystique_iload_read_l(uint32_t addr, void *p) +{ + mystique_t *mystique = (mystique_t *)p; + + wait_fifo_idle(mystique); + + if (!mystique->busy) + return 0xffffffff; + + mystique->dwgreg.words++; + return blit_idump_read(mystique); +} + + +static void +mystique_iload_write_b(uint32_t addr, uint8_t val, void *p) +{ + +} + + +static void +mystique_iload_write_l(uint32_t addr, uint32_t val, void *p) +{ + mystique_t *mystique = (mystique_t *)p; + + mystique_queue(mystique, 0, val, FIFO_WRITE_ILOAD_LONG); +} + +static void +mystique_accel_iload_write_l(uint32_t addr, uint32_t val, void *p) +{ + mystique_t *mystique = (mystique_t *)p; + + switch (mystique->dwgreg.dmamod) { + case DMA_MODE_REG: + if (mystique->dma.iload_state == 0) { + mystique->dma.iload_header = val; + mystique->dma.iload_state = 1; + } else { + uint32_t reg_addr = (mystique->dma.iload_header & 0x7f) << 2; + if (mystique->dma.iload_header & 0x80) + reg_addr += 0x2c00; + else + reg_addr += 0x1c00; + + if ((reg_addr & 0x300) == 0x100) + mystique->blitter_submit_dma_refcount++; + mystique_accel_ctrl_write_l(reg_addr, val, mystique); + + mystique->dma.iload_header >>= 8; + mystique->dma.iload_state = (mystique->dma.iload_state == 4) ? 0 : (mystique->dma.iload_state+1); + } + break; + + case DMA_MODE_BLIT: + if (!mystique->busy) + fatal("mystique_iload_write_l: !busy\n"); + blit_iload_write(mystique, val, 32); + break; + + /* default: + pclog("ILOAD write DMAMOD %i\n", mystique->dwgreg.dmamod); */ + } +} + + +static void +run_dma(mystique_t *mystique) +{ + int words_transferred = 0; + + thread_wait_mutex(mystique->dma.lock); + + if (mystique->dma.state == DMA_STATE_IDLE) { + thread_release_mutex(mystique->dma.lock); + return; + } + + while (words_transferred < DMA_MAX_WORDS && mystique->dma.state != DMA_STATE_IDLE) { + switch (mystique->dma.state) { + case DMA_STATE_PRI: + switch (mystique->dma.primaddress & DMA_MODE_MASK) { + case DMA_MODE_REG: + if (mystique->dma.pri_state == 0) { + mystique->dma.pri_header = *(uint32_t *)&ram[mystique->dma.primaddress & DMA_ADDR_MASK]; + mystique->dma.primaddress += 4; + } + + if ((mystique->dma.pri_header & 0xff) != 0x15) { + uint32_t val = *(uint32_t *)&ram[mystique->dma.primaddress & DMA_ADDR_MASK]; + uint32_t reg_addr; + + mystique->dma.primaddress += 4; + + reg_addr = (mystique->dma.pri_header & 0x7f) << 2; + if (mystique->dma.pri_header & 0x80) + reg_addr += 0x2c00; + else + reg_addr += 0x1c00; + + if ((reg_addr & 0x300) == 0x100) + mystique->blitter_submit_dma_refcount++; + + mystique_accel_ctrl_write_l(reg_addr, val, mystique); + } + + mystique->dma.pri_header >>= 8; + mystique->dma.pri_state = (mystique->dma.pri_state + 1) & 3; + + words_transferred++; + if (mystique->dma.state == DMA_STATE_SEC) + mystique->dma.pri_state = 0; + else if ((mystique->dma.primaddress & DMA_ADDR_MASK) == (mystique->dma.primend & DMA_ADDR_MASK)) { + mystique->endprdmasts_pending = 1; + mystique->dma.state = DMA_STATE_IDLE; + } break; - break; - } -// pclog("mcrb: addr=%08x ret=%02x\n", addr, ret); - return ret; -} + default: + fatal("DMA_STATE_PRI: mode %i\n", mystique->dma.primaddress & DMA_MODE_MASK); + } + break; -static void mystique_accel_ctrl_write_b(uint32_t addr, uint8_t val, void *p) -{ - mystique_t *mystique = (mystique_t *)p; - int start_blit = 0; - int x; + case DMA_STATE_SEC: + switch (mystique->dma.secaddress & DMA_MODE_MASK) { + case DMA_MODE_REG: + if (mystique->dma.sec_state == 0) { + mystique->dma.sec_header = *(uint32_t *)&ram[mystique->dma.secaddress & DMA_ADDR_MASK]; + mystique->dma.secaddress += 4; + } -// pclog("mystique accel addr=%04x val=%02x\n", addr & 0x3fff, val); + uint32_t val = *(uint32_t *)&ram[mystique->dma.secaddress & DMA_ADDR_MASK]; + uint32_t reg_addr; - if ((addr & 0x300) == 0x100) { - addr &= ~0x100; - start_blit = 1; - } + mystique->dma.secaddress += 4; - switch (addr & 0x3fff) - { - case REG_MACCESS: case REG_MACCESS+1: case REG_MACCESS+2: case REG_MACCESS+3: - WRITE8(addr, mystique->maccess, val); - mystique->dwgreg.dither = mystique->maccess >> 30; - break; - - case REG_MCTLWTST: case REG_MCTLWTST+1: case REG_MCTLWTST+2: case REG_MCTLWTST+3: - WRITE8(addr, mystique->mctlwtst, val); - break; - - - case REG_PAT0: case REG_PAT0+1: case REG_PAT0+2: case REG_PAT0+3: - case REG_PAT1: case REG_PAT1+1: case REG_PAT1+2: case REG_PAT1+3: - for (x = 0; x < 8; x++) - mystique->dwgreg.pattern[addr & 7][x] = val & (1 << (7-x)); - break; - - case REG_XYSTRT: case REG_XYSTRT+1: - WRITE8(addr&1, mystique->dwgreg.ar[5], val); - if (mystique->dwgreg.ar[5] & 0x8000) - mystique->dwgreg.ar[5] |= 0xffff8000; - else - mystique->dwgreg.ar[5] &= ~0xffff8000; - WRITE8(addr&1, mystique->dwgreg.xdst, val); - break; - case REG_XYSTRT+2: case REG_XYSTRT+3: - WRITE8(addr & 1, mystique->dwgreg.ar[6], val); - if (mystique->dwgreg.ar[6] & 0x8000) - mystique->dwgreg.ar[6] |= 0xffff8000; - else - mystique->dwgreg.ar[6] &= ~0xffff8000; - WRITE8(addr & 1, mystique->dwgreg.ydst, val); - mystique->dwgreg.ydst_lin = ((int32_t)(int16_t)mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; - break; - - case REG_XYEND: case REG_XYEND+1: - WRITE8(addr&1, mystique->dwgreg.ar[0], val); - if (mystique->dwgreg.ar[0] & 0x8000) - mystique->dwgreg.ar[0] |= 0xffff8000; - else - mystique->dwgreg.ar[0] &= ~0xffff8000; -// pclog("XYEND AR[0]=%08x\n", mystique->dwgreg.ar[0]); - break; - case REG_XYEND+2: case REG_XYEND+3: - WRITE8(addr & 1, mystique->dwgreg.ar[2], val); - if (mystique->dwgreg.ar[2] & 0x8000) - mystique->dwgreg.ar[2] |= 0xffff8000; - else - mystique->dwgreg.ar[2] &= ~0xffff8000; - break; - - case REG_SGN: - mystique->dwgreg.sgn.sdydxl = val & SGN_SDYDXL; - mystique->dwgreg.sgn.scanleft = val & SGN_SCANLEFT; - mystique->dwgreg.sgn.sdxl = val & SGN_SDXL; - mystique->dwgreg.sgn.sdy = val & SGN_SDY; - mystique->dwgreg.sgn.sdxr = val & SGN_SDXR; - break; - case REG_SGN+1: case REG_SGN+2: case REG_SGN+3: - break; - - case REG_LEN: case REG_LEN+1: - WRITE8(addr, mystique->dwgreg.length, val); - break; - case REG_LEN+2: - break; - case REG_LEN+3: - mystique->dwgreg.beta = val >> 4; - if (!mystique->dwgreg.beta) - mystique->dwgreg.beta = 16; - break; - - case REG_CXBNDRY: case REG_CXBNDRY+1: - WRITE8(addr, mystique->dwgreg.cxleft, val); - break; - case REG_CXBNDRY+2: case REG_CXBNDRY+3: - WRITE8(addr & 1, mystique->dwgreg.cxright, val); - break; - case REG_FXBNDRY: case REG_FXBNDRY+1: - WRITE8(addr, mystique->dwgreg.fxleft, val); - break; - case REG_FXBNDRY+2: case REG_FXBNDRY+3: - WRITE8(addr & 1, mystique->dwgreg.fxright, val); - break; - - case REG_YDSTLEN: case REG_YDSTLEN+1: - WRITE8(addr, mystique->dwgreg.length, val); -// pclog("Write YDSTLEN+%i %i\n", addr&1, mystique->dwgreg.length); - break; - case REG_YDSTLEN+2: - mystique->dwgreg.ydst = (mystique->dwgreg.ydst & ~0xff) | val; - if (mystique->dwgreg.pitch & PITCH_YLIN) - mystique->dwgreg.ydst_lin = (mystique->dwgreg.ydst << 5) + mystique->dwgreg.ydstorg; - else { - mystique->dwgreg.ydst_lin = ((int32_t)(int16_t)mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; - mystique->dwgreg.selline = val & 7; - } -// pclog("Write YDSTLEN+2 %i %08x\n", mystique->dwgreg.ydst, mystique->dwgreg.ydst_lin); - break; - case REG_YDSTLEN+3: - mystique->dwgreg.ydst = (mystique->dwgreg.ydst & 0xff) | (((int32_t)(int8_t)val) << 8); - if (mystique->dwgreg.pitch & PITCH_YLIN) - mystique->dwgreg.ydst_lin = (mystique->dwgreg.ydst << 5) + mystique->dwgreg.ydstorg; - else - mystique->dwgreg.ydst_lin = ((int32_t)(int16_t)mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; -// pclog("Write YDSTLEN+3 %i %08x\n", mystique->dwgreg.ydst, mystique->dwgreg.ydst_lin); - break; - - case REG_XDST: case REG_XDST+1: - WRITE8(addr & 1, mystique->dwgreg.xdst, val); - break; - case REG_XDST+2: case REG_XDST+3: - break; - - case REG_YDSTORG: case REG_YDSTORG+1: case REG_YDSTORG+2: case REG_YDSTORG+3: - WRITE8(addr, mystique->dwgreg.ydstorg, val); - mystique->dwgreg.z_base = mystique->dwgreg.ydstorg*2 + mystique->dwgreg.zorg; -// pclog("ydstorg=%06x z_base=%06x\n", mystique->dwgreg.ydstorg, mystique->dwgreg.z_base); - break; - case REG_YTOP: case REG_YTOP+1: case REG_YTOP+2: case REG_YTOP+3: - WRITE8(addr, mystique->dwgreg.ytop, val); - break; - case REG_YBOT: case REG_YBOT+1: case REG_YBOT+2: case REG_YBOT+3: - WRITE8(addr, mystique->dwgreg.ybot, val); - break; - - case REG_CXLEFT: case REG_CXLEFT+1: - WRITE8(addr, mystique->dwgreg.cxleft, val); - break; - case REG_CXLEFT+2: case REG_CXLEFT+3: - break; - case REG_CXRIGHT: case REG_CXRIGHT+1: - WRITE8(addr, mystique->dwgreg.cxright, val); - break; - case REG_CXRIGHT+2: case REG_CXRIGHT+3: - break; - - case REG_FXLEFT: case REG_FXLEFT+1: - WRITE8(addr, mystique->dwgreg.fxleft, val); - break; - case REG_FXLEFT+2: case REG_FXLEFT+3: - break; - case REG_FXRIGHT: case REG_FXRIGHT+1: - WRITE8(addr, mystique->dwgreg.fxright, val); - break; - case REG_FXRIGHT+2: case REG_FXRIGHT+3: - break; - - case REG_SECADDRESS: case REG_SECADDRESS+1: case REG_SECADDRESS+2: case REG_SECADDRESS+3: - WRITE8(addr, mystique->dma.secaddress, val); - mystique->dma.sec_state = 0; - break; - - case REG_TMR0: case REG_TMR0+1: case REG_TMR0+2: case REG_TMR0+3: - WRITE8(addr, mystique->dwgreg.tmr[0], val); - break; - case REG_TMR1: case REG_TMR1+1: case REG_TMR1+2: case REG_TMR1+3: - WRITE8(addr, mystique->dwgreg.tmr[1], val); - break; - case REG_TMR2: case REG_TMR2+1: case REG_TMR2+2: case REG_TMR2+3: - WRITE8(addr, mystique->dwgreg.tmr[2], val); - break; - case REG_TMR3: case REG_TMR3+1: case REG_TMR3+2: case REG_TMR3+3: - WRITE8(addr, mystique->dwgreg.tmr[3], val); - break; - case REG_TMR4: case REG_TMR4+1: case REG_TMR4+2: case REG_TMR4+3: - WRITE8(addr, mystique->dwgreg.tmr[4], val); - break; - case REG_TMR5: case REG_TMR5+1: case REG_TMR5+2: case REG_TMR5+3: - WRITE8(addr, mystique->dwgreg.tmr[5], val); - break; - case REG_TMR6: case REG_TMR6+1: case REG_TMR6+2: case REG_TMR6+3: - WRITE8(addr, mystique->dwgreg.tmr[6], val); - break; - case REG_TMR7: case REG_TMR7+1: case REG_TMR7+2: case REG_TMR7+3: - WRITE8(addr, mystique->dwgreg.tmr[7], val); - break; - case REG_TMR8: case REG_TMR8+1: case REG_TMR8+2: case REG_TMR8+3: - WRITE8(addr, mystique->dwgreg.tmr[8], val); - break; - - case REG_TEXORG: case REG_TEXORG+1: case REG_TEXORG+2: case REG_TEXORG+3: - WRITE8(addr, mystique->dwgreg.texorg, val); -// if ((addr & 3) == 3) pclog("texorg=%08x\n", mystique->dwgreg.texorg); - break; - case REG_TEXWIDTH: case REG_TEXWIDTH+1: case REG_TEXWIDTH+2: case REG_TEXWIDTH+3: - WRITE8(addr, mystique->dwgreg.texwidth, val); -// if ((addr & 3) == 3) pclog("texwith=%08x\n", mystique->dwgreg.texwidth); - break; - case REG_TEXHEIGHT: case REG_TEXHEIGHT+1: case REG_TEXHEIGHT+2: case REG_TEXHEIGHT+3: - WRITE8(addr, mystique->dwgreg.texheight, val); -// if ((addr & 3) == 3) pclog("texheight=%08x %i %i\n", mystique->dwgreg.texheight, mystique->dwgreg.texheight&0x3f, (int)(((mystique->dwgreg.texheight >> 9) & 0x3f) | ((mystique->dwgreg.texheight & (1 << 14)) ? 0xffffffc0 : 0))); - break; - case REG_TEXCTL: case REG_TEXCTL+1: case REG_TEXCTL+2: case REG_TEXCTL+3: - WRITE8(addr, mystique->dwgreg.texctl, val); -// if ((addr & 3) == 3) pclog("texctl=%08x\n", mystique->dwgreg.texctl); - mystique->dwgreg.ta_key = (mystique->dwgreg.texctl & TEXCTL_TAKEY) ? 1 : 0; - mystique->dwgreg.ta_mask = (mystique->dwgreg.texctl & TEXCTL_TAMASK) ? 1 : 0; - break; - case REG_TEXTRANS: case REG_TEXTRANS+1: case REG_TEXTRANS+2: case REG_TEXTRANS+3: - WRITE8(addr, mystique->dwgreg.textrans, val); -// /*if ((addr & 3) == 3) */pclog("textrans=%08x\n", mystique->dwgreg.textrans); - break; - - case 0x1c28: case 0x1c29: case 0x1c2a: case 0x1c2b: - case 0x1c2c: case 0x1c2d: case 0x1c2e: case 0x1c2f: - case 0x1cc4: case 0x1cc5: case 0x1cc6: case 0x1cc7: - case 0x1cd4: case 0x1cd5: case 0x1cd6: case 0x1cd7: - case 0x1ce4: case 0x1ce5: case 0x1ce6: case 0x1ce7: - case 0x1cf4: case 0x1cf5: case 0x1cf6: case 0x1cf7: - break; - - case REG_OPMODE: - mystique->dwgreg.dmamod = (val >> 2) & 3; - mystique->dma.iload_state = 0; - break; - - default: - if ((addr & 0x3fff) >= 0x2c4c && (addr & 0x3fff) <= 0x2cff) - break; -// pclog("Write MGA accel control %08x %02x\n", addr & 0x3fff, val); - break; - } - - if (start_blit) - mystique_start_blit(mystique); -} - -static void mystique_ctrl_write_b(uint32_t addr, uint8_t val, void *p) -{ - mystique_t *mystique = (mystique_t *)p; - svga_t *svga = &mystique->svga; - -// pclog("mystique addr=%04x val=%02x\n", addr & 0x3fff, val); - - if ((addr & 0x3fff) < 0x1c00) { - mystique_iload_write_b(addr, val, p); - return; - } - if ((addr & 0x3e00) == 0x1c00 || (addr & 0x3e00) == 0x2c00) { - if ((addr & 0x300) == 0x100) - mystique->blitter_submit_refcount++; -// pclog("mystique queue addr=%04x val=%02x\n", addr & 0x3fff, val); - mystique_queue(mystique, addr & 0x3fff, val, FIFO_WRITE_CTRL_BYTE); - return; - } - - switch (addr & 0x3fff) - { - case REG_ICLEAR: -// pclog("ICLEAR %02x\n", val); - if (val & ICLEAR_SOFTRAPICLR) { - mystique->status &= ~STATUS_SOFTRAPEN; - mystique_update_irqs(mystique); - } - if (val & ICLEAR_VLINEICLR) { - mystique->status &= ~STATUS_VLINEPEN; - mystique_update_irqs(mystique); - } - break; - case REG_ICLEAR+1: case REG_ICLEAR+2: case REG_ICLEAR+3: - break; - - case REG_IEN: - mystique->ien = val & 0x65; -// pclog("Write IEN %02x\n", val); - break; - case REG_IEN+1: case REG_IEN+2: case REG_IEN+3: - break; - - case REG_OPMODE: - mystique->dmamod = (val >> 2) & 3; -// pclog("OPMODE\n"); - mystique_queue(mystique, addr & 0x3fff, val, FIFO_WRITE_CTRL_BYTE); - break; - case REG_OPMODE+1: - mystique->dmadatasiz = val & 3; - break; - case REG_OPMODE+2: - mystique->dirdatasiz = val & 3; - break; - case REG_OPMODE+3: - break; - - case REG_PRIMADDRESS: case REG_PRIMADDRESS+1: case REG_PRIMADDRESS+2: case REG_PRIMADDRESS+3: - thread_wait_mutex(mystique->dma.lock); - WRITE8(addr, mystique->dma.primaddress, val); - mystique->dma.pri_state = 0; -// pclog("PRIMADDRESS write %04x %08x\n", addr, mystique->dma.primaddress); - thread_release_mutex(mystique->dma.lock); - break; - - case REG_DMAMAP: case REG_DMAMAP+0x1: case REG_DMAMAP+0x2: case REG_DMAMAP+0x3: - case REG_DMAMAP+0x4: case REG_DMAMAP+0x5: case REG_DMAMAP+0x6: case REG_DMAMAP+0x7: - case REG_DMAMAP+0x8: case REG_DMAMAP+0x9: case REG_DMAMAP+0xa: case REG_DMAMAP+0xb: - case REG_DMAMAP+0xc: case REG_DMAMAP+0xd: case REG_DMAMAP+0xe: case REG_DMAMAP+0xf: - mystique->dmamap[addr & 0xf] = val; - break; - - case REG_RST: case REG_RST+1: case REG_RST+2: case REG_RST+3: -// pclog("Write REG_RST\n"); - wait_fifo_idle(mystique); - mystique->busy = 0; - mystique->blitter_submit_refcount = 0; - mystique->blitter_submit_dma_refcount = 0; - mystique->blitter_complete_refcount = 0; - mystique->dwgreg.iload_rem_count = 0; - mystique->status = STATUS_ENDPRDMASTS; - break; - - case REG_MISC: - svga_out(0x3c2, val, svga); - break; - - case REG_SEQ_IDX: - svga_out(0x3c4, val, svga); - break; - case REG_SEQ_DATA: - svga_out(0x3c5, val, svga); - break; - - case REG_CRTC_IDX: - mystique_out(0x3d4, val, mystique); - break; - case REG_CRTC_DATA: - mystique_out(0x3d5, val, mystique); - break; - - case REG_CRTCEXT_IDX: - mystique_out(0x3de, val, mystique); - break; - case REG_CRTCEXT_DATA: - mystique_out(0x3df, val, mystique); - break; - - case REG_CACHEFLUSH: - break; - - case REG_PALWTADD: - svga_out(0x3c8, val, svga); - mystique->xreg_idx = val; - break; - case REG_PALDATA: - svga_out(0x3c9, val, svga); - break; - case REG_PIXRDMSK: - svga_out(0x3c6, val, svga); - break; - case REG_PALRDADD: - svga_out(0x3c7, val, svga); - break; - - case REG_X_DATAREG: - mystique_write_xreg(mystique, mystique->xreg_idx, val); - break; - - case REG_CURPOSX: case REG_CURPOSX+1: - WRITE8(addr, mystique->cursor.pos_x, val); - svga->hwcursor.x = mystique->cursor.pos_x - 64; - break; - case REG_CURPOSY: case REG_CURPOSY+1: - WRITE8(addr & 1, mystique->cursor.pos_y, val); - svga->hwcursor.y = mystique->cursor.pos_y - 64; - break; - - case 0x1e50: case 0x1e51: case 0x1e52: case 0x1e53: - case 0x3c0b: case 0x3e02: case 0x3e08: - break; - - default: - if ((addr & 0x3fff) >= 0x2c4c && (addr & 0x3fff) <= 0x2cff) - break; -// pclog("Write MGA control %08x %02x\n", addr & 0x3fff, val); - break; - } -} - -static uint32_t mystique_ctrl_read_l(uint32_t addr, void *p) -{ - uint32_t ret; - -// pclog("mystique_ctrl_read_l: addr=%08x %08x\n", addr, cpu_state.pc); - if ((addr & 0x3fff) < 0x1c00) - return mystique_iload_read_l(addr, p); - - ret = mystique_ctrl_read_b(addr, p); - ret |= mystique_ctrl_read_b(addr+1, p) << 8; - ret |= mystique_ctrl_read_b(addr+2, p) << 16; - ret |= mystique_ctrl_read_b(addr+3, p) << 24; -// pclog("mcrl: addr=%08x ret=%08x %08x\n", addr, ret, mystique->status); - - return ret; -} - -static void mystique_accel_ctrl_write_l(uint32_t addr, uint32_t val, void *p) -{ - mystique_t *mystique = (mystique_t *)p; - int start_blit = 0; - -// pclog("mystique accel addr=%04x val=%08x\n", addr & 0x3fff, val); - if ((addr & 0x300) == 0x100) { - addr &= ~0x100; - start_blit = 1; - } - - switch (addr & 0x3ffc) - { - case REG_DWGCTL: -// pclog(" dwgctrl write %08x %08x\n", addr2, val); - mystique->dwgreg.dwgctrl = val; - break; - - case REG_ZORG: - mystique->dwgreg.zorg = val; - mystique->dwgreg.z_base = mystique->dwgreg.ydstorg*2 + mystique->dwgreg.zorg; -// pclog("zorg=%08x z_base=%08x\n", mystique->dwgreg.zorg, mystique->dwgreg.z_base); - break; - - case REG_PLNWT: - mystique->dwgreg.plnwt = val; - break; - - case REG_SHIFT: - mystique->dwgreg.funcnt = val & 0xff; - mystique->dwgreg.xoff = val & 7; - mystique->dwgreg.yoff = (val >> 4) & 7; - mystique->dwgreg.stylelen = (val >> 16) & 0xff; - break; - - case REG_PITCH: - mystique->dwgreg.pitch = val & 0xffff; - if (mystique->dwgreg.pitch & PITCH_YLIN) - mystique->dwgreg.ydst_lin = (mystique->dwgreg.ydst << 5) + mystique->dwgreg.ydstorg; - else - mystique->dwgreg.ydst_lin = ((int32_t)(int16_t)mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; -// pclog("pitch=%04x %i\n", mystique->dwgreg.pitch, addr&1); - break; - - case REG_YDST: - mystique->dwgreg.ydst = val & 0x3fffff; - if (mystique->dwgreg.pitch & PITCH_YLIN) { - mystique->dwgreg.ydst_lin = (mystique->dwgreg.ydst << 5) + mystique->dwgreg.ydstorg; - mystique->dwgreg.selline = val >> 29; - } else { - mystique->dwgreg.ydst_lin = ((int32_t)(int16_t)mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; - mystique->dwgreg.selline = val & 7; - } -// pclog("ydst=%i ydsth=%08x %08x pitch=%08x\n", mystique->dwgreg.ydst, mystique->dwgreg.ydst, mystique->dwgreg.ydst_lin, mystique->dwgreg.pitch); - break; - case REG_BCOL: - mystique->dwgreg.bcol = val; -// pclog("BCOL %i %02x\n", addr & 3, val); - break; - case REG_FCOL: - mystique->dwgreg.fcol = val; -// pclog("FCOL %i %02x\n", addr & 3, val); - break; - - case REG_SRC0: - mystique->dwgreg.src[0] = val; - if ((mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) == DWGCTRL_OPCODE_ILOAD) - blit_iload_write(mystique, mystique->dwgreg.src[0], 32); - break; - case REG_SRC1: - mystique->dwgreg.src[1] = val; - if ((mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) == DWGCTRL_OPCODE_ILOAD) - blit_iload_write(mystique, mystique->dwgreg.src[1], 32); - break; - case REG_SRC2: - mystique->dwgreg.src[2] = val; - if ((mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) == DWGCTRL_OPCODE_ILOAD) - blit_iload_write(mystique, mystique->dwgreg.src[2], 32); - break; - case REG_SRC3: - mystique->dwgreg.src[3] = val; - if ((mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) == DWGCTRL_OPCODE_ILOAD) - blit_iload_write(mystique, mystique->dwgreg.src[3], 32); - break; - - case REG_DMAPAD: - break; - - case REG_AR0: - mystique->dwgreg.ar[0] = val; -// pclog("AR[0]=%08x\n", mystique->dwgreg.ar[0]); - break; - case REG_AR1: - mystique->dwgreg.ar[1] = val; - break; - case REG_AR2: - mystique->dwgreg.ar[2] = val; - break; - case REG_AR3: - mystique->dwgreg.ar[3] = val; -// pclog("AR[3]=%08x\n", mystique->dwgreg.ar[3]); - break; - case REG_AR4: - mystique->dwgreg.ar[4] = val; - break; - case REG_AR5: - mystique->dwgreg.ar[5] = val; - break; - case REG_AR6: - mystique->dwgreg.ar[6] = val; - break; - - case REG_DR0: - mystique->dwgreg.dr[0] = val; - break; - case REG_DR2: - mystique->dwgreg.dr[2] = val; - break; - case REG_DR3: - mystique->dwgreg.dr[3] = val; - break; - case REG_DR4: - mystique->dwgreg.dr[4] = val; -// if ((addr & 3) == 3) pclog("DR[4]=%08x\n", mystique->dwgreg.dr[4]); - break; - case REG_DR6: - mystique->dwgreg.dr[6] = val; -// if ((addr & 3) == 3) pclog("DR[6]=%08x\n", mystique->dwgreg.dr[6]); - break; - case REG_DR7: - mystique->dwgreg.dr[7] = val; -// if ((addr & 3) == 3) pclog("DR[7]=%08x\n", mystique->dwgreg.dr[7]); - break; - case REG_DR8: - mystique->dwgreg.dr[8] = val; - break; - case REG_DR10: - mystique->dwgreg.dr[10] = val; - break; - case REG_DR11: - mystique->dwgreg.dr[11] = val; - break; - case REG_DR12: - mystique->dwgreg.dr[12] = val; - break; - case REG_DR14: - mystique->dwgreg.dr[14] = val; - break; - case REG_DR15: - mystique->dwgreg.dr[15] = val; - break; - - case REG_SECEND: -// pclog("SECEND write %08x\n", val); - mystique->dma.secend = val; - if (mystique->dma.state != DMA_STATE_SEC && (mystique->dma.secaddress & DMA_ADDR_MASK) != (mystique->dma.secend & DMA_ADDR_MASK)) { -// pclog(" DMA state STATE_SEC\n"); - mystique->dma.state = DMA_STATE_SEC; - } - break; - - case REG_SOFTRAP: -// pclog("SOFTRAP\n"); -/* mystique->dma.secaddress = val;*/ - mystique->dma.state = DMA_STATE_IDLE; - mystique->endprdmasts_pending = 1; - mystique->softrap_pending_val = val; - mystique->softrap_pending = 1; -// pclog("SOFTRAP DMA state STATE_IDLE\n"); -/* mystique->status |= STATUS_SOFTRAPEN; - mystique_update_irqs(mystique);*/ - break; - - default: - mystique_accel_ctrl_write_b(addr, val & 0xff, p); - mystique_accel_ctrl_write_b(addr+1, (val >> 8) & 0xff, p); - mystique_accel_ctrl_write_b(addr+2, (val >> 16) & 0xff, p); - mystique_accel_ctrl_write_b(addr+3, (val >> 24) & 0xff, p); - break; - } - - if (start_blit) - mystique_start_blit(mystique); -} - -static void mystique_ctrl_write_l(uint32_t addr, uint32_t val, void *p) -{ - mystique_t *mystique = (mystique_t *)p; - uint32_t reg_addr; - -// pclog("mystique addr=%04x val=%08x\n", addr & 0x3fff, val); - if ((addr & 0x3fff) < 0x1c00) { - mystique_iload_write_l(addr, val, p); - return; - } - - if ((addr & 0x3e00) == 0x1c00 || (addr & 0x3e00) == 0x2c00) { - if ((addr & 0x300) == 0x100) - mystique->blitter_submit_refcount++; -// pclog("mystique queue addr=%04x val=%08x\n", addr & 0x3fff, val); - mystique_queue(mystique, addr & 0x3fff, val, FIFO_WRITE_CTRL_LONG); - return; - } - - switch (addr & 0x3ffc) - { - case REG_PRIMEND: - thread_wait_mutex(mystique->dma.lock); -// pclog("PRIMEND write %08x\n", val); - mystique->dma.primend = val; - if (mystique->dma.state == DMA_STATE_IDLE && (mystique->dma.primaddress & DMA_ADDR_MASK) != (mystique->dma.primend & DMA_ADDR_MASK)) { -// pclog("Clear DMA end flag\n"); - mystique->endprdmasts_pending = 0; - mystique->status &= ~STATUS_ENDPRDMASTS; - - mystique->dma.state = DMA_STATE_PRI; -// pclog(" DMA state STATE_PRI\n"); - mystique->dma.pri_state = 0; - wake_fifo_thread(mystique); - } - thread_release_mutex(mystique->dma.lock); - break; - - case REG_DWG_INDIR_WT: case REG_DWG_INDIR_WT+0x04: case REG_DWG_INDIR_WT+0x08: case REG_DWG_INDIR_WT+0x0c: - case REG_DWG_INDIR_WT+0x10: case REG_DWG_INDIR_WT+0x14: case REG_DWG_INDIR_WT+0x18: case REG_DWG_INDIR_WT+0x1c: - case REG_DWG_INDIR_WT+0x20: case REG_DWG_INDIR_WT+0x24: case REG_DWG_INDIR_WT+0x28: case REG_DWG_INDIR_WT+0x2c: - case REG_DWG_INDIR_WT+0x30: case REG_DWG_INDIR_WT+0x34: case REG_DWG_INDIR_WT+0x38: case REG_DWG_INDIR_WT+0x3c: - reg_addr = (mystique->dmamap[(addr >> 2) & 0xf] & 0x7f) << 2; - if (mystique->dmamap[(addr >> 2) & 0xf] & 0x80) - reg_addr += 0x2c00; - else - reg_addr += 0x1c00; - - if ((reg_addr & 0x300) == 0x100) - mystique->blitter_submit_refcount++; - -// pclog("mystique queue dwg addr=%04x val=%08x\n", reg_addr, val); - mystique_queue(mystique, reg_addr, val, FIFO_WRITE_CTRL_LONG); - break; - - default: - mystique_ctrl_write_b(addr, val & 0xff, p); - mystique_ctrl_write_b(addr+1, (val >> 8) & 0xff, p); - mystique_ctrl_write_b(addr+2, (val >> 16) & 0xff, p); - mystique_ctrl_write_b(addr+3, (val >> 24) & 0xff, p); - break; - } -} - -static uint8_t mystique_iload_read_b(uint32_t addr, void *p) -{ - mystique_t *mystique = (mystique_t *)p; - - wait_fifo_idle(mystique); - - if (!mystique->busy) - return 0xff; - -// pclog("Readb MGA ILOAD %08x\n", addr); - return blit_idump_read(mystique); -} - -static uint32_t mystique_iload_read_l(uint32_t addr, void *p) -{ - mystique_t *mystique = (mystique_t *)p; - - wait_fifo_idle(mystique); - - if (!mystique->busy) - return 0xffffffff; - -// pclog("Readl MGA ILOAD %08x %i\n", addr, mystique->dwgreg.words); - mystique->dwgreg.words++; - return blit_idump_read(mystique); -} - -static void mystique_iload_write_b(uint32_t addr, uint8_t val, void *p) -{ - -} - -static void mystique_iload_write_l(uint32_t addr, uint32_t val, void *p) -{ - mystique_t *mystique = (mystique_t *)p; - -// pclog("mystique queue iload addr=%04x val=%08x\n", addr, val); - mystique_queue(mystique, 0, val, FIFO_WRITE_ILOAD_LONG); -} - -static void mystique_accel_iload_write_l(uint32_t addr, uint32_t val, void *p) -{ - mystique_t *mystique = (mystique_t *)p; - -// pclog(" Write ILOAD %08x %i %i\n", val, mystique->dwgreg.dmamod, mystique->dma.iload_state); - switch (mystique->dwgreg.dmamod) - { - case DMA_MODE_REG: - if (mystique->dma.iload_state == 0) { -// pclog(" ILOAD header\n"); - mystique->dma.iload_header = val; - mystique->dma.iload_state = 1; - } else { - uint32_t reg_addr = (mystique->dma.iload_header & 0x7f) << 2; - if (mystique->dma.iload_header & 0x80) + reg_addr = (mystique->dma.sec_header & 0x7f) << 2; + if (mystique->dma.sec_header & 0x80) reg_addr += 0x2c00; else reg_addr += 0x1c00; -// pclog(" ILOAD write %08x to %02x %04x\n", val, mystique->dma.iload_header & 0xff, reg_addr); if ((reg_addr & 0x300) == 0x100) mystique->blitter_submit_dma_refcount++; + mystique_accel_ctrl_write_l(reg_addr, val, mystique); - mystique->dma.iload_header >>= 8; - mystique->dma.iload_state = (mystique->dma.iload_state == 4) ? 0 : (mystique->dma.iload_state+1); - } - break; - - case DMA_MODE_BLIT: - if (!mystique->busy) - fatal("mystique_iload_write_l: !busy\n"); - blit_iload_write(mystique, val, 32); - break; - - default: - pclog("ILOAD write DMAMOD %i\n", mystique->dwgreg.dmamod); - } -} - -static void run_dma(mystique_t *mystique) -{ - int words_transferred = 0; - - thread_wait_mutex(mystique->dma.lock); - - if (mystique->dma.state == DMA_STATE_IDLE) { - thread_release_mutex(mystique->dma.lock); - return; - } - - while (words_transferred < DMA_MAX_WORDS && mystique->dma.state != DMA_STATE_IDLE) { - switch (mystique->dma.state)// != DMA_STATE_IDLE) - { - case DMA_STATE_PRI: - switch (mystique->dma.primaddress & DMA_MODE_MASK) - { - case DMA_MODE_REG: - if (mystique->dma.pri_state == 0) { - mystique->dma.pri_header = *(uint32_t *)&ram[mystique->dma.primaddress & DMA_ADDR_MASK]; -// pclog("DMA pri read header %08x from %08x %08x\n", mystique->dma.pri_header, mystique->dma.primaddress, mystique->dma.primend); - mystique->dma.primaddress += 4; - } - -// if ((mystique->dma.pri_header & 0xff) != 0x15) - { - uint32_t val = *(uint32_t *)&ram[mystique->dma.primaddress & DMA_ADDR_MASK]; - uint32_t reg_addr; - - mystique->dma.primaddress += 4; - - reg_addr = (mystique->dma.pri_header & 0x7f) << 2; - if (mystique->dma.pri_header & 0x80) - reg_addr += 0x2c00; - else - reg_addr += 0x1c00; - -// pclog(" DMA pri write %08x to %02x %04x %08x %08x\n", val, mystique->dma.pri_header & 0xff, reg_addr, (mystique->dma.primaddress & DMA_ADDR_MASK), (mystique->dma.primend & DMA_ADDR_MASK)); - if ((reg_addr & 0x300) == 0x100) - mystique->blitter_submit_dma_refcount++; - - mystique_accel_ctrl_write_l(reg_addr, val, mystique); - } - - mystique->dma.pri_header >>= 8; - mystique->dma.pri_state = (mystique->dma.pri_state + 1) & 3; - - words_transferred++; - if (mystique->dma.state == DMA_STATE_SEC) - mystique->dma.pri_state = 0; - else if ((mystique->dma.primaddress & DMA_ADDR_MASK) == (mystique->dma.primend & DMA_ADDR_MASK)) { -// pclog("DMA pri end\n"); - mystique->endprdmasts_pending = 1; - mystique->dma.state = DMA_STATE_IDLE; - } - break; - - default: - fatal("DMA_STATE_PRI: mode %i\n", mystique->dma.primaddress & DMA_MODE_MASK); - } - break; - - case DMA_STATE_SEC: - switch (mystique->dma.secaddress & DMA_MODE_MASK) - { - case DMA_MODE_REG: - if (mystique->dma.sec_state == 0) { - mystique->dma.sec_header = *(uint32_t *)&ram[mystique->dma.secaddress & DMA_ADDR_MASK]; -// pclog("DMA sec read header %08x from %08x %08x\n", mystique->dma.sec_header, mystique->dma.secaddress, mystique->dma.secend); - mystique->dma.secaddress += 4; - } - -// if ((mystique->dma.sec_header & 0xff) != 0x15) - { - uint32_t val = *(uint32_t *)&ram[mystique->dma.secaddress & DMA_ADDR_MASK]; - uint32_t reg_addr; - - mystique->dma.secaddress += 4; - - reg_addr = (mystique->dma.sec_header & 0x7f) << 2; - if (mystique->dma.sec_header & 0x80) - reg_addr += 0x2c00; - else - reg_addr += 0x1c00; - -// pclog(" DMA sec write %08x to %02x %04x %08x %08x\n", val, mystique->dma.sec_header & 0xff, reg_addr, (mystique->dma.secaddress & DMA_ADDR_MASK), (mystique->dma.secend & DMA_ADDR_MASK)); - if ((reg_addr & 0x300) == 0x100) - mystique->blitter_submit_dma_refcount++; - - mystique_accel_ctrl_write_l(reg_addr, val, mystique); - } - - mystique->dma.sec_header >>= 8; - mystique->dma.sec_state = (mystique->dma.sec_state + 1) & 3; - - words_transferred++; - if ((mystique->dma.secaddress & DMA_ADDR_MASK) == (mystique->dma.secend & DMA_ADDR_MASK)) { -// pclog("DMA sec end\n"); - if ((mystique->dma.primaddress & DMA_ADDR_MASK) == (mystique->dma.primend & DMA_ADDR_MASK)) { -// pclog("DMA pri end\n"); - mystique->endprdmasts_pending = 1; - mystique->dma.state = DMA_STATE_IDLE; - } else { -// pclog("DMA pri resume\n"); - mystique->dma.state = DMA_STATE_PRI; - } - } - break; - - case DMA_MODE_BLIT: - { - uint32_t val = *(uint32_t *)&ram[mystique->dma.secaddress & DMA_ADDR_MASK]; -// pclog(" DMA_MODE_BLIT %08x %08x %08x %08x\n", mystique->dma.secaddress & DMA_ADDR_MASK, mystique->dma.secend & DMA_ADDR_MASK, mystique->dwgreg.dwgctrl_running, mystique->maccess_running); - mystique->dma.secaddress += 4; - - if (!mystique->busy) - fatal("mystique_iload_write_l: !busy\n"); - - blit_iload_write(mystique, val, 32); - - words_transferred++; - if ((mystique->dma.secaddress & DMA_ADDR_MASK) == (mystique->dma.secend & DMA_ADDR_MASK)) { -// pclog("DMA sec end\n"); - if ((mystique->dma.primaddress & DMA_ADDR_MASK) == (mystique->dma.primend & DMA_ADDR_MASK)) { -// pclog("DMA pri end\n"); - mystique->endprdmasts_pending = 1; - mystique->dma.state = DMA_STATE_IDLE; - } else { -// pclog("DMA pri resume\n"); - mystique->dma.state = DMA_STATE_PRI; - } - } - } - break; - - default: - fatal("DMA_STATE_SEC: mode %i\n", mystique->dma.secaddress & DMA_MODE_MASK); - } - break; - } - } - thread_release_mutex(mystique->dma.lock); -} - -static void fifo_thread(void *p) -{ - mystique_t *mystique = (mystique_t *)p; - - while (1) { - thread_set_event(mystique->fifo_not_full_event); - thread_wait_event(mystique->wake_fifo_thread, -1); - thread_reset_event(mystique->wake_fifo_thread); - - while (!FIFO_EMPTY || mystique->dma.state != DMA_STATE_IDLE) { - int words_transferred = 0; - - while (!FIFO_EMPTY && words_transferred < 100) { - fifo_entry_t *fifo = &mystique->fifo[mystique->fifo_read_idx & FIFO_MASK]; - - switch (fifo->addr_type & FIFO_TYPE) - { - case FIFO_WRITE_CTRL_BYTE: - mystique_accel_ctrl_write_b(fifo->addr_type & FIFO_ADDR, fifo->val, mystique); - break; - case FIFO_WRITE_CTRL_LONG: - mystique_accel_ctrl_write_l(fifo->addr_type & FIFO_ADDR, fifo->val, mystique); - break; - case FIFO_WRITE_ILOAD_LONG: - mystique_accel_iload_write_l(fifo->addr_type & FIFO_ADDR, fifo->val, mystique); - break; - } - - fifo->addr_type = FIFO_INVALID; - mystique->fifo_read_idx++; - - if (FIFO_ENTRIES > FIFO_THRESHOLD) - thread_set_event(mystique->fifo_not_full_event); + mystique->dma.sec_header >>= 8; + mystique->dma.sec_state = (mystique->dma.sec_state + 1) & 3; words_transferred++; - } - /*Only run DMA once the FIFO is empty. Required by - Screamer 2 / Rally which will incorrectly clip an ILOAD - if DMA runs ahead*/ - if (!words_transferred) - run_dma(mystique); + if ((mystique->dma.secaddress & DMA_ADDR_MASK) == (mystique->dma.secend & DMA_ADDR_MASK)) { + if ((mystique->dma.primaddress & DMA_ADDR_MASK) == (mystique->dma.primend & DMA_ADDR_MASK)) { + mystique->endprdmasts_pending = 1; + mystique->dma.state = DMA_STATE_IDLE; + } else + mystique->dma.state = DMA_STATE_PRI; + } + break; + + case DMA_MODE_BLIT: { + uint32_t val = *(uint32_t *)&ram[mystique->dma.secaddress & DMA_ADDR_MASK]; + mystique->dma.secaddress += 4; + + if (!mystique->busy) + fatal("mystique_iload_write_l: !busy\n"); + + blit_iload_write(mystique, val, 32); + + words_transferred++; + if ((mystique->dma.secaddress & DMA_ADDR_MASK) == (mystique->dma.secend & DMA_ADDR_MASK)) { + if ((mystique->dma.primaddress & DMA_ADDR_MASK) == (mystique->dma.primend & DMA_ADDR_MASK)) { + mystique->endprdmasts_pending = 1; + mystique->dma.state = DMA_STATE_IDLE; + } else + mystique->dma.state = DMA_STATE_PRI; + } + } break; + + default: + fatal("DMA_STATE_SEC: mode %i\n", mystique->dma.secaddress & DMA_MODE_MASK); } - } -} - -static void wake_fifo_thread(mystique_t *mystique) -{ - if (!timer_is_enabled(&mystique->wake_timer)) { - /*Don't wake FIFO thread immediately - if we do that it will probably - process one word and go back to sleep, requiring it to be woken on - almost every write. Instead, wait a short while so that the CPU - emulation writes more data so we have more batched-up work.*/ - timer_set_delay_u64(&mystique->wake_timer, WAKE_DELAY); + break; } + } + + thread_release_mutex(mystique->dma.lock); } -static void wake_fifo_thread_now(mystique_t *mystique) + +static void +fifo_thread(void *p) { - thread_set_event(mystique->wake_fifo_thread); + mystique_t *mystique = (mystique_t *)p; + + while (1) { + thread_set_event(mystique->fifo_not_full_event); + thread_wait_event(mystique->wake_fifo_thread, -1); + thread_reset_event(mystique->wake_fifo_thread); + + while (!FIFO_EMPTY || mystique->dma.state != DMA_STATE_IDLE) { + int words_transferred = 0; + + while (!FIFO_EMPTY && words_transferred < 100) { + fifo_entry_t *fifo = &mystique->fifo[mystique->fifo_read_idx & FIFO_MASK]; + + switch (fifo->addr_type & FIFO_TYPE) { + case FIFO_WRITE_CTRL_BYTE: + mystique_accel_ctrl_write_b(fifo->addr_type & FIFO_ADDR, fifo->val, mystique); + break; + case FIFO_WRITE_CTRL_LONG: + mystique_accel_ctrl_write_l(fifo->addr_type & FIFO_ADDR, fifo->val, mystique); + break; + case FIFO_WRITE_ILOAD_LONG: + mystique_accel_iload_write_l(fifo->addr_type & FIFO_ADDR, fifo->val, mystique); + break; + } + + fifo->addr_type = FIFO_INVALID; + mystique->fifo_read_idx++; + + if (FIFO_ENTRIES > FIFO_THRESHOLD) + thread_set_event(mystique->fifo_not_full_event); + + words_transferred++; + } + + /*Only run DMA once the FIFO is empty. Required by + Screamer 2 / Rally which will incorrectly clip an ILOAD + if DMA runs ahead*/ + if (!words_transferred) + run_dma(mystique); + } + } } -static void mystique_wake_timer(void *p) + +static void +wake_fifo_thread(mystique_t *mystique) { - mystique_t *mystique = (mystique_t *)p; - - thread_set_event(mystique->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ + if (!timer_is_enabled(&mystique->wake_timer)) { + /* Don't wake FIFO thread immediately - if we do that it will probably + process one word and go back to sleep, requiring it to be woken on + almost every write. Instead, wait a short while so that the CPU + emulation writes more data so we have more batched-up work. */ + timer_set_delay_u64(&mystique->wake_timer, WAKE_DELAY); + } } -static void wait_fifo_idle(mystique_t *mystique) + +static void +wake_fifo_thread_now(mystique_t *mystique) { - while (!FIFO_EMPTY) { - wake_fifo_thread_now(mystique); - thread_wait_event(mystique->fifo_not_full_event, 1); - } + thread_set_event(mystique->wake_fifo_thread); } + +static void +mystique_wake_timer(void *p) +{ + mystique_t *mystique = (mystique_t *)p; + + thread_set_event(mystique->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ +} + + +static void +wait_fifo_idle(mystique_t *mystique) +{ + while (!FIFO_EMPTY) { + wake_fifo_thread_now(mystique); + thread_wait_event(mystique->fifo_not_full_event, 1); + } +} + + /*IRQ code (PCI & PIC) is not currently thread safe. SOFTRAP IRQ requests must therefore be submitted from the main emulation thread, in this case via a timer callback. End-of-DMA status is also deferred here to prevent races between @@ -2251,832 +2205,640 @@ static void wait_fifo_idle(mystique_t *mystique) loop and triple fault if the ENDPRDMASTS flag is seen before the IRQ is taken*/ static void mystique_softrap_pending_timer(void *p) { - mystique_t *mystique = (mystique_t *)p; + mystique_t *mystique = (mystique_t *)p; - timer_advance_u64(&mystique->softrap_pending_timer, TIMER_USEC * 100); + timer_advance_u64(&mystique->softrap_pending_timer, TIMER_USEC * 100); - if (mystique->endprdmasts_pending) { - mystique->endprdmasts_pending = 0; - mystique->status |= STATUS_ENDPRDMASTS; - } - if (mystique->softrap_pending) { - mystique->softrap_pending = 0; + if (mystique->endprdmasts_pending) { + mystique->endprdmasts_pending = 0; + mystique->status |= STATUS_ENDPRDMASTS; + } + if (mystique->softrap_pending) { + mystique->softrap_pending = 0; -// pclog("Take SOFTRAP %08x\n", cpu_state.pc); - mystique->dma.secaddress = mystique->softrap_pending_val; - mystique->status |= STATUS_SOFTRAPEN; - mystique_update_irqs(mystique); - } + mystique->dma.secaddress = mystique->softrap_pending_val; + mystique->status |= STATUS_SOFTRAPEN; + mystique_update_irqs(mystique); + } } -static void mystique_queue(mystique_t *mystique, uint32_t addr, uint32_t val, uint32_t type) + +static +void mystique_queue(mystique_t *mystique, uint32_t addr, uint32_t val, uint32_t type) { - fifo_entry_t *fifo = &mystique->fifo[mystique->fifo_write_idx & FIFO_MASK]; + fifo_entry_t *fifo = &mystique->fifo[mystique->fifo_write_idx & FIFO_MASK]; - if (FIFO_FULL) { - thread_reset_event(mystique->fifo_not_full_event); - if (FIFO_FULL) { - thread_wait_event(mystique->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/ - } - } + if (FIFO_FULL) { + thread_reset_event(mystique->fifo_not_full_event); + if (FIFO_FULL) + thread_wait_event(mystique->fifo_not_full_event, -1); /* Wait for room in ringbuffer */ + } - fifo->val = val; - fifo->addr_type = (addr & FIFO_ADDR) | type; + fifo->val = val; + fifo->addr_type = (addr & FIFO_ADDR) | type; - mystique->fifo_write_idx++; + mystique->fifo_write_idx++; - if (FIFO_ENTRIES > FIFO_THRESHOLD || FIFO_ENTRIES < 8) - wake_fifo_thread(mystique); - -// wait_fifo_idle(mystique); + if (FIFO_ENTRIES > FIFO_THRESHOLD || FIFO_ENTRIES < 8) + wake_fifo_thread(mystique); } -static uint32_t bitop(uint32_t src, uint32_t dst, uint32_t dwgctrl) + +static uint32_t +bitop(uint32_t src, uint32_t dst, uint32_t dwgctrl) { - switch (dwgctrl & DWGCTRL_BOP_MASK) - { - case BOP(0x0): return 0; - case BOP(0x1): return ~(dst | src); - case BOP(0x2): return dst & ~src; - case BOP(0x3): return ~src; - case BOP(0x4): return ~dst & src; - case BOP(0x5): return ~dst; - case BOP(0x6): return dst ^ src; - case BOP(0x7): return ~(dst & src); - case BOP(0x8): return dst & src; - case BOP(0x9): return ~(dst ^ src); - case BOP(0xa): return dst; - case BOP(0xb): return dst | ~src; - case BOP(0xc): return src; - case BOP(0xd): return ~dst | src; - case BOP(0xe): return dst | src; - case BOP(0xf): return ~0; - } - return 0; + switch (dwgctrl & DWGCTRL_BOP_MASK) { + case BOP(0x0): return 0; + case BOP(0x1): return ~(dst | src); + case BOP(0x2): return dst & ~src; + case BOP(0x3): return ~src; + case BOP(0x4): return ~dst & src; + case BOP(0x5): return ~dst; + case BOP(0x6): return dst ^ src; + case BOP(0x7): return ~(dst & src); + case BOP(0x8): return dst & src; + case BOP(0x9): return ~(dst ^ src); + case BOP(0xa): return dst; + case BOP(0xb): return dst | ~src; + case BOP(0xc): return src; + case BOP(0xd): return ~dst | src; + case BOP(0xe): return dst | src; + case BOP(0xf): return ~0; + } + + return 0; } -static uint16_t dither(mystique_t *mystique, int r, int g, int b, int x, int y) + +static uint16_t +dither(mystique_t *mystique, int r, int g, int b, int x, int y) { - switch (mystique->dwgreg.dither) - { - case DITHER_NONE_555: - return (b >> 3) | ((g >> 3) << 5) | ((r >> 3) << 10); + switch (mystique->dwgreg.dither) { + case DITHER_NONE_555: + return (b >> 3) | ((g >> 3) << 5) | ((r >> 3) << 10); - case DITHER_NONE_565: - return (b >> 3) | ((g >> 2) << 5) | ((r >> 3) << 11); + case DITHER_NONE_565: + return (b >> 3) | ((g >> 2) << 5) | ((r >> 3) << 11); - case DITHER_555: - return dither5[b][y][x] | (dither5[g][y][x] << 5) | (dither5[r][y][x] << 10); + case DITHER_555: + return dither5[b][y][x] | (dither5[g][y][x] << 5) | (dither5[r][y][x] << 10); - case DITHER_565: - default: - return dither5[b][y][x] | (dither6[g][y][x] << 5) | (dither5[r][y][x] << 11); - } + case DITHER_565: + default: + return dither5[b][y][x] | (dither6[g][y][x] << 5) | (dither5[r][y][x] << 11); + } } -static uint32_t blit_idump_idump(mystique_t *mystique) + +static uint32_t +blit_idump_idump(mystique_t *mystique) { - svga_t *svga = &mystique->svga; - uint64_t val64 = 0; - uint32_t val = 0; - int count = 0; - - switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) - { - case DWGCTRL_ATYPE_RPL: - switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) - { - case DWGCTRL_BLTMOD_BU32RGB: - switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) - { - case MACCESS_PWIDTH_8: -// pclog(" IDUMP %08x\n", mystique->dwgreg.src_addr); - while (count < 32) { - val |= (svga->vram[mystique->dwgreg.src_addr & mystique->vram_mask] << count); + svga_t *svga = &mystique->svga; + uint64_t val64 = 0; + uint32_t val = 0; + int count = 0; - if (mystique->dwgreg.src_addr == mystique->dwgreg.ar[0]) { - mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; - mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; - mystique->dwgreg.src_addr = mystique->dwgreg.ar[3]; - } else - mystique->dwgreg.src_addr++; + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { + case DWGCTRL_ATYPE_RPL: + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { + case DWGCTRL_BLTMOD_BU32RGB: + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_8: + while (count < 32) { + val |= (svga->vram[mystique->dwgreg.src_addr & mystique->vram_mask] << count); - if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { - mystique->dwgreg.xdst = mystique->dwgreg.fxleft; - mystique->dwgreg.length_cur--; - if (!mystique->dwgreg.length_cur) { - mystique->busy = 0; - mystique->blitter_complete_refcount++; - break; - } - break; - } else - mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; - - count += 8; - } - break; - - case MACCESS_PWIDTH_16: -// pclog(" IDUMP %08x\n", mystique->dwgreg.src_addr); - while (count < 32) { - val |= (((uint16_t *)svga->vram)[mystique->dwgreg.src_addr & mystique->vram_mask_w] << count); - - if (mystique->dwgreg.src_addr == mystique->dwgreg.ar[0]) { - mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; - mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; - mystique->dwgreg.src_addr = mystique->dwgreg.ar[3]; - } else - mystique->dwgreg.src_addr++; - - if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { - mystique->dwgreg.xdst = mystique->dwgreg.fxleft; - mystique->dwgreg.length_cur--; - if (!mystique->dwgreg.length_cur) { - mystique->busy = 0; - mystique->blitter_complete_refcount++; - break; - } - break; - } else - mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; - - count += 16; - } - break; - - case MACCESS_PWIDTH_24: - if (mystique->dwgreg.idump_end_of_line) { - mystique->dwgreg.idump_end_of_line = 0; - val = mystique->dwgreg.iload_rem_data; - mystique->dwgreg.iload_rem_count = 0; - mystique->dwgreg.iload_rem_data = 0; - if (!mystique->dwgreg.length_cur) { - mystique->busy = 0; - mystique->blitter_complete_refcount++; - } - break; - } - - count += mystique->dwgreg.iload_rem_count; - val64 = mystique->dwgreg.iload_rem_data; - -// pclog(" IDUMP %08x\n", mystique->dwgreg.src_addr); - while ((count < 32) && !mystique->dwgreg.idump_end_of_line) { - val64 |= (uint64_t)((*(uint32_t *)&svga->vram[(mystique->dwgreg.src_addr * 3) & mystique->vram_mask]) & 0xffffff) << count; -/* pclog(" %i %i %i %016llx\n", count, mystique->dwgreg.xdst, - mystique->dwgreg.length_cur, val64);*/ - - if (mystique->dwgreg.src_addr == mystique->dwgreg.ar[0]) { - mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; - mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; - mystique->dwgreg.src_addr = mystique->dwgreg.ar[3]; - } else - mystique->dwgreg.src_addr++; - - if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { - mystique->dwgreg.xdst = mystique->dwgreg.fxleft; - mystique->dwgreg.length_cur--; - if (!mystique->dwgreg.length_cur) { - if (count > 8) - mystique->dwgreg.idump_end_of_line = 1; - else { - count = 32; - mystique->busy = 0; - mystique->blitter_complete_refcount++; - } - break; - } - if (!(mystique->dwgreg.dwgctrl_running & DWGCTRL_LINEAR)) { - if (count > 8) - mystique->dwgreg.idump_end_of_line = 1; - else { - count = 32; - break; - } - } - } else - mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; - - count += 24; - } - if (count > 32) - mystique->dwgreg.iload_rem_count = count - 32; - else - mystique->dwgreg.iload_rem_count = 0; - mystique->dwgreg.iload_rem_data = (uint32_t)(val64 >> 32); - val = val64 & 0xffffffff; - break; - - case MACCESS_PWIDTH_32: -// pclog(" IDUMP %08x\n", mystique->dwgreg.src_addr); - - val = (((uint32_t *)svga->vram)[mystique->dwgreg.src_addr & mystique->vram_mask_l] << count); - - if (mystique->dwgreg.src_addr == mystique->dwgreg.ar[0]) { - mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; - mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; - mystique->dwgreg.src_addr = mystique->dwgreg.ar[3]; - } else - mystique->dwgreg.src_addr++; - - if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { - mystique->dwgreg.xdst = mystique->dwgreg.fxleft; - mystique->dwgreg.length_cur--; - if (!mystique->dwgreg.length_cur) { - mystique->busy = 0; - mystique->blitter_complete_refcount++; - break; - } - break; - } else - mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; - break; - - default: - fatal("IDUMP DWGCTRL_BLTMOD_BU32RGB %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->maccess_running); - } - break; - - default: - fatal("IDUMP DWGCTRL_ATYPE_RPL %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running); - break; - } - break; - - default: - fatal("Unknown IDUMP atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); - } - - return val; -} - -static uint32_t blit_idump_read(mystique_t *mystique) -{ - uint32_t ret = 0xffffffff; - - switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) - { - case DWGCTRL_OPCODE_IDUMP: - ret = blit_idump_idump(mystique); - break; - - default: - pclog("blit_idump_read: bad opcode %08x\n", mystique->dwgreg.dwgctrl_running); - break; - } - -// pclog(" idump returned %08x\n", ret); - return ret; -} - -static void blit_iload_iload(mystique_t *mystique, uint32_t data, int size) -{ - svga_t *svga = &mystique->svga; - uint32_t src, dst; - uint64_t data64; - int min_size; - uint32_t bltckey = mystique->dwgreg.fcol, bltcmsk = mystique->dwgreg.bcol; - const int transc = mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC; - const int trans_sel = (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANS_MASK) >> DWGCTRL_TRANS_SHIFT; - uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; - - switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) - { - case MACCESS_PWIDTH_8: - bltckey &= 0xff; - bltcmsk &= 0xff; - break; - case MACCESS_PWIDTH_16: - bltckey &= 0xffff; - bltcmsk &= 0xffff; - break; - } - - mystique->dwgreg.words++; -// pclog("blit_iload_iload: %08x %06x %02x %i %08x words=%i %08x %08x\n", data, mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst, data, (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) == DWGCTRL_BLTMOD_BMONOWF, mystique->dwgreg.dwgctrl_running, mystique->dwgreg.words,mystique->dwgreg.words, mystique->maccess_running); - switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { - case DWGCTRL_ATYPE_RPL: - if (mystique->maccess_running & MACCESS_TLUTLOAD) { - while ((mystique->dwgreg.length_cur > 0) && (size >= 16)) { - uint16_t src = data & 0xffff; -// pclog(" LUT[%02x]=%04x\n", mystique->dwgreg.ydst & 0xff, src); - - mystique->lut[mystique->dwgreg.ydst & 0xff].r = (src >> 11) << 3; - mystique->lut[mystique->dwgreg.ydst & 0xff].g = ((src >> 5) & 0x3f) << 2; - mystique->lut[mystique->dwgreg.ydst & 0xff].b = (src & 0x1f) << 3; - mystique->dwgreg.ydst++; - mystique->dwgreg.length_cur--; - data >>= 16; - size -= 16; - } - - if (!mystique->dwgreg.length_cur) - { - mystique->busy = 0; - mystique->blitter_complete_refcount++; - } - break; - } - case DWGCTRL_ATYPE_RSTR: - case DWGCTRL_ATYPE_BLK: - switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) - { - case DWGCTRL_BLTMOD_BFCOL: - size += mystique->dwgreg.iload_rem_count; -// pclog(" size=%i xdst=%i cur=%i data= %08x %08x ", size, mystique->dwgreg.xdst, mystique->dwgreg.length_cur, mystique->dwgreg.iload_rem_data, data); - data64 = mystique->dwgreg.iload_rem_data | ((uint64_t)data << mystique->dwgreg.iload_rem_count); -// pclog("%016llx words=%i\n", data64, mystique->dwgreg.words); - - switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) - { - case MACCESS_PWIDTH_8: - min_size = 8; - break; - case MACCESS_PWIDTH_16: - min_size = 16; - break; - case MACCESS_PWIDTH_24: - min_size = 24; - break; - case MACCESS_PWIDTH_32: - min_size = 32; - break; - } - - while (size >= min_size) { - int draw = (!transc || (data & bltcmsk) != bltckey) && trans[mystique->dwgreg.xdst & 3]; - - switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) - { - case MACCESS_PWIDTH_8: - if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && draw) { - dst = svga->vram[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask]; - - dst = bitop(data & 0xff, dst, mystique->dwgreg.dwgctrl_running); -// pclog(" 8 %06x=%04x\n", mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst, dst); - svga->vram[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask) >> 12] = changeframecount; - } -/* else - pclog(" Clipped %i,%i %i %08x,%08x %08x\n", - mystique->dwgreg.cxleft, mystique->dwgreg.cxright, mystique->dwgreg.xdst, - mystique->dwgreg.ytop, mystique->dwgreg.ybot, mystique->dwgreg.ydst_lin);*/ - - data >>= 8; - size -= 8; - break; - - case MACCESS_PWIDTH_16: - if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && draw) { - dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w]; - - dst = bitop(data & 0xffff, dst, mystique->dwgreg.dwgctrl_running); -// pclog(" 16 %06x=%04x\n", mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst, dst); - ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w) >> 11] = changeframecount; - } - - data >>= 16; - size -= 16; - break; - - case MACCESS_PWIDTH_24: - if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { - uint32_t old_dst = *((uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask]); - - dst = bitop(data64, old_dst, mystique->dwgreg.dwgctrl_running); - *((uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask]) = (dst & 0xffffff) | (old_dst & 0xff000000); - svga->changedvram[(((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask) >> 12] = changeframecount; - } - - data64 >>= 24; - size -= 24; - break; - - case MACCESS_PWIDTH_32: - if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && draw) { - dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; - - dst = bitop(data, dst, mystique->dwgreg.dwgctrl_running); -// pclog(" 32 %06x=%04x\n", mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst, dst); - ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount; - } - - size = 0; - break; - - default: - fatal("ILOAD RSTR/RPL BFCOL pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); - } + if (mystique->dwgreg.src_addr == mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; + mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; + mystique->dwgreg.src_addr = mystique->dwgreg.ar[3]; + } else + mystique->dwgreg.src_addr++; if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { mystique->dwgreg.xdst = mystique->dwgreg.fxleft; - mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); - mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7; mystique->dwgreg.length_cur--; if (!mystique->dwgreg.length_cur) { mystique->busy = 0; mystique->blitter_complete_refcount++; break; } - data64 = 0; - size = 0; break; } else mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; - } - mystique->dwgreg.iload_rem_count = size; - mystique->dwgreg.iload_rem_data = data64; - break; - case DWGCTRL_BLTMOD_BMONOWF: - data = (data >> 24) | ((data & 0x00ff0000) >> 8) | ((data & 0x0000ff00) << 8) | (data << 24); - while (size) { - if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && - ((data & 0x80000000) || !(mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC)) && - trans[mystique->dwgreg.xdst & 3]) { - uint32_t old_dst; - - src = (data & 0x80000000) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; - switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) - { - case MACCESS_PWIDTH_8: - dst = svga->vram[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask]; - -// pclog(" %02x %02x %06x ", src, dst, mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst); - dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); -// pclog("%02x\n", dst); + count += 8; + } + break; - svga->vram[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask) >> 12] = changeframecount; - break; + case MACCESS_PWIDTH_16: + while (count < 32) { + val |= (((uint16_t *)svga->vram)[mystique->dwgreg.src_addr & mystique->vram_mask_w] << count); - case MACCESS_PWIDTH_16: - dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w]; - -// pclog(" %02x %02x %06x ", src, dst, mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst); - dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); -// pclog("%02x\n", dst); - - ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w) >> 11] = changeframecount; - break; - - case MACCESS_PWIDTH_24: - old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask]; - -// pclog(" %02x %02x %06x ", src, old_dst, mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst); - dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running); -// pclog("%02x %08x %08x %08x %i\n", dst, data, mystique->dwgreg.fcol, mystique->dwgreg.bcol, mystique->dwgreg.xdst); - - *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000); - svga->changedvram[(((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask) >> 12] = changeframecount; - break; - - case MACCESS_PWIDTH_32: - dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; - -// pclog(" %02x %02x %06x ", src, dst, mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst); - dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); -// pclog("%02x %08x %08x %08x %i\n", dst, data, mystique->dwgreg.fcol, mystique->dwgreg.bcol, mystique->dwgreg.xdst); - - ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount; - break; - - default: - fatal("ILOAD RSTR/RPL BMONOWF pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); - } - } + if (mystique->dwgreg.src_addr == mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; + mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; + mystique->dwgreg.src_addr = mystique->dwgreg.ar[3]; + } else + mystique->dwgreg.src_addr++; if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { mystique->dwgreg.xdst = mystique->dwgreg.fxleft; - mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); mystique->dwgreg.length_cur--; if (!mystique->dwgreg.length_cur) { mystique->busy = 0; mystique->blitter_complete_refcount++; break; } - if (!(mystique->dwgreg.dwgctrl_running & DWGCTRL_LINEAR)) - break; + break; } else mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; - data <<= 1; - size--; - } - break; - case DWGCTRL_BLTMOD_BU24RGB: - size += mystique->dwgreg.iload_rem_count; -// pclog(" size=%i data= %08x %08x ", size, mystique->dwgreg.iload_rem_data, data); - data64 = mystique->dwgreg.iload_rem_data | ((uint64_t)data << mystique->dwgreg.iload_rem_count); -// pclog("%016llx\n", data64); - - while (size >= 24) { + count += 16; + } + break; + + case MACCESS_PWIDTH_24: + if (mystique->dwgreg.idump_end_of_line) { + mystique->dwgreg.idump_end_of_line = 0; + val = mystique->dwgreg.iload_rem_data; + mystique->dwgreg.iload_rem_count = 0; + mystique->dwgreg.iload_rem_data = 0; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + } + break; + } + + count += mystique->dwgreg.iload_rem_count; + val64 = mystique->dwgreg.iload_rem_data; + + while ((count < 32) && !mystique->dwgreg.idump_end_of_line) { + val64 |= (uint64_t)((*(uint32_t *)&svga->vram[(mystique->dwgreg.src_addr * 3) & mystique->vram_mask]) & 0xffffff) << count; + + if (mystique->dwgreg.src_addr == mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; + mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; + mystique->dwgreg.src_addr = mystique->dwgreg.ar[3]; + } else + mystique->dwgreg.src_addr++; + + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + if (count > 8) + mystique->dwgreg.idump_end_of_line = 1; + else { + count = 32; + mystique->busy = 0; + mystique->blitter_complete_refcount++; + } + break; + } + if (!(mystique->dwgreg.dwgctrl_running & DWGCTRL_LINEAR)) { + if (count > 8) + mystique->dwgreg.idump_end_of_line = 1; + else { + count = 32; + break; + } + } + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + + count += 24; + } + if (count > 32) + mystique->dwgreg.iload_rem_count = count - 32; + else + mystique->dwgreg.iload_rem_count = 0; + mystique->dwgreg.iload_rem_data = (uint32_t)(val64 >> 32); + val = val64 & 0xffffffff; + break; + + case MACCESS_PWIDTH_32: + val = (((uint32_t *)svga->vram)[mystique->dwgreg.src_addr & mystique->vram_mask_l] << count); + + if (mystique->dwgreg.src_addr == mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; + mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; + mystique->dwgreg.src_addr = mystique->dwgreg.ar[3]; + } else + mystique->dwgreg.src_addr++; + + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + break; + } + break; + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + break; + + default: + fatal("IDUMP DWGCTRL_BLTMOD_BU32RGB %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->maccess_running); + } + break; + + default: + fatal("IDUMP DWGCTRL_ATYPE_RPL %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running); + break; + } + break; + + default: + fatal("Unknown IDUMP atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + } + + return val; +} + + +static uint32_t +blit_idump_read(mystique_t *mystique) +{ + uint32_t ret = 0xffffffff; + + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) { + case DWGCTRL_OPCODE_IDUMP: + ret = blit_idump_idump(mystique); + break; + + default: + /* pclog("blit_idump_read: bad opcode %08x\n", mystique->dwgreg.dwgctrl_running); */ + break; + } + + return ret; +} + + +static void +blit_iload_iload(mystique_t *mystique, uint32_t data, int size) +{ + svga_t *svga = &mystique->svga; + uint32_t src, dst; + uint64_t data64; + int min_size = 8; + uint32_t bltckey = mystique->dwgreg.fcol, bltcmsk = mystique->dwgreg.bcol; + const int transc = mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC; + const int trans_sel = (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANS_MASK) >> DWGCTRL_TRANS_SHIFT; + uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; + + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_8: + bltckey &= 0xff; + bltcmsk &= 0xff; + break; + case MACCESS_PWIDTH_16: + bltckey &= 0xffff; + bltcmsk &= 0xffff; + break; + } + + mystique->dwgreg.words++; + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { + case DWGCTRL_ATYPE_RPL: + if (mystique->maccess_running & MACCESS_TLUTLOAD) { + while ((mystique->dwgreg.length_cur > 0) && (size >= 16)) { + uint16_t src = data & 0xffff; + + mystique->lut[mystique->dwgreg.ydst & 0xff].r = (src >> 11) << 3; + mystique->lut[mystique->dwgreg.ydst & 0xff].g = ((src >> 5) & 0x3f) << 2; + mystique->lut[mystique->dwgreg.ydst & 0xff].b = (src & 0x1f) << 3; + mystique->dwgreg.ydst++; + mystique->dwgreg.length_cur--; + data >>= 16; + size -= 16; + } + + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + } + break; + } + case DWGCTRL_ATYPE_RSTR: + case DWGCTRL_ATYPE_BLK: + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { + case DWGCTRL_BLTMOD_BFCOL: + size += mystique->dwgreg.iload_rem_count; + data64 = mystique->dwgreg.iload_rem_data | ((uint64_t)data << mystique->dwgreg.iload_rem_count); + + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_8: + min_size = 8; + break; + case MACCESS_PWIDTH_16: + min_size = 16; + break; + case MACCESS_PWIDTH_24: + min_size = 24; + break; + case MACCESS_PWIDTH_32: + min_size = 32; + break; + } + + while (size >= min_size) { + int draw = (!transc || (data & bltcmsk) != bltckey) && trans[mystique->dwgreg.xdst & 3]; + + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_8: + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && draw) { + dst = svga->vram[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask]; + + dst = bitop(data & 0xff, dst, mystique->dwgreg.dwgctrl_running); + svga->vram[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask) >> 12] = changeframecount; + } + + data >>= 8; + size -= 8; + break; + + case MACCESS_PWIDTH_16: + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && draw) { + dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w]; + + dst = bitop(data & 0xffff, dst, mystique->dwgreg.dwgctrl_running); + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w) >> 11] = changeframecount; + } + + data >>= 16; + size -= 16; + break; + + case MACCESS_PWIDTH_24: if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { - switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) - { - case MACCESS_PWIDTH_32: - dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; + uint32_t old_dst = *((uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask]); -// pclog(" %06llx %02x %06x ", data64 & 0xffffff, dst, mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst); -// pclog("x=%i l=%i ", mystique->dwgreg.xdst, mystique->dwgreg.length_cur); - dst = bitop(data64 & 0xffffff, dst, mystique->dwgreg.dwgctrl_running); -// pclog("%02x\n", dst); - - ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount; - break; - - default: - fatal("ILOAD RSTR/RPL BU24RGB pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); - } + dst = bitop(data64, old_dst, mystique->dwgreg.dwgctrl_running); + *((uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask]) = (dst & 0xffffff) | (old_dst & 0xff000000); + svga->changedvram[(((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask) >> 12] = changeframecount; } data64 >>= 24; size -= 24; - if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { - mystique->dwgreg.xdst = mystique->dwgreg.fxleft; - mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); - mystique->dwgreg.length_cur--; - if (!mystique->dwgreg.length_cur) { - mystique->busy = 0; - mystique->blitter_complete_refcount++; - break; - } - data64 = 0; - size = 0; - break; - } else - mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; - } - - mystique->dwgreg.iload_rem_count = size; - mystique->dwgreg.iload_rem_data = data64; - break; - - default: - fatal("ILOAD DWGCTRL_ATYPE_RPL\n"); - break; - } - break; + break; - default: - fatal("Unknown ILOAD iload atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); - } -} + case MACCESS_PWIDTH_32: + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && draw) { + dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; -#define CLAMP(x) do \ - { \ - if ((x) & ~0xff) \ - x = ((x) < 0) ? 0 : 0xff; \ - } \ - while (0) + dst = bitop(data, dst, mystique->dwgreg.dwgctrl_running); + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount; + } -static void blit_iload_iload_scale(mystique_t *mystique, uint32_t data, int size) -{ - svga_t *svga = &mystique->svga; - uint64_t data64 = 0; - int y0, y1; - int u, v; - int dR, dG, dB; - int r0, g0, b0; - int r1, g1, b1; - -// pclog(" iload_scale: data=%08x\n", data); - - switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) - { - case DWGCTRL_BLTMOD_BUYUV: - y0 = (298 * ((int)(data & 0xff) - 16)) >> 8; - u = ((data >> 8) & 0xff) - 0x80; - y1 = (298 * ((int)((data >> 16) & 0xff) - 16)) >> 8; - v = ((data >> 24) & 0xff) - 0x80; + size = 0; + break; - dR = (309*v) >> 8; - dG = (100*u + 208*v) >> 8; - dB = (516*u) >> 8; - - r0 = y0 + dR; - CLAMP(r0); - g0 = y0 - dG; - CLAMP(g0); - b0 = y0 + dB; - CLAMP(b0); - r1 = y1 + dR; - CLAMP(r1); - g1 = y1 - dG; - CLAMP(g1); - b1 = y1 + dB; - CLAMP(b1); - - switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) - { - case MACCESS_PWIDTH_16: - data = (b0 >> 3) | ((g0 >> 2) << 5) | ((r0 >> 3) << 11); - data |= (((b1 >> 3) | ((g1 >> 2) << 5) | ((r1 >> 3) << 11)) << 16); - size = 32; - break; - case MACCESS_PWIDTH_32: - data64 = b0 | (g0 << 8) | (r0 << 16); - data64 |= ((uint64_t)b0 << 32) | ((uint64_t)g0 << 40) | ((uint64_t)r0 << 48); - size = 64; - break; - - default: - fatal("blit_iload_iload_scale BUYUV pwidth %i\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); - } - break; - - default: - fatal("blit_iload_iload_scale bltmod %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK); - break; - } - - switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) - { - case MACCESS_PWIDTH_16: - while (size >= 16) { -// pclog(" Write %i %i %08x\n", mystique->dwgreg.xdst, mystique->dwgreg.fxright, mystique->dwgreg.ar[6]); - if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { - uint16_t dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w]; - dst = bitop(data & 0xffff, dst, mystique->dwgreg.dwgctrl_running); - ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w) >> 11] = changeframecount; - } - - mystique->dwgreg.ar[6] += mystique->dwgreg.ar[2]; - if ((int32_t)mystique->dwgreg.ar[6] >= 0) { - mystique->dwgreg.ar[6] -= (mystique->dwgreg.fxright - mystique->dwgreg.fxleft); - data >>= 16; - size -= 16; + default: + fatal("ILOAD RSTR/RPL BFCOL pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); } if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { mystique->dwgreg.xdst = mystique->dwgreg.fxleft; mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); - mystique->dwgreg.ar[6] = mystique->dwgreg.ar[2] - (mystique->dwgreg.fxright - mystique->dwgreg.fxleft); + mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7; mystique->dwgreg.length_cur--; if (!mystique->dwgreg.length_cur) { mystique->busy = 0; mystique->blitter_complete_refcount++; break; } + data64 = 0; + size = 0; break; } else mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; - } - break; - - case MACCESS_PWIDTH_32: - while (size >= 32) { -// pclog(" Write %i %i %08x\n", mystique->dwgreg.xdst, mystique->dwgreg.fxright, mystique->dwgreg.ar[6]); - if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { - uint32_t dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; - dst = bitop(data64, dst, mystique->dwgreg.dwgctrl_running); - ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount; - } - - mystique->dwgreg.ar[6] += mystique->dwgreg.ar[2]; - if ((int32_t)mystique->dwgreg.ar[6] >= 0) { - mystique->dwgreg.ar[6] -= (mystique->dwgreg.fxright - mystique->dwgreg.fxleft); - data64 >>= 32; - size -= 32; - } - - if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { - mystique->dwgreg.xdst = mystique->dwgreg.fxleft; - mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); - mystique->dwgreg.ar[6] = mystique->dwgreg.ar[2] - (mystique->dwgreg.fxright - mystique->dwgreg.fxleft); - mystique->dwgreg.length_cur--; - if (!mystique->dwgreg.length_cur) { - mystique->busy = 0; - mystique->blitter_complete_refcount++; - break; - } - break; - } else - mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; - } - break; - - default: - fatal("ILOAD_SCALE pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); - } -} - -static void blit_iload_iload_high(mystique_t *mystique, uint32_t data, int size) -{ - svga_t *svga = &mystique->svga; - uint32_t out_data; - int y0, y1, u, v; - int dR, dG, dB; - int r = 0, g = 0, b = 0; - int next_r = 0, next_g = 0, next_b = 0; - -// pclog(" iload_high: data=%08x\n", data); - - switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) - { - case DWGCTRL_BLTMOD_BUYUV: - y0 = (298 * ((int)(data & 0xff) - 16)) >> 8; - u = ((data >> 8) & 0xff) - 0x80; - y1 = (298 * ((int)((data >> 16) & 0xff) - 16)) >> 8; - v = ((data >> 24) & 0xff) - 0x80; - - dR = (309*v) >> 8; - dG = (100*u + 208*v) >> 8; - dB = (516*u) >> 8; - - r = y0 + dR; - CLAMP(r); - g = y0 - dG; - CLAMP(g); - b = y0 + dB; - CLAMP(b); - - next_r = y1 + dR; - CLAMP(next_r); - next_g = y1 - dG; - CLAMP(next_g); - next_b = y1 + dB; - CLAMP(next_b); - - size = 32; - break; - - default: - fatal("blit_iload_iload_high bltmod %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK); - break; - } - - while (size >= 16) { - if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { - uint32_t dst; - int f1 = (mystique->dwgreg.ar[6] >> 12) & 0xf; - int f0 = 0x10 - f1; - int out_r = ((mystique->dwgreg.lastpix_r * f0) + (r * f1)) >> 4; - int out_g = ((mystique->dwgreg.lastpix_g * f0) + (g * f1)) >> 4; - int out_b = ((mystique->dwgreg.lastpix_b * f0) + (b * f1)) >> 4; - -// pclog(" Write %i %i %08x %i %i %i %i %i\n", mystique->dwgreg.xdst, mystique->dwgreg.fxright, mystique->dwgreg.ar[6], mystique->dwgreg.lastpix_r, r, f0, f1, out_r); - - switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) - { - case MACCESS_PWIDTH_16: - out_data = (out_b >> 3) | ((out_g >> 2) << 5) | ((out_r >> 3) << 11); - dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w]; - dst = bitop(out_data, dst, mystique->dwgreg.dwgctrl_running); - ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w) >> 11] = changeframecount; - break; - case MACCESS_PWIDTH_32: - out_data = out_b | (out_g << 8) | (out_r << 16); - dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; - dst = bitop(out_data, dst, mystique->dwgreg.dwgctrl_running); - ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount; - break; - - default: - fatal("ILOAD_SCALE_HIGH RSTR/RPL BUYUV pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); } + mystique->dwgreg.iload_rem_count = size; + mystique->dwgreg.iload_rem_data = data64; + break; + + case DWGCTRL_BLTMOD_BMONOWF: + data = (data >> 24) | ((data & 0x00ff0000) >> 8) | ((data & 0x0000ff00) << 8) | (data << 24); + while (size) { + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && + ((data & 0x80000000) || !(mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC)) && + trans[mystique->dwgreg.xdst & 3]) { + uint32_t old_dst; + + src = (data & 0x80000000) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_8: + dst = svga->vram[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask]; + + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + + svga->vram[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_16: + dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w]; + + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w) >> 11] = changeframecount; + break; + + case MACCESS_PWIDTH_24: + old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask]; + + dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running); + + *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000); + svga->changedvram[(((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_32: + dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; + + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount; + break; + + default: + fatal("ILOAD RSTR/RPL BMONOWF pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); + } + } + + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + break; + } + if (!(mystique->dwgreg.dwgctrl_running & DWGCTRL_LINEAR)) + break; + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + data <<= 1; + size--; + } + break; + + case DWGCTRL_BLTMOD_BU24RGB: + size += mystique->dwgreg.iload_rem_count; + data64 = mystique->dwgreg.iload_rem_data | ((uint64_t)data << mystique->dwgreg.iload_rem_count); + + while (size >= 24) { + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_32: + dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; + + dst = bitop(data64 & 0xffffff, dst, mystique->dwgreg.dwgctrl_running); + + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount; + break; + + default: + fatal("ILOAD RSTR/RPL BU24RGB pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); + } + } + + data64 >>= 24; + size -= 24; + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + break; + } + data64 = 0; + size = 0; + break; + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + } + + mystique->dwgreg.iload_rem_count = size; + mystique->dwgreg.iload_rem_data = data64; + break; + + default: + fatal("ILOAD DWGCTRL_ATYPE_RPL\n"); + break; + } + break; + + default: + fatal("Unknown ILOAD iload atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + } +} + + +#define CLAMP(x) do { \ + if ((x) & ~0xff) \ + x = ((x) < 0) ? 0 : 0xff; \ + } while (0) + + +static void +blit_iload_iload_scale(mystique_t *mystique, uint32_t data, int size) +{ + svga_t *svga = &mystique->svga; + uint64_t data64 = 0; + int y0, y1; + int u, v; + int dR, dG, dB; + int r0, g0, b0; + int r1, g1, b1; + + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { + case DWGCTRL_BLTMOD_BUYUV: + y0 = (298 * ((int)(data & 0xff) - 16)) >> 8; + u = ((data >> 8) & 0xff) - 0x80; + y1 = (298 * ((int)((data >> 16) & 0xff) - 16)) >> 8; + v = ((data >> 24) & 0xff) - 0x80; + + dR = (309*v) >> 8; + dG = (100*u + 208*v) >> 8; + dB = (516*u) >> 8; + + r0 = y0 + dR; + CLAMP(r0); + g0 = y0 - dG; + CLAMP(g0); + b0 = y0 + dB; + CLAMP(b0); + r1 = y1 + dR; + CLAMP(r1); + g1 = y1 - dG; + CLAMP(g1); + b1 = y1 + dB; + CLAMP(b1); + + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_16: + data = (b0 >> 3) | ((g0 >> 2) << 5) | ((r0 >> 3) << 11); + data |= (((b1 >> 3) | ((g1 >> 2) << 5) | ((r1 >> 3) << 11)) << 16); + size = 32; + break; + case MACCESS_PWIDTH_32: + data64 = b0 | (g0 << 8) | (r0 << 16); + data64 |= ((uint64_t)b0 << 32) | ((uint64_t)g0 << 40) | ((uint64_t)r0 << 48); + size = 64; + break; + + default: + fatal("blit_iload_iload_scale BUYUV pwidth %i\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); + } + break; + + default: + fatal("blit_iload_iload_scale bltmod %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK); + break; + } + + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_16: + while (size >= 16) { + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { + uint16_t dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w]; + dst = bitop(data & 0xffff, dst, mystique->dwgreg.dwgctrl_running); + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w) >> 11] = changeframecount; } mystique->dwgreg.ar[6] += mystique->dwgreg.ar[2]; if ((int32_t)mystique->dwgreg.ar[6] >= 0) { - mystique->dwgreg.ar[6] -= 65536; + mystique->dwgreg.ar[6] -= (mystique->dwgreg.fxright - mystique->dwgreg.fxleft); + data >>= 16; size -= 16; - - mystique->dwgreg.lastpix_r = r; - mystique->dwgreg.lastpix_g = g; - mystique->dwgreg.lastpix_b = b; - r = next_r; - g = next_g; - b = next_b; } if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { mystique->dwgreg.xdst = mystique->dwgreg.fxleft; mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); mystique->dwgreg.ar[6] = mystique->dwgreg.ar[2] - (mystique->dwgreg.fxright - mystique->dwgreg.fxleft); - mystique->dwgreg.lastpix_r = 0; - mystique->dwgreg.lastpix_g = 0; - mystique->dwgreg.lastpix_b = 0; - mystique->dwgreg.length_cur--; if (!mystique->dwgreg.length_cur) { mystique->busy = 0; @@ -3086,1786 +2848,1790 @@ static void blit_iload_iload_high(mystique_t *mystique, uint32_t data, int size) break; } else mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; - } + } + break; + + case MACCESS_PWIDTH_32: + while (size >= 32) { + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { + uint32_t dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; + dst = bitop(data64, dst, mystique->dwgreg.dwgctrl_running); + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount; + } + + mystique->dwgreg.ar[6] += mystique->dwgreg.ar[2]; + if ((int32_t)mystique->dwgreg.ar[6] >= 0) { + mystique->dwgreg.ar[6] -= (mystique->dwgreg.fxright - mystique->dwgreg.fxleft); + data64 >>= 32; + size -= 32; + } + + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + mystique->dwgreg.ar[6] = mystique->dwgreg.ar[2] - (mystique->dwgreg.fxright - mystique->dwgreg.fxleft); + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + break; + } + break; + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + } + break; + + default: + fatal("ILOAD_SCALE pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); + } } -static void blit_iload_iload_highv(mystique_t *mystique, uint32_t data, int size) + +static void +blit_iload_iload_high(mystique_t *mystique, uint32_t data, int size) { - uint8_t *src0, *src1; + svga_t *svga = &mystique->svga; + uint32_t out_data; + int y0, y1, u, v; + int dR, dG, dB; + int r = 0, g = 0, b = 0; + int next_r = 0, next_g = 0, next_b = 0; -// pclog(" iload_highv: data=%08x\n", data); + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { + case DWGCTRL_BLTMOD_BUYUV: + y0 = (298 * ((int)(data & 0xff) - 16)) >> 8; + u = ((data >> 8) & 0xff) - 0x80; + y1 = (298 * ((int)((data >> 16) & 0xff) - 16)) >> 8; + v = ((data >> 24) & 0xff) - 0x80; - switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) - { - case DWGCTRL_BLTMOD_BUYUV: - if (!mystique->dwgreg.highv_line) { - mystique->dwgreg.highv_data = data; - mystique->dwgreg.highv_line = 1; - return; - } - mystique->dwgreg.highv_line = 0; + dR = (309*v) >> 8; + dG = (100*u + 208*v) >> 8; + dB = (516*u) >> 8; - src0 = (uint8_t *)&mystique->dwgreg.highv_data; - src1 = (uint8_t *)&data; - - src1[0] = ((src0[0] * mystique->dwgreg.beta) + (src1[0] * (16 - mystique->dwgreg.beta))) >> 4; - src1[1] = ((src0[1] * mystique->dwgreg.beta) + (src1[1] * (16 - mystique->dwgreg.beta))) >> 4; - src1[2] = ((src0[2] * mystique->dwgreg.beta) + (src1[2] * (16 - mystique->dwgreg.beta))) >> 4; - src1[3] = ((src0[3] * mystique->dwgreg.beta) + (src1[3] * (16 - mystique->dwgreg.beta))) >> 4; - blit_iload_iload_high(mystique, data, 32); - break; + r = y0 + dR; + CLAMP(r); + g = y0 - dG; + CLAMP(g); + b = y0 + dB; + CLAMP(b); + + next_r = y1 + dR; + CLAMP(next_r); + next_g = y1 - dG; + CLAMP(next_g); + next_b = y1 + dB; + CLAMP(next_b); + + size = 32; + break; + + default: + fatal("blit_iload_iload_high bltmod %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK); + break; + } + + while (size >= 16) { + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { + uint32_t dst; + int f1 = (mystique->dwgreg.ar[6] >> 12) & 0xf; + int f0 = 0x10 - f1; + int out_r = ((mystique->dwgreg.lastpix_r * f0) + (r * f1)) >> 4; + int out_g = ((mystique->dwgreg.lastpix_g * f0) + (g * f1)) >> 4; + int out_b = ((mystique->dwgreg.lastpix_b * f0) + (b * f1)) >> 4; + + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_16: + out_data = (out_b >> 3) | ((out_g >> 2) << 5) | ((out_r >> 3) << 11); + dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w]; + dst = bitop(out_data, dst, mystique->dwgreg.dwgctrl_running); + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w) >> 11] = changeframecount; + break; + case MACCESS_PWIDTH_32: + out_data = out_b | (out_g << 8) | (out_r << 16); + dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; + dst = bitop(out_data, dst, mystique->dwgreg.dwgctrl_running); + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount; + break; default: - fatal("blit_iload_iload_highv bltmod %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK); - break; - } + fatal("ILOAD_SCALE_HIGH RSTR/RPL BUYUV pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); + } + } + + mystique->dwgreg.ar[6] += mystique->dwgreg.ar[2]; + if ((int32_t)mystique->dwgreg.ar[6] >= 0) { + mystique->dwgreg.ar[6] -= 65536; + size -= 16; + + mystique->dwgreg.lastpix_r = r; + mystique->dwgreg.lastpix_g = g; + mystique->dwgreg.lastpix_b = b; + r = next_r; + g = next_g; + b = next_b; + } + + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + mystique->dwgreg.ar[6] = mystique->dwgreg.ar[2] - (mystique->dwgreg.fxright - mystique->dwgreg.fxleft); + mystique->dwgreg.lastpix_r = 0; + mystique->dwgreg.lastpix_g = 0; + mystique->dwgreg.lastpix_b = 0; + + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + break; + } + break; + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + } } -static void blit_iload_write(mystique_t *mystique, uint32_t data, int size) + +static void +blit_iload_iload_highv(mystique_t *mystique, uint32_t data, int size) { -// pclog(" ILOAD %08x %08x\n", data, mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK); - switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) - { - case DWGCTRL_OPCODE_ILOAD: - blit_iload_iload(mystique, data, size); - break; - - case DWGCTRL_OPCODE_ILOAD_SCALE: - blit_iload_iload_scale(mystique, data, size); - break; + uint8_t *src0, *src1; - case DWGCTRL_OPCODE_ILOAD_HIGH: - blit_iload_iload_high(mystique, data, size); - break; + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { + case DWGCTRL_BLTMOD_BUYUV: + if (!mystique->dwgreg.highv_line) { + mystique->dwgreg.highv_data = data; + mystique->dwgreg.highv_line = 1; + return; + } + mystique->dwgreg.highv_line = 0; - case DWGCTRL_OPCODE_ILOAD_HIGHV: - blit_iload_iload_highv(mystique, data, size); - break; + src0 = (uint8_t *)&mystique->dwgreg.highv_data; + src1 = (uint8_t *)&data; - default: - fatal("blit_iload_write: bad opcode %08x\n", mystique->dwgreg.dwgctrl_running); - } + src1[0] = ((src0[0] * mystique->dwgreg.beta) + (src1[0] * (16 - mystique->dwgreg.beta))) >> 4; + src1[1] = ((src0[1] * mystique->dwgreg.beta) + (src1[1] * (16 - mystique->dwgreg.beta))) >> 4; + src1[2] = ((src0[2] * mystique->dwgreg.beta) + (src1[2] * (16 - mystique->dwgreg.beta))) >> 4; + src1[3] = ((src0[3] * mystique->dwgreg.beta) + (src1[3] * (16 - mystique->dwgreg.beta))) >> 4; + blit_iload_iload_high(mystique, data, 32); + break; + + default: + fatal("blit_iload_iload_highv bltmod %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK); + break; + } } -static int z_check(uint16_t z, uint16_t old_z, uint32_t z_mode)//mystique->dwgreg.dwgctrl & DWGCTRL_ZMODE_MASK) + +static void +blit_iload_write(mystique_t *mystique, uint32_t data, int size) { - switch (z_mode) - { - case DWGCTRL_ZMODE_ZE: - return (z == old_z); + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) { + case DWGCTRL_OPCODE_ILOAD: + blit_iload_iload(mystique, data, size); + break; + + case DWGCTRL_OPCODE_ILOAD_SCALE: + blit_iload_iload_scale(mystique, data, size); + break; + + case DWGCTRL_OPCODE_ILOAD_HIGH: + blit_iload_iload_high(mystique, data, size); + break; + + case DWGCTRL_OPCODE_ILOAD_HIGHV: + blit_iload_iload_highv(mystique, data, size); + break; + + default: + fatal("blit_iload_write: bad opcode %08x\n", mystique->dwgreg.dwgctrl_running); + } +} + + +static int +z_check(uint16_t z, uint16_t old_z, uint32_t z_mode)//mystique->dwgreg.dwgctrl & DWGCTRL_ZMODE_MASK) +{ + switch (z_mode) { + case DWGCTRL_ZMODE_ZE: + return (z == old_z); case DWGCTRL_ZMODE_ZNE: - return (z != old_z); + return (z != old_z); case DWGCTRL_ZMODE_ZLT: - return (z < old_z); + return (z < old_z); case DWGCTRL_ZMODE_ZLTE: - return (z <= old_z); + return (z <= old_z); case DWGCTRL_ZMODE_ZGT: - return (z > old_z); + return (z > old_z); case DWGCTRL_ZMODE_ZGTE: - return (z >= old_z); + return (z >= old_z); - case DWGCTRL_ZMODE_NOZCMP: - default: - return 1; - } + case DWGCTRL_ZMODE_NOZCMP: + default: + return 1; + } } -static void blit_line(mystique_t *mystique, int closed) + +static void +blit_line(mystique_t *mystique, int closed) { - svga_t *svga = &mystique->svga; - uint32_t src, dst, old_dst; - int x; - int z_write; + svga_t *svga = &mystique->svga; + uint32_t src, dst, old_dst; + int x; + int z_write; - switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) - { - case DWGCTRL_ATYPE_RSTR: - case DWGCTRL_ATYPE_RPL: - x = mystique->dwgreg.xdst; - while (mystique->dwgreg.length > 0) { - if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { - switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) - { + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { + case DWGCTRL_ATYPE_RSTR: + case DWGCTRL_ATYPE_RPL: + x = mystique->dwgreg.xdst; + while (mystique->dwgreg.length > 0) { + if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_8: + src = mystique->dwgreg.fcol; + dst = svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask]; + + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_16: + src = mystique->dwgreg.fcol; + dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w]; + + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount; + break; + + case MACCESS_PWIDTH_24: + src = mystique->dwgreg.fcol; + old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask]; + + dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running); + *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000); + svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_32: + src = mystique->dwgreg.fcol; + dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l]; + + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l) >> 10] = changeframecount; + break; + + default: + fatal("LINE RSTR/RPL PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); + } + } + + if (mystique->dwgreg.sgn.sdydxl) + x += (mystique->dwgreg.sgn.sdxl ? -1 : 1); + else + mystique->dwgreg.ydst_lin += (mystique->dwgreg.sgn.sdy ? -(mystique->dwgreg.pitch & PITCH_MASK) : (mystique->dwgreg.pitch & PITCH_MASK)); + + if ((int32_t)mystique->dwgreg.ar[1] >= 0) { + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; + if (mystique->dwgreg.sgn.sdydxl) + mystique->dwgreg.ydst_lin += (mystique->dwgreg.sgn.sdy ? -(mystique->dwgreg.pitch & PITCH_MASK) : (mystique->dwgreg.pitch & PITCH_MASK)); + else + x += (mystique->dwgreg.sgn.sdxl ? -1 : 1); + } else + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; + + mystique->dwgreg.length--; + } + break; + + case DWGCTRL_ATYPE_I: + case DWGCTRL_ATYPE_ZI: + z_write = ((mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) == DWGCTRL_ATYPE_ZI); + x = mystique->dwgreg.xdst; + while (mystique->dwgreg.length > 0) { + if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { + uint16_t z = ((int32_t)mystique->dwgreg.dr[0] < 0) ? 0 : (mystique->dwgreg.dr[0] >> 15); + uint16_t *z_p = (uint16_t *)&svga->vram[(mystique->dwgreg.ydst_lin*2 + mystique->dwgreg.zorg) & mystique->vram_mask]; + uint16_t old_z = z_p[x]; + + if (z_check(z, old_z, mystique->dwgreg.dwgctrl_running & DWGCTRL_ZMODE_MASK)) { + int r = 0, g = 0, b = 0; + + if (z_write) + z_p[x] = z; + + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_16: + if (!(mystique->dwgreg.dr[4] & (1 << 23))) + r = (mystique->dwgreg.dr[4] >> 18) & 0x1f; + if (!(mystique->dwgreg.dr[8] & (1 << 23))) + g = (mystique->dwgreg.dr[8] >> 17) & 0x3f; + if (!(mystique->dwgreg.dr[12] & (1 << 23))) + b = (mystique->dwgreg.dr[12] >> 18) & 0x1f; + dst = (r << 11) | (g << 5) | b; + + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount; + break; + + default: + fatal("LINE I/ZI PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); + } + } + } + + if (mystique->dwgreg.sgn.sdydxl) + x += (mystique->dwgreg.sgn.sdxl ? -1 : 1); + else + mystique->dwgreg.ydst_lin += (mystique->dwgreg.sgn.sdy ? -(mystique->dwgreg.pitch & PITCH_MASK) : (mystique->dwgreg.pitch & PITCH_MASK)); + + mystique->dwgreg.dr[0] += mystique->dwgreg.dr[2]; + mystique->dwgreg.dr[4] += mystique->dwgreg.dr[6]; + mystique->dwgreg.dr[8] += mystique->dwgreg.dr[10]; + mystique->dwgreg.dr[12] += mystique->dwgreg.dr[14]; + + if ((int32_t)mystique->dwgreg.ar[1] >= 0) { + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; + + if (mystique->dwgreg.sgn.sdydxl) + mystique->dwgreg.ydst_lin += (mystique->dwgreg.sgn.sdy ? -(mystique->dwgreg.pitch & PITCH_MASK) : (mystique->dwgreg.pitch & PITCH_MASK)); + else + x += (mystique->dwgreg.sgn.sdxl ? -1 : 1); + + mystique->dwgreg.dr[0] += mystique->dwgreg.dr[3]; + mystique->dwgreg.dr[4] += mystique->dwgreg.dr[7]; + mystique->dwgreg.dr[8] += mystique->dwgreg.dr[11]; + mystique->dwgreg.dr[12] += mystique->dwgreg.dr[15]; + } else + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; + + mystique->dwgreg.length--; + } + break; + + default: + fatal("Unknown atype %03x %08x LINE\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + } + + mystique->blitter_complete_refcount++; +} + + +static void +blit_autoline(mystique_t *mystique, int closed) +{ + int start_x = (int32_t)mystique->dwgreg.ar[5]; + int start_y = (int32_t)mystique->dwgreg.ar[6]; + int end_x = (int32_t)mystique->dwgreg.ar[0]; + int end_y = (int32_t)mystique->dwgreg.ar[2]; + int dx = end_x - start_x; + int dy = end_y - start_y; + + if (ABS(dx) > ABS(dy)) { + mystique->dwgreg.sgn.sdydxl = 1; + mystique->dwgreg.ar[0] = 2*ABS(dy); + mystique->dwgreg.ar[1] = 2*ABS(dy) - ABS(dx) - ((start_y > end_y) ? 1 : 0); + mystique->dwgreg.ar[2] = 2*ABS(dy) - 2*ABS(dx); + mystique->dwgreg.length = ABS(end_x - start_x); + } else { + mystique->dwgreg.sgn.sdydxl = 0; + mystique->dwgreg.ar[0] = 2*ABS(dx); + mystique->dwgreg.ar[1] = 2*ABS(dx) - ABS(dy) - ((start_y > end_y) ? 1 : 0); + mystique->dwgreg.ar[2] = 2*ABS(dx) - 2*ABS(dy); + mystique->dwgreg.length = ABS(end_y - start_y); + } + mystique->dwgreg.sgn.sdxl = (start_x > end_x) ? 1 : 0; + mystique->dwgreg.sgn.sdy = (start_y > end_y) ? 1 : 0; + + blit_line(mystique, closed); + + mystique->dwgreg.ar[5] = end_x; + mystique->dwgreg.xdst = end_x; + mystique->dwgreg.ar[6] = end_y; + mystique->dwgreg.ydst = end_y; + mystique->dwgreg.ydst_lin = ((int32_t)(int16_t)mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; +} + + +static void +blit_trap(mystique_t *mystique) +{ + svga_t *svga = &mystique->svga; + uint32_t z_back, r_back, g_back, b_back; + int z_write; + int y; + const int trans_sel = (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANS_MASK) >> DWGCTRL_TRANS_SHIFT; + + mystique->trap_count++; + + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { + case DWGCTRL_ATYPE_BLK: + case DWGCTRL_ATYPE_RPL: + for (y = 0; y < mystique->dwgreg.length; y++) { + uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; + int x_l = mystique->dwgreg.fxleft & 0xffff; + int x_r = mystique->dwgreg.fxright & 0xffff; + int yoff = (mystique->dwgreg.yoff + mystique->dwgreg.ydst) & 7; + + while (x_l != x_r) { + if (x_l >= mystique->dwgreg.cxleft && x_l <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && + trans[x_l & 3]) { + int xoff = (mystique->dwgreg.xoff + x_l) & 7; + int pattern = mystique->dwgreg.pattern[yoff][xoff]; + uint32_t dst; + + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_8: + svga->vram[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask] = + (pattern ? mystique->dwgreg.fcol : mystique->dwgreg.bcol) & 0xff; + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_16: + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w] = + (pattern ? mystique->dwgreg.fcol : mystique->dwgreg.bcol) & 0xffff; + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w) >> 11] = changeframecount; + break; + + case MACCESS_PWIDTH_24: + dst = *(uint32_t *)(&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask]) & 0xff000000; + *(uint32_t *)(&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask]) = + ((pattern ? mystique->dwgreg.fcol : mystique->dwgreg.bcol) & 0xffffff) | dst; + svga->changedvram[(((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_32: + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l] = + pattern ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l) >> 10] = changeframecount; + break; + + default: + fatal("TRAP BLK/RPL PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); + } + } + x_l = (x_l + 1) & 0xffff; + mystique->pixel_count++; + } + + if ((int32_t)mystique->dwgreg.ar[1] < 0) { + while ((int32_t)mystique->dwgreg.ar[1] < 0 && mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; + mystique->dwgreg.fxleft += (mystique->dwgreg.sgn.sdxl ? -1 : 1); + } + } else + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; + + if ((int32_t)mystique->dwgreg.ar[4] < 0) { + while ((int32_t)mystique->dwgreg.ar[4] < 0 && mystique->dwgreg.ar[6]) { + mystique->dwgreg.ar[4] += mystique->dwgreg.ar[6]; + mystique->dwgreg.fxright += (mystique->dwgreg.sgn.sdxr ? -1 : 1); + } + } else + mystique->dwgreg.ar[4] += mystique->dwgreg.ar[5]; + + mystique->dwgreg.ydst++; + mystique->dwgreg.ydst &= 0x7fffff; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + + mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7; + } + break; + + case DWGCTRL_ATYPE_RSTR: + for (y = 0; y < mystique->dwgreg.length; y++) { + uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; + int x_l = mystique->dwgreg.fxleft & 0xffff; + int x_r = mystique->dwgreg.fxright & 0xffff; + int yoff = (mystique->dwgreg.yoff + mystique->dwgreg.ydst) & 7; + + while (x_l != x_r) { + if (x_l >= mystique->dwgreg.cxleft && x_l <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && + trans[x_l & 3]) { + int xoff = (mystique->dwgreg.xoff + x_l) & 7; + int pattern = mystique->dwgreg.pattern[yoff][xoff]; + uint32_t src = pattern ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; + uint32_t dst, old_dst; + + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_8: + dst = svga->vram[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask]; + + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + svga->vram[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_16: + dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w]; + + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w) >> 11] = changeframecount; + break; + + case MACCESS_PWIDTH_24: + old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask]; + + dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running); + *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000); + svga->changedvram[(((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_32: + dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l]; + + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l) >> 10] = changeframecount; + break; + + default: + fatal("TRAP RSTR PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); + } + } + x_l = (x_l + 1) & 0xffff; + mystique->pixel_count++; + } + + if ((int32_t)mystique->dwgreg.ar[1] < 0) { + while ((int32_t)mystique->dwgreg.ar[1] < 0 && mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; + mystique->dwgreg.fxleft += (mystique->dwgreg.sgn.sdxl ? -1 : 1); + } + } else + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; + + if ((int32_t)mystique->dwgreg.ar[4] < 0) { + while ((int32_t)mystique->dwgreg.ar[4] < 0 && mystique->dwgreg.ar[6]) { + mystique->dwgreg.ar[4] += mystique->dwgreg.ar[6]; + mystique->dwgreg.fxright += (mystique->dwgreg.sgn.sdxr ? -1 : 1); + } + } else + mystique->dwgreg.ar[4] += mystique->dwgreg.ar[5]; + + mystique->dwgreg.ydst++; + mystique->dwgreg.ydst &= 0x7fffff; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + + mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7; + } + break; + + case DWGCTRL_ATYPE_I: + case DWGCTRL_ATYPE_ZI: + z_write = ((mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) == DWGCTRL_ATYPE_ZI); + + for (y = 0; y < mystique->dwgreg.length; y++) { + uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; + uint16_t *z_p = (uint16_t *)&svga->vram[(mystique->dwgreg.ydst_lin*2 + mystique->dwgreg.zorg) & mystique->vram_mask]; + int x_l = mystique->dwgreg.fxleft & 0xffff; + int x_r = mystique->dwgreg.fxright & 0xffff; + int old_x_l = x_l; + int dx; + + z_back = mystique->dwgreg.dr[0]; + r_back = mystique->dwgreg.dr[4]; + g_back = mystique->dwgreg.dr[8]; + b_back = mystique->dwgreg.dr[12]; + + while (x_l != x_r) { + if (x_l >= mystique->dwgreg.cxleft && x_l <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && + trans[x_l & 3]) { + uint16_t z = ((int32_t)mystique->dwgreg.dr[0] < 0) ? 0 : (mystique->dwgreg.dr[0] >> 15); + uint16_t old_z = z_p[x_l]; + + if (z_check(z, old_z, mystique->dwgreg.dwgctrl_running & DWGCTRL_ZMODE_MASK)) { + uint32_t dst = 0, old_dst; + int r = 0, g = 0, b = 0; + + if (!(mystique->dwgreg.dr[4] & (1 << 23))) + r = (mystique->dwgreg.dr[4] >> 15) & 0xff; + if (!(mystique->dwgreg.dr[8] & (1 << 23))) + g = (mystique->dwgreg.dr[8] >> 15) & 0xff; + if (!(mystique->dwgreg.dr[12] & (1 << 23))) + b = (mystique->dwgreg.dr[12] >> 15) & 0xff; + + if (z_write) + z_p[x_l] = z; + + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { case MACCESS_PWIDTH_8: - src = mystique->dwgreg.fcol; - dst = svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask]; - -// pclog(" LINE %i %08x %08x\n", x, mystique->dwgreg.ydst_lin, mystique->dwgreg.ar[1]); - dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); - svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount; + svga->vram[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask) >> 12] = changeframecount; break; case MACCESS_PWIDTH_16: - src = mystique->dwgreg.fcol; - dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w]; - -// pclog(" LINE %i %08x %08x\n", x, mystique->dwgreg.ydst_lin, mystique->dwgreg.ar[1]); - dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); - ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount; + dst = dither(mystique, r, g, b, x_l & 1, mystique->dwgreg.selline & 1); + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w) >> 11] = changeframecount; break; case MACCESS_PWIDTH_24: - src = mystique->dwgreg.fcol; - old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask]; - -// pclog(" LINE %i %08x %08x\n", x, mystique->dwgreg.ydst_lin, mystique->dwgreg.ar[1]); - dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running); - *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000); - svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount; + old_dst = *(uint32_t *)(&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask]) & 0xff000000; + *(uint32_t *)(&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask]) = old_dst | dst; + svga->changedvram[(((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask) >> 12] = changeframecount; break; case MACCESS_PWIDTH_32: - src = mystique->dwgreg.fcol; - dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l]; - -// pclog(" LINE %i %08x %08x\n", x, mystique->dwgreg.ydst_lin, mystique->dwgreg.ar[1]); - dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); - ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l) >> 10] = changeframecount; + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l] = b | (g << 8) | (r << 16); + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l) >> 10] = changeframecount; break; - + default: - fatal("LINE RSTR/RPL PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); + fatal("TRAP BLK/RPL PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); } } - - if (mystique->dwgreg.sgn.sdydxl) - x += (mystique->dwgreg.sgn.sdxl ? -1 : 1); - else - mystique->dwgreg.ydst_lin += (mystique->dwgreg.sgn.sdy ? -(mystique->dwgreg.pitch & PITCH_MASK) : (mystique->dwgreg.pitch & PITCH_MASK)); + } - if ((int32_t)mystique->dwgreg.ar[1] >= 0) { - mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; - if (mystique->dwgreg.sgn.sdydxl) - mystique->dwgreg.ydst_lin += (mystique->dwgreg.sgn.sdy ? -(mystique->dwgreg.pitch & PITCH_MASK) : (mystique->dwgreg.pitch & PITCH_MASK)); - else - x += (mystique->dwgreg.sgn.sdxl ? -1 : 1); - } else - mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; - - mystique->dwgreg.length--; - } - break; + mystique->dwgreg.dr[0] += mystique->dwgreg.dr[2]; + mystique->dwgreg.dr[4] += mystique->dwgreg.dr[6]; + mystique->dwgreg.dr[8] += mystique->dwgreg.dr[10]; + mystique->dwgreg.dr[12] += mystique->dwgreg.dr[14]; - case DWGCTRL_ATYPE_I: - case DWGCTRL_ATYPE_ZI: - z_write = ((mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) == DWGCTRL_ATYPE_ZI); - x = mystique->dwgreg.xdst; - while (mystique->dwgreg.length > 0) { - if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { + x_l = (x_l + 1) & 0xffff; + mystique->pixel_count++; + } + + mystique->dwgreg.dr[0] = z_back + mystique->dwgreg.dr[3]; + mystique->dwgreg.dr[4] = r_back + mystique->dwgreg.dr[7]; + mystique->dwgreg.dr[8] = g_back + mystique->dwgreg.dr[11]; + mystique->dwgreg.dr[12] = b_back + mystique->dwgreg.dr[15]; + + while ((int32_t)mystique->dwgreg.ar[1] < 0 && mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; + mystique->dwgreg.fxleft += (mystique->dwgreg.sgn.sdxl ? -1 : 1); + } + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; + + while ((int32_t)mystique->dwgreg.ar[4] < 0 && mystique->dwgreg.ar[6]) { + mystique->dwgreg.ar[4] += mystique->dwgreg.ar[6]; + mystique->dwgreg.fxright += (mystique->dwgreg.sgn.sdxr ? -1 : 1); + } + mystique->dwgreg.ar[4] += mystique->dwgreg.ar[5]; + + dx = (int16_t)((mystique->dwgreg.fxleft - old_x_l) & 0xffff); + mystique->dwgreg.dr[0] += dx*mystique->dwgreg.dr[2]; + mystique->dwgreg.dr[4] += dx*mystique->dwgreg.dr[6]; + mystique->dwgreg.dr[8] += dx*mystique->dwgreg.dr[10]; + mystique->dwgreg.dr[12] += dx*mystique->dwgreg.dr[14]; + + mystique->dwgreg.ydst++; + mystique->dwgreg.ydst &= 0x7fffff; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + + mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7; + } + break; + + default: + fatal("Unknown atype %03x %08x TRAP\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + } + + mystique->blitter_complete_refcount++; +} + + +static int texture_read(mystique_t *mystique, int *tex_r, int *tex_g, int *tex_b, int *atransp) +{ + svga_t *svga = &mystique->svga; + + const int tex_shift = 3 + ((mystique->dwgreg.texctl & TEXCTL_TPITCH_MASK) >> TEXCTL_TPITCH_SHIFT); + const unsigned int palsel = mystique->dwgreg.texctl & TEXCTL_PALSEL_MASK; + const uint16_t tckey = mystique->dwgreg.textrans & TEXTRANS_TCKEY_MASK; + const uint16_t tkmask = (mystique->dwgreg.textrans & TEXTRANS_TKMASK_MASK) >> TEXTRANS_TKMASK_SHIFT; + const unsigned int w_mask = (mystique->dwgreg.texwidth & TEXWIDTH_TWMASK_MASK) >> TEXWIDTH_TWMASK_SHIFT; + const unsigned int h_mask = (mystique->dwgreg.texheight & TEXHEIGHT_THMASK_MASK) >> TEXHEIGHT_THMASK_SHIFT; + uint16_t src = 0; + int s, t; + + if (mystique->dwgreg.texctl & TEXCTL_NPCEN) { + const int s_shift = 20 - (mystique->dwgreg.texwidth & TEXWIDTH_TW_MASK); + const int t_shift = 20 - (mystique->dwgreg.texheight & TEXHEIGHT_TH_MASK); + + s = (int32_t)mystique->dwgreg.tmr[6] >> s_shift; + t = (int32_t)mystique->dwgreg.tmr[7] >> t_shift; + } else { + const int s_shift = (20 + 16) - (mystique->dwgreg.texwidth & TEXWIDTH_TW_MASK); + const int t_shift = (20 + 16) - (mystique->dwgreg.texheight & TEXHEIGHT_TH_MASK); + int64_t q = mystique->dwgreg.tmr[8] ? ((0x100000000ll / (int64_t)(int32_t)mystique->dwgreg.tmr[8]) /*>> 16*/) : 0; + + s = (((int64_t)(int32_t)mystique->dwgreg.tmr[6] * q) /*<< 8*/) >> s_shift;/*((16+20)-12);*/ + t = (((int64_t)(int32_t)mystique->dwgreg.tmr[7] * q) /*<< 8*/) >> t_shift;/*((16+20)-9);*/ + } + + if (mystique->dwgreg.texctl & TEXCTL_CLAMPU) { + if (s < 0) + s = 0; + else if (s > w_mask) + s = w_mask; + } else + s &= w_mask; + + if (mystique->dwgreg.texctl & TEXCTL_CLAMPV) { + if (t < 0) + t = 0; + else if (t > h_mask) + t = h_mask; + } else + t &= h_mask; + + switch (mystique->dwgreg.texctl & TEXCTL_TEXFORMAT_MASK) { + case TEXCTL_TEXFORMAT_TW4: + src = svga->vram[(mystique->dwgreg.texorg + (((t << tex_shift) + s) >> 1)) & mystique->vram_mask]; + if (s & 1) + src >>= 4; + else + src &= 0xf; + *tex_r = mystique->lut[src | palsel].r; + *tex_g = mystique->lut[src | palsel].g; + *tex_b = mystique->lut[src | palsel].b; + *atransp = 0; + break; + case TEXCTL_TEXFORMAT_TW8: + src = svga->vram[(mystique->dwgreg.texorg + (t << tex_shift) + s) & mystique->vram_mask]; + *tex_r = mystique->lut[src].r; + *tex_g = mystique->lut[src].g; + *tex_b = mystique->lut[src].b; + *atransp = 0; + break; + case TEXCTL_TEXFORMAT_TW15: + src = ((uint16_t *)svga->vram)[((mystique->dwgreg.texorg >> 1) + (t << tex_shift) + s) & mystique->vram_mask_w]; + *tex_r = ((src >> 10) & 0x1f) << 3; + *tex_g = ((src >> 5) & 0x1f) << 3; + *tex_b = (src & 0x1f) << 3; + if (((src >> 15) & mystique->dwgreg.ta_mask) == mystique->dwgreg.ta_key) + *atransp = 1; + else + *atransp = 0; + break; + case TEXCTL_TEXFORMAT_TW16: + src = ((uint16_t *)svga->vram)[((mystique->dwgreg.texorg >> 1) + (t << tex_shift) + s) & mystique->vram_mask_w]; + *tex_r = (src >> 11) << 3; + *tex_g = ((src >> 5) & 0x3f) << 2; + *tex_b = (src & 0x1f) << 3; + *atransp = 0; + break; + default: + fatal("Unknown texture format %i\n", mystique->dwgreg.texctl & TEXCTL_TEXFORMAT_MASK); + break; + } + + return ((src & tkmask) == tckey); +} + + +static void +blit_texture_trap(mystique_t *mystique) +{ + svga_t *svga = &mystique->svga; + int y; + int z_write; + const int trans_sel = (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANS_MASK) >> DWGCTRL_TRANS_SHIFT; + const int dest32 = ((mystique->maccess_running & MACCESS_PWIDTH_MASK) == MACCESS_PWIDTH_32); + + mystique->trap_count++; + + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { + case DWGCTRL_ATYPE_I: + case DWGCTRL_ATYPE_ZI: + z_write = ((mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) == DWGCTRL_ATYPE_ZI); + + for (y = 0; y < mystique->dwgreg.length; y++) { + uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; + uint16_t *z_p = (uint16_t *)&svga->vram[(mystique->dwgreg.ydst_lin*2 + mystique->dwgreg.zorg) & mystique->vram_mask]; + int x_l = mystique->dwgreg.fxleft & 0xffff; + int x_r = mystique->dwgreg.fxright & 0xffff; + int old_x_l = x_l; + int dx; + + uint32_t z_back = mystique->dwgreg.dr[0]; + uint32_t r_back = mystique->dwgreg.dr[4]; + uint32_t g_back = mystique->dwgreg.dr[8]; + uint32_t b_back = mystique->dwgreg.dr[12]; + uint32_t s_back = mystique->dwgreg.tmr[6]; + uint32_t t_back = mystique->dwgreg.tmr[7]; + uint32_t q_back = mystique->dwgreg.tmr[8]; + + while (x_l != x_r) { + if (x_l >= mystique->dwgreg.cxleft && x_l <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && + trans[x_l & 3]) { uint16_t z = ((int32_t)mystique->dwgreg.dr[0] < 0) ? 0 : (mystique->dwgreg.dr[0] >> 15); - uint16_t *z_p = (uint16_t *)&svga->vram[(mystique->dwgreg.ydst_lin*2 + mystique->dwgreg.zorg) & mystique->vram_mask]; - uint16_t old_z = z_p[x]; + uint16_t old_z = z_p[x_l]; if (z_check(z, old_z, mystique->dwgreg.dwgctrl_running & DWGCTRL_ZMODE_MASK)) { - int r = 0, g = 0, b = 0; - - if (z_write) - z_p[x] = z; + int tex_r = 0, tex_g = 0, tex_b = 0; + int ctransp, atransp = 0; + int i_r = 0, i_g = 0, i_b = 0; - switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) - { - case MACCESS_PWIDTH_16: - if (!(mystique->dwgreg.dr[4] & (1 << 23))) - r = (mystique->dwgreg.dr[4] >> 18) & 0x1f; - if (!(mystique->dwgreg.dr[8] & (1 << 23))) - g = (mystique->dwgreg.dr[8] >> 17) & 0x3f; - if (!(mystique->dwgreg.dr[12] & (1 << 23))) - b = (mystique->dwgreg.dr[12] >> 18) & 0x1f; - dst = (r << 11) | (g << 5) | b; + if (!(mystique->dwgreg.dr[4] & (1 << 23))) + i_r = (mystique->dwgreg.dr[4] >> 15) & 0xff; + if (!(mystique->dwgreg.dr[8] & (1 << 23))) + i_g = (mystique->dwgreg.dr[8] >> 15) & 0xff; + if (!(mystique->dwgreg.dr[12] & (1 << 23))) + i_b = (mystique->dwgreg.dr[12] >> 15) & 0xff; - ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount; + ctransp = texture_read(mystique, &tex_r, &tex_g, &tex_b, &atransp); + + switch (mystique->dwgreg.texctl & (TEXCTL_TMODULATE | TEXCTL_STRANS | TEXCTL_ITRANS | TEXCTL_DECALCKEY)) { + case 0: + if (ctransp) + goto skip_pixel; + if (atransp) { + tex_r = i_r; + tex_g = i_g; + tex_b = i_b; + } + break; + + case TEXCTL_DECALCKEY: + if (ctransp) { + tex_r = i_r; + tex_g = i_g; + tex_b = i_b; + } + break; + + case (TEXCTL_STRANS | TEXCTL_DECALCKEY): + if (ctransp) + goto skip_pixel; + break; + + case TEXCTL_TMODULATE: + if (ctransp) + goto skip_pixel; + if (mystique->dwgreg.texctl & TEXCTL_TMODULATE) { + tex_r = (tex_r * i_r) >> 8; + tex_g = (tex_g * i_g) >> 8; + tex_b = (tex_b * i_b) >> 8; + } + break; + + case (TEXCTL_TMODULATE | TEXCTL_STRANS): + if (ctransp || atransp) + goto skip_pixel; + if (mystique->dwgreg.texctl & TEXCTL_TMODULATE) { + tex_r = (tex_r * i_r) >> 8; + tex_g = (tex_g * i_g) >> 8; + tex_b = (tex_b * i_b) >> 8; + } break; default: - fatal("LINE I/ZI PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); + fatal("Bad TEXCTL %08x %08x\n", mystique->dwgreg.texctl, mystique->dwgreg.texctl & (TEXCTL_TMODULATE | TEXCTL_STRANS | TEXCTL_ITRANS | TEXCTL_DECALCKEY)); } + + if (dest32) { + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l] = tex_b | (tex_g << 8) | (tex_r << 16); + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l) >> 10] = changeframecount; + } else { + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w] = dither(mystique, tex_r, tex_g, tex_b, x_l & 1, mystique->dwgreg.selline & 1); + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w) >> 11] = changeframecount; + } + if (z_write) + z_p[x_l] = z; } } - - if (mystique->dwgreg.sgn.sdydxl) - x += (mystique->dwgreg.sgn.sdxl ? -1 : 1); - else - mystique->dwgreg.ydst_lin += (mystique->dwgreg.sgn.sdy ? -(mystique->dwgreg.pitch & PITCH_MASK) : (mystique->dwgreg.pitch & PITCH_MASK)); +skip_pixel: + x_l = (x_l + 1) & 0xffff; + mystique->pixel_count++; mystique->dwgreg.dr[0] += mystique->dwgreg.dr[2]; mystique->dwgreg.dr[4] += mystique->dwgreg.dr[6]; mystique->dwgreg.dr[8] += mystique->dwgreg.dr[10]; mystique->dwgreg.dr[12] += mystique->dwgreg.dr[14]; + mystique->dwgreg.tmr[6] += mystique->dwgreg.tmr[0]; + mystique->dwgreg.tmr[7] += mystique->dwgreg.tmr[2]; + mystique->dwgreg.tmr[8] += mystique->dwgreg.tmr[4]; + } - if ((int32_t)mystique->dwgreg.ar[1] >= 0) { - mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; - - if (mystique->dwgreg.sgn.sdydxl) - mystique->dwgreg.ydst_lin += (mystique->dwgreg.sgn.sdy ? -(mystique->dwgreg.pitch & PITCH_MASK) : (mystique->dwgreg.pitch & PITCH_MASK)); - else - x += (mystique->dwgreg.sgn.sdxl ? -1 : 1); - - mystique->dwgreg.dr[0] += mystique->dwgreg.dr[3]; - mystique->dwgreg.dr[4] += mystique->dwgreg.dr[7]; - mystique->dwgreg.dr[8] += mystique->dwgreg.dr[11]; - mystique->dwgreg.dr[12] += mystique->dwgreg.dr[15]; - } else - mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; + mystique->dwgreg.dr[0] = z_back + mystique->dwgreg.dr[3]; + mystique->dwgreg.dr[4] = r_back + mystique->dwgreg.dr[7]; + mystique->dwgreg.dr[8] = g_back + mystique->dwgreg.dr[11]; + mystique->dwgreg.dr[12] = b_back + mystique->dwgreg.dr[15]; + mystique->dwgreg.tmr[6] = s_back + mystique->dwgreg.tmr[1]; + mystique->dwgreg.tmr[7] = t_back + mystique->dwgreg.tmr[3]; + mystique->dwgreg.tmr[8] = q_back + mystique->dwgreg.tmr[5]; - mystique->dwgreg.length--; - } - break; + while ((int32_t)mystique->dwgreg.ar[1] < 0 && mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; + mystique->dwgreg.fxleft += (mystique->dwgreg.sgn.sdxl ? -1 : 1); + } + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; + while ((int32_t)mystique->dwgreg.ar[4] < 0 && mystique->dwgreg.ar[6]) { + mystique->dwgreg.ar[4] += mystique->dwgreg.ar[6]; + mystique->dwgreg.fxright += (mystique->dwgreg.sgn.sdxr ? -1 : 1); + } + mystique->dwgreg.ar[4] += mystique->dwgreg.ar[5]; - default: - fatal("Unknown atype %03x %08x LINE\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); - } - mystique->blitter_complete_refcount++; + dx = (int16_t)((mystique->dwgreg.fxleft - old_x_l) & 0xffff); + mystique->dwgreg.dr[0] += dx*mystique->dwgreg.dr[2]; + mystique->dwgreg.dr[4] += dx*mystique->dwgreg.dr[6]; + mystique->dwgreg.dr[8] += dx*mystique->dwgreg.dr[10]; + mystique->dwgreg.dr[12] += dx*mystique->dwgreg.dr[14]; + mystique->dwgreg.tmr[6] += dx*mystique->dwgreg.tmr[0]; + mystique->dwgreg.tmr[7] += dx*mystique->dwgreg.tmr[2]; + mystique->dwgreg.tmr[8] += dx*mystique->dwgreg.tmr[4]; + + mystique->dwgreg.ydst++; + mystique->dwgreg.ydst &= 0x7fffff; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + + mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7; + } + break; + + default: + fatal("Unknown atype %03x %08x TEXTURE_TRAP\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + } + + mystique->blitter_complete_refcount++; } -static void blit_autoline(mystique_t *mystique, int closed) + +static void +blit_bitblt(mystique_t *mystique) { - int start_x = (int32_t)mystique->dwgreg.ar[5]; - int start_y = (int32_t)mystique->dwgreg.ar[6]; - int end_x = (int32_t)mystique->dwgreg.ar[0]; - int end_y = (int32_t)mystique->dwgreg.ar[2]; - int dx = end_x - start_x; - int dy = end_y - start_y; - - if (ABS(dx) > ABS(dy)) { - mystique->dwgreg.sgn.sdydxl = 1; - mystique->dwgreg.ar[0] = 2*ABS(dy); - mystique->dwgreg.ar[1] = 2*ABS(dy) - ABS(dx) - ((start_y > end_y) ? 1 : 0); - mystique->dwgreg.ar[2] = 2*ABS(dy) - 2*ABS(dx); - mystique->dwgreg.length = ABS(end_x - start_x); - } else { - mystique->dwgreg.sgn.sdydxl = 0; - mystique->dwgreg.ar[0] = 2*ABS(dx); - mystique->dwgreg.ar[1] = 2*ABS(dx) - ABS(dy) - ((start_y > end_y) ? 1 : 0); - mystique->dwgreg.ar[2] = 2*ABS(dx) - 2*ABS(dy); - mystique->dwgreg.length = ABS(end_y - start_y); - } - mystique->dwgreg.sgn.sdxl = (start_x > end_x) ? 1 : 0; - mystique->dwgreg.sgn.sdy = (start_y > end_y) ? 1 : 0; + svga_t *svga = &mystique->svga; + uint32_t src_addr; + int y; + int x_dir = mystique->dwgreg.sgn.scanleft ? -1 : 1; + int x_start = mystique->dwgreg.sgn.scanleft ? mystique->dwgreg.fxright : mystique->dwgreg.fxleft; + int x_end = mystique->dwgreg.sgn.scanleft ? mystique->dwgreg.fxleft : mystique->dwgreg.fxright; + const int trans_sel = (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANS_MASK) >> DWGCTRL_TRANS_SHIFT; + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { + case DWGCTRL_ATYPE_BLK: + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { + case DWGCTRL_BLTMOD_BMONOLEF: + src_addr = mystique->dwgreg.ar[3]; -/* pclog("Autoline %s\n", closed ? "closed" : "open"); - pclog("Start %i,%i\n", start_x, start_y); - pclog("End %i,%i\n", end_x, end_y); - pclog("SGN=%x\n", mystique->dwgreg.sgn); - pclog("AR0=%08x AR1=%08x AR2=%08x\n", mystique->dwgreg.ar[0], - mystique->dwgreg.ar[1], - mystique->dwgreg.ar[2]); - pclog("Length %i\n", mystique->dwgreg.length);*/ - blit_line(mystique, closed); - - mystique->dwgreg.ar[5] = end_x; - mystique->dwgreg.xdst = end_x; - mystique->dwgreg.ar[6] = end_y; - mystique->dwgreg.ydst = end_y; - mystique->dwgreg.ydst_lin = ((int32_t)(int16_t)mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; -} + for (y = 0; y < mystique->dwgreg.length; y++) { + int x = x_start; -static void blit_trap(mystique_t *mystique) -{ - svga_t *svga = &mystique->svga; - uint32_t z_back, r_back, g_back, b_back; - int z_write; - int y; - const int trans_sel = (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANS_MASK) >> DWGCTRL_TRANS_SHIFT; + while (1) { + if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { + uint32_t byte_addr = (src_addr >> 3) & mystique->vram_mask; + int bit_offset = src_addr & 7; + uint32_t old_dst; - mystique->trap_count++; - - switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) - { - case DWGCTRL_ATYPE_BLK: - case DWGCTRL_ATYPE_RPL: - //fxleft, fxright - //fcol -/* pclog("fxleft=%i fxright=%i\n", mystique->dwgreg.fxleft, mystique->dwgreg.fxright); - pclog("fcol=%08x\n", mystique->dwgreg.fcol); - pclog("ytop=%i length=%i\n", mystique->dwgreg.ytop, mystique->dwgreg.length); - pclog("pitch=%08x\n", mystique->dwgreg.pitch); - pclog("ydst_lin=%08x\n", mystique->dwgreg.ydst_lin);*/ -// if (!(mystique->dwgreg.dwgctrl_running & DWGCTRL_SGNZERO)) -// fatal("Not rectangle\n"); - - for (y = 0; y < mystique->dwgreg.length; y++) { - uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; - int x_l = mystique->dwgreg.fxleft & 0xffff; - int x_r = mystique->dwgreg.fxright & 0xffff; - int yoff = (mystique->dwgreg.yoff + mystique->dwgreg.ydst) & 7; - -// pclog(" line %03i: %08x\n", y, mystique->dwgreg.ydst_lin); - while (x_l != x_r) { - if (x_l >= mystique->dwgreg.cxleft && x_l <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && - trans[x_l & 3]) { - int xoff = (mystique->dwgreg.xoff + x_l) & 7; - int pattern = mystique->dwgreg.pattern[yoff][xoff]; - uint32_t dst; - -// pclog(" %06x %02x\n", mystique->dwgreg.ydst_lin + x, mystique->dwgreg.fcol & 0xff); - switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) - { + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { case MACCESS_PWIDTH_8: - svga->vram[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask] = - (pattern ? mystique->dwgreg.fcol : mystique->dwgreg.bcol) & 0xff; - svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask) >> 12] = changeframecount; + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC) { + if (svga->vram[byte_addr] & (1 << bit_offset)) + svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = mystique->dwgreg.fcol; + } else + svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = + (svga->vram[byte_addr] & (1 << bit_offset)) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount; break; - + case MACCESS_PWIDTH_16: - ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w] = - (pattern ? mystique->dwgreg.fcol : mystique->dwgreg.bcol) & 0xffff; - svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w) >> 11] = changeframecount; + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC) { + if (svga->vram[byte_addr] & (1 << bit_offset)) + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = mystique->dwgreg.fcol; + } else + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = + (svga->vram[byte_addr] & (1 << bit_offset)) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount; break; case MACCESS_PWIDTH_24: - dst = *(uint32_t *)(&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask]) & 0xff000000; - *(uint32_t *)(&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask]) = - ((pattern ? mystique->dwgreg.fcol : mystique->dwgreg.bcol) & 0xffffff) | dst; - svga->changedvram[(((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask) >> 12] = changeframecount; + old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask]; + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC) { + if (svga->vram[byte_addr] & (1 << bit_offset)) + *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = + (old_dst & 0xff000000) | (mystique->dwgreg.fcol & 0xffffff); + } else + *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = + (old_dst & 0xff000000) | (((svga->vram[byte_addr] & (1 << bit_offset)) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol) & 0xffffff); + svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount; break; case MACCESS_PWIDTH_32: - ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l] = - pattern ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; - svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l) >> 10] = changeframecount; + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC) { + if (svga->vram[byte_addr] & (1 << bit_offset)) + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l] = mystique->dwgreg.fcol; + } else + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l] = + (svga->vram[byte_addr] & (1 << bit_offset)) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l) >> 11] = changeframecount; break; default: - fatal("TRAP BLK/RPL PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); + fatal("BITBLT DWGCTRL_ATYPE_BLK unknown MACCESS %i\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); } } - x_l = (x_l + 1) & 0xffff; - mystique->pixel_count++; + + if (src_addr == mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; + mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; + src_addr = mystique->dwgreg.ar[3]; + } else + src_addr += x_dir; + + if (x != x_end) + x = (x + x_dir) & 0xffff; + else + break; } - if ((int32_t)mystique->dwgreg.ar[1] < 0) { - while ((int32_t)mystique->dwgreg.ar[1] < 0 && mystique->dwgreg.ar[0]) { - mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; - mystique->dwgreg.fxleft += (mystique->dwgreg.sgn.sdxl ? -1 : 1); - } - } else - mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; - - if ((int32_t)mystique->dwgreg.ar[4] < 0) { - while ((int32_t)mystique->dwgreg.ar[4] < 0 && mystique->dwgreg.ar[6]) { - mystique->dwgreg.ar[4] += mystique->dwgreg.ar[6]; - mystique->dwgreg.fxright += (mystique->dwgreg.sgn.sdxr ? -1 : 1); - } - } else - mystique->dwgreg.ar[4] += mystique->dwgreg.ar[5]; + if (mystique->dwgreg.sgn.sdy) + mystique->dwgreg.ydst_lin -= (mystique->dwgreg.pitch & PITCH_MASK); + else + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + } + break; - mystique->dwgreg.ydst++; - mystique->dwgreg.ydst &= 0x7fffff; - mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + default: + fatal("BITBLT BLK %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK); + break; + } + break; - mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7; - } - break; + case DWGCTRL_ATYPE_RPL: + if (mystique->maccess_running & MACCESS_TLUTLOAD) { + src_addr = mystique->dwgreg.ar[3]; + + y = mystique->dwgreg.ydst; + + while (mystique->dwgreg.length) { + uint16_t src = ((uint16_t *)svga->vram)[src_addr & mystique->vram_mask_w]; + + mystique->lut[y & 0xff].r = (src >> 11) << 3; + mystique->lut[y & 0xff].g = ((src >> 5) & 0x3f) << 2; + mystique->lut[y & 0xff].b = (src & 0x1f) << 3; + src_addr++; + y++; + mystique->dwgreg.length--; + } + break; + } + case DWGCTRL_ATYPE_RSTR: + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { + case DWGCTRL_BLTMOD_BMONOLEF: + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_PATTERN) + fatal("BITBLT RPL/RSTR BMONOLEF with pattern\n"); + + src_addr = mystique->dwgreg.ar[3]; - case DWGCTRL_ATYPE_RSTR: for (y = 0; y < mystique->dwgreg.length; y++) { uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; - int x_l = mystique->dwgreg.fxleft & 0xffff; - int x_r = mystique->dwgreg.fxright & 0xffff; - int yoff = (mystique->dwgreg.yoff + mystique->dwgreg.ydst) & 7; - -// pclog(" line %03i: %08x\n", y, mystique->dwgreg.ydst_lin); - while (x_l != x_r) { - if (x_l >= mystique->dwgreg.cxleft && x_l <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && - trans[x_l & 3]) { - int xoff = (mystique->dwgreg.xoff + x_l) & 7; - int pattern = mystique->dwgreg.pattern[yoff][xoff]; - uint32_t src = pattern ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; + int x = x_start; + + while (1) { + uint32_t byte_addr = (src_addr >> 3) & mystique->vram_mask; + int bit_offset = src_addr & 7; + + if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && + ((svga->vram[byte_addr] & (1 << bit_offset)) || !(mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC)) && + trans[x & 3]) { + uint32_t src = (svga->vram[byte_addr] & (1 << bit_offset)) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; uint32_t dst, old_dst; - - switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) - { + + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { case MACCESS_PWIDTH_8: - dst = svga->vram[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask]; + dst = svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask]; dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); -// pclog(" %06x %02x\n", mystique->dwgreg.ydst_lin + x, mystique->dwgreg.fcol & 0xff); - svga->vram[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask) >> 12] = changeframecount; + + svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount; break; case MACCESS_PWIDTH_16: - dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w]; - + dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w]; + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); -// pclog(" %06x %02x\n", mystique->dwgreg.ydst_lin + x, mystique->dwgreg.fcol & 0xff); - ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w) >> 11] = changeframecount; + + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount; break; - + case MACCESS_PWIDTH_24: - old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask]; + old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask]; - dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running); -// pclog(" %06x %02x\n", mystique->dwgreg.ydst_lin + x, mystique->dwgreg.fcol & 0xff); - *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000); - svga->changedvram[(((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask) >> 12] = changeframecount; - break; + dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running);// & DWGCTRL_BOP_MASK - case MACCESS_PWIDTH_32: - dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l]; - - dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); -// pclog(" %06x %02x\n", mystique->dwgreg.ydst_lin + x, mystique->dwgreg.fcol & 0xff); - ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l) >> 10] = changeframecount; + *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000); + svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount; break; default: - fatal("TRAP RSTR PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); + fatal("BITBLT RPL BMONOLEF PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); } } - x_l = (x_l + 1) & 0xffff; - mystique->pixel_count++; + + if (src_addr == mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; + mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; + src_addr = mystique->dwgreg.ar[3]; + } else + src_addr += x_dir; + + if (x != x_end) + x = (x + x_dir) & 0xffff; + else + break; } - if ((int32_t)mystique->dwgreg.ar[1] < 0) { - while ((int32_t)mystique->dwgreg.ar[1] < 0 && mystique->dwgreg.ar[0]) { - mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; - mystique->dwgreg.fxleft += (mystique->dwgreg.sgn.sdxl ? -1 : 1); - } - } else - mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; + if (mystique->dwgreg.sgn.sdy) + mystique->dwgreg.ydst_lin -= (mystique->dwgreg.pitch & PITCH_MASK); + else + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + } + break; - if ((int32_t)mystique->dwgreg.ar[4] < 0) { - while ((int32_t)mystique->dwgreg.ar[4] < 0 && mystique->dwgreg.ar[6]) { - mystique->dwgreg.ar[4] += mystique->dwgreg.ar[6]; - mystique->dwgreg.fxright += (mystique->dwgreg.sgn.sdxr ? -1 : 1); - } - } else - mystique->dwgreg.ar[4] += mystique->dwgreg.ar[5]; + case DWGCTRL_BLTMOD_BFCOL: + case DWGCTRL_BLTMOD_BU32RGB: + src_addr = mystique->dwgreg.ar[3]; - mystique->dwgreg.ydst++; - mystique->dwgreg.ydst &= 0x7fffff; - mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); - - mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7; - } - break; - - case DWGCTRL_ATYPE_I: - case DWGCTRL_ATYPE_ZI: - z_write = ((mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) == DWGCTRL_ATYPE_ZI); -/* pclog("fxleft=%i fxright=%i\n", mystique->dwgreg.fxleft, mystique->dwgreg.fxright); - pclog("fcol=%08x\n", mystique->dwgreg.fcol); - pclog("ytop=%i length=%i\n", mystique->dwgreg.ytop, mystique->dwgreg.length); - pclog("pitch=%08x\n", mystique->dwgreg.pitch); - pclog("ydst_lin=%08x\n", mystique->dwgreg.ydst_lin); - pclog("trap! maccess=%08x %08x %08x %08x\n", mystique->maccess_running, mystique->dwgreg.dr[4], mystique->dwgreg.dr[8], mystique->dwgreg.dr[12]);*/ - - for (y = 0; y < mystique->dwgreg.length; y++) { + for (y = 0; y < mystique->dwgreg.length; y++) { uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; - uint16_t *z_p = (uint16_t *)&svga->vram[(mystique->dwgreg.ydst_lin*2 + mystique->dwgreg.zorg) & mystique->vram_mask]; - int x_l = mystique->dwgreg.fxleft & 0xffff; - int x_r = mystique->dwgreg.fxright & 0xffff; - int old_x_l = x_l; - int dx; - - z_back = mystique->dwgreg.dr[0]; - r_back = mystique->dwgreg.dr[4]; - g_back = mystique->dwgreg.dr[8]; - b_back = mystique->dwgreg.dr[12]; + uint32_t old_src_addr = src_addr; + int x = x_start; -// pclog(" line %03i: %08x\n", y, mystique->dwgreg.ydst_lin); - while (x_l != x_r) { - if (x_l >= mystique->dwgreg.cxleft && x_l <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && - trans[x_l & 3]) { - uint16_t z = ((int32_t)mystique->dwgreg.dr[0] < 0) ? 0 : (mystique->dwgreg.dr[0] >> 15); - uint16_t old_z = z_p[x_l]; - - if (z_check(z, old_z, mystique->dwgreg.dwgctrl_running & DWGCTRL_ZMODE_MASK)) { - uint32_t dst = 0, old_dst; - int r = 0, g = 0, b = 0; + while (1) { + if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && + trans[x & 3]) { + uint32_t src, dst, old_dst; - if (!(mystique->dwgreg.dr[4] & (1 << 23))) - r = (mystique->dwgreg.dr[4] >> 15) & 0xff; - if (!(mystique->dwgreg.dr[8] & (1 << 23))) - g = (mystique->dwgreg.dr[8] >> 15) & 0xff; - if (!(mystique->dwgreg.dr[12] & (1 << 23))) - b = (mystique->dwgreg.dr[12] >> 15) & 0xff; + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_8: + src = svga->vram[src_addr & mystique->vram_mask]; + dst = svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask]; - if (z_write) - z_p[x_l] = z; + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); -// pclog(" %06x %02x\n", mystique->dwgreg.ydst_lin + x, mystique->dwgreg.fcol & 0xff); - switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) - { - case MACCESS_PWIDTH_8: - svga->vram[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask) >> 12] = changeframecount; - break; + svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount; + break; - case MACCESS_PWIDTH_16: - dst = dither(mystique, r, g, b, x_l & 1, mystique->dwgreg.selline & 1); -// pclog(" %08x %08x %08x %04x\n", mystique->dwgreg.dr[4], mystique->dwgreg.dr[8], mystique->dwgreg.dr[12], dst); - ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w) >> 11] = changeframecount; - break; + case MACCESS_PWIDTH_16: + src = ((uint16_t *)svga->vram)[src_addr & mystique->vram_mask_w]; + dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w]; - case MACCESS_PWIDTH_24: - old_dst = *(uint32_t *)(&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask]) & 0xff000000; - *(uint32_t *)(&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask]) = old_dst | dst; - svga->changedvram[(((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask) >> 12] = changeframecount; - break; + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); - case MACCESS_PWIDTH_32: - ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l] = b | (g << 8) | (r << 16); - svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l) >> 10] = changeframecount; - break; + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount; + break; - default: - fatal("TRAP BLK/RPL PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); - } + case MACCESS_PWIDTH_24: + src = *(uint32_t *)&svga->vram[(src_addr * 3) & mystique->vram_mask]; + old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask]; + + dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running); + + *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000); + svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_32: + src = ((uint32_t *)svga->vram)[src_addr & mystique->vram_mask_l]; + dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l]; + + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l) >> 10] = changeframecount; + break; + + default: + fatal("BITBLT RPL BFCOL PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); } } - mystique->dwgreg.dr[0] += mystique->dwgreg.dr[2]; - mystique->dwgreg.dr[4] += mystique->dwgreg.dr[6]; - mystique->dwgreg.dr[8] += mystique->dwgreg.dr[10]; - mystique->dwgreg.dr[12] += mystique->dwgreg.dr[14]; + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_PATTERN) + src_addr = ((src_addr + x_dir) & 7) | (src_addr & ~7); + else if (src_addr == mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; + mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; + src_addr = mystique->dwgreg.ar[3]; + } else + src_addr += x_dir; - x_l = (x_l + 1) & 0xffff; - mystique->pixel_count++; + if (x != x_end) + x = (x + x_dir) & 0xffff; + else + break; } - mystique->dwgreg.dr[0] = z_back + mystique->dwgreg.dr[3]; - mystique->dwgreg.dr[4] = r_back + mystique->dwgreg.dr[7]; - mystique->dwgreg.dr[8] = g_back + mystique->dwgreg.dr[11]; - mystique->dwgreg.dr[12] = b_back + mystique->dwgreg.dr[15]; - - while ((int32_t)mystique->dwgreg.ar[1] < 0 && mystique->dwgreg.ar[0]) { - mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; - mystique->dwgreg.fxleft += (mystique->dwgreg.sgn.sdxl ? -1 : 1); - } - mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; - - while ((int32_t)mystique->dwgreg.ar[4] < 0 && mystique->dwgreg.ar[6]) { - mystique->dwgreg.ar[4] += mystique->dwgreg.ar[6]; - mystique->dwgreg.fxright += (mystique->dwgreg.sgn.sdxr ? -1 : 1); - } - mystique->dwgreg.ar[4] += mystique->dwgreg.ar[5]; - - dx = (int16_t)((mystique->dwgreg.fxleft - old_x_l) & 0xffff); - mystique->dwgreg.dr[0] += dx*mystique->dwgreg.dr[2]; - mystique->dwgreg.dr[4] += dx*mystique->dwgreg.dr[6]; - mystique->dwgreg.dr[8] += dx*mystique->dwgreg.dr[10]; - mystique->dwgreg.dr[12] += dx*mystique->dwgreg.dr[14]; - - mystique->dwgreg.ydst++; - mystique->dwgreg.ydst &= 0x7fffff; - mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); - - mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7; - } - break; - - default: - fatal("Unknown atype %03x %08x TRAP\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); - } - - mystique->blitter_complete_refcount++; -} - -static int texture_read(mystique_t *mystique, int *tex_r, int *tex_g, int *tex_b, int *atransp) -{ - svga_t *svga = &mystique->svga; - const int tex_shift = 3 + ((mystique->dwgreg.texctl & TEXCTL_TPITCH_MASK) >> TEXCTL_TPITCH_SHIFT); - const unsigned int palsel = mystique->dwgreg.texctl & TEXCTL_PALSEL_MASK; - const uint16_t tckey = mystique->dwgreg.textrans & TEXTRANS_TCKEY_MASK; - const uint16_t tkmask = (mystique->dwgreg.textrans & TEXTRANS_TKMASK_MASK) >> TEXTRANS_TKMASK_SHIFT; - const unsigned int w_mask = (mystique->dwgreg.texwidth & TEXWIDTH_TWMASK_MASK) >> TEXWIDTH_TWMASK_SHIFT; - const unsigned int h_mask = (mystique->dwgreg.texheight & TEXHEIGHT_THMASK_MASK) >> TEXHEIGHT_THMASK_SHIFT; - uint16_t src = 0; - int s, t; - - if (mystique->dwgreg.texctl & TEXCTL_NPCEN) { - const int s_shift = 20 - (mystique->dwgreg.texwidth & TEXWIDTH_TW_MASK); - const int t_shift = 20 - (mystique->dwgreg.texheight & TEXHEIGHT_TH_MASK); - - s = (int32_t)mystique->dwgreg.tmr[6] >> s_shift; - t = (int32_t)mystique->dwgreg.tmr[7] >> t_shift; - } else { - const int s_shift = (20 + 16) - (mystique->dwgreg.texwidth & TEXWIDTH_TW_MASK); - const int t_shift = (20 + 16) - (mystique->dwgreg.texheight & TEXHEIGHT_TH_MASK); - int64_t q = mystique->dwgreg.tmr[8] ? ((0x100000000ll / (int64_t)(int32_t)mystique->dwgreg.tmr[8]) /*>> 16*/) : 0; - - s = (((int64_t)(int32_t)mystique->dwgreg.tmr[6] * q) /*<< 8*/) >> s_shift;/*((16+20)-12);*/ - t = (((int64_t)(int32_t)mystique->dwgreg.tmr[7] * q) /*<< 8*/) >> t_shift;/*((16+20)-9);*/ - } - - if (mystique->dwgreg.texctl & TEXCTL_CLAMPU) { - if (s < 0) - s = 0; - else if (s > w_mask) - s = w_mask; - } else - s &= w_mask; - - if (mystique->dwgreg.texctl & TEXCTL_CLAMPV) { - if (t < 0) - t = 0; - else if (t > h_mask) - t = h_mask; - } else - t &= h_mask; - - switch (mystique->dwgreg.texctl & TEXCTL_TEXFORMAT_MASK) - { - case TEXCTL_TEXFORMAT_TW4: - src = svga->vram[(mystique->dwgreg.texorg + (((t << tex_shift) + s) >> 1)) & mystique->vram_mask]; - if (s & 1) - src >>= 4; - else - src &= 0xf; - *tex_r = mystique->lut[src | palsel].r; - *tex_g = mystique->lut[src | palsel].g; - *tex_b = mystique->lut[src | palsel].b; - *atransp = 0; - break; - case TEXCTL_TEXFORMAT_TW8: - src = svga->vram[(mystique->dwgreg.texorg + (t << tex_shift) + s) & mystique->vram_mask]; - *tex_r = mystique->lut[src].r; - *tex_g = mystique->lut[src].g; - *tex_b = mystique->lut[src].b; - *atransp = 0; - break; - case TEXCTL_TEXFORMAT_TW15: - src = ((uint16_t *)svga->vram)[((mystique->dwgreg.texorg >> 1) + (t << tex_shift) + s) & mystique->vram_mask_w]; - *tex_r = ((src >> 10) & 0x1f) << 3; - *tex_g = ((src >> 5) & 0x1f) << 3; - *tex_b = (src & 0x1f) << 3; - if (((src >> 15) & mystique->dwgreg.ta_mask) == mystique->dwgreg.ta_key) - *atransp = 1; - else - *atransp = 0; - break; - case TEXCTL_TEXFORMAT_TW16: - src = ((uint16_t *)svga->vram)[((mystique->dwgreg.texorg >> 1) + (t << tex_shift) + s) & mystique->vram_mask_w]; - *tex_r = (src >> 11) << 3; - *tex_g = ((src >> 5) & 0x3f) << 2; - *tex_b = (src & 0x1f) << 3; - *atransp = 0; - break; - default: - fatal("Unknown texture format %i\n", mystique->dwgreg.texctl & TEXCTL_TEXFORMAT_MASK); - break; - } - - return ((src & tkmask) == tckey); -} - -static void blit_texture_trap(mystique_t *mystique) -{ - svga_t *svga = &mystique->svga; - int y; - int z_write; - const int trans_sel = (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANS_MASK) >> DWGCTRL_TRANS_SHIFT; - const int dest32 = ((mystique->maccess_running & MACCESS_PWIDTH_MASK) == MACCESS_PWIDTH_32); - - mystique->trap_count++; - - switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) - { - case DWGCTRL_ATYPE_I: - case DWGCTRL_ATYPE_ZI: - z_write = ((mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) == DWGCTRL_ATYPE_ZI); -// pclog("fxleft=%i fxright=%i texctl=%08x texorg=%08x ydst=%i len=%i\n", mystique->dwgreg.fxleft, mystique->dwgreg.fxright, mystique->dwgreg.texctl, mystique->dwgreg.texorg, mystique->dwgreg.ydst, mystique->dwgreg.length); -/* pclog("fcol=%08x\n", mystique->dwgreg.fcol); - pclog("ytop=%i length=%i\n", mystique->dwgreg.ytop, mystique->dwgreg.length); - pclog("pitch=%08x\n", mystique->dwgreg.pitch); - pclog("ydst=%i ydst_lin=%08x\n", mystique->dwgreg.ydst, mystique->dwgreg.ydst_lin); - pclog("dYl =%08x errl =%08x -|dXl|=%08x\n", mystique->dwgreg.ar[0], mystique->dwgreg.ar[1], mystique->dwgreg.ar[2]); - pclog("errr=%08x -|dXr|=%08x dYr =%08x\n", mystique->dwgreg.ar[4], mystique->dwgreg.ar[5], mystique->dwgreg.ar[6]); - pclog(" q/wc=%08x q/wc/dX=%08x q/wc/dY=%08x\n", - mystique->dwgreg.tmr[8], mystique->dwgreg.tmr[4], mystique->dwgreg.tmr[5]); - pclog(" s/wc=%08x s/wc/dX=%08x s/wc/dY=%08x\n", - mystique->dwgreg.tmr[6], mystique->dwgreg.tmr[0], mystique->dwgreg.tmr[1]); - pclog(" t/wc=%08x t/wc/dX=%08x t/wc/dY=%08x\n", - mystique->dwgreg.tmr[7], mystique->dwgreg.tmr[2], mystique->dwgreg.tmr[3]);*/ - - for (y = 0; y < mystique->dwgreg.length; y++) { - uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; - uint16_t *z_p = (uint16_t *)&svga->vram[(mystique->dwgreg.ydst_lin*2 + mystique->dwgreg.zorg) & mystique->vram_mask]; - int x_l = mystique->dwgreg.fxleft & 0xffff; - int x_r = mystique->dwgreg.fxright & 0xffff; - int old_x_l = x_l; - int dx; - - uint32_t z_back = mystique->dwgreg.dr[0]; - uint32_t r_back = mystique->dwgreg.dr[4]; - uint32_t g_back = mystique->dwgreg.dr[8]; - uint32_t b_back = mystique->dwgreg.dr[12]; - uint32_t s_back = mystique->dwgreg.tmr[6]; - uint32_t t_back = mystique->dwgreg.tmr[7]; - uint32_t q_back = mystique->dwgreg.tmr[8]; - -// pclog(" line %i: %i %i %08x %08x %08x %08x %i\n", __y, x_l, x_r, mystique->dwgreg.dr[0],mystique->dwgreg.dr[2],mystique->dwgreg.dr[3], mystique->dwgreg.ydst_lin*2 + mystique->dwgreg.zorg, z_write); -// pclog(" %08x %08x %08x\n", mystique->dwgreg.tmr[4],mystique->dwgreg.tmr[5], mystique->dwgreg.tmr[8]); -// pclog(" %08x %08x %08x\n", mystique->dwgreg.ar[4], mystique->dwgreg.ar[5], mystique->dwgreg.ar[6]); - - while (x_l != x_r) { - if (x_l >= mystique->dwgreg.cxleft && x_l <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && - trans[x_l & 3]) { - uint16_t z = ((int32_t)mystique->dwgreg.dr[0] < 0) ? 0 : (mystique->dwgreg.dr[0] >> 15); - uint16_t old_z = z_p[x_l]; - - if (z_check(z, old_z, mystique->dwgreg.dwgctrl_running & DWGCTRL_ZMODE_MASK)) { - int tex_r = 0, tex_g = 0, tex_b = 0; - int ctransp, atransp = 0; - int i_r = 0, i_g = 0, i_b = 0; - - if (!(mystique->dwgreg.dr[4] & (1 << 23))) - i_r = (mystique->dwgreg.dr[4] >> 15) & 0xff; - if (!(mystique->dwgreg.dr[8] & (1 << 23))) - i_g = (mystique->dwgreg.dr[8] >> 15) & 0xff; - if (!(mystique->dwgreg.dr[12] & (1 << 23))) - i_b = (mystique->dwgreg.dr[12] >> 15) & 0xff; - - ctransp = texture_read(mystique, &tex_r, &tex_g, &tex_b, &atransp); - - switch (mystique->dwgreg.texctl & (TEXCTL_TMODULATE | TEXCTL_STRANS | TEXCTL_ITRANS | TEXCTL_DECALCKEY)) - { - case 0: - if (ctransp) - goto skip_pixel; - if (atransp) { - tex_r = i_r; - tex_g = i_g; - tex_b = i_b; - } - break; - - case TEXCTL_DECALCKEY: - if (ctransp) { - tex_r = i_r; - tex_g = i_g; - tex_b = i_b; - } - break; - - case (TEXCTL_STRANS | TEXCTL_DECALCKEY): - if (ctransp) - goto skip_pixel; - break; - - case TEXCTL_TMODULATE: - if (ctransp) - goto skip_pixel; - if (mystique->dwgreg.texctl & TEXCTL_TMODULATE) { - tex_r = (tex_r * i_r) >> 8; - tex_g = (tex_g * i_g) >> 8; - tex_b = (tex_b * i_b) >> 8; - } - break; - - case (TEXCTL_TMODULATE | TEXCTL_STRANS): - if (ctransp || atransp) - goto skip_pixel; - if (mystique->dwgreg.texctl & TEXCTL_TMODULATE) { - tex_r = (tex_r * i_r) >> 8; - tex_g = (tex_g * i_g) >> 8; - tex_b = (tex_b * i_b) >> 8; - } - break; - - - default: - fatal("Bad TEXCTL %08x %08x\n", mystique->dwgreg.texctl, mystique->dwgreg.texctl & (TEXCTL_TMODULATE | TEXCTL_STRANS | TEXCTL_ITRANS | TEXCTL_DECALCKEY)); - } - - if (dest32) { - ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l] = tex_b | (tex_g << 8) | (tex_r << 16); - svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l) >> 10] = changeframecount; - } else { - ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w] = dither(mystique, tex_r, tex_g, tex_b, x_l & 1, mystique->dwgreg.selline & 1); - svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w) >> 11] = changeframecount; - } - if (z_write) - z_p[x_l] = z; - } - } -skip_pixel: - x_l = (x_l + 1) & 0xffff; - mystique->pixel_count++; - - mystique->dwgreg.dr[0] += mystique->dwgreg.dr[2]; - mystique->dwgreg.dr[4] += mystique->dwgreg.dr[6]; - mystique->dwgreg.dr[8] += mystique->dwgreg.dr[10]; - mystique->dwgreg.dr[12] += mystique->dwgreg.dr[14]; - mystique->dwgreg.tmr[6] += mystique->dwgreg.tmr[0]; - mystique->dwgreg.tmr[7] += mystique->dwgreg.tmr[2]; - mystique->dwgreg.tmr[8] += mystique->dwgreg.tmr[4]; + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_PATTERN) { + src_addr = old_src_addr; + if (mystique->dwgreg.sgn.sdy) + src_addr = ((src_addr - 32) & 0xe0) | (src_addr & ~0xe0); + else + src_addr = ((src_addr + 32) & 0xe0) | (src_addr & ~0xe0); } - mystique->dwgreg.dr[0] = z_back + mystique->dwgreg.dr[3]; - mystique->dwgreg.dr[4] = r_back + mystique->dwgreg.dr[7]; - mystique->dwgreg.dr[8] = g_back + mystique->dwgreg.dr[11]; - mystique->dwgreg.dr[12] = b_back + mystique->dwgreg.dr[15]; - mystique->dwgreg.tmr[6] = s_back + mystique->dwgreg.tmr[1]; - mystique->dwgreg.tmr[7] = t_back + mystique->dwgreg.tmr[3]; - mystique->dwgreg.tmr[8] = q_back + mystique->dwgreg.tmr[5]; - - while ((int32_t)mystique->dwgreg.ar[1] < 0 && mystique->dwgreg.ar[0]) { - mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; - mystique->dwgreg.fxleft += (mystique->dwgreg.sgn.sdxl ? -1 : 1); - } - mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; - - while ((int32_t)mystique->dwgreg.ar[4] < 0 && mystique->dwgreg.ar[6]) { - mystique->dwgreg.ar[4] += mystique->dwgreg.ar[6]; - mystique->dwgreg.fxright += (mystique->dwgreg.sgn.sdxr ? -1 : 1); - } - mystique->dwgreg.ar[4] += mystique->dwgreg.ar[5]; - - dx = (int16_t)((mystique->dwgreg.fxleft - old_x_l) & 0xffff); - mystique->dwgreg.dr[0] += dx*mystique->dwgreg.dr[2]; - mystique->dwgreg.dr[4] += dx*mystique->dwgreg.dr[6]; - mystique->dwgreg.dr[8] += dx*mystique->dwgreg.dr[10]; - mystique->dwgreg.dr[12] += dx*mystique->dwgreg.dr[14]; - mystique->dwgreg.tmr[6] += dx*mystique->dwgreg.tmr[0]; - mystique->dwgreg.tmr[7] += dx*mystique->dwgreg.tmr[2]; - mystique->dwgreg.tmr[8] += dx*mystique->dwgreg.tmr[4]; - - mystique->dwgreg.ydst++; - mystique->dwgreg.ydst &= 0x7fffff; - mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); - - mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7; - } - break; - - default: - fatal("Unknown atype %03x %08x TEXTURE_TRAP\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); - } - - mystique->blitter_complete_refcount++; -} - -static void blit_bitblt(mystique_t *mystique) -{ - svga_t *svga = &mystique->svga; - uint32_t src_addr; - int y; - int x_dir = mystique->dwgreg.sgn.scanleft ? -1 : 1; - int x_start = mystique->dwgreg.sgn.scanleft ? mystique->dwgreg.fxright : mystique->dwgreg.fxleft; - int x_end = mystique->dwgreg.sgn.scanleft ? mystique->dwgreg.fxleft : mystique->dwgreg.fxright; - const int trans_sel = (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANS_MASK) >> DWGCTRL_TRANS_SHIFT; - - switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) - { - case DWGCTRL_ATYPE_BLK: -// if (mystique->maccess_running & MACCESS_TLUTLOAD) -// fatal("Bitblt TLUTLOAD BLK\n"); -// if (mystique->dwgreg.dwgctrl_running & DWGCTRL_PATTERN) -// fatal("BITBLT BLK with pattern\n"); - switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) - { - case DWGCTRL_BLTMOD_BMONOLEF: -// pclog("ar0=%08x ar3=%08x ar5=%08x dwgctrl=%08x\n", mystique->dwgreg.ar[0], mystique->dwgreg.ar[3], mystique->dwgreg.ar[5], mystique->dwgreg.dwgctrl_running); -// pclog("fxleft=%i fxright=%i ydst=%i fcol=%08x bcol=%08x\n", mystique->dwgreg.fxleft, mystique->dwgreg.fxright, mystique->dwgreg.ydst, mystique->dwgreg.fcol, mystique->dwgreg.bcol); - - src_addr = mystique->dwgreg.ar[3]; -// mystique->dwgreg.bit_offset = 0; - - for (y = 0; y < mystique->dwgreg.length; y++) { - int x = x_start; - -// pclog(" line %03i: %08x %08x %02x\n", y, mystique->dwgreg.ydst_lin, src_addr, svga->vram[0x2eba3]); - while (1) { - if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { - uint32_t byte_addr = (src_addr >> 3) & mystique->vram_mask; - int bit_offset = src_addr & 7; - uint32_t old_dst; - - switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) - { - case MACCESS_PWIDTH_8: -// pclog(" pix %i %02x %i %i %06x\n", x, svga->vram[byte_addr], svga->vram[byte_addr] & (1 << bit_offset), mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC, byte_addr); - if (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC) { - if (svga->vram[byte_addr] & (1 << bit_offset)) - svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = mystique->dwgreg.fcol; - } else - svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = - (svga->vram[byte_addr] & (1 << bit_offset)) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; - svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount; - break; - - case MACCESS_PWIDTH_16: -// pclog(" pix %i %02x %i %i %06x\n", x, svga->vram[byte_addr], svga->vram[byte_addr] & (1 << bit_offset), mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC, byte_addr); - if (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC) { - if (svga->vram[byte_addr] & (1 << bit_offset)) - ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = mystique->dwgreg.fcol; - } else - ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = - (svga->vram[byte_addr] & (1 << bit_offset)) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; - svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount; - break; - - case MACCESS_PWIDTH_24: - old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask]; -// pclog(" pix %i %02x %i %i %06x\n", x, svga->vram[byte_addr], svga->vram[byte_addr] & (1 << bit_offset), mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC, byte_addr); - if (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC) { - if (svga->vram[byte_addr] & (1 << bit_offset)) - *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = - (old_dst & 0xff000000) | (mystique->dwgreg.fcol & 0xffffff); - } else - *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = - (old_dst & 0xff000000) | (((svga->vram[byte_addr] & (1 << bit_offset)) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol) & 0xffffff); - svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount; - break; - - case MACCESS_PWIDTH_32: -// pclog(" pix %i %02x %i %i %06x\n", x, svga->vram[byte_addr], svga->vram[byte_addr] & (1 << bit_offset), mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC, byte_addr); - if (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC) - { - if (svga->vram[byte_addr] & (1 << bit_offset)) - ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & 0xfffff] = mystique->dwgreg.fcol; - } - else - ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & 0xfffff] = - (svga->vram[byte_addr] & (1 << bit_offset)) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; - svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l) >> 10] = changeframecount; - break; - - default: - fatal("BITBLT DWGCTRL_ATYPE_BLK unknown MACCESS %i\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); - } - } - - if (src_addr == mystique->dwgreg.ar[0]) - { - mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; - mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; - src_addr = mystique->dwgreg.ar[3]; - } - else - src_addr += x_dir; - - if (x != x_end) - x = (x + x_dir) & 0xffff; - else - break; - } - - if (mystique->dwgreg.sgn.sdy) - mystique->dwgreg.ydst_lin -= (mystique->dwgreg.pitch & PITCH_MASK); - else - mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); - } - break; - - default: - fatal("BITBLT BLK %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK); - break; - } - break; - - - case DWGCTRL_ATYPE_RPL: -// pclog(" bitblt RPL\n"); - if (mystique->maccess_running & MACCESS_TLUTLOAD) - { -// pclog("TLUTLOAD!\n"); - src_addr = mystique->dwgreg.ar[3]; - - y = mystique->dwgreg.ydst; - - while (mystique->dwgreg.length) - { - uint16_t src = ((uint16_t *)svga->vram)[src_addr & mystique->vram_mask_w]; -// pclog(" LUT[%02x]=VRAM[%05X]=%04x\n", y & 0xff, src_addr, src); - - mystique->lut[y & 0xff].r = (src >> 11) << 3; - mystique->lut[y & 0xff].g = ((src >> 5) & 0x3f) << 2; - mystique->lut[y & 0xff].b = (src & 0x1f) << 3; - src_addr++; - y++; - mystique->dwgreg.length--; - } - break; - } - case DWGCTRL_ATYPE_RSTR: -// pclog(" bitblt RPL or RSTR\n"); -// if (mystique->maccess_running & MACCESS_TLUTLOAD) -// fatal("Bitblt TLUTLOAD RSTR\n"); - switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) - { - case DWGCTRL_BLTMOD_BMONOLEF: -// pclog("ar0=%08x ar3=%08x ar5=%08x\n", mystique->dwgreg.ar[0], mystique->dwgreg.ar[3], mystique->dwgreg.ar[5]); -// pclog("fxleft=%i fxright=%i\n", mystique->dwgreg.fxleft, mystique->dwgreg.fxright); - - if (mystique->dwgreg.dwgctrl_running & DWGCTRL_PATTERN) - fatal("BITBLT RPL/RSTR BMONOLEF with pattern\n"); - - src_addr = mystique->dwgreg.ar[3]; - - for (y = 0; y < mystique->dwgreg.length; y++) - { - uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; - int x = x_start; - -// pclog(" line %03i: %08x %08x\n", y, mystique->dwgreg.ydst_lin, src_addr); - while (1) - { - uint32_t byte_addr = (src_addr >> 3) & mystique->vram_mask; - int bit_offset = src_addr & 7; - - if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && - ((svga->vram[byte_addr] & (1 << bit_offset)) || !(mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC)) && - trans[x & 3]) - { - uint32_t src = (svga->vram[byte_addr] & (1 << bit_offset)) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; - uint32_t dst, old_dst; - - switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) - { - case MACCESS_PWIDTH_8: - dst = svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask]; - -// pclog(" %02x %02x ", src, dst); - dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running);// & DWGCTRL_BOP_MASK -// pclog("%08x %08x %i dst=%02x\n", src_addr, mystique->dwgreg.ydst_lin + x, mystique->dwgreg.sgn.scanleft, dst); - - svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount; - break; - - case MACCESS_PWIDTH_16: - dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w]; - -// pclog(" %02x %02x ", src, dst); - dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running);// & DWGCTRL_BOP_MASK -// pclog("%08x %08x %i dst=%02x\n", src_addr, mystique->dwgreg.ydst_lin + x, mystique->dwgreg.sgn.scanleft, dst); - - ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount; - break; - - case MACCESS_PWIDTH_24: - old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask]; - -// pclog(" %02x %02x ", src, old_dst); - dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running);// & DWGCTRL_BOP_MASK -// pclog("%08x %08x %i dst=%02x\n", src_addr, mystique->dwgreg.ydst_lin + x, mystique->dwgreg.sgn.scanleft, dst); - - *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000); - svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount; - break; - - default: - fatal("BITBLT RPL BMONOLEF PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); - } - } - - if (src_addr == mystique->dwgreg.ar[0]) - { - mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; - mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; - src_addr = mystique->dwgreg.ar[3]; - } - else - src_addr += x_dir; - - if (x != x_end) - x = (x + x_dir) & 0xffff; - else - break; - } - - if (mystique->dwgreg.sgn.sdy) - mystique->dwgreg.ydst_lin -= (mystique->dwgreg.pitch & PITCH_MASK); - else - mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); - } - break; - - - case DWGCTRL_BLTMOD_BFCOL: - case DWGCTRL_BLTMOD_BU32RGB: -// pclog("ar0=%08x ar3=%08x ar5=%08x\n", mystique->dwgreg.ar[0], mystique->dwgreg.ar[3], mystique->dwgreg.ar[5]); -// pclog("fxleft=%i fxright=%i\n", mystique->dwgreg.fxleft, mystique->dwgreg.fxright); - - src_addr = mystique->dwgreg.ar[3]; - - for (y = 0; y < mystique->dwgreg.length; y++) - { - uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; - uint32_t old_src_addr = src_addr; - int x = x_start; - -// pclog(" line %03i: %08x %08x\n", y, mystique->dwgreg.ydst_lin, src_addr); - while (1) - { - if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && - trans[x & 3]) - { - uint32_t src, dst, old_dst; - - switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) - { - case MACCESS_PWIDTH_8: - src = svga->vram[src_addr & mystique->vram_mask]; - dst = svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask]; - -// pclog(" %02x %02x ", src, dst); - dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running);// & DWGCTRL_BOP_MASK -// pclog("%08x %08x %i dst=%02x\n", src_addr, mystique->dwgreg.ydst_lin + x, mystique->dwgreg.sgn.scanleft, dst); - - svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount; - break; - - case MACCESS_PWIDTH_16: - src = ((uint16_t *)svga->vram)[src_addr & mystique->vram_mask_w]; - dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w]; - -// pclog(" %02x %02x ", src, dst); - dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running);// & DWGCTRL_BOP_MASK -// pclog("%08x %08x %i dst=%02x\n", src_addr, mystique->dwgreg.ydst_lin + x, mystique->dwgreg.sgn.scanleft, dst); - - ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount; - break; - - case MACCESS_PWIDTH_24: - src = *(uint32_t *)&svga->vram[(src_addr * 3) & mystique->vram_mask]; - old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask]; - -// pclog(" %02x %02x ", src, old_dst); - dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running);// & DWGCTRL_BOP_MASK -// pclog("%08x %08x %i dst=%02x\n", src_addr, mystique->dwgreg.ydst_lin + x, mystique->dwgreg.sgn.scanleft, dst); - - *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000); - svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount; - break; - - case MACCESS_PWIDTH_32: - src = ((uint32_t *)svga->vram)[src_addr & mystique->vram_mask_l]; - dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l]; - -// pclog(" %02x %02x ", src, dst); - dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running);// & DWGCTRL_BOP_MASK -// pclog("%08x %08x %i dst=%02x\n", src_addr, mystique->dwgreg.ydst_lin + x, mystique->dwgreg.sgn.scanleft, dst); - - ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l) >> 10] = changeframecount; - break; - - default: - fatal("BITBLT RPL BFCOL PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); - } - } - - if (mystique->dwgreg.dwgctrl_running & DWGCTRL_PATTERN) - src_addr = ((src_addr + x_dir) & 7) | (src_addr & ~7); - else if (src_addr == mystique->dwgreg.ar[0]) - { - mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; - mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; - src_addr = mystique->dwgreg.ar[3]; - } - else - src_addr += x_dir; - - if (x != x_end) - x = (x + x_dir) & 0xffff; - else - break; - } - - if (mystique->dwgreg.dwgctrl_running & DWGCTRL_PATTERN) - { - src_addr = old_src_addr; - if (mystique->dwgreg.sgn.sdy) - src_addr = ((src_addr - 32) & 0xe0) | (src_addr & ~0xe0); - else - src_addr = ((src_addr + 32) & 0xe0) | (src_addr & ~0xe0); - } - - if (mystique->dwgreg.sgn.sdy) - mystique->dwgreg.ydst_lin -= (mystique->dwgreg.pitch & PITCH_MASK); - else - mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); - } - break; - - default: - fatal("BITBLT DWGCTRL_ATYPE_RPL unknown BLTMOD %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running); - } - break; - - default: - fatal("Unknown BITBLT atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); - } - mystique->blitter_complete_refcount++; -} - -static void blit_iload(mystique_t *mystique) -{ -// if (mystique->maccess_running & MACCESS_TLUTLOAD) -// fatal("ILOAD TLUTLOAD\n"); - switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) - { - case DWGCTRL_ATYPE_RPL: - case DWGCTRL_ATYPE_RSTR: - case DWGCTRL_ATYPE_BLK: - switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) - { - case DWGCTRL_BLTMOD_BFCOL: - case DWGCTRL_BLTMOD_BMONOWF: - case DWGCTRL_BLTMOD_BU24RGB: -// pclog("fxleft=%i fxright=%i\n", mystique->dwgreg.fxleft, mystique->dwgreg.fxright); -// pclog("ytop=%i length=%i\n", mystique->dwgreg.ytop, mystique->dwgreg.length); - mystique->dwgreg.length_cur = mystique->dwgreg.length; - mystique->dwgreg.xdst = mystique->dwgreg.fxleft; - mystique->dwgreg.iload_rem_data = 0; - mystique->dwgreg.iload_rem_count = 0; - mystique->busy = 1; - mystique->dwgreg.words = 0; - break; - - default: - fatal("ILOAD DWGCTRL_ATYPE_RPL %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running); - break; - } - break; - - default: - fatal("Unknown ILOAD atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); - } -} - -static void blit_idump(mystique_t *mystique) -{ - switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) - { - case DWGCTRL_ATYPE_RPL: -// pclog("ar0=%08x ar3=%08x ar5=%08x\n", mystique->dwgreg.ar[0], mystique->dwgreg.ar[3], mystique->dwgreg.ar[5]); -// pclog("fxleft=%i fxright=%i\n", mystique->dwgreg.fxleft, mystique->dwgreg.fxright); - mystique->dwgreg.length_cur = mystique->dwgreg.length; - mystique->dwgreg.xdst = mystique->dwgreg.fxleft; - mystique->dwgreg.src_addr = mystique->dwgreg.ar[3]; - mystique->dwgreg.words = 0; - mystique->dwgreg.iload_rem_count = 0; - mystique->dwgreg.iload_rem_data = 0; - mystique->dwgreg.idump_end_of_line = 0; - mystique->busy = 1; - break; - - default: - fatal("Unknown IDUMP atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); - } -} - -static void blit_iload_scale(mystique_t *mystique) -{ - switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) - { - case DWGCTRL_ATYPE_RPL: - switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) - { - case DWGCTRL_BLTMOD_BUYUV: -/* pclog("fxleft=%i fxright=%i\n", mystique->dwgreg.fxleft, mystique->dwgreg.fxright); - pclog("ytop=%i length=%i\n", mystique->dwgreg.ytop, mystique->dwgreg.length); - pclog("ar0=%08x\n", mystique->dwgreg.ar[0]); - pclog("ar2=%08x\n", mystique->dwgreg.ar[2]); - pclog("ar3=%08x\n", mystique->dwgreg.ar[3]); - pclog("ar5=%08x\n", mystique->dwgreg.ar[5]); - pclog("ar6=%08x\n", mystique->dwgreg.ar[6]);*/ - mystique->dwgreg.length_cur = mystique->dwgreg.length; - mystique->dwgreg.xdst = mystique->dwgreg.fxleft; - mystique->dwgreg.iload_rem_data = 0; - mystique->dwgreg.iload_rem_count = 0; - mystique->busy = 1; - mystique->dwgreg.words = 0; - break; - - default: - fatal("ILOAD_SCALE DWGCTRL_ATYPE_RPL %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running); - break; - } - break; + if (mystique->dwgreg.sgn.sdy) + mystique->dwgreg.ydst_lin -= (mystique->dwgreg.pitch & PITCH_MASK); + else + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + } + break; default: - fatal("Unknown ILOAD_SCALE atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); - } -} - -static void blit_iload_high(mystique_t *mystique) -{ - switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) - { - case DWGCTRL_ATYPE_RPL: - switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) - { - case DWGCTRL_BLTMOD_BUYUV: -/* pclog("fxleft=%i fxright=%i\n", mystique->dwgreg.fxleft, mystique->dwgreg.fxright); - pclog("ytop=%i length=%i\n", mystique->dwgreg.ytop, mystique->dwgreg.length); - pclog("ar0=%08x\n", mystique->dwgreg.ar[0]); - pclog("ar2=%08x\n", mystique->dwgreg.ar[2]); - pclog("ar3=%08x\n", mystique->dwgreg.ar[3]); - pclog("ar5=%08x\n", mystique->dwgreg.ar[5]); - pclog("ar6=%08x\n", mystique->dwgreg.ar[6]);*/ - mystique->dwgreg.length_cur = mystique->dwgreg.length; - mystique->dwgreg.xdst = mystique->dwgreg.fxleft; - mystique->dwgreg.iload_rem_data = 0; - mystique->dwgreg.iload_rem_count = 0; - mystique->busy = 1; - mystique->dwgreg.words = 0; - break; - - default: - fatal("ILOAD_HIGH DWGCTRL_ATYPE_RPL %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running); - break; - } - break; - - default: - fatal("Unknown ILOAD_HIGH atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); - } -} -static void blit_iload_highv(mystique_t *mystique) -{ - switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) - { - case DWGCTRL_ATYPE_RPL: - switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) - { - case DWGCTRL_BLTMOD_BUYUV: -/* pclog("fxleft=%i fxright=%i\n", mystique->dwgreg.fxleft, mystique->dwgreg.fxright); - pclog("ytop=%i length=%i\n", mystique->dwgreg.ytop, mystique->dwgreg.length); - pclog("ar0=%08x\n", mystique->dwgreg.ar[0]); - pclog("ar2=%08x\n", mystique->dwgreg.ar[2]); - pclog("ar3=%08x\n", mystique->dwgreg.ar[3]); - pclog("ar5=%08x\n", mystique->dwgreg.ar[5]); - pclog("ar6=%08x\n", mystique->dwgreg.ar[6]);*/ - mystique->dwgreg.length_cur = mystique->dwgreg.length; - mystique->dwgreg.xdst = mystique->dwgreg.fxleft; - mystique->dwgreg.iload_rem_data = 0; - mystique->dwgreg.iload_rem_count = 0; - mystique->busy = 1; - mystique->dwgreg.words = 0; - mystique->dwgreg.highv_line = 0; - mystique->dwgreg.lastpix_r = 0; - mystique->dwgreg.lastpix_g = 0; - mystique->dwgreg.lastpix_b = 0; - break; - - default: - fatal("ILOAD_HIGHV DWGCTRL_ATYPE_RPL %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running); - break; - } - break; - - default: - fatal("Unknown ILOAD_HIGHV atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); - } -} - -static void mystique_start_blit(mystique_t *mystique) -{ - uint64_t start_time = plat_timer_read(); - uint64_t end_time; - - mystique->dwgreg.dwgctrl_running = mystique->dwgreg.dwgctrl; - mystique->maccess_running = mystique->maccess; -// pclog("start_blit %08x length=%i fxleft=%i fxright=%i %02x %i %i %i ylin=%08x ytop=%08x ybot=%08x\n", mystique->dwgreg.dwgctrl_running, mystique->dwgreg.length, mystique->dwgreg.fxleft, mystique->dwgreg.fxright, mystique->svga.vram[0x5c056], mystique->blitter_submit_refcount, mystique->blitter_submit_dma_refcount, mystique->blitter_complete_refcount, mystique->dwgreg.ydst_lin, mystique->dwgreg.ytop, mystique->dwgreg.ybot); - if (mystique->busy) { - fatal("Mystique still busy!\n"); + fatal("BITBLT DWGCTRL_ATYPE_RPL unknown BLTMOD %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running); } - if (mystique->dwgreg.dwgctrl_running & DWGCTRL_SOLID) - { - int x, y; - - for (y = 0; y < 8; y++) - { - for (x = 0; x < 8; x++) - mystique->dwgreg.pattern[y][x] = 1; - } - mystique->dwgreg.src[0] = 0xffffffff; - mystique->dwgreg.src[1] = 0xffffffff; - mystique->dwgreg.src[2] = 0xffffffff; - mystique->dwgreg.src[3] = 0xffffffff; - } - if (mystique->dwgreg.dwgctrl_running & DWGCTRL_ARZERO) - { - mystique->dwgreg.ar[0] = 0; - mystique->dwgreg.ar[1] = 0; - mystique->dwgreg.ar[2] = 0; - mystique->dwgreg.ar[4] = 0; - mystique->dwgreg.ar[5] = 0; - mystique->dwgreg.ar[6] = 0; - } - if (mystique->dwgreg.dwgctrl_running & DWGCTRL_SGNZERO) - { - mystique->dwgreg.sgn.sdydxl = 0; - mystique->dwgreg.sgn.scanleft = 0; - mystique->dwgreg.sgn.sdxl = 0; - mystique->dwgreg.sgn.sdy = 0; - mystique->dwgreg.sgn.sdxr = 0; - } - if (mystique->dwgreg.dwgctrl_running & DWGCTRL_SHTZERO) - { - mystique->dwgreg.funcnt = 0; - mystique->dwgreg.stylelen = 0; - mystique->dwgreg.xoff = 0; - mystique->dwgreg.yoff = 0; - } + break; - switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) - { - case DWGCTRL_OPCODE_LINE_OPEN: - blit_line(mystique, 0); - break; + default: + fatal("Unknown BITBLT atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + } - case DWGCTRL_OPCODE_AUTOLINE_OPEN: - blit_autoline(mystique, 0); - break; - - case DWGCTRL_OPCODE_AUTOLINE_CLOSE: - blit_autoline(mystique, 1); - break; - - case DWGCTRL_OPCODE_TRAP: - blit_trap(mystique); - break; - - case DWGCTRL_OPCODE_TEXTURE_TRAP: - blit_texture_trap(mystique); - break; - - case DWGCTRL_OPCODE_ILOAD_HIGH: - blit_iload_high(mystique); - break; - - case DWGCTRL_OPCODE_BITBLT: - blit_bitblt(mystique); - break; - - case DWGCTRL_OPCODE_ILOAD: - blit_iload(mystique); - break; - - case DWGCTRL_OPCODE_IDUMP: - blit_idump(mystique); - break; - - case DWGCTRL_OPCODE_ILOAD_SCALE: - blit_iload_scale(mystique); - break; - - case DWGCTRL_OPCODE_ILOAD_HIGHV: - blit_iload_highv(mystique); - break; - - default: - fatal("mystique_start_blit: unknown blit %08x\n", mystique->dwgreg.dwgctrl_running); - } -// pclog("blit done\n"); - - end_time = plat_timer_read(); - mystique->blitter_time += end_time - start_time; + mystique->blitter_complete_refcount++; } -static void mystique_hwcursor_draw(svga_t *svga, int displine) +static void +blit_iload(mystique_t *mystique) { - int x; - uint64_t dat[2]; - int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { + case DWGCTRL_ATYPE_RPL: + case DWGCTRL_ATYPE_RSTR: + case DWGCTRL_ATYPE_BLK: + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { + case DWGCTRL_BLTMOD_BFCOL: + case DWGCTRL_BLTMOD_BMONOWF: + case DWGCTRL_BLTMOD_BU24RGB: + mystique->dwgreg.length_cur = mystique->dwgreg.length; + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.iload_rem_data = 0; + mystique->dwgreg.iload_rem_count = 0; + mystique->busy = 1; + mystique->dwgreg.words = 0; + break; - dat[0] = *(uint64_t *)(&svga->vram[svga->hwcursor_latch.addr]); - dat[1] = *(uint64_t *)(&svga->vram[svga->hwcursor_latch.addr + 8]); - svga->hwcursor_latch.addr += 16; - for (x = 0; x < 64; x ++) - { - if (!(dat[1] & (1ull << 63))) - buffer32->line[displine][offset + svga->x_add] = (dat[0] & (1ull << 63)) ? 0xffffff : 0; - else if (dat[0] & (1ull << 63)) - buffer32->line[displine][offset + svga->x_add] ^= 0xffffff; + default: + fatal("ILOAD DWGCTRL_ATYPE_RPL %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running); + break; + } + break; - offset++; - dat[0] <<= 1; - dat[1] <<= 1; - } + default: + fatal("Unknown ILOAD atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + } } -static uint8_t mystique_pci_read(int func, int addr, void *p) +static void +blit_idump(mystique_t *mystique) { - mystique_t *mystique = (mystique_t *)p; + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { + case DWGCTRL_ATYPE_RPL: + mystique->dwgreg.length_cur = mystique->dwgreg.length; + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.src_addr = mystique->dwgreg.ar[3]; + mystique->dwgreg.words = 0; + mystique->dwgreg.iload_rem_count = 0; + mystique->dwgreg.iload_rem_data = 0; + mystique->dwgreg.idump_end_of_line = 0; + mystique->busy = 1; + break; -// pclog("mystique PCI read %08X\n", addr); - switch (addr) - { - case 0x00: return 0x2b; /*Matrox*/ - case 0x01: return 0x10; - - case 0x02: return 0x1a; /*MGA-1064SG*/ - case 0x03: return 0x05; - - case PCI_REG_COMMAND: - return mystique->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ - - case 0x07: return 0 << 1; /*Fast DEVSEL timing*/ - - case 0x08: return 0; /*Revision ID*/ - case 0x09: return 0; /*Programming interface*/ - - case 0x0a: return 0x00; /*Supports VGA interface*/ - case 0x0b: return 0x03; - - case 0x10: return 0x00; /*Control aperture*/ - case 0x11: return (mystique->ctrl_base >> 8) & 0xc0; - case 0x12: return mystique->ctrl_base >> 16; - case 0x13: return mystique->ctrl_base >> 24; - - case 0x14: return 0x00; /*Linear frame buffer*/ - case 0x16: return (mystique->lfb_base >> 16) & 0x80; - case 0x17: return mystique->lfb_base >> 24; - - case 0x18: return 0x00; /*Pseudo-DMA (ILOAD)*/ - case 0x1a: return (mystique->iload_base >> 16) & 0x80; - case 0x1b: return mystique->iload_base >> 24; - - case 0x30: return mystique->pci_regs[0x30] & 0x01; /*BIOS ROM address*/ - case 0x31: return 0x00; - case 0x32: return mystique->pci_regs[0x32]; - case 0x33: return mystique->pci_regs[0x33]; - - case 0x3c: return mystique->int_line; - case 0x3d: return PCI_INTA; - - case 0x40: return mystique->pci_regs[0x40]; - case 0x41: return mystique->pci_regs[0x41]; - case 0x42: return mystique->pci_regs[0x42]; - case 0x43: return mystique->pci_regs[0x43]; - - case 0x44: return mystique->pci_regs[0x44]; - case 0x45: return mystique->pci_regs[0x45]; - - case 0x48: case 0x49: case 0x4a: case 0x4b: - addr = (mystique->pci_regs[0x44] & 0xfc) | - ((mystique->pci_regs[0x45] & 0x3f) << 8) | - (addr & 3); - return mystique_ctrl_read_b(addr, mystique); - } - return 0; + default: + fatal("Unknown IDUMP atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + } } -static void mystique_pci_write(int func, int addr, uint8_t val, void *p) + +static void +blit_iload_scale(mystique_t *mystique) { - mystique_t *mystique = (mystique_t *)p; + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { + case DWGCTRL_ATYPE_RPL: + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { + case DWGCTRL_BLTMOD_BUYUV: + mystique->dwgreg.length_cur = mystique->dwgreg.length; + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.iload_rem_data = 0; + mystique->dwgreg.iload_rem_count = 0; + mystique->busy = 1; + mystique->dwgreg.words = 0; + break; -// pclog("mystique_pci_write: func=%i addr=%02x val=%02x\n", func, addr, val); - switch (addr) - { - case PCI_REG_COMMAND: - mystique->pci_regs[PCI_REG_COMMAND] = val & 0x23; - mystique_recalc_mapping(mystique); - break; + default: + fatal("ILOAD_SCALE DWGCTRL_ATYPE_RPL %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running); + break; + } + break; - case 0x11: - mystique->ctrl_base = (mystique->ctrl_base & 0xffff0000) | ((val & 0xc0) << 8); - mystique_recalc_mapping(mystique); - break; - case 0x12: - mystique->ctrl_base = (mystique->ctrl_base & 0xff00c000) | (val << 16); - mystique_recalc_mapping(mystique); - break; - case 0x13: - mystique->ctrl_base = (mystique->ctrl_base & 0x00ffc000) | (val << 24); - mystique_recalc_mapping(mystique); - break; - - case 0x16: - mystique->lfb_base = (mystique->lfb_base & 0xff000000) | ((val & 0x80) << 16); - mystique_recalc_mapping(mystique); - break; - case 0x17: - mystique->lfb_base = (mystique->lfb_base & 0x00800000) | (val << 24); - mystique_recalc_mapping(mystique); - break; - - case 0x1a: - mystique->iload_base = (mystique->iload_base & 0xff000000) | ((val & 0x80) << 16); - mystique_recalc_mapping(mystique); - break; - case 0x1b: - mystique->iload_base = (mystique->iload_base & 0x00800000) | (val << 24); - mystique_recalc_mapping(mystique); - break; - - case 0x30: case 0x32: case 0x33: - mystique->pci_regs[addr] = val; - if (mystique->pci_regs[0x30] & 0x01) - { - uint32_t addr = (mystique->pci_regs[0x32] << 16) | (mystique->pci_regs[0x33] << 24); - mem_mapping_set_addr(&mystique->bios_rom.mapping, addr, 0x8000); - } - else - mem_mapping_disable(&mystique->bios_rom.mapping); - return; - - case 0x3c: - mystique->int_line = val; - return; - - case 0x40: case 0x41: case 0x42: case 0x43: - mystique->pci_regs[addr] = val; - break; - - case 0x4c: case 0x4d: case 0x4e: case 0x4f: - mystique->pci_regs[addr-0x20] = val; - break; - - case 0x44: case 0x45: - mystique->pci_regs[addr] = val; - break; - - case 0x48: case 0x49: case 0x4a: case 0x4b: - addr = (mystique->pci_regs[0x44] & 0xfc) | - ((mystique->pci_regs[0x45] & 0x3f) << 8) | - (addr & 3); - mystique_ctrl_write_b(addr, val, mystique); - break; - } + default: + fatal("Unknown ILOAD_SCALE atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + } } + +static void +blit_iload_high(mystique_t *mystique) +{ + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { + case DWGCTRL_ATYPE_RPL: + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { + case DWGCTRL_BLTMOD_BUYUV: + mystique->dwgreg.length_cur = mystique->dwgreg.length; + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.iload_rem_data = 0; + mystique->dwgreg.iload_rem_count = 0; + mystique->busy = 1; + mystique->dwgreg.words = 0; + break; + + default: + fatal("ILOAD_HIGH DWGCTRL_ATYPE_RPL %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running); + break; + } + break; + + default: + fatal("Unknown ILOAD_HIGH atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + } +} + + +static +void blit_iload_highv(mystique_t *mystique) +{ + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { + case DWGCTRL_ATYPE_RPL: + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { + case DWGCTRL_BLTMOD_BUYUV: + mystique->dwgreg.length_cur = mystique->dwgreg.length; + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.iload_rem_data = 0; + mystique->dwgreg.iload_rem_count = 0; + mystique->busy = 1; + mystique->dwgreg.words = 0; + mystique->dwgreg.highv_line = 0; + mystique->dwgreg.lastpix_r = 0; + mystique->dwgreg.lastpix_g = 0; + mystique->dwgreg.lastpix_b = 0; + break; + + default: + fatal("ILOAD_HIGHV DWGCTRL_ATYPE_RPL %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running); + break; + } + break; + + default: + fatal("Unknown ILOAD_HIGHV atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + } +} + + +static void +mystique_start_blit(mystique_t *mystique) +{ + uint64_t start_time = plat_timer_read(); + uint64_t end_time; + + mystique->dwgreg.dwgctrl_running = mystique->dwgreg.dwgctrl; + mystique->maccess_running = mystique->maccess; + if (mystique->busy) + fatal("Mystique still busy!\n"); + + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_SOLID) { + int x, y; + + for (y = 0; y < 8; y++) { + for (x = 0; x < 8; x++) + mystique->dwgreg.pattern[y][x] = 1; + } + mystique->dwgreg.src[0] = 0xffffffff; + mystique->dwgreg.src[1] = 0xffffffff; + mystique->dwgreg.src[2] = 0xffffffff; + mystique->dwgreg.src[3] = 0xffffffff; + } + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_ARZERO) { + mystique->dwgreg.ar[0] = 0; + mystique->dwgreg.ar[1] = 0; + mystique->dwgreg.ar[2] = 0; + mystique->dwgreg.ar[4] = 0; + mystique->dwgreg.ar[5] = 0; + mystique->dwgreg.ar[6] = 0; + } + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_SGNZERO) { + mystique->dwgreg.sgn.sdydxl = 0; + mystique->dwgreg.sgn.scanleft = 0; + mystique->dwgreg.sgn.sdxl = 0; + mystique->dwgreg.sgn.sdy = 0; + mystique->dwgreg.sgn.sdxr = 0; + } + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_SHTZERO) { + mystique->dwgreg.funcnt = 0; + mystique->dwgreg.stylelen = 0; + mystique->dwgreg.xoff = 0; + mystique->dwgreg.yoff = 0; + } + + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) { + case DWGCTRL_OPCODE_LINE_OPEN: + blit_line(mystique, 0); + break; + + case DWGCTRL_OPCODE_AUTOLINE_OPEN: + blit_autoline(mystique, 0); + break; + + case DWGCTRL_OPCODE_AUTOLINE_CLOSE: + blit_autoline(mystique, 1); + break; + + case DWGCTRL_OPCODE_TRAP: + blit_trap(mystique); + break; + + case DWGCTRL_OPCODE_TEXTURE_TRAP: + blit_texture_trap(mystique); + break; + + case DWGCTRL_OPCODE_ILOAD_HIGH: + blit_iload_high(mystique); + break; + + case DWGCTRL_OPCODE_BITBLT: + blit_bitblt(mystique); + break; + + case DWGCTRL_OPCODE_ILOAD: + blit_iload(mystique); + break; + + case DWGCTRL_OPCODE_IDUMP: + blit_idump(mystique); + break; + + case DWGCTRL_OPCODE_ILOAD_SCALE: + blit_iload_scale(mystique); + break; + + case DWGCTRL_OPCODE_ILOAD_HIGHV: + blit_iload_highv(mystique); + break; + + case DWGCTRL_OPCODE_ILOAD_FILTER: + /* TODO: Actually implement this. */ + break; + + default: + fatal("mystique_start_blit: unknown blit %08x\n", mystique->dwgreg.dwgctrl_running); + } + + end_time = plat_timer_read(); + mystique->blitter_time += end_time - start_time; +} + + +static void +mystique_hwcursor_draw(svga_t *svga, int displine) +{ + int x; + uint64_t dat[2]; + int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; + + dat[0] = *(uint64_t *)(&svga->vram[svga->hwcursor_latch.addr]); + dat[1] = *(uint64_t *)(&svga->vram[svga->hwcursor_latch.addr + 8]); + svga->hwcursor_latch.addr += 16; + for (x = 0; x < 64; x ++) { + if (!(dat[1] & (1ull << 63))) + buffer32->line[displine][offset + svga->x_add] = (dat[0] & (1ull << 63)) ? 0xffffff : 0; + else if (dat[0] & (1ull << 63)) + buffer32->line[displine][offset + svga->x_add] ^= 0xffffff; + + offset++; + dat[0] <<= 1; + dat[1] <<= 1; + } +} + + +static +uint8_t mystique_pci_read(int func, int addr, void *p) +{ + mystique_t *mystique = (mystique_t *)p; + + switch (addr) { + case 0x00: return 0x2b; /*Matrox*/ + case 0x01: return 0x10; + + case 0x02: return 0x1a; /*MGA-1064SG*/ + case 0x03: return 0x05; + + case PCI_REG_COMMAND: + return mystique->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ + + case 0x07: return 0 << 1; /*Fast DEVSEL timing*/ + + case 0x08: return 0; /*Revision ID*/ + case 0x09: return 0; /*Programming interface*/ + + case 0x0a: return 0x00; /*Supports VGA interface*/ + case 0x0b: return 0x03; + + case 0x10: return 0x00; /*Control aperture*/ + case 0x11: return (mystique->ctrl_base >> 8) & 0xc0; + case 0x12: return mystique->ctrl_base >> 16; + case 0x13: return mystique->ctrl_base >> 24; + + case 0x14: return 0x00; /*Linear frame buffer*/ + case 0x16: return (mystique->lfb_base >> 16) & 0x80; + case 0x17: return mystique->lfb_base >> 24; + + case 0x18: return 0x00; /*Pseudo-DMA (ILOAD)*/ + case 0x1a: return (mystique->iload_base >> 16) & 0x80; + case 0x1b: return mystique->iload_base >> 24; + + case 0x30: return mystique->pci_regs[0x30] & 0x01; /*BIOS ROM address*/ + case 0x31: return 0x00; + case 0x32: return mystique->pci_regs[0x32]; + case 0x33: return mystique->pci_regs[0x33]; + + case 0x3c: return mystique->int_line; + case 0x3d: return PCI_INTA; + + case 0x40: return mystique->pci_regs[0x40]; + case 0x41: return mystique->pci_regs[0x41]; + case 0x42: return mystique->pci_regs[0x42]; + case 0x43: return mystique->pci_regs[0x43]; + + case 0x44: return mystique->pci_regs[0x44]; + case 0x45: return mystique->pci_regs[0x45]; + + case 0x48: case 0x49: case 0x4a: case 0x4b: + addr = (mystique->pci_regs[0x44] & 0xfc) | ((mystique->pci_regs[0x45] & 0x3f) << 8) | + (addr & 3); + return mystique_ctrl_read_b(addr, mystique); + } + + return 0; +} + + +static void +mystique_pci_write(int func, int addr, uint8_t val, void *p) +{ + mystique_t *mystique = (mystique_t *)p; + + switch (addr) { + case PCI_REG_COMMAND: + mystique->pci_regs[PCI_REG_COMMAND] = val & 0x23; + mystique_recalc_mapping(mystique); + break; + + case 0x11: + mystique->ctrl_base = (mystique->ctrl_base & 0xffff0000) | ((val & 0xc0) << 8); + mystique_recalc_mapping(mystique); + break; + case 0x12: + mystique->ctrl_base = (mystique->ctrl_base & 0xff00c000) | (val << 16); + mystique_recalc_mapping(mystique); + break; + case 0x13: + mystique->ctrl_base = (mystique->ctrl_base & 0x00ffc000) | (val << 24); + mystique_recalc_mapping(mystique); + break; + + case 0x16: + mystique->lfb_base = (mystique->lfb_base & 0xff000000) | ((val & 0x80) << 16); + mystique_recalc_mapping(mystique); + break; + case 0x17: + mystique->lfb_base = (mystique->lfb_base & 0x00800000) | (val << 24); + mystique_recalc_mapping(mystique); + break; + + case 0x1a: + mystique->iload_base = (mystique->iload_base & 0xff000000) | ((val & 0x80) << 16); + mystique_recalc_mapping(mystique); + break; + case 0x1b: + mystique->iload_base = (mystique->iload_base & 0x00800000) | (val << 24); + mystique_recalc_mapping(mystique); + break; + + case 0x30: case 0x32: case 0x33: + mystique->pci_regs[addr] = val; + if (mystique->pci_regs[0x30] & 0x01) { + uint32_t addr = (mystique->pci_regs[0x32] << 16) | (mystique->pci_regs[0x33] << 24); + mem_mapping_set_addr(&mystique->bios_rom.mapping, addr, 0x8000); + } else + mem_mapping_disable(&mystique->bios_rom.mapping); + return; + + case 0x3c: + mystique->int_line = val; + return; + + case 0x40: case 0x41: case 0x42: case 0x43: + mystique->pci_regs[addr] = val; + break; + + case 0x4c: case 0x4d: case 0x4e: case 0x4f: + mystique->pci_regs[addr-0x20] = val; + break; + + case 0x44: case 0x45: + mystique->pci_regs[addr] = val; + break; + + case 0x48: case 0x49: case 0x4a: case 0x4b: + addr = (mystique->pci_regs[0x44] & 0xfc) | ((mystique->pci_regs[0x45] & 0x3f) << 8) | + (addr & 3); + mystique_ctrl_write_b(addr, val, mystique); + break; + } +} + + static void * mystique_init(const device_t *info) { - int c; - mystique_t *mystique = malloc(sizeof(mystique_t)); - memset(mystique, 0, sizeof(mystique_t)); + int c; + mystique_t *mystique = malloc(sizeof(mystique_t)); - rom_init(&mystique->bios_rom, L"roms/video/matrox/MYSTIQUE.VBI", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + memset(mystique, 0, sizeof(mystique_t)); - mystique->vram_size = device_get_config_int("memory"); - mystique->vram_mask = (mystique->vram_size << 20) - 1; - mystique->vram_mask_w = mystique->vram_mask >> 1; - mystique->vram_mask_l = mystique->vram_mask >> 2; - - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_matrox_mystique); + rom_init(&mystique->bios_rom, L"roms/video/matrox/MYSTIQUE.VBI", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - svga_init(&mystique->svga, mystique, mystique->vram_size << 20, - mystique_recalctimings, - mystique_in, mystique_out, - mystique_hwcursor_draw, - NULL); - - io_sethandler(0x03c0, 0x0020, mystique_in, NULL, NULL, mystique_out, NULL, NULL, mystique); - mem_mapping_add(&mystique->ctrl_mapping, 0, 0, - mystique_ctrl_read_b, NULL, mystique_ctrl_read_l, - mystique_ctrl_write_b, NULL, mystique_ctrl_write_l, - NULL, 0, mystique); - mem_mapping_add(&mystique->lfb_mapping, 0, 0, - svga_read_linear, svga_readw_linear, svga_readl_linear, - svga_write_linear, svga_writew_linear, svga_writel_linear, - NULL, 0, mystique); - mem_mapping_add(&mystique->iload_mapping, 0, 0, - mystique_iload_read_b, NULL, mystique_iload_read_l, - mystique_iload_write_b, NULL, mystique_iload_write_l, - NULL, 0, mystique); + mystique->vram_size = device_get_config_int("memory"); + mystique->vram_mask = (mystique->vram_size << 20) - 1; + mystique->vram_mask_w = mystique->vram_mask >> 1; + mystique->vram_mask_l = mystique->vram_mask >> 2; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_matrox_mystique); - mystique->card = pci_add_card(PCI_ADD_VIDEO, mystique_pci_read, mystique_pci_write, mystique); - mystique->pci_regs[0x2c] = mystique->bios_rom.rom[0x7ff8]; - mystique->pci_regs[0x2d] = mystique->bios_rom.rom[0x7ff8]; - mystique->pci_regs[0x2e] = mystique->bios_rom.rom[0x7ff8]; - mystique->pci_regs[0x2f] = mystique->bios_rom.rom[0x7ff8]; + svga_init(&mystique->svga, mystique, mystique->vram_size << 20, + mystique_recalctimings, + mystique_in, mystique_out, + mystique_hwcursor_draw, + NULL); - mystique->svga.miscout = 1; - mystique->pci_regs[0x41] = 0x01; /*vgaboot=1*/ - - for (c = 0; c < 256; c++) - { - dither5[c][0][0] = c >> 3; - dither5[c][1][1] = (c + 2) >> 3; - dither5[c][1][0] = (c + 4) >> 3; - dither5[c][0][1] = (c + 6) >> 3; + io_sethandler(0x03c0, 0x0020, mystique_in, NULL, NULL, mystique_out, NULL, NULL, mystique); + mem_mapping_add(&mystique->ctrl_mapping, 0, 0, + mystique_ctrl_read_b, NULL, mystique_ctrl_read_l, + mystique_ctrl_write_b, NULL, mystique_ctrl_write_l, + NULL, 0, mystique); + mem_mapping_add(&mystique->lfb_mapping, 0, 0, + svga_read_linear, svga_readw_linear, svga_readl_linear, + svga_write_linear, svga_writew_linear, svga_writel_linear, + NULL, 0, mystique); + mem_mapping_add(&mystique->iload_mapping, 0, 0, + mystique_iload_read_b, NULL, mystique_iload_read_l, + mystique_iload_write_b, NULL, mystique_iload_write_l, + NULL, 0, mystique); - if (dither5[c][1][1] > 31) - dither5[c][1][1] = 31; - if (dither5[c][1][0] > 31) - dither5[c][1][0] = 31; - if (dither5[c][0][1] > 31) - dither5[c][0][1] = 31; + mystique->card = pci_add_card(PCI_ADD_VIDEO, mystique_pci_read, mystique_pci_write, mystique); + mystique->pci_regs[0x2c] = mystique->bios_rom.rom[0x7ff8]; + mystique->pci_regs[0x2d] = mystique->bios_rom.rom[0x7ff8]; + mystique->pci_regs[0x2e] = mystique->bios_rom.rom[0x7ff8]; + mystique->pci_regs[0x2f] = mystique->bios_rom.rom[0x7ff8]; - dither6[c][0][0] = c >> 2; - dither6[c][1][1] = (c + 1) >> 2; - dither6[c][1][0] = (c + 2) >> 2; - dither6[c][0][1] = (c + 3) >> 2; + mystique->svga.miscout = 1; + mystique->pci_regs[0x41] = 0x01; /*vgaboot=1*/ - if (dither6[c][1][1] > 63) - dither6[c][1][1] = 63; - if (dither6[c][1][0] > 63) - dither6[c][1][0] = 63; - if (dither6[c][0][1] > 63) - dither6[c][0][1] = 63; - } - - mystique->wake_fifo_thread = thread_create_event(); - mystique->fifo_not_full_event = thread_create_event(); - mystique->fifo_thread = thread_create(fifo_thread, mystique); - mystique->dma.lock = thread_create_mutex(L"86Box.MGAMutex"); + for (c = 0; c < 256; c++) { + dither5[c][0][0] = c >> 3; + dither5[c][1][1] = (c + 2) >> 3; + dither5[c][1][0] = (c + 4) >> 3; + dither5[c][0][1] = (c + 6) >> 3; - timer_add(&mystique->wake_timer, mystique_wake_timer, (void *)mystique, 0); - timer_add(&mystique->softrap_pending_timer, mystique_softrap_pending_timer, (void *)mystique, 1); - - mystique->status = STATUS_ENDPRDMASTS; + if (dither5[c][1][1] > 31) + dither5[c][1][1] = 31; + if (dither5[c][1][0] > 31) + dither5[c][1][0] = 31; + if (dither5[c][0][1] > 31) + dither5[c][0][1] = 31; - return mystique; + dither6[c][0][0] = c >> 2; + dither6[c][1][1] = (c + 1) >> 2; + dither6[c][1][0] = (c + 2) >> 2; + dither6[c][0][1] = (c + 3) >> 2; + + if (dither6[c][1][1] > 63) + dither6[c][1][1] = 63; + if (dither6[c][1][0] > 63) + dither6[c][1][0] = 63; + if (dither6[c][0][1] > 63) + dither6[c][0][1] = 63; + } + + mystique->wake_fifo_thread = thread_create_event(); + mystique->fifo_not_full_event = thread_create_event(); + mystique->fifo_thread = thread_create(fifo_thread, mystique); + mystique->dma.lock = thread_create_mutex(L"86Box.MGAMutex"); + + timer_add(&mystique->wake_timer, mystique_wake_timer, (void *)mystique, 0); + timer_add(&mystique->softrap_pending_timer, mystique_softrap_pending_timer, (void *)mystique, 1); + + mystique->status = STATUS_ENDPRDMASTS; + + return mystique; } -static void mystique_close(void *p) + +static void +mystique_close(void *p) { - mystique_t *mystique = (mystique_t *)p; + mystique_t *mystique = (mystique_t *)p; - thread_kill(mystique->fifo_thread); - thread_destroy_event(mystique->wake_fifo_thread); - thread_destroy_event(mystique->fifo_not_full_event); - thread_close_mutex(mystique->dma.lock); + thread_kill(mystique->fifo_thread); + thread_destroy_event(mystique->wake_fifo_thread); + thread_destroy_event(mystique->fifo_not_full_event); + thread_close_mutex(mystique->dma.lock); - svga_close(&mystique->svga); + svga_close(&mystique->svga); - free(mystique); + free(mystique); } -static int mystique_available(void) + +static int +mystique_available(void) { - return rom_present(L"roms/video/matrox/MYSTIQUE.VBI"); + return rom_present(L"roms/video/matrox/MYSTIQUE.VBI"); } -static void mystique_speed_changed(void *p) + +static void +mystique_speed_changed(void *p) { - mystique_t *mystique = (mystique_t *)p; + mystique_t *mystique = (mystique_t *)p; - svga_recalctimings(&mystique->svga); + svga_recalctimings(&mystique->svga); } -static void mystique_force_redraw(void *p) + +static void +mystique_force_redraw(void *p) { - mystique_t *mystique = (mystique_t *)p; + mystique_t *mystique = (mystique_t *)p; - mystique->svga.fullchange = changeframecount; + mystique->svga.fullchange = changeframecount; } + static const device_config_t mystique_config[] = { { @@ -4882,6 +4648,10 @@ static const device_config_t mystique_config[] = .description = "4 MB", .value = 4 }, + { + .description = "8 MB", + .value = 8 + }, { .description = "" } From 8136f989118a797669a5f87e9121d5f1ea728331 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 18 Jan 2020 02:54:39 +0100 Subject: [PATCH 175/177] The Pentium Pro and Pentium II Overdrive CPU's now use K6 timings when on the new recompiler. --- src/cpu_new/cpu.c | 123 ++++++++++++++++++++++++---------------------- 1 file changed, 63 insertions(+), 60 deletions(-) diff --git a/src/cpu_new/cpu.c b/src/cpu_new/cpu.c index 0c1b212c3..6b277275c 100644 --- a/src/cpu_new/cpu.c +++ b/src/cpu_new/cpu.c @@ -1390,38 +1390,39 @@ cpu_set(void) x86_opcodes_df_a16 = ops_fpu_686_df_a16; x86_opcodes_df_a32 = ops_fpu_686_df_a32; timing_rr = 1; /*register dest - register src*/ - timing_rm = 1; /*register dest - memory src*/ - timing_mr = 1; /*memory dest - register src*/ - timing_mm = 1; - timing_rml = 1; /*register dest - memory src long*/ - timing_mrl = 1; /*memory dest - register src long*/ - timing_mml = 1; + timing_rm = 2; /*register dest - memory src*/ + timing_mr = 3; /*memory dest - register src*/ + timing_mm = 3; + timing_rml = 2; /*register dest - memory src long*/ + timing_mrl = 3; /*memory dest - register src long*/ + timing_mml = 3; timing_bt = 0; /*branch taken*/ timing_bnt = 1; /*branch not taken*/ - timing_int_rm = 9; - timing_int_v86 = 46; - timing_int_pm = 21; - timing_int_pm_outer = 32; + timing_int = 6; + timing_int_rm = 11; + timing_int_v86 = 54; + timing_int_pm = 25; + timing_int_pm_outer = 42; timing_iret_rm = 7; - timing_iret_v86 = 26; + timing_iret_v86 = 27; /*unknown*/ timing_iret_pm = 10; - timing_iret_pm_outer = 26; - timing_call_rm = 3; + timing_iret_pm_outer = 27; + timing_call_rm = 4; timing_call_pm = 4; - timing_call_pm_gate = 15; - timing_call_pm_gate_inner = 26; + timing_call_pm_gate = 22; + timing_call_pm_gate_inner = 44; timing_retf_rm = 4; timing_retf_pm = 4; timing_retf_pm_outer = 23; - timing_jmp_rm = 1; - timing_jmp_pm = 4; - timing_jmp_pm_gate = 14; - timing_misaligned = 2; + timing_jmp_rm = 3; + timing_jmp_pm = 3; + timing_jmp_pm_gate = 18; + timing_misaligned = 3; cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME; msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PCE; #ifdef USE_DYNAREC - codegen_timing_set(&codegen_timing_686); + codegen_timing_set(&codegen_timing_k6); #endif break; @@ -1445,38 +1446,39 @@ cpu_set(void) x86_opcodes_df_a16 = ops_fpu_686_df_a16; x86_opcodes_df_a32 = ops_fpu_686_df_a32; timing_rr = 1; /*register dest - register src*/ - timing_rm = 1; /*register dest - memory src*/ - timing_mr = 1; /*memory dest - register src*/ - timing_mm = 1; - timing_rml = 1; /*register dest - memory src long*/ - timing_mrl = 1; /*memory dest - register src long*/ - timing_mml = 1; + timing_rm = 2; /*register dest - memory src*/ + timing_mr = 3; /*memory dest - register src*/ + timing_mm = 3; + timing_rml = 2; /*register dest - memory src long*/ + timing_mrl = 3; /*memory dest - register src long*/ + timing_mml = 3; timing_bt = 0; /*branch taken*/ timing_bnt = 1; /*branch not taken*/ - timing_int_rm = 9; - timing_int_v86 = 46; - timing_int_pm = 21; - timing_int_pm_outer = 32; + timing_int = 6; + timing_int_rm = 11; + timing_int_v86 = 54; + timing_int_pm = 25; + timing_int_pm_outer = 42; timing_iret_rm = 7; - timing_iret_v86 = 26; + timing_iret_v86 = 27; /*unknown*/ timing_iret_pm = 10; - timing_iret_pm_outer = 26; - timing_call_rm = 3; + timing_iret_pm_outer = 27; + timing_call_rm = 4; timing_call_pm = 4; - timing_call_pm_gate = 15; - timing_call_pm_gate_inner = 26; + timing_call_pm_gate = 22; + timing_call_pm_gate_inner = 44; timing_retf_rm = 4; timing_retf_pm = 4; timing_retf_pm_outer = 23; - timing_jmp_rm = 1; - timing_jmp_pm = 4; - timing_jmp_pm_gate = 14; - timing_misaligned = 2; + timing_jmp_rm = 3; + timing_jmp_pm = 3; + timing_jmp_pm_gate = 18; + timing_misaligned = 3; cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME | CPU_FEATURE_MMX; msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PCE; #ifdef USE_DYNAREC - codegen_timing_set(&codegen_timing_686); + codegen_timing_set(&codegen_timing_k6); #endif break; #endif @@ -1500,38 +1502,39 @@ cpu_set(void) x86_opcodes_df_a16 = ops_fpu_686_df_a16; x86_opcodes_df_a32 = ops_fpu_686_df_a32; timing_rr = 1; /*register dest - register src*/ - timing_rm = 1; /*register dest - memory src*/ - timing_mr = 1; /*memory dest - register src*/ - timing_mm = 1; - timing_rml = 1; /*register dest - memory src long*/ - timing_mrl = 1; /*memory dest - register src long*/ - timing_mml = 1; + timing_rm = 2; /*register dest - memory src*/ + timing_mr = 3; /*memory dest - register src*/ + timing_mm = 3; + timing_rml = 2; /*register dest - memory src long*/ + timing_mrl = 3; /*memory dest - register src long*/ + timing_mml = 3; timing_bt = 0; /*branch taken*/ timing_bnt = 1; /*branch not taken*/ - timing_int_rm = 9; - timing_int_v86 = 46; - timing_int_pm = 21; - timing_int_pm_outer = 32; + timing_int = 6; + timing_int_rm = 11; + timing_int_v86 = 54; + timing_int_pm = 25; + timing_int_pm_outer = 42; timing_iret_rm = 7; - timing_iret_v86 = 26; + timing_iret_v86 = 27; /*unknown*/ timing_iret_pm = 10; - timing_iret_pm_outer = 26; - timing_call_rm = 3; + timing_iret_pm_outer = 27; + timing_call_rm = 4; timing_call_pm = 4; - timing_call_pm_gate = 15; - timing_call_pm_gate_inner = 26; + timing_call_pm_gate = 22; + timing_call_pm_gate_inner = 44; timing_retf_rm = 4; timing_retf_pm = 4; timing_retf_pm_outer = 23; - timing_jmp_rm = 1; - timing_jmp_pm = 4; - timing_jmp_pm_gate = 14; - timing_misaligned = 2; + timing_jmp_rm = 3; + timing_jmp_pm = 3; + timing_jmp_pm_gate = 18; + timing_misaligned = 3; cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME | CPU_FEATURE_MMX; msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PCE | CR4_OSFXSR; #ifdef USE_DYNAREC - codegen_timing_set(&codegen_timing_686); + codegen_timing_set(&codegen_timing_k6); #endif break; #endif From bde65cb5ce5936465854d50fd79587e4ff34a748 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 18 Jan 2020 04:33:57 +0100 Subject: [PATCH 176/177] More Matrox clean-ups, fixed the interlaced modes (1920x resolutions now work), and added the Matrox Mystique 220. --- src/video/vid_mga.c | 693 ++++++++++++++++++++---------------------- src/video/vid_mga.h | 5 +- src/video/vid_table.c | 3 +- 3 files changed, 341 insertions(+), 360 deletions(-) diff --git a/src/video/vid_mga.c b/src/video/vid_mga.c index 340c15560..5df1a693b 100644 --- a/src/video/vid_mga.c +++ b/src/video/vid_mga.c @@ -8,7 +8,7 @@ * * Matrox MGA graphics card emulation. * - * Version: @(#)vid_mga.c 1.0.0 2020/01/16 + * Version: @(#)vid_mga.c 1.0.1 2020/01/18 * * Author: Sarah Walker, * Copyright 2008-2020 Sarah Walker. @@ -31,12 +31,16 @@ #include "vid_svga.h" #include "vid_svga_render.h" + +#define ROM_MYSTIQUE L"roms/video/matrox/MYSTIQUE.VBI" +#define ROM_MYSTIQUE_220 L"roms/video/matrox/Myst220_66-99mhz.vbi" + #define FIFO_SIZE 65536 #define FIFO_MASK (FIFO_SIZE - 1) #define FIFO_ENTRY_SIZE (1 << 31) #define FIFO_THRESHOLD 0xe000 -#define WAKE_DELAY (100 * TIMER_USEC) /*100us*/ +#define WAKE_DELAY (100 * TIMER_USEC) /* 100us */ #define FIFO_ENTRIES (mystique->fifo_write_idx - mystique->fifo_read_idx) #define FIFO_FULL ((mystique->fifo_write_idx - mystique->fifo_read_idx) >= (FIFO_SIZE-1)) @@ -45,311 +49,6 @@ #define FIFO_TYPE 0xff000000 #define FIFO_ADDR 0x00ffffff -enum -{ - FIFO_INVALID = (0x00 << 24), - FIFO_WRITE_CTRL_BYTE = (0x01 << 24), - FIFO_WRITE_CTRL_LONG = (0x02 << 24), - FIFO_WRITE_ILOAD_LONG = (0x03 << 24) -}; - -typedef struct -{ - uint32_t addr_type; - uint32_t val; -} fifo_entry_t; - -typedef struct mystique_t -{ - svga_t svga; - - rom_t bios_rom; - - mem_mapping_t lfb_mapping; - mem_mapping_t ctrl_mapping; - mem_mapping_t iload_mapping; - - uint8_t pci_regs[256]; - uint8_t int_line; - int card; - - int vram_size; - uint32_t vram_mask, vram_mask_w, vram_mask_l; - - uint32_t lfb_base, ctrl_base, iload_base; - - uint8_t crtcext_regs[6]; - int crtcext_idx; - - uint8_t xreg_regs[256]; - int xreg_idx; - - uint32_t ma_latch_old; - - uint32_t maccess, mctlwtst; - uint32_t maccess_running; - - uint32_t status; - - uint8_t xcurctrl; - - uint8_t xsyspllm, xsysplln, xsyspllp; - struct - { - int m, n, p, s; - } xpixpll[3]; - - uint8_t xgenioctrl; - uint8_t xgeniodata; - uint8_t xmulctrl; - uint8_t xgenctrl; - uint8_t xmiscctrl; - uint8_t xpixclkctrl; - uint8_t xvrefctrl; - int xzoomctrl; - - uint8_t ien; - - struct - { - uint8_t funcnt, stylelen; - int xoff, yoff; - - uint16_t cxleft, cxright; - int16_t fxleft, fxright; - uint16_t length; - - uint32_t dwgctrl; - uint32_t dwgctrl_running; - uint32_t bcol, fcol; - uint32_t pitch; - uint32_t plnwt; - uint32_t ybot; - uint32_t ydstorg; - uint32_t ytop; - int selline; - - uint32_t src[4]; - uint32_t ar[7]; - uint32_t dr[16]; - - int pattern[8][8]; - - struct - { - int sdydxl; - int scanleft; - int sdxl; - int sdy; - int sdxr; - } sgn; - - uint32_t tmr[9]; - uint32_t texorg, texwidth, texheight; - uint32_t texctl, textrans; - uint32_t zorg; - - int ydst; - uint32_t ydst_lin; - - int length_cur; - int16_t xdst; - uint32_t src_addr; - uint32_t z_base; - - int iload_rem_count; - uint32_t iload_rem_data; - int idump_end_of_line; - - int words; - - int ta_key, ta_mask; - - int lastpix_r, lastpix_g, lastpix_b; - - int highv_line; - uint32_t highv_data; - - int beta; - - int dither; - - uint8_t dmamod; - } dwgreg; - - struct - { - uint8_t r, g, b; - } lut[256]; - - struct - { - uint16_t pos_x, pos_y; - uint16_t addr; - uint32_t col[3]; - } cursor; - - uint8_t dmamod, dmadatasiz, dirdatasiz; - struct - { - uint32_t primaddress, primend; - uint32_t secaddress, secend; - - int pri_pos, sec_pos, iload_pos; - uint32_t pri_header, sec_header, iload_header; - - int pri_state, sec_state, iload_state; - - int state; - - mutex_t *lock; - } dma; - - uint8_t dmamap[16]; - - volatile int busy; - volatile int blitter_submit_refcount; - volatile int blitter_submit_dma_refcount; - volatile int blitter_complete_refcount; - - volatile int endprdmasts_pending; - volatile int softrap_pending; - uint32_t softrap_pending_val; - - pc_timer_t softrap_pending_timer; - - uint64_t blitter_time; - uint64_t status_time; - - int pixel_count, trap_count; - - fifo_entry_t fifo[FIFO_SIZE]; - volatile int fifo_read_idx, fifo_write_idx; - - thread_t *fifo_thread; - event_t *wake_fifo_thread; - event_t *fifo_not_full_event; - - pc_timer_t wake_timer; -} mystique_t; - -static void mystique_start_blit(mystique_t *mystique); -static void mystique_update_irqs(mystique_t *mystique); - -static void wake_fifo_thread(mystique_t *mystique); -static void wait_fifo_idle(mystique_t *mystique); -static void mystique_queue(mystique_t *mystique, uint32_t addr, uint32_t val, uint32_t type); - -static const uint8_t trans_masks[16][16] = -{ - { - 1, 1, 1, 1, - 1, 1, 1, 1, - 1, 1, 1, 1, - 1, 1, 1, 1 - }, - { - 1, 0, 1, 0, - 0, 1, 0, 1, - 1, 0, 1, 0, - 0, 1, 0, 1 - }, - { - 0, 1, 0, 1, - 1, 0, 1, 0, - 0, 1, 0, 1, - 1, 0, 1, 0 - }, - { - 1, 0, 1, 0, - 0, 0, 0, 0, - 1, 0, 1, 0, - 0, 0, 0, 0 - }, - { - 0, 1, 0, 1, - 0, 0, 0, 0, - 0, 1, 0, 1, - 0, 0, 0, 0 - }, - { - 0, 0, 0, 0, - 1, 0, 1, 0, - 0, 0, 0, 0, - 1, 0, 1, 0 - }, - { - 0, 0, 0, 0, - 0, 1, 0, 1, - 0, 0, 0, 0, - 0, 1, 0, 1 - }, - { - 1, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 0 - }, - { - 0, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 1 - }, - { - 0, 0, 0, 1, - 0, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 0, 0 - }, - { - 0, 0, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 0, - 1, 0, 0, 0 - }, - { - 0, 0, 0, 0, - 1, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 1, 0 - }, - { - 0, 1, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 1, - 0, 0, 0, 0 - }, - { - 0, 0, 0, 0, - 0, 0, 0, 1, - 0, 0, 0, 0, - 0, 1, 0, 0 - }, - { - 0, 0, 1, 0, - 0, 0, 0, 0, - 1, 0, 0, 0, - 0, 0, 0, 0 - }, - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0 - } -}; - -static int8_t dither5[256][2][2]; -static int8_t dither6[256][2][2]; - -enum -{ - DMA_STATE_IDLE = 0, - DMA_STATE_PRI, - DMA_STATE_SEC -}; - #define DMA_POLL_TIME_US 100 /*100us*/ #define DMA_MAX_WORDS 256 /*256 quad words per 100us poll*/ @@ -645,18 +344,262 @@ enum #define DITHER_555 2 #define DITHER_NONE_555 3 -static void mystique_recalc_mapping(mystique_t *mystique); -static int mystique_line_compare(svga_t *svga); -static uint8_t mystique_iload_read_b(uint32_t addr, void *p); -static uint32_t mystique_iload_read_l(uint32_t addr, void *p); -static void mystique_iload_write_b(uint32_t addr, uint8_t val, void *p); -static void mystique_iload_write_l(uint32_t addr, uint32_t val, void *p); +enum +{ + FIFO_INVALID = (0x00 << 24), + FIFO_WRITE_CTRL_BYTE = (0x01 << 24), + FIFO_WRITE_CTRL_LONG = (0x02 << 24), + FIFO_WRITE_ILOAD_LONG = (0x03 << 24) +}; -static uint32_t blit_idump_read(mystique_t *mystique); -static void blit_iload_write(mystique_t *mystique, uint32_t data, int size); +enum +{ + DMA_STATE_IDLE = 0, + DMA_STATE_PRI, + DMA_STATE_SEC +}; -static video_timings_t timing_matrox_mystique = {VIDEO_BUS, 4, 4, 4, 10, 10, 10}; + +typedef struct +{ + uint32_t addr_type; + uint32_t val; +} fifo_entry_t; + +typedef struct mystique_t +{ + svga_t svga; + + rom_t bios_rom; + + mem_mapping_t lfb_mapping, ctrl_mapping, + iload_mapping; + + uint8_t int_line, xcurctrl, + xsyspllm, xsysplln, xsyspllp, + xgenioctrl, xgeniodata, + xmulctrl, xgenctrl, + xmiscctrl, xpixclkctrl, + xvrefctrl, ien, dmamod, + dmadatasiz, dirdatasiz; + + uint8_t pci_regs[256], crtcext_regs[6], + xreg_regs[256], dmamap[16]; + + int card, vram_size, crtcext_idx, xreg_idx, + xzoomctrl, + pixel_count, trap_count; + + volatile int busy, blitter_submit_refcount, + blitter_submit_dma_refcount, blitter_complete_refcount, + endprdmasts_pending, softrap_pending, + fifo_read_idx, fifo_write_idx; + + uint32_t vram_mask, vram_mask_w, vram_mask_l, + lfb_base, ctrl_base, iload_base, + ma_latch_old, maccess, mctlwtst, maccess_running, + status, softrap_pending_val; + + uint64_t blitter_time, status_time; + + pc_timer_t softrap_pending_timer, wake_timer; + + fifo_entry_t fifo[FIFO_SIZE]; + + thread_t *fifo_thread; + + event_t *wake_fifo_thread, *fifo_not_full_event; + + struct + { + int m, n, p, s; + } xpixpll[3]; + + struct + { + uint8_t funcnt, stylelen, + dmamod; + + int16_t fxleft, fxright, + xdst; + + uint16_t cxleft, cxright, + length; + + int xoff, yoff, selline, ydst, + length_cur, iload_rem_count, idump_end_of_line, words, + ta_key, ta_mask, lastpix_r, lastpix_g, + lastpix_b, highv_line, beta, dither; + + int pattern[8][8]; + + uint32_t dwgctrl, dwgctrl_running, bcol, fcol, + pitch, plnwt, ybot, ydstorg, + ytop, texorg, texwidth, texheight, + texctl, textrans, zorg, ydst_lin, + src_addr, z_base, iload_rem_data, highv_data; + + uint32_t src[4], ar[7], + dr[16], tmr[9]; + + struct + { + int sdydxl, scanleft, sdxl, sdy, + sdxr; + } sgn; + } dwgreg; + + struct + { + uint8_t r, g, b; + } lut[256]; + + struct + { + uint16_t pos_x, pos_y, + addr; + uint32_t col[3]; + } cursor; + + struct + { + int pri_pos, sec_pos, iload_pos, + pri_state, sec_state, iload_state, state; + + uint32_t primaddress, primend, secaddress, secend, + pri_header, sec_header, + iload_header; + + mutex_t *lock; + } dma; +} mystique_t; + + +static const uint8_t trans_masks[16][16] = +{ + { + 1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1 + }, + { + 1, 0, 1, 0, + 0, 1, 0, 1, + 1, 0, 1, 0, + 0, 1, 0, 1 + }, + { + 0, 1, 0, 1, + 1, 0, 1, 0, + 0, 1, 0, 1, + 1, 0, 1, 0 + }, + { + 1, 0, 1, 0, + 0, 0, 0, 0, + 1, 0, 1, 0, + 0, 0, 0, 0 + }, + { + 0, 1, 0, 1, + 0, 0, 0, 0, + 0, 1, 0, 1, + 0, 0, 0, 0 + }, + { + 0, 0, 0, 0, + 1, 0, 1, 0, + 0, 0, 0, 0, + 1, 0, 1, 0 + }, + { + 0, 0, 0, 0, + 0, 1, 0, 1, + 0, 0, 0, 0, + 0, 1, 0, 1 + }, + { + 1, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 0 + }, + { + 0, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 + }, + { + 0, 0, 0, 1, + 0, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 0, 0 + }, + { + 0, 0, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 0, + 1, 0, 0, 0 + }, + { + 0, 0, 0, 0, + 1, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 1, 0 + }, + { + 0, 1, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1, + 0, 0, 0, 0 + }, + { + 0, 0, 0, 0, + 0, 0, 0, 1, + 0, 0, 0, 0, + 0, 1, 0, 0 + }, + { + 0, 0, 1, 0, + 0, 0, 0, 0, + 1, 0, 0, 0, + 0, 0, 0, 0 + }, + { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 + } +}; + + +static int8_t dither5[256][2][2]; +static int8_t dither6[256][2][2]; + +static video_timings_t timing_matrox_mystique = {VIDEO_BUS, 4, 4, 4, 10, 10, 10}; + + +static void mystique_start_blit(mystique_t *mystique); +static void mystique_update_irqs(mystique_t *mystique); + +static void wake_fifo_thread(mystique_t *mystique); +static void wait_fifo_idle(mystique_t *mystique); +static void mystique_queue(mystique_t *mystique, uint32_t addr, uint32_t val, uint32_t type); + +static void mystique_recalc_mapping(mystique_t *mystique); +static int mystique_line_compare(svga_t *svga); + +static uint8_t mystique_iload_read_b(uint32_t addr, void *p); +static uint32_t mystique_iload_read_l(uint32_t addr, void *p); +static void mystique_iload_write_b(uint32_t addr, uint8_t val, void *p); +static void mystique_iload_write_l(uint32_t addr, uint32_t val, void *p); + +static uint32_t blit_idump_read(mystique_t *mystique); +static void blit_iload_write(mystique_t *mystique, uint32_t data, int size); void @@ -815,18 +758,26 @@ mystique_recalctimings(svga_t *svga) if (mystique->crtcext_regs[2] & CRTCX_R2_LINECOMP10) svga->split += 0x400; + svga->interlace = !!(mystique->crtcext_regs[0] & 0x80); + if (mystique->crtcext_regs[3] & CRTCX_R3_MGAMODE) { int row_offset = svga->crtc[0x13] | ((mystique->crtcext_regs[0] & CRTCX_R0_OFFSET_MASK) << 4); svga->lowres = 0; - svga->rowoffset = row_offset * 2; + if (svga->interlace) + svga->rowoffset = row_offset; + else + svga->rowoffset = row_offset * 2; svga->ma_latch = ((mystique->crtcext_regs[0] & CRTCX_R0_STARTADD_MASK) << 17) | (svga->crtc[0xc] << 9) | (svga->crtc[0xd] << 1); /*Mystique, unlike most SVGA cards, allows display start to take effect mid-screen*/ if (svga->ma_latch != mystique->ma_latch_old) { - svga->ma = svga->maback = (svga->maback - (mystique->ma_latch_old << 2)) + (svga->ma_latch << 2); + if (svga->interlace && svga->oddeven) + svga->ma = svga->maback = (svga->maback - (mystique->ma_latch_old << 2)) + (svga->ma_latch << 2) + (svga->rowoffset << 1); + else + svga->ma = svga->maback = (svga->maback - (mystique->ma_latch_old << 2)) + (svga->ma_latch << 2); mystique->ma_latch_old = svga->ma_latch; } @@ -4351,6 +4302,9 @@ mystique_hwcursor_draw(svga_t *svga, int displine) uint64_t dat[2]; int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; + if (svga->interlace && svga->hwcursor_oddeven) + svga->hwcursor_latch.addr += 16; + dat[0] = *(uint64_t *)(&svga->vram[svga->hwcursor_latch.addr]); dat[1] = *(uint64_t *)(&svga->vram[svga->hwcursor_latch.addr + 8]); svga->hwcursor_latch.addr += 16; @@ -4364,6 +4318,9 @@ mystique_hwcursor_draw(svga_t *svga, int displine) dat[0] <<= 1; dat[1] <<= 1; } + + if (svga->interlace && !svga->hwcursor_oddeven) + svga->hwcursor_latch.addr += 16; } @@ -4510,10 +4467,16 @@ mystique_init(const device_t *info) { int c; mystique_t *mystique = malloc(sizeof(mystique_t)); + wchar_t *romfn; memset(mystique, 0, sizeof(mystique_t)); - rom_init(&mystique->bios_rom, L"roms/video/matrox/MYSTIQUE.VBI", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + if (info->local == 1) + romfn = ROM_MYSTIQUE_220; + else + romfn = ROM_MYSTIQUE; + + rom_init(&mystique->bios_rom, romfn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); mystique->vram_size = device_get_config_int("memory"); mystique->vram_mask = (mystique->vram_size << 20) - 1; @@ -4549,7 +4512,7 @@ mystique_init(const device_t *info) mystique->pci_regs[0x2f] = mystique->bios_rom.rom[0x7ff8]; mystique->svga.miscout = 1; - mystique->pci_regs[0x41] = 0x01; /*vgaboot=1*/ + mystique->pci_regs[0x41] = 0x01; /* vgaboot = 1 */ for (c = 0; c < 256; c++) { dither5[c][0][0] = c >> 3; @@ -4634,45 +4597,61 @@ mystique_force_redraw(void *p) static const device_config_t mystique_config[] = { - { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "2 MB", - .value = 2 - }, - { - .description = "4 MB", - .value = 4 - }, - { - .description = "8 MB", - .value = 8 - }, - { - .description = "" - } - }, - .default_int = 4 - }, - { - .type = -1 - } + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .selection = + { + { + .description = "2 MB", + .value = 2 + }, + { + .description = "4 MB", + .value = 4 + }, + { + .description = "8 MB", + .value = 8 + }, + { + .description = "" + } + }, + .default_int = 8 + }, + { + .type = -1 + } }; + const device_t mystique_device = { - "Matrox Mystique", - DEVICE_PCI, - 0, - mystique_init, - mystique_close, - NULL, - mystique_available, - mystique_speed_changed, - mystique_force_redraw, - mystique_config + "Matrox Mystique", + DEVICE_PCI, + 0, + mystique_init, + mystique_close, + NULL, + mystique_available, + mystique_speed_changed, + mystique_force_redraw, + mystique_config +}; + + +const device_t mystique_220_device = +{ + "Matrox Mystique 220", + DEVICE_PCI, + 1, + mystique_init, + mystique_close, + NULL, + mystique_available, + mystique_speed_changed, + mystique_force_redraw, + mystique_config }; diff --git a/src/video/vid_mga.h b/src/video/vid_mga.h index 50c72d3ae..5291c81e4 100644 --- a/src/video/vid_mga.h +++ b/src/video/vid_mga.h @@ -8,10 +8,11 @@ * * Matrox MGA graphics card emulation. * - * Version: @(#)vid_mga.h 1.0.0 2020/01/16 + * Version: @(#)vid_mga.h 1.0.1 2020/01/18 * * Author: Sarah Walker, * Copyright 2008-2020 Sarah Walker. */ -extern const device_t mystique_device; \ No newline at end of file +extern const device_t mystique_device; +extern const device_t mystique_220_device; diff --git a/src/video/vid_table.c b/src/video/vid_table.c index 4db6190ba..b72a71e08 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -8,7 +8,7 @@ * * Define all known video cards. * - * Version: @(#)vid_table.c 1.0.45 2020/01/17 + * Version: @(#)vid_table.c 1.0.46 2020/01/18 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -150,6 +150,7 @@ video_cards[] = { { "[PCI] Diamond Stealth 64 DRAM (S3 Trio64)", "stealth64d_pci", &s3_diamond_stealth64_pci_device }, { "[PCI] Diamond Stealth 64 VRAM (S3 Vision964)", "stealth64v_pci", &s3_diamond_stealth64_964_pci_device }, { "[PCI] Matrox Mystique", "mystique", &mystique_device }, + { "[PCI] Matrox Mystique 220", "mystique_220", &mystique_220_device }, { "[PCI] Number Nine 9FX (S3 Trio64)", "n9_9fx_pci", &s3_9fx_pci_device }, { "[PCI] Paradise Bahamas 64 (S3 Vision864)", "bahamas64_pci", &s3_bahamas64_pci_device }, { "[PCI] Phoenix S3 Vision864", "px_vision864_pci", &s3_phoenix_vision864_pci_device }, From 995e2f0c614ead4e9f5e6018cfec930bfb5ca908 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 18 Jan 2020 04:53:30 +0100 Subject: [PATCH 177/177] Fixed the fpu_log() function, it should now link correctly. --- src/cpu/x87.c | 4 ++-- src/cpu_new/x87.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cpu/x87.c b/src/cpu/x87.c index abc2f48a4..5016661a3 100644 --- a/src/cpu/x87.c +++ b/src/cpu/x87.c @@ -21,12 +21,12 @@ int fpu_do_log = ENABLE_FPU_LOG; -static void +void fpu_log(const char *fmt, ...) { va_list ap; - if (fpu_log) { + if (fpu_do_log) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); diff --git a/src/cpu_new/x87.c b/src/cpu_new/x87.c index 367948656..7d27e29f3 100644 --- a/src/cpu_new/x87.c +++ b/src/cpu_new/x87.c @@ -21,12 +21,12 @@ int fpu_do_log = ENABLE_FPU_LOG; -static void +void fpu_log(const char *fmt, ...) { va_list ap; - if (fpu_log) { + if (fpu_do_log) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap);