mirror of
https://github.com/schibo/1964js.git
synced 2025-04-02 10:52:54 -04:00
177 lines
4.6 KiB
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;
|
|
}
|
|
}
|
|
}
|