/*  KickMem V2.0 for version 1.3 kickstart, by Dave Williams 
    26 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 [] = {0x88,0xb2};  /* pointer to addmem */
BYTE mainbuffer [] = {             /* AddMem code */
   	0x4e,0xf9,0x00,0xfe,
   	0x89,0x1e,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,
   	0x84,0x44,0x4e,0x71   
     };
BYTE checksumbuffer[] = {0x48,0x6d,0x56,0x4f}; /* 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 2.0, Public Domain 1989, By Dave Williams\n");
        printf("\nPLACE KickStart V1.3 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 #37==================*/
       
        track = 3;    /* Check for version 34.1 disk resource */
        sector = 4;
        ReadSector(track,sector);
        if(diskbuffer[41]!= '3'|| diskbuffer[42]!= '4' || 
           diskbuffer[43]!= '.' ||  diskbuffer[44]!= '1'){
                printf("ERROR: Not a Version 34.5 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 #322===================*/
       
        track = 29;  /* grab strap pointer to point to addmem code */
        sector = 3;
        ReadSector(track,sector);
        for(myoffset= 504;myoffset < 506 ;myoffset++){
		diskbuffer[myoffset]= patchbuffer[myoffset-504]; 
         }
         WriteSector(track,sector);

       /*=================BLOCK #325=================*/
       
        track = 29;     /* main addmem code */
        sector = 6;
        ReadSector(track,sector);
        for(myoffset= 172;myoffset < 224 ;myoffset++){
        	diskbuffer[myoffset]= mainbuffer[myoffset-172]; 
        }
        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();
}                    
   
