agentbox-app 0.1.11 → 0.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (239) hide show
  1. package/README.md +24 -16
  2. package/bin/agentbox.mjs +18 -9
  3. package/briefs/message-rules.md +15 -4
  4. package/main/account-tooling.mjs +2 -1
  5. package/main/acp.mjs +296 -0
  6. package/main/agent-homes.mjs +158 -0
  7. package/main/agent-sessions.mjs +57 -20
  8. package/main/agent-updates.mjs +9 -20
  9. package/main/analytics.mjs +30 -0
  10. package/main/approvals.mjs +14 -5
  11. package/main/claude-bin.mjs +45 -310
  12. package/main/claude-input.mjs +9 -3
  13. package/main/claude-launch-env.mjs +54 -0
  14. package/main/claude-models.mjs +39 -7
  15. package/main/claude-plan.mjs +14 -2
  16. package/main/claude-usage.mjs +82 -25
  17. package/main/codex-bin.mjs +51 -248
  18. package/main/codex-launch-env.mjs +31 -0
  19. package/main/codex-session.mjs +38 -3
  20. package/main/codex-threads.mjs +41 -8
  21. package/main/codex-watch.mjs +67 -3
  22. package/main/config.mjs +40 -13
  23. package/main/corner-tag.mjs +489 -0
  24. package/main/crash-report.mjs +26 -3
  25. package/main/demo.mjs +17 -14
  26. package/main/engine-bin.mjs +595 -0
  27. package/main/engine-setup.mjs +27 -27
  28. package/main/feedback.mjs +11 -6
  29. package/main/fresh-user.mjs +1 -1
  30. package/main/git-change.mjs +8 -2
  31. package/main/harnesses/claude-stream.mjs +208 -0
  32. package/main/harnesses/claude.mjs +84 -0
  33. package/main/harnesses/codex.mjs +65 -0
  34. package/main/harnesses/common.mjs +78 -0
  35. package/main/harnesses/instructions-file.mjs +116 -0
  36. package/main/harnesses/opencode.mjs +234 -0
  37. package/main/harnesses.mjs +65 -0
  38. package/main/importable-threads.mjs +38 -0
  39. package/main/instruction-settings.mjs +47 -11
  40. package/main/ipc.mjs +175 -22
  41. package/main/local-app-frames.mjs +82 -0
  42. package/main/machine.mjs +1 -1
  43. package/main/main.mjs +120 -5
  44. package/main/memory-gate-history.mjs +51 -12
  45. package/main/memory-gate-server.mjs +67 -11
  46. package/main/memory-gate.mjs +49 -8
  47. package/main/memory-log.mjs +124 -0
  48. package/main/notify.mjs +48 -5
  49. package/main/opencode-server.mjs +271 -0
  50. package/main/opencode.mjs +287 -0
  51. package/main/phone-link.mjs +551 -0
  52. package/main/refresh-agent-models.mjs +2 -1
  53. package/main/relay-address.mjs +28 -0
  54. package/main/relay-client.mjs +246 -0
  55. package/main/row-label.mjs +8 -7
  56. package/main/runs-on.mjs +90 -0
  57. package/main/serve.mjs +124 -10
  58. package/main/settings.mjs +171 -11
  59. package/main/shell-path.mjs +86 -0
  60. package/main/ship-queue.mjs +25 -7
  61. package/main/sign-in-files.mjs +3 -7
  62. package/main/source-updater.mjs +27 -1
  63. package/main/start-hold.mjs +73 -0
  64. package/main/store/home.mjs +37 -5
  65. package/main/store/project.mjs +15 -19
  66. package/main/store.mjs +10 -4
  67. package/main/supervisor.mjs +1030 -447
  68. package/main/task-commands.mjs +13 -17
  69. package/main/task-folders-offthread.mjs +6 -1
  70. package/main/task-folders.mjs +491 -82
  71. package/main/task-terminals.mjs +49 -8
  72. package/main/team/index.mjs +2 -2
  73. package/main/team/projects.mjs +1 -1
  74. package/main/updater.mjs +71 -9
  75. package/main/worktree-include.mjs +494 -0
  76. package/mcp/core/page.mjs +1 -1
  77. package/mcp/core/work.mjs +34 -3
  78. package/mcp/tools.mjs +2 -1
  79. package/package.json +10 -1
  80. package/renderer/dist/assets/abnfDiagram-YUKMZFIV-DPPuMWt-.js +1 -0
  81. package/renderer/dist/assets/arc-HmFfdseH.js +1 -0
  82. package/renderer/dist/assets/architectureDiagram-47P4ROYG-DxJ3zHrH.js +36 -0
  83. package/renderer/dist/assets/blockDiagram-E7TT5TSB-CbTXzOqQ.js +140 -0
  84. package/renderer/dist/assets/c4Diagram-CRA5TL53-X5ItFyLn.js +38 -0
  85. package/renderer/dist/assets/channel-BlT2g9Sz.js +1 -0
  86. package/renderer/dist/assets/chunk-2Q5K7J3B-DC12Ho_L.js +1 -0
  87. package/renderer/dist/assets/chunk-5VM5RSS4-ClVtfPd0.js +15 -0
  88. package/renderer/dist/assets/chunk-7TKQ45FW-DgcOm0HT.js +1 -0
  89. package/renderer/dist/assets/chunk-AW2ZBBNX-C01s4yoF.js +88 -0
  90. package/renderer/dist/assets/chunk-FVRAUYC3-Bj0zxhR4.js +2 -0
  91. package/renderer/dist/assets/chunk-HTAEGDNF-DWDeEhLU.js +1 -0
  92. package/renderer/dist/assets/chunk-JWPE2WC7-Dsqwv3eW.js +1 -0
  93. package/renderer/dist/assets/chunk-KQW6MTUR-CE86ANL2.js +1 -0
  94. package/renderer/dist/assets/chunk-XXDRQBXY-CoNTASfs.js +1 -0
  95. package/renderer/dist/assets/classDiagram-v2-K4WV4PDN-2wprLqtw.js +217 -0
  96. package/renderer/dist/assets/cornerTag-BLrxiDE5.css +1 -0
  97. package/renderer/dist/assets/cornerTag-BOT6u3Tn.js +1 -0
  98. package/renderer/dist/assets/cose-bilkent-JH36ORCC-enqMiYbn.js +1 -0
  99. package/renderer/dist/assets/cynefin-EF2NZ3EQ-DHngLxvQ.js +141 -0
  100. package/renderer/dist/assets/cynefinDiagram-3GCD6N5R-C0rZZIl3.js +62 -0
  101. package/renderer/dist/assets/cytoscape.esm-C5JX3QLV.js +331 -0
  102. package/renderer/dist/assets/dagre-W4DXFKR2-DQnaEWO7.js +4 -0
  103. package/renderer/dist/assets/defaultLocale-DX6XiGOO.js +1 -0
  104. package/renderer/dist/assets/diagram-2UJZ2QOL-CS8AlGPx.js +200 -0
  105. package/renderer/dist/assets/diagram-OVF4WLC6-yiDMHIkY.js +24 -0
  106. package/renderer/dist/assets/diagram-PFPMY2P6-XbQKzbBA.js +30 -0
  107. package/renderer/dist/assets/diagram-UMYRVEAY-dhVvlfl_.js +24 -0
  108. package/renderer/dist/assets/diagram-YEKJPTXX-DZHe8SCf.js +41 -0
  109. package/renderer/dist/assets/diagram-ZIFT7M5P-B5h6aXVR.js +3 -0
  110. package/renderer/dist/assets/ebnfDiagram-VR2GEFS7-PR9ScDco.js +1 -0
  111. package/renderer/dist/assets/elk-IJKZMXRS-Cg-yQXPd.js +27 -0
  112. package/renderer/dist/assets/erDiagram-O2IAPWRE-omOrJMxu.js +99 -0
  113. package/renderer/dist/assets/flowDiagram-OXPTDLAJ-aOX2hzvT.js +213 -0
  114. package/renderer/dist/assets/ganttDiagram-R7TSEDQI-B1H3pWyI.js +292 -0
  115. package/renderer/dist/assets/gitGraphDiagram-XJZIOB7I-Cvw304HC.js +106 -0
  116. package/renderer/dist/assets/graph-DGbsTEsI.js +1 -0
  117. package/renderer/dist/assets/infoDiagram-5W2HQ5XZ-_ZXcNViH.js +2 -0
  118. package/renderer/dist/assets/init-Gi6I4Gst.js +1 -0
  119. package/renderer/dist/assets/ishikawaDiagram-K3B6WC7H-C7Mx_qQk.js +70 -0
  120. package/renderer/dist/assets/journeyDiagram-COXZFDF6-fr62QoAt.js +139 -0
  121. package/renderer/dist/assets/kanban-definition-P3RFRI5V-J8zsabCe.js +89 -0
  122. package/renderer/dist/assets/katex-C5jXJg4s.js +257 -0
  123. package/renderer/dist/assets/linear-BmNdEtIi.js +1 -0
  124. package/renderer/dist/assets/main-ChNdnUvt.js +1132 -0
  125. package/renderer/dist/assets/main-nj0QR5kg.css +32 -0
  126. package/renderer/dist/assets/mermaid.core-CnYzvFkz.js +314 -0
  127. package/renderer/dist/assets/mindmap-definition-LZFPQGKD-Bfcxc7PM.js +96 -0
  128. package/renderer/dist/assets/ordinal-Cboi1Yqb.js +1 -0
  129. package/renderer/dist/assets/pegDiagram-BGZESJAR-CwUJOq6X.js +1 -0
  130. package/renderer/dist/assets/pieDiagram-CAPJLFHJ-BrwMmqfC.js +39 -0
  131. package/renderer/dist/assets/product-name-CTKLYNWY.js +40 -0
  132. package/renderer/dist/assets/quadrantDiagram-GDMTTRAM-BN4Stoj-.js +7 -0
  133. package/renderer/dist/assets/railroadDiagram-SM67HX2B-CPZ5bbeR.js +1 -0
  134. package/renderer/dist/assets/requirementDiagram-X7JNWC4A-CgRnimVe.js +84 -0
  135. package/renderer/dist/assets/sankeyDiagram-UM26HJRW-Bt2rej__.js +40 -0
  136. package/renderer/dist/assets/sequenceDiagram-ZO4K6R2Y-Dd5nKe9G.js +169 -0
  137. package/renderer/dist/assets/sizeCapture-INFHLROL-usyNyXyh.js +1 -0
  138. package/renderer/dist/assets/stateDiagram-v2-TBUQTH76-CRzUBb0u.js +291 -0
  139. package/renderer/dist/assets/swimlanes-N4OXWK64-C1GJvMS0.js +1 -0
  140. package/renderer/dist/assets/swimlanesDiagram-K3J5GTZL-Cy4Av2_p.js +8 -0
  141. package/renderer/dist/assets/timeline-definition-YOQAKGHF-caeyPlcc.js +120 -0
  142. package/renderer/dist/assets/usecaseDiagram-VIAY4XPW-BN_SV6PC.js +370 -0
  143. package/renderer/dist/assets/vennDiagram-BLWOH2XV-BLGuaUX-.js +34 -0
  144. package/renderer/dist/assets/wardleyDiagram-YMQ3BMBF-Da0cJeNc.js +78 -0
  145. package/renderer/dist/assets/xychartDiagram-TAQBALBS-cGfUffMk.js +7 -0
  146. package/renderer/dist/corner-tag.html +13 -0
  147. package/renderer/dist/emulator/audio-rules.mjs +74 -0
  148. package/renderer/dist/emulator/data/compression/README.md +11 -0
  149. package/renderer/dist/emulator/data/compression/extract7z.js +1 -0
  150. package/renderer/dist/emulator/data/compression/extractzip.js +1 -0
  151. package/renderer/dist/emulator/data/compression/libunrar.js +519 -0
  152. package/renderer/dist/emulator/data/compression/libunrar.wasm +0 -0
  153. package/renderer/dist/emulator/data/cores/README.md +22 -0
  154. package/renderer/dist/emulator/data/cores/mgba-legacy-wasm.data +0 -0
  155. package/renderer/dist/emulator/data/cores/mgba-thread-legacy-wasm.data +0 -0
  156. package/renderer/dist/emulator/data/cores/mgba-thread-wasm.data +0 -0
  157. package/renderer/dist/emulator/data/cores/mgba-wasm.data +0 -0
  158. package/renderer/dist/emulator/data/cores/package.json +65 -0
  159. package/renderer/dist/emulator/data/cores/reports/mgba.json +1 -0
  160. package/renderer/dist/emulator/data/emulator.css +1614 -0
  161. package/renderer/dist/emulator/data/loader.js +170 -0
  162. package/renderer/dist/emulator/data/localization/README.md +63 -0
  163. package/renderer/dist/emulator/data/localization/af-FR.json +339 -0
  164. package/renderer/dist/emulator/data/localization/ar-AR.json +301 -0
  165. package/renderer/dist/emulator/data/localization/ben-BEN.json +301 -0
  166. package/renderer/dist/emulator/data/localization/de-GER.json +301 -0
  167. package/renderer/dist/emulator/data/localization/el-GR.json +301 -0
  168. package/renderer/dist/emulator/data/localization/en-US.json +339 -0
  169. package/renderer/dist/emulator/data/localization/es-ES.json +310 -0
  170. package/renderer/dist/emulator/data/localization/fa-AF.json +310 -0
  171. package/renderer/dist/emulator/data/localization/hi-HI.json +301 -0
  172. package/renderer/dist/emulator/data/localization/it-IT.json +302 -0
  173. package/renderer/dist/emulator/data/localization/ja-JA.json +301 -0
  174. package/renderer/dist/emulator/data/localization/jv-JV.json +301 -0
  175. package/renderer/dist/emulator/data/localization/ko-KO.json +336 -0
  176. package/renderer/dist/emulator/data/localization/pt-BR.json +361 -0
  177. package/renderer/dist/emulator/data/localization/retroarch.json +617 -0
  178. package/renderer/dist/emulator/data/localization/ro-RO.json +310 -0
  179. package/renderer/dist/emulator/data/localization/ru-RU.json +301 -0
  180. package/renderer/dist/emulator/data/localization/tr-TR.json +310 -0
  181. package/renderer/dist/emulator/data/localization/vi-VN.json +302 -0
  182. package/renderer/dist/emulator/data/localization/zh-CN.json +351 -0
  183. package/renderer/dist/emulator/data/src/GameManager.js +464 -0
  184. package/renderer/dist/emulator/data/src/compression.js +142 -0
  185. package/renderer/dist/emulator/data/src/emulator.js +6158 -0
  186. package/renderer/dist/emulator/data/src/gamepad.js +167 -0
  187. package/renderer/dist/emulator/data/src/nipplejs.js +1 -0
  188. package/renderer/dist/emulator/data/src/shaders.js +236 -0
  189. package/renderer/dist/emulator/data/src/socket.io.min.js +7 -0
  190. package/renderer/dist/emulator/data/src/storage.js +125 -0
  191. package/renderer/dist/emulator/data/version.json +5 -0
  192. package/renderer/dist/emulator/host.js +297 -0
  193. package/renderer/dist/emulator/index.html +28 -0
  194. package/renderer/dist/emulator/provenance.json +6 -0
  195. package/renderer/dist/index.html +16 -3
  196. package/scripts/after-install.mjs +14 -0
  197. package/scripts/approval-server.sh +31 -7
  198. package/scripts/before-publish.mjs +12 -10
  199. package/shared/agent-import.mjs +3 -1
  200. package/shared/agents.d.mts +1 -0
  201. package/shared/bridge-map.mjs +19 -0
  202. package/shared/claude-commands.generated.mjs +8 -6
  203. package/shared/claude-models.generated.mjs +10 -8
  204. package/shared/codex-modes.mjs +1 -1
  205. package/shared/corner-tag.d.mts +14 -0
  206. package/shared/corner-tag.mjs +141 -0
  207. package/shared/demo-world.mjs +1 -1
  208. package/shared/engines.mjs +20 -5
  209. package/shared/fresh-user-home.mjs +12 -1
  210. package/shared/harness-definitions.mjs +103 -0
  211. package/shared/instruction-defaults.json +1 -1
  212. package/shared/notify-rules.d.mts +25 -0
  213. package/shared/notify-rules.mjs +19 -0
  214. package/shared/project-folder-check.mjs +3 -3
  215. package/shared/provider-commands.mjs +10 -2
  216. package/shared/rank.d.mts +2 -0
  217. package/shared/rank.mjs +50 -0
  218. package/shared/relay-address.mjs +6 -0
  219. package/shared/relay-crypto.mjs +165 -0
  220. package/shared/runs-on.d.mts +10 -0
  221. package/shared/runs-on.mjs +55 -0
  222. package/shared/shortcuts.mjs +11 -5
  223. package/shared/spawn-trouble.mjs +58 -7
  224. package/shared/terminal-input.d.mts +1 -0
  225. package/shared/terminal-input.mjs +30 -0
  226. package/shared/terminal-keys.d.mts +1 -0
  227. package/shared/terminal-keys.mjs +16 -0
  228. package/shared/terminal-size.d.mts +4 -0
  229. package/shared/terminal-size.mjs +29 -0
  230. package/shared/usage.d.mts +3 -0
  231. package/shared/usage.mjs +7 -0
  232. package/shared/where-it-runs-from.d.mts +43 -0
  233. package/shared/where-it-runs-from.mjs +155 -0
  234. package/shared/work-items.mjs +28 -2
  235. package/shared/work-lines.mjs +1 -1
  236. package/shared/xterm-invalid-range.d.mts +2 -0
  237. package/shared/xterm-invalid-range.mjs +58 -0
  238. package/renderer/dist/assets/index-B-2Az952.css +0 -32
  239. package/renderer/dist/assets/index-D6qncgai.js +0 -1168
