From 765601f207598da745200060dab5c367423a5449 Mon Sep 17 00:00:00 2001 From: Thomas Farstrike Date: Tue, 7 Jul 2026 22:53:21 +0200 Subject: [PATCH 1/3] Doom and Duke Launchers: skip CRC32 of files for romart (too slow) --- .../apps/com.micropythonos.doom_launcher/MANIFEST.JSON | 2 +- .../apps/com.micropythonos.doom_launcher/doom_launcher.py | 1 + .../apps/com.micropythonos.doom_launcher/retrogo_launcher.py | 3 ++- .../apps/com.micropythonos.duke_launcher/MANIFEST.JSON | 2 +- .../apps/com.micropythonos.duke_launcher/duke_launcher.py | 1 + 5 files changed, 6 insertions(+), 3 deletions(-) diff --git a/internal_filesystem/apps/com.micropythonos.doom_launcher/MANIFEST.JSON b/internal_filesystem/apps/com.micropythonos.doom_launcher/MANIFEST.JSON index ba16f3a36..3575c6651 100644 --- a/internal_filesystem/apps/com.micropythonos.doom_launcher/MANIFEST.JSON +++ b/internal_filesystem/apps/com.micropythonos.doom_launcher/MANIFEST.JSON @@ -1 +1 @@ -{"name":"Doom Launcher","publisher":"MicroPythonOS","short_description":"Legendary 3D shooter","long_description":"Plays Doom 1, 2 and modded .wad files from internal storage or SD card. Place them in /roms/doom/. Uses ducalex's retro-go port of PrBoom. Supports zipped wad files too.","fullname":"com.micropythonos.doom_launcher","version":"0.4.4","category":"game","activities":[{"entrypoint":"doom_launcher.py","classname":"DoomLauncher","intent_filters":[{"action":"main","category":"launcher"}]}]} \ No newline at end of file +{"name":"Doom Launcher","publisher":"MicroPythonOS","short_description":"Legendary 3D shooter","long_description":"Plays Doom 1, 2 and modded .wad files from internal storage or SD card. Place them in /roms/doom/. Uses ducalex's retro-go port of PrBoom. Supports zipped wad files too.","fullname":"com.micropythonos.doom_launcher","version":"0.4.5","category":"game","activities":[{"entrypoint":"doom_launcher.py","classname":"DoomLauncher","intent_filters":[{"action":"main","category":"launcher"}]}]} \ No newline at end of file diff --git a/internal_filesystem/apps/com.micropythonos.doom_launcher/doom_launcher.py b/internal_filesystem/apps/com.micropythonos.doom_launcher/doom_launcher.py index 0eb7689bf..20f508ce4 100644 --- a/internal_filesystem/apps/com.micropythonos.doom_launcher/doom_launcher.py +++ b/internal_filesystem/apps/com.micropythonos.doom_launcher/doom_launcher.py @@ -13,4 +13,5 @@ def onCreate(self): .putExtra("boot_name", "doom") .putExtra("game_name", "Doom") .putExtra("file_extensions", (".wad", ".zip")) + .putExtra("skip_crc32", True) ) diff --git a/internal_filesystem/apps/com.micropythonos.doom_launcher/retrogo_launcher.py b/internal_filesystem/apps/com.micropythonos.doom_launcher/retrogo_launcher.py index 1d382a4bf..7e1beabbe 100644 --- a/internal_filesystem/apps/com.micropythonos.doom_launcher/retrogo_launcher.py +++ b/internal_filesystem/apps/com.micropythonos.doom_launcher/retrogo_launcher.py @@ -74,6 +74,7 @@ def onCreate(self): self.boot_name = extras.get("boot_name") self.game_name = extras.get("game_name", "Game") self.file_extensions = extras.get("file_extensions", (".wad", ".zip")) + self.skip_crc32 = extras.get("skip_crc32", False) self.romdir = "roms" self.romartdir = "romart" @@ -291,7 +292,7 @@ def refresh_file_list(self): gamedir = self.romdir + "/" + self.roms_subdir fullpath = gamedir + "/" + self.current_subdir + "/" + f if self.current_subdir else gamedir + "/" + f diskpath = self.bootfile_prefix + fullpath - romart = self._find_romart(diskpath, f) if has_romart else None + romart = self._find_romart(diskpath, f) if (has_romart and not self.skip_crc32) else None button = self.wadlist.add_button(romart, f) button.add_event_cb( lambda e, p=fullpath: self._launch_game(p), diff --git a/internal_filesystem/apps/com.micropythonos.duke_launcher/MANIFEST.JSON b/internal_filesystem/apps/com.micropythonos.duke_launcher/MANIFEST.JSON index f66de2b6b..c5ec111ad 100644 --- a/internal_filesystem/apps/com.micropythonos.duke_launcher/MANIFEST.JSON +++ b/internal_filesystem/apps/com.micropythonos.duke_launcher/MANIFEST.JSON @@ -1 +1 @@ -{"name": "Duke Nukem 3D", "publisher": "MicroPythonOS", "short_description": "Legendary 3D shooter", "long_description": "Plays Duke Nukem 3D .grp files from internal storage or SD card. Place them in /roms/duke3d/. Uses ducalex's retro-go port. Supports zipped grp files too.", "fullname": "com.micropythonos.duke_launcher", "version": "0.3.4", "category": "game", "activities": [{"entrypoint": "duke_launcher.py", "classname": "DukeLauncher", "intent_filters": [{"action": "main", "category": "launcher"}]}]} \ No newline at end of file +{"name": "Duke Nukem 3D", "publisher": "MicroPythonOS", "short_description": "Legendary 3D shooter", "long_description": "Plays Duke Nukem 3D .grp files from internal storage or SD card. Place them in /roms/duke3d/. Uses ducalex's retro-go port. Supports zipped grp files too.", "fullname": "com.micropythonos.duke_launcher", "version": "0.3.5", "category": "game", "activities": [{"entrypoint": "duke_launcher.py", "classname": "DukeLauncher", "intent_filters": [{"action": "main", "category": "launcher"}]}]} \ No newline at end of file diff --git a/internal_filesystem/apps/com.micropythonos.duke_launcher/duke_launcher.py b/internal_filesystem/apps/com.micropythonos.duke_launcher/duke_launcher.py index 3b35bb51f..9130099a7 100644 --- a/internal_filesystem/apps/com.micropythonos.duke_launcher/duke_launcher.py +++ b/internal_filesystem/apps/com.micropythonos.duke_launcher/duke_launcher.py @@ -25,5 +25,6 @@ def onCreate(self): .putExtra("boot_name", "duke3d") .putExtra("game_name", "Duke Nukem 3D") .putExtra("file_extensions", (".grp", ".zip")) + .putExtra("skip_crc32", True) .putExtra("starting_text", help_text) ) From 6d28084f87cde0c0b9f36de4297171374cb85c1b Mon Sep 17 00:00:00 2001 From: Thomas Farstrike Date: Tue, 7 Jul 2026 23:03:06 +0200 Subject: [PATCH 2/3] Increment version --- .../apps/com.micropythonos.retrocore_launcher/MANIFEST.JSON | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal_filesystem/apps/com.micropythonos.retrocore_launcher/MANIFEST.JSON b/internal_filesystem/apps/com.micropythonos.retrocore_launcher/MANIFEST.JSON index dd7f02018..152f8f1f0 100644 --- a/internal_filesystem/apps/com.micropythonos.retrocore_launcher/MANIFEST.JSON +++ b/internal_filesystem/apps/com.micropythonos.retrocore_launcher/MANIFEST.JSON @@ -1 +1 @@ -{"name":"Retro Core Launcher","publisher":"MicroPythonOS","short_description":"Classic 8-bit and handheld games","long_description":"Plays NES and Gameboy ROMs from storage or SD card. Place in /roms/nes/ or /roms/gb/. Uses retro-go. Zipped ROMs supported.","fullname":"com.micropythonos.retrocore_launcher","version":"0.5.2","category":"game","activities":[{"entrypoint":"retrocore_launcher.py","classname":"RetroCoreLauncher","intent_filters":[{"action":"main","category":"launcher"}]}]} \ No newline at end of file +{"name":"Retro Core Launcher","publisher":"MicroPythonOS","short_description":"Classic 8-bit and handheld games","long_description":"Plays NES and Gameboy ROMs from storage or SD card. Place in /roms/nes/ or /roms/gb/. Uses retro-go. Zipped ROMs supported.","fullname":"com.micropythonos.retrocore_launcher","version":"0.5.3","category":"game","activities":[{"entrypoint":"retrocore_launcher.py","classname":"RetroCoreLauncher","intent_filters":[{"action":"main","category":"launcher"}]}]} \ No newline at end of file From 00743a617eee5530a234eccc479b9e308664ab13 Mon Sep 17 00:00:00 2001 From: Thomas Farstrike Date: Tue, 7 Jul 2026 23:39:29 +0200 Subject: [PATCH 3/3] Add REPL shell app --- .../MANIFEST.JSON | 1 + .../icon_64x64.png | Bin 0 -> 3876 bytes .../repl_shell.py | 64 ++++++++++++++++++ 3 files changed, 65 insertions(+) create mode 100644 internal_filesystem/apps/com.micropythonos.repl_shell/MANIFEST.JSON create mode 100644 internal_filesystem/apps/com.micropythonos.repl_shell/icon_64x64.png create mode 100644 internal_filesystem/apps/com.micropythonos.repl_shell/repl_shell.py diff --git a/internal_filesystem/apps/com.micropythonos.repl_shell/MANIFEST.JSON b/internal_filesystem/apps/com.micropythonos.repl_shell/MANIFEST.JSON new file mode 100644 index 000000000..964263150 --- /dev/null +++ b/internal_filesystem/apps/com.micropythonos.repl_shell/MANIFEST.JSON @@ -0,0 +1 @@ +{"name": "REPL Shell", "publisher": "MicroPythonOS", "short_description": "Interactive Python REPL shell", "long_description": "Run Python code interactively. Output and errors are displayed inline.", "fullname": "com.micropythonos.repl_shell", "version": "0.1.0", "category": "development", "activities": [{"entrypoint": "repl_shell.py", "classname": "ReplShell", "intent_filters": [{"action": "main", "category": "launcher"}]}]} \ No newline at end of file diff --git a/internal_filesystem/apps/com.micropythonos.repl_shell/icon_64x64.png b/internal_filesystem/apps/com.micropythonos.repl_shell/icon_64x64.png new file mode 100644 index 0000000000000000000000000000000000000000..b09f9df052a25cd47b2de0183bb09496ee5af9c5 GIT binary patch literal 3876 zcmV+<58LpGP)eTCmHy7X_q~3vwOO)dS+;P@5`vKf6hth6Oe_fF5C+EyQO9F8hZqbVW2l-6%uoZ} zs!G*lCc_K_Y=&}WDrIBYyk;safy6_CZEA+i5M~l9!G=Jwc#~u;ZmG9-?>+NF-HIej zUbNVn$*Jn<>aO?hd*{2~Irp4%&jtR(g-+FTnfb^UA>#jc05CHplS$E9T}}1v?cCbh z%FWHqcBE_L@wlk3uczwjYHDw9=ccA6OOp(Wnk-<0AQ1hNN(O)#28w8T;f0E}_K>Gd z16;=;C!Nm5VzJB-pfC$05+adEn8^TxCS$f^vDkpZPdxWrRAjRYEW~Aiy?`y|Y7@?q zLe^^Cf0>j5*4mU(&ij^44*_oz@Vb=po!eru&f-`>5Xhr3=u`qgK@bcm{>Y0jM!eq4 zBCuUz*<1x+t{d^d%wTH)W(@ZM0D%MnL=Zwihars7hoq4IDM&sGoqO@NWy=m0ftV=s z7&ibx5Xhq954W_`_|mzPz~2^1odW2Lv zo6B(~pA*^|A*6(m5@9}nkU-BHHjk`Yx^&m@XP*)P;_Uw8;moMKNXBG*7$I1p8tF0#hY9_MlHf>rYmGh9}y7k#?7QW-^85Pq+ ziRTL;BrMy0>KD|fV?2@zfKUMtK?G(-CYR&RRFCQD>s4OVhYfX`vHblzmc||(4;yF< zvo4BG=<&^)6G}O8V=WYso>@6vmiZ+F0<7&G9O5bqLtvBu5wr!hgY;4pM4nR@)zhAeha{6>PKO$nKZ>m5-9}oTI18U16qR>z+LH7cF~D~AdZ*z1Io{EwhG5-Fu8nq=Iqm) z65oe5`lQFz+FB?namMUAMdH*QM! zB_&_UXENcuS#zAC@>5BywK%Q1M*7OpLdlsfiH#saeSJNR34kC7WOHMqUbkt}S3KW) zurHM|b7s^yQcBn9Jd{j&kx=haN}WEts+!B9Q85?*YX$DS^ET`~ z&^F}ex>++2Yl`8bh6YqrOgptqAc8g;AME>-L1ctA7u>#VS?h3LAclE<0V4LazS8r& zGbD&hJWq@?`?G3lj`;7>10DG1N7v!D+gIYJ|Nb-%9N2$KS>P%MrGANVA`ulbe+K}z zZ{IFPWkA3zV?<`{rp-Tz_>r5-BT+MRTBXv)91-w@`4FwY+lA+zc@}TJ^FJfLgsT+( z;+m_`c;!|2%)HZ2x}PYl2zGC0n+QX_+jO*_fA^X-`N7p^8tnXth<~_YLrGM~J<4%r zpEje0J|-eD0k2a2#g>GQ(rX@l>cK z{9)fG%tXvOyyT8$%ibDn25J}^xJ;?}P)?0taKv^0ShgB%8Icn6&pj8PJ7+$=@y$Qr zKeqk?FTK12c|9~4+wtm~*zxL{s6YD*eB+zf}xxON7g-o_x9`_ml+(>1OP-_m#j7*V8KH{;K!PpY%$9n z0HC!v9?=|TM#OQ63xkYRYHMo|Te=kg`uJL0_Js>4p+Z!!+oPxRaHORE2$pL~ySm)L zPEZZX`MEp@e1y6N%#cEiJLK2eV9)M%@!|_V!)tH-dQzf3J`Rs4gn%GoDW$8+%Vz`V zNhA^kfYl(n@cJO|bIhl)WjIRFSY!QsE{|Qiev4ibpU=}Op}KgXBdV|Kv=x-L?xY0qbM%1_}Z^x zVdGW!%)EIgwV=YxP(X{-sCUUoTV zju1tjG#TcQhx~FJhw`C5?j7Sp9UXY>wO7%y`6(RkOOJTXyt-LvYKq~)3ok-hdHE^N z53C-lpBlsu>iqGK!xBH*4We@Hw}DX#CWNPxTd?`5r;iADiqdew0$jKF>!@Gwc|;c3pQwU%*WG<*!~o zLU~syT($5DT>a;ZaOPQ`g_Lsg?fMu25fMRa&4!u6FieMG{{6vW!~g^8lgUDt3UvcO zSg7?MPvzHD60z%-;EF%{GV12kjmeKprf5^xv>{5B8DmB?f$HjND&VqH2)QJa%W+lN z(Fd-XUWuk}U5|?|xfE5?r%%ZmArT?3wG~oG4)MDcD^{f9BPBz{_*e+MVZxBJWW?y3 z9*pnax*YWj&O=E_$&@XSGBXH3I-6l3Bn07g09d$vyJ#*XLjwRbH8t5ncK1%GbvH{{ znb(?K#~Bh3F#|#{F23Y4Om!)4)@E{9VfyEB$Ee8=5iv81+hVaUw)~nnCFnK2*Yr{RO;=)lYK-h4XA>I7-nXDZTP07&)q8Ra?v z+h4AX#d-o}Ik=l-2mlKgE;ImOT=_yao9)Pjd6CKGc%)L61z;Gk-2cr}kp9M6^z`)# zs|^#;PXGYPo^K2fQgRfTnr zuLlu9Nr}$XVQUGb^Z9q%XV<<`DEkdr29KE9CV;_A4)9MppU)jm_lZnC$0sAGndsT? z=LW?Gv}{!N(6FV3;8INaCE6(yx)tex-|7Q*6*C!UzVz$Zj| zS0}r^CrsX~x%=+Bb3qVDDy;oOz#3_g9Xob#eSN+BPAryMv}8$dX<6B|UESTLqO@$F z-*2jlAi~FO`?ZR=Dw9bkSKqko2S@83JF5SRZ`-Dt8yof7mX@bI-@l%;)o0AEQ|F$N_7c)X=$nvl-hLW0&CA|6R-ceKhCML=T6Mz>U12U01JISqq~+eW19qxx zhch#jlsMGg#Rob&tmpY6o5`(Qee<$63PI2Knxu%x20CEk`Z(O$iL>eVe=#2+J__vJ> zC1u{T5VF?hLp`UuMwUkVn|LWHSrLqWqY{_`&Py^zRsD4Y%eJ5Z9rwcqx7HV1 z=8d)J=}p;=o^G}Tsg#1%W=lslz54!JZaH+)+T{mggm_#e5(y?EUbkVx0uk~4QA&9Y zGs9?&a=%1Zl$HrU68Ym{iNd*o(KcNO1WRlk* zyRxb2=ffxDqyaDz8`cNG)eQQcG3H9wi%1=65Hm+3o{2_0inuO0Qjrh>Qp({+W?-yg zV=d?MA*XX0&g8Npv{op`fzcXZ{tdv7>?3-zITp(^v%ok`i%bXr!`T1;>yydznCT{K z_16G8R~5?ZY)o;l4wA%>_1Ur|W0{x=o0(F=Xbq$Fr&6hxNYLgAV_q(TJrU=HCJcbV zY#4l+D+mJFE9HgSn9G^@OO|;)GiDjB%RS$hmTiFm0%1N60=mH53lhI4;@6~LZXV*117_)L-(I%wz=7Hl-=Edj+Y3M;;(5qrQoXb5 z>fUQhrSdBmFHR2!762wv@ks?>@c2Ox3>=$1UdlEFfjqZx&txB;J=yh4VrC=~2^!wU mo&*pSsD=}J0000>> %s" % code) + captured = [] + + def _print(*args, sep=" ", end="\n"): + captured.append(sep.join(str(a) for a in args) + end) + + self.namespace["print"] = _print + error = None + try: + exec(code, self.namespace) + except Exception as e: + error = "!!! %s: %s" % (type(e).__name__, e) + for line in "".join(captured).rstrip("\n").split("\n"): + if line: + self._append(line) + if error: + self._append(error) + + def _append(self, line): + self.buffer.append(line) + self.output.set_text("\n".join(self.buffer))