hex007 / freej2me

A free J2ME emulator with libretro, awt and sdl2 frontends.
Other
469 stars 72 forks source link

Does FreeJ2ME have an official compatibility list? #189

Open AShiningRay opened 1 year ago

AShiningRay commented 1 year ago

Mainly asking because there's a very small list in this project's wiki, and the screenshot gallery has quite a few games that aren't listed, so there's no info about their compatibility status... If we don't, i'd be willing to see it done over the weekend. Got some free time for that and also amassed quite a collection of j2me games while i tested a myriad of changes to FreeJ2ME and such.

I'm very interested in adding this one to the list of official libretro cores (if @recompileorg and @hex007 are also okay with it), so the more info we have on it, the better as it might also draw in a few more eyes to help with development down the line.

vadosnaprimer commented 1 year ago

Making (updating) such a list would be awesome, hard to tell how many games started working since then.

recompileorg commented 1 year ago

Work on the compatibility list would be fantastic.

On Libretro, there was quite a bit of interest initially, but that fizzled out when it became clear how limiting our dependence on Java was. Short of writing our own JVM, like SquirrelJME, I don't know that you'll have much luck. You're absolutely welcome to try.

AShiningRay commented 1 year ago

Work on the compatibility list would be fantastic.

On Libretro, there was quite a bit of interest initially, but that fizzled out when it became clear how limiting our dependence on Java was. Short of writing our own JVM, like SquirrelJME, I don't know that you'll have much luck. You're absolutely welcome to try.

Hmm, i see... is the dependency on a Java VM a limiting factor in pushing FreeJ2ME to the list of supported cores? Didn't find anything in the libretro documentation about requirements such as portability. In any case, being relegated to linux and windows still reaches quite a lot of users since there are some Java VMs for ARM archs as well.

Now coming back to the compatibility list: Alright, i'll get on it soon. Any specific format or structure you'd prefer the data to be? My initial idea is to classify each app/game entry with fields for ["Name", "Screen Resolution", "Status" , "Description/Notes"], as well as a pie graph containing the percentage of apps in each compatibility status. It's rather easy to do on excel or libreoffice calc and move it to a wiki or even a github.io page later.

AShiningRay commented 1 year ago

Okay... so it took a while to set everything up in Github Pages, but it's there. A weekend well-spent re-learning some aspects of HTML5, CSS3 and JS. (Also, turns out FreeJ2ME's compatibility is rather good on the apps i tested so far)

It's definitely not "final" by any means, but for those that are interested, here's the first iteration of it: https://ashiningray.github.io/freej2me/

Feedback is appreciated!

vadosnaprimer commented 1 year ago

Good job! For my oldschool primitive taste it's a bit too bouncy (pun intended), but the main hero here is the info itself, so it's good.

Where do people send info if they want to help with those tests? It would be cool if the chart was be able to get constructed from a simple table which users could send pull requests to tweak.

BTW from observations by the Bounce Tales community, framerate usually needs to be limited at 60 for game physics to work correctly. Did you test with it limited or not?

AShiningRay commented 1 year ago

BTW from observations by the Bounce Tales community, framerate usually needs to be limited at 60 for game physics to work correctly. Did you test with it limited or not?

Both, didn't notice any major difference between uncapped and limited to 60 on the 4 or so levels i tested through, the game just ran smoother uncapped. Most of the games i tested followed a similar methodology, though with that many tests in such a short time there are bound to be inaccuracies here and there.

Where do people send info if they want to help with those tests? It would be cool if the chart was be able to get constructed from a simple table which users could send pull requests to tweak.

This website constructs its compatibility list from a csv file inside docs/compat_data/ on the repo. It's a bit cluttered since i opted to simplify it as much as possible to facilitate CSVReader's life, but it's rather straightforward to understand with the very first line indicating how each category is laid out.

Definitely not very optimized yet, as can be seen by the time it takes to rebuild the whole list once you clear the search field after looking for something, but it's okay for a functionality preview and a smaller list.

vadosnaprimer commented 1 year ago

Both, didn't notice any major difference between uncapped and limited to 60 on the 4 or so levels i tested through, the game just ran smoother uncapped. Most of the games i tested followed a similar methodology, though with that many tests in such a short time there are bound to be inaccuracies here and there.

The difference was in how speedrun tricks worked, where certain objects would give unrealistic boosts due to difference in calculations timing. It may be harder to notice during normal play I guess, which means for general compatibility the data is representative enough.

AShiningRay commented 1 year ago

The difference was in how speedrun tricks worked, where certain objects would give unrealistic boosts due to difference in calculations timing. It may be harder to notice during normal play I guess, which means for general compatibility the data is representative enough.

I see. Well, i'm far from being a speedrunner on that game so to me it behaved almost identically ;)

Nevertheless it's still good to know that framerate locks (or lack thereof) can cause all sorts of issues on J2ME apps, from major slowdown/fast-forward to small-ish physics issues or desyncs... had only noticed the former so far.

recompileorg commented 1 year ago

Wow. I think just about everything surprised me, from how quickly this came together and the number of games tested to the energetic design. This is great. The use of a CSV for the actual data was a smart choice.

Looking down the list, it feels like a bit like a "to do", which is convenient as well.

There was someone who had M3G support just about done, but he seems to have vanished. There are some improvements to M3D(O) I'd like to make as well. I need more time...

The 'byte stream' problems aren't usually too hard to figure out. If anyone is looking for an easy on-ramp, that's a good place to start.

On the frame rate stuff, that's actually a major reason this project exists. I was adding that exact feature to Micro Emulator when I realized that I did not want to work on that nightmare for another minute.

The approach I used is far from precise. I worry about how well it will work for speed runners. It might be worth taking some time to find a way to make that more accurate, or at least reproducible. It would be great if the speed running community could make good use of this project.

AShiningRay commented 1 year ago

Wow. I think just about everything surprised me, from how quickly this came together and the number of games tested to the energetic design. This is great. The use of a CSV for the actual data was a smart choice.

Thanks! Had the whole weekend to play around with it so after most of the list was done, designing the website was pretty straightforward thanks to not needing anything too complex, and as for the CSV, it seemed like the best way to allow for other people to add to the list since it's easy enough to understand and modify, as well as following the same structure as the webpage's list.

Currently making some additional tweaks to the page in order get it where i want design-wise (some animations were too exaggerated for example), and since it's set up to use Github Pages, it can actually be pushed to this main repository and hosted from here, although the link will definitely need some extra adjustments in the project's settings, and it will change to hex007.github.io/freej2me instead of ashiningray.github.io/freej2me.

If everyone agrees, we can sort that out later as the webpage is rather unintrusive on the repository thanks to it being placed in its own docs/ directory.

Looking down the list, it feels like a bit like a "to do", which is convenient as well.

Figured it would be useful to know not only which games were breaking, but why they were breaking as well. Randomly testing games to find something that got stuck trying to save RMS data in a negative index or used a different media type from audio/wav a while back wasn't a great experience, so being able to check right on the list seemed like a good idea.

There was someone who had M3G support just about done, but he seems to have vanished.

