⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpumemory.pas

📁 一个不出名的GBA模拟器
💻 PAS
📖 第 1 页 / 共 5 页
字号:
//////////////////////////////////////////////////////////////////////
//                                                                  //
// cpuMemory.pas: CPU memory subsystem                              //
//   This handles all memory access and cartridge control           //
//                                                                  //
// The contents of this file are subject to the Bottled Light       //
// Public License Version 1.0 (the "License"); you may not use this //
// file except in compliance with the License. You may obtain a     //
// copy of the License at http://www.bottledlight.com/BLPL/         //
//                                                                  //
// Software distributed under the License is distributed on an      //
// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or   //
// implied. See the License for the specific language governing     //
// rights and limitations under the License.                        //
//                                                                  //
// The Original Code is the Mappy VM Core, released April 1st, 2003 //
// The Initial Developer of the Original Code is Bottled Light,     //
// Inc. Portions created by Bottled Light, Inc. are Copyright       //
// (C) 2001 - 2003 Bottled Light, Inc. All Rights Reserved.         //
//                                                                  //
// Author(s):                                                       //
//   Michael Noland (joat), michael@bottledlight.com                //
//                                                                  //
// Changelog:                                                       //
//   1.0: First public release (April 1st, 2003)                    //
//                                                                  //
// Greets:                                                          //
//   Forgotten provided C code to handle EEPROM access which I used //
//   to fix my version.  This was before VBA was released under the //
//   GPL.                                                           //
//                                                                  //
// Changelog:                                                       //
//   1.0: First public release                                      //
//                                                                  //
// Notes:                                                           //
//   CPU writes currently trigger a log write, thanks to my attempt //
//   to support the e-Reader.  This involves a ROM writes to a high //
//   address that needs to succeed (i.e. portions of the ROM space  //
//   for the e-Reader are actually RAM or control registers, or at  //
//   the very least, a single word).  In addition, at least the     //
//   american version of the e-Reader has strangely banked Flash    //
//   ROM, using a typical Flash control sequence ($B0 $xx, which    //
//   would normally be just $B0 to suspend a prior flash sector     //
//   erase command, but instead switches to bank xx) to bankswitch  //
//   between two 64 KB pages.  I've yet to test if all 8 bits are   //
//   used, or only the LSB, but I'd wager its only the LSB.         //
//   Right now, the e-Reader support is disabled, see               //
//   WriteROMBaby32 if you're interested in re-enabling the ROM     //
//   as RAM emulation.  I didn't keep it there because I didn't     //
//   find out the extents of the special address space, only a      //
//   single address seems to be currently used.                     //
//                                                                  //
//   The code in vmAddBreakpoint and vmRemoveBreakpoint could be    //
//   simplified a bit by altering the code in the breakpoint class. //
//   The toggle primitive is a remenant from when the code was all  //
//   a single project, no core seperation, and at the time it was   //
//   all that was needed.                                           //
//                                                                  //
//   I'm pretty sure the SRAM support is broken, or at least dodgy. //
//
//   There is some preliminary signature support, which would allow //
//   the user interface to display which regions of ROM are data,   //
//   and which regions contain either ARM or Thumb opcodes.  It is  //
//   currently IDFEF'ed out, and the sig writes were never added to //
//   data accesses.  In any event, theres no mechanism for the user //
//   interface to access the sig array right now.                   //
//                                                                  //
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
unit cpuMemory; //////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
interface ////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

uses
  Math, nexus, AddressSpace;

//////////////////////////////////////////////////////////////////////

procedure SetWaitStates;

function memReadByte(address: uint32): uint32;
procedure memWriteByte(address: uint32; data: uint32);
function memReadHalfWord(address: uint32): uint32;
procedure memWriteHalfWord(address: uint32; data: uint32);
function memReadWord(address: uint32): uint32;

// Does the rotation shiz
function memLoadWord(address: uint32): uint32;

procedure memWriteWord(address: uint32; data: uint32);

function memReadHalfWordUnc(address: uint32): uint32;
function memReadWordUnc(address: uint32): uint32;
procedure memWriteHalfWordUnc(address: uint32; data: uint32);
procedure memWriteWordUnc(address: uint32; data: uint32);

function memStopAtAddy(address: uint32): boolean;

procedure InitMemory;
procedure cpuMemFree;

//////////////////////////////////////////////////////////////////////
// Exported functions ////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

function vmReadByte(address: uint32): uint8;
function vmReadHalfword(address: uint32): uint16;
function vmReadWord(address: uint32): uint32;
procedure vmWriteByte(address: uint32; data: uint8);
procedure vmWriteHalfword(address: uint32; data: uint16);
procedure vmWriteWord(address: uint32; data: uint32);

procedure vmAddBreakpoint(address: uint32; soft: boolean);
procedure vmRemoveBreakpoint(address: uint32; mask: TBreakpointModes);
procedure vmSoftBreakpoints(active: boolean);
function vmIsBreakpoint(address: uint32): TBreakpointModes;

procedure vmInsertCartridge(data: pointer; size: integer);
procedure vmRemoveCartridge;

procedure vmLockMemory(var banks: TvmMemoryLock1);
procedure vmUnlockMemory(const banks: TvmMemoryLock1);

function vmGetCartInfo(info: PvmOpaqueChunk): integer;
procedure vmSetCartInfo(size: integer; info: PvmOpaqueChunk);

//////////////////////////////////////////////////////////////////////

exports
  vmReadByte,
  vmReadHalfword,
  vmReadWord,
  vmWriteByte,
  vmWriteHalfword,
  vmWriteWord,
  vmAddBreakpoint,
  vmRemoveBreakpoint,
  vmSoftBreakpoints,
  vmIsBreakpoint,
  vmInsertCartridge,
  vmRemoveCartridge,
  vmLockMemory,
  vmUnlockMemory,
  vmGetCartInfo,
  vmSetCartInfo;

//////////////////////////////////////////////////////////////////////

type
  TEepromMode = (emIdle, emReadAddress, emReadData, emReadData2, emWriteData);
  TFlashMode = (fmIdle, fmWriteData, fmProductID, fmExtended, fmErase, fmSectorErase, fmBankswitch);

//////////////////////////////////////////////////////////////////////
// State Variables ///////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

var
  // Memory spaces
  systemROM: array[0..SYSTEM_ROM_MASK] of byte;  // 00000000h..00003FFFh
  exWRAM: array[0..EX_WRAM_MASK] of byte;        // 02000000h..0203FFFFh
  WRAM: array[0..WRAM_MASK] of byte;             // 03000000h..03007FFFh
  registers: array[0..REGISTERS_MASK] of byte;   // 04000000h..
  palette: array[0..PALETTE_MASK] of byte;       // 05000000h..050003FFh
  VRAM: array[0..VRAM_MASK] of byte;             // 06000000h..06017FFFh
  OAM: array[0..OAM_MASK] of byte;               // 07000000h..070003FFh
  cartRAM: array[0..(SRAM_MASK+1)*2-1] of byte;          // 0E000000h..
  cartRAMdirty: boolean;
  lastAddress: uint32;

  // CPU status
  cpuGlobalTicks: uint32;
  cpuStopped, cpuHalted: boolean;
  irqPending: boolean;
  regs: array[0..36+2] of uint32;
  SPSR: uint32;

  // Events
  HBlankEvent: integer;
  enteringHBlank: boolean;
  eventCycleDelta: integer;
  eventCyclesLeft: integer;

  // Sound
  soundA, soundB: TDSoundRecord;
  sound1: TSoundChannel1;
  sound2: TSoundChannel2;
  sound3: TSoundChannel3;
  sound4: TSoundChannel4;

//////////////////////////////////////////////////////////////////////
// Globals shared between the emulation functions ////////////////////
//////////////////////////////////////////////////////////////////////

  // CPSR components (packed into regs[CPSR] for savestates)
  carry: boolean;
  overflow: boolean;
  negative: boolean;
  zero: boolean;
  irqDisabled: boolean;
  fiqDisabled: boolean;
  thumbMode: boolean;
  cpuMode: integer;

//////////////////////////////////////////////////////////////////////
// Not saved /////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

var
  // Only used in the decoders
  cpuCurrentOpcode: uint32;
  hitBreakpoint: boolean;
  barrelCarry: boolean;
  haveFlippedThumb: boolean;

  // Must be zero outside of vmExecute code path
  quota: integer;
  soundCyclesUndone: integer;
  soundQuotaAtLastFlush: integer;
  timerQuotaAtLastFlush: integer;

  // Maybe should be saved, but isn't right now
  eepromIndex, eepromByte, eepromAddress: uint32;
  eepromMode: TeepromMode;
  flashMode: TFlashMode;
  eepromBuffer: array[0..15] of byte;
  flashIndex: uint32;

  cartLoaded: boolean;
  cartROM1, cartROM2: Puint8Array;
  cartSize1, cartSize2: uint32;
  cartMask1, cartMask2: uint32;

  downKeys: uint16;
  cpuSourceDebug: boolean;

//////////////////////////////////////////////////////////////////////
// Signature support (will be used for smart disassembly)
// Note: no support has been added to the memory read/write code yet
//////////////////////////////////////////////////////////////////////

{$IFDEF SIGNATURES}
const
  ARM_READ = 1;
  THUMB_READ = 2;
  DATA_READ = 4;
  DATA_WRITE = 8;

var
  sigs: array[0..16777215] of byte;
{$ENDIF}

//////////////////////////////////////////////////////////////////////
implementation ///////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

uses
  SysUtils, cpuMisc, cpuGraphics, cpuSound, cpuPeripherals;

