#include "RDiskCP.h"

static long RDiskCPMacDev() {
	int i;
	// Check signature and return 0 if doesn't match
	// Don't check for length byte at beginning or null byte at endss
	for (i = 1; i < sizeof(RDiskSigStr)-1; i++) {
		if (RDiskSigPtr[i] != RDiskSigStr[i]) {
			// If signature doesn't match,
			// fail if not holding R key
			if (!((*((char*)0x175)) & 0x80)) { return 0; }
		}
	}
	return 1; // Otherwise return 1 if signature matches
}

static void RDiskCPUpdate(DialogPtr cpDialog, short numItems) {
	GrafPtr savePort;
	Handle h;
	Rect r;
	short type;
	char startup, ram;
	
	// Get startup and ram from PRAM
	RDiskCPReadXPRam(1, 4, &startup);
	RDiskCPReadXPRam(1, 5, &ram);
	
	// Save GrafPort and set port to dialog before updating items
	GetPort(&savePort);
	SetPort(cpDialog);
	
	GetDItem(cpDialog, BootCheckbox+numItems, &type, &h, &r);
	SetCtlValue((ControlHandle)h, startup & 0x01 ? 1 : 0);
	
	GetDItem(cpDialog, MountCheckbox+numItems, &type, &h, &r);
	SetCtlValue((ControlHandle)h, !(startup & 0x02) && !(startup & 0x01) ? 1 : 0);
	HiliteControl((ControlHandle)h, startup & 0x01 ? 255 : 0);
	
	GetDItem(cpDialog, RAMCheckbox+numItems, &type, &h, &r);
	SetCtlValue((ControlHandle)h, 
		((startup & 0x01) || !(startup & 0x02)) && (ram & 0x01) ? 1 : 0);
	HiliteControl((ControlHandle)h, (startup & 0x01) || !(startup & 0x02) ? 0 : 255);
	
	GetDItem(cpDialog, DebugCheckbox+numItems, &type, &h, &r);
	SetCtlValue((ControlHandle)h, startup & 0x04 && (startup & 0x01) ? 1 : 0);
	HiliteControl((ControlHandle)h, !(startup & 0x01) || !*RDiskDBGDisPos ? 255 : 0);
	
	GetDItem(cpDialog, CDROMCheckbox+numItems, &type, &h, &r);
	SetCtlValue((ControlHandle)h, startup & 0x08 && (startup & 0x01) ? 1 : 0);
	HiliteControl((ControlHandle)h, !(startup & 0x01) || !*RDiskCDROMDisPos ? 255 : 0);
	
	// Restore old GrafPort
	SetPort(savePort);
}

static void RDiskCPHitDev(short message, short item, short numItems,
				   short cpPrivateVal, EventRecord *theEvent,
				   void *cdevStorageValue, DialogPtr cpDialog) {
	char startup, ram;
	RDiskCPReadXPRam(1, 4, &startup);
	RDiskCPReadXPRam(1, 5, &ram);
	switch (item - numItems) {
		case BootCheckbox:
			if (startup & 0x01) { startup &= 0x0F & ~0x01; }
			else { startup = startup & 0x0F | 0x01; }
			break;
		case MountCheckbox:
			if (!(startup & 0x01)) {
				if (startup & 0x02) { startup &= 0x0F & ~0x02; }
				else { startup = startup & 0x0F | 0x02; }
			}
			break;
		case RAMCheckbox:
			if ((startup & 0x01) || !(startup & 0x02)) { 
				if (ram & 0x01) { ram = 0x00; }
				else { ram = 0x01; }
			}
			break;
		case DebugCheckbox:
			if (startup & 0x01) {
				if (startup & 0x04) { startup &= 0x0F & ~0x04; }
				else { startup = startup & 0x0F | 0x04; }
			}
			break;
		case CDROMCheckbox:
			if (startup & 0x01) {
				if (startup & 0x08) { startup &= 0x0F & ~0x08; }
				else { startup = startup & 0x0F | 0x08; }
			}
			break;
	};
	RDiskCPWriteXPRam(1, 4, &startup);
	RDiskCPWriteXPRam(1, 5, &ram);
	RDiskCPUpdate(cpDialog, numItems);
}

static void RDiskCPInitDev(short message, short item, short numItems,
						   short cpPrivateVal, EventRecord *theEvent,
						   void *cdevStorageValue, DialogPtr cpDialog) {
	Str15 ramSize;
	Str255 dbgName = "\pMacsBug";
	Str255 cdromName = "\pCD-ROM Ext.";
	int i;
	ramSize[0] = 2;
	if (RDiskCPMacDev()) {
		ramSize[1] = RDiskRAMReq[0];
		ramSize[2] = RDiskRAMReq[1];
	} else {
		ramSize[1] = '1';
		ramSize[2] = '6';
	}

	if (RDiskCPMacDev() && *RDiskDBGNamePos != 0) {
		for (i = 0; i < 255; i++) {
			dbgName[i] = (*RDiskDBGNamePos)[i];
		}
	}

	if (RDiskCPMacDev() && *RDiskCDROMNamePos != 0) {
		for (i = 0; i < 255; i++) {
			cdromName[i] = (*RDiskCDROMNamePos)[i];
		}
	}

	ParamText(ramSize, dbgName, cdromName, 0);
}

pascal long main(short message, short item, short numItems,
				 short cpPrivateVal, EventRecord *theEvent,
				 void *cdevStorageValue, DialogPtr cpDialog)
{
	long ret = (long)cdevStorageValue;
	// Switch to our A4 world
	EnterCodeResource();
	// Handle message
	switch (message) {
		case initDev:
			RDiskCPInitDev(message, item, numItems,
						   cpPrivateVal, theEvent,
						   cdevStorageValue, cpDialog);
			// (fall through to return cdevUnset)
		case closeDev:
			ret = cdevUnset; break;
		case macDev:
			ret = RDiskCPMacDev(); break;
		case updateDev:
		case activDev:
		case deactivDev:
			RDiskCPUpdate(cpDialog, numItems);
			break;
		case hitDev: 
			RDiskCPHitDev(message, item, numItems,
						  cpPrivateVal, theEvent,
						  cdevStorageValue, cpDialog);
			break;
	};
	// Restore old A4 world and return result
	ExitCodeResource();
	return ret;
}
