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

📄 cpumemory.pas

📁 一个不出名的GBA模拟器
💻 PAS
📖 第 1 页 / 共 5 页
字号:
            end;
          else
            logWriteLn(format('Invalid flash command: [%.4x] = %.2x',[address and $FFFF, data]));
            flashMode := fmIdle;
          end;

        flashIndex := 0;
      end;
    end;
end;

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

function memReadByte(address: uint32): uint32;
begin
  curBank := (address shr 24) and $F;
  Result := ReadByteFuncs[curBank](address);
  lastAddress := address;
end;

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

function memReadHalfword(address: uint32): uint32;
begin
  address := address and not 1;
  curBank := (address shr 24) and $F;
  Result := ReadHalfFuncs[curBank](address);
  lastAddress := address;
end;

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

function memReadWord(address: uint32): uint32;
var
  s: byte;
begin
  curBank := (address shr 24) and $F;
  Result := ReadWordFuncs[curBank](address and not 3);

  lastAddress := address;
  s := (lastAddress and 3) shl 3;
  Result := (Result shr s) or (Result shl (32-s));
end;

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

function memLoadWord(address: uint32): uint32;
var
  s: byte;
begin
  curBank := (address shr 24) and $F;
  Result := ReadWordFuncs[curBank](address and not 3);

  lastAddress := address;
  s := (lastAddress and 3) shl 3;
  Result := (Result shr s) or (Result shl (32-s));
end;

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

function memReadHalfwordUnc(address: uint32): uint32;
begin
  curBank := (address shr 24) and $F;
  Result := ReadHalfFuncs[curBank](address);
  lastAddress := address;
end;

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

function memReadWordUnc(address: uint32): uint32;
begin
  curBank := (address shr 24) and $F;
  Result := ReadWordFuncs[curBank](address);
  lastAddress := address;
end;

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

procedure memWriteByte(address: uint32; data: uint32);
begin
  curBank := (address shr 24) and $F;
  WriteByteFuncs[curBank](address, data);
  lastAddress := address;
end;

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

procedure memWriteHalfword(address: uint32; data: uint32);
begin
  address := address and not 1;
  curBank := (address shr 24) and $F;
  WriteHalfFuncs[curBank](address, data);
  lastAddress := address;
end;

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

procedure memWriteWord(address: uint32; data: uint32);
begin
  address := address and not 3; // fixme: this might need to go!
  curBank := (address shr 24) and $F;
  WriteWordFuncs[curBank](address, data);
  lastAddress := address;
end;

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

procedure memWriteHalfwordUnc(address: uint32; data: uint32);
begin
  curBank := (address shr 24) and $F;
  WriteHalfFuncs[curBank](address, data);
  lastAddress := address;
end;

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

procedure memWriteWordUnc(address: uint32; data: uint32);
begin
  curBank := (address shr 24) and $F;
  WriteWordFuncs[curBank](address, data);
  lastAddress := address;
end;

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

function vmReadByte(address: uint32): byte;
var
  la, lc, cpc: uint32;
begin
  cpc := regs[R15];
  regs[R15] := 0;
  lc := quota;
  la := lastAddress;
  Result := memReadByte(address);
  regs[R15] := cpc;
  lastAddress := la;
  quota := lc;
end;

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

function vmReadHalfWord(address: uint32): uint16;
var
  la, lc, cpc: uint32;
begin
  cpc := regs[R15];
  regs[R15] := 0;
  lc := quota;
  la := lastAddress;
  Result := memReadHalfword(address);
  regs[R15] := cpc;
  lastAddress := la;
  quota := lc;
end;

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

function vmReadWord(address: uint32): uint32;
var
  la, lc, cpc: uint32;
begin
  cpc := regs[R15];
  regs[R15] := 0;
  lc := quota;
  la := lastAddress;
  Result := memReadWord(address);
  regs[R15] := cpc;
  lastAddress := la;
  quota := lc;
end;

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

procedure vmWriteByte(address: uint32; data: uint8);
var
  la, lc, cpc: uint32;
begin
  cpc := regs[R15];
  regs[R15] := 0;
  lc := quota;
  la := lastAddress;

  memWriteByte(address, data);

  regs[R15] := cpc;
  lastAddress := la;
  quota := lc;
end;

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

procedure vmWriteHalfword(address: uint32; data: uint16);
var
  la, lc, cpc: uint32;
