Initializing vm6502 repository
This commit is contained in:
commit
ba946c39a2
149 changed files with 45076 additions and 0 deletions
42
65b2js.c
Normal file
42
65b2js.c
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* 65b2js.c
|
||||||
|
*
|
||||||
|
* Created on: May 19, 2011
|
||||||
|
* Author: Scott Duensing
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
if (argc != 2) {
|
||||||
|
printf("usage: %s filename\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
FILE *file = fopen(argv[1], "r");
|
||||||
|
if (file == 0) {
|
||||||
|
printf("Could not open file\n");
|
||||||
|
return 2;
|
||||||
|
} else {
|
||||||
|
int c;
|
||||||
|
int count = 0;
|
||||||
|
int first = 1;
|
||||||
|
printf("var PROGRAM = [\n");
|
||||||
|
while ((c = fgetc(file)) != EOF) {
|
||||||
|
if (first == 1)
|
||||||
|
first = 0;
|
||||||
|
else
|
||||||
|
printf(", ");
|
||||||
|
if (++count > 15) {
|
||||||
|
printf("\n");
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
printf("0x%02x", c);
|
||||||
|
}
|
||||||
|
if (count != 0)
|
||||||
|
printf("\n");
|
||||||
|
printf("];\n");
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
8820
EhBASIC/basic-v6502.asm
Normal file
8820
EhBASIC/basic-v6502.asm
Normal file
File diff suppressed because it is too large
Load diff
7
EhBASIC/build.sh
Executable file
7
EhBASIC/build.sh
Executable file
|
|
@ -0,0 +1,7 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
BASE=basic-v6502
|
||||||
|
|
||||||
|
../../xa-2.3.5/xa -M -e $BASE.error.txt -l $BASE.label.txt -o $BASE.out $BASE.asm
|
||||||
|
../../vm/65b2js/Debug/65b2js $BASE.out > $BASE.js
|
||||||
|
cp $BASE.js ../../vm/Virtual\ Computer/software/.
|
||||||
8691
EhBASIC/original/basic.asm
Normal file
8691
EhBASIC/original/basic.asm
Normal file
File diff suppressed because it is too large
Load diff
134
EhBASIC/original/min_mon.asm
Normal file
134
EhBASIC/original/min_mon.asm
Normal file
|
|
@ -0,0 +1,134 @@
|
||||||
|
|
||||||
|
; minimal monitor for EhBASIC and 6502 simulator V1.05
|
||||||
|
|
||||||
|
; To run EhBASIC on the simulator load and assemble [F7] this file, start the simulator
|
||||||
|
; running [F6] then start the code with the RESET [CTRL][SHIFT]R. Just selecting RUN
|
||||||
|
; will do nothing, you'll still have to do a reset to run the code.
|
||||||
|
|
||||||
|
.include "basic.asm"
|
||||||
|
|
||||||
|
; put the IRQ and MNI code in RAM so that it can be changed
|
||||||
|
|
||||||
|
IRQ_vec = VEC_SV+2 ; IRQ code vector
|
||||||
|
NMI_vec = IRQ_vec+$0A ; NMI code vector
|
||||||
|
|
||||||
|
; setup for the 6502 simulator environment
|
||||||
|
|
||||||
|
IO_AREA = $F000 ; set I/O area for this monitor
|
||||||
|
|
||||||
|
ACIAsimwr = IO_AREA+$01 ; simulated ACIA write port
|
||||||
|
ACIAsimrd = IO_AREA+$04 ; simulated ACIA read port
|
||||||
|
|
||||||
|
; now the code. all this does is set up the vectors and interrupt code
|
||||||
|
; and wait for the user to select [C]old or [W]arm start. nothing else
|
||||||
|
; fits in less than 128 bytes
|
||||||
|
|
||||||
|
*= $FF80 ; pretend this is in a 1/8K ROM
|
||||||
|
|
||||||
|
; reset vector points here
|
||||||
|
|
||||||
|
RES_vec
|
||||||
|
CLD ; clear decimal mode
|
||||||
|
LDX #$FF ; empty stack
|
||||||
|
TXS ; set the stack
|
||||||
|
|
||||||
|
; set up vectors and interrupt code, copy them to page 2
|
||||||
|
|
||||||
|
LDY #END_CODE-LAB_vec ; set index/count
|
||||||
|
LAB_stlp
|
||||||
|
LDA LAB_vec-1,Y ; get byte from interrupt code
|
||||||
|
STA VEC_IN-1,Y ; save to RAM
|
||||||
|
DEY ; decrement index/count
|
||||||
|
BNE LAB_stlp ; loop if more to do
|
||||||
|
|
||||||
|
; now do the signon message, Y = $00 here
|
||||||
|
|
||||||
|
LAB_signon
|
||||||
|
LDA LAB_mess,Y ; get byte from sign on message
|
||||||
|
BEQ LAB_nokey ; exit loop if done
|
||||||
|
|
||||||
|
JSR V_OUTP ; output character
|
||||||
|
INY ; increment index
|
||||||
|
BNE LAB_signon ; loop, branch always
|
||||||
|
|
||||||
|
LAB_nokey
|
||||||
|
JSR V_INPT ; call scan input device
|
||||||
|
BCC LAB_nokey ; loop if no key
|
||||||
|
|
||||||
|
AND #$DF ; mask xx0x xxxx, ensure upper case
|
||||||
|
CMP #'W' ; compare with [W]arm start
|
||||||
|
BEQ LAB_dowarm ; branch if [W]arm start
|
||||||
|
|
||||||
|
CMP #'C' ; compare with [C]old start
|
||||||
|
BNE RES_vec ; loop if not [C]old start
|
||||||
|
|
||||||
|
JMP LAB_COLD ; do EhBASIC cold start
|
||||||
|
|
||||||
|
LAB_dowarm
|
||||||
|
JMP LAB_WARM ; do EhBASIC warm start
|
||||||
|
|
||||||
|
; byte out to simulated ACIA
|
||||||
|
|
||||||
|
ACIAout
|
||||||
|
STA ACIAsimwr ; save byte to simulated ACIA
|
||||||
|
RTS
|
||||||
|
|
||||||
|
; byte in from simulated ACIA
|
||||||
|
|
||||||
|
ACIAin
|
||||||
|
LDA ACIAsimrd ; get byte from simulated ACIA
|
||||||
|
BEQ LAB_nobyw ; branch if no byte waiting
|
||||||
|
|
||||||
|
SEC ; flag byte received
|
||||||
|
RTS
|
||||||
|
|
||||||
|
LAB_nobyw
|
||||||
|
CLC ; flag no byte received
|
||||||
|
no_load ; empty load vector for EhBASIC
|
||||||
|
no_save ; empty save vector for EhBASIC
|
||||||
|
RTS
|
||||||
|
|
||||||
|
; vector tables
|
||||||
|
|
||||||
|
LAB_vec
|
||||||
|
.word ACIAin ; byte in from simulated ACIA
|
||||||
|
.word ACIAout ; byte out to simulated ACIA
|
||||||
|
.word no_load ; null load vector for EhBASIC
|
||||||
|
.word no_save ; null save vector for EhBASIC
|
||||||
|
|
||||||
|
; EhBASIC IRQ support
|
||||||
|
|
||||||
|
IRQ_CODE
|
||||||
|
PHA ; save A
|
||||||
|
LDA IrqBase ; get the IRQ flag byte
|
||||||
|
LSR ; shift the set b7 to b6, and on down ...
|
||||||
|
ORA IrqBase ; OR the original back in
|
||||||
|
STA IrqBase ; save the new IRQ flag byte
|
||||||
|
PLA ; restore A
|
||||||
|
RTI
|
||||||
|
|
||||||
|
; EhBASIC NMI support
|
||||||
|
|
||||||
|
NMI_CODE
|
||||||
|
PHA ; save A
|
||||||
|
LDA NmiBase ; get the NMI flag byte
|
||||||
|
LSR ; shift the set b7 to b6, and on down ...
|
||||||
|
ORA NmiBase ; OR the original back in
|
||||||
|
STA NmiBase ; save the new NMI flag byte
|
||||||
|
PLA ; restore A
|
||||||
|
RTI
|
||||||
|
|
||||||
|
END_CODE
|
||||||
|
|
||||||
|
LAB_mess
|
||||||
|
.byte $0D,$0A,"6502 EhBASIC [C]old/[W]arm ?",$00
|
||||||
|
; sign on string
|
||||||
|
|
||||||
|
; system vectors
|
||||||
|
|
||||||
|
*= $FFFA
|
||||||
|
|
||||||
|
.word NMI_vec ; NMI vector
|
||||||
|
.word RES_vec ; RESET vector
|
||||||
|
.word IRQ_vec ; IRQ vector
|
||||||
|
|
||||||
26
EhBASIC/original/readme.txt
Normal file
26
EhBASIC/original/readme.txt
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
|
||||||
|
Enhanced BASIC is a BASIC interpreter for the 6502 family microprocessors. It
|
||||||
|
is constructed to be quick and powerful and easily ported between 6502 systems.
|
||||||
|
It requires few resources to run and includes instructions to facilitate easy
|
||||||
|
low level handling of hardware devices. It also retains most of the powerful
|
||||||
|
high level instructions from similar BASICs.
|
||||||
|
|
||||||
|
EhBASIC is free but not copyright free. For non commercial use there is only one
|
||||||
|
restriction, any derivative work should include, in any binary image distributed,
|
||||||
|
the string "Derived from EhBASIC" and in any distribution that includes human
|
||||||
|
readable files a file that includes the above string in a human readable form
|
||||||
|
e.g. not as a comment in an HTML file.
|
||||||
|
|
||||||
|
For commercial use please contact me, Lee Davison, at leeedavison@googlemail.com
|
||||||
|
for conditions.
|
||||||
|
|
||||||
|
For more information on EhBASIC, other versions of EhBASIC and other projects
|
||||||
|
please visit my site at ..
|
||||||
|
|
||||||
|
http://members.multimania.co.uk/leeedavison/index.html
|
||||||
|
|
||||||
|
|
||||||
|
P.S. c't magazin, henceforth refered to as "those thieving german bastards", are
|
||||||
|
prohibited from using this or any version of EhBASIC for any of their projects
|
||||||
|
or products. The excuse "we don't charge people for it" doesn't wash, it adds
|
||||||
|
value to your product so you owe me.
|
||||||
3023
Krusader/Krusader 1.3 65C02.asm
Normal file
3023
Krusader/Krusader 1.3 65C02.asm
Normal file
File diff suppressed because it is too large
Load diff
3038
Krusader/krusader 1.3.asm
Normal file
3038
Krusader/krusader 1.3.asm
Normal file
File diff suppressed because it is too large
Load diff
BIN
Krusader/krusader13.pdf
Normal file
BIN
Krusader/krusader13.pdf
Normal file
Binary file not shown.
4
urls.txt
Normal file
4
urls.txt
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
- Assembler http://school.anhb.uwa.edu.au/personalpages/kwessen/apple1/Krusader.htm
|
||||||
|
- BASIC http://www.themotionstore.com/leeedavison/6502/ehbasic/index.html
|
||||||
|
- Pascal http://pascal.hansotten.com/
|
||||||
|
- DOS http://www.z80.eu/dos65.html
|
||||||
12
vm/ConsoleDummy.js
Normal file
12
vm/ConsoleDummy.js
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
(function (con) {
|
||||||
|
// the dummy function
|
||||||
|
function dummy() {};
|
||||||
|
// console methods that may exist
|
||||||
|
for(var methods = "assert,count,debug,dir,dirxml,error,exception,group,groupCollapsed,groupEnd,info,log,markTimeline,profile,profileEnd,time,timeEnd,trace,warn".split(','), func; func = methods.pop();) {
|
||||||
|
con[func] = con[func] || dummy;
|
||||||
|
}
|
||||||
|
}(window.console = window.console || {}));
|
||||||
|
// we do this crazy little dance so that the `console` object
|
||||||
|
// inside the function is a name that can be shortened to a single
|
||||||
|
// letter by the compressor to make the compressed script as tiny
|
||||||
|
// as possible.
|
||||||
339
vm/LICENSE.txt
Normal file
339
vm/LICENSE.txt
Normal file
|
|
@ -0,0 +1,339 @@
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
License is intended to guarantee your freedom to share and change free
|
||||||
|
software--to make sure the software is free for all its users. This
|
||||||
|
General Public License applies to most of the Free Software
|
||||||
|
Foundation's software and to any other program whose authors commit to
|
||||||
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
|
the GNU Lesser General Public License instead.) You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
this service if you wish), that you receive source code or can get it
|
||||||
|
if you want it, that you can change the software or use pieces of it
|
||||||
|
in new free programs; and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
anyone to deny you these rights or to ask you to surrender the rights.
|
||||||
|
These restrictions translate to certain responsibilities for you if you
|
||||||
|
distribute copies of the software, or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must give the recipients all the rights that
|
||||||
|
you have. You must make sure that they, too, receive or can get the
|
||||||
|
source code. And you must show them these terms so they know their
|
||||||
|
rights.
|
||||||
|
|
||||||
|
We protect your rights with two steps: (1) copyright the software, and
|
||||||
|
(2) offer you this license which gives you legal permission to copy,
|
||||||
|
distribute and/or modify the software.
|
||||||
|
|
||||||
|
Also, for each author's protection and ours, we want to make certain
|
||||||
|
that everyone understands that there is no warranty for this free
|
||||||
|
software. If the software is modified by someone else and passed on, we
|
||||||
|
want its recipients to know that what they have is not the original, so
|
||||||
|
that any problems introduced by others will not reflect on the original
|
||||||
|
authors' reputations.
|
||||||
|
|
||||||
|
Finally, any free program is threatened constantly by software
|
||||||
|
patents. We wish to avoid the danger that redistributors of a free
|
||||||
|
program will individually obtain patent licenses, in effect making the
|
||||||
|
program proprietary. To prevent this, we have made it clear that any
|
||||||
|
patent must be licensed for everyone's free use or not licensed at all.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License applies to any program or other work which contains
|
||||||
|
a notice placed by the copyright holder saying it may be distributed
|
||||||
|
under the terms of this General Public License. The "Program", below,
|
||||||
|
refers to any such program or work, and a "work based on the Program"
|
||||||
|
means either the Program or any derivative work under copyright law:
|
||||||
|
that is to say, a work containing the Program or a portion of it,
|
||||||
|
either verbatim or with modifications and/or translated into another
|
||||||
|
language. (Hereinafter, translation is included without limitation in
|
||||||
|
the term "modification".) Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running the Program is not restricted, and the output from the Program
|
||||||
|
is covered only if its contents constitute a work based on the
|
||||||
|
Program (independent of having been made by running the Program).
|
||||||
|
Whether that is true depends on what the Program does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Program's
|
||||||
|
source code as you receive it, in any medium, provided that you
|
||||||
|
conspicuously and appropriately publish on each copy an appropriate
|
||||||
|
copyright notice and disclaimer of warranty; keep intact all the
|
||||||
|
notices that refer to this License and to the absence of any warranty;
|
||||||
|
and give any other recipients of the Program a copy of this License
|
||||||
|
along with the Program.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy, and
|
||||||
|
you may at your option offer warranty protection in exchange for a fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Program or any portion
|
||||||
|
of it, thus forming a work based on the Program, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) You must cause the modified files to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
b) You must cause any work that you distribute or publish, that in
|
||||||
|
whole or in part contains or is derived from the Program or any
|
||||||
|
part thereof, to be licensed as a whole at no charge to all third
|
||||||
|
parties under the terms of this License.
|
||||||
|
|
||||||
|
c) If the modified program normally reads commands interactively
|
||||||
|
when run, you must cause it, when started running for such
|
||||||
|
interactive use in the most ordinary way, to print or display an
|
||||||
|
announcement including an appropriate copyright notice and a
|
||||||
|
notice that there is no warranty (or else, saying that you provide
|
||||||
|
a warranty) and that users may redistribute the program under
|
||||||
|
these conditions, and telling the user how to view a copy of this
|
||||||
|
License. (Exception: if the Program itself is interactive but
|
||||||
|
does not normally print such an announcement, your work based on
|
||||||
|
the Program is not required to print an announcement.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Program,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Program, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Program.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Program
|
||||||
|
with the Program (or with a work based on the Program) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may copy and distribute the Program (or a work based on it,
|
||||||
|
under Section 2) in object code or executable form under the terms of
|
||||||
|
Sections 1 and 2 above provided that you also do one of the following:
|
||||||
|
|
||||||
|
a) Accompany it with the complete corresponding machine-readable
|
||||||
|
source code, which must be distributed under the terms of Sections
|
||||||
|
1 and 2 above on a medium customarily used for software interchange; or,
|
||||||
|
|
||||||
|
b) Accompany it with a written offer, valid for at least three
|
||||||
|
years, to give any third party, for a charge no more than your
|
||||||
|
cost of physically performing source distribution, a complete
|
||||||
|
machine-readable copy of the corresponding source code, to be
|
||||||
|
distributed under the terms of Sections 1 and 2 above on a medium
|
||||||
|
customarily used for software interchange; or,
|
||||||
|
|
||||||
|
c) Accompany it with the information you received as to the offer
|
||||||
|
to distribute corresponding source code. (This alternative is
|
||||||
|
allowed only for noncommercial distribution and only if you
|
||||||
|
received the program in object code or executable form with such
|
||||||
|
an offer, in accord with Subsection b above.)
|
||||||
|
|
||||||
|
The source code for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For an executable work, complete source
|
||||||
|
code means all the source code for all modules it contains, plus any
|
||||||
|
associated interface definition files, plus the scripts used to
|
||||||
|
control compilation and installation of the executable. However, as a
|
||||||
|
special exception, the source code distributed need not include
|
||||||
|
anything that is normally distributed (in either source or binary
|
||||||
|
form) with the major components (compiler, kernel, and so on) of the
|
||||||
|
operating system on which the executable runs, unless that component
|
||||||
|
itself accompanies the executable.
|
||||||
|
|
||||||
|
If distribution of executable or object code is made by offering
|
||||||
|
access to copy from a designated place, then offering equivalent
|
||||||
|
access to copy the source code from the same place counts as
|
||||||
|
distribution of the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
4. You may not copy, modify, sublicense, or distribute the Program
|
||||||
|
except as expressly provided under this License. Any attempt
|
||||||
|
otherwise to copy, modify, sublicense or distribute the Program is
|
||||||
|
void, and will automatically terminate your rights under this License.
|
||||||
|
However, parties who have received copies, or rights, from you under
|
||||||
|
this License will not have their licenses terminated so long as such
|
||||||
|
parties remain in full compliance.
|
||||||
|
|
||||||
|
5. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Program or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Program (or any work based on the
|
||||||
|
Program), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Program or works based on it.
|
||||||
|
|
||||||
|
6. Each time you redistribute the Program (or any work based on the
|
||||||
|
Program), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute or modify the Program subject to
|
||||||
|
these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties to
|
||||||
|
this License.
|
||||||
|
|
||||||
|
7. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Program at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Program by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Program.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under
|
||||||
|
any particular circumstance, the balance of the section is intended to
|
||||||
|
apply and the section as a whole is intended to apply in other
|
||||||
|
circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system, which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
8. If the distribution and/or use of the Program is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Program under this License
|
||||||
|
may add an explicit geographical distribution limitation excluding
|
||||||
|
those countries, so that distribution is permitted only in or among
|
||||||
|
countries not thus excluded. In such case, this License incorporates
|
||||||
|
the limitation as if written in the body of this License.
|
||||||
|
|
||||||
|
9. The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Program
|
||||||
|
specifies a version number of this License which applies to it and "any
|
||||||
|
later version", you have the option of following the terms and conditions
|
||||||
|
either of that version or of any later version published by the Free
|
||||||
|
Software Foundation. If the Program does not specify a version number of
|
||||||
|
this License, you may choose any version ever published by the Free Software
|
||||||
|
Foundation.
|
||||||
|
|
||||||
|
10. If you wish to incorporate parts of the Program into other free
|
||||||
|
programs whose distribution conditions are different, write to the author
|
||||||
|
to ask for permission. For software which is copyrighted by the Free
|
||||||
|
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||||
|
make exceptions for this. Our decision will be guided by the two goals
|
||||||
|
of preserving the free status of all derivatives of our free software and
|
||||||
|
of promoting the sharing and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||||
|
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||||
|
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||||
|
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||||
|
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||||
|
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||||
|
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||||
|
REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||||
|
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||||
|
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||||
|
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||||
|
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||||
|
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program is interactive, make it output a short notice like this
|
||||||
|
when it starts in an interactive mode:
|
||||||
|
|
||||||
|
Gnomovision version 69, Copyright (C) year name of author
|
||||||
|
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, the commands you use may
|
||||||
|
be called something other than `show w' and `show c'; they could even be
|
||||||
|
mouse-clicks or menu items--whatever suits your program.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||||
|
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1989
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
This General Public License does not permit incorporating your program into
|
||||||
|
proprietary programs. If your program is a subroutine library, you may
|
||||||
|
consider it more useful to permit linking proprietary applications with the
|
||||||
|
library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License.
|
||||||
137
vm/README.txt
Normal file
137
vm/README.txt
Normal file
|
|
@ -0,0 +1,137 @@
|
||||||
|
6502 Based Virtual Computer
|
||||||
|
Copyright (C) 2011 Scott C. Duensing <scott@jaegertech.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
This is a simple (and fictional) 6502-based computer written in JavaScript.
|
||||||
|
|
||||||
|
Features:
|
||||||
|
|
||||||
|
- 6502 CPU (lacks interrupt support at this time).
|
||||||
|
- 16 color, 80x25 text display.
|
||||||
|
- "Hardware" psuedo-random number generator.
|
||||||
|
- Keyboard.
|
||||||
|
- Simple clock.
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
- All hardware components are in the "computer" folder.
|
||||||
|
- A sample "Hello World" is in the "software" folder.
|
||||||
|
- "machine.html" loads everything and provides a DIV for the display.
|
||||||
|
- "machine.js" glues all the components together into a computer.
|
||||||
|
|
||||||
|
Memory Map:
|
||||||
|
|
||||||
|
MM_IRQ_VECTOR = 0xfffe
|
||||||
|
MM_RESET_VECTOR = 0xfffc
|
||||||
|
MM_NMI_VECTOR = 0xfffa
|
||||||
|
MM_ROM_END = 0xfff9
|
||||||
|
MM_ROM_START = 0xf000
|
||||||
|
MM_CLOCK = 0xefa5
|
||||||
|
MM_PRNG = 0xefa4
|
||||||
|
MM_KEYBOARD_META = 0xefa3
|
||||||
|
MM_KEYBOARD_CHARACTER = 0xefa2
|
||||||
|
MM_DISPLAY_COMMAND = 0xefa1
|
||||||
|
MM_DISPLAY_DATA = 0xefa0
|
||||||
|
MM_DISPLAY_ADAPTER = 0xe000
|
||||||
|
MM_HEAP_END = 0xdfff
|
||||||
|
MM_CODE_START = 0x0200
|
||||||
|
MM_STACK = 0x0100
|
||||||
|
MM_ZERO_PAGE = 0x0000
|
||||||
|
|
||||||
|
Display Adapter:
|
||||||
|
|
||||||
|
You can either jam bytes right into display memory (beginning at
|
||||||
|
MM_DISPLAY_ADAPTER) or use the simple BIOS included in the adapter. ("BOS"?
|
||||||
|
displays don't do input!)
|
||||||
|
|
||||||
|
Each character on the display is comprised of two bytes: The character to
|
||||||
|
display, and the color attributes (in that order). Colors are stored with the
|
||||||
|
foreground value in the lower nibble of the attribute byte and the background
|
||||||
|
in the high nibble. Color values are:
|
||||||
|
|
||||||
|
0 = Black
|
||||||
|
1 = Blue
|
||||||
|
2 = Green
|
||||||
|
3 = Cyan
|
||||||
|
4 = Red
|
||||||
|
5 = Magenta
|
||||||
|
6 = Brown
|
||||||
|
7 = Light Gray
|
||||||
|
8 = Gray
|
||||||
|
9 = Light Blue
|
||||||
|
10 = Light Green
|
||||||
|
11 = Light Cyan
|
||||||
|
12 = Light Red
|
||||||
|
13 = Light Magenta
|
||||||
|
14 = Yellow
|
||||||
|
15 = White
|
||||||
|
|
||||||
|
Using the BIOS provides several conveniences over writing directly to the
|
||||||
|
framebuffer, including tab stops, line wrapping, scrolling, and more. Access
|
||||||
|
to the BIOS is through two memory locations, one for data (MM_DISPLAY_DATA)
|
||||||
|
and one for issuing commands to operate on that data (MM_DISPLAY_COMMAND).
|
||||||
|
Available commands are:
|
||||||
|
|
||||||
|
0 = Store Data LSB (data byte stored for later)
|
||||||
|
1 = Clear Display to Current Color (no data byte needed)
|
||||||
|
2 = Set Cursor X (position 0-79 stored in data byte)
|
||||||
|
3 = Set Cursor Y (position 0-24 stored in data byte)
|
||||||
|
4 = Get Cursor X (position returned in data byte)
|
||||||
|
5 = Get Cursor Y (position returned in data byte)
|
||||||
|
6 = Set Color (same format as above, store in data byte)
|
||||||
|
7 = Draw Character in Current Color (character code in data byte)
|
||||||
|
8 = Draw String in Current Color (see below)
|
||||||
|
|
||||||
|
For drawing strings, first write the LSB of the address of the string in
|
||||||
|
memory to MM_DISPLAY_DATA and then write a 0 to MM_DISPLAY_COMMAND to store
|
||||||
|
the LSB. Then write the MSB to MM_DISPLAY_DATA and 8 to MM_DISPLAY_COMMAND to
|
||||||
|
draw the string. Since no length information is provided, strings must be
|
||||||
|
zero terminated.
|
||||||
|
|
||||||
|
Keyboard:
|
||||||
|
|
||||||
|
The current status of the keyboard can be read from two bytes,
|
||||||
|
MM_KEYBOARD_CHARACTER and MM_KEYBOARD_META. MM_KEYBOARD_CHARACTER always
|
||||||
|
contains the value of the most recently pressed key. MM_KEYBOARD_META
|
||||||
|
contains the current state of the keyboard's Shift, Control, and Alt keys
|
||||||
|
in the following bits:
|
||||||
|
|
||||||
|
0 = Shift
|
||||||
|
1 = Control
|
||||||
|
2 = Alt
|
||||||
|
|
||||||
|
If you wish to wait for a keypress, write a 0 to MM_KEYBOARD_CHARACTER and
|
||||||
|
then poll until the value changes.
|
||||||
|
|
||||||
|
Random Number Generator:
|
||||||
|
|
||||||
|
To make it easy to get a random number for use in your code, a psuedo-random
|
||||||
|
number generator is provided. Simply read from MM_PRNG for a random value
|
||||||
|
between 0 and 255, inclusive.
|
||||||
|
|
||||||
|
Clock:
|
||||||
|
|
||||||
|
The value at MM_CLOCK increments every 100 milliseconds. It is intended for
|
||||||
|
simple timing operations and not actual "wall clock" time keeping.
|
||||||
|
|
||||||
|
Code Start:
|
||||||
|
|
||||||
|
By default, when the CPU starts, anything located at MM_CODE_START will be
|
||||||
|
executed. If you wish to relocate your code, either place a JMP at this
|
||||||
|
address or in "machine.js" change the default PC value in the call to
|
||||||
|
"cpu.attach()".
|
||||||
57
vm/computer/clock.js
Normal file
57
vm/computer/clock.js
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* 6502 Based Virtual Computer
|
||||||
|
* Copyright (C) 2011 Scott C. Duensing <scott@jaegertech.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Our Clock object.
|
||||||
|
function clock() {
|
||||||
|
|
||||||
|
// --- Private variables.
|
||||||
|
|
||||||
|
// Memory location for PRNG value.
|
||||||
|
var MEMORY = null;
|
||||||
|
var MEMORY_START = 0;
|
||||||
|
var CLOCK_ADDRESS = 0;
|
||||||
|
|
||||||
|
// Clock values.
|
||||||
|
var MILLISECONDS = 0;
|
||||||
|
var CLOCK = 0;
|
||||||
|
|
||||||
|
|
||||||
|
// --- Private methods.
|
||||||
|
|
||||||
|
var clockTick = function() {
|
||||||
|
MEMORY.writeByte(CLOCK_ADDRESS, CLOCK++);
|
||||||
|
if (CLOCK > 255) CLOCK = 0;
|
||||||
|
setTimeout(function(){
|
||||||
|
clockTick();
|
||||||
|
}, MILLISECONDS);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// --- Public methods.
|
||||||
|
|
||||||
|
// Attach clock to DOM.
|
||||||
|
this.attach = function(newMemory, newStartPosition, newMilliseconds) {
|
||||||
|
MEMORY = newMemory;
|
||||||
|
MEMORY_START = newStartPosition;
|
||||||
|
CLOCK_ADDRESS = MEMORY_START;
|
||||||
|
MILLISECONDS = newMilliseconds;
|
||||||
|
clockTick();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
1533
vm/computer/cpu6502.js
Normal file
1533
vm/computer/cpu6502.js
Normal file
File diff suppressed because it is too large
Load diff
151
vm/computer/keyboard.js
Normal file
151
vm/computer/keyboard.js
Normal file
|
|
@ -0,0 +1,151 @@
|
||||||
|
/*
|
||||||
|
* 6502 Based Virtual Computer
|
||||||
|
* Copyright (C) 2011 Scott C. Duensing <scott@jaegertech.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Our keyboard object.
|
||||||
|
function keyboard() {
|
||||||
|
|
||||||
|
// OMFGWTFBBQ - http://unixpapa.com/js/key.html
|
||||||
|
|
||||||
|
// --- Private variables.
|
||||||
|
|
||||||
|
// Memory location for keyboard status.
|
||||||
|
var MEMORY = null;
|
||||||
|
var MEMORY_START = 0;
|
||||||
|
var CHARACTER_ADDRESS = 0;
|
||||||
|
var META_ADDRESS = 0;
|
||||||
|
|
||||||
|
// Keymaps. Swiped from http://jonathan.tang.name/code/js_keycode
|
||||||
|
var KEY_MAP = {};
|
||||||
|
var SHIFTED_SYMBOLS = {
|
||||||
|
58: 59, // : -> ;
|
||||||
|
43: 61, // = -> +
|
||||||
|
60: 44, // < -> ,
|
||||||
|
95: 45, // _ -> -
|
||||||
|
62: 46, // > -> .
|
||||||
|
63: 47, // ? -> /
|
||||||
|
96: 192, // ` -> ~
|
||||||
|
124: 92, // | -> \
|
||||||
|
39: 222, // ' -> 222
|
||||||
|
34: 222, // " -> 222
|
||||||
|
33: 49, // ! -> 1
|
||||||
|
64: 50, // @ -> 2
|
||||||
|
35: 51, // # -> 3
|
||||||
|
36: 52, // $ -> 4
|
||||||
|
37: 53, // % -> 5
|
||||||
|
94: 54, // ^ -> 6
|
||||||
|
38: 55, // & -> 7
|
||||||
|
42: 56, // * -> 8
|
||||||
|
40: 57, // ( -> 9
|
||||||
|
41: 58, // ) -> 0
|
||||||
|
123: 91, // { -> [
|
||||||
|
125: 93 // } -> ]
|
||||||
|
};
|
||||||
|
var GECKO_IE_KEYMAP = {
|
||||||
|
186: 59, // ;: in IE
|
||||||
|
187: 61, // =+ in IE
|
||||||
|
188: 44, // ,<
|
||||||
|
109: 95, // -_ in Mozilla
|
||||||
|
107: 61, // =+ in Mozilla
|
||||||
|
189: 95, // -_ in IE
|
||||||
|
190: 62, // .>
|
||||||
|
191: 47, // /?
|
||||||
|
192: 126, // `~
|
||||||
|
219: 91, // {[
|
||||||
|
220: 92, // \|
|
||||||
|
221: 93 // }]
|
||||||
|
};
|
||||||
|
var OPERA_KEYMAP = {};
|
||||||
|
|
||||||
|
// Browser detection taken from quirksmode.org
|
||||||
|
var IS_WINDOWS = navigator.platform.indexOf('Win') != -1;
|
||||||
|
var IS_OPERA = window.opera && window.opera.version() < '9.5';
|
||||||
|
var IS_KONQUEROR = navigator.vendor && navigator.vendor.indexOf('KDE') != -1;
|
||||||
|
var IS_ICAB = navigator.vendor && navigator.vendor.indexOf('iCab') != -1;
|
||||||
|
|
||||||
|
|
||||||
|
// --- Public methods.
|
||||||
|
|
||||||
|
// Attach keyboard to DOM.
|
||||||
|
this.attach = function(newMemory, newStartPosition) {
|
||||||
|
MEMORY = newMemory;
|
||||||
|
MEMORY_START = newStartPosition;
|
||||||
|
CHARACTER_ADDRESS = MEMORY_START;
|
||||||
|
META_ADDRESS = MEMORY_START + 1;
|
||||||
|
// Determine key map.
|
||||||
|
if (IS_OPERA && IS_WINDOWS) {
|
||||||
|
KEY_MAP = OPERA_KEYMAP;
|
||||||
|
} else if (IS_OPERA || IS_KONQUEROR || IS_ICAB) {
|
||||||
|
var unshift = [33, 64, 35, 36, 37, 94, 38, 42, 40, 41,
|
||||||
|
58, 43, 60, 95, 62, 63, 124, 34];
|
||||||
|
KEY_MAP = OPERA_KEYMAP;
|
||||||
|
for (var i = 0; i < unshift.length; ++i) {
|
||||||
|
KEY_MAP[unshift[i]] = SHIFTED_SYMBOLS[unshift[i]];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// IE and Gecko are close enough that we can use the same map for both,
|
||||||
|
// and the rest of the world (eg. Opera 9.50) seems to be standardizing
|
||||||
|
// on them
|
||||||
|
KEY_MAP = GECKO_IE_KEYMAP;
|
||||||
|
}
|
||||||
|
if (IS_KONQUEROR) {
|
||||||
|
KEY_MAP[0] = 45;
|
||||||
|
KEY_MAP[127] = 46;
|
||||||
|
KEY_MAP[45] = 95;
|
||||||
|
}
|
||||||
|
// Hook browser for keydown events.
|
||||||
|
document.onkeydown = function(e){
|
||||||
|
e = e || window.event;
|
||||||
|
// Process the key press.
|
||||||
|
var code = e.which || e.keyCode;
|
||||||
|
var k = {
|
||||||
|
code: KEY_MAP[code] || code,
|
||||||
|
shift: e.shiftKey,
|
||||||
|
alt: e.altKey,
|
||||||
|
ctrl: e.ctrlKey
|
||||||
|
};
|
||||||
|
// Un-funk the input.
|
||||||
|
if (k.shift) {
|
||||||
|
// Fix shifted characters.
|
||||||
|
var oldC = "1234567890,/=[]\\';";
|
||||||
|
var newC = "!@#$%^&*()<?+{}|\":";
|
||||||
|
var x = oldC.indexOf(String.fromCharCode(k.code));
|
||||||
|
if (x >= 0) k.code = newC.charCodeAt(x);
|
||||||
|
if (k.code == 222) k.code = 34; // "
|
||||||
|
} else {
|
||||||
|
// Fix unshifted characters.
|
||||||
|
var oldC = "ABCDEFGHIJKLMNOPQRSTUVWXYZ~_>";
|
||||||
|
var newC = "abcdefghijklmnopqrstuvwxyz`-.";
|
||||||
|
var x = oldC.indexOf(String.fromCharCode(k.code));
|
||||||
|
if (x >= 0) k.code = newC.charCodeAt(x);
|
||||||
|
if (k.code == 222) k.code = 39; // '
|
||||||
|
}
|
||||||
|
// Write meta first. Then we can process on the character being written.
|
||||||
|
MEMORY.writeByte(META_ADDRESS, (k.alt * 4) + (k.ctrl * 2) + k.shift);
|
||||||
|
// Ignore "naked" meta keys in the character address.
|
||||||
|
if ((k.code != 16) && (k.code != 17) && (k.code != 18) && (k.code != 145) && (k.code != 146)) {
|
||||||
|
MEMORY.writeByte(CHARACTER_ADDRESS, k.code);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Fetch how much RAM the current settings will require.
|
||||||
|
this.getMemoryNeeded = function() {
|
||||||
|
return 2; // Complicated, huh?
|
||||||
|
};
|
||||||
|
}
|
||||||
44
vm/computer/prng.js
Normal file
44
vm/computer/prng.js
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* 6502 Based Virtual Computer
|
||||||
|
* Copyright (C) 2011 Scott C. Duensing <scott@jaegertech.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Our Psuedo-Random Number Generator object.
|
||||||
|
function prng() {
|
||||||
|
|
||||||
|
// --- Private variables.
|
||||||
|
|
||||||
|
// Memory location for PRNG value.
|
||||||
|
var MEMORY = null;
|
||||||
|
var MEMORY_START = 0;
|
||||||
|
var PRNG_ADDRESS = 0;
|
||||||
|
|
||||||
|
|
||||||
|
// --- Public methods.
|
||||||
|
|
||||||
|
// Attach PRNG to DOM.
|
||||||
|
this.attach = function(newMemory, newStartPosition) {
|
||||||
|
MEMORY = newMemory;
|
||||||
|
MEMORY_START = newStartPosition;
|
||||||
|
PRNG_ADDRESS = MEMORY_START;
|
||||||
|
MEMORY.addReadCallback(PRNG_ADDRESS, PRNG_ADDRESS, null, function(address, value, data){
|
||||||
|
// On read, change the random value.
|
||||||
|
MEMORY.writeByte(address, Math.floor(Math.random() * 256));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
118
vm/computer/ram.js
Normal file
118
vm/computer/ram.js
Normal file
|
|
@ -0,0 +1,118 @@
|
||||||
|
/*
|
||||||
|
* 6502 Based Virtual Computer
|
||||||
|
* Copyright (C) 2011 Scott C. Duensing <scott@jaegertech.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Memory
|
||||||
|
function ram(newSize) {
|
||||||
|
|
||||||
|
// --- Private Types.
|
||||||
|
|
||||||
|
function T_EVENT() {
|
||||||
|
this.callback = null;
|
||||||
|
this.startAddress = 0;
|
||||||
|
this.endAddress = 0;
|
||||||
|
this.anyData = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// --- Private variables.
|
||||||
|
|
||||||
|
var MEMORY = new Array(newSize);
|
||||||
|
var WRITE_EVENTS = new Array();
|
||||||
|
var READ_EVENTS = new Array();
|
||||||
|
var EVENTS_ENABLED = true;
|
||||||
|
var EVENTS_ENABLED_COUNTER = 0;
|
||||||
|
|
||||||
|
|
||||||
|
// --- Public methods.
|
||||||
|
|
||||||
|
// Add callback for memory read event.
|
||||||
|
this.addReadCallback = function(newStart, newEnd, newData, newCallback) {
|
||||||
|
var event = new T_EVENT();
|
||||||
|
event.callback = newCallback;
|
||||||
|
event.startAddress = newStart;
|
||||||
|
event.endAddress = newEnd;
|
||||||
|
event.anyData = newData;
|
||||||
|
READ_EVENTS.push(event);
|
||||||
|
console.log("Read event " + READ_EVENTS.length + " added from 0x" + newStart.toString(16) + " to 0x" + newEnd.toString(16));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add callback for memory write event.
|
||||||
|
this.addWriteCallback = function(newStart, newEnd, newData, newCallback) {
|
||||||
|
var event = new T_EVENT();
|
||||||
|
event.callback = newCallback;
|
||||||
|
event.startAddress = newStart;
|
||||||
|
event.endAddress = newEnd;
|
||||||
|
event.anyData = newData;
|
||||||
|
WRITE_EVENTS.push(event);
|
||||||
|
console.log("Write event " + WRITE_EVENTS.length + " added from 0x" + newStart.toString(16) + " to 0x" + newEnd.toString(16));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Are we performing callbacks?
|
||||||
|
this.callbacksEnabled = function(trueFalse) {
|
||||||
|
EVENTS_ENABLED_COUNTER += (trueFalse ? -1 : 1);
|
||||||
|
EVENTS_ENABLED = (EVENTS_ENABLED_COUNTER == 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
// See how much RAM we have.
|
||||||
|
this.getSize = function() {
|
||||||
|
return MEMORY.length;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Read a byte and return it.
|
||||||
|
this.readByte = function(address) {
|
||||||
|
if ((address < MEMORY.length) && (address >= 0)) {
|
||||||
|
if ((READ_EVENTS.length > 0) && (EVENTS_ENABLED)) {
|
||||||
|
for (var x=0; x<READ_EVENTS.length; x++) {
|
||||||
|
var event = READ_EVENTS[x];
|
||||||
|
if ((address >= event.startAddress) && (address <= event.endAddress))
|
||||||
|
event.callback(address, MEMORY[address] & 0xff, event.anyData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return MEMORY[address] & 0xff;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Remove registered events.
|
||||||
|
this.removeEvents = function() {
|
||||||
|
READ_EVENTS = new Array();
|
||||||
|
WRITE_EVENTS = new Array();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set all the memory to zero. Does NOT fire events.
|
||||||
|
this.reset = function() {
|
||||||
|
for (var x=0; x<MEMORY.length; x++) {
|
||||||
|
MEMORY[x] = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Write a byte.
|
||||||
|
this.writeByte = function(address, value) {
|
||||||
|
if ((address < MEMORY.length) && (address >= 0)) {
|
||||||
|
MEMORY[address] = value & 0xff;
|
||||||
|
if ((WRITE_EVENTS.length > 0) && (EVENTS_ENABLED)) {
|
||||||
|
for (var x=0; x<WRITE_EVENTS.length; x++) {
|
||||||
|
var event = WRITE_EVENTS[x];
|
||||||
|
if ((address >= event.startAddress) && (address <= event.endAddress))
|
||||||
|
event.callback(address, MEMORY[address] & 0xff, event.anyData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
322
vm/computer/textDisplay.js
Normal file
322
vm/computer/textDisplay.js
Normal file
|
|
@ -0,0 +1,322 @@
|
||||||
|
/*
|
||||||
|
* 6502 Based Virtual Computer
|
||||||
|
* Copyright (C) 2011 Scott C. Duensing <scott@jaegertech.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Our display adapter object.
|
||||||
|
function textDisplay() {
|
||||||
|
|
||||||
|
// This display adapter can render text in 16 foreground colors
|
||||||
|
// on 16 background colors. A simple "BIOS" is available by
|
||||||
|
// writing command data into the byte directly following the
|
||||||
|
// display memory and then the command into the byte after that.
|
||||||
|
// You may also write directly to display RAM.
|
||||||
|
|
||||||
|
|
||||||
|
// --- Private variables.
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
// Memory Information.
|
||||||
|
var MEMORY = null;
|
||||||
|
var MEMORY_START = 0;
|
||||||
|
var DATA_BYTE = 0;
|
||||||
|
var DATA_LSB = 0;
|
||||||
|
var DATA_BYTE_ADDRESS = 0;
|
||||||
|
var COMMAND_BYTE_ADDRESS = 0;
|
||||||
|
|
||||||
|
// Font size.
|
||||||
|
var FONT_SIZE = 12;
|
||||||
|
|
||||||
|
// Default character cell size.
|
||||||
|
var CELL_WIDTH = 8;
|
||||||
|
var CELL_HEIGHT = 12;
|
||||||
|
|
||||||
|
// Default display size.
|
||||||
|
var WIDTH = 80;
|
||||||
|
var HEIGHT = 25;
|
||||||
|
|
||||||
|
// Is this a color display?
|
||||||
|
var IS_COLOR = true;
|
||||||
|
|
||||||
|
// Cursor position.
|
||||||
|
var CURSOR_X = 0;
|
||||||
|
var CURSOR_Y = 0;
|
||||||
|
|
||||||
|
// Current color attribute. Boring white on black. (LSN=FG, MSN=BG)
|
||||||
|
var COLOR_VALUE = 7;
|
||||||
|
|
||||||
|
|
||||||
|
// --- Private methods.
|
||||||
|
|
||||||
|
// Clear the screen to the current color attributes.
|
||||||
|
var clearDisplay = function() {
|
||||||
|
var byte = MEMORY_START;
|
||||||
|
for (var y=0; y<HEIGHT; y++) {
|
||||||
|
for (var x=0; x<WIDTH; x++) {
|
||||||
|
MEMORY.writeByte(byte++, 32); // [SPACE] in ASCII.
|
||||||
|
if (IS_COLOR) {
|
||||||
|
MEMORY.writeByte(byte++, COLOR_VALUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
moveCursor(0, 0);
|
||||||
|
self.refreshAll();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Move the cursor to a new location.
|
||||||
|
var moveCursor = function(x, y) {
|
||||||
|
var element = document.getElementById("cc" + CURSOR_X + "x" + CURSOR_Y);
|
||||||
|
var style = element.style;
|
||||||
|
style.border = "none";
|
||||||
|
CURSOR_X = x;
|
||||||
|
CURSOR_Y = y;
|
||||||
|
element = document.getElementById("cc" + CURSOR_X + "x" + CURSOR_Y);
|
||||||
|
style = element.style;
|
||||||
|
style.borderBottom = "2px solid white"; //***TODO*** Avoid using background color.
|
||||||
|
};
|
||||||
|
|
||||||
|
// Draw one character to the display & update cursor position.
|
||||||
|
var drawCharacter = function(c) {
|
||||||
|
var color = (IS_COLOR ? 2 : 1);
|
||||||
|
var byte = MEMORY_START + (CURSOR_Y * WIDTH + CURSOR_X) * color;
|
||||||
|
var x = CURSOR_X;
|
||||||
|
var y = CURSOR_Y;
|
||||||
|
if (c == 8) {
|
||||||
|
// Backspace
|
||||||
|
if (x > 0)
|
||||||
|
x--;
|
||||||
|
} else if (c == 9) {
|
||||||
|
// TAB
|
||||||
|
x = (x + 8) & ~7;
|
||||||
|
} else if (c == 10) {
|
||||||
|
// Line Feed
|
||||||
|
y++;
|
||||||
|
} else if (c == 13) {
|
||||||
|
// Carriage Return
|
||||||
|
x = 0;
|
||||||
|
} else {
|
||||||
|
// Other characters.
|
||||||
|
MEMORY.writeByte(byte++, c);
|
||||||
|
if (IS_COLOR) MEMORY.writeByte(byte++, COLOR_VALUE);
|
||||||
|
self.refresh(x, y);
|
||||||
|
x++;
|
||||||
|
}
|
||||||
|
// Line wrap?
|
||||||
|
if (x >= WIDTH - 1) {
|
||||||
|
x = 0;
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
// Scroll required?
|
||||||
|
var didScroll = false;
|
||||||
|
while (y >= HEIGHT) {
|
||||||
|
didScroll = true;
|
||||||
|
byte = MEMORY_START;
|
||||||
|
for (var i=0; i<(HEIGHT - 1) * WIDTH; i++) {
|
||||||
|
MEMORY.writeByte(byte, MEMORY.readByte(byte + WIDTH * color));
|
||||||
|
byte++;
|
||||||
|
if (IS_COLOR) {
|
||||||
|
MEMORY.writeByte(byte, MEMORY.readByte(byte + WIDTH * color));
|
||||||
|
byte++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//byte = MEMORY_START + WIDTH * (HEIGHT - 1) * color;
|
||||||
|
for (var i=0; i<WIDTH; i++) {
|
||||||
|
MEMORY.writeByte(byte++, 32);
|
||||||
|
if (IS_COLOR) MEMORY.writeByte(byte++, COLOR_VALUE);
|
||||||
|
}
|
||||||
|
y--;
|
||||||
|
}
|
||||||
|
// Redraw entire display if we scrolled.
|
||||||
|
if (didScroll) self.refreshAll();
|
||||||
|
// Reposition cursor.
|
||||||
|
moveCursor(x, y);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Draw a zero-terminated string to the display & update cursor position.
|
||||||
|
var drawString = function(address) {
|
||||||
|
var byte = address;
|
||||||
|
do {
|
||||||
|
var c = MEMORY.readByte(byte++);
|
||||||
|
if (c != 0) drawCharacter(c);
|
||||||
|
} while (c != 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// --- Public methods.
|
||||||
|
|
||||||
|
// Attach this display to the VM and build the required HTML in a DIV in the document.
|
||||||
|
this.attach = function(newMemory, newStartPosition, divId) {
|
||||||
|
MEMORY = newMemory;
|
||||||
|
MEMORY_START = newStartPosition;
|
||||||
|
var html = "<table border='0' cellPadding='0' cellSpacing='0'>";
|
||||||
|
var byte = MEMORY_START;
|
||||||
|
for (var h=0; h<HEIGHT; h++) {
|
||||||
|
html += "<tr vAlign='middle' height='" + CELL_HEIGHT + "px'>";
|
||||||
|
for (var w=0; w<WIDTH; w++) {
|
||||||
|
MEMORY.writeByte(byte++, 32); // [SPACE] in ASCII.
|
||||||
|
if (IS_COLOR) {
|
||||||
|
MEMORY.writeByte(byte++, COLOR_VALUE);
|
||||||
|
}
|
||||||
|
html += "<td align='center' width='" + CELL_WIDTH + "px' id='cc" + w + "x" + h + "'> </td>";
|
||||||
|
}
|
||||||
|
html += "</tr>";
|
||||||
|
}
|
||||||
|
html += "</table>";
|
||||||
|
document.getElementById(divId).innerHTML = html;
|
||||||
|
DATA_BYTE_ADDRESS = byte++;
|
||||||
|
COMMAND_BYTE_ADDRESS = byte++;
|
||||||
|
moveCursor(0, 0);
|
||||||
|
this.refreshAll();
|
||||||
|
// Set up memory mapped hardware ports.
|
||||||
|
MEMORY.addWriteCallback(MEMORY_START, MEMORY_START + this.getMemoryNeeded() - 1, null, function(address, value, data){
|
||||||
|
MEMORY.callbacksEnabled(false);
|
||||||
|
var offset = address - MEMORY_START;
|
||||||
|
// Is this a write to one of the command ports or direct to video memory?
|
||||||
|
if (address >= DATA_BYTE_ADDRESS) {
|
||||||
|
// Command byte?
|
||||||
|
if (address == COMMAND_BYTE_ADDRESS) {
|
||||||
|
if (value == 0) DATA_LSB = DATA_BYTE;
|
||||||
|
if (value == 1) clearDisplay();
|
||||||
|
if (value == 2) moveCursor(DATA_BYTE, CURSOR_Y);
|
||||||
|
if (value == 3) moveCursor(CURSOR_X, DATA_BYTE);
|
||||||
|
if (value == 4) MEMORY.writeByte(DATA_BYTE_ADDRESS, CURSOR_X);
|
||||||
|
if (value == 5) MEMORY.writeByte(DATA_BYTE_ADDRESS, CURSOR_Y);
|
||||||
|
if (value == 6) COLOR_VALUE = DATA_BYTE;
|
||||||
|
if (value == 7) drawCharacter(DATA_BYTE);
|
||||||
|
if (value == 8) drawString((DATA_BYTE << 8) + DATA_LSB);
|
||||||
|
} else {
|
||||||
|
// Data byte.
|
||||||
|
DATA_BYTE = value;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (IS_COLOR) {
|
||||||
|
// Is this the character byte or the color byte?
|
||||||
|
if (offset % 2 == 0)
|
||||||
|
offset = offset / 2; // Character.
|
||||||
|
else
|
||||||
|
offset = ((offset + 1) / 2) - 1; // Color.
|
||||||
|
}
|
||||||
|
var y = Math.floor(offset / monitor.getWidth());
|
||||||
|
var x = offset - y * monitor.getWidth();
|
||||||
|
monitor.refresh(x, y);
|
||||||
|
}
|
||||||
|
MEMORY.callbacksEnabled(true);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Refresh a single character cell.
|
||||||
|
this.refresh = function(x, y) {
|
||||||
|
// These are good old PC DOS colors.
|
||||||
|
// black, dark red, dark green, brown, dark blue, dark magenta, dark cyan, gray
|
||||||
|
// dim gray, red, green, yellow, blue, magenta, cyan, white
|
||||||
|
var colors = ["#000000", "#8B0000", "#006400", "#8B8B00", "#00008B", "#8B008B", "#008B8B", "#808080",
|
||||||
|
"#696969", "#FF0000", "#00FF00", "#FFFF00", "#0000FF", "#FF00FF", "#00FFFF", "#FFFFFF"];
|
||||||
|
var byte = MEMORY_START + (y * WIDTH + x) * (IS_COLOR ? 2 : 1);
|
||||||
|
var foreground = colors[7];
|
||||||
|
var background = colors[0];
|
||||||
|
if (IS_COLOR) {
|
||||||
|
// LSN=FG, MSN=BG
|
||||||
|
var value = MEMORY.readByte(byte + 1);
|
||||||
|
var LSN = value & 0x0f;
|
||||||
|
var MSN = (value & 0xf0) >> 4;
|
||||||
|
foreground = colors[LSN];
|
||||||
|
background = colors[MSN];
|
||||||
|
}
|
||||||
|
var element = document.getElementById("cc" + x + "x" + y);
|
||||||
|
var style = element.style;
|
||||||
|
var html = "<span style='font-family:monospace; font-size:" + FONT_SIZE + "px; color:" + foreground + ";'>";
|
||||||
|
html += String.fromCharCode(MEMORY.readByte(byte));
|
||||||
|
html += "</span>";
|
||||||
|
element.innerHTML = html;
|
||||||
|
style.background = background;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Refresh the entire display.
|
||||||
|
this.refreshAll = function() {
|
||||||
|
for (var h=0; h<HEIGHT; h++) {
|
||||||
|
for (var w=0; w<WIDTH; w++) {
|
||||||
|
this.refresh(w, h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Fetch the current cell height.
|
||||||
|
this.getCellHeight = function() {
|
||||||
|
return CELL_HEIGHT;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Fetch the current cell width.
|
||||||
|
this.getCellWidth = function() {
|
||||||
|
return CELL_WIDTH;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Fetch the current font size.
|
||||||
|
this.getFontSize = function() {
|
||||||
|
return FONT_SIZE;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Fetch the current height.
|
||||||
|
this.getHeight = function() {
|
||||||
|
return HEIGHT;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Fetch how much RAM the current settings will require.
|
||||||
|
this.getMemoryNeeded = function() {
|
||||||
|
return WIDTH * HEIGHT * (IS_COLOR ? 2 : 1) + 2;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Fetch the current width.
|
||||||
|
this.getWidth = function() {
|
||||||
|
return WIDTH;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is this a color display?
|
||||||
|
this.isColor = function() {
|
||||||
|
return IS_COLOR;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set the current cell height.
|
||||||
|
this.setCellHeight = function(newCellHeight) {
|
||||||
|
CELL_HEIGHT = newCellHeight;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set the current cell width.
|
||||||
|
this.setCellWidth = function(newCellWidth) {
|
||||||
|
CELL_WIDTH = newCellWidth;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set if we're a color display or not.
|
||||||
|
this.setColor = function(newIsColor) {
|
||||||
|
IS_COLOR = newIsColor;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set the current font size.
|
||||||
|
this.setFontSize = function(newFontSize) {
|
||||||
|
FONT_SIZE = newFontSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set the current height.
|
||||||
|
this.setHeight = function(newHeight) {
|
||||||
|
HEIGHT = newHeight;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set the current width.
|
||||||
|
this.setWidth = function(newWidth) {
|
||||||
|
WIDTH = newWidth;
|
||||||
|
};
|
||||||
|
}
|
||||||
38
vm/machine.html
Normal file
38
vm/machine.html
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
<!--
|
||||||
|
6502 Based Virtual Computer
|
||||||
|
Copyright (C) 2011 Scott C. Duensing <scott@jaegertech.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
-->
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script src="https://getfirebug.com/firebug-lite.js" type="text/javascript" language="javascript"></script>
|
||||||
|
<script src="ConsoleDummy.js" type="text/javascript" language="javascript"></script>
|
||||||
|
<title>Virtual Computer Test</title>
|
||||||
|
<script src="computer/ram.js" type="text/javascript" language="javascript"></script>
|
||||||
|
<script src="computer/cpu6502.js" type="text/javascript" language="javascript"></script>
|
||||||
|
<script src="computer/textDisplay.js" type="text/javascript" language="javascript"></script>
|
||||||
|
<script src="computer/keyboard.js" type="text/javascript" language="javascript"></script>
|
||||||
|
<script src="computer/prng.js" type="text/javascript" language="javascript"></script>
|
||||||
|
<script src="computer/clock.js" type="text/javascript" language="javascript"></script>
|
||||||
|
<!--
|
||||||
|
<script src="software/basic.js" type="text/javascript" language="javascript"></script>
|
||||||
|
-->
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="display"></div>
|
||||||
|
<script src="machine.js" type="text/javascript" language="javascript"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
101
vm/machine.js
Normal file
101
vm/machine.js
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
/*
|
||||||
|
* 6502 Based Virtual Computer
|
||||||
|
* Copyright (C) 2011 Scott C. Duensing <scott@jaegertech.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Try it out!
|
||||||
|
|
||||||
|
// Declare components of our computer.
|
||||||
|
console.log("Creating components.");
|
||||||
|
var memory = new ram(64 * 1024);
|
||||||
|
var cpu = new cpu6502();
|
||||||
|
var monitor = new textDisplay();
|
||||||
|
var keys = new keyboard();
|
||||||
|
var random = new prng();
|
||||||
|
var timer = new clock();
|
||||||
|
console.log("Creating components - success!");
|
||||||
|
|
||||||
|
// Memory Map (64k):
|
||||||
|
var MM_ZERO_PAGE = 0x0000;
|
||||||
|
var MM_STACK = 0x0100;
|
||||||
|
var MM_CODE_START = 0x0200;
|
||||||
|
var MM_HEAP_END = 0xdfff;
|
||||||
|
var MM_DISPLAY_ADAPTER = 0xe000;
|
||||||
|
var MM_DISPLAY_DATA = MM_DISPLAY_ADAPTER + monitor.getMemoryNeeded() - 2;
|
||||||
|
var MM_DISPLAY_COMMAND = MM_DISPLAY_DATA + 1;
|
||||||
|
var MM_KEYBOARD_CHARACTER = MM_DISPLAY_COMMAND + 1;
|
||||||
|
var MM_KEYBOARD_META = MM_KEYBOARD_CHARACTER + 1;
|
||||||
|
var MM_PRNG = MM_KEYBOARD_META + 1;
|
||||||
|
var MM_CLOCK = MM_PRNG + 1;
|
||||||
|
var MM_ROM_START = 0xf000;
|
||||||
|
var MM_ROM_END = 0xfff9;
|
||||||
|
var MM_NMI_VECTOR = 0xfffa;
|
||||||
|
var MM_RESET_VECTOR = 0xfffc;
|
||||||
|
var MM_IRQ_VECTOR = 0xfffe;
|
||||||
|
|
||||||
|
console.log("MM_IRQ_VECTOR = 0x" + MM_IRQ_VECTOR.toString(16));
|
||||||
|
console.log("MM_RESET_VECTOR = 0x" + MM_RESET_VECTOR.toString(16));
|
||||||
|
console.log("MM_NMI_VECTOR = 0x" + MM_NMI_VECTOR.toString(16));
|
||||||
|
console.log("MM_ROM_END = 0x" + MM_ROM_END.toString(16));
|
||||||
|
console.log("MM_ROM_START = 0x" + MM_ROM_START.toString(16));
|
||||||
|
console.log("MM_CLOCK = 0x" + MM_CLOCK.toString(16));
|
||||||
|
console.log("MM_PRNG = 0x" + MM_PRNG.toString(16));
|
||||||
|
console.log("MM_KEYBOARD_META = 0x" + MM_KEYBOARD_META.toString(16));
|
||||||
|
console.log("MM_KEYBOARD_CHARACTER = 0x" + MM_KEYBOARD_CHARACTER.toString(16));
|
||||||
|
console.log("MM_DISPLAY_COMMAND = 0x" + MM_DISPLAY_COMMAND.toString(16));
|
||||||
|
console.log("MM_DISPLAY_DATA = 0x" + MM_DISPLAY_DATA.toString(16));
|
||||||
|
console.log("MM_DISPLAY_ADAPTER = 0x" + MM_DISPLAY_ADAPTER.toString(16));
|
||||||
|
console.log("MM_HEAP_END = 0x" + MM_HEAP_END.toString(16));
|
||||||
|
console.log("MM_CODE_START = 0x" + MM_CODE_START.toString(16));
|
||||||
|
console.log("MM_STACK = 0x" + MM_STACK.toString(16));
|
||||||
|
console.log("MM_ZERO_PAGE = 0x" + MM_ZERO_PAGE.toString(16));
|
||||||
|
|
||||||
|
// Configure components & connect them together.
|
||||||
|
cpu.attach(memory, MM_CODE_START, function(event){
|
||||||
|
// We don't care about events just yet.
|
||||||
|
var message = "Event " + event + " @ 0x" + cpu.getPC().toString(16) + " = " + memory.readByte(cpu.getPC()).toString(16);
|
||||||
|
console.log(message);
|
||||||
|
alert(message);
|
||||||
|
});
|
||||||
|
monitor.attach(memory, MM_DISPLAY_ADAPTER, "display");
|
||||||
|
keys.attach(memory, MM_KEYBOARD_CHARACTER);
|
||||||
|
random.attach(memory, MM_PRNG);
|
||||||
|
timer.attach(memory, MM_CLOCK, 0x100);
|
||||||
|
|
||||||
|
// Power on!
|
||||||
|
memory.reset();
|
||||||
|
cpu.reset();
|
||||||
|
|
||||||
|
// Make it do something!
|
||||||
|
var HELLO_WORLD = [0xA2, 0x00, 0xBD, 0x14, 0x02, 0xF0, 0x0B, 0x8D, 0xA0, 0xEF, 0xA9, 0x07,
|
||||||
|
0x8D, 0xA1, 0xEF, 0xE8, 0xD0, 0xF0, 0x00, 0x00, 0x48, 0x65, 0x6C,
|
||||||
|
0x6C, 0x6F, 0x2C, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x21, 0x00];
|
||||||
|
|
||||||
|
for (var x=0; x<HELLO_WORLD.length; x++) {
|
||||||
|
memory.writeByte(MM_CODE_START + x, HELLO_WORLD[x]);
|
||||||
|
}
|
||||||
|
console.log("Code loaded.");
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Load EhBASIC into RAM at 0xD000.
|
||||||
|
for (var x=0; x<PROGRAM.length; x++) {
|
||||||
|
memory.writeByte(0xD000 + x, PROGRAM[x]);
|
||||||
|
}
|
||||||
|
console.log("Code loaded.");
|
||||||
|
*/
|
||||||
|
|
||||||
|
cpu.run();
|
||||||
26
vm/software/hello.asm
Normal file
26
vm/software/hello.asm
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
; "Hello World" in dasm assembler format.
|
||||||
|
; This could actually be done in less code since the display
|
||||||
|
; BIOS can output strings.
|
||||||
|
; tpasm -l hello.out hello.asm -P 6502
|
||||||
|
|
||||||
|
processor 6502
|
||||||
|
|
||||||
|
ddata equ $efa0 ; Display data address.
|
||||||
|
dcommand equ $efa1 ; Display command address.
|
||||||
|
|
||||||
|
org $200 ; Code start.
|
||||||
|
|
||||||
|
ldx #0 ; Starting index 0 in X register.
|
||||||
|
printnext:
|
||||||
|
lda text,x ; Get character from string.
|
||||||
|
beq done ; If we read a 0 we're done.
|
||||||
|
sta ddata ; Output character.
|
||||||
|
lda #$7
|
||||||
|
sta dcommand
|
||||||
|
inx ; Increment index to next character.
|
||||||
|
bne printnext ; Repeat if index doesn't overflow to 0.
|
||||||
|
done:
|
||||||
|
brk ; Just die.
|
||||||
|
|
||||||
|
text:
|
||||||
|
dc.b "Hello, world!", $00
|
||||||
340
xa-2.3.5/COPYING
Normal file
340
xa-2.3.5/COPYING
Normal file
|
|
@ -0,0 +1,340 @@
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||||
|
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
License is intended to guarantee your freedom to share and change free
|
||||||
|
software--to make sure the software is free for all its users. This
|
||||||
|
General Public License applies to most of the Free Software
|
||||||
|
Foundation's software and to any other program whose authors commit to
|
||||||
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
|
the GNU Library General Public License instead.) You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
this service if you wish), that you receive source code or can get it
|
||||||
|
if you want it, that you can change the software or use pieces of it
|
||||||
|
in new free programs; and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
anyone to deny you these rights or to ask you to surrender the rights.
|
||||||
|
These restrictions translate to certain responsibilities for you if you
|
||||||
|
distribute copies of the software, or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must give the recipients all the rights that
|
||||||
|
you have. You must make sure that they, too, receive or can get the
|
||||||
|
source code. And you must show them these terms so they know their
|
||||||
|
rights.
|
||||||
|
|
||||||
|
We protect your rights with two steps: (1) copyright the software, and
|
||||||
|
(2) offer you this license which gives you legal permission to copy,
|
||||||
|
distribute and/or modify the software.
|
||||||
|
|
||||||
|
Also, for each author's protection and ours, we want to make certain
|
||||||
|
that everyone understands that there is no warranty for this free
|
||||||
|
software. If the software is modified by someone else and passed on, we
|
||||||
|
want its recipients to know that what they have is not the original, so
|
||||||
|
that any problems introduced by others will not reflect on the original
|
||||||
|
authors' reputations.
|
||||||
|
|
||||||
|
Finally, any free program is threatened constantly by software
|
||||||
|
patents. We wish to avoid the danger that redistributors of a free
|
||||||
|
program will individually obtain patent licenses, in effect making the
|
||||||
|
program proprietary. To prevent this, we have made it clear that any
|
||||||
|
patent must be licensed for everyone's free use or not licensed at all.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License applies to any program or other work which contains
|
||||||
|
a notice placed by the copyright holder saying it may be distributed
|
||||||
|
under the terms of this General Public License. The "Program", below,
|
||||||
|
refers to any such program or work, and a "work based on the Program"
|
||||||
|
means either the Program or any derivative work under copyright law:
|
||||||
|
that is to say, a work containing the Program or a portion of it,
|
||||||
|
either verbatim or with modifications and/or translated into another
|
||||||
|
language. (Hereinafter, translation is included without limitation in
|
||||||
|
the term "modification".) Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running the Program is not restricted, and the output from the Program
|
||||||
|
is covered only if its contents constitute a work based on the
|
||||||
|
Program (independent of having been made by running the Program).
|
||||||
|
Whether that is true depends on what the Program does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Program's
|
||||||
|
source code as you receive it, in any medium, provided that you
|
||||||
|
conspicuously and appropriately publish on each copy an appropriate
|
||||||
|
copyright notice and disclaimer of warranty; keep intact all the
|
||||||
|
notices that refer to this License and to the absence of any warranty;
|
||||||
|
and give any other recipients of the Program a copy of this License
|
||||||
|
along with the Program.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy, and
|
||||||
|
you may at your option offer warranty protection in exchange for a fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Program or any portion
|
||||||
|
of it, thus forming a work based on the Program, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) You must cause the modified files to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
b) You must cause any work that you distribute or publish, that in
|
||||||
|
whole or in part contains or is derived from the Program or any
|
||||||
|
part thereof, to be licensed as a whole at no charge to all third
|
||||||
|
parties under the terms of this License.
|
||||||
|
|
||||||
|
c) If the modified program normally reads commands interactively
|
||||||
|
when run, you must cause it, when started running for such
|
||||||
|
interactive use in the most ordinary way, to print or display an
|
||||||
|
announcement including an appropriate copyright notice and a
|
||||||
|
notice that there is no warranty (or else, saying that you provide
|
||||||
|
a warranty) and that users may redistribute the program under
|
||||||
|
these conditions, and telling the user how to view a copy of this
|
||||||
|
License. (Exception: if the Program itself is interactive but
|
||||||
|
does not normally print such an announcement, your work based on
|
||||||
|
the Program is not required to print an announcement.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Program,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Program, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Program.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Program
|
||||||
|
with the Program (or with a work based on the Program) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may copy and distribute the Program (or a work based on it,
|
||||||
|
under Section 2) in object code or executable form under the terms of
|
||||||
|
Sections 1 and 2 above provided that you also do one of the following:
|
||||||
|
|
||||||
|
a) Accompany it with the complete corresponding machine-readable
|
||||||
|
source code, which must be distributed under the terms of Sections
|
||||||
|
1 and 2 above on a medium customarily used for software interchange; or,
|
||||||
|
|
||||||
|
b) Accompany it with a written offer, valid for at least three
|
||||||
|
years, to give any third party, for a charge no more than your
|
||||||
|
cost of physically performing source distribution, a complete
|
||||||
|
machine-readable copy of the corresponding source code, to be
|
||||||
|
distributed under the terms of Sections 1 and 2 above on a medium
|
||||||
|
customarily used for software interchange; or,
|
||||||
|
|
||||||
|
c) Accompany it with the information you received as to the offer
|
||||||
|
to distribute corresponding source code. (This alternative is
|
||||||
|
allowed only for noncommercial distribution and only if you
|
||||||
|
received the program in object code or executable form with such
|
||||||
|
an offer, in accord with Subsection b above.)
|
||||||
|
|
||||||
|
The source code for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For an executable work, complete source
|
||||||
|
code means all the source code for all modules it contains, plus any
|
||||||
|
associated interface definition files, plus the scripts used to
|
||||||
|
control compilation and installation of the executable. However, as a
|
||||||
|
special exception, the source code distributed need not include
|
||||||
|
anything that is normally distributed (in either source or binary
|
||||||
|
form) with the major components (compiler, kernel, and so on) of the
|
||||||
|
operating system on which the executable runs, unless that component
|
||||||
|
itself accompanies the executable.
|
||||||
|
|
||||||
|
If distribution of executable or object code is made by offering
|
||||||
|
access to copy from a designated place, then offering equivalent
|
||||||
|
access to copy the source code from the same place counts as
|
||||||
|
distribution of the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
4. You may not copy, modify, sublicense, or distribute the Program
|
||||||
|
except as expressly provided under this License. Any attempt
|
||||||
|
otherwise to copy, modify, sublicense or distribute the Program is
|
||||||
|
void, and will automatically terminate your rights under this License.
|
||||||
|
However, parties who have received copies, or rights, from you under
|
||||||
|
this License will not have their licenses terminated so long as such
|
||||||
|
parties remain in full compliance.
|
||||||
|
|
||||||
|
5. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Program or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Program (or any work based on the
|
||||||
|
Program), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Program or works based on it.
|
||||||
|
|
||||||
|
6. Each time you redistribute the Program (or any work based on the
|
||||||
|
Program), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute or modify the Program subject to
|
||||||
|
these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties to
|
||||||
|
this License.
|
||||||
|
|
||||||
|
7. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Program at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Program by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Program.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under
|
||||||
|
any particular circumstance, the balance of the section is intended to
|
||||||
|
apply and the section as a whole is intended to apply in other
|
||||||
|
circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system, which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
8. If the distribution and/or use of the Program is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Program under this License
|
||||||
|
may add an explicit geographical distribution limitation excluding
|
||||||
|
those countries, so that distribution is permitted only in or among
|
||||||
|
countries not thus excluded. In such case, this License incorporates
|
||||||
|
the limitation as if written in the body of this License.
|
||||||
|
|
||||||
|
9. The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Program
|
||||||
|
specifies a version number of this License which applies to it and "any
|
||||||
|
later version", you have the option of following the terms and conditions
|
||||||
|
either of that version or of any later version published by the Free
|
||||||
|
Software Foundation. If the Program does not specify a version number of
|
||||||
|
this License, you may choose any version ever published by the Free Software
|
||||||
|
Foundation.
|
||||||
|
|
||||||
|
10. If you wish to incorporate parts of the Program into other free
|
||||||
|
programs whose distribution conditions are different, write to the author
|
||||||
|
to ask for permission. For software which is copyrighted by the Free
|
||||||
|
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||||
|
make exceptions for this. Our decision will be guided by the two goals
|
||||||
|
of preserving the free status of all derivatives of our free software and
|
||||||
|
of promoting the sharing and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||||
|
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||||
|
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||||
|
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||||
|
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||||
|
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||||
|
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||||
|
REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||||
|
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||||
|
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||||
|
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||||
|
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||||
|
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) 20yy <name of author>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program is interactive, make it output a short notice like this
|
||||||
|
when it starts in an interactive mode:
|
||||||
|
|
||||||
|
Gnomovision version 69, Copyright (C) 20yy name of author
|
||||||
|
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, the commands you use may
|
||||||
|
be called something other than `show w' and `show c'; they could even be
|
||||||
|
mouse-clicks or menu items--whatever suits your program.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||||
|
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1989
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
This General Public License does not permit incorporating your program into
|
||||||
|
proprietary programs. If your program is a subroutine library, you may
|
||||||
|
consider it more useful to permit linking proprietary applications with the
|
||||||
|
library. If this is what you want to do, use the GNU Library General
|
||||||
|
Public License instead of this License.
|
||||||
297
xa-2.3.5/ChangeLog
Normal file
297
xa-2.3.5/ChangeLog
Normal file
|
|
@ -0,0 +1,297 @@
|
||||||
|
xa-2.1.0
|
||||||
|
|
||||||
|
* Rewrite of command line option handling to better look like
|
||||||
|
usual (cc) options.
|
||||||
|
* Removed ^M from all files.
|
||||||
|
* Removed all external declarations to header files,
|
||||||
|
and made all static functions static.
|
||||||
|
| Now compiles almost without warning with 'gcc -W -Wall'.
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 31 Oct, 1996
|
||||||
|
|
||||||
|
xa-2.1.0a
|
||||||
|
|
||||||
|
* Introduced concept of code relocation. Now each label being set to
|
||||||
|
the program counter is a 'pointer', that gets an entry in a
|
||||||
|
relocation table. Simple arithmetic operations are allowed. The
|
||||||
|
relocation table is still just printed unsortedly.
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 31 Oct, 1996
|
||||||
|
|
||||||
|
xa-2.1.0b
|
||||||
|
|
||||||
|
* Produces some preliminary kind of relocatable file, including header
|
||||||
|
etc. Problems -- relocation table does as if file is assembled for
|
||||||
|
address 0. Need
|
||||||
|
a) a better way to set program counter.
|
||||||
|
b) pseudo opcodes for distinguishing segments.
|
||||||
|
c) a way to temporarily disable relocation.
|
||||||
|
d) a way to include extra headers and options into the file.
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 31 Oct, 1996
|
||||||
|
|
||||||
|
* Assembler now produces a relocatable file format, as described in
|
||||||
|
the file ``fileformat.txt''. Temporarily disabling relocation is with
|
||||||
|
the ``*=value'' directive, while switching back to relocation mode
|
||||||
|
goes with ``*='' (without value). New pseudo opcodes ``.text'',
|
||||||
|
``.data'', ``.bss'', ``.zero'' switch between the segments.
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 02 Nov, 1996
|
||||||
|
|
||||||
|
xa-2.1.0e
|
||||||
|
|
||||||
|
* There was a bug in the arithmetic routine that had set all pointer
|
||||||
|
to the text segment, if something was added.
|
||||||
|
* There also was a bug in the loader when actually using options.
|
||||||
|
* A new pseudo opcode was added -- ``.fopt''.
|
||||||
|
| Works like ``.byte'', but puts these bytes in a file option.
|
||||||
|
| The length in the file option is automagically set. ``.fopt''
|
||||||
|
| may appear anywhere in the file, but it should be at the
|
||||||
|
| beginning | (might be mandatory in a later version).
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 06 Nov, 1996
|
||||||
|
|
||||||
|
xa-2.1.0f
|
||||||
|
|
||||||
|
* Added a command line switch ``-M'' to ignore colons in a comment
|
||||||
|
after a semicolon.
|
||||||
|
* Without it, a colon separates complete mnemonics, including
|
||||||
|
the semicolon comment.
|
||||||
|
| Well, actually this switch is a ``MASM'' compatibility switch, and
|
||||||
|
will surely be expanded someday, when I get more info on MASM.
|
||||||
|
* Now ``*'' and ``='' can be separated for the definition
|
||||||
|
of the program counter and ``.byte'' is also accepted.
|
||||||
|
This makes it more MASM compatible. ".end" is ignored.
|
||||||
|
Still missing is ``.include''.
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 11 Nov, 1996
|
||||||
|
|
||||||
|
xa-2.1.0g
|
||||||
|
|
||||||
|
* Started working on ``official'' o65 fileformat.
|
||||||
|
If there are no undefined labels, and no relocated code
|
||||||
|
is embedded in absolute code, the thing should work.
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 21 Dec, 1996
|
||||||
|
|
||||||
|
xa-2.1.1
|
||||||
|
|
||||||
|
* ``.dsb'' now has an _optional_ parameter ``fillbyte''.
|
||||||
|
* Undefined references are now put into the relocation table
|
||||||
|
(i.e. handled correctly) if the ``-c'' option is given.
|
||||||
|
* The file format conforms to o65 version 1 file format.
|
||||||
|
* Embedding absolute in relocatable code and vice versa is buggy...
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 21 Dec, 1996
|
||||||
|
|
||||||
|
xa-2.1.1a
|
||||||
|
|
||||||
|
* Embedding absolute code in relocatable seems to work now.
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 21 Dec, 1996
|
||||||
|
|
||||||
|
xa-2.1.1e
|
||||||
|
|
||||||
|
* The option to embed relocatable code in absolute code has been
|
||||||
|
dropped. Therefore the command line options
|
||||||
|
``-A'' (make it romable), ``-b?'' (set segment start addresses),
|
||||||
|
and ``-G'' (omit exported globals from file) have been added.
|
||||||
|
* Internally, the whole thing has been made dynamic; except for the
|
||||||
|
preprocessor (and the storage between pass1 and pass2), everything
|
||||||
|
uses dynamically allocated tables. m_alloc, which had been
|
||||||
|
introduced long time ago because of the buggy malloc
|
||||||
|
on the Atari ST is gone now!
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 22 Dec, 1996
|
||||||
|
|
||||||
|
xa-2.1.1f
|
||||||
|
|
||||||
|
* Added the ``-a'' and ``-A'' options to file65, so that it can now
|
||||||
|
print the start addresses for following files in the ROM when making
|
||||||
|
romable code.
|
||||||
|
* Added shell (bash) script ``mkrom.sh'' that assembles a given list
|
||||||
|
of files and builds a ROMable file. The first two bytes are single
|
||||||
|
linked list pointers, and then comes the file.
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 02 Jan, 1997
|
||||||
|
|
||||||
|
xa-2.1.1g
|
||||||
|
|
||||||
|
* Added the file ``reloc65'', to relocate o65 files without
|
||||||
|
reassembling them.
|
||||||
|
* Fixed quite some bugs in xa (segment numbering in the globals list
|
||||||
|
and switched low/high byte relocation entry type in relocation
|
||||||
|
table. Now conforms to documentation, i.e. fileformat.txt)
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 03 Jan, 1997
|
||||||
|
|
||||||
|
xa-2.1.2
|
||||||
|
|
||||||
|
* Added ``ld65'', a simple linker for o65 files.
|
||||||
|
* Another bug in xa fixed now.
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 04 Jan, 1997
|
||||||
|
|
||||||
|
xa-2.1.3
|
||||||
|
|
||||||
|
* Allows to use ``.data'' etc in absolute mode, too. No relocation
|
||||||
|
entries are generated then. Segment start can be set with ``-b?''
|
||||||
|
command line options, though. Also the data segment is discarded
|
||||||
|
with this method! This allows to use the normal ``.data'' etc
|
||||||
|
syntax even when assembling a ROM (which is done in absolute mode.)
|
||||||
|
* Fixed a bug where ``.dsb'' in a data segment didn't fill with the
|
||||||
|
right value
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 25 Mar, 1997
|
||||||
|
|
||||||
|
xa-2.1.3e
|
||||||
|
|
||||||
|
* Added preprocessor continuation lines, and .block and .bend
|
||||||
|
pseudo-opcodes (They map to ``.('' and ``.)'' respectively.)
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 27 Jul, 1997
|
||||||
|
|
||||||
|
xa-2.1.4
|
||||||
|
|
||||||
|
* Do not leave output file around after an error -- this is
|
||||||
|
better for ``make''.
|
||||||
|
* Also it seems to have settled for a while, so I can release
|
||||||
|
a new version.
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 11 Sep, 1997
|
||||||
|
|
||||||
|
xa-2.1.4c
|
||||||
|
|
||||||
|
* Fixed a nasty bug that prevented correct relocation table
|
||||||
|
entries when a ``label2=label1'' contruct was used and
|
||||||
|
``label2'' was accessed.
|
||||||
|
* Added ``-I'' option.
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 30 Dec, 1997
|
||||||
|
|
||||||
|
xa-2.1.4d
|
||||||
|
|
||||||
|
* fixed align code. Now inserts NOP opcodes into text segment, and
|
||||||
|
sets file mode appropriately.
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 26 Jan, 1998
|
||||||
|
|
||||||
|
xa-2.1.4e
|
||||||
|
|
||||||
|
* Changed o65 fileformat and adopted it in xa.
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 26 Jan, 1998
|
||||||
|
|
||||||
|
xa-2.1.4g
|
||||||
|
|
||||||
|
* Fix handling of !zeropageaddress, that was broken (did not result
|
||||||
|
in absolute address, but gave error message.)
|
||||||
|
* Add cross reference list to labels if switched on on command line.
|
||||||
|
* Fix the filename when multiple files are given on the command line
|
||||||
|
(used to give the first filename for all errors in second pass.)
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 25 Nov, 1998
|
||||||
|
|
||||||
|
xa-2.1.4h
|
||||||
|
|
||||||
|
* In file65 added support for undefined labels and globals,
|
||||||
|
also for (some known) file options.
|
||||||
|
* Fix a preprocessor bug.
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 12 Dec, 1998
|
||||||
|
|
||||||
|
xa-2.2.0-p1-1
|
||||||
|
|
||||||
|
* Update COPYING to the latest version (Y2K-fixed + new address to GNU)
|
||||||
|
* Lots of fixes to the Makefiles
|
||||||
|
* Cleaned up the structure of the TODO file
|
||||||
|
* Added manual-pages for file65, ld65, printcbm, reloc65, uncpk, and xa
|
||||||
|
* Commented out LIB-flags -lm, -lcurses and -ltermcap,
|
||||||
|
since they are all unused
|
||||||
|
* Added `--help' and `--version' to all binaries
|
||||||
|
* Removed `-h', `-?' and `-v' options where applicable
|
||||||
|
* Created a file containing the version-function; version.h
|
||||||
|
* Moved common macros to a separate file; xad.h
|
||||||
|
* Restructuring of printcbm to become more readable
|
||||||
|
* Added ifndef/define/endif traps to all header-files
|
||||||
|
* Fixed a few typos
|
||||||
|
* Renamed romadr to romaddr
|
||||||
|
* Renamed all functions matching *such* to *search*
|
||||||
|
* Fixed all warnings
|
||||||
|
* Cleaned up all header-files
|
||||||
|
* Reformatted xa.log
|
||||||
|
|
||||||
|
-- David Weinehall <tao@acc.umu.se> 20 Aug, 2002
|
||||||
|
|
||||||
|
xa-2.3.0
|
||||||
|
|
||||||
|
* Version number jump for all the unofficial xa's out there
|
||||||
|
* Fixed addressing bugs for @, ! and completed 65816 merge
|
||||||
|
Thanks to David for the report
|
||||||
|
* Moderate legibility overhaul to xat.c (will continue on this)
|
||||||
|
* More compiler warnings corrected
|
||||||
|
Thanks to David for the report
|
||||||
|
* man files completed
|
||||||
|
* Documentation updated
|
||||||
|
* Last line bug corrected (where last line not assembled if no newline)
|
||||||
|
Thanks to silverdr for the report
|
||||||
|
* ld65 is now ldo65 to avoid conflicts with cc65 package
|
||||||
|
* Post-defined labels work better, or at least somewhat (no longer attempts
|
||||||
|
to optimize in pass 2 and generate bad code). Can be forced with `
|
||||||
|
Thanks to silverdr for the report
|
||||||
|
* Makefile bugs multiplied
|
||||||
|
* @ now mostly obligatory for 24-bit addressing
|
||||||
|
|
||||||
|
-- Cameron Kaiser <ckaiser@floodgap.com> 2 Apr, 2006
|
||||||
|
|
||||||
|
xa-2.3.2
|
||||||
|
|
||||||
|
* Introduced switch to convert values in quotes to different character
|
||||||
|
sets. Currently supported are ASCII (default) and PETSCII
|
||||||
|
* Fixed some quote bugs
|
||||||
|
|
||||||
|
-- André Fachat <afachat@gmx.de> 23 Dec, 2006
|
||||||
|
|
||||||
|
Thomas Giesel's reports and suggestions, thank you:
|
||||||
|
* -M works on colons in comments and nowhere else, as documented
|
||||||
|
* macro function arguments are properly recursively evaluated
|
||||||
|
* cpp output now grokked for more complex pre-parsing, rather than
|
||||||
|
reinvent the wheel
|
||||||
|
Other things:
|
||||||
|
* .xl, .xs, .al, .as weren't documented, and now they are (always worked)
|
||||||
|
for 65816 mode
|
||||||
|
* ! for forward-defined labels calculated wrong instruction length, fixed
|
||||||
|
* xap.c cleaned up some, xat.c cleaned up some more
|
||||||
|
Legibility work is going to be a long-term project.
|
||||||
|
* -x is now deprecated
|
||||||
|
* Documentation updated
|
||||||
|
|
||||||
|
-- Cameron Kaiser <ckaiser@floodgap.com> 13 Jan, 2007
|
||||||
|
|
||||||
|
xa-2.3.3
|
||||||
|
|
||||||
|
* Compatibility update for Microsoft Visual Studio and mingw/MSYS (thanks
|
||||||
|
Fabian Nunez and Mikkel Holm Olsen).
|
||||||
|
|
||||||
|
-- Cameron Kaiser <ckaiser@floodgap.com> 15 May, 2007
|
||||||
|
|
||||||
|
xa-2.3.4
|
||||||
|
|
||||||
|
* -p to define alternate synonym for # for preprocessor to avoid cpp/xa
|
||||||
|
preprocessor clashes and messes.
|
||||||
|
* Direct linking into output stream of binary files (.bin).
|
||||||
|
* Minor overhaul of error system to facilitate future expansion.
|
||||||
|
* Documentation updated.
|
||||||
|
|
||||||
|
-- Cameron Kaiser <ckaiser@floodgap.com> 1 July, 2008
|
||||||
|
|
||||||
|
xa-2.3.5
|
||||||
|
|
||||||
|
Most of this was suggested by Martin Wendt.
|
||||||
|
* Fixed bug where .bin was affected by the current character set.
|
||||||
|
* Added PETSCREEN and HIGH character sets.
|
||||||
|
* Added .aasc.
|
||||||
|
* Some more legibility work.
|
||||||
|
* Documentation updated.
|
||||||
|
|
||||||
|
-- Cameron Kaiser <ckaiser@floodgap.com> 7 February, 2009
|
||||||
62
xa-2.3.5/Makefile
Normal file
62
xa-2.3.5/Makefile
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
# Unix gcc or DOS go32 cross-compiling gcc
|
||||||
|
#
|
||||||
|
CC = gcc
|
||||||
|
LD = gcc
|
||||||
|
CFLAGS = -O2 -W -Wall -pedantic -ansi
|
||||||
|
LDFLAGS = -lc
|
||||||
|
|
||||||
|
# for DOS?
|
||||||
|
# CC = gcc-go32
|
||||||
|
# LD = gcc-go32
|
||||||
|
# CFLAGS = -W -Wall -pedantic
|
||||||
|
|
||||||
|
# Other cc
|
||||||
|
#CC = cc
|
||||||
|
#CFLAGS =
|
||||||
|
#LD = ld
|
||||||
|
|
||||||
|
DESTDIR = /usr/local
|
||||||
|
|
||||||
|
BINDIR = $(DESTDIR)/bin
|
||||||
|
MANDIR = $(DESTDIR)/share/man/man1
|
||||||
|
DOCDIR = $(DESTDIR)/share/doc
|
||||||
|
|
||||||
|
MKDIR = mkdir -p
|
||||||
|
INSTALL = install
|
||||||
|
|
||||||
|
all: xa uncpk
|
||||||
|
|
||||||
|
xa:
|
||||||
|
(cd src && LD=${LD} CC="${CC} ${CFLAGS}" ${MAKE})
|
||||||
|
|
||||||
|
load:
|
||||||
|
(cd loader && CC="${CC} ${CFLAGS}" ${MAKE})
|
||||||
|
|
||||||
|
uncpk:
|
||||||
|
(cd misc && CC="${CC} ${CFLAGS}" ${MAKE})
|
||||||
|
|
||||||
|
dos: clean
|
||||||
|
(cd src && LD=gcc-go32 CC=gcc-go32 CFLAGS="-W -Wall -pedantic" ${MAKE})
|
||||||
|
(cd misc && CC=gcc-go32 CFLAGS="-W -Wall -pedantic" ${MAKE})
|
||||||
|
rm -f xa file65 ldo65 uncpk printcbm reloc65 mkrom.sh src/*.o
|
||||||
|
|
||||||
|
mingw: clean
|
||||||
|
(cd src && LD=${LD} CC=${CC} CFLAGS="${CFLAGS}" LDFLAGS="" ${MAKE})
|
||||||
|
(cd misc && LD=${LD} CC=${CC} CFLAGS="${CFLAGS}" LDFLAGS="" ${MAKE})
|
||||||
|
|
||||||
|
clean:
|
||||||
|
(cd src && ${MAKE} clean)
|
||||||
|
(cd loader && ${MAKE} clean)
|
||||||
|
(cd misc && ${MAKE} mrproper)
|
||||||
|
rm -f xa *.exe *.o65
|
||||||
|
|
||||||
|
install: xa uncpk
|
||||||
|
$(MKDIR) $(BINDIR)
|
||||||
|
$(MKDIR) $(MANDIR)
|
||||||
|
$(INSTALL) xa reloc65 ldo65 file65 printcbm uncpk $(BINDIR)
|
||||||
|
$(INSTALL) man/file65.1 man/ldo65.1 man/printcbm.1 man/reloc65.1 man/uncpk.1 man/xa.1 $(MANDIR)
|
||||||
|
#$(MKDIR) $(DOCDIR)/xa65
|
||||||
|
|
||||||
|
dist: clean
|
||||||
|
#cd .. ; tar cvf xa-2.3.5A.tar xa-2.3.5 ; gzip xa-2.3.5A.tar
|
||||||
|
cd .. ; tar cvf xa-2.3.5.tar xa-2.3.5 ; gzip xa-2.3.5.tar
|
||||||
116
xa-2.3.5/README.1st
Normal file
116
xa-2.3.5/README.1st
Normal file
|
|
@ -0,0 +1,116 @@
|
||||||
|
This is the readme for xa, a cross-assembler for the 6502 and 65816 CPUs (and
|
||||||
|
derivatives). xa is a small, fast, portable two-pass assembler that compiles
|
||||||
|
under most ANSI C compilers. It is distributed under the GNU Public License
|
||||||
|
(see COPYING).
|
||||||
|
|
||||||
|
The current version is 2.3.4, which implements multiple improvements on
|
||||||
|
2.3.2, a bug fix to the 2.3.0 version. 2.3.0 itself features many
|
||||||
|
compatibility improvements and new man-based documentation. It also completed
|
||||||
|
the merge of the 65816 and 6502/R65C02 versions and thus the current xa can
|
||||||
|
generate code for all targets now.
|
||||||
|
|
||||||
|
To install on a generic Unixy thing, you should be able to just type
|
||||||
|
|
||||||
|
% make # to build the executable, and if it works ...
|
||||||
|
% make install # to install man pages and binaries into the system
|
||||||
|
|
||||||
|
This will create xa along with its various support utilities. Try assembling
|
||||||
|
the cpk depacker in examples/ as a test. xa also comes with uncpk (a program
|
||||||
|
for generating cpk archives) and printcbm (a program for listing Commodore
|
||||||
|
BASIC test) and file65, ldo65 and reloc65 for displaying, linking and
|
||||||
|
relocating o65 files in Andre's relocatable format (see doc/fileformats.txt).
|
||||||
|
The loader/ directory also has goodies for managing relocatable binaries.
|
||||||
|
|
||||||
|
Don't forget the man pages in man/. Install these into your MANPATH at your
|
||||||
|
leisure, or read them with nroff -man (and/or groff -man).
|
||||||
|
|
||||||
|
xa is no longer broadly supported outside of Unix due to my inability to test
|
||||||
|
it, but has nothing that should impair it from compiling elsewhere. To wit,
|
||||||
|
DOS compilation is still supported with the GO32 package. You should just be
|
||||||
|
able to type
|
||||||
|
|
||||||
|
C:\> make dos
|
||||||
|
|
||||||
|
In addition, there are compatibility updates to allow it to compile under
|
||||||
|
Microsoft Visual Studio and mingw. It should compile under VS2005 as written;
|
||||||
|
look in the vstudio directory for solution and project files provided by
|
||||||
|
Fabian Nunez. For mingw, use
|
||||||
|
|
||||||
|
make mingw
|
||||||
|
|
||||||
|
Similarly, Amiga and Atari ST compilation should still also function with
|
||||||
|
their particular compatible packages.
|
||||||
|
|
||||||
|
xa has a companion disassembler, the dxa package. dxa is not included in the
|
||||||
|
standard xa distribution, but can be downloaded from the xa home page at
|
||||||
|
|
||||||
|
http://www.floodgap.com/retrotech/xa/
|
||||||
|
|
||||||
|
Please check by periodically for the latest version of both packages.
|
||||||
|
|
||||||
|
xa was originally written and maintained by Andre Fachat. The current version
|
||||||
|
is maintained by Cameron Kaiser.
|
||||||
|
|
||||||
|
Please send me your comments at ckaiser@floodgap.com -- Andre's original
|
||||||
|
readme follows and applies generally to the present version.
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
XA is a 6502 cross compiler:
|
||||||
|
|
||||||
|
- under GNU public license
|
||||||
|
|
||||||
|
- can produce _relocatable_ binaries
|
||||||
|
|
||||||
|
- The full fileformat description and 6502 file loader included.
|
||||||
|
|
||||||
|
- also included relocation and info utilites, as well as linker
|
||||||
|
|
||||||
|
- for any ANSI-C compliant computer (only utilities need 'stat' call
|
||||||
|
for file size).
|
||||||
|
|
||||||
|
- fast by hashtables
|
||||||
|
|
||||||
|
- Rockwell CMOS opcodes
|
||||||
|
|
||||||
|
- running under DOS and any ANSI C system (Unix, Amiga, Atari ST)
|
||||||
|
|
||||||
|
I developed this cross assembler for the 6502 CPU family quite some time
|
||||||
|
ago on my Atari ST. The assembler has successfully been ported to Amiga
|
||||||
|
and Unix computer (ported? just compiled... :-)
|
||||||
|
Lately I came across the problem to need relocatable 6502 binary files, so
|
||||||
|
I revised the assembler from version 2.0.7 to 2.1.0, adding a (admittedly
|
||||||
|
proprietary) 6502 relocatable binary format. But there are not many other
|
||||||
|
formats around and they didn't fit my needs. I have developed this format
|
||||||
|
myself and it is under the GNU public license.
|
||||||
|
With version 2.1.1 the 'official' version of the fileformat is supported.
|
||||||
|
|
||||||
|
To compile it, just type "make" (if you have the GNU gcc. If not, edit the
|
||||||
|
Makefile for the compiler options). This produces "xa", the cross assembler;
|
||||||
|
"uncpk", a small packing utility (where the C64 counterpart is in the
|
||||||
|
examples subdirectory), "printcbm", that lists C64 BASIC files and
|
||||||
|
'file65' that prints some information about o65 files. The "loader" in
|
||||||
|
the loader subdirectory is a basic 6502 implementation of a relocating
|
||||||
|
binary loader.
|
||||||
|
"file65" prints file information on 'o65' relocatable files. "reloc65"
|
||||||
|
can relocate 'o65' files.
|
||||||
|
|
||||||
|
If you want to use it under DOS, you have to have the GO32 DOS crosscompiling
|
||||||
|
tools to compile. Then just type "make dos" and you'll end up with the
|
||||||
|
appropriate DOS binaries. This has been tested only under i386 Linux, however.
|
||||||
|
Another archive with the DOS binaries included is provided.
|
||||||
|
|
||||||
|
One problem on the Atari was it's broken "malloc". Therefore I used to
|
||||||
|
alloc everything in one chunk and divide the memory by hand. So everything
|
||||||
|
was kind of statically allocated. This is almost gone now. Only the
|
||||||
|
temporary storage between pass1 and pass2 and the preprocessor are still
|
||||||
|
allocated in one chunk (size definitions in xah.h). The rest is allocated
|
||||||
|
as needed.
|
||||||
|
|
||||||
|
The docs are in the 'doc' subdir. There also is a description of the
|
||||||
|
6502 relocatable binary format. If you think some things could be
|
||||||
|
expressed in a better way, feel free and mail me to improve my english ;-)
|
||||||
|
[ The documentation is now maintained in man(1) format in man/ . -- CK ]
|
||||||
|
|
||||||
|
Andre
|
||||||
|
|
||||||
10
xa-2.3.5/TODO
Normal file
10
xa-2.3.5/TODO
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
o nm65 that prints labels from o65 files
|
||||||
|
|
||||||
|
o `-L' option for ldo65, such that globals can be suppressed,
|
||||||
|
but KERNEL can be kept
|
||||||
|
|
||||||
|
o inc a -> ina, dec a -> dea (right now uses bare inc and dec)
|
||||||
|
|
||||||
|
o VICE label file support
|
||||||
|
|
||||||
|
o Smarter -X that can cope with non-block-aligned segment sizes
|
||||||
6
xa-2.3.5/doc/README
Normal file
6
xa-2.3.5/doc/README
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
As of 2.3.0, the official documentation will be maintained in the ../man/
|
||||||
|
directory. However, as the feature set is mostly mature, there is likely to
|
||||||
|
be little difference. The 2.2.x documents are here for your interest and
|
||||||
|
historical reference.
|
||||||
|
|
||||||
|
Cameron Kaiser
|
||||||
582
xa-2.3.5/doc/fileformat.txt
Normal file
582
xa-2.3.5/doc/fileformat.txt
Normal file
|
|
@ -0,0 +1,582 @@
|
||||||
|
|
||||||
|
6502 binary relocation format
|
||||||
|
|
||||||
|
V1.2 as of 26jan1998
|
||||||
|
|
||||||
|
(c) André Fachat (a.fachat@physik.tu-chemnitz.de)
|
||||||
|
_________________________________________________________________
|
||||||
|
|
||||||
|
Changes from V1.1
|
||||||
|
|
||||||
|
The order for saving the undefined reference and the low byte of a
|
||||||
|
high byte relocation entry has changed. This makes the OS/A65 lib6502
|
||||||
|
implementation easier. How many other people use this format
|
||||||
|
anyway...?
|
||||||
|
_________________________________________________________________
|
||||||
|
|
||||||
|
0) Preface
|
||||||
|
|
||||||
|
With some new 6502/C64/C128 operating systems comes the need for a new
|
||||||
|
binary format. In multitasking operating systems like Lunix, SMOS, or
|
||||||
|
OS/A65, a binary file cannot be loaded to a fixed location that might
|
||||||
|
already be used by another program. Therefore it must be possible to
|
||||||
|
relocate the program to an arbitrary address at least at load time. In
|
||||||
|
addition to that, more specific information might be stored in a
|
||||||
|
binary executable file, like interrupt vectors for example.
|
||||||
|
|
||||||
|
This text gives a good solution to this problem for the 6502 CPU and
|
||||||
|
an assembler source format to use this format in a general manner. The
|
||||||
|
file format can even be used as an object file format, i.e. a format a
|
||||||
|
linker can use as an input file. It is also usable as a 65816 file
|
||||||
|
format. Instead of zeropage addressing modes, the 65816 has direct
|
||||||
|
addressing modes, that add the contents of the direct register to the
|
||||||
|
zeropage address in the opcode.
|
||||||
|
|
||||||
|
1) 6502/65816 specifics
|
||||||
|
|
||||||
|
The 6502 has the special feature of a 'zeropage', i.e. a very limited
|
||||||
|
memory address range used for special addressing modes. So the format
|
||||||
|
should not only provide a means to relocate absolute addresses but
|
||||||
|
also zeropage addresses. The 65816 replaces zeropage addressing with
|
||||||
|
direct addressing modes.
|
||||||
|
|
||||||
|
The stack space is also very limited. A binary format has to provide a
|
||||||
|
measure of how much stack space is needed for the application.
|
||||||
|
|
||||||
|
Such limits should be defined as 2 byte values, even if the 6502 only
|
||||||
|
has a range of 8 address bits for zeropage and stack. But the 65816
|
||||||
|
behaves differently, it has a 16 bit stack pointer for example. For
|
||||||
|
further expandability, a 32 bit format should be provided, although
|
||||||
|
the 16 bit format suffices for the 65816 already.
|
||||||
|
|
||||||
|
Another problem is, that an address can be 'split', i.e. you can just
|
||||||
|
use the high byte or the low byte separately in an opcode. This gives
|
||||||
|
need to a special relocation table format, that can cope with
|
||||||
|
half-address references. The 65816 can even have three byte addresses,
|
||||||
|
i.e. address in a segment and segment number.
|
||||||
|
|
||||||
|
2) binary format
|
||||||
|
|
||||||
|
2.1) General
|
||||||
|
|
||||||
|
The file differs from the known Commodore file formats, in that a lot
|
||||||
|
more information is stored in the file. First the data is structured
|
||||||
|
in separate segments to allow different handling of text (program
|
||||||
|
code), data (like tables) and bss (uninitialized data).
|
||||||
|
|
||||||
|
Also tables are included to allow late binding, i.e. linking the file
|
||||||
|
with other files at load time, and relocation, i.e. executing the file
|
||||||
|
at different addresses in 6502 address space.
|
||||||
|
|
||||||
|
2.2) Segments
|
||||||
|
|
||||||
|
As already used in other formats, the assembler uses three different
|
||||||
|
segment types, i.e. text (the actual program code), data (initialized
|
||||||
|
variables), and bss (uninitialized variables). To have these different
|
||||||
|
segments seems to be 'overdesigned', but they actually make memory
|
||||||
|
handling easier in more complex operating systems on systems with
|
||||||
|
virtual addresses (OS/A65, for example).
|
||||||
|
|
||||||
|
The text segment is defined to be read-only memory. This doesn't allow
|
||||||
|
self-modifying code in this segment, but allows memory sharing in
|
||||||
|
virtual memory architectures. The data segment actually is like the
|
||||||
|
text segment, only it is allocated writable. This segment might not be
|
||||||
|
shared between different processes. The contents of these two segments
|
||||||
|
are loaded from the file. The bss segment is uninitialized data, i.e.
|
||||||
|
upon program start, it is not defined - and not loaded from the file.
|
||||||
|
This area is read-write and can be used during program execution. It
|
||||||
|
is also not shared between processes. In addition to these segments,
|
||||||
|
the 6502 format also includes a zeropage segment type, to allow
|
||||||
|
zeropage variables to be relocated. This zeropage segment is like a
|
||||||
|
bss segment, in that only the length, but not the data is saved. For
|
||||||
|
the 65816 the zeropage segment changes its meaning to a bank zero
|
||||||
|
segment.
|
||||||
|
|
||||||
|
The different segments hold different type of data and can be located
|
||||||
|
anywhere in memory (except zero segment, which has to be in the
|
||||||
|
zeropage resp. bank zero). The program must therefore not assume
|
||||||
|
anything about the relative addresses between different segments.
|
||||||
|
|
||||||
|
2.3) Relocation
|
||||||
|
|
||||||
|
In general, there are three ways to handle the relocation problem so
|
||||||
|
far:
|
||||||
|
|
||||||
|
- Tables: have a relocation table for a text segment
|
||||||
|
if the relocation table is put in front of code
|
||||||
|
you have to save the table in a side-storage
|
||||||
|
if table is behind, you still cannot relocate 'on the fly'.
|
||||||
|
|
||||||
|
- Deassembling: go through the code, deassemble it and change all absolute
|
||||||
|
addresses. Problem: needs to know or have hints about where some
|
||||||
|
data is in the code.
|
||||||
|
|
||||||
|
- Relocation info in the code: here each address is preceeded with an
|
||||||
|
'escape' code and is relocated when loading. But this disallows block
|
||||||
|
oriented transfer from storage media to memory.
|
||||||
|
|
||||||
|
This binary format uses the first method, with the table after the
|
||||||
|
code/data. This way block oriented transfer for the text/data segment
|
||||||
|
can be used. And while reading the relocation tables bytewise, the
|
||||||
|
relocation can be done without the need to save the table somewhere.
|
||||||
|
|
||||||
|
2.4) External References & Exported Globals
|
||||||
|
|
||||||
|
As this file format should not only be used as an executable format,
|
||||||
|
but also as object file format, it must provide a way to define
|
||||||
|
references - references exported from this object and labels
|
||||||
|
referenced in this object. The external references list (also called
|
||||||
|
'undefined list') lists the addresses where labels not defined in this
|
||||||
|
object are referenced. The exported globals list lists the addresses
|
||||||
|
that are available for other objects. The labels are named by
|
||||||
|
null-terminated ASCII strings.
|
||||||
|
|
||||||
|
Even an executable file can have non-empty globals and externals
|
||||||
|
lists, but only if the operating system allows this. In this case, so
|
||||||
|
called 'late binding' is used to link the object with some global
|
||||||
|
libraries at link time.
|
||||||
|
|
||||||
|
2.5) File extension
|
||||||
|
|
||||||
|
The proposed standard extension for the described format is ".o65"
|
||||||
|
when used as an object file.
|
||||||
|
|
||||||
|
2.6) Format description
|
||||||
|
|
||||||
|
The binary format is the following:
|
||||||
|
(
|
||||||
|
header
|
||||||
|
|
||||||
|
text segment
|
||||||
|
|
||||||
|
data segment
|
||||||
|
|
||||||
|
external references list
|
||||||
|
|
||||||
|
relocation table for text segment
|
||||||
|
|
||||||
|
relocation table for data segment
|
||||||
|
|
||||||
|
exported globals list
|
||||||
|
)
|
||||||
|
|
||||||
|
The description of the parts follows:
|
||||||
|
|
||||||
|
2.6.1) Header
|
||||||
|
|
||||||
|
The header contains the minimum needed data in a fixed struct. The
|
||||||
|
rest of the necessary information is put into the header options.
|
||||||
|
[Note: .word is a 16 bit value, low byte first, .byt is a simple byte.
|
||||||
|
.long is a 32 bit value, low byte first. .size is a 16 or 32 bit value
|
||||||
|
according to .word and .long, depending on the size bit in the mode
|
||||||
|
field ]
|
||||||
|
|
||||||
|
This is the fixed struct:
|
||||||
|
(
|
||||||
|
.byt $01,$00 ; non-C64 marker
|
||||||
|
|
||||||
|
.asc "o65" ; o65 MAGIC!
|
||||||
|
.byt 0 ; version
|
||||||
|
|
||||||
|
.word mode ; mode word
|
||||||
|
|
||||||
|
.size tbase ; address to which text is assembled to
|
||||||
|
; originally
|
||||||
|
.size tlen ; length of text segment
|
||||||
|
.size dbase ; originating address for data segment
|
||||||
|
.size dlen ; length of data segment
|
||||||
|
.size bbase ; originating address for bss segment
|
||||||
|
.size blen ; length of bss segment
|
||||||
|
.size zbase ; originating address for zero segment
|
||||||
|
.size zlen ; length of zero segment
|
||||||
|
.size stack ; minimum needed stack size, 0= not known.
|
||||||
|
; the OS should add reasonable values for
|
||||||
|
; interrupt handling before allocating
|
||||||
|
; stack space
|
||||||
|
)
|
||||||
|
|
||||||
|
The mode word currently has these defined bits:
|
||||||
|
mode.15 : CPU 0= 6502 1= 65816
|
||||||
|
mode.14 : reloc 0= bytewise... 1= page(256byte)wise relocation
|
||||||
|
allowed
|
||||||
|
mode.13 : size 0= size=16 bit, 1= size=32 bit
|
||||||
|
mode.12 : obj 0= executable 1= object file
|
||||||
|
|
||||||
|
mode.0-1: align 0= byte align,
|
||||||
|
1= word (i.e. 2 byte) align
|
||||||
|
2= long (4 byte) align
|
||||||
|
3= block (256 byte) align
|
||||||
|
|
||||||
|
The CPU bit tells the loader for which CPU the file was made. This has
|
||||||
|
implications on the zero segment, for example. Also a system can check
|
||||||
|
if the program will run at all (on a 6502 that is). The reloc bit
|
||||||
|
defines if an object file can be relocated bytewise, or if it must be
|
||||||
|
page-aligned. A page has 256 bytes. The restriction to pagewise
|
||||||
|
relocation simplifies the relocation table and also allows simpler
|
||||||
|
compilers/assemblers. The size bit determines the size of the segment
|
||||||
|
base address and length entries. Currently the 16 bit size (size bit =
|
||||||
|
0) works for 6502 and 65816 CPUs.
|
||||||
|
|
||||||
|
The obj bit distinguishes between object files and executables. An
|
||||||
|
object file is used as assembler output that can be linked with other
|
||||||
|
object files to build an executable or an object library. The two
|
||||||
|
align bits give the address boundary the segments can be placed. Even
|
||||||
|
the 6502 needs this, as, for example, "jmp ($xxFF)" is broken. The
|
||||||
|
align bits are valid for all of the segments. [Note: if reloc=1, then
|
||||||
|
align should be 3. But if align=3, reloc need not be 1, because reloc
|
||||||
|
switches to a simpler version of the relocation table. The reloc bit
|
||||||
|
might be obsoleted in newer versions of this format. Though it should
|
||||||
|
be set, if necessary.]
|
||||||
|
|
||||||
|
All unused bits in the mode field must be zero.
|
||||||
|
|
||||||
|
Note that the header size is 26 if the size bit is zero and 44 if the
|
||||||
|
size bit is one.
|
||||||
|
|
||||||
|
The fixed sized struct is immediately followed by a list of header
|
||||||
|
options. Each header option consists of a single byte total length, a
|
||||||
|
type byte and some data bytes if needed. A single length byte of $00
|
||||||
|
ends the header option list.
|
||||||
|
|
||||||
|
(
|
||||||
|
{ ; optional options, more than one allowed
|
||||||
|
.byt olen ; overall length (including length and type
|
||||||
|
; byte
|
||||||
|
.byt otype ; option type
|
||||||
|
[ .byt option_bytes ]
|
||||||
|
}
|
||||||
|
.byt $00 ; end of options marker (i.e. option len=0)
|
||||||
|
)
|
||||||
|
|
||||||
|
The header options currently defined/proposed are:
|
||||||
|
- Filename:
|
||||||
|
type=0; len=strlen(filename_in_ascii)+3; content="filename_in_ascii",0
|
||||||
|
The string contains the name of the object.
|
||||||
|
|
||||||
|
- Operating System Header
|
||||||
|
type=1; len=?
|
||||||
|
the first data byte is the OS type:
|
||||||
|
1 OSA/65 header supplement
|
||||||
|
2 Lunix header supplement
|
||||||
|
[others to follow?]
|
||||||
|
the following data contains OS specific information.
|
||||||
|
A suggested data byte is the OS version as second byte.
|
||||||
|
|
||||||
|
- Assemblerprogram:
|
||||||
|
type=2; len=strlen(ass)+3; content="ass",0
|
||||||
|
The string contains the name of the assembler resp. linker that produced
|
||||||
|
this file/object.
|
||||||
|
For example (syntax see below)
|
||||||
|
.fopt 2, "xa 2.1.1g",0
|
||||||
|
becomes
|
||||||
|
0c 02 78 61 20 32 2e 31 2e 31 67 00
|
||||||
|
in the file.
|
||||||
|
|
||||||
|
- Author:
|
||||||
|
type=3; len=strlen(author)+3; content="author",0
|
||||||
|
The string contains the author of the file.
|
||||||
|
|
||||||
|
- Creation data:
|
||||||
|
type=4; len=strlen(date)+3; content="date_string",0
|
||||||
|
The string contains the creation date in format like:
|
||||||
|
"Sat Dec 21 14:00:23 MET 1996", where we have the day, Month, date,
|
||||||
|
time, timezone and year. See output of `date`...
|
||||||
|
|
||||||
|
2.6.2) text and data segments
|
||||||
|
|
||||||
|
The text and data segments are just the assembled code. The only
|
||||||
|
difference between text and data segments is the read/write mode of
|
||||||
|
the two segments. Therefore, to be compliant to this file format,
|
||||||
|
self-modifying code goes into the data segment.
|
||||||
|
|
||||||
|
2.6.3) Undefined references list
|
||||||
|
|
||||||
|
The next list is an ASCII list of labels that are referenced in this
|
||||||
|
file but not defined. The lists is preceeded with the number of
|
||||||
|
undefined labels (16 or 32 bits, according to the mode.size bit).
|
||||||
|
|
||||||
|
undef_list: number_of_undefined_labels.s
|
||||||
|
"undefined_label1",0
|
||||||
|
"undefined_label2",0
|
||||||
|
...
|
||||||
|
|
||||||
|
2.6.4) Relocation tables
|
||||||
|
|
||||||
|
The relocation tables are the same format for the two segments, text
|
||||||
|
and data. In general a relocation entry consists of the offset from
|
||||||
|
the previous relocation address to the next one, the type of the
|
||||||
|
relocation and additional info. Relocation not only defines the
|
||||||
|
relocation when moving object code to a different address, but also
|
||||||
|
filling in the undefined references.
|
||||||
|
|
||||||
|
Each table starts at relocation address = segment base address -1.
|
||||||
|
I.e. if the segment base address is $1000 for example, the first entry
|
||||||
|
has an offset computed from base address-1 = $0fff. The offset to the
|
||||||
|
next relocation address is the first byte of each entry. If the offset
|
||||||
|
is larger than 254 (i.e. 255 or above), than a 255 is set as offset
|
||||||
|
byte, the offset is decremented by 254 (note the difference) and the
|
||||||
|
entry is started again.
|
||||||
|
|
||||||
|
{ [255,...,255,] offset of next relocation (b), typebyte|segmentID [, low_byte]
|
||||||
|
}+
|
||||||
|
|
||||||
|
where typebyte has the bits 5, 6 and 7 and is one of
|
||||||
|
WORD $80 2 byte address
|
||||||
|
HIGH $40 high byte of an address
|
||||||
|
LOW $20 low byte of an address
|
||||||
|
SEGADR $c0 3 byte address (65816)
|
||||||
|
SEG $a0 segment byte of 3 byte address
|
||||||
|
|
||||||
|
The segmentID stands for the segment the reference points to:
|
||||||
|
0 undefined
|
||||||
|
1 absolute value
|
||||||
|
2 text segment
|
||||||
|
3 data segment
|
||||||
|
4 bss segment
|
||||||
|
5 zero segment
|
||||||
|
|
||||||
|
(Of course the absolute value will never appear in a relocation table,
|
||||||
|
but this value is necessary for the exported list)
|
||||||
|
|
||||||
|
If the type is HIGH, the low byte of the value is stored behind the
|
||||||
|
relocation table entry, if bytewise relocation is allowed (header mode
|
||||||
|
field bit 14). If only pagewise relocation is allowed, then only HIGH
|
||||||
|
relocation entries can occur, and the low byte is implicitely set zero
|
||||||
|
(i.e. it is _not_ saved in the relocation table).
|
||||||
|
|
||||||
|
If the type is SEG, then the two lower bytes of the three byte segment
|
||||||
|
address are stored behind the entry in the relocation table, lower
|
||||||
|
byte first.
|
||||||
|
|
||||||
|
If the segment is "undefined", the typebyte is immediately followed by
|
||||||
|
the two (mode size=0) or four (mode size=1) byte value index in the
|
||||||
|
undefined references list. If it is a high byte relocation, the low
|
||||||
|
byte is saved behind the index value. The index value determines the
|
||||||
|
undefined reference, which must be looked up by the loader.
|
||||||
|
|
||||||
|
The value taken from the relocation address in the segment, together
|
||||||
|
with the low byte from the relocation table (if HIGH entry) form the
|
||||||
|
address used if the segment would be used unrelocated. To relocate the
|
||||||
|
segment, the difference between the relocated segment base address and
|
||||||
|
the segment base address from the file is then added to the above
|
||||||
|
address. The result is again saved in the segment.
|
||||||
|
|
||||||
|
A zero offset byte ends the relocation table. The first offset is
|
||||||
|
computed from the segment base address-1, to avoid a 0 value in the
|
||||||
|
first entry.
|
||||||
|
|
||||||
|
Note that direct addressing modes do not generate entries in the
|
||||||
|
relocation table. instead it is assumed that the 65816 direct register
|
||||||
|
holds the correct value (i.e. zero segment base address) when running
|
||||||
|
this program.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
Segment Base address in file (header.tbase) is $1000. The start
|
||||||
|
address of the text segment after relocation is real.tbase = $1234.
|
||||||
|
|
||||||
|
Now the first (unrelocated) address at which a relocation should take
|
||||||
|
place is here:
|
||||||
|
|
||||||
|
$1222 A9 23 lda #>vector
|
||||||
|
|
||||||
|
This generates the offset: $1222-($1000-1) = $223. This is larger than
|
||||||
|
254 ($fe), so the first byte is 255 ($ff). The offset is decremented
|
||||||
|
by $fe, and gives $125. This again is larger than $fe, so the next
|
||||||
|
byte is $ff again. After substracting $fe again, we have $27. But this
|
||||||
|
is the address of the opcode. To get the address of the address byte,
|
||||||
|
we have to add 1 to get $28, which becomes the third byte. The next
|
||||||
|
offset is then computed from $1223, because this is the last
|
||||||
|
relocation address.
|
||||||
|
|
||||||
|
Now we reference the high byte of an address, lets say vector=$23d0
|
||||||
|
(not relocated), in the text segment. Therefore the relocation type
|
||||||
|
becomes 'HIGH | text_segmentID = $42', which is the next byte. Because
|
||||||
|
we are referencing a high byte of an address, the low byte of the
|
||||||
|
unrelocated address is saved behind the typebyte in the relocation
|
||||||
|
entry. This byte is missing when referencing a low byte or address.
|
||||||
|
|
||||||
|
The relocation table entry is now:
|
||||||
|
$ff, $ff, $28, $42, $d0.
|
||||||
|
|
||||||
|
When actually doing the relocation, the relocation pointer is
|
||||||
|
initialized to real.tbase-1 = $1233. Then we compute the offset to
|
||||||
|
$224, which brings us to $1457, where the address byte of the above
|
||||||
|
opcode is after loading the file to $1234. We now have to compute the
|
||||||
|
new address, where vector is after relocation. So we take the
|
||||||
|
unrelocated low byte from the relocation table ($d0) and the high byte
|
||||||
|
from $1457 ($23).
|
||||||
|
|
||||||
|
vector_file = ($23
|
||||||
|
To this value we add
|
||||||
|
the difference between the address the program is assembled to and the
|
||||||
|
real load address:
|
||||||
|
|
||||||
|
vector_relocated = vector_file + (real.tbase - header.tbase)
|
||||||
|
= $23d0 + ($1234 - $1000)
|
||||||
|
= $23d0 + $234
|
||||||
|
= $2604
|
||||||
|
|
||||||
|
From this value the high byte is then written back to the address $1457.
|
||||||
|
Had we not saved the low byte in the relocation table, and only added
|
||||||
|
the high bytes, we would have missed the carry bit that increments
|
||||||
|
the high byte in this case!
|
||||||
|
|
||||||
|
Had "vector" now been an undefined reference, and "vector" would be
|
||||||
|
the second label in the undefined references list, we would get the
|
||||||
|
following relocation table entry (assuming mode.size=0):
|
||||||
|
|
||||||
|
$ff, $ff, $28, $40, $00, $02, $00
|
||||||
|
|
||||||
|
The value computed with the above formula for vector_file is now added
|
||||||
|
to the address the label "vector" now really has (This must of course
|
||||||
|
be looked up into an external table or list).
|
||||||
|
Had the opcode been "LDA #>vector+$567", then the low byte in the relocation
|
||||||
|
table would be $67, while the high byte in the opcode would be $05.
|
||||||
|
This value would result in vector_file and the real address of "vector"
|
||||||
|
would be added before wrting back the high byte to the opcode.
|
||||||
|
|
||||||
|
|
||||||
|
2.6.5) exported globals list
|
||||||
|
|
||||||
|
|
||||||
|
The global list is a list of names, together with the target segment
|
||||||
|
and the offset in the segment for each name. It is preceeded with the
|
||||||
|
number of exported labels. This allows the loader to allocate a table
|
||||||
|
large enough, if needed. The number of labels and the offset value
|
||||||
|
are 16 bit or 32 bit values according to the size bit in the header mode
|
||||||
|
field. The segmentID is a byte value and the same as in the relocation
|
||||||
|
table entry (see section 2.6.3).
|
||||||
|
|
||||||
|
number_of_exported_labels.s
|
||||||
|
"global_label_name_in_asc1",0, segmentID.b, value.s
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
3) assembler source format
|
||||||
|
|
||||||
|
|
||||||
|
The assembler source format is a suggestion only. It will be implemented
|
||||||
|
in xa65, a cross assembler for 6502 CPUs running on Unix/Atari ST/Amiga
|
||||||
|
as a reference platform.
|
||||||
|
|
||||||
|
The assembler provides a way to embed absolute address code in relocatable
|
||||||
|
code. This is needed when code should be copied to a specific location
|
||||||
|
known at assemble time.
|
||||||
|
There also is a way to make a file 'romable'. You can give the start
|
||||||
|
address of the _file_ in ROM, and the assembler automatically sets
|
||||||
|
the text segment start address to where the code will be in the ROM.
|
||||||
|
Of course, the other segments must be taken care of with -b? command
|
||||||
|
line parameter, that set the segment start address.
|
||||||
|
|
||||||
|
3.1) embed absolute code in relocatable files
|
||||||
|
|
||||||
|
|
||||||
|
When the assembler is started in relocatable mode, everything is put into
|
||||||
|
a .o65 relocatable file. All address references generate relocation table
|
||||||
|
entries. If a "*= value" pseudo opcode is encountered,
|
||||||
|
then the assembler switches to absolute mode. The following opcodes don't
|
||||||
|
generate relocation table entries. If a "*=" without a value is read,
|
||||||
|
then the assembler switches back to relocatable mode. The relocation
|
||||||
|
program counter is increased with the length of the absolute part and
|
||||||
|
the absolute code is embedded between the relocatable parts.
|
||||||
|
|
||||||
|
3.2) embed relocatable code in absolute files
|
||||||
|
|
||||||
|
|
||||||
|
This is dropped - too complicated. Should better be done with some
|
||||||
|
objdump or linker programs or so.
|
||||||
|
|
||||||
|
3.2) Header options
|
||||||
|
|
||||||
|
|
||||||
|
Before any opcode (after starting in relocatable mode, or after a .reloc
|
||||||
|
opcode), a header option can be set by:
|
||||||
|
|
||||||
|
.fopt byte1, byte2, ...
|
||||||
|
|
||||||
|
The header option length is automatically set by the assembler.
|
||||||
|
An example for an file author entry:
|
||||||
|
|
||||||
|
.fopt 3, "Andre Fachat",0
|
||||||
|
|
||||||
|
The 3 is the type byte for the author header option. The last zero ends
|
||||||
|
the name. The assembler can be configured to automatically include an
|
||||||
|
assembler header option into a file header.
|
||||||
|
|
||||||
|
3.3) allocation of data segment/zeropage segment address space
|
||||||
|
|
||||||
|
|
||||||
|
The assembler switches between the different segments by the means of
|
||||||
|
".text", ".data", ".bss" and ".zero" pseudo opcodes. After starting in
|
||||||
|
relocatable mode, the assembler is in the text segment.
|
||||||
|
|
||||||
|
The text segment contains the program code. Data holds the initialized data,
|
||||||
|
while bss and zero segments contain uninitialized data for normal/zeropage
|
||||||
|
address space.
|
||||||
|
Everything that is between one of these segment opcodes and the next segment
|
||||||
|
opcode gets into the corresponding segment, i.e. labels, assembled code etc.
|
||||||
|
The text and data segments are saved in the file, while for the bss and
|
||||||
|
zero segments only the length is saved in the file.
|
||||||
|
|
||||||
|
The assembler should issue a warning when a direct addressing mode
|
||||||
|
is used without a zero segment address and vice versa for 65816 CPUs.
|
||||||
|
|
||||||
|
3.4) referencing data/bss/zeropage addresses
|
||||||
|
|
||||||
|
|
||||||
|
One problem with the 6502 is, that it cannot load an address within one
|
||||||
|
step or assembler opcode. So an address is loaded with standard byte
|
||||||
|
opcodes, like "lda #
|
||||||
|
The assembler is now intelligent enough to evaluate such expressions
|
||||||
|
and check for:
|
||||||
|
|
||||||
|
- no address label : ok, absolute
|
||||||
|
- one address label, only add to label : ok, relocate
|
||||||
|
- difference between two addresses : If addresses in same segment, compute
|
||||||
|
diff and set absolute, otherwise bail
|
||||||
|
- everything else : warning
|
||||||
|
|
||||||
|
This way there is no change in syntax. Address labels are distinguished
|
||||||
|
by using the "label:" syntax, as opposed to "label = value".
|
||||||
|
Also, if the assembler is capable of doing so, an address label may be
|
||||||
|
defined by "label opcode", i.e. without a colon.
|
||||||
|
|
||||||
|
3.5) aligning code
|
||||||
|
|
||||||
|
|
||||||
|
The 6502 has the problem that some opcodes (e.g. "JMP ($xxFF)" are
|
||||||
|
broken, if the address given is at some (odd) address. But when loading
|
||||||
|
a relocatable file, one cannot know if an address will be odd or even.
|
||||||
|
Therefore there is a new opcode,
|
||||||
|
|
||||||
|
.align 2
|
||||||
|
|
||||||
|
that aligns the next address at the given address boundary. Valid
|
||||||
|
values are 2, 4, and 256.
|
||||||
|
|
||||||
|
4) Clearance
|
||||||
|
|
||||||
|
|
||||||
|
This file is surely not the optimum and could be improved. Also the
|
||||||
|
header option "assigned numbers" should be added here.
|
||||||
|
|
||||||
|
For this reason the author, André Fachat, will function as a
|
||||||
|
clearing point, where problems can be discussed and number can be assigned.
|
||||||
|
|
||||||
|
|
||||||
|
Dec. 22, 1996,
|
||||||
|
|
||||||
|
André Fachat
|
||||||
|
|
||||||
|
(fachat@physik.tu-chemnitz.de)
|
||||||
|
|
||||||
|
|
||||||
|
Appendix
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
A) File examples
|
||||||
|
|
||||||
|
|
||||||
|
(to be done with reference assembler)
|
||||||
89
xa-2.3.5/doc/xa-de.log
Normal file
89
xa-2.3.5/doc/xa-de.log
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
|
||||||
|
******** XASS65 1.0 ******** 15.11.89, Andre Fachat
|
||||||
|
|
||||||
|
2-Pass-Assembler f<>r 65(C)02. von Rockwell. Der erste Pass berechnet
|
||||||
|
die Labels, im zweiten Pass wird assembliert. Es wird eine Block-Struktur
|
||||||
|
unterst<EFBFBD>tzt, d.h. die Pseudo-Opcodes .( und .) verbergen dazwischenliegende
|
||||||
|
Labels vor Zugriffen aus anderen als dar<61>berliegenden Blocks.
|
||||||
|
Die Quell-, Object- und Fehlerdateien m<>ssen in der Kommandozeile angegeben
|
||||||
|
werden.
|
||||||
|
|
||||||
|
******** XASS 1.0 ******* 1.4.90, Andre Fachat
|
||||||
|
|
||||||
|
Die Object- und Fehlerdateien werden, falls nicht anders angegeben aus
|
||||||
|
der ersten Quelldatei durch „ndern der Extension ermittelt.
|
||||||
|
Es gibt jetzt einen C-„hnlichen Preprozessor mit define, ifdef, include etc.
|
||||||
|
'Funktionen' k”nnen keine definiert werden.
|
||||||
|
|
||||||
|
******** XA 2.00 ******** Andre Fachat
|
||||||
|
|
||||||
|
Ab jetzt wird das, was im ersten Pass schon zur Ermittelung der Opcode-
|
||||||
|
L„nge assembliert wurde zwischengespeichert. Das verdoppelt die
|
||||||
|
Geschwindigkeit ann„hernd. Dabei wird alles, was bekannt ist, vertokend,
|
||||||
|
um sp„ter nicht wieder soviel suchen zu m<>ssen.
|
||||||
|
|
||||||
|
******** XA 2.02 ******** 23.9.90, Andre Fachat
|
||||||
|
|
||||||
|
Labels k”nnen mit vorangestelltem '&' eine Blockstufe h”her definiert
|
||||||
|
werden, mit einem '-' werden sie global definiert (Block=0).
|
||||||
|
Bei eingeschalteter Option -c werden Fehler bei CMOS-Befehlen erzeugt.
|
||||||
|
Die Tabellen f<>r die Token-Erkennung sind vereinfacht und damit schneller
|
||||||
|
gemacht.
|
||||||
|
|
||||||
|
******** XA 2.03 ******** 16.6.91, Andre Fachat
|
||||||
|
|
||||||
|
Jetzt wird automatisch eine Liste mit Labels erzeugt und in einer .LAB-Datei
|
||||||
|
gespeichert. Im Preprozessor gibt es jetzt #if.
|
||||||
|
|
||||||
|
******** XA 2.04 ******** 14.7.91, Andre Fachat
|
||||||
|
|
||||||
|
Die Labeltabelle kann jetzt gr”žer als 32kByte werden. Da ein Eintrag in der
|
||||||
|
Label-Tabelle ohne den eigentlichen Namen 14 Byte betr„gt, sind jetzt mehr
|
||||||
|
als 2340 Labels m”glich.
|
||||||
|
Im Preprozessor sind jetzt auch 'Funktions'definitionen m”glich , also
|
||||||
|
z.B. #define mult(a,b) ((a)*(b))
|
||||||
|
|
||||||
|
******** XA 2.05 ******** 29.7.91, Andre Fachat
|
||||||
|
|
||||||
|
F<EFBFBD>r Labels, Defines und die Opcodes wird die Suche nach Hashcode durchgef<65>hrt.
|
||||||
|
damit werden ca. 350kByte Quelltext f<>r ein 32kByte EPROM nicht mehr in
|
||||||
|
18 sondern in ca. 3 Minuten assembliert.
|
||||||
|
|
||||||
|
******** XA 2.06 ******** 18.9.91,Andre Fachat
|
||||||
|
|
||||||
|
Der Preprozessor hat jetzt #ifldef und #iflused, was eigentlich heižt
|
||||||
|
'if label defined' und 'if label used'. Damit lassen sich Bibliotheks-
|
||||||
|
„hnliche Dateien aufbauen.
|
||||||
|
Die Umstellung auf PureC bringt ihn dazu, 350kByte (s.o.) in 2 Minuten zu
|
||||||
|
assemblieren. Die Vergr”žerung der Datei-Puffer per setvbuf() auf 4kByte
|
||||||
|
bringt auch noch 7 Sekunden. Aužerdem wird am Ende eine Statistik <20>ber
|
||||||
|
verbrauchte Resourcen gedruckt.
|
||||||
|
|
||||||
|
******** XA 2.07 ******** 30.9.91, Andre Fachat
|
||||||
|
|
||||||
|
Jetzt wird Zeit und Datum sowie die verbrauchten Sekunden in der Statistik
|
||||||
|
gezeigt. Die Environment-Variablen XAINPUT und XAOUTPUT werden unterst<73>tzt.
|
||||||
|
Falls die Quell- und Include-Dateien nicht gefunden werden, werden die in
|
||||||
|
XAINPUT aufgef<65>hrten Pfade der Reihe nach durchgetestet. Falls XAOUTPUT
|
||||||
|
existiert, wird dieser Pfad als Pfad f<>r .ERR, .LAB und .OBJ-Dateien
|
||||||
|
benutzt. Nach einem Turbo-C Referenzhandbuch sind alle Systemaufrufe
|
||||||
|
(malloc, fopen etc.) jetzt ANSI-kompatibel. (Der C-Quellcode allerdings
|
||||||
|
ist die Darstellung von Chaos im besten K&R-Stil...)
|
||||||
|
|
||||||
|
******** 16.2.92, Andre Fachat
|
||||||
|
|
||||||
|
#print und #printdef werden unterdr<64>ckt, wenn sie in der entsprechenden
|
||||||
|
#if-Strukur sind (war bisher im Gegensatz zu echo und include nicht so)
|
||||||
|
|
||||||
|
******** XA 2.07b ******** 5.1.94, Andre Fachat
|
||||||
|
|
||||||
|
Auf englisch uebersetzt, die Abhaengigkeit des Header-files von
|
||||||
|
stdio.h beseitigt, ebenso die Abhaengigkeit von der integer size.
|
||||||
|
in xah.h gibt es jetzt einen Define DIRCHAR und DIRCSTRING, die
|
||||||
|
das Verzeichnistrennzeichen definieren (DIRCHAR als '/' bzw '\\' und
|
||||||
|
DIRCSTRING als "/" bzw. "\\")
|
||||||
|
|
||||||
|
******** XA 2.0.7d ******** 96, Andre Fachat
|
||||||
|
|
||||||
|
Mehr auf Englisch übersetzt. #undef kann ein define löschen.
|
||||||
|
|
||||||
394
xa-2.3.5/doc/xa-de.txt
Normal file
394
xa-2.3.5/doc/xa-de.txt
Normal file
|
|
@ -0,0 +1,394 @@
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
XA 2.1.0
|
||||||
|
|
||||||
|
65(c)02 Cross-Assembler
|
||||||
|
|
||||||
|
von Andre Fachat
|
||||||
|
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* Block-Struktur (Versteckte Label)
|
||||||
|
|
||||||
|
* Sehr schnell durch hashing
|
||||||
|
|
||||||
|
* C-ähnlicher Preprozessor
|
||||||
|
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
1. Was ist das überhaupt und Geschichte
|
||||||
|
|
||||||
|
2. Aufruf und Features
|
||||||
|
|
||||||
|
3. 6502 Assembler
|
||||||
|
|
||||||
|
4. Pseudo-Opcodes, Block-Struktur und Gültigkeitsbereich von Labels
|
||||||
|
|
||||||
|
5. Preprozessor
|
||||||
|
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
1. Was ist das überhaupt und Geschichte
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
Mit dem Cross-Assembler können auf einem Rechner Programme für einen
|
||||||
|
anderen Rechner(typ) erstellt werden. Die Programmdateien müssen dann
|
||||||
|
nur noch auf das Zielsystem übertragen werden. In diesem Fall handelt
|
||||||
|
es sich um einen 6502-Cross-Assembler. Der 6502 ist ein 8-Bit-Prozessor,
|
||||||
|
der ursprünglich von MOS Technologies entwickelt wurde. Er tut seine
|
||||||
|
Dienste u.a. im Apple II, Commodore PET, VC20 und C64 (in abgewandelter
|
||||||
|
Form) und vielen anderen.
|
||||||
|
Inzwischen gibt es ihn in vielen Varianten mit verschiedenen Zusätzen
|
||||||
|
und in verschiedenen Gehäusen. Gemeinsam ist allen der Befehlssatz,
|
||||||
|
der für den Assembler die Grundlage bildet. Die CMOS-Versionen bieten
|
||||||
|
allerdings Erweiterungen des Befehlssatzes.
|
||||||
|
Die Idee zu einem Cross-Assembler entstand, als ich mir einen 6502-Computer
|
||||||
|
selbst baute und der (ebenfalls selbstgeschriebene) Assembler auf dem C64
|
||||||
|
zu langsam wurde. Nachdem auch noch ein Atari ST bei mir rumstand, war
|
||||||
|
die Idee schnell in die Tat umgesetzt.
|
||||||
|
|
||||||
|
|
||||||
|
2. Aufruf und Features
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
Der Assembler besteht nur aus dem Programm "xa".
|
||||||
|
Der Assembler verarbeitet eine oder mehrere Quelldateien zu einer
|
||||||
|
Objektdatei, die direkt verwendet werden kann. Das Linken entfällt, da der
|
||||||
|
Aufwand zu groß und die Geschwindigkeit hoch genug ist, um die
|
||||||
|
'Libraries' im Quelltext einzubinden. Ca. 350kByte Quelltext werden in
|
||||||
|
1 Minute und 50 Sekunden zu einer 32kByte Objektdatei für ein EPROM
|
||||||
|
assembliert (naja, der 8MHz Atari war nicht schnell. Aber dafür ist der
|
||||||
|
Wert ziemlich gut. Mein 486DX4/100 braucht vielleicht 2 Sekunden)!
|
||||||
|
Als Ausgabedateien werden eine Objektdatei, eine Fehlerdatei und eine
|
||||||
|
Labeldatei geschrieben.
|
||||||
|
|
||||||
|
Der Aufruf lautet:
|
||||||
|
XA Quell1 [Quell2 ...] [-oObject] [-eFehler] [-lLabel] [-C] [-v] [-x]
|
||||||
|
|
||||||
|
Die Angabe der Objekt-, Fehler- und Labeldatei ist optional, ohne Angabe
|
||||||
|
wird die Endung der ersten Quelldatei auf 'obj', 'err' und 'lab' verändert,
|
||||||
|
wenn "-x" angegeben ist. Ansonsten wird "a.o65" als Ausgabedatei verwendet
|
||||||
|
und keine Fehler- und Labeldatei geschrieben.
|
||||||
|
Die Option -C erzeugt Fehlermeldungen bei CMOS-Befehlen.
|
||||||
|
Im Environment werden die Variablen XAOUTPUT und XAINPUT unterstützt.
|
||||||
|
Falls die Quell- und Include-Dateien nicht gefunden werden, werden die in
|
||||||
|
XAINPUT aufgeführten Pfade der Reihe nach durchgetestet. Falls XAOUTPUT
|
||||||
|
existiert, wird dieser Pfad als Pfad für .err, .lab und .obj-Dateien
|
||||||
|
benutzt. Die Komponenten des Pfades sind mit ',' getrennt.
|
||||||
|
|
||||||
|
Die Labeldatei enthält hinterher eine Liste aller Labels mit Block-Nummer
|
||||||
|
und Wert in dezimal in der Form: 'Label, 1,-1234' in lesbarem ASCII.
|
||||||
|
Die Fehlerdatei enthält die Version des Assemblers, Datum und Uhrzeit des
|
||||||
|
Assemblerlaufs, die Liste der Fehler, die Ausdrücke, die mit #echo
|
||||||
|
und #print im Preprozessor erzeugt werden und eine Statistik über die
|
||||||
|
benutzten Resourcen (Speicherplatz etc.).
|
||||||
|
Die Objektdatei wird nur durch die Quelldatei bestimmt, es wird kein Code
|
||||||
|
vorgesetzt oder angehängt.
|
||||||
|
Die Quelldatei muß im ASCII-Format vorliegen.
|
||||||
|
|
||||||
|
|
||||||
|
3. 6502 Assembler
|
||||||
|
------------------
|
||||||
|
|
||||||
|
Da dies kein 6502-Assemblerkurs werden soll, nur eine ganz kurze
|
||||||
|
Beschreibung. Unterstützt wird der Code für alle Standard-6502 sowie
|
||||||
|
der Code für die Rockwell 65C02-CPU. Der Prozessor hat drei Register,
|
||||||
|
über die die meisten Operationen laufen. Transferoperationen benötigen
|
||||||
|
deshalb immer einen Load- und einen Store-Befehl.
|
||||||
|
Zusätzlich gibt es das Statusregister und den Stackpointer sowie,
|
||||||
|
natürlich, den Programmzähler. Der Stack liegt immer im Bereich $100 und
|
||||||
|
$1ff (Hexadezimal mit vorangestelltem '$'), weshalb der Stackpointer ein
|
||||||
|
8-Bit-Register ist. Eine besondere Behandlung durch kürzere Befehle
|
||||||
|
erfährt die Zeropage ($0-$ff), bei deren Adresse das Hi-Byte Null ist.
|
||||||
|
Das Statusregister besitzt folgende Flags:
|
||||||
|
|
||||||
|
N = Negativ
|
||||||
|
O = Overflow
|
||||||
|
B = Break
|
||||||
|
D = Dezimal
|
||||||
|
I = Interrupt
|
||||||
|
Z = Zeroflag
|
||||||
|
C = Carry
|
||||||
|
|
||||||
|
Befehle:
|
||||||
|
|
||||||
|
LDA lade Akkumulator
|
||||||
|
LDX lade X-Register
|
||||||
|
LDY lade Y-Register
|
||||||
|
|
||||||
|
STA speichere Akkumulator
|
||||||
|
STX speichere X-Register
|
||||||
|
STY speichere Y-Register
|
||||||
|
STZ speichere NULL (*)
|
||||||
|
|
||||||
|
TAX Kopiere Akku nach X
|
||||||
|
TAY Kopiere Akku nach Y
|
||||||
|
TXA Kopiere X nach Akku
|
||||||
|
TYA Kopiere Y nach Akku
|
||||||
|
TSX Kopiere Stackpointer nach X
|
||||||
|
TXS Kopiere X nach Stackpointer
|
||||||
|
|
||||||
|
ADC Addiere zu Akku mit Übertrag (Carry) (D)
|
||||||
|
SBC Subtrahiere von Akku mit Carry (D)
|
||||||
|
AND Logisches Und mit Akku
|
||||||
|
ORA Logisches Oder mit Akku
|
||||||
|
EOR Exklusiv-Oder mit Akku
|
||||||
|
BIT Bit-Test: Z=A&M, N=M7, O=M6
|
||||||
|
ROL Rotiere Links Akku oder Speicher A=A*2+C, C=A7
|
||||||
|
ROR Rotiere Rechts A=A/2+C*127, C=A0
|
||||||
|
ASL Arithmetisches Linksschieben A=A*2
|
||||||
|
LSR Logisches Rechtsschieben A=A/2
|
||||||
|
INX Erhöhe X-Register um eins
|
||||||
|
INY Y
|
||||||
|
INC Erhöhe Akku oder Speicher um eins
|
||||||
|
DEX Erniedrige X-Register um eins
|
||||||
|
DEY Y
|
||||||
|
DEC Erniedrige Akku oder Speicher um eins
|
||||||
|
|
||||||
|
CMP Vergleiche mit Akku (Substraktion ohne Akku zu ver„ndern)
|
||||||
|
CPX Vergleiche mit X-Register
|
||||||
|
CPY Vergleiche mit Y-Register
|
||||||
|
|
||||||
|
BNE Verzweige falls nicht Null
|
||||||
|
BEQ Null
|
||||||
|
BMI Negativ
|
||||||
|
BPL Positiv
|
||||||
|
BVC Overflow Clear
|
||||||
|
BVS Overflow Set
|
||||||
|
BCS Carry Set
|
||||||
|
BCC Carry Clear
|
||||||
|
BRA Verzweige immer (*)
|
||||||
|
|
||||||
|
JMP Springe an Adresse
|
||||||
|
JSR Springe in Unterroutine, R<>cksprungadresse auf dem Stack
|
||||||
|
RTS Return from Subroutine
|
||||||
|
|
||||||
|
CLC Carry-Flag löschen
|
||||||
|
SEC setzen
|
||||||
|
CLD Dezimal-Flag löschen
|
||||||
|
SED setzen
|
||||||
|
CLI Interrupt freigeben
|
||||||
|
SEI sperren
|
||||||
|
CLV Overflow-Flag löschen
|
||||||
|
|
||||||
|
PHA Akku auf Stack legen
|
||||||
|
PHX XR (*)
|
||||||
|
PHY YR (*)
|
||||||
|
PHP Status
|
||||||
|
PLA Akku vom Stack holen
|
||||||
|
PLX XR (*)
|
||||||
|
PLY YR (*)
|
||||||
|
PLP Status
|
||||||
|
|
||||||
|
BRK Löst Interrupt mit gesetztem Break-Flag aus
|
||||||
|
RTI Return from Interrupt
|
||||||
|
|
||||||
|
NOP No Operation
|
||||||
|
|
||||||
|
TRB Test und Reset Speicher mit Akku (*)
|
||||||
|
BBR Branch on Bit Reset (*)
|
||||||
|
BBS Branch on Bit Set (*)
|
||||||
|
RMB Reset Memory Bit (*)
|
||||||
|
SMB Set Memory Bit (*)
|
||||||
|
|
||||||
|
Die mit (*) markierten Befehle sind CMOS-Befehle. Außerdem haben einige
|
||||||
|
der anderen Befehle zusätzliche Addressierungsarten. Die mit (D) markierten
|
||||||
|
Befehle arbeiten im Dezimal-Mode (Dezimal-Flag gesetzt) anders, nämlich
|
||||||
|
im BCD-Mode (eine Ziffer von 0-9 in 4 Bit).
|
||||||
|
|
||||||
|
Addressierungsarten:
|
||||||
|
|
||||||
|
-Immediate LDA #$12
|
||||||
|
-Absolute STA $1234
|
||||||
|
-Zeropage EOR $10
|
||||||
|
-Bit,ZP,REL BBR #7,$10,label
|
||||||
|
-Akku ASL
|
||||||
|
-Implied TAX
|
||||||
|
-(Indirect,x) LDA ($10,X)
|
||||||
|
-(Indirect),y STA ($3e),Y
|
||||||
|
-Zeropage,x CMP $12,X
|
||||||
|
-Absolut,x LDY $4356,x
|
||||||
|
-(Absolut,x) jmp (jumptabelle,x)
|
||||||
|
-Absolut,y ORA $2345,y
|
||||||
|
-Relative BNE irgendwohin
|
||||||
|
-(Indirect) jmp (<28>berVektor)
|
||||||
|
-Zeropage,y ldx $12,y
|
||||||
|
-Bit,Zeropage RMB #1,zeropage
|
||||||
|
|
||||||
|
Bei Adressierungsarten, die in der Zeropage und Absolut existieren, wird,
|
||||||
|
soweit möglich die Zeropage-Adressierung angewendet. Ein vorangestelltes
|
||||||
|
'!' erzwingt absolute Adressierung, auch bei einem Wert kleiner 256.
|
||||||
|
Als Wert oder Adresse können arithmetische Ausdrücke mit Hierarchie und
|
||||||
|
Klammerung verwendet werden. Der Assembler versteht folgende Operanden:
|
||||||
|
|
||||||
|
123 -Dezimal
|
||||||
|
$234 -Hexadezimal
|
||||||
|
&123 -Oktal
|
||||||
|
%010110 -Binär
|
||||||
|
* -Programmzähler
|
||||||
|
"A" -ASCII-Code
|
||||||
|
labelx -Label
|
||||||
|
-(lab1+1) -Ausdruck
|
||||||
|
|
||||||
|
Folgende Operatoren können benutzt werden:
|
||||||
|
|
||||||
|
+ -Addition 9
|
||||||
|
- -Subtraktion 9
|
||||||
|
* -Multiplikation 10
|
||||||
|
/ -Integer-Division 10
|
||||||
|
<< -Shift nach links 8
|
||||||
|
>> -Shift nach rechts 8
|
||||||
|
>=,=> -größer oder gleich 7
|
||||||
|
<=,=< -kleiner oder gleich 7
|
||||||
|
< -kleiner 7
|
||||||
|
> -größer 7
|
||||||
|
= -gleich 6
|
||||||
|
<>,>< -ungleich 6
|
||||||
|
&& -Logisches UND 2
|
||||||
|
|| -Logisches ODER 1
|
||||||
|
& -Bitweises UND 5
|
||||||
|
| -Bitweises ODER 3
|
||||||
|
^ -Bitweises Exklusiv-Oder 4
|
||||||
|
|
||||||
|
Die Operatoren mit der höheren Priorität werden zuerst bearbeitet.
|
||||||
|
Ein gültiger Ausdruck ist dann z.B.
|
||||||
|
|
||||||
|
LDA base+number*2,x
|
||||||
|
|
||||||
|
Bei Addressierungsarten, die nicht mit einer Klammer beginnen, darf
|
||||||
|
auch im ersten Ausdruck keine Klammer am Anfang stehen:
|
||||||
|
|
||||||
|
LDX (1+2)*2,y ; Falsch !
|
||||||
|
LDX 2*(1+2),y ; Richtig !
|
||||||
|
|
||||||
|
Vor einem Ausdruck kann ein unärer Operator stehen:
|
||||||
|
|
||||||
|
< bildet Lo-Byte des Wertes
|
||||||
|
> bildet Hi-Byte des Wertes
|
||||||
|
|
||||||
|
LDA #<adresse
|
||||||
|
|
||||||
|
Die Einzelnen Befehle werden durch ':' oder eine neue Zeile getrennt.
|
||||||
|
Hinter jedem Befehl kann, durch ';' abgetrennt ein Kommentar stehen.
|
||||||
|
Der Kommentar gilt bis zum nächsten Doppelpunkt oder bis zur nächsten
|
||||||
|
Zeile.
|
||||||
|
|
||||||
|
|
||||||
|
4. Pseudo-Opcodes, Block-Struktur und Gültigkeitsbereich von Labels
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
|
||||||
|
Folgende Pseudo-Opcodes stehen noch zur Verfügung:
|
||||||
|
|
||||||
|
.byt wert1,wert2,wert3, ...
|
||||||
|
.word wert1,wert2, ...
|
||||||
|
.asc "text1","text2", ...
|
||||||
|
.dsb länge [,füllbyte]
|
||||||
|
*=
|
||||||
|
.(
|
||||||
|
.)
|
||||||
|
|
||||||
|
Hierbei sind '.byt' und '.asc' identisch und legen Daten Byteweise im
|
||||||
|
Speicher ab. '.word' legt Daten Wortweise (=2 Byte) im Speicher ab.
|
||||||
|
'.dsb' füllt einen Speicherbereich der Länge 'länge' mit dem Wert
|
||||||
|
'füllbyte' ab. Falls füllbyte nicht abgegeben ist, wird mit Null gefüllt.
|
||||||
|
Die folgenden Opcodes haben keine direkte Einwirkung auf die Objektdatei.
|
||||||
|
'*=' definiert den Programmzähler.
|
||||||
|
'.(' eröffnet einen neuen 'Block'. Alle Labels innerhalb eines solchen
|
||||||
|
Blocks sind lokal. Allerdings darf vorher kein Label gleichen Namens in
|
||||||
|
einem höheren Block definiert worden sein. '.)' schließt den Block wieder.
|
||||||
|
Die Maximale Blockschachtelungstiefe beträgt 16 Blocks.
|
||||||
|
|
||||||
|
Ein Label wird definiert dadurch, daß es kein Opcode ist:
|
||||||
|
|
||||||
|
label1 LDA #0 ; Position(=Programmzähler) des Opcodes
|
||||||
|
label2 =1234 ; direkte definition
|
||||||
|
label3 label4 label5 ; implizit Programmzähler, auch mehrere
|
||||||
|
; Labels werden definiert
|
||||||
|
label6 label7 = 3 ; label6 wird mit dem Wert des Programm-
|
||||||
|
; zählers gesetzt, label7 mit 3
|
||||||
|
label8: sta label2 ; Da Opcodes mit ':' getrennt werden,
|
||||||
|
; wird auch die übliche Schreibweise mit
|
||||||
|
; 'label:' erkannt.
|
||||||
|
|
||||||
|
Dabei werden Groß- und Kleinbuchstaben unterschieden.
|
||||||
|
Labels, die mit vorangestelltem '+' definiert werden, sind global (Block=0),
|
||||||
|
d.h. überall gültig. Mit vorangestellten '&' kann ein Label jeweils eine
|
||||||
|
Hierarchiestufe höher definiert werden als ohne '&'.
|
||||||
|
Mit vorangestelltem '-' kann ein Label umdefiniert werden:
|
||||||
|
|
||||||
|
-sysmem +=4 ; da gibts ==, +=, -=, *=, /=, &=, |=
|
||||||
|
-syszp =123
|
||||||
|
|
||||||
|
|
||||||
|
5. Preprozessor
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Der Preprozessor ist stark an den Preprozessor der Sprache C angelehnt.
|
||||||
|
So sind die für C typischen /* */ -Kommentare möglich.
|
||||||
|
Ein Preprozessor-Befehl wird mit einem '#' am Beginn der Zeile eingeleitet.
|
||||||
|
|
||||||
|
#include "Dateiname" fügt die Datei 'Dateiname' an dieser Stelle in den
|
||||||
|
Quelltext ein. Beim Laden wird zuerst der Name
|
||||||
|
direkt gesucht, danach mit den Pfaden aus
|
||||||
|
XAINPUT.
|
||||||
|
|
||||||
|
#echo Kommentar Gibt Kommentar in der Fehlerdatei aus.
|
||||||
|
|
||||||
|
#print ausdruck Gibt Ausdruck direkt, nach Preprzessorbehandlung
|
||||||
|
und nach dem Ausrechnen aus.
|
||||||
|
|
||||||
|
#printdef DEFINIERT Gibt die Definition in der Fehlerdatei aus.
|
||||||
|
|
||||||
|
#define DEF Text Definiert DEF als Text, deshalb wird hinterher
|
||||||
|
immer DEF durch Text ersetzt
|
||||||
|
|
||||||
|
#ifdef DEF Der Quelltext bis zum folgenden #endif oder #else
|
||||||
|
wird nur assembliert, falls DEF vorher mit #define
|
||||||
|
definiert wurde.
|
||||||
|
|
||||||
|
#else else halt...
|
||||||
|
|
||||||
|
#endif Beendet #if..-Konstrukt. Nach jedem #if.. muž!
|
||||||
|
ein #endif stehen.
|
||||||
|
|
||||||
|
#ifndef DEF .... falls DEF nicht definiert wurde.
|
||||||
|
|
||||||
|
#if ausdruck .... falls ausdruck ungleich null ist.
|
||||||
|
|
||||||
|
#iflused label .... falls Label schon benutzt wurde.
|
||||||
|
|
||||||
|
#ifldef label .... falls Label schon definiert wurde.
|
||||||
|
|
||||||
|
Dabei beziehen sich #iflused und #ifldef auf Labels, nicht auf Preprozessor-
|
||||||
|
Definitionen! Damit l„žt sich z.B. eine Bibliotheksstruktur aufbauen:
|
||||||
|
|
||||||
|
#iflused label
|
||||||
|
#ifldef label
|
||||||
|
#echo label schon definiert, nicht aus Library
|
||||||
|
#else
|
||||||
|
label lda #0
|
||||||
|
....
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Die #if-Schachtelungstiefe beträgt 15.
|
||||||
|
|
||||||
|
Mit #define können auch wie in C 'Funktionen' mit Parametern definiert
|
||||||
|
werden.
|
||||||
|
|
||||||
|
#define mult(a,b) ((a)*(b))
|
||||||
|
|
||||||
|
|
||||||
|
Literaturangaben
|
||||||
|
----------------
|
||||||
|
|
||||||
|
-"Das Maschinensprachebuch zum Commodore 64"
|
||||||
|
Lothar Englisch
|
||||||
|
Data Becker GmbH
|
||||||
|
-"Controller Products Data Book"
|
||||||
|
Rockwell International, Semiconductor Products Division
|
||||||
|
-"Programmieren in C"
|
||||||
|
Kernighan, Ritchie
|
||||||
|
Hanser Verlag
|
||||||
|
|
||||||
362
xa-2.3.5/doc/xa.html
Normal file
362
xa-2.3.5/doc/xa.html
Normal file
|
|
@ -0,0 +1,362 @@
|
||||||
|
<html><head><title> xa 2.1.4 6502 Cross Assembler </title></head>
|
||||||
|
<body bgcolor="#ffffff">
|
||||||
|
<hr>
|
||||||
|
<h1 align=center> XA 2.1.4 </h1>
|
||||||
|
<h2 align=center> 65(c)02 Cross Assembler </h2>
|
||||||
|
<h2 align=center> (c) Andre Fachat </h2>
|
||||||
|
<h2 align=center> email: fachat@galileo.rhein-neckar.de </h2>
|
||||||
|
<hr>
|
||||||
|
<ol>
|
||||||
|
<li> what it is
|
||||||
|
<li> parameters and features
|
||||||
|
<li> 6502 Assembler
|
||||||
|
<li> pseudo-opcodes, block structures and where labels are valid
|
||||||
|
<li> pre-processor
|
||||||
|
<li> utilities
|
||||||
|
</ol><ul>
|
||||||
|
<li> literature
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h3> What it is </h3>
|
||||||
|
|
||||||
|
This Cross-Assembler makes programms for another computer that has a 6502-like
|
||||||
|
CPU. This CPU has been widely used in the famous Apple II, all the Commodore
|
||||||
|
8-Bit Computers (PET, VC20 and a derivate in the C64) and many others.
|
||||||
|
Some are still used in one-chip microcontrollers, e.g. the Rockwell modem
|
||||||
|
chipset.
|
||||||
|
All these chip share a common set of standard machine language commands,
|
||||||
|
some of them (e.g. the CMOS versions) have additional (software) features.
|
||||||
|
<p>
|
||||||
|
I had the idea for this assembler when I built my small 6502 System that
|
||||||
|
had place for 32kByte ROM to take the kernel and lots of other programms.
|
||||||
|
(After all, it became a multitasking micro-kernel with file-systems for
|
||||||
|
IBM and Commodore, I can even use the IBM drives as Floppy for my C64 with
|
||||||
|
this computer as controller. Piping and i/o-redirection included, of course)
|
||||||
|
Development on my old C64 began to suck with programms growing. So I decided
|
||||||
|
to do a Cross-Assembler on my new Atari ST.
|
||||||
|
<p>
|
||||||
|
First versions were very like the old Assembler on the C64, not really
|
||||||
|
using the resources (Reading all files two times completely etc).
|
||||||
|
With files growing the assembler also became more sophisticated.
|
||||||
|
Now hashcodes are used for mnemonics, preprocessor definition and label
|
||||||
|
search (Version >= 2.0.5). The files are only read once, putting the
|
||||||
|
preassembled code into memory (Version >= 2.0), taking it from there on pass 2.
|
||||||
|
Now it makes about 350kByte Source Code to about 30kByte ROM code in
|
||||||
|
less then 2 Minutes on an 8 MHz Atari ST with 2.5 MByte RAM and Harddisk.
|
||||||
|
(Well, the Atari is not fast. On my 486DX4/100 it takes about 2 seconds...)
|
||||||
|
But adding the whole relocation stuff slowed it down again.
|
||||||
|
<p>
|
||||||
|
<h3> Parameters and features</h3>
|
||||||
|
|
||||||
|
The assembler contains only a single programm called "xa" (for Atari: XA.TTP).
|
||||||
|
It takes one or more Source files into one object file, that can directly
|
||||||
|
be used.
|
||||||
|
But the assembler also has a mode to produce relocatable files, conforming
|
||||||
|
to the 'o65' fileformat (See fileformat.txt).
|
||||||
|
<p>
|
||||||
|
Call:
|
||||||
|
<p><pre>
|
||||||
|
xa [options] Source1 [Source2 ...]
|
||||||
|
</pre>
|
||||||
|
Object: this is the name, the output (object) file gets
|
||||||
|
Error: Here you will find the Error listing.
|
||||||
|
Label: this is the label list
|
||||||
|
<p><pre>
|
||||||
|
'-C' gives error codes when using CMOS-opcodes. Default is not to
|
||||||
|
complain.
|
||||||
|
'-c' do not produce o65 executable, but object files that can
|
||||||
|
contain undefined references.
|
||||||
|
'-v' go into verbose mode
|
||||||
|
'-x' old filename behaviour (overrides -o, -e and -l)
|
||||||
|
'-R' do not produce absolute code, but do relocation and all that.
|
||||||
|
'-o filename' set output filename
|
||||||
|
'-e filename' set errorlog filename
|
||||||
|
'-l filename' set labellist filename
|
||||||
|
'-r' add crossreference list to labellist output
|
||||||
|
(i.e list of filename/line where label is used)
|
||||||
|
'-M' allow ':' to appear in comments after a semicolon (MASM mode)
|
||||||
|
'-b? adr' set segment start address for ? = t(ext), d(ata), b(ss) or
|
||||||
|
z(ero) segment.
|
||||||
|
'-A adr' If the _file_ starts at adr in a ROM, then the text segment
|
||||||
|
need not be relocated. That of course only works, if the
|
||||||
|
data/bss/zero segments are not occupied by other programs too!
|
||||||
|
'-G' omit writing the exported globals to the file.
|
||||||
|
'-B' Show lines with '.(' or '.)' pseudo opcodes
|
||||||
|
'-Llabel' defines 'label' as absolute, undefined reference
|
||||||
|
'-DDEF=TEXT' define a preprocessor replacement
|
||||||
|
'-Ipath' additional include path for include files. Is evaluated before
|
||||||
|
the XAINPUT environment variable. One path per '-I',
|
||||||
|
multiple '-Ipath' allowed.
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
Omitting the errorfile or labelfile Parameter will cause xa to not
|
||||||
|
write these files. Using '-x' will cause xa to take the name of the
|
||||||
|
first source file and change the extension (on an Atari there is only
|
||||||
|
one, like in DOS) to 'obj', 'err' and 'lab' respectively - if the old
|
||||||
|
behaviour is selected with the '-x' option or the files are defined with
|
||||||
|
"-l" and "-e". If no output file is given, "a.o65" is used.
|
||||||
|
<p>
|
||||||
|
<h4> Environment variables: </h4>
|
||||||
|
You can use the variables XAOUTPUT and XAINPUT to adjust the directory
|
||||||
|
structure. If source or include files are not found, the Path in XAINPUT
|
||||||
|
is being searched for the files. The different paths are separated by a
|
||||||
|
comma (','). XAINPUT gives the directory where the *.obj, *.err and
|
||||||
|
*.lab files are put.
|
||||||
|
If they are not set, there will be no search, respectively the files
|
||||||
|
are saved to the current directory.
|
||||||
|
<p>
|
||||||
|
The label file is a readable ASCII-file and lists all the labels
|
||||||
|
together with their block-count (see below) and their address.
|
||||||
|
The error file lists the version of the assembler, date and time of the
|
||||||
|
assembler run, all the error messages and the stuff being printed
|
||||||
|
with #echo and #print and last but not least a statistics of used
|
||||||
|
resources.
|
||||||
|
|
||||||
|
<h3> 6502 Assembler </h3>
|
||||||
|
|
||||||
|
xa supports both the standard 6502 opcodes as well as the CMOS versions
|
||||||
|
(Rockwell 65c02). Not supported are the 6502 undocumented opcodes, they have
|
||||||
|
to be put in by hand (with ".byte" directives).
|
||||||
|
<p>
|
||||||
|
For an introduction to 6502 Assembler please see elsewhere. A (very) short
|
||||||
|
introduction is given in the german version of this text.
|
||||||
|
<p>
|
||||||
|
|
||||||
|
<h4>Some Assembler specific details:</h4>
|
||||||
|
|
||||||
|
When using addressing modes that could be zeropage or absolute, zeropage
|
||||||
|
will be taken if possible. This can be prevented by prefixing the address
|
||||||
|
with a '!'. Then absolute addressing is taken, regardless of the address.
|
||||||
|
<p>
|
||||||
|
Values or Addresses can be expressed by arithmetik expressions with
|
||||||
|
hierachy and bracket. The following operands are understood:
|
||||||
|
<p><pre>
|
||||||
|
123 -decimal
|
||||||
|
$234 -hexadecimal
|
||||||
|
&123 -octal
|
||||||
|
%010110 -binary
|
||||||
|
* -program counter
|
||||||
|
"A" -ASCII-code
|
||||||
|
labelx -label
|
||||||
|
-(lab1+1) -expression
|
||||||
|
</pre>
|
||||||
|
The following operands can be used (third column is priority):
|
||||||
|
<p><pre>
|
||||||
|
+ -addition 9
|
||||||
|
- -subtraction 9
|
||||||
|
* -multiplication 10
|
||||||
|
/ -integer-division 10
|
||||||
|
<< -shift left 8
|
||||||
|
>> -shift right 8
|
||||||
|
>=,=> -more or equal 7
|
||||||
|
<=,=< -less or equal 7
|
||||||
|
< -less 7
|
||||||
|
> -more 7
|
||||||
|
= -equal 6
|
||||||
|
<>,>< -not equal 6
|
||||||
|
&& -logical AND 2
|
||||||
|
|| -Logical OR 1
|
||||||
|
& -Bitwise AND 5
|
||||||
|
| -Bitwise OR 3
|
||||||
|
^ -Bitwise XOR 4
|
||||||
|
</pre>
|
||||||
|
Operators with higher priority are evaluated first.
|
||||||
|
Brackets can be used as usual.
|
||||||
|
<p>
|
||||||
|
Valid expressions are, e.g.:
|
||||||
|
<p><pre>
|
||||||
|
LDA base+number*2,x
|
||||||
|
</pre>
|
||||||
|
For Addressing modes that do not start with a bracket, you can even use
|
||||||
|
a bracket at the beginning of an expression. Otherwise try this:
|
||||||
|
<p><pre>
|
||||||
|
LDX (1+2)*2,y ; Wrong!
|
||||||
|
LDX 2*(1+2),y ; Right!
|
||||||
|
</pre>
|
||||||
|
Before an expression you can use these unitary operators:
|
||||||
|
<p><pre>
|
||||||
|
< Gives the low byte of the expression
|
||||||
|
> Gives the high byte
|
||||||
|
|
||||||
|
LDA #<adresse
|
||||||
|
</pre>
|
||||||
|
Single Assembler statements are being separated by a ':' (You remember
|
||||||
|
the C64 :-) or a newline. Behind Each statement, separated by a ';'
|
||||||
|
you can write some comments. The next colon or a newline ends the
|
||||||
|
comment and starts a new statement.
|
||||||
|
In MASM compatibility mode ('-M' command line option), then a colon
|
||||||
|
in a comment is ignored, i.e. the comment lasts till the newline.
|
||||||
|
<p>
|
||||||
|
<h3> Pseudo opcodes, Block structures and where Labels are valid </h3>
|
||||||
|
|
||||||
|
In addition to the 6502 opcodes you have the following Pseudo opcodes:
|
||||||
|
<p><pre>
|
||||||
|
.byt value1,value2,value3, ...
|
||||||
|
.word value1,value2, ...
|
||||||
|
.asc "text1","text2", ...
|
||||||
|
.dsb length ,fillbte
|
||||||
|
.fopt value1, value2, ...
|
||||||
|
.text
|
||||||
|
.data
|
||||||
|
.bss
|
||||||
|
.zero
|
||||||
|
.align value
|
||||||
|
*=
|
||||||
|
.(
|
||||||
|
.)
|
||||||
|
|
||||||
|
</pre>
|
||||||
|
'.byt' and '.asc' are identical and save values to the memory (object file)
|
||||||
|
bytewise. '.word' does the same with words (2 Bytes).
|
||||||
|
'.dsb' fills a block with a given length with the value of fillbyte.
|
||||||
|
If fillbyte is not given, zero is taken.
|
||||||
|
<p>
|
||||||
|
'*=' changes the programm counter. The programm counter is not saved
|
||||||
|
to the file as no rewind is being done. Just the internal counter
|
||||||
|
is reloaded.
|
||||||
|
If a value is given when the assembler has been started in relocation mode
|
||||||
|
('-R command line option), the assembler goes into no-relocation mode, i.e
|
||||||
|
assembles everything without creating relocation table entries.
|
||||||
|
For '*=' without a value, the assembler switches back to relocation mode.
|
||||||
|
The absolute code is 'embedded' in the text segment, so the text segment
|
||||||
|
program counter is increased by the length of the absolute code.
|
||||||
|
<p>
|
||||||
|
'.(' opens a new 'block'. All labels in a block are local, i.e.
|
||||||
|
are only visible from inside the block - including sub-blocks.
|
||||||
|
An error is returned if a label is defined that is already defined
|
||||||
|
'above'.
|
||||||
|
With '.)' the block is closed. You can have a stack of up to 16 blocks
|
||||||
|
in each other (i.e. 16 times '.(' before the first '.)' will work, 17 not).
|
||||||
|
<p>
|
||||||
|
'.text', '.data', '.bss', '.zero' switch between the different segments.
|
||||||
|
The text segment is where the code goes in. The data segment is where
|
||||||
|
some initialized data goes in (it's actually like a second text segment).
|
||||||
|
The data segment might be allocated separated from the text segment.
|
||||||
|
The contents of the bss and the zero segment are not saved, just the
|
||||||
|
labels are evaluated. Here goes the uninitialized data stuff.
|
||||||
|
The zero segment allows allocation of zeropage space, bss is normal address
|
||||||
|
space.
|
||||||
|
These opcodes can be used in relative and absolute mode.
|
||||||
|
<p>
|
||||||
|
'.align' aligns the current segment to a byte boundary given by the
|
||||||
|
value. Allowed values are 2, 4, and 256. When using relative mode, the
|
||||||
|
align value is written to the file header, such that relocation keeps
|
||||||
|
the alignment.
|
||||||
|
<p>
|
||||||
|
'.fopt' works like ".byte", but saves the bytes as a fileoption (see
|
||||||
|
fileformat.txt). The length is computed automatically, so the first
|
||||||
|
byte in the ".fopt" list of values should be the type.
|
||||||
|
For example, the following line sets the filename for the object file.
|
||||||
|
<p><pre>
|
||||||
|
.fopt 0, "filename", 0
|
||||||
|
</pre>
|
||||||
|
A label is defined by not being an opcode:
|
||||||
|
<p><pre>
|
||||||
|
label1 LDA #0 ; assignes the programm counter
|
||||||
|
label2 =1234 ; explicit definition
|
||||||
|
label3 label4 label5 ; implicit programm counter
|
||||||
|
label6 label7 = 3 ; label6 becomes the program counter, while
|
||||||
|
; label7 is set to 3
|
||||||
|
label8: sta label2 ; As ':' divides opcodes, this is also
|
||||||
|
; working
|
||||||
|
</pre>
|
||||||
|
You can use more than one label for definition, except for explicit
|
||||||
|
definition.
|
||||||
|
Labels are case sensitive.
|
||||||
|
If a label is proceeded by a '+', this label is defined global.
|
||||||
|
If a label is proceeded by a '&', this label is defined one level 'up'
|
||||||
|
in the block hierachy, and you can use more than one '&'.
|
||||||
|
<p>
|
||||||
|
Redefinition of a label is possible by proceeding it with a dash '-'.
|
||||||
|
<p><pre>
|
||||||
|
-sysmem +=4 ; here you can use ==, +=, -=, *=, /=, &=, |=
|
||||||
|
-syszp =123
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h3> Preprocessor </h3>
|
||||||
|
|
||||||
|
The preprocessor is very close to the one of the language C.
|
||||||
|
So in addition to the ';'-comments you can also use C-like
|
||||||
|
comments in '/*' and '*/'. Comments can be nested.
|
||||||
|
<p><pre>
|
||||||
|
#include "filename" includes a file on exactly this position.
|
||||||
|
if the file is not found, it is searched using
|
||||||
|
XAINPUT.
|
||||||
|
|
||||||
|
#echo comment gives a comment to the error file.
|
||||||
|
|
||||||
|
#print expression prints an expression to the error file (after
|
||||||
|
preprocessing and calculating)
|
||||||
|
|
||||||
|
#printdef DEFINED prints the definition of a preprocessor define to
|
||||||
|
the error file.
|
||||||
|
|
||||||
|
#define DEF text defines 'DEF' by 'text'
|
||||||
|
|
||||||
|
#ifdef DEF The source code from here to the following #endif
|
||||||
|
or #else is only assembled if 'DEF' is defined
|
||||||
|
with #define.
|
||||||
|
|
||||||
|
#else just else... (optionally)
|
||||||
|
|
||||||
|
#endif ends an #if-construct. This is a must to end #IF*
|
||||||
|
|
||||||
|
#ifndef DEF .... if DEF is not defined
|
||||||
|
|
||||||
|
#if expression .... if expression is not zero
|
||||||
|
|
||||||
|
#iflused label .... if a label has already been used
|
||||||
|
|
||||||
|
#ifldef label .... if a label is already defined
|
||||||
|
</pre>
|
||||||
|
#iflused and #ifldef work an labels, not on preprocessor defs! With these
|
||||||
|
commands a kind of library is easily built:
|
||||||
|
<p><pre>
|
||||||
|
#iflused label
|
||||||
|
#ifldef label
|
||||||
|
#echo label already defined, not from library
|
||||||
|
#else
|
||||||
|
label lda #0
|
||||||
|
....
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
</pre>
|
||||||
|
You can have up to 15 #if* on stack before the first #endif
|
||||||
|
<p>
|
||||||
|
You can also use #define with functions, like in C.
|
||||||
|
<p><pre>
|
||||||
|
#define mult(a,b) ((a)*(b))
|
||||||
|
</pre>
|
||||||
|
The preprocessor also allows continuation lines. I.e. lines that end
|
||||||
|
with a '\' directly before the newline have the following line
|
||||||
|
concatenated to it.
|
||||||
|
<p>
|
||||||
|
<h3> Utilities </h3>
|
||||||
|
|
||||||
|
There now are a few utilities that come with the assembler:
|
||||||
|
<p><pre>
|
||||||
|
file65 : prints some information about an o65 file. Can compute the
|
||||||
|
"-A" parameter for xa, to built the following file in a ROM.
|
||||||
|
reloc65 : relocates o65 files.
|
||||||
|
mkrom.sh: example shell (bash) script to show how to use the file65 utility
|
||||||
|
to build a ROM image with several in the ROM runnable programs.
|
||||||
|
ld65 : a linker for o65 files. The given files are linked together and
|
||||||
|
one o65 executable file is produced. All header options of all files
|
||||||
|
are put in the new file. There must not be any undefined reference
|
||||||
|
left, otherwise the output file is corrupt, because
|
||||||
|
for now, ld65 cannot produce object files. But you get a warning.
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
<h3> Literature </h3>
|
||||||
|
<ul>
|
||||||
|
<li> "Das Maschinensprachebuch zum Commodore 64" <br>
|
||||||
|
Lothar Englisch, Data Becker GmbH
|
||||||
|
<li> "Controller Products Data Book" <br>
|
||||||
|
Rockwell International, Semiconductor Products Division
|
||||||
|
<li> "Programmieren in C" <br>
|
||||||
|
Kernighan, Ritchie, Hanser Verlag
|
||||||
|
</ul>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
254
xa-2.3.5/doc/xa.log
Normal file
254
xa-2.3.5/doc/xa.log
Normal file
|
|
@ -0,0 +1,254 @@
|
||||||
|
xa-2.1.0
|
||||||
|
|
||||||
|
* Rewrite of command line option handling to better look like
|
||||||
|
usual (cc) options.
|
||||||
|
* Removed ^M from all files.
|
||||||
|
* Removed all external declarations to header files,
|
||||||
|
and made all static functions static.
|
||||||
|
| Now compiles almost without warning with 'gcc -W -Wall'.
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 31 Oct, 1996
|
||||||
|
|
||||||
|
xa-2.1.0a
|
||||||
|
|
||||||
|
* Introduced concept of code relocation. Now each label being set to
|
||||||
|
the program counter is a 'pointer', that gets an entry in a
|
||||||
|
relocation table. Simple arithmetic operations are allowed. The
|
||||||
|
relocation table is still just printed unsortedly.
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 31 Oct, 1996
|
||||||
|
|
||||||
|
xa-2.1.0b
|
||||||
|
|
||||||
|
* Produces some preliminary kind of relocatable file, including header
|
||||||
|
etc. Problems -- relocation table does as if file is assembled for
|
||||||
|
address 0. Need
|
||||||
|
a) a better way to set program counter.
|
||||||
|
b) pseudo opcodes for distinguishing segments.
|
||||||
|
c) a way to temporarily disable relocation.
|
||||||
|
d) a way to include extra headers and options into the file.
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 31 Oct, 1996
|
||||||
|
|
||||||
|
* Assembler now produces a relocatable file format, as described in
|
||||||
|
the file ``fileformat.txt''. Temporarily disabling relocation is with
|
||||||
|
the ``*=value'' directive, while switching back to relocation mode
|
||||||
|
goes with ``*='' (without value). New pseudo opcodes ``.text'',
|
||||||
|
``.data'', ``.bss'', ``.zero'' switch between the segments.
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 02 Nov, 1996
|
||||||
|
|
||||||
|
xa-2.1.0e
|
||||||
|
|
||||||
|
* There was a bug in the arithmetic routine that had set all pointer
|
||||||
|
to the text segment, if something was added.
|
||||||
|
* There also was a bug in the loader when actually using options.
|
||||||
|
* A new pseudo opcode was added -- ``.fopt''.
|
||||||
|
| Works like ``.byte'', but puts these bytes in a file option.
|
||||||
|
| The length in the file option is automagically set. ``.fopt''
|
||||||
|
| may appear anywhere in the file, but it should be at the
|
||||||
|
| beginning | (might be mandatory in a later version).
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 06 Nov, 1996
|
||||||
|
|
||||||
|
xa-2.1.0f
|
||||||
|
|
||||||
|
* Added a command line switch ``-M'' to ignore colons in a comment
|
||||||
|
after a semicolon.
|
||||||
|
* Without it, a colon separates complete mnemonics, including
|
||||||
|
the semicolon comment.
|
||||||
|
| Well, actually this switch is a ``MASM'' compatibility switch, and
|
||||||
|
will surely be expanded someday, when I get more info on MASM.
|
||||||
|
* Now ``*'' and ``='' can be separated for the definition
|
||||||
|
of the program counter and ``.byte'' is also accepted.
|
||||||
|
This makes it more MASM compatible. ".end" is ignored.
|
||||||
|
Still missing is ``.include''.
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 11 Nov, 1996
|
||||||
|
|
||||||
|
xa-2.1.0g
|
||||||
|
|
||||||
|
* Started working on ``official'' o65 fileformat.
|
||||||
|
If there are no undefined labels, and no relocated code
|
||||||
|
is embedded in absolute code, the thing should work.
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 21 Dec, 1996
|
||||||
|
|
||||||
|
xa-2.1.1
|
||||||
|
|
||||||
|
* ``.dsb'' now has an _optional_ parameter ``fillbyte''.
|
||||||
|
* Undefined references are now put into the relocation table
|
||||||
|
(i.e. handled correctly) if the ``-c'' option is given.
|
||||||
|
* The file format conforms to o65 version 1 file format.
|
||||||
|
* Embedding absolute in relocatable code and vice versa is buggy...
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 21 Dec, 1996
|
||||||
|
|
||||||
|
xa-2.1.1a
|
||||||
|
|
||||||
|
* Embedding absolute code in relocatable seems to work now.
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 21 Dec, 1996
|
||||||
|
|
||||||
|
xa-2.1.1e
|
||||||
|
|
||||||
|
* The option to embed relocatable code in absolute code has been
|
||||||
|
dropped. Therefore the command line options
|
||||||
|
``-A'' (make it romable), ``-b?'' (set segment start addresses),
|
||||||
|
and ``-G'' (omit exported globals from file) have been added.
|
||||||
|
* Internally, the whole thing has been made dynamic; except for the
|
||||||
|
preprocessor (and the storage between pass1 and pass2), everything
|
||||||
|
uses dynamically allocated tables. m_alloc, which had been
|
||||||
|
introduced long time ago because of the buggy malloc
|
||||||
|
on the Atari ST is gone now!
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 22 Dec, 1996
|
||||||
|
|
||||||
|
xa-2.1.1f
|
||||||
|
|
||||||
|
* Added the ``-a'' and ``-A'' options to file65, so that it can now
|
||||||
|
print the start addresses for following files in the ROM when making
|
||||||
|
romable code.
|
||||||
|
* Added shell (bash) script ``mkrom.sh'' that assembles a given list
|
||||||
|
of files and builds a ROMable file. The first two bytes are single
|
||||||
|
linked list pointers, and then comes the file.
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 02 Jan, 1997
|
||||||
|
|
||||||
|
xa-2.1.1g
|
||||||
|
|
||||||
|
* Added the file ``reloc65'', to relocate o65 files without
|
||||||
|
reassembling them.
|
||||||
|
* Fixed quite some bugs in xa (segment numbering in the globals list
|
||||||
|
and switched low/high byte relocation entry type in relocation
|
||||||
|
table. Now conforms to documentation, i.e. fileformat.txt)
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 03 Jan, 1997
|
||||||
|
|
||||||
|
xa-2.1.2
|
||||||
|
|
||||||
|
* Added ``ld65'', a simple linker for o65 files.
|
||||||
|
* Another bug in xa fixed now.
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 04 Jan, 1997
|
||||||
|
|
||||||
|
xa-2.1.3
|
||||||
|
|
||||||
|
* Allows to use ``.data'' etc in absolute mode, too. No relocation
|
||||||
|
entries are generated then. Segment start can be set with ``-b?''
|
||||||
|
command line options, though. Also the data segment is discarded
|
||||||
|
with this method! This allows to use the normal ``.data'' etc
|
||||||
|
syntax even when assembling a ROM (which is done in absolute mode.)
|
||||||
|
* Fixed a bug where ``.dsb'' in a data segment didn't fill with the
|
||||||
|
right value
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 25 Mar, 1997
|
||||||
|
|
||||||
|
xa-2.1.3e
|
||||||
|
|
||||||
|
* Added preprocessor continuation lines, and .block and .bend
|
||||||
|
pseudo-opcodes (They map to ``.('' and ``.)'' respectively.)
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 27 Jul, 1997
|
||||||
|
|
||||||
|
xa-2.1.4
|
||||||
|
|
||||||
|
* Do not leave output file around after an error -- this is
|
||||||
|
better for ``make''.
|
||||||
|
* Also it seems to have settled for a while, so I can release
|
||||||
|
a new version.
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 11 Sep, 1997
|
||||||
|
|
||||||
|
xa-2.1.4c
|
||||||
|
|
||||||
|
* Fixed a nasty bug that prevented correct relocation table
|
||||||
|
entries when a ``label2=label1'' contruct was used and
|
||||||
|
``label2'' was accessed.
|
||||||
|
* Added ``-I'' option.
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 30 Dec, 1997
|
||||||
|
|
||||||
|
xa-2.1.4d
|
||||||
|
|
||||||
|
* fixed align code. Now inserts NOP opcodes into text segment, and
|
||||||
|
sets file mode appropriately.
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 26 Jan, 1998
|
||||||
|
|
||||||
|
xa-2.1.4e
|
||||||
|
|
||||||
|
* Changed o65 fileformat and adopted it in xa.
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 26 Jan, 1998
|
||||||
|
|
||||||
|
xa-2.1.4g
|
||||||
|
|
||||||
|
* Fix handling of !zeropageaddress, that was broken (did not result
|
||||||
|
in absolute address, but gave error message.)
|
||||||
|
* Add cross reference list to labels if switched on on command line.
|
||||||
|
* Fix the filename when multiple files are given on the command line
|
||||||
|
(used to give the first filename for all errors in second pass.)
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 25 Nov, 1998
|
||||||
|
|
||||||
|
xa-2.1.4h
|
||||||
|
|
||||||
|
* In file65 added support for undefined labels and globals,
|
||||||
|
also for (some known) file options.
|
||||||
|
* Fix a preprocessor bug.
|
||||||
|
|
||||||
|
-- André Fachat <a.fachat@physik.tu-chemnitz.de> 12 Dec, 1998
|
||||||
|
|
||||||
|
xa-2.2.0-p1-1
|
||||||
|
|
||||||
|
* Update COPYING to the latest version (Y2K-fixed + new address to GNU)
|
||||||
|
* Lots of fixes to the Makefiles
|
||||||
|
* Cleaned up the structure of the TODO file
|
||||||
|
* Added manual-pages for file65, ld65, printcbm, reloc65, uncpk, and xa
|
||||||
|
* Commented out LIB-flags -lm, -lcurses and -ltermcap,
|
||||||
|
since they are all unused
|
||||||
|
* Added `--help' and `--version' to all binaries
|
||||||
|
* Removed `-h', `-?' and `-v' options where applicable
|
||||||
|
* Created a file containing the version-function; version.h
|
||||||
|
* Moved common macros to a separate file; xad.h
|
||||||
|
* Restructuring of printcbm to become more readable
|
||||||
|
* Added ifndef/define/endif traps to all header-files
|
||||||
|
* Fixed a few typos
|
||||||
|
* Renamed romadr to romaddr
|
||||||
|
* Renamed all functions matching *such* to *search*
|
||||||
|
* Fixed all warnings
|
||||||
|
* Cleaned up all header-files
|
||||||
|
* Reformatted xa.log
|
||||||
|
|
||||||
|
-- David Weinehall <tao@acc.umu.se> 20 Aug, 2002
|
||||||
|
|
||||||
|
xa-2.3.0
|
||||||
|
|
||||||
|
* Version number jump for all the unofficial xa's out there
|
||||||
|
* Fixed addressing bugs for @, ! and completed 65816 merge
|
||||||
|
Thanks to David for the report
|
||||||
|
* Moderate legibility overhaul to xat.c (will continue on this)
|
||||||
|
* More compiler warnings corrected
|
||||||
|
Thanks to David for the report
|
||||||
|
* man files completed
|
||||||
|
* Documentation updated
|
||||||
|
* Last line bug corrected (where last line not assembled if no newline)
|
||||||
|
Thanks to silverdr for the report
|
||||||
|
* ld65 is now ldo65 to avoid conflicts with cc65 package
|
||||||
|
* Post-defined labels work better, or at least somewhat (no longer attempts
|
||||||
|
to optimize in pass 2 and generate bad code). Can be forced with `
|
||||||
|
Thanks to silverdr for the report
|
||||||
|
* Makefile bugs multiplied
|
||||||
|
* @ now mostly obligatory for 24-bit addressing
|
||||||
|
|
||||||
|
-- Cameron Kaiser <ckaiser@floodgap.com> 2 Apr, 2006
|
||||||
|
|
||||||
|
xa-??
|
||||||
|
|
||||||
|
* Introduced switch to convert values in quotes to different character
|
||||||
|
sets. Currently supported are ASCII (default) and PETSCII
|
||||||
|
* Fixed some quote bugs
|
||||||
|
|
||||||
|
-- André Fachat <afachat@gmx.de> 23 Dec, 2006
|
||||||
|
|
||||||
358
xa-2.3.5/doc/xa.txt
Normal file
358
xa-2.3.5/doc/xa.txt
Normal file
|
|
@ -0,0 +1,358 @@
|
||||||
|
|
||||||
|
_________________________________________________________________
|
||||||
|
|
||||||
|
XA 2.1.4
|
||||||
|
|
||||||
|
65(c)02 Cross Assembler
|
||||||
|
|
||||||
|
(c) Andre Fachat
|
||||||
|
|
||||||
|
email: fachat@galileo.rhein-neckar.de
|
||||||
|
_________________________________________________________________
|
||||||
|
|
||||||
|
1. what it is
|
||||||
|
2. parameters and features
|
||||||
|
3. 6502 Assembler
|
||||||
|
4. pseudo-opcodes, block structures and where labels are valid
|
||||||
|
5. pre-processor
|
||||||
|
6. utilities
|
||||||
|
|
||||||
|
* literature
|
||||||
|
_________________________________________________________________
|
||||||
|
|
||||||
|
What it is
|
||||||
|
|
||||||
|
This Cross-Assembler makes programms for another computer that has a
|
||||||
|
6502-like CPU. This CPU has been widely used in the famous Apple II,
|
||||||
|
all the Commodore 8-Bit Computers (PET, VC20 and a derivate in the
|
||||||
|
C64) and many others. Some are still used in one-chip
|
||||||
|
microcontrollers, e.g. the Rockwell modem chipset. All these chip
|
||||||
|
share a common set of standard machine language commands, some of them
|
||||||
|
(e.g. the CMOS versions) have additional (software) features.
|
||||||
|
|
||||||
|
I had the idea for this assembler when I built my small 6502 System
|
||||||
|
that had place for 32kByte ROM to take the kernel and lots of other
|
||||||
|
programms. (After all, it became a multitasking micro-kernel with
|
||||||
|
file-systems for IBM and Commodore, I can even use the IBM drives as
|
||||||
|
Floppy for my C64 with this computer as controller. Piping and
|
||||||
|
i/o-redirection included, of course) Development on my old C64 began
|
||||||
|
to suck with programms growing. So I decided to do a Cross-Assembler
|
||||||
|
on my new Atari ST.
|
||||||
|
|
||||||
|
First versions were very like the old Assembler on the C64, not really
|
||||||
|
using the resources (Reading all files two times completely etc). With
|
||||||
|
files growing the assembler also became more sophisticated. Now
|
||||||
|
hashcodes are used for mnemonics, preprocessor definition and label
|
||||||
|
search (Version >= 2.0.5). The files are only read once, putting the
|
||||||
|
preassembled code into memory (Version >= 2.0), taking it from there
|
||||||
|
on pass 2. Now it makes about 350kByte Source Code to about 30kByte
|
||||||
|
ROM code in less then 2 Minutes on an 8 MHz Atari ST with 2.5 MByte
|
||||||
|
RAM and Harddisk. (Well, the Atari is not fast. On my 486DX4/100 it
|
||||||
|
takes about 2 seconds...) But adding the whole relocation stuff slowed
|
||||||
|
it down again.
|
||||||
|
|
||||||
|
Parameters and features
|
||||||
|
|
||||||
|
The assembler contains only a single programm called "xa" (for Atari:
|
||||||
|
XA.TTP). It takes one or more Source files into one object file, that
|
||||||
|
can directly be used. But the assembler also has a mode to produce
|
||||||
|
relocatable files, conforming to the 'o65' fileformat (See
|
||||||
|
fileformat.txt).
|
||||||
|
|
||||||
|
Call:
|
||||||
|
|
||||||
|
xa [options] Source1 [Source2 ...]
|
||||||
|
|
||||||
|
Object: this is the name, the output (object) file gets Error: Here
|
||||||
|
you will find the Error listing. Label: this is the label list
|
||||||
|
|
||||||
|
'-C' gives error codes when using CMOS-opcodes. Default is not to
|
||||||
|
complain.
|
||||||
|
'-c' do not produce o65 executable, but object files that can
|
||||||
|
contain undefined references.
|
||||||
|
'-v' go into verbose mode
|
||||||
|
'-x' old filename behaviour (overrides -o, -e and -l)
|
||||||
|
'-R' do not produce absolute code, but do relocation and all that.
|
||||||
|
'-o filename' set output filename
|
||||||
|
'-e filename' set errorlog filename
|
||||||
|
'-l filename' set labellist filename
|
||||||
|
'-r' add crossreference list to labellist output
|
||||||
|
(i.e list of filename/line where label is used)
|
||||||
|
'-M' allow ':' to appear in comments after a semicolon (MASM mode)
|
||||||
|
'-b? adr' set segment start address for ? = t(ext), d(ata), b(ss) or
|
||||||
|
z(ero) segment.
|
||||||
|
'-A adr' If the _file_ starts at adr in a ROM, then the text segment
|
||||||
|
need not be relocated. That of course only works, if the
|
||||||
|
data/bss/zero segments are not occupied by other programs too!
|
||||||
|
'-G' omit writing the exported globals to the file.
|
||||||
|
'-B' Show lines with '.(' or '.)' pseudo opcodes
|
||||||
|
'-Llabel' defines 'label' as absolute, undefined reference
|
||||||
|
'-DDEF=TEXT' define a preprocessor replacement
|
||||||
|
'-Ipath' additional include path for include files. Is evaluated before
|
||||||
|
the XAINPUT environment variable. One path per '-I',
|
||||||
|
multiple '-Ipath' allowed.
|
||||||
|
|
||||||
|
Omitting the errorfile or labelfile Parameter will cause xa to not
|
||||||
|
write these files. Using '-x' will cause xa to take the name of the
|
||||||
|
first source file and change the extension (on an Atari there is only
|
||||||
|
one, like in DOS) to 'obj', 'err' and 'lab' respectively - if the old
|
||||||
|
behaviour is selected with the '-x' option or the files are defined
|
||||||
|
with "-l" and "-e". If no output file is given, "a.o65" is used.
|
||||||
|
|
||||||
|
Environment variables:
|
||||||
|
|
||||||
|
You can use the variables XAOUTPUT and XAINPUT to adjust the directory
|
||||||
|
structure. If source or include files are not found, the Path in
|
||||||
|
XAINPUT is being searched for the files. The different paths are
|
||||||
|
separated by a comma (','). XAINPUT gives the directory where the
|
||||||
|
*.obj, *.err and *.lab files are put. If they are not set, there will
|
||||||
|
be no search, respectively the files are saved to the current
|
||||||
|
directory.
|
||||||
|
|
||||||
|
The label file is a readable ASCII-file and lists all the labels
|
||||||
|
together with their block-count (see below) and their address. The
|
||||||
|
error file lists the version of the assembler, date and time of the
|
||||||
|
assembler run, all the error messages and the stuff being printed with
|
||||||
|
#echo and #print and last but not least a statistics of used
|
||||||
|
resources.
|
||||||
|
|
||||||
|
6502 Assembler
|
||||||
|
|
||||||
|
xa supports both the standard 6502 opcodes as well as the CMOS
|
||||||
|
versions (Rockwell 65c02). Not supported are the 6502 undocumented
|
||||||
|
opcodes, they have to be put in by hand (with ".byte" directives).
|
||||||
|
|
||||||
|
For an introduction to 6502 Assembler please see elsewhere. A (very)
|
||||||
|
short introduction is given in the german version of this text.
|
||||||
|
|
||||||
|
Some Assembler specific details:
|
||||||
|
|
||||||
|
When using addressing modes that could be zeropage or absolute,
|
||||||
|
zeropage will be taken if possible. This can be prevented by prefixing
|
||||||
|
the address with a '!'. Then absolute addressing is taken, regardless
|
||||||
|
of the address.
|
||||||
|
|
||||||
|
Values or Addresses can be expressed by arithmetik expressions with
|
||||||
|
hierachy and bracket. The following operands are understood:
|
||||||
|
|
||||||
|
123 -decimal
|
||||||
|
$234 -hexadecimal
|
||||||
|
&123 -octal
|
||||||
|
%010110 -binary
|
||||||
|
* -program counter
|
||||||
|
"A" -ASCII-code
|
||||||
|
labelx -label
|
||||||
|
-(lab1+1) -expression
|
||||||
|
|
||||||
|
The following operands can be used (third column is priority):
|
||||||
|
|
||||||
|
+ -addition 9
|
||||||
|
- -subtraction 9
|
||||||
|
* -multiplication 10
|
||||||
|
/ -integer-division 10
|
||||||
|
<< -shift left 8
|
||||||
|
>> -shift right 8
|
||||||
|
>=,=> -more or equal 7
|
||||||
|
<=,=< -less or equal 7
|
||||||
|
< -less 7
|
||||||
|
> -more 7
|
||||||
|
= -equal 6
|
||||||
|
<>,>< -not equal 6
|
||||||
|
&& -logical AND 2
|
||||||
|
|| -Logical OR 1
|
||||||
|
& -Bitwise AND 5
|
||||||
|
| -Bitwise OR 3
|
||||||
|
^ -Bitwise XOR 4
|
||||||
|
|
||||||
|
Operators with higher priority are evaluated first. Brackets can be
|
||||||
|
used as usual.
|
||||||
|
|
||||||
|
Valid expressions are, e.g.:
|
||||||
|
|
||||||
|
LDA base+number*2,x
|
||||||
|
|
||||||
|
For Addressing modes that do not start with a bracket, you can even
|
||||||
|
use a bracket at the beginning of an expression. Otherwise try this:
|
||||||
|
|
||||||
|
LDX (1+2)*2,y ; Wrong!
|
||||||
|
LDX 2*(1+2),y ; Right!
|
||||||
|
|
||||||
|
Before an expression you can use these unitary operators:
|
||||||
|
|
||||||
|
|
||||||
|
< Gives the low byte of the expression
|
||||||
|
> Gives the high byte
|
||||||
|
|
||||||
|
LDA #<adresse
|
||||||
|
|
||||||
|
Single Assembler statements are being separated by a ':' (You remember
|
||||||
|
the C64 :-) or a newline. Behind Each statement, separated by a ';'
|
||||||
|
you can write some comments. The next colon or a newline ends the
|
||||||
|
comment and starts a new statement. In MASM compatibility mode ('-M'
|
||||||
|
command line option), then a colon in a comment is ignored, i.e. the
|
||||||
|
comment lasts till the newline.
|
||||||
|
|
||||||
|
Pseudo opcodes, Block structures and where Labels are valid
|
||||||
|
|
||||||
|
In addition to the 6502 opcodes you have the following Pseudo opcodes:
|
||||||
|
|
||||||
|
.byt value1,value2,value3, ...
|
||||||
|
.word value1,value2, ...
|
||||||
|
.asc "text1","text2", ...
|
||||||
|
.dsb length ,fillbte
|
||||||
|
.fopt value1, value2, ...
|
||||||
|
.text
|
||||||
|
.data
|
||||||
|
.bss
|
||||||
|
.zero
|
||||||
|
.align value
|
||||||
|
*=
|
||||||
|
.(
|
||||||
|
.)
|
||||||
|
|
||||||
|
'.byt' and '.asc' are identical and save values to the memory (object
|
||||||
|
file) bytewise. '.word' does the same with words (2 Bytes). '.dsb'
|
||||||
|
fills a block with a given length with the value of fillbyte. If
|
||||||
|
fillbyte is not given, zero is taken.
|
||||||
|
|
||||||
|
'*=' changes the programm counter. The programm counter is not saved
|
||||||
|
to the file as no rewind is being done. Just the internal counter is
|
||||||
|
reloaded. If a value is given when the assembler has been started in
|
||||||
|
relocation mode ('-R command line option), the assembler goes into
|
||||||
|
no-relocation mode, i.e assembles everything without creating
|
||||||
|
relocation table entries. For '*=' without a value, the assembler
|
||||||
|
switches back to relocation mode. The absolute code is 'embedded' in
|
||||||
|
the text segment, so the text segment program counter is increased by
|
||||||
|
the length of the absolute code.
|
||||||
|
|
||||||
|
'.(' opens a new 'block'. All labels in a block are local, i.e. are
|
||||||
|
only visible from inside the block - including sub-blocks. An error is
|
||||||
|
returned if a label is defined that is already defined 'above'. With
|
||||||
|
'.)' the block is closed. You can have a stack of up to 16 blocks in
|
||||||
|
each other (i.e. 16 times '.(' before the first '.)' will work, 17
|
||||||
|
not).
|
||||||
|
|
||||||
|
'.text', '.data', '.bss', '.zero' switch between the different
|
||||||
|
segments. The text segment is where the code goes in. The data segment
|
||||||
|
is where some initialized data goes in (it's actually like a second
|
||||||
|
text segment). The data segment might be allocated separated from the
|
||||||
|
text segment. The contents of the bss and the zero segment are not
|
||||||
|
saved, just the labels are evaluated. Here goes the uninitialized data
|
||||||
|
stuff. The zero segment allows allocation of zeropage space, bss is
|
||||||
|
normal address space. These opcodes can be used in relative and
|
||||||
|
absolute mode.
|
||||||
|
|
||||||
|
'.align' aligns the current segment to a byte boundary given by the
|
||||||
|
value. Allowed values are 2, 4, and 256. When using relative mode, the
|
||||||
|
align value is written to the file header, such that relocation keeps
|
||||||
|
the alignment.
|
||||||
|
|
||||||
|
'.fopt' works like ".byte", but saves the bytes as a fileoption (see
|
||||||
|
fileformat.txt). The length is computed automatically, so the first
|
||||||
|
byte in the ".fopt" list of values should be the type. For example,
|
||||||
|
the following line sets the filename for the object file.
|
||||||
|
|
||||||
|
.fopt 0, "filename", 0
|
||||||
|
|
||||||
|
A label is defined by not being an opcode:
|
||||||
|
|
||||||
|
label1 LDA #0 ; assignes the programm counter
|
||||||
|
label2 =1234 ; explicit definition
|
||||||
|
label3 label4 label5 ; implicit programm counter
|
||||||
|
label6 label7 = 3 ; label6 becomes the program counter, while
|
||||||
|
; label7 is set to 3
|
||||||
|
label8: sta label2 ; As ':' divides opcodes, this is also
|
||||||
|
; working
|
||||||
|
|
||||||
|
You can use more than one label for definition, except for explicit
|
||||||
|
definition. Labels are case sensitive. If a label is proceeded by a
|
||||||
|
'+', this label is defined global. If a label is proceeded by a '&',
|
||||||
|
this label is defined one level 'up' in the block hierachy, and you
|
||||||
|
can use more than one '&'.
|
||||||
|
|
||||||
|
Redefinition of a label is possible by proceeding it with a dash '-'.
|
||||||
|
|
||||||
|
-sysmem +=4 ; here you can use ==, +=, -=, *=, /=, &=, |=
|
||||||
|
-syszp =123
|
||||||
|
|
||||||
|
Preprocessor
|
||||||
|
|
||||||
|
The preprocessor is very close to the one of the language C. So in
|
||||||
|
addition to the ';'-comments you can also use C-like comments in '/*'
|
||||||
|
and '*/'. Comments can be nested.
|
||||||
|
|
||||||
|
#include "filename" includes a file on exactly this position.
|
||||||
|
if the file is not found, it is searched using
|
||||||
|
XAINPUT.
|
||||||
|
|
||||||
|
#echo comment gives a comment to the error file.
|
||||||
|
|
||||||
|
#print expression prints an expression to the error file (after
|
||||||
|
preprocessing and calculating)
|
||||||
|
|
||||||
|
#printdef DEFINED prints the definition of a preprocessor define to
|
||||||
|
the error file.
|
||||||
|
|
||||||
|
#define DEF text defines 'DEF' by 'text'
|
||||||
|
|
||||||
|
#ifdef DEF The source code from here to the following #endif
|
||||||
|
or #else is only assembled if 'DEF' is defined
|
||||||
|
with #define.
|
||||||
|
|
||||||
|
#else just else... (optionally)
|
||||||
|
|
||||||
|
#endif ends an #if-construct. This is a must to end #IF*
|
||||||
|
|
||||||
|
#ifndef DEF .... if DEF is not defined
|
||||||
|
|
||||||
|
#if expression .... if expression is not zero
|
||||||
|
|
||||||
|
#iflused label .... if a label has already been used
|
||||||
|
|
||||||
|
#ifldef label .... if a label is already defined
|
||||||
|
|
||||||
|
#iflused and #ifldef work an labels, not on preprocessor defs! With
|
||||||
|
these commands a kind of library is easily built:
|
||||||
|
|
||||||
|
#iflused label
|
||||||
|
#ifldef label
|
||||||
|
#echo label already defined, not from library
|
||||||
|
#else
|
||||||
|
label lda #0
|
||||||
|
....
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
You can have up to 15 #if* on stack before the first #endif
|
||||||
|
|
||||||
|
You can also use #define with functions, like in C.
|
||||||
|
|
||||||
|
#define mult(a,b) ((a)*(b))
|
||||||
|
|
||||||
|
The preprocessor also allows continuation lines. I.e. lines that end
|
||||||
|
with a '\' directly before the newline have the following line
|
||||||
|
concatenated to it.
|
||||||
|
|
||||||
|
Utilities
|
||||||
|
|
||||||
|
There now are a few utilities that come with the assembler:
|
||||||
|
|
||||||
|
file65 : prints some information about an o65 file. Can compute the
|
||||||
|
"-A" parameter for xa, to built the following file in a ROM.
|
||||||
|
reloc65 : relocates o65 files.
|
||||||
|
mkrom.sh: example shell (bash) script to show how to use the file65 utility
|
||||||
|
to build a ROM image with several in the ROM runnable programs.
|
||||||
|
ld65 : a linker for o65 files. The given files are linked together and
|
||||||
|
one o65 executable file is produced. All header options of all files
|
||||||
|
are put in the new file. There must not be any undefined reference
|
||||||
|
left, otherwise the output file is corrupt, because
|
||||||
|
for now, ld65 cannot produce object files. But you get a warning.
|
||||||
|
|
||||||
|
Literature
|
||||||
|
|
||||||
|
* "Das Maschinensprachebuch zum Commodore 64"
|
||||||
|
Lothar Englisch, Data Becker GmbH
|
||||||
|
* "Controller Products Data Book"
|
||||||
|
Rockwell International, Semiconductor Products Division
|
||||||
|
* "Programmieren in C"
|
||||||
|
Kernighan, Ritchie, Hanser Verlag
|
||||||
105
xa-2.3.5/doc/xaannounce
Normal file
105
xa-2.3.5/doc/xaannounce
Normal file
|
|
@ -0,0 +1,105 @@
|
||||||
|
Subject: [ANN] 6502 reloc. binaries & assembler
|
||||||
|
Newsgroups: comp.sys.cbm,comp.emulators.cbm,comp.sys.atari.8bit,comp.sys.apple2.programmer,comp.arch.embedded
|
||||||
|
Organization: TU Chemnitz
|
||||||
|
Summary: Announcement of 6502 relocatable binary format and assembler
|
||||||
|
Keywords: 6502, 65816, relocation, cross assembler, assembler, file format
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
relocatable binary file format o65
|
||||||
|
& 6502 cross assembler xa65
|
||||||
|
|
||||||
|
This is the announcement for the 6502 relocatable binary file format 'o65'.
|
||||||
|
|
||||||
|
This format allows to
|
||||||
|
|
||||||
|
- relocate (i.e. move to a different address) a file when loading it, to
|
||||||
|
be able to execute at a different address
|
||||||
|
|
||||||
|
- produce global label lists, i.e. being able to export labels from one
|
||||||
|
file to another
|
||||||
|
|
||||||
|
- have undefined references, i.e. allow late binding (resolving symbols
|
||||||
|
at load time)
|
||||||
|
|
||||||
|
- code sharing in virtual memory architectures
|
||||||
|
|
||||||
|
- do block oriented transfer and have minimum side storage when loading a file
|
||||||
|
|
||||||
|
The format works for the 6502 and for the 65816 CPU. It knows object from
|
||||||
|
executable files and more.
|
||||||
|
The file format itself is free (I can do the clearance, if you have
|
||||||
|
suggestions for extensions etc.)
|
||||||
|
Have a look at: http://www.tu-chemnitz.de/~fachat/c64/xa/fileformat.txt
|
||||||
|
|
||||||
|
About another 6502 file format, see note 1).
|
||||||
|
|
||||||
|
|
||||||
|
6502 cross assembler xa65
|
||||||
|
|
||||||
|
As reference assembler to produce this kind of code, I have implemented
|
||||||
|
the file format in my 6502 cross assembler "xa65".
|
||||||
|
From version 2.1.1 it supports the new file format standard, and from
|
||||||
|
version 2.1.2a, it comes with the "file65", "reloc65" and
|
||||||
|
"ld65" utilities to print information about a file, relocate a file
|
||||||
|
and link several object files together resp.
|
||||||
|
All the programs are close to production stage (you never know if you
|
||||||
|
got all bugs...), while the linker is in beta stage. Esp. I want to know
|
||||||
|
about options you would like to have.
|
||||||
|
|
||||||
|
The assembler is under GNU public license and can be found at:
|
||||||
|
http://www.tu-chemnitz.de/~fachat/c64/xa/index.html
|
||||||
|
|
||||||
|
Other changes from earlier versions:
|
||||||
|
|
||||||
|
- supports o65 file format, including linker, relocator and file utility.
|
||||||
|
|
||||||
|
- much better code quality (only two warnings with
|
||||||
|
gcc -W -Wall -pedantic -ansi)
|
||||||
|
|
||||||
|
- supports more MASM pseudo opcodes (but still not the important ones
|
||||||
|
that I have my C-like preprocessor for: .if, .macro, .include.
|
||||||
|
This might change someday...
|
||||||
|
|
||||||
|
- DOS support by go32 cross-compiling (only Makefile changes!)
|
||||||
|
|
||||||
|
General description:
|
||||||
|
|
||||||
|
- C-like Preprocessor to make macros
|
||||||
|
- label "hiding" on different levels,
|
||||||
|
i.e. multiple use of the same label possible
|
||||||
|
- 1.5-pass assembler:
|
||||||
|
Everything that can be derefenced is being assembled in pass 1 and
|
||||||
|
saved in memory. The second pass does the rest. This (together
|
||||||
|
with hashing etc) gives quite a good speed (30kByte binary out of
|
||||||
|
300kByte source in less than two minutes on an 8MHz Atari ST -
|
||||||
|
hey, the first versions would have taken half an hour for this
|
||||||
|
job! - my 486DX4/100 with linux needs around two seconds or so...)
|
||||||
|
- needs no linker - all stuff is in source code (with this speed,
|
||||||
|
it's ok)
|
||||||
|
- (optional) support for relocatable 'o65' file format,
|
||||||
|
including linker, relocator and file utility. A loader in 6502
|
||||||
|
assembly code is also included.
|
||||||
|
- reads DOS and Unix(tm) files (LF or CR+LF)
|
||||||
|
|
||||||
|
so long
|
||||||
|
André Fachat
|
||||||
|
|
||||||
|
----
|
||||||
|
1) There is already another relocatable object file format, called "OMF",
|
||||||
|
which is mostly used in the Apple community. I didn't take this format
|
||||||
|
for my projects for several reasons: It has some limits on filename
|
||||||
|
lengths; the relocation information is encoded between assembler code,
|
||||||
|
i.e. one cannot easily use block loading; it doesn't provide different
|
||||||
|
segments (as I can see) that have this meaning.
|
||||||
|
The OMF file format has never been published on the internet and mostly
|
||||||
|
commercial companies from the Apple world seem to support it - but then
|
||||||
|
they even have C compilers for this file format.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
André Fachat |"I do not feel obliged to believe that the
|
||||||
|
Institute of physics, | same God who has endowed us with sense,
|
||||||
|
Technische Universität Chemnitz | reason, and intellect has intended us to
|
||||||
|
http://www.tu-chemnitz.de/~fachat | forego their use" -- Galileo Galilei
|
||||||
BIN
xa-2.3.5/examples/a.o65
Normal file
BIN
xa-2.3.5/examples/a.o65
Normal file
Binary file not shown.
309
xa-2.3.5/examples/c64def.def
Normal file
309
xa-2.3.5/examples/c64def.def
Normal file
|
|
@ -0,0 +1,309 @@
|
||||||
|
|
||||||
|
|
||||||
|
/* VIC 6567 */
|
||||||
|
|
||||||
|
#define VIC_S0_X 0
|
||||||
|
#define VIC_S0_Y 1
|
||||||
|
#define VIC_S1_X 2
|
||||||
|
#define VIC_S1_Y 3
|
||||||
|
#define VIC_S2_X 4
|
||||||
|
#define VIC_S2_Y 5
|
||||||
|
#define VIC_S3_X 6
|
||||||
|
#define VIC_S3_Y 7
|
||||||
|
#define VIC_S4_X 8
|
||||||
|
#define VIC_S4_Y 9
|
||||||
|
#define VIC_S5_X 10
|
||||||
|
#define VIC_S5_Y 11
|
||||||
|
#define VIC_S6_X 12
|
||||||
|
#define VIC_S6_Y 13
|
||||||
|
#define VIC_S7_X 14
|
||||||
|
#define VIC_S7_Y 15
|
||||||
|
#define VIC_SP_MSB 16
|
||||||
|
#define VIC_SR1 17
|
||||||
|
#define VIC_IRQ_RASTER 18
|
||||||
|
#define VIC_LP_X 19
|
||||||
|
#define VIC_LP_Y 20
|
||||||
|
#define VIC_SP_EN 21
|
||||||
|
#define VIC_SR2 22
|
||||||
|
#define VIC_SP_EXPY 23
|
||||||
|
#define VIC_BASEADR 24
|
||||||
|
#define VIC_IRR 25
|
||||||
|
#define VIC_IMR 26
|
||||||
|
#define VIC_SP_PRIOR 27
|
||||||
|
#define VIC_SP_MCOLOR 28
|
||||||
|
#define VIC_SP_EXPX 29
|
||||||
|
#define VIC_SP_SCOLL 30
|
||||||
|
#define VIC_SP_BCOLL 31
|
||||||
|
#define VIC_EXTCOL 32
|
||||||
|
#define VIC_BCKCOL0 33
|
||||||
|
#define VIC_BCKCOL1 34
|
||||||
|
#define VIC_BCKCOL2 35
|
||||||
|
#define VIC_BCKCOL3 36
|
||||||
|
#define VIC_SP_MCOL0 37
|
||||||
|
#define VIC_SP_MCOL1 38
|
||||||
|
#define VIC_S0_COL 39
|
||||||
|
#define VIC_S1_COL 40
|
||||||
|
#define VIC_S2_COL 41
|
||||||
|
#define VIC_S3_COL 42
|
||||||
|
#define VIC_S4_COL 43
|
||||||
|
#define VIC_S5_COL 44
|
||||||
|
#define VIC_S6_COL 45
|
||||||
|
#define VIC_S7_COL 46
|
||||||
|
|
||||||
|
#define COL_SCHWARZ 0
|
||||||
|
#define COL_WEISS 1
|
||||||
|
#define COL_ROT 2
|
||||||
|
#define COL_TUERKIS 3
|
||||||
|
#define COL_VIOLETT 4
|
||||||
|
#define COL_GRUEN 5
|
||||||
|
#define COL_BLAU 6
|
||||||
|
#define COL_GELB 7
|
||||||
|
#define COL_ORANGE 8
|
||||||
|
#define COL_BRAUN 9
|
||||||
|
#define COL_HELLROT 10
|
||||||
|
#define COL_GRAU1 11
|
||||||
|
#define COL_GRAU2 12
|
||||||
|
#define COL_HELLGRUEN 13
|
||||||
|
#define COL_HELLBLAU 14
|
||||||
|
#define COL_GRAU3 15
|
||||||
|
|
||||||
|
#define VIC $d000
|
||||||
|
|
||||||
|
|
||||||
|
/* SID 6581 */
|
||||||
|
|
||||||
|
#define SID_0FREQL 0
|
||||||
|
#define SID_0FREQH 1
|
||||||
|
#define SID_0PULSL 2
|
||||||
|
#define SID_0PULSH 3
|
||||||
|
#define SID_0SR 4
|
||||||
|
#define SID_0ATTDEC 5
|
||||||
|
#define SID_0SUSREL 6
|
||||||
|
#define SID_1FREQL 7
|
||||||
|
#define SID_1FREQH 8
|
||||||
|
#define SID_1PULSL 9
|
||||||
|
#define SID_1PULSH 10
|
||||||
|
#define SID_1SR 11
|
||||||
|
#define SID_1ATTDEC 12
|
||||||
|
#define SID_1SUSREL 13
|
||||||
|
#define SID_2FREQL 14
|
||||||
|
#define SID_2FREQH 15
|
||||||
|
#define SID_2PULSL 16
|
||||||
|
#define SID_2PULSH 17
|
||||||
|
#define SID_2SR 18
|
||||||
|
#define SID_2ATTDEC 19
|
||||||
|
#define SID_2SUSREL 20
|
||||||
|
#define SID_FILTL 21
|
||||||
|
#define SID_FILTH 22
|
||||||
|
#define SID_SR1 23
|
||||||
|
#define SID_SR2 24
|
||||||
|
|
||||||
|
#define SID $d800
|
||||||
|
|
||||||
|
|
||||||
|
/* CIA 6526 */
|
||||||
|
|
||||||
|
#define CIA_DRA 0
|
||||||
|
#define CIA_DRB 1
|
||||||
|
#define CIA_DDRA 2
|
||||||
|
#define CIA_DDRB 3
|
||||||
|
#define CIA_TAL 4
|
||||||
|
#define CIA_TAH 5
|
||||||
|
#define CIA_TBL 6
|
||||||
|
#define CIA_TBH 7
|
||||||
|
#define CIA_TOD_THS 8
|
||||||
|
#define CIA_TOD_SEC 9
|
||||||
|
#define CIA_TOD_MIN 10
|
||||||
|
#define CIA_TOD_HR 11
|
||||||
|
#define CIA_SDR 12
|
||||||
|
#define CIA_ICR 13
|
||||||
|
#define CIA_CRA 14
|
||||||
|
#define CIA_CRB 15
|
||||||
|
|
||||||
|
#define CIA1 $dc00
|
||||||
|
#define CIA2 $dd00
|
||||||
|
|
||||||
|
|
||||||
|
/* ACIA 6551 */
|
||||||
|
|
||||||
|
#define ACIA_DR 0
|
||||||
|
#define ACIA_SR 1
|
||||||
|
#define ACIA_CMD 2
|
||||||
|
#define ACIA_CTRL 3
|
||||||
|
|
||||||
|
#define ACIA $d600
|
||||||
|
|
||||||
|
|
||||||
|
/* Basic */
|
||||||
|
|
||||||
|
#define INT $14
|
||||||
|
#define PRGANF $2b
|
||||||
|
#define VARANF $2d
|
||||||
|
#define ARRANF $2f
|
||||||
|
#define ARREND $31
|
||||||
|
#define STRANF $33
|
||||||
|
#define STRPTR $35
|
||||||
|
#define RAMEND $37
|
||||||
|
|
||||||
|
#define VARNAME $45
|
||||||
|
#define VARADR $47
|
||||||
|
|
||||||
|
#define AKKU3 $57
|
||||||
|
#define AKKU4 $5c
|
||||||
|
|
||||||
|
#define FAC $61
|
||||||
|
#define ARG $69
|
||||||
|
|
||||||
|
|
||||||
|
#define CHRGET $73
|
||||||
|
#define CHRGOT $79
|
||||||
|
#define PRGPTR $7a
|
||||||
|
|
||||||
|
#define V_ERR $0300
|
||||||
|
#define V_WARM $0302
|
||||||
|
#define V_CONV2CODE $0304
|
||||||
|
#define V_CONV2ASC $0306
|
||||||
|
#define V_GETBEFADR $0308
|
||||||
|
#define V_GETAUSDR $030a
|
||||||
|
|
||||||
|
#define SYS_AKKU $030c
|
||||||
|
#define SYS_XR $030d
|
||||||
|
#define SYS_YR $030e
|
||||||
|
#define SYS_SR $030f
|
||||||
|
|
||||||
|
#define READY $a474
|
||||||
|
#define LINEIN $a560
|
||||||
|
#define INTOUT $bdcd
|
||||||
|
|
||||||
|
/* Betriebssystem */
|
||||||
|
|
||||||
|
#define STATUS $90
|
||||||
|
|
||||||
|
#define FNAMLEN $b7
|
||||||
|
#define LOGFNR $b8
|
||||||
|
#define SECADR $b9
|
||||||
|
#define DEVADR $ba
|
||||||
|
#define FNAMPTR $bb
|
||||||
|
|
||||||
|
#define IOANF $c1
|
||||||
|
#define IOEND $c3
|
||||||
|
|
||||||
|
#define LASTKEY $c5
|
||||||
|
#define NUMKEY $c6
|
||||||
|
#define REVFL $c7
|
||||||
|
#define INLINEEND $c8
|
||||||
|
#define INZEILE $c9
|
||||||
|
#define INSPALTE $ca
|
||||||
|
#define PRESSEDKEY $cb
|
||||||
|
#define CRSRFLASH $cc
|
||||||
|
#define CRSRFLASHCNT $cd
|
||||||
|
#define CHARUNDERCRSR $ce
|
||||||
|
#define CRSRFLASHFL $cf
|
||||||
|
#define KEYINPUTFL $d0
|
||||||
|
#define LINEADR $d1
|
||||||
|
#define CRSRSPALTE $d3
|
||||||
|
#define HKFL $d4
|
||||||
|
#define LENGTHOFLINE $d5
|
||||||
|
#define CRSRZEILE $d6
|
||||||
|
#define DIV $d7
|
||||||
|
#define NUMOFINS $d8
|
||||||
|
|
||||||
|
#define RS232INBUFPTR $f7
|
||||||
|
#define RS232OUTBUFPTR $f9
|
||||||
|
|
||||||
|
#define P1 $fb /* freier Pointer */
|
||||||
|
#define P2 $fd /* freier Pointer */
|
||||||
|
|
||||||
|
#define INBUF $200
|
||||||
|
|
||||||
|
#define V_USR $0311
|
||||||
|
#define V_IRQ $0314
|
||||||
|
#define V_BRK $0316
|
||||||
|
#define V_NMI $0318
|
||||||
|
#define V_OPEN $031a
|
||||||
|
#define V_CLOSE $031c
|
||||||
|
#define V_CHKIN $031e
|
||||||
|
#define V_CKOUT $0320
|
||||||
|
#define V_CLRCH $0322
|
||||||
|
#define V_INPUT $0324
|
||||||
|
#define V_OUTPUT $0326
|
||||||
|
#define V_STOP $0328
|
||||||
|
#define V_GET $032a
|
||||||
|
#define V_CLALL $032c
|
||||||
|
#define V_WARMSTART $032e
|
||||||
|
#define V_LOAD $0330
|
||||||
|
#define V_SAVE $0332
|
||||||
|
|
||||||
|
#define SENDNAM $f3d5
|
||||||
|
#define CLSFIL $f642
|
||||||
|
|
||||||
|
#define INICIA $ff84
|
||||||
|
#define INIRAM $ff87
|
||||||
|
#define INIIO $ff8a
|
||||||
|
#define INIIOVEC $ff8d
|
||||||
|
#define SETST $ff90
|
||||||
|
#define SECLISTEN $ff93
|
||||||
|
#define SECTALK $ff96
|
||||||
|
#define RAMEND $ff99
|
||||||
|
#define RAMSTART $ff9c
|
||||||
|
#define GETKEY $ff9f
|
||||||
|
#define IECTIMEOUT $ffa2
|
||||||
|
#define IECIN $ffa5
|
||||||
|
#define IECOUT $ffa8
|
||||||
|
#define UNTALK $ffab
|
||||||
|
#define UNLISTEN $ffae
|
||||||
|
#define LISTEN $ffb1
|
||||||
|
#define TALK $ffb4
|
||||||
|
#define GETST $ffb7
|
||||||
|
#define SETFPAR $ffba
|
||||||
|
#define SETFNPAR $ffbd
|
||||||
|
#define OPEN $ffc0
|
||||||
|
#define CLOSE $ffc3
|
||||||
|
#define CHKIN $ffc6
|
||||||
|
#define CKOUT $ffc9
|
||||||
|
#define CLRCH $ffcc
|
||||||
|
#define BASIN $ffcf
|
||||||
|
#define BSOUT $ffd2
|
||||||
|
#define LOAD $ffd5
|
||||||
|
#define SAVE $ffd8
|
||||||
|
#define SETTI $ffdb
|
||||||
|
#define GETTI $ffde
|
||||||
|
#define GETSTP $ffe1
|
||||||
|
#define GET $ffe4
|
||||||
|
#define CLALL $ffe7
|
||||||
|
#define INCTI $ffea
|
||||||
|
#define SCREEN $ffed
|
||||||
|
#define CURSOR $fff0
|
||||||
|
#define GETIOBASE $fff3
|
||||||
|
|
||||||
|
|
||||||
|
/* Terminal-Commands */
|
||||||
|
|
||||||
|
#define TC_SCO 8
|
||||||
|
#define TC_SCF 9
|
||||||
|
|
||||||
|
#define TC_LF 13 /*10*/
|
||||||
|
#define TC_CR 13
|
||||||
|
|
||||||
|
#define TC_LCH $0e
|
||||||
|
|
||||||
|
#define TC_REV 18
|
||||||
|
|
||||||
|
#define TC_F1 $85
|
||||||
|
#define TC_F3 $86
|
||||||
|
#define TC_F5 $87
|
||||||
|
#define TC_F7 $88
|
||||||
|
#define TC_F2 $89
|
||||||
|
#define TC_F4 $8a
|
||||||
|
#define TC_F6 $8b
|
||||||
|
#define TC_F8 $8c
|
||||||
|
|
||||||
|
#define TC_HCH $8e
|
||||||
|
|
||||||
|
#define TC_REO $92
|
||||||
|
#define TC_FF $93
|
||||||
|
|
||||||
|
#define TC_HELLGRUEN $99
|
||||||
|
|
||||||
|
#define TC_CRL $9d
|
||||||
|
|
||||||
12
xa-2.3.5/examples/pack.doc
Normal file
12
xa-2.3.5/examples/pack.doc
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
|
||||||
|
******** pack 1.0 ******** 11.10.92, A.Fachat
|
||||||
|
|
||||||
|
Dieses Programm f<>r den C64 packt Dateien in eine und kann sie wieder
|
||||||
|
auspacken. 'packen' ist zuviel, denn es werden nur Folgen gleicher Bytes
|
||||||
|
mit einer L„nge von mehr als 3 Byte durch die Folge $f7,anz,byte ersetzt.
|
||||||
|
$f7,0 zeigt das Ende der Datei, $f7 selbst werden durch diese Folge ersetzt,
|
||||||
|
egal wieviel in Reihe sind.
|
||||||
|
Das 'Archiv' beginnt mit der Versionsnummer: 1 Byte = 1
|
||||||
|
Dann folgen die Einzelnen Dateien - der Dateiname in ASCII, mit Nullbyte
|
||||||
|
abgeschlossen, danach die Datei selbst.
|
||||||
|
|
||||||
1070
xa-2.3.5/examples/pack_eng.a65
Normal file
1070
xa-2.3.5/examples/pack_eng.a65
Normal file
File diff suppressed because it is too large
Load diff
1070
xa-2.3.5/examples/pack_ger.a65
Normal file
1070
xa-2.3.5/examples/pack_ger.a65
Normal file
File diff suppressed because it is too large
Load diff
180
xa-2.3.5/examples/peng.l
Normal file
180
xa-2.3.5/examples/peng.l
Normal file
|
|
@ -0,0 +1,180 @@
|
||||||
|
basicend, 0x080b, 1, 0x0000
|
||||||
|
iniscreen, 0x10c4, 1, 0x0000
|
||||||
|
inipar, 0x1093, 1, 0x0000
|
||||||
|
menu1, 0x0819, 2, 0x0000
|
||||||
|
m1atxt, 0x0897, 2, 0x0000
|
||||||
|
Txtout, 0x10ae, 1, 0x0000
|
||||||
|
quellpfad, 0x10d4, 1, 0x0000
|
||||||
|
m1btxt, 0x08e1, 2, 0x0000
|
||||||
|
quelldrv, 0x10d2, 1, 0x0000
|
||||||
|
m1ctxt, 0x08f6, 2, 0x0000
|
||||||
|
zielpfad, 0x10fc, 1, 0x0000
|
||||||
|
m1dtxt, 0x090d, 2, 0x0000
|
||||||
|
zieldrv, 0x10d3, 1, 0x0000
|
||||||
|
m1etxt, 0x0923, 2, 0x0000
|
||||||
|
next, 0x085a, 2, 0x0000
|
||||||
|
l1, 0x0861, 2, 0x0000
|
||||||
|
befkeys, 0x088f, 2, 0x0000
|
||||||
|
exe, 0x086d, 2, 0x0000
|
||||||
|
Anzbefs, 0x0008, 2, 0x0000
|
||||||
|
exec, 0x0873, 2, 0x0000
|
||||||
|
madr, 0x087f, 2, 0x0000
|
||||||
|
pack, 0x0b32, 1, 0x0000
|
||||||
|
unpack, 0x0970, 1, 0x0000
|
||||||
|
quelle, 0x0fe5, 1, 0x0000
|
||||||
|
ziel, 0x102b, 1, 0x0000
|
||||||
|
switch, 0x1071, 1, 0x0000
|
||||||
|
dir, 0x0f01, 1, 0x0000
|
||||||
|
qdrv, 0x0fc5, 1, 0x0000
|
||||||
|
zdrv, 0x0fd5, 1, 0x0000
|
||||||
|
openarcrd, 0x0aff, 1, 0x0000
|
||||||
|
cls, 0x09a1, 12, 0x0000
|
||||||
|
rcnt, 0x132e, 1, 0x0000
|
||||||
|
rbyte, 0x0c09, 1, 0x0000
|
||||||
|
verr, 0x09a7, 12, 0x0000
|
||||||
|
loop, 0x0984, 12, 0x0000
|
||||||
|
unpackfile, 0x09dd, 1, 0x0000
|
||||||
|
t1, 0x09c9, 12, 0x0000
|
||||||
|
waitkey, 0x0f5f, 1, 0x0000
|
||||||
|
verrtxt, 0x09b1, 12, 0x0000
|
||||||
|
wcnt, 0x132c, 1, 0x0000
|
||||||
|
l1, 0x09ee, 15, 0x0000
|
||||||
|
endx, 0x0a27, 15, 0x0000
|
||||||
|
filetab, 0x1332, 1, 0x0000
|
||||||
|
endnam, 0x0a04, 15, 0x0000
|
||||||
|
ask, 0x0a8b, 15, 0x0000
|
||||||
|
nounpack, 0x0a2a, 15, 0x0000
|
||||||
|
tok, 0x0ec9, 1, 0x0000
|
||||||
|
fxopen, 0x0ab7, 1, 0x0000
|
||||||
|
Getzst, 0x0d6a, 1, 0x0000
|
||||||
|
xa, 0x0a31, 15, 0x0000
|
||||||
|
lo, 0x0a35, 15, 0x0000
|
||||||
|
end, 0x0a8a, 15, 0x0000
|
||||||
|
tno, 0x0ec0, 1, 0x0000
|
||||||
|
cls, 0x0a6b, 15, 0x0000
|
||||||
|
xb, 0x0a61, 15, 0x0000
|
||||||
|
wxanz, 0x1228, 1, 0x0000
|
||||||
|
wxbyt, 0x1227, 1, 0x0000
|
||||||
|
ly, 0x0a53, 15, 0x0000
|
||||||
|
wbyte, 0x0d0f, 1, 0x0000
|
||||||
|
wbuf, 0x0d25, 1, 0x0000
|
||||||
|
t1, 0x0aa0, 15, 0x0000
|
||||||
|
incwcnt, 0x0aae, 1, 0x0000
|
||||||
|
l1, 0x0ab6, 20, 0x0000
|
||||||
|
l1, 0x0abb, 21, 0x0000
|
||||||
|
l2, 0x0ad2, 21, 0x0000
|
||||||
|
l1a, 0x0acc, 21, 0x0000
|
||||||
|
l1b, 0x0ace, 21, 0x0000
|
||||||
|
l3, 0x0ad6, 21, 0x0000
|
||||||
|
err, 0x0afe, 21, 0x0000
|
||||||
|
clrwrbuf, 0x0d06, 1, 0x0000
|
||||||
|
l0, 0x0b01, 22, 0x0000
|
||||||
|
l1, 0x0b0b, 22, 0x0000
|
||||||
|
err, 0x0b30, 22, 0x0000
|
||||||
|
Getqst, 0x0d64, 1, 0x0000
|
||||||
|
clrrdbuf, 0x0c6a, 1, 0x0000
|
||||||
|
getlist, 0x0da7, 1, 0x0000
|
||||||
|
anzfiles, 0x1124, 1, 0x0000
|
||||||
|
end, 0x0b66, 23, 0x0000
|
||||||
|
openarcwr, 0x0cd0, 1, 0x0000
|
||||||
|
cls, 0x0b5e, 23, 0x0000
|
||||||
|
l1, 0x0b48, 23, 0x0000
|
||||||
|
setfadr, 0x0ed2, 1, 0x0000
|
||||||
|
packfile, 0x0b6a, 1, 0x0000
|
||||||
|
lft, 0x0baf, 24, 0x0000
|
||||||
|
l1, 0x0b73, 24, 0x0000
|
||||||
|
fopen, 0x0bb9, 1, 0x0000
|
||||||
|
le, 0x0b9a, 24, 0x0000
|
||||||
|
clrwxbyt, 0x0c97, 1, 0x0000
|
||||||
|
l2, 0x0b8c, 24, 0x0000
|
||||||
|
l3, 0x0b97, 24, 0x0000
|
||||||
|
wxbyte, 0x0c76, 1, 0x0000
|
||||||
|
savwxbyt, 0x0c9d, 1, 0x0000
|
||||||
|
l1, 0x0bbd, 26, 0x0000
|
||||||
|
l2, 0x0bd4, 26, 0x0000
|
||||||
|
l1a, 0x0bce, 26, 0x0000
|
||||||
|
l1b, 0x0bd0, 26, 0x0000
|
||||||
|
l3, 0x0bd8, 26, 0x0000
|
||||||
|
err, 0x0bff, 26, 0x0000
|
||||||
|
incrcnt, 0x0c00, 1, 0x0000
|
||||||
|
l1, 0x0c08, 27, 0x0000
|
||||||
|
ro, 0x122a, 1, 0x0000
|
||||||
|
ri, 0x1229, 1, 0x0000
|
||||||
|
leerbuf, 0x0c19, 28, 0x0000
|
||||||
|
rb, 0x122c, 1, 0x0000
|
||||||
|
rf, 0x122b, 1, 0x0000
|
||||||
|
ldbuf, 0x0c20, 28, 0x0000
|
||||||
|
lok, 0x0c31, 28, 0x0000
|
||||||
|
l0, 0x0c4a, 28, 0x0000
|
||||||
|
le, 0x0c5f, 28, 0x0000
|
||||||
|
add, 0x0c90, 31, 0x0000
|
||||||
|
ad2, 0x0c86, 31, 0x0000
|
||||||
|
adx, 0x0c93, 31, 0x0000
|
||||||
|
nosav, 0x0ccf, 33, 0x0000
|
||||||
|
savs, 0x0cb9, 33, 0x0000
|
||||||
|
l1, 0x0cad, 33, 0x0000
|
||||||
|
l0, 0x0cd2, 34, 0x0000
|
||||||
|
l1, 0x0cdc, 34, 0x0000
|
||||||
|
err, 0x0d04, 34, 0x0000
|
||||||
|
wi, 0x1125, 1, 0x0000
|
||||||
|
wo, 0x1126, 1, 0x0000
|
||||||
|
wb, 0x1127, 1, 0x0000
|
||||||
|
nowr, 0x0d24, 36, 0x0000
|
||||||
|
l1, 0x0d2d, 37, 0x0000
|
||||||
|
end, 0x0d58, 37, 0x0000
|
||||||
|
l0, 0x0d51, 37, 0x0000
|
||||||
|
Getst, 0x0d6d, 1, 0x0000
|
||||||
|
l1, 0x0d8a, 38, 0x0000
|
||||||
|
l2, 0x0d98, 38, 0x0000
|
||||||
|
err, 0x0da2, 38, 0x0000
|
||||||
|
l4x, 0x0da4, 39, 0x0000
|
||||||
|
l4, 0x0e80, 39, 0x0000
|
||||||
|
setdirnam, 0x0f65, 1, 0x0000
|
||||||
|
l0, 0x0dc7, 39, 0x0000
|
||||||
|
l1, 0x0dc9, 39, 0x0000
|
||||||
|
la, 0x0de3, 39, 0x0000
|
||||||
|
l3x, 0x0df1, 39, 0x0000
|
||||||
|
l3, 0x0e5c, 39, 0x0000
|
||||||
|
lb, 0x0e04, 39, 0x0000
|
||||||
|
lc, 0x0e19, 39, 0x0000
|
||||||
|
ld, 0x0e1e, 39, 0x0000
|
||||||
|
lf, 0x0e35, 39, 0x0000
|
||||||
|
lg, 0x0e49, 39, 0x0000
|
||||||
|
testkeys, 0x0e86, 1, 0x0000
|
||||||
|
lh, 0x0e53, 39, 0x0000
|
||||||
|
l2, 0x0e6c, 39, 0x0000
|
||||||
|
l5, 0x0e79, 39, 0x0000
|
||||||
|
ok, 0x0e8f, 40, 0x0000
|
||||||
|
t1, 0x0eb0, 40, 0x0000
|
||||||
|
ja, 0x0ea5, 40, 0x0000
|
||||||
|
l0, 0x0f1c, 45, 0x0000
|
||||||
|
l1, 0x0f1e, 45, 0x0000
|
||||||
|
l4, 0x0f59, 45, 0x0000
|
||||||
|
l3, 0x0f38, 45, 0x0000
|
||||||
|
l2, 0x0f48, 45, 0x0000
|
||||||
|
l5, 0x0f55, 45, 0x0000
|
||||||
|
p1, 0x0014, 46, 0x0000
|
||||||
|
l1, 0x0f70, 46, 0x0000
|
||||||
|
nodp, 0x0f7e, 46, 0x0000
|
||||||
|
dp, 0x0f84, 46, 0x0000
|
||||||
|
dp1, 0x0f86, 46, 0x0000
|
||||||
|
end, 0x0f9e, 46, 0x0000
|
||||||
|
l2a, 0x0f96, 46, 0x0000
|
||||||
|
l2, 0x0f98, 46, 0x0000
|
||||||
|
ok, 0x0fd4, 47, 0x0000
|
||||||
|
ok, 0x0fe4, 48, 0x0000
|
||||||
|
quelltxt, 0x1004, 49, 0x0000
|
||||||
|
q1, 0x0ff1, 49, 0x0000
|
||||||
|
end, 0x1003, 49, 0x0000
|
||||||
|
quelltxt, 0x104a, 51, 0x0000
|
||||||
|
q1, 0x1037, 51, 0x0000
|
||||||
|
end, 0x1049, 51, 0x0000
|
||||||
|
l1, 0x107f, 53, 0x0000
|
||||||
|
noval, 0x10a5, 54, 0x0000
|
||||||
|
ok, 0x10a7, 54, 0x0000
|
||||||
|
p, 0x0022, 55, 0x0000
|
||||||
|
l1, 0x10b2, 55, 0x0000
|
||||||
|
le, 0x10c3, 55, 0x0000
|
||||||
|
sysmem, 0x1332, 1, 0x0000
|
||||||
|
ecnt, 0x1330, 1, 0x0000
|
||||||
|
ende, 0x10d2, 1, 0x0000
|
||||||
18
xa-2.3.5/loader/Makefile
Normal file
18
xa-2.3.5/loader/Makefile
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
|
||||||
|
all: loader example test2 rom65
|
||||||
|
|
||||||
|
loader: loader.a65 file.def
|
||||||
|
../xa loader.a65 -o loader
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f loader test2 example a.o65 rom65
|
||||||
|
|
||||||
|
example: test.a
|
||||||
|
../xa -R test.a -o example
|
||||||
|
|
||||||
|
test2: test2.a
|
||||||
|
../xa test2.a -o test2
|
||||||
|
|
||||||
|
rom65: test.a
|
||||||
|
../mkrom.sh -O "-G" -S "-bd 1234" -R rom65 test.a test.a
|
||||||
|
|
||||||
8
xa-2.3.5/loader/README
Normal file
8
xa-2.3.5/loader/README
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
|
||||||
|
In this directory you find two test files, i.e. test.a and test2.a for
|
||||||
|
xa. test.a is assembled into the file "example", which is loaded by the
|
||||||
|
relocator "loader", when started on a C64. Don't try to execute this
|
||||||
|
file, it's just for testing.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BIN
xa-2.3.5/loader/ex2
Normal file
BIN
xa-2.3.5/loader/ex2
Normal file
Binary file not shown.
BIN
xa-2.3.5/loader/example2
Normal file
BIN
xa-2.3.5/loader/example2
Normal file
Binary file not shown.
36
xa-2.3.5/loader/file.def
Normal file
36
xa-2.3.5/loader/file.def
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
|
||||||
|
/* These definitions are without the two leading version/marker bytes,
|
||||||
|
* length is without options
|
||||||
|
*/
|
||||||
|
#define HDR_MAGIC 0
|
||||||
|
#define HDR_VERSION 3
|
||||||
|
#define HDR_MODE 4
|
||||||
|
#define HDR_TBASE 6
|
||||||
|
#define HDR_TLEN 8
|
||||||
|
#define HDR_DBASE 10
|
||||||
|
#define HDR_DLEN 12
|
||||||
|
#define HDR_BBASE 14
|
||||||
|
#define HDR_BLEN 16
|
||||||
|
#define HDR_ZBASE 18
|
||||||
|
#define HDR_ZLEN 20
|
||||||
|
#define HDR_STACKLEN 22
|
||||||
|
#define HDR_LEN 24
|
||||||
|
|
||||||
|
#define A_ADR $80
|
||||||
|
#define A_HIGH $40 /* or'd with the low byte */
|
||||||
|
#define A_LOW $20
|
||||||
|
#define A_MASK $e0 /* reloc type mask */
|
||||||
|
#define A_FMASK $0f /* segment type mask */
|
||||||
|
|
||||||
|
#define SEG_UNDEF 0
|
||||||
|
#define SEG_ABS 1
|
||||||
|
#define SEG_TEXT 2
|
||||||
|
#define SEG_DATA 3
|
||||||
|
#define SEG_BSS 4
|
||||||
|
#define SEG_ZERO 5
|
||||||
|
|
||||||
|
#define FM_OBJ %00010000
|
||||||
|
#define FM_SIZE %00100000
|
||||||
|
#define FM_RELOC %01000000
|
||||||
|
#define FM_CPU %10000000
|
||||||
|
|
||||||
909
xa-2.3.5/loader/loader.a65
Normal file
909
xa-2.3.5/loader/loader.a65
Normal file
|
|
@ -0,0 +1,909 @@
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
*
|
||||||
|
* Loader for 6502 relocatable binary format
|
||||||
|
*
|
||||||
|
* The loader supports 16 bit o65 version 1 files without undefined
|
||||||
|
* references. Also it doesn't like pagewise relocation and 65816
|
||||||
|
* code, because there are different/additional relocation entries.
|
||||||
|
*
|
||||||
|
* The support routines, that have to be changed are at the end of the
|
||||||
|
* file. The stuff in this file is in absolute format (well, you have to
|
||||||
|
* bootstrap from something :-)
|
||||||
|
* The support routines for the file handling are for the operating system
|
||||||
|
* OS/A65, as of version 1.3.10b. The first part of the file (wrapped in
|
||||||
|
* "#ifdef C64") shows how to use it with a C64, for example.
|
||||||
|
*
|
||||||
|
* The subroutine 'loader' is called with a file descriptor, that has a
|
||||||
|
* meaning for the support routines, in the X register.
|
||||||
|
* The file must already be open. Also binit must have been called before.
|
||||||
|
* The loader doesn't close the file.
|
||||||
|
*
|
||||||
|
* Support routines are:
|
||||||
|
* binit a = hi byte start address memory to handle,
|
||||||
|
* x = hi byte length of memory to handle
|
||||||
|
* balloc a/y = length of block -> x = memory descriptor
|
||||||
|
* bfree x = memory block descriptor to free
|
||||||
|
* getbadr x = memory descriptor -> a/y address of memory block
|
||||||
|
*
|
||||||
|
* zalloc a = length of needed zeropage block. returns a=address
|
||||||
|
* zfree a = address of block to free
|
||||||
|
*
|
||||||
|
* fgetc x = file descriptor, returns read byte (c=0) or error (c=1)
|
||||||
|
* The error is passed through; fgetc blocks if no data
|
||||||
|
* available
|
||||||
|
* fgetb x = filedescriptor, a/y = address of block descriptor,
|
||||||
|
* i.e. a word start address and a word length of block.
|
||||||
|
* returns (c=0) or error in accu (c=1).
|
||||||
|
*
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
* This part is a binding for a C64
|
||||||
|
* to show how it works
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define C64
|
||||||
|
|
||||||
|
#ifdef C64
|
||||||
|
|
||||||
|
sysmem =$033c
|
||||||
|
syszp =$57
|
||||||
|
|
||||||
|
|
||||||
|
.word $0801
|
||||||
|
*=$801
|
||||||
|
.word nextl
|
||||||
|
.word 10
|
||||||
|
.byt $9e, "2080",0
|
||||||
|
nextl .word 0
|
||||||
|
.dsb 2080-*, 0
|
||||||
|
|
||||||
|
c64load .(
|
||||||
|
lda #>PRGEND+255
|
||||||
|
ldx #>$A000-PRGEND
|
||||||
|
jsr binit ; init memory handling
|
||||||
|
|
||||||
|
lda #7
|
||||||
|
ldx #<fname
|
||||||
|
ldy #>fname
|
||||||
|
jsr $ffbd ; setfnpar
|
||||||
|
|
||||||
|
lda #2
|
||||||
|
ldx #11
|
||||||
|
ldy #0
|
||||||
|
jsr $ffba ; setfpar
|
||||||
|
|
||||||
|
jsr $ffc0 ; open
|
||||||
|
bcs end
|
||||||
|
|
||||||
|
ldx #2
|
||||||
|
jsr $ffc6 ; chkin
|
||||||
|
bcs end
|
||||||
|
|
||||||
|
jsr loader ; don't care about x, chkin did it
|
||||||
|
|
||||||
|
php
|
||||||
|
pha
|
||||||
|
jsr $ffcc ; clrch
|
||||||
|
lda #2
|
||||||
|
jsr $ffc3 ; close
|
||||||
|
pla
|
||||||
|
plp
|
||||||
|
end rts
|
||||||
|
|
||||||
|
fname ;.asc "example",0
|
||||||
|
.byt $45, $58, $41, $4d, $50, $4c, $45, 0
|
||||||
|
.)
|
||||||
|
|
||||||
|
fgetc .(
|
||||||
|
jsr $ffcf
|
||||||
|
php
|
||||||
|
pha
|
||||||
|
bcc carry
|
||||||
|
lda #"C"
|
||||||
|
jsr $ffd2
|
||||||
|
pla
|
||||||
|
pha
|
||||||
|
carry
|
||||||
|
jsr hexout
|
||||||
|
lda #$20
|
||||||
|
jsr $ffd2
|
||||||
|
pla
|
||||||
|
plp
|
||||||
|
rts
|
||||||
|
.)
|
||||||
|
|
||||||
|
hexout .(
|
||||||
|
pha
|
||||||
|
lsr
|
||||||
|
lsr
|
||||||
|
lsr
|
||||||
|
lsr
|
||||||
|
jsr nibout
|
||||||
|
pla
|
||||||
|
nibout and #$0f
|
||||||
|
clc
|
||||||
|
adc #$30
|
||||||
|
cmp #$3a
|
||||||
|
bcc ok
|
||||||
|
adc #$41-$3a-1
|
||||||
|
ok jmp $ffd2
|
||||||
|
.)
|
||||||
|
|
||||||
|
zalloc .(
|
||||||
|
cmp #$80 ; save from $90 upward = OS, below is only basic
|
||||||
|
bcs end
|
||||||
|
lda #$10
|
||||||
|
end rts
|
||||||
|
.)
|
||||||
|
|
||||||
|
zfree .(
|
||||||
|
clc
|
||||||
|
rts
|
||||||
|
.)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
* Here is the real loader code
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "file.def"
|
||||||
|
|
||||||
|
#define E_NOMEM <-40
|
||||||
|
#define E_FVERSION <-41
|
||||||
|
|
||||||
|
loader .(
|
||||||
|
p1 =syszp
|
||||||
|
p2 =syszp+2
|
||||||
|
-syszp +=4
|
||||||
|
|
||||||
|
tmp =sysmem
|
||||||
|
file =sysmem+1
|
||||||
|
-sysmem +=2
|
||||||
|
header =sysmem
|
||||||
|
-sysmem +=HDR_LEN
|
||||||
|
textb =sysmem ; memory block ID
|
||||||
|
texta =sysmem+1 ; address of block
|
||||||
|
textl =sysmem+3 ; address of block
|
||||||
|
textd =sysmem+5 ; difference to assemble address
|
||||||
|
-sysmem +=7
|
||||||
|
datab =sysmem
|
||||||
|
dataa =sysmem+1
|
||||||
|
datal =sysmem+3
|
||||||
|
datad =sysmem+5
|
||||||
|
-sysmem +=7
|
||||||
|
bssb =sysmem
|
||||||
|
bssa =sysmem+1
|
||||||
|
bssd =sysmem+3
|
||||||
|
-sysmem +=5
|
||||||
|
zeroa =sysmem
|
||||||
|
zerod =sysmem+1
|
||||||
|
-sysmem +=3
|
||||||
|
|
||||||
|
stx file
|
||||||
|
jsr fgetc
|
||||||
|
bcs end
|
||||||
|
sta tmp
|
||||||
|
jsr fgetc
|
||||||
|
bcs end
|
||||||
|
tay
|
||||||
|
lda tmp
|
||||||
|
cpy #0
|
||||||
|
bne rt
|
||||||
|
cmp #1
|
||||||
|
beq load
|
||||||
|
rt lda #E_FVERSION ; ok, but not this version
|
||||||
|
end sec
|
||||||
|
rts
|
||||||
|
|
||||||
|
load .(
|
||||||
|
lda #<header
|
||||||
|
sta p1
|
||||||
|
lda #>header
|
||||||
|
sta p1+1
|
||||||
|
lda #<HDR_LEN
|
||||||
|
sta p1+2
|
||||||
|
lda #>HDR_LEN
|
||||||
|
sta p1+3
|
||||||
|
|
||||||
|
ldx file
|
||||||
|
lda #<p1
|
||||||
|
ldy #>p1
|
||||||
|
jsr fgetb
|
||||||
|
bcs end
|
||||||
|
|
||||||
|
; header loaded, check magic and version
|
||||||
|
lda header+HDR_MAGIC
|
||||||
|
cmp #$6f
|
||||||
|
bne end
|
||||||
|
lda header+HDR_MAGIC+1
|
||||||
|
cmp #"6"
|
||||||
|
bne end
|
||||||
|
lda header+HDR_MAGIC+2
|
||||||
|
cmp #"5"
|
||||||
|
bne end
|
||||||
|
lda header+HDR_VERSION
|
||||||
|
cmp #0
|
||||||
|
bne end
|
||||||
|
lda header+HDR_MODE+1
|
||||||
|
and #%11110000
|
||||||
|
bne end
|
||||||
|
; now allocate buffers
|
||||||
|
lda header+HDR_TLEN
|
||||||
|
ldy header+HDR_TLEN+1
|
||||||
|
sta textl
|
||||||
|
sty textl+1
|
||||||
|
jsr balloc
|
||||||
|
stx textb
|
||||||
|
bcs no_text2
|
||||||
|
jsr getbadr
|
||||||
|
sta texta
|
||||||
|
sty texta+1
|
||||||
|
sec
|
||||||
|
sbc header+HDR_TBASE
|
||||||
|
sta textd
|
||||||
|
tya
|
||||||
|
sbc header+HDR_TBASE+1
|
||||||
|
sta textd+1
|
||||||
|
|
||||||
|
lda header+HDR_DLEN
|
||||||
|
ldy header+HDR_DLEN+1
|
||||||
|
sta datal
|
||||||
|
sty datal+1
|
||||||
|
jsr balloc
|
||||||
|
stx datab
|
||||||
|
bcs no_data2
|
||||||
|
no_text2 bcs no_text1
|
||||||
|
jsr getbadr
|
||||||
|
sta dataa
|
||||||
|
sty dataa+1
|
||||||
|
sec
|
||||||
|
sbc header+HDR_DBASE
|
||||||
|
sta datad
|
||||||
|
tya
|
||||||
|
sbc header+HDR_DBASE+1
|
||||||
|
sta datad+1
|
||||||
|
|
||||||
|
lda header+HDR_BLEN
|
||||||
|
ldy header+HDR_BLEN+1
|
||||||
|
jsr balloc
|
||||||
|
stx bssb
|
||||||
|
bcs no_bss
|
||||||
|
no_text1 bcs no_text
|
||||||
|
no_data2 bcs no_data
|
||||||
|
jsr getbadr
|
||||||
|
sta bssa
|
||||||
|
sty bssa+1
|
||||||
|
sec
|
||||||
|
sbc header+HDR_BBASE
|
||||||
|
sta bssd
|
||||||
|
tya
|
||||||
|
sbc header+HDR_BBASE+1
|
||||||
|
sta bssd+1
|
||||||
|
|
||||||
|
lda header+HDR_ZLEN
|
||||||
|
jsr zalloc
|
||||||
|
bcs no_zero
|
||||||
|
sta zeroa
|
||||||
|
sec
|
||||||
|
sbc header+HDR_ZBASE
|
||||||
|
sta zerod
|
||||||
|
lda #0
|
||||||
|
sta zerod+1
|
||||||
|
|
||||||
|
jmp do_load
|
||||||
|
|
||||||
|
&no_file lda zeroa
|
||||||
|
jsr zfree
|
||||||
|
no_zero ldx bssb
|
||||||
|
jsr bfree
|
||||||
|
no_bss ldx datab
|
||||||
|
jsr bfree
|
||||||
|
no_data ldx textb
|
||||||
|
jsr bfree
|
||||||
|
no_text rts
|
||||||
|
|
||||||
|
do_load ; load options (i.e. ignore them now)
|
||||||
|
jsr fgetc
|
||||||
|
bcs no_file
|
||||||
|
cmp #0
|
||||||
|
beq load_text
|
||||||
|
tay
|
||||||
|
dey
|
||||||
|
optl jsr fgetc
|
||||||
|
bcs no_file
|
||||||
|
dey
|
||||||
|
bne optl
|
||||||
|
beq do_load
|
||||||
|
|
||||||
|
load_text ; load text segment
|
||||||
|
ldx file
|
||||||
|
lda #<texta
|
||||||
|
ldy #>texta
|
||||||
|
jsr fgetb
|
||||||
|
bcs no_file
|
||||||
|
|
||||||
|
ldx file
|
||||||
|
lda #<dataa
|
||||||
|
ldy #>dataa
|
||||||
|
jsr fgetb
|
||||||
|
bcs no_file
|
||||||
|
; check number of undefined references
|
||||||
|
ldx file
|
||||||
|
jsr fgetc
|
||||||
|
&no_file2 bcs no_file
|
||||||
|
cmp #0
|
||||||
|
bne no_file ; we have some -> not handled
|
||||||
|
ldx file
|
||||||
|
jsr fgetc
|
||||||
|
bcs no_file
|
||||||
|
cmp #0
|
||||||
|
bne no_file
|
||||||
|
; ok, text segments loaded, now relocate
|
||||||
|
lda texta
|
||||||
|
sec
|
||||||
|
sbc #1
|
||||||
|
sta p1
|
||||||
|
lda texta+1
|
||||||
|
sbc #0
|
||||||
|
sta p1+1
|
||||||
|
jsr trel
|
||||||
|
|
||||||
|
lda dataa
|
||||||
|
sec
|
||||||
|
sbc #1
|
||||||
|
sta p1
|
||||||
|
lda dataa+1
|
||||||
|
sbc #0
|
||||||
|
sta p1+1
|
||||||
|
jsr trel
|
||||||
|
|
||||||
|
lda texta ; return start of text segment
|
||||||
|
ldy texta+1
|
||||||
|
clc
|
||||||
|
rts
|
||||||
|
.)
|
||||||
|
|
||||||
|
trel .(
|
||||||
|
ldx file
|
||||||
|
jsr fgetc
|
||||||
|
no_file1 bcs no_file2
|
||||||
|
cmp #0
|
||||||
|
beq reloc_rts
|
||||||
|
cmp #255
|
||||||
|
bne t1
|
||||||
|
lda #254
|
||||||
|
clc
|
||||||
|
adc p1
|
||||||
|
sta p1
|
||||||
|
bcc trel
|
||||||
|
inc p1+1
|
||||||
|
jmp trel
|
||||||
|
t1 clc
|
||||||
|
adc p1
|
||||||
|
sta p1
|
||||||
|
bcc t1a
|
||||||
|
inc p1+1
|
||||||
|
t1a ; p1 is the relocation address
|
||||||
|
ldx file
|
||||||
|
jsr fgetc
|
||||||
|
bcs no_file1
|
||||||
|
tay
|
||||||
|
and #A_MASK
|
||||||
|
sta tmp
|
||||||
|
tya
|
||||||
|
and #A_FMASK
|
||||||
|
jsr getreldiff
|
||||||
|
ldy tmp
|
||||||
|
cpy #A_ADR
|
||||||
|
bne t2
|
||||||
|
|
||||||
|
ldy #0
|
||||||
|
clc
|
||||||
|
adc (p1),y
|
||||||
|
sta (p1),y
|
||||||
|
iny
|
||||||
|
txa
|
||||||
|
adc (p1),y
|
||||||
|
sta (p1),y
|
||||||
|
jmp trel
|
||||||
|
t2
|
||||||
|
cpy #A_LOW
|
||||||
|
bne t3
|
||||||
|
ldy #0
|
||||||
|
clc
|
||||||
|
adc (p1),y
|
||||||
|
sta (p1),y
|
||||||
|
jmp trel
|
||||||
|
t3
|
||||||
|
cpy #A_HIGH
|
||||||
|
bne trel
|
||||||
|
sta p2
|
||||||
|
stx p2+1
|
||||||
|
ldx file
|
||||||
|
jsr fgetc
|
||||||
|
clc
|
||||||
|
adc p2 ; just get the carry bit
|
||||||
|
ldy #0
|
||||||
|
lda p2+1 ; relocate high byte
|
||||||
|
adc (p1),y
|
||||||
|
sta (p1),y
|
||||||
|
jmp trel
|
||||||
|
|
||||||
|
reloc_rts
|
||||||
|
clc
|
||||||
|
rts
|
||||||
|
.)
|
||||||
|
|
||||||
|
getreldiff .( ; comparing with SEG_UNDEF would give a way
|
||||||
|
; to get label value here for undefined refs
|
||||||
|
cmp #SEG_TEXT
|
||||||
|
bne notext
|
||||||
|
lda textd
|
||||||
|
ldx textd+1
|
||||||
|
rts
|
||||||
|
notext cmp #SEG_DATA
|
||||||
|
bne nodata
|
||||||
|
lda datad
|
||||||
|
ldx datad+1
|
||||||
|
rts
|
||||||
|
nodata cmp #SEG_BSS
|
||||||
|
bne nobss
|
||||||
|
lda bssd
|
||||||
|
ldx bssd+1
|
||||||
|
rts
|
||||||
|
nobss cmp #SEG_ZERO
|
||||||
|
bne nozero
|
||||||
|
lda zerod
|
||||||
|
ldx zerod+1
|
||||||
|
nozero rts
|
||||||
|
.)
|
||||||
|
|
||||||
|
.)
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
* Here come the support routines
|
||||||
|
*
|
||||||
|
* first is a simple and basic implementation of fgetb, just using fgetc
|
||||||
|
*/
|
||||||
|
|
||||||
|
fgetb .(
|
||||||
|
p =syszp
|
||||||
|
-syszp +=2
|
||||||
|
file =sysmem
|
||||||
|
l =sysmem+1
|
||||||
|
-sysmem +=3
|
||||||
|
|
||||||
|
stx file ; x=file, a=zp-adr of address, y=zp-adr of len
|
||||||
|
sta p
|
||||||
|
sty p+1
|
||||||
|
ldy #3
|
||||||
|
lda (p),y
|
||||||
|
sta l+1
|
||||||
|
dey
|
||||||
|
lda (p),y
|
||||||
|
sta l
|
||||||
|
dey
|
||||||
|
lda (p),y
|
||||||
|
pha
|
||||||
|
dey
|
||||||
|
lda (p),y
|
||||||
|
sta p
|
||||||
|
pla
|
||||||
|
sta p+1
|
||||||
|
|
||||||
|
loop ldx file
|
||||||
|
jsr fgetc ; this is a simple implementation
|
||||||
|
bcs end
|
||||||
|
ldy #0
|
||||||
|
sta (p),y
|
||||||
|
inc p
|
||||||
|
bne l0
|
||||||
|
inc p+1
|
||||||
|
l0
|
||||||
|
lda l
|
||||||
|
bne l1
|
||||||
|
dec l+1
|
||||||
|
l1 dec l
|
||||||
|
|
||||||
|
lda l
|
||||||
|
ora l+1
|
||||||
|
bne loop
|
||||||
|
clc
|
||||||
|
end
|
||||||
|
rts
|
||||||
|
.)
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
* support for memory allocation
|
||||||
|
*
|
||||||
|
* These routines are taken from a preliminary SLIP implementation, as of
|
||||||
|
* OS/A65 version 1.3.10b
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MAXSLOT 8
|
||||||
|
|
||||||
|
/**********************************************************************/
|
||||||
|
/* New memory management for IP buffers */
|
||||||
|
/* exports */
|
||||||
|
/* binit */
|
||||||
|
/* balloc, bfree, btrunc, bsplit, brealloc */
|
||||||
|
/* getbadr, getblen */
|
||||||
|
|
||||||
|
#define MINBUF 8
|
||||||
|
#define MINMASK %11111000
|
||||||
|
|
||||||
|
.(
|
||||||
|
|
||||||
|
slotladr =sysmem
|
||||||
|
slothadr =sysmem+MAXSLOT
|
||||||
|
slotllen =sysmem+MAXSLOT*2
|
||||||
|
slothlen =sysmem+MAXSLOT*3
|
||||||
|
-sysmem +=MAXSLOT*4
|
||||||
|
|
||||||
|
flist =sysmem
|
||||||
|
slot =sysmem+2
|
||||||
|
-sysmem +=3
|
||||||
|
|
||||||
|
p =syszp
|
||||||
|
p2 =syszp+2
|
||||||
|
p3 =syszp+4
|
||||||
|
p4 =syszp+6
|
||||||
|
-syszp +=8
|
||||||
|
|
||||||
|
/* init memory management */
|
||||||
|
&binit .(
|
||||||
|
sta p+1 ; hi byte startadress buffer
|
||||||
|
stx p2+1 ; hi byte length of buffer
|
||||||
|
|
||||||
|
lda #0
|
||||||
|
tay
|
||||||
|
l0 sta slotladr,y
|
||||||
|
sta slothadr,y
|
||||||
|
iny
|
||||||
|
cpy #MAXSLOT
|
||||||
|
bcc l0
|
||||||
|
|
||||||
|
sta p
|
||||||
|
tay
|
||||||
|
sta (p),y
|
||||||
|
iny
|
||||||
|
sta (p),y
|
||||||
|
iny
|
||||||
|
sta (p),y
|
||||||
|
iny
|
||||||
|
lda p2+1
|
||||||
|
sta (p),y
|
||||||
|
|
||||||
|
lda p
|
||||||
|
sta flist
|
||||||
|
lda p+1
|
||||||
|
sta flist+1
|
||||||
|
|
||||||
|
clc
|
||||||
|
rts
|
||||||
|
.)
|
||||||
|
|
||||||
|
/* a/y = size of buffer to be allocated -> x buffer-ID */
|
||||||
|
&balloc .(
|
||||||
|
/* walk along freelist, and take first matching buffer
|
||||||
|
length is made a multiple of 8 (for freelist connectors */
|
||||||
|
|
||||||
|
pha
|
||||||
|
jsr getbslot
|
||||||
|
pla
|
||||||
|
bcc gotslot
|
||||||
|
lda #E_NOMEM
|
||||||
|
rts
|
||||||
|
gotslot
|
||||||
|
stx slot
|
||||||
|
|
||||||
|
adc #MINBUF-1
|
||||||
|
and #MINMASK
|
||||||
|
sta slotllen,x
|
||||||
|
tya
|
||||||
|
adc #0
|
||||||
|
sta slothlen,x
|
||||||
|
|
||||||
|
lda #0
|
||||||
|
sta p2
|
||||||
|
sta p2+1
|
||||||
|
lda flist
|
||||||
|
sta p
|
||||||
|
lda flist+1
|
||||||
|
sta p+1
|
||||||
|
l0
|
||||||
|
ldy #2
|
||||||
|
lda (p),y
|
||||||
|
sec
|
||||||
|
sbc slotllen,x
|
||||||
|
sta p3
|
||||||
|
iny
|
||||||
|
lda (p),y
|
||||||
|
sbc slothlen,x
|
||||||
|
sta p3+1
|
||||||
|
bcs found
|
||||||
|
|
||||||
|
lda p
|
||||||
|
sta p2
|
||||||
|
lda p+1
|
||||||
|
sta p2+1
|
||||||
|
ldy #1
|
||||||
|
lda (p2),y
|
||||||
|
sta p+1
|
||||||
|
dey
|
||||||
|
lda (p2),y
|
||||||
|
sta p
|
||||||
|
ora p+1
|
||||||
|
bne l0
|
||||||
|
|
||||||
|
oops lda #E_NOMEM
|
||||||
|
sec
|
||||||
|
rts
|
||||||
|
|
||||||
|
found
|
||||||
|
/* ok, we found a free buffer: p points to the buffer, p2 to the
|
||||||
|
previous one. p3 is the length of the free buffer minus the
|
||||||
|
needed size. If the buffer is longer than needed, create a
|
||||||
|
new free buffer, then link new buffer to freelist */
|
||||||
|
|
||||||
|
lda p /* save buffer address */
|
||||||
|
sta slotladr,x
|
||||||
|
lda p+1
|
||||||
|
sta slothadr,x
|
||||||
|
|
||||||
|
lda p3 /* check length */
|
||||||
|
ora p3+1
|
||||||
|
beq nocreate
|
||||||
|
|
||||||
|
lda p /* get address of new free buffer */
|
||||||
|
clc
|
||||||
|
adc slotllen,x
|
||||||
|
sta p4
|
||||||
|
lda p+1
|
||||||
|
adc slothlen,x
|
||||||
|
sta p4+1
|
||||||
|
|
||||||
|
ldy #0 /* copy next pointer */
|
||||||
|
lda (p),y
|
||||||
|
sta (p4),y
|
||||||
|
iny
|
||||||
|
lda (p),y
|
||||||
|
sta (p4),y
|
||||||
|
|
||||||
|
iny /* set new length */
|
||||||
|
lda slotllen,x
|
||||||
|
sta (p),y
|
||||||
|
lda p3
|
||||||
|
sta (p4),y
|
||||||
|
iny
|
||||||
|
lda slothlen,x
|
||||||
|
sta (p),y
|
||||||
|
lda p3+1
|
||||||
|
sta (p4),y
|
||||||
|
|
||||||
|
lda p4
|
||||||
|
sta p
|
||||||
|
lda p4+1
|
||||||
|
sta p+1
|
||||||
|
|
||||||
|
nocreate
|
||||||
|
lda p2
|
||||||
|
ora p2+1
|
||||||
|
beq freestart
|
||||||
|
|
||||||
|
ldy #0
|
||||||
|
lda p
|
||||||
|
sta (p2),y
|
||||||
|
iny
|
||||||
|
lda p+1
|
||||||
|
sta (p2),y
|
||||||
|
clc
|
||||||
|
bcc geta
|
||||||
|
freestart
|
||||||
|
lda p
|
||||||
|
sta flist
|
||||||
|
lda p+1
|
||||||
|
sta flist+1
|
||||||
|
clc
|
||||||
|
geta
|
||||||
|
lda slotladr,x
|
||||||
|
ldy slothadr,x
|
||||||
|
rts
|
||||||
|
.)
|
||||||
|
|
||||||
|
/* free buffer (ID=xr) */
|
||||||
|
&bfree .(
|
||||||
|
lda slothadr,x
|
||||||
|
sta p3+1
|
||||||
|
lda slotladr,x
|
||||||
|
sta p3
|
||||||
|
ora p3+1
|
||||||
|
beq end2
|
||||||
|
|
||||||
|
ldy #2
|
||||||
|
lda slotllen,x
|
||||||
|
sta (p3),y
|
||||||
|
iny
|
||||||
|
lda slothlen,x
|
||||||
|
sta (p3),y
|
||||||
|
|
||||||
|
lda #0
|
||||||
|
sta slothadr,x
|
||||||
|
sta slotladr,x
|
||||||
|
|
||||||
|
lda flist
|
||||||
|
ora flist+1
|
||||||
|
bne ok /* no free buffer so far? */
|
||||||
|
|
||||||
|
lda p3
|
||||||
|
sta flist
|
||||||
|
lda p3+1
|
||||||
|
sta flist+1
|
||||||
|
ldy #0
|
||||||
|
tya
|
||||||
|
sta (p3),y
|
||||||
|
iny
|
||||||
|
sta (p3),y
|
||||||
|
end2 clc
|
||||||
|
rts
|
||||||
|
ok
|
||||||
|
lda #0
|
||||||
|
sta p2
|
||||||
|
sta p2+1
|
||||||
|
lda flist
|
||||||
|
sta p
|
||||||
|
lda flist+1
|
||||||
|
sta p+1
|
||||||
|
|
||||||
|
/* we have to find the place where to put the buffer in the
|
||||||
|
ordered free list. Then we have to check if we can merge
|
||||||
|
free buffers */
|
||||||
|
loop
|
||||||
|
lda p3+1
|
||||||
|
cmp p+1
|
||||||
|
bcc found
|
||||||
|
bne next
|
||||||
|
lda p3
|
||||||
|
cmp p
|
||||||
|
bcc found
|
||||||
|
next
|
||||||
|
lda p
|
||||||
|
sta p2
|
||||||
|
lda p+1
|
||||||
|
sta p2+1
|
||||||
|
ldy #0
|
||||||
|
lda (p2),y
|
||||||
|
sta p
|
||||||
|
iny
|
||||||
|
lda (p2),y
|
||||||
|
sta p+1
|
||||||
|
ora p
|
||||||
|
bne loop
|
||||||
|
beq found
|
||||||
|
end
|
||||||
|
clc
|
||||||
|
rts
|
||||||
|
|
||||||
|
found /* p2 is the buffer before the one to be freed, p the one behind.
|
||||||
|
p3 is the buffer to be inserted */
|
||||||
|
|
||||||
|
lda p2
|
||||||
|
ora p2+1
|
||||||
|
bne fok
|
||||||
|
; insert before the first free buffer so far
|
||||||
|
ldy #0
|
||||||
|
lda flist
|
||||||
|
sta (p3),y
|
||||||
|
iny
|
||||||
|
lda flist+1
|
||||||
|
sta (p3),y
|
||||||
|
lda p3
|
||||||
|
sta flist
|
||||||
|
ldy p3+1
|
||||||
|
sty flist+1
|
||||||
|
jsr bmerge
|
||||||
|
clc
|
||||||
|
rts
|
||||||
|
fok ; insert to list
|
||||||
|
ldy #1
|
||||||
|
lda p+1 ;lda (p2),y
|
||||||
|
sta (p3),y
|
||||||
|
dey
|
||||||
|
lda p ;lda (p2),y
|
||||||
|
sta (p3),y
|
||||||
|
lda p3
|
||||||
|
sta (p2),y
|
||||||
|
iny
|
||||||
|
lda p3+1
|
||||||
|
sta (p2),y
|
||||||
|
|
||||||
|
lda p3
|
||||||
|
ldy p3+1
|
||||||
|
jsr bmerge
|
||||||
|
lda p2
|
||||||
|
ldy p2+1
|
||||||
|
jsr bmerge
|
||||||
|
clc
|
||||||
|
rts
|
||||||
|
.)
|
||||||
|
|
||||||
|
/* get adress of buffer */
|
||||||
|
&getbadr .(
|
||||||
|
lda slotladr,x
|
||||||
|
ldy slothadr,x
|
||||||
|
clc
|
||||||
|
rts
|
||||||
|
.)
|
||||||
|
|
||||||
|
/* get length of buffer */
|
||||||
|
&getblen .(
|
||||||
|
lda slotllen,x
|
||||||
|
ldy slothlen,x
|
||||||
|
clc
|
||||||
|
rts
|
||||||
|
.)
|
||||||
|
|
||||||
|
/* get free buffer-ID slot */
|
||||||
|
getbslot .(
|
||||||
|
ldx #0
|
||||||
|
l0
|
||||||
|
clc
|
||||||
|
lda slotladr,x
|
||||||
|
ora slothadr,x
|
||||||
|
beq found
|
||||||
|
inx
|
||||||
|
cpx #MAXSLOT
|
||||||
|
bcc l0
|
||||||
|
found
|
||||||
|
rts
|
||||||
|
.)
|
||||||
|
|
||||||
|
/* check if two buffers (i.e. a/y plus following) can be merged */
|
||||||
|
bmerge .(
|
||||||
|
sta p
|
||||||
|
sty p+1
|
||||||
|
ldy #2
|
||||||
|
clc
|
||||||
|
lda (p),y
|
||||||
|
adc p
|
||||||
|
sta p3
|
||||||
|
iny
|
||||||
|
lda (p),y
|
||||||
|
adc p+1
|
||||||
|
sta p3+1
|
||||||
|
ldy #0
|
||||||
|
lda (p),y
|
||||||
|
cmp p3
|
||||||
|
bne nomerge
|
||||||
|
iny
|
||||||
|
lda (p),y
|
||||||
|
cmp p3+1
|
||||||
|
bne nomerge
|
||||||
|
merge
|
||||||
|
ldy #2
|
||||||
|
clc
|
||||||
|
lda (p3),y
|
||||||
|
adc (p),y
|
||||||
|
sta (p),y
|
||||||
|
iny
|
||||||
|
lda (p3),y
|
||||||
|
adc (p),y
|
||||||
|
sta (p),y
|
||||||
|
ldy #0
|
||||||
|
lda (p3),y
|
||||||
|
sta (p),y
|
||||||
|
iny
|
||||||
|
lda (p3),y
|
||||||
|
sta (p),y
|
||||||
|
nomerge
|
||||||
|
clc
|
||||||
|
rts
|
||||||
|
.)
|
||||||
|
|
||||||
|
.)
|
||||||
|
|
||||||
|
PRGEND
|
||||||
|
|
||||||
36
xa-2.3.5/loader/test.a
Normal file
36
xa-2.3.5/loader/test.a
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
|
||||||
|
.fopt 1, "filename"
|
||||||
|
.(
|
||||||
|
.text
|
||||||
|
&absv = 4
|
||||||
|
lda #>test+4
|
||||||
|
bne test
|
||||||
|
*=$8000 ;*
|
||||||
|
lda <test
|
||||||
|
lo bvc lo
|
||||||
|
*=
|
||||||
|
test
|
||||||
|
lda (0),y
|
||||||
|
jmp (test)
|
||||||
|
.word *
|
||||||
|
|
||||||
|
.data
|
||||||
|
+bla
|
||||||
|
.word test
|
||||||
|
.byt <test-8, >test-8
|
||||||
|
.)
|
||||||
|
.text
|
||||||
|
nop
|
||||||
|
|
||||||
|
; .fopt 1, "filename"
|
||||||
|
|
||||||
|
lda bsslab
|
||||||
|
lda zerolab
|
||||||
|
lda #absv*2
|
||||||
|
.bss
|
||||||
|
bsslab
|
||||||
|
.dsb 20,1
|
||||||
|
.zero
|
||||||
|
zerolab
|
||||||
|
.dsb 20
|
||||||
|
|
||||||
28
xa-2.3.5/loader/test2.a
Normal file
28
xa-2.3.5/loader/test2.a
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
|
||||||
|
*=$8000
|
||||||
|
.(
|
||||||
|
; .text
|
||||||
|
lda #>test+4
|
||||||
|
bne test
|
||||||
|
;*=*
|
||||||
|
lda <test
|
||||||
|
;*=
|
||||||
|
test
|
||||||
|
lda (0),y
|
||||||
|
jmp (test)
|
||||||
|
; .data
|
||||||
|
+bla
|
||||||
|
.word test
|
||||||
|
.byt <test-1, >test-1
|
||||||
|
.)
|
||||||
|
; .text
|
||||||
|
nop
|
||||||
|
lda bsslab
|
||||||
|
lda zerolab
|
||||||
|
; .bss
|
||||||
|
bsslab
|
||||||
|
.dsb 20,1
|
||||||
|
; .zero
|
||||||
|
zerolab
|
||||||
|
.dsb 20
|
||||||
|
|
||||||
3
xa-2.3.5/loader/test3.a
Normal file
3
xa-2.3.5/loader/test3.a
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
lda #label
|
||||||
|
lab2
|
||||||
3
xa-2.3.5/man/README
Normal file
3
xa-2.3.5/man/README
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
Also look at ../doc/ for previous documentation files and the Change log.
|
||||||
|
|
||||||
|
Cameron Kaiser
|
||||||
58
xa-2.3.5/man/file65.1
Normal file
58
xa-2.3.5/man/file65.1
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
.TH FILE65 "1" "11 April 2006"
|
||||||
|
|
||||||
|
.SH NAME
|
||||||
|
file65 \- print information for o65 object files
|
||||||
|
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B file65
|
||||||
|
[\fIOPTION\fR]... \fIFILE\fR...
|
||||||
|
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.B file65
|
||||||
|
prints file information for files in the o65 object format.
|
||||||
|
|
||||||
|
.SH OPTIONS
|
||||||
|
.TP
|
||||||
|
.B \-V
|
||||||
|
Print undefined and global labels.
|
||||||
|
.TP
|
||||||
|
.B \-P
|
||||||
|
Print the segment end addresses (suitable for the
|
||||||
|
.BR xa (1)
|
||||||
|
command line parameter
|
||||||
|
.BR \-b ).
|
||||||
|
.TP
|
||||||
|
.B \-a offset
|
||||||
|
Print
|
||||||
|
.BR xa (1)
|
||||||
|
"ROMmable" parameter for another file behind this one in
|
||||||
|
the same ROM, located at the specified offset.
|
||||||
|
.TP
|
||||||
|
.B \-A offset
|
||||||
|
Does the same thing as
|
||||||
|
.B \-a
|
||||||
|
but only prints the starting address of the next file in the ROM.
|
||||||
|
.TP
|
||||||
|
.B \-\-help
|
||||||
|
Show summary of options.
|
||||||
|
.TP
|
||||||
|
.B \-\-version
|
||||||
|
Show version of program.
|
||||||
|
|
||||||
|
.SH "SEE ALSO"
|
||||||
|
.BR ldo65 (1),
|
||||||
|
.BR printcbm (1),
|
||||||
|
.BR reloc65 (1),
|
||||||
|
.BR uncpk (1),
|
||||||
|
.BR xa (1),
|
||||||
|
.BR dxa (1)
|
||||||
|
|
||||||
|
.SH AUTHOR
|
||||||
|
This manual page was written by David Weinehall <tao@acc.umu.se>
|
||||||
|
and Cameron Kaiser <ckaiser@floodgap.com>.
|
||||||
|
Original xa package (C)1989-1997 Andre Fachat. Additional changes
|
||||||
|
(C)1989-2006 Andre Fachat, Jolse Maginnis, David Weinehall and
|
||||||
|
Cameron Kaiser. The current maintainer is Cameron Kaiser.
|
||||||
|
|
||||||
|
.SH WEBSITE
|
||||||
|
http://www.floodgap.com/retrotech/xa/
|
||||||
60
xa-2.3.5/man/ldo65.1
Normal file
60
xa-2.3.5/man/ldo65.1
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
.TH LDO65 "1" "11 April 2006"
|
||||||
|
|
||||||
|
.SH NAME
|
||||||
|
ldo65 \- linker for o65 object files
|
||||||
|
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B ldo65
|
||||||
|
[\fIOPTION\fR]... \fIFILE\fR...
|
||||||
|
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.B ldo65
|
||||||
|
is a linker for files in the `o65' object format, formerly
|
||||||
|
.B ld65
|
||||||
|
but renamed to avoid conflicts with the
|
||||||
|
.B cc65
|
||||||
|
package (a separate product).
|
||||||
|
|
||||||
|
.SH OPTIONS
|
||||||
|
.TP
|
||||||
|
.B \-b? addr
|
||||||
|
Relocate segment
|
||||||
|
.B ?
|
||||||
|
to
|
||||||
|
.BR addr \&.
|
||||||
|
.B ?
|
||||||
|
must be either t, d, b or z to indicate the text, data, bss or zero
|
||||||
|
segment respectively. See the
|
||||||
|
.BR xa (1)
|
||||||
|
man page for an explanation.
|
||||||
|
.TP
|
||||||
|
.B \-o filename
|
||||||
|
Set output filename. The default is
|
||||||
|
.BR a.o65 \&.
|
||||||
|
.TP
|
||||||
|
.B \-G
|
||||||
|
Suppress writing of globals.
|
||||||
|
.TP
|
||||||
|
.B \-\-help
|
||||||
|
Show summary of options.
|
||||||
|
.TP
|
||||||
|
.B \-\-version
|
||||||
|
Show version of program.
|
||||||
|
|
||||||
|
.SH "SEE ALSO"
|
||||||
|
.BR file65 (1),
|
||||||
|
.BR printcbm (1),
|
||||||
|
.BR reloc65 (1),
|
||||||
|
.BR uncpk (1),
|
||||||
|
.BR dxa (1),
|
||||||
|
.BR xa (1)
|
||||||
|
|
||||||
|
.SH AUTHOR
|
||||||
|
This manual page was written by David Weinehall <tao@acc.umu.se>
|
||||||
|
and Cameron Kaiser <ckaiser@floodgap.com>.
|
||||||
|
Original xa package (C)1989-1997 Andre Fachat. Additional changes
|
||||||
|
(C)1989-2006 Andre Fachat, Jolse Maginnis, David Weinehall and
|
||||||
|
Cameron Kaiser. The current maintainer is Cameron Kaiser.
|
||||||
|
|
||||||
|
.SH WEBSITE
|
||||||
|
http://www.floodgap.com/retrotech/xa/
|
||||||
37
xa-2.3.5/man/printcbm.1
Normal file
37
xa-2.3.5/man/printcbm.1
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
.TH PRINTCBM "1" "11 April 2006"
|
||||||
|
|
||||||
|
.SH NAME
|
||||||
|
printcbm \- list a Commodore BASIC file
|
||||||
|
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B printcbm
|
||||||
|
\fIFILE\fR
|
||||||
|
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.B printcbm
|
||||||
|
lists all lines of the specified Commodore BASIC program.
|
||||||
|
|
||||||
|
.SH OPTIONS
|
||||||
|
.TP
|
||||||
|
.B \-\-help
|
||||||
|
Show summary of options.
|
||||||
|
.TP
|
||||||
|
.B \-\-version
|
||||||
|
Show version of program.
|
||||||
|
|
||||||
|
.SH "SEE ALSO"
|
||||||
|
.BR file65 (1),
|
||||||
|
.BR ldo65 (1),
|
||||||
|
.BR reloc65 (1),
|
||||||
|
.BR uncpk (1),
|
||||||
|
.BR dxa (1),
|
||||||
|
.BR xa (1)
|
||||||
|
|
||||||
|
.SH AUTHOR
|
||||||
|
This manual page was written by David Weinehall <tao@acc.umu.se>.
|
||||||
|
Original xa package (C)1989-1997 Andre Fachat. Additional changes
|
||||||
|
(C)1989-2006 Andre Fachat, Jolse Maginnis, David Weinehall and
|
||||||
|
Cameron Kaiser. The current maintainer is Cameron Kaiser.
|
||||||
|
|
||||||
|
.SH WEBSITE
|
||||||
|
http://www.floodgap.com/retrotech/xa/
|
||||||
68
xa-2.3.5/man/reloc65.1
Normal file
68
xa-2.3.5/man/reloc65.1
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
.TH RELOC65 "1" "11 April 2006"
|
||||||
|
|
||||||
|
.SH NAME
|
||||||
|
reloc65 \- relocator for o65 object files
|
||||||
|
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B reloc65
|
||||||
|
[\fIOPTION\fR]... \fIFILE\fR...
|
||||||
|
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.B reloc65
|
||||||
|
is a relocator for files in the
|
||||||
|
.B o65
|
||||||
|
object format.
|
||||||
|
|
||||||
|
.SH OPTIONS
|
||||||
|
.TP
|
||||||
|
.B \-o filename
|
||||||
|
Set output filename. The default is
|
||||||
|
.BR a.o65 \&.
|
||||||
|
.TP
|
||||||
|
.B \-b? addr
|
||||||
|
Relocate segment
|
||||||
|
.B ?
|
||||||
|
to
|
||||||
|
.BR addr \&.
|
||||||
|
.B ?
|
||||||
|
should be t, d, b or z to represent the text, data, bss or zero
|
||||||
|
segment respectively. See the
|
||||||
|
.BR xa (1)
|
||||||
|
man page for an explanation.
|
||||||
|
.TP
|
||||||
|
.B \-x?
|
||||||
|
Extract segment
|
||||||
|
.B ?
|
||||||
|
from the file instead of writing back the whole
|
||||||
|
file. Valid arguments are t and d for the text or data segment
|
||||||
|
respectively. Not valid for bss or zero.
|
||||||
|
.TP
|
||||||
|
.B \-X
|
||||||
|
Extract text and data segment together
|
||||||
|
from the file instead of writing back the whole
|
||||||
|
file. Relocating data segment to the end of the text segment
|
||||||
|
(ignoring the \-xd option) before extracting.
|
||||||
|
.TP
|
||||||
|
.B \-\-help
|
||||||
|
Show summary of options.
|
||||||
|
.TP
|
||||||
|
.B \-\-version
|
||||||
|
Show version of program.
|
||||||
|
|
||||||
|
.SH "SEE ALSO"
|
||||||
|
.BR file65 (1),
|
||||||
|
.BR ldo65 (1),
|
||||||
|
.BR printcbm (1),
|
||||||
|
.BR uncpk (1),
|
||||||
|
.BR dxa (1),
|
||||||
|
.BR xa (1)
|
||||||
|
|
||||||
|
.SH AUTHOR
|
||||||
|
This manual page was written by David Weinehall <tao@acc.umu.se>
|
||||||
|
and Cameron Kaiser <ckaiser@floodgap.com>.
|
||||||
|
Original xa package (C)1989-1997 Andre Fachat. Additional changes
|
||||||
|
(C)1989-2006 Andre Fachat, Jolse Maginnis, David Weinehall and
|
||||||
|
Cameron Kaiser. The current maintainer is Cameron Kaiser.
|
||||||
|
|
||||||
|
.SH WEBSITE
|
||||||
|
http://www.floodgap.com/retrotech/xa/
|
||||||
77
xa-2.3.5/man/uncpk.1
Normal file
77
xa-2.3.5/man/uncpk.1
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
.TH UNCPK "1" "11 April 2006"
|
||||||
|
|
||||||
|
.SH NAME
|
||||||
|
uncpk \- manage c64 cpk archives
|
||||||
|
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B uncpk
|
||||||
|
[\fIOPTION\fR]... \fIFILE\fR...
|
||||||
|
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.B uncpk
|
||||||
|
is an archive tool for Commodore 64 .cpk-format archives.
|
||||||
|
|
||||||
|
.SH OPTIONS
|
||||||
|
.TP
|
||||||
|
.B c
|
||||||
|
Create an archive.
|
||||||
|
.TP
|
||||||
|
.B x
|
||||||
|
Extract from an archive.
|
||||||
|
.TP
|
||||||
|
.B l
|
||||||
|
List contents of archive.
|
||||||
|
.TP
|
||||||
|
.B a
|
||||||
|
Add a file to the archive.
|
||||||
|
.TP
|
||||||
|
.B v
|
||||||
|
Verbose output.
|
||||||
|
.TP
|
||||||
|
.B \-\-help
|
||||||
|
Show summary of options.
|
||||||
|
.TP
|
||||||
|
.B \-\-version
|
||||||
|
Show version of program.
|
||||||
|
|
||||||
|
.SH EXAMPLES
|
||||||
|
.TP
|
||||||
|
.B uncpk c foo.cpk bar
|
||||||
|
Create archive
|
||||||
|
.B foo.cpk
|
||||||
|
with the single file
|
||||||
|
.B bar
|
||||||
|
inside it.
|
||||||
|
.TP
|
||||||
|
.B uncpk a foo.cpk bar
|
||||||
|
Add file
|
||||||
|
.B bar
|
||||||
|
to archive
|
||||||
|
.B foo.cpk
|
||||||
|
(which must already exist).
|
||||||
|
.TP
|
||||||
|
.B uncpk x foo.cpk
|
||||||
|
Extract all files from archive
|
||||||
|
.BR foo.cpk \&.
|
||||||
|
.TP
|
||||||
|
.B uncpk l foo.cpk
|
||||||
|
List contents of archive
|
||||||
|
.BR foo.cpk \&.
|
||||||
|
|
||||||
|
.SH "SEE ALSO"
|
||||||
|
.BR file65 (1),
|
||||||
|
.BR ldo65 (1),
|
||||||
|
.BR printcbm (1),
|
||||||
|
.BR reloc65 (1),
|
||||||
|
.BR dxa (1),
|
||||||
|
.BR xa (1)
|
||||||
|
|
||||||
|
.SH AUTHOR
|
||||||
|
This manual page was written by David Weinehall <tao@acc.umu.se>
|
||||||
|
and Cameron Kaiser <ckaiser@floodgap.com>.
|
||||||
|
Original xa package (C)1989-1997 Andre Fachat. Additional changes
|
||||||
|
(C)1989-2006 Andre Fachat, Jolse Maginnis, David Weinehall and
|
||||||
|
Cameron Kaiser. The current maintainer is Cameron Kaiser.
|
||||||
|
|
||||||
|
.SH WEBSITE
|
||||||
|
http://www.floodgap.com/retrotech/xa/
|
||||||
837
xa-2.3.5/man/xa.1
Normal file
837
xa-2.3.5/man/xa.1
Normal file
|
|
@ -0,0 +1,837 @@
|
||||||
|
.TH XA "1" "7 February 2009"
|
||||||
|
|
||||||
|
.SH NAME
|
||||||
|
xa \- 6502/R65C02/65816 cross-assembler
|
||||||
|
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B xa
|
||||||
|
[\fIOPTION\fR]... \fIFILE\fR
|
||||||
|
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.B xa
|
||||||
|
is a multi-pass cross-assembler for the 8-bit processors in the 6502 series
|
||||||
|
(such as
|
||||||
|
the 6502, 65C02, 6504, 6507,
|
||||||
|
6510, 7501, 8500, 8501 and 8502), the Rockwell R65C02, and
|
||||||
|
the 16-bit 65816 processor. For a description of syntax, see
|
||||||
|
.B ASSEMBLER SYNTAX
|
||||||
|
further in this manual page.
|
||||||
|
|
||||||
|
.SH OPTIONS
|
||||||
|
.TP
|
||||||
|
.B \-v
|
||||||
|
Verbose output.
|
||||||
|
.TP
|
||||||
|
.B \-x
|
||||||
|
Use old filename behaviour (overrides
|
||||||
|
.BR \-o ,
|
||||||
|
.B \-e
|
||||||
|
and
|
||||||
|
.BR \-l ).
|
||||||
|
This option is now deprecated.
|
||||||
|
.TP
|
||||||
|
.B \-C
|
||||||
|
No CMOS opcodes (default is to allow R65C02 opcodes)
|
||||||
|
.TP
|
||||||
|
.B \-W
|
||||||
|
No 65816 opcodes (default).
|
||||||
|
.TP
|
||||||
|
.B \-w
|
||||||
|
Allow 65816 opcodes.
|
||||||
|
.TP
|
||||||
|
.B \-B
|
||||||
|
Show lines with block open/close (see
|
||||||
|
.BR PSEUDO-OPS ).
|
||||||
|
.TP
|
||||||
|
.B \-c
|
||||||
|
Produce o65 object files instead of executable files
|
||||||
|
(no linking performed); files may contain undefined references.
|
||||||
|
.TP
|
||||||
|
.B \-o filename
|
||||||
|
Set output filename. The default is
|
||||||
|
.BR a.o65 ;
|
||||||
|
use the special filename
|
||||||
|
.BR \-
|
||||||
|
to output to standard output.
|
||||||
|
.TP
|
||||||
|
.B \-e filename
|
||||||
|
Set errorlog filename, default is none.
|
||||||
|
.TP
|
||||||
|
.B \-l filename
|
||||||
|
Set labellist filename, default is none. This is the symbol table and can
|
||||||
|
be used by disassemblers such as
|
||||||
|
.BR dxa (1)
|
||||||
|
to reconstruct source.
|
||||||
|
.TP
|
||||||
|
.B \-r
|
||||||
|
Add cross-reference list to labellist (requires
|
||||||
|
.BR \-l ).
|
||||||
|
.TP
|
||||||
|
.B \-M
|
||||||
|
Allow colons to appear in comments; for MASM compatibility. This does
|
||||||
|
not affect colon interpretation elsewhere.
|
||||||
|
.TP
|
||||||
|
.B \-R
|
||||||
|
Start assembler in relocating mode.
|
||||||
|
.TP
|
||||||
|
.B \-Llabel
|
||||||
|
Defines
|
||||||
|
.B label
|
||||||
|
as an absolute (but undefined) label even when linking.
|
||||||
|
.TP
|
||||||
|
.B \-b? addr
|
||||||
|
Set segment base for segment
|
||||||
|
.B ?
|
||||||
|
to address
|
||||||
|
.BR addr \&.
|
||||||
|
.B ?
|
||||||
|
should be t, d, b or z for text, data, bss or zero segments, respectively.
|
||||||
|
.TP
|
||||||
|
.B \-A addr
|
||||||
|
Make text segment start at an address such that when the file
|
||||||
|
starts at address
|
||||||
|
.BR addr ,
|
||||||
|
relocation is not necessary. Overrides
|
||||||
|
.BR \-bt ;
|
||||||
|
other segments still have to be taken care of with
|
||||||
|
.BR \-b \&.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B \-G
|
||||||
|
Suppress list of exported globals.
|
||||||
|
.TP
|
||||||
|
.B \-DDEF=TEXT
|
||||||
|
Define a preprocessor macro on the command line (see
|
||||||
|
.BR PREPROCESSOR ).
|
||||||
|
.TP
|
||||||
|
.B \-I dir
|
||||||
|
Add directory
|
||||||
|
.B dir
|
||||||
|
to the include path (before
|
||||||
|
.BR XAINPUT ;
|
||||||
|
see
|
||||||
|
.BR ENVIRONMENT ).
|
||||||
|
.TP
|
||||||
|
.B \-O charset
|
||||||
|
Define the output charset for character strings. Currently supported are ASCII
|
||||||
|
(default), PETSCII (Commodore ASCII),
|
||||||
|
PETSCREEN (Commodore screen codes) and HIGH (set high bit on all
|
||||||
|
characters).
|
||||||
|
.TP
|
||||||
|
.B \-p?
|
||||||
|
Set the alternative preprocessor character to
|
||||||
|
.BR ? .
|
||||||
|
This is useful when you wish to use
|
||||||
|
.BR cpp (1)
|
||||||
|
and the built-in preprocessor at the same time (see
|
||||||
|
.BR PREPROCESSOR ).
|
||||||
|
Characters may need to be quoted for your shell (example:
|
||||||
|
.B \-p'~'
|
||||||
|
).
|
||||||
|
.TP
|
||||||
|
.B \-\-help
|
||||||
|
Show summary of options.
|
||||||
|
.TP
|
||||||
|
.B \-\-version
|
||||||
|
Show version of program.
|
||||||
|
|
||||||
|
.SH ASSEMBLER SYNTAX
|
||||||
|
|
||||||
|
An introduction to 6502 assembly language programming and mnemonics is
|
||||||
|
beyond the scope of this manual page. We invite you to investigate any
|
||||||
|
number of the excellent books on the subject; one useful title is "Machine
|
||||||
|
Language For Beginners" by Richard Mansfield (COMPUTE!), covering the Atari,
|
||||||
|
Commodore and Apple 8-bit systems, and is widely available on the used market.
|
||||||
|
.LP
|
||||||
|
.B xa
|
||||||
|
supports both the standard NMOS 6502 opcodes as well as the Rockwell
|
||||||
|
CMOS opcodes used in the 65C02 (R65C02). With the
|
||||||
|
.B \-w
|
||||||
|
option,
|
||||||
|
.B xa
|
||||||
|
will also accept opcodes for the 65816. NMOS 6502
|
||||||
|
undocumented opcodes are intentionally not supported, and should be entered
|
||||||
|
manually using the
|
||||||
|
.B \.byte
|
||||||
|
pseudo-op (see
|
||||||
|
.BR PSEUDO-OPS ).
|
||||||
|
Due to conflicts between the R65C02 and 65816 instruction sets and
|
||||||
|
undocumented instructions on the NMOS 6502, their use is discouraged.
|
||||||
|
.LP
|
||||||
|
In general,
|
||||||
|
.B xa
|
||||||
|
accepts the more-or-less standard 6502 assembler format as popularised by
|
||||||
|
MASM and TurboAssembler. Values and addresses
|
||||||
|
can be expressed either as literals, or as expressions; to wit,
|
||||||
|
.TP 10
|
||||||
|
.B 123
|
||||||
|
decimal value
|
||||||
|
.TP
|
||||||
|
.B $234
|
||||||
|
hexadecimal value
|
||||||
|
.TP
|
||||||
|
.B &123
|
||||||
|
octal
|
||||||
|
.TP
|
||||||
|
.B %010110
|
||||||
|
binary
|
||||||
|
.TP
|
||||||
|
.B *
|
||||||
|
current value of the program counter
|
||||||
|
.LP
|
||||||
|
The ASCII value of any quoted character is
|
||||||
|
inserted directly into the program text (example:
|
||||||
|
.B """A"""
|
||||||
|
inserts the byte "A" into the output stream); see also the
|
||||||
|
.B PSEUDO-OPS
|
||||||
|
section. This is affected by the currently selected character set, if any.
|
||||||
|
.LP
|
||||||
|
.B Labels
|
||||||
|
define locations within the program text, just as in other multi-pass
|
||||||
|
assemblers. A label is defined by anything that is not an opcode; for
|
||||||
|
example, a line such as
|
||||||
|
.IP
|
||||||
|
.B label1 lda #0
|
||||||
|
.LP
|
||||||
|
defines
|
||||||
|
.B label1
|
||||||
|
to be the current location of the program counter (thus the
|
||||||
|
address of the
|
||||||
|
.B LDA
|
||||||
|
opcode). A label can be explicitly defined by assigning it the value of
|
||||||
|
an expression, such as
|
||||||
|
.IP
|
||||||
|
.B label2 = $d000
|
||||||
|
.LP
|
||||||
|
which defines
|
||||||
|
.B label2
|
||||||
|
to be the address $d000, namely, the start of the VIC-II register block on
|
||||||
|
Commodore 64 computers. The program counter
|
||||||
|
.B *
|
||||||
|
is considered to be a special kind of label, and can be assigned to with
|
||||||
|
statements such as
|
||||||
|
.IP
|
||||||
|
.B * = $c000
|
||||||
|
.LP
|
||||||
|
which sets the program counter to decimal location 49152. With the exception
|
||||||
|
of the program counter, labels cannot be assigned multiple times. To explicitly
|
||||||
|
declare redefinition of a label, place a - (dash) before it, e.g.,
|
||||||
|
.IP
|
||||||
|
.B \-label2 = $d020
|
||||||
|
.LP
|
||||||
|
which sets
|
||||||
|
.B label2
|
||||||
|
to the Commodore 64 border colour register. The scope of a label is affected
|
||||||
|
by the block it resides within (see
|
||||||
|
.B PSEUDO-OPS
|
||||||
|
for block instructions). A label may also be hard-specified with the
|
||||||
|
.B \-L
|
||||||
|
command line option.
|
||||||
|
.LP
|
||||||
|
For those instructions where the accumulator is the implied argument (such as
|
||||||
|
.B asl
|
||||||
|
and
|
||||||
|
.BR lsr ;
|
||||||
|
.B inc
|
||||||
|
and
|
||||||
|
.B dec
|
||||||
|
on R65C02; etc.), the idiom of explicitly specifying the accumulator with
|
||||||
|
.B a
|
||||||
|
is unnecessary as the proper form will be selected if there is no explicit
|
||||||
|
argument. In fact, for consistency with label handing, if there is a label
|
||||||
|
named
|
||||||
|
.BR a ,
|
||||||
|
this will actually generate code referencing that label as a memory
|
||||||
|
location and not the accumulator. Otherwise, the assembler will complain.
|
||||||
|
.LP
|
||||||
|
Labels and opcodes may take
|
||||||
|
.B expressions
|
||||||
|
as their arguments to allow computed values, and may themselves reference
|
||||||
|
other labels and/or the program counter. An expression such as
|
||||||
|
.B lab1+1
|
||||||
|
(which operates on the current value of label
|
||||||
|
.B lab1
|
||||||
|
and increments it by one) may use the following operands, given from highest
|
||||||
|
to lowest priority:
|
||||||
|
.TP 8
|
||||||
|
.B *
|
||||||
|
multiplication (priority 10)
|
||||||
|
.TP
|
||||||
|
.B /
|
||||||
|
integer division (priority 10)
|
||||||
|
.TP
|
||||||
|
.B +
|
||||||
|
addition (priority 9)
|
||||||
|
.TP
|
||||||
|
.B \-
|
||||||
|
subtraction (9)
|
||||||
|
.TP
|
||||||
|
.B <<
|
||||||
|
shift left (8)
|
||||||
|
.TP
|
||||||
|
.B >>
|
||||||
|
shift right (8)
|
||||||
|
.TP
|
||||||
|
.B >= =>
|
||||||
|
greater than or equal to (7)
|
||||||
|
.TP
|
||||||
|
.B <
|
||||||
|
greater than (7)
|
||||||
|
.TP
|
||||||
|
.B <= =<
|
||||||
|
less than or equal to (7)
|
||||||
|
.TP
|
||||||
|
.B <
|
||||||
|
less than (7)
|
||||||
|
.TP
|
||||||
|
.B =
|
||||||
|
equal to (6)
|
||||||
|
.TP
|
||||||
|
.B <> ><
|
||||||
|
does not equal (6)
|
||||||
|
.TP
|
||||||
|
.B &
|
||||||
|
bitwise AND (5)
|
||||||
|
.TP
|
||||||
|
.B ^
|
||||||
|
bitwise XOR (4)
|
||||||
|
.TP
|
||||||
|
.B |
|
||||||
|
bitwise OR (3)
|
||||||
|
.TP
|
||||||
|
.B &&
|
||||||
|
logical AND (2)
|
||||||
|
.TP
|
||||||
|
.B ||
|
||||||
|
logical OR (1)
|
||||||
|
.LP
|
||||||
|
Parentheses are valid. When redefining a label, combining arithmetic or
|
||||||
|
bitwise operators with the = (equals) operator such as
|
||||||
|
.B +=
|
||||||
|
and so on are valid, e.g.,
|
||||||
|
.IP
|
||||||
|
.B \-redeflabel += (label12/4)
|
||||||
|
.LP
|
||||||
|
Normally,
|
||||||
|
.B xa
|
||||||
|
attempts to ascertain the value of the operand and (when referring to
|
||||||
|
a memory location) use zero page,
|
||||||
|
16-bit or (for 65816) 24-bit addressing where appropriate and where
|
||||||
|
supported by the particular opcode. This generates smaller and faster
|
||||||
|
code, and is almost always preferable.
|
||||||
|
.LP
|
||||||
|
Nevertheless, you can use these prefix operators to force a particular
|
||||||
|
rendering of the operand. Those that generate an eight bit result can also be
|
||||||
|
used in 8-bit addressing modes, such as immediate and zero page.
|
||||||
|
.TP
|
||||||
|
.B <
|
||||||
|
low byte of expression, e.g.,
|
||||||
|
.B lda #<vector
|
||||||
|
.TP
|
||||||
|
.B >
|
||||||
|
high byte of expression
|
||||||
|
.TP
|
||||||
|
.B !
|
||||||
|
in situations where the expression could be understood as either an absolute
|
||||||
|
or zero page value, do not attempt to optimize to a zero page argument
|
||||||
|
for those opcodes that support it (i.e., keep as 16 bit word)
|
||||||
|
.TP
|
||||||
|
.B @
|
||||||
|
render as 24-bit quantity for 65816 (must specify
|
||||||
|
.B \-w
|
||||||
|
command-line option).
|
||||||
|
.B This is required to specify any
|
||||||
|
.B 24-bit quantity!
|
||||||
|
.TP
|
||||||
|
.B `
|
||||||
|
force further optimization, even if the length of the instruction cannot
|
||||||
|
be reliably determined (see
|
||||||
|
.BR NOTES'N'BUGS )
|
||||||
|
.LP
|
||||||
|
Expressions can occur as arguments to opcodes or within the preprocessor
|
||||||
|
(see
|
||||||
|
.B PREPROCESSOR
|
||||||
|
for syntax). For example,
|
||||||
|
.IP
|
||||||
|
.B lda label2+1
|
||||||
|
.LP
|
||||||
|
takes the value at
|
||||||
|
.B label2+1
|
||||||
|
(using our previous label's value, this would be $d021), and will be assembled
|
||||||
|
as
|
||||||
|
.B $ad $21 $d0
|
||||||
|
to disk. Similarly,
|
||||||
|
.IP
|
||||||
|
.B lda #<label2
|
||||||
|
.LP
|
||||||
|
will take the lowest 8 bits of
|
||||||
|
.B label2
|
||||||
|
(i.e., $20), and assign them to the accumulator (assembling the instruction as
|
||||||
|
.B $a9 $20
|
||||||
|
to disk).
|
||||||
|
.LP
|
||||||
|
Comments are specified with a semicolon (;), such as
|
||||||
|
.IP
|
||||||
|
.B ;this is a comment
|
||||||
|
.LP
|
||||||
|
They can also be specified in the C language style, using
|
||||||
|
.B /* */
|
||||||
|
and
|
||||||
|
.B //
|
||||||
|
which are understood at the
|
||||||
|
.B PREPROCESSOR
|
||||||
|
level (q.v.).
|
||||||
|
.LP
|
||||||
|
Normally, the colon (:) separates statements, such as
|
||||||
|
.IP
|
||||||
|
.B label4 lda #0:sta $d020
|
||||||
|
.LP
|
||||||
|
or
|
||||||
|
.IP
|
||||||
|
.B label2: lda #2
|
||||||
|
.LP
|
||||||
|
(note the use of a colon for specifying a label, similar to some other
|
||||||
|
assemblers, which
|
||||||
|
.B xa
|
||||||
|
also understands with or without the colon). This also applies to semicolon
|
||||||
|
comments, such that
|
||||||
|
.IP
|
||||||
|
.B ; a comment:lda #0
|
||||||
|
.LP
|
||||||
|
is understood as a comment followed by an opcode. To defeat this, use the
|
||||||
|
.B \-M
|
||||||
|
command line option to allow colons within comments. This does not apply to
|
||||||
|
.B /* */
|
||||||
|
and
|
||||||
|
.B //
|
||||||
|
comments, which are dealt with at the preprocessor level (q.v.).
|
||||||
|
|
||||||
|
.SH PSEUDO-OPS
|
||||||
|
|
||||||
|
.B Pseudo-ops
|
||||||
|
are false opcodes used by the assembler to denote meta- or inlined commands.
|
||||||
|
Like most assemblers,
|
||||||
|
.B xa
|
||||||
|
has a rich set.
|
||||||
|
.TP
|
||||||
|
.B .byt value1,value2,value3,...
|
||||||
|
Specifies a string of bytes to be directly placed into the assembled object.
|
||||||
|
The arguments may be expressions. Any number of bytes can be specified.
|
||||||
|
.TP
|
||||||
|
.B .asc """text1""","text2",...
|
||||||
|
Specifies a character string which will be inserted into the assembled
|
||||||
|
object. Strings are understood according to the currently specified
|
||||||
|
character set; for example, if ASCII is specified, they will be rendered as
|
||||||
|
ASCII, and if PETSCII is specified, they will be translated into the equivalent
|
||||||
|
Commodore ASCII equivalent. Other non-standard ASCIIs such as ATASCII for
|
||||||
|
Atari computers should use the ASCII equivalent characters; graphic and
|
||||||
|
control characters should be specified explicitly using
|
||||||
|
.B .byt
|
||||||
|
for the precise character you want. Note that
|
||||||
|
when specifying the argument of an opcode,
|
||||||
|
.B .asc
|
||||||
|
is not necessary; the quoted character can simply be inserted (e.g.,
|
||||||
|
.B lda #"A"
|
||||||
|
), and is also affected by the current character set.
|
||||||
|
Any number of character strings can be specified.
|
||||||
|
.LP
|
||||||
|
.B .byt
|
||||||
|
and
|
||||||
|
.B .asc
|
||||||
|
are synonymous, so you can mix things such as
|
||||||
|
.B .byt $43, 22, """a character string"""
|
||||||
|
and get the expected result. The string is subject to the current character
|
||||||
|
set, but the remaining bytes are inserted wtihout modification.
|
||||||
|
.TP
|
||||||
|
.B .aasc """text1""","text2",...
|
||||||
|
Specifies a character string that is
|
||||||
|
.B always
|
||||||
|
rendered in true ASCII regardless of the current character set. Like
|
||||||
|
.BR .asc ,
|
||||||
|
it is synonymous with
|
||||||
|
.BR .byt .
|
||||||
|
.TP
|
||||||
|
.B .word value1,value2,value3...
|
||||||
|
Specifies a string of 16-bit words to be placed into the assembled object in
|
||||||
|
6502 little-endian format (that is, low-byte/high-byte). The arguments may
|
||||||
|
be expressions. Any number of words can be specified.
|
||||||
|
.TP
|
||||||
|
.B .dsb length,fillbyte
|
||||||
|
Specifies a data block; a total of
|
||||||
|
.B length
|
||||||
|
repetitions of
|
||||||
|
.B fillbyte
|
||||||
|
will be inserted into the assembled object. For example,
|
||||||
|
.B .dsb 5,$10
|
||||||
|
will insert five bytes, each being 16 decimal, into the object. The arguments
|
||||||
|
may be expressions.
|
||||||
|
.TP
|
||||||
|
.B .bin offset,length,"filename"
|
||||||
|
Inlines a binary file without further interpretation specified by
|
||||||
|
.B filename
|
||||||
|
from offset
|
||||||
|
.B offset
|
||||||
|
to length
|
||||||
|
.BR length .
|
||||||
|
This allows you to insert data such as a previously assembled object file
|
||||||
|
or an image or other binary data structure, inlined directly into this
|
||||||
|
file's object. If
|
||||||
|
.B length
|
||||||
|
is zero, then the length of
|
||||||
|
.BR filename ,
|
||||||
|
minus the offset, is used instead. The arguments may be expressions.
|
||||||
|
.TP
|
||||||
|
.B \&.(
|
||||||
|
Opens a new block for scoping. Within a block, all labels defined are local to
|
||||||
|
that block and any sub-blocks, and go out of scope as soon as the enclosing
|
||||||
|
block is closed (i.e., lexically scoped). All labels defined outside of the
|
||||||
|
block are still visible within it. To explicitly declare a global label within
|
||||||
|
a block, precede the label with
|
||||||
|
.B +
|
||||||
|
or precede it with
|
||||||
|
.B &
|
||||||
|
to declare it within the previous level only (or globally if you are only
|
||||||
|
one level deep). Sixteen levels of scoping are permitted.
|
||||||
|
.TP
|
||||||
|
.B \&.)
|
||||||
|
Closes a block.
|
||||||
|
.TP
|
||||||
|
.B \.as \.al \.xs \.xl
|
||||||
|
Only relevant in 65816 mode (with the
|
||||||
|
.B \-w
|
||||||
|
option specified). These pseudo-ops set what size accumulator and X/Y-register
|
||||||
|
should be used for future instructions;
|
||||||
|
.B .as
|
||||||
|
and
|
||||||
|
.B .xs
|
||||||
|
set 8-bit operands for the accumulator and index registers, respectively, and
|
||||||
|
.B .al
|
||||||
|
and
|
||||||
|
.B .xl
|
||||||
|
set 16-bit operands. These pseudo-ops on purpose do not automatically issue
|
||||||
|
.B sep
|
||||||
|
and
|
||||||
|
.B rep
|
||||||
|
instructions to set the specified width in the CPU;
|
||||||
|
set the processor bits as you need, or consider constructing
|
||||||
|
a macro.
|
||||||
|
.B \.al
|
||||||
|
and
|
||||||
|
.B \.xl
|
||||||
|
generate errors if
|
||||||
|
.B \-w
|
||||||
|
is not specified.
|
||||||
|
.LP
|
||||||
|
The following pseudo-ops apply primarily to relocatable .o65 objects.
|
||||||
|
A full discussion of the relocatable format is beyond the
|
||||||
|
scope of this manpage, as it is currently a format in flux. Documentation
|
||||||
|
on the proposed v1.2 format is in
|
||||||
|
.B doc/fileformat.txt
|
||||||
|
within the
|
||||||
|
.B xa
|
||||||
|
installation directory.
|
||||||
|
.TP
|
||||||
|
.B .text .data .bss .zero
|
||||||
|
These pseudo-ops switch between the different segments, .text being the actual
|
||||||
|
code section, .data being the data segment, .bss being uninitialized label
|
||||||
|
space for allocation and .zero being uninitialized zero page space for
|
||||||
|
allocation. In .bss and .zero, only labels are evaluated. These pseudo-ops
|
||||||
|
are valid in relative and absolute modes.
|
||||||
|
.TP
|
||||||
|
.B .align value
|
||||||
|
Aligns the current segment to a byte boundary (2, 4 or 256) as specified by
|
||||||
|
.B
|
||||||
|
value
|
||||||
|
(and places it in the header when relative mode is enabled). Other values
|
||||||
|
generate an error.
|
||||||
|
.TP
|
||||||
|
.B .fopt type,value1,value2,value3,...
|
||||||
|
Acts like
|
||||||
|
.B .byt/.asc
|
||||||
|
except that the values are embedded into the object file as file options.
|
||||||
|
The argument
|
||||||
|
.B type
|
||||||
|
is used to specify the file option being referenced. A table of these options
|
||||||
|
is in the relocatable o65 file format description. The remainder of the options
|
||||||
|
are interpreted as values to insert. Any number of values may be specified,
|
||||||
|
and may also be strings.
|
||||||
|
|
||||||
|
.SH PREPROCESSOR
|
||||||
|
|
||||||
|
.B xa
|
||||||
|
implements a preprocessor very similar to that of the C-language preprocessor
|
||||||
|
.BR cpp (1)
|
||||||
|
and many oddiments apply to both. For example, as in C, the use of
|
||||||
|
.B /* */
|
||||||
|
for comment delimiters is also supported in
|
||||||
|
.BR xa ,
|
||||||
|
and so are comments using the double slash
|
||||||
|
.BR // .
|
||||||
|
The preprocessor also supports continuation lines, i.e., lines ending with
|
||||||
|
a backslash (\\); the following line is then appended to it as if there were
|
||||||
|
no dividing newline. This too is handled at the preprocessor level.
|
||||||
|
.LP
|
||||||
|
For reasons of memory and complexity, the full breadth of the
|
||||||
|
.BR cpp (1)
|
||||||
|
syntax is not fully supported. In particular, macro definitions may not
|
||||||
|
be forward-defined (i.e., a macro definition can only reference a previously
|
||||||
|
defined macro definition), except for macro functions, where recursive
|
||||||
|
evaluation is supported; e.g., to
|
||||||
|
.B #define WW AA
|
||||||
|
,
|
||||||
|
.B AA
|
||||||
|
must have already been defined. Certain other directives are not supported,
|
||||||
|
nor are most standard pre-defined macros, and there are other
|
||||||
|
limits on evaluation and line length. Because the maintainers of
|
||||||
|
.B xa
|
||||||
|
recognize that some files will require more complicated preparsing than the
|
||||||
|
built-in preprocessor can supply, the preprocessor will accept
|
||||||
|
.BR cpp (1)-style
|
||||||
|
line/filename/flags output. When these lines are seen in the input file,
|
||||||
|
.B xa
|
||||||
|
will treat them as
|
||||||
|
.B cc
|
||||||
|
would, except that flags are ignored.
|
||||||
|
.B xa
|
||||||
|
does not accept files on standard input for parsing reasons, so you should
|
||||||
|
dump your
|
||||||
|
.BR cpp (1)
|
||||||
|
output to an intermediate temporary file, such as
|
||||||
|
.IP
|
||||||
|
.B cc -E test.s > test.xa
|
||||||
|
.br
|
||||||
|
.B xa test.xa
|
||||||
|
.LP
|
||||||
|
No special arguments need to be passed to
|
||||||
|
.BR xa ;
|
||||||
|
the presence of
|
||||||
|
.BR cpp (1)
|
||||||
|
output is detected automatically.
|
||||||
|
.LP
|
||||||
|
Note that passing your file through
|
||||||
|
.BR cpp (1)
|
||||||
|
may interfere with
|
||||||
|
.BR xa 's
|
||||||
|
own preprocessor directives. In this case, to mask directives from
|
||||||
|
.BR cpp (1),
|
||||||
|
use the
|
||||||
|
.B \-p
|
||||||
|
option to specify an alternative character instead of
|
||||||
|
.BR # ,
|
||||||
|
such as the tilde (e.g.,
|
||||||
|
.B \-p'~'
|
||||||
|
). With this option and argument specified, then instead of
|
||||||
|
.BR #include ,
|
||||||
|
for example, you can also use
|
||||||
|
.BR ~include ,
|
||||||
|
in addition to
|
||||||
|
.B #include
|
||||||
|
(which will also still be accepted by the
|
||||||
|
.B xa
|
||||||
|
preprocessor, assuming any survive
|
||||||
|
.BR cpp (1)).
|
||||||
|
Any character can be used, although frankly pathologic choices may lead
|
||||||
|
to amusing and frustrating glitches during parsing.
|
||||||
|
You can also use this option to defer preprocessor directives that
|
||||||
|
.BR cpp (1)
|
||||||
|
may interpret too early until the file actually gets to
|
||||||
|
.B xa
|
||||||
|
itself for processing.
|
||||||
|
.LP
|
||||||
|
The following preprocessor directives are supported.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B #include """filename"""
|
||||||
|
Inserts the contents of file
|
||||||
|
.B filename
|
||||||
|
at this position. If the file is not found, it is searched using paths
|
||||||
|
specified by the
|
||||||
|
.B \-I
|
||||||
|
command line option or the environment variable
|
||||||
|
.B XAINPUT
|
||||||
|
(q.v.). When inserted, the file will also be parsed for preprocessor
|
||||||
|
directives.
|
||||||
|
.TP
|
||||||
|
.B #echo comment
|
||||||
|
Inserts comment
|
||||||
|
.B comment
|
||||||
|
into the errorlog file, specified with the
|
||||||
|
.B \-e
|
||||||
|
command line option.
|
||||||
|
.TP
|
||||||
|
.B #print expression
|
||||||
|
Computes the value of expression
|
||||||
|
.B expression
|
||||||
|
and prints it into the errorlog file.
|
||||||
|
.TP
|
||||||
|
.B #define DEFINE text
|
||||||
|
Equates macro
|
||||||
|
.B DEFINE
|
||||||
|
with text
|
||||||
|
.B text
|
||||||
|
such that wherever
|
||||||
|
.B DEFINE
|
||||||
|
appears in the assembly source,
|
||||||
|
.B text
|
||||||
|
is substituted in its place (just like
|
||||||
|
.BR cpp (1)
|
||||||
|
would do). In addition,
|
||||||
|
.B #define
|
||||||
|
can specify macro functions like
|
||||||
|
.BR cpp (1)
|
||||||
|
such that a directive like
|
||||||
|
.B #define mult(a,b) ((a)*(b))
|
||||||
|
would generate the expected result wherever an expression of the form
|
||||||
|
.B mult(a,b)
|
||||||
|
appears in the source. This can also be specified on the command line with
|
||||||
|
the
|
||||||
|
.B \-D
|
||||||
|
option. The arguments of a macro function may be recursively evaluated,
|
||||||
|
unlike other
|
||||||
|
.BR #define s;
|
||||||
|
the preprocessor will attempt to re-evaluate any argument refencing
|
||||||
|
another preprocessor definition up to ten times before complaining.
|
||||||
|
.LP
|
||||||
|
The following directives are conditionals. If the conditional is not
|
||||||
|
satisfied, then the source code between the directive and its terminating
|
||||||
|
.B #endif
|
||||||
|
are expunged and not assembled. Up to fifteen levels of nesting are supported.
|
||||||
|
.TP
|
||||||
|
.B #endif
|
||||||
|
Closes a conditional block.
|
||||||
|
.TP
|
||||||
|
.B #else
|
||||||
|
Implements alternate path for a conditional block.
|
||||||
|
.TP
|
||||||
|
.B #ifdef DEFINE
|
||||||
|
True only if macro
|
||||||
|
.B DEFINE
|
||||||
|
is defined.
|
||||||
|
.TP
|
||||||
|
.B #ifndef DEFINE
|
||||||
|
The opposite; true only if macro
|
||||||
|
.B DEFINE
|
||||||
|
has not been previously defined.
|
||||||
|
.TP
|
||||||
|
.B #if expression
|
||||||
|
True if expression
|
||||||
|
.B expression
|
||||||
|
evaluates to non-zero.
|
||||||
|
.B expression
|
||||||
|
may reference other macros.
|
||||||
|
.TP
|
||||||
|
.B #iflused label
|
||||||
|
True if label
|
||||||
|
.B label
|
||||||
|
has been used (but not necessarily instantiated with a value).
|
||||||
|
.I This works on labels, not macros!
|
||||||
|
.TP
|
||||||
|
.B #ifldef label
|
||||||
|
True if label
|
||||||
|
.B label
|
||||||
|
is defined
|
||||||
|
.I and
|
||||||
|
assigned with a value.
|
||||||
|
.I This works on labels, not macros!
|
||||||
|
.LP
|
||||||
|
Unclosed conditional blocks at the end of included files generate warnings;
|
||||||
|
unclosed conditional blocks at the end of assembly generate an error.
|
||||||
|
.LP
|
||||||
|
.B #iflused
|
||||||
|
and
|
||||||
|
.B #ifldef
|
||||||
|
are useful for building up a library based on labels. For example,
|
||||||
|
you might use something like this in your library's code:
|
||||||
|
.IP
|
||||||
|
.B #iflused label
|
||||||
|
.br
|
||||||
|
.B #ifldef label
|
||||||
|
.br
|
||||||
|
.B #echo label already defined, library function label cannot be inserted
|
||||||
|
.br
|
||||||
|
.B #else
|
||||||
|
.br
|
||||||
|
.B label /* your code */
|
||||||
|
.br
|
||||||
|
.B #endif
|
||||||
|
.br
|
||||||
|
.B #endif
|
||||||
|
|
||||||
|
.SH ENVIRONMENT
|
||||||
|
|
||||||
|
.B xa
|
||||||
|
utilises the following environment variables, if they exist:
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B XAINPUT
|
||||||
|
Include file path; components should be separated by `,'.
|
||||||
|
.TP
|
||||||
|
.B XAOUTPUT
|
||||||
|
Output file path.
|
||||||
|
|
||||||
|
.SH NOTES'N'BUGS
|
||||||
|
The R65C02 instructions
|
||||||
|
.B ina
|
||||||
|
(often rendered
|
||||||
|
.B inc
|
||||||
|
.BR a )
|
||||||
|
and
|
||||||
|
.B dea
|
||||||
|
.RB ( dec
|
||||||
|
.BR a )
|
||||||
|
must be rendered as bare
|
||||||
|
.B inc
|
||||||
|
and
|
||||||
|
.B dec
|
||||||
|
instructions respectively.
|
||||||
|
.LP
|
||||||
|
Forward-defined labels -- that is, labels that are defined after the current
|
||||||
|
instruction is processed -- cannot be optimized into zero
|
||||||
|
page instructions even if the label does end up being defined as a zero page
|
||||||
|
location, because the assembler does not know the value of the label in
|
||||||
|
advance during the first pass when the length of an
|
||||||
|
instruction is computed. On the second pass, a warning will be issued when an
|
||||||
|
instruction that could have been optimized can't be because of this limitation.
|
||||||
|
(Obviously, this does not apply to branching or jumping instructions because
|
||||||
|
they're not optimizable anyhow, and those instructions that can
|
||||||
|
.I only
|
||||||
|
take an 8-bit parameter will always be casted to an 8-bit quantity.)
|
||||||
|
If the label cannot otherwise be defined ahead of the instruction, the backtick
|
||||||
|
prefix
|
||||||
|
.B `
|
||||||
|
may be used to force further optimization no matter where the label is defined
|
||||||
|
as long as the instruction supports it.
|
||||||
|
Indiscriminately forcing the issue can be fraught with peril, however, and
|
||||||
|
is not recommended; to discourage this, the assembler will complain about its
|
||||||
|
use in addressing mode situations where no ambiguity exists, such as indirect
|
||||||
|
indexed, branching and so on.
|
||||||
|
.LP
|
||||||
|
Also, as a further consequence of the way optimization is managed, we repeat
|
||||||
|
that
|
||||||
|
.B all
|
||||||
|
24-bit quantities and labels that reference a 24-bit quantity in 65816 mode,
|
||||||
|
anteriorly declared or otherwise,
|
||||||
|
.B MUST
|
||||||
|
be prepended with the
|
||||||
|
.B @
|
||||||
|
prefix. Otherwise, the assembler will attempt to optimize to 16 bits, which
|
||||||
|
may be undesirable.
|
||||||
|
|
||||||
|
.SH "SEE ALSO"
|
||||||
|
.BR file65 (1),
|
||||||
|
.BR ldo65 (1),
|
||||||
|
.BR printcbm (1),
|
||||||
|
.BR reloc65 (1),
|
||||||
|
.BR uncpk (1),
|
||||||
|
.BR dxa (1)
|
||||||
|
|
||||||
|
.SH AUTHOR
|
||||||
|
This manual page was written by David Weinehall <tao@acc.umu.se>,
|
||||||
|
Andre Fachat <fachat@web.de>
|
||||||
|
and Cameron Kaiser <ckaiser@floodgap.com>.
|
||||||
|
Original xa package (C)1989-1997 Andre Fachat. Additional changes
|
||||||
|
(C)1989-2009 Andre Fachat, Jolse Maginnis, David Weinehall,
|
||||||
|
Cameron Kaiser. The official maintainer is Cameron Kaiser.
|
||||||
|
|
||||||
|
.SH WEBSITE
|
||||||
|
http://www.floodgap.com/retrotech/xa/
|
||||||
44
xa-2.3.5/misc/Makefile
Normal file
44
xa-2.3.5/misc/Makefile
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
|
||||||
|
XCBMLIB = ..
|
||||||
|
|
||||||
|
CFLAGS = -Wall -O2 -ansi -W
|
||||||
|
|
||||||
|
LIBS = #-lncurses -ltermcap -lm
|
||||||
|
|
||||||
|
|
||||||
|
all: ../mkrom.sh ../uncpk ../printcbm ../file65 ../reloc65 ../ldo65
|
||||||
|
|
||||||
|
../uncpk: uncpk.c
|
||||||
|
${CC} ${CFLAGS} uncpk.c -o $(XCBMLIB)/uncpk
|
||||||
|
|
||||||
|
../printcbm: printcbm.c
|
||||||
|
${CC} ${CFLAGS} printcbm.c -o $(XCBMLIB)/printcbm
|
||||||
|
|
||||||
|
../file65: file65.c
|
||||||
|
${CC} ${CFLAGS} file65.c -o $(XCBMLIB)/file65
|
||||||
|
|
||||||
|
../ldo65: ldo65.c
|
||||||
|
${CC} ${CFLAGS} ldo65.c -o $(XCBMLIB)/ldo65
|
||||||
|
|
||||||
|
../reloc65: reloc65.c
|
||||||
|
${CC} ${CFLAGS} reloc65.c -o $(XCBMLIB)/reloc65
|
||||||
|
|
||||||
|
../mkrom.sh: mkrom.sh
|
||||||
|
cp mkrom.sh ../mkrom.sh
|
||||||
|
|
||||||
|
lt1: lt1.a
|
||||||
|
../xa -R -c -o lt1 lt1.a
|
||||||
|
|
||||||
|
lt2: lt2.a
|
||||||
|
../xa -R -c -o lt2 lt2.a
|
||||||
|
|
||||||
|
lt: lt1 lt2
|
||||||
|
../ldo65 -o lt lt1 lt2
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.o
|
||||||
|
|
||||||
|
mrproper: clean
|
||||||
|
rm -f ../uncpk ../printcbm ../file65 ../mkrom.sh ../reloc65 ../ldo65
|
||||||
|
rm -f lt1 lt2 lt
|
||||||
|
|
||||||
312
xa-2.3.5/misc/file65.c
Normal file
312
xa-2.3.5/misc/file65.c
Normal file
|
|
@ -0,0 +1,312 @@
|
||||||
|
/* file65 -- A part of xa65 - 65xx/65816 cross-assembler and utility suite
|
||||||
|
* Print information about o65 files
|
||||||
|
*
|
||||||
|
* Copyright (C) 1989-1997 André Fachat (a.fachat@physik.tu-chemnitz.de)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
|
#define BUF (9*4+8)
|
||||||
|
|
||||||
|
#define programname "file65"
|
||||||
|
#define progversion "v0.2.1"
|
||||||
|
#define author "Written by André Fachat"
|
||||||
|
#define copyright "Copyright (C) 1997-2002 André Fachat."
|
||||||
|
|
||||||
|
int read_options(FILE *fp);
|
||||||
|
int print_labels(FILE *fp, int offset);
|
||||||
|
|
||||||
|
unsigned char hdr[BUF];
|
||||||
|
unsigned char cmp[] = { 1, 0, 'o', '6', '5' };
|
||||||
|
|
||||||
|
int xapar = 0;
|
||||||
|
int rompar = 0;
|
||||||
|
int romoff = 0;
|
||||||
|
int labels = 0;
|
||||||
|
|
||||||
|
void usage(FILE *fp)
|
||||||
|
{
|
||||||
|
fprintf(fp,
|
||||||
|
"Usage: %s [options] [file]\n"
|
||||||
|
"Print file information about o65 files\n"
|
||||||
|
"\n",
|
||||||
|
programname);
|
||||||
|
fprintf(fp,
|
||||||
|
" -P print the segment end addresses according to `xa' command line\n"
|
||||||
|
" parameters `-b?'\n"
|
||||||
|
" -a offset print `xa' ``romable'' parameter for another file behind this one\n"
|
||||||
|
" in the same ROM. Add offset to start address.\n"
|
||||||
|
" -A offset same as `-a', but only print the start address of the next\n"
|
||||||
|
" file in the ROM\n"
|
||||||
|
" -V print undefined and global labels\n"
|
||||||
|
" --version output version information and exit\n"
|
||||||
|
" --help display this help and exit\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
int i = 1, n, mode, hlen;
|
||||||
|
FILE *fp;
|
||||||
|
char *aligntxt[4]= {"[align 1]","[align 2]","[align 4]","[align 256]"};
|
||||||
|
if(argc<=1) {
|
||||||
|
usage(stderr);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strstr(argv[1], "--help")) {
|
||||||
|
usage(stdout);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strstr(argv[1], "--version")) {
|
||||||
|
version(programname, progversion, author, copyright);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
while(i<argc) {
|
||||||
|
if(argv[i][0]=='-') {
|
||||||
|
/* process options */
|
||||||
|
switch(argv[i][1]) {
|
||||||
|
case 'V':
|
||||||
|
labels = 1;
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
printf("file65: Version 0.2\n");
|
||||||
|
break;
|
||||||
|
case 'a':
|
||||||
|
case 'A':
|
||||||
|
rompar = 1;
|
||||||
|
if(argv[i][1]=='A') rompar++;
|
||||||
|
if(argv[i][2]) romoff = atoi(argv[i]+2);
|
||||||
|
else romoff = atoi(argv[++i]);
|
||||||
|
break;
|
||||||
|
case 'P':
|
||||||
|
xapar = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr,"file65: %s unknown option\n",argv[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fp = fopen(argv[i],"rb");
|
||||||
|
if(fp) {
|
||||||
|
n = fread(hdr, 1, 8, fp);
|
||||||
|
if((n>=8) && (!memcmp(hdr, cmp, 5))) {
|
||||||
|
mode=hdr[7]*256+hdr[6];
|
||||||
|
if(!xapar && !rompar) {
|
||||||
|
printf("%s: o65 version %d %s file\n", argv[i], hdr[5],
|
||||||
|
hdr[7]&0x10 ? "object" : "executable");
|
||||||
|
printf(" mode: %04x =",mode );
|
||||||
|
printf("%s%s%s%s%s\n",
|
||||||
|
(mode & 0x1000)?"[object]":"[executable]",
|
||||||
|
(mode & 0x2000)?"[32bit]":"[16bit]",
|
||||||
|
(mode & 0x4000)?"[page relocation]":"[byte relocation]",
|
||||||
|
(mode & 0x8000)?"[CPU 65816]":"[CPU 6502]",
|
||||||
|
aligntxt[mode & 3]);
|
||||||
|
}
|
||||||
|
if(mode & 0x2000) {
|
||||||
|
fprintf(stderr,"file65: %s: 32 bit size not supported\n", argv[i]);
|
||||||
|
} else {
|
||||||
|
n=fread(hdr+8, 1, 18, fp);
|
||||||
|
if(n<18) {
|
||||||
|
fprintf(stderr,"file65: %s: truncated file\n", argv[i]);
|
||||||
|
} else {
|
||||||
|
if(!xapar && !rompar) {
|
||||||
|
printf(" text segment @ $%04x - $%04x [$%04x bytes]\n", hdr[9]*256+hdr[8], hdr[9]*256+hdr[8]+hdr[11]*256+hdr[10], hdr[11]*256+hdr[10]);
|
||||||
|
printf(" data segment @ $%04x - $%04x [$%04x bytes]\n", hdr[13]*256+hdr[12], hdr[13]*256+hdr[12]+hdr[15]*256+hdr[14], hdr[15]*256+hdr[14]);
|
||||||
|
printf(" bss segment @ $%04x - $%04x [$%04x bytes]\n", hdr[17]*256+hdr[16], hdr[17]*256+hdr[16]+hdr[19]*256+hdr[18], hdr[19]*256+hdr[18]);
|
||||||
|
printf(" zero segment @ $%04x - $%04x [$%04x bytes]\n", hdr[21]*256+hdr[20], hdr[21]*256+hdr[20]+hdr[23]*256+hdr[22], hdr[23]*256+hdr[22]);
|
||||||
|
printf(" stack size $%04x bytes %s\n", hdr[25]*256+hdr[24],
|
||||||
|
(hdr[25]*256+hdr[24])==0?"(i.e. unknown)":"");
|
||||||
|
if(labels) {
|
||||||
|
read_options(fp);
|
||||||
|
print_labels(fp, hdr[11]*256+hdr[10] + hdr[15]*256+hdr[14]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
struct stat fbuf;
|
||||||
|
hlen = 8+18+read_options(fp);
|
||||||
|
stat(argv[i],&fbuf);
|
||||||
|
if(xapar) {
|
||||||
|
if(!rompar) printf("-bt %d ",
|
||||||
|
(hdr[9]*256+hdr[8]) + (hdr[11]*256+hdr[10])
|
||||||
|
);
|
||||||
|
printf("-bd %d -bb %d -bz %d ",
|
||||||
|
(hdr[13]*256+hdr[12]) + (hdr[15]*256+hdr[14]),
|
||||||
|
(hdr[17]*256+hdr[16]) + (hdr[19]*256+hdr[18]),
|
||||||
|
(hdr[21]*256+hdr[20]) + (hdr[23]*256+hdr[22])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if(rompar==1) {
|
||||||
|
printf("-A %lu ", (unsigned long)((hdr[9]*256+hdr[8])
|
||||||
|
-hlen +romoff +fbuf.st_size));
|
||||||
|
} else
|
||||||
|
if(rompar==2) {
|
||||||
|
printf("%lu ", (unsigned long)((hdr[9]*256+hdr[8])
|
||||||
|
-hlen +romoff +fbuf.st_size));
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fprintf(stderr,"file65: %s: not an o65 file!\n", argv[i]);
|
||||||
|
if(hdr[0]==1 && hdr[1]==8 && hdr[3]==8) {
|
||||||
|
printf("%s: C64 BASIC executable (start address $0801)?\n", argv[i]);
|
||||||
|
} else
|
||||||
|
if(hdr[0]==1 && hdr[1]==4 && hdr[3]==4) {
|
||||||
|
printf("%s: CBM PET BASIC executable (start address $0401)?\n", argv[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fprintf(stderr,"file65: %s: %s\n", argv[i], strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct { int opt; int strfl; char *string; } otab[] = {
|
||||||
|
{ 0, 1, "Filename" },
|
||||||
|
{ 1, 0, "O/S Type" },
|
||||||
|
{ 2, 1, "Assembler" },
|
||||||
|
{ 3, 1, "Author" },
|
||||||
|
{ 4, 1, "Creation Date" },
|
||||||
|
{ -1, -1, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static char* stab[] = {
|
||||||
|
"undefined" ,
|
||||||
|
"absolute" ,
|
||||||
|
"text" ,
|
||||||
|
"data" ,
|
||||||
|
"bss" ,
|
||||||
|
"zero" ,
|
||||||
|
"-" ,
|
||||||
|
"-"
|
||||||
|
};
|
||||||
|
|
||||||
|
void print_option(unsigned char *buf, int len) {
|
||||||
|
int i, strfl=0;
|
||||||
|
for(i=0;otab[i].opt>=0; i++) if(*buf==otab[i].opt) break;
|
||||||
|
if(otab[i].opt>=0) {
|
||||||
|
printf("fopt: %-17s: ", otab[i].string);
|
||||||
|
strfl = otab[i].strfl;
|
||||||
|
} else {
|
||||||
|
printf("fopt: Unknown Type $%02x : ", (*buf & 0xff));
|
||||||
|
}
|
||||||
|
if(strfl) {
|
||||||
|
buf[len]=0;
|
||||||
|
printf("%s\n", buf+1);
|
||||||
|
} else {
|
||||||
|
for (i=1; i<len-1; i++) {
|
||||||
|
printf("%02x ", buf[i] & 0xff);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int read_options(FILE *fp) {
|
||||||
|
int c, l=0;
|
||||||
|
unsigned char tb[256];
|
||||||
|
|
||||||
|
c=fgetc(fp); l++;
|
||||||
|
while(c && c!=EOF) {
|
||||||
|
c&=255;
|
||||||
|
fread(tb, 1, c-1, fp);
|
||||||
|
if(labels) print_option(tb, c);
|
||||||
|
l+=c;
|
||||||
|
c=fgetc(fp);
|
||||||
|
}
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
int print_labels(FILE *fp, int offset) {
|
||||||
|
int i, nud, c, seg, off;
|
||||||
|
/*
|
||||||
|
printf("print_labels:offset=%d\n",offset);
|
||||||
|
*/
|
||||||
|
fseek(fp, offset, SEEK_CUR);
|
||||||
|
|
||||||
|
nud = (fgetc(fp) & 0xff);
|
||||||
|
nud += ((fgetc(fp) << 8) & 0xff00);
|
||||||
|
|
||||||
|
printf("Undefined Labels: %d\n", nud);
|
||||||
|
|
||||||
|
if(nud) {
|
||||||
|
do {
|
||||||
|
c=fgetc(fp);
|
||||||
|
while(c && c!=EOF) {
|
||||||
|
fputc(c, stdout);
|
||||||
|
c=fgetc(fp);
|
||||||
|
}
|
||||||
|
printf("\t");
|
||||||
|
} while(--nud);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0;i<2;i++) {
|
||||||
|
c=fgetc(fp);
|
||||||
|
while(c && c!=EOF) {
|
||||||
|
c&= 0xff;
|
||||||
|
while(c == 255 && c!= EOF) {
|
||||||
|
c=fgetc(fp);
|
||||||
|
if(c==EOF) break;
|
||||||
|
c&= 0xff;
|
||||||
|
}
|
||||||
|
if(c==EOF) break;
|
||||||
|
|
||||||
|
c=fgetc(fp);
|
||||||
|
if( (c & 0xe0) == 0x40 ) fgetc(fp);
|
||||||
|
if( (c & 0x07) == 0 ) { fgetc(fp); fgetc(fp); }
|
||||||
|
|
||||||
|
c=fgetc(fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nud = (fgetc(fp) & 0xff);
|
||||||
|
nud += ((fgetc(fp) << 8) & 0xff00);
|
||||||
|
printf("Global Labels: %d\n", nud);
|
||||||
|
|
||||||
|
if(nud) {
|
||||||
|
do {
|
||||||
|
c=fgetc(fp);
|
||||||
|
while(c && c!=EOF) {
|
||||||
|
fputc(c, stdout);
|
||||||
|
c=fgetc(fp);
|
||||||
|
}
|
||||||
|
if(c==EOF) break;
|
||||||
|
|
||||||
|
seg = fgetc(fp) & 0xff;
|
||||||
|
off= (fgetc(fp) & 0xff);
|
||||||
|
off+= ((fgetc(fp) << 8) & 0xff00);
|
||||||
|
printf(" (segID=%d (%s), offset=%04x)\n", seg, stab[seg&7], off);
|
||||||
|
|
||||||
|
} while(--nud);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
698
xa-2.3.5/misc/ldo65.c
Normal file
698
xa-2.3.5/misc/ldo65.c
Normal file
|
|
@ -0,0 +1,698 @@
|
||||||
|
/* ldo65 -- A part of xa65 - 65xx/65816 cross-assembler and utility suite
|
||||||
|
* o65 relocatable object file linker
|
||||||
|
*
|
||||||
|
* A part of the xa65 - 65xx/65816 cross-assembler and utility suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 1989-1997 André Fachat (a.fachat@physik.tu-chemnitz.de)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
|
#define BUF (9*2+8) /* 16 bit header */
|
||||||
|
|
||||||
|
#define programname "ldo65"
|
||||||
|
#define progversion "v0.1.1"
|
||||||
|
#define author "Written by André Fachat"
|
||||||
|
#define copyright "Copyright (C) 1997-2002 André Fachat. Formerly ld65."
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *name;
|
||||||
|
int len;
|
||||||
|
} undefs;
|
||||||
|
|
||||||
|
/* file information */
|
||||||
|
typedef struct {
|
||||||
|
char *fname; /* file name */
|
||||||
|
size_t fsize; /* length of file */
|
||||||
|
unsigned char *buf; /* file content */
|
||||||
|
|
||||||
|
int tbase; /* header: text base */
|
||||||
|
int tlen; /* text length */
|
||||||
|
int dbase; /* data base */
|
||||||
|
int dlen; /* data length */
|
||||||
|
int bbase; /* bss base */
|
||||||
|
int blen; /* bss length */
|
||||||
|
int zbase; /* zero base */
|
||||||
|
int zlen; /* zero length */
|
||||||
|
|
||||||
|
int tdiff; /* text segment relocation diff */
|
||||||
|
int ddiff; /* data segment relocation diff */
|
||||||
|
int bdiff; /* bss segment relocation diff */
|
||||||
|
int zdiff; /* zero segment relocation diff */
|
||||||
|
|
||||||
|
int tpos; /* position of text segment in file */
|
||||||
|
int dpos; /* position of data segment in file */
|
||||||
|
int upos; /* position of undef'd list in file */
|
||||||
|
int trpos; /* position of text reloc tab in file */
|
||||||
|
int drpos; /* position of data reloc tab in file */
|
||||||
|
int gpos; /* position of globals list in file */
|
||||||
|
|
||||||
|
int lasttreloc;
|
||||||
|
int lastdreloc;
|
||||||
|
|
||||||
|
int nundef; /* number of undefined labels */
|
||||||
|
undefs *ud; /* undefined labels list NULL if none */
|
||||||
|
} file65;
|
||||||
|
|
||||||
|
/* globally defined lables are stored in this struct */
|
||||||
|
typedef struct {
|
||||||
|
char *name;
|
||||||
|
int len; /* length of labelname */
|
||||||
|
int fl; /* 0=ok, 1=multiply defined */
|
||||||
|
int val; /* address value */
|
||||||
|
int seg; /* segment */
|
||||||
|
file65 *file; /* in which file is it? */
|
||||||
|
} glob;
|
||||||
|
|
||||||
|
file65 *load_file(char *fname);
|
||||||
|
|
||||||
|
int read_options(unsigned char *f);
|
||||||
|
int read_undef(unsigned char *f, file65 *fp);
|
||||||
|
int len_reloc_seg(unsigned char *buf, int ri);
|
||||||
|
int reloc_seg(unsigned char *buf, int adr, int ri, int *lreloc, file65 *fp);
|
||||||
|
unsigned char *reloc_globals(unsigned char *, file65 *fp);
|
||||||
|
int read_globals(file65 *file);
|
||||||
|
int write_options(FILE *fp, file65 *file);
|
||||||
|
int write_reloc(file65 *fp[], int nfp, FILE *f);
|
||||||
|
int write_globals(FILE *fp);
|
||||||
|
|
||||||
|
file65 file;
|
||||||
|
unsigned char cmp[] = { 1, 0, 'o', '6', '5' };
|
||||||
|
unsigned char hdr[26] = { 1, 0, 'o', '6', '5', 0 };
|
||||||
|
|
||||||
|
void usage(FILE *fp)
|
||||||
|
{
|
||||||
|
fprintf(fp,
|
||||||
|
"Usage: %s [OPTION]... [FILE]...\n"
|
||||||
|
"Linker for o65 object files\n"
|
||||||
|
"\n"
|
||||||
|
" -b? addr relocates segment `?' (i.e. `t' for text segment,\n"
|
||||||
|
" `d' for data, `b' for bss, and `z' for zeropage) to the new\n"
|
||||||
|
" address `addr'\n"
|
||||||
|
" -o file uses `file' as output file. Default is `a.o65'\n"
|
||||||
|
" -G suppress writing of globals\n"
|
||||||
|
" --version output version information and exit\n"
|
||||||
|
" --help display this help and exit\n",
|
||||||
|
programname);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
int noglob=0;
|
||||||
|
int i = 1;
|
||||||
|
int tbase = 0x0400, dbase = 0x1000, bbase = 0x4000, zbase = 0x0002;
|
||||||
|
int ttlen, tdlen, tblen, tzlen;
|
||||||
|
char *outfile = "a.o65";
|
||||||
|
int j, jm;
|
||||||
|
file65 *file, **fp = NULL;
|
||||||
|
FILE *fd;
|
||||||
|
|
||||||
|
if (argc <= 1) {
|
||||||
|
usage(stderr);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strstr(argv[1], "--help")) {
|
||||||
|
usage(stdout);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strstr(argv[1], "--version")) {
|
||||||
|
version(programname, progversion, author, copyright);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read options */
|
||||||
|
while(i<argc && argv[i][0]=='-') {
|
||||||
|
/* process options */
|
||||||
|
switch(argv[i][1]) {
|
||||||
|
case 'G':
|
||||||
|
noglob=1;
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
if(argv[i][2]) outfile=argv[i]+2;
|
||||||
|
else outfile=argv[++i];
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
switch(argv[i][2]) {
|
||||||
|
case 't':
|
||||||
|
if(argv[i][3]) tbase = atoi(argv[i]+3);
|
||||||
|
else tbase = atoi(argv[++i]);
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
if(argv[i][3]) dbase = atoi(argv[i]+3);
|
||||||
|
else dbase = atoi(argv[++i]);
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
if(argv[i][3]) bbase = atoi(argv[i]+3);
|
||||||
|
else bbase = atoi(argv[++i]);
|
||||||
|
break;
|
||||||
|
case 'z':
|
||||||
|
if(argv[i][3]) zbase = atoi(argv[i]+3);
|
||||||
|
else zbase = atoi(argv[++i]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("Unknown segment type '%c' - ignored!\n", argv[i][2]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr,"file65: %s unknown option, use '-?' for help\n",argv[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
/* each file is loaded first */
|
||||||
|
j=0; jm=0; fp=NULL;
|
||||||
|
while(i<argc) {
|
||||||
|
file65 *f;
|
||||||
|
f = load_file(argv[i]);
|
||||||
|
if(f) {
|
||||||
|
if(j>=jm) fp=realloc(fp, (jm=(jm?jm*2:10))*sizeof(file65*));
|
||||||
|
if(!fp) { fprintf(stderr,"Oops, no more memory\n"); exit(1); }
|
||||||
|
fp[j++] = f;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now [tdbz]base holds new segment base address */
|
||||||
|
/* set total length to zero */
|
||||||
|
ttlen = tdlen = tblen = tzlen = 0;
|
||||||
|
|
||||||
|
/* find new addresses for the files and read globals */
|
||||||
|
for(i=0;i<j;i++) {
|
||||||
|
file = fp[i];
|
||||||
|
|
||||||
|
/* compute relocation differences */
|
||||||
|
file->tdiff = ((tbase + ttlen) - file->tbase);
|
||||||
|
file->ddiff = ((dbase + tdlen) - file->dbase);
|
||||||
|
file->bdiff = ((bbase + tblen) - file->bbase);
|
||||||
|
file->zdiff = ((zbase + tzlen) - file->zbase);
|
||||||
|
/*printf("tbase=%04x, file->tbase=%04x, ttlen=%04x -> tdiff=%04x\n",
|
||||||
|
tbase, file->tbase, ttlen, file->tdiff);*/
|
||||||
|
|
||||||
|
/* update globals (for result file) */
|
||||||
|
ttlen += file->tlen;
|
||||||
|
tdlen += file->dlen;
|
||||||
|
tblen += file->blen;
|
||||||
|
tzlen += file->zlen;
|
||||||
|
|
||||||
|
read_globals(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0;i<j;i++) {
|
||||||
|
file = fp[i];
|
||||||
|
|
||||||
|
reloc_seg(file->buf,
|
||||||
|
file->tpos,
|
||||||
|
file->trpos,
|
||||||
|
&(file->lasttreloc),
|
||||||
|
file);
|
||||||
|
reloc_seg(file->buf,
|
||||||
|
file->dpos,
|
||||||
|
file->drpos,
|
||||||
|
&(file->lastdreloc),
|
||||||
|
file);
|
||||||
|
reloc_globals(file->buf+file->gpos, file);
|
||||||
|
|
||||||
|
file->tbase += file->tdiff;
|
||||||
|
file->dbase += file->ddiff;
|
||||||
|
file->bbase += file->bdiff;
|
||||||
|
file->zbase += file->zdiff;
|
||||||
|
|
||||||
|
file->lasttreloc += file->tbase - file->tpos;
|
||||||
|
file->lastdreloc += file->dbase - file->dpos;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
hdr[ 6] = 0; hdr[ 7] = 0;
|
||||||
|
hdr[ 8] = tbase & 255; hdr[ 9] = (tbase>>8) & 255;
|
||||||
|
hdr[10] = ttlen & 255; hdr[11] = (ttlen >>8)& 255;
|
||||||
|
hdr[12] = dbase & 255; hdr[13] = (dbase>>8) & 255;
|
||||||
|
hdr[14] = tdlen & 255; hdr[15] = (tdlen >>8)& 255;
|
||||||
|
hdr[16] = bbase & 255; hdr[17] = (bbase>>8) & 255;
|
||||||
|
hdr[18] = tblen & 255; hdr[19] = (tblen >>8)& 255;
|
||||||
|
hdr[20] = zbase & 255; hdr[21] = (zbase>>8) & 255;
|
||||||
|
hdr[22] = tzlen & 255; hdr[23] = (tzlen >>8)& 255;
|
||||||
|
hdr[24] = 0; hdr[25] = 0;
|
||||||
|
|
||||||
|
fd = fopen(outfile, "wb");
|
||||||
|
if(!fd) {
|
||||||
|
fprintf(stderr,"Couldn't open output file %s (%s)\n",
|
||||||
|
outfile, strerror(errno));
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
fwrite(hdr, 1, 26, fd);
|
||||||
|
/* this writes _all_ options from _all_files! */
|
||||||
|
for(i=0;i<j;i++) {
|
||||||
|
write_options(fd, fp[i]);
|
||||||
|
}
|
||||||
|
fputc(0,fd);
|
||||||
|
/* write text segment */
|
||||||
|
for(i=0;i<j;i++) {
|
||||||
|
fwrite(fp[i]->buf + fp[i]->tpos, 1, fp[i]->tlen, fd);
|
||||||
|
}
|
||||||
|
/* write data segment */
|
||||||
|
for(i=0;i<j;i++) {
|
||||||
|
fwrite(fp[i]->buf + fp[i]->dpos, 1, fp[i]->dlen, fd);
|
||||||
|
}
|
||||||
|
write_reloc(fp, j, fd);
|
||||||
|
if(!noglob) {
|
||||||
|
write_globals(fd);
|
||||||
|
} else {
|
||||||
|
fputc(0,fd);
|
||||||
|
fputc(0,fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
|
||||||
|
int write_options(FILE *fp, file65 *file) {
|
||||||
|
return fwrite(file->buf+BUF, 1, file->tpos-BUF-1, fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
int read_options(unsigned char *buf) {
|
||||||
|
int c, l=0;
|
||||||
|
|
||||||
|
c=buf[0];
|
||||||
|
while(c && c!=EOF) {
|
||||||
|
c&=255;
|
||||||
|
l+=c;
|
||||||
|
c=buf[l];
|
||||||
|
}
|
||||||
|
return ++l;
|
||||||
|
}
|
||||||
|
|
||||||
|
int read_undef(unsigned char *buf, file65 *file) {
|
||||||
|
int i, n, l = 2, ll;
|
||||||
|
|
||||||
|
n = buf[0] + 256*buf[1];
|
||||||
|
|
||||||
|
file->nundef = n;
|
||||||
|
|
||||||
|
if (n == 0) {
|
||||||
|
file->ud = NULL;
|
||||||
|
} else {
|
||||||
|
file->ud = malloc(n*sizeof(undefs));
|
||||||
|
if(!file->ud) {
|
||||||
|
fprintf(stderr,"Oops, no more memory\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
i=0;
|
||||||
|
while(i<n){
|
||||||
|
file->ud[i].name = (char*) buf+l;
|
||||||
|
ll=l;
|
||||||
|
while(buf[l++]);
|
||||||
|
file->ud[i].len = l-ll-1;
|
||||||
|
/*printf("read undef '%s'(%p), len=%d, ll=%d, l=%d, buf[l]=%d\n",
|
||||||
|
file->ud[i].name, file->ud[i].name, file->ud[i].len,ll,l,buf[l]);*/
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* compute and return the length of the relocation table */
|
||||||
|
int len_reloc_seg(unsigned char *buf, int ri) {
|
||||||
|
int type, seg;
|
||||||
|
|
||||||
|
while(buf[ri]) {
|
||||||
|
if((buf[ri] & 255) == 255) {
|
||||||
|
ri++;
|
||||||
|
} else {
|
||||||
|
ri++;
|
||||||
|
type = buf[ri] & 0xe0;
|
||||||
|
seg = buf[ri] & 0x07;
|
||||||
|
/*printf("reloc entry @ rtab=%p (offset=%d), adr=%04x, type=%02x, seg=%d\n",buf+ri-1, *(buf+ri-1), adr, type, seg);*/
|
||||||
|
ri++;
|
||||||
|
switch(type) {
|
||||||
|
case 0x80:
|
||||||
|
break;
|
||||||
|
case 0x40:
|
||||||
|
ri++;
|
||||||
|
break;
|
||||||
|
case 0x20:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(seg==0) ri+=2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ++ri;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define reldiff(s) (((s)==2)?fp->tdiff:(((s)==3)?fp->ddiff:(((s)==4)?fp->bdiff:(((s)==5)?fp->zdiff:0))))
|
||||||
|
|
||||||
|
unsigned char *reloc_globals(unsigned char *buf, file65 *fp) {
|
||||||
|
int n, old, new, seg;
|
||||||
|
|
||||||
|
n = buf[0] + 256*buf[1];
|
||||||
|
buf +=2;
|
||||||
|
|
||||||
|
while(n) {
|
||||||
|
/*printf("relocating %s, ", buf);*/
|
||||||
|
while(*(buf++));
|
||||||
|
seg = *buf;
|
||||||
|
old = buf[1] + 256*buf[2];
|
||||||
|
new = old + reldiff(seg);
|
||||||
|
/*printf("old=%04x, seg=%d, rel=%04x, new=%04x\n", old, seg, reldiff(seg), new);*/
|
||||||
|
buf[1] = new & 255;
|
||||||
|
buf[2] = (new>>8) & 255;
|
||||||
|
buf +=3;
|
||||||
|
n--;
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
|
||||||
|
file65 *load_file(char *fname) {
|
||||||
|
file65 *file;
|
||||||
|
struct stat fs;
|
||||||
|
FILE *fp;
|
||||||
|
int mode, hlen;
|
||||||
|
size_t n;
|
||||||
|
|
||||||
|
file=malloc(sizeof(file65));
|
||||||
|
if(!file) {
|
||||||
|
fprintf(stderr,"Oops, not enough memory!\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*printf("load_file(%s)\n",fname);*/
|
||||||
|
|
||||||
|
file->fname=fname;
|
||||||
|
stat(fname, &fs);
|
||||||
|
file->fsize=fs.st_size;
|
||||||
|
file->buf=malloc(file->fsize);
|
||||||
|
if(!file->buf) {
|
||||||
|
fprintf(stderr,"Oops, no more memory!\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fp = fopen(fname,"rb");
|
||||||
|
if(fp) {
|
||||||
|
n = fread(file->buf, 1, file->fsize, fp);
|
||||||
|
fclose(fp);
|
||||||
|
if((n>=file->fsize) && (!memcmp(file->buf, cmp, 5))) {
|
||||||
|
mode=file->buf[7]*256+file->buf[6];
|
||||||
|
if(mode & 0x2000) {
|
||||||
|
fprintf(stderr,"file65: %s: 32 bit size not supported\n", fname);
|
||||||
|
free(file->buf); free(file); file=NULL;
|
||||||
|
} else
|
||||||
|
if(mode & 0x4000) {
|
||||||
|
fprintf(stderr,"file65: %s: pagewise relocation not supported\n",
|
||||||
|
fname);
|
||||||
|
free(file->buf); free(file); file=NULL;
|
||||||
|
} else {
|
||||||
|
hlen = BUF+read_options(file->buf+BUF);
|
||||||
|
|
||||||
|
file->tbase = file->buf[ 9]*256+file->buf[ 8];
|
||||||
|
file->tlen = file->buf[11]*256+file->buf[10];
|
||||||
|
file->dbase = file->buf[13]*256+file->buf[12];
|
||||||
|
file->dlen = file->buf[15]*256+file->buf[14];
|
||||||
|
file->bbase = file->buf[17]*256+file->buf[16];
|
||||||
|
file->blen = file->buf[19]*256+file->buf[18];
|
||||||
|
file->zbase = file->buf[21]*256+file->buf[20];
|
||||||
|
file->zlen = file->buf[23]*256+file->buf[21];
|
||||||
|
|
||||||
|
file->tpos = hlen;
|
||||||
|
file->dpos = hlen + file->tlen;
|
||||||
|
file->upos = file->dpos + file->dlen;
|
||||||
|
file->trpos= file->upos + read_undef(file->buf+file->upos, file);
|
||||||
|
file->drpos= len_reloc_seg(file->buf, file->trpos);
|
||||||
|
file->gpos = len_reloc_seg(file->buf, file->drpos);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
fprintf(stderr,"file65: %s: %s\n", fname, strerror(errno));
|
||||||
|
} else
|
||||||
|
fprintf(stderr,"file65: %s: %s\n", fname, strerror(errno));
|
||||||
|
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
|
||||||
|
glob *gp = NULL;
|
||||||
|
int gm=0;
|
||||||
|
int g=0;
|
||||||
|
|
||||||
|
int write_reloc(file65 *fp[], int nfp, FILE *f) {
|
||||||
|
int tpc, pc, i;
|
||||||
|
unsigned char *p;
|
||||||
|
int low = 0, seg, typ, lab;
|
||||||
|
|
||||||
|
/* no undefined labels ? TODO */
|
||||||
|
fputc(0,f);
|
||||||
|
fputc(0,f);
|
||||||
|
|
||||||
|
tpc = fp[0]->tbase-1;
|
||||||
|
|
||||||
|
for(i=0;i<nfp;i++) {
|
||||||
|
pc = fp[i]->tbase-1;
|
||||||
|
p = fp[i]->buf + fp[i]->trpos;
|
||||||
|
|
||||||
|
while(*p) {
|
||||||
|
while((*p)==255) { pc+=254; p++; }
|
||||||
|
pc+=*(p++);
|
||||||
|
seg=(*p)&7;
|
||||||
|
typ=(*p)&0xe0;
|
||||||
|
if(typ==0x40) low=*(++p);
|
||||||
|
p++;
|
||||||
|
if(seg==0) {
|
||||||
|
lab=p[0]+256*p[1];
|
||||||
|
seg=gp[lab].seg;
|
||||||
|
p+=2;
|
||||||
|
}
|
||||||
|
if(seg>1) {
|
||||||
|
while(pc-tpc>254) {
|
||||||
|
fputc(255,f);
|
||||||
|
tpc+=254;
|
||||||
|
}
|
||||||
|
fputc(pc-tpc, f);
|
||||||
|
tpc=pc;
|
||||||
|
fputc(typ | seg, f);
|
||||||
|
if(typ==0x40) {
|
||||||
|
fputc(low,f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fputc(0,f);
|
||||||
|
|
||||||
|
tpc = fp[0]->dbase-1;
|
||||||
|
|
||||||
|
for(i=0;i<nfp;i++) {
|
||||||
|
pc = fp[i]->dbase-1;
|
||||||
|
p = fp[i]->buf + fp[i]->drpos;
|
||||||
|
|
||||||
|
while(*p) {
|
||||||
|
while((*p)==255) { pc+=254; p++; }
|
||||||
|
pc+=*(p++);
|
||||||
|
seg=(*p)&7;
|
||||||
|
typ=(*p)&0xe0;
|
||||||
|
if(typ==0x40) low=*(++p);
|
||||||
|
p++;
|
||||||
|
if(seg==0) {
|
||||||
|
lab=p[0]+256*p[1];
|
||||||
|
seg=gp[lab].seg;
|
||||||
|
p+=2;
|
||||||
|
}
|
||||||
|
if(seg>1) {
|
||||||
|
while(pc-tpc>254) {
|
||||||
|
fputc(255,f);
|
||||||
|
tpc+=254;
|
||||||
|
}
|
||||||
|
fputc(pc-tpc, f);
|
||||||
|
tpc=pc;
|
||||||
|
fputc(typ | seg, f);
|
||||||
|
if(typ==0x40) {
|
||||||
|
fputc(low,f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fputc(0,f);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int write_globals(FILE *fp) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
fputc(g&255, fp);
|
||||||
|
fputc((g>>8)&255, fp);
|
||||||
|
|
||||||
|
for(i=0;i<g;i++) {
|
||||||
|
fprintf(fp,"%s%c%c%c%c",gp[i].name,0,gp[i].seg,
|
||||||
|
gp[i].val & 255, (gp[i].val>>8)&255);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int read_globals(file65 *fp) {
|
||||||
|
int i, l, n, old, new, seg, ll;
|
||||||
|
char *name;
|
||||||
|
unsigned char *buf = fp->buf + fp->gpos;
|
||||||
|
|
||||||
|
n = buf[0] + 256*buf[1];
|
||||||
|
buf +=2;
|
||||||
|
|
||||||
|
while(n) {
|
||||||
|
/*printf("reading %s, ", buf);*/
|
||||||
|
name = (char*) buf;
|
||||||
|
l=0;
|
||||||
|
while(buf[l++]);
|
||||||
|
buf+=l;
|
||||||
|
ll=l-1;
|
||||||
|
seg = *buf;
|
||||||
|
old = buf[1] + 256*buf[2];
|
||||||
|
new = old + reldiff(seg);
|
||||||
|
/*printf("old=%04x, seg=%d, rel=%04x, new=%04x\n", old, seg, reldiff(seg), new);*/
|
||||||
|
|
||||||
|
/* multiply defined? */
|
||||||
|
for(i=0;i<g;i++) {
|
||||||
|
if(ll==gp[i].len && !strcmp(name, gp[i].name)) {
|
||||||
|
fprintf(stderr,"Warning: label '%s' multiply defined (%s and %s)\n",
|
||||||
|
name, fp->fname, gp[i].file->fname);
|
||||||
|
gp[i].fl = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* not already defined */
|
||||||
|
if(i>=g) {
|
||||||
|
if(g>=gm) {
|
||||||
|
gp = realloc(gp, (gm=(gm?2*gm:40))*sizeof(glob));
|
||||||
|
if(!gp) {
|
||||||
|
fprintf(stderr,"Oops, no more memory\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(g>=0x10000) {
|
||||||
|
fprintf(stderr,"Outch, maximum number of labels (65536) exceeded!\n");
|
||||||
|
exit(3);
|
||||||
|
}
|
||||||
|
gp[g].name = name;
|
||||||
|
gp[g].len = ll;
|
||||||
|
gp[g].seg = seg;
|
||||||
|
gp[g].val = new;
|
||||||
|
gp[g].fl = 0;
|
||||||
|
gp[g].file = fp;
|
||||||
|
/*printf("set label '%s' (l=%d, seg=%d, val=%04x)\n", gp[g].name,
|
||||||
|
gp[g].len, gp[g].seg, gp[g].val);*/
|
||||||
|
g++;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf +=3;
|
||||||
|
n--;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int find_global(unsigned char *bp, file65 *fp, int *seg) {
|
||||||
|
int i,l;
|
||||||
|
char *n;
|
||||||
|
int nl = bp[0]+256*bp[1];
|
||||||
|
|
||||||
|
l=fp->ud[nl].len;
|
||||||
|
n=fp->ud[nl].name;
|
||||||
|
/*printf("find_global(%s (len=%d))\n",n,l);*/
|
||||||
|
|
||||||
|
for(i=0;i<g;i++) {
|
||||||
|
if(gp[i].len == l && !strcmp(gp[i].name, n)) {
|
||||||
|
*seg = gp[i].seg;
|
||||||
|
bp[0] = i & 255; bp[1] = (i>>8) & 255;
|
||||||
|
/*printf("return gp[%d]=%s (len=%d), val=%04x\n",i,gp[i].name,gp[i].len,gp[i].val);*/
|
||||||
|
return gp[i].val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(stderr,"Warning: undefined label '%s' in file %s\n",
|
||||||
|
n, fp->fname);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int reloc_seg(unsigned char *buf, int pos, int ri, int *lreloc, file65 *fp) {
|
||||||
|
int type, seg, old, new;
|
||||||
|
|
||||||
|
/*
|
||||||
|
pos = position of segment in *buf
|
||||||
|
ri = position of relocation table in *buf
|
||||||
|
*/
|
||||||
|
pos--;
|
||||||
|
/*printf("reloc_seg: adr=%04x, tdiff=%04x, ddiff=%04x, bdiff=%04x, zdiff=%04x\n", pos, fp->tdiff, fp->ddiff, fp->bdiff, fp->zdiff); */
|
||||||
|
while(buf[ri]) {
|
||||||
|
if((buf[ri] & 255) == 255) {
|
||||||
|
pos += 254;
|
||||||
|
ri++;
|
||||||
|
} else {
|
||||||
|
pos += buf[ri] & 255;
|
||||||
|
ri++;
|
||||||
|
type = buf[ri] & 0xe0;
|
||||||
|
seg = buf[ri] & 0x07;
|
||||||
|
/*printf("reloc entry @ ri=%04x, pos=%04x, type=%02x, seg=%d\n",ri, pos, type, seg);*/
|
||||||
|
ri++;
|
||||||
|
switch(type) {
|
||||||
|
case 0x80:
|
||||||
|
old = buf[pos] + 256*buf[pos+1];
|
||||||
|
if(seg) {
|
||||||
|
new = old + reldiff(seg);
|
||||||
|
} else {
|
||||||
|
new = old + find_global(buf+ri, fp, &seg);
|
||||||
|
ri += 2; /* account for label number */
|
||||||
|
}
|
||||||
|
/*printf("old=%04x, new=%04x\n",old,new);*/
|
||||||
|
buf[pos] = new & 255;
|
||||||
|
buf[pos+1] = (new>>8)&255;
|
||||||
|
break;
|
||||||
|
case 0x40:
|
||||||
|
old = buf[pos]*256 + buf[ri];
|
||||||
|
if(seg) {
|
||||||
|
new = old + reldiff(seg);
|
||||||
|
} else {
|
||||||
|
new = old + find_global(buf+ri+1, fp, &seg);
|
||||||
|
ri += 2; /* account for label number */
|
||||||
|
}
|
||||||
|
buf[pos] = (new>>8)&255;
|
||||||
|
buf[ri] = new & 255;
|
||||||
|
ri++;
|
||||||
|
break;
|
||||||
|
case 0x20:
|
||||||
|
old = buf[pos];
|
||||||
|
if(seg) {
|
||||||
|
new = old + reldiff(seg);
|
||||||
|
} else {
|
||||||
|
new = old + find_global(buf+ri, fp, &seg);
|
||||||
|
ri += 2; /* account for label number */
|
||||||
|
}
|
||||||
|
buf[pos] = new & 255;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*lreloc = pos;
|
||||||
|
return ++ri;
|
||||||
|
}
|
||||||
92
xa-2.3.5/misc/mkrom.sh
Executable file
92
xa-2.3.5/misc/mkrom.sh
Executable file
|
|
@ -0,0 +1,92 @@
|
||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# xa65 - 6502 cross assembler and utility suite
|
||||||
|
# mkrom.sh - assemble several 'romable' files into one binary
|
||||||
|
# Copyright (C) 1997 André Fachat (a.fachat@physik.tu-chemnitz.de)
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
#
|
||||||
|
|
||||||
|
XA="../xa"
|
||||||
|
FILE=../file65
|
||||||
|
|
||||||
|
start=32768
|
||||||
|
ende=65536
|
||||||
|
romfile=rom65
|
||||||
|
|
||||||
|
next=$[ start + 2 ];
|
||||||
|
pars="-A $next"
|
||||||
|
|
||||||
|
umask 077
|
||||||
|
|
||||||
|
tmp1=/tmp/mkrom65.sh.$$.a
|
||||||
|
tmp2=/tmp/mkrom65.sh.$$.b
|
||||||
|
tmp3=/tmp/mkrom65.sh.$$.c
|
||||||
|
|
||||||
|
echo -e "#include <stdio.h>\nvoid main(int argc, char *argv[]) { printf(\"%c%c\",atoi(argv[1])&255,(atoi(argv[1])/256)&255);}" \
|
||||||
|
> $tmp3;
|
||||||
|
cc $tmp3 -o $tmp2
|
||||||
|
|
||||||
|
while [ $# -ne 0 ]; do
|
||||||
|
case $1 in
|
||||||
|
-A) # get start address
|
||||||
|
start=$[ $2 ];
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-E) # get end address
|
||||||
|
ende=$[ $2 ];
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-R) # get ROM filename
|
||||||
|
romfile=$2;
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-O) # xa options
|
||||||
|
XA="$XA $2";
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-S) # segment addresses - in xa option format
|
||||||
|
pars="$pars $2";
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
break;
|
||||||
|
;;
|
||||||
|
esac;
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
#get file list
|
||||||
|
list="$*"
|
||||||
|
|
||||||
|
|
||||||
|
echo -n > $romfile
|
||||||
|
|
||||||
|
for i in $list; do
|
||||||
|
#echo "next=$next, start=$start, pars=$pars"
|
||||||
|
#echo "cmd= ${XA} -R $pars -o $tmp1 $i"
|
||||||
|
$XA -R $pars -o $tmp1 $i
|
||||||
|
pars=`$FILE -a 2 -P $tmp1`;
|
||||||
|
next=`$FILE -A 0 $tmp1`;
|
||||||
|
|
||||||
|
$tmp2 $next >> $romfile
|
||||||
|
cat $tmp1 >> $romfile;
|
||||||
|
|
||||||
|
done;
|
||||||
|
|
||||||
|
$tmp2 65535 >> $romfile
|
||||||
|
|
||||||
|
rm -f $tmp1 $tmp2 $tmp3
|
||||||
|
|
||||||
109
xa-2.3.5/misc/printcbm.c
Normal file
109
xa-2.3.5/misc/printcbm.c
Normal file
|
|
@ -0,0 +1,109 @@
|
||||||
|
/* printcbm -- A part of xa65 - 65xx/65816 cross-assembler and utility suite
|
||||||
|
* list CBM BASIC programs
|
||||||
|
*
|
||||||
|
* Copyright (C) 1989-1997 André Fachat (a.fachat@physik.tu-chemnitz.de)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
|
#define programname "printcbm"
|
||||||
|
#define progversion "v1.0.0"
|
||||||
|
#define author "Written by André Fachat"
|
||||||
|
#define copyright "Copyright (C) 1997-2002 André Fachat."
|
||||||
|
|
||||||
|
char *cmd[] = {
|
||||||
|
"end", "for", "next", "data", "input#", "input", "dim", "read",
|
||||||
|
"let", "goto", "run", "if", "restore", "gosub", "return",
|
||||||
|
"rem", "stop", "on", "wait", "load", "save", "verify", "def",
|
||||||
|
"poke", "print#", "print", "cont", "list", "clr", "cmd", "sys",
|
||||||
|
"open", "close", "get", "new", "tab(", "to", "fn", "spc(",
|
||||||
|
"then", "not", "step", "+", "-", "*", "/", "^", "and", "or",
|
||||||
|
">", "=", "<", "sgn", "int", "abs", "usr", "fre", "pos", "sqr",
|
||||||
|
"rnd", "log", "exp", "cos", "sin", "tan", "atn", "peek", "len",
|
||||||
|
"str$", "val", "asc", "chr$", "left$", "right$", "mid$", "go"
|
||||||
|
};
|
||||||
|
|
||||||
|
void usage(FILE *fp)
|
||||||
|
{
|
||||||
|
fprintf(fp,
|
||||||
|
"Usage: %s [OPTION]... [FILE]...\n"
|
||||||
|
"List CBM BASIC programs\n"
|
||||||
|
"\n"
|
||||||
|
" --version output version information and exit\n"
|
||||||
|
" --help display this help and exit\n",
|
||||||
|
programname);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
int a, b, c;
|
||||||
|
|
||||||
|
if (argc < 2) {
|
||||||
|
usage(stderr);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strstr(argv[1], "--help")) {
|
||||||
|
usage(stdout);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strstr(argv[1], "--version")) {
|
||||||
|
version(programname, progversion, author, copyright);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fp = fopen(argv[1], "rb");
|
||||||
|
|
||||||
|
if (fp) {
|
||||||
|
b = fgetc(fp);
|
||||||
|
b = fgetc(fp);
|
||||||
|
|
||||||
|
while (b != EOF) {
|
||||||
|
a = fgetc(fp);
|
||||||
|
a = a + 256 * fgetc(fp);
|
||||||
|
|
||||||
|
if (a) {
|
||||||
|
a = fgetc(fp);
|
||||||
|
a = a + 256 * fgetc(fp);
|
||||||
|
printf("%d ", a);
|
||||||
|
|
||||||
|
while ((c = fgetc(fp))) {
|
||||||
|
if (c == EOF)
|
||||||
|
break;
|
||||||
|
if (c >= 0x80 && c < 0xcc)
|
||||||
|
printf("%s", cmd[c - 0x80]);
|
||||||
|
else
|
||||||
|
printf("%c", c);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
} else {
|
||||||
|
printf("File %s not found!\n", argv[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
384
xa-2.3.5/misc/reloc65.c
Normal file
384
xa-2.3.5/misc/reloc65.c
Normal file
|
|
@ -0,0 +1,384 @@
|
||||||
|
/* reloc65 -- A part of xa65 - 65xx/65816 cross-assembler and utility suite
|
||||||
|
* o65 file relocator
|
||||||
|
*
|
||||||
|
* Copyright (C) 1989-1997 André Fachat (a.fachat@physik.tu-chemnitz.de)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
|
#define BUF (9*2+8) /* 16 bit header */
|
||||||
|
|
||||||
|
#define programname "reloc65"
|
||||||
|
#define progversion "v0.2.1"
|
||||||
|
#define author "Written by André Fachat"
|
||||||
|
#define copyright "Copyright (C) 1997-2002 André Fachat."
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *fname;
|
||||||
|
size_t fsize;
|
||||||
|
unsigned char *buf;
|
||||||
|
int tbase, tlen, dbase, dlen, bbase, blen, zbase, zlen;
|
||||||
|
int tdiff, ddiff, bdiff, zdiff;
|
||||||
|
unsigned char *segt;
|
||||||
|
unsigned char *segd;
|
||||||
|
unsigned char *utab;
|
||||||
|
unsigned char *rttab;
|
||||||
|
unsigned char *rdtab;
|
||||||
|
unsigned char *extab;
|
||||||
|
} file65;
|
||||||
|
|
||||||
|
|
||||||
|
int read_options(unsigned char *f);
|
||||||
|
int read_undef(unsigned char *f);
|
||||||
|
unsigned char *reloc_seg(unsigned char *f, int len, unsigned char *rtab, file65 *fp, int undefwarn);
|
||||||
|
unsigned char *reloc_globals(unsigned char *, file65 *fp);
|
||||||
|
|
||||||
|
file65 file;
|
||||||
|
unsigned char cmp[] = { 1, 0, 'o', '6', '5' };
|
||||||
|
|
||||||
|
void usage(FILE *fp)
|
||||||
|
{
|
||||||
|
fprintf(fp,
|
||||||
|
"Usage: %s [OPTION]... [FILE]...\n"
|
||||||
|
"Relocator for o65 object files\n"
|
||||||
|
"\n"
|
||||||
|
" -b? addr relocates segment '?' (i.e. 't' for text segment,\n"
|
||||||
|
" 'd' for data, 'b' for bss and 'z' for zeropage) to the new\n"
|
||||||
|
" address `addr'\n"
|
||||||
|
" -o file uses `file' as output file. Default is `a.o65'\n"
|
||||||
|
" -x? extracts text `?' = `t' or data `?' = `d' segment from file\n",
|
||||||
|
programname);
|
||||||
|
fprintf(fp,
|
||||||
|
" instead of writing back the whole file\n"
|
||||||
|
" -X extracts the file such that text and data\n"
|
||||||
|
" segments are chained, i.e. possibly relocating\n"
|
||||||
|
" the data segment to the end of the text segment\n"
|
||||||
|
" --version output version information and exit\n"
|
||||||
|
" --help display this help and exit\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
int i = 1, mode, hlen;
|
||||||
|
size_t n;
|
||||||
|
FILE *fp;
|
||||||
|
int tflag = 0, dflag = 0, bflag = 0, zflag = 0;
|
||||||
|
int tbase = 0, dbase = 0, bbase = 0, zbase = 0;
|
||||||
|
char *outfile = "a.o65";
|
||||||
|
int extract = 0;
|
||||||
|
|
||||||
|
if (argc <= 1) {
|
||||||
|
usage(stderr);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strstr(argv[1], "--help")) {
|
||||||
|
usage(stdout);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strstr(argv[1], "--version")) {
|
||||||
|
version(programname, progversion, author, copyright);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
while(i<argc) {
|
||||||
|
if(argv[i][0]=='-') {
|
||||||
|
/* process options */
|
||||||
|
switch(argv[i][1]) {
|
||||||
|
case 'o':
|
||||||
|
if(argv[i][2]) outfile=argv[i]+2;
|
||||||
|
else outfile=argv[++i];
|
||||||
|
break;
|
||||||
|
case 'X':
|
||||||
|
extract=3;
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
switch(argv[i][2]) {
|
||||||
|
case 't':
|
||||||
|
tflag= 1;
|
||||||
|
if(argv[i][3]) tbase = atoi(argv[i]+3);
|
||||||
|
else tbase = atoi(argv[++i]);
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
dflag= 1;
|
||||||
|
if(argv[i][3]) dbase = atoi(argv[i]+3);
|
||||||
|
else dbase = atoi(argv[++i]);
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
bflag= 1;
|
||||||
|
if(argv[i][3]) bbase = atoi(argv[i]+3);
|
||||||
|
else bbase = atoi(argv[++i]);
|
||||||
|
break;
|
||||||
|
case 'z':
|
||||||
|
zflag= 1;
|
||||||
|
if(argv[i][3]) zbase = atoi(argv[i]+3);
|
||||||
|
else zbase = atoi(argv[++i]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("Unknown segment type '%c' - ignored!\n", argv[i][2]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'x': /* extract segment */
|
||||||
|
switch(argv[i][2]) {
|
||||||
|
case 't':
|
||||||
|
extract = 1;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
extract = 2;
|
||||||
|
break;
|
||||||
|
case 'z':
|
||||||
|
case 'b':
|
||||||
|
printf("Cannot extract segment type '%c' - ignored!\n", argv[i][2]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("Unknown segment type '%c' - ignored!\n", argv[i][2]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr,"reloc65: %s unknown option, use '-?' for help\n",argv[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
struct stat fs;
|
||||||
|
file.fname=argv[i];
|
||||||
|
stat(argv[i], &fs);
|
||||||
|
file.fsize=fs.st_size;
|
||||||
|
file.buf=malloc(file.fsize);
|
||||||
|
if(!file.buf) {
|
||||||
|
fprintf(stderr,"Oops, no more memory!\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
printf("reloc65: read file %s -> %s\n",argv[i],outfile);
|
||||||
|
fp = fopen(argv[i],"rb");
|
||||||
|
if(fp) {
|
||||||
|
n = fread(file.buf, 1, file.fsize, fp);
|
||||||
|
fclose(fp);
|
||||||
|
if((n>=file.fsize) && (!memcmp(file.buf, cmp, 5))) {
|
||||||
|
mode=file.buf[7]*256+file.buf[6];
|
||||||
|
if(mode & 0x2000) {
|
||||||
|
fprintf(stderr,"reloc65: %s: 32 bit size not supported\n", argv[i]);
|
||||||
|
} else
|
||||||
|
if(mode & 0x4000) {
|
||||||
|
fprintf(stderr,"reloc65: %s: pagewise relocation not supported\n", argv[i]);
|
||||||
|
} else {
|
||||||
|
hlen = BUF+read_options(file.buf+BUF);
|
||||||
|
|
||||||
|
file.tbase = file.buf[ 9]*256+file.buf[ 8];
|
||||||
|
file.tlen = file.buf[11]*256+file.buf[10];
|
||||||
|
file.tdiff = tflag? tbase - file.tbase : 0;
|
||||||
|
file.dbase = file.buf[13]*256+file.buf[12];
|
||||||
|
file.dlen = file.buf[15]*256+file.buf[14];
|
||||||
|
if (extract == 3) {
|
||||||
|
if (dflag) {
|
||||||
|
fprintf(stderr,"reloc65: %s: Warning: data segment address ignored for -X option\n", argv[i]);
|
||||||
|
}
|
||||||
|
dbase = file.tbase + file.tdiff + file.tlen;
|
||||||
|
file.ddiff = dbase - file.dbase;
|
||||||
|
} else {
|
||||||
|
file.ddiff = dflag? dbase - file.dbase : 0;
|
||||||
|
}
|
||||||
|
file.bbase = file.buf[17]*256+file.buf[16];
|
||||||
|
file.blen = file.buf[19]*256+file.buf[18];
|
||||||
|
file.bdiff = bflag? bbase - file.bbase : 0;
|
||||||
|
file.zbase = file.buf[21]*256+file.buf[20];
|
||||||
|
file.zlen = file.buf[23]*256+file.buf[21];
|
||||||
|
file.zdiff = zflag? zbase - file.zbase : 0;
|
||||||
|
|
||||||
|
file.segt = file.buf + hlen;
|
||||||
|
file.segd = file.segt + file.tlen;
|
||||||
|
file.utab = file.segd + file.dlen;
|
||||||
|
|
||||||
|
file.rttab = file.utab + read_undef(file.utab);
|
||||||
|
file.rdtab = reloc_seg(file.segt, file.tlen, file.rttab,
|
||||||
|
&file, extract);
|
||||||
|
file.extab = reloc_seg(file.segd, file.dlen, file.rdtab,
|
||||||
|
&file, extract);
|
||||||
|
|
||||||
|
reloc_globals(file.extab, &file);
|
||||||
|
|
||||||
|
if(tflag) {
|
||||||
|
file.buf[ 9]= (tbase>>8)&255;
|
||||||
|
file.buf[ 8]= tbase & 255;
|
||||||
|
}
|
||||||
|
if(dflag) {
|
||||||
|
file.buf[13]= (dbase>>8)&255;
|
||||||
|
file.buf[12]= dbase & 255;
|
||||||
|
}
|
||||||
|
if(bflag) {
|
||||||
|
file.buf[17]= (bbase>>8)&255;
|
||||||
|
file.buf[16]= bbase & 255;
|
||||||
|
}
|
||||||
|
if(zflag) {
|
||||||
|
file.buf[21]= (zbase>>8)&255;
|
||||||
|
file.buf[20]= zbase & 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
fp = fopen(outfile, "wb");
|
||||||
|
if(fp) {
|
||||||
|
switch(extract) {
|
||||||
|
case 0: /* whole file */
|
||||||
|
fwrite(file.buf, 1, file.fsize, fp);
|
||||||
|
break;
|
||||||
|
case 1: /* text segment */
|
||||||
|
fwrite(file.segt, 1, file.tlen, fp);
|
||||||
|
break;
|
||||||
|
case 2: /* data segment */
|
||||||
|
fwrite(file.segd, 1, file.dlen, fp);
|
||||||
|
break;
|
||||||
|
case 3: /* text+data */
|
||||||
|
fwrite(file.segt, 1, file.tlen, fp);
|
||||||
|
fwrite(file.segd, 1, file.dlen, fp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr,"reloc65: write '%s': %s\n",
|
||||||
|
outfile, strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fprintf(stderr,"reloc65: %s: not an o65 file!\n", argv[i]);
|
||||||
|
if(file.buf[0]==1 && file.buf[1]==8 && file.buf[3]==8) {
|
||||||
|
printf("%s: C64 BASIC executable (start address $0801)?\n", argv[i]);
|
||||||
|
} else
|
||||||
|
if(file.buf[0]==1 && file.buf[1]==4 && file.buf[3]==4) {
|
||||||
|
printf("%s: CBM PET BASIC executable (start address $0401)?\n", argv[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fprintf(stderr,"reloc65: read '%s': %s\n",
|
||||||
|
argv[i], strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int read_options(unsigned char *buf) {
|
||||||
|
int c, l=0;
|
||||||
|
|
||||||
|
c=buf[0];
|
||||||
|
while(c && c!=EOF) {
|
||||||
|
c&=255;
|
||||||
|
l+=c;
|
||||||
|
c=buf[l];
|
||||||
|
}
|
||||||
|
return ++l;
|
||||||
|
}
|
||||||
|
|
||||||
|
int read_undef(unsigned char *buf) {
|
||||||
|
int n, l = 2;
|
||||||
|
|
||||||
|
n = buf[0] + 256*buf[1];
|
||||||
|
while(n){
|
||||||
|
n--;
|
||||||
|
while(buf[l] != 0) {
|
||||||
|
l++;
|
||||||
|
}
|
||||||
|
l++;
|
||||||
|
}
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define reldiff(s) (((s)==2)?fp->tdiff:(((s)==3)?fp->ddiff:(((s)==4)?fp->bdiff:(((s)==5)?fp->zdiff:0))))
|
||||||
|
|
||||||
|
unsigned char *reloc_seg(unsigned char *buf, int len, unsigned char *rtab,
|
||||||
|
file65 *fp, int undefwarn) {
|
||||||
|
int adr = -1;
|
||||||
|
int type, seg, old, new;
|
||||||
|
/*printf("tdiff=%04x, ddiff=%04x, bdiff=%04x, zdiff=%04x\n",
|
||||||
|
fp->tdiff, fp->ddiff, fp->bdiff, fp->zdiff);*/
|
||||||
|
while(*rtab) {
|
||||||
|
if((*rtab & 255) == 255) {
|
||||||
|
adr += 254;
|
||||||
|
rtab++;
|
||||||
|
} else {
|
||||||
|
adr += *rtab & 255;
|
||||||
|
rtab++;
|
||||||
|
type = *rtab & 0xe0;
|
||||||
|
seg = *rtab & 0x07;
|
||||||
|
/*printf("reloc entry @ rtab=%p (offset=%d), adr=%04x, type=%02x, seg=%d\n",rtab-1, *(rtab-1), adr, type, seg);*/
|
||||||
|
rtab++;
|
||||||
|
switch(type) {
|
||||||
|
case 0x80: /* WORD - two byte address */
|
||||||
|
old = buf[adr] + 256*buf[adr+1];
|
||||||
|
new = old + reldiff(seg);
|
||||||
|
buf[adr] = new & 255;
|
||||||
|
buf[adr+1] = (new>>8)&255;
|
||||||
|
break;
|
||||||
|
case 0x40: /* HIGH - high byte of an address */
|
||||||
|
old = buf[adr]*256 + *rtab;
|
||||||
|
new = old + reldiff(seg);
|
||||||
|
buf[adr] = (new>>8)&255;
|
||||||
|
*rtab = new & 255;
|
||||||
|
rtab++;
|
||||||
|
break;
|
||||||
|
case 0x20: /* LOW - low byt of an address */
|
||||||
|
old = buf[adr];
|
||||||
|
new = old + reldiff(seg);
|
||||||
|
buf[adr] = new & 255;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(seg==0) {
|
||||||
|
/* undefined segment entry */
|
||||||
|
if (undefwarn) {
|
||||||
|
fprintf(stderr,"reloc65: %s: Warning: undefined relocation table entry not handled!\n", fp->fname);
|
||||||
|
}
|
||||||
|
rtab+=2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(adr > len) {
|
||||||
|
fprintf(stderr,"reloc65: %s: Warning: relocation table entries past segment end!\n",
|
||||||
|
fp->fname);
|
||||||
|
fprintf(stderr, "reloc65: adr=%x len=%x\n", adr, len);
|
||||||
|
}
|
||||||
|
return ++rtab;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char *reloc_globals(unsigned char *buf, file65 *fp) {
|
||||||
|
int n, old, new, seg;
|
||||||
|
|
||||||
|
n = buf[0] + 256*buf[1];
|
||||||
|
buf +=2;
|
||||||
|
|
||||||
|
while(n) {
|
||||||
|
/*printf("relocating %s, ", buf);*/
|
||||||
|
while(*(buf++));
|
||||||
|
seg = *buf;
|
||||||
|
old = buf[1] + 256*buf[2];
|
||||||
|
new = old + reldiff(seg);
|
||||||
|
/*printf("old=%04x, seg=%d, rel=%04x, new=%04x\n", old, seg, reldiff(seg), new);*/
|
||||||
|
buf[1] = new & 255;
|
||||||
|
buf[2] = (new>>8) & 255;
|
||||||
|
buf +=3;
|
||||||
|
n--;
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
207
xa-2.3.5/misc/uncpk.c
Normal file
207
xa-2.3.5/misc/uncpk.c
Normal file
|
|
@ -0,0 +1,207 @@
|
||||||
|
/* reloc65 -- A part of xa65 - 65xx/65816 cross-assembler and utility suite
|
||||||
|
* Pack/Unpack cpk archive files
|
||||||
|
*
|
||||||
|
* Copyright (C) 1989-2002 André Fachat (a.fachat@physik.tu-chemnitz.de)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
|
#define max(a, b) (a > b) ? a : b
|
||||||
|
#define min(a, b) (a < b) ? a : b
|
||||||
|
|
||||||
|
#define programname "uncpk"
|
||||||
|
#define progversion "v0.2.1"
|
||||||
|
#define author "Written by André Fachat"
|
||||||
|
#define copyright "Copyright (C) 1997-2002 André Fachat."
|
||||||
|
|
||||||
|
FILE *fp;
|
||||||
|
char name[100];
|
||||||
|
char *s;
|
||||||
|
|
||||||
|
void usage(FILE *fp)
|
||||||
|
{
|
||||||
|
fprintf(fp,
|
||||||
|
"Usage: %s [OPTION]... [FILE]...\n"
|
||||||
|
"Manage c64 cpk archives\n"
|
||||||
|
"\n"
|
||||||
|
" c create an archive\n"
|
||||||
|
" a add a file to an archive\n"
|
||||||
|
" x extract archive\n"
|
||||||
|
" l list contents of archive\n"
|
||||||
|
" v verbose output\n"
|
||||||
|
" --version output version information and exit\n"
|
||||||
|
" --help display this help and exit\n",
|
||||||
|
programname);
|
||||||
|
}
|
||||||
|
|
||||||
|
int list=0,verbose=0,add=0,create=0;
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int i,c,c2,fileok, nc;
|
||||||
|
size_t n,n2;
|
||||||
|
FILE *fp,*fpo=NULL;
|
||||||
|
|
||||||
|
if (argc <= 1) {
|
||||||
|
usage(stderr);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strstr(argv[1], "--help")) {
|
||||||
|
usage(stdout);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strstr(argv[1], "--version")) {
|
||||||
|
version(programname, progversion, author, copyright);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strchr(argv[1],(int)'l')) {
|
||||||
|
list=1;
|
||||||
|
}
|
||||||
|
if(strchr(argv[1],(int)'v')) {
|
||||||
|
verbose=1;
|
||||||
|
}
|
||||||
|
if(strchr(argv[1],(int)'a')) {
|
||||||
|
add=1;
|
||||||
|
}
|
||||||
|
if(strchr(argv[1],(int)'c')) {
|
||||||
|
create=1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(add||create) {
|
||||||
|
if (argc <= 3) {
|
||||||
|
usage(stderr);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if(add) {
|
||||||
|
fpo=fopen(argv[2],"ab");
|
||||||
|
} else
|
||||||
|
if(create) {
|
||||||
|
fpo=fopen(argv[2],"wb");
|
||||||
|
}
|
||||||
|
if(fpo) {
|
||||||
|
if(!add) fputc(1,fpo); /* Version Byte */
|
||||||
|
for(i=3;i<argc;i++) {
|
||||||
|
if(verbose) printf("%s\n",argv[i]);
|
||||||
|
fp=fopen(argv[i],"rb");
|
||||||
|
if(fp) {
|
||||||
|
while((s=strchr(argv[i],':'))) *s='/';
|
||||||
|
fprintf(fpo,"%s",argv[i]);
|
||||||
|
fputc(0,fpo);
|
||||||
|
c=fgetc(fp);
|
||||||
|
while(c!=EOF) {
|
||||||
|
n=1;
|
||||||
|
while((c2=fgetc(fp))==c) {
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
while(n) {
|
||||||
|
if(n>=4 || c==0xf7) {
|
||||||
|
n2=min(255,n);
|
||||||
|
fprintf(fpo,"\xf7%c%c",(char)n2,(char)c);
|
||||||
|
n-=n2;
|
||||||
|
} else {
|
||||||
|
fputc(c,fpo);
|
||||||
|
n--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c=c2;
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
fputc(0xf7,fpo); fputc(0,fpo);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr,"Couldn't open file '%s' for reading!",argv[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(fpo);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr,"Couldn't open file '%s' for writing!",argv[1]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (argc != 3) {
|
||||||
|
usage(stderr);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
fp=fopen(argv[2],"rb");
|
||||||
|
if(fp){
|
||||||
|
if(fgetc(fp)==1){
|
||||||
|
do{
|
||||||
|
/* read name */
|
||||||
|
i=0;
|
||||||
|
while((c=fgetc(fp))){
|
||||||
|
if(c==EOF) break;
|
||||||
|
name[i++]=c;
|
||||||
|
}
|
||||||
|
name[i++]='\0';
|
||||||
|
if(!c){ /* end of archive ? */
|
||||||
|
while((s=strchr(name,'/'))) *s=':';
|
||||||
|
|
||||||
|
if(verbose+list) printf("%s\n",name);
|
||||||
|
|
||||||
|
if(!list) {
|
||||||
|
fpo=fopen(name,"wb");
|
||||||
|
if(!fpo) {
|
||||||
|
fprintf(stderr,"Couldn't open output file %s !\n",name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fileok=0;
|
||||||
|
while((c=fgetc(fp))!=EOF){
|
||||||
|
/* test if 'compressed' */
|
||||||
|
if(c==0xf7){
|
||||||
|
nc=fgetc(fp);
|
||||||
|
if(!nc) {
|
||||||
|
fileok=1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
c=fgetc(fp);
|
||||||
|
if(fpo) { /* extract */
|
||||||
|
if(nc!=EOF && c!=EOF) {
|
||||||
|
nc &= 255;
|
||||||
|
while(nc--) {
|
||||||
|
fputc(c,fpo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(fpo) {
|
||||||
|
fputc(c,fpo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(fpo) {
|
||||||
|
fclose(fpo);
|
||||||
|
fpo=NULL;
|
||||||
|
}
|
||||||
|
if(!fileok) {
|
||||||
|
fprintf(stderr,"Unexpected end of file!\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while(c!=EOF);
|
||||||
|
} else
|
||||||
|
fprintf(stderr,"Wrong Version!\n");
|
||||||
|
fclose(fp);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr,"File %s not found!\n",argv[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
37
xa-2.3.5/misc/version.h
Normal file
37
xa-2.3.5/misc/version.h
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
/* xa65 - 65xx/65816 cross-assembler and utility suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 1989-1997 André Fachat (a.fachat@physik.tu-chemnitz.de)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
#ifndef __XA65_VERSION_H__
|
||||||
|
#define __XA65_VERSION_H__
|
||||||
|
|
||||||
|
void version(const char *programname, const char *progversion,
|
||||||
|
const char *authors, const char *copyright)
|
||||||
|
{
|
||||||
|
fprintf(stdout,
|
||||||
|
"%s (xa65) %s\n"
|
||||||
|
"%s\n"
|
||||||
|
"\n"
|
||||||
|
"%s\n"
|
||||||
|
"This is free software; see the source for "
|
||||||
|
"copying conditions. There is NO\n"
|
||||||
|
"warranty; not even for MERCHANTABILIY or "
|
||||||
|
"FITNESS FOR A PARTICULAR PURPOSE.\n",
|
||||||
|
programname, progversion, authors, copyright);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __XA65_VERSION_H__ */
|
||||||
18
xa-2.3.5/src/Makefile
Normal file
18
xa-2.3.5/src/Makefile
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
OBJ = xa.o xaa.o xal.o xap.o xat.o xar.o xar2.o xao.o xau.o xam.o xacharset.o
|
||||||
|
|
||||||
|
#CFLAGS=-W -Wall -pedantic -ansi #-g
|
||||||
|
#CFLAGS=-W -Wall -ansi -O2
|
||||||
|
#LD = ${CC}
|
||||||
|
#LDFLAGS = "-lc"
|
||||||
|
|
||||||
|
all: xa
|
||||||
|
|
||||||
|
xa: ${OBJ}
|
||||||
|
${LD} -o ../xa ${OBJ} ${LDFLAGS}
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.o *.o65
|
||||||
|
|
||||||
|
mrproper: clean
|
||||||
|
rm -f ../xa
|
||||||
|
|
||||||
37
xa-2.3.5/src/version.h
Normal file
37
xa-2.3.5/src/version.h
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
/* xa65 - 65xx/65816 cross-assembler and utility suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 1989-1997 André Fachat (a.fachat@physik.tu-chemnitz.de)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
#ifndef __XA65_VERSION_H__
|
||||||
|
#define __XA65_VERSION_H__
|
||||||
|
|
||||||
|
void version(const char *programname, const char *progversion,
|
||||||
|
const char *authors, const char *copyright)
|
||||||
|
{
|
||||||
|
fprintf(stdout,
|
||||||
|
"%s (xa65) %s\n"
|
||||||
|
"%s\n"
|
||||||
|
"\n"
|
||||||
|
"%s\n"
|
||||||
|
"This is free software; see the source for "
|
||||||
|
"copying conditions. There is NO\n"
|
||||||
|
"warranty; not even for MERCHANTABILIY or "
|
||||||
|
"FITNESS FOR A PARTICULAR PURPOSE.\n",
|
||||||
|
programname, progversion, authors, copyright);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __XA65_VERSION_H__ */
|
||||||
1131
xa-2.3.5/src/xa.c
Normal file
1131
xa-2.3.5/src/xa.c
Normal file
File diff suppressed because it is too large
Load diff
49
xa-2.3.5/src/xa.h
Normal file
49
xa-2.3.5/src/xa.h
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
/* xa65 - 65xx/65816 cross-assembler and utility suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 1989-1997 André Fachat (a.fachat@physik.tu-chemnitz.de)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
#ifndef __XA65_XA_H__
|
||||||
|
#define __XA65_XA_H__
|
||||||
|
|
||||||
|
#include "xah.h" /* For SEG_MAX */
|
||||||
|
|
||||||
|
extern int ncmos, cmosfl, w65816, n65816;
|
||||||
|
extern int masm, nolink;
|
||||||
|
extern int noglob;
|
||||||
|
extern int showblk;
|
||||||
|
extern int relmode;
|
||||||
|
extern int crossref;
|
||||||
|
extern char altppchar;
|
||||||
|
|
||||||
|
extern int tlen, tbase;
|
||||||
|
extern int blen, bbase;
|
||||||
|
extern int dlen, dbase;
|
||||||
|
extern int zlen, zbase;
|
||||||
|
extern int romable, romaddr;
|
||||||
|
|
||||||
|
extern int memode,xmode;
|
||||||
|
extern int segment;
|
||||||
|
extern int pc[SEG_MAX];
|
||||||
|
|
||||||
|
int h_length(void);
|
||||||
|
|
||||||
|
void set_align(int align_value);
|
||||||
|
|
||||||
|
void errout(int er);
|
||||||
|
void logout(char *s);
|
||||||
|
|
||||||
|
#endif /*__XA65_XA_H__ */
|
||||||
274
xa-2.3.5/src/xaa.c
Normal file
274
xa-2.3.5/src/xaa.c
Normal file
|
|
@ -0,0 +1,274 @@
|
||||||
|
/* xa65 - 65xx/65816 cross-assembler and utility suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 1989-1997 André Fachat (a.fachat@physik.tu-chemnitz.de)
|
||||||
|
*
|
||||||
|
* Preprocessing arithmetic module
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "xah.h"
|
||||||
|
|
||||||
|
#include "xad.h"
|
||||||
|
#include "xar.h"
|
||||||
|
#include "xa.h"
|
||||||
|
#include "xal.h"
|
||||||
|
#include "xaa.h"
|
||||||
|
#include "xat.h"
|
||||||
|
|
||||||
|
static int pr[]= { P_START,P_ADD,P_ADD,P_MULT,P_MULT,P_SHIFT,P_SHIFT,P_CMP,
|
||||||
|
P_CMP,P_EQU,P_CMP,P_CMP,P_EQU,P_AND,P_XOR,P_OR,
|
||||||
|
P_LAND,P_LOR };
|
||||||
|
|
||||||
|
static int pp,pcc;
|
||||||
|
static int fundef;
|
||||||
|
|
||||||
|
static int ag_term(signed char*,int,int*,int*,int*);
|
||||||
|
static int get_op(signed char*,int*);
|
||||||
|
static int do_op(int*,int,int);
|
||||||
|
|
||||||
|
/* s = string, v = variable */
|
||||||
|
int a_term(signed char *s, int *v, int *l, int xpc, int *pfl, int *label, int f)
|
||||||
|
{
|
||||||
|
int er=E_OK;
|
||||||
|
int afl = 0, bfl;
|
||||||
|
|
||||||
|
*pfl = 0;
|
||||||
|
fundef = f;
|
||||||
|
|
||||||
|
pp=0;
|
||||||
|
pcc=xpc;
|
||||||
|
|
||||||
|
if(s[0]=='<')
|
||||||
|
{
|
||||||
|
pp++;
|
||||||
|
er=ag_term(s,P_START,v,&afl, label);
|
||||||
|
bfl = afl & (A_MASK>>8);
|
||||||
|
if( bfl && (bfl != (A_ADR>>8)) && (bfl != (A_LOW>>8)) ) {
|
||||||
|
/*fprintf(stderr,"low byte relocation for a high byte - won't work!\n");*/
|
||||||
|
errout(W_LOWACC);
|
||||||
|
}
|
||||||
|
if(afl) *pfl=A_LOW | ((afl<<8) & A_FMASK);
|
||||||
|
*v = *v & 255;
|
||||||
|
} else
|
||||||
|
if(s[pp]=='>')
|
||||||
|
{
|
||||||
|
pp++;
|
||||||
|
er=ag_term(s,P_START,v,&afl, label);
|
||||||
|
bfl = afl & (A_MASK>>8);
|
||||||
|
if( bfl && (bfl != (A_ADR>>8)) && (bfl != (A_HIGH>>8)) ) {
|
||||||
|
/*fprintf(stderr,"high byte relocation for a low byte - won't work!\n");*/
|
||||||
|
errout(W_HIGHACC);
|
||||||
|
}
|
||||||
|
if(afl) *pfl=A_HIGH | ((afl<<8) & A_FMASK) | (*v & 255);
|
||||||
|
*v=(*v>>8)&255;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
er=ag_term(s,P_START,v,&afl, label);
|
||||||
|
bfl = afl & (A_MASK>>8);
|
||||||
|
if(bfl && (bfl != (A_ADR>>8)) ) {
|
||||||
|
/*fprintf(stderr,"address relocation for a low or high byte - won't work!\n");*/
|
||||||
|
errout(W_ADDRACC);
|
||||||
|
}
|
||||||
|
if(afl) *pfl = A_ADR | ((afl<<8) & A_FMASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
*l=pp;
|
||||||
|
/* printf("a_term: afl->%04x *pfl=%04x, (pc=%04x)\n",afl,*pfl, xpc); */
|
||||||
|
return(er);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ag_term(signed char *s, int p, int *v, int *nafl, int *label)
|
||||||
|
{
|
||||||
|
int er=E_OK,o,w,mf=1,afl;
|
||||||
|
|
||||||
|
afl = 0;
|
||||||
|
|
||||||
|
/*printf("ag_term(%02x %02x %02x %02x %02x %02x\n",s[0],s[1],s[2],s[3],s[4],s[5]);*/
|
||||||
|
while(s[pp]=='-')
|
||||||
|
{
|
||||||
|
pp++;
|
||||||
|
mf=-mf;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(s[pp]=='(')
|
||||||
|
{
|
||||||
|
pp++;
|
||||||
|
if(!(er=ag_term(s,P_START,v,&afl,label)))
|
||||||
|
{
|
||||||
|
if(s[pp]!=')')
|
||||||
|
er=E_SYNTAX;
|
||||||
|
else
|
||||||
|
pp++;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
if(s[pp]==T_LABEL)
|
||||||
|
{
|
||||||
|
er=l_get(cval(s+pp+1),v, &afl);
|
||||||
|
/* printf("label: er=%d, seg=%d, afl=%d, nolink=%d, fundef=%d\n",
|
||||||
|
er, segment, afl, nolink, fundef); */
|
||||||
|
if(er==E_NODEF && segment != SEG_ABS && fundef ) {
|
||||||
|
if( nolink || (afl==SEG_UNDEF)) {
|
||||||
|
er = E_OK;
|
||||||
|
*v = 0;
|
||||||
|
afl = SEG_UNDEF;
|
||||||
|
*label = cval(s+pp+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pp+=3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(s[pp]==T_VALUE)
|
||||||
|
{
|
||||||
|
*v=lval(s+pp+1);
|
||||||
|
pp+=4;
|
||||||
|
/* printf("value: v=%04x\n",*v); */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(s[pp]==T_POINTER)
|
||||||
|
{
|
||||||
|
afl = s[pp+1];
|
||||||
|
*v=cval(s+pp+2);
|
||||||
|
pp+=4;
|
||||||
|
/* printf("pointer: v=%04x, afl=%04x\n",*v,afl); */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(s[pp]=='*')
|
||||||
|
{
|
||||||
|
*v=pcc;
|
||||||
|
pp++;
|
||||||
|
afl = segment;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
er=E_SYNTAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
*v *= mf;
|
||||||
|
|
||||||
|
while(!er && s[pp]!=')' && s[pp]!=']' && s[pp]!=',' && s[pp]!=T_END)
|
||||||
|
{
|
||||||
|
er=get_op(s,&o);
|
||||||
|
|
||||||
|
if(!er && pr[o]>p)
|
||||||
|
{
|
||||||
|
pp+=1;
|
||||||
|
if(!(er=ag_term(s,pr[o],&w, nafl, label)))
|
||||||
|
{
|
||||||
|
if(afl || *nafl) { /* check pointer arithmetic */
|
||||||
|
if((afl == *nafl) && (afl!=SEG_UNDEF) && o==2) {
|
||||||
|
afl = 0; /* substract two pointers */
|
||||||
|
} else
|
||||||
|
if(((afl && !*nafl) || (*nafl && !afl)) && o==1) {
|
||||||
|
afl=(afl | *nafl); /* add constant to pointer */
|
||||||
|
} else
|
||||||
|
if((afl && !*nafl) && o==2) {
|
||||||
|
afl=(afl | *nafl); /* substract constant from pointer */
|
||||||
|
} else {
|
||||||
|
if(segment!=SEG_ABS) {
|
||||||
|
if(!dsb_len) {
|
||||||
|
er=E_ILLPOINTER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
afl=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!er) er=do_op(v,w,o);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*nafl = afl;
|
||||||
|
return(er);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_op(signed char *s, int *o)
|
||||||
|
{
|
||||||
|
int er;
|
||||||
|
|
||||||
|
*o=s[pp];
|
||||||
|
|
||||||
|
if(*o<1 || *o>17)
|
||||||
|
er=E_SYNTAX;
|
||||||
|
else
|
||||||
|
er=E_OK;
|
||||||
|
|
||||||
|
return(er);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int do_op(int *w,int w2,int o)
|
||||||
|
{
|
||||||
|
int er=E_OK;
|
||||||
|
switch (o) {
|
||||||
|
case 1:
|
||||||
|
*w +=w2;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
*w -=w2;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
*w *=w2;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
if (w!=0)
|
||||||
|
*w /=w2;
|
||||||
|
else
|
||||||
|
er =E_DIV;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
*w >>=w2;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
*w <<=w2;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
*w = *w<w2;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
*w = *w>w2;
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
*w = *w==w2;
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
*w = *w<=w2;
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
*w = *w>=w2;
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
*w = *w!=w2;
|
||||||
|
break;
|
||||||
|
case 13:
|
||||||
|
*w &=w2;
|
||||||
|
break;
|
||||||
|
case 14:
|
||||||
|
*w ^=w2;
|
||||||
|
break;
|
||||||
|
case 15:
|
||||||
|
*w |=w2;
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
*w =*w&&w2;
|
||||||
|
break;
|
||||||
|
case 17:
|
||||||
|
*w =*w||w2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return(er);
|
||||||
|
}
|
||||||
|
|
||||||
26
xa-2.3.5/src/xaa.h
Normal file
26
xa-2.3.5/src/xaa.h
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
/* xa65 - 65xx/65816 cross-assembler and utility suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 1989-1997 André Fachat (a.fachat@physik.tu-chemnitz.de)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
#ifndef __XA65_XAA_H__
|
||||||
|
#define __XA65_XAA_H__
|
||||||
|
|
||||||
|
/* f = 0 -> label must exist; f = 1 -> SEG_UNDEF entry */
|
||||||
|
int a_term(signed char *s, int *v, int *l, int xpc, int *afl,
|
||||||
|
int *label, int f);
|
||||||
|
|
||||||
|
#endif /* __XA65_XAA_H__ */
|
||||||
125
xa-2.3.5/src/xacharset.c
Normal file
125
xa-2.3.5/src/xacharset.c
Normal file
|
|
@ -0,0 +1,125 @@
|
||||||
|
/* xa65 - 65xx/65816 cross-assembler and utility suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 1989-1997 Andre Fachat (a.fachat@physik.tu-chemnitz.de)
|
||||||
|
* Maintained by Cameron Kaiser
|
||||||
|
*
|
||||||
|
* Charset conversion module
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "xacharset.h"
|
||||||
|
|
||||||
|
static signed char (*convert_func)(signed char);
|
||||||
|
|
||||||
|
static signed char convert_char_ascii(signed char c) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PETSCII conversion roughly follows the PETSCII to UNICODE
|
||||||
|
* mapping at http://www.df.lth.se/~triad/krad/recode/petscii_c64en_lc.txt
|
||||||
|
* linked from wikipedia http://en.wikipedia.org/wiki/PETSCII
|
||||||
|
*/
|
||||||
|
static signed char convert_char_petscii(signed char c) {
|
||||||
|
if (c >= 0x41 && c < 0x5b) {
|
||||||
|
return c + 0x20;
|
||||||
|
}
|
||||||
|
if (c >= 0x61 && c < 0x7b) {
|
||||||
|
return c - 0x20;
|
||||||
|
}
|
||||||
|
if (c == 0x7f) {
|
||||||
|
return 0x14;
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Built upon Steve Judd's suggested PETSCII -> screen code algorithm
|
||||||
|
* This could probably be written a lot better, but it works.
|
||||||
|
* http://www.floodgap.com/retrobits/ckb/display.cgi?572
|
||||||
|
*/
|
||||||
|
static signed char convert_char_petscreen(signed char c) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
i = (int)convert_char_petscii(c);
|
||||||
|
#ifdef SIGH
|
||||||
|
fprintf(stderr, "input: %i output: %i\n", c, i);
|
||||||
|
#endif
|
||||||
|
if (i< 0)
|
||||||
|
i += 0x80;
|
||||||
|
i ^= 0xe0;
|
||||||
|
#ifdef SIGH
|
||||||
|
fprintf(stderr, "(1)input: %i output: %i\n", c, i);
|
||||||
|
#endif
|
||||||
|
i += 0x20;
|
||||||
|
i &= 0xff;
|
||||||
|
#ifdef SIGH
|
||||||
|
fprintf(stderr, "(2)input: %i output: %i\n", c, i);
|
||||||
|
#endif
|
||||||
|
if (i < 0x80)
|
||||||
|
return (signed char)i;
|
||||||
|
i += 0x40;
|
||||||
|
i &= 0xff;
|
||||||
|
#ifdef SIGH
|
||||||
|
fprintf(stderr, "(3)input: %i output: %i\n", c, i);
|
||||||
|
#endif
|
||||||
|
if (i < 0x80)
|
||||||
|
return (signed char)i;
|
||||||
|
i ^= 0xa0;
|
||||||
|
#ifdef SIGH
|
||||||
|
fprintf(stderr, "(4)input: %i output: %i\n", c, i);
|
||||||
|
#endif
|
||||||
|
return (signed char)i;
|
||||||
|
}
|
||||||
|
|
||||||
|
static signed char convert_char_high(signed char c) {
|
||||||
|
return (c | 0x80);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *name;
|
||||||
|
signed char (*func)(signed char);
|
||||||
|
} charset;
|
||||||
|
|
||||||
|
static charset charsets[] = {
|
||||||
|
{ "ASCII", convert_char_ascii },
|
||||||
|
{ "PETSCII", convert_char_petscii },
|
||||||
|
{ "PETSCREEN", convert_char_petscreen },
|
||||||
|
{ "HIGH", convert_char_high },
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
int set_charset(char *charset_name) {
|
||||||
|
int i = 0;
|
||||||
|
while (charsets[i].name != NULL) {
|
||||||
|
if (strcmp(charsets[i].name, charset_name) == 0) {
|
||||||
|
convert_func = charsets[i].func;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
signed char convert_char(signed char c) {
|
||||||
|
return convert_func(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
31
xa-2.3.5/src/xacharset.h
Normal file
31
xa-2.3.5/src/xacharset.h
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
/* xa65 - 65xx/65816 cross-assembler and utility suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 1989-2006 André Fachat (a.fachat@physik.tu-chemnitz.de)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
#ifndef __XA65_XA_CHARSET_H__
|
||||||
|
#define __XA65_XA_CHARSET_H__
|
||||||
|
|
||||||
|
/* set the target character set the chars - values in quotes - should
|
||||||
|
be converted to
|
||||||
|
returns 0 on success and -1 when the name is not found */
|
||||||
|
int set_charset(char *charset_name);
|
||||||
|
|
||||||
|
/* convert a char */
|
||||||
|
signed char convert_char(signed char c);
|
||||||
|
|
||||||
|
#endif /*__XA65_XA_H__ */
|
||||||
|
|
||||||
41
xa-2.3.5/src/xad.h
Normal file
41
xa-2.3.5/src/xad.h
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
/* xa65 - 65xx/65816 cross-assembler and utility suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 1989-1997 André Fachat (a.fachat@physik.tu-chemnitz.de)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
#ifndef __XA65_XAD_H__
|
||||||
|
#define __XA65_XAD_H__
|
||||||
|
|
||||||
|
#ifndef abs
|
||||||
|
#define abs(a) (a >= 0) ? a : -a
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define hashcode(n, l) (n[0] & 0x0f) | (((l - 1) ? (n[1] & 0x0f) : 0) << 4)
|
||||||
|
#define fputw(a, fp) do { \
|
||||||
|
fputc(a & 255, fp); \
|
||||||
|
fputc((a >> 8) & 255, fp); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define cval(s) 256 * ((s)[1] & 255) + ((s)[0]&255)
|
||||||
|
#define lval(s) 65536 * ((s)[2] & 255) + 256 * ((s)[1] & 255) + ((s)[0] & 255)
|
||||||
|
#define wval(i, v) do { \
|
||||||
|
t[i++] = T_VALUE; \
|
||||||
|
t[i++] = v & 255; \
|
||||||
|
t[i++] = (v >> 8) & 255; \
|
||||||
|
t[i++] = (v >> 16) & 255; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#endif /* __XA65_XAD_H__ */
|
||||||
227
xa-2.3.5/src/xah.h
Normal file
227
xa-2.3.5/src/xah.h
Normal file
|
|
@ -0,0 +1,227 @@
|
||||||
|
/* xa65 - 65xx/65816 cross-assembler and utility suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 1989-1997 André Fachat (a.fachat@physik.tu-chemnitz.de)
|
||||||
|
* Maintained by Cameron Kaiser
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
#ifndef __XA65_XAH_H__
|
||||||
|
#define __XA65_XAH_H__
|
||||||
|
|
||||||
|
#define ANZLAB 5000 /* mal 14 -> Byte */
|
||||||
|
#define LABMEM 40000L
|
||||||
|
#define MAXLAB 32
|
||||||
|
#define MAXBLK 16
|
||||||
|
#define MAXFILE 7
|
||||||
|
#define MAXLINE 2048
|
||||||
|
#define MAXPP 40000L
|
||||||
|
#define ANZDEF 2340 /* mal 14 -> Byte, ANZDEF * 14 < 32768 */
|
||||||
|
#define TMPMEM 200000L /* Zwischenspeicher von Pass1 nach Pass 2 */
|
||||||
|
|
||||||
|
typedef struct LabOcc {
|
||||||
|
struct LabOcc *next;
|
||||||
|
int line;
|
||||||
|
char *fname;
|
||||||
|
} LabOcc;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int blk;
|
||||||
|
int val;
|
||||||
|
int len;
|
||||||
|
int fl; /* 0 = label value not valid/known,
|
||||||
|
* 1 = label value known
|
||||||
|
*/
|
||||||
|
int afl; /* 0 = no address (no relocation), 1 = address label */
|
||||||
|
int nextindex;
|
||||||
|
char *n;
|
||||||
|
struct LabOcc *occlist;
|
||||||
|
} Labtab;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *search;
|
||||||
|
int s_len;
|
||||||
|
char *replace;
|
||||||
|
int p_anz;
|
||||||
|
int nextindex;
|
||||||
|
} List;
|
||||||
|
|
||||||
|
|
||||||
|
#define MEMLEN (4 + TMPMEM + MAXPP + LABMEM + \
|
||||||
|
(long)(sizeof (Labtab) * ANZLAB) + \
|
||||||
|
(long)(sizeof (List) * ANZDEF))
|
||||||
|
|
||||||
|
#define DIRCHAR '/'
|
||||||
|
#define DIRCSTRING "/"
|
||||||
|
/* for Atari:
|
||||||
|
#define DIRCHAR '\\'
|
||||||
|
#define DIRCSTRING "\\"
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define BUFSIZE 4096 /* File-Puffegroesse (wg Festplatte) */
|
||||||
|
|
||||||
|
#define E_OK 0 /* Fehlernummern */
|
||||||
|
#define E_SYNTAX -1 /* Syntax Fehler */
|
||||||
|
#define E_LABDEF -2 /* Label definiert */
|
||||||
|
#define E_NODEF -3 /* Label nicht definiert */
|
||||||
|
#define E_LABFULL -4 /* Labeltabelle voll */
|
||||||
|
#define E_LABEXP -5 /* Label erwartet */
|
||||||
|
#define E_NOMEM -6 /* kein Speicher mehr */
|
||||||
|
#define E_ILLCODE -7 /* Illegaler Opcode */
|
||||||
|
#define E_ADRESS -8 /* Illegale Adressierung */
|
||||||
|
#define E_RANGE -9 /* Branch out of range */
|
||||||
|
#define E_OVERFLOW -10 /* Ueberlauf */
|
||||||
|
#define E_DIV -11 /* Division durch Null */
|
||||||
|
#define E_PSOEXP -12 /* Pseudo-Opcode erwartet */
|
||||||
|
#define E_BLKOVR -13 /* Block-Stack Uebergelaufen */
|
||||||
|
#define E_FNF -14 /* File not found (pp) */
|
||||||
|
#define E_EOF -15 /* End of File */
|
||||||
|
#define E_BLOCK -16 /* Block inkonsistent */
|
||||||
|
#define E_NOBLK -17
|
||||||
|
#define E_NOKEY -18
|
||||||
|
#define E_NOLINE -19
|
||||||
|
#define E_OKDEF -20 /* okdef */
|
||||||
|
#define E_DSB -21
|
||||||
|
#define E_NEWLINE -22
|
||||||
|
#define E_NEWFILE -23
|
||||||
|
#define E_CMOS -24
|
||||||
|
#define E_ANZPAR -25
|
||||||
|
#define E_ILLPOINTER -26 /* illegal pointer arithmetic! */
|
||||||
|
#define E_ILLSEGMENT -27 /* illegal pointer arithmetic! */
|
||||||
|
#define E_OPTLEN -28 /* file header option too long */
|
||||||
|
#define E_ROMOPT -29 /* header option not directly after
|
||||||
|
* file start in romable mode
|
||||||
|
*/
|
||||||
|
#define E_ILLALIGN -30 /* illegal align value */
|
||||||
|
|
||||||
|
#define E_65816 -31
|
||||||
|
|
||||||
|
#define E_ORECMAC -32 /* exceeded recursion limit for label eval */
|
||||||
|
#define E_OPENPP -33 /* open preprocessor directive */
|
||||||
|
#define E_OUTOFDATA -34 /* out of data */
|
||||||
|
#define E_ILLQUANT -35 /* generic illegal quantity error */
|
||||||
|
#define E_BIN -36 /* okdef */
|
||||||
|
/* errors thru 63 are placeholders */
|
||||||
|
|
||||||
|
#define W_ADRRELOC -64 /* word relocation in byte value */
|
||||||
|
#define W_BYTRELOC -65 /* byte relocation in word value */
|
||||||
|
#define E_WPOINTER -66 /* illegal pointer arithmetic! */
|
||||||
|
#define W_ADDRACC -67 /* addr access to low or high byte pointer */
|
||||||
|
#define W_HIGHACC -68 /* high byte access to low byte pointer */
|
||||||
|
#define W_LOWACC -69 /* low byte access to high byte pointer */
|
||||||
|
#define W_FORLAB -70 /* no zp-optimization for a forward label */
|
||||||
|
#define W_OPENPP -71 /* warning about open preprocessor directive */
|
||||||
|
#define W_OVER64K -72 /* included binary over 64K in 6502 mode */
|
||||||
|
#define W_OVER16M -73 /* included binary over 16M in 65816 mode */
|
||||||
|
/* warnings 74-76 are placeholders */
|
||||||
|
|
||||||
|
#define T_VALUE -1
|
||||||
|
#define T_LABEL -2
|
||||||
|
#define T_OP -3
|
||||||
|
#define T_END -4
|
||||||
|
#define T_LINE -5
|
||||||
|
#define T_FILE -6
|
||||||
|
#define T_POINTER -7
|
||||||
|
|
||||||
|
#define P_START 0 /* Prioritaeten fuer Arithmetik */
|
||||||
|
#define P_LOR 1 /* Von zwei Operationen wird immer */
|
||||||
|
#define P_LAND 2 /* die mit der hoeheren Prioritaet */
|
||||||
|
#define P_OR 3 /* zuerst ausgefuehrt */
|
||||||
|
#define P_XOR 4
|
||||||
|
#define P_AND 5
|
||||||
|
#define P_EQU 6
|
||||||
|
#define P_CMP 7
|
||||||
|
#define P_SHIFT 8
|
||||||
|
#define P_ADD 9
|
||||||
|
#define P_MULT 10
|
||||||
|
#define P_INV 11
|
||||||
|
|
||||||
|
#define A_ADR 0x8000 /* all are or'd with (afl = segment type)<<8 */
|
||||||
|
#define A_HIGH 0x4000 /* or'd with the low byte */
|
||||||
|
#define A_LOW 0x2000
|
||||||
|
#define A_MASK 0xe000 /* reloc type mask */
|
||||||
|
#define A_FMASK 0x0f00 /* segment type mask */
|
||||||
|
|
||||||
|
#define A_LONG 0xc000
|
||||||
|
|
||||||
|
#define FM_OBJ 0x1000
|
||||||
|
#define FM_SIZE 0x2000
|
||||||
|
#define FM_RELOC 0x4000
|
||||||
|
#define FM_CPU 0x8000
|
||||||
|
|
||||||
|
#define SEG_ABS 0
|
||||||
|
#define SEG_UNDEF 1
|
||||||
|
#define SEG_TEXT 2
|
||||||
|
#define SEG_DATA 3
|
||||||
|
#define SEG_BSS 4
|
||||||
|
#define SEG_ZERO 5
|
||||||
|
#define SEG_MAX 6
|
||||||
|
|
||||||
|
typedef struct Fopt {
|
||||||
|
signed char *text; /* text after pass1 */
|
||||||
|
int len;
|
||||||
|
} Fopt;
|
||||||
|
|
||||||
|
typedef struct relocateInfo {
|
||||||
|
int next;
|
||||||
|
int adr;
|
||||||
|
int afl;
|
||||||
|
int lab;
|
||||||
|
} relocateInfo;
|
||||||
|
|
||||||
|
typedef struct File {
|
||||||
|
int fmode;
|
||||||
|
int slen;
|
||||||
|
int relmode;
|
||||||
|
int old_abspc;
|
||||||
|
int base[SEG_MAX];
|
||||||
|
int len[SEG_MAX];
|
||||||
|
struct {
|
||||||
|
signed char *tmp;
|
||||||
|
unsigned long tmpz;
|
||||||
|
unsigned long tmpe;
|
||||||
|
} mn;
|
||||||
|
struct {
|
||||||
|
int *ulist;
|
||||||
|
int un;
|
||||||
|
int um;
|
||||||
|
} ud;
|
||||||
|
struct {
|
||||||
|
relocateInfo *rlist;
|
||||||
|
int mlist;
|
||||||
|
int nlist;
|
||||||
|
int first;
|
||||||
|
} rt;
|
||||||
|
struct {
|
||||||
|
relocateInfo *rlist;
|
||||||
|
int mlist;
|
||||||
|
int nlist;
|
||||||
|
int first;
|
||||||
|
} rd;
|
||||||
|
struct {
|
||||||
|
Fopt *olist;
|
||||||
|
int mlist;
|
||||||
|
int nlist;
|
||||||
|
} fo;
|
||||||
|
struct {
|
||||||
|
int hashindex[256];
|
||||||
|
Labtab *lt;
|
||||||
|
int lti;
|
||||||
|
int ltm;
|
||||||
|
} la;
|
||||||
|
} File;
|
||||||
|
|
||||||
|
extern File *afile;
|
||||||
|
|
||||||
|
#endif /* __XA65_XAH_H__ */
|
||||||
30
xa-2.3.5/src/xah2.h
Normal file
30
xa-2.3.5/src/xah2.h
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
/* xa65 - 65xx/65816 cross-assembler and utility suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 1989-1997 André Fachat (a.fachat@physik.tu-chemnitz.de)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
#ifndef __XA65_XAH2_H__
|
||||||
|
#define __XA65_XAH2_H__
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *fname; /* fname[MAXLINE]; */
|
||||||
|
int fline;
|
||||||
|
int bdepth;
|
||||||
|
FILE *filep;
|
||||||
|
char *flinep;
|
||||||
|
} Datei;
|
||||||
|
|
||||||
|
#endif /* __XA65_XAH2_H__ */
|
||||||
595
xa-2.3.5/src/xal.c
Normal file
595
xa-2.3.5/src/xal.c
Normal file
|
|
@ -0,0 +1,595 @@
|
||||||
|
/* xa65 - 65xx/65816 cross-assembler and utility suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 1989-1997 André Fachat (a.fachat@physik.tu-chemnitz.de)
|
||||||
|
*
|
||||||
|
* Label management module (also see xau.c)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
/* structs and defs */
|
||||||
|
|
||||||
|
#include "xad.h"
|
||||||
|
#include "xah.h"
|
||||||
|
#include "xar.h"
|
||||||
|
#include "xah2.h"
|
||||||
|
#include "xap.h"
|
||||||
|
#include "xa.h"
|
||||||
|
|
||||||
|
/* externals */
|
||||||
|
|
||||||
|
#include "xam.h"
|
||||||
|
#include "xal.h"
|
||||||
|
|
||||||
|
/* exported globals */
|
||||||
|
|
||||||
|
char *lz;
|
||||||
|
|
||||||
|
/* local prototypes */
|
||||||
|
|
||||||
|
static int b_fget(int*,int);
|
||||||
|
static int b_ltest(int,int);
|
||||||
|
static int b_get(int*);
|
||||||
|
static int b_test(int);
|
||||||
|
static int ll_def(char *s, int *n, int b);
|
||||||
|
|
||||||
|
/* local variables */
|
||||||
|
|
||||||
|
/*
|
||||||
|
static int hashindex[256];
|
||||||
|
static Labtab *lt = NULL;
|
||||||
|
static int lti = 0;
|
||||||
|
static int ltm = 0;
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
static char *ln;
|
||||||
|
static unsigned long lni;
|
||||||
|
static long sl;
|
||||||
|
*/
|
||||||
|
|
||||||
|
static Labtab *ltp;
|
||||||
|
|
||||||
|
int l_init(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
#if 0
|
||||||
|
int er;
|
||||||
|
|
||||||
|
for(er=0;er<256;er++)
|
||||||
|
hashindex[er]=0;
|
||||||
|
|
||||||
|
/*sl=(long)sizeof(Labtab);*/
|
||||||
|
|
||||||
|
/* if(!(er=m_alloc((long)(sizeof(Labtab)*ANZLAB),(char**)<)))
|
||||||
|
er=m_alloc((long)LABMEM,&ln);*/
|
||||||
|
|
||||||
|
er=m_alloc((long)(sizeof(Labtab)*ANZLAB),(char**)<);
|
||||||
|
|
||||||
|
lti=0;
|
||||||
|
/* lni=0L;*/
|
||||||
|
|
||||||
|
return(er);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int ga_lab(void)
|
||||||
|
{
|
||||||
|
return(afile->la.lti);
|
||||||
|
}
|
||||||
|
|
||||||
|
int gm_lab(void)
|
||||||
|
{
|
||||||
|
return(ANZLAB);
|
||||||
|
}
|
||||||
|
|
||||||
|
long gm_labm(void)
|
||||||
|
{
|
||||||
|
return((long)LABMEM);
|
||||||
|
}
|
||||||
|
|
||||||
|
long ga_labm(void)
|
||||||
|
{
|
||||||
|
return(0 /*lni*/);
|
||||||
|
}
|
||||||
|
|
||||||
|
void printllist(fp)
|
||||||
|
FILE *fp;
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
LabOcc *p;
|
||||||
|
char *fname = NULL;
|
||||||
|
|
||||||
|
for(i=0;i<afile->la.lti;i++)
|
||||||
|
{
|
||||||
|
ltp=afile->la.lt+i;
|
||||||
|
fprintf(fp,"%s, 0x%04x, %d, 0x%04x\n",ltp->n,ltp->val,ltp->blk,
|
||||||
|
ltp->afl);
|
||||||
|
p = ltp->occlist;
|
||||||
|
if(p) {
|
||||||
|
while(p) {
|
||||||
|
if(fname != p->fname) {
|
||||||
|
if(p!=ltp->occlist) fprintf(fp,"\n");
|
||||||
|
fprintf(fp," %s",p->fname);
|
||||||
|
fname=p->fname;
|
||||||
|
}
|
||||||
|
fprintf(fp," %d", p->line);
|
||||||
|
p=p->next;
|
||||||
|
}
|
||||||
|
fprintf(fp,"\n");
|
||||||
|
}
|
||||||
|
fname=NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int lg_set(char *s ) {
|
||||||
|
int n, er;
|
||||||
|
|
||||||
|
er = ll_search(s,&n);
|
||||||
|
|
||||||
|
if(er==E_OK) {
|
||||||
|
fprintf(stderr,"Warning: global label doubly defined!\n");
|
||||||
|
} else {
|
||||||
|
if(!(er=ll_def(s,&n,0))) {
|
||||||
|
ltp=afile->la.lt+n;
|
||||||
|
ltp->fl=2;
|
||||||
|
ltp->afl=SEG_UNDEF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return er;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int l_def(char *s, int *l, int *x, int *f)
|
||||||
|
{
|
||||||
|
int n,er,b,i=0;
|
||||||
|
|
||||||
|
*f=0;
|
||||||
|
b=0;
|
||||||
|
n=0;
|
||||||
|
|
||||||
|
if(s[0]=='-')
|
||||||
|
{
|
||||||
|
*f+=1;
|
||||||
|
i++;
|
||||||
|
} else
|
||||||
|
if(s[0]=='+')
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
n++;
|
||||||
|
b=0;
|
||||||
|
}
|
||||||
|
while(s[i]=='&')
|
||||||
|
{
|
||||||
|
n=0;
|
||||||
|
i++;
|
||||||
|
b++;
|
||||||
|
}
|
||||||
|
if(!n)
|
||||||
|
b_fget(&b,b);
|
||||||
|
|
||||||
|
|
||||||
|
if(!isalpha(s[i]) && s[i]!='_')
|
||||||
|
er=E_SYNTAX;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
er=ll_search(s+i,&n);
|
||||||
|
|
||||||
|
if(er==E_OK)
|
||||||
|
{
|
||||||
|
ltp=afile->la.lt+n;
|
||||||
|
|
||||||
|
if(*f)
|
||||||
|
{
|
||||||
|
*l=ltp->len+i;
|
||||||
|
} else
|
||||||
|
if(ltp->fl==0)
|
||||||
|
{
|
||||||
|
*l=ltp->len+i;
|
||||||
|
if(b_ltest(ltp->blk,b))
|
||||||
|
er=E_LABDEF;
|
||||||
|
else
|
||||||
|
ltp->blk=b;
|
||||||
|
|
||||||
|
} else
|
||||||
|
er=E_LABDEF;
|
||||||
|
} else
|
||||||
|
if(er==E_NODEF)
|
||||||
|
{
|
||||||
|
if(!(er=ll_def(s+i,&n,b))) /* ll_def(...,*f) */
|
||||||
|
{
|
||||||
|
ltp=afile->la.lt+n;
|
||||||
|
*l=ltp->len+i;
|
||||||
|
ltp->fl=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*x=n;
|
||||||
|
}
|
||||||
|
return(er);
|
||||||
|
}
|
||||||
|
|
||||||
|
int l_search(char *s, int *l, int *x, int *v, int *afl)
|
||||||
|
{
|
||||||
|
int n,er,b;
|
||||||
|
|
||||||
|
*afl=0;
|
||||||
|
|
||||||
|
er=ll_search(s,&n);
|
||||||
|
/*printf("l_search: lab=%s(l=%d), afl=%d, er=%d, n=%d\n",s,*l, *afl,er,n);*/
|
||||||
|
if(er==E_OK)
|
||||||
|
{
|
||||||
|
ltp=afile->la.lt+n;
|
||||||
|
*l=ltp->len;
|
||||||
|
if(ltp->fl == 1)
|
||||||
|
{
|
||||||
|
l_get(n,v,afl);/* *v=lt[n].val;*/
|
||||||
|
*x=n;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
er=E_NODEF;
|
||||||
|
lz=ltp->n;
|
||||||
|
*x=n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
b_get(&b);
|
||||||
|
er=ll_def(s,x,b); /* ll_def(...,*v); */
|
||||||
|
|
||||||
|
ltp=afile->la.lt+(*x);
|
||||||
|
|
||||||
|
*l=ltp->len;
|
||||||
|
|
||||||
|
if(!er)
|
||||||
|
{
|
||||||
|
er=E_NODEF;
|
||||||
|
lz=ltp->n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(er);
|
||||||
|
}
|
||||||
|
|
||||||
|
int l_vget(int n, int *v, char **s)
|
||||||
|
{
|
||||||
|
ltp=afile->la.lt+n;
|
||||||
|
(*v)=ltp->val;
|
||||||
|
*s=ltp->n;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void l_addocc(int n, int *v, int *afl) {
|
||||||
|
LabOcc *p, *pp;
|
||||||
|
|
||||||
|
(void)v; /* quench warning */
|
||||||
|
(void)afl; /* quench warning */
|
||||||
|
ltp = afile->la.lt+n;
|
||||||
|
pp=NULL;
|
||||||
|
p = ltp->occlist;
|
||||||
|
while(p) {
|
||||||
|
if (p->line == filep->fline && p->fname == filep->fname) return;
|
||||||
|
pp = p;
|
||||||
|
p = p->next;
|
||||||
|
}
|
||||||
|
p = malloc(sizeof(LabOcc));
|
||||||
|
if(!p) {
|
||||||
|
fprintf(stderr,"Oops, out of memory!\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
p->next = NULL;
|
||||||
|
p->line = filep->fline;
|
||||||
|
p->fname = filep->fname;
|
||||||
|
if(pp) {
|
||||||
|
pp->next = p;
|
||||||
|
} else {
|
||||||
|
ltp->occlist = p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int l_get(int n, int *v, int *afl)
|
||||||
|
{
|
||||||
|
if(crossref) l_addocc(n,v,afl);
|
||||||
|
|
||||||
|
ltp=afile->la.lt+n;
|
||||||
|
(*v)=ltp->val;
|
||||||
|
lz=ltp->n;
|
||||||
|
*afl = ltp->afl;
|
||||||
|
/*printf("l_get('%s'(%d), v=$%04x, afl=%d, fl=%d\n",ltp->n, n, *v, *afl, ltp->fl);*/
|
||||||
|
return( (ltp->fl==1) ? E_OK : E_NODEF);
|
||||||
|
}
|
||||||
|
|
||||||
|
void l_set(int n, int v, int afl)
|
||||||
|
{
|
||||||
|
ltp=afile->la.lt+n;
|
||||||
|
ltp->val = v;
|
||||||
|
ltp->fl = 1;
|
||||||
|
ltp->afl = afl;
|
||||||
|
/*printf("l_set('%s'(%d), v=$%04x, afl=%d\n",ltp->n, n, v, afl);*/
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ll_exblk(int a, int b)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i=0;i<afile->la.lti;i++)
|
||||||
|
{
|
||||||
|
ltp=afile->la.lt+i;
|
||||||
|
if((!ltp->fl) && (ltp->blk==a))
|
||||||
|
ltp->blk=b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ll_def(char *s, int *n, int b) /* definiert naechstes Label nr->n */
|
||||||
|
{
|
||||||
|
int j=0,er=E_NOMEM,hash;
|
||||||
|
char *s2;
|
||||||
|
|
||||||
|
/*printf("ll_def: s=%s\n",s); */
|
||||||
|
|
||||||
|
if(!afile->la.lt) {
|
||||||
|
afile->la.lti = 0;
|
||||||
|
afile->la.ltm = 1000;
|
||||||
|
afile->la.lt = malloc(afile->la.ltm * sizeof(Labtab));
|
||||||
|
}
|
||||||
|
if(afile->la.lti>=afile->la.ltm) {
|
||||||
|
afile->la.ltm *= 1.5;
|
||||||
|
afile->la.lt = realloc(afile->la.lt, afile->la.ltm * sizeof(Labtab));
|
||||||
|
}
|
||||||
|
if(!afile->la.lt) {
|
||||||
|
fprintf(stderr, "Oops: no memory!\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
if((lti<ANZLAB) /*&&(lni<(long)(LABMEM-MAXLAB))*/)
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
ltp=afile->la.lt+afile->la.lti;
|
||||||
|
/*
|
||||||
|
s2=ltp->n=ln+lni;
|
||||||
|
|
||||||
|
while((j<MAXLAB-1) && (s[j]!='\0') && (isalnum(s[j]) || s[j]=='_'))
|
||||||
|
{
|
||||||
|
s2[j]=s[j];
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
while((s[j]!='\0') && (isalnum(s[j]) || (s[j]=='_'))) j++;
|
||||||
|
s2 = malloc(j+1);
|
||||||
|
if(!s2) {
|
||||||
|
fprintf(stderr,"Oops: no memory!\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
strncpy(s2,s,j);
|
||||||
|
s2[j]=0;
|
||||||
|
/*
|
||||||
|
if(j<MAXLAB)
|
||||||
|
{
|
||||||
|
*/
|
||||||
|
er=E_OK;
|
||||||
|
ltp->len=j;
|
||||||
|
ltp->n = s2;
|
||||||
|
ltp->blk=b;
|
||||||
|
ltp->fl=0;
|
||||||
|
ltp->afl=0;
|
||||||
|
ltp->occlist=NULL;
|
||||||
|
hash=hashcode(s,j);
|
||||||
|
ltp->nextindex=afile->la.hashindex[hash];
|
||||||
|
afile->la.hashindex[hash]=afile->la.lti;
|
||||||
|
*n=afile->la.lti;
|
||||||
|
afile->la.lti++;
|
||||||
|
/* lni+=j+1;*/
|
||||||
|
/* }
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
/*printf("ll_def return: %d\n",er);*/
|
||||||
|
return(er);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int ll_search(char *s, int *n) /* search Label in Tabelle ,nr->n */
|
||||||
|
{
|
||||||
|
int i,j=0,k,er=E_NODEF,hash;
|
||||||
|
|
||||||
|
while(s[j] && (isalnum(s[j])||(s[j]=='_'))) j++;
|
||||||
|
|
||||||
|
hash=hashcode(s,j);
|
||||||
|
i=afile->la.hashindex[hash];
|
||||||
|
|
||||||
|
/*printf("search?\n");*/
|
||||||
|
if(i>=afile->la.ltm) return E_NODEF;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
ltp=afile->la.lt+i;
|
||||||
|
|
||||||
|
if(j==ltp->len)
|
||||||
|
{
|
||||||
|
for (k=0;(k<j)&&(ltp->n[k]==s[k]);k++);
|
||||||
|
|
||||||
|
if((j==k)&&(!b_test(ltp->blk)))
|
||||||
|
{
|
||||||
|
er=E_OK;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!i)
|
||||||
|
break;
|
||||||
|
|
||||||
|
i=ltp->nextindex;
|
||||||
|
|
||||||
|
}while(1);
|
||||||
|
|
||||||
|
*n=i;
|
||||||
|
#if 0
|
||||||
|
if(er!=E_OK && er!=E_NODEF)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Fehler in ll_search:er=%d\n",er);
|
||||||
|
getchar();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return(er);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ll_pdef(char *t)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
if(ll_search(t,&n)==E_OK)
|
||||||
|
{
|
||||||
|
ltp=afile->la.lt+n;
|
||||||
|
if(ltp->fl)
|
||||||
|
return(E_OK);
|
||||||
|
}
|
||||||
|
return(E_NODEF);
|
||||||
|
}
|
||||||
|
|
||||||
|
int l_write(FILE *fp)
|
||||||
|
{
|
||||||
|
int i, afl, n=0;
|
||||||
|
|
||||||
|
if(noglob) {
|
||||||
|
fputc(0, fp);
|
||||||
|
fputc(0, fp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
for (i=0;i<afile->la.lti;i++) {
|
||||||
|
ltp=afile->la.lt+i;
|
||||||
|
if((!ltp->blk) && (ltp->fl==1)) {
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fputc(n&255, fp);
|
||||||
|
fputc((n>>8)&255, fp);
|
||||||
|
for (i=0;i<afile->la.lti;i++)
|
||||||
|
{
|
||||||
|
ltp=afile->la.lt+i;
|
||||||
|
if((!ltp->blk) && (ltp->fl==1)) {
|
||||||
|
fprintf(fp, "%s",ltp->n);
|
||||||
|
fputc(0,fp);
|
||||||
|
afl = ltp->afl;
|
||||||
|
/* hack to switch undef and abs flag from internal to file format */
|
||||||
|
/*printf("label %s, afl=%04x, A_FMASK>>8=%04x\n", ltp->n, afl, A_FMASK>>8);*/
|
||||||
|
if( (afl & (A_FMASK>>8)) < SEG_TEXT) afl^=1;
|
||||||
|
fputc(afl,fp);
|
||||||
|
fputc(ltp->val&255, fp);
|
||||||
|
fputc((ltp->val>>8)&255, fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*fputc(0,fp);*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bt[MAXBLK];
|
||||||
|
static int blk;
|
||||||
|
static int bi;
|
||||||
|
|
||||||
|
int b_init(void)
|
||||||
|
{
|
||||||
|
blk =0;
|
||||||
|
bi =0;
|
||||||
|
bt[bi]=blk;
|
||||||
|
|
||||||
|
return(E_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
int b_depth(void)
|
||||||
|
{
|
||||||
|
return bi;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ga_blk(void)
|
||||||
|
{
|
||||||
|
return(blk);
|
||||||
|
}
|
||||||
|
|
||||||
|
int b_open(void)
|
||||||
|
{
|
||||||
|
int er=E_BLKOVR;
|
||||||
|
|
||||||
|
if(bi<MAXBLK-1)
|
||||||
|
{
|
||||||
|
bt[++bi]=++blk;
|
||||||
|
|
||||||
|
er=E_OK;
|
||||||
|
}
|
||||||
|
return(er);
|
||||||
|
}
|
||||||
|
|
||||||
|
int b_close(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(bi)
|
||||||
|
{
|
||||||
|
ll_exblk(bt[bi],bt[bi-1]);
|
||||||
|
bi--;
|
||||||
|
} else {
|
||||||
|
return E_BLOCK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return(E_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int b_get(int *n)
|
||||||
|
{
|
||||||
|
*n=bt[bi];
|
||||||
|
|
||||||
|
return(E_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int b_fget(int *n, int i)
|
||||||
|
{
|
||||||
|
if((bi-i)>=0)
|
||||||
|
*n=bt[bi-i];
|
||||||
|
else
|
||||||
|
*n=0;
|
||||||
|
return(E_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int b_test(int n)
|
||||||
|
{
|
||||||
|
int i=bi;
|
||||||
|
|
||||||
|
while( i>=0 && n!=bt[i] )
|
||||||
|
i--;
|
||||||
|
|
||||||
|
return( i+1 ? E_OK : E_NOBLK );
|
||||||
|
}
|
||||||
|
|
||||||
|
static int b_ltest(int a, int b) /* testet ob bt^-1(b) in intervall [0,bt^-1(a)] */
|
||||||
|
{
|
||||||
|
int i=0,er=E_OK;
|
||||||
|
|
||||||
|
if(a!=b)
|
||||||
|
{
|
||||||
|
er=E_OK;
|
||||||
|
|
||||||
|
while(i<=bi && b!=bt[i])
|
||||||
|
{
|
||||||
|
if(bt[i]==a)
|
||||||
|
{
|
||||||
|
er=E_NOBLK;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(er);
|
||||||
|
}
|
||||||
|
|
||||||
53
xa-2.3.5/src/xal.h
Normal file
53
xa-2.3.5/src/xal.h
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
/* xa65 - 65xx/65816 cross-assembler and utility suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 1989-1997 André Fachat (a.fachat@physik.tu-chemnitz.de)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
#ifndef __XA65_XAL_H__
|
||||||
|
#define __XA65_XAL_H__
|
||||||
|
|
||||||
|
#include <stdio.h> /* for FILE */
|
||||||
|
|
||||||
|
extern char *lz;
|
||||||
|
|
||||||
|
int l_init(void);
|
||||||
|
int ga_lab(void);
|
||||||
|
int gm_lab(void);
|
||||||
|
long gm_labm(void);
|
||||||
|
long ga_labm(void);
|
||||||
|
|
||||||
|
int lg_set(char *);
|
||||||
|
|
||||||
|
int b_init(void);
|
||||||
|
int b_depth(void);
|
||||||
|
|
||||||
|
void printllist(FILE *fp);
|
||||||
|
int ga_blk(void);
|
||||||
|
|
||||||
|
int l_def(char *s, int* l, int *x, int *f);
|
||||||
|
int l_search(char *s, int *l, int *x, int *v, int *afl);
|
||||||
|
void l_set(int n, int v, int afl);
|
||||||
|
int l_get(int n, int *v, int *afl);
|
||||||
|
int l_vget(int n, int *v, char **s);
|
||||||
|
int ll_search(char *s, int *n);
|
||||||
|
int ll_pdef(char *t);
|
||||||
|
|
||||||
|
int b_open(void);
|
||||||
|
int b_close(void);
|
||||||
|
|
||||||
|
int l_write(FILE *fp);
|
||||||
|
|
||||||
|
#endif /* __XA65_XAL_H__ */
|
||||||
188
xa-2.3.5/src/xam.c
Normal file
188
xa-2.3.5/src/xam.c
Normal file
|
|
@ -0,0 +1,188 @@
|
||||||
|
/* xa65 - 65xx/65816 cross-assembler and utility suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 1989-1997 André Fachat (a.fachat@physik.tu-chemnitz.de)
|
||||||
|
*
|
||||||
|
* Memory manager/malloc() stub module
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "xah.h" /* structs */
|
||||||
|
|
||||||
|
static int ninc = 0;
|
||||||
|
static char **nip = NULL;
|
||||||
|
|
||||||
|
void reg_include(char *path) {
|
||||||
|
char **nip2;
|
||||||
|
if(path && *path) {
|
||||||
|
nip2 = realloc(nip,sizeof(char*)*(ninc+1));
|
||||||
|
if(nip2) {
|
||||||
|
nip = nip2;
|
||||||
|
nip[ninc++] = path;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr,"Warning: couldn' alloc mem (reg_include)\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *xfopen(const char *fn,const char *mode)
|
||||||
|
{
|
||||||
|
FILE *file;
|
||||||
|
char c,*cp,n[MAXLINE],path[MAXLINE];
|
||||||
|
char xname[MAXLINE], n2[MAXLINE];
|
||||||
|
int i,l=(int)strlen(fn);
|
||||||
|
|
||||||
|
if(l>=MAXLINE) {
|
||||||
|
fprintf(stderr,"filename '%s' too long!\n",fn);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0;i<l+1;i++) {
|
||||||
|
xname[i]=((fn[i]=='\\')?DIRCHAR:fn[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mode[0]=='r')
|
||||||
|
{
|
||||||
|
if((file=fopen(fn,mode))==NULL
|
||||||
|
&& (file=fopen(xname, mode))==NULL) {
|
||||||
|
for(i=0;(!file) && (i<ninc);i++) {
|
||||||
|
strcpy(n,nip[i]);
|
||||||
|
c=n[(int)strlen(n)-1];
|
||||||
|
if(c!=DIRCHAR) strcat(n,DIRCSTRING);
|
||||||
|
strcpy(n2,n);
|
||||||
|
strcat(n2,xname);
|
||||||
|
strcat(n,fn);
|
||||||
|
/* printf("name=%s,n2=%s,mode=%s\n",n,n2,mode); */
|
||||||
|
file=fopen(n,mode);
|
||||||
|
if(!file) file=fopen(n2,mode);
|
||||||
|
}
|
||||||
|
if((!file) && (cp=getenv("XAINPUT"))!=NULL)
|
||||||
|
{
|
||||||
|
strcpy(path,cp);
|
||||||
|
cp=strtok(path,",");
|
||||||
|
while(cp && !file)
|
||||||
|
{
|
||||||
|
if(cp[0])
|
||||||
|
{
|
||||||
|
strcpy(n,cp);
|
||||||
|
c=n[(int)strlen(n)-1];
|
||||||
|
if(c!=DIRCHAR&&c!=':')
|
||||||
|
strcat(n,DIRCSTRING);
|
||||||
|
strcpy(n2,n);
|
||||||
|
strcat(n2,xname);
|
||||||
|
strcat(n,fn);
|
||||||
|
/* printf("name=%s,n2=%s,mode=%s\n",n,n2,mode); */
|
||||||
|
file=fopen(n,mode);
|
||||||
|
if(!file) file=fopen(n2,mode);
|
||||||
|
}
|
||||||
|
cp=strtok(NULL,",");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
if((cp=getenv("XAOUTPUT"))!=NULL)
|
||||||
|
{
|
||||||
|
strcpy(n,cp);
|
||||||
|
if(n[0])
|
||||||
|
{
|
||||||
|
c=n[(int)strlen(n)-1];
|
||||||
|
if(c!=DIRCHAR&&c!=':')
|
||||||
|
strcat(n,DIRCSTRING);
|
||||||
|
}
|
||||||
|
cp=strrchr(fn,DIRCHAR);
|
||||||
|
if(!cp)
|
||||||
|
{
|
||||||
|
cp=strrchr(fn,':');
|
||||||
|
if(!cp)
|
||||||
|
cp=(char*)fn;
|
||||||
|
else
|
||||||
|
cp++;
|
||||||
|
} else
|
||||||
|
cp++;
|
||||||
|
strcat(n,cp);
|
||||||
|
file=fopen(n,mode);
|
||||||
|
} else
|
||||||
|
file=fopen(fn,mode);
|
||||||
|
}
|
||||||
|
if(file)
|
||||||
|
setvbuf(file,NULL,_IOFBF,BUFSIZE);
|
||||||
|
|
||||||
|
return(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
static char *m_base;
|
||||||
|
static char *m_act;
|
||||||
|
static char *m_end;
|
||||||
|
|
||||||
|
int m_init(void)
|
||||||
|
{
|
||||||
|
int er=E_NOMEM;
|
||||||
|
|
||||||
|
m_base=m_end=m_act=0L;
|
||||||
|
/*
|
||||||
|
fprintf(stderr, "MEMLEN=%ld\n",MEMLEN);
|
||||||
|
getchar();
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
if ((m_base=(char*)malloc(MEMLEN))!=NULL)
|
||||||
|
{
|
||||||
|
m_end =m_base+MEMLEN;
|
||||||
|
m_act =(char*)(((long)m_base+3)&0xfffffffcl);
|
||||||
|
er=E_OK;
|
||||||
|
}
|
||||||
|
else m_base=NULL;
|
||||||
|
*/
|
||||||
|
er=E_OK;
|
||||||
|
|
||||||
|
return(er);
|
||||||
|
}
|
||||||
|
|
||||||
|
void m_exit(void)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
free(m_base);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
int m_alloc(long n, char **adr)
|
||||||
|
{
|
||||||
|
int er=E_NOMEM;
|
||||||
|
|
||||||
|
if((*adr=calloc(n,1))) {
|
||||||
|
er=E_OK;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
if(m_act+n<m_end)
|
||||||
|
{
|
||||||
|
*adr=m_act;
|
||||||
|
m_act=m_act+n;
|
||||||
|
er=E_OK;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
fprintf(stderr, "m_alloc n=%ld adr=%lx\n",n,*adr);
|
||||||
|
getchar();
|
||||||
|
*/
|
||||||
|
return(er);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
25
xa-2.3.5/src/xam.h
Normal file
25
xa-2.3.5/src/xam.h
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
/* xa65 - 65xx/65816 cross-assembler and utility suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 1989-1997 André Fachat (a.fachat@physik.tu-chemnitz.de)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
#ifndef __XA65_XAM_H__
|
||||||
|
#define __XA65_XAM_H__
|
||||||
|
|
||||||
|
FILE *xfopen(const char *fn, const char *mode);
|
||||||
|
void reg_include(char *);
|
||||||
|
|
||||||
|
#endif /* __XA65_XAM_H__ */
|
||||||
102
xa-2.3.5/src/xao.c
Normal file
102
xa-2.3.5/src/xao.c
Normal file
|
|
@ -0,0 +1,102 @@
|
||||||
|
/* xa65 - 65xx/65816 cross-assembler and utility suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 1989-1997 André Fachat (a.fachat@physik.tu-chemnitz.de)
|
||||||
|
*
|
||||||
|
* Options module (handles pass options and writing them out to disk)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "xah.h"
|
||||||
|
#include "xar.h"
|
||||||
|
#include "xa.h"
|
||||||
|
#include "xat.h"
|
||||||
|
#include "xao.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
static Fopt *olist =NULL;
|
||||||
|
static int mlist =0;
|
||||||
|
static int nlist =0;
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* sets file option after pass 1 */
|
||||||
|
void set_fopt(int l, signed char *buf, int reallen) {
|
||||||
|
/*printf("set_fopt(%s, l=%d\n",buf,l);*/
|
||||||
|
while(afile->fo.mlist<=afile->fo.nlist) {
|
||||||
|
afile->fo.mlist +=5;
|
||||||
|
afile->fo.olist = realloc(afile->fo.olist, afile->fo.mlist*sizeof(Fopt));
|
||||||
|
if(!afile->fo.olist) {
|
||||||
|
fprintf(stderr, "Fatal: Couldn't alloc memory (%lu bytes) for fopt list!\n",
|
||||||
|
(unsigned long)(
|
||||||
|
afile->fo.mlist*sizeof(Fopt)));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
afile->fo.olist[afile->fo.nlist].text=malloc(l);
|
||||||
|
if(!afile->fo.olist[afile->fo.nlist].text) {
|
||||||
|
fprintf(stderr, "Fatal: Couldn't alloc memory (%d bytes) for fopt!\n",l);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
memcpy(afile->fo.olist[afile->fo.nlist].text, buf, l);
|
||||||
|
afile->fo.olist[afile->fo.nlist++].len = reallen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* writes file options to a file */
|
||||||
|
void o_write(FILE *fp) {
|
||||||
|
int i,j,l,afl;
|
||||||
|
signed char *t;
|
||||||
|
|
||||||
|
for(i=0;i<afile->fo.nlist;i++) {
|
||||||
|
l=afile->fo.olist[i].len;
|
||||||
|
t=afile->fo.olist[i].text;
|
||||||
|
/* do not optimize */
|
||||||
|
t_p2(t, &l, 1, &afl);
|
||||||
|
|
||||||
|
if(l>254) {
|
||||||
|
errout(E_OPTLEN);
|
||||||
|
} else {
|
||||||
|
fputc((l+1)&0xff,fp);
|
||||||
|
}
|
||||||
|
for(j=0;j<l;j++) {
|
||||||
|
fputc(t[j],fp);
|
||||||
|
/*printf("%02x ", t[j]); */
|
||||||
|
}
|
||||||
|
/*printf("\n");*/
|
||||||
|
}
|
||||||
|
fputc(0,fp); /* end option list */
|
||||||
|
|
||||||
|
for(i=0;i<afile->fo.nlist;i++) {
|
||||||
|
free(afile->fo.olist[i].text);
|
||||||
|
}
|
||||||
|
free(afile->fo.olist);
|
||||||
|
afile->fo.olist = NULL;
|
||||||
|
afile->fo.nlist = 0;
|
||||||
|
afile->fo.mlist = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t o_length(void) {
|
||||||
|
int i;
|
||||||
|
size_t n = 0;
|
||||||
|
for(i=0;i<afile->fo.nlist;i++) {
|
||||||
|
/*printf("found option: %s, len=%d, n=%d\n", afile->fo.olist[i].text, afile->fo.olist[i].len,n);*/
|
||||||
|
n += afile->fo.olist[i].len +1;
|
||||||
|
}
|
||||||
|
return ++n;
|
||||||
|
}
|
||||||
|
|
||||||
31
xa-2.3.5/src/xao.h
Normal file
31
xa-2.3.5/src/xao.h
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
/* xa65 - 65xx/65816 cross-assembler and utility suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 1989-1997 André Fachat (a.fachat@physik.tu-chemnitz.de)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
#ifndef __XA65_XAO_H__
|
||||||
|
#define __XA65_XAO_H__
|
||||||
|
|
||||||
|
/* sets file option after pass 1 */
|
||||||
|
void set_fopt(int l, signed char *buf, int reallen);
|
||||||
|
|
||||||
|
/* writes file options to a file */
|
||||||
|
void o_write(FILE *fp);
|
||||||
|
|
||||||
|
/* return overall length of header options */
|
||||||
|
size_t o_length(void);
|
||||||
|
|
||||||
|
#endif /* __XA65_XAO_H__ */
|
||||||
1020
xa-2.3.5/src/xap.c
Normal file
1020
xa-2.3.5/src/xap.c
Normal file
File diff suppressed because it is too large
Load diff
41
xa-2.3.5/src/xap.h
Normal file
41
xa-2.3.5/src/xap.h
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
/* xa65 - 65xx/65816 cross-assembler and utility suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 1989-1997 André Fachat (a.fachat@physik.tu-chemnitz.de)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
#ifndef __XA65_XAP_H__
|
||||||
|
#define __XA65_XAP_H__
|
||||||
|
|
||||||
|
#include "xah2.h" /* for Datei */
|
||||||
|
|
||||||
|
int pp_comand(char *t);
|
||||||
|
int pp_init(void);
|
||||||
|
int pp_open(char *name);
|
||||||
|
int pp_define(char *name);
|
||||||
|
void pp_close(void);
|
||||||
|
void pp_end(void);
|
||||||
|
int pgetline(char *t);
|
||||||
|
Datei *pp_getidat(void);
|
||||||
|
|
||||||
|
int ga_pp(void);
|
||||||
|
int gm_pp(void);
|
||||||
|
long gm_ppm(void);
|
||||||
|
long ga_ppm(void);
|
||||||
|
|
||||||
|
Datei *filep;
|
||||||
|
char s[MAXLINE];
|
||||||
|
|
||||||
|
#endif /* __XA65_XAP_H__ */
|
||||||
284
xa-2.3.5/src/xar.c
Normal file
284
xa-2.3.5/src/xar.c
Normal file
|
|
@ -0,0 +1,284 @@
|
||||||
|
/* xa65 - 65xx/65816 cross-assembler and utility suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 1989-1997 André Fachat (a.fachat@physik.tu-chemnitz.de)
|
||||||
|
*
|
||||||
|
* Relocation module (for relocatable objects)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "xad.h"
|
||||||
|
#include "xah.h"
|
||||||
|
#include "xar.h"
|
||||||
|
#include "xa.h"
|
||||||
|
#include "xal.h"
|
||||||
|
#include "xao.h"
|
||||||
|
#include "xau.h"
|
||||||
|
|
||||||
|
File *afile = NULL;
|
||||||
|
|
||||||
|
int rmode = RMODE_RELOC;
|
||||||
|
|
||||||
|
int r_set(int pc, int afl, int l) {
|
||||||
|
/*printf("set relocation @$%04x, l=%d, afl=%04x, segment=%d\n",pc, l, afl,segment);*/
|
||||||
|
if(segment==SEG_TEXT) return rt_set(pc,afl,l,0);
|
||||||
|
if(segment==SEG_DATA) return rd_set(pc,afl,l,0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int u_set(int pc, int afl, int label, int l) {
|
||||||
|
/*printf("set relocation @$%04x, l=%d, afl=%04x, segment=%d, label=%d\n",
|
||||||
|
pc, l, afl,segment, label);*/
|
||||||
|
if((afl & A_FMASK) == (SEG_UNDEF<<8))
|
||||||
|
label = u_label(label); /* set label as undefined */
|
||||||
|
if(segment==SEG_TEXT) return rt_set(pc,afl,l,label);
|
||||||
|
if(segment==SEG_DATA) return rd_set(pc,afl,l,label);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void r_mode(int m) {
|
||||||
|
static int old_segment = SEG_TEXT;
|
||||||
|
/*printf("setting mode to %s\n",(m==RMODE_RELOC)?"reloc":"abs");*/
|
||||||
|
if(rmode!=m) {
|
||||||
|
if(m==RMODE_RELOC) {
|
||||||
|
segment = old_segment;
|
||||||
|
} else { /* absolute mode */
|
||||||
|
old_segment = segment;
|
||||||
|
segment = SEG_ABS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rmode = m;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rt_set(int pc, int afl, int l, int lab) {
|
||||||
|
int p,pp;
|
||||||
|
|
||||||
|
if(!rmode) return 0;
|
||||||
|
|
||||||
|
/*printf("set relocation @$%04x, l=%d, afl=%04x\n",pc, l, afl);*/
|
||||||
|
|
||||||
|
if(l==2 && ((afl & A_MASK)!=A_ADR)) {
|
||||||
|
errout(W_BYTRELOC);
|
||||||
|
/*printf("Warning: byte relocation in word value at PC=$%04x!\n",pc);*/
|
||||||
|
}
|
||||||
|
if(l==1 && ((afl&A_MASK)==A_ADR)) {
|
||||||
|
if((afl & A_FMASK) != (SEG_ZERO<<8)) {
|
||||||
|
/*printf("afl=%04x\n",afl);*/
|
||||||
|
errout(W_ADRRELOC);
|
||||||
|
}
|
||||||
|
/*printf("Warning: cutting address relocation in byte value at PC=$%04x!\n",pc);*/
|
||||||
|
afl = (afl & (~A_MASK)) | A_LOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(afile->rt.nlist>=afile->rt.mlist) {
|
||||||
|
afile->rt.mlist+=500;
|
||||||
|
afile->rt.rlist=realloc(afile->rt.rlist, afile->rt.mlist*sizeof(relocateInfo));
|
||||||
|
}
|
||||||
|
if(!afile->rt.rlist) {
|
||||||
|
fprintf(stderr, "Oops: no memory for relocation table!\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
afile->rt.rlist[afile->rt.nlist].adr = pc;
|
||||||
|
afile->rt.rlist[afile->rt.nlist].afl = afl;
|
||||||
|
afile->rt.rlist[afile->rt.nlist].lab = lab;
|
||||||
|
afile->rt.rlist[afile->rt.nlist].next= -1;
|
||||||
|
|
||||||
|
/* sorting this into the list is not optimized, to be honest... */
|
||||||
|
if(afile->rt.first<0) {
|
||||||
|
afile->rt.first = afile->rt.nlist;
|
||||||
|
} else {
|
||||||
|
p=afile->rt.first; pp=-1;
|
||||||
|
while(afile->rt.rlist[p].adr<pc && afile->rt.rlist[p].next>=0) {
|
||||||
|
pp=p;
|
||||||
|
p=afile->rt.rlist[p].next;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
printf("endloop: p=%d(%04x), pp=%d(%04x), nlist=%d(%04x)\n",
|
||||||
|
p,p<0?0:afile->rt.rlist[p].adr,pp,pp<0?0:afile->rt.rlist[pp].adr,afile->rt.nlist,afile->rt.nlist<0?0:afile->rt.rlist[afile->rt.nlist].adr);
|
||||||
|
*/
|
||||||
|
if(afile->rt.rlist[p].next<0 && afile->rt.rlist[p].adr<pc) {
|
||||||
|
afile->rt.rlist[p].next=afile->rt.nlist;
|
||||||
|
} else
|
||||||
|
if(pp==-1) {
|
||||||
|
afile->rt.rlist[afile->rt.nlist].next = afile->rt.first;
|
||||||
|
afile->rt.first = afile->rt.nlist;
|
||||||
|
} else {
|
||||||
|
afile->rt.rlist[afile->rt.nlist].next = p;
|
||||||
|
afile->rt.rlist[pp].next = afile->rt.nlist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
afile->rt.nlist++;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rt_write(FILE *fp, int pc) {
|
||||||
|
int p=afile->rt.first;
|
||||||
|
int pc2, afl;
|
||||||
|
|
||||||
|
while(p>=0) {
|
||||||
|
pc2=afile->rt.rlist[p].adr;
|
||||||
|
afl=afile->rt.rlist[p].afl;
|
||||||
|
/* hack to switch undef and abs flag from internal to file format */
|
||||||
|
if( ((afl & A_FMASK)>>8) < SEG_TEXT) afl^=0x100;
|
||||||
|
/*printf("rt_write: pc=%04x, pc2=%04x, afl=%x\n",pc,pc2,afl);*/
|
||||||
|
if((pc2-pc) < 0) {
|
||||||
|
fprintf(stderr, "Oops, negative offset!\n");
|
||||||
|
} else {
|
||||||
|
while((pc2-pc)>254) {
|
||||||
|
fputc(255,fp);
|
||||||
|
pc+=254;
|
||||||
|
}
|
||||||
|
fputc(pc2-pc, fp);
|
||||||
|
pc=pc2;
|
||||||
|
fputc((afl>>8)&255, fp);
|
||||||
|
if((afile->rt.rlist[p].afl&A_FMASK)==(SEG_UNDEF<<8)) {
|
||||||
|
fputc(afile->rt.rlist[p].lab & 255, fp);
|
||||||
|
fputc((afile->rt.rlist[p].lab>>8) & 255, fp);
|
||||||
|
}
|
||||||
|
if((afl&A_MASK)==A_HIGH) fputc(afl&255,fp);
|
||||||
|
}
|
||||||
|
p=afile->rt.rlist[p].next;
|
||||||
|
}
|
||||||
|
fputc(0, fp);
|
||||||
|
|
||||||
|
free(afile->rt.rlist);
|
||||||
|
afile->rt.rlist = NULL;
|
||||||
|
afile->rt.mlist = afile->rt.nlist = 0;
|
||||||
|
afile->rt.first = -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void seg_start(int fmode, int t_base, int d_base, int b_base, int z_base,
|
||||||
|
int slen, int relmode) {
|
||||||
|
afile->fmode = fmode;
|
||||||
|
afile->slen = slen;
|
||||||
|
afile->relmode = relmode;
|
||||||
|
|
||||||
|
pc[SEG_TEXT] = afile->base[SEG_TEXT] = t_base;
|
||||||
|
pc[SEG_DATA] = afile->base[SEG_DATA] = d_base;
|
||||||
|
pc[SEG_BSS] = afile->base[SEG_BSS] = b_base;
|
||||||
|
pc[SEG_ZERO] = afile->base[SEG_ZERO] = z_base;
|
||||||
|
|
||||||
|
afile->old_abspc = pc[SEG_ABS];
|
||||||
|
pc[SEG_ABS] = pc[SEG_TEXT];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
File *alloc_file(void) {
|
||||||
|
File *afile;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
afile = malloc(sizeof(File));
|
||||||
|
if(!afile) {
|
||||||
|
fprintf(stderr,"Oops: not enough memory!\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
afile->mn.tmp = malloc(TMPMEM);
|
||||||
|
if(!afile->mn.tmp) {
|
||||||
|
fprintf(stderr,"Oops: not enough memory!\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
afile->mn.tmpz = 0;
|
||||||
|
afile->mn.tmpe = 0;
|
||||||
|
|
||||||
|
afile->ud.ulist = NULL; afile->ud.un = afile->ud.um = 0;
|
||||||
|
afile->rt.rlist = NULL; afile->rt.first = -1;
|
||||||
|
afile->rt.mlist = afile->rt.nlist = 0;
|
||||||
|
afile->rd.rlist = NULL; afile->rd.first = -1;
|
||||||
|
afile->rd.mlist = afile->rd.nlist = 0;
|
||||||
|
afile->fo.olist = NULL;
|
||||||
|
afile->fo.mlist = afile->fo.nlist = 0;
|
||||||
|
|
||||||
|
for(i=0;i<256;i++) afile->la.hashindex[i]=0;
|
||||||
|
afile->la.lt = NULL;
|
||||||
|
afile->la.lti = 0;
|
||||||
|
afile->la.ltm = 0;
|
||||||
|
|
||||||
|
afile->len[SEG_TEXT] = afile->len[SEG_DATA] =
|
||||||
|
afile->len[SEG_BSS] = afile->len[SEG_ZERO] = 0;
|
||||||
|
|
||||||
|
return afile;
|
||||||
|
}
|
||||||
|
|
||||||
|
void seg_pass2(void) {
|
||||||
|
|
||||||
|
pc[SEG_TEXT] = afile->base[SEG_TEXT];
|
||||||
|
pc[SEG_DATA] = afile->base[SEG_DATA];
|
||||||
|
pc[SEG_BSS] = afile->base[SEG_BSS];
|
||||||
|
pc[SEG_ZERO] = afile->base[SEG_ZERO];
|
||||||
|
|
||||||
|
afile->old_abspc = pc[SEG_ABS];
|
||||||
|
pc[SEG_ABS] = pc[SEG_TEXT];
|
||||||
|
}
|
||||||
|
|
||||||
|
void seg_end(FILE *fpout) {
|
||||||
|
#if 0
|
||||||
|
afile->len[SEG_TEXT] = pc[SEG_TEXT] - afile->base[SEG_TEXT];
|
||||||
|
afile->len[SEG_DATA] = pc[SEG_DATA] - afile->base[SEG_DATA];
|
||||||
|
afile->len[SEG_BSS ] = pc[SEG_BSS ] - afile->base[SEG_BSS ];
|
||||||
|
afile->len[SEG_ZERO] = pc[SEG_ZERO] - afile->base[SEG_ZERO];
|
||||||
|
#endif
|
||||||
|
/* TODO: file length to embed */
|
||||||
|
/* pc[SEG_ABS] = afile->old_abspc + seg_flen();*/
|
||||||
|
|
||||||
|
/*printf("seg_end: len[text]=%d, len[data]=%d, len[bss]=%d, len[zero]=%d\n",
|
||||||
|
afile->len[SEG_TEXT], afile->len[SEG_DATA], afile->len[SEG_BSS], afile->len[SEG_ZERO]);*/
|
||||||
|
segment = SEG_ABS;
|
||||||
|
|
||||||
|
u_write(fpout);
|
||||||
|
rt_write(fpout, afile->base[SEG_TEXT]-1);
|
||||||
|
rd_write(fpout, afile->base[SEG_DATA]-1);
|
||||||
|
l_write(fpout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write header for relocatable output format */
|
||||||
|
int h_write(FILE *fp, int mode, int tlen, int dlen, int blen, int zlen,
|
||||||
|
int stack) {
|
||||||
|
|
||||||
|
afile->len[SEG_TEXT] = tlen;
|
||||||
|
afile->len[SEG_DATA] = dlen;
|
||||||
|
afile->len[SEG_BSS ] = blen;
|
||||||
|
afile->len[SEG_ZERO] = zlen;
|
||||||
|
|
||||||
|
fputc(1, fp); /* version byte */
|
||||||
|
fputc(0, fp); /* hi address 0 -> no C64 */
|
||||||
|
fputc('o', fp);
|
||||||
|
fputc('6', fp);
|
||||||
|
fputc('5', fp);
|
||||||
|
fputc(0, fp); /* format version */
|
||||||
|
fputw(mode, fp); /* file mode */
|
||||||
|
fputw(afile->base[SEG_TEXT],fp); /* text base */
|
||||||
|
fputw(tlen,fp); /* text length */
|
||||||
|
fputw(afile->base[SEG_DATA],fp); /* data base */
|
||||||
|
fputw(dlen,fp); /* data length */
|
||||||
|
fputw(afile->base[SEG_BSS],fp); /* bss base */
|
||||||
|
fputw(blen,fp); /* bss length */
|
||||||
|
fputw(afile->base[SEG_ZERO],fp); /* zerop base */
|
||||||
|
fputw(zlen,fp); /* zerop length */
|
||||||
|
fputw(stack,fp); /* needed stack size */
|
||||||
|
|
||||||
|
o_write(fp);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
48
xa-2.3.5/src/xar.h
Normal file
48
xa-2.3.5/src/xar.h
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
/* xa65 - 65xx/65816 cross-assembler and utility suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 1989-1997 André Fachat (a.fachat@physik.tu-chemnitz.de)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
#ifndef __XA65_XAR_H__
|
||||||
|
#define __XA65_XAR_H__
|
||||||
|
|
||||||
|
#define RMODE_ABS 0
|
||||||
|
#define RMODE_RELOC 1
|
||||||
|
|
||||||
|
extern File *alloc_file(void);
|
||||||
|
|
||||||
|
/* jumps to r[td]_set, depending on segment */
|
||||||
|
int r_set(int pc, int reloc, int len);
|
||||||
|
int u_set(int pc, int reloc, int label, int len);
|
||||||
|
|
||||||
|
int rt_set(int pc, int reloc, int len, int label);
|
||||||
|
int rd_set(int pc, int reloc, int len, int label);
|
||||||
|
int rt_write(FILE *fp, int pc);
|
||||||
|
int rd_write(FILE *fp, int pc);
|
||||||
|
|
||||||
|
void r_mode(int mode);
|
||||||
|
|
||||||
|
/* int rmode; */
|
||||||
|
|
||||||
|
int h_write(FILE *fp, int mode, int tlen, int dlen, int blen, int zlen,
|
||||||
|
int stacklen);
|
||||||
|
|
||||||
|
void seg_start(int fmode, int tbase, int dbase, int bbase, int zbase,
|
||||||
|
int stacklen, int relmode);
|
||||||
|
void seg_end(FILE *);
|
||||||
|
void seg_pass2(void);
|
||||||
|
|
||||||
|
#endif /* __XA65_XAR_H__ */
|
||||||
132
xa-2.3.5/src/xar2.c
Normal file
132
xa-2.3.5/src/xar2.c
Normal file
|
|
@ -0,0 +1,132 @@
|
||||||
|
/* xa65 - 65xx/65816 cross-assembler and utility suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 1989-1997 André Fachat (a.fachat@physik.tu-chemnitz.de)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "xah.h"
|
||||||
|
#include "xa.h"
|
||||||
|
#include "xar.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
static relocateInfo *rlist = NULL;
|
||||||
|
static int mlist = 0, nlist = 0;
|
||||||
|
static int first = -1;
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* int rmode; */
|
||||||
|
|
||||||
|
int rd_set(int pc, int afl, int l, int lab) {
|
||||||
|
int p,pp;
|
||||||
|
|
||||||
|
/* if(!rmode) return 0; */
|
||||||
|
|
||||||
|
/*printf("set relocation @$%04x, l=%d, afl=%04x\n",pc, l, afl);*/
|
||||||
|
|
||||||
|
if(l==2 && ((afl & A_MASK)!=A_ADR)) {
|
||||||
|
errout(W_BYTRELOC);
|
||||||
|
/*printf("Warning: byte relocation in word value at PC=$%04x!\n",pc);*/
|
||||||
|
}
|
||||||
|
if(l==1 && ((afl&A_MASK)==A_ADR)) {
|
||||||
|
if((afl & A_FMASK) != (SEG_ZERO<<8)) errout(W_ADRRELOC);
|
||||||
|
/*printf("Warning: cutting address relocation in byte value at PC=$%04x!\n",pc);*/
|
||||||
|
afl = (afl & (~A_MASK)) | A_LOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(afile->rd.nlist>=afile->rd.mlist) {
|
||||||
|
afile->rd.mlist+=500;
|
||||||
|
afile->rd.rlist=realloc(afile->rd.rlist, afile->rd.mlist*sizeof(relocateInfo));
|
||||||
|
}
|
||||||
|
if(!afile->rd.rlist) {
|
||||||
|
fprintf(stderr, "Oops: no memory for relocation table!\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
afile->rd.rlist[afile->rd.nlist].adr = pc;
|
||||||
|
afile->rd.rlist[afile->rd.nlist].afl = afl;
|
||||||
|
afile->rd.rlist[afile->rd.nlist].lab = lab;
|
||||||
|
afile->rd.rlist[afile->rd.nlist].next= -1;
|
||||||
|
|
||||||
|
/* sorting this into the list is not optimized, to be honest... */
|
||||||
|
if(afile->rd.first<0) {
|
||||||
|
afile->rd.first = afile->rd.nlist;
|
||||||
|
} else {
|
||||||
|
p=afile->rd.first; pp=-1;
|
||||||
|
while(afile->rd.rlist[p].adr<pc && afile->rd.rlist[p].next>=0) {
|
||||||
|
pp=p;
|
||||||
|
p=afile->rd.rlist[p].next;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
printf("endloop: p=%d(%04x), pp=%d(%04x), nlist=%d(%04x)\n",
|
||||||
|
p,p<0?0:afile->rd.rlist[p].adr,pp,pp<0?0:afile->rd.rlist[pp].adr,afile->rd.nlist,afile->rd.nlist<0?0:afile->rd.rlist[afile->rd.nlist].adr);
|
||||||
|
*/
|
||||||
|
if(afile->rd.rlist[p].next<0 && afile->rd.rlist[p].adr<pc) {
|
||||||
|
afile->rd.rlist[p].next=afile->rd.nlist;
|
||||||
|
} else
|
||||||
|
if(pp==-1) {
|
||||||
|
afile->rd.rlist[afile->rd.nlist].next = afile->rd.first;
|
||||||
|
afile->rd.first = afile->rd.nlist;
|
||||||
|
} else {
|
||||||
|
afile->rd.rlist[afile->rd.nlist].next = p;
|
||||||
|
afile->rd.rlist[pp].next = afile->rd.nlist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
afile->rd.nlist++;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rd_write(FILE *fp, int pc) {
|
||||||
|
int p=afile->rd.first;
|
||||||
|
int pc2, afl;
|
||||||
|
|
||||||
|
while(p>=0) {
|
||||||
|
pc2=afile->rd.rlist[p].adr;
|
||||||
|
afl=afile->rd.rlist[p].afl;
|
||||||
|
/*printf("rd_write: pc=%04x, pc2=%04x, afl=%x\n",pc,pc2,afl);*/
|
||||||
|
/* hack to switch undef and abs flag from internal to file format */
|
||||||
|
if( ((afl & A_FMASK)>>8) < SEG_TEXT) afl^=0x100;
|
||||||
|
if((pc2-pc) < 0) {
|
||||||
|
fprintf(stderr, "Oops, negative offset!\n");
|
||||||
|
} else {
|
||||||
|
while((pc2-pc)>254) {
|
||||||
|
fputc(255,fp);
|
||||||
|
pc+=254;
|
||||||
|
}
|
||||||
|
fputc(pc2-pc, fp);
|
||||||
|
pc=pc2;
|
||||||
|
fputc((afl>>8)&255, fp);
|
||||||
|
if((afile->rd.rlist[p].afl&A_FMASK)==(SEG_UNDEF<<8)) {
|
||||||
|
fputc(afile->rd.rlist[p].lab & 255, fp);
|
||||||
|
fputc((afile->rd.rlist[p].lab>>8) & 255, fp);
|
||||||
|
}
|
||||||
|
if((afl&A_MASK)==A_HIGH) fputc(afl&255,fp);
|
||||||
|
}
|
||||||
|
p=afile->rd.rlist[p].next;
|
||||||
|
}
|
||||||
|
fputc(0, fp);
|
||||||
|
|
||||||
|
free(afile->rd.rlist);
|
||||||
|
afile->rd.rlist = NULL;
|
||||||
|
afile->rd.mlist = afile->rd.nlist = 0;
|
||||||
|
afile->rd.first = -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
2097
xa-2.3.5/src/xat.c
Normal file
2097
xa-2.3.5/src/xat.c
Normal file
File diff suppressed because it is too large
Load diff
28
xa-2.3.5/src/xat.h
Normal file
28
xa-2.3.5/src/xat.h
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
/* xa65 - 65xx/65816 cross-assembler and utility suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 1989-1997 André Fachat (a.fachat@physik.tu-chemnitz.de)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
#ifndef __XA65_XAT_H__
|
||||||
|
#define __XA65_XAT_H__
|
||||||
|
|
||||||
|
extern int dsb_len;
|
||||||
|
|
||||||
|
int t_p1(signed char *s, signed char *t, int *ll, int *al);
|
||||||
|
int t_p2(signed char *t, int *ll, int fl, int *al);
|
||||||
|
int b_term(char *s, int *v, int *l, int pc);
|
||||||
|
|
||||||
|
#endif /* __XA65_XAT_H__ */
|
||||||
73
xa-2.3.5/src/xau.c
Normal file
73
xa-2.3.5/src/xau.c
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
/* xa65 - 65xx/65816 cross-assembler and utility suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 1989-1997 André Fachat (a.fachat@physik.tu-chemnitz.de)
|
||||||
|
*
|
||||||
|
* Undefined label tracking module (also see xal.c)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "xad.h"
|
||||||
|
#include "xau.h"
|
||||||
|
#include "xah.h"
|
||||||
|
#include "xal.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
static int *ulist = NULL;
|
||||||
|
static int un = 0;
|
||||||
|
static int um = 0;
|
||||||
|
*/
|
||||||
|
|
||||||
|
int u_label(int labnr) {
|
||||||
|
int i;
|
||||||
|
/*printf("u_label: %d\n",labnr);*/
|
||||||
|
if(!afile->ud.ulist) {
|
||||||
|
afile->ud.ulist = malloc(200*sizeof(int));
|
||||||
|
if(afile->ud.ulist) afile->ud.um=200;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0;i<afile->ud.un;i++) {
|
||||||
|
if(afile->ud.ulist[i] == labnr) return i;
|
||||||
|
}
|
||||||
|
if(afile->ud.un>=afile->ud.um) {
|
||||||
|
afile->ud.um *= 1.5;
|
||||||
|
afile->ud.ulist = realloc(afile->ud.ulist, afile->ud.um * sizeof(int));
|
||||||
|
if(!afile->ud.ulist) {
|
||||||
|
fprintf(stderr, "Panic: No memory!\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
afile->ud.ulist[afile->ud.un] = labnr;
|
||||||
|
return afile->ud.un++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void u_write(FILE *fp) {
|
||||||
|
int i, d;
|
||||||
|
char *s;
|
||||||
|
/*printf("u_write: un=%d\n",afile->ud.un);*/
|
||||||
|
fputw(afile->ud.un, fp);
|
||||||
|
|
||||||
|
for(i=0;i<afile->ud.un;i++) {
|
||||||
|
l_vget(afile->ud.ulist[i], &d, &s);
|
||||||
|
fprintf(fp,"%s", s);
|
||||||
|
fputc(0,fp);
|
||||||
|
}
|
||||||
|
free(afile->ud.ulist);
|
||||||
|
afile->ud.ulist=NULL;
|
||||||
|
afile->ud.um = afile->ud.un = 0;
|
||||||
|
}
|
||||||
24
xa-2.3.5/src/xau.h
Normal file
24
xa-2.3.5/src/xau.h
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
xa65 - 6502 cross assembler and utility suite
|
||||||
|
Copyright (C) 1989-1997 André Fachat (a.fachat@physik.tu-chemnitz.de)
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
extern int u_label(int labnr);
|
||||||
|
extern void u_write(FILE *fp);
|
||||||
|
|
||||||
24
xa-2.3.5/tests/README
Normal file
24
xa-2.3.5/tests/README
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
This is a directory of test suites for complex or pathological cases that
|
||||||
|
have been repaired (?) in the current version. It is primarily for internal
|
||||||
|
testing, but is here for your interest.
|
||||||
|
|
||||||
|
adrm/ Addressing mode test (especially the optimizer and quantity
|
||||||
|
prefixes)
|
||||||
|
nonl/ Patryk's no-new-line-on-last-line cases ;)
|
||||||
|
fordef/ Optimizer warnings for forward defined labels
|
||||||
|
relocundef/ Tests for the detection of undefined references during a
|
||||||
|
reloc65 export.
|
||||||
|
ldoreloc/ Test case for the relocation table reading of ldo when undef'd
|
||||||
|
refs are involved
|
||||||
|
comcom/ Comments-with-comments-with-commands-etc. for testing -M
|
||||||
|
recmac/ Recursive macro evaluation testing
|
||||||
|
openpp/ Testing of open #if*s in pp
|
||||||
|
cpp/ Random preprocessor tests, mostly crap
|
||||||
|
incerr/ 1) .xl/.al should error without -w 2) error should be in
|
||||||
|
the correct file
|
||||||
|
binclude/ Binary include code with some weird casing
|
||||||
|
chppch/ Changing preprocessor characters (-p)
|
||||||
|
charset/ Tests of when charsets should be honoured and when not
|
||||||
|
|
||||||
|
Cameron Kaiser, André Fachat
|
||||||
|
|
||||||
33
xa-2.3.5/tests/adrm/02.asm
Normal file
33
xa-2.3.5/tests/adrm/02.asm
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
.word $0400
|
||||||
|
* = $0400
|
||||||
|
|
||||||
|
q = $0005
|
||||||
|
fizz
|
||||||
|
/* these should be optimized to zero page */
|
||||||
|
sta $05
|
||||||
|
sta $0005
|
||||||
|
sta q
|
||||||
|
dec q
|
||||||
|
inc q
|
||||||
|
lda <$0005
|
||||||
|
/* these should not */
|
||||||
|
stx !$0005
|
||||||
|
sta !q
|
||||||
|
sta $8765
|
||||||
|
stx $919c
|
||||||
|
inc !q
|
||||||
|
dec $8342
|
||||||
|
sta $4431
|
||||||
|
inc $79e0
|
||||||
|
sty $1b0a
|
||||||
|
jsr $ffe4
|
||||||
|
jmp $fce2
|
||||||
|
jmp breadbox
|
||||||
|
lsr $2020
|
||||||
|
bne fizz
|
||||||
|
rts
|
||||||
|
|
||||||
|
breadbox rts
|
||||||
|
beq fizz
|
||||||
|
rts
|
||||||
|
|
||||||
29
xa-2.3.5/tests/adrm/816.asm
Normal file
29
xa-2.3.5/tests/adrm/816.asm
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
.word $0400
|
||||||
|
* = $0400
|
||||||
|
|
||||||
|
q = $0005
|
||||||
|
r = $000005
|
||||||
|
fizz
|
||||||
|
/* these should be optimized to zero page */
|
||||||
|
sta $05
|
||||||
|
sta $0005
|
||||||
|
sta q
|
||||||
|
sta r
|
||||||
|
/* 16-bit */
|
||||||
|
sta !$0005
|
||||||
|
sta !q
|
||||||
|
sta $8765
|
||||||
|
/* 24-bit */
|
||||||
|
sta @q
|
||||||
|
sta @$000005
|
||||||
|
sta $876543
|
||||||
|
rts
|
||||||
|
|
||||||
|
jmp $fce2
|
||||||
|
jmp $99fce2
|
||||||
|
jmp breadbox
|
||||||
|
jmp @breadbox
|
||||||
|
|
||||||
|
breadbox rts
|
||||||
|
bne fizz
|
||||||
|
rts
|
||||||
BIN
xa-2.3.5/tests/adrm/a.o65
Normal file
BIN
xa-2.3.5/tests/adrm/a.o65
Normal file
Binary file not shown.
28
xa-2.3.5/tests/adrm/bip.inc
Normal file
28
xa-2.3.5/tests/adrm/bip.inc
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
- tbasic.0.asm: if you make vecwri absolute with !, then the branch gets
|
||||||
|
generated as if it were NOT absolute. works okay without it (and
|
||||||
|
gets a warning)
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
test lda !$0095
|
||||||
|
bne test
|
||||||
|
|
||||||
|
ldx #13
|
||||||
|
lup0 lda @vecwri,x
|
||||||
|
sta $2005,x
|
||||||
|
dex
|
||||||
|
bne lup0
|
||||||
|
lda #$00
|
||||||
|
sta $0020
|
||||||
|
lda #$02
|
||||||
|
sta $0021
|
||||||
|
lda #$ff
|
||||||
|
sta $0022
|
||||||
|
lda #$13
|
||||||
|
sta $0023
|
||||||
|
jmp $2003
|
||||||
|
|
||||||
|
vectors .byt $4c, $5a, $1e, $4c, $a0, $1e, $4c, $00, $01
|
||||||
|
vecwri = vectors - 1
|
||||||
33
xa-2.3.5/tests/adrm/c02.asm
Normal file
33
xa-2.3.5/tests/adrm/c02.asm
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
.word $0400
|
||||||
|
* = $0400
|
||||||
|
|
||||||
|
q = $0005
|
||||||
|
fizz
|
||||||
|
/* these should be optimized to zero page */
|
||||||
|
sta $05
|
||||||
|
sta $0005
|
||||||
|
sta q
|
||||||
|
dec q
|
||||||
|
inc q
|
||||||
|
/* these should not */
|
||||||
|
stx !$0005
|
||||||
|
sta !q
|
||||||
|
sta $8765
|
||||||
|
stx $919c
|
||||||
|
inc !q
|
||||||
|
inc; a
|
||||||
|
dec $8342
|
||||||
|
dec; a
|
||||||
|
sta $4431
|
||||||
|
inc $79e0
|
||||||
|
sty $1b0a
|
||||||
|
jsr $ffe4
|
||||||
|
jmp $fce2
|
||||||
|
jmp breadbox
|
||||||
|
lsr $2020
|
||||||
|
rts
|
||||||
|
|
||||||
|
|
||||||
|
breadbox rts
|
||||||
|
bne fizz
|
||||||
|
rts
|
||||||
4
xa-2.3.5/tests/adrm/zab.asm
Normal file
4
xa-2.3.5/tests/adrm/zab.asm
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
.word $4000
|
||||||
|
* = $4000
|
||||||
|
|
||||||
|
#include "bip.inc"
|
||||||
4
xa-2.3.5/tests/adrm/zpa.asm
Normal file
4
xa-2.3.5/tests/adrm/zpa.asm
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
.word $0000
|
||||||
|
* = $0000
|
||||||
|
|
||||||
|
#include "bip.inc"
|
||||||
117
xa-2.3.5/tests/binclude/README.1st
Normal file
117
xa-2.3.5/tests/binclude/README.1st
Normal file
|
|
@ -0,0 +1,117 @@
|
||||||
|
This is the readme for xa, a cross-assembler for the 6502 and 65816 CPUs (and
|
||||||
|
derivatives). xa is a small, fast, portable two-pass assembler that compiles
|
||||||
|
under most ANSI C compilers. It is distributed under the GNU Public License
|
||||||
|
(see COPYING).
|
||||||
|
|
||||||
|
The current version is 2.3.3, which implements several compatibility
|
||||||
|
improvements on 2.3.2, a bug fix to the 2.3.0 version.
|
||||||
|
|
||||||
|
2.3.0 itself features many compatibility improvements and new man-based
|
||||||
|
documentation. It also completed the merge of the 65816 and 6502/R65C02
|
||||||
|
versions and thus the current xa can generate code for all targets now.
|
||||||
|
|
||||||
|
To install on a generic Unixy thing, you should be able to just type
|
||||||
|
|
||||||
|
% make # to build the executable, and if it works ...
|
||||||
|
% make install # to install man pages and binaries into the system
|
||||||
|
|
||||||
|
This will create xa along with its various support utilities. Try assembling
|
||||||
|
the cpk depacker in examples/ as a test. xa also comes with uncpk (a program
|
||||||
|
for generating cpk archives) and printcbm (a program for listing Commodore
|
||||||
|
BASIC test) and file65, ldo65 and reloc65 for displaying, linking and
|
||||||
|
relocating o65 files in Andre's relocatable format (see doc/fileformats.txt).
|
||||||
|
The loader/ directory also has goodies for managing relocatable binaries.
|
||||||
|
|
||||||
|
Don't forget the man pages in man/. Install these into your MANPATH at your
|
||||||
|
leisure, or read them with nroff -man (and/or groff -man).
|
||||||
|
|
||||||
|
xa is no longer broadly supported outside of Unix due to my inability to test
|
||||||
|
it, but has nothing that should impair it from compiling elsewhere. To wit,
|
||||||
|
DOS compilation is still supported with the GO32 package. You should just be
|
||||||
|
able to type
|
||||||
|
|
||||||
|
C:\> make dos
|
||||||
|
|
||||||
|
In addition, there are compatibility updates to allow it to compile under
|
||||||
|
Microsoft Visual Studio and mingw. It should compile under VS2005 as written;
|
||||||
|
look in the vstudio directory for solution and project files provided by
|
||||||
|
Fabian Nunez. For mingw, use
|
||||||
|
|
||||||
|
make mingw
|
||||||
|
|
||||||
|
Similarly, Amiga and Atari ST compilation should still also function with
|
||||||
|
their particular compatible packages.
|
||||||
|
|
||||||
|
xa has a companion disassembler, the dxa package. dxa is not included in the
|
||||||
|
standard xa distribution, but can be downloaded from the xa home page at
|
||||||
|
|
||||||
|
http://www.floodgap.com/retrotech/xa/
|
||||||
|
|
||||||
|
Please check by periodically for the latest version of both packages.
|
||||||
|
|
||||||
|
xa was originally written and maintained by Andre Fachat. The current version
|
||||||
|
is maintained by Cameron Kaiser.
|
||||||
|
|
||||||
|
Please send me your comments at ckaiser@floodgap.com -- Andre's original
|
||||||
|
readme follows and applies generally to the present version.
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
XA is a 6502 cross compiler:
|
||||||
|
|
||||||
|
- under GNU public license
|
||||||
|
|
||||||
|
- can produce _relocatable_ binaries
|
||||||
|
|
||||||
|
- The full fileformat description and 6502 file loader included.
|
||||||
|
|
||||||
|
- also included relocation and info utilites, as well as linker
|
||||||
|
|
||||||
|
- for any ANSI-C compliant computer (only utilities need 'stat' call
|
||||||
|
for file size).
|
||||||
|
|
||||||
|
- fast by hashtables
|
||||||
|
|
||||||
|
- Rockwell CMOS opcodes
|
||||||
|
|
||||||
|
- running under DOS and any ANSI C system (Unix, Amiga, Atari ST)
|
||||||
|
|
||||||
|
I developed this cross assembler for the 6502 CPU family quite some time
|
||||||
|
ago on my Atari ST. The assembler has successfully been ported to Amiga
|
||||||
|
and Unix computer (ported? just compiled... :-)
|
||||||
|
Lately I came across the problem to need relocatable 6502 binary files, so
|
||||||
|
I revised the assembler from version 2.0.7 to 2.1.0, adding a (admittedly
|
||||||
|
proprietary) 6502 relocatable binary format. But there are not many other
|
||||||
|
formats around and they didn't fit my needs. I have developed this format
|
||||||
|
myself and it is under the GNU public license.
|
||||||
|
With version 2.1.1 the 'official' version of the fileformat is supported.
|
||||||
|
|
||||||
|
To compile it, just type "make" (if you have the GNU gcc. If not, edit the
|
||||||
|
Makefile for the compiler options). This produces "xa", the cross assembler;
|
||||||
|
"uncpk", a small packing utility (where the C64 counterpart is in the
|
||||||
|
examples subdirectory), "printcbm", that lists C64 BASIC files and
|
||||||
|
'file65' that prints some information about o65 files. The "loader" in
|
||||||
|
the loader subdirectory is a basic 6502 implementation of a relocating
|
||||||
|
binary loader.
|
||||||
|
"file65" prints file information on 'o65' relocatable files. "reloc65"
|
||||||
|
can relocate 'o65' files.
|
||||||
|
|
||||||
|
If you want to use it under DOS, you have to have the GO32 DOS crosscompiling
|
||||||
|
tools to compile. Then just type "make dos" and you'll end up with the
|
||||||
|
appropriate DOS binaries. This has been tested only under i386 Linux, however.
|
||||||
|
Another archive with the DOS binaries included is provided.
|
||||||
|
|
||||||
|
One problem on the Atari was it's broken "malloc". Therefore I used to
|
||||||
|
alloc everything in one chunk and divide the memory by hand. So everything
|
||||||
|
was kind of statically allocated. This is almost gone now. Only the
|
||||||
|
temporary storage between pass1 and pass2 and the preprocessor are still
|
||||||
|
allocated in one chunk (size definitions in xah.h). The rest is allocated
|
||||||
|
as needed.
|
||||||
|
|
||||||
|
The docs are in the 'doc' subdir. There also is a description of the
|
||||||
|
6502 relocatable binary format. If you think some things could be
|
||||||
|
expressed in a better way, feel free and mail me to improve my english ;-)
|
||||||
|
[ The documentation is now maintained in man(1) format in man/ . -- CK ]
|
||||||
|
|
||||||
|
Andre
|
||||||
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue