I.K.E.M.E.N GO on Raspberry Pi 4 [Now with an Install Guide!]
-
@superfromnd
Check this
https://retropie.org.uk/forum/topic/28528/box86-and-wine-on-rpi4/333We've been working hard and have a how to add to any build in it . All old windows games ikemen would work loaded over 30 mugens and tested already
-
@SuperFromND Hey I just found out about Mugen last week and I need more of it lol. I think Ikemen and Retropie are a perfect match and so I wanted to step in and help as much as I can. Ive been trying to port Ikemen to the pi over the past couple days and i ran across this gem of a thread and i wanted to add my progress and hopefully we can get this thing built into retropie at some point.
Anyways Using the LucasFebatis branch of Ikemen-Go-Plus I was able to compile and run a match using the Retropie prebuilt 32-bit image.
I was getting the infamous SIGBUS error which is because some of the OPCodes (mainly just OC_float) in bytecode.go:run() is trying to convert some bytes from the stack into an address but this address is not valid hence the SIGBUS. To get around this i replaced the line:
sys.bcStack.PushF(*(*float32)(unsafe.Pointer(&be[i])))
with
sys.bcStack.PushF(0);
This fixed the sigbus error on match load and got me into matches. Where to my surprise i found no pallette bug. I wasn't able to find the pallette character you were using but i did try to fight with the one and only Ronald Mcdonald to produce the below screenshot.
The only bug i ran into now is that because the OC_Float opcode is used to convert float numbers in the boolean expressions that move characters from state to state in their .def file, by hard coding the address of 0 the characters get stuck in states that they cannot get out of. This leads to issues like KFM looks like he's falling forever and cant be hit since that state ignores hits. So if we can see why these addresses are coming up wrong when read in the OC_float case in bytecode.go:run() we should be able to actually play matches.
If you'd like me to send anything of what I have so far let me know ill keep monitoring this thread.
-
Oh and some stats about what I'm using night help recreate my results:
GO version (default installed from apt-get)
go 1.11.6 linux/armPi Model (from /proc/cpuinfo):
Raspberry Pi 4 Model B Rev 1.1Retropie version 4.6:
my Run.sh
#!/bin/sh
export GOPATH=$PWD/go
export DISPLAY=192.168.0.106:2.0
echo Using Display $DISPLAY
go fmt ./src/.go
MESA_GL_VERSION_OVERRIDE=4.3 go run ./src/.go -
So a little more digging into the issue led me to the fact that there is a byte alignment issue with the bcStack.
The address of be[i] when processing the OC_float op code is misaligned sometimes meaning its not a multiple of 4 like a pointer address needs to be. Not sure yet if this is related to a go unsafe pointer quirk or if we need to fix the alignment in the struct definitions.
This would be the reason why the 64bit OS doesn't have this SigBus Issue. The good news is that if i ported the code i have over to raspbianx64 this should be fully functioning now. Ill have to verify this still but with these alignment quirks caused by the use of 64 bit types (especially float64) on a 32bit opearting system the sigbus should sort itself out.
-
Woahhh, stellar work joam! This was a very pleasant thing to wake up to this morning :D
I can't really help out too much on this specifically since low-level instructions and byte-alignment stuff is far out of my realm of expertis, but if you do need me for anything else (testing stuff, etc.) then let me know!
(oh, and the character I was using was the original Donald by Kishio, which can be found here; not that you'll really need it seeing as the palette issues apparently didn't occur for you at all.)
-
I just forwarded these posts to the IKEMEN devs over on the Discord (which is probably a good idea for you join, by the way; it'll probably help being able to talk with the devs directly), and Gacel stated he's gonna look into adding these changes into the main IKEMEN GO fork (that's the Windblade-GR01 fork, not the LucasFebaits one you seem to be using).
Since I know how to compile and run that fork now, that would theoretically make it possible to compile directly from the main IKEMEN GO fork, meaning we'd always have the newest version of IKEMEN GO available for folks to compile!
If the changes are made and it turns out to work, I could probably (finally) start working on a scriptmodule for this. :D
-
Glad i can help. I joined the discord and ill start getting acquainted with everyone this week. I think Gacel's could be invaluable in helping to align the structures. Luckily Alignment issues usually only affect ARM based systems (other compilers/arch are good at padding things for you) so in theory the padding should only affect these devices.
I gave it a go for like 6 hours last night trying to figure out what needed to be aligned but couldn't get a working build though my results mentioned below with the 64 bit Raspbian tell me that the structures are properly 8-Byte Aligned when using the 64 bit types. So that just means its really close already.
Thanks for the character ill load that one in just to make sure its not that character causing issues and i just got lucky with my character choice.
Also i started with the LucasFebatis repo cause you seemed to be having better results with it but i see that its a little over 1000 commits behind so before we start to byte align things for the 32 bit OS ill migrate up to that version.
Good News! I was waiting on an SD Card to load the 64 bit OS which arrived today and i was able to verify that on the 64bit Beta Raspbian I was able to play the game without any crashes. As far as i can see everything works. Also the performance was pretty good.
Unfortunately I did notice however that when using the X server on the Pi itself i saw the pallette issue but using the external xserver on my PC everything drew up just fine. this makes me think that the Xserver is to blame here. Though it is possible that the rendering is done on the PC side and replaces whatever bugs may on the pi side.
I think the byte alignment issue is a technicality so it shoouldnt be a showstopper on getting Ikemen on the Pi, it will just take some to sort out.
The pallette bug on the other hand seems like it demands attention so i think ill continue my testing on the 64 bit Raspbian and try to see if i can figure that one out but I think ole Lucas was onto what i saw also. He mentions that the XServer may have issues processing gamma ramp so i may start with finding an alternative XServer.
"For Got b'X11: RandR gamma ramp support seems broken"
TLDR
Current State: (Lucas Febatis)
32 bit Retropie OS:
Menus work good
Crashes in Match due to an Alignment Trap processing OC_float in bytecode.go (be[i] is not 2, 4, or 8 byte aligned)
When using an External X Server on PC palletes show correctly
Using Pi as the XServer the palette bug exists.64 bit Raspbian OS:
Everything works except for the palette bug when using pi as the XServer
When using an External X Server on PC palettes show correctly. -
More progress updates on the 32 bit crashing when entering matches. I found a workaround for the Alignment trap by reading the array myself reallocating a slice and then dumping the resulting float32 in the stack where it belongs.
With this simple "fix" I am able to match the 64 bit OS functionality (Lucas Febatis repo) where you can play through matches and everything works as it should. The palette issue still exists as the only bug i can find so that's next on the todo list.
Maybe we can make a "Infection" Ikemen game so the palette issues become a feature lol.
Anyways ill port the "fix" in to the official windblade branch and test it there but since it was the same sigbus you were receiving this should fix that issue.
Fix for sigbus Alignment error on arm32
replace the line below from src/bytecode.go(line 898 ish or line 968 in WIndblade Repo) in Run() for OC_float case
sys.bcStack.PushF(*(*float32)(unsafe.Pointer(&be[i])))
to
arr := make([]byte, 4)
arr[0] = byte(be[i])
arr[1] = byte(be[i+1])
arr[2] = byte(be[i+2])
arr[3] = byte(be[i+3])
flo := Float32frombytes(arr)
sys.bcStack.PushF(flo)Im off to compile the main fork be back later ...
Aaaand I'm back. Thank to your great tutorial i was able to compile the windblade for (which has a lot more stuff in btw) and confirmed that with the above "fix" I was able to get complete a few matches on the Retropie distro and had no crashes anywhere.
Note: The windblade branch was missing a function and an import for "encoding/binary":
func Float32frombytes(bytes []byte) float32 {
bits := binary.LittleEndian.Uint32(bytes)
return math.Float32frombits(bits)
}Added a pull request for the windblade repo for this workaround. Ill leave the above explanation for history.
https://github.com/Windblade-GR01/Ikemen-GO/pull/319 -
Great news, the PR above that joamjoamjoam submitted just got merged, and I can confirm it DOES compile! As you can see by this gameplay footage I recorded the palette issues still persist on Pi (According to joam's posts above, there's something in the Pi's Xserver that breaks it for whatever reason), but aside from that it's basically fully functional.
Fun side note: that weird input bug I mentioned earlier? Turns out that was just a fluke; my Bluetooth keyboard just doesn't play well with IKEMEN for whatever reason, and plugging in my usual USB keyboard worked perfectly fine (though my X360 pad still had a rotated D-pad by default, this can be easily fixed by just modifying
config.json
and all the other buttons work fine).I guess it's time to start writing a scriptmodule then!
-
Another update from me, I have managed to create an almost fully-functioning RetroPie scriptmodule for IKEMEN GO! Keyword there being almost, because while it can indeed download, compile and install IKEMEN GO, and while said build can be started, it hangs when trying to load.
There's a really odd quirk, though I'm not sure if it's the fault of IKEMEN or a consequence of
xinit
, but for whatever reason the engine fails to find LUA script files (that it needs) if you try to run it from anywhere other than the directory Ikemen_GO itself is installed in. So for example, if you ran IKEMEN GO from/foo/bar/
but it needs a file from/the/monkey/paw.png
, it'll try to find the file at/foo/bar/paw.png
! Thankfully this can be fixed with a very simple shellscript to manually change the directory to IKEMEN GO's and run that throughXINIT:
like so:#!/bin/bash cd /opt/retropie/ports/ikemen-go MESA_GL_VERSION_OVERRIDE=4.3 ./Ikemen_GO
There's also something rather strange I encountered: when running IKEMEN GO from runcommand (making use of
XINIT:
, which is used in a few other scriptmodules likeuqm
andags
), it hangs on a black screen (assuming that the LUA issue mentioned above is solved already). It's not just refusing to run, as it will crash out if you have certain controllers plugged in when starting the engine up, but once it has started it just hangs indefinitely, leaving you with a black screen.It's not just displaying to the wrong screen either; even grabbing a keyboard and spamming the Esc key to try and quit IKEMEN GO doesn't do anything, it's just flat-out frozen. There's actually been at least one other project that has gotten this black screen issue through
XINIT:
, though sadly the thread never elaborated on it nor provided a solution.However, manually starting
xinit
and then running it... works perfectly fine! This seems to suggest that I might just need to tweak the launch command more, so perhaps someone more savvy and experienced withXINIT:
related stuff in RetroPie could come and assist (paging @mitu perhaps?)I should mention that there's a second way of running stuff that requires
xinit
in RetroPie, and that's usingxinit -e 'command'
. Unfortunately, trying that instead crashes due toxinit
not having permission to access/dev/tty0
, crashing before we even get a chance for IKEMEN GO to run. Now, there is a fix for this, and I confirmed that it DOES allow IKEMEN GO to run from runcommand.The only problem is that the fix is this:
# a very, VERY bad idea, especially for a game with user-made content ikemen-go = "sudo xinit -e '/opt/retropie/ports/ikemen-go/ikemen-go.sh'" default = "ikemen-go"
For those not super savvy with how Linux works,
sudo
is essentially the Linux equivalent of running a program as an administrator in Windows, and is really only supposed to be used as a last resort, and not for general use like this.I actually ran into this exact same conundrum back in 2018 while trying to get Flash and Java games running on RetroPie, and I did technically find a solution that didn't require
sudo xinit
. That solution was using achmod
command onXorg
to allow it to run from a script:sudo chmod ug+s /usr/lib/xorg/Xorg
Of course, since as you can see this also makes use of the
sudo
command, it's not a safe or elegant solution to this problem either.So to recap:
- Running IKEMEN GO manually works fine
- Running IKEMEN GO from
XINIT:
hangs at a black screen - Running IKEMEN GO from
xinit -e
isnt possible without a huge security risk
Thankfully, aside from the palette issues joam described above, and the controller bug mentioned earlier in this thread that's planned to be remedied soon anyways, this is the last major issue that needs to be fixed before IKEMEN GO could be feasibly added to RetroPie. And given the circumstances and the fact that running source ports through
XINIT:
is clearly possible already, this could very well be ready for testing soon. We're in the endgame. -
@SuperFromND Nice work!! It’s really coming along now.
A small update in the palette corruption issue. I’ve narrowed it down to being one of 4 things:
- A bug in the shaders that only shows on arm.
- A bug in the v3D driver (Mesa) when drawing textures
- A bug with the Go glfw pacakage or GLFW itself when running on the pi.
- A bug in the Ikemen_GO source that’s is causing the textures drawn from the sprites/palettes to be messed up on the pi only.
I think one of the first 3 is most likely since a remote c server shows no issues and OpenGL 2.1 support for the pi is relatively new.
Things I’ve tried to no avail:
-
Printing palettes being read from SFF files and looking for discrepancies from what’s is defined in fighter factory.
-
using Mesa 20.3 v3D drivers for OpenGL for the pi.
We also would need to rewrite the shaders in openGLES 2 if we wanted to support other Pi devices as the pi4 is the only pi that can handle OpenGL 2.1.
-
I found something that works with
XINIT:
! This is probably not the ideal way (I'm sure that either mitu or Jools will point out if there's a better way to handle it), but I found out that chaining the launch commands intoxterm
will cause IKEMEN GO to boot correctly from EmulationStation:ikemen-go = "XINIT:/opt/retropie/ports/ikemen-go/ikemen-go.sh" default = "ikemen-go"
#!/bin/bash export MESA_GL_VERSION_OVERRIDE=2.1 xterm -g 320x240+0+0 -e 'cd /opt/retropie/ports/ikemen-go && ./Ikemen_GO'
So all that's left is for me to clean up this scriptmodule a tiny bit, maybe adding some symlinks to intergrate it a bit better with RetroPie's folder structure, and then we can have people test it!
-
It will be pretty interesting to see a highly customizable fighting game engine be used on RetroPie for various fighting games.
Speaking of which, I haven't heard from the OpenBOR board in a couple of months. I wonder if they are still active...
-
A little bit more info on the palette issue. The issue is definitely caused by the shaders. For some reason the OpenGL texture mapping for the 1d texture palette is not mapping correctly when running in the pi hardware. I verified that palettes being read from sff files match on both the pi and my windows PC.
I think the issue is related to the difference in texture precision on the two devices. Unfortunately I think this is as far as I can take it unless there’s someone on the Dev team who knows what these shaders are doing and are willing to play around with some of the texture types for the pi to get more precision.
Edit: we’ll nvm after about 3 days of no progress I went to document what I found and what line was causing it in case someone smarter than me wanted to look at it.
In render.go there’s a line in the fragment shader around render.go:70 that maps the pallet texture to the 2d sprite.
Line 70
Vec4 c = texture1D(pal, r*0.9961)Simply tweaking the constant from .9961 to .9966 yielded the below results.
It stood out to me cause it had a hard coded constant by tweaking the constant by small amounts all the palettes lined up from the elecbyte logo to the characters in a match.
Also Ignore Gandalf's staff being transparent. That's just me being bad at editing sprites with Fighter Factory. All the characters I dint touch match exactly to how they play on Windows.
-
@joamjoamjoam Nice work! Really interesting that a single constant value was all that it took to break (and now fix) palettes, kinda makes me wonder how exactly that bit of code came about in the first place. Once again, a massive thank you for your help!
Also, I just now finished my first draft of the scriptmodule:
#!/usr/bin/env bash # This file is part of The RetroPie Project # # The RetroPie Project is the legal property of its developers, whose names are # too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source. # # See the LICENSE.md file at the top-level directory of this distribution and # at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md # rp_module_id="ikemen-go" rp_module_desc="I.K.E.M.E.N GO - Clone of M.U.G.E.N to the Go programming language" rp_module_licence="MIT https://raw.githubusercontent.com/Windblade-GR01/Ikemen-GO/master/License.txt" rp_module_help="Copy characters, stages, screenpacks, etc. to $romdir/ports/ikemen-go" rp_module_section="exp" function depends_ikemen-go() { getDepends golang-go libgl1-mesa-dev xinit xorg xorg-dev libopenal1 libopenal-dev libgtk-3-dev libasound2-dev freeglut3-dev } function sources_ikemen-go() { gitPullOrClone "$md_build" https://github.com/Windblade-GR01/Ikemen-GO.git } function build_ikemen-go() { go clean go mod tidy make TAGS='-tags al_cmpt' linux # grabs default screenpack and content required for the game to run; note that the screenpack has a CC-BY-NC 3.0 license make elecbyte md_ret_require="$md_build/Ikemen_GO" } function install_ikemen-go() { cp 'elecbyte/LICENCE.txt' 'ScreenpackLicense.txt' mkdir save sound md_ret_files=( 'Ikemen_GO' 'License.txt' 'ScreenpackLicense.txt' 'data' 'save' 'sound' 'font' 'external' 'elecbyte/chars' 'elecbyte/stages' 'elecbyte/data' 'elecbyte/font' ) } function configure_ikemen-go() { mkRomDir "ports/ikemen-go" addPort "$md_id" "ikemen-go" "I.K.E.M.E.N GO" "XINIT:$md_inst/ikemen-go.sh" moveConfigDir "$md_inst/chars" "$romdir/ports/ikemen-go/chars" moveConfigDir "$md_inst/stages" "$romdir/ports/ikemen-go/stages" moveConfigDir "$md_inst/data" "$romdir/ports/ikemen-go/data" moveConfigDir "$md_inst/external" "$romdir/ports/ikemen-go/external" moveConfigDir "$md_inst/font" "$romdir/ports/ikemen-go/font" moveConfigDir "$md_inst/sound" "$romdir/ports/ikemen-go/sound" moveConfigDir "$md_inst/save" "$configdir/ports/ikemen-go" cat >"$md_inst/ikemen-go.sh" << _EOF_ #!/bin/bash export MESA_GL_VERSION_OVERRIDE=2.1 xterm -g 1x1+0+0 -e 'cd /opt/retropie/ports/ikemen-go && ./Ikemen_GO' _EOF_ chmod +x "$md_inst/ikemen-go.sh" chown -R $user:$user "$md_inst" }
As you can see there's still some weirdness that should be sorted out (specifically the wall of
moveConfigDir
s could probably be reduced,chown -R $user:$user "$md_inst"
may be over-scoped, andmake elecbyte
probably should go in agame_data_
function), but this is still good enough to install IKEMEN GO in a way that works well with RetroPie's file structure.If you know how to install a scriptmodule into RetroPie manually, this should be testable! Just in case you don't though, here's a super-quick rundown of the procedure:
- If you haven't already, enable SSH on RetroPie.
- Open up whatever SSH program you prefer (I use PuTTY) and log into your Pi.
- Navigate to
/home/pi/RetroPie-Setup/scriptmodules/ports
using thecd
command. - Start up a text editor with elevated priveleges using
sudo nano ikemen-go.sh
. - Paste the contents of the scriptmodule above (in PuTTY, this can be accomplished by first copy-pasting the scriptmodule's contents in this post, and then simply right-clicking the PuTTY window), then press:
Ctrl-X
, thenY
, thenEnter / Return
to save the file and exitnano
. - If done correctly, there should be a new file called
ikemen-go.sh
present (You can verify this by runningls ikemen-go.sh
). You can now exit your SSH program. - From here, you can access and run the scriptmodule like any other; by going into RetroPie Setup and going to "Manage Packages". IKEMEN GO will be under "Experimental".
Addendum: Just for funsies, I made a launching.png image in the style of the Pixel theme's launching images, themed after the default screenpack in IKEMEN:
-
@superfromndso I'm gonna test this soon.
Installing now . Would love to have side by with my mugen -
Yeah it had to do with hoe precise, or imprecise, floating point operation were on the pi vs x86. It wasn't all unselfish either lol I wanted some MUGEN on piCade.
I tried installing the screen pack but was greeted with a permission error on start up.
something about save/stats.json. the ports/ikemen-go folder was missing the save folder also. even after copying a working save folder from my dev branch i got the same error.
let me know if there anything you want me to try. feel free to reach out on discord too.
Also on an unrelated note, I saw your video on the discord and your sound was working perfectly. on my pi4 the sound is garbled and terrible. I'm glad its not a real issue and did you do anything special to fix it?
-
@joamjoamjoam Ah, I see! The
save/stats.json
error happens whenever IKEMEN is unable to write to thesave
folder (this is also why thechown
command is there).I set it up so that IKEMEN GO symlinks the save folder to the
/opt/retropie/configs/ports/ikemen-go
directory since that's where configs typically go in RetroPie; it's possible that some write permissions might be preventing it on your side and I simply didn't realize this due to my permissions possibly being set up non-standard (I use a USB stick to store my ROM collections, and I achieved it by manually symlinking on RetroPie to point to it; I think I might'vechmod -R 777
'd my configs folder and forgot about it).This could probably be fixed really easily; as in just changing it to redirect to the
roms
location instead. Not a huge loss!# the line in question: moveConfigDir "$md_inst/save" "$configdir/ports/ikemen-go" # the (very simple) fix: moveConfigDir "$md_inst/save" "$romdir/ports/ikemen-go/save"
As for the sound thing... I have no idea actually! It just worked flawlessly whenever I installed it, though it was noticeable quiet (I ended up manually boosting the audio volume, both in IKEMEN's config.json and in post using MAGIX Vegas).
-
@superfromnd ah I see let me set the permission correctly in there and then I’ll try reinstalling the scripts with that change for the romdir.
The pi has a really bad sound system and it’s most notable in the volume outputted. If you get a usb sound card like this one on Amazon it makes it a lot better.
Sabrent USB External Stereo Sound Adapter:
Sabrent USB External Stereo Sound Adapter for Windows and Mac. Plug and Play No Drivers Needed. (AU-MMSA) https://www.amazon.com/dp/B00IRVQ0F8/ref=cm_sw_r_cp_api_glt_fabc_J3BVS30PKHX1RQX2MP17?_encoding=UTF8&psc=1Heres the permission for the configs directory if your interested:
So a chown and chgrp to pi on the ikemen folder /opt/retropie/configs/ports worked perfectly and it matched what other ports were doing so I think adding in those will work a charm.
The audio issue is still there however so it might be an issue with my HDMI display and getting sound out of it. I see you were using composite audio out. I grabbed my bluetooth speaker and plugged it into the pi and voila perfect sound. Theres probably some HDMI audio issues with Alsa when using openAL or some configuration I might need to do.
So I think the three outstanding issues are
- add a chown and chgrp to pi for ikemen config folder
- add joystick support (i think we need to pipe DInput into Ikemen but im not sure how the joysticks work on the pi). Ill handle this one and see if i can get my fight stick up and running
- Maybe add a basic config.json file for the pi since it defaults to being windowed 640x480. I had to manually set the fullscreen option to get it full screen for my 1080p display (which I think is unfortunately more common than CRTs these days.) We could use the opputunity to set the default audio volume a little higher for the pi too.
-
@joamjoamjoam
The permissions thing could be sorted out really easily, something like this:function configure_ikemen-go() { mkRomDir "ports/ikemen-go" addPort "$md_id" "ikemen-go" "I.K.E.M.E.N GO" "XINIT:$md_inst/ikemen-go.sh" moveConfigDir "$md_inst/chars" "$romdir/ports/ikemen-go/chars" moveConfigDir "$md_inst/stages" "$romdir/ports/ikemen-go/stages" moveConfigDir "$md_inst/data" "$romdir/ports/ikemen-go/data" moveConfigDir "$md_inst/external" "$romdir/ports/ikemen-go/external" moveConfigDir "$md_inst/font" "$romdir/ports/ikemen-go/font" moveConfigDir "$md_inst/sound" "$romdir/ports/ikemen-go/sound" moveConfigDir "$md_inst/save" "$configdir/ports/ikemen-go/save" cat >"$md_inst/ikemen-go.sh" << _EOF_ #!/bin/bash export MESA_GL_VERSION_OVERRIDE=2.1 xterm -g 320x240+0+0 -e 'cd /opt/retropie/ports/ikemen-go && ./Ikemen_GO' _EOF_ chmod +x "$md_inst/ikemen-go.sh" chown -R $user:$user "$configdir/ports/ikemen-go/save" }
I might have to tweak it a little bit (maybe using
mkRomDir
to create the folder with user-owner permissions instead of using a secondchown
command), and admittedly I haven't tested this fix yet, but that should do it, I think.That's really interesting that you mentioned fullscreen; for whatever reason whenever I tried to set the fullscreen parameter in IKEMEN to true, it just crashes out entirely, no error log or anything. Maybe it's because I'm not using a window manager like
matchbox
? That might also explain why my IKEMEN window isn't centered when running on a CRT, resulting in accidental underscan.I don't think a default config is really necessary here; a quiet volume is rather easy to remedy by the end user anyways, and adding a custom "default" config might cause issues down the road.
Contributions to the project are always appreciated, so if you would like to support us with a donation you can do so here.
Hosting provided by Mythic-Beasts. See the Hosting Information page for more information.