mirror of
https://github.com/cc65/cc65.git
synced 2025-04-12 00:37:12 +00:00
Merge remote-tracking branch 'upstream/master' into pcenginetarget
This commit is contained in:
commit
877fd532c2
@ -5,6 +5,7 @@ install:
|
||||
script:
|
||||
- make bin USER_CFLAGS=-Werror
|
||||
- make lib QUIET=1
|
||||
- make -C test
|
||||
- make -C src clean
|
||||
- make bin USER_CFLAGS=-Werror CROSS_COMPILE=i686-w64-mingw32-
|
||||
- make doc zip
|
||||
|
41
LICENSE
41
LICENSE
@ -1,44 +1,3 @@
|
||||
This is the original cc65 compiler copyright:
|
||||
|
||||
-*- Mode: Text -*-
|
||||
|
||||
This is the copyright notice for RA65, LINK65, LIBR65, and other
|
||||
Atari 8-bit programs. Said programs are Copyright 1989, by John R.
|
||||
Dunning. All rights reserved, with the following exceptions:
|
||||
|
||||
Anyone may copy or redistribute these programs, provided that:
|
||||
|
||||
1: You don't charge anything for the copy. It is permissable to
|
||||
charge a nominal fee for media, etc.
|
||||
|
||||
2: All source code and documentation for the programs is made
|
||||
available as part of the distribution.
|
||||
|
||||
3: This copyright notice is preserved verbatim, and included in
|
||||
the distribution.
|
||||
|
||||
You are allowed to modify these programs, and redistribute the
|
||||
modified versions, provided that the modifications are clearly noted.
|
||||
|
||||
There is NO WARRANTY with this software, it comes as is, and is
|
||||
distributed in the hope that it may be useful.
|
||||
|
||||
This copyright notice applies to any program which contains
|
||||
this text, or the refers to this file.
|
||||
|
||||
This copyright notice is based on the one published by the Free
|
||||
Software Foundation, sometimes known as the GNU project. The idea
|
||||
is the same as theirs, ie the software is free, and is intended to
|
||||
stay that way. Everybody has the right to copy, modify, and re-
|
||||
distribute this software. Nobody has the right to prevent anyone
|
||||
else from copying, modifying or redistributing it.
|
||||
|
||||
In acknowledgment of this copyright, I (Ullrich von Bassewitz) will place
|
||||
my own changes to the compiler under the same copyright.
|
||||
|
||||
The library and the binary utils are a complete rewrite done by me and
|
||||
covered by the following license:
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from
|
||||
the use of this software.
|
||||
|
@ -24,7 +24,7 @@ endif
|
||||
|
||||
SF_USER = oliverschmidt
|
||||
SF_HOST = frs.sourceforge.net
|
||||
SF_FILE = /home/frs/project/cc65/cc65-snapshot-win64.zip
|
||||
SF_FILE = /home/frs/project/cc65/cc65-snapshot-win32.zip
|
||||
|
||||
SCPFLAGS = -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -q
|
||||
|
||||
|
@ -27,6 +27,7 @@ including
|
||||
- the Supervision console.
|
||||
- the Oric Atmos.
|
||||
- the Lynx console.
|
||||
- the Ohio Scientific Challenger 1P
|
||||
|
||||
The libraries are fairly portable, so creating a version for other 6502s
|
||||
shouldn't be too much work.
|
||||
|
@ -1,22 +1,31 @@
|
||||
SYMBOLS {
|
||||
__STACKSIZE__: type = weak, value = $0800; # 2k stack
|
||||
__TAPEHDR__: type = import;
|
||||
__BASHDR__: type = import;
|
||||
__PROGFLAG__: type = weak, value = $00; # $00=BASIC, $80=machine code
|
||||
__AUTORUN__: type = weak, value = $00; # $00=only load, $C7=run
|
||||
__STACKSIZE__: type = weak, value = $0800; # 2K stack
|
||||
__GRAB__: type = weak, value = 0; # 0=don't grab graphics RAM, 1=grab graphics RAM
|
||||
__RAMEND__: type = weak, value = $9800 + $1C00 * __GRAB__;
|
||||
}
|
||||
MEMORY {
|
||||
ZP: file = "", define = yes, start = $00E2, size = $001A;
|
||||
TAPEHDR: file = %O, type = ro, start = $0000, size = $0011;
|
||||
RAM: file = %O, define = yes, start = $0500, size = $9300 - __STACKSIZE__;
|
||||
TAPEHDR: file = %O, type = ro, start = $0000, size = $001F;
|
||||
BASHEAD: file = %O, define = yes, start = $0501, size = $000D;
|
||||
RAM: file = %O, define = yes, start = __BASHEAD_LAST__, size = __RAMEND__ - __RAM_START__ - __STACKSIZE__;
|
||||
}
|
||||
SEGMENTS {
|
||||
ZEROPAGE: load = ZP, type = zp;
|
||||
TAPEHDR: load = TAPEHDR, type = ro;
|
||||
BASHDR: load = BASHEAD, type = ro, define = yes, optional = yes;
|
||||
STARTUP: load = RAM, type = ro;
|
||||
LOWCODE: load = RAM, type = ro, optional = yes;
|
||||
INIT: load = RAM, type = ro, define = yes, optional = yes;
|
||||
CODE: load = RAM, type = ro;
|
||||
RODATA: load = RAM, type = ro;
|
||||
INIT: load = RAM, type = ro, define = yes, optional = yes;
|
||||
DATA: load = RAM, type = rw;
|
||||
ZPSAVE: load = RAM, type = bss, define = yes;
|
||||
ZPSAVE1: load = RAM, type = rw, define = yes; # ZPSAVE1, ZPSAVE2 must be together
|
||||
ZPSAVE2: load = RAM, type = bss; # see "libsrc/atmos/crt0.s"
|
||||
BSS: load = RAM, type = bss, define = yes;
|
||||
ZEROPAGE: load = ZP, type = zp;
|
||||
}
|
||||
FEATURES {
|
||||
CONDES: type = constructor,
|
||||
|
25
cfg/osic1p-asm.cfg
Normal file
25
cfg/osic1p-asm.cfg
Normal file
@ -0,0 +1,25 @@
|
||||
FEATURES {
|
||||
STARTADDRESS: default = $0200;
|
||||
}
|
||||
SYMBOLS {
|
||||
# If you want ld65 to output a loadable-format file by default, then uncomment
|
||||
# the next line. (Then, "-u __BOOT__" wouldn't be needed on the command line.)
|
||||
# __BOOT__: type = import;
|
||||
__STACKSIZE__: type = weak, value = $0400; # 1 kB stack
|
||||
__HIMEM__: type = weak, value = $8000; # 32 kB RAM
|
||||
}
|
||||
MEMORY {
|
||||
# for size of ZP, see runtime/zeropage.s and c1p/extzp.s
|
||||
ZP: file = "", define = yes, start = $0002, size = $001A + $0006;
|
||||
HEAD: file = %O, start = $0000, size = $00B6;
|
||||
RAM: file = %O, define = yes, start = %S, size = __HIMEM__ - __STACKSIZE__ - %S;
|
||||
}
|
||||
SEGMENTS {
|
||||
BOOT: load = HEAD, type = ro, optional = yes;
|
||||
INIT: load = RAM, type = ro, define = yes, optional = yes;
|
||||
CODE: load = RAM, type = rw;
|
||||
RODATA: load = RAM, type = rw;
|
||||
DATA: load = RAM, type = rw;
|
||||
BSS: load = RAM, type = bss, define = yes;
|
||||
ZEROPAGE: load = ZP, type = zp;
|
||||
}
|
38
cfg/osic1p.cfg
Normal file
38
cfg/osic1p.cfg
Normal file
@ -0,0 +1,38 @@
|
||||
FEATURES {
|
||||
STARTADDRESS: default = $0200;
|
||||
}
|
||||
SYMBOLS {
|
||||
# If you want ld65 to output a loadable-format file by default, then uncomment
|
||||
# the next line. (Then, "-u __BOOT__" wouldn't be needed on the command line.)
|
||||
# __BOOT__: type = import;
|
||||
__STACKSIZE__: type = weak, value = $0400; # 1 kB stack
|
||||
__HIMEM__: type = weak, value = $8000; # 32 kB RAM
|
||||
}
|
||||
MEMORY {
|
||||
# for size of ZP, see runtime/zeropage.s and c1p/extzp.s
|
||||
ZP: file = "", define = yes, start = $0002, size = $001A + $0020;
|
||||
HEAD: file = %O, start = $0000, size = $00B6;
|
||||
RAM: file = %O, define = yes, start = %S, size = __HIMEM__ - __STACKSIZE__ - %S;
|
||||
}
|
||||
SEGMENTS {
|
||||
BOOT: load = HEAD, type = ro, optional = yes;
|
||||
STARTUP: load = RAM, type = ro;
|
||||
LOWCODE: load = RAM, type = ro, optional = yes;
|
||||
INIT: load = RAM, type = ro, define = yes, optional = yes;
|
||||
CODE: load = RAM, type = rw;
|
||||
RODATA: load = RAM, type = rw;
|
||||
DATA: load = RAM, type = rw;
|
||||
BSS: load = RAM, type = bss, define = yes;
|
||||
ZEROPAGE: load = ZP, type = zp;
|
||||
EXTZP: load = ZP, type = zp, define = yes, optional = yes;
|
||||
}
|
||||
FEATURES {
|
||||
CONDES: type = constructor,
|
||||
label = __CONSTRUCTOR_TABLE__,
|
||||
count = __CONSTRUCTOR_COUNT__,
|
||||
segment = INIT;
|
||||
CONDES: type = destructor,
|
||||
label = __DESTRUCTOR_TABLE__,
|
||||
count = __DESTRUCTOR_COUNT__,
|
||||
segment = RODATA;
|
||||
}
|
@ -2,7 +2,7 @@ ifneq ($(shell echo),)
|
||||
CMD_EXE = 1
|
||||
endif
|
||||
|
||||
.PHONY: all mostlyclean clean install zip doc html info gh-pages
|
||||
.PHONY: all mostlyclean clean install zip doc html info
|
||||
|
||||
.SUFFIXES:
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
<url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline>
|
||||
<url url="mailto:polluks@sdf.lonestar.org" name="Stefan A. Haubenthal">,<newline>
|
||||
<url url="mailto:greg.king5@verizon.net" name="Greg King">
|
||||
<date>2014-03-27
|
||||
<date>2015-01-09
|
||||
|
||||
<abstract>
|
||||
An overview over the Atmos runtime system as it is implemented for the cc65 C
|
||||
@ -32,27 +32,39 @@ more than one platform. Please see the function reference for more
|
||||
information.
|
||||
|
||||
|
||||
|
||||
<sect>Binary format<p>
|
||||
|
||||
The standard binary output format generated by the linker for the Atmos target
|
||||
is a machine language program with a 17 byte tape header including a cc65 tag.
|
||||
The standard load and autostart address is $500.
|
||||
is a machine language program with a one-line BASIC stub that jumps to the
|
||||
machine-language part through <tt/CALL/. It has one sacrificial byte attached
|
||||
to the end (a bug in the Oric ROM means that BASIC can put a variable on top
|
||||
of the last byte that was loaded). It has a 24-byte tape header. A file can
|
||||
be CLOADed as a BASIC program, and started by typing <tt/RUN/. The standard
|
||||
load address is $501.
|
||||
|
||||
|
||||
|
||||
<sect>Memory layout<p>
|
||||
|
||||
In the standard setup, cc65 generated programs use the memory from
|
||||
$500 to $9800, so nearly 37K of memory (including the stack) is
|
||||
In the standard setup, cc65-generated programs use the memory from
|
||||
$0501 to $9800; so, nearly 37K of memory (including the stack) is
|
||||
available. ROM calls are possible without further precautions.
|
||||
|
||||
If your program needs more memory, and it won't use TGI graphics, then you can
|
||||
use the ld65 command-line option, <tt/-D __GRAB__=1/, when building the
|
||||
program, to include the graphics screen RAM. Then, nearly 44K of memory
|
||||
($0501 to $B400) is available.
|
||||
|
||||
Special locations:
|
||||
|
||||
<descrip>
|
||||
<tag/Stack/
|
||||
The C runtime stack is located at $97FF and growing downwards.
|
||||
The C runtime stack is located at $97FF (or $B3FF), and grows
|
||||
downwards.
|
||||
|
||||
<tag/Heap/
|
||||
The C heap is located at the end of the program and grows towards the C
|
||||
The C heap is located at the end of the program, and grows towards the C
|
||||
runtime stack.
|
||||
|
||||
</descrip><p>
|
||||
@ -90,7 +102,7 @@ structures; accessing the struct fields will access the chip registers.
|
||||
<descrip>
|
||||
|
||||
<tag><tt/VIA/</tag>
|
||||
Access to the VIA (versatile interface adapter) chip is available via the
|
||||
Access to the VIA (Versatile Interface Adapter) chip is available via the
|
||||
<tt/VIA/ variable. The structure behind this variable is explained in <tt/_6522.h/.
|
||||
|
||||
</descrip><p>
|
||||
@ -117,7 +129,8 @@ The names in the parentheses denote the symbols to be used for static linking of
|
||||
|
||||
<sect1>Graphics drivers<p>
|
||||
|
||||
The default drivers, <tt/tgi_stddrv (tgi_static_stddrv)/, point to <tt/atmos-240-200-2.tgi (atmos_240_200_2_tgi)/.
|
||||
The default drivers, <tt/tgi_stddrv (tgi_static_stddrv)/,
|
||||
point to <tt/atmos-240-200-2.tgi (atmos_240_200_2_tgi)/.
|
||||
|
||||
<descrip>
|
||||
|
||||
@ -175,13 +188,14 @@ No mouse drivers are currently available for the Atmos.
|
||||
|
||||
<sect1>Disk I/O<p>
|
||||
|
||||
The existing library for the Atmos doesn't implement C file
|
||||
I/O. There are hacks for the <tt/read()/ and <tt/write()/ routines in
|
||||
place, which will make functions work that read from and write to <tt/stdout/
|
||||
(like <tt/printf()/). However, those functions have some shortcomings which
|
||||
won't be fixed, because they're going to be replaced anyway.
|
||||
The existing library for the Atmos doesn't implement C file I/O. There are
|
||||
hacks for the <tt/read()/ and <tt/write()/ routines in place, which will make
|
||||
functions work that read from <tt/stdin/ and write to <tt/stdout/ and
|
||||
<tt/stderr/ (such as <tt/printf()/). However, those functions have some
|
||||
shortcomings which won't be fixed, because they're going to be replaced
|
||||
anyway.
|
||||
|
||||
To be more concrete, the limitation means that you cannot use any of the
|
||||
To be more concrete, that limitation means that you cannot use any of the
|
||||
following functions (and a few others):
|
||||
|
||||
<itemize>
|
||||
@ -202,7 +216,14 @@ following functions (and a few others):
|
||||
|
||||
<sect1>Function keys<p>
|
||||
|
||||
These are defined to be FUNCT + number key.
|
||||
They are defined to be FUNCT + a number key.
|
||||
|
||||
|
||||
<sect1>Capitals lock<p>
|
||||
|
||||
The keyboard's "CAPS Lock" mode is turned off while the program is running.
|
||||
The previous mode (usually, CAPS Lock turned on [because Oric BASIC keywords
|
||||
must be UPPER-case]) is restored when the program stops.
|
||||
|
||||
|
||||
<sect1>Passing arguments to the program<p>
|
||||
@ -211,10 +232,12 @@ Command-line arguments can be passed to <tt/main()/. Since that is not
|
||||
supported directly by BASIC, the following syntax was chosen:
|
||||
|
||||
<tscreen><verb>
|
||||
CALL#500:REM ARG1 " ARG2 IS QUOTED" ARG3 "" ARG5
|
||||
RUN:REM arg1 " ARG2 IS QUOTED" ARG3 "" ARG5
|
||||
</verb></tscreen>
|
||||
|
||||
<enum>
|
||||
<item>You must turn <tt/CAPS/ lock off (tap CTRL-T) when you want to type
|
||||
lower-case arguments (but, <tt/RUN/ and <tt/REM/ must be UPPER-case).
|
||||
<item>Arguments are separated by spaces.
|
||||
<item>Arguments may be quoted.
|
||||
<item>Leading and trailing spaces around an argument are ignored. Spaces within
|
||||
@ -225,6 +248,15 @@ supported directly by BASIC, the following syntax was chosen:
|
||||
</enum>
|
||||
|
||||
|
||||
<sect1>Automatic starting<p>
|
||||
|
||||
Usually, a cc65-built program just will sit quietly in memory, after it is
|
||||
CLOADed. It waits for you to start it (by typing BASIC's <tt/RUN/ command).
|
||||
But, if you want to create a program that will start running immediately after
|
||||
it is loaded, then you can use the linker command-line option
|
||||
<tt/-D __AUTORUN__=$C7/.
|
||||
|
||||
|
||||
<sect1>Interrupts<p>
|
||||
|
||||
The runtime for the Atmos uses routines marked as <tt/.INTERRUPTOR/ for
|
||||
|
@ -1279,6 +1279,35 @@ Pseudo functions expect their arguments in parenthesis, and they have a result,
|
||||
either a string or an expression.
|
||||
|
||||
|
||||
<sect1><tt>.ADDRSIZE</tt><label id=".ADDRSIZE"><p>
|
||||
|
||||
The <tt/.ADDRSIZE/ function is used to return the interal address size
|
||||
associated with a symbol. This can be helpful in macros when knowing the address
|
||||
size of symbol can help with custom instructions.
|
||||
|
||||
Example:
|
||||
|
||||
<tscreen><verb>
|
||||
.macro myLDA foo
|
||||
.if .ADDRSIZE(foo) = 1
|
||||
;do custom command based on zeropage addressing:
|
||||
.byte 0A5h, foo
|
||||
.elseif .ADDRSIZE(foo) = 2
|
||||
;do custom command based on absolute addressing:
|
||||
.byte 0ADh
|
||||
.word foo
|
||||
.elseif .ADDRSIZE(foo) = 0
|
||||
; no address size defined for this symbol:
|
||||
.out .sprintf("Error, address size unknown for symbol %s", .string(foo))
|
||||
.endif
|
||||
.endmacro
|
||||
</verb></tscreen>
|
||||
|
||||
This command is new and must be enabled with the <tt/.FEATURE addrsize/ command.
|
||||
|
||||
See: <tt><ref id=".FEATURE" name=".FEATURE"></tt>
|
||||
|
||||
|
||||
<sect1><tt>.BANK</tt><label id=".BANK"><p>
|
||||
|
||||
The <tt/.BANK/ function is used to support systems with banked memory. The
|
||||
@ -2287,6 +2316,24 @@ Here's a list of all control commands and a description, what they do:
|
||||
</verb></tscreen>
|
||||
|
||||
|
||||
<sect1><tt>.ISMNEM, .ISMNEMONIC</tt><label id=".ISMNEMONIC"><p>
|
||||
|
||||
Builtin function. The function expects an identifier as argument in braces.
|
||||
The argument is evaluated, and the function yields "true" if the identifier
|
||||
is defined as an instruction mnemonic that is recognized by the assembler.
|
||||
Example:
|
||||
|
||||
<tscreen><verb>
|
||||
.if .not .ismnemonic(ina)
|
||||
.macro ina
|
||||
clc
|
||||
adc #$01
|
||||
.endmacro
|
||||
.endif
|
||||
|
||||
</verb></tscreen>
|
||||
|
||||
|
||||
<sect1><tt>.DESTRUCTOR</tt><label id=".DESTRUCTOR"><p>
|
||||
|
||||
Export a symbol and mark it as a module destructor. This may be used
|
||||
@ -2596,6 +2643,12 @@ Here's a list of all control commands and a description, what they do:
|
||||
|
||||
<descrip>
|
||||
|
||||
<tag><tt>addrsize</tt><label id="addrsize"></tag>
|
||||
|
||||
Enables the .ADDRSIZE pseudo function. This function is experimental and not enabled by default.
|
||||
|
||||
See also: <tt><ref id=".ADDRSIZE" name=".ADDRSIZE"></tt>
|
||||
|
||||
<tag><tt>at_in_identifiers</tt><label id="at_in_identifiers"></tag>
|
||||
|
||||
Accept the at character (`@') as a valid character in identifiers. The
|
||||
@ -4418,6 +4471,7 @@ compiler, depending on the target system selected:
|
||||
<item><tt/__LUNIX__/ - Target system is <tt/lunix/
|
||||
<item><tt/__LYNX__/ - Target system is <tt/lynx/
|
||||
<item><tt/__NES__/ - Target system is <tt/nes/
|
||||
<item><tt/__OSIC1P__/ - Target system is <tt/osic1p/
|
||||
<item><tt/__PET__/ - Target system is <tt/pet/
|
||||
<item><tt/__PLUS4__/ - Target system is <tt/plus4/
|
||||
<item><tt/__SIM6502__/ - Target system is <tt/sim6502/
|
||||
|
@ -3,7 +3,7 @@
|
||||
<article>
|
||||
<title>cc65 Users Guide
|
||||
<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">
|
||||
<date>2000-09-03, 2001-10-02, 2005-08-01
|
||||
<date>2015-05-26
|
||||
|
||||
<abstract>
|
||||
cc65 is a C compiler for 6502 targets. It supports several 6502 based home
|
||||
@ -74,6 +74,7 @@ Short options:
|
||||
|
||||
Long options:
|
||||
--add-source Include source as comment
|
||||
--all-cdecl Make functions default to __cdecl__
|
||||
--bss-name seg Set the name of the BSS segment
|
||||
--check-stack Generate stack overflow checks
|
||||
--code-name seg Set the name of the CODE segment
|
||||
@ -114,6 +115,14 @@ Here is a description of all the command line options:
|
||||
|
||||
<descrip>
|
||||
|
||||
<tag><tt>--all-cdecl</tt></tag>
|
||||
|
||||
Tells the compiler that functions which aren't declared explicitly with
|
||||
either the <tt/__cdecl__/ or <tt/__fastcall__/ calling conventions should
|
||||
have the cdecl convention. (Normally, functions that aren't variadic are
|
||||
fast-called.)
|
||||
|
||||
|
||||
<label id="option-bss-name">
|
||||
<tag><tt>--bss-name seg</tt></tag>
|
||||
|
||||
@ -348,6 +357,7 @@ Here is a description of all the command line options:
|
||||
<item>lunix
|
||||
<item>lynx
|
||||
<item>nes
|
||||
<item>osic1p
|
||||
<item>pet (all CBM PET systems except the 2001)
|
||||
<item>plus4
|
||||
<item>sim6502
|
||||
@ -549,9 +559,10 @@ and the one defined by the ISO standard:
|
||||
be passed as parameters by value. However, struct assignment *is*
|
||||
possible.
|
||||
<p>
|
||||
<item> Part of the C library is available only with fastcall calling
|
||||
conventions (see below). It means that you must not mix pointers to
|
||||
those functions with pointers to user-written, not-fastcall functions.
|
||||
<item> Most of the C library is available with only the fastcall calling
|
||||
convention (<ref id="extension-fastcall" name="see below">). It means
|
||||
that you must not mix pointers to those functions with pointers to
|
||||
user-written, cdecl functions (the calling conventions are incompatible).
|
||||
<p>
|
||||
<item> The <tt/volatile/ keyword doesn't have an effect. This is not as bad
|
||||
as it sounds, since the 6502 has so few registers that it isn't
|
||||
@ -589,30 +600,58 @@ This cc65 version has some extensions to the ISO C standard.
|
||||
<ref id="inline-asm" name="see there">.
|
||||
<p>
|
||||
|
||||
<item> There is a special calling convention named "fastcall".
|
||||
The syntax for a function declaration using fastcall is
|
||||
<label id="extension-fastcall">
|
||||
<item> The normal calling convention -- for non-variadic functions -- is
|
||||
named "fastcall". The syntax for a function declaration that
|
||||
<em/explicitly/ uses fastcall is
|
||||
|
||||
<tscreen><verb>
|
||||
<return type> fastcall <function name> (<parameter list>)
|
||||
</verb></tscreen>
|
||||
or
|
||||
<tscreen><verb>
|
||||
<return type> __fastcall__ <function name> (<parameter list>)
|
||||
<return type> __fastcall__ <function name> (<parameter list>)
|
||||
</verb></tscreen>
|
||||
An example would be
|
||||
An example is
|
||||
<tscreen><verb>
|
||||
void __fastcall__ f (unsigned char c)
|
||||
void __fastcall__ f (unsigned char c)
|
||||
</verb></tscreen>
|
||||
The first form of the fastcall keyword is in the user namespace and can
|
||||
therefore be disabled with the <tt><ref id="option--standard"
|
||||
name="--standard"></tt> command line option.
|
||||
|
||||
For functions declared as <tt/fastcall/, the rightmost parameter is not
|
||||
For functions that are <tt/fastcall/, the rightmost parameter is not
|
||||
pushed on the stack but left in the primary register when the function
|
||||
is called. This will reduce the cost when calling assembler functions
|
||||
significantly, especially when the function itself is rather small.
|
||||
is called. That significantly reduces the cost of calling those functions.
|
||||
<newline><newline>
|
||||
<p>
|
||||
|
||||
<item> There is another calling convention named "cdecl". Variadic functions
|
||||
(their prototypes have an ellipsis [<tt/.../]) always use that
|
||||
convention. The syntax for a function declaration using cdecl is
|
||||
|
||||
<tscreen><verb>
|
||||
<return type> cdecl <function name> (<parameter list>)
|
||||
</verb></tscreen>
|
||||
or
|
||||
<tscreen><verb>
|
||||
<return type> __cdecl__ <function name> (<parameter list>)
|
||||
</verb></tscreen>
|
||||
An example is
|
||||
<tscreen><verb>
|
||||
int* __cdecl__ f (unsigned char c)
|
||||
</verb></tscreen>
|
||||
|
||||
The first form of the cdecl keyword is in the user namespace;
|
||||
and therefore, can be disabled with the <tt/<ref id="option--standard"
|
||||
name="--standard">/ command-line option.
|
||||
|
||||
For functions that are <tt/cdecl/, the rightmost parameter is pushed
|
||||
onto the stack before the function is called. That increases the cost
|
||||
of calling those functions, especially when they are called from many
|
||||
places.<newline><newline>
|
||||
<p>
|
||||
|
||||
<item> There are two pseudo variables named <tt/__AX__/ and <tt/__EAX__/.
|
||||
Both refer to the primary register that is used by the compiler to
|
||||
evaluate expressions or return function results. <tt/__AX__/ is of
|
||||
@ -819,6 +858,11 @@ The compiler defines several macros at startup:
|
||||
|
||||
Is defined if the compiler was called with the <tt/-Os/ command line option.
|
||||
|
||||
<tag><tt>__OSIC1P__</tt></tag>
|
||||
|
||||
This macro is defined if the target is the Ohio Scientific Challenger 1P
|
||||
(-t osic1p).
|
||||
|
||||
<tag><tt>__PET__</tt></tag>
|
||||
|
||||
This macro is defined if the target is the PET family of computers (-t pet).
|
||||
|
@ -3,7 +3,7 @@
|
||||
<article>
|
||||
<title>Defining a Custom cc65 Target
|
||||
<author>Bruce Reidenbach
|
||||
<date>2010-02-22
|
||||
<date>2015-03-13
|
||||
|
||||
<abstract>
|
||||
This section provides step-by-step instructions on how to use the cc65
|
||||
@ -525,15 +525,16 @@ The first step in creating the assembly language code for the driver is
|
||||
to determine how to pass the C arguments to the assembly language
|
||||
routine. The cc65 toolset allows the user to specify whether the data
|
||||
is passed to a subroutine via the stack or by the processor registers by
|
||||
using the <tt>__fastcall__</tt> function declaration (note that there
|
||||
are two underscore characters in front of and two behind the
|
||||
<tt>fastcall</tt> declaration). When <tt>__fastcall__</tt> is
|
||||
specified, the rightmost argument in the function call is passed to the
|
||||
using the <tt/__fastcall__/ and <tt/__cdecl__/ function qualifiers (note that
|
||||
there are two underscore characters in front of and two behind each
|
||||
qualifier). <tt/__fastcall__/ is the default. When <tt/__cdecl__/ <em/isn't/
|
||||
specified, and the function isn't variadic (i.e., its prototype doesn't have
|
||||
an ellipsis), the rightmost argument in the function call is passed to the
|
||||
subroutine using the 6502 registers instead of the stack. Note that if
|
||||
there is only one argument in the function call, the execution overhead
|
||||
required by the stack interface routines is completely avoided.
|
||||
|
||||
Without <tt>__fastcall__</tt>, the argument is loaded in the A and X
|
||||
With <tt/__cdecl__</tt>, the last argument is loaded into the A and X
|
||||
registers and then pushed onto the stack via a call to <tt>pushax</tt>.
|
||||
The first thing the subroutine does is retrieve the argument from the
|
||||
stack via a call to <tt>ldax0sp</tt>, which copies the values into the A
|
||||
@ -561,7 +562,7 @@ _foo: jsr ldax0sp ; Retrieve A and X from the stack
|
||||
jmp incsp2 ; Pop A and X from the stack (includes return)
|
||||
</verb></tscreen>
|
||||
|
||||
If <tt>__fastcall__</tt> is specified, the argument is loaded into the A
|
||||
If <tt/__cdecl__/ isn't specified, then the argument is loaded into the A
|
||||
and X registers as before, but the subroutine is then called
|
||||
immediately. The subroutine does not need to retrieve the argument
|
||||
since the value is already available in the A and X registers.
|
||||
|
122
doc/da65.sgml
122
doc/da65.sgml
@ -2,12 +2,14 @@
|
||||
|
||||
<article>
|
||||
<title>da65 Users Guide
|
||||
<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">
|
||||
<date>2003-08-08
|
||||
<author>
|
||||
<url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline>
|
||||
<url url="mailto:greg.king5@verizon.net" name="Greg King">
|
||||
<date>2014-11-23
|
||||
|
||||
<abstract>
|
||||
da65 is a 6502/65C02 disassembler that is able to read user supplied
|
||||
information about its input data for better results. The output is ready for
|
||||
da65 is a 6502/65C02 disassembler that is able to read user-supplied
|
||||
information about its input data, for better results. The output is ready for
|
||||
feeding into ca65, the macro assembler supplied with the cc65 C compiler.
|
||||
</abstract>
|
||||
|
||||
@ -23,7 +25,7 @@ the cc65 C compiler and generates output that is suitable for the ca65
|
||||
macro assembler.
|
||||
|
||||
Besides generating output for ca65, one of the design goals was that the user
|
||||
is able to feed additional information about the code into the disassembler
|
||||
is able to feed additional information about the code into the disassembler,
|
||||
for improved results. This information may include the location and size of
|
||||
tables, and their format.
|
||||
|
||||
@ -106,11 +108,16 @@ Here is a description of all the command line options:
|
||||
<tag><tt>--cpu type</tt></tag>
|
||||
|
||||
Set the CPU type. The option takes a parameter, which may be one of
|
||||
<itemize>
|
||||
<item>6502
|
||||
<item>6502x
|
||||
<item>65sc02
|
||||
<item>65c02
|
||||
<item>huc6280
|
||||
</itemize>
|
||||
|
||||
6502, 6502x, 65sc02, 65c02, huc6280
|
||||
|
||||
6502x is the NMOS 6502 with illegal opcodes. huc6280 is the CPU of the PC
|
||||
engine. Support for the 65816 is currently not available.
|
||||
6502x is for the NMOS 6502 with unofficial opcodes. huc6280 is the CPU of
|
||||
the PC engine. Support for the 65816 currently is not available.
|
||||
|
||||
|
||||
<label id="option--formfeeds">
|
||||
@ -125,7 +132,7 @@ Here is a description of all the command line options:
|
||||
<tag><tt>-g, --debug-info</tt></tag>
|
||||
|
||||
This option adds the <tt/.DEBUGINFO/ command to the output file, so the
|
||||
assembler will generate debug information when reassembling the generated
|
||||
assembler will generate debug information when re-assembling the generated
|
||||
output.
|
||||
|
||||
|
||||
@ -241,7 +248,7 @@ unsupported.
|
||||
The disassembler works by creating an attribute map for the whole address
|
||||
space ($0000 - $FFFF). Initially, all attributes are cleared. Then, an
|
||||
external info file (if given) is read. Disassembly is done in several passes.
|
||||
In all passes with the exception of the last one, information about the
|
||||
In all passes, with the exception of the last one, information about the
|
||||
disassembled code is gathered and added to the symbol and attribute maps. The
|
||||
last pass generates output using the information from the maps.
|
||||
|
||||
@ -275,19 +282,19 @@ braces. Attributes have a name followed by a value. The syntax of the value
|
||||
depends on the type of the attribute. String attributes are places in double
|
||||
quotes, numeric attributes may be specified as decimal numbers or hexadecimal
|
||||
with a leading dollar sign. There are also attributes where the attribute
|
||||
value is a keyword, in this case the keyword is given as is (without quotes or
|
||||
value is a keyword; in this case, the keyword is given as-is (without quotes or
|
||||
anything). Each attribute is terminated by a semicolon.
|
||||
|
||||
<tscreen><verb>
|
||||
group-name { attribute1 attribute-value; attribute2 attribute-value; }
|
||||
group-name { attribute1 attribute-value; attribute2 attribute-value; }
|
||||
</verb></tscreen>
|
||||
|
||||
|
||||
<sect1>Comments<p>
|
||||
|
||||
Comments start with a hash mark (<tt/#/) and extend from the position of
|
||||
Comments start with a hash mark (<tt/#/); and, extend from the position of
|
||||
the mark to the end of the current line. Hash marks inside of strings will
|
||||
of course <em/not/ start a comment.
|
||||
<em/not/ start a comment, of course.
|
||||
|
||||
|
||||
<sect1>Specifying global options<label id="global-options"><p>
|
||||
@ -543,18 +550,17 @@ disassembled code. The following attributes are recognized:
|
||||
|
||||
<tag><tt>END</tt></tag>
|
||||
Followed by a numerical value. Specifies the end address of the segment. The
|
||||
end address is last the address that is part of the segment.
|
||||
end address is the last address that is a part of the segment.
|
||||
|
||||
<tag><tt>NAME</tt></tag>
|
||||
The attribute is followed by a string value which gives the name of the
|
||||
segment.
|
||||
</descrip>
|
||||
|
||||
All attributes are mandatory. Segments may not overlap. Since there is no
|
||||
explicit "end this segment" pseudo op, the disassembler cannot notify the
|
||||
assembler that one segment has ended. This may lead to errors if you don't
|
||||
define your segments carefully. As a rule of thumb, if you're using segments,
|
||||
your should define segments for all disassembled code.
|
||||
All attributes are mandatory. Segments must not overlap. The disassembler will
|
||||
change back to the (default) <tt/.code/ segment after the end of each defined
|
||||
segment. That might not be what you want. As a rule of thumb, if you're using
|
||||
segments, you should define segments for all disassembled code.
|
||||
|
||||
|
||||
<sect1>Specifying Assembler Includes<label id="infofile-asminc"><p>
|
||||
@ -563,8 +569,8 @@ The <tt/ASMINC/ directive is used to give the names of input files containing
|
||||
symbol assignments in assembler syntax:
|
||||
|
||||
<tscreen><verb>
|
||||
Name = value
|
||||
Name := value
|
||||
Name = value
|
||||
Name := value
|
||||
</verb></tscreen>
|
||||
|
||||
The usual conventions apply for symbol names. Values may be specified as hex
|
||||
@ -613,48 +619,46 @@ directives explained above:
|
||||
};
|
||||
|
||||
# One segment for the whole stuff
|
||||
SEGMENT { START $E000; END $FFFF; NAME kernal; };
|
||||
SEGMENT { START $E000; END $FFFF; NAME "kernal"; };
|
||||
|
||||
RANGE { START $E612; END $E631; TYPE Code; };
|
||||
RANGE { START $E632; END $E640; TYPE ByteTable; };
|
||||
RANGE { START $EA51; END $EA84; TYPE RtsTable; };
|
||||
RANGE { START $EC6C; END $ECAB; TYPE RtsTable; };
|
||||
RANGE { START $ED08; END $ED11; TYPE AddrTable; };
|
||||
RANGE { START $E612; END $E631; TYPE Code; };
|
||||
RANGE { START $E632; END $E640; TYPE ByteTable; };
|
||||
RANGE { START $EA51; END $EA84; TYPE RtsTable; };
|
||||
RANGE { START $EC6C; END $ECAB; TYPE RtsTable; };
|
||||
RANGE { START $ED08; END $ED11; TYPE AddrTable; };
|
||||
|
||||
# Zero page variables
|
||||
LABEL { NAME "fnadr"; ADDR $90; SIZE 3; };
|
||||
LABEL { NAME "sal"; ADDR $93; };
|
||||
LABEL { NAME "sah"; ADDR $94; };
|
||||
LABEL { NAME "sas"; ADDR $95; };
|
||||
# Zero-page variables
|
||||
LABEL { NAME "fnadr"; ADDR $90; SIZE 3; };
|
||||
LABEL { NAME "sal"; ADDR $93; };
|
||||
LABEL { NAME "sah"; ADDR $94; };
|
||||
LABEL { NAME "sas"; ADDR $95; };
|
||||
|
||||
# Stack
|
||||
LABEL { NAME "stack"; ADDR $100; SIZE 255; };
|
||||
LABEL { NAME "stack"; ADDR $100; SIZE 255; };
|
||||
|
||||
# Indirect vectors
|
||||
LABEL { NAME "cinv"; ADDR $300; SIZE 2; }; # IRQ
|
||||
LABEL { NAME "cbinv"; ADDR $302; SIZE 2; }; # BRK
|
||||
LABEL { NAME "nminv"; ADDR $304; SIZE 2; }; # NMI
|
||||
LABEL { NAME "cinv"; ADDR $300; SIZE 2; }; # IRQ
|
||||
LABEL { NAME "cbinv"; ADDR $302; SIZE 2; }; # BRK
|
||||
LABEL { NAME "nminv"; ADDR $304; SIZE 2; }; # NMI
|
||||
|
||||
# Jump table at end of kernal ROM
|
||||
LABEL { NAME "kscrorg"; ADDR $FFED; };
|
||||
LABEL { NAME "kplot"; ADDR $FFF0; };
|
||||
LABEL { NAME "kiobase"; ADDR $FFF3; };
|
||||
LABEL { NAME "kgbye"; ADDR $FFF6; };
|
||||
LABEL { NAME "kscrorg"; ADDR $FFED; };
|
||||
LABEL { NAME "kplot"; ADDR $FFF0; };
|
||||
LABEL { NAME "kiobase"; ADDR $FFF3; };
|
||||
LABEL { NAME "kgbye"; ADDR $FFF6; };
|
||||
|
||||
# Hardware vectors
|
||||
LABEL { NAME "hanmi"; ADDR $FFFA; };
|
||||
LABEL { NAME "hares"; ADDR $FFFC; };
|
||||
LABEL { NAME "hairq"; ADDR $FFFE; };
|
||||
LABEL { NAME "hanmi"; ADDR $FFFA; };
|
||||
LABEL { NAME "hares"; ADDR $FFFC; };
|
||||
LABEL { NAME "hairq"; ADDR $FFFE; };
|
||||
</verb></tscreen>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<sect>Copyright<p>
|
||||
|
||||
da65 (and all cc65 binutils) are (C) Copyright 1998-2007 Ullrich von
|
||||
Bassewitz. For usage of the binaries and/or sources the following
|
||||
da65 (and all cc65 binutils) is (C) Copyright 1998-2011, Ullrich von
|
||||
Bassewitz. For usage of the binaries and/or sources, the following
|
||||
conditions do apply:
|
||||
|
||||
This software is provided 'as-is', without any expressed or implied
|
||||
@ -666,20 +670,16 @@ including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
<enum>
|
||||
<item> The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
<item> Altered source versions must be plainly marked as such, and must not
|
||||
be misrepresented as being the original software.
|
||||
<item> This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
<item> The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
<item> Altered source versions must be plainly marked as such, and must not
|
||||
be misrepresented as being the original software.
|
||||
<item> This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
</enum>
|
||||
|
||||
|
||||
|
||||
</article>
|
||||
|
||||
|
||||
|
||||
|
||||
|
532
doc/funcref.sgml
532
doc/funcref.sgml
File diff suppressed because it is too large
Load Diff
@ -134,6 +134,9 @@
|
||||
<tag><htmlurl url="nes.html" name="nes.html"></tag>
|
||||
Topics specific to the Nintendo Entertainment System.
|
||||
|
||||
<tag><htmlurl url="osi.html" name="osi.html"></tag>
|
||||
Topics specific to the Ohio Scientific machines.
|
||||
|
||||
<tag><htmlurl url="pet.html" name="pet.html"></tag>
|
||||
Topics specific to the Commodore PET machines.
|
||||
|
||||
|
143
doc/intro.sgml
143
doc/intro.sgml
@ -6,8 +6,9 @@
|
||||
<author>
|
||||
<url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline>
|
||||
<url url="mailto:cbmnut@hushmail.com" name="CbmNut">,<newline>
|
||||
<url url="mailto:greg.king5@verizon.net" name="Greg King">
|
||||
<date>2014-4-24
|
||||
<url url="mailto:greg.king5@verizon.net" name="Greg King">,<newline>
|
||||
<url url="mailto:stephan.muehlstrasser@web.de" name="Stephan Mühlstrasser">
|
||||
<date>2015-03-07
|
||||
|
||||
<abstract>
|
||||
How to use the cc65 C language system -- an introduction.
|
||||
@ -342,8 +343,8 @@ Available at <url
|
||||
url="http://code.google.com/p/oriculator/">:
|
||||
|
||||
Emulates Oric-1 and Atmos computers, with sound, disk images,
|
||||
scanline-exact NTSC/PAL video, and movie export. Includes monitor.
|
||||
Fortunately for all SDL platforms. You will just need the emulator, all
|
||||
scanline-exact NTSC/PAL video, and movie export. Includes a monitor.
|
||||
Fortunately, for all SDL platforms. You will need just the emulator; all
|
||||
ROMs are supplied.
|
||||
|
||||
Compile the tutorial with
|
||||
@ -353,8 +354,11 @@ cl65 -O -t atmos hello.c text.s -o hello.tap
|
||||
</verb></tscreen>
|
||||
|
||||
Start the emulator, choose <bf/F1/ and <bf/Insert tape.../, and point to
|
||||
the "<bf/hello.tap/" executable. The file has an auto start header meant to
|
||||
be loaded directly from tape.
|
||||
the "<bf/hello.tap/" executable. After it has finished loading, type
|
||||
|
||||
<tscreen><verb>
|
||||
RUN
|
||||
</verb></tscreen>
|
||||
|
||||
On a real Atmos, you would need a tape drive.
|
||||
Turn on the computer, type
|
||||
@ -363,7 +367,11 @@ Turn on the computer, type
|
||||
CLOAD""
|
||||
</verb></tscreen>
|
||||
|
||||
at the BASIC prompt.
|
||||
at the BASIC prompt. After it has finished loading, type
|
||||
|
||||
<tscreen><verb>
|
||||
RUN
|
||||
</verb></tscreen>
|
||||
|
||||
The emulation, also, supports that method.
|
||||
|
||||
@ -514,6 +522,127 @@ The output is shown in a GEOS dialog box; click <bf/OK/ when you have finished
|
||||
reading it.
|
||||
|
||||
|
||||
<sect1>Ohio Scientific Challenger 1P<p>
|
||||
The <tt/osic1p/ runtime library returns to the boot prompt when the main()
|
||||
program exits. Therefore, the C file in the tutorial must be modified
|
||||
slightly, in order to see the results on the screen. Otherwise, the program
|
||||
would print the text string, and then jump to the boot prompt, making it
|
||||
impossible to see the results of running the tutorial program.
|
||||
|
||||
In addition to that, the <tt/osic1p/ target does not yet have support for stdio
|
||||
functions. Only the functions from the conio library are available.
|
||||
|
||||
Therefore, modify the "<tt/hello.c/" source file, as follows:
|
||||
|
||||
<tscreen><code>
|
||||
#include <conio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
extern const char text[]; /* In text.s */
|
||||
|
||||
int main (void)
|
||||
{
|
||||
clrscr ();
|
||||
cprintf ("%s\r\nPress <RETURN>.\r\n", text);
|
||||
cgetc ();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
</code></tscreen>
|
||||
|
||||
Compile the tutorial with
|
||||
|
||||
<tscreen><verb>
|
||||
cl65 -O -t osic1p -u __BOOT__ -o hello.lod hello.c text.s
|
||||
</verb></tscreen>
|
||||
|
||||
The program is configured for a Challenger 1P computer with, at least, 32 kB
|
||||
of RAM. See the <url url="osi.html"
|
||||
name="Ohio Scientifc-specific documentation"> for instructions about how to
|
||||
compile for other RAM sizes.
|
||||
|
||||
Plug a cassette player into your C1P computer; or, connect an RS-232 cable
|
||||
between your C1P and a PC (set the PC's serial port to 300 Bits Per Second,
|
||||
8 data bits, No parity, and 2 stop bits). (Turn on the computers.)
|
||||
|
||||
Tap the "<bf/BREAK/" key, to display the boot prompt; then, tap the "<tt/M/"
|
||||
key, to enter the 65V PROM monitor. Tap the "<tt/L/" key. Either start the
|
||||
cassette player (with a tape of the program), or start a transfer of the
|
||||
program file "<tt/hello.lod/" from the PC. After a while, you should see the
|
||||
following text on the screen:
|
||||
|
||||
<tscreen><verb>
|
||||
Hello world!
|
||||
Press <RETURN>.
|
||||
</verb></tscreen>
|
||||
|
||||
(Stop the cassette player.) After hitting the RETURN key, you should see the
|
||||
boot prompt again.
|
||||
|
||||
<sect2>WinOSI<p>
|
||||
Available at <url
|
||||
url="http://osi.marks-lab.com/#Emulator">:
|
||||
|
||||
Emulates the Ohio Scientific Challenger computers in different configurations.
|
||||
Configure it to emulate a C1P (model 600 board) with 32 kB of RAM.
|
||||
|
||||
Compile the tutorial with the same command that is used to make the program
|
||||
for a real machine.
|
||||
|
||||
Start the emulator. Tap the "<tt/M/" key, to enter the 65V PROM monitor; then,
|
||||
tap the "<tt/L/" key. If you had configured WinOSI to ask for a file when it
|
||||
starts to read data from the serial port, then you will see a file dialog box;
|
||||
otherwise, you must tap your host keyboard's F10 function key. Select the file
|
||||
"<tt/hello.lod/". After a moment, you should see the following text on the
|
||||
screen:
|
||||
|
||||
<tscreen><verb>
|
||||
Hello world!
|
||||
Press <RETURN>.
|
||||
</verb></tscreen>
|
||||
|
||||
After hitting the RETURN key, you should see the boot prompt again.
|
||||
|
||||
<sect2>C1Pjs<p>
|
||||
Available at <url
|
||||
url="http://www.pcjs.org/docs/c1pjs/">:
|
||||
|
||||
Emulates the Ohio Scientific Challenger 1P computer in different configurations.
|
||||
The 32 kB RAM machine that must be used with the default compiler settings is
|
||||
<url url="http://www.pcjs.org/devices/c1p/machine/32kb/" name="here">.
|
||||
|
||||
In addition to cc65, the <bf/srec_cat/ program from <url
|
||||
url="http://srecord.sourceforge.net/" name="the SRecord tool collection">
|
||||
must be installed. Some Linux distributions also provide srecord directly as
|
||||
an installable package.
|
||||
|
||||
Compile the tutorial with this command line:
|
||||
|
||||
<tscreen><verb>
|
||||
cl65 -O -t osic1p hello.c text.s
|
||||
</verb></tscreen>
|
||||
|
||||
Convert the binary file into a text file that can be loaded via
|
||||
the Ohio Scientific 65V PROM monitor, at start address 0x200:
|
||||
|
||||
<tscreen><verb>
|
||||
srec_cat hello -binary -offset 0x200 -o hello.c1p -Ohio_Scientific -execution-start-address=0x200
|
||||
</verb></tscreen>
|
||||
|
||||
Open the URL that points to the 32 kB machine; and, wait until the emulator
|
||||
has been loaded. Click on the "<bf/BREAK/" button to display the boot prompt;
|
||||
then, press the "<tt/M/" key to enter the 65V PROM monitor. Click the
|
||||
"<bf/Browse.../" button; and, select the file "<tt/hello.c1p/" that was
|
||||
created as the output of the above invocation of the "<tt/srec_cat/" command.
|
||||
Press the "<bf/Load/" button. You should see the following text on the screen:
|
||||
|
||||
<tscreen><verb>
|
||||
Hello world!
|
||||
Press <RETURN>.
|
||||
</verb></tscreen>
|
||||
|
||||
After hitting the RETURN key, you should see the boot prompt again.
|
||||
|
||||
|
||||
<sect1>Contributions wanted<p>
|
||||
|
||||
We need your help! Recommended emulators and instructions for other targets
|
||||
|
233
doc/osi.sgml
Normal file
233
doc/osi.sgml
Normal file
@ -0,0 +1,233 @@
|
||||
<!doctype linuxdoc system>
|
||||
|
||||
<article>
|
||||
|
||||
<title>Ohio Scientific-specific information for cc65
|
||||
<author>
|
||||
<url url="mailto:stephan.muehlstrasser@web.de" name="Stephan Mühlstrasser">,<newline>
|
||||
<url url="mailto:greg.king5@verizon.net" name="Greg King">
|
||||
<date>2015-03-17
|
||||
|
||||
<abstract>
|
||||
An overview over the Ohio Scientific runtime system as it is implemented for the cc65 C
|
||||
compiler.
|
||||
</abstract>
|
||||
|
||||
<!-- Table of contents -->
|
||||
<toc>
|
||||
|
||||
<!-- Begin the document -->
|
||||
|
||||
<sect>Overview<p>
|
||||
|
||||
This file contains an overview of the Ohio Scientific runtime system as it comes with the
|
||||
cc65 C compiler. It describes the memory layout, Ohio Scientific-specific header files,
|
||||
and any pitfalls specific to that platform.
|
||||
|
||||
Please note that Ohio Scientific-specific functions are just mentioned here, they are
|
||||
described in detail in the separate <url url="funcref.html" name="function
|
||||
reference">. Even functions marked as "platform dependent" may be available on
|
||||
more than one platform. Please see the function reference for more
|
||||
information.
|
||||
|
||||
<sect>Targets<p>
|
||||
|
||||
Currently the target "osic1p" is implemented. This works for the Ohio Scientific
|
||||
Challenger 1P machine and for the Briel Superboard /// replica.
|
||||
|
||||
<sect>Program file formats<p>
|
||||
|
||||
<descrip>
|
||||
<tag/Binary, then text/
|
||||
The standard binary output format generated by the linker for the osic1p
|
||||
target is a pure machine language program.
|
||||
|
||||
For uploading into a real machine over its serial port or into an emulator,
|
||||
that program must be converted into a text file that can be understood by
|
||||
the 65V PROM monitor. For that purpose, the <bf/srec_cat/ program from <url
|
||||
url="http://srecord.sourceforge.net/" name="the SRecord tool collection">
|
||||
can be used.
|
||||
|
||||
Care must be taken that the <tt/-offset/ and <tt/-execution-start-address/
|
||||
options for the <bf/srec_cat/ program correspond to the start address
|
||||
of the executable.
|
||||
|
||||
Example for converting an executable "hello" file that was built for the
|
||||
default start address $0200 to an uploadable file "hello.c1p":
|
||||
|
||||
<tscreen><verb>
|
||||
srec_cat hello -bin -of 0x200 -o hello.c1p -os -esa=0x200
|
||||
</verb></tscreen>
|
||||
|
||||
<tag/Hybrid/
|
||||
The linker can create an alternate format that contains two parts:
|
||||
<enum>
|
||||
<item>A text header that is understood by the 65V PROM monitor.
|
||||
It is a boot loader that reads the second part.
|
||||
<item>The default binary code that is described above.
|
||||
</enum>
|
||||
|
||||
You can make the alternate format by adding the option <tt/-u __BOOT__/ to
|
||||
<tt/cl65/'s or <tt/ld65/'s command lines.
|
||||
|
||||
This format doesn't need to be converted. It is smaller than the text-only
|
||||
format. But, it cannot be loaded by <url
|
||||
url="http://www.pcjs.org/docs/c1pjs/" name="C1Pjs">; you must use the
|
||||
SRecord-produced text-only format with that emulator. (However, if you know
|
||||
that you never will use C1Pjs, then you can edit the
|
||||
<tt>cfg/osic1p*.cfg</tt> files; uncomment the lines that import <tt/__BOOT__/.
|
||||
Then, you won't need to use <tt/-u __BOOT__/ on your command lines.)
|
||||
|
||||
</descrip>
|
||||
|
||||
<sect>Memory layout<p>
|
||||
|
||||
By default programs compiled for the osic1p target are configured for 32 kB RAM.
|
||||
The RAM size can be configured via the symbol <tt/__HIMEM__/.
|
||||
|
||||
Special locations:
|
||||
|
||||
<descrip>
|
||||
<tag/Program start address/
|
||||
The default start address is $0200. The start address is configurable
|
||||
via the linker option <tt/--start-addr/.
|
||||
|
||||
<tag/Stack/
|
||||
The C runtime stack is located at the top of RAM and growing downwards.
|
||||
The size is configurable via the symbol <tt/__STACKSIZE__/. The default
|
||||
stack size is $0400.
|
||||
|
||||
<tag/Heap/
|
||||
The C heap is located at the end of the program and grows towards the C
|
||||
runtime stack.
|
||||
|
||||
<tag/Video RAM/
|
||||
The 1 kB video RAM is located at $D000. On the monitor, only a subset
|
||||
of the available video RAM is visible. The address of the upper left corner
|
||||
of the visible area is $D085 and corresponds to conio cursor
|
||||
position (0, 0).
|
||||
|
||||
</descrip><p>
|
||||
|
||||
Example for building a program with start address $0300, stack size
|
||||
$0200 and RAM size $2000:
|
||||
|
||||
<tscreen><verb>
|
||||
cl65 --start-addr 0x300 -Wl -D,__HIMEM__=$2000,-D,__STACKSIZE__=$0200 -t osic1p hello.c
|
||||
</verb></tscreen>
|
||||
|
||||
<sect>Linker configurations<p>
|
||||
|
||||
The ld65 linker comes with a default config file "osic1p.cfg" for the Ohio Scientific
|
||||
Challenger 1P, which is implicitly used via <tt/-t osic1p/. The
|
||||
osic1p package comes with additional secondary linker config files, which are
|
||||
used via <tt/-t osic1p -C <configfile>/.
|
||||
|
||||
<sect1>Default config file (<tt/osic1p.cfg/)<p>
|
||||
|
||||
The default configuration is tailored to C programs.
|
||||
|
||||
<sect1><tt/osic1p-asm.cfg/<p>
|
||||
|
||||
This configuration is made for assembler programmers who don't need a special
|
||||
setup.
|
||||
|
||||
To use this config file, assemble with <tt/-t osic1p/ and link with
|
||||
<tt/-C osic1p-asm.cfg/. The former will make sure that correct runtime library
|
||||
is used, while the latter supplies the actual config. When using <tt/cl65/,
|
||||
use both command line options.
|
||||
|
||||
Sample command lines for <tt/cl65/:
|
||||
|
||||
<tscreen><verb>
|
||||
cl65 -t osic1p -C osic1p-asm.cfg -o program source.s
|
||||
cl65 -t osic1p -C osic1p-asm.cfg -u __BOOT__ -o program.lod source.s
|
||||
</verb></tscreen>
|
||||
|
||||
<sect>Platform-specific header files<p>
|
||||
|
||||
Programs containing Ohio Scientific-specific code may use the <tt/osic1p.h/
|
||||
header file.
|
||||
|
||||
<sect1>Ohio Scientific-specific functions<p>
|
||||
|
||||
There are currently no special Ohio Scientific functions.
|
||||
|
||||
<sect1>Hardware access<p>
|
||||
|
||||
There is no specific support for direct hardware access.
|
||||
|
||||
<sect>Loadable drivers<p>
|
||||
|
||||
There are no loadable drivers available.
|
||||
|
||||
<sect>Support for different screen layouts<p>
|
||||
|
||||
By default the conio library uses a 24 columns by 24 lines screen layout
|
||||
for the Challenger 1P, like under BASIC. In addition to that there is support
|
||||
for other screen layouts with extra modules.
|
||||
|
||||
There is a module <tt/screen-c1p-24x24.o/ in the OSI-specific
|
||||
cc65 runtime library that contains all conio functions that depend
|
||||
on the screen layout. No further configuration is needed for using the
|
||||
default screen layout of the Challenger 1P.
|
||||
|
||||
For other screen layouts additional versions of the screen module are
|
||||
available. The linker finds these modules without further configuration
|
||||
if they are specified on the compiler or linker command line. The
|
||||
extra module then overrides the default module.
|
||||
|
||||
Sample <tt/cl65/ command line to override the default screen
|
||||
module with the module <tt/osic1p-screen-s3-32x28.o/:
|
||||
|
||||
<tscreen><verb>
|
||||
cl65 -o hello -t osic1p osic1p-screen-s3-32x28.o hello.c
|
||||
</verb></tscreen>
|
||||
|
||||
Currently the following extra screen configuration modules are implemented:
|
||||
|
||||
<itemize>
|
||||
<item><tt>osic1p-screen-s3-32x28.o</tt>: 32 columns by 28 lines mode
|
||||
for Briel Superboard ///</item>
|
||||
</itemize>
|
||||
|
||||
<sect>Limitations<p>
|
||||
|
||||
<sect1>stdio implementation<p>
|
||||
|
||||
There is no support for stdio at the moment.
|
||||
|
||||
<sect>Other hints<p>
|
||||
|
||||
<sect1>Passing arguments to the program<p>
|
||||
|
||||
There is currently no support for passing arguments to a program.
|
||||
|
||||
<sect1>Program return code<p>
|
||||
|
||||
The program return code currently has no effect. When the main() function
|
||||
finishes, the boot prompt is shown again.
|
||||
|
||||
<sect>License<p>
|
||||
|
||||
This software is provided 'as-is', without any expressed or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
<enum>
|
||||
<item> The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
<item> Altered source versions must be plainly marked as such, and must not
|
||||
be misrepresented as being the original software.
|
||||
<item> This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
</enum>
|
||||
|
||||
</article>
|
||||
|
@ -2,14 +2,14 @@
|
||||
/* */
|
||||
/* ace.h */
|
||||
/* */
|
||||
/* ACE system specific definitions */
|
||||
/* ACE system-specific definitions */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2001 Ullrich von Bassewitz */
|
||||
/* Wacholderweg 14 */
|
||||
/* D-70597 Stuttgart */
|
||||
/* EMail: uz@musoftware.de */
|
||||
/* (C) 1998-2015, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
@ -61,9 +61,9 @@ struct aceDirentBuf {
|
||||
char ad_name [17]; /* Name itself, ASCIIZ */
|
||||
};
|
||||
|
||||
int aceDirOpen (char* dir);
|
||||
int aceDirClose (int handle);
|
||||
int aceDirRead (int handle, struct aceDirentBuf* buf);
|
||||
int __cdecl__ aceDirOpen (char* dir);
|
||||
int __cdecl__ aceDirClose (int handle);
|
||||
int __cdecl__ aceDirRead (int handle, struct aceDirentBuf* buf);
|
||||
|
||||
/* Type of an ACE key. Key in low byte, shift mask in high byte */
|
||||
typedef unsigned int aceKey;
|
||||
@ -92,23 +92,23 @@ typedef unsigned int aceKey;
|
||||
#define aceOP_RPTRATE 11 /* Key repeat rate */
|
||||
|
||||
/* Console functions */
|
||||
void aceConWrite (char* buf, size_t count);
|
||||
void aceConPutLit (int c);
|
||||
void aceConPos (unsigned x, unsigned y);
|
||||
void aceConGetPos (unsigned* x, unsigned* y);
|
||||
void __cdecl__ aceConWrite (char* buf, size_t count);
|
||||
void __cdecl__ aceConPutLit (int c);
|
||||
void __cdecl__ aceConPos (unsigned x, unsigned y);
|
||||
void __cdecl__ aceConGetPos (unsigned* x, unsigned* y);
|
||||
unsigned aceConGetX (void);
|
||||
unsigned aceConGetY (void);
|
||||
char* aceConInput (char* buf, unsigned initial);
|
||||
char __cdecl__* aceConInput (char* buf, unsigned initial);
|
||||
int aceConStopKey (void);
|
||||
aceKey aceConGetKey (void);
|
||||
int aceConKeyAvail (aceKey* key);
|
||||
void aceConKeyMat (char* matrix);
|
||||
void aceConSetOpt (unsigned char opt, unsigned char val);
|
||||
int aceConGetOpt (unsigned char opt);
|
||||
int __cdecl__ aceConKeyAvail (aceKey* key);
|
||||
void __cdecl__ aceConKeyMat (char* matrix);
|
||||
void __cdecl__ aceConSetOpt (unsigned char opt, unsigned char val);
|
||||
int __cdecl__ aceConGetOpt (unsigned char opt);
|
||||
|
||||
/* Misc stuff */
|
||||
int aceMiscIoPeek (unsigned addr);
|
||||
void aceMiscIoPoke (unsigned addr, unsigned char val);
|
||||
int __cdecl__ aceMiscIoPeek (unsigned addr);
|
||||
void __cdecl__ aceMiscIoPoke (unsigned addr, unsigned char val);
|
||||
|
||||
|
||||
|
||||
|
@ -6,10 +6,10 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2000 Ullrich von Bassewitz */
|
||||
/* Wacholderweg 14 */
|
||||
/* D-70597 Stuttgart */
|
||||
/* EMail: uz@musoftware.de */
|
||||
/* (C) 1998-2015, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
@ -42,7 +42,7 @@
|
||||
#ifdef NDEBUG
|
||||
# define assert(expr)
|
||||
#else
|
||||
extern void _afailed (const char*, unsigned);
|
||||
extern void __fastcall__ _afailed (const char*, unsigned);
|
||||
# define assert(expr) ((expr)? (void)0 : _afailed(__FILE__, __LINE__))
|
||||
#endif
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2012, Ullrich von Bassewitz */
|
||||
/* (C) 1998-2015, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
@ -222,7 +222,7 @@ void cbm_k_unlsn (void);
|
||||
|
||||
|
||||
|
||||
unsigned int cbm_load (const char* name, unsigned char device, void* data);
|
||||
unsigned int __fastcall__ cbm_load (const char* name, unsigned char device, void* data);
|
||||
/* Loads file "name", from given device, to given address -- or, to the load
|
||||
** address of the file if "data" is the null pointer (like load"name",8,1
|
||||
** in BASIC).
|
||||
|
@ -77,6 +77,8 @@
|
||||
# include <lynx.h>
|
||||
#elif defined(__NES__)
|
||||
# include <nes.h>
|
||||
#elif defined(__OSIC1P__)
|
||||
# include <osic1p.h>
|
||||
#elif defined(__PCE__)
|
||||
# include <pce.h>
|
||||
#endif
|
||||
|
@ -6,10 +6,10 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2000 Ullrich von Bassewitz */
|
||||
/* Wacholderweg 14 */
|
||||
/* D-70597 Stuttgart */
|
||||
/* EMail: uz@musoftware.de */
|
||||
/* (C) 1998-2000, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
@ -88,7 +88,7 @@ unsigned __fastcall__ DbgDisAsmLen (unsigned Addr);
|
||||
int __fastcall__ DbgIsRAM (unsigned Addr);
|
||||
/* Return true if we can read and write the given address */
|
||||
|
||||
char* DbgMemDump (unsigned Addr, char* Buf, unsigned char Len);
|
||||
char* __cdecl__ DbgMemDump (unsigned Addr, char* Buf, unsigned char Len);
|
||||
/* Create a line of a memory dump in the given buffer. The buffer contains
|
||||
** the starting address (4 digits hex), then Len bytes in this format:
|
||||
** "AAAA__XX_YY_ZZ_...". The passed char buffer must hold Len*3+5 bytes
|
||||
|
@ -2,7 +2,7 @@
|
||||
/* */
|
||||
/* lynx.h */
|
||||
/* */
|
||||
/* Lynx system specific definitions */
|
||||
/* Lynx system-specific definitions */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
@ -109,25 +109,25 @@ extern void lynx_160_102_16_tgi[]; /* Referred to by tgi_static_stddrv[] */
|
||||
/* Sound support */
|
||||
/*****************************************************************************/
|
||||
|
||||
void lynx_snd_init ();
|
||||
void lynx_snd_init (void);
|
||||
/* Initialize the sound driver */
|
||||
|
||||
void lynx_snd_pause ();
|
||||
void lynx_snd_pause (void);
|
||||
/* Pause sound */
|
||||
|
||||
void lynx_snd_continue ();
|
||||
void lynx_snd_continue (void);
|
||||
/* Continue sound after pause */
|
||||
|
||||
void __fastcall__ lynx_snd_play (unsigned char channel, unsigned char *music);
|
||||
/* Play tune on channel */
|
||||
|
||||
void lynx_snd_stop ();
|
||||
void lynx_snd_stop (void);
|
||||
/* Stop sound on all channels */
|
||||
|
||||
void __fastcall__ lynx_snd_stop_channel (unsigned char channel);
|
||||
/* Stop sound on all channels */
|
||||
|
||||
unsigned char lynx_snd_active();
|
||||
unsigned char lynx_snd_active(void);
|
||||
/* Show which channels are active */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
47
include/osic1p.h
Normal file
47
include/osic1p.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* osic1p.h */
|
||||
/* */
|
||||
/* Challenger 1P system specific definitions */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2015 Stephan Muehlstrasser */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef _OSIC1P_H
|
||||
#define _OSIC1P_H
|
||||
|
||||
/* Check for errors */
|
||||
#if !defined(__OSIC1P__)
|
||||
# error "This module may only be used when compiling for the Challenger 1P!"
|
||||
#endif
|
||||
|
||||
/* The following #defines will cause the matching functions calls in conio.h
|
||||
** to be overlaid by macros with the same names, saving the function call
|
||||
** overhead.
|
||||
*/
|
||||
#define _textcolor(color) COLOR_WHITE
|
||||
#define _bgcolor(color) COLOR_BLACK
|
||||
#define _bordercolor(color) COLOR_BLACK
|
||||
|
||||
#endif
|
@ -107,12 +107,12 @@ int __fastcall__ atoi (const char* s);
|
||||
long __fastcall__ atol (const char* s);
|
||||
int __fastcall__ atexit (void (*exitfunc) (void));
|
||||
void* __fastcall__ bsearch (const void* key, const void* base, size_t n,
|
||||
size_t size, int (*cmp) (const void*, const void*));
|
||||
size_t size, int __fastcall__ (* cmp) (const void*, const void*));
|
||||
div_t __fastcall__ div (int numer, int denom);
|
||||
void __fastcall__ exit (int ret) __attribute__ ((noreturn));
|
||||
char* __fastcall__ getenv (const char* name);
|
||||
void __fastcall__ qsort (void* base, size_t count, size_t size,
|
||||
int (*compare) (const void*, const void*));
|
||||
int __fastcall__ (* compare) (const void*, const void*));
|
||||
long __fastcall__ strtol (const char* nptr, char** endptr, int base);
|
||||
unsigned long __fastcall__ strtoul (const char* nptr, char** endptr, int base);
|
||||
int __fastcall__ system (const char* s);
|
||||
|
@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2001 Piotr Fusik <fox@scene.pl> */
|
||||
/* (C) 2000-2015 Piotr Fusik <fox@scene.pl> */
|
||||
/* */
|
||||
/* This file is based on the zlib.h from 'zlib' general purpose compression */
|
||||
/* library, version 1.1.3, (C) 1995-1998 Jean-loup Gailly and Mark Adler. */
|
||||
@ -83,8 +83,8 @@ unsigned __fastcall__ inflatemem (char* dest, const char* source);
|
||||
*/
|
||||
|
||||
|
||||
int uncompress (char* dest, unsigned* destLen,
|
||||
const char* source, unsigned sourceLen);
|
||||
int __fastcall__ uncompress (char* dest, unsigned* destLen,
|
||||
const char* source, unsigned sourceLen);
|
||||
/*
|
||||
Original zlib description:
|
||||
|
||||
|
@ -24,6 +24,7 @@ TARGETS = apple2 \
|
||||
$(GEOS) \
|
||||
lynx \
|
||||
nes \
|
||||
osic1p \
|
||||
pce \
|
||||
sim6502 \
|
||||
sim65c02 \
|
||||
|
@ -46,9 +46,9 @@
|
||||
sta $94
|
||||
sty $95
|
||||
|
||||
; Call into the Applesoft Block Transfer Utility -- which handles zero-
|
||||
; Call into Applesoft Block Transfer Up -- which handles zero-
|
||||
; sized blocks well -- to move the content of the LC memory area.
|
||||
jsr $D396 ; BLTU + 3
|
||||
jsr $D39A ; BLTU2
|
||||
|
||||
; Set the source start address.
|
||||
lda #<__ZPSAVE_RUN__
|
||||
@ -68,9 +68,9 @@
|
||||
sta $94
|
||||
sty $95
|
||||
|
||||
; Call into the Applesoft Block Transfer Utility -- which handles moving
|
||||
; Call into Applesoft Block Transfer Up -- which handles moving
|
||||
; overlapping blocks upwards well -- to move the INIT segment.
|
||||
jsr $D396 ; BLTU + 3
|
||||
jsr $D39A ; BLTU2
|
||||
|
||||
; Delegate all further processing, to keep the STARTUP segment small.
|
||||
jsr init
|
||||
@ -164,10 +164,6 @@ basic: lda HIMEM
|
||||
: sta sp
|
||||
stx sp+1
|
||||
|
||||
; Enable interrupts, as old ProDOS versions (i.e. 1.1.1)
|
||||
; jump to SYS and BIN programs with interrupts disabled.
|
||||
cli
|
||||
|
||||
; Call the module constructors.
|
||||
jsr initlib
|
||||
|
||||
|
@ -23,11 +23,29 @@ oserr: jsr popname ; Preserves A
|
||||
jmp __mappederrno
|
||||
|
||||
_exec:
|
||||
; Save cmdline
|
||||
sta ptr4
|
||||
stx ptr4+1
|
||||
|
||||
; Get and push name
|
||||
jsr popax
|
||||
jsr pushname
|
||||
bne oserr
|
||||
|
||||
; ProDOS TechRefMan, chapter 5.1.5.1:
|
||||
; "The complete or partial pathname of the system program
|
||||
; is stored at $280, starting with a length byte."
|
||||
; In fact BASIC.SYSTEM does the same for BLOAD and BRUN of
|
||||
; binary programs so we should do the same too in any case
|
||||
; especially as _we_ rely on it in mainargs.s for argv[0]
|
||||
ldy #$00
|
||||
lda (sp),y
|
||||
tay
|
||||
: lda (sp),y
|
||||
sta $0280,y
|
||||
dey
|
||||
bpl :-
|
||||
|
||||
; Set pushed name
|
||||
lda sp
|
||||
ldx sp+1
|
||||
@ -52,24 +70,14 @@ _exec:
|
||||
lda mliparam + MLI::INFO::FILE_TYPE
|
||||
cmp #$FF ; SYS file?
|
||||
bne binary ; No, check for BIN file
|
||||
sta file_type ; Save file type for cmdline handling
|
||||
|
||||
; ProDOS TechRefMan, chapter 5.1.5.1:
|
||||
; "The complete or partial pathname of the system program
|
||||
; is stored at $280, starting with a length byte."
|
||||
ldy #$00
|
||||
lda (sp),y
|
||||
tay
|
||||
: lda (sp),y
|
||||
sta $0280,y
|
||||
dey
|
||||
bpl :-
|
||||
|
||||
; SYS programs replace BASIC.SYSTEM so set in the ProDOS system bit map
|
||||
; protection for pages $80 - $BF just in case BASIC.SYSTEM is there now
|
||||
ldx #$0F ; Start with protection for pages $B8 - $BF
|
||||
lda #%00000001 ; Protect only system global page
|
||||
: sta $BF60,x ; Set protection for 8 pages
|
||||
lda #$00 ; Protect no page
|
||||
lda #%00000000 ; Protect no page
|
||||
dex
|
||||
bpl :-
|
||||
bmi prodos ; Branch always
|
||||
@ -112,7 +120,7 @@ setbuf: lda #$00 ; Low byte
|
||||
dex
|
||||
dex
|
||||
dex
|
||||
|
||||
|
||||
; Set I/O buffer
|
||||
sta mliparam + MLI::OPEN::IO_BUFFER
|
||||
stx mliparam + MLI::OPEN::IO_BUFFER+1
|
||||
@ -126,7 +134,7 @@ setbuf: lda #$00 ; Low byte
|
||||
stx level
|
||||
beq :+
|
||||
dec LEVEL
|
||||
|
||||
|
||||
; Open file
|
||||
: lda #OPEN_CALL
|
||||
ldx #OPEN_COUNT
|
||||
@ -158,8 +166,27 @@ setbuf: lda #$00 ; Low byte
|
||||
bit $C080
|
||||
.endif
|
||||
|
||||
; Reset stack as we already passed
|
||||
; the point of no return anyway
|
||||
ldx #$FF
|
||||
txs
|
||||
|
||||
; Store up to 127 chars of cmdline (if any)
|
||||
; including terminating zero in stack page
|
||||
ldy #$00
|
||||
lda ptr4+1 ; NULL?
|
||||
beq :++ ; Yes, store as '\0'
|
||||
: lda (ptr4),y
|
||||
: sta $0100,y
|
||||
beq :+ ; '\0' stored, done
|
||||
iny
|
||||
cpy #$7E
|
||||
bcc :--
|
||||
lda #$00 ; '\0'
|
||||
beq :- ; Branch always
|
||||
|
||||
; Call loader stub after C libary shutdown
|
||||
lda #<target
|
||||
: lda #<target
|
||||
ldx #>target
|
||||
sta done+1
|
||||
stx done+2
|
||||
@ -177,16 +204,58 @@ level : .res 1
|
||||
source: jsr $BF00
|
||||
.byte READ_CALL
|
||||
.word read_param
|
||||
bcs :+
|
||||
bcs error
|
||||
|
||||
; Close program file
|
||||
jsr $BF00
|
||||
.byte CLOSE_CALL
|
||||
.word close_param
|
||||
bcs :+
|
||||
bcs error
|
||||
|
||||
; Check for cmdline handling
|
||||
lda $0100 ; Valid cmdline?
|
||||
beq jump ; No, jump to program right away
|
||||
ldx file_type ; SYS file?
|
||||
bne system ; Yes, check for startup filename
|
||||
|
||||
; Store REM and cmdline in BASIC input buffer
|
||||
lda #$B2 ; REM token
|
||||
bne :++ ; Branch always
|
||||
: inx
|
||||
lda a:$0100-1,x
|
||||
: sta $0200,x
|
||||
bne :--
|
||||
beq jump ; Branch always
|
||||
|
||||
; Check for startup filename support
|
||||
; ProDOS TechRefMan, chapter 5.1.5.1:
|
||||
; "$2000 is a jump instruction. $2003 and $2004 are $EE."
|
||||
system: lda $2000
|
||||
cmp #$4C
|
||||
bne jump
|
||||
lda $2003
|
||||
cmp #$EE
|
||||
bne jump
|
||||
lda $2004
|
||||
cmp #$EE
|
||||
bne jump
|
||||
|
||||
; Store cmdline in startup filename buffer
|
||||
ldx #$01
|
||||
: lda a:$0100-1,x
|
||||
beq :+
|
||||
sta $2006,x
|
||||
inx
|
||||
cpx $2005 ; Buffer full?
|
||||
bcc :- ; No, continue
|
||||
: dex
|
||||
stx $2006 ; Store cmdline length
|
||||
|
||||
; Go for it ...
|
||||
jmp (data_buffer)
|
||||
jump: jmp (data_buffer)
|
||||
|
||||
file_type = * - source + target
|
||||
.byte $00
|
||||
|
||||
read_param = * - source + target
|
||||
.byte $04 ; PARAM_COUNT
|
||||
@ -204,7 +273,7 @@ close_ref = * - source + target
|
||||
|
||||
; Quit to ProDOS dispatcher
|
||||
quit = * - source + target
|
||||
: jsr $BF00
|
||||
error: jsr $BF00
|
||||
.byte $65 ; QUIT
|
||||
.word quit_param
|
||||
|
||||
|
@ -21,6 +21,10 @@ initirq:
|
||||
.byte $40 ; Alloc interrupt
|
||||
.addr i_param
|
||||
bcs prterr
|
||||
|
||||
; Enable interrupts, as old ProDOS versions (i.e. 1.1.1)
|
||||
; jump to SYS and BIN programs with interrupts disabled.
|
||||
cli
|
||||
rts
|
||||
|
||||
; Print error message and exit
|
||||
|
@ -34,12 +34,12 @@
|
||||
MAXARGS = 10
|
||||
|
||||
; ProDOS stores the filename in the second half of BASIC's input buffer, so
|
||||
; there are 128 characters left. At least 7 characters are necessary for the
|
||||
; CALLxxxx:REM so 121 characters may be used before overwriting the ProDOS
|
||||
; filename. As we don't want to put further restrictions on the command-line
|
||||
; length we reserve those 121 characters terminated by a zero.
|
||||
; there are 128 characters left. At least 1 character is necessary for the
|
||||
; REM so 127 characters (including the terminating zero) may be used before
|
||||
; overwriting the ProDOS filename. As we don't want to further restrict the
|
||||
; command-line length we reserve those 127 characters.
|
||||
|
||||
BUF_LEN = 122
|
||||
BUF_LEN = 127
|
||||
|
||||
BASIC_BUF = $200
|
||||
FNAM_LEN = $280
|
||||
@ -176,4 +176,4 @@ argv: .addr FNAM
|
||||
|
||||
.bss
|
||||
|
||||
buffer: .res BUF_LEN
|
||||
buffer: .res BUF_LEN
|
||||
|
@ -22,14 +22,14 @@ READ_CALL = $CA
|
||||
CLOSE_CALL = $CC
|
||||
FILE_NOT_FOUND_ERR = $46
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; ------------------------------------------------------------------------
|
||||
|
||||
.import __CODE_0300_SIZE__, __DATA_0300_SIZE__
|
||||
.import __CODE_0300_LOAD__, __CODE_0300_RUN__
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; ------------------------------------------------------------------------
|
||||
|
||||
.segment "DATA_2000"
|
||||
.segment "DATA_2000"
|
||||
|
||||
GET_FILE_INFO_PARAM:
|
||||
.byte $0A ;PARAM_COUNT
|
||||
@ -57,9 +57,9 @@ LOADING:
|
||||
ELLIPSES:
|
||||
.byte " ...", $0D, $0D, $00
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; ------------------------------------------------------------------------
|
||||
|
||||
.segment "DATA_0300"
|
||||
.segment "DATA_0300"
|
||||
|
||||
READ_PARAM:
|
||||
.byte $04 ;PARAM_COUNT
|
||||
@ -81,22 +81,22 @@ QUIT_PARAM:
|
||||
|
||||
FILE_NOT_FOUND:
|
||||
.asciiz "... File Not Found"
|
||||
|
||||
|
||||
ERROR_NUMBER:
|
||||
.asciiz "... Error $"
|
||||
|
||||
PRESS_ANY_KEY:
|
||||
.asciiz " - Press Any Key "
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; ------------------------------------------------------------------------
|
||||
|
||||
.segment "CODE_2000"
|
||||
.segment "CODE_2000"
|
||||
|
||||
jmp :+
|
||||
.byte $EE
|
||||
.byte $EE
|
||||
.byte 65
|
||||
STARTUP:.res 65
|
||||
.byte $7F
|
||||
STARTUP:.res $7F
|
||||
|
||||
; Reset stack
|
||||
: ldx #$FF
|
||||
@ -104,8 +104,8 @@ STARTUP:.res 65
|
||||
|
||||
; Relocate CODE_0300 and DATA_0300
|
||||
ldx #<(__CODE_0300_SIZE__ + __DATA_0300_SIZE__)
|
||||
: lda __CODE_0300_LOAD__ - 1,x
|
||||
sta __CODE_0300_RUN__ - 1,x
|
||||
: lda __CODE_0300_LOAD__-1,x
|
||||
sta __CODE_0300_RUN__-1,x
|
||||
dex
|
||||
bne :-
|
||||
|
||||
@ -118,23 +118,23 @@ STARTUP:.res 65
|
||||
; Add trailing '\0' to pathname
|
||||
tax
|
||||
lda #$00
|
||||
sta PATHNAME + 1,x
|
||||
sta PATHNAME+1,x
|
||||
|
||||
; Copy ProDOS startup filename and trailing '\0' to stack
|
||||
ldx STARTUP
|
||||
lda #$00
|
||||
beq :++ ; bra
|
||||
: lda STARTUP + 1,x
|
||||
beq :++ ; Branch always
|
||||
: lda STARTUP+1,x
|
||||
: sta STACK,x
|
||||
dex
|
||||
bpl :--
|
||||
bpl :--
|
||||
|
||||
; Provide some user feedback
|
||||
lda #<LOADING
|
||||
ldx #>LOADING
|
||||
jsr PRINT
|
||||
lda #<(PATHNAME + 1)
|
||||
ldx #>(PATHNAME + 1)
|
||||
lda #<(PATHNAME+1)
|
||||
ldx #>(PATHNAME+1)
|
||||
jsr PRINT
|
||||
lda #<ELLIPSES
|
||||
ldx #>ELLIPSES
|
||||
@ -159,16 +159,16 @@ STARTUP:.res 65
|
||||
|
||||
; Get load address from aux-type
|
||||
lda FILE_INFO_ADDR
|
||||
ldx FILE_INFO_ADDR + 1
|
||||
ldx FILE_INFO_ADDR+1
|
||||
sta READ_ADDR
|
||||
stx READ_ADDR + 1
|
||||
stx READ_ADDR+1
|
||||
|
||||
; It's high time to leave this place
|
||||
jmp __CODE_0300_RUN__
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; ------------------------------------------------------------------------
|
||||
|
||||
.segment "CODE_0300"
|
||||
.segment "CODE_0300"
|
||||
|
||||
jsr MLI
|
||||
.byte READ_CALL
|
||||
@ -180,15 +180,15 @@ STARTUP:.res 65
|
||||
.word CLOSE_PARAM
|
||||
bcs ERROR
|
||||
|
||||
; Copy REM token and startup filename to BASIC input buffer
|
||||
; Copy REM and startup filename to BASIC input buffer
|
||||
ldx #$00
|
||||
lda #$B2
|
||||
bne :++ ; bra
|
||||
lda #$B2 ; REM token
|
||||
bne :++ ; Branch always
|
||||
: inx
|
||||
lda a:STACK - 1,x
|
||||
lda a:STACK-1,x
|
||||
: sta BUF,x
|
||||
bne :--
|
||||
|
||||
|
||||
; Go for it ...
|
||||
jmp (READ_ADDR)
|
||||
|
||||
@ -207,7 +207,7 @@ PRINT:
|
||||
: ora #$80
|
||||
jsr COUT
|
||||
iny
|
||||
bne :-- ; bra
|
||||
bne :-- ; Branch always
|
||||
: rts
|
||||
|
||||
ERROR:
|
||||
@ -216,7 +216,7 @@ ERROR:
|
||||
lda #<FILE_NOT_FOUND
|
||||
ldx #>FILE_NOT_FOUND
|
||||
jsr PRINT
|
||||
beq :++ ; bra
|
||||
beq :++ ; Branch always
|
||||
: pha
|
||||
lda #<ERROR_NUMBER
|
||||
ldx #>ERROR_NUMBER
|
||||
@ -230,5 +230,3 @@ ERROR:
|
||||
jsr MLI
|
||||
.byte QUIT_CALL
|
||||
.word QUIT_PARAM
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
24
libsrc/atmos/bashdr.s
Normal file
24
libsrc/atmos/bashdr.s
Normal file
@ -0,0 +1,24 @@
|
||||
;
|
||||
; 2010-11-14, Ullrich von Bassewitz
|
||||
; 2014-09-06, Greg King
|
||||
;
|
||||
; This module supplies a small BASIC stub program that uses CALL
|
||||
; to jump to the machine-language code that follows it.
|
||||
;
|
||||
|
||||
; The following symbol is used by the linker config. file
|
||||
; to force this module to be included into the output file.
|
||||
.export __BASHDR__:abs = 1
|
||||
|
||||
|
||||
.segment "BASHDR"
|
||||
|
||||
.addr Next
|
||||
.word .version ; Line number
|
||||
.byte $BF,'#' ; CALL token, mark number as hexadecimal
|
||||
.byte <(Start >> 8 ) + '0' + (Start >> 8 > $09) * $07
|
||||
.byte <(Start >> 4 & $0F) + '0' + (Start >> 4 & $0F > $09) * $07
|
||||
.byte <(Start & $0F) + '0' + (Start & $0F > $09) * $07
|
||||
.byte $00 ; End of BASIC line
|
||||
Next: .addr $0000 ; BASIC program end marker
|
||||
Start:
|
@ -2,39 +2,18 @@
|
||||
; Startup code for cc65 (Oric version)
|
||||
;
|
||||
; By Debrune Jérôme <jede@oric.org> and Ullrich von Bassewitz <uz@cc65.org>
|
||||
; 2014-08-22, Greg King
|
||||
; 2015-01-09, Greg King
|
||||
;
|
||||
|
||||
.export _exit
|
||||
.export __STARTUP__ : absolute = 1 ; Mark as startup
|
||||
.import initlib, donelib
|
||||
.import callmain, zerobss
|
||||
.import __RAM_START__, __RAM_SIZE__
|
||||
.import __ZPSAVE_LOAD__, __STACKSIZE__
|
||||
.import __RAM_START__, __RAM_SIZE__, __STACKSIZE__
|
||||
|
||||
.include "zeropage.inc"
|
||||
.include "atmos.inc"
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; Oric tape header
|
||||
|
||||
.segment "TAPEHDR"
|
||||
|
||||
.byte $16, $16, $16 ; Sync bytes
|
||||
.byte $24 ; End of header marker
|
||||
|
||||
.byte $00 ; $2B0
|
||||
.byte $00 ; $2AF
|
||||
.byte $80 ; $2AE Machine code flag
|
||||
.byte $C7 ; $2AD Autoload flag
|
||||
.dbyt __ZPSAVE_LOAD__ - 1 ; $2AB
|
||||
.dbyt __RAM_START__ ; $2A9
|
||||
.byte $00 ; $2A8
|
||||
.byte ((.VERSION >> 8) & $0F) + '0'
|
||||
.byte ((.VERSION >> 4) & $0F) + '0'
|
||||
.byte (.VERSION & $0F) + '0'
|
||||
.byte $00 ; Zero terminated compiler version
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; Place the startup code in a special segment.
|
||||
|
||||
@ -52,7 +31,8 @@ L1: lda sp,x
|
||||
|
||||
jsr zerobss
|
||||
|
||||
; Unprotect screen columns 0 and 1.
|
||||
; Currently, color isn't supported on the text screen.
|
||||
; Unprotect screen columns 0 and 1 (where each line's color codes would sit).
|
||||
|
||||
lda STATUS
|
||||
sta stsave
|
||||
@ -79,7 +59,7 @@ L1: lda sp,x
|
||||
|
||||
; Call the module destructors. This is also the exit() entry.
|
||||
|
||||
_exit: jsr donelib ; Run module destructors
|
||||
_exit: jsr donelib
|
||||
|
||||
; Restore the system stuff.
|
||||
|
||||
@ -102,9 +82,23 @@ L2: lda zpsave,x
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
|
||||
.segment "ZPSAVE"
|
||||
.segment "ZPSAVE1"
|
||||
|
||||
zpsave: .res zpspace
|
||||
zpsave:
|
||||
|
||||
; This padding is needed by a bug in the ROM.
|
||||
; (The CLOAD command starts BASIC's variables table on top of the last byte
|
||||
; that was loaded [instead of at the next address].)
|
||||
; This is overlaid on a buffer, so that it doesn't use extra space in RAM.
|
||||
|
||||
.byte 0
|
||||
|
||||
; The segments "ZPSAVE1" and "ZPSAVE2" always must be together.
|
||||
; They create a single object (the zpsave buffer).
|
||||
|
||||
.segment "ZPSAVE2"
|
||||
|
||||
.res zpspace - 1
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
|
||||
|
31
libsrc/atmos/tapehdr.s
Normal file
31
libsrc/atmos/tapehdr.s
Normal file
@ -0,0 +1,31 @@
|
||||
;
|
||||
; Based on code by Debrune Jérôme <jede@oric.org>
|
||||
; 2015-01-08, Greg King
|
||||
;
|
||||
|
||||
; The following symbol is used by the linker config. file
|
||||
; to force this module to be included into the output file.
|
||||
.export __TAPEHDR__:abs = 1
|
||||
|
||||
; These symbols, also, come from the configuration file.
|
||||
.import __BASHDR_LOAD__, __ZPSAVE1_LOAD__, __AUTORUN__, __PROGFLAG__
|
||||
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; Oric cassette-tape header
|
||||
|
||||
.segment "TAPEHDR"
|
||||
|
||||
.byte $16, $16, $16 ; Sync bytes
|
||||
.byte $24 ; Beginning-of-header marker
|
||||
|
||||
.byte $00 ; $2B0
|
||||
.byte $00 ; $2AF
|
||||
.byte <__PROGFLAG__ ; $2AE Language flag ($00=BASIC, $80=machine code)
|
||||
.byte <__AUTORUN__ ; $2AD Auto-run flag ($C7=run, $00=only load)
|
||||
.dbyt __ZPSAVE1_LOAD__ ;$2AB Address of end of file
|
||||
.dbyt __BASHDR_LOAD__ ; $2A9 Address of start of file
|
||||
.byte $00 ; $2A8
|
||||
|
||||
; File name (a maximum of 17 characters), zero-terminated
|
||||
.asciiz .sprintf("%u", .time)
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
** Marc 'BlackJack' Rintsch, 06.03.2001
|
||||
**
|
||||
** unsigned int cbm_load(const char* name,
|
||||
** unsigned char device,
|
||||
** const unsigned char* data);
|
||||
** unsigned int __fastcall__ cbm_load(const char* name,
|
||||
** unsigned char device,
|
||||
** const unsigned char* data);
|
||||
*/
|
||||
|
||||
#include <cbm.h>
|
||||
@ -11,7 +11,7 @@
|
||||
/* loads file "name" from given device to given address or to the load address
|
||||
** of the file if "data" is 0
|
||||
*/
|
||||
unsigned int cbm_load(const char* name, unsigned char device, void* data)
|
||||
unsigned int __fastcall__ cbm_load(const char* name, unsigned char device, void* data)
|
||||
{
|
||||
/* LFN is set to 0; but, it's not needed for loading
|
||||
** (BASIC V2 sets it to the value of the SA for LOAD).
|
||||
|
@ -1,7 +1,8 @@
|
||||
/*
|
||||
** _afailed.c
|
||||
**
|
||||
** Ullrich von Bassewitz, 06.06.1998
|
||||
** 1998-06-06, Ullrich von Bassewitz
|
||||
** 2015-03-13, Greg King
|
||||
*/
|
||||
|
||||
|
||||
@ -11,7 +12,7 @@
|
||||
|
||||
|
||||
|
||||
void _afailed (char* file, unsigned line)
|
||||
void __fastcall__ _afailed (char* file, unsigned line)
|
||||
{
|
||||
fprintf (stderr, "ASSERTION FAILED IN %s(%u)\n", file, line);
|
||||
exit (2);
|
||||
|
@ -16,7 +16,7 @@
|
||||
struct outdesc;
|
||||
|
||||
/* Type of the function that is called to output data */
|
||||
typedef void (*outfunc) (struct outdesc* desc, const char* buf, unsigned count);
|
||||
typedef void __cdecl__ (* outfunc) (struct outdesc* desc, const char* buf, unsigned count);
|
||||
|
||||
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
/*
|
||||
** bsearch.c
|
||||
**
|
||||
** Ullrich von Bassewitz, 17.06.1998
|
||||
** 1998-06-17, Ullrich von Bassewitz
|
||||
** 2015-06-21, Greg King
|
||||
*/
|
||||
|
||||
|
||||
@ -11,7 +12,7 @@
|
||||
|
||||
|
||||
void* __fastcall__ bsearch (const void* key, const void* base, size_t n,
|
||||
size_t size, int (*cmp) (const void*, const void*))
|
||||
size_t size, int __fastcall__ (* cmp) (const void*, const void*))
|
||||
{
|
||||
int current;
|
||||
int result;
|
||||
|
@ -1,7 +1,8 @@
|
||||
/*
|
||||
** qsort.c
|
||||
**
|
||||
** Ullrich von Bassewitz, 09.12.1998
|
||||
** 1998.12.09, Ullrich von Bassewitz
|
||||
** 2015-06-21, Greg King
|
||||
*/
|
||||
|
||||
|
||||
@ -12,7 +13,7 @@
|
||||
|
||||
static void QuickSort (register unsigned char* Base, int Lo, int Hi,
|
||||
register size_t Size,
|
||||
int (*Compare)(const void*, const void*))
|
||||
int __fastcall__ (* Compare) (const void*, const void*))
|
||||
/* Internal recursive function. Works with ints, but this shouldn't be
|
||||
** a problem.
|
||||
*/
|
||||
@ -52,7 +53,7 @@ static void QuickSort (register unsigned char* Base, int Lo, int Hi,
|
||||
|
||||
|
||||
void __fastcall__ qsort (void* base, size_t nmemb, size_t size,
|
||||
int (*compare)(const void*, const void*))
|
||||
int __fastcall__ (* compare) (const void*, const void*))
|
||||
/* Quicksort implementation */
|
||||
{
|
||||
if (nmemb > 1) {
|
||||
|
@ -33,7 +33,7 @@ ptr: .res 2 ; Points to output file
|
||||
; can ignore the passed pointer d, and access the data directly. While this
|
||||
; is not very clean, it gives better and shorter code.
|
||||
;
|
||||
; static void out (struct outdesc* d, const char* buf, unsigned count)
|
||||
; static void cdecl out (struct outdesc* d, const char* buf, unsigned count)
|
||||
; /* Routine used for writing */
|
||||
; {
|
||||
; register size_t cnt;
|
||||
@ -56,7 +56,7 @@ out: ldy #5
|
||||
ldy #7
|
||||
jsr pushwysp ; Push count
|
||||
lda ptr
|
||||
ldx ptr+1
|
||||
ldx ptr+1
|
||||
jsr _fwrite
|
||||
sta ptr1 ; Save function result
|
||||
stx ptr1+1
|
||||
|
@ -1,5 +1,5 @@
|
||||
;
|
||||
; int vsnprintf (char* Buf, size_t size, const char* Format, va_list ap);
|
||||
; int __fastcall__ vsnprintf (char* Buf, size_t size, const char* Format, va_list ap);
|
||||
;
|
||||
; Ullrich von Bassewitz, 2009-09-26
|
||||
;
|
||||
@ -130,7 +130,7 @@ L9: pla
|
||||
; ----------------------------------------------------------------------------
|
||||
; Callback routine used for the actual output.
|
||||
;
|
||||
; static void out (struct outdesc* d, const char* buf, unsigned count)
|
||||
; static void __cdecl__ out (struct outdesc* d, const char* buf, unsigned count)
|
||||
; /* Routine used for writing */
|
||||
;
|
||||
; Since we know, we're called with a pointer to our static outdesc structure,
|
||||
|
@ -1,7 +1,7 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 11.08.1998
|
||||
;
|
||||
; char* DbgMemDump (unsigend Addr, char* Buf, unsigned char Length);
|
||||
; char* __cdecl__ DbgMemDump (unsigend Addr, char* Buf, unsigned char Length);
|
||||
;
|
||||
|
||||
.export _DbgMemDump
|
||||
|
153
libsrc/osic1p/bootstrap.s
Normal file
153
libsrc/osic1p/bootstrap.s
Normal file
@ -0,0 +1,153 @@
|
||||
;
|
||||
; 2015-03-08, Greg King
|
||||
;
|
||||
|
||||
; When you want to create a program with the alternate file format,
|
||||
; add "-u __BOOT__" to the cl65/ld65 command line. Then, the linker
|
||||
; will import this symbol name; and, link this module at the front
|
||||
; of your program file.
|
||||
;
|
||||
.export __BOOT__:abs = 1
|
||||
|
||||
.import __RAM_START__, __RAM_SIZE__, __BSS_RUN__
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
|
||||
load_addr := __RAM_START__
|
||||
load_size = __BSS_RUN__ - __RAM_START__
|
||||
ram_top := __RAM_START__ + __RAM_SIZE__
|
||||
|
||||
.segment "BOOT"
|
||||
|
||||
; If you want to change how this bootstrap loader works, then:
|
||||
; 1. edit this assembly source code,
|
||||
; 2. define the constant ASM (uncomment the line below),
|
||||
; 3. assemble this file (and, make a listing of that assembly),
|
||||
; 4. copy the listing's hex codes into the .byte lines below (notice that most
|
||||
; of the strings are followed by CR; it's required by the OS65V monitor)
|
||||
; (be sure to match the listing's lines against the .byte lines),
|
||||
; 5. undefine ASM (recomment the line),
|
||||
; 6. assemble this file, again,
|
||||
; 7. and, add the object file to "osic1p.lib".
|
||||
|
||||
;ASM = 1
|
||||
|
||||
.ifdef ASM
|
||||
|
||||
.include "osic1p.inc"
|
||||
.macpack generic
|
||||
|
||||
load := $08 ; private variables
|
||||
count := $0A
|
||||
|
||||
GETCHAR := $FFBF ; gets one character from ACIA
|
||||
|
||||
FIRSTVISC = $85 ; Offset of first visible character in video RAM
|
||||
LINEDIST = $20 ; Offset in video RAM between two lines
|
||||
|
||||
ldy #<$0000
|
||||
lda #<load_addr
|
||||
ldx #>load_addr
|
||||
sta load
|
||||
stx load+1
|
||||
lda #<load_size
|
||||
eor #$FF
|
||||
sta count ; store (-size - 1)
|
||||
lda #>load_size
|
||||
eor #$FF
|
||||
sta count+1
|
||||
|
||||
L1: inc count ; pre-count one's-complement upwards
|
||||
bnz L2
|
||||
inc count+1
|
||||
bze L3
|
||||
L2: jsr GETCHAR ; (doesn't change .Y)
|
||||
sta (load),y
|
||||
|
||||
; Show that the file is being loaded by rotating an arrow on the screen.
|
||||
;
|
||||
tya
|
||||
lsr a
|
||||
lsr a
|
||||
and #8 - 1
|
||||
ora #$10 ; eight arrow characters
|
||||
sta SCRNBASE + FIRSTVISC + 2 * LINEDIST + 11
|
||||
|
||||
iny
|
||||
bnz L1
|
||||
inc load+1
|
||||
bnz L1 ; branch always
|
||||
|
||||
L3: jmp load_addr
|
||||
|
||||
.else
|
||||
|
||||
.mac hex1 h
|
||||
.lobytes ((h) & $0F) + (((h) & $0F) > 9) * 7 + '0'
|
||||
.endmac
|
||||
|
||||
.mac hex2 h
|
||||
hex1 (h) >> 4
|
||||
hex1 (h) >> 0
|
||||
.endmac
|
||||
|
||||
.mac hex4 h
|
||||
hex2 >(h)
|
||||
hex2 <(h)
|
||||
.endmac
|
||||
|
||||
CR = $0D
|
||||
|
||||
.byte CR, CR
|
||||
.byte "." ; set an address
|
||||
hex4 ram_top ; put loader where stack will sit
|
||||
.byte "/" ; write bytes into RAM
|
||||
|
||||
; ASCII-coded hexadecimal translation of the above assembly code.
|
||||
; It was copied from the assembler listing.
|
||||
|
||||
.byte "A0", CR, "00", CR
|
||||
.byte "A9", CR
|
||||
hex2 <load_addr
|
||||
.byte CR, "A2", CR
|
||||
hex2 >load_addr
|
||||
.byte CR, "85", CR, "08", CR
|
||||
.byte "86", CR, "09", CR
|
||||
.byte "A9", CR
|
||||
hex2 <load_size
|
||||
.byte CR, "49", CR, "FF", CR
|
||||
.byte "85", CR, "0A", CR
|
||||
.byte "A9", CR
|
||||
hex2 >load_size
|
||||
.byte CR, "49", CR, "FF", CR
|
||||
.byte "85", CR, "0B", CR
|
||||
|
||||
.byte "E6", CR, "0A", CR
|
||||
.byte "D0", CR, "04", CR
|
||||
.byte "E6", CR, "0B", CR
|
||||
.byte "F0", CR, "16", CR
|
||||
.byte "20", CR, "BF", CR, "FF", CR
|
||||
.byte "91", CR, "08", CR
|
||||
|
||||
.byte "98", CR
|
||||
.byte "4A", CR
|
||||
.byte "4A", CR
|
||||
.byte "29", CR, "07", CR
|
||||
.byte "09", CR, "10", CR
|
||||
.byte "8D", CR, "D0", CR, "D0", CR
|
||||
|
||||
.byte "C8", CR
|
||||
.byte "D0", CR, "E6", CR
|
||||
.byte "E6", CR, "09", CR
|
||||
.byte "D0", CR, "E2", CR
|
||||
|
||||
.byte "4C", CR
|
||||
hex2 <load_addr
|
||||
.byte CR
|
||||
hex2 >load_addr
|
||||
|
||||
.byte CR, "."
|
||||
hex4 ram_top
|
||||
.byte "G" ; go to address
|
||||
|
||||
.endif
|
29
libsrc/osic1p/cclear.s
Normal file
29
libsrc/osic1p/cclear.s
Normal file
@ -0,0 +1,29 @@
|
||||
;
|
||||
; Copied from CBM implementation
|
||||
;
|
||||
; originally by:
|
||||
; Ullrich von Bassewitz, 08.08.1998
|
||||
;
|
||||
; void cclearxy (unsigned char x, unsigned char y, unsigned char length);
|
||||
; void cclear (unsigned char length);
|
||||
;
|
||||
|
||||
.export _cclearxy, _cclear
|
||||
.import popa, _gotoxy, cputdirect
|
||||
.importzp tmp1
|
||||
|
||||
_cclearxy:
|
||||
pha ; Save the length
|
||||
jsr popa ; Get y
|
||||
jsr _gotoxy ; Call this one, will pop params
|
||||
pla ; Restore the length and run into _cclear
|
||||
|
||||
_cclear:
|
||||
cmp #0 ; Is the length zero?
|
||||
beq L9 ; Jump if done
|
||||
sta tmp1
|
||||
L1: lda #' '
|
||||
jsr cputdirect ; Direct output
|
||||
dec tmp1
|
||||
bne L1
|
||||
L9: rts
|
48
libsrc/osic1p/cgetc.s
Normal file
48
libsrc/osic1p/cgetc.s
Normal file
@ -0,0 +1,48 @@
|
||||
;
|
||||
; char cgetc (void);
|
||||
;
|
||||
|
||||
.constructor initcgetc
|
||||
.export _cgetc
|
||||
.import cursor
|
||||
|
||||
.include "osic1p.inc"
|
||||
.include "extzp.inc"
|
||||
.include "zeropage.inc"
|
||||
|
||||
; Initialize one-character buffer that is filled by kbhit()
|
||||
initcgetc:
|
||||
lda #$00
|
||||
sta CHARBUF ; No character in buffer initially
|
||||
rts
|
||||
|
||||
; Input routine from 65V PROM MONITOR, show cursor if enabled
|
||||
_cgetc:
|
||||
lda CHARBUF ; character in buffer available?
|
||||
beq nobuffer
|
||||
tax ; save character in X
|
||||
lda #$00
|
||||
sta CHARBUF ; empty buffer
|
||||
beq restorex ; restore X and return
|
||||
nobuffer:
|
||||
lda cursor ; show cursor?
|
||||
beq nocursor
|
||||
ldy CURS_X
|
||||
lda (SCREEN_PTR),y ; fetch current character
|
||||
sta tmp1 ; save it
|
||||
lda #$A1 ; full white square
|
||||
sta (SCREEN_PTR),y ; store at cursor position
|
||||
nocursor:
|
||||
jsr INPUTC ; get input character in A
|
||||
ldx cursor
|
||||
beq done ; was cursor on?
|
||||
tax ; save A in X
|
||||
lda tmp1 ; fetch saved character
|
||||
ldy CURS_X
|
||||
sta (SCREEN_PTR),y ; store at cursor position
|
||||
|
||||
restorex:
|
||||
txa ; restore saved character from X
|
||||
done:
|
||||
ldx #$00 ; high byte of int return value
|
||||
rts
|
29
libsrc/osic1p/chline.s
Normal file
29
libsrc/osic1p/chline.s
Normal file
@ -0,0 +1,29 @@
|
||||
;
|
||||
; based on CBM implementation
|
||||
;
|
||||
; originally by:
|
||||
; Ullrich von Bassewitz, 08.08.1998
|
||||
;
|
||||
; void chlinexy (unsigned char x, unsigned char y, unsigned char length);
|
||||
; void chline (unsigned char length);
|
||||
;
|
||||
|
||||
.export _chlinexy, _chline
|
||||
.import popa, _gotoxy, cputdirect
|
||||
.importzp tmp1
|
||||
|
||||
_chlinexy:
|
||||
pha ; Save the length
|
||||
jsr popa ; Get y
|
||||
jsr _gotoxy ; Call this one, will pop params
|
||||
pla ; Restore the length
|
||||
|
||||
_chline:
|
||||
cmp #0 ; Is the length zero?
|
||||
beq L9 ; Jump if done
|
||||
sta tmp1
|
||||
L1: lda #$94 ; Horizontal line, screen code
|
||||
jsr cputdirect ; Direct output
|
||||
dec tmp1
|
||||
bne L1
|
||||
L9: rts
|
55
libsrc/osic1p/crt0.s
Normal file
55
libsrc/osic1p/crt0.s
Normal file
@ -0,0 +1,55 @@
|
||||
; ---------------------------------------------------------------------------
|
||||
; crt0.s
|
||||
; ---------------------------------------------------------------------------
|
||||
;
|
||||
; Startup code for Ohio Scientific Challenger 1P
|
||||
|
||||
.export _init, _exit
|
||||
.import _main
|
||||
|
||||
.export __STARTUP__ : absolute = 1 ; Mark as startup
|
||||
.import __RAM_START__, __RAM_SIZE__ ; Linker generated
|
||||
.import __STACKSIZE__
|
||||
|
||||
.import zerobss, initlib, donelib
|
||||
|
||||
.include "zeropage.inc"
|
||||
.include "extzp.inc"
|
||||
.include "osic1p.inc"
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Place the startup code in a special segment
|
||||
|
||||
.segment "STARTUP"
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; A little light 6502 housekeeping
|
||||
|
||||
_init: ldx #$FF ; Initialize stack pointer to $01FF
|
||||
txs
|
||||
cld ; Clear decimal mode
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Set cc65 argument stack pointer
|
||||
|
||||
lda #<(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
|
||||
sta sp
|
||||
lda #>(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
|
||||
sta sp+1
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Initialize memory storage
|
||||
|
||||
jsr zerobss ; Clear BSS segment
|
||||
jsr initlib ; Run constructors
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Call main()
|
||||
|
||||
jsr _main
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Back from main (this is also the _exit entry):
|
||||
|
||||
_exit: jsr donelib ; Run destructors
|
||||
jmp RESET ; Display boot menu after program exit
|
289
libsrc/osic1p/ctype.s
Normal file
289
libsrc/osic1p/ctype.s
Normal file
@ -0,0 +1,289 @@
|
||||
;
|
||||
; Character specification table.
|
||||
;
|
||||
; Ullrich von Bassewitz, 02.06.1998
|
||||
; 2003-05-02, Greg King
|
||||
;
|
||||
; Copied from cbm/ctype.s
|
||||
|
||||
; The following 256-byte-wide table specifies attributes for the isxxx type
|
||||
; of functions. Doing it by a table means some overhead in space, but it
|
||||
; has major advantages:
|
||||
;
|
||||
; * It is fast. If it weren't for the slow parameter-passing of cc65,
|
||||
; one even could define C-language macroes for the isxxx functions
|
||||
; (as it usually is done, on other platforms).
|
||||
;
|
||||
; * It is highly portable. The only unportable part is the table itself;
|
||||
; all real code goes into the common library.
|
||||
;
|
||||
; * We save some code in the isxxx functions.
|
||||
|
||||
; This table is taken from Craig S. Bruce's technical docs. for the ACE OS.
|
||||
|
||||
.include "ctype.inc"
|
||||
|
||||
; The table is read-only, put it into the RODATA segment.
|
||||
|
||||
.rodata
|
||||
|
||||
__ctype:
|
||||
.byte CT_CTRL ; 0/00 ___rvs_@___
|
||||
.byte CT_CTRL ; 1/01 ___rvs_a___
|
||||
.byte CT_CTRL ; 2/02 ___rvs_b___
|
||||
.byte CT_CTRL ; 3/03 ___rvs_c___
|
||||
.byte CT_CTRL ; 4/04 ___rvs_d___
|
||||
.byte CT_CTRL ; 5/05 ___rvs_e___
|
||||
.byte CT_CTRL ; 6/06 ___rvs_f___
|
||||
.byte CT_CTRL ; 7/07 _BEL/rvs_g_
|
||||
.byte CT_CTRL ; 8/08 ___rvs_h___
|
||||
.byte CT_CTRL | CT_OTHER_WS | CT_SPACE_TAB ; 9/09 _TAB/rvs_i_
|
||||
.byte CT_CTRL | CT_OTHER_WS ; 10/0a _BOL/rvs_j_
|
||||
.byte CT_CTRL ; 11/0b ___rvs_k___
|
||||
.byte CT_CTRL ; 12/0c ___rvs_l___
|
||||
.byte CT_CTRL | CT_OTHER_WS ; 13/0d _CR_/rvs_m_
|
||||
.byte CT_CTRL ; 14/0e ___rvs_n___
|
||||
.byte CT_CTRL ; 15/0f ___rvs_o___
|
||||
.byte CT_CTRL ; 16/10 ___rvs_p___
|
||||
.byte CT_CTRL | CT_OTHER_WS ; 17/11 _VT_/rvs_q_
|
||||
.byte CT_CTRL ; 18/12 ___rvs_r___
|
||||
.byte CT_CTRL | CT_OTHER_WS ; 19/13 HOME/rvs_s_
|
||||
.byte CT_CTRL | CT_OTHER_WS ; 20/14 _BS_/rvs_t_
|
||||
.byte CT_CTRL ; 21/15 ___rvs_u___
|
||||
.byte CT_CTRL ; 22/16 ___rvs_v___
|
||||
.byte CT_CTRL ; 23/17 ___rvs_w___
|
||||
.byte CT_CTRL ; 24/18 ___rvs_x___
|
||||
.byte CT_CTRL ; 25/19 ___rvs_y___
|
||||
.byte CT_CTRL ; 26/1a ___rvs_z___
|
||||
.byte CT_CTRL ; 27/1b ___rvs_[___
|
||||
.byte CT_CTRL ; 28/1c ___rvs_\___
|
||||
.byte CT_CTRL | CT_OTHER_WS ; 29/1d cursr-right
|
||||
.byte CT_CTRL ; 30/1e ___rvs_^___
|
||||
.byte CT_CTRL ; 31/1f _rvs_under_
|
||||
.byte CT_SPACE | CT_SPACE_TAB ; 32/20 ___SPACE___
|
||||
.byte $00 ; 33/21 _____!_____
|
||||
.byte $00 ; 34/22 _____"_____
|
||||
.byte $00 ; 35/23 _____#_____
|
||||
.byte $00 ; 36/24 _____$_____
|
||||
.byte $00 ; 37/25 _____%_____
|
||||
.byte $00 ; 38/26 _____&_____
|
||||
.byte $00 ; 39/27 _____'_____
|
||||
.byte $00 ; 40/28 _____(_____
|
||||
.byte $00 ; 41/29 _____)_____
|
||||
.byte $00 ; 42/2a _____*_____
|
||||
.byte $00 ; 43/2b _____+_____
|
||||
.byte $00 ; 44/2c _____,_____
|
||||
.byte $00 ; 45/2d _____-_____
|
||||
.byte $00 ; 46/2e _____._____
|
||||
.byte $00 ; 47/2f _____/_____
|
||||
.byte CT_DIGIT | CT_XDIGIT ; 48/30 _____0_____
|
||||
.byte CT_DIGIT | CT_XDIGIT ; 49/31 _____1_____
|
||||
.byte CT_DIGIT | CT_XDIGIT ; 50/32 _____2_____
|
||||
.byte CT_DIGIT | CT_XDIGIT ; 51/33 _____3_____
|
||||
.byte CT_DIGIT | CT_XDIGIT ; 52/34 _____4_____
|
||||
.byte CT_DIGIT | CT_XDIGIT ; 53/35 _____5_____
|
||||
.byte CT_DIGIT | CT_XDIGIT ; 54/36 _____6_____
|
||||
.byte CT_DIGIT | CT_XDIGIT ; 55/37 _____7_____
|
||||
.byte CT_DIGIT | CT_XDIGIT ; 56/38 _____8_____
|
||||
.byte CT_DIGIT | CT_XDIGIT ; 57/39 _____9_____
|
||||
.byte $00 ; 58/3a _____:_____
|
||||
.byte $00 ; 59/3b _____;_____
|
||||
.byte $00 ; 60/3c _____<_____
|
||||
.byte $00 ; 61/3d _____=_____
|
||||
.byte $00 ; 62/3e _____>_____
|
||||
.byte $00 ; 63/3f _____?_____
|
||||
|
||||
.byte $00 ; 64/40 _____@_____
|
||||
.byte CT_LOWER | CT_XDIGIT ; 65/41 _____a_____
|
||||
.byte CT_LOWER | CT_XDIGIT ; 66/42 _____b_____
|
||||
.byte CT_LOWER | CT_XDIGIT ; 67/43 _____c_____
|
||||
.byte CT_LOWER | CT_XDIGIT ; 68/44 _____d_____
|
||||
.byte CT_LOWER | CT_XDIGIT ; 69/45 _____e_____
|
||||
.byte CT_LOWER | CT_XDIGIT ; 70/46 _____f_____
|
||||
.byte CT_LOWER ; 71/47 _____g_____
|
||||
.byte CT_LOWER ; 72/48 _____h_____
|
||||
.byte CT_LOWER ; 73/49 _____i_____
|
||||
.byte CT_LOWER ; 74/4a _____j_____
|
||||
.byte CT_LOWER ; 75/4b _____k_____
|
||||
.byte CT_LOWER ; 76/4c _____l_____
|
||||
.byte CT_LOWER ; 77/4d _____m_____
|
||||
.byte CT_LOWER ; 78/4e _____n_____
|
||||
.byte CT_LOWER ; 79/4f _____o_____
|
||||
.byte CT_LOWER ; 80/50 _____p_____
|
||||
.byte CT_LOWER ; 81/51 _____q_____
|
||||
.byte CT_LOWER ; 82/52 _____r_____
|
||||
.byte CT_LOWER ; 83/53 _____s_____
|
||||
.byte CT_LOWER ; 84/54 _____t_____
|
||||
.byte CT_LOWER ; 85/55 _____u_____
|
||||
.byte CT_LOWER ; 86/56 _____v_____
|
||||
.byte CT_LOWER ; 87/57 _____w_____
|
||||
.byte CT_LOWER ; 88/58 _____x_____
|
||||
.byte CT_LOWER ; 89/59 _____y_____
|
||||
.byte CT_LOWER ; 90/5a _____z_____
|
||||
.byte $00 ; 91/5b _____[_____
|
||||
.byte $00 ; 92/5c _____\_____
|
||||
.byte $00 ; 93/5d _____]_____
|
||||
.byte $00 ; 94/5e _____^_____
|
||||
.byte $00 ; 95/5f _UNDERLINE_
|
||||
.byte $00 ; 96/60 _A`_grave__
|
||||
.byte $00 ; 97/61 _A'_acute__
|
||||
.byte $00 ; 98/62 _A^_circum_
|
||||
.byte $00 ; 99/63 _A~_tilde__
|
||||
.byte $00 ; 100/64 _A"_dieres_
|
||||
.byte $00 ; 101/65 _A__ring___
|
||||
.byte $00 ; 102/66 _AE________
|
||||
.byte $00 ; 103/67 _C,cedilla_
|
||||
.byte $00 ; 104/68 _E`_grave__
|
||||
.byte $00 ; 105/69 _E'_acute__
|
||||
.byte $00 ; 106/6a _E^_circum_
|
||||
.byte $00 ; 107/6b _E"_dieres_
|
||||
.byte $00 ; 108/6c _I`_grave__
|
||||
.byte $00 ; 109/6d _I'_acute__
|
||||
.byte $00 ; 110/6e _I^_circum_
|
||||
.byte $00 ; 111/6f _I"_dieres_
|
||||
.byte $00 ; 112/70 _D-_Eth_lr_
|
||||
.byte $00 ; 113/71 _N~_tilde__
|
||||
.byte $00 ; 114/72 _O`_grave__
|
||||
.byte $00 ; 115/73 _O'_acute__
|
||||
.byte $00 ; 116/74 _O^_circum_
|
||||
.byte $00 ; 117/75 _O~_tilde__
|
||||
.byte $00 ; 118/76 _O"_dieres_
|
||||
.byte $00 ; 119/77 __multiply_
|
||||
.byte $00 ; 120/78 _O/_slash__
|
||||
.byte $00 ; 121/79 _U`_grave__
|
||||
.byte $00 ; 122/7a _U'_acute__
|
||||
.byte $00 ; 123/7b _U^_circum_
|
||||
.byte $00 ; 124/7c _U"_dieres_
|
||||
.byte $00 ; 125/7d _Y'_acute__
|
||||
.byte $00 ; 126/7e _cap_thorn_
|
||||
.byte $00 ; 127/7f _Es-sed_B__
|
||||
|
||||
.byte CT_CTRL ; 128/80 __bullet___
|
||||
.byte CT_CTRL ; 129/81 __v_line___
|
||||
.byte CT_CTRL ; 130/82 __h_line___
|
||||
.byte CT_CTRL ; 131/83 ___cross___
|
||||
.byte CT_CTRL ; 132/84 _tl_corner_
|
||||
.byte CT_CTRL ; 133/85 _tr_corner_
|
||||
.byte CT_CTRL ; 134/86 _bl_corner_
|
||||
.byte CT_CTRL ; 135/87 _br_corner_
|
||||
.byte CT_CTRL ; 136/88 ___l_tee___
|
||||
.byte CT_CTRL ; 137/89 ___r_tee___
|
||||
.byte CT_CTRL ; 138/8a ___t_tee___
|
||||
.byte CT_CTRL ; 139/8b ___b_tee___
|
||||
.byte CT_CTRL ; 140/8c ___heart___
|
||||
.byte CT_CTRL | CT_OTHER_WS ; 141/8d _CR/diamond
|
||||
.byte CT_CTRL ; 142/8e ___club____
|
||||
.byte CT_CTRL ; 143/8f ___spade___
|
||||
.byte CT_CTRL ; 144/90 _s_circle__
|
||||
.byte CT_CTRL | CT_OTHER_WS ; 145/91 _cursor-up_
|
||||
.byte CT_CTRL ; 146/92 ___pound___
|
||||
.byte CT_CTRL | CT_OTHER_WS ; 147/93 _CLS/check_
|
||||
.byte CT_CTRL | CT_OTHER_WS ; 148/94 __INSert___
|
||||
.byte CT_CTRL ; 149/95 ____+/-____
|
||||
.byte CT_CTRL ; 150/96 __divide___
|
||||
.byte CT_CTRL ; 151/97 __degree___
|
||||
.byte CT_CTRL ; 152/98 _c_checker_
|
||||
.byte CT_CTRL ; 153/99 _f_checker_
|
||||
.byte CT_CTRL ; 154/9a _solid_sq__
|
||||
.byte CT_CTRL ; 155/9b __cr_char__
|
||||
.byte CT_CTRL ; 156/9c _up_arrow__
|
||||
.byte CT_CTRL | CT_OTHER_WS ; 157/9d cursor-left
|
||||
.byte CT_CTRL ; 158/9e _left_arro_
|
||||
.byte CT_CTRL ; 159/9f _right_arr_
|
||||
.byte CT_SPACE | CT_SPACE_TAB ; 160/a0 _req space_
|
||||
.byte $00 ; 161/a1 _!_invertd_
|
||||
.byte $00 ; 162/a2 ___cent____
|
||||
.byte $00 ; 163/a3 ___pound___
|
||||
.byte $00 ; 164/a4 __currency_
|
||||
.byte $00 ; 165/a5 ____yen____
|
||||
.byte $00 ; 166/a6 _|_broken__
|
||||
.byte $00 ; 167/a7 __section__
|
||||
.byte $00 ; 168/a8 __umulaut__
|
||||
.byte $00 ; 169/a9 _copyright_
|
||||
.byte $00 ; 170/aa __fem_ord__
|
||||
.byte $00 ; 171/ab _l_ang_quo_
|
||||
.byte $00 ; 172/ac ____not____
|
||||
.byte $00 ; 173/ad _syl_hyphn_
|
||||
.byte $00 ; 174/ae _registerd_
|
||||
.byte $00 ; 175/af _overline__
|
||||
.byte $00 ; 176/b0 __degrees__
|
||||
.byte $00 ; 177/b1 ____+/-____
|
||||
.byte $00 ; 178/b2 _2_supersc_
|
||||
.byte $00 ; 179/b3 _3_supersc_
|
||||
.byte $00 ; 180/b4 ___acute___
|
||||
.byte $00 ; 181/b5 ____mu_____
|
||||
.byte $00 ; 182/b6 _paragraph_
|
||||
.byte $00 ; 183/b7 __mid_dot__
|
||||
.byte $00 ; 184/b8 __cedilla__
|
||||
.byte $00 ; 185/b9 _1_supersc_
|
||||
.byte $00 ; 186/ba __mas_ord__
|
||||
.byte $00 ; 187/bb _r_ang_quo_
|
||||
.byte $00 ; 188/bc ____1/4____
|
||||
.byte $00 ; 189/bd ____1/2____
|
||||
.byte $00 ; 190/be ____3/4____
|
||||
.byte $00 ; 191/bf _?_invertd_
|
||||
|
||||
.byte $00 ; 192/c0 _____`_____
|
||||
.byte CT_UPPER | CT_XDIGIT ; 193/c1 _____A_____
|
||||
.byte CT_UPPER | CT_XDIGIT ; 194/c2 _____B_____
|
||||
.byte CT_UPPER | CT_XDIGIT ; 195/c3 _____C_____
|
||||
.byte CT_UPPER | CT_XDIGIT ; 196/c4 _____D_____
|
||||
.byte CT_UPPER | CT_XDIGIT ; 197/c5 _____E_____
|
||||
.byte CT_UPPER | CT_XDIGIT ; 198/c6 _____F_____
|
||||
.byte CT_UPPER ; 199/c7 _____G_____
|
||||
.byte CT_UPPER ; 200/c8 _____H_____
|
||||
.byte CT_UPPER ; 201/c9 _____I_____
|
||||
.byte CT_UPPER ; 202/ca _____J_____
|
||||
.byte CT_UPPER ; 203/cb _____K_____
|
||||
.byte CT_UPPER ; 204/cc _____L_____
|
||||
.byte CT_UPPER ; 205/cd _____M_____
|
||||
.byte CT_UPPER ; 206/ce _____N_____
|
||||
.byte CT_UPPER ; 207/cf _____O_____
|
||||
.byte CT_UPPER ; 208/d0 _____P_____
|
||||
.byte CT_UPPER ; 209/d1 _____Q_____
|
||||
.byte CT_UPPER ; 210/d2 _____R_____
|
||||
.byte CT_UPPER ; 211/d3 _____S_____
|
||||
.byte CT_UPPER ; 212/d4 _____T_____
|
||||
.byte CT_UPPER ; 213/d5 _____U_____
|
||||
.byte CT_UPPER ; 214/d6 _____V_____
|
||||
.byte CT_UPPER ; 215/d7 _____W_____
|
||||
.byte CT_UPPER ; 216/d8 _____X_____
|
||||
.byte CT_UPPER ; 217/d9 _____Y_____
|
||||
.byte CT_UPPER ; 218/da _____Z_____
|
||||
.byte $00 ; 219/db _____{_____
|
||||
.byte $00 ; 220/dc _____|_____
|
||||
.byte $00 ; 221/dd _____}_____
|
||||
.byte $00 ; 222/de _____~_____
|
||||
.byte $00 ; 223/df ___HOUSE___
|
||||
.byte $00 ; 224/e0 _a`_grave__
|
||||
.byte $00 ; 225/e1 _a'_acute__
|
||||
.byte $00 ; 226/e2 _a^_circum_
|
||||
.byte $00 ; 227/e3 _a~_tilde__
|
||||
.byte $00 ; 228/e4 _a"_dieres_
|
||||
.byte $00 ; 229/e5 _a__ring___
|
||||
.byte $00 ; 230/e6 _ae________
|
||||
.byte $00 ; 231/e7 _c,cedilla_
|
||||
.byte $00 ; 232/e8 _e`_grave__
|
||||
.byte $00 ; 233/e9 _e'_acute__
|
||||
.byte $00 ; 234/ea _e^_circum_
|
||||
.byte $00 ; 235/eb _e"_dieres_
|
||||
.byte $00 ; 236/ec _i`_grave__
|
||||
.byte $00 ; 237/ed _i'_acute__
|
||||
.byte $00 ; 238/ee _i^_circum_
|
||||
.byte $00 ; 239/ef _i"_dieres_
|
||||
.byte $00 ; 240/f0 _o^x_Eth_s_
|
||||
.byte $00 ; 241/f1 _n~_tilda__
|
||||
.byte $00 ; 242/f2 _o`_grave__
|
||||
.byte $00 ; 243/f3 _o'_acute__
|
||||
.byte $00 ; 244/f4 _o^_circum_
|
||||
.byte $00 ; 245/f5 _o~_tilde__
|
||||
.byte $00 ; 246/f6 _o"_dieres_
|
||||
.byte $00 ; 247/f7 __divide___
|
||||
.byte $00 ; 248/f8 _o/_slash__
|
||||
.byte $00 ; 249/f9 _u`_grave__
|
||||
.byte $00 ; 250/fa _u'_acute__
|
||||
.byte $00 ; 251/fb _u^_circum_
|
||||
.byte $00 ; 252/fc _u"_dieres_
|
||||
.byte $00 ; 253/fd _y'_acute__
|
||||
.byte $00 ; 254/fe _sm_thorn__
|
||||
.byte $00 ; 255/ff _y"_dieres_
|
29
libsrc/osic1p/cvline.s
Normal file
29
libsrc/osic1p/cvline.s
Normal file
@ -0,0 +1,29 @@
|
||||
;
|
||||
; based on CBM version
|
||||
; originally by:
|
||||
; Ullrich von Bassewitz, 08.08.1998
|
||||
;
|
||||
; void cvlinexy (unsigned char x, unsigned char y, unsigned char length);
|
||||
; void cvline (unsigned char length);
|
||||
;
|
||||
|
||||
.export _cvlinexy, _cvline
|
||||
.import popa, _gotoxy, putchar, newline
|
||||
.importzp tmp1
|
||||
|
||||
_cvlinexy:
|
||||
pha ; Save the length
|
||||
jsr popa ; Get y
|
||||
jsr _gotoxy ; Call this one, will pop params
|
||||
pla ; Restore the length and run into _cvline
|
||||
|
||||
_cvline:
|
||||
cmp #0 ; Is the length zero?
|
||||
beq L9 ; Jump if done
|
||||
sta tmp1
|
||||
L1: lda #$95 ; Vertical bar
|
||||
jsr putchar ; Write, no cursor advance
|
||||
jsr newline ; Advance cursor to next line
|
||||
dec tmp1
|
||||
bne L1
|
||||
L9: rts
|
16
libsrc/osic1p/extra/screen-s3-32x28.s
Normal file
16
libsrc/osic1p/extra/screen-s3-32x28.s
Normal file
@ -0,0 +1,16 @@
|
||||
;
|
||||
; Implementation of screen-layout related functions for Superboard ///
|
||||
;
|
||||
|
||||
.include "../osiscreen.inc"
|
||||
|
||||
S3_SCR_BASE := $D000 ; Base of Superboard /// video RAM
|
||||
S3_VRAM_SIZE = $0400 ; Size of Superboard /// video RAM (1 kB)
|
||||
S3_SCR_WIDTH = $20 ; Screen width
|
||||
S3_SCR_HEIGHT = $1C ; Screen height
|
||||
S3_SCR_FIRSTCHAR = $80 ; Offset of cursor position (0, 0) from base
|
||||
; of video RAM
|
||||
S3_SCROLL_DIST = $20 ; Memory distance for scrolling by one line
|
||||
|
||||
osi_screen_funcs S3_SCR_BASE, S3_VRAM_SIZE, S3_SCR_FIRSTCHAR, \
|
||||
S3_SCR_WIDTH, S3_SCR_HEIGHT, S3_SCROLL_DIST
|
7
libsrc/osic1p/extzp.inc
Normal file
7
libsrc/osic1p/extzp.inc
Normal file
@ -0,0 +1,7 @@
|
||||
;
|
||||
; Additional zero page locations for the Challenger 1P.
|
||||
;
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
|
||||
.globalzp CURS_X, CURS_Y, SCREEN_PTR, CHARBUF
|
20
libsrc/osic1p/extzp.s
Normal file
20
libsrc/osic1p/extzp.s
Normal file
@ -0,0 +1,20 @@
|
||||
;
|
||||
; Additional zero page locations for the Challenger 1P.
|
||||
; NOTE: The zeropage locations contained in this file get initialized
|
||||
; in the startup code, so if you change anything here, be sure to check
|
||||
; not only the linker config, but also the startup file.
|
||||
;
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
|
||||
.include "extzp.inc"
|
||||
|
||||
.segment "EXTZP" : zeropage
|
||||
|
||||
CURS_X: .res 1
|
||||
CURS_Y: .res 1
|
||||
SCREEN_PTR: .res 2
|
||||
CHARBUF: .res 1
|
||||
|
||||
; size 5
|
||||
; Adjust size of the ZP segment in osic1p.cfg if the size changes
|
13
libsrc/osic1p/gotox.s
Normal file
13
libsrc/osic1p/gotox.s
Normal file
@ -0,0 +1,13 @@
|
||||
;
|
||||
; copied from CBM implementation
|
||||
; originally by:
|
||||
; Ullrich von Bassewitz, 07.08.1998
|
||||
;
|
||||
; void gotox (unsigned char x);
|
||||
;
|
||||
.export _gotox
|
||||
.import plot
|
||||
.include "extzp.inc"
|
||||
|
||||
_gotox: sta CURS_X ; Set new position
|
||||
jmp plot ; And activate it
|
17
libsrc/osic1p/gotoxy.s
Normal file
17
libsrc/osic1p/gotoxy.s
Normal file
@ -0,0 +1,17 @@
|
||||
;
|
||||
; copied from CBM implementation
|
||||
;
|
||||
; originally by:
|
||||
; Ullrich von Bassewitz, 06.08.1998
|
||||
;
|
||||
; void gotoxy (unsigned char x, unsigned char y);
|
||||
;
|
||||
.export _gotoxy
|
||||
.import popa, plot
|
||||
.include "extzp.inc"
|
||||
|
||||
_gotoxy:
|
||||
sta CURS_Y ; Set Y
|
||||
jsr popa ; Get X
|
||||
sta CURS_X ; Set X
|
||||
jmp plot ; Set the cursor position
|
13
libsrc/osic1p/gotoy.s
Normal file
13
libsrc/osic1p/gotoy.s
Normal file
@ -0,0 +1,13 @@
|
||||
;
|
||||
; copied from CBM implementation
|
||||
; originally by:
|
||||
; Ullrich von Bassewitz, 0.08.1998
|
||||
;
|
||||
; void gotoy (unsigned char y);
|
||||
;
|
||||
.export _gotoy
|
||||
.import plot
|
||||
.include "extzp.inc"
|
||||
|
||||
_gotoy: sta CURS_Y ; Set the new position
|
||||
jmp plot ; And activate it
|
47
libsrc/osic1p/kbhit.s
Normal file
47
libsrc/osic1p/kbhit.s
Normal file
@ -0,0 +1,47 @@
|
||||
;
|
||||
; unsigned char kbhit (void);
|
||||
;
|
||||
; The method to detect a pressed key is based on the documentation in
|
||||
; "Section 3 Programmed Key Functions" in "The Challenger Character Graphics
|
||||
; Reference Manual"
|
||||
; We only want to return true for characters that can be returned by cgetc(),
|
||||
; but not for keys like <Shift> or <Ctrl>. Therefore a special handling is
|
||||
; needed for the first row. This is implemented by a bit mask that is stored
|
||||
; in tmp1 and that is set to zero after the first round.
|
||||
;
|
||||
|
||||
.export _kbhit
|
||||
.include "osic1p.inc"
|
||||
.include "extzp.inc"
|
||||
.include "zeropage.inc"
|
||||
|
||||
_kbhit:
|
||||
lda #%11011111 ; Mask for only checking the column for the
|
||||
sta tmp1 ; ESC key in the first keyboard row.
|
||||
|
||||
lda #%11111110 ; Mask for first keyboard row
|
||||
scan:
|
||||
sta KBD ; Select keyboard row
|
||||
tax ; Save A
|
||||
lda KBD ; Read keyboard columns
|
||||
ora tmp1 ; Mask out uninteresting keys (only relevant in
|
||||
; first row)
|
||||
cmp #$FF ; No keys pressed?
|
||||
bne keypressed
|
||||
lda #$00 ; For remaining rows no keys masked
|
||||
sta tmp1
|
||||
txa ; Restore A
|
||||
sec ; Want to shift in ones
|
||||
rol a ; Rotate row select to next bit position
|
||||
cmp #$FF ; Done?
|
||||
bne scan ; If not, continue
|
||||
lda #$00 ; Return false
|
||||
tax ; High byte of return is also zero
|
||||
sta CHARBUF ; No character in buffer
|
||||
rts
|
||||
keypressed:
|
||||
jsr INPUTC ; Get input character in A
|
||||
sta CHARBUF ; Save in buffer
|
||||
ldx #$00 ; High byte of return is always zero
|
||||
lda #$01 ; Return true
|
||||
rts
|
20
libsrc/osic1p/oserror.s
Normal file
20
libsrc/osic1p/oserror.s
Normal file
@ -0,0 +1,20 @@
|
||||
;
|
||||
; dummy implementation for Challenger 1P based on atmos implementation
|
||||
;
|
||||
; original by
|
||||
; Stefan Haubenthal, 2011-04-18
|
||||
;
|
||||
; int __fastcall__ _osmaperrno (unsigned char oserror);
|
||||
; /* Map a system specific error into a system independent code */
|
||||
;
|
||||
|
||||
.include "errno.inc"
|
||||
.export __osmaperrno
|
||||
|
||||
.proc __osmaperrno
|
||||
|
||||
lda #<EUNKNOWN
|
||||
ldx #>EUNKNOWN
|
||||
rts
|
||||
|
||||
.endproc
|
4
libsrc/osic1p/osic1p.inc
Normal file
4
libsrc/osic1p/osic1p.inc
Normal file
@ -0,0 +1,4 @@
|
||||
; Addresses
|
||||
INPUTC := $FD00 ; Input character from keyboard
|
||||
RESET := $FF00 ; Reset address, show boot prompt
|
||||
KBD := $DF00 ; Polled keyboard register
|
184
libsrc/osic1p/osiscreen.inc
Normal file
184
libsrc/osic1p/osiscreen.inc
Normal file
@ -0,0 +1,184 @@
|
||||
;
|
||||
; Macro definitions for screen layout modules
|
||||
;
|
||||
|
||||
.include "extzp.inc"
|
||||
|
||||
.linecont +
|
||||
|
||||
;
|
||||
; Internal function for screensize()
|
||||
;
|
||||
.macro osi_screensize ScrWidth, ScrHeight
|
||||
; Macro implementation of internal screensize
|
||||
; function for given width and height in
|
||||
; characters
|
||||
|
||||
.export screensize
|
||||
|
||||
.proc screensize
|
||||
ldx #ScrWidth
|
||||
ldy #ScrHeight
|
||||
rts
|
||||
.endproc
|
||||
.endmacro
|
||||
|
||||
;
|
||||
; void clrscr (void);
|
||||
;
|
||||
.macro osi_clrscr ScrBase, ScrRamSize
|
||||
|
||||
.export _clrscr
|
||||
|
||||
.proc _clrscr
|
||||
lda #<ScrBase ; Fill whole video RAM with blanks by calling
|
||||
ldx #>ScrBase ; memset appropriately
|
||||
jsr pushax
|
||||
|
||||
lda #' '
|
||||
ldx #$00
|
||||
jsr pushax
|
||||
|
||||
lda #<ScrRamSize
|
||||
ldx #>ScrRamSize
|
||||
jsr _memset
|
||||
|
||||
lda #$00 ; Cursor in upper left corner
|
||||
sta CURS_X
|
||||
sta CURS_Y
|
||||
|
||||
jmp plot ; Set the cursor position
|
||||
.endproc
|
||||
|
||||
.endmacro
|
||||
|
||||
;
|
||||
; cputc/cputcxy for Challenger 1P
|
||||
; Based on PET/CBM implementation
|
||||
;
|
||||
|
||||
.macro osi_cputfuncs ScrBase, ScrFirstChar, ScrWidth, ScrHeight, \
|
||||
ScrollDist, ScrLo, ScrHi
|
||||
|
||||
; Number of characters to move for scrolling
|
||||
; by one line
|
||||
ScrollLength = (ScrHeight - 1) * ScrollDist
|
||||
|
||||
;
|
||||
; void cputcxy (unsigned char x, unsigned char y, char c);
|
||||
; void cputc (char c);
|
||||
;
|
||||
.export _cputcxy, _cputc, cputdirect, putchar
|
||||
.export newline, plot
|
||||
|
||||
_cputcxy:
|
||||
pha ; Save C
|
||||
jsr popa ; Get Y
|
||||
jsr _gotoxy ; Set cursor, drop x
|
||||
pla ; Restore C
|
||||
|
||||
; Plot a character - also used as internal function
|
||||
|
||||
_cputc: cmp #$0A ; CR?
|
||||
bne L1
|
||||
lda #0
|
||||
sta CURS_X
|
||||
beq plot ; Recalculate pointers
|
||||
|
||||
L1: cmp #$0D ; LF?
|
||||
beq newline ; Recalculate pointers
|
||||
|
||||
cputdirect:
|
||||
jsr putchar ; Write the character to the screen
|
||||
|
||||
; Advance cursor position, register Y contains horizontal position after
|
||||
; putchar
|
||||
|
||||
cpy #(ScrWidth - 1) ; Check whether line is full
|
||||
bne L3
|
||||
jsr newline ; New line
|
||||
ldy #$FF ; + cr
|
||||
L3: iny
|
||||
sty CURS_X
|
||||
rts
|
||||
|
||||
newline:
|
||||
inc CURS_Y
|
||||
lda CURS_Y
|
||||
cmp #ScrHeight ; Screen height
|
||||
bne plot
|
||||
dec CURS_Y ; Bottom of screen reached, scroll
|
||||
|
||||
; Scroll destination address
|
||||
lda #<(ScrBase + ScrFirstChar)
|
||||
ldx #>(ScrBase + ScrFirstChar)
|
||||
jsr pushax
|
||||
|
||||
; Scroll source address
|
||||
lda #<(ScrBase + ScrFirstChar + ScrollDist)
|
||||
ldx #>(ScrBase + ScrFirstChar + ScrollDist)
|
||||
jsr pushax
|
||||
|
||||
; Number of characters to move
|
||||
lda #<ScrollLength
|
||||
ldx #>ScrollLength
|
||||
jsr _memmove
|
||||
|
||||
; Address of first character in last line
|
||||
; of screen
|
||||
lda #<(ScrBase + ScrFirstChar + ScrollLength)
|
||||
sta ptr1
|
||||
lda #>(ScrBase + ScrFirstChar + ScrollLength)
|
||||
sta ptr1+1
|
||||
|
||||
ldy #ScrWidth ; Fill last line with blanks
|
||||
lda #' '
|
||||
clrln: sta (ptr1),y
|
||||
dey
|
||||
bpl clrln
|
||||
|
||||
plot: ldy CURS_Y
|
||||
lda ScrLo,y
|
||||
sta SCREEN_PTR
|
||||
lda ScrHi,y
|
||||
sta SCREEN_PTR+1
|
||||
rts
|
||||
|
||||
; Write one character to the screen without doing anything else, return X
|
||||
; position in register Y
|
||||
|
||||
putchar:
|
||||
ldy CURS_X
|
||||
sta (SCREEN_PTR),y ; Set char
|
||||
rts
|
||||
|
||||
.endmacro
|
||||
|
||||
.macro osi_screen_funcs ScrBase, ScrRamSize, ScrFirstChar, \
|
||||
ScrWidth, ScrHeight, ScrollDist
|
||||
|
||||
.import popa, _gotoxy
|
||||
.import _memmove, _memset, pushax
|
||||
.importzp ptr1
|
||||
|
||||
.rodata
|
||||
|
||||
; Screen address tables - offset to real screen
|
||||
ScrTabLo:
|
||||
.repeat ScrHeight, I
|
||||
.byte <(ScrBase + ScrFirstChar + I * ScrollDist)
|
||||
.endrep
|
||||
|
||||
ScrTabHi:
|
||||
.repeat ScrHeight, I
|
||||
.byte >(ScrBase + ScrFirstChar + I * ScrollDist)
|
||||
.endrep
|
||||
|
||||
.code
|
||||
|
||||
osi_cputfuncs ScrBase, ScrFirstChar, ScrWidth, ScrHeight, \
|
||||
ScrollDist, ScrTabLo, ScrTabHi
|
||||
osi_screensize ScrWidth, ScrHeight
|
||||
osi_clrscr ScrBase, ScrRamSize
|
||||
|
||||
.endmacro
|
16
libsrc/osic1p/screen-c1p-24x24.s
Normal file
16
libsrc/osic1p/screen-c1p-24x24.s
Normal file
@ -0,0 +1,16 @@
|
||||
;
|
||||
; Implementation of screen-layout related functions for Challenger 1P
|
||||
;
|
||||
|
||||
.include "osiscreen.inc"
|
||||
|
||||
C1P_SCR_BASE := $D000 ; Base of C1P video RAM
|
||||
C1P_VRAM_SIZE = $0400 ; Size of C1P video RAM (1 kB)
|
||||
C1P_SCR_WIDTH = $18 ; Screen width
|
||||
C1P_SCR_HEIGHT = $18 ; Screen height
|
||||
C1P_SCR_FIRSTCHAR = $85 ; Offset of cursor position (0, 0) from base
|
||||
; of video RAM
|
||||
C1P_SCROLL_DIST = $20 ; Memory distance for scrolling by one line
|
||||
|
||||
osi_screen_funcs C1P_SCR_BASE, C1P_VRAM_SIZE, C1P_SCR_FIRSTCHAR, \
|
||||
C1P_SCR_WIDTH, C1P_SCR_HEIGHT, C1P_SCROLL_DIST
|
14
libsrc/osic1p/wherex.s
Normal file
14
libsrc/osic1p/wherex.s
Normal file
@ -0,0 +1,14 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 06.08.1998
|
||||
; Copied from cbm/wherex.s
|
||||
|
||||
; unsigned char wherex (void);
|
||||
;
|
||||
.export _wherex
|
||||
.include "extzp.inc"
|
||||
|
||||
.proc _wherex
|
||||
lda CURS_X
|
||||
ldx #$00
|
||||
rts
|
||||
.endproc
|
14
libsrc/osic1p/wherey.s
Normal file
14
libsrc/osic1p/wherey.s
Normal file
@ -0,0 +1,14 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 06.08.1998
|
||||
; Copied from cbm/wherey.s
|
||||
;
|
||||
; unsigned char wherey (void);
|
||||
;
|
||||
.export _wherey
|
||||
.include "extzp.inc"
|
||||
|
||||
.proc _wherey
|
||||
lda CURS_Y
|
||||
ldx #$00
|
||||
rts
|
||||
.endproc
|
@ -6,8 +6,8 @@
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
int uncompress (char* dest, unsigned* destLen,
|
||||
const char* source, unsigned sourceLen)
|
||||
int __fastcall__ uncompress (char* dest, unsigned* destLen,
|
||||
const char* source, unsigned sourceLen)
|
||||
{
|
||||
unsigned len;
|
||||
unsigned char* ptr;
|
||||
|
116
src/ca65/expr.c
116
src/ca65/expr.c
@ -62,6 +62,7 @@
|
||||
#include "symtab.h"
|
||||
#include "toklist.h"
|
||||
#include "ulabel.h"
|
||||
#include "macro.h"
|
||||
|
||||
|
||||
|
||||
@ -417,6 +418,34 @@ static ExprNode* FuncDefined (void)
|
||||
|
||||
|
||||
|
||||
static ExprNode* FuncIsMnemonic (void)
|
||||
/* Handle the .ISMNEMONIC, .ISMNEM builtin function */
|
||||
{
|
||||
int Instr = -1;
|
||||
|
||||
/* Check for a macro or an instruction depending on UbiquitousIdents */
|
||||
|
||||
if (CurTok.Tok == TOK_IDENT) {
|
||||
if (UbiquitousIdents) {
|
||||
/* Macros CAN be instructions, so check for them first */
|
||||
if (FindMacro (&CurTok.SVal) == 0) {
|
||||
Instr = FindInstruction (&CurTok.SVal);
|
||||
}
|
||||
} else {
|
||||
/* Macros and symbols may NOT use the names of instructions, so just check for the instruction */
|
||||
Instr = FindInstruction (&CurTok.SVal);
|
||||
}
|
||||
} else {
|
||||
Error ("Identifier expected.");
|
||||
}
|
||||
/* Skip the name */
|
||||
NextTok ();
|
||||
|
||||
return GenLiteralExpr (Instr > 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
ExprNode* FuncHiByte (void)
|
||||
/* Handle the .HIBYTE builtin function */
|
||||
{
|
||||
@ -629,6 +658,85 @@ static ExprNode* FuncReferenced (void)
|
||||
|
||||
|
||||
|
||||
static ExprNode* FuncAddrSize (void)
|
||||
/* Handle the .ADDRSIZE function */
|
||||
{
|
||||
StrBuf ScopeName = STATIC_STRBUF_INITIALIZER;
|
||||
StrBuf Name = STATIC_STRBUF_INITIALIZER;
|
||||
SymEntry* Sym;
|
||||
int AddrSize;
|
||||
int NoScope;
|
||||
|
||||
|
||||
/* Assume we don't know the size */
|
||||
AddrSize = 0;
|
||||
|
||||
/* Check for a cheap local which needs special handling */
|
||||
if (CurTok.Tok == TOK_LOCAL_IDENT) {
|
||||
|
||||
/* Cheap local symbol */
|
||||
Sym = SymFindLocal (SymLast, &CurTok.SVal, SYM_FIND_EXISTING);
|
||||
if (Sym == 0) {
|
||||
Error ("Unknown symbol or scope: `%m%p'", &CurTok.SVal);
|
||||
} else {
|
||||
AddrSize = Sym->AddrSize;
|
||||
}
|
||||
|
||||
/* Remember and skip SVal, terminate ScopeName so it is empty */
|
||||
SB_Copy (&Name, &CurTok.SVal);
|
||||
NextTok ();
|
||||
SB_Terminate (&ScopeName);
|
||||
|
||||
} else {
|
||||
|
||||
/* Parse the scope and the name */
|
||||
SymTable* ParentScope = ParseScopedIdent (&Name, &ScopeName);
|
||||
|
||||
/* Check if the parent scope is valid */
|
||||
if (ParentScope == 0) {
|
||||
/* No such scope */
|
||||
SB_Done (&ScopeName);
|
||||
SB_Done (&Name);
|
||||
return GenLiteral0 ();
|
||||
}
|
||||
|
||||
/* If ScopeName is empty, no explicit scope was specified. We have to
|
||||
** search upper scope levels in this case.
|
||||
*/
|
||||
NoScope = SB_IsEmpty (&ScopeName);
|
||||
|
||||
/* If we did find a scope with the name, read the symbol defining the
|
||||
** size, otherwise search for a symbol entry with the name and scope.
|
||||
*/
|
||||
if (NoScope) {
|
||||
Sym = SymFindAny (ParentScope, &Name);
|
||||
} else {
|
||||
Sym = SymFind (ParentScope, &Name, SYM_FIND_EXISTING);
|
||||
}
|
||||
/* If we found the symbol retrieve the size, otherwise complain */
|
||||
if (Sym) {
|
||||
AddrSize = Sym->AddrSize;
|
||||
} else {
|
||||
Error ("Unknown symbol or scope: `%m%p%m%p'", &ScopeName, &Name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (AddrSize == 0) {
|
||||
Warning (1, "Unknown address size: `%m%p%m%p'", &ScopeName, &Name);
|
||||
}
|
||||
|
||||
/* Free the string buffers */
|
||||
SB_Done (&ScopeName);
|
||||
SB_Done (&Name);
|
||||
|
||||
/* Return the size. */
|
||||
|
||||
return GenLiteralExpr (AddrSize);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static ExprNode* FuncSizeOf (void)
|
||||
/* Handle the .SIZEOF function */
|
||||
{
|
||||
@ -965,6 +1073,10 @@ static ExprNode* Factor (void)
|
||||
N = Function (FuncBankByte);
|
||||
break;
|
||||
|
||||
case TOK_ADDRSIZE:
|
||||
N = Function (FuncAddrSize);
|
||||
break;
|
||||
|
||||
case TOK_BLANK:
|
||||
N = Function (FuncBlank);
|
||||
break;
|
||||
@ -982,6 +1094,10 @@ static ExprNode* Factor (void)
|
||||
N = Function (FuncDefined);
|
||||
break;
|
||||
|
||||
case TOK_ISMNEMONIC:
|
||||
N = Function (FuncIsMnemonic);
|
||||
break;
|
||||
|
||||
case TOK_HIBYTE:
|
||||
N = Function (FuncHiByte);
|
||||
break;
|
||||
|
@ -63,6 +63,7 @@ static const char* FeatureKeys[FEAT_COUNT] = {
|
||||
"c_comments",
|
||||
"force_range",
|
||||
"underline_in_numbers",
|
||||
"addrsize",
|
||||
};
|
||||
|
||||
|
||||
@ -119,6 +120,7 @@ feature_t SetFeature (const StrBuf* Key)
|
||||
case FEAT_C_COMMENTS: CComments = 1; break;
|
||||
case FEAT_FORCE_RANGE: ForceRange = 1; break;
|
||||
case FEAT_UNDERLINE_IN_NUMBERS: UnderlineInNumbers= 1; break;
|
||||
case FEAT_ADDRSIZE: AddrSize = 1; break;
|
||||
default: /* Keep gcc silent */ break;
|
||||
}
|
||||
|
||||
|
@ -65,6 +65,7 @@ typedef enum {
|
||||
FEAT_C_COMMENTS,
|
||||
FEAT_FORCE_RANGE,
|
||||
FEAT_UNDERLINE_IN_NUMBERS,
|
||||
FEAT_ADDRSIZE,
|
||||
|
||||
/* Special value: Number of features available */
|
||||
FEAT_COUNT
|
||||
|
@ -82,3 +82,4 @@ unsigned char OrgPerSeg = 0; /* Make .org local to current seg */
|
||||
unsigned char CComments = 0; /* Allow C like comments */
|
||||
unsigned char ForceRange = 0; /* Force values into expected range */
|
||||
unsigned char UnderlineInNumbers = 0; /* Allow underlines in numbers */
|
||||
unsigned char AddrSize = 0; /* Allow .ADDRSIZE function */
|
||||
|
@ -84,6 +84,8 @@ extern unsigned char OrgPerSeg; /* Make .org local to current seg */
|
||||
extern unsigned char CComments; /* Allow C like comments */
|
||||
extern unsigned char ForceRange; /* Force values into expected range */
|
||||
extern unsigned char UnderlineInNumbers; /* Allow underlines in numbers */
|
||||
extern unsigned char AddrSize; /* Allow .ADDRSIZE function */
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -713,9 +713,9 @@ static const struct {
|
||||
{ "ROR", 0x000006F, 0x62, 1, PutAll },
|
||||
{ "RTI", 0x0000001, 0x40, 0, PutAll },
|
||||
{ "RTS", 0x0000001, 0x60, 0, PutAll },
|
||||
{ "SBC", 0x080A66C, 0xe0, 0, PutAll },
|
||||
{ "SAX", 0x0000001, 0x22, 0, PutAll },
|
||||
{ "SAY", 0x0000001, 0x42, 0, PutAll },
|
||||
{ "SBC", 0x080A66C, 0xe0, 0, PutAll },
|
||||
{ "SEC", 0x0000001, 0x38, 0, PutAll },
|
||||
{ "SED", 0x0000001, 0xf8, 0, PutAll },
|
||||
{ "SEI", 0x0000001, 0x78, 0, PutAll },
|
||||
|
@ -303,6 +303,10 @@ static void SetSys (const char* Sys)
|
||||
NewSymbol ("__SIM65C02__", 1);
|
||||
break;
|
||||
|
||||
case TGT_OSIC1P:
|
||||
NewSymbol ("__OSIC1P__", 1);
|
||||
break;
|
||||
|
||||
case TGT_PCENGINE:
|
||||
NewSymbol ("__PCE__", 1);
|
||||
break;
|
||||
|
@ -1964,6 +1964,7 @@ static CtrlDesc CtrlCmdTab [] = {
|
||||
{ ccNone, DoA16 },
|
||||
{ ccNone, DoA8 },
|
||||
{ ccNone, DoAddr }, /* .ADDR */
|
||||
{ ccNone, DoUnexpected }, /* .ADDRSIZE */
|
||||
{ ccNone, DoAlign },
|
||||
{ ccNone, DoASCIIZ },
|
||||
{ ccNone, DoAssert },
|
||||
@ -2039,6 +2040,7 @@ static CtrlDesc CtrlCmdTab [] = {
|
||||
{ ccNone, DoIncBin },
|
||||
{ ccNone, DoInclude },
|
||||
{ ccNone, DoInterruptor },
|
||||
{ ccNone, DoUnexpected }, /* .ISMNEMONIC */
|
||||
{ ccNone, DoInvalid }, /* .LEFT */
|
||||
{ ccNone, DoLineCont },
|
||||
{ ccNone, DoList },
|
||||
|
@ -135,6 +135,7 @@ struct DotKeyword {
|
||||
{ ".A16", TOK_A16 },
|
||||
{ ".A8", TOK_A8 },
|
||||
{ ".ADDR", TOK_ADDR },
|
||||
{ ".ADDRSIZE", TOK_ADDRSIZE },
|
||||
{ ".ALIGN", TOK_ALIGN },
|
||||
{ ".AND", TOK_BOOLAND },
|
||||
{ ".ASCIIZ", TOK_ASCIIZ },
|
||||
@ -222,6 +223,8 @@ struct DotKeyword {
|
||||
{ ".INCBIN", TOK_INCBIN },
|
||||
{ ".INCLUDE", TOK_INCLUDE },
|
||||
{ ".INTERRUPTOR", TOK_INTERRUPTOR },
|
||||
{ ".ISMNEM", TOK_ISMNEMONIC },
|
||||
{ ".ISMNEMONIC", TOK_ISMNEMONIC },
|
||||
{ ".LEFT", TOK_LEFT },
|
||||
{ ".LINECONT", TOK_LINECONT },
|
||||
{ ".LIST", TOK_LIST },
|
||||
@ -723,7 +726,24 @@ static token_t FindDotKeyword (void)
|
||||
R = bsearch (&K, DotKeywords, sizeof (DotKeywords) / sizeof (DotKeywords [0]),
|
||||
sizeof (DotKeywords [0]), CmpDotKeyword);
|
||||
if (R != 0) {
|
||||
|
||||
/* By default, disable any somewhat experiemental DotKeyword. */
|
||||
|
||||
switch (R->Tok) {
|
||||
|
||||
case TOK_ADDRSIZE:
|
||||
/* Disallow .ADDRSIZE function by default */
|
||||
if (AddrSize == 0) {
|
||||
return TOK_NONE;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return R->Tok;
|
||||
|
||||
} else {
|
||||
return TOK_NONE;
|
||||
}
|
||||
|
@ -696,10 +696,10 @@ void SymDump (FILE* F)
|
||||
|
||||
while (S) {
|
||||
/* Ignore unused symbols */
|
||||
if ((S->Flags & SF_UNUSED) != 0) {
|
||||
if ((S->Flags & SF_UNUSED) == 0) {
|
||||
fprintf (F,
|
||||
"%m%-24p %s %s %s %s %s\n",
|
||||
GetSymName (S),
|
||||
"%-24s %s %s %s %s %s\n",
|
||||
SB_GetConstBuf (GetSymName (S)),
|
||||
(S->Flags & SF_DEFINED)? "DEF" : "---",
|
||||
(S->Flags & SF_REFERENCED)? "REF" : "---",
|
||||
(S->Flags & SF_IMPORT)? "IMP" : "---",
|
||||
|
@ -123,6 +123,7 @@ typedef enum token_t {
|
||||
TOK_A16 = TOK_FIRSTPSEUDO,
|
||||
TOK_A8,
|
||||
TOK_ADDR,
|
||||
TOK_ADDRSIZE,
|
||||
TOK_ALIGN,
|
||||
TOK_ASCIIZ,
|
||||
TOK_ASSERT,
|
||||
@ -198,6 +199,7 @@ typedef enum token_t {
|
||||
TOK_INCBIN,
|
||||
TOK_INCLUDE,
|
||||
TOK_INTERRUPTOR,
|
||||
TOK_ISMNEMONIC,
|
||||
TOK_LEFT,
|
||||
TOK_LINECONT,
|
||||
TOK_LIST,
|
||||
|
@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2001-2012, Ullrich von Bassewitz */
|
||||
/* (C) 2001-2015, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
@ -46,6 +46,7 @@
|
||||
#include "codeseg.h"
|
||||
#include "datatype.h"
|
||||
#include "error.h"
|
||||
#include "global.h"
|
||||
#include "reginfo.h"
|
||||
#include "symtab.h"
|
||||
#include "codeinfo.h"
|
||||
@ -386,33 +387,35 @@ void GetFuncInfo (const char* Name, unsigned short* Use, unsigned short* Chg)
|
||||
** Search for it in the list of builtin functions.
|
||||
*/
|
||||
if (Name[0] == '_') {
|
||||
|
||||
/* Search in the symbol table, skip the leading underscore */
|
||||
SymEntry* E = FindGlobalSym (Name+1);
|
||||
|
||||
/* Did we find it in the top level table? */
|
||||
/* Did we find it in the top-level table? */
|
||||
if (E && IsTypeFunc (E->Type)) {
|
||||
|
||||
FuncDesc* D = E->V.F.Func;
|
||||
|
||||
/* A function may use the A or A/X registers if it is a fastcall
|
||||
** function. If it is not a fastcall function but a variadic one,
|
||||
** it will use the Y register (the parameter size is passed here).
|
||||
** In all other cases, no registers are used. However, we assume
|
||||
** that any function will destroy all registers.
|
||||
/* A variadic function will use the Y register (the parameter list
|
||||
** size is passed there). A fastcall function will use the A or A/X
|
||||
** registers. In all other cases, no registers are used. However,
|
||||
** we assume that any function will destroy all registers.
|
||||
*/
|
||||
if (IsQualFastcall (E->Type) && D->ParamCount > 0) {
|
||||
/* Will use registers depending on the last param */
|
||||
unsigned LastParamSize = CheckedSizeOf (D->LastParam->Type);
|
||||
if (LastParamSize == 1) {
|
||||
*Use = REG_A;
|
||||
} else if (LastParamSize == 2) {
|
||||
*Use = REG_AX;
|
||||
} else {
|
||||
*Use = REG_EAX;
|
||||
}
|
||||
} else if ((D->Flags & FD_VARIADIC) != 0) {
|
||||
if ((D->Flags & FD_VARIADIC) != 0) {
|
||||
*Use = REG_Y;
|
||||
} else if (D->ParamCount > 0 &&
|
||||
(AutoCDecl ?
|
||||
IsQualFastcall (E->Type) :
|
||||
!IsQualCDecl (E->Type))) {
|
||||
/* Will use registers depending on the last param. */
|
||||
switch (CheckedSizeOf (D->LastParam->Type)) {
|
||||
case 1u:
|
||||
*Use = REG_A;
|
||||
break;
|
||||
case 2u:
|
||||
*Use = REG_AX;
|
||||
break;
|
||||
default:
|
||||
*Use = REG_EAX;
|
||||
}
|
||||
} else {
|
||||
/* Will not use any registers */
|
||||
*Use = REG_NONE;
|
||||
|
@ -766,12 +766,8 @@ static unsigned Opt_toseqax_tosneax (StackOpData* D, const char* BoolTransformer
|
||||
InsertEntry (D, X, D->IP++);
|
||||
|
||||
/* Lhs load entries can be removed */
|
||||
if (LoadX->AM != AM65_IMM) {
|
||||
D->Lhs.X.Flags |= LI_REMOVE;
|
||||
}
|
||||
if (LoadA->AM != AM65_IMM) {
|
||||
D->Lhs.A.Flags |= LI_REMOVE;
|
||||
}
|
||||
D->Lhs.X.Flags |= LI_REMOVE;
|
||||
D->Lhs.A.Flags |= LI_REMOVE;
|
||||
|
||||
} else if ((D->Rhs.A.Flags & (LI_DIRECT | LI_RELOAD_Y)) == LI_DIRECT &&
|
||||
(D->Rhs.X.Flags & (LI_DIRECT | LI_RELOAD_Y)) == LI_DIRECT) {
|
||||
@ -794,12 +790,8 @@ static unsigned Opt_toseqax_tosneax (StackOpData* D, const char* BoolTransformer
|
||||
InsertEntry (D, X, D->IP++);
|
||||
|
||||
/* Rhs load entries can be removed */
|
||||
if (LoadX->AM != AM65_IMM) {
|
||||
D->Rhs.X.Flags |= LI_REMOVE;
|
||||
}
|
||||
if (LoadA->AM != AM65_IMM) {
|
||||
D->Rhs.A.Flags |= LI_REMOVE;
|
||||
}
|
||||
D->Rhs.X.Flags |= LI_REMOVE;
|
||||
D->Rhs.A.Flags |= LI_REMOVE;
|
||||
|
||||
} else if ((D->Rhs.A.Flags & LI_DIRECT) != 0 &&
|
||||
(D->Rhs.X.Flags & LI_DIRECT) != 0) {
|
||||
|
@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2012, Ullrich von Bassewitz */
|
||||
/* (C) 1998-2015, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
@ -293,15 +293,15 @@ void PrintType (FILE* F, const Type* T)
|
||||
/* Recursive call */
|
||||
PrintType (F, T + 1);
|
||||
if (T->A.L == UNSPECIFIED) {
|
||||
fprintf (F, "[]");
|
||||
fprintf (F, " []");
|
||||
} else {
|
||||
fprintf (F, "[%ld]", T->A.L);
|
||||
fprintf (F, " [%ld]", T->A.L);
|
||||
}
|
||||
return;
|
||||
case T_TYPE_PTR:
|
||||
/* Recursive call */
|
||||
PrintType (F, T + 1);
|
||||
fprintf (F, "*");
|
||||
fprintf (F, " *");
|
||||
return;
|
||||
case T_TYPE_FUNC:
|
||||
fprintf (F, "function returning ");
|
||||
@ -659,7 +659,7 @@ Type* GetBaseElementType (Type* T)
|
||||
** will return. Otherwise it will return the base element type, which means
|
||||
** the element type that is not an array.
|
||||
*/
|
||||
{
|
||||
{
|
||||
while (IsTypeArray (T)) {
|
||||
++T;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2012, Ullrich von Bassewitz */
|
||||
/* (C) 1998-2015, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
@ -603,6 +603,16 @@ INLINE int IsQualCDecl (const Type* T)
|
||||
# define IsQualCDecl(T) (((T)->C & T_QUAL_CDECL) != 0)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsQualCConv (const Type* T)
|
||||
/* Return true if the given type has a calling convention qualifier */
|
||||
{
|
||||
return (T->C & T_QUAL_CCONV) != 0;
|
||||
}
|
||||
#else
|
||||
# define IsQualCConv(T) (((T)->C & T_QUAL_CCONV) != 0)
|
||||
#endif
|
||||
|
||||
int IsVariadicFunc (const Type* T) attribute ((const));
|
||||
/* Return true if this is a function type or pointer to function type with
|
||||
** variable parameter list
|
||||
|
@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2013, Ullrich von Bassewitz */
|
||||
/* (C) 1998-2015, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
@ -85,7 +85,7 @@ struct StructInitData {
|
||||
|
||||
|
||||
static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers);
|
||||
/* Parse a type specificier */
|
||||
/* Parse a type specifier */
|
||||
|
||||
static unsigned ParseInitInternal (Type* T, int AllowFlexibleMembers);
|
||||
/* Parse initialization of variables. Return the number of data bytes. */
|
||||
@ -335,18 +335,30 @@ static void FixQualifiers (Type* DataType)
|
||||
T = DataType;
|
||||
while (T->C != T_END) {
|
||||
if (IsTypePtr (T)) {
|
||||
/* Calling convention qualifier on the pointer? */
|
||||
if (IsQualCConv (T)) {
|
||||
/* Pull the convention off of the pointer */
|
||||
Q = T[0].C & T_QUAL_CCONV;
|
||||
T[0].C &= ~T_QUAL_CCONV;
|
||||
|
||||
/* Fastcall qualifier on the pointer? */
|
||||
if (IsQualFastcall (T)) {
|
||||
/* Pointer to function which is not fastcall? */
|
||||
if (IsTypeFunc (T+1) && !IsQualFastcall (T+1)) {
|
||||
/* Move the fastcall qualifier from the pointer to
|
||||
** the function.
|
||||
*/
|
||||
T[0].C &= ~T_QUAL_FASTCALL;
|
||||
T[1].C |= T_QUAL_FASTCALL;
|
||||
/* Pointer to a function which doesn't have an explicit convention? */
|
||||
if (IsTypeFunc (T + 1)) {
|
||||
if (IsQualCConv (T + 1)) {
|
||||
if ((T[1].C & T_QUAL_CCONV) == Q) {
|
||||
Warning ("Pointer duplicates function's calling convention");
|
||||
} else {
|
||||
Error ("Function's and pointer's calling conventions are different");
|
||||
}
|
||||
} else {
|
||||
if (Q == T_QUAL_FASTCALL && IsVariadicFunc (T + 1)) {
|
||||
Error ("Variadic-function pointers cannot be __fastcall__");
|
||||
} else {
|
||||
/* Move the qualifier from the pointer to the function. */
|
||||
T[1].C |= Q;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Error ("Invalid `_fastcall__' qualifier for pointer");
|
||||
Error ("Not pointer to a function; can't use a calling convention");
|
||||
}
|
||||
}
|
||||
|
||||
@ -355,8 +367,8 @@ static void FixQualifiers (Type* DataType)
|
||||
if (Q == T_QUAL_NONE) {
|
||||
/* No address size qualifiers specified */
|
||||
if (IsTypeFunc (T+1)) {
|
||||
/* Pointer to function. Use the qualifier from the function
|
||||
** or the default if the function don't has one.
|
||||
/* Pointer to function. Use the qualifier from the function,
|
||||
** or the default if the function doesn't have one.
|
||||
*/
|
||||
Q = (T[1].C & T_QUAL_ADDRSIZE);
|
||||
if (Q == T_QUAL_NONE) {
|
||||
@ -368,7 +380,7 @@ static void FixQualifiers (Type* DataType)
|
||||
T[0].C |= Q;
|
||||
} else {
|
||||
/* We have address size qualifiers. If followed by a function,
|
||||
** apply these also to the function.
|
||||
** apply them to the function also.
|
||||
*/
|
||||
if (IsTypeFunc (T+1)) {
|
||||
TypeCode FQ = (T[1].C & T_QUAL_ADDRSIZE);
|
||||
@ -489,7 +501,7 @@ static void ParseEnumDecl (void)
|
||||
|
||||
|
||||
static int ParseFieldWidth (Declaration* Decl)
|
||||
/* Parse an optional field width. Returns -1 if no field width is speficied,
|
||||
/* Parse an optional field width. Returns -1 if no field width is specified,
|
||||
** otherwise the width of the field.
|
||||
*/
|
||||
{
|
||||
@ -862,7 +874,7 @@ NextMember: if (CurTok.Tok != TOK_COMMA) {
|
||||
|
||||
|
||||
static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers)
|
||||
/* Parse a type specificier */
|
||||
/* Parse a type specifier */
|
||||
{
|
||||
ident Ident;
|
||||
SymEntry* Entry;
|
||||
@ -1376,13 +1388,13 @@ static FuncDesc* ParseFuncDecl (void)
|
||||
static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode)
|
||||
/* Recursively process declarators. Build a type array in reverse order. */
|
||||
{
|
||||
/* Read optional function or pointer qualifiers. These modify the
|
||||
** identifier or token to the right. For convenience, we allow the fastcall
|
||||
** qualifier also for pointers here. If it is a pointer-to-function, the
|
||||
** qualifier will later be transfered to the function itself. If it's a
|
||||
/* Read optional function or pointer qualifiers. They modify the
|
||||
** identifier or token to the right. For convenience, we allow a calling
|
||||
** convention also for pointers here. If it's a pointer-to-function, the
|
||||
** qualifier later will be transfered to the function itself. If it's a
|
||||
** pointer to something else, it will be flagged as an error.
|
||||
*/
|
||||
TypeCode Qualifiers = OptionalQualifiers (T_QUAL_ADDRSIZE | T_QUAL_FASTCALL);
|
||||
TypeCode Qualifiers = OptionalQualifiers (T_QUAL_ADDRSIZE | T_QUAL_CCONV);
|
||||
|
||||
/* Pointer to something */
|
||||
if (CurTok.Tok == TOK_STAR) {
|
||||
@ -1390,10 +1402,10 @@ static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode)
|
||||
/* Skip the star */
|
||||
NextToken ();
|
||||
|
||||
/* Allow const, restrict and volatile qualifiers */
|
||||
/* Allow const, restrict, and volatile qualifiers */
|
||||
Qualifiers |= OptionalQualifiers (T_QUAL_CONST | T_QUAL_VOLATILE | T_QUAL_RESTRICT);
|
||||
|
||||
/* Parse the type, the pointer points to */
|
||||
/* Parse the type that the pointer points to */
|
||||
Declarator (Spec, D, Mode);
|
||||
|
||||
/* Add the type */
|
||||
@ -1443,7 +1455,7 @@ static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode)
|
||||
|
||||
/* We cannot specify fastcall for variadic functions */
|
||||
if ((F->Flags & FD_VARIADIC) && (Qualifiers & T_QUAL_FASTCALL)) {
|
||||
Error ("Variadic functions cannot be `__fastcall__'");
|
||||
Error ("Variadic functions cannot be __fastcall__");
|
||||
Qualifiers &= ~T_QUAL_FASTCALL;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* expr.c
|
||||
**
|
||||
** Ullrich von Bassewitz, 21.06.1998
|
||||
** 1998-06-21, Ullrich von Bassewitz
|
||||
** 2015-06-26, Greg King
|
||||
*/
|
||||
|
||||
|
||||
@ -470,9 +471,11 @@ static void FunctionCall (ExprDesc* Expr)
|
||||
/* Handle function pointers transparently */
|
||||
IsFuncPtr = IsTypeFuncPtr (Expr->Type);
|
||||
if (IsFuncPtr) {
|
||||
|
||||
/* Check wether it's a fastcall function that has parameters */
|
||||
IsFastcall = IsQualFastcall (Expr->Type + 1) && (Func->ParamCount > 0);
|
||||
/* Check whether it's a fastcall function that has parameters */
|
||||
IsFastcall = (Func->Flags & FD_VARIADIC) == 0 && Func->ParamCount > 0 &&
|
||||
(AutoCDecl ?
|
||||
IsQualFastcall (Expr->Type + 1) :
|
||||
!IsQualCDecl (Expr->Type + 1));
|
||||
|
||||
/* Things may be difficult, depending on where the function pointer
|
||||
** resides. If the function pointer is an expression of some sort
|
||||
@ -517,7 +520,10 @@ static void FunctionCall (ExprDesc* Expr)
|
||||
}
|
||||
|
||||
/* If we didn't inline the function, get fastcall info */
|
||||
IsFastcall = IsQualFastcall (Expr->Type);
|
||||
IsFastcall = (Func->Flags & FD_VARIADIC) == 0 &&
|
||||
(AutoCDecl ?
|
||||
IsQualFastcall (Expr->Type) :
|
||||
!IsQualCDecl (Expr->Type));
|
||||
}
|
||||
|
||||
/* Parse the parameter list */
|
||||
@ -1707,8 +1713,13 @@ void hie10 (ExprDesc* Expr)
|
||||
} else {
|
||||
Error ("Illegal indirection");
|
||||
}
|
||||
/* The * operator yields an lvalue */
|
||||
ED_MakeLVal (Expr);
|
||||
/* If the expression points to an array, then don't convert the
|
||||
** address -- it already is the location of the first element.
|
||||
*/
|
||||
if (!IsTypeArray (Expr->Type)) {
|
||||
/* The * operator yields an lvalue */
|
||||
ED_MakeLVal (Expr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2012, Ullrich von Bassewitz */
|
||||
/* (C) 2000-2015, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
@ -460,6 +460,9 @@ void NewFunc (SymEntry* Func)
|
||||
*/
|
||||
if (D->ParamCount > 0 || (D->Flags & FD_VARIADIC) != 0) {
|
||||
g_importmainargs ();
|
||||
|
||||
/* The start-up code doesn't fast-call main(). */
|
||||
Func->Type->C |= T_QUAL_CDECL;
|
||||
}
|
||||
|
||||
/* Determine if this is a main function in a C99 environment that
|
||||
@ -478,13 +481,12 @@ void NewFunc (SymEntry* Func)
|
||||
PushLiteralPool (Func);
|
||||
|
||||
/* If this is a fastcall function, push the last parameter onto the stack */
|
||||
if (IsQualFastcall (Func->Type) && D->ParamCount > 0) {
|
||||
|
||||
if ((D->Flags & FD_VARIADIC) == 0 && D->ParamCount > 0 &&
|
||||
(AutoCDecl ?
|
||||
IsQualFastcall (Func->Type) :
|
||||
!IsQualCDecl (Func->Type))) {
|
||||
unsigned Flags;
|
||||
|
||||
/* Fastcall functions may never have an ellipsis or the compiler is buggy */
|
||||
CHECK ((D->Flags & FD_VARIADIC) == 0);
|
||||
|
||||
/* Generate the push */
|
||||
if (IsTypeFunc (D->LastParam->Type)) {
|
||||
/* Pointer to function */
|
||||
|
@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2012, Ullrich von Bassewitz */
|
||||
/* (C) 1998-2015, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
@ -44,6 +44,7 @@
|
||||
|
||||
|
||||
unsigned char AddSource = 0; /* Add source lines as comments */
|
||||
unsigned char AutoCDecl = 0; /* Make functions default to __cdecl__ */
|
||||
unsigned char DebugInfo = 0; /* Add debug info to the obj */
|
||||
unsigned char PreprocessOnly = 0; /* Just preprocess the input */
|
||||
unsigned char DebugOptOutput = 0; /* Output debug stuff */
|
||||
|
@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2012, Ullrich von Bassewitz */
|
||||
/* (C) 1998-2015, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
@ -52,6 +52,7 @@
|
||||
|
||||
/* Options */
|
||||
extern unsigned char AddSource; /* Add source lines as comments */
|
||||
extern unsigned char AutoCDecl; /* Make functions default to __cdecl__ */
|
||||
extern unsigned char DebugInfo; /* Add debug info to the obj */
|
||||
extern unsigned char PreprocessOnly; /* Just preprocess the input */
|
||||
extern unsigned char DebugOptOutput; /* Output debug stuff */
|
||||
|
@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2013, Ullrich von Bassewitz */
|
||||
/* (C) 2000-2015, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
@ -104,6 +104,7 @@ static void Usage (void)
|
||||
"\n"
|
||||
"Long options:\n"
|
||||
" --add-source\t\t\tInclude source as comment\n"
|
||||
" --all-cdecl\t\t\tMake functions default to __cdecl__\n"
|
||||
" --bss-name seg\t\tSet the name of the BSS segment\n"
|
||||
" --check-stack\t\t\tGenerate stack overflow checks\n"
|
||||
" --code-name seg\t\tSet the name of the CODE segment\n"
|
||||
@ -258,6 +259,10 @@ static void SetSys (const char* Sys)
|
||||
DefineNumericMacro ("__SIM65C02__", 1);
|
||||
break;
|
||||
|
||||
case TGT_OSIC1P:
|
||||
DefineNumericMacro ("__OSIC1P__", 1);
|
||||
break;
|
||||
|
||||
case TGT_PCENGINE:
|
||||
DefineNumericMacro ("__PCE__", 1);
|
||||
break;
|
||||
@ -350,6 +355,15 @@ static void OptAddSource (const char* Opt attribute ((unused)),
|
||||
|
||||
|
||||
|
||||
static void OptAllCDecl (const char* Opt attribute ((unused)),
|
||||
const char* Arg attribute ((unused)))
|
||||
/* Make functions default to cdecl instead of fastcall. */
|
||||
{
|
||||
AutoCDecl = 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void OptBssName (const char* Opt attribute ((unused)), const char* Arg)
|
||||
/* Handle the --bss-name option */
|
||||
{
|
||||
@ -790,6 +804,7 @@ int main (int argc, char* argv[])
|
||||
/* Program long options */
|
||||
static const LongOpt OptTab[] = {
|
||||
{ "--add-source", 0, OptAddSource },
|
||||
{ "--all-cdecl", 0, OptAllCDecl },
|
||||
{ "--bss-name", 1, OptBssName },
|
||||
{ "--check-stack", 0, OptCheckStack },
|
||||
{ "--code-name", 1, OptCodeName },
|
||||
|
@ -6,10 +6,10 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* (C) 1998-2015, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
@ -37,6 +37,7 @@
|
||||
|
||||
/* cc65 */
|
||||
#include "funcdesc.h"
|
||||
#include "global.h"
|
||||
#include "symtab.h"
|
||||
#include "typecmp.h"
|
||||
|
||||
@ -245,23 +246,36 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (LeftType == T_TYPE_FUNC) {
|
||||
/* If a calling convention wasn't set explicitly,
|
||||
** then assume the default one.
|
||||
*/
|
||||
if ((LeftQual & T_QUAL_CCONV) == T_QUAL_NONE) {
|
||||
LeftQual |= (AutoCDecl || IsVariadicFunc (lhs)) ? T_QUAL_CDECL : T_QUAL_FASTCALL;
|
||||
}
|
||||
if ((RightQual & T_QUAL_CCONV) == T_QUAL_NONE) {
|
||||
RightQual |= (AutoCDecl || IsVariadicFunc (rhs)) ? T_QUAL_CDECL : T_QUAL_FASTCALL;
|
||||
}
|
||||
}
|
||||
|
||||
if (LeftQual != RightQual) {
|
||||
/* On the first indirection level, different qualifiers mean
|
||||
** that the types are still compatible. On the second level,
|
||||
** this is a (maybe minor) error, so we create a special
|
||||
** return code, since a qualifier is dropped from a pointer.
|
||||
** Starting from the next level, the types are incompatible
|
||||
** if the qualifiers differ.
|
||||
** that the types still are compatible. On the second level,
|
||||
** that is a (maybe minor) error. We create a special return-code
|
||||
** if a qualifier is dropped from a pointer. But, different calling
|
||||
** conventions are incompatible. Starting from the next level,
|
||||
** the types are incompatible if the qualifiers differ.
|
||||
*/
|
||||
/* (Debugging statement) */
|
||||
/* printf ("Ind = %d %06X != %06X\n", Indirections, LeftQual, RightQual); */
|
||||
switch (Indirections) {
|
||||
|
||||
case 0:
|
||||
SetResult (Result, TC_STRICT_COMPATIBLE);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
/* A non const value on the right is compatible to a
|
||||
/* A non-const value on the right is compatible to a
|
||||
** const one to the left, same for volatile.
|
||||
*/
|
||||
if ((LeftQual & T_QUAL_CONST) < (RightQual & T_QUAL_CONST) ||
|
||||
@ -270,7 +284,11 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
|
||||
} else {
|
||||
SetResult (Result, TC_STRICT_COMPATIBLE);
|
||||
}
|
||||
break;
|
||||
|
||||
if (LeftType != T_TYPE_FUNC || (LeftQual & T_QUAL_CCONV) == (RightQual & T_QUAL_CCONV)) {
|
||||
break;
|
||||
}
|
||||
/* else fall through */
|
||||
|
||||
default:
|
||||
SetResult (Result, TC_INCOMPATIBLE);
|
||||
@ -280,7 +298,6 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
|
||||
|
||||
/* Check for special type elements */
|
||||
switch (LeftType) {
|
||||
|
||||
case T_TYPE_PTR:
|
||||
++Indirections;
|
||||
break;
|
||||
|
@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2011, Ullrich von Bassewitz */
|
||||
/* (C) 2000-2015, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
@ -50,7 +50,7 @@
|
||||
|
||||
|
||||
/* Translation table with direct (no) translation */
|
||||
static unsigned char CTNone[256] = {
|
||||
static const unsigned char CTNone[256] = {
|
||||
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
|
||||
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
|
||||
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
|
||||
@ -69,8 +69,8 @@ static unsigned char CTNone[256] = {
|
||||
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,
|
||||
};
|
||||
|
||||
/* Translation table ISO-8859-1 -> ATASCII */
|
||||
static const unsigned char CTAtari [256] = {
|
||||
/* Translation table ISO-8859-1 -> AtASCII */
|
||||
static const unsigned char CTAtari[256] = {
|
||||
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0xFD,0x08,0x7F,0x9B,0x0B,0x7D,0x0D,0x0E,0x0F,
|
||||
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
|
||||
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
|
||||
@ -89,8 +89,28 @@ static const unsigned char CTAtari [256] = {
|
||||
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,
|
||||
};
|
||||
|
||||
/* Translation table ISO-8859-1 -> PETSCII */
|
||||
static const unsigned char CTPET [256] = {
|
||||
/* Translation table ISO-8859-1 -> OSASCII */
|
||||
static const unsigned char CTOSI[256] = {
|
||||
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
|
||||
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
|
||||
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
|
||||
0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
|
||||
0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,
|
||||
0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,
|
||||
0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
|
||||
0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0x7D,0x7C,0x7F,0x7E,
|
||||
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
|
||||
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
|
||||
0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,
|
||||
0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,
|
||||
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
|
||||
0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
|
||||
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,
|
||||
};
|
||||
|
||||
/* Translation table ISO-8859-1 -> PetSCII */
|
||||
static const unsigned char CTPET[256] = {
|
||||
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x14,0x09,0x0D,0x11,0x93,0x0A,0x0E,0x0F,
|
||||
0x10,0x0B,0x12,0x13,0x08,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
|
||||
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
|
||||
@ -142,6 +162,7 @@ static const TargetEntry TargetMap[] = {
|
||||
{ "module", TGT_MODULE },
|
||||
{ "nes", TGT_NES },
|
||||
{ "none", TGT_NONE },
|
||||
{ "osic1p", TGT_OSIC1P },
|
||||
{ "pce", TGT_PCENGINE },
|
||||
{ "pet", TGT_PET },
|
||||
{ "plus4", TGT_PLUS4 },
|
||||
@ -168,6 +189,7 @@ static const TargetProperties PropertyTable[TGT_COUNT] = {
|
||||
{ "plus4", CPU_6502, BINFMT_BINARY, CTPET },
|
||||
{ "cbm510", CPU_6502, BINFMT_BINARY, CTPET },
|
||||
{ "cbm610", CPU_6502, BINFMT_BINARY, CTPET },
|
||||
{ "osic1p", CPU_6502, BINFMT_BINARY, CTOSI },
|
||||
{ "pet", CPU_6502, BINFMT_BINARY, CTPET },
|
||||
{ "bbc", CPU_6502, BINFMT_BINARY, CTNone },
|
||||
{ "apple2", CPU_6502, BINFMT_BINARY, CTNone },
|
||||
|
@ -64,6 +64,7 @@ typedef enum {
|
||||
TGT_PLUS4,
|
||||
TGT_CBM510,
|
||||
TGT_CBM610,
|
||||
TGT_OSIC1P,
|
||||
TGT_PET,
|
||||
TGT_BBC,
|
||||
TGT_APPLE2,
|
||||
|
@ -47,7 +47,7 @@
|
||||
|
||||
|
||||
#define VER_MAJOR 2U
|
||||
#define VER_MINOR 14U
|
||||
#define VER_MINOR 15U
|
||||
|
||||
|
||||
|
||||
|
@ -6,10 +6,10 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2006 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* (C) 2000-2014, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
@ -66,6 +66,18 @@ void AddrCheck (unsigned Addr)
|
||||
|
||||
|
||||
|
||||
attr_t GetAttr (unsigned Addr)
|
||||
/* Return the attribute for the given address */
|
||||
{
|
||||
/* Check the given address */
|
||||
AddrCheck (Addr);
|
||||
|
||||
/* Return the attribute */
|
||||
return AttrTab[Addr];
|
||||
}
|
||||
|
||||
|
||||
|
||||
int SegmentDefined (unsigned Start, unsigned End)
|
||||
/* Return true if the atSegment bit is set somewhere in the given range */
|
||||
{
|
||||
@ -79,14 +91,18 @@ int SegmentDefined (unsigned Start, unsigned End)
|
||||
|
||||
|
||||
|
||||
int HaveSegmentChange (unsigned Addr)
|
||||
/* Return true if the segment change attribute is set for the given address */
|
||||
int IsSegmentEnd (unsigned Addr)
|
||||
/* Return true if a segment ends at the given address */
|
||||
{
|
||||
/* Check the given address */
|
||||
AddrCheck (Addr);
|
||||
return (GetAttr (Addr) & atSegmentEnd) != 0x0000;
|
||||
}
|
||||
|
||||
/* Return the attribute */
|
||||
return (AttrTab[Addr] & atSegmentChange) != 0;
|
||||
|
||||
|
||||
int IsSegmentStart (unsigned Addr)
|
||||
/* Return true if a segment starts at the given address */
|
||||
{
|
||||
return (GetAttr (Addr) & atSegmentStart) != 0x0000;
|
||||
}
|
||||
|
||||
|
||||
@ -145,18 +161,6 @@ void MarkAddr (unsigned Addr, attr_t Attr)
|
||||
|
||||
|
||||
|
||||
attr_t GetAttr (unsigned Addr)
|
||||
/* Return the attribute for the given address */
|
||||
{
|
||||
/* Check the given address */
|
||||
AddrCheck (Addr);
|
||||
|
||||
/* Return the attribute */
|
||||
return AttrTab[Addr];
|
||||
}
|
||||
|
||||
|
||||
|
||||
attr_t GetStyleAttr (unsigned Addr)
|
||||
/* Return the style attribute for the given address */
|
||||
{
|
||||
|
@ -6,10 +6,10 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2006 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* (C) 2000-2014, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
@ -47,33 +47,34 @@
|
||||
typedef enum attr_t {
|
||||
|
||||
/* Styles */
|
||||
atDefault = 0x0000, /* Default style */
|
||||
atCode = 0x0001,
|
||||
atIllegal = 0x0002,
|
||||
atByteTab = 0x0003, /* Same as illegal */
|
||||
atDByteTab = 0x0004,
|
||||
atWordTab = 0x0005,
|
||||
atDWordTab = 0x0006,
|
||||
atAddrTab = 0x0007,
|
||||
atRtsTab = 0x0008,
|
||||
atTextTab = 0x0009,
|
||||
atSkip = 0x000A, /* Skip code completely */
|
||||
atDefault = 0x0000, /* Default style */
|
||||
atCode = 0x0001,
|
||||
atIllegal = 0x0002,
|
||||
atByteTab = 0x0003, /* Same as illegal */
|
||||
atDByteTab = 0x0004,
|
||||
atWordTab = 0x0005,
|
||||
atDWordTab = 0x0006,
|
||||
atAddrTab = 0x0007,
|
||||
atRtsTab = 0x0008,
|
||||
atTextTab = 0x0009,
|
||||
atSkip = 0x000A, /* Skip code completely */
|
||||
|
||||
/* Label flags */
|
||||
atNoLabel = 0x0000, /* No label for this address */
|
||||
atExtLabel = 0x0010, /* External label */
|
||||
atIntLabel = 0x0020, /* Internally generated label */
|
||||
atDepLabel = 0x0040, /* Dependent label */
|
||||
atUnnamedLabel = 0x0080, /* Unnamed label */
|
||||
atNoLabel = 0x0000, /* No label for this address */
|
||||
atExtLabel = 0x0010, /* External label */
|
||||
atIntLabel = 0x0020, /* Internally generated label */
|
||||
atDepLabel = 0x0040, /* Dependent label */
|
||||
atUnnamedLabel = 0x0080, /* Unnamed label */
|
||||
|
||||
atLabelDefined = 0x0100, /* True if we defined the label */
|
||||
atLabelDefined = 0x0100, /* True if we defined the label */
|
||||
|
||||
atStyleMask = 0x000F, /* Output style */
|
||||
atLabelMask = 0x00F0, /* Label information */
|
||||
atStyleMask = 0x000F, /* Output style */
|
||||
atLabelMask = 0x00F0, /* Label information */
|
||||
|
||||
/* Segment */
|
||||
atSegment = 0x0100, /* Code is in a segment */
|
||||
atSegmentChange = 0x0200, /* Either segment start or segment end */
|
||||
atSegment = 0x0100, /* Code is in a segment */
|
||||
atSegmentEnd = 0x0200, /* Segment end */
|
||||
atSegmentStart = 0x0400, /* Segment start */
|
||||
} attr_t;
|
||||
|
||||
|
||||
@ -87,11 +88,17 @@ typedef enum attr_t {
|
||||
void AddrCheck (unsigned Addr);
|
||||
/* Check if the given address has a valid range */
|
||||
|
||||
attr_t GetAttr (unsigned Addr);
|
||||
/* Return the attribute for the given address */
|
||||
|
||||
int SegmentDefined (unsigned Start, unsigned End);
|
||||
/* Return true if the atSegment bit is set somewhere in the given range */
|
||||
|
||||
int HaveSegmentChange (unsigned Addr);
|
||||
/* Return true if the segment change attribute is set for the given address */
|
||||
int IsSegmentEnd (unsigned Addr);
|
||||
/* Return true if a segment ends at the given address */
|
||||
|
||||
int IsSegmentStart (unsigned Addr);
|
||||
/* Return true if a segment starts at the given address */
|
||||
|
||||
unsigned GetGranularity (attr_t Style);
|
||||
/* Get the granularity for the given style */
|
||||
@ -102,9 +109,6 @@ void MarkRange (unsigned Start, unsigned End, attr_t Attr);
|
||||
void MarkAddr (unsigned Addr, attr_t Attr);
|
||||
/* Mark an address with an attribute */
|
||||
|
||||
attr_t GetAttr (unsigned Addr);
|
||||
/* Return the attribute for the given address */
|
||||
|
||||
attr_t GetStyleAttr (unsigned Addr);
|
||||
/* Return the style attribute for the given address */
|
||||
|
||||
@ -114,5 +118,4 @@ attr_t GetLabelAttr (unsigned Addr);
|
||||
|
||||
|
||||
/* End of attrtab.h */
|
||||
|
||||
#endif
|
||||
|
@ -6,10 +6,10 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2007 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* (C) 2000-2014, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
@ -65,12 +65,12 @@ static unsigned GetSpan (attr_t Style)
|
||||
attr_t Attr;
|
||||
if (MustDefLabel(PC+Count)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Attr = GetAttr (PC+Count);
|
||||
if ((Attr & atStyleMask) != Style) {
|
||||
break;
|
||||
}
|
||||
if ((Attr & atSegmentChange)) {
|
||||
if ((Attr & (atSegmentStart | atSegmentEnd))) {
|
||||
break;
|
||||
}
|
||||
++Count;
|
||||
|
@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2011, Ullrich von Bassewitz */
|
||||
/* (C) 2000-2014, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
@ -748,16 +748,13 @@ static void SegmentSection (void)
|
||||
if (Start < 0) {
|
||||
InfoError ("Start address is missing");
|
||||
}
|
||||
if (Start == End) {
|
||||
InfoError ("Segment is empty");
|
||||
}
|
||||
if (Start > End) {
|
||||
InfoError ("Start address of segment is greater than end address");
|
||||
}
|
||||
|
||||
/* Check that segments do not overlap */
|
||||
if (SegmentDefined ((unsigned) Start, (unsigned) End)) {
|
||||
InfoError ("Segments cannot overlap");
|
||||
InfoError ("Segments must not overlap");
|
||||
}
|
||||
|
||||
/* Remember the segment data */
|
||||
|
@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2011, Ullrich von Bassewitz */
|
||||
/* (C) 1998-2014, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
@ -60,6 +60,7 @@
|
||||
#include "opctable.h"
|
||||
#include "output.h"
|
||||
#include "scanner.h"
|
||||
#include "segment.h"
|
||||
|
||||
|
||||
|
||||
@ -347,6 +348,8 @@ static void OptVersion (const char* Opt attribute ((unused)),
|
||||
static void OneOpcode (unsigned RemainingBytes)
|
||||
/* Disassemble one opcode */
|
||||
{
|
||||
unsigned I;
|
||||
|
||||
/* Get the opcode from the current address */
|
||||
unsigned char OPC = GetCodeByte (PC);
|
||||
|
||||
@ -356,6 +359,14 @@ static void OneOpcode (unsigned RemainingBytes)
|
||||
/* Get the output style for the current PC */
|
||||
attr_t Style = GetStyleAttr (PC);
|
||||
|
||||
/* If a segment begins here, then name that segment.
|
||||
** Note that the segment is named even if its code is being skipped,
|
||||
** because some of its later code might not be skipped.
|
||||
*/
|
||||
if (IsSegmentStart (PC)) {
|
||||
StartSegment (GetSegmentStartName (PC), GetSegmentAddrSize (PC));
|
||||
}
|
||||
|
||||
/* If we have a label at this address, output the label and an attached
|
||||
** comment, provided that we aren't in a skip area.
|
||||
*/
|
||||
@ -371,7 +382,8 @@ static void OneOpcode (unsigned RemainingBytes)
|
||||
** - ...if we have enough bytes remaining for the code at this address.
|
||||
** - ...if the current instruction is valid for the given CPU.
|
||||
** - ...if there is no label somewhere between the instruction bytes.
|
||||
** If any of these conditions is false, switch to data mode.
|
||||
** - ...if there is no segment change between the instruction bytes.
|
||||
** If any one of those conditions is false, switch to data mode.
|
||||
*/
|
||||
if (Style == atDefault) {
|
||||
if (D->Size > RemainingBytes) {
|
||||
@ -381,9 +393,15 @@ static void OneOpcode (unsigned RemainingBytes)
|
||||
Style = atIllegal;
|
||||
MarkAddr (PC, Style);
|
||||
} else {
|
||||
unsigned I;
|
||||
for (I = 1; I < D->Size; ++I) {
|
||||
if (HaveLabel (PC+I) || HaveSegmentChange (PC+I)) {
|
||||
for (I = PC + D->Size; --I > PC; ) {
|
||||
if (HaveLabel (I) || IsSegmentStart (I)) {
|
||||
Style = atIllegal;
|
||||
MarkAddr (PC, Style);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (I = 0; I < D->Size - 1u; ++I) {
|
||||
if (IsSegmentEnd (PC + I)) {
|
||||
Style = atIllegal;
|
||||
MarkAddr (PC, Style);
|
||||
break;
|
||||
@ -406,7 +424,6 @@ static void OneOpcode (unsigned RemainingBytes)
|
||||
*/
|
||||
if (D->Size <= RemainingBytes) {
|
||||
/* Output labels within the next insn */
|
||||
unsigned I;
|
||||
for (I = 1; I < D->Size; ++I) {
|
||||
ForwardLabel (I);
|
||||
}
|
||||
@ -453,7 +470,16 @@ static void OneOpcode (unsigned RemainingBytes)
|
||||
DataByteLine (1);
|
||||
++PC;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Change back to the default CODE segment if
|
||||
** a named segment stops at the current address.
|
||||
*/
|
||||
for (I = D->Size; I >= 1; --I) {
|
||||
if (IsSegmentEnd (PC - I)) {
|
||||
EndSegment ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2009, Ullrich von Bassewitz */
|
||||
/* (C) 2000-2014, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
@ -63,6 +63,8 @@ static unsigned Col = 1; /* Current column */
|
||||
static unsigned Line = 0; /* Current line on page */
|
||||
static unsigned Page = 1; /* Current output page */
|
||||
|
||||
static const char* SegmentName = 0; /* Name of current segment */
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -223,23 +225,6 @@ void DefConst (const char* Name, const char* Comment, unsigned Addr)
|
||||
|
||||
|
||||
|
||||
void StartSegment (const char* Name, unsigned AddrSize)
|
||||
/* Start a segment */
|
||||
{
|
||||
if (Pass == PassCount) {
|
||||
Output (".segment");
|
||||
Indent (ACol);
|
||||
if (AddrSize == ADDR_SIZE_DEFAULT) {
|
||||
Output ("\"%s\"", Name);
|
||||
} else {
|
||||
Output ("\"%s\": %s", Name, AddrSizeToStr (AddrSize));
|
||||
}
|
||||
LineFeed ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void DataByteLine (unsigned ByteCount)
|
||||
/* Output a line with bytes */
|
||||
{
|
||||
@ -335,6 +320,39 @@ void SeparatorLine (void)
|
||||
|
||||
|
||||
|
||||
void StartSegment (const char* Name, unsigned AddrSize)
|
||||
/* Start a segment */
|
||||
{
|
||||
if (Pass == PassCount) {
|
||||
LineFeed ();
|
||||
Output (".segment");
|
||||
Indent (ACol);
|
||||
SegmentName = Name;
|
||||
Output ("\"%s\"", Name);
|
||||
if (AddrSize != ADDR_SIZE_DEFAULT) {
|
||||
Output (": %s", AddrSizeToStr (AddrSize));
|
||||
}
|
||||
LineFeed ();
|
||||
LineFeed ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void EndSegment (void)
|
||||
/* End a segment */
|
||||
{
|
||||
LineFeed ();
|
||||
Output ("; End of \"%s\" segment", SegmentName);
|
||||
LineFeed ();
|
||||
SeparatorLine ();
|
||||
Output (".code");
|
||||
LineFeed ();
|
||||
LineFeed ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void UserComment (const char* Comment)
|
||||
/* Output a comment line */
|
||||
{
|
||||
|
@ -6,10 +6,10 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2007 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* (C) 2000-2014, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
@ -74,12 +74,6 @@ void DefForward (const char* Name, const char* Comment, unsigned Offs);
|
||||
|
||||
void DefConst (const char* Name, const char* Comment, unsigned Addr);
|
||||
/* Define an address constant */
|
||||
|
||||
void StartSegment (const char* Name, unsigned AddrSize);
|
||||
/* Start a segment */
|
||||
|
||||
void EndSegment (void);
|
||||
/* End a segment */
|
||||
|
||||
void OneDataByte (void);
|
||||
/* Output a .byte line with the current code byte */
|
||||
@ -99,6 +93,12 @@ void DataDWordLine (unsigned ByteCount);
|
||||
void SeparatorLine (void);
|
||||
/* Print a separator line */
|
||||
|
||||
void StartSegment (const char* Name, unsigned AddrSize);
|
||||
/* Start a segment */
|
||||
|
||||
void EndSegment (void);
|
||||
/* End a segment */
|
||||
|
||||
void UserComment (const char* Comment);
|
||||
/* Output a comment line */
|
||||
|
||||
@ -111,5 +111,4 @@ void OutputSettings (void);
|
||||
|
||||
|
||||
/* End of output.h */
|
||||
|
||||
#endif
|
||||
|
@ -6,10 +6,10 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2007 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* (C) 2007-2014, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
@ -58,18 +58,15 @@
|
||||
typedef struct Segment Segment;
|
||||
struct Segment {
|
||||
Segment* NextStart; /* Pointer to next segment */
|
||||
Segment* NextEnd; /* Pointer to next segment */
|
||||
unsigned long Start;
|
||||
unsigned long End;
|
||||
unsigned AddrSize;
|
||||
char Name[1]; /* Name, dynamically allocated */
|
||||
};
|
||||
|
||||
/* Tables containing the segments. A segment is inserted using it's hash
|
||||
** value. Collision is done by single linked lists.
|
||||
/* Table containing the segments. A segment is inserted using its hash
|
||||
** value. Collisions are handled by single-linked lists.
|
||||
*/
|
||||
static Segment* StartTab[HASH_SIZE]; /* Table containing segment starts */
|
||||
static Segment* EndTab[HASH_SIZE]; /* Table containing segment ends */
|
||||
|
||||
|
||||
|
||||
@ -90,20 +87,53 @@ void AddAbsSegment (unsigned Start, unsigned End, const char* Name)
|
||||
|
||||
/* Fill in the data */
|
||||
S->Start = Start;
|
||||
S->End = End;
|
||||
S->AddrSize = ADDR_SIZE_ABS;
|
||||
memcpy (S->Name, Name, Len + 1);
|
||||
|
||||
/* Insert the segment into the hash tables */
|
||||
/* Insert the segment into the hash table */
|
||||
S->NextStart = StartTab[Start % HASH_SIZE];
|
||||
StartTab[Start % HASH_SIZE] = S;
|
||||
S->NextEnd = EndTab[End % HASH_SIZE];
|
||||
EndTab[End % HASH_SIZE] = S;
|
||||
|
||||
/* Mark start and end of the segment */
|
||||
MarkAddr (Start, atSegmentChange);
|
||||
MarkAddr (End, atSegmentChange);
|
||||
MarkAddr (Start, atSegmentStart);
|
||||
MarkAddr (End, atSegmentEnd);
|
||||
|
||||
/* Mark the addresses within the segment */
|
||||
MarkRange (Start, End, atSegment);
|
||||
}
|
||||
|
||||
|
||||
|
||||
char* GetSegmentStartName (unsigned Addr)
|
||||
/* Return the name of the segment which starts at the given address */
|
||||
{
|
||||
Segment* S = StartTab[Addr % HASH_SIZE];
|
||||
|
||||
/* Search the collision list for the exact address */
|
||||
while (S != 0) {
|
||||
if (S->Start == Addr) {
|
||||
return S->Name;
|
||||
}
|
||||
S = S->NextStart;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned GetSegmentAddrSize (unsigned Addr)
|
||||
/* Return the address size of the segment which starts at the given address */
|
||||
{
|
||||
Segment* S = StartTab[Addr % HASH_SIZE];
|
||||
|
||||
/* Search the collision list for the exact address */
|
||||
while (S != 0) {
|
||||
if (S->Start == Addr) {
|
||||
return S->AddrSize;
|
||||
}
|
||||
S = S->NextStart;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -6,10 +6,10 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2007 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* (C) 2007-2014, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
@ -47,8 +47,13 @@
|
||||
void AddAbsSegment (unsigned Start, unsigned End, const char* Name);
|
||||
/* Add an absolute segment to the segment table */
|
||||
|
||||
char* GetSegmentStartName (unsigned Addr);
|
||||
/* Return the name of the segment which starts at the given address */
|
||||
|
||||
unsigned GetSegmentAddrSize (unsigned Addr);
|
||||
/* Return the address size of the segment which starts at the given address */
|
||||
|
||||
|
||||
|
||||
/* End of segment.h */
|
||||
|
||||
#endif
|
||||
|
@ -1,41 +1,43 @@
|
||||
|
||||
# toplevel makefile for the regression tests
|
||||
# top-level makefile for the regression tests
|
||||
|
||||
MAKE := make --no-print-dir
|
||||
# You can comment this special target when you debug the regression tests.
|
||||
# Then, make will give you more progress reports.
|
||||
.SILENT:
|
||||
|
||||
ifneq ($(shell echo),)
|
||||
CMD_EXE = 1
|
||||
CMD_EXE := 1
|
||||
endif
|
||||
|
||||
ifdef CMD_EXE
|
||||
RM := del /f
|
||||
EXE := .exe
|
||||
MKDIR = mkdir
|
||||
RMDIR = rmdir
|
||||
DEL = -del /f $(subst /,\,$1)
|
||||
MKDIR = mkdir $(subst /,\,$1)
|
||||
RMDIR = -rmdir /s /q $(subst /,\,$1)
|
||||
else
|
||||
RM := rm -f
|
||||
EXE :=
|
||||
MKDIR = mkdir -p
|
||||
RMDIR = rmdir
|
||||
DEL = $(RM) $1
|
||||
MKDIR = mkdir $1
|
||||
RMDIR = rmdir $1
|
||||
endif
|
||||
|
||||
WORKDIR := ../testwrk
|
||||
|
||||
.PHONY: dotests clean
|
||||
CC := gcc
|
||||
|
||||
.PHONY: all dotests continue mostly-clean clean
|
||||
|
||||
all: dotests
|
||||
|
||||
$(WORKDIR):
|
||||
@$(MKDIR) $(WORKDIR)
|
||||
$(call MKDIR,$(WORKDIR))
|
||||
|
||||
$(WORKDIR)/bdiff$(EXE): $(WORKDIR)
|
||||
@$(CC) -o $(WORKDIR)/bdiff$(EXE) bdiff.c
|
||||
$(WORKDIR)/bdiff$(EXE): bdiff.c | $(WORKDIR)
|
||||
$(CC) -O2 -o $@ $<
|
||||
|
||||
dotests: $(WORKDIR)/bdiff$(EXE)
|
||||
@$(MAKE) -C val clean all
|
||||
@$(MAKE) -C ref clean all
|
||||
@$(MAKE) -C err clean all
|
||||
@$(MAKE) -C misc clean all
|
||||
.NOTPARALLEL:
|
||||
|
||||
dotests: mostly-clean continue
|
||||
|
||||
continue: $(WORKDIR)/bdiff$(EXE)
|
||||
@$(MAKE) -C val all
|
||||
@ -43,10 +45,12 @@ continue: $(WORKDIR)/bdiff$(EXE)
|
||||
@$(MAKE) -C err all
|
||||
@$(MAKE) -C misc all
|
||||
|
||||
clean:
|
||||
mostly-clean:
|
||||
@$(MAKE) -C val clean
|
||||
@$(MAKE) -C ref clean
|
||||
@$(MAKE) -C err clean
|
||||
@$(MAKE) -C misc clean
|
||||
@$(RM) $(WORKDIR)/bdiff$(EXE)
|
||||
@$(RMDIR) $(WORKDIR)
|
||||
|
||||
clean: mostly-clean
|
||||
@$(call DEL,$(WORKDIR)/bdiff$(EXE))
|
||||
@$(call RMDIR,$(WORKDIR))
|
||||
|
@ -2,51 +2,47 @@
|
||||
# makefile for the tests that MUST NOT compile
|
||||
|
||||
ifneq ($(shell echo),)
|
||||
CMD_EXE = 1
|
||||
CMD_EXE := 1
|
||||
endif
|
||||
|
||||
CC65FLAGS = -t sim6502
|
||||
ifdef CMD_EXE
|
||||
NOT := - # Hack
|
||||
DEL = -del /f $(subst /,\,$1)
|
||||
else
|
||||
NOT := !
|
||||
DEL = $(RM) $1
|
||||
endif
|
||||
|
||||
CC65FLAGS := -t sim6502
|
||||
|
||||
CL65 := $(if $(wildcard ../../bin/cl65*),../../bin/cl65,cl65)
|
||||
|
||||
ifdef CMD_EXE
|
||||
RM := del /f
|
||||
else
|
||||
RM := rm -f
|
||||
endif
|
||||
|
||||
WORKDIR := ./../../testwrk
|
||||
WORKDIR := ../../testwrk
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
SOURCES := $(wildcard *.c)
|
||||
TESTS := $(SOURCES:%.c=$(WORKDIR)/%.prg)
|
||||
TESTS += $(SOURCES:%.c=$(WORKDIR)/%.o.prg)
|
||||
TESTS += $(SOURCES:%.c=$(WORKDIR)/%.os.prg)
|
||||
TESTS += $(SOURCES:%.c=$(WORKDIR)/%.osi.prg)
|
||||
TESTS += $(SOURCES:%.c=$(WORKDIR)/%.osir.prg)
|
||||
TESTS += $(SOURCES:%.c=$(WORKDIR)/%.oi.prg)
|
||||
TESTS += $(SOURCES:%.c=$(WORKDIR)/%.oir.prg)
|
||||
TESTS += $(SOURCES:%.c=$(WORKDIR)/%.or.prg)
|
||||
TESTS := $(foreach option,. .o. .os. .osi. .osir. .oi. .oir. .or.,$(SOURCES:%.c=$(WORKDIR)/%$(option)prg))
|
||||
|
||||
all: $(TESTS)
|
||||
|
||||
$(WORKDIR)/%.prg: %.c
|
||||
! $(CL65) $(CC65FLAGS) $< -o $@
|
||||
$(NOT) $(CL65) $(CC65FLAGS) $< -o $@
|
||||
$(WORKDIR)/%.o.prg: %.c
|
||||
! $(CL65) -O $(CC65FLAGS) $< -o $@
|
||||
$(NOT) $(CL65) -O $(CC65FLAGS) $< -o $@
|
||||
$(WORKDIR)/%.os.prg: %.c
|
||||
! $(CL65) -Os $(CC65FLAGS) $< -o $@
|
||||
$(NOT) $(CL65) -Os $(CC65FLAGS) $< -o $@
|
||||
$(WORKDIR)/%.osi.prg: %.c
|
||||
! $(CL65) -Osi $(CC65FLAGS) $< -o $@
|
||||
$(NOT) $(CL65) -Osi $(CC65FLAGS) $< -o $@
|
||||
$(WORKDIR)/%.osir.prg: %.c
|
||||
! $(CL65) -Osir $(CC65FLAGS) $< -o $@
|
||||
$(NOT) $(CL65) -Osir $(CC65FLAGS) $< -o $@
|
||||
$(WORKDIR)/%.oi.prg: %.c
|
||||
! $(CL65) -Oi $(CC65FLAGS) $< -o $@
|
||||
$(NOT) $(CL65) -Oi $(CC65FLAGS) $< -o $@
|
||||
$(WORKDIR)/%.oir.prg: %.c
|
||||
! $(CL65) -Oir $(CC65FLAGS) $< -o $@
|
||||
$(NOT) $(CL65) -Oir $(CC65FLAGS) $< -o $@
|
||||
$(WORKDIR)/%.or.prg: %.c
|
||||
! $(CL65) -Or $(CC65FLAGS) $< -o $@
|
||||
$(NOT) $(CL65) -Or $(CC65FLAGS) $< -o $@
|
||||
|
||||
clean:
|
||||
@$(RM) $(TESTS)
|
||||
@$(RM) $(SOURCES:%.c=$(WORKDIR)/%.o)
|
||||
@$(call DEL,$(TESTS))
|
||||
@$(call DEL,$(SOURCES:.c=.o))
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user