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

📄 main.pas

📁 delphi编制的nes模拟器--tNes
💻 PAS
📖 第 1 页 / 共 2 页
字号:
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 + -