@@ -0,0 +1,464 @@
1
+ class EJS_GameManager {
2
+ constructor(Module, EJS) {
3
+ this.EJS = EJS;
4
+ this.Module = Module;
5
+ this.FS = this.Module.FS;
6
+ this.functions = {
7
+ restart: this.Module.cwrap("system_restart", "", []),
8
+ saveStateInfo: this.Module.cwrap("save_state_info", "string", []),
9
+ loadState: this.Module.cwrap("load_state", "number", ["string", "number"]),
10
+ screenshot: this.Module.cwrap("cmd_take_screenshot", "", []),
11
+ simulateInput: this.Module.cwrap("simulate_input", "null", ["number", "number", "number"]),
12
+ toggleMainLoop: this.Module.cwrap("toggleMainLoop", "null", ["number"]),
13
+ getCoreOptions: this.Module.cwrap("get_core_options", "string", []),
14
+ setVariable: this.Module.cwrap("ejs_set_variable", "null", ["string", "string"]),
15
+ setCheat: this.Module.cwrap("set_cheat", "null", ["number", "number", "string"]),
16
+ resetCheat: this.Module.cwrap("reset_cheat", "null", []),
17
+ toggleShader: this.Module.cwrap("shader_enable", "null", ["number"]),
18
+ getDiskCount: this.Module.cwrap("get_disk_count", "number", []),
19
+ getCurrentDisk: this.Module.cwrap("get_current_disk", "number", []),
20
+ setCurrentDisk: this.Module.cwrap("set_current_disk", "null", ["number"]),
21
+ getSaveFilePath: this.Module.cwrap("save_file_path", "string", []),
22
+ saveSaveFiles: this.Module.cwrap("cmd_savefiles", "", []),
23
+ supportsStates: this.Module.cwrap("supports_states", "number", []),
24
+ loadSaveFiles: this.Module.cwrap("refresh_save_files", "null", []),
25
+ toggleFastForward: this.Module.cwrap("toggle_fastforward", "null", ["number"]),
26
+ setFastForwardRatio: this.Module.cwrap("set_ff_ratio", "null", ["number"]),
27
+ toggleRewind: this.Module.cwrap("toggle_rewind", "null", ["number"]),
28
+ setRewindGranularity: this.Module.cwrap("set_rewind_granularity", "null", ["number"]),
29
+ toggleSlowMotion: this.Module.cwrap("toggle_slow_motion", "null", ["number"]),
30
+ setSlowMotionRatio: this.Module.cwrap("set_sm_ratio", "null", ["number"]),
31
+ getFrameNum: this.Module.cwrap("get_current_frame_count", "number", [""]),
32
+ setVSync: this.Module.cwrap("set_vsync", "null", ["number"]),
33
+ setVideoRoation: this.Module.cwrap("set_video_rotation", "null", ["number"]),
34
+ getVideoDimensions: this.Module.cwrap("get_video_dimensions", "number", ["string"]),
35
+ setKeyboardEnabled: this.Module.cwrap("ejs_set_keyboard_enabled", "null", ["number"])
36
+ }
37
+
38
+ this.writeFile("/home/web_user/.config/retroarch/retroarch.cfg", this.getRetroArchCfg());
39
+
40
+ this.writeConfigFile();
41
+ this.initShaders();
42
+ this.setupPreLoadSettings();
43
+
44
+ this.EJS.on("exit", () => {
45
+ if (!this.EJS.failedToStart) {
46
+ this.saveSaveFiles();
47
+ this.functions.restart();
48
+ this.saveSaveFiles();
49
+ }
50
+ this.toggleMainLoop(0);
51
+ this.FS.unmount("/data/saves");
52
+ setTimeout(() => {
53
+ try {
54
+ this.Module.abort();
55
+ } catch(e) {
56
+ console.warn(e);
57
+ };
58
+ }, 1000);
59
+ })
60
+ }
61
+ setupPreLoadSettings() {
62
+ this.Module.callbacks.setupCoreSettingFile = (filePath) => {
63
+ if (this.EJS.debug) console.log("Setting up core settings with path:", filePath);
64
+ this.writeFile(filePath, this.EJS.getCoreSettings());
65
+ }
66
+ }
67
+ mountFileSystems() {
68
+ return new Promise(async resolve => {
69
+ this.mkdir("/data");
70
+ this.mkdir("/data/saves");
71
+ this.FS.mount(this.FS.filesystems.IDBFS, { autoPersist: true }, "/data/saves");
72
+ this.FS.syncfs(true, resolve);
73
+ });
74
+ }
75
+ writeConfigFile() {
76
+ if (!this.EJS.defaultCoreOpts.file || !this.EJS.defaultCoreOpts.settings) {
77
+ return;
78
+ }
79
+ let output = "";
80
+ for (const k in this.EJS.defaultCoreOpts.settings) {
81
+ output += k + ' = "' + this.EJS.defaultCoreOpts.settings[k] + '"\n';
82
+ }
83
+
84
+ this.writeFile("/home/web_user/retroarch/userdata/config/" + this.EJS.defaultCoreOpts.file, output);
85
+ }
86
+ loadExternalFiles() {
87
+ return new Promise(async (resolve, reject) => {
88
+ if (this.EJS.config.externalFiles && this.EJS.config.externalFiles.constructor.name === "Object") {
89
+ for (const key in this.EJS.config.externalFiles) {
90
+ await new Promise(done => {
91
+ this.EJS.downloadFile(this.EJS.config.externalFiles[key], null, true, { responseType: "arraybuffer", method: "GET" }).then(async (res) => {
92
+ if (res === -1) {
93
+ if (this.EJS.debug) console.warn("Failed to fetch file from '" + this.EJS.config.externalFiles[key] + "'. Make sure the file exists.");
94
+ return done();
95
+ }
96
+ let path = key;
97
+ if (key.trim().endsWith("/")) {
98
+ const invalidCharacters = /[#<$+%>!`&*'|{}/\\?"=@:^\r\n]/ig;
99
+ let name = this.EJS.config.externalFiles[key].split("/").pop().split("#")[0].split("?")[0].replace(invalidCharacters, "").trim();
100
+ if (!name) return done();
101
+ const files = await this.EJS.checkCompression(new Uint8Array(res.data), this.EJS.localization("Decompress Game Assets"));
102
+ if (files["!!notCompressedData"]) {
103
+ path += name;
104
+ } else {
105
+ for (const k in files) {
106
+ this.writeFile(path + k, files[k]);
107
+ }
108
+ return done();
109
+ }
110
+ }
111
+ try {
112
+ this.writeFile(path, res.data);
113
+ } catch(e) {
114
+ if (this.EJS.debug) console.warn("Failed to write file to '" + path + "'. Make sure there are no conflicting files.");
115
+ }
116
+ done();
117
+ });
118
+ })
119
+ }
120
+ }
121
+ resolve();
122
+ });
123
+ }
124
+ writeFile(path, data) {
125
+ const parts = path.split("/");
126
+ let current = "/";
127
+ for (let i = 0; i < parts.length - 1; i++) {
128
+ if (!parts[i].trim()) continue;
129
+ current += parts[i] + "/";
130
+ this.mkdir(current);
131
+ }
132
+ this.FS.writeFile(path, data);
133
+ }
134
+ mkdir(path) {
135
+ try {
136
+ this.FS.mkdir(path);
137
+ } catch(e) {}
138
+ }
139
+ getRetroArchCfg() {
140
+ let cfg = "autosave_interval = 60\n" +
141
+ "screenshot_directory = \"/\"\n" +
142
+ "block_sram_overwrite = false\n" +
143
+ "video_gpu_screenshot = false\n" +
144
+ "audio_latency = 64\n" +
145
+ "video_top_portrait_viewport = true\n" +
146
+ "video_vsync = true\n" +
147
+ "video_smooth = false\n" +
148
+ "fastforward_ratio = 3.0\n" +
149
+ "slowmotion_ratio = 3.0\n" +
150
+ (this.EJS.rewindEnabled ? "rewind_enable = true\n" : "") +
151
+ (this.EJS.rewindEnabled ? "rewind_granularity = 6\n" : "") +
152
+ "savefile_directory = \"/data/saves\"\n";
153
+
154
+ if (this.EJS.retroarchOpts && Array.isArray(this.EJS.retroarchOpts)) {
155
+ this.EJS.retroarchOpts.forEach(option => {
156
+ let selected = this.EJS.preGetSetting(option.name);
157
+ console.log(selected);
158
+ if (!selected) {
159
+ selected = option.default;
160
+ }
161
+ const value = option.isString === false ? selected : '"' + selected + '"';
162
+ cfg += option.name + " = " + value + "\n"
163
+ })
164
+ }
165
+ return cfg;
166
+ }
167
+ initShaders() {
168
+ if (!this.EJS.config.shaders) return;
169
+ this.mkdir("/shader");
170
+ for (const shaderFileName in this.EJS.config.shaders) {
171
+ const shader = this.EJS.config.shaders[shaderFileName];
172
+ if (typeof shader === "string") {
173
+ this.FS.writeFile(`/shader/${shaderFileName}`, shader);
174
+ }
175
+ }
176
+ }
177
+ clearEJSResetTimer() {
178
+ if (this.EJS.resetTimeout) {
179
+ clearTimeout(this.EJS.resetTimeout);
180
+ delete this.EJS.resetTimeout;
181
+ }
182
+ }
183
+ restart() {
184
+ this.clearEJSResetTimer();
185
+ this.functions.restart();
186
+ }
187
+ getState() {
188
+ const state = this.functions.saveStateInfo().split("|");
189
+ if (state[2] !== "1") {
190
+ console.error(state[0]);
191
+ throw new Error(state[0]);
192
+ }
193
+ const size = parseInt(state[0]);
194
+ const dataStart = parseInt(state[1]);
195
+ const data = this.Module.HEAPU8.subarray(dataStart, dataStart + size);
196
+ return new Uint8Array(data);
197
+ }
198
+ loadState(state) {
199
+ try {
200
+ this.FS.unlink("game.state");
201
+ } catch(e) {}
202
+ this.FS.writeFile("/game.state", state);
203
+ this.clearEJSResetTimer();
204
+ this.functions.loadState("game.state", 0);
205
+ setTimeout(() => {
206
+ try {
207
+ this.FS.unlink("game.state");
208
+ } catch(e) {}
209
+ }, 5000)
210
+ }
211
+ screenshot() {
212
+ try {
213
+ this.FS.unlink("screenshot.png");
214
+ } catch(e) {}
215
+ this.functions.screenshot();
216
+ return new Promise(async resolve => {
217
+ while (1) {
218
+ try {
219
+ this.FS.stat("/screenshot.png");
220
+ return resolve(this.FS.readFile("/screenshot.png"));
221
+ } catch(e) {}
222
+ await new Promise(res => setTimeout(res, 50));
223
+ }
224
+ })
225
+ }
226
+ quickSave(slot) {
227
+ if (!slot) slot = 1;
228
+ let name = slot + "-quick.state";
229
+ try {
230
+ this.FS.unlink(name);
231
+ } catch(e) {}
232
+ try {
233
+ let data = this.getState();
234
+ this.FS.writeFile("/" + name, data);
235
+ } catch(e) {
236
+ return false;
237
+ }
238
+ return true;
239
+ }
240
+ quickLoad(slot) {
241
+ if (!slot) slot = 1;
242
+ (async () => {
243
+ let name = slot + "-quick.state";
244
+ this.clearEJSResetTimer();
245
+ this.functions.loadState(name, 0);
246
+ })();
247
+ }
248
+ simulateInput(player, index, value) {
249
+ if (this.EJS.isNetplay) {
250
+ this.EJS.netplay.simulateInput(player, index, value);
251
+ return;
252
+ }
253
+ if ([24, 25, 26, 27, 28, 29].includes(index)) {
254
+ if (index === 24 && value === 1) {
255
+ const slot = this.EJS.settings["save-state-slot"] ? this.EJS.settings["save-state-slot"] : "1";
256
+ if (this.quickSave(slot)) {
257
+ this.EJS.displayMessage(this.EJS.localization("SAVED STATE TO SLOT") + " " + slot);
258
+ } else {
259
+ this.EJS.displayMessage(this.EJS.localization("FAILED TO SAVE STATE"));
260
+ }
261
+ }
262
+ if (index === 25 && value === 1) {
263
+ const slot = this.EJS.settings["save-state-slot"] ? this.EJS.settings["save-state-slot"] : "1";
264
+ this.quickLoad(slot);
265
+ this.EJS.displayMessage(this.EJS.localization("LOADED STATE FROM SLOT") + " " + slot);
266
+ }
267
+ if (index === 26 && value === 1) {
268
+ let newSlot;
269
+ try {
270
+ newSlot = parseFloat(this.EJS.settings["save-state-slot"] ? this.EJS.settings["save-state-slot"] : "1") + 1;
271
+ } catch(e) {
272
+ newSlot = 1;
273
+ }
274
+ if (newSlot > 9) newSlot = 1;
275
+ this.EJS.displayMessage(this.EJS.localization("SET SAVE STATE SLOT TO") + " " + newSlot);
276
+ this.EJS.changeSettingOption("save-state-slot", newSlot.toString());
277
+ }
278
+ if (index === 27) {
279
+ this.functions.toggleFastForward(this.EJS.isFastForward ? !value : value);
280
+ }
281
+ if (index === 29) {
282
+ this.functions.toggleSlowMotion(this.EJS.isSlowMotion ? !value : value);
283
+ }
284
+ if (index === 28) {
285
+ if (this.EJS.rewindEnabled) {
286
+ this.functions.toggleRewind(value);
287
+ }
288
+ }
289
+ return;
290
+ }
291
+ this.functions.simulateInput(player, index, value);
292
+ }
293
+ getFileNames() {
294
+ if (this.EJS.getCore() === "picodrive") {
295
+ return ["bin", "gen", "smd", "md", "32x", "cue", "iso", "sms", "68k", "chd"];
296
+ } else {
297
+ return ["toc", "ccd", "exe", "pbp", "chd", "img", "bin", "iso"];
298
+ }
299
+ }
300
+ createCueFile(fileNames) {
301
+ try {
302
+ if (fileNames.length > 1) {
303
+ fileNames = fileNames.filter((item) => {
304
+ return this.getFileNames().includes(item.split(".").pop().toLowerCase());
305
+ })
306
+ fileNames = fileNames.sort((a, b) => {
307
+ if (isNaN(a.charAt()) || isNaN(b.charAt())) throw new Error("Incorrect file name format");
308
+ return (parseInt(a.charAt()) > parseInt(b.charAt())) ? 1 : -1;
309
+ })
310
+ }
311
+ } catch(e) {
312
+ if (fileNames.length > 1) {
313
+ console.warn("Could not auto-create cue file(s).");
314
+ return null;
315
+ }
316
+ }
317
+ for (let i = 0; i < fileNames.length; i++) {
318
+ if (fileNames[i].split(".").pop().toLowerCase() === "ccd") {
319
+ console.warn("Did not auto-create cue file(s). Found a ccd.");
320
+ return null;
321
+ }
322
+ }
323
+ if (fileNames.length === 0) {
324
+ console.warn("Could not auto-create cue file(s).");
325
+ return null;
326
+ }
327
+ let baseFileName = fileNames[0].split("/").pop();
328
+ if (baseFileName.includes(".")) {
329
+ baseFileName = baseFileName.substring(0, baseFileName.length - baseFileName.split(".").pop().length - 1);
330
+ }
331
+ for (let i = 0; i < fileNames.length; i++) {
332
+ const contents = " FILE \"" + fileNames[i] + "\" BINARY\n TRACK 01 MODE1/2352\n INDEX 01 00:00:00";
333
+ this.FS.writeFile("/" + baseFileName + "-" + i + ".cue", contents);
334
+ }
335
+ if (fileNames.length > 1) {
336
+ let contents = "";
337
+ for (let i = 0; i < fileNames.length; i++) {
338
+ contents += "/" + baseFileName + "-" + i + ".cue\n";
339
+ }
340
+ this.FS.writeFile("/" + baseFileName + ".m3u", contents);
341
+ }
342
+ return (fileNames.length === 1) ? baseFileName + "-0.cue" : baseFileName + ".m3u";
343
+ }
344
+ loadPpssppAssets() {
345
+ return new Promise(resolve => {
346
+ this.EJS.downloadFile("cores/ppsspp-assets.zip", null, false, { responseType: "arraybuffer", method: "GET" }).then((res) => {
347
+ this.EJS.checkCompression(new Uint8Array(res.data), this.EJS.localization("Decompress Game Data")).then((pspassets) => {
348
+ if (pspassets === -1) {
349
+ this.EJS.textElem.innerText = this.localization("Network Error");
350
+ this.EJS.textElem.style.color = "red";
351
+ return;
352
+ }
353
+ this.mkdir("/PPSSPP");
354
+
355
+ for (const file in pspassets) {
356
+ const data = pspassets[file];
357
+ const path = "/PPSSPP/" + file;
358
+ const paths = path.split("/");
359
+ let cp = "";
360
+ for (let i = 0; i < paths.length - 1; i++) {
361
+ if (paths[i] === "") continue;
362
+ cp += "/" + paths[i];
363
+ if (!this.FS.analyzePath(cp).exists) {
364
+ this.FS.mkdir(cp);
365
+ }
366
+ }
367
+ if (!path.endsWith("/")) {
368
+ this.FS.writeFile(path, data);
369
+ }
370
+ }
371
+ resolve();
372
+ })
373
+ });
374
+ })
375
+ }
376
+ setVSync(enabled) {
377
+ this.functions.setVSync(enabled);
378
+ }
379
+ toggleMainLoop(playing) {
380
+ this.functions.toggleMainLoop(playing);
381
+ }
382
+ getCoreOptions() {
383
+ return this.functions.getCoreOptions();
384
+ }
385
+ setVariable(option, value) {
386
+ this.functions.setVariable(option, value);
387
+ }
388
+ setCheat(index, enabled, code) {
389
+ this.functions.setCheat(index, enabled, code);
390
+ }
391
+ resetCheat() {
392
+ this.functions.resetCheat();
393
+ }
394
+ toggleShader(active) {
395
+ this.functions.toggleShader(active);
396
+ }
397
+ getDiskCount() {
398
+ return this.functions.getDiskCount();
399
+ }
400
+ getCurrentDisk() {
401
+ return this.functions.getCurrentDisk();
402
+ }
403
+ setCurrentDisk(disk) {
404
+ this.functions.setCurrentDisk(disk);
405
+ }
406
+ getSaveFilePath() {
407
+ return this.functions.getSaveFilePath();
408
+ }
409
+ saveSaveFiles() {
410
+ this.functions.saveSaveFiles();
411
+ this.EJS.callEvent("saveSaveFiles", this.getSaveFile(false));
412
+ //this.FS.syncfs(false, () => {});
413
+ }
414
+ supportsStates() {
415
+ return !!this.functions.supportsStates();
416
+ }
417
+ getSaveFile(save) {
418
+ if (save !== false) {
419
+ this.saveSaveFiles();
420
+ }
421
+ const exists = this.FS.analyzePath(this.getSaveFilePath()).exists;
422
+ return (exists ? this.FS.readFile(this.getSaveFilePath()) : null);
423
+ }
424
+ loadSaveFiles() {
425
+ this.clearEJSResetTimer();
426
+ this.functions.loadSaveFiles();
427
+ }
428
+ setFastForwardRatio(ratio) {
429
+ this.functions.setFastForwardRatio(ratio);
430
+ }
431
+ toggleFastForward(active) {
432
+ this.functions.toggleFastForward(active);
433
+ }
434
+ setSlowMotionRatio(ratio) {
435
+ this.functions.setSlowMotionRatio(ratio);
436
+ }
437
+ toggleSlowMotion(active) {
438
+ this.functions.toggleSlowMotion(active);
439
+ }
440
+ setRewindGranularity(value) {
441
+ this.functions.setRewindGranularity(value);
442
+ }
443
+ getFrameNum() {
444
+ return this.functions.getFrameNum();
445
+ }
446
+ setVideoRotation(rotation) {
447
+ this.functions.setVideoRoation(rotation);
448
+ }
449
+ getVideoDimensions(type) {
450
+ try {
451
+ return this.functions.getVideoDimensions(type);
452
+ } catch(e) {
453
+ console.warn(e);
454
+ }
455
+ }
456
+ setKeyboardEnabled(enabled) {
457
+ this.functions.setKeyboardEnabled(enabled === true ? 1 : 0);
458
+ }
459
+ setAltKeyEnabled(enabled) {
460
+ this.functions.setKeyboardEnabled(enabled === true ? 3 : 2);
461
+ }
462
+ }
463
+
464
+ window.EJS_GameManager = EJS_GameManager;
@@ -0,0 +1,142 @@
1
+ class EJS_COMPRESSION {
2
+ constructor(EJS) {
3
+ this.EJS = EJS;
4
+ }
5
+ isCompressed(data) { //https://www.garykessler.net/library/file_sigs.html
6
+ //todo. Use hex instead of numbers
7
+ if ((data[0] === 80 && data[1] === 75) && ((data[2] === 3 && data[3] === 4) || (data[2] === 5 && data[3] === 6) || (data[2] === 7 && data[3] === 8))) {
8
+ return "zip";
9
+ } else if (data[0] === 55 && data[1] === 122 && data[2] === 188 && data[3] === 175 && data[4] === 39 && data[5] === 28) {
10
+ return "7z";
11
+ } else if ((data[0] === 82 && data[1] === 97 && data[2] === 114 && data[3] === 33 && data[4] === 26 && data[5] === 7) && ((data[6] === 0) || (data[6] === 1 && data[7] == 0))) {
12
+ return "rar";
13
+ }
14
+ return null;
15
+ }
16
+ decompress(data, updateMsg, fileCbFunc) {
17
+ const compressed = this.isCompressed(data.slice(0, 10));
18
+ if (compressed === null) {
19
+ if (typeof fileCbFunc === "function") {
20
+ fileCbFunc("!!notCompressedData", data);
21
+ }
22
+ return new Promise(resolve => resolve({ "!!notCompressedData": data }));
23
+ }
24
+ return this.decompressFile(compressed, data, updateMsg, fileCbFunc);
25
+ }
26
+ getWorkerFile(method) {
27
+ return new Promise(async (resolve, reject) => {
28
+ let path, obj;
29
+ if (method === "7z") {
30
+ path = "compression/extract7z.js";
31
+ obj = "sevenZip";
32
+ } else if (method === "zip") {
33
+ path = "compression/extractzip.js";
34
+ obj = "zip";
35
+ } else if (method === "rar") {
36
+ path = "compression/libunrar.js";
37
+ obj = "rar";
38
+ }
39
+ const res = await this.EJS.downloadFile(path, null, false, { responseType: "text", method: "GET" });
40
+ if (res === -1) {
41
+ this.EJS.startGameError(this.EJS.localization("Network Error"));
42
+ return;
43
+ }
44
+ if (method === "rar") {
45
+ const res2 = await this.EJS.downloadFile("compression/libunrar.wasm", null, false, { responseType: "arraybuffer", method: "GET" });
46
+ if (res2 === -1) {
47
+ this.EJS.startGameError(this.EJS.localization("Network Error"));
48
+ return;
49
+ }
50
+ const path = URL.createObjectURL(new Blob([res2.data], { type: "application/wasm" }));
51
+ let script = `
52
+ let dataToPass = [];
53
+ Module = {
54
+ monitorRunDependencies: function(left) {
55
+ if (left == 0) {
56
+ setTimeout(function() {
57
+ unrar(dataToPass, null);
58
+ }, 100);
59
+ }
60
+ },
61
+ onRuntimeInitialized: function() {},
62
+ locateFile: function(file) {
63
+ console.log("locateFile");
64
+ return "` + path + `";
65
+ }
66
+ };
67
+ ` + res.data + `
68
+ let unrar = function(data, password) {
69
+ let cb = function(fileName, fileSize, progress) {
70
+ postMessage({ "t": 4, "current": progress, "total": fileSize, "name": fileName });
71
+ };
72
+ let rarContent = readRARContent(data.map(function(d) {
73
+ return {
74
+ name: d.name,
75
+ content: new Uint8Array(d.content)
76
+ }
77
+ }), password, cb)
78
+ let rec = function(entry) {
79
+ if (!entry) return;
80
+ if (entry.type === "file") {
81
+ postMessage({ "t": 2, "file": entry.fullFileName, "size": entry.fileSize, "data": entry.fileContent });
82
+ } else if (entry.type === "dir") {
83
+ Object.keys(entry.ls).forEach(function(k) {
84
+ rec(entry.ls[k]);
85
+ });
86
+ } else {
87
+ throw "Unknown type";
88
+ }
89
+ }
90
+ rec(rarContent);
91
+ postMessage({ "t": 1 });
92
+ return rarContent;
93
+ };
94
+ onmessage = function(data) {
95
+ dataToPass.push({ name: "test.rar", content: data.data });
96
+ };
97
+ `;
98
+ const blob = new Blob([script], {
99
+ type: "application/javascript"
100
+ })
101
+ resolve(blob);
102
+ } else {
103
+ const blob = new Blob([res.data], {
104
+ type: "application/javascript"
105
+ })
106
+ resolve(blob);
107
+ }
108
+ })
109
+ }
110
+ decompressFile(method, data, updateMsg, fileCbFunc) {
111
+ return new Promise(async callback => {
112
+ const file = await this.getWorkerFile(method);
113
+ const worker = new Worker(URL.createObjectURL(file));
114
+ const files = {};
115
+ worker.onmessage = (data) => {
116
+ if (!data.data) return;
117
+ //data.data.t/ 4=progress, 2 is file, 1 is zip done
118
+ if (data.data.t === 4) {
119
+ const pg = data.data;
120
+ const num = Math.floor(pg.current / pg.total * 100);
121
+ if (isNaN(num)) return;
122
+ const progress = " " + num.toString() + "%";
123
+ updateMsg(progress, true);
124
+ }
125
+ if (data.data.t === 2) {
126
+ if (typeof fileCbFunc === "function") {
127
+ fileCbFunc(data.data.file, data.data.data);
128
+ files[data.data.file] = true;
129
+ } else {
130
+ files[data.data.file] = data.data.data;
131
+ }
132
+ }
133
+ if (data.data.t === 1) {
134
+ callback(files);
135
+ }
136
+ }
137
+ worker.postMessage(data);
138
+ });
139
+ }
140
+ }
141
+
142
+ window.EJS_COMPRESSION = EJS_COMPRESSION;