1
0
forked from sent/waves
waves/public/assets/g/commodoreclicker/js/c64/main.js
2025-04-09 17:11:14 -05:00

183 lines
5.0 KiB
JavaScript

define([
'c64/vic',
'c64/mmu',
'c64/cpu',
'c64/iec',
'c64/cia',
'c64/disk',
'thirdparty/jquery-ajax-blob-arraybuffer',
'thirdparty/jszip/dist/jszip.min'
], function(VIC, MMU, CPU, IEC, CIA, DISK, blob, JSZip) {
var C64 = {
MMU: MMU,
CPU: CPU,
IEC: IEC,
CIA: CIA,
DISK: DISK,
VIC: VIC
};
for (var i in C64) {
if (C64.hasOwnProperty(i)) {
C64[i].owner = C64;
C64[i].init.call(C64[i]);
}
}
C64.reset = function() {
C64.MMU.reset();
C64.CPU.reset();
C64.IEC.reset();
C64.CIA.reset();
C64.DISK.reset();
C64.VIC.reset();
C64.saveFrame(0, 1);
};
C64.savedFrames = {};
C64.saveFrame = function(frame, numFrames) {
if (C64.savedFrames[frame]) {
return;
}
if (numFrames > 2) {
numFrames = 2;
}
C64.savedFrames[frame] = {
MMU: C64.MMU.getState(),
CPU: C64.CPU.getState(),
IEC: C64.IEC.getState(),
CIA: C64.CIA.getState(),
DISK: C64.DISK.getState(),
VIC: C64.VIC.getState()
};
for (i in C64.savedFrames) {
if (i > 0 && i < (frame - numFrames)) {
delete C64.savedFrames[i];
}
}
};
C64.restoreFrame = function(frame) {
if (!C64.savedFrames[frame]) {
frame = 0;
}
for (i in C64.savedFrames[frame]) {
C64[i].setState(C64.savedFrames[frame][i]);
}
};
C64.dropFrame = function(frame) {
if (C64.savedFrames[frame]) {
delete C64.savedFrames[frame];
}
};
C64.loadPrg = function(prg) {
var promise = $.Deferred();
$.ajax({
url: prg,
dataType: 'arraybuffer',
beforeSend: function(xhr) {
xhr.overrideMimeType("text/plain; charset=x-user-defined");
}
}).done(function(data) {
var content = new Uint8Array(data);
var pc = content[0] + (content[1] * 256);
for (var i = 2; i < content.length; i++) {
this.MMU.ram[pc+i] = content[i];
}
this.CPU.reg.PC = pc;
promise.resolve();
}.bind(this));
return promise;
};
C64.loadDisk = function(d64) {
var promise = $.Deferred();
$.ajax({
url: d64,
dataType: 'arraybuffer',
beforeSend: function(xhr) {
xhr.overrideMimeType("text/plain; charset=x-user-defined");
}
}).done(function(data) {
this.dropFrame(0);
this.CPU.reset();
this.MMU.reset();
this.IEC.reset();
this.CIA.reset();
this.DISK.reset();
this.VIC.reset();
this.VIC.renderPixels(this.VIC.sizes.FRAME_SIZE * 10);
for (var i = 0; i < 65536; i++) {
this.MMU.ram[i] = DISK.loadDump[i];
}
this.CPU.reg.A = 0x00;
this.CPU.reg.X = 0x0C;
this.CPU.reg.Y = 0x26;
this.CPU.reg.PC = 0xE168;
this.CPU.reg.S = 0xE9;
this.DISK.load(data);
this.saveFrame(0, 1);
promise.resolve();
}.bind(this));
return promise;
};
C64.loadGame = function() {
var promise = $.Deferred();
$.ajax({
url: '/rom/game.zip',
dataType: 'arraybuffer',
beforeSend: function(xhr) {
xhr.overrideMimeType("text/plain; charset=x-user-defined");
}
}).done(function(data) {
this.dropFrame(0);
this.CPU.reset();
this.MMU.reset();
var i, zip = new JSZip();
zip.load(data);
var kernal = zip.file('kernal.rom').asUint8Array(),
basic = zip.file('basic.rom').asUint8Array(),
game = zip.file('game.bin').asUint8Array(),
loadDump = zip.file('loadram.bin').asUint8Array();
for (var i = 0; i < kernal.length; i++) {
this.MMU.romKernal[i] = kernal[i];
}
for (var i = 0; i < basic.length; i++) {
this.MMU.romBasic[i] = basic[i];
}
for (var i = 0; i < game.length; i++) {
this.MMU.ram[0xC000 + i] = game[i];
}
DISK.loadDump = new Uint8Array(loadDump);
this.IEC.reset();
this.CIA.reset();
this.DISK.reset();
this.VIC.reset();
this.VIC.renderPixels(this.VIC.sizes.FRAME_SIZE * 10);
this.CPU.reg.PC = 0xC000;
this.VIC.backContext.fillStyle = 'black';
this.VIC.backContext.fillRect(0, 0, this.VIC.sizes.RASTER_LENGTH, this.VIC.sizes.RASTER_COUNT);
this.saveFrame(0, 1);
promise.resolve();
}.bind(this));
return promise;
};
return C64;
});