Ren'Py homebrew port to Nintendo Switch

In this forum we discuss the future of Ren'Py, both bug fixes and longer-term development. Pre-releases are announced and discussed here.
Message
Author
User avatar
PyTom
Ren'Py Creator
Posts: 16088
Joined: Mon Feb 02, 2004 10:58 am
Completed: Moonlight Walks
Projects: Ren'Py
IRC Nick: renpytom
Github: renpytom
itch: renpytom
Location: Kings Park, NY
Contact:

Re: Ren'Py homebrew port to Nintendo Switch

#31 Post by PyTom »

Ren'Py doesn't use garbage collection in normal operation - over the last few releases, I've eliminated memory cycles, so everything works using reference counting.

I'll also note that I'm likely going to remove the SDL_Renderer based support from pygame_sdl2 to as part of a general stripping down and renaming that will happen when pygame_sdl2 becomes part of Ren'Py. So don't depend on that.

Really, I think the Switch makes sense, but the Vita doesn't - it's an underpowered, obsolete platform.
Supporting creators since 2004
(When was the last time you backed up your game?)
"Do good work." - Virgil Ivan "Gus" Grissom
Software > Drama • https://www.patreon.com/renpytom

User avatar
uyjulian
Regular
Posts: 128
Joined: Sun Mar 08, 2015 1:40 pm
Github: uyjulian
Contact:

Re: Ren'Py homebrew port to Nintendo Switch

#32 Post by uyjulian »

libnx v3.0.0 was released.

I'm going to see if the out of memory issue persists.

User avatar
uyjulian
Regular
Posts: 128
Joined: Sun Mar 08, 2015 1:40 pm
Github: uyjulian
Contact:

Re: Ren'Py homebrew port to Nintendo Switch

#33 Post by uyjulian »

Turns out that the OOM errors persist.

Code: Select all


romfs:/Contents/renpy/display/pgrender.py:118: UserWarning: Memory leak via Surface in pygame_sdl2.
  surf = Surface((width + 4, height + 4), 0, sample)