That was @crwxrws (i hope i'm not being rude by pinging so many people recently), and from what i tested, their implementation moved quite a few games from "Ingame/Not booting" straight to "Minor issues/Perfect", with a few examples that come to mind being Bomberman 3D Atomic and Rally Master Pro.

Unfortunately almost all of their implementation went way over my head and the most i could do was a few optimizations and smaller fixes here and there to help other games like Race Driver GRID while experimenting.

AShiningRay commented 1 year ago

Alright, now i think it's good enough. (clear your browser's cache before loading in, or else the css3 changes won't apply)

Much cleaner and overall easier to read with the trimmed color palette and better visual highlights but tried not to go overboard with it.

AShiningRay commented 1 year ago

The 'byte stream' problems aren't usually too hard to figure out. If anyone is looking for an easy on-ramp, that's a good place to start.

This one is really strange, cause it's mostly relegated to NET Lizard games and none of them seem to be affected by it. Added some debug messages into PlatformImage for a quick test and the output is rather interesting:

Reading image:[B@42d9e713| Stream:java.io.ByteArrayInputStream@6e571df1
Couldn't Load Image Data From Byte Array: Cannot invoke "java.awt.image.BufferedImage.getWidth()" because "temp" is null
Reading image:[B@42d9e713| Stream:java.io.ByteArrayInputStream@6db3cccf
Reading image:[B@c1ec6e4| Stream:java.io.ByteArrayInputStream@72a86902
Couldn't Load Image Data From Byte Array: Cannot invoke "java.awt.image.BufferedImage.getWidth()" because "temp" is null
Reading image:[B@c1ec6e4| Stream:java.io.ByteArrayInputStream@329813bd
Reading image:[B@28f8e325| Stream:java.io.ByteArrayInputStream@72542ec
Couldn't Load Image Data From Byte Array: Cannot invoke "java.awt.image.BufferedImage.getWidth()" because "temp" is null
Reading image:[B@28f8e325| Stream:java.io.ByteArrayInputStream@79d17c2f

The first element is the ImageData byte array passed to the PlatformImage constructor, while the second is the input stream that's created inside it. As can be seen, the received ImageData causes a failure the first time PlatformImage tries to read it with ImageIO, so the game sends them again and somehow it works out. In a way, this explains why despite so many of these messages showing up, none of their games were missing images or graphics compared to J2ME Loader (or my Huawei G6608 for that matter).

This also happens on three other games from them that i tested so far: Flowhex (so i guess this image issue isn't what prevents it from booting) Clone 3D and Liquidator 2... not sure why that is the case, maybe those games have some buggy code in regards to image data? They're all from the same developer after all, and most share the same underlying engine.

recompileorg commented 1 year ago

That sounds like some early work that needs tightened up. The PlatformImage constructor is being called by javax.microedition.lcdui.Image.createImage(InputStream) which should throw an IOException when something goes wrong with the stream.

https://docs.oracle.com/javame/config/cldc/ref-impl/midp2.0/jsr118/javax/microedition/lcdui/Image.html#createImage(java.io.InputStream)

The right thing to do here is to declare the exception thrown by javax.microedition.lcdui.Image.createImage(InputStream) and actually throw it in PlatformImage, instead of ignoring it. The constructor is only called in that one place, so we only need to change those two files. (This is not the case for the other constructors.)

That whole isNull hack ought to be revisited as well. It may have outlived its utility, though I'd need to check to see if it's still in use anywhere.

AShiningRay commented 1 year ago

That sounds like some early work that needs tightened up. The PlatformImage constructor is being called by javax.microedition.lcdui.Image.createImage(InputStream) which should throw an IOException when something goes wrong with the stream.

https://docs.oracle.com/javame/config/cldc/ref-impl/midp2.0/jsr118/javax/microedition/lcdui/Image.html#createImage(java.io.InputStream)

The right thing to do here is to declare the exception thrown by javax.microedition.lcdui.Image.createImage(InputStream) and actually throw it in PlatformImage, instead of ignoring it. The constructor is only called in that one place, so we only need to change those two files. (This is not the case for the other constructors.)

That whole isNull hack ought to be revisited as well. It may have outlived its utility, though I'd need to check to see if it's still in use anywhere.

Oh i see... so the issue isn't where i thought it was. I'll add it to the list of things to look at later if no one else is available to handle it, currently i gotta finish implementing the ima adpcm decoder (it's almost there, sounds a bit bad but at least now it uses the exact same structures as PCM wav everywhere, without relying on SourceDataLines like before)

This also confirmed that wav files playing two times in sequence is a thing, as it didn't happen when the adpcm data was a DataLine (because it really could only be played a single time through start() or drain() methods), but now it does since it's a wavClip.

recompileorg commented 1 year ago

Don't take it too seriously. That was just my best guess based on what you posted, I haven't done anything other than look at the two files and the docs to see if there was any problem. I was trying to think about why a game would "retry" loading an image that way and how we could screw that up with a bad implementation. I think I also missed the part about it passing a byte array and not a stream to a PlatformImage constructor. That's what I get for computing while holding a baby.

In any case, that needs to be cleaned up, but I'm less confident now. It could still be the problem, just in the other createImage method.