mikechambers84 / XTulator

XTulator is a portable, open source x86 PC emulator currently supporting the 8086 instruction set and 80186 extensions.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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
horizontal_lines

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?