Box86 - Linux Userspace x86 Emulator


Papers. please failed with latest HEAD :

Code:
Using emulated libudev.so.1
Using emulated libmount.so.1
Using emulated libblkid.so.1
Using emulated libuuid.so.1
Error: Symbol __openat64_2 not found, cannot apply R_386_JMP_SLOT @0x42a9538c (0x2e76)
Error: Symbol __fxstatat64 not found, cannot apply R_386_JMP_SLOT @0x42a95538 (0x3526)
Error: Symbol err not found, cannot apply R_386_JMP_SLOT @0x41bd03e4 (0x23ee)
Error: Symbol errx not found, cannot apply R_386_JMP_SLOT @0x41bd04c8 (0x277e)
Error: Symbol name_to_handle_at not found, cannot apply R_386_JMP_SLOT @0x41c28e28 (0x2836)
Error: Symbol reallocarray not found, cannot apply R_386_JMP_SLOT @0x41c28e44 (0x28a6)
Error: Symbol __asprintf_chk not found, cannot apply R_386_JMP_SLOT @0x41c28eac (0x2a46)
Error: Symbol readlinkat not found, cannot apply R_386_JMP_SLOT @0x41c28ebc (0x2a86)
Error: Symbol timerfd_create not found, cannot apply R_386_JMP_SLOT @0x41c28ec8 (0x2ab6)
Error: Symbol openat64 not found, cannot apply R_386_JMP_SLOT @0x41c28ef0 (0x2b56)
Error: Symbol __fsetlocking not found, cannot apply R_386_JMP_SLOT @0x41c28f24 (0x2c26)
Warning, function getauxval not found in lib libc.so.6
Error: Symbol getauxval not found, cannot apply R_386_JMP_SLOT @0x41c28f48 (0x2cb6)
6715|0xa80b44e3: Unimplemented Opcode C3 00 00 CC 53 43 8C 6A
Segmentation fault

and Luftrausers :

Code:
Using default BOX86_LD_LIBRARY_PATH: ./:lib/
Using default BOX86_PATH: ./:bin/
Counted 29 Env var
Looking for luftrausers
Using emulated libjsoncpp.so.0
Using native(wrapped) libpthread.so.0
Using emulated libstdc++.so.6
Using native(wrapped) libm.so.6
Using native(wrapped) libc.so.6
Using native(wrapped) ld-linux.so.2
Using native(wrapped) librt.so.1
Using emulated libgcc_s.so.1
Using emulated libsfml-audio.so.2
Using emulated libsfml-system.so.2
Using native(wrapped) libopenal.so.1
Using emulated libsndfile.so.1
Using emulated libFLAC.so.8
Using native(wrapped) libogg.so.0
Using emulated libvorbisenc.so.2
Using native(wrapped) libvorbis.so.0
Using native(wrapped) libSDL2-2.0.so.0
LIBGL: Initialising gl4es
LIBGL: v1.1.1 built on Mar 17 2019 17:09:25
LIBGL: Using GLES 1.1 backend
LIBGL: loaded: libGLES_CM.so
LIBGL: loaded: libEGL.so
LIBGL: Using GLES 1.1 backend
LIBGL: Extension GL_OES_framebuffer_object detected and used
LIBGL: Extension GL_OES_point_sprite detected and used
LIBGL: Extension GL_OES_point_size_array detected
LIBGL: Extension GL_OES_texture_cube_map detected and used
LIBGL: Extension GL_OES_blend_subtract detected and used
LIBGL: Extension GL_OES_blend_func_separate detected and used
LIBGL: Extension GL_OES_blend_equation_separate detected and used
LIBGL: Extension GL_OES_texture_mirrored_repeat detected and used
LIBGL: Extension GL_OES_mapbuffer detected
LIBGL: Extension GL_OES_depth24 detected and used
LIBGL: Extension GL_OES_rgb8_rgba8 detected and used
LIBGL: Extension GL_EXT_multi_draw_arrays detected
LIBGL: Extension GL_EXT_texture_format_BGRA8888 detected and used
LIBGL: Extension GL_OES_draw_texture detected and used
LIBGL: Max texture size: 2048
LIBGL: Texture Units: 4(4), Max lights: 8, Max planes: 6
LIBGL: Hardware vendor is Imagination Technologies
LIBGL: Targeting OpenGL 1.5
LIBGL: FBO workaround for using binded texture enabled
LIBGL: glX Will try to recycle EGL Surface
LIBGL: Current folder is:/media/bigpanda/box86/luftrausers-nodrm/i686
Using native(wrapped) libGL.so.1
Using native(wrapped) libXrandr.so.2
Using emulated libfreetype.so.6
Using native(wrapped) libz.so.1
Using native(wrapped) libX11.so.6
Using native(wrapped) libxcb.so.1
Using native(wrapped) libXext.so.6
Using emulated libXau.so.6
Using emulated libXdmcp.so.6
Using native(wrapped) libXrender.so.1
Using native(wrapped) libdl.so.2
Error: Symbol ogg_stream_reset not found, cannot apply R_386_JMP_SLOT @0x4069800c (0x7e66)
Error: Symbol ogg_page_checksum_set not found, cannot apply R_386_JMP_SLOT @0x40698038 (0x7f16)
Error: Symbol ogg_stream_flush not found, cannot apply R_386_JMP_SLOT @0x40698048 (0x7f56)
Error: Symbol ogg_stream_packetin not found, cannot apply R_386_JMP_SLOT @0x4069804c (0x7f66)
Error: Symbol ogg_sync_reset not found, cannot apply R_386_JMP_SLOT @0x40698068 (0x7fd6)
Error: Symbol ogg_stream_pageout not found, cannot apply R_386_JMP_SLOT @0x40698100 (0x8236)
Error: Symbol ogg_stream_reset not found, cannot apply R_386_JMP_SLOT @0x40214000 (0x2d96)
Error: Symbol vorbis_analysis_init not found, cannot apply R_386_JMP_SLOT @0x40214048 (0x2eb6)
Error: Symbol ogg_stream_flush not found, cannot apply R_386_JMP_SLOT @0x40214050 (0x2ed6)
Error: Symbol ogg_stream_packetin not found, cannot apply R_386_JMP_SLOT @0x40214060 (0x2f16)
Error: Symbol vorbis_analysis not found, cannot apply R_386_JMP_SLOT @0x40214074 (0x2f66)
Error: Symbol vorbis_version_string not found, cannot apply R_386_JMP_SLOT @0x40214078 (0x2f76)
Error: Symbol ogg_sync_reset not found, cannot apply R_386_JMP_SLOT @0x40214084 (0x2fa6)
Error: Symbol vorbis_analysis_wrote not found, cannot apply R_386_JMP_SLOT @0x402140b8 (0x3076)
Error: Symbol vorbis_analysis_blockout not found, cannot apply R_386_JMP_SLOT @0x402140c0 (0x3096)
Error: Symbol vorbis_analysis_buffer not found, cannot apply R_386_JMP_SLOT @0x402140c4 (0x30a6)
Error: Symbol vorbis_bitrate_flushpacket not found, cannot apply R_386_JMP_SLOT @0x402140ec (0x3146)
Error: Symbol vorbis_bitrate_addblock not found, cannot apply R_386_JMP_SLOT @0x40214114 (0x31e6)
Error: Symbol vorbis_comment_query not found, cannot apply R_386_JMP_SLOT @0x4021414c (0x32c6)
Error: Symbol vorbis_analysis_headerout not found, cannot apply R_386_JMP_SLOT @0x40214158 (0x32f6)
Error: Symbol vorbis_comment_add_tag not found, cannot apply R_386_JMP_SLOT @0x40214160 (0x3316)
Error: Symbol ogg_stream_pageout not found, cannot apply R_386_JMP_SLOT @0x402141b4 (0x3466)
Error: Symbol lrand48 not found, cannot apply R_386_JMP_SLOT @0x408e4f78 (0x1040)
Error: Symbol getentropy not found, cannot apply R_386_JMP_SLOT @0x408e4f94 (0x10b0)
Error: Symbol _ZNSt8__detail15_List_node_base7_M_hookEPS0_ not found, cannot apply R_386_JMP_SLOT @0x83566c0 (0x805d836)
Error: Symbol _ZNSsC1EOSs not found, cannot apply R_386_JMP_SLOT @0x8356818 (0x805dd96)
Error: Symbol _ZNSsaSEOSs not found, cannot apply R_386_JMP_SLOT @0x835686c (0x805dee6)
Warning, function glBindFragDataLocation not found in lib libGL.so.1
Error: Symbol glBindFragDataLocation not found, cannot apply R_386_JMP_SLOT @0x83568a4 (0x805dfc6)
Error: Symbol _ZNSt8__detail15_List_node_base9_M_unhookEv not found, cannot apply R_386_JMP_SLOT @0x8356ad4 (0x805e886)
Error: Symbol SDL_SetWindowDisplayMode not found, cannot apply R_386_JMP_SLOT @0x8356b18 (0x805e996)
Segmentation fault
 
@ElPoco :
For Paper, please, the unimplemented C3... is suspicious, because that RET and it's implemented of course. Something else must be going wrong. The function missig are probably what make it crash anyway, I assume stuff like getauxval or the various openat64 or timerfd_create are used durring initialization. Il see to add some of those function later (getauxval will probably be tricky).

