###1964js - JavaScript/HTML5 port of 1964 - N64 emulator Copyright (C) 2012 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.### #segments must be at least 64KB in size for lookup table. `const MEMORY_START_RDRAM = 0x00000000` `const MEMORY_START_RAMREGS4 = 0x03F04000` `const MEMORY_SIZE_RAMREGS4 = 0x10000` `const MEMORY_START_RAMREGS0 = 0x03F00000` `const MEMORY_START_RAMREGS8 = 0x03F80000` `const MEMORY_SIZE_RAMREGS0 = 0x10000` `const MEMORY_SIZE_RAMREGS8 = 0x10000` `const MEMORY_START_SPMEM = 0x04000000` `const MEMORY_START_SPREG_1 = 0x04040000` `const MEMORY_START_SPREG_2 = 0x04080000` `const MEMORY_START_DPC = 0x04100000` `const MEMORY_START_DPS = 0x04200000` `const MEMORY_START_MI = 0x04300000` `const MEMORY_START_VI = 0x04400000` `const MEMORY_START_AI = 0x04500000` `const MEMORY_START_PI = 0x04600000` `const MEMORY_START_RI = 0x04700000` `const MEMORY_START_SI = 0x04800000` `const MEMORY_START_C2A1 = 0x05000000` `const MEMORY_START_C1A1 = 0x06000000` `const MEMORY_START_C2A2 = 0x08000000` `const MEMORY_START_ROM_IMAGE = 0x10000000` `const MEMORY_START_GIO = 0x18000000` `const MEMORY_START_C1A3 = 0x1FD00000` `const MEMORY_START_DUMMY = 0x1FFF0000` `const MEMORY_SIZE_SPMEM = 0x10000` `const MEMORY_SIZE_SPREG_1 = 0x10000` `const MEMORY_SIZE_SPREG_2 = 0x10000` `const MEMORY_SIZE_DPC = 0x10000` `const MEMORY_SIZE_DPS = 0x10000` `const MEMORY_SIZE_MI = 0x10000` `const MEMORY_SIZE_VI = 0x10000` `const MEMORY_SIZE_AI = 0x10000` `const MEMORY_SIZE_PI = 0x10000` `const MEMORY_SIZE_RI = 0x10000` `const MEMORY_SIZE_SI = 0x10000` `const MEMORY_SIZE_C2A1 = 0x10000` `const MEMORY_SIZE_C1A1 = 0x10000` `const MEMORY_SIZE_C2A2 = 0x20000` `const MEMORY_SIZE_GIO = 0x10000` `const MEMORY_SIZE_C1A3 = 0x10000` `const MEMORY_SIZE_DUMMY = 0x10000` `const MEMORY_START_PIF = 0x1FC00000` `const MEMORY_START_PIF_RAM = 0x1FC007C0` `const MEMORY_SIZE_PIF = 0x10000` `const MEMORY_SIZE_ROM = 0x4000000` class C1964jsMemory constructor: (@core) -> ###* * @const ### @romUint8Array = `undefined` # set after rom is loaded. ###* * @const ### @rom = `undefined` # set after rom is loaded. ###* * @const ### @ramArrayBuffer = new ArrayBuffer(0x800000) ###* * @const ### @u8 = new Uint8Array(@ramArrayBuffer) # RDRAM ###* * @const ### @spMemUint8ArrayBuffer = new ArrayBuffer(0x10000) ###* * @const ### @spMemUint8Array = new Uint8Array(@spMemUint8ArrayBuffer) ###* * @const ### @spReg1Uint8ArrayBuffer = new ArrayBuffer(0x10000) ###* * @const ### @spReg1Uint8Array = new Uint8Array(@spReg1Uint8ArrayBuffer) ###* * @const ### @spReg2Uint8ArrayBuffer = new ArrayBuffer(0x10000) ###* * @const ### @spReg2Uint8Array = new Uint8Array(@spReg2Uint8ArrayBuffer) ###* * @const ### @dpcUint8ArrayBuffer = new ArrayBuffer(0x10000) ###* * @const ### @dpcUint8Array = new Uint8Array(@dpcUint8ArrayBuffer) ###* * @const ### @dpsUint8ArrayBuffer = new ArrayBuffer(0x10000) ###* * @const ### @dpsUint8Array = new Uint8Array(@dpsUint8ArrayBuffer) ###* * @const ### @miUint8ArrayBuffer = new ArrayBuffer(0x10000) ###* * @const ### @miUint8Array = new Uint8Array(@miUint8ArrayBuffer) ###* * @const ### @viUint8ArrayBuffer = new ArrayBuffer(0x10000) ###* * @const ### @viUint8Array = new Uint8Array(@viUint8ArrayBuffer) ###* * @const ### @aiUint8ArrayBuffer = new ArrayBuffer(0x10000) ###* * @const ### @aiUint8Array = new Uint8Array(@aiUint8ArrayBuffer) ###* * @const ### @piUint8ArrayBuffer = new ArrayBuffer(0x10000) ###* * @const ### @piUint8Array = new Uint8Array(@piUint8ArrayBuffer) ###* * @const ### @siUint8ArrayBuffer = new ArrayBuffer(0x10000) ###* * @const ### @siUint8Array = new Uint8Array(@siUint8ArrayBuffer) ###* * @const ### @c2a1Uint8ArrayBuffer = new ArrayBuffer(0x10000) ###* * @const ### @c2a1Uint8Array = new Uint8Array(@c2a1Uint8ArrayBuffer) ###* * @const ### @c1a1Uint8ArrayBuffer = new ArrayBuffer(0x10000) ###* * @const ### @c1a1Uint8Array = new Uint8Array(@c1a1Uint8ArrayBuffer) ###* * @const ### @c2a2Uint8ArrayBuffer = new ArrayBuffer(0x10000) ###* * @const ### @c2a2Uint8Array = new Uint8Array(@c2a2Uint8ArrayBuffer) ###* * @const ### @c1a3Uint8ArrayBuffer = new ArrayBuffer(0x10000) ###* * @const ### @c1a3Uint8Array = new Uint8Array(@c1a3Uint8ArrayBuffer) ###* * @const ### @riUint8ArrayBuffer = new ArrayBuffer(0x10000) ###* * @const ### @riUint8Array = new Uint8Array(@riUint8ArrayBuffer) ###* * @const ### @pifUint8ArrayBuffer = new ArrayBuffer(0x10000) ###* * @const ### @pifUint8Array = new Uint8Array(@pifUint8ArrayBuffer) ###* * @const ### @gioUint8ArrayBuffer = new ArrayBuffer(0x10000) ###* * @const ### @gioUint8Array = new Uint8Array(@gioUint8ArrayBuffer) ###* * @const ### @ramRegs0Uint8ArrayBuffer = new ArrayBuffer(0x10000) ###* * @const ### @ramRegs0Uint8Array = new Uint8Array(@ramRegs0Uint8ArrayBuffer) ###* * @const ### @ramRegs4Uint8ArrayBuffer = new ArrayBuffer(0x10000) ###* * @const ### @ramRegs4Uint8Array = new Uint8Array(@ramRegs4Uint8ArrayBuffer) ###* * @const ### @ramRegs8Uint8ArrayBuffer = new ArrayBuffer(0x10000) ###* * @const ### @ramRegs8Uint8Array = new Uint8Array(@ramRegs8Uint8ArrayBuffer) ###* * @const ### @dummyReadWriteUint8ArrayBuffer = new ArrayBuffer(0x10000) ###* * @const ### @dummyReadWriteUint8Array = new Uint8Array(@dummyReadWriteUint8ArrayBuffer) @lengthy = 50325 ###* * Load Byte * @type {!Array} * @const ### @LB = Array.apply(@readDummy8, Array(@lengthy)) ###* * Load Half * @type {!Array} * @const ### @LH = Array.apply(@readDummy16, Array(@lengthy)) ###* * Load Word * @type {!Array} * @const ### @LW = Array.apply(@readDummy32, Array(@lengthy)) ###* * Store byte * @type {!Array} * @const ### @SB = Array.apply(@writeDummy8, Array(@lengthy)) ###* * Store Half * @type {!Array} * @const ### @SH = Array.apply(@writeDummy16, Array(@lengthy)) ###* * Store Word * @type {!Array} * @const ### @SW = Array.apply(@writeDummy32, Array(@lengthy)) #todo: fix overlapping ramregs now that we are 0xffff in lut size instead of 0xfffc in lut size @t = undefined console.log "lengthy0 = " + @lengthy @readDummy8 = (a) => `const off_ = a & 0xFFFC` @dummyReadWriteUint8Array[off_] @readDummy16 = (a) => `const off_ = a & 0xFFFC` @dummyReadWriteUint8Array[off_] << 8 | @dummyReadWriteUint8Array[off_ + 1] @readDummy32 = (a) => `const off_ = a & 0xFFFC` @dummyReadWriteUint8Array[off_] << 24 | @dummyReadWriteUint8Array[off_ + 1] << 16 | @dummyReadWriteUint8Array[off_ + 2] << 8 | @dummyReadWriteUint8Array[off_ + 3] @readRdram8 = (a) => @u8[a] @readRdram16 = (a) => `const ram = this.u8` ram[a] << 8 | ram[a + 1] @readRdram32 = (a) => `const ram = this.u8` ram[a] << 24 | ram[a + 1] << 16 | ram[a + 2] << 8 | ram[a + 3] @readRamRegs0_8 = (a) => `const off_ = a - MEMORY_START_RAMREGS0` @ramRegs0Uint8Array[off_] @readRamRegs0_16 = (a) => `const off_ = (a-MEMORY_START_RAMREGS0)` @ramRegs0Uint8Array[off_] << 8 | @ramRegs0Uint8Array[off_ + 1] @readRamRegs0_32 = (a) => `const off_ = (a-MEMORY_START_RAMREGS0)` @ramRegs0Uint8Array[off_] << 24 | @ramRegs0Uint8Array[off_ + 1] << 16 | @ramRegs0Uint8Array[off_ + 2] << 8 | @ramRegs0Uint8Array[off_ + 3] @readRamRegs4_8 = (a) => `const off_ = a - MEMORY_START_RAMREGS4` @ramRegs4Uint8Array[off_] @readRamRegs4_16 = (a) => `const off_ = (a-MEMORY_START_RAMREGS4)` @ramRegs4Uint8Array[off_] << 8 | @ramRegs4Uint8Array[off_ + 1] @readRamRegs4_32 = (a) => `const off_ = (a-MEMORY_START_RAMREGS4)` @ramRegs4Uint8Array[off_] << 24 | @ramRegs4Uint8Array[off_ + 1] << 16 | @ramRegs4Uint8Array[off_ + 2] << 8 | @ramRegs4Uint8Array[off_ + 3] @readRamRegs8_8 = (a) => `const off_ = a - MEMORY_START_RAMREGS8` @ramRegs8Uint8Array[off_] @readRamRegs8_16 = (a) => `const off_ = (a-MEMORY_START_RAMREGS8)` @ramRegs8Uint8Array[off_] << 8 | @ramRegs8Uint8Array[off_ + 1] @readRamRegs8_32 = (a) => `const off_ = (a-MEMORY_START_RAMREGS8)` @ramRegs8Uint8Array[off_] << 24 | @ramRegs8Uint8Array[off_ + 1] << 16 | @ramRegs8Uint8Array[off_ + 2] << 8 | @ramRegs8Uint8Array[off_ + 3] @readSpMem8 = (a) => `const off_ = a - MEMORY_START_SPMEM` @spMemUint8Array[off_] @readSpMem16 = (a) => `const off_ = (a-MEMORY_START_SPMEM)` @spMemUint8Array[off_] << 8 | @spMemUint8Array[off_ + 1] @readSpMem32 = (a) => `const off_ = (a-MEMORY_START_SPMEM)` @spMemUint8Array[off_] << 24 | @spMemUint8Array[off_ + 1] << 16 | @spMemUint8Array[off_ + 2] << 8 | @spMemUint8Array[off_ + 3] @readSpReg1_8 = (a) => `const off_ = a - MEMORY_START_SPREG_1` @core.interrupts.readSPReg1 off_ @readSpReg1_16 = (a) => `const off_ = a - MEMORY_START_SPREG_1` @core.interrupts.readSPReg1 off_ @readSpReg1_32 = (a) => `const off_ = a - MEMORY_START_SPREG_1` @core.interrupts.readSPReg1 off_ @readSpReg2_8 = (a) => `const off_ = a - MEMORY_START_SPREG_2` @spReg2Uint8Array[off_] @readSpReg2_16 = (a) => `const off_ = (a-MEMORY_START_SPREG_2)` @spReg2Uint8Array[off_] << 8 | @spReg2Uint8Array[off_ + 1] @readSpReg2_32 = (a) => `const off_ = (a-MEMORY_START_SPREG_2)` @spReg2Uint8Array[off_] << 24 | @spReg2Uint8Array[off_ + 1] << 16 | @spReg2Uint8Array[off_ + 2] << 8 | @spReg2Uint8Array[off_ + 3] @readDpc8 = (a) => `const off_ = a - MEMORY_START_DPC` @dpcUint8Array[off_] @readDpc16 = (a) => `const off_ = (a-MEMORY_START_DPC)` @dpcUint8Array[off_] << 8 | @dpcUint8Array[off_ + 1] @readDpc32 = (a) => `const off_ = (a-MEMORY_START_DPC)` @dpcUint8Array[off_] << 24 | @dpcUint8Array[off_ + 1] << 16 | @dpcUint8Array[off_ + 2] << 8 | @dpcUint8Array[off_ + 3] @readDps8 = (a) => `const off_ = a - MEMORY_START_DPS` @dpsUint8Array[off_] @readDps16 = (a) => `const off_ = (a-MEMORY_START_DPS)` @dpsUint8Array[off_] << 8 | @dpsUint8Array[off_ + 1] @readDps32 = (a) => `const off_ = (a-MEMORY_START_DPS)` @dpsUint8Array[off_] << 24 | @dpsUint8Array[off_ + 1] << 16 | @dpsUint8Array[off_ + 2] << 8 | @dpsUint8Array[off_ + 3] @readMi8 = (a) => `const off_ = a - MEMORY_START_MI` @miUint8Array[off_] @readMi16 = (a) => `const off_ = (a-MEMORY_START_MI)` @miUint8Array[off_] << 8 | @miUint8Array[off_ + 1] @readMi32 = (a) => `const off_ = (a-MEMORY_START_MI)` @miUint8Array[off_] << 24 | @miUint8Array[off_ + 1] << 16 | @miUint8Array[off_ + 2] << 8 | @miUint8Array[off_ + 3] @readVi8 = (a) => `const off_ = a - MEMORY_START_VI` @core.interrupts.readVI off_ @readVi16 = (a) => `const off_ = a - MEMORY_START_VI` @core.interrupts.readVI off_ @readVi32 = (a) => `const off_ = a - MEMORY_START_VI` @core.interrupts.readVI off_ @readAi8 = (a) => `const off_ = a - MEMORY_START_AI` @core.interrupts.readAI off_ @readAi16 = (a) => `const off_ = a - MEMORY_START_AI` @core.interrupts.readAI off_ @readAi32 = (a) => `const off_ = a - MEMORY_START_AI` @core.interrupts.readAI off_ @readPi8 = (a) => `const off_ = a - MEMORY_START_PI` @piUint8Array[off_] @readPi16 = (a) => `const off_ = (a-MEMORY_START_PI)` @piUint8Array[off_] << 8 | @piUint8Array[off_ + 1] @readPi32 = (a) => `const off_ = (a-MEMORY_START_PI)` @piUint8Array[off_] << 24 | @piUint8Array[off_ + 1] << 16 | @piUint8Array[off_ + 2] << 8 | @piUint8Array[off_ + 3] @readSi8 = (a) => `const off_ = a - MEMORY_START_SI` @core.interrupts.readSI off_ @readSi16 = (a) => `const off_ = a - MEMORY_START_SI` @core.interrupts.readSI off_ @readSi32 = (a) => `const off_ = a - MEMORY_START_SI` @core.interrupts.readSI off_ @readC2A1_8 = (a) => `const off_ = a - MEMORY_START_C2A1` @c2a1Uint8Array[off_] @readC2A1_16 = (a) => `const off_ = (a-MEMORY_START_C2A1)` @c2a1Uint8Array[off_] << 8 | @c2a1Uint8Array[off_ + 1] @readC2A1_32 = (a) => `const off_ = (a-MEMORY_START_C2A1)` @c2a1Uint8Array[off_] << 24 | @c2a1Uint8Array[off_ + 1] << 16 | @c2a1Uint8Array[off_ + 2] << 8 | @c2a1Uint8Array[off_ + 3] @readC1A1_8 = (a) => `const off_ = a - MEMORY_START_C1A1` @c1a1Uint8Array[off_] @readC1A1_16 = (a) => `const off_ = (a-MEMORY_START_C1A1)` @c1a1Uint8Array[off_] << 8 | @c1a1Uint8Array[off_ + 1] @readC1A1_32 = (a) => `const off_ = (a-MEMORY_START_C1A1)` @c1a1Uint8Array[off_] << 24 | @c1a1Uint8Array[off_ + 1] << 16 | @c1a1Uint8Array[off_ + 2] << 8 | @c1a1Uint8Array[off_ + 3] @readC2A2_8 = (a) => `const off_ = a - MEMORY_START_C2A2` @c2a2Uint8Array[off_] @readC2A2_16 = (a) => `const off_ = (a-MEMORY_START_C2A2)` @c2a2Uint8Array[off_] << 8 | @c2a2Uint8Array[off_ + 1] @readC2A2_32 = (a) => `const off_ = (a-MEMORY_START_C2A2)` @c2a2Uint8Array[off_] << 24 | @c2a2Uint8Array[off_ + 1] << 16 | @c2a2Uint8Array[off_ + 2] << 8 | @c2a2Uint8Array[off_ + 3] @readRom8 = (a) => `const off_ = a - MEMORY_START_ROM_IMAGE` @romUint8Array[off_] @readRom16 = (a) => `const off_ = (a-MEMORY_START_ROM_IMAGE)` @romUint8Array[off_] << 8 | @romUint8Array[off_ + 1] @readRom32 = (a) => `const off_ = (a-MEMORY_START_ROM_IMAGE)` @romUint8Array[off_] << 24 | @romUint8Array[off_ + 1] << 16 | @romUint8Array[off_ + 2] << 8 | @romUint8Array[off_ + 3] @readC1A3_8 = (a) => `const off_ = a - MEMORY_START_C1A3` @c1a3Uint8Array[off_] @readC1A3_16 = (a) => `const off_ = (a-MEMORY_START_C1A3)` @c1a3Uint8Array[off_] << 8 | @c1a3Uint8Array[off_ + 1] @readC1A3_32 = (a) => `const off_ = (a-MEMORY_START_C1A3)` @c1a3Uint8Array[off_] << 24 | @c1a3Uint8Array[off_ + 1] << 16 | @c1a3Uint8Array[off_ + 2] << 8 | @c1a3Uint8Array[off_ + 3] @readRi8 = (a) => `const off_ = a - MEMORY_START_RI` @riUint8Array[off_] @readRi16 = (a) => `const off_ = (a-MEMORY_START_RI)` @riUint8Array[off_] << 8 | @riUint8Array[off_ + 1] @readRi32 = (a) => `const off_ = (a-MEMORY_START_RI)` @riUint8Array[off_] << 24 | @riUint8Array[off_ + 1] << 16 | @riUint8Array[off_ + 2] << 8 | @riUint8Array[off_ + 3] @readPif8 = (a) => `const off_ = a - MEMORY_START_PIF` @pifUint8Array[off_] @readPif16 = (a) => `const off_ = (a-MEMORY_START_PIF)` @pifUint8Array[off_] << 8 | @pifUint8Array[off_ + 1] @readPif32 = (a) => `const off_ = (a-MEMORY_START_PIF)` @pifUint8Array[off_] << 24 | @pifUint8Array[off_ + 1] << 16 | @pifUint8Array[off_ + 2] << 8 | @pifUint8Array[off_ + 3] @readGio8 = (a) => `const off_ = a - MEMORY_START_GIO` @gioUint8Array[off_] @readGio16 = (a) => `const off_ = (a-MEMORY_START_GIO)` @gioUint8Array[off_] << 8 | @gioUint8Array[off_ + 1] @readGio32 = (a) => `const off_ = (a-MEMORY_START_GIO)` @gioUint8Array[off_] << 24 | @gioUint8Array[off_ + 1] << 16 | @gioUint8Array[off_ + 2] << 8 | @gioUint8Array[off_ + 3] @writeRdram8 = (val, a) => @u8[a] = val return @writeRdram16 = (val, a) => `const ram = this.u8` ram[a] = val >> 8 ram[a + 1] = val return @writeRdram32 = (val, a) => `const ram = this.u8` ram[a] = val >> 24 ram[a + 1] = val >> 16 ram[a + 2] = val >> 8 ram[a + 3] = val return @writeSpMem8 = (val, a) => `const off_ = a - MEMORY_START_SPMEM` @spMemUint8Array[off_] = val return @writeSpMem16 = (val, a) => `const off_ = a - MEMORY_START_SPMEM` @spMemUint8Array[off_] = val >> 8 @spMemUint8Array[off_ + 1] = val return @writeSpMem32 = (val, a) => `const off_ = a - MEMORY_START_SPMEM` `const mem = this.spMemUint8Array` mem[off_] = val >> 24 mem[off_ + 1] = val >> 16 mem[off_ + 2] = val >> 8 mem[off_ + 3] = val return @writeRi8 = (val, a) => `const off_ = a - MEMORY_START_RI` @riUint8Array[off_] = val return @writeRi16 = (val, a) => `const off_ = a - MEMORY_START_RI` @riUint8Array[off_] = val >> 8 @riUint8Array[off_ + 1] = val return @writeRi32 = (val, a) => `const off_ = a - MEMORY_START_RI` @riUint8Array[off_] = val >> 24 @riUint8Array[off_ + 1] = val >> 16 @riUint8Array[off_ + 2] = val >> 8 @riUint8Array[off_ + 3] = val return @writeMi8 = (val, a, pc, isDelaySlot) => `const off_ = a - MEMORY_START_MI` @core.interrupts.writeMI off_, val, pc, isDelaySlot return @writeMi16 = (val, a, pc, isDelaySlot) => `const off_ = a - MEMORY_START_MI` @core.interrupts.writeMI off_, val, pc, isDelaySlot return @writeMi32 = (val, a, pc, isDelaySlot) => `const off_ = a - MEMORY_START_MI` @core.interrupts.writeMI off_, val, pc, isDelaySlot return @writeRamRegs8_8 = (val, a) => `const off_ = a - MEMORY_START_RAMREGS8` @ramRegs8Uint8Array[off_] = val return @writeRamRegs8_16 = (val, a) => `const off_ = a - MEMORY_START_RAMREGS8` @ramRegs8Uint8Array[off_] = val >> 8 @ramRegs8Uint8Array[off_ + 1] = val return @writeRamRegs8_32 = (val, a) => `const off_ = a - MEMORY_START_RAMREGS8` @ramRegs8Uint8Array[off_] = val >> 24 @ramRegs8Uint8Array[off_ + 1] = val >> 16 @ramRegs8Uint8Array[off_ + 2] = val >> 8 @ramRegs8Uint8Array[off_ + 3] = val return @writeRamRegs4_8 = (val, a) => `const off_ = a - MEMORY_START_RAMREGS4` @ramRegs4Uint8Array[off_] = val return @writeRamRegs4_16 = (val, a) => `const off_ = a - MEMORY_START_RAMREGS4` @ramRegs4Uint8Array[off_] = val >> 8 @ramRegs4Uint8Array[off_ + 1] = val return @writeRamRegs4_32 = (val, a) => `const off_ = a - MEMORY_START_RAMREGS4` @ramRegs4Uint8Array[off_] = val >> 24 @ramRegs4Uint8Array[off_ + 1] = val >> 16 @ramRegs4Uint8Array[off_ + 2] = val >> 8 @ramRegs4Uint8Array[off_ + 3] = val return @writeRamRegs0_8 = (val, a) => `const off_ = a - MEMORY_START_RAMREGS0` @ramRegs0Uint8Array[off_] = val return @writeRamRegs0_16 = (val, a) => `const off_ = a - MEMORY_START_RAMREGS0` @ramRegs0Uint8Array[off_] = val >> 8 @ramRegs0Uint8Array[off_ + 1] = val return @writeRamRegs0_32 = (val, a) => `const off_ = a - MEMORY_START_RAMREGS0` @ramRegs0Uint8Array[off_] = val >> 24 @ramRegs0Uint8Array[off_ + 1] = val >> 16 @ramRegs0Uint8Array[off_ + 2] = val >> 8 @ramRegs0Uint8Array[off_ + 3] = val return @writeSpReg1_8 = (val, a, pc, isDelaySlot) => `const off_ = a - MEMORY_START_SPREG_1` @core.interrupts.writeSPReg1 off_, val, pc, isDelaySlot return @writeSpReg1_16 = (val, a, pc, isDelaySlot) => `const off_ = a - MEMORY_START_SPREG_1` @core.interrupts.writeSPReg1 off_, val, pc, isDelaySlot return @writeSpReg1_32 = (val, a, pc, isDelaySlot) => `const off_ = a - MEMORY_START_SPREG_1` @core.interrupts.writeSPReg1 off_, val, pc, isDelaySlot return @writePi8 = (val, a, pc, isDelaySlot) => `const off_ = a - MEMORY_START_PI` @core.interrupts.writePI off_, val, pc, isDelaySlot return @writePi16 = (val, a, pc, isDelaySlot) => `const off_ = a - MEMORY_START_PI` @core.interrupts.writePI off_, val, pc, isDelaySlot return @writePi32 = (val, a, pc, isDelaySlot) => `const off_ = a - MEMORY_START_PI` @core.interrupts.writePI off_, val, pc, isDelaySlot return @writeSi8 = (val, a, pc, isDelaySlot) => `const off_ = a - MEMORY_START_SI` @core.interrupts.writeSI off_, val, pc, isDelaySlot return @writeSi16 = (val, a, pc, isDelaySlot) => `const off_ = a - MEMORY_START_SI` @core.interrupts.writeSI off_, val, pc, isDelaySlot return @writeSi32 = (val, a, pc, isDelaySlot) => `const off_ = a - MEMORY_START_SI` @core.interrupts.writeSI off_, val, pc, isDelaySlot return @writeAi8 = (val, a, pc, isDelaySlot) => `const off_ = a - MEMORY_START_AI` @core.interrupts.writeAI off_, val, pc, isDelaySlot return @writeAi16 = (val, a, pc, isDelaySlot) => `const off_ = a - MEMORY_START_AI` @core.interrupts.writeAI off_, val, pc, isDelaySlot return @writeAi32 = (val, a, pc, isDelaySlot) => `const off_ = a - MEMORY_START_AI` @core.interrupts.writeAI off_, val, pc, isDelaySlot return @writeVi8 = (val, a, pc, isDelaySlot) => `const off_ = a - MEMORY_START_VI` @core.interrupts.writeVI off_, val, pc, isDelaySlot return @writeVi16 = (val, a, pc, isDelaySlot) => `const off_ = a - MEMORY_START_VI` @core.interrupts.writeVI off_, val, pc, isDelaySlot return @writeVi32 = (val, a, pc, isDelaySlot) => `const off_ = a - MEMORY_START_VI` @core.interrupts.writeVI off_, val, pc, isDelaySlot return @writeSpReg2_8 = (val, a, pc, isDelaySlot) => `const off_ = a - MEMORY_START_SPREG_2` @core.interrupts.writeSPReg2 off_, val, pc, isDelaySlot return @writeSpReg2_16 = (val, a, pc, isDelaySlot) => `const off_ = a - MEMORY_START_SPREG_2` @core.interrupts.writeSPReg2 off_, val, pc, isDelaySlot return @writeSpReg2_32 = (val, a, pc, isDelaySlot) => `const off_ = a - MEMORY_START_SPREG_2` @core.interrupts.writeSPReg2 off_, val, pc, isDelaySlot return @writeDpc8 = (val, a, pc, isDelaySlot) => `const off_ = a - MEMORY_START_DPC` @core.interrupts.writeDPC off_, val, pc, isDelaySlot return @writeDpc16 = (val, a, pc, isDelaySlot) => `const off_ = a - MEMORY_START_DPC` @core.interrupts.writeDPC off_, val, pc, isDelaySlot return @writeDpc32 = (val, a, pc, isDelaySlot) => `const off_ = a - MEMORY_START_DPC` @core.interrupts.writeDPC off_, val, pc, isDelaySlot return @writeDps8 = (val, a) => `const off_ = a - MEMORY_START_DPS` @dpsUint8Array[off_] = val return @writeDps16 = (val, a) => `const off_ = a - MEMORY_START_DPS` @dpsUint8Array[off_] = val >> 8 @dpsUint8Array[off_ + 1] = val return @writeDps32 = (val, a) => `const off_ = a - MEMORY_START_DPS` @dpsUint8Array[off_] = val >> 24 @dpsUint8Array[off_ + 1] = val >> 16 @dpsUint8Array[off_ + 2] = val >> 8 @dpsUint8Array[off_ + 3] = val return @writeC2A1_8 = (val, a) => `const off_ = a - MEMORY_START_C2A1` @c2a1Uint8Array[off_] = val return @writeC2A1_16 = (val, a) => `const off_ = a - MEMORY_START_C2A1` @c2a1Uint8Array[off_] = val >> 8 @c2a1Uint8Array[off_ + 1] = val return @writeC2A1_32 = (val, a) => `const off_ = a - MEMORY_START_C2A1` @c2a1Uint8Array[off_] = val >> 24 @c2a1Uint8Array[off_ + 1] = val >> 16 @c2a1Uint8Array[off_ + 2] = val >> 8 @c2a1Uint8Array[off_ + 3] = val return @writeC1A1_8 = (val, a) => `const off_ = a - MEMORY_START_C1A1` @c1a1Uint8Array[off_] = val return @writeC1A1_16 = (val, a) => `const off_ = a - MEMORY_START_C1A1` @c1a1Uint8Array[off_] = val >> 8 @c1a1Uint8Array[off_ + 1] = val return @writeC1A1_32 = (val, a) => `const off_ = a - MEMORY_START_C1A1` @c1a1Uint8Array[off_] = val >> 24 @c1a1Uint8Array[off_ + 1] = val >> 16 @c1a1Uint8Array[off_ + 2] = val >> 8 @c1a1Uint8Array[off_ + 3] = val return @writeC2A2_8 = (val, a) => `const off_ = a - MEMORY_START_C2A2` @c2a2Uint8Array[off_] = val return @writeC2A2_16 = (val, a) => `const off_ = a - MEMORY_START_C2A2` @c2a2Uint8Array[off_] = val >> 8 @c2a2Uint8Array[off_ + 1] = val return @writeC2A2_32 = (val, a) => `const off_ = a - MEMORY_START_C2A2` @c2a2Uint8Array[off_] = val >> 24 @c2a2Uint8Array[off_ + 1] = val >> 16 @c2a2Uint8Array[off_ + 2] = val >> 8 @c2a2Uint8Array[off_ + 3] = val return @writeRom8 = (val, a) => alert "attempt to overwrite rom!" # `const off_ = a - MEMORY_START_ROM_IMAGE` # @romUint8Array[off_] = val return @writeRom16 = (val, a) => alert "attempt to overwrite rom!" # `const off_ = a - MEMORY_START_ROM_IMAGE` # @romUint8Array[off_] = val >> 8 # @romUint8Array[off_ + 1] = val return @writeRom32 = (val, a) => alert "attempt to overwrite rom!" # `const off_ = a - MEMORY_START_ROM_IMAGE` # @romUint8Array[off_] = val >> 24 # @romUint8Array[off_ + 1] = val >> 16 # @romUint8Array[off_ + 2] = val >> 8 # @romUint8Array[off_ + 3] = val return @writeC1A3_8 = (val, a) => `const off_ = a - MEMORY_START_C1A3` @c1a3Uint8Array[off_] = val return @writeC1A3_16 = (val, a) => `const off_ = a - MEMORY_START_C1A3` @c1a3Uint8Array[off_] = val >> 8 @c1a3Uint8Array[off_ + 1] = val return @writeC1A3_32 = (val, a) => `const off_ = a - MEMORY_START_C1A3` @c1a3Uint8Array[off_] = val >> 24 @c1a3Uint8Array[off_ + 1] = val >> 16 @c1a3Uint8Array[off_ + 2] = val >> 8 @c1a3Uint8Array[off_ + 3] = val return @writePif8 = (val, a) => `const off_ = a - MEMORY_START_PIF` @pifUint8Array[off_] = val return @writePif16 = (val, a) => `const off_ = a - MEMORY_START_PIF` @pifUint8Array[off_] = val >> 8 @pifUint8Array[off_ + 1] = val return @writePif32 = (val, a) => `const off_ = a - MEMORY_START_PIF` @pifUint8Array[off_] = val >> 24 @pifUint8Array[off_ + 1] = val >> 16 @pifUint8Array[off_ + 2] = val >> 8 @pifUint8Array[off_ + 3] = val return @writeGio8 = (val, a) => `const off_ = a - MEMORY_START_GIO` @gioUint8Array[off_] = val return @writeGio16 = (val, a) => `const off_ = a - MEMORY_START_GIO` @gioUint8Array[off_] = val >> 8 @gioUint8Array[off_ + 1] = val return @writeGio32 = (val, a) => `const off_ = a - MEMORY_START_GIO` @gioUint8Array[off_] = val >> 24 @gioUint8Array[off_ + 1] = val >> 16 @gioUint8Array[off_ + 2] = val >> 8 @gioUint8Array[off_ + 3] = val return @writeDummy8 = (val, a) => #log "writing to invalid memory at " + dec2hex(a) `const off_ = a & 0x0000fffc` @dummyReadWriteUint8Array[off_] = val return @writeDummy16 = (val, a) => `const off_ = a & 0x0000fffc` @dummyReadWriteUint8Array[off_] = val >> 8 @dummyReadWriteUint8Array[off_ + 1] = val return @writeDummy32 = (val, a) => `const off_ = a & 0x0000fffc` @dummyReadWriteUint8Array[off_] = val >> 24 @dummyReadWriteUint8Array[off_ + 1] = val >> 16 @dummyReadWriteUint8Array[off_ + 2] = val >> 8 @dummyReadWriteUint8Array[off_ + 3] = val return @virtualToPhysical = (a) => #uncomment to see where we're loading/storing #if ((((a & 0xF0000000)>>>0) isnt 0x80000000) and (((a & 0xF0000000)>>>0) isnt 0xA0000000)) # alert(dec2hex(a)) #uncomment to verify non-tlb lookup. #if dec2hex(a) != dec2hex(((@t[a>>>12]<<16) | a&0x0000ffff)) # alert dec2hex(a) + ' ' + dec2hex(((@t[a>>>12]<<16) | a&0x0000ffff)) return ((@t[a>>>12]<<18>>>2) | (a&0x0000ffff)) # removes the upper-2 bits to support kseg mirrors @readTLB8 = (b) => `const a = this.virtualToPhysical(b)` region = @LB[a>>>16] if region is @readTLB8 region = @readDummy8 region(a) @writeTLB8 = (val, b, pc, isDelaySlot) => `const a = this.virtualToPhysical(b)` region = @SB[a>>>16] if region is @writeTLB8 region = @writeDummy8 region(val, a, pc, isDelaySlot) return @readTLB16 = (b) => `const a = this.virtualToPhysical(b)` region = @LH[a>>>16] if region is @readTLB16 region = @readDummy16 region(a) @writeTLB16 = (val, b, pc, isDelaySlot) => `const a = this.virtualToPhysical(b)` region = @SH[a>>>16] if region is @writeTLB16 region = @writeDummy16 region(val, a, pc, isDelaySlot) return @readTLB32 = (b) => `const a = this.virtualToPhysical(b)` region = @LW[a>>>16] if region is @readTLB32 region = @readDummy32 region(a) @writeTLB32 = (val, b, pc, isDelaySlot) => `const a = this.virtualToPhysical(b)` region = @SW[a>>>16] if region is @writeTLB32 region = @writeDummy32 region(val, a, pc, isDelaySlot) return return initRegions: () -> @initRegion 0, 0x80000000, @readTLB8, @writeTLB8, @readTLB16, @writeTLB16, @readTLB32, @writeTLB32 @initRegion 0x80000000, 0x40000000, @readDummy8, @writeDummy8, @readDummy16, @writeDummy16, @readDummy32, @writeDummy32 @initRegion 0xC0000000, 0x40000000, @readTLB8, @writeTLB8, @readTLB16, @writeTLB16, @readTLB32, @writeTLB32 @initRegion MEMORY_START_RDRAM, @core.getRdramSize(), @readRdram8, @writeRdram8, @readRdram16, @writeRdram16, @readRdram32, @writeRdram32 @initRegion MEMORY_START_RAMREGS4, MEMORY_SIZE_RAMREGS4, @readRamRegs4_8, @writeRamRegs4_8, @readRamRegs4_16, @writeRamRegs4_16, @readRamRegs4_32, @writeRamRegs4_32 @initRegion MEMORY_START_SPMEM, MEMORY_SIZE_SPMEM, @readSpMem8, @writeSpMem8, @readSpMem16, @writeSpMem16, @readSpMem32, @writeSpMem32 @initRegion MEMORY_START_SPREG_1, MEMORY_SIZE_SPREG_1, @readSpReg1_8, @writeSpReg1_8, @readSpReg1_16, @writeSpReg1_16, @readSpReg1_32, @writeSpReg1_32 @initRegion MEMORY_START_SPREG_2, MEMORY_SIZE_SPREG_2, @readSpReg2_8, @writeSpReg2_8, @readSpReg2_16, @writeSpReg2_16, @readSpReg2_32, @writeSpReg2_32 @initRegion MEMORY_START_DPC, MEMORY_SIZE_DPC, @readDpc8, @writeDpc8, @readDpc16, @writeDpc16, @readDpc32, @writeDpc32 @initRegion MEMORY_START_DPS, MEMORY_SIZE_DPS, @readDps8, @writeDps8, @readDps16, @writeDps16, @readDps32, @writeDps32 @initRegion MEMORY_START_MI, MEMORY_SIZE_MI, @readMi8, @writeMi8, @readMi16, @writeMi16, @readMi32, @writeMi32 @initRegion MEMORY_START_VI, MEMORY_SIZE_VI, @readVi8, @writeVi8, @readVi16, @writeVi16, @readVi32, @writeVi32 @initRegion MEMORY_START_AI, MEMORY_SIZE_AI, @readAi8, @writeAi8, @readAi16, @writeAi16, @readAi32, @writeAi32 @initRegion MEMORY_START_PI, MEMORY_SIZE_PI, @readPi8, @writePi8, @readPi16, @writePi16, @readPi32, @writePi32 @initRegion MEMORY_START_SI, MEMORY_SIZE_SI, @readSi8, @writeSi8, @readSi16, @writeSi16, @readSi32, @writeSi32 @initRegion MEMORY_START_C2A1, MEMORY_SIZE_C2A1, @readC2A1_8, @writeC2A1_8, @readC2A1_16, @writeC2A1_16, @readC2A1_32, @writeC2A1_32 @initRegion MEMORY_START_C1A1, MEMORY_SIZE_C1A1, @readC1A1_8, @writeC1A1_8, @readC1A1_16, @writeC1A1_16, @readC1A1_32, @writeC1A1_32 @initRegion MEMORY_START_C2A2, MEMORY_SIZE_C2A2, @readC2A2_8, @writeC2A2_8, @readC2A2_16, @writeC2A2_16, @readC2A2_32, @writeC2A2_32 @initRegion MEMORY_START_ROM_IMAGE, MEMORY_SIZE_ROM, @readRom8, @writeRom8, @readRom16, @writeRom16, @readRom32, @writeRom32 #todo: could be a problem to use romLength @initRegion MEMORY_START_C1A3, MEMORY_SIZE_C1A3, @readC1A3_8, @writeC1A3_8, @readC1A3_16, @writeC1A3_16, @readC1A3_32, @writeC1A3_32 @initRegion MEMORY_START_RI, MEMORY_SIZE_RI, @readRi8, @writeRi8, @readRi16, @writeRi16, @readRi32, @writeRi32 @initRegion MEMORY_START_PIF, MEMORY_SIZE_PIF, @readPif8, @writePif8, @readPif16, @writePif16, @readPif32, @writePif32 @initRegion MEMORY_START_GIO, MEMORY_SIZE_GIO, @readGio8, @writeGio8, @readGio16, @writeGio16, @readGio32, @writeGio32 @initRegion MEMORY_START_RAMREGS0, MEMORY_SIZE_RAMREGS0, @readRamRegs0_8, @writeRamRegs0_8, @readRamRegs0_16, @writeRamRegs0_16, @readRamRegs0_32, @writeRamRegs0_32 @initRegion MEMORY_START_RAMREGS8, MEMORY_SIZE_RAMREGS8, @readRamRegs8_8, @writeRamRegs8_8, @readRamRegs8_16, @writeRamRegs8_16, @readRamRegs8_32, @writeRamRegs8_32 initRegion: (start, size, LB, SB, readLH, SH, readLW, SW) -> end = (start + size) >>> 16 start >>>= 16 while start < end @LB[start] = LB @LH[start] = readLH @LW[start] = readLW @SB[start] = SB @SH[start] = SH @SW[start] = SW start++ #@lengthy++ return initts: -> #Initialize the TLB Lookup Table @t = new Int16Array(0x100000) i = 0 #todo: replace with call to buildTLBHelper clear while i < 0x100000 @t[i] = (i & 0x1ffff) >>> 4 i++ return #getInt32 and getUint32 are identical. they both return signed. getInt32: (uregion, off_) -> uregion[off_] << 24 | uregion[off_ + 1] << 16 | uregion[off_ + 2] << 8 | uregion[off_ + 3] getUint32: (uregion, off_) -> uregion[off_] << 24 | uregion[off_ + 1] << 16 | uregion[off_ + 2] << 8 | uregion[off_ + 3] setInt32: (uregion, off_, val) -> uregion[off_] = val >> 24 uregion[off_ + 1] = val >> 16 uregion[off_ + 2] = val >> 8 uregion[off_ + 3] = val return setUint32: (uregion, off_, val) -> uregion[off_] = val >> 24 uregion[off_ + 1] = val >> 16 uregion[off_ + 2] = val >> 8 uregion[off_ + 3] = val return lb: (addr) -> #throw Error "todo: mirrored load address" if (addr & 0xff000000) is 0x84000000 `const a = this.virtualToPhysical(addr)` @LB[a>>>16](a) lh: (addr) -> #throw Error "todo: mirrored load address" if (addr & 0xff000000) is 0x84000000 `const a = this.virtualToPhysical(addr)&0x3fffffff` @LH[a>>>16](a) lw: (addr) -> #throw Error "todo: mirrored load address" if (addr & 0xff000000) is 0x84000000 `const a = this.virtualToPhysical(addr)` @LW[a>>>16](a) sw: (val, addr, pc, isDelaySlot) -> #throw Error "todo: mirrored load address" if (addr & 0xff000000) is 0x84000000 `const a = this.virtualToPhysical(addr)` @SW[a>>>16](val, a, pc, isDelaySlot) return #Same routine as storeWord, but store a byte sb: (val, addr, pc, isDelaySlot) -> #throw Error "todo: mirrored load address" if (addr & 0xff000000) is 0x84000000 `const a = this.virtualToPhysical(addr)` @SB[a>>>16](val, a, pc, isDelaySlot) return sh: (val, addr, pc, isDelaySlot) -> #throw Error "todo: mirrored load address" if (addr & 0xff000000) is 0x84000000 `const a = this.virtualToPhysical(addr)` @SH[a>>>16](val, a, pc, isDelaySlot) return #hack global space until we export classes properly #node.js uses exports; browser uses this (window) root = exports ? self root.C1964jsMemory = C1964jsMemory