Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Build MESS/MAME #131

Closed
ziz opened this Issue · 153 comments

3 participants

@ziz

dynamic_cast can get into an infinite loop (encountered when compiling the MAME / MESS source). Per discussion, "the current implementation is missing some stuff like multiple inheritance etc., so maybe more basic stuff needs to be done first."

The dynamic_cast call arguments can be found in llvm's tools/clang/lib/CodeGen/CGExprCXX.cpp around line 1535 (using SVN rev 139974 of clang 3.0).

(Apologies for the pretty minimal issue content; I don't have anything resembling a minimal reproduction case to offer yet.)

@kripken
Owner

If you can provide the relevant C++ source code that is compiled into the problem, that would also be very helpful. Without that, it's hard to know what to focus on here.

@ziz
ziz commented

My attempt at a minimal case was not successful in reproducing the bug: http://batcave.textfiles.com/ziz/staging/casttest.zip

As requested, here's the .js and .bc files:

http://batcave.textfiles.com/ziz/staging/messtiny-10.js.gz
http://batcave.textfiles.com/ziz/staging/messtiny-10.bc.gz

and the source code we're compiling is found in https://github.com/ziz/jsmess/tree/no_cothreads

So far as I can tell, the infinite loop happens during execution of a dynamic_cast call which runs as part of src/emu/clifront.c cli_frontend::listmedia, line 698.

Compiling fully from source requires a second, clean copy of the MESS source to build the external tools the build process depends on:

cd mess-orig; cp -rp src/osd/osdmini src/mess/osd; make TARGET=mess SUBTARGET=tiny

then build the MESS project:

make clean; find . -name \*.a.bc -o -name \*.o -delete; make clean; make TARGET=mess SUBTARGET=tiny
# Previous command fails because it can't run the external tools, copy them in
cp ../mess-orig/obj/osdmini/messtiny64/build/* obj/osdmini/messtiny/build/
# and finish the build
make TARGET=mess SUBTARGET=tiny

Then link with emscripten (since the build process tries to link .a instead of .a.bc, replace all .a with .a.bc in the link command):

/home/ziz/Dev/llvm-3.0-release/Release/bin/llvm-ld -disable-opt obj/osdmini/messtiny/version.o obj/osdmini/messtiny/drivlist.o obj/osdmini/messtiny/emu/drivers/emudummy.o obj/osdmini/messtiny/mess/drivers/coleco.o obj/osdmini/messtiny/mess/machine/coleco.o obj/osdmini/messtiny/libosd.a.bc obj/osdmini/messtiny/libcpu.a.bc obj/osdmini/messtiny/libemu.a.bc obj/osdmini/messtiny/libdasm.a.bc obj/osdmini/messtiny/libsound.a.bc obj/osdmini/messtiny/libutil.a.bc obj/osdmini/messtiny/libexpat.a.bc obj/osdmini/messtiny/libsoftfloat.a.bc obj/osdmini/messtiny/libformats.a.bc obj/osdmini/messtiny/libz.a.bc obj/osdmini/messtiny/libocore.a.bc -o=messtiny

and then emscripten:

../emscripten/emscripten.py messtiny.bc -o messtiny.js

Run with the argument '-listmedia'.

@kripken
Owner

I'll look at this very soon, I just need to finish a few more compiler optimizations to speed up building large files (which will help with compiling and debugging code like this).

@kripken
Owner

The compressed js file linked here doesn't seem to extract to a js file properly. I built my own though.

Just trying to run it, I ran into a few problems:

  1. spidermonkey and node fail on OOM.
  2. v8 shell gets farther, but fails on lack of bsearch. bsearch was implemented in pull request 114, however the submitter there was not willing to license the code in a way that we can use. So I guess we would need to reimplement that function and the other ones there from scratch.

We should really try to reduce the size of the compiled code - hopefully we don't need everything currently built. The compiled JS is 50MB, which is too much for node and spidermonkey. d8 can run it, but d8 has other limitations like poor support for typed arrays which will greatly limit our ability to test (we will likely need typed arrays for speed).

But the real blocker now is to re-implement the necessary functions mentioned before in a way that can actually be used by us.

@ziz

I have updated the jsmess makefile to use emcc and friends, and compiled with the latest emscripten. The JS is only 30M now, and compiles in less than half the time it used to - grats on the improvements!

There appears to be a minor bug in parseTools.js, preventing out-of-the-box compilation here: the 64-bit basic integer ops switch (around line 1660) is missing srem (compared to the 32-bit basic integer ops).

I may have recompiled spidermonkey with an increased functions limit to get around the OOM before. Pending a real fix, this is certainly an option.

Here's a new .bc and .js: http://batcave.textfiles.com/ziz/staging/messtiny-11.tgz

@kripken
Owner

How did you work around the lack of srem?

The problem is that 64-bit math isn't really possible in JS. We can add srem, but it might fail if values too big to fit in a double are used. Perhaps there is a way to make jsmess use 32-bit values over 64-bit ints?

@ziz

I applied the wrong-but-obvious solution: I just added srem to that case statement, which caused it to compile.

There may be an obvious solution that I'm missing to force 32-bit compilation for jsmess on OS X or other 64-bit platforms (and, so far as I can tell, this won't cause any problems if we do manage to force 32-bit compilation).

@kripken
Owner

I'm having trouble building this .ll file, not sure why. What version of LLVM did you use to build it?

@ziz
@kripken
Owner

3.0 should be fine.

Another question, I get warnings about different targets (os x vs linux). Can you perhaps run the automatic test suite, to see if there are any problems on os x? (Emscripten has not been heavily tested there I am afraid.) The command to run them is python tests/runner.py, it should take several hours.

@ziz

Sure, I'll run the test suite. Is this the first time the different targets problem has shown up? I don't recall it being an issue before.

@kripken
Owner

We do have people using OS X, and someone said things were working on Windows. But only Linux gets full test coverage all the time (because I run Linux, basically, no special reason).

Specifically for here, I worry that clang will implement dynamic cast differently on different platforms, and that that might be what is tripping us up here. A problem like that might have gone unnoticed even though we have some people using OS X for some projects.

@ziz
ziz commented

Test output: https://gist.github.com/87ad7200ca6f708e6a73

Failures specifically related to closure (Invalid or corrupt jarfile /usr/local/bin/closure) are because I had the config file pointed to a closure compiler wrapper .sh rather than the closure .jar. I can rerun those specific tests if needed.

@kripken
Owner

A lot of those errors will, I suspect, be fixed by pull 154. And I am hoping some will be fixed by a headers correctness fix we landed yesterday. But if not, then those errors look very dangerous, and could possibly explain the jsmess infinite loop. Let's focus on the shortest one, pystruct. Can you please run

EMCC_DEBUG=1 python tests/runner.py test_pystruct

and gist the results? There will be an .ll and .js file in /tmp/emscripten_tmp (assuming /tmp is what TEMP_DIR is set to in ~/.emscipten).

edit: and please make sure you pull the latest code, since the headers fix was just yesterday

@ziz
ziz commented
@kripken
Owner

Thanks!

Ok, it looks like we need to be more assertive in telling clang to generate platform-independent code. Long-term we will want to have a formal "emscripten" llvm target, but until then, let's try to use 32-bit linux as the uniform target. I pushed this to the incoming branch as 4cab9f5. Can you test it and see if it fixes pystruct?

@ziz
ziz commented
@kripken
Owner

Great! :)

There's a chance it will fix the other tests too (although we might still need the bitcode fix in pull #154). Can you run the rest as well?

@ziz
ziz commented
@kripken
Owner

That pull has just been merged to incoming, so hopefully all tests will now pass if you pull the latest incoming. (Note that it isn't in master yet, waiting on automatic tests.)

@kripken
Owner

test_emcc is in "other", so to run it separately you need python tests/runner.py other.test_emcc. But if you run the whole suite, it should be run.

@kripken
Owner

freetype, poppler, openjpeg and bullet should hopefully be fixed with that pull. The others do not look like they will be fixed by it.

Can you gist the output from EMCC_DEBUG=1 python tests/runner.py test_zlib?

@ziz
ziz commented
@kripken
Owner

On my machine it takes more than twice that, heh, I usually leave it to run overnight ;)

Based on the stack trace, on that part of the emcc test it is trying to run lli (the LLVM interpreter) on a bitcode file. Can you put up the generated bitcode files in that directory? (suffix .o and .bc)

@ziz
ziz commented
@ziz
ziz commented

http://batcave.textfiles.com/ziz/staging/test_emcc-bitcode.tgz is the generated bitcode from EM_SAVE_DIR=1 python tests/runner.py other.test_emcc

@kripken
Owner

The generated bitcode files work fine here. Do they work for you when you run them manually? lli hello_world.o

I am baffled by the zlib failure. The output is quite different, despite our using the same LLVM and Clang (3.0), and the same target.

@ziz
ziz commented
@kripken
Owner

Do both the normal and the "cleaned" .o files crash in that way? (the cleaned version removes debug info, which used to crash lli in the past)

Let's try to use exactly the same LLVM version, because I think we'll need to file an LLVM bug or post to their mailing list soon, not sure what else to do. I'm rebuilding LLVM 3.0 release from source now.

@ziz
ziz commented
@kripken
Owner

I think we should both use LLVM 3.0 release, from http://llvm.org/releases/3.0/llvm-3.0.tar.gz , since it looks like we will need to file a bug in LLVM if it still crashes for you.

@ziz
ziz commented

Okay. I have been building LLVM with configure --enable-optimized --disable-assertions - should we continue with that or change the options?

@kripken
Owner

I just build it with cmake .., no flags. I don't think it would make a difference, but probably best to use exactly the same build command.

Btw, I just pushed another headers fix to incoming - hopefully the last. It might help with some of the errors, but I am not sure.

@ziz
ziz commented
@ziz
ziz commented

(whoops, sorry, forgot to upload them) http://batcave.textfiles.com/ziz/staging/test_emcc.tgz

@kripken
Owner

Ok, it looks like there is a LLVM problem here on OS X. I will try to find time soon to boot into OS X and debug this in depth, because I don't have any other obvious ideas right now.

Meanwhile, to keep jsmess moving forward, is there any chance you can run Linux, maybe in a VM, as a workaround for this?

@ziz
ziz commented

Yep, spinning it up on a linux box (2.6.35-22-generic #35-Ubuntu SMP Sat Oct 16 20:45:36 UTC 2010 x86_64 GNU/Linux) now. Hopefully the tests will pass without issue there!

@kripken
Owner

It looks like the version of spidermonkey used there is too old, causing most of those errors. Best to either install the latest, or remove it from ~/.emscripten and just use node.

@ziz

Ok, removing spidermonkey in favor of node: http://batcave.textfiles.com/ziz/staging/testoutput-20120114.txt (still a couple of failures, it looks like)

@kripken
Owner

I don't understand those linking errors. That stuff should work with LLVM 3.0.

Can you run EM_SAVE_DIR=1 python tests/runner.py test_bullet, that will save the files in /tmp/emscripten_tmp. You can then try to manually run llvm-link and see if it works when run that way (might add a printout in tools/shared in link(), right before it fails, to print out the params it passes to llvm link).

@kripken
Owner

I want to build jsmess myself to try to push things forward. Are there instructions somewhere? (I don't see any in https://github.com/ziz/jsmess )

@ziz

Compilation instructions, such as they are, are in the wiki (https://github.com/ziz/jsmess/wiki).

@kripken
Owner

Should I use the no_coroutines branch?

How do I get the "clean" build? Can I use the jsmess code, with some other flag so it builds natively? Or do I need to get the MESS code from somewhere?

@ziz

no_coroutines is the right branch.

You can use the master branch (unmodified mess code) to make the clean build. Copy the checkout elsewhere, checkout master, and then running make TARGET=mess SUBTARGET=tiny should build the native version. (If you're on a 32-bit platform you'll need to adjust the path you copy the native tools from, of couse.)

The makefile process for jsmess should be modified to allow native building at some point, of course, but it's still a moving target, so...

@kripken
Owner

Thanks, I'll try to build this later today.

@kripken
Owner

I built natively, built for JS until the error, and then tried to copy the native object files. However, there are no files in ../jsmess-native/obj/osdmini/messtiny/build/ (the directory exists, but it is empty). Looks like there are some relevant files in the native build in /sdl/ instead of `/osdmini/'. I'm confused why the native build seems to use sdl and the js build osdmini (assuming that's what's happening here)?

@ziz

Those native tools in the sdl directory should work just as well. Looks like I may have forced building with osdmini rather than 'whatever the native build wants to use' when I originally wrote up those instructions.

(osdmini is a minimal, mostly-nonfunctional output driver, I believe, to reduce complexity while we're trying to get jsmess working at all)

@kripken
Owner

That gets me a bit further, but now it is looking for emu/layout/pinball.lh, which doesn't exist in the native build anywhere.

Maybe we should try to build the whole thing, it might be more feasible with the recent optimizations in emscripten? Or perhaps MAME instead of MESS? It's important to be building the same thing in native and JS apparently (and it's good for testing too, later on).

@ziz
@kripken
Owner

I'll try some more then.

What is the difference between MESS and MAME, btw? Isn't MAME smaller?

@ziz

MESS and MAME use the same main engine, and have a different set of emulation targets. MAME is smaller, but we're only (currently) compiling one emulation target in MESS (the coleco hardware), so the size is mostly immaterial.

@kripken kripken closed this
@kripken kripken reopened this
@kripken
Owner

Whoops, hit the wrong button, ignore that.

@DopefishJustin

The MESS source tree is larger than MAME's, but only because it's based on MAME and includes a copy-paste of the full MAME tree for convenience. In terms of the amount of code actually compiled MESS is significantly smaller. But as ziz said it makes no difference when compiling only a single emulation target.

@kripken
Owner

What is the mechanism for specifying a single emulation target? Modifying the makefile? Or a parameter when running make?

@DopefishJustin

The SUBTARGET=tiny parameter to make points it at tiny.mak which needs to be hand-edited to include only the files necessary for the desired target system.

@kripken
Owner

Thanks for the help everyone.

Ok, I set my goal to build mess in native and js in parallel, building the exact same thing. So I checked out the no-cothreads branch, then returned AR, CC etc. to use the native tools. I then had to also remove -Werror because that made it fail. It then built a native messtiny executable.

However, that executable hangs on startup (just running ./messtiny), so something seems to be wrong. This didn't happen in the main branch. Perhaps one of the commits in no-cothreads is problematic?

I suggest that the next step is to get it to build natively in the no-cothreads branch. That would allow us to build native and js in parallel, which makes it much easier to figure out problems in js.

@DopefishJustin

That may be expected if it is built with OSD=osdmini since mess with no parameters will try to display a graphical menu, and if the graphics output is stubbed that won't do anything. Does ./messtiny -help work?

@ziz

Here's the changes I made to the makefile to get make TARGET=mess SUBTARGET=tiny to compile natively on a 64-bit linux box: ziz/jsmess@c0ac13b

I think they're all pretty minor as far as these things go.

This in fact works as I expect; all of the following commands work.

  553  ./messtiny64 -help
  554  ./messtiny64 -listmedia
  555  ./messtiny64 -showusage
  556  ./messtiny64 -listslots
  557  ./messtiny64 -listdevices

and ./messtiny64 by itself appears to hang, for the reason described above.

@kripken
Owner

Ok, cool.

I built for js, to try to compare. I built the no-cothreads branch, just changing the paths to emscripten on my system. When native executables were missing, this fixed them:

cp obj/osdmini/messtiny/emu/*.fh ../jsmess/obj/osdmini/messtiny/emu/
cp obj/osdmini/messtiny/emu/layout/*.lh ../jsmess/obj/osdmini/messtiny/emu/layout/
cp obj/osdmini/messtiny/emu/layout/*.lay ../jsmess/obj/osdmini/messtiny/emu/layout/

However, I seem to be hitting an LLVM problem - it aborts on the final link of bitcode files, with

Broken module found, compilation aborted!

I narrowed this down from the original big link command to the linking of just two files, which is enough to trigger the error,

llvm-link obj/osdmini/messtiny/mess/drivers/coleco.o obj/osdmini/messtiny/libemu.a -o=messtiny

Before I file a bug with LLVM, can someone please confirm that they see it too?

Note that to build, you should use the incoming branch of emscripten, I had to push a fix for emar just now. (That branch will merge to master in a few hours once automatic tests pass.)

@ziz

I'm not sure if this is relevant in your case, but it looks like I might need to change .a to .a.bc in the linking command because the .a is an llvm wrapper of some sort. I haven't build the js recently, though - I'll have to try that later.

@kripken
Owner

That wrapper is what I fixed in incoming just now. It won't create the wrapper, the .a file will be the proper bitcode.

@kripken
Owner

Emscripten incoming just merged to master, so if anyone wants to try to reproduce my llvm error, you can use normal emscripten (updated to latest).

@ziz
ziz commented

With latest incoming, I got all the way through the linking step:

Linking messtiny...
/home/ziz/Dev/emscripten/emld -Wl,--warn-common -s  obj/osdmini/messtiny/version.o obj/osdmini/messtiny/drivlist.o obj/osdmini/messtiny/emu/drivers/emudummy.o obj/osdmini/messtiny/mess/drivers/coleco.o obj/osdmini/messtiny/mess/machine/coleco.o obj/osdmini/messtiny/libosd.a obj/osdmini/messtiny/libcpu.a obj/osdmini/messtiny/libemu.a obj/osdmini/messtiny/libdasm.a obj/osdmini/messtiny/libsound.a obj/osdmini/messtiny/libutil.a obj/osdmini/messtiny/libexpat.a obj/osdmini/messtiny/libsoftfloat.a obj/osdmini/messtiny/libformats.a obj/osdmini/messtiny/libz.a obj/osdmini/messtiny/libocore.a  -o messtiny

succeeded without issue.

However, when I then run emscripten, I get:

$ ../emscripten/emscripten.py -o messtiny.js messtiny.bc

node.js:201
        throw e; // process.nextTick error, or 'error' event on first tick
              ^
TypeError: Cannot read property '1' of null
    at Object._lineSplitter [as processItem] (eval at globalEval (/home/ziz/Dev/emscripten/src/compiler.js:79:8))
    at Object.process (eval at globalEval (/home/ziz/Dev/emscripten/src/compiler.js:79:8))
    at Object.solve (eval at globalEval (/home/ziz/Dev/emscripten/src/compiler.js:79:8))
    at intertyper (eval at globalEval (/home/ziz/Dev/emscripten/src/compiler.js:79:8))
    at Object.<anonymous> (/home/ziz/Dev/emscripten/src/compiler.js:186:18)
    at Module._compile (module.js:432:26)
    at Object..js (module.js:450:10)
    at Module.load (module.js:351:31)
    at Function._load (module.js:310:12)
    at Array.0 (module.js:470:10)

Produced .bc is at http://batcave.textfiles.com/ziz/staging/messtiny.bc-20120201.gz

@DopefishJustin

Finally got a proper environment for this set up and I get the same TypeError as ziz above.

To compile I did not need to do the

cp obj/osdmini/messtiny/emu/layout/*.lay ../jsmess/obj/osdmini/messtiny/emu/layout/

step, however I did need to do

cp obj/osdmini/messtiny64/drivlist.c ../jsmess/obj/osdmini/messtiny/
@kripken
Owner

Hmm, so no one is seeing the LLVM error I run into? Odd. I won't file a bug then.

You should use emcc to compile, not emscripten.py. I'll add a warning to emscripten.py now.

With emcc, that bitcode file compiles over here, and it hangs on run - which is the expected problem I think?

@DopefishJustin

Ah with emcc I get a functional messtiny.js. node messtiny.js hangs (expected) but node messtiny.js -help and node messtiny.js -listfull work. node messtiny.js -listmedia hangs after printing the headings which I think is the dynamic_cast issue that needed looking into.

@ziz
ziz commented

emcc works to compile here as well, and produces a messtiny.js which works as expected (as DFJustin describes above).

@kripken
Owner

Running emcc with -s LABEL_DEBUG=1, the generated code prints out each basic block of code as it enters it.

In node, it hangs on __ZN12memory_entry8allocateEjPvPKci:$for_cond. This looks like invalid behavior - only trivial operations happen in that very short basic block, and it immediately jumps to one of two other basic blocks, both of which print out something on entry, which isn't printed. This looks like a bug, if others can reproduce it we should file it.

In spidermonkey, we get past that hang, quite a lot further actually (confirming that the node hang is likely a bug). We do however eventually hang on __ZL34xml_get_attribute_float_with_substR15running_machineR14_xml_data_nodePKcf:$lor_lhs_false. This basic block contains a call to sscanf, so it is possible that our libc implementation of sscanf has a bug in it. Next step is to investigate the inputs to that function and debug why it hangs.

@kripken
Owner

The latter hang is confirmed as a bug with sscanf on negative floats, will have a fix soon.

@kripken
Owner

Fixed on emscripten's incoming branch. With that in place, I don't see an obvious hang near startup. It does run for a long time though (this is a debug build with LABEL_DEBUG which makes it even slower) so I can't be sure.

@DopefishJustin

Running node messtiny.js -listmedia with the sscanf fix and -s LABEL_DEBUG=1, it seems to hang at __ZN8device_t9interfaceI21device_slot_interfaceEEbRPT_:$5

@ziz
ziz commented

Confirmed (by way of a judicious couple of print statements) that node messtiny.js -listmedia is hung looping inside dynamic_cast (the second time it's called, not the first, apparently:

  function ___dynamic_cast(ptr, knownTI, attemptedTI, idunno) {
      var ptrTV = HEAP32[((ptr)>>2)];
      var count = HEAP32[((ptrTV)>>2)];
      ptrTV -= 4;
      var TI = HEAP32[((ptrTV)>>2)];
      do {
        print("" + ptr + " " + knownTI + " " + attemptedTI + " " + idunno + " " + ptrTV + " " + count + " " + TI + "\n")
        if (TI == attemptedTI) {print("gone 1"); return 1;}
        // Go to parent class
        var type_infoAddr = HEAP32[((TI)>>2)] - 8;
        var type_info = HEAP32[((type_infoAddr)>>2)];
        if (type_info == 1) {print("gone 0"); return 0;} // no parent class
        var TIAddr = TI + 8;
        var TI = HEAP32[((TIAddr)>>2)];
      } while (1);

      return 0;
    }

produces

$ ../node/bin/node messtiny.js -listmedia | head -40
 SYSTEM      MEDIA NAME (brief)   IMAGE FILE EXTENSIONS SUPPORTED     
----------  --------------------  ------------------------------------
5999976 5286012 5290132 -1 5247984 1722 5248108

5999976 5286012 5290132 -1 5247984 1722 5434080

5999976 5286012 5290132 -1 5247984 1722 5286012

5999976 5286012 5290132 -1 5247984 1722 5248584

gone 0
6000464 5286012 5290132 -1 5255296 2478 5255808

6000464 5286012 5290132 -1 5255296 2478 5280340

6000464 5286012 5290132 -1 5255296 2478 5280264

6000464 5286012 5290132 -1 5255296 2478 1

6000464 5286012 5290132 -1 5255296 2478 5269640

6000464 5286012 5290132 -1 5255296 2478 0

6000464 5286012 5290132 -1 5255296 2478 5269640

6000464 5286012 5290132 -1 5255296 2478 0

(forever)
@kripken
Owner

It would be faster to debug this if the generated code ran faster. So I tried to optimize it a little, the eliminator optimization step hangs on __Z20construct_core_typesR11simple_listI16input_type_entryE however. This is a 75,000 line function(!) whose code seems to repeat many many times. Perhaps tons of expanded macros? Or has something gone wrong with the compilation?

@ziz

Lots and lots of expanded macros - see src/emu/inpttype.h line 52-ish. Starts with expanding INPUT_PORT_DIGITAL_TYPE a bunch, which doesn't look (terribly) complicated, but seems to be generating calls that end up pretty antagonistic to emscripten for some reason.

@kripken
Owner

Those calls are antagonistic to everything I think ;)

So, today I worked on using the libcxxabi code to handle dynamic cast, so we can be sure all cases are handled right. Was harder to do than I thought, but I think I have it working on the incoming branch in emscripten. On that branch, building gives a js file that fails in node due to "too many variables" (!). In SpiderMonkey it starts to run, and does not hang on dynamic cast, so that part seems fixed. What I get now is

$js -m -n messtiny.js -listmedia
 SYSTEM      MEDIA NAME (brief)   IMAGE FILE EXTENSIONS SUPPORTED     
----------  --------------------  ------------------------------------
Device z80 specifies a 0 context size!

That is when built with -s EXCEPTION_DEBUG=0, otherwise there is a lot of output about the exception being thrown and then caught. Looks like that error message is a thrown exception, we need to look in the MESS code to find out what is going wrong there. Perhaps it is trying to read a file for that information? (If so we need to set up the emulated filesystem for it.)

@DopefishJustin

That error comes from src/emu/devcpu.c at the end of legacy_cpu_device::legacy_cpu_device(). The call to legacy_cpu_device::get_legacy_int() returns 0 and it bails. I notice that function uses const_cast - might const_cast have a similar issue to dynamic_cast, and benefit from replacement with libcxxabi?

@kripken
Owner

I don't have the compiled code on this machine so I can't check, but I am quite sure that const_cast is purely compile-time. It just removes a const attribute from a pointer (making a const char* into a char* for example). So I think the problem is elsewhere.

@DopefishJustin

Ah right you are. So I think what's supposed to happen here is it should reach src/emu/cpu/z80/z80.c line 3852:

case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(z80_state); break;

z80_state being a struct with a bunch of stuff in it defined at the top of the file. That info->i value is then what should be returned where we're apparently getting 0. Shouldn't be too hard to throw in some printf's and see where things are going haywire, I need to get my Emscripten setup working again though.

@DopefishJustin

So I threw in some printf's and legacy_cpu_device::get_legacy_int() gets a correct-looking value from the z80's CPU_GET_INFO function, so all of the const_cast and union stuff seems to work fine. That value should then be returned and assigned to tokenbytes, but for some reason tokenbytes is 0 after the assignment. So somehow a basic return from function and variable assignment are not working right.

I tried to make a reduced testcase doing all the same things but it works fine, tokenbytes gets the correct value. So there is some kind of screwy bug in emscripten I think but I am not sure how to narrow it down.

Attempted testcase: https://gist.github.com/1918971

@kripken
Owner

We will need to debug the .js I guess. If you can, find the return statement in the generated .js and see where it is received. Returns are normal JS returns, so they should be easy to follow. Then see what goes on with the variable assignment.

Or, tell me which are the relevant functions in the .ll and .js and which is the relevant return, and which is the relevant variable being set to that doesn't work.

@DopefishJustin

OK, the problem is in the generated JavaScript in the following function:

function __ZN17legacy_cpu_deviceC2ERK14machine_configPFP8device_tS2_PKcS4_jES6_S4_jPFvPS_jP7cpuinfoE($this, $mconfig, $type, $tag, $owner, $clock, $get_info)

Look for the last call to get_legacy_int - I have added some print() calls:

    case 40: // $232
      var $233=$16;
      var $234=(($233+356)|0);
      var $235=$234;
      var $236=(($235+5524)|0);
      var $237=$236;
      for (var $$dest = $237, $$stop = $$dest + 12; $$dest < $$stop; $$dest++) {
        HEAP8[$$dest] = 0
      };
      print("about to call get_legacy_int");
      var $238=(function() { try { __THREW__ = false; return __ZNK17legacy_cpu_device14get_legacy_intEj($16, 16384) } catch(e) { if (typeof e != "number") throw e; if (ABORT) throw e; __THREW__ = true; print("Exception: " + e + ", currently at: " + (new Error().stack)); return null } })(); if (!__THREW__) { __label__ = 41; break; } else { __label__ = 27; break; };
      print("does this ever execute?");
      var $238$0=$238[0];
      var $238$1=$238[1];
    case 41: // $239
      print("we have moved on to the next case");
      var $240$0=$238$0;
      var $240=$240$0;
      $tokenbytes=$240;
      var $241=$tokenbytes;
      var $242=(($241)|0)==0;
      if ($242) { __label__ = 42; break; } else { __label__ = 45; break; }

At runtime this shows the following:

 SYSTEM      MEDIA NAME (brief)   IMAGE FILE EXTENSIONS SUPPORTED     
----------  --------------------  ------------------------------------
about to call get_legacy_int
we have moved on to the next case
Compiled code throwing an exception, 6007712,5248320,16, at ___cxa_throw(6007712,5248320,16)@messtiny.js:868761

The "does this ever execute" line is never reached because the function call code above it always does a break;, so the statements that populate $238$0 and $238$1 are never reached and thus nothing gets into $tokenbytes.

@kripken
Owner

Thanks for the files, and the investigation from the previous comment. Yes, exactly as you said code is not being executed that needs to be. Specifically it looks like we don't legalize phis that are reached from invokes properly. I'll work on this now.

@kripken
Owner

Likely fix is in incoming branch, running automatic tests on it now.

@kripken
Owner

Tests passed, merged to master.

@DopefishJustin

Thanks for the prompt fix, with latest master I get this error running js messtiny.js -listmedia though:

messtiny.js:2316: ReferenceError: $$emscripten$temp$0 is not defined
@kripken
Owner

Can you link to the generated code?

@DopefishJustin

http://interbutt.com/temp/messtiny2.zip

I won't have time to look at it in detail until tonight.

@kripken
Owner

Thanks, I see the problem. Will have a fix shortly.

@kripken
Owner

Fix is in incoming branch of Emscripten.

@kripken
Owner

Sorry for these bugs btw, they are all to do with exception handling and 64-bit values. I guess the combination of those two is not represented in the emscripten test suite well enough.

@DopefishJustin

-listmedia looks good now, will have to try and put MESS through more of its paces :)

@kripken
Owner

Great! :)

@DopefishJustin

So I have been trying to get MESS to load files, without success. I'm now testing with romcmp which is a small file comparison utility packaged with MESS using the same core file I/O routines - to build it, add the parameter tools to the make command. I have put the .bc and the .js produced by emscripten master at http://interbutt.com/temp/romcmp.zip

I added the following after {{PRE_RUN_ADDITIONS}} in romcmp.js:

FS.createPath('/', 'roms', true, false);
FS.createLazyFile('/roms', 'coleco.zip', 'roms/coleco.zip', true, false);
FS.createLazyFile('/roms', 'colecoa.zip', 'roms/colecoa.zip', true, false);

coleco.zip and colecoa.zip are in a roms/ subfolder of the jsmess directory where I am running the .js from.

Running js romcmp.js /roms/coleco.zip /roms/colecoa.zip gives the following:

Warning: Enlarging memory arrays, this is not fast! 14300728,10485760
Error, cannot open zip file '/roms/coleco.zip' !

Debugging the code, the error is that the file does not exist.

Running the same command with node trips an assertion which may be of interest:

Warning: Enlarging memory arrays, this is not fast! 14300728,10485760
Assertion failed: Character code 65533 (�)  at offset 11 not in 0x00-0xFF.:
Error
    at abort (/home/jkerk/jsmess/romcmp.js:359:25)
    at assert (/home/jkerk/jsmess/romcmp.js:366:5)
    at intArrayFromString (/home/jkerk/jsmess/romcmp.js:739:9)
    at Object.forceLoadFile (/home/jkerk/jsmess/romcmp.js:20879:28)
    at _open (/home/jkerk/jsmess/romcmp.js:21639:19)
    at _fopen (/home/jkerk/jsmess/romcmp.js:21730:17)
    at _osd_open (/home/jkerk/jsmess/romcmp.js:13272:15)
    at __Z13zip_file_openPKcPP9_zip_file (/home/jkerk/jsmess/romcmp.js:4114:15)
    at __ZL10load_filesiPiPKc (/home/jkerk/jsmess/romcmp.js:1913:16)
    at _main (/home/jkerk/jsmess/romcmp.js:893:15)
Error, cannot open zip file '/roms/coleco.zip' !
@DopefishJustin

It's entirely possible that there is user error at work here too :)

@DopefishJustin

OK it actually does work in Firefox as an html file so it is just something about the command line I guess.

@kripken
Owner

There are some odd differences in how the node/d8/js shells handle files, it is definitely annoying. See the --embed-file option in emcc, for small files it helps work around this (by embedding the file in the .js).

Web browsers however should work fine, file input is standardized there. If you find a problem in a browser please let me know.

@DopefishJustin

--embed-file works well, I am able to embed coleco.zip and then start the emulation using js messtiny.js coleco -str 1 -rompath . -verbose. Unfortunately the emulation hangs while starting the Z80 device, in device_execute_interface::interface_clock_changed() in src/emu/diexec.c. This function does some int64 math which I know is not completely supported by emscripten yet.

Here is a reduced testcase for the function in question:
https://gist.github.com/1976973

With gcc or clang, it outputs the following:

m_divshift is 1
m_divshift is 2
m_divshift is 3
m_divshift is 4
m_divshift is 5
m_divshift is 6
m_divshift is 7
m_divshift is 8
m_divisor is 1091269979

1091269979 is the correct answer reached by native MESS when initializing the Z80. When compiled with emscripten, it loops infinitely, m_divshift increments all the way up to 255 and then wraps back to 0 again.

@kripken
Owner

Thanks, that's a bug in i64 comparisons. I think I fixed it on incoming now but needs more testing.

@DopefishJustin

So now we hang in validate_inlines() in src/emu/validate.c, which does a whole bunch of sanity tests on math operations with different data types. (yay...)

Here is a reduced testcase of the failing code: https://gist.github.com/1983766

In gcc or clang the following output is produced right away:

testu64a is 7373125414476351500

Emscripten-produced .js hangs indefinitely.

Interestingly, with emscripten revision ad9ce81 (just before the i64 fix) it does not hang, but outputs a different number:

testu64a is 14746250828952703000

That would explain why we did not hit this before, since this is earlier in the startup process than the previous hang.

@kripken
Owner

Thanks for yet another clear testcase! This should also be fixed on incoming. Note though that as before, I haven't fully tested it yet (I just wanted to push it out so this doesn't block you).

@DopefishJustin

Excellent! It does indeed appear to be fixed.

So now I'd like to try working with MESS compiled with OSD=sdl instead of OSD=mini, however I get the following error when I try to emscripten it:

[jkerk@myhost jsmess]$ ~/emscripten/emcc messtiny.bc -o messtiny_sdl.js
emcc: warning: using libcxx turns on CORRECT_* options
emcc: warning: using libcxxabi, this may need CORRECT_* options

node.js:201
        throw e; // process.nextTick error, or 'error' event on first tick
              ^
Invalid token, cannot triage: // {
//   "tokens": [
//     {
//       "text": "fence"
//     },
//     {
//       "text": "seq_cst"
//     }
//   ],
//   "indent": 2,
//   "lineNum": 100063,
//   "__uid__": 852
// }

.bc is at http://interbutt.com/temp/messtiny_sdl.zip

@kripken
Owner

That's a synchronization instruction that emscripten can ignore. Fixed in incoming branch.

Now if chokes on some inline assembly that needs to be removed, in _Z15sdl_read_socketP9_osd_filePvyjPj.

@DopefishJustin

I've yanked out the asm and TTF library stuff and I get a .js that seems to work, but needs stubs for the following functions:

_SDL_Linked_Version
_SDL_GetWMInfo
_SDL_VideoDriverName
_SDL_ThreadID
_SDL_NumJoysticks
_SDL_AudioDriverName
_SDL_EnableUNICODE

_pthread_cond_init
_pthread_cond_signal
_pthread_cond_destroy

They don't have to do anything, function foo() {} suffices. (Why does emscripten not generate that instead of var foo;?)

I also need to comment out the "Cannot return obtained SDL audio params" assert in _SDL_OpenAudio (I guess that may be relevant later when hooking up audio).

And when running with js from the command line (haven't tried anything else yet) I get some errors about the emscripten-supplied Javascript functions:

ReferenceError: addEventListener is not defined

in:

function _SDL_Init(what) {
      SDL.startTime = Date.now();
      ['keydown', 'keyup', 'keypress'].forEach(function(event) {
        addEventListener(event, SDL.receiveEvent, true);
      });

TypeError: Module.canvas is undefined
in:

  function _SDL_SetVideoMode(width, height, depth, flags) {
      Module['canvas'].width = width;
      Module['canvas'].height = height;
      return SDL.screen = SDL.makeSurface(width, height, flags);
    }

and
TypeError: Module.print is not a function
in:

      },createContext:function (useWebGL) {
...
        } catch (e) {
          Module.print('(canvas not available)');
          return null;
        }
@kripken
Owner

Emscripten doesn't generate empty stubs because then you would get silent failures that are very hard to debug. Instead, you get clear failures about what is missing.

In those examples, I'm not sure it's ok if they do nothing. They might need to return 0 or -1 or something like that. An empty stub returns undefined, if they do math on that, it can go very wrong.

The SDL errors are basically that our SDL implementation assumes its running in a browser, so event listening works, and there is a canvas as set up in src/shell.html. You get that automatically if you run emcc and tell it to generate html output.

@DopefishJustin

At least for me, having an auto-stub with print('foo unimplemented!'); or the like inside would be a lot more convenient for development, while still addressing the silent failure issue. I guess it depends somewhat on the project since in our case it's all superfluous stuff, whereas on another project it might go completely off the rails if key functions don't do anything. May be worth having an option for.

I did figure that I need a browser for the SDL stuff, it's a bit annoying because there are tests I can do from the command line whereas browsers have trouble with the size of the code, but I guess it makes sense. More robust checks would be nice :)

@DopefishJustin

So something has changed in emscripten just recently such that video no longer appears on the canvas (stays white forever) even if the code is for sure running. Trying to track down what exactly but there have been a lot of SDL changes....

@kripken
Owner

My first guess is we now support rgba and not just rgb. To test this, find the 4 short functions with CSSRGB in their name, and replace the rgba( to rgb( and remove the last parameter generated (the browser will break if rgb gets 4 params). (You don't need to compile to test this.) Maybe the alpha is reversed, that could explain no rendering.

If it isn't that, there is SDL.debugSurface which can be used on SDL surfaces to see their source and contents. Also useful without compiling.

Otherwise, bisection seems the best route (I mean, binary search to find the changeset that introduces the bug).

@DopefishJustin

I did guess the rgba thing but as far as I can tell the CSSRGB functions were not called anywhere. I'm trying to bisect now but it will take a while.

@kripken
Owner

Hmm. Another guess might be to find if MESS uses an SDL command to render that is not covered by the emscripten test suite (because what is tested, should not regress). If you can get a list of the relevant SDL commands MESS uses I can match them against the test suite.

But, bisection is a guaranteed result in logarithmic time, so that's usually best...

@kripken
Owner

Another suspect is the code in SDL_LockSurface and SDL_UnlockSurface. Those are the critical paths for getting pixels into the canvas representing the screen. Checking that these are in fact called, that they get non-0 pixels, and that they putImage those to the right canvas, might be helpful.

@DopefishJustin

6a3c393 is the first bad commit
commit 6a3c393
Author: Alon Zakai alonzakai@gmail.com
Date: Fri Mar 23 12:02:59 2012 -0700

minimal support for SDL text rendering
@kripken
Owner

Ok, there are two relevant changes,

  1. Some code was moved behind if (surf == SDL.screen) {
  2. Alpha is now copied, data[dst+3] = (val >> 24) & 0xff, instead of just = 0xff

Can you check which is the problem here? (no need to compile in either)

My bet is the second, we probably need to do = 0xff there if the target is SDL.screen, that is to ignore alpha when rendering the final RGB data. I guess SDL semantics mean we need to ignore alpha there..?

edit: forgot to say, thanks for bisecting this!

@kripken
Owner

Meanwhile I did a comparison of SDL's native behavior. Looks like it does in fact ignore alpha when rendering to the screen, so I am fixing that. Hopefully that's enough to resolve this.

Also I noticed we had R and B flipped, so I fixed that too. However I suspect that my seeing that natively with SDL might depend on the graphics hardware I have, not sure. If you see odd colors after this patch let me know.

@DopefishJustin

K the video shows up now but the colours are bad, blue instead of red.

@kripken
Owner

Ok, I'll revert the B/G flip then. There must be some setting that controls that, will investigate later.

@DopefishJustin

All better now, thanks.

@DopefishJustin

So commit 6b2a2b6 makes keyboard input stop working (ironically). Luckily, there is a simple program testkeys.c included with the project that polls SDL for keys and prints the results to stdout, which made this easy to pinpoint. I have posted the .bc and .c:

http://interbutt.com/temp/testkeys.bc
https://gist.github.com/2335842

You need to paste the code for _emscripten_set_loop() into the js output if testing the old revisions.

I guess 1.2 vs. 1.3+ API differences are probably the issue here but it was picking up keys fine prior to that commit.

@kripken
Owner

Yeah, 1.2 vs. 1.3 issue. In 1.3/2.0, scancodes are not the same as keycodes. We were missing a scancode translation table in the emscripten sdl impl. I added one now in incoming.

Note that I didn't include all the keys, because i can't find a good lookup table for DOM codes, so it means finding them out manually which is tedious. So let me know if something is missing.

@DopefishJustin

OK that does work if I recompile with the SDL 1.3 headers, but it doesn't work with the 1.2 compile (which did work before). Not sure if that's intended.

@kripken
Owner

Yes, we ship the 2.0 headers in emscripten and support only those. It's hard to support both. We used to support 1.2 by mistake since the code was not updated to 2.0, which meant 2.0 was broken, so fixing that broke 1.2 which is intentional.

@DopefishJustin

SDLMESS when compiled with SDL 1.3+ tries to include <pty.h> which is not provided by emscripten. Can probably be disabled but FYI.

@kripken
Owner

Ok, we need pty.h in emscripten then. I added a handwritten version to incoming now, let me know if it works.

@DopefishJustin

Yep that works, thanks.

@DopefishJustin

Wrong colours are back, reverting bc2e573 fixes it.

@kripken
Owner

That patch fixes the color masks, previously we had them wrong. So it isn't obvious to me what is going on here. Can you make a testcase I can debug? Then we can also add the testcase to the test suite to prevent future regressions.

@DopefishJustin

So with current emscripten the compiled js bombs out in Chrome with the following error in the error console:

Uncaught TypeError: Object #<CanvasRenderingContext2D> has no method 'createBuffer'

I guess it is trying to init something GL-related even though WebGL is not enabled; I guess emscripten should detect that more gracefully? The actual video output is not going through GL yet.

@kripken
Owner

What function is being called, and from where? If a GL function is called, that sounds like a bug in the C++ code. Unless it only happens in Chrome and not Firefox, in which case I would suspect a browser bug. But this might become clearer if you show me the relevant code.

@DopefishJustin

Whoops the markup ate part of that which might make it clearer.

@DopefishJustin

So the emscripten-generated code contains this:

createContext:function (canvas, useWebGL, setInModule) {
try {
var ctx = canvas.getContext(useWebGL ? 'experimental-webgl' : '2d');

And then later on there is code like this in GLEmulation.init():

this.vertexObject = Module.ctx.createBuffer();

Which apparently does not exist if the canvas is set up as 2D.

useWebGL is set in makeSurface:

// Decide if we want to use WebGL or not
var useWebGL = (flags & 0x04000000) != 0; // SDL_OPENGL

So I am assuming what is happening is useWebGL is coming out false for whatever reason and then the C++ is calling GL's init() somewhere, even though the OpenGL output option has not been enabled on the MESS command line. I haven't actually debugged it though.

I agree that ideally the C++ should not be calling GL stuff if the surface isn't set up for it (if that is indeed the problem), but this is also a pretty lame way to fail. If the createBuffer() method is not going to always exist then there should be some kind of type check or exception handling for the case where it doesn't, with an appropriate error message, and ideally allowing execution to continue (with, obviously, no GL output).

@kripken
Owner

Hmm, the question is why GLEmulation is included in the first place. There are a few functions which depend on it,

glVertexPointer
glMatrixMode
SDL_GL_GetProcAddress

Is one of those used in MESS? It seems like they should only appear in a build that uses GL. But perhaps they are included but not used, and we need to add a workaround for this?

@DopefishJustin

Yep all three of those are in MESS. Whether MESS uses GL or not is not a build-time option, just a command-line parameter:

mess -video soft (the default)

vs.

mess -video opengl

@kripken
Owner

But you are building without opengl as a build-time option, I assume? then why do those commands end up in the output binary?

@DopefishJustin

You assume wrongly. However now that I check there is such an option which may be enough to get by for now. But surely MESS is not the only software on earth with run-time video output selection?

@kripken
Owner

Not the only one, but the first to be compiled with emscripten I guess ;) ok, then we need runtime checks for this, I will add that.

@DopefishJustin

Thanks.

Just tried with emscripten incoming and now I can't link - I see emld was removed so I replaced it with emcc in the makefile but now this happens:

/home/jkerk/emscripten/emcc -Wl,--warn-common -s obj/sdl/messtiny/build/file2str.o obj/sdl/messtiny/libocore.a -lm `sdl-config --libs` `pkg-config --libs fontconfig` -lSDL_ttf -lutil -o obj/sdl/messtiny/build/file2str
JAVA not defined in ~/.emscripten, using "java"
Traceback (most recent call last):
File "/home/jkerk/emscripten/emcc", line 551, in <module>
assert '=' in newargs[i+1], 'Incorrect syntax for -s (use -s OPT=VAL): ' + newargs[i+1]
AssertionError: Incorrect syntax for -s (use -s OPT=VAL): obj/sdl/messtiny/build/file2str.o

@kripken
Owner

The first issue should be fixed in incoming.

@kripken
Owner

The second should be fixed on incoming as well (it was fallout from LLVM deprecating llvm-ld).

@DopefishJustin

When I try to compile now the resulting .js is missing important functions like _main() and __ZN7astring4initEv(). This is before closure has been run on it.

.bc: http://interbutt.com/temp/messtiny-20120622.bc.zip

Command line:
emcc messtiny.bc -o messtiny.js --post-js post.js --embed-file roms/coleco.zip --embed-file cosmofighter2.zip

post.js: https://raw.github.com/ziz/jsmess/no_cothreads/post.js

Maybe they are missing from the .bc file somehow but I don't know how to check.

@kripken
Owner

LLVM's llvm-nm tool can tell you what symbols are in a .bc file. Is main there?

@DopefishJustin

It's not there. It is in obj/sdl/messtiny/osd/sdl/sdlmain.o and also obj/sdl/messtiny/libosd.a but disappears after the final link:

/home/jkerk/emscripten/emcc -Wl,--warn-common -s obj/sdl/messtiny/version.o obj/sdl/messtiny/drivlist.o obj/sdl/messtiny/emu/drivers/emudummy.o obj/sdl/messtiny/mess/drivers/coleco.o obj/sdl/messtiny/mess/machine/coleco.o obj/sdl/messtiny/libosd.a obj/sdl/messtiny/libcpu.a obj/sdl/messtiny/libemu.a obj/sdl/messtiny/libdasm.a obj/sdl/messtiny/libsound.a obj/sdl/messtiny/libutil.a obj/sdl/messtiny/libexpat.a obj/sdl/messtiny/libsoftfloat.a obj/sdl/messtiny/libformats.a obj/sdl/messtiny/libz.a obj/sdl/messtiny/libocore.a -lm `sdl-config --libs` `pkg-config --libs fontconfig` -lSDL_ttf -lutil -o messtiny

I am getting a lot of /usr/bin/llvm-dis: Invalid bitcode signature at link time which may be related (llvm-dis likes sdlmain.o but not libosd.a, but llvm-nm works on both).

I'm using llvm 3.1.

@kripken
Owner

Perhaps LLVM 3.1 changed linking semantics somehow, very odd. Can you send me the relevant bitcode files (before the link that removes main) so I can try to reproduce myself? (please try to narrow it down as much as possible)

@DopefishJustin

Here's a smaller example with the testkeys utility: http://interbutt.com/temp/testkeys-linkerror.zip

Running the command line in maketestkeys results in an output file which is missing _Z15utf8_from_ucharPcjj(), which appears to be present in libutil.a. (Compiling the output to a .html with emcc, then opening it in a browser and pressing a key trips the missing function.)

@kripken
Owner

The problem is the attempt to link in native x86 binaries. You need to remove those, they can't be compiled into JS. Normally this is not too much of a problem, we detect them and ignore them - it just makes your builds slower. But in this case here, you have

emcc  -Wl,--warn-common -s testkeys.o libutil.a libocore.a -lm `sdl-config --libs` `pkg-config --libs fontconfig` -lSDL_ttf -lutil -o testkeys

Note there is both libutil.a - a bitcode file - and -lutil - a request for a system library to be linked. This is what mixes up the compiler.

Replace that line with

emcc  -Wl,--warn-common -s testkeys.o libutil.a libocore.a -o testkeys

that is, remove all requests for system libraries - and it will work.

@kripken
Owner

With that said, emcc should still not get confused even though there are irrelevant x86 libraries. I pushed a possible fix for that, it might help here. But I still recommend removing native libraries, even if they do not make the build fail they make it slower.

@DopefishJustin

Thanks, that fixes the testkeys example and restores __ZN7astring4initEv() to MESS, _main() is still missing though so some more poking is in order.

@DopefishJustin

Well my poking time has been pretty limited so here is something reproducible anyway:

http://interbutt.com/temp/mess-linkerror.zip

$ llvm-nm libosd.a | grep main

         T main
         d _ZL13main_threadid

$ emcc -s version.o drivlist.o emudummy.o coleco_driver.o coleco_machine.o libosd.a libcpu.a libemu.a libdasm.a libsound.a libutil.a libexpat.a libsoftfloat.a libformats.a libz.a libocore.a -o messtiny.bc

$ llvm-nm messtiny.bc | grep main

         T _Z16jsmess_main_loopv
         T _Z20jsmess_set_main_loopR16device_scheduler
         d _ZL13mnemonic_main
         t _ZL18menu_main_populateR15running_machineP7ui_menuPv
         t _ZL9menu_mainR15running_machineP7ui_menuPvS3_
         T _ZNK24device_execute_interface16cycles_remainingEv
         T _ZNK9emu_timer9remainingEv
         U emscripten_set_main_loop

No main(). Actually lots(all?) stuff from libosd.a appears not to make it in (e.g. _Z13sdlinput_initR15running_machine()) so maybe something is going wrong with that file.

@kripken
Owner

Ok, looks like what happens here is that main() is in an archive file and not a normal object. We were only looking for explicit undefined symbols in archives so we missed this. This is fixed in incoming. With this fix, I see main as well as _Z13sdlinput_initR15running_machine etc.

@DopefishJustin

Link is good now (thanks!)

Getting this when I try to run it in Chrome:

Uncaught TypeError: Object #<CanvasRenderingContext2D> has no method 'getExtension'

@kripken
Owner

Ok, that should be fixed on incoming now, and I added a test.

@DopefishJustin

MESS works again now!

Can probably close this issue at this point and file anything new that comes up separately.

@kripken
Owner

Cool. This page was getting long to scroll down on ;)

@kripken kripken closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.