mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-12-21 21:29:17 +00:00
164 lines
4.8 KiB
TypeScript
164 lines
4.8 KiB
TypeScript
|
|
import { Platform } from "../common/baseplatform";
|
|
import { PLATFORMS, RasterVideo } from "../common/emu";
|
|
import { loadScript } from "../common/util";
|
|
|
|
// PC emulator: https://github.com/copy/v86
|
|
|
|
declare var V86Starter : any;
|
|
declare var V86 : any;
|
|
declare var CPU : any;
|
|
declare var fatfs : any;
|
|
|
|
const PC_PRESETS = [
|
|
{id:'hello.asm', name:'Hello World (ASM)'},
|
|
{id:'mandelg.asm', name:'Mandelbrot (ASM)'},
|
|
{id:'snake.c', name:'Snake Game (C)'},
|
|
];
|
|
|
|
class FATFSArrayBufferDriver {
|
|
buffer : ArrayBuffer;
|
|
data : DataView;
|
|
sectorSize : number;
|
|
numSectors : number;
|
|
constructor(buffer : ArrayBuffer) {
|
|
this.buffer = buffer;
|
|
this.data = new DataView(this.buffer);
|
|
this.sectorSize = 512;
|
|
this.numSectors = this.buffer.byteLength / this.sectorSize;
|
|
}
|
|
readSectors(sector, dest, cb) {
|
|
var ofs = this.sectorSize * sector;
|
|
for (var i=0; i<dest.length; i++) {
|
|
dest[i] = this.data.getUint8(i + ofs);
|
|
}
|
|
//console.log('read', sector, dest, cb);
|
|
cb(null);
|
|
}
|
|
writeSectors(sector, data, cb) {
|
|
var ofs = this.sectorSize * sector;
|
|
for (var i=0; i<data.length; i++) {
|
|
this.data.setUint8(i + ofs, data[i]);
|
|
}
|
|
//console.log('write', sector, data, cb);
|
|
cb(null);
|
|
}
|
|
}
|
|
|
|
class X86PCPlatform implements Platform {
|
|
|
|
mainElement : HTMLElement;
|
|
video : RasterVideo;
|
|
console_div : HTMLElement;
|
|
|
|
emulator;
|
|
v86;
|
|
fda_image;
|
|
fda_driver;
|
|
fda_fs;
|
|
|
|
constructor(mainElement) {
|
|
//super();
|
|
this.mainElement = mainElement;
|
|
}
|
|
getToolForFilename(s: string): string {
|
|
if (s.endsWith(".c")) return "smlrc";
|
|
return "yasm";
|
|
}
|
|
getDefaultExtension(): string {
|
|
return ".asm";
|
|
}
|
|
getPresets() {
|
|
return PC_PRESETS;
|
|
}
|
|
pause(): void {
|
|
if (this.isRunning()) this.emulator.stop();
|
|
}
|
|
resume(): void {
|
|
if (!this.isRunning()) this.emulator.run();
|
|
}
|
|
reset() {
|
|
this.emulator.restart();
|
|
}
|
|
isRunning() {
|
|
return this.emulator.is_running();
|
|
}
|
|
loadROM(title: string, rom: any) {
|
|
this.fda_fs.writeFile('main.exe', rom, {encoding:'binary'}, (e) => {
|
|
if (e) throw e;
|
|
else this.reset();
|
|
});
|
|
}
|
|
async start() {
|
|
await loadScript('./lib/libv86.js');
|
|
await loadScript('./lib/fatfs.js');
|
|
|
|
this.video = new RasterVideo(this.mainElement,640,480,{overscan:false});
|
|
this.video.create();
|
|
|
|
var div = document.createElement('div');
|
|
div.classList.add('pc-console');
|
|
div.classList.add('emuvideo');
|
|
this.mainElement.appendChild(div);
|
|
this.console_div = div;
|
|
this.resize(); // set font size
|
|
|
|
this.emulator = new V86Starter({
|
|
memory_size: 2 * 1024 * 1024,
|
|
vga_memory_size: 1 * 1024 * 1024,
|
|
screen_container: this.mainElement,
|
|
bios: {
|
|
url: "./res/seabios.bin",
|
|
},
|
|
vga_bios: {
|
|
url: "./res/vgabios.bin",
|
|
},
|
|
fda: {
|
|
url: "./res/freedos722.img",
|
|
size: 737280,
|
|
},
|
|
autostart: true,
|
|
});
|
|
return new Promise<void>( (resolve, reject) => {
|
|
this.emulator.add_listener("emulator-ready", () => {
|
|
console.log("emulator ready");
|
|
console.log(this.emulator);
|
|
this.v86 = this.emulator.v86;
|
|
this.fda_image = this.v86.cpu.devices.fdc.fda_image;
|
|
this.fda_driver = new FATFSArrayBufferDriver(this.fda_image.buffer);
|
|
this.fda_fs = fatfs.createFileSystem(this.fda_driver);
|
|
resolve();
|
|
});
|
|
});
|
|
}
|
|
|
|
resize() {
|
|
// set font size proportional to window width
|
|
var charwidth = $(this.console_div).width() * 1.7 / 80;
|
|
$(this.console_div).css('font-size', charwidth+'px');
|
|
}
|
|
|
|
getDebugTree() {
|
|
return this.v86;
|
|
}
|
|
readAddress(addr:number) {
|
|
return this.v86.cpu.mem8[addr];
|
|
}
|
|
getMemoryMap() { return { main:[
|
|
{name:'Real Mode IVT',start:0x0,size:0x400,type:'ram'},
|
|
{name:'BIOS Data Area',start:0x400,size:0x100,type:'ram'},
|
|
{name:'User RAM',start:0x500,size:0x80000-0x500,type:'ram'},
|
|
{name:'Extended BIOS Data Area',start:0x80000,size:0x20000,type:'ram'},
|
|
{name:'Video RAM',start:0xa0000,size:0x20000,type:'ram'},
|
|
{name:'Video BIOS',start:0xc0000,size:0x8000,type:'rom'},
|
|
{name:'BIOS Expansions',start:0xc8000,size:0x28000,type:'rom'},
|
|
{name:'PC BIOS',start:0xf0000,size:0x10000,type:'rom'},
|
|
] } };
|
|
|
|
getROMExtension(rom : Uint8Array) {
|
|
return ".exe";
|
|
}
|
|
}
|
|
|
|
PLATFORMS['x86'] = X86PCPlatform;
|