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

📄 cpumemory.pas

📁 一个不出名的GBA模拟器
💻 PAS
📖 第 1 页 / 共 5 页
字号:
  Result := Puint32(@(Palette[address and PALETTE_MASK]))^;
end;

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

procedure WritePal_08(address, data: uint32);
begin
  Dec(quota);
  address := address and (PALETTE_MASK and not 1);
  Puint16(@(Palette[address]))^ := data + data shl 8;
end;

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

procedure WritePal_16(address, data: uint32);
begin
  Dec(quota);
  Puint16(@(Palette[address and PALETTE_MASK]))^ := data;
end;

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

procedure WritePal_32(address, data: uint32);
begin
  Dec(quota, 2);
  Puint32(@(Palette[address and PALETTE_MASK]))^ := data;
end;

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

function ReadVRAM_08(address: uint32): uint32;
begin
  Dec(quota);
  Result := VRAM[address and VRAM_MASK];
end;

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

function ReadVRAM_16(address: uint32): uint32;
begin
  Dec(quota);
  Result := Puint16(@(VRAM[address and VRAM_MASK]))^;
end;

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

function ReadVRAM_32(address: uint32): uint32;
begin
  Dec(quota, 2);
  Result := Puint32(@(VRAM[address and VRAM_MASK]))^;
end;

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

procedure WriteVRAM_08(address, data: uint32);
begin
  Dec(quota);
  address := address and (VRAM_MASK and not 1);
  Puint16(@(VRAM[address]))^ := data + data shl 8;
end;

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

procedure WriteVRAM_16(address, data: uint32);
begin
  Dec(quota);
  Puint16(@(VRAM[address and VRAM_MASK]))^ := data;
end;

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

procedure WriteVRAM_32(address, data: uint32);
begin
  Dec(quota, 2);
  Puint32(@(VRAM[address and VRAM_MASK]))^ := data;
end;

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

function ReadOAM_08(address: uint32): uint32;
begin
  Dec(quota);
  Result := OAM[address and OAM_MASK];
end;

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

function ReadOAM_16(address: uint32): uint32;
begin
  Dec(quota);
  Result := Puint16(@(OAM[address and OAM_MASK]))^;
end;

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

function ReadOAM_32(address: uint32): uint32;
begin
  Dec(quota, 2);
  Result := Puint32(@(OAM[address and OAM_MASK]))^;
end;

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

procedure WriteOAM_08(address, data: uint32);
begin
  Dec(quota);
  address := address and (OAM_MASK and not 1);
  Puint16(@(OAM[address]))^ := data + data shl 8;
end;

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

procedure WriteOAM_16(address, data: uint32);
begin
  Dec(quota);
  Puint16(@(OAM[address and OAM_MASK]))^ := data;
end;

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

procedure WriteOAM_32(address, data: uint32);
begin
  Dec(quota, 2);
  Puint32(@(OAM[address and OAM_MASK]))^ := data;
end;

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

function ReadROM1_08(address: uint32): uint32;
begin
  if address-lastAddress <= 4 then Dec(quota, bankSTimes[curBank]) else Dec(quota, bankNTimes[curBank]);
  Result := cartROM1^[address and cartMask1];

{ part of the e-Reader testing:
  if address >= $08700000 then
    logWriteLn(Format('%2.2x in ROM[%8.8x], at %8.8x', [Result, address, regs[R15]]));}
end;

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

function ReadROM1_16(address: uint32): uint32;
begin
  if address-lastAddress <= 4 then Dec(quota, bankSTimes[curBank]) else Dec(quota, bankNTimes[curBank]);
  Result := Puint16(@(cartROM1^[address and cartMask1]))^;

{ part of the e-Reader testing:
  if address >= $08700000 then
    logWriteLn(Format('%4.4x in ROM[%8.8x], at %8.8x', [Result, address, regs[R15]]));}
end;

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

function ReadROM1_32(address: uint32): uint32;
begin
  if address-lastAddress <= 4 then
    Dec(quota, bankSTimes[curBank]*2 + 1)
  else
    Dec(quota, bankNTimes[curBank] + bankSTimes[curBank] + 1);
  Result := Puint32(@(cartROM1^[address and cartMask1]))^;

{ part of the e-Reader testing:
  if address >= $08700000 then
    logWriteLn(Format('%8.8x in ROM[%8.8x], at %8.8x', [Result, address, regs[R15]]));}
end;

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

function ReadROM2_08(address: uint32): uint32;
begin
  if address-lastAddress <= 4 then Dec(quota, bankSTimes[curBank]) else Dec(quota, bankNTimes[curBank]);
  Result := cartROM2^[address and cartMask2];
