-
-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit bbf6a57
Showing
180 changed files
with
1,641 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
* binary |
Empty file.
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,175 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
|
||
<head> | ||
<meta charset="utf-8" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> | ||
<title>ZX Spectrum emulator running on Blazor</title> | ||
<base href="/ZXSpectrum/"/> | ||
<link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" /> | ||
<link href="css/app.css" rel="stylesheet" /> | ||
<link href="ZXBox.Blazor.styles.css" rel="stylesheet" /> | ||
</head> | ||
|
||
<body> | ||
<script> | ||
//Sound | ||
var audiobuffer = []; | ||
var nextStartTime = 0; | ||
var lastcall = performance.now() | ||
var audiocontext = new (window.AudioContext || window.webkitAudioContext)(); | ||
var gainNode = audiocontext.createGain(); | ||
gainNode.gain.value = 0.01; | ||
|
||
function addAudioBuffer | ||
(dataPtr) { | ||
var buffersize = 960; | ||
var myArrayBuffer = audiocontext.createBuffer(1, buffersize, audiocontext.sampleRate); | ||
var nowBuffering = myArrayBuffer.getChannelData(0); | ||
|
||
for (var d = 0; d < buffersize; d++) { | ||
nowBuffering[d] = Module.HEAPU8[dataPtr + d]; | ||
//console.log(nowBuffering[d]); | ||
} | ||
let source = audiocontext.createBufferSource(); | ||
source.buffer = myArrayBuffer; | ||
|
||
gainNode.connect(audiocontext.destination); | ||
source.connect(gainNode); | ||
if (nextStartTime == 0) nextStartTime = audiocontext.currentTime + (myArrayBuffer.length / myArrayBuffer.sampleRate); | ||
|
||
source.start(nextStartTime); | ||
nextStartTime += myArrayBuffer.length / myArrayBuffer.sampleRate; | ||
gainNode.gain.value = 0.0005; | ||
|
||
//console.log(dataPtr); | ||
} | ||
|
||
|
||
|
||
//function play() { | ||
// console.log("Playing sound"); | ||
// soundon = true; | ||
// //end of stream has been reached | ||
// if (audiobuffer.length === 0) | ||
// { | ||
// console.log("To slow"); | ||
// soundon = false; | ||
// return; | ||
// } | ||
// let source = audiocontext.createBufferSource(); | ||
// //get the latest buffer that should play next | ||
// source.buffer = audiobuffer.shift(); | ||
// source.connect(audiocontext.destination); | ||
|
||
// //add this function as a callback to play next buffer | ||
// //when current buffer has reached its end | ||
// source.onended = play; | ||
// source.start(); | ||
//} | ||
|
||
|
||
|
||
var pressedKeys = []; | ||
|
||
function GetKey(keyCode) { | ||
var key = String.fromCharCode(keyCode); | ||
//console.log(keyCode); | ||
switch (keyCode) { | ||
case 32: | ||
key = "space"; | ||
break; | ||
case 8: | ||
key = "backspace"; | ||
break; | ||
case 16: | ||
key = "shift"; | ||
break; | ||
case 17: | ||
key = "control"; | ||
break; | ||
case 9: | ||
key = "tab"; | ||
break; | ||
case 18: | ||
key = "alt"; | ||
break; | ||
case 38: | ||
key = "arrowup"; | ||
break; | ||
case 40: | ||
key = "arrowdown"; | ||
break; | ||
case 37: | ||
key = "arrowleft"; | ||
break; | ||
case 39: | ||
key = "arrowright"; | ||
break; | ||
case 13: | ||
key = "enter"; | ||
break; | ||
|
||
} | ||
return key; | ||
} | ||
|
||
window.onkeyup = function (e) { | ||
var key = GetKey(e.keyCode); | ||
const index = pressedKeys.indexOf(key); | ||
if (index > -1) { | ||
pressedKeys.splice(index, 1); | ||
} | ||
event.preventDefault(); | ||
//console.log(pressedKeys); | ||
} | ||
window.onkeydown = function (e) { | ||
var key = GetKey(e.keyCode); | ||
const index = pressedKeys.indexOf(key); | ||
if (index == -1) { | ||
pressedKeys.push(key); | ||
} | ||
event.preventDefault(); | ||
} | ||
|
||
window.getKeyStatus = function () { | ||
return pressedKeys; | ||
} | ||
|
||
var canvas; | ||
var context; | ||
var imageData; | ||
window.InitCanvas = function InitCanvas() { | ||
|
||
canvas = document.getElementById('emulatorCanvas'); | ||
context = canvas.getContext('2d'); | ||
context.mozImageSmoothingEnabled = false; | ||
context.webkitImageSmoothingEnabled = false; | ||
context.msImageSmoothingEnabled = false; | ||
context.imageSmoothingEnabled = false; | ||
imageData = context.createImageData(256 + 20 + 20, 192 + 20 + 20); | ||
return true; | ||
} | ||
|
||
window.PaintCanvas = function PaintCanvas(dataPtr) { | ||
imageData.data.set(Uint8ClampedArray.from(Module.HEAPU8.subarray(dataPtr, dataPtr + imageData.data.length))); | ||
context.putImageData(imageData, 0, 0); | ||
context.drawImage(canvas, 0, 0, canvas.width, canvas.height); | ||
return true; | ||
} | ||
</script> | ||
<div id="app"> | ||
<div style="height:100vh;text-align:center;padding-top:200px;">Loading...</div> | ||
</div> | ||
|
||
<div id="blazor-error-ui"> | ||
An unhandled error has occurred. | ||
<a href="" class="reload">Reload</a> | ||
<a class="dismiss">🗙</a> | ||
</div> | ||
<script src="JavaScript.js"></script> | ||
<script src="_framework/blazor.webassembly.js"></script> | ||
|
||
</body> | ||
|
||
</html> |
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,203 @@ | ||
(function () { | ||
window.BlazorInputFile = { | ||
init: function init(elem, componentInstance) { | ||
elem._blazorInputFileNextFileId = 0; | ||
|
||
elem.addEventListener('change', function handleInputFileChange(event) { | ||
// Reduce to purely serializable data, plus build an index by ID | ||
elem._blazorFilesById = {}; | ||
var fileList = Array.prototype.map.call(elem.files, function (file) { | ||
var result = { | ||
id: ++elem._blazorInputFileNextFileId, | ||
lastModified: new Date(file.lastModified).toISOString(), | ||
name: file.name, | ||
size: file.size, | ||
type: file.type, | ||
relativePath: file.webkitRelativePath | ||
}; | ||
elem._blazorFilesById[result.id] = result; | ||
|
||
// Attach the blob data itself as a non-enumerable property so it doesn't appear in the JSON | ||
Object.defineProperty(result, 'blob', { value: file }); | ||
|
||
return result; | ||
}); | ||
|
||
componentInstance.invokeMethodAsync('NotifyChange', fileList).then(function () { | ||
//reset file value ,otherwise, the same filename will not be trigger change event again | ||
elem.value = ''; | ||
}, function (err) { | ||
//reset file value ,otherwise, the same filename will not be trigger change event again | ||
elem.value = ''; | ||
throw new Error(err); | ||
}); | ||
}); | ||
}, | ||
|
||
toImageFile(elem, fileId, format, maxWidth, maxHeight) { | ||
var originalFile = getFileById(elem, fileId); | ||
|
||
return new Promise(function (resolve) { | ||
var originalFileImage = new Image(); | ||
originalFileImage.onload = function () { resolve(originalFileImage); }; | ||
originalFileImage.src = URL.createObjectURL(originalFile.blob); | ||
}).then(function (loadedImage) { | ||
return new Promise(function (resolve) { | ||
var desiredWidthRatio = Math.min(1, maxWidth / loadedImage.width); | ||
var desiredHeightRatio = Math.min(1, maxHeight / loadedImage.height); | ||
var chosenSizeRatio = Math.min(desiredWidthRatio, desiredHeightRatio); | ||
|
||
var canvas = document.createElement('canvas'); | ||
canvas.width = Math.round(loadedImage.width * chosenSizeRatio); | ||
canvas.height = Math.round(loadedImage.height * chosenSizeRatio); | ||
canvas.getContext('2d').drawImage(loadedImage, 0, 0, canvas.width, canvas.height); | ||
canvas.toBlob(resolve, format); | ||
}); | ||
}).then(function (resizedImageBlob) { | ||
var result = { | ||
id: ++elem._blazorInputFileNextFileId, | ||
lastModified: originalFile.lastModified, | ||
name: originalFile.name, // Note: we're not changing the file extension | ||
size: resizedImageBlob.size, | ||
type: format, | ||
relativePath: originalFile.relativePath | ||
}; | ||
|
||
elem._blazorFilesById[result.id] = result; | ||
|
||
// Attach the blob data itself as a non-enumerable property so it doesn't appear in the JSON | ||
Object.defineProperty(result, 'blob', { value: resizedImageBlob }); | ||
|
||
return result; | ||
}); | ||
}, | ||
|
||
readFileData: function readFileData(elem, fileId, startOffset, count) { | ||
var readPromise = getArrayBufferFromFileAsync(elem, fileId); | ||
|
||
return readPromise.then(function (arrayBuffer) { | ||
var uint8Array = new Uint8Array(arrayBuffer, startOffset, count); | ||
var base64 = uint8ToBase64(uint8Array); | ||
return base64; | ||
}); | ||
}, | ||
|
||
ensureArrayBufferReadyForSharedMemoryInterop: function ensureArrayBufferReadyForSharedMemoryInterop(elem, fileId) { | ||
return getArrayBufferFromFileAsync(elem, fileId).then(function (arrayBuffer) { | ||
getFileById(elem, fileId).arrayBuffer = arrayBuffer; | ||
}); | ||
}, | ||
|
||
readFileDataSharedMemory: function readFileDataSharedMemory(readRequest) { | ||
// This uses various unsupported internal APIs. Beware that if you also use them, | ||
// your code could become broken by any update. | ||
var inputFileElementReferenceId = Blazor.platform.readStringField(readRequest, 0); | ||
var inputFileElement = document.querySelector('[_bl_' + inputFileElementReferenceId + ']'); | ||
var fileId = Blazor.platform.readInt32Field(readRequest, 4); | ||
var sourceOffset = Blazor.platform.readUint64Field(readRequest, 8); | ||
var destination = Blazor.platform.readInt32Field(readRequest, 16); | ||
var destinationOffset = Blazor.platform.readInt32Field(readRequest, 20); | ||
var maxBytes = Blazor.platform.readInt32Field(readRequest, 24); | ||
|
||
var sourceArrayBuffer = getFileById(inputFileElement, fileId).arrayBuffer; | ||
var bytesToRead = Math.min(maxBytes, sourceArrayBuffer.byteLength - sourceOffset); | ||
var sourceUint8Array = new Uint8Array(sourceArrayBuffer, sourceOffset, bytesToRead); | ||
|
||
var destinationUint8Array = Blazor.platform.toUint8Array(destination); | ||
destinationUint8Array.set(sourceUint8Array, destinationOffset); | ||
|
||
return bytesToRead; | ||
} | ||
}; | ||
|
||
function getFileById(elem, fileId) { | ||
var file = elem._blazorFilesById[fileId]; | ||
if (!file) { | ||
throw new Error('There is no file with ID ' + fileId + '. The file list may have changed'); | ||
} | ||
|
||
return file; | ||
} | ||
|
||
function getArrayBufferFromFileAsync(elem, fileId) { | ||
var file = getFileById(elem, fileId); | ||
|
||
// On the first read, convert the FileReader into a Promise<ArrayBuffer> | ||
if (!file.readPromise) { | ||
file.readPromise = new Promise(function (resolve, reject) { | ||
var reader = new FileReader(); | ||
reader.onload = function () { resolve(reader.result); }; | ||
reader.onerror = function (err) { reject(err); }; | ||
reader.readAsArrayBuffer(file.blob); | ||
}); | ||
} | ||
|
||
return file.readPromise; | ||
} | ||
|
||
var uint8ToBase64 = (function () { | ||
// Code from https://github.com/beatgammit/base64-js/ | ||
// License: MIT | ||
var lookup = []; | ||
|
||
var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; | ||
for (var i = 0, len = code.length; i < len; ++i) { | ||
lookup[i] = code[i]; | ||
} | ||
|
||
function tripletToBase64(num) { | ||
return lookup[num >> 18 & 0x3F] + | ||
lookup[num >> 12 & 0x3F] + | ||
lookup[num >> 6 & 0x3F] + | ||
lookup[num & 0x3F]; | ||
} | ||
|
||
function encodeChunk(uint8, start, end) { | ||
var tmp; | ||
var output = []; | ||
for (var i = start; i < end; i += 3) { | ||
tmp = | ||
((uint8[i] << 16) & 0xFF0000) + | ||
((uint8[i + 1] << 8) & 0xFF00) + | ||
(uint8[i + 2] & 0xFF); | ||
output.push(tripletToBase64(tmp)); | ||
} | ||
return output.join(''); | ||
} | ||
|
||
return function fromByteArray(uint8) { | ||
var tmp; | ||
var len = uint8.length; | ||
var extraBytes = len % 3; // if we have 1 byte left, pad 2 bytes | ||
var parts = []; | ||
var maxChunkLength = 16383; // must be multiple of 3 | ||
|
||
// go through the array every three bytes, we'll deal with trailing stuff later | ||
for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { | ||
parts.push(encodeChunk( | ||
uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength) | ||
)); | ||
} | ||
|
||
// pad the end with zeros, but make sure to not forget the extra bytes | ||
if (extraBytes === 1) { | ||
tmp = uint8[len - 1]; | ||
parts.push( | ||
lookup[tmp >> 2] + | ||
lookup[(tmp << 4) & 0x3F] + | ||
'==' | ||
); | ||
} else if (extraBytes === 2) { | ||
tmp = (uint8[len - 2] << 8) + uint8[len - 1]; | ||
parts.push( | ||
lookup[tmp >> 10] + | ||
lookup[(tmp >> 4) & 0x3F] + | ||
lookup[(tmp << 2) & 0x3F] + | ||
'=' | ||
); | ||
} | ||
|
||
return parts.join(''); | ||
}; | ||
})(); | ||
})(); |
Binary file not shown.
Oops, something went wrong.