Testcase: Old Fake86: Replay problems with game "Stunts"
LowLevelMahn opened this issue · comments
Stunts driving replays did not work with latest fake86 code - but always with dosbox
- could be an opcode-implementation or timeing problem
maybe its already fixed with your new XTulator code
Problem:
http://forum.stunts.hu/index.php?topic=3272.msg70997#msg70997
Testdata:
http://forum.stunts.hu/index.php?topic=3272.msg71000#msg71000
Scenario:
http://forum.stunts.hu/index.php?topic=3272.msg71010#msg71010
this is just a reminder: i will come up with a clear test for this (possible) error later
the bug with Stunts still seems to happen - i will record a small video of the problem
Dosbox is the official emulator in the still living Stunts races community - very well tested
problems in XTulator (seconds = replay seconds in the stunts ui)
1. sometimes graphical glitches - horizontal lines? ~second: 10
2. leaving track at ~second: 34 - completely wrong (replay runs in dosbox from start to finish)
both bugs are also in your Fake86 emulator
Video-Comparison:
XTulator: https://streamable.com/8xjj9m
Dosbox: https://streamable.com/caake8
XTulator seems to be faster - my cycles seems to low - but
the XTulator bugs do not appear even with much higher cycles in dosbox
will compare to PCEm later
videos made with: https://github.com/MathewSachin/Captura
uploaded to streamable.com a free video hoster
Interesting. Going off the track may be timing-related somehow, but the lines across the sky seems like an opcode bug to me. Maybe wrong flags getting set somewhere. This may take some time to figure out. I'll probably need to comb through each opcode type and read some instruction set docs and/or compare to another emulator carefully.
UPDATE: most tests are for the 386 :(
could be the unit-test of the masm2c project of any help?: https://github.com/xor2003/masm2c
https://github.com/xor2003/masm2c/tree/master/asmTests
should run under XTulator
test386 project, works as bios
https://github.com/barotto/test386.asm
QEmu-Tests
https://github.com/xor2003/masm2c/tree/master/qemu_tests - could be ported to 16bit (reduce opcode amount)
run under dosbox, XTulator and compare
https://www.vogons.org/viewtopic.php?p=371657#p371657
org from qemu:
https://git.qemu.org/?p=qemu.git;a=tree;f=tests/tcg/i386;h=c74c9e23bf4f304fdb5d3345ba17633426aa4c9b;hb=HEAD
a list of Stunts using Opcodes (extracted from IDA - with removed seg-reg overrides)
adc 0x11
adc 0x13
adc 0x15
adc 0x83
add 0x00
add 0x01
add 0x02
add 0x03
add 0x04
add 0x05
add 0x80
add 0x81
add 0x83
and 0x20
and 0x21
and 0x22
and 0x23
and 0x24
and 0x25
and 0x80
and 0x81
and 0x83
call 0x9a
call 0xe8
call 0xff
cbw 0x98
clc 0xf8
cld 0xfc
cli 0xfa
cmp 0x38
cmp 0x39
cmp 0x3a
cmp 0x3b
cmp 0x3c
cmp 0x3d
cmp 0x80
cmp 0x81
cmp 0x83
cmps 0xa6
cmps 0xa6 REP/REPE/REPZ
cwd 0x99
dec 0x48
dec 0x49
dec 0x4a
dec 0x4b
dec 0x4e
dec 0x4f
dec 0xfe
dec 0xff
div 0xf6
div 0xf7
idiv 0xf6
idiv 0xf7
imul 0xf6
imul 0xf7
in 0xe4
in 0xec
inc 0x40
inc 0x41
inc 0x42
inc 0x43
inc 0x45
inc 0x46
inc 0x47
inc 0xfe
inc 0xff
int 0xcd
iret 0xcf
ja 0x77
jb 0x72
jbe 0x76
jcxz 0xe3
jg 0x7f
jge 0x7d
jl 0x7c
jle 0x7e
jmp 0xe9
jmp 0xea
jmp 0xeb
jmp 0xff
jnb 0x73
jno 0x71
jns 0x79
jnz 0x75
jo 0x70
js 0x78
jz 0x74
lahf 0x9f
lds 0xc5
lea 0x8d
les 0xc4
lods 0xac
lods 0xad
loop 0xe2
mov 0x88
mov 0x89
mov 0x8a
mov 0x8b
mov 0x8c
mov 0x8e
mov 0xa0
mov 0xa1
mov 0xa2
mov 0xa3
mov 0xb0
mov 0xb1
mov 0xb2
mov 0xb3
mov 0xb4
mov 0xb5
mov 0xb7
mov 0xb8
mov 0xb9
mov 0xba
mov 0xbb
mov 0xbd
mov 0xbe
mov 0xbf
mov 0xc6
mov 0xc7
movs 0xa4
movs 0xa4 REP/REPE/REPZ
movs 0xa4 REPNE/REPNZ
movs 0xa5
movs 0xa5 REP/REPE/REPZ
movs 0xa5 REPNE/REPNZ
mul 0xf6
mul 0xf7
neg 0xf6
neg 0xf7
nop 0x90
not 0xf6
not 0xf7
or 0x08
or 0x09
or 0x0a
or 0x0b
or 0x0c
or 0x0d
or 0x80
or 0x81
or 0x83
out 0xe6
out 0xee
pop 0x07
pop 0x1f
pop 0x58
pop 0x59
pop 0x5a
pop 0x5b
pop 0x5d
pop 0x5e
pop 0x5f
pop 0x8f
push 0x06
push 0x0e
push 0x16
push 0x1e
push 0x50
push 0x51
push 0x52
push 0x53
push 0x55
push 0x56
push 0x57
push 0xff
pushf 0x9c
rcl 0xd1
rcr 0xd1
retf 0xca
retf 0xcb
retn 0xc3
rol 0xd0
rol 0xd2
rol 0xd3
sahf 0x9e
sar 0xd1
sar 0xd3
sbb 0x19
sbb 0x1a
sbb 0x1b
sbb 0x1c
sbb 0x1d
sbb 0x83
scas 0xae
scas 0xae REPNE/REPNZ
shl 0xd0
shl 0xd1
shl 0xd2
shl 0xd3
shr 0xd0
shr 0xd1
shr 0xd3
stc 0xf9
std 0xfd
sti 0xfb
stos 0xaa
stos 0xaa REP/REPE/REPZ
stos 0xab
stos 0xab REP/REPE/REPZ
sub 0x28
sub 0x29
sub 0x2a
sub 0x2b
sub 0x2c
sub 0x2d
sub 0x80
sub 0x81
sub 0x83
test 0x84
test 0x85
test 0xa8
test 0xa9
test 0xf6
test 0xf7
xchg 0x86
xchg 0x87
xchg 0x91
xchg 0x92
xchg 0x93
xchg 0x95
xchg 0x96
xchg 0x97
xlat 0xd7
xor 0x30
xor 0x31
xor 0x32
xor 0x33
xor 0x34
xor 0x80
i would add a inline_asm version that compares the result (with define) inside of your interpreted opcode function
its slower but you can break right where the error occures
not the ideal solution but easy to develop :) and also small when using macros
FUNC_INLINE void op_add8(CPU_t* cpu) {
#ifdef COMPARE_INLINE_ASM
uint8_t comp_res = 0;
uint16_t comp_flags = makeflagsword(cpu);
uint8_t op1 = cpu->oper1b;
uint8_t op2 = cpu->oper2b;
__asm
{
// set flags
push comp_flags
popf
// set parameter
mov al, op1
mov bl, op2
// run cmd
add al, bl
// results
mov comp_res, al
pushf
pop comp_flags
}
#endif
cpu->res8 = cpu->oper1b + cpu->oper2b;
flag_add8(cpu, cpu->oper1b, cpu->oper2b);
#ifdef COMPARE_INLINE_ASM
uint8_t curr_res = cpu->res8;
uint16_t curr_flags = makeflagsword(cpu);
if (curr_res != comp_res)
{
assert(FALSE);
}
if (curr_flags != comp_flags)
{
assert(FALSE);
}
#endif
}
works only with x86 build (x64 build does not contain inline asm)
Going off the track may be timing-related somehow
even a very very slow (300 cycles, sometimes less then 0.1 FPS)
dosbox does not leave the track at this point and finished the replay like in the fast version
i would activate these inline tests for every operation seperately - just too slow to have all operations as inline-asm
or an "real" unit-test
void cpu_test()
{
{
uint8_t op1 = 0x10;
uint8_t op2 = 0x20;
uint16_t flags = 0x123;
uint8_t res = 0;
uint16_t res_flags = 0;
uint8_t asm_res = 0;
uint16_t asm_res_flags = 0;
{
CPU_t cpu;
cpu.oper1b = op1;
cpu.oper2b = op2;
decodeflagsword((&cpu), flags);
op_add8(&cpu);
res = cpu.res8;
res_flags = makeflagsword((&cpu));
}
{
__asm
{
push flags
popf
mov al,op1
mov bl,op2
add al,bl
mov asm_res,al
pushf
pop asm_res_flags
}
}
}
}
what is faux86?, what is circle?, what do you want to do with windows Bash? What is the relation to this Stunts issue?