/**************************************************
 
 	DiskNameChange.c  
 	Aendern des Disknamens
 	mit Trackdisk.device
 
 	-=mb=- Aug-87
 
 **************************************************/

#include <exec/types.h>
#include <exec/exec.h>
#include <devices/trackdisk.h>
#include <stdio.h>

/* Funktionsdeklarationen aus <functions.h> */
long DoIO();
void *AllocMem();
void FreeMem();
struct MsgPort *CreatePort();
void DeletePort();
struct IOStdReq *CreateStdIO();
void DeleteStdIO();
long OpenDevice();
void CloseDevice();

#define BLOCKSIZE TD_SECTOR
#define MOTOR_ON 1
#define MOTOR_OFF 0

struct MsgPort *diskport;
struct IOStdReq *diskreq;
int openerror = -999;
/* hier lesen wir einen Block hinein */
unsigned char *diskbuffer;
 
/* hier lesen wir einen Block von Diskette */
ReadBlock(block, buffer)	
int block;
unsigned char *buffer;
	{
	diskreq->io_Length = BLOCKSIZE;
	diskreq->io_Data = (APTR)buffer;
	diskreq->io_Command = CMD_READ;
	diskreq->io_Offset = block*BLOCKSIZE;
	DoIO(diskreq);
	}

/*----- ab hier neu --------------------------------*/

/* hier schreiben wir einen Block auf Diskette */
WriteBlock(block, buffer)	
int block;
unsigned char *buffer;
	{
	diskreq->io_Length = BLOCKSIZE;
	diskreq->io_Data = (APTR)buffer;
	diskreq->io_Command = CMD_WRITE;
	diskreq->io_Offset = block*BLOCKSIZE;
	DoIO(diskreq);
	}

/* alle Puffer im Speicher auf Disk zurueckschreiben */
Update()
	{
        diskreq->io_Command = CMD_UPDATE;
	DoIO(diskreq);
	}

/*----- bis hier neu -------------------------------*/

/* Drivemotor an- bzw. ausschalten */
SwitchMotor(onoffswitch)
/* onoffswitch ist MOTOR_ON oder MOTOR_OFF */
int onoffswitch;
	{
	diskreq->io_Length = onoffswitch;
	diskreq->io_Command = TD_MOTOR;
	DoIO(diskreq);
	}

/*----- ab hier neu --------------------------------*/

CorrectBlockChecksum(buffer)
unsigned char *buffer;
	{
	ULONG checksum, *longbufptr;
	int i;

	longbufptr = (ULONG *)buffer;
	checksum = 0;
	for (i = 0; i < BLOCKSIZE/4; i++)
		checksum += longbufptr[i];
	longbufptr[5] -= checksum;
	}

/*----- bis hier neu -------------------------------*/

/* Programmsteuerung */
main()   
	{
	char input[256];
	/* wir benutzen Drive 0 */
	long drive = 0;
	int namelength;
	int i;
        
	puts("Diskette in Laufwerk 0 einlegen und RETURN druecken");
	/* auf <RETURN> warten */
	gets(input);	

	/* CHIP-memory fuer Puffer holen */
	diskbuffer = AllocMem(BLOCKSIZE, MEMF_CHIP);
	if (diskbuffer == 0) cleanup("No memory!");

	/* Port zur Kommunikation mit trackdisk.device aufbauen */
	diskport = CreatePort("mydisk.port", 0L);
	if (diskport == 0) cleanup("CreatePort failed!");

	/* StdIO-Block zur Kommunikation ueber 'diskport' aufbauen */
	diskreq = CreateStdIO(diskport);
	if (diskreq == 0) cleanup("CreateStdIO failed!");
 
	/* wir reservieren uns trackdisk.device df0: */
	openerror = OpenDevice(TD_NAME,drive,diskreq,0L);
	if (openerror) cleanup("OpenDevice failed!");
    
	/* Drive-Motor einschalten */
	SwitchMotor(MOTOR_ON);

	/* Root-Block (normalerweise 880) einlesen */
	ReadBlock(880, diskbuffer);
	if (diskreq->io_Error != 0) {
		printf("Fehler beim Lesen, Fehlernummer: %d\n", 
			diskreq->io_Error);
		cleanup(NULL);
		}

	/* wir drucken den BCPL-String Diskettenname */
	/* Byte Nr. 432 gibt die Laenge des Namens */
	namelength = diskbuffer[432];
	/* Der eigentliche Name steht ab Byte 433 */
	printf("Alter Diskettenname: ");
	for (i = 0; i < namelength; i++)
		putchar(diskbuffer[433+i]);
	putchar('\n');

/*----- ab hier neu --------------------------------*/

	/* Neuen Disknamen einlesen */
	puts("Neuer Diskettenname ?");
	gets(input);
	if (strlen(input) > 30) 
		cleanup("Diskname zu lang (> 30 Zeichen)");
	diskbuffer[432] = strlen(input);
	for (i = 0; i < strlen(input); i++)
		diskbuffer[433+i] = input[i];

	/* Block-Checksumme neu berechnen und aktualisieren */
	CorrectBlockChecksum(diskbuffer);

	/* Root-Block schreiben und Disk updaten */
	WriteBlock(880, diskbuffer);
	if (diskreq->io_Error != 0) {
		printf("Fehler beim Schreiben, Fehlernummer: %d\n", 
			diskreq->io_Error);
		cleanup(NULL);
		}
	Update();
	if (diskreq->io_Error != 0) {
		printf("Fehler bei Update, Fehlernummer: %d\n", 
			diskreq->io_Error);
		cleanup(NULL);
		}

/*----- bis hier neu -------------------------------*/

	/* Drive-Motor ausschalten */
	SwitchMotor(MOTOR_OFF);
	cleanup(NULL);
	}
 
/* Aufraeumarbeiten erledigen */
cleanup(mes)
char *mes;
	{
	/* evtl. Fehlermeldung */
	if (mes) puts(mes);

	/* Drive df0: wieder freigeben */
	if (!openerror) CloseDevice(diskreq);
	/* StdIo-Block loeschen */
	if (diskreq) DeleteStdIO(diskreq);
	/* DiskPort entfernen */
	if (diskport) DeletePort(diskport);
	/* Pufferspeicher freigeben */
	if (diskbuffer) FreeMem(diskbuffer, BLOCKSIZE);
	exit(0);
	}
