Unit AtariDis;

Interface

Uses Profile;

Type
  TDisArray   = Packed Array[0..62 * 1024 - 1] Of Boolean;
  TGameROM    = Packed Array[0..65535] Of Byte;
  TASeg       = Packed Array[0..8191] Of Byte;
  TBankSwitch = Packed Array[0..8191] Of Byte;

Const
  ListingFileName : String = 'LISTING.ASM';
  BreakInstruction = 2;

  Timer_And : Packed Array[$0..$1F] Of Byte =
   ($80,$81,$82,$83,$84,$85,$84,$85,$80,$81,$82,$83,$84,$85,$84,$85,
    $94,$95,$96,$97,$94,$95,$96,$97,$94,$95,$96,$97,$94,$95,$96,$97);

  Bytes : Packed Array[0..255] Of Byte =
   (1,2,1,2,2,2,2,2, 1,2,1,2,3,3,3,3,  { 00-0F }
    2,2,1,2,2,2,2,2, 1,3,1,3,3,3,3,3,  { 10-1F }
    3,2,1,2,2,2,2,2, 1,2,1,2,3,3,3,3,  { 20-2F }
    2,2,1,2,2,2,2,2, 1,3,1,3,3,3,3,3,  { 30-3F }
    1,2,1,2,2,2,2,2, 1,2,1,2,3,3,3,3,  { 40-4F }
    2,2,1,2,2,2,2,2, 1,3,1,3,3,3,3,3,  { 50-5F }
    1,2,1,2,2,2,2,2, 1,2,1,2,3,3,3,3,  { 60-6F }
    2,2,1,2,2,2,2,2, 1,3,1,3,3,3,3,3,  { 70-7F }
    2,2,2,2,2,2,2,2, 1,1,1,2,3,3,3,3,  { 80-8F }
    2,2,1,2,2,2,2,2, 1,3,1,3,3,3,3,3,  { 90-9F }
    2,2,2,1,2,2,2,2, 1,2,1,2,3,3,3,3,  { A0-AF }
    2,2,1,2,2,2,2,2, 1,3,1,3,3,3,3,3,  { B0-BF }
    2,2,2,2,2,2,2,2, 1,2,1,2,3,3,3,3,  { C0-CF }
    2,2,1,2,2,2,2,2, 1,3,1,3,3,3,3,3,  { D0-DF }
    2,2,2,2,2,2,2,2, 1,2,1,2,3,3,3,3,  { E0-EF }
    2,2,1,2,2,2,2,2, 1,3,1,3,1,3,3,3); { F0-FF }

  Mnem : Packed Array[0..255] Of String[3] =
   ('BRK','ORA','   ','slo','skb','ORA','ASL','slo',   { 00-07 }
    'PHP','ORA','ASL','anc','skw','ORA','ASL','slo',   { 08-0F }
    'BPL','ORA','   ','slo','skb','ORA','ASL','slo',   { 10-17 }
    'CLC','ORA','NOP','slo','skw','ORA','ASL','slo',   { 18-1F }
    'JSR','AND','   ','rla','BIT','AND','ROL','rla',   { 20-27 }
    'PLP','AND','ROL','anc','BIT','AND','ROL','rla',   { 28-2F }
    'BMI','AND','   ','rla','skb','AND','ROL','rla',   { 30-37 }
    'SEC','AND','NOP','rla','skw','AND','ROL','rla',   { 38-3F }
    'RTI','EOR','   ','sre','skb','EOR','LSR','sre',   { 40-47 }
    'PHA','EOR','LSR','asr','JMP','EOR','LSR','sre',   { 48-4F }
    'BVC','EOR','   ','sre','skb','EOR','LSR','sre',   { 50-57 }
    'CLI','EOR','NOP','sre','skw','EOR','LSR','sre',   { 58-5F }
    'RTS','ADC','   ','rra','skb','ADC','ROR','rra',   { 60-67 }
    'PLA','ADC','ROR','arr','JMP','ADC','ROR','rra',   { 68-6F }
    'BVS','ADC','   ','rra','skb','ADC','ROR','rra',   { 70-77 }
    'SEI','ADC','NOP','rra','skw','ADC','ROR','rra',   { 78-7F }
    'skb','STA','skb','sax','STY','STA','STX','sax',   { 80-87 }
    'DEY','NOP','TXA','ane','STY','STA','STX','sax',   { 88-8F }
    'BCC','STA','   ','sha','STY','STA','STX','sax',   { 90-97 }
    'TYA','STA','TXS','shs','shy','STA','shx','sha',   { 98-9F }
    'LDY','LDA','LDX','lax','LDY','LDA','LDX','lax',   { A0-A7 }
    'TAY','LDA','TAX','lxa','LDY','LDA','LDX','lax',   { A8-AF }
    'BCS','LDA','   ','lax','LDY','LDA','LDX','lax',   { B0-B7 }
    'CLV','LDA','TSX','las','LDY','LDA','LDX','lax',   { B8-BF }
    'CPY','CMP','skb','dcp','CPY','CMP','DEC','dcp',   { C0-C7 }
    'INY','CMP','DEX','sbx','CPY','CMP','DEC','dcp',   { C8-CF }
    'BNE','CMP','   ','dcp','skb','CMP','DEC','dcp',   { D0-D7 }
    'CLD','CMP','NOP','dcp','skw','CMP','DEC','dcp',   { D8-DF }
    'CPX','SBC','skb','isb','CPX','SBC','INC','isb',   { E0-E7 }
    'INX','SBC','NOP','SBC','CPX','SBC','INC','isb',   { E8-EF }
    'BEQ','SBC','   ','isb','skb','SBC','INC','isb',   { F0-F7 }
    'SED','SBC','NOP','isb','skw','SBC','INC','isb');  { F8-FF }

  ATyp : Packed Array[0..255] Of String[3] =
   ('IMP','I.X','   ','I.X','IMP','Z.P','Z.P','Z.P',   { 00-07 }
    'IMP','IMM','ACC','IMM','IMP','ABS','ABS','ABS',   { 08-0F }
    'REL','I.Y','   ','I.Y','IMP','Z.X','Z.X','Z.X',   { 10-17 }
    'IMP','A.Y','IMP','A.Y','IMP','A.X','A.X','A.X',   { 18-1F }
    'ABS','I.X','   ','I.X','Z.P','Z.P','Z.P','Z.P',   { 20-27 }
    'IMP','IMM','ACC','IMM','ABS','ABS','ABS','ABS',   { 28-2F }
    'REL','I.Y','   ','I.Y','IMP','Z.X','Z.X','Z.X',   { 30-37 }
    'IMP','A.Y','IMP','A.Y','IMP','A.X','A.X','A.X',   { 38-3F }
    'IMP','I.X','   ','I.X','IMP','Z.P','Z.P','Z.P',   { 40-47 }
    'IMP','IMM','ACC','IMM','ABS','ABS','ABS','ABS',   { 48-4F }
    'REL','I.Y','   ','I.Y','IMP','Z.X','Z.X','Z.X',   { 50-57 }
    'IMP','A.Y','IMP','A.Y','IMP','A.X','A.X','A.X',   { 58-5F }
    'IMP','I.X','   ','I.X','IMP','Z.P','Z.P','Z.P',   { 60-67 }
    'IMP','IMM','ACC','IMM','IND','ABS','ABS','ABS',   { 68-6F }
    'REL','I.Y','   ','I.Y','IMP','Z.X','Z.X','Z.X',   { 70-77 }
    'IMP','A.Y','IMP','A.Y','IMP','A.X','A.X','A.X',   { 78-7F }
    'IMP','I.X','IMP','I.X','Z.P','Z.P','Z.P','Z.P',   { 80-87 }
    'IMP','IMP','IMP','IMM','ABS','ABS','ABS','ABS',   { 88-8F }
    'REL','I.Y','   ','I.Y','Z.X','Z.X','Z.Y','Z.Y',   { 90-97 }
    'IMP','A.Y','IMP','IMP','A.X','A.X','A.Y','A.Y',   { 98-9F }
    'IMM','I.X','IMM','I.X','Z.P','Z.P','Z.P','Z.P',   { A0-A7 }
    'IMP','IMM','IMP','I+A','ABS','ABS','ABS','ABS',   { A8-AF }
    'REL','I.Y','   ','I.Y','Z.X','Z.X','Z.Y','Z.Y',   { B0-B7 }
    'IMP','A.Y','IMP','ASY','A.X','A.X','A.Y','A.Y',   { B8-BF }
    'IMM','I.X','IMP','I.X','Z.P','Z.P','Z.P','Z.P',   { C0-C7 }
    'IMP','IMM','IMP','IMM','ABS','ABS','ABS','ABS',   { C8-CF }
    'REL','I.Y','   ','I.Y','IMP','Z.X','Z.X','Z.X',   { D0-D7 }
    'IMP','A.Y','IMP','A.Y','IMP','A.X','A.X','A.X',   { D8-DF }
    'IMM','I.X','IMP','I.X','Z.P','Z.P','Z.P','Z.P',   { E0-E7 }
    'IMP','IMM','IMP','IMM','ABS','ABS','ABS','ABS',   { E8-EF }
    'REL','I.Y','   ','I.Y','IMP','Z.X','Z.X','Z.X',   { F0-F7 }
    'IMP','A.Y','IMP','A.Y','IMP','A.X','A.Y','A.X');  { F8-FF }

  TIA_Name : Array[0..$2C] Of String[6] =
   ('VSYNC' ,'VBLANK','WSYNC' ,'RSYNC' ,'NUSIZ0','NUSIZ1','COLUP0','COLUP1',
    'COLUPF','COLUBK','CTRLPF','REFP0' ,'REFP1' ,'PF0'   ,'PF1'   ,'PF2',
    'RESP0' ,'RESP1' ,'RESM0' ,'RESM1' ,'RESBL' ,'AUDC0' ,'AUDC1' ,'AUDF0',
    'AUDF1' ,'AUDV0' ,'AUDV1' ,'GRP0'  ,'GRP1'  ,'ENAM0' ,'ENAM1' ,'ENABL' ,
    'HMP0'  ,'HMP1'  ,'HMM0'  ,'HMM1'  ,'HMBL'  ,'VDELP0','VDELP1','VDELBL',
    'RESMP0','RESMP1','HMOVE' ,'HMCLR' ,'CXCLR');

  PIA_Name : Array[$280..$297] Of String[8] =
   ('SWCHA','SWACNT','SWCHB','SWBCNT','INTTIM','INTRPT','','','','','','','','',
    '','','','','','','TIM1T','TIM8T','TIM64T','TIM1024T');

  TIA_Read_Name : Array[0..$F] Of String[7] =
   ('CXM0P' ,'CXM1P', 'CXP0FB','CXP1FB','CXM0FB','CXM1FB','CXBLPF','CXPPMM',
    'INPUT0','INPUT1','INPUT2','INPUT3','INPUT4','INPUT5','0E/000E','0F/000F');

