vic20: sort of functional (need res/vic20.bios, basic+chars+kernel)

This commit is contained in:
Steven Hugg 2022-02-23 13:36:44 -06:00
parent b6467ce314
commit ec089b2d89
12 changed files with 35518 additions and 11 deletions

20
presets/vic20/hello.dasm Normal file
View File

@ -0,0 +1,20 @@
;https://www.pagetable.com/?p=926
processor 6502
org $fff
.word $1001
.word basic
basic:
.word 0
start:
ldy #0
Loop:
lda MSG,y
beq Wait
JSR $FFD2
iny
bne Loop
Wait:
jmp Wait
MSG:
.byte "HELLO WORLD"
.byte 0

241
presets/vic20/siegegame.c Normal file
View File

@ -0,0 +1,241 @@
/*
Text-based version of a Blockade-style game.
For more information, see "Making Arcade Games in C".
*/
#include <stdlib.h>
#include <string.h>
#include <joystick.h>
#include <conio.h>
#include <vic20.h>
#include <cbm_petscii_charmap.h>
#define COLS 22
#define ROWS 23
typedef unsigned char byte;
typedef signed char sbyte;
typedef unsigned short word;
byte getchar(byte x, byte y) {
gotoxy(x,y); // set cursor position
return cpeekc();
}
void delay(byte count) {
while (count--) {
word i;
for (i=0; i<500; i++) ;
}
}
////////// GAME DATA
typedef struct {
byte x;
byte y;
byte dir;
word score;
char head_attr;
char tail_attr;
int collided:1;
int human:1;
} Player;
Player players[2];
byte credits = 0;
byte frames_per_move;
byte gameover;
#define START_SPEED 12
#define MAX_SPEED 5
#define MAX_SCORE 7
///////////
const char BOX_CHARS[8] = { '+', '+', '+', '+',
'-', '-', '!', '!'};
void draw_box(byte x, byte y, byte x2, byte y2, const char* chars) {
byte x1 = x;
cputcxy(x, y, chars[2]);
cputcxy(x2, y, chars[3]);
cputcxy(x, y2, chars[0]);
cputcxy(x2, y2, chars[1]);
while (++x < x2) {
cputcxy(x, y, chars[5]);
cputcxy(x, y2, chars[4]);
}
while (++y < y2) {
cputcxy(x1, y, chars[6]);
cputcxy(x2, y, chars[7]);
}
}
void draw_playfield() {
draw_box(0,1,COLS-1,ROWS-1,BOX_CHARS);
cputsxy( 0, 0, "Plyr1:");
cputsxy(10, 0, "Plyr2:");
cputcxy( 7, 0, players[0].score+'0');
cputcxy(17, 0, players[1].score+'0');
}
typedef enum { D_RIGHT, D_DOWN, D_LEFT, D_UP } dir_t;
const sbyte DIR_X[4] = { 1, 0, -1, 0 };
const sbyte DIR_Y[4] = { 0, 1, 0, -1 };
void init_game() {
memset(players, 0, sizeof(players));
players[0].head_attr = '1';
players[1].head_attr = '2';
players[0].tail_attr = '#';
players[1].tail_attr = '*';
frames_per_move = START_SPEED;
}
void reset_players() {
players[0].x = players[0].y = 5;
players[0].dir = D_RIGHT;
players[1].x = COLS-6;
players[1].y = ROWS-6;
players[1].dir = D_LEFT;
players[0].collided = players[1].collided = 0;
}
void draw_player(Player* p) {
cputcxy(p->x, p->y, p->head_attr);
}
void move_player(Player* p) {
cputcxy(p->x, p->y, p->tail_attr);
p->x += DIR_X[p->dir];
p->y += DIR_Y[p->dir];
if ((getchar(p->x, p->y) & 0x7f) != ' ')
p->collided = 1;
draw_player(p);
}
void human_control(Player* p) {
byte dir = 0xff;
char joy;
if (!p->human) return;
if (!kbhit()) return;
joy = joy_read(0);
if (JOY_UP(joy)) dir = D_UP;
if (JOY_LEFT(joy)) dir = D_LEFT;
if (JOY_RIGHT(joy)) dir = D_RIGHT;
if (JOY_DOWN(joy)) dir = D_DOWN;
// don't let the player reverse direction
if (dir < 0x80 && dir != (p->dir ^ 2)) {
p->dir = dir;
}
}
byte ai_try_dir(Player* p, dir_t dir, byte shift) {
byte x,y;
dir &= 3;
x = p->x + (DIR_X[dir] << shift);
y = p->y + (DIR_Y[dir] << shift);
if (x < COLS && y < ROWS && (getchar(x, y) & 0x7f) == ' ') {
p->dir = dir;
return 1;
} else {
return 0;
}
}
void ai_control(Player* p) {
dir_t dir;
if (p->human) return;
dir = p->dir;
if (!ai_try_dir(p, dir, 0)) {
ai_try_dir(p, dir+1, 0);
ai_try_dir(p, dir-1, 0);
} else {
ai_try_dir(p, dir-1, 0) && ai_try_dir(p, dir-1, 1+(rand() & 3));
ai_try_dir(p, dir+1, 0) && ai_try_dir(p, dir+1, 1+(rand() & 3));
ai_try_dir(p, dir, rand() & 3);
}
}
void flash_colliders() {
byte i;
// flash players that collided
for (i=0; i<56; i++) {
delay(2);
revers(players[0].collided && (i&1));
draw_player(&players[0]);
revers(players[1].collided && (i&1));
draw_player(&players[1]);
}
revers(0);
}
void make_move() {
byte i;
for (i=0; i<frames_per_move; i++) {
human_control(&players[0]);
delay(1);
}
ai_control(&players[0]);
ai_control(&players[1]);
// if players collide, 2nd player gets the point
textcolor(COLOR_CYAN);
move_player(&players[1]);
textcolor(COLOR_YELLOW);
move_player(&players[0]);
textcolor(COLOR_WHITE);
}
void declare_winner(byte winner) {
byte i;
clrscr();
for (i=0; i<ROWS/2-3; i++) {
draw_box(i,i,COLS-1-i,ROWS-1-i,BOX_CHARS);
delay(1);
}
cputsxy(12,10,"WINNER:");
cputsxy(12,13,"PLAYER ");
cputcxy(12+7, 13, '1'+winner);
delay(200);
gameover = 1;
}
void play_round() {
reset_players();
clrscr();
textcolor(COLOR_WHITE);
draw_playfield();
while (1) {
make_move();
if (players[0].collided || players[1].collided) break;
}
flash_colliders();
// add scores to players that didn't collide
if (players[0].collided) players[1].score++;
if (players[1].collided) players[0].score++;
// increase speed
if (frames_per_move > MAX_SPEED) frames_per_move--;
// game over?
if (players[0].score != players[1].score) {
if (players[0].score >= MAX_SCORE)
declare_winner(0);
else if (players[1].score >= MAX_SCORE)
declare_winner(1);
}
}
void play_game() {
gameover = 0;
init_game();
players[0].human = 1;
while (!gameover) {
play_round();
}
}
void main() {
joy_install (joy_static_stddrv);
play_game();
}

