mirror of
https://github.com/cc65/cc65.git
synced 2025-04-08 19:38:55 +00:00
Merge branch 'cc65:master' into master
This commit is contained in:
commit
e373aa2d3f
2
.github/checks/lastline.sh
vendored
2
.github/checks/lastline.sh
vendored
@ -9,7 +9,7 @@ nl='
|
||||
'
|
||||
nl=$'\n'
|
||||
r1="${nl}$"
|
||||
FILES=`find $CHECK_PATH -type f \( -name \*.inc -o -name Makefile -o -name \*.cfg -o -name \*.\[chs\] -o -name \*.mac -o -name \*.asm -o -name \*.sgml \) -print | while read f; do
|
||||
FILES=`find $CHECK_PATH -type f -size +0 \( -name \*.inc -o -name Makefile -o -name \*.cfg -o -name \*.\[chs\] -o -name \*.mac -o -name \*.asm -o -name \*.sgml \) -print | while read f; do
|
||||
t=$(tail -c2 $f; printf x)
|
||||
[[ ${t%x} =~ $r1 ]] || echo "$f"
|
||||
done`
|
||||
|
4
.github/workflows/build-on-pull-request.yml
vendored
4
.github/workflows/build-on-pull-request.yml
vendored
@ -35,7 +35,7 @@ jobs:
|
||||
run: make -j2 lib QUIET=1
|
||||
- name: Run the regression tests.
|
||||
shell: bash
|
||||
run: make test QUIET=1
|
||||
run: make -j2 test QUIET=1
|
||||
- name: Test that the samples can be built.
|
||||
run: make -C samples platforms
|
||||
- name: Test that the targettest programs can be built.
|
||||
@ -89,4 +89,4 @@ jobs:
|
||||
|
||||
- name: Run the regression tests (make test)
|
||||
shell: cmd
|
||||
run: make test QUIET=1 SHELL=cmd
|
||||
run: make -j2 test QUIET=1 SHELL=cmd
|
||||
|
@ -59,7 +59,7 @@ jobs:
|
||||
run: make -j2 lib QUIET=1
|
||||
- name: Run the regression tests.
|
||||
shell: bash
|
||||
run: make test QUIET=1
|
||||
run: make -j2 test QUIET=1
|
||||
- name: Test that the samples can be built.
|
||||
shell: bash
|
||||
run: make -j2 samples
|
||||
|
2
.github/workflows/windows-test-scheduled.yml
vendored
2
.github/workflows/windows-test-scheduled.yml
vendored
@ -70,7 +70,7 @@ jobs:
|
||||
- name: Run the regression tests (make test)
|
||||
if: steps.check-sha.outputs.cache-hit != 'true'
|
||||
shell: cmd
|
||||
run: make test QUIET=1 SHELL=cmd
|
||||
run: make -j2 test QUIET=1 SHELL=cmd
|
||||
|
||||
- name: Test that the samples can be built (make samples)
|
||||
if: steps.check-sha.outputs.cache-hit != 'true'
|
||||
|
468
Contributing.md
468
Contributing.md
@ -1,188 +1,321 @@
|
||||
This document contains all kinds of information that you should know if you want to contribute to the cc65 project. Before you start, please read all of it. If something is not clear to you, please ask - this document is an ongoing effort and may well be incomplete.
|
||||
Contributing to cc65
|
||||
====================
|
||||
|
||||
Also, before you put a lot of work into implementing something you want to contribute, please get in touch with one of the developers and ask if what you are going to do is actually wanted and has a chance of being merged. Perhaps someone else is already working on it, or perhaps what you have in mind is not how we'd expect it to be - talking to us before you start might save you a lot of work in those cases.
|
||||
This document contains all kinds of information that you
|
||||
should know if you want to contribute to the cc65 project.
|
||||
Before you start, please read all of it. If something is not
|
||||
clear to you, please ask - this document is an ongoing effort
|
||||
and may well be incomplete.
|
||||
|
||||
(''Note:'' The word "must" indicates a requirement. The word "should" indicates a recomendation.)
|
||||
Also, before you put a lot of work into implementing
|
||||
something you want to contribute, please get in touch with
|
||||
one of the developers and ask if what you are going to do is
|
||||
actually wanted and has a chance of being merged. Perhaps
|
||||
someone else is already working on it, or perhaps what you
|
||||
have in mind is not how we'd expect it to be - talking to us
|
||||
before you start might save you a lot of work in those cases.
|
||||
|
||||
*this is work in progress and is constantly updated - if in doubt, please ask*
|
||||
(''Note:'' The word "must" indicates a requirement. The word
|
||||
"should" indicates a recomendation.)
|
||||
|
||||
# generally
|
||||
*this is work in progress and is constantly updated - if in
|
||||
doubt, please ask*
|
||||
|
||||
* You must obey these rules when contributing new code or documentation to cc65. We are well aware that not all existing code may respect all rules outlined here - but this is no reason for you not to respect them.
|
||||
* One commit/patch/PR per issue. Do not mix several things unless they are very closely related.
|
||||
* Sometimes when you make a PR, it may break completely unrelated tests. However, any PR is expected to merge cleanly with no failures. That means in practise that you are expected to fix/update the failing tests if required - for example this might be needed if you make changes to the compiler that changes the format of error- or warning messages. In that case you might have to update some reference files in the testbench. Obviously still check if that is actually the right thing to do ;)
|
||||
# Generally
|
||||
|
||||
* You must obey these rules when contributing new code or
|
||||
documentation to cc65. We are well aware that not all
|
||||
existing code may respect all rules outlined here - but this
|
||||
is no reason for you not to respect them.
|
||||
* One commit/patch/PR per issue. Do not mix several things
|
||||
unless they are very closely related.
|
||||
* Sometimes when you make a PR, it may break completely
|
||||
unrelated tests. However, any PR is expected to merge
|
||||
cleanly with no failures. That means in practise that you
|
||||
are expected to fix/update the failing tests if required -
|
||||
for example this might be needed if you make changes to the
|
||||
compiler that changes the format of error- or warning
|
||||
messages. In that case you might have to update some
|
||||
reference files in the testbench. Obviously still check if
|
||||
that is actually the right thing to do. ;)
|
||||
|
||||
# Codestyle rules
|
||||
|
||||
## All Sources
|
||||
## All sources
|
||||
|
||||
### Line endings
|
||||
|
||||
All files must only contain Unix style 'LF' line endings. Please configure your editors accordingly.
|
||||
All files must only contain Unix style 'LF' line endings.
|
||||
Please configure your editors accordingly.
|
||||
|
||||
### TABs and spaces
|
||||
|
||||
This is an ongoing controversial topic - everyone knows that. However, the following is how we do it :)
|
||||
This is an ongoing controversial topic - everyone knows
|
||||
that. However, the following is how we do it :)
|
||||
|
||||
* TAB characters must be expanded to spaces.
|
||||
* 4 spaces per indention level (rather than 8) are preferred, especially if there are many different levels.
|
||||
* 4 spaces per indention level (rather than 8) are
|
||||
preferred, especially if there are many different levels.
|
||||
* No extra spaces at the end of lines.
|
||||
* All text files must end with new-line characters. Don't leave the last line "dangling".
|
||||
* All text files must end with new-line characters. Don't
|
||||
leave the last line "dangling".
|
||||
|
||||
The (bash) scripts used to check the above rules can be found in ```.github/check```. You can also run all checks using ```make check```.
|
||||
The (bash) scripts used to check the above rules can be
|
||||
found in ```.github/check```. You can also run all checks
|
||||
using ```make check```.
|
||||
|
||||
### Identifiers and Symbol names
|
||||
### Identifiers and symbol names
|
||||
|
||||
The C Standard defines certain identifiers and symbol names, which we can not use
|
||||
in our code. Since it is not always obvious which parts of the library code will
|
||||
actually end up in a linked program, the following applies to ALL of the library.
|
||||
The C Standard defines certain identifiers and symbol names,
|
||||
which we can not use in our code. Since it is not always
|
||||
obvious which parts of the library code will actually end up
|
||||
in a linked program, the following applies to ALL of the
|
||||
library.
|
||||
|
||||
Any non standard identifier/symbol/function that is exported from source files,
|
||||
or appears in header files:
|
||||
Any non standard identifier/symbol/function that is exported
|
||||
from source files, or appears in header files:
|
||||
|
||||
* must not be in the "_symbol" form in C, or "__symbol" form in assembly.
|
||||
* must start with (at least) two (C Code) or three (assembly code) underscores, unless the symbol appears in a non standard header file.
|
||||
* must not be in the "_symbol" form in C, or "__symbol" form
|
||||
in assembly,
|
||||
* must start with (at least) two (C Code) or three (assembly
|
||||
code) underscores, unless the symbol appears in a non
|
||||
standard header file.
|
||||
|
||||
This is likely more than the standard dictates us to do - but it is certainly
|
||||
standard compliant - and easy to remember.
|
||||
This is likely more than the standard dictates us to do -
|
||||
but it is certainly standard compliant - and easy to
|
||||
remember.
|
||||
|
||||
Also see the discussion in https://github.com/cc65/cc65/issues/1796
|
||||
Also see the discussion in
|
||||
https://github.com/cc65/cc65/issues/1796
|
||||
|
||||
### misc
|
||||
### Miscellaneous
|
||||
|
||||
* 80 characters is the desired maximum width of files. But, it isn't a "strong" rule; sometimes, you will want to type longer lines, in order to keep the parts of expressions or comments together on the same line.
|
||||
* 80 characters is the desired maximum width of files. But,
|
||||
it isn't a "strong" rule; sometimes, you will want to type
|
||||
longer lines, in order to keep the parts of expressions or
|
||||
comments together on the same line.
|
||||
* You should avoid typing non-ASCII characters.
|
||||
* If you change "normal" source code into comments, then you must add a comment about why that code is a comment.
|
||||
* When you want to create a comment from several lines of code, you should use preprocessor lines, instead of ```/* */``` or "```;```". Example:
|
||||
<pre>
|
||||
* If you change "normal" source code into comments, then you
|
||||
must add a comment about why that code is a comment.
|
||||
* When you want to create a comment from several lines of
|
||||
code, you should use preprocessor lines, instead of ```/*
|
||||
*/``` or "```;```". Example:
|
||||
|
||||
~~~C
|
||||
#if 0
|
||||
one ();
|
||||
two ();
|
||||
three = two () + one ();
|
||||
one (); two ();
|
||||
three = two () + one ();
|
||||
#endif
|
||||
</pre>
|
||||
~~~
|
||||
|
||||
* You should type upper case characters for hex values.
|
||||
* When you type zero-page addresses in hexadecimal, you should type two hex characters (after the hex prefix). When you type non-zero-page addresses in hex, you should type four hex characters.
|
||||
* When you type lists of addresses, it is a good idea to sort them in ascending numerical order. That makes it easier for readers to build mental pictures of where things are in an address space. And, it is easier to see how big the variables and buffers are. Example:
|
||||
<pre>
|
||||
* When you type zero-page addresses in hexadecimal, you
|
||||
should type two hex characters (after the hex prefix).
|
||||
When you type non-zero-page addresses in hex, you should
|
||||
type four hex characters.
|
||||
* When you type lists of addresses, it is a good idea to
|
||||
sort them in ascending numerical order. That makes it
|
||||
easier for readers to build mental pictures of where things
|
||||
are in an address space. And, it is easier to see how big
|
||||
the variables and buffers are. Example:
|
||||
|
||||
~~~asm
|
||||
xCoord := $0703
|
||||
yCoord := $0705 ; (this address implies that xCoord is 16 bits)
|
||||
cmdbuf := $0706 ; (this address implies that yCoord is 8 bits)
|
||||
cmdlen := $0786 ; (this address implies that cmdbuf is 128 bytes)
|
||||
yCoord := $0705 ; (this address implies that xCoord is 16 bits)
|
||||
cmdbuf := $0706 ; (this address implies that yCoord is 8 bits)
|
||||
cmdlen := $0786 ; (this address implies that cmdbuf is 128 bytes)
|
||||
color := $0787
|
||||
</pre>
|
||||
~~~
|
||||
|
||||
## C Sources
|
||||
## C sources
|
||||
|
||||
The following is still very incomplete - if in doubt please look at existing sourcefiles and adapt to the existing style
|
||||
The following is still very incomplete - if in doubt please
|
||||
look at existing sourcefiles and adapt to the existing style.
|
||||
|
||||
* Your files should generally obey the C89 standard, with a few C99 things (this is a bit similar to what cc65 itself supports). The exceptions are:
|
||||
* use stdint.h for variables that require a certain bit size
|
||||
* In printf-style functions use the PRIX64 (and similar) macros to deal with 64bit values (from inttypes.h)
|
||||
This list is not necessarily complete - if in doubt, please ask.
|
||||
Your files should generally obey the C89 standard, with a
|
||||
few C99 things (this is a bit similar to what cc65 itself
|
||||
supports). The exceptions are:
|
||||
|
||||
* Use stdint.h for variables that require a certain bit size
|
||||
* In printf-style functions use the PRIX64 (and similar)
|
||||
macros to deal with 64bit values (from inttypes.h) This
|
||||
list is not necessarily complete - if in doubt, please ask.
|
||||
* We generally have a "no warnings" policy
|
||||
* Warnings must not be hidden by using typecasts - fix the code instead
|
||||
* Warnings must not be hidden by using typecasts - fix the
|
||||
code instead
|
||||
* The normal indentation width should be four spaces.
|
||||
* You must use ANSI C comments (```/* */```); you must not use C++ comments (```//```).
|
||||
* When you add functions to an existing file, you should separate them by the same number of blank lines that separate the functions that already are in that file.
|
||||
* All function declarations must be followed by a comment block that tells at least briefly what the function does, what the parameters are, and what is returned. This comment must sit between the declaration and the function body, like this:
|
||||
<pre>
|
||||
* You must use ANSI C comments (```/* */```); you must not
|
||||
use C++ comments (```//```).
|
||||
* When you add functions to an existing file, you should
|
||||
separate them by the same number of blank lines that
|
||||
separate the functions that already are in that file.
|
||||
* All function declarations must be followed by a comment
|
||||
block that tells at least briefly what the function does,
|
||||
what the parameters are, and what is returned. This comment
|
||||
must sit between the declaration and the function body, like
|
||||
this:
|
||||
|
||||
~~~C
|
||||
int foo(int bar)
|
||||
/* Add 1 to bar, takes bar and returns the result */
|
||||
{
|
||||
return bar + 1;
|
||||
}
|
||||
</pre>
|
||||
* When a function's argument list wraps around to a next line, you should indent that next line by either the normal width or enough spaces to align it with the arguments on the previous line.
|
||||
* All declarations in a block must be at the beginning of that block.
|
||||
* You should put a blank line between a list of local variable declarations and the first line of code.
|
||||
* Always use curly braces even for single statements after ```if```, and the single statement should go into a new line.
|
||||
* Use "cuddling" braces, ie the opening brace goes in the same line as the ```if```:
|
||||
<pre>
|
||||
~~~
|
||||
|
||||
* When a function's argument list wraps around to a next
|
||||
line, you should indent that next line by either the
|
||||
normal width or enough spaces to align it with the arguments
|
||||
on the previous line.
|
||||
* All declarations in a block must be at the beginning of
|
||||
that block.
|
||||
* You should put a blank line between a list of local
|
||||
variable declarations and the first line of code.
|
||||
* Always use curly braces even for single statements after
|
||||
```if```, and the single statement should go into a new
|
||||
line.
|
||||
* Use "cuddling" braces, ie the opening brace goes in the
|
||||
same line as the ```if```:
|
||||
|
||||
~~~C
|
||||
if (foo > 42) {
|
||||
bar = 23;
|
||||
}
|
||||
</pre>
|
||||
* Should the ```if``` statement be followed by an empty conditional block, there should be a comment telling why this is the case
|
||||
<pre>
|
||||
if (check()) {
|
||||
/* nothing happened, do nothing */
|
||||
}
|
||||
</pre>
|
||||
* You must separate function names and parameter/argument lists by one space.
|
||||
* When declaring/defining pointers, you must put the asterisk (```*```) next to the data type, with a space between it and the variable's name. Examples:
|
||||
<pre>
|
||||
int* namedPtr[5];
|
||||
char* nextLine (FILE* f);
|
||||
</pre>
|
||||
~~~
|
||||
|
||||
* Should the ```if``` statement be followed by an empty
|
||||
conditional block, there should be a comment telling why
|
||||
this is the case:
|
||||
|
||||
~~~C
|
||||
if (check()) { /* nothing happened, do nothing */ }
|
||||
~~~
|
||||
|
||||
* You must separate function names and parameter/argument
|
||||
lists by one space.
|
||||
* When declaring/defining pointers, you must put the
|
||||
asterisk (```*```) next to the data type, with a space
|
||||
between it and the variable's name. Examples:
|
||||
|
||||
~~~C
|
||||
int* namedPtr[5];
|
||||
char* nextLine (FILE* f);
|
||||
~~~
|
||||
|
||||
### Header files
|
||||
|
||||
Headers that belong to the standard library (libc) must conform with the C standard. That means:
|
||||
* all non standard functions, or functions that only exist in a certain standard, should be in #ifdefs
|
||||
* the same is true for macros or typedefs
|
||||
<pre>
|
||||
#if __CC65_STD__ == __CC65_STD_C99__
|
||||
/* stuff that only exists in C99 here */
|
||||
#endif
|
||||
#if __CC65_STD__ == __CC65_STD_CC65__
|
||||
/* non standard stuff here */
|
||||
#endif
|
||||
</pre>
|
||||
You can refer to Annex B of the ISO C99 standard ([here](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf) is the draft).
|
||||
* All Headers should start with a copyright/license banner
|
||||
* Function prototypes must be a single line, not contain the redundant
|
||||
"extern" keyword, and followed by a brief comment that explains what
|
||||
the function does, and separated from the next prototype by a blank
|
||||
line:
|
||||
|
||||
## Assembly Sources
|
||||
~~~C
|
||||
void __fastcall__ cclear (unsigned char length);
|
||||
/* Clear part of a line (write length spaces). */
|
||||
|
||||
* Op-code mnemonics must have lower-case letters. The names of instruction macroes may have upper-case letters.
|
||||
* Op-codes must use their official and commonly used mnemonics, ie bcc and bcs and not bgt and blt
|
||||
* Hexadecimal number constants should be used except where decimal or binary numbers make much more sense in that constant's context.
|
||||
~~~
|
||||
|
||||
Headers that belong to the standard library (libc) must
|
||||
conform with the C standard. That means:
|
||||
|
||||
* All non standard functions, or functions that only exist
|
||||
in a certain standard, should be in #ifdefs
|
||||
* The same is true for macros or typedefs.
|
||||
You can refer to Annex B of the ISO C99 standard
|
||||
([here](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf)
|
||||
is the draft). Example:
|
||||
|
||||
~~~C
|
||||
#if __CC65_STD__ == __CC65_STD_C99__ /* stuff that only exists in C99 here */
|
||||
#endif
|
||||
#if __CC65_STD__ == __CC65_STD_CC65__ /* non standard stuff here */
|
||||
#endif </pre>
|
||||
~~~
|
||||
|
||||
## Assembly sources
|
||||
|
||||
* Opcode mnemonics must have lower-case letters. The names
|
||||
of instruction macroes may have upper-case letters.
|
||||
* Opcodes must use their official and commonly used
|
||||
mnemonics, ie 'bcc' and 'bcs' and not 'bgt' and 'blt'.
|
||||
* Hexadecimal number constants should be used except where
|
||||
decimal or binary numbers make much more sense in that
|
||||
constant's context.
|
||||
* Hexadecimal letters should be upper-case.
|
||||
* When you set two registers or two memory locations to an immediate 16-bit zero, you should use the expressions ```#<$0000``` and ```#>$0000``` (they make it obvious where you are putting the lower and upper bytes).
|
||||
* If a function is declared to return a char-sized value, it actually must return an integer-sized value. (When cc65 promotes a returned value, it sometimes assumes that the value already is an integer.) This must be done in one of the following ways:
|
||||
<pre>
|
||||
* When you set two registers or two memory locations to an
|
||||
immediate 16-bit zero, you should use the expressions
|
||||
```#<$0000``` and ```#>$0000``` (they make it obvious where
|
||||
you are putting the lower and upper bytes).
|
||||
* If a function is declared to return a char-sized value, it
|
||||
actually must return an integer-sized value. (When cc65
|
||||
promotes a returned value, it sometimes assumes that the value
|
||||
already is an integer.)
|
||||
This must be done in one of the following ways:
|
||||
|
||||
~~~asm
|
||||
lda #RETURN_VALUE
|
||||
ldx #0 ; Promote char return value
|
||||
</pre>
|
||||
or, if the value is 0, you can use:
|
||||
<pre>
|
||||
|
||||
; If the value is 0, you can use:
|
||||
lda #RETURN_VALUE
|
||||
.assert RETURN_VALUE = 0
|
||||
tax
|
||||
</pre>
|
||||
sometimes jumping to return0 could save a byte:
|
||||
<pre>
|
||||
|
||||
; Sometimes jumping to 'return 0' could save a byte:
|
||||
.assert RETURN_VALUE = 0
|
||||
jmp return 0
|
||||
</pre>
|
||||
* Functions, that are intended for a platform's system library, should be optimized as much as possible.
|
||||
* Sometimes, there must be a trade-off between size and speed. If you think that a library function won't be used often, then you should make it small. Otherwise, you should make it fast.
|
||||
* Comments that are put on the right side of instructions must be aligned (start in the same character columns).
|
||||
* Assembly source fields (label, operation, operand, comment) should start ''after'' character columns that are multiples of eight (such as 1, 9, 17, 33, and 41).
|
||||
~~~
|
||||
|
||||
* Functions, that are intended for a platform's system
|
||||
library, should be optimized as much as possible.
|
||||
* Sometimes, there must be a trade-off between size and
|
||||
speed. If you think that a library function won't be used
|
||||
often, then you should make it small. Otherwise, you should
|
||||
make it fast.
|
||||
* Comments that are put on the right side of instructions
|
||||
must be aligned (start in the same character columns).
|
||||
* Assembly source fields (label, operation, operand,
|
||||
comment) should start ''after'' character columns that are
|
||||
multiples of eight (such as 1, 9, 17, 33, and 41).
|
||||
|
||||
## LinuxDoc Sources
|
||||
## LinuxDoc sources
|
||||
|
||||
* TAB characters must be expanded to spaces.
|
||||
* All text files must end with new-line characters. Don't leave the last line "dangling".
|
||||
* All text files must end with new-line characters. Don't
|
||||
leave the last line "dangling".
|
||||
* 80 characters is the desired maximum width of files.
|
||||
* You should avoid typing non-ASCII characters.
|
||||
|
||||
* You should put blank lines between LinuxDoc sections:
|
||||
* Three blank lines between ```<sect>``` sections.
|
||||
* Two blank lines between ```<sect1>``` sections.
|
||||
* One blank line between other sections.
|
||||
* Three blank lines between ```<sect>``` sections.
|
||||
* Two blank lines between ```<sect1>``` sections.
|
||||
* One blank line between other sections.
|
||||
|
||||
# Library implementation rules
|
||||
|
||||
* By default the toolchain must output a "standard" binary for the platform, no emulator formats, no extra headers used by tools. If the resulting binaries can not be run as is on emulators or eg flash cartridges, the process of converting them to something that can be used with these should be documented in the user manual.
|
||||
* Generally every function should live in a seperate source file - unless the functions are so closely related that splitting makes no sense.
|
||||
* Source files should not contain commented out code - if they do, there should be a comment that explains why that commented out code exists.
|
||||
* By default the toolchain must output a "standard" binary
|
||||
for the platform, no emulator formats, no extra headers
|
||||
used by tools. If the resulting binaries can not be run as
|
||||
is on emulators or eg flash cartridges, the process of
|
||||
converting them to something that can be used with these
|
||||
should be documented in the user manual.
|
||||
* Generally every function should live in a seperate source
|
||||
file - unless the functions are so closely related that
|
||||
splitting makes no sense.
|
||||
* Source files should not contain commented out code - if
|
||||
they do, there should be a comment that explains why that
|
||||
commented out code exists.
|
||||
|
||||
# Makefile rules
|
||||
|
||||
* Makefiles must generally work on both *nix (ba)sh and windows cmd.exe.
|
||||
* Makefiles must not use external tools that are not provided by the cc65 toolchain itself.
|
||||
* Makefiles must generally work on both *nix (ba)sh and
|
||||
windows cmd.exe.
|
||||
* Makefiles must not use external tools that are not
|
||||
provided by the cc65 toolchain itself.
|
||||
|
||||
The only exception to the above are actions that are exclusive to the github actions - those may rely on bash and/or linux tools.
|
||||
The only exception to the above are actions that are exclusive
|
||||
to the github actions - those may rely on bash and/or linux tools.
|
||||
|
||||
# Documentation rules
|
||||
|
||||
@ -192,107 +325,42 @@ The only exception to the above are actions that are exclusive to the github act
|
||||
|
||||
## Wiki
|
||||
|
||||
* The Wiki is strictly for additional information that does not fit into the regular user manual (LinuxDoc). The wiki must not duplicate any information that is present in the user manual
|
||||
* The Wiki is strictly for additional information that does
|
||||
not fit into the regular user manual (LinuxDoc). The wiki
|
||||
must not duplicate any information that is present in the
|
||||
user manual.
|
||||
|
||||
# Roadmap / TODOs / open Ends
|
||||
# Roadmap / TODOs / open ends
|
||||
|
||||
## Documentation
|
||||
|
||||
* the printf family of function does not completely implement all printf modifiers and does not behave as expected in some cases - all this should be documented in detail
|
||||
* The printf() family of functions does not completely
|
||||
implement all printf() modifiers and does not behave as
|
||||
expected in some cases - all this should be documented in
|
||||
detail.
|
||||
|
||||
## Compiler
|
||||
|
||||
* We need a way that makes it possible to feed arbitrary assembler code into the optimzer, so we can have proper tests for it
|
||||
* We need a way that makes it possible to feed arbitrary
|
||||
assembler code into the optimzer, so we can have proper
|
||||
tests for it.
|
||||
|
||||
### Floating point support
|
||||
|
||||
The first step is implementing the datatype "float" as IEEE 754 floats. Help welcomed!
|
||||
The first step is implementing the datatype "float" as IEEE
|
||||
754 floats. Help welcomed!
|
||||
|
||||
* WIP compiler/library changes are here: https://github.com/cc65/cc65/pull/1777
|
||||
* WIP compiler/library changes are here:
|
||||
https://github.com/cc65/cc65/pull/1777
|
||||
|
||||
## Library
|
||||
|
||||
### name clashes in the library
|
||||
|
||||
see "Identifiers and Symbol names" above - not all identifiers have been checked
|
||||
and renamed yet. The following is a list of those that still might need to be
|
||||
fixed:
|
||||
|
||||
```
|
||||
common
|
||||
|
||||
__argc libsrc/runtime/callmain.s libsrc/cbm610/mainargs.s libsrc/cx16/mainargs.s libsrc/plus4/mainargs.s libsrc/lynx/mainargs.s libsrc/c16/mainargs.s libsrc/geos-common/system/mainargs.s libsrc/sim6502/mainargs.s libsrc/c128/mainargs.s libsrc/vic20/mainargs.s libsrc/nes/mainargs.s libsrc/atari/getargs.s libsrc/apple2/mainargs.s libsrc/cbm510/mainargs.s libsrc/telestrat/mainargs.s libsrc/c64/mainargs.s libsrc/pet/mainargs.s libsrc/atmos/mainargs.s
|
||||
__argv libsrc/runtime/callmain.s libsrc/cbm610/mainargs.s libsrc/cx16/mainargs.s libsrc/plus4/mainargs.s libsrc/lynx/mainargs.s libsrc/c16/mainargs.s libsrc/geos-common/system/mainargs.s libsrc/sim6502/mainargs.s libsrc/c128/mainargs.s libsrc/vic20/mainargs.s libsrc/nes/mainargs.s libsrc/atari/getargs.s libsrc/apple2/mainargs.s libsrc/cbm510/mainargs.s libsrc/telestrat/mainargs.s libsrc/c64/mainargs.s libsrc/pet/mainargs.s libsrc/atmos/mainargs.s
|
||||
__cos libsrc/common/sincos.s
|
||||
__ctypeidx libsrc/common/ctype.s libsrc/common/ctypemask.s libsrc/geos-common/system/ctype.s libsrc/atari/ctype.s libsrc/cbm/ctype.s libsrc/atmos/ctype.s asminc/ctype_common.inc
|
||||
__cwd libsrc/common/getcwd.s libsrc/common/_cwd.s libsrc/atari/initcwd.s libsrc/apple2/initcwd.s libsrc/apple2/initcwd.s libsrc/telestrat/initcwd.s libsrc/cbm/initcwd.s
|
||||
__cwd_buf_size libsrc/common/_cwd.s
|
||||
__envcount libsrc/common/searchenv.s libsrc/common/_environ.s libsrc/common/putenv.s libsrc/common/getenv.s
|
||||
__environ libsrc/common/searchenv.s libsrc/common/_environ.s libsrc/common/putenv.s libsrc/common/getenv.s
|
||||
__envsize libsrc/common/_environ.s libsrc/common/putenv.s
|
||||
__fdesc libsrc/common/_fdesc.s libsrc/common/fopen.s
|
||||
__filetab libsrc/common/_fdesc.s libsrc/common/_file.s asminc/_file.inc
|
||||
__fopen libsrc/common/fopen.s libsrc/common/_fopen.s
|
||||
__printf libsrc/common/vsnprintf.s libsrc/common/_printf.s libsrc/common/vfprintf.s libsrc/conio/vcprintf.s libsrc/pce/_printf.s
|
||||
__scanf libsrc/common/_scanf.inc libsrc/common/vsscanf.s libsrc/conio/vcscanf.s
|
||||
__sin libsrc/common/sincos.s
|
||||
__sys libsrc/common/_sys.s libsrc/apple2/_sys.s
|
||||
__sys_oserrlist libsrc/common/stroserr.s libsrc/geos-common/system/oserrlist.s libsrc/atari/oserrlist.s libsrc/apple2/oserrlist.s libsrc/cbm/oserrlist.s libsrc/atmos/oserrlist.s
|
||||
__syschdir libsrc/common/chdir.s libsrc/atari/syschdir.s libsrc/apple2/syschdir.s libsrc/telestrat/syschdir.s libsrc/cbm/syschdir.s
|
||||
__sysmkdir libsrc/common/mkdir.s libsrc/atari/sysmkdir.s libsrc/apple2/sysmkdir.s libsrc/telestrat/sysmkdir.s
|
||||
__sysremove libsrc/common/remove.s libsrc/geos-common/file/sysremove.s libsrc/atari/sysremove.s libsrc/atari/sysrmdir.s libsrc/apple2/sysremove.s libsrc/apple2/sysrmdir.s libsrc/telestrat/sysremove.s libsrc/cbm/sysremove.s
|
||||
__sysrename libsrc/common/rename.s libsrc/geos-common/file/sysrename.s libsrc/atari/sysrename.s libsrc/apple2/sysrename.s libsrc/cbm/sysrename.s
|
||||
__sysrmdir libsrc/common/rmdir.s libsrc/atari/sysrmdir.s libsrc/apple2/sysrmdir.s
|
||||
__sysuname libsrc/common/uname.s libsrc/cbm610/sysuname.s libsrc/cx16/sysuname.s libsrc/plus4/sysuname.s libsrc/lynx/sysuname.s libsrc/c16/sysuname.s libsrc/geos-common/system/sysuname.s libsrc/c128/sysuname.s libsrc/creativision/sysuname.s libsrc/vic20/sysuname.s libsrc/nes/sysuname.s libsrc/atari/sysuname.s libsrc/apple2/sysuname.s libsrc/cbm510/sysuname.s libsrc/telestrat/sysuname.s libsrc/c64/sysuname.s libsrc/pet/sysuname.s libsrc/atari5200/sysuname.s libsrc/atmos/sysuname.s
|
||||
|
||||
apple2
|
||||
|
||||
__auxtype libsrc/apple2/open.s
|
||||
__datetime libsrc/apple2/open.s
|
||||
__dos_type libsrc/apple2/dioopen.s libsrc/apple2/curdevice.s libsrc/apple2/mainargs.s libsrc/apple2/settime.s libsrc/apple2/getdevice.s libsrc/apple2/dosdetect.s libsrc/apple2/irq.s libsrc/apple2/open.s libsrc/apple2/mli.s libsrc/apple2/getres.s
|
||||
__filetype libsrc/apple2/open.s libsrc/apple2/exehdr.s
|
||||
|
||||
|
||||
atari
|
||||
|
||||
__defdev libsrc/atari/posixdirent.s libsrc/atari/ucase_fn.s libsrc/atari/getdefdev.s
|
||||
__dos_type libsrc/atari/getargs.s libsrc/atari/exec.s libsrc/atari/settime.s libsrc/atari/syschdir.s libsrc/atari/dosdetect.s libsrc/atari/is_cmdline_dos.s libsrc/atari/sysrmdir.s libsrc/atari/gettime.s libsrc/atari/lseek.s libsrc/atari/getres.s libsrc/atari/getdefdev.s
|
||||
__do_oserror libsrc/atari/posixdirent.s libsrc/atari/do_oserr.s libsrc/atari/serref.s libsrc/atari/read.s libsrc/atari/write.s libsrc/atari/close.s
|
||||
__getcolor libsrc/atari/setcolor.s
|
||||
__getdefdev libsrc/atari/getdefdev.s
|
||||
__graphics libsrc/atari/graphics.s
|
||||
__inviocb libsrc/atari/serref.s libsrc/atari/ser/atrrdev.s libsrc/atari/inviocb.s libsrc/atari/read.s libsrc/atari/write.s libsrc/atari/lseek.s libsrc/atari/close.s
|
||||
__is_cmdline_dos libsrc/atari/is_cmdline_dos.s libsrc/atari/doesclrscr.s
|
||||
__rest_vecs libsrc/atari/savevec.s
|
||||
__rwsetup libsrc/atari/rwcommon.s libsrc/atari/read.s libsrc/atari/write.s
|
||||
__save_vecs libsrc/atari/savevec.s
|
||||
__scroll libsrc/atari/scroll.s
|
||||
__setcolor libsrc/atari/setcolor.s
|
||||
__setcolor_low libsrc/atari/setcolor.s
|
||||
__sio_call libsrc/atari/diowritev.s libsrc/atari/diopncls.s libsrc/atari/siocall.s libsrc/atari/diowrite.s libsrc/atari/dioread.s
|
||||
|
||||
|
||||
cbm
|
||||
|
||||
__cbm_filetype libsrc/cbm/cbm_filetype.s asminc/cbm_filetype.in
|
||||
__dirread libsrc/cbm/dir.inc libsrc/cbm/dir.s
|
||||
__dirread1 libsrc/cbm/dir.inc libsrc/cbm/dir.s
|
||||
|
||||
|
||||
lynx
|
||||
|
||||
__iodat libsrc/lynx/lynx-cart.s libsrc/lynx/bootldr.s libsrc/lynx/extzp.s libsrc/lynx/crt0.s libsrc/lynx/extzp.inc
|
||||
__iodir libsrc/lynx/extzp.s libsrc/lynx/crt0.s libsrc/lynx/extzp.inc
|
||||
__sprsys libsrc/lynx/tgi/lynx-160-102-16.s libsrc/lynx/extzp.s libsrc/lynx/crt0.s libsrc/lynx/extzp.inc
|
||||
__viddma libsrc/lynx/tgi/lynx-160-102-16.s libsrc/lynx/extzp.s libsrc/lynx/crt0.s libsrc/lynx/extzp.inc
|
||||
|
||||
|
||||
pce
|
||||
|
||||
__nmi libsrc/pce/irq.s libsrc/pce/crt0.s
|
||||
```
|
||||
Some name clashes need to be resolved. Please see the
|
||||
[detailed list of name clashes](libsrc/NameClashes.md).
|
||||
|
||||
## Test suite
|
||||
|
||||
* specific tests to check the optimizer (rather than the codegenerator) are needed.
|
||||
* we need more specific tests to check standard conformance of the library headers
|
||||
* Specific tests to check the optimizer (rather than the code
|
||||
generator) are needed.
|
||||
* We need more specific tests to check standard conformance
|
||||
of the library headers.
|
||||
|
88
README.md
88
README.md
@ -1,21 +1,62 @@
|
||||
# About cc65
|
||||
The cc65 cross-compiler suite
|
||||
=============================
|
||||
|
||||
cc65 is a complete cross development package for 65(C)02 systems, including
|
||||
a powerful macro assembler, a C compiler, linker, archiver and several
|
||||
other tools. cc65 has C and runtime library support for many of the old 6502 machines.
|
||||
For details look at the [Website](https://cc65.github.io).
|
||||
cc65 is a complete cross-development package for 65(C)02 systems,
|
||||
including a powerful macro assembler, a C compiler, linker, archiver,
|
||||
simulator and several other tools. cc65 has C and runtime library
|
||||
support for many of the old 6502 machines. For details look at
|
||||
the [cc65 web site](https://cc65.github.io):
|
||||
|
||||
| Company / People | Machine / Environment |
|
||||
|-------------------------|-------------------------------------|
|
||||
| Apple | Apple II |
|
||||
| | Apple IIe enhanced |
|
||||
| Atari | Atari 400/800 |
|
||||
| | Atari 2600 |
|
||||
| | Atari 5200 |
|
||||
| | Atari 7800 |
|
||||
| | Atari XL |
|
||||
| | Lynx |
|
||||
| Tangerine | Oric Atmos |
|
||||
| Eureka | Oric Telestrat |
|
||||
| Acorn | BBC series |
|
||||
| Commodore | C128 |
|
||||
| | C16 |
|
||||
| | C64 |
|
||||
| | CBM 510/610 |
|
||||
| | PET |
|
||||
| | Plus/4 |
|
||||
| | VIC-20 |
|
||||
| VTech | CreatiVision |
|
||||
| Commander X16 Community | Commander X16 |
|
||||
| Bit Corporation | Gamate |
|
||||
| Berkeley Softworks | GEOS (Apple/CBM) |
|
||||
| LUnix Team | LUnix (C64) |
|
||||
| Nintendo | Nintendo Entertainment System (NES) |
|
||||
| Ohio Scientific | OSI C1P |
|
||||
| MOS Technology, Inc. | KIM-1 |
|
||||
| NEC | PC Engine (PCE) |
|
||||
| Dr. Jozo Dujmović | Picocomputer (RP6502) |
|
||||
| Watara | Watura/QuickShot Supervision |
|
||||
| Synertek | SYM-1 |
|
||||
|
||||
A generic configuration to adapt cc65 to new targets is also around.
|
||||
|
||||
## People
|
||||
|
||||
Project founders:
|
||||
cc65 is originally based on the "Small C" compiler by Ron Cain and
|
||||
enhanced by James E. Hendrix.
|
||||
|
||||
* John R. Dunning: [original implementation](https://public.websites.umich.edu/~archive/atari/8bit/Languages/Cc65/) of the C compiler and runtime library, Atari hosted
|
||||
### Project founders
|
||||
|
||||
* John R. Dunning: [original implementation](https://public.websites.umich.edu/~archive/atari/8bit/Languages/Cc65/)
|
||||
of the C compiler and runtime library, Atari hosted.
|
||||
* Ullrich von Bassewitz:
|
||||
* move the code to modern systems
|
||||
* rewrite most parts of the compiler
|
||||
* complete rewrite of the runtime library
|
||||
* moved Dunning's code to modern systems,
|
||||
* rewrote most parts of the compiler,
|
||||
* rewrote all of the runtime library.
|
||||
|
||||
Core team members:
|
||||
### Core team members
|
||||
|
||||
* [Christian Groessler](https://github.com/groessler): Atari, Atari5200, and CreatiVision library Maintainer
|
||||
* [dqh](https://github.com/dqh-au): GHA help
|
||||
@ -23,7 +64,7 @@ Core team members:
|
||||
* [groepaz](https://github.com/mrdudz): CBM library, Project Maintainer
|
||||
* [Oliver Schmidt](https://github.com/oliverschmidt): Apple II library Maintainer
|
||||
|
||||
External contributors:
|
||||
### External contributors
|
||||
|
||||
* [acqn](https://github.com/acqn): various compiler fixes
|
||||
* [jedeoric](https://github.com/jedeoric): Telestrat target
|
||||
@ -36,28 +77,31 @@ External contributors:
|
||||
|
||||
*(The above list is incomplete, if you feel left out - please speak up or add yourself in a PR)*
|
||||
|
||||
For a complete list look at the [full team list](https://github.com/orgs/cc65/teams) or the list of [all contributors](https://github.com/cc65/cc65/graphs/contributors)
|
||||
For a complete list look at the [full team list](https://github.com/orgs/cc65/teams)
|
||||
or the list of [all contributors](https://github.com/cc65/cc65/graphs/contributors).
|
||||
|
||||
# Contact
|
||||
|
||||
For general discussion, questions, etc subscribe to the [mailing list](https://cc65.github.io/mailing-lists.html) or use the [github discussions](https://github.com/cc65/cc65/discussions).
|
||||
For general discussion, questions, etc subscribe to the
|
||||
[mailing list](https://cc65.github.io/mailing-lists.html)
|
||||
or use the [github discussions](https://github.com/cc65/cc65/discussions).
|
||||
|
||||
Some of us may also be around on IRC [#cc65](https://web.libera.chat/#cc65) on libera.chat
|
||||
Some of us may also be around on IRC [#cc65](https://web.libera.chat/#cc65) on libera.chat.
|
||||
|
||||
# Documentation
|
||||
|
||||
* The main [Documentation](https://cc65.github.io/doc) for users and developers
|
||||
|
||||
* Info on [Contributing](Contributing.md) to the CC65 project. Please read this before working on something you want to contribute, and before reporting bugs.
|
||||
|
||||
* The [Wiki](https://github.com/cc65/wiki/wiki) contains some extra info that does not fit into the regular documentation.
|
||||
* The main [Documentation](https://cc65.github.io/doc) for users and
|
||||
developers.
|
||||
* Info on [Contributing](Contributing.md) to the CC65 project. Please
|
||||
read this before working on something you want to contribute, and
|
||||
before reporting bugs.
|
||||
* The [Wiki](https://github.com/cc65/wiki/wiki) contains some extra info
|
||||
that does not fit into the regular documentation.
|
||||
|
||||
# Downloads
|
||||
|
||||
* [Windows 64bit Snapshot](https://sourceforge.net/projects/cc65/files/cc65-snapshot-win64.zip)
|
||||
|
||||
* [Windows 32bit Snapshot](https://sourceforge.net/projects/cc65/files/cc65-snapshot-win32.zip)
|
||||
|
||||
* [Linux Snapshot DEB and RPM](https://software.opensuse.org/download.html?project=home%3Astrik&package=cc65)
|
||||
|
||||
[](https://github.com/cc65/cc65/actions/workflows/snapshot-on-push-master.yml)
|
||||
|
@ -15,7 +15,7 @@ CPU_ISET_4510 = $0400
|
||||
CPU_NONE = CPU_ISET_NONE
|
||||
CPU_6502 = CPU_ISET_6502
|
||||
CPU_6502X = CPU_ISET_6502|CPU_ISET_6502X
|
||||
CPU_6502DTV = CPU_ISET_6502|CPU_ISET_6502X|CPU_ISET_6502DTV
|
||||
CPU_6502DTV = CPU_ISET_6502|CPU_ISET_6502DTV
|
||||
CPU_65SC02 = CPU_ISET_6502|CPU_ISET_65SC02
|
||||
CPU_65C02 = CPU_ISET_6502|CPU_ISET_65SC02|CPU_ISET_65C02
|
||||
CPU_65816 = CPU_ISET_6502|CPU_ISET_65SC02|CPU_ISET_65816
|
||||
|
@ -66,3 +66,9 @@
|
||||
.global _clock_settime
|
||||
.global _localtime
|
||||
.global _mktime
|
||||
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; Constants
|
||||
|
||||
CLOCK_REALTIME = 0
|
||||
|
20
cfg/c16-asm.cfg
Normal file
20
cfg/c16-asm.cfg
Normal file
@ -0,0 +1,20 @@
|
||||
FEATURES {
|
||||
STARTADDRESS: default = $1001;
|
||||
}
|
||||
SYMBOLS {
|
||||
__LOADADDR__: type = import;
|
||||
}
|
||||
MEMORY {
|
||||
ZP: file = "", start = $0002, size = $001A;
|
||||
LOADADDR: file = %O, start = %S - 2, size = $0002;
|
||||
MAIN: file = %O, start = %S, size = $3000 - %S;
|
||||
}
|
||||
SEGMENTS {
|
||||
ZEROPAGE: load = ZP, type = zp, optional = yes;
|
||||
LOADADDR: load = LOADADDR, type = ro;
|
||||
EXEHDR: load = MAIN, type = ro, optional = yes;
|
||||
CODE: load = MAIN, type = ro;
|
||||
RODATA: load = MAIN, type = ro, optional = yes;
|
||||
DATA: load = MAIN, type = rw, optional = yes;
|
||||
BSS: load = MAIN, type = bss, define = yes;
|
||||
}
|
20
cfg/plus4-asm.cfg
Normal file
20
cfg/plus4-asm.cfg
Normal file
@ -0,0 +1,20 @@
|
||||
FEATURES {
|
||||
STARTADDRESS: default = $1001;
|
||||
}
|
||||
SYMBOLS {
|
||||
__LOADADDR__: type = import;
|
||||
}
|
||||
MEMORY {
|
||||
ZP: file = "", start = $0002, size = $001A;
|
||||
LOADADDR: file = %O, start = %S - 2, size = $0002;
|
||||
MAIN: file = %O, start = %S, size = $FD00 - %S;
|
||||
}
|
||||
SEGMENTS {
|
||||
ZEROPAGE: load = ZP, type = zp, optional = yes;
|
||||
LOADADDR: load = LOADADDR, type = ro;
|
||||
EXEHDR: load = MAIN, type = ro, optional = yes;
|
||||
CODE: load = MAIN, type = ro;
|
||||
RODATA: load = MAIN, type = ro, optional = yes;
|
||||
DATA: load = MAIN, type = rw, optional = yes;
|
||||
BSS: load = MAIN, type = bss, define = yes;
|
||||
}
|
22
cfg/vic20-asm-32k.cfg
Normal file
22
cfg/vic20-asm-32k.cfg
Normal file
@ -0,0 +1,22 @@
|
||||
# Assembly program configuration for expanded VICs (>= +8K).
|
||||
|
||||
FEATURES {
|
||||
STARTADDRESS: default = $1201;
|
||||
}
|
||||
SYMBOLS {
|
||||
__LOADADDR__: type = import;
|
||||
}
|
||||
MEMORY {
|
||||
ZP: file = "", start = $0002, size = $001A, define = yes;
|
||||
LOADADDR: file = %O, start = %S - 2, size = $0002;
|
||||
MAIN: file = %O, start = %S, size = $8000 - %S;
|
||||
}
|
||||
SEGMENTS {
|
||||
ZEROPAGE: load = ZP, type = zp, optional = yes;
|
||||
LOADADDR: load = LOADADDR, type = ro;
|
||||
EXEHDR: load = MAIN, type = ro, optional = yes;
|
||||
CODE: load = MAIN, type = ro;
|
||||
RODATA: load = MAIN, type = ro;
|
||||
DATA: load = MAIN, type = rw;
|
||||
BSS: load = MAIN, type = bss, optional = yes, define = yes;
|
||||
}
|
22
cfg/vic20-asm-3k.cfg
Normal file
22
cfg/vic20-asm-3k.cfg
Normal file
@ -0,0 +1,22 @@
|
||||
# Assembly program configuration for expanded VICs (+3K only).
|
||||
|
||||
FEATURES {
|
||||
STARTADDRESS: default = $0401;
|
||||
}
|
||||
SYMBOLS {
|
||||
__LOADADDR__: type = import;
|
||||
}
|
||||
MEMORY {
|
||||
ZP: file = "", start = $0002, size = $001A, define = yes;
|
||||
LOADADDR: file = %O, start = %S - 2, size = $0002;
|
||||
MAIN: file = %O, start = %S, size = $1E00 - %S;
|
||||
}
|
||||
SEGMENTS {
|
||||
ZEROPAGE: load = ZP, type = zp, optional = yes;
|
||||
LOADADDR: load = LOADADDR, type = ro;
|
||||
EXEHDR: load = MAIN, type = ro, optional = yes;
|
||||
CODE: load = MAIN, type = ro;
|
||||
RODATA: load = MAIN, type = ro;
|
||||
DATA: load = MAIN, type = rw;
|
||||
BSS: load = MAIN, type = bss, optional = yes, define = yes;
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
# Assembly program configuration for unexpanded VICs.
|
||||
|
||||
FEATURES {
|
||||
STARTADDRESS: default = $1001;
|
||||
}
|
||||
@ -7,11 +9,12 @@ SYMBOLS {
|
||||
MEMORY {
|
||||
ZP: file = "", start = $0002, size = $001A, define = yes;
|
||||
LOADADDR: file = %O, start = %S - 2, size = $0002;
|
||||
MAIN: file = %O, start = %S, size = $0DF3 - %S;
|
||||
MAIN: file = %O, start = %S, size = $1E00 - %S;
|
||||
}
|
||||
SEGMENTS {
|
||||
ZEROPAGE: load = ZP, type = zp, optional = yes;
|
||||
LOADADDR: load = LOADADDR, type = ro;
|
||||
EXEHDR: load = MAIN, type = ro, optional = yes;
|
||||
CODE: load = MAIN, type = ro;
|
||||
RODATA: load = MAIN, type = ro;
|
||||
DATA: load = MAIN, type = rw;
|
||||
|
@ -330,6 +330,7 @@ usage.
|
||||
<item>_dos_type
|
||||
<item>_filetype
|
||||
<item>_datetime
|
||||
<item>allow_lowercase
|
||||
<item>beep
|
||||
<item>get_ostype
|
||||
<item>gmtime_dt
|
||||
@ -452,10 +453,15 @@ The names in the parentheses denote the symbols to be used for static linking of
|
||||
(RTS/CTS) and does interrupt driven receives. Speeds faster than 9600 baud
|
||||
aren't reachable because the ROM and ProDOS IRQ handlers are too slow.
|
||||
Software flow control (XON/XOFF) is not supported.
|
||||
|
||||
Note that because of the peculiarities of the 6551 chip transmits are not
|
||||
interrupt driven, and the transceiver blocks if the receiver asserts
|
||||
flow control because of a full buffer.
|
||||
|
||||
Note that using the driver at SER_BAUD_115200 will disable IRQs. It will be up
|
||||
to the users to use the serial port, either by re-enabling IRQs themselves,
|
||||
or by directly poll-reading the ACIA DATA register without the help of ser_get().
|
||||
|
||||
The driver defaults to slot 2. Call <tt/ser_apple2_slot()/ prior to
|
||||
<tt/ser_open()/ in order to select a different slot. <tt/ser_apple2_slot()/
|
||||
succeeds for all Apple II slots, but <tt/ser_open()/ fails with
|
||||
|
@ -453,10 +453,15 @@ The names in the parentheses denote the symbols to be used for static linking of
|
||||
(RTS/CTS) and does interrupt driven receives. Speeds faster than 9600 baud
|
||||
aren't reachable because the ROM and ProDOS IRQ handlers are too slow.
|
||||
Software flow control (XON/XOFF) is not supported.
|
||||
|
||||
Note that because of the peculiarities of the 6551 chip transmits are not
|
||||
interrupt driven, and the transceiver blocks if the receiver asserts
|
||||
flow control because of a full buffer.
|
||||
|
||||
Note that using the driver at SER_BAUD_115200 will disable IRQs. It will be up
|
||||
to the users to use the serial port, either by re-enabling IRQs themselves,
|
||||
or by directly poll-reading the ACIA DATA register without the help of ser_get().
|
||||
|
||||
The driver defaults to slot 2. Call <tt/ser_apple2_slot()/ prior to
|
||||
<tt/ser_open()/ in order to select a different slot. <tt/ser_apple2_slot()/
|
||||
succeeds for all Apple II slots, but <tt/ser_open()/ fails with
|
||||
|
@ -1,15 +1,15 @@
|
||||
<!doctype linuxdoc system>
|
||||
|
||||
<article>
|
||||
<title>Oric Atmos-specific information for cc65
|
||||
<title>Tangerine Oric Atmos-specific information for cc65
|
||||
<author>
|
||||
<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:polluks@sdf.org" name="Stefan A. Haubenthal">,<newline>
|
||||
<url url="mailto:greg.king5@verizon.net" name="Greg King">
|
||||
|
||||
<abstract>
|
||||
An overview over the Atmos runtime system as it is implemented for the cc65 C
|
||||
compiler.
|
||||
An overview over the Oric Atmos runtime system as it is implemented for the cc65
|
||||
C compiler. This target is not Oric-1 compatible.
|
||||
</abstract>
|
||||
|
||||
<!-- Table of contents -->
|
||||
|
@ -829,49 +829,42 @@ names like "Loop". Here is an example:
|
||||
bne @Loop ; ERROR: Unknown identifier!
|
||||
</verb></tscreen>
|
||||
|
||||
|
||||
<sect1>Unnamed labels<p>
|
||||
|
||||
If you really want to write messy code, there are also unnamed labels. These
|
||||
labels do not have a name (you guessed that already, didn't you?). A colon is
|
||||
used to mark the absence of the name.
|
||||
If you really want to write messy code, there are also unnamed labels. To define
|
||||
an unnamed label, use either <tt>@:</tt> (<tt>.LOCALCHAR</tt> is respected if it
|
||||
is set) or sole <tt>:</tt>.
|
||||
|
||||
Unnamed labels may be accessed by using the colon plus several minus or plus
|
||||
characters as a label designator. Using the '-' characters will create a back
|
||||
reference (use the n'th label backwards), using '+' will create a forward
|
||||
reference (use the n'th label in forward direction). An example will help to
|
||||
understand this:
|
||||
To reference an unnamed label, use <tt>@</tt> (<tt>.LOCALCHAR</tt> is respected
|
||||
if it is set) or <tt>:</tt> with several <tt>-</tt> or <tt>+</tt> characters.
|
||||
The <tt>-</tt> characters will create a back reference (n'th label backwards),
|
||||
the <tt>+</tt> will create a forward reference (n'th label in forward direction).
|
||||
As an alternative, angle brackets <tt><</tt> and <tt>></tt> may be used
|
||||
instead of <tt>-</tt> and <tt>+</tt> with the same meaning.
|
||||
|
||||
Example:
|
||||
|
||||
<tscreen><verb>
|
||||
: lda (ptr1),y ; #1
|
||||
cmp (ptr2),y
|
||||
bne :+ ; -> #2
|
||||
tax
|
||||
beq :+++ ; -> #4
|
||||
iny
|
||||
bne :- ; -> #1
|
||||
inc ptr1+1
|
||||
inc ptr2+1
|
||||
bne :- ; -> #1
|
||||
|
||||
: bcs :+ ; #2 -> #3
|
||||
ldx #$FF
|
||||
rts
|
||||
|
||||
: ldx #$01 ; #3
|
||||
: rts ; #4
|
||||
cpy #0
|
||||
beq @++
|
||||
@:
|
||||
sta $2007
|
||||
dey
|
||||
bne @-
|
||||
@:
|
||||
rts
|
||||
</verb></tscreen>
|
||||
|
||||
As you can see from the example, unnamed labels will make even short
|
||||
sections of code hard to understand, because you have to count labels
|
||||
to find branch targets (this is the reason why I for my part do
|
||||
prefer the "cheap" local labels). Nevertheless, unnamed labels are
|
||||
convenient in some situations, so it's your decision.
|
||||
Unnamed labels may make even short sections of code hard to understand, because
|
||||
you have to count labels to find branch targets. It's better to prefer the
|
||||
"cheap" local labels. Nevertheless, unnamed labels are convenient in some
|
||||
situations, so it's up to your discretion.
|
||||
|
||||
<em/Note:/ <ref id="scopes" name="Scopes"> organize named symbols, not
|
||||
unnamed ones, so scopes don't have an effect on unnamed labels.
|
||||
|
||||
|
||||
|
||||
<sect1>Using macros to define labels and constants<p>
|
||||
|
||||
While there are drawbacks with this approach, it may be handy in a few rare
|
||||
|
@ -61,7 +61,7 @@ Short options:
|
||||
-Os Inline some standard functions
|
||||
-T Include source as comment
|
||||
-V Print the compiler version number
|
||||
-W warning[,...] Suppress warnings
|
||||
-W [-+]warning[,...] Control warnings ('-' disables, '+' enables)
|
||||
-d Debug mode
|
||||
-g Add debug info to object file
|
||||
-h Help (this text)
|
||||
@ -84,8 +84,9 @@ Long options:
|
||||
--create-full-dep name Create a full make dependency file
|
||||
--data-name seg Set the name of the DATA segment
|
||||
--debug Debug mode
|
||||
--debug-tables name Write symbol table debug info to a file
|
||||
--debug-info Add debug info to object file
|
||||
--debug-opt name Configure optimizations with a file
|
||||
--debug-opt name Debug optimization steps
|
||||
--debug-opt-output Debug output of each optimization step
|
||||
--dep-target target Use this dependency target
|
||||
--disable-opt name Disable an optimization step
|
||||
@ -823,6 +824,11 @@ and the one defined by the ISO standard:
|
||||
as it sounds, since the 6502 has so few registers that it isn't
|
||||
possible to keep values in registers anyway.
|
||||
<p>
|
||||
<item> In <tt/cc65/ mode, <tt/main()/ cannot be called recursively. If this
|
||||
is necessary, the program must be compiled in <tt/c89/ or <tt/c99/ mode
|
||||
using the <tt><ref id="option--standard" name="--standard"></tt>
|
||||
command line option.
|
||||
<p>
|
||||
</itemize>
|
||||
|
||||
There may be some more minor differences I'm currently not aware of. The
|
||||
@ -1273,6 +1279,12 @@ If the first parameter is <tt/push/, the old value is saved onto a stack
|
||||
before changing it. The value may later be restored by using the <tt/pop/
|
||||
parameter with the <tt/#pragma/.
|
||||
|
||||
For all pragma names that contain hyphens, the same name using underlines
|
||||
instead of the hyphens is available as an alternative. While the former
|
||||
resembles the corresponding command line option and is more orthogonal, the
|
||||
latter may be more compatible with external tools that rewrite the token
|
||||
sequences of the input.
|
||||
|
||||
|
||||
<sect1><tt>#pragma allow-eager-inline ([push,] on|off)</tt><label id="pragma-allow-eager-inline"><p>
|
||||
|
||||
|
@ -243,6 +243,12 @@ point to <tt/cx320p1.tgi (cx320p1_tgi)/.
|
||||
a way that's compatible with some of the other color drivers).
|
||||
</descrip><p>
|
||||
|
||||
<descrip>
|
||||
<tag><tt/cx640p1.tgi (cx640p1_tgi)/</tag>
|
||||
This driver features a resolution of 640 across and 480 down with 2 colors,
|
||||
black and white.
|
||||
</descrip><p>
|
||||
|
||||
|
||||
<sect1>Extended memory drivers<p>
|
||||
|
||||
|
@ -95,6 +95,7 @@ function.
|
||||
|
||||
<itemize>
|
||||
<item>_dos_type
|
||||
<item>allow_lowercase
|
||||
<item><ref id="beep" name="beep">
|
||||
<item><ref id="get_ostype" name="get_ostype">
|
||||
<item><ref id="gmtime_dt" name="gmtime_dt">
|
||||
@ -154,6 +155,7 @@ function.
|
||||
<item><ref id="atmos_tick" name="atmos_tick">
|
||||
<item><ref id="atmos_tock" name="atmos_tock">
|
||||
<item><ref id="atmos_zap" name="atmos_zap">
|
||||
<item><ref id="waitvsync" name="waitvsync">
|
||||
</itemize>
|
||||
|
||||
|
||||
@ -780,6 +782,7 @@ communication, see also <tt>testcode/lib/ser-test.c</tt>.
|
||||
<item><ref id="strqtok" name="strqtok">
|
||||
<item><ref id="strrchr" name="strrchr">
|
||||
<item><ref id="strspn" name="strspn">
|
||||
<item><ref id="strcasestr" name="strcasestr">
|
||||
<item><ref id="strstr" name="strstr">
|
||||
<item><ref id="strtok" name="strtok">
|
||||
<item><ref id="strxfrm" name="strxfrm">
|
||||
@ -7899,22 +7902,47 @@ be used in presence of a prototype.
|
||||
</quote>
|
||||
|
||||
|
||||
<sect1>strstr<label id="strstr"><p>
|
||||
<sect1>strcasestr<label id="strcasestr"><p>
|
||||
|
||||
<quote>
|
||||
<descrip>
|
||||
<tag/Function/Find a substring.
|
||||
<tag/Function/Find a substring, case-insensitive.
|
||||
<tag/Header/<tt/<ref id="string.h" name="string.h">/
|
||||
<tag/Declaration/<tt/char* __fastcall__ strstr (const char* str, const char* substr);/
|
||||
<tag/Description/<tt/strstr/ searches for the first occurrence of the string
|
||||
<tt/substr/ within <tt/str/. If found, it returns a pointer to the copy,
|
||||
otherwise it returns <tt/NULL/.
|
||||
<tag/Declaration/<tt/char* __fastcall__ strcasestr (const char* str, const char* substr);/
|
||||
<tag/Description/<tt/strcasestr/ searches for the first occurrence of the string
|
||||
<tt/substr/ within <tt/str/. If found, it returns a pointer to the start of the
|
||||
match in <tt/str/, otherwise it returns <tt/NULL/.
|
||||
<tag/Notes/<itemize>
|
||||
<item>The function is only available as fastcall function, so it may only
|
||||
be used in presence of a prototype.
|
||||
</itemize>
|
||||
<tag/Availability/ISO 9899
|
||||
<tag/See also/
|
||||
<ref id="strstr" name="strstr">,
|
||||
<ref id="strcspn" name="strcspn">,
|
||||
<ref id="strspn" name="strspn">
|
||||
<tag/Example/None.
|
||||
</descrip>
|
||||
</quote>
|
||||
|
||||
|
||||
<sect1>strstr<label id="strstr"><p>
|
||||
|
||||
<quote>
|
||||
<descrip>
|
||||
<tag/Function/Find a substring, case-sensitive.
|
||||
<tag/Header/<tt/<ref id="string.h" name="string.h">/
|
||||
<tag/Declaration/<tt/char* __fastcall__ strstr (const char* str, const char* substr);/
|
||||
<tag/Description/<tt/strstr/ searches for the first occurrence of the string
|
||||
<tt/substr/ within <tt/str/. If found, it returns a pointer to the start of the
|
||||
match in <tt/str/, otherwise it returns <tt/NULL/.
|
||||
<tag/Notes/<itemize>
|
||||
<item>The function is only available as fastcall function, so it may only
|
||||
be used in presence of a prototype.
|
||||
</itemize>
|
||||
<tag/Availability/ISO 9899
|
||||
<tag/See also/
|
||||
<ref id="strcasestr" name="strcasestr">,
|
||||
<ref id="strcspn" name="strcspn">,
|
||||
<ref id="strspn" name="strspn">
|
||||
<tag/Example/None.
|
||||
@ -8331,6 +8359,7 @@ only in the presence of a prototype.
|
||||
<descrip>
|
||||
<tag/Function/Wait until the start of the next video frame.
|
||||
<tag/Header/<tt/
|
||||
<ref id="atmos.h" name="atmos.h">,
|
||||
<ref id="cbm.h" name="cbm.h">,
|
||||
<ref id="gamate.h" name="gamate.h">,
|
||||
<ref id="nes.h" name="nes.h">,
|
||||
@ -8338,6 +8367,7 @@ only in the presence of a prototype.
|
||||
<tag/Declaration/<tt/void waitvsync (void);/
|
||||
<tag/Description/Wait for vertical sync, to reduce flickering.
|
||||
<tag/Availability/Platforms served by the headers above
|
||||
(Atmos requires the VSync hack)
|
||||
<tag/Example/None.
|
||||
</descrip>
|
||||
</quote>
|
||||
|
@ -115,37 +115,78 @@ PVExit ($01)
|
||||
|
||||
<sect>Creating a Test in C<p>
|
||||
|
||||
For a C test compiled and linked with <tt/--target sim6502/ the
|
||||
For a C test linked with <tt/--target sim6502/ and the <tt/sim6502.lib/ library,
|
||||
command line arguments to <tt/sim65/ will be passed to <tt/main/,
|
||||
and the return value from <tt/main/ will become sim65's exit code.
|
||||
The <tt/exit/ function may also be used to terminate with an exit code.
|
||||
The <tt/stdlib.h/ <tt/exit/ function may also be used to terminate with an exit code.
|
||||
|
||||
Exit codes are limited to 8 bits.
|
||||
Exit codes are limited to an unsigned 8 bit value. (E.g. returning -1 will give an exit code of 255.)
|
||||
|
||||
The standard C library high level file input and output is functional.
|
||||
A sim65 application can be written like a command line application,
|
||||
providing arguments to <tt/main/ and using the <tt/stdio.h/ interfaces.
|
||||
providing command line arguments to <tt/main/ and using the <tt/stdio.h/ interfaces
|
||||
to interact with the console or access files.
|
||||
|
||||
Internally, file input and output is provided at a lower level by
|
||||
a set of built-in paravirtualization functions (<ref id="paravirt-internal" name="see below">).
|
||||
a set of built-in paravirtualization functions (see <ref id="paravirt-internal" name="below">).
|
||||
|
||||
Example:
|
||||
|
||||
<tscreen><verb>
|
||||
#include <stdio.h>
|
||||
int main()
|
||||
{
|
||||
printf("Hello!\n");
|
||||
return 5;
|
||||
}
|
||||
|
||||
// Build and run:
|
||||
// cl65 -t sim6502 -o example.prg example.c
|
||||
// sim65 example.prg
|
||||
|
||||
// Build and run, separate steps:
|
||||
// cc65 -t sim6502 -o example.s example.c
|
||||
// ca65 -t sim6502 -o example.o example.s
|
||||
// ld65 -t sim6502 -o example.prg example.o sim6502.lib
|
||||
// sim65 example.prg
|
||||
</verb></tscreen>
|
||||
|
||||
<sect>Creating a Test in Assembly<p>
|
||||
|
||||
Assembly tests may similarly be assembled and linked with
|
||||
<tt/--target sim6502/ or <tt/--target sim65c02/.
|
||||
Define and export <tt/_main/ as an entry point,
|
||||
Though a C test may also link with assembly code,
|
||||
a pure assembly test can also be created.
|
||||
|
||||
Link with <tt/--target sim6502/ or <tt/--target sim65c02/ and the corresponding library,
|
||||
define and export <tt/_main/ as an entry point,
|
||||
and the sim65 library provides two ways to return an 8-bit exit code:
|
||||
|
||||
<itemize>
|
||||
|
||||
<item>Return from <tt/_main/ with the exit code in <tt/A/.
|
||||
|
||||
<item><tt/jmp exit/ with the code in <tt/A/.
|
||||
<item><tt/jmp exit/ with the code in <tt/A/. (<tt/.import exit/ from the sim65 library.)
|
||||
|
||||
</itemize>
|
||||
|
||||
The binary file has a 12 byte header:
|
||||
Example:
|
||||
|
||||
<tscreen><verb>
|
||||
.export _main
|
||||
_main:
|
||||
lda #5
|
||||
rts
|
||||
|
||||
; Build and run:
|
||||
; cl65 -t sim6502 -o example.prg example.s
|
||||
; sim65 example.prg
|
||||
|
||||
; Build and run, separate steps:
|
||||
; ca65 -t sim6502 -o example.o example.s
|
||||
; ld65 -t sim6502 -o example.prg example.o sim6502.lib
|
||||
; sim65 example.prg
|
||||
</verb></tscreen>
|
||||
|
||||
Internally, the binary program file has a 12 byte header provided by the library:
|
||||
|
||||
<itemize>
|
||||
|
||||
@ -182,6 +223,9 @@ These use cc65 calling conventions, and are intended for use with the sim65 targ
|
||||
<item><tt/IRQ/ and <tt/NMI/ events will not be generated, though <tt/BRK/
|
||||
can be used if the IRQ vector at <tt/$FFFE/ is manually prepared by the test code.
|
||||
|
||||
<item>The <tt/sim6502/ or <tt/sim65c02/ targets provide a default configuration,
|
||||
but if customization is needed <tt/sim6502.cfg/ or <tt/sim65c02.cfg/ might be used as a template.
|
||||
|
||||
</itemize>
|
||||
|
||||
|
||||
|
@ -232,6 +232,16 @@ struct tm* __fastcall__ gmtime_dt (const struct datetime* dt);
|
||||
time_t __fastcall__ mktime_dt (const struct datetime* dt);
|
||||
/* Converts a ProDOS date/time structure to a time_t UNIX timestamp */
|
||||
|
||||
#if !defined(__APPLE2ENH__)
|
||||
unsigned char __fastcall__ allow_lowercase (unsigned char onoff);
|
||||
/* If onoff is 0, lowercase characters printed to the screen via STDIO and
|
||||
** CONIO are forced to uppercase. If onoff is 1, lowercase characters are
|
||||
** printed to the screen untouched. By default lowercase characters are
|
||||
** forced to uppercase because a stock Apple ][+ doesn't support lowercase
|
||||
** display. The function returns the old lowercase setting.
|
||||
*/
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* End of apple2.h */
|
||||
|
@ -220,17 +220,17 @@
|
||||
/* Color register functions */
|
||||
/*****************************************************************************/
|
||||
|
||||
extern void __fastcall__ _setcolor (unsigned char color_reg, unsigned char hue, unsigned char luminance);
|
||||
extern void __fastcall__ _setcolor_low (unsigned char color_reg, unsigned char color_value);
|
||||
extern unsigned char __fastcall__ _getcolor (unsigned char color_reg);
|
||||
void __fastcall__ _setcolor (unsigned char color_reg, unsigned char hue, unsigned char luminance);
|
||||
void __fastcall__ _setcolor_low (unsigned char color_reg, unsigned char color_value);
|
||||
unsigned char __fastcall__ _getcolor (unsigned char color_reg);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Other screen functions */
|
||||
/*****************************************************************************/
|
||||
|
||||
extern void waitvsync (void); /* wait for start of next frame */
|
||||
extern int __fastcall__ _graphics (unsigned char mode); /* mode value same as in BASIC */
|
||||
extern void __fastcall__ _scroll (signed char numlines);
|
||||
void waitvsync (void); /* wait for start of next frame */
|
||||
int __fastcall__ _graphics (unsigned char mode); /* mode value same as in BASIC */
|
||||
void __fastcall__ _scroll (signed char numlines);
|
||||
/* numlines > 0 scrolls up */
|
||||
/* numlines < 0 scrolls down */
|
||||
|
||||
@ -239,18 +239,18 @@ extern void __fastcall__ _scroll (signed char numlines);
|
||||
/* Sound function */
|
||||
/*****************************************************************************/
|
||||
|
||||
extern void __fastcall__ _sound (unsigned char voice, unsigned char frequency, unsigned char distortion, unsigned char volume);
|
||||
void __fastcall__ _sound (unsigned char voice, unsigned char frequency, unsigned char distortion, unsigned char volume);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Misc. functions */
|
||||
/*****************************************************************************/
|
||||
|
||||
extern unsigned char get_ostype(void); /* get ROM version */
|
||||
extern unsigned char get_tv(void); /* get TV system */
|
||||
extern void _save_vecs(void); /* save system vectors */
|
||||
extern void _rest_vecs(void); /* restore system vectors */
|
||||
extern char *_getdefdev(void); /* get default floppy device */
|
||||
extern unsigned char _is_cmdline_dos(void); /* does DOS support command lines */
|
||||
unsigned char get_ostype(void); /* get ROM version */
|
||||
unsigned char get_tv(void); /* get TV system */
|
||||
void _save_vecs(void); /* save system vectors */
|
||||
void _rest_vecs(void); /* restore system vectors */
|
||||
char *_getdefdev(void); /* get default floppy device */
|
||||
unsigned char _is_cmdline_dos(void); /* does DOS support command lines */
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -94,7 +94,7 @@ extern void atr5200std_joy[]; /* referred to by joy_static_stddrv[] */
|
||||
#define _bordercolor(color) 0
|
||||
|
||||
/* wait for start of next frame */
|
||||
extern void waitvsync (void);
|
||||
void waitvsync (void);
|
||||
|
||||
/* end of atari5200.h */
|
||||
#endif
|
||||
|
@ -52,7 +52,7 @@
|
||||
/* No support for dynamically loadable drivers */
|
||||
#define DYN_DRV 0
|
||||
|
||||
extern unsigned char get_tv(void); /* get TV system */
|
||||
unsigned char get_tv(void); /* get TV system */
|
||||
|
||||
#include <_tia.h>
|
||||
#define TIA (*(struct __tia*)0x0000)
|
||||
|
@ -169,6 +169,9 @@ void atmos_tock (void);
|
||||
void atmos_zap (void);
|
||||
/* Raygun sound effect */
|
||||
|
||||
void waitvsync (void);
|
||||
/* Wait for start of next frame */
|
||||
|
||||
|
||||
|
||||
/* End of atmos.h */
|
||||
|
@ -52,15 +52,15 @@ typedef unsigned char uint8_t;
|
||||
typedef unsigned uint16_t;
|
||||
typedef unsigned long uint32_t;
|
||||
|
||||
#define INT8_MIN ((int8_t) 0x80)
|
||||
#define INT8_MAX ((int8_t) 0x7F)
|
||||
#define INT16_MIN ((int16_t) 0x8000)
|
||||
#define INT16_MAX ((int16_t) 0x7FFF)
|
||||
#define INT32_MIN ((int32_t) 0x80000000)
|
||||
#define INT32_MAX ((int32_t) 0x7FFFFFFF)
|
||||
#define UINT8_MAX ((uint8_t) 0xFF)
|
||||
#define UINT16_MAX ((uint16_t) 0xFFFF)
|
||||
#define UINT32_MAX ((uint32_t) 0xFFFFFFFF)
|
||||
#define INT8_MIN -128
|
||||
#define INT8_MAX 127
|
||||
#define INT16_MIN (-32767 - 1)
|
||||
#define INT16_MAX 32767
|
||||
#define INT32_MIN (-2147483647L - 1L)
|
||||
#define INT32_MAX 2147483647L
|
||||
#define UINT8_MAX 255
|
||||
#define UINT16_MAX 65535U
|
||||
#define UINT32_MAX 4294967295UL
|
||||
|
||||
/* Minimum-width integer types */
|
||||
typedef signed char int_least8_t;
|
||||
@ -70,15 +70,15 @@ typedef unsigned char uint_least8_t;
|
||||
typedef unsigned uint_least16_t;
|
||||
typedef unsigned long uint_least32_t;
|
||||
|
||||
#define INT_LEAST8_MIN ((int_least8_t) 0x80)
|
||||
#define INT_LEAST8_MAX ((int_least8_t) 0x7F)
|
||||
#define INT_LEAST16_MIN ((int_least16_t) 0x8000)
|
||||
#define INT_LEAST16_MAX ((int_least16_t) 0x7FFF)
|
||||
#define INT_LEAST32_MIN ((int_least32_t) 0x80000000)
|
||||
#define INT_LEAST32_MAX ((int_least32_t) 0x7FFFFFFF)
|
||||
#define UINT_LEAST8_MAX ((uint_least8_t) 0xFF)
|
||||
#define UINT_LEAST16_MAX ((uint_least16_t) 0xFFFF)
|
||||
#define UINT_LEAST32_MAX ((uint_least32_t) 0xFFFFFFFF)
|
||||
#define INT_LEAST8_MIN INT8_MIN
|
||||
#define INT_LEAST8_MAX INT8_MAX
|
||||
#define INT_LEAST16_MIN INT16_MIN
|
||||
#define INT_LEAST16_MAX INT16_MAX
|
||||
#define INT_LEAST32_MIN INT32_MIN
|
||||
#define INT_LEAST32_MAX INT32_MAX
|
||||
#define UINT_LEAST8_MAX UINT8_MAX
|
||||
#define UINT_LEAST16_MAX UINT16_MAX
|
||||
#define UINT_LEAST32_MAX UINT32_MAX
|
||||
|
||||
/* Fastest minimum-width integer types */
|
||||
typedef signed char int_fast8_t;
|
||||
@ -88,40 +88,40 @@ typedef unsigned char uint_fast8_t;
|
||||
typedef unsigned uint_fast16_t;
|
||||
typedef unsigned long uint_fast32_t;
|
||||
|
||||
#define INT_FAST8_MIN ((int_fast8_t) 0x80)
|
||||
#define INT_FAST8_MAX ((int_fast8_t) 0x7F)
|
||||
#define INT_FAST16_MIN ((int_fast16_t) 0x8000)
|
||||
#define INT_FAST16_MAX ((int_fast16_t) 0x7FFF)
|
||||
#define INT_FAST32_MIN ((int_fast32_t) 0x80000000)
|
||||
#define INT_FAST32_MAX ((int_fast32_t) 0x7FFFFFFF)
|
||||
#define UINT_FAST8_MAX ((uint_fast8_t) 0xFF)
|
||||
#define UINT_FAST16_MAX ((uint_fast16_t) 0xFFFF)
|
||||
#define UINT_FAST32_MAX ((uint_fast32_t) 0xFFFFFFFF)
|
||||
#define INT_FAST8_MIN INT8_MIN
|
||||
#define INT_FAST8_MAX INT8_MAX
|
||||
#define INT_FAST16_MIN INT16_MIN
|
||||
#define INT_FAST16_MAX INT16_MAX
|
||||
#define INT_FAST32_MIN INT32_MIN
|
||||
#define INT_FAST32_MAX INT32_MAX
|
||||
#define UINT_FAST8_MAX UINT8_MAX
|
||||
#define UINT_FAST16_MAX UINT16_MAX
|
||||
#define UINT_FAST32_MAX UINT32_MAX
|
||||
|
||||
/* Integer types capable of holding object pointers */
|
||||
typedef int intptr_t;
|
||||
typedef unsigned uintptr_t;
|
||||
|
||||
#define INTPTR_MIN ((intptr_t)0x8000)
|
||||
#define INTPTR_MAX ((intptr_t)0x7FFF)
|
||||
#define UINTPTR_MAX ((uintptr_t) 0xFFFF)
|
||||
#define INTPTR_MIN INT16_MIN
|
||||
#define INTPTR_MAX INT16_MAX
|
||||
#define UINTPTR_MAX UINT16_MAX
|
||||
|
||||
/* Greatest width integer types */
|
||||
typedef long intmax_t;
|
||||
typedef unsigned long uintmax_t;
|
||||
|
||||
#define INTMAX_MIN ((intmax_t) 0x80000000)
|
||||
#define INTMAX_MAX ((intmax_t) 0x7FFFFFFF)
|
||||
#define UINTMAX_MAX ((uintmax_t) 0xFFFFFFFF)
|
||||
#define INTMAX_MIN INT32_MIN
|
||||
#define INTMAX_MAX INT32_MAX
|
||||
#define UINTMAX_MAX UINT32_MAX
|
||||
|
||||
/* Limits of other integer types */
|
||||
#define PTRDIFF_MIN ((int) 0x8000)
|
||||
#define PTRDIFF_MAX ((int) 0x7FFF)
|
||||
#define PTRDIFF_MIN INT16_MIN
|
||||
#define PTRDIFF_MAX INT16_MAX
|
||||
|
||||
#define SIG_ATOMIC_MIN ((unsigned char) 0x00)
|
||||
#define SIG_ATOMIC_MAX ((unsigned char) 0xFF)
|
||||
#define SIG_ATOMIC_MIN 0
|
||||
#define SIG_ATOMIC_MAX UINT8_MAX
|
||||
|
||||
#define SIZE_MAX 0xFFFF
|
||||
#define SIZE_MAX UINT16_MAX
|
||||
|
||||
/* Macros for minimum width integer constants */
|
||||
#define INT8_C(c) c
|
||||
|
@ -81,6 +81,7 @@ void __fastcall__ bzero (void* ptr, size_t n); /* BSD */
|
||||
char* __fastcall__ strdup (const char* s); /* SYSV/BSD */
|
||||
int __fastcall__ stricmp (const char* s1, const char* s2); /* DOS/Windows */
|
||||
int __fastcall__ strcasecmp (const char* s1, const char* s2); /* Same for Unix */
|
||||
char* __fastcall__ strcasestr (const char* str, const char* substr);
|
||||
int __fastcall__ strnicmp (const char* s1, const char* s2, size_t count); /* DOS/Windows */
|
||||
int __fastcall__ strncasecmp (const char* s1, const char* s2, size_t count); /* Same for Unix */
|
||||
size_t __fastcall__ strnlen (const char* s, size_t maxlen); /* POSIX.1-2008 */
|
||||
@ -89,6 +90,7 @@ char* __fastcall__ strlower (char* s);
|
||||
char* __fastcall__ strupr (char* s);
|
||||
char* __fastcall__ strupper (char* s);
|
||||
char* __fastcall__ strqtok (char* s1, const char* s2);
|
||||
char* __fastcall__ stpcpy (char* dest, const char* src);
|
||||
#endif
|
||||
|
||||
const char* __fastcall__ __stroserror (unsigned char errcode);
|
||||
|
380
libsrc/NameClashes.md
Normal file
380
libsrc/NameClashes.md
Normal file
@ -0,0 +1,380 @@
|
||||
List of cc65 library name clashes
|
||||
=================================
|
||||
|
||||
The following is a list of identifiers that might need
|
||||
to be fixed, sorted by directory and identifier:
|
||||
|
||||
# common
|
||||
|
||||
## \_\_argc
|
||||
|
||||
* libsrc/runtime/callmain.s
|
||||
* libsrc/cbm610/mainargs.s
|
||||
* libsrc/cx16/mainargs.s
|
||||
* libsrc/plus4/mainargs.s
|
||||
* libsrc/lynx/mainargs.s
|
||||
* libsrc/c16/mainargs.s
|
||||
* libsrc/geos-common/system/mainargs.s
|
||||
* libsrc/sim6502/mainargs.s
|
||||
* libsrc/c128/mainargs.s
|
||||
* libsrc/vic20/mainargs.s
|
||||
* libsrc/nes/mainargs.s
|
||||
* libsrc/atari/getargs.s
|
||||
* libsrc/apple2/mainargs.s
|
||||
* libsrc/cbm510/mainargs.s
|
||||
* libsrc/telestrat/mainargs.s
|
||||
* libsrc/c64/mainargs.s
|
||||
* libsrc/pet/mainargs.s
|
||||
* libsrc/atmos/mainargs.s
|
||||
|
||||
## \_\_argv
|
||||
|
||||
* libsrc/runtime/callmain.s
|
||||
* libsrc/cbm610/mainargs.s
|
||||
* libsrc/cx16/mainargs.s
|
||||
* libsrc/plus4/mainargs.s
|
||||
* libsrc/lynx/mainargs.s
|
||||
* libsrc/c16/mainargs.s
|
||||
* libsrc/geos-common/system/mainargs.s
|
||||
* libsrc/sim6502/mainargs.s
|
||||
* libsrc/c128/mainargs.s
|
||||
* libsrc/vic20/mainargs.s
|
||||
* libsrc/nes/mainargs.s
|
||||
* libsrc/atari/getargs.s
|
||||
* libsrc/apple2/mainargs.s
|
||||
* libsrc/cbm510/mainargs.s
|
||||
* libsrc/telestrat/mainargs.s
|
||||
* libsrc/c64/mainargs.s
|
||||
* libsrc/pet/mainargs.s
|
||||
* libsrc/atmos/mainargs.s
|
||||
|
||||
## \_\_cos
|
||||
|
||||
* libsrc/common/sincos.s
|
||||
|
||||
## \_\_ctypeidx
|
||||
|
||||
* libsrc/common/ctype.s
|
||||
* libsrc/common/ctypemask.s
|
||||
* libsrc/geos-common/system/ctype.s
|
||||
* libsrc/atari/ctype.s
|
||||
* libsrc/cbm/ctype.s
|
||||
* libsrc/atmos/ctype.s
|
||||
* asminc/ctype\_common.inc
|
||||
|
||||
## \_\_cwd
|
||||
|
||||
* libsrc/common/getcwd.s
|
||||
* libsrc/common/_cwd.s
|
||||
* libsrc/atari/initcwd.s
|
||||
* libsrc/apple2/initcwd.s
|
||||
* libsrc/apple2/initcwd.s
|
||||
* libsrc/telestrat/initcwd.s
|
||||
* libsrc/cbm/initcwd.s
|
||||
|
||||
## \_\_cwd\_buf\_size
|
||||
|
||||
* libsrc/common/_cwd.s
|
||||
|
||||
## \_\_envcount
|
||||
|
||||
* libsrc/common/searchenv.s
|
||||
* libsrc/common/_environ.s
|
||||
* libsrc/common/putenv.s
|
||||
* libsrc/common/getenv.s
|
||||
|
||||
## \_\_environ
|
||||
|
||||
* libsrc/common/searchenv.s
|
||||
* libsrc/common/_environ.s
|
||||
* libsrc/common/putenv.s
|
||||
* libsrc/common/getenv.s
|
||||
|
||||
## \_\_envsize
|
||||
|
||||
* libsrc/common/_environ.s
|
||||
* libsrc/common/putenv.s
|
||||
|
||||
## \_\_fdesc
|
||||
|
||||
* libsrc/common/_fdesc.s
|
||||
* libsrc/common/fopen.s
|
||||
|
||||
## \_\_filetab
|
||||
|
||||
* libsrc/common/_fdesc.s
|
||||
* libsrc/common/_file.s
|
||||
* asminc/_file.inc
|
||||
|
||||
## \_\_fopen
|
||||
|
||||
* libsrc/common/fopen.s
|
||||
* libsrc/common/_fopen.s
|
||||
|
||||
## \_\_printf
|
||||
|
||||
* libsrc/common/vsnprintf.s
|
||||
* libsrc/common/_printf.s
|
||||
* libsrc/common/vfprintf.s
|
||||
* libsrc/conio/vcprintf.s
|
||||
* libsrc/pce/_printf.s
|
||||
|
||||
## \_\_scanf
|
||||
|
||||
* libsrc/common/_scanf.inc
|
||||
* libsrc/common/vsscanf.s
|
||||
* libsrc/conio/vcscanf.s
|
||||
|
||||
## \_\_sin
|
||||
|
||||
* libsrc/common/sincos.s
|
||||
|
||||
## \_\_sys
|
||||
|
||||
* libsrc/common/_sys.s
|
||||
* libsrc/apple2/_sys.s
|
||||
|
||||
## \_\_sys\_oserrlist
|
||||
|
||||
* libsrc/common/stroserr.s
|
||||
* libsrc/geos-common/system/oserrlist.s
|
||||
* libsrc/atari/oserrlist.s
|
||||
* libsrc/apple2/oserrlist.s
|
||||
* libsrc/cbm/oserrlist.s
|
||||
* libsrc/atmos/oserrlist.s
|
||||
|
||||
## \_\_syschdir
|
||||
|
||||
* libsrc/common/chdir.s
|
||||
* libsrc/atari/syschdir.s
|
||||
* libsrc/apple2/syschdir.s
|
||||
* libsrc/telestrat/syschdir.s
|
||||
* libsrc/cbm/syschdir.s
|
||||
|
||||
## \_\_sysmkdir
|
||||
|
||||
* libsrc/common/mkdir.s
|
||||
* libsrc/atari/sysmkdir.s
|
||||
* libsrc/apple2/sysmkdir.s
|
||||
* libsrc/telestrat/sysmkdir.s
|
||||
|
||||
## \_\_sysremove
|
||||
|
||||
* libsrc/common/remove.s
|
||||
* libsrc/geos-common/file/sysremove.s
|
||||
* libsrc/atari/sysremove.s
|
||||
* libsrc/atari/sysrmdir.s
|
||||
* libsrc/apple2/sysremove.s
|
||||
* libsrc/apple2/sysrmdir.s
|
||||
* libsrc/telestrat/sysremove.s
|
||||
* libsrc/cbm/sysremove.s
|
||||
|
||||
## \_\_sysrename
|
||||
|
||||
* libsrc/common/rename.s
|
||||
* libsrc/geos-common/file/sysrename.s
|
||||
* libsrc/atari/sysrename.s
|
||||
* libsrc/apple2/sysrename.s
|
||||
* libsrc/cbm/sysrename.s
|
||||
|
||||
## \_\_sysrmdir
|
||||
|
||||
* libsrc/common/rmdir.s
|
||||
* libsrc/atari/sysrmdir.s
|
||||
* libsrc/apple2/sysrmdir.s
|
||||
|
||||
\_\_sysuname
|
||||
|
||||
* libsrc/common/uname.s
|
||||
* libsrc/cbm610/sysuname.s
|
||||
* libsrc/cx16/sysuname.s
|
||||
* libsrc/plus4/sysuname.s
|
||||
* libsrc/lynx/sysuname.s
|
||||
* libsrc/c16/sysuname.s
|
||||
* libsrc/geos-common/system/sysuname.s
|
||||
* libsrc/c128/sysuname.s
|
||||
* libsrc/creativision/sysuname.s
|
||||
* libsrc/vic20/sysuname.s
|
||||
* libsrc/nes/sysuname.s
|
||||
* libsrc/atari/sysuname.s
|
||||
* libsrc/apple2/sysuname.s
|
||||
* libsrc/cbm510/sysuname.s
|
||||
* libsrc/telestrat/sysuname.s
|
||||
* libsrc/c64/sysuname.s
|
||||
* libsrc/pet/sysuname.s
|
||||
* libsrc/atari5200/sysuname.s
|
||||
* libsrc/atmos/sysuname.s
|
||||
|
||||
# apple2
|
||||
|
||||
## \_\_auxtype
|
||||
|
||||
* libsrc/apple2/open.s
|
||||
|
||||
## \_\_datetime
|
||||
|
||||
* libsrc/apple2/open.s
|
||||
|
||||
## \_\_dos\_type
|
||||
|
||||
* libsrc/apple2/dioopen.s
|
||||
* libsrc/apple2/curdevice.s
|
||||
* libsrc/apple2/mainargs.s
|
||||
* libsrc/apple2/settime.s
|
||||
* libsrc/apple2/getdevice.s
|
||||
* libsrc/apple2/dosdetect.s
|
||||
* libsrc/apple2/irq.s
|
||||
* libsrc/apple2/open.s
|
||||
* libsrc/apple2/mli.s
|
||||
* libsrc/apple2/getres.s
|
||||
|
||||
## \_\_filetype
|
||||
|
||||
* libsrc/apple2/open.s
|
||||
* libsrc/apple2/exehdr.s
|
||||
|
||||
## atari
|
||||
|
||||
## \_\_defdev
|
||||
|
||||
* libsrc/atari/posixdirent.s
|
||||
* libsrc/atari/ucase\_fn.s
|
||||
* libsrc/atari/getdefdev.s
|
||||
|
||||
## \_\_dos\_type
|
||||
|
||||
* libsrc/atari/getargs.s
|
||||
* libsrc/atari/exec.s
|
||||
* libsrc/atari/settime.s
|
||||
* libsrc/atari/syschdir.s
|
||||
* libsrc/atari/dosdetect.s
|
||||
* libsrc/atari/is\_cmdline\_dos.s
|
||||
* libsrc/atari/sysrmdir.s
|
||||
* libsrc/atari/gettime.s
|
||||
* libsrc/atari/lseek.s
|
||||
* libsrc/atari/getres.s
|
||||
* libsrc/atari/getdefdev.s
|
||||
|
||||
## \_\_do\_oserror
|
||||
|
||||
* libsrc/atari/posixdirent.s
|
||||
* libsrc/atari/do\_oserr.s
|
||||
* libsrc/atari/serref.s
|
||||
* libsrc/atari/read.s
|
||||
* libsrc/atari/write.s
|
||||
* libsrc/atari/close.s
|
||||
|
||||
## \_\_getcolor
|
||||
|
||||
* libsrc/atari/setcolor.s
|
||||
|
||||
## \_\_getdefdev
|
||||
|
||||
* libsrc/atari/getdefdev.s
|
||||
|
||||
## \_\_graphics
|
||||
|
||||
* libsrc/atari/graphics.s
|
||||
|
||||
## \_\_inviocb
|
||||
|
||||
* libsrc/atari/serref.s
|
||||
* libsrc/atari/ser/atrrdev.s
|
||||
* libsrc/atari/inviocb.s
|
||||
* libsrc/atari/read.s
|
||||
* libsrc/atari/write.s
|
||||
* libsrc/atari/lseek.s
|
||||
* libsrc/atari/close.s
|
||||
|
||||
## \_\_is\_cmdline\_dos
|
||||
|
||||
* libsrc/atari/is\_cmdline\_dos.s
|
||||
* libsrc/atari/doesclrscr.s
|
||||
|
||||
## \_\_rest\_vecs
|
||||
|
||||
* libsrc/atari/savevec.s
|
||||
|
||||
## \_\_rwsetup
|
||||
|
||||
* libsrc/atari/rwcommon.s
|
||||
* libsrc/atari/read.s
|
||||
* libsrc/atari/write.s
|
||||
|
||||
## \_\_save\_vecs
|
||||
|
||||
* libsrc/atari/savevec.s
|
||||
|
||||
## \_\_scroll
|
||||
|
||||
* libsrc/atari/scroll.s
|
||||
|
||||
## \_\_setcolor
|
||||
|
||||
* libsrc/atari/setcolor.s
|
||||
|
||||
## \_\_setcolor\_low
|
||||
|
||||
* libsrc/atari/setcolor.s
|
||||
|
||||
## \_\_sio\_call
|
||||
|
||||
* libsrc/atari/diowritev.s
|
||||
* libsrc/atari/diopncls.s
|
||||
* libsrc/atari/siocall.s
|
||||
* libsrc/atari/diowrite.s
|
||||
* libsrc/atari/dioread.s
|
||||
|
||||
# cbm
|
||||
|
||||
## \_\_cbm\_filetype
|
||||
|
||||
* libsrc/cbm/cbm\_filetype.s
|
||||
* asminc/cbm\_filetype.in
|
||||
|
||||
## \_\_dirread
|
||||
|
||||
* libsrc/cbm/dir.inc
|
||||
* libsrc/cbm/dir.s
|
||||
|
||||
## \_\_dirread1
|
||||
|
||||
* libsrc/cbm/dir.inc
|
||||
* libsrc/cbm/dir.s
|
||||
|
||||
# lynx
|
||||
|
||||
## \_\_iodat
|
||||
|
||||
* libsrc/lynx/lynx-cart.s
|
||||
* libsrc/lynx/bootldr.s
|
||||
* libsrc/lynx/extzp.s
|
||||
* libsrc/lynx/crt0.s
|
||||
* libsrc/lynx/extzp.inc
|
||||
|
||||
## \_\_iodir
|
||||
|
||||
* libsrc/lynx/extzp.s
|
||||
* libsrc/lynx/crt0.s
|
||||
* libsrc/lynx/extzp.inc
|
||||
|
||||
## \_\_sprsys
|
||||
|
||||
* libsrc/lynx/tgi/lynx-160-102-16.s
|
||||
* libsrc/lynx/extzp.s
|
||||
* libsrc/lynx/crt0.s
|
||||
* libsrc/lynx/extzp.inc
|
||||
|
||||
## \_\_viddma
|
||||
|
||||
* libsrc/lynx/tgi/lynx-160-102-16.s
|
||||
* libsrc/lynx/extzp.s
|
||||
* libsrc/lynx/crt0.s
|
||||
* libsrc/lynx/extzp.inc
|
||||
|
||||
# pce
|
||||
|
||||
## \_\_nmi
|
||||
|
||||
* libsrc/pce/irq.s
|
||||
* libsrc/pce/crt0.s
|
23
libsrc/apple2/allow_lowercase.s
Normal file
23
libsrc/apple2/allow_lowercase.s
Normal file
@ -0,0 +1,23 @@
|
||||
;
|
||||
; Oliver Schmidt, 2024-08-06
|
||||
;
|
||||
; unsigned char __fastcall__ allow_lowercase (unsigned char onoff);
|
||||
;
|
||||
|
||||
.export _allow_lowercase
|
||||
.import uppercasemask, return0, return1
|
||||
|
||||
_allow_lowercase:
|
||||
tax
|
||||
lda values,x
|
||||
ldx uppercasemask
|
||||
sta uppercasemask
|
||||
cpx #$FF
|
||||
beq :+
|
||||
jmp return0
|
||||
: jmp return1
|
||||
|
||||
.rodata
|
||||
|
||||
values: .byte $DF ; Force uppercase
|
||||
.byte $FF ; Keep lowercase
|
75
libsrc/apple2/callmain.s
Normal file
75
libsrc/apple2/callmain.s
Normal file
@ -0,0 +1,75 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 2003-03-07
|
||||
;
|
||||
; Push arguments and call main()
|
||||
;
|
||||
|
||||
|
||||
.export callmain, _exit
|
||||
.export __argc, __argv
|
||||
|
||||
.import _main, pushax, done, donelib
|
||||
.import zpsave, rvsave, reset
|
||||
|
||||
.include "zeropage.inc"
|
||||
.include "apple2.inc"
|
||||
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
; Setup the stack for main(), then jump to it
|
||||
|
||||
callmain:
|
||||
lda __argc
|
||||
ldx __argc+1
|
||||
jsr pushax ; Push argc
|
||||
|
||||
lda __argv
|
||||
ldx __argv+1
|
||||
jsr pushax ; Push argv
|
||||
|
||||
ldy #4 ; Argument size
|
||||
jsr _main
|
||||
|
||||
; Avoid a re-entrance of donelib. This is also the exit() entry.
|
||||
_exit: ldx #<exit
|
||||
lda #>exit
|
||||
jsr reset ; Setup RESET vector
|
||||
|
||||
; Switch in LC bank 2 for R/O in case it was switched out by a RESET.
|
||||
bit $C080
|
||||
|
||||
; Call the module destructors.
|
||||
jsr donelib
|
||||
|
||||
; Switch in ROM.
|
||||
bit $C082
|
||||
|
||||
; Restore the original RESET vector.
|
||||
exit: ldx #$02
|
||||
: lda rvsave,x
|
||||
sta SOFTEV,x
|
||||
dex
|
||||
bpl :-
|
||||
|
||||
; Copy back the zero-page stuff.
|
||||
ldx #zpspace-1
|
||||
: lda zpsave,x
|
||||
sta sp,x
|
||||
dex
|
||||
bpl :-
|
||||
|
||||
; ProDOS TechRefMan, chapter 5.2.1:
|
||||
; "System programs should set the stack pointer to $FF at the
|
||||
; warm-start entry point."
|
||||
ldx #$FF
|
||||
txs ; Re-init stack pointer
|
||||
|
||||
; We're done
|
||||
jmp done
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
; Data
|
||||
|
||||
.data
|
||||
__argc: .word 0
|
||||
__argv: .addr 0
|
@ -11,6 +11,9 @@
|
||||
.export _cputcxy, _cputc
|
||||
.export cputdirect, newline, putchar, putchardirect
|
||||
.import gotoxy, VTABZ
|
||||
.ifndef __APPLE2ENH__
|
||||
.import uppercasemask
|
||||
.endif
|
||||
|
||||
.include "apple2.inc"
|
||||
|
||||
@ -43,7 +46,7 @@ _cputc:
|
||||
.ifndef __APPLE2ENH__
|
||||
cmp #$E0 ; Test for lowercase
|
||||
bcc cputdirect
|
||||
and #$DF ; Convert to uppercase
|
||||
and uppercasemask
|
||||
.endif
|
||||
|
||||
cputdirect:
|
||||
|
@ -4,10 +4,11 @@
|
||||
; Startup code for cc65 (Apple2 version)
|
||||
;
|
||||
|
||||
.export _exit, done, return
|
||||
.export done, return
|
||||
.export zpsave, rvsave, reset
|
||||
.export __STARTUP__ : absolute = 1 ; Mark as startup
|
||||
|
||||
.import initlib, donelib
|
||||
.import initlib, _exit
|
||||
.import zerobss, callmain
|
||||
.import __ONCE_LOAD__, __ONCE_SIZE__ ; Linker generated
|
||||
.import __LC_START__, __LC_LAST__ ; Linker generated
|
||||
@ -33,44 +34,7 @@
|
||||
jsr zerobss
|
||||
|
||||
; Push the command-line arguments; and, call main().
|
||||
jsr callmain
|
||||
|
||||
; Avoid a re-entrance of donelib. This is also the exit() entry.
|
||||
_exit: ldx #<exit
|
||||
lda #>exit
|
||||
jsr reset ; Setup RESET vector
|
||||
|
||||
; Switch in LC bank 2 for R/O in case it was switched out by a RESET.
|
||||
bit $C080
|
||||
|
||||
; Call the module destructors.
|
||||
jsr donelib
|
||||
|
||||
; Switch in ROM.
|
||||
bit $C082
|
||||
|
||||
; Restore the original RESET vector.
|
||||
exit: ldx #$02
|
||||
: lda rvsave,x
|
||||
sta SOFTEV,x
|
||||
dex
|
||||
bpl :-
|
||||
|
||||
; Copy back the zero-page stuff.
|
||||
ldx #zpspace-1
|
||||
: lda zpsave,x
|
||||
sta sp,x
|
||||
dex
|
||||
bpl :-
|
||||
|
||||
; ProDOS TechRefMan, chapter 5.2.1:
|
||||
; "System programs should set the stack pointer to $FF at the
|
||||
; warm-start entry point."
|
||||
ldx #$FF
|
||||
txs ; Re-init stack pointer
|
||||
|
||||
; We're done
|
||||
jmp done
|
||||
jmp callmain
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
|
||||
|
@ -66,34 +66,16 @@ HSType: .res 1 ; Flow-control type
|
||||
RecvBuf: .res 256 ; Receive buffers: 256 bytes
|
||||
SendBuf: .res 256 ; Send buffers: 256 bytes
|
||||
|
||||
CurClockSource: .res 1 ; Whether to use BRG or RTxC for clock
|
||||
|
||||
.data
|
||||
|
||||
Opened: .byte $00 ; 1 when opened
|
||||
Channel: .byte $00 ; Channel B by default
|
||||
CurChanIrqFlags:.byte INTR_PENDING_RX_EXT_B
|
||||
CurChanIrqFlags:.byte $00
|
||||
|
||||
SerFlagOrig: .byte $00
|
||||
|
||||
; Tables used to translate cc65 RS232 params into register values
|
||||
; (Ref page 5-18 and 5-19)
|
||||
BaudLowTable: .byte $7E ; SER_BAUD_300
|
||||
.byte $5E ; SER_BAUD_1200
|
||||
.byte $2E ; SER_BAUD_2400
|
||||
.byte $16 ; SER_BAUD_4800
|
||||
.byte $0A ; SER_BAUD_9600
|
||||
.byte $04 ; SER_BAUD_19200
|
||||
.byte $01 ; SER_BAUD_38400
|
||||
.byte $00 ; SER_BAUD_57600
|
||||
|
||||
BaudHighTable: .byte $01 ; SER_BAUD_300
|
||||
.byte $00 ; SER_BAUD_1200
|
||||
.byte $00 ; SER_BAUD_2400
|
||||
.byte $00 ; SER_BAUD_4800
|
||||
.byte $00 ; SER_BAUD_9600
|
||||
.byte $00 ; SER_BAUD_19200
|
||||
.byte $00 ; SER_BAUD_38400
|
||||
.byte $00 ; SER_BAUD_57600
|
||||
|
||||
RxBitTable: .byte %00000000 ; SER_BITS_5, in WR_RX_CTRL (WR3)
|
||||
.byte %10000000 ; SER_BITS_6 (Ref page 5-7)
|
||||
.byte %01000000 ; SER_BITS_7
|
||||
@ -106,29 +88,65 @@ TxBitTable: .byte %00000000 ; SER_BITS_5, in WR_TX_CTRL (WR5)
|
||||
|
||||
.rodata
|
||||
|
||||
ClockMultiplier:.byte %01000000 ; Clock x16 (300-57600bps, WR4, ref page 5-8)
|
||||
.byte %10000000 ; Clock x32 (115200bps, ref page 5-8)
|
||||
|
||||
ClockSource: .byte %01010000 ; Use baud rate generator (ch. B) (WR11, page 5-17)
|
||||
.byte %00000000 ; Use RTxC (115200bps) (ch. B)
|
||||
.byte %11010000 ; Use baud rate generator (ch. A)
|
||||
.byte %10000000 ; Use RTxC (115200bps) (ch. A)
|
||||
|
||||
BrgEnabled: .byte %00000001 ; Baud rate generator on (WR14, page 5-19)
|
||||
.byte %00000000 ; BRG Off
|
||||
|
||||
ChanIrqFlags: .byte %00000101 ; ANDed (RX/special IRQ, ch. B) (page 5-25)
|
||||
.byte %00101000 ; ANDed (RX/special IRQ, ch. A)
|
||||
|
||||
ChanIrqMask: .byte %00000111 ; Ch. B IRQ flags mask
|
||||
.byte %00111000 ; Ch. A IRQ flags mask
|
||||
|
||||
BaudTable: ; bit7 = 1 means setting is invalid
|
||||
; Otherwise refers to the index in
|
||||
; Baud(Low/High)Table
|
||||
.byte $FF ; SER_BAUD_45_5
|
||||
.byte $FF ; SER_BAUD_50
|
||||
.byte $FF ; SER_BAUD_75
|
||||
.byte $FF ; SER_BAUD_110
|
||||
.byte $FF ; SER_BAUD_134_5
|
||||
.byte $FF ; SER_BAUD_150
|
||||
.byte $00 ; SER_BAUD_300
|
||||
.byte $FF ; SER_BAUD_600
|
||||
.byte $01 ; SER_BAUD_1200
|
||||
.byte $FF ; SER_BAUD_1800
|
||||
.byte $02 ; SER_BAUD_2400
|
||||
.byte $FF ; SER_BAUD_3600
|
||||
.byte $03 ; SER_BAUD_4800
|
||||
.byte $FF ; SER_BAUD_7200
|
||||
.byte $04 ; SER_BAUD_9600
|
||||
.byte $05 ; SER_BAUD_19200
|
||||
.byte $06 ; SER_BAUD_38400
|
||||
.byte $07 ; SER_BAUD_57600
|
||||
.byte $FF ; SER_BAUD_115200
|
||||
.byte $FF ; SER_BAUD_230400
|
||||
; Indexes cc65 RS232 SER_BAUD enum
|
||||
; into WR12/13 register values
|
||||
; (Ref page 5-18 and 5-19)
|
||||
.word $FFFF ; SER_BAUD_45_5
|
||||
.word $FFFF ; SER_BAUD_50
|
||||
.word $FFFF ; SER_BAUD_75
|
||||
.word $FFFF ; SER_BAUD_110
|
||||
.word $FFFF ; SER_BAUD_134_5
|
||||
.word $FFFF ; SER_BAUD_150
|
||||
.word $017E ; SER_BAUD_300
|
||||
.word $FFFF ; SER_BAUD_600
|
||||
.word $005E ; SER_BAUD_1200
|
||||
.word $FFFF ; SER_BAUD_1800
|
||||
.word $002E ; SER_BAUD_2400
|
||||
.word $FFFF ; SER_BAUD_3600
|
||||
.word $0016 ; SER_BAUD_4800
|
||||
.word $FFFF ; SER_BAUD_7200
|
||||
.word $000A ; SER_BAUD_9600
|
||||
.word $0004 ; SER_BAUD_19200
|
||||
.word $0001 ; SER_BAUD_38400
|
||||
.word $0000 ; SER_BAUD_57600
|
||||
.word $0000 ; SER_BAUD_115200 (constant unused at that speed)
|
||||
.word $FFFF ; SER_BAUD_230400
|
||||
|
||||
; About the speed selection: either we use the baud rate generator:
|
||||
; - Load the time constants from BaudTable into WR12/WR13
|
||||
; - Setup the TX/RX clock source to BRG (ClockSource into WR11)
|
||||
; - Setup the clock multiplier (WR4)
|
||||
; - Enable the baud rate generator (WR14)
|
||||
; In this case, the baud rate will be:
|
||||
; rate = crystal_clock/(2+BRG_time_constant))/(2*clock_multiplier)
|
||||
; Example: (3686400/(2+0x0004)) / (2*16) = 19200 bps
|
||||
;
|
||||
; Or we don't use the baud rate generator:
|
||||
; - Setup the TX/RX clock source to RTxC
|
||||
; - Setup the clock multiplier
|
||||
; - Disable the baud rate generator
|
||||
; - WR12 and 13 are ignored
|
||||
; In this case, the baud rate will be:
|
||||
; rate = crystal_clock/clock_multiplier
|
||||
; Example: 3686400/32 = 115200 bps
|
||||
|
||||
StopTable: .byte %00000100 ; SER_STOP_1, in WR_TX_RX_CTRL (WR4)
|
||||
.byte %00001100 ; SER_STOP_2 (Ref page 5-8)
|
||||
@ -156,6 +174,7 @@ SER_FLAG := $E10104
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; Channels
|
||||
|
||||
CHANNEL_B = 0
|
||||
CHANNEL_A = 1
|
||||
|
||||
@ -180,7 +199,6 @@ RX_CTRL_OFF = %11111110 ; ANDed,Rx disabled
|
||||
|
||||
WR_TX_RX_CTRL = 4
|
||||
RR_TX_RX_STATUS = 4
|
||||
TX_RX_CLOCK_MUL = %01000000 ; Clock x16 (Ref page 5-8)
|
||||
|
||||
WR_TX_CTRL = 5 ; (Ref page 5-9)
|
||||
RR_TX_STATUS = 5 ; Corresponding status register
|
||||
@ -197,15 +215,11 @@ MASTER_IRQ_MIE_RST = %00001010 ; STA'd
|
||||
MASTER_IRQ_SET = %00011001 ; STA'd
|
||||
|
||||
WR_CLOCK_CTRL = 11 ; (Ref page 5-17)
|
||||
CLOCK_CTRL_CH_A = %11010000
|
||||
CLOCK_CTRL_CH_B = %01010000
|
||||
|
||||
WR_BAUDL_CTRL = 12 ; (Ref page 5-18)
|
||||
WR_BAUDH_CTRL = 13 ; (Ref page 5-19)
|
||||
|
||||
WR_MISC_CTRL = 14 ; (Ref page 5-19)
|
||||
MISC_CTRL_RATE_GEN_ON = %00000001 ; ORed
|
||||
MISC_CTRL_RATE_GEN_OFF = %11111110 ; ANDed
|
||||
|
||||
WR_IRQ_CTRL = 15 ; (Ref page 5-20)
|
||||
IRQ_CLEANUP_EIRQ = %00001000
|
||||
@ -220,13 +234,8 @@ IRQ_RX = %00100000
|
||||
IRQ_SPECIAL = %01100000
|
||||
|
||||
RR_INTR_PENDING_STATUS = 3 ; (Ref page 5-25)
|
||||
INTR_PENDING_RX_EXT_A = %00101000 ; ANDed (RX or special IRQ)
|
||||
INTR_PENDING_RX_EXT_B = %00000101 ; ANDed (RX or special IRQ)
|
||||
INTR_IS_RX = %00100100 ; ANDed (RX IRQ, channel A or B)
|
||||
|
||||
SER_FLAG_CH_A = %00111000
|
||||
SER_FLAG_CH_B = %00000111
|
||||
|
||||
.code
|
||||
|
||||
; Read register value to A.
|
||||
@ -329,6 +338,15 @@ IIgs:
|
||||
: txa ; Promote char return value
|
||||
rts
|
||||
|
||||
getClockSource:
|
||||
.assert SER_PARAMS::BAUDRATE = 0, error
|
||||
lda (ptr1) ; Baudrate index - cc65 value
|
||||
cmp #SER_BAUD_115200
|
||||
lda #$00
|
||||
adc #$00
|
||||
sta CurClockSource ; 0 = BRG, 1 = RTxC
|
||||
rts
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; SER_OPEN: A pointer to a ser_params structure is passed in ptr1.
|
||||
; Must return an SER_ERR_xx code in a/x.
|
||||
@ -360,11 +378,13 @@ SER_OPEN:
|
||||
ldy #RR_INIT_STATUS ; Hit rr0 once to sync up
|
||||
jsr readSSCReg
|
||||
|
||||
ldy #WR_MISC_CTRL ; Turn everything off
|
||||
ldy #WR_MISC_CTRL ; WR14: Turn everything off
|
||||
lda #$00
|
||||
jsr writeSCCReg
|
||||
|
||||
ldy #SER_PARAMS::STOPBITS
|
||||
jsr getClockSource ; Should we use BRG or RTxC?
|
||||
|
||||
ldy #SER_PARAMS::STOPBITS ; WR4 setup: clock mult., stop & parity
|
||||
lda (ptr1),y ; Stop bits
|
||||
tay
|
||||
lda StopTable,y ; Get value
|
||||
@ -377,36 +397,33 @@ SER_OPEN:
|
||||
ora ParityTable,y ; Get value
|
||||
bmi InvParam
|
||||
|
||||
ora #TX_RX_CLOCK_MUL
|
||||
ldy CurClockSource ; Clock multiplier
|
||||
ora ClockMultiplier,y
|
||||
|
||||
ldy #WR_TX_RX_CTRL ; Setup stop & parity bits
|
||||
jsr writeSCCReg
|
||||
ldy #WR_TX_RX_CTRL
|
||||
jsr writeSCCReg ; End of WR4 setup
|
||||
|
||||
ldy CurClockSource ; WR11 setup: clock source
|
||||
cpx #CHANNEL_B
|
||||
bne ClockA
|
||||
ClockB:
|
||||
beq SetClock
|
||||
iny ; Shift to get correct ClockSource val
|
||||
iny ; depending on our channel
|
||||
|
||||
SetClock:
|
||||
lda ClockSource,y
|
||||
ldy #WR_CLOCK_CTRL
|
||||
lda #CLOCK_CTRL_CH_B
|
||||
jsr writeSCCReg
|
||||
jsr writeSCCReg ; End of WR11 setup
|
||||
|
||||
lda #INTR_PENDING_RX_EXT_B ; Store which IRQ bits we'll check
|
||||
sta CurChanIrqFlags
|
||||
|
||||
bra SetBaud
|
||||
ClockA:
|
||||
ldy #WR_CLOCK_CTRL
|
||||
lda #CLOCK_CTRL_CH_A
|
||||
jsr writeSCCReg
|
||||
|
||||
lda #INTR_PENDING_RX_EXT_A ; Store which IRQ bits we'll check
|
||||
lda ChanIrqFlags,x ; Store which IRQ bits we'll check
|
||||
sta CurChanIrqFlags
|
||||
|
||||
SetBaud:
|
||||
ldy #SER_PARAMS::BAUDRATE
|
||||
lda (ptr1),y ; Baudrate index - cc65 value
|
||||
.assert SER_PARAMS::BAUDRATE = 0, error
|
||||
lda (ptr1) ; Baudrate index - cc65 value
|
||||
asl
|
||||
tay
|
||||
|
||||
lda BaudTable,y ; Get chip value from Low/High tables
|
||||
lda BaudTable,y ; Get low byte of register value
|
||||
bpl BaudOK ; Verify baudrate is supported
|
||||
|
||||
InvParam:
|
||||
@ -415,59 +432,57 @@ InvParam:
|
||||
bra SetupOut
|
||||
|
||||
BaudOK:
|
||||
tay
|
||||
|
||||
lda BaudLowTable,y ; Get low byte
|
||||
|
||||
phy
|
||||
ldy #WR_BAUDL_CTRL
|
||||
jsr writeSCCReg
|
||||
phy ; WR12 setup: BRG time constant, low byte
|
||||
ldy #WR_BAUDL_CTRL ; Setting WR12 & 13 is useless if we're using
|
||||
jsr writeSCCReg ; RTxC, but doing it anyway makes code smaller
|
||||
ply
|
||||
|
||||
lda BaudHighTable,y ; Get high byte
|
||||
iny
|
||||
lda BaudTable,y ; WR13 setup: BRG time constant, high byte
|
||||
ldy #WR_BAUDH_CTRL
|
||||
jsr writeSCCReg
|
||||
|
||||
ldy CurClockSource ; WR14 setup: BRG enabling
|
||||
lda BrgEnabled,y
|
||||
ldy #WR_MISC_CTRL ; Time to turn this thing on
|
||||
lda #MISC_CTRL_RATE_GEN_ON
|
||||
jsr writeSCCReg
|
||||
|
||||
ldy #SER_PARAMS::DATABITS
|
||||
lda (ptr1),y ; Data bits
|
||||
ldy #SER_PARAMS::DATABITS ; WR3 setup: RX data bits
|
||||
lda (ptr1),y
|
||||
tay
|
||||
lda RxBitTable,y ; Data bits for RX
|
||||
ora #RX_CTRL_ON ; and turn RX on
|
||||
lda RxBitTable,y
|
||||
ora #RX_CTRL_ON ; and turn receiver on
|
||||
|
||||
phy
|
||||
ldy #WR_RX_CTRL
|
||||
jsr writeSCCReg
|
||||
jsr writeSCCReg ; End of WR3 setup
|
||||
ply
|
||||
|
||||
lda TxBitTable,y ; Data bits for TX
|
||||
ora #TX_CTRL_ON ; and turn TX on
|
||||
and #TX_DTR_ON
|
||||
lda TxBitTable,y ; WR5 setup: TX data bits
|
||||
ora #TX_CTRL_ON ; and turn transmitter on
|
||||
and #TX_DTR_ON ; and turn DTR on
|
||||
|
||||
sta RtsOff ; Save value for flow control
|
||||
|
||||
ora #TX_RTS_ON
|
||||
ora #TX_RTS_ON ; and turn RTS on
|
||||
|
||||
ldy #WR_TX_CTRL
|
||||
jsr writeSCCReg
|
||||
jsr writeSCCReg ; End of WR5 setup
|
||||
|
||||
ldy #WR_IRQ_CTRL
|
||||
ldy #WR_IRQ_CTRL ; WR15 setup: IRQ
|
||||
lda #IRQ_CLEANUP_EIRQ
|
||||
jsr writeSCCReg
|
||||
|
||||
ldy #WR_INIT_CTRL ; Clear ext status (write twice)
|
||||
ldy #WR_INIT_CTRL ; WR0 setup: clear existing IRQs
|
||||
lda #INIT_CTRL_CLEAR_EIRQ
|
||||
jsr writeSCCReg
|
||||
jsr writeSCCReg ; Clear (write twice)
|
||||
jsr writeSCCReg
|
||||
|
||||
ldy #WR_TX_RX_MODE_CTRL ; Activate RX IRQ
|
||||
ldy #WR_TX_RX_MODE_CTRL ; WR1 setup: Activate RX IRQ
|
||||
lda #TX_RX_MODE_RXIRQ
|
||||
jsr writeSCCReg
|
||||
|
||||
lda SCCBREG ; Activate master IRQ
|
||||
lda SCCBREG ; WR9 setup: Activate master IRQ
|
||||
ldy #WR_MASTER_IRQ_RST
|
||||
lda #MASTER_IRQ_SET
|
||||
jsr writeSCCReg
|
||||
@ -475,14 +490,7 @@ BaudOK:
|
||||
lda SER_FLAG ; Get SerFlag's current value
|
||||
sta SerFlagOrig ; and save it
|
||||
|
||||
cpx #CHANNEL_B
|
||||
bne IntA
|
||||
IntB:
|
||||
ora #SER_FLAG_CH_B ; Inform firmware we want channel B IRQs
|
||||
bra StoreFlag
|
||||
IntA:
|
||||
ora #SER_FLAG_CH_A ; Inform firmware we want channel A IRQs
|
||||
StoreFlag:
|
||||
ora ChanIrqMask,x ; Tell firmware which channel IRQs we want
|
||||
sta SER_FLAG
|
||||
|
||||
ldy #$01 ; Mark port opened
|
||||
|
@ -121,7 +121,7 @@ BaudTable: ; Table used to translate RS232 baudrate param
|
||||
.byte $0F ; SER_BAUD_19200
|
||||
.byte $FF ; SER_BAUD_38400
|
||||
.byte $FF ; SER_BAUD_57600
|
||||
.byte $FF ; SER_BAUD_115200
|
||||
.byte $00 ; SER_BAUD_115200
|
||||
.byte $FF ; SER_BAUD_230400
|
||||
|
||||
BitTable: ; Table used to translate RS232 databits param
|
||||
@ -302,6 +302,7 @@ HandshakeOK:
|
||||
lda (ptr1),y ; Baudrate index
|
||||
tay
|
||||
lda BaudTable,y ; Get 6551 value
|
||||
sta tmp2 ; Backup for IRQ setting
|
||||
bpl BaudOK ; Check that baudrate is supported
|
||||
|
||||
lda #SER_ERR_BAUD_UNAVAIL
|
||||
@ -332,8 +333,13 @@ BaudOK: sta tmp1
|
||||
|
||||
ora #%00000001 ; Set DTR active
|
||||
sta RtsOff ; Store value to easily handle flow control later
|
||||
ora #%00001000 ; Enable receive interrupts (RTS low)
|
||||
sta ACIA_CMD,x
|
||||
|
||||
ora #%00001010 ; Disable interrupts and set RTS low
|
||||
|
||||
ldy tmp2 ; Don't enable IRQs if 115200bps
|
||||
beq :+
|
||||
and #%11111101 ; Enable receive IRQs
|
||||
: sta ACIA_CMD,x
|
||||
|
||||
; Done
|
||||
stx Index ; Mark port as open
|
||||
|
9
libsrc/apple2/uppercasemask.s
Normal file
9
libsrc/apple2/uppercasemask.s
Normal file
@ -0,0 +1,9 @@
|
||||
;
|
||||
; Oliver Schmidt, 2024-08-06
|
||||
;
|
||||
|
||||
.export uppercasemask
|
||||
|
||||
.data
|
||||
|
||||
uppercasemask: .byte $DF ; Convert to uppercase
|
@ -7,6 +7,9 @@
|
||||
.export _write
|
||||
.import rwprolog, rwcommon, rwepilog
|
||||
.import COUT
|
||||
.ifndef __APPLE2ENH__
|
||||
.import uppercasemask
|
||||
.endif
|
||||
|
||||
.include "zeropage.inc"
|
||||
.include "errno.inc"
|
||||
@ -84,7 +87,7 @@ next: lda (ptr1),y
|
||||
.ifndef __APPLE2ENH__
|
||||
cmp #$E0 ; Test for lowercase
|
||||
bcc output
|
||||
and #$DF ; Convert to uppercase
|
||||
and uppercasemask
|
||||
.endif
|
||||
output: jsr COUT ; Preserves X and Y
|
||||
|
||||
|
@ -53,13 +53,20 @@ JOY_COUNT = 2 ; Number of joysticks we support
|
||||
; Must return an JOY_ERR_xx code in a/x.
|
||||
;
|
||||
|
||||
PB2 = $04 ; Joystick 0
|
||||
PB4 = $10 ; Joystick 1
|
||||
|
||||
INSTALL:
|
||||
; Assume 7800 2-button controller, can change
|
||||
; to 2600 1-button later
|
||||
lda #$14
|
||||
sta CTLSWB ; enable 2-button 7800 controller 1: set pin 6 to output
|
||||
lda #(PB2 | PB4)
|
||||
; enable 2-button 7800 controllers on both ports
|
||||
; by setting PB2 and PB4 to output
|
||||
sta CTLSWB
|
||||
; enable 2-button 7800 controllers by setting
|
||||
; the outputs to 0; (INPT4 and INPT5) high
|
||||
ldy #$00
|
||||
sty SWCHB ; enable 2-button 7800 controller 2: pull pin 6 (INPT4) high
|
||||
sty SWCHB
|
||||
|
||||
reset:
|
||||
lda #JOY_ERR_OK
|
||||
@ -88,6 +95,28 @@ COUNT:
|
||||
; ------------------------------------------------------------------------
|
||||
; READ: Read a particular joystick passed in A for 2 fire buttons.
|
||||
|
||||
readdualbuttons0:
|
||||
ldy #0 ; ........
|
||||
bit INPT0 ; Check for right button
|
||||
bpl L1
|
||||
ldy #2 ; ......2.
|
||||
L1: bit INPT1 ; Check for left button
|
||||
bpl L2
|
||||
iny ; ......21
|
||||
L2: tya
|
||||
rts
|
||||
|
||||
readdualbuttons1:
|
||||
ldy #0 ; ........
|
||||
bit INPT2 ; Check for right button
|
||||
bpl L1
|
||||
ldy #2 ; ......2.
|
||||
L3: bit INPT3 ; Check for left button
|
||||
bpl L2
|
||||
iny ; ......21
|
||||
L4: tya
|
||||
rts
|
||||
|
||||
readbuttons:
|
||||
; Y has joystick of interest 0/1
|
||||
; return value:
|
||||
@ -97,42 +126,48 @@ readbuttons:
|
||||
; $03: both buttons
|
||||
; preserves X
|
||||
tya
|
||||
beq L5
|
||||
beq readbuttons0
|
||||
readbuttons1:
|
||||
; Joystick 1 processing
|
||||
; 7800 joystick 1 buttons
|
||||
ldy #0 ; ........
|
||||
bit INPT2 ; Check for right button
|
||||
bpl L1
|
||||
ldy #2 ; ......2.
|
||||
L1: bit INPT3 ;Check for left button
|
||||
bpl L2
|
||||
iny ; ......21
|
||||
L2: tya
|
||||
bne L4 ; 7800 mode joystick worked
|
||||
; 2600 Joystick 1
|
||||
; Start by checking for single button 2600 joystick
|
||||
bit INPT5
|
||||
bmi L4
|
||||
L3: iny ; .......1
|
||||
lda #0 ; Fallback to 2600 joystick mode
|
||||
sta CTLSWB
|
||||
L4: tya ; ......21
|
||||
bpl singlebtn1detected
|
||||
jmp readdualbuttons1
|
||||
singlebtn1detected:
|
||||
; Single button joystick detected but could be dual
|
||||
jsr readdualbuttons1
|
||||
bne L5 ; It was a dual button press
|
||||
; It was a single button press
|
||||
bit INPT5
|
||||
bmi L5
|
||||
iny ; .......1
|
||||
lda #PB4 ; Joystick 1 is a single button unit
|
||||
clc
|
||||
adc SWCHB
|
||||
sta SWCHB ; Cut power from the dual button circuit
|
||||
L5: tya ; ......21
|
||||
rts
|
||||
|
||||
L5: ; Joystick 0 processing
|
||||
; 7800 joystick 0 buttons
|
||||
ldy #0 ; ........
|
||||
bit INPT0 ; Check for right button
|
||||
bpl L6
|
||||
ldy #2 ; ......2.
|
||||
L6: bit INPT1 ;Check for left button
|
||||
bpl L7
|
||||
iny ; ......21
|
||||
L7: tya
|
||||
bne L4 ; 7800 mode joystick worked
|
||||
; 2600 Joystick 0
|
||||
readbuttons0:
|
||||
; Joystick 0 processing
|
||||
; Start by checking for single button 2600 joystick
|
||||
bit INPT4
|
||||
bmi L4
|
||||
bpl L3
|
||||
bpl singlebtn0detected
|
||||
jmp readdualbuttons0
|
||||
singlebtn0detected:
|
||||
; Single button joystick detected but could be dual
|
||||
jsr readdualbuttons0
|
||||
bne L6 ; It was a dual button press
|
||||
; It was a single button press
|
||||
bit INPT4
|
||||
bmi L6
|
||||
iny ; .......1
|
||||
lda #PB2 ; Joystick 0 is a single button unit
|
||||
clc
|
||||
adc SWCHB
|
||||
sta SWCHB ; Cut power from the dual button circuit
|
||||
L6: tya ; ......21
|
||||
rts
|
||||
|
||||
READ:
|
||||
tay ; Store joystick 0/1 in Y
|
||||
|
18
libsrc/atmos/waitvsync.s
Normal file
18
libsrc/atmos/waitvsync.s
Normal file
@ -0,0 +1,18 @@
|
||||
;
|
||||
; Written by Stefan Haubenthal <polluks@sdf.org>, requires VSync hack
|
||||
;
|
||||
; void waitvsync (void);
|
||||
;
|
||||
|
||||
.export _waitvsync
|
||||
|
||||
.include "atmos.inc"
|
||||
|
||||
.proc _waitvsync
|
||||
|
||||
lda #%00010000 ; CB1
|
||||
wait: and VIA::PRA2
|
||||
bne wait
|
||||
rts
|
||||
|
||||
.endproc
|
@ -23,8 +23,8 @@ _waitvsync:
|
||||
|
||||
@c80:
|
||||
;FIXME: do we have to switch banks?
|
||||
lda #$20
|
||||
@l3:
|
||||
lda VDC_INDEX
|
||||
and #$20
|
||||
and VDC_INDEX
|
||||
beq @l3
|
||||
rts
|
||||
|
22
libsrc/common/stpcpy.s
Normal file
22
libsrc/common/stpcpy.s
Normal file
@ -0,0 +1,22 @@
|
||||
;
|
||||
; Colin Leroy-Mira, 4 Sept. 2024
|
||||
;
|
||||
; char* stpcpy (char* dest, const char* src);
|
||||
;
|
||||
|
||||
.export _stpcpy
|
||||
.import _strcpy
|
||||
|
||||
.importzp tmp1, ptr2
|
||||
|
||||
_stpcpy:
|
||||
jsr _strcpy
|
||||
|
||||
ldx ptr2+1 ; Load dest pointer's last high byte
|
||||
tya ; Get the last offset strcpy wrote to
|
||||
|
||||
clc
|
||||
adc ptr2 ; Add to low byte value
|
||||
bcc :+
|
||||
inx
|
||||
: rts ; Return pointer to dest's terminator
|
95
libsrc/common/strcasestr.s
Normal file
95
libsrc/common/strcasestr.s
Normal file
@ -0,0 +1,95 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 11.12.1998
|
||||
;
|
||||
; char* strcasestr (const char* haystack, const char* needle);
|
||||
;
|
||||
|
||||
.export _strcasestr
|
||||
.import popptr1, return0, tolowerdirect
|
||||
.importzp ptr1, ptr2, ptr3, ptr4, tmp1, tmp2, tmp3, tmp4
|
||||
.include "ctype.inc"
|
||||
|
||||
.segment "LOWCODE"
|
||||
|
||||
_strcasestr:
|
||||
sta ptr2 ; Save needle
|
||||
stx ptr2+1
|
||||
sta ptr4 ; Setup temp copy for later
|
||||
|
||||
jsr popptr1 ; Get haystack to ptr1
|
||||
|
||||
; If needle is empty, return haystack
|
||||
|
||||
; ldy #$00 Y=0 guaranteed by popptr1
|
||||
lda (ptr2),y ; Get first byte of needle
|
||||
beq @Found ; Needle is empty --> we're done
|
||||
|
||||
; Search for the beginning of the string (this is not an optimal search
|
||||
; strategy [in fact, it's pretty dumb], but it's simple to implement).
|
||||
|
||||
jsr tolowerdirect ; Lowercase
|
||||
sta tmp1 ; Save start of needle
|
||||
@L1: lda (ptr1),y ; Get next char from haystack
|
||||
beq @NotFound ; Jump if end
|
||||
|
||||
jsr tolowerdirect ; Lowercase
|
||||
cmp tmp1 ; Start of needle found?
|
||||
beq @L2 ; Jump if so
|
||||
iny ; Next char
|
||||
bne @L1
|
||||
inc ptr1+1 ; Bump high byte
|
||||
bne @L1 ; Branch always
|
||||
|
||||
; We found the start of needle in haystack
|
||||
|
||||
@L2: tya ; Get offset
|
||||
clc
|
||||
adc ptr1
|
||||
sta ptr1 ; Make ptr1 point to start
|
||||
bcc @L3
|
||||
inc ptr1+1
|
||||
|
||||
; ptr1 points to the start of needle in haystack now. Setup temporary pointers for the
|
||||
; search. The low byte of ptr4 is already set.
|
||||
|
||||
@L3: sta ptr3
|
||||
lda ptr1+1
|
||||
sta ptr3+1
|
||||
lda ptr2+1
|
||||
sta ptr4+1
|
||||
ldy #1 ; First char is identical, so start on second
|
||||
|
||||
; Do the compare
|
||||
|
||||
@L4: lda (ptr4),y ; Get char from needle
|
||||
beq @Found ; Jump if end of needle (-> found)
|
||||
|
||||
jsr tolowerdirect ; Lowercase
|
||||
sta tmp2
|
||||
|
||||
lda (ptr3),y ; Compare with haystack
|
||||
|
||||
jsr tolowerdirect ; Lowercase
|
||||
cmp tmp2
|
||||
bne @L5 ; Jump if not equal
|
||||
iny ; Next char
|
||||
bne @L4
|
||||
inc ptr3+1
|
||||
inc ptr4+1 ; Bump hi byte of pointers
|
||||
bne @L4 ; Next char (branch always)
|
||||
|
||||
; The strings did not compare equal, search next start of needle
|
||||
|
||||
@L5: ldy #1 ; Start after this char
|
||||
bne @L1 ; Branch always
|
||||
|
||||
; We found the start of needle
|
||||
|
||||
@Found: lda ptr1
|
||||
ldx ptr1+1
|
||||
rts
|
||||
|
||||
; We reached end of haystack without finding needle
|
||||
|
||||
@NotFound:
|
||||
jmp return0 ; return NULL
|
@ -25,6 +25,9 @@ L1: lda (ptr1),y
|
||||
inc ptr2+1
|
||||
bne L1
|
||||
|
||||
L9: lda ptr2 ; X still contains high byte
|
||||
rts
|
||||
L9: lda ptr2 ; X still contains dest's original high byte
|
||||
|
||||
; On exit, we want AX to be dest (as this is what strcpy returns).
|
||||
; We also want (ptr2),y to still point to dest's terminator, as this
|
||||
; is used by stpcpy().
|
||||
rts
|
||||
|
@ -82,14 +82,3 @@ _strstr:
|
||||
lda #$00 ; return NULL
|
||||
tax
|
||||
rts
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
.export _time
|
||||
|
||||
.import decsp1, ldeaxi
|
||||
.import pusha, ldeaxi
|
||||
.importzp ptr1, sreg, tmp1, tmp2
|
||||
|
||||
.include "time.inc"
|
||||
@ -22,54 +22,50 @@
|
||||
|
||||
; Get the time (machine dependent)
|
||||
|
||||
jsr decsp1
|
||||
.assert timespec::tv_sec = 0, error
|
||||
lda #CLOCK_REALTIME
|
||||
jsr pusha
|
||||
lda #<time
|
||||
ldx #>time
|
||||
jsr _clock_gettime
|
||||
sta tmp2
|
||||
lda #<time
|
||||
ldx #>time
|
||||
.assert timespec::tv_sec = 0, error
|
||||
jsr ldeaxi
|
||||
sta tmp1 ; Save low byte of result
|
||||
|
||||
; _clock_gettime returns 0 on success and -1 on error. Check that.
|
||||
|
||||
inx ; Did _clock_gettime return -1?
|
||||
bne @L2 ; Jump if not
|
||||
|
||||
; We had an error so invalidate time. A contains $FF.
|
||||
|
||||
ldy #3
|
||||
@L1: sta time,y
|
||||
dey
|
||||
bpl @L1
|
||||
|
||||
; Restore timep and check if it is NULL
|
||||
|
||||
pla
|
||||
@L2: pla
|
||||
sta ptr1+1
|
||||
pla
|
||||
sta ptr1 ; Restore timep
|
||||
ora ptr1+1 ; timep == 0?
|
||||
beq @L1
|
||||
beq @L4
|
||||
|
||||
; timep is not NULL, store the result there
|
||||
|
||||
ldy #3
|
||||
lda sreg+1
|
||||
@L3: lda time,y
|
||||
sta (ptr1),y
|
||||
dey
|
||||
lda sreg
|
||||
sta (ptr1),y
|
||||
dey
|
||||
txa
|
||||
sta (ptr1),y
|
||||
dey
|
||||
lda tmp1
|
||||
sta (ptr1),y
|
||||
bpl @L3
|
||||
|
||||
; If the result is != 0, return -1
|
||||
; Load the final result.
|
||||
|
||||
@L1: lda tmp2
|
||||
beq @L2
|
||||
|
||||
tax
|
||||
sta sreg
|
||||
@L4: lda time+3
|
||||
sta sreg+1
|
||||
rts
|
||||
|
||||
; Reload the low byte of the result and return
|
||||
|
||||
@L2: lda tmp1
|
||||
lda time+2
|
||||
sta sreg
|
||||
ldx time+1
|
||||
lda time
|
||||
rts
|
||||
|
||||
.endproc
|
||||
|
@ -10,19 +10,20 @@
|
||||
; int tolower (int c);
|
||||
;
|
||||
|
||||
.export _tolower
|
||||
.export _tolower, tolowerdirect
|
||||
.include "ctype.inc"
|
||||
.import ctypemaskdirect
|
||||
|
||||
_tolower:
|
||||
cpx #$00 ; out of range?
|
||||
bne @L2 ; if so, return the argument unchanged
|
||||
tay ; save char
|
||||
bne out ; if so, return the argument unchanged
|
||||
tolowerdirect:
|
||||
pha ; save char
|
||||
jsr ctypemaskdirect ; get character classification
|
||||
and #CT_UPPER ; upper case char?
|
||||
beq @L1 ; jump if no
|
||||
tya ; restore char
|
||||
pla ; restore char
|
||||
adc #<('a'-'A') ; make lower case char (ctypemaskdirect ensures carry clear)
|
||||
rts
|
||||
@L1: tya ; restore char
|
||||
@L2: rts
|
||||
@L1: pla ; restore char
|
||||
out: rts
|
||||
|
675
libsrc/cx16/tgi/cx640p1.s
Normal file
675
libsrc/cx16/tgi/cx640p1.s
Normal file
@ -0,0 +1,675 @@
|
||||
;
|
||||
; Graphics driver for the 640 pixels across, 480 pixels down, 2 color mode
|
||||
; on the Commander X16
|
||||
;
|
||||
; 2024-06-11, Scott Hutter
|
||||
; Based on code by Greg King
|
||||
;
|
||||
|
||||
.include "zeropage.inc"
|
||||
|
||||
.include "tgi-kernel.inc"
|
||||
.include "tgi-error.inc"
|
||||
|
||||
.include "cbm_kernal.inc"
|
||||
.include "cx16.inc"
|
||||
|
||||
.macpack generic
|
||||
.macpack module
|
||||
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; Header. Includes jump table and constants.
|
||||
|
||||
module_header _cx640p1_tgi ; 640 pixels across, 1 pixel per bit
|
||||
|
||||
; First part of the header is a structure that has a signature,
|
||||
; and defines the capabilities of the driver.
|
||||
|
||||
.byte $74, $67, $69 ; ASCII "tgi"
|
||||
.byte TGI_API_VERSION ; TGI API version number
|
||||
.addr $0000 ; Library reference
|
||||
.word 640 ; X resolution
|
||||
.word 480 ; Y resolution
|
||||
.byte 2 ; Number of drawing colors
|
||||
.byte 0 ; Number of screens available
|
||||
.byte 8 ; System font X size
|
||||
.byte 8 ; System font Y size
|
||||
.word $0100 ; Aspect ratio (based on VGA display)
|
||||
.byte 0 ; TGI driver flags
|
||||
|
||||
; Next, comes the jump table. Currently, all entries must be valid,
|
||||
; and may point to an RTS for test versions (function not implemented).
|
||||
|
||||
.addr INSTALL
|
||||
.addr UNINSTALL
|
||||
.addr INIT
|
||||
.addr DONE
|
||||
.addr GETERROR
|
||||
.addr CONTROL
|
||||
.addr CLEAR
|
||||
.addr SETVIEWPAGE
|
||||
.addr SETDRAWPAGE
|
||||
.addr SETCOLOR
|
||||
.addr SETPALETTE
|
||||
.addr GETPALETTE
|
||||
.addr GETDEFPALETTE
|
||||
.addr SETPIXEL
|
||||
.addr GETPIXEL
|
||||
.addr LINE
|
||||
.addr BAR
|
||||
.addr TEXTSTYLE
|
||||
.addr OUTTEXT
|
||||
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; Constant
|
||||
|
||||
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; Data.
|
||||
|
||||
; Variables mapped to the zero page segment variables. Some of these are
|
||||
; used for passing parameters to the driver.
|
||||
|
||||
X1 = ptr1
|
||||
Y1 = ptr2
|
||||
X2 = ptr3
|
||||
Y2 = ptr4
|
||||
|
||||
ADDR = tmp1 ; ADDR+1,2,3
|
||||
|
||||
TEMP = tmp3
|
||||
TEMP2 = tmp4 ; HORLINE
|
||||
TEMP3 = sreg ; HORLINE
|
||||
|
||||
|
||||
; Absolute variables used in the code
|
||||
|
||||
.bss
|
||||
|
||||
; The colors are indicies into a TGI palette. The TGI palette is indicies into
|
||||
; VERA's palette. Vera's palette is a table of Red, Green, and Blue levels.
|
||||
; The first 16 RGB elements mimic the Commodore 64's colors.
|
||||
|
||||
SCRBASE: .res 1 ; High byte of screen base
|
||||
BITMASK: .res 1 ; $00 = clear, $FF = set pixels
|
||||
|
||||
defpalette: .res 2
|
||||
palette: .res 2
|
||||
|
||||
color: .res 1 ; Stroke and fill index
|
||||
text_mode: .res 1 ; Old text mode
|
||||
|
||||
tempX: .res 2
|
||||
tempY: .res 2
|
||||
ERR2: .res 1
|
||||
ERR: .res 1
|
||||
SY: .res 1
|
||||
SX: .res 1
|
||||
DY: .res 1
|
||||
DX: .res 1
|
||||
CURRENT_Y: .res 2
|
||||
CURRENT_X: .res 2
|
||||
|
||||
.data
|
||||
|
||||
ERROR: .byte TGI_ERR_OK ; Error code
|
||||
|
||||
|
||||
; Constants and tables
|
||||
|
||||
.rodata
|
||||
|
||||
veracolors:
|
||||
col_black: .byte %00000000, %00000000
|
||||
col_white: .byte %11111111, %00001111
|
||||
col_red: .byte %00000000, %00001000
|
||||
col_cyan: .byte %11111110, %00001010
|
||||
col_purple: .byte %01001100, %00001100
|
||||
col_green: .byte %11000101, %00000000
|
||||
col_blue: .byte %00001010, %00000000
|
||||
col_yellow: .byte %11100111, %00001110
|
||||
col_orange: .byte %10000101, %00001101
|
||||
col_brown: .byte %01000000, %00000110
|
||||
col_lred: .byte %01110111, %00001111
|
||||
col_gray1: .byte %00110011, %00000011
|
||||
col_gray2: .byte %01110111, %00000111
|
||||
col_lgreen: .byte %11110110, %00001010
|
||||
col_lblue: .byte %10001111, %00000000
|
||||
col_gray3: .byte %10111011, %00001011
|
||||
|
||||
; Bit masks for setting pixels
|
||||
bitMasks1:
|
||||
.byte %10000000, %01000000, %00100000, %00010000
|
||||
.byte %00001000, %00000100, %00000010, %00000001
|
||||
bitMasks2:
|
||||
.byte %01111111, %10111111, %11011111, %11101111
|
||||
.byte %11110111, %11111011, %11111101, %11111110
|
||||
|
||||
|
||||
.code
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; INSTALL routine. Is called after the driver is loaded into memory. May
|
||||
; initialize anything that has to be done just once. Is probably empty
|
||||
; most of the time.
|
||||
;
|
||||
; Must set an error code: NO
|
||||
|
||||
INSTALL:
|
||||
; Create the default palette.
|
||||
lda #$00
|
||||
sta defpalette
|
||||
lda #$01
|
||||
sta defpalette+1
|
||||
|
||||
; Fall through.
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; UNINSTALL routine. Is called before the driver is removed from memory. May
|
||||
; clean up anything done by INSTALL, but is probably empty most of the time.
|
||||
;
|
||||
; Must set an error code: NO
|
||||
|
||||
UNINSTALL:
|
||||
rts
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; INIT: Changes an already installed device from text mode to graphics
|
||||
; mode.
|
||||
; Note that INIT/DONE may be called multiple times while the driver
|
||||
; is loaded, while INSTALL is called only once; so, any code that is needed
|
||||
; to initiate variables and so on must go here. Setting the palette is not
|
||||
; needed because that is called by the graphics kernel later.
|
||||
; The graphics kernel never will call INIT when a graphics mode already is
|
||||
; active, so there is no need to protect against that.
|
||||
;
|
||||
; Must set an error code: YES
|
||||
|
||||
INIT: stz ERROR ; #TGI_ERR_OK
|
||||
|
||||
; Save the current text mode.
|
||||
|
||||
sec
|
||||
jsr SCREEN_MODE
|
||||
sta text_mode
|
||||
|
||||
; Switch into (640 x 480 x 2 bpp) graphics mode.
|
||||
|
||||
lda #%00000000 ; DCSEL = 0, VRAM port 1
|
||||
sta VERA::CTRL
|
||||
lda #%00100001 ; Disable sprites, layer 1 enable, VGA
|
||||
sta VERA::DISP::VIDEO
|
||||
lda #%00000100 ; Bitmap mode enable
|
||||
sta VERA::L1::CONFIG
|
||||
lda #%00000001 ; Tile width 640
|
||||
sta VERA::L1::TILE_BASE
|
||||
rts
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; DONE: Will be called to switch the graphics device back into text mode.
|
||||
; The graphics kernel never will call DONE when no graphics mode is active,
|
||||
; so there is no need to protect against that.
|
||||
;
|
||||
; Must set an error code: NO
|
||||
|
||||
DONE:
|
||||
jsr CINT
|
||||
lda text_mode
|
||||
clc
|
||||
jmp SCREEN_MODE
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; GETERROR: Return the error code in .A, and clear it.
|
||||
|
||||
GETERROR:
|
||||
lda ERROR
|
||||
stz ERROR
|
||||
rts
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; CONTROL: Platform-/driver-specific entry point.
|
||||
;
|
||||
; Must set an error code: YES
|
||||
|
||||
CONTROL:
|
||||
lda #TGI_ERR_INV_FUNC
|
||||
sta ERROR
|
||||
rts
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; CLEAR: Clear the screen.
|
||||
;
|
||||
; Must set an error code: NO
|
||||
|
||||
CLEAR:
|
||||
.scope inner
|
||||
|
||||
; set up DCSEL=2
|
||||
lda #(2 << 1)
|
||||
sta VERA::CTRL
|
||||
|
||||
; set cache writes
|
||||
lda #$40
|
||||
tsb VERA::DISP::VIDEO ; VERA_FX_CTRL when DCSEL=2
|
||||
|
||||
; set FX cache to all zeroes
|
||||
lda #(6 << 1)
|
||||
sta VERA::CTRL
|
||||
|
||||
lda #$00
|
||||
sta VERA::DISP::VIDEO
|
||||
sta VERA::DISP::HSCALE
|
||||
sta VERA::DISP::VSCALE
|
||||
sta VERA::DISP::FRAME
|
||||
|
||||
stz VERA::CTRL
|
||||
; set address and increment for bitmap area
|
||||
stz VERA::ADDR
|
||||
stz VERA::ADDR + 1
|
||||
lda #$30 ; increment +4
|
||||
sta VERA::ADDR + 2
|
||||
|
||||
ldy #$F0
|
||||
@blank_outer:
|
||||
ldx #$0A
|
||||
@blank_loop:
|
||||
|
||||
.repeat 8
|
||||
stz VERA::DATA0
|
||||
.endrep
|
||||
|
||||
dex
|
||||
bne @blank_loop
|
||||
dey
|
||||
bne @blank_outer
|
||||
|
||||
; set up DCSEL=2
|
||||
lda #(2 << 1)
|
||||
sta VERA::CTRL
|
||||
|
||||
; set FX off (cache write bit 1 -> 0)
|
||||
stz VERA::DISP::VIDEO ; VERA_FX_CTRL when DCSEL=2
|
||||
stz VERA::CTRL
|
||||
|
||||
.endscope
|
||||
rts
|
||||
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; SETVIEWPAGE: Set the visible page. Called with the new page in .A (0..n-1).
|
||||
; The page number already is checked to be valid by the graphics kernel.
|
||||
;
|
||||
; Must set an error code: NO (will be called only if page OK)
|
||||
|
||||
SETVIEWPAGE:
|
||||
|
||||
; Fall through.
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; SETDRAWPAGE: Set the drawable page. Called with the new page in .A (0..n-1).
|
||||
; The page number already is checked to be valid by the graphics kernel.
|
||||
;
|
||||
; Must set an error code: NO (will be called only if page OK)
|
||||
|
||||
SETDRAWPAGE:
|
||||
rts
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; SETPALETTE: Set the palette (not available with all drivers/hardware).
|
||||
; A pointer to the palette is passed in ptr1. Must set an error if palettes
|
||||
; are not supported
|
||||
;
|
||||
; Must set an error code: YES
|
||||
|
||||
SETPALETTE:
|
||||
stz ERROR ; #TGI_ERR_OK
|
||||
ldy #$01 ; Palette size of 2 colors
|
||||
@L1: lda (ptr1),y ; Copy the palette
|
||||
sta palette,y
|
||||
dey
|
||||
bpl @L1
|
||||
|
||||
; set background color from palette color 0
|
||||
lda #$00
|
||||
sta VERA::ADDR
|
||||
lda #$FA
|
||||
sta VERA::ADDR+1
|
||||
lda #$01
|
||||
sta VERA::ADDR+2 ; write color RAM @ $1FA00
|
||||
|
||||
lda palette
|
||||
asl
|
||||
tay
|
||||
lda veracolors,y
|
||||
sta VERA::DATA0
|
||||
|
||||
inc VERA::ADDR ; $1FA01
|
||||
|
||||
lda palette
|
||||
asl
|
||||
tay
|
||||
iny ; second byte of color
|
||||
lda veracolors,y
|
||||
sta VERA::DATA0
|
||||
|
||||
; set foreground color from palette color 1
|
||||
inc VERA::ADDR ; $1FA02
|
||||
|
||||
lda palette+1
|
||||
asl
|
||||
tay
|
||||
lda veracolors,y
|
||||
sta VERA::DATA0
|
||||
|
||||
inc VERA::ADDR ; $1FA03
|
||||
|
||||
lda palette+1
|
||||
asl
|
||||
tay
|
||||
iny ; second byte of color
|
||||
lda veracolors,y
|
||||
sta VERA::DATA0
|
||||
rts
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; SETCOLOR: Set the drawing color (in .A). The new color already is checked
|
||||
; to be in a valid range (0..maxcolor).
|
||||
;
|
||||
; Must set an error code: NO (will be called only if color OK)
|
||||
|
||||
SETCOLOR:
|
||||
tax
|
||||
beq @L1
|
||||
lda #$FF
|
||||
@L1: sta BITMASK
|
||||
stx color
|
||||
rts
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; GETPALETTE: Return the current palette in .XA. Even drivers that cannot
|
||||
; set the palette should return the default palette here, so there's no
|
||||
; way for this function to fail.
|
||||
;
|
||||
; Must set an error code: NO
|
||||
|
||||
GETPALETTE:
|
||||
lda #<palette
|
||||
ldx #>palette
|
||||
rts
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; GETDEFPALETTE: Return the default palette for the driver in .XA. All
|
||||
; drivers should return something reasonable here, even drivers that don't
|
||||
; support palettes, otherwise the caller has no way to determine the colors
|
||||
; of the (not changable) palette.
|
||||
;
|
||||
; Must set an error code: NO (all drivers must have a default palette)
|
||||
|
||||
GETDEFPALETTE:
|
||||
lda #<defpalette
|
||||
ldx #>defpalette
|
||||
rts
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; SETPIXEL: Draw one pixel at X1/Y1 = ptr1/ptr2 with the current drawing
|
||||
; color. The co-ordinates passed to this function never are outside the
|
||||
; visible screen area, so there is no need for clipping inside this function.
|
||||
;
|
||||
; Must set an error code: NO
|
||||
|
||||
SETPIXEL:
|
||||
jsr CALC
|
||||
|
||||
stx TEMP
|
||||
|
||||
lda ADDR
|
||||
ldy ADDR+1
|
||||
ldx #$00
|
||||
|
||||
sta VERA::ADDR
|
||||
sty VERA::ADDR + 1
|
||||
stx VERA::ADDR + 2
|
||||
|
||||
ldx TEMP
|
||||
|
||||
lda BITMASK
|
||||
beq @ahead
|
||||
|
||||
; if BITMASK = $00, white is line color
|
||||
; Set the bit in the byte at VERA_DATA0
|
||||
lda VERA::DATA0 ; Load the byte at memory address
|
||||
ora bitMasks1,X ; OR with the bit mask
|
||||
sta VERA::DATA0 ; Store back the modified byte
|
||||
rts
|
||||
|
||||
@ahead:
|
||||
; if BITMASK = $FF, black is line color
|
||||
lda VERA::DATA0 ; Load the byte at memory address
|
||||
and bitMasks2,X ; OR with the bit mask
|
||||
sta VERA::DATA0 ; Store back the modified byte
|
||||
rts
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; GETPIXEL: Read the color value of a pixel, and return it in .XA. The
|
||||
; co-ordinates passed to this function never are outside the visible screen
|
||||
; area, so there is no need for clipping inside this function.
|
||||
|
||||
GETPIXEL:
|
||||
jsr CALC
|
||||
|
||||
stx TEMP
|
||||
|
||||
lda ADDR
|
||||
ldy ADDR+1
|
||||
ldx #$00
|
||||
|
||||
sta VERA::ADDR
|
||||
sty VERA::ADDR + 1
|
||||
stx VERA::ADDR + 2
|
||||
|
||||
ldx TEMP
|
||||
lda VERA::DATA0 ; Load the byte at memory address
|
||||
and bitMasks1,X
|
||||
|
||||
bne @ahead
|
||||
|
||||
ldx #$00
|
||||
lda #$00
|
||||
rts
|
||||
|
||||
@ahead:
|
||||
ldx #$00
|
||||
lda #$01
|
||||
rts
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; BAR: Draw a filled rectangle with the corners X1/Y1, X2/Y2, where
|
||||
; X1/Y1 = ptr1/ptr2 and X2/Y2 = ptr3/ptr4, using the current drawing color.
|
||||
; Contrary to most other functions, the graphics kernel will sort and clip
|
||||
; the co-ordinates before calling the driver; so on entry, the following
|
||||
; conditions are valid:
|
||||
; X1 <= X2
|
||||
; Y1 <= Y2
|
||||
; (X1 >= 0) && (X1 < XRES)
|
||||
; (X2 >= 0) && (X2 < XRES)
|
||||
; (Y1 >= 0) && (Y1 < YRES)
|
||||
; (Y2 >= 0) && (Y2 < YRES)
|
||||
;
|
||||
; Must set an error code: NO
|
||||
|
||||
BAR:
|
||||
; Initialize tempY with Y1
|
||||
lda Y1
|
||||
sta tempY
|
||||
lda Y1+1
|
||||
sta tempY+1
|
||||
|
||||
@outer_loop:
|
||||
; Compare tempY with Y2
|
||||
lda tempY+1
|
||||
cmp Y2+1
|
||||
bcc @outer_continue ; If tempY high byte < Y2 high byte, continue
|
||||
bne @outer_end ; If tempY high byte > Y2 high byte, end
|
||||
lda tempY
|
||||
cmp Y2
|
||||
bcc @outer_continue ; If tempY low byte < Y2 low byte, continue
|
||||
beq @outer_end ; If tempY low byte = Y2 low byte, end
|
||||
|
||||
@outer_continue:
|
||||
; Initialize tempX with X1
|
||||
lda X1
|
||||
sta tempX
|
||||
lda X1+1
|
||||
sta tempX+1
|
||||
|
||||
@inner_loop:
|
||||
; Compare tempX with X2
|
||||
lda tempX+1
|
||||
cmp X2+1
|
||||
bcc @inner_continue ; If tempX high byte < X2 high byte, continue
|
||||
bne @inner_end ; If tempX high byte > X2 high byte, end
|
||||
lda tempX
|
||||
cmp X2
|
||||
bcc @inner_continue ; If tempX low byte < X2 low byte, continue
|
||||
|
||||
@inner_end:
|
||||
; Increment tempY
|
||||
inc tempY
|
||||
bne @outer_loop ; If no overflow, continue outer loop
|
||||
inc tempY+1 ; If overflow, increment high byte
|
||||
|
||||
@inner_continue:
|
||||
; Call setpixel(tempX, tempY)
|
||||
lda X1
|
||||
pha
|
||||
lda X1+1
|
||||
pha
|
||||
lda Y1
|
||||
pha
|
||||
lda Y1+1
|
||||
pha
|
||||
|
||||
lda tempX
|
||||
ldx tempX+1
|
||||
sta X1
|
||||
stx X1+1
|
||||
|
||||
lda tempY
|
||||
ldx tempY+1
|
||||
sta Y1
|
||||
stx Y1+1
|
||||
|
||||
jsr SETPIXEL
|
||||
|
||||
pla
|
||||
sta Y1+1
|
||||
pla
|
||||
sta Y1
|
||||
pla
|
||||
sta X1+1
|
||||
pla
|
||||
sta X1
|
||||
|
||||
; Increment tempX
|
||||
inc tempX
|
||||
bne @inner_loop_check ; If no overflow, continue
|
||||
inc tempX+1 ; If overflow, increment high byte
|
||||
|
||||
@inner_loop_check:
|
||||
; Compare tempX with X2 again after increment
|
||||
lda tempX+1
|
||||
cmp X2+1
|
||||
bcc @inner_continue ; If tempX high byte < X2 high byte, continue
|
||||
bne @outer_increment ; If tempX high byte > X2 high byte, increment tempY
|
||||
lda tempX
|
||||
cmp X2
|
||||
bcc @inner_continue ; If tempX low byte < X2 low byte, continue
|
||||
|
||||
@outer_increment:
|
||||
; Increment tempY
|
||||
inc tempY
|
||||
bne @outer_loop ; If no overflow, continue outer loop
|
||||
inc tempY+1 ; If overflow, increment high byte
|
||||
|
||||
@outer_end:
|
||||
jmp @done
|
||||
|
||||
@done:
|
||||
rts
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; TEXTSTYLE: Set the style used when calling OUTTEXT. Text scaling in X and Y
|
||||
; directions are passed in .X and .Y, the text direction is passed in .A.
|
||||
;
|
||||
; Must set an error code: NO
|
||||
|
||||
TEXTSTYLE:
|
||||
rts
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; OUTTEXT: Output text at X/Y = ptr1/ptr2 using the current color and the
|
||||
; current text style. The text to output is given as a zero-terminated
|
||||
; string with address in ptr3.
|
||||
;
|
||||
; Must set an error code: NO
|
||||
|
||||
OUTTEXT:
|
||||
rts
|
||||
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; Calculate all variables to plot the pixel at X1/Y1.
|
||||
;------------------------
|
||||
;< X1,Y1 - pixel
|
||||
;> ADDR - address of card
|
||||
;> X - bit number (X1 & 7)
|
||||
CALC:
|
||||
lda Y1+1
|
||||
sta ADDR+1
|
||||
lda Y1
|
||||
asl
|
||||
rol ADDR+1
|
||||
asl
|
||||
rol ADDR+1 ; Y*4
|
||||
clc
|
||||
adc Y1
|
||||
sta ADDR
|
||||
lda Y1+1
|
||||
adc ADDR+1
|
||||
sta ADDR+1 ; Y*4+Y=Y*5
|
||||
lda ADDR
|
||||
asl
|
||||
rol ADDR+1
|
||||
asl
|
||||
rol ADDR+1
|
||||
asl
|
||||
rol ADDR+1
|
||||
asl
|
||||
rol ADDR+1
|
||||
sta ADDR ; Y*5*16=Y*80
|
||||
lda X1+1
|
||||
sta TEMP
|
||||
lda X1
|
||||
lsr TEMP
|
||||
ror
|
||||
lsr TEMP
|
||||
ror
|
||||
lsr TEMP
|
||||
ror
|
||||
clc
|
||||
adc ADDR
|
||||
sta ADDR
|
||||
lda ADDR+1 ; ADDR = Y*80+x/8
|
||||
adc TEMP
|
||||
sta ADDR+1
|
||||
lda ADDR+1
|
||||
lda X1
|
||||
and #7
|
||||
tax
|
||||
rts
|
||||
|
||||
|
||||
.include "../../tgi/tgidrv_line.inc"
|
@ -9,8 +9,7 @@
|
||||
.include "pet.inc"
|
||||
|
||||
_waitvsync:
|
||||
@l1:
|
||||
lda VIA_PB
|
||||
and #%00100000
|
||||
bne @l1
|
||||
lda #%00100000
|
||||
: and VIA_PB
|
||||
bne :-
|
||||
rts
|
||||
|
@ -9,11 +9,21 @@
|
||||
.import __MAIN_START__
|
||||
.import startup
|
||||
|
||||
.macpack cpu
|
||||
|
||||
.segment "EXEHDR"
|
||||
|
||||
.byte $73, $69, $6D, $36, $35 ; 'sim65'
|
||||
.byte 2 ; header version
|
||||
.byte .defined(__SIM65C02__) ; CPU type
|
||||
.if (.cpu .bitand ::CPU_ISET_6502X)
|
||||
.byte 2
|
||||
.elseif (.cpu .bitand ::CPU_ISET_65C02)
|
||||
.byte 1
|
||||
.elseif (.cpu .bitand ::CPU_ISET_6502)
|
||||
.byte 0
|
||||
.else
|
||||
.error Unknow CPU type.
|
||||
.endif
|
||||
.byte sp ; sp address
|
||||
.addr __MAIN_START__ ; load address
|
||||
.addr startup ; reset address
|
||||
|
@ -80,17 +80,19 @@ ifneq ($(filter disk samples.%,$(MAKECMDGOALS)),)
|
||||
C1541 ?= c1541
|
||||
endif
|
||||
|
||||
DISK_c64 = samples.d64
|
||||
DISK_$(SYS) = samples.d64
|
||||
|
||||
EXELIST_c64 = \
|
||||
fire \
|
||||
plasma \
|
||||
nachtm
|
||||
nachtm \
|
||||
hello
|
||||
|
||||
EXELIST_c128 = \
|
||||
fire \
|
||||
plasma \
|
||||
nachtm
|
||||
nachtm \
|
||||
hello
|
||||
|
||||
EXELIST_cbm510 = \
|
||||
fire \
|
||||
@ -101,16 +103,17 @@ EXELIST_cbm610 = \
|
||||
nachtm
|
||||
|
||||
EXELIST_plus4 = \
|
||||
plasma
|
||||
plasma \
|
||||
hello
|
||||
|
||||
EXELIST_c16 = \
|
||||
notavailable
|
||||
hello
|
||||
|
||||
EXELIST_pet = \
|
||||
notavailable
|
||||
|
||||
EXELIST_vic20 = \
|
||||
notavailable
|
||||
hello
|
||||
|
||||
ifneq ($(EXELIST_$(SYS)),)
|
||||
samples: $(EXELIST_$(SYS))
|
||||
@ -135,6 +138,15 @@ plasma: plasma.c
|
||||
$(CL) -t $(SYS) -O -o plasma -m plasma.map plasma.c
|
||||
nachtm: nachtm.c
|
||||
$(CL) -t $(SYS) -O -o nachtm -m nachtm.map nachtm.c
|
||||
hello: hello-asm.s
|
||||
# Use separate assembler ...
|
||||
$(AS) -t $(SYS) hello-asm.s
|
||||
# ... and linker commands ...
|
||||
$(LD) -C $(SYS)-asm.cfg -o hello -m hello-asm.map -u __EXEHDR__ hello-asm.o $(SYS).lib
|
||||
@$(DEL) hello-asm.o 2>$(NULLDEV)
|
||||
# ... or compile & link utility
|
||||
# $(CL) -C $(SYS)-asm.cfg -o hello -m hello-asm.map -u __EXEHDR__ hello-asm.s
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Rule to make a CBM disk with all samples. Needs the c1541 program that comes
|
||||
|
15
samples/cbm/hello-asm.s
Normal file
15
samples/cbm/hello-asm.s
Normal file
@ -0,0 +1,15 @@
|
||||
;
|
||||
; Sample assembly program for Commodore machines
|
||||
;
|
||||
|
||||
.include "cbm_kernal.inc"
|
||||
|
||||
ldx #$00
|
||||
: lda text,x
|
||||
beq out
|
||||
jsr CHROUT
|
||||
inx
|
||||
bne :-
|
||||
out: rts
|
||||
|
||||
text: .asciiz "hello world!"
|
@ -133,24 +133,26 @@ static void SetIfCond (IfDesc* ID, int C)
|
||||
|
||||
|
||||
|
||||
static void ElseClause (IfDesc* ID, const char* Directive)
|
||||
/* Enter an .ELSE clause */
|
||||
static int ElseClause (IfDesc* ID, const char* Directive)
|
||||
/* Enter an .ELSE clause. Return true if this was ok, zero on errors. */
|
||||
{
|
||||
/* Check if we have an open .IF - otherwise .ELSE is not allowed */
|
||||
if (ID == 0) {
|
||||
Error ("Unexpected %s", Directive);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check for a duplicate else, then remember that we had one */
|
||||
if (ID->Flags & ifElse) {
|
||||
/* We already had a .ELSE ! */
|
||||
Error ("Duplicate .ELSE");
|
||||
return 0;
|
||||
}
|
||||
ID->Flags |= ifElse;
|
||||
|
||||
/* Condition is inverted now */
|
||||
ID->Flags ^= ifCond;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@ -226,46 +228,52 @@ void DoConditionals (void)
|
||||
D = GetCurrentIf ();
|
||||
|
||||
/* Allow an .ELSE */
|
||||
ElseClause (D, ".ELSE");
|
||||
if (ElseClause (D, ".ELSE")) {
|
||||
/* Remember the data for the .ELSE */
|
||||
if (D) {
|
||||
ReleaseFullLineInfo (&D->LineInfos);
|
||||
GetFullLineInfo (&D->LineInfos);
|
||||
D->Name = ".ELSE";
|
||||
}
|
||||
|
||||
/* Remember the data for the .ELSE */
|
||||
if (D) {
|
||||
ReleaseFullLineInfo (&D->LineInfos);
|
||||
GetFullLineInfo (&D->LineInfos);
|
||||
D->Name = ".ELSE";
|
||||
/* Calculate the new overall condition */
|
||||
CalcOverallIfCond ();
|
||||
|
||||
/* Skip .ELSE */
|
||||
NextTok ();
|
||||
ExpectSep ();
|
||||
} else {
|
||||
/* Problem with .ELSE, ignore remainder of line */
|
||||
SkipUntilSep ();
|
||||
}
|
||||
|
||||
/* Calculate the new overall condition */
|
||||
CalcOverallIfCond ();
|
||||
|
||||
/* Skip .ELSE */
|
||||
NextTok ();
|
||||
ExpectSep ();
|
||||
break;
|
||||
|
||||
case TOK_ELSEIF:
|
||||
D = GetCurrentIf ();
|
||||
/* Handle as if there was an .ELSE first */
|
||||
ElseClause (D, ".ELSEIF");
|
||||
if (ElseClause (D, ".ELSEIF")) {
|
||||
/* Calculate the new overall if condition */
|
||||
CalcOverallIfCond ();
|
||||
|
||||
/* Calculate the new overall if condition */
|
||||
CalcOverallIfCond ();
|
||||
/* Allocate and prepare a new descriptor */
|
||||
D = AllocIf (".ELSEIF", 0);
|
||||
NextTok ();
|
||||
|
||||
/* Allocate and prepare a new descriptor */
|
||||
D = AllocIf (".ELSEIF", 0);
|
||||
NextTok ();
|
||||
/* Ignore the new condition if we are inside a false .ELSE
|
||||
** branch. This way we won't get any errors about undefined
|
||||
** symbols or similar...
|
||||
*/
|
||||
if (IfCond) {
|
||||
SetIfCond (D, ConstExpression ());
|
||||
ExpectSep ();
|
||||
}
|
||||
|
||||
/* Ignore the new condition if we are inside a false .ELSE
|
||||
** branch. This way we won't get any errors about undefined
|
||||
** symbols or similar...
|
||||
*/
|
||||
if (IfCond) {
|
||||
SetIfCond (D, ConstExpression ());
|
||||
ExpectSep ();
|
||||
/* Get the new overall condition */
|
||||
CalcOverallIfCond ();
|
||||
} else {
|
||||
/* Problem with .ELSEIF, ignore remainder of line */
|
||||
SkipUntilSep ();
|
||||
}
|
||||
|
||||
/* Get the new overall condition */
|
||||
CalcOverallIfCond ();
|
||||
break;
|
||||
|
||||
case TOK_ENDIF:
|
||||
|
@ -156,3 +156,29 @@ void CheckInputStack (void)
|
||||
Error ("Open %s", IStack->Desc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
InputStack RetrieveInputStack (void)
|
||||
/* Retrieve the current input stack. This will also clear it. Used when
|
||||
** including a file. The current input stack is stored together with the old
|
||||
** input file and restored when the file is closed.
|
||||
*/
|
||||
{
|
||||
/* We do not touch the counter so input sources are counted across
|
||||
** includes.
|
||||
*/
|
||||
InputStack S = IStack;
|
||||
IStack = 0;
|
||||
return S;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void RestoreInputStack (InputStack S)
|
||||
/* Restore an old input stack that was retrieved by RetrieveInputStack(). */
|
||||
{
|
||||
CHECK (IStack == 0);
|
||||
IStack = S;
|
||||
}
|
||||
|
||||
|
@ -38,6 +38,17 @@
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* Opaque pointer to an input stack */
|
||||
typedef void* InputStack;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
@ -63,6 +74,15 @@ void CheckInputStack (void);
|
||||
** stuff on the input stack.
|
||||
*/
|
||||
|
||||
InputStack RetrieveInputStack (void);
|
||||
/* Retrieve the current input stack. This will also clear it. Used when
|
||||
** including a file. The current input stack is stored together with the old
|
||||
** input file and restored when the file is closed.
|
||||
*/
|
||||
|
||||
void RestoreInputStack (InputStack S);
|
||||
/* Restore an old input stack that was retrieved by RetrieveInputStack(). */
|
||||
|
||||
|
||||
|
||||
/* End of istack.h */
|
||||
|
@ -707,6 +707,24 @@ static void OneLine (void)
|
||||
NextTok ();
|
||||
}
|
||||
|
||||
/* Handle @-style unnamed labels */
|
||||
if (CurTok.Tok == TOK_ULABEL) {
|
||||
if (CurTok.IVal != 0) {
|
||||
Error ("Invalid unnamed label definition");
|
||||
}
|
||||
ULabDef ();
|
||||
NextTok ();
|
||||
|
||||
/* Skip the colon. If NoColonLabels is enabled, allow labels without
|
||||
** a colon if there is no whitespace before the identifier.
|
||||
*/
|
||||
if (CurTok.Tok == TOK_COLON) {
|
||||
NextTok ();
|
||||
} else if (CurTok.WS || !NoColonLabels) {
|
||||
Error ("':' expected");
|
||||
}
|
||||
}
|
||||
|
||||
/* If the first token on the line is an identifier, check for a macro or
|
||||
** an instruction.
|
||||
*/
|
||||
|
@ -113,6 +113,7 @@ struct CharSource {
|
||||
token_t Tok; /* Last token */
|
||||
int C; /* Last character */
|
||||
int SkipN; /* For '\r\n' line endings, skip '\n\ if next */
|
||||
InputStack IStack; /* Saved input stack */
|
||||
const CharSourceFunctions* Func; /* Pointer to function table */
|
||||
union {
|
||||
InputFile File; /* File data */
|
||||
@ -321,6 +322,9 @@ static void UseCharSource (CharSource* S)
|
||||
S->Tok = CurTok.Tok;
|
||||
S->C = C;
|
||||
|
||||
/* Remember the current input stack */
|
||||
S->IStack = RetrieveInputStack ();
|
||||
|
||||
/* Use the new input source */
|
||||
S->Next = Source;
|
||||
Source = S;
|
||||
@ -347,7 +351,10 @@ static void DoneCharSource (void)
|
||||
|
||||
/* Restore the old token */
|
||||
CurTok.Tok = Source->Tok;
|
||||
C = Source->C;
|
||||
C = Source->C;
|
||||
|
||||
/* Restore the old input source */
|
||||
RestoreInputStack (Source->IStack);
|
||||
|
||||
/* Remember the last stacked input source */
|
||||
S = Source->Next;
|
||||
@ -1124,17 +1131,33 @@ Again:
|
||||
/* Local symbol? */
|
||||
if (C == LocalStart) {
|
||||
|
||||
/* Read the identifier. */
|
||||
ReadIdent ();
|
||||
NextChar ();
|
||||
|
||||
/* Start character alone is not enough */
|
||||
if (SB_GetLen (&CurTok.SVal) == 1) {
|
||||
Error ("Invalid cheap local symbol");
|
||||
goto Again;
|
||||
if (IsIdChar (C)) {
|
||||
/* Read a local identifier */
|
||||
CurTok.Tok = TOK_LOCAL_IDENT;
|
||||
SB_AppendChar (&CurTok.SVal, LocalStart);
|
||||
ReadIdent ();
|
||||
} else {
|
||||
/* Read an unnamed label */
|
||||
CurTok.IVal = 0;
|
||||
CurTok.Tok = TOK_ULABEL;
|
||||
|
||||
if (C == '-' || C == '<') {
|
||||
int PrevC = C;
|
||||
do {
|
||||
--CurTok.IVal;
|
||||
NextChar ();
|
||||
} while (C == PrevC);
|
||||
} else if (C == '+' || C == '>') {
|
||||
int PrevC = C;
|
||||
do {
|
||||
++CurTok.IVal;
|
||||
NextChar ();
|
||||
} while (C == PrevC);
|
||||
}
|
||||
}
|
||||
|
||||
/* A local identifier */
|
||||
CurTok.Tok = TOK_LOCAL_IDENT;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1314,22 +1337,30 @@ CharAgain:
|
||||
break;
|
||||
|
||||
case '-':
|
||||
case '<':
|
||||
{
|
||||
int PrevC = C;
|
||||
CurTok.IVal = 0;
|
||||
do {
|
||||
--CurTok.IVal;
|
||||
NextChar ();
|
||||
} while (C == '-');
|
||||
} while (C == PrevC);
|
||||
CurTok.Tok = TOK_ULABEL;
|
||||
break;
|
||||
}
|
||||
|
||||
case '+':
|
||||
case '>':
|
||||
{
|
||||
int PrevC = C;
|
||||
CurTok.IVal = 0;
|
||||
do {
|
||||
++CurTok.IVal;
|
||||
NextChar ();
|
||||
} while (C == '+');
|
||||
} while (C == PrevC);
|
||||
CurTok.Tok = TOK_ULABEL;
|
||||
break;
|
||||
}
|
||||
|
||||
case '=':
|
||||
NextChar ();
|
||||
@ -1497,7 +1528,7 @@ CharAgain:
|
||||
/* In case of the main file, do not close it, but return EOF. */
|
||||
if (Source && Source->Next) {
|
||||
DoneCharSource ();
|
||||
goto Again;
|
||||
goto Restart;
|
||||
} else {
|
||||
CurTok.Tok = TOK_EOF;
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ typedef enum token_t {
|
||||
TOK_REG, /* Sweet16 R.. register (in sweet16 mode) */
|
||||
|
||||
TOK_ASSIGN, /* := */
|
||||
TOK_ULABEL, /* :++ or :-- */
|
||||
TOK_ULABEL, /* An unnamed label */
|
||||
|
||||
TOK_EQ, /* = */
|
||||
TOK_NE, /* <> */
|
||||
|
@ -107,8 +107,12 @@ ExprNode* ULabRef (int Which)
|
||||
int Index;
|
||||
ULabel* L;
|
||||
|
||||
/* Which can never be 0 */
|
||||
PRECONDITION (Which != 0);
|
||||
/* Which should not be 0 */
|
||||
if (Which == 0) {
|
||||
Error ("Invalid unnamed label reference");
|
||||
/* We must return something valid */
|
||||
return GenCurrentPC();
|
||||
}
|
||||
|
||||
/* Get the index of the referenced label */
|
||||
if (Which > 0) {
|
||||
|
@ -507,34 +507,39 @@ void g_enter (unsigned flags, unsigned argsize)
|
||||
|
||||
|
||||
|
||||
void g_leave (void)
|
||||
void g_leave (int DoCleanup)
|
||||
/* Function epilogue */
|
||||
{
|
||||
/* How many bytes of locals do we have to drop? */
|
||||
unsigned ToDrop = (unsigned) -StackPtr;
|
||||
/* In the main function in cc65 mode nothing has to be dropped because
|
||||
** the program is terminated anyway.
|
||||
*/
|
||||
if (DoCleanup) {
|
||||
/* How many bytes of locals do we have to drop? */
|
||||
unsigned ToDrop = (unsigned) -StackPtr;
|
||||
|
||||
/* If we didn't have a variable argument list, don't call leave */
|
||||
if (funcargs >= 0) {
|
||||
/* If we didn't have a variable argument list, don't call leave */
|
||||
if (funcargs >= 0) {
|
||||
|
||||
/* Drop stackframe if needed */
|
||||
g_drop (ToDrop + funcargs);
|
||||
/* Drop stackframe if needed */
|
||||
g_drop (ToDrop + funcargs);
|
||||
|
||||
} else if (StackPtr != 0) {
|
||||
} else if (StackPtr != 0) {
|
||||
|
||||
/* We've a stack frame to drop */
|
||||
if (ToDrop > 255) {
|
||||
g_drop (ToDrop); /* Inlines the code */
|
||||
AddCodeLine ("jsr leave");
|
||||
} else {
|
||||
AddCodeLine ("ldy #$%02X", ToDrop);
|
||||
AddCodeLine ("jsr leavey");
|
||||
}
|
||||
|
||||
/* We've a stack frame to drop */
|
||||
if (ToDrop > 255) {
|
||||
g_drop (ToDrop); /* Inlines the code */
|
||||
AddCodeLine ("jsr leave");
|
||||
} else {
|
||||
AddCodeLine ("ldy #$%02X", ToDrop);
|
||||
AddCodeLine ("jsr leavey");
|
||||
|
||||
/* Nothing to drop */
|
||||
AddCodeLine ("jsr leave");
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* Nothing to drop */
|
||||
AddCodeLine ("jsr leave");
|
||||
|
||||
}
|
||||
|
||||
/* Add the final rts */
|
||||
|
@ -247,7 +247,7 @@ void g_scale (unsigned flags, long val);
|
||||
void g_enter (unsigned flags, unsigned argsize);
|
||||
/* Function prologue */
|
||||
|
||||
void g_leave (void);
|
||||
void g_leave (int DoCleanup);
|
||||
/* Function epilogue */
|
||||
|
||||
|
||||
|
@ -1128,8 +1128,10 @@ void AddOpHigh (StackOpData* D, opc_t OPC, LoadInfo* LI, int KeepResult)
|
||||
InsertEntry (D, X, D->IP++);
|
||||
}
|
||||
|
||||
/* In both cases, we can remove the load */
|
||||
LI->X.Flags |= LI_REMOVE;
|
||||
/* If this is the right hand side, we can remove the load. */
|
||||
if (LI == &D->Rhs) {
|
||||
LI->X.Flags |= LI_REMOVE;
|
||||
}
|
||||
|
||||
} else {
|
||||
/* opc zphi */
|
||||
|
1048
src/cc65/declare.c
1048
src/cc65/declare.c
File diff suppressed because it is too large
Load Diff
@ -1219,9 +1219,6 @@ static void Primary (ExprDesc* E)
|
||||
/* Is the symbol known? */
|
||||
if (Sym) {
|
||||
|
||||
/* We found the symbol - skip the name token */
|
||||
NextToken ();
|
||||
|
||||
/* Check for illegal symbol types */
|
||||
CHECK ((Sym->Flags & SC_TYPEMASK) != SC_LABEL);
|
||||
if ((Sym->Flags & SC_TYPEMASK) == SC_TYPEDEF) {
|
||||
@ -1230,9 +1227,14 @@ static void Primary (ExprDesc* E)
|
||||
/* Assume an int type to make E valid */
|
||||
E->Flags = E_LOC_STACK | E_RTYPE_LVAL;
|
||||
E->Type = type_int;
|
||||
/* Skip the erroneous token */
|
||||
NextToken ();
|
||||
break;
|
||||
}
|
||||
|
||||
/* Skip the name token */
|
||||
NextToken ();
|
||||
|
||||
/* Mark the symbol as referenced */
|
||||
Sym->Flags |= SC_REF;
|
||||
|
||||
@ -1286,7 +1288,23 @@ static void Primary (ExprDesc* E)
|
||||
** rvalue, too, because we cannot store anything in a function.
|
||||
** So fix the flags depending on the type.
|
||||
*/
|
||||
if (IsTypeArray (E->Type) || IsTypeFunc (E->Type)) {
|
||||
if (IsTypeArray (E->Type)) {
|
||||
ED_AddrExpr (E);
|
||||
} else if (IsTypeFunc (E->Type)) {
|
||||
/* In cc65 mode we cannot call or take the address of
|
||||
** main().
|
||||
*/
|
||||
if (IS_Get (&Standard) == STD_CC65 &&
|
||||
strcmp (Sym->Name, "main") == 0) {
|
||||
/* Adjust the error message depending on a call or an
|
||||
** address operation.
|
||||
*/
|
||||
if (CurTok.Tok == TOK_LPAREN) {
|
||||
Error ("'main' must not be called recursively");
|
||||
} else {
|
||||
Error ("The address of 'main' cannot be taken");
|
||||
}
|
||||
}
|
||||
ED_AddrExpr (E);
|
||||
}
|
||||
|
||||
@ -3272,7 +3290,7 @@ static void parsesub (ExprDesc* Expr)
|
||||
/* The right hand side is constant. Check left hand side. */
|
||||
if (ED_IsQuasiConst (Expr)) {
|
||||
/* We can't do all 'ptr1 - ptr2' constantly at the moment */
|
||||
if (Expr->Sym == Expr2.Sym) {
|
||||
if (ED_GetLoc (Expr) == ED_GetLoc (&Expr2) && Expr->Sym == Expr2.Sym) {
|
||||
Expr->IVal = (Expr->IVal - Expr2.IVal) / rscale;
|
||||
/* Get rid of unneeded flags etc. */
|
||||
ED_MakeConstAbsInt (Expr, Expr->IVal);
|
||||
|
@ -646,11 +646,17 @@ void NewFunc (SymEntry* Func, FuncDesc* D)
|
||||
/* Output the function exit code label */
|
||||
g_defcodelabel (F_GetRetLab (CurrentFunc));
|
||||
|
||||
/* Restore the register variables */
|
||||
F_RestoreRegVars (CurrentFunc);
|
||||
/* Restore the register variables (not necessary for the main function in
|
||||
** cc65 mode)
|
||||
*/
|
||||
int CleanupOnExit = (IS_Get (&Standard) != STD_CC65) ||
|
||||
!F_IsMainFunc (CurrentFunc);
|
||||
if (CleanupOnExit) {
|
||||
F_RestoreRegVars (CurrentFunc);
|
||||
}
|
||||
|
||||
/* Generate the exit code */
|
||||
g_leave ();
|
||||
g_leave (CleanupOnExit);
|
||||
|
||||
/* Emit references to imports/exports */
|
||||
EmitExternals ();
|
||||
|
@ -302,6 +302,13 @@ static unsigned ParsePointerInit (const Type* T)
|
||||
/* Optional opening brace */
|
||||
unsigned BraceCount = OpeningCurlyBraces (0);
|
||||
|
||||
/* We warn if an initializer for a scalar contains braces, because this is
|
||||
** quite unusual and often a sign for some problem in the input.
|
||||
*/
|
||||
if (BraceCount > 0) {
|
||||
Warning ("Braces around scalar initializer");
|
||||
}
|
||||
|
||||
/* Expression */
|
||||
ExprDesc ED = NoCodeConstExpr (hie1);
|
||||
TypeConversion (&ED, T);
|
||||
|
@ -111,15 +111,12 @@ static void ParseRegisterDecl (Declarator* Decl, int Reg)
|
||||
/* Get the size of the variable */
|
||||
unsigned Size = SizeOf (Decl->Type);
|
||||
|
||||
/* Save the current contents of the register variable on stack */
|
||||
F_AllocLocalSpace (CurrentFunc);
|
||||
g_save_regvars (Reg, Size);
|
||||
|
||||
/* Add the symbol to the symbol table. We do that now, because for register
|
||||
** variables the current stack pointer is implicitly used as location for
|
||||
** the save area.
|
||||
/* Check if this is the main function and we are in cc65 mode. If so, we
|
||||
** won't save the old contents of the register variables since in cc65
|
||||
** mode main() may not be called recursively.
|
||||
*/
|
||||
Sym = AddLocalSym (Decl->Ident, Decl->Type, Decl->StorageClass, Reg);
|
||||
int SaveRegVars = (IS_Get (&Standard) != STD_CC65) ||
|
||||
!F_IsMainFunc (CurrentFunc);
|
||||
|
||||
/* Check for an optional initialization */
|
||||
if (CurTok.Tok == TOK_ASSIGN) {
|
||||
@ -127,6 +124,25 @@ static void ParseRegisterDecl (Declarator* Decl, int Reg)
|
||||
/* Skip the '=' */
|
||||
NextToken ();
|
||||
|
||||
/* If the register variable is initialized, the initialization code may
|
||||
** access other already declared variables. This means that we have to
|
||||
** allocate them now.
|
||||
*/
|
||||
F_AllocLocalSpace (CurrentFunc);
|
||||
|
||||
/* Save the current contents of the register variable on stack. This is
|
||||
** not necessary for the main function.
|
||||
*/
|
||||
if (SaveRegVars) {
|
||||
g_save_regvars (Reg, Size);
|
||||
}
|
||||
|
||||
/* Add the symbol to the symbol table. We do that now, because for
|
||||
** register variables the current stack pointer is implicitly used
|
||||
** as location for the save area (maybe unused in case of main()).
|
||||
*/
|
||||
Sym = AddLocalSym (Decl->Ident, Decl->Type, Decl->StorageClass, Reg);
|
||||
|
||||
/* Special handling for compound types */
|
||||
if (IsCompound) {
|
||||
|
||||
@ -173,6 +189,21 @@ static void ParseRegisterDecl (Declarator* Decl, int Reg)
|
||||
|
||||
/* Mark the variable as referenced */
|
||||
Sym->Flags |= SC_REF;
|
||||
} else {
|
||||
|
||||
/* Save the current contents of the register variable on stack. This is
|
||||
** not necessary for the main function.
|
||||
*/
|
||||
if (SaveRegVars) {
|
||||
F_AllocLocalSpace (CurrentFunc);
|
||||
g_save_regvars (Reg, Size);
|
||||
}
|
||||
|
||||
/* Add the symbol to the symbol table. We do that now, because for
|
||||
** register variables the current stack pointer is implicitly used
|
||||
** as location for the save area (maybe unused in case of main()).
|
||||
*/
|
||||
Sym = AddLocalSym (Decl->Ident, Decl->Type, Decl->StorageClass, Reg);
|
||||
}
|
||||
|
||||
/* Cannot allocate a variable of unknown size */
|
||||
|
@ -91,7 +91,7 @@ static void Usage (void)
|
||||
" -Os\t\t\t\tInline some standard functions\n"
|
||||
" -T\t\t\t\tInclude source as comment\n"
|
||||
" -V\t\t\t\tPrint the compiler version number\n"
|
||||
" -W warning[,...]\t\tSuppress warnings\n"
|
||||
" -W [-+]warning[,...]\t\tControl warnings ('-' disables, '+' enables)\n"
|
||||
" -d\t\t\t\tDebug mode\n"
|
||||
" -g\t\t\t\tAdd debug info to object file\n"
|
||||
" -h\t\t\t\tHelp (this text)\n"
|
||||
|
@ -726,7 +726,7 @@ static void PPhieQuest (PPExpr* Expr)
|
||||
PPhieQuest (&Expr3);
|
||||
|
||||
/* Set the result */
|
||||
Expr->IVal = Expr->IVal ? Expr2.IVal != 0 : Expr3.IVal != 0;
|
||||
Expr->IVal = Expr->IVal ? Expr2.IVal : Expr3.IVal;
|
||||
|
||||
/* Restore evaluation as before */
|
||||
PPEvaluationEnabled = PPEvaluationEnabledPrev;
|
||||
|
@ -68,70 +68,67 @@ typedef enum {
|
||||
PRAGMA_ALIGN,
|
||||
PRAGMA_ALLOW_EAGER_INLINE,
|
||||
PRAGMA_BSS_NAME,
|
||||
PRAGMA_BSSSEG, /* obsolete */
|
||||
PRAGMA_CHARMAP,
|
||||
PRAGMA_CHECK_STACK,
|
||||
PRAGMA_CHECKSTACK, /* obsolete */
|
||||
PRAGMA_CODE_NAME,
|
||||
PRAGMA_CODESEG, /* obsolete */
|
||||
PRAGMA_CODESIZE,
|
||||
PRAGMA_DATA_NAME,
|
||||
PRAGMA_DATASEG, /* obsolete */
|
||||
PRAGMA_INLINE_STDFUNCS,
|
||||
PRAGMA_LOCAL_STRINGS,
|
||||
PRAGMA_MESSAGE,
|
||||
PRAGMA_OPTIMIZE,
|
||||
PRAGMA_REGISTER_VARS,
|
||||
PRAGMA_REGVARADDR,
|
||||
PRAGMA_REGVARS, /* obsolete */
|
||||
PRAGMA_RODATA_NAME,
|
||||
PRAGMA_RODATASEG, /* obsolete */
|
||||
PRAGMA_SIGNED_CHARS,
|
||||
PRAGMA_SIGNEDCHARS, /* obsolete */
|
||||
PRAGMA_STATIC_LOCALS,
|
||||
PRAGMA_STATICLOCALS, /* obsolete */
|
||||
PRAGMA_WARN,
|
||||
PRAGMA_WRAPPED_CALL,
|
||||
PRAGMA_WRITABLE_STRINGS,
|
||||
PRAGMA_ZPSYM,
|
||||
PRAGMA_COUNT
|
||||
} pragma_t;
|
||||
|
||||
/* Pragma table */
|
||||
static const struct Pragma {
|
||||
const char* Key; /* Keyword */
|
||||
pragma_t Tok; /* Token */
|
||||
} Pragmas[PRAGMA_COUNT] = {
|
||||
} Pragmas[] = {
|
||||
{ "align", PRAGMA_ALIGN },
|
||||
{ "allow-eager-inline", PRAGMA_ALLOW_EAGER_INLINE },
|
||||
{ "allow_eager_inline", PRAGMA_ALLOW_EAGER_INLINE },
|
||||
{ "bss-name", PRAGMA_BSS_NAME },
|
||||
{ "bssseg", PRAGMA_BSSSEG }, /* obsolete */
|
||||
{ "bss_name", PRAGMA_BSS_NAME },
|
||||
{ "charmap", PRAGMA_CHARMAP },
|
||||
{ "check-stack", PRAGMA_CHECK_STACK },
|
||||
{ "checkstack", PRAGMA_CHECKSTACK }, /* obsolete */
|
||||
{ "check_stack", PRAGMA_CHECK_STACK },
|
||||
{ "code-name", PRAGMA_CODE_NAME },
|
||||
{ "codeseg", PRAGMA_CODESEG }, /* obsolete */
|
||||
{ "code_name", PRAGMA_CODE_NAME },
|
||||
{ "codesize", PRAGMA_CODESIZE },
|
||||
{ "data-name", PRAGMA_DATA_NAME },
|
||||
{ "dataseg", PRAGMA_DATASEG }, /* obsolete */
|
||||
{ "data_name", PRAGMA_DATA_NAME },
|
||||
{ "inline-stdfuncs", PRAGMA_INLINE_STDFUNCS },
|
||||
{ "inline_stdfuncs", PRAGMA_INLINE_STDFUNCS },
|
||||
{ "local-strings", PRAGMA_LOCAL_STRINGS },
|
||||
{ "local_strings", PRAGMA_LOCAL_STRINGS },
|
||||
{ "message", PRAGMA_MESSAGE },
|
||||
{ "optimize", PRAGMA_OPTIMIZE },
|
||||
{ "register-vars", PRAGMA_REGISTER_VARS },
|
||||
{ "register_vars", PRAGMA_REGISTER_VARS },
|
||||
{ "regvaraddr", PRAGMA_REGVARADDR },
|
||||
{ "regvars", PRAGMA_REGVARS }, /* obsolete */
|
||||
{ "rodata-name", PRAGMA_RODATA_NAME },
|
||||
{ "rodataseg", PRAGMA_RODATASEG }, /* obsolete */
|
||||
{ "rodata_name", PRAGMA_RODATA_NAME },
|
||||
{ "signed-chars", PRAGMA_SIGNED_CHARS },
|
||||
{ "signedchars", PRAGMA_SIGNEDCHARS }, /* obsolete */
|
||||
{ "signed_chars", PRAGMA_SIGNED_CHARS },
|
||||
{ "static-locals", PRAGMA_STATIC_LOCALS },
|
||||
{ "staticlocals", PRAGMA_STATICLOCALS }, /* obsolete */
|
||||
{ "static_locals", PRAGMA_STATIC_LOCALS },
|
||||
{ "warn", PRAGMA_WARN },
|
||||
{ "wrapped-call", PRAGMA_WRAPPED_CALL },
|
||||
{ "wrapped_call", PRAGMA_WRAPPED_CALL },
|
||||
{ "writable-strings", PRAGMA_WRITABLE_STRINGS },
|
||||
{ "writable_strings", PRAGMA_WRITABLE_STRINGS },
|
||||
{ "zpsym", PRAGMA_ZPSYM },
|
||||
};
|
||||
#define PRAGMA_COUNT (sizeof (Pragmas) / sizeof (Pragmas[0]))
|
||||
|
||||
/* Result of ParsePushPop */
|
||||
typedef enum {
|
||||
@ -402,22 +399,18 @@ static void ApplySegNamePragma (pragma_t Token, int PushPop, const char* Name, u
|
||||
|
||||
switch (Token) {
|
||||
case PRAGMA_CODE_NAME:
|
||||
case PRAGMA_CODESEG:
|
||||
Seg = SEG_CODE;
|
||||
break;
|
||||
|
||||
case PRAGMA_RODATA_NAME:
|
||||
case PRAGMA_RODATASEG:
|
||||
Seg = SEG_RODATA;
|
||||
break;
|
||||
|
||||
case PRAGMA_DATA_NAME:
|
||||
case PRAGMA_DATASEG:
|
||||
Seg = SEG_DATA;
|
||||
break;
|
||||
|
||||
case PRAGMA_BSS_NAME:
|
||||
case PRAGMA_BSSSEG:
|
||||
Seg = SEG_BSS;
|
||||
break;
|
||||
|
||||
@ -933,9 +926,6 @@ static void ParsePragmaString (void)
|
||||
FlagPragma (PES_STMT, Pragma, &B, &EagerlyInlineFuncs);
|
||||
break;
|
||||
|
||||
case PRAGMA_BSSSEG:
|
||||
Warning ("#pragma bssseg is obsolete, please use #pragma bss-name instead");
|
||||
/* FALLTHROUGH */
|
||||
case PRAGMA_BSS_NAME:
|
||||
/* TODO: PES_STMT or even PES_EXPR (PES_DECL) maybe? */
|
||||
SegNamePragma (PES_FUNC, PRAGMA_BSS_NAME, &B);
|
||||
@ -945,17 +935,11 @@ static void ParsePragmaString (void)
|
||||
CharMapPragma (PES_IMM, &B);
|
||||
break;
|
||||
|
||||
case PRAGMA_CHECKSTACK:
|
||||
Warning ("#pragma checkstack is obsolete, please use #pragma check-stack instead");
|
||||
/* FALLTHROUGH */
|
||||
case PRAGMA_CHECK_STACK:
|
||||
/* TODO: PES_SCOPE maybe? */
|
||||
FlagPragma (PES_FUNC, Pragma, &B, &CheckStack);
|
||||
break;
|
||||
|
||||
case PRAGMA_CODESEG:
|
||||
Warning ("#pragma codeseg is obsolete, please use #pragma code-name instead");
|
||||
/* FALLTHROUGH */
|
||||
case PRAGMA_CODE_NAME:
|
||||
/* PES_FUNC is the only sensible option so far */
|
||||
SegNamePragma (PES_FUNC, PRAGMA_CODE_NAME, &B);
|
||||
@ -966,9 +950,6 @@ static void ParsePragmaString (void)
|
||||
IntPragma (PES_STMT, Pragma, &B, &CodeSizeFactor, 10, 1000);
|
||||
break;
|
||||
|
||||
case PRAGMA_DATASEG:
|
||||
Warning ("#pragma dataseg is obsolete, please use #pragma data-name instead");
|
||||
/* FALLTHROUGH */
|
||||
case PRAGMA_DATA_NAME:
|
||||
/* TODO: PES_STMT or even PES_EXPR (PES_DECL) maybe? */
|
||||
SegNamePragma (PES_FUNC, PRAGMA_DATA_NAME, &B);
|
||||
@ -999,33 +980,21 @@ static void ParsePragmaString (void)
|
||||
FlagPragma (PES_FUNC, Pragma, &B, &AllowRegVarAddr);
|
||||
break;
|
||||
|
||||
case PRAGMA_REGVARS:
|
||||
Warning ("#pragma regvars is obsolete, please use #pragma register-vars instead");
|
||||
/* FALLTHROUGH */
|
||||
case PRAGMA_REGISTER_VARS:
|
||||
/* TODO: PES_STMT or even PES_EXPR (PES_DECL) maybe? */
|
||||
FlagPragma (PES_FUNC, Pragma, &B, &EnableRegVars);
|
||||
break;
|
||||
|
||||
case PRAGMA_RODATASEG:
|
||||
Warning ("#pragma rodataseg is obsolete, please use #pragma rodata-name instead");
|
||||
/* FALLTHROUGH */
|
||||
case PRAGMA_RODATA_NAME:
|
||||
/* TODO: PES_STMT or even PES_EXPR maybe? */
|
||||
SegNamePragma (PES_FUNC, PRAGMA_RODATA_NAME, &B);
|
||||
break;
|
||||
|
||||
case PRAGMA_SIGNEDCHARS:
|
||||
Warning ("#pragma signedchars is obsolete, please use #pragma signed-chars instead");
|
||||
/* FALLTHROUGH */
|
||||
case PRAGMA_SIGNED_CHARS:
|
||||
/* TODO: PES_STMT or even PES_EXPR maybe? */
|
||||
FlagPragma (PES_FUNC, Pragma, &B, &SignedChars);
|
||||
break;
|
||||
|
||||
case PRAGMA_STATICLOCALS:
|
||||
Warning ("#pragma staticlocals is obsolete, please use #pragma static-locals instead");
|
||||
/* FALLTHROUGH */
|
||||
case PRAGMA_STATIC_LOCALS:
|
||||
/* TODO: PES_STMT or even PES_EXPR (PES_DECL) maybe? */
|
||||
FlagPragma (PES_FUNC, Pragma, &B, &StaticLocals);
|
||||
|
@ -2640,6 +2640,18 @@ static void DoDefine (void)
|
||||
goto Error_Handler;
|
||||
}
|
||||
NextChar ();
|
||||
|
||||
} else {
|
||||
|
||||
/* Object like macro. Check ISO/IEC 9899:1999 (E) 6.10.3p3:
|
||||
** "There shall be white-space between the identifier and the
|
||||
** replacement list in the definition of an object-like macro."
|
||||
** Note: C89 doesn't have this constraint.
|
||||
*/
|
||||
if (Std == STD_C99 && !IsSpace (CurC)) {
|
||||
PPWarning ("ISO C99 requires whitespace after the macro name");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Remove whitespace and comments from the line, store the preprocessed
|
||||
@ -2812,11 +2824,30 @@ static void DoInclude (void)
|
||||
InputType IT;
|
||||
StrBuf Filename = AUTO_STRBUF_INITIALIZER;
|
||||
|
||||
/* Macro-replace a single line with special support for <filename> */
|
||||
SB_Clear (MLine);
|
||||
PreprocessDirective (Line, MLine, MSM_TOK_HEADER);
|
||||
/* Skip whitespace so the input pointer points to the argument */
|
||||
SkipWhitespace (0);
|
||||
|
||||
/* Read from the processed line */
|
||||
/* We may have three forms of the #include directive:
|
||||
**
|
||||
** - # include "q-char-sequence" new-line
|
||||
** - # include <h-char-sequence> new-line
|
||||
** - # include pp-tokens new-line
|
||||
**
|
||||
** The former two are processed as is while the latter is preprocessed and
|
||||
** must then resemble one of the first two forms.
|
||||
*/
|
||||
if (CurC == '"' || CurC == '<') {
|
||||
/* Copy the argument part over to MLine */
|
||||
unsigned Start = SB_GetIndex (Line);
|
||||
unsigned Length = SB_GetLen (Line) - Start;
|
||||
SB_Slice (MLine, Line, Start, Length);
|
||||
} else {
|
||||
/* Macro-replace a single line with special support for <filename> */
|
||||
SB_Clear (MLine);
|
||||
PreprocessDirective (Line, MLine, MSM_TOK_HEADER);
|
||||
}
|
||||
|
||||
/* Read from the copied/preprocessed line */
|
||||
SB_Reset (MLine);
|
||||
MLine = InitLine (MLine);
|
||||
|
||||
@ -2894,7 +2925,7 @@ static unsigned GetLineDirectiveNum (void)
|
||||
|
||||
/* Ensure the buffer is terminated with a '\0' */
|
||||
SB_Terminate (&Buf);
|
||||
if (SkipWhitespace (0) != 0 || CurC == '\0') {
|
||||
if (SB_GetLen (&Buf) > 0) {
|
||||
const char* Str = SB_GetConstBuf (&Buf);
|
||||
if (Str[0] == '\0') {
|
||||
PPWarning ("#line directive interprets number as decimal, not octal");
|
||||
@ -2910,9 +2941,10 @@ static unsigned GetLineDirectiveNum (void)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
PPError ("#line directive requires a simple decimal digit sequence");
|
||||
PPError ("#line directive requires a decimal digit sequence");
|
||||
ClearLine ();
|
||||
}
|
||||
SkipWhitespace (0);
|
||||
|
||||
/* Done with the buffer */
|
||||
SB_Done (&Buf);
|
||||
|
@ -1267,7 +1267,7 @@ static int CloseBrace (Collection* C, token_t Tok)
|
||||
*/
|
||||
{
|
||||
if (CollCount (C) > 0) {
|
||||
token_t LastTok = (token_t)CollLast (C);
|
||||
token_t LastTok = (token_t)(intptr_t)CollLast (C);
|
||||
if (LastTok == Tok) {
|
||||
CollPop (C);
|
||||
NextToken ();
|
||||
|
@ -231,9 +231,11 @@ static int findToken (const char * const *tokenTbl, const char *token)
|
||||
/* takes as input table of tokens and token, returns position in table or -1 if not found */
|
||||
int i;
|
||||
|
||||
for (i = 0; tokenTbl[i][0]; i++) {
|
||||
if (strcmp (tokenTbl[i], token) == 0) {
|
||||
return i;
|
||||
if (token != NULL) {
|
||||
for (i = 0; tokenTbl[i][0]; i++) {
|
||||
if (strcmp (tokenTbl[i], token) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -889,6 +889,7 @@ static void ParseO65 (void)
|
||||
CfgOptionalAssign ();
|
||||
|
||||
/* Check which attribute was given */
|
||||
CfgSymbol* Sym;
|
||||
switch (AttrTok) {
|
||||
|
||||
case CFGTOK_EXPORT:
|
||||
@ -896,8 +897,11 @@ static void ParseO65 (void)
|
||||
AttrFlags |= atExport;
|
||||
/* We expect an identifier */
|
||||
CfgAssureIdent ();
|
||||
/* Remember it as an export for later */
|
||||
NewCfgSymbol (CfgSymO65Export, GetStrBufId (&CfgSVal));
|
||||
/* Remember it as an export for later. We do not support o65
|
||||
* output for the 65816, so the address size is always 16 bit.
|
||||
*/
|
||||
Sym = NewCfgSymbol (CfgSymO65Export, GetStrBufId (&CfgSVal));
|
||||
Sym->AddrSize = ADDR_SIZE_ABS;
|
||||
/* Eat the identifier token */
|
||||
CfgNextTok ();
|
||||
break;
|
||||
@ -907,8 +911,11 @@ static void ParseO65 (void)
|
||||
AttrFlags |= atImport;
|
||||
/* We expect an identifier */
|
||||
CfgAssureIdent ();
|
||||
/* Remember it as an import for later */
|
||||
NewCfgSymbol (CfgSymO65Import, GetStrBufId (&CfgSVal));
|
||||
/* Remember it as an import for later. We do not support o65
|
||||
* output for the 65816, so the address size is always 16 bit.
|
||||
*/
|
||||
Sym = NewCfgSymbol (CfgSymO65Import, GetStrBufId (&CfgSVal));
|
||||
Sym->AddrSize = ADDR_SIZE_ABS;
|
||||
/* Eat the identifier token */
|
||||
CfgNextTok ();
|
||||
break;
|
||||
|
@ -808,6 +808,15 @@ static int CmpExpName (const void* K1, const void* K2)
|
||||
|
||||
|
||||
|
||||
static int CmpExpValue (const void* K1, const void* K2)
|
||||
/* Compare function for qsort */
|
||||
{
|
||||
long Diff = GetExportVal (*(Export**)K1) - GetExportVal (*(Export**)K2);
|
||||
return Diff < 0? -1 : Diff > 0? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void CreateExportPool (void)
|
||||
/* Create an array with pointer to all exports */
|
||||
{
|
||||
@ -880,19 +889,25 @@ static char GetAddrSizeCode (unsigned char AddrSize)
|
||||
|
||||
|
||||
|
||||
void PrintExportMapByName (FILE* F)
|
||||
/* Print an export map, sorted by symbol name, to the given file */
|
||||
static void PrintExportMap (Export** Pool, unsigned Count, FILE* F)
|
||||
/* Print an export map to the given file */
|
||||
{
|
||||
unsigned I;
|
||||
unsigned Count;
|
||||
|
||||
/* Print all exports */
|
||||
Count = 0;
|
||||
for (I = 0; I < ExpCount; ++I) {
|
||||
const Export* E = ExpPool [I];
|
||||
unsigned Col = 0;
|
||||
for (I = 0; I < Count; ++I) {
|
||||
const Export* E = Pool [I];
|
||||
|
||||
/* Print unreferenced symbols only if explictly requested */
|
||||
if (VerboseMap || E->ImpCount > 0 || SYM_IS_CONDES (E->Type)) {
|
||||
/* Print unreferenced symbols only if explictly requested. If Expr is
|
||||
** NULL, the export is undefined. This happens for imports that don't
|
||||
** have a matching export, but if we have one of those, we don't come
|
||||
** here. It does also happen for imports that where satisfied from
|
||||
** elsewhere, like o65 imports defined in the linker config.
|
||||
** So ignore exports here that have an invalid Expr.
|
||||
*/
|
||||
if (E->Expr != 0 &&
|
||||
(VerboseMap || E->ImpCount > 0 || SYM_IS_CONDES (E->Type))) {
|
||||
fprintf (F,
|
||||
"%-25s %06lX %c%c%c%c ",
|
||||
GetString (E->Name),
|
||||
@ -901,8 +916,8 @@ void PrintExportMapByName (FILE* F)
|
||||
SYM_IS_LABEL (E->Type)? 'L' : 'E',
|
||||
GetAddrSizeCode ((unsigned char) E->AddrSize),
|
||||
SYM_IS_CONDES (E->Type)? 'I' : ' ');
|
||||
if (++Count == 2) {
|
||||
Count = 0;
|
||||
if (++Col == 2) {
|
||||
Col = 0;
|
||||
fprintf (F, "\n");
|
||||
}
|
||||
}
|
||||
@ -912,13 +927,10 @@ void PrintExportMapByName (FILE* F)
|
||||
|
||||
|
||||
|
||||
static int CmpExpValue (const void* I1, const void* I2)
|
||||
/* Compare function for qsort */
|
||||
void PrintExportMapByName (FILE* F)
|
||||
/* Print an export map, sorted by symbol name, to the given file */
|
||||
{
|
||||
long V1 = GetExportVal (ExpPool [*(unsigned *)I1]);
|
||||
long V2 = GetExportVal (ExpPool [*(unsigned *)I2]);
|
||||
|
||||
return V1 < V2 ? -1 : V1 == V2 ? 0 : 1;
|
||||
PrintExportMap (ExpPool, ExpCount, F);
|
||||
}
|
||||
|
||||
|
||||
@ -926,43 +938,16 @@ static int CmpExpValue (const void* I1, const void* I2)
|
||||
void PrintExportMapByValue (FILE* F)
|
||||
/* Print an export map, sorted by symbol value, to the given file */
|
||||
{
|
||||
unsigned I;
|
||||
unsigned Count;
|
||||
unsigned *ExpValXlat;
|
||||
/* Create a new pool that is sorted by value */
|
||||
Export** Pool = xmalloc (ExpCount * sizeof (Export*));
|
||||
memcpy (Pool, ExpPool, ExpCount * sizeof (Export*));
|
||||
qsort (Pool, ExpCount, sizeof (Export*), CmpExpValue);
|
||||
|
||||
/* Create a translation table where the symbols are sorted by value. */
|
||||
ExpValXlat = xmalloc (ExpCount * sizeof (unsigned));
|
||||
for (I = 0; I < ExpCount; ++I) {
|
||||
/* Initialize table with current sort order. */
|
||||
ExpValXlat [I] = I;
|
||||
}
|
||||
/* Print the exports */
|
||||
PrintExportMap (Pool, ExpCount, F);
|
||||
|
||||
/* Sort them by value */
|
||||
qsort (ExpValXlat, ExpCount, sizeof (unsigned), CmpExpValue);
|
||||
|
||||
/* Print all exports */
|
||||
Count = 0;
|
||||
for (I = 0; I < ExpCount; ++I) {
|
||||
const Export* E = ExpPool [ExpValXlat [I]];
|
||||
|
||||
/* Print unreferenced symbols only if explictly requested */
|
||||
if (VerboseMap || E->ImpCount > 0 || SYM_IS_CONDES (E->Type)) {
|
||||
fprintf (F,
|
||||
"%-25s %06lX %c%c%c%c ",
|
||||
GetString (E->Name),
|
||||
GetExportVal (E),
|
||||
E->ImpCount? 'R' : ' ',
|
||||
SYM_IS_LABEL (E->Type)? 'L' : 'E',
|
||||
GetAddrSizeCode ((unsigned char) E->AddrSize),
|
||||
SYM_IS_CONDES (E->Type)? 'I' : ' ');
|
||||
if (++Count == 2) {
|
||||
Count = 0;
|
||||
fprintf (F, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf (F, "\n");
|
||||
xfree (ExpValXlat);
|
||||
/* Free the allocated buffer */
|
||||
xfree (Pool);
|
||||
}
|
||||
|
||||
|
||||
|
2703
src/sim65/6502.c
2703
src/sim65/6502.c
File diff suppressed because it is too large
Load Diff
@ -47,7 +47,8 @@
|
||||
/* Supported CPUs */
|
||||
typedef enum CPUType {
|
||||
CPU_6502,
|
||||
CPU_65C02
|
||||
CPU_65C02,
|
||||
CPU_6502X
|
||||
} CPUType;
|
||||
|
||||
/* Current CPU */
|
||||
|
@ -177,10 +177,16 @@ static unsigned char ReadProgramFile (void)
|
||||
|
||||
/* Get the CPU type from the file header */
|
||||
if ((Val = fgetc(F)) != EOF) {
|
||||
if (Val != CPU_6502 && Val != CPU_65C02) {
|
||||
switch (Val) {
|
||||
case CPU_6502:
|
||||
case CPU_65C02:
|
||||
case CPU_6502X:
|
||||
CPU = Val;
|
||||
break;
|
||||
|
||||
default:
|
||||
Error ("'%s': Invalid CPU type", ProgramFile);
|
||||
}
|
||||
CPU = Val;
|
||||
}
|
||||
|
||||
/* Get the address of sp from the file header */
|
||||
|
@ -21,6 +21,8 @@ unsigned int *MEMTOP = (unsigned int *)741;
|
||||
unsigned int *MEMLO = (unsigned int *)743;
|
||||
void *allocmem;
|
||||
|
||||
void code(void) { }
|
||||
|
||||
int main(void)
|
||||
{
|
||||
allocmem = malloc(257);
|
||||
@ -35,7 +37,7 @@ int main(void)
|
||||
printf(" MEMLO = $%04X (%u)\n", *MEMLO, *MEMLO);
|
||||
|
||||
printf(" ----------------------\n");
|
||||
printf(" main: $%04X (code)\n", &main);
|
||||
printf(" code: $%04X (code)\n", &code);
|
||||
printf(" data: $%04X (data)\n", &data);
|
||||
printf(" _dos_type: $%04X (bss)\n", &_dos_type);
|
||||
printf(" allocmem: $%04X (dyn. data)\n", allocmem);
|
||||
|
@ -11,6 +11,8 @@ static char hex[16] = { "0123456789abcdef" };
|
||||
static char charbuf[0x20];
|
||||
static char colbuf[0x20];
|
||||
|
||||
void func(void) { }
|
||||
|
||||
void main(void)
|
||||
{
|
||||
int stackvar = 42;
|
||||
@ -65,7 +67,7 @@ void main(void)
|
||||
p[8],p[9],p[10],p[11],p[12],p[13],p[14],p[15]
|
||||
);
|
||||
}
|
||||
memcpy(p, main, i = 0); /* test that a zero length doesn't copy 64K */
|
||||
memcpy(p, func, i = 0); /* test that a zero length doesn't copy 64K */
|
||||
|
||||
gotoxy(0,ysize - 1);
|
||||
for (i = 0; i < xsize; ++i) {
|
||||
|
@ -159,12 +159,14 @@ static void Pause(void) {
|
||||
#endif
|
||||
}
|
||||
|
||||
static void Nil() { }
|
||||
|
||||
int main(void) {
|
||||
long n0;
|
||||
unsigned t;
|
||||
int c, n1 = 12345, n2, n3;
|
||||
char s1[80], s2[80];
|
||||
void *p1 = main, *p2 = main, *p3 = main, *p4 = main;
|
||||
void *p1 = Nil, *p2 = Nil, *p3 = Nil, *p4 = Nil;
|
||||
|
||||
#ifndef USE_STDIO
|
||||
clrscr();
|
||||
|
@ -14,7 +14,9 @@ WORKDIR = ../testwrk
|
||||
|
||||
.PHONY: test continue mostlyclean clean
|
||||
|
||||
test: mostlyclean continue
|
||||
test:
|
||||
@$(MAKE) mostlyclean
|
||||
@$(MAKE) continue
|
||||
|
||||
continue:
|
||||
@$(MAKE) -C asm all
|
||||
|
@ -12,23 +12,25 @@ endif
|
||||
|
||||
WORKDIR = ../testwrk/asm
|
||||
|
||||
SUBDIRS = cpudetect opcodes listing val err misc
|
||||
|
||||
.PHONY: all continue mostlyclean clean
|
||||
|
||||
all: mostlyclean continue
|
||||
|
||||
define CALL_template
|
||||
continue: mostlyclean
|
||||
@$(MAKE) -C cpudetect all
|
||||
@$(MAKE) -C opcodes all
|
||||
@$(MAKE) -C listing all
|
||||
@$(MAKE) -C val all
|
||||
@$(MAKE) -C err all
|
||||
@$(MAKE) -C misc all
|
||||
|
||||
continue::
|
||||
@$(MAKE) -C $1 all
|
||||
|
||||
mostlyclean::
|
||||
@$(MAKE) -C $1 clean
|
||||
|
||||
endef
|
||||
|
||||
$(foreach subdir,$(SUBDIRS),$(eval $(call CALL_template,$(subdir))))
|
||||
mostlyclean:
|
||||
@$(MAKE) -C cpudetect clean
|
||||
@$(MAKE) -C opcodes clean
|
||||
@$(MAKE) -C listing clean
|
||||
@$(MAKE) -C val clean
|
||||
@$(MAKE) -C err clean
|
||||
@$(MAKE) -C misc clean
|
||||
|
||||
clean: mostlyclean
|
||||
@$(call RMDIR,$(WORKDIR))
|
||||
|
25
test/asm/listing/060-ulabel.s
Normal file
25
test/asm/listing/060-ulabel.s
Normal file
@ -0,0 +1,25 @@
|
||||
; Test new-style (@:) and legacy-style (:) unnamed labels.
|
||||
; Make sure that they have identical behavior.
|
||||
|
||||
.ORG $0000
|
||||
|
||||
@: nop
|
||||
: nop
|
||||
.ASSERT @<< = $0000, error
|
||||
.ASSERT @-- = $0000, error
|
||||
.ASSERT :<< = $0000, error
|
||||
.ASSERT :-- = $0000, error
|
||||
.ASSERT @< = $0001, error
|
||||
.ASSERT @- = $0001, error
|
||||
.ASSERT :< = $0001, error
|
||||
.ASSERT :- = $0001, error
|
||||
.ASSERT @> = $0002, error
|
||||
.ASSERT @+ = $0002, error
|
||||
.ASSERT :> = $0002, error
|
||||
.ASSERT :+ = $0002, error
|
||||
.ASSERT @>> = $0003, error
|
||||
.ASSERT @++ = $0003, error
|
||||
.ASSERT :>> = $0003, error
|
||||
.ASSERT :++ = $0003, error
|
||||
@: nop
|
||||
: nop
|
1
test/asm/listing/070-include-macro.inc
Normal file
1
test/asm/listing/070-include-macro.inc
Normal file
@ -0,0 +1 @@
|
||||
foo:
|
13
test/asm/listing/070-include-macro.s
Normal file
13
test/asm/listing/070-include-macro.s
Normal file
@ -0,0 +1,13 @@
|
||||
.macro IncludeFile FilePath
|
||||
.proc bar
|
||||
.include FilePath
|
||||
.endproc
|
||||
.endmacro
|
||||
|
||||
IncludeFile "070-include-macro.inc"
|
||||
|
||||
.ifdef bar::foo
|
||||
.out "bar::foo is defined"
|
||||
.else
|
||||
.out "bar::foo is undefined"
|
||||
.endif
|
1
test/asm/listing/070-include-repeat.inc
Normal file
1
test/asm/listing/070-include-repeat.inc
Normal file
@ -0,0 +1 @@
|
||||
.out "include file"
|
4
test/asm/listing/070-include-repeat.s
Normal file
4
test/asm/listing/070-include-repeat.s
Normal file
@ -0,0 +1,4 @@
|
||||
.repeat 3
|
||||
.include "070-include-repeat.inc"
|
||||
.out "main file"
|
||||
.endrepeat
|
1
test/asm/listing/ref/070-include-macro.err-ref
Normal file
1
test/asm/listing/ref/070-include-macro.err-ref
Normal file
@ -0,0 +1 @@
|
||||
bar::foo is defined
|
6
test/asm/listing/ref/070-include-repeat.err-ref
Normal file
6
test/asm/listing/ref/070-include-repeat.err-ref
Normal file
@ -0,0 +1,6 @@
|
||||
include file
|
||||
main file
|
||||
include file
|
||||
main file
|
||||
include file
|
||||
main file
|
@ -102,6 +102,14 @@ $(WORKDIR)/bug1265.$1.$2.prg: bug1265.c | $(WORKDIR)
|
||||
$(LD65) -t sim$2 -o $$@ $$(@:.prg=.o) sim$2.lib $(NULLERR)
|
||||
$(SIM65) $(SIM65FLAGS) $$@ $(NULLOUT) $(NULLERR)
|
||||
|
||||
# should not compile, but gives different diagnostics in C99 mode than in others
|
||||
$(WORKDIR)/bug2515.$1.$2.prg: bug2515.c | $(WORKDIR)
|
||||
$(if $(QUIET),echo misc/bug2515.$1.$2.prg)
|
||||
$(NOT) $(CC65) --standard c99 -t sim$2 -$1 -o $$(@:.prg=.s) $$< 2>$(WORKDIR)/bug2515.$1.$2.out
|
||||
$(ISEQUAL) $(WORKDIR)/bug2515.$1.$2.out bug2515.c99.ref
|
||||
$(NOT) $(CC65) -t sim$2 -$1 -o $$(@:.prg=.s) $$< 2>$(WORKDIR)/bug2515.$1.$2.out
|
||||
$(ISEQUAL) $(WORKDIR)/bug2515.$1.$2.out bug2515.ref
|
||||
|
||||
# this one requires -Werror
|
||||
$(WORKDIR)/bug1768.$1.$2.prg: bug1768.c | $(WORKDIR)
|
||||
$(if $(QUIET),echo misc/bug1768.$1.$2.prg)
|
||||
|
4
test/misc/bug2515.c
Normal file
4
test/misc/bug2515.c
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
#line 13"x"
|
||||
#define X"y"
|
||||
int main() { foo; }
|
2
test/misc/bug2515.c99.ref
Normal file
2
test/misc/bug2515.c99.ref
Normal file
@ -0,0 +1,2 @@
|
||||
x:13: Warning: ISO C99 requires whitespace after the macro name
|
||||
x:14: Error: Undeclared identifier 'foo'
|
1
test/misc/bug2515.ref
Normal file
1
test/misc/bug2515.ref
Normal file
@ -0,0 +1 @@
|
||||
x:14: Error: Undeclared identifier 'foo'
|
@ -50,7 +50,7 @@ ISEQUAL = ..$S..$Stestwrk$Sisequal$(EXE)
|
||||
# will have to change that, and create said special cases here.
|
||||
# see discussion in https://github.com/cc65/cc65/issues/2277
|
||||
CC = gcc
|
||||
CFLAGS = -std=gnu17 -O2 -Wall -W -Wextra -funsigned-char -fwrapv -fno-strict-overflow
|
||||
CFLAGS = -std=gnu17 -O2 -Wall -W -Wextra -funsigned-char -fwrapv -fno-strict-overflow -Wno-error=implicit-int -Wno-error=int-conversion
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
|
3
test/ref/bug2134.c
Normal file
3
test/ref/bug2134.c
Normal file
@ -0,0 +1,3 @@
|
||||
int i = { 0 };
|
||||
char* p = { 0 };
|
||||
int main() { return 0; }
|
2
test/ref/bug2134.cref
Normal file
2
test/ref/bug2134.cref
Normal file
@ -0,0 +1,2 @@
|
||||
bug2134.c:1: Warning: Braces around scalar initializer
|
||||
bug2134.c:2: Warning: Braces around scalar initializer
|
@ -22,6 +22,5 @@ return_t main(int argc, char* argv[])
|
||||
n = 0; /* produce an error */
|
||||
/* produce a warning */
|
||||
}
|
||||
|
||||
int arr[main(0, 0)]; /* produce an error */
|
||||
int b = 0;
|
||||
int arr[b]; /* produce an error */
|
||||
|
167
test/standard/stdint.c
Normal file
167
test/standard/stdint.c
Normal file
@ -0,0 +1,167 @@
|
||||
/* Test definitions from stdint.h */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <signal.h>
|
||||
|
||||
/* All macros from stdint.h must be evaluatable by the preprocessor */
|
||||
#if INT8_MIN
|
||||
#endif
|
||||
#if INT8_MAX
|
||||
#endif
|
||||
#if INT16_MIN
|
||||
#endif
|
||||
#if INT16_MAX
|
||||
#endif
|
||||
#if INT32_MIN
|
||||
#endif
|
||||
#if INT32_MAX
|
||||
#endif
|
||||
#if UINT8_MAX
|
||||
#endif
|
||||
#if UINT16_MAX
|
||||
#endif
|
||||
#if UINT32_MAX
|
||||
#endif
|
||||
#if INT_LEAST8_MIN
|
||||
#endif
|
||||
#if INT_LEAST8_MAX
|
||||
#endif
|
||||
#if INT_LEAST16_MIN
|
||||
#endif
|
||||
#if INT_LEAST16_MAX
|
||||
#endif
|
||||
#if INT_LEAST32_MIN
|
||||
#endif
|
||||
#if INT_LEAST32_MAX
|
||||
#endif
|
||||
#if UINT_LEAST8_MAX
|
||||
#endif
|
||||
#if UINT_LEAST16_MAX
|
||||
#endif
|
||||
#if UINT_LEAST32_MAX
|
||||
#endif
|
||||
#if INT_FAST8_MIN
|
||||
#endif
|
||||
#if INT_FAST8_MAX
|
||||
#endif
|
||||
#if INT_FAST16_MIN
|
||||
#endif
|
||||
#if INT_FAST16_MAX
|
||||
#endif
|
||||
#if INT_FAST32_MIN
|
||||
#endif
|
||||
#if INT_FAST32_MAX
|
||||
#endif
|
||||
#if UINT_FAST8_MAX
|
||||
#endif
|
||||
#if UINT_FAST16_MAX
|
||||
#endif
|
||||
#if UINT_FAST32_MAX
|
||||
#endif
|
||||
#if INTPTR_MIN
|
||||
#endif
|
||||
#if INTPTR_MAX
|
||||
#endif
|
||||
#if UINTPTR_MAX
|
||||
#endif
|
||||
#if INTMAX_MIN
|
||||
#endif
|
||||
#if INTMAX_MAX
|
||||
#endif
|
||||
#if UINTMAX_MAX
|
||||
#endif
|
||||
#if PTRDIFF_MIN
|
||||
#endif
|
||||
#if PTRDIFF_MAX
|
||||
#endif
|
||||
#if SIG_ATOMIC_MIN
|
||||
#endif
|
||||
#if SIG_ATOMIC_MAX
|
||||
#endif
|
||||
#if SIZE_MAX
|
||||
#endif
|
||||
|
||||
#define SMIN(type) ((type)(1L << (sizeof(type) * CHAR_BIT - 1)))
|
||||
#define SMAX(type) ((type)(~SMIN(type)))
|
||||
#define UMAX(type) ((type)(~(type)0))
|
||||
|
||||
#define SMIN_CHECK(type, val) \
|
||||
if (SMIN(type) != val) { \
|
||||
++failures; \
|
||||
printf("Mismatch for %s, minimum (%ld) is not %s (%ld)\n", \
|
||||
#type, (long)SMIN(type), #val, (long)val); \
|
||||
}
|
||||
#define SMAX_CHECK(type, val) \
|
||||
if (SMAX(type) != val) { \
|
||||
++failures; \
|
||||
printf("Mismatch for %s, maximum (%ld) is not %s (%ld)\n", \
|
||||
#type, (long)SMAX(type), #val, (long)val); \
|
||||
}
|
||||
#define UMAX_CHECK(type, val) \
|
||||
if (UMAX(type) != val) { \
|
||||
++failures; \
|
||||
printf("Mismatch for %s, maximum (%lu) is not %s (%lu)\n", \
|
||||
#type, (unsigned long)UMAX(type), #val, \
|
||||
(unsigned long)val); \
|
||||
}
|
||||
|
||||
static unsigned failures = 0;
|
||||
|
||||
int main()
|
||||
{
|
||||
SMIN_CHECK(int8_t, INT8_MIN);
|
||||
SMAX_CHECK(int8_t, INT8_MAX);
|
||||
SMIN_CHECK(int16_t, INT16_MIN);
|
||||
SMAX_CHECK(int16_t, INT16_MAX);
|
||||
SMIN_CHECK(int32_t, INT32_MIN);
|
||||
SMAX_CHECK(int32_t, INT32_MAX);
|
||||
UMAX_CHECK(uint8_t, UINT8_MAX);
|
||||
UMAX_CHECK(uint16_t, UINT16_MAX);
|
||||
UMAX_CHECK(uint32_t, UINT32_MAX);
|
||||
|
||||
SMIN_CHECK(int_least8_t, INT_LEAST8_MIN);
|
||||
SMAX_CHECK(int_least8_t, INT_LEAST8_MAX);
|
||||
SMIN_CHECK(int_least16_t, INT_LEAST16_MIN);
|
||||
SMAX_CHECK(int_least16_t, INT_LEAST16_MAX);
|
||||
SMIN_CHECK(int_least32_t, INT_LEAST32_MIN);
|
||||
SMAX_CHECK(int_least32_t, INT_LEAST32_MAX);
|
||||
UMAX_CHECK(uint_least8_t, UINT_LEAST8_MAX);
|
||||
UMAX_CHECK(uint_least16_t, UINT_LEAST16_MAX);
|
||||
UMAX_CHECK(uint_least32_t, UINT_LEAST32_MAX);
|
||||
|
||||
SMIN_CHECK(int_fast8_t, INT_FAST8_MIN);
|
||||
SMAX_CHECK(int_fast8_t, INT_FAST8_MAX);
|
||||
SMIN_CHECK(int_fast16_t, INT_FAST16_MIN);
|
||||
SMAX_CHECK(int_fast16_t, INT_FAST16_MAX);
|
||||
SMIN_CHECK(int_fast32_t, INT_FAST32_MIN);
|
||||
SMAX_CHECK(int_fast32_t, INT_FAST32_MAX);
|
||||
UMAX_CHECK(uint_fast8_t, UINT_FAST8_MAX);
|
||||
UMAX_CHECK(uint_fast16_t, UINT_FAST16_MAX);
|
||||
UMAX_CHECK(uint_fast32_t, UINT_FAST32_MAX);
|
||||
|
||||
SMIN_CHECK(intptr_t, INTPTR_MIN);
|
||||
SMAX_CHECK(intptr_t, INTPTR_MAX);
|
||||
UMAX_CHECK(uintptr_t, UINTPTR_MAX);
|
||||
|
||||
SMIN_CHECK(intmax_t, INTMAX_MIN);
|
||||
SMAX_CHECK(intmax_t, INTMAX_MAX);
|
||||
UMAX_CHECK(uintmax_t, UINTMAX_MAX);
|
||||
|
||||
SMIN_CHECK(ptrdiff_t, PTRDIFF_MIN);
|
||||
SMAX_CHECK(ptrdiff_t, PTRDIFF_MAX);
|
||||
|
||||
#if SIG_ATOMIC_MIN < 0
|
||||
SMIN_CHECK(sig_atomic_t, SIG_ATOMIC_MIN);
|
||||
SMAX_CHECK(sig_atomic_t, SIG_ATOMIC_MAX);
|
||||
#else
|
||||
UMAX_CHECK(sig_atomic_t, SIG_ATOMIC_MAX);
|
||||
#endif
|
||||
|
||||
UMAX_CHECK(size_t, SIZE_MAX);
|
||||
|
||||
return failures;
|
||||
}
|
10
test/val/bug2458.c
Normal file
10
test/val/bug2458.c
Normal file
@ -0,0 +1,10 @@
|
||||
#define str(arg) #arg
|
||||
#include str(bug2458.h) /* Ok, macro replacement */
|
||||
|
||||
#define string foo
|
||||
#include <string.h> /* Ok, no macro replacement */
|
||||
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
1
test/val/bug2458.h
Normal file
1
test/val/bug2458.h
Normal file
@ -0,0 +1 @@
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user