#include "exec/types.h"
#include "exec/nodes.h"
#include "exec/lists.h"
#include "exec/memory.h"
#include "exec/interrupts.h"
#include "exec/ports.h"
#include "exec/libraries.h"
#include "exec/io.h"
#include "exec/tasks.h"
#include "exec/execbase.h"
#include "exec/devices.h"
#include "devices/trackdisk.h"
#include "stdio.h"
#include "functions.h"
#include "libraries/dos.h"

#define TD_READ CMD_READ
#define BLOCKSIZE TD_SECTOR
#define MAXSECTOR 512
#define KICKSIZE 0x40200L

SHORT error;
struct MsgPort *diskport;
struct IOExtTD *diskreq;
char *diskdata;
SHORT testval;
char *kickdata;
LONG openerror;
struct DosBase *DosBase; 
extern struct MsgPort *CreatePort();
extern struct IORequest *CreateExtIO();
 
ULONG diskChangeCount,*ModData;


ReadCylSec(cyl, sec, hd)

/* diese Funktion liest den durch cyl,sec und hd  *
 * bestimmten Sektor in den Lesepuffer ein		  */

SHORT cyl, sec, hd;
{
		  LONG offset;
 
		  diskreq->iotd_Req.io_Length = BLOCKSIZE;
		  diskreq->iotd_Req.io_Data = (APTR)diskdata;
		  diskreq->iotd_Req.io_Command = ETD_READ;
		  diskreq->iotd_Count = diskChangeCount;
		  offset = TD_SECTOR * (sec + NUMSECS * hd + NUMSECS * NUMHEADS * cyl);
		  diskreq->iotd_Req.io_Offset = offset;
		  DoIO(diskreq);
		  return(0);
}


WriteCylSec(cyl, sec, hd)

/* diese Funktion schreibt den durch cyl, sec und hd *
 * bestimmten Sektor auf Diskette. ACHTUNG der		  *
 * zuletzt geschriebene Sektor wird erst bei einem   *
 * Spurwechsel auf Diskette übertragen.				  */
 
SHORT cyl, sec, hd;
{
		  LONG offset;
 
		  diskreq->iotd_Req.io_Length = BLOCKSIZE;
		  diskreq->iotd_Req.io_Data = (APTR)diskdata;
		  diskreq->iotd_Req.io_Command = ETD_WRITE;
		  diskreq->iotd_Count = diskChangeCount;
		  offset = TD_SECTOR * (sec + NUMSECS * hd + NUMSECS * NUMHEADS * cyl);
		  diskreq->iotd_Req.io_Offset = offset;
		  DoIO(diskreq);
		  return(0);
}
  
MotorOn()

/* diese Funktion schaltet den Motor des im *
 * diskreq angegebenen Laufwerks ein		  */
 
{
		  diskreq->iotd_Req.io_Length = 1;
		  diskreq->iotd_Req.io_Command = TD_MOTOR;
		  DoIO(diskreq);
		  return(0);
}
 
MotorOff()

/* dies Funktion schaltet den Motor aus	  */

{
		  diskreq->iotd_Req.io_Length = 0;
		  diskreq->iotd_Req.io_Command = TD_MOTOR;
		  DoIO(diskreq);
		  return(0);
}

OpenStuff()

/* alle benötigten Systemresourcen werden   *
 * hier geöffnet bzw. reserviert 			  */
 
{
	if(!(DosBase=(struct DosBase *)OpenLibrary((UBYTE *)"dos.library",0L)))CloseStuff();
		  if(!(diskdata=(char *)AllocMem(BLOCKSIZE,MEMF_CHIP|MEMF_CLEAR)))CloseStuff();
	if(!(kickdata=(char *)AllocMem(KICKSIZE,MEMF_PUBLIC)))CloseStuff();
		  if(!(diskport=CreatePort(0L,0L)))CloseStuff();
		  if(!(diskreq=(struct IOExtTD *)CreateExtIO(diskport,(LONG)sizeof(struct IOExtTD))))CloseStuff();
		  if(openerror=OpenDevice(TD_NAME,0L,diskreq,0L))CloseStuff();
		  diskreq->iotd_Req.io_Command = TD_CHANGENUM;
		  DoIO(diskreq);
		  diskChangeCount = diskreq->iotd_Req.io_Actual;
		  return(0);
}

CloseStuff()

/* dies Funktion beendet das Programm *
 * ordnungsgemäß							  */
 
{
		  if(!openerror)
	{
		MotorOff();
		CloseDevice(diskreq);
	}
		  if(DosBase)CloseLibrary(DosBase);
	if(diskdata)FreeMem(diskdata,BLOCKSIZE);
	if(kickdata)FreeMem(kickdata,KICKSIZE);
		  if(diskport)DeletePort(diskport);
		  if(diskreq)DeleteExtIO(diskreq,(LONG)sizeof(struct IOExtTD));
		  printf("\n     Bye Bye\n\n");
		  exit();
}

StartUp()

/* Ausgabe der Einschaltmeldung */

{
		  printf("\n    Legen Sie eine Kickstart Diskette in das\n");
		  printf("    interne Laufwerk df0: und betätigen Sie <RETURN>\n");
		  printf("    Achtung !!! Es muß eine KICKSTART DISKETTE sein.\n\n");		  
		  printf("    Wenn das Programm eine Fehlermeldung ausgibt,\n");					  
		  printf("    überprüfen Sie ob eine KICKSTART-Diskette eingelegt ist.\n");
		  printf("    Ansonsten kopieren Sie das Programm  GETKICK auf dir RAM-Disk.\n");				  
		  printf("    <copy Getkick to ram:>\n");
		  printf("    und starten das Programm erneut von der RAM-Disk.\n");
		  printf("    Bei einem erneuten Fehler starten Sie das Programm erneut\n");
		  printf("    bis die KICKSTART-Diskette zerlegt wird.\n\n");					
		  printf("    <RETURN>\n");
		  getchar();
		  return(0);
}
	
Schreibe()

/* die Funktion Schreibe entfernt die KICK *
 * Kennung am Anfang der gelesenen Daten	 *
 * und teilt die 256 KByte in zwei 128 	 *
 * KByte große Teile, die nach geraden und *
 * ungeraden Adressen getrennt in seperaten*
 * Dateien abgelegt werden 					 */
 
{
	char *schreibepuffer,*konvertpuffer;
	struct FileHandle *datei;
	LONG error,i;
	
	konvertpuffer=kickdata;
	if(!(schreibepuffer=AllocMem(0x10000L,MEMF_PUBLIC)))
	{
		puts("puffer fehler");
		return();
	}
	konvertpuffer+=512L;  /* sector 0 ausblenden */
	for(i=0;i<0x10000;i++)
	{
		*(schreibepuffer+i)=*(konvertpuffer+(i<<1));
	}
	datei=Open((char *)"KICK1.EVEN",MODE_NEWFILE);
	error=Write(datei,schreibepuffer,0x10000L);
	if(error==-1L)puts("Fehler Schreiben");
	Close(datei);
	for(i=0;i<0x10000;i++)
	{
		*(schreibepuffer+i)=*(konvertpuffer+1+(i<<1));
	}
	datei=Open((char *)"KICK1.ODD",MODE_NEWFILE);
	error=Write(datei,schreibepuffer,0x10000L);
	if(error==-1L)puts("Fehler Schreiben");
	Close(datei);
	konvertpuffer+=0x20000;  /* zweite bank */
	for(i=0;i<0x10000;i++)
	{
		*(schreibepuffer+i)=*(konvertpuffer+(i<<1));
	}
	datei=Open((char *)"KICK2.EVEN",MODE_NEWFILE);
	error=Write(datei,schreibepuffer,0x10000L);
	if(error==-1L)puts("Fehler Schreiben");
	Close(datei);
	for(i=0;i<0x10000;i++)
	{
		*(schreibepuffer+i)=*(konvertpuffer+1+(i<<1));
	}
	datei=Open((char *)"KICK2.ODD",MODE_NEWFILE);
	error=Write(datei,schreibepuffer,0x10000L);
	if(error==-1L)puts("Fehler Schreiben");
	Close(datei);
	FreeMem(schreibepuffer,0x10000L);
	return();
}
	
main()	

/* die Funktion main überprüft das Vorhanden *
 * sein einer Kickstart Diskette und liest	*
 * diese ein. Bei Erfolg wird die Funktion	*
 * Schreibe aufgerufen								*/
 
{
		  int track,head,sektor,i;
	char *lesepointer;

		  OpenStuff();
	lesepointer=kickdata;
		  StartUp();
		  MotorOn();
	Delay(60L);

/*   ReadCylSec((SHORT)0,(SHORT)0,(SHORT)0);
	if(strcmp(diskdata,(char *)"KICK")!=0)
	{
		puts("keine Kickstart Diskette !\n");
		CloseStuff();
	}

*/   

			for(track=0;track<80;track++){
			  for(head=0;head<2;head++){
				  for(sektor=0;sektor<11;sektor++){
						ReadCylSec(track,sektor,head);  
						if(diskreq->iotd_Req.io_Error != 0)
		  {
							printf("Fehler bei Track %d Sektor %d Seite %d\n"
											 ,track,sektor,head);
							CloseStuff();
						}
						for(i=0;i<512;i+=1)
		  {
							*(lesepointer++)=*(diskdata+i);
						}
						if((lesepointer-kickdata) >= KICKSIZE)
		  {
			Schreibe();
			CloseStuff();
		  } 
				  }
			  }
		  } 
		  CloseStuff();
		  return(0);
}
 
 
 
/* 
 
Älter Compilerversionen benötigen dies beiden 
Funktionen, da sie noch nicht in den Libraries
verfügbar waren.
 
struct IORequest *CreateExtIO(ioReplyPort,size)
	 struct MsgPort *ioReplyPort;
	 LONG size;
{
	 struct IORequest *ioReq;

	 if (ioReplyPort == 0)
		  return ((struct IORequest	*) 0);
	 ioReq = (struct IORequest *)AllocMem (size, MEMF_CLEAR | MEMF_PUBLIC);
	 if (ioReq == 0)
		  return ((struct IORequest	*) 0);
 
	 ioReq -> io_Message.mn_Node.ln_Type = NT_MESSAGE;
	 ioReq -> io_Message.mn_Node.ln_Pri = 0;
	 ioReq -> io_Message.mn_ReplyPort = ioReplyPort;
 
	 return (ioReq);
}
  
  
DeleteExtIO(ioExt,size)
	 struct IORequest *ioExt;
	 LONG size;
{
	 ioExt -> io_Message.mn_Node.ln_Type = 0xff;
	 ioExt -> io_Device = (struct Device *) -1;
	 ioExt -> io_Unit = (struct Unit *) -1;
 
	 FreeMem (ioExt, size);
	 return(0);
}

*/
