c64: started WASM implementation from https://github.com/sehugg/chips
use async functions in startUI()
This commit is contained in:
parent
0daea22c2a
commit
7d6e910e57
|
@ -590,7 +590,7 @@ $( ".dropdown-submenu" ).click(function(event) {
|
|||
</script>
|
||||
|
||||
<script>
|
||||
startUI(true);
|
||||
startUI();
|
||||
</script>
|
||||
|
||||
<script>
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
|
||||
processor 6502
|
||||
org $7ffe
|
||||
word $8000 ; load address
|
||||
; cartridge header (http://swut.net/c64cart-howto.html)
|
||||
.byte $09, $80, $25, $80
|
||||
.byte $c3, $c2, $cd, $38, $30
|
||||
.byte $8e, $16, $d0, $20, $a3, $fd, $20
|
||||
.byte $50, $fd, $20, $15, $fd, $20, $5b
|
||||
.byte $ff, $58
|
||||
.byte $ea, $ea, $ea, $ea, $ea, $ea, $ea
|
||||
.byte $ea, $ea, $ea, $ea, $ea
|
||||
; program start
|
||||
Temp equ $00
|
||||
Start
|
||||
sei ; turn off interrupts
|
||||
ldy #0
|
||||
sty $d020 ; reset border color
|
||||
Loop
|
||||
lda Message,y ; load message byte
|
||||
beq EOM ; 0 = end of string
|
||||
clc
|
||||
adc #$c0 ; + 192
|
||||
sta $400+41,y ; store to screen
|
||||
iny
|
||||
bne Loop ; next character
|
||||
EOM
|
||||
Wait1
|
||||
lda $d011
|
||||
bmi Wait1 ; wait for line < 256
|
||||
Wait2
|
||||
lda $d012 ; get current scanline
|
||||
Wait3
|
||||
cmp $d012
|
||||
beq Wait3 ; wait for scanline to change
|
||||
lsr
|
||||
lsr
|
||||
clc
|
||||
adc Temp
|
||||
sta $d020 ; set border color
|
||||
lda $d011 ; get status bits
|
||||
bpl Wait2 ; repeat until line >= 256
|
||||
sty $d020 ; reset border color
|
||||
dec Temp ; scroll colors
|
||||
jmp Wait1 ; endless loop
|
||||
Message
|
||||
; PETSCII - http://sta.c64.org/cbm64pet.html
|
||||
byte "HELLO`WORLDa"
|
||||
byte 0
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
import { RAM, RasterVideo, dumpRAM, AnimationTimer, setKeyboardFromMap, padBytes, ControllerPoller } from "./emu";
|
||||
import { hex, printFlags, invertMap } from "./util";
|
||||
import { RAM, RasterVideo, KeyFlags, dumpRAM, AnimationTimer, setKeyboardFromMap, padBytes, ControllerPoller } from "./emu";
|
||||
import { hex, printFlags, invertMap, getBasePlatform } from "./util";
|
||||
import { CodeAnalyzer } from "./analysis";
|
||||
import { Segment } from "./workertypes";
|
||||
import { disassemble6502 } from "./cpu/disasm6502";
|
||||
|
@ -68,7 +68,7 @@ export interface Debuggable {
|
|||
}
|
||||
|
||||
export interface Platform {
|
||||
start() : void;
|
||||
start() : void | Promise<void>;
|
||||
reset() : void;
|
||||
isRunning() : boolean;
|
||||
getToolForFilename(s:string) : string;
|
||||
|
@ -925,7 +925,7 @@ export function lookupSymbol(platform:Platform, addr:number, extra:boolean) {
|
|||
|
||||
/// new Machine platform adapters
|
||||
|
||||
import { Bus, Resettable, FrameBased, VideoSource, SampledAudioSource, AcceptsROM, AcceptsKeyInput, SavesState, SavesInputState, HasCPU } from "./devices";
|
||||
import { Bus, Resettable, FrameBased, VideoSource, SampledAudioSource, AcceptsROM, AcceptsKeyInput, SavesState, SavesInputState, HasCPU, TrapCondition } from "./devices";
|
||||
import { Probeable, RasterFrameBased, AcceptsPaddleInput } from "./devices";
|
||||
import { SampledAudio } from "./audio";
|
||||
import { ProbeRecorder } from "./recorder";
|
||||
|
@ -1038,7 +1038,7 @@ export abstract class BaseMachinePlatform<T extends Machine> extends BaseDebugPl
|
|||
}
|
||||
|
||||
isRunning() {
|
||||
return this.timer.isRunning();
|
||||
return this.timer && this.timer.isRunning();
|
||||
}
|
||||
|
||||
resume() {
|
||||
|
@ -1113,3 +1113,124 @@ export abstract class BaseZ80MachinePlatform<T extends Machine> extends BaseMach
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
// WASM Support
|
||||
|
||||
export class WASMMachine implements Machine {
|
||||
|
||||
prefix : string;
|
||||
instance : WebAssembly.Instance;
|
||||
exports : any;
|
||||
sys : number;
|
||||
pixel_dest : Uint32Array;
|
||||
pixel_src : Uint32Array;
|
||||
romptr : number;
|
||||
romarr : Uint8Array;
|
||||
|
||||
// TODO
|
||||
cpu = {
|
||||
getPC() : number {
|
||||
return 0;
|
||||
},
|
||||
getSP() : number {
|
||||
return 0;
|
||||
},
|
||||
isStable() : boolean {
|
||||
return false;
|
||||
},
|
||||
reset() {
|
||||
},
|
||||
connectMemoryBus() {
|
||||
},
|
||||
saveState() {
|
||||
},
|
||||
loadState() {
|
||||
}
|
||||
}
|
||||
|
||||
constructor(prefix: string) {
|
||||
this.prefix = prefix;
|
||||
}
|
||||
async loadWASM() {
|
||||
// fetch WASM
|
||||
var wasmResponse = await fetch('wasm/'+this.prefix+'.wasm');
|
||||
var wasmBinary = await wasmResponse.arrayBuffer();
|
||||
var wasmCompiled = await WebAssembly.compile(wasmBinary);
|
||||
var wasmResult = await WebAssembly.instantiate(wasmCompiled);
|
||||
this.instance = wasmResult;
|
||||
this.exports = wasmResult.exports;
|
||||
this.exports.memory.grow(32);
|
||||
// fetch BIOS
|
||||
var biosResponse = await fetch('wasm/'+this.prefix+'.bios');
|
||||
var biosBinary = await biosResponse.arrayBuffer();
|
||||
const cBIOSPointer = this.exports.malloc(0x5000);
|
||||
const srcArray = new Uint8Array(biosBinary);
|
||||
const destArray = new Uint8Array(this.exports.memory.buffer, cBIOSPointer, 0x5000);
|
||||
destArray.set(srcArray);
|
||||
// init machine instance
|
||||
this.sys = this.exports.machine_init(cBIOSPointer);
|
||||
console.log('machine_init', this.sys);
|
||||
}
|
||||
reset() {
|
||||
this.exports.machine_reset(this.sys);
|
||||
}
|
||||
loadROM(rom: Uint8Array) {
|
||||
if (!this.romptr) {
|
||||
this.romptr = this.exports.malloc(0x10000);
|
||||
this.romarr = new Uint8Array(this.exports.memory.buffer, this.romptr, 0x10000);
|
||||
}
|
||||
this.reset();
|
||||
// this.exports.c64_exec(this.sys, 1000000);
|
||||
this.romarr.set(rom);
|
||||
this.exports.machine_load_rom(this.sys, this.romptr, rom.length);
|
||||
}
|
||||
advanceFrame(trap: TrapCondition) : number {
|
||||
if (trap) {
|
||||
// TODO
|
||||
} else {
|
||||
this.exports.c64_exec(this.sys, 16421);
|
||||
}
|
||||
this.syncVideo();
|
||||
return 0; // TODO
|
||||
}
|
||||
read(address: number) : number {
|
||||
return this.exports.machine_mem_read(this.sys, address & 0xffff);
|
||||
}
|
||||
readConst(address: number) : number {
|
||||
return this.exports.machine_mem_read(this.sys, address & 0xffff);
|
||||
}
|
||||
write(address: number, value: number) : void {
|
||||
this.exports.machine_mem_write(this.sys, address & 0xffff, value & 0xff);
|
||||
}
|
||||
saveState() : EmuState {
|
||||
return null;
|
||||
}
|
||||
loadState(state: EmuState) : void {
|
||||
}
|
||||
saveControlsState() : any {
|
||||
}
|
||||
loadControlsState(state) : void {
|
||||
}
|
||||
getVideoParams() {
|
||||
return {width:392, height:272, overscan:true}; // TODO: const
|
||||
}
|
||||
connectVideo(pixels:Uint32Array) : void {
|
||||
this.pixel_dest = pixels;
|
||||
// save video pointer
|
||||
var pixbuf = this.exports.machine_get_pixel_buffer(this.sys);
|
||||
this.pixel_src = new Uint32Array(this.exports.memory.buffer, pixbuf, pixels.length);
|
||||
console.log(pixbuf, pixels.length);
|
||||
}
|
||||
syncVideo() {
|
||||
if (this.pixel_dest != null) {
|
||||
this.pixel_dest.set(this.pixel_src);
|
||||
}
|
||||
}
|
||||
setKeyInput(key: number, code: number, flags: number): void {
|
||||
if (flags & KeyFlags.KeyDown) {
|
||||
this.exports.machine_key_down(this.sys, key);
|
||||
} else if (flags & KeyFlags.KeyUp) {
|
||||
this.exports.machine_key_up(this.sys, key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1789,7 +1789,7 @@ function installGAHooks() {
|
|||
}
|
||||
}
|
||||
|
||||
function startPlatform() {
|
||||
async function startPlatform() {
|
||||
if (!PLATFORMS[platform_id]) throw Error("Invalid platform '" + platform_id + "'.");
|
||||
platform = new PLATFORMS[platform_id]($("#emuscreen")[0]);
|
||||
setPlatformUI();
|
||||
|
@ -1814,7 +1814,7 @@ function startPlatform() {
|
|||
}
|
||||
// start platform and load file
|
||||
replaceURLState();
|
||||
platform.start();
|
||||
await platform.start();
|
||||
installGAHooks();
|
||||
loadBIOSFromProject();
|
||||
initProject();
|
||||
|
@ -1824,7 +1824,6 @@ function startPlatform() {
|
|||
addPageFocusHandlers();
|
||||
showInstructions();
|
||||
revealTopBar();
|
||||
return true;
|
||||
}
|
||||
|
||||
function revealTopBar() {
|
||||
|
@ -1896,7 +1895,7 @@ function setPlatformUI() {
|
|||
}
|
||||
|
||||
// start
|
||||
export function startUI(loadplatform : boolean) {
|
||||
export function startUI() {
|
||||
// import from github?
|
||||
if (qs['githubURL']) {
|
||||
importProjectFromGithub(qs['githubURL'], true);
|
||||
|
@ -1932,33 +1931,38 @@ export function startUI(loadplatform : boolean) {
|
|||
return;
|
||||
}
|
||||
// load and start platform object
|
||||
if (loadplatform) {
|
||||
loadAndStartPlatform();
|
||||
} else {
|
||||
startPlatform();
|
||||
revealTopBar();
|
||||
}
|
||||
loadAndStartPlatform();
|
||||
});
|
||||
}
|
||||
|
||||
function loadAndStartPlatform() {
|
||||
async function loadAndStartPlatform() {
|
||||
var platformfn = 'gen/platform/' + platform_id.split(/[.-]/)[0] + '.js'; // required file
|
||||
var machinefn = platformfn.replace('/platform/', '/machine/'); // optional file
|
||||
loadScript(platformfn).then( () => {
|
||||
return loadScript(machinefn).catch(() => { console.log('skipped',machinefn); }); // optional file skipped
|
||||
}).then( () => {
|
||||
try {
|
||||
await loadScript(platformfn); // load platform file
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
alertError('Platform "' + platform_id + '" not supported.');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await loadScript(machinefn); // load machine file
|
||||
} catch (e) {
|
||||
console.log('skipped',machinefn); // optional file skipped
|
||||
}
|
||||
try {
|
||||
console.log("starting platform", platform_id); // loaded required <platform_id>.js file
|
||||
try {
|
||||
startPlatform();
|
||||
await startPlatform();
|
||||
showWelcomeMessage();
|
||||
document.title = document.title + " [" + platform_id + "] - " + (repo_id?('['+repo_id+'] - '):'') + current_project.mainPath;
|
||||
} finally {
|
||||
revealTopBar();
|
||||
}
|
||||
}).catch( (e) => {
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
alertError('Platform "' + platform_id + '" not supported.');
|
||||
});
|
||||
alertError('Platform "' + platform_id + '" failed to load.');
|
||||
}
|
||||
}
|
||||
|
||||
// HTTPS REDIRECT
|
||||
|
|
|
@ -1,32 +1,61 @@
|
|||
|
||||
import { C64 } from "../machine/c64";
|
||||
import { Platform, Base6502MachinePlatform } from "../common/baseplatform";
|
||||
import { Platform, WASMMachine, Base6502MachinePlatform, getToolForFilename_6502, getOpcodeMetadata_6502 } from "../common/baseplatform";
|
||||
import { PLATFORMS } from "../common/emu";
|
||||
|
||||
var C64_PRESETS = [
|
||||
const C64_PRESETS = [
|
||||
{id:'hello.dasm', name:'Hello World (ASM)'},
|
||||
];
|
||||
|
||||
const C64_MEMORY_MAP = { main:[
|
||||
{name:'6510 Registers',start:0x0, size:0x2,type:'io'},
|
||||
{name:'RAM', start:0x2, size:0x7ffe,type:'ram'},
|
||||
{name:'Cartridge ROM',start:0x8000,size:0x2000,type:'rom'},
|
||||
{name:'BASIC ROM', start:0xa000,size:0x2000,type:'rom'},
|
||||
{name:'RAM', start:0xc000,size:0x1000,type:'ram'},
|
||||
{name:'VIC-II I/O', start:0xd000,size:0x0400,type:'io'},
|
||||
{name:'Color RAM', start:0xd800,size:0x0400,type:'io'},
|
||||
{name:'CIA 1', start:0xdc00,size:0x0100,type:'io'},
|
||||
{name:'CIA 2', start:0xdd00,size:0x0100,type:'io'},
|
||||
{name:'KERNAL ROM', start:0xe000,size:0x2000,type:'rom'},
|
||||
] }
|
||||
|
||||
class C64Platform extends Base6502MachinePlatform<C64> implements Platform {
|
||||
|
||||
newMachine() { return new C64(); }
|
||||
getPresets() { return C64_PRESETS; }
|
||||
getDefaultExtension() { return ".c"; };
|
||||
readAddress(a) { return this.machine.readConst(a); }
|
||||
loadBios(bios) { this.machine.loadBIOS(bios); }
|
||||
getMemoryMap() { return { main:[
|
||||
{name:'6510 Registers',start:0x0, size:0x2,type:'io'},
|
||||
{name:'RAM', start:0x2, size:0x7ffe,type:'ram'},
|
||||
{name:'Cartridge ROM',start:0x8000,size:0x2000,type:'rom'},
|
||||
{name:'BASIC ROM', start:0xa000,size:0x2000,type:'rom'},
|
||||
{name:'RAM', start:0xc000,size:0x1000,type:'ram'},
|
||||
{name:'VIC-II I/O', start:0xd000,size:0x0400,type:'io'},
|
||||
{name:'Color RAM', start:0xd800,size:0x0400,type:'io'},
|
||||
{name:'CIA 1', start:0xdc00,size:0x0100,type:'io'},
|
||||
{name:'CIA 2', start:0xdd00,size:0x0100,type:'io'},
|
||||
{name:'KERNAL ROM', start:0xe000,size:0x2000,type:'rom'},
|
||||
] } };
|
||||
loadBios(bios) { this.machine.loadBIOS(bios); }
|
||||
getMemoryMap() { return C64_MEMORY_MAP; }
|
||||
}
|
||||
|
||||
PLATFORMS['c64'] = C64Platform;
|
||||
class C64WASMPlatform extends Base6502MachinePlatform<WASMMachine> implements Platform {
|
||||
|
||||
newMachine() { return new WASMMachine('c64'); }
|
||||
|
||||
async start() {
|
||||
// TODO: start() needs to block
|
||||
await this.machine.loadWASM();
|
||||
super.start();
|
||||
}
|
||||
getPresets() { return C64_PRESETS; }
|
||||
getDefaultExtension() { return ".c"; };
|
||||
readAddress(a) { return this.machine.readConst(a); }
|
||||
getMemoryMap() { return C64_MEMORY_MAP; }
|
||||
}
|
||||
|
||||
/*
|
||||
class C64WASMPlatform extends BaseWASMPlatform implements Platform {
|
||||
|
||||
prefix = 'c64';
|
||||
|
||||
getPresets() { return C64_PRESETS; }
|
||||
getToolForFilename = getToolForFilename_6502;
|
||||
getOpcodeMetadata = getOpcodeMetadata_6502;
|
||||
getDefaultExtension() { return ".c"; };
|
||||
}
|
||||
*/
|
||||
|
||||
PLATFORMS['c64'] = C64Platform;
|
||||
PLATFORMS['c64.wasm'] = C64WASMPlatform;
|
||||
|
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue