📄 cpumemory.pas
字号:
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 + -