acme/src/encoding.c
marcobaye 294fe25c36 ACME Release 0.96: Added experimental support for instruction sets of Rockwell 65C02, WDC 65C02(S), CSG 65CE02 and CSG 4502.
Stack indexing can now be given either as ",s" or as ",sp" (only relevant for 65816 and 65CE02).


git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@78 4df02467-bbd4-4a76-a152-e7ce94205b78
2016-12-28 20:32:00 +00:00

141 lines
3.3 KiB
C

// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code.
// Copyright (C) 1998-2016 Marco Baye
// Have a look at "acme.c" for further info
//
// Character encoding stuff
#include "encoding.h"
#include <stdio.h>
#include <string.h>
#include "alu.h"
#include "acme.h"
#include "dynabuf.h"
#include "global.h" // FIXME - remove when no longer needed
#include "output.h"
#include "input.h"
#include "tree.h"
// struct definition
struct encoder {
char (*fn)(char);
// maybe add table pointer?
};
// variables
static char outermost_table[256]; // space for encoding table...
const struct encoder *encoder_current; // gets set before each pass
char *encoding_loaded_table = outermost_table; // ...loaded from file
// encoder functions:
// convert raw to raw (do not convert at all)
static char encoderfn_raw(char byte)
{
return byte;
}
// convert raw to petscii
static char encoderfn_pet(char byte)
{
if ((byte >= 'A') && (byte <= 'Z'))
return (char) (byte | 0x80); // FIXME - check why SAS-C
if ((byte >= 'a') && (byte <= 'z')) // wants these casts.
return (char) (byte - 32); // There are more below.
return byte;
}
// convert raw to C64 screencode
static char encoderfn_scr(char byte)
{
if ((byte >= 'a') && (byte <= 'z'))
return (char) (byte - 96); // shift uppercase down
if ((byte >= '[') && (byte <= '_'))
return (char) (byte - 64); // shift [\]^_ down
if (byte == '`')
return 64; // shift ` down
if (byte == '@')
return 0; // shift @ down
return byte;
}
// convert raw to whatever is defined in table
static char encoderfn_file(char byte)
{
return encoding_loaded_table[(unsigned char) byte];
}
// predefined encoder structs:
const struct encoder encoder_raw = {
encoderfn_raw
};
const struct encoder encoder_pet = {
encoderfn_pet
};
const struct encoder encoder_scr = {
encoderfn_scr
};
const struct encoder encoder_file = {
encoderfn_file
};
// keywords for "!convtab" pseudo opcode
static struct ronode *encoder_tree = NULL; // tree to hold encoders
static struct ronode encoder_list[] = {
//no! PREDEFNODE("file", &encoder_file), "!ct file" is not needed; just use {} after initial loading of table!
PREDEFNODE(s_pet, &encoder_pet),
PREDEFNODE(s_raw, &encoder_raw),
PREDEFLAST(s_scr, &encoder_scr),
// ^^^^ this marks the last element
};
// exported functions
// convert character using current encoding (exported for use by alu.c and pseudoopcodes.c)
char encoding_encode_char(char byte)
{
return encoder_current->fn(byte);
}
// set "raw" as default encoding
void encoding_passinit(void)
{
encoder_current = &encoder_raw;
}
// try to load encoding table from given file
void encoding_load(char target[256], const char *filename)
{
FILE *fd = fopen(filename, FILE_READBINARY);
if (fd) {
if (fread(target, sizeof(char), 256, fd) != 256)
Throw_error("Conversion table incomplete.");
fclose(fd);
} else {
Throw_error(exception_cannot_open_input_file);
}
}
// lookup encoder held in DynaBuf and return its struct pointer (or NULL on failure)
const struct encoder *encoding_find(void)
{
void *node_body;
// make sure tree is initialised
if (encoder_tree == NULL)
Tree_add_table(&encoder_tree, encoder_list);
// perform lookup
if (!Tree_easy_scan(encoder_tree, &node_body, GlobalDynaBuf)) {
Throw_error("Unknown encoding.");
return NULL;
}
return node_body;
}