/*  KickMem V1.0 for version 1.3 kickstart, by Dave Williams 
    18 May 1989

               Use FixHunk to direct data hunks to Chip Memory

*/
#include <stdio.h>  
#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"

#define BLOCKSIZE TD_SECTOR

short error;
struct MsgPort *diskport;
struct IOExtTD *diskreq;
BYTE diskbuffer[BLOCKSIZE];
BYTE patchbuffer [] = {0x8c,0xfe};  /* pointer to addmem */
BYTE mainbuffer [] = {             /* AddMem code */
   	0x4e,0xf9,0x00,0xfe,
   	0x8d,0x6a,0x48,0xe7,
   	0xe0,0xc2,0x2c,0x78,
   	0x00,0x04,0x20,0x3c,
   	0x00,0x08,0x00,0x00,  /* $00080000 = how much to add */
   	0x22,0x3c,0x00,0x01,
   	0x00,0x05,0x74,0x00,
   	0x20,0x7c,0x00,0x08,  /* $00080000 = address of extra memory */
   	0x00,0x00,0x93,0xc9,
   	0x4e,0xae,0xfd,0x96,
   	0x4c,0xdf,0x43,0x07,
   	0x4e,0xf9,0x00,0xfe,
   	0x88,0xd6,0x4e,0x71   
     };
BYTE checksumbuffer[] = {0x81,0xa1,0xbb,0x42}; /* I got this from SumKick*/

extern struct MsgPort *CreatePort();
extern struct IORequest *CreateExtIO();

ReadSector(trk,sec)
SHORT trk,sec;
{
        LONG offset;
	
        diskreq->iotd_Req.io_Length = BLOCKSIZE;
        diskreq->iotd_Req.io_Data = (APTR)diskbuffer;            
        diskreq->iotd_Req.io_Command = CMD_READ;
        offset = TD_SECTOR * ((trk * NUMSECS) + sec);
        diskreq->iotd_Req.io_Offset = offset;        
        DoIO(diskreq);
        if (diskreq->iotd_Req.io_Error != 0)
        printf("ERROR: Disk Error %ld on Trk %ld Sec %ld\n",
               diskreq->iotd_Req.io_Error,trk,sec);
       	return(0);
}

WriteSector(trk,sec)
SHORT trk,sec;
{
        LONG offset;

        diskreq->iotd_Req.io_Length = BLOCKSIZE;
        diskreq->iotd_Req.io_Data = (APTR)diskbuffer;            
        diskreq->iotd_Req.io_Command = CMD_WRITE;
        offset = TD_SECTOR * ((trk * NUMSECS) + sec);
        diskreq->iotd_Req.io_Offset = offset;        
        DoIO(diskreq);
        diskreq->iotd_Req.io_Command = CMD_UPDATE;
        DoIO(diskreq);
        if (diskreq->iotd_Req.io_Error != 0)
        printf("ERROR: Disk Error %ld on Trk %ld Sec %ld\n",
                diskreq->iotd_Req.io_Error,trk,sec);
       	return(0);
}

void Gracefulexit()
{
        diskreq->iotd_Req.io_Length = 0;
        diskreq->iotd_Req.io_Command = TD_MOTOR;
        DoIO(diskreq);
        CloseDevice(diskreq);
        DeleteExtIO(diskreq, sizeof(struct IOExtTD));
        DeletePort(diskport);
        exit(0);
}             
	
void main()
{
        char c; 
        SHORT track,sector,myoffset;

        printf("\nKickMem 1.0, Public Domain 1989, By Dave Williams\n");
        printf("\nPLACE KickStart V1.2 disk to be modified in drive df1:\n");
        printf("Press return to CONTINUE or 'q' return to ABORT.\n:");  
        c = getchar();
        if(c != '\n'){exit(TRUE);};               
        diskport = CreatePort(0,0);
        if(diskport == 0) exit (TRUE);
        diskreq = (struct IOExtTD*)CreateExtIO(diskport,sizeof(struct IOExtTD));
        if(diskreq == 0) {DeletePort(diskport); exit(TRUE);}
        error=OpenDevice(TD_NAME,1,diskreq,0);
        if(error != 0){
             	printf("OpenDevice returned %ld error \n",error);
             	exit (TRUE);
        }
        diskreq->iotd_Req.io_Command = TD_CHANGESTATE;
        DoIO(diskreq);
        if(diskreq->iotd_Req.io_Actual != 0){
           	printf("ERROR: Who are you kidding? There's no disk in df1:\n");
           	exit (TRUE);
        }
        diskreq->iotd_Req.io_Command = TD_PROTSTATUS;
        DoIO(diskreq);
        if(diskreq->iotd_Req.io_Actual != 0){
                printf("ERROR: Disk write protected\n");
        	exit (TRUE);
        }
       /*=================BLOCK #36==================*/
       
        track = 3;    /* Check for version 33.18 disk resource */
        sector = 3;
        ReadSector(track,sector);
        if(diskbuffer[449]!= '3'|| diskbuffer[450]!= '3' || 
           diskbuffer[451]!= '.' ||  diskbuffer[452]!= '1' ||
           diskbuffer[453]!= '8'){
                printf("ERROR: Not a Version 33.18 Kickstart disk\n");
                Gracefulexit();
        }
      
  	 
       /*===============BLOCK #2=====================*/
       
       track = 0;    /* Disable kickstart from adding to CHIP_MEM */
       sector = 2;
       ReadSector(track,sector);
       diskbuffer[15]= 0x08; 
       WriteSector(track,sector);
  
       /*==============BLOCK #325===================*/
       
        track = 29;  /* grab strap pointer to point to addmem code */
        sector = 6;
        ReadSector(track,sector);
        for(myoffset= 156;myoffset < 158;myoffset++){
		diskbuffer[myoffset]= patchbuffer[myoffset-156]; 
         }
         WriteSector(track,sector);

       /*=================BLOCK #327=================*/
       
        track = 29;     /* main addmem code */
        sector = 8;
        ReadSector(track,sector);
        for(myoffset= 248;myoffset < 300;myoffset++){
        	diskbuffer[myoffset]= mainbuffer[myoffset-248]; 
        }
        WriteSector(track,sector);

     /* =============BLOCK #512=================== */
       
        track = 46;  /* Oh yes we can't forget the checksum */        
        sector = 6;
        ReadSector(track,sector);
        for(myoffset= 488;myoffset < 492 ;myoffset++){
                 diskbuffer[myoffset] = checksumbuffer[myoffset-488]; 
        }      
        WriteSector(track,sector);
        
  
      /* ========== Exit we're done ============= */

        printf("KickMem Completed.\n");
        Gracefulexit();
}                    
   