For Luftrausers, there seems to be a large bunch of libogg and libvorbis function that I need to add. There are a few C++ functions, that I found strange to see not found (all the _ZNS... stuffs), but maybe it's ok.
Also, the glBindFragDataLocation : that's a function not supported in gl4es. I'll have to check what this thing do. Anyway, you will probably need to use LIBGL_ES=2 for this one, as it seems to use shader (anyway, for Box86, you will need LIBGL_ES=2 most of the time, there is almost nothing running with just OpenGL 1.5)
 
I might have done something wrong with the libs. I downloaded most of them from https://pkgs.org by taking the first i386 or i686 lib I could find.
Let me know if there's anything I can do to help.
 
Yeah, I have done some more updates. Some wrapped function and a few libs, and, lately, a somehow correct implementation of TLS handling (Thread Local Storage). But I still haven't worked on any DynaRec yet, so nothing major to anounce.
 
somehow correct? You say that like it's correctness was more accident than design...

-Neelix
It's more that I'm confidentent it's fairly correct, but still probably not 100%.
I think TLS data in the program elf is handled correctly (everything going through GS:[negative offset] should be handled correctly. TLS stuffs in libs, and ___tls_get_addr or __tls_get_addr, I'm less sure (it's more, I'm a bit unsure of the R_386_TLS_DTPMOD32 and R_386_TLS_DTPOFF32 relocation in elfloading).
 
Here is a small update on what is happening on Box86:

More and more libs, with more funciton have been wrapped. And some bug fixes have also been done. Box86 is now pretty stable. Still not able to really launch Steam (the full client) yet, but that's more a matter of wrapping new libs now, like all ffmpeg/libav stuff, that would help greatly.
But for now, I have put on hold all the lib wrapping and started working on a dynarec. At last, as I waited long enough to stat it.
So the dynarec is, for now, ARM only, and I started implementing basic infrastructure bricks.
The principle is: you take an x86 instruction, and translate each instruction to ARM equivalent code until there is an unknow opcode (meaning, the dynarec cannot execute it), or a JMP/CALL/RET instruction (unless that jmp instruction jumps inside the block). The point is to have block of ARM instruction that are then linked between them.
The Block handling is done. Linking between blocks is done (there is table with each block, and the 'linker" will write the address of next block, if jump address is static, so next time there is no need to look for it again).
ARM has 16 general register (r0..r15), but not all are available. Also, regular C use r0..r3 for Function call parameter, and r0 is also use for return value (when stuff don't fill in the register, it goes on the stack).
What I decided to do here is to have the "x86emu_t" structure (holding all x86 emulated state, including registers) is mapped in "r0", then r1..r3 are free for each opcode (to use as temporary for storage or calculus), then all x86 regs (EAX, ECX, EDX, EBX, EBP, ESP, ESI, EDI) are directly mapped to r4..r11. The EIP (Instruction Pointer) can be mapped on r12, but r12 is used most of the time has another scratch register, because each x86 opocde doesn't update EIP locally.

For now, dynarec developpement occurs on a branch (very creativelly called "dynarec"). I'll merge that to master when it will be in a pretty stable and somehow developped enough state.

For X86Flags handling, for now I rely on the same mechanism as the Interpreter: with a "lazy flag" scheme (so not computing flags change at every instruction), and rely for most of the time on the C function to compute them.

Many X86 General Instruction have been coded already, but I haven't worked yet on any X87, MMX, or SSE(2) opcode. So there is already some speedup, but it's not yet dramatic, as most of the time the interpreter is running (don't forget a block end when an unknown instruction is found, and the dynarec will be call only at the next JMP/CALL/RET opcode).

To give you an idea on what is going on, here is a trace a dynarec log, when emitting a block (so x86 -> arm translation)
Code:
Ask for DynaRec Block creation @0x804b110
Ask for DynaRec Block Alloc #1
Emitting 124 bytes for 27 x86 bytes
0x804b110: 8D 4C 24 04 lea ecx, [esp+0x04]
        e2885004        ADD r5, r8, #4
0x804b114: 83 E4 F0 and esp, 0xFFFFFFF0
        e30f3ff0        MOVW r3, #0xfff0
        e34f3fff        MOVT r3, #0xffff
        e0088003        AND r8, r8, r3
0x804b117: FF 71 FC push [ecx-0x04]
        e2452004        SUB r2, r5, #4
        e5921000        LDR r1,[r2]
        e9280002        STMDB r8!,{r1}
0x804b11a: 55 push ebp
        e9280200        STMDB r8!,{r9}
0x804b11b: 89 E5 mov ebp, esp
        e1a09008        MOV r9, r8
0x804b11d: 51 push ecx
        e9280020        STMDB r8!,{r5}
0x804b11e: 83 EC 0C sub esp, 0x0C
        e58083b0        STR r8,[r0, #944]
        e300300c        MOVW r3, #0xc
        e58033b4        STR r3,[r0, #948]
        e248800c        SUB r8, r8, #12
        e58083b8        STR r8,[r0, #952]
        e3003024        MOVW r3, #0x24
        e58033ac        STR r3,[r0, #940]
0x804b121: FF 71 04 push [ecx+0x04]
        e2852004        ADD r2, r5, #4
        e5921000        LDR r1,[r2]
        e9280002        STMDB r8!,{r1}
0x804b124: FF 31 push [ecx]
        e5951000        LDR r1,[r5]
        e9280002        STMDB r8!,{r1}
0x804b126: E8 B5 21 06 00 call 0x080AD2E0
        e30b212b        MOVW r2, #0xb12b
        e3402804        MOVT r2, #0x804
        e9280004        STMDB r8!,{r2}
Jump to linker (#0)
        e30dc2e0        MOVW r12, #0xd2e0
        e340c80a        MOVT r12, #0x80a
        e30b1618        MOVW r1, #0xb618
        e34a1812        MOVT r1, #0xa812
        e5912000        LDR r2,[r1]
        e12fff12        BX r2
 --- DynaRec Block created @0x804b110 (0x408e7000, 0x7c bytes)
The emitted code is not perfect, but it's a start.
For now, I need more opcode, and I should also do more unit test. I have a few already, but I have seen that this is clearly not enough to trap all the mistakes and typo I do...

That was a quick glipse, I hope you enjoyed it...
 
Last edited:
I think I have one or two opcodes I don't use anymore, do you want them ?
:^)

Amazing work, you have no limit :^)
 
Fantastic; I check this part of the forum most days, specifically to see if there has been any update here, as well as checking commits on github, but it is obviously one of those projects where a lot of up front work is required to get a handlful of things running, and each new app/game takes another load of effort, but eventually things start moving a bit quicker. Although from a different angle, the dynrec will certainly get things moving a bit quicker!
 
Here are some more news about Box86.
The Dynarec is progressing.
Most of the main x86 instructions are done, with some optimizations about flags handling. And now most x87 instruction are also done, using VFPU. For now, I keep internal x87 registers as "double", making potentially a lot conversions between double and float (on x87, register are "long double", so 80bits internally, and conversion long double -> double/float is basically free).

I have now started a stabilisation phase, where I work mostly on buug fix and not adding new instructions. I fixed a lot, but a few are still there, but there are quite difficult to found now.
The status of my testing:

World of Goo: There is a bug that I haven't found yet (and 1 spent 1 day on it already) were the Profile data are not saved correctly. This is happening at the end of a session only, and there is no error message, it's completly silent, so difficult to tract down. Intro and "Win" screen are still a bit slow: they used "movies" and this seems to be a bit too much for the Pandora. The game play itself is super smooth, look:

Super Meat Boy: The game is fullspeed on my Gigahertz Pandora! But there is a bug somewhere and the sound stop after the Intro, the gameplay is silent, so I didn't do a video of it yet.

FTL: Game now load quickly (like 2min, it was 20min before the Dynarec). The Game is still too slow for now, but this one use SSE(2) a lot, so more speed to come.

NeverWinter Night (Diamond Edition): The game now runs. The sound is fine (it was choppy before the Dynarec). There is a strange unstability at start, were sometime it just segfault, but I had this also without the dynarec. The Dynarec is also missing some opcode for this game, and the graphics are heavy for the Pandora, but it is already looking good:

Memoranda: The game is bit long to load (lots of FullHD texture), but the intro looks fine now. Still a bit slow, but use SSE..
Undertale: Loads and run, but a bit slow because of the lack of SSE in the Dynarec.

Maldita Castilla: Runs fine. I think added SSE in the Dynarec will get some of the advanced level more playable, but already fully playable on the Pandora.

Gaurodan: Fully playable on the Pandora now.
 
@ptitSeb, Seeing both World of Goo and Neverwinter Night both run better on the Pandora then it did on my OMAP5 devboard with Exagear gets me excited for what box86 can do for the Pyra.

Edit: Well I didn't have 3D acceleration working through Exagear back during my experiments a few years ago on my Devboard.
 
Last edited:
@ptitSeb, Seeing both World of Goo and Neverwinter Night both run better on the Pandora then it did on my OMAP5 devboard with Exagear gets me excited for what box86 can do for the Pyra.
I need 3D driver to do some more testing on the Pyra. There are a few non opengl stuff, but really not that much.

Edit: Well I didn't have 3D acceleration working through Exagear back during my experiments a few years ago on my Devboard.
Yep, that would be a limiting factor.
 
I need 3D driver to do some more testing on the Pyra. There are a few non opengl stuff, but really not that much.
Ironically at one point I did have a working 3D driver, but exagear couldn't utilize it, think lunixbochs had some hacky solution, but I never could get it working.
 
Back
Top