#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"

#define TD_READ CMD_READ
#define BLOCKSIZE TD_SECTOR
#define MAXSECTOR 512
#define NUMCYLS 79
#define NUMHEADS 2

SHORT error;
struct MsgPort *diskport;
struct IOExtTD *diskreq;
APTR diskdata;
SHORT testval;
 
extern struct MsgPort *CreatePort();
extern struct IORequest *CreateExtIO();
 
ULONG diskChangeCount,*ModData;


ReadCylSec(cyl, sec, hd)
SHORT cyl, sec, hd;
{
        LONG offset;
 
        diskreq->iotd_Req.io_Length = BLOCKSIZE;
        diskreq->iotd_Req.io_Data = 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)
SHORT cyl, sec, hd;
{
        LONG offset;
 
        diskreq->iotd_Req.io_Length = BLOCKSIZE;
        diskreq->iotd_Req.io_Data = 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()
{
        diskreq->iotd_Req.io_Length = 1;
        diskreq->iotd_Req.io_Command = TD_MOTOR;
        DoIO(diskreq);
        return(0);
}
 
MotorOff()
{
        diskreq->iotd_Req.io_Length = 0;
        diskreq->iotd_Req.io_Command = TD_MOTOR;
        DoIO(diskreq);
        return(0);
}

UpDateTrack()
{
        diskreq->iotd_Req.io_Length = 0;
        diskreq->iotd_Req.io_Command = ETD_UPDATE;
        DoIO(diskreq);
        return((int)diskreq->iotd_Req.io_Error);
}

OpenStuff()
{
        diskdata = (APTR)AllocMem(BLOCKSIZE,MEMF_CHIP|MEMF_CLEAR);
        diskport = CreatePort(0,0);
        if(diskport == 0){
            printf("Fehler beim Öffnen des Diskports  Ende Programm\n");
            FreeMem(diskdata,BLOCKSIZE);
            exit(200);
        }
        diskreq = (struct IOExtTD *)CreateExtIO(diskport,sizeof(struct IOExtTD));
        if(diskreq == 0){
            FreeMem(diskdata,BLOCKSIZE);
            DeletePort(diskport);
            printf("Fehler beim Anlegen des Disk IO Blocks  EndeProgramm\n");
            exit(200);
        }
        if(OpenDevice(TD_NAME,0,diskreq,0)!=0){
            FreeMem(diskdata,BLOCKSIZE);
            DeletePort(diskport);
            DeleteExtIO(diskreq, sizeof(struct IOExtTD));
            printf("Fehler beim Öffnen des Diskettentreibers  EndeProgramm\n");
            exit(200);
        }
        diskreq->iotd_Req.io_Command = TD_CHANGENUM;
        DoIO(diskreq);
        diskChangeCount = diskreq->iotd_Req.io_Actual;
        return(0);
}

CloseStuff()
{
        MotorOff();
        CloseDevice(diskreq);
        FreeMem(diskdata,BLOCKSIZE);
        DeletePort(diskport);
        DeleteExtIO(diskreq, sizeof(struct IOExtTD));
        printf("\n     Bye Bye\n\n\n     PS. Ein Programm von Zoro.\n\n");
        return(0);
}

Startup()
{
        printf("\n    Dieses Programm liest die Kickstartsoftware\n");
        printf("    aus dem Speicher (ROM oder RAM) und schreibt\n");
        printf("    sie in einem für den A1000 bootfähigen Format\n");
        printf("    auf eine Diskette. Diese muß jedoch schon\n");
        printf("    formatiert sein.\n");
        printf("\n    Einige Kingsoft Spiele laufen nur mit der ROM\n");
        printf("    Version der Kickstart. Starten Sie dazu dieses\n");
        printf("    Programm auf einem A500 oder A2000 und Sie\n");
        printf("    erhalten die ROM Version auf Diskette.\n");
        printf("\n    Viel Spaß mit der neuen Software.\n");
        printf("\n    Legen Sie eine formatierte Diskette in\n");
        printf("    das interne Laufwerk df0: und betätigen Sie\n");
        printf("    <RETURN>\n");
        getchar();
        return(0);
}
   
main()   
{
        int track,head,sektor,i;
        unsigned long *rombase,speicher;

        OpenStuff();
        Startup();
        MotorOn();
        *diskdata=0x4b49434b;
        rombase=0xfc0000;
        for(track=0;track<80;track++){
           for(head=0;head<2;head++){
              for(sektor=0;sektor<11;sektor++){
                  WriteCylSec(track,sektor,head);  
                  if(diskreq->iotd_Req.io_Error != 0){
                     printf("Fehler bei Track %d Sektor %d Seite %d\n"
                                  ,track,sektor,head);
                     goto abbruch;
                  }
                  if((APTR)rombase >= (APTR)0x1000000)goto ok;
                  for(i=0;i<128;i+=1){
                     speicher=*rombase;
                     *(diskdata+i)=speicher;
                     rombase+=1;
                     } 
              }
           }
        } 
ok:      UpDateTrack();
abbruch: CloseStuff();
        return(0);
}
 
 
 
 
 
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);
}