Var
  Executed : TDisArray;
  Branched : TDisArray;

Procedure Disassemble(Var BankSwitch: TBankSwitch;
                      Cart: TCart; ROMSize: LongInt);
Function AtariSegW(Addr: Word): Word;
Function ROMBackupW(Addr: Word): Word;

Implementation

Uses HexWrite,HandTIA;

Function AtariSegW(Addr: Word): Word;
Var L,H: Word;
Begin
  L := AtariSeg[Addr];
  H := AtariSeg[Addr + 1];
  AtariSegW := (H Shl 8) + L;
End; // AtariSegW

Function ROMBackupW(Addr: Word): Word;
Var L,H: Word;
Begin
  L := ROMBackup[Addr];
  H := ROMBackup[Addr + 1];
  ROMBackupW := L + (H Shl 8);
End; { ROMBackupW }

Procedure Disassemble(Var BankSwitch: TBankSwitch;
                      Cart: TCart; ROMSize: LongInt);
Var
  I,J      : LongInt;{Word;}
  Start    : Word;
  Listing  : Text;
  Opcode   : Byte;
  DBStart  : Word;
  B        : Byte;
  OTyp     : String[3];
  Bank     : Word;
  OldASeg  : Packed Array[0..4095] Of Byte;
  BAddr    : Word;
  NewBank  : Word;
  BankSize : Word;

  Procedure Unassemble(PC,Bank: Word);
  Var
    Addr     : Word;