Full traceback:
  File "romfs:/Contents/game/script.rpyc", line 41, in script
    A��(|G���񲟏Sx�|a\
  File "romfs:/Contents/renpy/ast.py", line 1628, in execute
    choice = renpy.exports.menu(choices, self.set, args, kwargs, item_arguments)
  File "romfs:/Contents/renpy/exports.py", line 990, in menu
    rv = renpy.store.menu(new_items)
  File "romfs:/Contents/renpy/exports.py", line 1226, in display_menu
    rv = renpy.ui.interact(mouse='menu', type=type, roll_forward=roll_forward)
  File "romfs:/Contents/renpy/ui.py", line 297, in interact
    rv = renpy.game.interface.interact(roll_forward=roll_forward, **kwargs)
  File "romfs:/Contents/renpy/display/core.py", line 2703, in interact
    repeat, rv = self.interact_core(preloads=preloads, trans_pause=trans_pause, **kwargs)
  File "romfs:/Contents/renpy/display/core.py", line 3323, in interact_core
    self.idle_frame(can_block, expensive)
  File "romfs:/Contents/renpy/display/core.py", line 2781, in idle_frame
    if self.event_peek():
  File "romfs:/Contents/renpy/display/core.py", line 2314, in event_peek
    self.check_background_screenshot()
  File "romfs:/Contents/renpy/display/core.py", line 2162, in check_background_screenshot
    self.bgscreenshot_surface = renpy.display.draw.screenshot(self.surftree, self.fullscreen_video)
  File "gldraw.pyx", line 1382, in renpy.gl.gldraw.GLDraw.screenshot
  File "romfs:/Contents/renpy/display/pgrender.py", line 118, in surface
    surf = Surface((width + 4, height + 4), 0, sample)
  File "src/pygame_sdl2/surface.pyx", line 164, in pygame_sdl2.surface.Surface.__init__
error: Out of memory

While running game code:
error: Out of memory
While handling exception:
Traceback (most recent call last):
  File "romfs:/Contents/renpy/display/error.py", line 140, in report_exception
    traceback_fn=traceback_fn,
  File "romfs:/Contents/renpy/game.py", line 281, in invoke_in_new_context
    return callable(*args, **kwargs)
  File "romfs:/Contents/renpy/display/error.py", line 45, in call_exception_screen
    return renpy.ui.interact(mouse="screen", type="screen", suppress_overlay=True, suppress_underlay=True)
  File "romfs:/Contents/renpy/ui.py", line 297, in interact
    rv = renpy.game.interface.interact(roll_forward=roll_forward, **kwargs)
  File "romfs:/Contents/renpy/display/core.py", line 2703, in interact
    repeat, rv = self.interact_core(preloads=preloads, trans_pause=trans_pause, **kwargs)
  File "romfs:/Contents/renpy/display/core.py", line 3197, in interact_core
    self.draw_screen(root_widget, fullscreen_video, (not fullscreen_video) or video_frame_drawn)
  File "romfs:/Contents/renpy/display/core.py", line 2095, in draw_screen
    renpy.config.screen_height,
  File "render.pyx", line 490, in renpy.display.render.render_screen
  File "render.pyx", line 259, in renpy.display.render.render
  File "romfs:/Contents/renpy/display/layout.py", line 722, in render
    surf = render(child, width, height, cst, cat)
  File "render.pyx", line 166, in renpy.display.render.render
  File "render.pyx", line 259, in renpy.display.render.render
  File "romfs:/Contents/renpy/display/layout.py", line 722, in render
    surf = render(child, width, height, cst, cat)
  File "render.pyx", line 166, in renpy.display.render.render
  File "render.pyx", line 259, in renpy.display.render.render
  File "romfs:/Contents/renpy/display/layout.py", line 722, in render
    surf = render(child, width, height, cst, cat)
  File "render.pyx", line 166, in renpy.display.render.render
  File "render.pyx", line 259, in renpy.display.render.render
  File "romfs:/Contents/renpy/display/screen.py", line 675, in render
    child = renpy.display.render.render(self.child, w, h, st, at)
  File "render.pyx", line 166, in renpy.display.render.render
  File "render.pyx", line 259, in renpy.display.render.render
  File "romfs:/Contents/renpy/display/layout.py", line 722, in render
    surf = render(child, width, height, cst, cat)
  File "render.pyx", line 166, in renpy.display.render.render
  File "render.pyx", line 259, in renpy.display.render.render
  File "romfs:/Contents/renpy/display/layout.py", line 1127, in render
    st, at)
  File "render.pyx", line 166, in renpy.display.render.render
  File "render.pyx", line 259, in renpy.display.render.render
  File "romfs:/Contents/renpy/display/layout.py", line 1594, in render
    cwidth, cheight = sizeit('c', width, height, 0, 0)
  File "romfs:/Contents/renpy/display/layout.py", line 1591, in sizeit
    rend = renpy.display.render.render_for_size(pos_d[pos], width, height, st, at)
  File "render.pyx", line 310, in renpy.display.render.render_for_size
  File "render.pyx", line 259, in renpy.display.render.render
  File "romfs:/Contents/renpy/display/layout.py", line 1594, in render
    cwidth, cheight = sizeit('c', width, height, 0, 0)
  File "romfs:/Contents/renpy/display/layout.py", line 1591, in sizeit
    rend = renpy.display.render.render_for_size(pos_d[pos], width, height, st, at)
  File "render.pyx", line 310, in renpy.display.render.render_for_size
  File "render.pyx", line 259, in renpy.display.render.render
  File "romfs:/Contents/renpy/display/viewport.py", line 264, in render
    surf = renpy.display.render.render(self.child, child_width, child_height, st, at)
  File "render.pyx", line 166, in renpy.display.render.render
  File "render.pyx", line 259, in renpy.display.render.render
  File "romfs:/Contents/renpy/display/layout.py", line 925, in render
    surf = render(d, width - x, rh, cst, cat)
  File "render.pyx", line 166, in renpy.display.render.render
  File "render.pyx", line 259, in renpy.display.render.render
  File "romfs:/Contents/renpy/text/text.py", line 2008, in render
    layout = Layout(self, width, height, renders, splits_from=virtual_layout)
  File "romfs:/Contents/renpy/text/text.py", line 821, in __init__
    tex = renpy.display.draw.load_texture(surf)
  File "gldraw.pyx", line 747, in renpy.gl.gldraw.GLDraw.load_texture
  File "gltexture.pyx", line 883, in renpy.gl.gltexture.texture_grid_from_surface
  File "gltexture.pyx", line 319, in renpy.gl.gltexture.TextureCore.load_surface
  File "gltexture.pyx", line 1174, in renpy.gl.gltexture.premultiply
MemoryError

