📄 main.pas
字号:
unit main;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Menus, DXDraws, ExtCtrls, DXInput,IniFiles;
type
TmainWin = class(TForm)
MainMenu1: TMainMenu;
File1: TMenuItem;
Load1: TMenuItem;
DXDraw: TDXDraw;
OpenDialog1: TOpenDialog;
dxi1: TDXInput;
dxi2: TDXInput;
Debug1: TMenuItem;
SaveNametable1: TMenuItem;
SavePalette1: TMenuItem;
SaveSprRam1: TMenuItem;
SavePatterntable1: TMenuItem;
NameTable01: TMenuItem;
NameTable11: TMenuItem;
NameTable21: TMenuItem;
NameTable31: TMenuItem;
Setup1: TMenuItem;
Input1: TMenuItem;
N1: TMenuItem;
RomItem1: TMenuItem;
RomItem2: TMenuItem;
RomItem3: TMenuItem;
RomItem4: TMenuItem;
N2: TMenuItem;
Exit1: TMenuItem;
Help1: TMenuItem;
About1: TMenuItem;
NameTableView1: TMenuItem;
procedure Load1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure SavePalette1Click(Sender: TObject);
procedure SaveSprRam1Click(Sender: TObject);
procedure SavePatterntable1Click(Sender: TObject);
procedure btn1Click(Sender: TObject);
procedure NameTable01Click(Sender: TObject);
procedure NameTable11Click(Sender: TObject);
procedure NameTable21Click(Sender: TObject);
procedure NameTable31Click(Sender: TObject);
procedure Exit1Click(Sender: TObject);
procedure File1Click(Sender: TObject);
procedure RomItem1Click(Sender: TObject);
procedure Input1Click(Sender: TObject);
procedure About1Click(Sender: TObject);
procedure FormActivate(Sender: TObject);
procedure FormDeactivate(Sender: TObject);
procedure NameTableView1Click(Sender: TObject);
private
{ Private declarations }
procedure interrupt(cc: Integer; scanline: integer);
procedure SaveStatus(cc: integer; sl: integer);
public
{ Public declarations }
pause: boolean;
VBlank: Boolean;
procedure RunNes(romname: string);
function RAssignKey(var KeyAssignList: TKeyAssignList; State: TDXInputState):integer;
procedure WAssignKey(var KeyAssignList: TKeyAssignList; State: TDXInputState;const Keys: Integer);
end;
var
mainWin: TmainWin;
implementation
uses cpu, cart, nesppu, dbwin, input,inputset,sound,about,NTView;
var
cpu: TCPU;
cart: TCart;
ppu: TPPU;
padle: TInput;
snd:TSound;
dbw: TDebugWin;
running: boolean;
increment: integer;
FirstRead:Boolean;
VRamBuff:byte;
VRAddr:WORD;
TempAddr:Word;
RomListNum:integer;
iniconf:TIniFile;
RomList:TStringList;
joy1:array [0..7] of Integer;
WinActive:Boolean;
FrameTimes:Integer;
{$R *.dfm}
procedure tmainWin.WAssignKey(var KeyAssignList: TKeyAssignList; State: TDXInputState;
const Keys: Integer);
var
KeyAssign: PKeyAssign;
begin
KeyAssign := @KeyAssignList[State];
FillChar(KeyAssign^, SizeOf(TKeyAssign), 0);
KeyAssign^[0] := Keys;
end;
function tmainWin.RAssignKey(var KeyAssignList: TKeyAssignList; State: TDXInputState):integer;
var
KeyAssign: PKeyAssign;
begin
KeyAssign := @KeyAssignList[State];
result:=KeyAssign^[0] ;
end;
procedure Readconfig;
var
keys:integer;
begin
RomList.Strings[0]:=iniconf.ReadString('RomList','RomItem1','');
RomList.Strings[1]:=iniconf.ReadString('RomList','RomItem2','');
RomList.Strings[2]:=iniconf.ReadString('RomList','RomItem3','');
RomList.Strings[3]:=iniconf.ReadString('RomList','RomItem4','');
keys:=iniconf.ReadInteger('Joy1','Up',38);
mainWin.WAssignKey(mainWin.dxi1.keyboard.keyAssigns,isUp,keys);
keys:=iniconf.ReadInteger('Joy1','Down',40);
mainWin.WAssignKey(mainWin.dxi1.keyboard.keyAssigns,isDown,keys);
keys:=iniconf.ReadInteger('Joy1','Left',37);
mainWin.WAssignKey(mainWin.dxi1.keyboard.keyAssigns,isLeft,keys);
keys:=iniconf.ReadInteger('Joy1','Right',39);
mainWin.WAssignKey(mainWin.dxi1.keyboard.keyAssigns,isRight,keys);
keys:=iniconf.ReadInteger('Joy1','A',65);
mainWin.WAssignKey(mainWin.dxi1.keyboard.keyAssigns,isButton1,keys);
keys:=iniconf.ReadInteger('Joy1','B',83);
mainWin.WAssignKey(mainWin.dxi1.keyboard.keyAssigns,isButton2,keys);
keys:=iniconf.ReadInteger('Joy1','Select',81);
mainWin.WAssignKey(mainWin.dxi1.keyboard.keyAssigns,isButton3,keys);
keys:=iniconf.ReadInteger('Joy1','Start',87);
mainWin.WAssignKey(mainWin.dxi1.keyboard.keyAssigns,isButton4,keys);
end;
procedure WriteConfig;
begin
iniconf.WriteString('RomList','RomItem1',Romlist.Strings[0]);
iniconf.WriteString('RomList','RomItem2',Romlist.Strings[1]);
iniconf.WriteString('RomList','RomItem3',Romlist.Strings[2]);
iniconf.WriteString('RomList','RomItem4',Romlist.Strings[3]);
iniconf.WriteInteger('Joy1','Up',mainWin.RAssignKey(mainWin.dxi1.keyboard.keyAssigns,isUp));
iniconf.WriteInteger('Joy1','Down',mainWin.RAssignKey(mainWin.dxi1.keyboard.keyAssigns,isDown));
iniconf.WriteInteger('Joy1','Left',mainWin.RAssignKey(mainWin.dxi1.keyboard.keyAssigns,isLeft));
iniconf.WriteInteger('Joy1','Right',mainWin.RAssignKey(mainWin.dxi1.keyboard.keyAssigns,isRight));
iniconf.WriteInteger('Joy1','A',mainWin.RAssignKey(mainWin.dxi1.keyboard.keyAssigns,isButton1));
iniconf.WriteInteger('Joy1','B',mainWin.RAssignKey(mainWin.dxi1.keyboard.keyAssigns,isButton2));
iniconf.WriteInteger('Joy1','Select',mainWin.RAssignKey(mainWin.dxi1.keyboard.keyAssigns,isButton3));
iniconf.WriteInteger('Joy1','Start',mainWin.RAssignKey(mainWin.dxi1.keyboard.keyAssigns,isButton4));
end;
procedure tmainWin.interrupt(cc: Integer; scanline: integer);
begin
pause := True;
if dbw.bp then
begin
if cpu.pc <> dbw.breakpoint then
begin
pause := false;
end
else SaveStatus(cc, scanline);
end;
while pause do
begin
Application.ProcessMessages;
end;
if not dbw.bp then SaveStatus(cc, scanline);
end;
procedure tmainWin.SaveStatus(cc: Integer; sl: integer);
begin
dbw.lst_insList.Items.Add(' ' + cpu.curIns);
dbw.ve_status.Values['ClockCycle'] := IntToStr(cc);
dbw.ve_status.Values['X'] := IntToHex(cpu.x, 0);
dbw.ve_status.Values['Y'] := IntToHex(cpu.y, 0);
dbw.ve_status.Values['A'] := IntToHex(cpu.a, 0);
dbw.ve_status.Values['SP'] := IntToHex(cpu.sp, 0);
dbw.ve_status.Values['PC'] := IntToHex(cpu.pc, 0);
dbw.ve_status.Values['ScanLines'] := IntTostr(SL);
dbw.ve_status.Values['2000'] := IntToHex(ppu.registers[0], 0);
dbw.ve_status.Values['2001'] := IntToHex(ppu.registers[1], 0);
dbw.ve_status.Values['2002'] := IntToHex(ppu.registers[2], 0);
dbw.ve_status.Values['2003'] := IntToHex(ppu.registers[3], 0);
dbw.ve_status.Values['2004'] := IntToHex(ppu.registers[4], 0);
dbw.ve_status.Values['2005'] := IntToHex(ppu.registers[5], 0);
dbw.ve_status.Values['2006'] := IntToHex(ppu.registers[6], 0);
dbw.ve_status.Values['2007'] := IntToHex(ppu.registers[7], 0);
end;
procedure Mem_Write(addr: word; data: byte);
var
d2: byte;
// sprAddr:Integer;
rno:Word;
tem:Word;
begin
case addr of
0..$7ff : cpu.CPU_Mem[addr] := data;
$800..$1fff : cpu.CPU_Mem[addr and $7ff] := data;
$2000..$2007: begin
rno := addr and 7;
case rno of
0:begin
ppu.registers[rno] := data;
VRAddr:= VRAddr and $f3ff;
VRAddr:=VRAddr or ((data and 3) shl 10);
end;
1,3: ppu.registers[rno] := data;
2: ppu.registers[rno]:=data;
4: begin
ppu.sprRam[ppu.registers[3]] := data;
Inc(ppu.registers[3]);
end;
5: begin
tem:=VRAddr;
if cpu.toggle then
begin
tem:=tem and $8c1f;
tem:=tem or ((data and $f8) shl 2);
tem:=tem or ((data and 7) shl 12);
ppu.y_scroll := data;
cpu.toggle := false;
end
else
begin
tem:=tem and $ffe0;
tem:=tem or (data shr 3);
ppu.x_scroll := data;
cpu.toggle := true;
end;
VRAddr:=tem;
end;
6: begin
if cpu.toggle then
begin
Vraddr:=VRAddr and $ff00;
VRAddr:=VRAddr or data;
ppu.VRamAddr := VRAddr;
cpu.toggle := false;
FirstRead:=true;
end else begin
VRAddr := VRAddr and $ff;
VRAddr := VRAddr or ((data and $3f) shl 8);
cpu.toggle := true;
end;
end;
7: begin
if (ppu.registers[2] and $10)=$0 then begin
if (ppu.VRamAddr>=$3000) and (ppu.VRamAddr<$3f00) then
ppu.VRamAddr:=ppu.Vramaddr-$1000;
if (ppu.VRamAddr>=$3f20) then
ppu.VRamAddr:=ppu.VRamAddr and $3f1f;
ppu.ppu_mem[ppu.VRamAddr] := data;
if (ppu.VRamAddr>=$2000) and (ppu.VRamAddr<$2400) then
ppu.ppu_mem[ppu.nametable[0] + ppu.VRamAddr - $2000]:=data
else if (ppu.VRamAddr>=$2400) and (ppu.VRamAddr<$2800) then
ppu.ppu_mem[ppu.nametable[1] + ppu.VRamAddr - $2400]:=data
else if (ppu.VRamAddr>=$2800) and (ppu.VRamAddr<$2c00) then
ppu.ppu_mem[ppu.nametable[2] + ppu.VRamAddr - $2800]:=data
else if (ppu.VRamAddr>=$2c00) and (ppu.VRamAddr<$3000) then
ppu.ppu_mem[ppu.nametable[3] + ppu.VRamAddr - $2c00]:=data;
if (ppu.VRamAddr = $3F10) or (ppu.VRamAddr=$3f00) then
begin
ppu.ppu_mem[$3F00] := data;
ppu.ppu_mem[$3F04] := data;
ppu.ppu_mem[$3F08] := data;
ppu.ppu_mem[$3F0C] := data;
ppu.ppu_mem[$3F10] := data;
ppu.ppu_mem[$3F14] := data;
ppu.ppu_mem[$3F18] := data;
ppu.ppu_mem[$3F1C] := data;
end;
d2 := (ppu.registers[0] shr 2) and 1;
if d2 = 0 then
increment := 1
else
increment := 32;
ppu.VRamAddr := ppu.VRamAddr + increment;
end;
FirstRead:=False;
end;
end;
end;
$4000..$4013,$4015,$4017:begin
snd.SetFrameTimes(FrameTimes);
snd.Snd_Write(addr,data);
end;
$4014:CopyMemory(@ppu.sprRam, @cpu.cpu_mem[$100 * data], $100);
$4016:padle.InputWrite(addr, data);
//$4017:padle.InputWrite(addr, data);
else
if addr<$8000 then
cpu.CPU_Mem[addr] := data
else cart.WriteByte(addr,data);
end;
end;
function Mem_Read(addr: word): byte;
var
d2: byte;
rno:word;
begin
case addr of
$0..$7ff: Result:=cpu.CPU_Mem[addr];
$800..$1fff: Result:=cpu.cpu_mem[addr and $7ff];
$2000..$2008: begin
rno := addr and 7;
case rno of
0..1, 3: Result := ppu.registers[rno];
2: begin
Result := ppu.registers[rno];
ppu.registers[2]:= ppu.registers[2] AND $7F;
cpu.toggle := false;
end;
4: Result := ppu.sprRam[ppu.registers[3]];
7: begin
ppu.VRamAddr:=ppu.VRamAddr and $3fff;
if (ppu.VRamAddr>=$3000) and (ppu.VRamAddr<$3f00) then
ppu.VRamAddr:=ppu.Vramaddr-$1000;
case ppu.VRamAddr of
$0..$2fff:begin
if FirstRead then
begin
FirstRead := false;
Result := $ff;
VRamBuff:=ppu.ppu_mem[ppu.VRamAddr];
d2 := (ppu.registers[0] shr 2) and 1;
if d2 = 0 then
increment := 1
else
increment := 32;
ppu.VRamAddr := ppu.VRamAddr + increment;
Exit;
end;
Result:=VRamBuff;
VRamBuff:=ppu.ppu_mem[ppu.VRamAddr];
if (ppu.VRamAddr>=$2000) and (ppu.VRamAddr<$2400) then
VRamBuff := ppu.ppu_mem[ppu.nametable[0] + ppu.VRamAddr - $2000]
else if (ppu.VRamAddr>=$2400) and (ppu.VRamAddr<$2800) then
VRamBuff := ppu.ppu_mem[ppu.nametable[1] + ppu.VRamAddr - $2400]
else if (ppu.VRamAddr>=$2800) and (ppu.VRamAddr<$2c00) then
VRamBuff := ppu.ppu_mem[ppu.nametable[2] + ppu.VRamAddr - $2800]
else if (ppu.VRamAddr>=$2c00) and (ppu.VRamAddr<$3000) then
VRamBuff := ppu.ppu_mem[ppu.nametable[3] + ppu.VRamAddr - $2c00];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -