From 4be5dadb24b9631208ff3a11764077c80ad7bc7d Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Mon, 17 Mar 2025 15:46:35 -0500 Subject: [PATCH] Prepping save file support --- public/emulator.html | 32 ++++++++++++++++++++++++++++++-- src/components/Emulator.tsx | 11 ++++++----- src/pages/games/index.tsx | 10 +++------- 3 files changed, 39 insertions(+), 14 deletions(-) diff --git a/public/emulator.html b/public/emulator.html index 2e93c50..221b75e 100644 --- a/public/emulator.html +++ b/public/emulator.html @@ -25,6 +25,7 @@ display: none !important; } + @@ -85,6 +86,29 @@ clearInterval(initInterval); } + const md5File = async path => { + const buffer = EJS_emulator.gameManager.FS.readFile(path); + const hash = await crypto.subtle.digest('SHA-256', buffer); + const hashArray = Array.from(new Uint8Array(hash)); + const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join(''); + return hashHex; + } + + const emulatorSave = async () => { + // First, we get the currently saved MD5 hash of all files in the save + // directory + const contents = EJS_emulator.gameManager.FS.readdir('/homeplay/saves').filter(f => !f.startsWith('.')); + const hashes = await Promise.all(contents.map(f => md5File(`/homeplay/saves/${f}`))); + EJS_emulator.gameManager.saveSaveFiles(); + const newHashes = await Promise.all(contents.map(f => md5File(`/homeplay/saves/${f}`))); + const changedFiles = contents.filter((f, i) => hashes[i] !== newHashes[i]); + console.log('Changed files', changedFiles); + + send({ + message: '' + }) + } + const send = data => { window.parent.postMessage(data, '*'); } @@ -107,6 +131,10 @@ EJS_emulator.setVolume(data.volume); break; + case 'save': + emulatorSave(); + break; + default: console.error('Unknown message', message); } @@ -142,11 +170,11 @@ } EJS_onSaveState = () => { - send({ message: 'save' }); + send({ message: 'save_state' }); } EJS_onLoadState = () => { - send({ message: 'load' }); + send({ message: 'load_state' }); } EJS_onGameStart = () => { diff --git a/src/components/Emulator.tsx b/src/components/Emulator.tsx index ea4bfd0..89be53e 100644 --- a/src/components/Emulator.tsx +++ b/src/components/Emulator.tsx @@ -18,15 +18,16 @@ type SendEmulatorMessageVolume = { type SendEmulatorMessage = ( SendEmulatorMessageInit | - SendEmulatorMessageVolume + SendEmulatorMessageVolume | + { message: 'save' } ); type ReceiveEmulatorMessage = ( { message: 'iframe_loaded' } | { message: 'start' } | { message: 'ready' } | - { message: 'save' } | - { message: 'load' } + { message: 'save_state' } | + { message: 'load_state' } ); export type EmulatorProps = { @@ -69,8 +70,8 @@ export const Emulator:React.FC = props => { case 'start': case 'ready': - case 'load': - case 'save': + case 'load_state': + case 'save_state': break; default: console.error('Invalid message received:', msg); diff --git a/src/pages/games/index.tsx b/src/pages/games/index.tsx index 76f16ee..4644130 100644 --- a/src/pages/games/index.tsx +++ b/src/pages/games/index.tsx @@ -7,12 +7,6 @@ import Error500, { Error500Props } from '../500'; import { extendFragment, includeFragment } from '@/lib/fragment'; import { Paginated, paginationQuery } from '@/lib/page'; -type Game = { - id: string; - name: string; - system: string; -}; - type PageProps = { games:Paginated|null; } | Error500Props; @@ -21,7 +15,9 @@ export const getServerSideProps: GetServerSideProps = async () => { try { const client = await apiClientGet(); const res = await client.query<{ games:Paginated }>({ - variables: { }, + variables: { + after: null, + }, query: gql` ${includeFragment(GameLightFragment)} query getGames {