diff --git a/embed.html b/embed.html
index 55777ca3..6ff4b3a4 100644
--- a/embed.html
+++ b/embed.html
@@ -63,6 +63,7 @@ function require(modname) {
+
diff --git a/src/video/tms9918a.ts b/src/video/tms9918a.ts
index 39be382e..9fe7b621 100644
--- a/src/video/tms9918a.ts
+++ b/src/video/tms9918a.ts
@@ -25,18 +25,55 @@ enum TMS9918A_Mode {
/**
* @constructor
*/
-export function TMS9918A(canvas, cru, enableFlicker) {
+export class TMS9918A {
+
+ canvas;
+
+ cru : { setVDPInterrupt: (b:boolean) => void };
+ enableFlicker : boolean;
+
+ ram = new Uint8Array(16384); // VDP RAM
+ registers = new Uint8Array(8);
+ spriteBuffer = new Uint8Array(256);
+ addressRegister : number;
+ statusRegister : number;
+
+ palette : [number, number, number][];
+
+ latch : boolean;
+ prefetchByte : number;
+
+ displayOn = null;
+ interruptsOn = null;
+ screenMode : number;
+ bitmapMode : boolean;
+ textMode : boolean;
+ colorTable : number;
+ nameTable : number;
+ charPatternTable : number;
+ spriteAttributeTable : number;
+ spritePatternTable : number;
+ colorTableMask : number;
+ patternTableMask : number;
+ ramMask : number;
+ fgColor : number;
+ bgColor : number;
+
+ flicker : boolean;
+ redrawRequired : boolean;
+
+ canvasContext;
+ imageData;
+
+ width : number;
+ height : number;
+
+ constructor(canvas, cru, enableFlicker:boolean) {
this.canvas = canvas;
this.cru = cru;
this.enableFlicker = enableFlicker;
- this.ram = new Uint8Array(16384); // VDP RAM
- this.registers = new Uint8Array(8);
- this.spriteBuffer = new Uint8Array(256);
- this.addressRegister = null;
- this.statusRegister = null;
-
this.palette = [
[0, 0, 0],
[0, 0, 0],
@@ -56,41 +93,11 @@ export function TMS9918A(canvas, cru, enableFlicker) {
[255, 255, 255]
];
- this.latch = null;
- this.prefetchByte = null;
-
- this.displayOn = null;
- this.interruptsOn = null;
- this.screenMode = null;
- this.bitmapMode = null;
- this.textMode = null;
- this.colorTable = null;
- this.nameTable = null;
- this.charPatternTable = null;
- this.spriteAttributeTable = null;
- this.spritePatternTable = null;
- this.colorTableMask = null;
- this.patternTableMask = null;
- this.ramMask = null;
- this.fgColor = null;
- this.bgColor = null;
-
- this.flicker = null;
- this.redrawRequired = null;
-
this.canvasContext = this.canvas.getContext("2d");
- this.imageData = null;
- this.width = null;
- this.height = null;
-
- //this.log = Log.getLog();
-
this.reset();
-}
+ }
-TMS9918A.prototype = {
-
- reset: function () {
+ reset() {
var i;
for (i = 0; i < this.ram.length; i++) {
@@ -133,9 +140,9 @@ TMS9918A.prototype = {
this.imageData = this.canvasContext.getImageData(0, 0, this.canvas.width, this.canvas.height);
this.width = this.canvas.width;
this.height = this.canvas.height;
- },
+ }
- drawFrame: function (timestamp) {
+ drawFrame(timestamp:number) {
if (this.redrawRequired) {
for (var y = 0; y < this.height; y++) {
this.drawScanline(y);
@@ -143,12 +150,12 @@ TMS9918A.prototype = {
this.updateCanvas();
this.redrawRequired = false;
}
- },
+ }
- initFrame: function (timestamp) {
- },
+ initFrame(timestamp:number) {
+ }
- drawScanline: function (y) {
+ drawScanline(y:number) {
var imageData = this.imageData.data,
width = this.width,
imageDataAddr = (y * width) << 2,
@@ -344,13 +351,13 @@ TMS9918A.prototype = {
if (fifthSprite) {
this.statusRegister |= 0x40;
}
- },
+ }
- updateCanvas: function () {
+ updateCanvas() {
this.canvasContext.putImageData(this.imageData, 0, 0);
- },
+ }
- writeAddress: function (i) {
+ writeAddress(i:number) {
if (!this.latch) {
this.addressRegister = (this.addressRegister & 0xFF00) | i;
}
@@ -427,9 +434,9 @@ TMS9918A.prototype = {
this.redrawRequired = true;
}
this.latch = !this.latch;
- },
+ }
- updateMode: function (reg0, reg1) {
+ updateMode(reg0:number, reg1:number) {
this.bitmapMode = (reg0 & 0x02) !== 0;
this.textMode = (reg1 & 0x10) !== 0;
// Check bitmap mode bit, not text or multicolor
@@ -483,9 +490,9 @@ TMS9918A.prototype = {
this.nameTable = (this.registers[2] & 0xf) << 10;
this.spriteAttributeTable = (this.registers[5] & 0x7f) << 7;
this.spritePatternTable = (this.registers[6] & 0x7) << 11;
- },
+ }
- updateTableMasks: function () {
+ updateTableMasks() {
if (this.screenMode === TMS9918A_Mode.BITMAP) {
this.colorTableMask = ((this.registers[3] & 0x7F) << 6) | 0x3F; // 000CCCCCCC111111
this.patternTableMask = ((this.registers[4] & 0x03) << 11) | (this.colorTableMask & 0x7FF); // 000PPCCCCC111111
@@ -500,15 +507,15 @@ TMS9918A.prototype = {
this.colorTableMask = this.ramMask;
this.patternTableMask = this.ramMask;
}
- },
+ }
- writeData: function (i) {
+ writeData(i:number) {
this.ram[this.addressRegister++] = i;
this.addressRegister &= this.ramMask;
this.redrawRequired = true;
- },
+ }
- readStatus: function () {
+ readStatus() : number {
var i = this.statusRegister;
this.statusRegister = 0x1F;
if (this.interruptsOn) {
@@ -516,20 +523,20 @@ TMS9918A.prototype = {
}
this.latch = false;
return i;
- },
+ }
- readData: function () {
+ readData() : number {
var i = this.prefetchByte;
this.prefetchByte = this.ram[this.addressRegister++];
this.addressRegister &= this.ramMask;
return i;
- },
+ }
- getRAM: function () {
+ getRAM() : Uint8Array {
return this.ram;
- },
+ }
- colorTableSize: function () {
+ colorTableSize() : number {
if (this.screenMode === TMS9918A_Mode.GRAPHICS) {
return 0x20;
}
@@ -539,18 +546,18 @@ TMS9918A.prototype = {
else {
return 0;
}
- },
+ }
- patternTableSize: function () {
+ patternTableSize() : number {
if (this.bitmapMode) {
return Math.min(this.patternTableMask + 1, 0x1800);
}
else {
return 0x800;
}
- },
+ }
- getRegsString: function () {
+ getRegsString() : string {
var s = "";
for (var i = 0; i < this.registers.length; i++) {
s += "VR" + i + ":" + hex(this.registers[i],2) + " ";
@@ -559,36 +566,36 @@ TMS9918A.prototype = {
" CT:" + hex(this.colorTable,4) + " (" + hex(this.colorTableSize(),4) + ") SDT:" + hex(this.spritePatternTable,4) +
" SAL:" + hex(this.spriteAttributeTable,4) + "\nVDP: " + hex(this.addressRegister,4);
return s;
- },
+ }
- hexView: function (start, length, anchorAddr) {
+ hexView(start:number, length:number, anchorAddr:number) : {text,lineCount,anchorLine} {
var text = "";
var anchorLine = null;
var addr = start;
var line = 0;
for (var i = 0; i < length && addr < 0x4000; addr++, i++) {
if ((i & 0x000F) === 0) {
- text += "\n" + addr.toHexWord() + ":";
+ text += "\n" + hex(addr,4) + ":";
line++;
}
text += " ";
if (anchorAddr && anchorAddr === addr) {
anchorLine = line;
}
- var hex = this.ram[addr].toString(16).toUpperCase();
- if (hex.length === 1) {
+ var hx = this.ram[addr].toString(16).toUpperCase();
+ if (hx.length === 1) {
text += "0";
}
- text += hex;
+ text += hx;
}
return {text: text.substr(1), lineCount: line, anchorLine: anchorLine - 1};
- },
+ }
- getWord: function (addr) {
+ getWord(addr:number) : number {
return addr < 0x4000 ? this.ram[addr] << 8 | this.ram[addr+1] : 0;
- },
+ }
- getCharAt: function (x, y) {
+ getCharAt(x:number, y:number) : number {
x -= 24;
y -= 24;
if (!this.textMode) {
@@ -597,14 +604,14 @@ TMS9918A.prototype = {
else {
return this.ram[this.nameTable + Math.floor((x - 8) / 6) + Math.floor(y / 8) * 40];
}
- },
+ }
- setFlicker: function (value) {
+ setFlicker(value:boolean) {
this.flicker = value;
this.enableFlicker = value;
- },
+ }
- getState: function () {
+ getState() {
return {
ram: this.ram,
registers: this.registers,
@@ -629,9 +636,9 @@ TMS9918A.prototype = {
bgColor: this.bgColor,
flicker: this.flicker
};
- },
+ }
- restoreState: function (state) {
+ restoreState(state) {
this.ram = state.ram;
this.registers = state.registers;
this.addressRegister = state.addressRegister;
diff --git a/test/cli/testplatforms.js b/test/cli/testplatforms.js
index a0ff6d72..47655638 100644
--- a/test/cli/testplatforms.js
+++ b/test/cli/testplatforms.js
@@ -42,6 +42,7 @@ var _williams = require('gen/platform/williams.js');
var _sound_williams = require('gen/platform/sound_williams.js');
var _astrocade = require('gen/platform/astrocade.js');
var _atari8 = require('gen/platform/atari8.js');
+var _coleco = require('gen/platform/coleco.js');
//
@@ -50,7 +51,7 @@ dom.window.HTMLCanvasElement.prototype.getContext = function() {
getImageData: function(x,y,w,h) { return {data: new Uint32Array(w*h) }; },
fillRect: function(x,y,w,h) { },
drawImage: function(img,x,y,w,h) { },
- putImageData: function(data,w,h) { }
+ putImageData: function(data,w,h) { },
};
}
global.navigator = {};
@@ -223,6 +224,15 @@ describe('Platform Replay', () => {
}
});
});
+/*
+ it('Should run coleco', () => {
+ var platform = testPlatform('coleco', 'shoot.c.rom', 92, (platform, frameno) => {
+ if (frameno == 62) {
+ keycallback(Keys.VK_SPACE.c, Keys.VK_SPACE.c, 1);
+ }
+ });
+ });
+*/
/* TODO
it('Should run atari8-5200', () => {
var platform = testPlatform('atari8-5200', 'hello.a.rom', 92, (platform, frameno) => {
diff --git a/test/roms/coleco/shoot.c.rom b/test/roms/coleco/shoot.c.rom
new file mode 100644
index 00000000..63629a0b
Binary files /dev/null and b/test/roms/coleco/shoot.c.rom differ