1
0
mirror of https://github.com/sehugg/8bitworkshop.git synced 2025-02-18 00:30:43 +00:00

cleaned up galaxian platform

This commit is contained in:
Steven Hugg 2019-08-24 21:11:38 -04:00
parent 698d0c616c
commit 43f65b99ae

View File

@ -1,4 +1,3 @@
"use strict";
import { Platform, BaseZ80Platform } from "../baseplatform";
import { PLATFORMS, RAM, newAddressDecoder, padBytes, noise, setKeyboardFromMap, AnimationTimer, RasterVideo, Keys, makeKeycodeMap } from "../emu";
@ -37,43 +36,25 @@ const SCRAMBLE_KEYCODE_MAP = makeKeycodeMap([
//[Keys.VK_UP, 2, -0x10],
]);
const GalaxianVideo = function(rom:Uint8Array, vram:RAM, oram:RAM, palette:Uint32Array, options) {
const _GalaxianPlatform = function(mainElement, options) {
options = options || {};
var romSize = options.romSize || 0x4000;
var gfxBase = options.gfxBase || 0x2800;
var palBase = options.palBase || 0x3800;
var keyMap = options.keyMap || GALAXIAN_KEYCODE_MAP;
var missileWidth = options.missileWidth || 4;
var missileOffset = options.missileOffset || 0;
var cpu;
var ram, vram, oram : RAM;
var membus, iobus, rom, palette, outlatches;
var video, audio, timer, pixels;
var psg1, psg2;
var inputs;
var interruptEnabled = 0;
var starsEnabled = 0;
var watchdog_counter;
var frameCounter = 0;
var XTAL = 18432000.0;
var scanlinesPerFrame = 264;
var cpuFrequency = XTAL/6; // 3.072 MHz
var hsyncFrequency = XTAL/3/192/2; // 16 kHz
var vsyncFrequency = hsyncFrequency/132/2; // 60.606060 Hz
var vblankDuration = 1/vsyncFrequency * (20/132); // 2500 us
var cpuCyclesPerLine = cpuFrequency/hsyncFrequency;
var INITIAL_WATCHDOG = 8;
var showOffscreenObjects = false;
this.missileWidth = options.missileWidth || 4;
this.missileOffset = options.missileOffset || 0;
this.showOffscreenObjects = false;
this.frameCounter = 0;
this.starsEnabled = 0;
var stars = [];
for (var i = 0; i < 256; i++)
stars[i] = noise();
function drawScanline(pixels, sl) {
if (sl < 16 && !showOffscreenObjects) return; // offscreen
if (sl >= 240 && !showOffscreenObjects) return; // offscreen
this.advanceFrame = function() {
this.frameCounter = (this.frameCounter + 1) & 0xff;
}
this.drawScanline = function(pixels, sl) {
if (sl < 16 && !this.showOffscreenObjects) return; // offscreen
if (sl >= 240 && !this.showOffscreenObjects) return; // offscreen
// draw tiles
var pixofs = sl * 264;
var outi = pixofs; // starting output pixel in frame buffer
@ -104,7 +85,7 @@ const _GalaxianPlatform = function(mainElement, options) {
var yy = (sl - sy);
if (yy >= 0 && yy < 16) {
var sx = oram.mem[base + 3] + 1; // +1 pixel offset from tiles
if (sx == 0 && !showOffscreenObjects)
if (sx == 0 && !this.showOffscreenObjects)
continue; // drawn off-buffer
var code = oram.mem[base + 1];
var flipx = code & 0x40; // TODO: flipx
@ -112,7 +93,6 @@ const _GalaxianPlatform = function(mainElement, options) {
yy = 15 - yy;
code &= 0x3f;
var color0 = (oram.mem[base + 2] & 7) << 2;
var color0 = 0;
var addr = gfxBase + (code << 5) + (yy < 8 ? yy : yy + 8);
outi = pixofs + sx; //<< 1
var data1 = rom[addr];
@ -149,15 +129,15 @@ const _GalaxianPlatform = function(mainElement, options) {
which = i ? missile : shell;
if (which != 0xff) {
var sx = 255 - oram.mem[0x60 + (which << 2) + 3];
var outi = pixofs+sx-missileOffset;
var outi = pixofs + sx - this.missileOffset;
var col = which == 7 ? 0xffffff00 : 0xffffffff;
for (var j=0; j<missileWidth; j++)
for (var j = 0; j < this.missileWidth; j++)
pixels[outi++] = col;
}
}
// draw stars
if (starsEnabled) {
var starx = ((frameCounter + stars[sl & 0xff]) & 0xff);
if (this.starsEnabled) {
var starx = ((this.frameCounter + stars[sl & 0xff]) & 0xff);
if ((starx + sl) & 0x10) {
var outi = pixofs + starx;
if ((pixels[outi] & 0xffffff) == 0) {
@ -167,6 +147,33 @@ const _GalaxianPlatform = function(mainElement, options) {
}
}
}
const _GalaxianPlatform = function(mainElement, options) {
options = options || {};
var romSize = options.romSize || 0x4000;
var palBase = options.palBase || 0x3800;
var keyMap = options.keyMap || GALAXIAN_KEYCODE_MAP;
var cpu;
var ram, vram, oram: RAM;
var membus, iobus, rom, palette, outlatches;
var video, audio, timer, pixels;
var psg1, psg2;
var inputs;
var interruptEnabled = 0;
var watchdog_counter;
var XTAL = 18432000.0;
var scanlinesPerFrame = 264;
var cpuFrequency = XTAL / 6; // 3.072 MHz
var hsyncFrequency = XTAL / 3 / 192 / 2; // 16 kHz
var vsyncFrequency = hsyncFrequency / 132 / 2; // 60.606060 Hz
var vblankDuration = 1 / vsyncFrequency * (20 / 132); // 2500 us
var cpuCyclesPerLine = cpuFrequency / hsyncFrequency;
var INITIAL_WATCHDOG = 8;
var gfx; // = new GalaxianVideo(rom, vram, oram, palette, options);
var m_protection_state = 0;
var m_protection_result = 0;
function scramble_protection_w(addr, data) {
@ -177,8 +184,7 @@ const _GalaxianPlatform = function(mainElement, options) {
expects certain results in the upper nibble afterwards.
*/
m_protection_state = (m_protection_state << 4) | (data & 0x0f);
switch (m_protection_state & 0xfff)
{
switch (m_protection_state & 0xfff) {
/* scramble */
case 0xf09: m_protection_result = 0xff; break;
case 0xa49: m_protection_result = 0xbf; break;
@ -214,6 +220,10 @@ const _GalaxianPlatform = function(mainElement, options) {
ram = new RAM(0x800);
vram = new RAM(0x400);
oram = new RAM(0x100);
rom = new Uint8Array(romSize);
palette = new Uint32Array(new ArrayBuffer(32 * 4));
gfx = new GalaxianVideo(rom, vram, oram, palette, options);
outlatches = new RAM(0x8);
if (options.scramble) {
inputs = [0xff, 0xfc, 0xf1];
@ -243,9 +253,9 @@ const _GalaxianPlatform = function(mainElement, options) {
[0x6801, 0x6801, 0, function(a, v) { interruptEnabled = v & 1; /*console.log(a,v,cpu.getPC().toString(16));*/ }],
[0x6802, 0x6802, 0, function(a, v) { /* TODO: coin counter */ }],
[0x6803, 0x6803, 0, function(a, v) { /* TODO: backgroundColor = (v & 1) ? 0xFF000056 : 0xFF000000; */ }],
[0x6804, 0x6804, 0, function(a,v) { starsEnabled = v & 1; }],
[0x6808, 0x6808, 0, function(a,v) { missileWidth = v; }], // not on h/w
[0x6809, 0x6809, 0, function(a,v) { missileOffset = v; }], // not on h/w
[0x6804, 0x6804, 0, function(a, v) { gfx.starsEnabled = v & 1; }],
[0x6808, 0x6808, 0, function(a, v) { gfx.missileWidth = v; }], // not on h/w
[0x6809, 0x6809, 0, function(a, v) { gfx.missileOffset = v; }], // not on h/w
[0x8202, 0x8202, 0, scramble_protection_w],
//[0x8100, 0x8103, 0, function(a,v){ /* PPI 0 */ }],
//[0x8200, 0x8203, 0, function(a,v){ /* PPI 1 */ }],
@ -274,7 +284,7 @@ const _GalaxianPlatform = function(mainElement, options) {
//[0x7800, 0x7800, 0x7, function(a,v) { }], // pitch
[0x6000, 0x6003, 0x3, function(a, v) { outlatches.mem[a] = v; }],
[0x7001, 0x7001, 0, function(a, v) { interruptEnabled = v & 1; }],
[0x7004, 0x7004, 0, function(a,v) { starsEnabled = v & 1; }],
[0x7004, 0x7004, 0, function(a, v) { gfx.starsEnabled = v & 1; }],
]),
isContended: function() { return false; },
};
@ -312,15 +322,15 @@ const _GalaxianPlatform = function(mainElement, options) {
for (var sl = 0; sl < scanlinesPerFrame; sl++) {
this.scanline = sl;
if (!novideo) {
drawScanline(pixels, sl);
gfx.drawScanline(pixels, sl);
}
this.runCPU(cpu, cpuCyclesPerLine);
}
// visible area is 256x224 (before rotation)
if (!novideo) {
video.updateFrame(0, 0, 0, 0, showOffscreenObjects ? 264 : 256, 264);
video.updateFrame(0, 0, 0, 0, gfx.showOffscreenObjects ? 264 : 256, 264);
}
frameCounter = (frameCounter + 1) & 0xff;
gfx.advanceFrame();
if (watchdog_counter-- <= 0) {
console.log("WATCHDOG FIRED, PC ", hex(cpu.getPC())); // TODO: alert on video
this.reset();
@ -332,9 +342,8 @@ const _GalaxianPlatform = function(mainElement, options) {
getRasterScanline() { return this.scanline; }
loadROM(title, data) {
rom = padBytes(data, romSize);
rom.set(padBytes(data, romSize));
palette = new Uint32Array(new ArrayBuffer(32*4));
for (var i = 0; i < 32; i++) {
var b = rom[palBase + i];
palette[i] = 0xff000000;
@ -342,6 +351,7 @@ const _GalaxianPlatform = function(mainElement, options) {
if (((1 << j) & b))
palette[i] += bitcolors[j];
}
this.reset();
}
@ -352,8 +362,8 @@ const _GalaxianPlatform = function(mainElement, options) {
oram.mem.set(state.bo);
watchdog_counter = state.wdc;
interruptEnabled = state.ie;
starsEnabled = state.se;
frameCounter = state.fc;
gfx.starsEnabled = state.se;
gfx.frameCounter = state.fc;
inputs[0] = state.in0;
inputs[1] = state.in1;
inputs[2] = state.in2;
@ -364,9 +374,9 @@ const _GalaxianPlatform = function(mainElement, options) {
b: ram.mem.slice(0),
bv: vram.mem.slice(0),
bo: oram.mem.slice(0),
fc:frameCounter,
fc: gfx.frameCounter,
ie: interruptEnabled,
se:starsEnabled,
se: gfx.starsEnabled,
wdc: watchdog_counter,
in0: inputs[0],
in1: inputs[1],