//    _Addr    : Word;
    B        : Byte;
    Instr    : String[3];
    Opcode   : Byte;
    _PC      : Word;
    NewBank  : Word;

    Function BankPC(PC,Bank: Word): Word;
    Begin
      If Cart = ctMNetwork Then
      Begin
        If PC < $1800
         Then BankPC := PC - $1000 + Bank * BankSize
         Else BankPC := PC - $1800 +    7 * BankSize;
      End
      Else BankPC := PC - $1000 + Bank * BankSize;
    End; { BankPC }

  Begin

    { Tally instructions }

    _PC := BankPC(PC,Bank);

    Branched[_PC] := True;
    While Not Executed[_PC] Do
    Begin
      Executed[_PC] := True;
      Opcode         := AtariSeg[PC];
      Instr          := Mnem[Opcode];

      { Handle some bankswitching }

      If ATyp[Opcode] = 'ABS' Then
      Begin
        Addr := AtariSegW(PC + 1) And $1FFF;
        If BankSwitch[Addr] <> 0 Then
        Begin
          Case BankSwitch[Addr] Of
            1..13: Begin                             { 2k/4k/8k/16k }
                     NewBank := (BankSwitch[Addr] - 1) Shr 2;
                     Move(ROMBackup[NewBank * BankSize],AtariSeg[$1000],BankSize);
                     Unassemble(PC + Word(Bytes[Opcode]),NewBank);
                     Move(ROMBackup[Bank * BankSize],AtariSeg[$1000],BankSize);
                   End;
         $21..$29: Begin                             { CBS }
                     NewBank := (BankSwitch[Addr] - $21) Shr 2;
                     Move(ROMBackup[NewBank * BankSize],AtariSeg[$1000],BankSize);
                     Unassemble(PC + Word(Bytes[Opcode]),NewBank);
                     Move(ROMBackup[Bank * BankSize],AtariSeg[$1000],BankSize);
                   End;
         $40..$4F: Begin                             { SuperChip }
                     NewBank := BankSwitch[Addr] - $40;
                     Move(ROMBackup[NewBank * BankSize],AtariSeg[$1000],BankSize);
                     Unassemble(PC + Word(Bytes[Opcode]),NewBank);
                     Move(ROMBackup[Bank * BankSize],AtariSeg[$1000],BankSize);
                   End;
         $D0..$D6: Begin                             { SuperChip }
                     NewBank := BankSwitch[Addr] - $D0;
                     Move(ROMBackup[NewBank * BankSize],AtariSeg[$1000],BankSize);
                     Unassemble(PC + Word(Bytes[Opcode]),NewBank);
                     Move(ROMBackup[Bank * BankSize],AtariSeg[$1000],BankSize);
                   End;
          End; { Case }
        End;
      End;

      { Look for control transfer instructions }

      If (Instr = 'JSR') Or
         (Instr = 'BPL') Or
         (Instr = 'BMI') Or
         (Instr = 'BVC') Or
         (Instr = 'BVS') Or
         (Instr = 'BEQ') Or
         (Instr = 'BNE') Or
         (Instr = 'BCC') Or
         (Instr = 'BCS') Then
      Begin
        If Instr = 'JSR'
         Then Addr := AtariSegW(PC + 1) And $1FFF
         Else
         Begin
           B := AtariSeg[PC + 1];
           Asm
             MOV   BX,WORD PTR PC
             ADD   BX,2
             MOV   AL,BYTE PTR B
             CBW
             ADD   BX,AX
             MOV   WORD PTR Addr,BX
           End; { Asm }
         End;
