Casio_asm/assembler/main.c

230 lines
6.5 KiB
C

#include "../common/types.h"
#include "../common/opcodeInfo.h"
#include "../common/buffer.h"
#include "../common/sourceFile.h"
#include "assembler.h"
#include "assemblerConfig.h"
#include <stdio.h>
#include <stdlib.h>
#define error(...) fprintf(stderr, __VA_ARGS__)
int main(int argc, char** argv) {
//BEGIN variable definitions
int sourceFile=-1, outputFile=-1, configFile=-1;
buffer_t sourceBuffer, outputBuffer, configBuffer, infoBuffer;
int sourceLen, configLen, outputPos;
assembler_config_t config;
source_file_t header;
mapping_t mapping;
assembler_t assembler;
int hasConfig;
//END variable definitions
//BEGIN check usage
argc--;
if(argc!=2&&argc!=3) {
error("Usage: %s <source> <output> [config]\n", argv[0]);
return 1;
} else {
printf("Using %d arguments\n", argc);
}
hasConfig=argc==3;
//END check usage
//BEGIN open the files
sourceFile=File_open(argv[1], FILE_OPEN_read);
outputFile=File_open(argv[2], FILE_OPEN_write|FILE_OPEN_create);
if(hasConfig) configFile=File_open(argv[3], FILE_OPEN_read);
//END open the files
//BEGIN check if opening the files went well
if(sourceFile==-1) {
error("ERR: Couldn't open input file %s\n", argv[1]);
return 1;
}
if(outputFile==-1) {
error("ERR: Couldn't open output file %s\n", argv[2]);
return 1;
}
if(hasConfig&&configFile==-1) {
error("ERR: Couldn't open config file %s\n", argv[3]);
return 1;
}
//END check if opening the files went well
//BEGIN read the source file
sourceLen=File_length(sourceFile);
if(!allocBuffer(&sourceBuffer, sourceLen)) {
error("ERR: Failed to allocate memory for reading source file\n");
return 1;
}
File_read(sourceFile, 0, sourceBuffer.data, sourceLen);
File_close(sourceFile);
printf("Successfully loaded source file in memory\n");
//END read the source file
//BEGIN read the config file
if(hasConfig) {
configLen=File_length(configFile);
if(!allocBuffer(&configBuffer, configLen)) {
error("ERR: Failed to allocate memory for reading config file\n");
return 1;
}
File_read(configFile, 0, configBuffer.data, configLen);
File_close(configFile);
printf("Successfully loaded config file in memory\n");
}
//END read the config file
//BEGIN allocate the output and info buffer
if(!allocBuffer(&outputBuffer, 256)) {
error("ERR: Failed to allocate memory for output buffer\n");
return 1;
}
outputBuffer.size=0;
outputPos=0;
if(!allocBuffer(&infoBuffer, 256)) {
error("ERR: Failed to allocate memory for info buffer\n");
return 1;
}
infoBuffer.size=0;
//END allocate the output and info buffer
//BEGIN read the config
if(hasConfig) {
if(!readConfig(&configBuffer, &config)) {
error("ERR: Error while reading config file\n");
return 1;
}
freeBuffer(&configBuffer);
printf("Successfully read the config\n");
}
//END read the config
//BEGIN assemble the code
printf("Preparing to assemble the code\n");
//setup the assembler struct
if(hasConfig) assembler.offset=config.codeOffset;
else assembler.offset=0x0000;
assembler.pos=0;
assembler.line=1;
assembler.col=1;
assembler.labelCount=0;
assembler.in=&sourceBuffer;
assembler.out=&outputBuffer;
assembler.stdout=&infoBuffer;
//register opcodes
Opcode_registerOpcodes();
//assemble the code
if(!Assembler_assemble(&assembler)) {
error("ERR: Failed to assemble the code\n");
toStringBuffer(&infoBuffer);
error("%s", (char*) infoBuffer.data);
return 1;
}
//print information
printf("Successfully assembled the code\n");
toStringBuffer(&infoBuffer);
printf("%s", (char*) infoBuffer.data);
freeBuffer(&infoBuffer);
//END assemble the code
//BEGIN compute the header
//we hash the source file and push source version
printf("Computing hash\n");
header.magic=MAGIC;
header.hash=strsuml((char*) sourceBuffer.data, sourceBuffer.size);
header.version=SOURCE_VERSION;
freeBuffer(&sourceBuffer);
if(hasConfig) {
//add the header
printf("Injecting config\n");
header.entryPoint=config.entryPoint;
header.mappings=config.mappingCount;
File_write(outputFile, outputPos, &header, HEADER_LENGTH);
outputPos+=HEADER_LENGTH;
for(int i=0; i<config.mappingCount; i++) {
//read the mapping and add it
printf("Adding mapping %d\n", i);
assembler_mapping_t map=config.mappings[i];
mapping.offset=map.offset;
mapping.length=map.length;
mapping.type=map.type;
mapping.access=map.access;
File_write(outputFile, outputPos, &mapping, MAPPING_LENGTH);
outputPos+=MAPPING_LENGTH;
//write the filename if we have one
if(mapping.type==MAPPING_TYPE_file||mapping.type==MAPPING_TYPE_file_raw) {
//name length
big_endian_int_t bei={.value=map.filenameLen};
File_write(outputFile, outputPos, &bei, sizeof(bei));
outputPos+=sizeof(bei);
//name itself
File_write(outputFile, outputPos, &map.filename, map.filenameLen);
outputPos+=map.filenameLen;
}
}
} else {
//we start at 0 in a regular script, and have 3 mappings
printf("Injecting default config\n");
header.entryPoint=0x0000;
header.mappings=3;
File_write(outputFile, outputPos, &header, HEADER_LENGTH);
outputPos+=HEADER_LENGTH;
//we map the ROM at offset 0x0000
printf("Mapping the ROM at %.4x\n", 0x0000);
mapping.offset=0x0000;
mapping.length=outputBuffer.size;
mapping.type=MAPPING_TYPE_rom;
mapping.access=MAPPING_ACCESS_r|MAPPING_ACCESS_x;
File_write(outputFile, outputPos, &mapping, MAPPING_LENGTH);
outputPos+=MAPPING_LENGTH;
//we map 1kB of RAM at offset 0x10000
printf("Mapping 1kB of RAM at %.4x\n", 0x10000);
mapping.offset=0x10000;
mapping.length=1024;
mapping.type=MAPPING_TYPE_ram;
mapping.access=MAPPING_ACCESS_r|MAPPING_ACCESS_w;
File_write(outputFile, outputPos, &mapping, MAPPING_LENGTH);
outputPos+=MAPPING_LENGTH;
//we map the stack at offset 0x20000
printf("Mapping the stack at %.4x\n", 0x20000);
mapping.offset=0x20000;
mapping.length=-1;
mapping.type=MAPPING_TYPE_stack;
mapping.access=MAPPING_ACCESS_r|MAPPING_ACCESS_w;
File_write(outputFile, outputPos, &mapping, MAPPING_LENGTH);
outputPos+=MAPPING_LENGTH;
}
printf("Written header to disk\n");
//END compute the header
//BEGIN add the code
if(!File_write(outputFile, outputPos, outputBuffer.data, outputBuffer.size)) {
error("ERR: Cannot write to output file\n");
return 1;
}
outputPos+=outputBuffer.size;
if(!File_truncate(outputFile, outputPos)) {
error("ERR: Cannot truncate output file\n");
return 1;
}
freeBuffer(&outputBuffer);
File_close(outputFile);
printf("Successfully assembled the code\n");
//END add the code
return 0;
}