1964js/dart/web/system.dart

177 lines
4.6 KiB
Dart

/**
* 1964 (WebApp version)
* An N64 emulator Copyright (C) Joel Middendorf
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
library system;
import 'dart:html';
import 'dma.dart';
import 'interrupts.dart';
import 'memory.dart';
import 'pif.dart';
import 'settings.dart';
import 'tlb.dart';
import 'webgl.dart';
import 'vm.dart';
import 'jsvm.dart';
import 'romfile.dart';
class System {
Int32Array r, h, vAddr, cp0, cp1Con, cp1_i;
ArrayBuffer _cp1Buffer;
Float32Array cp1_f;
Float64Array cp1_f64;
int LLbit;
List<TLB> tlb;
Object _code;
Memory memory;
Interrupts interrupts;
Pif pif;
DMA dma;
WebGL webGL;
// app config
int _isLittleEndian;
int _isBigEndian;
Settings _appSettings;
VM vm;
/**
* Construct the N64 system.
* System components are allocated here.
*/
System() :
r = new Int32Array(35),
h = new Int32Array(35),
vAddr = new Int32Array(32),
cp0 = new Int32Array(32),
_cp1Buffer = new ArrayBuffer(32*4),
cp1Con = new Int32Array(32),
tlb = new List(32),
_appSettings = new Settings(),
vm = new JavaScriptVM()
{
cp1_i = new Int32Array.fromBuffer(_cp1Buffer);
cp1_f = new Float32Array.fromBuffer(_cp1Buffer);
cp1_f64 = new Float64Array.fromBuffer(_cp1Buffer);
memory = new Memory(this);
interrupts = new Interrupts(this, cp0);
pif = new Pif(memory.pifUint8Array);
dma = new DMA(memory, interrupts, pif);
webGL = new WebGL(_appSettings.wireframe);
}
/**
* Initialize registers and memory to their initial state
* simulating the completion of PIF ROM execution. This does
* not zero-initialize memory. Also, reset app components.
*/
void softReset() {
// Initialize the low values of MIPS registers.
r.setElements([0, 0, 0xd1731be9, 0xd1731be9, 0x001be9,
0xf45231e5, 0xa4001f0c, 0xa4001f08, 0x070, 0, 0x040, 0xA4000040,
0xd1330bc3, 0xd1330bc3, 0x025613a26, 0x02ea04317, 0, 0, 0, 0, 0, 0, 0,
0x06, 0, 0xd73f2993, 0, 0, 0, 0xa4001ff0, 0, 0xa4001554, 0, 0, 0]);
// Sign-extend the low values in r to store the high values in h.
int i = 0;
while (i < 35) {
h[i] = r[i] >> 31;
i += 1;
}
LLbit = 0;
_initTLB();
// Reset app settings
vm.reset(_appSettings.writeToDom);
}
/**
* Initialize the Translation Lookaside Buffer (TLB).
* TLB maps virtual memory addresses to physical memory addresses.
*/
void _initTLB() {
int i=0;
for (; i < 32; i++) {
tlb[i] = new TLB();
}
}
/**
* Start
*/
void start() {
softReset();
_readFile();
}
/**
* Load and play the rom.
*/
void _readFile() {
print('read file');
String url = "roms/unofficial/rotate.v64";
HttpRequest request = new HttpRequest();
/**
* If the next two lines are reversed, Firefox fails (as of version 16.0.2).
*/
request.open("GET", url, true);
request.responseType = "arraybuffer";
request.on
..load.add( (event) {
if (request.status !== 200) {
String statusText = request.statusText;
String errorCode = request.status.toString();
window.alert('HTTP Error $errorCode: ($statusText)\n\n$url');
return;
}
_endianTest();
memory.rom = RomFile.byteSwap(new Uint8Array.fromBuffer(request.response));
})
..error.add( (event) {
print('$event');
});
request.send();
}
/**
* Find out if the user's device is little-endian or big-endian
*/
void _endianTest() {
ArrayBuffer ii = new ArrayBuffer(2);
Uint8Array iiSetView = new Uint8Array.fromBuffer(ii);
Uint16Array iiView = new Uint16Array.fromBuffer(ii);
iiSetView[0] = 0xff;
iiSetView[1] = 0x11;
if (iiView[0] === 0x11FF) {
print("You are on a little-endian system");
_isLittleEndian = 1;
_isBigEndian = 0;
} else {
print("You are on a big-endian system");
_isLittleEndian = 0;
_isBigEndian = 1;
}
}
}