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 |