#include <stdio.h>
#include <stdlib.h>
#include <string.h>

const char fileheader[]= {
    '*','*','T','I','*',0x1A,0xA0,0x00};
const char comment[42]= "File generated by Makeprgm ";

const char typearray[] = {
    '7','3','*',0x0B,
    '8','2','*',0x0B,
    '8','3','*',0x0B,
    '8','3','F',0x0D};

const char extensions[][4] = {
    "73P","82P","83P","8XP"};


void makeprgm(FILE* infile, FILE* outfile, char* name, int calc);
void namefix(char* name);
void error(const char* msg );

int main(int argc, char *argv[]) {
    FILE* infile;
    FILE* outfile;
    int i,namelength,calc;
    char* name;

    if (argc < 3){
        printf("Usage:  %s infile.bin PRGMNAME.8xp\n",argv[0]);
        puts("PRGMNAME should be no longer than 8 characters.\n"
             "It should only use Numbers and Letters.\n"
             "Extension determines the model the file will be generated for.\n"
             "73 = 73P | 82 = 82P | 83 = 83P | 83+ = 8XP\n");
        return 1;
    }

    if (!(outfile = fopen(argv[2],"wb"))) error("Could not open out file.");

    for(i = 0; argv[2][i]!='.' && argv[2][i]; i++);
    if (!argv[2][i]) error("Output file name does not have an extension");
    if (i > 8) error("Output file name is too long.\n It must only be 8 characters w/o extension");
    argv[2][i] = 0;
    namelength = i-1;
    name = argv[2]+i+1;
    namefix(name);
    for(i = 0; i < sizeof(extensions)/4 && strcmp(name,extensions[i]); i++);
    if (i == sizeof(extensions)/4) error("Output Extension invalid!");

    if (!(infile = fopen(argv[1],"rb"))) error("Could not open in file.");
    makeprgm(infile,outfile,argv[2],i);
    fclose(outfile);
    fclose(infile);
    puts("File Created");
    return 0;
}


void makeprgm(FILE* infile, FILE* outfile, char* name, int calc) {
    int i,size,temp;
    unsigned char* pnt;
    int chksum;
    
    namefix(name);
    
    fseek(infile,0,SEEK_END);
    size = ftell(infile)+2;
    rewind(infile);
    
    if (size > 24000) {
        if (size > 65000) error("File size is greater than 64k");
        puts("Warning: Files size greater than 24k");
    }
    for(i = 0; i < 4; i++) fputc(fileheader[i],outfile);
    pnt = ((unsigned char*)typearray+(calc<<2));
    fputc(pnt[0],outfile);
    fputc(pnt[1],outfile);
    fputc(pnt[2],outfile);
    while (i < 8) fputc(fileheader[i++],outfile);
    for (i = 0; i < 42; i++) fputc(comment[i],outfile);

    temp=size+15+((calc==3)?2:0);
    fputc(temp & 0xFF,outfile);
    fputc(temp >> 8,outfile);
    fputc((chksum = pnt[3]),outfile);
    fputc(0,outfile);
    chksum += fputc(size & 0xFF,outfile);
    chksum += fputc(size>>8,outfile);
    chksum += fputc(6,outfile);
    
    if (!((temp=name[0])>='A' && temp<='Z')) error("1st character in name must be a letter.");
    for(i = 0; i < 8; i++) chksum += fputc(name[i], outfile);

    if (calc==3) {
        fputc(0,outfile);
        fputc(0,outfile);
    }
    chksum += fputc(size & 0xFF,outfile);
    chksum += fputc(size>>8,outfile);
    size-=2;
    chksum += fputc(size & 0xFF,outfile);
    chksum += fputc(size>>8,outfile);
    for(i = 0; i < size; i++) {
        chksum += fputc(fgetc(infile),outfile);
    }
    fputc(chksum & 0xFF,outfile);
    fputc((chksum >> 8) & 0xFF,outfile);
}

void error( const char* msg ) {
    printf("Error: %s\n",msg);
    exit(1);
}

void namefix(char* name) {
    int i;
    char temp;

    while (temp = *name) {
        if (temp>='a' && temp<='z') *name = temp =(temp-('a'-'A'));
        if (!( ((temp>='A') && (temp<='Z')) || (temp>='0' && temp<='9') || (temp==0) ) ) {
            error("Invalid characters in name. Alphanumeric Only.");
        }
        name++;
    }
}