//////////////////////////////////////////////////////////////////////

type
  TBreakpointMemory = class
  private
    bpBanks: array[$0..$F] of Puint8Array;
    bpBankMasks: array[$0..$F] of uint32;

    FCartSize1, FCartSize2: uint32;
    bcartROM1, bcartROM2: Puint8Array;

    bsystemROM: array[0..(SYSTEM_ROM_MASK+1) shr 4-1] of byte;  // 00000000h..00003FFFh
    bexWRAM: array[0..(EX_WRAM_MASK+1) shr 4-1] of byte;        // 02000000h..0203FFFFh
    bWRAM: array[0..(WRAM_MASK+1) shr 4-1] of byte;             // 03000000h..03007FFFh
    bpalette: array[0..(PALETTE_MASK+1) shr 4-1] of byte;       // 05000000h..050003FFh
    bVRAM: array[0..(VRAM_MASK+1) shr 4-1] of byte;             // 06000000h..06017FFFh
    bOAM: array[0..(OAM_MASK+1) shr 4-1] of byte;               // 07000000h..070003FFh

    null: uint32;

    procedure SetCartSize1(const Value: uint32);
    procedure SetCartSize2(const Value: uint32);
  public
    constructor Create;
    destructor Destroy; override;
    property cartSize1: uint32 read FCartSize1 write SetCartSize1;
    property cartSize2: uint32 read FCartSize2 write SetCartSize2;

    function isBreakpoint(address: uint32): boolean;
    function toggleBreakpoint(address: uint32): boolean;
  end;

//////////////////////////////////////////////////////////////////////
// Non-state Variables (all regenerated) /////////////////////////////
//////////////////////////////////////////////////////////////////////

var
  bankNTimes: array[$0..$F] of byte;
  bankSTimes: array[$0..$F] of byte;

  interestingAddresses: TBreakpointMemory;
  breakpoints, sourcePoints: TBreakpointMemory;

  ReadByteFuncs, ReadHalfFuncs, ReadWordFuncs: array[0..$F] of function (address: uint32): uint32;
  WriteByteFuncs, WriteHalfFuncs, WriteWordFuncs: array[0..$F] of procedure (address, data: uint32);

  memBanks: array[0..15] of pointer;
  memMasks: array[0..15] of uint32;

  curBank: byte;

//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

function ReadNOP(address: uint32): uint32;
begin
  Result := 0;
end;

//////////////////////////////////////////////////////////////////////

procedure WriteNOP(address, data: uint32);
begin
//
end;

//////////////////////////////////////////////////////////////////////
// TODO: This is in-progress code for the e-Reader support
// also: see the table set functions which reference these
//////////////////////////////////////////////////////////////////////

procedure WriteROMBaby8(address, data: uint32);
begin
  logWriteLn(Format('ROM[%8.8x]=%2.2x at %8.8x', [address, data, regs[R15]]));
end;

procedure WriteROMBaby16(address, data: uint32);
begin
  logWriteLn(Format('ROM[%8.8x]=%4.4x at %8.8x', [address, data, regs[R15]]));
end;

procedure WriteROMBaby32(address, data: uint32);
begin
//  if cartMask1 > 0 then Puint32(@(cartROM1^[address and cartMask1]))^ := data;
  logWriteLn(Format('ROM[%8.8x]=%8.8x at %8.8x', [address, data, regs[R15]]));
end;

//////////////////////////////////////////////////////////////////////

function ReadBIOS_08(address: uint32): uint32;
begin
  Dec(quota);
  if regs[R15] < $02000000 then
    Result := systemROM[address and SYSTEM_ROM_MASK]
  else
    Result := 0;
end;

//////////////////////////////////////////////////////////////////////

function ReadBIOS_16(address: uint32): uint32;
begin
  Dec(quota);
  if regs[R15] < $02000000 then
    Result := Puint16(@(systemROM[address and SYSTEM_ROM_MASK]))^
  else
    Result := 0;
end;

//////////////////////////////////////////////////////////////////////

function ReadBIOS_32(address: uint32): uint32;
begin
  Dec(quota);
  if regs[R15] < $02000000 then
    Result := Puint32(@(systemROM[address and SYSTEM_ROM_MASK]))^
  else
    Result := 0;
end;

//////////////////////////////////////////////////////////////////////

function ReadExWRAM_08(address: uint32): uint32;
begin
  Dec(quota, 3);
  Result := exWRAM[address and EX_WRAM_MASK];
end;

//////////////////////////////////////////////////////////////////////

function ReadExWRAM_16(address: uint32): uint32;
begin
  Dec(quota, 3);
  Result := Puint16(@(exWRAM[address and EX_WRAM_MASK]))^;
end;

//////////////////////////////////////////////////////////////////////

function ReadExWRAM_32(address: uint32): uint32;
begin

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -