Update DS emu

This commit is contained in:
octospacc 2023-01-19 13:07:46 +01:00
parent c8326e953b
commit ba33a4e087
3 changed files with 442 additions and 587 deletions

View File

@ -1,263 +1,139 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="viewport"
content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height">
<link rel="manifest" href="manifest.json">
<link rel="apple-touch-icon" href="https://ds.44670.org/icon.png">
<link href="dark.css" rel="stylesheet">
<title>DS Player</title>
<!-- Add hint for search engine -->
<meta name="description"
content="DS Player is a web emulator for playing NDS and GBA games, designed for iOS(iPhone and iPad) and also workable for other devices.">
<meta name="keywords" content="NDS, GBA, iOS, iPhone, iPad, emulator, DS, Safari, online, PWA">
<meta name="author" content="44670">
</head>
<body>
<style>
html,
body {
overflow-x: hidden;
-webkit-user-select: none;
user-select: none;
-webkit-touch-callout: none;
cursor: inherit;
}
body {
background-color: black;
color: white;
padding: 0;
margin: 0;
width: 100vw;
height: 100vh;
font-family: 'Myriad Set Pro', 'Helvetica Neue', Helvetica, Arial, sans-serif;
}
canvas {
position: absolute;
z-index: 1;
}
#msg-layer {
position: absolute;
left: 0;
width: 100%;
top: 40vh;
background: rgba(0, 0, 0, 0.5);
z-index: 3;
backdrop-filter: blur(3px);
-webkit-backdrop-filter: blur(3px);
}
#vk-layer {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 2;
touch-action: none;
opacity: 0.3;
}
#menu {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 4;
overflow: hidden scroll;
background: rgba(0, 0, 0, 0.4);
backdrop-filter: blur(3px);
-webkit-backdrop-filter: blur(3px);
}
#menu button {
background: transparent;
}
#menu button:active {
background: rgba(255, 255, 255, 0.5);
}
a,
a:visited {
color: white;
}
.vk-round {
text-align: center;
vertical-align: middle;
border-radius: 50%;
display: inline-block;
}
.vk-round-rect {
border-radius: 0.5em;
display: inline-block;
}
.vk {
color: #000;
background-color: #fff;
position: absolute;
z-index: 1;
text-align: center;
vertical-align: middle;
display: inline-block;
}
.vk-touched {}
.link {
text-decoration: underline;
}
hr {
border: 1px solid #fff;
height: 0;
}
</style>
<div id="welcome" class="menu">
<h1>DS Player</h1>
<div id="loading">Loading...</div>
<div id="loadrom" hidden>
<input id="rom" type="file" hidden>
<button style="width:calc(100% - 2em);margin: 1em;" id="btn-choose-file">Choose File (or
drag/drop)...</button><br>
</div>
<p style="color: #888;">
Your files are processed locally and won't be uploaded to any server.<br>
This software should not be used to play games you have not legally obtained.<br>
"Nintendo DS" is a trademark of Nintendo Co., Ltd. This site is not associated with Nintendo in any way.
</p>
<hr>
<p><span id="ver-info"></span><a onclick="whatsNew()" id="whats-new" href="index.html#">What's New</a>&nbsp;|&nbsp;<a
href="index.html#" onclick="uiSwitchTo('menu')">⚙ Settings...</a></p>
<p id="p-sns">
<a href="https://ds.44670.org/gba/">GBA Player</a>
</p>
<p>
<a href="https://github.com/44670/desmume-wasm">Help</a>&nbsp;|&nbsp;<a href="index.html#" id="a-gamepad">No
Gamepad</a>
</p>
<p>
Powered by <a
href="https://github.com/44670/desmume-wasm">desmume-wasm.</a>&nbsp;|&nbsp;https://ds.44670.org<br>
</p>
<div id="pro" style="background-color: #333">
</div>
<p id="ios-power-hint" hidden>
Please <b>turn off "Low Power Mode"</b> in iOS Control Center for better performance.
</p>
<div id="mac-warning" hidden>
WARNING:<br>
It looks like you are using macOS.<br>
Due to macOS Safari <a href="https://webkit.org/tracking-prevention/">limitations</a>, ALL of you save data
will be LOST after 7 days of inactivity.<br>
For this reason, it is highly recommended to use a different browser. (For example: <a
href="https://www.google.com/chrome/">Chrome</a>)
</div>
</div>
<div id="ios-hint" hidden>
<h1>DS Player</h1>
Due to iOS limitations, please open this site(https://ds.44670.org) in <b>Safari</b>, and add it to your
<b>Home Screen</b> by <b>Share Menu</b> to continue.
<p style="text-align: center;">⬇⬇⬇</p>
</div>
<div id="vk-layer" hidden>
<div class="vk-rect vk" data-k="menu" id="vk-menu">M</div>
<div class="vk-rect vk" data-k="l">L</div>
<div class="vk-rect vk" data-k="r">R</div>
<div class="vk-round vk" data-k="a">A</div>
<div class="vk-round vk" data-k="b">B</div>
<div class="vk-round vk" data-k="x">X</div>
<div class="vk-round vk" data-k="y">Y</div>
<div class="vk-rect vk" data-k="select">SE</div>
<div class="vk-rect vk" data-k="start">ST</div>
<div class="vk-round vk" data-k="stick" id="vk-stick"></div>
<div id="vk-dpad-1" class="vk vk-round-rect"></div>
<div id="vk-dpad-2" class="vk vk-round-rect"></div>
</div>
<div style="z-index: 2;position: absolute;bottom: 20px;" id="fps"></div>
<div id="msg-layer" hidden>
<p id="msg-text"></p>
</div>
<div id="menu" hidden>
<button onclick="uiMenuBack()"> Back</button>
<hr>
<div id="cfg-ea" hidden>
<b>Early Access features</b><br>
Please note that these features are experimental and may not be stable.<br>
<input type="checkbox" id="cfg-turbo">
<label for="cfg-turbo">Turbo mode</label><br>
<br>
<label for="cfg-ls-layout">Landscape Screen Layout</label>
<select id="cfg-ls-layout" value="">
<option value="0">TB</option>
<option value="1">LR 1:1</option>
<option value="2">LR X:1</option>
</select><br>
<label for="cfg-scale-mode">Screen filter(restart required)</label>
<select id="cfg-scale-mode" value="">
<option value="0">Pixelated</option>
<option value="1">Smooth</option>
<option value="2">XBRZ</option>
</select><br>
</div>
<hr>
<input type="checkbox" id="power-save">
<label for="power-save">30FPS limit</label><br>
<input type="checkbox" id="vk-enabled">
<label for="vk-enabled">Virtual gamepad</label><br>
<input type="checkbox" id="cfg-mute-sound">
<label for="cfg-mute-sound">Mute sound</label><br>
<label for="vk-direction">Virtual gamepad Style</label>
<select id="vk-direction" value="">
<option value="0">Circle-Pad</option>
<option value="1">D-Pad</option>
</select><br>
<label for="cfg-lang">Firmware Language</label>
<select id="cfg-lang">
<option value="0">Japanese</option>
<option value="1">English</option>
<option value="2">French</option>
<option value="3">German</option>
<option value="4">Italian</option>
<option value="5">Spanish</option>
</select><br>
<input type="checkbox" id="cfg-swap-abxy">
<label for="cfg-swap-abxy">Gamepad: Swap A/B and X/Y</label><br>
<input type="checkbox" id="lid-closed" onchange="window.lidClosed = this.checked">
<label for="lid-closed">Close the lid</label><br>
<hr>
<div id="menu-savegame" hidden>
<input type="file" id="restore-file" onchange="uiSaveRestore()" hidden>
Save Data: <button onclick="uiSaveExport()">Backup</button>|<button
onclick="$id('restore-file').click()">Restore</button><br>
</div>
<hr>
Cloud Save:<span id="span-cloud-id"></span><br>
<button onclick="dpOnConnectButtonClicked()" id="btn-dp-connect">Connect Dropbox</button><br>
<button onclick="dpManualBtn(true)">↑ Upload</button>|<button
onclick="dpManualBtn(false)">↓ Download</button><br>
</div>
<div id="player" hidden>
<canvas id="top" width="256" height="192"></canvas>
<canvas id="bottom" width="256" height="192"></canvas>
</div>
<script src="localforage.js"></script>
<script src="pako.min.js"></script>
<script src="app.js"></script>
<script src="build/nds.js"></script>
</body>
</html>
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="viewport"
content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height">
<link rel="manifest" href="manifest.json">
<link rel="apple-touch-icon" href="https://ds.44670.org/icon.png">
<link href="dark.css" rel="stylesheet">
<title>DeSmuME-WASM Fork</title>
<!-- Add hint for search engine -->
<meta name="description"
content="This is a personal fork of DeSmuME-WASM, a web emulator for playing NDS games, designed for iOS (iPhone and iPad) and also workable for other devices.">
<meta name="keywords" content="NDS, GBA, iOS, iPhone, iPad, emulator, DS, Safari, online, PWA">
<meta name="author" content="44670">
</head>
<body>
<style>
html,
body {
overflow-x: hidden;
-webkit-user-select: none;
user-select: none;
-webkit-touch-callout: none;
cursor: inherit;
}
body {
background-color: black;
color: white;
padding: 0;
margin: 0;
width: 100vw;
height: 100vh;
font-family: 'Myriad Set Pro', 'Helvetica Neue', Helvetica, Arial, sans-serif;
}
canvas {
position: absolute;
z-index: 1;
}
#msg-layer {
position: absolute;
left: 0;
width: 100%;
top: 40vh;
background: rgba(0, 0, 0, 0.5);
z-index: 3;
backdrop-filter: blur(3px);
-webkit-backdrop-filter: blur(3px);
}
#vk-layer {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 2;
touch-action: none;
opacity: 0.3;
}
#menu {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 4;
overflow: hidden scroll;
background: rgba(0, 0, 0, 0.4);
backdrop-filter: blur(3px);
-webkit-backdrop-filter: blur(3px);
}
#menu button {
background: transparent;
}
#menu button:active {
background: rgba(255, 255, 255, 0.5);
}
a,
a:visited {
color: white;
}
.vk-round {
text-align: center;
vertical-align: middle;
border-radius: 50%;
display: inline-block;
}
.vk-round-rect {
border-radius: 0.5em;
display: inline-block;
}
.vk {
color: #000;
background-color: #fff;
position: absolute;
z-index: 1;
text-align: center;
vertical-align: middle;
display: inline-block;
}
.vk-touched {}
.link {
text-decoration: underline;
}
hr {
border: 1px solid #fff;
height: 0;
}
</style>
<div id="welcome" class="menu">
<h1>Redirecting</h1>
<div id="loading">Click <a href="./">here</a> if not redirected automatically</div>
</div>
<script src="localforage.js"></script>
<script src="pako.min.js"></script>
<script src="app.js"></script>
<script>
window.location = "https://octospacc.gitlab.io/Web-Archives-Misc/Repo/DeSmuME" + window.location.hash;
</script>
</body>
</html>