View File

@ -0,0 +1,5 @@
#include <stdio.h>
void main(void) {
printf("HELLO WORLD\n");
}

BIN
res/vic20.wasm Executable file

Binary file not shown.

View File

@ -1,5 +1,4 @@
import { loadScript } from "../common/util";
import { WasmFs } from "@wasmer/wasmfs";
import { CpuState, EmuState } from "./baseplatform";
import { CPU, SampledAudioSink, ProbeAll, NullProbe } from "./devices";
@ -60,18 +59,22 @@ export abstract class BaseWASMMachine {
}
async fetchWASM() {
var wasmResponse = await fetch('res/'+this.prefix+'.wasm');
var wasmBinary = await wasmResponse.arrayBuffer();
var wasmCompiled = await WebAssembly.compile(wasmBinary);
var wasmResult = await WebAssembly.instantiate(wasmCompiled, this.getImports(wasmCompiled));
this.instance = wasmResult;
this.exports = wasmResult.exports;
if (wasmResponse.status == 200) {
var wasmBinary = await wasmResponse.arrayBuffer();
var wasmCompiled = await WebAssembly.compile(wasmBinary);
var wasmResult = await WebAssembly.instantiate(wasmCompiled, this.getImports(wasmCompiled));
this.instance = wasmResult;
this.exports = wasmResult.exports;
}
}
async fetchBIOS() {
var biosResponse = await fetch('res/'+this.prefix+'.bios');
var biosBinary = await biosResponse.arrayBuffer();
this.biosptr = this.exports.malloc(biosBinary.byteLength);
this.biosarr = new Uint8Array(this.exports.memory.buffer, this.biosptr, biosBinary.byteLength);
this.loadBIOS(new Uint8Array(biosBinary));
if (biosResponse.status == 200) {
var biosBinary = await biosResponse.arrayBuffer();
this.biosptr = this.exports.malloc(biosBinary.byteLength);
this.biosarr = new Uint8Array(this.exports.memory.buffer, this.biosptr, biosBinary.byteLength);
this.loadBIOS(new Uint8Array(biosBinary));
}
}
async initWASM() {
// init machine instance
@ -143,11 +146,12 @@ export abstract class BaseWASMMachine {
getAudioParams() {
return {sampleRate:44100, stereo:false};
}
videoOffsetBytes = 0;
connectVideo(pixels:Uint32Array) : void {
this.pixel_dest = pixels;
var pixbuf = this.exports.machine_get_pixel_buffer(this.sys); // save video pointer
this.pixel_src = new Uint32Array(this.exports.memory.buffer, pixbuf, pixels.length);
console.log('connectVideo', pixbuf, pixels.length);
this.pixel_src = new Uint32Array(this.exports.memory.buffer, pixbuf+this.videoOffsetBytes, pixels.length);
}
syncVideo() {
if (this.exports.machine_update_video) {

154
src/machine/vic20.ts Normal file
View File

@ -0,0 +1,154 @@
//// WASM Machine
import { Machine } from "../common/baseplatform";
import { Probeable, TrapCondition } from "../common/devices";
import { KeyFlags } from "../common/emu";
import { hex } from "../common/util";
import { BaseWASMMachine } from "../common/wasmplatform";
export class VIC20_WASMMachine extends BaseWASMMachine implements Machine, Probeable {
numTotalScanlines = 312;
cpuCyclesPerLine = 63;
videoOffsetBytes = -24 * 4;
prgstart : number;
joymask0 = 0;
joymask1 = 0;
getBIOSLength() { return 0x5000 };
loadBIOS(srcArray: Uint8Array) {
super.loadBIOS(srcArray);
}
reset() {
super.reset();
// clear keyboard
for (var ch=0; ch<128; ch++) {
this.setKeyInput(ch, 0, KeyFlags.KeyUp);
}
// load rom
if (this.romptr && this.romlen) {
this.exports.machine_load_rom(this.sys, this.romptr, this.romlen);
this.prgstart = this.romarr[0] + (this.romarr[1]<<8); // get load address
// look for BASIC program start
if (this.prgstart == 0x1001) {
this.prgstart = this.romarr[2] + (this.romarr[3]<<8) + 2; // point to after BASIC program
console.log("prgstart", hex(this.prgstart));
}
// is program loaded into RAM?
if (this.prgstart < 0x8000) {
// advance BIOS a few frames
this.exports.machine_exec(this.sys, 400000);
// type in command (SYS 2061)
var cmd = "SYS "+this.prgstart+"\r";
console.log(cmd);
for (var i=0; i<cmd.length; i++) {
var key = cmd.charCodeAt(i);
this.exports.machine_exec(this.sys, 20000);
this.exports.machine_exec(this.sys, 20000);
this.exports.machine_key_down(this.sys, key);
this.exports.machine_exec(this.sys, 20000);
this.exports.machine_exec(this.sys, 20000);
this.exports.machine_key_up(this.sys, key);
}
// advance clock until program starts
for (var i=0; i<10000 && this.getPC() != this.prgstart; i++) {
//this.exports.machine_tick(this.sys);
}
} else {
// get out of reset
this.exports.machine_exec(this.sys, 100);
// wait until cartridge start
// TODO: detect ROM cartridge
var warmstart = this.romarr[0x4] + this.romarr[0x5]*256;
for (var i=0; i<150000 && this.getPC() != warmstart; i++) {
this.exports.machine_tick(this.sys);
}
}
// TODO: shouldn't we return here @ start of frame?
// and stop probing
}
}
advanceFrame(trap: TrapCondition) : number {
// TODO: does this sync with VSYNC?
var scanline = this.exports.machine_get_raster_line(this.sys);
var clocks = Math.floor((this.numTotalScanlines - scanline) * (19656+295+32) / this.numTotalScanlines);
var probing = this.probe != null;
if (probing) this.exports.machine_reset_probe_buffer();
clocks = super.advanceFrameClock(trap, clocks);
if (probing) this.copyProbeData();
return clocks;
}
getCPUState() {
this.exports.machine_save_cpu_state(this.sys, this.cpustateptr);
var s = this.cpustatearr;
var pc = s[2] + (s[3]<<8);
return {
PC:pc,
SP:s[9],
A:s[6],
X:s[7],
Y:s[8],
C:s[10] & 1,
Z:s[10] & 2,
I:s[10] & 4,
D:s[10] & 8,
V:s[10] & 64,
N:s[10] & 128,
o:this.readConst(pc),
}
}
saveState() {
this.exports.machine_save_state(this.sys, this.stateptr);
return {
c:this.getCPUState(),
state:this.statearr.slice(0),
ram:this.statearr.slice(18640, 18640+0x200), // ZP and stack (TODO)
};
}
loadState(state) : void {
this.statearr.set(state.state);
this.exports.machine_load_state(this.sys, this.stateptr);
}
getVideoParams() {
return {width:232, height:272, overscan:true, videoFrequency:50, aspect:1.5};
}
setKeyInput(key: number, code: number, flags: number): void {
// TODO: handle shifted keys
if (key == 16 || key == 17 || key == 18 || key == 224) return; // meta keys
//console.log(key, code, flags);
//if (flags & KeyFlags.Shift) { key += 64; }
// convert to vic20
var mask = 0;
var mask2 = 0;
if (key == 37) { key = 0x8; mask = 0x4; } // LEFT
if (key == 38) { key = 0xb; mask = 0x1; } // UP
if (key == 39) { key = 0x9; mask = 0x8; } // RIGHT
if (key == 40) { key = 0xa; mask = 0x2; } // DOWN
if (key == 32) { mask = 0x10; } // FIRE
/* player 2 (TODO)
if (key == 65) { key = 65; mask2 = 0x4; } // LEFT
if (key == 87) { key = 87; mask2 = 0x1; } // UP
if (key == 68) { key = 68; mask2 = 0x8; } // RIGHT
if (key == 83) { key = 83; mask2 = 0x2; } // DOWN
if (key == 69) { mask2 = 0x10; } // FIRE
*/
if (key == 113) { key = 0xf1; } // F2
if (key == 115) { key = 0xf3; } // F4
if (key == 119) { key = 0xf5; } // F8
if (key == 121) { key = 0xf7; } // F10
if (flags & KeyFlags.KeyDown) {
this.exports.machine_key_down(this.sys, key);
this.joymask0 |= mask;
this.joymask1 |= mask2;
} else if (flags & KeyFlags.KeyUp) {
this.exports.machine_key_up(this.sys, key);
this.joymask0 &= ~mask;
this.joymask1 &= ~mask2;
}
this.exports.vic20_joystick(this.sys, this.joymask0, this.joymask1);
}
}

View File

@ -26,6 +26,7 @@ export function importPlatform(name: string) : Promise<any> {
case "vector": return import("../platform/vector");
case "vectrex": return import("../platform/vectrex");
case "verilog": return import("../platform/verilog");
case "vic20": return import("../platform/vic20");
case "vicdual": return import("../platform/vicdual");
case "williams": return import("../platform/williams");
case "x86": return import("../platform/x86");

83
src/platform/vic20.ts Normal file
View File

@ -0,0 +1,83 @@
import { VIC20_WASMMachine } from "../machine/vic20";
import { Platform, Base6502MachinePlatform, getToolForFilename_6502, getOpcodeMetadata_6502 } from "../common/baseplatform";
import { PLATFORMS } from "../common/emu";
import { BaseMAME6502Platform } from "../common/mameplatform";
const VIC20_PRESETS = [
{id:'hello.dasm', name:'Hello World (ASM)'},
{id:'siegegame.c', name:'Siege Game (C)'},
];
const VIC20_MEMORY_MAP = { main:[
{name:'RAM', start:0x0000,size:0x0400,type:'ram'},
{name:'RAM', start:0x1000,size:0x1000,type:'ram'},
{name:'Cartridge ROM',start:0x8000,size:0x2000,type:'rom'},
{name:'BASIC ROM', start:0xc000,size:0x2000,type:'rom'},
{name:'I/O 1', start:0x9000,size:0x0400,type:'io'},
{name:'Color RAM', start:0x9400,size:0x0400,type:'io'},
{name:'I/O 2', start:0x9800,size:0x0400,type:'io'},
{name:'I/O 3', start:0x9c00,size:0x0400,type:'io'},
{name:'KERNAL ROM', start:0xe000,size:0x2000,type:'rom'},
] }
// WASM VIC20 platform
class VIC20WASMPlatform extends Base6502MachinePlatform<VIC20_WASMMachine> implements Platform {
newMachine() { return new VIC20_WASMMachine('vic20'); }
getPresets() { return VIC20_PRESETS; }
getDefaultExtension() { return ".c"; };
readAddress(a) { return this.machine.readConst(a); }
getMemoryMap() { return VIC20_MEMORY_MAP; }
showHelp() {
window.open("https://8bitworkshop.com/docs/platforms/vic20/", "_help");
}
getROMExtension(rom:Uint8Array) {
/*
if (rom && rom[0] == 0x00 && rom[1] == 0x80 && rom[2+4] == 0xc3 && rom[2+5] == 0xc2) return ".crt";
*/
if (rom && rom[0] == 0x01 && rom[1] == 0x08) return ".prg";
else return ".bin";
}
}
// VIC20 MAME platform (TODO)
abstract class VIC20MAMEPlatform extends BaseMAME6502Platform {
getPresets() { return VIC20_PRESETS; }
getToolForFilename = getToolForFilename_6502;
getOpcodeMetadata = getOpcodeMetadata_6502;
getDefaultExtension() { return ".c"; }
loadROM(title, data) {
if (!this.started) {
this.startModule(this.mainElement, {
jsfile:'mame8bitpc.js',
biosfile:'vic20.zip',
cfgfile:'vic20.cfg',
driver:'vic20',
width:418,
height:235,
romfn:'/emulator/image.crt',
romdata:new Uint8Array(data),
romsize:0x10000,
extraargs: ['-autoboot_delay','5','-autoboot_command','load "$",8,1\n'],
preInit:function(_self) {
},
});
} else {
this.loadROMFile(data);
this.loadRegion(":quickload", data);
var result = this.luacall(`image:load("/emulator/image.prg")`)
console.log('load rom', result);
//this.loadRegion(":exp:standard", data);
}
}
start() {
}
getMemoryMap() { return VIC20_MEMORY_MAP; }
}
PLATFORMS['vic20'] = VIC20WASMPlatform;
PLATFORMS['vic20.wasm'] = VIC20WASMPlatform;
PLATFORMS['vic20.mame'] = VIC20MAMEPlatform;

34764
src/worker/fs/fs65-vic20.data Normal file

File diff suppressed because one or more lines are too long

225
src/worker/fs/fs65-vic20.js Normal file
View File

@ -0,0 +1,225 @@
var Module = typeof Module !== 'undefined' ? Module : {};
if (!Module.expectedDataFileDownloads) {
Module.expectedDataFileDownloads = 0;
}
Module.expectedDataFileDownloads++;
(function() {
// When running as a pthread, FS operations are proxied to the main thread, so we don't need to
// fetch the .data bundle on the worker
if (Module['ENVIRONMENT_IS_PTHREAD']) return;
var loadPackage = function(metadata) {
var PACKAGE_PATH = '';
if (typeof window === 'object') {
PACKAGE_PATH = window['encodeURIComponent'](window.location.pathname.toString().substring(0, window.location.pathname.toString().lastIndexOf('/')) + '/');
} else if (typeof process === 'undefined' && typeof location !== 'undefined') {
// web worker
PACKAGE_PATH = encodeURIComponent(location.pathname.toString().substring(0, location.pathname.toString().lastIndexOf('/')) + '/');
}
var PACKAGE_NAME = '/home/pzp/8bitworkshop-compilers/output/fs/fs65-vic20.data';
var REMOTE_PACKAGE_BASE = 'fs65-vic20.data';
if (typeof Module['locateFilePackage'] === 'function' && !Module['locateFile']) {
Module['locateFile'] = Module['locateFilePackage'];
err('warning: you defined Module.locateFilePackage, that has been renamed to Module.locateFile (using your locateFilePackage for now)');
}
var REMOTE_PACKAGE_NAME = Module['locateFile'] ? Module['locateFile'](REMOTE_PACKAGE_BASE, '') : REMOTE_PACKAGE_BASE;
var REMOTE_PACKAGE_SIZE = metadata['remote_package_size'];
var PACKAGE_UUID = metadata['package_uuid'];
function fetchRemotePackage(packageName, packageSize, callback, errback) {
if (typeof process === 'object' && typeof process.versions === 'object' && typeof process.versions.node === 'string') {
require('fs').readFile(packageName, function(err, contents) {
if (err) {
errback(err);
} else {
callback(contents.buffer);
}
});
return;
}
var xhr = new XMLHttpRequest();
xhr.open('GET', packageName, true);
xhr.responseType = 'arraybuffer';
xhr.onprogress = function(event) {
var url = packageName;
var size = packageSize;
if (event.total) size = event.total;
if (event.loaded) {
if (!xhr.addedTotal) {
xhr.addedTotal = true;
if (!Module.dataFileDownloads) Module.dataFileDownloads = {};
Module.dataFileDownloads[url] = {
loaded: event.loaded,
total: size
};
} else {
Module.dataFileDownloads[url].loaded = event.loaded;
}
var total = 0;
var loaded = 0;
var num = 0;
for (var download in Module.dataFileDownloads) {
var data = Module.dataFileDownloads[download];
total += data.total;
loaded += data.loaded;
num++;
}
total = Math.ceil(total * Module.expectedDataFileDownloads/num);
if (Module['setStatus']) Module['setStatus']('Downloading data... (' + loaded + '/' + total + ')');
} else if (!Module.dataFileDownloads) {
if (Module['setStatus']) Module['setStatus']('Downloading data...');
}
};
xhr.onerror = function(event) {
throw new Error("NetworkError for: " + packageName);
}
xhr.onload = function(event) {
if (xhr.status == 200 || xhr.status == 304 || xhr.status == 206 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0
var packageData = xhr.response;
callback(packageData);
} else {
throw new Error(xhr.statusText + " : " + xhr.responseURL);
}
};
xhr.send(null);
};
function handleError(error) {
console.error('package error:', error);
};
var fetchedCallback = null;
var fetched = Module['getPreloadedPackage'] ? Module['getPreloadedPackage'](REMOTE_PACKAGE_NAME, REMOTE_PACKAGE_SIZE) : null;
if (!fetched) fetchRemotePackage(REMOTE_PACKAGE_NAME, REMOTE_PACKAGE_SIZE, function(data) {
if (fetchedCallback) {
fetchedCallback(data);
fetchedCallback = null;
} else {
fetched = data;
}
}, handleError);
function runWithFS() {
function assert(check, msg) {
if (!check) throw msg + new Error().stack;
}
Module['FS_createPath']("/", "include", true, true);
Module['FS_createPath']("/include", "em", true, true);
Module['FS_createPath']("/include", "geos", true, true);
Module['FS_createPath']("/include", "tgi", true, true);
Module['FS_createPath']("/include", "mouse", true, true);
Module['FS_createPath']("/include", "joystick", true, true);
Module['FS_createPath']("/include", "sys", true, true);
Module['FS_createPath']("/", "asminc", true, true);
Module['FS_createPath']("/", "cfg", true, true);
Module['FS_createPath']("/", "lib", true, true);
Module['FS_createPath']("/", "target", true, true);
Module['FS_createPath']("/target", "vic20", true, true);
Module['FS_createPath']("/target/vic20", "drv", true, true);
Module['FS_createPath']("/target/vic20/drv", "joy", true, true);
Module['FS_createPath']("/target/vic20/drv", "tgi", true, true);
Module['FS_createPath']("/target/vic20/drv", "emd", true, true);
/** @constructor */
function DataRequest(start, end, audio) {
this.start = start;
this.end = end;
this.audio = audio;
}
DataRequest.prototype = {
requests: {},
open: function(mode, name) {
this.name = name;
this.requests[name] = this;
Module['addRunDependency']('fp ' + this.name);
},
send: function() {},
onload: function() {
var byteArray = this.byteArray.subarray(this.start, this.end);
this.finish(byteArray);
},
finish: function(byteArray) {
var that = this;
Module['FS_createDataFile'](this.name, null, byteArray, true, true, true); // canOwn this data in the filesystem, it is a slide into the heap that will never change
Module['removeRunDependency']('fp ' + that.name);
this.requests[this.name] = null;
}
};
var files = metadata['files'];
for (var i = 0; i < files.length; ++i) {
new DataRequest(files[i]['start'], files[i]['end'], files[i]['audio'] || 0).open('GET', files[i]['filename']);
}
function processPackageData(arrayBuffer) {
assert(arrayBuffer, 'Loading data file failed.');
assert(arrayBuffer instanceof ArrayBuffer, 'bad input to processPackageData');
var byteArray = new Uint8Array(arrayBuffer);
var curr;
// Reuse the bytearray from the XHR as the source for file reads.
DataRequest.prototype.byteArray = byteArray;
var files = metadata['files'];
for (var i = 0; i < files.length; ++i) {
DataRequest.prototype.requests[files[i].filename].onload();
}
Module['removeRunDependency']('datafile_/home/pzp/8bitworkshop-compilers/output/fs/fs65-vic20.data');
};
Module['addRunDependency']('datafile_/home/pzp/8bitworkshop-compilers/output/fs/fs65-vic20.data');
if (!Module.preloadResults) Module.preloadResults = {};
Module.preloadResults[PACKAGE_NAME] = {fromCache: false};
if (fetched) {
processPackageData(fetched);
fetched = null;
} else {
fetchedCallback = processPackageData;
}
}
if (Module['calledRun']) {
runWithFS();
} else {
if (!Module['preRun']) Module['preRun'] = [];
Module["preRun"].push(runWithFS); // FS is not initialized yet, wait for it
}
Module['removeRunDependency']('fs65-vic20.js.metadata');
}
function runMetaWithFS() {
Module['addRunDependency']('fs65-vic20.js.metadata');
var REMOTE_METADATA_NAME = Module['locateFile'] ? Module['locateFile']('fs65-vic20.js.metadata', '') : 'fs65-vic20.js.metadata';
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
loadPackage(JSON.parse(xhr.responseText));
}
}
xhr.open('GET', REMOTE_METADATA_NAME, true);
xhr.overrideMimeType('application/json');
xhr.send(null);
}
if (Module['calledRun']) {
runMetaWithFS();
} else {
if (!Module['preRun']) Module['preRun'] = [];
Module["preRun"].push(runMetaWithFS);
}
})();

File diff suppressed because one or more lines are too long

View File

@ -320,6 +320,13 @@ var PLATFORM_PARAMS = {
libargs: ['c64.lib'],
//extra_link_files: ['c64-cart.cfg'],
},
'vic20': {
arch: '6502',
define: ['__CBM__', '__VIC20__'],
cfgfile: 'vic20.cfg',
libargs: ['vic20.lib'],
//extra_link_files: ['c64-cart.cfg'],
},
'kim1': {
arch: '6502',
},
@ -1138,6 +1145,8 @@ var TOOL_PRELOADFS = {
'ca65-apple2': '65-apple2',
'cc65-c64': '65-c64',
'ca65-c64': '65-c64',
'cc65-vic20': '65-vic20',
'ca65-vic20': '65-vic20',
'cc65-nes': '65-nes',
'ca65-nes': '65-nes',
'cc65-atari8': '65-atari8',