Full traceback:
  File "romfs:/Contents/renpy/bootstrap.py", line 322, in bootstrap
    renpy.main.main()
  File "romfs:/Contents/renpy/main.py", line 578, in main
    run(restart)
  File "romfs:/Contents/renpy/main.py", line 143, in run
    renpy.execution.run_context(True)
  File "romfs:/Contents/renpy/execution.py", line 908, in run_context
    context.run()
  File "romfs:/Contents/game/script.rpyc", line 41, in script
    A��(|G���񲟏Sx�|a\
  File "romfs:/Contents/game/script.rpyc", line 41, in script
    A��(|G���񲟏Sx�|a\
  File "romfs:/Contents/renpy/ast.py", line 1628, in execute
    choice = renpy.exports.menu(choices, self.set, args, kwargs, item_arguments)
  File "romfs:/Contents/renpy/exports.py", line 990, in menu
    rv = renpy.store.menu(new_items)
  File "romfs:/Contents/renpy/exports.py", line 1226, in display_menu
    rv = renpy.ui.interact(mouse='menu', type=type, roll_forward=roll_forward)
  File "romfs:/Contents/renpy/ui.py", line 297, in interact
    rv = renpy.game.interface.interact(roll_forward=roll_forward, **kwargs)
  File "romfs:/Contents/renpy/display/core.py", line 2703, in interact
    repeat, rv = self.interact_core(preloads=preloads, trans_pause=trans_pause, **kwargs)
  File "romfs:/Contents/renpy/display/core.py", line 3323, in interact_core
    self.idle_frame(can_block, expensive)
  File "romfs:/Contents/renpy/display/core.py", line 2781, in idle_frame
    if self.event_peek():
  File "romfs:/Contents/renpy/display/core.py", line 2314, in event_peek
    self.check_background_screenshot()
  File "romfs:/Contents/renpy/display/core.py", line 2162, in check_background_screenshot
    self.bgscreenshot_surface = renpy.display.draw.screenshot(self.surftree, self.fullscreen_video)
  File "gldraw.pyx", line 1382, in renpy.gl.gldraw.GLDraw.screenshot
  File "romfs:/Contents/renpy/display/pgrender.py", line 118, in surface
    surf = Surface((width + 4, height + 4), 0, sample)
  File "src/pygame_sdl2/surface.pyx", line 164, in pygame_sdl2.surface.Surface.__init__
error: Out of memory

While running game code:
error: Out of memory

Either there is a memory leak in renpy.display.pgrender.surface, or memory allocation doesn't work too well on threads.
In the meantime, I changed the renderer to use desktop OpenGL instead of OpenGLES.

spastixx
Newbie
Posts: 1
Joined: Wed Dec 11, 2019 9:56 am
Contact:

Re: Ren'Py homebrew port to Nintendo Switch

#34 Post by spastixx »

I'd personally love a Vita port as I can't afford a Switch anytime soon unfortunately, but do whatever you find worth your time. : )

User avatar
Imperf3kt
Lemma-Class Veteran
Posts: 3785
Joined: Mon Dec 14, 2015 5:05 am
itch: Imperf3kt
Location: Your monitor
Contact:

Re: Ren'Py homebrew port to Nintendo Switch

#35 Post by Imperf3kt »

spastixx wrote: Tue Dec 17, 2019 1:35 am I'd personally love a Vita port as I can't afford a Switch anytime soon unfortunately, but do whatever you find worth your time. : )
The switch lite (which homebrew does not work on) is cheaper than the original Switch.
https://www.amazon.com.au/Nintendo-Swit ... 07V7QPX7L/
Perhaps once http://ratalaikagames.com/ port more games to Nintendo officially, it may be worthwhile buying one.

I think PyTom is right in that the PSVita, as much as I'd love it to work, is not the best platform to aim for.
It only has 500MB of RAM and in my tests of running simple Ren'Py games, almost everything I tested used more than 500MB of RAM for the game alone.

Here's a bit more info from Ratalaika Games, just for more opinions.
https://twitter.com/RatalaikaGames/stat ... 7211327488
https://twitter.com/RatalaikaGames/stat ... 0186468357
Warning: May contain trace amounts of gratuitous plot.
pro·gram·mer (noun) An organism capable of converting caffeine into code.

Current project: GGD Mentor

Twitter

User avatar
uyjulian
Regular
Posts: 128
Joined: Sun Mar 08, 2015 1:40 pm
Github: uyjulian
Contact:

Re: Ren'Py homebrew port to Nintendo Switch

#36 Post by uyjulian »

I could probably make it run in less than 500MB by setting RENPY_LESS_MEMORY.
However, there is a memory leak that causes out of memory errors, even if you use small assets.

I already got Python compiling and linking on the Vita. I'll probably just use software rendering, since VitaGL has some features missing.

User avatar
Andredron
Miko-Class Veteran
Posts: 700
Joined: Thu Dec 28, 2017 2:37 pm
Location: Russia
Contact:

Re: Ren'Py homebrew port to Nintendo Switch

#37 Post by Andredron »

Tell me, how is your version different from the commercial in 1 post of yours?

User avatar
uyjulian
Regular
Posts: 128
Joined: Sun Mar 08, 2015 1:40 pm
Github: uyjulian
Contact:

Re: Ren'Py homebrew port to Nintendo Switch

#38 Post by uyjulian »

Andredron wrote: Thu Dec 19, 2019 3:54 am Tell me, how is your version different from the commercial in 1 post of yours?
It is using a more recent version of Ren'Py, is open source, and can support the same amount of multimedia formats as the upstream version.

