   {MAGICSPC.PAS}
   {Magic - Converter:.__C->.Z80 Input&Command-Version}
   {Final-Version 1.00, 05.Juli.1995}
   {Written by Bernhard Lutz, Hammerstr. 35, D-76756 Bellheim, Germany}
   {Phone: Germany-07272-77372}
   {Please note: This was my first steps into (Turbo-)Pascal.}
   {Many thanks goto Thomas Steg of Thomas Steg Software for his help}


USES
  Dos,Crt;

CONST
  PufSize = 49169; {L„nge des .TAP-Files ---> richtig ???}

TYPE
  Puffertyp = Array[1..PufSize] of Byte; {oder Char}

VAR
  DatenPuffer : PufferTyp;


FUNCTION MAGIC_KONVERTIEREN  (FName      : PathStr;
                              VAR OutPuf : PufferTyp;
                              OFName     : PathStr;
                              NoPrint    : Byte) : Boolean;

VAR

  Offset        : Word; {File beginnt bei 16384 anstatt bei 0 !}
  Header        : Word; {L„nge des .__C-File-Headers: 17}
  a             : Word;
  F             : File;
  OUTF          : File; {Output-File}
  ReadResult    : Word;
  WriteResult   : Word;
  AllesOK       : Boolean;
  PC            : Word;  {Program-Counter}
  PC2           : Word;  {wie PC, nur High- und Low-Byte vertauscht !}
  SP            : Word;  {Stackpointer steht im Header CODE sp, len !, TEMP!}
  Stackpointer  : Word;  {Stackpointer steht im Header CODE sp, len !}
  R             : Byte;
  I             : Byte;
  AUTOIM        : Byte;
  AUTOEI        : Byte;
  A2            : Byte;  {A'-Register}
  F2            : Byte;  {F'-Register}
  HL2           : Word;  {HL'-Register}
  DE2           : Word;
  BC2           : Word;
  IY            : Word;  {IY-Register}
  IX            : Word;  {IX-Register}
  HL1           : Word;  {HL-Register}
  DE1           : Word;
  BC1           : Word;
  A1            : Byte; {A-Register -> 'Accumulator'}
  F1            : Byte; {Flag-Register}
  EI            : Byte; {Header: DI=0, EI=1}
  IFF2          : Byte; {IFF2: Interrupt-Flip-Flop 2 --> immer wie EI ?}
  IM            : Byte; {Interrupt-Mode (Bit 0-1) usw ... !}
  X             : Byte; {verschiedenes: Bordercolor, R-Reg Bit, etc. !!}
  Joy           : Byte; {Joystick-Emulation}
  InputText     : String [1];
  InputZahl     : Byte;
  Error         : Word;
  Issue2        : Byte;
  Border        : Byte;
  Parity        : Byte;
  ParityEven    : Byte;




  label weiter1, weiter2, weiter3, weiter4, weiter5, weiter6, weiter7,
        weiter8, weiter9, weiter10, weiter11, weiter12, weiter13, weiter14,
        weiter15, weiter16, weiter17, weiter18, weiter19, weiter20, weiter21;

BEGIN

  {$M 8192,0,0}
  header :=17;
  offset :=16384;
  offset :=offset-header;
  {$I-}
  If IOResult <> 0 then;
  Assign (F, FName);
  Reset (F, 1);
  BlockRead (F, OutPuf[1], PufSize, ReadResult);
    AllesOK := (IOResult = 0) and (ReadResult = PufSize);
  { writeln ('Eingelesenes File hat L„nge: ',ReadResult); }
  If IOResult <> 0 then;
  Close (F);
  if IOResult <> 0 then;
  {$I+}
  If not AllesOK
  then FillChar (OutPuf, Sizeof(PufferTyp), 0);
  MAGIC_KONVERTIEREN := AllesOK;

    if noprint<>1 then clrscr;

    sp:=(OutPuf[14]+256*OutPuf[15]);
    stackpointer:=sp;
    sp:=sp-offset+1+1;
    r:=(OutPuf[sp+1]);
    i:=(OutPuf[sp+2]);
    a2:=(OutPuf[sp+4]);
    f2:=(OutPuf[sp+3]);
    hl2:=(OutPuf[sp+5]+256*Outpuf[sp+6]);
    de2:=(OutPuf[sp+7]+256*OutPuf[sp+8]);
    bc2:=(OutPuf[sp+9]+256*OutPuf[sp+10]);
    iy:=(OutPuf[sp+11]+256*OutPuf[sp+12]);
    ix:=(OutPuf[sp+13]+256*OutPuf[sp+14]);
    hl1:=(OutPuf[sp+15]+256*OutPuf[sp+16]);
    de1:=(OutPuf[sp+17]+256*OutPuf[sp+18]);
    bc1:=(OutPuf[sp+19]+256*OutPuf[sp+20]);
    a1:=(OutPuf[sp+22]);
    f1:=(OutPuf[sp+21]);
    pc:=(OutPuf[sp+23]+256*OutPuf[sp+24]);
    pc2:=pc;
    {doch nicht: pc2:=(OutPuf[sp+24]+256*OutPuf[sp+23]);
    {High-/Low-Byte getauscht !}


  X:=0;
  if noprint=1 then goto weiter20;

  writeln;
  writeln ('For Defaults just press RETURN !!!');
  writeln;
  writeln ('Interrupt enable EI (1) or disable (0) or AUTO (RETURN) ?:');
  readln (InputText);
  AUTOEI:=0;
  if InputText='0' then goto weiter2;
  if InputText='1' then goto weiter1;
  goto weiter20;

  weiter1:
  ei:=1;
  goto weiter3;

  weiter2:
  ei:=0;
  goto weiter3;

  {Auto-Select EI/DI --> wenn I-Register Parity ODD, dann EI !}
  {wenn Parity ODD, dann DI !}

  weiter20:
  AUTOEI:=1;
  ParityEven:=0;
  Parity:=I and 128;
  if Parity <> 0 then ParityEven:=ParityEven+1;
  Parity:=I and 64;
  if Parity <> 0 then ParityEven:=ParityEven+1;
  Parity:=I and 32;
  if Parity <> 0 then ParityEven:=ParityEven+1;
  Parity:=I and 16;
  if Parity <> 0 then ParityEven:=ParityEven+1;
  Parity:=I and 8;
  if Parity <> 0 then ParityEven:=ParityEven+1;
  Parity:=I and 4;
  if Parity <> 0 then ParityEven:=ParityEven+1;
  Parity:=I and 2;
  if Parity <> 0 then ParityEven:=ParityEven+1;
  Parity:=I and 1;
  if Parity <> 0 then ParityEven:=ParityEven+1;
  EI:=1;
  if odd (ParityEven) then EI:=0;

  weiter3:
  if noprint=1 then goto weiter18;

  {IM--> Bit 0-1 = InterruptMode 0/1/2  , Bit 6-7 = 00 = Cursor Joystick}
  writeln ('IM-Interruptmode (0), (1), (2) or AUTO (RETURN) ?:');
  readln (InputText);
  if InputText='' then goto weiter18;
  AUTOIM:=0;
  if InputText='1' then goto weiter4;
  if InputText='2' then goto weiter5;
  if InputText='0' then goto weiter6;
  goto weiter18;


  weiter4:
  im:=1;
  goto weiter7;

  weiter5:
  im:=2;
  goto weiter7;

  weiter6:
  im:=0;
  goto weiter7;


  {Auto-Select: IM 1 wenn Interrupt- (I-) Register = 63 (3Fh)}
  {oder IM 2 wenn <> 63.        IM 0 ist nicht gebr„uchlich !}
  {AUTO-Interrupt-Mode-Select abgschaltet, da zu unsicher !!!}

  weiter18:
  autoim:=1;
  if i=63 then goto weiter19;
  im:=2;
  goto weiter7;

  weiter19:
  im:=1;
  goto weiter7;

  weiter7:
  if noprint=1 then goto weiter8;
  writeln ('Joystick:');
  writeln ('Cursor (0), Kempston (1), Sinclair2 Left (2), Sinclair2 Right (3=default) ?:');
  readln (InputText);
  if InputText='' then goto weiter8;
  if InputText='0' then goto weiter9;
  if InputText='1' then goto weiter10;
  if InputText='2' then goto weiter11;

  weiter8:
  joy:=3;
  goto weiter12;

  weiter9:
  joy:=0;
  goto weiter12;

  weiter10:
  joy:=1;
  goto weiter12;

  weiter11:
  joy:=2;

  weiter12:
  if joy=1 then joy:=64;
  if joy=2 then joy:=128;
  if joy=3 then joy:=128+64;

  if noprint=1 then goto weiter13;

  writeln ('Issue 2-Emulation on (1, default) or off (0) ?:');
  readln (InputText);
  if InputText='' then goto weiter13;
  if InputText='0' then goto weiter14;

  weiter13:
  Issue2:=1;
  goto weiter15;

  weiter14:
  Issue2:=0;

  weiter15:
  if noprint=1 then goto weiter16;
  writeln ('Border-Colour (0-7, 0=default) ?:');
  readln (InputText);
  if InputText='' then goto weiter16;
  val (InputText,InputZahl,Error);
  if InputZahl <0 then goto weiter16;
  if InputZahl >7 then goto weiter16;
  Border:=InputZahl;
  goto weiter17;

  weiter16:
  border:=0;

  weiter17:
  IFF2:=EI; {IFF2 wird hier immer gleich EI gesetzt}

  {if noprint=1 then goto weiter21;}

    clrscr;
    writeln ('Stackpointer= ',sp+26+7); {plus 26, da nicht ge-popt wird !}
    writeln ('R-Register  = ',r);
    writeln ('I-Register  = ',i);
    writeln ('A''-Register = ',a2);
    writeln ('F''-Register = ',f2);
    writeln ('IX-Register = ',ix);
    gotoxy (41,6);
    writeln ('IY-Register = ',iy);
    writeln ('HL-Register = ',hl1);
    gotoxy (40,7);
    writeln ('HL''-Register = ',hl2);
    writeln ('DE-Register = ',de1);
    gotoxy (40,8);
    writeln ('DE''-Register = ',de2);
    writeln ('BC-Register = ',bc1);
    gotoxy (40,9);
    writeln ('BC''-Register = ',bc2);
    writeln ('A-Register (=Accumulator)= ',a1);
    writeln ('F-Register (=Flag-Register)= ',f1);
    writeln ('PC (=Program-Counter)= ',pc);
    if ei=1 then writeln ('Interrupt=EI (enabled),     ---> (IFF2=EI) set');
    if ei=0 then writeln ('Interrupt=DI (disabled),    ---> (IFF2=DI) set');
    if AUTOEI=1 then writeln ('Interrupt EI/DI AUTOSELECTED !');
    { writeln ('IFF2= ',iff2); }
    if im=0 then writeln ('Interrupt-Mode=IM0');
    if im=1 then writeln ('Interrupt-Mode=IM1');
    if im=2 then writeln ('Interrupt-Mode=IM2');
    if AUTOIM=1 then writeln ('Interrupt-Mode AUTOSELECTED !');
    if joy=0 then writeln ('Joystick-Emulation: Cursor');
    if joy=64 then writeln ('Joystick-Emulation: Kempston');
    if joy=128 then writeln ('Joystick-Emulation: Sinclair2 Left');
    if joy=128+64 then writeln ('Joystick-Emulation: Sinclair2 Right');
    if Issue2=0 then writeln ('Issue 2-Emulation OFF');
    if Issue2=1 then writeln ('Issue 2-Emulation ON');
    writeln ('Bordercolour=',Border);

    weiter21:

    {$I-}
    Assign (OUTF, OFName);
    Rewrite (OUTF);
    Reset (OUTF,1);
    BlockWrite (OUTF, A1,1, WriteResult);
    BlockWrite (OUTF, F1,1, WriteResult);
    BlockWrite (OUTF, BC1,2, WriteResult);
    BlockWrite (OUTF, HL1,2, WriteResult);
    BlockWrite (OUTF, PC2,2, WriteResult); {Achtung ! L/H Byte getauscht !}
    stackpointer:=stackpointer+26; {plus 26, da nicht ge-popt wird !!!}
    BlockWrite (OUTF, Stackpointer,2, WriteResult);
    BlockWrite (OUTF, I,1, WriteResult);
    if r>127 then x:=1; {Wenn R-Reg Bit 7=1 dann X, Bit 0=1 !}
    { if r=255 then r:=1; siehe Z80.DOC !, wenn R=255, dann R=1 ! }
    BlockWrite (OUTF, R,1, WriteResult);
    border:=border*2; {um ein Bit verschieben (Border= Bit 1-3)}
    x:=x+border;
    BlockWrite (OUTF, X,1, WriteResult);
    BlockWrite (OUTF, DE1,2, WriteResult);
    BlockWrite (OUTF, BC2,2, WriteResult);
    BlockWrite (OUTF, DE2,2, WriteResult);
    BlockWrite (OUTF, HL2,2, WriteResult);
    BlockWrite (OUTF, A2,1, WriteResult);
    BlockWrite (OUTF, F2,1, WriteResult);
    BlockWrite (OUTF, IY,2, WriteResult);
    BlockWrite (OUTF, IX,2, WriteResult);
    BlockWrite (OUTF, EI,1, WriteResult); {Int-Flip-Flop: DI=0, EI=1}
    BlockWrite (OUTF, IFF2,1, WriteResult); {IFF2 ->not particular important}
    im:=im+joy;
    if Issue2=1 then im:=im+4;
    BlockWrite (OUTF, IM,1, WriteResult); {hier Interruptmode etc. !!}

    BlockWrite (OUTF, OutPuf [(49169-49152+1)], 49152, WriteResult);

    Close (OUTF);
    {$I+}


END;


    var

    InpFile  : string [8];
    OutpFile : string [8];
    Noprint  : Byte;

Label LesenOK, LeseFehler, ende, nochmal, cmd, Ende3, Help;

BEGIN
  nochmal:
  InpFile:=ParamStr(1);
  if InpFile='/?' then goto help;
  if InpFile='/help' then goto help;
  if InpFile='/HELP' then goto help;
  OutpFile:=ParamStr(2);
  if OutpFile='' then OutpFile:=InpFile;
  noprint:=0;
  if InpFile<>'' then noprint:=1;
  if noprint=1 then goto cmd;
  clrscr;
  writeln;
  writeln ('MAGIC - Version 1.00');
  writeln;
  writeln ('translates BETA-DISK-Snapshots (48k) -SpecEm (.__C)-Files (LEN=49169) created');
  writeln ('by BDDE to .Z80-Snapshot-Format used by G.A. Lunter''s Z80 Spectrum Emulator');
  writeln ('Please enter /? oder /help for Help-Page !');
  writeln;
  writeln ('Please enter Input-Filename (without! Extension: (.__C !): ');
  readln (InpFile);
  if InpFile='' then goto help;
  writeln ('Please enter Output-Filename (without ! Extension (.Z80 !): ');
  readln (OutpFile);
  if OutpFile='' then OutpFile:=InpFile;

  cmd:
  If MAGIC_KONVERTIEREN (InpFile+'.__C', DatenPuffer,OutpFile+'.z80',noprint)
  then goto LesenOK
  else goto LeseFehler;

  LesenOK:
  { writeln ('.TAP-File lesen war OK !' ); }
  { writeln; }
  writeln (InpFile+'.__C     ---> converted to --->     '+OutpFile+'.Z80');
  goto ende;

  LeseFehler:
  clrscr;
  writeln;
  writeln ('ReadError! LEN <> 49169 or File doesn''t exist ! Readbuffer is empty !');
  writeln;


  {$M 8192,0,0} {Speicher fr HEAP reservieren ist unbedingt fr exec n”tig !}
  SwapVectors;
  exec ('command.com','/c del '+OutpFile+'.z80');   {/c ist wichtig !}
  SwapVectors;

  Ende:
  writeln;
  writeln ('Magic: Version 1.00, written for Public Domain by Bernhard Lutz');
  writeln ('Please enter /? oder /help for Help-Page !');
  WRITELN;

  goto Ende3;

  Help:
  clrscr;
  writeln;
  writeln ('MAGIC - Version 1.00, written for Public Domain by Bernhard Lutz');
  writeln;
  writeln ('translates BETA-DISK-Snapshots (48k) -SpecEm (.__C)-Files (LEN=49169) created');
  writeln ('by BDDE to .Z80-Snapshot-Format used by G.A. Lunter''s Z80 Spectrum Emulator');
  writeln;
  writeln ('Examples:');
  writeln;
  writeln ('MAGIC               -> forces User-Input-Mode');
  writeln;
  writeln ('MAGIC filename      -> translates filename.__C --> filename.z80      (*)');
  writeln;
  writeln ('MAGIC file1 file2   -> translates file1.__C    --> file2.z80         (*)');
  writeln;
  writeln ('(*) = AUTOSET: EI/DI, IM');
  writeln ('(*) = SET:     Border 0, Sinclair2 Joystick Right, Issue2 Emulation ON)');
  writeln ('Note: AUTOSET (autoselect) EI/DI and IM (Interrupt-Mode) does not allways');
  writeln ('work right. If .Z80-Files fails to run, please alter EI/DI and/or IM using');
  writeln ('User-Input-Mode, oder programs SETINTER, SETIMODE !');
  writeln;
  writeln ('BDDE (Beta-Disk-Dump-Extractor) (c) by J.L. Bezemer / HanSoft & Partners');
  writeln ('Z80 - The Sinclair ZX Spectrum Emulator (c) by G.A. Lunter');
  writeln ('MAGIC is Public Domain, written by Bernhard Lutz, Hammerstr. 35, D-76756 Germany');

  Ende3:


  {   writeln ('Programm-Ende');  }
  {   writeln;                    }
END.
