1
0
mirror of https://github.com/cc65/cc65.git synced 2025-04-12 00:37:12 +00:00

Merge remote-tracking branch 'upstream/master' into pcenginetarget

This commit is contained in:
mrdudz 2015-07-11 13:05:26 +02:00
commit 877fd532c2
112 changed files with 3314 additions and 940 deletions

View File

@ -5,6 +5,7 @@ install:
script:
- make bin USER_CFLAGS=-Werror
- make lib QUIET=1
- make -C test
- make -C src clean
- make bin USER_CFLAGS=-Werror CROSS_COMPILE=i686-w64-mingw32-
- make doc zip

41
LICENSE
View File

@ -1,44 +1,3 @@
This is the original cc65 compiler copyright:
-*- Mode: Text -*-
This is the copyright notice for RA65, LINK65, LIBR65, and other
Atari 8-bit programs. Said programs are Copyright 1989, by John R.
Dunning. All rights reserved, with the following exceptions:
Anyone may copy or redistribute these programs, provided that:
1: You don't charge anything for the copy. It is permissable to
charge a nominal fee for media, etc.
2: All source code and documentation for the programs is made
available as part of the distribution.
3: This copyright notice is preserved verbatim, and included in
the distribution.
You are allowed to modify these programs, and redistribute the
modified versions, provided that the modifications are clearly noted.
There is NO WARRANTY with this software, it comes as is, and is
distributed in the hope that it may be useful.
This copyright notice applies to any program which contains
this text, or the refers to this file.
This copyright notice is based on the one published by the Free
Software Foundation, sometimes known as the GNU project. The idea
is the same as theirs, ie the software is free, and is intended to
stay that way. Everybody has the right to copy, modify, and re-
distribute this software. Nobody has the right to prevent anyone
else from copying, modifying or redistributing it.
In acknowledgment of this copyright, I (Ullrich von Bassewitz) will place
my own changes to the compiler under the same copyright.
The library and the binary utils are a complete rewrite done by me and
covered by the following license:
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from
the use of this software.

View File

@ -24,7 +24,7 @@ endif
SF_USER = oliverschmidt
SF_HOST = frs.sourceforge.net
SF_FILE = /home/frs/project/cc65/cc65-snapshot-win64.zip
SF_FILE = /home/frs/project/cc65/cc65-snapshot-win32.zip
SCPFLAGS = -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -q

View File

@ -27,6 +27,7 @@ including
- the Supervision console.
- the Oric Atmos.
- the Lynx console.
- the Ohio Scientific Challenger 1P
The libraries are fairly portable, so creating a version for other 6502s
shouldn't be too much work.

View File