User avatar
uyjulian
Regular
Posts: 128
Joined: Sun Mar 08, 2015 1:40 pm
Github: uyjulian
Contact:

Re: Ren'Py homebrew port to Nintendo Switch

#39 Post by uyjulian »

Possible reasoning for OOM error: Heap size is randomized, so in one circumstance, there may be plenty of memory, while in another circumstance, there may not be enough memory.

How did I determine this? Here is some example code: https://gist.github.com/uyjulian/df5e5c ... 9f0358ac0a

User avatar
wyverngem
Miko-Class Veteran
Posts: 615
Joined: Mon Oct 03, 2011 7:27 pm
Completed: Simple as Snow, Lady Luck's Due,
Projects: Aether Skies, Of the Waterfall
Tumblr: casting-dreams
itch: castingdreams
Location: USA
Contact:

Re: Ren'Py homebrew port to Nintendo Switch

#40 Post by wyverngem »

It looks fun. I'll give it a shot when I get a chance.

User avatar
uyjulian
Regular
Posts: 128
Joined: Sun Mar 08, 2015 1:40 pm
Github: uyjulian
Contact:

Re: Ren'Py homebrew port to Nintendo Switch

#41 Post by uyjulian »

Vita port of Python 2: https://github.com/uyjulian/python_vita

Currently, it compiles and links. I haven't done anything else and probably won't until I can fix the memory allocation failures in my Switch port.

User avatar
uyjulian
Regular
Posts: 128
Joined: Sun Mar 08, 2015 1:40 pm
Github: uyjulian
Contact:

Re: Ren'Py homebrew port to Nintendo Switch

#42 Post by uyjulian »

The next version will support mostly complete libnx bindings.
The bindings are generated by SWIG.

To use the bindings, you need to import the library "libnx".

Code: Select all

import libnx
To initialize a structure, you can use the following syntax:

Code: Select all

clkrstSession = libnx.ClkrstSession()
To access members of a structure, you can use the following syntax:

Code: Select all

service = clkrstSession.s
To access a enumeration, you can use the following syntax:

Code: Select all

libnx.PcvModuleId_CpuBus
To call a function, you can use the following syntax:

Code: Select all

libnx.clkrstOpenSession(clkrstSession, libnx.PcvModuleId_CpuBus, 3)
This feature can be used for mounting game RomFS, creating save data on the system memory, opening a video in the web browser applet (with hardware acceleration), opening the software keyboard applet, and more.

Plans for next version:
Fix memory leaks
Proper mouse support
Proper rumble support

Plans for future version:
Lower memory usage
Export NRO or NSP from Ren'Py Launcher
New renderer API
TJS2 interpreter implementation
Video hardware acceleration (possibly streaming image data from web browser)?

User avatar
uyjulian
Regular
Posts: 128
Joined: Sun Mar 08, 2015 1:40 pm
Github: uyjulian
Contact:

Re: Ren'Py homebrew port to Nintendo Switch

#43 Post by uyjulian »

Possible reasons for out of memory error:
1. Textures are duplicated in memory twice
2. Mesa/nouveau has a memory leak
3. Mesa/nouveau is bloated

User avatar
uyjulian
Regular
Posts: 128
Joined: Sun Mar 08, 2015 1:40 pm
Github: uyjulian
Contact:

Re: Ren'Py homebrew port to Nintendo Switch

#44 Post by uyjulian »

Plans for next version:
Proper mouse support
Proper rumble support
_socket module support

Plans for future version:
Lower memory usage
Export NRO or NSP from Ren'Py Launcher
deko3d render backend implementation
TJS2 interpreter implementation
Video hardware acceleration (via webActivity?)

User avatar
uyjulian
Regular
Posts: 128
Joined: Sun Mar 08, 2015 1:40 pm
Github: uyjulian
Contact:

Re: Ren'Py homebrew port to Nintendo Switch

#45 Post by uyjulian »

New version coming soon...
Already implemented and will be in next released version:
Out of memory workaround removed (making it more likely that you can rollback, save, and restart the game)
Overclock removed
Better error messages with error applet
Mostly complete libnx bindings
_socket, _hotshot, and imageop modules added
pymalloc now allocates memory aligned to page boundary
Show a helpful error message and quit when launched as applet
Update to libnx 3.1.0
Update to CPython 2.7.18
zipimport Python libraries
Update to switch-sdl2 2.0.12

Plans for future released version:
On screen keyboard (future version of switch-sdl2)
Lower memory usage
Remove more usages of daemon/detached threads
Export NRO or NSP from Ren'Py Launcher
deko3d or SDL_Renderer render backend implementation
TJS2 interpreter implementation
Video hardware acceleration (via webActivity?)
Save to system save data
Open installed or inserted commercially released games with open source version
_ssl module (requires either libressl or openssl to be ported)

Post Reply

Who is online

Users browsing this forum: No registered users