1
0
mirror of https://github.com/sehugg/8bitworkshop.git synced 2024-12-23 18:31:08 +00:00

converted tms9918a to typescript class

This commit is contained in:
Steven Hugg 2018-11-19 11:48:56 -05:00
parent a1aa24f2e8
commit 97f69c2af1
4 changed files with 102 additions and 84 deletions

View File

@ -63,6 +63,7 @@ function require(modname) {
<script src="tss/js/tss/AudioLooper.js"></script> <script src="tss/js/tss/AudioLooper.js"></script>
<script src="tss/js/Log.js"></script> <script src="tss/js/Log.js"></script>
<script src="gen/video/tms9918a.js"></script>
<script src="gen/util.js"></script> <script src="gen/util.js"></script>
<script src="gen/store.js"></script> <script src="gen/store.js"></script>
<script src="src/vlist.js"></script> <script src="src/vlist.js"></script>

View File

@ -25,18 +25,55 @@ enum TMS9918A_Mode {
/** /**
* @constructor * @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.canvas = canvas;
this.cru = cru; this.cru = cru;
this.enableFlicker = enableFlicker; 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 = [ this.palette = [
[0, 0, 0], [0, 0, 0],
[0, 0, 0], [0, 0, 0],
@ -56,41 +93,11 @@ export function TMS9918A(canvas, cru, enableFlicker) {
[255, 255, 255] [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.canvasContext = this.canvas.getContext("2d");
this.imageData = null;
this.width = null;
this.height = null;
//this.log = Log.getLog();
this.reset(); this.reset();
} }
TMS9918A.prototype = { reset() {
reset: function () {
var i; var i;
for (i = 0; i < this.ram.length; 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.imageData = this.canvasContext.getImageData(0, 0, this.canvas.width, this.canvas.height);
this.width = this.canvas.width; this.width = this.canvas.width;
this.height = this.canvas.height; this.height = this.canvas.height;
}, }
drawFrame: function (timestamp) { drawFrame(timestamp:number) {
if (this.redrawRequired) { if (this.redrawRequired) {
for (var y = 0; y < this.height; y++) { for (var y = 0; y < this.height; y++) {
this.drawScanline(y); this.drawScanline(y);
@ -143,12 +150,12 @@ TMS9918A.prototype = {
this.updateCanvas(); this.updateCanvas();
this.redrawRequired = false; this.redrawRequired = false;
} }
}, }
initFrame: function (timestamp) { initFrame(timestamp:number) {
}, }
drawScanline: function (y) { drawScanline(y:number) {
var imageData = this.imageData.data, var imageData = this.imageData.data,
width = this.width, width = this.width,
imageDataAddr = (y * width) << 2, imageDataAddr = (y * width) << 2,
@ -344,13 +351,13 @@ TMS9918A.prototype = {
if (fifthSprite) { if (fifthSprite) {
this.statusRegister |= 0x40; this.statusRegister |= 0x40;
} }
}, }
updateCanvas: function () { updateCanvas() {
this.canvasContext.putImageData(this.imageData, 0, 0); this.canvasContext.putImageData(this.imageData, 0, 0);
}, }
writeAddress: function (i) { writeAddress(i:number) {
if (!this.latch) { if (!this.latch) {
this.addressRegister = (this.addressRegister & 0xFF00) | i; this.addressRegister = (this.addressRegister & 0xFF00) | i;
} }
@ -427,9 +434,9 @@ TMS9918A.prototype = {
this.redrawRequired = true; this.redrawRequired = true;
} }
this.latch = !this.latch; this.latch = !this.latch;
}, }
updateMode: function (reg0, reg1) { updateMode(reg0:number, reg1:number) {
this.bitmapMode = (reg0 & 0x02) !== 0; this.bitmapMode = (reg0 & 0x02) !== 0;
this.textMode = (reg1 & 0x10) !== 0; this.textMode = (reg1 & 0x10) !== 0;
// Check bitmap mode bit, not text or multicolor // Check bitmap mode bit, not text or multicolor
@ -483,9 +490,9 @@ TMS9918A.prototype = {
this.nameTable = (this.registers[2] & 0xf) << 10; this.nameTable = (this.registers[2] & 0xf) << 10;
this.spriteAttributeTable = (this.registers[5] & 0x7f) << 7; this.spriteAttributeTable = (this.registers[5] & 0x7f) << 7;
this.spritePatternTable = (this.registers[6] & 0x7) << 11; this.spritePatternTable = (this.registers[6] & 0x7) << 11;
}, }
updateTableMasks: function () { updateTableMasks() {
if (this.screenMode === TMS9918A_Mode.BITMAP) { if (this.screenMode === TMS9918A_Mode.BITMAP) {
this.colorTableMask = ((this.registers[3] & 0x7F) << 6) | 0x3F; // 000CCCCCCC111111 this.colorTableMask = ((this.registers[3] & 0x7F) << 6) | 0x3F; // 000CCCCCCC111111
this.patternTableMask = ((this.registers[4] & 0x03) << 11) | (this.colorTableMask & 0x7FF); // 000PPCCCCC111111 this.patternTableMask = ((this.registers[4] & 0x03) << 11) | (this.colorTableMask & 0x7FF); // 000PPCCCCC111111
@ -500,15 +507,15 @@ TMS9918A.prototype = {
this.colorTableMask = this.ramMask; this.colorTableMask = this.ramMask;
this.patternTableMask = this.ramMask; this.patternTableMask = this.ramMask;
} }
}, }
writeData: function (i) { writeData(i:number) {
this.ram[this.addressRegister++] = i; this.ram[this.addressRegister++] = i;
this.addressRegister &= this.ramMask; this.addressRegister &= this.ramMask;
this.redrawRequired = true; this.redrawRequired = true;
}, }
readStatus: function () { readStatus() : number {
var i = this.statusRegister; var i = this.statusRegister;
this.statusRegister = 0x1F; this.statusRegister = 0x1F;
if (this.interruptsOn) { if (this.interruptsOn) {
@ -516,20 +523,20 @@ TMS9918A.prototype = {
} }
this.latch = false; this.latch = false;
return i; return i;
}, }
readData: function () { readData() : number {
var i = this.prefetchByte; var i = this.prefetchByte;
this.prefetchByte = this.ram[this.addressRegister++]; this.prefetchByte = this.ram[this.addressRegister++];
this.addressRegister &= this.ramMask; this.addressRegister &= this.ramMask;
return i; return i;
}, }
getRAM: function () { getRAM() : Uint8Array {
return this.ram; return this.ram;
}, }
colorTableSize: function () { colorTableSize() : number {
if (this.screenMode === TMS9918A_Mode.GRAPHICS) { if (this.screenMode === TMS9918A_Mode.GRAPHICS) {
return 0x20; return 0x20;
} }
@ -539,18 +546,18 @@ TMS9918A.prototype = {
else { else {
return 0; return 0;
} }
}, }
patternTableSize: function () { patternTableSize() : number {
if (this.bitmapMode) { if (this.bitmapMode) {
return Math.min(this.patternTableMask + 1, 0x1800); return Math.min(this.patternTableMask + 1, 0x1800);
} }
else { else {
return 0x800; return 0x800;
} }
}, }
getRegsString: function () { getRegsString() : string {
var s = ""; var s = "";
for (var i = 0; i < this.registers.length; i++) { for (var i = 0; i < this.registers.length; i++) {
s += "VR" + i + ":" + hex(this.registers[i],2) + " "; 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) + " CT:" + hex(this.colorTable,4) + " (" + hex(this.colorTableSize(),4) + ") SDT:" + hex(this.spritePatternTable,4) +
" SAL:" + hex(this.spriteAttributeTable,4) + "\nVDP: " + hex(this.addressRegister,4); " SAL:" + hex(this.spriteAttributeTable,4) + "\nVDP: " + hex(this.addressRegister,4);
return s; return s;
}, }
hexView: function (start, length, anchorAddr) { hexView(start:number, length:number, anchorAddr:number) : {text,lineCount,anchorLine} {
var text = ""; var text = "";
var anchorLine = null; var anchorLine = null;
var addr = start; var addr = start;
var line = 0; var line = 0;
for (var i = 0; i < length && addr < 0x4000; addr++, i++) { for (var i = 0; i < length && addr < 0x4000; addr++, i++) {
if ((i & 0x000F) === 0) { if ((i & 0x000F) === 0) {
text += "\n" + addr.toHexWord() + ":"; text += "\n" + hex(addr,4) + ":";
line++; line++;
} }
text += " "; text += " ";
if (anchorAddr && anchorAddr === addr) { if (anchorAddr && anchorAddr === addr) {
anchorLine = line; anchorLine = line;
} }
var hex = this.ram[addr].toString(16).toUpperCase(); var hx = this.ram[addr].toString(16).toUpperCase();
if (hex.length === 1) { if (hx.length === 1) {
text += "0"; text += "0";
} }
text += hex; text += hx;
} }
return {text: text.substr(1), lineCount: line, anchorLine: anchorLine - 1}; 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; return addr < 0x4000 ? this.ram[addr] << 8 | this.ram[addr+1] : 0;
}, }
getCharAt: function (x, y) { getCharAt(x:number, y:number) : number {
x -= 24; x -= 24;
y -= 24; y -= 24;
if (!this.textMode) { if (!this.textMode) {
@ -597,14 +604,14 @@ TMS9918A.prototype = {
else { else {
return this.ram[this.nameTable + Math.floor((x - 8) / 6) + Math.floor(y / 8) * 40]; 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.flicker = value;
this.enableFlicker = value; this.enableFlicker = value;
}, }
getState: function () { getState() {
return { return {
ram: this.ram, ram: this.ram,
registers: this.registers, registers: this.registers,
@ -629,9 +636,9 @@ TMS9918A.prototype = {
bgColor: this.bgColor, bgColor: this.bgColor,
flicker: this.flicker flicker: this.flicker
}; };
}, }
restoreState: function (state) { restoreState(state) {
this.ram = state.ram; this.ram = state.ram;
this.registers = state.registers; this.registers = state.registers;
this.addressRegister = state.addressRegister; this.addressRegister = state.addressRegister;

View File

@ -42,6 +42,7 @@ var _williams = require('gen/platform/williams.js');
var _sound_williams = require('gen/platform/sound_williams.js'); var _sound_williams = require('gen/platform/sound_williams.js');
var _astrocade = require('gen/platform/astrocade.js'); var _astrocade = require('gen/platform/astrocade.js');
var _atari8 = require('gen/platform/atari8.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) }; }, getImageData: function(x,y,w,h) { return {data: new Uint32Array(w*h) }; },
fillRect: function(x,y,w,h) { }, fillRect: function(x,y,w,h) { },
drawImage: function(img,x,y,w,h) { }, drawImage: function(img,x,y,w,h) { },
putImageData: function(data,w,h) { } putImageData: function(data,w,h) { },
}; };
} }
global.navigator = {}; 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 /* TODO
it('Should run atari8-5200', () => { it('Should run atari8-5200', () => {
var platform = testPlatform('atari8-5200', 'hello.a.rom', 92, (platform, frameno) => { var platform = testPlatform('atari8-5200', 'hello.a.rom', 92, (platform, frameno) => {

Binary file not shown.