/*
* Copyright 2007 Michael Buckley
*
* 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 2 of the license or (at your option)
* any later version.
*
* This program 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 Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, If not, see .
*/
#include
#include
#ifndef __mac_os
#undef FALSE
#undef TRUE
typedef enum { FALSE, TRUE } bool;
#endif
#define COOKIE "MegaHALv8"
#define BYTE1 unsigned char
#define BYTE2 unsigned short
#define BYTE4 unsigned long
static void convert_brain(FILE* in, FILE* out, bool native);
static bool convert_tree(FILE* in, FILE* out, bool native);
static bool convert_dictionary(FILE* in, FILE* out, bool native);
static BYTE2 swap2(BYTE2 val);
static BYTE4 swap4(BYTE4 val);
int main(int argc, char* argv[])
{
/* This code is outdated. It's worth a look if you want to understand the
* workings of the megahal brain. However, a lot of it is similar to the
* load methods from the MegaHAL source. Furthermore, it requires the user
* to specify whether to convert it to or from the native format. The newer
* version uses a different method which does not parse the data structures
* as MegaHAL does. If you really want to see this program in action,
* comment out the next three lines.
*/
fprintf(stdout, "DO NOT USE THIS PROGRAM, IT IS OUTDATED.\n");
fprintf(stdout, "You can get a new version from http://angrymen.org/\n\n");
return 0;
if(argc < 3 || argc > 4){
fprintf(stdout, "Incorrect arguments.\n");
fprintf(stdout, "Usage: %s in out [tonative|fromnative]\n", argv[0]);
return 0;
}
FILE* in = fopen(argv[1], "r");
if(in == NULL){
printf("Could not open the file %s for reading", argv[1]);
return 0;
}
FILE* out = fopen(argv[2], "w");
if(in == NULL){
printf("Could not open the file %s for writing", argv[2]);
return 0;
}
bool native;
if(argc == 3){
native = FALSE;
}else{
native = strcmp(argv[3], "tonative") != 0;
}
convert_brain(in, out, native);
return 0;
}
void convert_brain(FILE* in, FILE* out, bool native)
{
char cookie[10];
memset(cookie, 0, 10);
if(fread(cookie, sizeof(char), strlen(COOKIE), in) < strlen(COOKIE)){
fprintf(stderr, "Error: Reached file end before magic number.\n");
}
if(strcmp(cookie, COOKIE)!=0){
fprintf(stderr, "This is not a Megahal Brain.\n");
return;
}
fwrite(cookie, 1, strlen(COOKIE), out);
BYTE1 order = fgetc(in);
if(feof(in) != 0){
fprintf(stderr, "Error: reached file end before model order.\n");
return;
}
fputc(order, out);
if(convert_tree(in, out, native) == TRUE){
if(convert_tree(in, out, native) == FALSE){
return;
}
}else{
return;
}
if(convert_dictionary(in, out, native) == FALSE){
return;
}
fprintf(stdout, "Conversion successful.\n");
}
bool convert_tree(FILE* in, FILE* out, bool native)
{
BYTE2 symbol;
if(fread(&symbol, sizeof(BYTE2), 1, in) < 1){
fprintf(stderr, "Error: reached file end before tree symbol.\n");
return FALSE;
}
symbol = swap2(symbol);
fwrite(&symbol, sizeof(BYTE2), 1, out);
BYTE4 usage;
if(fread(&usage, sizeof(BYTE4), 1, in) < 1){
fprintf(stderr, "Error: reached file end before tree usage.\n");
return FALSE;
}
usage = swap4(usage);
fwrite(&usage, sizeof(BYTE4), 1, out);
BYTE2 count;
if(fread(&count, sizeof(BYTE2), 1, in) < 1){
fprintf(stderr, "Error: reached file end before tree count.\n");
return FALSE;
}
count = swap2(count);
fwrite(&count, sizeof(BYTE2), 1, out);
BYTE2 branch;
if(fread(&branch, sizeof(BYTE2), 1, in) < 1){
fprintf(stderr, "Error: reached file end before tree branch.\n");
return FALSE;
}
int loopval = branch;
branch = swap2(branch);
if(native == FALSE){
loopval = branch;
}
fwrite(&branch, sizeof(BYTE2), 1, out);
register unsigned int i;
for(i = 0; i < loopval; ++i){
if(convert_tree(in, out, native) == FALSE){
return FALSE;
}
}
return TRUE;
}
bool convert_dictionary(FILE* in, FILE* out, bool native)
{
BYTE4 size;
if(fread(&size, sizeof(BYTE4), 1, in) < 1){
fprintf(stderr, "Error: reached file end before dictionary size.\n");
return FALSE;
}
size = swap4(size);
fwrite(&size, sizeof(BYTE4), 1, out);
char c = fgetc(in);
while(c != EOF){
fputc(c, out);
c = fgetc(in);
}
return TRUE;
}
BYTE2 swap2(BYTE2 val)
{
return (((val & 0xFF00) >> 8) | ((val & 0x00FF) << 8));
}
BYTE4 swap4(BYTE4 val)
{
return (((val & 0xFF000000) >> 24) | ((val & 0x00FF0000) >> 8) |
((val & 0x0000FF00) << 8) | ((val & 0x000000FF) << 24));
}