|
Subject: Re: [stella] Atari 7800 From: Eckhard Stolberg <Eckhard_Stolberg@xxxxxxxxxxxxxxxxxxxxx> Date: Wed, 18 Nov 1998 16:35:48 +0100 |
At 12:40 17.11.98 -0600, you wrote:
>>Bruce Tomlin posted a Pascal version of the validation routine to RGVC
>>about two years ago. I think I still have this message somewhere and could
>>send it to you, if you want it.
>
>Absolutely! That would be awesome!
I'm not sure, if you still need this, since someone else already
posted a C version, but here is Bruce Tomlin's messege from RGVC.
Ciao, Eckhard Stolberg
============================================================================
Okay, here's the finished Turbo Pascal program to validate an Atari 7800
cartridge checksum. It expects a 64k dump file of the entire cartridge
address space, and if anyone ever comes up with the reverse algorithm, it
should automatically use it when the bytes from $FF80-$FFF7 are all $FF.
Of course if you ever make a cartridge of your own after the reverse
algorithm is discovered, you will want to set $FFF9 to $F7 (or $F3 if you
don't want the way-cool Atari logo to show on startup) to minimize the
time it takes to validate the checksum. The reset vector *MUST* point
into a checksummed region, and of course you don't want the checksum to go
down into a bank-selected region.
One important thing to note is that the 13 bits in the MSB end of the
result which are cleared before comparison *will be* different between the
result of the cartridge and checksum functions. This may have been due to
a short-cut to make the reverse algorithm computable within a reasonable
amount of time.
PROGRAM Crypt78;
{ $R+}
TYPE
Blk120 = ARRAY[0..$77+1] OF Byte;
Blk256 = ARRAY[0..$FF] OF Byte;
CONST
hex : String[16] = ('0123456789ABCDEF');
(*
A_cart : Blk120 = ($02,$E0,$77,$88,$A6,$1B,$03,$39, { from Monitor Cart }
$DE,$FC,$51,$11,$DD,$B9,$A9,$9B,
$12,$B6,$44,$CD,$DC,$6C,$BD,$06,
$AD,$FE,$7E,$56,$FA,$37,$B3,$58,
$6A,$85,$B4,$88,$39,$57,$8F,$ED,
$42,$A6,$88,$BE,$7A,$BC,$A2,$CD,
$A8,$07,$08,$DE,$8B,$93,$BF,$3A,
$74,$A1,$DC,$7E,$03,$9C,$AD,$3F,
$0F,$33,$E6,$F6,$CF,$83,$79,$2B,
$A1,$89,$9E,$6C,$DC,$56,$B1,$19,
$48,$C7,$00,$A0,$F9,$08,$6F,$C2,
$52,$71,$7D,$24,$A3,$9A,$B4,$99,
$1B,$5C,$6E,$18,$A8,$5A,$46,$DF,
$03,$91,$6E,$1E,$E6,$2C,$6C,$D2,
$0A,$C6,$93,$05,$8A,$CC,$4E,$B0,$FF);
*)
A_ROM : Blk120 = ($09,$CA,$C9,$C6,$B4,$12,$08,$1B,
$60,$58,$81,$4B,$86,$01,$D8,$BF,
$D9,$25,$A0,$7B,$DC,$32,$79,$84,
$3B,$7C,$BC,$2F,$E2,$E2,$FA,$8D,
$0A,$00,$3B,$C5,$EC,$AF,$2D,$8A,
$CD,$06,$93,$6A,$A5,$14,$46,$77,
$C4,$6A,$B2,$53,$36,$EF,$8C,$CE,
$0C,$A2,$68,$71,$D3,$73,$E8,$F7,
$6D,$06,$B5,$20,$EF,$23,$47,$0C,
$51,$55,$C8,$FE,$F4,$58,$C4,$3F,
$20,$A7,$67,$38,$B0,$76,$E2,$C4,
$D8,$05,$63,$F8,$3C,$58,$3B,$2D,
$22,$CC,$88,$B3,$71,$8F,$1D,$80,
$0A,$87,$BD,$A1,$59,$23,$E9,$70,
$E2,$D3,$EC,$46,$68,$80,$42,$39,$EA);
A_munge : ARRAY[0..255+8] OF Byte =
($C7,$65,$AB,$CA,$EE,$F7,$83,$09,
$E1,$D0,$92,$67,$62,$B6,$72,$55,
$8E,$91,$DC,$C5,$81,$BE,$78,$20,
$59,$B7,$E6,$3D,$06,$45,$AF,$C8,
$08,$31,$38,$D1,$FB,$73,$84,$A9,
$17,$FC,$34,$87,$A3,$94,$FA,$90,
$B8,$ED,$CE,$3B,$5B,$0A,$43,$D9,
$F3,$53,$82,$B3,$0D,$6D,$5A,$60,
$9D,$51,$A7,$B9,$11,$10,$BC,$E4,
$7F,$80,$41,$E7,$E3,$F6,$56,$26,
$35,$EC,$D6,$DF,$0C,$7F,$F4,$9E,
$AC,$52,$46,$EF,$CF,$BF,$A2,$3F,
$A4,$13,$15,$97,$4A,$1C,$B0,$42,
$8C,$B1,$05,$58,$80,$18,$77,$2B,
$02,$3E,$A8,$49,$1A,$6A,$CB,$6E,
$0B,$8A,$EB,$F1,$4F,$14,$79,$8B,
$D8,$9F,$9B,$57,$19,$F8,$2A,$2D,
$76,$0E,$E8,$2E,$4B,$F9,$07,$03,
$DE,$93,$16,$7E,$D4,$E5,$B2,$F0,
$7D,$7A,$DA,$D2,$A1,$CC,$1D,$E0,
$5E,$23,$A0,$95,$22,$1E,$36,$85,
$FE,$1F,$39,$AA,$89,$96,$AD,$0F,
$2F,$C0,$47,$27,$5D,$24,$EA,$C3,
$A5,$F5,$21,$5F,$1B,$40,$8F,$AE,
$74,$25,$DD,$C1,$7C,$CD,$A6,$70,
$D7,$33,$7B,$2C,$75,$BB,$86,$99,
$BD,$54,$9A,$6C,$63,$32,$48,$4C,
$8D,$BA,$5C,$61,$C4,$4E,$29,$37,
$12,$C6,$98,$9C,$D5,$69,$6B,$E2,
$04,$4D,$E9,$C2,$88,$3A,$DB,$64,
$01,$44,$6F,$B5,$F2,$30,$28,$FD,
$50,$71,$3C,$B4,$66,$68,$C9,$D3,
$CA,$83,$C7,$AB,$F7,$65,$09,$EE);
VAR
A_1800 : Blk256;
A_1900 : ARRAY[0..7] OF Blk120;
A_2000 : Blk120;
A_1A00 : Blk120;
A_cart : Blk120;
A_mem : ARRAY[$4000..$FFFF] OF Byte;
fname : String;
f : File;
PROCEDURE Write1Hex(n: Word);
BEGIN
n := n AND 15;
Write(Copy(hex,n+1,1));
END;
PROCEDURE Write2Hex(n: Word);
BEGIN
Write1Hex(n SHR 4);
Write1Hex(n);
END;
PROCEDURE Dump1800;
VAR
i : Integer;
BEGIN
FOR i := 0 TO $FF DO BEGIN
Write2Hex(A_1800[i]);
IF (i AND 15)=7 THEN Write(' ')
ELSE IF (i AND 15)=15 THEN WriteLn
ELSE Write(' ');
END;
WriteLn;
END;
PROCEDURE Dump120(VAR {read only} ary: Blk120);
VAR
i : Integer;
BEGIN
FOR i := 0 TO $77 DO BEGIN
Write2Hex(ary[i]);
IF (i AND 15)=7 THEN Write(' ')
ELSE IF (i AND 15)=15 THEN WriteLn
ELSE Write(' ');
END;
WriteLn;
WriteLn;
END;
PROCEDURE ReadBlock(addr,len: Word; buf: Pointer);
BEGIN
Seek(f,addr);
BlockRead(f,buf^,len);
END;
PROCEDURE BigRot;
VAR
i,j,n,carry : Integer;
BEGIN
A_1900[0,0] := 0;
FOR i := 0 TO 6 DO BEGIN
carry := 0;
FOR j := $78 DOWNTO 0 DO BEGIN
n := A_1900[i,j] * 2 + carry;
A_1900[i+1,j] := n AND 255;
carry := n SHR 8;
END;
END;
END;
PROCEDURE BigSub(i,j: Integer);
VAR
x,n,borrow : Integer;
BEGIN
borrow := 0;
FOR x := $78 DOWNTO 0 DO BEGIN
n := A_1800[i+x] - A_1900[j,x] - borrow;
A_1800[i+x] := n AND 255;
borrow := (n SHR 8) AND 1;
END;
x := -1;
WHILE borrow<>0 DO BEGIN
n := A_1800[i+x] - borrow;
A_1800[i+x] := n;
borrow := (n SHR 8) AND 1;
x := x - 1;
END;
END;
FUNCTION BigCmp(i,j: Integer): Boolean;
VAR
x : Integer;
BEGIN
x := 0;
WHILE A_1800[i+x] = A_1900[j,x] DO
x := x + 1;
BigCmp := (A_1800[i+x] > A_1900[j,x]);
END;
PROCEDURE BigDiv;
VAR
i,j : Integer;
BEGIN
BigRot;
A_1800[0] := 0;
FOR i := 0 TO $78 DO
FOR j := 7 DOWNTO 0 DO
IF BigCmp(i,j) THEN
BigSub(i,j);
END;
PROCEDURE BigAdd(i,j: Integer);
VAR
x,n,carry : Integer;
BEGIN
carry := 0;
FOR x := $78 DOWNTO 0 DO BEGIN
n := A_1800[i+x] + A_1900[j,x] + carry;
A_1800[i+x] := n AND 255;
carry := n SHR 8;
END;
x := -1;
WHILE carry<>0 DO BEGIN
n := A_1800[i+x] + carry;
A_1800[i+x] := n AND 255;
carry := n SHR 8;
x := x - 1;
END;
END;
PROCEDURE BigMul;
VAR
i,j : Integer;
BEGIN
BigRot;
FOR i := $F0 DOWNTO 0 DO
A_1800[i] := 0;
FOR i := $77 DOWNTO 0 DO BEGIN
FOR j := 0 TO 7 DO BEGIN
IF (A_2000[i] AND (1 SHL j))<>0 THEN
BigAdd(i+1,j);
END;
END;
END;
PROCEDURE MungeChecksum;
VAR
i : Integer;
BEGIN
WriteLn('MungeChecksum');
FOR i := 0 TO $77 DO
A_1900[0,i+1] := A_cart[i];
A_2000 := A_cart;
BigMul;
FOR i := 0 TO $77 DO
A_1900[0,i+1] := A_ROM[i];
BigDiv;
FOR i := 0 TO $77 DO
A_2000[i] := A_1800[i+$79];
Dump120(A_2000);
A_2000[0] := A_2000[0] AND 7;
A_2000[4] := 0;
END;
PROCEDURE X_23FF(page: Word; munge: Word; VAR a,carry: Integer);
VAR
i,n : Integer;
addr : Word;
BEGIN
addr := page SHL 8;
FOR i := 0 TO 255 DO BEGIN
n := a + A_1800[i] + carry;
carry := (n SHR 8) AND 1;
n := (n AND 255) + A_mem[addr+i] + carry;
a := A_munge[munge + (n AND 255)];
A_1800[i] := a AND 255;
carry := (n SHR 8) AND 1;
END;
END;
PROCEDURE ROLWork(VAR carry: Integer);
VAR
i,n : Integer;
BEGIN
FOR i := 0 TO 255 DO BEGIN
n := (A_1800[i] SHL 1) + carry;
A_1800[i] := n AND 255;
carry := n SHR 8;
END;
END;
PROCEDURE MungeCart;
VAR
i : Integer;
a,carry : Integer;
p : Integer;
BEGIN
WriteLn('MungeCart');
p := A_mem[$FFF9] AND $F0;
FOR i := 0 TO 255 DO
IF i IN [$80..$F8] THEN A_1800[i] := 0
ELSE A_1800[i] := A_mem[$FF00+i];
a := 0;
carry := 1;
FOR i := p TO $FE DO BEGIN
X_23FF(i,0,a,carry);
carry := 0;
END;
carry := 1;
ROLWork(carry);
ROLWork(carry);
FOR i := $FE DOWNTO p DO BEGIN
X_23FF(i,8,a,carry);
carry := 1;
END;
{Dump1800;}
FOR i := 0 TO $77 DO
A_1A00[i] := A_1800[i] XOR A_1800[i+$50] XOR A_1800[i+$88];
Dump120(A_1A00);
A_1A00[0] := A_1A00[0] AND 7;
A_1A00[4] := 0;
END;
VAR
i : Integer;
BEGIN
WriteLn;
FillChar(A_1800,SizeOf(A_1800),#0);
FillChar(A_1900,SizeOf(A_1900),#0);
FillChar(A_2000,SizeOf(A_2000),#0);
IF ParamCount=0 THEN fname := 'HATTRICK.BIN'
ELSE fname := ParamStr(1);
Assign(f,fname);
Reset(f,1);
ReadBlock($FF80,SizeOf(A_cart),@A_cart);
ReadBlock($4000,SizeOf(A_mem) ,@A_mem);
Close(f);
MungeChecksum;
MungeCart;
i := 0;
WHILE (i<=$77) AND (A_1A00[i]=A_2000[i]) DO
i := i + 1;
IF i=$78 THEN WriteLn('Cartridge checksum for ',fname,' is valid!')
ELSE WriteLn('Cartridge checksum for ',fname,' is not valid!');
WriteLn;
END.
--
Archives (includes files) at http://www.biglist.com/lists/stella/archives/
Unsub & more at http://www.biglist.com/lists/stella/
| Current Thread |
|---|
|
| <- Previous | Index | Next -> |
|---|---|---|
| Re: [stella] Atari 7800, Bob Colbert | Thread | Re: [stella] Atari 7800, Bob Colbert |
| Re: [stella] Atari 7800, Dan Boris | Date | Re: [stella] Atari 7800, Teknovore |
| Month |