begin
  cpc := regs[R15];
  regs[R15] := 0;
  lc := quota;
  la := lastAddress;

  memWriteHalfword(address, data);

  regs[R15] := cpc;
  lastAddress := la;
  quota := lc;
end;

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

procedure vmWriteWord(address: uint32; data: uint32);
var
  la, lc, cpc: uint32;
begin
  cpc := regs[R15];
  regs[R15] := 0;
  lc := quota;
  la := lastAddress;

  memWriteWord(address, data);

  regs[R15] := cpc;
  lastAddress := la;
  quota := lc;
end;

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

procedure SetWaitStates;
var
  romMode: byte;
  sramMode: byte;
  wait: uint16;
  i: integer;
begin
  wait := Puint16(@(registers[WAIT_STATE_CR]))^;

  // Set ROM bank times
  romMode := (wait shr 2) and $7;
  bankNTimes[$8] := romWait[romMode, 0];  bankSTimes[$8] := romWait[romMode, 1];
  bankNTimes[$9] := romWait[romMode, 0];  bankSTimes[$9] := romWait[romMode, 1];

  // Set mirror bank 2 times
  romMode := (wait shr 5) and $7;
  bankNTimes[$A] := romWait[romMode, 0];  bankSTimes[$A] := romWait[romMode, 2];
  bankNTimes[$B] := romWait[romMode, 0];  bankSTimes[$B] := romWait[romMode, 2];

  // Set mirror bank 3 times
  romMode := (wait shr 8) and $7;
  bankNTimes[$C] := romWait[romMode, 0];  bankSTimes[$C] := romWait[romMode, 3];
  bankNTimes[$D] := romWait[romMode, 0];  bankSTimes[$D] := romWait[romMode, 3];

  // Set SRAM times
  sramMode := wait and $3;
  bankNTimes[$E] := sramWait[sramMode];   bankSTimes[$E] := sramWait[sramMode];
  bankNTimes[$F] := sramWait[sramMode];   bankSTimes[$F] := sramWait[sramMode];

  for i := 0 to 15 do begin
    Inc(bankNTimes[i]);
    Inc(bankSTimes[i]);
  end;
end;

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

procedure ResetBank1;
begin
  // Set the sizes to 0
  cartSize1 := 0;
  cartMask1 := 0;

  // Set the bank 1 memory functions to NOP
  ReadByteFuncs[$8] := ReadNOP;  WriteByteFuncs[$8] := WriteNOP;
  ReadByteFuncs[$A] := ReadNOP;  WriteByteFuncs[$A] := WriteNOP;
  ReadByteFuncs[$C] := ReadNOP;  WriteByteFuncs[$C] := WriteNOP;
  ReadHalfFuncs[$8] := ReadNOP;  WriteHalfFuncs[$8] := WriteNOP;
  ReadHalfFuncs[$A] := ReadNOP;  WriteHalfFuncs[$A] := WriteNOP;
  ReadHalfFuncs[$C] := ReadNOP;  WriteHalfFuncs[$C] := WriteNOP;
  ReadWordFuncs[$8] := ReadNOP;  WriteWordFuncs[$8] := WriteNOP;
  ReadWordFuncs[$A] := ReadNOP;  WriteWordFuncs[$A] := WriteNOP;
  ReadWordFuncs[$C] := ReadNOP;  WriteWordFuncs[$C] := WriteNOP;
  memBanks[$8] := nil;
  memBanks[$A] := nil;
  memBanks[$C] := nil;

  // Set the bank 1 breakpoints to null
  breakpoints.cartSize1 := 0;
  interestingAddresses.cartSize1 := 0;
  sourcePoints.cartSize1 := 0;
end;

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

procedure ResetBank2;
begin
  // Set the sizes to 0
  cartSize2 := 0;
  cartMask2 := 0;

  // Set the bank 2 memory functions to NOP
  eepromIndex := 0;
  eepromByte := 0;
  eepromMode := emIdle;
  flashIndex := 0;
  flashMode := fmIdle;

  // If there is no ROM loaded, treat this space as an EEPROM
  ReadByteFuncs[$9] := ReadEEPROM_08;  WriteByteFuncs[$9] := WriteEEPROM_08;
  ReadByteFuncs[$B] := ReadEEPROM_08;  WriteByteFuncs[$B] := WriteEEPROM_08;
  ReadByteFuncs[$D] := ReadEEPROM_08;  WriteByteFuncs[$D] := WriteEEPROM_08;
  ReadHalfFuncs[$9] := ReadEEPROM_16;  WriteHalfFuncs[$9] := WriteEEPROM_16;
  ReadHalfFuncs[$B] := ReadEEPROM_16;  WriteHalfFuncs[$B] := WriteEEPROM_16;
  ReadHalfFuncs[$D] := ReadEEPROM_16;  WriteHalfFuncs[$D] := WriteEEPROM_16;
  ReadWordFuncs[$9] := ReadEEPROM_32;  WriteWordFuncs[$9] := WriteEEPROM_32;
  ReadWordFuncs[$B] := ReadEEPROM_32;  WriteWordFuncs[$B] := WriteEEPROM_32;
  ReadWordFuncs[$D] := ReadEEPROM_32;  WriteWordFuncs[$D] := WriteEEPROM_32;
  memBanks[$9] := nil;
  memBanks[$B] := nil;
  memBanks[$D] := nil;

  // Set the bank 2 breakpoints to null
  breakpoints.cartSize2 := 0;
  interestingAddresses.cartSize2 := 0;
  sourcePoints.cartSize2 := 0;
end;

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

procedure vmRemoveCartridge;
begin
  if not cartLoaded then Exit;

  if cartSize1 > 0 then begin
    FreeMem(cartROM1, cartSize1+cartSize2);
    ResetBank1;
  end;
  if cartSize2 > 0 then ResetBank2;

  //currentHeader := nil;
  cartLoaded := false;
end;

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

function RoundUpToPow2(num: uint32): uint32;
begin
  Result := 1;
  while Result < num do Result := Result shl 1;
end;

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

procedure vmInsertCartridge(data: pointer; size: integer);
begin
  // Remove the old cart
  vmRemoveCartridge;

  // Figure out how much to read, and how much to allocate for the ROM
  cartSize1 := Min(RoundUpToPow2(size), 1 shl 25);
  GetMem(cartROM1, cartSize1);
  Move(data^, cartROM1^, size);

  if cartSize1 > 1 shl 24 then begin
    cartSize2 := cartSize1 - 1 shl 24;
    cartSize1 := 1 shl 24;

    cartROM2 := pointer(integer(cartROM1) + 1 shl 24);
    cartMask2 := cartSize2 - 1;
  end;

  if cartSize1 > 0 then begin
    cartMask1 := cartSize1 - 1;

    ReadByteFuncs[$8] := ReadROM1_08;  WriteByteFuncs[$8] := WriteROMBaby8;
    ReadByteFuncs[$A] := ReadROM1_08;  WriteByteFuncs[$A] := WriteROMBaby8;
    ReadByteFuncs[$C] := ReadROM1_08;  WriteByteFuncs[$C] := WriteROMBaby8;
    ReadHalfFuncs[$8] := ReadROM1_16;  WriteHalfFuncs[$8] := WriteROMBaby16;
    ReadHalfFuncs[$A] := ReadROM1_16;  WriteHalfFuncs[$A] := WriteROMBaby16;
    ReadHalfFuncs[$C] := ReadROM1_16;  WriteHalfFuncs[$C] := WriteROMBaby16;
    ReadWordFuncs[$8] := ReadROM1_32;  WriteWordFuncs[$8] := WriteROMBaby32;
    ReadWordFuncs[$A] := ReadROM1_32;  WriteWordFuncs[$A] := WriteROMBaby32;
    ReadWordFuncs[$C] := ReadROM1_32;  WriteWordFuncs[$C] := WriteROMBaby32;

    memBanks[$8] := cartROM1;          memMasks[$8] := cartMask1;
    memBanks[$A] := cartROM1;          memMasks[$A] := cartMask1;
    memBanks[$C] := cartROM1;          memMasks[$C] := cartMask1;

    // Set up the bank 1 breakpoints
    breakpoints.cartSize1 := Max(cartSize1 shr 4, 1);
    interestingAddresses.cartSize1 := breakpoints.cartSize1;
    sourcePoints.cartSize1 := breakpoints.cartSize1;
  end else
    ResetBank1;

  if cartSize2 > 0 then begin
    cartMask2 := cartSize2 - 1;

    ReadByteFuncs[$9] := ReadROM2_08;  WriteByteFuncs[$9] := WriteROMBaby8;
    ReadByteFuncs[$B] := ReadROM2_08;  WriteByteFuncs[$B] := WriteROMBaby8;
    ReadByteFuncs[$D] := Rea

⌨️ 快捷键说明

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