end;

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

function ReadROM2_16(address: uint32): uint32;
begin
  if address-lastAddress <= 4 then Dec(quota, bankSTimes[curBank]) else Dec(quota, bankNTimes[curBank]);
  Result := Puint16(@(cartROM2^[address and cartMask2]))^;
end;

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

function ReadROM2_32(address: uint32): uint32;
begin
  if address-lastAddress <= 4 then
    Dec(quota, bankSTimes[curBank]*2 + 1)
  else
    Dec(quota, bankNTimes[curBank] + bankSTimes[curBank] + 1);
  Result := Puint32(@(cartROM2^[address and cartMask2]))^;
end;

//////////////////////////////////////////////////////////////////////
// Thanks to Forgotten for his help with EEPROM support //////////////
//////////////////////////////////////////////////////////////////////

function ReadEEPROM_08(address: uint32): uint32;
begin
  if address-lastAddress <= 4 then Dec(quota, bankSTimes[curBank]) else Dec(quota, bankNTimes[curBank]);

  Result := 0;
  case eepromMode of
    emIdle, emReadAddress, emWriteData: Result := 1;
    emReadData: begin
      Inc(eepromIndex);
      if eepromIndex = 4 then begin
        eepromMode := emReadData2;
        eepromIndex := 0;
        eepromByte := 0;
      end;
    end;
    emReadData2: begin
      Result := (cartRAM[eepromAddress shl 3 + eepromByte] shr (7 - eepromIndex and 7)) and 1;
      Inc(eepromIndex);
      if eepromIndex and 7 = 0 then Inc(eepromByte);
      if eepromIndex = 64 then eepromMode := emIdle;
    end;
  end;
end;

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

function ReadEEPROM_16(address: uint32): uint32;
begin
  Result := ReadEEPROM_08(address);
end;

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

function ReadEEPROM_32(address: uint32): uint32;
begin
  Result := ReadEEPROM_08(address);
  Dec(quota, bankSTimes[curBank] + 1);
end;

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

procedure WriteEEPROM_08(address, data: uint32);
var
  i: uint32;
begin
  if address-lastAddress <= 4 then Dec(quota, bankSTimes[curBank]) else Dec(quota, bankNTimes[curBank]);
  cartRAMdirty := true;

  data := data and 1;
  case eepromMode of
    emIdle: begin
      eepromIndex := 1;
      eepromByte := 0;
      eepromBuffer[0] := data;
      eepromMode := emReadAddress;
    end;
    emReadAddress: begin
      eepromBuffer[eepromByte] := eepromBuffer[eepromByte] shl 1;
      eepromBuffer[eepromByte] := eepromBuffer[eepromByte] or data;
      Inc(eepromIndex);
      if eepromIndex and 7 = 0 then Inc(eepromByte);
      if eepromIndex = 9 then begin
        eepromAddress := eepromBuffer[0] and $3F;
        if eepromBuffer[0] and $40 = 0 then
          eepromMode := emWriteData
        else begin
          eepromMode := emReadData;
          eepromByte := 0;
          eepromIndex := 0;
        end;
      end;
    end;
    emReadData, emReadData2: begin
      eepromMode := emIdle;
    end;
    emWriteData: begin
      eepromBuffer[eepromByte] := eepromBuffer[eepromByte] shl 1;
      eepromBuffer[eepromByte] := eepromBuffer[eepromByte] or data;
      Inc(eepromIndex);
      if eepromIndex and 7 = 0 then Inc(eepromByte);
      if eepromIndex = $49 then begin
        // Write data
        for i := 0 to 7 do
          cartRAM[(eepromAddress shl 3 + i) and EEPROM_MASK] := eepromBuffer[1+i];
        eepromMode := emIdle;
      end;
    end;
  end;
end;

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

procedure WriteEEPROM_16(address, data: uint32);
begin
  WriteEEPROM_08(address, data);
end;

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

procedure WriteEEPROM_32(address, data: uint32);
begin
  WriteEEPROM_08(address, data);
  Dec(quota, bankSTimes[curBank] + 1);
end;

