mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-12-21 21:29:17 +00:00
astrocade: worked on arcade emulation
This commit is contained in:
parent
0ede0e514b
commit
d08d73f422
@ -71,6 +71,7 @@ const _BallyAstrocade = function(arcade:boolean) {
|
|||||||
const swidth = arcade ? 320 : 160;
|
const swidth = arcade ? 320 : 160;
|
||||||
const sheight = arcade ? 204 : 102;
|
const sheight = arcade ? 204 : 102;
|
||||||
const swbytes = swidth >> 2;
|
const swbytes = swidth >> 2;
|
||||||
|
const samask = arcade ? 0x3fff : 0xfff;
|
||||||
const INITIAL_WATCHDOG = 256;
|
const INITIAL_WATCHDOG = 256;
|
||||||
const PIXEL_ON = 0xffeeeeee;
|
const PIXEL_ON = 0xffeeeeee;
|
||||||
const PIXEL_OFF = 0xff000000;
|
const PIXEL_OFF = 0xff000000;
|
||||||
@ -90,19 +91,19 @@ const _BallyAstrocade = function(arcade:boolean) {
|
|||||||
var palinds = new Uint8Array(8);
|
var palinds = new Uint8Array(8);
|
||||||
var refreshlines = 0;
|
var refreshlines = 0;
|
||||||
var dirtylines = new Uint8Array(arcade ? 262 : 131);
|
var dirtylines = new Uint8Array(arcade ? 262 : 131);
|
||||||
var vidactive = false;
|
|
||||||
var rotdata = new Uint8Array(4);
|
var rotdata = new Uint8Array(4);
|
||||||
var rotcount = 0;
|
var rotcount = 0;
|
||||||
var intst = 0;
|
var intst = 0;
|
||||||
var waitstates = 0;
|
var waitstates = 0;
|
||||||
|
var patboard = new Uint8Array(0x08);
|
||||||
|
var patdest = 0;
|
||||||
|
|
||||||
function ramwrite(a: number, v: number) {
|
function ramwrite(a: number, v: number) {
|
||||||
// set RAM
|
// set RAM
|
||||||
ram[a] = v;
|
ram[a] = v;
|
||||||
waitstates++;
|
waitstates++;
|
||||||
// mark scanline as dirty
|
// mark scanline as dirty
|
||||||
dirtylines[((a & 0xfff) / swbytes) | 0] = 1;
|
dirtylines[((a & samask) / swbytes) | 0] = 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);
|
||||||
@ -201,7 +202,105 @@ const _BallyAstrocade = function(arcade:boolean) {
|
|||||||
function refreshall() {
|
function refreshall() {
|
||||||
refreshlines = sheight;
|
refreshlines = sheight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bally astrocade pattern board
|
||||||
|
// https://github.com/mamedev/mame/blob/7ff10685c56a6e123336c684e5e96fdb9e8b3674/src/mame/midway/astrocde_v.cpp#L726
|
||||||
|
function xfer_patboard() {
|
||||||
|
let m_pattern_source = patboard[0] | (patboard[1] << 8);
|
||||||
|
let m_pattern_mode = patboard[2] & 0x3f;
|
||||||
|
let m_pattern_skip = patboard[3];
|
||||||
|
let m_pattern_dest = (patdest & 0xff) | (patboard[4] << 8);
|
||||||
|
let m_pattern_width = patboard[5];
|
||||||
|
let m_pattern_height = patboard[6] + 1;
|
||||||
|
|
||||||
|
let curwidth: number;
|
||||||
|
let u13ff: number = 0;
|
||||||
|
let cycles: number = 0;
|
||||||
|
|
||||||
|
u13ff = 0;
|
||||||
|
|
||||||
|
if ((m_pattern_mode & 0x02) === 0) {
|
||||||
|
u13ff = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function incrementSource(): void {
|
||||||
|
if (u13ff && (m_pattern_mode & 0x04) !== 0 && (curwidth !== 0 || (m_pattern_mode & 0x08) === 0)) {
|
||||||
|
m_pattern_source++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((m_pattern_mode & 0x02) !== 0) {
|
||||||
|
u13ff ^= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function incrementDest(): void {
|
||||||
|
if (curwidth !== 0) {
|
||||||
|
if ((m_pattern_mode & 0x20) !== 0) {
|
||||||
|
m_pattern_dest++;
|
||||||
|
} else {
|
||||||
|
m_pattern_dest--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop over height
|
||||||
|
while (m_pattern_height >= 0) {
|
||||||
|
let carry: number;
|
||||||
|
|
||||||
|
curwidth = m_pattern_width;
|
||||||
|
|
||||||
|
// Loop over width
|
||||||
|
while (curwidth >= 0) {
|
||||||
|
let busaddr: number;
|
||||||
|
let busdata: number;
|
||||||
|
|
||||||
|
// Read Phase
|
||||||
|
busaddr = (m_pattern_mode & 0x01) === 0 ? m_pattern_source : m_pattern_dest;
|
||||||
|
|
||||||
|
if (curwidth === 0 && (m_pattern_mode & 0x08) !== 0) {
|
||||||
|
busdata = 0;
|
||||||
|
} else {
|
||||||
|
busdata = membus.read(m_pattern_source);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((m_pattern_mode & 0x01) === 0) {
|
||||||
|
incrementSource();
|
||||||
|
} else {
|
||||||
|
incrementDest();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write Phase
|
||||||
|
busaddr = (m_pattern_mode & 0x01) !== 0 ? m_pattern_source : m_pattern_dest;
|
||||||
|
ramwrite(busaddr, busdata);
|
||||||
|
|
||||||
|
if ((m_pattern_mode & 0x01) === 0) {
|
||||||
|
incrementDest();
|
||||||
|
} else {
|
||||||
|
incrementSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
cycles += 4;
|
||||||
|
curwidth--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// At the end of each row, adjust m_pattern_dest
|
||||||
|
carry = ((m_pattern_dest & 0xff) + m_pattern_skip) & 0x100;
|
||||||
|
m_pattern_dest = (m_pattern_dest & 0xff00) | ((m_pattern_dest + m_pattern_skip) & 0xff);
|
||||||
|
|
||||||
|
if ((m_pattern_mode & 0x10) === 0) {
|
||||||
|
m_pattern_dest += carry;
|
||||||
|
} else {
|
||||||
|
m_pattern_dest -= carry ^ 0x100;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_pattern_height--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adjust m_maincpu.icount
|
||||||
|
// m_maincpu.adjust_icount(-cycles);
|
||||||
|
// Replace the above line with the actual adjustment of icount.
|
||||||
|
}
|
||||||
|
|
||||||
this.drawScanline = (sl:number) => {
|
this.drawScanline = (sl:number) => {
|
||||||
// interrupt
|
// interrupt
|
||||||
if (sl == inlin && (inmod & 0x8)) {
|
if (sl == inlin && (inmod & 0x8)) {
|
||||||
@ -226,9 +325,9 @@ const _BallyAstrocade = function(arcade:boolean) {
|
|||||||
ram = r;
|
ram = r;
|
||||||
inputs = inp;
|
inputs = inp;
|
||||||
psg = psgg;
|
psg = psgg;
|
||||||
//bios = padBytes(ASTROCADE_MINIMAL_BIOS, 0x2000);
|
|
||||||
bios = padBytes(new lzgmini().decode(stringToByteArray(atob(ASTROLIBRE_BIOS_LZG))), 0x2000);
|
|
||||||
if (!arcade) {
|
if (!arcade) {
|
||||||
|
//bios = padBytes(ASTROCADE_MINIMAL_BIOS, 0x2000);
|
||||||
|
bios = padBytes(new lzgmini().decode(stringToByteArray(atob(ASTROLIBRE_BIOS_LZG))), 0x2000);
|
||||||
// game console
|
// game console
|
||||||
membus = {
|
membus = {
|
||||||
read: newAddressDecoder([
|
read: newAddressDecoder([
|
||||||
@ -246,13 +345,14 @@ const _BallyAstrocade = function(arcade:boolean) {
|
|||||||
membus = {
|
membus = {
|
||||||
read: newAddressDecoder([
|
read: newAddressDecoder([
|
||||||
[0x4000, 0x7fff, 0x3fff, function(a) { return ram[a]; }], // screen RAM
|
[0x4000, 0x7fff, 0x3fff, function(a) { return ram[a]; }], // screen RAM
|
||||||
[0xd000, 0xdfff, 0xfff, function(a) { return ram[a + 0x4000]; }], // static RAM
|
[0xd000, 0xdfff, 0x0fff, function(a) { return ram[a + 0x4000]; }], // static RAM
|
||||||
[0x0000, 0xafff, 0xffff, function(a) { return rom ? rom[a] : 0; }], // ROM (0-3fff,8000-afff)
|
[0x0000, 0x3fff, 0x3fff, function(a) { return rom ? rom[a] : 0; }], // ROM
|
||||||
|
[0x8000, 0xbfff, 0x3fff, function(a) { return rom ? rom[a + 0x4000] : 0; }], // ROM
|
||||||
]),
|
]),
|
||||||
write: newAddressDecoder([
|
write: newAddressDecoder([
|
||||||
[0x4000, 0x7fff, 0x3fff, ramwrite],
|
[0x4000, 0x7fff, 0x3fff, ramwrite],
|
||||||
[0xd000, 0xdfff, 0xfff, function(a, v) { ramwrite(a + 0x4000, v); }], // static RAM
|
|
||||||
[0x0000, 0x3fff, 0x3fff, magicwrite],
|
[0x0000, 0x3fff, 0x3fff, magicwrite],
|
||||||
|
[0xd000, 0xdfff, 0x0fff, function(a, v) { ramwrite(a + 0x4000, v); }], // static RAM
|
||||||
]),
|
]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -273,6 +373,19 @@ const _BallyAstrocade = function(arcade:boolean) {
|
|||||||
return rtn;
|
return rtn;
|
||||||
},
|
},
|
||||||
write: function(addr, val) {
|
write: function(addr, val) {
|
||||||
|
if (addr == 0xa55b) {
|
||||||
|
// TODO: protected_ram_enable_w
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
addr &= 0xff;
|
||||||
|
// pattern board
|
||||||
|
if (addr > 0x78 && addr < 0x80) {
|
||||||
|
patboard[addr & 7] = val;
|
||||||
|
if (addr == 0x72) { patdest = 0; }
|
||||||
|
if (addr == 0x74) { patdest = (patdest + patboard[3]) & 0xff; }
|
||||||
|
if (addr == 0x7e) { xfer_patboard(); }
|
||||||
|
return;
|
||||||
|
}
|
||||||
addr &= 0x1f;
|
addr &= 0x1f;
|
||||||
val &= 0xff;
|
val &= 0xff;
|
||||||
switch (addr) {
|
switch (addr) {
|
||||||
@ -332,8 +445,15 @@ const _BallyAstrocade = function(arcade:boolean) {
|
|||||||
case 0x19: // XPAND
|
case 0x19: // XPAND
|
||||||
xpand = val;
|
xpand = val;
|
||||||
break;
|
break;
|
||||||
|
case 0x1a:
|
||||||
|
case 0x1b:
|
||||||
|
case 0x1c:
|
||||||
|
case 0x1d:
|
||||||
|
case 0x1e:
|
||||||
|
//psg2.setACRegister(addr - 0x1a, val);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
console.log('IO write', hex(addr, 4), hex(val, 2));
|
//console.log('IO write', hex(addr, 4), hex(val, 2));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -372,6 +492,8 @@ const _BallyAstrocade = function(arcade:boolean) {
|
|||||||
rotdata.set(state.rotdata);
|
rotdata.set(state.rotdata);
|
||||||
intst = state.intst;
|
intst = state.intst;
|
||||||
inputs.set(state.inputs);
|
inputs.set(state.inputs);
|
||||||
|
patboard.set(state.patboard);
|
||||||
|
patdest = state.patdest;
|
||||||
refreshall();
|
refreshall();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -393,7 +515,9 @@ const _BallyAstrocade = function(arcade:boolean) {
|
|||||||
verbl: verbl,
|
verbl: verbl,
|
||||||
rotcount: rotcount,
|
rotcount: rotcount,
|
||||||
rotdata: rotdata.slice(0),
|
rotdata: rotdata.slice(0),
|
||||||
intst: intst
|
intst: intst,
|
||||||
|
patboard: patboard.slice(0),
|
||||||
|
patdest: patdest,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
this.reset = () => {
|
this.reset = () => {
|
||||||
@ -450,6 +574,7 @@ export class BallyAstrocade extends BasicScanlineMachine implements AcceptsPaddl
|
|||||||
ram : Uint8Array;
|
ram : Uint8Array;
|
||||||
cpu : Z80;
|
cpu : Z80;
|
||||||
m; // _BallyAstrocade
|
m; // _BallyAstrocade
|
||||||
|
arcade : boolean;
|
||||||
|
|
||||||
psg: AstrocadeAudio;
|
psg: AstrocadeAudio;
|
||||||
audioadapter;
|
audioadapter;
|
||||||
@ -458,6 +583,7 @@ export class BallyAstrocade extends BasicScanlineMachine implements AcceptsPaddl
|
|||||||
|
|
||||||
constructor(arcade:boolean) {
|
constructor(arcade:boolean) {
|
||||||
super();
|
super();
|
||||||
|
this.arcade = arcade;
|
||||||
this.cpu = new Z80();
|
this.cpu = new Z80();
|
||||||
this.psg = new AstrocadeAudio(new MasterAudio());
|
this.psg = new AstrocadeAudio(new MasterAudio());
|
||||||
this.audioadapter = new TssChannelAdapter(this.psg.psg, audioOversample, this.sampleRate);
|
this.audioadapter = new TssChannelAdapter(this.psg.psg, audioOversample, this.sampleRate);
|
||||||
@ -471,6 +597,12 @@ export class BallyAstrocade extends BasicScanlineMachine implements AcceptsPaddl
|
|||||||
//this.cpuCyclesPerVisible = this.cpuCyclesPerLine - this.cpuCyclesPerHBlank;
|
//this.cpuCyclesPerVisible = this.cpuCyclesPerLine - this.cpuCyclesPerHBlank;
|
||||||
this.m = new _BallyAstrocade(arcade);
|
this.m = new _BallyAstrocade(arcade);
|
||||||
this.m.init(this, this.cpu, this.ram, this.inputs, this.psg);
|
this.m.init(this, this.cpu, this.ram, this.inputs, this.psg);
|
||||||
|
if (arcade) {
|
||||||
|
this.inputs[0x10] = 0xff; // switches (active low)
|
||||||
|
this.inputs[0x11] = 0xff; // switches (active low)
|
||||||
|
this.inputs[0x12] = 0x00;
|
||||||
|
this.inputs[0x13] = 0x08; // dip switches
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
read(a:number) : number {
|
read(a:number) : number {
|
||||||
@ -556,8 +688,16 @@ export class BallyAstrocade extends BasicScanlineMachine implements AcceptsPaddl
|
|||||||
case 'Astro': return this.m.toLongString(state);
|
case 'Astro': return this.m.toLongString(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
getRasterCanvasPosition() { return { x: this.getRasterX(), y: this.getRasterY() }; }
|
getRasterCanvasPosition() {
|
||||||
|
return { x: this.getRasterX(), y: this.getRasterY() };
|
||||||
|
}
|
||||||
|
getVideoParams() {
|
||||||
|
if (this.arcade) {
|
||||||
|
return { width: 320, height: 204, rotate: 180 };
|
||||||
|
} else {
|
||||||
|
return { width: 160, height: 102 };
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/////
|
/////
|
||||||
@ -591,16 +731,6 @@ class AstrocadeAudio extends AY38910_Audio {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const _BallyArcade = function() {
|
|
||||||
this.__proto__ = new (_BallyAstrocade as any)(true);
|
|
||||||
// TODO: inputs[0x13] = 0xfe; // dip switch on arcade
|
|
||||||
// TODO: arcade controls, bit blit
|
|
||||||
var _in = this.saveControlsState();
|
|
||||||
_in.in[0x10] = 0xff; // switches
|
|
||||||
_in.in[0x13] = 0xfe; // dip switches
|
|
||||||
this.loadControlsState(_in);
|
|
||||||
}
|
|
||||||
|
|
||||||
/////
|
/////
|
||||||
|
|
||||||
//http://glankonian.com/~lance/astrocade_palette.html
|
//http://glankonian.com/~lance/astrocade_palette.html
|
||||||
|
@ -26,6 +26,10 @@ const ASTROCADE_BIOS_PRESETS = [
|
|||||||
{ id: 'bios.c', name: 'BIOS' },
|
{ id: 'bios.c', name: 'BIOS' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const ASTROCADE_ARCADE_PRESETS = [
|
||||||
|
{ id: 'hello.c', name: 'Hello Graphics' },
|
||||||
|
];
|
||||||
|
|
||||||
class BallyAstrocadePlatform extends BaseZ80MachinePlatform<BallyAstrocade> implements Platform {
|
class BallyAstrocadePlatform extends BaseZ80MachinePlatform<BallyAstrocade> implements Platform {
|
||||||
|
|
||||||
newMachine() { return new BallyAstrocade(false); }
|
newMachine() { return new BallyAstrocade(false); }
|
||||||
@ -52,10 +56,13 @@ class BallyAstrocadeBIOSPlatform extends BallyAstrocadePlatform implements Platf
|
|||||||
class BallyArcadePlatform extends BallyAstrocadePlatform implements Platform {
|
class BallyArcadePlatform extends BallyAstrocadePlatform implements Platform {
|
||||||
|
|
||||||
newMachine() { return new BallyAstrocade(true); }
|
newMachine() { return new BallyAstrocade(true); }
|
||||||
|
getPresets() { return ASTROCADE_ARCADE_PRESETS; }
|
||||||
|
|
||||||
getMemoryMap = function() { return { main:[
|
getMemoryMap = function() { return { main:[
|
||||||
|
{name:'ROM',start:0x0,size:0x4000,type:'rom'},
|
||||||
{name:'Magic RAM',start:0x0,size:0x4000,type:'ram'},
|
{name:'Magic RAM',start:0x0,size:0x4000,type:'ram'},
|
||||||
{name:'Screen RAM',start:0x4000,size:0x4000,type:'ram'},
|
{name:'Screen RAM',start:0x4000,size:0x4000,type:'ram'},
|
||||||
|
{name:'ROM',start:0x8000,size:0x4000,type:'rom'},
|
||||||
] } };
|
] } };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user