xa-2.4.0/0000700000031500000010000000000014524607311011430 5ustar spectrestaffxa-2.4.0/COPYING0000600000031500000010000004312214513025305012462 0ustar spectrestaff 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. Copyright (C) 20yy 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. , 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. xa-2.4.0/ChangeLog0000600000031500000010000004012314526073141013204 0ustar spectrestaffxa-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 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 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 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 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 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 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 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 21 Dec, 1996 xa-2.1.1a * Embedding absolute code in relocatable seems to work now. -- André Fachat 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 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 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 03 Jan, 1997 xa-2.1.2 * Added ``ld65'', a simple linker for o65 files. * Another bug in xa fixed now. -- André Fachat 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 25 Mar, 1997 xa-2.1.3e * Added preprocessor continuation lines, and .block and .bend pseudo-opcodes (They map to ``.('' and ``.)'' respectively.) -- André Fachat 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 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 30 Dec, 1997 xa-2.1.4d * fixed align code. Now inserts NOP opcodes into text segment, and sets file mode appropriately. -- André Fachat 26 Jan, 1998 xa-2.1.4e * Changed o65 fileformat and adopted it in xa. -- André Fachat 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 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 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 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 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 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 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 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 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 7 February, 2009 xa-2.3.6 * 'make test' for regression testing framework (requires Perl). * Changed getline() to xa_getline() to avoid collision with glibc 2.10+ * Fixed compile problems with misc/. * Fixed message offsets. -- Cameron Kaiser 11 July 2014 xa-2.3.7 * Fixed buffer overflow and test failure with gcc 4.9 (thanks Adam Sampson). * mvn and mvp now use the standard syntax (thanks Alessandro Gatti). * Copyright message is no longer put in the error log to simplify testing. * Makefile properly triggers a relink for testing or source changes. * Spurious messages quelled. * Documentation updated. * Testsuite expanded. -- Cameron Kaiser 29 December 2014 xa-2.3.8 * Fixed issue with colons in string literals being treated as separators (thanks Simon Rowe). * Testsuite expanded. -- Cameron Kaiser 29 June 2017 xa-2.3.9 * Fixed issue on Windows and DOS systems with the .bin pseudo-op (thanks Bago Zonde). * Documentation updated. * Testsuite expanded. * For the thirty year anniversary of xa, we're changing the name to xxxa. (Just kidding.) -- Cameron Kaiser 31 January 2019 xa-2.3.10 * Three fixes, all from Andre: - Don't crash if a useless segment is referenced outside of relocating mode (thanks Laszlo Barath for the report). - Don't substitute within strings, for better cpp compatibility (thanks Glenn Holmer for the report). I added the -S option for backwards compatibility for the old behaviour; it will be removed in 2.4 and later. - Fix underflow issue if a variable is late-bound (with -L) when that variable is used in computations with negative offsets. * Deprecated options will be removed in 2.4 and everything is warned. * Documentation updated. * Testsuite expanded. -- Cameron Kaiser 9 November 2019 xa-2.3.11 * Compilation fix for gcc 10 (thanks Dan Horak). * Allow pointer arithmetic in relocating mode within the same segment, since the result is segmentless (thanks Andre for the report). * .dsb with negative quantities shouldn't work (thanks Andre for the report). * Stop a divide-by-zero floating point exception (thanks Frederic Cambus). * Testsuite expanded. -- Cameron Kaiser 4 May 2020 xa-2.3.12 * Regression fix for address size validation in 65816 mode (thanks Sam Falvo; we had a pending fix for this but I like his test case). * Testsuite expanded. -- Cameron Kaiser 26 November 2021 xa-2.3.13 * Fix // and /* */ in quoted strings. Incredible no one ever hit this before (thanks ZornsLemma). * Segfault fixes for file65, reloc65 and xa. Remember, kids, if you ever run xa as root all kittens will die. Please save the kittens (thanks Stephen Kitt). * Just compare to null in the preprocessor (thanks Bas Wassink). * Testsuite expanded. -- Cameron Kaiser 25 March 2022 xa-2.3.14 * Fix a segfault when a recursive macro has a smaller arity than the macro it references (thanks Emil Johansson for the report). * Fix for recursive comments, which was a regression from 2.3.13 (note: this may be reexamined for 2.4), and some improvements to the comment parser to fix more edge cases. (Andre) * Now you can just do 'make test TESTS=test,test,test' instead of running ./tests/harness with specific options. ('make test' by itself of course still works fine to run the whole suite.) * Testsuite expanded. -- Cameron Kaiser 7 February 2023 xa-2.4.0 * Listing feature in plain text or HTML, along with .listbytes to control how hex bytes get listed in the output. * Add -E commandline option to not stop after 20 errors, but show all of them. * Introduce -X compatibility set commandline option, to distinguish between MASM and CA65 compatibility options; also adds C option for 0x and 0 to specify hex or octal. As a result, -M is now deprecated, and colons in comments may become the default in a future version. * Implement CA65 "cheap local labels", ":=" label definitions, and various pseudo-opcodes (.include, .import, .importzp, .zeropage, .proc (anonymous only), .endproc, .code, .org, .reloc). * -U option to allow all undefined labels in relocation mode; this allows exporting them to an o65 file and link at a later time (or specify one at a time with -L). * Globals may also be specified manually with -g. * #error allows preprocessor-level assertions. * .assert allows assembler-level assertions. * Better fix for segfault with smaller arity macro issue. * Main Makefile fixes. * Fixed parallel make in tests, incorporating a patch from Sergei Trofimovich. * Added a test case that failed in 2.3.14 from Tom Hargreaves. * Some 2.3.x features still allowed with -XXA23, which is obviously deprecated. * The quote escape character is now the \ (backslash), except if -XXA23. * Recursive /* */ comments are no longer allowed, except if -XXA23. * XA_MAJOR and XA_MINOR predefined macros, except if -XXA23. * Testsuite greatly expanded. * The old loader/ testsuite and doc/ archive are now in attic/, which is the repository for old unsupported components. It may be purged in a future version. * -M is now deprecated (use -XMASM), just in case you forgot. * printcbm(1) is now deprecated (use VICE petcat, it does a lot more). * Previously deprecated options (16-bit mvn/mvp argument, -S, -x) finally removed. If you need this support, you must use 2.3.x. -- André Fachat and -- Cameron Kaiser , 18 November, 2023 xa-2.4.0/Makefile0000600000031500000010000000327414520633224013076 0ustar spectrestaff# Unix gcc or DOS go32 cross-compiling gcc # VERS = 2.4.0 CC = gcc LD = gcc # for testing. not to be used; build failures in misc/. #CFLAGS = -O2 -W -Wall -pedantic -ansi #CFLAGS = -O2 -g CFLAGS = -O2 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 TESTS=ALL all: killxa xa uncpk killxa: rm -f xa 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 *.s core install: all $(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-$(VERS).tar xa-$(VERS) ; gzip xa-$(VERS).tar # no prereqs to force parallel make to play nice test: rm -rf xa $(MAKE) xa $(MAKE) uncpk cd tests && ./harness \ -tests="$(TESTS)" \ -cc="$(CC)" -cflags="$(CFLAGS)" \ -make="$(MAKE)" -makeflags="$(MAKEFLAGS)" xa-2.4.0/README.1st0000600000031500000010000001310614526073206013023 0ustar spectrestaffThis 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.4.0, the first new feature release literally in years. It builds upon the improvements in 2.3.x and its unified 6502/65816 assembler core by adding listing capability, greater flexibility with relocatable objects, and better cross-compatibility with other popular cross-assemblers (notably ca65) because once you use xa, you'll want to keep on using it. :) Certain long-deprecated options and non-standard syntaxes have also been removed in this release, so it is possible some very old code may not assemble without errors. These changes have been a long time coming and we gave lots of warnings, so if you require these features and cannot change your code to work without them, you must use xa 2.3.14. Fortunately, most code should continue to work just fine and the test suite is even bigger to catch these sorts of regressions. To install on a generic Unixy thing, you should be able to just type % make # to build the executable, and if it works ... % make test # if you have Perl, make and prerequisites, otherwise % 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, now deprecated as of 2.4) and file65, ldo65 and reloc65 for displaying, linking and relocating o65 files in Andre's relocatable format. 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 (but do it from within MSYS2). 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 xa-2.4.0/TODO0000600000031500000010000000125314520616356012130 0ustar spectrestaffo nm65 that prints labels from o65 files 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 (in reloc65) o The listing feature is not bug-free yet: - ca65 and other assembler compatibility pseudo-opcodes will be listed as xa specific ones, not the original in the source E.g. a CA65 ".scope" will appear as ".(" in the listing - The assembler has no pre-processor handling, so pp constants are resolved at parse time. Thus they appear as their value in the listing. - One situation is ".listbytes unlimited", which will show as ".listbytes 0" in the listing xa-2.4.0/attic/0000755000031500000010000000000014524335050012544 5ustar spectrestaffxa-2.4.0/attic/README0000644000031500000010000000030014524335174013424 0ustar spectrestaffThese are files that have been superseded and may be removed in the future. loader/ Rewritten as tests/loader/ doc/ Replaced by man/ (for o65, see http://www.6502.org/users/andre/o65/ ) xa-2.4.0/attic/doc/0000700000031500000010000000000014513025305013274 5ustar spectrestaffxa-2.4.0/attic/doc/README0000644000031500000010000000040514513025305014165 0ustar spectrestaffAs 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 xa-2.4.0/attic/doc/fileformat.txt0000600000031500000010000005755014513025305016203 0ustar spectrestaff 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) xa-2.4.0/attic/doc/xa-de.log0000600000031500000010000000735014513025305015004 0ustar spectrestaff ******** XASS65 1.0 ******** 15.11.89, Andre Fachat 2-Pass-Assembler fr 65(C)02. von Rockwell. Der erste Pass berechnet die Labels, im zweiten Pass wird assembliert. Es wird eine Block-Struktur untersttzt, d.h. die Pseudo-Opcodes .( und .) verbergen dazwischenliegende Labels vor Zugriffen aus anderen als darberliegenden Blocks. Die Quell-, Object- und Fehlerdateien mssen 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 mssen. ******** 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 fr 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 Fr Labels, Defines und die Opcodes wird die Suche nach Hashcode durchgefhrt. damit werden ca. 350kByte Quelltext fr 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 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 untersttzt. Falls die Quell- und Include-Dateien nicht gefunden werden, werden die in XAINPUT aufgefhrten Pfade der Reihe nach durchgetestet. Falls XAOUTPUT existiert, wird dieser Pfad als Pfad fr .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 unterdrckt, 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. xa-2.4.0/attic/doc/xa-de.txt0000600000031500000010000003470614513025305015047 0ustar spectrestaff---------------------------------------------------------------------------- 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, Rcksprungadresse 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 (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 # xa 2.1.4 6502 Cross Assembler

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
xa-2.4.0/attic/doc/xa.log0000600000031500000010000002171214513025305014414 0ustar spectrestaffxa-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 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 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 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 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 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 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 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 21 Dec, 1996 xa-2.1.1a * Embedding absolute code in relocatable seems to work now. -- André Fachat 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 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 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 03 Jan, 1997 xa-2.1.2 * Added ``ld65'', a simple linker for o65 files. * Another bug in xa fixed now. -- André Fachat 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 25 Mar, 1997 xa-2.1.3e * Added preprocessor continuation lines, and .block and .bend pseudo-opcodes (They map to ``.('' and ``.)'' respectively.) -- André Fachat 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 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 30 Dec, 1997 xa-2.1.4d * fixed align code. Now inserts NOP opcodes into text segment, and sets file mode appropriately. -- André Fachat 26 Jan, 1998 xa-2.1.4e * Changed o65 fileformat and adopted it in xa. -- André Fachat 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 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 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 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 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 23 Dec, 2006 xa-2.4.0/attic/doc/xa.txt0000600000031500000010000003521314513025305014453 0ustar spectrestaff _________________________________________________________________ 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 # 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 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+1 lda #HDR_LEN sta p1+3 ldx file lda #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 jsr fgetb bcs no_file ldx file lda #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 xa-2.4.0/attic/loader/rom65.ok0000600000031500000010000000027214520632636015314 0ustar spectrestaff\€o65'€Ň@ filename©€Đ­0Pţ±l0€5€ę­@­©0€(€B4 ‚‚„…‚"B(¸€o65€Ö@ filename©€Đ­ŚPţ±lŚ€‘€ę­@­©Ś€„€B ‚‚„…‚"B„˙˙xa-2.4.0/attic/loader/test.a0000600000031500000010000000047614513025305015127 0ustar spectrestaff .fopt 1, "filename" .( .text &absv = 4 lda #>test+4 bne test *=$8000 ;* lda test-8 .) .text nop ; .fopt 1, "filename" lda bsslab lda zerolab lda #absv*2 .bss bsslab .dsb 20,1 .zero zerolab .dsb 20 xa-2.4.0/attic/loader/test2.a0000600000031500000010000000035614513025305015206 0ustar spectrestaff *=$8000 .( ; .text lda #>test+4 bne test ;*=* lda test-1 .) ; .text nop lda bsslab lda zerolab ; .bss bsslab .dsb 20,1 ; .zero zerolab .dsb 20 xa-2.4.0/attic/loader/test3.a0000600000031500000010000000002214513025305015175 0ustar spectrestaff lda #label lab2 xa-2.4.0/examples/0000700000031500000010000000000014513025305013241 5ustar spectrestaffxa-2.4.0/examples/a.o650000644000031500000010000000432314513025305014030 0ustar spectrestaff  ž2064 Ě˙ Ä “©—  ®©Ô  ®©á  ®®Ň© Í˝©ö  ®©ü  ®©   ®®Ó© Í˝©#  ® ä˙đű˘ÝŹđčŕö°í sLŠ Ş˝€H˝H`1 o ä*pÄÔ…‰†‡ŚŠ‹“ (F1) PACK PROGRAMMS (F2) EXTRACT FROM ARCHIVE (F3) SOURCEPATH/ARC: (F4) SOURCEDEVICE: (F5) TARGETPATH/ARC: (F6) TARGETDEVICE : (F7) SOURCEDIRECTORY (F8) EXCHANGE TARGET AND SOURCE YOUR CHOICE PLEASE ˙ °,©Ť.Ť/ ÉĐ# Ý ű©É  ®­/®. Í˝© Ň˙ _© Ă˙`©±  ®Lˇ UNKNOWN ARCHIVE VERSIONARCHIVE HAD BYTES #©Ť,Ť-© Ň˙ „ű °4¤ű™2ćűÉđ Ň˙Lî ©‹  ® _ÉJЩɠ ®©˙…ü · j ° LŠ ©Ŕ  ®©…ü °1É÷Đ# Ť(Éđ" Ť'$üâ­'  Î(ĐőL5 $üĐ  L5  % © Ă˙©   ®­-®, Í˝© Ň˙(` EXTRACT FILE (Y/N)?GIVES BYTES #î,Đî-` „ąü™đČÉ:đÉ/Đ„Ŕ(馠ą2ťčČÉĐôĘŠ˘  ˝˙©®Ó  ş˙ Ŕ˙°  ` ąÔđČŔ(öŔđ!˘Ô  ˝˙©®Ň  ş˙ Ŕ˙° d ° j `8` § ­$đ, Đ °©  ©…ű Ň…ý†ţ j ćűĄűÍ$í % © Ă˙ j L`Ą`©Ż  ® „ü±ý Ň˙  ¤üČÉĐď ą ° — ° v LŚ ť © Ă˙©÷  ©  © Ň˙` cOPYING  „ąÔ™đČÉ:đÉ/Đ„Ŕ(馠±ýťčČÉĐőĘŠ˘  ˝˙©®Ň  ş˙ Ŕ˙° j `î.Đî/`¬*Ě)đą,î*`­+đ8`©Ť)Ť*˘ Ć˙©… Ď˙HĄđ©L Ň˙¦© Í˝© Ň˙h ¬)™,ČŚ)ČđĄđŇĄŤ+ Ě˙L ©Ť)Ť*Ť+`®(đčĐH ť hL Í'đH ť hŤ'î(`©Ť(`­(đ-ɰ­'É÷đ ­'  Î(Đő`©÷  ­(  ­'  ©Ť(` ąüđČŔ(öŔđ$˘ü  ˝˙©®Ó  ş˙ Ŕ˙° ­Ó j °  `8`©Ť%Ť&`¬%™'ČŚ%ČĚ&ĐH % h`˘ É˙¬&Ě%đ&ą' Ň˙ĄđH©W çĄ @ ç© çh¨ ® ČL- ©Ť%Ť& Ě˙`­ŇLm ­ÓH Ě˙© Ň˙h ´˙©o –˙©… Ą˙H Ň˙ Ą˙Éđ Ň˙Ąđň «˙hÉ0Đ`8`L€©Ť$©“ Ň˙ e ŐóĄş ´˙Ąą –˙©… „ű Ą˙…ü¤ĐŇ Ą˙ĆűĐđ¦ü Í˝© Ň˙ Ą˙ÉđşÉĐL\ Ň˙É"Đë­$ Ň…ý†ţ „ű Ą˙ Ň˙¤űÉ"đ‘ýČŔë©,‘ýČ„ű Ą˙ Ň˙¤űÉ đň…ü‘ýČ©‘ýŞ Ą˙ Ň˙É Đőŕ<đ© Ň˙© Ň˙Ąü † Ą˙ÉĐůđ Ą˙¦ĐŞđ Ň˙L\© Ň˙ ä˙đ _ đLÇ BöL_ÉPđÉSđ`©°  ® _ÉJđ©Ŕ  ®`©É  ®î$`YES/NO ťťťťťťť’NO ’YES ˘† & &…¦ & &e…Še…©2e…H©e…Şh`©“ Ň˙ e ŐóĄş ´˙Ąą –˙©… „ű Ą˙…ü¤Đ2 Ą˙ĆűĐđ¦ü Í˝© Ň˙ Ą˙¦ĐŞđ Ň˙L8© Ň˙ ä˙đ _ ĐĂ BöL_ ä˙đű`©$Ť˘† ąÔđ É:đ ČŔ(ň©:ťč ąÔťđÉ:đÉ/ІčČŔ(č¦č©*ťč©.ťč©*ť芢  ˝˙©®Ň Lş˙îŇ­ŇÉ ©ŤŇ`îÓ­ÓÉ ©ŤÓ`©  ® `Ą ą™Ôđ ČŔ'ó©™Ô` PLEASE INPUT NEW SOURCEPATH/ARCHIVE: ©J  ® `Ą ą™üđ ČŔ'ó©™ü` PLEASE INPUT NEW TARGETPATH/ARCHIVE: ­Ň®ÓŽŇŤÓ˘˝ÔH˝üťÔhťüčŕ(í`©ŤÔŤüĄşÉÉ ©ŤŇŤÓ`…"„# ±"đ Ň˙ć"Đóć#Đď`©Ť ĐŤ!Đ©™ Ň˙`xa-2.4.0/examples/c64def.def0000600000031500000010000001724514513025305015007 0ustar spectrestaff /* 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 xa-2.4.0/examples/pack.doc0000600000031500000010000000105114513025305014645 0ustar spectrestaff ******** pack 1.0 ******** 11.10.92, A.Fachat Dieses Programm fr 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. xa-2.4.0/examples/pack_eng.a650000600000031500000010000004722614513025305015342 0ustar spectrestaff #include "c64def.def" #define Tout(a) .(:lda #a:jsr Txtout:.) #define Aout(a) .(:lda #b:jsr Txtout:jmp c:b .byt a,0:c .) #define Ibout(a) .(:ldx a:lda #0:jsr INTOUT:.) #define Iout(a) .(:ldx a:lda a+1:jsr INTOUT:.) #define PFADLEN 40 #define FN_WR 3 #define FN_RD 4 #define XCODE $f7 #define Version 1 .( .word $0801 *=$0801 .word basicend,10 .byt $9e,"2064",0 ;sys $0810 basicend .word 0 .byt 0,0,0 .( jsr CLRCH jsr iniscreen jsr inipar menu1 Tout(m1atxt) Tout(quellpfad) Tout(m1btxt) Ibout(quelldrv) Tout(m1ctxt) Tout(zielpfad) Tout(m1dtxt) Ibout(zieldrv) Tout(m1etxt) next jsr GET beq next ldx #0 l1 cmp befkeys,x beq exe inx cpx #Anzbefs bcc l1 bcs next exe jsr exec jmp menu1 exec txa asl tax lda madr+1,x pha lda madr,x pha rts madr .word pack-1,unpack-1,quelle-1,ziel-1,switch-1,dir-1,qdrv-1,zdrv-1 befkeys .asc TC_F1,TC_F2,TC_F3,TC_F5,TC_F8,TC_F7,TC_F4,TC_F6 Anzbefs =8 m1atxt .asc TC_LCH,TC_SCO,TC_FF,TC_LF,TC_LF .asc "(F1) PACK PROGRAMMS",TC_CR,TC_LF .asc "(F2) EXTRACT FROM ARCHIVE",TC_CR,TC_LF .asc "(F3) SOURCEPATH/ARC:",0 m1btxt .asc TC_CR,TC_LF .asc "(F4) SOURCEDEVICE:",0 m1ctxt .asc TC_CR,TC_LF .asc "(F5) TARGETPATH/ARC:",0 m1dtxt .asc TC_CR,TC_LF .asc "(F6) TARGETDEVICE :",0 m1etxt .asc TC_CR,TC_LF .asc "(F7) SOURCEDIRECTORY",TC_CR,TC_LF .asc "(F8) EXCHANGE TARGET AND SOURCE",TC_CR,TC_LF .asc "YOUR CHOICE PLEASE",TC_CR,0 .) unpack .( jsr openarcrd bcs cls lda #0 sta rcnt sta rcnt+1 jsr rbyte cmp #Version bne verr loop jsr unpackfile bcc loop Tout(t1) lda rcnt+1 ldx rcnt jsr INTOUT lda #TC_CR jsr BSOUT jsr waitkey cls lda #FN_RD jsr CLOSE rts verr Tout(verrtxt) jmp cls verrtxt .asc "UNKNOWN ARCHIVE VERSION",0 t1 .asc "ARCHIVE HAD BYTES #",0 .) unpackfile .( lda #0 sta wcnt sta wcnt+1 lda #TC_CR jsr BSOUT ldy #0 sty P1 l1 jsr rbyte bcs endx ldy P1 sta filetab,y inc P1 cmp #0 beq endnam jsr BSOUT jmp l1 endnam Tout(ask) jsr waitkey cmp #"J" bne nounpack Tout(tok) lda #<-1 sta P1+1 jsr fxopen jsr Getzst bcs xa bcc lo endx jmp end nounpack Tout(tno) xa lda #0 sta P1+1 lo jsr rbyte bcs cls cmp #XCODE bne xb jsr rbyte sta wxanz cmp #0 clc beq cls jsr rbyte sta wxbyt bit P1+1 bpl lo ly lda wxbyt jsr wbyte dec wxanz bne ly jmp lo xb bit P1+1 bpl lo jsr wbyte jmp lo cls php jsr wbuf lda #FN_WR jsr CLOSE Tout(t1) lda wcnt+1 ldx wcnt jsr INTOUT lda #TC_CR jsr BSOUT plp end rts ask .asc TC_CR,"EXTRACT FILE (Y/N)?",0 t1 .asc "GIVES BYTES #",0 .) incwcnt .( inc wcnt bne l1 inc wcnt+1 l1 rts .) fxopen .( ldy #0 sty INT l1 lda zielpfad,y sta INBUF,y beq l2 iny cmp #":" beq l1a cmp #"/" bne l1b l1a sty INT l1b cpy #PFADLEN bcc l1 l2 ldx INT ldy #0 l3 lda filetab,y sta INBUF,x inx iny cmp #0 bne l3 dex txa ldx #INBUF jsr SETFNPAR lda #FN_WR ldx zieldrv ldy #1 jsr SETFPAR jsr OPEN bcs err jsr clrwrbuf clc err rts .) openarcrd .( ldy #0 l0 lda quellpfad,y beq l1 iny cpy #PFADLEN bcc l0 l1 cpy #0 beq err tya ldx #quellpfad jsr SETFNPAR lda #FN_RD ldx quelldrv ldy #0 jsr SETFPAR jsr OPEN bcs err jsr Getqst bcs err jsr clrrdbuf clc rts err sec rts .) pack .( jsr getlist lda anzfiles beq end jsr openarcwr bcs cls lda #Version jsr wbyte lda #0 sta P1 l1 jsr setfadr sta P2 stx P2+1 jsr packfile inc P1 lda P1 cmp anzfiles bcc l1 jsr wbuf cls lda #FN_WR jsr CLOSE jsr Getzst end jmp LINEIN:rts .) packfile .( Tout(lft) ldy #0 l1 sty P1+1 lda (P2),y jsr BSOUT jsr wbyte ldy P1+1 iny cmp #0 bne l1 jsr fopen bcs le jsr clrwxbyt l2 jsr rbyte bcs l3 jsr wxbyte jmp l2 l3 jsr savwxbyt le lda #FN_RD jsr CLOSE lda #XCODE jsr wbyte lda #0 jsr wbyte lda #TC_CR jsr BSOUT rts lft .asc TC_CR,"cOPYING ",0 .) fopen .( ldy #0 sty INT l1 lda quellpfad,y sta INBUF,y beq l2 iny cmp #":" beq l1a cmp #"/" bne l1b l1a sty INT l1b cpy #PFADLEN bcc l1 l2 ldx INT ldy #0 l3 lda (P2),y sta INBUF,x inx iny cmp #0 bne l3 dex txa ldx #INBUF jsr SETFNPAR lda #FN_RD ldx quelldrv ldy #0 jsr SETFPAR jsr OPEN bcs err jsr clrrdbuf clc err rts .) incrcnt .( inc rcnt bne l1 inc rcnt+1 l1 rts .) rbyte .( ldy ro cpy ri beq leerbuf lda rb,y inc ro clc rts leerbuf lda rf beq ldbuf sec rts ldbuf lda #0 sta ri sta ro ldx #FN_RD jsr CHKIN lda #0 sta STATUS lok jsr BASIN pha lda STATUS beq l0 lda #"L" jsr BSOUT Ibout($90) lda #TC_CR jsr BSOUT l0 pla jsr incrcnt ldy ri sta rb,y iny sty ri iny ;cpy ro beq le lda STATUS beq lok le lda STATUS sta rf jsr CLRCH jmp rbyte .) clrrdbuf .( lda #0 sta ri sta ro sta rf rts .) wxbyte .( ldx wxanz beq add inx bne ad2 pha jsr savwxbyt pla jmp add ad2 cmp wxbyt beq adx pha jsr savwxbyt pla add sta wxbyt adx inc wxanz rts .) clrwxbyt .( lda #0 sta wxanz rts .) savwxbyt .( lda wxanz beq nosav cmp #4 bcs savs lda wxbyt cmp #XCODE beq savs l1 lda wxbyt jsr wbyte dec wxanz bne l1 rts savs lda #XCODE jsr wbyte lda wxanz jsr wbyte lda wxbyt jsr wbyte lda #0 sta wxanz nosav rts .) openarcwr .( ldy #0 l0 lda zielpfad,y beq l1 iny cpy #PFADLEN bcc l0 l1 cpy #0 beq err tya ldx #zielpfad jsr SETFNPAR lda #FN_WR ldx zieldrv ldy #1 jsr SETFPAR jsr OPEN bcs err lda zieldrv jsr Getzst bcs err jsr clrwrbuf clc rts err sec rts .) clrwrbuf .( lda #0 sta wi sta wo rts .) wbyte .( ldy wi sta wb,y iny sty wi iny cpy wo bne nowr pha jsr wbuf pla nowr rts .) wbuf .( ldx #FN_WR jsr CKOUT ldy wo l1 cpy wi beq end lda wb,y jsr BSOUT lda STATUS beq l0 tya pha lda #"W" jsr $e716 lda $90 ora #$40 jsr $e716 lda #TC_CR jsr $e716 pla tay l0 jsr incwcnt iny jmp l1 end lda #0 sta wi sta wo jsr CLRCH rts .) .( &Getqst lda quelldrv jmp Getst &Getzst lda zieldrv &Getst pha jsr CLRCH lda #TC_CR jsr BSOUT pla jsr TALK lda #15+$60 jsr SECTALK lda #0 sta STATUS jsr IECIN pha jsr BSOUT l1 jsr IECIN cmp #0 beq l2 jsr BSOUT lda STATUS beq l1 l2 jsr UNTALK pla cmp #"0" bne err clc rts err sec rts .) /* showlist .( lda #0 sta P1 l1 lda P1 cmp anzfiles bcs le jsr setfadr lda #TC_CR jsr BSOUT lda INT ldy INT+1 jsr Txtout inc P1 jmp l1 le rts .) */ .( l4x jmp l4 &getlist lda #0 sta anzfiles lda #TC_FF jsr BSOUT jsr setdirnam jsr SENDNAM lda DEVADR jsr TALK lda SECADR jsr SECTALK lda #0 sta STATUS ldy #3 l0 sty P1 l1 jsr IECIN sta P1+1 ldy STATUS bne l4x jsr IECIN dec P1 bne l1 ldx P1+1 jsr INTOUT lda #" " jsr BSOUT la jsr IECIN cmp #0 beq l4x cmp #TC_REV bne l3x jmp l3 l3x jsr BSOUT cmp #34 bne la lda anzfiles jsr setfadr sta P2 stx P2+1 ldy #0 lb sty P1 jsr IECIN jsr BSOUT ldy P1 cmp #34 beq lc sta (P2),y iny cpy #17 bcc lb lc lda #"," sta (P2),y iny ld sty P1 jsr IECIN jsr BSOUT ldy P1 cmp #" " beq ld sta P1+1 sta (P2),y iny lda #0 sta (P2),y /* lda #TC_CR jsr BSOUT lda P2+1 ldx P2 jsr INTOUT lda #":" jsr BSOUT lda P2 ldy P2+1 jsr Txtout */ lf tax jsr IECIN jsr BSOUT cmp #" " bne lf cpx #"<" beq lg lda #" " jsr BSOUT lg lda #" " jsr BSOUT lda P1+1 jsr testkeys lh jsr IECIN cmp #0 bne lh beq l2 l3 jsr IECIN ldx STATUS bne l4 tax beq l2 jsr BSOUT jmp l3 l2 lda #TC_CR jsr BSOUT jsr GET beq l5 jsr waitkey l5 ldy #2 beq l4 jmp l0 l4 jsr CLSFIL jmp waitkey .) testkeys .( cmp #"P" beq ok cmp #"S" beq ok rts ok Tout(t1) jsr waitkey cmp #"J" beq ja Tout(tno) rts ja Tout(tok) inc anzfiles rts t1 .asc TC_REV,"YES/NO ",TC_CRL,TC_CRL,TC_CRL .asc TC_CRL,TC_CRL,TC_CRL,TC_CRL,0 &tno .asc TC_REO,"NO ",0 &tok .asc TC_REO,"YES ",0 .) setfadr .( ldx #0 stx INT+1 asl rol INT+1 asl rol INT+1 sta INT ldx INT+1 asl rol INT+1 asl rol INT+1 clc adc INT sta INT txa adc INT+1 sta INT+1 lda #filetab adc INT+1 sta INT+1 tax pla rts .) dir .( lda #TC_FF jsr BSOUT jsr setdirnam jsr SENDNAM lda DEVADR jsr TALK lda SECADR jsr SECTALK lda #0 sta STATUS ldy #3 l0 sty P1 l1 jsr IECIN sta P1+1 ldy STATUS bne l4 jsr IECIN dec P1 bne l1 ldx P1+1 jsr INTOUT lda #" " jsr BSOUT l3 jsr IECIN ldx STATUS bne l4 tax beq l2 jsr BSOUT jmp l3 l2 lda #TC_CR jsr BSOUT jsr GET beq l5 jsr waitkey l5 ldy #2 bne l0 l4 jsr CLSFIL jmp waitkey .) waitkey jsr GET beq waitkey rts setdirnam .( p1 =INT lda #"$" sta INBUF ldx #1 stx p1 ldy #0 l1 lda quellpfad,y beq nodp cmp #":" beq dp iny cpy #PFADLEN bcc l1 nodp lda #":" sta INBUF,x inx dp ldy #0 dp1 lda quellpfad,y sta INBUF,x beq end cmp #":" beq l2a cmp #"/" bne l2 l2a stx p1 l2 inx iny cpy #PFADLEN bcc dp1 end ldx p1 inx lda #"*" sta INBUF,x inx lda #"." sta INBUF,x inx lda #"*" sta INBUF,x inx txa ldx #INBUF jsr SETFNPAR lda #1 ldx quelldrv ldy #0 jmp SETFPAR .) qdrv .( inc quelldrv lda quelldrv cmp #12 bcc ok lda #8 sta quelldrv ok rts .) zdrv .( inc zieldrv lda zieldrv cmp #12 bcc ok lda #8 sta zieldrv ok rts .) quelle .( Tout(quelltxt) jsr LINEIN ldy #0 q1 lda INBUF,y sta quellpfad,y beq end iny cpy #PFADLEN-1 bcc q1 lda #0 sta quellpfad,y end rts quelltxt .asc TC_CR,"PLEASE INPUT NEW SOURCEPATH/ARCHIVE:",TC_CR,0 .) ziel .( Tout(quelltxt) jsr LINEIN ldy #0 q1 lda INBUF,y sta zielpfad,y beq end iny cpy #PFADLEN-1 bcc q1 lda #0 sta zielpfad,y end rts quelltxt .asc TC_CR,"PLEASE INPUT NEW TARGETPATH/ARCHIVE:",TC_CR,0 .) switch .( lda quelldrv ldx zieldrv stx quelldrv sta zieldrv ldx #0 l1 lda quellpfad,x pha lda zielpfad,x sta quellpfad,x pla sta zielpfad,x inx cpx #PFADLEN bcc l1 rts .) inipar .( lda #0 sta quellpfad sta zielpfad lda DEVADR cmp #8 bcc noval cmp #12 bcc ok noval lda #8 ok sta quelldrv sta zieldrv rts .) Txtout .( p =$22 sta p sty p+1 l1 ldy #0 lda (p),y beq le jsr BSOUT inc p bne l1 inc p+1 bne l1 le rts .) iniscreen .( lda #COL_SCHWARZ sta VIC+VIC_EXTCOL sta VIC+VIC_BCKCOL0 lda #TC_HELLGRUEN jsr BSOUT rts .) sysmem =* quelldrv =sysmem zieldrv =sysmem+1 -sysmem +=2 quellpfad =sysmem zielpfad =sysmem+PFADLEN -sysmem +=2*PFADLEN anzfiles =sysmem -sysmem +=1 wi =sysmem wo =sysmem+1 -sysmem +=2 wb =sysmem -sysmem +=256 wxbyt =sysmem wxanz =sysmem+1 -sysmem +=2 ri =sysmem ro =sysmem+1 rf =sysmem+2 -sysmem +=3 rb =sysmem -sysmem +=256 wcnt =sysmem -sysmem +=2 rcnt =sysmem -sysmem +=2 ecnt =sysmem -sysmem +=2 filetab =sysmem ende .) xa-2.4.0/examples/pack_ger.a650000600000031500000010000004721014513025305015337 0ustar spectrestaff #include "c64def.def" #define Tout(a) .(:lda #a:jsr Txtout:.) #define Aout(a) .(:lda #b:jsr Txtout:jmp c:b .byt a,0:c .) #define Ibout(a) .(:ldx a:lda #0:jsr INTOUT:.) #define Iout(a) .(:ldx a:lda a+1:jsr INTOUT:.) #define PFADLEN 40 #define FN_WR 3 #define FN_RD 4 #define XCODE $f7 #define Version 1 .( .word $0801 *=$0801 .word basicend,10 .byt $9e,"2064",0 ;sys $0810 basicend .word 0 .byt 0,0,0 .( jsr CLRCH jsr iniscreen jsr inipar menu1 Tout(m1atxt) Tout(quellpfad) Tout(m1btxt) Ibout(quelldrv) Tout(m1ctxt) Tout(zielpfad) Tout(m1dtxt) Ibout(zieldrv) Tout(m1etxt) next jsr GET beq next ldx #0 l1 cmp befkeys,x beq exe inx cpx #Anzbefs bcc l1 bcs next exe jsr exec jmp menu1 exec txa asl tax lda madr+1,x pha lda madr,x pha rts madr .word pack-1,unpack-1,quelle-1,ziel-1,switch-1,dir-1,qdrv-1,zdrv-1 befkeys .asc TC_F1,TC_F2,TC_F3,TC_F5,TC_F8,TC_F7,TC_F4,TC_F6 Anzbefs =8 m1atxt .asc TC_LCH,TC_SCO,TC_FF,TC_LF,TC_LF .asc "(F1) PROGRAMME ZUSAMMENPACKEN",TC_CR,TC_LF .asc "(F2) ARCHIV AUSPACKEN",TC_CR,TC_LF .asc "(F3) QUELLPFAD:",0 m1btxt .asc TC_CR,TC_LF .asc "(F4) QUELLDEVICE:",0 m1ctxt .asc TC_CR,TC_LF .asc "(F5) ZIELPFAD :",0 m1dtxt .asc TC_CR,TC_LF .asc "(F6) ZIELDEVICE :",0 m1etxt .asc TC_CR,TC_LF .asc "(F7) QUELLDIRECTORY",TC_CR,TC_LF .asc "(F8) QUELLE UND ZIEL TAUSCHEN",TC_CR,TC_LF .asc "IHRE EINGABE BITTE",TC_CR,0 .) unpack .( jsr openarcrd bcs cls lda #0 sta rcnt sta rcnt+1 jsr rbyte cmp #Version bne verr loop jsr unpackfile bcc loop Tout(t1) lda rcnt+1 ldx rcnt jsr INTOUT lda #TC_CR jsr BSOUT jsr waitkey cls lda #FN_RD jsr CLOSE rts verr Tout(verrtxt) jmp cls verrtxt .asc "UNGUELTIGE ARCHIV-VERSION",0 t1 .asc "ARCHIV HATTE BYTES #",0 .) unpackfile .( lda #0 sta wcnt sta wcnt+1 lda #TC_CR jsr BSOUT ldy #0 sty P1 l1 jsr rbyte bcs endx ldy P1 sta filetab,y inc P1 cmp #0 beq endnam jsr BSOUT jmp l1 endnam Tout(ask) jsr waitkey cmp #"J" bne nounpack Tout(tok) lda #<-1 sta P1+1 jsr fxopen jsr Getzst bcs xa bcc lo endx jmp end nounpack Tout(tno) xa lda #0 sta P1+1 lo jsr rbyte bcs cls cmp #XCODE bne xb jsr rbyte sta wxanz cmp #0 clc beq cls jsr rbyte sta wxbyt bit P1+1 bpl lo ly lda wxbyt jsr wbyte dec wxanz bne ly jmp lo xb bit P1+1 bpl lo jsr wbyte jmp lo cls php jsr wbuf lda #FN_WR jsr CLOSE Tout(t1) lda wcnt+1 ldx wcnt jsr INTOUT lda #TC_CR jsr BSOUT plp end rts ask .asc TC_CR,"DATEI AUSPACKEN (J/N)?",0 t1 .asc "ERGIBT BYTES #",0 .) incwcnt .( inc wcnt bne l1 inc wcnt+1 l1 rts .) fxopen .( ldy #0 sty INT l1 lda zielpfad,y sta INBUF,y beq l2 iny cmp #":" beq l1a cmp #"/" bne l1b l1a sty INT l1b cpy #PFADLEN bcc l1 l2 ldx INT ldy #0 l3 lda filetab,y sta INBUF,x inx iny cmp #0 bne l3 dex txa ldx #INBUF jsr SETFNPAR lda #FN_WR ldx zieldrv ldy #1 jsr SETFPAR jsr OPEN bcs err jsr clrwrbuf clc err rts .) openarcrd .( ldy #0 l0 lda quellpfad,y beq l1 iny cpy #PFADLEN bcc l0 l1 cpy #0 beq err tya ldx #quellpfad jsr SETFNPAR lda #FN_RD ldx quelldrv ldy #0 jsr SETFPAR jsr OPEN bcs err jsr Getqst bcs err jsr clrrdbuf clc rts err sec rts .) pack .( jsr getlist lda anzfiles beq end jsr openarcwr bcs cls lda #Version jsr wbyte lda #0 sta P1 l1 jsr setfadr sta P2 stx P2+1 jsr packfile inc P1 lda P1 cmp anzfiles bcc l1 jsr wbuf cls lda #FN_WR jsr CLOSE jsr Getzst end jmp LINEIN:rts .) packfile .( Tout(lft) ldy #0 l1 sty P1+1 lda (P2),y jsr BSOUT jsr wbyte ldy P1+1 iny cmp #0 bne l1 jsr fopen bcs le jsr clrwxbyt l2 jsr rbyte bcs l3 jsr wxbyte jmp l2 l3 jsr savwxbyt le lda #FN_RD jsr CLOSE lda #XCODE jsr wbyte lda #0 jsr wbyte lda #TC_CR jsr BSOUT rts lft .asc TC_CR,"cOPYING ",0 .) fopen .( ldy #0 sty INT l1 lda quellpfad,y sta INBUF,y beq l2 iny cmp #":" beq l1a cmp #"/" bne l1b l1a sty INT l1b cpy #PFADLEN bcc l1 l2 ldx INT ldy #0 l3 lda (P2),y sta INBUF,x inx iny cmp #0 bne l3 dex txa ldx #INBUF jsr SETFNPAR lda #FN_RD ldx quelldrv ldy #0 jsr SETFPAR jsr OPEN bcs err jsr clrrdbuf clc err rts .) incrcnt .( inc rcnt bne l1 inc rcnt+1 l1 rts .) rbyte .( ldy ro cpy ri beq leerbuf lda rb,y inc ro clc rts leerbuf lda rf beq ldbuf sec rts ldbuf lda #0 sta ri sta ro ldx #FN_RD jsr CHKIN lda #0 sta STATUS lok jsr BASIN pha lda STATUS beq l0 lda #"L" jsr BSOUT Ibout($90) lda #TC_CR jsr BSOUT l0 pla jsr incrcnt ldy ri sta rb,y iny sty ri iny ;cpy ro beq le lda STATUS beq lok le lda STATUS sta rf jsr CLRCH jmp rbyte .) clrrdbuf .( lda #0 sta ri sta ro sta rf rts .) wxbyte .( ldx wxanz beq add inx bne ad2 pha jsr savwxbyt pla jmp add ad2 cmp wxbyt beq adx pha jsr savwxbyt pla add sta wxbyt adx inc wxanz rts .) clrwxbyt .( lda #0 sta wxanz rts .) savwxbyt .( lda wxanz beq nosav cmp #4 bcs savs lda wxbyt cmp #XCODE beq savs l1 lda wxbyt jsr wbyte dec wxanz bne l1 rts savs lda #XCODE jsr wbyte lda wxanz jsr wbyte lda wxbyt jsr wbyte lda #0 sta wxanz nosav rts .) openarcwr .( ldy #0 l0 lda zielpfad,y beq l1 iny cpy #PFADLEN bcc l0 l1 cpy #0 beq err tya ldx #zielpfad jsr SETFNPAR lda #FN_WR ldx zieldrv ldy #1 jsr SETFPAR jsr OPEN bcs err lda zieldrv jsr Getzst bcs err jsr clrwrbuf clc rts err sec rts .) clrwrbuf .( lda #0 sta wi sta wo rts .) wbyte .( ldy wi sta wb,y iny sty wi iny cpy wo bne nowr pha jsr wbuf pla nowr rts .) wbuf .( ldx #FN_WR jsr CKOUT ldy wo l1 cpy wi beq end lda wb,y jsr BSOUT lda STATUS beq l0 tya pha lda #"W" jsr $e716 lda $90 ora #$40 jsr $e716 lda #TC_CR jsr $e716 pla tay l0 jsr incwcnt iny jmp l1 end lda #0 sta wi sta wo jsr CLRCH rts .) .( &Getqst lda quelldrv jmp Getst &Getzst lda zieldrv &Getst pha jsr CLRCH lda #TC_CR jsr BSOUT pla jsr TALK lda #15+$60 jsr SECTALK lda #0 sta STATUS jsr IECIN pha jsr BSOUT l1 jsr IECIN cmp #0 beq l2 jsr BSOUT lda STATUS beq l1 l2 jsr UNTALK pla cmp #"0" bne err clc rts err sec rts .) /* showlist .( lda #0 sta P1 l1 lda P1 cmp anzfiles bcs le jsr setfadr lda #TC_CR jsr BSOUT lda INT ldy INT+1 jsr Txtout inc P1 jmp l1 le rts .) */ .( l4x jmp l4 &getlist lda #0 sta anzfiles lda #TC_FF jsr BSOUT jsr setdirnam jsr SENDNAM lda DEVADR jsr TALK lda SECADR jsr SECTALK lda #0 sta STATUS ldy #3 l0 sty P1 l1 jsr IECIN sta P1+1 ldy STATUS bne l4x jsr IECIN dec P1 bne l1 ldx P1+1 jsr INTOUT lda #" " jsr BSOUT la jsr IECIN cmp #0 beq l4x cmp #TC_REV bne l3x jmp l3 l3x jsr BSOUT cmp #34 bne la lda anzfiles jsr setfadr sta P2 stx P2+1 ldy #0 lb sty P1 jsr IECIN jsr BSOUT ldy P1 cmp #34 beq lc sta (P2),y iny cpy #17 bcc lb lc lda #"," sta (P2),y iny ld sty P1 jsr IECIN jsr BSOUT ldy P1 cmp #" " beq ld sta P1+1 sta (P2),y iny lda #0 sta (P2),y /* lda #TC_CR jsr BSOUT lda P2+1 ldx P2 jsr INTOUT lda #":" jsr BSOUT lda P2 ldy P2+1 jsr Txtout */ lf tax jsr IECIN jsr BSOUT cmp #" " bne lf cpx #"<" beq lg lda #" " jsr BSOUT lg lda #" " jsr BSOUT lda P1+1 jsr testkeys lh jsr IECIN cmp #0 bne lh beq l2 l3 jsr IECIN ldx STATUS bne l4 tax beq l2 jsr BSOUT jmp l3 l2 lda #TC_CR jsr BSOUT jsr GET beq l5 jsr waitkey l5 ldy #2 beq l4 jmp l0 l4 jsr CLSFIL jmp waitkey .) testkeys .( cmp #"P" beq ok cmp #"S" beq ok rts ok Tout(t1) jsr waitkey cmp #"J" beq ja Tout(tno) rts ja Tout(tok) inc anzfiles rts t1 .asc TC_REV,"JA/NEIN",TC_CRL,TC_CRL,TC_CRL .asc TC_CRL,TC_CRL,TC_CRL,TC_CRL,0 &tno .asc TC_REO,"NEIN ",0 &tok .asc TC_REO,"JA ",0 .) setfadr .( ldx #0 stx INT+1 asl rol INT+1 asl rol INT+1 sta INT ldx INT+1 asl rol INT+1 asl rol INT+1 clc adc INT sta INT txa adc INT+1 sta INT+1 lda #filetab adc INT+1 sta INT+1 tax pla rts .) dir .( lda #TC_FF jsr BSOUT jsr setdirnam jsr SENDNAM lda DEVADR jsr TALK lda SECADR jsr SECTALK lda #0 sta STATUS ldy #3 l0 sty P1 l1 jsr IECIN sta P1+1 ldy STATUS bne l4 jsr IECIN dec P1 bne l1 ldx P1+1 jsr INTOUT lda #" " jsr BSOUT l3 jsr IECIN ldx STATUS bne l4 tax beq l2 jsr BSOUT jmp l3 l2 lda #TC_CR jsr BSOUT jsr GET beq l5 jsr waitkey l5 ldy #2 bne l0 l4 jsr CLSFIL jmp waitkey .) waitkey jsr GET beq waitkey rts setdirnam .( p1 =INT lda #"$" sta INBUF ldx #1 stx p1 ldy #0 l1 lda quellpfad,y beq nodp cmp #":" beq dp iny cpy #PFADLEN bcc l1 nodp lda #":" sta INBUF,x inx dp ldy #0 dp1 lda quellpfad,y sta INBUF,x beq end cmp #":" beq l2a cmp #"/" bne l2 l2a stx p1 l2 inx iny cpy #PFADLEN bcc dp1 end ldx p1 inx lda #"*" sta INBUF,x inx lda #"." sta INBUF,x inx lda #"*" sta INBUF,x inx txa ldx #INBUF jsr SETFNPAR lda #1 ldx quelldrv ldy #0 jmp SETFPAR .) qdrv .( inc quelldrv lda quelldrv cmp #12 bcc ok lda #8 sta quelldrv ok rts .) zdrv .( inc zieldrv lda zieldrv cmp #12 bcc ok lda #8 sta zieldrv ok rts .) quelle .( Tout(quelltxt) jsr LINEIN ldy #0 q1 lda INBUF,y sta quellpfad,y beq end iny cpy #PFADLEN-1 bcc q1 lda #0 sta quellpfad,y end rts quelltxt .asc TC_CR,"BITTE NEUEN QUELLPFAD EINGEBEN:",TC_CR,0 .) ziel .( Tout(quelltxt) jsr LINEIN ldy #0 q1 lda INBUF,y sta zielpfad,y beq end iny cpy #PFADLEN-1 bcc q1 lda #0 sta zielpfad,y end rts quelltxt .asc TC_CR,"BITTE NEUEN ZIELPFAD EINGEBEN:",TC_CR,0 .) switch .( lda quelldrv ldx zieldrv stx quelldrv sta zieldrv ldx #0 l1 lda quellpfad,x pha lda zielpfad,x sta quellpfad,x pla sta zielpfad,x inx cpx #PFADLEN bcc l1 rts .) inipar .( lda #0 sta quellpfad sta zielpfad lda DEVADR cmp #8 bcc noval cmp #12 bcc ok noval lda #8 ok sta quelldrv sta zieldrv rts .) Txtout .( p =$22 sta p sty p+1 l1 ldy #0 lda (p),y beq le jsr BSOUT inc p bne l1 inc p+1 bne l1 le rts .) iniscreen .( lda #COL_SCHWARZ sta VIC+VIC_EXTCOL sta VIC+VIC_BCKCOL0 lda #TC_HELLGRUEN jsr BSOUT rts .) sysmem =* quelldrv =sysmem zieldrv =sysmem+1 -sysmem +=2 quellpfad =sysmem zielpfad =sysmem+PFADLEN -sysmem +=2*PFADLEN anzfiles =sysmem -sysmem +=1 wi =sysmem wo =sysmem+1 -sysmem +=2 wb =sysmem -sysmem +=256 wxbyt =sysmem wxanz =sysmem+1 -sysmem +=2 ri =sysmem ro =sysmem+1 rf =sysmem+2 -sysmem +=3 rb =sysmem -sysmem +=256 wcnt =sysmem -sysmem +=2 rcnt =sysmem -sysmem +=2 ecnt =sysmem -sysmem +=2 filetab =sysmem ende .) xa-2.4.0/examples/peng.l0000644000031500000010000001046614513025305014370 0ustar spectrestaffbasicend, 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 xa-2.4.0/man/0000755000031500000010000000000014520360011012202 5ustar spectrestaffxa-2.4.0/man/README0000644000031500000010000000011514524335752013101 0ustar spectrestaffAlso look at ../attic/doc/ for previous documentation files. Cameron Kaiser xa-2.4.0/man/file65.10000644000031500000010000000237214526073155013402 0ustar spectrestaff.TH FILE65 "1" "18 November 2023" .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 \-vv Print undefined and global labels, and relocation tables. .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 and Cameron Kaiser . Original xa package (C)1989-1997 Andre Fachat. Additional changes (C)1989-2023 Andre Fachat, Jolse Maginnis, David Weinehall and Cameron Kaiser. The current maintainer is Cameron Kaiser. .SH WEBSITE http://www.floodgap.com/retrotech/xa/ xa-2.4.0/man/ldo65.10000644000031500000010000000273214526073162013237 0ustar spectrestaff.TH LDO65 "1" "18 November 2023" .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 \-L name Allow label .B name to remain undefined, even after linking. This option may be specified multiple times for multiple labels. .TP .B \-U Allow any label to remain undefined, even after linking. .TP .B \-G Suppress writing of globals. .TP .B \-g name Only export global .BR name . This option may be specified multiple times for multiple 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 and Cameron Kaiser . Original xa package (C)1989-1997 Andre Fachat. Additional changes (C)1989-2023 Andre Fachat, Jolse Maginnis, David Weinehall and Cameron Kaiser. The current maintainer is Cameron Kaiser. .SH WEBSITE http://www.floodgap.com/retrotech/xa/ xa-2.4.0/man/printcbm.10000644000031500000010000000163014524323501014111 0ustar spectrestaff.TH PRINTCBM "1" "DEPRECATED" .SH NAME printcbm \- list a Commodore BASIC file (DEPRECATED) .SH NOTICE As of .B xa 2.4, .B printcbm is deprecated and will be removed in a future version. Please consider migrating your usage to VICE .BR petcat(1) , which has many more options. .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 . Original xa package (C)1989-1997 Andre Fachat. Additional changes (C)1989-2023 Andre Fachat, Jolse Maginnis, David Weinehall and Cameron Kaiser. The current maintainer is Cameron Kaiser. .SH WEBSITE http://www.floodgap.com/retrotech/xa/ xa-2.4.0/man/reloc65.10000644000031500000010000000300614526073171013560 0ustar spectrestaff.TH RELOC65 "1" "18 November 2023" .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 \-v Verbose output. .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 and bss segment to the end of the data segment (\-xd and \-xb options override the derived address) 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 and Cameron Kaiser . Original xa package (C)1989-1997 Andre Fachat. Additional changes (C)1989-2023 Andre Fachat, Jolse Maginnis, David Weinehall and Cameron Kaiser. The current maintainer is Cameron Kaiser. .SH WEBSITE http://www.floodgap.com/retrotech/xa/ xa-2.4.0/man/uncpk.10000644000031500000010000000237014526073176013431 0ustar spectrestaff.TH UNCPK "1" "18 November 2023" .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 and Cameron Kaiser . Original xa package (C)1989-1997 Andre Fachat. Additional changes (C)1989-2023 Andre Fachat, Jolse Maginnis, David Weinehall and Cameron Kaiser. The current maintainer is Cameron Kaiser. .SH WEBSITE http://www.floodgap.com/retrotech/xa/ xa-2.4.0/man/xa.10000644000031500000010000007437614526073150012730 0ustar spectrestaff.TH XA "1" "18 November 2023" .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 \-E Do not stop after 20 errors, but show all errors. .TP .B \-v Verbose output. .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 \-P filename Set listing filename. The default is none; use the special filename .BR \- to print the listing to standard output. .TP .B \-F format Set listing format; default is .BR plain . The only other currently supported format is .BR html . .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 \-Xcompatset Enables compatibility settings to become more (not fully!) compatible with other 6502 assemblers and codebases. Currently supported are compatibility sets .BR MASM , .BR CA65 and .BR C , with .B XA23 available as a deprecated option for codebases relying on compatibility with the previous version of .BR xa . Multiple compatibility sets may be specified and combined, e.g., .B \-XMASM .BR \-XXA23 . .IP .B \-XMASM allows colons to appear in comments for MASM compatibility. This does not affect colon interpretation elsewhere and may become the default in a future version. .IP .B \-XCA65 adds syntactic features more compatible with .BR ca65 (1). It permits .B := for defining labels (instead of plain .BR = ), and adds support for unnamed labels and "cheap" local labels using the .B @ character, but disables its other meaning for 24-bit mode (see .B ASSEMBLER .BR SYNTAX ). .IP .B \-XC enables the usage of .B 0xHEX and .B 0OCTAL C-style number encodings. .IP .B \-XXA23 restores partial compatibility with .B xa 2.3.x. In particular, it uses .B ^ for quote escapes instead of 2.4's .BR \e , allows nested multi-line comments, and disables all predefined .B xa preprocessor macros. This option is inherently deprecated and may be removed in the next 2.x or 3.x release. .TP .B \-M This option is deprecated and will be removed in a future version; use .B \-XMASM instead. Allows colons to appear in comments for MASM compatibility. This does not affect colon interpretation elsewhere, and may become the default in a future version. .TP .B \-R Start assembler in relocating mode, i.e. use segments. .TP .B \-U Do not allow undefined labels 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 .RB ( -? is a synonym). .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 .RB ( 0x234 accepted with .BR -XC ) .TP .B &123 octal .RB ( 0123 accepted with .BR -XC ) .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. If .B \-XCA65 is specified, you can also use .B := as well as .BR = . .LP 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 Redefining a label does not change previously assembled code that used the earlier value. Therefore, because the program counter is a special type of label, changing the program counter to a lower value does not reorder code assembled previously and changing it to a higher value does not issue padding to put subsequent code at the new location. This is intentional behaviour to facilitate generating relocatable and position-independent code, but can differ from other assemblers which use this behaviour for linking. However, it is possible to use pseudo-ops to simulate other assemblers' behaviour and use .B xa as a linker; see .B PSEUDO-OPS and .BR LINKING . .LP If .B \-XCA65 is specified, "cheap" local labels may be used, marked by the .B @ prefix. Additionally, unnamed labels may be specified with .B : (i.e., no label, just a colon); branches may then reference these unnamed labels with a colon and plus signs for forward branching or minus signs for backward branching. For example (from the .B ca65 documentation), .LP : lda (ptr1),y ; #1 .BR cmp (ptr2),y .BR bne :+ ; -> #2 .BR tax .BR beq :+++ ; -> #4 .BR iny .BR bne :- ; -> #1 .BR inc ptr1+1 .BR inc ptr2+1 .BR bne :- ; -> #1 .BR .BR : bcs :+ ; #2 -> #3 .BR ldx #$FF .BR rts .BR .BR : ldx #$01 ; #3 .BR : rts ; #4 .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 handling, 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); .B == also accepted .TP .B <> >< does not equal (6); .B != also accepted .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 # 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, even if smaller than 24 bits (must specify .B \-w command-line option, must not specify .BR \-XCA65 ) .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 # , .BR >= , .B != and .BR <> . .TP .B \.include "filename" Includes another file in place of the pseudo-op, as if the preprocessor had done so with an .B #include directive (see .BR PREPROCESSOR ), but at the assembler phase after preprocessing has already occurred. .LP The following pseudo-op applies to listing mode. .TP .B \.listbytes number In the listing output, sets the maximum number of hex bytes to be printed in the listing for pseudo-ops like .BR .byt , by default 8. The special argument .B unlimited sets no upper limit. If listing mode is disabled, this pseudo-op has no observable effect. .LP The following pseudo-ops apply primarily to relocatable .B .o65 objects. A full discussion of the relocatable format is beyond the scope of this manpage; see .B http://www.6502.org/users/andre/o65/ for the most current specification. .TP .B .text .data .bss .zero These pseudo-ops switch between the different segments, .B .text being the actual code section, .B .data being the data segment, .B .bss being uninitialized label space for allocation and .B .zero being uninitialized zero page space for allocation. In .B .bss and .BR .zero , only labels are evaluated. These pseudo-ops are valid in relocating and absolute modes. .TP .B .code For .B ca65 compatibility, this is currently mapped to .BR .text . .TP .B .zeropage For .B ca65 compatibility, this is currently mapped to .BR .zero . .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 relocating 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. .TP .B .import label1, label2, label3, ... Defines the given labels as global labels which are imported and resolved during the link stage, like the .B -L command line parameter. .TP .B .importzp label1, label2, label3, ... Analogous to .BR .import , except that it only imports zeropage labels (i.e., byte values). .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 predefined macros are supported, except if .B \-XXA23 is specified: .TP .B XA_MAJOR The current major version of .BR xa . .TP .B XA_MINOR The current minor version of .BR xa . .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 #error message Displays the message as an error and terminates assembly. .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 #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! .TP .B #else Implements alternate path for a conditional block. .TP .B #endif Closes a conditional block. .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 LINKING .B xa is oriented towards generating sequential binaries. Code is strictly emitted in order even if the program counter is set to a lower location than previously assembled code, and padding is not automatically emitted if the program counter is set to a higher location. Changing the program location only changes new labels for code that is subsequently emitted; previous emitted code remains unchanged. Fortunately, for many object files these conventions have no effect on their generation. .LP However, some applications may require generating an object file built from several previously generated components, and/or submodules which may need to be present at specific memory locations. With a minor amount of additional specification, it is possible to use .B xa for this purpose as well. .LP The first means of doing so uses the o65 format to make relocatable objects that in turn can be linked by .BR ldo65 (1) (q.v.). .LP The second means involves either assembled code, or insertion of previously built object or data files with .BR .bin , using .B .dsb pseudo-ops with computed expression arguments to insert any necessary padding between them, in the sequential order they are to reside in memory. Consider this example: .LP .br .word $1000 .br * = $1000 .br .br ; this is your code at $1000 .br part1 rts .br ; this label marks the end of code .br endofpart1 .br .br ; DON'T PUT A NEW .word HERE! .br * = $2000 .br .dsb (*-endofpart1), 0 .br ; yes, set it again .br * = $2000 .br .br ; this is your code at $2000 .br part2 rts .br .LP This example, written for Commodore microcomputers using a 16-bit starting address, has two "modules" in it: one block of code at $1000 (4096), indicated by the code between labels .B part1 and .BR endofpart1 , and a second block at $2000 (8192) starting at label .BR part2 . .LP The padding is computed by the .B .dsb pseudo-op between the two modules. Note that the program counter is set to the new address and then a computed expression inserts the proper number of fill bytes from the end of the assembled code in part 1 up to the new program counter address. Since this itself advances the program counter, the program counter is reset again, and assembly continues. .LP When the object this source file generates is loaded, there will be an .B rts instruction at address 4096 and another at address 8192, with null bytes between them. .LP Should one of these areas need to contain a pre-built file, instead of assembly code, simply use a .B .bin pseudo-op to load whatever portions of the file are required into the output. The computation of addresses and number of necessary fill bytes is done in the same fashion. .LP Although this example used the program counter itself to compute the difference between addresses, you can use any label for this purpose, keeping in mind that only the program counter determines where relative addresses within assembled code are resolved. .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 The 65816 instructions .B mvn and .B mvp use two eight bit parameters, the only instructions in the entire instruction set to do so. Older versions of .B xa took a single 16-bit absolute value. As of 2.4.0, this old syntax is no longer accepted. .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. .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 , Andre Fachat and Cameron Kaiser . Original xa package (C)1989-1997 Andre Fachat. Additional changes (C)1989-2023 Andre Fachat, Jolse Maginnis, David Weinehall, Cameron Kaiser. The official maintainer is Cameron Kaiser. .SH OVER 30 YEARS OF XA Yay us? .SH WEBSITE http://www.floodgap.com/retrotech/xa/ xa-2.4.0/misc/0000700000031500000010000000000014520744426012370 5ustar spectrestaffxa-2.4.0/misc/Makefile0000600000031500000010000000145414513025501014022 0ustar spectrestaff XCBMLIB = .. # -Wall -ansi et al. cause compile problems. CFLAGS = -O2 -g 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 xa-2.4.0/misc/file65.c0000600000031500000010000002217114520616356013633 0ustar spectrestaff/* 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. */ #ifndef _MSC_VER #include #endif #include #include #include #include #include #include #include "version.h" #define BUF (9*4+8) #define programname "file65" #define progversion "v0.2.1" #define author "Written by Andre Fachat" #define copyright "Copyright (C) 1997-2002 Andre 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; int verbose = 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" " -vv print undefined and global labels, and relocation tables\n" " --version output version information and exit\n" " --help display this help and exit\n"); } int main(int argc, char *argv[]) { int i, j, n, mode, hlen; FILE *fp; char *aligntxt[4]= {"[align 1]","[align 2]","[align 4]","[align 256]"}; if(argc<=1) { usage(stderr); exit(1); } i = 1; if (strstr(argv[i], "--help") || strstr(argv[i], "-?")) { usage(stdout); exit(0); } if (strstr(argv[i], "--version")) { version(programname, progversion, author, copyright); exit(0); } while(i=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(verbose) { 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 1) { printf("Relocation table for %s:\n", i ? "text":"data"); } c=fgetc(fp); while(c && c!=EOF) { c&= 0xff; while(c == 255 && c!= EOF) { offset += 254; c=fgetc(fp); if(c==EOF) break; c&= 0xff; } if(c==EOF) break; offset += c; c=fgetc(fp); if( (c & 0xe0) == 0x40 ) { lowbyte = fgetc(fp); } if( (c & 0x07) == 0 ) { index = fgetc(fp) & 0xff; index += (fgetc(fp) & 0xff) << 8; } if (verbose > 1) { printf("\t%d:%s(%s (%d)", offset, reltype[ (c>>5) & 0xf], segments[c & 0x07], (c&0x07)); if ( (c & 0xe0) == 0x40) { printf(", %02x", lowbyte); } if ( (c & 0x07) == 0) { printf(", %04x", index); } printf(")"); } c=fgetc(fp); } if (verbose > 1) { printf("\n"); } } // --------------------------------------------------------- // print global labels 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; } xa-2.4.0/misc/ldo65.c0000600000031500000010000007243414524572207013501 0ustar spectrestaff/* 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) 1997-2023 André Fachat (fachat@web.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 #include #include #include #ifndef _MSC_VER #include #endif #include #include "version.h" #define BUF (9*2+8) /* 16 bit header */ #define programname "ldo65" #define progversion "v0.2.0" #define author "Written by Andre Fachat" #define copyright "Copyright (C) 1997-2023 Andre Fachat. Formerly ld65." #undef DEBUG /* The process of linking works as follows: 1. Every file is loaded in turn via load_file() 2. Calculate new base addresses per segment 3. Merge all globals from all files into a single table, checking for duplicates 4. Resolve undefined labels, and merge remaining into global list 5. relocate all segments, create global relocation tables 6. verify undefined labels 7. write out target file */ typedef struct { char *name; int len; int newidx; /* index in new global undef table (for reloc) */ int resolved; /* index in current global label table after resolve (-1 is not found) */ } 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 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 write_undef(FILE *f, file65 *fp); int check_undef(file65 *fp, char *defined[], int ndefined); int len_reloc_seg(unsigned char *buf, int ri); int reloc_seg(unsigned char *buf, int pos, int addr, int rdiff, int ri, unsigned char *obuf, int *lastaddrp, int *rop, 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); int write_nglobals(FILE *fp, char **globdef, int nglobal); int find_global(unsigned char *name); int resolve_undef(file65 *file, int *remains); file65 file; unsigned char cmp[] = { 1, 0, 'o', '6', '5' }; unsigned char hdr[26] = { 1, 0, 'o', '6', '5', 0 }; int verbose = 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" " -U accept any undef'd labels after linking\n" " -L accept specific given undef'd labels after linking\n" " -g only export the globals defined with (multiple) -g options\n" " -v verbose output\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 undefok=0; int i = 1; int tbase = 0x0400, dbase = 0x1000, bbase = 0x4000, zbase = 0x0002; int ttlen, tdlen, tblen, tzlen, routtlen, routdlen, tro, dro; int lasttaddr, lastdaddr; unsigned char *treloc, *dreloc; char *outfile = "a.o65"; int j, jm; file65 *file, **fp = NULL; FILE *fd; int nundef = 0; // counter/index in list of remaining undef'd labels char *arg; char **defined = NULL; int ndefined = 0; int ndefalloc = 0; // globals allowed by -g char **globdef = NULL; int nglobal = 0; int ngloballoc = 0; if (argc <= 1) { usage(stderr); exit(1); } if (strstr(argv[1], "--help") || strstr(argv[1], "-?")) { usage(stdout); exit(0); } if (strstr(argv[1], "--version")) { version(programname, progversion, author, copyright); exit(0); } /* read options */ while(i= ngloballoc) { ngloballoc *= 2; globdef = realloc(globdef, ngloballoc * sizeof(char*)); } globdef[nglobal++] = arg; break; case 'L': if(argv[i][2]) arg=argv[i]+2; else arg=argv[++i]; if (ndefalloc == 0) { ndefalloc = 20; defined = malloc(ndefalloc * sizeof(char*)); } else if (ndefined >= ndefalloc) { ndefalloc *= 2; defined = realloc(defined, ndefalloc * sizeof(char*)); } defined[ndefined++] = arg; 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++; } // ------------------------------------------------------------------------- // step 1 - load files /* each file is loaded first */ j=0; jm=0; fp=NULL; while(i=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; } else { exit(1); } i++; } // ------------------------------------------------------------------------- // step 2 - calculate new segment base addresses per file, by // concatenating the segments per type /* 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;itdiff = ((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+len=%04x->%04x, file->tbase=%04x, f.tlen=%04x -> tdiff=%04x\n", tbase, ttlen, (tbase + ttlen), file->tbase, file->tlen, file->tdiff); printf("zbase=%04x+len=%04x->%04x, file->zbase=%04x, f.zlen=%04x -> zdiff=%04x\n", zbase, tzlen, (zbase + tzlen), file->zbase, file->zlen, file->zdiff); */ if (verbose > 0) { printf("Relocating file: %s\n", file->fname); printf(" text: from %04x to %04x (diff is %04x, length is %04x)\n", file->tbase, file->tbase + file->tdiff, file->tdiff, file->tlen); printf(" data: from %04x to %04x (diff is %04x, length is %04x)\n", file->dbase, file->dbase + file->ddiff, file->ddiff, file->dlen); printf(" bss: from %04x to %04x (diff is %04x, length is %04x)\n", file->bbase, file->bbase + file->bdiff, file->bdiff, file->blen); printf(" zero: from %02x to %02x (diff is %02x, length is %02x)\n", file->zbase, file->zbase + file->zdiff, file->zdiff, file->zlen); } /* update globals (for result file) */ ttlen += file->tlen; tdlen += file->dlen; tblen += file->blen; tzlen += file->zlen; } // validate various situations. { int er = 0; if (tbase + ttlen > 0x10000) { fprintf(stderr, "Overflow in text segment: end at %06x behind 64k limit\n", tbase + ttlen); er = 1; } if (dbase + tdlen > 0x10000) { fprintf(stderr, "Overflow in data segment: end at %06x behind 64k limit\n", dbase + tdlen); er = 1; } if (bbase + tblen > 0x10000) { fprintf(stderr, "Overflow in bss segment: end at %06x behind 64k limit\n", bbase + tblen); er = 1; } if (zbase + tzlen > 0x100) { fprintf(stderr, "Overflow in zero segment: end at %04x behind 256 byte limit\n", zbase + tzlen); er = 1; } if (er) { exit (1); } } // ------------------------------------------------------------------------- // step 3 - merge globals from all files into single table // for(i=0;idrpos - file->trpos); routdlen += (file->gpos - file->drpos); reloc_globals(file->buf+file->gpos, file); } // prep global reloc tables treloc = malloc(routtlen); dreloc = malloc(routdlen); #ifdef DEBUG printf("prep'd text reloc table at %p (%d bytes)\n", treloc, routtlen); printf("prep'd data reloc table at %p (%d bytes)\n", dreloc, routdlen); #endif tro = 0; dro = 0; // segment position of last relocation entry to compute offsets across files lasttaddr = tbase - 1; lastdaddr = dbase - 1; for(i=0;ibuf, // input buffer file->tpos, // position of segment in input buffer file->tbase, // segment base address file->tdiff, // reloc difference file->trpos, // position of reloc table in input treloc, // output reloc buffer &lasttaddr, // last relocated target address &tro, // pointer in output reloc bufer file); reloc_seg(file->buf, file->dpos, file->dbase, file->ddiff, file->drpos, dreloc, &lastdaddr, &dro, file); // change file information to relocated values file->tbase += file->tdiff; file->dbase += file->ddiff; file->bbase += file->bdiff; file->zbase += file->zdiff; } // finalize global reloc table treloc[tro++] = 0; dreloc[dro++] = 0; // ------------------------------------------------------------------------- // step 6 - validate undefined labels // if (nundef > 0 && !undefok) { int er = 0; // we have undefined labels, but it's not ok (no -U) // check -L defined labels for(i=0;i>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; // open file fd = fopen(outfile, "wb"); if(!fd) { fprintf(stderr,"Couldn't open output file %s (%s)\n", outfile, strerror(errno)); exit(2); } // write header fwrite(hdr, 1, 26, fd); // write options - this writes _all_ options from _all_files! for(i=0;ibuf + fp[i]->tpos, 1, fp[i]->tlen, fd); } // write data segment for(i=0;ibuf + fp[i]->dpos, 1, fp[i]->dlen, fd); } // write list of undefined labels fputc(nundef & 0xff,fd); fputc((nundef >> 8) & 0xff,fd); if (nundef > 0) { for(i=0;i 0) { write_nglobals(fd, globdef, nglobal); } 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 bufp; // pointer in input buffer int startp; // pointer to start of label name int nlabels; // number of labels in file undefs *current = NULL; int i; bufp = 0; nlabels = buf[bufp] + 256*buf[bufp+1]; bufp += 2; file->nundef = nlabels; if (nlabels == 0) { file->ud = NULL; } else { file->ud = malloc(nlabels*sizeof(undefs)); if(!file->ud) { fprintf(stderr,"Oops, no more memory\n"); exit(1); } i=0; while(iud[i]; current->name = (char*) buf+startp; current->len = bufp-startp-1; current->resolved = -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 bufp; } int resolve_undef(file65 *file, int *remains) { int i; undefs *current; int nlabels = file->nundef; #ifdef DEBUG printf("resolved undef file %s (%d undef'd)\n", file->fname, nlabels); #endif if (nlabels == 0) { return 0; } current = file->ud; for (i = 0; i < nlabels; i++) { // store pointer to global in label info // if NULL is returned, is not resolved current->resolved = find_global(current->name); #ifdef DEBUG printf("resolved undef label %s to: resolved=%d, newidx=%d\n", current->name, current->resolved, *remains); #endif if (current->resolved == -1) { // keep in global undef list current->newidx = *remains; *remains += 1; } current++; } return 0; } int write_undef(FILE *f, file65 *fp) { int i; for (i = 0; i < fp->nundef; i++) { undefs *current = &fp->ud[i]; if (current->resolved == -1) { // only write unresolved entries fprintf(f, "%s%c", current->name, 0); } } return 0; } int check_undef(file65 *fp, char *defined[], int ndefined) { int er = 0; int i, j; for (i = 0; i < fp->nundef; i++) { undefs *current = &fp->ud[i]; if (current->resolved == -1) { // only check unresolved entries int found = 0; for (j = 0; j < ndefined; j++) { if (defined && !strcmp(defined[j], current->name)) { // label is found, so it's ok found = 1; break; } } if (!found) { fprintf(stderr, "Unresolved label '%s' from file '%s'\n", current->name, fp->fname); er = -1; } } } return er; } /***************************************************************************/ /* 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; char *name; n = buf[0] + 256*buf[1]; buf +=2; while(n) { name = buf; while(*(buf++)); seg = *buf & 0x07; old = buf[1] + 256*buf[2]; new = old + reldiff(seg); if (verbose > 1) { printf("%s:%s: old=%04x, seg=%d, rel=%04x, new=%04x\n", fp->fname, name, 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[22]; 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,"Error: %s: not an o65 file\n", fname); return NULL; } } else { fprintf(stderr,"file65: %s: %s\n", fname, strerror(errno)); return NULL; } return file; } /***************************************************************************/ // global list of all global labels glob *gp = NULL; // number of global labels int g=0; // number of globals for which memory is already allocated int gm=0; int write_globals(FILE *fp) { int i; fputc(g&255, fp); fputc((g>>8)&255, fp); for(i=0;i>8)&255); } return 0; } int write_nglobals(FILE *fp, char **globdef, int nglobal) { int i, j; int newnum = 0; // first check which defined globals are allowed to be exported // and clear out the other ones for (i = 0; i < g; i++) { for (j = 0; j < nglobal; j++) { if (!strcmp(gp[i].name, globdef[j])) { // found break; } } if (j >= nglobal) { // not found gp[i].name = NULL; } else { // found, so we inc the counter newnum++; } } // then check which globals from the -g list are actually used, and warn about unused ones for (j = 0; j < nglobal; j++) { for (i = 0; i < g; i++) { if (gp[i].name != NULL && !strcmp(gp[i].name, globdef[j])) { // found break; } } if (i >= g) { // not found fprintf(stderr,"Warning: command line allowed global '%s' is not defined!\n", globdef[j]); } } // write out only defined globals fputc(newnum&255, fp); fputc((newnum>>8)&255, fp); for(i=0;i>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;ifname, 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; #ifdef DEBUG printf("set global label '%s' (l=%d, seg=%d, val=%04x)\n", gp[g].name, gp[g].len, gp[g].seg, gp[g].val); #endif g++; } buf +=3; n--; } return 0; } int find_global(unsigned char *name) { int i; for (i = 0; i < g; i++) { if (!strcmp(gp[i].name, name)) { // found return i; } } return -1; } // searches for a global label in a file by name. // returns the value of a found global value int find_file_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>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; } /***************************************************************************/ #define forwardpos() \ while(addr-lastaddr>254){obuf[ro++]=255;lastaddr+=254;}obuf[ro++]=addr-lastaddr;lastaddr=addr int reloc_seg(unsigned char *buf, int pos, int addr, int rdiff, int ri, unsigned char *obuf, int *lastaddrp, int *rop, file65 *fp) { int type, seg, old, new, ro, lastaddr, diff; int base; /* pos = address of current position ri = position of relocation table in *buf for reading the reloc entries ro(p) = position of relocation table entry for writing the modified entries */ base = addr; addr--; ro = *rop; lastaddr = *lastaddrp - rdiff; #ifdef DEBUG printf("reloc_seg: %s: addr=%04x, pos=%04x, lastaddr=%04x (%04x - %04x)\n", fp->fname, addr, pos, lastaddr, *lastaddrp, rdiff); #endif while(buf[ri]) { // still reloc entry if((buf[ri] & 255) == 255) { addr += 254; ri++; } else { addr += buf[ri] & 255; type = buf[ri+1] & 0xe0; seg = buf[ri+1] & 0x07; #ifdef DEBUG printf("reloc entry @ ri=%04x, pos=%04x, type=%02x, seg=%d, offset=%d, reldiff=%04x\n", ri, pos, type, seg, addr-lastaddr, reldiff(seg)); #endif switch(type) { case 0x80: // address (word) relocation old = buf[addr-base+pos] + 256*buf[addr-base+pos+1]; if(seg) { diff = reldiff(seg); ri++; // skip position byte forwardpos(); // re-write position offset obuf[ro++] = buf[ri++]; // relocation byte ($8x for segments text, data, bss, zp) } else { // undefined undefs *u = &fp->ud[buf[ri+2]+256*buf[ri+3]]; #ifdef DEBUG printf("found undef'd label %s, resolved=%d, newidx=%d, (ri=%d, ro=%d)\n", u->name, u->resolved, u->newidx, ri, ro); #endif if (u->resolved == -1) { // not resolved diff = 0; ri++; // skip position byte forwardpos(); // re-write position offset obuf[ro++] = buf[ri++]; // relocation byte ($8x for segments text, data, bss, zp) obuf[ro++] = u->newidx & 0xff; // output label number lo/hi obuf[ro++] = (u->newidx >> 8) & 0xff; ri += 2; // acount for label number in input } else { // resolved from global list glob *gl = &gp[u->resolved]; diff = gl->val; seg = gl->seg; if (seg != 1) { // not an absolute value forwardpos(); // re-write position offset obuf[ro++] = 0x80 | seg;// relocation byte for new segment } else { // absolute value - do not write a new relocation entry } ri += 4; // account for position, segment byte, label number in reloc table } } new = old + diff; /*printf("old=%04x, new=%04x\n",old,new);*/ buf[addr-base+pos] = new & 255; buf[addr-base+pos+1] = (new>>8)&255; break; case 0x40: // high byte relocation if(seg) { old = buf[addr-base+pos]*256 + buf[ri+2]; diff = reldiff(seg); forwardpos(); // re-write position offset obuf[ro++] = buf[ri+1]; // relocation byte ($4x for segments text, data, bss, zp) obuf[ro++] = (old + diff) & 255; ri += 3; // skip position, segment, and low byte } else { undefs *u; old = buf[addr-base+pos]*256 + buf[ri+4]; // undefined u = &fp->ud[buf[ri+2]+256*buf[ri+3]]; if (u->resolved == -1) { // not resolved diff = 0; forwardpos(); // re-write position offset obuf[ro++] = buf[ri+1]; // relocation byte ($8x for segments text, data, bss, zp) obuf[ro++] = u->newidx & 0xff; // output label number lo/hi obuf[ro++] = (u->newidx >> 8) & 0xff; obuf[ro++] = buf[ri+4]; // low byte for relocation } else { // resolved from global list glob *gl = &gp[u->resolved]; diff = gl->val; seg = gl->seg; if (seg != 1) { // not an absolute value forwardpos(); // re-write position offset obuf[ro++] = 0x40 | seg; // relocation byte for new segment obuf[ro++] = (old + diff) & 0xff; // low byte for relocation } else { // absolute value - do not write a new relocation entry } } ri += 5; // account for position, segment byte, label number in reloc table, low byte } new = old + diff; buf[addr-base+pos] = (new>>8)&255; break; case 0x20: // low byte relocation old = buf[addr-base+pos]; diff = 0; if(seg) { diff = reldiff(seg); forwardpos(); obuf[ro++] = buf[ri+1]; // relocation byte ($4x for segments text, data, bss, zp) ri += 2; // account for position & segment } else { // undefined undefs *u = &fp->ud[buf[ri+2]+256*buf[ri+3]]; if (u->resolved == -1) { // not resolved diff = 0; forwardpos(); // re-write position offset obuf[ro++] = buf[ri+1]; // relocation byte ($8x for segments text, data, bss, zp) obuf[ro++] = u->newidx & 0xff; // output label number lo/hi obuf[ro++] = (u->newidx >> 8) & 0xff; } else { // resolved from global list glob *gl = &gp[u->resolved]; diff = gl->val; seg = gl->seg; if (seg != 1) { // not an absolute value forwardpos(); // re-write position offset obuf[ro++] = 0x20 | seg; // relocation byte for new segment } else { // absolute value - do not write a new relocation entry } } ri += 4;// account for position, segment byte, label number in reloc table } new = old + diff; buf[addr-base+pos] = new & 255; break; } } } *lastaddrp = lastaddr + rdiff; *rop = ro; #ifdef DEBUG printf(" --> lastaddr=%04x (%04x - %04x), rop=%d\n", lastaddr, *lastaddrp, rdiff, ro); #endif return ++ri; } xa-2.4.0/misc/mkrom.sh0000700000031500000010000000367214513025305014052 0ustar spectrestaff#!/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 \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 xa-2.4.0/misc/printcbm.c0000600000031500000010000000563514524323611014356 0ustar spectrestaff/* 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 #include #include #include "version.h" #define programname "printcbm" #define progversion "v1.0.0" #define author "Written by Andre Fachat" #define copyright "Copyright (C) 1997-2002 Andre 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" "This tool is deprecated as of xa 2.4 and will be removed in a future version.\n" "Please consider migrating to VICE petcat, which has many more options.\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") || strstr(argv[1], "-?")) { 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; } xa-2.4.0/misc/reloc65.c0000600000031500000010000002646114517123714014023 0ustar spectrestaff/* 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 #include #include #include #include #include #include "version.h" #define BUF (9*2+8) /* 16 bit header */ #define programname "reloc65" #define progversion "v0.2.1" #define author "Written by Andre Fachat" #define copyright "Copyright (C) 1997-2002 Andre 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" " -v verbose output\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; int *base; char *outfile = "a.o65"; int extract = 0; int verbose = 0; if (argc <= 1) { usage(stderr); exit(1); } if (strstr(argv[1], "--help") || strstr(argv[1], "-?")) { usage(stdout); exit(0); } if (strstr(argv[1], "--version")) { version(programname, progversion, author, copyright); exit(0); } while(i %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]; file.ddiff = dflag ? dbase - file.dbase : 0; if (extract == 3) { if (dflag) { fprintf(stderr,"reloc65: %s: Warning: data segment address overrides -X option\n", argv[i]); } else { dbase = file.tbase + file.tdiff + file.tlen; file.ddiff = dbase - file.dbase; } } 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; if (extract == 3) { if (bflag) { fprintf(stderr,"reloc65: %s: Warning: bss segment address overrides -X option\n", argv[i]); } else { bbase = file.dbase + file.ddiff + file.dlen; file.bdiff = bbase - file.bbase; } } file.zbase = file.buf[21]*256+file.buf[20]; file.zlen = file.buf[23]*256+file.buf[22]; file.zdiff = zflag ? zbase - file.zbase : 0; if (verbose) { printf("Relocating segments to:\n"); printf("text segment @ $%04x - $%04x, %5d ($%04x) bytes, diff is %5d ($%04x)\n", file.tbase + file.tdiff, file.tbase + file.tdiff + file.tlen, file.tlen, file.tlen, file.tdiff, file.tdiff & 0xffff); printf("data segment @ $%04x - $%04x, %5d ($%04x) bytes, diff is %5d ($%04x)\n", file.dbase + file.ddiff, file.dbase + file.ddiff + file.dlen, file.dlen, file.dlen, file.ddiff, file.ddiff & 0xffff); printf("bss segment @ $%04x - $%04x, %5d ($%04x) bytes, diff is %5d ($%04x)\n", file.bbase + file.bdiff, file.bbase + file.bdiff + file.blen, file.blen, file.blen, file.bdiff, file.bdiff & 0xffff); printf("zero segment @ $%04x - $%04x, %5d ($%04x) bytes, diff is %5d ($%04x)\n", file.zbase + file.zdiff, file.zbase + file.zdiff + file.zlen, file.zlen, file.zlen, file.zdiff, file.zdiff & 0xffff); } /* pointer of position in file */ 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; } xa-2.4.0/misc/uncpk.c0000600000031500000010000001117414517123714013657 0ustar spectrestaff/* 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 #include #include #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 Andre Fachat" #define copyright "Copyright (C) 1997-2002 Andre 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") || strstr(argv[1], "-?")) { 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=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); } xa-2.4.0/misc/version.h0000644000031500000010000000245414513025305014233 0ustar spectrestaff/* 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__ */ xa-2.4.0/src/0000700000031500000010000000000014524607311012217 5ustar spectrestaffxa-2.4.0/src/Makefile0000600000031500000010000000051114513122762013656 0ustar spectrestaffOBJ = xa.o xaa.o xal.o xap.o xat.o xar.o xar2.o xao.o xau.o xam.o xacharset.o xalisting.o #CFLAGS=-W -Wall -pedantic -ansi -g #CFLAGS=-W -Wall -ansi -O2 #CFLAGS=-g -std=c11 -D_GNU_SOURCE #LD = ${CC} #LDFLAGS = "-lc" all: xa xa: ${OBJ} ${LD} -o ../xa ${OBJ} ${LDFLAGS} clean: rm -f *.o *.o65 mrproper: clean rm -f ../xa xa-2.4.0/src/version.h0000644000031500000010000000244414514131764014076 0ustar spectrestaff/* 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 *version, 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, version, authors, copyright); } #endif /* __XA65_VERSION_H__ */ xa-2.4.0/src/xa.c0000600000031500000010000010110614520354110012764 0ustar spectrestaff/* xa65 - 65xx/65816 cross-assembler and utility suite * * Copyright (C) 1989-1997 André Fachat (a.fachat@physik.tu-chemnitz.de) * maintained by Cameron Kaiser (ckaiser@floodgap.com) * * Main program * * 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 #include #include #include #include #ifndef _MSC_VER #include #endif /* macros */ #include "xad.h" /* structs and defs */ #include "xah.h" #include "xah2.h" /* exported functions are defined here */ #include "xa.h" #include "xal.h" #include "xam.h" #include "xao.h" #include "xap.h" #include "xar.h" #include "xat.h" #include "xacharset.h" #include "xalisting.h" #include "version.h" /* ANZERR: total number of errors */ /* ANZWARN: total number of warnings */ #define ANZERR 64 #define ANZWARN 13 #define programname "xa" /* progversion now in xa.h */ #define authors "Written by Andre Fachat, Jolse Maginnis, David Weinehall and Cameron Kaiser" #define copyright "Copyright (C) 1989-2023 Andre Fachat, Jolse Maginnis, David Weinehall\nand Cameron Kaiser." /* exported globals */ int ncmos, cmosfl, w65816, n65816; /* compatibility flags */ int masm = 0; /* MASM */ int ca65 = 0; /* CA65 */ int xa23 = 0; /* ^ and recursive comments, disable \ escape */ int ctypes = 0; /* C compatibility, like "0xab" types */ int nolink = 0; int romable = 0; int romaddr = 0; int noglob = 0; int showblk = 0; int crossref = 0; int undefok = 0; // -R only accepts -Llabels; with -U all undef'd labels are ok in -R mode char altppchar; /* local variables */ static char out[MAXLINE]; static time_t tim1, tim2; static FILE *fpout, *fperr, *fplab, *fplist; static int ner = 0; static int ner_max = 20; static int align = 1; static void printstat(void); static void usage(int, FILE *); static int setfext(char *, char *); static int x_init(void); static int pass1(void); static int pass2(void); static int puttmp(int); static int puttmpw(int); static int puttmps(signed char *, int); static void chrput(int); static int xa_getline(char *); static void lineout(void); static long ga_p1(void); static long gm_p1(void); static int set_compat(char *compat_name); /* text */ int memode,xmode; int segment; int tlen=0, tbase=0x1000; int dlen=0, dbase=0x0400; int blen=0, bbase=0x4000; int zlen=0, zbase=4; int fmode=0; int relmode=0; int pc[SEG_MAX]; /* segments */ int main(int argc,char *argv[]) { int er=1,i; signed char *s=NULL; char *tmpp; char *listformat = NULL; int mifiles = 5; int nifiles = 0; int verbose = 0; int no_link = 0; char **ifiles; char *printfile; /* print listing to this file */ char *ofile; /* output file */ char *efile; /* error listing goes there */ char *lfile; /* labels go here */ char *ifile; char old_e[MAXLINE]; char old_l[MAXLINE]; char old_o[MAXLINE]; tim1=time(NULL); ncmos=0; n65816=0; cmosfl=1; w65816=0; /* default: 6502 only */ altppchar = '#' ; /* i.e., NO alternate char */ if((tmpp = strrchr(argv[0],'/'))) { tmpp++; } else { tmpp = argv[0]; } if( (!strcmp(tmpp,"xa65816")) || (!strcmp(tmpp,"XA65816")) || (!strcmp(tmpp,"xa816")) || (!strcmp(tmpp,"XA816")) ) { w65816 = 1; /* allow 65816 per default */ } /* default output charset for strings in quotes */ set_charset("ASCII"); ifiles = malloc(mifiles*sizeof(char*)); afile = alloc_file(); if (argc <= 1) { usage(w65816, stderr); exit(1); } if (strstr(argv[1], "--help") || strstr(argv[1], "-?")) { usage(w65816, stdout); exit(0); } if (strstr(argv[1], "--version")) { version(programname, progversion, authors, copyright); exit(0); } ofile="a.o65"; efile=NULL; lfile=NULL; printfile=NULL; if(pp_init()) { logout("fatal: pp: no memory!"); return 1; } if(b_init()) { logout("fatal: b: no memory!"); return 1; } if(l_init()) { logout("fatal: l: no memory!"); return 1; } i=1; while(i filename */ ifiles[nifiles++] = argv[i]; if(nifiles>=mifiles) { mifiles += 5; ifiles=realloc(ifiles, mifiles*sizeof(char*)); if(!ifiles) { fprintf(stderr, "Oops: couldn't alloc enough mem for filelist table..!\n"); exit(1); } } } i++; } if(!nifiles) { fprintf(stderr, "No input files given!\n"); exit(0); } if(verbose) fprintf(stderr, "%s\n",copyright); if (printfile!=NULL && !strcmp(printfile, "-")) { printfile=NULL; fplist = stdout; } else { fplist= printfile ? xfopen(printfile,"w") : NULL; } fplab= lfile ? xfopen(lfile,"w") : NULL; fperr= efile ? xfopen(efile,"w") : NULL; if(!strcmp(ofile,"-")) { ofile=NULL; fpout = stdout; } else { fpout= xfopen(ofile,"wb"); } if(!fpout) { fprintf(stderr, "Couldn't open output file!\n"); exit(1); } if(verbose) fprintf(stderr, "%s\n",copyright); if(1 /*!m_init()*/) { if(1 /*!b_init()*/) { if(1 /*!l_init()*/) { /*if(!pp_init())*/ { if(!x_init()) { /* if(fperr) fprintf(fperr,"%s\n",copyright); */ if(verbose) logout(ctime(&tim1)); list_setfile(fplist); /* Pass 1 */ pc[SEG_ABS]= 0; /* abs addressing */ seg_start(fmode, tbase, dbase, bbase, zbase, 0, relmode); if(relmode) { r_mode(RMODE_RELOC); segment = SEG_TEXT; } else { /* prime old_segment in r_mode with SEG_TEXT */ segment = SEG_ABS; r_mode(RMODE_ABS); } nolink = no_link; for (i=0; ifname)); if(!er) { er=pass1(); pp_close(); } else { sprintf(out, "Couldn't open source file '%s'!\n", ifile); logout(out); } } if((er=b_depth())) { sprintf(out,"Still %d blocks open at end of file!\n",er); logout(out); } if(tbase & (align-1)) { sprintf(out,"Warning: text segment ($%04x) start address doesn't align to %d!\n", tbase, align); logout(out); } if(dbase & (align-1)) { sprintf(out,"Warning: data segment ($%04x) start address doesn't align to %d!\n", dbase, align); logout(out); } if(bbase & (align-1)) { sprintf(out,"Warning: bss segment ($%04x) start address doesn't align to %d!\n", bbase, align); logout(out); } if(zbase & (align-1)) { sprintf(out,"Warning: zero segment ($%04x) start address doesn't align to %d!\n", zbase, align); logout(out); } if (n65816>0) fmode |= 0x8000; switch(align) { case 1: break; case 2: fmode |= 1; break; case 4: fmode |= 2; break; case 256: fmode |=3; break; } if((!er) && relmode) h_write(fpout, fmode, tlen, dlen, blen, zlen, 0); if(!er) { if(verbose) logout("xAss65: Pass 2:\n"); list_start(listformat); seg_pass2(); if(relmode) { r_mode(RMODE_RELOC); segment = SEG_TEXT; } else { /* prime old_segment in r_mode with SEG_TEXT */ segment = SEG_ABS; r_mode(RMODE_ABS); } er=pass2(); list_end(); } if(fplab) printllist(fplab); tim2=time(NULL); if(verbose) printstat(); if((!er) && relmode) seg_end(fpout); /* write reloc/label info */ if(fplist && fplist!=stdout) fclose(fplist); if(fperr) fclose(fperr); if(fplab) fclose(fplab); if(fpout && fpout!=stdout) fclose(fpout); } else { logout("fatal: x: no memory!\n"); } pp_end(); /* } else { logout("fatal: pp: no memory!");*/ } } else { logout("fatal: l: no memory!\n"); } } else { logout("fatal: b: no memory!\n"); } /*m_exit();*/ } else { logout("Not enough memory available!\n"); } if(ner || er) { if (ner_max > 0) { fprintf(stderr, "Break after %d error%c\n",ner,ner?'s':0); } else { /* ner_max==0, i.e. show all errors */ fprintf(stderr, "End after %d error%c\n",ner,ner?'s':0); } /*unlink();*/ if(ofile) { unlink(ofile); } } free(ifiles); return( (er || ner) ? 1 : 0 ); } static void printstat(void) { logout("Statistics:\n"); sprintf(out," %8d of %8d label used\n",ga_lab(),gm_lab()); logout(out); sprintf(out," %8ld of %8ld byte label-memory used\n",ga_labm(),gm_labm()); logout(out); sprintf(out," %8d of %8d PP-defs used\n",ga_pp(),gm_pp()); logout(out); sprintf(out," %8ld of %8ld byte PP-memory used\n",ga_ppm(),gm_ppm()); logout(out); sprintf(out," %8ld of %8ld byte buffer memory used\n",ga_p1(),gm_p1()); logout(out); sprintf(out," %8d blocks used\n",ga_blk()); logout(out); sprintf(out," %8ld seconds used\n",(long)difftime(tim2,tim1)); logout(out); } int h_length(void) { return 26+o_length(); } #if 0 /* write header for relocatable output format */ int h_write(FILE *fp, int tbase, int tlen, int dbase, int dlen, int bbase, int blen, int zbase, int 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(tbase,fp); /* text base */ fputw(tlen,fp); /* text length */ fputw(dbase,fp); /* data base */ fputw(dlen,fp); /* data length */ fputw(bbase,fp); /* bss base */ fputw(blen,fp); /* bss length */ fputw(zbase,fp); /* zerop base */ fputw(zlen,fp); /* zerop length */ o_write(fp); return 0; } #endif static int setfext(char *s, char *ext) { int j,i=(int)strlen(s); if(i>MAXLINE-5) return(-1); for(j=i-1;j>=0;j--) { if(s[j]==DIRCHAR) { strcpy(s+i,ext); break; } if(s[j]=='.') { strcpy(s+j,ext); break; } } if(!j) strcpy(s+i,ext); return(0); } /* static char *tmp; static unsigned long tmpz; static unsigned long tmpe; */ static long ga_p1(void) { return(afile->mn.tmpz); } static long gm_p1(void) { return(TMPMEM); } static int pass2(void) { int c,er,l,ll,i,al; Datei datei; signed char *dataseg=NULL; signed char *datap=NULL; memode=0; xmode=0; if((dataseg=malloc(dlen))) { if(!dataseg) { fprintf(stderr, "Couldn't alloc dataseg memory...\n"); exit(1); } datap=dataseg; } filep=&datei; afile->mn.tmpe=0L; while((ner_max==0 || nermn.tmpemn.tmpz) { // get the length of the entry (now two byte - need to handle the sign) l = 255 & afile->mn.tmp[afile->mn.tmpe++]; l |= afile->mn.tmp[afile->mn.tmpe++] << 8; ll=l; //printf("%p: l=%d first=%02x\n", afile->mn.tmp+afile->mn.tmpe-1, l, 0xff & afile->mn.tmp[afile->mn.tmpe]); if(!l) { if(afile->mn.tmp[afile->mn.tmpe]==T_LINE) { datei.fline=(afile->mn.tmp[afile->mn.tmpe+1]&255)+(afile->mn.tmp[afile->mn.tmpe+2]<<8); afile->mn.tmpe+=3; list_line(datei.fline); /* set line number of next listing output */ } else if(afile->mn.tmp[afile->mn.tmpe]==T_FILE) { // copy the current line number from the current file descriptor datei.fline=(afile->mn.tmp[afile->mn.tmpe+1]&255)+(afile->mn.tmp[afile->mn.tmpe+2]<<8); // copy the pointer to the file name in the current file descriptor // Note: the filename in the current file descriptor is separately malloc'd and // thus save to store the pointer memcpy(&datei.fname, afile->mn.tmp+afile->mn.tmpe+3, sizeof(datei.fname)); afile->mn.tmpe+=3+sizeof(datei.fname); list_filename(datei.fname); /* set file name of next listing output */ } } else { /* do not attempt address mode optimization on pass 2 */ /* t_p2_l() includes the listing call to do_listing() */ er=t_p2_l(afile->mn.tmp+afile->mn.tmpe,&ll,&al); if(er==E_NOLINE) { } else if(er==E_OK) { if(segmentmn.tmp[afile->mn.tmpe+i]); } else if (segment==SEG_DATA && datap) { memcpy(datap,afile->mn.tmp+afile->mn.tmpe,ll); datap+=ll; } } else if(er==E_DSB) { c=afile->mn.tmp[afile->mn.tmpe]; if(segmentmn.tmp[afile->mn.tmpe]);*/ for(i=0;imn.tmpe; /* fprintf(stderr, "ok, ready to insert\n"); for (i=0; imn.tmp[afile->mn.tmpe+i]); } */ offset = afile->mn.tmp[i] + (afile->mn.tmp[i+1] << 8) + (afile->mn.tmp[i+2] << 16); fstart = afile->mn.tmp[i+3] + 1 + (afile->mn.tmp[i+4] << 8); /* usually redundant but here for single-char names that get interpreted as chars */ flen = afile->mn.tmp[i+5]; if (flen > 1) fstart++; /* now fstart points either to string past quote and length mark, OR, single char byte */ /* fprintf(stderr, "offset = %i length = %i fstart = %i flen = %i charo = %c\n", offset, ll, fstart, flen, afile->mn.tmp[afile->mn.tmpe+fstart]); */ /* there is a race condition here where altering the file between validation in t_p2 (xat.c) and here will cause problems. I'm not going to worry about this right now. */ for(j=0; jmn.tmp[i+fstart+j]; } binfnam[flen] = '\0'; /* fprintf(stderr, "fnam = %s\n", binfnam); */ /* primitive insurance */ if (!(foo = fopen(binfnam, "rb"))) { errout(E_FNF); ner++; } else { fseek(foo, offset, SEEK_SET); for(j=0; jmn.tmpe+=abs(l); } if(relmode) { if((ll=fwrite(dataseg, 1, dlen, fpout))mn.tmpz); */ } if(er!=E_EOF) { errout(er); } /* { int i; printf("Pass 1 \n"); for(i=0;imn.tmpz;i++) fprintf(stderr, " %02x",255 & afile->mn.tmp[i]); getchar();} */ return(ner); } static void usage(int default816, FILE *fp) { fprintf(fp, "Usage: %s [options] file\n" "Cross-assembler for 65xx/R65C02/65816\n" "\n", programname); fprintf(fp, " -v verbose output\n" " -E do not break after 20 errors, but show all\n" " -C no CMOS-opcodes\n" " -W no 65816-opcodes%s\n" " -w allow 65816-opcodes%s\n", default816 ? "" : " (default)", default816 ? " (default)" : ""); fprintf(fp, " -B show lines with block open/close\n" " -c produce `o65' object instead of executable files (i.e. don't link)\n" " -o filename sets output filename, default is `a.o65'\n" " A filename of `-' sets stdout as output file\n"); fprintf(fp, " -e filename sets errorlog filename, default is none\n" " -l filename sets labellist filename, default is none\n" " -P filename sets filename for listing, default is none, '-' is stdout\n" " -F format sets format for listing, default is plain, 'html' is current only other\n" " supported format\n" " -r adds crossreference list to labellist (if `-l' given)\n" " -M allow ``:'' to appear in comments for MASM compatibility\n" " (deprecated: prefer -XMASM)\n" " -Xcompatset set compatibility flags for other assemblers, known values are:\n" " C, MASM, CA65, XA23 (deprecated: for better 2.3 compatibility)\n" " -R start assembler in relocating mode\n" " -U allow all undefined labels in relocating mode\n"); fprintf(fp, " -Llabel defines `label' as absolute, undefined label even when linking\n" " -p replace preprocessor char '#' with custom, e.g. '-p!' replaces it with '!'\n" " -b? addr set segment base address to integer value addr\n" " `?' stands for t(ext), d(ata), b(ss) and z(ero) segment\n" " (address can be given more than once, last one is used)\n"); fprintf(fp, " -A addr make text segment start at an address that when the _file_\n" " starts at addr, relocation is not necessary. Overrides -bt\n" " Other segments must be specified with `-b?'\n" " -G suppress list of exported globals\n"); fprintf(fp, " -p? set preprocessor character to ?, default is #\n" " -DDEF=TEXT defines a preprocessor replacement\n" " -Ocharset set output charset (PETSCII, ASCII, etc.), case-sensitive\n" " -Idir add directory `dir' to include path (before XAINPUT)\n" " --version output version information and exit\n" " --help display this help and exit\n"); } static char *ertxt[] = { "Syntax", // E_SYNTAX =-1 "Label already defined", // E_LABDEF =-2 "Label not defined", // E_NODEF =-3 "Label table full", // E_LABFULL =-4 "Label expected", // E_LABEXP =-5 "Out of memory", // E_NOMEM =-6 "Illegal opcode", // E_ILLCODE =-7 "Wrong addressing mode", // E_ADRESS =-8 "Branch out of range", // E_RANGE =-9 "Overflow", // E_OVERFLOW =-10 "Division by zero", // E_DIV =-11 "Pseudo-opcode expected", // E_PSOEXP =-12 "Block stack overflow", // E_BLKOVR =-13 "File not found", // E_FNF =-14 "End of file", // E_EOF =-15 "Unmatched block close", // E_BLOCK =-16 "NoBlk", // E_NOBLK =-17 "NoKey", // E_NOKEY =-18 "NoLine", // E_NOLINE =-19 "OKDef", // E_OKDEF =-20 "DSB", // E_DSB =-21 "NewLine", // E_NEWLINE =-22 "NewFile", // E_NEWFILE =-23 "CMOS instruction used with -C", // E_DMOS =-24 "pp:Wrong parameter count", // E_ANZPAR =-25 "Illegal pointer arithmetic (-26)", // E_ILLPOINTER =-26 "Illegal segment", // E_ILLSEGMENT =-27 "File header option too long", // E_OPTLEN =-28 "File option not at file start (when ROM-able)", // E_ROMOPT =-29 "Illegal align value", // E_ILLALIGN =-30 "65816 mode used/required", // E_65816 =-31 "Exceeded recursion limit for label evaluation", // E_ORECMAC =-32 "Unresolved preprocessor directive at end of file", // E_OPENPP =-33 "Data underflow", // E_OUTOFDATA =-34 "Illegal quantity", // E_ILLQUANT =-35 ".bin", // E_BIN =-36 "#error directive", // E_UERROR =-37 "Assertion", // E_AERROR =-38 "DSB has negative length", // E_NEGDSBLEN =-39 /* placeholders for future fatal errors */ "", // -40 "", // -41 "", // -42 "", // -43 "", // -44 "", // -45 "", // -46 "", // -47 "", // -48 "", // -49 "", // -50 "", // -51 "", // -52 "", // -53 "", // -54 "", // -55 "", // -56 "", // -57 "", // -58 "", // -59 "", // -60 "", // -61 "", // -62 "", // -63 "", // -64 (was missing...) /* warnings */ "Cutting word relocation in byte value", // W_ADRRELOC =-65 "Byte relocation in word value", // W_BYTERELOC =-66 "Illegal pointer arithmetic (-66)", // E_WPOINTER =-67 "Address access to low or high byte pointer", // W_ADDRACC =-68 "High byte access to low byte pointer", // W_HIGHACC =-69 "Low byte access to high byte pointer", // W_LOWACC =-70 "Can't optimize forward-defined label; using absolute addressing", // W_FORLAB =-71 "Open preprocessor directive at end of file (intentional?)", // W_OPENPP =-72 "Included binary data exceeds 64KB", // W_OVER64K =-73 "Included binary data exceeds 16MB", // W_OVER16M =-74 "Subtracting pointer from constant not supported in -R mode", // W_SUBTRACT =-75 /* more placeholders */ "", // -76 "", // -77 }; static int gl; static int gf; static int x_init(void) { return 0; #if 0 int er=0; /*er=m_alloc(TMPMEM,&tmp);*/ afile->mn.tmp=malloc(TMPMEM); if(!afile->mn.tmp) er=E_NOMEM; afile->mn.tmpz=0L; return(er); #endif } static int puttmp(int c) { int er=E_NOMEM; //printf("puttmp: %02x -> %p \n",0xff & c, afile->mn.tmp+afile->mn.tmpz); if(afile->mn.tmpzmn.tmp[afile->mn.tmpz++]=c; er=E_OK; } return(er); } static int puttmpw(int c) { int er=E_NOMEM; //printf("puttmp: %02x -> %p \n",0xff & c, afile->mn.tmp+afile->mn.tmpz); if(afile->mn.tmpzmn.tmp[afile->mn.tmpz++]= c & 0xff; afile->mn.tmp[afile->mn.tmpz++]= (c >> 8) & 0xff; er=E_OK; } return(er); } static int puttmps(signed char *s, int l) { int i=0,er=E_NOMEM; // printf("puttmps %d bytes from %p to %p:", l, s, afile->mn.tmp+afile->mn.tmpz); if(afile->mn.tmpz+lmn.tmp[afile->mn.tmpz++]=s[i++]; } er=E_OK; } // printf("\n"); return(er); } static char l[MAXLINE]; static int xa_getline(char *s) { static int ec; static int i,c; int hkfl,j,comcom; j=hkfl=comcom=0; ec=E_OK; if(!gl) { do { ec=pgetline(l); i=0; while(l[i]==' ') i++; while(l[i]!='\0' && isdigit(l[i])) i++; gf=1; if(ec==E_NEWLINE) { puttmpw(0); puttmp(T_LINE); puttmpw(filep->fline); ec=E_OK; } else if(ec==E_NEWFILE) { puttmpw(0); puttmp(T_FILE); puttmpw(filep->fline); puttmps((signed char*)&(filep->fname), sizeof(filep->fname)); ec=E_OK; } } while(!ec && l[i]=='\0'); } gl=0; if(!ec || ec==E_EOF) { int startofline = 1; do { c=s[j]=l[i++]; if (!(hkfl&2) && c=='\"') hkfl^=1; if (!comcom && !(hkfl&1) && c=='\'') hkfl^=2; if (c==';' && !hkfl) { comcom = 1; } if (c=='\0') { // end of line break; /* hkfl = comcom = 0 */ } if (c==':' && !hkfl) { /* if the next char is a "=" - so that we have a ":=" - and we we have ca65 compatibility, we ignore the colon */ // also check for ":+" and ":-" if (((!startofline) && l[i]!='=' && l[i]!='+' && l[i]!='-') || !ca65 || comcom) { /* but otherwise we check if it is in a comment and we have MASM or CA65 compatibility, then we ignore the colon as well */ if(!comcom || !(masm || ca65)) { /* we found a colon, so we keep the current line in memory but return the part before the colon, and next time the part after the colon, so we can parse C64 BASIC text assembler... */ gl=1; break; } } } if (!isspace(c)) { startofline = 0; } j++; } while (c!='\0' && jalign)?a:align; } static void lineout(void) { if(gf) { logout(filep->flinep); logout("\n"); gf=0; } } void errout(int er) { if (er<=-ANZERR || er>-1) { if(er>=-(ANZERR+ANZWARN) && er <= -ANZERR) { sprintf(out,"%s:line %d: %04x: Warning - %s\n", filep->fname, filep->fline, pc[segment], ertxt[(-er)-1]); } else { /* sprintf(out,"%s:Zeile %d: %04x:Unbekannter Fehler Nr.: %d\n",*/ sprintf(out,"%s:line %d: %04x: Unknown error # %d\n", filep->fname,filep->fline,pc[segment],er); ner++; } } else { if (er==E_NODEF) sprintf(out,"%s:line %d: %04x:Label '%s' not defined\n", filep->fname,filep->fline,pc[segment],lz); else sprintf(out,"%s:line %d: %04x:%s error\n", filep->fname,filep->fline,pc[segment],ertxt[(-er)-1]); ner++; } logout(out); } static void chrput(int c) { /* printf(" %02x",c&255);*/ putc( c&0x00ff,fpout); } void logout(char *s) { fprintf(stderr, "%s",s); if(fperr) fprintf(fperr,"%s",s); } /*****************************************************************/ typedef struct { char *name; int *flag; } compat_set; static compat_set compat_sets[] = { { "MASM", &masm }, { "CA65", &ca65 }, { "C", &ctypes }, { "XA23", &xa23 }, { NULL, NULL } }; int set_compat(char *compat_name) { int i = 0; while (compat_sets[i].name != NULL) { if (strcmp(compat_sets[i].name, compat_name) == 0) { /* set appropriate compatibility flag */ (*compat_sets[i].flag) = 1; /* warn on old versions of xa */ if (xa23) fprintf(stderr, "Warning: -XXA23 is explicitly deprecated\n"); return 0; } i++; } return -1; } xa-2.4.0/src/xa.h0000600000031500000010000000304514514131703013000 0ustar spectrestaff/* 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 */ #define progmajor "2" #define progminor "4" #define progpatch "0" #define progversion progmajor "." progminor "." progpatch extern int ncmos, cmosfl, w65816, n65816; extern int masm, ca65, xa23, nolink, undefok; extern int noglob; extern int showblk; extern int relmode; extern int crossref; extern int ctypes; 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__ */ xa-2.4.0/src/xaa.c0000600000031500000010000001634714517116621013152 0ustar spectrestaff/* 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 #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,P_EQU,P_START }; 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 if(s[pp]!=T_END) { 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); } else { er = E_SYNTAX; } *l=pp; //fprintf(stderr, "a_term: nolink=%d, noundef=%d ->er=%d; l=%d, pp=%d, afl->%04x *pfl=%04x, (pc=%04x)\n",nolink, noundef ,er, *l, pp, 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; //fprintf(stderr, "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(0) /* NYI: this is hacked into .assert for now */ if(s[pp]==18) /* logical not */ { pp++; if(!(er=ag_term(s,P_START,v,&afl,label))) { if(s[pp]!=')') er=E_SYNTAX; else pp++; } *v = !(*v); } else #endif 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) || (afl==SEG_UNDEFZP))) { er = E_OK; *v = 0; if(afl!=SEG_UNDEFZP) { afl = SEG_UNDEF; } *label = cval(s+pp+1); } } pp+=3; } else if(s[pp]==T_VALUE || s[pp] == T_CAST) { while (s[pp] == T_CAST) { pp+=2; } *v=lval(s+pp+1); pp+=5; /* printf("value: v=%04x\n",*v); */ } else if(s[pp]==T_POINTER) { afl = s[pp+1]; *v=cval(s+pp+2); pp+=6; /* 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 && s[pp]!=T_COMMENT) { //fprintf(stderr, "ag_term while: s[pp=%d]=%02x\n", pp, s[pp]); 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_UNDEFZP) && (afl!=SEG_UNDEF) && o==2) { afl = 0; /* subtract 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); /* subtract constant from pointer */ } else { if((!afl && *nafl) && o==2) { /* subtract pointer from constant */ errout(W_SUBTRACT); } /* allow math in the same segment */ if(segment!=SEG_ABS && segment != afl) { if(!dsb_len) { /*printf("ILLPOINTER=dsb_len=%d,segment=%d\n",dsb_len, segment);*/ /* e.g. adding two pointers, adding two undefined values */ er=E_ILLSEGMENT; } } 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) { /* printf("*o=%d, pp=%d, s=%s\n", *o, pp, s); for (int i=0; i< 10; i++) { printf(" %02x", s[i]); } printf("\n"); */ 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 (w2!=0) *w /=w2; else er =E_DIV; break; case 5: *w >>=w2; break; case 6: *w <<=w2; break; case 7: *w = *ww2; 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); } xa-2.4.0/src/xaa.h0000600000031500000010000000203714513025305013140 0ustar spectrestaff/* 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__ */ xa-2.4.0/src/xacharset.c0000644000031500000010000000566414514122203014361 0ustar spectrestaff/* 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 #include #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); } xa-2.4.0/src/xacharset.h0000644000031500000010000000223014513025305014354 0ustar spectrestaff/* 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__ */ xa-2.4.0/src/xad.h0000644000031500000010000000270514513025326013160 0ustar spectrestaff/* 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, f) do { \ t[i++] = T_VALUE; \ t[i++] = v & 255; \ t[i++] = (v >> 8) & 255; \ t[i++] = (v >> 16) & 255; \ t[i++] = f & 255; \ } while (0) #endif /* __XA65_XAD_H__ */ xa-2.4.0/src/xah.h0000600000031500000010000002047714517116714013170 0ustar spectrestaff/* 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__ /* * Note: the computations to get the number of bytes necessary to allocate are * a historic remnant of the Atari ST (the original platform) not being able to efficiently allocate small chunks * of memory so I had to allocate a large chunk myself and manage the tables myself. * This has changed and some parts of xa65 are modified to just do a malloc() now. * These fixed numbers should actually go away. AF 20110623 */ #define ANZLAB 5000 /* multiplied by sizeof(Labtab) -> Byte */ #define LABMEM 40000L #define MAXLAB 32 #define MAXBLK 16 #define MAXFILE 7 #define MAXLINE 2048 #define MAXPP 40000L #define ANZDEF 2340 /* multiplied by sizeof(List) -> Byte, ANZDEF * 20 < 32768 */ #define TMPMEM 2000000L /* temporary memory buffer from Pass1 to Pass 2 (includes all source, thus enlarged) */ typedef enum { STD = 0, CHEAP = 1, UNNAMED = 2, UNNAMED_DEF = 3 } xalabel_t; typedef struct LabOcc { struct LabOcc *next; int line; char *fname; } LabOcc; /** * struct that defines a label, after it has been parsed */ typedef struct { int blk; int origblk; // only for fl=3 int val; int len; int fl; /* 0 = label value not valid/known, * 1 = label value known * 2 = label value not known, external global label (imported on link) * 3 = label value not known, temporarily on external global label list (for -U) */ int afl; /* 0 = no address (no relocation), 1 = address label */ int nextindex; xalabel_t is_cll; /* 0 is normal label, 1 is cheap local label (used for listing) */ char *n; struct LabOcc *occlist; // within a block, make a linked list for the unnamed label counting // use indexes, as the label table can be re-alloced (so pointers change) // -1 is the "undef'd" end of list int blknext; int blkprev; } 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 /* No error */ #define E_SYNTAX -1 /* Syntax error */ #define E_LABDEF -2 /* Label already defined (duplicate label definition) */ #define E_NODEF -3 /* Label not defined */ #define E_LABFULL -4 /* Label table full */ #define E_LABEXP -5 /* Label expected but not found */ #define E_NOMEM -6 /* out of memory */ #define E_ILLCODE -7 /* Illegal Opcode */ #define E_ADRESS -8 /* Illegal Addressing mode */ #define E_RANGE -9 /* Branch out of range */ #define E_OVERFLOW -10 /* overflow */ #define E_DIV -11 /* Division by zero */ #define E_PSOEXP -12 /* Pseudo-Opcode expected but not found */ #define E_BLKOVR -13 /* Block-Stack overflow */ #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 */ #define E_UERROR -37 /* #error */ #define E_AERROR -38 /* .assert failed */ #define E_NEGDSBLEN -39 /* .dsb has negative length */ /* errors thru 64 are placeholders available for use */ #define W_ADRRELOC -65 /* word relocation in byte value */ #define W_BYTRELOC -66 /* byte relocation in word value */ #define E_WPOINTER -67 /* illegal pointer arithmetic! */ #define W_ADDRACC -68 /* addr access to low or high byte pointer */ #define W_HIGHACC -69 /* high byte access to low byte pointer */ #define W_LOWACC -70 /* low byte access to high byte pointer */ #define W_FORLAB -71 /* no zp-optimization for a forward label */ #define W_OPENPP -72 /* warning about open preprocessor directive */ #define W_OVER64K -73 /* included binary over 64K in 6502 mode */ #define W_OVER16M -74 /* included binary over 16M in 65816 mode */ #define W_SUBTRACT -75 /* subtract a segment pointer from a constant - not supported in -R mode */ /* warnings 75-77 are placeholders available for use */ /* Meta-values for the token list. Note must not overlap with the * K* definitions in xat.c, which have outgrown the positive numbers * and are now growing up from -128 ... */ #define T_VALUE -1 /* following is a 24 bit value in the token list */ #define T_LABEL -2 /* referring to a label, following the token is the 16bit label number */ #define T_OP -3 /* label oriented operation; following is the label number (16bit), plus the operation char (e.g. '+') */ #define T_END -4 /* end of line marker */ #define T_LINE -5 /* new line indicator; following is the 16 bit line number */ #define T_FILE -6 /* new file indicator; following is the 16 bit line number, then the file name (zero-term) */ #define T_POINTER -7 /* ??? */ #define T_COMMENT -8 /* unused */ #define T_DEFINE -9 /* define a label; inserted at conversion and discarded in pass1, only used in listing output */ #define T_LISTING -10 /* meta token, inserted after conversion before pass1, used after pass2 to create listing */ #define T_CAST -11 /* token inserted for a cast */ #define P_START 0 /* arithmetic operation priorities */ #define P_LOR 1 /* of any two operations, the one with */ #define P_LAND 2 /* the higher priority will be done first */ #define P_OR 3 #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 #define SEG_UNDEFZP 7 /* is being mapped to UNDEF */ 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 { // temporary memory between pass1 and pass2 signed char *tmp; // write pointer unsigned long tmpz; // read pointer 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__ */ xa-2.4.0/src/xah2.h0000600000031500000010000000200614513025305013225 0ustar spectrestaff/* 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__ */ xa-2.4.0/src/xal.c0000600000031500000010000005053314520744437013166 0ustar spectrestaff/* 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 #include #include #include /* 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, xalabel_t ltype); static int b_link(int); static int b_new(void); static void cll_init(); static int cll_get(); static void cll_clear(); static int cll_getcur(); static Labtab *ltp; int l_init(void) { cll_init(); //unn_init(); return 0; } 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;ila.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; } } /********************************************************************************** * cheap local labels */ static int cll_current = 0; /* the current cheap local labels block */ /** * init the cheap local labels */ void cll_init() { cll_current = 0; } /** * get the block number for a new cheap local label block */ int cll_get() { if (cll_current == 0) { cll_current = b_new(); } return cll_current; } /** * clear the local labels */ void cll_clear() { cll_current = 0; } int cll_getcur() { return cll_current; } /**********************************************************************************/ /** * define a global label (from the "-L" command line parameter) */ int lg_set(char *s ) { int n, er; er = ll_search(s,&n, STD); if(er==E_OK) { fprintf(stderr,"Warning: global label doubly defined!\n"); } else { if(!(er=ll_def(s,&n,0, STD))) { return lg_import(n); } } return er; } /** * define a global label (from the .import pseudo opcode)) * "s" is a pointer to the first label character, end is at \0 * or at non-alphanumeric/_ char */ int lg_import(int n) { int er=E_OK; ltp=afile->la.lt+n; ltp->fl=2; ltp->afl=SEG_UNDEF; return er; } /* * re-define a previously undef'd label as globally undefined * (for -U option) */ int lg_toglobal(char *s ) { int n, er; //printf("lg_toglobal(%s)\n", s); er = ll_search(s,&n, STD); if(er==E_OK && ltp->fl != 3) { // fonnd, but not yet set as global undef'd label ltp=afile->la.lt+n; ltp->fl=3; ltp->afl=SEG_UNDEF; ltp->origblk=ltp->blk; ltp->blk=0; } return er; } /** * define a global zeropage label (from the .importzp pseudo opcode)) * "s" is a pointer to the first label character, end is at \0 * or at non-alphanumeric/_ char */ int lg_importzp(int n) { int er=E_OK; ltp=afile->la.lt+n; ltp->fl=2; ltp->afl=SEG_UNDEFZP; return er; } /**********************************************************************************/ int l_def(char *s, int *l, int *x, int *f) { int n,er,b,i=0; xalabel_t cll_fl; *f=0; /* flag (given as param) that the label is to be re-defined and the "label defined error" is to be skipped */ b=0; /* block level on block stack, resp. block number */ n=0; /* flag, when set, b is absolute block number and not being translated */ cll_fl=STD; /* when 0, clear the cheap local label block */ if(s[0]==':') { // ca65 unnamed label i++; //n++; /* block number b is absolute */ //b=unn_get(); /* current (possibly newly allocated) unnamed label block */ cll_fl = UNNAMED; // keep the cheap local label block } else if(s[0]=='-') { *f+=1; /* label is being redefined */ i++; } else if(s[0]=='@') { i++; n++; /* block number b is absolute */ b=cll_get(); /* current (possibly newly allocated) cheap label block */ cll_fl=CHEAP; /* do not clear the cll block again... */ } else if(s[0]=='+') { i++; n++; /* block number b is absolute */ b=0; /* global block number */ } while(s[i]=='&') { if (n) b=0; /* reset block number */ n=0; /* block number is relative */ i++; b++; /* one (more) level up the block stack */ } if(!n) { /* translate from block stack level to absolute block number */ b_fget(&b,b); } if(cll_fl == STD) { /* clear cheap local labels */ cll_clear(); } if((!isalpha(s[i])) && (s[i]!='_') && !(ca65 && ((cll_fl == UNNAMED) || isdigit(s[i])) ) ) { //printf("SYNTAX cll_fl=%d, i=%d, s[i]=%02x (%c)\n", cll_fl, i, s[i], s[i]); er=E_SYNTAX; } else { er = E_NODEF; if (cll_fl != UNNAMED) { er=ll_search(s+i,&n, cll_fl); } if(er==E_OK) { //printf("l_def OK: cll_fl=%d, i=%d, s=%s\n", cll_fl, i, s); /* we actually found an existing label in the same scope */ ltp=afile->la.lt+n; if(*f) { /* redefinition of label */ *l=ltp->len+i; } else if(ltp->fl == 0) { /* label has not been defined yet, (e.g. pass1 forward ref), so we try to set it. */ *l=ltp->len+i; if(b_ltest(ltp->blk,b)) er=E_LABDEF; else ltp->blk=b; } else if(ltp->fl == 3) { /* label has been defined as -U undef'd label so far - we need to check */ *l=ltp->len+i; if(b_ltest(ltp->origblk,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, cll_fl) )) /* store the label in the table of labels */ { ltp=afile->la.lt+n; *l=ltp->len+i; ltp->fl=0; ltp->is_cll=cll_fl; } //printf("l_def NODEF: n=%d, s=%s\n", n, ltp->n); } *x=n; } return(er); } int l_search(char *s, int *l, int *x, int *v, int *afl) { int n,er,b; xalabel_t cll_fl; *afl=0; /* check cheap local label */ cll_fl=STD; if (s[0]=='@') { cll_fl=CHEAP; s++; } else if (s[0]==':') { cll_fl = UNNAMED_DEF; s++; } er = E_NODEF; if (cll_fl != UNNAMED_DEF) { er=ll_search(s,&n, cll_fl); } //printf("l_search: lab=%s(afl=%d, er=%d, cll_fl=%d, cll_cur=%d)\n",s,*afl,er, cll_fl, cll_getcur()); if(er==E_OK) { ltp=afile->la.lt+n; *l=ltp->len + ((cll_fl == STD) ? 0 : 1); 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 { if(cll_fl == CHEAP) { b=cll_get(); } else if(cll_fl == UNNAMED_DEF) { b_get(&b); // b=unn_get(); } else { b_get(&b); } er=ll_def(s,x,b, cll_fl); /* ll_def(...,*v); */ ltp=afile->la.lt+(*x); ltp->is_cll = cll_fl; *l=ltp->len + ((cll_fl == STD) ? 0 : 1); //*l=ltp->len + cll_fl; 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; } } /* for the list functionality */ char *l_get_name(int n, xalabel_t *is_cll) { if (n > afile->la.ltm) { fprintf(stderr, "Corrupted structures! n=%d, but max=%d\n", n, afile->la.ltm); exit(1); } ltp=afile->la.lt+n; *is_cll = ltp->is_cll; return ltp->n; } // works on the static(!) ltp "label table pointer" // also returns the actual index in the table of the current ltp static int resolve_unnamed() { // need to count up/down in the linkd label list for the block char *namep = ltp->n; int nextp = -1; //printf("::: unnamed_def: %s, n=%d\n", namep, n); while ((*namep == '+') || (*namep == '-')) { char c = *namep; nextp = -1; if (c == '+') { nextp = ltp->blknext; } else if (c == '-') { nextp = ltp->blkprev; } //printf("::: nextp=%d\n", nextp); if (nextp == -1) { return -1; // E_NODEF } ltp = afile->la.lt+nextp; //printf("::: leads to: %s, nextp=%d\n", ltp->n, nextp); if (ltp->is_cll == UNNAMED) { namep++; } } return nextp; } /* for the listing, esp. html links; returns a pointer to a static buffer, available till next call */ char *l_get_unique_name(int n) { static char buf[MAXLINE]; ltp=afile->la.lt+n; if (ltp->is_cll == CHEAP || ltp->is_cll == STD) { sprintf(buf, "%d%c%s", ltp->blk, (ltp->is_cll == CHEAP) ? 'C' : '_', ltp->n); } else if (ltp->is_cll == UNNAMED) { // definition of unnamed label - name is NULL // so use the actual index sprintf(buf, "%dU%d", ltp->blk, n); } else if (ltp->is_cll == UNNAMED_DEF) { // we actually need to find the correct label from the "+" and "-" // in the name int tmp = resolve_unnamed(); if (tmp >= 0) { sprintf(buf, "%dU%d", ltp->blk, tmp); } else { sprintf(buf, "__%d", tmp); } } else { buf[0] = 0; // no value } return buf; } int l_get(int n, int *v, int *afl) { if(crossref) l_addocc(n,v,afl); ltp = afile->la.lt+n; if (ltp->is_cll == UNNAMED_DEF) { int tmp = resolve_unnamed(); if (tmp == -1) return E_NODEF; // now ltp is set to the actual label } (*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;ila.lti;i++) { ltp=afile->la.lt+i; if((!ltp->fl) && (ltp->blk==a)) ltp->blk=b; } } /* defines next label, returns new label number in out param n */ static int ll_def(char *s, int *n, int b, xalabel_t ltype) { int j=0,er=E_NOMEM,hash; char *s2 = NULL; //printf("ll_def: s=%s, ltype=%d, no_name=%d\n",s, ltype, no_name); // label table for the file ... if(!afile->la.lt) { // ... does not exist yet, so malloc it afile->la.lti = 0; afile->la.ltm = 1000; afile->la.lt = malloc(afile->la.ltm * sizeof(Labtab)); } if(afile->la.lti>=afile->la.ltm) { // ... or is at its capacity limit, so realloc it 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); } // current pointer in label table ltp = afile->la.lt + afile->la.lti; if (ltype != UNNAMED) { // alloc space and copy over name if (ltype == UNNAMED_DEF) { // unnamed lables are like ":--" or ":+" with variable length while((s[j]!='\0') && (s[j]=='+' || s[j]=='-')) j++; } else { // standard (and cheap) labels are normal text 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; } // init new entry in label table er=E_OK; ltp->len=j; // length of label ltp->n = s2; // name of label (char*) ltp->blk=b; // block number ltp->fl=0; ltp->afl=0; ltp->is_cll=ltype; // STD, CHEAP, or UNNAMED label ltp->occlist=NULL; hash=hashcode(s,j); // compute hashcode ltp->nextindex=afile->la.hashindex[hash]; // and link in before last entry with same hashcode afile->la.hashindex[hash]=afile->la.lti; // set as start of list for that hashcode // TODO: does not work across files! ltp->blknext = -1; // no next block ltp->blkprev = b_link( afile->la.lti ); // previous block, linked within block if (ltp->blkprev != -1) { ltp = afile->la.lt + ltp->blkprev; ltp->blknext = afile->la.lti; } *n=afile->la.lti; // return the list index for that file in the out parameter n afile->la.lti++; // increase last index in lable table return(er); } /** * search a label name in the label table. Return the label number * in "n". Finds only labels that are in a block that is in the current * set of blocks (in the block stack) * * If cll_fl is set, the label is also searched in the local cheap label scope * * Do not define the label (as is done in l_search()!) */ int ll_search(char *s, int *n, xalabel_t cll_fl) /* 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]; if(i>=afile->la.ltm) return E_NODEF; do { ltp=afile->la.lt+i; if(j==ltp->len) { for (k=0;(kn[k]==s[k]);k++); if (cll_fl == CHEAP) { if (ltp->blk == cll_getcur()) { er=E_OK; break; } } else if (cll_fl == UNNAMED) { // TODO } else { //printf("ll_search:match labels %s with %p (%s) from block %d, block check is %d\n", s, ltp, ltp->n, ltp->blk, b_test(ltp->blk)); /* check if the found label is in any of the blocks in the current block stack */ if((j==k)&&(!b_test(ltp->blk))) { /* ok, label found and it is reachable (its block nr is in the current block stack */ 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 //printf("l_search(%s) returns er=%d, n=%d\n", s, er, *n); return(er); } int ll_pdef(char *t) { int n; if(ll_search(t,&n, STD)==E_OK) { ltp=afile->la.lt+n; if(ltp->fl) return(E_OK); } return(E_NODEF); } /* * Write out the list of global labels in an o65 file */ int l_write(FILE *fp) { int i, afl, n=0; if(noglob) { fputc(0, fp); fputc(0, fp); return 0; } // calculate number of global labels for (i=0;ila.lti;i++) { ltp=afile->la.lt+i; if((!ltp->blk) && (ltp->fl==1)) { n++; } } // write number of globals to file fputc(n&255, fp); fputc((n>>8)&255, fp); // iterate over labels and write out label for (i=0;ila.lti;i++) { ltp=afile->la.lt+i; if((!ltp->blk) && (ltp->fl==1)) { // write global name fprintf(fp, "%s",ltp->n); fputc(0,fp); // segment byte afl = ltp->afl; // hack to switch undef and abs flag from internal to file format // if asolute of undefined (< SEG_TEXT, i.e. 0 or 1) // then invert bit 0 (0 = absolute) if( (afl & (A_FMASK>>8)) < SEG_TEXT) { afl^=1; } // remove residue flags, only write out real segment number // according to o65 file format definition afl = afl & (A_FMASK >> 8); fputc(afl,fp); // value fputc(ltp->val&255, fp); fputc((ltp->val>>8)&255, fp); } } /*fputc(0,fp);*/ return 0; } /******************************************************************************************* * block management code. Here the ".(" and ".)" blocks are maintained. * * Blocks are numbered uniquely, every time a new block is opened, the "blk" variable * is increased and its number used as block number. * * The currently open blocks are maintained in a stack (bt[]). The lowest entry is the outermost * block number, adding block numbers as blocks are opened. When a block is closed, * the block stack is shortened again (bi has the length of the block stack) * * Methods exist to open new blocks, close a block, and do some checks, e.g. whether * a specific block number is contained in the current block stack. */ static int bt[MAXBLK]; /* block stack */ static int labind; /* last allocated label, -1 none yet alloc'd - used for linking to find unnamed labels */ static int bi; /* length of the block stack (minus 1, i.e. bi[bi] has the innermost block) */ static int blk; /* current block number for allocation */ int b_init(void) { blk =0; bi =0; bt[bi]=blk; labind=-1; return(E_OK); } int b_new(void) { return ++blk; } int b_depth(void) { return bi; } int ga_blk(void) { return(blk); } /** * open a new block scope */ int b_open(void) { int er=E_BLKOVR; if(bi=0) *n=bt[bi-i]; else *n=0; return(E_OK); } /** * tests whether the given block number n is in the current stack of * current block numbers bt[] */ static int b_test(int n) { int i=bi; while( i>=0 && n!=bt[i] ) i--; return( i+1 ? E_OK : E_NOBLK ); } /** * tests whether the given block number "a" is in the */ 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); } int b_link(int newlab) { int tmp = labind; //printf("b_link: old was %d, set to %d\n", tmp, newlab); labind = newlab; return tmp; } xa-2.4.0/src/xal.h0000600000031500000010000000354214513031270013153 0ustar spectrestaff/* 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 /* for FILE */ /* nasty stuff - "lz" is exported from xal.c so xa.c can print the name * of the label that was last searched for in the error message that the * label was not found... */ 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 lg_import(int); int lg_importzp(int); // used to re-define undef'd labels as global for -U option int lg_toglobal(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); char* l_get_name(int n, xalabel_t *is_cll); char* l_get_unique_name(int n); 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, xalabel_t labeltype); int ll_pdef(char *t); int b_open(void); int b_close(void); int l_write(FILE *fp); #endif /* __XA65_XAL_H__ */ xa-2.4.0/src/xalisting.c0000644000031500000010000004437214524565763014427 0ustar spectrestaff/* xa65 - 65xx/65816 cross-assembler and utility suite * * Copyright (C) 1989-1997 André Fachat (a.fachat@physik.tu-chemnitz.de) * maintained by Cameron Kaiser * * Assembler listing * * 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. */ /* enable this to turn on (copious) optimization output */ /* #define DEBUG_AM */ #undef LISTING_DEBUG #include #include #include "xah.h" #include "xal.h" #include "xat.h" /*********************************************************************************************/ /* this is the listing code * * Unfortunately this code has to go here (for now), as this file is the only one * where we have access to the tables that allow to convert the tokens back to * a listing */ static FILE *listfp = NULL; static int list_lineno = 1; /* current line number */ static int list_last_lineno = 0; /* current line number */ static char *list_filenamep = NULL; /* current file name pointer */ static int list_numbytes = 8; static int list_string(char *buf, char *string); static int list_tokens(char *buf, signed char *input, int len); static int list_value(char *buf, int val, signed char format); static int list_nchar(char *buf, signed char c, int n); static int list_char(char *buf, signed char c); static int list_sp(char *buf); static int list_word(char *buf, int outword); static int list_word_f(char *buf, int outword, signed char format); static int list_byte(char *buf, int outbyte); static int list_byte_f(char *buf, int outbyte, signed char format); static int list_nibble_f(char *buf, int outnib, signed char format); /*********************************************************************************************/ // formatter typedef struct { void (*start_listing)(char *name); void (*start_line)(); int (*set_anchor)(char *buf, char *name); // returns number of bytes added to buf int (*start_label)(char *buf, char *name); // returns number of bytes added to buf int (*end_label)(char *buf); void (*end_line)(); void (*end_listing)(); char* (*escape)(char *toescape); // returns pointer to static buffer, valid until next call char* (*escape_char)(char toescape); // returns pointer to static buffer, valid until next call } formatter_t; static char *def_escape(char *toescape) { return toescape; } static char *def_escape_char(char toescape) { static char buf[2]; buf[0] = toescape; buf[1] = 0; return buf; } static formatter_t def_format = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, def_escape, def_escape_char }; static void html_start_listing(char *name) { // really short version for now fprintf(listfp, "%s
\n", 
		(name == NULL) ? "(null)" : name);
}

static int html_set_anchor(char *buf, char *name) {
	sprintf(buf, " ", name);
	return strlen(buf);
}

static int html_start_label(char *buf, char *name) {
	sprintf(buf, "", name);
	return strlen(buf);
}

static int html_end_label(char *buf) {
	sprintf(buf, "");
	return strlen(buf);
}

static void html_end_listing() {
	fprintf(listfp, "
\n"); } static char *html_escape(char *toescape) { static char buf[MAXLINE]; char *p = toescape; char *q = buf; while (*p != 0) { if (*p == '<') { strcpy(q, "<"); q+=4; p++; } else if (*p == '&') { strcpy(q, "&"); q+=5; p++; } else if (*p == '>') { strcpy(q, ">"); q+=4; p++; } else { *q = *p; q++; p++; } } *q = 0; // string terminator return buf; } static char *html_escape_char(char toescape) { static char buf[2]; buf[0] = toescape; buf[1] = 0; return html_escape(buf); } static formatter_t html_format = { html_start_listing, NULL, html_set_anchor, html_start_label, html_end_label, NULL, html_end_listing, html_escape, html_escape_char }; static formatter_t *formatp = &def_format; /*********************************************************************************************/ void list_flush() { if (listfp != NULL) { fflush(listfp); } } void list_start(const char *formatname) { formatp = &def_format; if (formatname != NULL && strcmp("html", formatname) == 0) { formatp = &html_format; } if (listfp != NULL) { if (formatp->start_listing != NULL) formatp->start_listing(list_filenamep); } } void list_end() { if (listfp != NULL) { if (formatp->end_listing != NULL) formatp->end_listing(); } } // set number of bytes per line displayed as hex void list_setbytes(int number_of_bytes_per_line) { list_numbytes = number_of_bytes_per_line; } /* set line number for the coming listing output */ void list_line(int l) { list_lineno = l; } /* set file name for the coming listing output */ void list_filename(char *fname) { if (list_filenamep == NULL || (fname != NULL && strcmp(fname, list_filenamep) != 0)) { list_filenamep = fname; list_lineno = 1; list_last_lineno = 0; /* Hack */ if (listfp != NULL) { fprintf(listfp, "\n%s\n\n", fname); } } } /** * set the output file descriptor where to write the listing */ void list_setfile(FILE *fp) { listfp = fp; } char *list_preamble(char *buf, int lineno, int seg, int pc) { int i; char c; /* line number in file */ snprintf(buf, 10, "% 5d", lineno); i = strlen(buf); buf += i; buf += list_char(buf, ' '); c = '?'; /* preamble ':'
' ' */ switch(seg) { case SEG_ABS: c='A'; break; case SEG_TEXT: c='T'; break; case SEG_BSS: c='B'; break; case SEG_DATA: c='D'; break; case SEG_UNDEF: c='U'; break; case SEG_ZERO: c='Z'; break; } buf = buf + list_char(buf, c); buf = buf + list_char(buf, ':'); buf = buf + list_word(buf, pc); buf = buf + list_nchar(buf, ' ', 2); return buf; } /** * listing/listing_len give the buffer address and length respectively that contains * the token as they are produced by the tokenizer. * bincode/bincode_len give the buffer address and length that contain the binary code * that is produced from the token listing * * Note that both lengths may be zero */ void do_listing(signed char *listing, int listing_len, signed char *bincode, int bincode_len) { int i, n_hexb, num_last_line, tmp, overflow; char outline[MAXLINE]; char *buf = outline; int lst_seg = listing[0]; int lst_pc = (listing[2]<<8) | (listing[1] & 255); /* no output file (not even stdout) */ if (listfp == NULL) return; /*printf("do_listing: listing=%p (%d), bincode=%p (%d)\n", listing, listing_len, bincode, bincode_len);*/ if (bincode_len < 0) bincode_len = -bincode_len; /* do we need a separation line? */ if (list_lineno > list_last_lineno+1) { /* yes */ /*fprintf(listfp, "line=%d, last=%d\n", list_lineno, list_last_lineno);*/ fprintf(listfp, "\n"); } list_last_lineno = list_lineno; // could be extended to include the preamble... if (formatp->start_line != NULL) formatp->start_line(); buf = list_preamble(buf, list_lineno, lst_seg, lst_pc); // check if we have labels, so we can adjust the max printable number of // bytes in the last line num_last_line = 11; tmp = listing[3] & 255; if (tmp == (T_DEFINE & 255)) { // we have label definition num_last_line = 8; } overflow = 0; /* binary output (up to 8 byte. If more than 8 byte, print 7 plus "..." */ n_hexb = bincode_len; if (list_numbytes != 0 && n_hexb >= list_numbytes) { n_hexb = list_numbytes-1; overflow = 1; } for (i = 0; i < n_hexb; i++) { buf = buf + list_byte(buf, bincode[i]); buf = buf + list_sp(buf); if ( (i%16) == 15) { // make a break buf[0] = 0; fprintf(listfp, "%s\n", outline); if (formatp->end_line != NULL) formatp->end_line(); if (formatp->start_line != NULL) formatp->start_line(); buf = outline; buf = list_preamble(buf, list_lineno, lst_seg, lst_pc + i + 1); } } if (overflow) { // are we at the last byte? if (n_hexb + 1 == bincode_len) { // just print the last byte buf = buf + list_byte(buf, bincode[i]); buf = buf + list_sp(buf); } else { // display "..." buf = buf + list_nchar(buf, '.', 3); } n_hexb++; } i = n_hexb % 16; if (i > num_last_line) { // make a break (Note: with original PC, as now the assembler text follows buf[0] = 0; fprintf(listfp, "%s\n", outline); if (formatp->end_line != NULL) formatp->end_line(); if (formatp->start_line != NULL) formatp->start_line(); buf = outline; buf = list_preamble(buf, list_lineno, lst_seg, lst_pc); i = 0; } i = num_last_line - i; buf = buf + list_nchar(buf, ' ', i * 3); buf = buf + list_sp(buf); buf += list_tokens(buf, listing + 3, listing_len - 3); #ifdef LISTING_DEBUG /* for now only do a hex dump so we see what actually happens */ { char valbuf[32]; i = buf - outline; if (i<80) buf += list_nchar(buf, ' ', 80-i); buf += list_string(buf, " >>"); sprintf(valbuf, "%p", listing+3); buf += list_string(buf, valbuf); buf += list_sp(buf); for (i = 3; i < listing_len; i++) { buf = buf + list_byte(buf, listing[i]); buf = buf + list_sp(buf); } } #endif buf[0] = 0; fprintf(listfp, "%s\n", outline); if (formatp->end_line != NULL) formatp->end_line(); } int list_tokens(char *buf, signed char *input, int len) { int outp = 0; int inp = 0; int tmp; char *name; signed char c; xalabel_t is_cll; int tabval, operator; signed char format; if (inp >= len) return 0; tmp = input[inp] & 255; tabval = 0; if (tmp == (T_DEFINE & 255)) { while (inp < len && tmp == (T_DEFINE & 255)) { tmp = ((input[inp+2]&255)<<8) | (input[inp+1]&255); /*printf("define: len=%d, inp=%d, tmp=%d\n", len, inp, tmp);*/ name=l_get_name(tmp, &is_cll); // duplicate anchor names? if (formatp->set_anchor != NULL) { outp += formatp->set_anchor(buf+outp, l_get_unique_name(tmp)); } if (is_cll == CHEAP) { outp += list_char(buf+outp, '@'); } else if (is_cll == UNNAMED_DEF || is_cll == UNNAMED) { outp += list_char(buf+outp, ':'); } if (is_cll != UNNAMED) { tmp = list_string(buf+outp, name); tabval += tmp + 1 + is_cll; outp += tmp; } outp += list_char(buf+outp, ' '); inp += 3; tmp = input[inp] & 255; } if (tabval < 10) { outp += list_nchar(buf+outp, ' ', 10-tabval); } } else { if (tmp >= 0 && tmp < number_of_valid_tokens) { outp += list_string(buf+outp, " "); } } if (tmp >= 0 && tmp < number_of_valid_tokens) { /* assembler keyword */ /*printf("tmp=%d, kt[tmp]=%p\n", tmp, kt[tmp]);*/ if (kt[tmp] != NULL) { outp += list_string(buf+outp, kt[tmp]); } outp += list_sp(buf + outp); inp += 1; #if 0 if (tmp == Kinclude) { /* just another exception from the rule... */ /* next char is terminator (", ') then the length and then the file name */ char term = input[inp]; int len = input[inp+1] & 255; outp += list_char(buf+outp, term); for (tmp = 2; tmp < len+2; tmp++) { outp += list_char(buf+outp, input[inp+tmp]); } outp += list_char(buf+outp, term); inp += len + 2; } #endif } operator = 0; while (inp < len) { switch(input[inp]) { case T_CAST: outp += list_string(buf+outp, formatp->escape_char(input[inp+1])); inp+=2; break; case T_VALUE: /*outp += list_char(buf+outp, 'V');*/ /* 24 bit value */ tmp = ((input[inp+3]&255)<<16) | ((input[inp+2]&255)<<8) | (input[inp+1]&255); format = input[inp+4]; outp += list_value(buf+outp, tmp, format); inp += 5; operator = 1; /* check if arithmetic operator follows */ break; case T_LABEL: /*outp += list_char(buf+outp, 'L');*/ /* 16 bit label number */ tmp = ((input[inp+2]&255)<<8) | (input[inp+1]&255); name=l_get_name(tmp, &is_cll); // duplicate label name if (formatp->start_label != NULL) { outp += formatp->start_label(buf+outp, l_get_unique_name(tmp)); } if (is_cll == CHEAP) { outp += list_char(buf+outp, '@'); } else if (is_cll == UNNAMED || is_cll == UNNAMED_DEF) { outp += list_char(buf+outp, ':'); } if (is_cll != UNNAMED) { outp += list_string(buf+outp, name == NULL ? "" : name); } if (formatp->end_label != NULL) outp += formatp->end_label(buf+outp); inp += 3; operator = 1; /* check if arithmetic operator follows */ break; case T_OP: /* label arithmetic operation; inp[3] is operation like '=' or '+' */ tmp = ((input[inp+2]&255)<<8) | (input[inp+1]&255); name=l_get_name(tmp, &is_cll); if (input[inp+3] == '=') { // label definition if (formatp->set_anchor != NULL) { outp += formatp->set_anchor(buf+outp, l_get_unique_name(tmp)); } } if (is_cll) outp += list_char(buf+outp, '@'); outp += list_string(buf+outp, name); outp += list_char(buf+outp, input[inp+3]); inp += 4; break; case T_END: /* end of operation */ /*outp += list_string(buf+outp, ";");*/ inp += 1; goto end; break; case T_COMMENT: if (inp > 0 && inp < 20) { outp += list_nchar(buf+outp, ' ', 20-inp); } tmp = ((input[inp+2]&255)<<8) | (input[inp+1]&255); outp += list_char(buf+outp, ';'); outp += list_string(buf+outp, (char*)input+inp+3); inp += tmp + 3; break; case T_LINE: case T_FILE: /* those two are meta-tokens, evaluated outside the t_p2 call, * they result in calls to list_line(), list_filename() */ break; case T_POINTER: /* what is this? It's actually resolved during token conversion */ tmp = ((input[inp+5]&255)<<8) | (input[inp+4]&255); name=l_get_name(tmp, &is_cll); if (formatp->start_label != NULL) { outp += formatp->start_label(buf+outp, l_get_unique_name(tmp)); } if (is_cll) outp += list_char(buf+outp, '@'); outp += list_string(buf+outp, name); if (formatp->end_label != NULL) outp += formatp->end_label(buf+outp); /* outp += list_byte(buf+outp, input[inp+1]); outp += list_char(buf+outp, '#'); tmp = ((input[inp+3]&255)<<8) | (input[inp+2]&255); outp += list_value(buf+outp, tmp); */ inp += 6; operator = 1; /* check if arithmetic operator follows */ break; case '"': { int i, len; // string display inp++; outp += list_char(buf+outp, '"'); len = input[inp] & 0xff; for (i = 0; i < len; i++) { inp++; outp += list_char(buf+outp, input[inp]); } inp++; outp += list_char(buf+outp, '"'); break; } case '*': { // If '*' appears as operand, it is the PC. We need to switch to operator then inp++; outp += list_char(buf+outp, '*'); operator = 1; break; } default: c = input[inp]; if (c > 31) { outp += list_string(buf+outp, formatp->escape_char(input[inp])); } else { outp += list_char(buf+outp, '\''); outp += list_byte(buf+outp, input[inp]); } inp += 1; break; } if (operator && inp < len) { signed char op = input[inp]; if (op > 0 && op <= 20) { // sizeof(arith_ops) outp += list_string(buf+outp, formatp->escape(arith_ops[op])); inp += 1; operator = 0; } // note: falls through for closing brackets which are where an operator would normally be. // closing bracket is then printed in upper (operand) part in default case before // another operator is expected after the bracket } } end: return outp; } int list_string(char *buf, char *string) { int p = 0; if (buf == NULL || string == NULL) { fprintf(stderr, "NULL pointer: buf=%p, string=%p\n", buf, string); fflush(stderr); //exit(1); return 0; } while (string[p] != 0) { buf[p] = string[p]; p++; } return p; } int list_value(char *buf, int val, signed char format) { int p = 0; char valbuf[32]; switch (format) { case '$': p += list_char(buf + p, '$'); if (val & (255<<16)) { p += list_byte(buf+p, val>>16); p += list_word(buf+p, val); } else if (val & (255<<8)) { p += list_word(buf+p, val); } else { p += list_byte(buf+p, val); } break; case '%': p += list_char(buf + p, '%'); if (val & (255<<16)) { p += list_byte_f(buf+p, val>>16,'%'); p += list_word_f(buf+p, val,'%'); } else if (val & (255<<8)) { p += list_word_f(buf+p, val,'%'); } else { p += list_byte_f(buf+p, val,'%'); } break; case '&': snprintf(valbuf, 32, "%o",val); p+= list_char(buf+p, '&'); p+= list_string(buf+p, valbuf); break; case 'd': snprintf(valbuf, 32, "%d",val); p+= list_string(buf+p, valbuf); break; case '\'': case '"': p+= list_char(buf+p, format); p+= list_char(buf+p, val); p+= list_char(buf+p, format); break; default: /* hex format as fallback */ p += list_char(buf + p, '$'); if (val & (255<<16)) { p += list_byte(buf+p, val>>16); p += list_word(buf+p, val); } else if (val & (255<<8)) { p += list_word(buf+p, val); } else { p += list_byte(buf+p, val); } break; } return p; } int list_nchar(char *buf, signed char c, int n) { int i; for (i = 0; i < n; i++) { buf[i]=c; } return n; } int list_char(char *buf, signed char c) { buf[0] = c; return 1; } int list_sp(char *buf) { buf[0] = ' '; return 1; } int list_word(char *buf, int outword) { return list_word_f(buf, outword, '$'); } int list_word_f(char *buf, int outword, signed char format) { int p = 0; p+= list_byte_f(buf+p, outword >> 8, format); p+= list_byte_f(buf+p, outword, format); return p; } int list_byte(char *buf, int outbyte) { return list_byte_f(buf, outbyte, '$'); } int list_byte_f(char *buf, int outbyte, signed char format) { int p = 0; p+= list_nibble_f(buf+p, (outbyte >> 4), format); p+= list_nibble_f(buf+p, outbyte, format); return p; } int list_nibble_f(char *buf, int outnib, signed char format) { int p = 0; outnib = outnib & 0xf; switch(format) { case '$': if (outnib < 10) { buf[p]='0'+outnib; } else { buf[p]='a'-10+outnib; } p++; break; case '%': buf[p++] = (outnib&8)?'1':'0'; buf[p++] = (outnib&4)?'1':'0'; buf[p++] = (outnib&2)?'1':'0'; buf[p++] = (outnib&1)?'1':'0'; break; default: /* hex as default */ if (outnib < 10) { buf[p]='0'+outnib; } else { buf[p]='a'-10+outnib; } p++; break; } return p; } xa-2.4.0/src/xalisting.h0000644000031500000010000000253014513025326014402 0ustar spectrestaff/* 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_XALISTING_H__ #define __XA65_XALISTING_H__ void list_start(char *formatname); //either NULL or "html" void list_end(); void list_flush(); // debug helper void list_setfile(FILE *fp); void list_line(int l); /* set line number for the coming listing output */ void list_filename(char *fname);/* set file name for the coming listing output */ // list a single line/token set void do_listing(signed char *listing, int listing_len, signed char *bincode, int bincode_len); #endif /* __XA65_XALISTING_H__ */ xa-2.4.0/src/xam.c0000600000031500000010000000727114513025326013157 0ustar spectrestaff/* 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 #include #include #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; } // copy to xname by replacing windows backslashes with the proper DIRCHAR for(i=0;i #include #include #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;ifo.nlist;i++) { l=afile->fo.olist[i].len; t=afile->fo.olist[i].text; /* do not optimize */ t_p2_l(t, &l, &afl); if(l>254) { errout(E_OPTLEN); } else { fputc((l+1)&0xff,fp); } for(j=0;jfo.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;ifo.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; } xa-2.4.0/src/xao.h0000600000031500000010000000215314513025305013155 0ustar spectrestaff/* 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__ */ xa-2.4.0/src/xap.c0000644000031500000010000007700214524564556013210 0ustar spectrestaff/* xa65 - 65xx/65816 cross-assembler and utility suite * * Copyright (C) 1989-1997 André Fachat (a.fachat@physik.tu-chemnitz.de) * Maintained by Cameron Kaiser * * File handling and preprocessor (also see xaa.c) 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 #include #include #include #ifndef _MSC_VER #include #endif #include "xad.h" #include "xah.h" #include "xah2.h" #include "xar.h" #include "xa.h" #include "xam.h" #include "xal.h" #include "xat.h" #include "xap.h" /* define this for recursive evaluation output */ #undef DEBUG_RECMAC #undef DEBUG_REPLACE char s[MAXLINE]; Datei *filep; static int tcompare(char*,char**,int); static int pp_replace(char*,char*,int,int); static int searchdef(char*); static int fgetline(char*,int len, int *rlen, FILE*); /*static int icl_open(char*);*/ static int pp_ifdef(char*),pp_ifndef(char*); static int pp_else(char*),pp_endif(char*); static int pp_echo(char*),pp_if(char*),pp_print(char*),pp_prdef(char*); static int pp_ifldef(char*),pp_iflused(char*); static int pp_undef(char*); static int pp_error(char*); #define ANZBEF 14 #define VALBEF 7 static int quotebs = 0; static int inquote = 0; static char *cmd[]={ "echo","include","define","undef","printdef","print","error", /* VALBEF */ "ifdef","ifndef","else","endif", "ifldef","iflused","if" }; /* ANZBEF */ static int (*func[])(char*) = { pp_echo,icl_open,pp_define,pp_undef, pp_prdef,pp_print,pp_error,pp_ifdef,pp_ifndef, pp_else,pp_endif, pp_ifldef,pp_iflused,pp_if }; static char *mem; static unsigned long memfre; static int nlf; static int nff; static int hashindex[256]; static List *liste; static unsigned int rlist; static int fsp; static int loopfl; static Datei flist[MAXFILE+1]; static char in_line[MAXLINE]; int pp_comand(char *t) { int i,l,er=1; i=tcompare(t,cmd,ANZBEF); if(i>=0) { if(loopfl && (i>1; return(0); } /* stub for handling CPP directives */ int pp_cpp(char *t) { char name[MAXLINE]; if(sscanf(t, " %d \"%s\"", &filep->fline, name) == 2) { /* massage it into our parameters and drop last quote */ char *u; filep->fline--; if((u = (char *)strrchr(name, '"'))) *u = '\0'; free(filep->fname); filep->fname = strdup(name); if(!filep->fname) { fprintf(stderr,"Oops, no more memory!\n"); exit(1); } return (0); } else { return(E_SYNTAX); } } /* pp_undef is a great hack to get it working fast... */ int pp_undef(char *t) { int i; if((i=searchdef(t))) { i+=rlist; liste[i].s_len=0; } return 0; } int pp_prdef(char *t) { char *x; int i,j; if((i=searchdef(t))) { i+=rlist; x=liste[i].search; sprintf(s,"\n%s",x); if(liste[i].p_anz) { sprintf(s+strlen(s),"("); for(j=0;j=ANZDEF || memfrei=%d, len=%d\n", n, liste[n].search,i, liste[n].s_len); #endif return i == liste[n].s_len; } /** * this is a break out of the original pp_replace code, as this code * was basically duplicated for initial and recursive calls. * * to -> original output buffer for overflow check (only!) * t -> where to write the output * n -> replace macro n in liste[] * sl -> length of liste[n].search (= liste[n].s_len) * recursive -> * l -> * blist -> * */ static int pp_replace_part(char *to, char *t, int n, int sl, int recursive, int *l, int blist) { int er = E_OK; int i, d; char c; // save mem, to restore it when we don't need the pseudo replacements anymore // Note: in a real version, that should probably be a parameter, and not fiddling // with global variables... char *saved_mem = mem; #ifdef DEBUG_RECMAC printf("replace part: n=%d, sl=%d, rec=%d, %s\n", n, sl, recursive, t); #endif // yes, mark replacement string char *rs=liste[n].replace; // does it have parameters? if(liste[n].p_anz) { // yes, we have parameters, so we need to pp_replace them // as well. char fti[MAXLINE],fto[MAXLINE]; // copy replacement into temp buffer (void)strcpy(fti,liste[n].replace); // boundary checks ... if(blist+liste[n].p_anz>=ANZDEF || memfre10) { // we ran into 10 recursions deep - that does not look sound, bail out errout(E_ORECMAC); } } #endif // catch an error situation if (liste[rlist+i].replace == NULL) { errout(E_ANZPAR); return E_ANZPAR; } // copy over the replacement string into free memory (using mx as pointer) (void)strcpy(mx, nfto); // replace the pointer to the (now obsolete) old replacement with the one we just created // Note that due to the nature of the (more or less static) memory allocation, this is not // being freed. Oh well... liste[blist+i].replace = mx; mx += strlen(mx)+1; #ifdef DEBUG_RECMAC printf("FINAL: -%s=%s\n",liste[rlist+i].search,liste[rlist+i].replace); #endif } if(!er) { // safe-guard our memory allocations mem = mx; // only change (of two) from recursive: rlist is 0 there #ifdef DEBUG_RECMAC printf("replace macro: recursive=%d, blist=%d, -> b=%d\n", recursive, blist, blist+liste[n].p_anz); printf(" from: %s\n", fti); #endif er=pp_replace(fto,fti,recursive ? 0 : blist,blist+liste[n].p_anz); #ifdef DEBUG_RECMAC printf(" to: %s\n", fto); #endif } /* if(flag) printf("sl=%d,",sl);*/ sl=(int)((long)y+1L-(long)t); /* if(flag) printf("sl=%d\n",sl);*/ rs=fto; #ifdef DEBUG_RECMAC printf("->%s\n",fto); #endif } } if(er) { mem = saved_mem; return(er); } } // end if(liste[n].p_anz), i.e. if it has parameters d=(int)strlen(rs)-sl; if(strlen(to)+d>=MAXLINE) { mem = saved_mem; return(E_NOMEM); } /* if(d<0) { y=t+sl+d; x=t+sl; while(*y++=*x++); } if(d>0) { for(ll=strlen(t);ll>=sl;ll--) t[ll+d]=t[ll]; } */ if(d) { // d can be positive or negative, so strcpy cannot be used, use memmove instead (void)memmove(t+sl+d,t+sl, strlen(t) - sl + 1); } i=0; while((c=rs[i])) { t[i++]=c; } // other change from recursive. there sl is missing from add //*l=(recursive ? 0 : sl) + d;/*=0;*/ *l=sl + d;/*=0;*/ mem = saved_mem; return (er); } /** * copy the input string pointed to by ti into * an output string buffer pointed to by to, replacing all * preprocessor definitions in the process. * * Note: this method is called recursively, with "a" being -1 * when called from the "outside" respectively in a new context * (like macro parameters) * * The "b" parameter denotes the index in the list from which on * pseudo replacement entries are being created for replacement * parameters * */ int pp_replace(char *to, char *ti, int a,int b) { char *t=to; int l,n,sl,er=E_OK; int ld; // length of name/token to analyse /* int flag=!strncmp(ti,"TOUT",4); if(flag) printf("flag=%d\n",flag); */ // t points to to, so copy input to output 1:1 // then below work on the copy in-place (void)strcpy(t,ti); // if there are replacements in the list of replacements if(rlist) { // loop over the whole input while(t[0]!='\0' && t[0] != ';') { // skip over the whitespace // comment handling is NASTY NASTY NASTY // but I currently don't see another way, as comments and colons // can (and do) appear in preprocessor replacements char quotefl = 0; char commentfl = 0; while((t[0] != 0) && (quotefl || commentfl || ((!isalpha(t[0]) && t[0]!='_')))) { if (t[0]=='\0') { break; /*return(E_OK);*/ } else { if (t[0] == ';' && !quotefl) { commentfl = 1; } if (t[0] == ':' && !quotefl && !ca65 && !masm) { // note that both ca65 and masm allow colons in comments // so in these cases we cannot reset the comment handling here commentfl = 0; } if (quotefl) { // ignore other quotes within a quote if (t[0] == quotefl) { quotefl = 0; } } else if (t[0] == '"' || t[0] == '\'') { quotefl = t[0]; } t++; ti++; } } // determine the length of the name for(l=0;isalnum(t[l])||t[l]=='_';l++); // store in ld ld=l; #ifdef DEBUG_RECMAC printf("l=%d,a=%d,b=%d, t=%s\n",l,a, b ,t); #endif // the following if() is executed when being called from an // 'external' context, i.e. not from a recursion if(a<0) { // when called from an external context, not by recursion // compute hashcode for the name for the search index entry (liste[n]) n=hashindex[hashcode(t,l)]; // loop over all entries in linked list for hash code (think: hash collisions) do // while(1); { // length of name of pp definition sl=liste[n].s_len; #ifdef DEBUG_RECMAC printf("macro entry: name=%s, sl=%d, p_anz=%d\n", liste[n].search, sl, liste[n].p_anz); #endif // does pp definition match what we have found? if(sl && (sl==l) && check_name(t, n)) { er = pp_replace_part(to, t, n, sl, 0, &l, b); if (er != E_OK) { return er; } break; } if(!n) break; // next index in linked list for given hash code n=liste[n].nextindex; } while(1); } else { // called when in recursive call // loop over all the replacement entries from the given b down to 0 // that allows to replace the parameters first (as they were added at // the end of the list) for(n=b-1;n>=a;n--) { sl=liste[n].s_len; if(sl && (sl==l) && check_name(t, n)) { er = pp_replace_part(to, t, n, sl, 1, &l, b); break; } } } // advance input by length of name ti+=ld; // advance output by l t+=l; } /* end while(t[0] != 0) */ } /* end if(rlist) */ return(E_OK); } int pp_init(void) { int er; for(er=0;er<256;er++) hashindex[er]=0; fsp=0; er=0; mem=malloc(MAXPP); if(!mem) er=E_NOMEM; memfre=MAXPP; rlist=0; nlf=1; nff=1; if(!er) { liste=malloc((long)ANZDEF*sizeof(List)); if(!liste) er=E_NOMEM; if(!er && !xa23) { er = pp_define("XA_MAJOR " progmajor); if (!er) er = pp_define("XA_MINOR " progminor); if (!er) er = pp_define("XA_PATCH " progpatch); } } return(er); } int pp_open(char *name) { FILE *fp; int l; fp=xfopen(name,"r"); l = strlen(name); /* we have to alloc it dynamically to make the name survive another pp_open - it's used in the cross-reference list */ flist[0].fname = malloc(l+1); if(!flist[0].fname) { fprintf(stderr,"Oops, no more memory!\n"); exit(1); } (void)strncpy(flist[0].fname,name,l+1); flist[0].fline=0; flist[0].bdepth=b_depth(); flist[0].filep=fp; flist[0].flinep=NULL; return (fp == NULL); } void pp_close(void) { if(flist[fsp].bdepth != b_depth()) { fprintf(stderr, "Blocks not consistent in file %s: start depth=%d, end depth=%d\n", flist[fsp].fname, flist[fsp].bdepth, b_depth()); } fclose(flist[fsp].filep); } void pp_end(void) { } Datei *pp_getidat(void) { return &flist[fsp]; } int icl_close(int *c) { *c='\n'; if(!fsp) return(E_EOF); if(flist[fsp].bdepth != b_depth()) { fprintf(stderr, "Blocks not consistent in file %s: start depth=%d, end depth=%d\n", flist[fsp].fname, flist[fsp].bdepth, b_depth()); } fclose(flist[fsp--].filep); nff=1; return(E_OK); } int icl_open(char *tt) { FILE *fp2; char *namep; int len,j,i=0; pp_replace(s,tt,-1,rlist); if(fsp>=MAXFILE) return(-1); if(s[i]=='<' || s[i]=='"') i++; for(j=i;s[j];j++) if(s[j]=='>' || s[j]=='"') s[j]='\0'; fp2=xfopen(s+i,"r"); if(!fp2) return(E_FNF); setvbuf(fp2,NULL,_IOFBF,BUFSIZE); fsp++; namep = s+i; len = strlen(namep); /* we have to alloc it dynamically to make the name survive another pp_open - it's used in the cross-reference list */ flist[fsp].fname = malloc(len+1); if(!flist[fsp].fname) { fprintf(stderr,"Oops, no more memory!\n"); exit(1); } strncpy(flist[fsp].fname,namep, len+1); flist[fsp].fline=0; flist[fsp].bdepth=b_depth(); flist[fsp].flinep=NULL; flist[fsp].filep=fp2; nff=1; return(0); } int pgetline(char *t) { int c,er=E_OK; int rlen, tlen; char *p = 0; char *q = 0; loopfl =0; /* set if additional fetch needed */ filep =flist+fsp; do { int is_continuation = 0; tlen = 0; // start of current line in in_line[] do { c=fgetline(in_line + tlen, MAXLINE - tlen, &rlen, flist[fsp].filep); //fprintf(stderr, "fgetline -> c=%02x, rlen->%d, t->%s\n", c, rlen, in_line+tlen); /* check for continuation lines */ is_continuation = ((c == '\n') && (rlen > 0) && (in_line[tlen + rlen - 1]=='\\')); if (is_continuation) { // cut off the continuation character rlen--; in_line[tlen + rlen] = 0; } tlen += rlen; } while (is_continuation); if(in_line[0]=='#' || in_line[0] == altppchar) { if (in_line[1]==' ') { /* cpp comment -- pp_comand doesn't handle this right */ er=pp_cpp(in_line+1); } else { if((er=pp_comand(in_line+1))) { if(er!=1) { logout(in_line); logout("\n"); } } } } else { er=1; } if(c==EOF) { if (loopfl && fsp) { char bletch[MAXLINE]; sprintf(bletch, "at end of included file %s:\n", flist[fsp].fname); logout(bletch); errout(W_OPENPP); } er=icl_close(&c); } } while(!er || (loopfl && er!=E_EOF)); if (loopfl) { errout(E_OPENPP); } if(!er || loopfl) { in_line[0]='\0'; } er= (er==1) ? E_OK : er ; if(!er) { #ifdef DEBUG_REPLACE // printf("<<<: %s\n", in_line); #endif er=pp_replace(t,in_line,-1,rlist); #ifdef DEBUG_REPLACE printf(">>>: %s\n", t); #endif } if(!er && nff) er=E_NEWFILE; if(!er && nlf) er=E_NEWLINE; nlf=nff=0; filep=flist+fsp; filep->flinep=in_line; //fprintf(stderr, "pgetline -> er=%d, t=%s\n", er, t); return(er); } /*************************************************************************/ /* smart getc that can skip C comment blocks */ int rgetc(FILE *fp) { int incomment; int c; static int d; static int d_isvalid = 0; static int last = 0; incomment=0; do { restart: /* we had a look-ahead to see if two-char sequence was received? */ if (d_isvalid) { c = d; d_isvalid = 0; } else { c = getc(fp); } while(c==13) { c = getc(fp); }; /* remove ^M for unices */ /* a newlinebreaks any quote */ if (c == '\n') { inquote = 0; flist[fsp].fline++; nlf=1; } /* check for start of comment anyway, to allow for nested comments */ /* only allow this with 2.3 compatibility */ if(!inquote && c=='/' && (xa23 || !incomment)) { d = getc(fp); // C++ double slash comment if (d == '/') { do { c = getc(fp); } while (c != '\n' && c != EOF); if (c == '\n') { flist[fsp].fline++; nlf=1; } } else if (d == '*') { /* start block comment */ incomment++; /* convene normal processing */ goto restart; } else { d_isvalid = 1; } } /* here we are in a dilemma. If we interpret quotes in comments, * this may break end-of-block comment when singular quotes are * in a comment. If we don't interpret quotes in a comment, * a quoted string with end-of-comment in it may break when * commented. * * Unfortunately GeckOS has quotes in comments, and in an inconsistent way. * * #define E_FILLNAM <-34 / * illegal name (joker "*","?","\"") * / * * ... except if we handle backslash-escaped quotes? No, then this breaks * in apps/lsh/lsh.a65:347 * * / * TODO: interpret "\" escape codes, shell variables * / * * But I guess for 2.4 it is ok to break things like this. */ if (!incomment) { /* not in comment */ /* flag if we're in a quoted string */ /* but only if quote isnot escaped with backslash */ if(c=='"' && last!='\\' && !quotebs) { inquote ^= 1; } /* implement backslashed quotes for 2.4 */ if(!xa23 && c=='\\') quotebs=1; else quotebs=0; } else { /* in comment */ /* check for end of comment */ /* note: for xa2.3, incomment only set true if not quoted, and quote not changed in comment */ if((!inquote || !xa23) && (c=='*')) { if((d=getc(fp))!='/') { d_isvalid = 1; } else { incomment--; /* convene normal processing */ goto restart; } } } /* force newline at the end of a file */ if (c == EOF && last != EOF) { last = EOF; c = '\n'; } else { last = c; } } while(incomment && (c!=EOF)); return(c-'\t'?c:' '); } /** * Note that the line returned is always zero-terminated, * the rlen out parameter is just convenience, so that * a further strlen() can be saved */ int fgetline(char *t, int len, int *rlen, FILE *fp) { static int c,i; i=0; do { c=rgetc(fp); if(c==EOF || c=='\n') { t[i]='\0'; break; } t[i]=c; i= (i #include #include "xad.h" #include "xah.h" #include "xar.h" #include "xa.h" #include "xal.h" #include "xao.h" #include "xau.h" #undef DEBUG_RELOC File *afile = NULL; int rmode = RMODE_RELOC; /* int r_set(int pc, int afl, int l) { 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) { #ifdef DEBUG_RELOC printf("set relocation @$%04x, l=%d, afl=%04x, segment=%d, label=%d\n", pc, l, afl,segment, label); #endif if(((afl & A_FMASK) == (SEG_UNDEF<<8)) || ((afl & A_FMASK) == (SEG_UNDEFZP<<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)) && ((afl & A_FMASK) != (SEG_UNDEFZP<<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].adrrt.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].adrrt.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; if((afile->rt.rlist[p].afl&A_FMASK)==(SEG_UNDEFZP<<8)) { fputc( (((afl & ~A_FMASK)>>8)&255)|SEG_UNDEF, fp); fputc(afile->rt.rlist[p].lab & 255, fp); fputc((afile->rt.rlist[p].lab>>8) & 255, fp); } else { 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; } xa-2.4.0/src/xar.h0000600000031500000010000000305114513025326013161 0ustar spectrestaff/* 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__ */ xa-2.4.0/src/xar2.c0000600000031500000010000001013614513025326013240 0ustar spectrestaff/* 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 #include #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].adrrd.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].adrrd.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; if((afile->rd.rlist[p].afl&A_FMASK)==(SEG_UNDEFZP<<8)) { fputc((((afl & ~A_FMASK)>>8)&255)|SEG_UNDEF, fp); fputc(afile->rd.rlist[p].lab & 255, fp); fputc((afile->rd.rlist[p].lab>>8) & 255, fp); } else { 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; } xa-2.4.0/src/xat.c0000600000031500000010000026541314520746416013202 0ustar spectrestaff/* xa65 - 65xx/65816 cross-assembler and utility suite * * Copyright (C) 1989-1997 André Fachat (a.fachat@physik.tu-chemnitz.de) * maintained by Cameron Kaiser * * Core tokenizing module/pass 1 and pass 2 * * 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. */ /* enable this to turn on (copious) optimization output */ #undef LISTING_DEBUG #undef DEBUG_CONV #undef DEBUG_CAST #undef DEBUG_RELOC #undef DEBUG_AM #include #include #include #include "xad.h" #include "xah.h" #include "xah2.h" #include "xar.h" #include "xa.h" #include "xaa.h" #include "xal.h" #include "xat.h" #include "xao.h" #include "xap.h" #include "xacharset.h" #include "xalisting.h" int dsb_len = 0; static int t_conv(signed char*,signed char*,int*,int,int*,int*,int*,int,int*); static int t_keyword(signed char*,int*,int*); static int tg_asc(signed char*,signed char*,int*,int*,int*,int*,int); static void tg_dez(signed char*,int*,int*); static void tg_hex(signed char*,int*,int*); static void tg_oct(signed char*,int*,int*); static void tg_bin(signed char*,int*,int*); static int t_p2(signed char *t, int *ll, int fl, int *al); //static void do_listing(signed char *listing, int listing_len, signed char *bincode, int bincode_len); void list_setbytes(int number_of_bytes_per_line); /* assembly mnemonics and pseudo-op tokens */ /* ina and dea don't work yet */ /* Note AF 20110624: added some ca65 compatibility pseudo opcodes, * many are still missing (and will most likely never by supported in this * code base). Potential candidates are .hibytes, .lobytes, .asciiz, * .addr, .charmap, .dbyt, .faraddr, .bankbytes, .segment (at least for the known ones) * .incbin is similar to our .bin, but with parameters reversed (argh...) * I like the .popseg/.pushseg pair; * .global/.globalzp is equivalent to forward-defining a label in the global block * .export/.exportzp could be implemented with a commandline switch to NOT export * global labels, where .exported labels would still be exported in an o65 file. */ char *kt[] ={ /* 1 2 3 4 5 6 7 8 9 10 */ "adc","and","asl","bbr","bbs","bcc","bcs","beq","bit","bmi", "bne","bpl","bra","brk","bvc","bvs","brl","clc","cld","cli", /* "clv","cmp","cpx","cpy","cop","dea","dec","dex","dey","eor", */ "clv","cmp","cpx","cpy","cop",/*"dea",*/"dec","dex","dey","eor", /* "ina","inc","inx","iny","jmp","jsr","lda","ldx","ldy","lsr", */ /*"ina",*/"inc","inx","iny","jmp","jsr","lda","ldx","ldy","lsr", "mvp","mvn","nop","ora","pha","php","phx","phy","pla","plp", "plx","ply","phb","phd","phk","plb","pld","pea","pei","per", "rmb","rol","ror","rti","rts","rep","rtl","sbc","sec","sed", "sei","smb","sta","stx","sty","stz","sep","stp","tax","tay", "trb","tsb","tsx","txa","txs","tya","txy","tyx","tcd","tdc", "tcs","tsc","wai","wdb","xba","xce", ".byt",".word",".asc",".dsb", ".(", ".)", "*=", ".text",".data",".bss", ".zero",".fopt", ".byte", ".end", ".list", ".xlist", ".dupb", ".blkb", ".db", ".dw", ".align",".block", ".bend",".al",".as",".xl",".xs", ".bin", ".aasc", ".code", ".include", ".import", ".importzp", ".proc", ".endproc", ".zeropage", ".org", ".reloc", ".listbytes", ".scope", ".endscope", ".assert" }; /* arithmetic operators (purely for listing, parsing is done programmatically */ char *arith_ops[] = { "", "+", "-", // 0,1,2 "*", "/", // 3,4 ">>", "<<", // 5,6 "<", ">", "=", // 7,8,9 "<=", ">=", "<>", // 10,11,12 "&", "^", "|", // 13,14,15 "&&", "||", "==", "!=", "!" // 16,17,18 (9),19 (12),20 (NYI) }; /* length of arithmetic operators indexed by operator number */ static int lp[]= { 0,1,1,1,1,2,2,1,1,1,2,2,2,1,1,1,2,2,2,2,1 }; /* mvn and mvp are handled specially, they have a weird syntax */ #define Kmvp 38 #define Kmvn Kmvp+1 /* index into token array for pseudo-ops */ /* last valid mnemonic */ #define Lastbef 93 #define Kbyt Lastbef+1 #define Kword Lastbef+2 #define Kasc Lastbef+3 #define Kdsb Lastbef+4 #define Kopen Lastbef+5 /* .( */ #define Kclose Lastbef+6 /* .) */ #define Kpcdef Lastbef+7 /* *=value */ #define Ktext Lastbef+8 #define Kdata Lastbef+9 #define Kbss Lastbef+10 #define Kzero Lastbef+11 #define Kfopt Lastbef+12 #define Kbyte Lastbef+13 /* gets remapped to Kbyt */ #define Kend Lastbef+14 /* ignored (MASM compat.) */ #define Klist Lastbef+15 /* ignored (MASM compat.) */ #define Kxlist Lastbef+16 /* ignored (MASM compat.) */ #define Kdupb Lastbef+17 /* gets remapped to Kdsb */ #define Kblkb Lastbef+18 /* gets remapped to Kdsb */ #define Kdb Lastbef+19 /* gets remapped to Kbyt */ #define Kdw Lastbef+20 /* gets remapped to Kword */ #define Kalign Lastbef+21 #define Kblock Lastbef+22 /* gets remapped to .( */ #define Kbend Lastbef+23 /* gets remapped to .) */ #define Kalong Lastbef+24 #define Kashort Lastbef+25 #define Kxlong Lastbef+26 #define Kxshort Lastbef+27 #define Kbin Lastbef+28 #define Kaasc Lastbef+29 #define Kcode Lastbef+30 /* gets remapped to Ktext */ /* 93 + 30 -> 123 */ #define Kinclude Lastbef+31 #define Kimport Lastbef+32 #define Kimportzp Lastbef+33 #define Kproc Lastbef+34 /* mapped to Kopen */ /* 93 + 35 -> 128 */ #define Kendproc Lastbef+35 /* mapped to Kclose */ #define Kzeropage Lastbef+36 /* mapped to Kzero */ #define Korg Lastbef+37 /* mapped to Kpcdef - with parameter equivalent to "*=$abcd" */ #define Krelocx Lastbef+38 /* mapped to Kpcdef - without parameter equivalent to "*=" */ #define Klistbytes (Lastbef+39-256) #define Kscope (Lastbef+40) /* mapped to Kopen */ #define Kendscope (Lastbef+41) /* mapped to Kclose */ #define Kassert (Lastbef+42-256) /* last valid token+1 */ #define Anzkey Lastbef+43 /* define last valid token number; last define above plus one */ #define Kreloc (Anzkey-256) /* *= (relocation mode) */ #define Ksegment (Anzkey+1-256) /* this actually now is above 127, which might be a problem as char is signed ... */ int number_of_valid_tokens = Anzkey; /* array used for hashing tokens (26 entries, a-z) */ static int ktp[]={ 0,3,17,25,28,29,29,29,29,32,34,34,38,40,41,42,58, 58,65,76,90,90,90,92,94,94,94,Anzkey }; #define Admodes 24 /* * opcodes for each addressing mode * high byte: supported architecture (no bits = original NMOS 6502) * bit 1: R65C02 * bit 2: 65816 and allows 16-bit quantity (accum only) * bit 3: 65816 and allows 16-bit quantity (index only) * low byte: opcode itself * * each opcode is indexed in this order: *=65816, ^=R65C02 * 00 = implied * 01 = zero page * 02 = zero page,x * 03 = direct page,y* * 04 = direct page (indirect)* * 05 = (indirect,x) * 06 = (indirect),y * 07 = immediate (8-bit) * 08 = absolute * 09 = absolute,x * 10 = absolute,y * 11 = relative * 12 = (indirect-16) i.e., jmp (some_vector) * 13 = (absolute,x)* * 14 = zero page+relative test'n'branch ^ * 15 = zero page clear'n'set'bit ^ * 16 = relative long* * 17 = absolute long* * 18 = absolute long,x* * 19 = stack relative* * 20 = stack relative (indirect),y* * 21 = direct page (indirect long)* * 22 = direct page (indirect long),y* * 23 = (indirect long) */ static int ct[Lastbef+1][Admodes] ={ /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 imm */ { -1, 0x65,0x75,-1,0x172,0x61,0x71,0x469,0x6d,0x7d,0x79,-1, -1, -1, -1, -1, -1,0x26f,0x27f,0x263,0x273,0x267,0x277,-1 }, /*adc*/ { -1, 0x25,0x35,-1,0x132,0x21,0x31,0x429,0x2d,0x3d,0x39,-1, -1, -1, -1, -1, -1,0x22f,0x23f,0x223,0x233,0x227,0x237,-1 }, /*and*/ { 0x0a,0x06,0x16,-1, -1, -1, -1, -1, 0x0e,0x1e,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*asl*/ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0x10f,-1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*bbr*/ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0x18f,-1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*bbs*/ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0x90,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*bcc*/ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0xb0,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*bcs*/ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0xf0,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*beq*/ { -1, 0x24,0x134,-1, -1, -1, -1, 0x589,0x2c,0x13c,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*bit*/ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0x30,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*bmi*/ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0xd0,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*bne*/ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0x10,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*bpl*/ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0x180,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*bra*/ { 0x00,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*brk*/ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0x50,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*bvc*/ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0x70,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*bvs*/ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,0x282, -1, -1, -1, -1, -1, -1, -1 }, /*brl*/ { 0x18,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*clc*/ { 0xd8,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*cld*/ { 0x58,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*cli*/ { 0xb8,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*clv*/ { -1, 0xc5,0xd5,-1, 0x1d2,0xc1,0xd1,0x4c9,0xcd,0xdd,0xd9,-1, -1, -1, -1, -1,-1,0x2cf,0x2df,0x2c3,0x2d3,0x2c7,0x2d7,-1 }, /*cmp*/ { -1, 0xe4,-1, -1, -1, -1, -1, 0x8e0,0xec,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*cpx*/ { -1, 0xc4,-1, -1, -1, -1, -1, 0x8c0,0xcc,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*cpy*/ { -1, -1, -1, -1, -1, -1, -1, 0x202,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*cop*/ /* { 0x13a,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },*/ /*dea*/ { 0x13a,0xc6,0xd6,-1, -1, -1, -1, -1, 0xce,0xde,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*dec*/ { 0xca,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*dex*/ { 0x88,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*dey*/ { -1, 0x45,0x55,-1, 0x152,0x41,0x51,0x449,0x4d,0x5d,0x59,-1, -1, -1, -1, -1,-1,0x24f,0x25f,0x243,0x253,0x247,0x257,-1 }, /*eor*/ /* { 0x11a,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },*/ /*ina*/ { 0x11a,0xe6,0xf6,-1, -1, -1, -1, -1, 0xee,0xfe,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*inc*/ { 0xe8,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*inx*/ { 0xc8,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*iny*/ { -1, -1, -1, -1, -1, -1, -1, -1, 0x4c,-1, -1, -1, 0x6c,0x17c,-1, -1, -1,0x25c, -1, -1, -1, -1, -1,0x2dc}, /*jmp*/ { -1, -1, -1, -1, -1, -1, -1, -1, 0x20,-1, -1, -1, -1, 0x2fc,-1, -1, -1,0x222, -1, -1, -1, -1, -1, -1 }, /*jsr*/ { -1, 0xa5,0xb5,-1, 0x1b2,0xa1,0xb1,0x4a9,0xad,0xbd,0xb9,-1, -1, -1, -1, -1,-1,0x2af,0x2bf,0x2a3,0x2b3,0x2a7,0x2b7,-1 }, /*lda*/ { -1, 0xa6,-1, 0xb6,-1, -1, -1, 0x8a2,0xae,-1, 0xbe,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*ldx*/ { -1, 0xa4,0xb4,-1, -1, -1, -1, 0x8a0,0xac,0xbc,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*ldy*/ { 0x4a,0x46,0x56,-1, -1, -1, -1, -1, 0x4e,0x5e,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*lsr*/ { -1, -1, -1, -1, -1, -1, -1, -1, 0x244,-1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*mvp*/ { -1, -1, -1, -1, -1, -1, -1, -1, 0x254,-1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*mvn*/ { 0xea,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*nop*/ { -1, 0x05,0x15,-1, 0x112,0x01,0x11,0x409,0x0d,0x1d,0x19,-1, -1, -1, -1, -1,-1,0x20f,0x21f,0x203,0x213,0x207,0x217,-1 }, /*ora*/ { 0x48,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*pha*/ { 0x08,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*php*/ { 0x1da,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*phx*/ { 0x15a,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*phy*/ { 0x68,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*pla*/ { 0x28,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*plp*/ { 0x1fa,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*plx*/ { 0x17a,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*ply*/ { 0x28b,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*phb*/ { 0x20b,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*phd*/ { 0x24b,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*phk*/ { 0x2ab,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*plb*/ { 0x22b,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*pld*/ { -1, -1, -1, -1, -1, -1, -1, -1, 0x2f4,-1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*pea*/ { -1, -1, -1, -1,0x2d4, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*pei*/ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, 0x262,-1, -1, -1, -1, -1, -1, -1 }, /*per*/ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,0x107, -1, -1, -1, -1, -1, -1, -1, -1 }, /*rmb*/ { 0x2a,0x26,0x36,-1, -1, -1, -1, -1, 0x2e,0x3e,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*rol*/ { 0x6a,0x66,0x76,-1, -1, -1, -1, -1, 0x6e,0x7e,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*ror*/ { 0x40,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*rti*/ { 0x60,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*rts*/ { -1, -1, -1, -1, -1, -1, -1, 0x2c2,-1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*rep*/ { 0x26b,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*rtl*/ { -1, 0xe5,0xf5,-1, 0x1f2,0xe1,0xf1,0x4e9,0xed,0xfd,0xf9,-1, -1, -1, -1, -1,-1,0x2ef,0x2ff,0x2e3,0x2f3,0x2e7,0x2f7,-1 }, /*sbc*/ { 0x38,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*sec*/ { 0xf8,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*sed*/ { 0x78,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*sei*/ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,0x187, -1, -1, -1, -1, -1, -1, -1, -1 }, /*smb*/ { -1, 0x85,0x95,-1, 0x192,0x81,0x91,-1, 0x8d,0x9d,0x99,-1, -1, -1, -1, -1,-1,0x28f,0x29f,0x283,0x293,0x287,0x297,-1 }, /*sta*/ { -1, 0x86,-1, 0x96,-1, -1, -1, -1, 0x8e,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*stx*/ { -1, 0x84,0x94,-1, -1, -1, -1, -1, 0x8c,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*sty*/ { -1, 0x164,0x174,-1, -1, -1, -1, -1, 0x19c,0x19e,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*stz*/ { -1, -1, -1, -1, -1, -1, -1, 0x2e2,-1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*sep*/ { 0x2db,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*stp*/ { 0xaa,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*tax*/ { 0xa8,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*tay*/ { -1, 0x114,-1, -1, -1, -1, -1, -1, 0x11c,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*trb*/ { -1, 0x104,-1, -1, -1, -1, -1, -1, 0x10c,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*tsb*/ { 0xba,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*tsx*/ { 0x8a,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*txa*/ { 0x9a,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*txs*/ { 0x98,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*tya*/ { 0x29b,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*txy*/ { 0x2bb,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*tyx*/ { 0x25b,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*tcd*/ { 0x27b,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*tdc*/ { 0x21b,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*tcs*/ { 0x23b,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*tsc*/ { 0x2cb,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*wai*/ { 0x242,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*wdb*/ { 0x2eb,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /*xba*/ { 0x2fb,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } /*xce*/ } ; #define Syntax 14 #define Maxbyt 4 /* grouped syntaxes. each row = operand type, column = bytes allowed */ static int at[Syntax][Maxbyt] ={ { 0, -1, -1 ,-1 }, /* implied: no operand */ { -1, 7, -1 ,-1 }, /* immediate: single byte operand only */ { -1, 15, -1 ,-1 }, /* relative: single byte operand only */ { -1, -1, 14 ,-1 }, /* test'n'branch: two bytes only */ { -1, 1, 8 ,17 }, /* addressing: 1 byte for zp, 2 for absolute, 3 for absolute long */ { -1, 2, 9 ,18 }, /* ,x: same */ { -1, 3, 10 ,-1 }, /* ,y: 1 byte for dp,y, 2 for absolute,y */ { -1, 4, 12 ,-1 }, /* (indirect): 1 byte for (dp), 2 for (absolute) */ { -1, 5, 13 ,-1 }, /* (i,x): 1 byte for (zp,x), 2 for (a,x) */ { -1, 6, -1 ,-1 }, /* (i),y: 1 byte only */ { -1, 21, 23 ,-1 }, /* (indirect long): 1 byte for (dp), 2 for (a) */ { -1, 22, -1 ,-1 }, /* (indirect long),y: 1 byte only */ { -1, 19, -1 ,-1 }, /* stack relative: 1 byte only */ { -1, 20, -1 ,-1 } /* SR (in),y: 1 byte only */ }; #define AnzAlt 5 /* disambiguation table. for example, arbitrary instruction xxx $0000 could be either interpreted as an absolute operand, or possibly relative. note: does not look at comma or after, if present. */ static int xt[AnzAlt][2] ={ /* Alternativ Adr-Modes */ { 8, 11 }, /* abs -> rel */ { 2, 3 }, /* z,x -> z,y */ { 5, 6 }, /* ,x) -> ),y */ { 9, 10 }, /* a,x -> a,y */ { 8, 16 } /* abs -> relong */ }; /* cross check: instruction should be this many bytes long in total */ /* indexed by addressing mode */ static int le[] ={ 1,2,2,2,2,2,2,2,3,3,3,2,3,3,3,2, /* new modes */ 3,4,4,2,2,2,2,3 }; /* indicates absolute->zp optimizable addressing modes (abs->zp) */ /* indexed by addressing mode */ static int opt[] ={ -1,-1,-1,-1,-1,-1,-1,-1,1,2,3,-1,4,5,-1,-1, /*new*/ -1,8,9,-1,-1,-1,-1,-1 }; /* abs -> zp */ /*********************************************************************************************/ /* pass 1 */ int t_p1(signed char *s, signed char *t, int *ll, int *al) { static int er,l,n,v,nk,na1,na2,bl,am,sy,i,label,byte; /*,j,v2 ;*/ int afl = 0; int tlen; /* token listing length, to adjust length that is returned */ int inp; /* input pointer in t[] */ unsigned char cast; /* notes and typical conventions ... er = error code am = addressing mode in use */ cast='\0'; bl=0; *al = 0; /* printf("\n"); */ /* convert the next token from string s */ #ifdef DEBUG_AM fprintf(stderr, "- p1 %d starting -\n", pc[segment]); #endif /* As the t_p1 code below always works through the tokens * from t_conv in such a way that it always produces a shorter * result, the conversion below takes place "in place". * This, however, means that the original token sequence, which * would be useful for some assembler listing, is overwritten. * While the original assumption was ok for a constrained * environment like the Atari ST, this is no longer true. * Converting the code below to have separate input and output * areas would be error-prone, so we do some copy-magic here * instead...*/ /* we keep three bytes buffer for "T_LISTING" and the length of the * token list */ t[0]=T_LISTING; er=t_conv(s,t+6,&l,pc[segment],&nk,&na1,&na2,0,&byte); tlen = l+6; t[1]=tlen&255; t[2]=(tlen>>8)&255; t[3]=segment; t[4]=pc[segment]&255; t[5]=(pc[segment]>>8)&255; /* now we have to duplicate the token sequence from the T_LISTING buffer * to the end of "t", so we can then in-place convert it * below. Non-overlapping, size is known in advance, so * using memcpy is fine here */ inp = 0; /* discard label definitions before copying the buffer, so we don't get * label defined errors */ while (inp1) && (t[inp]base[SEG_TEXT] = pc[SEG_TEXT] = romaddr + h_length(); romable=1; } if(!er) { /* * * pseudo-op dispatch (except .byt, .asc) * */ // fix sign n=t[0]; // & 0xff; /* TODO: make that a big switch statement... */ /* maybe later. Cameron */ if(n==Kend || n==Klist || n==Kxlist) { *ll = 0; /* ignore */ } else if(n==Kinclude) { *ll = 0; /* no output length */ i=1; if(t[i]=='\"') { int k,j=0; char binfname[255]; i++; k=t[i]+i+1; i++; while(i 255) er = E_NOMEM; /* buffer overflow */ } binfname[j] = '\0'; er=icl_open(binfname); } else { er=E_SYNTAX; } } else if(n==Kfopt) { if(romable==1) er=E_ROMOPT; t[0] = Kbyt; set_fopt(l,t,nk+1-na1+na2); *ll = 0; } else if(n==Klistbytes) { int p = 0; if(!(er=a_term(t+1,&p,&l,pc[segment],&afl,&label,0))) { er=E_OKDEF; } *ll = 3; t[0] = Klistbytes; t[1] = p & 0xff; t[2] = (p >> 8) & 0xff; //printf("Klistbytes p1: er=%d, l=%d\n", er, l); } else if(n==Kpcdef) { int tmp; // get parameter for *= er=a_term(t+1,&tmp,&l,pc[segment],&afl,&label,0); // found? if(!er) { i=1; wval(i,tmp, 0); /* writes T_VALUE, 3 bytes value, plus one byte */ t[i++]=T_END; *ll=7; er=E_OKDEF; #ifdef DEBUG_RELOC printf("set pc=%04x, oldsegment=%d, pc[segm]=%04x, ", pc[SEG_ABS], segment, pc[segment]); printf(" wrote %02x %02x %02x %02x %02x %02x, %02x, %02x\n", t[0],t[1],t[2],t[3],t[4],t[5],t[6],t[7]); #endif if(segment==SEG_TEXT) { pc[SEG_ABS] = tmp; r_mode(RMODE_ABS); } else { if(!relmode) { pc[segment] = tmp; } else { er = E_ILLSEGMENT; } } /*printf("newsegment=%d, pc[ABS]=%04x\n", segment, pc[SEG_ABS]);*/ } else { // no param found, only "*=". // if we ABS, we switch back to reloc #ifdef DEBUG_RELOC printf("reloc: er=%d, l=%d, segment=%d, pc[%d]=%04x, pc[abs(%d)]=%04x, pc[text(%d)]=%04x\n", er, l, segment, segment, pc[segment], SEG_ABS, pc[SEG_ABS],SEG_TEXT, pc[SEG_TEXT]); #endif if((segment==SEG_ABS) && (er==E_SYNTAX && l==0)) { t[0]=Kreloc; i=1; wval(i,pc[SEG_TEXT], 0); t[i++]=T_END; *ll=7; er=E_OKDEF; r_mode(RMODE_RELOC); /*printf(" : newseg=%d, pc[newseg]=%04x, pc[abs]=%04x, pc[text]=%04x\n", segment, pc[segment], pc[SEG_ABS], pc[SEG_TEXT]);*/ } } } else if(n==Kopen) { if(showblk) fprintf(stderr, "%s line %d: .(\n", pp_getidat()->fname, pp_getidat()->fline); b_open(); er=E_NOLINE; } else if(n==Kclose) { if(showblk) fprintf(stderr, "%s line %d: .)\n", pp_getidat()->fname, pp_getidat()->fline); er=b_close(); if(!er) er=E_NOLINE; } else if(n==Kalong) { if (!w65816) { er=E_65816; } else { memode=1; t[0]=Kalong; *ll=1; er=E_OKDEF; } } else if(n==Kashort) { memode=0; t[0]=Kashort; *ll=1; er=E_OKDEF; } else if(n==Kxlong) { if (!w65816) { er=E_65816; } else { xmode=1; t[0]=Kxlong; *ll=1; er=E_OKDEF; } } else if(n==Kxshort) { xmode=0; t[0]=Kxshort; *ll=1; er=E_OKDEF; } else if(n==Kdsb) { dsb_len = 1; if(!(er=a_term(t+1,&bl,&l,pc[segment],&afl,&label,0))) { er=E_OKDEF; } dsb_len = 0; } else if(n==Ktext) { r_mode(RMODE_RELOC); // use of segments restores previous segment / reloc mode segment = relmode ? SEG_TEXT : SEG_ABS; t[0]=Ksegment; t[1]=segment; *ll=2; er=E_OKDEF; } else if(n==Kdata) { if(relmode) { r_mode(RMODE_RELOC); // use of segments restores previous segment / reloc mode segment = SEG_DATA; t[0]=Ksegment; t[1]=SEG_DATA; *ll=2; er=E_OKDEF; } else { er=E_ILLSEGMENT; } } else if(n==Kbss) { if(relmode) { r_mode(RMODE_RELOC); // use of segments restores previous segment / reloc mode segment = SEG_BSS; t[0]=Ksegment; t[1]=SEG_BSS; *ll=2; er=E_OKDEF; } else { er=E_ILLSEGMENT; } } else if(n==Kzero) { if(relmode) { r_mode(RMODE_RELOC); // use of segments restores previous segment / reloc mode segment = SEG_ZERO; t[0]=Ksegment; t[1]=SEG_ZERO; *ll=2; er=E_OKDEF; } else { er=E_ILLSEGMENT; } } else if (n==Kassert) { /* ignore this in first pass, just check syntax */ int x; i = 1; /* XXX: sadly, can't implement unary logical not yet */ if(!(er=a_term(t+i,&x,&l,pc[segment],&afl,&label,1))) { i += l; } if(t[i] == ',') { /* skip comma */ i++; } else { er = E_SYNTAX; } /* get filename. the tokenizer can either see it as a multichar string ... */ if (!er) { int k; if(t[i]=='\"') { i++; k=t[i]+i+1; i++; while(i 255) er = E_NOMEM; /* buffer overflow */ } binfnam[j] = '\0'; /* or as a 'char' if it's a single character ("word" would have been caught by the above) */ } else if(!(er=a_term(t+i,&v,&l,pc[segment],&afl,&label,1))) { binfnam[0] = v; binfnam[1] = '\0'; i += l; } } /* three arguments only please */ if (!er && t[i] != T_END && t[i] != T_COMMENT) { er = E_SYNTAX; } if (!er) { FILE *foo; #ifdef DEBUG_AM fprintf(stderr, "binclude1 offset = %i len = %i filename = %s endchar = %i\n", offset, length, binfnam, i); #endif if (!(foo = fopen(binfnam, "rb"))) { er = E_FNF; } else { fseek(foo, 0, SEEK_END); if ((length+offset) > ftell(foo)) { er = E_OUTOFDATA; } else { length = (length) ? length : (ftell(foo)-offset); } fclose(foo); } if (!er) { if (length > 65535 && !w65816) { errout(W_OVER64K); } else if (length > 16777215) { errout(W_OVER16M); } /* pass parameters back to xa.c */ *ll=i+1; /* bl=length+2; */ bl=length; er = E_OKDEF; /* defer to pass 2 */ } } } else if(n==Kalign) { int tmp; if(segment!=SEG_ABS) { if(!(er=a_term(t+1,&tmp,&l,pc[segment],&afl,&label,0))) { if(tmp == 1 || tmp == 2 || tmp == 4 || tmp == 256) { set_align(tmp); if(pc[segment] & (tmp-1)) { /* not aligned */ int tmp2; t[0]=Kdsb; i=1; bl=tmp=(tmp - (pc[segment] & (tmp-1))) & (tmp-1); wval(i,tmp, 0); t[i++]=','; tmp2= 0xea; wval(i,tmp2, 0); /* nop opcode */ t[i++]=T_END; *ll=9; er=E_OKDEF; } else { *ll=0; /* ignore if aligned right */ } } else { er=E_ILLALIGN; } } } else { er=E_ILLSEGMENT; } } else /* optimization okay on pass 1: use 0 for fl */ { #ifdef DEBUG_AM fprintf(stderr, "E_OK ... t_p2 xat.c %i %i\n", t[0], *ll); #endif /* this actually calls pass2 on the current tokenization stream, * but without including the Klisting token listing */ er=t_p2(t,ll,(0 | byte), al); #ifdef DEBUG_AM fprintf(stderr, "... --> er=%d\n", er); #endif } } else if(er==E_NODEF) { /* * no label was found from t_conv! * try to figure out most likely length * */ #ifdef DEBUG_AM fprintf(stderr, "E_NODEF pass1 xat.c\n"); #endif er = E_OK; /* stuff error */ n=t[0]; /* look at first token */ /* mnemonic dispatch -- abbreviated form in t_p2, but changed here to not do anything other than 24-bit optimization since we don't know the value of the label */ /* choose addressing mode; add commas found */ if(n>=0 && n<=Lastbef && n != Kmvn && n != Kmvp) /* not for mvn/p */ { int inp = 1; /* input pointer */ if(t[inp]==T_END || t[inp]==T_COMMENT) { sy=0; /* implied */ inp++; } else if(t[inp]=='#') { sy=1+nk; /* immediate */ inp++; } else if(t[inp]=='(') { sy=7+nk; /* computed */ inp++; } else { sy=4+nk; /* absolute or zero page */ } /* this actually finds the cast for all addressing modes, but t_conv() only puts it there for immediate (#) or absolute/ absolute indexed addressing modes */ if (t[inp] == T_CAST) { inp++; cast = t[inp]; inp++; #ifdef DEBUG_CAST printf("Found cast to: %c\n", cast); #endif } /* length counter set to maximum length + 1 */ if (w65816 || (t[l-1]=='@' || t[l-1] == '!')) { /* for 65816 allow addressing modes up to 4 byte overall length */ bl=Maxbyt+1; } else { /* for other modes only check for addressing modes up to 3 byte overall length */ bl=Maxbyt; } /* find best fit for length of this operand */ while(--bl) { /* look at syntax table (at) using syntax (sy) as index. is there an addressing mode for an operand of this length? am = addressing mode */ if((am=at[sy][bl-1])>=0) { if(am>Admodes-1) /* no, it's -1, syntax error */ { er=E_SYNTAX; break; } if(ct[n][am]>=0) /* yes, valid token *and* mode, so we're done */ break; /* no valid mode for this token, see if it's something ambiguous; if so, try to interpret in that context. */ for(v=0;v=0) break; if(v=0 && am>16) /* <<< NOTE! */ if(ct[n][opt[am]]>=0) am=opt[am]; } /* if ` is declared, force further optimization */ if (cast=='`') { if (opt[am]<0 || ct[n][opt[am]]<0) errout(E_ADRESS); am=opt[am]; } /* if ! is declared, force to 16-bit quantity */ if (cast=='!' && am>16 && opt[am]>=0 && bl) { am=opt[am]; } /* couldn't match anything for this opcode */ if(!bl) er=E_SYNTAX; else { /* ok, get length of instruction */ bl=le[am]; /* and add one for 65816 special instruction modes */ if( ((ct[n][am]&0x400) && memode) || ((ct[n][am]&0x800) && xmode)) { bl++; } } if (er == E_NODEF) er = E_OK; /* .byt, .asc, .word, .dsb, .fopt pseudo-op dispatch */ } else if(n==Kimportzp) { int i; *ll=0; /* no output */ bl = 0; /* no output length */ /* import labels; next follow a comma-separated list of labels that are imported. Tokenizer has already created label entries, we only need to set the flags appropriately */ i=1; /*printf("Kimport: t[i]=%d\n",t[i]);*/ while(t[i]==T_LABEL) { int n = (t[i+1] & 255) | (t[i+2] << 8); /* label number */ /*printf("lg_import: %d\n",n);*/ lg_importzp(n); i+=3; while (t[i]==' ') i++; if (t[i]!=',') break; i++; while (t[i]==' ') i++; } er=E_NOLINE; } else if(n==Kimport) { int i; *ll=0; /* no output */ bl = 0; /* no output length */ /* import labels; next follow a comma-separated list of labels that are imported. Tokenizer has already created label entries, we only need to set the flags appropriately */ i=1; /*printf("Kimport: t[i]=%d\n",t[i]);*/ while(t[i]==T_LABEL) { int n = (t[i+1] & 255) | (t[i+2] << 8); /* label number */ /*printf("lg_import: %d\n",n);*/ lg_import(n); i+=3; while (t[i]==' ') i++; if (t[i]!=',') break; i++; while (t[i]==' ') i++; } er=E_NOLINE; } else if(n==Kmvn || n==Kmvp) { bl=3; if (!w65816) er = E_65816; } else if(n==Kbyt || n==Kasc || n==Kaasc) { #ifdef DEBUG_AM fprintf(stderr, "byt pass 1 %i\n", nk+1-na1+na2); #endif bl=nk+1-na1+na2; } else if(n==Kword) { bl=2*nk+2; } else if(n==Kdsb) { er=a_term(t+1,&bl,&l,pc[segment],&afl,&label,0); } else if(n==Kfopt) { set_fopt(l-1,t+1, nk+1-na1+na2); *ll = 0; } else if(n==T_OP) { er=E_OKDEF; } else er=E_NODEF; if(!er) er=E_OKDEF; #ifdef DEBUG_AM fprintf(stderr, "guessing instruction length is %d\n", bl); #endif } if(er==E_NOLINE) { er=E_OK; *ll=0; } *al += bl; pc[segment]+=bl; if(segment==SEG_TEXT) pc[SEG_ABS]+=bl; if(segment==SEG_ABS) pc[SEG_TEXT]+=bl; /* adjust length by token listing buffer length */ #ifdef DEBUG_CONV printf("converted: (er=%d, t=%p, ll=%d, tlen=%d):",er, t, *ll, tlen); for(i=0;i<*ll;i++) printf("%02x,",t[i] & 0xff); printf("\n"); printf("adjusted len=%d\n", *ll+tlen); #endif *ll = *ll + tlen; return(er); } /*********************************************************************************************/ /* t_pass 2 * * *t is the token list as given from pass1 * *ll is the returned length of bytes (doubles as * input for whether OK or OKDEF status from pass1) * fl defines if we allow zeropage optimization * * Conversion takes place "in place" in the *t array. */ /** * function called from the main loop, where "only" the * undefined labels have to be resolved and the affected * opcodes are assembled, the rest is passed through from * pass1 (pass-through is done in t_p2, when *ll<0) * As this is not called from p1, assume that we do not * do length optimization * * *t is the input token list * *ll is the input length of the token list, * and the output of how many bytes of the buffer are to be taken * into the file; note that for .dsb and .bin, this does NOT match * the length in the internal data structures! */ int t_p2_l(signed char *t, int *ll, int *al) { int er = E_OK; int l = *ll; if (l < 0) l = -l; #if 0 { printf("t_p2_l (ll=%d, t=%p):", *ll, t); for(int i=0;i l) { int i; // that is corrupt data and should not happen list_flush(); printf("corrupt: t_p2_l (l=%d, tlen=%d, ll=%d, t=%p):", l, tlen, *ll, t); for(i=0;i0 when E_OKDEF */ { *ll=-*ll; bl=*ll; er=E_OK; } else { n=t[0]; if(n==T_OP) { n=cval(t+1); er=a_term(t+4,&v,&l,pc[segment],&nafl,&label,0); if(!er) { if(t[3]=='=') { v2=v; } else { if( (!(er=l_get(n,&v2, &afl))) && ((afl & A_FMASK)!=(SEG_UNDEF<<8)) && ((afl & A_FMASK)!=(SEG_UNDEFZP<<8)) ) { if(t[3]=='+') { if(afl && nafl) { errout(E_WPOINTER); nafl=0; } nafl = afl; v2+=v; } else if(t[3]=='-') { if( (((nafl & A_FMASK)>>8) != afl) || ((nafl & A_MASK)==A_HIGH) ) { errout(E_WPOINTER); nafl=0; } else { nafl = afl; } v2-=v; } else if(t[3]=='*') { if(afl || nafl) { errout(E_WPOINTER); nafl=0; } v2*=v; } else if(t[3]=='/') { if(afl || nafl) { errout(E_WPOINTER); nafl=0; } if(v) v2/=v; else er=E_DIV; } else if(t[3]=='|') { if(afl || nafl) { errout(E_WPOINTER); nafl=0; } v2=v|v2; } else if(t[3]=='&') { if(afl || nafl) { errout(E_WPOINTER); nafl=0; } v2=v2&v; } } } l_set(n,v2,nafl>>8); *ll=0; if(!er) er=E_NOLINE; } } else if(n==Kword) { i=1; j=0; while(!er && t[i]!=T_END && t[i] != T_COMMENT) { if(!(er=a_term(t+i,&v,&l,pc[segment],&afl,&label,1))) { /*if(afl) printf("relocation 1 %04x at pc=$%04x, value now =$%04x\n", afl,pc[segment],v); */ if(afl) u_set(pc[segment]+j, afl, label, 2); t[j++]=v&255; t[j++]=(v>>8)&255; i+=l; if(t[i]!=T_END && t[i] != T_COMMENT && t[i]!=',') er=E_SYNTAX; else if(t[i]==',') i++; } } *ll=j; bl=j; } else if (n == Kassert) { int result = 0; int c; i = 1; /* this time, actually check something */ if(!(er=a_term(t+i,&result,&l,pc[segment],&afl,&label,1))) { i += l; } if(t[i] == ',') { /* skip comma */ i++; } else { er = E_SYNTAX; } /* get filename. the tokenizer can either see it as a multichar string ... */ if (!er) { int k; if (!result) fprintf(stderr, "Assertion failed: "); if(t[i]=='\"') { i++; k=t[i]+i+1; i++; while(i 255) er = E_NOMEM; /* buffer overflow */ } binfnam[j] = '\0'; flen = j; /* or as a 'char' if it's a single character ("word" would have been caught by the above) */ } else if(!(er=a_term(t+i,&v,&l,pc[segment],&afl,&label,1))) { binfnam[0] = v; binfnam[1] = '\0'; i += l; flen = 1; } } /* three arguments only please */ if (!er && t[i] != T_END && t[i] != T_COMMENT) { er = E_SYNTAX; } if (!er) { FILE *foo; #ifdef DEBUG_AM fprintf(stderr, "binclude2 offset = %i len = %i filename = %s endchar = %i\n", offset, length, binfnam, i); #endif if (!(foo = fopen(binfnam, "rb"))) { er = E_FNF; } else { fseek(foo, 0, SEEK_END); if ((length+offset) > ftell(foo)) { er = E_OUTOFDATA; } else { length = (length) ? length : (ftell(foo)-offset); } fclose(foo); } if (!er) { if (length > 65535 && !w65816) { errout(W_OVER64K); } else if (length > 16777215) { errout(W_OVER16M); } /* pass parameters back to xa.c */ *ll=length; /* bl=length+2; */ bl=length; t[0] = offset & 255; t[1] = (offset >> 8) & 255; t[2] = (offset >> 16) & 255; /* God help us if the index is > 65535 */ t[3] = fstart & 255; t[4] = (fstart >> 8) & 255; t[5] = flen; /* to massage 'char' types */ er = E_BIN; } } } else if (n==Kmvn || n==Kmvp) { /* special case these instructions' syntax */ int wide=0; i=1; j=1; /* write opcode */ t[0] = ((n == Kmvp) ? 0x44 : 0x54); while(!er && t[i]!=T_END && t[i]!=T_COMMENT) { if (wide) /* oops */ er = E_SYNTAX; #ifdef DEBUG_AM fprintf(stderr, "mvn mvp: %i %i %i %i %i\n", t[0], t[i], wide, i, j); #endif if(!(er=a_term(t+i,&v,&l,pc[segment],&afl,&label,1))) { /*if(afl) printf("relocation 1 %04x at pc=$%04x, value now =$%04x\n", afl,pc[segment],v); */ if(afl) u_set(pc[segment]+j, afl, label, 2); i+=l; if (v & 0xff00) er=E_ILLQUANT; else t[j++]=v; } if (j > 3) er=E_SYNTAX; if(t[i]!=T_END && t[i]!=T_COMMENT && t[i]!=',') er=E_SYNTAX; else if(t[i]==',') i++; } if (j != 3) er = E_SYNTAX; /* oops */ /* before we leave, swap the bytes. although disassembled as mv? src,dest it's actually represented as mv? $ddss -- see http://6502org.wikidot.com/software-65816-memorymove */ i = t[2]; t[2] = t[1]; t[1] = i; *ll = j; bl = j; if (!w65816) er = E_65816; } else if(n==Kasc || n==Kbyt || n==Kaasc) { i=1; j=0; while(!er && t[i]!=T_END && t[i] != T_COMMENT) { if(t[i]=='\"') { i++; k=t[i]+i+1; i++; while(i er=%d, nbytes=%d\n", er, nbytes); list_setbytes(nbytes); l = 2; *ll=0; bl =0; } else if(n==Ksegment) { segment = t[1]; *ll=0; bl =0; } else if(n==Kdsb) { dsb_len = 1; if(!(er=a_term(t+1,&j,&i,pc[segment],&afl,&label,0))) { if (j<0) er=E_NEGDSBLEN; else /* if(t[i+1]!=',') er=E_SYNTAX; else */ /* if((segment!=SEG_ABS) && afl) er=E_ILLPOINTER; else */ { dsb_len = 0; if(t[i+1]==',') { er=a_term(t+2+i,&v,&l,pc[segment],&afl,&label,0); } else { v=0; } if(!er && v>>8) er=E_OVERFLOW; t[0]=v&255; if(!er) { *ll=j; bl=j; #ifdef DEBUG_AM fprintf(stderr, "Kdsb E_DSB %i\n", j); #endif er=E_DSB; } } if(!er) bl=j; } dsb_len = 0; } else if(n>=0 && n<=Lastbef) { int inp = 1; /* input pointer */ signed char cast = '\0'; /* cast value */ c = t[inp]; if(c=='#') { inp++; if (t[inp] == T_CAST) { inp++; cast = t[inp]; inp++; #ifdef DEBUG_CAST printf("Found cast to (2): %c\n", cast); #endif } sy=1; if(!(er=a_term(t+inp,vv,&l,pc[segment],&afl,&label,1))) { /* if(1) printf("a_term returns afl=%04x\n",afl); */ rlt[0] = afl; lab[0] = label; inp+=l; if(t[inp]!=T_END && t[inp] != T_COMMENT) { if(t[inp]!=',') er=E_SYNTAX; else { inp++; sy++; if(!(er=a_term(t+inp,vv+1,&l,pc[segment],&afl,&label,1))) { rlt[1] = afl; lab[1] = label; inp+=l; if(t[inp]!=T_END && t[inp] != T_COMMENT) { if(t[inp]!=',') er=E_SYNTAX; else { inp++; sy++; if(!(er=a_term(t+inp,vv+2,&l,pc[segment],&afl,&label,1))) { rlt[2] = afl; lab[2] = label; inp+=l; if(t[inp]!=T_END && t[inp]!=T_COMMENT) er=E_SYNTAX; } } } } } } } } else if(c==T_END || c==T_COMMENT) { sy=0; } else if(c=='(') { inp++; if (t[inp] == T_CAST) { inp++; cast = t[inp]; inp++; #ifdef DEBUG_CAST printf("Found cast to (3): %c\n", cast); #endif } sy=7; if(!(er=a_term(t+inp,vv,&l,pc[segment],&afl,&label,1))) { inp += l; rlt[0] = afl; lab[0] = label; if(t[inp]!=T_END && t[inp]!=T_COMMENT) { if(t[inp]==',') { inp++; if (tolower(t[inp])=='x') sy=8; else sy=13; } else if(t[inp]==')') { inp++; if(t[inp]==',') { inp++; if(tolower(t[inp])=='y') sy=9; else er=E_SYNTAX; } else if(t[inp]!=T_END && t[inp]!=T_COMMENT) er=E_SYNTAX; } } else er=E_SYNTAX; } } else if(c=='[') { inp++; if (t[inp] == T_CAST) { inp++; cast = t[inp]; inp++; #ifdef DEBUG_CAST printf("Found cast to (4): %c\n", cast); #endif } sy=10; if(!(er=a_term(t+inp,vv,&l,pc[segment],&afl,&label,1))) { inp += l; rlt[0] = afl; lab[0] = label; if(t[inp]!=T_END && t[inp]!=T_COMMENT) { if(t[inp]==']') { inp++; if(t[inp]==',') { inp++; if(tolower(t[inp])=='y') sy=11; else er=E_SYNTAX; } else if(t[inp]!=T_END && t[inp]!=T_COMMENT) er=E_SYNTAX; } } else er=E_SYNTAX; } } else { if (t[inp] == T_CAST) { inp++; cast = t[inp]; inp++; #ifdef DEBUG_CAST printf("Found cast to (5): %c\n", cast); #endif } sy=4; if(!(er=a_term(t+inp,vv,&l,pc[segment],&afl,&label,1))) { inp += l; rlt[0] = afl; lab[0] = label; if(t[inp]!=T_END && t[inp]!=T_COMMENT) { if(t[inp]==',') { inp++; if(tolower(t[inp])=='y') sy=6; else if(tolower(t[inp])=='s') sy=12; else sy=5; } else er=E_SYNTAX; } } } /* set bl to maximum overall length +1 as while() below starts with decrementing it */ if (w65816 || cast=='@' || cast== '!') { /* for 65816 allow addressing modes up to 4 byte overall length */ bl=Maxbyt+1; } else { /* for other modes only check for addressing modes up to 3 byte overall length */ bl=Maxbyt; } #ifdef DEBUG_AM printf("--- trying to find am using: (max+1) bl=%d, sy=%d\n", bl, sy); #endif while(--bl) { if((am=at[sy][bl-1])>=0) { if(am>Admodes) { er=E_SYNTAX; break; } if(ct[n][am]>=0) break; for(v=0;v=0) break; if(v16 && !er && (((vv[0]&0xff8000)==0xff8000) || !(vv[0]&0xff0000)) && opt[am]>=0) if(ct[n][opt[am]]>=0) am=opt[am]; #ifdef DEBUG_AM fprintf(stderr, "aftaa1: pc= %d, am = %d and vv[0] = %d, optimize = %d, bitmask = %d, bl = %d\n", pc[segment], am, vv[0], fl, (vv[0]&0xffff00), bl); #endif if(cast!='!') { if(bl && !er && !(vv[0]&0xffff00) && opt[am]>=0) { if(ct[n][opt[am]]>=0) { if (!fl || cast=='`') { am=opt[am]; } else { errout(W_FORLAB); } } } } #ifdef DEBUG_AM fprintf(stderr, "aftaa2: pc=%d, am=%d and vv[0]=%d, optimize=%d, bitmask=%d, op=%d, bl=%d\n", pc[segment], am, vv[0], fl, (vv[0]&0xffff00), ct[n][opt[am]], bl); #endif } if(!bl) er=E_SYNTAX; else { bl=le[am]; if( ((ct[n][am]&0x400) && memode) || ((ct[n][am]&0x800) && xmode)) { bl++; } if ((am != 11 && am != 16) && (vv[0] > 255 || vv[0] < -256) && bl == 2) { er = E_OVERFLOW; } else if ((am != 11 && am != 16) && (vv[0] > 65535 || vv[0] < -65536) && (bl == 2 || bl == 3)) { er = E_OVERFLOW; } *ll=bl; } #ifdef DEBUG_AM fprintf(stderr, "byte length is now %d, am=%d, er=%d\n", bl, am, er); #endif if(!er) { t[0]=ct[n][am]&0x00ff; if(ct[n][am]&0x0300) { if(ct[n][am]&0x100) { ncmos++; if(!cmosfl) er=E_CMOS; } else { n65816++; if(!w65816) { fprintf(stderr,"n=%d, am=%d\n", n, am); er=E_65816; } } } if(am!=0) { if((am<8 && !( ((ct[n][am]&0x400) && memode) || ((ct[n][am]&0x800) && xmode) )) || (am>=19 && am!=23)) { if(vv[0]&0xff00) { #ifdef DEBUG_AM fprintf(stderr, "address mode: %i address: %i\n", am, vv[0]); #endif er=E_OVERFLOW; } else t[1]=vv[0]; /*if(rlt[0]) printf("relocation 1 byte %04x at pc=$%04x, value now =$%04x\n",rlt[0],pc[segment]+1,*vv); */ if(rlt[0]) u_set(pc[segment]+1, rlt[0], lab[0], 1); } else if(((am<14 || am==23) && am!=11) || am==7) { if (vv[0]>0xffff) { #ifdef DEBUG_AM fprintf(stderr, "address mode: %i address: %i\n", am, vv[0]); #endif er=E_OVERFLOW; } else { t[1]=vv[0]&255; t[2]=(vv[0]>>8)&255; /*if(rlt[0]) printf("relocation 2 byte %04x at pc=$%04x, value now =$%04x\n",rlt[0],pc[segment]+1,*vv); */ if(rlt[0]) u_set(pc[segment]+1, rlt[0], lab[0], 2); } } else if(am==11 || am==16) { /* relative, relative long */ if((segment!=SEG_ABS) && (!rlt[0])) { er=E_ILLPOINTER; } else { /*printf("am=11, pc=%04x, vv[0]=%04x, segment=%d\n",pc[segment],vv[0], segment);*/ v=vv[0]-pc[segment]-le[am]; if(((v&0xff80)!=0xff80) && (v&0xff80) && (am==11)) er=E_RANGE; else { t[1]=v&255; t[2]=(v>>8)&255; } } } else if(am==14) { if(vv[0]&0xfff8 || vv[1]&0xff00) er=E_RANGE; else if((segment!=SEG_ABS) && (rlt[0] || !rlt[2])) { er=E_ILLPOINTER; } else { /*if(rlt[1]) printf("relocation 1 byte %04x at pc=$%04x, value now =$%04x\n",rlt[1],pc[segment]+1,*vv); */ if(rlt[1]) u_set(pc[segment]+1, rlt[1], lab[1], 1); t[0]=t[0]|(vv[0]<<4); t[1]=vv[1]; v=vv[2]-pc[segment]-3; if((v&0xff80) && ((v&0xff80)!=0xff80)) er=E_OVERFLOW; else t[2]=v; } } else if(am==15) { /*if(rlt[1]) printf("relocation 1 byte %04x at pc=$%04x, value now =$%04x\n",rlt[1],pc[segment]+1,*vv); */ if(rlt[1]) u_set(pc[segment]+1, rlt[1], lab[1], 1); if(vv[0]&0xfff8 || vv[1]&0xff00) er=E_OVERFLOW; else { t[0]=t[0]|(vv[0]<<4); t[1]=vv[1]; } } else if(am==17 || am==18) { t[1]=vv[0]&255; t[2]=(vv[0]>>8)&255; t[3]=(vv[0]>>16)&255; if(rlt[0]) { rlt[0]|=A_LONG; u_set(pc[segment]+1, rlt[0], lab[0], 3); } } else er=E_SYNTAX; } } } else er=E_SYNTAX; } #ifdef DEBUG_AM fprintf(stderr, "-- endof P2\n"); #endif pc[segment]+=bl; if(segment==SEG_TEXT) pc[SEG_ABS]+=bl; if(segment==SEG_ABS) pc[SEG_TEXT]+=bl; *al = bl; return(er); } /*********************************************************************************************/ /* helper function for the preprocessor, to compute an arithmetic value * (e.g. for #if or #print). * First tokenizes it, then calculates the value */ int b_term(char *s, int *v, int *l, int pc) { static signed char t[MAXLINE]; int er,i,afl, label; if(!(er=t_conv((signed char*)s,t,l,pc,&i,&i,&i,1,NULL))) { er=a_term(t,v,&i,pc,&afl,&label,0); } return(er); } /*********************************************************************************************/ /* translate a string into a first-pass sequence of tokens; * Take the text from *s (stopping at \0 or ';'), tokenize it * and write the result to *t, returning the length of the * token sequence in *l * * Input params: * s source input line * t output token sequence buffer * l return length of output token sequence here * pc the current PC to set address labels to that value * nk return number of comma in the parameters * na1 asc text count returned * na2 total byte count in asc texts returned * af arithmetic flag: 0=do label definitions, parse opcodes and params; * 1=only tokenize parameters, for b_term() call from the preprocessor * for arithmetic conditions * bytep ??? */ static int t_conv(signed char *s, signed char *t, int *l, int pc, int *nk, int *na1, int *na2, int af, int *bytep) { static int v,f; static int operand,o; int fl,afl; int p,q,ll,mk,er; int ud; /* counts undefined labels */ int n; /* label number to be passed between l_def (definition) and l_set (set the value) */ int byte; int uz; /* unused at the moment */ /*static unsigned char cast;*/ /* ich verstehe deutsch, aber verstehen andere leute nicht; so, werde ich diese bemerkungen uebersetzen ... cameron */ /* I understand German, but other folks don't, so I'll translate these comments ... Cameron */ /* note that I don't write so good tho' ;) */ *nk=0; /* comma count */ *na1=0; /* asc text count */ *na2=0; /* total bytecount in asc texts */ ll=0; er=E_OK; /* error state */ p=0; q=0; ud = uz = byte =0; mk=0; /* 0 = add'l commas ok */ fl=0; /* 1 = pass text thru */ afl=0; /* pointer flag for label */ // skip leading whitespace while(isspace(s[p])) p++; n=T_END; /*cast='\0';*/ if(!af) { while(s[p]!='\0' && s[p]!=';') { //printf("CONV: %s\n", s); if (s[p] == ':') { // this is a ca65 unnamed label if ((er = l_def((char*)s+p, &ll, &n, &f))) break; l_set(n,pc,segment); /* set as address value */ t[q++]=T_DEFINE; t[q++]=n&255; t[q++]=(n>>8)&255; n=0; p+=ll; while(isspace(s[p])) p++; // end of line if (s[p] == 0 || s[p] == ';') { break; } } /* is keyword? */ if(!(er=t_keyword(s+p,&ll,&n))) break; /* valid syntax, but just not a real token? */ if(er && er!=E_NOKEY) break; // if so, try to understand as label // it returns the label number in n if((er=l_def((char*)s+p,&ll,&n,&f))) break; p+=ll; while(isspace(s[p])) p++; if(s[p]=='=') { /*printf("Found = @%s\n",s+p);*/ t[q++]=T_OP; t[q++]=n&255; t[q++]=(n>>8)&255; t[q++]='='; p++; ll=n=0; break; } else if(s[p]==':' && s[p+1]=='=') /* support := label assignments (ca65 compatibility) */ { /*printf("Found := @%s\n", s+p);*/ t[q++]=T_OP; t[q++]=n&255; t[q++]=(n>>8)&255; t[q++]='='; p+=2; ll=n=0; break; } else if(f && s[p]!='\0' && s[p+1]=='=') { t[q++]=T_OP; t[q++]=n&255; t[q++]=(n>>8)&255; t[q++]=s[p]; p+=2; ll=n=0; break; } else if(s[p]==':') /* to support label: ... syntax */ { p++; while(s[p]==' ') p++; l_set(n,pc,segment); /* set as address value */ t[q++]=T_DEFINE; t[q++]=n&255; t[q++]=(n>>8)&255; n=0; } else { /* label ... syntax */ l_set(n,pc,segment); /* set as address value */ t[q++]=T_DEFINE; t[q++]=n&255; t[q++]=(n>>8)&255; n=0; } } if(n != Kmvn && n != Kmvp && ((n & 0xff) <=Lastbef)) { mk=1; /* = only 1 comma ok for normal opcodes */ } } if(s[p]=='\0' || s[p]==';') { er=E_NOLINE; ll=0; } else if(!er) { p+=ll; if(ll) { t[q++]= n & 0xff; /* if( (n&0xff) == Kmacro) { t[q++]= (n >> 8) & 0xff; } */ } operand=1; // skip whitespace while(isspace(s[p])) { p++; } if(s[p]=='#') { mk=0; t[q++]=s[p++]; // skip following whitespace while(isspace(s[p])) { p++; } } /* * * operand processing * byte = length of operand in bytes to be assembled * * */ /* this addresses forced high/low/two byte addressing, but only for the first operand. Further processing is done in a_term() */ /* FIXIT2 */ while(s[p]!='\0' && s[p]!=';' && !er) { if(fl) { // pass through text (e.g. for ",y") t[q++]=s[p++]; } else { if(operand) { /* are we forcing the operand into a particular addressing mode? !, @, ` operators Note these are not available in ca65, but we only switch off "@" which are used for cheap local labels*/ if(s[p]=='!' || (s[p]=='@' && !ca65) || s[p]=='`') { #ifdef DEBUG_CAST printf("Setting cast to: %c\n", s[p]); #endif t[q++]=T_CAST; t[q++]=s[p]; operand= -operand+1; p++; } else if(s[p]=='(' || s[p]=='-' || s[p]=='>' || s[p]=='<' || s[p]=='[') { t[q++]=s[p++]; operand= -operand+1; /* invert to become reinverted */ } else if(s[p]=='*') { t[q++]=s[p++]; } else /* maybe it's a label Note that for ca65 cheap local labels, we check for "@" */ if(isalpha(s[p]) || s[p]=='_' || ((s[p]==':' || s[p]=='@') && ca65)) { int p2 = 0; if (n == (Klistbytes & 0xff)) { // check for "unlimited" // Note: this could be done by a more general "constants" handling, // where in appropriate places (like the one here), constants are // replaced by a pointer to a predefined constants info, e.g. using // a T_CONSTANT. Which would also fix the listing of this constant // (which is currently listed as "0") static char *unlimited = "unlimited"; while (s[p+p2] != 0 && unlimited[p2] != 0 && s[p+p2] == unlimited[p2]) p2++; } if (p2 == 9) { // length of "unlimited" er = E_OK; // found constant wval(q, 0, 'd'); p += p2; } else { //m=n; er=l_search((char*)s+p,&ll,&n,&v,&afl); if (er == E_NODEF && undefok) { lg_toglobal(s+p); } if(!er) { if(afl) { t[q++]=T_POINTER; t[q++]=afl & 255; t[q++]=v & 255; t[q++]=(v>>8) & 255; t[q++]=n & 255; /* cheap fix for listing */ t[q++]=(n>>8) & 255; /* why is the label already resolved in t_conv? */ } else { t[q++]=T_LABEL; t[q++]=n & 255; t[q++]=(n>>8) & 255; /*wval(q,v, 0);*/ } } else if(er==E_NODEF) { #ifdef DEBUG_AM fprintf(stderr, "could not find %s\n", (char *)s+p); #endif t[q++]=T_LABEL; t[q++]=n & 255; t[q++]=(n>>8) & 255; /* if(afl==SEG_ZEROUNDEF) uz++; */ ud++; // number of undefined labels er=E_OK; } p+=ll; } } else if(s[p]<='9' && (s[p]>'0' || (s[p] == '0' && !ctypes))) { tg_dez(s+p,&ll,&v); p+=ll; wval(q,v, 'd'); } else /* handle encodings: hex, binary, octal, quoted strings */ switch(s[p]) { case '0': // only gets here when "ctypes" is set, and starts with 0 // we here check for the C stype "0xHEX" and "0OCTAL" encodings if ('x' == tolower(s[p+1])) { // c-style hex tg_hex(s+p+2, &ll, &v); p+=2+ll; wval(q, v, '$'); } else if (isdigit(s[p+1])) { // c-style octal if digit follows tg_oct(s+p+1,&ll,&v); p+=1+ll; wval(q,v, '&'); } else { // else use decimal (0) tg_dez(s+p,&ll,&v); p+=ll; wval(q,v, 'd'); } break; case '$': tg_hex(s+p+1,&ll,&v); p+=1+ll; wval(q,v, '$'); break; case '%': tg_bin(s+p+1,&ll,&v); p+=1+ll; wval(q,v, '%'); break; case '&': tg_oct(s+p+1,&ll,&v); p+=1+ll; wval(q,v, '&'); break; case '\'': case '\"': er=tg_asc(s+p,t+q,&q,&p,na1,na2,n); break; case ',': if(mk) while(s[p]!='\0' && s[p]!=';') { while(s[p]==' ') p++; *nk+=(s[p]==','); t[q++]=s[p++]; } else { *nk+=1; t[q++]=s[p++]; } break; default : er=E_SYNTAX; break; } operand= -operand+1; } else /* operator */ { o=0; if(s[p]==')' || s[p]==']') { t[q++]=s[p++]; operand =-operand+1; } else if(s[p]==',') { t[q++]=s[p++]; if(mk) { // if only one comma, pass through all following text - esp. ",y" or ",x" etc fl++; } *nk+=1; } else switch(s[p]) { case '+': o=1; break; case '-': o=2; break; case '*': o=3; break; case '/': o=4; break; case '!': if (s[p+1] == '=') o=12; break; case '<': switch (s[p+1]) { case '<': o=6; break; case '>': o=12; break; case '=': o=10; break; default : o=7; break; } break; case '>': switch (s[p+1]) { case '>': o=5; break; case '<': o=12; break; case '=': o=11; break; default: o=8; break; } break; case '=': switch (s[p+1]) { case '<': o=10; break; case '>': o=11; break; case '=': o=9; p++; /* hack */ break; default: o=9; break; } break; case '&': if (s[p+1]=='&') o=16; else o=13; break; case '|': if (s[p+1]=='|') o=17; else o=15; break; case '^': o=14; break; default: er=E_SYNTAX; break; } if(o) { t[q++]=o; p+=lp[o]; } operand= -operand+1; } while(s[p]==' ') p++; } } } //printf("er=%d, ud=%d\n", er, ud); if(!er) { /* if(uz==1 && ud==1 && byte!=2) { byte=1; } if(byte == 1) { t[q++] = T_FBYTE; } else if(byte == 2) { t[q++] = T_FADDR; } */ byte = 0; if(ud > 0) { er=E_NODEF; byte = 1; } } if (s[p] == ';') { /* handle comments */ /* first find out how long */ int i; for (i = p+1; s[i] != '\0'; i++); i = i - p; /* actual length of the comment, including zero-byte terminator */ /*if (i >= 1) {*/ /* there actually is a comment */ t[q++] = T_COMMENT; t[q++] = i&255; t[q++] = (i>>8)&255; memcpy(t+q, s+p+1, i); /* also copy zero terminator, used in listing */ q += i; /*}*/ } t[q++]=T_END; /* FIXME: this is an unholy union of two "!" implementations :-( */ /* FIXME FIXME FIXME ... if (operand==1) { t[q++]='\0'; t[q++]=cast; } */ *l=q; if(bytep) *bytep=byte; return(er); } /********************************************************************************************* * identifies a keyword in s, if it is found, starting with s[0] * A keyword is either a mnemonic, or a pseudo-opcode */ static int t_keyword(signed char *s, int *l, int *n) { int i = 0; // index into keywords int j = 0; int hash; // keywords either start with a character, a "." or "*" if(!isalpha(s[0]) && s[0]!='.' && s[0]!='*' ) return(E_NOKEY); // if first char is a character, use it as hash... if(isalpha(s[0])) hash=tolower(s[0])-'a'; else hash=26; // check for "*=" if(s[0]=='*') { j=1; while(s[j] && isspace(s[j])) j++; if(s[j]=='=') { i=Kpcdef; j++; } } // no keyword yet found? if(!i) { // get sub-table from hash code, and compare with table content // (temporarily) redefine i as start index in opcode table, and hash as end index i=ktp[hash]; hash=ktp[hash+1]; // check all entries in opcode table from start to end for that hash code while(i='0') val=val*8+(s[i++]-'0'); *l=i; *v=val; } static void tg_hex(signed char *s, int *l, int *v) { int i=0,val=0; while((s[i]>='0' && s[i]<='9') || (tolower(s[i])<='f' && tolower(s[i])>='a')) { val=val*16+(s[i]<='9' ? s[i]-'0' : tolower(s[i])-'a'+10); i++; } *l=i; *v=val; } /* * tokenize a string - handle two delimiter types, ' and " */ static int tg_asc(signed char *s, signed char *t, int *q, int *p, int *na1, int *na2,int n) { int er=E_OK,i=0,j=0,bs=0; signed char delimiter = s[i++]; #ifdef DEBUG_AM fprintf(stderr, "tg_asc token = %i\n", n); #endif t[j++]='"'; /* pass2 token for string */ j++; /* skip place for length */ while(s[i]!='\0' && (bs || s[i]!=delimiter)) { /* implement backslashed quotes for 2.4 */ if(n != Kbin && s[i] == '\\' && !bs && !xa23) { bs=1; i++; continue; } else bs=0; /* do NOT convert for Kbin or Kaasc, or for initial parse */ if (!n || n == Kbin || n == Kaasc) { t[j++]=s[i]; /* XXX 2.4 implement option for ^ for backwards compatibility */ } else if(ca65 || !xa23 || s[i]!='^') { /* no escape code "^" - TODO: does ca65 has an escape code */ t[j++]=convert_char(s[i]); } else { /* escape code */ signed char payload = s[i+1]; switch(payload) { case '\0': er=E_SYNTAX; break; case '\"': if (payload == delimiter) { t[j++]=convert_char(payload); i++; } else { er=E_SYNTAX; } break; case '\'': if (payload == delimiter) { t[j++]=convert_char(payload); i++; } else { er=E_SYNTAX; } break; case '^': t[j++]=convert_char('^'); i++; break; default: t[j++]=convert_char(payload&0x1f); i++; break; } } i++; } if(j==3) /* optimize single byte string to value */ { t[0]=T_VALUE; t[1]=t[2]; t[2]=0; t[3]=0; t[4]=delimiter; j+=2; } else { /* handle as string */ t[1]=j-2; *na1 +=1; *na2 +=j-2; } if(s[i]==delimiter) { /* in case of no error */ i++; /* skip ending delimiter */ } *q +=j; *p +=i; return(er); } xa-2.4.0/src/xat.h0000600000031500000010000000241514513025326013166 0ustar spectrestaff/* 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_l(signed char *t, int *ll, int *al); int b_term(char *s, int *v, int *l, int pc); extern char *kt[]; // table of key words, needed for listing extern char *arith_ops[]; // table of arithmetic operators, needed for listing extern int number_of_valid_tokens; // as it says, in the "kt" table #endif /* __XA65_XAT_H__ */ xa-2.4.0/src/xau.c0000600000031500000010000000354614513025326013170 0ustar spectrestaff/* xa65 - 65xx/65816 cross-assembler and utility suite * * Copyright (C) 1989-1997 André Fachat (fachat@web.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 #include #include "xad.h" #include "xau.h" #include "xah.h" #include "xal.h" #undef DEBUG_UNDEF int u_label(int labnr) { int i; #ifdef DEBUG_UNDEF printf("u_label: %d\n",labnr); #endif if(!afile->ud.ulist) { afile->ud.ulist = malloc(200*sizeof(int)); if(afile->ud.ulist) afile->ud.um=200; } for(i=0;iud.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;iud.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; } xa-2.4.0/src/xau.h0000600000031500000010000000160514513025305013164 0ustar spectrestaff /* 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); xa-2.4.0/tests/0000755000031500000010000000000014526071413012604 5ustar spectrestaffxa-2.4.0/tests/README0000644000031500000010000000544514526073130013472 0ustar spectrestaffThis 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. It requires a reasonably compatible `make` and Perl. You can run specific tests from the main source directory with make test TESTS=test,test,test,... or, if `make test` doesn't work right on your system, you can run the Perl harness directly: ./harness -cc=... -cflags=... -make=... -tests=testdir,testdir,testdir,... If -tests is omitted, all tests are run. Don't run the makefiles directly, if they exist; they may not work properly. If a Makefile is not present, then the test harness assembles "test.s" and compares it with "ok". 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 relocmode/ Tests to prevent use of irrational segments if relocating mde isn't on 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 ('816) binclude/ Binary include code with some weird casing ppstrings/ Don't substitute inside strings (unless -S) neg_offset/ Test negative offsets/values with/without relocation chppch/ Changing preprocessor characters (-p) charset/ Tests of when charsets should be honoured and when not ca65/ Compatibility tests for ca65 compatibility relmode/ tests concerning switches between segments and absolute mode mvnmvp/ Test MVN MVP unusual addressing mode ('816) dos51/ Regression test, label scoping, "real world code" cpktest/ Regression test, label listing, "real world code" listing/ Test of listing feature op816/ Regression test for '816 opcodes (thanks Alessandro Gatti) branch/ Branch range test masmcom/ Another test for -M that generates totally valid code quotch/ Test quoting problematic characters (thanks Simon Rowe) linkr/ Test linking using .dsb and generated code csapiec/ Test on pointer arithmetic in relocating mode math/ Math tests (currently divide by zero, thanks Frederic Cambus) alxl/ Various '816 width tests (includes Samuel Falvo's test) pparity/ Tests of preprocessor macro arity (with Emil Johansson's test) recucom/ Recursive comments test aserror/ Tests of .assert and #error syntax/function reset_segment/ Verifies conditions under which a segment is reset expando/ Test of preprocessor expansion (thanks Tom Hargreaves) Cameron Kaiser, AndrĂ© Fachat xa-2.4.0/tests/adrm/0000755000031500000010000000000014524607234013533 5ustar spectrestaffxa-2.4.0/tests/adrm/02.asm0000644000031500000010000000053514513025305014450 0ustar spectrestaff .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 xa-2.4.0/tests/adrm/02.ok0000644000031500000010000000007414513025305014277 0ustar spectrestaff………Ć楎ŤŤe‡Žś‘îÎBŤ1DîŕyŚ  ä˙LâüL6N ĐË``đÇ`xa-2.4.0/tests/adrm/816.asm0000644000031500000010000000047114513025305014544 0ustar spectrestaff .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 xa-2.4.0/tests/adrm/816.ok0000644000031500000010000000006214513025305014371 0ustar spectrestaff…………ŤŤŤe‡ŹŹŹCe‡`Lâü\âü™L,\,`ĐŃ`xa-2.4.0/tests/adrm/Makefile0000644000031500000010000000116114513025305015161 0ustar spectrestaffdefault: # xa should not allow this to happen. if it does, this test is no good. ../../xa 816.asm || exit 0 && exit 1 ../../xa zab.asm || exit 0 && exit 1 ../../xa zpa.asm || exit 0 && exit 1 ../../xa -C c02.asm || exit 0 && exit 1 # expected-to-fail tests did fail. should be no more errors now. ../../xa -C 02.asm -o 02.o ../hextool -cmp=02.ok < 02.o ../../xa c02.asm -o c02.o ../hextool -cmp=c02.ok < c02.o ../../xa -w 816.asm -o 816.o ../hextool -cmp=816.ok < 816.o ../../xa -w zab.asm -o zab.o ../hextool -cmp=zab.ok < zab.o ../../xa -w zpa.asm -o zpa.o ../hextool -cmp=zpa.ok < zpa.o clean: rm -f *.o xa-2.4.0/tests/adrm/bip.inc0000644000031500000010000000066514513025305014776 0ustar spectrestaff/* - 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 xa-2.4.0/tests/adrm/c02.asm0000644000031500000010000000052714513025305014614 0ustar spectrestaff .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 xa-2.4.0/tests/adrm/c02.ok0000644000031500000010000000007214513025305014440 0ustar spectrestaff………Ć掍Ťe‡Žś‘îÎB:Ť1DîŕyŚ  ä˙LâüL4N ``ĐÉ`xa-2.4.0/tests/adrm/zab.asm0000644000031500000010000000005414513025305014777 0ustar spectrestaff .word $4000 * = $4000 #include "bip.inc" xa-2.4.0/tests/adrm/zab.ok0000644000031500000010000000005714513025305014633 0ustar spectrestaff@­•Đű˘ ż#@ť ĘĐö©… ©…!©˙…"©…#L LZL Lxa-2.4.0/tests/adrm/zpa.asm0000644000031500000010000000005414513025305015015 0ustar spectrestaff .word $0000 * = $0000 #include "bip.inc" xa-2.4.0/tests/adrm/zpa.ok0000644000031500000010000000005714513025305014651 0ustar spectrestaff­•Đű˘ ż#ť ĘĐö©… ©…!©˙…"©…#L LZL Lxa-2.4.0/tests/alxl/0000755000031500000010000000000014524607235013551 5ustar spectrestaffxa-2.4.0/tests/alxl/Makefile0000644000031500000010000000150714513025305015202 0ustar spectrestaffdefault: # xa should not allow this to happen. if it does, this test is no good. ../../xa alxl.s || exit 0 && exit 1 ../../xa alxlo1.s || exit 0 && exit 1 ../../xa alxlo2.s || exit 0 && exit 1 ../../xa alxlx1.s || exit 0 && exit 1 ../../xa alxlx2.s || exit 0 && exit 1 ../../xa alxlx3.s || exit 0 && exit 1 ../../xa sizes.s || exit 0 && exit 1 ../../xa -w alxlx1.s || exit 0 && exit 1 ../../xa -w alxlx2.s || exit 0 && exit 1 ../../xa -w alxlx3.s || exit 0 && exit 1 # expected-to-fail tests did fail. should be no more errors now. ../../xa -w alxl.s -o alxl.o ../hextool -cmp=alxl.ok < alxl.o ../../xa -w alxlo1.s -o alxlo1.o ../hextool -cmp=alxlo1.ok < alxlo1.o ../../xa -w alxlo2.s -o alxlo2.o ../hextool -cmp=alxlo2.ok < alxlo2.o ../../xa -w sizes.s -o sizes.o ../hextool -cmp=sizes.ok < sizes.o clean: rm -f *.o xa-2.4.0/tests/alxl/alxl.ok0000644000031500000010000000001314513025305015024 0ustar spectrestaff¢4 4©4xa-2.4.0/tests/alxl/alxl.s0000644000031500000010000000033314513025305014662 0ustar spectrestaff; test for the xa .xl opcode that should set the XR handling to 16 bit *=$f000 ; set X/Y registers to 16 bit ... rep #%00010000 ; ... and tell the assembler about it .xl ldx #$1234 ldy #$1234 .al lda #$1234 xa-2.4.0/tests/alxl/alxlo1.ok0000644000031500000010000000000514513025305015265 0ustar spectrestaff©4xa-2.4.0/tests/alxl/alxlo1.s0000644000031500000010000000027614513025305015130 0ustar spectrestaff; test for the xa .xl opcode that should set the XR handling to 16 bit *=$f000 ; set X/Y registers to 16 bit ... rep #%00010000 ; ... and tell the assembler about it .al lda #$1234 xa-2.4.0/tests/alxl/alxlo2.ok0000644000031500000010000000001014513025305015262 0ustar spectrestaff¢4 4xa-2.4.0/tests/alxl/alxlo2.s0000644000031500000010000000031114513025305015117 0ustar spectrestaff; test for the xa .xl opcode that should set the XR handling to 16 bit *=$f000 ; set X/Y registers to 16 bit ... rep #%00010000 ; ... and tell the assembler about it .xl ldx #$1234 ldy #$1234 xa-2.4.0/tests/alxl/alxlx1.s0000644000031500000010000000032614513025305015135 0ustar spectrestaff; test for the xa .xl opcode that should set the XR handling to 16 bit *=$f000 ; set X/Y registers to 16 bit ... rep #%00010000 ; ... and tell the assembler about it .al ldx #$1234 ldy #$1234 lda #$1234 xa-2.4.0/tests/alxl/alxlx2.s0000644000031500000010000000032514513025305015135 0ustar spectrestaff; test for the xa .xl opcode that should set the XR handling to 16 bit *=$f000 ; set X/Y registers to 16 bit ... rep #%00010000 ; ... and tell the assembler about it .xl ldx #$1234 ldy #$1234 lda #$1234 xa-2.4.0/tests/alxl/alxlx3.s0000644000031500000010000000032014513025305015131 0ustar spectrestaff; test for the xa .xl opcode that should set the XR handling to 16 bit *=$f000 ; set X/Y registers to 16 bit ... rep #%00010000 ; ... and tell the assembler about it ldx #$1234 ldy #$1234 lda #$1234 xa-2.4.0/tests/alxl/sizes.ok0000644000031500000010000000003614513025305015226 0ustar spectrestaff`\3"\3"Ż3"Ż3"­3"Ą3©H©3"Hxa-2.4.0/tests/alxl/sizes.s0000644000031500000010000000044214513025305015060 0ustar spectrestaff#define HI(z) (((z) >> 16) & $FFFF) #define LO(z) ((z) & $FFFF) .al .xl *=$112233 SYM: rts jmp SYM jmp $112233 lda $112233 lda @$2233 lda $2233 lda $33 #print HI(SYM) lda #HI(SYM) pha #print LO(SYM) lda #LO(SYM) pha xa-2.4.0/tests/aserr/0000755000031500000010000000000014524607235013725 5ustar spectrestaffxa-2.4.0/tests/aserr/Makefile0000644000031500000010000000062114514134123015352 0ustar spectrestaff default: test.s @echo expected to fail.... ../../xa -DBAD0 test.s || exit 0 && exit 1 ../../xa -DBAD1 test.s || exit 0 && exit 1 ../../xa -DBAD2 test.s || exit 0 && exit 1 ../../xa -DBAD3 test.s || exit 0 && exit 1 ../../xa -DBAD4 test.s || exit 0 && exit 1 ../../xa -DBAD5 test.s || exit 0 && exit 1 @echo no more failures! ../../xa test.s ../hextool -cmp=ok < a.o65 clean: rm -f a.o65 xa-2.4.0/tests/aserr/ok0000644000031500000010000000000214514126736014252 0ustar spectrestaff©xa-2.4.0/tests/aserr/test.s0000644000031500000010000000124214514134110015051 0ustar spectrestaff#if XA_MAJOR != 2 #error make sure this is up to date for future tests #endif #if XA_MINOR != 4 #error make sure this is up to date for future tests #endif * = $1000 #ifdef BAD0 .assert w=w, "what the" #endif w #ifdef BAD1 #error bad1 #endif #ifdef BAD2 .assert *<>$1000, "everything is bad" #endif lda #1 .assert *-2=w, "everything is really bad" .assert w==w, "everything sucks" .assert ((w & $ff00)>>8)=16, "everything is hideous" #ifdef BAD3 .assert *==$1003, "everything is terrible" #endif #ifdef BAD4 .assert w!=w, "everything sucks and is terrible and hideous and bad" #endif #ifdef BAD5 #if XA_MAJOR != 1 #error I want a really old version #endif #endif xa-2.4.0/tests/binclude/0000755000031500000010000000000014524607235014376 5ustar spectrestaffxa-2.4.0/tests/binclude/Makefile0000644000031500000010000000045014513025305016023 0ustar spectrestaffdefault: ../../xa test.asm -o test.o ../hextool -cmp=test.ok < test.o ../../xa -w test.asm -o test816.o ../hextool -cmp=test.ok < test816.o ../../xa test2.asm -o test2.o ../hextool -cmp=test2.ok < test2.o ../../xa test3.asm -o test3.o ../hextool -cmp=test.ok < test3.o clean: rm -f *.o xa-2.4.0/tests/binclude/README.1st0000600000031500000010000001204714513025305015746 0ustar spectrestaffThis 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 xa-2.4.0/tests/binclude/sd/0000755000031500000010000000000014513025305014772 5ustar spectrestaffxa-2.4.0/tests/binclude/sd/README.2nd0000600000031500000010000001204714513025305016330 0ustar spectrestaffThis 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 xa-2.4.0/tests/binclude/test.asm0000644000031500000010000000040514513025305016044 0ustar spectrestaff .word $9000 * = $9000 w = 10 glorb .dsb 9,10 ; +9 .byt 6, 6, 6, "devil", 'Q' ; +9 => 18 .bin 0,5,'README.1st' ; +5 => 23 .bin w,w+256,'README.1st' ; +266 => 289 ($0121) gleeb ; $0123 jmp glorb ; should be $9121 (remember the SA) jmp gleeb bne * xa-2.4.0/tests/binclude/test.ok0000644000031500000010000000045314513025305015700 0ustar spectrestaff devilQThis e 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,LL!‘Đţxa-2.4.0/tests/binclude/test2.asm0000644000031500000010000000024614513025305016131 0ustar spectrestaff .word $9000 * = $9000 w = 10 glorb .dsb 9,10 .byt 6, 6, 6, "devil", 'Q' .bin 0,109,'README.1st' .bin w,w+119,'README.1st' gleeb jmp glorb jmp gleeb bne * xa-2.4.0/tests/binclude/test2.ok0000644000031500000010000000041214513025305015755 0ustar spectrestaff devilQThis is the readme for xa, a cross-assembler for the 6502 and 65816 CPUs (and derivatives). xa is a small, fae readme for xa, a cross-assembler for the 6502 and 65816 CPUs (and derivatives). xa is a small, fast, portable two-pass assembleLL‘Đţxa-2.4.0/tests/binclude/test3.asm0000644000031500000010000000046514513025305016135 0ustar spectrestaff/* This should be the same as test.ok */ .word $9000 * = $9000 w = 10 glorb .dsb 9,10 ; +9 .byt 6, 6, 6, "devil", 'Q' ; +9 => 18 .bin 0,5,'sd/README.2nd' ; +5 => 23 .bin w,w+256,'sd/README.2nd' ; +266 => 289 ($0121) gleeb ; $0123 jmp glorb ; should be $9121 (remember the SA) jmp gleeb bne * xa-2.4.0/tests/branch/0000755000031500000010000000000014524607235014046 5ustar spectrestaffxa-2.4.0/tests/branch/Makefile0000644000031500000010000000041114513025305015470 0ustar spectrestaffdefault: # xa should not allow this to happen. if it does, this test is no good. ../../xa bor.s || exit 0 && exit 1 # expected-to-fail tests did fail. should be no more errors now. ../../xa -w bir.s -o test.o ../hextool -cmp=bir.ok < test.o clean: rm -f *.o xa-2.4.0/tests/branch/bir.ok0000644000031500000010000000021414513025305015140 0ustar spectrestaffĐ|đ€°üpúPřö0ôxa-2.4.0/tests/branch/bir.s0000644000031500000010000000015114513025305014771 0ustar spectrestaff/* just in range */ bcc pdq pdq bne xyz .dsb 124,6 xyz beq pdq bcs xyz bvs xyz bvc xyz bpl xyz bmi xyz xa-2.4.0/tests/branch/bor.s0000644000031500000010000000015114513025305014777 0ustar spectrestaff/* just in range */ bcc pdq pdq bne xyz .dsb 125,6 xyz beq pdq bcs xyz bvs xyz bvc xyz bpl xyz bmi xyz xa-2.4.0/tests/ca65/0000755000031500000010000000000014524607235013347 5ustar spectrestaffxa-2.4.0/tests/ca65/Makefile0000644000031500000010000000171614524606443015014 0ustar spectrestaff# # Makefile for tests # XA=../../xa CA65=ca65 LD65=ld65 OBJS=unnamed1 unnamed2 escape2 # escape1 test only relevant if xa23 mode is on #tests: unnamed1 unnamed2 escape1 escape2 clean tests: $(OBJS) # BSD make won't populate $< in these and GNU make doesn't like $> unnamed1: unnamed1.a65 #${CA65} unnamed1.a65; ${LD65} -t none -o unnamed1.ca65 unnamed1.o; rm unnamed1.o ${XA} -XCA65 unnamed1.a65 -o $@ ../hextool -cmp=unnamed1.ca65 < $@ unnamed2: unnamed2.a65 #${CA65} unnamed2.a65; ${LD65} -t none -o unnamed2.ca65 unnamed2.o; rm unnamed2.o ${XA} -XCA65 unnamed2.a65 -o $@ 2>a.err || true ../hextool -cmp=unnamed2.ca65 < $@ # add -XXA23 to actually test this escape1: escape1.a65 ${XA} escape1.a65 -o $@ ../hextool -cmp=escape1.out < $@ escape2: escape2.a65 #${CA65} escape2.a65; ${LD65} -t none -o escape2.ca65 escape2.o; rm escape2.o ${XA} -XCA65 escape2.a65 -o $@ 2>a.err || true ../hextool -cmp=escape2.ca65 < $@ clean: rm -f *.err a.o65 $(OBJS) xa-2.4.0/tests/ca65/escape1.a650000644000031500000010000000003014513025326015167 0ustar spectrestaff *=$1000 lda #"^^" xa-2.4.0/tests/ca65/escape1.out0000644000031500000010000000000214513025326015402 0ustar spectrestaff©^xa-2.4.0/tests/ca65/escape2.a650000644000031500000010000000003214513025326015172 0ustar spectrestaff .org $1000 lda #'^' xa-2.4.0/tests/ca65/escape2.ca650000644000031500000010000000000214513025326015332 0ustar spectrestaff©^xa-2.4.0/tests/ca65/unnamed1.a650000644000031500000010000000027514513025326015371 0ustar spectrestaff ; test of unnamed labels start: .org $4000 lda #$00 : iny ; first bne :- ; go to first beq :++ ; go to third : ; second jmp :- ; go to second jmp :++ : ldy #1 ; third : nop xa-2.4.0/tests/ca65/unnamed1.ca650000644000031500000010000000002014513107503015516 0ustar spectrestaff©ČĐýđL@L@ ęxa-2.4.0/tests/ca65/unnamed2.a650000644000031500000010000000032014513025326015361 0ustar spectrestaff ; test of unnamed labels start: .org $4000 lda #$00 : iny ; first bne :- ; go to first beq :++ ; go to third .scope : ; second jmp :- ; go to second jmp :++ : ldy #1 ; third .endscope : nop xa-2.4.0/tests/ca65/unnamed2.ca650000644000031500000010000000002014513122526015521 0ustar spectrestaff©ČĐýđL@L@ ęxa-2.4.0/tests/chardelimiter/0000755000031500000010000000000014524607241015422 5ustar spectrestaffxa-2.4.0/tests/chardelimiter/ok0000644000031500000010000000002314514122525015745 0ustar spectrestaff©A©A1234512345"''"nxa-2.4.0/tests/chardelimiter/test.s0000644000031500000010000000021514514121107016552 0ustar spectrestaff *=$033c lda #"A" lda #'A' .asc "12345" .asc '12345' .asc "\"" ; \ is escape character .asc '\'' .asc "'" .asc '"' .asc "\n" xa-2.4.0/tests/charset/0000755000031500000010000000000014524607235014242 5ustar spectrestaffxa-2.4.0/tests/charset/Makefile0000644000031500000010000000042114513025305015665 0ustar spectrestaffdefault: ../../xa test.s ../hextool -cmp=no-charset.o < a.o65 ../../xa -O PETSCII test.s ../hextool -cmp=petscii.o < a.o65 ../../xa -O PETSCREEN test.s ../hextool -cmp=petscreen.o < a.o65 ../../xa -O HIGH test.s ../hextool -cmp=high.o < a.o65 clean: rm -rf a.o65 xa-2.4.0/tests/charset/README.1st0000600000031500000010000001203114513025305015603 0ustar spectrestaffThis 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 xa-2.4.0/tests/charset/high.o0000644000031500000010000000012714513025305015327 0ustar spectrestaffThis is the readme fThis is thtest2ĆďďÂáňFooBarĆďďÂáňAa FooBarThis is thBarfooAa ©Á©Áxa-2.4.0/tests/charset/no-charset.o0000644000031500000010000000012714513025305016453 0ustar spectrestaffThis is the readme fThis is thtest2FooBarFooBarFooBarAa FooBarThis is thBarfooAa ©A©Axa-2.4.0/tests/charset/petscii.o0000644000031500000010000000012714513025305016050 0ustar spectrestaffThis is the readme fThis is thtest2fOObARFooBarfOObARAa FooBarThis is thBarfooAa ©a©axa-2.4.0/tests/charset/petscreen.o0000644000031500000010000000012714513025305016400 0ustar spectrestaffThis is the readme fThis is thtest2FBFooBarFBAa FooBarThis is thBarfooAa ©A©Axa-2.4.0/tests/charset/test.s0000644000031500000010000000035114513025305015372 0ustar spectrestaff .word $9000 * = $9000 w = 10 .bin 0,10+w,"README.1st" .bin 0,10,"README.1st" #include "test2.s" .byt "FooBar" .aasc "FooBar" .asc "FooBar",65,97,10 .aasc "FooBar" .bin 0,10,"README.1st" .aasc "Barfoo",65,97,10 lda #'A' lda #"A" xa-2.4.0/tests/charset/test2.s0000644000031500000010000000001614513025305015452 0ustar spectrestaff.aasc "test2" xa-2.4.0/tests/chppch/0000755000031500000010000000000014524607235014056 5ustar spectrestaffxa-2.4.0/tests/chppch/Makefile0000644000031500000010000000015514513025305015505 0ustar spectrestaffdefault: ../../xa -p'~' -e test.out test.c ../hextool -cmp=ok.out < test.out clean: rm -f a.o65 test.out xa-2.4.0/tests/chppch/ok.out0000644000031500000010000000005114513025305015202 0ustar spectrestaff12+12=12+12=24 10+10=10+10=20 5+5=5+5=10 xa-2.4.0/tests/chppch/qwerty.h0000644000031500000010000000004014513025305015542 0ustar spectrestaff rts #print 12+12 ~print 10+10 xa-2.4.0/tests/chppch/test.c0000644000031500000010000000004014513025305015161 0ustar spectrestaff#include "qwerty.h" ~print 5+5 xa-2.4.0/tests/comcom/0000755000031500000010000000000014524607235014066 5ustar spectrestaffxa-2.4.0/tests/comcom/Makefile0000644000031500000010000000047614513025305015523 0ustar spectrestaffdefault: # this should fail. ../../xa scomcom.asm || exit 0 && exit 1 # it did fail. these should now all succeed. ../../xa -M scomcom.asm ../hextool -cmp=scomcomm.ok < a.o65 ../../xa comcom.asm ../hextool -cmp=comcom.ok < a.o65 ../../xa -M comcom.asm ../hextool -cmp=comcomm.ok < a.o65 clean: rm -f a.o65 xa-2.4.0/tests/comcom/comcom.asm0000644000031500000010000000047414513025305016040 0ustar spectrestaff .word $c000 * = $c000 lda #147 ; depending on the -M option:lda #65 jsr $ffd2:rts ; maybe some stuff out here:tay ; there will be:cli ; extra code:sei ; or not:rti ; let's ; be ; tricky : ; does it ; work? :nop:nop: ; let's see! ; rts /* hey, ; what about now? : brk */ // do I make you sexy? ; :brk rti xa-2.4.0/tests/comcom/comcom.ok0000644000031500000010000000002114513025305015655 0ustar spectrestaffŔ©“©A Ň˙`¨Xx@ęę@xa-2.4.0/tests/comcom/comcomm.ok0000644000031500000010000000001114513025305016031 0ustar spectrestaffŔ©“ Ň˙`@xa-2.4.0/tests/comcom/scomcom.asm0000644000031500000010000000006014513025305016212 0ustar spectrestaff; some comment: *2 = 1 start lda #1: sta 2 xa-2.4.0/tests/comcom/scomcomm.ok0000644000031500000010000000000414513025305016216 0ustar spectrestaff©…xa-2.4.0/tests/cpktest/0000755000031500000010000000000014524607235014266 5ustar spectrestaffxa-2.4.0/tests/cpktest/Makefile0000644000031500000010000000042614514120550015715 0ustar spectrestaffdefault: ../../xa -l test.l -o test.o pack_eng.a65 ../hextool -cmp=test.l < english.l || exit 1 ../hextool -cmp=eng.ok < test.o ../../xa -l test.l -o test.o pack_ger.a65 ../hextool -cmp=test.l < deutsch.l || exit 1 ../hextool -cmp=de.ok < test.o clean: rm -f *.o test.l xa-2.4.0/tests/cpktest/c64def.def0000600000031500000010000001724514513025305016010 0ustar spectrestaff /* 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 xa-2.4.0/tests/cpktest/de.ok0000644000031500000010000000430514513025305015201 0ustar spectrestaff  ž2064 Ě˙ ¶ …©—   ©Ć   ©â   ®Ä© Í˝©ö   ©î   ©   ®Ĺ© Í˝©    ä˙đű˘ÝŹđčŕö°í sLŠ Ş˝€H˝H`. e á"býÁŃ…‰†‡ŚŠ‹“ (F1) PROGRAMME ZUSAMMENPACKEN (F2) ARCHIV AUSPACKEN (F3) QUELLPFAD: (F4) QUELLDEVICE: (F5) ZIELPFAD : (F6) ZIELDEVICE : (F7) QUELLDIRECTORY (F8) QUELLE UND ZIEL TAUSCHEN IHRE EINGABE BITTE ü °,©Ť Ť!  ÉĐ# Ö ű©Á   ­!®  Í˝© Ň˙ \© Ă˙`©§   L— UNGUELTIGE ARCHIV-VERSIONARCHIV HATTE BYTES #©ŤŤ© Ň˙ „ű  °4¤ű™$ćűÉđ Ň˙Lç ©„    \ÉJЩƠ  ©˙…ü ´ g ° L ©˝   ©…ü  °1É÷Đ#  ŤÉđ"  Ť$üâ­ ÎĐőL. $üĐ L.  " © Ă˙©ś   ­® Í˝© Ň˙(` DATEI AUSPACKEN (J/N)?ERGIBT BYTES #îĐî` „ąî™đČÉ:đÉ/Đ„Ŕ(馠ą$ťčČÉĐôĘŠ˘  ˝˙©®Ĺ  ş˙ Ŕ˙°  ` ąĆđČŔ(öŔđ!˘Ć  ˝˙©®Ä  ş˙ Ŕ˙° a ° g `8` ¤ ­đ, Í °© ©…ű Ď…ý†ţ g ćűĄűÍí " © Ă˙ g L`Ą`©¬    „ü±ý Ň˙ ¤üČÉĐď ¶ ° ”  ° s L‰ š © Ă˙©÷ © © Ň˙` cOPYING  „ąĆ™đČÉ:đÉ/Đ„Ŕ(馠±ýťčČÉĐőĘŠ˘  ˝˙©®Ä  ş˙ Ŕ˙° g `î Đî!`¬Ěđąî`­đ8`©ŤŤ˘ Ć˙©… Ď˙HĄđ©L Ň˙¦© Í˝© Ň˙h ý ¬™ČŚČđĄđŇĄŤ Ě˙L ©ŤŤŤ`®đčĐH š hLŤ ÍđH š hŤî`©Ť`­đ-ɰ­É÷đ ­ ÎĐő`©÷ ­ ­ ©Ť` ąîđČŔ(öŔđ$˘î  ˝˙©®Ĺ  ş˙ Ŕ˙° ­Ĺ g °  `8`©ŤŤ`¬™ČŚČĚĐH " h`˘ É˙¬Ěđ&ą Ň˙ĄđH©W çĄ @ ç© çh¨ « ČL* ©ŤŤ Ě˙`­ÄLj ­ĹH Ě˙© Ň˙h ´˙©o –˙©… Ą˙H Ň˙ Ą˙Éđ Ň˙Ąđň «˙hÉ0Đ`8`L}©Ť©“ Ň˙ b ŐóĄş ´˙Ąą –˙©… „ű Ą˙…ü¤ĐŇ Ą˙ĆűĐđ¦ü Í˝© Ň˙ Ą˙ÉđşÉĐLY Ň˙É"Đë­ Ď…ý†ţ „ű Ą˙ Ň˙¤űÉ"đ‘ýČŔë©,‘ýČ„ű Ą˙ Ň˙¤űÉ đň…ü‘ýČ©‘ýŞ Ą˙ Ň˙É Đőŕ<đ© Ň˙© Ň˙Ąü  Ą˙ÉĐůđ Ą˙¦ĐŞđ Ň˙LY© Ň˙ ä˙đ \ đLÄ BöL\ÉPđÉSđ`©­    \ÉJđ©˝   `©Ć   î`JA/NEINťťťťťťť’NEIN ’JA ˘† & &…¦ & &e…Še…©$e…H©e…Şh`©“ Ň˙ b ŐóĄş ´˙Ąą –˙©… „ű Ą˙…ü¤Đ2 Ą˙ĆűĐđ¦ü Í˝© Ň˙ Ą˙¦ĐŞđ Ň˙L5© Ň˙ ä˙đ \ ĐĂ BöL\ ä˙đű`©$Ť˘† ąĆđ É:đ ČŔ(ň©:ťč ąĆťđÉ:đÉ/ІčČŔ(č¦č©*ťč©.ťč©*ť芢  ˝˙©®Ä Lş˙îÄ­ÄÉ ©ŤÄ`îĹ­ĹÉ ©ŤĹ`©    `Ą ą™Ćđ ČŔ'ó©™Ć` BITTE NEUEN QUELLPFAD EINGEBEN: ©B    `Ą ą™îđ ČŔ'ó©™î` BITTE NEUEN ZIELPFAD EINGEBEN: ­Ä®ĹŽÄŤĹ˘˝ĆH˝îťĆhťîčŕ(í`©ŤĆŤîĄşÉÉ ©ŤÄŤĹ`…"„# ±"đ Ň˙ć"Đóć#Đď`©Ť ĐŤ!Đ©™ Ň˙`xa-2.4.0/tests/cpktest/deutsch.l0000644000031500000010000001046614513025305016077 0ustar spectrestaffbasicend, 0x080b, 1, 0x0000 iniscreen, 0x10b6, 1, 0x0000 inipar, 0x1085, 1, 0x0000 menu1, 0x0819, 2, 0x0000 m1atxt, 0x0897, 2, 0x0000 Txtout, 0x10a0, 1, 0x0000 quellpfad, 0x10c6, 1, 0x0000 m1btxt, 0x08e2, 2, 0x0000 quelldrv, 0x10c4, 1, 0x0000 m1ctxt, 0x08f6, 2, 0x0000 zielpfad, 0x10ee, 1, 0x0000 m1dtxt, 0x0908, 2, 0x0000 zieldrv, 0x10c5, 1, 0x0000 m1etxt, 0x091c, 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, 0x0b2f, 1, 0x0000 unpack, 0x0966, 1, 0x0000 quelle, 0x0fe2, 1, 0x0000 ziel, 0x1023, 1, 0x0000 switch, 0x1063, 1, 0x0000 dir, 0x0efe, 1, 0x0000 qdrv, 0x0fc2, 1, 0x0000 zdrv, 0x0fd2, 1, 0x0000 openarcrd, 0x0afc, 1, 0x0000 cls, 0x0997, 12, 0x0000 rcnt, 0x1320, 1, 0x0000 rbyte, 0x0c06, 1, 0x0000 verr, 0x099d, 12, 0x0000 loop, 0x097a, 12, 0x0000 unpackfile, 0x09d6, 1, 0x0000 t1, 0x09c1, 12, 0x0000 waitkey, 0x0f5c, 1, 0x0000 verrtxt, 0x09a7, 12, 0x0000 wcnt, 0x131e, 1, 0x0000 l1, 0x09e7, 15, 0x0000 endx, 0x0a20, 15, 0x0000 filetab, 0x1324, 1, 0x0000 endnam, 0x09fd, 15, 0x0000 ask, 0x0a84, 15, 0x0000 nounpack, 0x0a23, 15, 0x0000 tok, 0x0ec6, 1, 0x0000 fxopen, 0x0ab4, 1, 0x0000 Getzst, 0x0d67, 1, 0x0000 xa, 0x0a2a, 15, 0x0000 lo, 0x0a2e, 15, 0x0000 end, 0x0a83, 15, 0x0000 tno, 0x0ebd, 1, 0x0000 cls, 0x0a64, 15, 0x0000 xb, 0x0a5a, 15, 0x0000 wxanz, 0x121a, 1, 0x0000 wxbyt, 0x1219, 1, 0x0000 ly, 0x0a4c, 15, 0x0000 wbyte, 0x0d0c, 1, 0x0000 wbuf, 0x0d22, 1, 0x0000 t1, 0x0a9c, 15, 0x0000 incwcnt, 0x0aab, 1, 0x0000 l1, 0x0ab3, 20, 0x0000 l1, 0x0ab8, 21, 0x0000 l2, 0x0acf, 21, 0x0000 l1a, 0x0ac9, 21, 0x0000 l1b, 0x0acb, 21, 0x0000 l3, 0x0ad3, 21, 0x0000 err, 0x0afb, 21, 0x0000 clrwrbuf, 0x0d03, 1, 0x0000 l0, 0x0afe, 22, 0x0000 l1, 0x0b08, 22, 0x0000 err, 0x0b2d, 22, 0x0000 Getqst, 0x0d61, 1, 0x0000 clrrdbuf, 0x0c67, 1, 0x0000 getlist, 0x0da4, 1, 0x0000 anzfiles, 0x1116, 1, 0x0000 end, 0x0b63, 23, 0x0000 openarcwr, 0x0ccd, 1, 0x0000 cls, 0x0b5b, 23, 0x0000 l1, 0x0b45, 23, 0x0000 setfadr, 0x0ecf, 1, 0x0000 packfile, 0x0b67, 1, 0x0000 lft, 0x0bac, 24, 0x0000 l1, 0x0b70, 24, 0x0000 fopen, 0x0bb6, 1, 0x0000 le, 0x0b97, 24, 0x0000 clrwxbyt, 0x0c94, 1, 0x0000 l2, 0x0b89, 24, 0x0000 l3, 0x0b94, 24, 0x0000 wxbyte, 0x0c73, 1, 0x0000 savwxbyt, 0x0c9a, 1, 0x0000 l1, 0x0bba, 26, 0x0000 l2, 0x0bd1, 26, 0x0000 l1a, 0x0bcb, 26, 0x0000 l1b, 0x0bcd, 26, 0x0000 l3, 0x0bd5, 26, 0x0000 err, 0x0bfc, 26, 0x0000 incrcnt, 0x0bfd, 1, 0x0000 l1, 0x0c05, 27, 0x0000 ro, 0x121c, 1, 0x0000 ri, 0x121b, 1, 0x0000 leerbuf, 0x0c16, 28, 0x0000 rb, 0x121e, 1, 0x0000 rf, 0x121d, 1, 0x0000 ldbuf, 0x0c1d, 28, 0x0000 lok, 0x0c2e, 28, 0x0000 l0, 0x0c47, 28, 0x0000 le, 0x0c5c, 28, 0x0000 add, 0x0c8d, 31, 0x0000 ad2, 0x0c83, 31, 0x0000 adx, 0x0c90, 31, 0x0000 nosav, 0x0ccc, 33, 0x0000 savs, 0x0cb6, 33, 0x0000 l1, 0x0caa, 33, 0x0000 l0, 0x0ccf, 34, 0x0000 l1, 0x0cd9, 34, 0x0000 err, 0x0d01, 34, 0x0000 wi, 0x1117, 1, 0x0000 wo, 0x1118, 1, 0x0000 wb, 0x1119, 1, 0x0000 nowr, 0x0d21, 36, 0x0000 l1, 0x0d2a, 37, 0x0000 end, 0x0d55, 37, 0x0000 l0, 0x0d4e, 37, 0x0000 Getst, 0x0d6a, 1, 0x0000 l1, 0x0d87, 38, 0x0000 l2, 0x0d95, 38, 0x0000 err, 0x0d9f, 38, 0x0000 l4x, 0x0da1, 39, 0x0000 l4, 0x0e7d, 39, 0x0000 setdirnam, 0x0f62, 1, 0x0000 l0, 0x0dc4, 39, 0x0000 l1, 0x0dc6, 39, 0x0000 la, 0x0de0, 39, 0x0000 l3x, 0x0dee, 39, 0x0000 l3, 0x0e59, 39, 0x0000 lb, 0x0e01, 39, 0x0000 lc, 0x0e16, 39, 0x0000 ld, 0x0e1b, 39, 0x0000 lf, 0x0e32, 39, 0x0000 lg, 0x0e46, 39, 0x0000 testkeys, 0x0e83, 1, 0x0000 lh, 0x0e50, 39, 0x0000 l2, 0x0e69, 39, 0x0000 l5, 0x0e76, 39, 0x0000 ok, 0x0e8c, 40, 0x0000 t1, 0x0ead, 40, 0x0000 ja, 0x0ea2, 40, 0x0000 l0, 0x0f19, 45, 0x0000 l1, 0x0f1b, 45, 0x0000 l4, 0x0f56, 45, 0x0000 l3, 0x0f35, 45, 0x0000 l2, 0x0f45, 45, 0x0000 l5, 0x0f52, 45, 0x0000 p1, 0x0014, 46, 0x0000 l1, 0x0f6d, 46, 0x0000 nodp, 0x0f7b, 46, 0x0000 dp, 0x0f81, 46, 0x0000 dp1, 0x0f83, 46, 0x0000 end, 0x0f9b, 46, 0x0000 l2a, 0x0f93, 46, 0x0000 l2, 0x0f95, 46, 0x0000 ok, 0x0fd1, 47, 0x0000 ok, 0x0fe1, 48, 0x0000 quelltxt, 0x1001, 49, 0x0000 q1, 0x0fee, 49, 0x0000 end, 0x1000, 49, 0x0000 quelltxt, 0x1042, 51, 0x0000 q1, 0x102f, 51, 0x0000 end, 0x1041, 51, 0x0000 l1, 0x1071, 53, 0x0000 noval, 0x1097, 54, 0x0000 ok, 0x1099, 54, 0x0000 p, 0x0022, 55, 0x0000 l1, 0x10a4, 55, 0x0000 le, 0x10b5, 55, 0x0000 sysmem, 0x1324, 1, 0x0000 ecnt, 0x1322, 1, 0x0000 ende, 0x10c4, 1, 0x0000 xa-2.4.0/tests/cpktest/eng.ok0000644000031500000010000000432314513025305015362 0ustar spectrestaff  ž2064 Ě˙ Ä “©—  ®©Ô  ®©á  ®®Ň© Í˝©ö  ®©ü  ®©   ®®Ó© Í˝©#  ® ä˙đű˘ÝŹđčŕö°í sLŠ Ş˝€H˝H`1 o ä*pÄÔ…‰†‡ŚŠ‹“ (F1) PACK PROGRAMMS (F2) EXTRACT FROM ARCHIVE (F3) SOURCEPATH/ARC: (F4) SOURCEDEVICE: (F5) TARGETPATH/ARC: (F6) TARGETDEVICE : (F7) SOURCEDIRECTORY (F8) EXCHANGE TARGET AND SOURCE YOUR CHOICE PLEASE ˙ °,©Ť.Ť/ ÉĐ# Ý ű©É  ®­/®. Í˝© Ň˙ _© Ă˙`©±  ®Lˇ UNKNOWN ARCHIVE VERSIONARCHIVE HAD BYTES #©Ť,Ť-© Ň˙ „ű °4¤ű™2ćűÉđ Ň˙Lî ©‹  ® _ÉJЩɠ ®©˙…ü · j ° LŠ ©Ŕ  ®©…ü °1É÷Đ# Ť(Éđ" Ť'$üâ­'  Î(ĐőL5 $üĐ  L5  % © Ă˙©   ®­-®, Í˝© Ň˙(` EXTRACT FILE (Y/N)?GIVES BYTES #î,Đî-` „ąü™đČÉ:đÉ/Đ„Ŕ(馠ą2ťčČÉĐôĘŠ˘  ˝˙©®Ó  ş˙ Ŕ˙°  ` ąÔđČŔ(öŔđ!˘Ô  ˝˙©®Ň  ş˙ Ŕ˙° d ° j `8` § ­$đ, Đ °©  ©…ű Ň…ý†ţ j ćűĄűÍ$í % © Ă˙ j L`Ą`©Ż  ® „ü±ý Ň˙  ¤üČÉĐď ą ° — ° v LŚ ť © Ă˙©÷  ©  © Ň˙` cOPYING  „ąÔ™đČÉ:đÉ/Đ„Ŕ(馠±ýťčČÉĐőĘŠ˘  ˝˙©®Ň  ş˙ Ŕ˙° j `î.Đî/`¬*Ě)đą,î*`­+đ8`©Ť)Ť*˘ Ć˙©… Ď˙HĄđ©L Ň˙¦© Í˝© Ň˙h ¬)™,ČŚ)ČđĄđŇĄŤ+ Ě˙L ©Ť)Ť*Ť+`®(đčĐH ť hL Í'đH ť hŤ'î(`©Ť(`­(đ-ɰ­'É÷đ ­'  Î(Đő`©÷  ­(  ­'  ©Ť(` ąüđČŔ(öŔđ$˘ü  ˝˙©®Ó  ş˙ Ŕ˙° ­Ó j °  `8`©Ť%Ť&`¬%™'ČŚ%ČĚ&ĐH % h`˘ É˙¬&Ě%đ&ą' Ň˙ĄđH©W çĄ @ ç© çh¨ ® ČL- ©Ť%Ť& Ě˙`­ŇLm ­ÓH Ě˙© Ň˙h ´˙©o –˙©… Ą˙H Ň˙ Ą˙Éđ Ň˙Ąđň «˙hÉ0Đ`8`L€©Ť$©“ Ň˙ e ŐóĄş ´˙Ąą –˙©… „ű Ą˙…ü¤ĐŇ Ą˙ĆűĐđ¦ü Í˝© Ň˙ Ą˙ÉđşÉĐL\ Ň˙É"Đë­$ Ň…ý†ţ „ű Ą˙ Ň˙¤űÉ"đ‘ýČŔë©,‘ýČ„ű Ą˙ Ň˙¤űÉ đň…ü‘ýČ©‘ýŞ Ą˙ Ň˙É Đőŕ<đ© Ň˙© Ň˙Ąü † Ą˙ÉĐůđ Ą˙¦ĐŞđ Ň˙L\© Ň˙ ä˙đ _ đLÇ BöL_ÉPđÉSđ`©°  ® _ÉJđ©Ŕ  ®`©É  ®î$`YES/NO ťťťťťťť’NO ’YES ˘† & &…¦ & &e…Še…©2e…H©e…Şh`©“ Ň˙ e ŐóĄş ´˙Ąą –˙©… „ű Ą˙…ü¤Đ2 Ą˙ĆűĐđ¦ü Í˝© Ň˙ Ą˙¦ĐŞđ Ň˙L8© Ň˙ ä˙đ _ ĐĂ BöL_ ä˙đű`©$Ť˘† ąÔđ É:đ ČŔ(ň©:ťč ąÔťđÉ:đÉ/ІčČŔ(č¦č©*ťč©.ťč©*ť芢  ˝˙©®Ň Lş˙îŇ­ŇÉ ©ŤŇ`îÓ­ÓÉ ©ŤÓ`©  ® `Ą ą™Ôđ ČŔ'ó©™Ô` PLEASE INPUT NEW SOURCEPATH/ARCHIVE: ©J  ® `Ą ą™üđ ČŔ'ó©™ü` PLEASE INPUT NEW TARGETPATH/ARCHIVE: ­Ň®ÓŽŇŤÓ˘˝ÔH˝üťÔhťüčŕ(í`©ŤÔŤüĄşÉÉ ©ŤŇŤÓ`…"„# ±"đ Ň˙ć"Đóć#Đď`©Ť ĐŤ!Đ©™ Ň˙`xa-2.4.0/tests/cpktest/english.l0000644000031500000010000001046614513025305016071 0ustar spectrestaffbasicend, 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 xa-2.4.0/tests/cpktest/pack_eng.a650000600000031500000010000004722614513025305016343 0ustar spectrestaff #include "c64def.def" #define Tout(a) .(:lda #a:jsr Txtout:.) #define Aout(a) .(:lda #b:jsr Txtout:jmp c:b .byt a,0:c .) #define Ibout(a) .(:ldx a:lda #0:jsr INTOUT:.) #define Iout(a) .(:ldx a:lda a+1:jsr INTOUT:.) #define PFADLEN 40 #define FN_WR 3 #define FN_RD 4 #define XCODE $f7 #define Version 1 .( .word $0801 *=$0801 .word basicend,10 .byt $9e,"2064",0 ;sys $0810 basicend .word 0 .byt 0,0,0 .( jsr CLRCH jsr iniscreen jsr inipar menu1 Tout(m1atxt) Tout(quellpfad) Tout(m1btxt) Ibout(quelldrv) Tout(m1ctxt) Tout(zielpfad) Tout(m1dtxt) Ibout(zieldrv) Tout(m1etxt) next jsr GET beq next ldx #0 l1 cmp befkeys,x beq exe inx cpx #Anzbefs bcc l1 bcs next exe jsr exec jmp menu1 exec txa asl tax lda madr+1,x pha lda madr,x pha rts madr .word pack-1,unpack-1,quelle-1,ziel-1,switch-1,dir-1,qdrv-1,zdrv-1 befkeys .asc TC_F1,TC_F2,TC_F3,TC_F5,TC_F8,TC_F7,TC_F4,TC_F6 Anzbefs =8 m1atxt .asc TC_LCH,TC_SCO,TC_FF,TC_LF,TC_LF .asc "(F1) PACK PROGRAMMS",TC_CR,TC_LF .asc "(F2) EXTRACT FROM ARCHIVE",TC_CR,TC_LF .asc "(F3) SOURCEPATH/ARC:",0 m1btxt .asc TC_CR,TC_LF .asc "(F4) SOURCEDEVICE:",0 m1ctxt .asc TC_CR,TC_LF .asc "(F5) TARGETPATH/ARC:",0 m1dtxt .asc TC_CR,TC_LF .asc "(F6) TARGETDEVICE :",0 m1etxt .asc TC_CR,TC_LF .asc "(F7) SOURCEDIRECTORY",TC_CR,TC_LF .asc "(F8) EXCHANGE TARGET AND SOURCE",TC_CR,TC_LF .asc "YOUR CHOICE PLEASE",TC_CR,0 .) unpack .( jsr openarcrd bcs cls lda #0 sta rcnt sta rcnt+1 jsr rbyte cmp #Version bne verr loop jsr unpackfile bcc loop Tout(t1) lda rcnt+1 ldx rcnt jsr INTOUT lda #TC_CR jsr BSOUT jsr waitkey cls lda #FN_RD jsr CLOSE rts verr Tout(verrtxt) jmp cls verrtxt .asc "UNKNOWN ARCHIVE VERSION",0 t1 .asc "ARCHIVE HAD BYTES #",0 .) unpackfile .( lda #0 sta wcnt sta wcnt+1 lda #TC_CR jsr BSOUT ldy #0 sty P1 l1 jsr rbyte bcs endx ldy P1 sta filetab,y inc P1 cmp #0 beq endnam jsr BSOUT jmp l1 endnam Tout(ask) jsr waitkey cmp #"J" bne nounpack Tout(tok) lda #<-1 sta P1+1 jsr fxopen jsr Getzst bcs xa bcc lo endx jmp end nounpack Tout(tno) xa lda #0 sta P1+1 lo jsr rbyte bcs cls cmp #XCODE bne xb jsr rbyte sta wxanz cmp #0 clc beq cls jsr rbyte sta wxbyt bit P1+1 bpl lo ly lda wxbyt jsr wbyte dec wxanz bne ly jmp lo xb bit P1+1 bpl lo jsr wbyte jmp lo cls php jsr wbuf lda #FN_WR jsr CLOSE Tout(t1) lda wcnt+1 ldx wcnt jsr INTOUT lda #TC_CR jsr BSOUT plp end rts ask .asc TC_CR,"EXTRACT FILE (Y/N)?",0 t1 .asc "GIVES BYTES #",0 .) incwcnt .( inc wcnt bne l1 inc wcnt+1 l1 rts .) fxopen .( ldy #0 sty INT l1 lda zielpfad,y sta INBUF,y beq l2 iny cmp #":" beq l1a cmp #"/" bne l1b l1a sty INT l1b cpy #PFADLEN bcc l1 l2 ldx INT ldy #0 l3 lda filetab,y sta INBUF,x inx iny cmp #0 bne l3 dex txa ldx #INBUF jsr SETFNPAR lda #FN_WR ldx zieldrv ldy #1 jsr SETFPAR jsr OPEN bcs err jsr clrwrbuf clc err rts .) openarcrd .( ldy #0 l0 lda quellpfad,y beq l1 iny cpy #PFADLEN bcc l0 l1 cpy #0 beq err tya ldx #quellpfad jsr SETFNPAR lda #FN_RD ldx quelldrv ldy #0 jsr SETFPAR jsr OPEN bcs err jsr Getqst bcs err jsr clrrdbuf clc rts err sec rts .) pack .( jsr getlist lda anzfiles beq end jsr openarcwr bcs cls lda #Version jsr wbyte lda #0 sta P1 l1 jsr setfadr sta P2 stx P2+1 jsr packfile inc P1 lda P1 cmp anzfiles bcc l1 jsr wbuf cls lda #FN_WR jsr CLOSE jsr Getzst end jmp LINEIN:rts .) packfile .( Tout(lft) ldy #0 l1 sty P1+1 lda (P2),y jsr BSOUT jsr wbyte ldy P1+1 iny cmp #0 bne l1 jsr fopen bcs le jsr clrwxbyt l2 jsr rbyte bcs l3 jsr wxbyte jmp l2 l3 jsr savwxbyt le lda #FN_RD jsr CLOSE lda #XCODE jsr wbyte lda #0 jsr wbyte lda #TC_CR jsr BSOUT rts lft .asc TC_CR,"cOPYING ",0 .) fopen .( ldy #0 sty INT l1 lda quellpfad,y sta INBUF,y beq l2 iny cmp #":" beq l1a cmp #"/" bne l1b l1a sty INT l1b cpy #PFADLEN bcc l1 l2 ldx INT ldy #0 l3 lda (P2),y sta INBUF,x inx iny cmp #0 bne l3 dex txa ldx #INBUF jsr SETFNPAR lda #FN_RD ldx quelldrv ldy #0 jsr SETFPAR jsr OPEN bcs err jsr clrrdbuf clc err rts .) incrcnt .( inc rcnt bne l1 inc rcnt+1 l1 rts .) rbyte .( ldy ro cpy ri beq leerbuf lda rb,y inc ro clc rts leerbuf lda rf beq ldbuf sec rts ldbuf lda #0 sta ri sta ro ldx #FN_RD jsr CHKIN lda #0 sta STATUS lok jsr BASIN pha lda STATUS beq l0 lda #"L" jsr BSOUT Ibout($90) lda #TC_CR jsr BSOUT l0 pla jsr incrcnt ldy ri sta rb,y iny sty ri iny ;cpy ro beq le lda STATUS beq lok le lda STATUS sta rf jsr CLRCH jmp rbyte .) clrrdbuf .( lda #0 sta ri sta ro sta rf rts .) wxbyte .( ldx wxanz beq add inx bne ad2 pha jsr savwxbyt pla jmp add ad2 cmp wxbyt beq adx pha jsr savwxbyt pla add sta wxbyt adx inc wxanz rts .) clrwxbyt .( lda #0 sta wxanz rts .) savwxbyt .( lda wxanz beq nosav cmp #4 bcs savs lda wxbyt cmp #XCODE beq savs l1 lda wxbyt jsr wbyte dec wxanz bne l1 rts savs lda #XCODE jsr wbyte lda wxanz jsr wbyte lda wxbyt jsr wbyte lda #0 sta wxanz nosav rts .) openarcwr .( ldy #0 l0 lda zielpfad,y beq l1 iny cpy #PFADLEN bcc l0 l1 cpy #0 beq err tya ldx #zielpfad jsr SETFNPAR lda #FN_WR ldx zieldrv ldy #1 jsr SETFPAR jsr OPEN bcs err lda zieldrv jsr Getzst bcs err jsr clrwrbuf clc rts err sec rts .) clrwrbuf .( lda #0 sta wi sta wo rts .) wbyte .( ldy wi sta wb,y iny sty wi iny cpy wo bne nowr pha jsr wbuf pla nowr rts .) wbuf .( ldx #FN_WR jsr CKOUT ldy wo l1 cpy wi beq end lda wb,y jsr BSOUT lda STATUS beq l0 tya pha lda #"W" jsr $e716 lda $90 ora #$40 jsr $e716 lda #TC_CR jsr $e716 pla tay l0 jsr incwcnt iny jmp l1 end lda #0 sta wi sta wo jsr CLRCH rts .) .( &Getqst lda quelldrv jmp Getst &Getzst lda zieldrv &Getst pha jsr CLRCH lda #TC_CR jsr BSOUT pla jsr TALK lda #15+$60 jsr SECTALK lda #0 sta STATUS jsr IECIN pha jsr BSOUT l1 jsr IECIN cmp #0 beq l2 jsr BSOUT lda STATUS beq l1 l2 jsr UNTALK pla cmp #"0" bne err clc rts err sec rts .) /* showlist .( lda #0 sta P1 l1 lda P1 cmp anzfiles bcs le jsr setfadr lda #TC_CR jsr BSOUT lda INT ldy INT+1 jsr Txtout inc P1 jmp l1 le rts .) */ .( l4x jmp l4 &getlist lda #0 sta anzfiles lda #TC_FF jsr BSOUT jsr setdirnam jsr SENDNAM lda DEVADR jsr TALK lda SECADR jsr SECTALK lda #0 sta STATUS ldy #3 l0 sty P1 l1 jsr IECIN sta P1+1 ldy STATUS bne l4x jsr IECIN dec P1 bne l1 ldx P1+1 jsr INTOUT lda #" " jsr BSOUT la jsr IECIN cmp #0 beq l4x cmp #TC_REV bne l3x jmp l3 l3x jsr BSOUT cmp #34 bne la lda anzfiles jsr setfadr sta P2 stx P2+1 ldy #0 lb sty P1 jsr IECIN jsr BSOUT ldy P1 cmp #34 beq lc sta (P2),y iny cpy #17 bcc lb lc lda #"," sta (P2),y iny ld sty P1 jsr IECIN jsr BSOUT ldy P1 cmp #" " beq ld sta P1+1 sta (P2),y iny lda #0 sta (P2),y /* lda #TC_CR jsr BSOUT lda P2+1 ldx P2 jsr INTOUT lda #":" jsr BSOUT lda P2 ldy P2+1 jsr Txtout */ lf tax jsr IECIN jsr BSOUT cmp #" " bne lf cpx #"<" beq lg lda #" " jsr BSOUT lg lda #" " jsr BSOUT lda P1+1 jsr testkeys lh jsr IECIN cmp #0 bne lh beq l2 l3 jsr IECIN ldx STATUS bne l4 tax beq l2 jsr BSOUT jmp l3 l2 lda #TC_CR jsr BSOUT jsr GET beq l5 jsr waitkey l5 ldy #2 beq l4 jmp l0 l4 jsr CLSFIL jmp waitkey .) testkeys .( cmp #"P" beq ok cmp #"S" beq ok rts ok Tout(t1) jsr waitkey cmp #"J" beq ja Tout(tno) rts ja Tout(tok) inc anzfiles rts t1 .asc TC_REV,"YES/NO ",TC_CRL,TC_CRL,TC_CRL .asc TC_CRL,TC_CRL,TC_CRL,TC_CRL,0 &tno .asc TC_REO,"NO ",0 &tok .asc TC_REO,"YES ",0 .) setfadr .( ldx #0 stx INT+1 asl rol INT+1 asl rol INT+1 sta INT ldx INT+1 asl rol INT+1 asl rol INT+1 clc adc INT sta INT txa adc INT+1 sta INT+1 lda #filetab adc INT+1 sta INT+1 tax pla rts .) dir .( lda #TC_FF jsr BSOUT jsr setdirnam jsr SENDNAM lda DEVADR jsr TALK lda SECADR jsr SECTALK lda #0 sta STATUS ldy #3 l0 sty P1 l1 jsr IECIN sta P1+1 ldy STATUS bne l4 jsr IECIN dec P1 bne l1 ldx P1+1 jsr INTOUT lda #" " jsr BSOUT l3 jsr IECIN ldx STATUS bne l4 tax beq l2 jsr BSOUT jmp l3 l2 lda #TC_CR jsr BSOUT jsr GET beq l5 jsr waitkey l5 ldy #2 bne l0 l4 jsr CLSFIL jmp waitkey .) waitkey jsr GET beq waitkey rts setdirnam .( p1 =INT lda #"$" sta INBUF ldx #1 stx p1 ldy #0 l1 lda quellpfad,y beq nodp cmp #":" beq dp iny cpy #PFADLEN bcc l1 nodp lda #":" sta INBUF,x inx dp ldy #0 dp1 lda quellpfad,y sta INBUF,x beq end cmp #":" beq l2a cmp #"/" bne l2 l2a stx p1 l2 inx iny cpy #PFADLEN bcc dp1 end ldx p1 inx lda #"*" sta INBUF,x inx lda #"." sta INBUF,x inx lda #"*" sta INBUF,x inx txa ldx #INBUF jsr SETFNPAR lda #1 ldx quelldrv ldy #0 jmp SETFPAR .) qdrv .( inc quelldrv lda quelldrv cmp #12 bcc ok lda #8 sta quelldrv ok rts .) zdrv .( inc zieldrv lda zieldrv cmp #12 bcc ok lda #8 sta zieldrv ok rts .) quelle .( Tout(quelltxt) jsr LINEIN ldy #0 q1 lda INBUF,y sta quellpfad,y beq end iny cpy #PFADLEN-1 bcc q1 lda #0 sta quellpfad,y end rts quelltxt .asc TC_CR,"PLEASE INPUT NEW SOURCEPATH/ARCHIVE:",TC_CR,0 .) ziel .( Tout(quelltxt) jsr LINEIN ldy #0 q1 lda INBUF,y sta zielpfad,y beq end iny cpy #PFADLEN-1 bcc q1 lda #0 sta zielpfad,y end rts quelltxt .asc TC_CR,"PLEASE INPUT NEW TARGETPATH/ARCHIVE:",TC_CR,0 .) switch .( lda quelldrv ldx zieldrv stx quelldrv sta zieldrv ldx #0 l1 lda quellpfad,x pha lda zielpfad,x sta quellpfad,x pla sta zielpfad,x inx cpx #PFADLEN bcc l1 rts .) inipar .( lda #0 sta quellpfad sta zielpfad lda DEVADR cmp #8 bcc noval cmp #12 bcc ok noval lda #8 ok sta quelldrv sta zieldrv rts .) Txtout .( p =$22 sta p sty p+1 l1 ldy #0 lda (p),y beq le jsr BSOUT inc p bne l1 inc p+1 bne l1 le rts .) iniscreen .( lda #COL_SCHWARZ sta VIC+VIC_EXTCOL sta VIC+VIC_BCKCOL0 lda #TC_HELLGRUEN jsr BSOUT rts .) sysmem =* quelldrv =sysmem zieldrv =sysmem+1 -sysmem +=2 quellpfad =sysmem zielpfad =sysmem+PFADLEN -sysmem +=2*PFADLEN anzfiles =sysmem -sysmem +=1 wi =sysmem wo =sysmem+1 -sysmem +=2 wb =sysmem -sysmem +=256 wxbyt =sysmem wxanz =sysmem+1 -sysmem +=2 ri =sysmem ro =sysmem+1 rf =sysmem+2 -sysmem +=3 rb =sysmem -sysmem +=256 wcnt =sysmem -sysmem +=2 rcnt =sysmem -sysmem +=2 ecnt =sysmem -sysmem +=2 filetab =sysmem ende .) xa-2.4.0/tests/cpktest/pack_ger.a650000600000031500000010000004721014513025305016340 0ustar spectrestaff #include "c64def.def" #define Tout(a) .(:lda #a:jsr Txtout:.) #define Aout(a) .(:lda #b:jsr Txtout:jmp c:b .byt a,0:c .) #define Ibout(a) .(:ldx a:lda #0:jsr INTOUT:.) #define Iout(a) .(:ldx a:lda a+1:jsr INTOUT:.) #define PFADLEN 40 #define FN_WR 3 #define FN_RD 4 #define XCODE $f7 #define Version 1 .( .word $0801 *=$0801 .word basicend,10 .byt $9e,"2064",0 ;sys $0810 basicend .word 0 .byt 0,0,0 .( jsr CLRCH jsr iniscreen jsr inipar menu1 Tout(m1atxt) Tout(quellpfad) Tout(m1btxt) Ibout(quelldrv) Tout(m1ctxt) Tout(zielpfad) Tout(m1dtxt) Ibout(zieldrv) Tout(m1etxt) next jsr GET beq next ldx #0 l1 cmp befkeys,x beq exe inx cpx #Anzbefs bcc l1 bcs next exe jsr exec jmp menu1 exec txa asl tax lda madr+1,x pha lda madr,x pha rts madr .word pack-1,unpack-1,quelle-1,ziel-1,switch-1,dir-1,qdrv-1,zdrv-1 befkeys .asc TC_F1,TC_F2,TC_F3,TC_F5,TC_F8,TC_F7,TC_F4,TC_F6 Anzbefs =8 m1atxt .asc TC_LCH,TC_SCO,TC_FF,TC_LF,TC_LF .asc "(F1) PROGRAMME ZUSAMMENPACKEN",TC_CR,TC_LF .asc "(F2) ARCHIV AUSPACKEN",TC_CR,TC_LF .asc "(F3) QUELLPFAD:",0 m1btxt .asc TC_CR,TC_LF .asc "(F4) QUELLDEVICE:",0 m1ctxt .asc TC_CR,TC_LF .asc "(F5) ZIELPFAD :",0 m1dtxt .asc TC_CR,TC_LF .asc "(F6) ZIELDEVICE :",0 m1etxt .asc TC_CR,TC_LF .asc "(F7) QUELLDIRECTORY",TC_CR,TC_LF .asc "(F8) QUELLE UND ZIEL TAUSCHEN",TC_CR,TC_LF .asc "IHRE EINGABE BITTE",TC_CR,0 .) unpack .( jsr openarcrd bcs cls lda #0 sta rcnt sta rcnt+1 jsr rbyte cmp #Version bne verr loop jsr unpackfile bcc loop Tout(t1) lda rcnt+1 ldx rcnt jsr INTOUT lda #TC_CR jsr BSOUT jsr waitkey cls lda #FN_RD jsr CLOSE rts verr Tout(verrtxt) jmp cls verrtxt .asc "UNGUELTIGE ARCHIV-VERSION",0 t1 .asc "ARCHIV HATTE BYTES #",0 .) unpackfile .( lda #0 sta wcnt sta wcnt+1 lda #TC_CR jsr BSOUT ldy #0 sty P1 l1 jsr rbyte bcs endx ldy P1 sta filetab,y inc P1 cmp #0 beq endnam jsr BSOUT jmp l1 endnam Tout(ask) jsr waitkey cmp #"J" bne nounpack Tout(tok) lda #<-1 sta P1+1 jsr fxopen jsr Getzst bcs xa bcc lo endx jmp end nounpack Tout(tno) xa lda #0 sta P1+1 lo jsr rbyte bcs cls cmp #XCODE bne xb jsr rbyte sta wxanz cmp #0 clc beq cls jsr rbyte sta wxbyt bit P1+1 bpl lo ly lda wxbyt jsr wbyte dec wxanz bne ly jmp lo xb bit P1+1 bpl lo jsr wbyte jmp lo cls php jsr wbuf lda #FN_WR jsr CLOSE Tout(t1) lda wcnt+1 ldx wcnt jsr INTOUT lda #TC_CR jsr BSOUT plp end rts ask .asc TC_CR,"DATEI AUSPACKEN (J/N)?",0 t1 .asc "ERGIBT BYTES #",0 .) incwcnt .( inc wcnt bne l1 inc wcnt+1 l1 rts .) fxopen .( ldy #0 sty INT l1 lda zielpfad,y sta INBUF,y beq l2 iny cmp #":" beq l1a cmp #"/" bne l1b l1a sty INT l1b cpy #PFADLEN bcc l1 l2 ldx INT ldy #0 l3 lda filetab,y sta INBUF,x inx iny cmp #0 bne l3 dex txa ldx #INBUF jsr SETFNPAR lda #FN_WR ldx zieldrv ldy #1 jsr SETFPAR jsr OPEN bcs err jsr clrwrbuf clc err rts .) openarcrd .( ldy #0 l0 lda quellpfad,y beq l1 iny cpy #PFADLEN bcc l0 l1 cpy #0 beq err tya ldx #quellpfad jsr SETFNPAR lda #FN_RD ldx quelldrv ldy #0 jsr SETFPAR jsr OPEN bcs err jsr Getqst bcs err jsr clrrdbuf clc rts err sec rts .) pack .( jsr getlist lda anzfiles beq end jsr openarcwr bcs cls lda #Version jsr wbyte lda #0 sta P1 l1 jsr setfadr sta P2 stx P2+1 jsr packfile inc P1 lda P1 cmp anzfiles bcc l1 jsr wbuf cls lda #FN_WR jsr CLOSE jsr Getzst end jmp LINEIN:rts .) packfile .( Tout(lft) ldy #0 l1 sty P1+1 lda (P2),y jsr BSOUT jsr wbyte ldy P1+1 iny cmp #0 bne l1 jsr fopen bcs le jsr clrwxbyt l2 jsr rbyte bcs l3 jsr wxbyte jmp l2 l3 jsr savwxbyt le lda #FN_RD jsr CLOSE lda #XCODE jsr wbyte lda #0 jsr wbyte lda #TC_CR jsr BSOUT rts lft .asc TC_CR,"cOPYING ",0 .) fopen .( ldy #0 sty INT l1 lda quellpfad,y sta INBUF,y beq l2 iny cmp #":" beq l1a cmp #"/" bne l1b l1a sty INT l1b cpy #PFADLEN bcc l1 l2 ldx INT ldy #0 l3 lda (P2),y sta INBUF,x inx iny cmp #0 bne l3 dex txa ldx #INBUF jsr SETFNPAR lda #FN_RD ldx quelldrv ldy #0 jsr SETFPAR jsr OPEN bcs err jsr clrrdbuf clc err rts .) incrcnt .( inc rcnt bne l1 inc rcnt+1 l1 rts .) rbyte .( ldy ro cpy ri beq leerbuf lda rb,y inc ro clc rts leerbuf lda rf beq ldbuf sec rts ldbuf lda #0 sta ri sta ro ldx #FN_RD jsr CHKIN lda #0 sta STATUS lok jsr BASIN pha lda STATUS beq l0 lda #"L" jsr BSOUT Ibout($90) lda #TC_CR jsr BSOUT l0 pla jsr incrcnt ldy ri sta rb,y iny sty ri iny ;cpy ro beq le lda STATUS beq lok le lda STATUS sta rf jsr CLRCH jmp rbyte .) clrrdbuf .( lda #0 sta ri sta ro sta rf rts .) wxbyte .( ldx wxanz beq add inx bne ad2 pha jsr savwxbyt pla jmp add ad2 cmp wxbyt beq adx pha jsr savwxbyt pla add sta wxbyt adx inc wxanz rts .) clrwxbyt .( lda #0 sta wxanz rts .) savwxbyt .( lda wxanz beq nosav cmp #4 bcs savs lda wxbyt cmp #XCODE beq savs l1 lda wxbyt jsr wbyte dec wxanz bne l1 rts savs lda #XCODE jsr wbyte lda wxanz jsr wbyte lda wxbyt jsr wbyte lda #0 sta wxanz nosav rts .) openarcwr .( ldy #0 l0 lda zielpfad,y beq l1 iny cpy #PFADLEN bcc l0 l1 cpy #0 beq err tya ldx #zielpfad jsr SETFNPAR lda #FN_WR ldx zieldrv ldy #1 jsr SETFPAR jsr OPEN bcs err lda zieldrv jsr Getzst bcs err jsr clrwrbuf clc rts err sec rts .) clrwrbuf .( lda #0 sta wi sta wo rts .) wbyte .( ldy wi sta wb,y iny sty wi iny cpy wo bne nowr pha jsr wbuf pla nowr rts .) wbuf .( ldx #FN_WR jsr CKOUT ldy wo l1 cpy wi beq end lda wb,y jsr BSOUT lda STATUS beq l0 tya pha lda #"W" jsr $e716 lda $90 ora #$40 jsr $e716 lda #TC_CR jsr $e716 pla tay l0 jsr incwcnt iny jmp l1 end lda #0 sta wi sta wo jsr CLRCH rts .) .( &Getqst lda quelldrv jmp Getst &Getzst lda zieldrv &Getst pha jsr CLRCH lda #TC_CR jsr BSOUT pla jsr TALK lda #15+$60 jsr SECTALK lda #0 sta STATUS jsr IECIN pha jsr BSOUT l1 jsr IECIN cmp #0 beq l2 jsr BSOUT lda STATUS beq l1 l2 jsr UNTALK pla cmp #"0" bne err clc rts err sec rts .) /* showlist .( lda #0 sta P1 l1 lda P1 cmp anzfiles bcs le jsr setfadr lda #TC_CR jsr BSOUT lda INT ldy INT+1 jsr Txtout inc P1 jmp l1 le rts .) */ .( l4x jmp l4 &getlist lda #0 sta anzfiles lda #TC_FF jsr BSOUT jsr setdirnam jsr SENDNAM lda DEVADR jsr TALK lda SECADR jsr SECTALK lda #0 sta STATUS ldy #3 l0 sty P1 l1 jsr IECIN sta P1+1 ldy STATUS bne l4x jsr IECIN dec P1 bne l1 ldx P1+1 jsr INTOUT lda #" " jsr BSOUT la jsr IECIN cmp #0 beq l4x cmp #TC_REV bne l3x jmp l3 l3x jsr BSOUT cmp #34 bne la lda anzfiles jsr setfadr sta P2 stx P2+1 ldy #0 lb sty P1 jsr IECIN jsr BSOUT ldy P1 cmp #34 beq lc sta (P2),y iny cpy #17 bcc lb lc lda #"," sta (P2),y iny ld sty P1 jsr IECIN jsr BSOUT ldy P1 cmp #" " beq ld sta P1+1 sta (P2),y iny lda #0 sta (P2),y /* lda #TC_CR jsr BSOUT lda P2+1 ldx P2 jsr INTOUT lda #":" jsr BSOUT lda P2 ldy P2+1 jsr Txtout */ lf tax jsr IECIN jsr BSOUT cmp #" " bne lf cpx #"<" beq lg lda #" " jsr BSOUT lg lda #" " jsr BSOUT lda P1+1 jsr testkeys lh jsr IECIN cmp #0 bne lh beq l2 l3 jsr IECIN ldx STATUS bne l4 tax beq l2 jsr BSOUT jmp l3 l2 lda #TC_CR jsr BSOUT jsr GET beq l5 jsr waitkey l5 ldy #2 beq l4 jmp l0 l4 jsr CLSFIL jmp waitkey .) testkeys .( cmp #"P" beq ok cmp #"S" beq ok rts ok Tout(t1) jsr waitkey cmp #"J" beq ja Tout(tno) rts ja Tout(tok) inc anzfiles rts t1 .asc TC_REV,"JA/NEIN",TC_CRL,TC_CRL,TC_CRL .asc TC_CRL,TC_CRL,TC_CRL,TC_CRL,0 &tno .asc TC_REO,"NEIN ",0 &tok .asc TC_REO,"JA ",0 .) setfadr .( ldx #0 stx INT+1 asl rol INT+1 asl rol INT+1 sta INT ldx INT+1 asl rol INT+1 asl rol INT+1 clc adc INT sta INT txa adc INT+1 sta INT+1 lda #filetab adc INT+1 sta INT+1 tax pla rts .) dir .( lda #TC_FF jsr BSOUT jsr setdirnam jsr SENDNAM lda DEVADR jsr TALK lda SECADR jsr SECTALK lda #0 sta STATUS ldy #3 l0 sty P1 l1 jsr IECIN sta P1+1 ldy STATUS bne l4 jsr IECIN dec P1 bne l1 ldx P1+1 jsr INTOUT lda #" " jsr BSOUT l3 jsr IECIN ldx STATUS bne l4 tax beq l2 jsr BSOUT jmp l3 l2 lda #TC_CR jsr BSOUT jsr GET beq l5 jsr waitkey l5 ldy #2 bne l0 l4 jsr CLSFIL jmp waitkey .) waitkey jsr GET beq waitkey rts setdirnam .( p1 =INT lda #"$" sta INBUF ldx #1 stx p1 ldy #0 l1 lda quellpfad,y beq nodp cmp #":" beq dp iny cpy #PFADLEN bcc l1 nodp lda #":" sta INBUF,x inx dp ldy #0 dp1 lda quellpfad,y sta INBUF,x beq end cmp #":" beq l2a cmp #"/" bne l2 l2a stx p1 l2 inx iny cpy #PFADLEN bcc dp1 end ldx p1 inx lda #"*" sta INBUF,x inx lda #"." sta INBUF,x inx lda #"*" sta INBUF,x inx txa ldx #INBUF jsr SETFNPAR lda #1 ldx quelldrv ldy #0 jmp SETFPAR .) qdrv .( inc quelldrv lda quelldrv cmp #12 bcc ok lda #8 sta quelldrv ok rts .) zdrv .( inc zieldrv lda zieldrv cmp #12 bcc ok lda #8 sta zieldrv ok rts .) quelle .( Tout(quelltxt) jsr LINEIN ldy #0 q1 lda INBUF,y sta quellpfad,y beq end iny cpy #PFADLEN-1 bcc q1 lda #0 sta quellpfad,y end rts quelltxt .asc TC_CR,"BITTE NEUEN QUELLPFAD EINGEBEN:",TC_CR,0 .) ziel .( Tout(quelltxt) jsr LINEIN ldy #0 q1 lda INBUF,y sta zielpfad,y beq end iny cpy #PFADLEN-1 bcc q1 lda #0 sta zielpfad,y end rts quelltxt .asc TC_CR,"BITTE NEUEN ZIELPFAD EINGEBEN:",TC_CR,0 .) switch .( lda quelldrv ldx zieldrv stx quelldrv sta zieldrv ldx #0 l1 lda quellpfad,x pha lda zielpfad,x sta quellpfad,x pla sta zielpfad,x inx cpx #PFADLEN bcc l1 rts .) inipar .( lda #0 sta quellpfad sta zielpfad lda DEVADR cmp #8 bcc noval cmp #12 bcc ok noval lda #8 ok sta quelldrv sta zieldrv rts .) Txtout .( p =$22 sta p sty p+1 l1 ldy #0 lda (p),y beq le jsr BSOUT inc p bne l1 inc p+1 bne l1 le rts .) iniscreen .( lda #COL_SCHWARZ sta VIC+VIC_EXTCOL sta VIC+VIC_BCKCOL0 lda #TC_HELLGRUEN jsr BSOUT rts .) sysmem =* quelldrv =sysmem zieldrv =sysmem+1 -sysmem +=2 quellpfad =sysmem zielpfad =sysmem+PFADLEN -sysmem +=2*PFADLEN anzfiles =sysmem -sysmem +=1 wi =sysmem wo =sysmem+1 -sysmem +=2 wb =sysmem -sysmem +=256 wxbyt =sysmem wxanz =sysmem+1 -sysmem +=2 ri =sysmem ro =sysmem+1 rf =sysmem+2 -sysmem +=3 rb =sysmem -sysmem +=256 wcnt =sysmem -sysmem +=2 rcnt =sysmem -sysmem +=2 ecnt =sysmem -sysmem +=2 filetab =sysmem ende .) xa-2.4.0/tests/cpp/0000755000031500000010000000000014524607236013374 5ustar spectrestaffxa-2.4.0/tests/cpp/Makefile0000644000031500000010000000017514513025305015024 0ustar spectrestaffdefault: $(CC) -E over.c > over.asm ../../xa -w over.asm ../hextool -cmp=expected.o < a.o65 clean: rm -f over.asm a.o65 xa-2.4.0/tests/cpp/expected.o0000644000031500000010000000002214513025305015334 0ustar spectrestaff©L`©ŤĐů`ŻŔŔŔxa-2.4.0/tests/cpp/over.c0000644000031500000010000000046214513025305014502 0ustar spectrestaff/* #define BUG */ #ifdef BUG #define WW AA #define AA WW #else #define CC 1 #define WW CC #define AA WW #endif /* This has a .c extension for those cc -E's that won't deal with .asm */ * = $0000 lda #AA jmp buggy rts #include "over.h" /* the buggy will force a line number to be printed */ buggy xa-2.4.0/tests/cpp/over.h0000644000031500000010000000011714513025305014504 0ustar spectrestaff #define X W #define W 5 fuzz lda #W sta $0400 bne fuzz rts lda @$c0c0c0 xa-2.4.0/tests/csapiec/0000755000031500000010000000000014524607236014221 5ustar spectrestaffxa-2.4.0/tests/csapiec/Makefile0000644000031500000010000000060414513025305015646 0ustar spectrestaffdefault: # xa should not allow this to happen. if it does, this test is no good. ../../xa -DBUG=1 -o test.o test.s || exit 0 && exit 1 ../../xa -R -DBUG=1 -o testseg.o test.s || exit 0 && exit 1 # xa *should* allow this to happen. ../../xa -o test.o test.s ../hextool -cmp=test.ok < test.o ../../xa -R -o testseg.o test.s ../hextool -cmp=testseg.ok < testseg.o clean: rm -f *.o xa-2.4.0/tests/csapiec/test.ok0000644000031500000010000000012514513025305015516 0ustar spectrestaff$@renamescratchcopynewvalidateinitializeassigncdrdmddrv˙ &18;>Axa-2.4.0/tests/csapiec/test.s0000644000031500000010000000125414513025305015353 0ustar spectrestaff .text c0 =*-1 #ifdef BUG .data #endif cmdt .asc "$",0 cow .asc "@",0 c2 .asc "rename",0 c3 .asc "scratch",0 c4 .asc "copy",0 c5 .asc "new",0 c6 .asc "validate",0 c7 .asc "initialize",0 ;c8 .asc "rmdir",0 ;c9 .asc "mkdir",0 ;c10 .asc "chdir",0 c11 .asc "assign",0 c12 .asc "cd",0 c13 .asc "rd",0 c14 .asc "md",0 c15 .asc "drv",0 ; iec-bus-unit cmda .byt cmdt-c0 .byt AF"c0˙cmdtcowc2c3 c4c5c6c7%c110c127c13:c14=c15@cmdaDxa-2.4.0/tests/dos51/0000755000031500000010000000000014524607236013545 5ustar spectrestaffxa-2.4.0/tests/dos51/Makefile0000644000031500000010000000041214513025305015167 0ustar spectrestaffdefault: # xa should not allow this to happen. if it does, this test is no good. ../../xa -DBUG test.s || exit 0 && exit 1 # expected-to-fail tests did fail. should be no more errors now. ../../xa test.s -o test.o ../hextool -cmp=ok < test.o clean: rm -f *.o xa-2.4.0/tests/dos51/dos51.inc0000644000031500000010000000465214513025305015167 0ustar spectrestaff/* dos wedge code for inlining into routines */ /* define SA51 to allow stand-alone generation */ #ifdef SA51 .word SA51 * = SA51 #endif /* otherwise assume this has been inlined via #include <> */ /* define BASIC51 to use BASIC interface stub */ #ifdef BASIC51 jsr $aefd jsr $ad9e jsr $b6a3 ; leaving a=len x=lb y=hb #endif /* otherwise load a with length, x/y = lb/hb */ .( crunchsrv = $a57c setlfs = $ffba setnam = $ffbd open = $ffc0 close = $ffc3 clall = $ffe7 chkin = $ffc6 chkout = $ffc9 clrchn = $ffcc chrin = $ffcf getin = $ffe4 print = $ffd2 readst = $ffb7 chrout = print ready = $e37b cnvrtdec = $bdcd erasealine = 59903 workzp = $a5 sta work1 sty workzp+1 stx workzp ; set the filename (directory, error channel and commands) ; a, x and y already setup for us jsr setnam ; are we requesting just the error channel? ldx work1 beq errchn ; yes ; are we requesting a disk directory? ldy #0 lda (workzp),y cmp #"$" bne errchn ; no ; yes, display directory lda #$01 ldx 186 ldy #$00 jsr setlfs jsr open ; open 1,dev,0 to read as BASIC formatted text lda #147 jsr print clc ldx #01 jsr chkin bcs dirdone jsr chrin jsr chrin lda #$0d jsr print ; routine to print each line of the directory dirpll jsr chrin jsr chrin ; skip line link jsr chrin ; grab length (as line #) sta work1 jsr chrin sta work2 ; stash for later jsr readst ; EOF or other error? bne dirdone ; yes, end directory lda work2 ; no, print this line ldx work1 jsr cnvrtdec ; first the number/length lda #$20 jsr print ; and a space jsr chrin dirpl jsr print ; then the filename in quotes and filetype until a null jsr chrin adc #0 bne dirpl ; no null yet lda #13 ; yes, null, print CR jsr print jmp dirpll ; and do next line ; finish directory and clear channel, then fall through to errchn dirdone lda #1 jsr close jsr clall lda #0 jsr setnam ; common routine for error channel and disk commands errchn lda #15 ldx $ba ldy #15 jsr setlfs ; open 15,8,15,command jsr open lda #18 jsr print ; rvson ; read until there's a null, adding $0d for devices that don't errchnl ldx #15 jsr chkin jsr chrin sta work1 jsr readst ; power 64 sucks sometimes =-( sta work2 ; its emulated messages have no $0d lda work1 jsr print lda work2 beq errchnl lda work1 cmp #13 beq errchnd lda #13 jsr print errchnd lda #15 jsr close jsr clall lda #146 jsr print ; rvsoff rts work1 .byt 0 work2 .byt 0 .) xa-2.4.0/tests/dos51/ok0000644000031500000010000000031514513025305014065 0ustar spectrestaff#ÁŤěÁ„¦†Ą ˝˙®ěÁđs ±ĄÉ$Đk©¦ş  ş˙ Ŕ˙©“ Ň˙˘ Ć˙°E Ď˙ Ď˙© Ň˙ Ď˙ Ď˙ Ď˙ŤěÁ Ď˙ŤíÁ ·˙Đ#­íÁ®ěÁ Í˝© Ň˙ Ď˙ Ň˙ Ď˙iĐö© Ň˙L^Á© Ă˙ ç˙© ˝˙©¦ş  ş˙ Ŕ˙© Ň˙˘ Ć˙ Ď˙ŤěÁ ·˙ŤíÁ­ěÁ Ň˙­íÁđä­ěÁÉ đ© Ň˙© Ă˙ ç˙©’ Ň˙`xa-2.4.0/tests/dos51/test.s0000644000031500000010000000011114513025305014666 0ustar spectrestaff#define SA51 $c123 #include "dos51.inc" #ifdef BUG jsr crunchsrv #endif xa-2.4.0/tests/expando/0000755000031500000010000000000014524607241014244 5ustar spectrestaffxa-2.4.0/tests/expando/ok0000644000031500000010000000020014524315711014566 0ustar spectrestaffxa-2.4.0/tests/expando/test.s0000644000031500000010000000147514524316602015414 0ustar spectrestaffPBI=6 #define NIB(x) PBI+((x&1)>>0), \ PBI+((x&2)>>1), \ PBI+((x&4)>>2), \ PBI+((x&8)>>3) tab0 .byt NIB(10),NIB(12),NIB(0), NIB(0) .byt NIB(10),NIB(12),NIB(15),NIB(0) .byt NIB(10),NIB(12),NIB(0), NIB(15) .byt NIB(10),NIB(12),NIB(15),NIB(15) ; oh well. tab1 .byt PBI+0,PBI+1,PBI+0,PBI+1,PBI+0,PBI+0,PBI+1,PBI+1 .byt PBI+0,PBI+0,PBI+0,PBI+0,PBI+0,PBI+0,PBI+0,PBI+0 .byt PBI+0,PBI+1,PBI+0,PBI+1,PBI+0,PBI+0,PBI+1,PBI+1 .byt PBI+1,PBI+1,PBI+1,PBI+1,PBI+0,PBI+0,PBI+0,PBI+0 .byt PBI+0,PBI+1,PBI+0,PBI+1,PBI+0,PBI+0,PBI+1,PBI+1 .byt PBI+0,PBI+0,PBI+0,PBI+0,PBI+1,PBI+1,PBI+1,PBI+1 .byt PBI+0,PBI+1,PBI+0,PBI+1,PBI+0,PBI+0,PBI+1,PBI+1 .byt PBI+1,PBI+1,PBI+1,PBI+1,PBI+1,PBI+1,PBI+1,PBI+1 xa-2.4.0/tests/fordef/0000755000031500000010000000000014524607236014057 5ustar spectrestaffxa-2.4.0/tests/fordef/Makefile0000644000031500000010000000046114513025305015505 0ustar spectrestaffdefault: # this must not pass. ../../xa -DFAIL test3.asm || exit 0 && exit 1 # these must pass. ../../xa test3.asm ../hextool -cmp=test3.ok < a.o65 # testing warnings. ../../xa -e test.out test.asm ../hextool -cmp=ok.out < test.out ../hextool -cmp=test1.ok < a.o65 clean: rm -f a.o65 test.out xa-2.4.0/tests/fordef/ok.out0000644000031500000010000000030214513025305015201 0ustar spectrestafftest.asm:line 6: 0400: Warning - Can't optimize forward-defined label; using absolute addressing test.asm:line 7: 0403: Warning - Can't optimize forward-defined label; using absolute addressing xa-2.4.0/tests/fordef/test.asm0000644000031500000010000000033414513025305015525 0ustar spectrestaff .word $0400 * = $0400 /* this should generate optimizer warnings */ lda forward1 sta forward2 /* this shouldn't */ jmp forward3 /* and this won't */ t1 lda `forward1 sta `forward2 rts #include "test2.asm" xa-2.4.0/tests/fordef/test1.ok0000644000031500000010000000002114513025305015430 0ustar spectrestaff­ŤLĄ…``xa-2.4.0/tests/fordef/test2.asm0000644000031500000010000000005514513025305015607 0ustar spectrestaff forward1 = $02 forward2 = $03 forward3 rts xa-2.4.0/tests/fordef/test3.asm0000644000031500000010000000052614513025305015613 0ustar spectrestaff .word $0400 *=$0400 /* define this if you want to crash and burn */ #ifdef FAIL jmp `forward3 bne `forward3 lda (`forward1),y lda (`forward3),y #echo congrats, you have FAILED! #endif sta `forward3 /* this looks like it should fail, but won't because there is no ambiguity */ lda (forward1),y jmp forward3 #include "test2.asm" xa-2.4.0/tests/fordef/test3.ok0000644000031500000010000000001314513025305015433 0ustar spectrestaffŤ±L`xa-2.4.0/tests/harness0000755000031500000010000000434414524317477014215 0ustar spectrestaff#!/usr/bin/perl -s $cc ||= "cc"; $make ||= "make"; $cflags ||= ''; $makeflags ||= ''; # defeat multiple jobs, this doesn't do parallel right now #$make =~ s/-j\d*(\s|$)//; #$make =~ s/--jobserver-[^\s]+//; #$makeflags =~ s/-j\d*(\s|$)//; #$makeflags =~ s/--jobserver-[^\s]+//; $ENV{'CC'} = $cc; $ENV{'MAKE'} = $make; $ENV{'CFLAGS'} = $cflags; $ENV{'MFLAGS'} = $makeflags; $ENV{'MAKEFLAGS'} = $makeflags; $|++; $ntests = 0; $dtests = $tests || "ALL"; $tests = '' if ($tests eq "ALL"); print <<"EOF"; CC = $cc CFLAGS = $cflags MAKE = $make MAKEFLAGS = $makeflags EOF # Get a list of all directories. If there is a Makefile there, do it. # If there is not, see if there is an .s file and an ok binary to cmp to. # Otherwise, do nothing (acknowledge and ignore directories we don't grok). opendir(D, ".") || die("test harness failed: $!\n"); while($x = readdir(D)) { next if ($x =~ /^\./ || $x =~ /\s/); next if (length($tests) && ($tests !~ /$x/)); next if (! -d $x); if (-r "$x/Makefile") { push(@mtests, $x); } else { push(@stests, $x); } } closedir(D); @tests = (); push(@tests, sort @mtests) if (scalar(@mtests)); push(@tests, sort @stests) if (scalar(@stests)); print "matching tests: "; print join(",", @tests); print "\n\n"; W: foreach $x (@tests) { next W if (!chdir($x)); $x = substr($x . " " . ("." x 79), 0, 50); print STDOUT "$x > "; if (-e "Makefile") { print STDOUT "running Makefile\n"; print STDOUT "=" x 79, "\n"; system("$make clean"); print STDOUT "-" x 79, "\n"; system("$make"); print STDOUT "-" x 79, "\n"; if ($?) { print STDOUT "## FAILURE (make clean NOT run) ##\n"; exit 1; } system("$make clean"); print STDOUT "=" x 35, " PASSED! ", "=" x 35, "\n"; $ntests++; } elsif (-e "ok" && -e "test.s") { unlink("a.o65"); &failed("../../xa test.s"); &failed("../hextool -cmp=ok < a.o65"); unlink("a.o65"); print STDOUT "PASSED\n"; $ntests++; } else { print STDOUT "ignored\n"; } chdir(".."); } print STDOUT "=" x 79, "\n"; if ($ntests) { # ntestacy is a terrible thing print STDOUT "\n## ALL SELECTED TESTS PASS ($dtests, n=$ntests) ##\n"; exit 0; } print STDOUT "\n## NO TESTS WERE RUN ##\n"; exit 1; sub failed { system(@_); if ($?) { print STDOUT "## FAILURE ##\n"; exit 1; } } xa-2.4.0/tests/hextool0000755000031500000010000000234314513025305014211 0ustar spectrestaff#!/usr/bin/perl -s # This tool either emits hex in a machine or human parseable format, or # compares two binaries in the form of cmp. It is mostly to deal with # systems with an unreliable hexdump, that *lack* hexdump (or od), and/or # emit non-standard output. # "use bytes" BEGIN { $^H |= 0x00000008 unless ($] < 5.006); } if ($output || $noutput) { # check output mode. If $output, there must be output. If there is # $noutput there must NOT be output. Feed tee or something to this. $wasoutput = 0; while(<>) { $wasoutput++; } exit (($wasoutput && $output) ? 0 : ($wasoutput && $noutput) ? 1 : (!$wasoutput && !$noutput) ? 0 : 1); } if ($cmp) { # compare mode. both files must fit in memory. to eliminate any # weirdness about endianness, encoding, etc., we unpack them to # hex bytes and just compare strings. undef $/; open(W, "$cmp") || die("can't open $cmp: $!\n"); $cmp = unpack("H*", ); close(W); $std = unpack("H*", <>); if ($cmp ne $std) { print <<"EOF"; FAILED! received from stdin ------------------- $std expected to equal ----------------- $cmp FAILED! EOF exit 255; } exit 0; } # hexdump mode. accept data on stdin, spew a stream of hex bytes. while(<>) { print STDOUT unpack("H*", $_); } xa-2.4.0/tests/incerr/0000755000031500000010000000000014524607236014074 5ustar spectrestaffxa-2.4.0/tests/incerr/Makefile0000644000031500000010000000022614513025305015521 0ustar spectrestaffdefault: # in 6502 mode, it will fail. ../../xa test.s || exit 0 && exit 1 # in 65816 mode, it will pass. ../../xa -w test.s clean: rm -f a.o65 xa-2.4.0/tests/incerr/test.65020000644000031500000010000000000514513025305015351 0ustar spectrestaff .xl xa-2.4.0/tests/incerr/test.s0000644000031500000010000000002514513025305015221 0ustar spectrestaff#include "test.6502" xa-2.4.0/tests/ldoreloc/0000755000031500000010000000000014524607236014415 5ustar spectrestaffxa-2.4.0/tests/ldoreloc/1.s0000644000031500000010000000003014513025305014717 0ustar spectrestaffjsr bla: loop: jmp loop xa-2.4.0/tests/ldoreloc/10.s0000644000031500000010000000004114513025326015004 0ustar spectrestaff jsr bla loop: jmp loop lda l1 xa-2.4.0/tests/ldoreloc/2.s0000644000031500000010000000001114513025305014717 0ustar spectrestaffbla: rts xa-2.4.0/tests/ldoreloc/20.s0000644000031500000010000000010514513025501015001 0ustar spectrestaff jsr bla loop: jmp loop lda #loop lda #l1 xa-2.4.0/tests/ldoreloc/30.s0000644000031500000010000000003214513025501015001 0ustar spectrestaff jsr bla loop: jmp loop xa-2.4.0/tests/ldoreloc/31.s0000644000031500000010000000003114513025501015001 0ustar spectrestaff jsr loop bla: jmp bla xa-2.4.0/tests/ldoreloc/40.s0000644000031500000010000000004614513025501015007 0ustar spectrestafffoo =$1234 jsr bla loop: jmp loop xa-2.4.0/tests/ldoreloc/41.s0000644000031500000010000000007214513025501015007 0ustar spectrestaff jsr loop bla: jmp bla lda foo lda #foo xa-2.4.0/tests/ldoreloc/50.s0000644000031500000010000000007514513025501015012 0ustar spectrestafffoo =$1234 jsr bla loop: jmp loop .data bar .word bla xa-2.4.0/tests/ldoreloc/51.s0000644000031500000010000000012214513025501015004 0ustar spectrestaff jsr loop bla: lda bar .data .word foo .word bar .byte foo xa-2.4.0/tests/ldoreloc/60.s0000644000031500000010000000013114517124232015011 0ustar spectrestaff .zero ptr .word 0 .text foo =$1234 lda ptr2 loop: jmp loop .data bar .word bla xa-2.4.0/tests/ldoreloc/61.s0000644000031500000010000000015714517124232015022 0ustar spectrestaff jsr loop bla: lda ptr lda #ptr .zero ptr2 .byt 0 .data .word foo .word bar .byte foo xa-2.4.0/tests/ldoreloc/Makefile0000644000031500000010000000545214524606662016065 0ustar spectrestaff default: all all: t1 t2 t10 t11 t20 t21 t30 t31 t40 t41 t50 t51 t60 t61 t62 # BSD only has suffix rules .SUFFIXES: .o65 .hex #%.o65: %.s .s.o65: ../../xa -R -c -o $@ $< #%.hex: %.o65 .o65.hex: ../hextool $< > $@ linked.o65: 1.o65 2.o65 ../../ldo65 -o $@ 1.o65 2.o65 linked2.o65: 1.o65 2.o65 ../../ldo65 -o $@ 2.o65 1.o65 linked10.o65: 10.o65 2.o65 ../../ldo65 -U -o $@ 10.o65 2.o65 linked11.o65: 10.o65 2.o65 ../../ldo65 -U -o $@ 2.o65 10.o65 linked20.o65: 20.o65 2.o65 ../../ldo65 -Ll1 -o $@ 2.o65 20.o65 linked21.o65: 20.o65 2.o65 ../../ldo65 -L l1 -o $@ 20.o65 2.o65 linked22.o65: 20.o65 2.o65 ../../ldo65 -o $@ 20.o65 2.o65 && exit 1 || exit 0 linked30.o65: 30.o65 31.o65 ../../ldo65 -o $@ 30.o65 31.o65 linked31.o65: 30.o65 31.o65 ../../ldo65 -o $@ 31.o65 30.o65 linked40.o65: 40.o65 41.o65 ../../ldo65 -o $@ 40.o65 41.o65 linked41.o65: 40.o65 41.o65 ../../ldo65 -o $@ 41.o65 40.o65 linked50.o65: 50.o65 51.o65 ../../ldo65 -o $@ 50.o65 51.o65 linked51.o65: 50.o65 51.o65 ../../ldo65 -o $@ 51.o65 50.o65 linked60.o65: 60.o65 61.o65 ../../ldo65 -o $@ 60.o65 61.o65 linked61.o65: 60.o65 61.o65 ../../ldo65 -o $@ 61.o65 60.o65 linked62.o65: 60.o65 61.o65 ../../ldo65 -bd 65529 -bt 65523 -bz 255 -o $@ 61.o65 60.o65 && exit 1 || exit 0 # BSD make doesn't populate $< in these rules and GNU make doesn't like $> t1: linked.o65 ../../reloc65 -bt 32768 -xt -o $@ linked.o65 ../hextool -cmp=$@ < t1.ok t2: linked2.o65 ../../reloc65 -bt 32768 -xt -o $@ linked2.o65 ../hextool -cmp=$@ < t2.ok t10: linked10.o65 ../../reloc65 -bt 32768 -xt -o $@ linked10.o65 ../hextool -cmp=$@ < t10.ok t11: linked11.o65 ../../reloc65 -bt 32768 -xt -o $@ linked11.o65 ../hextool -cmp=$@ < t11.ok t20: linked20.o65 ../../reloc65 -bt 32768 -xt -o $@ linked20.o65 ../hextool -cmp=$@ < t20.ok t21: linked21.o65 ../../reloc65 -bt 32768 -xt -o $@ linked21.o65 ../hextool -cmp=$@ < t21.ok t22: linked22.o65 # should fail, so no action t30: linked30.o65 ../../reloc65 -bt 32768 -xt -o $@ linked30.o65 ../hextool -cmp=$@ < t30.ok t31: linked31.o65 ../../reloc65 -bt 32768 -xt -o $@ linked31.o65 ../hextool -cmp=$@ < t31.ok t40: linked40.o65 ../../reloc65 -bt 32768 -xt -o $@ linked40.o65 ../hextool -cmp=$@ < t40.ok t41: linked41.o65 ../../reloc65 -bt 32768 -xt -o $@ linked41.o65 ../hextool -cmp=$@ < t41.ok t50: linked50.o65 ../../reloc65 -bt 32768 -bd 40960 -o $@ linked50.o65 ../hextool -cmp=$@ < t50.ok t51: linked51.o65 ../../reloc65 -bt 32768 -bd 40960 -o $@ linked51.o65 ../hextool -cmp=$@ < t51.ok t60: linked60.o65 ../../reloc65 -bt 32768 -bd 40960 -o $@ linked60.o65 ../hextool -cmp=$@ < t60.ok t61: linked61.o65 ../../reloc65 -bt 32768 -bd 40960 -o $@ linked61.o65 ../hextool -cmp=$@ < t61.ok t62: linked62.o65 clean: rm -f *.o65 *.hex t1 t2 t10 t11 t20 t21 t30 t31 t40 t41 t50 t51 t60 t61 xa-2.4.0/tests/ldoreloc/t.ok0000644000031500000010000000000714513025305015175 0ustar spectrestaff €L€`xa-2.4.0/tests/ldoreloc/t1.ok0000644000031500000010000000000714513123617015263 0ustar spectrestaff €L€`xa-2.4.0/tests/ldoreloc/t10.ok0000644000031500000010000000001214513123645015340 0ustar spectrestaff €L€­`xa-2.4.0/tests/ldoreloc/t11.ok0000644000031500000010000000001214513123656015343 0ustar spectrestaff` €L€­xa-2.4.0/tests/ldoreloc/t2.ok0000644000031500000010000000000714513123633015262 0ustar spectrestaff` €L€xa-2.4.0/tests/ldoreloc/t20.ok0000644000031500000010000000001714513123671015345 0ustar spectrestaff` €L€©©€©©xa-2.4.0/tests/ldoreloc/t21.ok0000644000031500000010000000001714513123701015340 0ustar spectrestaff €L€©©€©©`xa-2.4.0/tests/ldoreloc/t30.ok0000644000031500000010000000001414513025501015334 0ustar spectrestaff €L€ €L €xa-2.4.0/tests/ldoreloc/t31.ok0000644000031500000010000000001414513025501015335 0ustar spectrestaff €L€ €L €xa-2.4.0/tests/ldoreloc/t40.ok0000644000031500000010000000002314513025501015335 0ustar spectrestaff €L€ €L €­4©4©xa-2.4.0/tests/ldoreloc/t41.ok0000644000031500000010000000002314513025501015336 0ustar spectrestaff €L€­4©4© €L€xa-2.4.0/tests/ldoreloc/t50.ok0000644000031500000010000000013614513123712015346 0ustar spectrestaffo65€  @ €L€ €­  €4 4‚‚‚‚foo4loop€bar bla €xa-2.4.0/tests/ldoreloc/t51.ok0000644000031500000010000000013614513123724015352 0ustar spectrestaffo65€  @ €­  €L €4 4€‚‚‚‚bla€foo4loop €bar xa-2.4.0/tests/ldoreloc/t60.ok0000600000031500000010000000016114517123652015344 0ustar spectrestaffo65€ @­L€ €­© €4 4…‚‚…%‚ptrfoo4loop€bar bla €ptr2xa-2.4.0/tests/ldoreloc/t61.ok0000600000031500000010000000016114517123656015351 0ustar spectrestaffo65€ @ €­©­L €4 4€‚…%…‚‚bla€ptr2ptrfoo4loop €bar xa-2.4.0/tests/ldoreloc/xatestanalysis.txt0000644000031500000010000000664214513025305020227 0ustar spectrestaff mkdir xatest cd xatest echo "jsr bla: loop: jmp loop" > 1.s echo "bla: rts" > 2.s xa -R -c -o 1.o65 1.s xa -R -c -o 2.o65 2.s ldo65 -o linked.o65 1.o65 2.o65 reloc65 -bt 32768 -xt -o t linked.o65 hexdump -C t output: 00000000 20 06 80 4c 03 8c 60 | ..L..`| 00000007 The bytes 20 06 80 are correct, it's JSR $8006. But 4c 03 8c means JMP $8c03. What's wrong here? Do I use it in a wrong way? Following procedure leads to the expected code: echo "jsr bla: loop: jmp loop: bla: rts" > 1.s xa -R -c -o 1.o65 1.s ldo65 -o linked.o65 1.o65 reloc65 -bt 32768 -xt -o t linked.o65 hexdump -C t I use 2.3.0, it comes with Debian Testing. ============================================================================== Analysis: cat 1.o65.hex 00000000 01 00 6f 36 35 00 00 10 00 10 06 00 00 04 00 00 |..o65...........| 00000010 00 40 00 00 04 00 00 00 00 00 00 20 00 00 4c 03 |.@......... ..L.| 00000020 10 01 00 62 6c 61 00 02 80 00 00 03 82 00 00 01 |...bla..........| 00000030 00 6c 6f 6f 70 00 02 03 10 |.loop....| 00000039 file65 -V 1.o65 1.o65: o65 version 0 object file mode: 1000 =[object][16bit][byte relocation][CPU 6502][align 1] text segment @ $1000 - $1006 [$0006 bytes] data segment @ $0400 - $0400 [$0000 bytes] bss segment @ $4000 - $4000 [$0000 bytes] zero segment @ $0004 - $0004 [$0000 bytes] stack size $0000 bytes (i.e. unknown) Undefined Labels: 1 bla Global Labels: 1 loop (segID=2 (text), offset=1003) ==> text segment start $1000, loop is at $1003 -> ok undef'd label bla stored as zero (00 00) in opcode -> ok relocation table entry: $1001, ADR, undef'd, label #0 -> ok $1004, ADR, text segment -> ok --------------------------------------------------- cat 2.o65.hex 00000000 01 00 6f 36 35 00 00 10 00 10 01 00 00 04 00 00 |..o65...........| 00000010 00 40 00 00 04 00 00 00 00 00 00 60 00 00 00 00 |.@.........`....| 00000020 01 00 62 6c 61 00 02 00 10 |..bla....| file65 -V 2.o65 2.o65: o65 version 0 object file mode: 1000 =[object][16bit][byte relocation][CPU 6502][align 1] text segment @ $1000 - $1001 [$0001 bytes] data segment @ $0400 - $0400 [$0000 bytes] bss segment @ $4000 - $4000 [$0000 bytes] zero segment @ $0004 - $0004 [$0000 bytes] stack size $0000 bytes (i.e. unknown) Undefined Labels: 0 Global Labels: 1 bla (segID=2 (text), offset=1000) => text segment start $1000 -> ok no relocation table entries -> ok global label text segment, at $1000 -> ok --------------------------------------------------- ldo65 -o linked.o65 1.o65 2.o65 linked.o65.hex 00000000 01 00 6f 36 35 00 00 00 00 04 07 00 00 10 00 00 |..o65...........| 00000010 00 40 00 00 02 00 00 00 00 00 00 20 06 04 4c 03 |.@......... ..L.| 00000020 10 60 00 00 02 82 03 82 00 00 02 00 6c 6f 6f 70 |.`..........loop| 00000030 00 02 03 04 62 6c 61 00 02 06 04 |....bla....| ile65 -V linked.o65 linked.o65: o65 version 0 executable file mode: 0000 =[executable][16bit][byte relocation][CPU 6502][align 1] text segment @ $0400 - $0407 [$0007 bytes] data segment @ $1000 - $1000 [$0000 bytes] bss segment @ $4000 - $4000 [$0000 bytes] zero segment @ $0002 - $0002 [$0000 bytes] stack size $0000 bytes (i.e. unknown) Undefined Labels: 0 Global Labels: 2 loop (segID=2 (text), offset=0403) bla (segID=2 (text), offset=0406) => text segment start $0400 $0400 jsr $0406 -> RTS -> ok $0403 jmp $1003 >>>>>>>>>>>>>>>> wrong !!! should be $0403 xa-2.4.0/tests/line/0000755000031500000010000000000014524607241013535 5ustar spectrestaffxa-2.4.0/tests/line/ok0000644000031500000010000000011214524574055014071 0ustar spectrestaffxa-2.4.0/tests/line/test.s0000644000031500000010000000131414513025326014673 0ustar spectrestaff /* * tests the internal line presentation getting over 128 */ #define MAX_ENDPOINTS 4 *=$c000 txmax .dsb MAX_ENDPOINTS, 0 ; max transfer length per endpoint txpos .dsb MAX_ENDPOINTS, 0 ; endpoint buffer position per endpoint, calculated at usbd_start txlen .dsb MAX_ENDPOINTS, 0 ; endpoint buffer length, set per transaction /* * tests the internal line presentation getting over 256 */ txpos2 .byt MAX_ENDPOINTS, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; endpoint buffer position per endpoint, calculated at usbd_start and even more comments, but the many values alone use 5 byte per value internally... xa-2.4.0/tests/linkr/0000755000031500000010000000000014524607241013725 5ustar spectrestaffxa-2.4.0/tests/linkr/ok0000644000031500000010000001000314513025305014244 0ustar spectrestaff``xa-2.4.0/tests/linkr/test.s0000644000031500000010000000071114513025305015060 0ustar spectrestaff; Actual example from man page .word $1000 * = $1000 ; this is your code at $1000 part1 rts ; this label marks the end of code endofpart1 ; DON'T PUT A NEW .word HERE! * = $2000 .dsb (*-endofpart1), 0 ; yes, set it again * = $2000 ; this is your code at $2000 part2 rts xa-2.4.0/tests/listing/0000755000031500000010000000000014524607237014264 5ustar spectrestaffxa-2.4.0/tests/listing/Makefile0000644000031500000010000000257714524606771015741 0ustar spectrestaff# # Makefile for tests # XA=../../xa CA65=ca65 LD65=ld65 tests: operatorsx.out assertx.out assertx.html linebreakx.out include1x.out listblocksx.html listca65x.html listca65_2x.html operatorsx.out: operators.a65 ${XA} -P- -o operatorsx.o65 operators.a65 > $@ ../hextool -cmp=operators.out < $@ assertx.out: assert.a65 ${XA} -P- -o assertx.o65 assert.a65 > $@ ../hextool -cmp=assert.out < $@ ../hextool -cmp=assert.o65 < assertx.o65 assertx.html: assert.a65 ${XA} -P- -Fhtml -o assertx.o65 assert.a65 > $@ ../hextool -cmp=assert.html < $@ include1x.out: include1.a65 ${XA} -P- include1.a65 > $@ ../hextool -cmp=include1.out < $@ linebreakx.out: linebreak.a65 ${XA} -P- linebreak.a65 > $@ ../hextool -cmp=linebreak.out < $@ listblocksx.html: listblocks.a65 ${XA} -P- -Fhtml listblocks.a65 > $@ ../hextool -cmp=listblocks.html < $@ listca65x.html: listca65.a65 ${XA} -XCA65 -P- -Fhtml -o listca65x.o65 listca65.a65 > $@ #${CA65} $>; ${LD65} -t none -o listca65.ca65 listca65.o; rm listca65.o ../hextool -cmp=listca65.html < $@ ../hextool -cmp=listca65.ca65 < listca65x.o65 listca65_2x.html: listca65_2.a65 ${XA} -XCA65 -P- -Fhtml -o listca65_2x.o65 listca65_2.a65 > $@ #${CA65} $>; ${LD65} -t none -o listca65_2.ca65 listca65_2.o; rm listca65_2.o ../hextool -cmp=listca65_2.html < $@ ../hextool -cmp=listca65_2.ca65 < listca65_2x.o65 clean: rm -f *.err *x.out *x.html *x.o65 xa-2.4.0/tests/listing/a.o650000644000031500000010000000002014524607236015026 0ustar spectrestaff©…ĐüĄĐüČđýLxa-2.4.0/tests/listing/assert.a650000644000031500000010000000015114516776536016111 0ustar spectrestaff *=$0400 .assert *<$17e6, "routine too long" lda #<$17e6 >> 2 lda *-2 xa-2.4.0/tests/listing/assert.html0000644000031500000010000000055414520352106016443 0ustar spectrestaff(null)

assert.a65

    1 A:1000                                     *= $0400

    3 A:0400                                     .assert *<$17e6,"routine too long"

    5 A:0400  a9 f9                              lda #<$17e6>>2

    7 A:0402  ad 00 04                           lda *-2
xa-2.4.0/tests/listing/assert.o650000644000031500000010000000000514520352234016101 0ustar spectrestaff©ů­xa-2.4.0/tests/listing/assert.out0000644000031500000010000000042714520351663016314 0ustar spectrestaff assert.a65 1 A:1000 *= $0400 3 A:0400 .assert *<$17e6,"routine too long" 5 A:0400 a9 f9 lda #<$17e6>>2 7 A:0402 ad 00 04 lda *-2 xa-2.4.0/tests/listing/include1.a650000644000031500000010000000010314513025326016266 0ustar spectrestaff .org $1000 #include "include1a.a65" .include "include1a.a65" xa-2.4.0/tests/listing/include1.out0000644000031500000010000000051114513025326016505 0ustar spectrestaff include1.a65 2 A:1000 *= $1000 include1a.a65 2 A:1000 a9 00 lda #$00 include1.a65 6 A:1002 .include "include1a.a65" include1a.a65 2 A:1002 a9 00 lda #$00 include1.a65 xa-2.4.0/tests/listing/include1a.a650000644000031500000010000000001414513025326016430 0ustar spectrestaff lda #$00 xa-2.4.0/tests/listing/linebreak.a650000644000031500000010000000637514513025326016537 0ustar spectrestaff *=$1000 // default listbytes is 8 lda #$0 // first without labels .( // less than 8 bytes .byt 0,1,2,3,4,5 ; 6 // seven bytes .byt 0,1,2,3,4,5,6 ; 7 // eight bytes .byt 0,1,2,3,4,5,6,7 ; 8 // nine bytes .byt 0,1,2,3,4,5,6,7,8 ; 9 // ten bytes .byt 0,1,2,3,4,5,6,7,8,9 ; 10 // eleven bytes .byt 0,1,2,3,4,5,6,7,8,9,10 ; 11 // fifteen bytes .asc "012345678901234" ; 15, asc test as well // sixteen bytes .asc "0123456789012345" ; 16 // seventeen bytes .asc "01234567890123456"; 17 // thirtythree .asc "012345678901234567890123456789012"; 32 // now with labels // less than 8 bytes l6 .byt 0,1,2,3,4,5 ; 6 // seven bytes l7 .byt 0,1,2,3,4,5,6 ; 7 // eight bytes l8 .byt 0,1,2,3,4,5,6,7 ; 8 // nine bytes l9 .byt 0,1,2,3,4,5,6,7,8 ; 9 // ten bytes l10 .byt 0,1,2,3,4,5,6,7,8,9 ; 10 // eleven bytes l11 .byt 0,1,2,3,4,5,6,7,8,9,10 ; 11 // fifteen bytes l15 .asc "012345678901234" ; 15, asc test as well // sixteen bytes l16 .asc "0123456789012345" ; 16 // seventeen bytes l17 .asc "01234567890123456"; 17 // thirtythree l32 .asc "012345678901234567890123456789012"; 32 .) // now set number of bytes per listing line to 10 .listbytes 10 .( // less than 8 bytes .byt 0,1,2,3,4,5 ; 6 // seven bytes .byt 0,1,2,3,4,5,6 ; 7 // eight bytes .byt 0,1,2,3,4,5,6,7 ; 8 // nine bytes .byt 0,1,2,3,4,5,6,7,8 ; 9 // ten bytes .byt 0,1,2,3,4,5,6,7,8,9 ; 10 // eleven bytes .byt 0,1,2,3,4,5,6,7,8,9,10 ; 11 // fifteen bytes .asc "012345678901234" ; 15, asc test as well // sixteen bytes .asc "0123456789012345" ; 16 // seventeen bytes .asc "01234567890123456"; 17 // thirtythree .asc "012345678901234567890123456789012"; 32 // now with labels // less than 8 bytes l6 .byt 0,1,2,3,4,5 ; 6 // seven bytes l7 .byt 0,1,2,3,4,5,6 ; 7 // eight bytes l8 .byt 0,1,2,3,4,5,6,7 ; 8 // nine bytes l9 .byt 01,2,3,4,5,6,7,8 ; 9 // ten bytes l10 .byt 01,2,3,4,5,6,7,8,9 ; 10 // eleven bytes l11 .byt 01,2,3,4,5,6,7,8,9,10 ; 11 // fifteen bytes l15 .asc "012345678901234" ; 15, asc test as well // sixteen bytes l16 .asc "0123456789012345" ; 16 // seventeen bytes l17 .asc "01234567890123456"; 17 // thirtythree l32 .asc "012345678901234567890123456789012"; 32 .) // set number of listing bytes to unlimited .listbytes unlimited .( // less than 8 bytes .byt 0,1,2,3,4,5 ; 6 // seven bytes .byt 0,1,2,3,4,5,6 ; 7 // eight bytes .byt 0,1,2,3,4,5,6,7 ; 8 // nine bytes .byt 0,1,2,3,4,5,6,7,8 ; 9 // ten bytes .byt 0,1,2,3,4,5,6,7,8,9 ; 10 // eleven bytes .byt 0,1,2,3,4,5,6,7,8,9,10 ; 11 // fifteen bytes .asc "012345678901234" ; 15, asc test as well // sixteen bytes .asc "0123456789012345" ; 16 // seventeen bytes .asc "01234567890123456"; 17 // thirtythree .asc "012345678901234567890123456789012"; 32 // now with labels // less than 8 bytes l6 .byt 0,1,2,3,4,5 ; 6 // seven bytes l7 .byt 0,1,2,3,4,5,6 ; 7 // eight bytes l8 .byt 0,1,2,3,4,5,6,7 ; 8 // nine byte l9 .byt 0,1,2,3,4,5,6,7,8 ; 9 // ten bytes l10 .byt 0,1,2,3,4,5,6,7,8,9 ; 10 // eleven bytes l11 .byt 0,1,2,3,4,5,6,7,8,9,10 ; 11 // fifteen bytes l15 .asc "012345678901234" ; 15, test as well // sixteen bytes l16 .asc "0123456789012345" ; 16 // seventeen bytes l17 .asc "01234567890123456"; 17 // thirtythree l32 .asc "012345678901234567890123456789012"; 32 .) xa-2.4.0/tests/listing/linebreak.out0000644000031500000010000001441214513025326016742 0ustar spectrestaff linebreak.a65 2 A:1000 *= $1000 6 A:1000 a9 00 lda #$00 10 A:1002 .( 12 A:1002 00 01 02 03 04 05 .byt 0,1,2,3,4,5; 6 14 A:1008 00 01 02 03 04 05 06 .byt 0,1,2,3,4,5,6; 7 16 A:100f 00 01 02 03 04 05 06 07 .byt 0,1,2,3,4,5,6,7; 8 18 A:1017 00 01 02 03 04 05 06 ... .byt 0,1,2,3,4,5,6,7,8; 9 20 A:1020 00 01 02 03 04 05 06 ... .byt 0,1,2,3,4,5,6,7,8,9; 10 22 A:102a 00 01 02 03 04 05 06 ... .byt 0,1,2,3,4,5,6,7,8,9,10; 11 24 A:1035 30 31 32 33 34 35 36 ... .asc "012345678901234" ; 15, asc test as well 26 A:1044 30 31 32 33 34 35 36 ... .asc "0123456789012345" ; 16 28 A:1054 30 31 32 33 34 35 36 ... .asc "01234567890123456"; 17 30 A:1065 30 31 32 33 34 35 36 ... .asc "012345678901234567890123456789012"; 32 35 A:1086 00 01 02 03 04 05 l6 .byt 0,1,2,3,4,5; 6 37 A:108c 00 01 02 03 04 05 06 l7 .byt 0,1,2,3,4,5,6; 7 39 A:1093 00 01 02 03 04 05 06 07 l8 .byt 0,1,2,3,4,5,6,7; 8 41 A:109b 00 01 02 03 04 05 06 ... l9 .byt 0,1,2,3,4,5,6,7,8; 9 43 A:10a4 00 01 02 03 04 05 06 ... l10 .byt 0,1,2,3,4,5,6,7,8,9; 10 45 A:10ae 00 01 02 03 04 05 06 ... l11 .byt 0,1,2,3,4,5,6,7,8,9,10; 11 47 A:10b9 30 31 32 33 34 35 36 ... l15 .asc "012345678901234"; 15, asc test as well 49 A:10c8 30 31 32 33 34 35 36 ... l16 .asc "0123456789012345"; 16 51 A:10d8 30 31 32 33 34 35 36 ... l17 .asc "01234567890123456"; 17 53 A:10e9 30 31 32 33 34 35 36 ... l32 .asc "012345678901234567890123456789012"; 32 55 A:110a .) 59 A:110a .listbytes 10 61 A:110a .( 63 A:110a 00 01 02 03 04 05 .byt 0,1,2,3,4,5; 6 65 A:1110 00 01 02 03 04 05 06 .byt 0,1,2,3,4,5,6; 7 67 A:1117 00 01 02 03 04 05 06 07 .byt 0,1,2,3,4,5,6,7; 8 69 A:111f 00 01 02 03 04 05 06 07 08 .byt 0,1,2,3,4,5,6,7,8; 9 71 A:1128 00 01 02 03 04 05 06 07 08 09 .byt 0,1,2,3,4,5,6,7,8,9; 10 73 A:1132 00 01 02 03 04 05 06 07 08 ... .byt 0,1,2,3,4,5,6,7,8,9,10; 11 75 A:113d 30 31 32 33 34 35 36 37 38 ... .asc "012345678901234" ; 15, asc test as well 77 A:114c 30 31 32 33 34 35 36 37 38 ... .asc "0123456789012345" ; 16 79 A:115c 30 31 32 33 34 35 36 37 38 ... .asc "01234567890123456"; 17 81 A:116d 30 31 32 33 34 35 36 37 38 ... .asc "012345678901234567890123456789012"; 32 87 A:118e 00 01 02 03 04 05 l6 .byt 0,1,2,3,4,5; 6 89 A:1194 00 01 02 03 04 05 06 l7 .byt 0,1,2,3,4,5,6; 7 91 A:119b 00 01 02 03 04 05 06 07 l8 .byt 0,1,2,3,4,5,6,7; 8 93 A:11a3 01 02 03 04 05 06 07 08 l9 .byt 1,2,3,4,5,6,7,8; 9 95 A:11ab 01 02 03 04 05 06 07 08 09 95 A:11ab l10 .byt 1,2,3,4,5,6,7,8,9; 10 97 A:11b4 01 02 03 04 05 06 07 08 09 0a 97 A:11b4 l11 .byt 1,2,3,4,5,6,7,8,9,10; 11 99 A:11be 30 31 32 33 34 35 36 37 38 ... 99 A:11be l15 .asc "012345678901234"; 15, asc test as well 101 A:11cd 30 31 32 33 34 35 36 37 38 ... 101 A:11cd l16 .asc "0123456789012345"; 16 103 A:11dd 30 31 32 33 34 35 36 37 38 ... 103 A:11dd l17 .asc "01234567890123456"; 17 105 A:11ee 30 31 32 33 34 35 36 37 38 ... 105 A:11ee l32 .asc "012345678901234567890123456789012"; 32 107 A:120f .) 110 A:120f .listbytes 0 112 A:120f .( 114 A:120f 00 01 02 03 04 05 .byt 0,1,2,3,4,5; 6 116 A:1215 00 01 02 03 04 05 06 .byt 0,1,2,3,4,5,6; 7 118 A:121c 00 01 02 03 04 05 06 07 .byt 0,1,2,3,4,5,6,7; 8 120 A:1224 00 01 02 03 04 05 06 07 08 .byt 0,1,2,3,4,5,6,7,8; 9 122 A:122d 00 01 02 03 04 05 06 07 08 09 .byt 0,1,2,3,4,5,6,7,8,9; 10 124 A:1237 00 01 02 03 04 05 06 07 08 09 0a .byt 0,1,2,3,4,5,6,7,8,9,10; 11 126 A:1242 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 126 A:1242 .asc "012345678901234" ; 15, asc test as well 128 A:1251 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 128 A:1261 .asc "0123456789012345" ; 16 130 A:1261 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 130 A:1271 36 .asc "01234567890123456"; 17 132 A:1272 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 132 A:1282 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 132 A:1292 32 .asc "012345678901234567890123456789012"; 32 138 A:1293 00 01 02 03 04 05 l6 .byt 0,1,2,3,4,5; 6 140 A:1299 00 01 02 03 04 05 06 l7 .byt 0,1,2,3,4,5,6; 7 142 A:12a0 00 01 02 03 04 05 06 07 l8 .byt 0,1,2,3,4,5,6,7; 8 144 A:12a8 00 01 02 03 04 05 06 07 08 144 A:12a8 l9 .byt 0,1,2,3,4,5,6,7,8; 9 146 A:12b1 00 01 02 03 04 05 06 07 08 09 146 A:12b1 l10 .byt 0,1,2,3,4,5,6,7,8,9; 10 148 A:12bb 00 01 02 03 04 05 06 07 08 09 0a 148 A:12bb l11 .byt 0,1,2,3,4,5,6,7,8,9,10; 11 150 A:12c6 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 150 A:12c6 l15 .asc "012345678901234"; 15, test as well 152 A:12d5 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 152 A:12e5 l16 .asc "0123456789012345"; 16 154 A:12e5 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 154 A:12f5 36 l17 .asc "01234567890123456"; 17 156 A:12f6 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 156 A:1306 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 156 A:1316 32 l32 .asc "012345678901234567890123456789012"; 32 158 A:1317 .) xa-2.4.0/tests/listing/listblocks.a650000644000031500000010000000040114513025326016734 0ustar spectrestaff // tests the html listing feature with blocks that // contain the same label names, but in different scopes *=$1000 label1 lda #$00 .( label2 sta $02 bne label2 .) .( label2 lda $02 ; again! bne label2 .) label2 iny beq label2 jmp label1 xa-2.4.0/tests/listing/listblocks.html0000644000031500000010000000202314513025326017307 0ustar spectrestaff(null)

listblocks.a65


    5 A:1000                                     *= $1000

    7 A:1000  a9 00                     label1    lda #$00

    9 A:1002                                     .( 
   10 A:1002  85 02                     label2    sta $02
   11 A:1004  d0 fc                              bne label2
   12 A:1006                                     .) 

   14 A:1006                                     .( 
   15 A:1006  a5 02                     label2    lda $02           ; again!
   16 A:1008  d0 fc                              bne label2
   17 A:100a                                     .) 

   19 A:100a  c8                        label2    iny 
   20 A:100b  f0 fd                              beq label2

   22 A:100d  4c 00 10                           jmp label1
xa-2.4.0/tests/listing/listca65.a650000644000031500000010000000042614513025326016224 0ustar spectrestaff ; tests the html listing feature with blocks that ; contain the same label names, but in different scopes .org $1000 : lda #$00 .scope : sta $02 : bne :- .endscope .scope @label2: lda $02 ; again! bne @label2 .endscope label2: iny beq label2 beq :--- jmp :-- xa-2.4.0/tests/listing/listca65.ca650000644000031500000010000000002214513125055016357 0ustar spectrestaff©…ĐţĄĐüČđýđńLxa-2.4.0/tests/listing/listca65.html0000644000031500000010000000262014513025326016573 0ustar spectrestaff(null)

listca65.a65


    2 A:1000                                    ; tests the html listing feature with blocks that 
    3 A:1000                                    ; contain the same label names, but in different scopes

    5 A:1000                                     *= $1000

    7 A:1000  a9 00                     :           lda #$00

    9 A:1002                                     .( 
   10 A:1002  85 02                     :           sta $02
   11 A:1004  d0 fe                     :           bne :-
   12 A:1006                                     .) 

   14 A:1006                                     .( 
   15 A:1006                            @label2   
   15 A:1006  a5 02                              lda $02              ; again!
   16 A:1008  d0 fc                              bne @label2
   17 A:100a                                     .) 

   19 A:100a                            label2    
   19 A:100a  c8                                 iny 
   20 A:100b  f0 fd                              beq label2

   22 A:100d  f0 f1                              beq :---
   23 A:100f  4c 02 10                           jmp :--
xa-2.4.0/tests/listing/listca65_2.a650000644000031500000010000000030514513025326016441 0ustar spectrestaff ; tests the html listing feature with blocks that ; contain the same label names, but in different scopes .org $1000 : lda #$00 .include "listca65_2b.a65" label2: iny beq label2 jmp :- xa-2.4.0/tests/listing/listca65_2.ca650000644000031500000010000000001314513125121016572 0ustar spectrestaff©ČĐýČđýLxa-2.4.0/tests/listing/listca65_2.html0000644000031500000010000000222414513025326017014 0ustar spectrestaff(null)

listca65_2.a65


    2 A:1000                                    ; tests the html listing feature with blocks that 
    3 A:1000                                    ; contain the same label names, but in different scopes

    5 A:1000                                     *= $1000

    7 A:1000  a9 00                     :           lda #$00

    9 A:1002                                     .include "listca65_2b.a65"

listca65_2b.a65


    2 A:1002                                    ; to be included in listca65_2.a65
    3 A:1002                                    ; to check HTML linkage of unnamed labels across files

    5 A:1002  c8                        :           iny 
    6 A:1003  d0 fd                              bne :-

listca65_2.a65


   11 A:1005                            label2    
   11 A:1005  c8                                 iny 
   12 A:1006  f0 fd                              beq label2

   14 A:1008  4c 02 10                           jmp :-
xa-2.4.0/tests/listing/listca65_2b.a650000644000031500000010000000015514513025326016606 0ustar spectrestaff ; to be included in listca65_2.a65 ; to check HTML linkage of unnamed labels across files : iny bne :- xa-2.4.0/tests/listing/operators.a650000644000031500000010000000034414520744134016612 0ustar spectrestaff la9a5 =$a9a5 lac15 =$ac15 lad24 =$ad24 lb3c0 =$b3c0 laf28 =$af28 x1 =(la9a5^laf28)&$00ff x2 =(lac15^laf28)&$00ff x3 =(lad24^laf28)&$00ff x4 =(lb3c0^laf28)&$00ff x5 =$ff&(la9a5|laf28) x6 =$ff&(la9a5|laf28)&$00ff xa-2.4.0/tests/listing/operators.out0000644000031500000010000000134114520744134017024 0ustar spectrestaff operators.a65 3 A:1000 la9a5=$a9a5 4 A:1000 lac15=$ac15 5 A:1000 lad24=$ad24 6 A:1000 lb3c0=$b3c0 7 A:1000 laf28=$af28 9 A:1000 x1=(la9a5^laf28)&$ff 10 A:1000 x2=(lac15^laf28)&$ff 11 A:1000 x3=(lad24^laf28)&$ff 12 A:1000 x4=(lb3c0^laf28)&$ff 14 A:1000 x5=$ff&(la9a5|laf28) 15 A:1000 x6=$ff&(la9a5|laf28)&$ff xa-2.4.0/tests/masmcom/0000755000031500000010000000000014524607237014247 5ustar spectrestaffxa-2.4.0/tests/masmcom/Makefile0000644000031500000010000000031214513025305015667 0ustar spectrestaffdefault: # compile with masm mode on. ../../xa -M -o test.o test.s ../hextool -cmp=okmasm < test.o # compile without ../../xa -o test.o test.s ../hextool -cmp=oknomasm < test.o clean: rm -f *.o xa-2.4.0/tests/masmcom/okmasm0000644000031500000010000000000214513025305015435 0ustar spectrestaff©xa-2.4.0/tests/masmcom/oknomasm0000644000031500000010000000000614513025305015776 0ustar spectrestaff©©©:xa-2.4.0/tests/masmcom/test.s0000644000031500000010000000016614513025305015401 0ustar spectrestaff/* when assembled with/without -M, we get two different objects */ lda #00 ; and this: lda #01 ; is why : lda #":" xa-2.4.0/tests/math/0000755000031500000010000000000014524607237013544 5ustar spectrestaffxa-2.4.0/tests/math/Makefile0000644000031500000010000000032114513025305015164 0ustar spectrestaffdefault: # xa should not allow this to happen. if it does, this test is no good. ../../xa -o divzero.o divzero.s || exit 0 && exit 1 ../../xa -o divzero2.o divzero2.s || exit 0 && exit 1 clean: rm -f *.o xa-2.4.0/tests/math/divzero.s0000644000031500000010000000002314513025305015371 0ustar spectrestaff.word $ * = $0/00 xa-2.4.0/tests/math/divzero2.s0000644000031500000010000000005514513025305015460 0ustar spectrestaff.word $ xyz = 2 zyx = xyz - xyz * = $0/zyx xa-2.4.0/tests/mvnmvp/0000755000031500000010000000000014524607237014136 5ustar spectrestaffxa-2.4.0/tests/mvnmvp/Makefile0000644000031500000010000000047414513142255015573 0ustar spectrestaffdefault: # xa should not allow this to happen. if it does, this test is no good. ../../xa test.s || exit 0 && exit 1 ../../xa -w -DOLD_SYNTAX test.s || exit 0 && exit 1 # expected-to-fail tests did fail. should be no more errors now. ../../xa -w test.s -o test.o ../hextool -cmp=ok < test.o clean: rm -f *.o xa-2.4.0/tests/mvnmvp/ok0000644000031500000010000000003314513025305014452 0ustar spectrestaff­ ĐJTTTfDDDęZ¶Z¶xa-2.4.0/tests/mvnmvp/test.s0000644000031500000010000000064114513142440015266 0ustar spectrestaff; test instructions that failed during our testing ; and test instructions in the tokenizer bordering mvn/mvp w = $01 lda $d020 lsr mvn w, $02 #ifdef OLD_SYNTAX mvn $0201 mvn $0066 #else mvn $02,$01 mvn $00,$66 #endif mvp $03, w+3 #ifdef OLD_SYNTAX mvp $0403 mvp $0088 #else mvp $04,$03 mvp $00,$88 #endif #ifdef OLD_SYNTAX mvp $0403,$03 mvp $03,$0405 mvn $0403,$03 mvn $03,$0405 #endif nop .byt $5a, $b6 .word $b65a xa-2.4.0/tests/neg_offset/0000755000031500000010000000000014524607237014732 5ustar spectrestaffxa-2.4.0/tests/neg_offset/Makefile0000644000031500000010000000152314513025305016357 0ustar spectrestaffdefault: test0 test1 test2 test3 test4 test5 test6 test7 test8 test0: # this test must fail. ../../xa -o test0.o test0.s || exit 0 && exit 1 test1: ../../xa -R -LLIB6502 test1.s -o test1.o ../hextool -cmp=ok1 < test1.o test2: ../../xa -R -LLIB6502 test2.s -o test2.o ../hextool -cmp=ok2 < test2.o test3: ../../xa -R -LLIB6502 test3.s -o test3.o ../hextool -cmp=ok3 < test3.o test4: ../../xa -R -LLIB6502 test4.s -o test4.o ../hextool -cmp=ok4 < test4.o test5: ../../xa -R -LLIB6502 test5.s -o test5.o ../hextool -cmp=ok5 < test5.o test6: # this test must fail. ../../xa -R -LLIB6502 test6.s -o test6.o || exit 0 && exit 1 test7: # this test must fail. ../../xa -R -LLIB6502 test7.s -o test7.o || exit 0 && exit 1 test8: # this test must fail. ../../xa -R -LLIB6502 test8.s -o test8.o || exit 0 && exit 1 clean: rm -f *.o xa-2.4.0/tests/neg_offset/a.o650000644000031500000010000000006014513025305015465 0ustar spectrestaffo65@ ˙LIB6502€xa-2.4.0/tests/neg_offset/ok10000644000031500000010000000006014513025305015327 0ustar spectrestaffo65@ ý˙LIB6502€xa-2.4.0/tests/neg_offset/ok20000644000031500000010000000006014513025305015330 0ustar spectrestaffo65@ ý˙LIB6502€xa-2.4.0/tests/neg_offset/ok30000644000031500000010000000006014513025305015331 0ustar spectrestaffo65@ ˙LIB6502€xa-2.4.0/tests/neg_offset/ok40000644000031500000010000000006014513025305015332 0ustar spectrestaffo65@ LIB6502€xa-2.4.0/tests/neg_offset/ok50000644000031500000010000000006014513025305015333 0ustar spectrestaffo65@ ˙LIB6502€xa-2.4.0/tests/neg_offset/test0.s0000644000031500000010000000001714513025305016137 0ustar spectrestaff .dsb -10, 32 xa-2.4.0/tests/neg_offset/test1.s0000644000031500000010000000003214513025305016135 0ustar spectrestaff .text jsr LIB6502-3 xa-2.4.0/tests/neg_offset/test2.s0000644000031500000010000000007214513025305016142 0ustar spectrestaff #define flib2osa_r LIB6502-3 .text jsr flib2osa_r xa-2.4.0/tests/neg_offset/test3.s0000644000031500000010000000003414513025305016141 0ustar spectrestaff .text jsr LIB6502-255 xa-2.4.0/tests/neg_offset/test4.s0000644000031500000010000000003414513025305016142 0ustar spectrestaff .text jsr LIB6502+256 xa-2.4.0/tests/neg_offset/test5.s0000644000031500000010000000003414513025305016143 0ustar spectrestaff .text jsr LIB6502-256 xa-2.4.0/tests/neg_offset/test6.s0000644000031500000010000000003614513025305016146 0ustar spectrestaff .text jsr LIB6502-65537 xa-2.4.0/tests/neg_offset/test7.s0000644000031500000010000000002614513025305016146 0ustar spectrestaff .text jsr 65536 xa-2.4.0/tests/neg_offset/test8.s0000644000031500000010000000003614513025305016150 0ustar spectrestaff .text jsr LIB6502+65536 xa-2.4.0/tests/nonl/0000755000031500000010000000000014524607241013554 5ustar spectrestaffxa-2.4.0/tests/nonl/ok0000644000031500000010000000000614513025305014075 0ustar spectrestaff©Ť`xa-2.4.0/tests/nonl/test.s0000644000031500000010000000003014513025305014701 0ustar spectrestaff lda #4 sta !$0005 rtsxa-2.4.0/tests/nonl/test2.asm0000644000031500000010000000002314513025305015303 0ustar spectrestaff#include "test.asm"xa-2.4.0/tests/op816/0000755000031500000010000000000014524607237013470 5ustar spectrestaffxa-2.4.0/tests/op816/Makefile0000644000031500000010000000040714513025305015115 0ustar spectrestaffdefault: # xa should not allow this to happen. if it does, this test is no good. ../../xa test.s || exit 0 && exit 1 # expected-to-fail tests did fail. should be no more errors now. ../../xa -w test.s -o test.o ../hextool -cmp=ok < test.o clean: rm -f *.o xa-2.4.0/tests/op816/ok0000644000031500000010000000113614513025305014011 0ustar spectrestaff [ [[[˙L$[[[[[˙LJ ]!"[˙#$%&'()"*+,[-[.[/[˙Lr0123456789[:;<[=[>[?[˙L@ABCDDDEFGHIDJKL]M[N[O[˙LĽPQRSTUUUVWXY[Z[\[˙][^[_[˙Lä`abqcdefghifjkl[m[n[o[˙L pqrstuvwxy[z{|[}[~[[˙L/€‚%„…†‡‰Š‹Ś[Ť[Ž[Ź[˙LU‘ ’ “ ” • – — ™[š›ť[ž[ź[˙Lx Şˇ ˘ŞŁ ¤ Ą ¦ § ¨©ŞŞ«¬[­[®[Ż[˙Lť°± ˛ ł ´ µ ¶ · ¸ą[ş»Ľ[˝[ľ[ż[˙LĂŔĚÁ ÂĚĂ Ä Ĺ Ć Ç ČÉĚĘËĚ[Í[Î[Ď[˙LčĐŃ Ň Ó Ô Ő Ö × ŘŮ[ÚŰÜ4Ý[Ţ[ß[˙Lŕîáâîăäĺćçčéîęëě[í[î[ď[˙L3đńňóôőö÷řů[úűü[ý[ţ[˙[˙LZ`4@xa-2.4.0/tests/op816/test.s0000600000031500000010000001500714513025305014612 0ustar spectrestaff; Copyright (c) 2014, Alessandro Gatti - frob.it ; All rights reserved. ; ; Redistribution and use in source and binary forms, with or without ; modification, are permitted provided that the following conditions are met: ; ; 1. Redistributions of source code must retain the above copyright notice, ; this list of conditions and the following disclaimer. ; ; 2. Redistributions in binary form must reproduce the above copyright notice, ; this list of conditions and the following disclaimer in the documentation ; and/or other materials provided with the distribution. ; ; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ; ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE ; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ; POSSIBILITY OF SUCH DAMAGE. #define ZEROPAGE_0 $0 #define ZEROPAGE_1 $1 #define ZEROPAGE_2 $2 #define ZEROPAGE_3 $3 #define ZEROPAGE_4 $4 #define ZEROPAGE_5 $5 #define ZEROPAGE_6 $6 #define ZEROPAGE_7 $7 #define ZEROPAGE_8 $8 #define ZEROPAGE_9 $9 #define ZEROPAGE_A $a #define ZEROPAGE_B $b #define ZEROPAGE_C $c #define ZEROPAGE_D $d #define ZEROPAGE_E $e #define ZEROPAGE_F $f *=$1000 row0 BRK ORA (ZEROPAGE_0,X) COP #$00 ORA ZEROPAGE_0,S TSB ZEROPAGE_0 ORA ZEROPAGE_0 ASL ZEROPAGE_0 ORA [ZEROPAGE_0] PHP ORA #$00 ASL PHD TSB datablockabs ORA datablockabs ASL datablockabs ORA @datablockabs+@$FF0000 JMP row1 row1 BPL row1_target ORA (ZEROPAGE_1),Y row1_target ORA (ZEROPAGE_1) ORA (ZEROPAGE_1,S),Y TRB ZEROPAGE_1 ORA ZEROPAGE_1,X ASL ZEROPAGE_1,X ORA [ZEROPAGE_1],Y CLC ORA datablockabs,Y INC TCS TRB datablockabs ORA datablockabs,X ASL datablockabs,X ORA @datablockabs+@$FF0000,X JMP row2 row2 JSR farcode AND (ZEROPAGE_2,X) JSR @datablockabs+@$FF0000 AND ZEROPAGE_2,S BIT ZEROPAGE_2 AND ZEROPAGE_2 ROL ZEROPAGE_2 AND [ZEROPAGE_2] PLP AND #$22 ROL PLD BIT datablockabs AND datablockabs ROL datablockabs AND @datablockabs+@$FF0000 JMP row3 row3 BMI row3_target AND (ZEROPAGE_3),Y row3_target AND (ZEROPAGE_3) AND (ZEROPAGE_3,S),Y BIT ZEROPAGE_3,X AND ZEROPAGE_3,X ROL ZEROPAGE_3,X AND [ZEROPAGE_3],Y SEC AND datablockabs,Y DEC TSC BIT datablockabs,X AND datablockabs,X ROL datablockabs,X AND @datablockabs+@$FF0000,X JMP row4 row4 RTI EOR (ZEROPAGE_4,X) .byte $42 ; WDM EOR ZEROPAGE_3,S MVP $44,$44 ;$4444 ; Should be $44, $44 instead EOR ZEROPAGE_4 LSR ZEROPAGE_4 EOR [ZEROPAGE_4] PHA EOR #$44 LSR PHK JMP farcode EOR datablockabs LSR datablockabs EOR @datablockabs+@$FF0000 JMP row5 row5 BVC row5_target EOR (ZEROPAGE_5),Y row5_target EOR (ZEROPAGE_5) EOR (ZEROPAGE_5,S),Y MVN $55,$55 ; $5555 ; Should be $55, $55 instead EOR ZEROPAGE_5,X LSR ZEROPAGE_5,X EOR [ZEROPAGE_5],Y CLI EOR datablockabs,Y PHY TCD JMP @datablockabs+@$FF0000 EOR datablockabs,X LSR datablockabs,X EOR @datablockabs+@$FF0000,X JMP row6 row6 RTS ADC (ZEROPAGE_6,X) PER datablockabs ADC ZEROPAGE_6,S STZ ZEROPAGE_6 ADC ZEROPAGE_6 ROR ZEROPAGE_6 ADC [ZEROPAGE_6] PLA ADC #$66 ROR RTL JMP (datablockabs) ADC datablockabs ROR datablockabs ADC @datablockabs+@$FF0000 JMP row7 row7 BVS row7_target ADC (ZEROPAGE_7),Y row7_target ADC (ZEROPAGE_7) ADC (ZEROPAGE_7,S),Y STZ ZEROPAGE_7,X ADC ZEROPAGE_7,X ROR ZEROPAGE_7,X ADC [ZEROPAGE_7],Y SEI ADC datablockabs,Y PLY TDC JMP (datablockabs,X) ADC datablockabs,X ROR datablockabs,X ADC @datablockabs+@$FF0000,X JMP row8 row8 BRA row8_target STA (ZEROPAGE_8,X) row8_target BRL datablockabs STA ZEROPAGE_8,S STY ZEROPAGE_8 STA ZEROPAGE_8 STX ZEROPAGE_8 STA [ZEROPAGE_8] DEY BIT #$88 TXA PHB STY datablockabs STA datablockabs STX datablockabs STA @datablockabs+@$FF0000 JMP row9 row9 BCC row9_target STA (ZEROPAGE_9),Y row9_target STA (ZEROPAGE_9) STA (ZEROPAGE_9,S),Y STY ZEROPAGE_9,X STA ZEROPAGE_9,X STX ZEROPAGE_9,Y STA [ZEROPAGE_9],Y TYA STA datablockabs,Y TXS TXY STA datablockabs,X STZ datablockabs,X STA @datablockabs+@$FF0000,X JMP rowa rowa LDY #$AA LDA (ZEROPAGE_A,X) LDX #$AA LDA ZEROPAGE_A,S LDY ZEROPAGE_A LDA ZEROPAGE_A LDX ZEROPAGE_A LDA [ZEROPAGE_A] TAY LDA #$AA TAX PLB LDY datablockabs LDA datablockabs LDX datablockabs LDA @datablockabs+@$FF0000 JMP rowb rowb BCS rowb_target LDA (ZEROPAGE_B),Y rowb_target LDA (ZEROPAGE_B) LDA (ZEROPAGE_B,S),Y LDY ZEROPAGE_B,X LDA ZEROPAGE_B,X LDX ZEROPAGE_B,Y LDA [ZEROPAGE_B],Y CLV LDA datablockabs,Y TSX TYX LDY datablockabs,X LDA datablockabs,X LDX datablockabs,Y LDA @datablockabs+@$FF0000,X JMP rowc rowc CPY #$CC CMP (ZEROPAGE_C,X) REP #$CC CMP ZEROPAGE_C,S CPY ZEROPAGE_C CMP ZEROPAGE_C DEC ZEROPAGE_C CMP [ZEROPAGE_C] INY CMP #$CC DEX WAI CPY datablockabs CMP datablockabs DEC datablockabs CMP @datablockabs+@$FF0000 JMP rowd rowd BNE rowd_target CMP (ZEROPAGE_D),Y rowd_target CMP (ZEROPAGE_D) CMP (ZEROPAGE_D,S),Y PEI (ZEROPAGE_D) CMP ZEROPAGE_D,X DEC ZEROPAGE_D,X CMP [ZEROPAGE_D],Y CLD CMP datablockabs,Y PHX STP .byte $DC, $34, $12 ; JML (label) CMP datablockabs,X DEC datablockabs,X CMP @datablockabs+@$FF0000,X JMP rowe rowe CPX #$EE SBC (ZEROPAGE_E,X) SEP #$EE SBC ZEROPAGE_E,S CPX ZEROPAGE_E SBC ZEROPAGE_E INC ZEROPAGE_E SBC [ZEROPAGE_E] INX SBC #$EE NOP XBA CPX datablockabs SBC datablockabs INC datablockabs SBC @datablockabs+@$FF0000 JMP rowf rowf BEQ rowf_target SBC (ZEROPAGE_F),Y rowf_target SBC (ZEROPAGE_F) SBC (ZEROPAGE_F,S),Y PEA $1000 SBC ZEROPAGE_F,X INC ZEROPAGE_F,X SBC [ZEROPAGE_F],Y SED SBC datablockabs,Y PLX XCE JSR (datablockabs,X) SBC datablockabs,X INC datablockabs,X SBC @datablockabs+@$FF0000,X JMP end end RTS datablockabs .word $1234 farcode RTI xa-2.4.0/tests/openpp/0000755000031500000010000000000014524607240014106 5ustar spectrestaffxa-2.4.0/tests/openpp/Makefile0000644000031500000010000000050414513025305015537 0ustar spectrestaffdefault: # xa should not allow this to happen. if it does, this test is no good. ../../xa test.inc || exit 0 && exit 1 # expected-to-fail tests did fail. should be no more errors now. ../../xa -DBUG test.s -o test.o ../hextool -cmp=ok < test.o ../../xa test.s -o test.o ../hextool -cmp=ok < test.o clean: rm -f *.o xa-2.4.0/tests/openpp/ok0000644000031500000010000000001414513025305014427 0ustar spectrestaffŔ©] Ň˙©] Ň˙xa-2.4.0/tests/openpp/test.inc0000644000031500000010000000003714513025305015552 0ustar spectrestaff#ifdef BUGOUTTTTT /* #endif */ xa-2.4.0/tests/openpp/test.s0000644000031500000010000000044214513025305015243 0ustar spectrestaff .word $c000 * = $c000 #if 0 #error BUGGGGG #endif #if 1 lda #93 jsr $ffd2 #endif /* comment this out to stop testing included gaffes */ #ifdef BUG #include "test.inc" #endif #if 1 #if 2 lda #93 jsr $ffd2 #endif #endif #ifdef X /* comment this out for bugs in this file */ #endif xa-2.4.0/tests/pparity/0000755000031500000010000000000014524607240014275 5ustar spectrestaffxa-2.4.0/tests/pparity/Makefile0000644000031500000010000000056714513025326015742 0ustar spectrestaffdefault: # xa should not allow this to happen. if it does, this test is no good. ../../xa bad.s || exit 0 && exit 1 ../../xa bad2.s || exit 0 && exit 1 ../../xa bad3.s || exit 0 && exit 1 ../../xa bad4.s || exit 0 && exit 1 # expected-to-fail tests did fail. should be no more errors now. ../../xa good.s -o good.o ../hextool -cmp=good.ok < good.o clean: rm -f *.o xa-2.4.0/tests/pparity/bad.s0000644000031500000010000000005014513025326015177 0ustar spectrestaff#define FOO(a,b) #define BAR(c) FOO(c) xa-2.4.0/tests/pparity/bad2.s0000644000031500000010000000005614513025326015267 0ustar spectrestaff#define FOO(a,b,c) #define BAR(b,c) FOO(b,c) xa-2.4.0/tests/pparity/bad3.s0000644000031500000010000000025414513025326015270 0ustar spectrestaff#define FOO(a,b,c) #define BAR(a,b,c) FOO(c,b,a) #define FOO(a,b,c) #define BAR(b,c) FOO("x",b,c) #define FOO(a,b,c) .byt a,b,c #define BAR(c) FOO("1", "2", c) FOO("3") xa-2.4.0/tests/pparity/bad4.s0000644000031500000010000000006214513025326015266 0ustar spectrestaff#define FOO(a) #define BAR(c) FOO(c,a) BAR(1, 2) xa-2.4.0/tests/pparity/good.ok0000644000031500000010000000000314513025326015546 0ustar spectrestaff123xa-2.4.0/tests/pparity/good.s0000644000031500000010000000025414513025326015407 0ustar spectrestaff#define FOO(a,b,c) #define BAR(a,b,c) FOO(c,b,a) #define FOO(a,b,c) #define BAR(b,c) FOO("x",b,c) #define FOO(a,b,c) .byt a,b,c #define BAR(c) FOO("1", "2", c) BAR("3") xa-2.4.0/tests/ppdefines/0000755000031500000010000000000014524607240014562 5ustar spectrestaffxa-2.4.0/tests/ppdefines/Makefile0000644000031500000010000000050414524577671016237 0ustar spectrestaff XA=../../xa OBJS=test1.u test2.u test3.u test4.u test5.u test6.u test6a.u test6b.u test7.u all: $(OBJS) clean: rm -f a.o65 $(OBJS) #%: %.a65 %.o65 # ${XA} -XC $< -o $@ # ../hextool -cmp=$@.o65 < $@ # BSD make only understands suffix rules .SUFFIXES: .u .a65 .a65.u: ${XA} -XC $< -o $@ ../hextool -cmp=$*.o65 < $@ xa-2.4.0/tests/ppdefines/test1.a650000644000031500000010000000050614513025326016135 0ustar spectrestaff #define macro1() \ lda #0 #define macro2(a) \ lda #(a) #define macro3(a,b) \ lda #(a): \ ldy #(b) #define const1 $40 #define func1(a) (a) | $20 *=$c000 macro1() macro2(2) macro3(2,3) lda #(2) | $20 lda #func1(2) macro2(func1(3)) macro3(const1, func1(5)) macro3(func1(const1), func1(func1(const1))) xa-2.4.0/tests/ppdefines/test1.o650000644000031500000010000000002614513125337016153 0ustar spectrestaff©©© ©"©"©#©@ %©` `xa-2.4.0/tests/ppdefines/test2.a650000644000031500000010000000073314513025326016140 0ustar spectrestaff /* * tests the definition of macro parameters with spaces * between the name and the brackers / comma */ #define wreg(reg, val) \ lda #(reg) | 0x02 :\ lda #(val) #define wreg2( reg , val , val2 ) \ lda #(reg) | 0x02 :\ lda #(val) :\ ldx #(val2) #define wreg3(reg, val, val2) \ .byt reg, val, val2 #define P1 1 #define P2 2 #define P3 3 *=$c000 wreg(P1, P2) wreg2(P1, P2, P3) wreg3( P1 , P2 , P3 ) xa-2.4.0/tests/ppdefines/test2.o650000644000031500000010000000001514513025326016147 0ustar spectrestaff©©©©˘xa-2.4.0/tests/ppdefines/test3.a650000644000031500000010000000045414513025326016141 0ustar spectrestaff #define GD_DEVICE 0x01 // Get device descriptor for Device #define GD_CONFIGURATION 0x02 // Get device descriptor for Configuration #define GD_STRING 0x03 // Get device descriptor for String *=$c000 lda #GD_DEVICE ; test lda #GD_CONFIGURATION+$10 xa-2.4.0/tests/ppdefines/test3.o650000644000031500000010000000000414513025326016146 0ustar spectrestaff©©xa-2.4.0/tests/ppdefines/test4.a650000644000031500000010000000054014513025326016136 0ustar spectrestaff ; same as test3, only there is a colon in the "//" comment #define GD_DEVICE 0x01 // Get device descriptor: Device #define GD_CONFIGURATION 0x02 // Get device descriptor: Configuration #define GD_STRING 0x03 // Get device descriptor: String *=$c000 lda #GD_DEVICE ; test lda #GD_CONFIGURATION+$10 xa-2.4.0/tests/ppdefines/test4.o650000644000031500000010000000000414513025326016147 0ustar spectrestaff©©xa-2.4.0/tests/ppdefines/test5.a650000644000031500000010000000111714513025326016140 0ustar spectrestaff ; this tests the double-slash quote in lines with various disturbances... lda #1 ; test1 lda #2/1 ; test2 with a constant division lda #3*2 ; test3 with multi lda #4<<1 ; test with shift left lda #4>>1 ; test with shift right lda #"/" ; test with quotes lda #'/' ; test with single quotes .byt "/", "/", '/' ; test with multiple quotes ; test with comments in quotes .byt "//" ; test with comment in quotes ; tests with escaped and quoted quotes .byt '"' ; test xa65 specific escape code .byt '"' ; test .byt "'" ; test xa65 specific escape code .byt "'" ; test xa-2.4.0/tests/ppdefines/test5.o650000644000031500000010000000002714513025326016155 0ustar spectrestaff©©©©©©/©//////""''xa-2.4.0/tests/ppdefines/test6.a650000644000031500000010000000214114513025326016137 0ustar spectrestaff // testing some more complicated defines #define spi_enable(mask) \ lda SPISSRB :\ and #255-(mask) :\ sta SPISSRB #define spi_disable(mask) \ lda SPISSRB :\ ora #(mask) :\ sta SPISSRB #define spi_wra() \ .( :\ sta SPIDR :\ l_ bit SPISR :\ bpl l_ :\ lda SPIDR :\ .) #define max3420e_enable() \ spi_enable(MAX3420E_EnMask) #define max3420e_disable() \ spi_disable(MAX3420E_EnMask) #define wrac(reg) \ pha :\ max3420e_enable() :\ lda #(reg) | 0x02 :\ spi_wra() :\ pla :\ spi_wra() :\ max3420e_disable() // just the definition of this macro hangs the xa indefinitely... #define CLRBIT(reg, val) \ rreg(reg) :\ and #255-val :\ wrac(reg) xa-2.4.0/tests/ppdefines/test6.o650000644000031500000010000000000014513125370016145 0ustar spectrestaffxa-2.4.0/tests/ppdefines/test6a.a650000644000031500000010000000121314513025326016277 0ustar spectrestaff // testing some more complicated defines #define max3420e_enable() \ spi_enable(MAX3420E_EnMask) #define max3420e_disable() \ spi_disable(MAX3420E_EnMask) #define wrac(reg) \ pha :\ max3420e_enable() :\ lda #(reg) | 0x02 :\ spi_wra() :\ pla :\ spi_wra() :\ max3420e_disable() // just the definition of this macro hangs the xa indefinitely... #define CLRBIT(reg, val) \ rreg(reg) :\ and #255-val :\ wrac(reg) xa-2.4.0/tests/ppdefines/test6a.o650000644000031500000010000000000014513125421016303 0ustar spectrestaffxa-2.4.0/tests/ppdefines/test6b.a650000644000031500000010000000060014513025326016277 0ustar spectrestaff // testing some more complicated defines // this is the minimum I found to trigger the hang symptom #define max3420e_enable() nop #define wrac(reg) \ max3420e_enable() :\ lda #(reg) // just the definition of this macro hangs the xa indefinitely... #define CLRBIT(reg, val) \ wrac(reg) // *=$c000 // CLRBIT(1,2) xa-2.4.0/tests/ppdefines/test6b.o650000644000031500000010000000000014513125433016307 0ustar spectrestaffxa-2.4.0/tests/ppdefines/test7.a650000644000031500000010000000111314513025326016136 0ustar spectrestaff // due to a bug, the first definition was not behaving correct with the // parameters during evaluation (which wasn't tested in test6*). // With max3420e_enable2() first, the code would work, as it // was not used, with the used max3420e_enable() first it would break. #define max3420e_enable() nop #define max3420e_enable2() nop #define wrac(reg) \ max3420e_enable() :\ lda #(reg) // just the definition of this macro hangs the xa indefinitely... #define CLRBIT(reg, val) \ wrac(reg) *=$c000 CLRBIT(1,2) xa-2.4.0/tests/ppdefines/test7.o650000644000031500000010000000000314513025326016151 0ustar spectrestaffę©xa-2.4.0/tests/ppstrings/0000755000031500000010000000000014524607241014637 5ustar spectrestaffxa-2.4.0/tests/ppstrings/ok0000644000031500000010000000002714514123025015162 0ustar spectrestaffDUP^@0DUP@DUP^@DUPDU0DUxa-2.4.0/tests/ppstrings/test.s0000644000031500000010000000017014514123014015766 0ustar spectrestaff #define DUP 123 .asc "DUP^@" .asc '0DUP\@' .asc "D","UP^@" .asc "DUP .asc "DU0 .asc "DU xa-2.4.0/tests/quotch/0000755000031500000010000000000014524607241014111 5ustar spectrestaffxa-2.4.0/tests/quotch/ok0000644000031500000010000000001614513025305014433 0ustar spectrestaff©;É:)"é; :I'xa-2.4.0/tests/quotch/test.s0000644000031500000010000000020614513025305015243 0ustar spectrestaff .word $9000 * = $9000 ; test specific single characters can be quoted LDA #';' CMP #':' AND #'"' SBC #";" ORA #":" EOR #"'" xa-2.4.0/tests/recmac/0000755000031500000010000000000014524607240014037 5ustar spectrestaffxa-2.4.0/tests/recmac/Makefile0000644000031500000010000000034614513025305015474 0ustar spectrestaffdefault: # this should fail. ../../xa -DFAIL test.asm || exit 0 && exit 1 # these should not fail. ../../xa test.asm ../hextool -cmp=test.ok < a.o65 ../../xa testi.asm ../hextool -cmp=testi.ok < a.o65 clean: rm -f a.o65 xa-2.4.0/tests/recmac/cpu.inc0000644000031500000010000000006114513025305015310 0ustar spectrestaff; ; FILE cpu.inc ; #define WDM(v) .byt $42,(v) xa-2.4.0/tests/recmac/test.asm0000644000031500000010000000065314513025305015516 0ustar spectrestaff#define AA 1 #define POKE(a,b) lda #b: sta a #define WW AA start ; next line works POKE(1, 2) ; next two lines work lda #AA sta 2 ; next line fails POKE(AA, 2) POKE(WW, 2) lda #WW sta 2 #define WW 94 POKE(WW, 2) #define WW 5 #define AA WW #define POKE(a,b) lda #a: sta b POKE(AA, 3) bne start rts /* this should bug out */ #ifdef FAIL POKE(NOGOOD, 7) #endif xa-2.4.0/tests/recmac/test.ok0000644000031500000010000000003714513025305015343 0ustar spectrestaff©…©…©…©…©…©…^©…Đâ`xa-2.4.0/tests/recmac/testi.asm0000644000031500000010000000012314513025305015657 0ustar spectrestaff ; ; FILE image.a ; #include "cpu.inc" .text *=$C000 Foo: WDM(170) xa-2.4.0/tests/recmac/testi.ok0000644000031500000010000000000214513025305015504 0ustar spectrestaffBŞxa-2.4.0/tests/recucom/0000755000031500000010000000000014524607241014243 5ustar spectrestaffxa-2.4.0/tests/recucom/ok0000644000031500000010000000002014514123276014567 0ustar spectrestaff©©©©©TOBY©xa-2.4.0/tests/recucom/test.s0000644000031500000010000000074414514123271015406 0ustar spectrestaff *=$1000 lda #0 ; recursive comments are gone in 2.4 /* sta $2000 /* commented lda #1 */ ; C++ comments // sta $2001 ; quotes in comments lda #2 /* this is '$' */ lda #3 /* this is "$" */ lda #4 /* this is "\"" */ lda #5 /* this is '"' */ ; examples in preprocessor statements #define E_ILLNAM <-34 /* illegal name (joker "*", "?", "\"") */ /* TODO: interpret "\" escape codes, shell variables */ .asc "TOBY" // Handle *EXEC/*SPOOL case lda #0 xa-2.4.0/tests/relmode/0000755000031500000010000000000014524607240014234 5ustar spectrestaffxa-2.4.0/tests/relmode/Makefile0000644000031500000010000000120114524607047015673 0ustar spectrestaff# # Makefile for tests # XA=../../xa tests: mixabs1 mixabs2 mix1 mix2 mixabs1: mixabsolute.a65 @echo This should fail ${XA} mixabsolute.a65 || exit 0 && exit 1 mixabs2: mixabsolute.a65 ${XA} -R mixabsolute.a65 -o $@.tmp ../../file65 -v $@.tmp ../../reloc65 -bt 40960 -o $@ $@.tmp ../hextool -cmp=b.ok < $@ mix1: mix1.a65 ${XA} -R -o $@.o65 mix1.a65 ../../file65 -v $@.o65 ../../reloc65 -X -o $@ $@.o65 ../hextool -cmp=$@.ok < $@.o65 mix2: mix2.a65 ${XA} -R -o $@.o65 mix2.a65 ../../file65 -v $@.o65 ../../reloc65 -X -o $@ $@.o65 ../hextool -cmp=$@.ok < $@.o65 clean: rm -f a.err *.o65 a.hex mixabs2* mix1 mix2 *.tmp xa-2.4.0/tests/relmode/b.ok0000644000031500000010000000012614513126412015002 0ustar spectrestaffo65  @­ ­ ­ ­  ‚‚‚l1 l2 l2a l3l4  xa-2.4.0/tests/relmode/mix1.a650000644000031500000010000000020114520352712015415 0ustar spectrestaff .text .word $0401 *=$0401 *= .data NextPacketPtr: .byte 0,0 ; word xa-2.4.0/tests/relmode/mix1.ok0000600000031500000010000000006614520352640015434 0ustar spectrestaffo65@NextPacketPtrxa-2.4.0/tests/relmode/mix2.a650000644000031500000010000000017514520352712015430 0ustar spectrestaff .text .word $0401 *=$0401 .data NextPacketPtr: .byte 0,0 ; word xa-2.4.0/tests/relmode/mix2.ok0000600000031500000010000000006614520352643015440 0ustar spectrestaffo65@NextPacketPtrxa-2.4.0/tests/relmode/mixabsolute.a650000644000031500000010000000014614513025326017103 0ustar spectrestaff .text l1 lda l1 *=$2000 l2 lda l2 *= l2a lda l2a .data l3 .word l3 .text l4 lda l4 xa-2.4.0/tests/relmode/testseg.ok0000600000031500000010000000033414520352645016237 0ustar spectrestaffo65U@$@renamescratchcopynewvalidateinitializeassigncdrdmddrv˙ &18;>AF"c0˙cmdtcowc2c3 c4c5c6c7%c110c127c13:c14=c15@cmdaDxa-2.4.0/tests/relocmode/0000755000031500000010000000000014524607240014556 5ustar spectrestaffxa-2.4.0/tests/relocmode/Makefile0000644000031500000010000000031014513025305016202 0ustar spectrestaffdefault: test1 test1: # this should fail in non-relocating mode ../../xa test1.s -o test1.o || exit 0 && exit 1 ../../xa -R test1.s -o test1.o ../hextool -cmp=ok < test1.o clean: rm -f *.o xa-2.4.0/tests/relocmode/ok0000644000031500000010000000005614513025305015105 0ustar spectrestaffo65@­Şfooxa-2.4.0/tests/relocmode/test1.s0000644000031500000010000000004114513025305015767 0ustar spectrestaff lda foo .data foo .byt $aa xa-2.4.0/tests/relocundef/0000755000031500000010000000000014524607240014733 5ustar spectrestaffxa-2.4.0/tests/relocundef/Makefile0000644000031500000010000000133314514123676016400 0ustar spectrestaff default: all all: a.o65 b.o65 compare a.o65: test1.o65 @echo "********* This should give a warning about an undefined relocation table entry" ../../reloc65 -X test1.o65 ../hextool a.o65 > a.o65.hex b.o65: test2.o65 @echo "********* This should NOT give a warning" ../../reloc65 -X -o b.o65 test2.o65 ../hextool b.o65 > b.o65.hex test1.o65: test1.a65 ../../xa -R -Lundefl -Ll2 -o test1.o65 test1.a65 ../hextool test1.o65 > test1.o65.hex test2.o65: test2.a65 ../../xa -R -o test2.o65 test2.a65 ../hextool test2.o65 > test2.o65.hex compare: a.o65 b.o65 ../hextool -cmp=a.ok < a.o65 ../hextool -cmp=b.ok < b.o65 clean: rm -f test1.o65 a.o65 test1.o65.hex a.o65.hex rm -f test2.o65 b.o65 test2.o65.hex b.o65.hex xa-2.4.0/tests/relocundef/a.ok0000644000031500000010000000001114513025305015470 0ustar spectrestaff˘­ĘĐú`xa-2.4.0/tests/relocundef/b.ok0000644000031500000010000000001114513025305015471 0ustar spectrestaff˘­ĘĐú`xa-2.4.0/tests/relocundef/test1.a650000644000031500000010000000013114513025305016275 0ustar spectrestaff // this file defines an undefined label .text ldx #1 l1 lda undefl dex bne l1 rts xa-2.4.0/tests/relocundef/test2.a650000644000031500000010000000014414513025305016302 0ustar spectrestaff // this file defines an undefined label .text ldx #1 l1 lda undefl dex bne l1 rts undefl =1 xa-2.4.0/tests/reset_segment/0000755000031500000010000000000014524607240015451 5ustar spectrestaffxa-2.4.0/tests/reset_segment/Makefile0000644000031500000010000000027114513025326017106 0ustar spectrestaffdefault: test1 test1: ../../xa -R -LLIB6502 test1.s -o test1.o ../hextool -cmp=ok1 < test1.o ../../xa -R test2.s -o test2.o ../hextool -cmp=ok2 < test2.o clean: rm -f *.o a.o65 xa-2.4.0/tests/reset_segment/ok10000644000031500000010000000005214513025305016055 0ustar spectrestaffo65@Đfooxa-2.4.0/tests/reset_segment/ok20000644000031500000010000000011414513025305016055 0ustar spectrestaffo65@­4­absolute­4­reloc‚foo4barxa-2.4.0/tests/reset_segment/test1.s0000644000031500000010000000021214513025305016662 0ustar spectrestaff ; forward reference ; results in illegal ptr arithmetic when segment ; is not reset between pass1 and pass2 bne foo foo .data xa-2.4.0/tests/reset_segment/test2.s0000644000031500000010000000033314513025305016667 0ustar spectrestaff ; test absolute code embedded into relocatable mode .text lda foo lda bar ; go into absolute mode *=$1234 foo .asc "absolute",0 lda foo lda bar ; go back into relocatble mode *= bar .asc "reloc",0 xa-2.4.0/tests/reset_segment/test2a.s0000644000031500000010000000002414513025326017030 0ustar spectrestaff *=$1234 *= xa-2.4.0/tests/stringcom/0000755000031500000010000000000014524607241014613 5ustar spectrestaffxa-2.4.0/tests/stringcom/ok0000644000031500000010000000015714513334417015152 0ustar spectrestaff€SIEx256SNSIE/256SNSIE//256SNSIEy256SNPASS/*PASS*///PASS//PASSPASS"\PASS/*PASS*///PASS//"\PASSSIE/*256*/NPASSxa-2.4.0/tests/stringcom/test.s0000644000031500000010000000063114514117254015755 0ustar spectrestaff* = $e00 .byt 10/2 // watchs // phlegm /* .word 10/2 */ .word 65536/2 // .byt 9/9 // yo mama // .asc "FAIL" .asc "SIEx256SN" // foo .asc "SIE/256SN" // bar .asc "SIE//256SN" // bar .asc "SIEy256SN" // baz .asc "PASS/*PASS*///PASS//PASS" .asc "PASS\"\\PASS/*PASS*///PASS//\"\\PASS" .asc "SIE/*256*/N" /* .asc "SIE/*256 .asc "FAIL" */ .asc "PASS" // .asc "FAIL" /* .asc "FAIL*/" */ xa-2.4.0/tests/undef/0000755000031500000010000000000014524607241013707 5ustar spectrestaffxa-2.4.0/tests/undef/Makefile0000644000031500000010000000313114524607173015351 0ustar spectrestaff# # Makefile for tests # XA=../../xa OBJS=undef2 undef3 undef5 undef6 tests: bannerf undef1 undef4 undef5f undef6f banner $(OBJS) banner: @echo ======================================= @echo All tests meant to fail have done so correctly; @echo The following tests should pass bannerf: @echo ======================================= @echo The following should fail undef1: undef.a65 @echo These should fail ${XA} undef.a65 || exit 0 && exit 1 ${XA} -R undef.a65 || exit 0 && exit 1 ${XA} -R -U -DFAIL undef.a65 || exit 0 && exit 1 ${XA} -R -Ll1 -Ll3 -Ll4 -Ll5 undef.a65 || exit 0 && exit 1 undef2: undef.a65 ${XA} -R -Ll1 -Ll3 undef.a65 -o $@.tmp ../../reloc65 -bt 40960 -o $@ $@.tmp ../hextool -cmp=undef2.ok < $@ undef3: undef.a65 ${XA} -R -U undef.a65 -o $@.tmp ../../reloc65 -bt 40960 -o $@ $@.tmp ../hextool -cmp=undef2.ok < $@ undef4: undef4.a65 @echo These should fail ${XA} undef4.a65 || exit 0 && exit 1 ${XA} -R undef4.a65 || exit 0 && exit 1 ${XA} -R -Ll1 undef4.a65 || exit 0 && exit 1 ${XA} -R -U undef4.a65 || exit 0 && exit 1 undef5f: undef5.a65 @echo These should fail ${XA} undef5.a65 || exit 0 && exit 1 ${XA} -R undef5.a65 || exit 0 && exit 1 ${XA} -R -Ll1 undef5.a65 || exit 0 && exit 1 undef5: undef5.a65 ${XA} -R -U undef5.a65 -o $@ ../hextool -cmp=undef5.ok < $@ undef6f: undef6.a65 @echo These should fail ${XA} undef6.a65 || exit 0 && exit 1 ${XA} -R undef6.a65 || exit 0 && exit 1 ${XA} -R -Ll1 undef6.a65 || exit 0 && exit 1 undef6: undef6.a65 ${XA} -R -U undef6.a65 -o $@ ../hextool -cmp=undef6.ok < $@ clean: rm -f a.err a.o65 b.o65 *.tmp $(OBJS) xa-2.4.0/tests/undef/undef.a650000644000031500000010000000015014513025326015315 0ustar spectrestaff .text lda l1 *=$2000 #ifdef FAIL lda l2 #endif *= lda l3 .( lda l4 .) l4=1 lda l5 l5 xa-2.4.0/tests/undef/undef2.ok0000644000031500000010000000011114513131643015412 0ustar spectrestaffo65  @­­­­  l1l3€€‚l4l5  xa-2.4.0/tests/undef/undef4.a650000644000031500000010000000006014513025326015401 0ustar spectrestaff .text lda l1 .( .( lda l1 .) l1 .) xa-2.4.0/tests/undef/undef5.a650000644000031500000010000000006214513025326015404 0ustar spectrestaff .text .( .( lda l1 .) l1 .) lda l1 xa-2.4.0/tests/undef/undef5.ok0000644000031500000010000000006014513133120015410 0ustar spectrestaffo65@­­l1‚€xa-2.4.0/tests/undef/undef6.a650000644000031500000010000000012114513025326015401 0ustar spectrestaff .text .( .( lda l1 .) l1 .) .( .( lda l1 .) l1 .) lda l1 xa-2.4.0/tests/undef/undef6.ok0000644000031500000010000000006514513133162015424 0ustar spectrestaffo65 @­­­l1‚‚€xa-2.4.0/tests/usb65/0000755000031500000010000000000014524607241013552 5ustar spectrestaffxa-2.4.0/tests/usb65/Makefile0000644000031500000010000000030414517106304015203 0ustar spectrestaffdefault: test1.a65 test2.a65 test1.o65 test2.o65 ../../xa -XC -R -U test1.a65 ../hextool -cmp=test1.o65 < a.o65 ../../xa -R -U test2.a65 ../hextool -cmp=test2.o65 < a.o65 clean: rm -f a.o65 xa-2.4.0/tests/usb65/test1.a650000644000031500000010000000154714517105737015143 0ustar spectrestaff #define MAX3421E_EnMask $04 #define max3421e_enable() \ lda #MAX3421E_EnMask :\ jsr spi_enable #define max3421e_disable() \ jsr spi_disable #define spi_wra() /********************************************************************/ #define rPINCTL (17<<3) #define bmFDUPSPI $10 #define bmINTLEVEL $08 #define wreg(reg, val) \ max3421e_enable() :\ lda #(reg) | $02 :\ spi_wra() :\ lda #(val) :\ spi_wra() :\ max3421e_disable() /********************************************************************/ ; unrolled macrois ok max3421e_enable() lda #(rPINCTL) | $02 spi_wra() lda #(bmFDUPSPI+bmINTLEVEL) spi_wra() max3421e_disable() ; macro used o give syntax... wreg(rPINCTL, bmFDUPSPI+bmINTLEVEL) xa-2.4.0/tests/usb65/test1.o650000644000031500000010000000014014517106141015133 0ustar spectrestaffo65@© ©Š© © ©Š© spi_enablespi_disable€€€€xa-2.4.0/tests/usb65/test2.a650000644000031500000010000000013214517106051015117 0ustar spectrestaff .( jsr single single jmp single jmp lenerr bne lenerr lenerr jsr lenerr .) xa-2.4.0/tests/usb65/test2.o650000644000031500000010000000006714517106135015147 0ustar spectrestaffo65@ LL Đ ‚‚‚‚xa-2.4.0/vstudio/0000755000031500000010000000000014513025305013132 5ustar spectrestaffxa-2.4.0/vstudio/00readme.txt0000644000031500000010000000062214513025305015270 0ustar spectrestaffThis directory contains a solution and project files that can be used to build xa and the various tools in the misc directory with the free version of Microsoft Visual C++ 2005 (AKA Visual Studio 2005 Express). This compiler and IDE can be dowloaded free from http://msdn.microsoft.com/vstudio/express/downloads/default.aspx Just run visual studio and load the solution called "vstudio.sln" xa-2.4.0/vstudio/file65.vcproj0000644000031500000010000000753214513025305015460 0ustar spectrestaff xa-2.4.0/vstudio/ldo65.vcproj0000644000031500000010000000752714513025305015323 0ustar spectrestaff xa-2.4.0/vstudio/printcbm.vcproj0000644000031500000010000000754014513025305016203 0ustar spectrestaff xa-2.4.0/vstudio/uncpk.vcproj0000644000031500000010000000752714513025305015512 0ustar spectrestaff xa-2.4.0/vstudio/vstudio.sln0000644000031500000010000000515514513025305015353 0ustar spectrestaff Microsoft Visual Studio Solution File, Format Version 9.00 # Visual C++ Express 2005 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xa", "xa.vcproj", "{55808FFA-DA3B-44AF-AB9E-D937A531F932}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "uncpk", "uncpk.vcproj", "{32CE058C-D818-4756-BAA6-A8AD4378308D}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "file65", "file65.vcproj", "{3CB15D2B-3777-4401-BF81-C0BC1B8AE8E6}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ldo65", "ldo65.vcproj", "{EFA4F295-A2CD-4B8A-ABE9-DD9DEB670CA6}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "printcbm", "printcbm.vcproj", "{26727633-7B9B-40CB-A31A-C6C6FEBA00CA}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {55808FFA-DA3B-44AF-AB9E-D937A531F932}.Debug|Win32.ActiveCfg = Debug|Win32 {55808FFA-DA3B-44AF-AB9E-D937A531F932}.Debug|Win32.Build.0 = Debug|Win32 {55808FFA-DA3B-44AF-AB9E-D937A531F932}.Release|Win32.ActiveCfg = Release|Win32 {55808FFA-DA3B-44AF-AB9E-D937A531F932}.Release|Win32.Build.0 = Release|Win32 {32CE058C-D818-4756-BAA6-A8AD4378308D}.Debug|Win32.ActiveCfg = Debug|Win32 {32CE058C-D818-4756-BAA6-A8AD4378308D}.Debug|Win32.Build.0 = Debug|Win32 {32CE058C-D818-4756-BAA6-A8AD4378308D}.Release|Win32.ActiveCfg = Release|Win32 {32CE058C-D818-4756-BAA6-A8AD4378308D}.Release|Win32.Build.0 = Release|Win32 {3CB15D2B-3777-4401-BF81-C0BC1B8AE8E6}.Debug|Win32.ActiveCfg = Debug|Win32 {3CB15D2B-3777-4401-BF81-C0BC1B8AE8E6}.Debug|Win32.Build.0 = Debug|Win32 {3CB15D2B-3777-4401-BF81-C0BC1B8AE8E6}.Release|Win32.ActiveCfg = Release|Win32 {3CB15D2B-3777-4401-BF81-C0BC1B8AE8E6}.Release|Win32.Build.0 = Release|Win32 {EFA4F295-A2CD-4B8A-ABE9-DD9DEB670CA6}.Debug|Win32.ActiveCfg = Debug|Win32 {EFA4F295-A2CD-4B8A-ABE9-DD9DEB670CA6}.Debug|Win32.Build.0 = Debug|Win32 {EFA4F295-A2CD-4B8A-ABE9-DD9DEB670CA6}.Release|Win32.ActiveCfg = Release|Win32 {EFA4F295-A2CD-4B8A-ABE9-DD9DEB670CA6}.Release|Win32.Build.0 = Release|Win32 {26727633-7B9B-40CB-A31A-C6C6FEBA00CA}.Debug|Win32.ActiveCfg = Debug|Win32 {26727633-7B9B-40CB-A31A-C6C6FEBA00CA}.Debug|Win32.Build.0 = Debug|Win32 {26727633-7B9B-40CB-A31A-C6C6FEBA00CA}.Release|Win32.ActiveCfg = Release|Win32 {26727633-7B9B-40CB-A31A-C6C6FEBA00CA}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal xa-2.4.0/vstudio/xa.vcproj0000644000031500000010000001235314513025305014773 0ustar spectrestaff