1
0
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:
mrdudz 2023-01-28 11:22:20 +01:00
commit 61f2f4fa56
115 changed files with 3710 additions and 761 deletions

View File

@ -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

View File

@ -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
View 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
View 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
View 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;
}

View File

@ -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>

View File

@ -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

View File

@ -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&sol;enumdevdir.c/
</descrip>
</quote>
@ -6908,7 +6949,6 @@ switching the CPU into single clock mode.
</descrip>
</quote>
<sect1>srand<label id="srand"><p>
<quote>

View File

@ -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
View 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
&quot;platform dependent&quot; 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 &dollar;200 - &dollar;0FFF. The 60k config expands
this range to &dollar;DFFF. The starting memory location and entry point for running the program is
&dollar;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 &dollar;0FFF on 4kb KIM-1s, or at &dollar;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 &quot;master console&quot;
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 &quot;Hello World!&quot; 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>

View File

@ -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>

View File

@ -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

View File

@ -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[];

View File

@ -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[];

View File

@ -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[] */

View File

@ -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[];

View File

@ -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[] */

View File

@ -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[] */

View File

@ -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
View 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

View File

@ -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[] */

View File

@ -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

View File

@ -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[] */

View File

@ -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 */

View File

@ -27,6 +27,7 @@ TARGETS = apple2 \
$(CBMS) \
$(GEOS) \
gamate \
kim1 \
lynx \
nes \
none \

View File

@ -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

View 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

View 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

View 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
View 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
View 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

View 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
View 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"

View 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
View 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"

View 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
View 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"

View 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

View 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"

View 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

View 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
View 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
View File

@ -0,0 +1,5 @@
; Character specification table.
;
; uses the "common" definition
.include "ctype_common.inc"

51
libsrc/kim1/read.s Normal file
View 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
View 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
View 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

View 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

View 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
View 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"

View File

@ -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 \

View File

@ -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
View 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
View 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
View 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
View 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);
}
}
}

View File

@ -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);

View File

@ -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.

View File

@ -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
/*****************************************************************************/

View File

@ -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.

View File

@ -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 {

View File

@ -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);

View File

@ -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

View File

@ -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);
}
}

View File

@ -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"));

View File

@ -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;
}

View File

@ -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:

View File

@ -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);
}

View File

@ -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 */

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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)) {

View File

@ -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 */

View File

@ -87,6 +87,7 @@ typedef enum {
TGT_C65,
TGT_CX16,
TGT_SYM1,
TGT_KIM1,
TGT_COUNT /* Number of target systems */
} target_t;

View File

@ -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') {

View File

@ -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);
}

View File

@ -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 */

View File

@ -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 */
{

View File

@ -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 */

View File

@ -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];
}

View File

@ -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;

View File

@ -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 */

View File

@ -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 */

View File

@ -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) {

View File

@ -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 ();
}

View File

@ -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);

View File

@ -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 */
};

View File

@ -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 */

View File

@ -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;

View File

@ -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 ();
}

View File

@ -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 */

View File

@ -90,6 +90,8 @@ typedef enum token_t {
INFOTOK_START,
INFOTOK_END,
INFOTOK_TYPE,
INFOTOK_ADDRMODE,
INFOTOK_UNIT,
INFOTOK_CODE,
INFOTOK_BYTETAB,

View File

@ -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;

View File

@ -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);

View File

@ -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>

View File

@ -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
View 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
View 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

View File

@ -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;
}

View File

@ -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