2016-12-28 20:32:00 +00:00
|
|
|
// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code.
|
|
|
|
// Copyright (C) 1998-2016 Marco Baye
|
2012-02-27 21:14:46 +00:00
|
|
|
// Have a look at "acme.c" for further info
|
|
|
|
//
|
|
|
|
// Character encoding stuff
|
2014-12-22 00:47:52 +00:00
|
|
|
#include "encoding.h"
|
2012-02-27 21:14:46 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include "alu.h"
|
|
|
|
#include "acme.h"
|
|
|
|
#include "dynabuf.h"
|
2014-12-03 22:18:06 +00:00
|
|
|
#include "global.h" // FIXME - remove when no longer needed
|
2012-02-27 21:14:46 +00:00
|
|
|
#include "output.h"
|
|
|
|
#include "input.h"
|
|
|
|
#include "tree.h"
|
|
|
|
|
|
|
|
|
2014-12-04 23:58:00 +00:00
|
|
|
// struct definition
|
|
|
|
struct encoder {
|
|
|
|
char (*fn)(char);
|
|
|
|
// maybe add table pointer?
|
|
|
|
};
|
2012-02-27 21:14:46 +00:00
|
|
|
|
|
|
|
|
2014-12-04 23:58:00 +00:00
|
|
|
// variables
|
|
|
|
static char outermost_table[256]; // space for encoding table...
|
2014-12-16 08:21:44 +00:00
|
|
|
const struct encoder *encoder_current; // gets set before each pass
|
|
|
|
char *encoding_loaded_table = outermost_table; // ...loaded from file
|
2012-02-27 21:14:46 +00:00
|
|
|
|
|
|
|
|
2014-12-04 23:58:00 +00:00
|
|
|
// encoder functions:
|
2012-02-27 21:14:46 +00:00
|
|
|
|
|
|
|
|
|
|
|
// convert raw to raw (do not convert at all)
|
2014-12-04 23:58:00 +00:00
|
|
|
static char encoderfn_raw(char byte)
|
2012-02-27 21:14:46 +00:00
|
|
|
{
|
|
|
|
return byte;
|
|
|
|
}
|
|
|
|
// convert raw to petscii
|
2014-12-04 23:58:00 +00:00
|
|
|
static char encoderfn_pet(char byte)
|
2012-02-27 21:14:46 +00:00
|
|
|
{
|
|
|
|
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
|
2014-12-04 23:58:00 +00:00
|
|
|
static char encoderfn_scr(char byte)
|
2012-02-27 21:14:46 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
2014-12-04 23:58:00 +00:00
|
|
|
// convert raw to whatever is defined in table
|
|
|
|
static char encoderfn_file(char byte)
|
2012-02-27 21:14:46 +00:00
|
|
|
{
|
2014-12-16 08:21:44 +00:00
|
|
|
return encoding_loaded_table[(unsigned char) byte];
|
2012-02-27 21:14:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-12-04 23:58:00 +00:00
|
|
|
// predefined encoder structs:
|
2012-02-27 21:14:46 +00:00
|
|
|
|
2014-12-04 23:58:00 +00:00
|
|
|
|
2014-12-16 08:21:44 +00:00
|
|
|
const struct encoder encoder_raw = {
|
2014-12-04 23:58:00 +00:00
|
|
|
encoderfn_raw
|
|
|
|
};
|
2014-12-16 08:21:44 +00:00
|
|
|
const struct encoder encoder_pet = {
|
2014-12-04 23:58:00 +00:00
|
|
|
encoderfn_pet
|
|
|
|
};
|
2014-12-16 08:21:44 +00:00
|
|
|
const struct encoder encoder_scr = {
|
2014-12-04 23:58:00 +00:00
|
|
|
encoderfn_scr
|
|
|
|
};
|
2014-12-16 08:21:44 +00:00
|
|
|
const struct encoder encoder_file = {
|
2014-12-04 23:58:00 +00:00
|
|
|
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
|
|
|
|
|
|
|
|
|
2014-12-16 08:21:44 +00:00
|
|
|
// convert character using current encoding (exported for use by alu.c and pseudoopcodes.c)
|
|
|
|
char encoding_encode_char(char byte)
|
2014-12-04 23:58:00 +00:00
|
|
|
{
|
2014-12-16 08:21:44 +00:00
|
|
|
return encoder_current->fn(byte);
|
2014-12-04 23:58:00 +00:00
|
|
|
}
|
|
|
|
|
2014-12-16 08:21:44 +00:00
|
|
|
// set "raw" as default encoding
|
|
|
|
void encoding_passinit(void)
|
2014-12-04 23:58:00 +00:00
|
|
|
{
|
2014-12-16 08:21:44 +00:00
|
|
|
encoder_current = &encoder_raw;
|
2014-12-04 23:58:00 +00:00
|
|
|
}
|
|
|
|
|
2014-12-16 08:21:44 +00:00
|
|
|
// try to load encoding table from given file
|
2017-12-22 22:55:36 +00:00
|
|
|
void encoding_load_from_file(char target[256], FILE *stream)
|
2014-12-04 23:58:00 +00:00
|
|
|
{
|
2017-12-22 22:55:36 +00:00
|
|
|
if (fread(target, sizeof(char), 256, stream) != 256)
|
|
|
|
Throw_error("Conversion table incomplete.");
|
2014-12-04 23:58:00 +00:00
|
|
|
}
|
|
|
|
|
2014-12-16 08:21:44 +00:00
|
|
|
// lookup encoder held in DynaBuf and return its struct pointer (or NULL on failure)
|
|
|
|
const struct encoder *encoding_find(void)
|
2012-02-27 21:14:46 +00:00
|
|
|
{
|
2014-12-16 08:21:44 +00:00
|
|
|
void *node_body;
|
2012-02-27 21:14:46 +00:00
|
|
|
|
2014-12-16 08:21:44 +00:00
|
|
|
// 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;
|
|
|
|
}
|
2012-02-27 21:14:46 +00:00
|
|
|
|
2014-12-16 08:21:44 +00:00
|
|
|
return node_body;
|
2012-02-27 21:14:46 +00:00
|
|
|
}
|