- Initial commit
This commit is contained in:
parent
1df3cd8634
commit
0f99222dbc
30 changed files with 11602 additions and 0 deletions
BIN
bin/armv6_softfpu-linux/micro64disktool
Normal file
BIN
bin/armv6_softfpu-linux/micro64disktool
Normal file
Binary file not shown.
BIN
bin/x86_32-linux/micro64disktool
Normal file
BIN
bin/x86_32-linux/micro64disktool
Normal file
Binary file not shown.
BIN
bin/x86_32-win32/micro64disktool.exe
Normal file
BIN
bin/x86_32-win32/micro64disktool.exe
Normal file
Binary file not shown.
BIN
bin/x86_64-linux/micro64disktool
Normal file
BIN
bin/x86_64-linux/micro64disktool
Normal file
Binary file not shown.
BIN
bin/x86_64-win64/micro64disktool.exe
Normal file
BIN
bin/x86_64-win64/micro64disktool.exe
Normal file
Binary file not shown.
856
src/BeRoStream.pas
Normal file
856
src/BeRoStream.pas
Normal file
|
|
@ -0,0 +1,856 @@
|
|||
(*
|
||||
** This file is part of the Micro64 Disk Tool.
|
||||
** Copyright (C) 2002-2013 by Benjamin Rosseaux
|
||||
**
|
||||
** The source code of the Micro64 Disk Tool and helper tools are
|
||||
** distributed under the Library GNU General Public License
|
||||
** (see the file COPYING) with the following modification:
|
||||
**
|
||||
** As a special exception, the copyright holders of this software give you
|
||||
** permission to link this software with independent modules to produce
|
||||
** an executable, regardless of the license terms of these independent modules,
|
||||
** and to copy and distribute the resulting executable under terms of your
|
||||
** choice, provided that you also meet, for each linked independent module,
|
||||
** the terms and conditions of the license of that module. An independent
|
||||
** module is a module which is not derived from or based on this software. If
|
||||
** you modify this software, you may extend this exception to your version of
|
||||
** the software, but you are not obligated to do so. If you do not wish to do
|
||||
** so, delete this exception statement from your version.
|
||||
**
|
||||
** If you didn't receive a copy of the file COPYING, contact:
|
||||
** Free Software Foundation
|
||||
** 675 Mass Ave
|
||||
** Cambridge, MA 02139
|
||||
** USA
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
*)
|
||||
unit BeRoStream;
|
||||
{$IFDEF FPC}
|
||||
{$MODE DELPHI}
|
||||
{$WARNINGS OFF}
|
||||
{$HINTS OFF}
|
||||
{$OVERFLOWCHECKS OFF}
|
||||
{$RANGECHECKS OFF}
|
||||
{$IFDEF CPUI386}
|
||||
{$DEFINE CPU386}
|
||||
{$ASMMODE INTEL}
|
||||
{$ENDIF}
|
||||
{$IFDEF FPC_LITTLE_ENDIAN}
|
||||
{$DEFINE LITTLE_ENDIAN}
|
||||
{$ELSE}
|
||||
{$IFDEF FPC_BIG_ENDIAN}
|
||||
{$DEFINE BIG_ENDIAN}
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
{$ELSE}
|
||||
{$DEFINE LITTLE_ENDIAN}
|
||||
{$IFNDEF CPU64}
|
||||
{$DEFINE CPU32}
|
||||
{$ENDIF}
|
||||
{$OPTIMIZATION ON}
|
||||
{$ENDIF}
|
||||
{$ifdef win32}
|
||||
{$define win}
|
||||
{$endif}
|
||||
{$ifdef win64}
|
||||
{$define win}
|
||||
{$endif}
|
||||
|
||||
interface
|
||||
|
||||
uses {$ifdef win}Windows,{$endif}SysUtils,Classes;
|
||||
|
||||
const bsoFromBeginning=0;
|
||||
bsoFromCurrent=1;
|
||||
bsoFromEnd=2;
|
||||
|
||||
type PBeRoStreamData=^TBeRoStreamData;
|
||||
TBeRoStreamData=packed array[0..$7ffffffe] of byte;
|
||||
|
||||
PBeRoStreamBuffer=^TBeRoStreamBuffer;
|
||||
TBeRoStreamBuffer=packed array[1..4096] of byte;
|
||||
|
||||
PBeRoStream=^TBeRoStream;
|
||||
TBeRoStream=class
|
||||
private
|
||||
fPosition,fSize,fInMemorySize:longint;
|
||||
fData:PBeRoStreamData;
|
||||
fBitBuffer:longword;
|
||||
fBitBufferSize:byte;
|
||||
procedure Realloc(NewInMemorySize:longint);
|
||||
procedure Resize(NewSize:longint);
|
||||
function GetString:ansistring;
|
||||
procedure SetString(Value:ansistring);
|
||||
function GetByte(BytePosition:longint):byte;
|
||||
procedure SetByte(BytePosition:longint;Value:byte);
|
||||
public
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
function ReadFromStream(Stream:TStream):longint;
|
||||
function WriteToStream(Stream:TStream):longint;
|
||||
function Assign(Src:TBeRoStream):longint;
|
||||
function Append(Src:TBeRoStream):longint;
|
||||
function AppendFrom(Src:TBeRoStream;Counter:longint):longint;
|
||||
procedure Clear; virtual;
|
||||
function Read(var Buf;Count:longint):longint; virtual;
|
||||
function ReadAt(Position:longint;var Buf;Count:longint):longint; virtual;
|
||||
function Write(const Buf;Count:longint):longint; virtual;
|
||||
function SeekEx(APosition:longint):longint; virtual;
|
||||
function Seek(APosition:longint):longint; overload;
|
||||
function Seek(APosition,Origin:longint):longint; overload;
|
||||
function Position:longint; virtual;
|
||||
function Size:longint; virtual;
|
||||
procedure SetSize(NewSize:longint);
|
||||
function ReadByte:byte;
|
||||
function ReadWord:word;
|
||||
function ReadDWord:longword;
|
||||
function ReadLine:ansistring;
|
||||
function ReadString:ansistring;
|
||||
procedure WriteByte(Value:byte);
|
||||
function WriteByteCount(Value:byte;Count:longint):longint;
|
||||
procedure WriteWord(Value:word);
|
||||
procedure WriteDWord(Value:longword);
|
||||
procedure WriteShortInt(Value:shortint);
|
||||
procedure WriteSmallInt(Value:smallint);
|
||||
procedure WriteLongInt(Value:longint);
|
||||
procedure WriteInt64(Value:int64);
|
||||
procedure WriteBoolean(Value:boolean);
|
||||
procedure WriteLine(Line:ansistring);
|
||||
procedure WriteString(S:ansistring);
|
||||
procedure WriteDataString(S:ansistring);
|
||||
procedure ResetBits;
|
||||
function ReadBit:boolean;
|
||||
function ReadBits(BitsCount:byte):longword;
|
||||
function ReadBitsSigned(BitsCount:byte):longint;
|
||||
procedure WriteBit(Value:boolean);
|
||||
procedure WriteBits(Value:longword;BitsCount:byte);
|
||||
procedure WriteBitsSigned(Value:longint;BitsCount:byte);
|
||||
procedure FlushBits;
|
||||
property Text:ansistring read GetString write SetString;
|
||||
property Data:PBeRoStreamData read fData;
|
||||
property Bytes[BytePosition:longint]:byte read GetByte write SetByte; default;
|
||||
property BitsInBuffer:byte read fBitBufferSize;
|
||||
end;
|
||||
|
||||
PBeRoDatenStream=^TBeRoDatenStream;
|
||||
TBeRoDatenStream=TBeRoStream;
|
||||
|
||||
PBeRoMemoryStream=^TBeRoMemoryStream;
|
||||
TBeRoMemoryStream=TBeRoStream;
|
||||
|
||||
PBeRoFileStream=^TBeRoFileStream;
|
||||
TBeRoFileStream=class(TBeRoStream)
|
||||
private
|
||||
{$ifdef win}
|
||||
fFile:longword;
|
||||
{$else}
|
||||
fFile:file;
|
||||
{$endif}
|
||||
public
|
||||
ReadOnly:boolean;
|
||||
constructor Create(FileName:ansistring);
|
||||
constructor CreateNew(FileName:ansistring);
|
||||
destructor Destroy; override;
|
||||
function Read(var Buf;Count:longint):longint; override;
|
||||
function Write(const Buf;Count:longint):longint; override;
|
||||
function SeekEx(APosition:longint):longint; override;
|
||||
function Position:longint; override;
|
||||
function Size:longint; override;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
type pbyte=^byte;
|
||||
|
||||
const MemoryDelta=1 shl 16;
|
||||
MemoryDeltaMask=MemoryDelta-1;
|
||||
|
||||
constructor TBeRoStream.Create;
|
||||
begin
|
||||
inherited Create;
|
||||
fData:=nil;
|
||||
REALLOCMEM(fData,0);
|
||||
fPosition:=0;
|
||||
fSize:=0;
|
||||
fInMemorySize:=0;
|
||||
ResetBits;
|
||||
end;
|
||||
|
||||
destructor TBeRoStream.Destroy;
|
||||
begin
|
||||
REALLOCMEM(fData,0);
|
||||
fPosition:=0;
|
||||
fSize:=0;
|
||||
fInMemorySize:=0;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
function TBeRoStream.ReadFromStream(Stream:TStream):longint;
|
||||
var Remain,ToDo:longint;
|
||||
Buf:TBeRoStreamBuffer;
|
||||
begin
|
||||
Clear;
|
||||
result:=0;
|
||||
if (Seek(0)=0) and (Stream.Seek(0,soBeginning)=0) then begin
|
||||
Remain:=Stream.Size;
|
||||
while Remain>0 do begin
|
||||
ToDo:=sizeof(TBeRoStreamBuffer);
|
||||
if ToDo>Remain then begin
|
||||
ToDo:=Remain;
|
||||
end;
|
||||
if Stream.Read(Buf,ToDo)<>ToDo then begin
|
||||
break;
|
||||
end;
|
||||
if Write(Buf,ToDo)<>ToDo then begin
|
||||
break;
|
||||
end;
|
||||
inc(result,ToDo);
|
||||
dec(Remain,ToDo);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TBeRoStream.WriteToStream(Stream:TStream):longint;
|
||||
var Remain,ToDo:longint;
|
||||
Buf:TBeRoStreamBuffer;
|
||||
begin
|
||||
result:=0;
|
||||
if (Seek(0)=0) and (Stream.Seek(0,soBeginning)=0) then begin
|
||||
Remain:=Size;
|
||||
while Remain>0 do begin
|
||||
ToDo:=sizeof(TBeRoStreamBuffer);
|
||||
if ToDo>Remain then begin
|
||||
ToDo:=Remain;
|
||||
end;
|
||||
if Read(Buf,ToDo)<>ToDo then begin
|
||||
break;
|
||||
end;
|
||||
if Stream.Write(Buf,ToDo)<>ToDo then begin
|
||||
break;
|
||||
end;
|
||||
inc(result,ToDo);
|
||||
dec(Remain,ToDo);
|
||||
end;
|
||||
if Stream.Seek(0,soBeginning)<>0 then begin
|
||||
result:=0;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TBeRoStream.Assign(Src:TBeRoStream):longint;
|
||||
var Remain,Count:longint;
|
||||
Buf:TBeRoStreamBuffer;
|
||||
begin
|
||||
Clear;
|
||||
result:=0;
|
||||
Remain:=Src.Size;
|
||||
if (Seek(0)<>0) or (Src.Seek(0)<>0) then exit;
|
||||
while Remain>=sizeof(TBeRoStreamBuffer) do begin
|
||||
Count:=Src.Read(Buf,sizeof(TBeRoStreamBuffer));
|
||||
Write(Buf,Count);
|
||||
inc(result,Count);
|
||||
dec(Remain,sizeof(TBeRoStreamBuffer));
|
||||
end;
|
||||
if Remain>0 then begin
|
||||
Count:=Src.Read(Buf,Remain);
|
||||
Write(Buf,Count);
|
||||
inc(result,Count);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TBeRoStream.Append(Src:TBeRoStream):longint;
|
||||
var Remain,Count:longint;
|
||||
Buf:TBeRoStreamBuffer;
|
||||
begin
|
||||
result:=0;
|
||||
Remain:=Src.Size;
|
||||
if Src.Seek(0)<>0 then exit;
|
||||
while Remain>=sizeof(TBeRoStreamBuffer) do begin
|
||||
Count:=Src.Read(Buf,sizeof(TBeRoStreamBuffer));
|
||||
Write(Buf,Count);
|
||||
inc(result,Count);
|
||||
dec(Remain,sizeof(TBeRoStreamBuffer));
|
||||
end;
|
||||
if Remain>0 then begin
|
||||
Count:=Src.Read(Buf,Remain);
|
||||
Write(Buf,Count);
|
||||
inc(result,Count);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TBeRoStream.AppendFrom(Src:TBeRoStream;Counter:longint):longint;
|
||||
var Remain,Count:longint;
|
||||
Buf:TBeRoStreamBuffer;
|
||||
begin
|
||||
result:=0;
|
||||
Remain:=Counter;
|
||||
while Remain>=sizeof(TBeRoStreamBuffer) do begin
|
||||
Count:=Src.Read(Buf,sizeof(TBeRoStreamBuffer));
|
||||
Write(Buf,Count);
|
||||
inc(result,Count);
|
||||
dec(Remain,sizeof(TBeRoStreamBuffer));
|
||||
end;
|
||||
if Remain>0 then begin
|
||||
Count:=Src.Read(Buf,Remain);
|
||||
Write(Buf,Count);
|
||||
inc(result,Count);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TBeRoStream.Clear;
|
||||
begin
|
||||
ReallocMem(fData,0);
|
||||
fPosition:=0;
|
||||
fSize:=0;
|
||||
fInMemorySize:=0;
|
||||
end;
|
||||
|
||||
procedure TBeRoStream.Realloc(NewInMemorySize:longint);
|
||||
var OldInMemorySize,Count:longint;
|
||||
begin
|
||||
if NewInMemorySize>0 then begin
|
||||
NewInMemorySize:=(NewInMemorySize+MemoryDeltaMask) and not MemoryDeltaMask;
|
||||
end;
|
||||
if fInMemorySize<>NewInMemorySize then begin
|
||||
OldInMemorySize:=fInMemorySize;
|
||||
fInMemorySize:=NewInMemorySize;
|
||||
ReallocMem(fData,fInMemorySize);
|
||||
Count:=NewInMemorySize-OldInMemorySize;
|
||||
if Count>0 then begin
|
||||
FillChar(fData^[OldInMemorySize],Count,#0);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TBeRoStream.Resize(NewSize:longint);
|
||||
begin
|
||||
fSize:=NewSize;
|
||||
if fPosition>fSize then begin
|
||||
fPosition:=fSize;
|
||||
end;
|
||||
Realloc(fSize);
|
||||
end;
|
||||
|
||||
function TBeRoStream.Read(var Buf;Count:longint):longint;
|
||||
begin
|
||||
if (fPosition>=0) and (Count>0) then begin
|
||||
result:=fSize-fPosition;
|
||||
if result>0 then begin
|
||||
if result>Count then begin
|
||||
result:=Count;
|
||||
end;
|
||||
Move(fData^[fPosition],Buf,result);
|
||||
inc(fPosition,result);
|
||||
end else begin
|
||||
result:=0;
|
||||
end;
|
||||
end else begin
|
||||
result:=0;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TBeRoStream.ReadAt(Position:longint;var Buf;Count:longint):longint;
|
||||
begin
|
||||
if Seek(Position)=Position then begin
|
||||
result:=Read(Buf,Count);
|
||||
end else begin
|
||||
result:=0;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TBeRoStream.Write(const Buf;Count:longint):longint;
|
||||
var EndPosition:longint;
|
||||
begin
|
||||
if (fPosition>=0) and (Count>0) then begin
|
||||
EndPosition:=fPosition+Count;
|
||||
if EndPosition>fSize then begin
|
||||
Resize(EndPosition);
|
||||
end;
|
||||
Move(Buf,fData^[fPosition],Count);
|
||||
fPosition:=EndPosition;
|
||||
result:=Count;
|
||||
end else begin
|
||||
result:=0;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TBeRoStream.SeekEx(APosition:longint):longint;
|
||||
var AltePos,RemainSize:longint;
|
||||
begin
|
||||
fPosition:=APosition;
|
||||
if fPosition<0 then fPosition:=0;
|
||||
if fPosition>fSize then begin
|
||||
AltePos:=fSize;
|
||||
RemainSize:=fPosition-fSize;
|
||||
if RemainSize>0 then begin
|
||||
Resize(fSize+RemainSize);
|
||||
FILLCHAR(fData^[AltePos],RemainSize,#0);
|
||||
end;
|
||||
result:=fPosition;
|
||||
end else begin
|
||||
result:=fPosition;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TBeRoStream.Seek(APosition:longint):longint;
|
||||
begin
|
||||
result:=SeekEx(APosition);
|
||||
end;
|
||||
|
||||
function TBeRoStream.Seek(APosition,Origin:longint):longint;
|
||||
begin
|
||||
case Origin of
|
||||
bsoFromBeginning:result:=SeekEx(APosition);
|
||||
bsoFromCurrent:result:=SeekEx(Position+APosition);
|
||||
bsoFromEnd:result:=SeekEx(Size-APosition);
|
||||
else result:=SeekEx(APosition);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TBeRoStream.Position:longint;
|
||||
begin
|
||||
result:=fPosition;
|
||||
end;
|
||||
|
||||
function TBeRoStream.Size:longint;
|
||||
begin
|
||||
result:=fSize;
|
||||
end;
|
||||
|
||||
procedure TBeRoStream.SetSize(NewSize:longint);
|
||||
begin
|
||||
fSize:=NewSize;
|
||||
if fPosition>fSize then fPosition:=fSize;
|
||||
REALLOCMEM(fData,fSize);
|
||||
end;
|
||||
|
||||
function TBeRoStream.ReadByte:byte;
|
||||
var B:byte;
|
||||
begin
|
||||
if Read(B,1)<>1 then begin
|
||||
result:=0;
|
||||
end else begin
|
||||
result:=B;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TBeRoStream.ReadWord:word;
|
||||
begin
|
||||
result:=ReadByte or (ReadByte shl 8);
|
||||
end;
|
||||
|
||||
function TBeRoStream.ReadDWord:longword;
|
||||
begin
|
||||
result:=ReadWord or (ReadWord shl 16);
|
||||
end;
|
||||
|
||||
function TBeRoStream.ReadLine:ansistring;
|
||||
var C:ansichar;
|
||||
begin
|
||||
result:='';
|
||||
while Position<Size do begin
|
||||
Read(C,1);
|
||||
case C of
|
||||
#10,#13:begin
|
||||
if (Position<Size) and (((C=#13) and (Bytes[Position]=10)) or
|
||||
((C=#10) and (Bytes[Position]=13))) then begin
|
||||
Read(C,1);
|
||||
end;
|
||||
break;
|
||||
end;
|
||||
else begin
|
||||
result:=result+C;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TBeRoStream.ReadString:ansistring;
|
||||
var L:longword;
|
||||
begin
|
||||
L:=ReadDWord;
|
||||
setlength(result,L);
|
||||
if L>0 then begin
|
||||
Read(result[1],L);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TBeRoStream.WriteByte(Value:byte);
|
||||
begin
|
||||
Write(Value,sizeof(byte));
|
||||
end;
|
||||
|
||||
function TBeRoStream.WriteByteCount(Value:byte;Count:longint):longint;
|
||||
var Counter:longint;
|
||||
begin
|
||||
result:=0;
|
||||
for Counter:=1 to Count do begin
|
||||
inc(result,Write(Value,sizeof(byte)));
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TBeRoStream.WriteWord(Value:word);
|
||||
begin
|
||||
Write(Value,sizeof(word));
|
||||
end;
|
||||
|
||||
procedure TBeRoStream.WriteDWord(Value:longword);
|
||||
begin
|
||||
Write(Value,sizeof(longword));
|
||||
end;
|
||||
|
||||
procedure TBeRoStream.WriteShortInt(Value:shortint);
|
||||
begin
|
||||
Write(Value,sizeof(shortint));
|
||||
end;
|
||||
|
||||
procedure TBeRoStream.WriteSmallInt(Value:smallint);
|
||||
begin
|
||||
Write(Value,sizeof(smallint));
|
||||
end;
|
||||
|
||||
procedure TBeRoStream.WriteLongInt(Value:longint);
|
||||
begin
|
||||
Write(Value,sizeof(longint));
|
||||
end;
|
||||
|
||||
procedure TBeRoStream.WriteInt64(Value:int64);
|
||||
begin
|
||||
Write(Value,sizeof(int64));
|
||||
end;
|
||||
|
||||
procedure TBeRoStream.WriteBoolean(Value:boolean);
|
||||
begin
|
||||
if Value then begin
|
||||
WriteByte(1);
|
||||
end else begin
|
||||
WriteByte(0);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TBeRoStream.WriteLine(Line:ansistring);
|
||||
const CRLF:array[1..2] of ansichar=#13#10;
|
||||
begin
|
||||
if length(Line)>0 then Write(Line[1],length(Line));
|
||||
Write(CRLF,2);
|
||||
end;
|
||||
|
||||
procedure TBeRoStream.WriteString(S:ansistring);
|
||||
var L:longword;
|
||||
begin
|
||||
L:=length(S);
|
||||
if L>0 then Write(S[1],L);
|
||||
end;
|
||||
|
||||
procedure TBeRoStream.WriteDataString(S:ansistring);
|
||||
var L:longword;
|
||||
begin
|
||||
L:=length(S);
|
||||
WriteDWord(L);
|
||||
if L>0 then Write(S[1],L);
|
||||
end;
|
||||
|
||||
procedure TBeRoStream.ResetBits;
|
||||
begin
|
||||
fBitBuffer:=0;
|
||||
fBitBufferSize:=0;
|
||||
end;
|
||||
|
||||
function TBeRoStream.ReadBit:boolean;
|
||||
begin
|
||||
result:=(ReadBits(1)<>0);
|
||||
end;
|
||||
|
||||
function TBeRoStream.ReadBits(BitsCount:byte):longword;
|
||||
begin
|
||||
while fBitBufferSize<BitsCount do begin
|
||||
fBitBuffer:=(fBitBuffer shl 8) or ReadByte;
|
||||
inc(fBitBufferSize,8);
|
||||
end;
|
||||
result:=(fBitBuffer shr (fBitBufferSize-BitsCount)) and ((1 shl BitsCount)-1);
|
||||
dec(fBitBufferSize,BitsCount);
|
||||
end;
|
||||
|
||||
function TBeRoStream.ReadBitsSigned(BitsCount:byte):longint;
|
||||
begin
|
||||
result:=0;
|
||||
if BitsCount>1 then begin
|
||||
if ReadBits(1)<>0 then begin
|
||||
result:=-ReadBits(BitsCount-1);
|
||||
end else begin
|
||||
result:=ReadBits(BitsCount-1);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TBeRoStream.WriteBit(Value:boolean);
|
||||
begin
|
||||
if Value then begin
|
||||
WriteBits(1,1);
|
||||
end else begin
|
||||
WriteBits(0,1);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TBeRoStream.WriteBits(Value:longword;BitsCount:byte);
|
||||
begin
|
||||
fBitBuffer:=(fBitBuffer shl BitsCount) or Value;
|
||||
inc(fBitBufferSize,BitsCount);
|
||||
while fBitBufferSize>=8 do begin
|
||||
WriteByte((fBitBuffer shr (fBitBufferSize-8)) and $ff);
|
||||
dec(fBitBufferSize,8);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TBeRoStream.WriteBitsSigned(Value:longint;BitsCount:byte);
|
||||
begin
|
||||
if BitsCount>1 then begin
|
||||
if Value<0 then begin
|
||||
WriteBits(1,1);
|
||||
WriteBits(longword(0-Value),BitsCount-1);
|
||||
end else begin
|
||||
WriteBits(0,1);
|
||||
WriteBits(longword(Value),BitsCount-1);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TBeRoStream.FlushBits;
|
||||
begin
|
||||
if fBitBufferSize>0 then begin
|
||||
WriteByte(fBitBuffer shl (8-fBitBufferSize));
|
||||
end;
|
||||
fBitBuffer:=0;
|
||||
fBitBufferSize:=0;
|
||||
end;
|
||||
|
||||
function TBeRoStream.GetString:ansistring;
|
||||
begin
|
||||
Seek(0);
|
||||
if Size>0 then begin
|
||||
setlength(result,Size);
|
||||
Read(result[1],Size);
|
||||
end else begin
|
||||
result:='';
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TBeRoStream.SetString(Value:ansistring);
|
||||
begin
|
||||
Clear;
|
||||
if length(Value)>0 then begin
|
||||
Write(Value[1],length(Value));
|
||||
end;
|
||||
end;
|
||||
|
||||
function TBeRoStream.GetByte(BytePosition:longint):byte;
|
||||
var AltePosition:longint;
|
||||
begin
|
||||
AltePosition:=Position;
|
||||
Seek(BytePosition);
|
||||
Read(result,sizeof(byte));
|
||||
Seek(AltePosition);
|
||||
end;
|
||||
|
||||
procedure TBeRoStream.SetByte(BytePosition:longint;Value:byte);
|
||||
var AltePosition:longint;
|
||||
begin
|
||||
AltePosition:=Position;
|
||||
Seek(BytePosition);
|
||||
Write(Value,sizeof(byte));
|
||||
Seek(AltePosition);
|
||||
end;
|
||||
|
||||
constructor TBeRoFileStream.Create(FileName:ansistring);
|
||||
{$ifndef win}
|
||||
var Alt:byte;
|
||||
{$endif}
|
||||
begin
|
||||
inherited Create;
|
||||
ReadOnly:=false;
|
||||
{$ifdef win}
|
||||
if (FileGetAttr(String(FileName)) and faReadOnly)<>0 then begin
|
||||
fFile:=CreateFile(pchar(String(FileName)),GENERIC_READ,FILE_SHARE_READ,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL or FILE_FLAG_RANDOM_ACCESS or FILE_FLAG_WRITE_THROUGH,0);
|
||||
if fFile<>0 then begin
|
||||
ReadOnly:=true;
|
||||
end;
|
||||
end else begin
|
||||
fFile:=CreateFile(pchar(String(FileName)),GENERIC_READ or GENERIC_WRITE,FILE_SHARE_READ,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL or FILE_FLAG_RANDOM_ACCESS or FILE_FLAG_WRITE_THROUGH,0);
|
||||
if fFile=0 then begin
|
||||
fFile:=CreateFile(pchar(String(FileName)),GENERIC_READ,FILE_SHARE_READ,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL or FILE_FLAG_RANDOM_ACCESS or FILE_FLAG_WRITE_THROUGH,0);
|
||||
if fFile<>0 then begin
|
||||
ReadOnly:=true;
|
||||
end else begin
|
||||
fFile:=CreateFile(pchar(String(FileName)),GENERIC_READ or GENERIC_WRITE,FILE_SHARE_READ,nil,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL or FILE_FLAG_RANDOM_ACCESS or FILE_FLAG_WRITE_THROUGH,0);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
{$else}
|
||||
Alt:=FileMode;
|
||||
if (FileGetAttr(FileName) and faReadOnly)<>0 then begin
|
||||
FileMode:=0;
|
||||
ReadOnly:=true;
|
||||
end else begin
|
||||
FileMode:=2;
|
||||
end;
|
||||
assignfile(fFile,FileName);
|
||||
{$i-}reset(fFile,1);{$i+}
|
||||
if IOResult<>0 then begin
|
||||
FileMode:=0;
|
||||
ReadOnly:=true;
|
||||
assignfile(fFile,FileName);
|
||||
{$i-}reset(fFile,1);{$i+}
|
||||
if IOResult<>0 then begin
|
||||
FileMode:=2;
|
||||
assignfile(fFile,FileName);
|
||||
{$i-}rewrite(fFile,1);{$i+}
|
||||
end;
|
||||
end;
|
||||
FileMode:=Alt;
|
||||
if IOResult<>0 then begin
|
||||
end;
|
||||
{$endif}
|
||||
end;
|
||||
|
||||
constructor TBeRoFileStream.CreateNew(FileName:ansistring);
|
||||
{$ifndef win}
|
||||
var Alt:byte;
|
||||
{$endif}
|
||||
begin
|
||||
inherited Create;
|
||||
ReadOnly:=false;
|
||||
{$ifdef win}
|
||||
fFile:=CreateFile(pchar(string(FileName)),GENERIC_READ or GENERIC_WRITE,FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE,nil,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL or FILE_FLAG_RANDOM_ACCESS or FILE_FLAG_WRITE_THROUGH,0);
|
||||
{$else}
|
||||
Alt:=FileMode;
|
||||
FileMode:=2;
|
||||
assignfile(fFile,FileName);
|
||||
{$i-}rewrite(fFile,1);{$i+}
|
||||
FileMode:=Alt;
|
||||
if IOResult<>0 then begin
|
||||
end;
|
||||
{$endif}
|
||||
end;
|
||||
|
||||
destructor TBeRoFileStream.Destroy;
|
||||
begin
|
||||
{$ifdef win}
|
||||
CloseHandle(fFile);
|
||||
{$else}
|
||||
{$i-}closefile(fFile);{$i+}
|
||||
if IOResult<>0 then begin
|
||||
end;
|
||||
{$endif}
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
function TBeRoFileStream.Read(var Buf;Count:longint):longint;
|
||||
{$ifdef win}
|
||||
var l:longword;
|
||||
{$else}
|
||||
var i:longint;
|
||||
{$endif}
|
||||
begin
|
||||
{$ifdef win}
|
||||
ReadFile(fFile,Buf,Count,l,nil);
|
||||
result:=l;
|
||||
{$else}
|
||||
{$i-}blockread(fFile,Buf,Count,i);{$i+}
|
||||
if IOResult<>0 then begin
|
||||
result:=0;
|
||||
exit;
|
||||
end;
|
||||
{$i-}fPosition:=filepos(fFile);{$i+}
|
||||
if IOResult<>0 then begin
|
||||
result:=0;
|
||||
exit;
|
||||
end;
|
||||
result:=i;
|
||||
{$endif}
|
||||
end;
|
||||
|
||||
function TBeRoFileStream.Write(const Buf;Count:longint):longint;
|
||||
{$ifdef win}
|
||||
var l:longword;
|
||||
{$else}
|
||||
var i:longint;
|
||||
{$endif}
|
||||
begin
|
||||
{$ifdef win}
|
||||
WriteFile(fFile,Buf,Count,l,nil);
|
||||
result:=l;
|
||||
{$else}
|
||||
{$i-}blockwrite(fFile,Buf,Count,i);{$i+}
|
||||
if IOResult<>0 then begin
|
||||
result:=0;
|
||||
exit;
|
||||
end;
|
||||
{$i-}fPosition:=filepos(fFile);{$i+}
|
||||
if IOResult<>0 then begin
|
||||
result:=0;
|
||||
exit
|
||||
end;
|
||||
result:=i;
|
||||
{$endif}
|
||||
end;
|
||||
|
||||
function TBeRoFileStream.SeekEx(APosition:longint):longint;
|
||||
begin
|
||||
{$ifdef win}
|
||||
if APosition<=Size then begin
|
||||
SetFilePointer(fFile,APosition,nil,FILE_BEGIN);
|
||||
if IOResult<>0 then begin
|
||||
result:=0;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
result:=SetFilePointer(fFile,0,nil,FILE_CURRENT);
|
||||
{$else}
|
||||
if APosition<=Size then begin
|
||||
{$i-}System.Seek(fFile,APosition);{$i+}
|
||||
if IOResult<>0 then begin
|
||||
result:=0;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
{$i-}result:=filepos(fFile);{$i+}
|
||||
if IOResult<>0 then begin
|
||||
result:=0;
|
||||
end;
|
||||
{$endif}
|
||||
end;
|
||||
|
||||
function TBeRoFileStream.Position:longint;
|
||||
begin
|
||||
{$ifdef win}
|
||||
result:=SetFilePointer(fFile,0,nil,FILE_CURRENT);
|
||||
{$else}
|
||||
{$i-}result:=filepos(fFile);{$i+}
|
||||
if IOResult<>0 then begin
|
||||
result:=0;
|
||||
end;
|
||||
{$endif}
|
||||
end;
|
||||
|
||||
function TBeRoFileStream.Size:longint;
|
||||
{$ifdef win}
|
||||
var Old:longint;
|
||||
{$endif}
|
||||
begin
|
||||
{$ifdef win}
|
||||
Old:=SetFilePointer(fFile,0,nil,FILE_CURRENT);
|
||||
result:=SetFilePointer(fFile,0,nil,FILE_END);
|
||||
SetFilePointer(fFile,Old,nil,FILE_BEGIN);
|
||||
{$else}
|
||||
{$i-}result:=filesize(fFile);{$i+}
|
||||
if IOResult<>0 then begin
|
||||
result:=0;
|
||||
end;
|
||||
{$endif}
|
||||
end;
|
||||
|
||||
end.
|
||||
1403
src/BeRoStringToDouble.pas
Normal file
1403
src/BeRoStringToDouble.pas
Normal file
File diff suppressed because it is too large
Load diff
1043
src/BeRoUtils.pas
Normal file
1043
src/BeRoUtils.pas
Normal file
File diff suppressed because it is too large
Load diff
504
src/COPYING.txt
Normal file
504
src/COPYING.txt
Normal file
|
|
@ -0,0 +1,504 @@
|
|||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
|
||||
|
||||
90
src/ChecksumUtils.pas
Normal file
90
src/ChecksumUtils.pas
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
(*
|
||||
** This file is part of the Micro64 Disk Tool.
|
||||
** Copyright (C) 2002-2013 by Benjamin Rosseaux
|
||||
**
|
||||
** The source code of the Micro64 Disk Tool and helper tools are
|
||||
** distributed under the Library GNU General Public License
|
||||
** (see the file COPYING) with the following modification:
|
||||
**
|
||||
** As a special exception, the copyright holders of this software give you
|
||||
** permission to link this software with independent modules to produce
|
||||
** an executable, regardless of the license terms of these independent modules,
|
||||
** and to copy and distribute the resulting executable under terms of your
|
||||
** choice, provided that you also meet, for each linked independent module,
|
||||
** the terms and conditions of the license of that module. An independent
|
||||
** module is a module which is not derived from or based on this software. If
|
||||
** you modify this software, you may extend this exception to your version of
|
||||
** the software, but you are not obligated to do so. If you do not wish to do
|
||||
** so, delete this exception statement from your version.
|
||||
**
|
||||
** If you didn't receive a copy of the file COPYING, contact:
|
||||
** Free Software Foundation
|
||||
** 675 Mass Ave
|
||||
** Cambridge, MA 02139
|
||||
** USA
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
*)
|
||||
unit ChecksumUtils;
|
||||
{$IFDEF FPC}
|
||||
{$MODE DELPHI}
|
||||
{$WARNINGS OFF}
|
||||
{$HINTS OFF}
|
||||
{$OVERFLOWCHECKS OFF}
|
||||
{$RANGECHECKS OFF}
|
||||
{$IFDEF CPUI386}
|
||||
{$DEFINE CPU386}
|
||||
{$ASMMODE INTEL}
|
||||
{$ENDIF}
|
||||
{$IFDEF FPC_LITTLE_ENDIAN}
|
||||
{$DEFINE LITTLE_ENDIAN}
|
||||
{$ELSE}
|
||||
{$IFDEF FPC_BIG_ENDIAN}
|
||||
{$DEFINE BIG_ENDIAN}
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
{$ELSE}
|
||||
{$DEFINE LITTLE_ENDIAN}
|
||||
{$IFNDEF CPU64}
|
||||
{$DEFINE CPU32}
|
||||
{$ENDIF}
|
||||
{$OPTIMIZATION ON}
|
||||
{$ENDIF}
|
||||
{$define use64}
|
||||
|
||||
interface
|
||||
|
||||
function CRC32(Data:pointer;Len:longword):longword;
|
||||
|
||||
implementation
|
||||
|
||||
function CRC32(Data:pointer;Len:longword):longword;
|
||||
const CRC32Table:array[0..15] of longword=($00000000,$1db71064,$3b6e20c8,$26d930ac,$76dc4190,
|
||||
$6b6b51f4,$4db26158,$5005713c,$edb88320,$f00f9344,
|
||||
$d6d6a3e8,$cb61b38c,$9b64c2b0,$86d3d2d4,$a00ae278,
|
||||
$bdbdf21c);
|
||||
|
||||
var b:pansichar;
|
||||
i:longword;
|
||||
begin
|
||||
if Len=0 then begin
|
||||
result:=0;
|
||||
end else begin
|
||||
b:=Data;
|
||||
result:=$ffffffff;
|
||||
for i:=1 to Len do begin
|
||||
result:=result xor byte(b^);
|
||||
result:=CRC32Table[result and $f] xor (result shr 4);
|
||||
result:=CRC32Table[result and $f] xor (result shr 4);
|
||||
inc(b);
|
||||
end;
|
||||
result:=result xor $ffffffff;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
end.
|
||||
|
||||
1144
src/DiskImageD64.pas
Normal file
1144
src/DiskImageD64.pas
Normal file
File diff suppressed because it is too large
Load diff
1312
src/DiskImageFDI.pas
Normal file
1312
src/DiskImageFDI.pas
Normal file
File diff suppressed because it is too large
Load diff
354
src/DiskImageG64.pas
Normal file
354
src/DiskImageG64.pas
Normal file
|
|
@ -0,0 +1,354 @@
|
|||
(*
|
||||
** This file is part of the Micro64 Disk Tool.
|
||||
** Copyright (C) 2002-2013 by Benjamin Rosseaux
|
||||
**
|
||||
** The source code of the Micro64 Disk Tool and helper tools are
|
||||
** distributed under the Library GNU General Public License
|
||||
** (see the file COPYING) with the following modification:
|
||||
**
|
||||
** As a special exception, the copyright holders of this software give you
|
||||
** permission to link this software with independent modules to produce
|
||||
** an executable, regardless of the license terms of these independent modules,
|
||||
** and to copy and distribute the resulting executable under terms of your
|
||||
** choice, provided that you also meet, for each linked independent module,
|
||||
** the terms and conditions of the license of that module. An independent
|
||||
** module is a module which is not derived from or based on this software. If
|
||||
** you modify this software, you may extend this exception to your version of
|
||||
** the software, but you are not obligated to do so. If you do not wish to do
|
||||
** so, delete this exception statement from your version.
|
||||
**
|
||||
** If you didn't receive a copy of the file COPYING, contact:
|
||||
** Free Software Foundation
|
||||
** 675 Mass Ave
|
||||
** Cambridge, MA 02139
|
||||
** USA
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
*)
|
||||
unit DiskImageG64;
|
||||
{$IFDEF FPC}
|
||||
{$MODE DELPHI}
|
||||
{$WARNINGS OFF}
|
||||
{$HINTS OFF}
|
||||
{$OVERFLOWCHECKS OFF}
|
||||
{$RANGECHECKS OFF}
|
||||
{$IFDEF CPUI386}
|
||||
{$DEFINE CPU386}
|
||||
{$ASMMODE INTEL}
|
||||
{$ENDIF}
|
||||
{$IFDEF FPC_LITTLE_ENDIAN}
|
||||
{$DEFINE LITTLE_ENDIAN}
|
||||
{$ELSE}
|
||||
{$IFDEF FPC_BIG_ENDIAN}
|
||||
{$DEFINE BIG_ENDIAN}
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
{$ELSE}
|
||||
{$DEFINE LITTLE_ENDIAN}
|
||||
{$IFNDEF CPU64}
|
||||
{$DEFINE CPU32}
|
||||
{$ENDIF}
|
||||
{$OPTIMIZATION ON}
|
||||
{$ENDIF}
|
||||
{$define use64}
|
||||
|
||||
interface
|
||||
|
||||
uses Globals,BeRoStream,GCR;
|
||||
|
||||
function G64IsEmpty(const Data;Len,Threshold:longint;Value:byte):boolean;
|
||||
function G64IsEmptyEx(const Data;Len,Threshold:longint):boolean;
|
||||
function G64CountHalfTracks(const GCR:TGCR):longint;
|
||||
function G64Read(var GCR:TGCR;SrcStream:TBeRoStream):boolean;
|
||||
function G64Write(const GCR:TGCR;DstStream:TBeRoStream):boolean;
|
||||
|
||||
implementation
|
||||
|
||||
function G64IsEmpty(const Data;Len,Threshold:longint;Value:byte):boolean;
|
||||
var p:pbyte;
|
||||
begin
|
||||
result:=true;
|
||||
p:=@Data;
|
||||
while Len>0 do begin
|
||||
dec(Len);
|
||||
if p^<>Value then begin
|
||||
dec(Threshold);
|
||||
if Threshold<0 then begin
|
||||
result:=false;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
inc(p);
|
||||
end;
|
||||
end;
|
||||
|
||||
function G64IsEmptyEx(const Data;Len,Threshold:longint):boolean;
|
||||
var p:pbyte;
|
||||
Value:byte;
|
||||
begin
|
||||
result:=true;
|
||||
if Len>0 then begin
|
||||
p:=@Data;
|
||||
Value:=p^;
|
||||
while Len>0 do begin
|
||||
dec(Len);
|
||||
if p^<>Value then begin
|
||||
dec(Threshold);
|
||||
if Threshold<0 then begin
|
||||
result:=false;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
inc(p);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function G64CountHalfTracks(const GCR:TGCR):longint;
|
||||
var Track:longint;
|
||||
begin
|
||||
result:=0;
|
||||
for Track:=FirstHalfTrack to LastHalfTrack do begin
|
||||
if not G64IsEmpty(GCR.Data[Track*MaxBytesPerGCRHalfTrack],GCR.HalfTrackSize[Track],2,$00) then begin
|
||||
result:=(Track-FirstHalfTrack)+1;
|
||||
end;
|
||||
end;
|
||||
if (result and 1)<>0 then begin
|
||||
result:=result+1;
|
||||
end;
|
||||
if result<70 then begin
|
||||
result:=70;
|
||||
end else if result>84 then begin
|
||||
result:=84;
|
||||
end;
|
||||
end;
|
||||
|
||||
function G64Read(var GCR:TGCR;SrcStream:TBeRoStream):boolean;
|
||||
var ImageHalfTracks,HalfTrack,TrackLen,ZoneLen,i:longint;
|
||||
G64Signature:array[1..8] of ansichar;
|
||||
GCRHalfTracks,GCRHalfTrackSpeeds:array[0..MaxHalfTracks1541] of longword;
|
||||
G64TrackData,G64ZoneData:pbyte;
|
||||
Len:array[0..1] of byte;
|
||||
CompSpeed:PGCRSpeedMap;
|
||||
Buffer:array[0..259] of byte;
|
||||
begin
|
||||
result:=false;
|
||||
|
||||
if SrcStream.Seek(0)<>0 then begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
if SrcStream.Read(G64Signature,sizeof(G64Signature))<>sizeof(G64Signature) then begin
|
||||
exit;
|
||||
end;
|
||||
if G64Signature<>'GCR-1541' then begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
if SrcStream.Read(Buffer,4)<>4 then begin
|
||||
exit;
|
||||
end;
|
||||
if not (Buffer[1] in [(NumTracks1541*2)-1..MaxHalfTracks1541]) then begin
|
||||
exit;
|
||||
end;
|
||||
ImageHalfTracks:=Buffer[1];
|
||||
GCR.HalfTracks:=Buffer[1];
|
||||
GCR.MaximumHalfTrackSize:=Buffer[2] or (Buffer[3] shl 8);
|
||||
|
||||
if SrcStream.Seek(sizeof(TGCRHeader))<>sizeof(TGCRHeader) then begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
FillChar(GCRHalfTracks,SizeOf(GCRHalfTracks),#0);
|
||||
FillChar(GCRHalfTrackSpeeds,SizeOf(GCRHalfTrackSpeeds),#0);
|
||||
if SrcStream.Read(GCRHalfTracks,ImageHalfTracks*sizeof(longword))<>(ImageHalfTracks*sizeof(longword)) then begin
|
||||
exit;
|
||||
end;
|
||||
if SrcStream.Read(GCRHalfTrackSpeeds,ImageHalfTracks*sizeof(longword))<>(ImageHalfTracks*sizeof(longword)) then begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
FillChar(GCR.Data,SizeOf(GCR.Data),#$00);
|
||||
FillChar(GCR.SpeedZone,SizeOf(GCR.SpeedZone),#$00);
|
||||
|
||||
for HalfTrack:=FirstHalfTrack to LastHalfTrack do begin
|
||||
G64TrackData:=@GCR.Data[HalfTrack*MaxBytesPerGCRHalfTrack];
|
||||
G64ZoneData:=@GCR.SpeedZone[HalfTrack*MaxBytesPerGCRHalfTrack];
|
||||
GCR.HalfTrackSize[HalfTrack]:=6250;
|
||||
if (HalfTrack<=ImageHalfTracks) and (GCRHalfTracks[HalfTrack-FirstHalfTrack]<>0) then begin
|
||||
if SrcStream.Seek(GCRHalfTracks[HalfTrack-FirstHalfTrack])<>longint(GCRHalfTracks[HalfTrack-FirstHalfTrack]) then begin
|
||||
exit;
|
||||
end;
|
||||
if SrcStream.Read(Len,sizeof(Len))<>sizeof(Len) then begin
|
||||
exit;
|
||||
end;
|
||||
TrackLen:=Len[0] or (Len[1] shl 8);
|
||||
if (TrackLen<1) or (TrackLen>MaxBytesPerGCRHalfTrack) then begin
|
||||
exit;
|
||||
end;
|
||||
GCR.HalfTrackSize[HalfTrack]:=TrackLen;
|
||||
if SrcStream.Read(G64TrackData^,TrackLen)<>TrackLen then begin
|
||||
exit;
|
||||
end;
|
||||
ZoneLen:=(TrackLen+3) div 4;
|
||||
if GCRHalfTrackSpeeds[HalfTrack-FirstHalfTrack]>3 then begin
|
||||
if SrcStream.Seek(GCRHalfTrackSpeeds[HalfTrack-FirstHalfTrack])<>longint(GCRHalfTrackSpeeds[HalfTrack-FirstHalfTrack]) then begin
|
||||
exit;
|
||||
end;
|
||||
GetMem(CompSpeed,SizeOf(TGCRSpeedMap));
|
||||
FillChar(CompSpeed^,SizeOf(TGCRSpeedMap),AnsiChar(#0));
|
||||
if SrcStream.Read(CompSpeed^,ZoneLen)<>ZoneLen then begin
|
||||
FreeMem(CompSpeed);
|
||||
exit;
|
||||
end;
|
||||
try
|
||||
for i:=0 to ZoneLen-1 do begin
|
||||
PByteArray(G64ZoneData)^[(i*4)+3]:=CompSpeed^[i] and 3;
|
||||
PByteArray(G64ZoneData)^[(i*4)+2]:=(CompSpeed^[i] shr 2) and 3;
|
||||
PByteArray(G64ZoneData)^[(i*4)+1]:=(CompSpeed^[i] shr 4) and 3;
|
||||
PByteArray(G64ZoneData)^[(i*4)+0]:=(CompSpeed^[i] shr 6) and 3;
|
||||
end;
|
||||
finally
|
||||
FreeMem(CompSpeed);
|
||||
end;
|
||||
end else begin
|
||||
FillChar(G64ZoneData^,MaxBytesPerGCRHalfTrack,chr(GCRHalfTrackSpeeds[HalfTrack-FirstHalfTrack]));
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
result:=true;
|
||||
end;
|
||||
|
||||
function G64Write(const GCR:TGCR;DstStream:TBeRoStream):boolean;
|
||||
var HalfTrack,ImageHalfTracks,DataOffset,TrackLen,ZoneLen,Counter,MaximumHalfTrackSize:longint;
|
||||
G64Signature:array[1..8] of ansichar;
|
||||
Buffer:array[0..4] of byte;
|
||||
GCRHalfTracks,GCRHalfTrackSpeeds:array[0..MaxHalfTracks1541] of longword;
|
||||
G64TrackData,G64ZoneData:pbyte;
|
||||
CompSpeed:PGCRSpeedMap;
|
||||
Len:array[0..1] of byte;
|
||||
Zone:byte;
|
||||
Different:boolean;
|
||||
begin
|
||||
result:=false;
|
||||
|
||||
DstStream.Clear;
|
||||
|
||||
if DstStream.Seek(0)<>0 then begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
MaximumHalfTrackSize:=GCR.MaximumHalfTrackSize;
|
||||
|
||||
if MaximumHalfTrackSize=0 then begin
|
||||
for HalfTrack:=FirstHalfTrack to LastHalfTrack do begin
|
||||
G64TrackData:=@GCR.Data[HalfTrack*MaxBytesPerGCRHalfTrack];
|
||||
TrackLen:=GCR.HalfTrackSize[HalfTrack];
|
||||
if (TrackLen<>0) and not G64IsEmpty(G64TrackData^,TrackLen,0,$00) then begin
|
||||
if MaximumHalfTrackSize<TrackLen then begin
|
||||
MaximumHalfTrackSize:=TrackLen;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
G64Signature:='GCR-1541';
|
||||
if DstStream.Write(G64Signature,sizeof(G64Signature))<>sizeof(G64Signature) then begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
ImageHalfTracks:=G64CountHalfTracks(GCR);
|
||||
Buffer[0]:=0;
|
||||
Buffer[1]:=ImageHalfTracks;
|
||||
Buffer[2]:=MaximumHalfTrackSize and $ff;
|
||||
Buffer[3]:=(MaximumHalfTrackSize shr 8) and $ff;
|
||||
if DstStream.Write(Buffer,4)<>4 then begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
FillChar(GCRHalfTracks,SizeOf(GCRHalfTracks),#0);
|
||||
FillChar(GCRHalfTrackSpeeds,SizeOf(GCRHalfTrackSpeeds),#0);
|
||||
|
||||
DataOffset:=DstStream.Position;
|
||||
if DstStream.Write(GCRHalfTracks,ImageHalfTracks*sizeof(longword))<>(ImageHalfTracks*sizeof(longword)) then begin
|
||||
exit;
|
||||
end;
|
||||
if DstStream.Write(GCRHalfTrackSpeeds,ImageHalfTracks*sizeof(longword))<>(ImageHalfTracks*sizeof(longword)) then begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
for HalfTrack:=FirstHalfTrack to LastHalfTrack do begin
|
||||
G64TrackData:=@GCR.Data[HalfTrack*MaxBytesPerGCRHalfTrack];
|
||||
G64ZoneData:=@GCR.SpeedZone[HalfTrack*MaxBytesPerGCRHalfTrack];
|
||||
TrackLen:=GCR.HalfTrackSize[HalfTrack];
|
||||
if (TrackLen<>0) and not G64IsEmpty(G64TrackData^,TrackLen,0,$00) then begin
|
||||
Len[0]:=TrackLen and $ff;
|
||||
Len[1]:=(TrackLen shr 8) and $ff;
|
||||
GCRHalfTracks[HalfTrack-FirstHalfTrack]:=DstStream.Position;
|
||||
if DstStream.Write(Len,sizeof(Len))<>sizeof(Len) then begin
|
||||
exit;
|
||||
end;
|
||||
if DstStream.Write(G64TrackData^,TrackLen)<>TrackLen then begin
|
||||
exit;
|
||||
end;
|
||||
if TrackLen<MaximumHalfTrackSize then begin
|
||||
if DstStream.WriteByteCount($00,MaximumHalfTrackSize-TrackLen)<>(MaximumHalfTrackSize-TrackLen) then begin
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
begin
|
||||
Zone:=byte(pansichar(G64ZoneData)[0]) and 3;
|
||||
Different:=false;
|
||||
for Counter:=1 to TrackLen-1 do begin
|
||||
if (byte(pansichar(G64ZoneData)[Counter]) and 3)<>Zone then begin
|
||||
Different:=true;
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
if Different then begin
|
||||
ZoneLen:=(TrackLen+3) div 4;
|
||||
GetMem(CompSpeed,SizeOf(TGCRSpeedMap));
|
||||
FillChar(CompSpeed^,SizeOf(TGCRSpeedMap),AnsiChar(#0));
|
||||
try
|
||||
for Counter:=0 to ZoneLen-1 do begin
|
||||
CompSpeed^[Counter]:=((PByteArray(G64ZoneData)^[(Counter*4)+3] and 3) shl 0) or
|
||||
((PByteArray(G64ZoneData)^[(Counter*4)+2] and 3) shl 2) or
|
||||
((PByteArray(G64ZoneData)^[(Counter*4)+1] and 3) shl 4) or
|
||||
((PByteArray(G64ZoneData)^[(Counter*4)+0] and 3) shl 6);
|
||||
end;
|
||||
GCRHalfTrackSpeeds[HalfTrack-FirstHalfTrack]:=DstStream.Position;
|
||||
result:=DstStream.Write(CompSpeed^,ZoneLen)=ZoneLen;
|
||||
finally
|
||||
FreeMem(CompSpeed);
|
||||
end;
|
||||
if not result then begin
|
||||
exit;
|
||||
end;
|
||||
end else begin
|
||||
GCRHalfTrackSpeeds[HalfTrack-FirstHalfTrack]:=Zone;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
if DstStream.Seek(DataOffset)<>DataOffset then begin
|
||||
exit;
|
||||
end;
|
||||
if DstStream.Write(GCRHalfTracks,ImageHalfTracks*sizeof(longword))<>(ImageHalfTracks*sizeof(longword)) then begin
|
||||
exit;
|
||||
end;
|
||||
if DstStream.Write(GCRHalfTrackSpeeds,ImageHalfTracks*sizeof(longword))<>(ImageHalfTracks*sizeof(longword)) then begin
|
||||
exit;
|
||||
end;
|
||||
if DstStream.Seek(DstStream.Size)<>DstStream.Size then begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
result:=true;
|
||||
end;
|
||||
|
||||
end.
|
||||
684
src/DiskImageKryofluxStream.pas
Normal file
684
src/DiskImageKryofluxStream.pas
Normal file
|
|
@ -0,0 +1,684 @@
|
|||
(*
|
||||
** This file is part of the Micro64 Disk Tool.
|
||||
** Copyright (C) 2002-2013 by Benjamin Rosseaux
|
||||
**
|
||||
** The source code of the Micro64 Disk Tool and helper tools are
|
||||
** distributed under the Library GNU General Public License
|
||||
** (see the file COPYING) with the following modification:
|
||||
**
|
||||
** As a special exception, the copyright holders of this software give you
|
||||
** permission to link this software with independent modules to produce
|
||||
** an executable, regardless of the license terms of these independent modules,
|
||||
** and to copy and distribute the resulting executable under terms of your
|
||||
** choice, provided that you also meet, for each linked independent module,
|
||||
** the terms and conditions of the license of that module. An independent
|
||||
** module is a module which is not derived from or based on this software. If
|
||||
** you modify this software, you may extend this exception to your version of
|
||||
** the software, but you are not obligated to do so. If you do not wish to do
|
||||
** so, delete this exception statement from your version.
|
||||
**
|
||||
** If you didn't receive a copy of the file COPYING, contact:
|
||||
** Free Software Foundation
|
||||
** 675 Mass Ave
|
||||
** Cambridge, MA 02139
|
||||
** USA
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
*)
|
||||
unit DiskImageKryofluxStream;
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}
|
||||
{$ifdef cpui386}
|
||||
{$define cpu386}
|
||||
{$endif}
|
||||
{$ifdef cpu386}
|
||||
{$asmmode intel}
|
||||
{$endif}
|
||||
{$ifdef cpuamd64}
|
||||
{$asmmode intel}
|
||||
{$endif}
|
||||
{$ifdef FPC_LITTLE_ENDIAN}
|
||||
{$define LITTLE_ENDIAN}
|
||||
{$else}
|
||||
{$ifdef FPC_BIG_ENDIAN}
|
||||
{$define BIG_ENDIAN}
|
||||
{$endif}
|
||||
{$endif}
|
||||
{-$pic off}
|
||||
{$define caninline}
|
||||
{$ifdef FPC_HAS_TYPE_EXTENDED}
|
||||
{$define HAS_TYPE_EXTENDED}
|
||||
{$else}
|
||||
{$undef HAS_TYPE_EXTENDED}
|
||||
{$endif}
|
||||
{$ifdef FPC_HAS_TYPE_DOUBLE}
|
||||
{$define HAS_TYPE_DOUBLE}
|
||||
{$else}
|
||||
{$undef HAS_TYPE_DOUBLE}
|
||||
{$endif}
|
||||
{$ifdef FPC_HAS_TYPE_SINGLE}
|
||||
{$define HAS_TYPE_SINGLE}
|
||||
{$else}
|
||||
{$undef HAS_TYPE_SINGLE}
|
||||
{$endif}
|
||||
{$else}
|
||||
{$realcompatibility off}
|
||||
{$localsymbols on}
|
||||
{$define LITTLE_ENDIAN}
|
||||
{$ifndef cpu64}
|
||||
{$define cpu32}
|
||||
{$endif}
|
||||
{$define HAS_TYPE_EXTENDED}
|
||||
{$define HAS_TYPE_DOUBLE}
|
||||
{$define HAS_TYPE_SINGLE}
|
||||
{$endif}
|
||||
{$ifdef win32}
|
||||
{$define windows}
|
||||
{$endif}
|
||||
{$ifdef win64}
|
||||
{$define windows}
|
||||
{$endif}
|
||||
{$ifdef wince}
|
||||
{$define windows}
|
||||
{$endif}
|
||||
{$rangechecks off}
|
||||
{$extendedsyntax on}
|
||||
{$writeableconst on}
|
||||
{$hints off}
|
||||
{$booleval off}
|
||||
{$typedaddress off}
|
||||
{$stackframes off}
|
||||
{$varstringchecks on}
|
||||
{$typeinfo on}
|
||||
{$overflowchecks off}
|
||||
{$longstrings on}
|
||||
{$openstrings on}
|
||||
|
||||
interface
|
||||
|
||||
uses SysUtils,Classes,BeRoStream,Math;
|
||||
|
||||
function ConvertKryofluxStream(Prefix,OutputFileName:ansistring;Side,FDI,DoubleWideTracks:boolean;TargetRPM:double):boolean;
|
||||
|
||||
implementation
|
||||
|
||||
uses DiskImageP64,DiskImageFDI;
|
||||
|
||||
{$ifdef fpc}
|
||||
{$undef OldDelphi}
|
||||
{$else}
|
||||
{$ifdef conditionalexpressions}
|
||||
{$if CompilerVersion>=23.0}
|
||||
{$undef OldDelphi}
|
||||
type qword=uint64;
|
||||
ptruint=NativeUInt;
|
||||
ptrint=NativeInt;
|
||||
{$else}
|
||||
{$define OldDelphi}
|
||||
{$ifend}
|
||||
{$else}
|
||||
{$define OldDelphi}
|
||||
{$endif}
|
||||
{$endif}
|
||||
{$ifdef OldDelphi}
|
||||
type qword=int64;
|
||||
{$ifdef cpu64}
|
||||
ptruint=qword;
|
||||
ptrint=int64;
|
||||
{$else}
|
||||
ptruint=longword;
|
||||
ptrint=longint;
|
||||
{$endif}
|
||||
{$endif}
|
||||
|
||||
function RoundUpToPowerOfTwo(x:ptruint):ptruint; {$ifdef caninline}inline;{$endif}
|
||||
begin
|
||||
dec(x);
|
||||
x:=x or (x shr 1);
|
||||
x:=x or (x shr 2);
|
||||
x:=x or (x shr 4);
|
||||
x:=x or (x shr 8);
|
||||
x:=x or (x shr 16);
|
||||
{$ifdef cpu64}
|
||||
x:=x or (x shr 32);
|
||||
{$endif}
|
||||
result:=x+1;
|
||||
end;
|
||||
|
||||
type TPulses=array of longword;
|
||||
|
||||
procedure QuickSortPulses(var Pulses:TPulses;PulsesLeft,PulsesRight:longint);
|
||||
var Left,Right:longint;
|
||||
Pivot,Pulse:longword;
|
||||
begin
|
||||
Left:=PulsesLeft;
|
||||
Right:=PulsesRight;
|
||||
Pivot:=Pulses[(Left+Right) div 2];
|
||||
repeat
|
||||
while Pulses[Left]<Pivot do begin
|
||||
inc(Left);
|
||||
end;
|
||||
while Pulses[Right]>Pivot do begin
|
||||
dec(Right);
|
||||
end;
|
||||
if Left<=Right then begin
|
||||
Pulse:=Pulses[Left];
|
||||
Pulses[Left]:=Pulses[Right];
|
||||
Pulses[Right]:=Pulse;
|
||||
inc(Left);
|
||||
dec(Right);
|
||||
end;
|
||||
until Left>Right;
|
||||
if Right>PulsesLeft then begin
|
||||
QuickSortPulses(Pulses,PulsesLeft,Right);
|
||||
end;
|
||||
if Left<PulsesRight then begin
|
||||
QuickSortPulses(Pulses,Left,PulsesRight);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure LoadRAW(Stream:TStream;Backward:boolean;var PulseValues:TPulses;TargetRPM:double);
|
||||
const kryo_mck=((18432000*73)/14)/2;
|
||||
kryo_sck=kryo_mck/2;
|
||||
kryo_ick=kryo_mck/16;
|
||||
type TFloat={$ifdef HAS_TYPE_EXTENDED}extended{$else}double{$endif};
|
||||
TIndex=record
|
||||
StreamPosition:longword;
|
||||
Timer:longword;
|
||||
SystemTimer:longword;
|
||||
CellPosition:longint;
|
||||
IndexTime:longword;
|
||||
PreIndexCellTime:longword;
|
||||
PostIndexCellTime:longword;
|
||||
FluxIndex:longint;
|
||||
PreIndexCellTimePercent:TFloat;
|
||||
PostIndexCellTimePercent:TFloat;
|
||||
RPM:TFloat;
|
||||
BitIndex:longword;
|
||||
ByteIndex:longword;
|
||||
PreBitCount:longword;
|
||||
PostBitCount:longword;
|
||||
DeltaSinceIndexSignal:int64;
|
||||
end;
|
||||
TCell=record
|
||||
CyclePosition:longword;
|
||||
StreamPosition:longword;
|
||||
Delta:qword;
|
||||
end;
|
||||
var OBBStream:TMemoryStream;
|
||||
OBBType:byte;
|
||||
OBBLen:longint;
|
||||
CellValues:array of TCell;
|
||||
CellCount:longint;
|
||||
PulseCount:longint;
|
||||
IndexValues:array of TIndex;
|
||||
IndexCount:longint;
|
||||
procedure ReadStream;
|
||||
var Cmd:byte;
|
||||
Done:boolean;
|
||||
NextCellValue,NewCellValue,StreamOffset:longword;
|
||||
Counter:longint;
|
||||
function ReadByte:byte;
|
||||
begin
|
||||
Stream.Read(result,sizeof(byte));
|
||||
end;
|
||||
procedure Skip(Bytes:longint);
|
||||
begin
|
||||
Stream.Seek(Bytes,soFromCurrent);
|
||||
end;
|
||||
procedure OutputCellValue(Value:longword);
|
||||
begin
|
||||
if CellCount>=length(CellValues) then begin
|
||||
SetLength(CellValues,RoundUpToPowerOfTwo(CellCount+16));
|
||||
end;
|
||||
CellValues[CellCount].CyclePosition:=Value;
|
||||
CellValues[CellCount].StreamPosition:=StreamOffset;
|
||||
inc(CellCount);
|
||||
end;
|
||||
function ReadDWordFromOBB:longword;
|
||||
var b:byte;
|
||||
begin
|
||||
OBBStream.Read(b,sizeof(byte));
|
||||
result:=b;
|
||||
OBBStream.Read(b,sizeof(byte));
|
||||
result:=result or (b shl 8);
|
||||
OBBStream.Read(b,sizeof(byte));
|
||||
result:=result or (b shl 16);
|
||||
OBBStream.Read(b,sizeof(byte));
|
||||
result:=result or (b shl 24);
|
||||
end;
|
||||
begin
|
||||
Done:=false;
|
||||
NextCellValue:=0;
|
||||
StreamOffset:=0;
|
||||
while (Stream.Position<Stream.Size) and not Done do begin
|
||||
if StreamOffset<>0 then begin
|
||||
if (IndexCount>0) and (IndexValues[IndexCount-1].StreamPosition=StreamOffset) then begin
|
||||
IndexValues[IndexCount-1].FluxIndex:=CellCount;
|
||||
end else begin
|
||||
for Counter:=0 to IndexCount-1 do begin
|
||||
if (IndexValues[Counter].FluxIndex<0) and (IndexValues[Counter].StreamPosition=StreamOffset) then begin
|
||||
IndexValues[Counter].FluxIndex:=CellCount;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
Cmd:=ReadByte;
|
||||
case Cmd of
|
||||
$00:begin
|
||||
NewCellValue:=ReadByte+NextCellValue;
|
||||
NextCellValue:=0;
|
||||
OutputCellValue(NewCellValue);
|
||||
inc(StreamOffset,2);
|
||||
end;
|
||||
$01..$07:begin
|
||||
NewCellValue:=((Cmd shl 8) or ReadByte)+NextCellValue;
|
||||
NextCellValue:=0;
|
||||
OutputCellValue(NewCellValue);
|
||||
inc(StreamOffset,2);
|
||||
end;
|
||||
$0e..$ff:begin
|
||||
NewCellValue:=Cmd+NextCellValue;
|
||||
NextCellValue:=0;
|
||||
OutputCellValue(NewCellValue);
|
||||
inc(StreamOffset);
|
||||
end;
|
||||
$08:begin
|
||||
inc(StreamOffset);
|
||||
end;
|
||||
$09:begin
|
||||
ReadByte;
|
||||
inc(StreamOffset,2);
|
||||
end;
|
||||
$0a:begin
|
||||
ReadByte;
|
||||
ReadByte;
|
||||
inc(StreamOffset,3);
|
||||
end;
|
||||
$0b:begin
|
||||
inc(NextCellValue,$10000);
|
||||
inc(StreamOffset);
|
||||
end;
|
||||
$0c:begin
|
||||
NewCellValue:=ReadByte shl 8;
|
||||
NewCellValue:=(NewCellValue or ReadByte)+NextCellValue;
|
||||
NextCellValue:=0;
|
||||
OutputCellValue(NewCellValue);
|
||||
inc(StreamOffset,3);
|
||||
end;
|
||||
$0d:begin
|
||||
OBBType:=ReadByte;
|
||||
OBBLen:=ReadByte;
|
||||
OBBLen:=OBBLen or (ReadByte shl 8);
|
||||
OBBStream:=TMemoryStream.Create;
|
||||
try
|
||||
if OBBType<>$0d then begin
|
||||
OBBStream.CopyFrom(Stream,OBBLen);
|
||||
end;
|
||||
OBBStream.Seek(0,soFromBeginning);
|
||||
case OBBType of
|
||||
$00:begin
|
||||
end;
|
||||
$01:begin
|
||||
// OBB:Stream Read
|
||||
ReadDWordFromOBB;
|
||||
ReadDWordFromOBB;
|
||||
end;
|
||||
$02:begin
|
||||
// OBB:Index
|
||||
if IndexCount>=length(IndexValues) then begin
|
||||
SetLength(IndexValues,RoundUpToPowerOfTwo(IndexCount+16));
|
||||
end;
|
||||
IndexValues[IndexCount].StreamPosition:=ReadDWordFromOBB;
|
||||
IndexValues[IndexCount].Timer:=ReadDWordFromOBB;
|
||||
IndexValues[IndexCount].SystemTimer:=ReadDWordFromOBB;
|
||||
IndexValues[IndexCount].CellPosition:=0;
|
||||
IndexValues[IndexCount].IndexTime:=0;
|
||||
IndexValues[IndexCount].PreIndexCellTime:=0;
|
||||
IndexValues[IndexCount].PostIndexCellTime:=0;
|
||||
IndexValues[IndexCount].FluxIndex:=-1;
|
||||
IndexValues[IndexCount].RPM:=0;
|
||||
inc(IndexCount);
|
||||
end;
|
||||
$03:begin
|
||||
// OBB:Stream End
|
||||
ReadDWordFromOBB;
|
||||
ReadDWordFromOBB;
|
||||
end;
|
||||
$04:begin
|
||||
// OBB:Comment
|
||||
end;
|
||||
$0d:begin
|
||||
// OBB:EOF
|
||||
Done:=true;
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
OBBStream.Free;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
if CellCount>=length(CellValues) then begin
|
||||
SetLength(CellValues,RoundUpToPowerOfTwo(CellCount+16));
|
||||
end;
|
||||
CellValues[CellCount].CyclePosition:=NextCellValue;
|
||||
CellValues[CellCount].StreamPosition:=StreamOffset;
|
||||
SetLength(CellValues,CellCount+1);
|
||||
end;
|
||||
function DecodeIndex:boolean;
|
||||
var IndexPosition,CellPosition,NextCellPosition:longint;
|
||||
IndexTime,NextStreamPosition,IndexCellTime,IndexCellOverflowCount,PreCellOverflowCount,PreIndexCellTime:longword;
|
||||
begin
|
||||
if (IndexCount<3) or (CellCount<1) then begin
|
||||
result:=false;
|
||||
exit;
|
||||
end;
|
||||
IndexTime:=0;
|
||||
IndexPosition:=0;
|
||||
NextStreamPosition:=IndexValues[IndexPosition].StreamPosition;
|
||||
for CellPosition:=0 to CellCount-1 do begin
|
||||
inc(IndexTime,CellValues[CellPosition].CyclePosition);
|
||||
NextCellPosition:=CellPosition+1;
|
||||
if CellValues[NextCellPosition].StreamPosition<NextStreamPosition then begin
|
||||
continue;
|
||||
end;
|
||||
if (CellPosition=0) and (CellValues[NextCellPosition].StreamPosition>=NextStreamPosition) then begin
|
||||
NextCellPosition:=0;
|
||||
end;
|
||||
if IndexPosition<IndexCount then begin
|
||||
IndexValues[IndexPosition].CellPosition:=NextCellPosition;
|
||||
IndexCellTime:=CellValues[NextCellPosition].CyclePosition;
|
||||
if IndexValues[IndexPosition].Timer=0 then begin
|
||||
IndexValues[IndexPosition].Timer:=IndexCellTime;
|
||||
end;
|
||||
if (NextCellPosition>=CellCount) and (CellValues[NextCellPosition].StreamPosition=NextStreamPosition) then begin
|
||||
inc(IndexCellTime,IndexValues[IndexPosition].Timer);
|
||||
CellValues[NextCellPosition].CyclePosition:=IndexCellTime;
|
||||
end;
|
||||
IndexCellOverflowCount:=IndexCellTime shr 16;
|
||||
PreCellOverflowCount:=CellValues[NextCellPosition].StreamPosition-NextStreamPosition;
|
||||
if IndexCellOverflowCount<PreCellOverflowCount then begin
|
||||
result:=false;
|
||||
exit;
|
||||
end;
|
||||
PreIndexCellTime:=((IndexCellOverflowCount-PreCellOverflowCount) shl 16)+IndexValues[IndexPosition].Timer;
|
||||
IndexValues[IndexPosition].PreIndexCellTime:=PreIndexCellTime;
|
||||
IndexValues[IndexPosition].PostIndexCellTime:=IndexCellTime-PreIndexCellTime;
|
||||
if IndexPosition<>0 then begin
|
||||
dec(IndexTime,IndexValues[IndexPosition-1].PreIndexCellTime);
|
||||
end;
|
||||
if NextCellPosition<>0 then begin
|
||||
IndexValues[IndexPosition].IndexTime:=IndexTime+PreIndexCellTime;
|
||||
end else begin
|
||||
IndexValues[IndexPosition].IndexTime:=PreIndexCellTime;
|
||||
end;
|
||||
inc(IndexPosition);
|
||||
if IndexPosition<IndexCount then begin
|
||||
NextStreamPosition:=IndexValues[IndexPosition].StreamPosition;
|
||||
end else begin
|
||||
NextStreamPosition:=0;
|
||||
end;
|
||||
if NextCellPosition<>0 then begin
|
||||
IndexTime:=0;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
if IndexPosition<IndexCount then begin
|
||||
result:=false;
|
||||
exit;
|
||||
end;
|
||||
if IndexValues[IndexPosition-1].CellPosition>=CellCount then begin
|
||||
if CellCount>=length(CellValues) then begin
|
||||
SetLength(CellValues,RoundUpToPowerOfTwo(CellCount+16));
|
||||
end;
|
||||
CellValues[CellCount].CyclePosition:=IndexTime;
|
||||
CellValues[CellCount].StreamPosition:=NextStreamPosition;
|
||||
inc(CellCount);
|
||||
end;
|
||||
result:=true;
|
||||
end;
|
||||
procedure ConvertIndex;
|
||||
var IndexPosition:longint;
|
||||
Delta:longword;
|
||||
PreCycle,PostCycle,AllCycle,PreIndexCellPercent,RPM,FloatDelta:TFloat;
|
||||
begin
|
||||
RPM:=360;
|
||||
for IndexPosition:=0 to IndexCount-1 do begin
|
||||
PreCycle:=IndexValues[IndexPosition].PreIndexCellTime;
|
||||
PostCycle:=IndexValues[IndexPosition].PostIndexCellTime;
|
||||
AllCycle:=PreCycle+PostCycle;
|
||||
PreIndexCellPercent:=PreCycle/AllCycle;
|
||||
IndexValues[IndexPosition].PreIndexCellTimePercent:=PreIndexCellPercent;
|
||||
IndexValues[IndexPosition].PostIndexCellTimePercent:=1.0-PreIndexCellPercent;
|
||||
if IndexPosition<>0 then begin
|
||||
Delta:=IndexValues[IndexPosition].SystemTimer-IndexValues[IndexPosition-1].SystemTimer;
|
||||
if Delta<>0 then begin
|
||||
RPM:=(kryo_ick*60)/Delta;
|
||||
end;
|
||||
IndexValues[IndexPosition].RPM:=RPM;
|
||||
end;
|
||||
IndexValues[IndexPosition].BitIndex:=0;
|
||||
IndexValues[IndexPosition].ByteIndex:=0;
|
||||
IndexValues[IndexPosition].PreBitCount:=0;
|
||||
IndexValues[IndexPosition].PostBitCount:=0;
|
||||
end;
|
||||
if IndexCount<2 then begin
|
||||
IndexValues[0].RPM:=0;
|
||||
end else begin
|
||||
IndexValues[0].RPM:=IndexValues[1].RPM;
|
||||
end;
|
||||
for IndexPosition:=0 to IndexCount-1 do begin
|
||||
FloatDelta:=((IndexValues[IndexPosition].PostIndexCellTime/kryo_sck)*(IndexValues[IndexPosition].RPM/TargetRPM))*16000000;
|
||||
IndexValues[IndexPosition].DeltaSinceIndexSignal:=(qword(int64(trunc(FloatDelta))) shl 32)+trunc(frac(FloatDelta)*$100000000);
|
||||
end;
|
||||
end;
|
||||
procedure ConvertCellTime;
|
||||
var IndexPosition,CellPosition,RPMPosition:longint;
|
||||
RPM,RPMOffset,RPMStep,Delta:TFloat;
|
||||
begin
|
||||
IndexPosition:=0;
|
||||
RPMOffset:=IndexValues[IndexPosition].RPM;
|
||||
RPMStep:=0;
|
||||
RPMPosition:=0;
|
||||
for CellPosition:=0 to CellCount-1 do begin
|
||||
if (CellPosition=IndexValues[IndexPosition].CellPosition) and ((IndexPosition+1)<IndexCount) then begin
|
||||
RPMOffset:=IndexValues[IndexPosition].RPM;
|
||||
RPMStep:=(IndexValues[IndexPosition+1].RPM-IndexValues[IndexPosition].RPM)/(IndexValues[IndexPosition+1].CellPosition-IndexValues[IndexPosition].CellPosition);
|
||||
RPMPosition:=0;
|
||||
end;
|
||||
RPM:=RPMOffset+(RPMStep*RPMPosition);
|
||||
inc(RPMPosition);
|
||||
Delta:=((CellValues[CellPosition].CyclePosition/kryo_sck)*(RPM/TargetRPM))*16000000;
|
||||
CellValues[CellPosition].Delta:=(qword(int64(trunc(Delta))) shl 32)+trunc(frac(Delta)*$100000000);
|
||||
end;
|
||||
end;
|
||||
procedure DoCollect(WhichIndex:longint);
|
||||
var CellPosition,PulsePosition:longint;
|
||||
Position:int64;
|
||||
MustSort:boolean;
|
||||
begin
|
||||
while (WhichIndex+1)>=IndexCount do begin
|
||||
dec(WhichIndex);
|
||||
end;
|
||||
while WhichIndex<0 do begin
|
||||
inc(WhichIndex);
|
||||
end;
|
||||
MustSort:=false;
|
||||
PulseCount:=0;
|
||||
if IndexValues[WhichIndex].CellPosition<IndexValues[WhichIndex+1].CellPosition then begin
|
||||
SetLength(PulseValues,(IndexValues[WhichIndex+1].CellPosition-IndexValues[WhichIndex].CellPosition)+1);
|
||||
Position:=0;
|
||||
for CellPosition:=IndexValues[WhichIndex].CellPosition to IndexValues[WhichIndex+1].CellPosition do begin
|
||||
inc(Position,CellValues[CellPosition].Delta);
|
||||
if Position>=0 then begin
|
||||
if (Position shr 32)>=P64PulseSamplesPerRotation then begin
|
||||
break;
|
||||
end else begin
|
||||
PulsePosition:=(Position+IndexValues[WhichIndex].DeltaSinceIndexSignal) shr 32;
|
||||
if PulsePosition>=P64PulseSamplesPerRotation then begin
|
||||
repeat
|
||||
dec(PulsePosition,P64PulseSamplesPerRotation);
|
||||
until PulsePosition<P64PulseSamplesPerRotation;
|
||||
MustSort:=true;
|
||||
end;
|
||||
PulseValues[PulseCount]:=PulsePosition;
|
||||
inc(PulseCount);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
SetLength(PulseValues,PulseCount);
|
||||
if MustSort and (PulseCount>1) then begin
|
||||
QuickSortPulses(PulseValues,0,PulseCount-1);
|
||||
end;
|
||||
end;
|
||||
const NewFPUExceptionMask:TFPUExceptionMask=[exInvalidOp,exDenormalized,exZeroDivide,exOverflow,exUnderflow,exPrecision];
|
||||
NewFPURoundingMode:TFPURoundingMode=rmNEAREST;
|
||||
NewFPUPrecisionMode:TFPUPrecisionMode={$ifdef HAS_TYPE_EXTENDED}pmEXTENDED{$else}pmDOUBLE{$endif};
|
||||
var Counter,WhichIndex:longint;
|
||||
OldFPUExceptionMask:TFPUExceptionMask;
|
||||
OldFPURoundingMode:TFPURoundingMode;
|
||||
OldFPUPrecisionMode:TFPUPrecisionMode;
|
||||
begin
|
||||
OldFPUExceptionMask:=GetExceptionMask;
|
||||
OldFPURoundingMode:=GetRoundMode;
|
||||
OldFPUPrecisionMode:=GetPrecisionMode;
|
||||
try
|
||||
if OldFPUExceptionMask<>NewFPUExceptionMask then begin
|
||||
SetExceptionMask(NewFPUExceptionMask);
|
||||
end;
|
||||
if OldFPURoundingMode<>NewFPURoundingMode then begin
|
||||
SetRoundMode(NewFPURoundingMode);
|
||||
end;
|
||||
if OldFPUPrecisionMode<>NewFPUPrecisionMode then begin
|
||||
SetPrecisionMode(NewFPUPrecisionMode);
|
||||
end;
|
||||
CellValues:=nil;
|
||||
CellCount:=0;
|
||||
PulseValues:=nil;
|
||||
PulseCount:=0;
|
||||
IndexValues:=nil;
|
||||
IndexCount:=0;
|
||||
try
|
||||
ReadStream;
|
||||
|
||||
if DecodeIndex then begin
|
||||
|
||||
ConvertIndex;
|
||||
ConvertCellTime;
|
||||
|
||||
// Try first the middle index
|
||||
WhichIndex:=(IndexCount+1) div 2;
|
||||
while (WhichIndex+1)>=(IndexCount-1) do begin
|
||||
dec(WhichIndex);
|
||||
end;
|
||||
while WhichIndex<1 do begin
|
||||
inc(WhichIndex);
|
||||
end;
|
||||
|
||||
DoCollect(WhichIndex);
|
||||
|
||||
if Backward then begin
|
||||
for Counter:=0 to PulseCount-1 do begin
|
||||
PulseValues[Counter]:=P64PulseSamplesPerRotation-(PulseValues[Counter]+1);
|
||||
end;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
finally
|
||||
SetLength(CellValues,0);
|
||||
SetLength(IndexValues,0);
|
||||
end;
|
||||
finally
|
||||
if OldFPUExceptionMask<>NewFPUExceptionMask then begin
|
||||
SetExceptionMask(OldFPUExceptionMask);
|
||||
end;
|
||||
if OldFPURoundingMode<>NewFPURoundingMode then begin
|
||||
SetRoundMode(OldFPURoundingMode);
|
||||
end;
|
||||
if OldFPUPrecisionMode<>NewFPUPrecisionMode then begin
|
||||
SetPrecisionMode(OldFPUPrecisionMode);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ConvertKryofluxStream(Prefix,OutputFileName:ansistring;Side,FDI,DoubleWideTracks:boolean;TargetRPM:double):boolean;
|
||||
var Stream:TStream;
|
||||
MemoryStream:TMemoryStream;
|
||||
StreamEx:TBeRoStream;
|
||||
Pulses:array[0..85] of TPulses;
|
||||
Counter,SubCounter:longint;
|
||||
FileName:ansistring;
|
||||
P64Image:TP64Image;
|
||||
begin
|
||||
FillChar(Pulses,SizeOf(TPulses),#0);
|
||||
for Counter:=2 to 85 do begin
|
||||
FileName:=AnsiString(IntToStr(Counter-2));
|
||||
if length(FileName)<2 then begin
|
||||
FileName:='0'+FileName;
|
||||
end;
|
||||
if Side then begin
|
||||
FileName:=FileName+'.1';
|
||||
end else begin
|
||||
FileName:=FileName+'.0';
|
||||
end;
|
||||
FileName:=Prefix+FileName+'.raw';
|
||||
if FileExists(String(FileName)) then begin
|
||||
Stream:=TFileStream.Create(String(FileName),fmOpenRead);
|
||||
try
|
||||
MemoryStream:=TMemoryStream.Create;
|
||||
try
|
||||
MemoryStream.LoadFromStream(Stream);
|
||||
MemoryStream.Seek(0,soFromBeginning);
|
||||
LoadRAW(MemoryStream,Side,Pulses[Counter],TargetRPM);
|
||||
finally
|
||||
MemoryStream.Free;
|
||||
end;
|
||||
finally
|
||||
Stream.Free;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
P64Image:=TP64Image.Create;
|
||||
try
|
||||
for Counter:=0 to 85 do begin
|
||||
for SubCounter:=0 to length(Pulses[Counter])-1 do begin
|
||||
if Pulses[Counter,SubCounter]<P64PulseSamplesPerRotation then begin
|
||||
P64Image.PulseStreams[Counter].AddPulse(Pulses[Counter,SubCounter],$ffffffff);
|
||||
if DoubleWideTracks and ((Counter and 1)=0) and (Counter<85) then begin
|
||||
P64Image.PulseStreams[Counter+1].AddPulse(Pulses[Counter,SubCounter],$ffffffff);
|
||||
end;
|
||||
end else begin
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
if FDI then begin
|
||||
StreamEx:=TBeRoFileStream.CreateNew(OutputFileName);
|
||||
try
|
||||
result:=FDIWrite(P64Image,StreamEx);
|
||||
finally
|
||||
StreamEx.Free;
|
||||
end;
|
||||
end else begin
|
||||
Stream:=TFileStream.Create(String(OutputFileName),fmCreate);
|
||||
try
|
||||
result:=P64Image.WriteToStream(Stream);
|
||||
finally
|
||||
Stream.Free;
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
P64Image.Free;
|
||||
end;
|
||||
for Counter:=0 to 85 do begin
|
||||
SetLength(Pulses[Counter],0);
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
346
src/DiskImageNIB.pas
Normal file
346
src/DiskImageNIB.pas
Normal file
|
|
@ -0,0 +1,346 @@
|
|||
(*
|
||||
** This file is part of the Micro64 Disk Tool.
|
||||
** Copyright (C) 2002-2013 by Benjamin Rosseaux
|
||||
**
|
||||
** The source code of the Micro64 Disk Tool and helper tools are
|
||||
** distributed under the Library GNU General Public License
|
||||
** (see the file COPYING) with the following modification:
|
||||
**
|
||||
** As a special exception, the copyright holders of this software give you
|
||||
** permission to link this software with independent modules to produce
|
||||
** an executable, regardless of the license terms of these independent modules,
|
||||
** and to copy and distribute the resulting executable under terms of your
|
||||
** choice, provided that you also meet, for each linked independent module,
|
||||
** the terms and conditions of the license of that module. An independent
|
||||
** module is a module which is not derived from or based on this software. If
|
||||
** you modify this software, you may extend this exception to your version of
|
||||
** the software, but you are not obligated to do so. If you do not wish to do
|
||||
** so, delete this exception statement from your version.
|
||||
**
|
||||
** If you didn't receive a copy of the file COPYING, contact:
|
||||
** Free Software Foundation
|
||||
** 675 Mass Ave
|
||||
** Cambridge, MA 02139
|
||||
** USA
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
*)
|
||||
unit DiskImageNIB;
|
||||
{$IFDEF FPC}
|
||||
{$MODE DELPHI}
|
||||
{$WARNINGS OFF}
|
||||
{$HINTS OFF}
|
||||
{$OVERFLOWCHECKS OFF}
|
||||
{$RANGECHECKS OFF}
|
||||
{$IFDEF CPUI386}
|
||||
{$DEFINE CPU386}
|
||||
{$ASMMODE INTEL}
|
||||
{$ENDIF}
|
||||
{$IFDEF FPC_LITTLE_ENDIAN}
|
||||
{$DEFINE LITTLE_ENDIAN}
|
||||
{$ELSE}
|
||||
{$IFDEF FPC_BIG_ENDIAN}
|
||||
{$DEFINE BIG_ENDIAN}
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
{$ELSE}
|
||||
{$DEFINE LITTLE_ENDIAN}
|
||||
{$IFNDEF CPU64}
|
||||
{$DEFINE CPU32}
|
||||
{$ENDIF}
|
||||
{$OPTIMIZATION ON}
|
||||
{$ENDIF}
|
||||
{$define use64}
|
||||
|
||||
interface
|
||||
|
||||
uses SysUtils,BeRoStream,BeRoUtils,Classes,GCR;
|
||||
|
||||
type TNIBSignature=array[0..12] of ansichar;
|
||||
|
||||
const NIBSignature:TNIBSignature='MNIB-1541-RAW';
|
||||
|
||||
MNIB_TRACK_LENGTH=$2000;
|
||||
MIN_TRACK_LENGTH=$1780;
|
||||
MATCH_LENGTH=7;
|
||||
|
||||
function NIBRead(var GCR:TGCR;Stream:TBeRoStream):boolean;
|
||||
|
||||
function ConvertNIBtoG64(SrcStream,DstStream:TBeRoStream):boolean;
|
||||
|
||||
implementation
|
||||
|
||||
uses DiskImageG64;
|
||||
|
||||
function Equals(Data:pansichar;FromPos,ToPos,Len:longint):boolean;
|
||||
var i:longint;
|
||||
begin
|
||||
result:=true;
|
||||
for i:=0 to Len-1 do begin
|
||||
if Data[FromPos+i]<>Data[ToPos+i] then begin
|
||||
result:=false;
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function FindSync(Data:pansichar;Pos,GCREnd:longint):longint;
|
||||
begin
|
||||
while true do begin
|
||||
if (Pos+1)>=GCREnd then begin
|
||||
result:=-1;
|
||||
exit;
|
||||
end;
|
||||
if ((byte(Data[Pos+0]) and 3)=3) and (byte(Data[Pos+1])=$ff) then begin
|
||||
break;
|
||||
end;
|
||||
inc(Pos);
|
||||
end;
|
||||
inc(Pos);
|
||||
while (Pos<GCREnd) and (Data[Pos+1]=#$ff) do begin
|
||||
inc(Pos);
|
||||
end;
|
||||
if Pos<GCREnd then begin
|
||||
result:=Pos;
|
||||
end else begin
|
||||
result:=-1;
|
||||
end;
|
||||
end;
|
||||
|
||||
function FindSector0(Data:pansichar;TrackLen:longint):longint;
|
||||
var Pos,BufferEnd:longint;
|
||||
begin
|
||||
Pos:=0;
|
||||
BufferEnd:=(TrackLen shl 1)-10;
|
||||
|
||||
while Pos<BufferEnd do begin
|
||||
Pos:=FindSync(Data,Pos,BufferEnd);
|
||||
if Pos<0 then begin
|
||||
break;
|
||||
end;
|
||||
if (Data[Pos+0]=#$52) and ((byte(Data[Pos+1]) and $c0)=$40) and ((byte(Data[Pos+2]) and $0f)=$05) and ((byte(Data[Pos+3]) and $fc)=$28) then begin
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
|
||||
repeat
|
||||
dec(Pos);
|
||||
if Pos<=0 then begin
|
||||
inc(Pos,TrackLen);
|
||||
end;
|
||||
until Data[Pos]<>#$ff;
|
||||
|
||||
inc(Pos);
|
||||
while Pos>=TrackLen do begin
|
||||
dec(Pos,TrackLen);
|
||||
end;
|
||||
|
||||
result:=Pos;
|
||||
end;
|
||||
|
||||
function FindSectorGap(Data:pansichar;TrackLen:longint):longint;
|
||||
var SyncMax,Pos,BufferEnd,SyncLast,MaxGap,Gap:longint;
|
||||
begin
|
||||
SyncMax:=0;
|
||||
Pos:=0;
|
||||
BufferEnd:=(TrackLen shl 1)-10;
|
||||
|
||||
Pos:=FindSync(Data,Pos,BufferEnd);
|
||||
if Pos<0 then begin
|
||||
result:=-1;
|
||||
exit;
|
||||
end;
|
||||
|
||||
SyncLast:=Pos;
|
||||
MaxGap:=0;
|
||||
while Pos<BufferEnd do begin
|
||||
Pos:=FindSync(Data,Pos,BufferEnd);
|
||||
if Pos<0 then begin
|
||||
break;
|
||||
end;
|
||||
Gap:=Pos-SyncLast;
|
||||
if MaxGap<Gap then begin
|
||||
MaxGap:=Gap;
|
||||
SyncMax:=Pos;
|
||||
end;
|
||||
SyncLast:=Pos;
|
||||
end;
|
||||
|
||||
if MaxGap=0 then begin
|
||||
result:=-1;
|
||||
exit;
|
||||
end;
|
||||
|
||||
Pos:=SyncMax;
|
||||
repeat
|
||||
dec(Pos);
|
||||
if Pos<=0 then begin
|
||||
inc(Pos,TrackLen);
|
||||
end;
|
||||
until Data[Pos]<>#$ff;
|
||||
|
||||
inc(Pos);
|
||||
while Pos>=TrackLen do begin
|
||||
dec(Pos,TrackLen);
|
||||
end;
|
||||
|
||||
result:=Pos;
|
||||
end;
|
||||
|
||||
function FindTrackCycle(Data:pansichar;var CycleStart,CycleStop:longint):longint;
|
||||
var NIBTrack,StopPos,StartPos,SyncPos,p1,CyclePos,p2:longint;
|
||||
begin
|
||||
NIBTrack:=CycleStart;
|
||||
StopPos:=(NIBTrack+MNIB_TRACK_LENGTH)-MATCH_LENGTH;
|
||||
StartPos:=NIBTrack;
|
||||
while true do begin
|
||||
SyncPos:=StartPos+MIN_TRACK_LENGTH;
|
||||
if SyncPos>=StopPos then begin
|
||||
CycleStop:=CycleStart;
|
||||
result:=0;
|
||||
exit;
|
||||
end;
|
||||
while true do begin
|
||||
SyncPos:=FindSync(Data,SyncPos,StopPos);
|
||||
if SyncPos<0 then begin
|
||||
break;
|
||||
end;
|
||||
p1:=StartPos;
|
||||
CyclePos:=SyncPos;
|
||||
p2:=CyclePos;
|
||||
while p2<StopPos do begin
|
||||
if not Equals(Data,p1,p2,MATCH_LENGTH) then begin
|
||||
CyclePos:=-1;
|
||||
break;
|
||||
end;
|
||||
p1:=FindSync(Data,p1,StopPos);
|
||||
if p1<0 then begin
|
||||
break;
|
||||
end;
|
||||
p2:=FindSync(Data,p2,StopPos);
|
||||
if p2<0 then begin
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
if CyclePos>=0 then begin
|
||||
CycleStart:=StartPos;
|
||||
CycleStop:=CyclePos;
|
||||
result:=CyclePos-StartPos;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
StartPos:=FindSync(Data,StartPos,StopPos);
|
||||
if StartPos<0 then begin
|
||||
StartPos:=StopPos;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function NIBRead(var GCR:TGCR;Stream:TBeRoStream):boolean;
|
||||
var FileNIBSignature:TNIBSignature;
|
||||
HalfTrack,CycleStart,CycleStop,Sector0Pos,SectorGapPos,TrackLen,HeaderOffset:longint;
|
||||
Header:array[0..$ff] of byte;
|
||||
Buffer,OtherBuffer,G64TrackData,G64ZoneData:pointer;
|
||||
begin
|
||||
result:=false;
|
||||
|
||||
if Stream.Seek(0)<>0 then begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
if Stream.Read(FileNIBSignature,SizeOf(TNIBSignature))<>SizeOf(TNIBSignature) then begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
if FileNIBSignature<>NIBSignature then begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
if Stream.Seek(0)<>0 then begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
if Stream.Read(Header,SizeOf(Header))<>SizeOf(Header) then begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
GetMem(Buffer,$2000+MaxBytesPerGCRHalfTrack);
|
||||
GetMem(OtherBuffer,$8000+MaxBytesPerGCRHalfTrack);
|
||||
|
||||
FillChar(GCR.Data,SizeOf(GCR.Data),#$00);
|
||||
FillChar(GCR.SpeedZone,SizeOf(GCR.SpeedZone),#$00);
|
||||
GCR.MaximumHalfTrackSize:=FileMinMaxBytesPerGCRHalfTrack;
|
||||
|
||||
HeaderOffset:=16;
|
||||
for HalfTrack:=2 to 84 do begin
|
||||
G64TrackData:=@GCR.Data[HalfTrack*MaxBytesPerGCRHalfTrack];
|
||||
G64ZoneData:=@GCR.SpeedZone[HalfTrack*MaxBytesPerGCRHalfTrack];
|
||||
GCR.HalfTrackSize[HalfTrack]:=RawTrackSize[SpeedMap[HalfTrack shr 1]];
|
||||
if (Header[HeaderOffset]=HalfTrack) and (Stream.Read(Buffer^,$2000)=$2000) then begin
|
||||
inc(HeaderOffset,2);
|
||||
CycleStart:=0;
|
||||
CycleStop:=0;
|
||||
TrackLen:=FindTrackCycle(Buffer,CycleStart,CycleStop);
|
||||
if TrackLen>0 then begin
|
||||
Move(PAnsiChar(Buffer)[CycleStart],PAnsiChar(OtherBuffer)[0],TrackLen);
|
||||
Move(PAnsiChar(Buffer)[CycleStart],PAnsiChar(OtherBuffer)[TrackLen],TrackLen);
|
||||
|
||||
GCR.HalfTrackSize[HalfTrack]:=TrackLen;
|
||||
FillChar(G64TrackData^,MaxBytesPerGCRHalfTrack,$ff);
|
||||
FillChar(G64ZoneData^,MaxBytesPerGCRHalfTrack,ansichar(byte(Header[17+(HalfTrack-2)] and 3)));
|
||||
|
||||
SectorGapPos:=FindSectorGap(OtherBuffer,TrackLen);
|
||||
if SectorGapPos>=0 then begin
|
||||
Move(PAnsiChar(OtherBuffer)[SectorGapPos],G64TrackData^,TrackLen);
|
||||
end else begin
|
||||
Sector0Pos:=FindSector0(OtherBuffer,TrackLen);
|
||||
if Sector0Pos>=0 then begin
|
||||
Move(PAnsiChar(OtherBuffer)[Sector0Pos],G64TrackData^,TrackLen);
|
||||
end else begin
|
||||
Move(PAnsiChar(OtherBuffer)[0],G64TrackData^,TrackLen);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end else begin
|
||||
TrackLen:=0;
|
||||
end;
|
||||
if TrackLen=0 then begin
|
||||
FillChar(G64TrackData^,MaxBytesPerGCRHalfTrack,$55);
|
||||
FillChar(Buffer^,$2000,$55);
|
||||
byte(Buffer^):=$ff;
|
||||
Move(Buffer^,G64TrackData^,$2000);
|
||||
FillChar(G64ZoneData^,MaxBytesPerGCRHalfTrack,ansichar(byte(SpeedMap[HalfTrack shr 1])));
|
||||
end;
|
||||
if GCR.MaximumHalfTrackSize<TrackLen then begin
|
||||
GCR.MaximumHalfTrackSize:=TrackLen;
|
||||
end;
|
||||
end;
|
||||
|
||||
FreeMem(Buffer);
|
||||
FreeMem(OtherBuffer);
|
||||
|
||||
result:=true;
|
||||
end;
|
||||
|
||||
function ConvertNIBtoG64(SrcStream,DstStream:TBeRoStream):boolean;
|
||||
var GCR:PGCR;
|
||||
begin
|
||||
New(GCR);
|
||||
try
|
||||
result:=NIBRead(GCR^,SrcStream);
|
||||
if result then begin
|
||||
G64Write(GCR^,DstStream);
|
||||
end else begin
|
||||
DstStream.Assign(SrcStream);
|
||||
end;
|
||||
finally
|
||||
if assigned(GCR) then begin
|
||||
Dispose(GCR);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
1415
src/DiskImageP64.pas
Normal file
1415
src/DiskImageP64.pas
Normal file
File diff suppressed because it is too large
Load diff
661
src/GCR.pas
Normal file
661
src/GCR.pas
Normal file
|
|
@ -0,0 +1,661 @@
|
|||
(*
|
||||
** This file is part of the Micro64 Disk Tool.
|
||||
** Copyright (C) 2002-2013 by Benjamin Rosseaux
|
||||
**
|
||||
** The source code of the Micro64 Disk Tool and helper tools are
|
||||
** distributed under the Library GNU General Public License
|
||||
** (see the file COPYING) with the following modification:
|
||||
**
|
||||
** As a special exception, the copyright holders of this software give you
|
||||
** permission to link this software with independent modules to produce
|
||||
** an executable, regardless of the license terms of these independent modules,
|
||||
** and to copy and distribute the resulting executable under terms of your
|
||||
** choice, provided that you also meet, for each linked independent module,
|
||||
** the terms and conditions of the license of that module. An independent
|
||||
** module is a module which is not derived from or based on this software. If
|
||||
** you modify this software, you may extend this exception to your version of
|
||||
** the software, but you are not obligated to do so. If you do not wish to do
|
||||
** so, delete this exception statement from your version.
|
||||
**
|
||||
** If you didn't receive a copy of the file COPYING, contact:
|
||||
** Free Software Foundation
|
||||
** 675 Mass Ave
|
||||
** Cambridge, MA 02139
|
||||
** USA
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
*)
|
||||
unit GCR;
|
||||
{$IFDEF FPC}
|
||||
{$MODE DELPHI}
|
||||
{$WARNINGS OFF}
|
||||
{$HINTS OFF}
|
||||
{$OVERFLOWCHECKS OFF}
|
||||
{$RANGECHECKS OFF}
|
||||
{$IFDEF CPUI386}
|
||||
{$DEFINE CPU386}
|
||||
{$ASMMODE INTEL}
|
||||
{$ENDIF}
|
||||
{$IFDEF FPC_LITTLE_ENDIAN}
|
||||
{$DEFINE LITTLE_ENDIAN}
|
||||
{$ELSE}
|
||||
{$IFDEF FPC_BIG_ENDIAN}
|
||||
{$DEFINE BIG_ENDIAN}
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
{$ELSE}
|
||||
{$DEFINE LITTLE_ENDIAN}
|
||||
{$IFNDEF CPU64}
|
||||
{$DEFINE CPU32}
|
||||
{$ENDIF}
|
||||
{$OPTIMIZATION ON}
|
||||
{$ENDIF}
|
||||
{$J+}
|
||||
|
||||
interface
|
||||
|
||||
uses Globals,BeRoStream;
|
||||
|
||||
const MaxGCRHalfTracks=84;
|
||||
MaxBytesPerGCRHalfTrack=65536;
|
||||
MaxBytesPerGCRHalfTrackMask=MaxBytesPerGCRHalfTrack-1;
|
||||
|
||||
FileMinMaxBytesPerGCRHalfTrack=7928;
|
||||
|
||||
MaxTracks1541=42;
|
||||
|
||||
MaxHalfTracks1541=MaxTracks1541*2;
|
||||
|
||||
FirstHalfTrack=2;
|
||||
LastHalfTrack=FirstHalfTrack+MaxHalfTracks1541-1;
|
||||
|
||||
NumTracks1541=35;
|
||||
ExtTracks1541=40;
|
||||
|
||||
Sectors35=683;
|
||||
Sectors40=768;
|
||||
|
||||
RawTrackSize:array[0..3] of word=(6250,6666,7142,7692);
|
||||
|
||||
SectorCount:array[0..42] of byte=(0,
|
||||
21,21,21,21,21,21,21,21,21,21,
|
||||
21,21,21,21,21,21,21,19,19,19,
|
||||
19,19,19,19,18,18,18,18,18,18,
|
||||
17,17,17,17,17,17,17,17,17,17,
|
||||
17,17);
|
||||
|
||||
SectorOfs:array[0..40] of integer=(0,
|
||||
0,21,42,63,84,105,126,147,168,189,210,
|
||||
231,252,273,294,315,336,357,376,395,
|
||||
414,433,452,471,490,508,526,544,562,
|
||||
580,598,615,632,649,666,683,700,717,
|
||||
734,751);
|
||||
|
||||
TrackSpeedTable:array[0..43] of integer=(13,13,13,13,13,13,13,13,
|
||||
13,13,13,13,13,13,13,13,
|
||||
13,13,14,14,14,14,14,14,
|
||||
14,15,15,15,15,15,15,16,
|
||||
16,16,16,16,16,16,16,16,
|
||||
16,16,16,16);
|
||||
|
||||
SpeedMap:array[0..MaxTracks1541+2] of byte=(3,
|
||||
3,3,3,3,3,3,3,3,3,3,
|
||||
3,3,3,3,3,3,3,2,2,2,
|
||||
2,2,2,2,1,1,1,1,1,1,
|
||||
0,0,0,0,0,
|
||||
2,2,2,2,2,2,2{,0,0,0,0,0,0,0},
|
||||
0,0);
|
||||
|
||||
GCRConvData:array[0..$f] of byte=($0a,$0b,$12,$13,$0e,$0f,$16,$17,$09,$19,$1a,$1b,$0d,$1d,$1e,$15);
|
||||
FromGCRConvData:array[0..$1f] of byte=(0,0,0,0,0,0,0,0,0,8,0,1,0,12,4,5,0,0,2,3,0,15,6,7,0,9,10,11,0,13,14,0);
|
||||
|
||||
type TGCRHalfTrackSizes=array[0..MaxGCRHalfTracks+2] of longint;
|
||||
|
||||
PGCR=^TGCR;
|
||||
TGCR=packed record
|
||||
Data:array[0..((MaxGCRHalfTracks+2)*MaxBytesPerGCRHalfTrack)-1] of byte;
|
||||
SpeedZone:array[0..((MaxGCRHalfTracks+2)*MaxBytesPerGCRHalfTrack)-1] of byte;
|
||||
HalfTrackSize:TGCRHalfTrackSizes;
|
||||
MaximumHalfTrackSize:longint;
|
||||
HalfTracks:byte;
|
||||
end;
|
||||
|
||||
TGCRBytes=array of byte;
|
||||
|
||||
PGCRSpeedMap=^TGCRSpeedMap;
|
||||
TGCRSpeedMap=array[0..((MaxBytesPerGCRHalfTrack+3) shr 2)-1] of byte;
|
||||
|
||||
TGCRHeaderSignature=packed array[0..7] of ansichar;
|
||||
|
||||
PGCRHeader=^TGCRHeader;
|
||||
TGCRHeader=packed record
|
||||
Signature:TGCRHeaderSignature;
|
||||
Version:byte;
|
||||
HalfTracks:byte;
|
||||
TrackSize:word;
|
||||
end;
|
||||
|
||||
PGCRFile=^TGCRFile;
|
||||
TGCRFile=packed record
|
||||
Header:TGCRHeader;
|
||||
Data:TGCR;
|
||||
end;
|
||||
|
||||
const GCRHeaderSignature:TGCRHeaderSignature='GCR-1541';
|
||||
|
||||
procedure GCRConvert4BytesToGCR(var Buffer,Ptr);
|
||||
procedure GCRConvertGCRTo4Bytes(var Buffer,Ptr);
|
||||
procedure GCRConvertSectorToGCR(Buffer,Ptr:pbyte;Track,Sector:longword;DiskID1,DiskID2,ErrorCode:byte);
|
||||
procedure GCRConvertGCRToSector(Buffer,Ptr,GCRTrackPointer:pbyte;GCRTrackSize:longword);
|
||||
procedure GCRByteRealign(GCRTrackPointer:pbyte;GCRTrackSize:longword);
|
||||
function GCRBitsReadSector(GCRTrackPointer:pbyte;GCRTrackSize:longword;var ReadData;Track,Sector:longword):boolean;
|
||||
function GCRFindSectorHeader(Track,Sector:longword;GCRTrackPointer:pbyte;GCRTrackSize:longword):pbyte;
|
||||
function GCRFindSectorData(Offset,GCRTrackPointer:pbyte;GCRTrackSize:longword):pbyte;
|
||||
function GCRReadSector(GCRTrackPointer:pbyte;GCRTrackSize:longword;var ReadData;Track,Sector:longword):boolean;
|
||||
function GCRWriteSector(GCRTrackPointer:pbyte;GCRTrackSize:longword;var WriteData;Track,Sector:longword):boolean;
|
||||
|
||||
implementation
|
||||
|
||||
const RandomSeed:longword=$c6c2de31;
|
||||
RandomSeedA:longword=$7b4d3ce3;
|
||||
RandomSeedB:longword=$8e37ab31;
|
||||
RandomSeedX:longword=$a4254e16;
|
||||
RandomSeedY:longword=$8b24f787;
|
||||
RandomSeedZ:longword=$d719ca32;
|
||||
RandomSeedW:longword=$f784d312;
|
||||
|
||||
function GenerateRandomValue:longword;
|
||||
begin
|
||||
// My own variant of a "kiss it stupid simple" PRNG
|
||||
// A mixture of XorShift128 + LCG + MWC
|
||||
RandomSeed:=((RandomSeed*1664525)+1013904223)*134775813;
|
||||
RandomSeedA:=(65184*(RandomSeedA and 65535))+((RandomSeedA shr 16));
|
||||
RandomSeedB:=(64860*(RandomSeedB and 65535))+((RandomSeedB shr 16));
|
||||
result:=(RandomSeedX xor (RandomSeedX shl 11));
|
||||
RandomSeedX:=RandomSeedY;
|
||||
RandomSeedY:=RandomSeedZ;
|
||||
RandomSeedZ:=RandomSeedW;
|
||||
RandomSeedW:=(RandomSeedW xor (RandomSeedW shr 19)) xor (result xor (result shr 8));
|
||||
result:=(RandomSeedW+RandomSeed) xor (RandomSeedA+(RandomSeedB shl 16));
|
||||
end;
|
||||
|
||||
procedure GCRConvert4BytesToGCR(var Buffer,Ptr);
|
||||
var BufferByte:pbyte;
|
||||
PtrByte:pbyte;
|
||||
i:integer;
|
||||
td:longword;
|
||||
begin
|
||||
BufferByte:=@Buffer;
|
||||
PtrByte:=@Ptr;
|
||||
td:=0;
|
||||
i:=2;
|
||||
while i<10 do begin
|
||||
td:=(td shl 5) or GCRConvData[BufferByte^ shr 4];
|
||||
td:=(td shl 5) or GCRConvData[BufferByte^ and $f];
|
||||
PtrByte^:=(td shr i) and $ff;
|
||||
inc(BufferByte);
|
||||
inc(PtrByte);
|
||||
inc(i,2);
|
||||
end;
|
||||
PtrByte^:=td and $ff;
|
||||
end;
|
||||
|
||||
procedure GCRConvertGCRTo4Bytes(var Buffer,Ptr);
|
||||
var BufferByte:pbyte;
|
||||
PtrByte:pbyte;
|
||||
i:integer;
|
||||
td:longword;
|
||||
begin
|
||||
BufferByte:=@Buffer;
|
||||
PtrByte:=@Ptr;
|
||||
td:=BufferByte^ shl 13;
|
||||
i:=5;
|
||||
while i<13 do begin
|
||||
inc(BufferByte);
|
||||
td:=td or (BufferByte^ shl i);
|
||||
PtrByte^:=FromGCRConvData[(td shr 16) and $1f] shl 4;
|
||||
td:=td shl 5;
|
||||
PtrByte^:=PtrByte^ or FromGCRConvData[(td shr 16) and $1f];
|
||||
td:=td shl 5;
|
||||
inc(PtrByte);
|
||||
inc(i,2);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure GCRConvertSectorToGCR(Buffer,Ptr:pbyte;Track,Sector:longword;DiskID1,DiskID2,ErrorCode:byte);
|
||||
var Buf:array[0..3] of byte;
|
||||
HeaderID,Checksum:byte;
|
||||
Counter:integer;
|
||||
begin
|
||||
if ErrorCode=29 then begin
|
||||
HeaderID:=DiskID1 xor $ff;
|
||||
end else begin
|
||||
HeaderID:=DiskID1;
|
||||
end;
|
||||
FillChar(Ptr^,5,#$ff);
|
||||
inc(Ptr,5);
|
||||
if ErrorCode=20 then begin
|
||||
Buf[0]:=$ff;
|
||||
end else begin
|
||||
Buf[0]:=$08;
|
||||
end;
|
||||
Buf[1]:=Sector xor Track xor DiskID2 xor HeaderID;
|
||||
Buf[2]:=Sector;
|
||||
Buf[3]:=Track;
|
||||
if ErrorCode=27 then begin
|
||||
Buf[1]:=Buf[1] xor $ff;
|
||||
end;
|
||||
GCRConvert4BytesToGCR(Buf,Ptr^);
|
||||
inc(Ptr,5);
|
||||
Buf[0]:=DiskID2;
|
||||
Buf[1]:=HeaderID;
|
||||
Buf[2]:=$0f;
|
||||
Buf[3]:=$0f;
|
||||
GCRConvert4BytesToGCR(Buf,Ptr^);
|
||||
inc(Ptr,5);
|
||||
FillChar(Ptr^,9,#$55);
|
||||
inc(Ptr,9);
|
||||
FillChar(Ptr^,5,#$ff);
|
||||
inc(Ptr,5);
|
||||
if ErrorCode=22 then begin
|
||||
PByteArray(Buffer)^[0]:=$ff;
|
||||
end else begin
|
||||
PByteArray(Buffer)^[0]:=$7;
|
||||
end;
|
||||
Checksum:=PByteArray(Buffer)^[1];
|
||||
for Counter:=2 to 256 do begin
|
||||
Checksum:=Checksum xor PByteArray(Buffer)^[Counter];
|
||||
end;
|
||||
if ErrorCode=23 then begin
|
||||
PByteArray(Buffer)^[257]:=Checksum xor $ff;
|
||||
end else begin
|
||||
PByteArray(Buffer)^[257]:=Checksum;
|
||||
end;
|
||||
PByteArray(Buffer)^[258]:=0;
|
||||
PByteArray(Buffer)^[259]:=0;
|
||||
for Counter:=0 to 64 do begin
|
||||
GCRConvert4BytesToGCR(Buffer^,Ptr^);
|
||||
inc(Buffer,4);
|
||||
inc(Ptr,5);
|
||||
end;
|
||||
FillChar(Ptr^,6,#$55);
|
||||
end;
|
||||
|
||||
procedure GCRConvertGCRToSector(Buffer,Ptr,GCRTrackPointer:pbyte;GCRTrackSize:longword);
|
||||
var Offset:pbyte;
|
||||
GCRTrackEnd:pbyte;
|
||||
GCRHeader:array[0..4] of byte;
|
||||
Counter,SubCounter:integer;
|
||||
begin
|
||||
Offset:=Ptr;
|
||||
GCRTrackEnd:=GCRTrackPointer;
|
||||
inc(GCRTrackEnd,GCRTrackSize);
|
||||
for Counter:=0 to 64 do begin
|
||||
for SubCounter:=0 to 4 do begin
|
||||
GCRHeader[SubCounter]:=Offset^;
|
||||
inc(Offset);
|
||||
if longword(Offset)>=longword(GCRTrackEnd) then Offset:=GCRTrackPointer;
|
||||
end;
|
||||
GCRConvertGCRTo4Bytes(GCRHeader,Buffer^);
|
||||
inc(Buffer,4);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure GCRByteRealign(GCRTrackPointer:pbyte;GCRTrackSize:longword);
|
||||
type PBuffer=^TBuffer;
|
||||
TBuffer=array[0..$3fff] of byte;
|
||||
var HeadBitLength,RemainHeadBits,HeadBitOffset,ReadShiftRegister,LowBitCount,BitCounter,BufferOffset,SyncMark,
|
||||
WrittenHighBits,HighBits:longword;
|
||||
Buffer:PBuffer;
|
||||
LastWasSyncMark,SyncMarkReadyForWrite,InSync:boolean;
|
||||
begin
|
||||
New(Buffer);
|
||||
try
|
||||
FillChar(Buffer^,SizeOf(TBuffer),AnsiChar(#0));
|
||||
HeadBitLength:=GCRTrackSize shl 3;
|
||||
LowBitCount:=0;
|
||||
BitCounter:=0;
|
||||
BufferOffset:=0;
|
||||
ReadShiftRegister:=0;
|
||||
RemainHeadBits:=HeadBitLength shl 1;
|
||||
HeadBitOffset:=0;
|
||||
LastWasSyncMark:=false;
|
||||
SyncMarkReadyForWrite:=false;
|
||||
InSync:=false;
|
||||
SyncMark:=0;
|
||||
HighBits:=0;
|
||||
WrittenHighBits:=0;
|
||||
while (RemainHeadBits>0) and (BufferOffset<=high(TBuffer)) do begin
|
||||
ReadShiftRegister:=((ReadShiftRegister shl 1) and $3fe) or (PByteArray(GCRTrackPointer)^[HeadBitOffset shr 3] shr ((not HeadBitOffset) and 7));
|
||||
LowBitCount:=(LowBitCount and longword($ffffffff+(ReadShiftRegister and 1)))+1;
|
||||
InSync:=InSync and (LowBitCount<8);
|
||||
if (LowBitCount>8) and ((ReadShiftRegister and $3f)=8) and (GenerateRandomValue>=$c0000000) then begin
|
||||
// Too many low bits confuse the electronics, so return garbage random low and high bits,
|
||||
// but never more than three low bits in a row.
|
||||
ReadShiftRegister:=ReadShiftRegister or 1;
|
||||
if (BitCounter<7) and (GenerateRandomValue<$80000000) then begin
|
||||
inc(BitCounter);
|
||||
ReadShiftRegister:=(ReadShiftRegister shl 1) and $3fe;
|
||||
end;
|
||||
end else if (ReadShiftRegister and $f)=0 then begin
|
||||
ReadShiftRegister:=ReadShiftRegister or 1;
|
||||
end;
|
||||
if (ReadShiftRegister and 1)<>0 then begin
|
||||
inc(HighBits);
|
||||
end else begin
|
||||
HighBits:=0;
|
||||
end;
|
||||
if ReadShiftRegister=$3ff then begin
|
||||
// At least 10 high bits found -> so sync mark found!
|
||||
// That will remain so until a low bit is found, then -> so end of sync mark found!
|
||||
// Reset byte shift register bit counter for perfect synchronizing reading/writing
|
||||
BitCounter:=0;
|
||||
if LastWasSyncMark then begin
|
||||
inc(SyncMark);
|
||||
end else begin
|
||||
if WrittenHighBits<=HighBits then begin
|
||||
SyncMark:=HighBits-WrittenHighBits;
|
||||
end else begin
|
||||
SyncMark:=10;
|
||||
end;
|
||||
WrittenHighBits:=0;
|
||||
end;
|
||||
LastWasSyncMark:=true;
|
||||
SyncMarkReadyForWrite:=true;
|
||||
InSync:=true;
|
||||
end else begin
|
||||
if InSync then begin
|
||||
if (ReadShiftRegister and 1)<>0 then begin
|
||||
inc(WrittenHighBits);
|
||||
end else begin
|
||||
WrittenHighBits:=0;
|
||||
end;
|
||||
end;
|
||||
LastWasSyncMark:=false;
|
||||
inc(BitCounter);
|
||||
if BitCounter=8 then begin
|
||||
if InSync then begin
|
||||
if SyncMarkReadyForWrite then begin
|
||||
SyncMarkReadyForWrite:=false;
|
||||
SyncMark:=(SyncMark+7) shr 3;
|
||||
if SyncMark>0 then begin
|
||||
FillChar(Buffer^[BufferOffset],SyncMark,AnsiChar(#$ff));
|
||||
inc(BufferOffset,SyncMark);
|
||||
SyncMark:=0;
|
||||
end;
|
||||
end;
|
||||
Buffer^[BufferOffset]:=ReadShiftRegister and $ff;
|
||||
inc(BufferOffset);
|
||||
end;
|
||||
BitCounter:=0;
|
||||
end;
|
||||
end;
|
||||
inc(HeadBitOffset);
|
||||
while HeadBitOffset>=HeadBitLength do begin
|
||||
dec(HeadBitOffset,HeadBitLength);
|
||||
end;
|
||||
dec(RemainHeadBits);
|
||||
end;
|
||||
Move(Buffer[0],GCRTrackPointer^,GCRTrackSize);
|
||||
finally
|
||||
Dispose(Buffer);
|
||||
end;
|
||||
end;
|
||||
|
||||
function GCRBitsReadSector(GCRTrackPointer:pbyte;GCRTrackSize:longword;var ReadData;Track,Sector:longword):boolean;
|
||||
type PBuffer=^TBuffer;
|
||||
TBuffer=array[0..$3fff] of byte;
|
||||
var HeadBitLength,RemainHeadBits,HeadBitOffset,ReadShiftRegister,LowBitCount,BitCounter,BufferOffset,SyncMark,
|
||||
WrittenHighBits,HighBits:longword;
|
||||
Buffer:PBuffer;
|
||||
LastWasSyncMark,SyncMarkReadyForWrite,InSync:boolean;
|
||||
begin
|
||||
try
|
||||
New(Buffer);
|
||||
try
|
||||
FillChar(Buffer^,SizeOf(TBuffer),AnsiChar(#0));
|
||||
HeadBitLength:=GCRTrackSize shl 3;
|
||||
LowBitCount:=0;
|
||||
BitCounter:=0;
|
||||
BufferOffset:=0;
|
||||
ReadShiftRegister:=0;
|
||||
RemainHeadBits:=HeadBitLength shl 1;
|
||||
HeadBitOffset:=0;
|
||||
LastWasSyncMark:=false;
|
||||
SyncMarkReadyForWrite:=false;
|
||||
InSync:=false;
|
||||
SyncMark:=0;
|
||||
HighBits:=0;
|
||||
WrittenHighBits:=0;
|
||||
while (RemainHeadBits>0) and (BufferOffset<=high(TBuffer)) do begin
|
||||
ReadShiftRegister:=((ReadShiftRegister shl 1) and $3fe) or (PByteArray(GCRTrackPointer)^[HeadBitOffset shr 3] shr ((not HeadBitOffset) and 7));
|
||||
LowBitCount:=(LowBitCount and longword($ffffffff+(ReadShiftRegister and 1)))+1;
|
||||
InSync:=InSync and (LowBitCount<8);
|
||||
if (LowBitCount>8) and ((ReadShiftRegister and $3f)=8) and (GenerateRandomValue>=$c0000000) then begin
|
||||
// Too many low bits confuse the electronics, so return garbage random low and high bits,
|
||||
// but never more than three low bits in a row.
|
||||
ReadShiftRegister:=ReadShiftRegister or 1;
|
||||
if (BitCounter<7) and (GenerateRandomValue<$80000000) then begin
|
||||
inc(BitCounter);
|
||||
ReadShiftRegister:=(ReadShiftRegister shl 1) and $3fe;
|
||||
end;
|
||||
end else if (ReadShiftRegister and $f)=0 then begin
|
||||
ReadShiftRegister:=ReadShiftRegister or 1;
|
||||
end;
|
||||
if (ReadShiftRegister and 1)<>0 then begin
|
||||
inc(HighBits);
|
||||
end else begin
|
||||
HighBits:=0;
|
||||
end;
|
||||
if ReadShiftRegister=$3ff then begin
|
||||
// At least 10 high bits found -> so sync mark found!
|
||||
// That will remain so until a low bit is found, then -> so end of sync mark found!
|
||||
// Reset byte shift register bit counter for perfect synchronizing reading/writing
|
||||
BitCounter:=0;
|
||||
if LastWasSyncMark then begin
|
||||
inc(SyncMark);
|
||||
end else begin
|
||||
if WrittenHighBits<=HighBits then begin
|
||||
SyncMark:=HighBits-WrittenHighBits;
|
||||
end else begin
|
||||
SyncMark:=10;
|
||||
end;
|
||||
WrittenHighBits:=0;
|
||||
end;
|
||||
LastWasSyncMark:=true;
|
||||
SyncMarkReadyForWrite:=true;
|
||||
InSync:=true;
|
||||
end else begin
|
||||
if InSync then begin
|
||||
if (ReadShiftRegister and 1)<>0 then begin
|
||||
inc(WrittenHighBits);
|
||||
end else begin
|
||||
WrittenHighBits:=0;
|
||||
end;
|
||||
end;
|
||||
LastWasSyncMark:=false;
|
||||
inc(BitCounter);
|
||||
if BitCounter=8 then begin
|
||||
if InSync then begin
|
||||
if SyncMarkReadyForWrite then begin
|
||||
SyncMarkReadyForWrite:=false;
|
||||
SyncMark:=(SyncMark+7) shr 3;
|
||||
if SyncMark>0 then begin
|
||||
FillChar(Buffer^[BufferOffset],SyncMark,AnsiChar(#$ff));
|
||||
inc(BufferOffset,SyncMark);
|
||||
SyncMark:=0;
|
||||
end;
|
||||
end;
|
||||
Buffer^[BufferOffset]:=ReadShiftRegister and $ff;
|
||||
inc(BufferOffset);
|
||||
end;
|
||||
BitCounter:=0;
|
||||
end;
|
||||
end;
|
||||
inc(HeadBitOffset);
|
||||
while HeadBitOffset>=HeadBitLength do begin
|
||||
dec(HeadBitOffset,HeadBitLength);
|
||||
end;
|
||||
dec(RemainHeadBits);
|
||||
end;
|
||||
result:=GCRReadSector(@Buffer[0],BufferOffset,ReadData,Track,Sector);
|
||||
finally
|
||||
Dispose(Buffer);
|
||||
end;
|
||||
except
|
||||
result:=false;
|
||||
end;
|
||||
end;
|
||||
|
||||
function GCRFindSectorHeader(Track,Sector:longword;GCRTrackPointer:pbyte;GCRTrackSize:longword):pbyte;
|
||||
var Offset:pbyte;
|
||||
GCRTrackEnd:pbyte;
|
||||
GCRHeader:array[0..4] of byte;
|
||||
HeaderData:array[0..3] of byte;
|
||||
Counter:integer;
|
||||
SyncCount:longword;
|
||||
WrapOver:boolean;
|
||||
begin
|
||||
Offset:=GCRTrackPointer;
|
||||
GCRTrackEnd:=GCRTrackPointer;
|
||||
inc(GCRTrackEnd,GCRTrackSize);
|
||||
WrapOver:=false;
|
||||
SyncCount:=0;
|
||||
while (longword(Offset)<longword(GCRTrackEnd)) and not WrapOver do begin
|
||||
while Offset^<>$ff do begin
|
||||
inc(Offset);
|
||||
if longword(Offset)>=longword(GCRTrackEnd) then begin
|
||||
result:=nil;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
while Offset^=$ff do begin
|
||||
inc(Offset);
|
||||
if longword(Offset)=longword(GCRTrackEnd) then begin
|
||||
Offset:=GCRTrackPointer;
|
||||
WrapOver:=true;
|
||||
end;
|
||||
inc(SyncCount);
|
||||
if SyncCount>=GCRTrackSize then begin
|
||||
result:=nil;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
for Counter:=0 to 4 do begin
|
||||
GCRHeader[Counter]:=Offset^;
|
||||
inc(Offset);
|
||||
if longword(Offset)>=longword(GCRTrackEnd) then begin
|
||||
Offset:=GCRTrackPointer;
|
||||
WrapOver:=true;
|
||||
end;
|
||||
end;
|
||||
GCRConvertGCRTo4Bytes(GCRHeader,HeaderData);
|
||||
if HeaderData[0]=$08 then begin
|
||||
if (HeaderData[2]=Sector) and (HeaderData[3]=Track) then begin
|
||||
result:=Offset;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
result:=nil;
|
||||
end;
|
||||
|
||||
function GCRFindSectorData(Offset,GCRTrackPointer:pbyte;GCRTrackSize:longword):pbyte;
|
||||
var GCRTrackEnd:pbyte;
|
||||
Header:integer;
|
||||
begin
|
||||
GCRTrackEnd:=GCRTrackPointer;
|
||||
inc(GCRTrackEnd,GCRTrackSize);
|
||||
Header:=0;
|
||||
while Offset^<>$ff do begin
|
||||
inc(Offset);
|
||||
if longword(Offset)>=longword(GCRTrackEnd) then begin
|
||||
Offset:=GCRTrackPointer;
|
||||
end;
|
||||
inc(Header);
|
||||
if Header>=500 then begin
|
||||
result:=nil;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
while Offset^=$ff do begin
|
||||
inc(Offset);
|
||||
if longword(Offset)=longword(GCRTrackEnd) then begin
|
||||
Offset:=GCRTrackPointer;
|
||||
end;
|
||||
end;
|
||||
result:=Offset;
|
||||
end;
|
||||
|
||||
function GCRReadSector(GCRTrackPointer:pbyte;GCRTrackSize:longword;var ReadData;Track,Sector:longword):boolean;
|
||||
var Offset:pbyte;
|
||||
Buffer:array[0..259] of byte;
|
||||
begin
|
||||
Offset:=GCRFindSectorHeader(Track,Sector,GCRTrackPointer,GCRTrackSize);
|
||||
if not assigned(Offset) then begin
|
||||
result:=false;
|
||||
exit;
|
||||
end;
|
||||
Offset:=GCRFindSectorData(Offset,GCRTrackPointer,GCRTrackSize);
|
||||
if not assigned(Offset) then begin
|
||||
result:=false;
|
||||
exit;
|
||||
end;
|
||||
GCRConvertGCRToSector(@Buffer,Offset,GCRTrackPointer,GCRTrackSize);
|
||||
if Buffer[0]<>$7 then begin
|
||||
result:=false;
|
||||
exit;
|
||||
end;
|
||||
Move(Buffer[0],ReadData,260);
|
||||
result:=true;
|
||||
end;
|
||||
|
||||
function GCRWriteSector(GCRTrackPointer:pbyte;GCRTrackSize:longword;var WriteData;Track,Sector:longword):boolean;
|
||||
var GCRTrackEnd,Offset,Buf,GCRData:pbyte;
|
||||
Buffer:array[0..259] of byte;
|
||||
GCRBuffer:array[0..324] of byte;
|
||||
Checksum:byte;
|
||||
Counter:integer;
|
||||
begin
|
||||
Offset:=GCRFindSectorHeader(Track,Sector,GCRTrackPointer,GCRTrackSize);
|
||||
if not assigned(Offset) then begin
|
||||
result:=false;
|
||||
exit;
|
||||
end;
|
||||
Offset:=GCRFindSectorData(Offset,GCRTrackPointer,GCRTrackSize);
|
||||
if not assigned(Offset) then begin
|
||||
result:=false;
|
||||
exit;
|
||||
end;
|
||||
Buffer[0]:=$7;
|
||||
Move(WriteData,Buffer[1],256);
|
||||
Checksum:=Buffer[1];
|
||||
for Counter:=2 to 256 do begin
|
||||
Checksum:=Checksum xor Buffer[Counter];
|
||||
end;
|
||||
Buffer[257]:=Checksum;
|
||||
Buffer[258]:=0;
|
||||
Buffer[259]:=0;
|
||||
Buf:=@Buffer;
|
||||
GCRData:=@GCRBuffer;
|
||||
for Counter:=0 to 64 do begin
|
||||
GCRConvert4BytesToGCR(Buf^,GCRData^);
|
||||
inc(Buf,4);
|
||||
inc(GCRData,5);
|
||||
end;
|
||||
GCRTrackEnd:=GCRTrackPointer;
|
||||
inc(GCRTrackEnd,GCRTrackSize);
|
||||
for Counter:=0 to 324 do begin
|
||||
Offset^:=GCRBuffer[Counter];
|
||||
inc(Offset);
|
||||
if longword(Offset)>=longword(GCRTrackEnd) then begin
|
||||
Offset:=GCRTrackPointer;
|
||||
end;
|
||||
end;
|
||||
result:=true;
|
||||
end;
|
||||
|
||||
end.
|
||||
464
src/Globals.pas
Normal file
464
src/Globals.pas
Normal file
|
|
@ -0,0 +1,464 @@
|
|||
(*
|
||||
** This file is part of the Micro64 Disk Tool.
|
||||
** Copyright (C) 2002-2013 by Benjamin Rosseaux
|
||||
**
|
||||
** The source code of the Micro64 Disk Tool and helper tools are
|
||||
** distributed under the Library GNU General Public License
|
||||
** (see the file COPYING) with the following modification:
|
||||
**
|
||||
** As a special exception, the copyright holders of this software give you
|
||||
** permission to link this software with independent modules to produce
|
||||
** an executable, regardless of the license terms of these independent modules,
|
||||
** and to copy and distribute the resulting executable under terms of your
|
||||
** choice, provided that you also meet, for each linked independent module,
|
||||
** the terms and conditions of the license of that module. An independent
|
||||
** module is a module which is not derived from or based on this software. If
|
||||
** you modify this software, you may extend this exception to your version of
|
||||
** the software, but you are not obligated to do so. If you do not wish to do
|
||||
** so, delete this exception statement from your version.
|
||||
**
|
||||
** If you didn't receive a copy of the file COPYING, contact:
|
||||
** Free Software Foundation
|
||||
** 675 Mass Ave
|
||||
** Cambridge, MA 02139
|
||||
** USA
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
*)
|
||||
unit Globals;
|
||||
{$IFDEF FPC}
|
||||
{$MODE DELPHI}
|
||||
{$WARNINGS OFF}
|
||||
{$HINTS OFF}
|
||||
{$OVERFLOWCHECKS OFF}
|
||||
{$RANGECHECKS OFF}
|
||||
{$IFDEF CPUI386}
|
||||
{$DEFINE CPU386}
|
||||
{$ASMMODE INTEL}
|
||||
{$ENDIF}
|
||||
{$IFDEF FPC_LITTLE_ENDIAN}
|
||||
{$DEFINE LITTLE_ENDIAN}
|
||||
{$ELSE}
|
||||
{$IFDEF FPC_BIG_ENDIAN}
|
||||
{$DEFINE BIG_ENDIAN}
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
{$ELSE}
|
||||
{$DEFINE LITTLE_ENDIAN}
|
||||
{$IFNDEF CPU64}
|
||||
{$DEFINE CPU32}
|
||||
{$ENDIF}
|
||||
{$OPTIMIZATION ON}
|
||||
{$ENDIF}
|
||||
{$writeableconst on}
|
||||
|
||||
interface
|
||||
|
||||
uses SysUtils,{$ifdef win32}ShellApi,{$endif}BeRoStream;
|
||||
|
||||
type PByteArray=^TByteArray;
|
||||
TByteArray=array[0..($7fffffff div sizeof(byte))-1] of byte;
|
||||
|
||||
PBooleanArray=^TBooleanArray;
|
||||
TBooleanArray=array[0..($7fffffff div sizeof(boolean))-1] of boolean;
|
||||
|
||||
PLongWordArray=^TLongWordArray;
|
||||
TLongWordArray=array[0..($7fffffff div sizeof(longword))-1] of longword;
|
||||
|
||||
pbyte=^byte;
|
||||
|
||||
procedure ParseParameter;
|
||||
function ASCIIToPETSCIIChar(const C:ansichar):ansichar;
|
||||
function ASCIIToPETSCII(const StringValue:ansistring):ansistring;
|
||||
function PETSCIIToASCIIChar(const C:ansichar):ansichar;
|
||||
function PETSCIIToASCII(const StringValue:ansistring):ansistring;
|
||||
function MatchFilePattern(Pattern,ToTest:pansichar;Len:longint):boolean;
|
||||
|
||||
implementation
|
||||
|
||||
uses BeRoUtils,BeRoStringToDouble,DiskImageD64,DiskImageP64,DiskImageFDI,DiskImageNIB,DiskImageKryofluxStream;
|
||||
|
||||
procedure ParseParameter;
|
||||
var I,J:longint;
|
||||
Side,DoubleWideTracks:boolean;
|
||||
S,L:ansistring;
|
||||
Stream:TBeRoStream;
|
||||
FileStream:TBeRoFileStream;
|
||||
DstFileStream:TBeRoFileStream;
|
||||
RPM:double;
|
||||
p,OK:longbool;
|
||||
begin
|
||||
J:=0;
|
||||
if PARAMCOUNT<>0 then begin
|
||||
for I:=1 to PARAMCOUNT do begin
|
||||
S:=AnsiString(PARAMSTR(I));
|
||||
if length(S)>0 then begin
|
||||
if not (S[1] in ['-','+','/']) then begin
|
||||
inc(J);
|
||||
end else begin
|
||||
case S[1] of
|
||||
'+','/':P:=true;
|
||||
else {'-':}P:=false;
|
||||
end;
|
||||
if p then begin
|
||||
end;
|
||||
L:=COPY(S,2,length(S)-1);
|
||||
S:=UPPERCASE(L);
|
||||
if S='NEWD64' then begin
|
||||
if (i+1)<=ParamCount then begin
|
||||
try
|
||||
Stream:=TBeRoStream.Create;
|
||||
try
|
||||
if CreateEmptyD64(Stream,'DISK') then begin
|
||||
DstFileStream:=TBeRoFileStream.CreateNew(AnsiString(ParamStr(i+1)));
|
||||
try
|
||||
DstFileStream.Assign(Stream);
|
||||
finally
|
||||
DstFileStream.Free;
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
Stream.Free;
|
||||
end;
|
||||
except
|
||||
end;
|
||||
end;
|
||||
halt;
|
||||
|
||||
end else if S='G642D64' then begin
|
||||
if ((i+2)<=ParamCount) and FileExists(AnsiString(ParamStr(i+1))) then begin
|
||||
try
|
||||
FileStream:=TBeRoFileStream.Create(AnsiString(ParamStr(i+1)));
|
||||
try
|
||||
Stream:=TBeRoStream.Create;
|
||||
try
|
||||
if ConvertG64toD64(FileStream,Stream) then begin
|
||||
DstFileStream:=TBeRoFileStream.CreateNew(AnsiString(ParamStr(i+2)));
|
||||
try
|
||||
DstFileStream.Assign(Stream);
|
||||
finally
|
||||
DstFileStream.Free;
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
Stream.Free;
|
||||
end;
|
||||
finally
|
||||
FileStream.Free;
|
||||
end;
|
||||
except
|
||||
end;
|
||||
end;
|
||||
halt;
|
||||
|
||||
end else if S='D642G64' then begin
|
||||
if ((i+2)<=ParamCount) and FileExists(AnsiString(ParamStr(i+1))) then begin
|
||||
try
|
||||
FileStream:=TBeRoFileStream.Create(AnsiString(ParamStr(i+1)));
|
||||
try
|
||||
Stream:=TBeRoStream.Create;
|
||||
try
|
||||
if ConvertD64toG64(FileStream,Stream) then begin
|
||||
DstFileStream:=TBeRoFileStream.CreateNew(AnsiString(ParamStr(i+2)));
|
||||
try
|
||||
DstFileStream.Assign(Stream);
|
||||
finally
|
||||
DstFileStream.Free;
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
Stream.Free;
|
||||
end;
|
||||
finally
|
||||
FileStream.Free;
|
||||
end;
|
||||
except
|
||||
end;
|
||||
end;
|
||||
halt;
|
||||
|
||||
end else if S='G642P64' then begin
|
||||
if ((i+2)<=ParamCount) and FileExists(AnsiString(ParamStr(i+1))) then begin
|
||||
try
|
||||
FileStream:=TBeRoFileStream.Create(AnsiString(ParamStr(i+1)));
|
||||
try
|
||||
Stream:=TBeRoStream.Create;
|
||||
try
|
||||
if ConvertG64toP64(FileStream,Stream) then begin
|
||||
DstFileStream:=TBeRoFileStream.CreateNew(AnsiString(ParamStr(i+2)));
|
||||
try
|
||||
DstFileStream.Assign(Stream);
|
||||
finally
|
||||
DstFileStream.Free;
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
Stream.Free;
|
||||
end;
|
||||
finally
|
||||
FileStream.Free;
|
||||
end;
|
||||
except
|
||||
end;
|
||||
end;
|
||||
halt;
|
||||
|
||||
end else if S='P642G64' then begin
|
||||
if ((i+2)<=ParamCount) and FileExists(AnsiString(ParamStr(i+1))) then begin
|
||||
try
|
||||
FileStream:=TBeRoFileStream.Create(AnsiString(ParamStr(i+1)));
|
||||
try
|
||||
Stream:=TBeRoStream.Create;
|
||||
try
|
||||
if ConvertP64toG64(FileStream,Stream,true) then begin
|
||||
DstFileStream:=TBeRoFileStream.CreateNew(AnsiString(ParamStr(i+2)));
|
||||
try
|
||||
DstFileStream.Assign(Stream);
|
||||
finally
|
||||
DstFileStream.Free;
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
Stream.Free;
|
||||
end;
|
||||
finally
|
||||
FileStream.Free;
|
||||
end;
|
||||
except
|
||||
end;
|
||||
end;
|
||||
halt;
|
||||
|
||||
end else if S='FDI2P64' then begin
|
||||
if ((i+2)<=ParamCount) and FileExists(AnsiString(ParamStr(i+1))) then begin
|
||||
try
|
||||
FileStream:=TBeRoFileStream.Create(AnsiString(ParamStr(i+1)));
|
||||
try
|
||||
Stream:=TBeRoStream.Create;
|
||||
try
|
||||
if ConvertFDItoP64(FileStream,Stream) then begin
|
||||
DstFileStream:=TBeRoFileStream.CreateNew(AnsiString(ParamStr(i+2)));
|
||||
try
|
||||
DstFileStream.Assign(Stream);
|
||||
finally
|
||||
DstFileStream.Free;
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
Stream.Free;
|
||||
end;
|
||||
finally
|
||||
FileStream.Free;
|
||||
end;
|
||||
except
|
||||
end;
|
||||
end;
|
||||
halt;
|
||||
|
||||
end else if S='P642FDI' then begin
|
||||
if ((i+2)<=ParamCount) and FileExists(AnsiString(ParamStr(i+1))) then begin
|
||||
try
|
||||
FileStream:=TBeRoFileStream.Create(AnsiString(ParamStr(i+1)));
|
||||
try
|
||||
Stream:=TBeRoStream.Create;
|
||||
try
|
||||
if ConvertP64toFDI(FileStream,Stream) then begin
|
||||
DstFileStream:=TBeRoFileStream.CreateNew(AnsiString(ParamStr(i+2)));
|
||||
try
|
||||
DstFileStream.Assign(Stream);
|
||||
finally
|
||||
DstFileStream.Free;
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
Stream.Free;
|
||||
end;
|
||||
finally
|
||||
FileStream.Free;
|
||||
end;
|
||||
except
|
||||
end;
|
||||
end;
|
||||
halt;
|
||||
|
||||
end else if S='NIB2G64' then begin
|
||||
if ((i+2)<=ParamCount) and FileExists(AnsiString(ParamStr(i+1))) then begin
|
||||
try
|
||||
FileStream:=TBeRoFileStream.Create(AnsiString(ParamStr(i+1)));
|
||||
try
|
||||
Stream:=TBeRoStream.Create;
|
||||
try
|
||||
if ConvertNIBtoG64(FileStream,Stream) then begin
|
||||
DstFileStream:=TBeRoFileStream.CreateNew(AnsiString(ParamStr(i+2)));
|
||||
try
|
||||
DstFileStream.Assign(Stream);
|
||||
finally
|
||||
DstFileStream.Free;
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
Stream.Free;
|
||||
end;
|
||||
finally
|
||||
FileStream.Free;
|
||||
end;
|
||||
except
|
||||
end;
|
||||
end;
|
||||
halt;
|
||||
|
||||
end else if S='DUMPFDI' then begin
|
||||
if ((i+2)<=ParamCount) and FileExists(AnsiString(ParamStr(i+1))) then begin
|
||||
try
|
||||
FileStream:=TBeRoFileStream.Create(AnsiString(ParamStr(i+1)));
|
||||
try
|
||||
Stream:=TBeRoFileStream.CreateNew(AnsiString(ParamStr(i+2)));
|
||||
try
|
||||
if DumpFDI(FileStream,Stream) then begin
|
||||
end;
|
||||
finally
|
||||
Stream.Free;
|
||||
end;
|
||||
finally
|
||||
FileStream.Free;
|
||||
end;
|
||||
except
|
||||
end;
|
||||
end;
|
||||
halt;
|
||||
|
||||
end else if S='DUMPP64' then begin
|
||||
if ((i+2)<=ParamCount) and FileExists(AnsiString(ParamStr(i+1))) then begin
|
||||
try
|
||||
FileStream:=TBeRoFileStream.Create(AnsiString(ParamStr(i+1)));
|
||||
try
|
||||
Stream:=TBeRoFileStream.CreateNew(AnsiString(ParamStr(i+2)));
|
||||
try
|
||||
if DumpP64(FileStream,Stream) then begin
|
||||
end;
|
||||
finally
|
||||
Stream.Free;
|
||||
end;
|
||||
finally
|
||||
FileStream.Free;
|
||||
end;
|
||||
except
|
||||
end;
|
||||
end;
|
||||
halt;
|
||||
|
||||
end else if S='DUMPP64HALFTRACK' then begin
|
||||
if ((i+3)<=ParamCount) and FileExists(AnsiString(ParamStr(i+1))) then begin
|
||||
try
|
||||
FileStream:=TBeRoFileStream.Create(AnsiString(ParamStr(i+1)));
|
||||
try
|
||||
Stream:=TBeRoFileStream.CreateNew(AnsiString(ParamStr(i+2)));
|
||||
try
|
||||
if DumpP64HalfTrack(FileStream,Stream,StrToIntDef(ParamStr(i+3),36)) then begin
|
||||
end;
|
||||
finally
|
||||
Stream.Free;
|
||||
end;
|
||||
finally
|
||||
FileStream.Free;
|
||||
end;
|
||||
except
|
||||
end;
|
||||
end;
|
||||
halt;
|
||||
|
||||
end else if (S='KRYOFLUXSTREAM2P64') or (S='KRYOFLUXSTREAM2FDI') then begin
|
||||
if (i+2)<=ParamCount then begin
|
||||
if (i+3)<=ParamCount then begin
|
||||
Side:=ParamStr(i+3)='1';
|
||||
end else begin
|
||||
Side:=false;
|
||||
end;
|
||||
if (i+4)<=ParamCount then begin
|
||||
OK:=false;
|
||||
RPM:=BeRoConvertStringToDouble(AnsiString(ParamStr(i+4)),bstd_ROUND_TO_NEAREST,@OK);
|
||||
if (not OK) or (RPM<1) then begin
|
||||
RPM:=300;
|
||||
end;
|
||||
end else begin
|
||||
RPM:=300;
|
||||
end;
|
||||
if (i+5)<=ParamCount then begin
|
||||
DoubleWideTracks:=ParamStr(i+5)='1';
|
||||
end else begin
|
||||
DoubleWideTracks:=false;
|
||||
end;
|
||||
if ConvertKryofluxStream(AnsiString(ParamStr(i+1)),AnsiString(ParamStr(i+2)),Side,S='KRYOFLUXSTREAM2FDI',DoubleWideTracks,RPM) then begin
|
||||
end;
|
||||
end;
|
||||
halt;
|
||||
|
||||
end;
|
||||
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
if j<>0 then begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function ASCIIToPETSCIIChar(const C:ansichar):ansichar;
|
||||
begin
|
||||
case C of
|
||||
'A'..'Z','a'..'z':result:=ansichar(byte(byte(C) xor $20));
|
||||
else result:=C;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ASCIIToPETSCII(const StringValue:ansistring):ansistring;
|
||||
var Counter:longint;
|
||||
begin
|
||||
result:=StringValue;
|
||||
for Counter:=1 to length(result) do begin
|
||||
result[Counter]:=ASCIIToPETSCIIChar(result[Counter]);
|
||||
end;
|
||||
end;
|
||||
|
||||
function PETSCIIToASCIIChar(const C:ansichar):ansichar;
|
||||
begin
|
||||
case C of
|
||||
'A'..'Z','a'..'z':result:=ansichar(byte(byte(C) xor $20));
|
||||
#$c1..#$da:result:=ansichar(byte(byte(C) xor $80));
|
||||
else result:=C;
|
||||
end;
|
||||
end;
|
||||
|
||||
function PETSCIIToASCII(const StringValue:ansistring):ansistring;
|
||||
var Counter:longint;
|
||||
begin
|
||||
result:=StringValue;
|
||||
for Counter:=1 to length(result) do begin
|
||||
result[Counter]:=PETSCIIToASCIIChar(result[Counter]);
|
||||
end;
|
||||
end;
|
||||
|
||||
function MatchFilePattern(Pattern,ToTest:pansichar;Len:longint):boolean;
|
||||
var Counter:longint;
|
||||
begin
|
||||
result:=true;
|
||||
if Len>16 then Len:=16;
|
||||
for Counter:=1 to Len do begin
|
||||
if Pattern^='*' then begin
|
||||
break;
|
||||
end else if (Pattern^<>'?') and (Pattern^<>ToTest^) then begin
|
||||
result:=false;
|
||||
break;
|
||||
end;
|
||||
inc(Pattern);
|
||||
inc(ToTest);
|
||||
end;
|
||||
end;
|
||||
|
||||
initialization
|
||||
end.
|
||||
|
||||
|
||||
626
src/LZBRA.pas
Normal file
626
src/LZBRA.pas
Normal file
|
|
@ -0,0 +1,626 @@
|
|||
(*
|
||||
** This file is part of the Micro64 Disk Tool.
|
||||
** Copyright (C) 2002-2013 by Benjamin Rosseaux
|
||||
**
|
||||
** The source code of the Micro64 Disk Tool and helper tools are
|
||||
** distributed under the Library GNU General Public License
|
||||
** (see the file COPYING) with the following modification:
|
||||
**
|
||||
** As a special exception, the copyright holders of this software give you
|
||||
** permission to link this software with independent modules to produce
|
||||
** an executable, regardless of the license terms of these independent modules,
|
||||
** and to copy and distribute the resulting executable under terms of your
|
||||
** choice, provided that you also meet, for each linked independent module,
|
||||
** the terms and conditions of the license of that module. An independent
|
||||
** module is a module which is not derived from or based on this software. If
|
||||
** you modify this software, you may extend this exception to your version of
|
||||
** the software, but you are not obligated to do so. If you do not wish to do
|
||||
** so, delete this exception statement from your version.
|
||||
**
|
||||
** If you didn't receive a copy of the file COPYING, contact:
|
||||
** Free Software Foundation
|
||||
** 675 Mass Ave
|
||||
** Cambridge, MA 02139
|
||||
** USA
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
*)
|
||||
unit LZBRA;
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}
|
||||
{$ifdef cpui386}
|
||||
{$define cpu386}
|
||||
{$endif}
|
||||
{$ifdef cpu386}
|
||||
{$asmmode intel}
|
||||
{$endif}
|
||||
{$ifdef cpuamd64}
|
||||
{$asmmode intel}
|
||||
{$endif}
|
||||
{$ifdef FPC_LITTLE_ENDIAN}
|
||||
{$define LITTLE_ENDIAN}
|
||||
{$else}
|
||||
{$ifdef FPC_BIG_ENDIAN}
|
||||
{$define BIG_ENDIAN}
|
||||
{$endif}
|
||||
{$endif}
|
||||
{$pic on}
|
||||
{$define caninline}
|
||||
{$ifdef FPC_HAS_TYPE_EXTENDED}
|
||||
{$define HAS_TYPE_EXTENDED}
|
||||
{$else}
|
||||
{$undef HAS_TYPE_EXTENDED}
|
||||
{$endif}
|
||||
{$ifdef FPC_HAS_TYPE_DOUBLE}
|
||||
{$define HAS_TYPE_DOUBLE}
|
||||
{$else}
|
||||
{$undef HAS_TYPE_DOUBLE}
|
||||
{$endif}
|
||||
{$ifdef FPC_HAS_TYPE_SINGLE}
|
||||
{$define HAS_TYPE_SINGLE}
|
||||
{$else}
|
||||
{$undef HAS_TYPE_SINGLE}
|
||||
{$endif}
|
||||
{$else}
|
||||
{$realcompatibility off}
|
||||
{$localsymbols on}
|
||||
{$define LITTLE_ENDIAN}
|
||||
{$ifndef cpu64}
|
||||
{$define cpu32}
|
||||
{$endif}
|
||||
{$define HAS_TYPE_EXTENDED}
|
||||
{$define HAS_TYPE_DOUBLE}
|
||||
{$define HAS_TYPE_SINGLE}
|
||||
{$endif}
|
||||
{$ifdef win32}
|
||||
{$define windows}
|
||||
{$endif}
|
||||
{$ifdef win64}
|
||||
{$define windows}
|
||||
{$endif}
|
||||
{$ifdef wince}
|
||||
{$define windows}
|
||||
{$endif}
|
||||
{$assertions off}
|
||||
{$rangechecks off}
|
||||
{$extendedsyntax on}
|
||||
{$writeableconst on}
|
||||
{$hints off}
|
||||
{$booleval off}
|
||||
{$typedaddress off}
|
||||
{$stackframes off}
|
||||
{$varstringchecks on}
|
||||
{$typeinfo on}
|
||||
{$overflowchecks off}
|
||||
{$longstrings on}
|
||||
{$openstrings on}
|
||||
|
||||
interface
|
||||
|
||||
type TCompressLZBRAStatusHook=function(Current,Total:longint):boolean;
|
||||
|
||||
function CompressLZBRA(SourcePointer:pointer;var DestinationPointer:pointer;SourceSize,WindowSize:longword;OptimalMatching:boolean;StatusHook:TCompressLZBRAStatusHook):longword;
|
||||
function DecompressLZBRA(SourcePointer:pointer;var DestinationPointer:pointer;SourceSize:longword):longword;
|
||||
|
||||
implementation
|
||||
|
||||
const FlagModel=0;
|
||||
PrevMatchModel=2;
|
||||
MatchLowModel=3;
|
||||
LiteralModel=35;
|
||||
Gamma0Model=291;
|
||||
Gamma1Model=547;
|
||||
SizeModels=803;
|
||||
|
||||
type pbyte=^byte;
|
||||
|
||||
{$ifdef fpc}
|
||||
{$undef OldDelphi}
|
||||
{$else}
|
||||
{$ifdef conditionalexpressions}
|
||||
{$if CompilerVersion>=23.0}
|
||||
{$undef OldDelphi}
|
||||
type qword=uint64;
|
||||
ptruint=NativeUInt;
|
||||
ptrint=NativeInt;
|
||||
{$else}
|
||||
{$define OldDelphi}
|
||||
{$ifend}
|
||||
{$else}
|
||||
{$define OldDelphi}
|
||||
{$endif}
|
||||
{$endif}
|
||||
{$ifdef OldDelphi}
|
||||
type qword=int64;
|
||||
{$ifdef cpu64}
|
||||
ptruint=qword;
|
||||
ptrint=int64;
|
||||
{$else}
|
||||
ptruint=longword;
|
||||
ptrint=longint;
|
||||
{$endif}
|
||||
{$endif}
|
||||
|
||||
function CompressLZBRA(SourcePointer:pointer;var DestinationPointer:pointer;SourceSize,WindowSize:longword;OptimalMatching:boolean;StatusHook:TCompressLZBRAStatusHook):longword;
|
||||
type PNode=^TNode;
|
||||
TNode=record
|
||||
DataPointer:pointer;
|
||||
Previous,Next:PNode;
|
||||
end;
|
||||
PNodes=^TNodes;
|
||||
TNodes=array[0..($7fffffff div sizeof(TNode))-1] of TNode;
|
||||
PRecentNodes=^TRecentNodes;
|
||||
TRecentNodes=array[byte] of PNode;
|
||||
var Source,Destination,EndPointer,LastHashed:pansichar;
|
||||
DestinationAllocated:longword;
|
||||
Nodes:PNodes;
|
||||
RecentNodes:PRecentNodes;
|
||||
NodePosition:longword;
|
||||
Code,Range:longword;
|
||||
Model:array[0..SizeModels-1] of longword;
|
||||
LastWasMatch:boolean;
|
||||
LastPosition:longint;
|
||||
|
||||
procedure IncrementSize(Count:longword);
|
||||
begin
|
||||
if ((ptruint(Destination)-ptruint(DestinationPointer))+Count)>=DestinationAllocated then begin
|
||||
while ((ptruint(Destination)-ptruint(DestinationPointer))+Count)>=DestinationAllocated do begin
|
||||
inc(DestinationAllocated,DestinationAllocated);
|
||||
end;
|
||||
dec(ptruint(Destination),ptruint(DestinationPointer));
|
||||
ReAllocMem(DestinationPointer,DestinationAllocated);
|
||||
inc(ptruint(Destination),ptruint(DestinationPointer));
|
||||
end;
|
||||
end;
|
||||
|
||||
function AddNode(Data:pansichar):boolean;
|
||||
var Prefix:byte;
|
||||
LastNode:PNode;
|
||||
NewNode:PNode;
|
||||
begin
|
||||
result:=NodePosition<(SourceSize-1);
|
||||
if result then begin
|
||||
Prefix:=byte(pointer(Data)^);
|
||||
LastNode:=RecentNodes^[Prefix];
|
||||
NewNode:=@Nodes^[NodePosition];
|
||||
with NewNode^ do begin
|
||||
DataPointer:=Data;
|
||||
Previous:=LastNode;
|
||||
Next:=nil;
|
||||
end;
|
||||
if assigned(LastNode) then begin
|
||||
LastNode^.Next:=NewNode;
|
||||
end;
|
||||
RecentNodes^[Prefix]:=NewNode;
|
||||
inc(NodePosition);
|
||||
end;
|
||||
end;
|
||||
|
||||
function RemoveNode(Data:pointer):boolean;
|
||||
var Prefix:word;
|
||||
Node:PNode;
|
||||
begin
|
||||
result:=NodePosition<(SourceSize-1);
|
||||
if result then begin
|
||||
Prefix:=byte(Data^);
|
||||
Node:=RecentNodes^[Prefix];
|
||||
if assigned(Node) and (Node^.DataPointer=Data) and (Node=@Nodes^[NodePosition-1]) then begin
|
||||
RecentNodes^[Prefix]:=Node^.Previous;
|
||||
if assigned(Node^.Previous) then begin
|
||||
Node^.Previous^.Next:=Node^.Next;
|
||||
end;
|
||||
if assigned(Node^.Next) then begin
|
||||
Node^.Next^.Previous:=Node^.Previous;
|
||||
end;
|
||||
Node^.Previous:=nil;
|
||||
Node^.Next:=nil;
|
||||
dec(NodePosition);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure DoHash(Source:pansichar);
|
||||
begin
|
||||
while LastHashed<Source do begin
|
||||
AddNode(LastHashed);
|
||||
inc(LastHashed);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure DoUnhash(Source:pansichar);
|
||||
begin
|
||||
while LastHashed>Source do begin
|
||||
dec(LastHashed);
|
||||
RemoveNode(LastHashed);
|
||||
end;
|
||||
end;
|
||||
|
||||
function EncodeBit(ModelIndex,Move,Bit:longint):longint;
|
||||
var Bound,OldCode:longword;
|
||||
p:pansichar;
|
||||
begin
|
||||
Bound:=(Range shr 12)*Model[ModelIndex];
|
||||
if Bit=0 then begin
|
||||
Range:=Bound;
|
||||
inc(Model[ModelIndex],(4096-Model[ModelIndex]) shr Move);
|
||||
end else begin
|
||||
OldCode:=Code;
|
||||
inc(Code,Bound);
|
||||
dec(Range,Bound);
|
||||
dec(Model[ModelIndex],Model[ModelIndex] shr Move);
|
||||
if Code<OldCode then begin
|
||||
p:=@Destination[-1];
|
||||
while p^=#$ff do begin
|
||||
p^:=#0;
|
||||
dec(p);
|
||||
end;
|
||||
inc(p^);
|
||||
end;
|
||||
end;
|
||||
while Range<$1000000 do begin
|
||||
IncrementSize(1);
|
||||
byte(pointer(Destination)^):=Code shr 24;
|
||||
inc(Destination);
|
||||
Code:=Code shl 8;
|
||||
Range:=Range shl 8;
|
||||
end;
|
||||
result:=Bit;
|
||||
end;
|
||||
|
||||
procedure EncoderFlush;
|
||||
var OldCode,Bytes:longword;
|
||||
p:pansichar;
|
||||
begin
|
||||
OldCode:=Code;
|
||||
if Range>$2000000 then begin
|
||||
inc(Code,$1000000);
|
||||
Range:=$800000;
|
||||
end else begin
|
||||
inc(Code,$800000);
|
||||
Range:=$8000;
|
||||
end;
|
||||
if Code<OldCode then begin
|
||||
p:=@Destination[-1];
|
||||
while p^=#$ff do begin
|
||||
p^:=#0;
|
||||
dec(p);
|
||||
end;
|
||||
inc(p^);
|
||||
end;
|
||||
for Bytes:=1 to 4 do begin
|
||||
IncrementSize(1);
|
||||
byte(pointer(Destination)^):=Code shr 24;
|
||||
inc(Destination);
|
||||
Code:=Code shl 8;
|
||||
Range:=Range shl 8;
|
||||
end;
|
||||
longword(pointer(@pansichar(DestinationPointer)[4])^):=(byte(pansichar(DestinationPointer)[4]) shl 24) or (byte(pansichar(DestinationPointer)[5]) shl 16) or (byte(pansichar(DestinationPointer)[6]) shl 8) or byte(pansichar(DestinationPointer)[7]);
|
||||
end;
|
||||
|
||||
procedure EncodeTree(ModelIndex,Bits,Move,Value:longint);
|
||||
var Context:longint;
|
||||
begin
|
||||
Context:=1;
|
||||
while Bits>0 do begin
|
||||
dec(Bits);
|
||||
Context:=(Context shl 1) or EncodeBit(ModelIndex+Context,Move,(Value shr Bits) and 1);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure EncodeGamma(ModelIndex,Value:longword);
|
||||
var Mask:longword;
|
||||
Context:byte;
|
||||
begin
|
||||
Context:=1;
|
||||
Mask:=Value shr 1;
|
||||
while (Mask and (Mask-1))<>0 do begin
|
||||
Mask:=Mask and (Mask-1);
|
||||
end;
|
||||
while Mask<>0 do begin
|
||||
Context:=(Context shl 1) or EncodeBit(ModelIndex+Context,5,(0-(Mask shr 1)) shr 31);
|
||||
Context:=(Context shl 1) or longword(EncodeBit(ModelIndex+Context,5,(0-(Value and Mask)) shr 31));
|
||||
Mask:=Mask shr 1;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure EncodeEnd(ModelIndex:longint);
|
||||
var Bits:longword;
|
||||
Context:byte;
|
||||
begin
|
||||
Context:=1;
|
||||
Bits:=32;
|
||||
while Bits>0 do begin
|
||||
dec(Bits);
|
||||
Context:=(Context shl 1) or EncodeBit(ModelIndex+Context,5,(0-Bits) shr 31);
|
||||
EncodeBit(ModelIndex+Context,5,0);
|
||||
Context:=Context shl 1;
|
||||
end;
|
||||
end;
|
||||
|
||||
function CompareBytes(FirstComparePointer,SecondComparePointer:pansichar):longword;
|
||||
begin
|
||||
result:=0;
|
||||
while (SecondComparePointer<EndPointer) and (FirstComparePointer^=SecondComparePointer^) do begin
|
||||
inc(result);
|
||||
inc(FirstComparePointer);
|
||||
inc(SecondComparePointer);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure DoSearch(Source:pansichar;var BestPosition,BestFoundLength:longint);
|
||||
var SearchPointer:pansichar;
|
||||
FoundLength,Position:longint;
|
||||
Node:PNode;
|
||||
begin
|
||||
BestPosition:=0;
|
||||
BestFoundLength:=1;
|
||||
Node:=RecentNodes^[byte(pointer(Source)^)];
|
||||
while assigned(Node) and ((longword(Source)-longword(Node^.DataPointer))<=WindowSize) do begin
|
||||
SearchPointer:=Node^.DataPointer;
|
||||
FoundLength:=CompareBytes(SearchPointer,Source);
|
||||
if FoundLength>1 then begin
|
||||
Position:=pansichar(Source)-pansichar(SearchPointer);
|
||||
if ((Position>0) and ((Position<96) or ((Position>96) and (FoundLength>3)) or ((Position>2048) and (FoundLength>4)))) and
|
||||
((BestFoundLength<FoundLength) or (((BestFoundLength=FoundLength) and (Position<=BestPosition)))) then begin
|
||||
BestFoundLength:=FoundLength;
|
||||
BestPosition:=Position;
|
||||
end;
|
||||
end;
|
||||
Node:=Node^.Previous;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure PutResult(var Source:pansichar;BestPosition,BestFoundLength:longint); register;
|
||||
var Offset:longword;
|
||||
begin
|
||||
if (BestFoundLength>1) and (BestPosition>0) then begin
|
||||
inc(Source,BestFoundLength);
|
||||
EncodeBit(FlagModel+byte(boolean(LastWasMatch)),5,1);
|
||||
if (not LastWasMatch) and (BestPosition=LastPosition) then begin
|
||||
EncodeBit(PrevMatchModel,5,1);
|
||||
end else begin
|
||||
if not LastWasMatch then begin
|
||||
EncodeBit(PrevMatchModel,5,0);
|
||||
end;
|
||||
Offset:=BestPosition-1;
|
||||
EncodeGamma(Gamma0Model,(Offset shr 4)+2);
|
||||
EncodeTree(MatchLowModel+(ord((Offset shr 4)<>0) shl 4),4,5,Offset and $f);
|
||||
dec(BestFoundLength,ord(BestPosition>=96)+ord(BestPosition>=2048));
|
||||
end;
|
||||
EncodeGamma(Gamma1Model,BestFoundLength);
|
||||
LastWasMatch:=true;
|
||||
LastPosition:=BestPosition;
|
||||
end else begin
|
||||
EncodeBit(FlagModel+byte(boolean(LastWasMatch)),5,0);
|
||||
EncodeTree(LiteralModel,8,4,byte(pointer(Source)^));
|
||||
inc(Source);
|
||||
LastWasMatch:=false;
|
||||
end;
|
||||
end;
|
||||
|
||||
var BestPosition,BestFoundLength:longint;
|
||||
LookaheadBestPosition,LookaheadBestFoundLength:longint;
|
||||
Lookahead,OldLastHashed:pansichar;
|
||||
begin
|
||||
result:=0;
|
||||
if SourceSize>0 then begin
|
||||
GetMem(Nodes,SourceSize*sizeof(TNode));
|
||||
New(RecentNodes);
|
||||
FillChar(Nodes^,SourceSize*sizeof(TNode),#0);
|
||||
FillChar(RecentNodes^,sizeof(TRecentNodes),#0);
|
||||
|
||||
NodePosition:=0;
|
||||
Source:=SourcePointer;
|
||||
LastHashed:=Source;
|
||||
|
||||
DestinationAllocated:=(SourceSize shr 1) or 16;
|
||||
GetMem(DestinationPointer,DestinationAllocated);
|
||||
Destination:=DestinationPointer;
|
||||
EndPointer:=Source;
|
||||
inc(EndPointer,SourceSize);
|
||||
|
||||
IncrementSize(4);
|
||||
longword(pointer(Destination)^):=0;
|
||||
inc(Destination,4);
|
||||
|
||||
Range:=$ffffffff;
|
||||
Code:=0;
|
||||
|
||||
LastPosition:=-1;
|
||||
|
||||
for BestPosition:=0 to SizeModels-1 do begin
|
||||
Model[BestPosition]:=2048;
|
||||
end;
|
||||
|
||||
BestPosition:=0;
|
||||
BestFoundLength:=0;
|
||||
|
||||
LookaheadBestPosition:=0;
|
||||
LookaheadBestFoundLength:=0;
|
||||
|
||||
EncodeTree(LiteralModel,8,4,byte(pointer(Source)^));
|
||||
inc(Source);
|
||||
|
||||
while longword(Source)<longword(EndPointer) do begin
|
||||
if assigned(StatusHook) then begin
|
||||
StatusHook(pansichar(Source)-pansichar(SourcePointer),SourceSize);
|
||||
end;
|
||||
DoSearch(Source,BestPosition,BestFoundLength);
|
||||
if OptimalMatching and (BestFoundLength>1) then begin
|
||||
Lookahead:=Source;
|
||||
OldLastHashed:=LastHashed;
|
||||
while Lookahead<pansichar(@Source[BestFoundLength]) do begin
|
||||
inc(Lookahead);
|
||||
DoHash(Lookahead);
|
||||
DoSearch(Lookahead,LookaheadBestPosition,LookaheadBestFoundLength);
|
||||
if LookaheadBestFoundLength>0 then begin
|
||||
if (BestFoundLength+(Lookahead-Source))<=LookaheadBestFoundLength then begin
|
||||
BestPosition:=0;
|
||||
BestFoundLength:=1;
|
||||
end;
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
DoUnhash(OldLastHashed);
|
||||
end;
|
||||
PutResult(Source,BestPosition,BestFoundLength);
|
||||
DoHash(Source);
|
||||
end;
|
||||
|
||||
EncodeBit(FlagModel+byte(boolean(LastWasMatch)),5,1);
|
||||
if not LastWasMatch then begin
|
||||
EncodeBit(PrevMatchModel,5,0);
|
||||
end;
|
||||
EncodeEnd(Gamma0Model);
|
||||
|
||||
EncoderFlush;
|
||||
|
||||
Dispose(RecentNodes);
|
||||
FreeMem(Nodes);
|
||||
|
||||
longword(pointer(DestinationPointer)^):=SourceSize;
|
||||
|
||||
result:=Destination-pansichar(DestinationPointer);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
function DecompressLZBRA(SourcePointer:pointer;var DestinationPointer:pointer;SourceSize:longword):longword;
|
||||
var Code,Range:longword;
|
||||
Model:array[0..SizeModels-1] of longword;
|
||||
Source:pansichar;
|
||||
Abort:boolean;
|
||||
|
||||
function DecodeBit(ModelIndex,Move:longint):longint;
|
||||
var Bound:longword;
|
||||
begin
|
||||
Bound:=(Range shr 12)*Model[ModelIndex];
|
||||
if Code<Bound then begin
|
||||
Range:=Bound;
|
||||
inc(Model[ModelIndex],(4096-Model[ModelIndex]) shr Move);
|
||||
result:=0;
|
||||
end else begin
|
||||
dec(Code,Bound);
|
||||
dec(Range,Bound);
|
||||
dec(Model[ModelIndex],Model[ModelIndex] shr Move);
|
||||
result:=1;
|
||||
end;
|
||||
while Range<$1000000 do begin
|
||||
if ptruint(Source)<(ptruint(SourcePointer)+SourceSize) then begin
|
||||
Code:=(Code shl 8) or byte(pointer(Source)^);
|
||||
inc(Source);
|
||||
Range:=Range shl 8;
|
||||
end else begin
|
||||
Abort:=true;
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function DecodeTree(ModelIndex,MaxValue,Move:longint):longint;
|
||||
begin
|
||||
result:=1;
|
||||
while result<MaxValue do begin
|
||||
result:=(result shl 1) or DecodeBit(ModelIndex+result,Move);
|
||||
end;
|
||||
dec(result,MaxValue);
|
||||
end;
|
||||
|
||||
function DecodeGamma(ModelIndex:longint):longint;
|
||||
var Context:byte;
|
||||
begin
|
||||
result:=1;
|
||||
Context:=1;
|
||||
repeat
|
||||
Context:=(Context shl 1) or DecodeBit(ModelIndex+Context,5);
|
||||
result:=(result shl 1) or DecodeBit(ModelIndex+Context,5);
|
||||
Context:=(Context shl 1) or (result and 1);
|
||||
until ((Context and 2)=0) or Abort;
|
||||
end;
|
||||
|
||||
var Len,Offset,LastOffset:longint;
|
||||
Flag,LastWasMatch:boolean;
|
||||
Destination:pansichar;
|
||||
Size:longword;
|
||||
begin
|
||||
if assigned(SourcePointer) and (SourceSize>=8) then begin
|
||||
Abort:=false;
|
||||
|
||||
Source:=SourcePointer;
|
||||
|
||||
Size:=longword(pointer(Source)^);
|
||||
inc(Source,sizeof(longword));
|
||||
|
||||
GetMem(DestinationPointer,Size);
|
||||
Destination:=DestinationPointer;
|
||||
|
||||
Code:=longword(pointer(Source)^);
|
||||
inc(Source,sizeof(longword));
|
||||
|
||||
Range:=$ffffffff;
|
||||
|
||||
for Len:=0 to SizeModels-1 do begin
|
||||
Model[Len]:=2048;
|
||||
end;
|
||||
|
||||
LastOffset:=0;
|
||||
|
||||
LastWasMatch:=false;
|
||||
|
||||
Flag:=false;
|
||||
|
||||
while (ptruint(Source)<(ptruint(SourcePointer)+SourceSize)) and not Abort do begin
|
||||
|
||||
if Flag then begin
|
||||
if (not LastWasMatch) and (DecodeBit(PrevMatchModel,5)<>0) then begin
|
||||
Offset:=LastOffset;
|
||||
Len:=0;
|
||||
end else begin
|
||||
Offset:=DecodeGamma(Gamma0Model);
|
||||
if Offset=0 then begin
|
||||
result:=Destination-pansichar(DestinationPointer);
|
||||
exit;
|
||||
end;
|
||||
dec(Offset,2);
|
||||
Offset:=((Offset shl 4)+DecodeTree(MatchLowModel+(ord(Offset<>0) shl 4),16,5))+1;
|
||||
Len:=ord(Offset>=96)+ord(Offset>=2048);
|
||||
end;
|
||||
LastOffset:=Offset;
|
||||
LastWasMatch:=true;
|
||||
inc(Len,DecodeGamma(Gamma1Model));
|
||||
if ((ptruint(Destination)+longword(Len))<=(ptruint(DestinationPointer)+longword(Size))) and not Abort then begin
|
||||
while Len>0 do begin
|
||||
dec(Len);
|
||||
Destination^:=Destination[-Offset];
|
||||
inc(Destination);
|
||||
end;
|
||||
end else begin
|
||||
break;
|
||||
end;
|
||||
end else begin
|
||||
if (ptruint(Destination)<(ptruint(DestinationPointer)+Size)) and not Abort then begin
|
||||
byte(pointer(Destination)^):=DecodeTree(LiteralModel,256,4);
|
||||
inc(Destination);
|
||||
LastWasMatch:=false;
|
||||
end else begin
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
|
||||
Flag:=boolean(byte(DecodeBit(FlagModel+byte(boolean(LastWasMatch)),5)));
|
||||
|
||||
end;
|
||||
|
||||
FreeMem(DestinationPointer);
|
||||
|
||||
end;
|
||||
|
||||
DestinationPointer:=nil;
|
||||
result:=0;
|
||||
|
||||
end;
|
||||
|
||||
end.
|
||||
248
src/RangeCoder.pas
Normal file
248
src/RangeCoder.pas
Normal file
|
|
@ -0,0 +1,248 @@
|
|||
(*
|
||||
** This file is part of the Micro64 Disk Tool.
|
||||
** Copyright (C) 2002-2013 by Benjamin Rosseaux
|
||||
**
|
||||
** The source code of the Micro64 Disk Tool and helper tools are
|
||||
** distributed under the Library GNU General Public License
|
||||
** (see the file COPYING) with the following modification:
|
||||
**
|
||||
** As a special exception, the copyright holders of this software give you
|
||||
** permission to link this software with independent modules to produce
|
||||
** an executable, regardless of the license terms of these independent modules,
|
||||
** and to copy and distribute the resulting executable under terms of your
|
||||
** choice, provided that you also meet, for each linked independent module,
|
||||
** the terms and conditions of the license of that module. An independent
|
||||
** module is a module which is not derived from or based on this software. If
|
||||
** you modify this software, you may extend this exception to your version of
|
||||
** the software, but you are not obligated to do so. If you do not wish to do
|
||||
** so, delete this exception statement from your version.
|
||||
**
|
||||
** If you didn't receive a copy of the file COPYING, contact:
|
||||
** Free Software Foundation
|
||||
** 675 Mass Ave
|
||||
** Cambridge, MA 02139
|
||||
** USA
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
*)
|
||||
unit RangeCoder;
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}
|
||||
{$endif}
|
||||
{$assertions off}
|
||||
{$rangechecks off}
|
||||
{$extendedsyntax on}
|
||||
{$writeableconst on}
|
||||
{$hints off}
|
||||
{$booleval off}
|
||||
{$typedaddress off}
|
||||
{$stackframes off}
|
||||
{$varstringchecks on}
|
||||
{$typeinfo on}
|
||||
{$overflowchecks off}
|
||||
{$longstrings on}
|
||||
{$openstrings on}
|
||||
|
||||
interface
|
||||
|
||||
type PRangeCoderProbabilities=^TRangeCoderProbabilities;
|
||||
TRangeCoderProbabilities=array[0..$3ffffff] of longword;
|
||||
|
||||
PRangeCoder=^TRangeCoder;
|
||||
TRangeCoder=record
|
||||
Buffer:pointer;
|
||||
BufferSize:longword;
|
||||
BufferPosition:longword;
|
||||
RangeCode:longword;
|
||||
RangeLow:longword;
|
||||
RangeHigh:longword;
|
||||
RangeMiddle:longword;
|
||||
end;
|
||||
|
||||
function RangeCoderProbabilitiesAllocate(Count:longint):PRangeCoderProbabilities;
|
||||
procedure RangeCoderProbabilitiesFree(Probabilities:PRangeCoderProbabilities);
|
||||
procedure RangeCoderProbabilitiesReset(Probabilities:PRangeCoderProbabilities;Count:longint);
|
||||
|
||||
function RangeCoderRead(var Instance:TRangeCoder):byte;
|
||||
procedure RangeCoderWrite(var Instance:TRangeCoder;Value:byte);
|
||||
|
||||
procedure RangeCoderInit(var Instance:TRangeCoder);
|
||||
|
||||
procedure RangeCoderStart(var Instance:TRangeCoder);
|
||||
|
||||
procedure RangeCoderFlush(var Instance:TRangeCoder);
|
||||
|
||||
procedure RangeCoderEncodeNormalize(var Instance:TRangeCoder);
|
||||
function RangeCoderEncodeBit(var Instance:TRangeCoder;var Probability:longword;Shift,BitValue:longword):longword;
|
||||
function RangeCoderEncodeBitWithoutProbability(var Instance:TRangeCoder;BitValue:longword):longword;
|
||||
|
||||
procedure RangeCoderDecodeNormalize(var Instance:TRangeCoder);
|
||||
function RangeCoderDecodeBit(var Instance:TRangeCoder;var Probability:longword;Shift:longword):longword;
|
||||
function RangeCoderDecodeBitWithoutProbability(var Instance:TRangeCoder):longword;
|
||||
|
||||
function RangeCoderEncodeDirectBits(var Instance:TRangeCoder;Bits,Value:longword):longword;
|
||||
function RangeCoderDecodeDirectBits(var Instance:TRangeCoder;Bits:longword):longword;
|
||||
|
||||
implementation
|
||||
|
||||
function RangeCoderProbabilitiesAllocate(Count:longint):PRangeCoderProbabilities;
|
||||
begin
|
||||
GetMem(result,Count*SizeOf(longword));
|
||||
end;
|
||||
|
||||
procedure RangeCoderProbabilitiesFree(Probabilities:PRangeCoderProbabilities);
|
||||
begin
|
||||
FreeMem(Probabilities);
|
||||
end;
|
||||
|
||||
procedure RangeCoderProbabilitiesReset(Probabilities:PRangeCoderProbabilities;Count:longint);
|
||||
var Index:longint;
|
||||
begin
|
||||
for Index:=0 to Count-1 do begin
|
||||
Probabilities^[Index]:=2048;
|
||||
end;
|
||||
end;
|
||||
|
||||
function RangeCoderRead(var Instance:TRangeCoder):byte;
|
||||
begin
|
||||
if Instance.BufferPosition<Instance.BufferSize then begin
|
||||
result:=byte(PAnsiChar(Instance.Buffer)[Instance.BufferPosition]);
|
||||
inc(Instance.BufferPosition);
|
||||
end else begin
|
||||
result:=0;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure RangeCoderWrite(var Instance:TRangeCoder;Value:byte);
|
||||
begin
|
||||
if Instance.BufferPosition>=Instance.BufferSize then begin
|
||||
if Instance.BufferSize<16 then begin
|
||||
Instance.BufferSize:=16;
|
||||
end;
|
||||
while Instance.BufferPosition>=Instance.BufferSize do begin
|
||||
inc(Instance.BufferSize,Instance.BufferSize);
|
||||
end;
|
||||
ReallocMem(Instance.Buffer,Instance.BufferSize);
|
||||
end;
|
||||
byte(PAnsiChar(Instance.Buffer)[Instance.BufferPosition]):=Value;
|
||||
inc(Instance.BufferPosition);
|
||||
end;
|
||||
|
||||
procedure RangeCoderInit(var Instance:TRangeCoder);
|
||||
begin
|
||||
Instance.RangeCode:=0;
|
||||
Instance.RangeLow:=0;
|
||||
Instance.RangeHigh:=$ffffffff;
|
||||
end;
|
||||
|
||||
procedure RangeCoderStart(var Instance:TRangeCoder);
|
||||
var Counter:longword;
|
||||
begin
|
||||
for Counter:=1 to 4 do begin
|
||||
Instance.RangeCode:=(Instance.RangeCode shl 8) or RangeCoderRead(Instance);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure RangeCoderFlush(var Instance:TRangeCoder);
|
||||
var Counter:longword;
|
||||
begin
|
||||
for Counter:=1 to 4 do begin
|
||||
RangeCoderWrite(Instance,Instance.RangeHigh shr 24);
|
||||
Instance.RangeHigh:=Instance.RangeHigh shl 8;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure RangeCoderEncodeNormalize(var Instance:TRangeCoder);
|
||||
begin
|
||||
while ((Instance.RangeLow xor Instance.RangeHigh) and $ff000000)=0 do begin
|
||||
RangeCoderWrite(Instance,Instance.RangeHigh shr 24);
|
||||
Instance.RangeLow:=Instance.RangeLow shl 8;
|
||||
Instance.RangeHigh:=(Instance.RangeHigh shl 8) or $ff;
|
||||
end;
|
||||
end;
|
||||
|
||||
function RangeCoderEncodeBit(var Instance:TRangeCoder;var Probability:longword;Shift,BitValue:longword):longword;
|
||||
begin
|
||||
Instance.RangeMiddle:=Instance.RangeLow+(((Instance.RangeHigh-Instance.RangeLow) shr 12)*Probability);
|
||||
if BitValue<>0 then begin
|
||||
inc(Probability,($fff-Probability) shr Shift);
|
||||
Instance.RangeHigh:=Instance.RangeMiddle;
|
||||
end else begin
|
||||
dec(Probability,Probability shr Shift);
|
||||
Instance.RangeLow:=Instance.RangeMiddle+1;
|
||||
end;
|
||||
RangeCoderEncodeNormalize(Instance);
|
||||
result:=BitValue;
|
||||
end;
|
||||
|
||||
function RangeCoderEncodeBitWithoutProbability(var Instance:TRangeCoder;BitValue:longword):longword;
|
||||
begin
|
||||
Instance.RangeMiddle:=Instance.RangeLow+((Instance.RangeHigh-Instance.RangeLow) shr 1);
|
||||
if BitValue<>0 then begin
|
||||
Instance.RangeHigh:=Instance.RangeMiddle;
|
||||
end else begin
|
||||
Instance.RangeLow:=Instance.RangeMiddle+1;
|
||||
end;
|
||||
RangeCoderEncodeNormalize(Instance);
|
||||
result:=BitValue;
|
||||
end;
|
||||
|
||||
procedure RangeCoderDecodeNormalize(var Instance:TRangeCoder);
|
||||
begin
|
||||
while ((Instance.RangeLow xor Instance.RangeHigh) and $ff000000)=0 do begin
|
||||
Instance.RangeLow:=Instance.RangeLow shl 8;
|
||||
Instance.RangeHigh:=(Instance.RangeHigh shl 8) or $ff;
|
||||
Instance.RangeCode:=(Instance.RangeCode shl 8) or RangeCoderRead(Instance);
|
||||
end;
|
||||
end;
|
||||
|
||||
function RangeCoderDecodeBit(var Instance:TRangeCoder;var Probability:longword;Shift:longword):longword;
|
||||
begin
|
||||
Instance.RangeMiddle:=Instance.RangeLow+(((Instance.RangeHigh-Instance.RangeLow) shr 12)*Probability);
|
||||
if Instance.RangeCode<=Instance.RangeMiddle then begin
|
||||
inc(Probability,($fff-Probability) shr Shift);
|
||||
Instance.RangeHigh:=Instance.RangeMiddle;
|
||||
result:=1;
|
||||
end else begin
|
||||
dec(Probability,Probability shr Shift);
|
||||
Instance.RangeLow:=Instance.RangeMiddle+1;
|
||||
result:=0;
|
||||
end;
|
||||
RangeCoderDecodeNormalize(Instance);
|
||||
end;
|
||||
|
||||
function RangeCoderDecodeBitWithoutProbability(var Instance:TRangeCoder):longword;
|
||||
begin
|
||||
Instance.RangeMiddle:=Instance.RangeLow+((Instance.RangeHigh-Instance.RangeLow) shr 1);
|
||||
if Instance.RangeCode<=Instance.RangeMiddle then begin
|
||||
Instance.RangeHigh:=Instance.RangeMiddle;
|
||||
result:=1;
|
||||
end else begin
|
||||
Instance.RangeLow:=Instance.RangeMiddle+1;
|
||||
result:=0;
|
||||
end;
|
||||
RangeCoderDecodeNormalize(Instance);
|
||||
end;
|
||||
|
||||
function RangeCoderEncodeDirectBits(var Instance:TRangeCoder;Bits,Value:longword):longword;
|
||||
begin
|
||||
while Bits>0 do begin
|
||||
dec(Bits);
|
||||
RangeCoderEncodeBitWithoutProbability(Instance,(Value shr Bits) and 1);
|
||||
end;
|
||||
result:=Value;
|
||||
end;
|
||||
|
||||
function RangeCoderDecodeDirectBits(var Instance:TRangeCoder;Bits:longword):longword;
|
||||
begin
|
||||
result:=0;
|
||||
while Bits>0 do begin
|
||||
dec(Bits);
|
||||
inc(result,result+RangeCoderDecodeBitWithoutProbability(Instance));
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
8
src/makeunixlinuxbsdfreepascal
Normal file
8
src/makeunixlinuxbsdfreepascal
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#!/bin/sh
|
||||
# Tested with FreePascal 2.6.0
|
||||
# fpc.exe must be in your PATH environment variable
|
||||
rm -f *.ppu
|
||||
rm -f *.o
|
||||
fpc -B -Sd -O3 micro64disktool.dpr
|
||||
rm -f *.ppu
|
||||
rm -f *.o
|
||||
6
src/makewindelphi.bat
Normal file
6
src/makewindelphi.bat
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
@echo off
|
||||
rem Tested with Borland Delphi 7 and Delphi XE3
|
||||
rem You must adjust the path to your dcc32.exe of your Delphi installation
|
||||
del *.dcu
|
||||
"c:\Program Files (x86)\Borland\Delphi7\bin\dcc32.exe" -b micro64disktool.dpr
|
||||
del *.dcu
|
||||
8
src/makewinfreepascal.bat
Normal file
8
src/makewinfreepascal.bat
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
@echo off
|
||||
rem Tested with FreePascal 2.6.0
|
||||
rem fpc.exe must be in your %PATH% environment variable
|
||||
del *.o
|
||||
del *.ppu
|
||||
fpc -B -Sd -O3 micro64disktool.dpr
|
||||
del *.o
|
||||
del *.ppu
|
||||
BIN
src/micro64disktool
Normal file
BIN
src/micro64disktool
Normal file
Binary file not shown.
38
src/micro64disktool.cfg
Normal file
38
src/micro64disktool.cfg
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
-$A8
|
||||
-$B-
|
||||
-$C+
|
||||
-$D+
|
||||
-$E-
|
||||
-$F-
|
||||
-$G+
|
||||
-$H+
|
||||
-$I+
|
||||
-$J-
|
||||
-$K-
|
||||
-$L+
|
||||
-$M-
|
||||
-$N+
|
||||
-$O+
|
||||
-$P+
|
||||
-$Q-
|
||||
-$R-
|
||||
-$S-
|
||||
-$T-
|
||||
-$U-
|
||||
-$V+
|
||||
-$W-
|
||||
-$X+
|
||||
-$YD
|
||||
-$Z1
|
||||
-cg
|
||||
-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
|
||||
-H+
|
||||
-W+
|
||||
-M
|
||||
-$M16384,1048576
|
||||
-K$00400000
|
||||
-LE"c:\program files (x86)\borland\delphi7\Projects\Bpl"
|
||||
-LN"c:\program files (x86)\borland\delphi7\Projects\Bpl"
|
||||
-w-UNSAFE_TYPE
|
||||
-w-UNSAFE_CODE
|
||||
-w-UNSAFE_CAST
|
||||
7
src/micro64disktool.cfp
Normal file
7
src/micro64disktool.cfp
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
[Settings]
|
||||
Syntax=1280
|
||||
CodeGen=512
|
||||
Optimizer=2
|
||||
Dialect=2
|
||||
Parameters=
|
||||
DebuggerArguments=
|
||||
136
src/micro64disktool.dof
Normal file
136
src/micro64disktool.dof
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
[FileVersion]
|
||||
Version=7.0
|
||||
[Compiler]
|
||||
A=8
|
||||
B=0
|
||||
C=1
|
||||
D=1
|
||||
E=0
|
||||
F=0
|
||||
G=1
|
||||
H=1
|
||||
I=1
|
||||
J=0
|
||||
K=0
|
||||
L=1
|
||||
M=0
|
||||
N=1
|
||||
O=1
|
||||
P=1
|
||||
Q=0
|
||||
R=0
|
||||
S=0
|
||||
T=0
|
||||
U=0
|
||||
V=1
|
||||
W=0
|
||||
X=1
|
||||
Y=1
|
||||
Z=1
|
||||
ShowHints=1
|
||||
ShowWarnings=1
|
||||
UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
|
||||
NamespacePrefix=
|
||||
SymbolDeprecated=1
|
||||
SymbolLibrary=1
|
||||
SymbolPlatform=1
|
||||
UnitLibrary=1
|
||||
UnitPlatform=1
|
||||
UnitDeprecated=1
|
||||
HResultCompat=1
|
||||
HidingMember=1
|
||||
HiddenVirtual=1
|
||||
Garbage=1
|
||||
BoundsError=1
|
||||
ZeroNilCompat=1
|
||||
StringConstTruncated=1
|
||||
ForLoopVarVarPar=1
|
||||
TypedConstVarPar=1
|
||||
AsgToTypedConst=1
|
||||
CaseLabelRange=1
|
||||
ForVariable=1
|
||||
ConstructingAbstract=1
|
||||
ComparisonFalse=1
|
||||
ComparisonTrue=1
|
||||
ComparingSignedUnsigned=1
|
||||
CombiningSignedUnsigned=1
|
||||
UnsupportedConstruct=1
|
||||
FileOpen=1
|
||||
FileOpenUnitSrc=1
|
||||
BadGlobalSymbol=1
|
||||
DuplicateConstructorDestructor=1
|
||||
InvalidDirective=1
|
||||
PackageNoLink=1
|
||||
PackageThreadVar=1
|
||||
ImplicitImport=1
|
||||
HPPEMITIgnored=1
|
||||
NoRetVal=1
|
||||
UseBeforeDef=1
|
||||
ForLoopVarUndef=1
|
||||
UnitNameMismatch=1
|
||||
NoCFGFileFound=1
|
||||
MessageDirective=1
|
||||
ImplicitVariants=1
|
||||
UnicodeToLocale=1
|
||||
LocaleToUnicode=1
|
||||
ImagebaseMultiple=1
|
||||
SuspiciousTypecast=1
|
||||
PrivatePropAccessor=1
|
||||
UnsafeType=0
|
||||
UnsafeCode=0
|
||||
UnsafeCast=0
|
||||
[Linker]
|
||||
MapFile=0
|
||||
OutputObjs=0
|
||||
ConsoleApp=1
|
||||
DebugInfo=0
|
||||
RemoteSymbols=0
|
||||
MinStackSize=16384
|
||||
MaxStackSize=1048576
|
||||
ImageBase=4194304
|
||||
ExeDescription=
|
||||
[Directories]
|
||||
OutputDir=
|
||||
UnitOutputDir=
|
||||
PackageDLLOutputDir=
|
||||
PackageDCPOutputDir=
|
||||
SearchPath=
|
||||
Packages=
|
||||
Conditionals=
|
||||
DebugSourceDirs=
|
||||
UsePackages=0
|
||||
[Parameters]
|
||||
RunParams=
|
||||
HostApplication=
|
||||
Launcher=
|
||||
UseLauncher=0
|
||||
DebugCWD=
|
||||
[Language]
|
||||
ActiveLang=
|
||||
ProjectLang=
|
||||
RootDir=
|
||||
[Version Info]
|
||||
IncludeVerInfo=0
|
||||
AutoIncBuild=0
|
||||
MajorVer=1
|
||||
MinorVer=0
|
||||
Release=0
|
||||
Build=0
|
||||
Debug=0
|
||||
PreRelease=0
|
||||
Special=0
|
||||
Private=0
|
||||
DLL=0
|
||||
Locale=1031
|
||||
CodePage=1252
|
||||
[Version Info Keys]
|
||||
CompanyName=
|
||||
FileDescription=
|
||||
FileVersion=1.0.0.0
|
||||
InternalName=
|
||||
LegalCopyright=
|
||||
LegalTrademarks=
|
||||
OriginalFilename=
|
||||
ProductName=
|
||||
ProductVersion=1.0.0.0
|
||||
Comments=
|
||||
109
src/micro64disktool.dpr
Normal file
109
src/micro64disktool.dpr
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
(*
|
||||
** This file is part of the Micro64 Disk Tool.
|
||||
** Copyright (C) 2002-2013 by Benjamin Rosseaux
|
||||
**
|
||||
** The source code of the Micro64 Disk Tool and helper tools are
|
||||
** distributed under the Library GNU General Public License
|
||||
** (see the file COPYING) with the following modification:
|
||||
**
|
||||
** As a special exception, the copyright holders of this software give you
|
||||
** permission to link this software with independent modules to produce
|
||||
** an executable, regardless of the license terms of these independent modules,
|
||||
** and to copy and distribute the resulting executable under terms of your
|
||||
** choice, provided that you also meet, for each linked independent module,
|
||||
** the terms and conditions of the license of that module. An independent
|
||||
** module is a module which is not derived from or based on this software. If
|
||||
** you modify this software, you may extend this exception to your version of
|
||||
** the software, but you are not obligated to do so. If you do not wish to do
|
||||
** so, delete this exception statement from your version.
|
||||
**
|
||||
** If you didn't receive a copy of the file COPYING, contact:
|
||||
** Free Software Foundation
|
||||
** 675 Mass Ave
|
||||
** Cambridge, MA 02139
|
||||
** USA
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
*)
|
||||
program micro64disktool;
|
||||
{-$DEFINE DEBUG}
|
||||
{$IFDEF FPC}
|
||||
{$MODE DELPHI}
|
||||
{$WARNINGS OFF}
|
||||
{$HINTS OFF}
|
||||
{$OVERFLOWCHECKS OFF}
|
||||
{$RANGECHECKS OFF}
|
||||
{$IFDEF CPUI386}
|
||||
{$DEFINE CPU386}
|
||||
{$ASMMODE INTEL}
|
||||
{$ENDIF}
|
||||
{$IFDEF FPC_LITTLE_ENDIAN}
|
||||
{$DEFINE LITTLE_ENDIAN}
|
||||
{$ELSE}
|
||||
{$IFDEF FPC_BIG_ENDIAN}
|
||||
{$DEFINE BIG_ENDIAN}
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
{$ELSE}
|
||||
{$DEFINE LITTLE_ENDIAN}
|
||||
{$IFNDEF CPU64}
|
||||
{$DEFINE CPU32}
|
||||
{$ENDIF}
|
||||
{$OPTIMIZATION ON}
|
||||
{$setpeoptflags $140}
|
||||
{$ENDIF}
|
||||
{$ifdef WIN32}
|
||||
{$IMAGEBASE $500000}
|
||||
{$SETPEFLAGS $20}
|
||||
{-$APPTYPE GUI}
|
||||
{$APPTYPE CONSOLE}
|
||||
{$define windows}
|
||||
{$ENDIF}
|
||||
{$ifdef WIN64}
|
||||
{$APPTYPE GUI}
|
||||
{$APPTYPE CONSOLE}
|
||||
{$define windows}
|
||||
{$ENDIF}
|
||||
|
||||
uses
|
||||
SysUtils,
|
||||
BeRoStream in 'BeRoStream.pas',
|
||||
BeRoUtils in 'BeRoUtils.pas',
|
||||
ChecksumUtils in 'ChecksumUtils.pas',
|
||||
DiskImageD64 in 'DiskImageD64.pas',
|
||||
DiskImageFDI in 'DiskImageFDI.pas',
|
||||
DiskImageG64 in 'DiskImageG64.pas',
|
||||
DiskImageKryofluxStream in 'DiskImageKryofluxStream.pas',
|
||||
DiskImageNIB in 'DiskImageNIB.pas',
|
||||
DiskImageP64 in 'DiskImageP64.pas',
|
||||
GCR in 'GCR.pas',
|
||||
Globals in 'Globals.pas',
|
||||
RangeCoder in 'RangeCoder.pas';
|
||||
|
||||
begin
|
||||
writeln('Micro64 Disk Tool 20130113 - Copyright (C) 2012-2013, Benjamin ''BeRo'' Rosseaux');
|
||||
writeln('http://www.micro64.de/');
|
||||
if ParamCount=0 then begin
|
||||
writeln('Usage: ',ChangeFileExt(ExtractFileName(ParamStr(0)),''),' [options]');
|
||||
writeln('Options: +newd64 [filename.d64]');
|
||||
writeln(' +g642d64 [input.g64] [output.d64]');
|
||||
writeln(' +d642g64 [input.d64] [output.g64]');
|
||||
writeln(' +g642p64 [input.g64] [output.p64]');
|
||||
writeln(' +p642g64 [input.p64] [output.g64]');
|
||||
writeln(' +fdi2p64 [input.fdi] [output.p64]');
|
||||
writeln(' +p642fdi [input.p64] [output.fdi]');
|
||||
writeln(' +nib2g64 [input.nib] [output.g64]');
|
||||
writeln(' +dumpfdi [input.fdi] [output.log]');
|
||||
writeln(' +dumpp64 [input.p64] [output.log]');
|
||||
writeln(' +dumpp64halftrack [input.p64] [output.log] ([halftrack])');
|
||||
writeln(' +kryofluxstream2p64 [inputpathprefix] [output.p64] ([side(0/1)]) ([rpm(180-360)]) ([doublewidetrack(0/1)])');
|
||||
writeln(' +kryofluxstream2fdi [inputpathprefix] [output.fdi] ([side(0/1)]) ([rpm(180-360)]) ([doublewidetrack(0/1)])');
|
||||
end else begin
|
||||
ParseParameter;
|
||||
end;
|
||||
end.
|
||||
|
||||
|
||||
140
src/micro64disktool.dproj
Normal file
140
src/micro64disktool.dproj
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{9402AD95-BDC7-47B0-B247-0F0E602E879B}</ProjectGuid>
|
||||
<MainSource>micro64disktool.dpr</MainSource>
|
||||
<Base>True</Base>
|
||||
<Config Condition="'$(Config)'==''">Release</Config>
|
||||
<TargetedPlatforms>1</TargetedPlatforms>
|
||||
<AppType>Console</AppType>
|
||||
<FrameworkType>None</FrameworkType>
|
||||
<ProjectVersion>14.3</ProjectVersion>
|
||||
<Platform Condition="'$(Platform)'==''">Win32</Platform>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
|
||||
<Base>true</Base>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Base)'=='true') or '$(Base_Win32)'!=''">
|
||||
<Base_Win32>true</Base_Win32>
|
||||
<CfgParent>Base</CfgParent>
|
||||
<Base>true</Base>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_1)'!=''">
|
||||
<Cfg_1>true</Cfg_1>
|
||||
<CfgParent>Base</CfgParent>
|
||||
<Base>true</Base>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_2)'!=''">
|
||||
<Cfg_2>true</Cfg_2>
|
||||
<CfgParent>Base</CfgParent>
|
||||
<Base>true</Base>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Base)'!=''">
|
||||
<DCC_S>false</DCC_S>
|
||||
<DCC_E>false</DCC_E>
|
||||
<DCC_ImageBase>00400000</DCC_ImageBase>
|
||||
<DCC_Namespace>System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)</DCC_Namespace>
|
||||
<DCC_K>false</DCC_K>
|
||||
<VerInfo_Keys>CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName=;CFBundleDisplayName=;CFBundleIdentifier=;CFBundleVersion=;CFBundlePackageType=;CFBundleSignature=;CFBundleAllowMixedLocalizations=;CFBundleExecutable=</VerInfo_Keys>
|
||||
<VerInfo_Locale>1031</VerInfo_Locale>
|
||||
<DCC_F>false</DCC_F>
|
||||
<DCC_N>false</DCC_N>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Base_Win32)'!=''">
|
||||
<DCC_Namespace>Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)</DCC_Namespace>
|
||||
<VerInfo_Keys>CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
|
||||
<VerInfo_Locale>1033</VerInfo_Locale>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Cfg_1)'!=''">
|
||||
<DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
|
||||
<DCC_Define>RELEASE;$(DCC_Define)</DCC_Define>
|
||||
<DCC_SymbolReferenceInfo>0</DCC_SymbolReferenceInfo>
|
||||
<DCC_DebugInformation>false</DCC_DebugInformation>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Cfg_2)'!=''">
|
||||
<DCC_Define>DEBUG;$(DCC_Define)</DCC_Define>
|
||||
<DCC_GenerateStackFrames>true</DCC_GenerateStackFrames>
|
||||
<DCC_Optimize>false</DCC_Optimize>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<DelphiCompile Include="$(MainSource)">
|
||||
<MainSource>MainSource</MainSource>
|
||||
</DelphiCompile>
|
||||
<DCCReference Include="BeRoStream.pas"/>
|
||||
<DCCReference Include="BeRoUtils.pas"/>
|
||||
<DCCReference Include="ChecksumUtils.pas"/>
|
||||
<DCCReference Include="DiskImageD64.pas"/>
|
||||
<DCCReference Include="DiskImageFDI.pas"/>
|
||||
<DCCReference Include="DiskImageG64.pas"/>
|
||||
<DCCReference Include="DiskImageKryofluxStream.pas"/>
|
||||
<DCCReference Include="DiskImageNIB.pas"/>
|
||||
<DCCReference Include="DiskImageP64.pas"/>
|
||||
<DCCReference Include="GCR.pas"/>
|
||||
<DCCReference Include="Globals.pas"/>
|
||||
<DCCReference Include="RangeCoder.pas"/>
|
||||
<BuildConfiguration Include="Debug">
|
||||
<Key>Cfg_2</Key>
|
||||
<CfgParent>Base</CfgParent>
|
||||
</BuildConfiguration>
|
||||
<BuildConfiguration Include="Base">
|
||||
<Key>Base</Key>
|
||||
</BuildConfiguration>
|
||||
<BuildConfiguration Include="Release">
|
||||
<Key>Cfg_1</Key>
|
||||
<CfgParent>Base</CfgParent>
|
||||
</BuildConfiguration>
|
||||
</ItemGroup>
|
||||
<ProjectExtensions>
|
||||
<Borland.Personality>Delphi.Personality.12</Borland.Personality>
|
||||
<Borland.ProjectType/>
|
||||
<BorlandProject>
|
||||
<Delphi.Personality>
|
||||
<Source>
|
||||
<Source Name="MainSource">micro64disktool.dpr</Source>
|
||||
</Source>
|
||||
<VersionInfo>
|
||||
<VersionInfo Name="IncludeVerInfo">False</VersionInfo>
|
||||
<VersionInfo Name="AutoIncBuild">False</VersionInfo>
|
||||
<VersionInfo Name="MajorVer">1</VersionInfo>
|
||||
<VersionInfo Name="MinorVer">0</VersionInfo>
|
||||
<VersionInfo Name="Release">0</VersionInfo>
|
||||
<VersionInfo Name="Build">0</VersionInfo>
|
||||
<VersionInfo Name="Debug">False</VersionInfo>
|
||||
<VersionInfo Name="PreRelease">False</VersionInfo>
|
||||
<VersionInfo Name="Special">False</VersionInfo>
|
||||
<VersionInfo Name="Private">False</VersionInfo>
|
||||
<VersionInfo Name="DLL">False</VersionInfo>
|
||||
<VersionInfo Name="Locale">1031</VersionInfo>
|
||||
<VersionInfo Name="CodePage">1252</VersionInfo>
|
||||
</VersionInfo>
|
||||
<VersionInfoKeys>
|
||||
<VersionInfoKeys Name="CompanyName"/>
|
||||
<VersionInfoKeys Name="FileDescription"/>
|
||||
<VersionInfoKeys Name="FileVersion">1.0.0.0</VersionInfoKeys>
|
||||
<VersionInfoKeys Name="InternalName"/>
|
||||
<VersionInfoKeys Name="LegalCopyright"/>
|
||||
<VersionInfoKeys Name="LegalTrademarks"/>
|
||||
<VersionInfoKeys Name="OriginalFilename"/>
|
||||
<VersionInfoKeys Name="ProductName"/>
|
||||
<VersionInfoKeys Name="ProductVersion">1.0.0.0</VersionInfoKeys>
|
||||
<VersionInfoKeys Name="Comments"/>
|
||||
<VersionInfoKeys Name="CFBundleName"/>
|
||||
<VersionInfoKeys Name="CFBundleDisplayName"/>
|
||||
<VersionInfoKeys Name="CFBundleIdentifier"/>
|
||||
<VersionInfoKeys Name="CFBundleVersion"/>
|
||||
<VersionInfoKeys Name="CFBundlePackageType"/>
|
||||
<VersionInfoKeys Name="CFBundleSignature"/>
|
||||
<VersionInfoKeys Name="CFBundleAllowMixedLocalizations"/>
|
||||
<VersionInfoKeys Name="CFBundleExecutable"/>
|
||||
</VersionInfoKeys>
|
||||
</Delphi.Personality>
|
||||
<Platforms>
|
||||
<Platform value="OSX32">False</Platform>
|
||||
<Platform value="Win32">True</Platform>
|
||||
<Platform value="Win64">False</Platform>
|
||||
</Platforms>
|
||||
</BorlandProject>
|
||||
<ProjectFileVersion>12</ProjectFileVersion>
|
||||
</ProjectExtensions>
|
||||
<Import Project="$(BDS)\Bin\CodeGear.Delphi.Targets" Condition="Exists('$(BDS)\Bin\CodeGear.Delphi.Targets')"/>
|
||||
<Import Project="$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj" Condition="Exists('$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj')"/>
|
||||
</Project>
|
||||
BIN
src/micro64disktool.res
Normal file
BIN
src/micro64disktool.res
Normal file
Binary file not shown.
Loading…
Reference in a new issue