mirror of
https://github.com/uffejakobsen/acme.git
synced 2024-12-23 10:29:46 +00:00
Release 0.97: Now with string symbols, lists, backslash escaping,
"unpseudopc" operator, MEGA65 support, !while, else if, and a CLI switch to mimic older versions. Make sure to read "docs/Changes.txt" and "docs/Upgrade.txt"! git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@266 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
parent
ca6b6d8771
commit
d2683cc64d
45
ACME_Lib/6502/split.a
Normal file
45
ACME_Lib/6502/split.a
Normal file
@ -0,0 +1,45 @@
|
||||
;ACME 0.96.5
|
||||
!set split_cache = [] ; start every pass with an empty cache
|
||||
!ifdef lib_6502_split_a !eof
|
||||
lib_6502_split_a = 1
|
||||
|
||||
!macro split_lo @args {
|
||||
+split_putbytes 0, @args
|
||||
!set split_cache = split_cache + @args
|
||||
}
|
||||
!macro split_hi @args {
|
||||
+split_putbytes 8, @args
|
||||
!set split_cache = split_cache + @args
|
||||
}
|
||||
!macro split_lo {
|
||||
+split_putbytes 0, split_cache
|
||||
!set split_cache = []
|
||||
}
|
||||
!macro split_hi {
|
||||
+split_putbytes 8, split_cache
|
||||
!set split_cache = []
|
||||
}
|
||||
!macro split_putbytes @shift, @bytes {
|
||||
!if len(@bytes) {
|
||||
!for @idx, 0, len(@bytes) - 1 {
|
||||
!by (@bytes[@idx] >> @shift) & $ff
|
||||
}
|
||||
}
|
||||
}
|
||||
!eof
|
||||
; these macros can be used to split address tables in two separate
|
||||
; parts for high- and low-bytes. example:
|
||||
|
||||
table_hi
|
||||
+split_hi [$0123, $4567, $89ab, $cdef] ; writes $01, $45, $89, $cd
|
||||
+split_hi [$1122, $3344, $5566, $7788] ; writes $11, $33, $55, $77
|
||||
table_lo
|
||||
+split_lo ; writes $23, $67, $ab, $ef, $22, $44, $66, $88 from cache
|
||||
|
||||
; of course you can also put the low bytes first:
|
||||
|
||||
table_lo
|
||||
+split_lo [$0123, $4567, $89ab, $cdef] ; writes $23, $67, $ab, $ef
|
||||
+split_lo [$1122, $3344, $5566, $7788] ; writes $22, $44, $66, $88
|
||||
table_hi
|
||||
+split_hi ; writes $01, $45, $89, $cd, $11, $33, $55, $77 from cache
|
@ -30,12 +30,13 @@ According to WDC's official syntax for 65816 assembly language, the
|
||||
argument order of the MVN and MVP instructions differs between
|
||||
assembly language and machine code.
|
||||
To copy bytes from bank $ab to bank $cd, use the following statement:
|
||||
mvn $ab, $cd ; source bank $ab, destination bank $cd
|
||||
mvn $ab, $cd ; source bank $ab, destination bank $cd
|
||||
or
|
||||
mvn #$ab, #$cd ; source bank $ab, destination bank $cd
|
||||
ACME will then produce the following machine code:
|
||||
$54 $cd $ab ; opcode mvn, destination bank $cd, source bank $ab
|
||||
$54 $cd $ab ; opcode mvn, destination bank $cd, source bank $ab
|
||||
|
||||
ACME 0.05 and earlier did it the wrong way. Several other assemblers
|
||||
still do. Make sure your sources are correct.
|
||||
ACME 0.05 and earlier did it the wrong way.
|
||||
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
@ -12,6 +12,70 @@ platform used. There should be another help file in this archive
|
||||
outlining the platform specific changes.
|
||||
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Section: New in release 0.97
|
||||
----------------------------------------------------------------------
|
||||
|
||||
FINALLY strings can be assigned to symbols!
|
||||
"anything in double quotes" is a string, while characters in
|
||||
single quotes are, just as before, immediately converted to their
|
||||
character code. Go and read "docs/Upgrade.txt" to learn about
|
||||
compatibility issues.
|
||||
Added backslash escaping in all string literals:
|
||||
\0 is a null byte, \t is a TAB, \n is a line feed, \r is a
|
||||
carriage return, \" is a double quote, \' is a single quote and
|
||||
\\ is a backslash. Go and read "docs/Upgrade.txt" to learn about
|
||||
compatibility issues.
|
||||
Added "--dialect" CLI switch:
|
||||
Because string symbols and backslash escaping introduce a few
|
||||
incompatibilities to older versions, ACME can now be told to mimic
|
||||
the behavior of older versions. So it's still possible to assemble
|
||||
older sources.
|
||||
Added lists:
|
||||
Lists can be used to pass an arbitrary number of arguments to
|
||||
macros, or to store any number of items (including other lists) in
|
||||
a single symbol. Example: my_list = [1, 2, label, "string", 9]
|
||||
Added "len()" operator:
|
||||
This returns the number of elements in a string or list.
|
||||
Added "[]" operator (for indexing):
|
||||
This returns a single element from a string or list. Negative
|
||||
indices are supported as well, they access the string/list from
|
||||
the other end. Examples: a = my_list[2] b = my_string[-1]
|
||||
Added "&" operator:
|
||||
This operator converts labels or the program counter from its
|
||||
value inside a "!pseudopc" block to the value outside of that
|
||||
block. Thanks to markusC64 for the suggestion!
|
||||
Added "!while {}" pseudo opcode.
|
||||
Added "else if", "else ifdef" and "else ifndef" possibilities.
|
||||
Added "M65" cpu:
|
||||
This instruction set includes the MEGA65 extensions, namely 32-bit
|
||||
pointers and 32-bit data operations using prefix bytes.
|
||||
Added "NMOS6502" as an alias for "6510" cpu.
|
||||
Improved NMOS6502/6510 mode:
|
||||
DOP and TOP can now also be written as NOP.
|
||||
Improved 65816 mode:
|
||||
MVN and MVP can now also be written with '#' before arguments.
|
||||
Added "--test" CLI switch:
|
||||
This is for people who want to help test experimental features.
|
||||
Improved error messages:
|
||||
"Garbage data at end of statement" now includes the unexpected
|
||||
character.
|
||||
"Symbol not defined" is only output once per symbol.
|
||||
Added warning:
|
||||
ACME complains about binary literals with an "unusual" number of
|
||||
digits. Thanks to groepaz for the suggestion!
|
||||
The warning can be disabled using the "-Wno-bin-len" CLI switch.
|
||||
Added warning:
|
||||
All mnemonics without indirect addressing now complain about
|
||||
unneeded parentheses.
|
||||
Fix: Characters are now unsigned (had been architecture-dependent).
|
||||
Improved error handling of "--cpu" and "--format" switches.
|
||||
Added opcode table for NMOS6502 cpu to docs.
|
||||
Added some test sources.
|
||||
Fixed some minor bugs no-one ever seems to have encountered.
|
||||
Rewritten "docs/Upgrade.txt".
|
||||
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Section: New in release 0.96.5
|
||||
----------------------------------------------------------------------
|
||||
|
@ -106,7 +106,7 @@ Then there are local symbols (their names starting with a '.'
|
||||
character). These can only be accessed from inside the macro or zone
|
||||
they were defined in (for more about macros and zones, see the file
|
||||
"AllPOs.txt").
|
||||
There are also "cheap locals": their names start with a '@' character.
|
||||
There are also "cheap locals": their names start with an '@'.
|
||||
The area where these can be accessed is limited automatically by the
|
||||
previous and the following global label (cheap locals are "cheap"
|
||||
because you don't have to put in any extra work to limit their range).
|
||||
@ -323,56 +323,116 @@ given on the command line.
|
||||
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Section: The maths parser
|
||||
Section: The expression parser
|
||||
----------------------------------------------------------------------
|
||||
|
||||
ACME has a relatively powerful maths parser. This parser is used
|
||||
whenever ACME expects to read a numerical value. Supported operations
|
||||
include addition, subtraction, multiplication, divisions, comparisons,
|
||||
shifts, negation, boolean operations and some assembler-specific stuff
|
||||
like extracting the "low byte", the "high byte" or the "bank byte"
|
||||
of a value.
|
||||
Calculations are done using either signed 32-bit integer arithmetic or
|
||||
floating point arithmetic using the C "double" data type. Symbol
|
||||
values are stored the same way.
|
||||
whenever ACME expects to read a value. Supported operations include
|
||||
addition, subtraction, multiplication, divisions, comparisons, shifts,
|
||||
negation, boolean operations and some assembler-specific stuff like
|
||||
extracting the "low byte", the "high byte" or the "bank byte" of a
|
||||
value.
|
||||
Calculations are done using either signed (at least 32-bit) integer
|
||||
arithmetic or floating point arithmetic using the C "double" data
|
||||
type. Symbol values are stored the same way.
|
||||
|
||||
|
||||
This is a list of the value formats currently known by ACME:
|
||||
|
||||
Examples Notes
|
||||
---------------------------------------------------------------------
|
||||
128 a decimal value, integer
|
||||
128.5 a decimal value, floating point
|
||||
$d011 hexadecimal values are indicated by either a
|
||||
0xffd2 leading "$" or a leading "0x".
|
||||
&1701 an octal value, indicated by "&"
|
||||
%1010 binary values are indicated by either a leading "%"
|
||||
%....#... or a leading "0b". In binary values, you can
|
||||
0b01100110 substitute the characters "0" and "1" by "." and
|
||||
"#" respectively. This way the values are much
|
||||
more readable, especially when building bitmapped
|
||||
objects (like C64 sprites or fonts) in your source
|
||||
code.
|
||||
'p' single characters in single quotes are converted to
|
||||
their character code. The actual numeric value
|
||||
depends on the current conversion table chosen
|
||||
using the "!ct" pseudo opcode.
|
||||
"player 2" double quotes indicate text strings. See below for
|
||||
more information on single vs. double quotes.
|
||||
[2, 3, 5, 7] brackets indicate lists. These are useful to group
|
||||
[0, [x, y], 9] data, for example when passing an arbitrary number
|
||||
of arguments to a macro.
|
||||
poll_joy2 a global symbol
|
||||
.fail a local symbol, indicated by leading "."
|
||||
@loop a "cheap local", indicated by leading "@"
|
||||
* the current program counter. During offset assembly,
|
||||
"*" gives the value of the "Pseudo PC". Just to
|
||||
make sure: The value of the program counter is
|
||||
always the value that was valid at the start of
|
||||
the current statement, so
|
||||
!word *, *, *, *
|
||||
will give the same value four times. I think most
|
||||
assemblers do it this way.
|
||||
|
||||
In older versions of ACME , 'x' and "x" were the same thing, namely
|
||||
the character code of the letter x using the currently selected
|
||||
encoding table.
|
||||
Since release 0.97, anything in single quotes gives the character code
|
||||
(as before), while anything in double quotes is treated as a string
|
||||
object. To be compatible to those older versions, ACME keeps accepting
|
||||
one-char strings in a lot of places where actually single characters
|
||||
are expected.
|
||||
|
||||
|
||||
This is a list of the operators currently known by ACME:
|
||||
|
||||
Priority Example Meaning Alias
|
||||
------------------------------------------------------------
|
||||
14 sin(v) Trigonometric sine function
|
||||
14 cos(v) Trigonometric cosine function
|
||||
14 tan(v) Trigonometric tangent function
|
||||
14 arcsin(v) Inverse of sin()
|
||||
14 arccos(v) Inverse of cos()
|
||||
14 arctan(v) Inverse of tan()
|
||||
14 address(v) Mark as address addr(v)
|
||||
14 int(v) Convert to integer
|
||||
14 float(v) Convert to float
|
||||
13 ! v Complement of NOT
|
||||
12 v ^ w To the power of
|
||||
11 - v Negate
|
||||
10 v * w Multiply
|
||||
10 v / w Divide
|
||||
10 v DIV w Integer-Divide
|
||||
10 v % w Remainder of DIV MOD
|
||||
9 v + w Add
|
||||
9 v - w Subtract
|
||||
8 v << w Shift left ASL, LSL
|
||||
8 v >> w Arithmetic shift right ASR
|
||||
8 v >>> w Logical shift right LSR
|
||||
7 < v Lowbyte of
|
||||
7 > v Highbyte of
|
||||
7 ^ v Bankbyte of
|
||||
6 v <= w Lower or equal
|
||||
6 v < w Lower than
|
||||
6 v >= w Higher or equal
|
||||
6 v > w Higher than
|
||||
5 v != w Not equal <>, ><
|
||||
4 v = w Equal
|
||||
3 v & w Bit-wise AND AND
|
||||
2 Bit-wise exclusive OR XOR
|
||||
1 v | w Bit-wise OR OR
|
||||
Priority Example Meaning Alias Note
|
||||
----------------------------------------------------------------------
|
||||
16 is_number(v) these three functions return 1 *3
|
||||
16 is_list(v) if v is the correct symbol *3
|
||||
16 is_string(v) type and 0 otherwise *3
|
||||
16 len(v) length of list or string *2
|
||||
16 sin(v) trigonometric sine function
|
||||
16 cos(v) trigonometric cosine function
|
||||
16 tan(v) trigonometric tangent function
|
||||
16 arcsin(v) inverse of sin()
|
||||
16 arccos(v) inverse of cos()
|
||||
16 arctan(v) inverse of tan()
|
||||
16 address(v) mark as address addr(v)
|
||||
16 int(v) convert to integer
|
||||
16 float(v) convert to float
|
||||
15 &symbol "unpseudopc" symbol (see docs on "!pseudopc")
|
||||
14 v[w] access v with index w *2
|
||||
13 ! v bit-wise complement NOT
|
||||
12 v ^ w to the power of
|
||||
11 - v negate
|
||||
10 v * w multiply
|
||||
10 v / w divide
|
||||
10 v DIV w integer divide
|
||||
10 v % w remainder of DIV MOD
|
||||
9 v + w add *3
|
||||
9 v - w subtract
|
||||
8 v << w shift left ASL, LSL
|
||||
8 v >> w arithmetic shift right ASR
|
||||
8 v >>> w logical shift right LSR
|
||||
7 < v low byte of
|
||||
7 > v high byte of
|
||||
7 ^ v bank byte of
|
||||
6 v <= w lower or equal
|
||||
6 v < w lower than
|
||||
6 v >= w higher or equal
|
||||
6 v > w higher than
|
||||
5 v != w not equal <>, >< *3
|
||||
4 v = w equal *3
|
||||
3 v & w bit-wise AND AND
|
||||
2 bit-wise exclusive OR XOR
|
||||
1 v | w bit-wise OR OR
|
||||
|
||||
Notes:
|
||||
"*2" means this operator only works on lists and strings.
|
||||
"*3" means this operator works on all three data types (numbers, lists
|
||||
and strings).
|
||||
All other operators only work on numbers.
|
||||
|
||||
Operations with higher priority are done first. Of course you can
|
||||
change this using parentheses.
|
||||
@ -392,42 +452,8 @@ Calculating 0^0 (zero to the power of zero) will give 1. If
|
||||
you don't know why I'm telling you this, ask a mathematician. :)
|
||||
|
||||
|
||||
This is a list of the value formats currently known by ACME:
|
||||
|
||||
Examples Notes
|
||||
---------------------------------------------------------------------
|
||||
128 a decimal value, integer
|
||||
128.5 a decimal value, floating point
|
||||
$d011 hexadecimal values are indicated by either a
|
||||
0xffd2 leading "$" or a leading "0x".
|
||||
&1701 an octal value, indicated by "&"
|
||||
%1010 binary values are indicated by either a leading "%"
|
||||
%....#... or a leading "0b". In binary values, you can
|
||||
0b01100110 substitute the characters "0" and "1" by "." and
|
||||
"#" respectively. This way the values are much
|
||||
more readable, especially when building bitmapped
|
||||
objects (like C64 sprites or fonts) in your source
|
||||
code.
|
||||
'p' character values are indicated by single or double
|
||||
"q" quotes. The actual numeric value depends on the
|
||||
current conversion table (none/petscii/screen),
|
||||
chosen using the "!ct" pseudo opcode.
|
||||
poll_joy2 a global symbol
|
||||
.fail a local symbol, indicated by leading "."
|
||||
@loop a "cheap local", indicated by leading "@"
|
||||
* the current program counter. During offset assembly,
|
||||
"*" gives the value of the "Pseudo PC". Just to
|
||||
make sure: The value of the program counter is
|
||||
always the value that was valid at the start of
|
||||
the current statement, so
|
||||
!word *, *, *, *
|
||||
will give the same value four times. I think most
|
||||
assemblers do it this way.
|
||||
|
||||
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Section: Almost, but not quite, entirely useless syntax
|
||||
Section: Almost, but not quite, complete syntax
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Every ACME source code file consists of a non-negative number of
|
||||
@ -457,9 +483,9 @@ Two other possibilities for label names are "all-characters-are-minus"
|
||||
(then it is an anonymous forward label).
|
||||
|
||||
Every command is one of the following:
|
||||
An assembler opcode
|
||||
An assembler mnemonic with an optional argument
|
||||
A pseudo opcode, beginning with a "!" character
|
||||
A symbol definition (symbol=value)
|
||||
An explicit symbol definition (SYMBOL = VALUE)
|
||||
A pc definition, beginning with a "*" character
|
||||
A macro call, beginning with a "+" character
|
||||
...and the syntax of those things varies. :)
|
||||
|
@ -11,6 +11,68 @@ If you haven't used ACME before, you don't need to read this text.
|
||||
|
||||
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Upgrading from earlier releases to ACME release 0.97
|
||||
----------------------------------------------------------------------
|
||||
|
||||
a) Single quotes vs. double quotes:
|
||||
Since "anything in double quotes" is now considered to be a string,
|
||||
problems can arise when trying to do a calculation with a character
|
||||
code. Here are some examples:
|
||||
lda #' ' ; loads 32 like before (ASCII code of space)
|
||||
lda #' ' + 1 ; loads 33 like before (32 plus one)
|
||||
lda #" " ; loads 32 like before (ASCII code of space)
|
||||
lda #" " + 1 ; used to load 33, now fails with error!
|
||||
The third example still works, because 1-char-strings are treated
|
||||
just like single characters when returned by the expression parser as
|
||||
an argument for a mnemonic.
|
||||
However, the fourth example now fails because the expression parser
|
||||
tries to add a string to an integer, which is an undefined operation.
|
||||
Some examples for a related problem:
|
||||
a = ' ' ; a is 32 (ASCII code of space)
|
||||
b = ' ' + 1 ; b is 33 (32 plus one)
|
||||
c = "!" ; c used to be 33, now it's a 1-char string
|
||||
d = "!" + "!" ; d used to be 66, now it's a 2-char string
|
||||
If you do not get any errors when compiling your old sources, you do
|
||||
not need to worry about this problem.
|
||||
If you _do_ get errors, just use single quotes instead of double
|
||||
quotes. If you had to use double quotes because the quoted character
|
||||
itself is a single quote, write '\'' instead (backslash escaping, see
|
||||
below).
|
||||
|
||||
b) Backslash escaping:
|
||||
Backslashes in single or double quotes are now used as escape
|
||||
characters. You need to replace any backslash in older sources with a
|
||||
sequence of two backslashes, so "some\string" becomes "some\\string",
|
||||
and a single character '\' becomes '\\'.
|
||||
If you have used backslashes as directory separators in path names (in
|
||||
Windows/DOS environments), these also need changing - but instead of
|
||||
using a double backslash, just use a single forward slash ('/')
|
||||
instead. This has the added benefit of making the sources platform-
|
||||
independent (*and* it's compatible to older ACME releases as well).
|
||||
|
||||
c) Character values are now unsigned:
|
||||
When parsing a character in single quotes, ACME returns its character
|
||||
code, according to the chosen encoding (raw/petscii/screencode). If
|
||||
this resulted in a byte with its most significant bit set, the actual
|
||||
number was architecture-dependent. Here's an example:
|
||||
!ct pet ; choose PetSCII encoding
|
||||
x = 'A' ; PetSCII 'A' is 0xc1, so MSB is set
|
||||
Now x was either -63 or +193, depending on the host cpu architecture.
|
||||
Since release 0.97, this example will give 193 on all architectures.
|
||||
In most cases, this is not a problem, because the actual bit pattern
|
||||
of the lower eight bits is the same. But if you have written any code
|
||||
where the numerical value of a PetSCII character is used for
|
||||
computations _in_the_source_code_, please check those computations.
|
||||
|
||||
Use the "--dialect 0.94.12" CLI switch to get the old behavior
|
||||
concerning a) double quotes and b) backslashes. There is no way to get
|
||||
the old behavior concerning c) character values, because, as explained
|
||||
above, the old behavior was architecture-dependent, which is a bad
|
||||
idea(tm).
|
||||
|
||||
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Upgrading from earlier releases to ACME release 0.95.2
|
||||
----------------------------------------------------------------------
|
||||
@ -18,7 +80,7 @@ Upgrading from earlier releases to ACME release 0.95.2
|
||||
In 6510 mode, ACME now outputs 0x0b instead of 0x2b when assembling
|
||||
the undocumented ("illegal") ANC #imm8 instruction. Both opcodes do
|
||||
the same thing, this was only changed because all other mnemonics use
|
||||
the smallest possible opcode as well.
|
||||
the lowest-numbered possible opcode as well.
|
||||
Forcing the old behavior via the "--dialect" switch is not supported.
|
||||
|
||||
|
||||
|
@ -141,7 +141,7 @@ static void show_help_and_exit(void)
|
||||
" -I PATH/TO/DIR add search path for input files\n"
|
||||
// TODO: replace these:
|
||||
" -W" OPTIONWNO_LABEL_INDENT " suppress warnings about indented labels\n"
|
||||
" -W" OPTIONWNO_OLD_FOR " suppress warnings about old \"!for\" syntax\n"
|
||||
" -W" OPTIONWNO_OLD_FOR " (old, use \"--dialect 0.94.8\" instead)\n"
|
||||
" -W" OPTIONWNO_BIN_LEN " suppress warnings about lengths of binary literals\n"
|
||||
" -W" OPTIONWTYPE_MISMATCH " enable type checking (warn about type mismatch)\n"
|
||||
// with this line and add a separate function:
|
||||
@ -470,8 +470,8 @@ struct dialect dialects[] = {
|
||||
{VER_DISABLED_OBSOLETE_STUFF, "0.94.8", "\"*=\" works inside \"!pseudopc\", disabled \"!cbm/!realpc/!subzone\""},
|
||||
{VER_NEWFORSYNTAX, "0.94.12", "new \"!for\" syntax"},
|
||||
// {VER_, "0.95.2", "changed ANC#8 from 0x2b to 0x0b"},
|
||||
{VER_BACKSLASHESCAPING, "0.97", "backslash escaping and strings"},
|
||||
// {VER_CURRENT, "default", "default"},
|
||||
// {VER_BACKSLASHESCAPING, "0.97", "backslash escaping and strings"},
|
||||
{VER_FUTURE, "future", "enable all experimental features"},
|
||||
{0, NULL, NULL} // NULLs terminate
|
||||
};
|
||||
|
@ -453,7 +453,7 @@ static void parse_quoted(char closing_quote)
|
||||
if (GlobalDynaBuf->size != 1)
|
||||
Throw_error("There's more than one character.");
|
||||
// parse character
|
||||
value = (intval_t) (unsigned char) encoding_encode_char(GLOBALDYNABUF_CURRENT[0]);
|
||||
value = encoding_encode_char(GLOBALDYNABUF_CURRENT[0]);
|
||||
PUSH_INT_ARG(value, 0, 0); // no flags, no addr refs
|
||||
}
|
||||
// Now GotByte = char following closing quote (or CHAR_EOS on error)
|
||||
@ -490,7 +490,7 @@ static void parse_binary_literal(void) // Now GotByte = "%" or "b"
|
||||
}
|
||||
if (!digits)
|
||||
Throw_warning("Binary literal without any digits."); // FIXME - make into error!
|
||||
if ((digits & config.warn_bin_mask) && (config.wanted_version >= VER_BACKSLASHESCAPING))
|
||||
if (digits & config.warn_bin_mask)
|
||||
Throw_first_pass_warning("Binary literal with strange number of digits.");
|
||||
// set force bits
|
||||
if (config.honor_leading_zeroes) {
|
||||
@ -1293,7 +1293,7 @@ static void string_to_byte(struct object *self, int index)
|
||||
{
|
||||
intval_t byte;
|
||||
|
||||
byte = (intval_t) (unsigned char) encoding_encode_char(self->u.string->payload[index]);
|
||||
byte = encoding_encode_char(self->u.string->payload[index]);
|
||||
self->u.string->refs--; // FIXME - call a function for this...
|
||||
int_create_byte(self, byte);
|
||||
}
|
||||
|
@ -17,41 +17,41 @@
|
||||
|
||||
// struct definition
|
||||
struct encoder {
|
||||
char (*fn)(char);
|
||||
unsigned char (*fn)(unsigned char);
|
||||
// maybe add table pointer?
|
||||
};
|
||||
|
||||
|
||||
// variables
|
||||
static char outermost_table[256]; // space for encoding table...
|
||||
static unsigned 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
|
||||
unsigned 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)
|
||||
static unsigned char encoderfn_raw(unsigned char byte)
|
||||
{
|
||||
return byte;
|
||||
}
|
||||
// convert raw to petscii
|
||||
static char encoderfn_pet(char byte)
|
||||
static unsigned char encoderfn_pet(unsigned 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.
|
||||
if ((byte >= (unsigned char) 'A') && (byte <= (unsigned char) 'Z'))
|
||||
return byte | 0x80;
|
||||
if ((byte >= (unsigned char) 'a') && (byte <= (unsigned char) 'z'))
|
||||
return byte - 32;
|
||||
return byte;
|
||||
}
|
||||
// convert raw to C64 screencode
|
||||
static char encoderfn_scr(char byte)
|
||||
static unsigned char encoderfn_scr(unsigned 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 >= (unsigned char) 'a') && (byte <= (unsigned char) 'z'))
|
||||
return byte - 96; // shift uppercase down
|
||||
if ((byte >= (unsigned char) '[') && (byte <= (unsigned char) '_'))
|
||||
return byte - 64; // shift [\]^_ down
|
||||
if (byte == '`')
|
||||
return 64; // shift ` down
|
||||
if (byte == '@')
|
||||
@ -59,9 +59,9 @@ static char encoderfn_scr(char byte)
|
||||
return byte;
|
||||
}
|
||||
// convert raw to whatever is defined in table
|
||||
static char encoderfn_file(char byte)
|
||||
static unsigned char encoderfn_file(unsigned char byte)
|
||||
{
|
||||
return encoding_loaded_table[(unsigned char) byte];
|
||||
return encoding_loaded_table[byte];
|
||||
}
|
||||
|
||||
|
||||
@ -97,7 +97,7 @@ static struct ronode encoder_list[] = {
|
||||
|
||||
|
||||
// convert character using current encoding (exported for use by alu.c and pseudoopcodes.c)
|
||||
char encoding_encode_char(char byte)
|
||||
unsigned char encoding_encode_char(unsigned char byte)
|
||||
{
|
||||
return encoder_current->fn(byte);
|
||||
}
|
||||
@ -109,7 +109,7 @@ void encoding_passinit(void)
|
||||
}
|
||||
|
||||
// try to load encoding table from given file
|
||||
void encoding_load_from_file(char target[256], FILE *stream)
|
||||
void encoding_load_from_file(unsigned char target[256], FILE *stream)
|
||||
{
|
||||
if (fread(target, sizeof(char), 256, stream) != 256)
|
||||
Throw_error("Conversion table incomplete.");
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code.
|
||||
// Copyright (C) 1998-2016 Marco Baye
|
||||
// Copyright (C) 1998-2020 Marco Baye
|
||||
// Have a look at "acme.c" for further info
|
||||
//
|
||||
// Character encoding stuff
|
||||
@ -16,17 +16,17 @@ extern const struct encoder encoder_raw;
|
||||
extern const struct encoder encoder_pet;
|
||||
extern const struct encoder encoder_scr;
|
||||
extern const struct encoder encoder_file;
|
||||
extern char *encoding_loaded_table; // ...loaded from file
|
||||
extern unsigned char *encoding_loaded_table; // ...loaded from file
|
||||
|
||||
|
||||
// prototypes
|
||||
|
||||
// convert character using current encoding
|
||||
extern char encoding_encode_char(char byte);
|
||||
extern unsigned char encoding_encode_char(unsigned char byte);
|
||||
// set "raw" as default encoding
|
||||
extern void encoding_passinit(void);
|
||||
// try to load encoding table from given file
|
||||
extern void encoding_load_from_file(char target[256], FILE *stream);
|
||||
extern void encoding_load_from_file(unsigned char target[256], FILE *stream);
|
||||
// lookup encoder held in DynaBuf and return its struct pointer (or NULL on failure)
|
||||
extern const struct encoder *encoding_find(void);
|
||||
|
||||
|
@ -67,8 +67,8 @@ enum version {
|
||||
VER_DISABLED_OBSOLETE_STUFF, // v0.94.8 made *= work inside !pseudopc, disabled !cbm/!realpc/!subzone
|
||||
VER_NEWFORSYNTAX, // v0.94.12 introduced the new "!for" syntax
|
||||
// v0.95.2 changed ANC#8 from 0x2b to 0x0b
|
||||
VER_BACKSLASHESCAPING, // v0.97 introduced backslash escaping (and therefore strings)
|
||||
VER_CURRENT, // "RELEASE"
|
||||
VER_BACKSLASHESCAPING, // v0.97 added backslash escaping (and therefore strings)
|
||||
// possible changes in future versions:
|
||||
// paths should be relative to file, not start dir
|
||||
// ignore leading zeroes?
|
||||
@ -170,9 +170,9 @@ extern void Throw_serious_error(const char *msg);
|
||||
extern void Bug_found(const char *msg, int code);
|
||||
// insert object (in case of list, will iterate/recurse until done)
|
||||
struct iter_context {
|
||||
void (*fn)(intval_t); // output function
|
||||
boolean accept_long_strings; // if FALSE, only 1-char-strings work
|
||||
char stringxor; // for !scrxor, 0 otherwise
|
||||
void (*fn)(intval_t); // output function
|
||||
boolean accept_long_strings; // if FALSE, only 1-char-strings work
|
||||
unsigned char stringxor; // for !scrxor, 0 otherwise
|
||||
};
|
||||
extern void output_object(struct object *object, struct iter_context *iter);
|
||||
// output 8-bit value with range check
|
||||
|
@ -319,7 +319,7 @@ static enum eos po_cbm(void)
|
||||
// read encoding table from file
|
||||
static enum eos user_defined_encoding(FILE *stream)
|
||||
{
|
||||
char local_table[256],
|
||||
unsigned char local_table[256],
|
||||
*buffered_table = encoding_loaded_table;
|
||||
const struct encoder *buffered_encoder = encoder_current;
|
||||
|
||||
@ -345,7 +345,7 @@ static enum eos user_defined_encoding(FILE *stream)
|
||||
// use one of the pre-defined encodings (raw, pet, scr)
|
||||
static enum eos predefined_encoding(void)
|
||||
{
|
||||
char local_table[256],
|
||||
unsigned char local_table[256],
|
||||
*buffered_table = encoding_loaded_table;
|
||||
const struct encoder *buffered_encoder = encoder_current;
|
||||
|
||||
@ -382,7 +382,7 @@ static enum eos po_convtab(void)
|
||||
}
|
||||
}
|
||||
// insert string(s)
|
||||
static enum eos encode_string(const struct encoder *inner_encoder, char xor)
|
||||
static enum eos encode_string(const struct encoder *inner_encoder, unsigned char xor)
|
||||
{
|
||||
const struct encoder *outer_encoder = encoder_current; // buffer encoder
|
||||
struct iter_context iter;
|
||||
|
@ -7,9 +7,9 @@
|
||||
#define version_H
|
||||
|
||||
|
||||
#define RELEASE "0.96.5" // update before release FIXME
|
||||
#define CODENAME "Fenchurch" // update before release
|
||||
#define CHANGE_DATE "26 June" // update before release FIXME
|
||||
#define RELEASE "0.97" // update before release FIXME
|
||||
#define CODENAME "Zem" // update before release
|
||||
#define CHANGE_DATE "28 June" // update before release FIXME
|
||||
#define CHANGE_YEAR "2020" // update before release
|
||||
//#define HOME_PAGE "http://home.pages.de/~mac_bacon/smorbrod/acme/"
|
||||
#define HOME_PAGE "http://sourceforge.net/p/acme-crossass/" // FIXME
|
||||
|
Loading…
Reference in New Issue
Block a user