Playdate Nim bindings - C performance, Python like syntax

Thanks Samdze and Daeke,

That's great to hear about Nim2 bindings Samdze!

That's correct Daeke no sprites were used. Probably not the best for battery life as it's a full screen redraw. I haven't figured out how to redraw dirty areas for bitmaps and geometry like they do with sprites just yet, though in this case it probably would make much difference.

2 Likes

Right. The screen works in dirty rows so I don't think you'd gain much.

Yeah, all lines are probably changing every frame indeed.

Note that your comparison might actually be selling Nim short, considering it's being limited by the system's 50 fps. You could also post the cpu usage for a clearer picture

Very nice scene, BTW

Why dirty rows? I have almost no experience with this stuff, but the one time I worked with HTML Canvas doing pixel level rendering, marking for redraw was done in rectangular regions.

Edit: I'm guessing it's just less overhead/simpler to treat the problem as 1D since you don't have to track overlapping regions and is closer to how fundamentally the image is drawn in general.

Would it be possible to switch it to draw by column? Given the screen dimensions statistically you are more likely to run more efficiently that way (I mean, still not much to be gained from this example as there's like maybe 5-8% of vertical drawlines being untouched, but you get what I mean)

That's how the screen hardware receives data. So even if you work more granularly you still have to send whole rows to be updated.

Ah. By that metric it’s going to update the entire screen every-time. This isn’t e-ink. The entire screen is reloaded for every frame regardless of what you got going on computationally underneath. (At least I assume, it's possible panic made the process row by row and my HTML canvas comparison doesn't exactly work here since HTML Canvases also have the outside OS screen rendering to worry about and you can't really "chase the buffer").

Instead you should think of updating dirty regions of draw as more like updating sections of memory for that process. In practice this plays out more like animating a scene using ms paint where you either recreate the entire thing screen by screen every-time, or you just make all the small changes to the regions of the image as required frame by frame.

In 3D graphics, moving the camera effects the entire screen so usually you are doing the math at the entire screen level anyway (there’s the possibility of using motion vectors though to change the math to difference between previous and next frame though which effectively is closer to the concept of dirty draw).

The complicated part of dirty draw though (based on my experience with canvas drawing) is that you need the drawing process to be reversible.
Ie: if I point to a region on the screen I want to redraw while ignoring touching the rest…., you need to know what parts of the code only affect that region you are trying to redraw and rerun the drawing process for just this region.

This is easier with sprites and background images because (assuming no rotations or moving background) the math is more like: grab this subregion of this image and copy the memory over here rather than copy the memory of the whole thing.

Not so easy with code generated stuff which isn’t going to have fixed sizes and positioning. Not to say it isn’t worth it though in some cases.

In the case of the rain though which takes over so much of the screen with so many small parts, the process of jumping around the memory to copy this small piece and that small piece is likely to be heavier than just copying the whole thing without trying to subdivide. Maybe motion vectors could work here to process things in a quickly iterable way, but at that point you are usually better breaking down rendering into slow processes taking multiple frames and letting quicker motion vectors to handle the in between but that’s both really complicated and likely to make the “response to human input” portion of the code slower (basically allowing you to work ahead for the next 2-3 frames as you aren't concerning yourself with the random noise generators that are humans).

Oh, and this should go without saying but motion vectors + the hardware in place/level of math going on behind the scenes could be wholly not worth it what-so-ever. I just mention it as I understand it from the VR world.

Playdate screen (Sharp Memory LCD) is actually quite like eink: rows that aren't updated retain their display and use almost no power.

Playdate SDK Sprite system allows you to do partial redraw/refresh. Of course it only works with some game designs. It won't work for your rain.

I recommend taking a look at the SDK Examples, make sure to turn on "Highlight Screen Updates" in the Simulator, and immerse yourself in the docs to learn more about this.

Here's a recent thread where implementations are discussed:
https://devforum.play.date/t/frame-independent-games-brainstorm/16628

1 Like

Interested in using nim and these nimble bindings for Playdate and have followed the installation instructions for Windows (I'm on Windows 11). However I'm unable to build the 'playdate_example' included in the git repo. I'm having this error:

playdate_example\src\playdate_example.nim(22, 38) Error: attempting to call undeclared routine: 'getButtonState'

Is this a known issue? I'm using Playdate SDK 2.4.2, should I roll back to an earlier version of the Playdate SDK? I didn't see a recommended Playdate SDK version on the Playdate Nim readme, but I assume something has changed in the more recent SDK's?

Thanks!

This is due to the published package (v0.13.0) not being up to date with the main branch of the repo.
v0.14.0 will be released soon, but in the meantime you can rename getButtonState to getButtonsState

1 Like

Hey thanks for the almost instant answer! Alright I will do that and continue to experiment - thank you kindly!

1 Like

I had other issues, so I simply replaced the playdate 0.13.0 package contents with the latest in the repo which solved all those, but now it seems my mingw64 setup isn't quite correct.

Ugh Windows. Time to escape to the Linux laptop I have and try again...

Are folks generally using nim playdate under Linux or Windows?

I think folks using Nim here are generally on macOS or Linux, but Windows needs to be perfectly supported so feel free to open an issue on GitHub!

We could probably make the MSYS2 and mingw64 install process more clear

I'm on windows and it runs well but yes I think most people are on Mac.

I had the same issue look at my post above with -reinstall MSYS2 from https://www.msys2.org/

After that you should be good to go.

1 Like

I float around a bunch of platforms and tooling and honestly...things just always seem to work better under the original platform they were built on.

I agree things should work under Windows...but in may case I just want to code games :slight_smile: Moving to Linux and things are already working better. I acknowledge this is a somewhat selfish and non-altruistic stance!

Edit: Ah @jmation I see your post above and have just tried that as well. Let's see if it builds now...? Hmmmm no still have issues. Might have to reboot...

Additional info: Requested command not found: 'C:\Users\Stu\Documents\nim-1.6.18\dist\mingw64\bin\arm-none-eabi-gcc.exe -c  -DTARGET_EXTENSION=1 -Wall -Wno-unknown-pragmas -Wdouble-promotion -IC:\Users\Stu\Documents\PlaydateSDK\C_API -D__HEAP_SIZE=8388208 -D__STACK_SIZE=61800 -DTARGET_PLAYDATE=1 -mthumb -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-sp-d16 -D__FPU_USED=1 -falign-functions=16 -fomit-frame-pointer -gdwarf-2 -fverbose-asm -ffunction-sections -fdata-sections -mword-relocations -fno-common -Wno-unused-but-set-variable -Wno-unused-label -Wno-parentheses -Wno-discarded-qualifiers -Wno-array-bounds --specs=nosys.specs -O3 -fno-strict-aliasing -fno-ident   -IC:\Users\Stu\Documents\nim-1.6.18\lib -IC:\Users\Stu\Documents\git\playdate-nim\playdate_example\src -o C:\Users\Stu\nimcache\playdate_example_r\device\setup.c.o C:\Users\Stu\Documents\PlaydateSDK\C_API\buildsupport\setup.c'. OS error: 2
     Error: Build failed for package: playdate_example
        ... Execution failed with exit code 1
        ... Command: C:\Users\Stu\Documents\nim-1.6.18\bin\nim.exe c --colors:on --noNimblePath -d:device -d:release -d:NimblePkgVersion=0.8.0 --path:C:\Users\Stu\.nimble\pkgs\playdate-0.13.0 -o:C:\Users\Stu\Documents\git\playdate-nim\playdate_example\playdate_example.exe C:\Users\Stu\Documents\git\playdate-nim\playdate_example\src\playdate_example.nim

Does compiling for the Windows simulator work?
Seems you're now lacking the arm-none-eabi toolchain but I can't tell for sure.

Nonetheless, if you don't mind having to use a different (secondary?) pc with Linux, go for it!

This was one of multiple issues I had on Windows. Note the path it searches for the compiler.
That's mingw64 inside the nim installation folder.

The windows builds of Nim try to help you out by bundling mingw64, but that does not contain the compiler for playdate. The stupid thing is that if you install a separate compiler, it won't find it.

What I did:

  • remove Nim installation. I believe it's just a matter of deleting the folder

  • download choosenim and use it to install nim.
    This will get you nim without the bundled mingw64.

  • now make sure your msys2 mingw installation is in working order, with it's bin folder on the path.

Finally install the two compilers you will need:

pacman -S mingw-w64-x86_64-arm-none-eabi-gcc
pacman -S mingw-w64-x86_64-gcc
2 Likes

My recommendation is to start with the example project instead of creating a new nim project. There are some configurations in place in the sample project that you can benefit from. It's also simply a good sanity check to see if your environment is in working order.

OK, one more gotcha: make sure the playdate sdk is up to date. I think 2.4.0 is the minimum. But really, just make sure you keep it up to date.
(can you tell I got burned by this one? :stuck_out_tongue::sob:)

Haha thanks for the tips! Yes my Windows machine is a mixed bag of installed toolkits.

I will try these suggestions on Windows because I am very curious to try nim on play.date. I'm a crusty C programmer but haven't used it in anger for decades. Nim seemed like a much nicer solution, if only I could get it working :).

I can definitely build the Play.date C Examples without issue under Windows so yes likely some nim tool chain oddities.

@Nino your instructions worked like a charm! Thank you. Steps for Windows would seem to be:

  • use choosenim

  • choosenim 1.6.18 (as that's the last in the 1.6.x series)

  • make sure the .choosenim toolchain is in your Path. Defaults to C:\Users\(username)\.choosenim\toolchains\nim-1.6.18\bin

  • use msys2 for MinGW on Windows

  • pacman -S mingw-w64-x86_64-arm-none-eabi-gcc

  • pacman -S mingw-w64-x86_64-gcc

Now I have to force myself to wrap up the Lua clone game I was working on before embarking on a nim game...! Thanks all.

I can probably uninstall a bunch of msys2 pacman stuff now...

2 Likes