View File

@ -1,5 +1,20 @@
var VER = 'v20230106'
var VER = 'v2023-01-19'
const whatsNew = _ => {
alert(`\
{{ DeSmuME-WASM - OctoSpacc Fork }}
< Changelog >
[ 2023-01-19 ]
- Add this changelog and copyright notice
- Fix URL loading happening prematurely
- Change notices and visible options in the HTML
[ 2023-01-18 ]
- Add support for loading ROMs from URL
`)};
var EngineIsReady = false;
var isIOS = !!navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform);
var isMacOS = !!navigator.platform && /Mac/.test(navigator.platform);
if (isMacOS) {
@ -197,7 +212,6 @@ async function uiSaveRestore() {
})
}
var gameID = ''
var emuKeyState = new Array(14)
const emuKeyNames = ["right", "left", "down", "up", "select", "start", "b", "a", "y", "x", "l", "r", "debug", "lid"]
var vkMap = {}
@ -209,20 +223,16 @@ for (var i = 0; i < emuKeyNames.length; i++) {
keyNameToKeyId[emuKeyNames[i]] = i
}
var isLandscape = false
const emuKeyboardMapping = [39, 37, 40, 38, 16, 13, 90, 88, 65, 83, 81, 87, -1, 8]
var emuIsRunning = false
var emuIsGameLoaded = false
var fps = 0
var divFPS = $id('fps')
var fileInput = $id('rom')
var romSize = 0
var FB = [0, 0]
var screenCanvas = [document.getElementById('top'), document.getElementById('bottom')]
var ctx2d;
var audioContext
var audioBuffer
var scriptNode
@ -231,8 +241,6 @@ var audioFifoL = new Int16Array(audioFifoCap)
var audioFifoR = new Int16Array(audioFifoCap)
var audioFifoHead = 0
var audioFifoLen = 0
var frameCount = 0
var prevCalcFPSTime = 0
var touched = 0
@ -242,7 +250,6 @@ var prevSaveFlag = 0
var lastTwoFrameTime = 10
var fbSize
function callPlugin(type, arg) {
for (var k in plugins) {
if (plugins[k].handler) {
@ -299,10 +306,8 @@ function emuRunFrame() {
Module._runFrame(0, keyMask, touched, touchX, touchY)
emuRunAudio()
}
Module._runFrame(1, keyMask, touched, touchX, touchY)
emuRunAudio()
if (optScaleMode < 2) {
ctx2d[0].putImageData(FB[0], 0, 0)
ctx2d[1].putImageData(FB[1], 0, 0)
@ -310,8 +315,6 @@ function emuRunFrame() {
gpuDraw(screenCanvas[0], FB[0])
gpuDraw(screenCanvas[1], FB[1])
}
frameCount += 1
if (frameCount % 120 == 0) {
var time = performance.now()
@ -324,7 +327,6 @@ function emuRunFrame() {
}
}
function wasmReady() {
Module._setSampleRate(47856)
setTimeout(() => {
@ -347,6 +349,7 @@ function wasmReady() {
} else {
gpuInit()
}
EngineIsReady = true;
}
function emuCopySavBuffer() {
@ -481,7 +484,6 @@ function makeVKStyle(top, left, w, h, fontSize) {
return 'top:' + top + 'px;left:' + left + 'px;width:' + w + 'px;height:' + h + 'px;' + 'font-size:' + fontSize + 'px;line-height:' + h + 'px;'
}
function uiAdjustVKLayout() {
var baseSize = Math.min(window.innerWidth, window.innerHeight) * 0.14 * config.vkScale
var fontSize = baseSize * 0.7
@ -491,7 +493,6 @@ function uiAdjustVKLayout() {
var abxyHeight = baseSize * 3
var vkw = baseSize
var vkh = baseSize
vkw = baseSize * 1.5
vkh = baseSize * 0.6
fontSize = baseSize * 0.5
@ -500,8 +501,6 @@ function uiAdjustVKLayout() {
vkw = baseSize * 0.4
vkh = baseSize * 0.4
$id('vk-menu').style = makeVKStyle(offTop, window.innerWidth / 2 - vkw / 2, vkw, vkh, fontSize)
offTop += baseSize * 0.62
vkw = baseSize
vkh = baseSize
@ -510,13 +509,11 @@ function uiAdjustVKLayout() {
vkMap['b'].style = makeVKStyle(offTop + abxyHeight - vkh, offLeft + abxyWidth / 2 - vkw / 2, vkw, vkh, fontSize)
vkMap['x'].style = makeVKStyle(offTop, offLeft + abxyWidth / 2 - vkw / 2, vkw, vkh, fontSize)
vkMap['y'].style = makeVKStyle(offTop + abxyHeight / 2 - vkh / 2, offLeft, vkw, vkh, fontSize)
vkw = baseSize * 1.0
vkh = baseSize * 1.0
offLeft = 0
$id('vk-stick').style = config.useDPad ? 'display:none;' : makeVKStyle(offTop + abxyHeight / 2 - vkh / 2, offLeft + abxyHeight / 2 - vkw / 2, vkw, vkh, fontSize)
vkStickPos = [offTop + abxyHeight / 2, offLeft + abxyHeight / 2, vkw, vkh, fontSize]
var dpadW = abxyWidth
var dpadH = abxyHeight
var dpadX = offLeft
@ -554,7 +551,6 @@ function setScreenPos(c, left, top, w, h) {
}
}
function uiUpdateLayout() {
isLandscape = isScreenLandscape()
if ((!isLandscape) || (config.lsLayout == 0)) {
@ -597,11 +593,9 @@ function uiUpdateLayout() {
}
}
uiAdjustVKLayout()
}
function uiSwitchTo(mode) {
if (mode == uiCurrentMode) {
return
@ -614,7 +608,6 @@ function uiSwitchTo(mode) {
body.style = ''
html.style = ''
emuIsRunning = false
if (mode == 'player') {
body.style = 'touch-action: none;'
html.style = 'position: fixed;overflow:hidden;touch-action: none;'
@ -709,7 +702,6 @@ function tryInitSound() {
function emuLoop() {
window.requestAnimationFrame(emuLoop)
if (emuIsRunning && (!emuUseTimer33)) {
prevRunFrameTime = performance.now()
emuRunFrame()
@ -753,32 +745,25 @@ function handleTouch(event) {
}
event.preventDefault();
event.stopPropagation();
var isDown = false
var x = 0
var y = 0
var needUpdateStick = false
var stickY = vkStickPos[0]
var stickX = vkStickPos[1]
var stickW = vkStickPos[2]
var stickH = vkStickPos[3]
var stickPressed = false
var stickDeadZone = stickW * 0.2
var nextStickTouchID = null
var nextTpadTouchID = null
var tsRect = screenCanvas[1].getBoundingClientRect()
for (var i = 0; i < emuKeyState.length; i++) {
emuKeyState[i] = false
}
for (var k in vkState) {
vkState[k][1] = 0
}
for (var i = 0; i < event.touches.length; i++) {
var t = event.touches[i];
var tid = t.identifier
@ -805,7 +790,6 @@ function handleTouch(event) {
} else {
if ((tid === stickTouchID) || ((dom == vkMap['stick']) && (tid != tpadTouchID))) {
stickPressed = true
vkState['stick'][1] = 1
var sx = t.clientX
var sy = t.clientY
@ -844,11 +828,9 @@ function handleTouch(event) {
continue
}
}
touched = isDown ? 1 : 0;
touchX = x
touchY = y
for (var k in vkState) {
if (vkState[k][0] != vkState[k][1]) {
var dom = vkMap[k]
@ -867,7 +849,6 @@ function handleTouch(event) {
}
}
for (var i = 0; i < emuKeyState.length; i++) {
var k = emuKeyNames[i]
if (vkState[k]) {
@ -876,11 +857,9 @@ function handleTouch(event) {
}
}
}
if (needUpdateStick) {
vkMap['stick'].style = makeVKStyle(stickY - stickW / 2, stickX - stickW / 2, stickW, stickH, vkStickPos[4])
}
stickTouchID = nextStickTouchID
tpadTouchID = nextTpadTouchID
}
@ -888,9 +867,6 @@ function handleTouch(event) {
window.addEventListener(val, handleTouch)
})
window.onmousedown = window.onmouseup = window.onmousemove = (e) => {
if (!emuIsRunning) {
return
@ -981,7 +957,6 @@ if (isSaveSupported) {
});
}
function processGamepadInput() {
var padMap = gamePadKeyMap
if (config.swapABXY) {
@ -1023,8 +998,6 @@ function processGamepadInput() {
}
}
var isMicrophoneEnabled = false
var micPtr
var micBuf
@ -1080,7 +1053,6 @@ function enableMicrophone() {
}
}
micScriptNode.connect(audioContext.destination);
});
}
@ -1088,8 +1060,6 @@ function isScreenLandscape() {
return (window.innerWidth / window.innerHeight) > 1.2
}
if (location.origin == 'https://ds.44670.org') {
if (isSaveSupported) {
// Register Service Worker
@ -1110,7 +1080,6 @@ if (location.origin == 'https://ds.44670.org') {
}
}
(function () {
var cnt = 0;
// Prompt to install PWA
window.onbeforeinstallprompt = function (e) {
@ -1497,7 +1466,6 @@ function gpuDraw(canvas, idata) {
gl.drawArrays(gl.TRIANGLES, 0, 6);
}
function gpuInit() {
if (!gpuInitWithCanvas(screenCanvas[0])) {
return
@ -1505,7 +1473,6 @@ function gpuInit() {
gpuInitWithCanvas(screenCanvas[1]);
}
var DP_BASE_PATH = "/dssav"
var DP_EXT = ".4dsaz"
@ -1519,8 +1486,6 @@ function dpGetCurrentDayInt() {
return retInt;
}
function dpIsConnected() {
return localStorage['d-token'] ? true : false
}
@ -1536,7 +1501,6 @@ async function dpIDHash(gameID) {
return digestHex.substring(0, 8)
}
async function dpGameLoaded() {
if (dpIsConnected()) {
var hash = await dpIDHash(gameID)
@ -1544,7 +1508,6 @@ async function dpGameLoaded() {
}
}
async function dpConnect() {
var redirectUri = encodeURIComponent(location.origin)
var url = "https://www.dropbox.com/oauth2/authorize?client_id=zro5k6xlnsxu4gz&response_type=code&token_access_type=offline"
@ -1705,9 +1668,6 @@ async function dpTryUploadCloudSave(gameID, tag, u8Arr, mode) {
return false
}
async function dpTryAutoBackup() {
if (!dpIsConnected()) {
return false
@ -1724,9 +1684,6 @@ async function dpTryAutoBackup() {
return false
}
function dpOnConnectButtonClicked() {
if (dpIsConnected()) {
if (confirm("Are you sure to disconnect from Dropbox?")) {
@ -1742,7 +1699,6 @@ function dpOnConnectButtonClicked() {
}
async function dpManualBtn(isUpload) {
if (!dpIsConnected()) {
alert("Please connect to Dropbox first.")
return
@ -1792,11 +1748,25 @@ const LoadRomFromUrl = _ => {
Req.open('GET', RomUrl, true);
Req.responseType = 'blob';
Req.onload = function() {
while (!EngineIsReady) {};
tryLoadROM(Req.response);
};
Req.send();
};
};
/*
const RomUrlBoxChange = _ => {
if (RomUrlBox.value) {
$id('btn-choose-file').innerHTML = 'Load from URL!';
} else {
$id('btn-choose-file').innerHTML = 'Choose File (or drag/drop)...';
};
};
['onchange', 'oninput', 'onpaste'].forEach(function (i) {
RomUrlBox[i] = RomUrlBoxChange;
});
*/
dpOnLoad();
LoadRomFromUrl();

View File

@ -1,263 +1,272 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="viewport"
content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height">
<link rel="manifest" href="manifest.json">
<link rel="apple-touch-icon" href="https://ds.44670.org/icon.png">
<link href="dark.css" rel="stylesheet">
<title>DS Player</title>
<!-- Add hint for search engine -->
<meta name="description"
content="DS Player is a web emulator for playing NDS and GBA games, designed for iOS(iPhone and iPad) and also workable for other devices.">
<meta name="keywords" content="NDS, GBA, iOS, iPhone, iPad, emulator, DS, Safari, online, PWA">
<meta name="author" content="44670">
</head>
<body>
<style>
html,
body {
overflow-x: hidden;
-webkit-user-select: none;
user-select: none;
-webkit-touch-callout: none;
cursor: inherit;
}
body {
background-color: black;
color: white;
padding: 0;
margin: 0;
width: 100vw;
height: 100vh;
font-family: 'Myriad Set Pro', 'Helvetica Neue', Helvetica, Arial, sans-serif;
}
canvas {
position: absolute;
z-index: 1;
}
#msg-layer {
position: absolute;
left: 0;
width: 100%;
top: 40vh;
background: rgba(0, 0, 0, 0.5);
z-index: 3;
backdrop-filter: blur(3px);
-webkit-backdrop-filter: blur(3px);
}
#vk-layer {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 2;
touch-action: none;
opacity: 0.3;
}
#menu {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 4;
overflow: hidden scroll;
background: rgba(0, 0, 0, 0.4);
backdrop-filter: blur(3px);
-webkit-backdrop-filter: blur(3px);
}
#menu button {
background: transparent;
}
#menu button:active {
background: rgba(255, 255, 255, 0.5);
}
a,
a:visited {
color: white;
}
.vk-round {
text-align: center;
vertical-align: middle;
border-radius: 50%;
display: inline-block;
}
.vk-round-rect {
border-radius: 0.5em;
display: inline-block;
}
.vk {
color: #000;
background-color: #fff;
position: absolute;
z-index: 1;
text-align: center;
vertical-align: middle;
display: inline-block;
}
.vk-touched {}
.link {
text-decoration: underline;
}
hr {
border: 1px solid #fff;
height: 0;
}
</style>
<div id="welcome" class="menu">
<h1>DS Player</h1>
<div id="loading">Loading...</div>
<div id="loadrom" hidden>
<input id="rom" type="file" hidden>
<button style="width:calc(100% - 2em);margin: 1em;" id="btn-choose-file">Choose File (or
drag/drop)...</button><br>
</div>
<p style="color: #888;">
Your files are processed locally and won't be uploaded to any server.<br>
This software should not be used to play games you have not legally obtained.<br>
"Nintendo DS" is a trademark of Nintendo Co., Ltd. This site is not associated with Nintendo in any way.
</p>
<hr>
<p><span id="ver-info"></span><a onclick="whatsNew()" id="whats-new" href="index.html#">What's New</a>&nbsp;|&nbsp;<a
href="index.html#" onclick="uiSwitchTo('menu')">⚙ Settings...</a></p>
<p id="p-sns">
<a href="https://ds.44670.org/gba/">GBA Player</a>
</p>
<p>
<a href="https://github.com/44670/desmume-wasm">Help</a>&nbsp;|&nbsp;<a href="index.html#" id="a-gamepad">No
Gamepad</a>
</p>
<p>
Powered by <a
href="https://github.com/44670/desmume-wasm">desmume-wasm.</a>&nbsp;|&nbsp;https://ds.44670.org<br>
</p>
<div id="pro" style="background-color: #333">
</div>
<p id="ios-power-hint" hidden>
Please <b>turn off "Low Power Mode"</b> in iOS Control Center for better performance.
</p>
<div id="mac-warning" hidden>
WARNING:<br>
It looks like you are using macOS.<br>
Due to macOS Safari <a href="https://webkit.org/tracking-prevention/">limitations</a>, ALL of you save data
will be LOST after 7 days of inactivity.<br>
For this reason, it is highly recommended to use a different browser. (For example: <a
href="https://www.google.com/chrome/">Chrome</a>)
</div>
</div>
<div id="ios-hint" hidden>
<h1>DS Player</h1>
Due to iOS limitations, please open this site(https://ds.44670.org) in <b>Safari</b>, and add it to your
<b>Home Screen</b> by <b>Share Menu</b> to continue.
<p style="text-align: center;">⬇⬇⬇</p>
</div>
<div id="vk-layer" hidden>
<div class="vk-rect vk" data-k="menu" id="vk-menu">M</div>
<div class="vk-rect vk" data-k="l">L</div>
<div class="vk-rect vk" data-k="r">R</div>
<div class="vk-round vk" data-k="a">A</div>
<div class="vk-round vk" data-k="b">B</div>
<div class="vk-round vk" data-k="x">X</div>
<div class="vk-round vk" data-k="y">Y</div>
<div class="vk-rect vk" data-k="select">SE</div>
<div class="vk-rect vk" data-k="start">ST</div>
<div class="vk-round vk" data-k="stick" id="vk-stick"></div>
<div id="vk-dpad-1" class="vk vk-round-rect"></div>
<div id="vk-dpad-2" class="vk vk-round-rect"></div>
</div>
<div style="z-index: 2;position: absolute;bottom: 20px;" id="fps"></div>
<div id="msg-layer" hidden>
<p id="msg-text"></p>
</div>
<div id="menu" hidden>
<button onclick="uiMenuBack()"> Back</button>
<hr>
<div id="cfg-ea" hidden>
<b>Early Access features</b><br>
Please note that these features are experimental and may not be stable.<br>
<input type="checkbox" id="cfg-turbo">
<label for="cfg-turbo">Turbo mode</label><br>
<br>
<label for="cfg-ls-layout">Landscape Screen Layout</label>
<select id="cfg-ls-layout" value="">
<option value="0">TB</option>
<option value="1">LR 1:1</option>
<option value="2">LR X:1</option>
</select><br>
<label for="cfg-scale-mode">Screen filter(restart required)</label>
<select id="cfg-scale-mode" value="">
<option value="0">Pixelated</option>
<option value="1">Smooth</option>
<option value="2">XBRZ</option>
</select><br>
</div>
<hr>
<input type="checkbox" id="power-save">
<label for="power-save">30FPS limit</label><br>
<input type="checkbox" id="vk-enabled">
<label for="vk-enabled">Virtual gamepad</label><br>
<input type="checkbox" id="cfg-mute-sound">
<label for="cfg-mute-sound">Mute sound</label><br>
<label for="vk-direction">Virtual gamepad Style</label>
<select id="vk-direction" value="">
<option value="0">Circle-Pad</option>
<option value="1">D-Pad</option>
</select><br>
<label for="cfg-lang">Firmware Language</label>
<select id="cfg-lang">
<option value="0">Japanese</option>
<option value="1">English</option>
<option value="2">French</option>
<option value="3">German</option>
<option value="4">Italian</option>
<option value="5">Spanish</option>
</select><br>
<input type="checkbox" id="cfg-swap-abxy">
<label for="cfg-swap-abxy">Gamepad: Swap A/B and X/Y</label><br>
<input type="checkbox" id="lid-closed" onchange="window.lidClosed = this.checked">
<label for="lid-closed">Close the lid</label><br>
<hr>
<div id="menu-savegame" hidden>
<input type="file" id="restore-file" onchange="uiSaveRestore()" hidden>
Save Data: <button onclick="uiSaveExport()">Backup</button>|<button
onclick="$id('restore-file').click()">Restore</button><br>
</div>
<hr>
Cloud Save:<span id="span-cloud-id"></span><br>
<button onclick="dpOnConnectButtonClicked()" id="btn-dp-connect">Connect Dropbox</button><br>
<button onclick="dpManualBtn(true)">↑ Upload</button>|<button
onclick="dpManualBtn(false)">↓ Download</button><br>
</div>
<div id="player" hidden>
<canvas id="top" width="256" height="192"></canvas>
<canvas id="bottom" width="256" height="192"></canvas>
</div>
<script src="localforage.js"></script>
<script src="pako.min.js"></script>
<script src="app.js"></script>
<script src="build/nds.js"></script>
</body>
</html>
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="viewport"
content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height">
<link rel="manifest" href="manifest.json">
<link rel="apple-touch-icon" href="https://ds.44670.org/icon.png">
<link href="dark.css" rel="stylesheet">
<title>DeSmuME-WASM Fork</title>
<!-- Add hint for search engine -->
<meta name="description"
content="This is a personal fork of DeSmuME-WASM, a web emulator for playing NDS games, designed for iOS (iPhone and iPad) and also workable for other devices.">
<meta name="keywords" content="NDS, GBA, iOS, iPhone, iPad, emulator, DS, Safari, online, PWA">
<meta name="author" content="44670">
</head>
<body>
<style>
html,
body {
overflow-x: hidden;
-webkit-user-select: none;
user-select: none;
-webkit-touch-callout: none;
cursor: inherit;
}
body {
background-color: black;
color: white;
padding: 0;
margin: 0;
width: 100vw;
height: 100vh;
font-family: 'Myriad Set Pro', 'Helvetica Neue', Helvetica, Arial, sans-serif;
}
canvas {
position: absolute;
z-index: 1;
}
#msg-layer {
position: absolute;
left: 0;
width: 100%;
top: 40vh;
background: rgba(0, 0, 0, 0.5);
z-index: 3;
backdrop-filter: blur(3px);
-webkit-backdrop-filter: blur(3px);
}
#vk-layer {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 2;
touch-action: none;
opacity: 0.3;
}
#menu {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 4;
overflow: hidden scroll;
background: rgba(0, 0, 0, 0.4);
backdrop-filter: blur(3px);
-webkit-backdrop-filter: blur(3px);
}
#menu button {
background: transparent;
}
#menu button:active {
background: rgba(255, 255, 255, 0.5);
}
a,
a:visited {
color: white;
}
.vk-round {
text-align: center;
vertical-align: middle;
border-radius: 50%;
display: inline-block;
}
.vk-round-rect {
border-radius: 0.5em;
display: inline-block;
}
.vk {
color: #000;
background-color: #fff;
position: absolute;
z-index: 1;
text-align: center;
vertical-align: middle;
display: inline-block;
}
.vk-touched {}
.link {
text-decoration: underline;
}
hr {
border: 1px solid #fff;
height: 0;
}
</style>
<div id="welcome" class="menu">
<h1>DeSmuME-WASM Fork</h1>
<div id="loading">Loading...</div>
<div id="loadrom" hidden>
<!--<input id="RomUrlBox" type="text" placeholder="Paste a ROM URL to load from that...">-->
<input id="rom" type="file" hidden>
<button style="width:calc(100% - 2em);margin: 1em;" id="btn-choose-file">Choose File (or
drag/drop)...</button><br>
</div>
<p style="color: #888; font-size: smaller;">
Your files are processed locally and won't be uploaded to any server.<br>
This software should not be used to play games you have not legally obtained.<br>
This software is released under the GPL-2 license. Visit the original repo to read the terms.
<br>Changes in this fork from the original version are stated in the changelog.
<br>Modified parts of the source are "index.html" and "app.js" of this website, you can view their code directly.
<br>Compiled parts ("nds.js", "nds.wasm") are not modified and you can find their source on the original repo.
</p>
<hr>
<p><span id="ver-info"></span><a onclick="whatsNew()" id="whats-new" href="index.html#">What's New</a>&nbsp;|&nbsp;<a
href="index.html#" onclick="uiSwitchTo('menu')">⚙ Settings...</a></p>
<p id="p-sns">
<a href="https://gba.44670.org">GBA Player</a>
</p>
<p>
<a href="https://github.com/44670/desmume-wasm">Help</a><!--&nbsp;|&nbsp;<a href="index.html#" id="a-gamepad">No
Gamepad--></a>
</p>
<p>
Powered by <a
href="https://github.com/44670/desmume-wasm">desmume-wasm.</a>&nbsp;|&nbsp;OctoSpacc Fork <span style="font-size: smaller;">(Click on "What's New" for more information - DO NOT report issues with this fork to the original developer!)</span><br>
</p>
<!--
<p>
Powered by <a
href="https://github.com/octospacc/DeSmuME-WASM">DeSmuME-WASM - OctoSpacc Fork</a> (GPLv2)--&nbsp;|&nbsp;OctoSpacc fork--<br>
</p>
-->
<div id="pro" style="background-color: #333">
</div>
<p id="ios-power-hint" hidden>
Please <b>turn off "Low Power Mode"</b> in iOS Control Center for better performance.
</p>
<div id="mac-warning" hidden>
WARNING:<br>
It looks like you are using macOS.<br>
Due to macOS Safari <a href="https://webkit.org/tracking-prevention/">limitations</a>, ALL of you save data
will be LOST after 7 days of inactivity.<br>
For this reason, it is highly recommended to use a different browser. (For example: <a
href="https://www.google.com/chrome/">Chrome</a>)
</div>
</div>
<div id="ios-hint" hidden>
<h1>DS Player</h1>
Due to iOS limitations, please open this site(https://ds.44670.org) in <b>Safari</b>, and add it to your
<b>Home Screen</b> by <b>Share Menu</b> to continue.
<p style="text-align: center;">⬇⬇⬇</p>
</div>
<div id="vk-layer" hidden>
<div class="vk-rect vk" data-k="menu" id="vk-menu">M</div>
<div class="vk-rect vk" data-k="l">L</div>
<div class="vk-rect vk" data-k="r">R</div>
<div class="vk-round vk" data-k="a">A</div>
<div class="vk-round vk" data-k="b">B</div>
<div class="vk-round vk" data-k="x">X</div>
<div class="vk-round vk" data-k="y">Y</div>
<div class="vk-rect vk" data-k="select">SE</div>
<div class="vk-rect vk" data-k="start">ST</div>
<div class="vk-round vk" data-k="stick" id="vk-stick"></div>
<div id="vk-dpad-1" class="vk vk-round-rect"></div>
<div id="vk-dpad-2" class="vk vk-round-rect"></div>
</div>
<div style="z-index: 2;position: absolute;bottom: 20px;" id="fps"></div>
<div id="msg-layer" hidden>
<p id="msg-text"></p>
</div>
<div id="menu" hidden>
<button onclick="uiMenuBack()"> Back</button>
<hr>
<div id="cfg-ea">
<b>Early Access features</b><br>
Please note that these features are experimental and may not be stable.<br>
<input type="checkbox" id="cfg-turbo">
<label for="cfg-turbo">Turbo mode</label><br>
<br>
<label for="cfg-ls-layout">Landscape Screen Layout</label>
<select id="cfg-ls-layout" value="">
<option value="0">TB</option>
<option value="1">LR 1:1</option>
<option value="2">LR X:1</option>
</select><br>
<label for="cfg-scale-mode">Screen filter(restart required)</label>
<select id="cfg-scale-mode" value="">
<option value="0">Pixelated</option>
<option value="1">Smooth</option>
<option value="2">XBRZ</option>
</select><br>
</div>
<hr>
<input type="checkbox" id="power-save">
<label for="power-save">30FPS limit</label><br>
<input type="checkbox" id="vk-enabled">
<label for="vk-enabled">Virtual gamepad</label><br>
<input type="checkbox" id="cfg-mute-sound">
<label for="cfg-mute-sound">Mute sound</label><br>
<label for="vk-direction">Virtual gamepad Style</label>
<select id="vk-direction" value="">
<option value="0">Circle-Pad</option>
<option value="1">D-Pad</option>
</select><br>
<label for="cfg-lang">Firmware Language</label>
<select id="cfg-lang">
<option value="0">Japanese</option>
<option value="1">English</option>
<option value="2">French</option>
<option value="3">German</option>
<option value="4">Italian</option>
<option value="5">Spanish</option>
</select><br>
<input type="checkbox" id="cfg-swap-abxy">
<label for="cfg-swap-abxy">Gamepad: Swap A/B and X/Y</label><br>
<input type="checkbox" id="lid-closed" onchange="window.lidClosed = this.checked">
<label for="lid-closed">Close the lid</label><br>
<hr>
<div id="menu-savegame" hidden>
<input type="file" id="restore-file" onchange="uiSaveRestore()" hidden>
Save Data: <button onclick="uiSaveExport()">Backup</button>|<button
onclick="$id('restore-file').click()">Restore</button><br>
</div>
<hr>
Cloud Save:<span id="span-cloud-id"></span><br>
<button onclick="dpOnConnectButtonClicked()" id="btn-dp-connect">Connect Dropbox</button><br>
<button onclick="dpManualBtn(true)">↑ Upload</button>|<button
onclick="dpManualBtn(false)">↓ Download</button><br>
</div>
<div id="player" hidden>
<canvas id="top" width="256" height="192"></canvas>
<canvas id="bottom" width="256" height="192"></canvas>
</div>
<script src="localforage.js"></script>
<script src="pako.min.js"></script>
<script src="app.js"></script>
<script src="build/nds.js"></script>
</body>
</html>