//////////////////////////////////////////////////////////////////////
{
SRAM support is currently disabled

function ReadSRAM_08(address: uint32): uint32;
begin
  logwriteln(format('SRAM read of %.4x',[address and $FFFF]));
  if address-lastAddress <= 4 then Dec(quota, bankSTimes[curBank]) else Dec(quota, bankNTimes[curBank]);
  Result := cartRAM[address and SRAM_MASK];
end;

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

procedure WriteSRAM_08(address, data: uint32);
begin
  logwriteln(format('SRAM write: [%.4x] = %.2x',[address and $FFFF, data]));
  if address-lastAddress <= 4 then Dec(quota, bankSTimes[curBank]) else Dec(quota, bankNTimes[curBank]);
  cartRAM[address and SRAM_MASK] := data;
  cartRAMdirty := true;
end;
}
//////////////////////////////////////////////////////////////////////


var
  bankId: longword = 0;

function ReadFlash_08(address: uint32): uint32;
begin
  if address-lastAddress <= 4 then Dec(quota, bankSTimes[curBank]) else Dec(quota, bankNTimes[curBank]);

  if flashMode = fmProductID then begin
//    if address and 1 <> 0 then Result := $BC else Result := $1F;
    if address and 1 <> 0 then Result := $09 else Result := $C2;
  end else
    Result := cartRAM[bankId + address and SRAM_MASK];

  if address and $FFF < 5 then
  logwriteln(format('FLASH read of %.4x (%.2x), i/m/b=%d/%d/%d, from %.8x', [address and $FFFF, Result, flashIndex, Ord(flashMode), bankId shr 16, regs[R15]]));
end;

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

const
  MX_FLASH_READ_ID = $90;
  MX_FLASH_PROGRAM = $A0;

  MX_FLASH_RESET = $F0;
  MX_FLASH_SECTOR_ERASE_SUSPEND = $B0;  // Not needed, since sector erase is currently instentanious
// MX_FLASH_SECTOR_ERASE_RESUME = $30;  double strikeout, not needed as above, and same as erase command
  MX_FLASH_EXTENDED = $80;

  // Requires a MX_FLASH_EXTENDED first
  MX_FLASH_CHIP_ERASE = $10;
  MX_FLASH_SECTOR_ERASE = $30;
//  MX_FLASH_SECTOR_UNLOCK = $20;  not needed, since there are no lockable sectors

procedure WriteFlash_08(address, data: uint32);
begin
  cartRAMdirty := true;
  logwriteln(format('FLASH write: [%.4x] = %.2x, at %.8x', [address and $FFFF, data, regs[R15]]));

  if address-lastAddress <= 4 then Dec(quota, bankSTimes[curBank]) else Dec(quota, bankNTimes[curBank]);

  data := data and $FF;
  if flashMode = fmWriteData then begin
    cartRAM[bankID + address and SRAM_MASK] := {cartRAM[bankID + address and SRAM_MASK] and }data;
//    cartRAM[address and SRAM_MASK] := data;
    flashMode := fmIdle;
    flashIndex := 0;
  end else if flashMode = fmBankswitch then begin
    flashMode := fmIdle;
    flashIndex := 0;
    bankID := (data and 1) shl 16;
    logwriteln(format('Bankswitch: [%.4x] = %.2x, at %.8x', [address and $FFFF, data, regs[R15]]));
  end else if data = MX_FLASH_RESET then begin
    flashMode := fmIdle;
    flashIndex := 0;
  end else
    case flashIndex of
      0: if (address and $FFFF = $5555) and (data and $FF = $AA) then Inc(flashIndex);
      1: if (address and $FFFF = $2AAA) and (data and $FF = $55) then Inc(flashIndex);
      2: begin
        if (data = MX_FLASH_SECTOR_ERASE) and (flashMode = fmExtended) then begin
          // Do a sector erase
          FillChar(cartRAM[bankID + (address and (2*SRAM_MASK+1)) and not $3FFF], $4000, $FF);
//          FillChar(cartRAM[(address and SRAM_MASK) and not $1F], 32, $00);
          flashMode := fmIdle;
        end;

        if (address and $FFFF = $5555) then
          case data of
            MX_FLASH_EXTENDED: flashMode := fmExtended;
            MX_FLASH_READ_ID:  flashMode := fmProductID;
            MX_FLASH_PROGRAM:  flashMode := fmWriteData;
            MX_FLASH_SECTOR_ERASE: ; // done above
            MX_FLASH_SECTOR_ERASE_SUSPEND: flashMode := fmBankswitch;
            MX_FLASH_CHIP_ERASE: if flashMode = fmExtended then begin
              // Erase the whole chip
              FillChar(cartRAM, 2*SRAM_MASK+2, $FF);
//              FillChar(cartRAM, SRAM_MASK+1, $FF);
              flashMode := fmIdle;

⌨️ 快捷键说明

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