@ -1,22 +1,31 @@
SYMBOLS {
__STACKSIZE__: type = weak, value = $0800; # 2k stack
__TAPEHDR__: type = import;
__BASHDR__: type = import;
__PROGFLAG__: type = weak, value = $00; # $00=BASIC, $80=machine code
__AUTORUN__: type = weak, value = $00; # $00=only load, $C7=run
__STACKSIZE__: type = weak, value = $0800; # 2K stack
__GRAB__: type = weak, value = 0; # 0=don't grab graphics RAM, 1=grab graphics RAM
__RAMEND__: type = weak, value = $9800 + $1C00 * __GRAB__;
}
MEMORY {
ZP: file = "", define = yes, start = $00E2, size = $001A;
TAPEHDR: file = %O, type = ro, start = $0000, size = $0011;
RAM: file = %O, define = yes, start = $0500, size = $9300 - __STACKSIZE__;
TAPEHDR: file = %O, type = ro, start = $0000, size = $001F;
BASHEAD: file = %O, define = yes, start = $0501, size = $000D;
RAM: file = %O, define = yes, start = __BASHEAD_LAST__, size = __RAMEND__ - __RAM_START__ - __STACKSIZE__;
}
SEGMENTS {
ZEROPAGE: load = ZP, type = zp;
TAPEHDR: load = TAPEHDR, type = ro;
BASHDR: load = BASHEAD, type = ro, define = yes, optional = yes;
STARTUP: load = RAM, type = ro;
LOWCODE: load = RAM, type = ro, optional = yes;
INIT: load = RAM, type = ro, define = yes, optional = yes;
CODE: load = RAM, type = ro;
RODATA: load = RAM, type = ro;
INIT: load = RAM, type = ro, define = yes, optional = yes;
DATA: load = RAM, type = rw;
ZPSAVE: load = RAM, type = bss, define = yes;
ZPSAVE1: load = RAM, type = rw, define = yes; # ZPSAVE1, ZPSAVE2 must be together
ZPSAVE2: load = RAM, type = bss; # see "libsrc/atmos/crt0.s"
BSS: load = RAM, type = bss, define = yes;
ZEROPAGE: load = ZP, type = zp;
}
FEATURES {
CONDES: type = constructor,

25
cfg/osic1p-asm.cfg Normal file
View File

@ -0,0 +1,25 @@
FEATURES {
STARTADDRESS: default = $0200;
}
SYMBOLS {
# If you want ld65 to output a loadable-format file by default, then uncomment
# the next line. (Then, "-u __BOOT__" wouldn't be needed on the command line.)
# __BOOT__: type = import;
__STACKSIZE__: type = weak, value = $0400; # 1 kB stack
__HIMEM__: type = weak, value = $8000; # 32 kB RAM
}
MEMORY {
# for size of ZP, see runtime/zeropage.s and c1p/extzp.s
ZP: file = "", define = yes, start = $0002, size = $001A + $0006;
HEAD: file = %O, start = $0000, size = $00B6;
RAM: file = %O, define = yes, start = %S, size = __HIMEM__ - __STACKSIZE__ - %S;
}
SEGMENTS {
BOOT: load = HEAD, type = ro, optional = yes;
INIT: load = RAM, type = ro, define = yes, optional = yes;
CODE: load = RAM, type = rw;
RODATA: load = RAM, type = rw;
DATA: load = RAM, type = rw;
BSS: load = RAM, type = bss, define = yes;
ZEROPAGE: load = ZP, type = zp;
}

38
cfg/osic1p.cfg Normal file
View File

@ -0,0 +1,38 @@
FEATURES {
STARTADDRESS: default = $0200;
}
SYMBOLS {
# If you want ld65 to output a loadable-format file by default, then uncomment
# the next line. (Then, "-u __BOOT__" wouldn't be needed on the command line.)
# __BOOT__: type = import;
__STACKSIZE__: type = weak, value = $0400; # 1 kB stack
__HIMEM__: type = weak, value = $8000; # 32 kB RAM
}
MEMORY {
# for size of ZP, see runtime/zeropage.s and c1p/extzp.s
ZP: file = "", define = yes, start = $0002, size = $001A + $0020;
HEAD: file = %O, start = $0000, size = $00B6;
RAM: file = %O, define = yes, start = %S, size = __HIMEM__ - __STACKSIZE__ - %S;
}
SEGMENTS {
BOOT: load = HEAD, type = ro, optional = yes;
STARTUP: load = RAM, type = ro;
LOWCODE: load = RAM, type = ro, optional = yes;
INIT: load = RAM, type = ro, define = yes, optional = yes;
CODE: load = RAM, type = rw;
RODATA: load = RAM, type = rw;
DATA: load = RAM, type = rw;
BSS: load = RAM, type = bss, define = yes;
ZEROPAGE: load = ZP, type = zp;
EXTZP: load = ZP, type = zp, define = yes, optional = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
segment = INIT;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
segment = RODATA;
}

View File

@ -2,7 +2,7 @@ ifneq ($(shell echo),)
CMD_EXE = 1
endif
.PHONY: all mostlyclean clean install zip doc html info gh-pages
.PHONY: all mostlyclean clean install zip doc html info
.SUFFIXES:

View File

@ -7,7 +7,7 @@
<url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline>
<url url="mailto:polluks@sdf.lonestar.org" name="Stefan A. Haubenthal">,<newline>
<url url="mailto:greg.king5@verizon.net" name="Greg King">
<date>2014-03-27
<date>2015-01-09
<abstract>
An overview over the Atmos runtime system as it is implemented for the cc65 C
@ -32,27 +32,39 @@ more than one platform. Please see the function reference for more
information.
<sect>Binary format<p>
The standard binary output format generated by the linker for the Atmos target
is a machine language program with a 17 byte tape header including a cc65 tag.
The standard load and autostart address is &dollar;500.
is a machine language program with a one-line BASIC stub that jumps to the
machine-language part through <tt/CALL/. It has one sacrificial byte attached
to the end (a bug in the Oric ROM means that BASIC can put a variable on top
of the last byte that was loaded). It has a 24-byte tape header. A file can
be CLOADed as a BASIC program, and started by typing <tt/RUN/. The standard
load address is &dollar;501.
<sect>Memory layout<p>
In the standard setup, cc65 generated programs use the memory from
&dollar;500 to &dollar;9800, so nearly 37K of memory (including the stack) is
In the standard setup, cc65-generated programs use the memory from
&dollar;0501 to &dollar;9800; so, nearly 37K of memory (including the stack) is
available. ROM calls are possible without further precautions.
If your program needs more memory, and it won't use TGI graphics, then you can
use the ld65 command-line option, <tt/-D __GRAB__=1/, when building the
program, to include the graphics screen RAM. Then, nearly 44K of memory
(&dollar;0501 to &dollar;B400) is available.
Special locations:
<descrip>
<tag/Stack/
The C runtime stack is located at &dollar;97FF and growing downwards.
The C runtime stack is located at &dollar;97FF (or &dollar;B3FF), and grows
downwards.
<tag/Heap/
The C heap is located at the end of the program and grows towards the C
The C heap is located at the end of the program, and grows towards the C
runtime stack.
</descrip><p>
@ -90,7 +102,7 @@ structures; accessing the struct fields will access the chip registers.
<descrip>
<tag><tt/VIA/</tag>
Access to the VIA (versatile interface adapter) chip is available via the
Access to the VIA (Versatile Interface Adapter) chip is available via the
<tt/VIA/ variable. The structure behind this variable is explained in <tt/_6522.h/.
</descrip><p>
@ -117,7 +129,8 @@ The names in the parentheses denote the symbols to be used for static linking of
<sect1>Graphics drivers<p>
The default drivers, <tt/tgi_stddrv (tgi_static_stddrv)/, point to <tt/atmos-240-200-2.tgi (atmos_240_200_2_tgi)/.
The default drivers, <tt/tgi_stddrv (tgi_static_stddrv)/,
point to <tt/atmos-240-200-2.tgi (atmos_240_200_2_tgi)/.
<descrip>
@ -175,13 +188,14 @@ No mouse drivers are currently available for the Atmos.
<sect1>Disk I/O<p>
The existing library for the Atmos doesn't implement C file
I/O. There are hacks for the <tt/read()/ and <tt/write()/ routines in
place, which will make functions work that read from and write to <tt/stdout/
(like <tt/printf()/). However, those functions have some shortcomings which
won't be fixed, because they're going to be replaced anyway.
The existing library for the Atmos doesn't implement C file I/O. There are
hacks for the <tt/read()/ and <tt/write()/ routines in place, which will make
functions work that read from <tt/stdin/ and write to <tt/stdout/ and
<tt/stderr/ (such as <tt/printf()/). However, those functions have some
shortcomings which won't be fixed, because they're going to be replaced
anyway.
To be more concrete, the limitation means that you cannot use any of the
To be more concrete, that limitation means that you cannot use any of the
following functions (and a few others):
<itemize>
@ -202,7 +216,14 @@ following functions (and a few others):
<sect1>Function keys<p>
These are defined to be FUNCT + number key.
They are defined to be FUNCT + a number key.
<sect1>Capitals lock<p>
The keyboard's "CAPS Lock" mode is turned off while the program is running.
The previous mode (usually, CAPS Lock turned on [because Oric BASIC keywords
must be UPPER-case]) is restored when the program stops.
<sect1>Passing arguments to the program<p>
@ -211,10 +232,12 @@ Command-line arguments can be passed to <tt/main()/. Since that is not
supported directly by BASIC, the following syntax was chosen:
<tscreen><verb>
CALL#500:REM ARG1 " ARG2 IS QUOTED" ARG3 "" ARG5
RUN:REM arg1 " ARG2 IS QUOTED" ARG3 "" ARG5
</verb></tscreen>
<enum>
<item>You must turn <tt/CAPS/ lock off (tap CTRL-T) when you want to type
lower-case arguments (but, <tt/RUN/ and <tt/REM/ must be UPPER-case).
<item>Arguments are separated by spaces.
<item>Arguments may be quoted.
<item>Leading and trailing spaces around an argument are ignored. Spaces within
@ -225,6 +248,15 @@ supported directly by BASIC, the following syntax was chosen:
</enum>
<sect1>Automatic starting<p>
Usually, a cc65-built program just will sit quietly in memory, after it is
CLOADed. It waits for you to start it (by typing BASIC's <tt/RUN/ command).
But, if you want to create a program that will start running immediately after
it is loaded, then you can use the linker command-line option
<tt/-D __AUTORUN__=$C7/.
<sect1>Interrupts<p>
The runtime for the Atmos uses routines marked as <tt/.INTERRUPTOR/ for

View File

@ -1279,6 +1279,35 @@ Pseudo functions expect their arguments in parenthesis, and they have a result,
either a string or an expression.
<sect1><tt>.ADDRSIZE</tt><label id=".ADDRSIZE"><p>
The <tt/.ADDRSIZE/ function is used to return the interal address size
associated with a symbol. This can be helpful in macros when knowing the address
size of symbol can help with custom instructions.
Example:
<tscreen><verb>
.macro myLDA foo
.if .ADDRSIZE(foo) = 1
;do custom command based on zeropage addressing:
.byte 0A5h, foo
.elseif .ADDRSIZE(foo) = 2
;do custom command based on absolute addressing:
.byte 0ADh
.word foo
.elseif .ADDRSIZE(foo) = 0
; no address size defined for this symbol:
.out .sprintf("Error, address size unknown for symbol %s", .string(foo))
.endif
.endmacro
</verb></tscreen>
This command is new and must be enabled with the <tt/.FEATURE addrsize/ command.
See: <tt><ref id=".FEATURE" name=".FEATURE"></tt>
<sect1><tt>.BANK</tt><label id=".BANK"><p>
The <tt/.BANK/ function is used to support systems with banked memory. The
@ -2287,6 +2316,24 @@ Here's a list of all control commands and a description, what they do:
</verb></tscreen>
<sect1><tt>.ISMNEM, .ISMNEMONIC</tt><label id=".ISMNEMONIC"><p>
Builtin function. The function expects an identifier as argument in braces.
The argument is evaluated, and the function yields "true" if the identifier
is defined as an instruction mnemonic that is recognized by the assembler.
Example:
<tscreen><verb>
.if .not .ismnemonic(ina)
.macro ina
clc
adc #$01
.endmacro
.endif
</verb></tscreen>
<sect1><tt>.DESTRUCTOR</tt><label id=".DESTRUCTOR"><p>
Export a symbol and mark it as a module destructor. This may be used
@ -2596,6 +2643,12 @@ Here's a list of all control commands and a description, what they do:
<descrip>
<tag><tt>addrsize</tt><label id="addrsize"></tag>
Enables the .ADDRSIZE pseudo function. This function is experimental and not enabled by default.
See also: <tt><ref id=".ADDRSIZE" name=".ADDRSIZE"></tt>
<tag><tt>at_in_identifiers</tt><label id="at_in_identifiers"></tag>
Accept the at character (`@') as a valid character in identifiers. The
@ -4418,6 +4471,7 @@ compiler, depending on the target system selected:
<item><tt/__LUNIX__/ - Target system is <tt/lunix/
<item><tt/__LYNX__/ - Target system is <tt/lynx/
<item><tt/__NES__/ - Target system is <tt/nes/
<item><tt/__OSIC1P__/ - Target system is <tt/osic1p/
<item><tt/__PET__/ - Target system is <tt/pet/
<item><tt/__PLUS4__/ - Target system is <tt/plus4/
<item><tt/__SIM6502__/ - Target system is <tt/sim6502/

View File

@ -3,7 +3,7 @@
<article>
<title>cc65 Users Guide
<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">
<date>2000-09-03, 2001-10-02, 2005-08-01
<date>2015-05-26
<abstract>
cc65 is a C compiler for 6502 targets. It supports several 6502 based home
@ -74,6 +74,7 @@ Short options:
Long options:
--add-source Include source as comment
--all-cdecl Make functions default to __cdecl__
--bss-name seg Set the name of the BSS segment
--check-stack Generate stack overflow checks
--code-name seg Set the name of the CODE segment
@ -114,6 +115,14 @@ Here is a description of all the command line options:
<descrip>
<tag><tt>--all-cdecl</tt></tag>
Tells the compiler that functions which aren't declared explicitly with
either the <tt/__cdecl__/ or <tt/__fastcall__/ calling conventions should
have the cdecl convention. (Normally, functions that aren't variadic are
fast-called.)
<label id="option-bss-name">
<tag><tt>--bss-name seg</tt></tag>
@ -348,6 +357,7 @@ Here is a description of all the command line options:
<item>lunix
<item>lynx
<item>nes
<item>osic1p
<item>pet (all CBM PET systems except the 2001)
<item>plus4
<item>sim6502
@ -549,9 +559,10 @@ and the one defined by the ISO standard:
be passed as parameters by value. However, struct assignment *is*
possible.
<p>
<item> Part of the C library is available only with fastcall calling
conventions (see below). It means that you must not mix pointers to
those functions with pointers to user-written, not-fastcall functions.
<item> Most of the C library is available with only the fastcall calling
convention (<ref id="extension-fastcall" name="see below">). It means
that you must not mix pointers to those functions with pointers to
user-written, cdecl functions (the calling conventions are incompatible).
<p>
<item> The <tt/volatile/ keyword doesn't have an effect. This is not as bad
as it sounds, since the 6502 has so few registers that it isn't
@ -589,30 +600,58 @@ This cc65 version has some extensions to the ISO C standard.
<ref id="inline-asm" name="see there">.
<p>
<item> There is a special calling convention named "fastcall".
The syntax for a function declaration using fastcall is
<label id="extension-fastcall">
<item> The normal calling convention -- for non-variadic functions -- is
named "fastcall". The syntax for a function declaration that
<em/explicitly/ uses fastcall is
<tscreen><verb>
&lt;return type&gt; fastcall &lt;function name&gt; (&lt;parameter list&gt;)
</verb></tscreen>
or
<tscreen><verb>
&lt;return type&gt; __fastcall__ &lt;function name&gt; (&lt;parameter list&gt;)
&lt;return type&gt; __fastcall__ &lt;function name&gt; (&lt;parameter list&gt;)
</verb></tscreen>
An example would be
An example is
<tscreen><verb>
void __fastcall__ f (unsigned char c)
void __fastcall__ f (unsigned char c)
</verb></tscreen>
The first form of the fastcall keyword is in the user namespace and can
therefore be disabled with the <tt><ref id="option--standard"
name="--standard"></tt> command line option.
For functions declared as <tt/fastcall/, the rightmost parameter is not
For functions that are <tt/fastcall/, the rightmost parameter is not
pushed on the stack but left in the primary register when the function
is called. This will reduce the cost when calling assembler functions
significantly, especially when the function itself is rather small.
is called. That significantly reduces the cost of calling those functions.
<newline><newline>
<p>
<item> There is another calling convention named "cdecl". Variadic functions
(their prototypes have an ellipsis &lsqb;<tt/.../&rsqb;) always use that
convention. The syntax for a function declaration using cdecl is
<tscreen><verb>
&lt;return type&gt; cdecl &lt;function name&gt; (&lt;parameter list&gt;)
</verb></tscreen>
or
<tscreen><verb>
&lt;return type&gt; __cdecl__ &lt;function name&gt; (&lt;parameter list&gt;)
</verb></tscreen>
An example is
<tscreen><verb>
int* __cdecl__ f (unsigned char c)
</verb></tscreen>
The first form of the cdecl keyword is in the user namespace;
and therefore, can be disabled with the <tt/<ref id="option--standard"
name="--standard">/ command-line option.
For functions that are <tt/cdecl/, the rightmost parameter is pushed
onto the stack before the function is called. That increases the cost
of calling those functions, especially when they are called from many
places.<newline><newline>
<p>
<item> There are two pseudo variables named <tt/__AX__/ and <tt/__EAX__/.
Both refer to the primary register that is used by the compiler to
evaluate expressions or return function results. <tt/__AX__/ is of
@ -819,6 +858,11 @@ The compiler defines several macros at startup:
Is defined if the compiler was called with the <tt/-Os/ command line option.
<tag><tt>__OSIC1P__</tt></tag>
This macro is defined if the target is the Ohio Scientific Challenger 1P
(-t osic1p).
<tag><tt>__PET__</tt></tag>
This macro is defined if the target is the PET family of computers (-t pet).

View File

@ -3,7 +3,7 @@
<article>
<title>Defining a Custom cc65 Target
<author>Bruce Reidenbach
<date>2010-02-22
<date>2015-03-13
<abstract>
This section provides step-by-step instructions on how to use the cc65
@ -525,15 +525,16 @@ The first step in creating the assembly language code for the driver is
to determine how to pass the C arguments to the assembly language
routine. The cc65 toolset allows the user to specify whether the data
is passed to a subroutine via the stack or by the processor registers by
using the <tt>__fastcall__</tt> function declaration (note that there
are two underscore characters in front of and two behind the
<tt>fastcall</tt> declaration). When <tt>__fastcall__</tt> is
specified, the rightmost argument in the function call is passed to the
using the <tt/__fastcall__/ and <tt/__cdecl__/ function qualifiers (note that
there are two underscore characters in front of and two behind each
qualifier). <tt/__fastcall__/ is the default. When <tt/__cdecl__/ <em/isn't/
specified, and the function isn't variadic (i.e., its prototype doesn't have
an ellipsis), the rightmost argument in the function call is passed to the
subroutine using the 6502 registers instead of the stack. Note that if
there is only one argument in the function call, the execution overhead
required by the stack interface routines is completely avoided.
Without <tt>__fastcall__</tt>, the argument is loaded in the A and X
With <tt/__cdecl__</tt>, the last argument is loaded into the A and X
registers and then pushed onto the stack via a call to <tt>pushax</tt>.
The first thing the subroutine does is retrieve the argument from the
stack via a call to <tt>ldax0sp</tt>, which copies the values into the A
@ -561,7 +562,7 @@ _foo: jsr ldax0sp ; Retrieve A and X from the stack
jmp incsp2 ; Pop A and X from the stack (includes return)
</verb></tscreen>
If <tt>__fastcall__</tt> is specified, the argument is loaded into the A
If <tt/__cdecl__/ isn't specified, then the argument is loaded into the A
and X registers as before, but the subroutine is then called
immediately. The subroutine does not need to retrieve the argument
since the value is already available in the A and X registers.

View File

@ -2,12 +2,14 @@
<article>
<title>da65 Users Guide
<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">
<date>2003-08-08
<author>
<url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline>
<url url="mailto:greg.king5@verizon.net" name="Greg King">
<date>2014-11-23
<abstract>
da65 is a 6502/65C02 disassembler that is able to read user supplied
information about its input data for better results. The output is ready for
da65 is a 6502/65C02 disassembler that is able to read user-supplied
information about its input data, for better results. The output is ready for
feeding into ca65, the macro assembler supplied with the cc65 C compiler.
</abstract>
@ -23,7 +25,7 @@ the cc65 C compiler and generates output that is suitable for the ca65
macro assembler.
Besides generating output for ca65, one of the design goals was that the user
is able to feed additional information about the code into the disassembler
is able to feed additional information about the code into the disassembler,
for improved results. This information may include the location and size of
tables, and their format.
@ -106,11 +108,16 @@ Here is a description of all the command line options:
<tag><tt>--cpu type</tt></tag>
Set the CPU type. The option takes a parameter, which may be one of
<itemize>
<item>6502
<item>6502x
<item>65sc02
<item>65c02
<item>huc6280
</itemize>
6502, 6502x, 65sc02, 65c02, huc6280
6502x is the NMOS 6502 with illegal opcodes. huc6280 is the CPU of the PC
engine. Support for the 65816 is currently not available.
6502x is for the NMOS 6502 with unofficial opcodes. huc6280 is the CPU of
the PC engine. Support for the 65816 currently is not available.
<label id="option--formfeeds">
@ -125,7 +132,7 @@ Here is a description of all the command line options:
<tag><tt>-g, --debug-info</tt></tag>
This option adds the <tt/.DEBUGINFO/ command to the output file, so the
assembler will generate debug information when reassembling the generated
assembler will generate debug information when re-assembling the generated
output.
@ -241,7 +248,7 @@ unsupported.
The disassembler works by creating an attribute map for the whole address
space ($0000 - $FFFF). Initially, all attributes are cleared. Then, an
external info file (if given) is read. Disassembly is done in several passes.
In all passes with the exception of the last one, information about the
In all passes, with the exception of the last one, information about the
disassembled code is gathered and added to the symbol and attribute maps. The
last pass generates output using the information from the maps.
@ -275,19 +282,19 @@ braces. Attributes have a name followed by a value. The syntax of the value
depends on the type of the attribute. String attributes are places in double
quotes, numeric attributes may be specified as decimal numbers or hexadecimal
with a leading dollar sign. There are also attributes where the attribute
value is a keyword, in this case the keyword is given as is (without quotes or
value is a keyword; in this case, the keyword is given as-is (without quotes or
anything). Each attribute is terminated by a semicolon.
<tscreen><verb>
group-name { attribute1 attribute-value; attribute2 attribute-value; }
group-name { attribute1 attribute-value; attribute2 attribute-value; }
</verb></tscreen>
<sect1>Comments<p>
Comments start with a hash mark (<tt/#/) and extend from the position of
Comments start with a hash mark (<tt/#/); and, extend from the position of
the mark to the end of the current line. Hash marks inside of strings will
of course <em/not/ start a comment.
<em/not/ start a comment, of course.
<sect1>Specifying global options<label id="global-options"><p>
@ -543,18 +550,17 @@ disassembled code. The following attributes are recognized:
<tag><tt>END</tt></tag>
Followed by a numerical value. Specifies the end address of the segment. The
end address is last the address that is part of the segment.
end address is the last address that is a part of the segment.
<tag><tt>NAME</tt></tag>
The attribute is followed by a string value which gives the name of the
segment.
</descrip>
All attributes are mandatory. Segments may not overlap. Since there is no
explicit "end this segment" pseudo op, the disassembler cannot notify the
assembler that one segment has ended. This may lead to errors if you don't
define your segments carefully. As a rule of thumb, if you're using segments,
your should define segments for all disassembled code.
All attributes are mandatory. Segments must not overlap. The disassembler will
change back to the (default) <tt/.code/ segment after the end of each defined
segment. That might not be what you want. As a rule of thumb, if you're using
segments, you should define segments for all disassembled code.
<sect1>Specifying Assembler Includes<label id="infofile-asminc"><p>
@ -563,8 +569,8 @@ The <tt/ASMINC/ directive is used to give the names of input files containing
symbol assignments in assembler syntax:
<tscreen><verb>
Name = value
Name := value
Name = value
Name := value
</verb></tscreen>
The usual conventions apply for symbol names. Values may be specified as hex
@ -613,48 +619,46 @@ directives explained above:
};
# One segment for the whole stuff
SEGMENT { START $E000; END $FFFF; NAME kernal; };
SEGMENT { START $E000; END $FFFF; NAME "kernal"; };
RANGE { START $E612; END $E631; TYPE Code; };
RANGE { START $E632; END $E640; TYPE ByteTable; };
RANGE { START $EA51; END $EA84; TYPE RtsTable; };
RANGE { START $EC6C; END $ECAB; TYPE RtsTable; };
RANGE { START $ED08; END $ED11; TYPE AddrTable; };
RANGE { START $E612; END $E631; TYPE Code; };
RANGE { START $E632; END $E640; TYPE ByteTable; };
RANGE { START $EA51; END $EA84; TYPE RtsTable; };
RANGE { START $EC6C; END $ECAB; TYPE RtsTable; };
RANGE { START $ED08; END $ED11; TYPE AddrTable; };
# Zero page variables
LABEL { NAME "fnadr"; ADDR $90; SIZE 3; };
LABEL { NAME "sal"; ADDR $93; };
LABEL { NAME "sah"; ADDR $94; };
LABEL { NAME "sas"; ADDR $95; };
# Zero-page variables
LABEL { NAME "fnadr"; ADDR $90; SIZE 3; };
LABEL { NAME "sal"; ADDR $93; };
LABEL { NAME "sah"; ADDR $94; };
LABEL { NAME "sas"; ADDR $95; };
# Stack
LABEL { NAME "stack"; ADDR $100; SIZE 255; };
LABEL { NAME "stack"; ADDR $100; SIZE 255; };
# Indirect vectors
LABEL { NAME "cinv"; ADDR $300; SIZE 2; }; # IRQ
LABEL { NAME "cbinv"; ADDR $302; SIZE 2; }; # BRK
LABEL { NAME "nminv"; ADDR $304; SIZE 2; }; # NMI
LABEL { NAME "cinv"; ADDR $300; SIZE 2; }; # IRQ
LABEL { NAME "cbinv"; ADDR $302; SIZE 2; }; # BRK
LABEL { NAME "nminv"; ADDR $304; SIZE 2; }; # NMI
# Jump table at end of kernal ROM
LABEL { NAME "kscrorg"; ADDR $FFED; };
LABEL { NAME "kplot"; ADDR $FFF0; };
LABEL { NAME "kiobase"; ADDR $FFF3; };
LABEL { NAME "kgbye"; ADDR $FFF6; };
LABEL { NAME "kscrorg"; ADDR $FFED; };
LABEL { NAME "kplot"; ADDR $FFF0; };
LABEL { NAME "kiobase"; ADDR $FFF3; };
LABEL { NAME "kgbye"; ADDR $FFF6; };
# Hardware vectors
LABEL { NAME "hanmi"; ADDR $FFFA; };
LABEL { NAME "hares"; ADDR $FFFC; };
LABEL { NAME "hairq"; ADDR $FFFE; };
LABEL { NAME "hanmi"; ADDR $FFFA; };
LABEL { NAME "hares"; ADDR $FFFC; };
LABEL { NAME "hairq"; ADDR $FFFE; };
</verb></tscreen>
<sect>Copyright<p>
da65 (and all cc65 binutils) are (C) Copyright 1998-2007 Ullrich von
Bassewitz. For usage of the binaries and/or sources the following
da65 (and all cc65 binutils) is (C) Copyright 1998-2011, Ullrich von
Bassewitz. For usage of the binaries and/or sources, the following
conditions do apply:
This software is provided 'as-is', without any expressed or implied
@ -666,20 +670,16 @@ 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.
<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>

File diff suppressed because it is too large Load Diff

View File

@ -134,6 +134,9 @@
<tag><htmlurl url="nes.html" name="nes.html"></tag>
Topics specific to the Nintendo Entertainment System.
<tag><htmlurl url="osi.html" name="osi.html"></tag>
Topics specific to the Ohio Scientific machines.
<tag><htmlurl url="pet.html" name="pet.html"></tag>
Topics specific to the Commodore PET machines.

View File

@ -6,8 +6,9 @@
<author>
<url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline>
<url url="mailto:cbmnut@hushmail.com" name="CbmNut">,<newline>
<url url="mailto:greg.king5@verizon.net" name="Greg King">
<date>2014-4-24
<url url="mailto:greg.king5@verizon.net" name="Greg King">,<newline>
<url url="mailto:stephan.muehlstrasser@web.de" name="Stephan M&uuml;hlstrasser">
<date>2015-03-07
<abstract>
How to use the cc65 C language system -- an introduction.
@ -342,8 +343,8 @@ Available at <url
url="http://code.google.com/p/oriculator/">:
Emulates Oric-1 and Atmos computers, with sound, disk images,
scanline-exact NTSC/PAL video, and movie export. Includes monitor.
Fortunately for all SDL platforms. You will just need the emulator, all
scanline-exact NTSC/PAL video, and movie export. Includes a monitor.
Fortunately, for all SDL platforms. You will need just the emulator; all
ROMs are supplied.
Compile the tutorial with
@ -353,8 +354,11 @@ cl65 -O -t atmos hello.c text.s -o hello.tap
</verb></tscreen>
Start the emulator, choose <bf/F1/ and <bf/Insert tape.../, and point to
the "<bf/hello.tap/" executable. The file has an auto start header meant to
be loaded directly from tape.
the "<bf/hello.tap/" executable. After it has finished loading, type
<tscreen><verb>
RUN
</verb></tscreen>
On a real Atmos, you would need a tape drive.
Turn on the computer, type
@ -363,7 +367,11 @@ Turn on the computer, type
CLOAD""
</verb></tscreen>
at the BASIC prompt.
at the BASIC prompt. After it has finished loading, type
<tscreen><verb>
RUN
</verb></tscreen>
The emulation, also, supports that method.
@ -514,6 +522,127 @@ The output is shown in a GEOS dialog box; click <bf/OK/ when you have finished
reading it.
<sect1>Ohio Scientific Challenger 1P<p>
The <tt/osic1p/ runtime library returns to the boot prompt when the main()
program exits. Therefore, the C file in the tutorial must be modified
slightly, in order to see the results on the screen. Otherwise, the program
would print the text string, and then jump to the boot prompt, making it
impossible to see the results of running the tutorial program.
In addition to that, the <tt/osic1p/ target does not yet have support for stdio
functions. Only the functions from the conio library are available.
Therefore, modify the "<tt/hello.c/" source file, as follows:
<tscreen><code>
#include <conio.h>
#include <stdlib.h>
extern const char text[]; /* In text.s */
int main (void)
{
clrscr ();
cprintf ("%s\r\nPress <RETURN>.\r\n", text);
cgetc ();
return EXIT_SUCCESS;
}
</code></tscreen>
Compile the tutorial with
<tscreen><verb>
cl65 -O -t osic1p -u __BOOT__ -o hello.lod hello.c text.s
</verb></tscreen>
The program is configured for a Challenger 1P computer with, at least, 32 kB
of RAM. See the <url url="osi.html"
name="Ohio Scientifc-specific documentation"> for instructions about how to
compile for other RAM sizes.
Plug a cassette player into your C1P computer; or, connect an RS-232 cable
between your C1P and a PC (set the PC's serial port to 300 Bits Per Second,
8 data bits, No parity, and 2 stop bits). (Turn on the computers.)
Tap the "<bf/BREAK/" key, to display the boot prompt; then, tap the "<tt/M/"
key, to enter the 65V PROM monitor. Tap the "<tt/L/" key. Either start the
cassette player (with a tape of the program), or start a transfer of the
program file "<tt/hello.lod/" from the PC. After a while, you should see the
following text on the screen:
<tscreen><verb>
Hello world!
Press <RETURN>.
</verb></tscreen>
(Stop the cassette player.) After hitting the RETURN key, you should see the
boot prompt again.
<sect2>WinOSI<p>
Available at <url
url="http://osi.marks-lab.com/#Emulator">:
Emulates the Ohio Scientific Challenger computers in different configurations.
Configure it to emulate a C1P (model 600 board) with 32 kB of RAM.
Compile the tutorial with the same command that is used to make the program
for a real machine.
Start the emulator. Tap the "<tt/M/" key, to enter the 65V PROM monitor; then,
tap the "<tt/L/" key. If you had configured WinOSI to ask for a file when it
starts to read data from the serial port, then you will see a file dialog box;
otherwise, you must tap your host keyboard's F10 function key. Select the file
"<tt/hello.lod/". After a moment, you should see the following text on the
screen:
<tscreen><verb>
Hello world!
Press <RETURN>.
</verb></tscreen>
After hitting the RETURN key, you should see the boot prompt again.
<sect2>C1Pjs<p>
Available at <url
url="http://www.pcjs.org/docs/c1pjs/">:
Emulates the Ohio Scientific Challenger 1P computer in different configurations.
The 32 kB RAM machine that must be used with the default compiler settings is
<url url="http://www.pcjs.org/devices/c1p/machine/32kb/" name="here">.
In addition to cc65, the <bf/srec_cat/ program from <url
url="http://srecord.sourceforge.net/" name="the SRecord tool collection">
must be installed. Some Linux distributions also provide srecord directly as
an installable package.
Compile the tutorial with this command line:
<tscreen><verb>
cl65 -O -t osic1p hello.c text.s
</verb></tscreen>
Convert the binary file into a text file that can be loaded via
the Ohio Scientific 65V PROM monitor, at start address 0x200:
<tscreen><verb>
srec_cat hello -binary -offset 0x200 -o hello.c1p -Ohio_Scientific -execution-start-address=0x200
</verb></tscreen>
Open the URL that points to the 32 kB machine; and, wait until the emulator
has been loaded. Click on the "<bf/BREAK/" button to display the boot prompt;
then, press the "<tt/M/" key to enter the 65V PROM monitor. Click the
"<bf/Browse.../" button; and, select the file "<tt/hello.c1p/" that was
created as the output of the above invocation of the "<tt/srec_cat/" command.
Press the "<bf/Load/" button. You should see the following text on the screen:
<tscreen><verb>
Hello world!
Press <RETURN>.
</verb></tscreen>
After hitting the RETURN key, you should see the boot prompt again.
<sect1>Contributions wanted<p>
We need your help! Recommended emulators and instructions for other targets

233
doc/osi.sgml Normal file
View File

@ -0,0 +1,233 @@
<!doctype linuxdoc system>
<article>
<title>Ohio Scientific-specific information for cc65
<author>
<url url="mailto:stephan.muehlstrasser@web.de" name="Stephan M&uuml;hlstrasser">,<newline>
<url url="mailto:greg.king5@verizon.net" name="Greg King">
<date>2015-03-17
<abstract>
An overview over the Ohio Scientific 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 Ohio Scientific runtime system as it comes with the
cc65 C compiler. It describes the memory layout, Ohio Scientific-specific header files,
and any pitfalls specific to that platform.
Please note that Ohio Scientific-specific functions are just mentioned here, they are
described in detail in the separate <url url="funcref.html" name="function
reference">. Even functions marked as "platform dependent" may be available on
more than one platform. Please see the function reference for more
information.
<sect>Targets<p>
Currently the target "osic1p" is implemented. This works for the Ohio Scientific
Challenger 1P machine and for the Briel Superboard /// replica.
<sect>Program file formats<p>
<descrip>
<tag/Binary, then text/
The standard binary output format generated by the linker for the osic1p
target is a pure machine language program.
For uploading into a real machine over its serial port or into an emulator,
that program must be converted into a text file that can be understood by
the 65V PROM monitor. For that purpose, the <bf/srec_cat/ program from <url
url="http://srecord.sourceforge.net/" name="the SRecord tool collection">
can be used.
Care must be taken that the <tt/-offset/ and <tt/-execution-start-address/
options for the <bf/srec_cat/ program correspond to the start address
of the executable.
Example for converting an executable "hello" file that was built for the
default start address &dollar;0200 to an uploadable file "hello.c1p":
<tscreen><verb>
srec_cat hello -bin -of 0x200 -o hello.c1p -os -esa=0x200
</verb></tscreen>
<tag/Hybrid/
The linker can create an alternate format that contains two parts:
<enum>
<item>A text header that is understood by the 65V PROM monitor.
It is a boot loader that reads the second part.
<item>The default binary code that is described above.
</enum>
You can make the alternate format by adding the option <tt/-u __BOOT__/ to
<tt/cl65/'s or <tt/ld65/'s command lines.
This format doesn't need to be converted. It is smaller than the text-only
format. But, it cannot be loaded by <url
url="http://www.pcjs.org/docs/c1pjs/" name="C1Pjs">; you must use the
SRecord-produced text-only format with that emulator. (However, if you know
that you never will use C1Pjs, then you can edit the
<tt>cfg/osic1p*.cfg</tt> files; uncomment the lines that import <tt/__BOOT__/.
Then, you won't need to use <tt/-u __BOOT__/ on your command lines.)
</descrip>
<sect>Memory layout<p>
By default programs compiled for the osic1p target are configured for 32 kB RAM.
The RAM size can be configured via the symbol <tt/__HIMEM__/.
Special locations:
<descrip>
<tag/Program start address/
The default start address is &dollar;0200. The start address is configurable
via the linker option <tt/--start-addr/.
<tag/Stack/
The C runtime stack is located at the top of RAM and growing downwards.
The size is configurable via the symbol <tt/__STACKSIZE__/. The default
stack size is &dollar;0400.
<tag/Heap/
The C heap is located at the end of the program and grows towards the C
runtime stack.
<tag/Video RAM/
The 1 kB video RAM is located at &dollar;D000. On the monitor, only a subset
of the available video RAM is visible. The address of the upper left corner
of the visible area is &dollar;D085 and corresponds to conio cursor
position (0, 0).
</descrip><p>
Example for building a program with start address &dollar;0300, stack size
&dollar;0200 and RAM size &dollar;2000:
<tscreen><verb>
cl65 --start-addr 0x300 -Wl -D,__HIMEM__=$2000,-D,__STACKSIZE__=$0200 -t osic1p hello.c
</verb></tscreen>
<sect>Linker configurations<p>
The ld65 linker comes with a default config file "osic1p.cfg" for the Ohio Scientific
Challenger 1P, which is implicitly used via <tt/-t osic1p/. The
osic1p package comes with additional secondary linker config files, which are
used via <tt/-t osic1p -C &lt;configfile&gt;/.
<sect1>Default config file (<tt/osic1p.cfg/)<p>
The default configuration is tailored to C programs.
<sect1><tt/osic1p-asm.cfg/<p>
This configuration is made for assembler programmers who don't need a special
setup.
To use this config file, assemble with <tt/-t osic1p/ and link with
<tt/-C osic1p-asm.cfg/. The former will make sure that correct runtime library
is used, while the latter supplies the actual config. When using <tt/cl65/,
use both command line options.
Sample command lines for <tt/cl65/:
<tscreen><verb>
cl65 -t osic1p -C osic1p-asm.cfg -o program source.s
cl65 -t osic1p -C osic1p-asm.cfg -u __BOOT__ -o program.lod source.s
</verb></tscreen>
<sect>Platform-specific header files<p>
Programs containing Ohio Scientific-specific code may use the <tt/osic1p.h/
header file.
<sect1>Ohio Scientific-specific functions<p>
There are currently no special Ohio Scientific functions.
<sect1>Hardware access<p>
There is no specific support for direct hardware access.
<sect>Loadable drivers<p>
There are no loadable drivers available.
<sect>Support for different screen layouts<p>
By default the conio library uses a 24 columns by 24 lines screen layout
for the Challenger 1P, like under BASIC. In addition to that there is support
for other screen layouts with extra modules.
There is a module <tt/screen-c1p-24x24.o/ in the OSI-specific
cc65 runtime library that contains all conio functions that depend
on the screen layout. No further configuration is needed for using the
default screen layout of the Challenger 1P.
For other screen layouts additional versions of the screen module are
available. The linker finds these modules without further configuration
if they are specified on the compiler or linker command line. The
extra module then overrides the default module.
Sample <tt/cl65/ command line to override the default screen
module with the module <tt/osic1p-screen-s3-32x28.o/:
<tscreen><verb>
cl65 -o hello -t osic1p osic1p-screen-s3-32x28.o hello.c
</verb></tscreen>
Currently the following extra screen configuration modules are implemented:
<itemize>
<item><tt>osic1p-screen-s3-32x28.o</tt>: 32 columns by 28 lines mode
for Briel Superboard ///</item>
</itemize>
<sect>Limitations<p>
<sect1>stdio implementation<p>
There is no support for stdio at the moment.
<sect>Other hints<p>
<sect1>Passing arguments to the program<p>
There is currently no support for passing arguments to a program.
<sect1>Program return code<p>
The program return code currently has no effect. When the main() function
finishes, the boot prompt is shown again.
<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

@ -2,14 +2,14 @@
/* */
/* ace.h */
/* */
/* ACE system specific definitions */
/* ACE system-specific definitions */
/* */
/* */
/* */
/* (C) 1998-2001 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* (C) 1998-2015, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
@ -61,9 +61,9 @@ struct aceDirentBuf {
char ad_name [17]; /* Name itself, ASCIIZ */
};
int aceDirOpen (char* dir);
int aceDirClose (int handle);
int aceDirRead (int handle, struct aceDirentBuf* buf);
int __cdecl__ aceDirOpen (char* dir);
int __cdecl__ aceDirClose (int handle);
int __cdecl__ aceDirRead (int handle, struct aceDirentBuf* buf);
/* Type of an ACE key. Key in low byte, shift mask in high byte */
typedef unsigned int aceKey;
@ -92,23 +92,23 @@ typedef unsigned int aceKey;
#define aceOP_RPTRATE 11 /* Key repeat rate */
/* Console functions */
void aceConWrite (char* buf, size_t count);
void aceConPutLit (int c);
void aceConPos (unsigned x, unsigned y);
void aceConGetPos (unsigned* x, unsigned* y);
void __cdecl__ aceConWrite (char* buf, size_t count);
void __cdecl__ aceConPutLit (int c);
void __cdecl__ aceConPos (unsigned x, unsigned y);
void __cdecl__ aceConGetPos (unsigned* x, unsigned* y);
unsigned aceConGetX (void);
unsigned aceConGetY (void);
char* aceConInput (char* buf, unsigned initial);
char __cdecl__* aceConInput (char* buf, unsigned initial);
int aceConStopKey (void);
aceKey aceConGetKey (void);
int aceConKeyAvail (aceKey* key);
void aceConKeyMat (char* matrix);
void aceConSetOpt (unsigned char opt, unsigned char val);
int aceConGetOpt (unsigned char opt);
int __cdecl__ aceConKeyAvail (aceKey* key);
void __cdecl__ aceConKeyMat (char* matrix);
void __cdecl__ aceConSetOpt (unsigned char opt, unsigned char val);
int __cdecl__ aceConGetOpt (unsigned char opt);
/* Misc stuff */
int aceMiscIoPeek (unsigned addr);
void aceMiscIoPoke (unsigned addr, unsigned char val);
int __cdecl__ aceMiscIoPeek (unsigned addr);
void __cdecl__ aceMiscIoPoke (unsigned addr, unsigned char val);

View File

@ -6,10 +6,10 @@
/* */
/* */
/* */
/* (C) 1998-2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* (C) 1998-2015, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
@ -42,7 +42,7 @@
#ifdef NDEBUG
# define assert(expr)
#else
extern void _afailed (const char*, unsigned);
extern void __fastcall__ _afailed (const char*, unsigned);
# define assert(expr) ((expr)? (void)0 : _afailed(__FILE__, __LINE__))
#endif

View File

@ -6,7 +6,7 @@
/* */
/* */
/* */
/* (C) 1998-2012, Ullrich von Bassewitz */
/* (C) 1998-2015, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
@ -222,7 +222,7 @@ void cbm_k_unlsn (void);
unsigned int cbm_load (const char* name, unsigned char device, void* data);
unsigned int __fastcall__ cbm_load (const char* name, unsigned char device, void* data);
/* Loads file "name", from given device, to given address -- or, to the load
** address of the file if "data" is the null pointer (like load"name",8,1
** in BASIC).

View File

@ -77,6 +77,8 @@
# include <lynx.h>
#elif defined(__NES__)
# include <nes.h>
#elif defined(__OSIC1P__)
# include <osic1p.h>
#elif defined(__PCE__)
# include <pce.h>
#endif

View File

@ -6,10 +6,10 @@
/* */
/* */
/* */
/* (C) 1998-2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* (C) 1998-2000, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
@ -88,7 +88,7 @@ unsigned __fastcall__ DbgDisAsmLen (unsigned Addr);
int __fastcall__ DbgIsRAM (unsigned Addr);
/* Return true if we can read and write the given address */
char* DbgMemDump (unsigned Addr, char* Buf, unsigned char Len);
char* __cdecl__ DbgMemDump (unsigned Addr, char* Buf, unsigned char Len);
/* Create a line of a memory dump in the given buffer. The buffer contains
** the starting address (4 digits hex), then Len bytes in this format:
** "AAAA__XX_YY_ZZ_...". The passed char buffer must hold Len*3+5 bytes

View File

@ -2,7 +2,7 @@
/* */
/* lynx.h */
/* */
/* Lynx system specific definitions */
/* Lynx system-specific definitions */
/* */
/* */
/* */
@ -109,25 +109,25 @@ extern void lynx_160_102_16_tgi[]; /* Referred to by tgi_static_stddrv[] */
/* Sound support */
/*****************************************************************************/
void lynx_snd_init ();
void lynx_snd_init (void);
/* Initialize the sound driver */
void lynx_snd_pause ();
void lynx_snd_pause (void);
/* Pause sound */
void lynx_snd_continue ();
void lynx_snd_continue (void);
/* Continue sound after pause */
void __fastcall__ lynx_snd_play (unsigned char channel, unsigned char *music);
/* Play tune on channel */
void lynx_snd_stop ();
void lynx_snd_stop (void);
/* Stop sound on all channels */
void __fastcall__ lynx_snd_stop_channel (unsigned char channel);
/* Stop sound on all channels */
unsigned char lynx_snd_active();
unsigned char lynx_snd_active(void);
/* Show which channels are active */
/*****************************************************************************/

47
include/osic1p.h Normal file
View File

@ -0,0 +1,47 @@
/*****************************************************************************/
/* */
/* osic1p.h */
/* */
/* Challenger 1P system specific definitions */
/* */
/* */
/* */
/* (C) 2015 Stephan Muehlstrasser */
/* */
/* */
/* 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 _OSIC1P_H
#define _OSIC1P_H
/* Check for errors */
#if !defined(__OSIC1P__)
# error "This module may only be used when compiling for the Challenger 1P!"
#endif
/* 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.
*/
#define _textcolor(color) COLOR_WHITE
#define _bgcolor(color) COLOR_BLACK
#define _bordercolor(color) COLOR_BLACK
#endif

View File

@ -107,12 +107,12 @@ int __fastcall__ atoi (const char* s);
long __fastcall__ atol (const char* s);
int __fastcall__ atexit (void (*exitfunc) (void));
void* __fastcall__ bsearch (const void* key, const void* base, size_t n,
size_t size, int (*cmp) (const void*, const void*));
size_t size, int __fastcall__ (* cmp) (const void*, const void*));
div_t __fastcall__ div (int numer, int denom);
void __fastcall__ exit (int ret) __attribute__ ((noreturn));
char* __fastcall__ getenv (const char* name);
void __fastcall__ qsort (void* base, size_t count, size_t size,
int (*compare) (const void*, const void*));
int __fastcall__ (* compare) (const void*, const void*));
long __fastcall__ strtol (const char* nptr, char** endptr, int base);
unsigned long __fastcall__ strtoul (const char* nptr, char** endptr, int base);
int __fastcall__ system (const char* s);

View File

@ -6,7 +6,7 @@
/* */
/* */
/* */
/* (C) 2000-2001 Piotr Fusik <fox@scene.pl> */
/* (C) 2000-2015 Piotr Fusik <fox@scene.pl> */
/* */
/* This file is based on the zlib.h from 'zlib' general purpose compression */
/* library, version 1.1.3, (C) 1995-1998 Jean-loup Gailly and Mark Adler. */
@ -83,8 +83,8 @@ unsigned __fastcall__ inflatemem (char* dest, const char* source);
*/
int uncompress (char* dest, unsigned* destLen,
const char* source, unsigned sourceLen);
int __fastcall__ uncompress (char* dest, unsigned* destLen,
const char* source, unsigned sourceLen);
/*
Original zlib description:

View File

@ -24,6 +24,7 @@ TARGETS = apple2 \
$(GEOS) \
lynx \
nes \
osic1p \
pce \
sim6502 \
sim65c02 \

View File

@ -46,9 +46,9 @@
sta $94
sty $95
; Call into the Applesoft Block Transfer Utility -- which handles zero-
; Call into Applesoft Block Transfer Up -- which handles zero-
; sized blocks well -- to move the content of the LC memory area.
jsr $D396 ; BLTU + 3
jsr $D39A ; BLTU2
; Set the source start address.
lda #<__ZPSAVE_RUN__
@ -68,9 +68,9 @@
sta $94
sty $95
; Call into the Applesoft Block Transfer Utility -- which handles moving
; Call into Applesoft Block Transfer Up -- which handles moving
; overlapping blocks upwards well -- to move the INIT segment.
jsr $D396 ; BLTU + 3
jsr $D39A ; BLTU2
; Delegate all further processing, to keep the STARTUP segment small.
jsr init
@ -164,10 +164,6 @@ basic: lda HIMEM
: sta sp
stx sp+1
; Enable interrupts, as old ProDOS versions (i.e. 1.1.1)
; jump to SYS and BIN programs with interrupts disabled.
cli
; Call the module constructors.
jsr initlib

View File

@ -23,11 +23,29 @@ oserr: jsr popname ; Preserves A
jmp __mappederrno
_exec:
; Save cmdline
sta ptr4
stx ptr4+1
; Get and push name
jsr popax
jsr pushname
bne oserr
; ProDOS TechRefMan, chapter 5.1.5.1:
; "The complete or partial pathname of the system program
; is stored at $280, starting with a length byte."
; In fact BASIC.SYSTEM does the same for BLOAD and BRUN of
; binary programs so we should do the same too in any case
; especially as _we_ rely on it in mainargs.s for argv[0]
ldy #$00
lda (sp),y
tay
: lda (sp),y
sta $0280,y
dey
bpl :-
; Set pushed name
lda sp
ldx sp+1
@ -52,24 +70,14 @@ _exec:
lda mliparam + MLI::INFO::FILE_TYPE
cmp #$FF ; SYS file?
bne binary ; No, check for BIN file
sta file_type ; Save file type for cmdline handling
; ProDOS TechRefMan, chapter 5.1.5.1:
; "The complete or partial pathname of the system program
; is stored at $280, starting with a length byte."
ldy #$00
lda (sp),y
tay
: lda (sp),y
sta $0280,y
dey
bpl :-
; SYS programs replace BASIC.SYSTEM so set in the ProDOS system bit map
; protection for pages $80 - $BF just in case BASIC.SYSTEM is there now
ldx #$0F ; Start with protection for pages $B8 - $BF
lda #%00000001 ; Protect only system global page
: sta $BF60,x ; Set protection for 8 pages
lda #$00 ; Protect no page
lda #%00000000 ; Protect no page
dex
bpl :-
bmi prodos ; Branch always
@ -112,7 +120,7 @@ setbuf: lda #$00 ; Low byte
dex
dex
dex
; Set I/O buffer
sta mliparam + MLI::OPEN::IO_BUFFER
stx mliparam + MLI::OPEN::IO_BUFFER+1
@ -126,7 +134,7 @@ setbuf: lda #$00 ; Low byte
stx level
beq :+
dec LEVEL
; Open file
: lda #OPEN_CALL
ldx #OPEN_COUNT
@ -158,8 +166,27 @@ setbuf: lda #$00 ; Low byte
bit $C080
.endif
; Reset stack as we already passed
; the point of no return anyway
ldx #$FF
txs
; Store up to 127 chars of cmdline (if any)
; including terminating zero in stack page
ldy #$00
lda ptr4+1 ; NULL?
beq :++ ; Yes, store as '\0'
: lda (ptr4),y
: sta $0100,y
beq :+ ; '\0' stored, done
iny
cpy #$7E
bcc :--
lda #$00 ; '\0'
beq :- ; Branch always
; Call loader stub after C libary shutdown
lda #<target
: lda #<target
ldx #>target
sta done+1
stx done+2
@ -177,16 +204,58 @@ level : .res 1
source: jsr $BF00
.byte READ_CALL
.word read_param
bcs :+
bcs error
; Close program file
jsr $BF00
.byte CLOSE_CALL
.word close_param
bcs :+
bcs error
; Check for cmdline handling
lda $0100 ; Valid cmdline?
beq jump ; No, jump to program right away
ldx file_type ; SYS file?
bne system ; Yes, check for startup filename
; Store REM and cmdline in BASIC input buffer
lda #$B2 ; REM token
bne :++ ; Branch always
: inx
lda a:$0100-1,x
: sta $0200,x
bne :--
beq jump ; Branch always
; Check for startup filename support
; ProDOS TechRefMan, chapter 5.1.5.1:
; "$2000 is a jump instruction. $2003 and $2004 are $EE."
system: lda $2000
cmp #$4C
bne jump
lda $2003
cmp #$EE
bne jump
lda $2004
cmp #$EE
bne jump
; Store cmdline in startup filename buffer
ldx #$01
: lda a:$0100-1,x
beq :+
sta $2006,x
inx
cpx $2005 ; Buffer full?
bcc :- ; No, continue
: dex
stx $2006 ; Store cmdline length
; Go for it ...
jmp (data_buffer)
jump: jmp (data_buffer)
file_type = * - source + target
.byte $00
read_param = * - source + target
.byte $04 ; PARAM_COUNT
@ -204,7 +273,7 @@ close_ref = * - source + target
; Quit to ProDOS dispatcher
quit = * - source + target
: jsr $BF00
error: jsr $BF00
.byte $65 ; QUIT
.word quit_param

View File

@ -21,6 +21,10 @@ initirq:
.byte $40 ; Alloc interrupt
.addr i_param
bcs prterr
; Enable interrupts, as old ProDOS versions (i.e. 1.1.1)
; jump to SYS and BIN programs with interrupts disabled.
cli
rts
; Print error message and exit

View File

@ -34,12 +34,12 @@
MAXARGS = 10
; ProDOS stores the filename in the second half of BASIC's input buffer, so
; there are 128 characters left. At least 7 characters are necessary for the
; CALLxxxx:REM so 121 characters may be used before overwriting the ProDOS
; filename. As we don't want to put further restrictions on the command-line
; length we reserve those 121 characters terminated by a zero.
; there are 128 characters left. At least 1 character is necessary for the
; REM so 127 characters (including the terminating zero) may be used before
; overwriting the ProDOS filename. As we don't want to further restrict the
; command-line length we reserve those 127 characters.
BUF_LEN = 122
BUF_LEN = 127
BASIC_BUF = $200
FNAM_LEN = $280
@ -176,4 +176,4 @@ argv: .addr FNAM
.bss
buffer: .res BUF_LEN
buffer: .res BUF_LEN

View File

@ -22,14 +22,14 @@ READ_CALL = $CA
CLOSE_CALL = $CC
FILE_NOT_FOUND_ERR = $46
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ------------------------------------------------------------------------
.import __CODE_0300_SIZE__, __DATA_0300_SIZE__
.import __CODE_0300_LOAD__, __CODE_0300_RUN__
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ------------------------------------------------------------------------
.segment "DATA_2000"
.segment "DATA_2000"
GET_FILE_INFO_PARAM:
.byte $0A ;PARAM_COUNT
@ -57,9 +57,9 @@ LOADING:
ELLIPSES:
.byte " ...", $0D, $0D, $00
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ------------------------------------------------------------------------
.segment "DATA_0300"
.segment "DATA_0300"
READ_PARAM:
.byte $04 ;PARAM_COUNT
@ -81,22 +81,22 @@ QUIT_PARAM:
FILE_NOT_FOUND:
.asciiz "... File Not Found"
ERROR_NUMBER:
.asciiz "... Error $"
PRESS_ANY_KEY:
.asciiz " - Press Any Key "
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ------------------------------------------------------------------------
.segment "CODE_2000"
.segment "CODE_2000"
jmp :+
.byte $EE
.byte $EE
.byte 65
STARTUP:.res 65
.byte $7F
STARTUP:.res $7F
; Reset stack
: ldx #$FF
@ -104,8 +104,8 @@ STARTUP:.res 65
; Relocate CODE_0300 and DATA_0300
ldx #<(__CODE_0300_SIZE__ + __DATA_0300_SIZE__)
: lda __CODE_0300_LOAD__ - 1,x
sta __CODE_0300_RUN__ - 1,x
: lda __CODE_0300_LOAD__-1,x
sta __CODE_0300_RUN__-1,x
dex
bne :-
@ -118,23 +118,23 @@ STARTUP:.res 65
; Add trailing '\0' to pathname
tax
lda #$00
sta PATHNAME + 1,x
sta PATHNAME+1,x
; Copy ProDOS startup filename and trailing '\0' to stack
ldx STARTUP
lda #$00
beq :++ ; bra
: lda STARTUP + 1,x
beq :++ ; Branch always
: lda STARTUP+1,x
: sta STACK,x
dex
bpl :--
bpl :--
; Provide some user feedback
lda #<LOADING
ldx #>LOADING
jsr PRINT
lda #<(PATHNAME + 1)
ldx #>(PATHNAME + 1)
lda #<(PATHNAME+1)
ldx #>(PATHNAME+1)
jsr PRINT
lda #<ELLIPSES
ldx #>ELLIPSES
@ -159,16 +159,16 @@ STARTUP:.res 65
; Get load address from aux-type
lda FILE_INFO_ADDR
ldx FILE_INFO_ADDR + 1
ldx FILE_INFO_ADDR+1
sta READ_ADDR
stx READ_ADDR + 1
stx READ_ADDR+1
; It's high time to leave this place
jmp __CODE_0300_RUN__
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ------------------------------------------------------------------------
.segment "CODE_0300"
.segment "CODE_0300"
jsr MLI
.byte READ_CALL
@ -180,15 +180,15 @@ STARTUP:.res 65
.word CLOSE_PARAM
bcs ERROR
; Copy REM token and startup filename to BASIC input buffer
; Copy REM and startup filename to BASIC input buffer
ldx #$00
lda #$B2
bne :++ ; bra
lda #$B2 ; REM token
bne :++ ; Branch always
: inx
lda a:STACK - 1,x
lda a:STACK-1,x
: sta BUF,x
bne :--
; Go for it ...
jmp (READ_ADDR)
@ -207,7 +207,7 @@ PRINT:
: ora #$80
jsr COUT
iny
bne :-- ; bra
bne :-- ; Branch always
: rts
ERROR:
@ -216,7 +216,7 @@ ERROR:
lda #<FILE_NOT_FOUND
ldx #>FILE_NOT_FOUND
jsr PRINT
beq :++ ; bra
beq :++ ; Branch always
: pha
lda #<ERROR_NUMBER
ldx #>ERROR_NUMBER
@ -230,5 +230,3 @@ ERROR:
jsr MLI
.byte QUIT_CALL
.word QUIT_PARAM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

24
libsrc/atmos/bashdr.s Normal file
View File

@ -0,0 +1,24 @@
;
; 2010-11-14, Ullrich von Bassewitz
; 2014-09-06, Greg King
;
; This module supplies a small BASIC stub program that uses CALL
; to jump to the machine-language code that follows it.
;
; The following symbol is used by the linker config. file
; to force this module to be included into the output file.
.export __BASHDR__:abs = 1
.segment "BASHDR"
.addr Next
.word .version ; Line number
.byte $BF,'#' ; CALL token, mark number as hexadecimal
.byte <(Start >> 8 ) + '0' + (Start >> 8 > $09) * $07
.byte <(Start >> 4 & $0F) + '0' + (Start >> 4 & $0F > $09) * $07
.byte <(Start & $0F) + '0' + (Start & $0F > $09) * $07
.byte $00 ; End of BASIC line
Next: .addr $0000 ; BASIC program end marker
Start:

View File

@ -2,39 +2,18 @@
; Startup code for cc65 (Oric version)
;
; By Debrune Jérôme <jede@oric.org> and Ullrich von Bassewitz <uz@cc65.org>
; 2014-08-22, Greg King
; 2015-01-09, Greg King
;
.export _exit
.export __STARTUP__ : absolute = 1 ; Mark as startup
.import initlib, donelib
.import callmain, zerobss
.import __RAM_START__, __RAM_SIZE__
.import __ZPSAVE_LOAD__, __STACKSIZE__
.import __RAM_START__, __RAM_SIZE__, __STACKSIZE__
.include "zeropage.inc"
.include "atmos.inc"
; ------------------------------------------------------------------------
; Oric tape header
.segment "TAPEHDR"
.byte $16, $16, $16 ; Sync bytes
.byte $24 ; End of header marker
.byte $00 ; $2B0
.byte $00 ; $2AF
.byte $80 ; $2AE Machine code flag
.byte $C7 ; $2AD Autoload flag
.dbyt __ZPSAVE_LOAD__ - 1 ; $2AB
.dbyt __RAM_START__ ; $2A9
.byte $00 ; $2A8
.byte ((.VERSION >> 8) & $0F) + '0'
.byte ((.VERSION >> 4) & $0F) + '0'
.byte (.VERSION & $0F) + '0'
.byte $00 ; Zero terminated compiler version
; ------------------------------------------------------------------------
; Place the startup code in a special segment.
@ -52,7 +31,8 @@ L1: lda sp,x
jsr zerobss
; Unprotect screen columns 0 and 1.
; Currently, color isn't supported on the text screen.
; Unprotect screen columns 0 and 1 (where each line's color codes would sit).
lda STATUS
sta stsave
@ -79,7 +59,7 @@ L1: lda sp,x
; Call the module destructors. This is also the exit() entry.
_exit: jsr donelib ; Run module destructors
_exit: jsr donelib
; Restore the system stuff.
@ -102,9 +82,23 @@ L2: lda zpsave,x
; ------------------------------------------------------------------------
.segment "ZPSAVE"
.segment "ZPSAVE1"
zpsave: .res zpspace
zpsave:
; This padding is needed by a bug in the ROM.
; (The CLOAD command starts BASIC's variables table on top of the last byte
; that was loaded [instead of at the next address].)
; This is overlaid on a buffer, so that it doesn't use extra space in RAM.
.byte 0
; The segments "ZPSAVE1" and "ZPSAVE2" always must be together.
; They create a single object (the zpsave buffer).
.segment "ZPSAVE2"
.res zpspace - 1
; ------------------------------------------------------------------------

31
libsrc/atmos/tapehdr.s Normal file
View File

@ -0,0 +1,31 @@
;
; Based on code by Debrune Jérôme <jede@oric.org>
; 2015-01-08, Greg King
;
; The following symbol is used by the linker config. file
; to force this module to be included into the output file.
.export __TAPEHDR__:abs = 1
; These symbols, also, come from the configuration file.
.import __BASHDR_LOAD__, __ZPSAVE1_LOAD__, __AUTORUN__, __PROGFLAG__
; ------------------------------------------------------------------------
; Oric cassette-tape header
.segment "TAPEHDR"
.byte $16, $16, $16 ; Sync bytes
.byte $24 ; Beginning-of-header marker
.byte $00 ; $2B0
.byte $00 ; $2AF
.byte <__PROGFLAG__ ; $2AE Language flag ($00=BASIC, $80=machine code)
.byte <__AUTORUN__ ; $2AD Auto-run flag ($C7=run, $00=only load)
.dbyt __ZPSAVE1_LOAD__ ;$2AB Address of end of file
.dbyt __BASHDR_LOAD__ ; $2A9 Address of start of file
.byte $00 ; $2A8
; File name (a maximum of 17 characters), zero-terminated
.asciiz .sprintf("%u", .time)

View File

@ -1,9 +1,9 @@
/*
** Marc 'BlackJack' Rintsch, 06.03.2001
**
** unsigned int cbm_load(const char* name,
** unsigned char device,
** const unsigned char* data);
** unsigned int __fastcall__ cbm_load(const char* name,
** unsigned char device,
** const unsigned char* data);
*/
#include <cbm.h>
@ -11,7 +11,7 @@
/* loads file "name" from given device to given address or to the load address
** of the file if "data" is 0
*/
unsigned int cbm_load(const char* name, unsigned char device, void* data)
unsigned int __fastcall__ cbm_load(const char* name, unsigned char device, void* data)
{
/* LFN is set to 0; but, it's not needed for loading
** (BASIC V2 sets it to the value of the SA for LOAD).

View File

@ -1,7 +1,8 @@
/*
** _afailed.c
**
** Ullrich von Bassewitz, 06.06.1998
** 1998-06-06, Ullrich von Bassewitz
** 2015-03-13, Greg King
*/
@ -11,7 +12,7 @@
void _afailed (char* file, unsigned line)
void __fastcall__ _afailed (char* file, unsigned line)
{
fprintf (stderr, "ASSERTION FAILED IN %s(%u)\n", file, line);
exit (2);

View File

@ -16,7 +16,7 @@
struct outdesc;
/* Type of the function that is called to output data */
typedef void (*outfunc) (struct outdesc* desc, const char* buf, unsigned count);
typedef void __cdecl__ (* outfunc) (struct outdesc* desc, const char* buf, unsigned count);

View File

@ -1,7 +1,8 @@
/*
** bsearch.c
**
** Ullrich von Bassewitz, 17.06.1998
** 1998-06-17, Ullrich von Bassewitz
** 2015-06-21, Greg King
*/
@ -11,7 +12,7 @@
void* __fastcall__ bsearch (const void* key, const void* base, size_t n,
size_t size, int (*cmp) (const void*, const void*))
size_t size, int __fastcall__ (* cmp) (const void*, const void*))
{
int current;
int result;

View File

@ -1,7 +1,8 @@
/*
** qsort.c
**
** Ullrich von Bassewitz, 09.12.1998
** 1998.12.09, Ullrich von Bassewitz
** 2015-06-21, Greg King
*/
@ -12,7 +13,7 @@
static void QuickSort (register unsigned char* Base, int Lo, int Hi,
register size_t Size,
int (*Compare)(const void*, const void*))
int __fastcall__ (* Compare) (const void*, const void*))
/* Internal recursive function. Works with ints, but this shouldn't be
** a problem.
*/
@ -52,7 +53,7 @@ static void QuickSort (register unsigned char* Base, int Lo, int Hi,
void __fastcall__ qsort (void* base, size_t nmemb, size_t size,
int (*compare)(const void*, const void*))
int __fastcall__ (* compare) (const void*, const void*))
/* Quicksort implementation */
{
if (nmemb > 1) {

View File

@ -33,7 +33,7 @@ ptr: .res 2 ; Points to output file
; can ignore the passed pointer d, and access the data directly. While this
; is not very clean, it gives better and shorter code.
;
; static void out (struct outdesc* d, const char* buf, unsigned count)
; static void cdecl out (struct outdesc* d, const char* buf, unsigned count)
; /* Routine used for writing */
; {
; register size_t cnt;
@ -56,7 +56,7 @@ out: ldy #5
ldy #7
jsr pushwysp ; Push count
lda ptr
ldx ptr+1
ldx ptr+1
jsr _fwrite
sta ptr1 ; Save function result
stx ptr1+1

View File

@ -1,5 +1,5 @@
;
; int vsnprintf (char* Buf, size_t size, const char* Format, va_list ap);
; int __fastcall__ vsnprintf (char* Buf, size_t size, const char* Format, va_list ap);
;
; Ullrich von Bassewitz, 2009-09-26
;
@ -130,7 +130,7 @@ L9: pla
; ----------------------------------------------------------------------------
; Callback routine used for the actual output.
;
; static void out (struct outdesc* d, const char* buf, unsigned count)
; static void __cdecl__ out (struct outdesc* d, const char* buf, unsigned count)
; /* Routine used for writing */
;
; Since we know, we're called with a pointer to our static outdesc structure,

View File

@ -1,7 +1,7 @@
;
; Ullrich von Bassewitz, 11.08.1998
;
; char* DbgMemDump (unsigend Addr, char* Buf, unsigned char Length);
; char* __cdecl__ DbgMemDump (unsigend Addr, char* Buf, unsigned char Length);
;
.export _DbgMemDump

153
libsrc/osic1p/bootstrap.s Normal file
View File

@ -0,0 +1,153 @@
;
; 2015-03-08, Greg King
;
; When you want to create a program with the alternate file format,
; add "-u __BOOT__" to the cl65/ld65 command line. Then, the linker
; will import this symbol name; and, link this module at the front
; of your program file.
;
.export __BOOT__:abs = 1
.import __RAM_START__, __RAM_SIZE__, __BSS_RUN__
; ------------------------------------------------------------------------
load_addr := __RAM_START__
load_size = __BSS_RUN__ - __RAM_START__
ram_top := __RAM_START__ + __RAM_SIZE__
.segment "BOOT"
; If you want to change how this bootstrap loader works, then:
; 1. edit this assembly source code,
; 2. define the constant ASM (uncomment the line below),
; 3. assemble this file (and, make a listing of that assembly),
; 4. copy the listing's hex codes into the .byte lines below (notice that most
; of the strings are followed by CR; it's required by the OS65V monitor)
; (be sure to match the listing's lines against the .byte lines),
; 5. undefine ASM (recomment the line),
; 6. assemble this file, again,
; 7. and, add the object file to "osic1p.lib".
;ASM = 1
.ifdef ASM
.include "osic1p.inc"
.macpack generic
load := $08 ; private variables
count := $0A
GETCHAR := $FFBF ; gets one character from ACIA
FIRSTVISC = $85 ; Offset of first visible character in video RAM
LINEDIST = $20 ; Offset in video RAM between two lines
ldy #<$0000
lda #<load_addr
ldx #>load_addr
sta load
stx load+1
lda #<load_size
eor #$FF
sta count ; store (-size - 1)
lda #>load_size
eor #$FF
sta count+1
L1: inc count ; pre-count one's-complement upwards
bnz L2
inc count+1
bze L3
L2: jsr GETCHAR ; (doesn't change .Y)
sta (load),y
; Show that the file is being loaded by rotating an arrow on the screen.
;
tya
lsr a
lsr a
and #8 - 1
ora #$10 ; eight arrow characters
sta SCRNBASE + FIRSTVISC + 2 * LINEDIST + 11
iny
bnz L1
inc load+1
bnz L1 ; branch always
L3: jmp load_addr
.else
.mac hex1 h
.lobytes ((h) & $0F) + (((h) & $0F) > 9) * 7 + '0'
.endmac
.mac hex2 h
hex1 (h) >> 4
hex1 (h) >> 0
.endmac
.mac hex4 h
hex2 >(h)
hex2 <(h)
.endmac
CR = $0D
.byte CR, CR
.byte "." ; set an address
hex4 ram_top ; put loader where stack will sit
.byte "/" ; write bytes into RAM
; ASCII-coded hexadecimal translation of the above assembly code.
; It was copied from the assembler listing.
.byte "A0", CR, "00", CR
.byte "A9", CR
hex2 <load_addr
.byte CR, "A2", CR
hex2 >load_addr
.byte CR, "85", CR, "08", CR
.byte "86", CR, "09", CR
.byte "A9", CR
hex2 <load_size
.byte CR, "49", CR, "FF", CR
.byte "85", CR, "0A", CR
.byte "A9", CR
hex2 >load_size
.byte CR, "49", CR, "FF", CR
.byte "85", CR, "0B", CR
.byte "E6", CR, "0A", CR
.byte "D0", CR, "04", CR
.byte "E6", CR, "0B", CR
.byte "F0", CR, "16", CR
.byte "20", CR, "BF", CR, "FF", CR
.byte "91", CR, "08", CR
.byte "98", CR
.byte "4A", CR
.byte "4A", CR
.byte "29", CR, "07", CR
.byte "09", CR, "10", CR
.byte "8D", CR, "D0", CR, "D0", CR
.byte "C8", CR
.byte "D0", CR, "E6", CR
.byte "E6", CR, "09", CR
.byte "D0", CR, "E2", CR
.byte "4C", CR
hex2 <load_addr
.byte CR
hex2 >load_addr
.byte CR, "."
hex4 ram_top
.byte "G" ; go to address
.endif

29
libsrc/osic1p/cclear.s Normal file
View File

@ -0,0 +1,29 @@
;
; Copied from CBM implementation
;
; originally by:
; Ullrich von Bassewitz, 08.08.1998
;
; void cclearxy (unsigned char x, unsigned char y, unsigned char length);
; void cclear (unsigned char length);
;
.export _cclearxy, _cclear
.import popa, _gotoxy, cputdirect
.importzp tmp1
_cclearxy:
pha ; Save the length
jsr popa ; Get y
jsr _gotoxy ; Call this one, will pop params
pla ; Restore the length and run into _cclear
_cclear:
cmp #0 ; Is the length zero?
beq L9 ; Jump if done
sta tmp1
L1: lda #' '
jsr cputdirect ; Direct output
dec tmp1
bne L1
L9: rts

48
libsrc/osic1p/cgetc.s Normal file
View File

@ -0,0 +1,48 @@
;
; char cgetc (void);
;
.constructor initcgetc
.export _cgetc
.import cursor
.include "osic1p.inc"
.include "extzp.inc"
.include "zeropage.inc"
; Initialize one-character buffer that is filled by kbhit()
initcgetc:
lda #$00
sta CHARBUF ; No character in buffer initially
rts
; Input routine from 65V PROM MONITOR, show cursor if enabled
_cgetc:
lda CHARBUF ; character in buffer available?
beq nobuffer
tax ; save character in X
lda #$00
sta CHARBUF ; empty buffer
beq restorex ; restore X and return
nobuffer:
lda cursor ; show cursor?
beq nocursor
ldy CURS_X
lda (SCREEN_PTR),y ; fetch current character
sta tmp1 ; save it
lda #$A1 ; full white square
sta (SCREEN_PTR),y ; store at cursor position
nocursor:
jsr INPUTC ; get input character in A
ldx cursor
beq done ; was cursor on?
tax ; save A in X
lda tmp1 ; fetch saved character
ldy CURS_X
sta (SCREEN_PTR),y ; store at cursor position
restorex:
txa ; restore saved character from X
done:
ldx #$00 ; high byte of int return value
rts

29
libsrc/osic1p/chline.s Normal file
View File

@ -0,0 +1,29 @@
;
; based on CBM implementation
;
; originally by:
; Ullrich von Bassewitz, 08.08.1998
;
; void chlinexy (unsigned char x, unsigned char y, unsigned char length);
; void chline (unsigned char length);
;
.export _chlinexy, _chline
.import popa, _gotoxy, cputdirect
.importzp tmp1
_chlinexy:
pha ; Save the length
jsr popa ; Get y
jsr _gotoxy ; Call this one, will pop params
pla ; Restore the length
_chline:
cmp #0 ; Is the length zero?
beq L9 ; Jump if done
sta tmp1
L1: lda #$94 ; Horizontal line, screen code
jsr cputdirect ; Direct output
dec tmp1
bne L1
L9: rts

55
libsrc/osic1p/crt0.s Normal file
View File

@ -0,0 +1,55 @@
; ---------------------------------------------------------------------------
; crt0.s
; ---------------------------------------------------------------------------
;
; Startup code for Ohio Scientific Challenger 1P
.export _init, _exit
.import _main
.export __STARTUP__ : absolute = 1 ; Mark as startup
.import __RAM_START__, __RAM_SIZE__ ; Linker generated
.import __STACKSIZE__
.import zerobss, initlib, donelib
.include "zeropage.inc"
.include "extzp.inc"
.include "osic1p.inc"
; ---------------------------------------------------------------------------
; Place the startup code in a special segment
.segment "STARTUP"
; ---------------------------------------------------------------------------
; A little light 6502 housekeeping
_init: ldx #$FF ; Initialize stack pointer to $01FF
txs
cld ; Clear decimal mode
; ---------------------------------------------------------------------------
; Set cc65 argument stack pointer
lda #<(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
sta sp
lda #>(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
sta sp+1
; ---------------------------------------------------------------------------
; Initialize memory storage
jsr zerobss ; Clear BSS segment
jsr initlib ; Run constructors
; ---------------------------------------------------------------------------
; Call main()
jsr _main
; ---------------------------------------------------------------------------
; Back from main (this is also the _exit entry):
_exit: jsr donelib ; Run destructors
jmp RESET ; Display boot menu after program exit

289
libsrc/osic1p/ctype.s Normal file
View File

@ -0,0 +1,289 @@
;
; Character specification table.
;
; Ullrich von Bassewitz, 02.06.1998
; 2003-05-02, Greg King
;
; Copied from cbm/ctype.s
; The following 256-byte-wide table specifies attributes for the isxxx type
; of functions. Doing it by a table means some overhead in space, but it
; has major advantages:
;
; * It is fast. If it weren't for the slow parameter-passing of cc65,
; one even could define C-language macroes for the isxxx functions
; (as it usually is done, on other platforms).
;
; * It is highly portable. The only unportable part is the table itself;
; all real code goes into the common library.
;
; * We save some code in the isxxx functions.
; This table is taken from Craig S. Bruce's technical docs. for the ACE OS.
.include "ctype.inc"
; The table is read-only, put it into the RODATA segment.
.rodata
__ctype:
.byte CT_CTRL ; 0/00 ___rvs_@___
.byte CT_CTRL ; 1/01 ___rvs_a___
.byte CT_CTRL ; 2/02 ___rvs_b___
.byte CT_CTRL ; 3/03 ___rvs_c___
.byte CT_CTRL ; 4/04 ___rvs_d___
.byte CT_CTRL ; 5/05 ___rvs_e___
.byte CT_CTRL ; 6/06 ___rvs_f___
.byte CT_CTRL ; 7/07 _BEL/rvs_g_
.byte CT_CTRL ; 8/08 ___rvs_h___
.byte CT_CTRL | CT_OTHER_WS | CT_SPACE_TAB ; 9/09 _TAB/rvs_i_
.byte CT_CTRL | CT_OTHER_WS ; 10/0a _BOL/rvs_j_
.byte CT_CTRL ; 11/0b ___rvs_k___
.byte CT_CTRL ; 12/0c ___rvs_l___
.byte CT_CTRL | CT_OTHER_WS ; 13/0d _CR_/rvs_m_
.byte CT_CTRL ; 14/0e ___rvs_n___
.byte CT_CTRL ; 15/0f ___rvs_o___
.byte CT_CTRL ; 16/10 ___rvs_p___
.byte CT_CTRL | CT_OTHER_WS ; 17/11 _VT_/rvs_q_
.byte CT_CTRL ; 18/12 ___rvs_r___
.byte CT_CTRL | CT_OTHER_WS ; 19/13 HOME/rvs_s_
.byte CT_CTRL | CT_OTHER_WS ; 20/14 _BS_/rvs_t_
.byte CT_CTRL ; 21/15 ___rvs_u___
.byte CT_CTRL ; 22/16 ___rvs_v___
.byte CT_CTRL ; 23/17 ___rvs_w___
.byte CT_CTRL ; 24/18 ___rvs_x___
.byte CT_CTRL ; 25/19 ___rvs_y___
.byte CT_CTRL ; 26/1a ___rvs_z___
.byte CT_CTRL ; 27/1b ___rvs_[___
.byte CT_CTRL ; 28/1c ___rvs_\___
.byte CT_CTRL | CT_OTHER_WS ; 29/1d cursr-right
.byte CT_CTRL ; 30/1e ___rvs_^___
.byte CT_CTRL ; 31/1f _rvs_under_
.byte CT_SPACE | CT_SPACE_TAB ; 32/20 ___SPACE___
.byte $00 ; 33/21 _____!_____
.byte $00 ; 34/22 _____"_____
.byte $00 ; 35/23 _____#_____
.byte $00 ; 36/24 _____$_____
.byte $00 ; 37/25 _____%_____
.byte $00 ; 38/26 _____&_____
.byte $00 ; 39/27 _____'_____
.byte $00 ; 40/28 _____(_____
.byte $00 ; 41/29 _____)_____
.byte $00 ; 42/2a _____*_____
.byte $00 ; 43/2b _____+_____
.byte $00 ; 44/2c _____,_____
.byte $00 ; 45/2d _____-_____
.byte $00 ; 46/2e _____._____
.byte $00 ; 47/2f _____/_____
.byte CT_DIGIT | CT_XDIGIT ; 48/30 _____0_____
.byte CT_DIGIT | CT_XDIGIT ; 49/31 _____1_____
.byte CT_DIGIT | CT_XDIGIT ; 50/32 _____2_____
.byte CT_DIGIT | CT_XDIGIT ; 51/33 _____3_____
.byte CT_DIGIT | CT_XDIGIT ; 52/34 _____4_____
.byte CT_DIGIT | CT_XDIGIT ; 53/35 _____5_____
.byte CT_DIGIT | CT_XDIGIT ; 54/36 _____6_____
.byte CT_DIGIT | CT_XDIGIT ; 55/37 _____7_____
.byte CT_DIGIT | CT_XDIGIT ; 56/38 _____8_____
.byte CT_DIGIT | CT_XDIGIT ; 57/39 _____9_____
.byte $00 ; 58/3a _____:_____
.byte $00 ; 59/3b _____;_____
.byte $00 ; 60/3c _____<_____
.byte $00 ; 61/3d _____=_____
.byte $00 ; 62/3e _____>_____
.byte $00 ; 63/3f _____?_____
.byte $00 ; 64/40 _____@_____
.byte CT_LOWER | CT_XDIGIT ; 65/41 _____a_____
.byte CT_LOWER | CT_XDIGIT ; 66/42 _____b_____
.byte CT_LOWER | CT_XDIGIT ; 67/43 _____c_____
.byte CT_LOWER | CT_XDIGIT ; 68/44 _____d_____
.byte CT_LOWER | CT_XDIGIT ; 69/45 _____e_____
.byte CT_LOWER | CT_XDIGIT ; 70/46 _____f_____
.byte CT_LOWER ; 71/47 _____g_____
.byte CT_LOWER ; 72/48 _____h_____
.byte CT_LOWER ; 73/49 _____i_____
.byte CT_LOWER ; 74/4a _____j_____
.byte CT_LOWER ; 75/4b _____k_____
.byte CT_LOWER ; 76/4c _____l_____
.byte CT_LOWER ; 77/4d _____m_____
.byte CT_LOWER ; 78/4e _____n_____
.byte CT_LOWER ; 79/4f _____o_____
.byte CT_LOWER ; 80/50 _____p_____
.byte CT_LOWER ; 81/51 _____q_____
.byte CT_LOWER ; 82/52 _____r_____
.byte CT_LOWER ; 83/53 _____s_____
.byte CT_LOWER ; 84/54 _____t_____
.byte CT_LOWER ; 85/55 _____u_____
.byte CT_LOWER ; 86/56 _____v_____
.byte CT_LOWER ; 87/57 _____w_____
.byte CT_LOWER ; 88/58 _____x_____
.byte CT_LOWER ; 89/59 _____y_____
.byte CT_LOWER ; 90/5a _____z_____
.byte $00 ; 91/5b _____[_____
.byte $00 ; 92/5c _____\_____
.byte $00 ; 93/5d _____]_____
.byte $00 ; 94/5e _____^_____
.byte $00 ; 95/5f _UNDERLINE_
.byte $00 ; 96/60 _A`_grave__
.byte $00 ; 97/61 _A'_acute__
.byte $00 ; 98/62 _A^_circum_
.byte $00 ; 99/63 _A~_tilde__
.byte $00 ; 100/64 _A"_dieres_
.byte $00 ; 101/65 _A__ring___
.byte $00 ; 102/66 _AE________
.byte $00 ; 103/67 _C,cedilla_
.byte $00 ; 104/68 _E`_grave__
.byte $00 ; 105/69 _E'_acute__
.byte $00 ; 106/6a _E^_circum_
.byte $00 ; 107/6b _E"_dieres_
.byte $00 ; 108/6c _I`_grave__
.byte $00 ; 109/6d _I'_acute__
.byte $00 ; 110/6e _I^_circum_
.byte $00 ; 111/6f _I"_dieres_
.byte $00 ; 112/70 _D-_Eth_lr_
.byte $00 ; 113/71 _N~_tilde__
.byte $00 ; 114/72 _O`_grave__
.byte $00 ; 115/73 _O'_acute__
.byte $00 ; 116/74 _O^_circum_
.byte $00 ; 117/75 _O~_tilde__
.byte $00 ; 118/76 _O"_dieres_
.byte $00 ; 119/77 __multiply_
.byte $00 ; 120/78 _O/_slash__
.byte $00 ; 121/79 _U`_grave__
.byte $00 ; 122/7a _U'_acute__
.byte $00 ; 123/7b _U^_circum_
.byte $00 ; 124/7c _U"_dieres_
.byte $00 ; 125/7d _Y'_acute__
.byte $00 ; 126/7e _cap_thorn_
.byte $00 ; 127/7f _Es-sed_B__
.byte CT_CTRL ; 128/80 __bullet___
.byte CT_CTRL ; 129/81 __v_line___
.byte CT_CTRL ; 130/82 __h_line___
.byte CT_CTRL ; 131/83 ___cross___
.byte CT_CTRL ; 132/84 _tl_corner_
.byte CT_CTRL ; 133/85 _tr_corner_
.byte CT_CTRL ; 134/86 _bl_corner_
.byte CT_CTRL ; 135/87 _br_corner_
.byte CT_CTRL ; 136/88 ___l_tee___
.byte CT_CTRL ; 137/89 ___r_tee___
.byte CT_CTRL ; 138/8a ___t_tee___
.byte CT_CTRL ; 139/8b ___b_tee___
.byte CT_CTRL ; 140/8c ___heart___
.byte CT_CTRL | CT_OTHER_WS ; 141/8d _CR/diamond
.byte CT_CTRL ; 142/8e ___club____
.byte CT_CTRL ; 143/8f ___spade___
.byte CT_CTRL ; 144/90 _s_circle__
.byte CT_CTRL | CT_OTHER_WS ; 145/91 _cursor-up_
.byte CT_CTRL ; 146/92 ___pound___
.byte CT_CTRL | CT_OTHER_WS ; 147/93 _CLS/check_
.byte CT_CTRL | CT_OTHER_WS ; 148/94 __INSert___
.byte CT_CTRL ; 149/95 ____+/-____
.byte CT_CTRL ; 150/96 __divide___
.byte CT_CTRL ; 151/97 __degree___
.byte CT_CTRL ; 152/98 _c_checker_
.byte CT_CTRL ; 153/99 _f_checker_
.byte CT_CTRL ; 154/9a _solid_sq__
.byte CT_CTRL ; 155/9b __cr_char__
.byte CT_CTRL ; 156/9c _up_arrow__
.byte CT_CTRL | CT_OTHER_WS ; 157/9d cursor-left
.byte CT_CTRL ; 158/9e _left_arro_
.byte CT_CTRL ; 159/9f _right_arr_
.byte CT_SPACE | CT_SPACE_TAB ; 160/a0 _req space_
.byte $00 ; 161/a1 _!_invertd_
.byte $00 ; 162/a2 ___cent____
.byte $00 ; 163/a3 ___pound___
.byte $00 ; 164/a4 __currency_
.byte $00 ; 165/a5 ____yen____
.byte $00 ; 166/a6 _|_broken__
.byte $00 ; 167/a7 __section__
.byte $00 ; 168/a8 __umulaut__
.byte $00 ; 169/a9 _copyright_
.byte $00 ; 170/aa __fem_ord__
.byte $00 ; 171/ab _l_ang_quo_
.byte $00 ; 172/ac ____not____
.byte $00 ; 173/ad _syl_hyphn_
.byte $00 ; 174/ae _registerd_
.byte $00 ; 175/af _overline__
.byte $00 ; 176/b0 __degrees__
.byte $00 ; 177/b1 ____+/-____
.byte $00 ; 178/b2 _2_supersc_
.byte $00 ; 179/b3 _3_supersc_
.byte $00 ; 180/b4 ___acute___
.byte $00 ; 181/b5 ____mu_____
.byte $00 ; 182/b6 _paragraph_
.byte $00 ; 183/b7 __mid_dot__
.byte $00 ; 184/b8 __cedilla__
.byte $00 ; 185/b9 _1_supersc_
.byte $00 ; 186/ba __mas_ord__
.byte $00 ; 187/bb _r_ang_quo_
.byte $00 ; 188/bc ____1/4____
.byte $00 ; 189/bd ____1/2____
.byte $00 ; 190/be ____3/4____
.byte $00 ; 191/bf _?_invertd_
.byte $00 ; 192/c0 _____`_____
.byte CT_UPPER | CT_XDIGIT ; 193/c1 _____A_____
.byte CT_UPPER | CT_XDIGIT ; 194/c2 _____B_____
.byte CT_UPPER | CT_XDIGIT ; 195/c3 _____C_____
.byte CT_UPPER | CT_XDIGIT ; 196/c4 _____D_____
.byte CT_UPPER | CT_XDIGIT ; 197/c5 _____E_____
.byte CT_UPPER | CT_XDIGIT ; 198/c6 _____F_____
.byte CT_UPPER ; 199/c7 _____G_____
.byte CT_UPPER ; 200/c8 _____H_____
.byte CT_UPPER ; 201/c9 _____I_____
.byte CT_UPPER ; 202/ca _____J_____
.byte CT_UPPER ; 203/cb _____K_____
.byte CT_UPPER ; 204/cc _____L_____
.byte CT_UPPER ; 205/cd _____M_____
.byte CT_UPPER ; 206/ce _____N_____
.byte CT_UPPER ; 207/cf _____O_____
.byte CT_UPPER ; 208/d0 _____P_____
.byte CT_UPPER ; 209/d1 _____Q_____
.byte CT_UPPER ; 210/d2 _____R_____
.byte CT_UPPER ; 211/d3 _____S_____
.byte CT_UPPER ; 212/d4 _____T_____
.byte CT_UPPER ; 213/d5 _____U_____
.byte CT_UPPER ; 214/d6 _____V_____
.byte CT_UPPER ; 215/d7 _____W_____
.byte CT_UPPER ; 216/d8 _____X_____
.byte CT_UPPER ; 217/d9 _____Y_____
.byte CT_UPPER ; 218/da _____Z_____
.byte $00 ; 219/db _____{_____
.byte $00 ; 220/dc _____|_____
.byte $00 ; 221/dd _____}_____
.byte $00 ; 222/de _____~_____
.byte $00 ; 223/df ___HOUSE___
.byte $00 ; 224/e0 _a`_grave__
.byte $00 ; 225/e1 _a'_acute__
.byte $00 ; 226/e2 _a^_circum_
.byte $00 ; 227/e3 _a~_tilde__
.byte $00 ; 228/e4 _a"_dieres_
.byte $00 ; 229/e5 _a__ring___
.byte $00 ; 230/e6 _ae________
.byte $00 ; 231/e7 _c,cedilla_
.byte $00 ; 232/e8 _e`_grave__
.byte $00 ; 233/e9 _e'_acute__
.byte $00 ; 234/ea _e^_circum_
.byte $00 ; 235/eb _e"_dieres_
.byte $00 ; 236/ec _i`_grave__
.byte $00 ; 237/ed _i'_acute__
.byte $00 ; 238/ee _i^_circum_
.byte $00 ; 239/ef _i"_dieres_
.byte $00 ; 240/f0 _o^x_Eth_s_
.byte $00 ; 241/f1 _n~_tilda__
.byte $00 ; 242/f2 _o`_grave__
.byte $00 ; 243/f3 _o'_acute__
.byte $00 ; 244/f4 _o^_circum_
.byte $00 ; 245/f5 _o~_tilde__
.byte $00 ; 246/f6 _o"_dieres_
.byte $00 ; 247/f7 __divide___
.byte $00 ; 248/f8 _o/_slash__
.byte $00 ; 249/f9 _u`_grave__
.byte $00 ; 250/fa _u'_acute__
.byte $00 ; 251/fb _u^_circum_
.byte $00 ; 252/fc _u"_dieres_
.byte $00 ; 253/fd _y'_acute__
.byte $00 ; 254/fe _sm_thorn__
.byte $00 ; 255/ff _y"_dieres_

29
libsrc/osic1p/cvline.s Normal file
View File

@ -0,0 +1,29 @@
;
; based on CBM version
; originally by:
; Ullrich von Bassewitz, 08.08.1998
;
; void cvlinexy (unsigned char x, unsigned char y, unsigned char length);
; void cvline (unsigned char length);
;
.export _cvlinexy, _cvline
.import popa, _gotoxy, putchar, newline
.importzp tmp1
_cvlinexy:
pha ; Save the length
jsr popa ; Get y
jsr _gotoxy ; Call this one, will pop params
pla ; Restore the length and run into _cvline
_cvline:
cmp #0 ; Is the length zero?
beq L9 ; Jump if done
sta tmp1
L1: lda #$95 ; Vertical bar
jsr putchar ; Write, no cursor advance
jsr newline ; Advance cursor to next line
dec tmp1
bne L1
L9: rts

View File

@ -0,0 +1,16 @@
;
; Implementation of screen-layout related functions for Superboard ///
;
.include "../osiscreen.inc"
S3_SCR_BASE := $D000 ; Base of Superboard /// video RAM
S3_VRAM_SIZE = $0400 ; Size of Superboard /// video RAM (1 kB)
S3_SCR_WIDTH = $20 ; Screen width
S3_SCR_HEIGHT = $1C ; Screen height
S3_SCR_FIRSTCHAR = $80 ; Offset of cursor position (0, 0) from base
; of video RAM
S3_SCROLL_DIST = $20 ; Memory distance for scrolling by one line
osi_screen_funcs S3_SCR_BASE, S3_VRAM_SIZE, S3_SCR_FIRSTCHAR, \
S3_SCR_WIDTH, S3_SCR_HEIGHT, S3_SCROLL_DIST

7
libsrc/osic1p/extzp.inc Normal file
View File

@ -0,0 +1,7 @@
;
; Additional zero page locations for the Challenger 1P.
;
; ------------------------------------------------------------------------
.globalzp CURS_X, CURS_Y, SCREEN_PTR, CHARBUF

20
libsrc/osic1p/extzp.s Normal file
View File

@ -0,0 +1,20 @@
;
; Additional zero page locations for the Challenger 1P.
; NOTE: The zeropage locations contained in this file get initialized
; in the startup code, so if you change anything here, be sure to check
; not only the linker config, but also the startup file.
;
; ------------------------------------------------------------------------
.include "extzp.inc"
.segment "EXTZP" : zeropage
CURS_X: .res 1
CURS_Y: .res 1
SCREEN_PTR: .res 2
CHARBUF: .res 1
; size 5
; Adjust size of the ZP segment in osic1p.cfg if the size changes

13
libsrc/osic1p/gotox.s Normal file
View File

@ -0,0 +1,13 @@
;
; copied from CBM implementation
; originally by:
; Ullrich von Bassewitz, 07.08.1998
;
; void gotox (unsigned char x);
;
.export _gotox
.import plot
.include "extzp.inc"
_gotox: sta CURS_X ; Set new position
jmp plot ; And activate it

17
libsrc/osic1p/gotoxy.s Normal file
View File

@ -0,0 +1,17 @@
;
; copied from CBM implementation
;
; originally by:
; Ullrich von Bassewitz, 06.08.1998
;
; void gotoxy (unsigned char x, unsigned char y);
;
.export _gotoxy
.import popa, plot
.include "extzp.inc"
_gotoxy:
sta CURS_Y ; Set Y
jsr popa ; Get X
sta CURS_X ; Set X
jmp plot ; Set the cursor position

13
libsrc/osic1p/gotoy.s Normal file
View File

@ -0,0 +1,13 @@
;
; copied from CBM implementation
; originally by:
; Ullrich von Bassewitz, 0.08.1998
;
; void gotoy (unsigned char y);
;
.export _gotoy
.import plot
.include "extzp.inc"
_gotoy: sta CURS_Y ; Set the new position
jmp plot ; And activate it

47
libsrc/osic1p/kbhit.s Normal file
View File

@ -0,0 +1,47 @@
;
; unsigned char kbhit (void);
;
; The method to detect a pressed key is based on the documentation in
; "Section 3 Programmed Key Functions" in "The Challenger Character Graphics
; Reference Manual"
; We only want to return true for characters that can be returned by cgetc(),
; but not for keys like <Shift> or <Ctrl>. Therefore a special handling is
; needed for the first row. This is implemented by a bit mask that is stored
; in tmp1 and that is set to zero after the first round.
;
.export _kbhit
.include "osic1p.inc"
.include "extzp.inc"
.include "zeropage.inc"
_kbhit:
lda #%11011111 ; Mask for only checking the column for the
sta tmp1 ; ESC key in the first keyboard row.
lda #%11111110 ; Mask for first keyboard row
scan:
sta KBD ; Select keyboard row
tax ; Save A
lda KBD ; Read keyboard columns
ora tmp1 ; Mask out uninteresting keys (only relevant in
; first row)
cmp #$FF ; No keys pressed?
bne keypressed
lda #$00 ; For remaining rows no keys masked
sta tmp1
txa ; Restore A
sec ; Want to shift in ones
rol a ; Rotate row select to next bit position
cmp #$FF ; Done?
bne scan ; If not, continue
lda #$00 ; Return false
tax ; High byte of return is also zero
sta CHARBUF ; No character in buffer
rts
keypressed:
jsr INPUTC ; Get input character in A
sta CHARBUF ; Save in buffer
ldx #$00 ; High byte of return is always zero
lda #$01 ; Return true
rts

20
libsrc/osic1p/oserror.s Normal file
View File

@ -0,0 +1,20 @@
;
; dummy implementation for Challenger 1P based on atmos implementation
;
; original by
; Stefan Haubenthal, 2011-04-18
;
; int __fastcall__ _osmaperrno (unsigned char oserror);
; /* Map a system specific error into a system independent code */
;
.include "errno.inc"
.export __osmaperrno
.proc __osmaperrno
lda #<EUNKNOWN
ldx #>EUNKNOWN
rts
.endproc

4
libsrc/osic1p/osic1p.inc Normal file
View File

@ -0,0 +1,4 @@
; Addresses
INPUTC := $FD00 ; Input character from keyboard
RESET := $FF00 ; Reset address, show boot prompt
KBD := $DF00 ; Polled keyboard register

184
libsrc/osic1p/osiscreen.inc Normal file
View File

@ -0,0 +1,184 @@
;
; Macro definitions for screen layout modules
;
.include "extzp.inc"
.linecont +
;
; Internal function for screensize()
;
.macro osi_screensize ScrWidth, ScrHeight
; Macro implementation of internal screensize
; function for given width and height in
; characters
.export screensize
.proc screensize
ldx #ScrWidth
ldy #ScrHeight
rts
.endproc
.endmacro
;
; void clrscr (void);
;
.macro osi_clrscr ScrBase, ScrRamSize
.export _clrscr
.proc _clrscr
lda #<ScrBase ; Fill whole video RAM with blanks by calling
ldx #>ScrBase ; memset appropriately
jsr pushax
lda #' '
ldx #$00
jsr pushax
lda #<ScrRamSize
ldx #>ScrRamSize
jsr _memset
lda #$00 ; Cursor in upper left corner
sta CURS_X
sta CURS_Y
jmp plot ; Set the cursor position
.endproc
.endmacro
;
; cputc/cputcxy for Challenger 1P
; Based on PET/CBM implementation
;
.macro osi_cputfuncs ScrBase, ScrFirstChar, ScrWidth, ScrHeight, \
ScrollDist, ScrLo, ScrHi
; Number of characters to move for scrolling
; by one line
ScrollLength = (ScrHeight - 1) * ScrollDist
;
; void cputcxy (unsigned char x, unsigned char y, char c);
; void cputc (char c);
;
.export _cputcxy, _cputc, cputdirect, putchar
.export newline, plot
_cputcxy:
pha ; Save C
jsr popa ; Get Y
jsr _gotoxy ; Set cursor, drop x
pla ; Restore C
; Plot a character - also used as internal function
_cputc: cmp #$0A ; CR?
bne L1
lda #0
sta CURS_X
beq plot ; Recalculate pointers
L1: cmp #$0D ; LF?
beq newline ; Recalculate pointers
cputdirect:
jsr putchar ; Write the character to the screen
; Advance cursor position, register Y contains horizontal position after
; putchar
cpy #(ScrWidth - 1) ; Check whether line is full
bne L3
jsr newline ; New line
ldy #$FF ; + cr
L3: iny
sty CURS_X
rts
newline:
inc CURS_Y
lda CURS_Y
cmp #ScrHeight ; Screen height
bne plot
dec CURS_Y ; Bottom of screen reached, scroll
; Scroll destination address
lda #<(ScrBase + ScrFirstChar)
ldx #>(ScrBase + ScrFirstChar)
jsr pushax
; Scroll source address
lda #<(ScrBase + ScrFirstChar + ScrollDist)
ldx #>(ScrBase + ScrFirstChar + ScrollDist)
jsr pushax
; Number of characters to move
lda #<ScrollLength
ldx #>ScrollLength
jsr _memmove
; Address of first character in last line
; of screen
lda #<(ScrBase + ScrFirstChar + ScrollLength)
sta ptr1
lda #>(ScrBase + ScrFirstChar + ScrollLength)
sta ptr1+1
ldy #ScrWidth ; Fill last line with blanks
lda #' '
clrln: sta (ptr1),y
dey
bpl clrln
plot: ldy CURS_Y
lda ScrLo,y
sta SCREEN_PTR
lda ScrHi,y
sta SCREEN_PTR+1
rts
; Write one character to the screen without doing anything else, return X
; position in register Y
putchar:
ldy CURS_X
sta (SCREEN_PTR),y ; Set char
rts
.endmacro
.macro osi_screen_funcs ScrBase, ScrRamSize, ScrFirstChar, \
ScrWidth, ScrHeight, ScrollDist
.import popa, _gotoxy
.import _memmove, _memset, pushax
.importzp ptr1
.rodata
; Screen address tables - offset to real screen
ScrTabLo:
.repeat ScrHeight, I
.byte <(ScrBase + ScrFirstChar + I * ScrollDist)
.endrep
ScrTabHi:
.repeat ScrHeight, I
.byte >(ScrBase + ScrFirstChar + I * ScrollDist)
.endrep
.code
osi_cputfuncs ScrBase, ScrFirstChar, ScrWidth, ScrHeight, \
ScrollDist, ScrTabLo, ScrTabHi
osi_screensize ScrWidth, ScrHeight
osi_clrscr ScrBase, ScrRamSize
.endmacro

View File

@ -0,0 +1,16 @@
;
; Implementation of screen-layout related functions for Challenger 1P
;
.include "osiscreen.inc"
C1P_SCR_BASE := $D000 ; Base of C1P video RAM
C1P_VRAM_SIZE = $0400 ; Size of C1P video RAM (1 kB)
C1P_SCR_WIDTH = $18 ; Screen width
C1P_SCR_HEIGHT = $18 ; Screen height
C1P_SCR_FIRSTCHAR = $85 ; Offset of cursor position (0, 0) from base
; of video RAM
C1P_SCROLL_DIST = $20 ; Memory distance for scrolling by one line
osi_screen_funcs C1P_SCR_BASE, C1P_VRAM_SIZE, C1P_SCR_FIRSTCHAR, \
C1P_SCR_WIDTH, C1P_SCR_HEIGHT, C1P_SCROLL_DIST

14
libsrc/osic1p/wherex.s Normal file
View File

@ -0,0 +1,14 @@
;
; Ullrich von Bassewitz, 06.08.1998
; Copied from cbm/wherex.s
; unsigned char wherex (void);
;
.export _wherex
.include "extzp.inc"
.proc _wherex
lda CURS_X
ldx #$00
rts
.endproc

14
libsrc/osic1p/wherey.s Normal file
View File

@ -0,0 +1,14 @@
;
; Ullrich von Bassewitz, 06.08.1998
; Copied from cbm/wherey.s
;
; unsigned char wherey (void);
;
.export _wherey
.include "extzp.inc"
.proc _wherey
lda CURS_Y
ldx #$00
rts
.endproc

View File

@ -6,8 +6,8 @@
#include <zlib.h>
int uncompress (char* dest, unsigned* destLen,
const char* source, unsigned sourceLen)
int __fastcall__ uncompress (char* dest, unsigned* destLen,
const char* source, unsigned sourceLen)
{
unsigned len;
unsigned char* ptr;

View File

@ -62,6 +62,7 @@
#include "symtab.h"
#include "toklist.h"
#include "ulabel.h"
#include "macro.h"
@ -417,6 +418,34 @@ static ExprNode* FuncDefined (void)
static ExprNode* FuncIsMnemonic (void)
/* Handle the .ISMNEMONIC, .ISMNEM builtin function */
{
int Instr = -1;
/* Check for a macro or an instruction depending on UbiquitousIdents */
if (CurTok.Tok == TOK_IDENT) {
if (UbiquitousIdents) {
/* Macros CAN be instructions, so check for them first */
if (FindMacro (&CurTok.SVal) == 0) {
Instr = FindInstruction (&CurTok.SVal);
}
} else {
/* Macros and symbols may NOT use the names of instructions, so just check for the instruction */
Instr = FindInstruction (&CurTok.SVal);
}
} else {
Error ("Identifier expected.");
}
/* Skip the name */
NextTok ();
return GenLiteralExpr (Instr > 0);
}
ExprNode* FuncHiByte (void)
/* Handle the .HIBYTE builtin function */
{
@ -629,6 +658,85 @@ static ExprNode* FuncReferenced (void)
static ExprNode* FuncAddrSize (void)
/* Handle the .ADDRSIZE function */
{
StrBuf ScopeName = STATIC_STRBUF_INITIALIZER;
StrBuf Name = STATIC_STRBUF_INITIALIZER;
SymEntry* Sym;
int AddrSize;
int NoScope;
/* Assume we don't know the size */
AddrSize = 0;
/* Check for a cheap local which needs special handling */
if (CurTok.Tok == TOK_LOCAL_IDENT) {
/* Cheap local symbol */
Sym = SymFindLocal (SymLast, &CurTok.SVal, SYM_FIND_EXISTING);
if (Sym == 0) {
Error ("Unknown symbol or scope: `%m%p'", &CurTok.SVal);
} else {
AddrSize = Sym->AddrSize;
}
/* Remember and skip SVal, terminate ScopeName so it is empty */
SB_Copy (&Name, &CurTok.SVal);
NextTok ();
SB_Terminate (&ScopeName);
} else {
/* Parse the scope and the name */
SymTable* ParentScope = ParseScopedIdent (&Name, &ScopeName);
/* Check if the parent scope is valid */
if (ParentScope == 0) {
/* No such scope */
SB_Done (&ScopeName);
SB_Done (&Name);
return GenLiteral0 ();
}
/* If ScopeName is empty, no explicit scope was specified. We have to
** search upper scope levels in this case.
*/
NoScope = SB_IsEmpty (&ScopeName);
/* If we did find a scope with the name, read the symbol defining the
** size, otherwise search for a symbol entry with the name and scope.
*/
if (NoScope) {
Sym = SymFindAny (ParentScope, &Name);
} else {
Sym = SymFind (ParentScope, &Name, SYM_FIND_EXISTING);
}
/* If we found the symbol retrieve the size, otherwise complain */
if (Sym) {
AddrSize = Sym->AddrSize;
} else {
Error ("Unknown symbol or scope: `%m%p%m%p'", &ScopeName, &Name);
}
}
if (AddrSize == 0) {
Warning (1, "Unknown address size: `%m%p%m%p'", &ScopeName, &Name);
}
/* Free the string buffers */
SB_Done (&ScopeName);
SB_Done (&Name);
/* Return the size. */
return GenLiteralExpr (AddrSize);
}
static ExprNode* FuncSizeOf (void)
/* Handle the .SIZEOF function */
{
@ -965,6 +1073,10 @@ static ExprNode* Factor (void)
N = Function (FuncBankByte);
break;
case TOK_ADDRSIZE:
N = Function (FuncAddrSize);
break;
case TOK_BLANK:
N = Function (FuncBlank);
break;
@ -982,6 +1094,10 @@ static ExprNode* Factor (void)
N = Function (FuncDefined);
break;
case TOK_ISMNEMONIC:
N = Function (FuncIsMnemonic);
break;
case TOK_HIBYTE:
N = Function (FuncHiByte);
break;

View File

@ -63,6 +63,7 @@ static const char* FeatureKeys[FEAT_COUNT] = {
"c_comments",
"force_range",
"underline_in_numbers",
"addrsize",
};
@ -119,6 +120,7 @@ feature_t SetFeature (const StrBuf* Key)
case FEAT_C_COMMENTS: CComments = 1; break;
case FEAT_FORCE_RANGE: ForceRange = 1; break;
case FEAT_UNDERLINE_IN_NUMBERS: UnderlineInNumbers= 1; break;
case FEAT_ADDRSIZE: AddrSize = 1; break;
default: /* Keep gcc silent */ break;
}

View File

@ -65,6 +65,7 @@ typedef enum {
FEAT_C_COMMENTS,
FEAT_FORCE_RANGE,
FEAT_UNDERLINE_IN_NUMBERS,
FEAT_ADDRSIZE,
/* Special value: Number of features available */
FEAT_COUNT

View File

@ -82,3 +82,4 @@ unsigned char OrgPerSeg = 0; /* Make .org local to current seg */
unsigned char CComments = 0; /* Allow C like comments */
unsigned char ForceRange = 0; /* Force values into expected range */
unsigned char UnderlineInNumbers = 0; /* Allow underlines in numbers */
unsigned char AddrSize = 0; /* Allow .ADDRSIZE function */

View File

@ -84,6 +84,8 @@ extern unsigned char OrgPerSeg; /* Make .org local to current seg */
extern unsigned char CComments; /* Allow C like comments */
extern unsigned char ForceRange; /* Force values into expected range */
extern unsigned char UnderlineInNumbers; /* Allow underlines in numbers */
extern unsigned char AddrSize; /* Allow .ADDRSIZE function */

View File

@ -713,9 +713,9 @@ static const struct {
{ "ROR", 0x000006F, 0x62, 1, PutAll },
{ "RTI", 0x0000001, 0x40, 0, PutAll },
{ "RTS", 0x0000001, 0x60, 0, PutAll },
{ "SBC", 0x080A66C, 0xe0, 0, PutAll },
{ "SAX", 0x0000001, 0x22, 0, PutAll },
{ "SAY", 0x0000001, 0x42, 0, PutAll },
{ "SBC", 0x080A66C, 0xe0, 0, PutAll },
{ "SEC", 0x0000001, 0x38, 0, PutAll },
{ "SED", 0x0000001, 0xf8, 0, PutAll },
{ "SEI", 0x0000001, 0x78, 0, PutAll },

View File

@ -303,6 +303,10 @@ static void SetSys (const char* Sys)
NewSymbol ("__SIM65C02__", 1);
break;
case TGT_OSIC1P:
NewSymbol ("__OSIC1P__", 1);
break;
case TGT_PCENGINE:
NewSymbol ("__PCE__", 1);
break;

View File

@ -1964,6 +1964,7 @@ static CtrlDesc CtrlCmdTab [] = {
{ ccNone, DoA16 },
{ ccNone, DoA8 },
{ ccNone, DoAddr }, /* .ADDR */
{ ccNone, DoUnexpected }, /* .ADDRSIZE */
{ ccNone, DoAlign },
{ ccNone, DoASCIIZ },
{ ccNone, DoAssert },
@ -2039,6 +2040,7 @@ static CtrlDesc CtrlCmdTab [] = {
{ ccNone, DoIncBin },
{ ccNone, DoInclude },
{ ccNone, DoInterruptor },
{ ccNone, DoUnexpected }, /* .ISMNEMONIC */
{ ccNone, DoInvalid }, /* .LEFT */
{ ccNone, DoLineCont },
{ ccNone, DoList },

View File

@ -135,6 +135,7 @@ struct DotKeyword {
{ ".A16", TOK_A16 },
{ ".A8", TOK_A8 },
{ ".ADDR", TOK_ADDR },
{ ".ADDRSIZE", TOK_ADDRSIZE },
{ ".ALIGN", TOK_ALIGN },
{ ".AND", TOK_BOOLAND },
{ ".ASCIIZ", TOK_ASCIIZ },
@ -222,6 +223,8 @@ struct DotKeyword {
{ ".INCBIN", TOK_INCBIN },
{ ".INCLUDE", TOK_INCLUDE },
{ ".INTERRUPTOR", TOK_INTERRUPTOR },
{ ".ISMNEM", TOK_ISMNEMONIC },
{ ".ISMNEMONIC", TOK_ISMNEMONIC },
{ ".LEFT", TOK_LEFT },
{ ".LINECONT", TOK_LINECONT },
{ ".LIST", TOK_LIST },
@ -723,7 +726,24 @@ static token_t FindDotKeyword (void)
R = bsearch (&K, DotKeywords, sizeof (DotKeywords) / sizeof (DotKeywords [0]),
sizeof (DotKeywords [0]), CmpDotKeyword);
if (R != 0) {
/* By default, disable any somewhat experiemental DotKeyword. */
switch (R->Tok) {
case TOK_ADDRSIZE:
/* Disallow .ADDRSIZE function by default */
if (AddrSize == 0) {
return TOK_NONE;
}
break;
default:
break;
}
return R->Tok;
} else {
return TOK_NONE;
}

View File

@ -696,10 +696,10 @@ void SymDump (FILE* F)
while (S) {
/* Ignore unused symbols */
if ((S->Flags & SF_UNUSED) != 0) {
if ((S->Flags & SF_UNUSED) == 0) {
fprintf (F,
"%m%-24p %s %s %s %s %s\n",
GetSymName (S),
"%-24s %s %s %s %s %s\n",
SB_GetConstBuf (GetSymName (S)),
(S->Flags & SF_DEFINED)? "DEF" : "---",
(S->Flags & SF_REFERENCED)? "REF" : "---",
(S->Flags & SF_IMPORT)? "IMP" : "---",

View File

@ -123,6 +123,7 @@ typedef enum token_t {
TOK_A16 = TOK_FIRSTPSEUDO,
TOK_A8,
TOK_ADDR,
TOK_ADDRSIZE,
TOK_ALIGN,
TOK_ASCIIZ,
TOK_ASSERT,
@ -198,6 +199,7 @@ typedef enum token_t {
TOK_INCBIN,
TOK_INCLUDE,
TOK_INTERRUPTOR,
TOK_ISMNEMONIC,
TOK_LEFT,
TOK_LINECONT,
TOK_LIST,

View File

@ -6,7 +6,7 @@
/* */
/* */
/* */
/* (C) 2001-2012, Ullrich von Bassewitz */
/* (C) 2001-2015, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
@ -46,6 +46,7 @@
#include "codeseg.h"
#include "datatype.h"
#include "error.h"
#include "global.h"
#include "reginfo.h"
#include "symtab.h"
#include "codeinfo.h"
@ -386,33 +387,35 @@ void GetFuncInfo (const char* Name, unsigned short* Use, unsigned short* Chg)
** Search for it in the list of builtin functions.
*/
if (Name[0] == '_') {
/* Search in the symbol table, skip the leading underscore */
SymEntry* E = FindGlobalSym (Name+1);
/* Did we find it in the top level table? */
/* Did we find it in the top-level table? */
if (E && IsTypeFunc (E->Type)) {
FuncDesc* D = E->V.F.Func;
/* A function may use the A or A/X registers if it is a fastcall
** function. If it is not a fastcall function but a variadic one,
** it will use the Y register (the parameter size is passed here).
** In all other cases, no registers are used. However, we assume
** that any function will destroy all registers.
/* A variadic function will use the Y register (the parameter list
** size is passed there). A fastcall function will use the A or A/X
** registers. In all other cases, no registers are used. However,
** we assume that any function will destroy all registers.
*/
if (IsQualFastcall (E->Type) && D->ParamCount > 0) {
/* Will use registers depending on the last param */
unsigned LastParamSize = CheckedSizeOf (D->LastParam->Type);
if (LastParamSize == 1) {
*Use = REG_A;
} else if (LastParamSize == 2) {
*Use = REG_AX;
} else {
*Use = REG_EAX;
}
} else if ((D->Flags & FD_VARIADIC) != 0) {
if ((D->Flags & FD_VARIADIC) != 0) {
*Use = REG_Y;
} else if (D->ParamCount > 0 &&
(AutoCDecl ?
IsQualFastcall (E->Type) :
!IsQualCDecl (E->Type))) {
/* Will use registers depending on the last param. */
switch (CheckedSizeOf (D->LastParam->Type)) {
case 1u:
*Use = REG_A;
break;
case 2u:
*Use = REG_AX;
break;
default:
*Use = REG_EAX;
}
} else {
/* Will not use any registers */
*Use = REG_NONE;

View File

@ -766,12 +766,8 @@ static unsigned Opt_toseqax_tosneax (StackOpData* D, const char* BoolTransformer
InsertEntry (D, X, D->IP++);
/* Lhs load entries can be removed */
if (LoadX->AM != AM65_IMM) {
D->Lhs.X.Flags |= LI_REMOVE;
}
if (LoadA->AM != AM65_IMM) {
D->Lhs.A.Flags |= LI_REMOVE;
}
D->Lhs.X.Flags |= LI_REMOVE;
D->Lhs.A.Flags |= LI_REMOVE;
} else if ((D->Rhs.A.Flags & (LI_DIRECT | LI_RELOAD_Y)) == LI_DIRECT &&
(D->Rhs.X.Flags & (LI_DIRECT | LI_RELOAD_Y)) == LI_DIRECT) {
@ -794,12 +790,8 @@ static unsigned Opt_toseqax_tosneax (StackOpData* D, const char* BoolTransformer
InsertEntry (D, X, D->IP++);
/* Rhs load entries can be removed */
if (LoadX->AM != AM65_IMM) {
D->Rhs.X.Flags |= LI_REMOVE;
}
if (LoadA->AM != AM65_IMM) {
D->Rhs.A.Flags |= LI_REMOVE;
}
D->Rhs.X.Flags |= LI_REMOVE;
D->Rhs.A.Flags |= LI_REMOVE;
} else if ((D->Rhs.A.Flags & LI_DIRECT) != 0 &&
(D->Rhs.X.Flags & LI_DIRECT) != 0) {

View File

@ -6,7 +6,7 @@
/* */
/* */
/* */
/* (C) 1998-2012, Ullrich von Bassewitz */
/* (C) 1998-2015, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
@ -293,15 +293,15 @@ void PrintType (FILE* F, const Type* T)
/* Recursive call */
PrintType (F, T + 1);
if (T->A.L == UNSPECIFIED) {
fprintf (F, "[]");
fprintf (F, " []");
} else {
fprintf (F, "[%ld]", T->A.L);
fprintf (F, " [%ld]", T->A.L);
}
return;
case T_TYPE_PTR:
/* Recursive call */
PrintType (F, T + 1);
fprintf (F, "*");
fprintf (F, " *");
return;
case T_TYPE_FUNC:
fprintf (F, "function returning ");
@ -659,7 +659,7 @@ Type* GetBaseElementType (Type* T)
** will return. Otherwise it will return the base element type, which means
** the element type that is not an array.
*/
{
{
while (IsTypeArray (T)) {
++T;
}

View File

@ -6,7 +6,7 @@
/* */
/* */
/* */
/* (C) 1998-2012, Ullrich von Bassewitz */
/* (C) 1998-2015, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
@ -603,6 +603,16 @@ INLINE int IsQualCDecl (const Type* T)
# define IsQualCDecl(T) (((T)->C & T_QUAL_CDECL) != 0)
#endif
#if defined(HAVE_INLINE)
INLINE int IsQualCConv (const Type* T)
/* Return true if the given type has a calling convention qualifier */
{
return (T->C & T_QUAL_CCONV) != 0;
}
#else
# define IsQualCConv(T) (((T)->C & T_QUAL_CCONV) != 0)
#endif
int IsVariadicFunc (const Type* T) attribute ((const));
/* Return true if this is a function type or pointer to function type with
** variable parameter list

View File

@ -6,7 +6,7 @@
/* */
/* */
/* */
/* (C) 1998-2013, Ullrich von Bassewitz */
/* (C) 1998-2015, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
@ -85,7 +85,7 @@ struct StructInitData {
static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers);
/* Parse a type specificier */
/* Parse a type specifier */
static unsigned ParseInitInternal (Type* T, int AllowFlexibleMembers);
/* Parse initialization of variables. Return the number of data bytes. */
@ -335,18 +335,30 @@ static void FixQualifiers (Type* DataType)
T = DataType;
while (T->C != T_END) {
if (IsTypePtr (T)) {
/* Calling convention qualifier on the pointer? */
if (IsQualCConv (T)) {
/* Pull the convention off of the pointer */
Q = T[0].C & T_QUAL_CCONV;
T[0].C &= ~T_QUAL_CCONV;
/* Fastcall qualifier on the pointer? */
if (IsQualFastcall (T)) {
/* Pointer to function which is not fastcall? */
if (IsTypeFunc (T+1) && !IsQualFastcall (T+1)) {
/* Move the fastcall qualifier from the pointer to
** the function.
*/
T[0].C &= ~T_QUAL_FASTCALL;
T[1].C |= T_QUAL_FASTCALL;
/* Pointer to a function which doesn't have an explicit convention? */
if (IsTypeFunc (T + 1)) {
if (IsQualCConv (T + 1)) {
if ((T[1].C & T_QUAL_CCONV) == Q) {
Warning ("Pointer duplicates function's calling convention");
} else {
Error ("Function's and pointer's calling conventions are different");
}
} else {
if (Q == T_QUAL_FASTCALL && IsVariadicFunc (T + 1)) {
Error ("Variadic-function pointers cannot be __fastcall__");
} else {
/* Move the qualifier from the pointer to the function. */
T[1].C |= Q;
}
}
} else {
Error ("Invalid `_fastcall__' qualifier for pointer");
Error ("Not pointer to a function; can't use a calling convention");
}
}
@ -355,8 +367,8 @@ static void FixQualifiers (Type* DataType)
if (Q == T_QUAL_NONE) {
/* No address size qualifiers specified */
if (IsTypeFunc (T+1)) {
/* Pointer to function. Use the qualifier from the function
** or the default if the function don't has one.
/* Pointer to function. Use the qualifier from the function,
** or the default if the function doesn't have one.
*/
Q = (T[1].C & T_QUAL_ADDRSIZE);
if (Q == T_QUAL_NONE) {
@ -368,7 +380,7 @@ static void FixQualifiers (Type* DataType)
T[0].C |= Q;
} else {
/* We have address size qualifiers. If followed by a function,
** apply these also to the function.
** apply them to the function also.
*/
if (IsTypeFunc (T+1)) {
TypeCode FQ = (T[1].C & T_QUAL_ADDRSIZE);
@ -489,7 +501,7 @@ static void ParseEnumDecl (void)
static int ParseFieldWidth (Declaration* Decl)
/* Parse an optional field width. Returns -1 if no field width is speficied,
/* Parse an optional field width. Returns -1 if no field width is specified,
** otherwise the width of the field.
*/
{
@ -862,7 +874,7 @@ NextMember: if (CurTok.Tok != TOK_COMMA) {
static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers)
/* Parse a type specificier */
/* Parse a type specifier */
{
ident Ident;
SymEntry* Entry;
@ -1376,13 +1388,13 @@ static FuncDesc* ParseFuncDecl (void)
static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode)
/* Recursively process declarators. Build a type array in reverse order. */
{
/* Read optional function or pointer qualifiers. These modify the
** identifier or token to the right. For convenience, we allow the fastcall
** qualifier also for pointers here. If it is a pointer-to-function, the
** qualifier will later be transfered to the function itself. If it's a
/* Read optional function or pointer qualifiers. They modify the
** identifier or token to the right. For convenience, we allow a calling
** convention also for pointers here. If it's a pointer-to-function, the
** qualifier later will be transfered to the function itself. If it's a
** pointer to something else, it will be flagged as an error.
*/
TypeCode Qualifiers = OptionalQualifiers (T_QUAL_ADDRSIZE | T_QUAL_FASTCALL);
TypeCode Qualifiers = OptionalQualifiers (T_QUAL_ADDRSIZE | T_QUAL_CCONV);
/* Pointer to something */
if (CurTok.Tok == TOK_STAR) {
@ -1390,10 +1402,10 @@ static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode)
/* Skip the star */
NextToken ();
/* Allow const, restrict and volatile qualifiers */
/* Allow const, restrict, and volatile qualifiers */
Qualifiers |= OptionalQualifiers (T_QUAL_CONST | T_QUAL_VOLATILE | T_QUAL_RESTRICT);
/* Parse the type, the pointer points to */
/* Parse the type that the pointer points to */
Declarator (Spec, D, Mode);
/* Add the type */
@ -1443,7 +1455,7 @@ static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode)
/* We cannot specify fastcall for variadic functions */
if ((F->Flags & FD_VARIADIC) && (Qualifiers & T_QUAL_FASTCALL)) {
Error ("Variadic functions cannot be `__fastcall__'");
Error ("Variadic functions cannot be __fastcall__");
Qualifiers &= ~T_QUAL_FASTCALL;
}

View File

@ -1,6 +1,7 @@
/* expr.c
**
** Ullrich von Bassewitz, 21.06.1998
** 1998-06-21, Ullrich von Bassewitz
** 2015-06-26, Greg King
*/
@ -470,9 +471,11 @@ static void FunctionCall (ExprDesc* Expr)
/* Handle function pointers transparently */
IsFuncPtr = IsTypeFuncPtr (Expr->Type);
if (IsFuncPtr) {
/* Check wether it's a fastcall function that has parameters */
IsFastcall = IsQualFastcall (Expr->Type + 1) && (Func->ParamCount > 0);
/* Check whether it's a fastcall function that has parameters */
IsFastcall = (Func->Flags & FD_VARIADIC) == 0 && Func->ParamCount > 0 &&
(AutoCDecl ?
IsQualFastcall (Expr->Type + 1) :
!IsQualCDecl (Expr->Type + 1));
/* Things may be difficult, depending on where the function pointer
** resides. If the function pointer is an expression of some sort
@ -517,7 +520,10 @@ static void FunctionCall (ExprDesc* Expr)
}
/* If we didn't inline the function, get fastcall info */
IsFastcall = IsQualFastcall (Expr->Type);
IsFastcall = (Func->Flags & FD_VARIADIC) == 0 &&
(AutoCDecl ?
IsQualFastcall (Expr->Type) :
!IsQualCDecl (Expr->Type));
}
/* Parse the parameter list */
@ -1707,8 +1713,13 @@ void hie10 (ExprDesc* Expr)
} else {
Error ("Illegal indirection");
}
/* The * operator yields an lvalue */
ED_MakeLVal (Expr);
/* If the expression points to an array, then don't convert the
** address -- it already is the location of the first element.
*/
if (!IsTypeArray (Expr->Type)) {
/* The * operator yields an lvalue */
ED_MakeLVal (Expr);
}
}
break;

View File

@ -6,7 +6,7 @@
/* */
/* */
/* */
/* (C) 2000-2012, Ullrich von Bassewitz */
/* (C) 2000-2015, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
@ -460,6 +460,9 @@ void NewFunc (SymEntry* Func)
*/
if (D->ParamCount > 0 || (D->Flags & FD_VARIADIC) != 0) {
g_importmainargs ();
/* The start-up code doesn't fast-call main(). */
Func->Type->C |= T_QUAL_CDECL;
}
/* Determine if this is a main function in a C99 environment that
@ -478,13 +481,12 @@ void NewFunc (SymEntry* Func)
PushLiteralPool (Func);
/* If this is a fastcall function, push the last parameter onto the stack */
if (IsQualFastcall (Func->Type) && D->ParamCount > 0) {
if ((D->Flags & FD_VARIADIC) == 0 && D->ParamCount > 0 &&
(AutoCDecl ?
IsQualFastcall (Func->Type) :
!IsQualCDecl (Func->Type))) {
unsigned Flags;
/* Fastcall functions may never have an ellipsis or the compiler is buggy */
CHECK ((D->Flags & FD_VARIADIC) == 0);
/* Generate the push */
if (IsTypeFunc (D->LastParam->Type)) {
/* Pointer to function */

View File

@ -6,7 +6,7 @@
/* */
/* */
/* */
/* (C) 1998-2012, Ullrich von Bassewitz */
/* (C) 1998-2015, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
@ -44,6 +44,7 @@
unsigned char AddSource = 0; /* Add source lines as comments */
unsigned char AutoCDecl = 0; /* Make functions default to __cdecl__ */
unsigned char DebugInfo = 0; /* Add debug info to the obj */
unsigned char PreprocessOnly = 0; /* Just preprocess the input */
unsigned char DebugOptOutput = 0; /* Output debug stuff */

View File

@ -6,7 +6,7 @@
/* */
/* */
/* */
/* (C) 1998-2012, Ullrich von Bassewitz */
/* (C) 1998-2015, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
@ -52,6 +52,7 @@
/* Options */
extern unsigned char AddSource; /* Add source lines as comments */
extern unsigned char AutoCDecl; /* Make functions default to __cdecl__ */
extern unsigned char DebugInfo; /* Add debug info to the obj */
extern unsigned char PreprocessOnly; /* Just preprocess the input */
extern unsigned char DebugOptOutput; /* Output debug stuff */

View File

@ -6,7 +6,7 @@
/* */
/* */
/* */
/* (C) 2000-2013, Ullrich von Bassewitz */
/* (C) 2000-2015, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
@ -104,6 +104,7 @@ static void Usage (void)
"\n"
"Long options:\n"
" --add-source\t\t\tInclude source as comment\n"
" --all-cdecl\t\t\tMake functions default to __cdecl__\n"
" --bss-name seg\t\tSet the name of the BSS segment\n"
" --check-stack\t\t\tGenerate stack overflow checks\n"
" --code-name seg\t\tSet the name of the CODE segment\n"
@ -258,6 +259,10 @@ static void SetSys (const char* Sys)
DefineNumericMacro ("__SIM65C02__", 1);
break;
case TGT_OSIC1P:
DefineNumericMacro ("__OSIC1P__", 1);
break;
case TGT_PCENGINE:
DefineNumericMacro ("__PCE__", 1);
break;
@ -350,6 +355,15 @@ static void OptAddSource (const char* Opt attribute ((unused)),
static void OptAllCDecl (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* Make functions default to cdecl instead of fastcall. */
{
AutoCDecl = 1;
}
static void OptBssName (const char* Opt attribute ((unused)), const char* Arg)
/* Handle the --bss-name option */
{
@ -790,6 +804,7 @@ int main (int argc, char* argv[])
/* Program long options */
static const LongOpt OptTab[] = {
{ "--add-source", 0, OptAddSource },
{ "--all-cdecl", 0, OptAllCDecl },
{ "--bss-name", 1, OptBssName },
{ "--check-stack", 0, OptCheckStack },
{ "--code-name", 1, OptCodeName },

View File

@ -6,10 +6,10 @@
/* */
/* */
/* */
/* (C) 1998-2008 Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* (C) 1998-2015, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
@ -37,6 +37,7 @@
/* cc65 */
#include "funcdesc.h"
#include "global.h"
#include "symtab.h"
#include "typecmp.h"
@ -245,23 +246,36 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
return;
}
}
if (LeftType == T_TYPE_FUNC) {
/* If a calling convention wasn't set explicitly,
** then assume the default one.
*/
if ((LeftQual & T_QUAL_CCONV) == T_QUAL_NONE) {
LeftQual |= (AutoCDecl || IsVariadicFunc (lhs)) ? T_QUAL_CDECL : T_QUAL_FASTCALL;
}
if ((RightQual & T_QUAL_CCONV) == T_QUAL_NONE) {
RightQual |= (AutoCDecl || IsVariadicFunc (rhs)) ? T_QUAL_CDECL : T_QUAL_FASTCALL;
}
}
if (LeftQual != RightQual) {
/* On the first indirection level, different qualifiers mean
** that the types are still compatible. On the second level,
** this is a (maybe minor) error, so we create a special
** return code, since a qualifier is dropped from a pointer.
** Starting from the next level, the types are incompatible
** if the qualifiers differ.
** that the types still are compatible. On the second level,
** that is a (maybe minor) error. We create a special return-code
** if a qualifier is dropped from a pointer. But, different calling
** conventions are incompatible. Starting from the next level,
** the types are incompatible if the qualifiers differ.
*/
/* (Debugging statement) */
/* printf ("Ind = %d %06X != %06X\n", Indirections, LeftQual, RightQual); */
switch (Indirections) {
case 0:
SetResult (Result, TC_STRICT_COMPATIBLE);
break;
case 1:
/* A non const value on the right is compatible to a
/* A non-const value on the right is compatible to a
** const one to the left, same for volatile.
*/
if ((LeftQual & T_QUAL_CONST) < (RightQual & T_QUAL_CONST) ||
@ -270,7 +284,11 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
} else {
SetResult (Result, TC_STRICT_COMPATIBLE);
}
break;
if (LeftType != T_TYPE_FUNC || (LeftQual & T_QUAL_CCONV) == (RightQual & T_QUAL_CCONV)) {
break;
}
/* else fall through */
default:
SetResult (Result, TC_INCOMPATIBLE);
@ -280,7 +298,6 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
/* Check for special type elements */
switch (LeftType) {
case T_TYPE_PTR:
++Indirections;
break;

View File

@ -6,7 +6,7 @@
/* */
/* */
/* */
/* (C) 2000-2011, Ullrich von Bassewitz */
/* (C) 2000-2015, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
@ -50,7 +50,7 @@
/* Translation table with direct (no) translation */
static unsigned char CTNone[256] = {
static const unsigned char CTNone[256] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@ -69,8 +69,8 @@ static unsigned char CTNone[256] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,
};
/* Translation table ISO-8859-1 -> ATASCII */
static const unsigned char CTAtari [256] = {
/* Translation table ISO-8859-1 -> AtASCII */
static const unsigned char CTAtari[256] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0xFD,0x08,0x7F,0x9B,0x0B,0x7D,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@ -89,8 +89,28 @@ static const unsigned char CTAtari [256] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,
};
/* Translation table ISO-8859-1 -> PETSCII */
static const unsigned char CTPET [256] = {
/* Translation table ISO-8859-1 -> OSASCII */
static const unsigned char CTOSI[256] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,
0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,
0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0x7D,0x7C,0x7F,0x7E,
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,
0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,
};
/* Translation table ISO-8859-1 -> PetSCII */
static const unsigned char CTPET[256] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x14,0x09,0x0D,0x11,0x93,0x0A,0x0E,0x0F,
0x10,0x0B,0x12,0x13,0x08,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@ -142,6 +162,7 @@ static const TargetEntry TargetMap[] = {
{ "module", TGT_MODULE },
{ "nes", TGT_NES },
{ "none", TGT_NONE },
{ "osic1p", TGT_OSIC1P },
{ "pce", TGT_PCENGINE },
{ "pet", TGT_PET },
{ "plus4", TGT_PLUS4 },
@ -168,6 +189,7 @@ static const TargetProperties PropertyTable[TGT_COUNT] = {
{ "plus4", CPU_6502, BINFMT_BINARY, CTPET },
{ "cbm510", CPU_6502, BINFMT_BINARY, CTPET },
{ "cbm610", CPU_6502, BINFMT_BINARY, CTPET },
{ "osic1p", CPU_6502, BINFMT_BINARY, CTOSI },
{ "pet", CPU_6502, BINFMT_BINARY, CTPET },
{ "bbc", CPU_6502, BINFMT_BINARY, CTNone },
{ "apple2", CPU_6502, BINFMT_BINARY, CTNone },

View File

@ -64,6 +64,7 @@ typedef enum {
TGT_PLUS4,
TGT_CBM510,
TGT_CBM610,
TGT_OSIC1P,
TGT_PET,
TGT_BBC,
TGT_APPLE2,

View File

@ -47,7 +47,7 @@
#define VER_MAJOR 2U
#define VER_MINOR 14U
#define VER_MINOR 15U

View File

@ -6,10 +6,10 @@
/* */
/* */
/* */
/* (C) 2000-2006 Ullrich von Bassewitz */
/* Römerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* (C) 2000-2014, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
@ -66,6 +66,18 @@ void AddrCheck (unsigned Addr)
attr_t GetAttr (unsigned Addr)
/* Return the attribute for the given address */
{
/* Check the given address */
AddrCheck (Addr);
/* Return the attribute */
return AttrTab[Addr];
}
int SegmentDefined (unsigned Start, unsigned End)
/* Return true if the atSegment bit is set somewhere in the given range */
{
@ -79,14 +91,18 @@ int SegmentDefined (unsigned Start, unsigned End)
int HaveSegmentChange (unsigned Addr)
/* Return true if the segment change attribute is set for the given address */
int IsSegmentEnd (unsigned Addr)
/* Return true if a segment ends at the given address */
{
/* Check the given address */
AddrCheck (Addr);
return (GetAttr (Addr) & atSegmentEnd) != 0x0000;
}
/* Return the attribute */
return (AttrTab[Addr] & atSegmentChange) != 0;
int IsSegmentStart (unsigned Addr)
/* Return true if a segment starts at the given address */
{
return (GetAttr (Addr) & atSegmentStart) != 0x0000;
}
@ -145,18 +161,6 @@ void MarkAddr (unsigned Addr, attr_t Attr)
attr_t GetAttr (unsigned Addr)
/* Return the attribute for the given address */
{
/* Check the given address */
AddrCheck (Addr);
/* Return the attribute */
return AttrTab[Addr];
}
attr_t GetStyleAttr (unsigned Addr)
/* Return the style attribute for the given address */
{

View File

@ -6,10 +6,10 @@
/* */
/* */
/* */
/* (C) 2000-2006 Ullrich von Bassewitz */
/* Römerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* (C) 2000-2014, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
@ -47,33 +47,34 @@
typedef enum attr_t {
/* Styles */
atDefault = 0x0000, /* Default style */
atCode = 0x0001,
atIllegal = 0x0002,
atByteTab = 0x0003, /* Same as illegal */
atDByteTab = 0x0004,
atWordTab = 0x0005,
atDWordTab = 0x0006,
atAddrTab = 0x0007,
atRtsTab = 0x0008,
atTextTab = 0x0009,
atSkip = 0x000A, /* Skip code completely */
atDefault = 0x0000, /* Default style */
atCode = 0x0001,
atIllegal = 0x0002,
atByteTab = 0x0003, /* Same as illegal */
atDByteTab = 0x0004,
atWordTab = 0x0005,
atDWordTab = 0x0006,
atAddrTab = 0x0007,
atRtsTab = 0x0008,
atTextTab = 0x0009,
atSkip = 0x000A, /* Skip code completely */
/* Label flags */
atNoLabel = 0x0000, /* No label for this address */
atExtLabel = 0x0010, /* External label */
atIntLabel = 0x0020, /* Internally generated label */
atDepLabel = 0x0040, /* Dependent label */
atUnnamedLabel = 0x0080, /* Unnamed label */
atNoLabel = 0x0000, /* No label for this address */
atExtLabel = 0x0010, /* External label */
atIntLabel = 0x0020, /* Internally generated label */
atDepLabel = 0x0040, /* Dependent label */
atUnnamedLabel = 0x0080, /* Unnamed label */
atLabelDefined = 0x0100, /* True if we defined the label */
atLabelDefined = 0x0100, /* True if we defined the label */
atStyleMask = 0x000F, /* Output style */
atLabelMask = 0x00F0, /* Label information */
atStyleMask = 0x000F, /* Output style */
atLabelMask = 0x00F0, /* Label information */
/* Segment */
atSegment = 0x0100, /* Code is in a segment */
atSegmentChange = 0x0200, /* Either segment start or segment end */
atSegment = 0x0100, /* Code is in a segment */
atSegmentEnd = 0x0200, /* Segment end */
atSegmentStart = 0x0400, /* Segment start */
} attr_t;
@ -87,11 +88,17 @@ typedef enum attr_t {
void AddrCheck (unsigned Addr);
/* Check if the given address has a valid range */
attr_t GetAttr (unsigned Addr);
/* Return the attribute for the given address */
int SegmentDefined (unsigned Start, unsigned End);
/* Return true if the atSegment bit is set somewhere in the given range */
int HaveSegmentChange (unsigned Addr);
/* Return true if the segment change attribute is set for the given address */
int IsSegmentEnd (unsigned Addr);
/* Return true if a segment ends at the given address */
int IsSegmentStart (unsigned Addr);
/* Return true if a segment starts at the given address */
unsigned GetGranularity (attr_t Style);
/* Get the granularity for the given style */
@ -102,9 +109,6 @@ void MarkRange (unsigned Start, unsigned End, attr_t Attr);
void MarkAddr (unsigned Addr, attr_t Attr);
/* Mark an address with an attribute */
attr_t GetAttr (unsigned Addr);
/* Return the attribute for the given address */
attr_t GetStyleAttr (unsigned Addr);
/* Return the style attribute for the given address */
@ -114,5 +118,4 @@ attr_t GetLabelAttr (unsigned Addr);
/* End of attrtab.h */
#endif

View File

@ -6,10 +6,10 @@
/* */
/* */
/* */
/* (C) 2000-2007 Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* (C) 2000-2014, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
@ -65,12 +65,12 @@ static unsigned GetSpan (attr_t Style)
attr_t Attr;
if (MustDefLabel(PC+Count)) {
break;
}
}
Attr = GetAttr (PC+Count);
if ((Attr & atStyleMask) != Style) {
break;
}
if ((Attr & atSegmentChange)) {
if ((Attr & (atSegmentStart | atSegmentEnd))) {
break;
}
++Count;

View File

@ -6,7 +6,7 @@
/* */
/* */
/* */
/* (C) 2000-2011, Ullrich von Bassewitz */
/* (C) 2000-2014, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
@ -748,16 +748,13 @@ static void SegmentSection (void)
if (Start < 0) {
InfoError ("Start address is missing");
}
if (Start == End) {
InfoError ("Segment is empty");
}
if (Start > End) {
InfoError ("Start address of segment is greater than end address");
}
/* Check that segments do not overlap */
if (SegmentDefined ((unsigned) Start, (unsigned) End)) {
InfoError ("Segments cannot overlap");
InfoError ("Segments must not overlap");
}
/* Remember the segment data */

View File

@ -6,7 +6,7 @@
/* */
/* */
/* */
/* (C) 1998-2011, Ullrich von Bassewitz */
/* (C) 1998-2014, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
@ -60,6 +60,7 @@
#include "opctable.h"
#include "output.h"
#include "scanner.h"
#include "segment.h"
@ -347,6 +348,8 @@ static void OptVersion (const char* Opt attribute ((unused)),
static void OneOpcode (unsigned RemainingBytes)
/* Disassemble one opcode */
{
unsigned I;
/* Get the opcode from the current address */
unsigned char OPC = GetCodeByte (PC);
@ -356,6 +359,14 @@ static void OneOpcode (unsigned RemainingBytes)
/* Get the output style for the current PC */
attr_t Style = GetStyleAttr (PC);
/* If a segment begins here, then name that segment.
** Note that the segment is named even if its code is being skipped,
** because some of its later code might not be skipped.
*/
if (IsSegmentStart (PC)) {
StartSegment (GetSegmentStartName (PC), GetSegmentAddrSize (PC));
}
/* If we have a label at this address, output the label and an attached
** comment, provided that we aren't in a skip area.
*/
@ -371,7 +382,8 @@ static void OneOpcode (unsigned RemainingBytes)
** - ...if we have enough bytes remaining for the code at this address.
** - ...if the current instruction is valid for the given CPU.
** - ...if there is no label somewhere between the instruction bytes.
** If any of these conditions is false, switch to data mode.
** - ...if there is no segment change between the instruction bytes.
** If any one of those conditions is false, switch to data mode.
*/
if (Style == atDefault) {
if (D->Size > RemainingBytes) {
@ -381,9 +393,15 @@ static void OneOpcode (unsigned RemainingBytes)
Style = atIllegal;
MarkAddr (PC, Style);
} else {
unsigned I;
for (I = 1; I < D->Size; ++I) {
if (HaveLabel (PC+I) || HaveSegmentChange (PC+I)) {
for (I = PC + D->Size; --I > PC; ) {
if (HaveLabel (I) || IsSegmentStart (I)) {
Style = atIllegal;
MarkAddr (PC, Style);
break;
}
}
for (I = 0; I < D->Size - 1u; ++I) {
if (IsSegmentEnd (PC + I)) {
Style = atIllegal;
MarkAddr (PC, Style);
break;
@ -406,7 +424,6 @@ static void OneOpcode (unsigned RemainingBytes)
*/
if (D->Size <= RemainingBytes) {
/* Output labels within the next insn */
unsigned I;
for (I = 1; I < D->Size; ++I) {
ForwardLabel (I);
}
@ -453,7 +470,16 @@ static void OneOpcode (unsigned RemainingBytes)
DataByteLine (1);
++PC;
break;
}
/* Change back to the default CODE segment if
** a named segment stops at the current address.
*/
for (I = D->Size; I >= 1; --I) {
if (IsSegmentEnd (PC - I)) {
EndSegment ();
break;
}
}
}

View File

@ -6,7 +6,7 @@
/* */
/* */
/* */
/* (C) 2000-2009, Ullrich von Bassewitz */
/* (C) 2000-2014, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
@ -63,6 +63,8 @@ static unsigned Col = 1; /* Current column */
static unsigned Line = 0; /* Current line on page */
static unsigned Page = 1; /* Current output page */
static const char* SegmentName = 0; /* Name of current segment */
/*****************************************************************************/
@ -223,23 +225,6 @@ void DefConst (const char* Name, const char* Comment, unsigned Addr)
void StartSegment (const char* Name, unsigned AddrSize)
/* Start a segment */
{
if (Pass == PassCount) {
Output (".segment");
Indent (ACol);
if (AddrSize == ADDR_SIZE_DEFAULT) {
Output ("\"%s\"", Name);
} else {
Output ("\"%s\": %s", Name, AddrSizeToStr (AddrSize));
}
LineFeed ();
}
}
void DataByteLine (unsigned ByteCount)
/* Output a line with bytes */
{
@ -335,6 +320,39 @@ void SeparatorLine (void)
void StartSegment (const char* Name, unsigned AddrSize)
/* Start a segment */
{
if (Pass == PassCount) {
LineFeed ();
Output (".segment");
Indent (ACol);
SegmentName = Name;
Output ("\"%s\"", Name);
if (AddrSize != ADDR_SIZE_DEFAULT) {
Output (": %s", AddrSizeToStr (AddrSize));
}
LineFeed ();
LineFeed ();
}
}
void EndSegment (void)
/* End a segment */
{
LineFeed ();
Output ("; End of \"%s\" segment", SegmentName);
LineFeed ();
SeparatorLine ();
Output (".code");
LineFeed ();
LineFeed ();
}
void UserComment (const char* Comment)
/* Output a comment line */
{

View File

@ -6,10 +6,10 @@
/* */
/* */
/* */
/* (C) 2000-2007 Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* (C) 2000-2014, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
@ -74,12 +74,6 @@ void DefForward (const char* Name, const char* Comment, unsigned Offs);
void DefConst (const char* Name, const char* Comment, unsigned Addr);
/* Define an address constant */
void StartSegment (const char* Name, unsigned AddrSize);
/* Start a segment */
void EndSegment (void);
/* End a segment */
void OneDataByte (void);
/* Output a .byte line with the current code byte */
@ -99,6 +93,12 @@ void DataDWordLine (unsigned ByteCount);
void SeparatorLine (void);
/* Print a separator line */
void StartSegment (const char* Name, unsigned AddrSize);
/* Start a segment */
void EndSegment (void);
/* End a segment */
void UserComment (const char* Comment);
/* Output a comment line */
@ -111,5 +111,4 @@ void OutputSettings (void);
/* End of output.h */
#endif

View File

@ -6,10 +6,10 @@
/* */
/* */
/* */
/* (C) 2007 Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* (C) 2007-2014, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
@ -58,18 +58,15 @@
typedef struct Segment Segment;
struct Segment {
Segment* NextStart; /* Pointer to next segment */
Segment* NextEnd; /* Pointer to next segment */
unsigned long Start;
unsigned long End;
unsigned AddrSize;
char Name[1]; /* Name, dynamically allocated */
};
/* Tables containing the segments. A segment is inserted using it's hash
** value. Collision is done by single linked lists.
/* Table containing the segments. A segment is inserted using its hash
** value. Collisions are handled by single-linked lists.
*/
static Segment* StartTab[HASH_SIZE]; /* Table containing segment starts */
static Segment* EndTab[HASH_SIZE]; /* Table containing segment ends */
@ -90,20 +87,53 @@ void AddAbsSegment (unsigned Start, unsigned End, const char* Name)
/* Fill in the data */
S->Start = Start;
S->End = End;
S->AddrSize = ADDR_SIZE_ABS;
memcpy (S->Name, Name, Len + 1);
/* Insert the segment into the hash tables */
/* Insert the segment into the hash table */
S->NextStart = StartTab[Start % HASH_SIZE];
StartTab[Start % HASH_SIZE] = S;
S->NextEnd = EndTab[End % HASH_SIZE];
EndTab[End % HASH_SIZE] = S;
/* Mark start and end of the segment */
MarkAddr (Start, atSegmentChange);
MarkAddr (End, atSegmentChange);
MarkAddr (Start, atSegmentStart);
MarkAddr (End, atSegmentEnd);
/* Mark the addresses within the segment */
MarkRange (Start, End, atSegment);
}
char* GetSegmentStartName (unsigned Addr)
/* Return the name of the segment which starts at the given address */
{
Segment* S = StartTab[Addr % HASH_SIZE];
/* Search the collision list for the exact address */
while (S != 0) {
if (S->Start == Addr) {
return S->Name;
}
S = S->NextStart;
}
return 0;
}
unsigned GetSegmentAddrSize (unsigned Addr)
/* Return the address size of the segment which starts at the given address */
{
Segment* S = StartTab[Addr % HASH_SIZE];
/* Search the collision list for the exact address */
while (S != 0) {
if (S->Start == Addr) {
return S->AddrSize;
}
S = S->NextStart;
}
return 0;
}

View File

@ -6,10 +6,10 @@
/* */
/* */
/* */
/* (C) 2007 Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* (C) 2007-2014, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
@ -47,8 +47,13 @@
void AddAbsSegment (unsigned Start, unsigned End, const char* Name);
/* Add an absolute segment to the segment table */
char* GetSegmentStartName (unsigned Addr);
/* Return the name of the segment which starts at the given address */
unsigned GetSegmentAddrSize (unsigned Addr);
/* Return the address size of the segment which starts at the given address */
/* End of segment.h */
#endif

View File

@ -1,41 +1,43 @@
# toplevel makefile for the regression tests
# top-level makefile for the regression tests
MAKE := make --no-print-dir
# You can comment this special target when you debug the regression tests.
# Then, make will give you more progress reports.
.SILENT:
ifneq ($(shell echo),)
CMD_EXE = 1
CMD_EXE := 1
endif
ifdef CMD_EXE
RM := del /f
EXE := .exe
MKDIR = mkdir
RMDIR = rmdir
DEL = -del /f $(subst /,\,$1)
MKDIR = mkdir $(subst /,\,$1)
RMDIR = -rmdir /s /q $(subst /,\,$1)
else
RM := rm -f
EXE :=
MKDIR = mkdir -p
RMDIR = rmdir
DEL = $(RM) $1
MKDIR = mkdir $1
RMDIR = rmdir $1
endif
WORKDIR := ../testwrk
.PHONY: dotests clean
CC := gcc
.PHONY: all dotests continue mostly-clean clean
all: dotests
$(WORKDIR):
@$(MKDIR) $(WORKDIR)
$(call MKDIR,$(WORKDIR))
$(WORKDIR)/bdiff$(EXE): $(WORKDIR)
@$(CC) -o $(WORKDIR)/bdiff$(EXE) bdiff.c
$(WORKDIR)/bdiff$(EXE): bdiff.c | $(WORKDIR)
$(CC) -O2 -o $@ $<
dotests: $(WORKDIR)/bdiff$(EXE)
@$(MAKE) -C val clean all
@$(MAKE) -C ref clean all
@$(MAKE) -C err clean all
@$(MAKE) -C misc clean all
.NOTPARALLEL:
dotests: mostly-clean continue
continue: $(WORKDIR)/bdiff$(EXE)
@$(MAKE) -C val all
@ -43,10 +45,12 @@ continue: $(WORKDIR)/bdiff$(EXE)
@$(MAKE) -C err all
@$(MAKE) -C misc all
clean:
mostly-clean:
@$(MAKE) -C val clean
@$(MAKE) -C ref clean
@$(MAKE) -C err clean
@$(MAKE) -C misc clean
@$(RM) $(WORKDIR)/bdiff$(EXE)
@$(RMDIR) $(WORKDIR)
clean: mostly-clean
@$(call DEL,$(WORKDIR)/bdiff$(EXE))
@$(call RMDIR,$(WORKDIR))

View File

@ -2,51 +2,47 @@
# makefile for the tests that MUST NOT compile
ifneq ($(shell echo),)
CMD_EXE = 1
CMD_EXE := 1
endif
CC65FLAGS = -t sim6502
ifdef CMD_EXE
NOT := - # Hack
DEL = -del /f $(subst /,\,$1)
else
NOT := !
DEL = $(RM) $1
endif
CC65FLAGS := -t sim6502
CL65 := $(if $(wildcard ../../bin/cl65*),../../bin/cl65,cl65)
ifdef CMD_EXE
RM := del /f
else
RM := rm -f
endif
WORKDIR := ./../../testwrk
WORKDIR := ../../testwrk
.PHONY: all clean
SOURCES := $(wildcard *.c)
TESTS := $(SOURCES:%.c=$(WORKDIR)/%.prg)
TESTS += $(SOURCES:%.c=$(WORKDIR)/%.o.prg)
TESTS += $(SOURCES:%.c=$(WORKDIR)/%.os.prg)
TESTS += $(SOURCES:%.c=$(WORKDIR)/%.osi.prg)
TESTS += $(SOURCES:%.c=$(WORKDIR)/%.osir.prg)
TESTS += $(SOURCES:%.c=$(WORKDIR)/%.oi.prg)
TESTS += $(SOURCES:%.c=$(WORKDIR)/%.oir.prg)
TESTS += $(SOURCES:%.c=$(WORKDIR)/%.or.prg)
TESTS := $(foreach option,. .o. .os. .osi. .osir. .oi. .oir. .or.,$(SOURCES:%.c=$(WORKDIR)/%$(option)prg))
all: $(TESTS)
$(WORKDIR)/%.prg: %.c
! $(CL65) $(CC65FLAGS) $< -o $@
$(NOT) $(CL65) $(CC65FLAGS) $< -o $@
$(WORKDIR)/%.o.prg: %.c
! $(CL65) -O $(CC65FLAGS) $< -o $@
$(NOT) $(CL65) -O $(CC65FLAGS) $< -o $@
$(WORKDIR)/%.os.prg: %.c
! $(CL65) -Os $(CC65FLAGS) $< -o $@
$(NOT) $(CL65) -Os $(CC65FLAGS) $< -o $@
$(WORKDIR)/%.osi.prg: %.c
! $(CL65) -Osi $(CC65FLAGS) $< -o $@
$(NOT) $(CL65) -Osi $(CC65FLAGS) $< -o $@
$(WORKDIR)/%.osir.prg: %.c
! $(CL65) -Osir $(CC65FLAGS) $< -o $@
$(NOT) $(CL65) -Osir $(CC65FLAGS) $< -o $@
$(WORKDIR)/%.oi.prg: %.c
! $(CL65) -Oi $(CC65FLAGS) $< -o $@
$(NOT) $(CL65) -Oi $(CC65FLAGS) $< -o $@
$(WORKDIR)/%.oir.prg: %.c
! $(CL65) -Oir $(CC65FLAGS) $< -o $@
$(NOT) $(CL65) -Oir $(CC65FLAGS) $< -o $@
$(WORKDIR)/%.or.prg: %.c
! $(CL65) -Or $(CC65FLAGS) $< -o $@
$(NOT) $(CL65) -Or $(CC65FLAGS) $< -o $@
clean:
@$(RM) $(TESTS)
@$(RM) $(SOURCES:%.c=$(WORKDIR)/%.o)
@$(call DEL,$(TESTS))
@$(call DEL,$(SOURCES:.c=.o))

Some files were not shown because too many files have changed in this diff Show More