mirror of
https://github.com/cc65/cc65.git
synced 2024-06-01 13:41:34 +00:00
Merge branch 'master' into fptest
This commit is contained in:
commit
61f2f4fa56
|
@ -181,9 +181,13 @@ The only exception to the above are actions that are exclusive to the github act
|
|||
|
||||
* the printf family of function does not completely implement all printf modifiers and does not behave as expected in some cases - all this should be documented in detail
|
||||
|
||||
## Floating point support
|
||||
## Compiler
|
||||
|
||||
The first step is implementing the datatype "float" as IEEE488 floats. Help welcomed!
|
||||
* We need a way that makes it possible to feed arbitrary assembler code into the optimzer, so we can have proper tests for it
|
||||
|
||||
### Floating point support
|
||||
|
||||
The first step is implementing the datatype "float" as IEEE 754 floats. Help welcomed!
|
||||
|
||||
* WIP compiler/library changes are here: https://github.com/cc65/cc65/pull/1777
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ External contributors:
|
|||
* [karrika](https://github.com/karrika): Atari 7800 target
|
||||
* [Stephan Mühlstrasser](https://github.com/smuehlst): osic1p target
|
||||
* [Wayne Parham](https://github.com/WayneParham): Sym-1 target
|
||||
* [Dave Plummer](https://github.com/davepl): KIM-1 target
|
||||
|
||||
*(The above list is incomplete, if you feel left out - please speak up or add yourself in a PR)*
|
||||
|
||||
|
|
27
asminc/kim1.inc
Normal file
27
asminc/kim1.inc
Normal file
|
@ -0,0 +1,27 @@
|
|||
; ---------------------------------------------------------------------------
|
||||
;
|
||||
; KIM-1 definitions
|
||||
;
|
||||
; ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
RAMSTART := $0200 ; Entry point
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Monitor Functions
|
||||
; ---------------------------------------------------------------------------
|
||||
OUTCHR := $1EA0 ; Output character
|
||||
INTCHR := $1E5A ; Input character without case conversion
|
||||
DUMPT := $1800 ; Dump memory to tape
|
||||
LOADT := $1873 ; Load memory from tape
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; System Memory
|
||||
; ---------------------------------------------------------------------------
|
||||
SAL := $17F5 ; Tape load address low
|
||||
SAH := $17F6 ; Tape load address high
|
||||
EAL := $17F7 ; Tape address end low
|
||||
EAH := $17F8 ; Tape address end high
|
||||
ID := $17F9 ; Tape Identification number
|
41
cfg/kim1-60k.cfg
Normal file
41
cfg/kim1-60k.cfg
Normal file
|
@ -0,0 +1,41 @@
|
|||
# kim1-60k.cfg (4k)
|
||||
#
|
||||
# for expanded KIM-1
|
||||
#
|
||||
# ld65 --config kim1-60k.cfg -o <prog>.bin <prog>.o
|
||||
|
||||
FEATURES {
|
||||
STARTADDRESS: default = $2000;
|
||||
CONDES: segment = STARTUP,
|
||||
type = constructor,
|
||||
label = __CONSTRUCTOR_TABLE__,
|
||||
count = __CONSTRUCTOR_COUNT__;
|
||||
CONDES: segment = STARTUP,
|
||||
type = destructor,
|
||||
label = __DESTRUCTOR_TABLE__,
|
||||
count = __DESTRUCTOR_COUNT__;
|
||||
}
|
||||
|
||||
SYMBOLS {
|
||||
__STACKSIZE__: type = weak, value = $0080; # 128 byte program stack
|
||||
__STARTADDRESS__: type = export, value = %S;
|
||||
}
|
||||
|
||||
MEMORY {
|
||||
ZP: file = %O, define = yes, start = $0000, size = $00EE;
|
||||
CPUSTACK: file = "", define = yes, start = $0100, size = $0100;
|
||||
RAM: file = %O, define = yes, start = %S, size = $E000 - %S - __STACKSIZE__;
|
||||
MAINROM: file = "", define = yes, start = $E000, size = $1000;
|
||||
TOP: file = "", define = yes, start = $F000, size = $1000;
|
||||
}
|
||||
|
||||
SEGMENTS {
|
||||
ZEROPAGE: load = ZP, type = zp, define = yes;
|
||||
STARTUP: load = RAM, type = ro, define = yes;
|
||||
CODE: load = RAM, type = ro, define = yes;
|
||||
RODATA: load = RAM, type = ro, define = yes;
|
||||
ONCE: load = RAM, type = ro, define = yes;
|
||||
DATA: load = RAM, type = rw, define = yes;
|
||||
BSS: load = RAM, type = bss, define = yes;
|
||||
}
|
||||
|
41
cfg/kim1.cfg
Normal file
41
cfg/kim1.cfg
Normal file
|
@ -0,0 +1,41 @@
|
|||
# kim1.cfg (4k)
|
||||
#
|
||||
# for unexpanded KIM-1
|
||||
#
|
||||
# ld65 --config kim1.cfg -o <prog>.bin <prog>.o
|
||||
|
||||
FEATURES {
|
||||
STARTADDRESS: default = $0200;
|
||||
CONDES: segment = STARTUP,
|
||||
type = constructor,
|
||||
label = __CONSTRUCTOR_TABLE__,
|
||||
count = __CONSTRUCTOR_COUNT__;
|
||||
CONDES: segment = STARTUP,
|
||||
type = destructor,
|
||||
label = __DESTRUCTOR_TABLE__,
|
||||
count = __DESTRUCTOR_COUNT__;
|
||||
}
|
||||
|
||||
SYMBOLS {
|
||||
__STACKSIZE__: type = weak, value = $0080; # 128 byte program stack
|
||||
__STARTADDRESS__: type = export, value = %S;
|
||||
}
|
||||
|
||||
MEMORY {
|
||||
ZP: file = %O, define = yes, start = $0000, size = $00EE;
|
||||
CPUSTACK: file = "", define = yes, start = $0100, size = $0100;
|
||||
RAM: file = %O, define = yes, start = %S, size = $1000 - %S - __STACKSIZE__;
|
||||
MAINROM: file = "", define = yes, start = $E000, size = $1000;
|
||||
TOP: file = "", define = yes, start = $F000, size = $1000;
|
||||
}
|
||||
|
||||
SEGMENTS {
|
||||
ZEROPAGE: load = ZP, type = zp, define = yes;
|
||||
STARTUP: load = RAM, type = ro, define = yes;
|
||||
CODE: load = RAM, type = ro, define = yes;
|
||||
RODATA: load = RAM, type = ro, define = yes;
|
||||
ONCE: load = RAM, type = ro, define = yes;
|
||||
DATA: load = RAM, type = rw, define = yes;
|
||||
BSS: load = RAM, type = bss, define = yes;
|
||||
}
|
||||
|
|
@ -332,6 +332,7 @@ See the <url url="funcref.html" name="function reference"> for declaration and u
|
|||
<item>_scroll
|
||||
<item>_setcolor
|
||||
<item>_setcolor_low
|
||||
<item>_sound
|
||||
<item>waitvsync
|
||||
</itemize>
|
||||
|
||||
|
|
|
@ -115,14 +115,14 @@ Here is a description of all the command line options:
|
|||
<item>6502dtv
|
||||
<item>65sc02
|
||||
<item>65c02
|
||||
<item>65816
|
||||
<item>huc6280
|
||||
<item>4510
|
||||
</itemize>
|
||||
|
||||
6502x is for the NMOS 6502 with unofficial opcodes. 6502dtv is for the
|
||||
emulated CPU of the C64DTV device. huc6280 is the CPU of the PC engine.
|
||||
4510 is the CPU of the Commodore C65. Support for the 65816 currently
|
||||
is not available.
|
||||
4510 is the CPU of the Commodore C65. 65816 is the CPU of the SNES.
|
||||
|
||||
|
||||
<label id="option--formfeeds">
|
||||
|
@ -263,8 +263,9 @@ can produce output that can not be re-assembled, when one or more of those
|
|||
branches point outside of the disassembled memory. This can happen when text
|
||||
or binary data is processed.
|
||||
|
||||
While there is some code for the 65816 in the sources, it is currently
|
||||
unsupported.
|
||||
The 65816 support requires annotating ranges with the M and X flag states.
|
||||
This can be recorded with an emulator that supports Code and Data Logging,
|
||||
for example. Disassemble one bank at a time.
|
||||
|
||||
|
||||
<sect1>Attribute map<p>
|
||||
|
@ -521,6 +522,16 @@ following attributes are recognized:
|
|||
|
||||
</descrip>
|
||||
|
||||
<tag><tt>UNIT</tt></tag>
|
||||
Split the table into sections of this size. For example, if you have a
|
||||
ByteTable of size 48, but it has logical groups of size 16, specifying
|
||||
16 for UNIT adds newlines after every 16 bytes. UNIT is always in bytes.
|
||||
|
||||
<tag><tt>ADDRMODE</tt></tag>
|
||||
When disassembling 65816 code, this specifies the M and X flag states
|
||||
for this range. It's a string argument of the form "mx", capital letters
|
||||
mean the flag is enabled.
|
||||
|
||||
</descrip>
|
||||
|
||||
|
||||
|
@ -693,6 +704,20 @@ directives explained above:
|
|||
|
||||
|
||||
|
||||
<sect>Helper scripts<p>
|
||||
|
||||
<tt>util/parse-bsnes-log.awk</tt> is a supplied script for 65816 disassembly,
|
||||
to parse bsnes-plus Code-Data log files and output the RANGE sections
|
||||
for your info file. For typical usage, you'd check the S-CPU log and trace
|
||||
log mask boxes in the bsnes-plus debugger, play through the game, then grep
|
||||
for the bank you're disassembling, and pass that to this script.
|
||||
|
||||
<tscreen><verb>
|
||||
grep ^83 my-game-log | parse-bsnes-log.awk
|
||||
</verb></tscreen>
|
||||
|
||||
|
||||
|
||||
<sect>Copyright<p>
|
||||
|
||||
da65 (and all cc65 binutils) is (C) Copyright 1998-2011, Ullrich von
|
||||
|
|
|
@ -126,6 +126,7 @@ function.
|
|||
<!-- <item><ref id="_scroll" name="_scroll"> -->
|
||||
<!-- <item><ref id="_setcolor" name="_setcolor"> -->
|
||||
<!-- <item><ref id="_setcolor_low" name="_setcolor_low"> -->
|
||||
<item><ref id="_sound" name="_sound">
|
||||
<item><ref id="get_ostype" name="get_ostype">
|
||||
<!-- <item><ref id="get_tv" name="get_tv"> -->
|
||||
</itemize>
|
||||
|
@ -1108,6 +1109,46 @@ considered random to a certain degree.
|
|||
</descrip>
|
||||
</quote>
|
||||
|
||||
<sect1>_sound<label id="_sound"><p>
|
||||
<quote>
|
||||
<descrip>
|
||||
<tag/Function/Use the speaker to produce sound in a specified voice. (Atari only)
|
||||
<tag/Header/<tt/<ref id="atari.h" name="atari.h">/
|
||||
<tag/Declaration/<tt/void __fastcall__ _sound (unsigned char voice, unsigned char pitch, unsigned char distortion, unsigned char volume);/
|
||||
<tag/Description/The function produces a sound with the specified parameters using any of the 4 available oscillators (voices) controlled by the POKEY chip. Sound is non cpu-blocking and it keeps oscillating until program sends 0 in all the other parameters.
|
||||
|
||||
<tag/Notes/<itemize>
|
||||
<item>The function is available only as a fastcall function; so, it may be used
|
||||
only in the presence of a prototype.
|
||||
<item>The function is specific to the Atari 8 bit.
|
||||
<item> Voice can be any of 0-3 different sound channels.
|
||||
<item> Pitch goes from 0-255 (about 125 Hz to 32 Khz).
|
||||
<item> Distortion (0-14) uses poly dividers to reshape wave in order to create a noise effect. Use 10 for a "pure" square-wave sound.
|
||||
<item>Volume (0-15) is the intensity for the wave.
|
||||
<item>Extra bits in those parameters will be ignored.
|
||||
<item>Parameters are the same as for the AtariBASIC SOUND statement.
|
||||
</itemize>
|
||||
<tag/Availability/cc65 (<tt/atari/ and <tt/atarixl/ platforms)
|
||||
<tag/Example/
|
||||
<verb>
|
||||
|
||||
#include <stdio.h>
|
||||
int main(void)
|
||||
{
|
||||
int i=0;
|
||||
unsigned char j;
|
||||
printf("playing sound \n");
|
||||
for (j=0; j<144; j++) {
|
||||
_sound(1,144-j,10,8); //change the pitch for voice 1
|
||||
for (i=0; i<50; i++); //pause for sound duration
|
||||
}
|
||||
_sound(1,0,0,0); //use zero in other parameters to stop the sound
|
||||
return 0;
|
||||
}
|
||||
|
||||
</verb>
|
||||
</descrip>
|
||||
</quote>
|
||||
|
||||
<sect1>_stroserror<label id="_stroserror"><p>
|
||||
|
||||
|
@ -4148,7 +4189,7 @@ be used in presence of a prototype.
|
|||
<tag/Example/<verb>
|
||||
chdir (getdevicedir (device, buf, sizeof buf));
|
||||
</verb>
|
||||
cf. <tt/samples/enumdevdir.c/
|
||||
cf. <tt/samples/enumdevdir.c/
|
||||
</descrip>
|
||||
</quote>
|
||||
|
||||
|
@ -6908,7 +6949,6 @@ switching the CPU into single clock mode.
|
|||
</descrip>
|
||||
</quote>
|
||||
|
||||
|
||||
<sect1>srand<label id="srand"><p>
|
||||
|
||||
<quote>
|
||||
|
|
|
@ -154,6 +154,9 @@
|
|||
<tag><htmlurl url="gamate.html" name="gamate.html"></tag>
|
||||
Topics specific to the Bit Corporation Gamate Console.
|
||||
|
||||
<tag><htmlurl url="kim1.html" name="kim1.html"></tag>
|
||||
Topics specific to the MOS Technology KIM-1.
|
||||
|
||||
<tag><htmlurl url="lynx.html" name="lynx.html"></tag>
|
||||
Topics specific to the Atari Lynx Game Console.
|
||||
|
||||
|
|
148
doc/kim1.sgml
Normal file
148
doc/kim1.sgml
Normal file
|
@ -0,0 +1,148 @@
|
|||
<!doctype linuxdoc system>
|
||||
|
||||
<article>
|
||||
<title>MOS Technology KIM-1 specific information for cc65
|
||||
<author><url url="mailto:davepl@davepl.com" name="Dave Plummer">
|
||||
|
||||
<abstract>
|
||||
An overview of the KIM-1 runtime system as it is implemented for the cc65 C compiler.
|
||||
</abstract>
|
||||
|
||||
<!-- Table of contents -->
|
||||
<toc>
|
||||
|
||||
<!-- Begin the document -->
|
||||
|
||||
<sect>Overview<p>
|
||||
|
||||
This file contains an overview of the KIM-1 runtime system as it comes with the cc65 C compiler.
|
||||
It describes the memory layout, KIM-1 specific header files, available drivers, and any pitfalls
|
||||
specific to the platform.
|
||||
|
||||
Please note that KIM-1 specific functions are just mentioned here, they are described in detail
|
||||
in the separate <url url="funcref.html" name="function reference">. Even functions marked as
|
||||
"platform dependent" may be available on more than one platform. Please see the
|
||||
function reference for more information.
|
||||
|
||||
<sect>Binary format<p>
|
||||
|
||||
The output format generated by the linker for the KIM-1 target is a raw binary BIN file, which
|
||||
is essentially a memory image. You can convert this to a papertape format file using
|
||||
Convert8bithexformat or KIMPaper, which are open-source conversion utility programs.
|
||||
A papertape format files can be transferred to the KIM-1 using the RS-232 terminal port (TTY),
|
||||
just as if the machine-code was entered by hand. Enter 'L' in the TTY and start the paper tape file
|
||||
transfer.
|
||||
|
||||
<p>
|
||||
|
||||
Included with this distribution is a 4k configuration file and a 60k config file. The KIM-1
|
||||
on-board memory is limited to 4 kbytes but system memory can be increased to 60 kbytes of
|
||||
contiguous RAM with aftermarket add-on boards. So choose the config file that matches your
|
||||
system configuration before compiling and linking user programs.
|
||||
|
||||
<sect>Memory layout<p>
|
||||
|
||||
The ROMs and I/O areas are defined in the configuration files, as are most of the entry points
|
||||
for useful subroutines in the KIM-1 monitor ROM. cc65 generated programs compiled and linked
|
||||
using 4k config run in the memory range of $200 - $0FFF. The 60k config expands
|
||||
this range to $DFFF. The starting memory location and entry point for running the program is
|
||||
$200, so when the program is transferred to the KIM-1, it is executed by typing '200 G'.
|
||||
|
||||
Special locations:
|
||||
|
||||
<descrip>
|
||||
<tag/Text screen/
|
||||
Conio support is not currently available for the KIM-1. But stdio console functions are available.
|
||||
|
||||
<tag/Stack/
|
||||
The C runtime stack is located at $0FFF on 4kb KIM-1s, or at $DFFF for 60kb systems.
|
||||
The stack always grows downwards.
|
||||
|
||||
<tag/Heap/
|
||||
The C heap is located at the end of the program and grows towards the C runtime stack.
|
||||
|
||||
</descrip><p>
|
||||
|
||||
<sect>Platform specific header files<p>
|
||||
|
||||
Programs containing KIM-1 code may use the <tt/kim.h/ header file. See the header file for more information.
|
||||
|
||||
<sect>Loadable drivers<p>
|
||||
|
||||
<sect1>Graphics drivers<p>
|
||||
|
||||
No graphics drivers are currently available for the KIM-1.
|
||||
|
||||
<sect1>Joystick drivers<p>
|
||||
|
||||
No joystick driver is currently available for the KIM-1.
|
||||
|
||||
<sect1>Mouse drivers<p>
|
||||
|
||||
No mouse drivers are currently available for the KIM-1.
|
||||
|
||||
<sect1>RS232 device drivers<p>
|
||||
|
||||
No communication port drivers are currently available for the KIM-1. It has only the "master console"
|
||||
e.g. stdin and stdout.
|
||||
|
||||
<sect>Limitations<p>
|
||||
|
||||
<sect1>Disk I/O<p>
|
||||
|
||||
The existing library for the KIM-1 doesn't implement C file I/O.
|
||||
|
||||
To be more specific, this limitation means that you cannot use any of the following functions (and a few others):
|
||||
|
||||
<itemize>
|
||||
<item>fopen
|
||||
<item>fclose
|
||||
<item>fread
|
||||
<item>fwrite
|
||||
<item>...
|
||||
</itemize>
|
||||
|
||||
<sect>Other hints<p>
|
||||
|
||||
<sect1>kim1.h<p>
|
||||
This header exposes KIM-1 specific I/O functions that are useful for reading and writing its ports and front panel.
|
||||
See the <tt/kim1.h/ include file for a list of the functions available.
|
||||
|
||||
<sect1>Limited memory applications<p>
|
||||
|
||||
As stated earlier, there are config files for 4kb and 60kb systems. If you have 60kb RAM, then you will probably
|
||||
want to use the kim1-60k configuration, but if not - if you are using the kim1-4k configuration - then you may
|
||||
want to use functions like getchar, putchar, gets and puts rather than functions like scanf and printf.
|
||||
Printf, for example, requires about 1KB because it needs to know how to process all the format specifiers.
|
||||
|
||||
<sect1>Sample programs<p>
|
||||
|
||||
These sample programs can be found in the samples/kim1 directory:
|
||||
|
||||
<itemize>
|
||||
<item>kimHello prints "Hello World!" and then inputs characters, which are echoed on the screen.
|
||||
This program will run on both 4kb and 60kb systems.</item>
|
||||
<item>kimSieve finds the prime numbers up to 100,000 using the Sieve of Eratosthenes algorithm, and prints how many
|
||||
prime numbers were found. This program requires a 60kb system to run.</item>
|
||||
</itemize>
|
||||
|
||||
<sect>License<p>
|
||||
|
||||
This software is provided 'as-is', without any expressed or implied warranty. In no event will the authors be held
|
||||
liable for any damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter
|
||||
it and redistribute it freely, subject to the following restrictions:
|
||||
|
||||
<enum>
|
||||
<item> The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
<item> Altered source versions must be plainly marked as such, and must not
|
||||
be misrepresented as being the original software.
|
||||
<item> This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
</enum>
|
||||
|
||||
</article>
|
|
@ -44,6 +44,7 @@ Short options:
|
|||
-lc List all possible conversions
|
||||
-r file[,attrlist] Read an input file
|
||||
-v Increase verbosity
|
||||
-p tgt,file[,attrlist] Write the palette to a file
|
||||
-w file[,attrlist] Write the output to a file
|
||||
|
||||
Long options:
|
||||
|
@ -56,6 +57,7 @@ Long options:
|
|||
--slice x,y,w,h Generate a slice from the loaded bitmap
|
||||
--verbose Increase verbosity
|
||||
--version Print the version number and exit
|
||||
--palette tgt,file{,attrlist] Write the palette to a file
|
||||
--write file[,attrlist] Write the output to a file
|
||||
---------------------------------------------------------------------------
|
||||
</verb></tscreen>
|
||||
|
@ -124,6 +126,13 @@ attribute lists see <ref id="attr-lists" name="below">.
|
|||
bugfixes, please include the version number.
|
||||
|
||||
|
||||
<label id="option--palette">
|
||||
<tag><tt>-p, --palette target,filename[,attrlist]</tt></tag>
|
||||
|
||||
Write the palette of the input bitmap to a file in a format suitable of
|
||||
the target.
|
||||
|
||||
|
||||
<label id="option--write">
|
||||
<tag><tt>-w, --write filename[,attrlist]</tt></tag>
|
||||
|
||||
|
@ -265,6 +274,7 @@ of a sprite is roughly 508 pixels but in reality the Lynx screen is only 160 by
|
|||
102 pixels which makes very large sprites useless.
|
||||
|
||||
The number per pixels is taken from the number of colors of the input bitmap.
|
||||
You can also force the number of pens used in the conversion.
|
||||
|
||||
There are a few attributes that you can give to the conversion software.
|
||||
|
||||
|
@ -273,7 +283,7 @@ There are a few attributes that you can give to the conversion software.
|
|||
<tag/mode/
|
||||
The first is what kind of encoding to use for the sprite. The attribute for
|
||||
this is called "mode" and the possible values are "literal", "packed" or
|
||||
"transparent". The default is "packed" if no mode is specified.
|
||||
"shaped". The default is "packed" if no mode is specified.
|
||||
|
||||
The "literal" is a totally literal mode with no packing. In this mode the
|
||||
number of pixels per scanline will be a multiple of 8 both right and left from
|
||||
|
@ -290,10 +300,26 @@ There are a few attributes that you can give to the conversion software.
|
|||
using run-length encoding and literal coding mixed for optimisation to
|
||||
produce a small sprite.
|
||||
|
||||
The last encoding mode "transparent" is like packed. But here we know that
|
||||
the index 0 will be transparent so we can clip off all 0 pixels from the left
|
||||
and right edge of the sprite. This will produce the smallest sprite possible
|
||||
on the Lynx. The sprite is not rectangular anymore.
|
||||
The last encoding mode "shaped" is like packed. But we can stop the conversion
|
||||
to the right abd left edge when we get the first "edge" colour. If no edge
|
||||
colour is specified we stop at the first index 0 colour.
|
||||
If your edge index is outside the range 0..15 then your sprite can use all
|
||||
the colours in the defined palette.
|
||||
This will also produce the smallest sprite possible on the Lynx. The sprite
|
||||
is not rectangular anymore.
|
||||
|
||||
<tag/edge/
|
||||
This keyword is only meaningful for shaped sprites. By default it is 0.
|
||||
The shaped sprite outer edge is defined by the colour index "edge".
|
||||
|
||||
<tag/pen/
|
||||
This keyword defines the order the colours in the original bitmap is
|
||||
mapped to the Lynx sprite. The length of the pen also defines the depth
|
||||
of the generated sprite.
|
||||
If you want to create a 1 BPP sprite you can define the two indices used
|
||||
in the sprite like pen=34. Now areas in colour index 3 will be mapped as 0.
|
||||
Areas in colour index 4 will be mapped as 1.
|
||||
The default pen=0123456789abcdef.
|
||||
|
||||
<tag/ax/
|
||||
The sprite is painted around the Anchor point. The anchor point x can be
|
||||
|
@ -301,7 +327,9 @@ There are a few attributes that you can give to the conversion software.
|
|||
painting the sprite in location 10,20 will set the left edge of the sprite
|
||||
10 pixels from the left of the Lynx screen. When the sprite is scaled by
|
||||
hardware the anchor point stays in place and the sprite grows or shrinks
|
||||
around the anchor point. The default value is 0 (left).
|
||||
around the anchor point. You can also define the location using the words
|
||||
"mid" for the center or "max" for the right edge.
|
||||
The default value is 0 (left).
|
||||
|
||||
<tag/ay/
|
||||
The sprite is painted around the Anchor point. The anchor point y can be
|
||||
|
@ -309,7 +337,8 @@ There are a few attributes that you can give to the conversion software.
|
|||
painting the sprite in location 10,20 will set the top of the sprite 20
|
||||
pixels from the top of the Lynx screen. When the sprite is scaled by
|
||||
hardware the anchor point stays in place and the sprite grows or shrinks
|
||||
around the anchor point. The default value is 0 (top).
|
||||
around the anchor point. You can also define the location using the words
|
||||
"mid" for the center or "max" for the bottom. The default value is 0 (top).
|
||||
|
||||
</descrip>
|
||||
|
||||
|
|
|
@ -171,7 +171,7 @@ extern struct {
|
|||
extern void a2_auxmem_emd[];
|
||||
extern void a2_stdjoy_joy[]; /* Referred to by joy_static_stddrv[] */
|
||||
extern void a2_stdmou_mou[]; /* Referred to by mouse_static_stddrv[] */
|
||||
extern void a2_ssc_ser[];
|
||||
extern void a2_ssc_ser[]; /* Referred to by ser_static_stddrv[] */
|
||||
extern void a2_hi_tgi[]; /* Referred to by tgi_static_stddrv[] */
|
||||
extern void a2_lo_tgi[];
|
||||
#endif
|
||||
|
|
|
@ -99,7 +99,7 @@
|
|||
extern void a2e_auxmem_emd[];
|
||||
extern void a2e_stdjoy_joy[]; /* Referred to by joy_static_stddrv[] */
|
||||
extern void a2e_stdmou_mou[]; /* Referred to by mouse_static_stddrv[] */
|
||||
extern void a2e_ssc_ser[];
|
||||
extern void a2e_ssc_ser[]; /* Referred to by ser_static_stddrv[] */
|
||||
extern void a2e_hi_tgi[]; /* Referred to by tgi_static_stddrv[] */
|
||||
extern void a2e_lo_tgi[];
|
||||
|
||||
|
|
|
@ -235,6 +235,12 @@ extern void __fastcall__ _scroll (signed char numlines);
|
|||
/* numlines < 0 scrolls down */
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Sound function */
|
||||
/*****************************************************************************/
|
||||
|
||||
extern void __fastcall__ _sound (unsigned char voice, unsigned char frequency, unsigned char distortion, unsigned char volume);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Misc. functions */
|
||||
/*****************************************************************************/
|
||||
|
@ -261,7 +267,7 @@ extern void atrst_mou[]; /* referred to by mouse_static_stddrv[]
|
|||
extern void atrami_mou[];
|
||||
extern void atrtrk_mou[];
|
||||
extern void atrtt_mou[];
|
||||
extern void atrrdev_ser[];
|
||||
extern void atrrdev_ser[]; /* referred to by ser_static_stddrv[] */
|
||||
extern void atr3_tgi[];
|
||||
extern void atr4_tgi[];
|
||||
extern void atr5_tgi[];
|
||||
|
@ -286,7 +292,7 @@ extern void atrxst_mou[]; /* referred to by mouse_static_stddrv[]
|
|||
extern void atrxami_mou[];
|
||||
extern void atrxtrk_mou[];
|
||||
extern void atrxtt_mou[];
|
||||
extern void atrxrdev_ser[];
|
||||
extern void atrxrdev_ser[]; /* referred to by ser_static_stddrv[] */
|
||||
extern void atrx3_tgi[];
|
||||
extern void atrx4_tgi[];
|
||||
extern void atrx5_tgi[];
|
||||
|
|
|
@ -133,7 +133,7 @@
|
|||
/* The addresses of the static drivers */
|
||||
extern void atmos_pase_joy[]; /* Referred to by joy_static_stddrv[] */
|
||||
extern void atmos_ijk_joy[];
|
||||
extern void atmos_acia_ser[];
|
||||
extern void atmos_acia_ser[]; /* Referred to by ser_static_stddrv[] */
|
||||
extern void atmos_228_200_3_tgi[];
|
||||
extern void atmos_240_200_2_tgi[]; /* Referred to by tgi_static_stddrv[] */
|
||||
|
||||
|
|
|
@ -140,7 +140,7 @@ extern void c128_1351_mou[]; /* Referred to by mouse_static_stddrv[] */
|
|||
extern void c128_joy_mou[];
|
||||
extern void c128_inkwell_mou[];
|
||||
extern void c128_pot_mou[];
|
||||
extern void c128_swlink_ser[];
|
||||
extern void c128_swlink_ser[]; /* Referred to by ser_static_stddrv[] */
|
||||
extern void c128_hi_tgi[];
|
||||
extern void c128_vdc_tgi[]; /* Referred to by tgi_static_stddrv[] */
|
||||
extern void c128_vdc2_tgi[];
|
||||
|
|
|
@ -155,7 +155,7 @@ extern void c64_1351_mou[]; /* Referred to by mouse_static_stddrv[]
|
|||
extern void c64_joy_mou[];
|
||||
extern void c64_inkwell_mou[];
|
||||
extern void c64_pot_mou[];
|
||||
extern void c64_swlink_ser[];
|
||||
extern void c64_swlink_ser[]; /* Referred to by ser_static_stddrv[] */
|
||||
extern void c64_hi_tgi[]; /* Referred to by tgi_static_stddrv[] */
|
||||
|
||||
|
||||
|
|
|
@ -128,7 +128,7 @@ extern void cbm510_inkwl_mou[];
|
|||
extern void cbm510_joy_mou[]; /* Referred to by mouse_static_stddrv[] */
|
||||
extern void cbm510_ram_emd[];
|
||||
extern void cbm510_std_joy[]; /* Referred to by joy_static_stddrv[] */
|
||||
extern void cbm510_std_ser[];
|
||||
extern void cbm510_std_ser[]; /* Referred to by ser_static_stddrv[] */
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@
|
|||
|
||||
/* The addresses of the static drivers */
|
||||
extern void cbm610_ram_emd[];
|
||||
extern void cbm610_std_ser[];
|
||||
extern void cbm610_std_ser[]; /* Referred to by ser_static_stddrv[] */
|
||||
|
||||
|
||||
|
||||
|
|
60
include/kim1.h
Normal file
60
include/kim1.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*****************************************************************************/
|
||||
/* */
|
||||
/* kim1.h */
|
||||
/* */
|
||||
/* KIM-1 system-specific definitions */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2022 Dave Plummer */
|
||||
/* Email: davepl@davepl.com */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef _KIM1_H
|
||||
#define _KIM1_H
|
||||
|
||||
/* Check for errors */
|
||||
#if !defined(__KIM1__)
|
||||
# error This module may only be used when compiling for the KIM-1!
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Hardware */
|
||||
/*****************************************************************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Read from tape */
|
||||
int __fastcall__ loadt (unsigned char);
|
||||
|
||||
/* Write to tape */
|
||||
int __fastcall__ dumpt (unsigned char, const void*, const void*);
|
||||
|
||||
/* End of sym1.h */
|
||||
#endif
|
|
@ -115,7 +115,7 @@
|
|||
|
||||
/* The addresses of the static drivers */
|
||||
extern void lynx_stdjoy_joy[]; /* Referred to by joy_static_stddrv[] */
|
||||
extern void lynx_comlynx_ser[];
|
||||
extern void lynx_comlynx_ser[]; /* Referred to by ser_static_stddrv[] */
|
||||
extern void lynx_160_102_16_tgi[]; /* Referred to by tgi_static_stddrv[] */
|
||||
|
||||
|
||||
|
|
|
@ -36,6 +36,24 @@
|
|||
# error "This module may only be used when compiling for the Challenger 1P!"
|
||||
#endif
|
||||
|
||||
/* Colors are not functional, display is black and white only. */
|
||||
#define COLOR_BLACK 0x00
|
||||
#define COLOR_WHITE 0x01
|
||||
|
||||
#define CH_ULCORNER 0xCC
|
||||
#define CH_URCORNER 0xCD
|
||||
#define CH_LLCORNER 0xCB
|
||||
#define CH_LRCORNER 0xCE
|
||||
#define CH_TTEE 0xD9
|
||||
#define CH_BTEE 0xD7
|
||||
#define CH_LTEE 0xD8
|
||||
#define CH_RTEE 0xDA
|
||||
#define CH_CROSS 0xDB
|
||||
#define CH_HLINE 0x94
|
||||
#define CH_VLINE 0x95
|
||||
|
||||
#define CH_ENTER 0x0D
|
||||
|
||||
/* The following #defines will cause the matching functions calls in conio.h
|
||||
** to be overlaid by macros with the same names, saving the function call
|
||||
** overhead.
|
||||
|
@ -43,5 +61,6 @@
|
|||
#define _textcolor(color) COLOR_WHITE
|
||||
#define _bgcolor(color) COLOR_BLACK
|
||||
#define _bordercolor(color) COLOR_BLACK
|
||||
#define _cpeekcolor(color) COLOR_WHITE
|
||||
|
||||
#endif
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
|
||||
/* The addresses of the static drivers */
|
||||
extern void plus4_stdjoy_joy[]; /* Referred to by joy_static_stddrv[] */
|
||||
extern void plus4_stdser_ser[];
|
||||
extern void plus4_stdser_ser[]; /* Referred to by ser_static_stddrv[] */
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -123,6 +123,13 @@ struct ser_params {
|
|||
unsigned char handshake; /* Type of handshake to use */
|
||||
};
|
||||
|
||||
/* The name of the standard serial driver for a platform */
|
||||
extern const char ser_stddrv[];
|
||||
|
||||
/* The address of the static standard serial driver for a platform */
|
||||
extern const void ser_static_stddrv[];
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
|
|
|
@ -27,6 +27,7 @@ TARGETS = apple2 \
|
|||
$(CBMS) \
|
||||
$(GEOS) \
|
||||
gamate \
|
||||
kim1 \
|
||||
lynx \
|
||||
nes \
|
||||
none \
|
||||
|
|
|
@ -199,7 +199,7 @@ SER_OPEN:
|
|||
asl
|
||||
asl
|
||||
asl
|
||||
adc Offset ; Assume carry to be clear
|
||||
adc #Offset ; Assume carry to be clear
|
||||
tax
|
||||
|
||||
; Check if the handshake setting is valid
|
||||
|
|
22
libsrc/apple2/ser_stat_stddrv.s
Normal file
22
libsrc/apple2/ser_stat_stddrv.s
Normal file
|
@ -0,0 +1,22 @@
|
|||
;
|
||||
; Address of the static standard serial driver
|
||||
;
|
||||
; Oliver Schmidt, 2022-12-22
|
||||
;
|
||||
; const void ser_static_stddrv[];
|
||||
;
|
||||
|
||||
.export _ser_static_stddrv
|
||||
.ifdef __APPLE2ENH__
|
||||
.import _a2e_ssc_ser
|
||||
.else
|
||||
.import _a2_ssc_ser
|
||||
.endif
|
||||
|
||||
.rodata
|
||||
|
||||
.ifdef __APPLE2ENH__
|
||||
_ser_static_stddrv := _a2e_ssc_ser
|
||||
.else
|
||||
_ser_static_stddrv := _a2_ssc_ser
|
||||
.endif
|
18
libsrc/apple2/ser_stddrv.s
Normal file
18
libsrc/apple2/ser_stddrv.s
Normal file
|
@ -0,0 +1,18 @@
|
|||
;
|
||||
; Name of the standard serial driver
|
||||
;
|
||||
; Oliver Schmidt, 2022-12-22
|
||||
;
|
||||
; const char ser_stddrv[];
|
||||
;
|
||||
|
||||
.export _ser_stddrv
|
||||
|
||||
.rodata
|
||||
|
||||
_ser_stddrv:
|
||||
.ifdef __APPLE2ENH__
|
||||
.asciiz "A2E.SSC.SER"
|
||||
.else
|
||||
.asciiz "A2.SSC.SER"
|
||||
.endif
|
22
libsrc/atari/ser_stat_stddrv.s
Normal file
22
libsrc/atari/ser_stat_stddrv.s
Normal file
|
@ -0,0 +1,22 @@
|
|||
;
|
||||
; Address of the static standard serial driver
|
||||
;
|
||||
; Oliver Schmidt, 2022-12-22
|
||||
;
|
||||
; const void ser_static_stddrv[];
|
||||
;
|
||||
|
||||
.export _ser_static_stddrv
|
||||
.ifdef __ATARIXL__
|
||||
.import _atrxrdev_ser
|
||||
.else
|
||||
.import _atrrdev_ser
|
||||
.endif
|
||||
|
||||
.rodata
|
||||
|
||||
.ifdef __ATARIXL__
|
||||
_ser_static_stddrv := _atrxrdev_ser
|
||||
.else
|
||||
_ser_static_stddrv := _atrrdev_ser
|
||||
.endif
|
18
libsrc/atari/ser_stddrv.s
Normal file
18
libsrc/atari/ser_stddrv.s
Normal file
|
@ -0,0 +1,18 @@
|
|||
;
|
||||
; Name of the standard serial driver
|
||||
;
|
||||
; Oliver Schmidt, 2022-12-22
|
||||
;
|
||||
; const char ser_stddrv[];
|
||||
;
|
||||
|
||||
.export _ser_stddrv
|
||||
|
||||
.rodata
|
||||
|
||||
_ser_stddrv:
|
||||
.ifdef __ATARIXL__
|
||||
.asciiz "atrxrdev.ser"
|
||||
.else
|
||||
.asciiz "atrrdev.ser"
|
||||
.endif
|
39
libsrc/atari/sound.s
Normal file
39
libsrc/atari/sound.s
Normal file
|
@ -0,0 +1,39 @@
|
|||
;
|
||||
; Mariano Domínguez
|
||||
; 2022-12-4
|
||||
;
|
||||
; this file provides an equivalent to the BASIC SOUND function
|
||||
;
|
||||
; void __fastcall__ _sound (unsigned char voice, unsigned char frequency, unsigned char distortion, unsigned char volume);
|
||||
;
|
||||
.include "atari.inc"
|
||||
.export __sound
|
||||
.import popa
|
||||
.importzp tmp1,tmp2
|
||||
|
||||
; play sound, arguments: voice, pitch, distortion, volume
|
||||
.proc __sound
|
||||
sta tmp2 ;save volume
|
||||
jsr popa ;get distortion
|
||||
sta tmp1 ;save distortion
|
||||
jsr popa ;get pitch
|
||||
pha ;save in stack
|
||||
jsr popa ;get voice
|
||||
asl a ;adjust voice *2 for offset in x
|
||||
tax
|
||||
pla ;get pitch from stack
|
||||
sta AUDF1,x ;store pitch
|
||||
lda #0
|
||||
sta AUDCTL
|
||||
lda #3
|
||||
sta SKCTL ;init sound
|
||||
lda tmp1 ;get distortion
|
||||
asl a ;ignore the high nibble
|
||||
asl a
|
||||
asl a
|
||||
asl a
|
||||
clc ;setup for adding volume
|
||||
adc tmp2 ;add volume
|
||||
sta AUDC1,x ;volume + distortion in control channel
|
||||
rts
|
||||
.endproc
|
14
libsrc/atmos/ser_stat_stddrv.s
Normal file
14
libsrc/atmos/ser_stat_stddrv.s
Normal file
|
@ -0,0 +1,14 @@
|
|||
;
|
||||
; Address of the static standard serial driver
|
||||
;
|
||||
; Oliver Schmidt, 2022-12-22
|
||||
;
|
||||
; const void ser_static_stddrv[];
|
||||
;
|
||||
|
||||
.export _ser_static_stddrv
|
||||
.import _atmos_acia_ser
|
||||
|
||||
.rodata
|
||||
|
||||
_ser_static_stddrv := _atmos_acia_ser
|
13
libsrc/atmos/ser_stddrv.s
Normal file
13
libsrc/atmos/ser_stddrv.s
Normal file
|
@ -0,0 +1,13 @@
|
|||
;
|
||||
; Name of the standard serial driver
|
||||
;
|
||||
; Oliver Schmidt, 2022-12-22
|
||||
;
|
||||
; const char ser_stddrv[];
|
||||
;
|
||||
|
||||
.export _ser_stddrv
|
||||
|
||||
.rodata
|
||||
|
||||
_ser_stddrv: .asciiz "atmos-acia.ser"
|
14
libsrc/c128/ser_stat_stddrv.s
Normal file
14
libsrc/c128/ser_stat_stddrv.s
Normal file
|
@ -0,0 +1,14 @@
|
|||
;
|
||||
; Address of the static standard serial driver
|
||||
;
|
||||
; Oliver Schmidt, 2022-12-22
|
||||
;
|
||||
; const void ser_static_stddrv[];
|
||||
;
|
||||
|
||||
.export _ser_static_stddrv
|
||||
.import _c128_swlink_ser
|
||||
|
||||
.rodata
|
||||
|
||||
_ser_static_stddrv := _c128_swlink_ser
|
13
libsrc/c128/ser_stddrv.s
Normal file
13
libsrc/c128/ser_stddrv.s
Normal file
|
@ -0,0 +1,13 @@
|
|||
;
|
||||
; Name of the standard serial driver
|
||||
;
|
||||
; Oliver Schmidt, 2022-12-22
|
||||
;
|
||||
; const char ser_stddrv[];
|
||||
;
|
||||
|
||||
.export _ser_stddrv
|
||||
|
||||
.rodata
|
||||
|
||||
_ser_stddrv: .asciiz "c128_swlink.ser"
|
14
libsrc/c64/ser_stat_stddrv.s
Normal file
14
libsrc/c64/ser_stat_stddrv.s
Normal file
|
@ -0,0 +1,14 @@
|
|||
;
|
||||
; Address of the static standard serial driver
|
||||
;
|
||||
; Oliver Schmidt, 2022-12-22
|
||||
;
|
||||
; const void ser_static_stddrv[];
|
||||
;
|
||||
|
||||
.export _ser_static_stddrv
|
||||
.import _c64_swlink_ser
|
||||
|
||||
.rodata
|
||||
|
||||
_ser_static_stddrv := _c64_swlink_ser
|
13
libsrc/c64/ser_stddrv.s
Normal file
13
libsrc/c64/ser_stddrv.s
Normal file
|
@ -0,0 +1,13 @@
|
|||
;
|
||||
; Name of the standard serial driver
|
||||
;
|
||||
; Oliver Schmidt, 2022-12-22
|
||||
;
|
||||
; const char ser_stddrv[];
|
||||
;
|
||||
|
||||
.export _ser_stddrv
|
||||
|
||||
.rodata
|
||||
|
||||
_ser_stddrv: .asciiz "c64_swlink.ser"
|
14
libsrc/cbm510/ser_stat_stddrv.s
Normal file
14
libsrc/cbm510/ser_stat_stddrv.s
Normal file
|
@ -0,0 +1,14 @@
|
|||
;
|
||||
; Address of the static standard serial driver
|
||||
;
|
||||
; Oliver Schmidt, 2022-12-22
|
||||
;
|
||||
; const void ser_static_stddrv[];
|
||||
;
|
||||
|
||||
.export _ser_static_stddrv
|
||||
.import _cbm510_std_ser
|
||||
|
||||
.rodata
|
||||
|
||||
_ser_static_stddrv := _cbm510_std_ser
|
13
libsrc/cbm510/ser_stddrv.s
Normal file
13
libsrc/cbm510/ser_stddrv.s
Normal file
|
@ -0,0 +1,13 @@
|
|||
;
|
||||
; Name of the standard serial driver
|
||||
;
|
||||
; Oliver Schmidt, 2022-12-22
|
||||
;
|
||||
; const char ser_stddrv[];
|
||||
;
|
||||
|
||||
.export _ser_stddrv
|
||||
|
||||
.rodata
|
||||
|
||||
_ser_stddrv: .asciiz "cbm510-std.ser"
|
14
libsrc/cbm610/ser_stat_stddrv.s
Normal file
14
libsrc/cbm610/ser_stat_stddrv.s
Normal file
|
@ -0,0 +1,14 @@
|
|||
;
|
||||
; Address of the static standard serial driver
|
||||
;
|
||||
; Oliver Schmidt, 2022-12-22
|
||||
;
|
||||
; const void ser_static_stddrv[];
|
||||
;
|
||||
|
||||
.export _ser_static_stddrv
|
||||
.import _cbm610_std_ser
|
||||
|
||||
.rodata
|
||||
|
||||
_ser_static_stddrv := _cbm610_std_ser
|
13
libsrc/cbm610/ser_stddrv.s
Normal file
13
libsrc/cbm610/ser_stddrv.s
Normal file
|
@ -0,0 +1,13 @@
|
|||
;
|
||||
; Name of the standard serial driver
|
||||
;
|
||||
; Oliver Schmidt, 2022-12-22
|
||||
;
|
||||
; const char ser_stddrv[];
|
||||
;
|
||||
|
||||
.export _ser_stddrv
|
||||
|
||||
.rodata
|
||||
|
||||
_ser_stddrv: .asciiz "cbm610-std.ser"
|
47
libsrc/kim1/crt0.s
Normal file
47
libsrc/kim1/crt0.s
Normal file
|
@ -0,0 +1,47 @@
|
|||
;
|
||||
; Startup code for cc65 (KIM-1 version)
|
||||
;
|
||||
|
||||
.export _init, _exit
|
||||
.export __STARTUP__ : absolute = 1 ; Mark as startup
|
||||
|
||||
.import _main
|
||||
.import initlib, donelib, copydata, zerobss
|
||||
.import __RAM_START__, __RAM_SIZE__ ; Linker generated
|
||||
.import __STACKSIZE__ ; Linker generated
|
||||
|
||||
.include "zeropage.inc"
|
||||
.include "kim1.inc"
|
||||
|
||||
|
||||
; Place the startup code in a special segment
|
||||
|
||||
.segment "STARTUP"
|
||||
|
||||
|
||||
; A little light housekeeping
|
||||
|
||||
_init: cld ; Clear decimal mode
|
||||
|
||||
; Set cc65 argument stack pointer
|
||||
|
||||
lda #<(__RAM_START__ + __RAM_SIZE__)
|
||||
sta sp
|
||||
lda #>(__RAM_START__ + __RAM_SIZE__)
|
||||
sta sp+1
|
||||
|
||||
; Initialize memory storage
|
||||
|
||||
jsr zerobss ; Clear BSS segment
|
||||
jsr copydata ; Initialize DATA segment
|
||||
jsr initlib ; Run constructors
|
||||
|
||||
; Call main()
|
||||
|
||||
jsr _main
|
||||
|
||||
; Back from main (this is also the _exit entry). There may be a more elegant way to
|
||||
; return to the monitor on the KIM-1, but I don't know it!
|
||||
|
||||
_exit: brk
|
||||
|
5
libsrc/kim1/ctype.s
Normal file
5
libsrc/kim1/ctype.s
Normal file
|
@ -0,0 +1,5 @@
|
|||
; Character specification table.
|
||||
;
|
||||
; uses the "common" definition
|
||||
|
||||
.include "ctype_common.inc"
|
51
libsrc/kim1/read.s
Normal file
51
libsrc/kim1/read.s
Normal file
|
@ -0,0 +1,51 @@
|
|||
;
|
||||
; int __fastcall__ read (int fd, void* buf, unsigned count);
|
||||
;
|
||||
|
||||
.include "kim1.inc"
|
||||
|
||||
.import popax, popptr1
|
||||
.importzp ptr1, ptr2, ptr3
|
||||
|
||||
.export _read
|
||||
|
||||
.proc _read
|
||||
|
||||
sta ptr3
|
||||
stx ptr3+1 ; Count in ptr3
|
||||
inx
|
||||
stx ptr2+1 ; Increment and store in ptr2
|
||||
tax
|
||||
inx
|
||||
stx ptr2
|
||||
jsr popptr1 ; Buffer address in ptr1
|
||||
jsr popax
|
||||
|
||||
begin: dec ptr2
|
||||
bne getch
|
||||
dec ptr2+1
|
||||
beq done ; If buffer full, return
|
||||
|
||||
getch: jsr INTCHR ; Get character using Monitor ROM call
|
||||
;jsr OUTCHR ; Echo it
|
||||
and #$7F ; Clear top bit
|
||||
cmp #$07 ; Check for '\a'
|
||||
bne chkcr ; ...if BEL character
|
||||
;jsr BEEP ; Make beep sound TODO
|
||||
chkcr: cmp #$0D ; Check for '\r'
|
||||
bne putch ; ...if CR character
|
||||
lda #$0A ; Replace with '\n'
|
||||
jsr OUTCHR ; and echo it
|
||||
|
||||
putch: ldy #$00 ; Put char into return buffer
|
||||
sta (ptr1),y
|
||||
inc ptr1 ; Increment pointer
|
||||
bne begin
|
||||
inc ptr1+1
|
||||
bne begin
|
||||
|
||||
done: lda ptr3
|
||||
ldx ptr3+1
|
||||
rts ; Return count
|
||||
|
||||
.endproc
|
39
libsrc/kim1/tapeio.s
Normal file
39
libsrc/kim1/tapeio.s
Normal file
|
@ -0,0 +1,39 @@
|
|||
;
|
||||
; int __fastcall__ loadt (unsigned char id);
|
||||
; int __fastcall__ dumpt (unsigned char id, void* start_addr, void* end_addr);
|
||||
;
|
||||
|
||||
.include "kim1.inc"
|
||||
|
||||
.import popa, popax, return0, return1
|
||||
|
||||
.export _loadt, _dumpt
|
||||
|
||||
.segment "CODE"
|
||||
|
||||
.proc _loadt: near
|
||||
|
||||
sta ID ; Tape record ID to P1L
|
||||
jsr LOADT ; Read data from tape
|
||||
bcs error
|
||||
jmp return0 ; Return 0 if sucessful
|
||||
error: jmp return1 ; or 1 if not
|
||||
|
||||
.endproc
|
||||
|
||||
.proc _dumpt: near
|
||||
|
||||
sta EAL ; End address
|
||||
stx EAH
|
||||
jsr popax
|
||||
sta SAL ; Start address
|
||||
stx SAH
|
||||
jsr popa
|
||||
sta ID ; Tape Record ID
|
||||
ldx #$00
|
||||
jsr DUMPT ; Write data to tape
|
||||
bcs error
|
||||
jmp return0 ; Return 0 if sucessful
|
||||
error: jmp return1 ; or 1 if not
|
||||
|
||||
.endproc
|
49
libsrc/kim1/write.s
Normal file
49
libsrc/kim1/write.s
Normal file
|
@ -0,0 +1,49 @@
|
|||
;
|
||||
; int __fastcall__ write (int fd, const void* buf, int count);
|
||||
;
|
||||
|
||||
.include "kim1.inc"
|
||||
|
||||
.import popax, popptr1
|
||||
.importzp ptr1, ptr2, ptr3
|
||||
|
||||
.export _write
|
||||
|
||||
.proc _write
|
||||
|
||||
sta ptr3
|
||||
stx ptr3+1 ; Count in ptr3
|
||||
inx
|
||||
stx ptr2+1 ; Increment and store in ptr2
|
||||
tax
|
||||
inx
|
||||
stx ptr2
|
||||
jsr popptr1 ; Buffer address in ptr1
|
||||
jsr popax
|
||||
|
||||
begin: dec ptr2
|
||||
bne outch
|
||||
dec ptr2+1
|
||||
beq done
|
||||
|
||||
outch: ldy #0
|
||||
lda (ptr1),y
|
||||
jsr OUTCHR ; Send character using Monitor call
|
||||
cmp #$07 ; Check for '\a'
|
||||
bne chklf ; ...if BEL character
|
||||
;jsr BEEP ; Make beep sound
|
||||
chklf: cmp #$0A ; Check for 'n'
|
||||
bne next ; ...if LF character
|
||||
lda #$0D ; Add a carriage return
|
||||
jsr OUTCHR
|
||||
|
||||
next: inc ptr1
|
||||
bne begin
|
||||
inc ptr1+1
|
||||
jmp begin
|
||||
|
||||
done: lda ptr3
|
||||
ldx ptr3+1
|
||||
rts ; Return count
|
||||
|
||||
.endproc
|
14
libsrc/lynx/ser_stat_stddrv.s
Normal file
14
libsrc/lynx/ser_stat_stddrv.s
Normal file
|
@ -0,0 +1,14 @@
|
|||
;
|
||||
; Address of the static standard serial driver
|
||||
;
|
||||
; Oliver Schmidt, 2022-12-22
|
||||
;
|
||||
; const void ser_static_stddrv[];
|
||||
;
|
||||
|
||||
.export _ser_static_stddrv
|
||||
.import _lynx_comlynx_ser
|
||||
|
||||
.rodata
|
||||
|
||||
_ser_static_stddrv := _lynx_comlynx_ser
|
14
libsrc/plus4/ser_stat_stddrv.s
Normal file
14
libsrc/plus4/ser_stat_stddrv.s
Normal file
|
@ -0,0 +1,14 @@
|
|||
;
|
||||
; Address of the static standard serial driver
|
||||
;
|
||||
; Oliver Schmidt, 2022-12-22
|
||||
;
|
||||
; const void ser_static_stddrv[];
|
||||
;
|
||||
|
||||
.export _ser_static_stddrv
|
||||
.import _plus4_stdser_ser
|
||||
|
||||
.rodata
|
||||
|
||||
_ser_static_stddrv := _plus4_stdser_ser
|
13
libsrc/plus4/ser_stddrv.s
Normal file
13
libsrc/plus4/ser_stddrv.s
Normal file
|
@ -0,0 +1,13 @@
|
|||
;
|
||||
; Name of the standard serial driver
|
||||
;
|
||||
; Oliver Schmidt, 2022-12-22
|
||||
;
|
||||
; const char ser_stddrv[];
|
||||
;
|
||||
|
||||
.export _ser_stddrv
|
||||
|
||||
.rodata
|
||||
|
||||
_ser_stddrv: .asciiz "plus4-stdser.ser"
|
|
@ -154,7 +154,7 @@ endif
|
|||
# Lists of subdirectories
|
||||
|
||||
# disasm depends on cpp
|
||||
DIRLIST = tutorial geos atari2600 atari5200 apple2 gamate lynx supervision sym1 cbm
|
||||
DIRLIST = tutorial geos atari2600 atari5200 apple2 gamate lynx supervision sym1 kim1 cbm
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Lists of executables
|
||||
|
@ -172,6 +172,7 @@ EXELIST_apple2 = \
|
|||
multdemo \
|
||||
ovrldemo \
|
||||
sieve \
|
||||
terminal \
|
||||
tinyshell \
|
||||
tgidemo
|
||||
|
||||
|
@ -188,6 +189,7 @@ EXELIST_atari = \
|
|||
multdemo \
|
||||
ovrldemo \
|
||||
sieve \
|
||||
terminal \
|
||||
tinyshell \
|
||||
tgidemo
|
||||
|
||||
|
@ -206,6 +208,7 @@ EXELIST_atmos = \
|
|||
mandelbrot \
|
||||
mandelfloat \
|
||||
sieve \
|
||||
terminal \
|
||||
tgidemo
|
||||
|
||||
EXELIST_bbc = \
|
||||
|
@ -224,6 +227,7 @@ EXELIST_c64 = \
|
|||
multdemo \
|
||||
ovrldemo \
|
||||
sieve \
|
||||
terminal \
|
||||
tinyshell \
|
||||
tgidemo
|
||||
|
||||
|
@ -237,6 +241,7 @@ EXELIST_c128 = \
|
|||
mandelfloat \
|
||||
mousedemo \
|
||||
sieve \
|
||||
terminal \
|
||||
tinyshell \
|
||||
tgidemo
|
||||
|
||||
|
@ -254,6 +259,7 @@ EXELIST_cbm510 = \
|
|||
hello \
|
||||
mandelfloat \
|
||||
mousedemo \
|
||||
terminal \
|
||||
tinyshell \
|
||||
sieve
|
||||
|
||||
|
@ -263,6 +269,7 @@ EXELIST_cbm610 = \
|
|||
gunzip65 \
|
||||
hello \
|
||||
mandelfloat \
|
||||
terminal \
|
||||
tinyshell \
|
||||
sieve
|
||||
|
||||
|
@ -325,6 +332,7 @@ EXELIST_plus4 = \
|
|||
gunzip65 \
|
||||
hello \
|
||||
mandelfloat \
|
||||
terminal \
|
||||
tinyshell \
|
||||
sieve
|
||||
|
||||
|
@ -340,6 +348,9 @@ EXELIST_supervision = \
|
|||
EXELIST_sym1 = \
|
||||
notavailable
|
||||
|
||||
EXELIST_kim1 = \
|
||||
notavailable
|
||||
|
||||
EXELIST_telestrat = \
|
||||
ascii \
|
||||
checkversion \
|
||||
|
@ -408,6 +419,7 @@ TARGETS := \
|
|||
creativision \
|
||||
cx16 \
|
||||
gamate \
|
||||
kim1 \
|
||||
lunix \
|
||||
lynx \
|
||||
nes \
|
||||
|
|
|
@ -80,6 +80,14 @@ EXELIST_geos-apple = \
|
|||
ifneq ($(EXELIST_$(SYS)),)
|
||||
samples: $(EXELIST_$(SYS))
|
||||
$(foreach dir,$(DIRLIST),$(SUBDIR_recipe))
|
||||
|
||||
define samples-geos
|
||||
c1541 -attach $(0).d64 -geoswrite $(1);
|
||||
endef
|
||||
|
||||
samples-geos: $(EXELIST_$(SYS))
|
||||
c1541 -format "$@,01" d64 $@.d64
|
||||
$(foreach tool,$(EXELIST_$(SYS)),$(call samples-geos,$(tool)))
|
||||
else
|
||||
samples:
|
||||
ifeq ($(MAKELEVEL),0)
|
||||
|
@ -94,37 +102,37 @@ bitmap.c: logo.pcx
|
|||
$(SP) -r logo.pcx -c geos-bitmap -w bitmap.c,ident=bitmap
|
||||
|
||||
bitmap-demo.cvt: bitmap.c bitmap-demores.grc bitmap-demo.c
|
||||
$(CL) -t $(SYS) -O -o bitmap-demo.cvt -m bitmap-demo.map bitmap-demores.grc bitmap-demo.c
|
||||
$(CL) -t $(SYS) -O -o $@ -m bitmap-demo.map bitmap-demores.grc bitmap-demo.c
|
||||
|
||||
filesel.cvt: fileselres.grc filesel.c
|
||||
$(CL) -t $(SYS) -O -o filesel.cvt -m filesel.map fileselres.grc filesel.c
|
||||
$(CL) -t $(SYS) -O -o $@ -m filesel.map fileselres.grc filesel.c
|
||||
|
||||
geosconio.cvt: geosconiores.grc geosconio.c
|
||||
$(CL) -t $(SYS) -O -o geosconio.cvt -m geosconio.map geosconiores.grc geosconio.c
|
||||
$(CL) -t $(SYS) -O -o $@ -m geosconio.map geosconiores.grc geosconio.c
|
||||
|
||||
geosver.cvt: geosverres.grc geosver.c
|
||||
$(CL) -t $(SYS) -O -o geover.cvt -m geosver.map geosverres.grc geosver.c
|
||||
$(CL) -t $(SYS) -O -o $@ -m geosver.map geosverres.grc geosver.c
|
||||
|
||||
getid.cvt: getidres.grc getid.c
|
||||
$(CL) -t $(SYS) -O -o getid.cvt -m getid.map getidres.grc getid.c
|
||||
$(CL) -t $(SYS) -O -o $@ -m getid.map getidres.grc getid.c
|
||||
|
||||
hello1.cvt: hello1res.grc hello1.c
|
||||
$(CL) -t $(SYS) -O -o hello1.cvt -m hello1.map hello1res.grc hello1.c
|
||||
$(CL) -t $(SYS) -O -o $@ -m hello1.map hello1res.grc hello1.c
|
||||
|
||||
hello2.cvt: hello2res.grc hello2.c
|
||||
$(CL) -t $(SYS) -O -o hello2.cvt -m hello2.map hello2res.grc hello2.c
|
||||
$(CL) -t $(SYS) -O -o $@ -m hello2.map hello2res.grc hello2.c
|
||||
|
||||
overlay-demo.cvt: overlay-demores.grc overlay-demo.c
|
||||
$(CL) -t $(SYS) -O -o overlay-demo.cvt -m overlay-demo.map overlay-demores.grc overlay-demo.c
|
||||
$(CL) -t $(SYS) -O -o $@ -m overlay-demo.map overlay-demores.grc overlay-demo.c
|
||||
|
||||
rmvprot.cvt: rmvprotres.grc rmvprot.c
|
||||
$(CL) -t $(SYS) -O -o rmvprot.cvt -m rmvprot.map rmvprotres.grc rmvprot.c
|
||||
$(CL) -t $(SYS) -O -o $@ -m rmvprot.map rmvprotres.grc rmvprot.c
|
||||
|
||||
vector-demo.cvt: vector-demores.grc vector-demo.c
|
||||
$(CL) -t $(SYS) -O -o vector-demo.cvt -m vector-demo.map vector-demores.grc vector-demo.c
|
||||
$(CL) -t $(SYS) -O -o $@ -m vector-demo.map vector-demores.grc vector-demo.c
|
||||
|
||||
yesno.cvt: yesnores.grc yesno.c
|
||||
$(CL) -t $(SYS) -O -o yesno.cvt -m yesno.map yesnores.grc yesno.c
|
||||
$(CL) -t $(SYS) -O -o $@ -m yesno.map yesnores.grc yesno.c
|
||||
|
||||
|
||||
clean:
|
||||
|
|
62
samples/kim1/Makefile
Normal file
62
samples/kim1/Makefile
Normal file
|
@ -0,0 +1,62 @@
|
|||
|
||||
# Run 'make SYS=<target>'; or, set a SYS env.
|
||||
# var. to build for another target system.
|
||||
SYS ?= kim1
|
||||
|
||||
# Just the usual way to find out if we're
|
||||
# using cmd.exe to execute make rules.
|
||||
ifneq ($(shell echo),)
|
||||
CMD_EXE = 1
|
||||
endif
|
||||
|
||||
ifdef CMD_EXE
|
||||
NULLDEV = nul:
|
||||
DEL = -del /f
|
||||
RMDIR = rmdir /s /q
|
||||
else
|
||||
NULLDEV = /dev/null
|
||||
DEL = $(RM)
|
||||
RMDIR = $(RM) -r
|
||||
endif
|
||||
|
||||
ifdef CC65_HOME
|
||||
AS = $(CC65_HOME)/bin/ca65
|
||||
CC = $(CC65_HOME)/bin/cc65
|
||||
CL = $(CC65_HOME)/bin/cl65
|
||||
LD = $(CC65_HOME)/bin/ld65
|
||||
else
|
||||
AS := $(if $(wildcard ../../bin/ca65*),../../bin/ca65,ca65)
|
||||
CC := $(if $(wildcard ../../bin/cc65*),../../bin/cc65,cc65)
|
||||
CL := $(if $(wildcard ../../bin/cl65*),../../bin/cl65,cl65)
|
||||
LD := $(if $(wildcard ../../bin/ld65*),../../bin/ld65,ld65)
|
||||
endif
|
||||
|
||||
EXELIST_kim1 = \
|
||||
kimHello.bin \
|
||||
kimSieve.bin
|
||||
|
||||
ifneq ($(EXELIST_$(SYS)),)
|
||||
samples: $(EXELIST_$(SYS))
|
||||
else
|
||||
samples: notavailable
|
||||
endif
|
||||
|
||||
# empty target used to skip systems that will not work with any program in this dir
|
||||
notavailable:
|
||||
ifeq ($(MAKELEVEL),0)
|
||||
@echo "info: kim1 tests not available for" $(SYS)
|
||||
else
|
||||
# suppress the "nothing to be done for 'samples' message
|
||||
@echo > $(NULLDEV)
|
||||
endif
|
||||
|
||||
kimSieve.bin: kimSieve.c
|
||||
$(CL) -t kim1 -C kim1-60k.cfg -O -o kimSieve.bin kimSieve.c
|
||||
|
||||
kimHello.bin: kimHello.c
|
||||
$(CL) -t kim1 -O -o kimHello.bin kimHello.c
|
||||
|
||||
clean:
|
||||
@$(DEL) kimSieve.bin 2>$(NULLDEV)
|
||||
@$(DEL) kimHello.bin 2>$(NULLDEV)
|
||||
|
24
samples/kim1/kimHello.c
Normal file
24
samples/kim1/kimHello.c
Normal file
|
@ -0,0 +1,24 @@
|
|||
// --------------------------------------------------------------------------
|
||||
// Hello World for KIM-1
|
||||
//
|
||||
// Dave Plummer based on Sym-1 sample by Wayne Parham
|
||||
//
|
||||
// davepl@davepl.com
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
#include <stdio.h>
|
||||
#include <kim1.h>
|
||||
|
||||
int main (void)
|
||||
{
|
||||
char str[100];
|
||||
char c = 0x00;
|
||||
|
||||
printf ("\nHello World!\n\n");
|
||||
printf ("Type a line and press ENTER, please.\n\n");
|
||||
|
||||
gets( str );
|
||||
|
||||
printf ("\n\nThanks: %s\n\n", str);
|
||||
return 0;
|
||||
}
|
125
samples/kim1/kimSieve.c
Normal file
125
samples/kim1/kimSieve.c
Normal file
|
@ -0,0 +1,125 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef unsigned char byte;
|
||||
typedef unsigned short int ushort;
|
||||
typedef unsigned long int ulong;
|
||||
|
||||
#define LIMIT 100000L
|
||||
|
||||
// BITARRAY
|
||||
//
|
||||
// My bit-access macros pre-divide by two on the presumption that you'll never
|
||||
// try try access both odd and even bits!
|
||||
|
||||
#define GETBIT(array, bit) (array[bit >> 4] & (1 << ((bit >> 1) & 7)))
|
||||
#define SETBIT(array, bit) (array[bit >> 4] |= (1 << ((bit >> 1) & 7)))
|
||||
#define CLRBIT(array, bit) (array[bit >> 4] &= ~(1 << ((bit >> 1) & 7)))
|
||||
|
||||
// RepeatChar
|
||||
//
|
||||
// Outputs a given character N times
|
||||
|
||||
void RepeatChar(char c, size_t count)
|
||||
{
|
||||
while (count--)
|
||||
putc(c, stdout);
|
||||
}
|
||||
|
||||
// sqrti
|
||||
//
|
||||
// Binary search integer square root
|
||||
|
||||
ushort sqrti(ulong num)
|
||||
{
|
||||
long i;
|
||||
ulong ret = 0;
|
||||
|
||||
for(i = 15; i >= 0; i--)
|
||||
{
|
||||
ulong temp = ret | (1L << (ulong)i);
|
||||
if(temp * temp <= num)
|
||||
{
|
||||
ret = temp;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// main()
|
||||
//
|
||||
// CC65 main function receives no parameters
|
||||
|
||||
int main(void)
|
||||
{
|
||||
// CC65 cannot mix code and data so we have to declare all variables here in the function prolog
|
||||
|
||||
ulong iNumber;
|
||||
ushort currentFactor;
|
||||
ulong numBytesAllocated, rootOfLimit;
|
||||
byte *array;
|
||||
ulong countOfPrimes;
|
||||
|
||||
rootOfLimit = sqrti(LIMIT);
|
||||
puts("\r\n\r\n");
|
||||
RepeatChar('*', 70);
|
||||
puts("\r\n** Prime Number Sieve - Dave Plummer 2022 **");
|
||||
RepeatChar('*', 70);
|
||||
|
||||
printf("\r\n\r\nCalculating primes to %ld using a sqrt of %ld...\r\n", LIMIT, rootOfLimit);
|
||||
|
||||
// Calculate how much memory should be allocated
|
||||
|
||||
numBytesAllocated = (LIMIT + 15) / 16;
|
||||
array = malloc(numBytesAllocated);
|
||||
if (!array)
|
||||
{
|
||||
printf("Unable to allocate %ld bytes for %ld bits\r\n", numBytesAllocated, LIMIT);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Allocated %ld bytes for %ld slots\r\n", numBytesAllocated, LIMIT);
|
||||
|
||||
// Preset all the bits to true
|
||||
|
||||
for (iNumber = 0; iNumber < numBytesAllocated; iNumber++)
|
||||
array[iNumber] = 0xFF;
|
||||
}
|
||||
|
||||
// Search for next unmarked factor
|
||||
|
||||
currentFactor = 3;
|
||||
while (currentFactor <= rootOfLimit)
|
||||
{
|
||||
ulong num, n;
|
||||
|
||||
for (num = currentFactor; num <= LIMIT; num += 2)
|
||||
{
|
||||
if (GETBIT(array, num))
|
||||
{
|
||||
currentFactor = num;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (n = (ulong) currentFactor * currentFactor; n <= LIMIT; n += currentFactor * 2)
|
||||
CLRBIT(array, n);
|
||||
|
||||
currentFactor += 2;
|
||||
}
|
||||
|
||||
// Display results
|
||||
//
|
||||
// printf("The following primes were found at or below %ld:\r\n2, ", LIMIT);
|
||||
|
||||
countOfPrimes = 1;
|
||||
for (iNumber = 3; iNumber <= LIMIT; iNumber += 2)
|
||||
if (GETBIT(array, iNumber))
|
||||
countOfPrimes++;
|
||||
|
||||
printf("[END: Count = %ld]\r\n", countOfPrimes);
|
||||
|
||||
free(array);
|
||||
return 1;
|
||||
}
|
76
samples/terminal.c
Normal file
76
samples/terminal.c
Normal file
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
** Minimalistic terminal program.
|
||||
**
|
||||
** Makes use of the serial drivers.
|
||||
**
|
||||
** 2022-12-23, Oliver Schmidt (ol.sc@web.de)
|
||||
**
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <cc65.h>
|
||||
#include <conio.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <serial.h>
|
||||
|
||||
|
||||
static void check (const char* msg, unsigned char err)
|
||||
{
|
||||
if (err == SER_ERR_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
printf ("%s:0x%02x\n", msg, err);
|
||||
if (doesclrscrafterexit ()) {
|
||||
cgetc ();
|
||||
}
|
||||
exit (1);
|
||||
}
|
||||
|
||||
|
||||
void main (void)
|
||||
{
|
||||
const struct ser_params par = {
|
||||
SER_BAUD_9600,
|
||||
SER_BITS_8,
|
||||
SER_STOP_1,
|
||||
SER_PAR_NONE,
|
||||
SER_HS_HW
|
||||
};
|
||||
|
||||
check ("ser_install", ser_install (ser_static_stddrv));
|
||||
|
||||
check ("ser_open", ser_open (&par));
|
||||
|
||||
atexit ((void (*)) ser_close);
|
||||
|
||||
printf ("Serial Port: 9600-8-1-N RTS/CTS\n"
|
||||
"Simple Term: Press ESC for exit\n");
|
||||
|
||||
while (1)
|
||||
{
|
||||
char chr;
|
||||
|
||||
if (kbhit ())
|
||||
{
|
||||
chr = cgetc ();
|
||||
|
||||
if (chr == CH_ESC) {
|
||||
putchar ('\n');
|
||||
return;
|
||||
}
|
||||
|
||||
if (ser_put (chr) == SER_ERR_OK) {
|
||||
putchar (chr);
|
||||
} else {
|
||||
putchar ('\a');
|
||||
}
|
||||
}
|
||||
|
||||
if (ser_get (&chr) == SER_ERR_OK) {
|
||||
putchar (chr);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -342,6 +342,10 @@ static void SetSys (const char* Sys)
|
|||
NewSymbol ("__SYM1__", 1);
|
||||
break;
|
||||
|
||||
case TGT_KIM1:
|
||||
NewSymbol ("__KIM1__", 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
AbEnd ("Invalid target name: '%s'", Sys);
|
||||
|
||||
|
|
|
@ -624,7 +624,7 @@ void OpAssign (const GenDesc* Gen, ExprDesc* Expr, const char* Op)
|
|||
Expr2.Flags |= Expr->Flags & E_MASK_KEEP_SUBEXPR;
|
||||
|
||||
/* Only "=" accept struct/union */
|
||||
if (IsClassStruct (ltype) ? Gen != 0 : !IsClassScalar (ltype)) {
|
||||
if (IsClassStruct (ltype) ? Gen != 0 : !IsScalarType (ltype)) {
|
||||
Error ("Invalid left operand for binary operator '%s'", Op);
|
||||
/* Continue. Wrong code will be generated, but the compiler won't
|
||||
** break, so this is the best error recovery.
|
||||
|
|
|
@ -71,12 +71,12 @@
|
|||
/* This is a terrible hack that tries to combat the ever reoccuring issue with
|
||||
Mingw and PRIXPTR - the macro should have been defined like this for us in
|
||||
the first place.
|
||||
NOTE: "I64u" works in the github actions now, so if your local mingw64 fails,
|
||||
NOTE: "I64x" works in the github actions now, so if your local mingw64 fails,
|
||||
you probably have to update.
|
||||
*/
|
||||
#if defined(__MINGW64__)
|
||||
#undef PRIXPTR
|
||||
#define PRIXPTR "I64u"
|
||||
#define PRIXPTR "I64x"
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
@ -850,6 +850,10 @@ static unsigned RunOptGroup7 (CodeSeg* S)
|
|||
C += RunOptFunc (S, &DOptJumpCascades, 1);
|
||||
C += RunOptFunc (S, &DOptBranchDist2, 1);
|
||||
|
||||
/* Adjust branch distances again, since the previous step may change code
|
||||
between branches */
|
||||
C += RunOptFunc (S, &DOptBranchDist, 3);
|
||||
|
||||
Changes += C;
|
||||
/* If we had changes, we must run dead code elimination again,
|
||||
** since the changes may have introduced dead code.
|
||||
|
|
|
@ -521,7 +521,7 @@ CodeSeg* NewCodeSeg (const char* SegName, SymEntry* Func)
|
|||
/* If we have a function given, get the return type of the function.
|
||||
** Assume ANY return type besides void will use the A and X registers.
|
||||
*/
|
||||
if (S->Func && !IsTypeVoid ((RetType = GetFuncReturn (Func->Type)))) {
|
||||
if (S->Func && !IsTypeVoid ((RetType = GetFuncReturnType (Func->Type)))) {
|
||||
if (SizeOf (RetType) == SizeOf (type_long)) {
|
||||
S->ExitRegs = REG_EAX;
|
||||
} else {
|
||||
|
|
|
@ -150,7 +150,7 @@ void TypeFree (Type* T)
|
|||
|
||||
|
||||
int SignExtendChar (int C)
|
||||
/* Do correct sign extension of a character */
|
||||
/* Do correct sign extension of a character to an int */
|
||||
{
|
||||
if (IS_Get (&SignedChars) && (C & 0x80) != 0) {
|
||||
return C | ~0xFF;
|
||||
|
@ -214,7 +214,7 @@ unsigned BitSizeOf (const Type* T)
|
|||
unsigned SizeOf (const Type* T)
|
||||
/* Compute size (in bytes) of object represented by type array */
|
||||
{
|
||||
switch (GetUnderlyingTypeCode (T)) {
|
||||
switch (GetUnqualTypeCode (T)) {
|
||||
|
||||
case T_VOID:
|
||||
/* A void variable is a cc65 extension.
|
||||
|
@ -347,7 +347,7 @@ unsigned CheckedPSizeOf (const Type* T)
|
|||
|
||||
|
||||
|
||||
static unsigned GetBitFieldMinimalTypeSize (unsigned BitWidth)
|
||||
static unsigned GetMinimalTypeSizeByBitWidth (unsigned BitWidth)
|
||||
/* Return the size of the smallest integer type that may have BitWidth bits */
|
||||
{
|
||||
/* Since all integer types supported in cc65 for bit-fields have sizes that
|
||||
|
@ -366,14 +366,14 @@ static unsigned GetBitFieldMinimalTypeSize (unsigned BitWidth)
|
|||
|
||||
|
||||
|
||||
TypeCode GetUnderlyingTypeCode (const Type* Type)
|
||||
/* Get the type code of the unqualified underlying type of TCode.
|
||||
** Return UnqualTypeCode (Type) if Type is not scalar.
|
||||
TypeCode GetUnqualTypeCode (const Type* Type)
|
||||
/* Get the type code of the unqualified underlying type of Type.
|
||||
** Return GetUnqualRawTypeCode (Type) if Type is not scalar.
|
||||
*/
|
||||
{
|
||||
TypeCode Underlying = UnqualifiedType (Type->C);
|
||||
TypeCode Underlying = GetUnqualRawTypeCode (Type);
|
||||
|
||||
if (IsISOChar (Type)) {
|
||||
if (IsDeclTypeChar (Type)) {
|
||||
|
||||
return IS_Get (&SignedChars) ? T_SCHAR : T_UCHAR;
|
||||
|
||||
|
@ -382,7 +382,7 @@ TypeCode GetUnderlyingTypeCode (const Type* Type)
|
|||
|
||||
/* This should not happen, but just in case */
|
||||
if (Type->A.S == 0) {
|
||||
Internal ("Enum tag type error in GetUnderlyingTypeCode");
|
||||
Internal ("Enum tag type error in GetUnqualTypeCode");
|
||||
}
|
||||
|
||||
/* Inspect the underlying type of the enum */
|
||||
|
@ -390,24 +390,24 @@ TypeCode GetUnderlyingTypeCode (const Type* Type)
|
|||
/* Incomplete enum type is used */
|
||||
return Underlying;
|
||||
}
|
||||
TCode = UnqualifiedType (Type->A.S->V.E.Type->C);
|
||||
TCode = GetUnqualRawTypeCode (Type->A.S->V.E.Type);
|
||||
|
||||
/* Replace the type code with integer */
|
||||
Underlying = (TCode & ~T_MASK_TYPE);
|
||||
Underlying = (TCode & ~T_MASK_RANK);
|
||||
switch (TCode & T_MASK_SIZE) {
|
||||
case T_SIZE_INT: Underlying |= T_TYPE_INT; break;
|
||||
case T_SIZE_LONG: Underlying |= T_TYPE_LONG; break;
|
||||
case T_SIZE_SHORT: Underlying |= T_TYPE_SHORT; break;
|
||||
case T_SIZE_CHAR: Underlying |= T_TYPE_CHAR; break;
|
||||
case T_SIZE_LONGLONG: Underlying |= T_TYPE_LONGLONG; break;
|
||||
default: Underlying |= T_TYPE_INT; break;
|
||||
case T_SIZE_INT: Underlying |= T_RANK_INT; break;
|
||||
case T_SIZE_LONG: Underlying |= T_RANK_LONG; break;
|
||||
case T_SIZE_SHORT: Underlying |= T_RANK_SHORT; break;
|
||||
case T_SIZE_CHAR: Underlying |= T_RANK_CHAR; break;
|
||||
case T_SIZE_LONGLONG: Underlying |= T_RANK_LONGLONG; break;
|
||||
default: Underlying |= T_RANK_INT; break;
|
||||
}
|
||||
} else if (IsTypeBitField (Type)) {
|
||||
/* We consider the smallest type that can represent all values of the
|
||||
** bit-field, instead of the type used in the declaration, the truly
|
||||
** underlying of the bit-field.
|
||||
*/
|
||||
switch (GetBitFieldMinimalTypeSize (Type->A.B.Width)) {
|
||||
switch (GetMinimalTypeSizeByBitWidth (Type->A.B.Width)) {
|
||||
case SIZEOF_CHAR: Underlying = T_CHAR; break;
|
||||
case SIZEOF_INT: Underlying = T_INT; break;
|
||||
case SIZEOF_LONG: Underlying = T_LONG; break;
|
||||
|
@ -494,7 +494,7 @@ Type* NewPointerTo (const Type* T)
|
|||
|
||||
|
||||
|
||||
Type* NewBitFieldType (const Type* T, unsigned BitOffs, unsigned BitWidth)
|
||||
Type* NewBitFieldOf (const Type* T, unsigned BitOffs, unsigned BitWidth)
|
||||
/* Return a type string that is "T : BitWidth" aligned on BitOffs. The type
|
||||
** string is allocated on the heap and may be freed after use.
|
||||
*/
|
||||
|
@ -560,20 +560,6 @@ const Type* Indirect (const Type* T)
|
|||
|
||||
|
||||
|
||||
Type* IndirectModifiable (Type* T)
|
||||
/* Do one indirection for the given type, that is, return the type where the
|
||||
** given type points to.
|
||||
*/
|
||||
{
|
||||
/* We are expecting a pointer expression */
|
||||
CHECK (IsClassPtr (T));
|
||||
|
||||
/* Skip the pointer or array token itself */
|
||||
return T + 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Type* ArrayToPtr (const Type* T)
|
||||
/* Convert an array to a pointer to it's first element */
|
||||
{
|
||||
|
@ -648,12 +634,12 @@ const Type* IntPromotion (const Type* T)
|
|||
return IsSignUnsigned (T) ? type_ulong : type_long;
|
||||
}
|
||||
return T->A.B.Width == INT_BITS && IsSignUnsigned (T) ? type_uint : type_int;
|
||||
} else if (IsTypeChar (T)) {
|
||||
} else if (IsRankChar (T)) {
|
||||
/* An integer can represent all values from either signed or unsigned char, so convert
|
||||
** chars to int.
|
||||
*/
|
||||
return type_int;
|
||||
} else if (IsTypeShort (T)) {
|
||||
} else if (IsRankShort (T)) {
|
||||
/* An integer cannot represent all values from unsigned short, so convert unsigned short
|
||||
** to unsigned int.
|
||||
*/
|
||||
|
@ -703,8 +689,8 @@ const Type* ArithmeticConvert (const Type* lhst, const Type* rhst)
|
|||
/* If either operand has type unsigned long int, the other operand is converted to
|
||||
** unsigned long int.
|
||||
*/
|
||||
if ((IsTypeLong (lhst) && IsSignUnsigned (lhst)) ||
|
||||
(IsTypeLong (rhst) && IsSignUnsigned (rhst))) {
|
||||
if ((IsRankLong (lhst) && IsSignUnsigned (lhst)) ||
|
||||
(IsRankLong (rhst) && IsSignUnsigned (rhst))) {
|
||||
return type_ulong;
|
||||
}
|
||||
|
||||
|
@ -713,74 +699,74 @@ const Type* ArithmeticConvert (const Type* lhst, const Type* rhst)
|
|||
** is converted to long int ; if a long int cannot represent all the values of an unsigned int,
|
||||
** both operands are converted to unsigned long int.
|
||||
*/
|
||||
if ((IsTypeLong (lhst) && IsTypeInt (rhst) && IsSignUnsigned (rhst)) ||
|
||||
(IsTypeLong (rhst) && IsTypeInt (lhst) && IsSignUnsigned (lhst))) {
|
||||
if ((IsRankLong (lhst) && IsRankInt (rhst) && IsSignUnsigned (rhst)) ||
|
||||
(IsRankLong (rhst) && IsRankInt (lhst) && IsSignUnsigned (lhst))) {
|
||||
/* long can represent all unsigneds, so we are in the first sub-case. */
|
||||
return type_long;
|
||||
}
|
||||
|
||||
/* Otherwise, if either operand has type long int, the other operand is converted to long int.
|
||||
*/
|
||||
if (IsTypeLong (lhst) || IsTypeLong (rhst)) {
|
||||
if (IsRankLong (lhst) || IsRankLong (rhst)) {
|
||||
return type_long;
|
||||
}
|
||||
|
||||
/* Otherwise, if either operand has type unsigned int, the other operand is converted to
|
||||
** unsigned int.
|
||||
*/
|
||||
if ((IsTypeInt (lhst) && IsSignUnsigned (lhst)) ||
|
||||
(IsTypeInt (rhst) && IsSignUnsigned (rhst))) {
|
||||
if ((IsRankInt (lhst) && IsSignUnsigned (lhst)) ||
|
||||
(IsRankInt (rhst) && IsSignUnsigned (rhst))) {
|
||||
return type_uint;
|
||||
}
|
||||
|
||||
/* Otherwise, both operands have type int. */
|
||||
CHECK (IsTypeInt (lhst));
|
||||
CHECK (IsRankInt (lhst));
|
||||
CHECK (IsSignSigned (lhst));
|
||||
CHECK (IsTypeInt (rhst));
|
||||
CHECK (IsRankInt (rhst));
|
||||
CHECK (IsSignSigned (rhst));
|
||||
return type_int;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const Type* SignedType (const Type* T)
|
||||
const Type* GetSignedType (const Type* T)
|
||||
/* Get signed counterpart of the integral type */
|
||||
{
|
||||
switch (GetUnderlyingTypeCode (T) & T_MASK_TYPE) {
|
||||
case T_TYPE_CHAR:
|
||||
switch (GetUnqualTypeCode (T) & T_MASK_RANK) {
|
||||
case T_RANK_CHAR:
|
||||
return type_schar;
|
||||
|
||||
case T_TYPE_INT:
|
||||
case T_TYPE_SHORT:
|
||||
case T_RANK_INT:
|
||||
case T_RANK_SHORT:
|
||||
return type_int;
|
||||
|
||||
case T_TYPE_LONG:
|
||||
case T_RANK_LONG:
|
||||
return type_long;
|
||||
|
||||
default:
|
||||
Internal ("Unknown type code: %lX", GetUnderlyingTypeCode (T));
|
||||
Internal ("Unknown type code: %lX", GetUnqualTypeCode (T));
|
||||
return T;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const Type* UnsignedType (const Type* T)
|
||||
const Type* GetUnsignedType (const Type* T)
|
||||
/* Get unsigned counterpart of the integral type */
|
||||
{
|
||||
switch (GetUnderlyingTypeCode (T) & T_MASK_TYPE) {
|
||||
case T_TYPE_CHAR:
|
||||
switch (GetUnqualTypeCode (T) & T_MASK_RANK) {
|
||||
case T_RANK_CHAR:
|
||||
return type_uchar;
|
||||
|
||||
case T_TYPE_INT:
|
||||
case T_TYPE_SHORT:
|
||||
case T_RANK_INT:
|
||||
case T_RANK_SHORT:
|
||||
return type_uint;
|
||||
|
||||
case T_TYPE_LONG:
|
||||
case T_RANK_LONG:
|
||||
return type_ulong;
|
||||
|
||||
default:
|
||||
Internal ("Unknown type code: %lX", GetUnderlyingTypeCode (T));
|
||||
Internal ("Unknown type code: %lX", GetUnqualTypeCode (T));
|
||||
return T;
|
||||
}
|
||||
}
|
||||
|
@ -790,12 +776,12 @@ const Type* UnsignedType (const Type* T)
|
|||
const Type* GetUnderlyingType (const Type* Type)
|
||||
/* Get the underlying type of an enum or other integer class type */
|
||||
{
|
||||
if (IsISOChar (Type)) {
|
||||
if (IsDeclTypeChar (Type)) {
|
||||
return IS_Get (&SignedChars) ? type_schar : type_uchar;
|
||||
} else if (IsTypeEnum (Type)) {
|
||||
/* This should not happen, but just in case */
|
||||
if (Type->A.S == 0) {
|
||||
Internal ("Enum tag type error in GetUnderlyingTypeCode");
|
||||
Internal ("Enum tag type error in GetUnderlyingType");
|
||||
}
|
||||
|
||||
/* If incomplete enum type is used, just return its raw type */
|
||||
|
@ -807,7 +793,7 @@ const Type* GetUnderlyingType (const Type* Type)
|
|||
** bit-field, instead of the type used in the declaration, the truly
|
||||
** underlying of the bit-field.
|
||||
*/
|
||||
switch (GetBitFieldMinimalTypeSize (Type->A.B.Width)) {
|
||||
switch (GetMinimalTypeSizeByBitWidth (Type->A.B.Width)) {
|
||||
case SIZEOF_CHAR: Type = IsSignSigned (Type) ? type_schar : type_uchar; break;
|
||||
case SIZEOF_INT: Type = IsSignSigned (Type) ? type_int : type_uint; break;
|
||||
case SIZEOF_LONG: Type = IsSignSigned (Type) ? type_long : type_ulong; break;
|
||||
|
@ -821,7 +807,7 @@ const Type* GetUnderlyingType (const Type* Type)
|
|||
|
||||
|
||||
const Type* GetStructReplacementType (const Type* SType)
|
||||
/* Get a replacement type for passing a struct/union in the primary register */
|
||||
/* Get a replacement type for passing a struct/union by value in the primary */
|
||||
{
|
||||
const Type* NewType;
|
||||
/* If the size is less than or equal to that of a long, we will copy the
|
||||
|
@ -850,7 +836,7 @@ const Type* GetBitFieldChunkType (const Type* Type)
|
|||
return GetUnderlyingType (Type);
|
||||
}
|
||||
|
||||
ChunkSize = GetBitFieldMinimalTypeSize (Type->A.B.Offs + Type->A.B.Width);
|
||||
ChunkSize = GetMinimalTypeSizeByBitWidth (Type->A.B.Offs + Type->A.B.Width);
|
||||
if (ChunkSize < SizeOf (Type + 1)) {
|
||||
/* The end of the bit-field is offset by some bits so that it requires
|
||||
** more bytes to be accessed as a whole than its underlying type does.
|
||||
|
@ -888,50 +874,50 @@ int IsTypeFragBitField (const Type* T)
|
|||
|
||||
|
||||
|
||||
int IsClassObject (const Type* T)
|
||||
int IsObjectType (const Type* T)
|
||||
/* Return true if this is a fully described object type */
|
||||
{
|
||||
return !IsTypeFunc (T) && !IsClassIncomplete (T);
|
||||
return !IsTypeFunc (T) && !IsIncompleteType (T);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int IsClassIncomplete (const Type* T)
|
||||
int IsIncompleteType (const Type* T)
|
||||
/* Return true if this is an object type lacking size info */
|
||||
{
|
||||
if (IsTypeArray (T)) {
|
||||
return GetElementCount (T) == UNSPECIFIED || IsClassIncomplete (T + 1);
|
||||
return GetElementCount (T) == UNSPECIFIED || IsIncompleteType (T + 1);
|
||||
}
|
||||
return IsTypeVoid (T) || IsIncompleteESUType (T);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int IsClassArithmetic (const Type* T)
|
||||
/* Return true if this is an integer or real floating type */
|
||||
int IsArithmeticType (const Type* T)
|
||||
/* Return true if this is an integer or floating type */
|
||||
{
|
||||
return IsClassInt (T) || IsClassFloat (T);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int IsClassBasic (const Type* T)
|
||||
/* Return true if this is a char, integer or floating type */
|
||||
int IsBasicType (const Type* T)
|
||||
/* Return true if this is a character, integer or floating type */
|
||||
{
|
||||
return IsClassChar (T) || IsClassInt (T) || IsClassFloat (T);
|
||||
return IsDeclRankChar (T) || IsClassInt (T) || IsClassFloat (T);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int IsClassScalar (const Type* T)
|
||||
int IsScalarType (const Type* T)
|
||||
/* Return true if this is an arithmetic or pointer type */
|
||||
{
|
||||
return IsClassArithmetic (T) || IsTypePtr (T);
|
||||
return IsArithmeticType (T) || IsTypePtr (T);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int IsClassDerived (const Type* T)
|
||||
int IsDerivedType (const Type* T)
|
||||
/* Return true if this is an array, struct, union, function or pointer type */
|
||||
{
|
||||
return IsTypeArray (T) || IsClassStruct (T) || IsClassFunc (T) || IsTypePtr (T);
|
||||
|
@ -939,7 +925,7 @@ int IsClassDerived (const Type* T)
|
|||
|
||||
|
||||
|
||||
int IsClassAggregate (const Type* T)
|
||||
int IsAggregateType (const Type* T)
|
||||
/* Return true if this is an array or struct type */
|
||||
{
|
||||
return IsTypeArray (T) || IsTypeStruct (T);
|
||||
|
@ -950,7 +936,7 @@ int IsClassAggregate (const Type* T)
|
|||
int IsRelationType (const Type* T)
|
||||
/* Return true if this is an arithmetic, array or pointer type */
|
||||
{
|
||||
return IsClassArithmetic (T) || IsClassPtr (T);
|
||||
return IsArithmeticType (T) || IsClassPtr (T);
|
||||
}
|
||||
|
||||
|
||||
|
@ -958,7 +944,7 @@ int IsRelationType (const Type* T)
|
|||
int IsCastType (const Type* T)
|
||||
/* Return true if this type can be used for casting */
|
||||
{
|
||||
return IsClassScalar (T) || IsTypeVoid (T);
|
||||
return IsScalarType (T) || IsTypeVoid (T);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1000,7 +986,7 @@ int HasUnknownSize (const Type* T)
|
|||
|
||||
|
||||
|
||||
int TypeHasAttr (const Type* T)
|
||||
int TypeHasAttrData (const Type* T)
|
||||
/* Return true if the given type has attribute data */
|
||||
{
|
||||
return IsClassStruct (T) || IsTypeArray (T) || IsClassFunc (T);
|
||||
|
@ -1057,7 +1043,7 @@ int IsFastcallFunc (const Type* T)
|
|||
** Check fails if the type is not a function or a pointer to function.
|
||||
*/
|
||||
{
|
||||
if (UnqualifiedType (T->C) == T_PTR) {
|
||||
if (GetUnqualRawTypeCode (T) == T_PTR) {
|
||||
/* Pointer to function */
|
||||
++T;
|
||||
}
|
||||
|
@ -1069,7 +1055,7 @@ int IsFastcallFunc (const Type* T)
|
|||
FuncDesc* GetFuncDesc (const Type* T)
|
||||
/* Get the FuncDesc pointer from a function or pointer-to-function type */
|
||||
{
|
||||
if (UnqualifiedType (T->C) == T_PTR) {
|
||||
if (GetUnqualRawTypeCode (T) == T_PTR) {
|
||||
/* Pointer to function */
|
||||
++T;
|
||||
}
|
||||
|
@ -1086,7 +1072,7 @@ FuncDesc* GetFuncDesc (const Type* T)
|
|||
void SetFuncDesc (Type* T, FuncDesc* F)
|
||||
/* Set the FuncDesc pointer in a function or pointer-to-function type */
|
||||
{
|
||||
if (UnqualifiedType (T->C) == T_PTR) {
|
||||
if (GetUnqualRawTypeCode (T) == T_PTR) {
|
||||
/* Pointer to function */
|
||||
++T;
|
||||
}
|
||||
|
@ -1100,10 +1086,10 @@ void SetFuncDesc (Type* T, FuncDesc* F)
|
|||
|
||||
|
||||
|
||||
const Type* GetFuncReturn (const Type* T)
|
||||
const Type* GetFuncReturnType (const Type* T)
|
||||
/* Return a pointer to the return type of a function or pointer-to-function type */
|
||||
{
|
||||
if (UnqualifiedType (T->C) == T_PTR) {
|
||||
if (GetUnqualRawTypeCode (T) == T_PTR) {
|
||||
/* Pointer to function */
|
||||
++T;
|
||||
}
|
||||
|
@ -1117,10 +1103,10 @@ const Type* GetFuncReturn (const Type* T)
|
|||
|
||||
|
||||
|
||||
Type* GetFuncReturnModifiable (Type* T)
|
||||
Type* GetFuncReturnTypeModifiable (Type* T)
|
||||
/* Return a non-const pointer to the return type of a function or pointer-to-function type */
|
||||
{
|
||||
if (UnqualifiedType (T->C) == T_PTR) {
|
||||
if (GetUnqualRawTypeCode (T) == T_PTR) {
|
||||
/* Pointer to function */
|
||||
++T;
|
||||
}
|
||||
|
@ -1177,7 +1163,16 @@ void SetElementCount (Type* T, long Count)
|
|||
|
||||
|
||||
const Type* GetElementType (const Type* T)
|
||||
/* Return the element type of the given array type. */
|
||||
/* Return the element type of the given array type */
|
||||
{
|
||||
CHECK (IsTypeArray (T));
|
||||
return T + 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Type* GetElementTypeModifiable (Type* T)
|
||||
/* Return the element type of the given array type */
|
||||
{
|
||||
CHECK (IsTypeArray (T));
|
||||
return T + 1;
|
||||
|
@ -1241,48 +1236,48 @@ const char* GetBasicTypeName (const Type* T)
|
|||
** Return "type" for unknown basic types.
|
||||
*/
|
||||
{
|
||||
switch (GetRawType (T)) {
|
||||
case T_TYPE_ENUM: return "enum";
|
||||
case T_TYPE_BITFIELD: return "bit-field";
|
||||
case T_TYPE_FLOAT: return "float";
|
||||
case T_TYPE_DOUBLE: return "double";
|
||||
case T_TYPE_VOID: return "void";
|
||||
case T_TYPE_STRUCT: return "struct";
|
||||
case T_TYPE_UNION: return "union";
|
||||
case T_TYPE_ARRAY: return "array";
|
||||
case T_TYPE_PTR: return "pointer";
|
||||
case T_TYPE_FUNC: return "function";
|
||||
case T_TYPE_NONE: /* FALLTHROUGH */
|
||||
switch (GetRawTypeRank (T)) {
|
||||
case T_RANK_ENUM: return "enum";
|
||||
case T_RANK_BITFIELD: return "bit-field";
|
||||
case T_RANK_FLOAT: return "float";
|
||||
case T_RANK_DOUBLE: return "double";
|
||||
case T_RANK_VOID: return "void";
|
||||
case T_RANK_STRUCT: return "struct";
|
||||
case T_RANK_UNION: return "union";
|
||||
case T_RANK_ARRAY: return "array";
|
||||
case T_RANK_PTR: return "pointer";
|
||||
case T_RANK_FUNC: return "function";
|
||||
case T_RANK_NONE: /* FALLTHROUGH */
|
||||
default: break;
|
||||
}
|
||||
if (IsClassInt (T)) {
|
||||
if (IsRawSignSigned (T)) {
|
||||
switch (GetRawType (T)) {
|
||||
case T_TYPE_CHAR: return "signed char";
|
||||
case T_TYPE_SHORT: return "short";
|
||||
case T_TYPE_INT: return "int";
|
||||
case T_TYPE_LONG: return "long";
|
||||
case T_TYPE_LONGLONG: return "long long";
|
||||
switch (GetRawTypeRank (T)) {
|
||||
case T_RANK_CHAR: return "signed char";
|
||||
case T_RANK_SHORT: return "short";
|
||||
case T_RANK_INT: return "int";
|
||||
case T_RANK_LONG: return "long";
|
||||
case T_RANK_LONGLONG: return "long long";
|
||||
default:
|
||||
return "signed integer";
|
||||
}
|
||||
} else if (IsRawSignUnsigned (T)) {
|
||||
switch (GetRawType (T)) {
|
||||
case T_TYPE_CHAR: return "unsigned char";
|
||||
case T_TYPE_SHORT: return "unsigned short";
|
||||
case T_TYPE_INT: return "unsigned int";
|
||||
case T_TYPE_LONG: return "unsigned long";
|
||||
case T_TYPE_LONGLONG: return "unsigned long long";
|
||||
switch (GetRawTypeRank (T)) {
|
||||
case T_RANK_CHAR: return "unsigned char";
|
||||
case T_RANK_SHORT: return "unsigned short";
|
||||
case T_RANK_INT: return "unsigned int";
|
||||
case T_RANK_LONG: return "unsigned long";
|
||||
case T_RANK_LONGLONG: return "unsigned long long";
|
||||
default:
|
||||
return "unsigned integer";
|
||||
}
|
||||
} else {
|
||||
switch (GetRawType (T)) {
|
||||
case T_TYPE_CHAR: return "char";
|
||||
case T_TYPE_SHORT: return "short";
|
||||
case T_TYPE_INT: return "int";
|
||||
case T_TYPE_LONG: return "long";
|
||||
case T_TYPE_LONGLONG: return "long long";
|
||||
switch (GetRawTypeRank (T)) {
|
||||
case T_RANK_CHAR: return "char";
|
||||
case T_RANK_SHORT: return "short";
|
||||
case T_RANK_INT: return "int";
|
||||
case T_RANK_LONG: return "long";
|
||||
case T_RANK_LONGLONG: return "long long";
|
||||
default:
|
||||
return "integer";
|
||||
}
|
||||
|
@ -1613,7 +1608,7 @@ void PrintFuncSig (FILE* F, const char* Name, const Type* T)
|
|||
SB_Done (&ParamList);
|
||||
|
||||
/* Complete with the return type */
|
||||
GetFullTypeNameWestEast (&West, &East, GetFuncReturn (T));
|
||||
GetFullTypeNameWestEast (&West, &East, GetFuncReturnType (T));
|
||||
SB_Append (&West, &East);
|
||||
SB_Terminate (&West);
|
||||
|
||||
|
|
|
@ -71,24 +71,24 @@ struct SymEntry;
|
|||
enum {
|
||||
T_END = 0x000000,
|
||||
|
||||
/* Basic types */
|
||||
T_TYPE_NONE = 0x000000,
|
||||
T_TYPE_CHAR = 0x000001,
|
||||
T_TYPE_SHORT = 0x000002,
|
||||
T_TYPE_INT = 0x000003,
|
||||
T_TYPE_LONG = 0x000004,
|
||||
T_TYPE_LONGLONG = 0x000005,
|
||||
T_TYPE_ENUM = 0x000008,
|
||||
T_TYPE_BITFIELD = 0x000009,
|
||||
T_TYPE_FLOAT = 0x00000A,
|
||||
T_TYPE_DOUBLE = 0x00000B,
|
||||
T_TYPE_VOID = 0x000010,
|
||||
T_TYPE_STRUCT = 0x000011,
|
||||
T_TYPE_UNION = 0x000012,
|
||||
T_TYPE_ARRAY = 0x000018,
|
||||
T_TYPE_PTR = 0x000019,
|
||||
T_TYPE_FUNC = 0x00001A,
|
||||
T_MASK_TYPE = 0x00001F,
|
||||
/* Basic type ranks */
|
||||
T_RANK_NONE = 0x000000,
|
||||
T_RANK_CHAR = 0x000001,
|
||||
T_RANK_SHORT = 0x000002,
|
||||
T_RANK_INT = 0x000003,
|
||||
T_RANK_LONG = 0x000004,
|
||||
T_RANK_LONGLONG = 0x000005,
|
||||
T_RANK_ENUM = 0x000008,
|
||||
T_RANK_BITFIELD = 0x000009,
|
||||
T_RANK_FLOAT = 0x00000A,
|
||||
T_RANK_DOUBLE = 0x00000B,
|
||||
T_RANK_VOID = 0x000010,
|
||||
T_RANK_STRUCT = 0x000011,
|
||||
T_RANK_UNION = 0x000012,
|
||||
T_RANK_ARRAY = 0x000018,
|
||||
T_RANK_PTR = 0x000019,
|
||||
T_RANK_FUNC = 0x00001A,
|
||||
T_MASK_RANK = 0x00001F,
|
||||
|
||||
/* Type classes */
|
||||
T_CLASS_NONE = 0x000000,
|
||||
|
@ -129,28 +129,28 @@ enum {
|
|||
T_MASK_QUAL = 0x7F0000,
|
||||
|
||||
/* Types */
|
||||
T_CHAR = T_TYPE_CHAR | T_CLASS_INT | T_SIGN_NONE | T_SIZE_CHAR,
|
||||
T_SCHAR = T_TYPE_CHAR | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_CHAR,
|
||||
T_UCHAR = T_TYPE_CHAR | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_CHAR,
|
||||
T_SHORT = T_TYPE_SHORT | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_SHORT,
|
||||
T_USHORT = T_TYPE_SHORT | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_SHORT,
|
||||
T_INT = T_TYPE_INT | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_INT,
|
||||
T_UINT = T_TYPE_INT | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_INT,
|
||||
T_LONG = T_TYPE_LONG | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_LONG,
|
||||
T_ULONG = T_TYPE_LONG | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_LONG,
|
||||
T_LONGLONG = T_TYPE_LONGLONG | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_LONGLONG,
|
||||
T_ULONGLONG = T_TYPE_LONGLONG | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_LONGLONG,
|
||||
T_ENUM = T_TYPE_ENUM | T_CLASS_INT | T_SIGN_NONE | T_SIZE_NONE,
|
||||
T_SBITFIELD = T_TYPE_BITFIELD | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_NONE,
|
||||
T_UBITFIELD = T_TYPE_BITFIELD | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_NONE,
|
||||
T_FLOAT = T_TYPE_FLOAT | T_CLASS_FLOAT | T_SIGN_NONE | T_SIZE_NONE,
|
||||
T_DOUBLE = T_TYPE_DOUBLE | T_CLASS_FLOAT | T_SIGN_NONE | T_SIZE_NONE,
|
||||
T_VOID = T_TYPE_VOID | T_CLASS_NONE | T_SIGN_NONE | T_SIZE_NONE,
|
||||
T_STRUCT = T_TYPE_STRUCT | T_CLASS_STRUCT | T_SIGN_NONE | T_SIZE_NONE,
|
||||
T_UNION = T_TYPE_UNION | T_CLASS_STRUCT | T_SIGN_NONE | T_SIZE_NONE,
|
||||
T_ARRAY = T_TYPE_ARRAY | T_CLASS_PTR | T_SIGN_NONE | T_SIZE_NONE,
|
||||
T_PTR = T_TYPE_PTR | T_CLASS_PTR | T_SIGN_NONE | T_SIZE_NONE,
|
||||
T_FUNC = T_TYPE_FUNC | T_CLASS_FUNC | T_SIGN_NONE | T_SIZE_NONE,
|
||||
T_CHAR = T_RANK_CHAR | T_CLASS_INT | T_SIGN_NONE | T_SIZE_CHAR,
|
||||
T_SCHAR = T_RANK_CHAR | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_CHAR,
|
||||
T_UCHAR = T_RANK_CHAR | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_CHAR,
|
||||
T_SHORT = T_RANK_SHORT | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_SHORT,
|
||||
T_USHORT = T_RANK_SHORT | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_SHORT,
|
||||
T_INT = T_RANK_INT | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_INT,
|
||||
T_UINT = T_RANK_INT | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_INT,
|
||||
T_LONG = T_RANK_LONG | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_LONG,
|
||||
T_ULONG = T_RANK_LONG | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_LONG,
|
||||
T_LONGLONG = T_RANK_LONGLONG | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_LONGLONG,
|
||||
T_ULONGLONG = T_RANK_LONGLONG | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_LONGLONG,
|
||||
T_ENUM = T_RANK_ENUM | T_CLASS_INT | T_SIGN_NONE | T_SIZE_NONE,
|
||||
T_SBITFIELD = T_RANK_BITFIELD | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_NONE,
|
||||
T_UBITFIELD = T_RANK_BITFIELD | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_NONE,
|
||||
T_FLOAT = T_RANK_FLOAT | T_CLASS_FLOAT | T_SIGN_NONE | T_SIZE_NONE,
|
||||
T_DOUBLE = T_RANK_DOUBLE | T_CLASS_FLOAT | T_SIGN_NONE | T_SIZE_NONE,
|
||||
T_VOID = T_RANK_VOID | T_CLASS_NONE | T_SIGN_NONE | T_SIZE_NONE,
|
||||
T_STRUCT = T_RANK_STRUCT | T_CLASS_STRUCT | T_SIGN_NONE | T_SIZE_NONE,
|
||||
T_UNION = T_RANK_UNION | T_CLASS_STRUCT | T_SIGN_NONE | T_SIZE_NONE,
|
||||
T_ARRAY = T_RANK_ARRAY | T_CLASS_PTR | T_SIGN_NONE | T_SIZE_NONE,
|
||||
T_PTR = T_RANK_PTR | T_CLASS_PTR | T_SIGN_NONE | T_SIZE_NONE,
|
||||
T_FUNC = T_RANK_FUNC | T_CLASS_FUNC | T_SIGN_NONE | T_SIZE_NONE,
|
||||
|
||||
/* More types for convenience */
|
||||
T_C_CHAR = T_CHAR | T_QUAL_CONST,
|
||||
|
@ -316,7 +316,9 @@ unsigned CheckedPSizeOf (const Type* T);
|
|||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE TypeCode GetQualifier (const Type* T)
|
||||
/* Get the qualifier from the given type string */
|
||||
/* Get the qualifier from the given type. This doesn't have a "raw" version
|
||||
** since an underlying type can never be qualified.
|
||||
*/
|
||||
{
|
||||
return (T->C & T_MASK_QUAL);
|
||||
}
|
||||
|
@ -324,66 +326,78 @@ INLINE TypeCode GetQualifier (const Type* T)
|
|||
# define GetQualifier(T) ((T)->C & T_MASK_QUAL)
|
||||
#endif
|
||||
|
||||
TypeCode GetUnderlyingTypeCode (const Type* Type);
|
||||
/* Get the type code of the unqualified underlying type of TCode.
|
||||
** Return TCode if it is not scalar.
|
||||
TypeCode GetUnqualTypeCode (const Type* Type);
|
||||
/* Get the type code of the unqualified underlying type of Type.
|
||||
** Return GetUnqualRawTypeCode (Type) if Type is not scalar.
|
||||
*/
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE TypeCode UnqualifiedType (TypeCode T)
|
||||
/* Return the unqualified type code */
|
||||
INLINE TypeCode GetUnqualRawTypeCode (const Type* T)
|
||||
/* Return the unqualified raw type code */
|
||||
{
|
||||
return (T & ~T_MASK_QUAL);
|
||||
return (T->C & ~T_MASK_QUAL);
|
||||
}
|
||||
#else
|
||||
# define UnqualifiedType(T) ((T) & ~T_MASK_QUAL)
|
||||
# define GetUnqualRawTypeCode(T) ((T)->C & ~T_MASK_QUAL)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE TypeCode GetClass (const Type* T)
|
||||
/* Get the class of a type string */
|
||||
INLINE TypeCode GetTypeClass (const Type* T)
|
||||
/* Get the class of a type. This doesn't have a "raw" version since an
|
||||
** underlying type can never be in a different class.
|
||||
*/
|
||||
{
|
||||
return (T->C & T_MASK_CLASS);
|
||||
}
|
||||
#else
|
||||
# define GetClass(T) ((T)->C & T_MASK_CLASS)
|
||||
# define GetTypeClass(T) ((T)->C & T_MASK_CLASS)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE TypeCode GetTypeRank (const Type* T)
|
||||
/* Get the type rank of a type */
|
||||
{
|
||||
return (GetUnqualTypeCode (T) & T_MASK_RANK);
|
||||
}
|
||||
#else
|
||||
# define GetTypeRank(T) (GetUnqualTypeCode (T) & T_MASK_RANK)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE TypeCode GetSignedness (const Type* T)
|
||||
/* Get the signedness of a type */
|
||||
{
|
||||
return (GetUnderlyingTypeCode (T) & T_MASK_SIGN);
|
||||
return (GetUnqualTypeCode (T) & T_MASK_SIGN);
|
||||
}
|
||||
#else
|
||||
# define GetSignedness(T) (GetUnderlyingTypeCode (T) & T_MASK_SIGN)
|
||||
# define GetSignedness(T) (GetUnqualTypeCode (T) & T_MASK_SIGN)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE TypeCode GetSizeModifier (const Type* T)
|
||||
/* Get the size modifier of a type */
|
||||
{
|
||||
return (GetUnderlyingTypeCode (T) & T_MASK_SIZE);
|
||||
return (GetUnqualTypeCode (T) & T_MASK_SIZE);
|
||||
}
|
||||
#else
|
||||
# define GetSizeModifier(T) (GetUnderlyingTypeCode (T) & T_MASK_SIZE)
|
||||
# define GetSizeModifier(T) (GetUnqualTypeCode (T) & T_MASK_SIZE)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE TypeCode GetRawType (const Type* T)
|
||||
/* Get the raw type */
|
||||
INLINE TypeCode GetRawTypeRank (const Type* T)
|
||||
/* Get the raw type rank of a type */
|
||||
{
|
||||
return (T->C & T_MASK_TYPE);
|
||||
return (T->C & T_MASK_RANK);
|
||||
}
|
||||
#else
|
||||
# define GetRawType(T) ((T)->C & T_MASK_TYPE)
|
||||
# define GetRawTypeRank(T) ((T)->C & T_MASK_RANK)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE TypeCode GetRawSignedness (const Type* T)
|
||||
/* Get the raw signedness of a type */
|
||||
{
|
||||
return ((T)->C & T_MASK_SIGN);
|
||||
return (T->C & T_MASK_SIGN);
|
||||
}
|
||||
#else
|
||||
# define GetRawSignedness(T) ((T)->C & T_MASK_SIGN)
|
||||
|
@ -391,7 +405,7 @@ INLINE TypeCode GetRawSignedness (const Type* T)
|
|||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE TypeCode GetRawSizeModifier (const Type* T)
|
||||
/* Get the size modifier of a raw type */
|
||||
/* Get the raw size modifier of a type */
|
||||
{
|
||||
return (T->C & T_MASK_SIZE);
|
||||
}
|
||||
|
@ -418,7 +432,7 @@ Type* NewPointerTo (const Type* T);
|
|||
** on the heap and may be freed after use.
|
||||
*/
|
||||
|
||||
Type* NewBitFieldType (const Type* T, unsigned BitOffs, unsigned BitWidth);
|
||||
Type* NewBitFieldOf (const Type* T, unsigned BitOffs, unsigned BitWidth);
|
||||
/* Return a type string that is "T : BitWidth" aligned on BitOffs. The type
|
||||
** string is allocated on the heap and may be freed after use.
|
||||
*/
|
||||
|
@ -433,11 +447,6 @@ const Type* Indirect (const Type* T);
|
|||
** given type points to.
|
||||
*/
|
||||
|
||||
Type* IndirectModifiable (Type* T);
|
||||
/* Do one indirection for the given type, that is, return the type where the
|
||||
** given type points to.
|
||||
*/
|
||||
|
||||
Type* ArrayToPtr (const Type* T);
|
||||
/* Convert an array to a pointer to it's first element */
|
||||
|
||||
|
@ -461,17 +470,17 @@ const Type* IntPromotion (const Type* T);
|
|||
const Type* ArithmeticConvert (const Type* lhst, const Type* rhst);
|
||||
/* Perform the usual arithmetic conversions for binary operators. */
|
||||
|
||||
const Type* SignedType (const Type* T);
|
||||
const Type* GetSignedType (const Type* T);
|
||||
/* Get signed counterpart of the integral type */
|
||||
|
||||
const Type* UnsignedType (const Type* T);
|
||||
const Type* GetUnsignedType (const Type* T);
|
||||
/* Get unsigned counterpart of the integral type */
|
||||
|
||||
const Type* GetUnderlyingType (const Type* Type);
|
||||
/* Get the underlying type of an enum or other integer class type */
|
||||
|
||||
const Type* GetStructReplacementType (const Type* SType);
|
||||
/* Get a replacement type for passing a struct/union in the primary register */
|
||||
/* Get a replacement type for passing a struct/union by value in the primary */
|
||||
|
||||
const Type* GetBitFieldChunkType (const Type* Type);
|
||||
/* Get the type needed to operate on the byte chunk containing the bit-field */
|
||||
|
@ -485,155 +494,127 @@ const Type* GetBitFieldChunkType (const Type* Type);
|
|||
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsTypeChar (const Type* T)
|
||||
/* Return true if this is a char type */
|
||||
INLINE int IsRankChar (const Type* T)
|
||||
/* Return true if this is a character type */
|
||||
{
|
||||
return (GetRawType (GetUnderlyingType (T)) == T_TYPE_CHAR);
|
||||
return (GetTypeRank (T) == T_RANK_CHAR);
|
||||
}
|
||||
#else
|
||||
# define IsTypeChar(T) (GetRawType (GetUnderlyingType (T)) == T_TYPE_CHAR)
|
||||
# define IsRankChar(T) (GetTypeRank (T) == T_RANK_CHAR)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsTypeShort (const Type* T)
|
||||
INLINE int IsRankShort (const Type* T)
|
||||
/* Return true if this is a short type (signed or unsigned) */
|
||||
{
|
||||
return (GetRawType (GetUnderlyingType (T)) == T_TYPE_SHORT);
|
||||
return (GetTypeRank (T) == T_RANK_SHORT);
|
||||
}
|
||||
#else
|
||||
# define IsTypeShort(T) (GetRawType (GetUnderlyingType (T)) == T_TYPE_SHORT)
|
||||
# define IsRankShort(T) (GetTypeRank (T) == T_RANK_SHORT)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsTypeInt (const Type* T)
|
||||
INLINE int IsRankInt (const Type* T)
|
||||
/* Return true if this is an int type (signed or unsigned) */
|
||||
{
|
||||
return (GetRawType (GetUnderlyingType (T)) == T_TYPE_INT);
|
||||
return (GetTypeRank (T) == T_RANK_INT);
|
||||
}
|
||||
#else
|
||||
# define IsTypeInt(T) (GetRawType (GetUnderlyingType (T)) == T_TYPE_INT)
|
||||
# define IsRankInt(T) (GetTypeRank (T) == T_RANK_INT)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsTypeLong (const Type* T)
|
||||
INLINE int IsRankLong (const Type* T)
|
||||
/* Return true if this is a long int type (signed or unsigned) */
|
||||
{
|
||||
return (GetRawType (GetUnderlyingType (T)) == T_TYPE_LONG);
|
||||
return (GetTypeRank (T) == T_RANK_LONG);
|
||||
}
|
||||
#else
|
||||
# define IsTypeLong(T) (GetRawType (GetUnderlyingType (T)) == T_TYPE_LONG)
|
||||
# define IsRankLong(T) (GetTypeRank (T) == T_RANK_LONG)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsISOChar (const Type* T)
|
||||
/* Return true if this is a narrow character type (without signed/unsigned) */
|
||||
{
|
||||
return (UnqualifiedType (T->C) == T_CHAR);
|
||||
}
|
||||
#else
|
||||
# define IsISOChar(T) (UnqualifiedType ((T)->C) == T_CHAR)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsClassChar (const Type* T)
|
||||
/* Return true if this is a narrow character type (including signed/unsigned).
|
||||
** For now this is the same as IsRawTypeChar(T).
|
||||
INLINE int IsDeclTypeChar (const Type* T)
|
||||
/* Return true if this is declared as a char type (without signed/unsigned).
|
||||
** This function is to exclude enums whose underlying type is char.
|
||||
*/
|
||||
{
|
||||
return (GetRawType (T) == T_TYPE_CHAR);
|
||||
return (GetUnqualRawTypeCode (T) == T_CHAR);
|
||||
}
|
||||
#else
|
||||
# define IsClassChar(T) (GetRawType (T) == T_TYPE_CHAR)
|
||||
# define IsDeclTypeChar(T) (GetUnqualRawTypeCode (T) == T_CHAR)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsRawTypeChar (const Type* T)
|
||||
/* Return true if this is a char raw type (including signed/unsigned) */
|
||||
INLINE int IsDeclRankChar (const Type* T)
|
||||
/* Return true if this is declared as a character type (including signed/unsigned).
|
||||
** This function is to exclude enums whose underlying types are character types.
|
||||
*/
|
||||
{
|
||||
return (GetRawType (T) == T_TYPE_CHAR);
|
||||
return (GetRawTypeRank (T) == T_RANK_CHAR);
|
||||
}
|
||||
#else
|
||||
# define IsRawTypeChar(T) (GetRawType (T) == T_TYPE_CHAR)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsRawTypeInt (const Type* T)
|
||||
/* Return true if this is an int raw type (signed or unsigned) */
|
||||
{
|
||||
return (GetRawType (T) == T_TYPE_INT);
|
||||
}
|
||||
#else
|
||||
# define IsRawTypeInt(T) (GetRawType (T) == T_TYPE_INT)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsRawTypeLong (const Type* T)
|
||||
/* Return true if this is a long raw type (signed or unsigned) */
|
||||
{
|
||||
return (GetRawType (T) == T_TYPE_LONG);
|
||||
}
|
||||
#else
|
||||
# define IsRawTypeLong(T) (GetRawType (T) == T_TYPE_LONG)
|
||||
# define IsDeclRankChar(T) (GetRawTypeRank (T) == T_RANK_CHAR)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsTypeFloat (const Type* T)
|
||||
/* Return true if this is a float type */
|
||||
{
|
||||
return (GetRawType (T) == T_TYPE_FLOAT);
|
||||
return (GetRawTypeRank (T) == T_RANK_FLOAT);
|
||||
}
|
||||
#else
|
||||
# define IsTypeFloat(T) (GetRawType (T) == T_TYPE_FLOAT)
|
||||
# define IsTypeFloat(T) (GetRawTypeRank (T) == T_RANK_FLOAT)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsTypeDouble (const Type* T)
|
||||
/* Return true if this is a double type */
|
||||
{
|
||||
return (GetRawType (T) == T_TYPE_DOUBLE);
|
||||
return (GetRawTypeRank (T) == T_RANK_DOUBLE);
|
||||
}
|
||||
#else
|
||||
# define IsTypeDouble(T) (GetRawType (T) == T_TYPE_DOUBLE)
|
||||
# define IsTypeDouble(T) (GetRawTypeRank (T) == T_RANK_DOUBLE)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsTypePtr (const Type* T)
|
||||
/* Return true if this is a pointer type */
|
||||
{
|
||||
return (GetRawType (T) == T_TYPE_PTR);
|
||||
return (GetRawTypeRank (T) == T_RANK_PTR);
|
||||
}
|
||||
#else
|
||||
# define IsTypePtr(T) (GetRawType (T) == T_TYPE_PTR)
|
||||
# define IsTypePtr(T) (GetRawTypeRank (T) == T_RANK_PTR)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsTypeEnum (const Type* T)
|
||||
/* Return true if this is an enum type */
|
||||
{
|
||||
return (GetRawType (T) == T_TYPE_ENUM);
|
||||
return (GetRawTypeRank (T) == T_RANK_ENUM);
|
||||
}
|
||||
#else
|
||||
# define IsTypeEnum(T) (GetRawType (T) == T_TYPE_ENUM)
|
||||
# define IsTypeEnum(T) (GetRawTypeRank (T) == T_RANK_ENUM)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsTypeSignedBitField (const Type* T)
|
||||
/* Return true if this is a signed bit-field */
|
||||
{
|
||||
return (UnqualifiedType (T->C) == T_SBITFIELD);
|
||||
return (GetUnqualRawTypeCode (T) == T_SBITFIELD);
|
||||
}
|
||||
#else
|
||||
# define IsTypeSignedBitField(T) (UnqualifiedType ((T)->C) == T_SBITFIELD)
|
||||
# define IsTypeSignedBitField(T) (GetUnqualRawTypeCode (T) == T_SBITFIELD)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsTypeUnsignedBitField (const Type* T)
|
||||
/* Return true if this is an unsigned bit-field */
|
||||
{
|
||||
return (UnqualifiedType (T->C) == T_UBITFIELD);
|
||||
return (GetUnqualRawTypeCode (T) == T_UBITFIELD);
|
||||
}
|
||||
#else
|
||||
# define IsTypeUnsignedBitField(T) (UnqualifiedType ((T)->C) == T_UBITFIELD)
|
||||
# define IsTypeUnsignedBitField(T) (GetUnqualRawTypeCode (T) == T_UBITFIELD)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
|
@ -653,55 +634,55 @@ int IsTypeFragBitField (const Type* T);
|
|||
INLINE int IsTypeStruct (const Type* T)
|
||||
/* Return true if this is a struct type */
|
||||
{
|
||||
return (GetRawType (T) == T_TYPE_STRUCT);
|
||||
return (GetRawTypeRank (T) == T_RANK_STRUCT);
|
||||
}
|
||||
#else
|
||||
# define IsTypeStruct(T) (GetRawType (T) == T_TYPE_STRUCT)
|
||||
# define IsTypeStruct(T) (GetRawTypeRank (T) == T_RANK_STRUCT)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsTypeUnion (const Type* T)
|
||||
/* Return true if this is a union type */
|
||||
{
|
||||
return (GetRawType (T) == T_TYPE_UNION);
|
||||
return (GetRawTypeRank (T) == T_RANK_UNION);
|
||||
}
|
||||
#else
|
||||
# define IsTypeUnion(T) (GetRawType (T) == T_TYPE_UNION)
|
||||
# define IsTypeUnion(T) (GetRawTypeRank (T) == T_RANK_UNION)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsTypeArray (const Type* T)
|
||||
/* Return true if this is an array type */
|
||||
{
|
||||
return (GetRawType (T) == T_TYPE_ARRAY);
|
||||
return (GetRawTypeRank (T) == T_RANK_ARRAY);
|
||||
}
|
||||
#else
|
||||
# define IsTypeArray(T) (GetRawType (T) == T_TYPE_ARRAY)
|
||||
# define IsTypeArray(T) (GetRawTypeRank (T) == T_RANK_ARRAY)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsTypeVoid (const Type* T)
|
||||
/* Return true if this is a void type */
|
||||
{
|
||||
return (GetRawType (T) == T_TYPE_VOID);
|
||||
return (GetRawTypeRank (T) == T_RANK_VOID);
|
||||
}
|
||||
#else
|
||||
# define IsTypeVoid(T) (GetRawType (T) == T_TYPE_VOID)
|
||||
# define IsTypeVoid(T) (GetRawTypeRank (T) == T_RANK_VOID)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsTypeFunc (const Type* T)
|
||||
/* Return true if this is a function class */
|
||||
/* Return true if this is a function type */
|
||||
{
|
||||
return (GetRawType (T) == T_TYPE_FUNC);
|
||||
return (GetRawTypeRank (T) == T_RANK_FUNC);
|
||||
}
|
||||
#else
|
||||
# define IsTypeFunc(T) (GetRawType (T) == T_TYPE_FUNC)
|
||||
# define IsTypeFunc(T) (GetRawTypeRank (T) == T_RANK_FUNC)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsTypeFuncPtr (const Type* T)
|
||||
/* Return true if this is a function pointer */
|
||||
/* Return true if this is a function pointer type */
|
||||
{
|
||||
return (IsTypePtr (T) && IsTypeFunc (T+1));
|
||||
}
|
||||
|
@ -713,71 +694,71 @@ INLINE int IsTypeFuncPtr (const Type* T)
|
|||
INLINE int IsClassInt (const Type* T)
|
||||
/* Return true if this is an integer type */
|
||||
{
|
||||
return (GetClass (T) == T_CLASS_INT);
|
||||
return (GetTypeClass (T) == T_CLASS_INT);
|
||||
}
|
||||
#else
|
||||
# define IsClassInt(T) (GetClass (T) == T_CLASS_INT)
|
||||
# define IsClassInt(T) (GetTypeClass (T) == T_CLASS_INT)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsClassFloat (const Type* T)
|
||||
/* Return true if this is a float type */
|
||||
/* Return true if this is a floating type */
|
||||
{
|
||||
return (GetClass (T) == T_CLASS_FLOAT);
|
||||
return (GetTypeClass (T) == T_CLASS_FLOAT);
|
||||
}
|
||||
#else
|
||||
# define IsClassFloat(T) (GetClass (T) == T_CLASS_FLOAT)
|
||||
# define IsClassFloat(T) (GetTypeClass (T) == T_CLASS_FLOAT)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsClassPtr (const Type* T)
|
||||
/* Return true if this is a pointer type */
|
||||
/* Return true if this is a pointer or array type */
|
||||
{
|
||||
return (GetClass (T) == T_CLASS_PTR);
|
||||
return (GetTypeClass (T) == T_CLASS_PTR);
|
||||
}
|
||||
#else
|
||||
# define IsClassPtr(T) (GetClass (T) == T_CLASS_PTR)
|
||||
# define IsClassPtr(T) (GetTypeClass (T) == T_CLASS_PTR)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsClassStruct (const Type* T)
|
||||
/* Return true if this is a struct or union type */
|
||||
{
|
||||
return (GetClass (T) == T_CLASS_STRUCT);
|
||||
return (GetTypeClass (T) == T_CLASS_STRUCT);
|
||||
}
|
||||
#else
|
||||
# define IsClassStruct(T) (GetClass (T) == T_CLASS_STRUCT)
|
||||
# define IsClassStruct(T) (GetTypeClass (T) == T_CLASS_STRUCT)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsClassFunc (const Type* T)
|
||||
/* Return true if this is a function type */
|
||||
{
|
||||
return (GetClass (T) == T_CLASS_FUNC);
|
||||
return (GetTypeClass (T) == T_CLASS_FUNC);
|
||||
}
|
||||
#else
|
||||
# define IsClassFunc(T) (GetClass (T) == T_CLASS_FUNC)
|
||||
# define IsClassFunc(T) (GetTypeClass (T) == T_CLASS_FUNC)
|
||||
#endif
|
||||
|
||||
int IsClassObject (const Type* T);
|
||||
int IsObjectType (const Type* T);
|
||||
/* Return true if this is a fully described object type */
|
||||
|
||||
int IsClassIncomplete (const Type* T);
|
||||
int IsIncompleteType (const Type* T);
|
||||
/* Return true if this is an object type lacking size info */
|
||||
|
||||
int IsClassArithmetic (const Type* T);
|
||||
/* Return true if this is an integer or real floating type */
|
||||
int IsArithmeticType (const Type* T);
|
||||
/* Return true if this is an integer or floating type */
|
||||
|
||||
int IsClassBasic (const Type* T);
|
||||
int IsBasicType (const Type* T);
|
||||
/* Return true if this is a char, integer or floating type */
|
||||
|
||||
int IsClassScalar (const Type* T);
|
||||
int IsScalarType (const Type* T);
|
||||
/* Return true if this is an arithmetic or pointer type */
|
||||
|
||||
int IsClassDerived (const Type* T);
|
||||
int IsDerivedType (const Type* T);
|
||||
/* Return true if this is an array, struct, union, function or pointer type */
|
||||
|
||||
int IsClassAggregate (const Type* T);
|
||||
int IsAggregateType (const Type* T);
|
||||
/* Return true if this is an array or struct type */
|
||||
|
||||
int IsRelationType (const Type* T);
|
||||
|
@ -798,7 +779,7 @@ int IsEmptiableObjectType (const Type* T);
|
|||
int HasUnknownSize (const Type* T);
|
||||
/* Return true if this is an incomplete ESU type or an array of unknown size */
|
||||
|
||||
int TypeHasAttr (const Type* T);
|
||||
int TypeHasAttrData (const Type* T);
|
||||
/* Return true if the given type has attribute data */
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
|
@ -978,10 +959,10 @@ FuncDesc* GetFuncDesc (const Type* T) attribute ((const));
|
|||
void SetFuncDesc (Type* T, FuncDesc* F);
|
||||
/* Set the FuncDesc pointer in a function or pointer-to-function type */
|
||||
|
||||
const Type* GetFuncReturn (const Type* T) attribute ((const));
|
||||
const Type* GetFuncReturnType (const Type* T) attribute ((const));
|
||||
/* Return a pointer to the return type of a function or pointer-to-function type */
|
||||
|
||||
Type* GetFuncReturnModifiable (Type* T) attribute ((const));
|
||||
Type* GetFuncReturnTypeModifiable (Type* T) attribute ((const));
|
||||
/* Return a non-const pointer to the return type of a function or pointer-to-function type */
|
||||
|
||||
const FuncDesc* GetFuncDefinitionDesc (const Type* T) attribute ((const));
|
||||
|
@ -1006,7 +987,10 @@ void SetElementCount (Type* T, long Count);
|
|||
*/
|
||||
|
||||
const Type* GetElementType (const Type* T);
|
||||
/* Return the element type of the given array type. */
|
||||
/* Return the element type of the given array type */
|
||||
|
||||
Type* GetElementTypeModifiable (Type* T);
|
||||
/* Return the element type of the given array type */
|
||||
|
||||
const Type* GetBaseElementType (const Type* T);
|
||||
/* Return the base element type of a given type. If T is not an array, this
|
||||
|
|
|
@ -406,7 +406,7 @@ static void FixQualifiers (Type* DataType)
|
|||
if (IsTypeArray (T)) {
|
||||
/* Extract any type qualifiers */
|
||||
Q |= GetQualifier (T);
|
||||
T->C = UnqualifiedType (T->C);
|
||||
T->C = GetUnqualRawTypeCode (T);
|
||||
} else {
|
||||
/* Add extracted type qualifiers here */
|
||||
T->C |= Q;
|
||||
|
@ -646,7 +646,7 @@ static SymEntry* ParseEnumSpec (const char* Name, unsigned* DSFlags)
|
|||
/* Enumerate by adding one to the previous value */
|
||||
EnumVal = (long)(((unsigned long)EnumVal + 1UL) & 0xFFFFFFFFUL);
|
||||
|
||||
if (UnqualifiedType (MemberType->C) == T_ULONG && EnumVal == 0) {
|
||||
if (GetUnqualRawTypeCode (MemberType) == T_ULONG && EnumVal == 0) {
|
||||
/* Error since the new value cannot be represented in the
|
||||
** largest unsigned integer type supported by cc65 for enum.
|
||||
*/
|
||||
|
@ -688,7 +688,7 @@ static SymEntry* ParseEnumSpec (const char* Name, unsigned* DSFlags)
|
|||
if (PrevErrorCount == ErrorCount &&
|
||||
IsIncremented &&
|
||||
(!IsSigned || EnumVal >= 0) &&
|
||||
NewType->C != UnqualifiedType (MemberType->C)) {
|
||||
NewType->C != GetUnqualRawTypeCode (MemberType)) {
|
||||
/* The possible overflow here can only be when EnumVal > 0 */
|
||||
Warning ("Enumerator '%s' (value = %lu) implies type '%s'",
|
||||
Ident,
|
||||
|
@ -959,7 +959,7 @@ static SymEntry* ParseUnionSpec (const char* Name, unsigned* DSFlags)
|
|||
}
|
||||
|
||||
/* Check for incomplete types including 'void' */
|
||||
if (IsClassIncomplete (Decl.Type)) {
|
||||
if (IsIncompleteType (Decl.Type)) {
|
||||
Error ("Field '%s' has incomplete type '%s'",
|
||||
Decl.Ident,
|
||||
GetFullTypeName (Decl.Type));
|
||||
|
@ -1159,7 +1159,7 @@ static SymEntry* ParseStructSpec (const char* Name, unsigned* DSFlags)
|
|||
}
|
||||
|
||||
/* Check for incomplete types including 'void' */
|
||||
if (IsClassIncomplete (Decl.Type)) {
|
||||
if (IsIncompleteType (Decl.Type)) {
|
||||
Error ("Field '%s' has incomplete type '%s'",
|
||||
Decl.Ident,
|
||||
GetFullTypeName (Decl.Type));
|
||||
|
@ -2036,7 +2036,7 @@ void ParseDecl (const DeclSpec* Spec, Declarator* D, declmode_t Mode)
|
|||
if (IsTypeFunc (D->Type) || IsTypeFuncPtr (D->Type)) {
|
||||
|
||||
/* A function. Check the return type */
|
||||
Type* RetType = GetFuncReturnModifiable (D->Type);
|
||||
Type* RetType = GetFuncReturnTypeModifiable (D->Type);
|
||||
|
||||
/* Functions may not return functions or arrays */
|
||||
if (IsTypeFunc (RetType)) {
|
||||
|
@ -2048,13 +2048,13 @@ void ParseDecl (const DeclSpec* Spec, Declarator* D, declmode_t Mode)
|
|||
/* The return type must not be qualified */
|
||||
if (GetQualifier (RetType) != T_QUAL_NONE && RetType[1].C == T_END) {
|
||||
|
||||
if (GetRawType (RetType) == T_TYPE_VOID) {
|
||||
if (GetRawTypeRank (RetType) == T_RANK_VOID) {
|
||||
/* A qualified void type is always an error */
|
||||
Error ("function definition has qualified void return type");
|
||||
} else {
|
||||
/* For others, qualifiers are ignored */
|
||||
Warning ("type qualifiers ignored on function return type");
|
||||
RetType[0].C = UnqualifiedType (RetType[0].C);
|
||||
RetType[0].C = GetUnqualRawTypeCode (RetType);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -134,7 +134,7 @@ unsigned TypeOf (const Type* T)
|
|||
{
|
||||
unsigned NewType;
|
||||
|
||||
switch (GetUnderlyingTypeCode (T)) {
|
||||
switch (GetUnqualTypeCode (T)) {
|
||||
|
||||
case T_SCHAR:
|
||||
return CF_CHAR;
|
||||
|
@ -193,7 +193,7 @@ unsigned TypeOf (const Type* T)
|
|||
unsigned FuncTypeOf (const Type* T)
|
||||
/* Get the code generator flag for calling the function */
|
||||
{
|
||||
if (GetUnderlyingTypeCode (T) == T_FUNC) {
|
||||
if (GetUnqualTypeCode (T) == T_FUNC) {
|
||||
return (T->A.F->Flags & FD_VARIADIC) ? 0 : CF_FIXARGC;
|
||||
} else {
|
||||
Error ("Illegal function type %04lX", T->C);
|
||||
|
@ -296,7 +296,7 @@ static unsigned typeadjust (ExprDesc* lhs, const ExprDesc* rhs, int NoPush)
|
|||
void LimitExprValue (ExprDesc* Expr, int WarnOverflow)
|
||||
/* Limit the constant value of the expression to the range of its type */
|
||||
{
|
||||
switch (GetUnderlyingTypeCode (Expr->Type)) {
|
||||
switch (GetUnqualTypeCode (Expr->Type)) {
|
||||
case T_INT:
|
||||
case T_SHORT:
|
||||
if (WarnOverflow && ((Expr->IVal < -0x8000) || (Expr->IVal > 0x7FFF))) {
|
||||
|
@ -1158,7 +1158,7 @@ static void FunctionCall (ExprDesc* Expr)
|
|||
|
||||
/* The function result is an rvalue in the primary register */
|
||||
ED_FinalizeRValLoad (Expr);
|
||||
ReturnType = GetFuncReturn (Expr->Type);
|
||||
ReturnType = GetFuncReturnType (Expr->Type);
|
||||
|
||||
/* Handle struct/union specially */
|
||||
if (IsClassStruct (ReturnType)) {
|
||||
|
@ -2778,7 +2778,7 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */
|
|||
}
|
||||
|
||||
/* Determine the type of the operation. */
|
||||
if (IsTypeChar (Expr->Type) && rconst && (!LeftSigned || RightSigned)) {
|
||||
if (IsRankChar (Expr->Type) && rconst && (!LeftSigned || RightSigned)) {
|
||||
LOG(("hie_compare 1\n"));
|
||||
|
||||
/* Left side is unsigned char, right side is constant.
|
||||
|
@ -2862,7 +2862,7 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */
|
|||
flags |= CF_UNSIGNED;
|
||||
}
|
||||
|
||||
} else if (IsTypeChar (Expr->Type) && IsTypeChar (Expr2.Type) &&
|
||||
} else if (IsRankChar (Expr->Type) && IsRankChar (Expr2.Type) &&
|
||||
GetSignedness (Expr->Type) == GetSignedness (Expr2.Type)) {
|
||||
LOG(("hie_compare 2\n"));
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@ static Function* NewFunction (struct SymEntry* Sym, FuncDesc* D)
|
|||
|
||||
/* Initialize the fields */
|
||||
F->FuncEntry = Sym;
|
||||
F->ReturnType = GetFuncReturn (Sym->Type);
|
||||
F->ReturnType = GetFuncReturnType (Sym->Type);
|
||||
F->Desc = D;
|
||||
F->Reserved = 0;
|
||||
F->RetLab = 0;
|
||||
|
@ -540,7 +540,7 @@ void NewFunc (SymEntry* Func, FuncDesc* D)
|
|||
/* Determine if this is a main function in a C99 environment that
|
||||
** returns an int.
|
||||
*/
|
||||
if (IsRawTypeInt (F_GetReturnType (CurrentFunc)) &&
|
||||
if (GetUnqualRawTypeCode (ReturnType) == T_INT &&
|
||||
IS_Get (&Standard) == STD_C99) {
|
||||
C99MainFunc = 1;
|
||||
}
|
||||
|
|
|
@ -352,12 +352,12 @@ static unsigned ParseArrayInit (Type* T, int* Braces, int AllowFlexibleMembers)
|
|||
int HasCurly = 0;
|
||||
|
||||
/* Get the array data */
|
||||
Type* ElementType = IndirectModifiable (T);
|
||||
Type* ElementType = GetElementTypeModifiable (T);
|
||||
unsigned ElementSize = SizeOf (ElementType);
|
||||
long ElementCount = GetElementCount (T);
|
||||
|
||||
/* Special handling for a character array initialized by a literal */
|
||||
if (IsClassChar (ElementType) &&
|
||||
if (IsDeclRankChar (ElementType) &&
|
||||
(CurTok.Tok == TOK_SCONST || CurTok.Tok == TOK_WCSCONST ||
|
||||
(CurTok.Tok == TOK_LCURLY &&
|
||||
(NextTok.Tok == TOK_SCONST || NextTok.Tok == TOK_WCSCONST)))) {
|
||||
|
@ -691,7 +691,7 @@ static unsigned ParseVoidInit (Type* T)
|
|||
Size = 0;
|
||||
do {
|
||||
ExprDesc Expr = NoCodeConstExpr (hie1);
|
||||
switch (GetUnderlyingTypeCode (&Expr.Type[0])) {
|
||||
switch (GetUnqualTypeCode (&Expr.Type[0])) {
|
||||
|
||||
case T_SCHAR:
|
||||
case T_UCHAR:
|
||||
|
@ -759,7 +759,7 @@ static unsigned ParseVoidInit (Type* T)
|
|||
static unsigned ParseInitInternal (Type* T, int *Braces, int AllowFlexibleMembers)
|
||||
/* Parse initialization of variables. Return the number of data bytes. */
|
||||
{
|
||||
switch (GetUnderlyingTypeCode (T)) {
|
||||
switch (GetUnqualTypeCode (T)) {
|
||||
|
||||
case T_SCHAR:
|
||||
case T_UCHAR:
|
||||
|
|
|
@ -299,6 +299,10 @@ static void SetSys (const char* Sys)
|
|||
DefineNumericMacro ("__SYM1__", 1);
|
||||
break;
|
||||
|
||||
case TGT_KIM1:
|
||||
DefineNumericMacro ("__KIM1__", 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
AbEnd ("Unknown target system '%s'", Sys);
|
||||
}
|
||||
|
|
|
@ -531,7 +531,7 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
|
|||
|
||||
/* The function result is an rvalue in the primary register */
|
||||
ED_FinalizeRValLoad (Expr);
|
||||
Expr->Type = GetFuncReturn (Expr->Type);
|
||||
Expr->Type = GetFuncReturnType (Expr->Type);
|
||||
|
||||
/* Bail out, no need for further processing */
|
||||
goto ExitPoint;
|
||||
|
@ -540,7 +540,7 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
|
|||
|
||||
/* The function result is an rvalue in the primary register */
|
||||
ED_FinalizeRValLoad (Expr);
|
||||
Expr->Type = GetFuncReturn (Expr->Type);
|
||||
Expr->Type = GetFuncReturnType (Expr->Type);
|
||||
|
||||
ExitPoint:
|
||||
/* We expect the closing brace */
|
||||
|
@ -757,7 +757,7 @@ static void StdFunc_memset (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
|
|||
|
||||
/* The function result is an rvalue in the primary register */
|
||||
ED_FinalizeRValLoad (Expr);
|
||||
Expr->Type = GetFuncReturn (Expr->Type);
|
||||
Expr->Type = GetFuncReturnType (Expr->Type);
|
||||
|
||||
/* Bail out, no need for further processing */
|
||||
goto ExitPoint;
|
||||
|
@ -766,7 +766,7 @@ static void StdFunc_memset (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
|
|||
|
||||
/* The function result is an rvalue in the primary register */
|
||||
ED_FinalizeRValLoad (Expr);
|
||||
Expr->Type = GetFuncReturn (Expr->Type);
|
||||
Expr->Type = GetFuncReturnType (Expr->Type);
|
||||
|
||||
ExitPoint:
|
||||
/* We expect the closing brace */
|
||||
|
@ -968,7 +968,7 @@ static void StdFunc_strcmp (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
|
|||
|
||||
/* The function result is an rvalue in the primary register */
|
||||
ED_FinalizeRValLoad (Expr);
|
||||
Expr->Type = GetFuncReturn (Expr->Type);
|
||||
Expr->Type = GetFuncReturnType (Expr->Type);
|
||||
|
||||
/* We expect the closing brace */
|
||||
ConsumeRParen ();
|
||||
|
@ -1165,7 +1165,7 @@ static void StdFunc_strcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
|
|||
|
||||
/* The function result is an rvalue in the primary register */
|
||||
ED_FinalizeRValLoad (Expr);
|
||||
Expr->Type = GetFuncReturn (Expr->Type);
|
||||
Expr->Type = GetFuncReturnType (Expr->Type);
|
||||
|
||||
ExitPoint:
|
||||
/* We expect the closing brace */
|
||||
|
|
|
@ -133,7 +133,7 @@ void SwitchStatement (void)
|
|||
|
||||
/* Setup the control structure, save the old and activate the new one */
|
||||
SwitchData.Nodes = NewCollection ();
|
||||
SwitchData.ExprType = GetUnderlyingTypeCode (&SwitchExpr.Type[0]);
|
||||
SwitchData.ExprType = GetUnqualTypeCode (&SwitchExpr.Type[0]);
|
||||
SwitchData.Depth = SizeOf (SwitchExpr.Type);
|
||||
SwitchData.DefaultLabel = 0;
|
||||
OldSwitch = Switch;
|
||||
|
|
|
@ -1007,7 +1007,7 @@ SymEntry* AddBitField (const char* Name, const Type* T, unsigned Offs,
|
|||
Entry = NewSymEntry (Name, SC_BITFIELD);
|
||||
|
||||
/* Set the symbol attributes. Bit-fields are always integral types. */
|
||||
Entry->Type = NewBitFieldType (T, BitOffs, BitWidth);
|
||||
Entry->Type = NewBitFieldOf (T, BitOffs, BitWidth);
|
||||
Entry->V.Offs = Offs;
|
||||
|
||||
if (!SignednessSpecified) {
|
||||
|
@ -1019,7 +1019,7 @@ SymEntry* AddBitField (const char* Name, const Type* T, unsigned Offs,
|
|||
** `char -> unsigned char` adjustment that is performed with other integral types.
|
||||
*/
|
||||
CHECK ((Entry->Type->C & T_MASK_SIGN) == T_SIGN_SIGNED ||
|
||||
IsTypeChar (Entry->Type));
|
||||
IsRankChar (Entry->Type));
|
||||
Entry->Type[0].C &= ~T_MASK_SIGN;
|
||||
Entry->Type[0].C |= T_SIGN_UNSIGNED;
|
||||
Entry->Type[1].C &= ~T_MASK_SIGN;
|
||||
|
|
|
@ -244,7 +244,7 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
|
|||
SymEntry* Sym2;
|
||||
FuncDesc* F1;
|
||||
FuncDesc* F2;
|
||||
TypeCode LeftType, RightType;
|
||||
TypeCode LeftRank, RightRank;
|
||||
long LeftCount, RightCount;
|
||||
|
||||
|
||||
|
@ -262,9 +262,23 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Get the left and right types */
|
||||
LeftType = (GetUnderlyingTypeCode (lhs) & T_MASK_TYPE);
|
||||
RightType = (GetUnderlyingTypeCode (rhs) & T_MASK_TYPE);
|
||||
/* Get the ranks of the left and right hands */
|
||||
LeftRank = (GetUnqualTypeCode (lhs) & T_MASK_RANK);
|
||||
RightRank = (GetUnqualTypeCode (rhs) & T_MASK_RANK);
|
||||
|
||||
/* If one side is a pointer and the other side is an array, both are
|
||||
** compatible.
|
||||
*/
|
||||
if (Result->Indirections == 0) {
|
||||
if (LeftRank == T_RANK_PTR && RightRank == T_RANK_ARRAY) {
|
||||
RightRank = T_RANK_PTR;
|
||||
SetResult (Result, TC_PTR_DECAY);
|
||||
}
|
||||
if (LeftRank == T_RANK_ARRAY && RightRank == T_RANK_PTR) {
|
||||
LeftRank = T_RANK_PTR;
|
||||
SetResult (Result, TC_STRICT_COMPATIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Bit-fields are considered compatible if they have the same
|
||||
** signedness, bit-offset and bit-width.
|
||||
|
@ -275,29 +289,14 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
|
|||
lhs->A.B.Offs != rhs->A.B.Offs ||
|
||||
lhs->A.B.Width != rhs->A.B.Width) {
|
||||
SetResult (Result, TC_INCOMPATIBLE);
|
||||
return;
|
||||
}
|
||||
if (LeftType != RightType) {
|
||||
if (LeftRank != RightRank) {
|
||||
SetResult (Result, TC_STRICT_COMPATIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
/* If one side is a pointer and the other side is an array, both are
|
||||
** compatible.
|
||||
*/
|
||||
if (Result->Indirections == 0) {
|
||||
if (LeftType == T_TYPE_PTR && RightType == T_TYPE_ARRAY) {
|
||||
RightType = T_TYPE_PTR;
|
||||
SetResult (Result, TC_PTR_DECAY);
|
||||
}
|
||||
if (LeftType == T_TYPE_ARRAY && RightType == T_TYPE_PTR) {
|
||||
LeftType = T_TYPE_PTR;
|
||||
SetResult (Result, TC_STRICT_COMPATIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
/* If the underlying types are not identical, the types are incompatible */
|
||||
if (LeftType != RightType) {
|
||||
/* If the ranks are different, the types are incompatible */
|
||||
if (LeftRank != RightRank) {
|
||||
SetResult (Result, TC_INCOMPATIBLE);
|
||||
return;
|
||||
}
|
||||
|
@ -337,8 +336,8 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
|
|||
}
|
||||
|
||||
/* 'char' is neither 'signed char' nor 'unsigned char' */
|
||||
if ((IsISOChar (lhs) && !IsISOChar (rhs)) ||
|
||||
(!IsISOChar (lhs) && IsISOChar (rhs))) {
|
||||
if ((IsDeclTypeChar (lhs) && !IsDeclTypeChar (rhs)) ||
|
||||
(!IsDeclTypeChar (lhs) && IsDeclTypeChar (rhs))) {
|
||||
SetResult (Result, TC_SIGN_DIFF);
|
||||
}
|
||||
|
||||
|
@ -350,14 +349,14 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
|
|||
}
|
||||
|
||||
/* Check for special type elements */
|
||||
switch (LeftType) {
|
||||
case T_TYPE_PTR:
|
||||
switch (LeftRank) {
|
||||
case T_RANK_PTR:
|
||||
++Result->Indirections;
|
||||
if (Result->Indirections == 1) {
|
||||
if ((GetUnderlyingTypeCode (lhs + 1) & T_MASK_TYPE) == T_TYPE_VOID) {
|
||||
if ((GetUnqualTypeCode (lhs + 1) & T_MASK_RANK) == T_RANK_VOID) {
|
||||
Result->F |= TCF_VOID_PTR_ON_LEFT;
|
||||
}
|
||||
if ((GetUnderlyingTypeCode (rhs + 1) & T_MASK_TYPE) == T_TYPE_VOID) {
|
||||
if ((GetUnqualTypeCode (rhs + 1) & T_MASK_RANK) == T_RANK_VOID) {
|
||||
Result->F |= TCF_VOID_PTR_ON_RIGHT;
|
||||
}
|
||||
} else {
|
||||
|
@ -365,7 +364,7 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
|
|||
}
|
||||
break;
|
||||
|
||||
case T_TYPE_FUNC:
|
||||
case T_RANK_FUNC:
|
||||
/* Compare the function descriptors */
|
||||
F1 = GetFuncDesc (lhs);
|
||||
F2 = GetFuncDesc (rhs);
|
||||
|
@ -399,7 +398,7 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
|
|||
/* Keep on and compare the return type */
|
||||
break;
|
||||
|
||||
case T_TYPE_ARRAY:
|
||||
case T_RANK_ARRAY:
|
||||
/* Check member count */
|
||||
LeftCount = GetElementCount (lhs);
|
||||
RightCount = GetElementCount (rhs);
|
||||
|
@ -420,8 +419,8 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
|
|||
}
|
||||
break;
|
||||
|
||||
case T_TYPE_STRUCT:
|
||||
case T_TYPE_UNION:
|
||||
case T_RANK_STRUCT:
|
||||
case T_RANK_UNION:
|
||||
/* Compare the tag types */
|
||||
Sym1 = GetESUTagSym (lhs);
|
||||
Sym2 = GetESUTagSym (rhs);
|
||||
|
|
|
@ -475,7 +475,7 @@ void TypeComposition (Type* lhs, const Type* rhs)
|
|||
}
|
||||
|
||||
/* Check for sanity */
|
||||
CHECK (GetUnderlyingTypeCode (lhs) == GetUnderlyingTypeCode (rhs));
|
||||
CHECK (GetUnqualTypeCode (lhs) == GetUnqualTypeCode (rhs));
|
||||
|
||||
/* Check for special type elements */
|
||||
if (IsTypeFunc (lhs)) {
|
||||
|
|
|
@ -163,6 +163,7 @@ static const TargetEntry TargetMap[] = {
|
|||
{ "geos", TGT_GEOS_CBM },
|
||||
{ "geos-apple", TGT_GEOS_APPLE },
|
||||
{ "geos-cbm", TGT_GEOS_CBM },
|
||||
{ "kim1", TGT_KIM1 },
|
||||
{ "lunix", TGT_LUNIX },
|
||||
{ "lynx", TGT_LYNX },
|
||||
{ "module", TGT_MODULE },
|
||||
|
@ -219,6 +220,7 @@ static const TargetProperties PropertyTable[TGT_COUNT] = {
|
|||
{ "c65", CPU_4510, BINFMT_BINARY, CTPET },
|
||||
{ "cx16", CPU_65C02, BINFMT_BINARY, CTPET },
|
||||
{ "sym1", CPU_6502, BINFMT_BINARY, CTNone },
|
||||
{ "kim1", CPU_6502, BINFMT_BINARY, CTNone },
|
||||
};
|
||||
|
||||
/* Target system */
|
||||
|
|
|
@ -87,6 +87,7 @@ typedef enum {
|
|||
TGT_C65,
|
||||
TGT_CX16,
|
||||
TGT_SYM1,
|
||||
TGT_KIM1,
|
||||
TGT_COUNT /* Number of target systems */
|
||||
} target_t;
|
||||
|
||||
|
|
|
@ -486,6 +486,18 @@ int xvsnprintf (char* Buf, size_t Size, const char* Format, va_list ap)
|
|||
}
|
||||
break;
|
||||
|
||||
/* support the MSVC specific I64 for long long */
|
||||
case 'I':
|
||||
F = *Format++;
|
||||
if (F == '6') {
|
||||
F = *Format++;
|
||||
if (F == '4') {
|
||||
F = *Format++;
|
||||
P.LengthMod = lmLongLong;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
F = *Format++;
|
||||
if (F == 'l') {
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
|
||||
/* da65 */
|
||||
#include "cpu.h"
|
||||
#include "error.h"
|
||||
#include "attrtab.h"
|
||||
|
||||
|
@ -48,6 +49,12 @@
|
|||
/* Attribute table */
|
||||
static unsigned short AttrTab[0x10000];
|
||||
|
||||
/* 65816 attribute table */
|
||||
#define MAX_LONG_ATTRS 256
|
||||
static unsigned short LongAttrVal[MAX_LONG_ATTRS];
|
||||
static unsigned LongAttrAddr[MAX_LONG_ATTRS];
|
||||
static unsigned LongAttrsUsed;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -59,12 +66,19 @@ static unsigned short AttrTab[0x10000];
|
|||
void AddrCheck (unsigned Addr)
|
||||
/* Check if the given address has a valid range */
|
||||
{
|
||||
if (Addr >= 0x10000) {
|
||||
if (Addr >= 0x10000 && CPU != CPU_65816) {
|
||||
Error ("Address out of range: %08X", Addr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned char IsLongAddr (unsigned Addr)
|
||||
/* Is it 24-bit? */
|
||||
{
|
||||
return Addr >= 0x10000 && CPU == CPU_65816;
|
||||
}
|
||||
|
||||
|
||||
|
||||
attr_t GetAttr (unsigned Addr)
|
||||
/* Return the attribute for the given address */
|
||||
|
@ -72,6 +86,17 @@ attr_t GetAttr (unsigned Addr)
|
|||
/* Check the given address */
|
||||
AddrCheck (Addr);
|
||||
|
||||
if (IsLongAddr (Addr)) {
|
||||
unsigned i;
|
||||
for (i = 0; i < LongAttrsUsed; i++) {
|
||||
if (LongAttrAddr[i] == Addr) {
|
||||
return LongAttrVal[i];
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return the attribute */
|
||||
return AttrTab[Addr];
|
||||
}
|
||||
|
@ -148,6 +173,33 @@ void MarkAddr (unsigned Addr, attr_t Attr)
|
|||
/* Check the given address */
|
||||
AddrCheck (Addr);
|
||||
|
||||
if (IsLongAddr (Addr)) {
|
||||
unsigned i;
|
||||
for (i = 0; i < LongAttrsUsed; i++) {
|
||||
if (LongAttrAddr[i] == Addr) {
|
||||
|
||||
/* We must not have more than one style bit */
|
||||
if (Attr & atStyleMask) {
|
||||
if (LongAttrVal[i] & atStyleMask) {
|
||||
Error ("Duplicate style for long address %06X", Addr);
|
||||
}
|
||||
}
|
||||
LongAttrVal[i] |= Attr;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (LongAttrsUsed >= MAX_LONG_ATTRS) {
|
||||
Error ("Too many long addresses");
|
||||
}
|
||||
LongAttrVal[LongAttrsUsed] |= Attr;
|
||||
LongAttrAddr[LongAttrsUsed] = Addr;
|
||||
LongAttrsUsed++;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* We must not have more than one style bit */
|
||||
if (Attr & atStyleMask) {
|
||||
if (AttrTab[Addr] & atStyleMask) {
|
||||
|
@ -168,7 +220,7 @@ attr_t GetStyleAttr (unsigned Addr)
|
|||
AddrCheck (Addr);
|
||||
|
||||
/* Return the attribute */
|
||||
return (AttrTab[Addr] & atStyleMask);
|
||||
return (GetAttr (Addr) & atStyleMask);
|
||||
}
|
||||
|
||||
|
||||
|
@ -180,5 +232,5 @@ attr_t GetLabelAttr (unsigned Addr)
|
|||
AddrCheck (Addr);
|
||||
|
||||
/* Return the attribute */
|
||||
return (AttrTab[Addr] & atLabelMask);
|
||||
return (GetAttr (Addr) & atLabelMask);
|
||||
}
|
||||
|
|
|
@ -66,15 +66,25 @@ typedef enum attr_t {
|
|||
atDepLabel = 0x0040, /* Dependent label */
|
||||
atUnnamedLabel = 0x0080, /* Unnamed label */
|
||||
|
||||
atLabelDefined = 0x0100, /* True if we defined the label */
|
||||
|
||||
atStyleMask = 0x000F, /* Output style */
|
||||
atLabelMask = 0x00F0, /* Label information */
|
||||
|
||||
/* Segment */
|
||||
atSegment = 0x0100, /* Code is in a segment */
|
||||
atSegmentEnd = 0x0200, /* Segment end */
|
||||
atSegmentStart = 0x0400, /* Segment start */
|
||||
|
||||
/* Table unit separator */
|
||||
atTableUnit = 0x0800,
|
||||
|
||||
/* 65816 addressing mode */
|
||||
atMem8 = 0x1000, /* M flag enabled, 8-bit */
|
||||
atMem16 = 0x2000, /* M flag disabled, 16-bit */
|
||||
atIdx8 = 0x4000, /* X flag enabled, 8-bit */
|
||||
atIdx16 = 0x8000, /* X flag disabled, 16-bit */
|
||||
|
||||
atStyleMask = 0x000F, /* Output style */
|
||||
atLabelMask = 0x00F0, /* Label information */
|
||||
atSegmentMask = 0x0700, /* Segment information */
|
||||
at65816Mask = 0xF000, /* 65816 information */
|
||||
|
||||
} attr_t;
|
||||
|
||||
|
||||
|
@ -88,6 +98,9 @@ typedef enum attr_t {
|
|||
void AddrCheck (unsigned Addr);
|
||||
/* Check if the given address has a valid range */
|
||||
|
||||
unsigned char IsLongAddr (unsigned Addr);
|
||||
/* Check if the given address is 24-bit */
|
||||
|
||||
attr_t GetAttr (unsigned Addr);
|
||||
/* Return the attribute for the given address */
|
||||
|
||||
|
|
|
@ -194,6 +194,17 @@ unsigned long GetCodeDWord (unsigned Addr)
|
|||
|
||||
|
||||
|
||||
unsigned GetCodeLongAddr (unsigned Addr)
|
||||
/* Get a word from the given address */
|
||||
{
|
||||
unsigned Lo = GetCodeByte (Addr);
|
||||
unsigned Mid = GetCodeByte (Addr+1);
|
||||
unsigned Hi = GetCodeByte (Addr+2);
|
||||
return Lo | (Mid << 8) | (Hi << 16);
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned GetRemainingBytes (void)
|
||||
/* Return the number of remaining code bytes */
|
||||
{
|
||||
|
|
|
@ -72,6 +72,9 @@ unsigned GetCodeWord (unsigned Addr);
|
|||
unsigned long GetCodeDWord (unsigned Addr);
|
||||
/* Get a dword from the given address */
|
||||
|
||||
unsigned GetCodeLongAddr (unsigned Addr);
|
||||
/* Get a 24-bit address from the given address */
|
||||
|
||||
unsigned GetRemainingBytes (void);
|
||||
/* Return the number of remaining code bytes */
|
||||
|
||||
|
|
|
@ -52,6 +52,11 @@
|
|||
/* Comment table */
|
||||
static const char* CommentTab[0x10000];
|
||||
|
||||
#define MAX_LONG_COMMENTS 256
|
||||
static const char* LongCommentVal[MAX_LONG_COMMENTS];
|
||||
static unsigned LongCommentAddr[MAX_LONG_COMMENTS];
|
||||
static unsigned LongCommentsUsed;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -60,17 +65,43 @@ static const char* CommentTab[0x10000];
|
|||
|
||||
|
||||
|
||||
static unsigned FindLongIndex (unsigned Addr)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < LongCommentsUsed; i++) {
|
||||
if (LongCommentAddr[i] == Addr) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SetComment (unsigned Addr, const char* Comment)
|
||||
/* Set a comment for the given address */
|
||||
{
|
||||
/* Check the given address */
|
||||
AddrCheck (Addr);
|
||||
|
||||
/* If we do already have a comment, warn and ignore the new one */
|
||||
if (CommentTab[Addr]) {
|
||||
Warning ("Duplicate comment for address $%04X", Addr);
|
||||
if (IsLongAddr (Addr)) {
|
||||
if (FindLongIndex (Addr)) {
|
||||
Warning ("Duplicate comment for address $%06X", Addr);
|
||||
} else {
|
||||
if (LongCommentsUsed >= MAX_LONG_COMMENTS) {
|
||||
Error("Too many long-address comments");
|
||||
}
|
||||
LongCommentVal[LongCommentsUsed] = xstrdup (Comment);
|
||||
LongCommentAddr[LongCommentsUsed] = Addr;
|
||||
LongCommentsUsed++;
|
||||
}
|
||||
} else {
|
||||
CommentTab[Addr] = xstrdup (Comment);
|
||||
/* If we do already have a comment, warn and ignore the new one */
|
||||
if (CommentTab[Addr]) {
|
||||
Warning ("Duplicate comment for address $%04X", Addr);
|
||||
} else {
|
||||
CommentTab[Addr] = xstrdup (Comment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,6 +113,14 @@ const char* GetComment (unsigned Addr)
|
|||
/* Check the given address */
|
||||
AddrCheck (Addr);
|
||||
|
||||
if (IsLongAddr (Addr)) {
|
||||
const unsigned i = FindLongIndex (Addr);
|
||||
if (i < LongCommentsUsed) {
|
||||
return LongCommentVal[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Return the label if any */
|
||||
return CommentTab[Addr];
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ static unsigned GetSpan (attr_t Style)
|
|||
if ((Attr & atStyleMask) != Style) {
|
||||
break;
|
||||
}
|
||||
if ((Attr & (atSegmentStart | atSegmentEnd))) {
|
||||
if ((Attr & (atSegmentStart | atSegmentEnd | atTableUnit))) {
|
||||
break;
|
||||
}
|
||||
++Count;
|
||||
|
|
|
@ -99,7 +99,9 @@ static const char* GetAbsOverride (unsigned Flags, unsigned Addr)
|
|||
** string, otherwise return the empty string.
|
||||
*/
|
||||
{
|
||||
if ((Flags & flAbsOverride) != 0 && Addr < 0x100) {
|
||||
if ((Flags & flFarOverride) != 0 && Addr < 0x10000) {
|
||||
return "f:";
|
||||
} else if ((Flags & flAbsOverride) != 0 && Addr < 0x100) {
|
||||
return "a:";
|
||||
} else {
|
||||
return "";
|
||||
|
@ -121,8 +123,10 @@ static const char* GetAddrArg (unsigned Flags, unsigned Addr)
|
|||
static char Buf [32];
|
||||
if (Addr < 0x100) {
|
||||
xsprintf (Buf, sizeof (Buf), "$%02X", Addr);
|
||||
} else {
|
||||
} else if (Addr < 0x10000) {
|
||||
xsprintf (Buf, sizeof (Buf), "$%04X", Addr);
|
||||
} else {
|
||||
xsprintf (Buf, sizeof (Buf), "$%06X", Addr);
|
||||
}
|
||||
return Buf;
|
||||
}
|
||||
|
@ -229,6 +233,28 @@ void OH_Immediate (const OpcDesc* D)
|
|||
|
||||
|
||||
|
||||
void OH_Immediate65816M (const OpcDesc* D)
|
||||
{
|
||||
if (GetAttr (PC) & atMem16) {
|
||||
OneLine (D, "#$%04X", GetCodeWord (PC+1));
|
||||
} else {
|
||||
OneLine (D, "#$%02X", GetCodeByte (PC+1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void OH_Immediate65816X (const OpcDesc* D)
|
||||
{
|
||||
if (GetAttr (PC) & atIdx16) {
|
||||
OneLine (D, "#$%04X", GetCodeWord (PC+1));
|
||||
} else {
|
||||
OneLine (D, "#$%02X", GetCodeByte (PC+1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void OH_ImmediateWord (const OpcDesc* D)
|
||||
{
|
||||
OneLine (D, "#$%04X", GetCodeWord (PC+1));
|
||||
|
@ -322,14 +348,28 @@ void OH_AbsoluteY (const OpcDesc* D)
|
|||
|
||||
void OH_AbsoluteLong (const OpcDesc* D attribute ((unused)))
|
||||
{
|
||||
Error ("Not implemented");
|
||||
/* Get the operand */
|
||||
unsigned Addr = GetCodeLongAddr (PC+1);
|
||||
|
||||
/* Generate a label in pass 1 */
|
||||
GenerateLabel (D->Flags, Addr);
|
||||
|
||||
/* Output the line */
|
||||
OneLine (D, "%s%s", GetAbsOverride (D->Flags, Addr), GetAddrArg (D->Flags, Addr));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void OH_AbsoluteLongX (const OpcDesc* D attribute ((unused)))
|
||||
{
|
||||
Error ("Not implemented");
|
||||
/* Get the operand */
|
||||
unsigned Addr = GetCodeLongAddr (PC+1);
|
||||
|
||||
/* Generate a label in pass 1 */
|
||||
GenerateLabel (D->Flags, Addr);
|
||||
|
||||
/* Output the line */
|
||||
OneLine (D, "%s%s,x", GetAbsOverride (D->Flags, Addr), GetAddrArg (D->Flags, Addr));
|
||||
}
|
||||
|
||||
|
||||
|
@ -358,7 +398,17 @@ void OH_Relative (const OpcDesc* D)
|
|||
|
||||
void OH_RelativeLong (const OpcDesc* D attribute ((unused)))
|
||||
{
|
||||
Error ("Not implemented");
|
||||
/* Get the operand */
|
||||
signed short Offs = GetCodeWord (PC+1);
|
||||
|
||||
/* Calculate the target address */
|
||||
unsigned Addr = (((int) PC+3) + Offs) & 0xFFFF;
|
||||
|
||||
/* Generate a label in pass 1 */
|
||||
GenerateLabel (D->Flags, Addr);
|
||||
|
||||
/* Output the line */
|
||||
OneLine (D, "%s", GetAddrArg (D->Flags, Addr));
|
||||
}
|
||||
|
||||
|
||||
|
@ -541,14 +591,15 @@ void OH_ImmediateAbsoluteX (const OpcDesc* D)
|
|||
|
||||
void OH_StackRelative (const OpcDesc* D attribute ((unused)))
|
||||
{
|
||||
Error ("Not implemented");
|
||||
/* Output the line */
|
||||
OneLine (D, "$%02X,s", GetCodeByte (PC+1));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void OH_DirectIndirectLongX (const OpcDesc* D attribute ((unused)))
|
||||
{
|
||||
Error ("Not implemented");
|
||||
Error ("Not implemented %s", __FUNCTION__);
|
||||
}
|
||||
|
||||
|
||||
|
@ -571,14 +622,28 @@ void OH_StackRelativeIndirectY4510 (const OpcDesc* D attribute ((unused)))
|
|||
|
||||
void OH_DirectIndirectLong (const OpcDesc* D attribute ((unused)))
|
||||
{
|
||||
Error ("Not implemented");
|
||||
/* Get the operand */
|
||||
unsigned Addr = GetCodeByte (PC+1);
|
||||
|
||||
/* Generate a label in pass 1 */
|
||||
GenerateLabel (D->Flags, Addr);
|
||||
|
||||
/* Output the line */
|
||||
OneLine (D, "[%s]", GetAddrArg (D->Flags, Addr));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void OH_DirectIndirectLongY (const OpcDesc* D attribute ((unused)))
|
||||
{
|
||||
Error ("Not implemented");
|
||||
/* Get the operand */
|
||||
unsigned Addr = GetCodeByte (PC+1);
|
||||
|
||||
/* Generate a label in pass 1 */
|
||||
GenerateLabel (D->Flags, Addr);
|
||||
|
||||
/* Output the line */
|
||||
OneLine (D, "[%s],y", GetAddrArg (D->Flags, Addr));
|
||||
}
|
||||
|
||||
|
||||
|
@ -613,6 +678,19 @@ void OH_BlockMove (const OpcDesc* D)
|
|||
|
||||
|
||||
|
||||
void OH_BlockMove65816 (const OpcDesc* D)
|
||||
{
|
||||
/* Get source operand */
|
||||
unsigned Src = GetCodeByte (PC+2);
|
||||
/* Get destination operand */
|
||||
unsigned Dst = GetCodeByte (PC+1);
|
||||
|
||||
/* Output the line */
|
||||
OneLine (D, "#$%02X, #$%02X", Src, Dst);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void OH_AbsoluteXIndirect (const OpcDesc* D attribute ((unused)))
|
||||
{
|
||||
/* Get the operand */
|
||||
|
|
|
@ -57,6 +57,8 @@ void OH_Illegal (const OpcDesc* D attribute ((unused)));
|
|||
void OH_Accumulator (const OpcDesc*);
|
||||
void OH_Implicit (const OpcDesc*);
|
||||
void OH_Immediate (const OpcDesc*);
|
||||
void OH_Immediate65816M (const OpcDesc*);
|
||||
void OH_Immediate65816X (const OpcDesc*);
|
||||
void OH_ImmediateWord (const OpcDesc*);
|
||||
void OH_Direct (const OpcDesc*);
|
||||
void OH_DirectX (const OpcDesc*);
|
||||
|
@ -89,6 +91,7 @@ void OH_StackRelativeIndirectY4510 (const OpcDesc*);
|
|||
void OH_DirectIndirectLong (const OpcDesc*);
|
||||
void OH_DirectIndirectLongY (const OpcDesc*);
|
||||
void OH_BlockMove (const OpcDesc*);
|
||||
void OH_BlockMove65816 (const OpcDesc*);
|
||||
void OH_AbsoluteXIndirect (const OpcDesc*);
|
||||
|
||||
/* Mitsubishi 740 */
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#if defined(_MSC_VER)
|
||||
/* Microsoft compiler */
|
||||
|
@ -521,11 +522,13 @@ static void RangeSection (void)
|
|||
/* Parse a range section */
|
||||
{
|
||||
static const IdentTok RangeDefs[] = {
|
||||
{ "COMMENT", INFOTOK_COMMENT },
|
||||
{ "END", INFOTOK_END },
|
||||
{ "NAME", INFOTOK_NAME },
|
||||
{ "START", INFOTOK_START },
|
||||
{ "TYPE", INFOTOK_TYPE },
|
||||
{ "COMMENT", INFOTOK_COMMENT },
|
||||
{ "END", INFOTOK_END },
|
||||
{ "NAME", INFOTOK_NAME },
|
||||
{ "START", INFOTOK_START },
|
||||
{ "TYPE", INFOTOK_TYPE },
|
||||
{ "ADDRMODE", INFOTOK_ADDRMODE },
|
||||
{ "UNIT", INFOTOK_UNIT },
|
||||
};
|
||||
|
||||
static const IdentTok TypeDefs[] = {
|
||||
|
@ -543,12 +546,14 @@ static void RangeSection (void)
|
|||
|
||||
/* Which values did we get? */
|
||||
enum {
|
||||
tNone = 0x00,
|
||||
tStart = 0x01,
|
||||
tEnd = 0x02,
|
||||
tType = 0x04,
|
||||
tName = 0x08,
|
||||
tComment= 0x10,
|
||||
tNone = 0x00,
|
||||
tStart = 0x01,
|
||||
tEnd = 0x02,
|
||||
tType = 0x04,
|
||||
tName = 0x08,
|
||||
tComment = 0x10,
|
||||
tAddrMode = 0x20,
|
||||
tUnit = 0x40,
|
||||
tNeeded = (tStart | tEnd | tType)
|
||||
};
|
||||
unsigned Attributes = tNone;
|
||||
|
@ -557,9 +562,11 @@ static void RangeSection (void)
|
|||
unsigned Start = 0;
|
||||
unsigned End = 0;
|
||||
unsigned char Type = 0;
|
||||
unsigned AddrMode = 0;
|
||||
char* Name = 0;
|
||||
char* Comment = 0;
|
||||
unsigned MemberSize = 0;
|
||||
unsigned Unit = 0;
|
||||
|
||||
|
||||
/* Skip the token */
|
||||
|
@ -647,6 +654,46 @@ static void RangeSection (void)
|
|||
InfoNextTok ();
|
||||
break;
|
||||
|
||||
case INFOTOK_ADDRMODE:
|
||||
AddAttr ("ADDRMODE", &Attributes, tAddrMode);
|
||||
InfoNextTok ();
|
||||
InfoAssureStr ();
|
||||
if (InfoSVal[0] == '\0') {
|
||||
InfoError ("AddrMode may not be empty");
|
||||
}
|
||||
if (InfoSVal[1] == '\0') {
|
||||
InfoError ("AddrMode must be two characters long");
|
||||
}
|
||||
if (tolower(InfoSVal[0]) == 'm') {
|
||||
if (InfoSVal[0] == 'm') {
|
||||
AddrMode = atMem16;
|
||||
} else {
|
||||
AddrMode = atMem8;
|
||||
}
|
||||
} else {
|
||||
InfoError ("AddrMode syntax: mx");
|
||||
}
|
||||
if (tolower(InfoSVal[1]) == 'x') {
|
||||
if (InfoSVal[1] == 'x') {
|
||||
AddrMode |= atIdx16;
|
||||
} else {
|
||||
AddrMode |= atIdx8;
|
||||
}
|
||||
} else {
|
||||
InfoError ("AddrMode syntax: mx");
|
||||
}
|
||||
InfoNextTok ();
|
||||
break;
|
||||
|
||||
case INFOTOK_UNIT:
|
||||
AddAttr ("UNIT", &Attributes, tUnit);
|
||||
InfoNextTok ();
|
||||
InfoAssureInt ();
|
||||
InfoRangeCheck (0x0002, 0xFFFF);
|
||||
Unit = InfoIVal;
|
||||
InfoNextTok ();
|
||||
break;
|
||||
|
||||
default:
|
||||
Internal ("Unexpected token: %u", InfoTok);
|
||||
}
|
||||
|
@ -661,6 +708,35 @@ static void RangeSection (void)
|
|||
InfoError ("Required values missing from this section");
|
||||
}
|
||||
|
||||
if (CPU == CPU_65816) {
|
||||
if (Type == atCode && !(Attributes & tAddrMode)) {
|
||||
InfoError ("65816 code sections require addressing mode");
|
||||
}
|
||||
if (Type != atCode && (Attributes & tAddrMode)) {
|
||||
InfoError ("AddrMode is only valid for code sections");
|
||||
}
|
||||
}
|
||||
|
||||
/* Only tables support unit sizes */
|
||||
if ((Attributes & tUnit) &&
|
||||
Type != atAddrTab &&
|
||||
Type != atByteTab &&
|
||||
Type != atDByteTab &&
|
||||
Type != atDWordTab &&
|
||||
Type != atRtsTab &&
|
||||
Type != atTextTab &&
|
||||
Type != atWordTab) {
|
||||
InfoError ("Only table types support unit size");
|
||||
}
|
||||
|
||||
/* Mark each unit separator */
|
||||
if (Attributes & tUnit) {
|
||||
unsigned i;
|
||||
for (i = Start; i < End; i += Unit) {
|
||||
MarkAddr(i, atTableUnit);
|
||||
}
|
||||
}
|
||||
|
||||
/* Start must be less than end */
|
||||
if (Start > End) {
|
||||
InfoError ("Start value must not be greater than end value");
|
||||
|
@ -672,7 +748,7 @@ static void RangeSection (void)
|
|||
}
|
||||
|
||||
/* Set the range */
|
||||
MarkRange (Start, End, Type);
|
||||
MarkRange (Start, End, Type | AddrMode);
|
||||
|
||||
/* Do we have a label? */
|
||||
if (Attributes & tName) {
|
||||
|
|
|
@ -60,6 +60,12 @@
|
|||
/* Symbol table */
|
||||
static const char* SymTab[0x10000];
|
||||
|
||||
/* 65816 symbol table */
|
||||
#define MAX_LONG_LABELS 256
|
||||
static const char* LongSymVal[MAX_LONG_LABELS];
|
||||
static unsigned LongSymAddr[MAX_LONG_LABELS];
|
||||
static unsigned LongLabelsUsed;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -74,12 +80,27 @@ static const char* MakeLabelName (unsigned Addr)
|
|||
*/
|
||||
{
|
||||
static char LabelBuf [32];
|
||||
xsprintf (LabelBuf, sizeof (LabelBuf), "L%04X", Addr);
|
||||
xsprintf (LabelBuf, sizeof (LabelBuf),
|
||||
IsLongAddr (Addr) ? "L%06X" : "L%04X", Addr);
|
||||
return LabelBuf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static unsigned FindLongIndex (unsigned Addr)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < LongLabelsUsed; i++) {
|
||||
if (LongSymAddr[i] == Addr) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void AddLabel (unsigned Addr, attr_t Attr, const char* Name)
|
||||
/* Add a label */
|
||||
{
|
||||
|
@ -91,19 +112,41 @@ static void AddLabel (unsigned Addr, attr_t Attr, const char* Name)
|
|||
/* Allow redefinition if identical. Beware: Unnamed labels don't
|
||||
** have a name (you guessed that, didn't you?).
|
||||
*/
|
||||
if (ExistingAttr == Attr &&
|
||||
((Name == 0 && SymTab[Addr] == 0) ||
|
||||
(Name != 0 && SymTab[Addr] != 0 &&
|
||||
strcmp (SymTab[Addr], Name) == 0))) {
|
||||
return;
|
||||
if (IsLongAddr (Addr)) {
|
||||
const unsigned i = FindLongIndex (Addr);
|
||||
if (ExistingAttr == Attr &&
|
||||
((Name == 0 && LongSymVal[i] == 0) ||
|
||||
(Name != 0 && LongSymVal[i] != 0 &&
|
||||
strcmp (LongSymVal[i], Name) == 0))) {
|
||||
return;
|
||||
}
|
||||
Error ("Duplicate label for address $%06X (%s): '%s'", Addr,
|
||||
LongSymVal[i] == 0 ? "<unnamed label>" : LongSymVal[i],
|
||||
Name == 0 ? "<unnamed label>" : Name);
|
||||
} else {
|
||||
if (ExistingAttr == Attr &&
|
||||
((Name == 0 && SymTab[Addr] == 0) ||
|
||||
(Name != 0 && SymTab[Addr] != 0 &&
|
||||
strcmp (SymTab[Addr], Name) == 0))) {
|
||||
return;
|
||||
}
|
||||
Error ("Duplicate label for address $%04X (%s): '%s'", Addr,
|
||||
SymTab[Addr] == 0 ? "<unnamed label>" : SymTab[Addr],
|
||||
Name == 0 ? "<unnamed label>" : Name);
|
||||
}
|
||||
Error ("Duplicate label for address $%04X (%s): '%s'", Addr,
|
||||
SymTab[Addr] == 0 ? "<unnamed label>" : SymTab[Addr],
|
||||
Name == 0 ? "<unnamed label>" : Name);
|
||||
}
|
||||
|
||||
/* Create a new label (xstrdup will return NULL if input NULL) */
|
||||
SymTab[Addr] = xstrdup (Name);
|
||||
if (IsLongAddr (Addr)) {
|
||||
if (LongLabelsUsed >= MAX_LONG_LABELS) {
|
||||
Error ("Too many long labels");
|
||||
}
|
||||
LongSymAddr[LongLabelsUsed] = Addr;
|
||||
LongSymVal[LongLabelsUsed] = xstrdup (Name);
|
||||
LongLabelsUsed++;
|
||||
} else {
|
||||
SymTab[Addr] = xstrdup (Name);
|
||||
}
|
||||
|
||||
/* Remember the attribute */
|
||||
MarkAddr (Addr, Attr);
|
||||
|
@ -254,6 +297,10 @@ const char* GetLabelName (unsigned Addr)
|
|||
*/
|
||||
if (A == atUnnamedLabel) {
|
||||
return "";
|
||||
} else if (IsLongAddr (Addr)) {
|
||||
/* Return the label if any */
|
||||
const unsigned i = FindLongIndex (Addr);
|
||||
return i < LongLabelsUsed ? LongSymVal[i] : NULL;
|
||||
} else {
|
||||
/* Return the label if any */
|
||||
return SymTab[Addr];
|
||||
|
@ -327,6 +374,10 @@ const char* GetLabel (unsigned Addr, unsigned RefFrom)
|
|||
return FwdLabels[Count-1];
|
||||
}
|
||||
|
||||
} else if (IsLongAddr (Addr)) {
|
||||
/* Return the label if any */
|
||||
const unsigned i = FindLongIndex (Addr);
|
||||
return i < LongLabelsUsed ? LongSymVal[i] : NULL;
|
||||
} else {
|
||||
/* Return the label if any */
|
||||
return SymTab[Addr];
|
||||
|
@ -371,7 +422,13 @@ static void DefOutOfRangeLabel (unsigned long Addr)
|
|||
|
||||
case atIntLabel:
|
||||
case atExtLabel:
|
||||
DefConst (SymTab[Addr], GetComment (Addr), Addr);
|
||||
if (IsLongAddr (Addr)) {
|
||||
const unsigned i = FindLongIndex (Addr);
|
||||
DefConst (i < LongLabelsUsed ? LongSymVal[i] : NULL,
|
||||
GetComment (Addr), Addr);
|
||||
} else {
|
||||
DefConst (SymTab[Addr], GetComment (Addr), Addr);
|
||||
}
|
||||
break;
|
||||
|
||||
case atUnnamedLabel:
|
||||
|
@ -390,6 +447,7 @@ void DefOutOfRangeLabels (void)
|
|||
/* Output any labels that are out of the loaded code range */
|
||||
{
|
||||
unsigned long Addr;
|
||||
unsigned i;
|
||||
|
||||
SeparatorLine ();
|
||||
|
||||
|
@ -412,5 +470,10 @@ void DefOutOfRangeLabels (void)
|
|||
DefOutOfRangeLabel (Addr++);
|
||||
}
|
||||
|
||||
/* 65816 long range */
|
||||
for (i = 0; i < LongLabelsUsed; i++) {
|
||||
DefOutOfRangeLabel (LongSymAddr[i]);
|
||||
}
|
||||
|
||||
SeparatorLine ();
|
||||
}
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
#include "data.h"
|
||||
#include "error.h"
|
||||
#include "global.h"
|
||||
#include "handler.h"
|
||||
#include "infofile.h"
|
||||
#include "labels.h"
|
||||
#include "opctable.h"
|
||||
|
@ -63,6 +64,8 @@
|
|||
#include "segment.h"
|
||||
|
||||
|
||||
static unsigned PrevAddrMode;
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
|
@ -427,8 +430,13 @@ static void OneOpcode (unsigned RemainingBytes)
|
|||
switch (Style) {
|
||||
|
||||
case atDefault:
|
||||
D->Handler (D);
|
||||
PC += D->Size;
|
||||
if (CPU == CPU_65816) {
|
||||
DataByteLine (1);
|
||||
++PC;
|
||||
} else {
|
||||
D->Handler (D);
|
||||
PC += D->Size;
|
||||
}
|
||||
break;
|
||||
|
||||
case atCode:
|
||||
|
@ -436,12 +444,36 @@ static void OneOpcode (unsigned RemainingBytes)
|
|||
** following insn, fall through to byte mode.
|
||||
*/
|
||||
if (D->Size <= RemainingBytes) {
|
||||
if (CPU == CPU_65816) {
|
||||
const unsigned AddrMode = GetAttr (PC) & at65816Mask;
|
||||
if (PrevAddrMode != AddrMode) {
|
||||
if ((PrevAddrMode & atMem8) != (AddrMode & atMem8) ||
|
||||
(PrevAddrMode & atMem16) != (AddrMode & atMem16)) {
|
||||
OutputMFlag(!!(AddrMode & atMem8));
|
||||
}
|
||||
if ((PrevAddrMode & atIdx8) != (AddrMode & atIdx8) ||
|
||||
(PrevAddrMode & atIdx16) != (AddrMode & atIdx16)) {
|
||||
OutputXFlag(!!(AddrMode & atIdx8));
|
||||
}
|
||||
|
||||
PrevAddrMode = AddrMode;
|
||||
}
|
||||
}
|
||||
|
||||
/* Output labels within the next insn */
|
||||
for (I = 1; I < D->Size; ++I) {
|
||||
ForwardLabel (I);
|
||||
}
|
||||
/* Output the insn */
|
||||
D->Handler (D);
|
||||
if (CPU == CPU_65816 && (D->Flags & flSizeChanges)) {
|
||||
if ((D->Handler == OH_Immediate65816M &&
|
||||
GetAttr (PC) & atMem16) ||
|
||||
(D->Handler == OH_Immediate65816X &&
|
||||
GetAttr (PC) & atIdx16)) {
|
||||
PC++;
|
||||
}
|
||||
}
|
||||
PC += D->Size;
|
||||
break;
|
||||
}
|
||||
|
@ -503,6 +535,8 @@ static void OnePass (void)
|
|||
{
|
||||
unsigned Count;
|
||||
|
||||
PrevAddrMode = 0;
|
||||
|
||||
/* Disassemble until nothing left */
|
||||
while ((Count = GetRemainingBytes()) > 0) {
|
||||
OneOpcode (Count);
|
||||
|
|
|
@ -56,13 +56,13 @@ const OpcDesc OpcTable_65816[256] = {
|
|||
{ "asl", 2, flUseLabel, OH_Direct }, /* $06 */
|
||||
{ "ora", 2, flUseLabel, OH_DirectIndirectLong }, /* $07 */
|
||||
{ "php", 1, flNone, OH_Implicit }, /* $08 */
|
||||
{ "ora", 2, flNone, OH_Immediate }, /* $09 */
|
||||
{ "ora", 2, flSizeChanges, OH_Immediate65816M }, /* $09 */
|
||||
{ "asl", 1, flNone, OH_Accumulator }, /* $0a */
|
||||
{ "phd", 1, flNone, OH_Implicit }, /* $0b */
|
||||
{ "tsb", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $0c */
|
||||
{ "ora", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $0d */
|
||||
{ "asl", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $0e */
|
||||
{ "ora", 4, flUseLabel, OH_AbsoluteLong }, /* $0f */
|
||||
{ "ora", 4, flUseLabel|flFarOverride, OH_AbsoluteLong }, /* $0f */
|
||||
{ "bpl", 2, flLabel, OH_Relative }, /* $10 */
|
||||
{ "ora", 2, flUseLabel, OH_DirectIndirectY }, /* $11 */
|
||||
{ "ora", 2, flUseLabel, OH_DirectIndirect }, /* $12 */
|
||||
|
@ -78,23 +78,23 @@ const OpcDesc OpcTable_65816[256] = {
|
|||
{ "trb", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $1c */
|
||||
{ "ora", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $1d */
|
||||
{ "asl", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $1e */
|
||||
{ "ora", 4, flUseLabel, OH_AbsoluteLongX }, /* $1f */
|
||||
{ "ora", 4, flUseLabel|flFarOverride, OH_AbsoluteLongX }, /* $1f */
|
||||
{ "jsr", 3, flLabel, OH_JsrAbsolute }, /* $20 */
|
||||
{ "and", 2, flUseLabel, OH_DirectXIndirect }, /* $21 */
|
||||
{ "jsl", 3, flLabel, OH_AbsoluteLong }, /* $22 */
|
||||
{ "jsl", 4, flLabel|flFarOverride, OH_AbsoluteLong }, /* $22 */
|
||||
{ "and", 2, flNone, OH_StackRelative }, /* $23 */
|
||||
{ "bit", 2, flUseLabel, OH_Direct }, /* $24 */
|
||||
{ "and", 2, flUseLabel, OH_Direct }, /* $25 */
|
||||
{ "rol", 2, flUseLabel, OH_Direct }, /* $26 */
|
||||
{ "and", 2, flUseLabel, OH_DirectIndirectLong }, /* $27 */
|
||||
{ "plp", 1, flNone, OH_Implicit }, /* $28 */
|
||||
{ "and", 2, flNone, OH_Immediate }, /* $29 */
|
||||
{ "and", 2, flSizeChanges, OH_Immediate65816M }, /* $29 */
|
||||
{ "rol", 1, flNone, OH_Accumulator }, /* $2a */
|
||||
{ "pld", 1, flNone, OH_Implicit }, /* $2b */
|
||||
{ "bit", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2c */
|
||||
{ "and", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2d */
|
||||
{ "rol", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2e */
|
||||
{ "and", 4, flUseLabel, OH_AbsoluteLong }, /* $2f */
|
||||
{ "and", 4, flUseLabel|flFarOverride, OH_AbsoluteLong }, /* $2f */
|
||||
{ "bmi", 2, flLabel, OH_Relative }, /* $30 */
|
||||
{ "and", 2, flUseLabel, OH_DirectIndirectY }, /* $31 */
|
||||
{ "and", 2, flUseLabel, OH_DirectIndirect }, /* $32 */
|
||||
|
@ -110,28 +110,28 @@ const OpcDesc OpcTable_65816[256] = {
|
|||
{ "bit", 3, flUseLabel, OH_AbsoluteX }, /* $3c */
|
||||
{ "and", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $3d */
|
||||
{ "rol", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $3e */
|
||||
{ "and", 4, flUseLabel, OH_AbsoluteLongX }, /* $3f */
|
||||
{ "and", 4, flUseLabel|flFarOverride, OH_AbsoluteLongX }, /* $3f */
|
||||
{ "rti", 1, flNone, OH_Rts }, /* $40 */
|
||||
{ "eor", 2, flUseLabel, OH_DirectXIndirect }, /* $41 */
|
||||
{ "wdm", 2, flNone, OH_Implicit }, /* $42 */
|
||||
{ "eor", 2, flNone, OH_StackRelative }, /* $43 */
|
||||
{ "mvp", 3, flNone, OH_BlockMove }, /* $44 */
|
||||
{ "mvp", 3, flNone, OH_BlockMove65816 }, /* $44 */
|
||||
{ "eor", 2, flUseLabel, OH_Direct }, /* $45 */
|
||||
{ "lsr", 2, flUseLabel, OH_Direct }, /* $46 */
|
||||
{ "eor", 2, flUseLabel, OH_DirectIndirectLong }, /* $47 */
|
||||
{ "pha", 1, flNone, OH_Implicit }, /* $48 */
|
||||
{ "eor", 2, flNone, OH_Immediate }, /* $49 */
|
||||
{ "eor", 2, flSizeChanges, OH_Immediate65816M }, /* $49 */
|
||||
{ "lsr", 1, flNone, OH_Accumulator }, /* $4a */
|
||||
{ "phk", 1, flNone, OH_Implicit }, /* $4b */
|
||||
{ "jmp", 3, flLabel, OH_JmpAbsolute }, /* $4c */
|
||||
{ "eor", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $4d */
|
||||
{ "lsr", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $4e */
|
||||
{ "eor", 4, flUseLabel, OH_AbsoluteLong }, /* $4f */
|
||||
{ "eor", 4, flUseLabel|flFarOverride, OH_AbsoluteLong }, /* $4f */
|
||||
{ "bvc", 2, flLabel, OH_Relative }, /* $50 */
|
||||
{ "eor", 2, flUseLabel, OH_DirectIndirectY }, /* $51 */
|
||||
{ "eor", 2, flUseLabel, OH_DirectIndirect }, /* $52 */
|
||||
{ "eor", 2, flNone, OH_StackRelativeIndirectY}, /* $53 */
|
||||
{ "mvn", 3, flNone, OH_BlockMove }, /* $54 */
|
||||
{ "mvn", 3, flNone, OH_BlockMove65816 }, /* $54 */
|
||||
{ "eor", 2, flUseLabel, OH_DirectX }, /* $55 */
|
||||
{ "lsr", 2, flUseLabel, OH_DirectX }, /* $56 */
|
||||
{ "eor", 2, flUseLabel, OH_DirectIndirectLongY }, /* $57 */
|
||||
|
@ -139,10 +139,10 @@ const OpcDesc OpcTable_65816[256] = {
|
|||
{ "eor", 3, flUseLabel, OH_AbsoluteY }, /* $59 */
|
||||
{ "phy", 1, flNone, OH_Implicit }, /* $5a */
|
||||
{ "tcd", 1, flNone, OH_Implicit }, /* $5b */
|
||||
{ "jml", 4, flLabel, OH_AbsoluteLong }, /* $5c */
|
||||
{ "jml", 4, flLabel|flFarOverride, OH_AbsoluteLong }, /* $5c */
|
||||
{ "eor", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $5d */
|
||||
{ "lsr", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $5e */
|
||||
{ "eor", 4, flUseLabel, OH_AbsoluteLongX }, /* $5f */
|
||||
{ "eor", 4, flUseLabel|flFarOverride, OH_AbsoluteLongX }, /* $5f */
|
||||
{ "rts", 1, flNone, OH_Rts }, /* $60 */
|
||||
{ "adc", 2, flUseLabel, OH_DirectXIndirect }, /* $61 */
|
||||
{ "per", 3, flLabel, OH_RelativeLong }, /* $62 */
|
||||
|
@ -152,13 +152,13 @@ const OpcDesc OpcTable_65816[256] = {
|
|||
{ "ror", 2, flUseLabel, OH_Direct }, /* $66 */
|
||||
{ "adc", 2, flUseLabel, OH_DirectIndirectLong }, /* $67 */
|
||||
{ "pla", 1, flNone, OH_Implicit }, /* $68 */
|
||||
{ "adc", 2, flNone, OH_Immediate }, /* $69 */
|
||||
{ "adc", 2, flSizeChanges, OH_Immediate65816M }, /* $69 */
|
||||
{ "ror", 1, flNone, OH_Accumulator }, /* $6a */
|
||||
{ "rtl", 1, flNone, OH_Implicit }, /* $6b */
|
||||
{ "jmp", 3, flLabel, OH_JmpAbsoluteIndirect }, /* $6c */
|
||||
{ "adc", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $6d */
|
||||
{ "ror", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $6e */
|
||||
{ "adc", 4, flUseLabel, OH_AbsoluteLong }, /* $6f */
|
||||
{ "adc", 4, flUseLabel|flFarOverride, OH_AbsoluteLong }, /* $6f */
|
||||
{ "bvs", 2, flLabel, OH_Relative }, /* $70 */
|
||||
{ "adc", 2, flUseLabel, OH_DirectIndirectY }, /* $71 */
|
||||
{ "adc", 2, flUseLabel, OH_DirectIndirect }, /* $72 */
|
||||
|
@ -174,7 +174,7 @@ const OpcDesc OpcTable_65816[256] = {
|
|||
{ "jmp", 3, flLabel, OH_AbsoluteXIndirect }, /* $7c */
|
||||
{ "adc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $7d */
|
||||
{ "ror", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $7e */
|
||||
{ "adc", 4, flUseLabel, OH_AbsoluteLongX }, /* $7f */
|
||||
{ "adc", 4, flUseLabel|flFarOverride, OH_AbsoluteLongX }, /* $7f */
|
||||
{ "bra", 2, flLabel, OH_Relative }, /* $80 */
|
||||
{ "sta", 2, flUseLabel, OH_DirectXIndirect }, /* $81 */
|
||||
{ "brl", 3, flLabel, OH_RelativeLong }, /* $82 */
|
||||
|
@ -184,13 +184,13 @@ const OpcDesc OpcTable_65816[256] = {
|
|||
{ "stx", 2, flUseLabel, OH_Direct }, /* $86 */
|
||||
{ "sta", 2, flUseLabel, OH_DirectIndirectLong }, /* $87 */
|
||||
{ "dey", 1, flNone, OH_Implicit }, /* $88 */
|
||||
{ "bit", 2, flNone, OH_Immediate }, /* $89 */
|
||||
{ "bit", 2, flSizeChanges, OH_Immediate65816M }, /* $89 */
|
||||
{ "txa", 1, flNone, OH_Implicit }, /* $8a */
|
||||
{ "phb", 1, flNone, OH_Implicit }, /* $8b */
|
||||
{ "sty", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8c */
|
||||
{ "sta", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8d */
|
||||
{ "stx", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8e */
|
||||
{ "sta", 4, flUseLabel, OH_AbsoluteLong }, /* $8f */
|
||||
{ "sta", 4, flUseLabel|flFarOverride, OH_AbsoluteLong }, /* $8f */
|
||||
{ "bcc", 2, flLabel, OH_Relative }, /* $90 */
|
||||
{ "sta", 2, flUseLabel, OH_DirectIndirectY }, /* $91 */
|
||||
{ "sta", 2, flUseLabel, OH_DirectIndirect }, /* $92 */
|
||||
|
@ -206,23 +206,23 @@ const OpcDesc OpcTable_65816[256] = {
|
|||
{ "stz", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $9c */
|
||||
{ "sta", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $9d */
|
||||
{ "stz", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $9e */
|
||||
{ "sta", 4, flUseLabel, OH_AbsoluteLongX }, /* $9f */
|
||||
{ "ldy", 2, flNone, OH_Immediate }, /* $a0 */
|
||||
{ "sta", 4, flUseLabel|flFarOverride, OH_AbsoluteLongX }, /* $9f */
|
||||
{ "ldy", 2, flSizeChanges, OH_Immediate65816X }, /* $a0 */
|
||||
{ "lda", 2, flUseLabel, OH_DirectXIndirect }, /* $a1 */
|
||||
{ "ldx", 2, flNone, OH_Immediate }, /* $a2 */
|
||||
{ "ldx", 2, flSizeChanges, OH_Immediate65816X }, /* $a2 */
|
||||
{ "lda", 2, flNone, OH_StackRelative }, /* $a3 */
|
||||
{ "ldy", 2, flUseLabel, OH_Direct }, /* $a4 */
|
||||
{ "lda", 2, flUseLabel, OH_Direct }, /* $a5 */
|
||||
{ "ldx", 2, flUseLabel, OH_Direct }, /* $a6 */
|
||||
{ "lda", 2, flUseLabel, OH_DirectIndirectLong }, /* $a7 */
|
||||
{ "tay", 1, flNone, OH_Implicit }, /* $a8 */
|
||||
{ "lda", 2, flNone, OH_Immediate }, /* $a9 */
|
||||
{ "lda", 2, flSizeChanges, OH_Immediate65816M }, /* $a9 */
|
||||
{ "tax", 1, flNone, OH_Implicit }, /* $aa */
|
||||
{ "plb", 1, flNone, OH_Implicit }, /* $ab */
|
||||
{ "ldy", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ac */
|
||||
{ "lda", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ad */
|
||||
{ "ldx", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ae */
|
||||
{ "lda", 4, flUseLabel, OH_AbsoluteLong }, /* $af */
|
||||
{ "lda", 4, flUseLabel|flFarOverride, OH_AbsoluteLong }, /* $af */
|
||||
{ "bcs", 2, flLabel, OH_Relative }, /* $b0 */
|
||||
{ "lda", 2, flUseLabel, OH_DirectIndirectY }, /* $b1 */
|
||||
{ "lda", 2, flUseLabel, OH_DirectIndirect }, /* $b2 */
|
||||
|
@ -238,8 +238,8 @@ const OpcDesc OpcTable_65816[256] = {
|
|||
{ "ldy", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $bc */
|
||||
{ "lda", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $bd */
|
||||
{ "ldx", 3, flUseLabel|flAbsOverride, OH_AbsoluteY }, /* $be */
|
||||
{ "lda", 4, flUseLabel, OH_AbsoluteLongX }, /* $bf */
|
||||
{ "cpy", 2, flNone, OH_Immediate }, /* $c0 */
|
||||
{ "lda", 4, flUseLabel|flFarOverride, OH_AbsoluteLongX }, /* $bf */
|
||||
{ "cpy", 2, flSizeChanges, OH_Immediate65816X }, /* $c0 */
|
||||
{ "cmp", 2, flUseLabel, OH_DirectXIndirect }, /* $c1 */
|
||||
{ "rep", 2, flNone, OH_Immediate }, /* $c2 */
|
||||
{ "cmp", 2, flNone, OH_StackRelative }, /* $c3 */
|
||||
|
@ -248,18 +248,18 @@ const OpcDesc OpcTable_65816[256] = {
|
|||
{ "dec", 2, flUseLabel, OH_Direct }, /* $c6 */
|
||||
{ "cmp", 2, flUseLabel, OH_DirectIndirectLong }, /* $c7 */
|
||||
{ "iny", 1, flNone, OH_Implicit }, /* $c8 */
|
||||
{ "cmp", 2, flNone, OH_Immediate }, /* $c9 */
|
||||
{ "cmp", 2, flSizeChanges, OH_Immediate65816M }, /* $c9 */
|
||||
{ "dex", 1, flNone, OH_Implicit }, /* $ca */
|
||||
{ "wai", 1, flNone, OH_Implicit }, /* $cb */
|
||||
{ "cpy", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $cc */
|
||||
{ "cmp", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $cd */
|
||||
{ "dec", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ce */
|
||||
{ "cmp", 4, flUseLabel, OH_AbsoluteLong }, /* $cf */
|
||||
{ "cmp", 4, flUseLabel|flFarOverride, OH_AbsoluteLong }, /* $cf */
|
||||
{ "bne", 2, flLabel, OH_Relative }, /* $d0 */
|
||||
{ "cmp", 2, flUseLabel, OH_DirectIndirectY }, /* $d1 */
|
||||
{ "cmp", 2, flUseLabel, OH_DirectIndirect }, /* $d2 */
|
||||
{ "cmp", 2, flNone, OH_StackRelativeIndirectY}, /* $d3 */
|
||||
{ "pei", 2, flUseLabel, OH_Direct }, /* $d4 */
|
||||
{ "pei", 2, flUseLabel, OH_DirectIndirect }, /* $d4 */
|
||||
{ "cmp", 2, flUseLabel, OH_DirectX }, /* $d5 */
|
||||
{ "dec", 2, flUseLabel, OH_DirectX }, /* $d6 */
|
||||
{ "cmp", 2, flUseLabel, OH_DirectIndirectLongY }, /* $d7 */
|
||||
|
@ -270,8 +270,8 @@ const OpcDesc OpcTable_65816[256] = {
|
|||
{ "jml", 3, flLabel, OH_AbsoluteIndirect }, /* $dc */
|
||||
{ "cmp", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $dd */
|
||||
{ "dec", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $de */
|
||||
{ "cmp", 4, flUseLabel, OH_AbsoluteLongX }, /* $df */
|
||||
{ "cpx", 2, flNone, OH_Immediate }, /* $e0 */
|
||||
{ "cmp", 4, flUseLabel|flFarOverride, OH_AbsoluteLongX }, /* $df */
|
||||
{ "cpx", 2, flSizeChanges, OH_Immediate65816X }, /* $e0 */
|
||||
{ "sbc", 2, flUseLabel, OH_DirectXIndirect }, /* $e1 */
|
||||
{ "sep", 2, flNone, OH_Immediate }, /* $e2 */
|
||||
{ "sbc", 2, flNone, OH_StackRelative }, /* $e3 */
|
||||
|
@ -280,13 +280,13 @@ const OpcDesc OpcTable_65816[256] = {
|
|||
{ "inc", 2, flUseLabel, OH_Direct }, /* $e6 */
|
||||
{ "sbc", 2, flUseLabel, OH_DirectIndirectLong }, /* $e7 */
|
||||
{ "inx", 1, flNone, OH_Implicit }, /* $e8 */
|
||||
{ "sbc", 2, flNone, OH_Immediate }, /* $e9 */
|
||||
{ "sbc", 2, flSizeChanges, OH_Immediate65816M }, /* $e9 */
|
||||
{ "nop", 1, flNone, OH_Implicit }, /* $ea */
|
||||
{ "xba", 1, flNone, OH_Implicit }, /* $eb */
|
||||
{ "cpx", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ec */
|
||||
{ "sbc", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ed */
|
||||
{ "inc", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ee */
|
||||
{ "sbc", 4, flUseLabel, OH_AbsoluteLong }, /* $ef */
|
||||
{ "sbc", 4, flUseLabel|flFarOverride, OH_AbsoluteLong }, /* $ef */
|
||||
{ "beq", 2, flLabel, OH_Relative }, /* $f0 */
|
||||
{ "sbc", 2, flUseLabel, OH_DirectIndirectY }, /* $f1 */
|
||||
{ "sbc", 2, flUseLabel, OH_DirectIndirect }, /* $f2 */
|
||||
|
@ -302,5 +302,5 @@ const OpcDesc OpcTable_65816[256] = {
|
|||
{ "jsr", 3, flLabel, OH_AbsoluteXIndirect }, /* $fc */
|
||||
{ "sbc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $fd */
|
||||
{ "inc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $fe */
|
||||
{ "sbc", 4, flUseLabel, OH_AbsoluteLongX }, /* $ff */
|
||||
{ "sbc", 4, flUseLabel|flFarOverride, OH_AbsoluteLongX }, /* $ff */
|
||||
};
|
||||
|
|
|
@ -53,7 +53,8 @@ enum {
|
|||
flLabel = flUseLabel|flGenLabel, /* Generate and use a label */
|
||||
flIllegal = 0x10, /* Illegal instruction */
|
||||
flAbsOverride = 0x20, /* Need a: override */
|
||||
flFarOverride = 0x40 /* Need f: override */
|
||||
flFarOverride = 0x40, /* Need f: override */
|
||||
flSizeChanges = 0x80 /* 65816: size may change */
|
||||
};
|
||||
|
||||
/* Forward/typedef for struct OpcDesc */
|
||||
|
|
|
@ -74,6 +74,7 @@ void SetOpcTable (cpu_t CPU)
|
|||
case CPU_6502DTV: OpcTable = OpcTable_6502DTV; break;
|
||||
case CPU_65SC02: OpcTable = OpcTable_65SC02; break;
|
||||
case CPU_65C02: OpcTable = OpcTable_65C02; break;
|
||||
case CPU_65816: OpcTable = OpcTable_65816; break;
|
||||
case CPU_HUC6280: OpcTable = OpcTable_HuC6280; break;
|
||||
case CPU_M740: OpcTable = OpcTable_M740; break;
|
||||
case CPU_4510: OpcTable = OpcTable_4510; break;
|
||||
|
|
|
@ -401,3 +401,23 @@ void OutputSettings (void)
|
|||
LineFeed ();
|
||||
LineFeed ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void OutputMFlag (unsigned char enabled)
|
||||
/* Output the 65816 M-flag state */
|
||||
{
|
||||
Indent (MCol);
|
||||
Output (enabled ? ".a8" : ".a16");
|
||||
LineFeed ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void OutputXFlag (unsigned char enabled)
|
||||
/* Output the 65816 X-flag state */
|
||||
{
|
||||
Indent (MCol);
|
||||
Output (enabled ? ".i8" : ".i16");
|
||||
LineFeed ();
|
||||
}
|
||||
|
|
|
@ -108,6 +108,12 @@ void LineComment (unsigned PC, unsigned Count);
|
|||
void OutputSettings (void);
|
||||
/* Output CPU and other settings */
|
||||
|
||||
void OutputMFlag (unsigned char enabled);
|
||||
/* Output the 65816 M-flag state */
|
||||
|
||||
void OutputXFlag (unsigned char enabled);
|
||||
/* Output the 65816 X-flag state */
|
||||
|
||||
|
||||
|
||||
/* End of output.h */
|
||||
|
|
|
@ -90,6 +90,8 @@ typedef enum token_t {
|
|||
INFOTOK_START,
|
||||
INFOTOK_END,
|
||||
INFOTOK_TYPE,
|
||||
INFOTOK_ADDRMODE,
|
||||
INFOTOK_UNIT,
|
||||
|
||||
INFOTOK_CODE,
|
||||
INFOTOK_BYTETAB,
|
||||
|
|
|
@ -4736,14 +4736,18 @@ static SpanInfoListEntry* FindSpanInfoByAddr (const SpanInfoList* L, cc65_addr A
|
|||
|
||||
|
||||
|
||||
static LineInfo* FindLineInfoByLine (const Collection* LineInfos, cc65_line Line)
|
||||
/* Find the LineInfo for a given line number. The function returns the line
|
||||
** info or NULL if none was found.
|
||||
static int FindLineInfoByLine (const Collection* LineInfos, cc65_line Line,
|
||||
unsigned *Index)
|
||||
/* Find the LineInfo for a given line number. The function returns true if the
|
||||
** name was found. In this case, Index contains the index of the first item
|
||||
** that matches. If the item wasn't found, the function returns false and
|
||||
** Index contains the insert position for Name.
|
||||
*/
|
||||
{
|
||||
/* Do a binary search */
|
||||
int Lo = 0;
|
||||
int Hi = (int) CollCount (LineInfos) - 1;
|
||||
int Found = 0;
|
||||
while (Lo <= Hi) {
|
||||
|
||||
/* Mid of range */
|
||||
|
@ -4755,16 +4759,20 @@ static LineInfo* FindLineInfoByLine (const Collection* LineInfos, cc65_line Line
|
|||
/* Found? */
|
||||
if (Line > CurItem->Line) {
|
||||
Lo = Cur + 1;
|
||||
} else if (Line < CurItem->Line) {
|
||||
Hi = Cur - 1;
|
||||
} else {
|
||||
/* Found */
|
||||
return CurItem;
|
||||
Hi = Cur - 1;
|
||||
/* Since we may have duplicates, repeat the search until we've
|
||||
** the first item that has a match.
|
||||
*/
|
||||
if(Line == CurItem->Line) {
|
||||
Found = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Not found */
|
||||
return 0;
|
||||
/* Pass back the index. This is also the insert position */
|
||||
*Index = Lo;
|
||||
return Found;
|
||||
}
|
||||
|
||||
|
||||
|
@ -6127,13 +6135,17 @@ const cc65_lineinfo* cc65_line_byid (cc65_dbginfo Handle, unsigned Id)
|
|||
const cc65_lineinfo* cc65_line_bynumber (cc65_dbginfo Handle, unsigned FileId,
|
||||
cc65_line Line)
|
||||
/* Return line information for a source file/line number combination. The
|
||||
** function returns NULL if no line information was found.
|
||||
** function returns NULL if no line information was found, otherwise a list
|
||||
** of line infos.
|
||||
*/
|
||||
{
|
||||
const DbgInfo* Info;
|
||||
const FileInfo* F;
|
||||
cc65_lineinfo* D;
|
||||
LineInfo* L = 0;
|
||||
unsigned I;
|
||||
unsigned Index;
|
||||
unsigned Count;
|
||||
|
||||
/* Check the parameter */
|
||||
assert (Handle != 0);
|
||||
|
@ -6150,18 +6162,31 @@ const cc65_lineinfo* cc65_line_bynumber (cc65_dbginfo Handle, unsigned FileId,
|
|||
F = CollAt (&Info->FileInfoById, FileId);
|
||||
|
||||
/* Search in the file for the given line */
|
||||
L = FindLineInfoByLine (&F->LineInfoByLine, Line);
|
||||
|
||||
/* Bail out if we didn't find the line */
|
||||
if (L == 0) {
|
||||
if(!FindLineInfoByLine (&F->LineInfoByLine, Line, &Index)) {
|
||||
/* Not found */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Index contains the first position. Count how many lines with this number
|
||||
** we have. Skip the first one, since we have at least one.
|
||||
*/
|
||||
Count = 1;
|
||||
|
||||
while ((unsigned) Index + Count < CollCount( &F->LineInfoByLine)) {
|
||||
L = CollAt (&F->LineInfoByLine, (unsigned) Index + Count);
|
||||
if (L->Line != Line) {
|
||||
break;
|
||||
}
|
||||
++Count;
|
||||
}
|
||||
|
||||
/* Prepare the struct we will return to the caller */
|
||||
D = new_cc65_lineinfo (1);
|
||||
D = new_cc65_lineinfo (Count);
|
||||
|
||||
/* Copy the data */
|
||||
CopyLineInfo (D->data, L);
|
||||
for (I = 0; I < Count; ++I) {
|
||||
CopyLineInfo (D->data + I, CollAt (&F->LineInfoByLine, Index++));
|
||||
}
|
||||
|
||||
/* Return the allocated struct */
|
||||
return D;
|
||||
|
|
|
@ -258,7 +258,8 @@ const cc65_lineinfo* cc65_line_bynumber (cc65_dbginfo handle,
|
|||
unsigned source_id,
|
||||
cc65_line line);
|
||||
/* Return line information for a source file/line number combination. The
|
||||
** function returns NULL if no line information was found.
|
||||
** function returns NULL if no line information was found, otherwise a list
|
||||
** of line infos.
|
||||
*/
|
||||
|
||||
const cc65_lineinfo* cc65_line_bysource (cc65_dbginfo Handle, unsigned source_id);
|
||||
|
|
|
@ -62,9 +62,11 @@
|
|||
<ClCompile Include="sp65\geosicon.c" />
|
||||
<ClCompile Include="sp65\input.c" />
|
||||
<ClCompile Include="sp65\koala.c" />
|
||||
<ClCompile Include="sp65\lynxpalette.c" />
|
||||
<ClCompile Include="sp65\lynxsprite.c" />
|
||||
<ClCompile Include="sp65\main.c" />
|
||||
<ClCompile Include="sp65\output.c" />
|
||||
<ClCompile Include="sp65\palconv.c" />
|
||||
<ClCompile Include="sp65\palette.c" />
|
||||
<ClCompile Include="sp65\pcx.c" />
|
||||
<ClCompile Include="sp65\raw.c" />
|
||||
|
@ -84,8 +86,10 @@
|
|||
<ClInclude Include="sp65\geosicon.h" />
|
||||
<ClInclude Include="sp65\input.h" />
|
||||
<ClInclude Include="sp65\koala.h" />
|
||||
<ClInclude Include="sp65\lynxpalette.h" />
|
||||
<ClInclude Include="sp65\lynxsprite.h" />
|
||||
<ClInclude Include="sp65\output.h" />
|
||||
<ClInclude Include="sp65\palconv.h" />
|
||||
<ClInclude Include="sp65\palette.h" />
|
||||
<ClInclude Include="sp65\pcx.h" />
|
||||
<ClInclude Include="sp65\pixel.h" />
|
||||
|
@ -95,4 +99,4 @@
|
|||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
@ -75,6 +75,9 @@ struct Bitmap {
|
|||
unsigned Width;
|
||||
unsigned Height;
|
||||
|
||||
/* Bits per pixels */
|
||||
unsigned BPP;
|
||||
|
||||
/* Palette for indexed bitmap types, otherwise NULL */
|
||||
Palette* Pal;
|
||||
|
||||
|
@ -179,6 +182,17 @@ INLINE unsigned GetBitmapColors (const Bitmap* B)
|
|||
# define GetBitmapColors(B) ((B)->Pal? (B)->Pal->Count : (1U << 24))
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE unsigned GetBitmapBPP (const Bitmap* B)
|
||||
/* Get the bits per pixel of the converted sprite
|
||||
*/
|
||||
{
|
||||
return B->BPP;
|
||||
}
|
||||
#else
|
||||
# define GetBitmapBPP(B) ((B)->BPP
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* End of bitmap.h */
|
||||
|
|
93
src/sp65/lynxpalette.c
Normal file
93
src/sp65/lynxpalette.c
Normal file
|
@ -0,0 +1,93 @@
|
|||
/*****************************************************************************/
|
||||
/* */
|
||||
/* lynxpalette.c */
|
||||
/* */
|
||||
/* Lynx palette backend for the sp65 sprite and bitmap utility */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2022, Karri Kaksonen */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/* common */
|
||||
#include "attrib.h"
|
||||
#include "print.h"
|
||||
|
||||
/* sp65 */
|
||||
#include "attr.h"
|
||||
#include "error.h"
|
||||
#include "palette.h"
|
||||
#include "lynxpalette.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
StrBuf* GenLynxPalette (const Bitmap* B, const Collection* A)
|
||||
/* Generate binary output in Lynx palette format for the bitmap B. The output
|
||||
** is stored in a string buffer (which is actually a dynamic char array) and
|
||||
** returned.
|
||||
**
|
||||
*/
|
||||
{
|
||||
StrBuf* D;
|
||||
const Palette* P = GetBitmapPalette (B);
|
||||
const char* Format = GetAttrVal(A, "format");
|
||||
unsigned I;
|
||||
|
||||
if (Format == 0) {
|
||||
/* No format specified */
|
||||
}
|
||||
D = NewStrBuf ();
|
||||
for (I = 0; I < 16; ++I) {
|
||||
|
||||
/* Get the color entry */
|
||||
const Color* C = P->Entries + I;
|
||||
|
||||
/* Add the green component */
|
||||
SB_AppendChar (D, C->G >> 4);
|
||||
}
|
||||
for (I = 0; I < 16; ++I) {
|
||||
|
||||
/* Get the color entry */
|
||||
const Color* C = P->Entries + I;
|
||||
|
||||
/* Add the blue,red component */
|
||||
SB_AppendChar (D, (C->B & 0xF0) | (C->R >> 4));
|
||||
}
|
||||
|
||||
/* Return the converted palette */
|
||||
return D;
|
||||
}
|
||||
|
63
src/sp65/lynxpalette.h
Normal file
63
src/sp65/lynxpalette.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*****************************************************************************/
|
||||
/* */
|
||||
/* lynxpalette.h */
|
||||
/* */
|
||||
/* Lynx palette format backend for the sp65 sprite and bitmap utility */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2022, Karri Kaksonen */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifndef LYNXPALETTE_H
|
||||
#define LYNXPALETTE_H
|
||||
|
||||
|
||||
|
||||
/* common */
|
||||
#include "coll.h"
|
||||
#include "strbuf.h"
|
||||
|
||||
/* sp65 */
|
||||
#include "bitmap.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
StrBuf* GenLynxPalette (const Bitmap* B, const Collection* A);
|
||||
/* Generate binary output in Lynx palette format for the bitmap B. The output
|
||||
** is stored in a string buffer (which is actually a dynamic char array) and
|
||||
** returned.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* End of lynxpalette.h */
|
||||
|
||||
#endif
|
|
@ -88,12 +88,18 @@ static enum Mode GetMode (const Collection* A)
|
|||
}
|
||||
|
||||
|
||||
static unsigned GetActionPointX (const Collection* A)
|
||||
static unsigned GetActionPointX (const Bitmap* B, const Collection* A)
|
||||
/* Return the sprite mode from the attribute collection A */
|
||||
{
|
||||
/* Check for a action point x attribute */
|
||||
const char* ActionPointX = GetAttrVal (A, "ax");
|
||||
if (ActionPointX) {
|
||||
if (strcmp (ActionPointX, "mid") == 0) {
|
||||
return GetBitmapWidth (B) / 2;
|
||||
}
|
||||
if (strcmp (ActionPointX, "max") == 0) {
|
||||
return GetBitmapWidth (B) - 1;
|
||||
}
|
||||
return atoi(ActionPointX);
|
||||
} else {
|
||||
return 0;
|
||||
|
@ -101,12 +107,18 @@ static unsigned GetActionPointX (const Collection* A)
|
|||
}
|
||||
|
||||
|
||||
static unsigned GetActionPointY (const Collection* A)
|
||||
static unsigned GetActionPointY (const Bitmap* B, const Collection* A)
|
||||
/* Return the sprite mode from the attribute collection A */
|
||||
{
|
||||
/* Check for a action point y attribute */
|
||||
const char* ActionPointY = GetAttrVal (A, "ay");
|
||||
if (ActionPointY) {
|
||||
if (strcmp (ActionPointY, "mid") == 0) {
|
||||
return GetBitmapHeight (B) / 2;
|
||||
}
|
||||
if (strcmp (ActionPointY, "max") == 0) {
|
||||
return GetBitmapHeight (B) - 1;
|
||||
}
|
||||
return atoi(ActionPointY);
|
||||
} else {
|
||||
return 0;
|
||||
|
@ -125,6 +137,124 @@ static unsigned GetEdgeIndex (const Collection* A)
|
|||
}
|
||||
}
|
||||
|
||||
static unsigned GetQuadrant (const Collection* A)
|
||||
/* Return the sprite mode from the attribute collection A */
|
||||
{
|
||||
/* Get index for edge color in shaped mode */
|
||||
const char* Quadrant = GetAttrVal (A, "quadrant");
|
||||
if (Quadrant) {
|
||||
return atoi(Quadrant);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void OptimizePenpal (const Bitmap* B, char *PenPal)
|
||||
/* Create an optimal Penpal */
|
||||
{
|
||||
char usage[16];
|
||||
unsigned I, J, Val;
|
||||
|
||||
memset(usage, 0, sizeof(usage));
|
||||
for (J = 0; J < GetBitmapHeight (B); J++) {
|
||||
for (I = 0; I < GetBitmapWidth (B); I++) {
|
||||
Val = GetPixel (B, I, J).Index;
|
||||
if (Val < 16) {
|
||||
usage[Val] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
J = 0;
|
||||
for (I = 0; I < 16; I++) {
|
||||
if (usage[I]) {
|
||||
switch (I) {
|
||||
case 0:
|
||||
PenPal[J] = '0';
|
||||
break;
|
||||
case 1:
|
||||
PenPal[J] = '1';
|
||||
break;
|
||||
case 2:
|
||||
PenPal[J] = '2';
|
||||
break;
|
||||
case 3:
|
||||
PenPal[J] = '3';
|
||||
break;
|
||||
case 4:
|
||||
PenPal[J] = '4';
|
||||
break;
|
||||
case 5:
|
||||
PenPal[J] = '5';
|
||||
break;
|
||||
case 6:
|
||||
PenPal[J] = '6';
|
||||
break;
|
||||
case 7:
|
||||
PenPal[J] = '7';
|
||||
break;
|
||||
case 8:
|
||||
PenPal[J] = '8';
|
||||
break;
|
||||
case 9:
|
||||
PenPal[J] = '9';
|
||||
break;
|
||||
case 10:
|
||||
PenPal[J] = 'a';
|
||||
break;
|
||||
case 11:
|
||||
PenPal[J] = 'b';
|
||||
break;
|
||||
case 12:
|
||||
PenPal[J] = 'c';
|
||||
break;
|
||||
case 13:
|
||||
PenPal[J] = 'd';
|
||||
break;
|
||||
case 14:
|
||||
PenPal[J] = 'e';
|
||||
break;
|
||||
case 15:
|
||||
PenPal[J] = 'f';
|
||||
break;
|
||||
}
|
||||
J++;
|
||||
}
|
||||
}
|
||||
while (J < 16) {
|
||||
PenPal[J] = 0;
|
||||
J++;
|
||||
}
|
||||
/* printf("Penpal %s\n", PenPal); */
|
||||
}
|
||||
|
||||
static unsigned GetPenpal (const Bitmap* B, const Collection* A, char *PenPal)
|
||||
/* Return the penpal from the attribute collection A */
|
||||
{
|
||||
const char* Pen = GetAttrVal (A, "pen");
|
||||
if (Pen) {
|
||||
if (strcmp (Pen, "opt") == 0) {
|
||||
/* So we need to optimize the penpal and colour depth */
|
||||
OptimizePenpal (B, PenPal);
|
||||
} else {
|
||||
strncpy(PenPal, Pen, 17);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned GetBPP (const Collection* A)
|
||||
/* Return the sprite depth from the attribute collection A */
|
||||
{
|
||||
/* Get index for edge color in shaped mode */
|
||||
const char* BPP = GetAttrVal (A, "bpp");
|
||||
if (BPP) {
|
||||
return atoi(BPP);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static char OutBuffer[512]; /* The maximum size is 508 pixels */
|
||||
static unsigned char OutIndex;
|
||||
|
||||
|
@ -140,26 +270,16 @@ static void AssembleByte(unsigned bits, char val)
|
|||
return;
|
||||
}
|
||||
/* handle end of line */
|
||||
if (bits == 8) {
|
||||
if (bits == 7) {
|
||||
if (bit_counter != 8) {
|
||||
byte <<= bit_counter;
|
||||
OutBuffer[OutIndex++] = byte;
|
||||
if (!OutIndex) {
|
||||
Error ("Sprite is too large for the Lynx");
|
||||
}
|
||||
if (byte & 0x1) {
|
||||
OutBuffer[OutIndex++] = byte;
|
||||
if (!OutIndex) {
|
||||
Error ("Sprite is too large for the Lynx");
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
/* handle end of line for literal */
|
||||
if (bits == 7) {
|
||||
if (bit_counter != 8) {
|
||||
byte <<= bit_counter;
|
||||
} else {
|
||||
/* Add pad byte */
|
||||
byte = 0;
|
||||
OutBuffer[OutIndex++] = byte;
|
||||
if (!OutIndex) {
|
||||
Error ("Sprite is too large for the Lynx");
|
||||
|
@ -189,28 +309,78 @@ static void AssembleByte(unsigned bits, char val)
|
|||
} while (--bits);
|
||||
}
|
||||
|
||||
static unsigned char ChoosePackagingMode(signed len, signed index, char ColorBits, char LineBuffer[512])
|
||||
static unsigned char AnalyseNextChunks(signed *newlen, signed len, char data[32], char ColorBits)
|
||||
{
|
||||
--len;
|
||||
if (!len) {
|
||||
return 0;
|
||||
char longest = 1;
|
||||
char prev = 255;
|
||||
char count = 0;
|
||||
char index = 0;
|
||||
char lindex = 0;
|
||||
int i;
|
||||
int literal_cost;
|
||||
int packed_cost;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
index = index + 1;
|
||||
if (data[i] == prev) {
|
||||
count = count + 1;
|
||||
if (count >= longest) {
|
||||
longest = count;
|
||||
lindex = index - count;
|
||||
}
|
||||
} else {
|
||||
prev = data[i];
|
||||
count = 1;
|
||||
}
|
||||
}
|
||||
if (LineBuffer[index] != LineBuffer[index + 1]) {
|
||||
return 0;
|
||||
if (longest == 1) {
|
||||
if (len > 16) {
|
||||
*newlen = 16;
|
||||
} else {
|
||||
*newlen = len;
|
||||
}
|
||||
return 'L';
|
||||
}
|
||||
if (ColorBits > 2) {
|
||||
return 1;
|
||||
if ((lindex > 0) && (lindex + longest > 15)) {
|
||||
/* We cannot pack the stride in this packet */
|
||||
*newlen = lindex;
|
||||
return 'A';
|
||||
}
|
||||
if (LineBuffer[index] != LineBuffer[index + 2]) {
|
||||
return 0;
|
||||
/* Cost till end of area */
|
||||
literal_cost = 5 + lindex * ColorBits + longest * ColorBits;
|
||||
packed_cost = 5 + lindex * ColorBits + 5 + ColorBits;
|
||||
if (packed_cost < literal_cost) {
|
||||
if (lindex == 0) {
|
||||
/* Use packed data */
|
||||
if (longest > 16) {
|
||||
*newlen = 16;
|
||||
} else {
|
||||
*newlen = longest;
|
||||
}
|
||||
return 'P';
|
||||
}
|
||||
/* We had a good find, but it was not at the start of the line */
|
||||
*newlen = lindex;
|
||||
return 'A';
|
||||
}
|
||||
if (ColorBits > 1) {
|
||||
return 1;
|
||||
/* There is no point in packing - use literal */
|
||||
if (len > 16) {
|
||||
*newlen = 16;
|
||||
} else {
|
||||
*newlen = len;
|
||||
}
|
||||
if (LineBuffer[index] != LineBuffer[index + 3]) {
|
||||
return 0;
|
||||
return 'L';
|
||||
}
|
||||
|
||||
static unsigned char GetNextChunk(signed *newlen, signed len, char data[32], char ColorBits)
|
||||
{
|
||||
char oper = 'A';
|
||||
|
||||
while (oper == 'A') {
|
||||
oper = AnalyseNextChunks(newlen, len, data, ColorBits);
|
||||
len = *newlen;
|
||||
}
|
||||
return 1;
|
||||
return oper; /* The packet type is now P or L and the length is in newlen */
|
||||
}
|
||||
|
||||
static void WriteOutBuffer(StrBuf *D)
|
||||
|
@ -235,27 +405,25 @@ static void WriteOutBuffer(StrBuf *D)
|
|||
static void encodeSprite(StrBuf *D, enum Mode M, char ColorBits, char ColorMask, char LineBuffer[512],
|
||||
int len, int LastOpaquePixel) {
|
||||
/*
|
||||
** The data starts with a byte count. It tells the number of bytes on this
|
||||
** line + 1.
|
||||
** Special case is a count of 1. It will change to next quadrant.
|
||||
** Other special case is 0. It will end the sprite.
|
||||
**
|
||||
** Ordinary data packet. These are bits in a stream.
|
||||
** 1=literal 0=packed
|
||||
** 4 bit count (+1)
|
||||
** for literal you put "count" values
|
||||
** for packed you repeat the value "count" times
|
||||
** Never use packed mode for one pixel
|
||||
** If the last bit on a line is 1 you need to add a byte of zeroes
|
||||
** A sequence 00000 ends a scan line
|
||||
**
|
||||
** All data is high nybble first
|
||||
*/
|
||||
* The data starts with a byte count. It tells the number of bytes on this
|
||||
* line + 1.
|
||||
* Special case is a count of 1. It will change to next quadrant.
|
||||
* Other special case is 0. It will end the sprite.
|
||||
*
|
||||
* Ordinary data packet. These are bits in a stream.
|
||||
* 1=literal 0=packed
|
||||
* 4 bit count (+1)
|
||||
* for literal you put "count" values
|
||||
* for packed you repeat the value "count" times
|
||||
* Never use packed mode for one pixel
|
||||
* If the last bit on a line is in use you need to add a byte of zeroes
|
||||
* A sequence 00000 ends a scan line
|
||||
*
|
||||
* All data is high nybble first
|
||||
*/
|
||||
unsigned char V = 0;
|
||||
signed i;
|
||||
signed count;
|
||||
unsigned char differ[16];
|
||||
unsigned char *d_ptr;
|
||||
|
||||
AssembleByte(0, 0);
|
||||
switch (M) {
|
||||
|
@ -270,100 +438,46 @@ static void encodeSprite(StrBuf *D, enum Mode M, char ColorBits, char ColorMask,
|
|||
WriteOutBuffer(D);
|
||||
break;
|
||||
case smPacked:
|
||||
case smShaped:
|
||||
if (M == smShaped) {
|
||||
if (LastOpaquePixel > -1) {
|
||||
if (LastOpaquePixel < len - 1) {
|
||||
len = LastOpaquePixel + 1;
|
||||
}
|
||||
} else {
|
||||
len = 0;
|
||||
}
|
||||
}
|
||||
i = 0;
|
||||
while (len) {
|
||||
if (ChoosePackagingMode(len, i, ColorBits, LineBuffer)) {
|
||||
signed analyselen;
|
||||
analyselen = len;
|
||||
if (analyselen > 32) {
|
||||
analyselen = 32;
|
||||
}
|
||||
if (GetNextChunk(&count, analyselen, LineBuffer + i, ColorBits) == 'P') {
|
||||
/* Make runlength packet */
|
||||
V = LineBuffer[i];
|
||||
++i;
|
||||
--len;
|
||||
count = 0;
|
||||
do {
|
||||
++count;
|
||||
++i;
|
||||
--len;
|
||||
} while (V == LineBuffer[i] && len && count != 15);
|
||||
|
||||
AssembleByte(5, count);
|
||||
AssembleByte(ColorBits, V);
|
||||
i += count;
|
||||
len -= count;
|
||||
AssembleByte(5, count-1);
|
||||
AssembleByte(ColorBits, V & ColorMask);
|
||||
|
||||
} else {
|
||||
/* Make packed literal packet */
|
||||
d_ptr = differ;
|
||||
V = LineBuffer[i++];
|
||||
*d_ptr++ = V;
|
||||
--len;
|
||||
count = 0;
|
||||
while (ChoosePackagingMode(len, i, ColorBits, LineBuffer) == 0 && len && count != 15) {
|
||||
V = LineBuffer[i++];
|
||||
*d_ptr++ = V;
|
||||
++count;
|
||||
--len;
|
||||
}
|
||||
|
||||
AssembleByte(5, count | 0x10);
|
||||
d_ptr = differ;
|
||||
AssembleByte(5, (count-1) | 0x10);
|
||||
do {
|
||||
AssembleByte(ColorBits, *d_ptr++);
|
||||
} while (--count >= 0);
|
||||
|
||||
AssembleByte(ColorBits, LineBuffer[i]);
|
||||
i++;
|
||||
len--;
|
||||
} while (--count > 0);
|
||||
}
|
||||
}
|
||||
AssembleByte(8, 0);
|
||||
/* Force EOL for shaped? AssembleByte(5, 0); */
|
||||
AssembleByte(7, 0);
|
||||
/* Write the buffer to file */
|
||||
WriteOutBuffer(D);
|
||||
break;
|
||||
|
||||
case smShaped:
|
||||
if (LastOpaquePixel > -1) {
|
||||
if (LastOpaquePixel < len - 1) {
|
||||
len = LastOpaquePixel + 1;
|
||||
}
|
||||
i = 0;
|
||||
while (len) {
|
||||
if (ChoosePackagingMode(len, i, ColorBits, LineBuffer)) {
|
||||
/* Make runlength packet */
|
||||
V = LineBuffer[i];
|
||||
++i;
|
||||
--len;
|
||||
count = 0;
|
||||
do {
|
||||
++count;
|
||||
++i;
|
||||
--len;
|
||||
} while (V == LineBuffer[i] && len && count != 15);
|
||||
|
||||
AssembleByte(5, count);
|
||||
AssembleByte(ColorBits, V);
|
||||
|
||||
} else {
|
||||
/* Make packed literal packet */
|
||||
d_ptr = differ;
|
||||
V = LineBuffer[i++];
|
||||
*d_ptr++ = V;
|
||||
--len;
|
||||
count = 0;
|
||||
while (ChoosePackagingMode(len, i, ColorBits, LineBuffer) == 0 && len && count != 15) {
|
||||
V = LineBuffer[i++];
|
||||
*d_ptr++ = V;
|
||||
++count;
|
||||
--len;
|
||||
}
|
||||
|
||||
AssembleByte(5, count | 0x10);
|
||||
d_ptr = differ;
|
||||
do {
|
||||
AssembleByte(ColorBits, *d_ptr++);
|
||||
} while (--count >= 0);
|
||||
|
||||
}
|
||||
}
|
||||
AssembleByte(5, 0);
|
||||
AssembleByte(8, 0);
|
||||
/* Write the buffer to file */
|
||||
WriteOutBuffer(D);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -373,10 +487,10 @@ StrBuf* GenLynxSprite (const Bitmap* B, const Collection* A)
|
|||
** returned.
|
||||
**
|
||||
** The Lynx will draw 4 quadrants:
|
||||
** - Down right
|
||||
** - Up right
|
||||
** - Up left
|
||||
** - Down left
|
||||
** 0 - Down right
|
||||
** 1 - Up right
|
||||
** 2 - Up left
|
||||
** 3 - Down left
|
||||
**
|
||||
** The sprite will end with a byte 0.
|
||||
*/
|
||||
|
@ -388,13 +502,24 @@ StrBuf* GenLynxSprite (const Bitmap* B, const Collection* A)
|
|||
char ColorBits;
|
||||
char ColorMask;
|
||||
char EdgeIndex;
|
||||
char Quadrant;
|
||||
char quad;
|
||||
char BPP;
|
||||
/* The default mapping is 1:1 plus extra colours become 0 */
|
||||
char Map[17] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0};
|
||||
signed PenColors;
|
||||
char PenPal[18];
|
||||
signed Val;
|
||||
|
||||
/* Get EdgeIndex */
|
||||
EdgeIndex = GetEdgeIndex (A);
|
||||
|
||||
/* Get Quadrant for starting the draw process */
|
||||
Quadrant = GetQuadrant (A) & 3;
|
||||
|
||||
/* Action point of the sprite */
|
||||
OX = GetActionPointX (A);
|
||||
OY = GetActionPointY (A);
|
||||
OX = GetActionPointX (B, A);
|
||||
OY = GetActionPointY (B, A);
|
||||
if (OX >= GetBitmapWidth (B)) {
|
||||
Error ("Action point X cannot be larger than bitmap width");
|
||||
}
|
||||
|
@ -410,145 +535,293 @@ StrBuf* GenLynxSprite (const Bitmap* B, const Collection* A)
|
|||
/* Get the sprite mode */
|
||||
M = GetMode (A);
|
||||
|
||||
/* Now check if bitmap indexes are ok */
|
||||
if (GetBitmapColors (B) > 16) {
|
||||
Error ("Too many colors for a Lynx sprite");
|
||||
/* Now check how to do the mapping */
|
||||
if (GetPenpal (B, A, &PenPal[0])) {
|
||||
signed I;
|
||||
|
||||
/* Modify the map by content of PenPal */
|
||||
PenColors = strlen(PenPal);
|
||||
for (I = 0; I < PenColors; I++) {
|
||||
switch (PenPal[I]) {
|
||||
case '0':
|
||||
Map[0] = I;
|
||||
break;
|
||||
case '1':
|
||||
Map[1] = I;
|
||||
break;
|
||||
case '2':
|
||||
Map[2] = I;
|
||||
break;
|
||||
case '3':
|
||||
Map[3] = I;
|
||||
break;
|
||||
case '4':
|
||||
Map[4] = I;
|
||||
break;
|
||||
case '5':
|
||||
Map[5] = I;
|
||||
break;
|
||||
case '6':
|
||||
Map[6] = I;
|
||||
break;
|
||||
case '7':
|
||||
Map[7] = I;
|
||||
break;
|
||||
case '8':
|
||||
Map[8] = I;
|
||||
break;
|
||||
case '9':
|
||||
Map[9] = I;
|
||||
break;
|
||||
case 'a':
|
||||
case 'A':
|
||||
Map[10] = I;
|
||||
break;
|
||||
case 'b':
|
||||
case 'B':
|
||||
Map[11] = I;
|
||||
break;
|
||||
case 'c':
|
||||
case 'C':
|
||||
Map[12] = I;
|
||||
break;
|
||||
case 'd':
|
||||
case 'D':
|
||||
Map[13] = I;
|
||||
break;
|
||||
case 'e':
|
||||
case 'E':
|
||||
Map[14] = I;
|
||||
break;
|
||||
case 'f':
|
||||
case 'F':
|
||||
Map[15] = I;
|
||||
break;
|
||||
/* The X is reserved as transparency. This allows for shaped sprites */
|
||||
case 'x':
|
||||
case 'X':
|
||||
Map[16] = I;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
PenColors = GetBitmapColors (B);
|
||||
}
|
||||
ColorBits = 4;
|
||||
ColorMask = 0x0f;
|
||||
if (GetBitmapColors (B) < 9) {
|
||||
if (PenColors < 9) {
|
||||
ColorBits = 3;
|
||||
ColorMask = 0x07;
|
||||
}
|
||||
if (GetBitmapColors (B) < 5) {
|
||||
if (PenColors < 5) {
|
||||
ColorBits = 2;
|
||||
ColorMask = 0x03;
|
||||
}
|
||||
if (GetBitmapColors (B) < 3) {
|
||||
if (PenColors < 3) {
|
||||
ColorBits = 1;
|
||||
ColorMask = 0x01;
|
||||
}
|
||||
|
||||
BPP = GetBPP (A);
|
||||
if (BPP > 0) {
|
||||
ColorBits = BPP;
|
||||
}
|
||||
switch (ColorBits) {
|
||||
case 1:
|
||||
ColorMask = 0x01;
|
||||
break;
|
||||
case 2:
|
||||
ColorMask = 0x03;
|
||||
break;
|
||||
case 3:
|
||||
ColorMask = 0x07;
|
||||
break;
|
||||
default:
|
||||
case 4:
|
||||
ColorMask = 0x0f;
|
||||
break;
|
||||
}
|
||||
/* B->BPP = ColorBits; */
|
||||
/* Create the output buffer and resize it to the required size. */
|
||||
D = NewStrBuf ();
|
||||
SB_Realloc (D, 63);
|
||||
|
||||
/* Convert the image for quadrant bottom right */
|
||||
for (Y = OY; Y < (signed)GetBitmapHeight (B); ++Y) {
|
||||
signed i = 0;
|
||||
signed LastOpaquePixel = -1;
|
||||
char LineBuffer[512]; /* The maximum size is 508 pixels */
|
||||
for (quad = 0; quad < 4; quad++) {
|
||||
switch ((Quadrant + quad) & 3) {
|
||||
case 0:
|
||||
/* Convert the image for quadrant bottom right */
|
||||
for (Y = OY; Y < (signed)GetBitmapHeight (B); ++Y) {
|
||||
signed i = 0;
|
||||
signed LastOpaquePixel = -1;
|
||||
char LineBuffer[512]; /* The maximum size is 508 pixels */
|
||||
|
||||
/* Fill the LineBuffer for easier optimisation */
|
||||
for (X = OX; X < (signed)GetBitmapWidth (B); ++X) {
|
||||
/* Fill the LineBuffer for easier optimisation */
|
||||
for (X = OX; X < (signed)GetBitmapWidth (B); ++X) {
|
||||
/* Fetch next bit into byte buffer */
|
||||
Val = GetPixel (B, X, Y).Index;
|
||||
if (Val > 16) Val = 16;
|
||||
LineBuffer[i] = Map[Val] & ColorMask;
|
||||
|
||||
/* Fetch next bit into byte buffer */
|
||||
LineBuffer[i] = GetPixel (B, X, Y).Index & ColorMask;
|
||||
if (Val != EdgeIndex) {
|
||||
LastOpaquePixel = i;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
if (LineBuffer[i] != EdgeIndex) {
|
||||
LastOpaquePixel = i;
|
||||
encodeSprite(D, M, ColorBits, ColorMask, LineBuffer, i, LastOpaquePixel);
|
||||
}
|
||||
++i;
|
||||
}
|
||||
if ((OY == 0) && (OX == 0)) {
|
||||
/* Trivial case only one quadrant */
|
||||
|
||||
encodeSprite(D, M, ColorBits, ColorMask, LineBuffer, i, LastOpaquePixel);
|
||||
}
|
||||
/* Mark end of sprite */
|
||||
SB_AppendChar (D, 0);
|
||||
|
||||
if ((OY == 0) && (OX == 0)) {
|
||||
/* Trivial case only one quadrant */
|
||||
|
||||
/* Mark end of sprite */
|
||||
SB_AppendChar (D, 0);
|
||||
|
||||
/* Return the converted bitmap */
|
||||
return D;
|
||||
}
|
||||
|
||||
/* Next quadrant */
|
||||
SB_AppendChar (D, 1);
|
||||
|
||||
/* Convert the image for quadrant top right */
|
||||
for (Y = OY - 1; Y >= 0; --Y) {
|
||||
signed i = 0;
|
||||
signed LastOpaquePixel = -1;
|
||||
char LineBuffer[512]; /* The maximum size is 508 pixels */
|
||||
|
||||
/* Fill the LineBuffer for easier optimisation */
|
||||
for (X = OX; X < (signed)GetBitmapWidth (B); ++X) {
|
||||
|
||||
/* Fetch next bit into byte buffer */
|
||||
LineBuffer[i] = GetPixel (B, X, Y).Index & ColorMask;
|
||||
|
||||
if (LineBuffer[i] != EdgeIndex) {
|
||||
LastOpaquePixel = i;
|
||||
/* Return the converted bitmap */
|
||||
return D;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
if ((quad == 1) && (OY == 0)) {
|
||||
/* Special case only two quadrants */
|
||||
|
||||
encodeSprite(D, M, ColorBits, ColorMask, LineBuffer, i, LastOpaquePixel);
|
||||
}
|
||||
/* Mark end of sprite */
|
||||
SB_AppendChar (D, 0);
|
||||
|
||||
if (OX == 0) {
|
||||
/* Special case only two quadrants */
|
||||
|
||||
/* Mark end of sprite */
|
||||
SB_AppendChar (D, 0);
|
||||
|
||||
/* Return the converted bitmap */
|
||||
return D;
|
||||
}
|
||||
|
||||
/* Next quadrant */
|
||||
SB_AppendChar (D, 1);
|
||||
|
||||
/* Convert the image for quadrant top left */
|
||||
for (Y = OY - 1; Y >= 0; --Y) {
|
||||
signed i = 0;
|
||||
signed LastOpaquePixel = -1;
|
||||
char LineBuffer[512]; /* The maximum size is 508 pixels */
|
||||
|
||||
/* Fill the LineBuffer for easier optimisation */
|
||||
for (X = OX - 1; X >= 0; --X) {
|
||||
|
||||
/* Fetch next bit into byte buffer */
|
||||
LineBuffer[i] = GetPixel (B, X, Y).Index & ColorMask;
|
||||
|
||||
if (LineBuffer[i] != EdgeIndex) {
|
||||
LastOpaquePixel = i;
|
||||
/* Return the converted bitmap */
|
||||
return D;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
/* Convert the image for quadrant top right */
|
||||
for (Y = OY - 1; Y >= 0; --Y) {
|
||||
signed i = 0;
|
||||
signed LastOpaquePixel = -1;
|
||||
char LineBuffer[512]; /* The maximum size is 508 pixels */
|
||||
|
||||
encodeSprite(D, M, ColorBits, ColorMask, LineBuffer, i, LastOpaquePixel);
|
||||
}
|
||||
/* Fill the LineBuffer for easier optimisation */
|
||||
for (X = OX; X < (signed)GetBitmapWidth (B); ++X) {
|
||||
/* Fetch next bit into byte buffer */
|
||||
Val = GetPixel (B, X, Y).Index;
|
||||
if (Val > 16) Val = 16;
|
||||
|
||||
/* Next quadrant */
|
||||
SB_AppendChar (D, 1);
|
||||
LineBuffer[i] = Map[Val] & ColorMask;
|
||||
|
||||
/* Convert the image for quadrant bottom left */
|
||||
for (Y = OY; Y < (signed)GetBitmapHeight (B); ++Y) {
|
||||
signed i = 0;
|
||||
signed LastOpaquePixel = -1;
|
||||
char LineBuffer[512]; /* The maximum size is 508 pixels */
|
||||
if (Val != EdgeIndex) {
|
||||
LastOpaquePixel = i;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
/* Fill the LineBuffer for easier optimisation */
|
||||
for (X = OX - 1; X >= 0; --X) {
|
||||
|
||||
/* Fetch next bit into byte buffer */
|
||||
LineBuffer[i] = GetPixel (B, X, Y).Index & ColorMask;
|
||||
|
||||
if (LineBuffer[i] != EdgeIndex) {
|
||||
LastOpaquePixel = i;
|
||||
encodeSprite(D, M, ColorBits, ColorMask, LineBuffer, i, LastOpaquePixel);
|
||||
}
|
||||
++i;
|
||||
|
||||
if ((OY == GetBitmapHeight (B) - 1) && (OX == 0)) {
|
||||
/* Trivial case only one quadrant */
|
||||
|
||||
/* Mark end of sprite */
|
||||
SB_AppendChar (D, 0);
|
||||
|
||||
/* Return the converted bitmap */
|
||||
return D;
|
||||
}
|
||||
if ((quad == 1) && (OX == 0)) {
|
||||
/* Special case only two quadrants */
|
||||
|
||||
/* Mark end of sprite */
|
||||
SB_AppendChar (D, 0);
|
||||
|
||||
/* Return the converted bitmap */
|
||||
return D;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
/* Convert the image for quadrant top left */
|
||||
for (Y = OY - 1; Y >= 0; --Y) {
|
||||
signed i = 0;
|
||||
signed LastOpaquePixel = -1;
|
||||
char LineBuffer[512]; /* The maximum size is 508 pixels */
|
||||
|
||||
/* Fill the LineBuffer for easier optimisation */
|
||||
for (X = OX - 1; X >= 0; --X) {
|
||||
/* Fetch next bit into byte buffer */
|
||||
Val = GetPixel (B, X, Y).Index;
|
||||
if (Val > 16) Val = 16;
|
||||
|
||||
LineBuffer[i] = Map[Val] & ColorMask;
|
||||
|
||||
if (Val != EdgeIndex) {
|
||||
LastOpaquePixel = i;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
encodeSprite(D, M, ColorBits, ColorMask, LineBuffer, i, LastOpaquePixel);
|
||||
}
|
||||
if ((OY == GetBitmapHeight (B) - 1) && (OX == GetBitmapWidth (B) - 1)) {
|
||||
/* Trivial case only one quadrant */
|
||||
|
||||
/* Mark end of sprite */
|
||||
SB_AppendChar (D, 0);
|
||||
|
||||
/* Return the converted bitmap */
|
||||
return D;
|
||||
}
|
||||
if ((quad == 1) && (OY == GetBitmapHeight (B) - 1)) {
|
||||
/* Special case only two quadrants */
|
||||
|
||||
/* Mark end of sprite */
|
||||
SB_AppendChar (D, 0);
|
||||
|
||||
/* Return the converted bitmap */
|
||||
return D;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
/* Convert the image for quadrant bottom left */
|
||||
for (Y = OY; Y < (signed)GetBitmapHeight (B); ++Y) {
|
||||
signed i = 0;
|
||||
signed LastOpaquePixel = -1;
|
||||
char LineBuffer[512]; /* The maximum size is 508 pixels */
|
||||
|
||||
/* Fill the LineBuffer for easier optimisation */
|
||||
for (X = OX - 1; X >= 0; --X) {
|
||||
/* Fetch next bit into byte buffer */
|
||||
Val = GetPixel (B, X, Y).Index;
|
||||
if (Val > 16) Val = 16;
|
||||
|
||||
LineBuffer[i] = Map[Val] & ColorMask;
|
||||
|
||||
if (Val != EdgeIndex) {
|
||||
LastOpaquePixel = i;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
encodeSprite(D, M, ColorBits, ColorMask, LineBuffer, i, LastOpaquePixel);
|
||||
}
|
||||
if ((OY == 0) && (OX == GetBitmapWidth (B) - 1)) {
|
||||
/* Trivial case only one quadrant */
|
||||
|
||||
/* Mark end of sprite */
|
||||
SB_AppendChar (D, 0);
|
||||
|
||||
/* Return the converted bitmap */
|
||||
return D;
|
||||
}
|
||||
if ((quad == 1) && (OX == GetBitmapWidth (B) - 1)) {
|
||||
/* Special case only two quadrants */
|
||||
|
||||
/* Mark end of sprite */
|
||||
SB_AppendChar (D, 0);
|
||||
|
||||
/* Return the converted bitmap */
|
||||
return D;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (quad < 3) {
|
||||
/* Next quadrant */
|
||||
SB_AppendChar (D, 1);
|
||||
} else {
|
||||
/* End sprite */
|
||||
SB_AppendChar (D, 0);
|
||||
}
|
||||
|
||||
encodeSprite(D, M, ColorBits, ColorMask, LineBuffer, i, LastOpaquePixel);
|
||||
}
|
||||
|
||||
/* End sprite */
|
||||
SB_AppendChar (D, 0);
|
||||
|
||||
/* Return the converted bitmap */
|
||||
return D;
|
||||
}
|
||||
|
|
|
@ -54,9 +54,9 @@
|
|||
|
||||
|
||||
StrBuf* GenLynxSprite (const Bitmap* B, const Collection* A);
|
||||
/* Generate binary output in packed Lynx sprite format for the bitmap B. The output
|
||||
** is stored in a string buffer (which is actually a dynamic char array) and
|
||||
** returned.
|
||||
/* Generate binary output in packed Lynx sprite format for the bitmap B.
|
||||
** The output is stored in a string buffer (which is actually a dynamic
|
||||
** char array) and returned.
|
||||
*/
|
||||
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user