📄 unit1.pas
字号:
end;
end;
freemem(Buffer);
end;
}
function FindSpace(var Start_Address:string;var End_Address:string;Add_File_Size:integer):integer;
var
i,n:integer;
iSize:int64;
iFileHandle:integer;
iStartAddress:int64;
Buffer:pChar;
j,start0:integer;
y:boolean;
begin
result:=-1;
with Form1 do
if OpenDialog1.FileName<>'' then
begin
m_bSort:=false;
ListView1.CustomSort(@CustomSortProc,2);//读出的内容按地址进行排序
n:=0;
start0:=0;
y:=false;
ListView2.Clear;
iFileHandle:=FileOpen(OpenDialog1.Filename, fmOpenRead);
if iFileHandle>0 then
begin
with ListView1 do
begin
iSize:=rom_in-strtoint64def('$'+Items[0].SubItems.Strings[1],0);//计算第一个地址与ROM结束地址是否有空间
if iSize>100 then //与ROM结尾空间大于100字节才考虑是否可以利用
begin
begin
iStartAddress:=strtoint64def('$'+address_conv(Items[0].SubItems.Strings[1],false),0);
Buffer := Pchar(AllocMem(iSize+1));
FileSeek(iFileHandle,iStartAddress,0);
FileRead(iFileHandle, Buffer^, iSize);
begin
for j:=0 to iSize-1 do
begin
if (Buffer[j]=#0)and(j<>iSize-1) then
begin
if (y=false) then begin start0:=j; y:=true; end;
end
else
begin
if (j-start0>=200)and(y=true) then //连续0空间大于200字节
begin
ListView2.Items.Add;
ListView2.Items[n].Caption:=inttostr(j-start0+1);//空间大小
ListView2.Items[n].SubItems.add(inttohex(iStartAddress+start0+rom_base,8));//开始地址
ListView2.Items[n].SubItems.add(inttohex(iStartAddress+rom_base+j+1,8));//结束地址(Items[i].SubItems.Strings[0]);
n:=n+1;
end;
start0:=0;
y:=false;
end;
end;
end;
freemem(Buffer);
end;
end;
start0:=0; //重赋初值
y:=false;
for i:=0 to Items.Count-2 do //主要部分的空间判断
begin
iSize:=(strtoint64def('$'+Items[i].SubItems.Strings[0],0)-strtoint64def('$'+Items[i+1].SubItems.Strings[1],0));
//if (1000000<iSize) and (100000000>iSize) then op_log(inttostr(iSize));
if (200<iSize) and (100000000>iSize) then
begin
iStartAddress:=strtoint64def('$'+address_conv(Items[i+1].SubItems.Strings[1],false),0);
Buffer := Pchar(AllocMem(iSize+1));
FileSeek(iFileHandle,iStartAddress,0);
FileRead(iFileHandle, Buffer^, iSize);
begin
for j:=0 to iSize-1 do
begin
if (Buffer[j]=#0)and(j<>iSize-1) then
begin
if (y=false) then begin start0:=j; y:=true; end;
end
else
begin
if (j-start0>=200)and(y=true) then //连续0空间大于200字节才利用
begin
ListView2.Items.Add;
ListView2.Items[n].Caption:=inttostr(j-start0+1-((iStartAddress+start0) mod 2));//空间大小,开始地址,地址取偶数位
ListView2.Items[n].SubItems.add(inttohex(iStartAddress+start0+rom_base+((iStartAddress+start0) mod 2),8));//开始地址,地址取偶数位
ListView2.Items[n].SubItems.add(inttohex(iStartAddress+rom_base+j+1,8));//结束地址(Items[i].SubItems.Strings[0]);
n:=n+1;
end;
start0:=0;
y:=false;
end;
end;
end;
freemem(Buffer);
end;
end;
end;
ListView2.CustomSort(@CustomSortProc,-1); //自定义-1
if debug then op_log('找到'+inttostr(n)+'个可用空间!');
FileClose(iFileHandle);
result:=n;
begin //返回空间地址
i:=ListView2.Items.Count;
if i=0 then begin op_log('没有空间!'); exit; end; //没有列表时提示没有空间
repeat
i:=i-1;
until (strtointdef(ListView2.Items[i].Caption,0)>=Add_File_Size)or(i<=0);
if (strtointdef(ListView2.Items[i].Caption,0)>=Add_File_Size) then
begin
Start_Address:=ListView2.Items[i].SubItems.Strings[0];
End_Address:=ListView2.Items[i].SubItems.Strings[1];
end else result:=-1;
end;
ListView2.Visible:=true;
ListView2.SetFocus;//为按ESC建作聚焦
end;
end;
end;
function Add_Data(Add_File:string;Rom_File:string;IF_Add:boolean):integer;
var
Source,Target:TFileStream;
Pin,Pout: PBYTE;
S_Add,E_Add:string;
begin
begin
Source:=TFileStream.Create(Add_File,fmOpenRead);
result:=Source.Size;
Pin:=AllocMem(Source.Size);
Source.Read(Pin^,Source.Size);
Pout:=AllocMem(add_file_size-1);
try
result:=integer(Do_compress(Pin,result, Pout));
if (result=0) or (If_Add=false) then exit;
if FindSpace(S_Add,E_Add,result)=-1 then
begin
showmessage('请检查剩余空间!');
exit;
end;
begin//替换文件数据
Source.Seek(0,soFromBeginning);
Target:= TFileStream.Create(Rom_File,fmOpenReadWrite);
Target.Seek(strtoint(ihextoint(address_conv(S_Add,false))),soFromBeginning);
if (form1.Checkbox1.Checked=true) then Target.WriteBuffer(Pout^,result)
else Target.WriteBuffer(Pin^,result)
end;
finally
Freemem(Pin);
Freemem(Pout);
FreeAndNil(Target);//一定要Nil,否则下面读写会出错
FreeAndNil(Source);
end;
end;
end;
function AddFiles(Add_File:string;Rom_File:string):integer;
var
Source,Target:TFileStream;
Pin,Pout: PBYTE;
S_Add,E_Add:string;
size_org:Longword;
//i:integer;
w:Longword;
iFileHandle:integer;
Buffer_w:array [0..6] of Longword;
Buffer_0:Pbyte;
Ftime:string;
begin
result:=-1;
if get_rom_info()=-1 then exit;
if num_org<>(num_mod+num_filent) then Form1.Button5.Click;//是否被改过
if (Add_File<>'') and (get_rom_info()<>-1) then
with Form1 do
//if MessageDlg('将会覆盖文件,请自行备份'+#10+'确认开始?',mtConfirmation,[mbYes,mbNo],0)=mryes then
begin
begin
Source:=TFileStream.Create(Add_File,fmOpenRead);
size_org:=Source.Size;
add_file_size:=size_org;
Pin:=AllocMem(Source.Size);
Source.Read(Pin^,Source.Size);
Pout:=AllocMem(add_file_size-1);
try
if Checkbox1.Checked=true then
begin
add_file_size:=integer(Do_compress(Pin,add_file_size, Pout));
if (add_file_size=0) then exit;
end;
if FindSpace(S_Add,E_Add,add_file_size)=-1 then
begin
showmessage('请检查剩余空间!');
exit;
end;
begin//替换文件数据
Source.Seek(0,soFromBeginning);
Target:= TFileStream.Create(Rom_File,fmOpenReadWrite);
Target.Seek(strtoint(ihextoint(address_conv(S_Add,false))),soFromBeginning);
if (Checkbox1.Checked=true) then Target.WriteBuffer(Pout^,add_file_size)
else Target.WriteBuffer(Pin^,size_org);
Labelededit1.Text:=S_Add;
Labelededit5.Text:=E_Add;
end;
finally
Freemem(Pin);
Freemem(Pout);
FreeAndNil(Target);//一定要Nil,否则下面读写会出错
FreeAndNil(Source);
end;
end;
//开始处理文件指针区
iFileHandle:=FileOpen(Rom_File, fmOpenReadWrite);
if iFileHandle >0 then
try
begin
w:= strtoint64def('$'+address_conv(S_Add,false),0);
if (S_Add<>'')and (w<>0) then
begin
data_address:=address_conv(S_Add,true);
now_address:=(rom_in+84+longword(32*num_mod)+longword(28*num_filent));//文件指针区尾地址
//加文件名
add_file_name:=Pchar(ExtractFileName(Add_File));
w:=get_name_sp(iFileHandle,strlen(add_file_name));
if w<>0 then
begin
name_address:=w+rom_base;
if debug then LabeledEdit2.EditLabel.Caption:=inttohex(w,8);
FileSeek(iFileHandle,w,0);
FileWrite(iFileHandle,add_file_name^, strlen(add_file_name));
end else exit; //已在get_name_sp判断有无空间并提示
//加文件指针
if (rom_size-now_address) < 28+16 then
if MessageDlg('文件指针空间不足'+#10+'是否增加空间?',mtConfirmation,[mbYes,mbNo],0)=mryes then
begin
Buffer_0:=Allocmem(33);
FileSeek(iFileHandle,0,2);
FileWrite(iFileHandle,Buffer_0^, 32);
rom_size:=FileSeek(iFileHandle,0,2);
freemem(Buffer_0);
end else exit;
if CheckBox1.Checked=true then
Buffer_w[0]:=$00000801
else Buffer_w[0]:=$00000001;//5为系统隐藏
Ftime:=inttohex(
(trunc(FileDateToDateTime(FileAge(Add_File))*864000000000)
+94352832000000000),16);
Buffer_w[1]:=strtoint64def('$'+copy( Ftime,9,8),0);//日期后段
Buffer_w[2]:=strtoint64def('$'+copy( Ftime,1,8),0);//日期前段
Buffer_w[3]:=size_org;
Buffer_w[4]:=add_file_size;
Buffer_w[5]:=name_address;
Buffer_w[6]:=strtoint64def('$'+data_address,0);
FileSeek(iFileHandle,now_address,0);
FileWrite(iFileHandle,Buffer_w, 28);//SizeOf(Buffer_w));
//改文件数
max_address:= now_address+28+(rom_base);
FileSeek(iFileHandle,(rom_in+12),0);
FileWrite(iFileHandle,max_address, 4);//改结束地址
num_filent:=num_filent+1;
FileSeek(iFileHandle,rom_in+48,0);
FileWrite(iFileHandle,num_filent, sizeof(num_filent));
result:=1;
end;
end;
finally
FileClose(iFileHandle);
end;
Button10.Click;//自动改最后地址
end;//22
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
with opendialog1 do
if execute then
begin
rom_name_edit.Text:=filename;
button5.Click;
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
iFileHandle,iFileLength:integer;
begin
with opendialog2 do
if execute then
begin
iFileHandle:=FileOpen(Filename, fmOpenRead);
if iFileHandle>0 then
begin
file_name_edit.Text:=Filename;
iFileLength:=FileSeek(iFileHandle,0,2);
label1.Caption:=('文件大小:'+inttostr(iFileLength)+' ['+inttohex(iFileLength,8)+']');
if iFileLength=0 then
begin
filename:='';
showmessage('文件大小为0!');
end;
{if debug and (iFileLength>0) then richedit1.text:=Richedit1.Text+#13+inttohex(
(trunc(FileDateToDateTime(FileAge(OpenDialog2.FileName))*864000000000)
+94352832000000000),16);
if debug and (iFileLength>0) then Labelededit3.text:=floattostr(FileDateToDateTime(FileAge(OpenDialog2.FileName)));
}
FileClose(iFileHandle);
end;
end;
end;
procedure TForm1.Button3Click(Sender: TObject);
var
i:integer;
begin
if get_rom_info()=-1 then exit;
if num_org<>(num_mod+num_filent) then Button5.Click;//是否被改过
if FileExists(OpenDialog2.FileName) and (get_rom_info()<>-1) then
//if MessageDlg('将会覆盖文件,请自行备份'+#10+'确认开始?',mtConfirmation,[mbYes,mbNo],0)=mryes then
begin//11
i:=-1;//是否存在
repeat
i:=i+1;
Until (ExtractFileName(OpenDialog2.FileName)=ListView1.Items[i].Caption) or (i>=(ListView1.Items.Count-1));
if (ExtractFileName(OpenDialog2.FileName)=ListView1.Items[i].Caption) then
begin
ListView1.SetFocus;
ListView1.Items[i].Selected := True;
ListView1.Selected.MakeVisible(true);//其中PartialOK参数决定是否该item整体可见还是只要可见就可以了.
showmessage(ExtractFileName(OpenDialog2.FileName)+' 已存在!');
op_log(ExtractFileName(OpenDialog2.FileName)+' 已存在!');
exit;
end;
if AddFiles(OpenDialog2.FileName,OpenDialog1.FileName)<>-1 then
op_log(ExtractFileName(OpenDialog2.FileName)+' 添加成功!');
end;//11
end;
procedure TForm1.labelededit1KeyPress(Sender: TObject; var Key: Char);
begin
if not (key in ['0'..'9','a'..'f','A'..'F',#8,#13]) then
key:= #0;
//if (key in [#13]) then labelededit1Change(Sender);
end;
procedure TForm1.labelededit1KeyUp(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if ssCtrl in shift then
begin
if key=67 then
labelededit1.CopyToClipboard;
if key=86 then
labelededit1.PasteFromClipboard;
if key=88 then
labelededit1.CutToClipboard;
end;
end;
procedure TForm1.LabeledEdit2KeyPress(Sender: TObject; var Key: Char);
begin
if not (key in ['0'..'9','a'..'f','A'..'F',#8,#13]) then
key:= #0;
//if (key in [#13]) then labelededit2Change(Sender);
end;
procedure TForm1.Button4Click(Sender: TObject);
var
iFileHandle:integer;
begin
if FileExists(OpenDialog1.FileName) then
begin
iFileHandle:=FileOpen(opendialog1.FileName, fmOpenRead);
op_log(labelededit2.Text+':'+getname(iFileHandle,address_conv(labelededit2.Text,false)));
FileClose(iFileHandle);
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -