Unit ICartROM;
{ ======================================================================== }
{  INTELLICART ROM manipulation routines.              J. Zbiciak, 2001    }
{                                                                          }
{  These routines are intended for reading and writing Intellicart ROM     }
{  images.  Portions of this code are based on Chad Schell's own routines  }
{  for generating Intellicart ROM images.                                  }
{ ======================================================================== }

{ ======================================================================== }
{  This program is free software; you can redistribute it and/or modify    }
{  it under the terms of the GNU General Public License as published by    }
{  the Free Software Foundation; either version 2 of the License, or       }
{  (at your option) any later version.                                     }
{                                                                          }
{  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.  See the GNU       }
{  General Public License for more details.                                }
{                                                                          }
{  You should have received a copy of the GNU General Public License       }
{  along with this program; if not, write to the Free Software             }
{  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               }
{ ======================================================================== }
{                 Copyright (c) 2001-+Inf, Joseph Zbiciak                  }
{ ======================================================================== }

Interface

Uses CRC16,IntvDis   ,Dialogs,HexWrite;

Function ICartROM_Load(Var F: File; Var IntvMem: CP1600Mem; Ignore_CRC: Boolean): Boolean;

Implementation

Function ICartROM_Load(Var F: File; Var IntvMem: CP1600Mem; Ignore_CRC: Boolean): Boolean;
{ ======================================================================== }
{  ICARTROM_LOAD -- Loads a .ROM image from a file into memory.            }
{ ======================================================================== }
Type
  TICartHeader = Packed Record
    BaudSync   : Byte;
    NumSegs    : Byte;
    NumSegsXor : Byte;
  End;

Var
  Low        : Integer;
  High       : Integer;
  CRCL       : Integer;
  CRCH       : Integer;
  I,J,K      : Integer;
  CRC_Expect : Word;
  CRC_Actual : Word;
  Header     : TICartHeader;
  W,W1       : Word;

Begin

  { -------------------------------------------------------------------- }
  {  First, check to see if the header passes initial muster.            }
  { -------------------------------------------------------------------- }

  BlockRead(F,Header,SizeOf(Header));
  If (Header.BaudSync <> $A8) Or
     (Header.NumSegs <> ($FF Xor Header.NumSegsXor)) Then
  Begin
    ICartROM_Load := False;      { Bad header }
    Exit;
  End;

  { -------------------------------------------------------------------- }
  {  Step through the ROM segments.                                      }
  { -------------------------------------------------------------------- }

  For I := 0 To Header.NumSegs - 1 Do
  Begin
    { ---------------------------------------------------------------- }
    {  Get the range of addresses for the ROM segment.                 }
    { ---------------------------------------------------------------- }

    BlockRead(F,W,2);
    Low  := Lo(W);
    High := Hi(W);

    If High < Low Then
    Begin
      ICartROM_Load := False;  { Bad ROM segment address range. }
      Exit;
    End;

    { Load the ROM into memory in 256-word chunks }

    For J := Low To High Do BlockRead(F,IntvMem[J Shl 8],512);

    { ---------------------------------------------------------------- }
    {  Check the CRC-16, unless instructed not to.  (We might do this  }
    {  to try to rescue a corrupt or tweaked ROM or something.)        }
    { ---------------------------------------------------------------- }

    BlockRead(F,W1,2);
    CRCL := Hi(W1);    { CRC is stored in the file in big-endian format }
    CRCH := Lo(W1);
    If Not Ignore_CRC Then
    Begin
      CRC_Expect := CRCL + (CRCH Shl 8);
      CRC_Actual := CRC16_Update($FFFF,Low);
      CRC_Actual := CRC16_Update(CRC_Actual,High);
      For J := Low To High Do
       CRC_Actual := CRC16_Block(CRC_Actual,IntvMem[J Shl 8],512);
      If CRC_Expect <> CRC_Actual Then
      Begin
        ICartROM_Load := False;  { CRC error in ROM segments. }
        Exit;
      End;
    End;

    { Since the Intellicart format stores actual game data in big-endian }
    { format, swap the bytes now that we have calculated the CRC         }

    For J := Low To High Do
    Begin
      For K := 0 To 255 Do
      Begin
        W := IntvMem[(J Shl 8) + K];
        IntvMem[(J Shl 8) + K] := (W Shr 8) + (W Shl 8);
      End; { For K }
    End; { For J }
  End; { For I }
  ICartROM_Load := True;
End; { ICartROM_Load }

{ ======================================================================== }
{                 Copyright (c) 2001-+Inf, Joseph Zbiciak                  }
{ ======================================================================== }
End.