//        _Addr            := Addr - $1000 + Bank * BankSize;
  {      Branched[_Addr] := True;}
        Unassemble(Addr,Bank);
      End;
      If Instr <> 'RTS' Then
      Begin
        If Instr = 'JMP' Then
        Begin
          If ATyp[Opcode] = 'ABS'
           Then PC := AtariSegW(PC + 1) And $1FFF
           Else PC := AtariSegW(AtariSegW(PC + 1) And $1FFF) And $1FFF;
{          _PC := PC - $1000 + Bank * BankSize;}
          _PC := BankPC(PC,Bank);
          Branched[_PC] := True;
        End
        Else Inc(PC,Word(Bytes[Opcode]));
      End;
      _PC := BankPC(PC,Bank);
{      _PC := PC - $1000 + Bank * BankSize;}
    End; { While }
  End; { Unassemble }

  Function TransWordWrite(Addr: Word): String;
  Begin
    If (Addr < $80) Or ((Addr >= $100) And (Addr < $180)) Then Addr := Addr And $3F;
    Case Addr Of
      0..$2C: TransWordWrite := TIA_Name[Addr];
{    $280..$297: TransWordWrite := PIA_Name[Addr];
  $380..$397: TransWordWrite := PIA_Name[Addr - $100];}
  $200..$3FF: TransWordWrite := PIA_Name[$200 Or Timer_And[Addr And $1F]];
    Else TransWordWrite := HexWord(Addr);
    End; { Case }
  End; { TransWordWrite }


  Function TransWordRead(Addr: Word): String;
  Begin
    Case Addr Of
      0..$7F,$100..$17F: TransWordRead := TIA_Read_Name[Addr And $F];
  $200..$3FF: TransWordRead := PIA_Name[$200 Or Timer_And[Addr And $1F]];
{    $280..$297: TransWordRead := PIA_Name[Addr];
  $380..$397: TransWordRead := PIA_Name[Addr - $100];}
    Else TransWordRead := HexWord(Addr);
    End; { Case }
  End; { TransWordRead }


  Function TransByteRead(Addr: Word): String;
  Begin
    Case Addr Of
      0..$7F,$100..$17F: TransByteRead := TIA_Read_Name[Addr And $F];
  $200..$3FF: TransByteRead := PIA_Name[$200 Or Timer_And[Addr And $1F]];
{    $280..$297: TransByteRead := PIA_Name[Addr];
  $380..$397: TransByteRead := PIA_Name[Addr - $100];}
     Else TransByteRead := HexByte(Addr);
     End; { Case }
  End; { TransByteRead }


  Function TransByteWrite(Addr: Word): String;
  Begin
    If (Addr < $80) Or ((Addr >= $100) And (Addr < $180)) Then Addr := Addr And $3F;
    Case Addr Of
      0..$2C: TransByteWrite := TIA_Name[Addr];
    Else TransByteWrite := HexByte(Addr);
    End; { Case }
  End; { TransByteWrite }


  Function TransWord(Addr: Word): String;
  Var Instr: String[3];
  Begin
    Instr := Mnem[Opcode];
    If (Addr < $80) And (Copy(Instr,1,2) = 'RO')
     Then TransWord := TransWordRead(Addr)
     Else
      If (Instr           = 'ADC') Or
         (Instr           = 'DEC') Or
         (Instr           = 'INC') Or
         (Instr           = 'SBC') Or
         (Copy(Instr,1,2) = 'PH')  Or
         (Copy(Instr,1,2) = 'RO')  Or
         (Copy(Instr,1,2) = 'ST')
       Then TransWord := TransWordWrite(Addr)
       Else TransWord := TransWordRead(Addr);
  End; { TransWord }


  Function TransByte(Addr: Word): String;
  Var Instr: String[3];
  Begin
    Instr := Mnem[Opcode];
    If (Addr < $80) And (Copy(Instr,1,2) = 'RO')
     Then TransByte := TransByteRead(Addr)
     Else
      If (Instr           = 'ADC') Or
         (Instr           = 'DEC') Or
         (Instr           = 'INC') Or
         (Instr           = 'SBC') Or
         (Copy(Instr,1,2) = 'PH')  Or
         (Copy(Instr,1,2) = 'RO')  Or
         (Copy(Instr,1,2) = 'ST')
       Then TransByte := TransByteWrite(Addr)
       Else TransByte := TransByteRead(Addr);
  End; { TransByte }


  Function BankW(W: Word): Word;
  Begin
    If W >= $1000 Then BankW := W + (I And $F000) - $1000 Else BankW := W;
  End; { BankW }

