/* med-objsav.c: Object file saving routine by Teijo Kinnunen, 1990 */

#include "med.h"
#define	ERR return(diskerr(fh,0))
extern struct Kappale far tamakappale;
extern struct Soitin *soitin[];
extern struct Lohko *lohko[];
extern BOOL diskerr(),AskName(),Continue();
extern UWORD lohkoja;
static BPTR fh;

static BOOL FWrite(char *ptr,long len)
{
	return((BOOL)(Write(fh,ptr,len) != len));
}

static BOOL WriteLong(ULONG lw)
{
	return(FWrite((char *)(&lw),4));
}

static ULONG NofLWs(ULONG num)
{
	while(num % 4) num++;
	num /= 4;
	return(num);
}

static BOOL WriteName(char *name)
{
	ULONG	namelen = NofLWs(strlen(name));
	UBYTE	padn = ((UBYTE)namelen * 4) - strlen(name),padcnt,zero = 0;
	if(WriteLong(namelen)) return(TRUE);
	if(FWrite(name,strlen(name))) return(TRUE);
	for(padcnt = 0; padcnt < padn; padcnt++) {
		if(FWrite(&zero,1)) return(TRUE);
	}
	return(FALSE);
}

static BOOL pad(ULONG size)
{
	ULONG paddedsize = NofLWs(size) * 4;
	UBYTE zero = 0;
	while(size++ < paddedsize) if(FWrite(&zero,1)) return(TRUE);
	return(FALSE);
}

BOOL WriteObj(char *name)
{
	char fname2[52];
	struct ObjSong osng;
	ULONG instrsiz = 2,blksiz = 0,bpsiz,ioffstbl[32],blkoffstbl[100] = {0};
	ULONG reloffs = 0;
	UBYTE scnt,nofinstrs = 0,oldexists = 0;
	if(*name == '\0') return(AskName());
	strcpy(fname2,name);
	scnt = strlen(fname2);
	if(scnt > 2 && fname2[scnt - 1] == 'o' && fname2[scnt - 2] == '.');
	else strcat(fname2,".o");
	if(IsHere(fname2)) {
		Ilmoita("File already exists. Continue?");
		oldexists = 1;
		if(!Continue()) return(TRUE);
	}
	if(!(fh = Open2(fname2,MODE_NEWFILE))) return(diskerr(0,0));
	Ilmoita("Saving object file...");
/* -------- First: write hunk_unit, which contains the name of this unit */
	if(WriteLong(0x000003E7)) ERR; /* hunk_unit */
	if(WriteName(fname2)) ERR;
	memcpy((char *)(&osng),(char *)(&tamakappale.soittimenvoimakkuus[0]),
		264);
	osng.blocks = lohkoja;
	osng.songlen = tamakappale.kappaleen_pituus;
	osng.playtransp = tamakappale.playtransp;
	osng.flags = tamakappale.liput;
	osng.slide = tamakappale.vaihtoja;
	memcpy(&osng.midichan[0],&tamakappale.midikanava[0],64);
/* ----------- Write the first hunk, which contains the instruments */
	if(WriteLong(0x400003EA)) ERR; /* hunk_data (chip) */
	for(scnt = 0; scnt < 32; scnt++) {
		if(soitin[scnt]) {
			ioffstbl[scnt] = instrsiz;
			instrsiz += sizeof(struct Soitin);
			instrsiz += (soitin[scnt]->length & 0xfffffffe);
			nofinstrs++;
		} else ioffstbl[scnt] = 0L;
	}
	for(scnt = 0; scnt < lohkoja; scnt++) {
		blkoffstbl[scnt] = blksiz;
		blksiz += 4 + ONETRKSIZE * lohko[scnt]->numtracks;
	}
	bpsiz = 4 * lohkoja; /* size of block pointers */
	if(WriteLong(NofLWs(instrsiz))) ERR;
	if(FWrite((char *)reloffs,2)) ERR; /*write zero to the beginning*/
	for(scnt = 0; scnt < 32; scnt++) {
		if(soitin[scnt]) {
			if(FWrite((char *)soitin[scnt],sizeof(struct Soitin)
				+ (soitin[scnt]->length & 0xfffffffe))) ERR;
		}
	}
	if(pad(instrsiz)) ERR;
	if(WriteLong(0x000003EF)) ERR; /* hunk_ext */
	if(WriteLong(0x01000002)) ERR;
	if(FWrite("_zeroptr",8)) ERR;
	if(WriteLong(0x00000000)) ERR;
	if(WriteLong(0x00000000)) ERR;
	if(WriteLong(0x000003F2)) ERR; /* hunk_end */
/* ---------- Then write the second hunk, music */
	if(WriteLong(0x000003EA)) ERR; /* hunk_data */
	if(WriteLong(NofLWs(blksiz))) ERR;
	for(scnt = 0; scnt < lohkoja; scnt++) {
		if(FWrite((char *)(lohko[scnt]),4 + ONETRKSIZE *
			lohko[scnt]->numtracks)) ERR;
	}
	if(pad(blksiz)) ERR;
	if(WriteLong(0x000003F2)) ERR; /* hunk_end */
/* --------- And finally the third hunk, which contains everythine else */
	if(WriteLong(0x000003EA)) ERR; /* hunk_data */
	/* sizes of: instrument ptrs, song, block ptrs */
	if(WriteLong(NofLWs(32 * 4 + sizeof(osng) + bpsiz))) ERR;
	if(FWrite((char *)ioffstbl,32 * 4)) ERR; /* write the instr ptrs */
	if(FWrite((char *)(&osng),sizeof(osng))) ERR; /* write the song */
	if(FWrite((char *)blkoffstbl,bpsiz)) ERR; /* write the blk ptrs */
	if(pad(32 * 4 + sizeof(osng) + bpsiz)) ERR;
/* --------- We need to relocate something */
	if(WriteLong(0x000003EC)) ERR; /* hunk_reloc32 */
	if(nofinstrs) {
		if(WriteLong((ULONG)nofinstrs)) ERR;
		if(WriteLong(0x00000000)) ERR; /* Instruments in hunk #0 */
		for(scnt = 0; scnt < 32; scnt++, reloffs += 4) {
			if(soitin[scnt]) {
				if(WriteLong(reloffs)) ERR;
			}
		}
	}
	reloffs = 32 * 4 + sizeof(osng);
	if(WriteLong((ULONG)lohkoja)) ERR;
	if(WriteLong(0x00000001)) ERR; /* Music in hunk #1 */
	for(scnt = 0; scnt < lohkoja; scnt++, reloffs += 4) {
		if(WriteLong(reloffs)) ERR;
	}
	if(WriteLong(0x00000000)) ERR; /* end */
/* -------- And dump the external symbols defined in this file */
	if(WriteLong(0x000003EF)) ERR; /* hunk_ext */
	if(WriteLong(0x01000002)) ERR;
	if(FWrite("_samples",8)) ERR;
	if(WriteLong(0x00000000)) ERR;
	if(WriteLong(0x01000002)) ERR;
	if(FWrite("_song\0\0\0",8)) ERR;
	if(WriteLong(0x00000080)) ERR;
	if(WriteLong(0x01000002)) ERR;
	if(FWrite("_blocks\0",8)) ERR;
	if(WriteLong(0x00000080 + sizeof(osng))) ERR;
	if(WriteLong(0x00000000)) ERR;
	if(WriteLong(0x000003F2)) ERR; /* hunk_end */
	Close(fh); /* huh, huh !! */
	if(!oldexists) InsertSavedFile(fname2);
	Ilmoita("Object file is now saved.");
	return(FALSE);
}
