mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-11-25 18:33:11 +00:00
log clocks at start of scanline; added everything to Platforms menu
This commit is contained in:
parent
d8421fee7f
commit
f32009ca0b
10
index.html
10
index.html
@ -147,13 +147,21 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
|
|||||||
<a tabindex="-1" href="#">Game Consoles</a>
|
<a tabindex="-1" href="#">Game Consoles</a>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
<li><a class="dropdown-item" href="?platform=vcs">Atari 2600</a></li>
|
<li><a class="dropdown-item" href="?platform=vcs">Atari 2600</a></li>
|
||||||
|
<li><a class="dropdown-item" href="?platform=astrocade">Bally Astrocade</a></li>
|
||||||
|
<li><a class="dropdown-item" href="?platform=coleco">ColecoVision</a></li>
|
||||||
<li><a class="dropdown-item" href="?platform=nes">NES</a></li>
|
<li><a class="dropdown-item" href="?platform=nes">NES</a></li>
|
||||||
|
<li><a class="dropdown-item" href="?platform=sms-sg1000-libcv">Sega SG-1000</a></li>
|
||||||
|
<li><a class="dropdown-item" href="?platform=sms-sms-libcv">Sega Master System</a></li>
|
||||||
|
<li><a class="dropdown-item" href="?platform=atari7800">Atari 7800</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown dropdown-submenu">
|
<li class="dropdown dropdown-submenu">
|
||||||
<a tabindex="-1" href="#">Computers</a>
|
<a tabindex="-1" href="#">Computers</a>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
<li><a class="dropdown-item" href="?platform=apple2">Apple ][+</a></li>
|
<li><a class="dropdown-item" href="?platform=apple2">Apple ][+</a></li>
|
||||||
|
<li><a class="dropdown-item" href="?platform=c64">Commodore 64</a></li>
|
||||||
|
<li><a class="dropdown-item" href="?platform=msx">MSX (BIOS)</a></li>
|
||||||
|
<li><a class="dropdown-item" href="?platform=msx-libcv">MSX (libCV)</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown dropdown-submenu">
|
<li class="dropdown dropdown-submenu">
|
||||||
@ -178,8 +186,8 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
|
|||||||
<a tabindex="-1" href="#">Other</a>
|
<a tabindex="-1" href="#">Other</a>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
<li><a class="dropdown-item" href="?platform=vcs.mame">Atari 2600 (MAME)</a></li>
|
<li><a class="dropdown-item" href="?platform=vcs.mame">Atari 2600 (MAME)</a></li>
|
||||||
<li><a class="dropdown-item" href="?platform=nes.mame">NES (MAME)</a></li>
|
|
||||||
<li><a class="dropdown-item" href="?platform=vector-ataricolor">Atari Color Vector (6502)</a></li>
|
<li><a class="dropdown-item" href="?platform=vector-ataricolor">Atari Color Vector (6502)</a></li>
|
||||||
|
<li><a class="dropdown-item" href="?platform=nes.mame">NES (MAME)</a></li>
|
||||||
<li><a class="dropdown-item" href="?platform=markdown">Markdown</a></li>
|
<li><a class="dropdown-item" href="?platform=markdown">Markdown</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
@ -360,6 +360,7 @@ export abstract class BasicScanlineMachine extends BasicMachine implements Raste
|
|||||||
}
|
}
|
||||||
this.drawScanline();
|
this.drawScanline();
|
||||||
this.probe.logNewScanline();
|
this.probe.logNewScanline();
|
||||||
|
this.probe.logClocks(clock-endLineClock);
|
||||||
}
|
}
|
||||||
this.postFrame();
|
this.postFrame();
|
||||||
return clock;
|
return clock;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
import { Platform, BaseZ80Platform } from "../baseplatform";
|
import { Platform, BaseZ80Platform } from "../baseplatform";
|
||||||
import { PLATFORMS, RAM, newAddressDecoder, padBytes, noise, setKeyboardFromMap, AnimationTimer, RasterVideo, Keys, makeKeycodeMap } from "../emu";
|
import { PLATFORMS, RAM, newAddressDecoder, padBytes, noise, setKeyboardFromMap, AnimationTimer, RasterVideo, Keys, makeKeycodeMap } from "../emu";
|
||||||
import { hex, lzgmini, stringToByteArray, rgb2bgr, clamp } from "../util";
|
import { hex, lzgmini, stringToByteArray, rgb2bgr, clamp } from "../util";
|
||||||
import { MasterAudio, AY38910_Audio } from "../audio";
|
import { MasterAudio, AY38910_Audio } from "../audio";
|
||||||
@ -8,23 +8,23 @@ import { MasterAudio, AY38910_Audio } from "../audio";
|
|||||||
// http://metopal.com/projects/ballybook/doku.php
|
// http://metopal.com/projects/ballybook/doku.php
|
||||||
|
|
||||||
const ASTROCADE_PRESETS = [
|
const ASTROCADE_PRESETS = [
|
||||||
{id:'01-helloworlds.asm', name:'Hello World'},
|
{ id: '01-helloworlds.asm', name: 'Hello World' },
|
||||||
{id:'02-telephone.asm', name:'Telephone'},
|
{ id: '02-telephone.asm', name: 'Telephone' },
|
||||||
{id:'03-horcbpal.asm', name:'Paddle Demo'},
|
{ id: '03-horcbpal.asm', name: 'Paddle Demo' },
|
||||||
{id:'hello.c', name:'Hello Graphics'},
|
{ id: 'hello.c', name: 'Hello Graphics' },
|
||||||
{id:'lines.c', name:'Lines'},
|
{ id: 'lines.c', name: 'Lines' },
|
||||||
{id:'sprites.c', name:'Sprites'},
|
{ id: 'sprites.c', name: 'Sprites' },
|
||||||
{id:'vsync.c', name:'Sprites w/ VSYNC'},
|
{ id: 'vsync.c', name: 'Sprites w/ VSYNC' },
|
||||||
{id:'fastsprites.c', name:'Fast Sprites'},
|
{ id: 'fastsprites.c', name: 'Fast Sprites' },
|
||||||
{id:'music.c', name:'Music'},
|
{ id: 'music.c', name: 'Music' },
|
||||||
{id:'rotate.c', name:'Rotate Op'},
|
{ id: 'rotate.c', name: 'Rotate Op' },
|
||||||
{id:'rainbow.c', name:'Rainbow'},
|
{ id: 'rainbow.c', name: 'Rainbow' },
|
||||||
{id:'cosmic.c', name:'Cosmic Impalas Game'},
|
{ id: 'cosmic.c', name: 'Cosmic Impalas Game' },
|
||||||
{id:'racing.c', name:'Pseudo 3-D Racing Game'},
|
{ id: 'racing.c', name: 'Pseudo 3-D Racing Game' },
|
||||||
];
|
];
|
||||||
|
|
||||||
const ASTROCADE_BIOS_PRESETS = [
|
const ASTROCADE_BIOS_PRESETS = [
|
||||||
{id:'bios.c', name:'BIOS'},
|
{ id: 'bios.c', name: 'BIOS' },
|
||||||
];
|
];
|
||||||
|
|
||||||
// TODO: fix keys, more controllers, vibrato/noise, border color, debug info, rotate
|
// TODO: fix keys, more controllers, vibrato/noise, border color, debug info, rotate
|
||||||
@ -32,45 +32,45 @@ const ASTROCADE_BIOS_PRESETS = [
|
|||||||
|
|
||||||
const ASTROCADE_KEYCODE_MAP = makeKeycodeMap([
|
const ASTROCADE_KEYCODE_MAP = makeKeycodeMap([
|
||||||
// player 1
|
// player 1
|
||||||
[Keys.UP, 0x10, 0x1],
|
[Keys.UP, 0x10, 0x1],
|
||||||
[Keys.DOWN, 0x10, 0x2],
|
[Keys.DOWN, 0x10, 0x2],
|
||||||
[Keys.LEFT, 0x10, 0x4],
|
[Keys.LEFT, 0x10, 0x4],
|
||||||
[Keys.RIGHT, 0x10, 0x8],
|
[Keys.RIGHT, 0x10, 0x8],
|
||||||
[Keys.A, 0x10, 0x10],
|
[Keys.A, 0x10, 0x10],
|
||||||
// player 2
|
// player 2
|
||||||
[Keys.P2_UP, 0x11, 0x1],
|
[Keys.P2_UP, 0x11, 0x1],
|
||||||
[Keys.P2_DOWN, 0x11, 0x2],
|
[Keys.P2_DOWN, 0x11, 0x2],
|
||||||
[Keys.P2_LEFT, 0x11, 0x4],
|
[Keys.P2_LEFT, 0x11, 0x4],
|
||||||
[Keys.P2_RIGHT, 0x11, 0x8],
|
[Keys.P2_RIGHT, 0x11, 0x8],
|
||||||
[Keys.P2_A, 0x11, 0x10],
|
[Keys.P2_A, 0x11, 0x10],
|
||||||
// keypad $14
|
// keypad $14
|
||||||
[Keys.VK_P, 0x14, 0x1],
|
[Keys.VK_P, 0x14, 0x1],
|
||||||
[Keys.VK_SLASH, 0x14, 0x2],
|
[Keys.VK_SLASH, 0x14, 0x2],
|
||||||
[Keys.VK_X, 0x14, 0x4],
|
[Keys.VK_X, 0x14, 0x4],
|
||||||
[Keys.VK_MINUS, 0x14, 0x8],
|
[Keys.VK_MINUS, 0x14, 0x8],
|
||||||
[Keys.VK_COMMA, 0x14, 0x10],
|
[Keys.VK_COMMA, 0x14, 0x10],
|
||||||
[Keys.VK_EQUALS,0x14, 0x20],
|
[Keys.VK_EQUALS, 0x14, 0x20],
|
||||||
// keypad $15
|
// keypad $15
|
||||||
[Keys.VK_O, 0x15, 0x1],
|
[Keys.VK_O, 0x15, 0x1],
|
||||||
[Keys.VK_L, 0x15, 0x2],
|
[Keys.VK_L, 0x15, 0x2],
|
||||||
[Keys.VK_9, 0x15, 0x4],
|
[Keys.VK_9, 0x15, 0x4],
|
||||||
[Keys.VK_6, 0x15, 0x8],
|
[Keys.VK_6, 0x15, 0x8],
|
||||||
[Keys.VK_3, 0x15, 0x10],
|
[Keys.VK_3, 0x15, 0x10],
|
||||||
[Keys.VK_PERIOD,0x15, 0x20],
|
[Keys.VK_PERIOD, 0x15, 0x20],
|
||||||
// keypad $16
|
// keypad $16
|
||||||
[Keys.VK_I, 0x16, 0x1],
|
[Keys.VK_I, 0x16, 0x1],
|
||||||
[Keys.VK_K, 0x16, 0x2],
|
[Keys.VK_K, 0x16, 0x2],
|
||||||
[Keys.VK_8, 0x16, 0x4],
|
[Keys.VK_8, 0x16, 0x4],
|
||||||
[Keys.VK_5, 0x16, 0x8],
|
[Keys.VK_5, 0x16, 0x8],
|
||||||
[Keys.VK_2, 0x16, 0x10],
|
[Keys.VK_2, 0x16, 0x10],
|
||||||
[Keys.VK_0, 0x16, 0x20],
|
[Keys.VK_0, 0x16, 0x20],
|
||||||
// keypad $17
|
// keypad $17
|
||||||
[Keys.VK_U, 0x17, 0x1],
|
[Keys.VK_U, 0x17, 0x1],
|
||||||
[Keys.VK_J, 0x17, 0x2],
|
[Keys.VK_J, 0x17, 0x2],
|
||||||
[Keys.VK_7, 0x17, 0x4],
|
[Keys.VK_7, 0x17, 0x4],
|
||||||
[Keys.VK_4, 0x17, 0x8],
|
[Keys.VK_4, 0x17, 0x8],
|
||||||
[Keys.VK_1, 0x17, 0x10],
|
[Keys.VK_1, 0x17, 0x10],
|
||||||
[Keys.VK_BACK_SLASH, 0x17, 0x20],
|
[Keys.VK_BACK_SLASH, 0x17, 0x20],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const _BallyAstrocadePlatform = function(mainElement, arcade) {
|
const _BallyAstrocadePlatform = function(mainElement, arcade) {
|
||||||
@ -83,8 +83,8 @@ const _BallyAstrocadePlatform = function(mainElement, arcade) {
|
|||||||
const sheight = arcade ? 204 : 102;
|
const sheight = arcade ? 204 : 102;
|
||||||
const swbytes = Math.floor(swidth / 4);
|
const swbytes = Math.floor(swidth / 4);
|
||||||
const cpuFrequency = 1789000;
|
const cpuFrequency = 1789000;
|
||||||
const cpuCyclesPerLine = Math.floor(cpuFrequency/(60*262.5));
|
const cpuCyclesPerLine = Math.floor(cpuFrequency / (60 * 262.5));
|
||||||
const cpuCyclesPerHBlank = Math.floor(cpuCyclesPerLine*0.33);
|
const cpuCyclesPerHBlank = Math.floor(cpuCyclesPerLine * 0.33);
|
||||||
const cpuCyclesPerVisible = cpuCyclesPerLine - cpuCyclesPerHBlank;
|
const cpuCyclesPerVisible = cpuCyclesPerLine - cpuCyclesPerHBlank;
|
||||||
const INITIAL_WATCHDOG = 256;
|
const INITIAL_WATCHDOG = 256;
|
||||||
const PIXEL_ON = 0xffeeeeee;
|
const PIXEL_ON = 0xffeeeeee;
|
||||||
@ -109,41 +109,41 @@ const _BallyAstrocadePlatform = function(mainElement, arcade) {
|
|||||||
var rotdata = new Uint8Array(4);
|
var rotdata = new Uint8Array(4);
|
||||||
var rotcount = 0;
|
var rotcount = 0;
|
||||||
var intst = 0;
|
var intst = 0;
|
||||||
|
|
||||||
function ramwrite(a:number, v:number) {
|
function ramwrite(a: number, v: number) {
|
||||||
// set RAM
|
// set RAM
|
||||||
ram.mem[a] = v;
|
ram.mem[a] = v;
|
||||||
// mark scanline as dirty
|
// mark scanline as dirty
|
||||||
dirtylines[Math.floor((a & 0xfff)/swbytes)] = 1;
|
dirtylines[Math.floor((a & 0xfff) / swbytes)] = 1;
|
||||||
// this was old behavior where we updated instantly
|
// this was old behavior where we updated instantly
|
||||||
// but it had problems if we had mid-screen palette changes
|
// but it had problems if we had mid-screen palette changes
|
||||||
//ramupdate(a, v);
|
//ramupdate(a, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ramupdate(a:number, v:number) {
|
function ramupdate(a: number, v: number) {
|
||||||
var ofs = a*4+3; // 4 pixels per byte
|
var ofs = a * 4 + 3; // 4 pixels per byte
|
||||||
for (var i=0; i<4; i++) {
|
for (var i = 0; i < 4; i++) {
|
||||||
var lr = ((a % swbytes) >= (horcb & 0x3f)) ? 0 : 4;
|
var lr = ((a % swbytes) >= (horcb & 0x3f)) ? 0 : 4;
|
||||||
pixels[ofs--] = palette[lr + (v & 3)];
|
pixels[ofs--] = palette[lr + (v & 3)];
|
||||||
v >>= 2;
|
v >>= 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function refreshline(y:number) {
|
function refreshline(y: number) {
|
||||||
var ofs = y*swidth/4;
|
var ofs = y * swidth / 4;
|
||||||
for (var i=0; i<swidth/4; i++)
|
for (var i = 0; i < swidth / 4; i++)
|
||||||
ramupdate(ofs+i, ram.mem[ofs+i]);
|
ramupdate(ofs + i, ram.mem[ofs + i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function magicwrite(a:number, v:number) {
|
function magicwrite(a: number, v: number) {
|
||||||
// expand
|
// expand
|
||||||
if (magicop & 0x8) {
|
if (magicop & 0x8) {
|
||||||
var v2 = 0;
|
var v2 = 0;
|
||||||
if (!xplower)
|
if (!xplower)
|
||||||
v >>= 4;
|
v >>= 4;
|
||||||
for (var i=0; i<4; i++) {
|
for (var i = 0; i < 4; i++) {
|
||||||
var pix = (v&1) ? ((xpand>>2)&3) : (xpand&3);
|
var pix = (v & 1) ? ((xpand >> 2) & 3) : (xpand & 3);
|
||||||
v2 |= pix << (i*2);
|
v2 |= pix << (i * 2);
|
||||||
v >>= 1;
|
v >>= 1;
|
||||||
}
|
}
|
||||||
v = v2;
|
v = v2;
|
||||||
@ -155,9 +155,9 @@ const _BallyAstrocadePlatform = function(mainElement, arcade) {
|
|||||||
// drain buffer
|
// drain buffer
|
||||||
var sh = 2 * (~rotcount & 3);
|
var sh = 2 * (~rotcount & 3);
|
||||||
v = (((rotdata[3] >> sh) & 3) << 6) |
|
v = (((rotdata[3] >> sh) & 3) << 6) |
|
||||||
(((rotdata[2] >> sh) & 3) << 4) |
|
(((rotdata[2] >> sh) & 3) << 4) |
|
||||||
(((rotdata[1] >> sh) & 3) << 2) |
|
(((rotdata[1] >> sh) & 3) << 2) |
|
||||||
(((rotdata[0] >> sh) & 3) << 0);
|
(((rotdata[0] >> sh) & 3) << 0);
|
||||||
} else {
|
} else {
|
||||||
// fill buffer
|
// fill buffer
|
||||||
rotdata[rotcount & 3] = v;
|
rotdata[rotcount & 3] = v;
|
||||||
@ -167,12 +167,12 @@ const _BallyAstrocadePlatform = function(mainElement, arcade) {
|
|||||||
// shift
|
// shift
|
||||||
var sh = (magicop & 3) << 1;
|
var sh = (magicop & 3) << 1;
|
||||||
var v2 = (v >> sh) | shift2;
|
var v2 = (v >> sh) | shift2;
|
||||||
shift2 = (v << (8-sh)) & 0xff;
|
shift2 = (v << (8 - sh)) & 0xff;
|
||||||
v = v2;
|
v = v2;
|
||||||
}
|
}
|
||||||
// flop
|
// flop
|
||||||
if (magicop & 0x40) {
|
if (magicop & 0x40) {
|
||||||
v =
|
v =
|
||||||
((v & 0x03) << 6) |
|
((v & 0x03) << 6) |
|
||||||
((v & 0x0c) << 2) |
|
((v & 0x0c) << 2) |
|
||||||
((v & 0x30) >> 2) |
|
((v & 0x30) >> 2) |
|
||||||
@ -193,15 +193,15 @@ const _BallyAstrocadePlatform = function(mainElement, arcade) {
|
|||||||
if (magicop & 0x20)
|
if (magicop & 0x20)
|
||||||
v ^= oldv; // TODO: what if both?
|
v ^= oldv; // TODO: what if both?
|
||||||
// upper 4 bits persist, lower are just since last write
|
// upper 4 bits persist, lower are just since last write
|
||||||
intst = (intst & 0xf0) | icpt | (icpt<<4);
|
intst = (intst & 0xf0) | icpt | (icpt << 4);
|
||||||
}
|
}
|
||||||
// commit write to ram/screen
|
// commit write to ram/screen
|
||||||
ramwrite(a, v);
|
ramwrite(a, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setpalette(a:number, v:number) {
|
function setpalette(a: number, v: number) {
|
||||||
palinds[a&7] = v&0xff;
|
palinds[a & 7] = v & 0xff;
|
||||||
palette[a&7] = ASTROCADE_PALETTE[v&0xff];
|
palette[a & 7] = ASTROCADE_PALETTE[v & 0xff];
|
||||||
refreshall();
|
refreshall();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,327 +214,327 @@ const _BallyAstrocadePlatform = function(mainElement, arcade) {
|
|||||||
refreshlines = sheight;
|
refreshlines = sheight;
|
||||||
}
|
}
|
||||||
|
|
||||||
class BallyAstrocadePlatform extends BaseZ80Platform implements Platform {
|
class BallyAstrocadePlatform extends BaseZ80Platform implements Platform {
|
||||||
|
|
||||||
scanline : number;
|
|
||||||
poller;
|
|
||||||
|
|
||||||
getPresets() {
|
scanline: number;
|
||||||
return ASTROCADE_PRESETS;
|
poller;
|
||||||
}
|
|
||||||
|
|
||||||
start = function() {
|
getPresets() {
|
||||||
ram = new RAM(arcade ? 0x5000 : 0x1000);
|
return ASTROCADE_PRESETS;
|
||||||
//bios = padBytes(ASTROCADE_MINIMAL_BIOS, 0x2000);
|
|
||||||
bios = padBytes(new lzgmini().decode(stringToByteArray(atob(ASTROLIBRE_BIOS_LZG))), 0x2000);
|
|
||||||
if (!arcade) {
|
|
||||||
// game console
|
|
||||||
membus = {
|
|
||||||
read: newAddressDecoder([
|
|
||||||
[0x0000, 0x1fff, 0x1fff, function(a) { return bios[a]; }],
|
|
||||||
[0x2000, 0x3fff, 0x1fff, function(a) { return rom ? rom[a] : 0; }],
|
|
||||||
[0x4000, 0x4fff, 0xfff, function(a) { return ram.mem[a]; }],
|
|
||||||
]),
|
|
||||||
write: newAddressDecoder([
|
|
||||||
[0x4000, 0x4fff, 0xfff, ramwrite],
|
|
||||||
[0x0000, 0x3fff, 0xfff, magicwrite],
|
|
||||||
]),
|
|
||||||
// TODO: correct values?
|
|
||||||
isContended: () => { return true; },
|
|
||||||
contend: (addr:number) => { return vidactive && addr >= 0x4000 ? 1 : 0; },
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
// arcade game
|
|
||||||
membus = {
|
|
||||||
read: newAddressDecoder([
|
|
||||||
[0x4000, 0x7fff, 0x3fff, function(a) { return ram.mem[a]; }], // screen RAM
|
|
||||||
[0xd000, 0xdfff, 0xfff, function(a) { return ram.mem[a+0x4000]; }], // static RAM
|
|
||||||
[0x0000, 0xafff, 0xffff, function(a) { return rom ? rom[a] : 0; }], // ROM (0-3fff,8000-afff)
|
|
||||||
]),
|
|
||||||
write: newAddressDecoder([
|
|
||||||
[0x4000, 0x7fff, 0x3fff, ramwrite],
|
|
||||||
[0xd000, 0xdfff, 0xfff, function(a,v) { ramwrite(a+0x4000, v); } ], // static RAM
|
|
||||||
[0x0000, 0x3fff, 0x3fff, magicwrite],
|
|
||||||
]),
|
|
||||||
isContended: () => { return true; },
|
|
||||||
contend: (addr:number) => { return vidactive ? 1 : 0; },
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
iobus = {
|
|
||||||
isULAPort: function(addr) {
|
start = function() {
|
||||||
return false; // TODO?
|
ram = new RAM(arcade ? 0x5000 : 0x1000);
|
||||||
},
|
//bios = padBytes(ASTROCADE_MINIMAL_BIOS, 0x2000);
|
||||||
contend: function(addr) {
|
bios = padBytes(new lzgmini().decode(stringToByteArray(atob(ASTROLIBRE_BIOS_LZG))), 0x2000);
|
||||||
return 0; // TODO?
|
if (!arcade) {
|
||||||
},
|
// game console
|
||||||
read: function(addr) {
|
membus = {
|
||||||
addr &= 0x1f;
|
read: newAddressDecoder([
|
||||||
var rtn;
|
[0x0000, 0x1fff, 0x1fff, function(a) { return bios[a]; }],
|
||||||
switch (addr) {
|
[0x2000, 0x3fff, 0x1fff, function(a) { return rom ? rom[a] : 0; }],
|
||||||
case 8:
|
[0x4000, 0x4fff, 0xfff, function(a) { return ram.mem[a]; }],
|
||||||
rtn = intst;
|
]),
|
||||||
intst = 0;
|
write: newAddressDecoder([
|
||||||
break;
|
[0x4000, 0x4fff, 0xfff, ramwrite],
|
||||||
default:
|
[0x0000, 0x3fff, 0xfff, magicwrite],
|
||||||
rtn = inputs[addr];
|
]),
|
||||||
break;
|
// TODO: correct values?
|
||||||
// $10 = watchdog
|
isContended: () => { return true; },
|
||||||
|
contend: (addr: number) => { return vidactive && addr >= 0x4000 ? 1 : 0; },
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
// arcade game
|
||||||
|
membus = {
|
||||||
|
read: newAddressDecoder([
|
||||||
|
[0x4000, 0x7fff, 0x3fff, function(a) { return ram.mem[a]; }], // screen RAM
|
||||||
|
[0xd000, 0xdfff, 0xfff, function(a) { return ram.mem[a + 0x4000]; }], // static RAM
|
||||||
|
[0x0000, 0xafff, 0xffff, function(a) { return rom ? rom[a] : 0; }], // ROM (0-3fff,8000-afff)
|
||||||
|
]),
|
||||||
|
write: newAddressDecoder([
|
||||||
|
[0x4000, 0x7fff, 0x3fff, ramwrite],
|
||||||
|
[0xd000, 0xdfff, 0xfff, function(a, v) { ramwrite(a + 0x4000, v); }], // static RAM
|
||||||
|
[0x0000, 0x3fff, 0x3fff, magicwrite],
|
||||||
|
]),
|
||||||
|
isContended: () => { return true; },
|
||||||
|
contend: (addr: number) => { return vidactive ? 1 : 0; },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
iobus = {
|
||||||
|
isULAPort: function(addr) {
|
||||||
|
return false; // TODO?
|
||||||
|
},
|
||||||
|
contend: function(addr) {
|
||||||
|
return 0; // TODO?
|
||||||
|
},
|
||||||
|
read: function(addr) {
|
||||||
|
addr &= 0x1f;
|
||||||
|
var rtn;
|
||||||
|
switch (addr) {
|
||||||
|
case 8:
|
||||||
|
rtn = intst;
|
||||||
|
intst = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
rtn = inputs[addr];
|
||||||
|
break;
|
||||||
|
// $10 = watchdog
|
||||||
|
}
|
||||||
|
return rtn;
|
||||||
|
},
|
||||||
|
write: function(addr, val) {
|
||||||
|
addr &= 0x1f;
|
||||||
|
val &= 0xff;
|
||||||
|
switch (addr) {
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
case 4:
|
||||||
|
case 5:
|
||||||
|
case 6:
|
||||||
|
case 7:
|
||||||
|
setpalette(addr, val);
|
||||||
|
break;
|
||||||
|
case 9: // HORCB (horizontal boundary byte)
|
||||||
|
horcb = val;
|
||||||
|
setbordercolor();
|
||||||
|
refreshall();
|
||||||
|
break;
|
||||||
|
case 0xa: // VERBL (vertical blank)
|
||||||
|
verbl = arcade ? val : val >> 1;
|
||||||
|
refreshall();
|
||||||
|
break;
|
||||||
|
case 0xb: // OTIR (set palette)
|
||||||
|
var c = cpu.saveState();
|
||||||
|
//console.log(c.BC>>8, c.HL);
|
||||||
|
setpalette((c.BC >> 8) - 1, membus.read(c.HL));
|
||||||
|
break;
|
||||||
|
case 0xc: // magic register
|
||||||
|
magicop = val;
|
||||||
|
shift2 = 0;
|
||||||
|
rotcount = 0;
|
||||||
|
xplower = false;
|
||||||
|
break;
|
||||||
|
case 0xd: // INFBK (interrupt feedback)
|
||||||
|
infbk = val;
|
||||||
|
break;
|
||||||
|
case 0xe: // INMOD (interrupt enable)
|
||||||
|
inmod = val;
|
||||||
|
break;
|
||||||
|
case 0xf: // INLIN (interrupt line)
|
||||||
|
inlin = arcade ? val : val >> 1;
|
||||||
|
break;
|
||||||
|
case 0x10:
|
||||||
|
case 0x11:
|
||||||
|
case 0x12:
|
||||||
|
case 0x13:
|
||||||
|
case 0x14:
|
||||||
|
case 0x15:
|
||||||
|
case 0x16:
|
||||||
|
case 0x17:
|
||||||
|
psg.setACRegister(addr, val);
|
||||||
|
break;
|
||||||
|
case 0x18:
|
||||||
|
var c = cpu.saveState();
|
||||||
|
psg.setACRegister((c.BC >> 8) - 1, membus.read(c.HL));
|
||||||
|
break;
|
||||||
|
case 0x19: // XPAND
|
||||||
|
xpand = val;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.log('IO write', hex(addr, 4), hex(val, 2));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return rtn;
|
};
|
||||||
},
|
cpu = this.newCPU(membus, iobus, { applyContention: true });
|
||||||
write: function(addr, val) {
|
audio = new MasterAudio();
|
||||||
addr &= 0x1f;
|
psg = new AstrocadeAudio(audio);
|
||||||
val &= 0xff;
|
video = new RasterVideo(mainElement, swidth, sheight, {});
|
||||||
switch (addr) {
|
video.create();
|
||||||
case 0:
|
video.setupMouseEvents();
|
||||||
case 1:
|
var idata = video.getFrameData();
|
||||||
case 2:
|
this.poller = setKeyboardFromMap(video, inputs, ASTROCADE_KEYCODE_MAP);
|
||||||
case 3:
|
pixels = video.getFrameData();
|
||||||
case 4:
|
timer = new AnimationTimer(60, this.nextFrame.bind(this));
|
||||||
case 5:
|
// default palette
|
||||||
case 6:
|
for (var i = 0; i < 8; i++) {
|
||||||
case 7:
|
palinds[i] = i;
|
||||||
setpalette(addr,val);
|
palette[i] = ASTROCADE_PALETTE[i];
|
||||||
break;
|
}
|
||||||
case 9: // HORCB (horizontal boundary byte)
|
}
|
||||||
horcb = val;
|
|
||||||
setbordercolor();
|
readAddress(addr) {
|
||||||
refreshall();
|
return membus.read(addr);
|
||||||
break;
|
}
|
||||||
case 0xa: // VERBL (vertical blank)
|
|
||||||
verbl = arcade ? val : val >> 1;
|
loadControls() {
|
||||||
refreshall();
|
inputs[0x1c] = video.paddle_x & 0xff;
|
||||||
break;
|
inputs[0x1d] = video.paddle_y & 0xff;
|
||||||
case 0xb: // OTIR (set palette)
|
}
|
||||||
var c = cpu.saveState();
|
|
||||||
//console.log(c.BC>>8, c.HL);
|
pollControls() { this.poller.poll(); }
|
||||||
setpalette((c.BC>>8)-1, membus.read(c.HL));
|
|
||||||
break;
|
advance(novideo: boolean) {
|
||||||
case 0xc: // magic register
|
this.scanline = 0;
|
||||||
magicop = val;
|
var extra = 0; // keep track of spare cycles
|
||||||
shift2 = 0;
|
for (var sl = 0; sl < 131; sl++) {
|
||||||
rotcount = 0;
|
// double scanlines in consumer mode
|
||||||
xplower = false;
|
for (var i = 0; i < 2; i++) {
|
||||||
break;
|
// simulate contention during visible part of scanline
|
||||||
case 0xd: // INFBK (interrupt feedback)
|
vidactive = sl < verbl;
|
||||||
infbk = val;
|
extra = this.runCPU(cpu, cpuCyclesPerVisible - extra);
|
||||||
break;
|
vidactive = false;
|
||||||
case 0xe: // INMOD (interrupt enable)
|
extra = this.runCPU(cpu, cpuCyclesPerHBlank - extra);
|
||||||
inmod = val;
|
this.scanline++;
|
||||||
break;
|
|
||||||
case 0xf: // INLIN (interrupt line)
|
|
||||||
inlin = arcade ? val : val >> 1;
|
|
||||||
break;
|
|
||||||
case 0x10:
|
|
||||||
case 0x11:
|
|
||||||
case 0x12:
|
|
||||||
case 0x13:
|
|
||||||
case 0x14:
|
|
||||||
case 0x15:
|
|
||||||
case 0x16:
|
|
||||||
case 0x17:
|
|
||||||
psg.setACRegister(addr, val);
|
|
||||||
break;
|
|
||||||
case 0x18:
|
|
||||||
var c = cpu.saveState();
|
|
||||||
psg.setACRegister((c.BC>>8)-1, membus.read(c.HL));
|
|
||||||
break;
|
|
||||||
case 0x19: // XPAND
|
|
||||||
xpand = val;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
console.log('IO write', hex(addr,4), hex(val,2));
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
// interrupt
|
||||||
};
|
if (sl == inlin && (inmod & 0x8)) {
|
||||||
cpu = this.newCPU(membus, iobus, {applyContention:true});
|
cpu.retryInterrupts = !(inmod & 0x4);
|
||||||
audio = new MasterAudio();
|
cpu.interrupt(infbk);
|
||||||
psg = new AstrocadeAudio(audio);
|
}
|
||||||
video = new RasterVideo(mainElement,swidth,sheight,{});
|
// refresh this line in frame buffer?
|
||||||
video.create();
|
if (sl < sheight && refreshlines > 0) {
|
||||||
video.setupMouseEvents();
|
dirtylines[sl] = 0;
|
||||||
var idata = video.getFrameData();
|
refreshline(sl);
|
||||||
this.poller = setKeyboardFromMap(video, inputs, ASTROCADE_KEYCODE_MAP);
|
refreshlines--;
|
||||||
pixels = video.getFrameData();
|
}
|
||||||
timer = new AnimationTimer(60, this.nextFrame.bind(this));
|
else if (dirtylines[sl]) {
|
||||||
// default palette
|
dirtylines[sl] = 0;
|
||||||
for (var i=0; i<8; i++) {
|
refreshline(sl);
|
||||||
palinds[i] = i;
|
}
|
||||||
palette[i] = ASTROCADE_PALETTE[i];
|
}
|
||||||
|
if (!novideo) {
|
||||||
|
video.updateFrame(0, 0, 0, 0, swidth, verbl);
|
||||||
|
video.clearRect(0, verbl, swidth, sheight - verbl);
|
||||||
|
this.loadControls();
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
if (watchdog_counter-- <= 0) {
|
||||||
|
console.log("WATCHDOG FIRED"); // TODO: alert on video
|
||||||
|
this.reset();
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
readAddress(addr) {
|
getRasterScanline() { return this.scanline; }
|
||||||
return membus.read(addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
loadControls() {
|
loadROM(title, data) {
|
||||||
inputs[0x1c] = video.paddle_x & 0xff;
|
rom = padBytes(data, arcade ? 0xb000 : 0x2000);
|
||||||
inputs[0x1d] = video.paddle_y & 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
pollControls() { this.poller.poll(); }
|
|
||||||
|
|
||||||
advance(novideo : boolean) {
|
|
||||||
this.scanline = 0;
|
|
||||||
var extra = 0; // keep track of spare cycles
|
|
||||||
for (var sl=0; sl<131; sl++) {
|
|
||||||
// double scanlines in consumer mode
|
|
||||||
for (var i=0; i<2; i++) {
|
|
||||||
// simulate contention during visible part of scanline
|
|
||||||
vidactive = sl < verbl;
|
|
||||||
extra = this.runCPU(cpu, cpuCyclesPerVisible - extra);
|
|
||||||
vidactive = false;
|
|
||||||
extra = this.runCPU(cpu, cpuCyclesPerHBlank - extra);
|
|
||||||
this.scanline++;
|
|
||||||
}
|
|
||||||
// interrupt
|
|
||||||
if (sl == inlin && (inmod & 0x8)) {
|
|
||||||
cpu.retryInterrupts = !(inmod & 0x4);
|
|
||||||
cpu.interrupt(infbk);
|
|
||||||
}
|
|
||||||
// refresh this line in frame buffer?
|
|
||||||
if (sl < sheight && refreshlines>0) {
|
|
||||||
dirtylines[sl] = 0;
|
|
||||||
refreshline(sl);
|
|
||||||
refreshlines--;
|
|
||||||
}
|
|
||||||
else if (dirtylines[sl]) {
|
|
||||||
dirtylines[sl] = 0;
|
|
||||||
refreshline(sl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!novideo) {
|
|
||||||
video.updateFrame(0, 0, 0, 0, swidth, verbl);
|
|
||||||
video.clearRect(0, verbl, swidth, sheight-verbl);
|
|
||||||
this.loadControls();
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
if (watchdog_counter-- <= 0) {
|
|
||||||
console.log("WATCHDOG FIRED"); // TODO: alert on video
|
|
||||||
this.reset();
|
this.reset();
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
getRasterScanline() { return this.scanline; }
|
|
||||||
|
|
||||||
loadROM(title, data) {
|
loadBIOS(title, data) {
|
||||||
rom = padBytes(data, arcade ? 0xb000 : 0x2000);
|
bios = padBytes(data, 0x2000);
|
||||||
this.reset();
|
this.reset();
|
||||||
}
|
|
||||||
|
|
||||||
loadBIOS(title, data) {
|
|
||||||
bios = padBytes(data, 0x2000);
|
|
||||||
this.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
loadState(state) {
|
|
||||||
cpu.loadState(state.c);
|
|
||||||
ram.mem.set(state.b);
|
|
||||||
palette.set(state.palette);
|
|
||||||
palinds.set(state.palinds);
|
|
||||||
magicop = state.magicop;
|
|
||||||
xpand = state.xpand;
|
|
||||||
xplower = state.xplower;
|
|
||||||
shift2 = state.shift2;
|
|
||||||
horcb = state.horcb;
|
|
||||||
inmod = state.inmod;
|
|
||||||
inlin = state.inlin;
|
|
||||||
infbk = state.infbk;
|
|
||||||
verbl = state.verbl;
|
|
||||||
rotcount = state.rotcount;
|
|
||||||
rotdata.set(state.rotdata);
|
|
||||||
intst = state.intst;
|
|
||||||
this.scanline = state.sl;
|
|
||||||
this.loadControlsState(state);
|
|
||||||
refreshall();
|
|
||||||
}
|
|
||||||
saveState() {
|
|
||||||
return {
|
|
||||||
c: this.getCPUState(),
|
|
||||||
b: ram.mem.slice(0),
|
|
||||||
in: inputs.slice(0),
|
|
||||||
palette: palette.slice(0),
|
|
||||||
palinds: palinds.slice(0),
|
|
||||||
magicop: magicop,
|
|
||||||
xpand: xpand,
|
|
||||||
xplower: xplower,
|
|
||||||
shift2: shift2,
|
|
||||||
horcb: horcb,
|
|
||||||
inmod: inmod,
|
|
||||||
inlin: inlin,
|
|
||||||
infbk: infbk,
|
|
||||||
verbl: verbl,
|
|
||||||
rotcount: rotcount,
|
|
||||||
rotdata: rotdata.slice(0),
|
|
||||||
intst: intst,
|
|
||||||
sl: this.scanline,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
loadControlsState(state) {
|
|
||||||
inputs.set(state.in);
|
|
||||||
}
|
|
||||||
saveControlsState() {
|
|
||||||
return {
|
|
||||||
in:inputs.slice(0)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
getCPUState() {
|
|
||||||
return cpu.saveState();
|
|
||||||
}
|
|
||||||
|
|
||||||
isRunning() {
|
|
||||||
return timer && timer.isRunning();
|
|
||||||
}
|
|
||||||
pause() {
|
|
||||||
timer.stop();
|
|
||||||
audio.stop();
|
|
||||||
}
|
|
||||||
resume() {
|
|
||||||
timer.start();
|
|
||||||
audio.start();
|
|
||||||
}
|
|
||||||
reset() {
|
|
||||||
cpu.reset();
|
|
||||||
psg.reset();
|
|
||||||
// TODO?
|
|
||||||
magicop = xpand = inmod = inlin = infbk = shift2 = horcb = 0;
|
|
||||||
verbl = sheight;
|
|
||||||
xplower = false;
|
|
||||||
//watchdog_counter = INITIAL_WATCHDOG;
|
|
||||||
}
|
|
||||||
getDebugCategories() {
|
|
||||||
return super.getDebugCategories().concat(['Astro']);
|
|
||||||
}
|
|
||||||
getDebugInfo(category, state) {
|
|
||||||
switch (category) {
|
|
||||||
case 'Astro': return this.toLongString(state);
|
|
||||||
default: return super.getDebugInfo(category, state);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
toLongString(st) {
|
|
||||||
var s = "";
|
|
||||||
s += " Scan Y: " + st.sl;
|
|
||||||
s += "\n INLIN: " + st.inlin;
|
|
||||||
s += "\n VERBL: " + st.verbl;
|
|
||||||
s += "\nMAGICOP: $" + hex(st.magicop);
|
|
||||||
s += "\n XPAND: $" + hex(st.xpand);
|
|
||||||
s += "\nXPLOWER: " + st.xplower;
|
|
||||||
s += "\n SHIFT2: $" + hex(st.shift2);
|
|
||||||
s += "\n HORCB: $" + hex(st.horcb);
|
|
||||||
s += "\n INMOD: $" + hex(st.inmod);
|
|
||||||
s += "\n INFBK: $" + hex(st.infbk);
|
|
||||||
s += "\n INTST: $" + hex(st.intst); // intercept status
|
|
||||||
s += "\nPalette: ";
|
|
||||||
for (var i=0; i<8; i++)
|
|
||||||
s += hex(palinds[i]);
|
|
||||||
s += "\n";
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
loadState(state) {
|
||||||
|
cpu.loadState(state.c);
|
||||||
|
ram.mem.set(state.b);
|
||||||
|
palette.set(state.palette);
|
||||||
|
palinds.set(state.palinds);
|
||||||
|
magicop = state.magicop;
|
||||||
|
xpand = state.xpand;
|
||||||
|
xplower = state.xplower;
|
||||||
|
shift2 = state.shift2;
|
||||||
|
horcb = state.horcb;
|
||||||
|
inmod = state.inmod;
|
||||||
|
inlin = state.inlin;
|
||||||
|
infbk = state.infbk;
|
||||||
|
verbl = state.verbl;
|
||||||
|
rotcount = state.rotcount;
|
||||||
|
rotdata.set(state.rotdata);
|
||||||
|
intst = state.intst;
|
||||||
|
this.scanline = state.sl;
|
||||||
|
this.loadControlsState(state);
|
||||||
|
refreshall();
|
||||||
|
}
|
||||||
|
saveState() {
|
||||||
|
return {
|
||||||
|
c: this.getCPUState(),
|
||||||
|
b: ram.mem.slice(0),
|
||||||
|
in: inputs.slice(0),
|
||||||
|
palette: palette.slice(0),
|
||||||
|
palinds: palinds.slice(0),
|
||||||
|
magicop: magicop,
|
||||||
|
xpand: xpand,
|
||||||
|
xplower: xplower,
|
||||||
|
shift2: shift2,
|
||||||
|
horcb: horcb,
|
||||||
|
inmod: inmod,
|
||||||
|
inlin: inlin,
|
||||||
|
infbk: infbk,
|
||||||
|
verbl: verbl,
|
||||||
|
rotcount: rotcount,
|
||||||
|
rotdata: rotdata.slice(0),
|
||||||
|
intst: intst,
|
||||||
|
sl: this.scanline,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
loadControlsState(state) {
|
||||||
|
inputs.set(state.in);
|
||||||
|
}
|
||||||
|
saveControlsState() {
|
||||||
|
return {
|
||||||
|
in: inputs.slice(0)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
getCPUState() {
|
||||||
|
return cpu.saveState();
|
||||||
|
}
|
||||||
|
|
||||||
|
isRunning() {
|
||||||
|
return timer && timer.isRunning();
|
||||||
|
}
|
||||||
|
pause() {
|
||||||
|
timer.stop();
|
||||||
|
audio.stop();
|
||||||
|
}
|
||||||
|
resume() {
|
||||||
|
timer.start();
|
||||||
|
audio.start();
|
||||||
|
}
|
||||||
|
reset() {
|
||||||
|
cpu.reset();
|
||||||
|
psg.reset();
|
||||||
|
// TODO?
|
||||||
|
magicop = xpand = inmod = inlin = infbk = shift2 = horcb = 0;
|
||||||
|
verbl = sheight;
|
||||||
|
xplower = false;
|
||||||
|
//watchdog_counter = INITIAL_WATCHDOG;
|
||||||
|
}
|
||||||
|
getDebugCategories() {
|
||||||
|
return super.getDebugCategories().concat(['Astro']);
|
||||||
|
}
|
||||||
|
getDebugInfo(category, state) {
|
||||||
|
switch (category) {
|
||||||
|
case 'Astro': return this.toLongString(state);
|
||||||
|
default: return super.getDebugInfo(category, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
toLongString(st) {
|
||||||
|
var s = "";
|
||||||
|
s += " Scan Y: " + st.sl;
|
||||||
|
s += "\n INLIN: " + st.inlin;
|
||||||
|
s += "\n VERBL: " + st.verbl;
|
||||||
|
s += "\nMAGICOP: $" + hex(st.magicop);
|
||||||
|
s += "\n XPAND: $" + hex(st.xpand);
|
||||||
|
s += "\nXPLOWER: " + st.xplower;
|
||||||
|
s += "\n SHIFT2: $" + hex(st.shift2);
|
||||||
|
s += "\n HORCB: $" + hex(st.horcb);
|
||||||
|
s += "\n INMOD: $" + hex(st.inmod);
|
||||||
|
s += "\n INFBK: $" + hex(st.infbk);
|
||||||
|
s += "\n INTST: $" + hex(st.intst); // intercept status
|
||||||
|
s += "\nPalette: ";
|
||||||
|
for (var i = 0; i < 8; i++)
|
||||||
|
s += hex(palinds[i]);
|
||||||
|
s += "\n";
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
return new BallyAstrocadePlatform();
|
return new BallyAstrocadePlatform();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -542,7 +542,7 @@ const _BallyAstrocadePlatform = function(mainElement, arcade) {
|
|||||||
|
|
||||||
// TODO: https://github.com/mamedev/mame/blob/master/src/devices/sound/astrocde.cpp
|
// TODO: https://github.com/mamedev/mame/blob/master/src/devices/sound/astrocde.cpp
|
||||||
class AstrocadeAudio extends AY38910_Audio {
|
class AstrocadeAudio extends AY38910_Audio {
|
||||||
setACRegister(addr : number, val : number) {
|
setACRegister(addr: number, val: number) {
|
||||||
addr &= 0x7;
|
addr &= 0x7;
|
||||||
val &= 0xff;
|
val &= 0xff;
|
||||||
switch (addr) {
|
switch (addr) {
|
||||||
@ -553,17 +553,17 @@ class AstrocadeAudio extends AY38910_Audio {
|
|||||||
case 1:
|
case 1:
|
||||||
case 2:
|
case 2:
|
||||||
case 3:
|
case 3:
|
||||||
var i = (addr-1)*2;
|
var i = (addr - 1) * 2;
|
||||||
var j = val*2+1;
|
var j = val * 2 + 1;
|
||||||
this.psg.writeRegisterAY(i, j&0xff); // freq lo
|
this.psg.writeRegisterAY(i, j & 0xff); // freq lo
|
||||||
this.psg.writeRegisterAY(i+1, (j>>8)&0xff); // freq hi
|
this.psg.writeRegisterAY(i + 1, (j >> 8) & 0xff); // freq hi
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
this.psg.writeRegisterAY(10, val & 0xf); // tone c vol
|
this.psg.writeRegisterAY(10, val & 0xf); // tone c vol
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
this.psg.writeRegisterAY(8, val & 0xf); // tone a vol
|
this.psg.writeRegisterAY(8, val & 0xf); // tone a vol
|
||||||
this.psg.writeRegisterAY(9, (val>>4) & 0xf); // tone b vol
|
this.psg.writeRegisterAY(9, (val >> 4) & 0xf); // tone b vol
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -596,9 +596,9 @@ PLATFORMS['astrocade-bios'] = _BallyAstrocadeBIOSPlatform;
|
|||||||
PLATFORMS['astrocade-arcade'] = _BallyArcadePlatform;
|
PLATFORMS['astrocade-arcade'] = _BallyArcadePlatform;
|
||||||
|
|
||||||
//http://glankonian.com/~lance/astrocade_palette.html
|
//http://glankonian.com/~lance/astrocade_palette.html
|
||||||
var ASTROCADE_PALETTE = [0x000000,0x242424,0x484848,0x6D6D6D,0x919191,0xB6B6B6,0xDADADA,0xFFFFFF,0x2500BB,0x4900E0,0x6E11FF,0x9235FF,0xB75AFF,0xDB7EFF,0xFFA3FF,0xFFC7FF,0x4900B0,0x6D00D5,0x9201F9,0xB625FF,0xDA4AFF,0xFF6EFF,0xFF92FF,0xFFB7FF,0x6A009F,0x8E00C3,0xB300E7,0xD718FF,0xFB3CFF,0xFF61FF,0xFF85FF,0xFFA9FF,0x870087,0xAB00AB,0xD000D0,0xF40EF4,0xFF32FF,0xFF56FF,0xFF7BFF,0xFF9FFF,0x9F006A,0xC3008E,0xE700B3,0xFF07D7,0xFF2CFB,0xFF50FF,0xFF74FF,0xFF99FF,0xB00049,0xD5006D,0xF90092,0xFF05B6,0xFF29DA,0xFF4DFF,0xFF72FF,0xFF96FF,0xBB0025,0xE00049,0xFF006E,0xFF0692,0xFF2AB7,0xFF4FDB,0xFF73FF,0xFF98FF,0xBF0000,0xE30024,0xFF0048,0xFF0B6D,0xFF3091,0xFF54B6,0xFF79DA,0xFF9DFF,0xBB0000,0xE00000,0xFF0023,0xFF1447,0xFF396C,0xFF5D90,0xFF82B5,0xFFA6D9,0xB00000,0xD50000,0xF90000,0xFF2124,0xFF4548,0xFF6A6C,0xFF8E91,0xFFB3B5,0x9F0000,0xC30000,0xE70C00,0xFF3003,0xFF5527,0xFF794B,0xFF9E70,0xFFC294,0x870000,0xAB0000,0xD01E00,0xF44200,0xFF670A,0xFF8B2E,0xFFAF53,0xFFD477,0x6A0000,0x8E0D00,0xB33100,0xD75600,0xFB7A00,0xFF9E17,0xFFC33B,0xFFE75F,0x490000,0x6D2100,0x924500,0xB66A00,0xDA8E00,0xFFB305,0xFFD729,0xFFFC4E,0x251100,0x493500,0x6E5A00,0x927E00,0xB7A300,0xDBC700,0xFFEB1E,0xFFFF43,0x002500,0x244900,0x486D00,0x6D9200,0x91B600,0xB6DB00,0xDAFF1B,0xFFFF3F,0x003700,0x005B00,0x238000,0x47A400,0x6CC900,0x90ED00,0xB5FF1E,0xD9FF43,0x004700,0x006C00,0x009000,0x24B400,0x48D900,0x6CFD05,0x91FF29,0xB5FF4E,0x005500,0x007900,0x009D00,0x03C200,0x27E600,0x4BFF17,0x70FF3B,0x94FF5F,0x005F00,0x008300,0x00A800,0x00CC00,0x0AF00A,0x2EFF2E,0x53FF53,0x77FF77,0x006500,0x008A00,0x00AE00,0x00D203,0x00F727,0x17FF4B,0x3BFF70,0x5FFF94,0x006800,0x008C00,0x00B100,0x00D524,0x00F948,0x05FF6C,0x29FF91,0x4EFFB5,0x006600,0x008B00,0x00AF23,0x00D447,0x00F86C,0x00FF90,0x1EFFB5,0x43FFD9,0x006100,0x008524,0x00AA48,0x00CE6D,0x00F391,0x00FFB6,0x1BFFDA,0x3FFFFE,0x005825,0x007C49,0x00A16E,0x00C592,0x00EAB7,0x00FFDB,0x1EFFFF,0x43FFFF,0x004B49,0x00706D,0x009492,0x00B9B6,0x00DDDA,0x05FFFF,0x29FFFF,0x4EFFFF,0x003C6A,0x00608E,0x0085B3,0x00A9D7,0x00CEFB,0x17F2FF,0x3BFFFF,0x5FFFFF,0x002A87,0x004FAB,0x0073D0,0x0097F4,0x0ABCFF,0x2EE0FF,0x53FFFF,0x77FFFF,0x00179F,0x003BC3,0x0060E7,0x0384FF,0x27A8FF,0x4BCDFF,0x70F1FF,0x94FFFF,0x0002B0,0x0027D5,0x004BF9,0x2470FF,0x4894FF,0x6CB9FF,0x91DDFF,0xB5FFFF,0x0000BB,0x0013E0,0x2337FF,0x475BFF,0x6C80FF,0x90A4FF,0xB5C9FF,0xD9EDFF];
|
var ASTROCADE_PALETTE = [0x000000, 0x242424, 0x484848, 0x6D6D6D, 0x919191, 0xB6B6B6, 0xDADADA, 0xFFFFFF, 0x2500BB, 0x4900E0, 0x6E11FF, 0x9235FF, 0xB75AFF, 0xDB7EFF, 0xFFA3FF, 0xFFC7FF, 0x4900B0, 0x6D00D5, 0x9201F9, 0xB625FF, 0xDA4AFF, 0xFF6EFF, 0xFF92FF, 0xFFB7FF, 0x6A009F, 0x8E00C3, 0xB300E7, 0xD718FF, 0xFB3CFF, 0xFF61FF, 0xFF85FF, 0xFFA9FF, 0x870087, 0xAB00AB, 0xD000D0, 0xF40EF4, 0xFF32FF, 0xFF56FF, 0xFF7BFF, 0xFF9FFF, 0x9F006A, 0xC3008E, 0xE700B3, 0xFF07D7, 0xFF2CFB, 0xFF50FF, 0xFF74FF, 0xFF99FF, 0xB00049, 0xD5006D, 0xF90092, 0xFF05B6, 0xFF29DA, 0xFF4DFF, 0xFF72FF, 0xFF96FF, 0xBB0025, 0xE00049, 0xFF006E, 0xFF0692, 0xFF2AB7, 0xFF4FDB, 0xFF73FF, 0xFF98FF, 0xBF0000, 0xE30024, 0xFF0048, 0xFF0B6D, 0xFF3091, 0xFF54B6, 0xFF79DA, 0xFF9DFF, 0xBB0000, 0xE00000, 0xFF0023, 0xFF1447, 0xFF396C, 0xFF5D90, 0xFF82B5, 0xFFA6D9, 0xB00000, 0xD50000, 0xF90000, 0xFF2124, 0xFF4548, 0xFF6A6C, 0xFF8E91, 0xFFB3B5, 0x9F0000, 0xC30000, 0xE70C00, 0xFF3003, 0xFF5527, 0xFF794B, 0xFF9E70, 0xFFC294, 0x870000, 0xAB0000, 0xD01E00, 0xF44200, 0xFF670A, 0xFF8B2E, 0xFFAF53, 0xFFD477, 0x6A0000, 0x8E0D00, 0xB33100, 0xD75600, 0xFB7A00, 0xFF9E17, 0xFFC33B, 0xFFE75F, 0x490000, 0x6D2100, 0x924500, 0xB66A00, 0xDA8E00, 0xFFB305, 0xFFD729, 0xFFFC4E, 0x251100, 0x493500, 0x6E5A00, 0x927E00, 0xB7A300, 0xDBC700, 0xFFEB1E, 0xFFFF43, 0x002500, 0x244900, 0x486D00, 0x6D9200, 0x91B600, 0xB6DB00, 0xDAFF1B, 0xFFFF3F, 0x003700, 0x005B00, 0x238000, 0x47A400, 0x6CC900, 0x90ED00, 0xB5FF1E, 0xD9FF43, 0x004700, 0x006C00, 0x009000, 0x24B400, 0x48D900, 0x6CFD05, 0x91FF29, 0xB5FF4E, 0x005500, 0x007900, 0x009D00, 0x03C200, 0x27E600, 0x4BFF17, 0x70FF3B, 0x94FF5F, 0x005F00, 0x008300, 0x00A800, 0x00CC00, 0x0AF00A, 0x2EFF2E, 0x53FF53, 0x77FF77, 0x006500, 0x008A00, 0x00AE00, 0x00D203, 0x00F727, 0x17FF4B, 0x3BFF70, 0x5FFF94, 0x006800, 0x008C00, 0x00B100, 0x00D524, 0x00F948, 0x05FF6C, 0x29FF91, 0x4EFFB5, 0x006600, 0x008B00, 0x00AF23, 0x00D447, 0x00F86C, 0x00FF90, 0x1EFFB5, 0x43FFD9, 0x006100, 0x008524, 0x00AA48, 0x00CE6D, 0x00F391, 0x00FFB6, 0x1BFFDA, 0x3FFFFE, 0x005825, 0x007C49, 0x00A16E, 0x00C592, 0x00EAB7, 0x00FFDB, 0x1EFFFF, 0x43FFFF, 0x004B49, 0x00706D, 0x009492, 0x00B9B6, 0x00DDDA, 0x05FFFF, 0x29FFFF, 0x4EFFFF, 0x003C6A, 0x00608E, 0x0085B3, 0x00A9D7, 0x00CEFB, 0x17F2FF, 0x3BFFFF, 0x5FFFFF, 0x002A87, 0x004FAB, 0x0073D0, 0x0097F4, 0x0ABCFF, 0x2EE0FF, 0x53FFFF, 0x77FFFF, 0x00179F, 0x003BC3, 0x0060E7, 0x0384FF, 0x27A8FF, 0x4BCDFF, 0x70F1FF, 0x94FFFF, 0x0002B0, 0x0027D5, 0x004BF9, 0x2470FF, 0x4894FF, 0x6CB9FF, 0x91DDFF, 0xB5FFFF, 0x0000BB, 0x0013E0, 0x2337FF, 0x475BFF, 0x6C80FF, 0x90A4FF, 0xB5C9FF, 0xD9EDFF];
|
||||||
// swap palette RGB to BGR
|
// swap palette RGB to BGR
|
||||||
for (var i=0; i<256; i++) {
|
for (var i = 0; i < 256; i++) {
|
||||||
var x = ASTROCADE_PALETTE[i];
|
var x = ASTROCADE_PALETTE[i];
|
||||||
ASTROCADE_PALETTE[i] = rgb2bgr(x) | 0xff000000;
|
ASTROCADE_PALETTE[i] = rgb2bgr(x) | 0xff000000;
|
||||||
}
|
}
|
||||||
|
@ -231,8 +231,8 @@ const _GalaxianPlatform = function(mainElement, options) {
|
|||||||
read: newAddressDecoder([
|
read: newAddressDecoder([
|
||||||
[0x0000, 0x3fff, 0, function(a) { return rom ? rom[a] : null; }],
|
[0x0000, 0x3fff, 0, function(a) { return rom ? rom[a] : null; }],
|
||||||
[0x4000, 0x47ff, 0x7ff, function(a) { return ram.mem[a]; }],
|
[0x4000, 0x47ff, 0x7ff, function(a) { return ram.mem[a]; }],
|
||||||
// [0x4800, 0x4fff, 0x3ff, function(a) { return vram.mem[a]; }],
|
[0x4800, 0x4fff, 0x3ff, function(a) { return vram.mem[a]; }],
|
||||||
// [0x5000, 0x5fff, 0xff, function(a) { return oram.mem[a]; }],
|
[0x5000, 0x5fff, 0xff, function(a) { return oram.mem[a]; }],
|
||||||
[0x7000, 0x7000, 0, function(a) { watchdog_counter = INITIAL_WATCHDOG; }],
|
[0x7000, 0x7000, 0, function(a) { watchdog_counter = INITIAL_WATCHDOG; }],
|
||||||
[0x7800, 0x7800, 0, function(a) { watchdog_counter = INITIAL_WATCHDOG; }],
|
[0x7800, 0x7800, 0, function(a) { watchdog_counter = INITIAL_WATCHDOG; }],
|
||||||
//[0x8000, 0x820f, 0, function(a) { return noise(); }], // TODO: remove
|
//[0x8000, 0x820f, 0, function(a) { return noise(); }], // TODO: remove
|
||||||
|
20
src/views.ts
20
src/views.ts
@ -1041,12 +1041,12 @@ abstract class ProbeBitmapViewBase extends ProbeViewBase {
|
|||||||
}
|
}
|
||||||
getOpRGB(op:number) : number {
|
getOpRGB(op:number) : number {
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case ProbeFlags.EXECUTE: return 0x0f3f0f;
|
case ProbeFlags.EXECUTE: return 0x0f3f0f;
|
||||||
case ProbeFlags.MEM_READ: return 0x3f0101;
|
case ProbeFlags.MEM_READ: return 0x3f0101;
|
||||||
case ProbeFlags.MEM_WRITE: return 0x000f3f;
|
case ProbeFlags.MEM_WRITE: return 0x010f3f;
|
||||||
case ProbeFlags.IO_READ: return 0x001f01;
|
case ProbeFlags.IO_READ: return 0x001f01;
|
||||||
case ProbeFlags.IO_WRITE: return 0x003f3f;
|
case ProbeFlags.IO_WRITE: return 0x017f7f;
|
||||||
case ProbeFlags.INTERRUPT: return 0x3f3f00;
|
case ProbeFlags.INTERRUPT: return 0x3f3f00;
|
||||||
default: return 0;
|
default: return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1091,8 +1091,12 @@ export class RasterPCHeatMapView extends ProbeBitmapViewBase implements ProjectV
|
|||||||
drawEvent(op, addr, col, row) {
|
drawEvent(op, addr, col, row) {
|
||||||
// if (op != ProbeFlags.EXECUTE) return;
|
// if (op != ProbeFlags.EXECUTE) return;
|
||||||
var iofs = col + row * this.canvas.width;
|
var iofs = col + row * this.canvas.width;
|
||||||
var rgb = addr << 8;
|
//var rgb = addr << 8;
|
||||||
this.datau32[iofs] = rgb | 0xff000000;
|
var rgb = this.getOpRGB(op) << 1;
|
||||||
|
var data = this.datau32[iofs];
|
||||||
|
rgb |= addr & 0x3f3f;
|
||||||
|
data = data | rgb | 0xff000000;
|
||||||
|
this.datau32[iofs] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user