Begin
  Move(AtariSeg[$1000],OldASeg,4096);
  FillChar(Executed,SizeOf(Executed),#0);
  FillChar(Branched,SizeOf(Branched),#0);
  Start := AtariSegW($1FFC) And $1FFF;

  Case Cart Of
    ct8k:
    Begin
      Bank     := 1;
      BankSize := 4096;
    End;
    ctMNetwork:
    Begin
      Bank     := 0;
      BankSize := 2048;
    End;
  Else
    Bank     := 0;
    BankSize := 4096;
  End; { Case }

  Unassemble(Start,Bank);

  { Output listing }

  Assign(Listing,ListingFileName);
  Rewrite(Listing);
  WriteLn(Listing,'; Listing for ',ParamStr(1));
  WriteLn(Listing);

  I       := $1000;
  DBStart := 0;
  While I <= ROMSize + 4095 Do
{    While I <= $1FFF Do}
  Begin
    Opcode := ROMBackup[I - $1000];
{      Opcode := AtariSeg[I];}

{      Write(HexWord(I),' ');}

    If Not Executed[I - $1000] Then
    Begin

      { Tally the byte }

      If DBStart = 0 Then DBStart := I;
      Inc(I);
    End
    Else
    Begin

      { Output any accumulated data }

      If DBStart <> 0 Then
      Begin
        For J := DBStart To I - 1 Do
        Begin
          If ((J - DBStart) And $7) = 0 Then Write(Listing,HexWord(J),'            DB    ');
{            Write(Listing,HexByte(AtariSeg[J]),'h');}
          Write(Listing,HexByte(ROMBackup[J - $1000]),'h');
          If (J < I - 1) And (((J - DBStart) And $7) <> $7) Then Write(Listing,',');
          If (J < I - 1) And (((J - DBStart) And $7) =  $7) Then WriteLn(Listing);
        End;
        WriteLn(Listing);
        DBStart := 0;
      End;

      { Output the instruction }

      If Branched[I - $1000]
       Then Write(Listing,HexWord(I),'  ')
       Else Write(Listing,'      ');
      For J := 1 To 5 Do
       If Word(Bytes[Opcode]) >= J
{          Then Write(Listing,HexByte(AtariSeg^[I + J - 1]))}
        Then Write(Listing,HexByte(ROMBackup[I + J - 1 - $1000]))
        Else Write(Listing,'  ');
      Write(Listing,Mnem[Opcode]);
      OTyp := ATyp[Opcode];
      If OTyp = 'ABS' Then Write(Listing,'   ',TransWord(BankW(ROMBackupW(I + 1 - $1000) And $1FFF)));
      If OTyp = 'A.X' Then Write(Listing,'   ',TransWord(BankW(ROMBackupW(I + 1 - $1000) And $1FFF)),',X');
      If OTyp = 'A.Y' Then Write(Listing,'   ',TransWord(BankW(ROMBackupW(I + 1 - $1000) And $1FFF)),',Y');
      If OTyp = 'ASY' Then Write(Listing,'   (',TransWord(BankW(ROMBackupW(I + 1 - $1000) And $1FFF)),',Y) & S');
      If OTyp = 'IND' Then Write(Listing,'   (',HexWord(BankW(ROMBackupW(I + 1 - $1000) And $1FFF)),')');
      If OTyp = 'I.X' Then Write(Listing,'   (',HexByte(ROMBackup[I + 1 - $1000]),',X)');
      If OTyp = 'I.Y' Then Write(Listing,'   (',HexByte(ROMBackup[I + 1 - $1000]),'),Y');
      If OTyp = 'ACC' Then Write(Listing,'   A');
      If OTyp = 'IMM' Then Write(Listing,'   #',HexByte(ROMBackup[I + 1 - $1000]));
      If OTyp = 'Z.P' Then Write(Listing,'   ',TransByte(ROMBackup[I + 1 - $1000]));
      If OTyp = 'Z.X' Then Write(Listing,'   ',TransByte(ROMBackup[I + 1 - $1000]),',X');
      If OTyp = 'Z.Y' Then Write(Listing,'   ',TransByte(ROMBackup[I + 1 - $1000]),',Y');
      If OTyp = 'I+A' Then Write(Listing,'   #',HexByte(ROMBackup[I + 1 - $1000]),' + A');
      If OTyp = 'REL' Then
      Begin
        B := ROMBackup[I + 1 - $1000];
        Asm
          MOV   BX,WORD PTR I
          ADD   BX,2
          MOV   AL,BYTE PTR B
          CBW
          ADD   BX,AX
          MOV   WORD PTR J,BX
        End; { Asm }
        Write(Listing,'   ',HexWord(J));
      End;

      { Look for bankswitching info }

      If OTyp = 'ABS' Then
      Begin
        BAddr := ROMBackupW(I + 1 - $1000) And $1FFF;
        If BankSwitch[BAddr] <> 0 Then
        Begin
          Case BankSwitch[BAddr] Of
            1..13: Begin                             { 2k/4k/8k/16k }
                     NewBank := (BankSwitch[BAddr] - 1) Shr 2;
                     Write(Listing,'   <-- Switch to bank ',NewBank Shr 2);
                     Write(Listing,' (',HexWord((I And $FFF) + Word(Bytes[Opcode]) + NewBank * BankSize + $1000),'h)');
                   End;
         $21..$29: Begin                             { CBS }
                     NewBank := (BankSwitch[BAddr] - $21) Shr 2;
                     Write(Listing,'   <-- Switch to bank ',NewBank Shr 2);
                     Write(Listing,' (',HexWord((I And $FFF) + Word(Bytes[Opcode]) + NewBank * BankSize + $1000),'h)');
                    End;
         $40..$4F: Begin                             { SuperChip }
                     NewBank := BankSwitch[BAddr] - $40;
                     Write(Listing,'   <-- Switch to bank ',NewBank Shr 2);
                     Write(Listing,' (',HexWord((I And $FFF) + Word(Bytes[Opcode]) + NewBank * BankSize + $1000),'h)');
                   End;
         $D0..$D6: Begin                             { M-Network }
                     NewBank := (BankSwitch[BAddr] - $D0);
                     Write(Listing,'   <-- Switch to bank ',NewBank);
                     Write(Listing,' (',HexWord((I And $FFF) + Word(Bytes[Opcode]) + NewBank * BankSize + $1000),'h)');
                   End;
          End; { Case }
        End;
      End;
      WriteLn(Listing);
      Inc(I,Word(Bytes[Opcode]));
    End;
  End; { While }

  { Output any accumulated data }

  If DBStart <> 0 Then
  Begin
    For J := DBStart To I - 1 Do
    Begin
      If ((J - DBStart) And $7) = 0 Then Write(Listing,HexWord(J),'            DB    ');
      Write(Listing,HexByte(ROMBackup[J - $1000]),'h');
      If (J < I - 1) And (((J - DBStart) And $7) <> $7) Then Write(Listing,',');
      If (J < I - 1) And (((J - DBStart) And $7) =  $7) Then WriteLn(Listing);
    End;
    WriteLn(Listing);
//    DBStart := 0;
  End;
  Close(Listing);
  Move(OldASeg,AtariSeg[$1000],4096);
End; { Disassemble }

End.

// ----------------------------------------------------------------------
// PCAE and PCAEWin - PC Atari Emulator - Atari 2600 emulator
// Copyright (C) 2000 John Dullea
//
//  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.
// ----------------------------------------------------------------------
