-
-
Notifications
You must be signed in to change notification settings - Fork 388
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add WASM version of the engine (#9406)
- Loading branch information
Showing
107 changed files
with
541 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
########################################################################### | ||
# fheroes2: https://github.com/ihhub/fheroes2 # | ||
# Copyright (C) 2025 # | ||
# # | ||
# This program is free software; you can redistribute it and/or modify # | ||
# it under the terms of the GNU General Public License as published by # | ||
# the Free Software Foundation; either version 2 of the License, or # | ||
# (at your option) any later version. # | ||
# # | ||
# This program is distributed in the hope that it will be useful, # | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of # | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # | ||
# GNU General Public License for more details. # | ||
# # | ||
# You should have received a copy of the GNU General Public License # | ||
# along with this program; if not, write to the # | ||
# Free Software Foundation, Inc., # | ||
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # | ||
########################################################################### | ||
|
||
# Options: | ||
# | ||
# FHEROES2_STRICT_COMPILATION: build in strict compilation mode (turns warnings into errors) | ||
# FHEROES2_WITH_DEBUG: build in debug mode | ||
# FHEROES2_DATA: set the built-in path to the fheroes2 data directory (e.g. /usr/share/fheroes2) | ||
|
||
.PHONY: all clean translations | ||
|
||
all: fheroes2.js | ||
|
||
fheroes2.js: translations | ||
$(MAKE) -C src/dist PLATFORM=emscripten | ||
cp src/dist/fheroes2-ems/fheroes2.data . | ||
cp src/dist/fheroes2-ems/fheroes2.js . | ||
cp src/dist/fheroes2-ems/fheroes2.wasm . | ||
|
||
translations: | ||
$(MAKE) -C files/lang | ||
|
||
clean: | ||
$(MAKE) -C src/dist clean | ||
$(MAKE) -C files/lang clean | ||
rm -f fheroes2.data fheroes2.js fheroes2.wasm |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,210 @@ | ||
<html lang="en"> | ||
<head> | ||
<title>fheroes2</title> | ||
<link rel="preconnect" href="https://fonts.googleapis.com"> | ||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | ||
<link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel="stylesheet"> | ||
<script src="https://cdnjs.cloudflare.com/ajax/libs/progress.js/0.1.0/progress.min.js" integrity="sha512-CklrzCqwODBOEJHJq73SZrgWC7xcxssgg5M1xokosfDDz2/nLTCuMDyc51gbJtb8DriV4EYjJSlklPH5Ejn9XA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> | ||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/progress.js/0.1.0/progressjs.min.css" integrity="sha512-ovRFHsWpnYUBNZd/8CmbaWAKBDO8xb0l5Y8PdIae1O5RXO2QyU3CZGNzuYuE0CQHKazIzWMQpnTn26WpPjexfw==" crossorigin="anonymous" referrerpolicy="no-referrer" /> | ||
<style> | ||
body { margin: 0; height: 0; font-family: "Roboto", serif;} | ||
#canvas { | ||
height: 100vh; | ||
width: 100vw; | ||
display: block; | ||
margin: 0 auto; | ||
background: url(./fheroes2.jpeg) center center; | ||
background-size: cover; | ||
position: absolute; | ||
z-index: 10; | ||
} | ||
#uploader, #launcher { | ||
z-index: 100; | ||
position: absolute; | ||
color: #fff; | ||
font-size: 30px; | ||
text-stroke: 1px #000; | ||
-webkit-text-stroke: 1px #000; | ||
height: 100vh; | ||
width: 100vw; | ||
} | ||
#launcher { | ||
display: none; | ||
text-stroke: 1px #fff; | ||
-webkit-text-stroke: 1px #fff; | ||
} | ||
#uploader input[type=file] { | ||
display: none | ||
} | ||
#uploader label { | ||
text-align: center; | ||
display: block; | ||
cursor: pointer; | ||
height: 100vh; | ||
width: 100vw; | ||
position: absolute; | ||
} | ||
#uploader label span { | ||
padding: 10vh 0 0 0; | ||
display: block; | ||
} | ||
#launcher button { | ||
font-size: 30px; | ||
} | ||
#launcher .buttons { | ||
text-align: center; | ||
padding: 10vh 0 0 0; | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
<canvas id="canvas" width="640" height="400"></canvas> | ||
<div id="uploader"> | ||
<label> | ||
<span>Click to select your Heroes 2 folder</span> | ||
<input | ||
type="file" | ||
directory="directory" | ||
multiple | ||
webkitdirectory="webkitdirectory" | ||
id="files" | ||
/> | ||
</label> | ||
</div> | ||
<div id="launcher"> | ||
<div class="buttons"> | ||
<button onclick="Module.startGame()">Start game</button> | ||
<button onclick="Module.deleteFiles()">Delete files</button> | ||
</div> | ||
</div> | ||
<script> | ||
const S_IFMT = 61440; /* 0x0170000 type of file */ | ||
const S_IFDIR = 16384; /* 0x0040000 directory */ | ||
const progressBar = progressJs("#canvas").setOptions({ | ||
theme: 'blueOverlayRadiusWithPercentBar', | ||
overlayMode: true, | ||
considerTransition: true | ||
}); | ||
const canvas = document.querySelector('canvas'); | ||
canvas.oncontextmenu = event => event.preventDefault(); | ||
Object.assign(window, { Module: { | ||
preRun: [ | ||
() => Object.assign(window.ENV, { | ||
FHEROES2_DATA: `/fheroes2/data`, | ||
HOME: '/fheroes2' | ||
}), | ||
() => { | ||
addRunDependency('syncfs'); | ||
FS.mkdir('/fheroes2'); | ||
FS.mount(IDBFS, { root: '/' }, '/fheroes2'); | ||
FS.syncfs(true, (err) => { | ||
if (err) throw err; | ||
try { | ||
if (Object.keys(FS.lookupPath(`${ENV.FHEROES2_DATA}`)).length === 0) return; | ||
document.querySelector('#uploader').style.display = 'none'; | ||
document.querySelector('#launcher').style.display = 'block'; | ||
} | ||
catch (ignore) { | ||
FS.mkdir(`${ENV.FHEROES2_DATA}`); | ||
} | ||
}); | ||
}, | ||
() => { | ||
document.querySelector('input[type=file]').addEventListener('input', e => { | ||
const files = [...e.target.files]; | ||
const requiredFiles = ['data/HEROES2.AGG', 'data/HEROES2X.AGG'] | ||
if (files.length === 1) return Module.clearInput('zip archives are not supported yet, sorry'); | ||
if (files.length > 3000) return Module.clearInput('wrong directory, or your maps collection is really awesome.'); | ||
const requiredResolved = files.filter(({ webkitRelativePath: path }) => | ||
requiredFiles.some(rq => path.toLocaleLowerCase().endsWith(rq.toLocaleLowerCase()))).length === 2; | ||
if (!requiredResolved) return Module.clearInput('wrong directory'); | ||
const whitListed = ['data', 'heroes2', 'maps', 'music']; | ||
files.filter(file => { | ||
const [fileName, ...path] = file.webkitRelativePath.split('/').reverse(); | ||
if (fileName.startsWith('.')) return false; | ||
return path | ||
.map(folder => folder.toLocaleLowerCase()) | ||
.some(folder => whitListed.includes(folder)) | ||
}).reduce((uploaded, file, _ignore, queue) => { | ||
const [fileName, ...path] = file.webkitRelativePath.split('/').reverse(); | ||
const [ignore, ...relativePath] = path.reverse(); | ||
Module.mkdirWithParents(`${ENV.FHEROES2_DATA}/${relativePath.join('/')}`); | ||
|
||
const reader = new FileReader(); | ||
reader.addEventListener('error', console.error); | ||
reader.addEventListener('loadend', ({ target: { result } }) => { | ||
FS.writeFile(`${ENV.FHEROES2_DATA}/${relativePath.join('/')}/${fileName}`, new Uint8Array(result), { | ||
encoding: 'binary' | ||
}); | ||
uploaded.push(file); | ||
if (uploaded.length === queue.length) { | ||
FS.syncfs(false, err => { | ||
if (err) return Module.clearInput('Failed to sync FS'); | ||
document.querySelector('#uploader').style.display = 'none'; | ||
document.querySelector('#launcher').style.display = 'block'; | ||
}) | ||
} | ||
}); | ||
reader.readAsArrayBuffer(file); | ||
return uploaded; | ||
}, []); | ||
}) | ||
} | ||
], | ||
clearInput: (msg = '') => { | ||
document.querySelector('input[type=file]').value = null; | ||
msg && alert(msg); | ||
}, | ||
mkdirWithParents: path => { | ||
const parts = path.split('/'); | ||
try { FS.lookupPath(parts.join('/')) } | ||
catch (ignore) { | ||
parts.reduce((p, part) => { | ||
p = [...p, part]; | ||
try { FS.lookupPath(p.join('/')) } | ||
catch (ignore) { FS.mkdir(p.join('/')) } | ||
return p; | ||
}, []); | ||
} | ||
}, | ||
clearPath: path => { | ||
try { | ||
Object.keys(FS.lookupPath(path).node.contents).forEach(node => | ||
(FS.stat(`${path}/${node}`).mode & S_IFMT) === S_IFDIR | ||
? Module.clearPath(`${path}/${node}`) | ||
: FS.unlink(`${path}/${node}`)); | ||
FS.rmdir(`${path}`) | ||
} catch (ignore) {} | ||
}, | ||
startGame: () => { | ||
removeRunDependency('syncfs'); | ||
document.querySelector('#uploader').style.display = 'none'; | ||
document.querySelector('#launcher').style.display = 'none'; | ||
}, | ||
deleteFiles: () => { | ||
if (false === confirm('Are you sure?')) return; | ||
Module.clearPath(ENV.FHEROES2_DATA); | ||
FS.syncfs(false, ignore => {}); | ||
Module.clearInput(); | ||
document.querySelector('#uploader').style.display = 'block'; | ||
document.querySelector('#launcher').style.display = 'none'; | ||
}, | ||
setStatus: status => { | ||
const dlProgressRE = /(?<progress>\d+)\/(?<total>\d+)/ig; | ||
if (!status || !dlProgressRE.test(status)) { | ||
if ((status ?? '').startsWith('Downloading data')) progressBar.start(); | ||
return; | ||
} | ||
dlProgressRE.lastIndex = 0; | ||
const {groups: {progress, total}} = [...status.matchAll(dlProgressRE)][0]; | ||
const done = Math.round(progress / total * 100); | ||
progressBar.set(done); | ||
if (100 === done) progressBar.end(); | ||
}, | ||
canvas | ||
} | ||
}); | ||
|
||
document.head.append(Object.assign(document.createElement('script'), {src: './fheroes2.js'})); | ||
</script> | ||
</body> |
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.