//###############################################################################
//#										#
//# AX81 computer with ATmega1284P						#
//# copyright (c) 2010-2012 Joerg Wolfram (joerg@jcwolfram.de)			#
//#										#
//#										#
//# This program is free software; you can redistribute it and/or		#
//# modify it under the terms of the GNU General Public License as		#
//# published by the Free Software Foundation; either version 3 of		#
//# the License, or (at your option) any later version.				#
//#										#
//# This library is distributed in the hope that it will be useful,		#
//# but WITHOUT ANY WARRANTY; without even the implied warranty of		#
//# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU		#
//# General Public License for more details.					#
//#										#
//# You should have received a copy of the GNU General Public			#
//# License along with this library; if not, write to the			#
//# Free Software Foundation, Inc., 59 Temple Place - Suite 330,		#
//# Boston, MA 02111-1307, USA.							#
//#										#
//###############################################################################

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <string.h>
#include <unistd.h>

struct stat buf;

int main( void )
{
	char* buffer;
	struct dirent *CurrentFile;
	DIR *Directory;
	int tape,i,rstat,tfile,wzero;
	unsigned char tprog[16896];
	unsigned char buffer1[50000];
	unsigned char buffer2[50000];
	unsigned char head1[100];
	unsigned char head2[100];
	char filename[1000];
	FILE* imagefile;
	FILE* pfile;
	long offset;
	long filesize;
	int size_low;
	int size_high;
	int fs_type;
	int rptr,wptr,reps,h2len,ftype,blen,page,poffset;
	unsigned char rbyte;

	buffer = (char*)malloc(1000);

	if( (buffer = getcwd( NULL, 0 )) == NULL )
	{
		perror("cannot get working dir");
		return EXIT_FAILURE;
	}


	tape=0;
	fs_type=0;

	for(i=0;i<256;i++)
	{
		sprintf(filename,"/TAPES81_ZX81/TAPE_%03u",i);
		if (strstr(buffer,filename))
		{
			tape=i; 	//found
			fs_type=1;
		}

		sprintf(filename,"/TAPES81_ZX80/TAPE_%03u",i);
		if (strstr(buffer,filename))
		{
			tape=i; 	//found
			fs_type=2;
		}

		sprintf(filename,"/TAPES81_JACE/TAPE_%03u",i);
		if (strstr(buffer,filename))
		{
			tape=i; 	//found
			fs_type=3;
		}

		sprintf(filename,"/TAPES81_SPEC/TAPE_%03u",i);
		if (strstr(buffer,filename))
		{
			tape=i; 	//found
			fs_type=4;
		}
	}


	printf("##############################################################################\n");
	printf("#                                                                            #\n");
	printf("#  AX81b Filesystem Writer V1.26                                             #\n");
	printf("#  (c) 2012 Joerg Wolfram                                                    #\n");
	printf("#                                                                            #\n");
	switch(fs_type)
	{
		case 1:
		printf("#  ZX81 - Mode                                                               #\n");
		break;

		case 2:
		printf("#  ZX80 - Mode                                                               #\n");
		break;

		case 3:
		printf("#  Jupiter ACE - Mode                                                        #\n");
		break;

		case 4:
		printf("#  ZX Spectrum - Mode                                                        #\n");
		break;

		default:
		printf("#  Unknown Mode                                                              #\n");
		break;
	}

	printf("#                                                                            #\n");
	printf("##############################################################################\n\n");

	if(fs_type < 1)
	{
//		printf("WD=%s\n",buffer);
//		printf("FN=%s\n",filename);
		free(buffer);
		printf("Wrong place.\n");
		return EXIT_FAILURE;
	}


	for(i=0;i<16896;i++)
	{
		tprog[i]=255;
	}
	offset=512+540672*tape;

	if(fs_type == 1)
	{
		printf("ZX81 Mode, Tape %d \n",tape);
		imagefile = fopen("../../ax81_x81.bin","r+b");
		rstat=fseek(imagefile,offset,SEEK_SET);

		printf("FORMATTING TAPE\n" );

		for(i=0;i<32;i++)
		{
			fwrite (tprog , 1 , 16896 , imagefile );
		}

		fclose(imagefile);
		tfile=0;

		if ( (Directory = opendir(".")) == NULL)
		{
			free(buffer);
			fflush(stdin);
			printf("Cannot open current dir. Press ENTER !\n");
			getchar();
			return EXIT_FAILURE;
		}

		while ( (CurrentFile = readdir(Directory)) != NULL)
		{
			if (strcmp(CurrentFile->d_name,".") && strcmp(CurrentFile->d_name,".."))
			{
				strcpy(buffer,CurrentFile->d_name);
				if ((strstr(buffer,".p") || strstr(buffer,".P")) && (!strstr(buffer,".pl")))
				{
					if(tfile<32)
					{
						printf("ADDING %s\n",buffer );

						stat(buffer,&buf);
						filesize = buf.st_size;

						if(filesize < 16384)
						{
							for(i=0;i<16896;i++)
							{
								tprog[i]=255;
							}

							pfile = fopen(buffer,"rb");
							rstat=fread(tprog+512 , 1 , filesize , pfile );
							fclose(pfile);

							wzero=0;
							for(i=0;i<10;i++)
							{
								if ((buffer[i]== 0x2e) || (buffer[i]== 0x00)) 
								{
									wzero=1;
								}

								if(wzero==1)
								{
									tprog[i]=32;
								}
								else
								{
									tprog[i]=buffer[i];
								}
							}
							size_low=filesize & 0xff;
							size_high=(filesize >> 8) & 0xff;
							tprog[10]=size_low;
							tprog[11]=size_high;

							imagefile = fopen("../../ax81_x81.bin","r+b");
							offset=512+540672*tape+16896*tfile;
							rstat=fseek(imagefile,offset,SEEK_SET);
							fwrite (tprog , 1 , 16896 , imagefile );
							fclose(imagefile);
							tfile++;		//we have occupied this place
						} //filesize < 16384
					} //tfile<32
				} // (strstr(buffer,".o") || strstr(buffer,".O"))
			} // ne ..
		} // while
	} // if ZX81

	if(fs_type == 2)
	{
		printf("ZX80 Mode, Tape %d \n",tape);
		imagefile = fopen("../../ax81_x80.bin","r+b");
		rstat=fseek(imagefile,offset,SEEK_SET);

		printf("FORMATTING TAPE\n" );

		for(i=0;i<32;i++)
		{
			fwrite (tprog , 1 , 16896 , imagefile );
		}

		fclose(imagefile);
		tfile=0;

		if ( (Directory = opendir(".")) == NULL)
		{
			free(buffer);
			fflush(stdin);
			printf("Cannot open current dir. Press ENTER !\n");
			getchar();
			return EXIT_FAILURE;
		}

		while ( (CurrentFile = readdir(Directory)) != NULL)
		{
			if (strcmp(CurrentFile->d_name,".") && strcmp(CurrentFile->d_name,".."))
			{
				strcpy(buffer,CurrentFile->d_name);
				if ((strstr(buffer,".o") || strstr(buffer,".O")))
				{
					if(tfile<32)
					{
						printf("ADDING %s\n",buffer );

						stat(buffer,&buf);
						filesize = buf.st_size;

						if(filesize < 16384)
						{
							for(i=0;i<16896;i++)
							{
								tprog[i]=255;
							}

							pfile = fopen(buffer,"rb");
							rstat=fread(tprog+512 , 1 , filesize , pfile );
							fclose(pfile);

							wzero=0;
							for(i=0;i<10;i++)
							{
								if ((buffer[i]== 0x2e) || (buffer[i]== 0x00)) 
								{
									wzero=1;
								}

								if(wzero==1)
								{
									tprog[i]=32;
								}
								else
								{
									tprog[i]=buffer[i];
								}
							}

							size_low=filesize & 0xff;
							size_high=(filesize >> 8) & 0xff;
							tprog[10]=size_low;
							tprog[11]=size_high;

							imagefile = fopen("../../ax81_x80.bin","r+b");
							offset=512+540672*tape+16896*tfile;
							rstat=fseek(imagefile,offset,SEEK_SET);
							fwrite (tprog , 1 , 16896 , imagefile );
							fclose(imagefile);
							tfile++;		//we have occupied this place
						} //filesize < 16384
					} //tfile<32
				} // (strstr(buffer,".o") || strstr(buffer,".O"))
			} // ne ..
		} // while
	} // if ZX80

	if(fs_type == 3)
	{
		printf("Jupiter ACE Mode Tape %d \n",tape);
		imagefile = fopen("../../ax81_ace.bin","r+b");
		rstat=fseek(imagefile,offset,SEEK_SET);


		printf("FORMATTING TAPE\n" );

		for(i=0;i<32;i++)
		{
			fwrite (tprog , 1 , 16896 , imagefile );
		}

		fclose(imagefile);
		tfile=0;

		if ( (Directory = opendir(".")) == NULL)
		{
			free(buffer);
			fflush(stdin);
			printf("Cannot open current dir. Press ENTER !\n");
			getchar();
			return EXIT_FAILURE;
		}

		while ( (CurrentFile = readdir(Directory)) != NULL)
		{
			if (strcmp(CurrentFile->d_name,".") && strcmp(CurrentFile->d_name,".."))
			{
				strcpy(buffer,CurrentFile->d_name);
				if ((strstr(buffer,".ace") || strstr(buffer,".ACE")))
				{
					if(tfile<32)
					{
						printf("ADDING %s\n",buffer );

						stat(buffer,&buf);
						filesize = buf.st_size;

						if(filesize < 16384)
						{
							for(i=0;i<16896;i++)
							{
								tprog[i]=255;
							}

							for(i=0;i<40000;i++)
							{
								buffer2[i]=0;
							}

							pfile = fopen(buffer,"rb");
							rstat=fread(buffer1 , 1 , filesize , pfile ); //read into temp file
							fclose(pfile);

							rptr=0;		//read pointer
							wptr=0;		//write pointer

							while(rptr >= 0)
							{
								if(buffer1[rptr] == 0xed)
								{
									if(buffer1[rptr+1] == 0x00)
									{
										rptr = -1;
									}
									else
									{
										reps=buffer1[rptr+1];
										rbyte=buffer1[rptr+2];
										rptr+=3;
										for(i=0;i<reps;i++)
										{
											buffer2[wptr++]=rbyte;
										}
									}
								}
								else
								{
									buffer2[wptr++]=buffer1[rptr++];
								}
							}

							wzero=0;
							for(i=0;i<10;i++)
							{
								if ((buffer[i]== 0x2e) || (buffer[i]== 0x00)) 
								{
									wzero=1;
								}

								if(wzero==1)
								{
									tprog[i]=32;
								}
								else
								{
									tprog[i]=buffer[i];
								}
							}

							size_low=buffer2[0x80];		//RAMTOP
							size_high=buffer2[0x81];	//RAMTOP
							tprog[10]=size_low;
							tprog[11]=size_high;
							tprog[16]=0xdc;

							for(i=0;i<72;i++)		//copy register settings
							{
								tprog[256+i]=buffer2[256+i];
							}

							for(i=0;i<16384;i++)		//copy memory
							{
								tprog[512+i]=buffer2[i];
							}

							imagefile = fopen("../../ax81_ace.bin","r+b");
							offset=512+540672*tape+16896*tfile;
							rstat=fseek(imagefile,offset,SEEK_SET);
							fwrite (tprog , 1 , 16896 , imagefile );
							fclose(imagefile);
							tfile++;		//we have occupied this place
						} //filesize < 16384
					} //tfile<32
				} //(strstr(buffer,".ace") || strstr(buffer,".ACE"))
			} // ne ..
		} //while

	} // if ACE

	if(fs_type == 4)
	{
		printf("ZX Spectrum Mode Tape %d \n",tape);

		imagefile = fopen("../../ax81_spc.bin","r+b");
		rstat=fseek(imagefile,offset,SEEK_SET);

		printf("FORMATTING TAPE\n" );

		for(i=0;i<32;i++)
		{
			fwrite (tprog , 1 , 16896 , imagefile );
		}

		fclose(imagefile);
		tfile=0;

		if ( (Directory = opendir(".")) == NULL)
		{
			free(buffer);
			fflush(stdin);
			printf("Cannot open current dir. Press ENTER !\n");
			getchar();
			return EXIT_FAILURE;
		}

		while ( (CurrentFile = readdir(Directory)) != NULL)
		{
			if (strcmp(CurrentFile->d_name,".") && strcmp(CurrentFile->d_name,".."))
			{
				strcpy(buffer,CurrentFile->d_name);
				if ((strstr(buffer,".z80") || strstr(buffer,".Z80")))
				{
					if(tfile<32)
					{
						printf("ADDING %s\n",buffer );

						stat(buffer,&buf);
						filesize = buf.st_size;

						if(filesize < 16384)
						{
							for(i=0;i<16896;i++)
							{
								tprog[i]=255;
							}

							pfile = fopen(buffer,"rb");
							rstat=fread(buffer1 , 1 , filesize , pfile );
							fclose(pfile);

							wzero=0;
							for(i=0;i<10;i++)
							{
								if ((buffer[i]== 0x2e) || (buffer[i]== 0x00)) 
								{
									wzero=1;
								}

								if(wzero==1)
								{
									tprog[i]=32;
								}
								else
								{
									tprog[i]=buffer[i];
								}
							}
							tprog[16]=0xcc;

							ftype=1;		//file type

							for(i=0;i<30;i++)		//copy register settings
							{
								head1[i]=buffer1[i];
							}
							filesize-=30;
							rptr+=30;

							if((head1[6]==0) && (head1[7]==0))
							{
								printf (" >> MODE 2 ");
								h2len=buffer1[rptr]+256*buffer1[rptr+1];
								rptr+=2;
								filesize-=2;

								if(h2len > 54)
								{
									ftype=99;
									printf ("%s has invalid format\n",buffer);
								}

								for(i=0;i<h2len;i++)		//copy register settings
								{
									head2[i]=buffer1[rptr++];
								}
								filesize-=h2len;

								//copy PC value from header2 to header1
								head1[6]=head2[0];
								head1[7]=head2[1];


								if(head2[4] > 1)
								{
									ftype=99;
									printf ("%s is not hardware compatible\n",buffer);
								}


								while(filesize>3)
								{
									blen=buffer1[rptr]+256*buffer1[rptr+1];
									page=buffer1[rptr+2];
									filesize-=3;
									rptr+=3;

									poffset=-1;
									if (page==8) { poffset=0; }
									if (page==4) { poffset=16384; }
									if (page==5) { poffset=32768; }
									if (poffset >=0)
									{
										printf (" >> Page %d",page);
										//&uncompress_data($blen,$poffset,16384);
									}
									else
									{
										printf("\nWrong page $page in %s\n",buffer);
										ftype=99;
									}
								}
								printf (" >> End of file\n");
							} //end mode 2
							else
							{
								if((head1[12] & 32) == 32)
								{
									printf (" >> MODE 1C ");
									//&uncompress_data($dlen-4,0,49152);
									printf (" >> End of file, rest %ld\n",filesize);

								}
								else
								{
									printf (" >> MODE 1U ");
									for(i=0;i<49152;i++)
									{
										buffer2[i]=buffer1[rptr++];
										filesize-=1;
									}
									printf (" >> End of file, rest %ld\n",filesize);
								}
							} //(head1[6]==0) && (head1[7]==0)


							if(ftype < 99)
							{
								for(i=0;i<30;i++)		//write header
								{
									tprog[i+256]=head1[i];
								}
								for(i=0;i<15360;i++)		//write data
								{
									tprog[i+512]=buffer2[i];
								}

								imagefile = fopen("../../ax81_spc.bin","r+b");
								offset=512+540672*tape+16896*tfile;
								rstat=fseek(imagefile,offset,SEEK_SET);
								fwrite (tprog , 1 , 16896 , imagefile );
								fclose(imagefile);
								tfile++;		//we have occupied this place
							} //ftype < 99
						} //filesize < 16384
					} //tfile<32
				} //(strstr(buffer,".z80") || strstr(buffer,".Z80"))
			} // ne ..
		} //while

	} //if spectrum

	free(buffer);
	return(0);
}
