pax_global_header00006660000000000000000000000064135724110130014507gustar00rootroot0000000000000052 comment=6b433c5512d693262742a93c8bfdfb353d4be853 CheeseCutter-master/000077500000000000000000000000001357241101300147275ustar00rootroot00000000000000CheeseCutter-master/AUTHORS000066400000000000000000000000001357241101300157650ustar00rootroot00000000000000CheeseCutter-master/ChangeLog000066400000000000000000000000711357241101300164770ustar00rootroot00000000000000See http://theyamo.kapsi.fi/ccutter/ for latest changes CheeseCutter-master/INSTALL000066400000000000000000000004371357241101300157640ustar00rootroot00000000000000make -- build Linux binary using gdc make -f Makefile.mac -- build MacOS binary using ldc2 make -f Makefile.mingw -- build MinGW binary using gdc on Wine make -f Makefile.dmd -- build using dmd make-wintest.sh -- build Windows zip archive with required dlls CheeseCutter-master/LICENSE.md000066400000000000000000000431101357241101300163320ustar00rootroot00000000000000 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) 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) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 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. CheeseCutter-master/Makefile000066400000000000000000000034031357241101300163670ustar00rootroot00000000000000# make install DESTDIR=/home/yamo/devel/cc2/snap/parts/ccutter/install LIBS=-ldl -lstdc++ COMFLAGS=-O2 -g VERSION=$(shell cat Version) DFLAGS=$(COMFLAGS) $(LDFLAGS) -I./src -J./src/c64 -J./src/font CFLAGS:=$(COMFLAGS) $(CFLAGS) CXXFLAGS=$(COMFLAGS) $(CPPFLAGS) -I./src COMPILE.d = $(DC) $(DFLAGS) -c DC=gdc EXE= TARGET=ccutter OBJ_EXT=.o include Makefile.objects.mk .PHONY: install release dist clean dclean tar all: ct2util ccutter ccutter:$(C64OBJS) $(OBJS) $(CXX_OBJS) $(DC) $(COMFLAGS) -o $@ $(OBJS) $(CXX_OBJS) $(LIBS) .cpp.o : $(CXX_SRCS) $(CXX) $(CXXFLAGS) -c $< -o $@ .c.o : $(C_SRCS) $(CC) -c $< -o $@ ct: $(C64OBJS) $(CTOBJS) ct2util: $(C64OBJS) $(UTILOBJS) $(DC) $(COMFLAGS) -o $@ $(UTILOBJS) c64: $(C64OBJS) install: all strip ccutter$(EXE) strip ct2util$(EXE) cp ccutter$(EXE) $(DESTDIR) cp ct2util$(EXE) $(DESTDIR) mkdir $(DESTDIR)/example_tunes cp -r tunes/* $(DESTDIR)/example_tunes # release version with additional optimizations release: DFLAGS += -frelease -fno-bounds-check release: all strip ccutter$(EXE) strip ct2util$(EXE) # tarred release dist: release tar --transform 's,^\.,cheesecutter-$(VERSION),' -cvf cheesecutter-$(VERSION)-linux-x86.tar.gz $(DIST_FILES) clean: rm -f *.o *~ resid/*.o resid-fp/*.o ccutter ct2util \ $(C64OBJS) $(OBJS) $(CTOBJS) $(CXX_OBJS) $(UTILOBJS) $(C_OBJS) dclean: clean rm -f cheesecutter-$(VERSION)-linux-x86.tar.gz # tarred source from master tar: git archive master --prefix=cheesecutter-$(VERSION)/ | bzip2 > cheesecutter-$(VERSION)-src.tar.bz2 # -------------------------------------------------------------------------------- src/c64/player.bin: src/c64/player_v4.acme acme -f cbm --outfile $@ $< src/ct/base.o: src/c64/player.bin src/ui/ui.o: src/ui/help.o %.o: %.d $(COMPILE.d) -o $@ $< CheeseCutter-master/Makefile.dmd000066400000000000000000000033401357241101300171320ustar00rootroot00000000000000LIBS=-L-ldl -L-lstdc++ COMFLAGS= DLINK=$(COMFLAGS) VERSION=$(shell cat Version) DFLAGS=$(COMFLAGS) -I./src -J./src/c64 -J./src/font -O CFLAGS=$(COMFLAGS) -O1 CXXFLAGS=-I./src -O3 COMPILE.d = $(DC) $(DFLAGS) -c -of$@ OUTPUT_OPTION= DC=dmd EXE= TARGET=ccutter OBJ_EXT=.o include Makefile.objects.mk $(TARGET): $(C64OBJS) $(OBJS) $(CXX_OBJS) $(DC) $(DLINK) -of$(TARGET) $(OBJS) $(CXX_OBJS) $(LIBS) .cpp.o : $(CXX_SRCS) $(CXX) $(CXXFLAGS) -c $< -o $@ .c.o : $(C_SRCS) $(CC) -c $< -o $@ ct: $(C64OBJS) $(CTOBJS) ct2util: $(C64OBJS) $(UTILOBJS) $(DC) $(DLINK) -of$@ $(UTILOBJS) $(LIBS) c64: $(C64OBJS) all: c64 $(OBJS) $(CXX_OBJS) $(UTILOBJS) ct2util ct $(TARGET) # release version with additional optimizations # release: DFLAGS += -release -boundscheck=off release: all strip ccutter$(EXE) strip ct2util$(EXE) # development release pulled from git master devrelease: DFLAGS += -version=DEV devrelease: all tar --transform 's,^\.,cheesecutter-devbuild,' -cvf cheesecutter-devbuild-linux-x86.tar.gz $(DIST_FILES) # tarred release dist: release tar --transform 's,^\.,cheesecutter-$(VERSION),' -cvf cheesecutter-$(VERSION)-linux-x86.tar.gz $(DIST_FILES) clean: rm -f *.o *~ resid/*.o resid-fp/*.o ccutter ct2util \ $(C64OBJS) $(OBJS) $(CTOBJS) $(CXX_OBJS) $(UTILOBJS) $(C_OBJS) dclean: clean rm -f cheesecutter-$(VERSION)-linux-x86.tar.gz # tarred source from master tar: git archive master --prefix=cheesecutter-$(VERSION)/ | bzip2 > cheesecutter-$(VERSION)-src.tar.bz2 # -------------------------------------------------------------------------------- src/c64/player.bin: src/c64/player_v4.acme acme -f cbm --outfile $@ $< src/ct/base.o: src/c64/player.bin src/ui/ui.o: src/ui/help.o %.o: %.d $(COMPILE.d) $(OUTPUT_OPTION) $< CheeseCutter-master/Makefile.ldc000066400000000000000000000033461357241101300171360ustar00rootroot00000000000000# make install DESTDIR=/home/yamo/devel/cc2/snap/parts/ccutter/install LIBS=-L-ldl -L-lstdc++ COMFLAGS=-O2 VERSION=$(shell cat Version) DFLAGS=$(COMFLAGS) -I./src -J./src/c64 -J./src/font CFLAGS=$(COMFLAGS) CXXFLAGS=$(COMFLAGS) -I./src COMPILE.d = $(DC) $(DFLAGS) -c DC=ldc2 EXE= TARGET=ccutter OBJ_EXT=.o include Makefile.objects.mk .PHONY: install release dist clean dclean tar all: ct2util ccutter ccutter:$(C64OBJS) $(OBJS) $(CXX_OBJS) $(DC) $(COMFLAGS) -of=$@ $(OBJS) $(CXX_OBJS) $(LIBS) .cpp.o : $(CXX_SRCS) $(CXX) $(CXXFLAGS) -c $< -o $@ .c.o : $(C_SRCS) $(CC) -c $< -o $@ ct: $(C64OBJS) $(CTOBJS) ct2util: $(C64OBJS) $(UTILOBJS) $(DC) $(COMFLAGS) -of=$@ $(UTILOBJS) c64: $(C64OBJS) install: all strip ccutter$(EXE) strip ct2util$(EXE) cp ccutter$(EXE) $(DESTDIR) cp ct2util$(EXE) $(DESTDIR) mkdir $(DESTDIR)/example_tunes cp -r tunes/* $(DESTDIR)/example_tunes # release version with additional optimizations release: DFLAGS += -frelease -fno-bounds-check release: all strip ccutter$(EXE) strip ct2util$(EXE) # tarred release dist: release tar --transform 's,^\.,cheesecutter-$(VERSION),' -cvf cheesecutter-$(VERSION)-linux-x86.tar.gz $(DIST_FILES) clean: rm -f *.o *~ resid/*.o resid-fp/*.o ccutter ct2util \ $(C64OBJS) $(OBJS) $(CTOBJS) $(CXX_OBJS) $(UTILOBJS) $(C_OBJS) dclean: clean rm -f cheesecutter-$(VERSION)-linux-x86.tar.gz # tarred source from master tar: git archive master --prefix=cheesecutter-$(VERSION)/ | bzip2 > cheesecutter-$(VERSION)-src.tar.bz2 # -------------------------------------------------------------------------------- src/c64/player.bin: src/c64/player_v4.acme acme -f cbm --outfile $@ $< src/ct/base.o: src/c64/player.bin src/ui/ui.o: src/ui/help.o %.o: %.d $(COMPILE.d) -of=$@ $< CheeseCutter-master/Makefile.mac000066400000000000000000000037761357241101300171430ustar00rootroot00000000000000#LIBS=/opt/ldc/build/lib/libphobos-ldc.a /opt/ldc/build/lib/libdruntime-ldc.a -lstdc++ #LIBS=/opt/ldc2/lib/libphobos-ldc.a /opt/ldc2/lib/libdruntime-ldc.a -lstdc++ LIBS=/usr/local/lib/libphobos2-ldc.a /usr/local/lib/libdruntime-ldc.a -lstdc++ FRAMEWORKS=-framework Foundation -framework SDL COMFLAGS= -mmacosx-version-min=10.7 VERSION=$(shell cat Version) DLINK=$(COMFLAGS) DFLAGS=-I./src -J./src/c64 -J./src/font CFLAGS=$(COMFLAGS) CXXFLAGS=$(CFLAGS) -I./src -O2 LDFLAGS=-rpath,@executable_path/../Frameworks COMPILE.d = $(DC) $(DFLAGS) -d -O2 -c -of=$@ DC=ldc2 EXE= TARGET=ccutter OBJ_EXT=.o include Makefile.objects.mk $(TARGET): $(C64OBJS) $(OBJS) $(CXX_OBJS) $(CC) $(DLINK) -Wl,$(LDFLAGS) -o $(TARGET) $(OBJS) $(CXX_OBJS) $(LIBS) $(FRAMEWORKS) .cpp.o : $(CXX_SRCS) $(CXX) $(CXXFLAGS) -c $< -o $@ .c.o : $(C_SRCS) $(CC) -c $< -o $@ ct: $(C64OBJS) $(CTOBJS) ct2util: $(C64OBJS) $(UTILOBJS) $(CC) $(DLINK) -o $@ $(UTILOBJS) $(LIBS) c64: $(C64OBJS) all: c64 $(OBJS) $(CXX_OBJS) ct2util ct $(TARGET) release: all strip ccutter$(EXE) strip ct2util$(EXE) rm -rf CheeseCutter.app mkdir -p CheeseCutter.app/Contents/Frameworks mkdir -p CheeseCutter.app/Contents/MacOS cp -r arch/MacOS/Contents CheeseCutter.app cp -r /Library/Frameworks/SDL.framework CheeseCutter.app/Contents/Frameworks cp $(TARGET) CheeseCutter.app/Contents/MacOS cp ct2util CheeseCutter.app/Contents/MacOS dist: release rm -rf dist rm -rf CheeseCutter_$(VERSION).dmg arch/makedmg.sh clean: rm -f *.o *~ resid/*.o resid-fp/*.o ccutter ct2util \ $(C64OBJS) $(OBJS) $(CTOBJS) $(CXX_OBJS) $(UTILOBJS) dclean: clean rm -rf dist rm -rf CheeseCutter.app rm -rf CheeseCutter_$(VERSION).dmg tar: git archive master --prefix=cheesecutter-$(VERSION)/ | bzip2 > cheesecutter-$(VERSION)-macosx-src.tar.bz2 # -------------------------------------------------------------------------------- src/c64/player.bin: src/c64/player_v4.acme acme -f cbm --outfile $@ $< src/ct/base.o: src/c64/player.bin src/ui/ui.o: src/ui/help.o %.o: %.d $(COMPILE.d) $< CheeseCutter-master/Makefile.objects.mk000066400000000000000000000073531357241101300204350ustar00rootroot00000000000000OBJS= src/derelict/util/compat$(OBJ_EXT) \ src/derelict/util/sharedlib$(OBJ_EXT) \ src/derelict/util/exception$(OBJ_EXT) \ src/derelict/util/loader$(OBJ_EXT) \ src/derelict/util/wintypes$(OBJ_EXT) \ src/derelict/util/xtypes$(OBJ_EXT) \ src/derelict/sdl/sdl$(OBJ_EXT) \ src/derelict/sdl/net$(OBJ_EXT) \ src/derelict/sdl/ttf$(OBJ_EXT) \ src/derelict/sdl/mixer$(OBJ_EXT) \ src/derelict/sdl/image$(OBJ_EXT) \ src/derelict/sdl/sdlfuncs$(OBJ_EXT) \ src/derelict/sdl/sdltypes$(OBJ_EXT) \ src/derelict/sdl/macinit/CoreFoundation$(OBJ_EXT) \ src/derelict/sdl/macinit/DerelictSDLMacLoader$(OBJ_EXT) \ src/derelict/sdl/macinit/ID$(OBJ_EXT) \ src/derelict/sdl/macinit/MacTypes$(OBJ_EXT) \ src/derelict/sdl/macinit/NSApplication$(OBJ_EXT) \ src/derelict/sdl/macinit/NSArray$(OBJ_EXT) \ src/derelict/sdl/macinit/NSAutoreleasePool$(OBJ_EXT) \ src/derelict/sdl/macinit/NSDictionary$(OBJ_EXT) \ src/derelict/sdl/macinit/NSEnumerator$(OBJ_EXT) \ src/derelict/sdl/macinit/NSEvent$(OBJ_EXT) \ src/derelict/sdl/macinit/NSGeometry$(OBJ_EXT) \ src/derelict/sdl/macinit/NSMenu$(OBJ_EXT) \ src/derelict/sdl/macinit/NSMenuItem$(OBJ_EXT) \ src/derelict/sdl/macinit/NSNotification$(OBJ_EXT) \ src/derelict/sdl/macinit/NSObject$(OBJ_EXT) \ src/derelict/sdl/macinit/NSProcessInfo$(OBJ_EXT) \ src/derelict/sdl/macinit/NSString$(OBJ_EXT) \ src/derelict/sdl/macinit/NSZone$(OBJ_EXT) \ src/derelict/sdl/macinit/runtime$(OBJ_EXT) \ src/derelict/sdl/macinit/SDLMain$(OBJ_EXT) \ src/derelict/sdl/macinit/selectors$(OBJ_EXT) \ src/derelict/sdl/macinit/string$(OBJ_EXT) \ src/audio/audio$(OBJ_EXT) \ src/audio/player$(OBJ_EXT) \ src/audio/timer$(OBJ_EXT) \ src/audio/callback$(OBJ_EXT) \ src/ct/purge$(OBJ_EXT) \ src/ct/base$(OBJ_EXT) \ src/ct/dump$(OBJ_EXT) \ src/com/fb$(OBJ_EXT) \ src/com/cpu$(OBJ_EXT) \ src/com/kbd$(OBJ_EXT) \ src/com/session$(OBJ_EXT) \ src/com/util$(OBJ_EXT) \ src/main$(OBJ_EXT) \ src/ui/tables$(OBJ_EXT) \ src/ui/dialogs$(OBJ_EXT) \ src/ui/ui$(OBJ_EXT) \ src/ui/input$(OBJ_EXT) \ src/ui/help$(OBJ_EXT) \ src/seq/seqtable$(OBJ_EXT) \ src/seq/tracktable$(OBJ_EXT) \ src/seq/trackmap$(OBJ_EXT) \ src/seq/fplay$(OBJ_EXT) \ src/seq/sequencer$(OBJ_EXT) \ src/audio/resid/filter$(OBJ_EXT) CXX_SRCS = src/audio/resid/residctrl.cpp \ src/resid/envelope.cpp \ src/resid/extfilt.cpp \ src/resid/filter.cpp \ src/resid/w6_ps_.cpp \ src/resid/w6_pst.cpp \ src/resid/w6_p_t.cpp \ src/resid/w6__st.cpp \ src/resid/w8_ps_.cpp \ src/resid/w8_pst.cpp \ src/resid/w8_p_t.cpp \ src/resid/w8__st.cpp \ src/resid/pot.cpp \ src/resid/sid.cpp \ src/resid/voice.cpp \ src/resid/wave.cpp \ src/resid-fp/envelopefp.cpp \ src/resid-fp/extfiltfp.cpp \ src/resid-fp/filterfp.cpp \ src/resid-fp/potfp.cpp \ src/resid-fp/sidfp.cpp \ src/resid-fp/versionfp.cpp \ src/resid-fp/voicefp.cpp \ src/resid-fp/wavefp.cpp CXX_OBJS = $(CXX_SRCS:.cpp=$(OBJ_EXT)) C_SRCS = \ src/asm/acme.c \ src/asm/alu.c \ src/asm/basics.c \ src/asm/cpu.c \ src/asm/dynabuf.c \ src/asm/encoding.c \ src/asm/flow.c \ src/asm/global.c \ src/asm/input.c src/asm/label.c \ src/asm/macro.c \ src/asm/mnemo.c \ src/asm/output.c \ src/asm/platform.c \ src/asm/section.c \ src/asm/tree.c C_OBJS = $(C_SRCS:.c=$(OBJ_EXT)) UTILOBJS = src/ct2util$(OBJ_EXT) \ src/ct/base$(OBJ_EXT) \ src/com/cpu$(OBJ_EXT) \ src/com/util$(OBJ_EXT) \ src/ct/purge$(OBJ_EXT) \ src/ct/dump$(OBJ_EXT) \ src/ct/build$(OBJ_EXT) \ $(C_OBJS) C64OBJS = src/c64/player.bin CTOBJS = DIST_FILES = \ ./ChangeLog \ ./LICENSE.md \ ./README.md \ ./ccutter$(EXE) \ ./ct2util$(EXE) \ ./tunes/* CheeseCutter-master/Makefile.win32000066400000000000000000000035701357241101300173350ustar00rootroot00000000000000# dmd + clang + clang++ for windows builds LIBS= COMFLAGS= DLINK=$(COMFLAGS) -m32mscoff VERSION=$(shell cat Version) DFLAGS=$(COMFLAGS) -I./src -J./src/c64 -J./src/font -O -m32mscoff CFLAGS=$(COMFLAGS) -O1 CXXFLAGS=-I./src -O3 COMPILE.d = $(DC) $(DFLAGS) -c -of$@ OUTPUT_OPTION= DC=dmd CC=clang CXX=clang++ EXE= TARGET=ccutter OBJ_EXT=.obj include Makefile.objects.mk $(TARGET): $(C64OBJS) $(OBJS) $(CXX_OBJS) $(DC) $(DLINK) -of$(TARGET) $(OBJS) $(CXX_OBJS) $(LIBS) .cpp.obj : $(CXX_SRCS) $(CXX) $(CXXFLAGS) -c $< -o $@ .c.obj : $(C_SRCS) $(CC) -c $< -o $@ ct: $(C64OBJS) $(CTOBJS) ct2util: $(C64OBJS) $(UTILOBJS) $(DC) $(DLINK) -of$@ $(UTILOBJS) $(LIBS) c64: $(C64OBJS) all: c64 $(OBJS) $(CXX_OBJS) $(UTILOBJS) ct2util ct $(TARGET) # release version with additional optimizations # release: DFLAGS += -release -boundscheck=off release: all strip ccutter$(EXE) strip ct2util$(EXE) # development release pulled from git master devrelease: DFLAGS += -version=DEV devrelease: all tar --transform 's,^\.,cheesecutter-devbuild,' -cvf cheesecutter-devbuild-linux-x86.tar.gz $(DIST_FILES) # tarred release dist: release tar --transform 's,^\.,cheesecutter-$(VERSION),' -cvf cheesecutter-$(VERSION)-linux-x86.tar.gz $(DIST_FILES) clean: rm -f *.o *.obj *~ resid/*.o resid-fp/*.o ccutter ct2util \ $(C64OBJS) $(OBJS) $(CTOBJS) $(CXX_OBJS) $(UTILOBJS) $(C_OBJS) dclean: clean rm -f cheesecutter-$(VERSION)-linux-x86.tar.gz # tarred source from master tar: git archive master --prefix=cheesecutter-$(VERSION)/ | bzip2 > cheesecutter-$(VERSION)-src.tar.bz2 # -------------------------------------------------------------------------------- src/c64/player.bin: src/c64/player_v4.acme acme -f cbm --outfile $@ $< src/ct/base.obj: src/c64/player.bin src/ui/ui.obj: src/ui/help.obj %.obj: %.d $(COMPILE.d) $(OUTPUT_OPTION) $< %.obj: %.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(OUTPUT_OPTION) $< CheeseCutter-master/NEWS000066400000000000000000000000001357241101300154140ustar00rootroot00000000000000CheeseCutter-master/README.md000066400000000000000000000010361357241101300162060ustar00rootroot00000000000000CheeseCutter 2 http://theyamo.kapsi.fi/ccutter Programmed by abaddon 2009-2017. Mac OSX and D2 port by Ruk 2013. reSID engine by Dag Lem & A. Lankila. Parts of reSID interface (sid.cpp) by Cadaver / CovertBitops. Includes Acme Assembler 0.91 by Marco Baye libSDL by the SDL team. derelict, http://www.dsource.org/projects/derelict Special thanks to Vent/Triad, Blackspawn, Mr Ammo, Scarzix/Offence, SuperNoise, Wisdom/Crescent and the forgotten ones... Licensed under GNU General Public License (see the file COPYING for details). CheeseCutter-master/Version000066400000000000000000000000041357241101300162710ustar00rootroot000000000000002.9 CheeseCutter-master/arch/000077500000000000000000000000001357241101300156445ustar00rootroot00000000000000CheeseCutter-master/arch/MacOS/000077500000000000000000000000001357241101300166065ustar00rootroot00000000000000CheeseCutter-master/arch/MacOS/Contents/000077500000000000000000000000001357241101300204035ustar00rootroot00000000000000CheeseCutter-master/arch/MacOS/Contents/Info.plist000066400000000000000000000025241357241101300223560ustar00rootroot00000000000000 CFBundleDevelopmentRegion English CFBundleDocumentTypes CFBundleTypeExtensions ct CFBundleTypeIconFile ct.icns CFBundleTypeName ChesseCutter song file CFBundleTypeOSTypes SONG CFBundleTypeRole Editor LSTypeIsPackage NSPersistentStoreTypeKey Binary CFBundleExecutable ccutter CFBundleGetInfoString Version 2.5.0 CFBundleIconFile ct.icns CFBundleIdentifier fi.kapsi.theyamo.ct CFBundleInfoDictionaryVersion 6.0 CFBundleName CheeseCutter CFBundlePackageType APPL CFBundleSignature CT CFBundleVersion 2.5.0 NSHighResolutionCapable CheeseCutter-master/arch/MacOS/Contents/Resources/000077500000000000000000000000001357241101300223555ustar00rootroot00000000000000CheeseCutter-master/arch/MacOS/Contents/Resources/ct.icns000066400000000000000000001235531357241101300236520ustar00rootroot00000000000000icnskic08c jP ftypjp2 jp2 Ojp2hihdrcolr"cdefjp2cOQ2d#Creator: JasPer Version 1.900.1R \@@HHPHHPHHPHHPHHP]@@HHPHHPHHPHHPHHP]@@HHPHHPHHPHHPHHP]@@HHPHHPHHPHHPHHP "߂G힒ǐOp J+M#ME%cWown~kn [*_t9߂G=XsW̉uk=Q" kb6-szhIf`u[ɹghpW߂ GQS>QEE<€HaK{H#{BPg=P4WcBIyKZ1܌Q&ϴ\Yi> D-qv=/9kL2jX۞Q g(B3ԳjR 4edmKo ԘՂϥE\ĩ)G6aw#ҕO>&3WŜ^ YV6,(MB3Yi~D-qB{eBe2O{#bVVJҵR r1 4z**$iYں<6hhMf# )LqKɬ"̪m"VTK9q8n«T<%%a[]? D*1U`, JdVldf1W=/KKhj`&oe#$<𞩘3 R?)LqKK71uxKSh :Szۯ>? o"Mci<ٯl EY⣊dKK2]P t{~XҠ&82I6B[+p߆y |icČ8`$MeHm=]ٿj seD3ZοQҽ̭m ke- T[hf[2,juEH5Hk]'m~M-z߱m?' S> I~it#D-IѧKSXqSW2Bs$pŇd"`R]PN 1c4,Nvrb[Y*-gz'roS2/L\eډi 0pb>.? o"McjᳶK{wNGGEReYe4+-8BL;u&䒝(5,!09ƮH8Hk3\3oVK!Vxw}0OIW.j%/ ?Fk:#a[$X?KSyZuy_,4|ﶮT2 |n *w0ZӒhM'*XN<9Ib h RJG,</~7-A V9' S>!D;` uS#pƪ;*)opwΐ?E6t! J֫It,etG'|xq7C~6oViKN{sEF91IetI0C~l~Xoٺd6gzDP^妁PpVV&3Rpi ׸tV"OKS/8 ?ᣆ8~5ǯu?&ڎC4}j)Մu?QZ2]%ܞSO~-Z2[\6_MYcȩv~NU7&Y'I&ć>/%f>*%]J)}-%YM S!^\_3L-{&V.xÏA0ۇ )PJ~*l65N”1ׂ1dR٩hPok7L0>5Kv)U"eZ0L˿=|*3W!?)叺qHBf}yVpJJyYQl F9qR҂;0)d\j -ul/I~Gf&Wok;->g4U_Y/>~뜲#-ýUBxd9ËgB]atRӝÂo6 tݪ9`5M*vx~߳(J8JfqrHEiJƅnu2{asд>WqWc~؈XR>8u,GnHdOs}t@]U:(5&z*YPMم&KL)X(;v,:^* ?`#ĭ##Êׅ}N0[P^1ޡl{ VgЁ8Rd s I&ԩb&p-Y.TXw<2:c.э*̛ʀ1=ˊd% 4V-T3yn[vmZBib}4~t%fY-¹hXN.%P"@x asoMיR`ur+cSak֧PE"ab=S`7d:èP J(f*T bZ+D7, ({w VvV;#Yru_\NhgM3x)/F20s?T$BɊA&,% ;hH YaBi=hE5(Tb _YǨ%9˭JK+Q) S@V~Zu 45:rE3FR"5|@WG2G 4"^&a]<_҇[e")EQ<|X5qdeѦAF702R&-mH]AqD)oѲ^u}6ׯykk2xvGz[6i(O0ݴ7 hUlE#Mr=: )&5mcz;JA19Yx62M2ek=Pwz޿v9!i8n[vX-5 ?MS#ɸ(mPvuzqM:6J37c߃^Qq5so`nr[gᲑl F9JWecgL2QRSԀy6cvN!3|Fp!Uz'w@LX9+56T&G +KU!sW WO^ ^Dbn$423ԋ-8]*J4S @F=Y"jms oKt"A7*2eE:ʠ*\.U45&;T\cuSIpReM9$WWFj[tÜib[>d_}C;}ڄH mܨf|eb[<m.y]?[ iz2kQLSI;(rˊIg5#Ё8Rd s \,y>q'N PPcwDucwfuنXB35fEL^=6P9 dTPV} pufvkàl ĮlA0'SE\w EObIieL`9mf(Db!"ÏC[ZWbtjrqyU {vԋm˲9_v~o|^@Hݥ> \8nuWGi:!FoدS1e19mRLvJ,ISv }c@ aؕ:ct6UA4 F'1m h]82 ]@ۨCzT QgB>Jv"%S}T%19'40DY*ї<8p E"2˭JK+Q) S?4D @_zXSr+xh+l&l*-!ˆ1 ~RղUf/|80.Km$Gδ>Z]D92gbAFR!/_>ВRRu̠%dq_( ґ*6 )2^n^yP/e=h^]J=_]x҉2Jh?'e{HTc_;uQCʯ%^謞M?>2WuXyӁ/-۪ iхC9U6&LDkXؼSlAN B9B gat*;YGA4JZFk@^qh8([R@wU1Tc"W{~4sB!سY9B:sǐoiS#z~> ]wD (5 g)rt A`Rdd(~|U,#z.P%0=mf ve@b2Lb?9%s˭JK+Q)o@3mgvuzf_ C u-sbBD" VE@7Scw82W࿋iwvNkWp2Odp47\Ѕq|b_gnl";〈 '1ݏ7B 骕!웎GYK_d9F8z')5AbD2=ż< s[{6="(AeD-`yIZU,IP+/TUrPt^7of$mq ?t՗>q%0Vesgq8IxŒ6Ve/3TLZF/RY6} &q?% ge-N u3YH6۞6>յ .d6,e]w놢wwdMltv~ߜ #e3Ml:vlg|$[,!sp2#js=AS,_d܈,R1M2`O^蔘7m@1S.Cs%LxEQ H|GR< cꜟঈ߃emI%$ NG/Ktw%>l/8,5j}֏y^Ȓx=>_U9 ׾锳8#@=3vf'5K_`#^whD$gܕq5RJܠ\ޠ,ʧ5G5͙bmƞ"4݇:x3 +{'vq~ ).ǼZb.+Jcdw/-Dӑ ҕFAb2U\&s%Ԗ?{ڀ(|PgϤ_/@pqe+|6(N3.G 'F^T PzD*/'S Gs{Zq js~]g/d i}淈~50@fkԓvet{˪΅L`ˤ?rARL`5Z2lVWZT05Flf2 Q lt6e4~L&Uꓶ h|Y\.xCbN`sČ6_aCRϒ0P2 <96)bxUV>G-#IRFiшGc/ool"BK'}vS@nOʸAʳRϱdOƃkOrpBnF^5UUR\+ [@)hc~9m83S#y@&R[/uYh|%F7<H_ s}W 8ej`DxB&7*g4Pus@T'5Wp$ l(w TȖwZ<;椮 kwY_өieܝmjW78pt\œىY?jTS<&&˓7+] yEIi۔yv.H*xFrm#My(Dd$6x(9d6 K̓L$%QjٚHY@ي ;T\H83ɏYn2~g]Xh?S(`wuX14?D.Tnvtw)-el64L2"ggk\~ٿbO>,zL6'PI]_$juMw*7=x= ҽHJ\帻!,|:E~Aj fۓE@VX,2|IP\[EuKK׏f) a"hWYmYB_p=˺+xMoZs+Ch{5,o#%FEvYީ5Rִ"2%ύТ~zMkKRD\Xʞ?yCckХ9tC Dc4k^䪍h=ŕ nFzo>ځ2 ͇nuo#wx)}&#h !@3z?6F"9:Qgz`'F ^K ~4)\w"R-Ѿe-FxѨ*gP2E?.ߍJ[ZHŒ·C+@w_(gSY{& ݚI g]e! eQ ZQGTu9&hvP xku֝k 4ZhlT]z)TF"w.XuC vj0A+-yk]y.dbz35"II=lW Ihy Ci 8X+kIvkdFE)̾ceQWr49-f&3 UΥe|#Kbsq&8`y>/0_$" ?[~CT+NL]]1=l_FV -} F'N8yl6 @6le:`Lǚ+jO8"ޅP냷JxO םcjOh-RBKmi5 fi(?PPnN˰hQeٰ9_ĢMG2}vR%:,$K@jܿ"$I}enå+:졤j&hAiT^GlF@͘H哕?m*ʛd^ύs!Jqi5J d %!ԁ3h3!cBr۲N3t$Ǒۥ:#n|8OA$qEiu[aIPD*g)w>nO/"~CZ+H @= MGߒUG3:[%8O?zQbTC47,.O~}rxG.$퀢E|4i'e^7Z`ϸh(gthMO(kӞ|=s:mn؞"OܑJe$\ ?t՗>q%0Vesgq8IxȦ Pm;B,ձ]d ^::T#8s9P _QLNL,DŽt?x̎YjYAAn$e|!h.i ,"+>y BOn4Co %b o҆$\E8gd=,zg|%k$t4)nd(9EV jkQDY:zvNRI\ CLټts(5B}yz!t:[9A.;Vq[mQ)fko atbn|J"9*P24y *CsV.?ME3VqiŦ8ǂ(2S2 HC?  ܩvV0|c??1.Oҵ8 3)ֿpEGL,~N`A.gmUIye eAiȰG)λ~@/\/y:5|aEP x )Ym*:s@*bςR2Ƕeڛ1]zQ3:?2~?~Բ:PB '~4`g[fW#׼[_{ta_zk;2BIWlk0 [۾&h3'j~QReTP}oưOeIR!αo\u[P"!vwfN>k};Tf$%HQHd?O+`iUـF3(3NkcC`Jy AQ&LnPzaIS+ec'IX˥[;uG<x3F}=w/AC1SZ :٣{شA nZOV#pX@vca=(#o V/^qw n@]:EGU(5L0i'dU?!_!;ĩmJ>fͼ)IٱZFR.sMX ,yKR^T. z>w߾qlAÚD) 6i4l_<>I+=MY܂/c8ƛI{ctoSuHoG݅A)x.[Jb=w3S;c\ur},B">Ĝ[pMFIW-̳ex{gBU\q&P>G?.(2cHQ`rʚ_\ &.vI#P=U~NHȡ3#6 ;MBӥ"wK9Š'}G~8Tn,i`ZbL?뉹 a1'o8CT냎by@_pK%))_ Q?KC{xօj9{hZqͅ!_4bW쵢eu%Njy>zpEZ M x_̋gW32ɉĈ_J_~*Eg'Ld!k{jD'^2h!e\++ 5@ɘjt}aX7W[Sם`P lGcx\%9emT6744մz a=ng&p#6/i\3zjg2 }2ۯ-΃ϯ7fIV @[JHzP]Ch9p˖[:8g<%CзPr<0'yLO['ؖ3=Mޱ:v_4\ï:)Z5Ś̠dLN _2 +b27[ȉ~- *7dqQ,/ffJj9m25?wwYuZK]rJߏFq k7ӄDr0c=yD|@NH(שׁinTR~?<OVXDSK,.0i_ؿ^Y0:ObfX`2ɰ;OR+`(m<( Y>ZE,4[ߊ>I 6jM 62zf,-Ԡs 1 7օ=N4Ξm(Fin\Z<[$@ɎxިfLϸݴr̓WJI OmoKdF{e )Opc^c⒉UwjQ):^BObN΀}kel fnUIC=!m* 1_,U6v񕃥*M v0PZ5,Y.I'UVooԜ9v/J"ւ:M. b8{fsѻH -^nRaBH RIAB<nN5G R >5=?AA](#˻і / 3Y3<&Q ߿AWC)9~ Z :۹DW{˕ګf0tyhf .(YX i#9CJK80|־u1_^$kЛR/7N,&%*0+@*'Z~@A+' Xl {@"5cIANu = pUlJg IεchԌkB]1(MEP%"1^(#z`iq y %ηwiǍ?NSqb x7:O퍷 Bq lQ߬E!SV'%+fI-624k vYy#l%ߕR SuZ&UMy5N!U ȿ"n)@ @î%61fJ`O-qr%Wnof))Gd]k@e1<եKv]ɳrl4h-ͦЈ1?jg<뉍7ީ)8RԆPE J9$z7b%)‵΄<7\ǚ,Խ N9ˑWPSlR6HICLNZO-Fw4Jy黆\-X*aeN\4RIܝpxF*]0$ٽ~;oLm$9r( "#0_듢Xqz9wF$FRZelnxp]Oi5xgݯ7֞Z^po;O ;/=Pn/p3?J$ݬv2''&Ϸ>[+zsΤiuĒ'F@=l2pS P!\7g\=$P0Q]#SSnSI-.BCG?g{qxǚEiDcs/ֲpy.Vsbқga&k0Qyu3}e%02BiުpCΑZXSl6VDEzbxHdtnb^ŨW~]ǓN]$P~I\!S[dqHzD9-YooPx^N%iJ9ОK_yyԌ>R4"H qH)"@m^R IzI%Pt&}Q.>\9#o [,=(4`W)&r]`pd)T񣖁YU!(~P,ss_K"ߦSp%"! Nin=ڄpVdxpqoŁ!$.qU,5A֪H-#+nBD ?]r07>:Y)` )ǵ|K J6p|H!?;M*Y сJ<, $lFe.zk9 _w FN"aWiu_P=z:IlVۤL:^\06M_Z^sONk.o?\"IT!ˍ S=fa-G9'>y#Gs>֜<̥{k3TAvd#bDFJ/}l%Yjt|O0Auhevne"aMbB&G@yBr Sa4arAOVǶ7R1h%QjOH;,-ר(:>kD\`>H:Q`Qƹ-iCb?Y3~g+vdrq˪WE'~h'"=' 9Qo,S6$ `̜viO2`_R8#5+6&Ae!E5,G-Ȅ'&d_; T_U3LtwH6e"f@¶ʒ- P'>Ct0R$7/'ěRBd=t~%0Ё7A6ՃogP<9JvޔSiN9( ,QL=b&粌sȴiG;~56ok^G`;Ȅ-v3sˆ\o[k(<6Ě23Ě vr55BqD2ke+XGj*b yhv\pA^2שv7#,x<4@&TAr%8HB`qGcͨ<^\^CJ WA{NlzxKX0_ic>]2BMsxVj*0|sz=be-z9 ̀li͊iGpL L]KV58-QfI')dÆ\_,v!i(̒x`4$XHO  YE7Ynwen&@1 @|hG-K? )Q_t$mK*`ҙi {2gVf~᣻48 w(p_%CZPBE.1TW6S;/Y3 gƴ&s 6quݱ z\+̫vu0Qv%0]] [B|#;r~\Hu.S'' qW6eox&5>D"IBUq=&CaU @Һ}_2WK[8lîDž# kɭP2X1bZͨ}c:Xl绱Mdd,Vr}[A!TCyArK(]WMQ]bu4k ?ҫ^{R8䏿4y'͸D(~+!vN;yXN{2ZlIwo 7c^ǥӾ!9Uc vI,}VO57)MP(EC]3xqId 7LĖ ږý~mtI(l:msB N5TK@b" ;Ն+E 'u8& !KЃ>쯑itk+ٮuM˭"y ֦";09ы2Vv?4{zN'S=s&*[gLF8WqP [p .hť\ۍiy=mH!8m4@Y Q+JU-==`a[z.;|,S5 _iTa?{pVNydDX̛[62`nى>u7">AFJ3 @k|TXҶLhIΙiG\r\ G]n{wTS+ ՞ϧo7V6EjBM\5¯IٝUZF)o1Y֏id I* Pڤp*Km n}O@~Tw.Ncs!wuWdGf17v:yL^jolK4%V=g臒GrVǰt(}O񔒻|_QL]Af7JIS5Yãg!I!˵ {_Mh3 MXб$-ok%<d攇L3ѩPEZf ^{%-TXI^ E)ѡ "n)"M:e@}nJ s_jo|Ifߘ%RDʩL4ۭXIzy!Lvv?]ȬX_]Hv S9Nw(Sx%zΌ>vJPj2ɨ'h1٥ K7%nQ -Á )"рQ $$8-T a,̏>Ăpoxt CNPEֹ*usQ*:?&q*rF|6pzkZezi#pžmՌ& 3&Pŵ#ҽhoCː9$C4ot\;A2k{WHȀ lmͿkJ:S= z:L$L{ 6F% rDBաc'žAt)M*rLI]M8{INlqw^I ﶴjj,xg b(+Õқ;1QЏU04{eڂ' k<'*$!m57J塧Ծw' h0p xuJc%١r[]'k޳\dٓtUHuY'J$QD-!"*oMJUYVKEĀ(2ҕ([Bʓ{&7KiM7Ϲb 2M6>#H/ٺuEUt'l[y~n3 kaRš#R 2?r끎¼糰!b<5d/ Y'vl2Ѧm eœ9U?EoNPа4cH\.+ʻ"S)Bo^L)͘1u|Jc}׾G$U/NK%ÙdO KS8bBCp}K8JawDZ#70ĮЙpMM;ؐ?,"aqe8#)VFJz!'9AɞQr@T& /aaJOy@GN.< V$SEWQ~۷XNPDc9s3 # -9Eh'(XH!P$^C;-qN6oI}Ac\uq@'Huf6!.^Uݬ-]tuڧC $*2LZ!VZˀzB9J ORK_\䰄rUT3n cR1m`NcePk?եChJ V26ɖ 0r`d{_w|`6wy e?`١PaNJ`gQ䤠yQwSM: k-W& J?SYGu!Xf+R6Ρ#8iakPkqK^dN ( 81 9~[pH=Ց_oHr%kĘk2'aHM0M}BE)wN]MX'!!NRr4ee)}o*Tհ-_,a[dltZˬF]`#zB<%˒poU,lԗqs`0&F`"zhѓ.%3x]1ik K2r^Nf̼ܢ֝;5gȋa{{c5ϷdLKre̙"ۇw ғ"@{rc 8'ݸ$YnlהC,)'o ;OJA pK]`"%Mq3BUC%>]ϏT+?qit8133L"tCd %$l]]0|a7M% ' 5ji<HeXX 7A#§ .V, :baۨ_؟?փozHVFŜ.|m^RrvU.{vo}ҹ=} ▶K=wF|v"NI*JeGOЮu?B]Ć+Z8^]Rocx.HNp>(BGOcdrS=l|RfWGWFldwxz--TDz Tqo舫9syۂαKĤnX:^ʛ%w."8j|0!rSdAOwFּWJ Z{$vQ r|e M1CRp⥺Dtp3XR6^ jDUvtZR$3ˤ"$7]^"|_!>1U]uġ}Cő9~ײeUD7PҢGrh&qg-9Pt6}c bb."T{qR,SS7+IP+?dZ+=? "H(9c8<]F1(AiC:7DzH*J'O+ؾ{[ .`_Y.Tr9,(4~imdگ_)](á1 Ur|܌9X /ǬaB-(HJh"kUcbp]|uR,$,²_ Oi2 xD\ue-}E6iiN b֯jb#TcZqE&(Va-MĞ9Γw7r=NrXyaO~ 5%+sO{!?9C(pꋼ2b/nCnAG%=/,g@0ETtMmWǁL"8p9A/H9'5,/c jm9U)+nju3\S;VI )ily+lxenjP "fvHz3S2&?qijm9Vg(d7*B{OPq;I\L 6r⥮32KQ4ȵ 穝}sZ@zz\3xqpJe ? 4=? FE:fіw6[}z'H9w *_2Kd˞nID}MFamu DS14DZa<}ժ`qu 1\]3~}73Y)I̞<{T9;zI Ě܌9P?{D~=^nxbcc ?UB0i}H%~J3~,YltQ{b|i{,CGU 0P4y c>+TK@^U ew,@H-8 Sc&2dAp]j ` :ũDhG7 Nf 9BER]P `/l,Q!+k_bgJ *܄ʃjϬB Fa5ĩ(Q֝]AI )f_oN܌ s|:sMȲū^8\aIh3Ն`8)q{`|A%\FO)rPlK7{~I{w:¾E:%vfg3zټ;B.B"_!| [ҭ!\Vj֯iJy UԪza4vvۥZA>hL#%S`Q!5 5A'fzc Ϟct!bG~6,NChEg57%I.(V+EBܣ+1PrXAF^^?nx= :Tŀ>Kx\B{dh؆h˰ׂ1$䧹/M\Nx(}ٓ#T Na"HȦXy&@1˥nb/mT9L8s?G)Oc =O+=Ih \<쨮ؐt[_3hZ՜bA8Q51~lFrF\w8Y2]njD&+&"'!5n"MH>Z+܋k 0+.=&*F-c47eZ:6}S v)^=ǟuc1$߲ R#l x՚ra OXsg^JR6ċuw׌it/9͊S5apo~ fmRY,ivzƥToW['ZXޭJ qos ̌.!aP'UD~ó 7Oψؗb%lF<( \WrDV.b+y``\dAP$=X+G&P PIwǐ4`; 4KyMZB9m,M|~cieA/;A`Wv)OWc|:{ _vl5if\tz[x,W0;yA4aM*1qJ ;`Q'iRXH 9g K5"=F{ ރsY|¿oTvʼno?zO|Ѡ b3'eBcm sFf𜉸tƈ!Dl'1m zVaǁ ,ƳTNevI_jkEW{݀{,*廿o %o g.MUfl[#@I0Ȓ?gɞ39]rr:5q~ΰmC PA2 := aV=o "^t߿rÅؗ&>Sf&KPG(!<Mef9ԡFuU)&܁-;m^?gH;^`K*oag{(eu'KOw'%ž^vϢ>pd&MPDoꈩfMՎ[`g^$u,p0J ѭChB\&sȒxZ%Dw}YBo0Y "hҏBp:$Gv`]㾋m+`5yҘpÁb(_s_MccopbA֕| ̦&)[] PD0![9d)ay}-Yw<݄*jả`z(j9Wx{Y.4fISk4u*s7ռ:8UJvhM R2w1$zkgk+QM֤O*%:O;Bp7-ǩH^6j1,^2"㏋ t&%1[%K' d؄6g.Q|93Ψ HS9yրΎ}a$rHP_PɈ(\GX tY3)ymnS|fhvSdQj}]aX&mWKVV`vv`)}VA:%cy4MD']LO[뫱Lu)1w}`K1rOzmܼo"e~pvzA/s _ֽzdžPF iTԮO+MWضDnܘjiZf؇bj)<0Ϯܳi;H1DS}p:ȎqmG3}D=' @ 3280dgznl b4\yʕkh9̀Ωl f䜼ɘ<>`VimG w\tO@0uc`[&ęlA`FܱWw)D{sDo;Dief{,~XPz_ `G,wL✍ \ Аʁ&c6洖}N=RcǗɳ &g'v3g[~o#}TuV~h_f4W<zy?_"3'<daX qJG)bzmMĶ".Q2c~ղjQa?{L%XtS i]$ͩ iTa?{pVNkZK(~05q6P0uUf^OBzKx6T! ϡ]4?s,#aR\]x*86A;mtbY^8DSTِhҰY|- S?%?/͖<36)rcwJ#v_ <}ϧ2mOp7~ ln՟d: `EV.b/DJy/x"~ͧIݣ ì6q[tIHv9i}ލY0mfGg.">|/ *4Xl*#Οȓz tKV^W i%* W`19 IWH``@Pd^l GR|ؤ%Jveb |h_ G@tk3_\j1:-tcz@8QȧpzJLn0Ĉ.Ije;?(iIꍱ >MHGyYP7$aʫ;_ :}+χ-Sop,~oZ|&o+Y뢇&z:/ ;*UJȬ%&['.૳.ÛawL% Kr^Z%{לq)S* 2߄BouE|%~~O"l|;(sEN>OWHȘdHJ f^hj1Ȍo'43OeM{'j4| ڝ.h9_^~$s`,xZNH,,pmb{0bMCɅIMdP?C5u5 X]Owxkn>kX2=**]=5%^wH6 7ZPtxŀb2X%m"P} .-"ùϦXw0Lg >^7W[lyx3ek=Ip]F5.=OpK5)8?ԭ}]po$|dWJ۹J]I#42x#BGs +F9CaM#݂;O]\ĩWL Bb9[ASΣOu1jD A2,w]UQ`u=tO4BUkR`6 :tśWV {ϵFWW-u jb }9DJZ֜="5Sk)l&IgG0=_9NHHN${.{, oºMh}F8γrnT\|46Mwy?/2X2!xխ . P7ږlM l>d/OFIgɉ&.|q8c_x{rЮu?B]Ć+Z8^]Rh8s2|6+G+Hnl9N7 ѱqs]|;m:#j`xdW>dg&E0c%ƒZ#UQnX:m}yVˤk !z4U ׹V|{#-+ "™V]GZ#`9=z'Vwc)p-GaLµ?2sac`NPPKi')wN\BWζt~I;Mȃ Z5`VMAXέ ~SACV[Ht,.T#/~@%)Z0Xyeuh:7 ( ?ѕםT1eÝl!•ԩ6HB5=LJ˲ұ7|pP\ـW8żELs$STK3\&P»l^?~U )t@EqI)& %tRDzr򅼱X_,#1_,~uLH^ 1QPqu0W!CBk\3i7`ݤ4?ǕxK.j#N&4_WXHfD TE ,%uK?I~ 6ݠ 6 0ĕUōI\6.{CS>z 'aRQ0pgȤ_㻥t~۱Z'%!xP1*jR@Pbܼ9qKt 2[?mB Xev~cY?+Gi| 2TrW۾JŐI\)G=JV*aRceT.H+֭ ,Ċ<5k B&ħQTA'jkPtj CdΣ H\ht|or:_?j^\8^Zjsߢܼ2&d> Z(ѶV~4'S*]!&?Xɥ|\]2 ̫xgJΜREHx9xjw\~`(њzL&FB&[&f܈Ǒ F<Q|[UϤU܀A,0fdyQ؛Yok5#L =c3S>BPlji mƽa\1"3'Oq0W2;E>e K5沔QPLF:Y RcWW?VsEq1K=!.2L&nո $.~*jNs"b( uױ$E0fREe,&[l(_ nh/S{! z@Amds- *?I"EuϚ\.Ч T~x/ul1=/יPv6][[?.NzOfg%y۫̎5d~Jn/$g4\^w9 dGfn0pod|g 3Ն(eu;`&V+*0k;Ta 'wx0Y$g %m -LnD~@.UϐܬmDe"f 3wgD(" : є=o&;{~ ؾE6(;ȏ`{o~ Y`9A tJ(n:nDYHsej|X7'&׾$2I g/6c%B|ڲ- IJcCsd~_C*5YGRN\S8 :K- Pw{J(E`!F#`yd_n ֐'Nٸ4\ήVQ R8dL7x=rXW.2 =GIA$DĆ@0q;Zbgxt2t8v džF++efBZYSN/hVGz}S0@DF]|;@h@CFR  GOE^RGbfAAD'*G yrxn<{l\Yf:{<=<#y{֗Hz"7>3VP ` 92d1F0M˶U^}VHdͅB=]>jv-=oLRKTTs.Ƹ>lTWs;%э\ 'H):gvQ6퀎WL_i068z$X_s]0]] [B|#;rѻ$W2V2 BD c}G9OBʣOUjBmgx У3?=ܗ2 @Q D爈 (uȴ_>=^ş.}|v {Z9/J"!"u=x47(7*i幮`\eC1K4Ӻ$}$ei ԫw.w6q2#h UjI]DUٸz#^F%Bl>V`rD]~Tʕ#L`_a_9103a%xٞ\;̵(B,>9,9PJ0#| cKv>Ntn4>#.5&`fkC Ox?1kԱn.g <;TFʕ|`h]ޱLxbրåˡdF틴(ǟ>N5[ @S§\[oF*F OWedn$%ٷI^$ū(?`CG) D"2!)W* 6@?pqZVyZlf}D ҂cXӸQhC7 {"q $*XH??A(hAkxm)pR~b䠂EϾ<]cb5A/:l ,tpF# #M'gZ!L%I $ =Kfβ4R}2C,y9=GbwN.sd/&I-t m tE(UЂz1`a xap!scgν#2GwՋ[UXeힿW~T9"]VBUhSk; Q԰1 9h`nC t-vH+G~y)!o? owi%'ɺq'qX'T ٺgnf-Q3@cV{lVGRk4q7BsG*ܘ1?^7MReu/OVGYA&(&1xx;R-Lx ).C;oAVRbS6XZ^ >IjIOnn|HQx/|N,_}O]~W&*WﯖkbNpe1hRWtLw6[-zMMËP[(.}UP5Jb/⹢+$JTW׵[f~ P^nR=K̳r!YJ($:-\ :Ņ.$CR y9{e*_w=z֝V,lɻ0ieF5+V&_U:FdFn!uF52GC l͓Pk)̃( ڸId(F à K\)#aB 3t㭓ۏ("9'[9TJx莽^y2eCfIC/W-:TjWOic ]k!tˏ;[ (]SB^&I両$n}]!@(sG:eNj\SeQ -X% 6:A].puu+xa iO 4ٰ.!86*PKy3#8j_a".j?ˆ/8zęߣ!)E+WN|:Q.‹}7[-h4 wZh *-_V0#׼ݫG 6ݴ/k ѧʀ>K)qz`j59#:vPl L6i"qj/.vy$Ix/Ypf2Q$f@Au(o#L 9uxxGְGш̸w:=WsxptaO_l7`3gd3tS ;n4f#cb&O΀{W.cI8` @&֍ٲQ+7CRy2@-Ƥ0Yt9Imb!o ?R`+ƆR']X.ą ?(s/LElƮ3߯mwf{gU x͡۹H&[TO-(pzè5MW83w=m"V&ۖd"&7Sya+ (Rcrc-`ĔbߏSI(EY[jkRu/>Z񉪏yTNV2DgX-AGyPd6KR˜S @~c\J. w2pC_;7] `'wKJj5Ÿ9<0I-e[JhzeUv*3†?3yśQw.D&P9wF[=d 3cH/v'~U'ВX#FFas_»KA-u~H tQ 8Wٝ?a';o)-ǚާpo7u}ҠvWyY?V|+ЮuHV_s닞5?̒JTc/Ct KS= q3B*uhmGaY>ߛC5Ւ>)aBB~kĥ/$/4tT{FnS5{A43"I!@uӷ TcyL~EQ>K'@4s#1iցn,-_Ή\`}Ǐ!ąO②:aTKБ_.VG!毼]{ =<㐭SeA/GS ' ǎUMc+,NVKu.BO&z`k/\Ndšv3kF x52Lr(mP^Je kkӣڌͤQ:/>Oo`P;y@q9~ ә_1{7KwF.v>>[[vV62 ,}# 5,}c\go|qI`;:.?+؃Ird5O~ m` l[6P:@qjǗ0X 1;Z'-8Po'3JL3Ukq@"vQ8^Ar?F2xuw4Xz{.x4x?.jO9杍rl><#u}.=oj5,;>q8e]|?Uu] -CH^*uF2ҏMj.&y.6ݛH,CR)p|j>KH0)g?Usi Tվ`:`Cu{3YڧzJ4YaΔ `=6>&&[鯾qF!DrXXQ!96F;aضX/tNjEຝIZ b!l-WmEQێ:[͙+HGRY`9C(pӑ>$vpB2(S <cnyHs=>"+FSQ%-Bҁ] |uYğu[uUc`b $7u۽L8z.>b!OiTo'`.ƽ6Dv+n!+QfR !傘lfHXi9M*&^8ͩ0qaD#Xu 2 o(P dT 8tiT =Y{-΋{w|BW63zkCw1\ D.koe^ Y;>#w}s#V]ե zc>휅ܦW!+k_bgE6m)}{f5ܧ Sa(,ac" #;t\wxMP)\߄JV7x4€5((ys$Vcy6g Wb@uoWNV`P>Ǎ>Ahڈr\S2:'&!͘H`4'8rk(:&GlsK4$l ȷ5rb>+FEoYGЬ VD`~1J j%mE::nen*7Zv=rd/,zw5gs~Xlȁm5%:e6P%oXN.x-9,24 wue;t*g@^w2]ɴ_@i4SCs .)bX'gϛ^*%n[.Iq+K{Z'E ҊZ2#0jR)adց7Ԃ _}?S;) d7|zDX[4#B]'tKo *$5@b9rkvPHi~X$2mɰʗEv 8&XDoRԖ2r $+QeaJ6< Wޡo;j|`u*E& H )a X FkD\/U PC#\sDT4!#;vζSf{0wk@9r)La@k`D/*Av6ԯWS$ ` Gfވ=By?P!D}Kb]sGaQf21:+$k:AqEd hW%:ŢT35P5|ANHYLb㎹FJ2.|:qwy$2E4lѧrVC,Al8I]@fCheeseCutter-master/arch/background.png000066400000000000000000000264461357241101300205050ustar00rootroot00000000000000PNG  IHDR#iCCPICC ProfileX Yy~ѾnPnKħ f@!.āMq7<Гɔ@s.0c ! " ydlL%}%'_L[&7k-p$88:2 zaK` nqd9!>oa^I5MoZ8B yŘ;1NBZM~h'g-,FAo΅RKrtcol1"+eX? #?!fd D[6+TM=7&&}?zkQ!fR7yѼCЊA?tȰcюM;BiMzxӶ&B` Ȁ3@X#`H{@P`?`oϱhpo> KֿCHTg6 7F>(c40zߺ±re>J\L{d C PVQ\3Lp8s)N }}݅nE?B7 ݈AĿ3 R6ih` bE?7o //)1y-o0кC31 0۠ 0zs5r `ڱ[k :©qTKhOd<%80*hwKYA_yYAeE%n`"Oc}?4 @X4i%9C0/, ]p~ $E0@8x/HI dS 8@ W A+ݠ<`LY0UA!!\" ʈ V=x#H$")HC.!u6Ҋ}9} D"QOt'R'v+<Azόbso2>eceg2b"3`*`4̴LbVbegdb~<͂gg1acIe)aigyGBDHF$_R AdűJZf^eegcaVvm.n~ ?1eNN}NtZ+\\&\\Y\ \ni{/pwphyɋ[ûgɗ7ίŸF$+,#"QM@0L0OP%^Ua a'dZqHHHȼhhK1Z1 b]b.Għ%8%,$$%$zQŒϤpRRRQҪAOeP2j22eeŲrrrrro?+*+d)t)RTU S,UUbQڡԤMYZW@ QTJm2]6JRV=ڦFQQQUV/T`հx4<٬SKMuC닶vvvK!\ҙֽ;'G+{/_?e ebpೡ!Ბ~hc3t^'s&LMMMT7ǚ[g[YZTZP߱KzKso(VM(֧ll"lliq; (;;q;v`dh@rrrhxqI)Ʃ͙ùy%eUuk[[;ٽ}iɮ3&=T=<<%<<7Ż{lK.&/X  <84l|.kyHQrmhyFKXm8MwЈ{鏔LҊ:5OE#ўэTVHy[cޛqqq=L.ז(fK>L=8yPE!)4IbrvbKJS*_wW1Q҆h):9|ʱcg(ffef>>t<Ɖ'N^8;qj(K/"9;!i999g<ݖ[tp6DU^chsA+\>w~"G.]//-Ė|(u.q,l<|¾AzeeojTuL+}W6\e͸\x m75nԉ"JG&o֤tf悻lwO#Kђвt?\k`6vgv>xiePa#Gk4Uk׵jwyv&S??N LUN+O7Ϙ}qr6rvu.ϒwJ-sk|qbےҫWpkeeju~-o]j寱H2 a [9 @`6.y f?T`~@p` .\^?Hs֛ O{EȨ´9:iݍ,O$=~F@{\"f 5Hr闲x99y8$*RwjHkb4_i㤫ǣҟ360e\nRhmnlo2*og}qS En==vwzu{?% +,bv4JDߞ(F5.&3`{ 3tzJIJLu?MQcG2J39w>+3;Snٱ|sg ._T[<]*|٣R~TeqUcR7Rwn6]vyݯVZ6ZmvB'skaߣǔn'O&z  =yP0yDoF]O{`wbEbM(:rLǺs>\boK?D؀\q;1F"(T jVm03nZa'qj4i=B9Y$ʬbOakbd2sw_LWPwQn1m]ђǤeJd/ȝOVSWڦLRR #LIzFzCG\nQ}O CV/F0RM},Fw4Y[YيvXBq%9RdM{k{gwo4`,p~\dHrXaDKQ1qWS&a<לks&cħK_~XU-c`i0!H> A۠0* [hL^&y[59xfŲ9x8ŹTMxy}\- K0Œ[xO[Rb2eeˑRs9l%M7**oTUU;nI#_Ds^@L{a{R={ zQqɲiY,Uu-]@{C?g >Ϯ-n}axy^}[L"w?&-P'H(<$zؙ=2Q\by$lv ]}+c-47jZ!<臈1(TfFIz 9k[64/U<.u!XN&|XX:!n~ 3Qh1q[ vQ")iQ2!rro(USURw/w0Sbzz_48e`zm-OۤR|w;(;;;sq Pm;sܷϟ"#!,3={D3p Xɽ1q <4&q$g?"v>8c8RU9Ew \мSUYQ[}j5 cE4l!vTv}{lswh0yWaIo_97{~]\. _C[PXq[H:J eAanNDWG1t\ك) axl=v ca]19GLF{ C(c;NJ(ClfcbLb`jeg!4nUT>Ue;IBLB"TQ#16i{Rv2DOrY TE7%]e1>RTѪ٤uK+:zee况Fw N T2v y޾¡αiˊ.#Oݹ 0$R:a@wlT'q! ͉L;đܓ*q8%mα ' r=k7~nO!|^%ҟeOZ\QQWVd߬rej=uH=e[xi(s%hxkĵ&çӧ?f-}r~~R ?cVW~nmh;G}$t!_὎%ǩBXU{ /ynqQvxQ)e"FSi"FW&VWk%;ԸyxxI|Z넪DJEŮ7HtJHJoȲI)8))V.RmBF]YK=y]L6FƻMrM̉6;-_XmlPlnWXrg? ਐ0𘈁H35L^}r8peciG0̼t9wQ3 g{Ws]Ŋ%.ʎWR>] | SU{?cgÊǮ='O֞5 Ex:;w~?p*( 652 159 LxIDATx6Fura,&'b 7EH^$?UBw7^ @ E\{ Ф?Iй_(n+ΗL -7zqjo*T$  Фl>Wz=B;ܫ|,/@&!  E&Ez=1 z|j}xL%@ <tͷo{)ie xCp20/A&1  [} ,(AҁfYuWOާS38OnqujqZ/^+:P-T5dtΪzpx6o ۻO[Gʡ]D8@INV@.MZ~$S]S Yz)Y-NJ_UW}Ʋ'z3Iq @x-MZ> ܏?^|j/[7^)j:^ur+kt 6]k5TsqZgp=Nkz{ < 99n\@ %yI ^-ήJ^uUu;)NI\g' ls|?j>*^|j'[^/32VsW]>1z3I+g !0gl~ȭ>pg5>j_TIU - 7I Ώ{Y-NKW]Eq | o[5ɋtY @ %pEFZ[Kjqr{՚7珞wV.=eoSM|B I`xfy⤕XtzR&VT2٬&]>oV!@ۤ{Y-̸W]g44<|XX/z'{}il.4 $׏!(풱֫.(^ZHv}5hOQ輹UJautlޔ3n 5onYqZ067A=ȳ,=&, rAMG7am2l::o. =8I @(I@H`llhV^u3qV;r-E L6i_$c@mz Ҥis/=EW]E%q %| o3ޱM|ҬB P 0I?W]θi =e\)ǔzR&6>ޤ2 @Mz^zVSe^uԯD~< du=ּͨi՟UW.~=B¸;N-GkuG ǮKuM U>n 5onYqZ067A=ȳ,=&, rAMG7am2l::o. =8I @(I@H&=>!@%4 @ Ф''5 @D&] @`"D ФKtX L$@ tk h P"@.a  0Mz"|RCJh%:A&IOOj@@MD5@Ds1O~ӊtjՙ],|68I͘J-a韆 m-aZY]q[+UߧcL;tDAGrF'&)_}fc5uR2'g,?g,Ƿbb6}ؖM{0JTOmc1MaTona͘ :%N[4)BMHoe{>;핀ҩEe S[ҩ:T-~vY:Juj]_-aie.g.~pi.o(Syy2` pM4\J`gFԮ&Enk1dl}X|4O7)4SSLEg'Adq7iȾM1fA\25>t3H胋 v iqo)nG&}#COz`A^:6pb SsfOWo܌ mj\ok\- djK:|8b20˖B  {O=Co'@~p}%oX ع 2(lZ,B&A k.4yE7gmI  O+tbFHIzw! X3mf}e(-AqgWl2V4N+XK1Qq0c _xlU H7 izFǟKE2OҽBWD8Z ФoxhH9]9gtPS<8Ӥ@xuo.&|*(jlW*`\ Q!MmaT}l7 }@1'8ܬ%9½~38o1Xm✋=]@Y C Фz@'?C*#wsv) hlܒ ]EدZ0] $Xv#F+b I/x(HI@{e*/dUf 9u]?G3V_B*og  @>-f |]G4l }x8!>gfk¥j T&hRnI* tR Ф?#6!#t7bw>_Mz5z$@R@ >DxS0H)J-+ۓm>/'gץ\/Ǒf 5:-NN6}0p֥r|4XlmcqȀ e~e@ 4ǃ8@x3O!@`i4饏q f47>ChK @ho>}j Ф>A Ф|@KI/}< 7I&@^x@o&@~S; ,M& L&ӧv@XMzA MͧO 4ǃ8@x3O!@`i4饏q f47>C>Lݯ|1@Iz  @nEfVIENDB`CheeseCutter-master/arch/fd/000077500000000000000000000000001357241101300162355ustar00rootroot00000000000000CheeseCutter-master/arch/fd/ccutter.desktop000066400000000000000000000004001357241101300212730ustar00rootroot00000000000000[Desktop Entry] # Actions=Play; Version=1.0 Name=CheeseCutter Comment=SID music editor Terminal=false TryExec=ccutter Exec=ccutter %f Type=Application Icon=ccutter-96 Categories=GNOME;Application;AudioVideo;Audio;Video; X-Desktop-File-Install-Version=0.21 CheeseCutter-master/arch/makedmg.sh000077500000000000000000000035451357241101300176170ustar00rootroot00000000000000#!/bin/bash VERSION="2.6" applicationName="CheeseCutter.app" backgroundPictureName="background.png" source="dist" title="CheeseCutter ${VERSION}" size=20000 finalDMGName="CheeseCutter_${VERSION}.dmg" mkdir "${source}" cp -r "${applicationName}" "${source}" hdiutil create -srcfolder "${source}" -volname "${title}" -fs HFS+ \ -fsargs "-c c=64,a=16,e=16" -format UDRW -size ${size}k pack.temp.dmg device=$(hdiutil attach -readwrite -noverify -noautoopen "pack.temp.dmg" | \ egrep '^/dev/' | sed 1q | awk '{print $1}') sleep 5 mkdir /Volumes/"${title}"/.background cp arch/background.png /Volumes/"${title}"/.background cp -r tunes README COPYING Changelog /Volumes/"${title}"/ pushd /Volumes/"${title}" ln -s /Applications popd echo ' tell application "Finder" tell disk "'${title}'" open set current view of container window to icon view set toolbar visible of container window to false set statusbar visible of container window to false set the bounds of container window to {400, 100, 885, 430} set theViewOptions to the icon view options of container window set arrangement of theViewOptions to not arranged set icon size of theViewOptions to 72 set background picture of theViewOptions to file ".background:'${backgroundPictureName}'" delay 1 set position of item "'${applicationName}'" of container window to {100, 100} set position of item "Applications" of container window to {375, 100} update without registering applications close open delay 5 eject end tell end tell ' | osascript chmod -Rf go-w /Volumes/"${title}" sync sync hdiutil detach ${device} hdiutil convert pack.temp.dmg -format UDZO -imagekey zlib-level=9 -o ${finalDMGName} rm pack.temp.dmg CheeseCutter-master/doc/000077500000000000000000000000001357241101300154745ustar00rootroot00000000000000CheeseCutter-master/doc/README000066400000000000000000000001271357241101300163540ustar00rootroot00000000000000Visit the website at: http://theyamo.kapsi.fi/ccutter for instructions on program use. CheeseCutter-master/doc/ccutter.1000066400000000000000000000013151357241101300172270ustar00rootroot00000000000000.TH ccutter "1" "November 2018" "User Commands" .SH NAME ccutter \- SID music editor .SH SYNOPSIS .B ccutter [\fI\,OPTION\/\fR]... [\fI\,FILE\/\fR] .SH DESCRIPTION CheeseCutter (C) 2009\-17 Abaddon Released under GNU GPL. .SH OPTIONS .TP \fB\-b\fR [value] Set playback buffer size (def=2048) .TP \fB\-f\fR Start in fullscreen mode .TP \fB\-nofp\fR Do not use resid\-fp emulation .TP \fB\-fpr\fR [x] Specify filter preset. x = 0..16 for 6581 and 0..1 for 8580 .TP \fB\-i\fR Disable resid interpolation (use fast mode instead) .TP \fB\-m\fR [0|1] Specify SID model for reSID (6581/8580) (def=0) .TP \fB\-n\fR Enable NTSC mode .TP \fB\-r\fR [value] Set playback frequency (def=48000) .TP \fB\-y\fR Use YUV video overlay CheeseCutter-master/doc/ccutter.fr.1000066400000000000000000000020561357241101300176400ustar00rootroot00000000000000.TH ccutter "1" "Novembre 2018" "Commandes utilisateur" .SH NOM ccutter \- éditeur de musique SID .SH SYNOPSIS .B ccutter [\fI\,OPTION\/\fR]... [\fI\,FICHIER\/\fR] .SH DESCRIPTION CheeseCutter (C) 2009\-17 Abaddon Publié sous GNU GPL. .SH OPTIONS .TP \fB\-b\fR [valeur] Définir la taille du tampon de lecture (déf=2048) .TP \fB\-f\fR Démarrer en mode plein écran .TP \fB\-nofp\fR Ne pas utiliser l'émulation resid\-fp .TP \fB\-fpr\fR [x] Spécifie le préréglage de filtre. x = 0..16 pour 6581 et 0..1 pour 8580 .TP \fB\-i\fR Désactive l'interpolation resid (utilise le mode rapide à la place) .TP \fB\-m\fR [0|1] Spécifie le modèle SID pour reSID (6581/8580) (déf=0) .TP \fB\-n\fR Active le mode NTSC .TP \fB\-r\fR [value] Paramètre la fréquence de lecture (déf=48000) .TP \fB\-y\fR Utiliser la superposition vidéo YUV .SH AUTEUR Michel Vergnaud \- Copyright 2015\-2016. .PP Cette page de manuel a été traduite par Olivier Humbert "trebmuh" le 24 avril 2019 pour le projet LibraZiK et peut être utilisée par tout un chacun. CheeseCutter-master/doc/ct2util.1000066400000000000000000000022641357241101300171500ustar00rootroot00000000000000.TH ct2util "1" "November 2018" "CheeseCutter 2 utilities (Nov 12 2018)" "User Commands" .SH NAME ct2util \- manual page for CheeseCutter 2 utilities (Nov 12 2018) .SH SYNOPSIS .B ct2util \fI\, <-o outfile>\/\fR .SH DESCRIPTION CheeseCutter 2 utilities (Nov 12 2018) .IP ct2util import <\-o outfile> ct2util init <\-o outfile> .SS "Commands:" .TP prg Export song (.ct) to PRG file .TP sid Export song (.ct) to SID file .TP dump Dump song data to assembler source (BETA) .TP import Copy data from another song without overwriting the player .TP init Create a fresh .ct from player binary .SS "General options:" .TP \fB\-o\fR Set output filename (by default gathered from input filename) .SS "Export options:" .TP \fB\-r\fR Relocate output to address (default = ) .TP \fB\-d\fR Set the default subtune (1\-32) .TP \fB\-s\fR Export single subtune (1\-32) (disables \fB\-d\fR) .TP \fB\-zp\fR Relocate zero page (valid range 2\-) .TP \fB\-q\fR Don't output information .PP Prefix value options with '0x' or '$' to indicate a hexadecimal value. .SH "SEE ALSO" .BR ccutter(1), .BR klystrack(1), .BR goattracker (1). CheeseCutter-master/doc/ct2util.fr.1000066400000000000000000000033341357241101300175550ustar00rootroot00000000000000.TH ct2util "1" "Novembre 2018" "utilitaires CheeseCutter 2 (12 nov 2018)" "Commandes utilisateur" .SH NOM ct2util \- page de manuel pour les utilitaires de CheeseCutter 2 utilities (12 nov 2018) .SH SYNOPSIS .B ct2util \fI\, <-o fichier_en_sortie>\/\fR .SH DESCRIPTION Utilitaires CheeseCutter 2 (12 nov 2018) .IP ct2util import <\-o fichier_en_sortie> ct2util init <\-o fichier_en_sortie> .SS "Commandes :" .TP prg Exporter le morceau (.ct) en un fichier PRG .TP sid Exporter le morceau (.ct) en un fichier SID .TP dump Déverser les données du morceau dans une source assembleur (BETA) .TP import Copier les données depuis un autre morceau sans écraser le lecteur .TP init Créer un .ct frais depuis le lecteur binaire .SS "Options générales :" .TP \fB\-o\fR Paramètrer le nom de fichier de sortie (par défaut recueilli à partir du nom du fichier d'entrée) .SS "Options d'export :" .TP \fB\-r\fR Relocaliser la sortie à l'adresse (par défaut = ) .TP \fB\-d\fR Définir les sous-réglages par défaut (1\-32) .TP \fB\-s\fR Export une sub-tonalité unique (1\-32) (désactive \fB\fB\-d\fR) .TP \fB\-zp\fR Relocaliser la page zéro (plage valide 2\-) .TP \fB\-q\fR Ne pas afficher d'informations .PP Préfixer les options de valeur par'0x' ou '$' pour indiquer une valeur hexadécimale. .SH "VOIR ÉGALEMENT" .BR ccutter(1), .BR klystrack(1), .BR goattracker (1). .SH AUTEUR Michel Vergnaud \- Copyright 2015\-2016. .PP Cette page de manuel a été traduite par Olivier Humbert "trebmuh" le 24 avril 2019 pour le projet LibraZiK et peut être utilisée par tout un chacun. CheeseCutter-master/make-wintest.cmd000066400000000000000000000007071357241101300200300ustar00rootroot00000000000000@echo off REM Expecting directory ..\DLL to contain SDL.dll set /p VER=' version: '2.9' # just for humans, typically '1.2+git' or '1.3.2' summary: CheeseCutter SID music editor description: CheeseCutter is a tracker program for composing music for the SID chip. It uses the reSID engine for SID emulation. Packed files can be played on a real C64. grade: stable # must be 'stable' to release into candidate/stable channels confinement: strict # use 'strict' once you have the right plugs and slots apps: ccutter: command: ccutter environment: CC_HOME: $SNAP_USER_COMMON plugs: - x11 - pulseaudio - home ct2util: command: ct2util plugs: - home parts: ccutter: plugin: make stage-packages: - libsdl1.2debian build-packages: - ldc source: ../ CheeseCutter-master/src/000077500000000000000000000000001357241101300155165ustar00rootroot00000000000000CheeseCutter-master/src/asm/000077500000000000000000000000001357241101300162765ustar00rootroot00000000000000CheeseCutter-master/src/asm/_std.c000066400000000000000000000016541357241101300174010ustar00rootroot00000000000000// // ACME - a crossassembler for producing 6502/65c02/65816 code. // Copyright (C) 1998-2006 Marco Baye // Have a look at "acme.c" for further info // // Platform specific stuff (in this case, for unknown OSes) #ifndef platform_C #define platform_C #include #include "dynabuf.h" // Variables char *AnyOS_lib_prefix = NULL; // header string of library tree // Functions // used as PLATFORM_INIT: reads "ACME" environment variable void AnyOS_entry(void) { char *env_var; // Find out the path of ACME's library env_var = getenv("ACME"); // if environment variable was found, make a copy if(env_var) { DYNABUF_CLEAR(GlobalDynaBuf); // copy environment variable to global dynamic buffer DynaBuf_add_string(GlobalDynaBuf, env_var); DynaBuf_append(GlobalDynaBuf, '/'); // add dir separator DynaBuf_append(GlobalDynaBuf, '\0'); // add terminator AnyOS_lib_prefix = DynaBuf_get_copy(GlobalDynaBuf); } } #endif CheeseCutter-master/src/asm/_std.h000066400000000000000000000026171357241101300174060ustar00rootroot00000000000000// // ACME - a crossassembler for producing 6502/65c02/65816 code. // Copyright (C) 1998-2006 Marco Baye // Have a look at "acme.c" for further info // // Platform specific stuff (in this case, for unknown OSes) #ifndef platform_H #define platform_H // Symbolic constants and macros // Called once on program startup (could register exit handler, if needed) #define PLATFORM_INIT AnyOS_entry() // Convert UNIX-style pathname to AnyOS-style pathname (no change) #define PLATFORM_CONVERTPATHCHAR(a) (a) // String containing the prefix for accessing files from the library tree #define PLATFORM_LIBPREFIX AnyOS_lib_prefix // Setting the created files' types #define PLATFORM_SETFILETYPE_CBM(a) #define PLATFORM_SETFILETYPE_PLAIN(a) #define PLATFORM_SETFILETYPE_TEXT(a) // Platform specific message output #define PLATFORM_WARNING(a) #define PLATFORM_ERROR(a) #define PLATFORM_SERIOUS(a) // Integer-to-character conversion #define PLATFORM_UINT2CHAR(x) do {\ x ^= x >> 16;\ x ^= x >> 8;\ x &= 255;\ } while(0) // Output of platform-specific command line switches #define PLATFORM_OPTION_HELP // Processing of platform-specific command line switches #define PLATFORM_SHORTOPTION_CODE #define PLATFORM_LONGOPTION_CODE // Variables extern char *AnyOS_lib_prefix; // header string of library tree // Prototypes // used as PLATFORM_INIT: reads "ACME" environment variable extern void AnyOS_entry(void); #endif CheeseCutter-master/src/asm/acme.c000066400000000000000000000121021357241101300173430ustar00rootroot00000000000000// // ACME - a crossassembler for producing 6502/65c02/65816 code. // Copyright (C) 1998-2006 Marco Baye // // Modified by abaddon 2013 // // 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 #define RELEASE "0.93" // update before release (FIXME) #define CODENAME "Zarquon" // update before release #define CHANGE_DATE "11 Oct" // update before release #define CHANGE_YEAR "2006" // update before release #define HOME_PAGE "http://home.pages.de/~mac_bacon/smorbrod/acme/" #include #include #include #include #include "acme.h" #include "alu.h" #include "basics.h" #include "config.h" #include "cpu.h" #include "dynabuf.h" #include "encoding.h" #include "flow.h" #include "global.h" #include "input.h" #include "label.h" #include "macro.h" #include "mnemo.h" #include "output.h" #include "platform.h" #include "section.h" // Constants static const char FILE_WRITETEXT[] = "w"; static const char FILE_WRITEBINARY[] = "wb"; // names for error messages static const char name_outfile[] = "output filename"; static const char name_dumpfile[] = "label dump filename"; // long options #define OPTION_HELP "help" #define OPTION_FORMAT "format" #define OPTION_OUTFILE "outfile" #define OPTION_LABELDUMP "labeldump" #define OPTION_SETPC "setpc" #define OPTION_CPU "cpu" #define OPTION_INITMEM "initmem" #define OPTION_MAXERRORS "maxerrors" #define OPTION_MAXDEPTH "maxdepth" #define OPTION_USE_STDOUT "use-stdout" #define OPTION_VERSION "version" // Variables static signed long start_addr = -1; // <0 is illegal static signed long fill_value = MEMINIT_USE_DEFAULT; static struct cpu_t *default_cpu = NULL; const char* labeldump_filename = NULL; const char* output_filename = NULL; const char* source = NULL; // maximum recursion depth for macro calls and "!source" signed long macro_recursions_left = MAX_NESTING; signed long source_recursions_left = MAX_NESTING; // Perform a single pass. Returns number of "NeedValue" type errors. static int perform_pass(void) { // call modules' "pass init" functions CPU_passinit(default_cpu);// set default cpu values (PC undefined) Output_passinit(start_addr);// call after CPU_passinit(), to define PC Encoding_passinit(); // set default encoding Section_passinit(); // set initial zone (untitled) // init variables pass_undefined_count = 0; // no "NeedValue" errors yet pass_real_errors = 0; // no real errors yet Parse_source(source); if(pass_real_errors) { longjmp(exception_env, 0); } else Output_end_segment(); return(pass_undefined_count); } // do passes until done (or errors occured). Return whether output is ready. static bool do_actual_work(void) { int undefined_prev, // "NeedValue" errors of previous pass undefined_curr; // "NeedValue" errors of current pass if(Process_verbosity > 1) puts("First pass."); pass_count = 0; undefined_curr = perform_pass(); // First pass // now pretend there has been a pass before the first one undefined_prev = undefined_curr + 1; // As long as the number of "NeedValue" errors is decreasing but // non-zero, keep doing passes. while(undefined_curr && (undefined_curr < undefined_prev)) { pass_count++; undefined_prev = undefined_curr; if(Process_verbosity > 1) puts("Further pass."); undefined_curr = perform_pass(); } // If still errors (unsolvable by doing further passes), // perform additional pass to find and show them if(undefined_curr == 0) return(TRUE); if(Process_verbosity > 1) puts("Further pass needed to find error."); ALU_throw_errors(); // activate error output (CAUTION - one-way!) pass_count++; perform_pass(); // perform pass, but now show "value undefined" return(FALSE); } char* acme_assemble(const char* src, const int *length, char *error) { error_message = error; source = src; msg_stream = stdout; DynaBuf_init();// inits *global* dynamic buffer - important, so first // Init platform-specific stuff. // For example, this could read the library path from an // environment variable, which in turn may need DynaBuf already. PLATFORM_INIT; // init some keyword trees needed for argument handling CPUtype_init(); Outputfile_init(); // Init modules (most of them will just build keyword trees) ALU_init(); Basics_init(); CPU_init(); Encoding_init(); Flow_init(); Input_init(); Label_init(); Macro_init(); Mnemo_init(); Output_init(fill_value); Section_init(); if(!setjmp(exception_env)) { if(do_actual_work()) { return Output_get_final_data(length); } } return NULL; } CheeseCutter-master/src/asm/acme.h000066400000000000000000000010711357241101300173530ustar00rootroot00000000000000// // ACME - a crossassembler for producing 6502/65c02/65816 code. // Copyright (C) 1998-2006 Marco Baye // Have a look at "acme.c" for further info // // Main definitions #ifndef acme_H #define acme_H #include "config.h" // Variables extern const char* labeldump_filename; extern const char* output_filename; // maximum recursion depth for macro calls and "!source" extern signed long macro_recursions_left; extern signed long source_recursions_left; // Prototypes // Tidy up before exiting by saving label dump extern int ACME_finalize(int exit_code); #endif CheeseCutter-master/src/asm/alu.c000066400000000000000000001230521357241101300172260ustar00rootroot00000000000000// // ACME - a crossassembler for producing 6502/65c02/65816 code. // Copyright (C) 1998-2006 Marco Baye // Have a look at "acme.c" for further info // // Arithmetic/logic unit // 11 Oct 006 Improved float reading in parse_decimal_value() #include #include // only for experimental fp support #include "platform.h" // done first in case "inline" is redefined #include "alu.h" #include "cpu.h" #include "dynabuf.h" #include "encoding.h" #include "global.h" #include "input.h" #include "label.h" #include "section.h" #include "tree.h" // Constants #define FUNCION_DYNABUF_INITIALSIZE 8 // enough for "arctan" #define HALF_INITIAL_STACK_SIZE 8 static const char exception_div_by_zero[] = "Division by zero."; static const char exception_no_value[] = "No value given."; static const char exception_paren_open[] = "Too many '('."; static const char exception_undefined[] = "Value not defined."; #define s_or (s_eor+1) // Yes, I know I'm sick #define s_xor (s_scrxor+3) // Yes, I know I'm sick static const char s_arcsin[] = "arcsin"; #define s_sin (s_arcsin+3) // Yes, I know I'm sick static const char s_arccos[] = "arccos"; #define s_cos (s_arccos+3) // Yes, I know I'm sick static const char s_arctan[] = "arctan"; #define s_tan (s_arctan+3) // Yes, I know I'm sick // Operator handles (FIXME - use function pointers instead? or too slow?) enum op_handle_t { // special values (pseudo operators) OPHANDLE_END, // "reached end of expression" OPHANDLE_RETURN, // "return value to caller" // functions OPHANDLE_INT, // int(v) OPHANDLE_FLOAT, // float(v) OPHANDLE_SIN, // sin(v) OPHANDLE_COS, // cos(v) OPHANDLE_TAN, // tan(v) OPHANDLE_ARCSIN, // arcsin(v) OPHANDLE_ARCCOS, // arccos(v) OPHANDLE_ARCTAN, // arctan(v) // monadic operators OPHANDLE_OPENING, // (v '(', starts subexpression OPHANDLE_NOT, // !v NOT v bit-wise NOT OPHANDLE_NEGATE, // -v Negate OPHANDLE_LOWBYTEOF, // v Highbyte of OPHANDLE_BANKBYTEOF, // ^v Bankbyte of // dyadic operators OPHANDLE_CLOSING, // v) ')', ends subexpression OPHANDLE_POWEROF, // v^w OPHANDLE_MULTIPLY, // v*w OPHANDLE_DIVIDE, // v/w (Integer) Division OPHANDLE_INTDIV, // v/w v DIV w Integer Division OPHANDLE_MODULO, // v%w v MOD w Remainder OPHANDLE_SL, // v<>w v ASR w Arithmetic shift right OPHANDLE_LSR, // v>>>w v LSR w Logical shift right OPHANDLE_ADD, // v+w OPHANDLE_SUBTRACT, // v-w OPHANDLE_EQUALS, // v=w OPHANDLE_LE, // v<=w OPHANDLE_LESSTHAN, // v< w OPHANDLE_GE, // v>=w OPHANDLE_GREATERTHAN, // v> w OPHANDLE_NOTEQUAL, // v!=w v<>w v>>= 1; } return(result); } // arithmetic shift right (works even if C compiler does not support it) static inline intval_t my_asr(intval_t left, intval_t right) { intval_t result = left >> right; // perform shift right // if left operand >= 0, then ASR and LSR are equivalent, so ok // if result < 0, then ASR has been performed, so ok if((left >= 0) || (result < 0)) return(result); // otherwise, correct result and return that return(result | (-1L << (8 * sizeof(intval_t) - right))); } // Lookup (and create, if necessary) label tree item and return its value. // DynaBuf holds the label's name and "zone" its zone. // This function is not allowed to change DynaBuf because that's where the // label name is stored! static void get_label_value(zone_t zone) { label_t* label; // If the label gets created now, mark it as unsure label = Label_find(zone, MVALUE_UNSURE); // in first pass, count usage if(pass_count == 0) label->usage++; // push operand, regardless of whether int or float operand_stack[operand_sp] = label->result; operand_stack[operand_sp++].flags |= MVALUE_EXISTS; } // Parse quoted character. // The character will be converted using the current encoding. static inline void parse_quoted_character(char closing_quote) { intval_t value; // read character to parse - make sure not at end of statement if(GetQuotedByte() == CHAR_EOS) return; // on empty string, complain if(GotByte == closing_quote) { Throw_error(exception_missing_string); Input_skip_remainder(); return; } // parse character value = (intval_t) Encoding_encode_char(GotByte); // Read closing quote (hopefully) if(GetQuotedByte() == closing_quote) GetByte();// If length == 1, proceed with next byte else if(GotByte) { // If longer than one character Throw_error("There's more than one character."); Input_skip_remainder(); } PUSH_INTOPERAND(value, MVALUE_GIVEN | MVALUE_ISBYTE); // Now GotByte = char following closing quote (or CHAR_EOS on error) } // Parse hexadecimal value. It accepts "0" to "9", "a" to "f" and "A" to "F". // Capital letters will be converted to lowercase letters using the flagtable. // The current value is stored as soon as a character is read that is none of // those given above. static void parse_hexadecimal_value(void) {// Now GotByte = "$" or "x" char byte; bool go_on; // continue loop flag int digits = -1, // digit counter flags = MVALUE_GIVEN; intval_t value = 0; do { digits++; go_on = FALSE; byte = GetByte(); // first, convert "A-F" to "a-f" byte |= (BYTEFLAGS(byte) & BYTEIS_UPCASE); // if digit, add digit value if((byte >= '0') && (byte <= '9')) { value = (value << 4) + (byte - '0'); go_on = TRUE;// keep going } // if legal ("a-f") character, add character value if((byte >= 'a') && (byte <= 'f')) { value = (value << 4) + (byte - 'a') + 10; go_on = TRUE;// keep going } } while(go_on); // set force bits if(digits > 2) { if(digits > 4) { if(value < 65536) flags |= MVALUE_FORCE24; } else { if(value < 256) flags |= MVALUE_FORCE16; } } PUSH_INTOPERAND(value, flags); // Now GotByte = non-hexadecimal char } // Parse a decimal value. As decimal values don't use any prefixes, this // function expects the first digit to be read already. If the first two digits // are "0x", this function branches to the one for parsing hexadecimal values. // This function accepts '0' through '9' and one dot ('.') as the decimal // point. The current value is stored as soon as a character is read that is // none of those given above. Float usage is only activated when a decimal // point has been found, so don't expect "100000000000000000000" to work. static inline void parse_decimal_value(void) {// Now GotByte = first digit double fpval, denominator; intval_t intval = (GotByte & 15);// this works. it's ASCII. GetByte(); if((intval == 0) && (GotByte == 'x')) return(parse_hexadecimal_value()); // parse digits until no more while((GotByte >= '0') && (GotByte <= '9')) { intval *= 10; intval += (GotByte & 15);// this works. it's ASCII. GetByte(); } // check whether it's a float if(GotByte == '.') { // read fractional part and store as fp value GetByte(); fpval = intval; denominator = 1; // parse digits until no more while((GotByte >= '0') && (GotByte <= '9')) { fpval *= 10; fpval += (GotByte & 15);// this works. it' ASCII. denominator *= 10; GetByte(); } fpval /= denominator; PUSH_FPOPERAND(fpval, MVALUE_GIVEN); } else { // integer PUSH_INTOPERAND(intval, MVALUE_GIVEN); } // Now GotByte = non-decimal char } // Parse octal value. It accepts "0" to "7". The current value is stored as // soon as a character is read that is none of those given above. static inline void parse_octal_value(void) {// Now GotByte = "&" intval_t value = 0; int flags = MVALUE_GIVEN, digits = 0; // digit counter GetByte(); while((GotByte >= '0') && (GotByte <= '7')) { value = (value << 3) + (GotByte & 7);// this works. it's ASCII. digits++; GetByte(); } // set force bits if(digits > 3) { if(digits > 6) { if(value < 65536) flags |= MVALUE_FORCE24; } else { if(value < 256) flags |= MVALUE_FORCE16; } } PUSH_INTOPERAND(value, flags); // Now GotByte = non-octal char } // Parse binary value. Apart from '0' and '1', it also accepts the characters // '.' and '#', this is much more readable. The current value is stored as soon // as a character is read that is none of those given above. static inline void parse_binary_value(void) {// Now GotByte = "%" intval_t value = 0; bool go_on = TRUE; // continue loop flag int flags = MVALUE_GIVEN, digits = -1; // digit counter do { digits++; switch(GetByte()) { case '0': case '.': value <<= 1; break; case '1': case '#': value = (value << 1) | 1; break; default: go_on = FALSE; } } while(go_on); // set force bits if(digits > 8) { if(digits > 16) { if(value < 65536) flags |= MVALUE_FORCE24; } else { if(value < 256) flags |= MVALUE_FORCE16; } } PUSH_INTOPERAND(value, flags); // Now GotByte = non-binary char } // Parse function call (sin(), cos(), arctan(), ...) static inline void parse_function_call(void) { void* node_body; // make lower case version of name in local dynamic buffer DynaBuf_to_lower(function_dyna_buf, GlobalDynaBuf); // search for tree item if(Tree_easy_scan(function_tree, &node_body, function_dyna_buf)) PUSH_OPERATOR((op_t*) node_body); else Throw_error("Unknown function."); } // Expect operand or monadic operator (hopefully inlined) static inline void expect_operand_or_monadic_operator(void) { op_t* operator; bool perform_negation; SKIPSPACE(); switch(GotByte) { case '+':// anonymous forward label // count plus signs to build name of anonymous label DYNABUF_CLEAR(GlobalDynaBuf); do DYNABUF_APPEND(GlobalDynaBuf, '+'); while(GetByte() == '+'); Label_fix_forward_name(); get_label_value(Section_now->zone); goto now_expect_dyadic; case '-':// NEGATION operator or anonymous backward label // count minus signs in case it's an anonymous backward label perform_negation = FALSE; DYNABUF_CLEAR(GlobalDynaBuf); do { DYNABUF_APPEND(GlobalDynaBuf, '-'); perform_negation = !perform_negation; } while(GetByte() == '-'); SKIPSPACE(); if(BYTEFLAGS(GotByte) & FOLLOWS_ANON) { DynaBuf_append(GlobalDynaBuf, '\0'); get_label_value(Section_now->zone); goto now_expect_dyadic; } // goto means we don't need an "else {" here if(perform_negation) PUSH_OPERATOR(&ops_negate); // State doesn't change break; // Real monadic operators (state doesn't change, still ExpectMonadic) case '!':// NOT operator operator = &ops_not; goto get_byte_and_push_monadic; case '<':// LOWBYTE operator operator = &ops_lowbyteof; goto get_byte_and_push_monadic; case '>':// HIGHBYTE operator operator = &ops_highbyteof; goto get_byte_and_push_monadic; case '^':// BANKBYTE operator operator = &ops_bankbyteof; goto get_byte_and_push_monadic; // Faked monadic operators case '(':// left parenthesis operator = &ops_opening; goto get_byte_and_push_monadic; case ')':// right parenthesis // this makes "()" also throw a syntax error Throw_error(exception_syntax); alu_state = STATE_ERROR; break; // Operands (values, state changes to ExpectDyadic) // Quoted character case '"': case '\'': // Character will be converted using current encoding parse_quoted_character(GotByte); // Now GotByte = char following closing quote goto now_expect_dyadic; // Binary value case '%': parse_binary_value();// Now GotByte = non-binary char goto now_expect_dyadic; // Octal value case '&': parse_octal_value();// Now GotByte = non-octal char goto now_expect_dyadic; // Hexadecimal value case '$': parse_hexadecimal_value(); // Now GotByte = non-hexadecimal char goto now_expect_dyadic; // Program counter case '*': GetByte();// proceed with next char PUSH_INTOPERAND(CPU_pc.intval, CPU_pc.flags | MVALUE_EXISTS); // Now GotByte = char after closing quote goto now_expect_dyadic; // Local label case '.': GetByte();// start after '.' if(Input_read_keyword()) { // Now GotByte = illegal char get_label_value(Section_now->zone); goto now_expect_dyadic; } // goto means we don't need an "else {" here alu_state = STATE_ERROR; break; // Decimal values and global labels default:// (all other characters) if((GotByte >= '0') && (GotByte <= '9')) { parse_decimal_value(); // Now GotByte = non-decimal char goto now_expect_dyadic; } // goto means we don't need an "else {" here if(BYTEFLAGS(GotByte) & STARTS_KEYWORD) { register int length; // Read global label (or "NOT") length = Input_read_keyword(); // Now GotByte = illegal char // Check for NOT. Okay, it's hardcoded, // but so what? Sue me... if((length == 3) && ((GlobalDynaBuf->buffer[0] | 32) == 'n') && ((GlobalDynaBuf->buffer[1] | 32) == 'o') && ((GlobalDynaBuf->buffer[2] | 32) == 't')) { PUSH_OPERATOR(&ops_not); // state doesn't change } else { if(GotByte == '(') parse_function_call(); else { get_label_value(ZONE_GLOBAL); goto now_expect_dyadic; } } } else { // illegal character read - so don't go on PUSH_INTOPERAND(0, 0); // push pseudo value, EXISTS flag is clear if(operator_stack[operator_sp-1] == &ops_return) { PUSH_OPERATOR(&ops_end); alu_state = STATE_TRY_TO_REDUCE_STACKS; } else { Throw_error(exception_syntax); alu_state = STATE_ERROR; } } break; // no other possibilities, so here are the shared endings get_byte_and_push_monadic: GetByte(); PUSH_OPERATOR(operator); // State doesn't change break; now_expect_dyadic: alu_state = STATE_EXPECT_DYADIC_OPERATOR; break; } } // Expect dyadic operator (hopefully inlined) static inline void expect_dyadic_operator(void) { void* node_body; op_t* operator; SKIPSPACE(); switch(GotByte) { // Single-character dyadic operators case '^':// "to the power of" operator = &ops_powerof; goto get_byte_and_push_dyadic; case '+':// add operator = &ops_add; goto get_byte_and_push_dyadic; case '-':// subtract operator = &ops_subtract; goto get_byte_and_push_dyadic; case '*':// multiply operator = &ops_multiply; goto get_byte_and_push_dyadic; case '/':// divide operator = &ops_divide; goto get_byte_and_push_dyadic; case '%':// modulo operator = &ops_modulo; goto get_byte_and_push_dyadic; case '&':// bitwise AND operator = &ops_and; goto get_byte_and_push_dyadic; case '|':// bitwise OR operator = &ops_or; goto get_byte_and_push_dyadic; // This part is commented out because there is no XOR character defined // case ???:// bitwise exclusive OR // operator = &ops_xor; // goto get_byte_and_push_dyadic; case '=':// is equal operator = &ops_equals; goto get_byte_and_push_dyadic; case ')':// closing parenthesis operator = &ops_closing; goto get_byte_and_push_dyadic; // Multi-character dyadic operators // "!=" case '!': if(GetByte() == '=') { operator = &ops_notequal; goto get_byte_and_push_dyadic; } // goto means we don't need an "else {" here Throw_error(exception_syntax); alu_state = STATE_ERROR; break; // "<", "<=", "<<" and "<>" case '<': switch(GetByte()) { case '=':// "<=", less or equal operator = &ops_le; goto get_byte_and_push_dyadic; case '<':// "<<", shift left operator = &ops_sl; goto get_byte_and_push_dyadic; case '>':// "<>", not equal operator = &ops_notequal; goto get_byte_and_push_dyadic; default:// "<", less than operator = &ops_lessthan; goto push_dyadic; } break; // ">", ">=", ">>", ">>>" and "><" case '>': switch(GetByte()) { case '=':// ">=", greater or equal operator = &ops_ge; goto get_byte_and_push_dyadic; case '<':// "><", not equal operator = &ops_notequal; goto get_byte_and_push_dyadic; case '>':// ">>" or ">>>", shift right operator = &ops_asr;// arithmetic shift right if(GetByte() != '>') goto push_dyadic; operator = &ops_lsr;// logical shift right goto get_byte_and_push_dyadic; default:// ">", greater than operator = &ops_greaterthan; goto push_dyadic; } break; // end of expression or text version of dyadic operator default: // check string version of operators if(BYTEFLAGS(GotByte) & STARTS_KEYWORD) { Input_read_and_lower_keyword(); // Now GotByte = illegal char // search for tree item if(Tree_easy_scan(operator_tree, &node_body, GlobalDynaBuf)) { operator = node_body; goto push_dyadic; } // goto means we don't need an "else {" here Throw_error("Unknown operator."); alu_state = STATE_ERROR; } else { operator = &ops_end; goto push_dyadic; } break; // no other possibilities, so here are the shared endings get_byte_and_push_dyadic: GetByte(); push_dyadic: PUSH_OPERATOR(operator); alu_state = STATE_TRY_TO_REDUCE_STACKS; break; } } // call C's sin/cos/tan function static void perform_fp(double (*fn)(double)) { if((RIGHT_FLAGS & MVALUE_IS_FP) == 0) { RIGHT_FPVAL = RIGHT_INTVAL; RIGHT_FLAGS |= MVALUE_IS_FP; } RIGHT_FPVAL = fn(RIGHT_FPVAL); } // make sure arg is in [-1, 1] range before calling function static void perform_ranged_fp(double (*fn)(double)) { if((RIGHT_FLAGS & MVALUE_IS_FP) == 0) { RIGHT_FPVAL = RIGHT_INTVAL; RIGHT_FLAGS |= MVALUE_IS_FP; } if((RIGHT_FPVAL >= -1) && (RIGHT_FPVAL <= 1)) RIGHT_FPVAL = fn(RIGHT_FPVAL); else { if(RIGHT_FLAGS & MVALUE_DEFINED) Throw_error("Argument out of range."); RIGHT_FPVAL = 0; } } // convert right-hand value from fp to int static void right_fp_to_int() { RIGHT_INTVAL = RIGHT_FPVAL; RIGHT_FLAGS &= ~MVALUE_IS_FP; } // check both left-hand and right-hand values. if float, convert to int. // in first pass, throw warning static void both_ensure_int(bool warn) { if(LEFT_FLAGS & MVALUE_IS_FP) { LEFT_INTVAL = LEFT_FPVAL; LEFT_FLAGS &= ~MVALUE_IS_FP; } if(RIGHT_FLAGS & MVALUE_IS_FP) { RIGHT_INTVAL = RIGHT_FPVAL; RIGHT_FLAGS &= ~MVALUE_IS_FP; } Throw_first_pass_warning("Converted to integer for binary logic operator."); } // check both left-hand and right-hand values. if int, convert to float. static void both_ensure_fp() { if((LEFT_FLAGS & MVALUE_IS_FP) == 0) { LEFT_FPVAL = LEFT_INTVAL; LEFT_FLAGS |= MVALUE_IS_FP; } if((RIGHT_FLAGS & MVALUE_IS_FP) == 0) { RIGHT_FPVAL = RIGHT_INTVAL; RIGHT_FLAGS |= MVALUE_IS_FP; } } // make sure both values are float, but mark left one as int (will become one) static void ensure_int_from_fp() { both_ensure_fp(); LEFT_FLAGS &= ~MVALUE_IS_FP; } // Try to reduce stacks by performing high-priority operations static inline void try_to_reduce_stacks(int* open_parentheses) { if(operator_sp < 2) { alu_state = STATE_EXPECT_OPERAND_OR_MONADIC_OPERATOR; return; } if(operator_stack[operator_sp-2]->priority < operator_stack[operator_sp-1]->priority) { alu_state = STATE_EXPECT_OPERAND_OR_MONADIC_OPERATOR; return; } switch(operator_stack[operator_sp-2]->handle) { // special (pseudo) operators case OPHANDLE_RETURN: // don't touch indirect_flag; needed for INDIRECT flag operator_sp--;// decrement operator stack pointer alu_state = STATE_END; break; case OPHANDLE_OPENING: indirect_flag = MVALUE_INDIRECT;// parentheses found switch(operator_stack[operator_sp-1]->handle) { case OPHANDLE_CLOSING:// matching parentheses operator_sp -= 2;// remove both of them alu_state = STATE_EXPECT_DYADIC_OPERATOR; break; case OPHANDLE_END:// unmatched parenthesis (*open_parentheses)++;// count goto RNTLObutDontTouchIndirectFlag; default: Bug_found("StrangeParenthesis", operator_stack[operator_sp-1]->handle); } break; case OPHANDLE_CLOSING: Throw_error("Too many ')'."); goto remove_next_to_last_operator; // functions case OPHANDLE_INT: if(RIGHT_FLAGS & MVALUE_IS_FP) right_fp_to_int(); goto remove_next_to_last_operator; case OPHANDLE_FLOAT: // convert right-hand value from int to fp if((RIGHT_FLAGS & MVALUE_IS_FP) == 0) { RIGHT_FPVAL = RIGHT_INTVAL; RIGHT_FLAGS |= MVALUE_IS_FP; } goto remove_next_to_last_operator; case OPHANDLE_SIN: perform_fp(sin); goto remove_next_to_last_operator; case OPHANDLE_COS: perform_fp(cos); goto remove_next_to_last_operator; case OPHANDLE_TAN: perform_fp(tan); goto remove_next_to_last_operator; case OPHANDLE_ARCSIN: perform_ranged_fp(asin); goto remove_next_to_last_operator; case OPHANDLE_ARCCOS: perform_ranged_fp(acos); goto remove_next_to_last_operator; case OPHANDLE_ARCTAN: perform_fp(atan); goto remove_next_to_last_operator; // monadic operators case OPHANDLE_NOT: // different operations for fp and int if(RIGHT_FLAGS & MVALUE_IS_FP) right_fp_to_int(); RIGHT_INTVAL = ~(RIGHT_INTVAL); RIGHT_FLAGS &= ~MVALUE_ISBYTE; goto remove_next_to_last_operator; case OPHANDLE_NEGATE: // different operations for fp and int if(RIGHT_FLAGS & MVALUE_IS_FP) RIGHT_FPVAL = -(RIGHT_FPVAL); else RIGHT_INTVAL = -(RIGHT_INTVAL); RIGHT_FLAGS &= ~MVALUE_ISBYTE; goto remove_next_to_last_operator; case OPHANDLE_LOWBYTEOF: // fp becomes int if(RIGHT_FLAGS & MVALUE_IS_FP) right_fp_to_int(); RIGHT_INTVAL = (RIGHT_INTVAL) & 255; RIGHT_FLAGS |= MVALUE_ISBYTE; RIGHT_FLAGS &= ~MVALUE_FORCEBITS; goto remove_next_to_last_operator; case OPHANDLE_HIGHBYTEOF: // fp becomes int if(RIGHT_FLAGS & MVALUE_IS_FP) right_fp_to_int(); RIGHT_INTVAL = ((RIGHT_INTVAL) >> 8) & 255; RIGHT_FLAGS |= MVALUE_ISBYTE; RIGHT_FLAGS &= ~MVALUE_FORCEBITS; goto remove_next_to_last_operator; case OPHANDLE_BANKBYTEOF: // fp becomes int if(RIGHT_FLAGS & MVALUE_IS_FP) right_fp_to_int(); RIGHT_INTVAL = ((RIGHT_INTVAL) >> 16) & 255; RIGHT_FLAGS |= MVALUE_ISBYTE; RIGHT_FLAGS &= ~MVALUE_FORCEBITS; goto remove_next_to_last_operator; // dyadic operators case OPHANDLE_POWEROF: if((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP) { both_ensure_fp(); LEFT_FPVAL = pow(LEFT_FPVAL, RIGHT_FPVAL); goto handle_flags_and_dec_stacks; } if(RIGHT_INTVAL >= 0) LEFT_INTVAL = my_pow(LEFT_INTVAL, RIGHT_INTVAL); else { if(RIGHT_FLAGS & MVALUE_DEFINED) Throw_error("Exponent is negative."); LEFT_INTVAL = 0; } goto handle_flags_and_dec_stacks; case OPHANDLE_MULTIPLY: if((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP) { both_ensure_fp(); LEFT_FPVAL *= RIGHT_FPVAL; } else LEFT_INTVAL *= RIGHT_INTVAL; goto handle_flags_and_dec_stacks; case OPHANDLE_DIVIDE: if((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP) { both_ensure_fp(); if(RIGHT_FPVAL) LEFT_FPVAL /= RIGHT_FPVAL; else { if(RIGHT_FLAGS & MVALUE_DEFINED) Throw_error(exception_div_by_zero); LEFT_FPVAL = 0; } } else { if(RIGHT_INTVAL) LEFT_INTVAL /= RIGHT_INTVAL; else { if(RIGHT_FLAGS & MVALUE_DEFINED) Throw_error(exception_div_by_zero); LEFT_INTVAL = 0; } } goto handle_flags_and_dec_stacks; case OPHANDLE_INTDIV: if((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP) { both_ensure_fp(); if(RIGHT_FPVAL) LEFT_INTVAL = LEFT_FPVAL / RIGHT_FPVAL; else { if(RIGHT_FLAGS & MVALUE_DEFINED) Throw_error(exception_div_by_zero); LEFT_INTVAL = 0; } LEFT_FLAGS &= ~MVALUE_IS_FP; } else { if(RIGHT_INTVAL) LEFT_INTVAL /= RIGHT_INTVAL; else { if(RIGHT_FLAGS & MVALUE_DEFINED) Throw_error(exception_div_by_zero); LEFT_INTVAL = 0; } } goto handle_flags_and_dec_stacks; case OPHANDLE_MODULO: if((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP) both_ensure_int(FALSE); if(RIGHT_INTVAL) LEFT_INTVAL %= RIGHT_INTVAL; else { if(RIGHT_FLAGS & MVALUE_DEFINED) Throw_error(exception_div_by_zero); LEFT_INTVAL = 0; } goto handle_flags_and_dec_stacks; case OPHANDLE_ADD: if((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP) { both_ensure_fp(); LEFT_FPVAL += RIGHT_FPVAL; } else LEFT_INTVAL += RIGHT_INTVAL; goto handle_flags_and_dec_stacks; case OPHANDLE_SUBTRACT: if((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP) { both_ensure_fp(); LEFT_FPVAL -= RIGHT_FPVAL; } else LEFT_INTVAL -= RIGHT_INTVAL; goto handle_flags_and_dec_stacks; case OPHANDLE_SL: if(RIGHT_FLAGS & MVALUE_IS_FP) right_fp_to_int(); if(LEFT_FLAGS & MVALUE_IS_FP) LEFT_FPVAL *= (1 << RIGHT_INTVAL); else LEFT_INTVAL <<= RIGHT_INTVAL; goto handle_flags_and_dec_stacks; case OPHANDLE_ASR: if(RIGHT_FLAGS & MVALUE_IS_FP) right_fp_to_int(); if(LEFT_FLAGS & MVALUE_IS_FP) LEFT_FPVAL /= (1 << RIGHT_INTVAL); else LEFT_INTVAL = my_asr(LEFT_INTVAL, RIGHT_INTVAL); goto handle_flags_and_dec_stacks; case OPHANDLE_LSR: if((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP) both_ensure_int(TRUE); LEFT_INTVAL = ((uintval_t) LEFT_INTVAL) >> RIGHT_INTVAL; goto handle_flags_and_dec_stacks; case OPHANDLE_LE: if((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP) { ensure_int_from_fp(); LEFT_INTVAL = (LEFT_FPVAL <= RIGHT_FPVAL); } else LEFT_INTVAL = (LEFT_INTVAL <= RIGHT_INTVAL); goto handle_flags_and_dec_stacks; case OPHANDLE_LESSTHAN: if((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP) { ensure_int_from_fp(); LEFT_INTVAL = (LEFT_FPVAL < RIGHT_FPVAL); } else LEFT_INTVAL = (LEFT_INTVAL < RIGHT_INTVAL); goto handle_flags_and_dec_stacks; case OPHANDLE_GE: if((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP) { ensure_int_from_fp(); LEFT_INTVAL = (LEFT_FPVAL >= RIGHT_FPVAL); } else LEFT_INTVAL = (LEFT_INTVAL >= RIGHT_INTVAL); goto handle_flags_and_dec_stacks; case OPHANDLE_GREATERTHAN: if((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP) { ensure_int_from_fp(); LEFT_INTVAL = (LEFT_FPVAL > RIGHT_FPVAL); } else LEFT_INTVAL = (LEFT_INTVAL > RIGHT_INTVAL); goto handle_flags_and_dec_stacks; case OPHANDLE_NOTEQUAL: if((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP) { ensure_int_from_fp(); LEFT_INTVAL = (LEFT_FPVAL != RIGHT_FPVAL); } else LEFT_INTVAL = (LEFT_INTVAL != RIGHT_INTVAL); goto handle_flags_and_dec_stacks; case OPHANDLE_EQUALS: if((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP) { ensure_int_from_fp(); LEFT_INTVAL = (LEFT_FPVAL == RIGHT_FPVAL); } else LEFT_INTVAL = (LEFT_INTVAL == RIGHT_INTVAL); goto handle_flags_and_dec_stacks; case OPHANDLE_AND: if((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP) both_ensure_int(TRUE); LEFT_INTVAL &= RIGHT_INTVAL; goto handle_flags_and_dec_stacks; case OPHANDLE_EOR: Throw_first_pass_warning("\"EOR\" is deprecated; use \"XOR\" instead."); /*FALLTHROUGH*/ case OPHANDLE_XOR: if((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP) both_ensure_int(TRUE); LEFT_INTVAL ^= RIGHT_INTVAL; goto handle_flags_and_dec_stacks; case OPHANDLE_OR: if((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP) both_ensure_int(TRUE); LEFT_INTVAL |= RIGHT_INTVAL; goto handle_flags_and_dec_stacks; default: Bug_found("IllegalOperatorHandle", operator_stack[operator_sp-2]->handle); break; // no other possibilities, so here are the shared endings // entry point for dyadic operators handle_flags_and_dec_stacks: // Handle flags and decrement value stack pointer // "OR" EXISTS, UNSURE and FORCEBIT flags LEFT_FLAGS |= RIGHT_FLAGS & (MVALUE_EXISTS|MVALUE_UNSURE|MVALUE_FORCEBITS); // "AND" DEFINED flag LEFT_FLAGS &= (RIGHT_FLAGS | ~MVALUE_DEFINED); LEFT_FLAGS &= ~MVALUE_ISBYTE;// clear ISBYTE flag operand_sp--; /*FALLTHROUGH*/ // entry point for monadic operators remove_next_to_last_operator: // toplevel operation was something other than parentheses indirect_flag = 0; /*FALLTHROUGH*/ // entry point for '(' operator (has set indirect_flag, so don't clear now) RNTLObutDontTouchIndirectFlag: // Remove operator and shift down next one operator_stack[operator_sp-2] = operator_stack[operator_sp-1]; operator_sp--;// decrement operator stack pointer break; } } // The core of it. Returns number of parentheses left open. // FIXME - make state machine using function pointers? or too slow? static int parse_expression(result_t* result) { int open_parentheses = 0; operator_sp = 0; // operator stack pointer operand_sp = 0; // value stack pointer // begin by reading value (or monadic operator) alu_state = STATE_EXPECT_OPERAND_OR_MONADIC_OPERATOR; indirect_flag = 0; // Contains either 0 or MVALUE_INDIRECT PUSH_OPERATOR(&ops_return); do { // check stack sizes. enlarge if needed if(operator_sp >= operator_stk_size) enlarge_operator_stack(); if(operand_sp >= operand_stk_size) enlarge_operand_stack(); switch(alu_state) { case STATE_EXPECT_OPERAND_OR_MONADIC_OPERATOR: expect_operand_or_monadic_operator(); break; case STATE_EXPECT_DYADIC_OPERATOR: expect_dyadic_operator(); break;// no fallthrough; state might // have been changed to END or ERROR case STATE_TRY_TO_REDUCE_STACKS: try_to_reduce_stacks(&open_parentheses); break; case STATE_MAX_GO_ON: // suppress case STATE_ERROR: // compiler case STATE_END: // warnings break; } } while(alu_state < STATE_MAX_GO_ON); // done. check state. if(alu_state == STATE_END) { // check for bugs if(operand_sp != 1) Bug_found("OperandStackNotEmpty", operand_sp); if(operator_sp != 1) Bug_found("OperatorStackNotEmpty", operator_sp); // copy result *result = operand_stack[0]; result->flags |= indirect_flag; // OR indirect flag // only allow *one* force bit if(result->flags & MVALUE_FORCE24) result->flags &= ~(MVALUE_FORCE16 | MVALUE_FORCE08); else if(result->flags & MVALUE_FORCE16) result->flags &= ~MVALUE_FORCE08; // if there was nothing to parse, mark as undefined // (so ALU_defined_int() can react) if((result->flags & MVALUE_EXISTS) == 0) result->flags &= ~MVALUE_DEFINED; // do some checks depending on int/float if(result->flags & MVALUE_IS_FP) { /*float*/ // if undefined, return zero if((result->flags & MVALUE_DEFINED) == 0) result->val.fpval = 0; // if value is sure, check to set ISBYTE else if(((result->flags & MVALUE_UNSURE) == 0) && (result->val.fpval <= 255.0) && (result->val.fpval >= -128.0)) result->flags |= MVALUE_ISBYTE; } else { /*int*/ // if undefined, return zero if((result->flags & MVALUE_DEFINED) == 0) result->val.intval = 0; // if value is sure, check to set ISBYTE else if(((result->flags & MVALUE_UNSURE) == 0) && (result->val.intval <= 255) && (result->val.intval >= -128)) result->flags |= MVALUE_ISBYTE; } } else { // State is STATE_ERROR. But actually, nobody cares. // ...errors have already been reported anyway. :) } // return number of open (unmatched) parentheses return(open_parentheses); } // These functions handle numerical expressions. There are operators for // arithmetic, logic, shift and comparison operations. // There are several different ways to call the core function: // intval_t ALU_any_int(void); // returns int value (0 if result was undefined) // intval_t ALU_defined_int(void); // returns int value // if result was undefined, serious error is thrown // void ALU_int_result(result_int_t*); // stores int value and flags (floats are transformed to int) // void ALU_any_result(result_t*); // stores value and flags (result may be either int or float) // int ALU_liberal_int(result_int_t*); // stores int value and flags. allows one '(' too many (for x- // indirect addressing). returns number of additional '(' (1 or 0). // bool ALU_optional_defined_int(intval_t*); // stores int value if given. Returns whether stored. // Throws error if undefined. // return int value (if result is undefined, returns zero) // It the result's "exists" flag is clear (=empty expression), it throws an // error. // If the result's "defined" flag is clear, result_is_undefined() is called. intval_t ALU_any_int(void) { result_t result; if(parse_expression(&result)) Throw_error(exception_paren_open); if((result.flags & MVALUE_EXISTS) == 0) Throw_error(exception_no_value); else if((result.flags & MVALUE_DEFINED) == 0) result_is_undefined(); if(result.flags & MVALUE_IS_FP) return(result.val.fpval); else return(result.val.intval); } // return int value (if result is undefined, serious error is thrown) intval_t ALU_defined_int(void) { result_t result; if(parse_expression(&result)) Throw_error(exception_paren_open); if((result.flags & MVALUE_DEFINED) == 0) Throw_serious_error(exception_undefined); if(result.flags & MVALUE_IS_FP) return(result.val.fpval); else return(result.val.intval); } // Store int value if given. Returns whether stored. Throws error if undefined. // This function needs either a defined value or no expression at all. So // empty expressions are accepted, but undefined ones are not. // If the result's "defined" flag is clear and the "exists" flag is set, it // throws a serious error and therefore stops assembly. bool ALU_optional_defined_int(intval_t* target) { result_t result; if(parse_expression(&result)) Throw_error(exception_paren_open); if((result.flags & MVALUE_GIVEN) == MVALUE_EXISTS) Throw_serious_error(exception_undefined); if((result.flags & MVALUE_EXISTS) == 0) return(FALSE); // something was given, so store if(result.flags & MVALUE_IS_FP) *target = result.val.fpval; else *target = result.val.intval; return(TRUE); } // Store int value and flags (floats are transformed to int) // It the result's "exists" flag is clear (=empty expression), it throws an // error. // If the result's "defined" flag is clear, result_is_undefined() is called. void ALU_int_result(result_int_t* intresult) { result_t result; if(parse_expression(&result)) Throw_error(exception_paren_open); if((result.flags & MVALUE_EXISTS) == 0) Throw_error(exception_no_value); else if((result.flags & MVALUE_DEFINED) == 0) result_is_undefined(); if(result.flags & MVALUE_IS_FP) { intresult->intval = result.val.fpval; intresult->flags = result.flags & ~MVALUE_IS_FP; } else { intresult->intval = result.val.intval; intresult->flags = result.flags; } } // Store int value and flags. // This function allows for one '(' too many. Needed when parsing indirect // addressing modes where internal indices have to be possible. Returns number // of parentheses still open (either 0 or 1). int ALU_liberal_int(result_int_t* intresult) { result_t result; int parentheses_still_open; parentheses_still_open = parse_expression(&result); if(parentheses_still_open > 1) { parentheses_still_open = 0; Throw_error(exception_paren_open); } if((result.flags & MVALUE_EXISTS) && ((result.flags & MVALUE_DEFINED) == 0)) result_is_undefined(); if(result.flags & MVALUE_IS_FP) { intresult->intval = result.val.fpval; intresult->flags = result.flags & ~MVALUE_IS_FP; } else { intresult->intval = result.val.intval; intresult->flags = result.flags; } return(parentheses_still_open); } // Store value and flags (result may be either int or float) // It the result's "exists" flag is clear (=empty expression), it throws an // error. // If the result's "defined" flag is clear, result_is_undefined() is called. void ALU_any_result(result_t* result) { if(parse_expression(result)) Throw_error(exception_paren_open); if((result->flags & MVALUE_EXISTS) == 0) Throw_error(exception_no_value); else if((result->flags & MVALUE_DEFINED) == 0) result_is_undefined(); } CheeseCutter-master/src/asm/alu.h000066400000000000000000000044531357241101300172360ustar00rootroot00000000000000// // ACME - a crossassembler for producing 6502/65c02/65816 code. // Copyright (C) 1998-2006 Marco Baye // Have a look at "acme.c" for further info // // ALU stuff (the expression parser) #ifndef alu_H #define alu_H #include "config.h" // Constants // Meaning of bits in "flags" of result_t and result_int_t structures: #define MVALUE_IS_FP (1u << 8) // Floating point value (never set in result_int_t) #define MVALUE_INDIRECT (1u << 7) // Needless parentheses indicate use of indirect addressing modes #define MVALUE_EXISTS (1u << 6) // 0: expression was empty. 1: there was *something* to parse. #define MVALUE_UNSURE (1u << 5) // Value once was related to undefined expression. Needed for producing // the same addresses in all passes; because in the first pass there // will almost for sure be labels that are undefined, you can't simply // get the addressing mode from looking at the parameter's value. #define MVALUE_DEFINED (1u << 4) // 0: undefined expression (value will be zero). 1: known result #define MVALUE_ISBYTE (1u << 3) // Value is guaranteed to fit in one byte #define MVALUE_FORCE24 (1u << 2) // Value usage forces 24-bit usage #define MVALUE_FORCE16 (1u << 1) // Value usage forces 16-bit usage #define MVALUE_FORCE08 (1u << 0) // Value usage forces 8-bit usage #define MVALUE_FORCEBITS (MVALUE_FORCE08|MVALUE_FORCE16|MVALUE_FORCE24) #define MVALUE_GIVEN (MVALUE_DEFINED | MVALUE_EXISTS) // Bit mask for fixed values (defined and existing) // Prototypes // create dynamic buffer, operator/function trees and operator/operand stacks extern void ALU_init(void); // Activate error output for "value undefined" extern void ALU_throw_errors(void); // returns int value (0 if result was undefined) extern intval_t ALU_any_int(void); // returns int value (if result was undefined, serious error is thrown) extern intval_t ALU_defined_int(void); // stores int value if given. Returns whether stored. Throws error if undefined. extern bool ALU_optional_defined_int(intval_t*); // stores int value and flags (floats are transformed to int) extern void ALU_int_result(result_int_t*); // stores int value and flags, allowing for one '(' too many (x-indirect addr) extern int ALU_liberal_int(result_int_t*); // stores value and flags (result may be either int or float) extern void ALU_any_result(result_t*); #endif CheeseCutter-master/src/asm/basics.c000066400000000000000000000130311357241101300177040ustar00rootroot00000000000000// // ACME - a crossassembler for producing 6502/65c02/65816 code. // Copyright (C) 1998-2006 Marco Baye // Have a look at "acme.c" for further info // // basic assembly stuff #include #include #include "config.h" #include "cpu.h" #include "basics.h" #include "alu.h" #include "dynabuf.h" #include "input.h" #include "global.h" #include "output.h" #include "tree.h" // Constants #define USERMSG_DYNABUF_INITIALSIZE 80 static const char s_08[] = "08"; #define s_8 (s_08+1) // Yes, I know I'm sick #define s_16 (s_65816+3) // Yes, I know I'm sick // Variables static dynabuf_t* user_message; // dynamic buffer (!warn/error/serious) // Functions // Helper function for !8, !16, !24 and !32 pseudo opcodes static enum eos_t output_objects(void (*fn)(intval_t)) { do fn(ALU_any_int()); while(Input_accept_comma()); return(ENSURE_EOS); } // Insert 8-bit values ("!08" / "!8" / "!by" / "!byte" pseudo opcode) static enum eos_t PO_08(void) { return(output_objects(Output_8b)); } // Insert 16-bit values ("!16" / "!wo" / "!word" pseudo opcode) static enum eos_t PO_16(void) { return(output_objects(Output_16b)); } // Insert 24-bit values ("!24" pseudo opcode) static enum eos_t PO_24(void) { return(output_objects(Output_24b)); } // Insert 32-bit values ("!32" pseudo opcode) static enum eos_t PO_32(void) { return(output_objects(Output_32b)); } // Include binary file static enum eos_t PO_binary(void) { FILE* fd; int byte; intval_t size = -1, // means "not given" => "until EOF" skip = 0; // if file name is missing, don't bother continuing if(Input_read_filename(TRUE)) return(SKIP_REMAINDER); // try to open file fd = fopen(GLOBALDYNABUF_CURRENT, FILE_READBINARY); if(fd == NULL) { Throw_error(exception_cannot_open_input_file); return(SKIP_REMAINDER); } // read optional arguments if(Input_accept_comma()) { if(ALU_optional_defined_int(&size) && (size <0)) Throw_serious_error("Negative size argument."); if(Input_accept_comma()) ALU_optional_defined_int(&skip);// read skip } // check whether including is a waste of time if((size >= 0) && (pass_undefined_count || pass_real_errors)) Output_fake(size); // really including is useless anyway else { // really insert file fseek(fd, skip, SEEK_SET); // set read pointer // if "size" non-negative, read "size" bytes. // otherwise, read until EOF. while(size != 0) { byte = getc(fd); if(byte == EOF) break; Output_byte(byte); size--; } // if more should have been read, warn and add padding if(size > 0) { Throw_warning("Padding with zeroes."); do Output_byte(0); while(--size); } } fclose(fd); // if verbose, produce some output if((pass_count == 0) && (Process_verbosity > 1)) printf("Loaded %d ($%x) bytes from file offset %ld ($%lx).\n", CPU_2add, CPU_2add, skip, skip); return(ENSURE_EOS); } // Reserve space by sending bytes of given value ("!fi" / "!fill" pseudo opcode) static enum eos_t PO_fill(void) { intval_t fill = FILLVALUE_FILL, size = ALU_defined_int(); if(Input_accept_comma()) fill = ALU_any_int(); while(size--) Output_8b(fill); return(ENSURE_EOS); } // show user-defined message static enum eos_t throw_string(const char prefix[], void (*fn)(const char*)) { result_t result; DYNABUF_CLEAR(user_message); DynaBuf_add_string(user_message, prefix); do { if(GotByte == '"') { // parse string GetQuotedByte(); // read initial character // send characters until closing quote is reached while(GotByte && (GotByte != '"')) { DYNABUF_APPEND(user_message, GotByte); GetQuotedByte(); } if(GotByte == CHAR_EOS) return(AT_EOS_ANYWAY); // after closing quote, proceed with next char GetByte(); } else { // parse value ALU_any_result(&result); if(result.flags & MVALUE_IS_FP) { // floating point if(result.flags & MVALUE_DEFINED) DynaBuf_add_double( user_message, result.val.fpval); else DynaBuf_add_string( user_message, ""); } else { // integer if(result.flags & MVALUE_DEFINED) DynaBuf_add_signed_long( user_message, result.val.intval); else DynaBuf_add_string( user_message, ""); } } } while(Input_accept_comma()); DynaBuf_append(user_message, '\0'); fn(user_message->buffer); return(ENSURE_EOS); } //// //static enum eos_t PO_print(void) { // return(throw_string()); //} // throw warning as given in source code static enum eos_t PO_warn(void) { return(throw_string("!warn: ", Throw_warning)); } // throw error as given in source code static enum eos_t PO_error(void) { return(throw_string("!error: ", Throw_error)); } // throw serious error as given in source code static enum eos_t PO_serious(void) { return(throw_string("!serious: ", Throw_serious_error)); } // pseudo ocpode table static node_t pseudo_opcodes[] = { PREDEFNODE(s_08, PO_08), PREDEFNODE(s_8, PO_08), PREDEFNODE("by", PO_08), PREDEFNODE("byte", PO_08), PREDEFNODE(s_16, PO_16), PREDEFNODE("wo", PO_16), PREDEFNODE("word", PO_16), PREDEFNODE("24", PO_24), PREDEFNODE("32", PO_32), PREDEFNODE("bin", PO_binary), PREDEFNODE("binary", PO_binary), PREDEFNODE("fi", PO_fill), PREDEFNODE("fill", PO_fill), // PREDEFNODE("print", PO_print), PREDEFNODE("warn", PO_warn), PREDEFNODE(s_error, PO_error), PREDEFLAST("serious", PO_serious), // ^^^^ this marks the last element }; // register pseudo opcodes and create dynamic buffer void Basics_init(void) { user_message = DynaBuf_create(USERMSG_DYNABUF_INITIALSIZE); Tree_add_table(&pseudo_opcode_tree, pseudo_opcodes); } CheeseCutter-master/src/asm/basics.h000066400000000000000000000005251357241101300177150ustar00rootroot00000000000000// // ACME - a crossassembler for producing 6502/65c02/65816 code. // Copyright (C) 1998-2006 Marco Baye // Have a look at "acme.c" for further info // // basic assembly stuff #ifndef basics_H #define basics_H #include "config.h" // Prototypes // register pseudo opcodes and create dynamic buffer extern void Basics_init(void); #endif CheeseCutter-master/src/asm/config.h000066400000000000000000000027701357241101300177220ustar00rootroot00000000000000// // ACME - a crossassembler for producing 6502/65c02/65816 code. // Copyright (C) 1998-2006 Marco Baye // Have a look at "acme.c" for further info // // Configuration #ifndef config_H #define config_H // types typedef unsigned int zone_t; typedef signed long intval_t; // at least 32 bits #define INTVAL_MAXCHARACTERS 11 // -2^32 takes 11 characters typedef unsigned long uintval_t; // just for logical shift right typedef struct node_ra_t node_ra_t; typedef struct node_t node_t; typedef struct label_t label_t; // result structure type definition with support for floating point struct result_t { int flags; // Expression flags union { intval_t intval; // integer value double fpval; // floating point value } val; // Expression value }; typedef struct result_t result_t; // either int or float // result structure type definition for int struct result_int_t { int flags; // Expression flags intval_t intval; // Expression value }; typedef struct result_int_t result_int_t; // always int, never float // Debugging flag, should be undefined in release version // #define FDEBUG // Maximum nesting depth of "!src" and macro calls // Is not actually a limitation, but a means of finding recursions #define MAX_NESTING 64 // Default value for output buffer #define FILLVALUE_INITIAL 0 // Default value for "!fill" #define FILLVALUE_FILL 0 // Nullpointer definition #ifndef NULL #define NULL ((void *)0) #endif // Boolean values #ifndef FALSE typedef int bool; #define FALSE 0 #define TRUE 1 #endif #endif CheeseCutter-master/src/asm/cpu.c000066400000000000000000000161761357241101300172440ustar00rootroot00000000000000// // ACME - a crossassembler for producing 6502/65c02/65816 code. // Copyright (C) 1998-2006 Marco Baye // Have a look at "acme.c" for further info // // CPU stuff #include "config.h" #include "alu.h" #include "cpu.h" #include "dynabuf.h" #include "global.h" #include "input.h" #include "mnemo.h" #include "output.h" #include "tree.h" // Constants static struct cpu_t CPU_6502 = { keyword_is_6502mnemo, NULL, // no long registers CPUFLAG_INDJMPBUGGY, // JMP ($xxFF) is buggy 234 // !align fills with "NOP" }; static struct cpu_t CPU_6510 = { keyword_is_6510mnemo, NULL, // no long registers CPUFLAG_INDJMPBUGGY, // JMP ($xxFF) is buggy 234 // !align fills with "NOP" }; static struct cpu_t CPU_65c02= { keyword_is_65c02mnemo, NULL, // no long registers 0, // no flags 234 // !align fills with "NOP" }; /* static struct cpu_t CPU_Rockwell65c02 = { keyword_is_Rockwell65c02mnemo, NULL, // no long registers 0, // no flags 234 // !align fills with "NOP" }; static struct cpu_t CPU_WDC65c02 = { keyword_is_WDC65c02mnemo, NULL, // no long registers 0, // no flags 234 // !align fills with "NOP" }; */ static bool long_of_65816[2]; // 65816 struct needs array of 2 bools static struct cpu_t CPU_65816 = { keyword_is_65816mnemo, long_of_65816, // two booleans for long accu/long regs 0, // no flags 234 // !align fills with "NOP" }; #define s_rl (s_brl+1) // Yes, I know I'm sick // Variables struct cpu_t *CPU_now; // Struct of current CPU type (default 6502) result_int_t CPU_pc; // (Pseudo) program counter at start of statement int CPU_2add; // Increase PC by this after statement static intval_t current_offset; // PseudoPC - MemIndex static bool uses_pseudo_pc; // offset assembly active? // predefined stuff static node_t* CPU_tree = NULL;// tree to hold CPU types static node_t CPUs[] = { // PREDEFNODE("z80", &CPU_Z80), PREDEFNODE("6502", &CPU_6502), PREDEFNODE("6510", &CPU_6510), PREDEFNODE("65c02", &CPU_65c02), // PREDEFNODE("Rockwell65c02", &CPU_Rockwell65c02), // PREDEFNODE("WDC65c02", &CPU_WDC65c02), PREDEFLAST(s_65816, &CPU_65816), // ^^^^ this marks the last element }; // Insert byte until PC fits condition static enum eos_t PO_align(void) { intval_t and, equal, fill, test = CPU_pc.intval; // make sure PC is defined. if((CPU_pc.flags & MVALUE_DEFINED) == 0) { Throw_error(exception_pc_undefined); CPU_pc.flags |= MVALUE_DEFINED; // do not complain again return(SKIP_REMAINDER); } and = ALU_defined_int(); if(!Input_accept_comma()) Throw_error(exception_syntax); equal = ALU_defined_int(); if(Input_accept_comma()) fill = ALU_any_int(); else fill = CPU_now->default_align_value; while((test++ & and) != equal) Output_8b(fill); return(ENSURE_EOS); } // Try to find CPU type held in DynaBuf. Returns whether succeeded. bool CPU_find_cpu_struct(struct cpu_t** target) { void* node_body; if(!Tree_easy_scan(CPU_tree, &node_body, GlobalDynaBuf)) return(FALSE); *target = node_body; return(TRUE); } // Select CPU ("!cpu" pseudo opcode) static enum eos_t PO_cpu(void) { struct cpu_t* cpu_buffer = CPU_now; // remember current cpu if(Input_read_and_lower_keyword()) if(!CPU_find_cpu_struct(&CPU_now)) Throw_error("Unknown processor."); // If there's a block, parse that and then restore old value! if(Parse_optional_block()) CPU_now = cpu_buffer; return(ENSURE_EOS); } static const char Warning_old_offset_assembly[] = "\"!pseudopc/!realpc\" is deprecated; use \"!pseudopc {}\" instead."; // Start offset assembly static enum eos_t PO_pseudopc(void) { bool outer_state = uses_pseudo_pc; intval_t new_pc, outer_offset = current_offset; int outer_flags = CPU_pc.flags; // set new new_pc = ALU_defined_int(); current_offset = (current_offset + new_pc - CPU_pc.intval) & 0xffff; CPU_pc.intval = new_pc; CPU_pc.flags |= MVALUE_DEFINED; uses_pseudo_pc = TRUE; // If there's a block, parse that and then restore old value! if(Parse_optional_block()) { // restore old uses_pseudo_pc = outer_state; CPU_pc.flags = outer_flags; CPU_pc.intval = (outer_offset + CPU_pc.intval - current_offset) & 0xffff; current_offset = outer_offset; } else Throw_first_pass_warning(Warning_old_offset_assembly); return(ENSURE_EOS); } // End offset assembly static enum eos_t PO_realpc(void) { Throw_first_pass_warning(Warning_old_offset_assembly); // deactivate offset assembly CPU_pc.intval = (CPU_pc.intval - current_offset) & 0xffff; current_offset = 0; uses_pseudo_pc = FALSE; return(ENSURE_EOS); } // return whether offset assembly is active bool CPU_uses_pseudo_pc(void) { return(uses_pseudo_pc); } // If cpu type and value match, set register length variable to value. // If cpu type and value don't match, complain instead. static void check_and_set_reg_length(bool *var, bool long_reg) { if(long_reg && ((CPU_now->long_regs) == NULL)) Throw_error("Chosen CPU does not support long registers."); else *var = long_reg; } // Set register length, block-wise if needed. static enum eos_t set_register_length(bool *var, bool long_reg) { bool buffer = *var; // Set new register length (or complain - whichever is more fitting) check_and_set_reg_length(var, long_reg); // If there's a block, parse that and then restore old value! if(Parse_optional_block()) check_and_set_reg_length(var, buffer);// restore old length return(ENSURE_EOS); } // Switch to long accu ("!al" pseudo opcode) static enum eos_t PO_al(void) { return(set_register_length(CPU_now->long_regs + LONGREG_IDX_A, TRUE)); } // Switch to short accu ("!as" pseudo opcode) static enum eos_t PO_as(void) { return(set_register_length(CPU_now->long_regs + LONGREG_IDX_A, FALSE)); } // Switch to long index registers ("!rl" pseudo opcode) static enum eos_t PO_rl(void) { return(set_register_length(CPU_now->long_regs + LONGREG_IDX_R, TRUE)); } // Switch to short index registers ("!rs" pseudo opcode) static enum eos_t PO_rs(void) { return(set_register_length(CPU_now->long_regs + LONGREG_IDX_R, FALSE)); } // pseudo opcode table static node_t pseudo_opcodes[] = { PREDEFNODE("align", PO_align), PREDEFNODE("cpu", PO_cpu), PREDEFNODE("pseudopc", PO_pseudopc), PREDEFNODE("realpc", PO_realpc), PREDEFNODE("al", PO_al), PREDEFNODE("as", PO_as), PREDEFNODE(s_rl, PO_rl), PREDEFLAST("rs", PO_rs), // ^^^^ this marks the last element }; // Set default values for pass void CPU_passinit(struct cpu_t* cpu_type) { // handle cpu type (default is 6502) CPU_now = cpu_type ? cpu_type : &CPU_6502; CPU_pc.flags = 0; // not defined yet CPU_pc.intval = 512; // actually, there should be no need to init CPU_2add = 0; // Increase PC by this at end of statement CPU_65816.long_regs[LONGREG_IDX_A] = FALSE; // short accu CPU_65816.long_regs[LONGREG_IDX_R] = FALSE; // short index regs uses_pseudo_pc = FALSE; // offset assembly is not active, current_offset = 0; // so offset is 0 } // create cpu type tree (is done early) void CPUtype_init(void) { Tree_add_table(&CPU_tree, CPUs); } // register pseudo opcodes (done later) void CPU_init(void) { Tree_add_table(&pseudo_opcode_tree, pseudo_opcodes); } // set program counter to defined value void CPU_set_pc(intval_t new_pc) { CPU_pc.flags |= MVALUE_DEFINED; CPU_pc.intval = new_pc; } CheeseCutter-master/src/asm/cpu.h000066400000000000000000000025711357241101300172430ustar00rootroot00000000000000// // ACME - a crossassembler for producing 6502/65c02/65816 code. // Copyright (C) 1998-2006 Marco Baye // Have a look at "acme.c" for further info // // CPU stuff #ifndef cpu_H #define cpu_H #include "config.h" // CPU type structure definition struct cpu_t { // This function is not allowed to change GlobalDynaBuf // because that's where the mnemonic is stored! bool (*keyword_is_mnemonic)(int); bool* long_regs; // pointer to array of bool: #define LONGREG_IDX_A 0 // array index for "long accu" bool #define LONGREG_IDX_R 1 // array index for "long index regs" bool int flags; char default_align_value; }; #define CPUFLAG_INDJMPBUGGY (1u << 0) // Variables extern struct cpu_t *CPU_now;// Struct of current CPU type (default 6502) extern result_int_t CPU_pc; // Current program counter (pseudo value) extern int CPU_2add; // add to PC after statement // Prototypes // create cpu type tree (is done early) extern void CPUtype_init(void); // register pseudo opcodes (done later) extern void CPU_init(void); // Set default values for pass extern void CPU_passinit(struct cpu_t* cpu_type); // set program counter to defined value extern void CPU_set_pc(intval_t new_pc); // Try to find CPU type held in DynaBuf. Returns whether succeeded. extern bool CPU_find_cpu_struct(struct cpu_t** target); // return whether offset assembly is active extern bool CPU_uses_pseudo_pc(void); #endif CheeseCutter-master/src/asm/dynabuf.c000066400000000000000000000077431357241101300201050ustar00rootroot00000000000000// // ACME - a crossassembler for producing 6502/65c02/65816 code. // Copyright (C) 1998-2006 Marco Baye // Have a look at "acme.c" for further info // // Dynamic buffer stuff #include #include #include #include "acme.h" #include "global.h" #include "dynabuf.h" #include "input.h" // Constants and macros // macro to grow dynabuf (CAUTION - fails if a < 1) #define MAKE_LARGER_THAN(a) (2*(a)) // if someone requests a dynabuf smaller than this, use this size instead #define DYNABUF_MINIMUM_INITIALSIZE 128 // should be >0 (see above) // initial size for global dynabuf // (as it holds macros, loop bodies, etc., make it large to begin with) #define GLOBALDYNABUF_INITIALSIZE 1024 // should be >0 (see above) // Variables dynabuf_t* GlobalDynaBuf; // global dynamic buffer // Functions // get new buffer of given size static void resize(dynabuf_t* db, size_t new_size) { char* new_buf; new_buf = realloc(db->buffer, new_size); if(new_buf == NULL) Throw_serious_error(exception_no_memory_left); db->reserved = new_size; db->buffer = new_buf; } // Exported functions // Create and init a dynamic buffer and return pointer dynabuf_t* DynaBuf_create(int initial_size) { dynabuf_t* db; if(initial_size < DYNABUF_MINIMUM_INITIALSIZE) initial_size = DYNABUF_MINIMUM_INITIALSIZE; if((db = malloc(sizeof(dynabuf_t)))) { db->size = 0; db->reserved = initial_size; db->buffer = malloc(initial_size); if(db->buffer) return(db);// if both pointers are != NULL, no error } // otherwise, complain fputs("Error: No memory for dynamic buffer.\n", stderr); exit(EXIT_FAILURE); } // Enlarge buffer void DynaBuf_enlarge(dynabuf_t* db) { resize(db, MAKE_LARGER_THAN(db->reserved)); } // Claim enough memory to hold a copy of the current buffer contents, // make that copy and return it. // The copy must be released by calling free(). char* DynaBuf_get_copy(dynabuf_t* db) { char *copy; copy = safe_malloc(db->size); memcpy(copy, db->buffer, db->size); return(copy); } // add char to buffer void DynaBuf_append(dynabuf_t* db, char byte) { DYNABUF_APPEND(db, byte); } // Append string to buffer (without terminator) void DynaBuf_add_string(dynabuf_t* db, const char* string) { char byte; while((byte = *string++)) DYNABUF_APPEND(db, byte); } // make sure DynaBuf is large enough to take "size" more bytes // return pointer to end of current contents static char* ensure_free_space(dynabuf_t* db, int size) { while((db->reserved - db->size) < size) resize(db, MAKE_LARGER_THAN(db->reserved)); return(db->buffer + db->size); } // add string version of int to buffer (without terminator) void DynaBuf_add_signed_long(dynabuf_t* db, signed long value) { char *write = ensure_free_space(db, INTVAL_MAXCHARACTERS + 1); db->size += sprintf(write, "%ld", value); } // add string version of float to buffer (without terminator) void DynaBuf_add_double(dynabuf_t* db, double value) { char *write = ensure_free_space(db, 40); // reserve 40 chars // write up to 30 significant characters. remaining 10 should suffice // for sign, decimal point, exponent, terminator etc. db->size += sprintf(write, "%.30g", value); } // Convert buffer contents to lower case (target and source may be identical) void DynaBuf_to_lower(dynabuf_t* target, dynabuf_t* source) { char *read, *write; // make sure target can take it if(source->size > target->reserved) resize(target, source->size); // convert to lower case read = source->buffer;// CAUTION - ptr may change when buf grows! write = target->buffer;// CAUTION - ptr may change when buf grows! while(*read) *write++ = (*read++) | 32; // Okay, so this method of converting to lowercase is lousy. // But actually it doesn't matter, because only pre-defined // keywords are converted, and all of those are plain // old-fashioned 7-bit ASCII anyway. So I guess it'll do. *write = '\0'; // terminate } // Initialisation - allocate global dynamic buffer void DynaBuf_init(void) { GlobalDynaBuf = DynaBuf_create(GLOBALDYNABUF_INITIALSIZE); } CheeseCutter-master/src/asm/dynabuf.h000066400000000000000000000034671357241101300201110ustar00rootroot00000000000000// // ACME - a crossassembler for producing 6502/65c02/65816 code. // Copyright (C) 1998-2006 Marco Baye // Have a look at "acme.c" for further info // // Dynamic buffer stuff #ifndef dynabuf_H #define dynabuf_H #include "config.h" // Macros #define DYNABUF_CLEAR(db) {db->size = 0;} #define DYNABUF_APPEND(db, byte) do {\ if(db->size == db->reserved)\ DynaBuf_enlarge(db);\ db->buffer[(db->size)++] = byte;\ } while(0) // The next one is dangerous - the buffer location can change when a character // is appended. So after calling this, don't change the buffer as long as you // use the address. #define GLOBALDYNABUF_CURRENT (GlobalDynaBuf->buffer) // dynamic buffer structure struct dynabuf_t { char* buffer; // pointer to buffer int size; // size of buffer's used portion int reserved; // total size of buffer }; typedef struct dynabuf_t dynabuf_t; // Variables extern dynabuf_t* GlobalDynaBuf; // global dynamic buffer // Prototypes // create global DynaBuf (call once on program startup) extern void DynaBuf_init(void); // create (private) DynaBuf extern dynabuf_t* DynaBuf_create(int initial_size); // call whenever buffer is too small extern void DynaBuf_enlarge(dynabuf_t* db); // return malloc'd copy of buffer contents extern char* DynaBuf_get_copy(dynabuf_t* db); // copy string to buffer (without terminator) extern void DynaBuf_add_string(dynabuf_t* db, const char*); // add string version of int to buffer (without terminator) extern void DynaBuf_add_signed_long(dynabuf_t* db, signed long value); // add string version of float to buffer (without terminator) extern void DynaBuf_add_double(dynabuf_t* db, double value); // converts buffer contents to lower case extern void DynaBuf_to_lower(dynabuf_t* target, dynabuf_t* source); // add char to buffer extern void DynaBuf_append(dynabuf_t* db, char); #endif CheeseCutter-master/src/asm/encoding.c000066400000000000000000000147541357241101300202430ustar00rootroot00000000000000// // ACME - a crossassembler for producing 6502/65c02/65816 code. // Copyright (C) 1998-2006 Marco Baye // Have a look at "acme.c" for further info // // Character encoding stuff #include #include #include "alu.h" #include "acme.h" #include "dynabuf.h" #include "encoding.h" #include "global.h" #include "output.h" #include "input.h" #include "tree.h" // Encoder function type definition typedef char (*encoder_t)(char) ; // Constants static const char s_pet[] = "pet"; static const char s_raw[] = "raw"; static const char s_scr[] = "scr"; // Variables static char outermost_table[256]; // space for encoding table... static char* loaded_table = outermost_table; // ...loaded from file // predefined stuff static node_t* encoder_tree = NULL; // tree to hold encoders // Functions // convert character using current encoding // Conversion function pointer. No init needed: gets set before each pass. char (*Encoding_encode_char)(char); // Insert string(s) static enum eos_t encode_string(encoder_t inner_encoder, char eor) { encoder_t outer_encoder = Encoding_encode_char;// buffer encoder // make given encoder the current one (for ALU-parsed values) Encoding_encode_char = inner_encoder; do { if(GotByte == '"') { // read initial character GetQuotedByte(); // send characters until closing quote is reached while(GotByte && (GotByte != '"')) { Output_8b(eor ^ Encoding_encode_char(GotByte)); GetQuotedByte(); } if(GotByte == CHAR_EOS) return(AT_EOS_ANYWAY); // after closing quote, proceed with next char GetByte(); } else { // Parse value. No problems with single characters // because the current encoding is // temporarily set to the given one. Output_8b(ALU_any_int()); } } while(Input_accept_comma()); Encoding_encode_char = outer_encoder; // reactivate buffered encoder return(ENSURE_EOS); } // Insert text string (default format) static enum eos_t PO_text(void) { return(encode_string(Encoding_encode_char, 0)); } // convert raw to raw (do not convert at all) static char encoder_raw(char byte) { return(byte); } // Insert raw string static enum eos_t PO_raw(void) { return(encode_string(encoder_raw, 0)); } // convert raw to petscii static char encoder_pet(char byte) { if((byte >= 'A') && (byte <= 'Z')) return((char) (byte | 0x80)); // FIXME - check why SAS-C if((byte >= 'a') && (byte <= 'z')) // wants these casts. return((char)(byte - 32)); // There are more below. return(byte); } // Insert PetSCII string static enum eos_t PO_pet(void) { return(encode_string(encoder_pet, 0)); } // convert raw to C64 screencode static char encoder_scr(char byte) { if((byte >= 'a') && (byte <= 'z')) return((char)(byte - 96)); // shift uppercase down if((byte >= '[') && (byte <= '_')) return((char)(byte - 64)); // shift [\]^_ down if(byte == '`') return(64); // shift ` down if(byte == '@') return(0); // shift @ down return(byte); } // Insert screencode string static enum eos_t PO_scr(void) { return(encode_string(encoder_scr, 0)); } // Insert screencode string, EOR'd static enum eos_t PO_scrxor(void) { intval_t num = ALU_any_int(); if(Input_accept_comma()) return(encode_string(encoder_scr, num)); Throw_error(exception_syntax); return(SKIP_REMAINDER); } // Switch to CBM mode ("!cbm" pseudo opcode) static enum eos_t PO_cbm(void) { Encoding_encode_char = encoder_pet; // output deprecation warning Throw_first_pass_warning("\"!cbm\" is deprecated; use \"!ct pet\" instead."); return(ENSURE_EOS); } // static char encoder_file(char byte) { return(loaded_table[(unsigned char) byte]); } // read encoding table from file static enum eos_t user_defined_encoding(void) { FILE* fd; char local_table[256], *buffered_table = loaded_table; encoder_t buffered_encoder = Encoding_encode_char; // if file name is missing, don't bother continuing if(Input_read_filename(TRUE)) return(SKIP_REMAINDER); fd = fopen(GLOBALDYNABUF_CURRENT, FILE_READBINARY); if(fd) { if(fread(local_table, sizeof(char), 256, fd) != 256) Throw_error("Conversion table incomplete."); fclose(fd); } else Throw_error(exception_cannot_open_input_file); Encoding_encode_char = encoder_file; // activate new encoding loaded_table = local_table; // activate local table // If there's a block, parse that and then restore old values if(Parse_optional_block()) Encoding_encode_char = buffered_encoder; else // if there's *no* block, the table must be used from now on. // copy the local table to the "outer" table memcpy(buffered_table, local_table, 256); // re-activate "outer" table (it might have been changed by memcpy()) loaded_table = buffered_table; return(ENSURE_EOS); } // use one of the pre-defined encodings (raw, pet, scr) static enum eos_t predefined_encoding(void) { void* node_body; char local_table[256], *buffered_table = loaded_table; encoder_t buffered_encoder = Encoding_encode_char; // use one of the pre-defined encodings if(Input_read_and_lower_keyword()) { // search for tree item if(Tree_easy_scan(encoder_tree, &node_body, GlobalDynaBuf)) Encoding_encode_char = (encoder_t) node_body;// activate new encoder else Throw_error("Unknown encoding."); } loaded_table = local_table; // activate local table // If there's a block, parse that and then restore old values if(Parse_optional_block()) Encoding_encode_char = buffered_encoder; // re-activate "outer" table loaded_table = buffered_table; return(ENSURE_EOS); } // Set current encoding ("!convtab" pseudo opcode) static enum eos_t PO_convtab(void) { if((GotByte == '<') || (GotByte == '"')) return(user_defined_encoding()); else return(predefined_encoding()); } // pseudo opcode table static node_t pseudo_opcodes[] = { PREDEFNODE(s_cbm, PO_cbm), PREDEFNODE("ct", PO_convtab), PREDEFNODE("convtab", PO_convtab), PREDEFNODE(s_pet, PO_pet), PREDEFNODE(s_raw, PO_raw), PREDEFNODE(s_scr, PO_scr), PREDEFNODE(s_scrxor, PO_scrxor), PREDEFNODE("text", PO_text), PREDEFLAST("tx", PO_text), // ^^^^ this marks the last element }; // keywords for "!convtab" pseudo opcode static node_t encoders[] = { PREDEFNODE(s_pet, encoder_pet), PREDEFNODE(s_raw, encoder_raw), PREDEFLAST(s_scr, encoder_scr), // ^^^^ this marks the last element }; // Exported functions // register pseudo opcodes and build keyword tree for encoders void Encoding_init(void) { Tree_add_table(&encoder_tree, encoders); Tree_add_table(&pseudo_opcode_tree, pseudo_opcodes); } // Set "raw" as default encoding void Encoding_passinit(void) { Encoding_encode_char = encoder_raw; } CheeseCutter-master/src/asm/encoding.h000066400000000000000000000007611357241101300202410ustar00rootroot00000000000000// // ACME - a crossassembler for producing 6502/65c02/65816 code. // Copyright (C) 1998-2006 Marco Baye // Have a look at "acme.c" for further info // // Character encoding stuff #ifndef encoding_H #define encoding_H // Prototypes // register pseudo opcodes and build keyword tree for encoders extern void Encoding_init(void); // convert character using current encoding extern char (*Encoding_encode_char)(char); // Set "raw" as default encoding extern void Encoding_passinit(void); #endif CheeseCutter-master/src/asm/flow.c000066400000000000000000000300231357241101300174070ustar00rootroot00000000000000// // ACME - a crossassembler for producing 6502/65c02/65816 code. // Copyright (C) 1998-2006 Marco Baye // Have a look at "acme.c" for further info // // Flow control stuff (loops, conditional assembly etc.) // // Macros, conditional assembly, loops and sourcefile-includes are all based on // parsing blocks of code. When defining macros or using loops or conditional // assembly, the block starts with "{" and ends with "}". In the case of // "!source", the given file is treated like a block - the outermost assembler // function uses the same technique to parse the top level file. #include #include "acme.h" #include "alu.h" #include "config.h" #include "dynabuf.h" #include "global.h" #include "input.h" #include "label.h" #include "macro.h" #include "mnemo.h" #include "tree.h" // type definitions enum cond_key_t { ID_UNTIL, // Handles to store instead of ID_WHILE, // the UNTIL and WHILE keywords }; typedef struct { enum cond_key_t type; // either ID_UNTIL or ID_WHILE int line; // original line number char* body; // pointer to actual expression } loopcond_t; // Variables // predefined stuff static node_t* condkey_tree = NULL;// tree to hold UNTIL and WHILE static node_t condkeys[] = { PREDEFNODE("until", ID_UNTIL), PREDEFLAST("while", ID_WHILE), // ^^^^ this marks the last element }; // Helper functions for "!for" and "!do" // Parse a loop body (could also be used for macro body) static void parse_ram_block(int line_number, char* body) { Input_now->line_number = line_number;// set line number to loop start Input_now->src.ram_ptr = body;// set RAM read pointer to loop // Parse loop body Parse_until_eob_or_eof(); if(GotByte != CHAR_EOB) Bug_found("IllegalBlockTerminator", GotByte); } // Try to read a condition into DynaBuf and store copy pointer in // given loopcond_t structure. // If no condition given, NULL is written to structure. // Call with GotByte = first interesting character static void store_condition(loopcond_t* condition, char terminator) { void* node_body; // write line number condition->line = Input_now->line_number; // Check for empty condition if(GotByte == terminator) { // Write NULL condition, then return condition->body = NULL; return; } // Seems as if there really *is* a condition. // Read UNTIL/WHILE keyword if(Input_read_and_lower_keyword()) { // Search for new tree item if(!Tree_easy_scan(condkey_tree, &node_body, GlobalDynaBuf)) { Throw_error(exception_syntax); condition->body = NULL; return; } condition->type = (enum cond_key_t) node_body; // Write given condition into buffer SKIPSPACE(); DYNABUF_CLEAR(GlobalDynaBuf); Input_until_terminator(terminator); DynaBuf_append(GlobalDynaBuf, CHAR_EOS);// ensure terminator condition->body = DynaBuf_get_copy(GlobalDynaBuf); } return; } // Check a condition expression static bool check_condition(loopcond_t* condition) { intval_t expression; // First, check whether there actually *is* a condition if(condition->body == NULL) return(TRUE); // non-existant conditions are always true // set up input for expression evaluation Input_now->line_number = condition->line; Input_now->src.ram_ptr = condition->body; GetByte(); // proceed with next char expression = ALU_defined_int(); if(GotByte) Throw_serious_error(exception_syntax); if(condition->type == ID_UNTIL) return(!expression); return(!!expression); } // Looping assembly ("!do"). Has to be re-entrant. static enum eos_t PO_do(void) { // Now GotByte = illegal char loopcond_t condition1, condition2; input_t loop_input, *outer_input; char* loop_body; bool go_on; int loop_start;// line number of loop pseudo opcode // Read head condition to buffer SKIPSPACE(); store_condition(&condition1, CHAR_SOB); if(GotByte != CHAR_SOB) Throw_serious_error(exception_no_left_brace); // Remember line number of loop body, // then read block and get copy loop_start = Input_now->line_number; loop_body = Input_skip_or_store_block(TRUE); // changes line number! // now GotByte = '}' NEXTANDSKIPSPACE();// Now GotByte = first non-blank char after block // Read tail condition to buffer store_condition(&condition2, CHAR_EOS); // now GotByte = CHAR_EOS // set up new input loop_input = *Input_now;// copy current input structure into new loop_input.source_is_ram = TRUE; // set new byte source // remember old input outer_input = Input_now; // activate new input (not useable yet, as pointer and // line number are not yet set up) Input_now = &loop_input; do { // Check head condition go_on = check_condition(&condition1); if(go_on) { parse_ram_block(loop_start, loop_body); // Check tail condition go_on = check_condition(&condition2); } } while(go_on); // Free memory free(condition1.body); free(loop_body); free(condition2.body); // restore previous input: Input_now = outer_input; GotByte = CHAR_EOS; // CAUTION! Very ugly kluge. // But by switching input, we lost the outer input's GotByte. We know // it was CHAR_EOS. We could just call GetByte() to get real input, but // then the main loop could choke on unexpected bytes. So we pretend // that we got the outer input's GotByte value magically back. return(AT_EOS_ANYWAY); } // Looping assembly ("!for"). Has to be re-entrant. static enum eos_t PO_for(void) {// Now GotByte = illegal char input_t loop_input, *outer_input; result_t loop_counter; intval_t maximum; char* loop_body;// pointer to loop's body block label_t* label; zone_t zone; int force_bit, loop_start;// line number of "!for" pseudo opcode if(Input_read_zone_and_keyword(&zone) == 0) // skips spaces before return(SKIP_REMAINDER); // Now GotByte = illegal char force_bit = Input_get_force_bit(); // skips spaces after label = Label_find(zone, force_bit); if(Input_accept_comma() == FALSE) { Throw_error(exception_syntax); return(SKIP_REMAINDER); } maximum = ALU_defined_int(); if(maximum < 0) Throw_serious_error("Loop count is negative."); if(GotByte != CHAR_SOB) Throw_serious_error(exception_no_left_brace); // remember line number of loop pseudo opcode loop_start = Input_now->line_number; // read loop body into DynaBuf and get copy loop_body = Input_skip_or_store_block(TRUE); // changes line number! // switching input makes us lose GotByte. But we know it's '}' anyway! // set up new input loop_input = *Input_now;// copy current input structure into new loop_input.source_is_ram = TRUE; // set new byte source // remember old input outer_input = Input_now; // activate new input // (not yet useable; pointer and line number are still missing) Input_now = &loop_input; // init counter loop_counter.flags = MVALUE_DEFINED | MVALUE_EXISTS; loop_counter.val.intval = 0; // if count == 0, skip loop if(maximum) { do { loop_counter.val.intval++;// increment counter Label_set_value(label, &loop_counter, TRUE); parse_ram_block(loop_start, loop_body); } while(loop_counter.val.intval < maximum); } else Label_set_value(label, &loop_counter, TRUE); // Free memory free(loop_body); // restore previous input: Input_now = outer_input; // GotByte of OuterInput would be '}' (if it would still exist) GetByte(); // fetch next byte return(ENSURE_EOS); } // Helper functions for "!if" and "!ifdef" // Parse or skip a block. Returns whether block's '}' terminator was missing. // Afterwards: GotByte = '}' static bool skip_or_parse_block(bool parse) { if(!parse) { Input_skip_or_store_block(FALSE); return(FALSE); } // if block was correctly terminated, return FALSE Parse_until_eob_or_eof(); // if block isn't correctly terminated, complain and exit if(GotByte != CHAR_EOB) Throw_serious_error(exception_no_right_brace); return(FALSE); } // Parse {block} [else {block}] static void parse_block_else_block(bool parse_first) { // Parse first block. // If it's not correctly terminated, return immediately (because // in that case, there's no use in checking for an "else" part). if(skip_or_parse_block(parse_first)) return; // now GotByte = '}'. Check for "else" part. // If end of statement, return immediately. NEXTANDSKIPSPACE(); if(GotByte == CHAR_EOS) return; // read keyword and check whether really "else" if(Input_read_and_lower_keyword()) { if(strcmp(GlobalDynaBuf->buffer, "else")) Throw_error(exception_syntax); else { SKIPSPACE(); if(GotByte != CHAR_SOB) Throw_serious_error(exception_no_left_brace); skip_or_parse_block(!parse_first); // now GotByte = '}' GetByte(); } } Input_ensure_EOS(); } // Conditional assembly ("!if"). Has to be re-entrant. static enum eos_t PO_if(void) {// Now GotByte = illegal char intval_t cond; cond = ALU_defined_int(); if(GotByte != CHAR_SOB) Throw_serious_error(exception_no_left_brace); parse_block_else_block(!!cond); return(ENSURE_EOS); } // Conditional assembly ("!ifdef"). Has to be re-entrant. static enum eos_t PO_ifdef(void) {// Now GotByte = illegal char node_ra_t* node; label_t* label; zone_t zone; bool defined = FALSE; if(Input_read_zone_and_keyword(&zone) == 0) // skips spaces before return(SKIP_REMAINDER); Tree_hard_scan(&node, Label_forest, zone, FALSE); if(node) { label = (label_t*) node->body; // in first pass, count usage if(pass_count == 0) label->usage++; if(label->result.flags & MVALUE_DEFINED) defined = TRUE; } SKIPSPACE(); if(GotByte == CHAR_SOB) parse_block_else_block(defined); else { if(defined) return(PARSE_REMAINDER); return(SKIP_REMAINDER); } return(ENSURE_EOS); } // Macro definition ("!macro"). static enum eos_t PO_macro(void) {// Now GotByte = illegal char // In first pass, parse. In all other passes, skip. if(pass_count == 0) Macro_parse_definition(); // now GotByte = '}' else { // skip until CHAR_SOB ('{') is found. // no need to check for end-of-statement, because such an // error would already have been detected in first pass. // for the same reason, there is no need to check for quotes. while(GotByte != CHAR_SOB) GetByte(); Input_skip_or_store_block(FALSE); // now GotByte = '}' } GetByte(); // Proceed with next character return(ENSURE_EOS); } // Parse a whole source code file void Parse_source(char *source) { // be verbose if(Process_verbosity > 2) printf("Parsing source file!\n"); // set up new input Input_new_file(source); // Parse block and check end reason Parse_until_eob_or_eof(); if(GotByte != CHAR_EOF) Throw_error("Found '}' instead of end-of-file."); // close sublevel src //fclose(Input_now->src.fd); } // Include source file ("!source" or "!src"). Has to be re-entrant. static enum eos_t PO_source(void) {// Now GotByte = illegal char Throw_error("PO_SOURCE not implemented"); return 0; } /* static enum eos_t X_PO_source(void) {// Now GotByte = illegal char FILE* fd; char local_gotbyte; input_t new_input, *outer_input; // Enter new nesting level. // Quit program if recursion too deep. if(--source_recursions_left < 0) Throw_serious_error("Too deeply nested. Recursive \"!source\"?"); // Read file name. Quit function on error. if(Input_read_filename(TRUE)) return(SKIP_REMAINDER); // If file could be opened, parse it. Otherwise, complain. if((fd = fopen(GLOBALDYNABUF_CURRENT, FILE_READBINARY))) { char filename[GlobalDynaBuf->size]; strcpy(filename, GLOBALDYNABUF_CURRENT); outer_input = Input_now;// remember old input local_gotbyte = GotByte;// CAUTION - ugly kluge Input_now = &new_input;// activate new input Parse_and_close_file(fd, filename); Input_now = outer_input;// restore previous input GotByte = local_gotbyte;// CAUTION - ugly kluge } else Throw_error(exception_cannot_open_input_file); // Leave nesting level source_recursions_left++; return(ENSURE_EOS); } */ // pseudo opcode table static node_t pseudo_opcodes[] = { PREDEFNODE("do", PO_do), PREDEFNODE("for", PO_for), PREDEFNODE("if", PO_if), PREDEFNODE("ifdef", PO_ifdef), PREDEFNODE("macro", PO_macro), PREDEFNODE("source", PO_source), PREDEFLAST("src", PO_source), // ^^^^ this marks the last element }; // register pseudo opcodes and build keyword tree for until/while void Flow_init(void) { Tree_add_table(&condkey_tree, condkeys); Tree_add_table(&pseudo_opcode_tree, pseudo_opcodes); } CheeseCutter-master/src/asm/flow.h000066400000000000000000000007311357241101300174170ustar00rootroot00000000000000// // ACME - a crossassembler for producing 6502/65c02/65816 code. // Copyright (C) 1998-2006 Marco Baye // Have a look at "acme.c" for further info // // Flow control stuff (loops, conditional assembly etc.) #ifndef flow_H #define flow_H #include #include "config.h" // Prototypes // register pseudo opcodes and build keyword tree for until/while extern void Flow_init(void); // Parse a whole source code file extern void Parse_source(const char*); #endif CheeseCutter-master/src/asm/global.c000066400000000000000000000305621357241101300177100ustar00rootroot00000000000000// // ACME - a crossassembler for producing 6502/65c02/65816 code. // Copyright (C) 1998-2006 Marco Baye // Have a look at "acme.c" for further info // // Global stuff - things that are needed by several modules // 4 Oct 2006 Fixed a typo in a comment #include #include #include "platform.h" // done first in case "inline" is redefined #include "acme.h" #include "cpu.h" #include "dynabuf.h" #include "global.h" #include "input.h" #include "label.h" #include "macro.h" #include "output.h" #include "section.h" #include "tree.h" // Constants const char s_65816[] = "65816"; const char s_and[] = "and"; const char s_asl[] = "asl"; const char s_asr[] = "asr"; const char s_brl[] = "brl"; const char s_cbm[] = "cbm"; const char s_eor[] = "eor"; const char s_error[] = "error"; const char s_lsr[] = "lsr"; const char s_scrxor[] = "scrxor"; // Exception messages during assembly const char exception_cannot_open_input_file[] = "Cannot open input file."; const char exception_missing_string[] = "No string given."; const char exception_no_left_brace[] = "Missing '{'."; const char exception_no_memory_left[] = "Out of memory."; const char exception_no_right_brace[]= "Found end-of-file instead of '}'."; //const char exception_not_yet[] = "Sorry, feature not yet implemented."; const char exception_number_out_of_range[] = "Number out of range."; const char exception_pc_undefined[] = "Program counter undefined."; const char exception_syntax[] = "Syntax error."; // default value for number of errors before exiting #define MAXERRORS 10 // Flag table: // This table contains flags for all the 256 possible byte values. The // assembler reads the table whenever it needs to know whether a byte is // allowed to be in a label name, for example. // Bits Meaning when set // 7....... Byte allowed to start keyword // .6...... Byte allowed in keyword // ..5..... Byte is upper case, can be lowercased by OR-ing this bit(!) // ...4.... special character for input syntax: 0x00 TAB LF CR SPC : ; } // ....3... preceding sequence of '-' characters is anonymous backward // label. Currently only set for ')', ',' and CHAR_EOS. // .....210 unused const char Byte_flags[256] = { /*$00*/ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,// control characters 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*$20*/ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,// " !"#$%&'" 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,// "()*+,-./" 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,// "01234567" 0x40, 0x40, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,// "89:;<=>?" /*$40*/ 0x00, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0,// "@ABCDEFG" 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0,// "HIJKLMNO" 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0,// "PQRSTUVW" 0xe0, 0xe0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0xc0,// "XYZ[\]^_" /*$60*/ 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,// "`abcdefg" 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,// "hijklmno" 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,// "pqrstuvw" 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x10, 0x00, 0x00,// "xyz{|}~" BACKSPACE /*$80*/ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,// umlauts etc. ... 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /*$a0*/ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /*$c0*/ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /*$e0*/ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, }; // Variables node_t* pseudo_opcode_tree = NULL; // tree to hold pseudo opcodes int pass_count; // number of current pass (starts 0) char GotByte; // Last byte read (processed) int Process_verbosity = 0; // Level of additional output // Global counters int pass_undefined_count; // "NeedValue" type errors int pass_real_errors; // Errors yet signed long max_errors = MAXERRORS;// errors before giving up FILE* msg_stream = NULL;// set to stdout by --use-stdout jmp_buf exception_env; char* error_message; //int cbm_load_address = 0; // Functions // Memory allocation stuff // Allocate memory and die if not available void* safe_malloc(size_t size) { void* block; if((block = malloc(size)) == NULL) Throw_serious_error(exception_no_memory_left); return(block); } // Parser stuff // Parse (re-)definitions of program counter static void parse_pc_def(void) {// Now GotByte = "*" NEXTANDSKIPSPACE(); // proceed with next char // re-definitions of program counter change segment if(GotByte == '=') { GetByte();// proceed with next char Output_start_segment(); Input_ensure_EOS(); } else { Throw_error(exception_syntax); Input_skip_remainder(); } } // Parse pseudo opcodes. Has to be re-entrant. static inline void parse_pseudo_opcode(void) {// Now GotByte = "!" void* node_body; enum eos_t (*fn)(void); enum eos_t then = SKIP_REMAINDER; // prepare for errors GetByte();// read next byte // on missing keyword, return (complaining will have been done) if(Input_read_and_lower_keyword()) { // search for tree item if((Tree_easy_scan(pseudo_opcode_tree, &node_body, GlobalDynaBuf)) && node_body) { fn = (enum eos_t (*)(void)) node_body; SKIPSPACE(); // call function then = fn(); } else Throw_error("Unknown pseudo opcode."); } if(then == SKIP_REMAINDER) Input_skip_remainder(); else if(then == ENSURE_EOS) Input_ensure_EOS(); // the other two possibilities (PARSE_REMAINDER and AT_EOS_ANYWAY) // will lead to the remainder of the line being parsed by the mainloop. } // Check and return whether first label of statement. Complain if not. static bool first_label_of_statement(int *statement_flags) { if((*statement_flags) & SF_IMPLIED_LABEL) { Throw_error(exception_syntax); Input_skip_remainder(); return(FALSE); } (*statement_flags) |= SF_IMPLIED_LABEL; // now there has been one return(TRUE); } // Parse global label definition or assembler mnemonic static void parse_mnemo_or_global_label_def(int *statement_flags) { // It is only a label if it isn't a mnemonic if((CPU_now->keyword_is_mnemonic(Input_read_keyword()) == FALSE) && first_label_of_statement(statement_flags)) { // Now GotByte = illegal char // 04 Jun 2005 - this fix should help to // explain "strange" error messages. if(*GLOBALDYNABUF_CURRENT == '') Throw_first_pass_warning("Label name starts with a shift-space character."); Label_parse_definition(ZONE_GLOBAL, *statement_flags); } } // Parse local label definition static void parse_local_label_def(int *statement_flags) { if(!first_label_of_statement(statement_flags)) return; GetByte();// start after '.' if(Input_read_keyword()) Label_parse_definition(Section_now->zone, *statement_flags); } // Parse anonymous backward label definition. Called with GotByte == '-' static void parse_backward_anon_def(int *statement_flags) { if(!first_label_of_statement(statement_flags)) return; DYNABUF_CLEAR(GlobalDynaBuf); do DYNABUF_APPEND(GlobalDynaBuf, '-'); while(GetByte() == '-'); DynaBuf_append(GlobalDynaBuf, '\0'); Label_implicit_definition(Section_now->zone, *statement_flags, 0, TRUE); } // Parse anonymous forward label definition. Called with GotByte == ? static void parse_forward_anon_def(int *statement_flags) { label_t* counter_label; if(!first_label_of_statement(statement_flags)) return; DYNABUF_CLEAR(GlobalDynaBuf); DynaBuf_append(GlobalDynaBuf, '+'); while(GotByte == '+') { DYNABUF_APPEND(GlobalDynaBuf, '+'); GetByte(); } counter_label = Label_fix_forward_name(); counter_label->result.val.intval++; DynaBuf_append(GlobalDynaBuf, '\0'); Label_implicit_definition(Section_now->zone, *statement_flags, 0, TRUE); } // Parse block, beginning with next byte. // End reason (either CHAR_EOB or CHAR_EOF) can be found in GotByte afterwards // Has to be re-entrant. void Parse_until_eob_or_eof(void) { int statement_flags; // // start with next byte, don't care about spaces // NEXTANDSKIPSPACE(); // start with next byte GetByte(); // loop until end of block or end of file while((GotByte != CHAR_EOB) && (GotByte != CHAR_EOF)) { // process one statement statement_flags = 0;// no "label = pc" definition yet // Parse until end of statement. Only loops if statement // contains "label = pc" definition and something else; or // if "!ifdef" is true. do { switch(GotByte) { case CHAR_EOS: // end of statement // Ignore now, act later // (stops from being "default") break; case ' ': // space statement_flags |= SF_FOUND_BLANK; /*FALLTHROUGH*/ case CHAR_SOL: // start of line GetByte();// skip break; case '-': parse_backward_anon_def(&statement_flags); break; case '+': GetByte(); if((GotByte == '.') || (BYTEFLAGS(GotByte) & CONTS_KEYWORD)) Macro_parse_call(); else parse_forward_anon_def(&statement_flags); break; case '!': parse_pseudo_opcode(); break; case '*': parse_pc_def(); break; case '.': parse_local_label_def(&statement_flags); break; default: if(BYTEFLAGS(GotByte) & STARTS_KEYWORD) { parse_mnemo_or_global_label_def(&statement_flags); } else { Throw_error(exception_syntax); Input_skip_remainder(); } } } while(GotByte != CHAR_EOS); // until end-of-statement // adjust program counter CPU_pc.intval = (CPU_pc.intval + CPU_2add) & 0xffff; CPU_2add = 0; // go on with next byte GetByte();//NEXTANDSKIPSPACE(); } } // Skip space. If GotByte is CHAR_SOB ('{'), parse block and return TRUE. // Otherwise (if there is no block), return FALSE. // Don't forget to call EnsureEOL() afterwards. bool Parse_optional_block(void) { SKIPSPACE(); if(GotByte != CHAR_SOB) return(FALSE); Parse_until_eob_or_eof(); if(GotByte != CHAR_EOB) Throw_serious_error(exception_no_right_brace); GetByte(); return(TRUE); } // Error handling // This function will do the actual output for warnings, errors and serious // errors. It shows the given message string, as well as the current // context: file name, line number, source type and source title. static void throw_message(const char* message, const char* type) { snprintf(error_message, 100, "assembler: %s - line %d (%s %s): %s\n", type, Input_now->line_number, Section_now->type, Section_now->title, message ); error_message += strlen(error_message); //fprintf(stdout, "%d ",strlen(error_message)); // fprintf(stdout, error_message); } // Output a warning. // This means the produced code looks as expected. But there has been a // situation that should be reported to the user, for example ACME may have // assembled a 16-bit parameter with an 8-bit value. void Throw_warning(const char* message) { PLATFORM_WARNING(message); throw_message(message, "Warning"); } // Output a warning if in first pass. See above. void Throw_first_pass_warning(const char* message) { if(pass_count == 0) Throw_warning(message); } // Output an error. // This means something went wrong in a way that implies that the output // almost for sure won't look like expected, for example when there was a // syntax error. The assembler will try to go on with the assembly though, so // the user gets to know about more than one of his typos at a time. void Throw_error(const char* message) { PLATFORM_ERROR(message); throw_message(message, "Error"); pass_real_errors++; if(pass_real_errors >= max_errors) longjmp(exception_env, 0); //exit(ACME_finalize(EXIT_FAILURE)); } // Output a serious error, stopping assembly. // Serious errors are those that make it impossible to go on with the // assembly. Example: "!fill" without a parameter - the program counter cannot // be set correctly in this case, so proceeding would be of no use at all. void Throw_serious_error(const char* message) { PLATFORM_SERIOUS(message); throw_message(message, "Serious error"); longjmp(exception_env, 0); //exit(ACME_finalize(EXIT_FAILURE)); } // Handle bugs void Bug_found(const char* message, int code) { Throw_warning("Bug in ACME, code follows"); fprintf(stderr, "(0x%x:)", code); Throw_serious_error(message); } CheeseCutter-master/src/asm/global.h000066400000000000000000000103221357241101300177050ustar00rootroot00000000000000// // ACME - a crossassembler for producing 6502/65c02/65816 code. // Copyright (C) 1998-2006 Marco Baye // Have a look at "acme.c" for further info // // Global stuff - things that are needed by several modules #ifndef global_H #define global_H #include #include #include #include "config.h" // Constants #define SF_FOUND_BLANK (1u) // statement had space or tab #define SF_IMPLIED_LABEL (2u) // statement had implied label def extern const char s_65816[]; extern const char s_and[]; extern const char s_asl[]; extern const char s_asr[]; extern const char s_brl[]; extern const char s_cbm[]; extern const char s_eor[]; extern const char s_error[]; extern const char s_lsr[]; extern const char s_scrxor[]; // Error messages during assembly extern const char exception_cannot_open_input_file[]; extern const char exception_missing_string[]; extern const char exception_no_left_brace[]; extern const char exception_no_memory_left[]; extern const char exception_no_right_brace[]; //extern const char exception_not_yet[]; extern const char exception_number_out_of_range[]; extern const char exception_pc_undefined[]; extern const char exception_syntax[]; // Byte flags table extern const char Byte_flags[]; #define BYTEFLAGS(c) (Byte_flags[(unsigned char) c]) #define STARTS_KEYWORD (1u << 7) // Byte is allowed to start a keyword #define CONTS_KEYWORD (1u << 6) // Byte is allowed in a keyword #define BYTEIS_UPCASE (1u << 5) // Byte is upper case and can be // converted to lower case by OR-ing this bit(!) #define BYTEIS_SYNTAX (1u << 4) // special character for input syntax #define FOLLOWS_ANON (1u << 3) // preceding '-' are backward label // bits 2, 1 and 0 are unused // Variables extern node_t* pseudo_opcode_tree;// tree to hold pseudo opcodes // structures enum eos_t { SKIP_REMAINDER, // skip remainder of line - (after errors) ENSURE_EOS, // make sure there's nothing left in statement PARSE_REMAINDER, // parse what's left AT_EOS_ANYWAY, // actually, same as PARSE_REMAINDER }; extern int pass_count; extern int Process_verbosity;// Level of additional output extern char GotByte;// Last byte read (processed) // Global counters extern int pass_undefined_count;// "NeedValue" type errors in current pass extern int pass_real_errors; // Errors yet extern signed long max_errors; // errors before giving up extern FILE* msg_stream; // set to stdout by --errors_to_stdout extern jmp_buf exception_env; extern char* error_message; //extern int cbm_load_address; // Macros for skipping a single space character #define SKIPSPACE() do {if(GotByte == ' ') GetByte();} while(0) #define NEXTANDSKIPSPACE() do {if(GetByte() == ' ') GetByte();} while(0) // Prototypes // Allocate memory and die if not available extern inline void* safe_malloc(size_t); // Parse block, beginning with next byte. // End reason (either CHAR_EOB or CHAR_EOF) can be found in GotByte afterwards // Has to be re-entrant. extern void Parse_until_eob_or_eof(void); // Skip space. If GotByte is CHAR_SOB ('{'), parse block and return TRUE. // Otherwise (if there is no block), return FALSE. // Don't forget to call EnsureEOL() afterwards. extern int Parse_optional_block(void); // Output a warning. // This means the produced code looks as expected. But there has been a // situation that should be reported to the user, for example ACME may have // assembled a 16-bit parameter with an 8-bit value. extern void Throw_warning(const char*); // Output a warning if in first pass. See above. extern void Throw_first_pass_warning(const char*); // Output an error. // This means something went wrong in a way that implies that the output // almost for sure won't look like expected, for example when there was a // syntax error. The assembler will try to go on with the assembly though, so // the user gets to know about more than one of his typos at a time. extern void Throw_error(const char*); // Output a serious error, stopping assembly. // Serious errors are those that make it impossible to go on with the // assembly. Example: "!fill" without a parameter - the program counter cannot // be set correctly in this case, so proceeding would be of no use at all. extern void Throw_serious_error(const char*); // Handle bugs extern void Bug_found(const char*, int); #endif CheeseCutter-master/src/asm/input.c000066400000000000000000000363161357241101300176120ustar00rootroot00000000000000// // ACME - a crossassembler for producing 6502/65c02/65816 code. // Copyright (C) 1998-2006 Marco Baye // Have a look at "acme.c" for further info // // Input stuff #include "config.h" #include "alu.h" #include "dynabuf.h" #include "global.h" #include "input.h" #include "platform.h" #include "section.h" #include "tree.h" // Constants const char FILE_READBINARY[] = "rb"; #define CHAR_TAB (9) // Tab character #define CHAR_LF (10) // line feed (in file) // (10) // start of line (in high-level format) #define CHAR_CR (13) // carriage return (in file) // (13) // end of file (in high-level format) #define CHAR_STATEMENT_DELIMITER ':' #define CHAR_COMMENT_SEPARATOR ';' // If the characters above are changed, don't forget to adjust ByteFlags[]! // fake input structure (for error msgs before any real input is established) static input_t outermost = { "", // file name 0, // line number FALSE, // Faked file access, so no RAM read INPUTSTATE_EOF, // state of input { NULL // RAM read pointer or file handle } }; // Variables input_t* Input_now = &outermost; // current input structure // End of source file ("!endoffile" or "!eof") static enum eos_t PO_eof(void) { // Well, it doesn't end right here and now, but at end-of-line! :-) Input_ensure_EOS(); Input_now->state = INPUTSTATE_EOF; return(AT_EOS_ANYWAY); } // predefined stuff static node_t pseudo_opcodes[] = { PREDEFNODE("eof", PO_eof), PREDEFLAST("endoffile", PO_eof), // ^^^^ this marks the last element }; // Functions // register pseudo opcodes void Input_init(void) { Tree_add_table(&pseudo_opcode_tree, pseudo_opcodes); } // Let current input point to start of file void Input_new_file(char *src) { /* Input_now->original_filename = ""; //filename; Input_now->line_number = 1; Input_now->source_is_ram = FALSE; Input_now->state = INPUTSTATE_NORMAL; Input_now->src.fd = NULL; */ Input_now->original_filename = ""; //filename; Input_now->line_number = 1; Input_now->source_is_ram = FALSE; Input_now->state = INPUTSTATE_NORMAL; Input_now->src.fd = NULL; Input_now->string_source = src; Input_now->string_source_length = strlen(src); Input_now->string_source_position = 0; } int hacked_getc(input_t *Input) { if(Input->string_source_position >= Input->string_source_length) return EOF; int byte = *(Input->string_source++); Input->string_source_position++; return byte; } // Deliver source code from current file (!) in shortened high-level format static char get_processed_from_file(void) { int from_file; do { switch(Input_now->state) { case INPUTSTATE_NORMAL: // fetch a fresh byte from the current source file //from_file = getc(Input_now->src.fd); from_file = hacked_getc(Input_now); // now process it /*FALLTHROUGH*/ case INPUTSTATE_AGAIN: // Process the latest byte again. Of course, this only // makes sense if the loop has executed at least once, // otherwise the contents of from_file are undefined. // If the source is changed so there is a possibility // to enter INPUTSTATE_AGAIN mode without first having // defined "from_file", trouble may arise... Input_now->state = INPUTSTATE_NORMAL; // EOF must be checked first because it cannot be used // as an index into Byte_flags[] if(from_file == EOF) { // remember to send an end-of-file Input_now->state = INPUTSTATE_EOF; return(CHAR_EOS);// end of statement } // check whether character is special one // if not, everything's cool and froody, so return it if((BYTEFLAGS(from_file) & BYTEIS_SYNTAX) == 0) return((char) from_file); // check special characters ("0x00 TAB LF CR SPC :;}") switch(from_file) { case CHAR_TAB:// TAB character case ' ': // remember to skip all following blanks Input_now->state = INPUTSTATE_SKIPBLANKS; return(' '); case CHAR_LF:// LF character // remember to send a start-of-line Input_now->state = INPUTSTATE_LF; return(CHAR_EOS);// end of statement case CHAR_CR:// CR character // remember to check CRLF + send start-of-line Input_now->state = INPUTSTATE_CR; return(CHAR_EOS);// end of statement case CHAR_EOB: // remember to send an end-of-block Input_now->state = INPUTSTATE_EOB; return(CHAR_EOS);// end of statement case CHAR_STATEMENT_DELIMITER: // just deliver an EOS instead return(CHAR_EOS);// end of statement case CHAR_COMMENT_SEPARATOR: // remember to skip remainder of line Input_now->state = INPUTSTATE_COMMENT; return(CHAR_EOS);// end of statement default: // complain if byte is 0 Throw_error("Source file contains illegal character."); return((char) from_file); } case INPUTSTATE_SKIPBLANKS: // read until non-blank, then deliver that do { // from_file = getc(Input_now->src.fd); from_file = hacked_getc(Input_now); } while((from_file == CHAR_TAB) || (from_file == ' ')); // re-process last byte Input_now->state = INPUTSTATE_AGAIN; break; case INPUTSTATE_LF: // return start-of-line, then continue in normal mode Input_now->state = INPUTSTATE_NORMAL; return(CHAR_SOL);// new line case INPUTSTATE_CR: // return start-of-line, remember to check for LF Input_now->state = INPUTSTATE_SKIPLF; return(CHAR_SOL);// new line case INPUTSTATE_SKIPLF: from_file = hacked_getc(Input_now); // if LF, ignore it and fetch another byte // otherwise, process current byte if(from_file == CHAR_LF) Input_now->state = INPUTSTATE_NORMAL; else Input_now->state = INPUTSTATE_AGAIN; break; case INPUTSTATE_COMMENT: // read until end-of-line or end-of-file do from_file = hacked_getc(Input_now); while((from_file != EOF) && (from_file != CHAR_CR) && (from_file != CHAR_LF)); // re-process last byte Input_now->state = INPUTSTATE_AGAIN; break; case INPUTSTATE_EOB: // deliver EOB Input_now->state = INPUTSTATE_NORMAL; return(CHAR_EOB);// end of block case INPUTSTATE_EOF: // deliver EOF Input_now->state = INPUTSTATE_NORMAL; return(CHAR_EOF);// end of file default: Bug_found("StrangeInputMode", Input_now->state); } } while(TRUE); } // This function delivers the next byte from the currently active byte source // in shortened high-level format. FIXME - use fn ptr? // When inside quotes, use GetQuotedByte() instead! char GetByte(void) { // do { // If byte source is RAM, then no conversions are // necessary, because in RAM the source already has // high-level format // Otherwise, the source is a file. This means we will call // GetFormatted() which will do a shit load of conversions. if(Input_now->source_is_ram) GotByte = *(Input_now->src.ram_ptr++); else GotByte = get_processed_from_file(); // // if start-of-line was read, increment line counter and repeat // if(GotByte != CHAR_SOL) // return(GotByte); // Input_now->line_number++; // } while(TRUE); if(GotByte == CHAR_SOL) Input_now->line_number++; return(GotByte); } // This function delivers the next byte from the currently active byte source // in un-shortened high-level format. // This function complains if CHAR_EOS (end of statement) is read. char GetQuotedByte(void) { int from_file; // must be an int to catch EOF // If byte source is RAM, then no conversion is necessary, // because in RAM the source already has high-level format if(Input_now->source_is_ram) GotByte = *(Input_now->src.ram_ptr++); // Otherwise, the source is a file. else { // fetch a fresh byte from the current source file from_file = hacked_getc(Input_now); switch(from_file) { case EOF: // remember to send an end-of-file Input_now->state = INPUTSTATE_EOF; GotByte = CHAR_EOS; // end of statement break; case CHAR_LF:// LF character // remember to send a start-of-line Input_now->state = INPUTSTATE_LF; GotByte = CHAR_EOS; // end of statement break; case CHAR_CR:// CR character // remember to check for CRLF + send a start-of-line Input_now->state = INPUTSTATE_CR; GotByte = CHAR_EOS; // end of statement break; default: GotByte = from_file; } } // now check for end of statement if(GotByte == CHAR_EOS) Throw_error("Quotes still open at end of line."); return(GotByte); } // Skip remainder of statement, for example on error void Input_skip_remainder(void) { while(GotByte) GetByte();// Read characters until end-of-statement } // Ensure that the remainder of the current statement is empty, for example // after mnemonics using implied addressing. void Input_ensure_EOS(void) {// Now GotByte = first char to test SKIPSPACE(); if(GotByte) { Throw_error("Garbage data at end of statement."); Input_skip_remainder(); } } // Skip or store block (starting with next byte, so call directly after // reading opening brace). // If "Store" is TRUE, the block is read into GlobalDynaBuf, then a copy // is made and a pointer to that is returned. // If "Store" is FALSE, NULL is returned. // After calling this function, GotByte holds '}'. Unless EOF was found first, // but then a serious error would have been thrown. char* Input_skip_or_store_block(bool store) { char byte; int depth = 1; // to find matching block end // prepare global dynamic buffer DYNABUF_CLEAR(GlobalDynaBuf); do { byte = GetByte(); // if wanted, store if(store) DYNABUF_APPEND(GlobalDynaBuf, byte); // now check for some special characters switch(byte) { case CHAR_EOF: // End-of-file in block? Sorry, no way. Throw_serious_error(exception_no_right_brace); case '"': // Quotes? Okay, read quoted stuff. case '\'': do { GetQuotedByte(); // if wanted, store if(store) DYNABUF_APPEND(GlobalDynaBuf, GotByte); } while((GotByte != CHAR_EOS) && (GotByte != byte)); break; case CHAR_SOB: depth++; break; case CHAR_EOB: depth--; break; } } while(depth); // in case of skip, return now if(!store) return(NULL); // otherwise, prepare to return copy of block // add EOF, just to make sure block is never read too far DynaBuf_append(GlobalDynaBuf, CHAR_EOS); DynaBuf_append(GlobalDynaBuf, CHAR_EOF); // return pointer to copy return(DynaBuf_get_copy(GlobalDynaBuf)); } // Read bytes and add to GlobalDynaBuf until the given terminator (or CHAR_EOS) // is found. Act upon single and double quotes by entering (and leaving) quote // mode as needed (So the terminator does not terminate when inside quotes). void Input_until_terminator(char terminator) { char byte = GotByte; do { // Terminator? Exit. EndOfStatement? Exit. if((byte == terminator) || (byte == CHAR_EOS)) return; // otherwise, append to GlobalDynaBuf and check for quotes DYNABUF_APPEND(GlobalDynaBuf, byte); if((byte == '"') || (byte == '\'')) { do { // Okay, read quoted stuff. GetQuotedByte();// throws error on EOS DYNABUF_APPEND(GlobalDynaBuf, GotByte); } while((GotByte != CHAR_EOS) && (GotByte != byte)); // on error, exit now, before calling GetByte() if(GotByte != byte) return; } byte = GetByte(); } while(TRUE); } // Append to GlobalDynaBuf while characters are legal for keywords. // Throws "missing string" error if none. // Returns number of characters added. int Input_append_keyword_to_global_dynabuf(void) { int length = 0; // add characters to buffer until an illegal one comes along while(BYTEFLAGS(GotByte) & CONTS_KEYWORD) { DYNABUF_APPEND(GlobalDynaBuf, GotByte); length++; GetByte(); } if(length == 0) Throw_error(exception_missing_string); return(length); } // Check whether GotByte is a dot. // If not, store global zone value. // If yes, store current zone value and read next byte. // Then jump to Input_read_keyword(), which returns length of keyword. int Input_read_zone_and_keyword(zone_t *zone) { SKIPSPACE(); if(GotByte == '.') { GetByte(); *zone = Section_now->zone; } else *zone = ZONE_GLOBAL; return(Input_read_keyword()); } // Clear dynamic buffer, then append to it until an illegal (for a keyword) // character is read. Zero-terminate the string. Return its length (without // terminator). // Zero lengths will produce a "missing string" error. int Input_read_keyword(void) { int length; DYNABUF_CLEAR(GlobalDynaBuf); length = Input_append_keyword_to_global_dynabuf(); // add terminator to buffer (increments buffer's length counter) DynaBuf_append(GlobalDynaBuf, '\0'); return(length); } // Clear dynamic buffer, then append to it until an illegal (for a keyword) // character is read. Zero-terminate the string, then convert to lower case. // Return its length (without terminator). // Zero lengths will produce a "missing string" error. int Input_read_and_lower_keyword(void) { int length; DYNABUF_CLEAR(GlobalDynaBuf); length = Input_append_keyword_to_global_dynabuf(); // add terminator to buffer (increments buffer's length counter) DynaBuf_append(GlobalDynaBuf, '\0'); DynaBuf_to_lower(GlobalDynaBuf, GlobalDynaBuf);// convert to lower case return(length); } // Try to read a file name. If "allow_library" is TRUE, library access by using // <...> quoting is possible as well. The file name given in the assembler // source code is converted from UNIX style to platform style. // Returns whether error occurred (TRUE on error). Filename in GlobalDynaBuf. // Errors are handled and reported, but caller should call // Input_skip_remainder() then. bool Input_read_filename(bool allow_library) { char *lib_prefix, end_quote; DYNABUF_CLEAR(GlobalDynaBuf); SKIPSPACE(); // check for library access if(GotByte == '<') { // if library access forbidden, complain if(allow_library == FALSE) { Throw_error("Writing to library not supported."); return(TRUE); } // read platform's lib prefix lib_prefix = PLATFORM_LIBPREFIX; #ifndef NO_NEED_FOR_ENV_VAR // if lib prefix not set, complain if(lib_prefix == NULL) { Throw_error("\"ACME\" environment variable not found."); return(TRUE); } #endif // copy lib path and set quoting char DynaBuf_add_string(GlobalDynaBuf, lib_prefix); end_quote = '>'; } else { if(GotByte == '"') end_quote = '"'; else { Throw_error("File name quotes not found (\"\" or <>)."); return(TRUE); } } // read first character, complain if closing quote if(GetQuotedByte() == end_quote) { Throw_error("No file name given."); return(TRUE); } // read characters until closing quote (or EOS) is reached // append platform-converted characters to current string while((GotByte != CHAR_EOS) && (GotByte != end_quote)) { DYNABUF_APPEND(GlobalDynaBuf, PLATFORM_CONVERTPATHCHAR(GotByte)); GetQuotedByte(); } // on error, return if(GotByte == CHAR_EOS) return(TRUE); GetByte(); // fetch next to forget closing quote // terminate string DynaBuf_append(GlobalDynaBuf, '\0'); // add terminator return(FALSE); // no error } // Try to read a comma, skipping spaces before and after. Return TRUE if comma // found, otherwise FALSE. bool Input_accept_comma(void) { SKIPSPACE(); if(GotByte != ',') return(FALSE); NEXTANDSKIPSPACE(); return(TRUE); } // read optional info about parameter length int Input_get_force_bit(void) { char byte; int force_bit = 0; if(GotByte == '+') { byte = GetByte(); if(byte == '1') force_bit = MVALUE_FORCE08; else if(byte == '2') force_bit = MVALUE_FORCE16; else if(byte == '3') force_bit = MVALUE_FORCE24; if(force_bit) GetByte(); else Throw_error("Illegal postfix."); } SKIPSPACE(); return(force_bit); } CheeseCutter-master/src/asm/input.h000066400000000000000000000115111357241101300176050ustar00rootroot00000000000000// // ACME - a crossassembler for producing 6502/65c02/65816 code. // Copyright (C) 1998-2006 Marco Baye // Have a look at "acme.c" for further info // // Input stuff #ifndef input_H #define input_H #include #include // type definitions // values for input_t component "Src.State" enum inputstate_t { INPUTSTATE_NORMAL, // everything's fine INPUTSTATE_AGAIN, // re-process last byte INPUTSTATE_SKIPBLANKS, // shrink multiple spaces INPUTSTATE_LF, // send start-of-line after end-of-statement INPUTSTATE_CR, // same, but also remember to skip LF INPUTSTATE_SKIPLF, // skip LF if that's next INPUTSTATE_COMMENT, // skip characters until newline or EOF INPUTSTATE_EOB, // send end-of-block after end-of-statement INPUTSTATE_EOF, // send end-of-file after end-of-statement }; typedef struct { const char* original_filename;// during RAM reads, too int line_number; // in file (on RAM reads, too) bool source_is_ram; // TRUE if RAM, FALSE if file enum inputstate_t state; // state of input union { FILE* fd; // file descriptor char* ram_ptr; // RAM read ptr (loop or macro block) } src; char *string_source; int string_source_length; int string_source_position; } input_t; // Constants extern const char FILE_READBINARY[]; // Special characters // The program *heavily* relies on CHAR_EOS (end of statement) being 0x00! #define CHAR_EOS (0) // end of statement (in high-level format) #define CHAR_SOB '{' // start of block #define CHAR_EOB '}' // end of block #define CHAR_SOL (10) // start of line (in high-level format) #define CHAR_EOF (13) // end of file (in high-level format) // If the characters above are changed, don't forget to adjust Byte_flags[]! // Variables extern input_t* Input_now; // current input structure // Prototypes // register pseudo opcodes extern void Input_init(void); // Let current input point to start of file extern void Input_new_file(char *); // get next byte from currently active byte source in shortened high-level // format. When inside quotes, use GetQuotedByte() instead! extern char GetByte(void); // get next byte from currently active byte source in un-shortened high-level // format. Complains if CHAR_EOS (end of statement) is read. extern char GetQuotedByte(void); // Skip remainder of statement, for example on error extern void Input_skip_remainder(void); // Ensure that the remainder of the current statement is empty, for example // after mnemonics using implied addressing. extern void Input_ensure_EOS(void); // Skip or store block (starting with next byte, so call directly after // reading opening brace). // If "Store" is TRUE, the block is read into GlobalDynaBuf, then a copy // is made and a pointer to that is returned. // If "Store" is FALSE, NULL is returned. // After calling this function, GotByte holds '}'. Unless EOF was found first, // but then a serious error would have been thrown. extern char* Input_skip_or_store_block(bool store); // Read bytes and add to GlobalDynaBuf until the given terminator (or CHAR_EOS) // is found. Act upon single and double quotes by entering (and leaving) quote // mode as needed (So the terminator does not terminate when inside quotes). extern void Input_until_terminator(char terminator); // Append to GlobalDynaBuf while characters are legal for keywords. // Throws "missing string" error if none. Returns number of characters added. extern int Input_append_keyword_to_global_dynabuf(void); // Check whether GotByte is a dot. // If not, store global zone value. // If yes, store current zone value and read next byte. // Then jump to Input_read_keyword(), which returns length of keyword. extern int Input_read_zone_and_keyword(zone_t*); // Clear dynamic buffer, then append to it until an illegal (for a keyword) // character is read. Zero-terminate the string. Return its length (without // terminator). // Zero lengths will produce a "missing string" error. extern int Input_read_keyword(void); // Clear dynamic buffer, then append to it until an illegal (for a keyword) // character is read. Zero-terminate the string, then convert to lower case. // Return its length (without terminator). // Zero lengths will produce a "missing string" error. extern int Input_read_and_lower_keyword(void); // Try to read a file name. If "allow_library" is TRUE, library access by using // <...> quoting is possible as well. The file name given in the assembler // source code is converted from UNIX style to platform style. // Returns whether error occurred (TRUE on error). Filename in GlobalDynaBuf. // Errors are handled and reported, but caller should call // Input_skip_remainder() then. extern bool Input_read_filename(bool library_allowed); // Try to read a comma, skipping spaces before and after. Return TRUE if comma // found, otherwise FALSE. extern bool Input_accept_comma(void); // read optional info about parameter length extern int Input_get_force_bit(void); #endif CheeseCutter-master/src/asm/label.c000066400000000000000000000174321357241101300175300ustar00rootroot00000000000000// // ACME - a crossassembler for producing 6502/65c02/65816 code. // Copyright (C) 1998-2006 Marco Baye // Have a look at "acme.c" for further info // // Label stuff #include #include "acme.h" #include "alu.h" #include "cpu.h" #include "dynabuf.h" #include "global.h" #include "input.h" #include "label.h" #include "platform.h" #include "section.h" #include "tree.h" // Constants #define WARN_IF_LABEL_INDENTED 1 // FIXME - use CLI switch? #define s_sl (s_asl+1) // Yes, I know I'm sick // Variables node_ra_t* Label_forest[256];// ... (because of 8-bit hash) // Dump label value and flags to dump file static void dump_one_label(node_ra_t* node, FILE* fd) { label_t* label = node->body; // output name fprintf(fd, "%s", node->id_string); switch(label->result.flags & MVALUE_FORCEBITS) { case MVALUE_FORCE16: fprintf(fd, "+2="); break; case MVALUE_FORCE16 | MVALUE_FORCE24: /*FALLTHROUGH*/ case MVALUE_FORCE24: fprintf(fd, "+3="); break; default: fprintf(fd, " ="); } if(label->result.flags & MVALUE_DEFINED) { if(label->result.flags & MVALUE_IS_FP) fprintf(fd, "%.30f", label->result.val.fpval);//FIXME %g else fprintf(fd, "$%x", (unsigned) label->result.val.intval); } else fprintf(fd, " ?"); if(label->result.flags & MVALUE_UNSURE) fprintf(fd, "; ?"); if(label->usage == 0) fprintf(fd, "; unused"); fprintf(fd, "\n"); } // Search for label. Create if nonexistant. If created, give it flags "Flags". // The label name must be held in GlobalDynaBuf. label_t* Label_find(zone_t zone, int flags) { node_ra_t* node; label_t* label; bool node_created; int force_bits = flags & MVALUE_FORCEBITS; node_created = Tree_hard_scan(&node, Label_forest, zone, TRUE); // if node has just been created, create label as well if(node_created) { // Create new label structure label = safe_malloc(sizeof(label_t)); // Finish empty label item label->result.flags = flags; if(flags & MVALUE_IS_FP) label->result.val.fpval = 0; else label->result.val.intval = 0; label->usage = 0;// usage count label->pass = pass_count; node->body = label; } else label = node->body; // make sure the force bits don't clash if((node_created == FALSE) && force_bits) if((label->result.flags & MVALUE_FORCEBITS) != force_bits) Throw_error("Too late for postfix."); return(label); } // Assign value to label. The function acts upon the label's flag bits and // produces an error if needed. void Label_set_value(label_t* label, result_t* new, bool change_allowed) { int oldflags = label->result.flags; // value stuff if((oldflags & MVALUE_DEFINED) && (change_allowed == FALSE)) { // Label is already defined, so compare new and old values // if different type OR same type but different value, complain if(((oldflags ^ new->flags) & MVALUE_IS_FP) || ((oldflags & MVALUE_IS_FP) ? (label->result.val.fpval != new->val.fpval) : (label->result.val.intval != new->val.intval))) Throw_error("Label already defined."); } else // Label is not defined yet OR redefinitions are allowed label->result = *new; // flags stuff // Ensure that "unsure" labels without "isByte" state don't get that if((oldflags & (MVALUE_UNSURE | MVALUE_ISBYTE)) == MVALUE_UNSURE) new->flags &= ~MVALUE_ISBYTE; if(change_allowed) oldflags = (oldflags & MVALUE_UNSURE) | new->flags; else { if((oldflags & MVALUE_FORCEBITS) == 0) if((oldflags & (MVALUE_UNSURE | MVALUE_DEFINED)) == 0) oldflags |= new->flags & MVALUE_FORCEBITS; oldflags |= new->flags & ~MVALUE_FORCEBITS; } label->result.flags = oldflags; } // (Re)set label static enum eos_t PO_set(void) {// Now GotByte = illegal char result_t result; int force_bit; label_t* label; zone_t zone; if(Input_read_zone_and_keyword(&zone) == 0) // skips spaces before // Now GotByte = illegal char return(SKIP_REMAINDER); force_bit = Input_get_force_bit();// skips spaces after label = Label_find(zone, force_bit); if(GotByte != '=') { Throw_error(exception_syntax); return(SKIP_REMAINDER); } // label = parsed value GetByte();// proceed with next char ALU_any_result(&result); // clear label's force bits and set new ones label->result.flags &= ~(MVALUE_FORCEBITS | MVALUE_ISBYTE); if(force_bit) { label->result.flags |= force_bit; result.flags &= ~(MVALUE_FORCEBITS | MVALUE_ISBYTE); } Label_set_value(label, &result, TRUE); return(ENSURE_EOS); } // Select dump file static enum eos_t PO_sl(void) { // only process this pseudo opcode in the first pass if(pass_count) return(SKIP_REMAINDER); // if label dump file already chosen, complain and exit if(labeldump_filename) { Throw_warning("Label dump file already chosen."); return(SKIP_REMAINDER); } // read filename to global dynamic buffer // if no file name given, exit (complaining will have been done) if(Input_read_filename(FALSE)) return(SKIP_REMAINDER); // get malloc'd copy of filename labeldump_filename = DynaBuf_get_copy(GlobalDynaBuf); // ensure there's no garbage at end of line return(ENSURE_EOS); } // predefined stuff static node_t pseudo_opcodes[] = { PREDEFNODE("set", PO_set), PREDEFLAST(s_sl, PO_sl), // ^^^^ this marks the last element }; // Parse implicit label definition (can be either global or local). // GlobalDynaBuf holds the label name. void Label_implicit_definition(zone_t zone, int stat_flags, int force_bit, bool change) { result_t result; label_t* label; label = Label_find(zone, force_bit); // implicit label definition (label) if((stat_flags & SF_FOUND_BLANK) && WARN_IF_LABEL_INDENTED) Throw_first_pass_warning("Implicit label definition not in leftmost column."); result.flags = CPU_pc.flags & MVALUE_DEFINED; result.val.intval = CPU_pc.intval; Label_set_value(label, &result, change); } // Parse label definition (can be either global or local). // GlobalDynaBuf holds the label name. void Label_parse_definition(zone_t zone, int stat_flags) { result_t result; label_t* label; int force_bit = Input_get_force_bit();// skips spaces after // FIXME - force bit is allowed for implicit label defs?! if(GotByte == '=') { // explicit label definition (label = ) label = Label_find(zone, force_bit); // label = parsed value GetByte(); // skip '=' ALU_any_result(&result); Label_set_value(label, &result, FALSE); Input_ensure_EOS(); } else Label_implicit_definition(zone, stat_flags, force_bit, FALSE); } // Dump global labels to file void Label_dump_all(FILE* fd) { Tree_dump_forest(Label_forest, ZONE_GLOBAL, dump_one_label, fd); PLATFORM_SETFILETYPE_TEXT(labeldump_filename); } // register pseudo opcodes and clear label forest void Label_init(void) { node_ra_t** ptr; int i; Tree_add_table(&pseudo_opcode_tree, pseudo_opcodes); // Cut down all the trees (clear pointer table) ptr = Label_forest; // Clear pointertable for(i = 255; i >= 0; i--) *ptr++ = NULL; } // Fix name of anonymous forward label (held in DynaBuf, NOT TERMINATED!) so it // references the *next* anonymous forward label definition. The tricky bit is, // each name length would need its own counter. But hey, ACME's real quick in // finding labels, so I'll just abuse the label system to store those counters. label_t* Label_fix_forward_name(void) { label_t* counter_label; unsigned long number; // terminate name, find "counter" label and read value DynaBuf_append(GlobalDynaBuf, '\0'); counter_label = Label_find(Section_now->zone, 0); // make sure it gets reset to zero in each new pass if(counter_label->pass != pass_count) { counter_label->pass = pass_count; counter_label->result.val.intval = 0; } number = (unsigned long) counter_label->result.val.intval; // now append to the name to make it unique GlobalDynaBuf->size--; // forget terminator, we want to append do { DYNABUF_APPEND(GlobalDynaBuf, 'a' + (number & 15)); number >>= 4; } while(number); DynaBuf_append(GlobalDynaBuf, '\0'); return(counter_label); } CheeseCutter-master/src/asm/label.h000066400000000000000000000027741357241101300175400ustar00rootroot00000000000000// // ACME - a crossassembler for producing 6502/65c02/65816 code. // Copyright (C) 1998-2006 Marco Baye // Have a look at "acme.c" for further info // // Label stuff #ifndef label_H #define label_H #include // "label" structure type definition struct label_t { struct result_t result; // Expression flags and value int usage; // usage count int pass; // pass of creation (for anon counters) }; // Variables extern node_ra_t* Label_forest[]; // trees (because of 8-bit hash) // Prototypes // register pseudo opcodes and clear label forest extern void Label_init(void); // function acts upon the label's flag bits and produces an error if needed. extern void Label_set_value(label_t*, result_t*, bool change_allowed); // Parse implicit label definition (can be either global or local). // Name must be held in GlobalDynaBuf. extern void Label_implicit_definition(zone_t zone, int stat_flags, int force_bit, bool change); // Parse label definition (can be either global or local). // Name must be held in GlobalDynaBuf. extern void Label_parse_definition(zone_t zone, int stat_flags); // Search for label. Create if nonexistant. If created, assign flags. // Name must be held in GlobalDynaBuf. extern label_t* Label_find(zone_t, int flags); // Dump global labels to file extern void Label_dump_all(FILE* fd); // Fix name of anonymous forward label (held in GlobalDynaBuf, NOT TERMINATED!) // so it references the *next* anonymous forward label definition. extern label_t* Label_fix_forward_name(void); #endif CheeseCutter-master/src/asm/macro.c000066400000000000000000000304661357241101300175540ustar00rootroot00000000000000// // ACME - a crossassembler for producing 6502/65c02/65816 code. // Copyright (C) 1998-2006 Marco Baye // Have a look at "acme.c" for further info // // Macro stuff #include // needs strlen() + memcpy() #include "config.h" #include "platform.h" // done first in case "inline" is redefined #include "acme.h" #include "alu.h" #include "dynabuf.h" #include "global.h" #include "input.h" #include "label.h" #include "section.h" #include "tree.h" #include "macro.h" // Constants #define MACRONAME_DYNABUF_INITIALSIZE 128 #define ARG_SEPARATOR ' ' // separates macro title from arg types #define ARGTYPE_NUM_VAL 'v' #define ARGTYPE_NUM_REF 'V' //#define ARGTYPE_STR_VAL 's' //#define ARGTYPE_STR_REF 'S' #define REFERENCE_CHAR '~' // prefix for call-by-reference #define HALF_INITIAL_ARG_TABLE_SIZE 4 static const char exception_macro_twice[] = "Macro already defined."; // macro struct type definition struct macro_t { int def_line_number;// line number of definition for error msgs char* def_filename; // file name of definition for error msgs char* original_name; // user-supplied name for error msgs char* parameter_list; // parameters (whole line) char* body; // RAM block containing macro body }; // there's no need to make this a struct and add a type component: // when the macro has been found, accessing its parameter_list component // gives us the possibility to find out which args are call-by-value and // which ones are call-by-reference. union macro_arg_t { result_t result; // value and flags (call by value) label_t* label; // pointer to label struct (call by reference) }; // Variables static dynabuf_t* user_macro_name; // original macro title static dynabuf_t* internal_name; // plus param type chars static node_ra_t* macro_forest[256]; // trees (because of 8b hash) // Dynamic argument table static union macro_arg_t* arg_table = NULL; static int argtable_size = HALF_INITIAL_ARG_TABLE_SIZE; // Functions // Enlarge the argument table static void enlarge_arg_table(void) { argtable_size *= 2; arg_table = realloc(arg_table, argtable_size * sizeof(union macro_arg_t)); if(arg_table == NULL) Throw_serious_error(exception_no_memory_left); } // create dynamic buffers and arg table void Macro_init(void) { user_macro_name = DynaBuf_create(MACRONAME_DYNABUF_INITIALSIZE); internal_name = DynaBuf_create(MACRONAME_DYNABUF_INITIALSIZE); enlarge_arg_table(); } // Read macro zone and title. Title is read to GlobalDynaBuf and then copied // over to internal_name DynaBuf, where ARG_SEPARATOR is added. // In user_macro_name DynaBuf, the original name is reconstructed (even with // '.' prefix) so a copy can be linked to the resulting macro struct. static zone_t get_zone_and_title(void) { zone_t macro_zone; Input_read_zone_and_keyword(¯o_zone); // skips spaces before // now GotByte = illegal character after title // copy macro title to private dynabuf and add separator character DYNABUF_CLEAR(user_macro_name); DYNABUF_CLEAR(internal_name); if(macro_zone != ZONE_GLOBAL) DynaBuf_append(user_macro_name, '.'); DynaBuf_add_string(user_macro_name, GLOBALDYNABUF_CURRENT); DynaBuf_add_string(internal_name, GLOBALDYNABUF_CURRENT); DynaBuf_append(user_macro_name, '\0'); DynaBuf_append(internal_name, ARG_SEPARATOR); SKIPSPACE();// done here once so it's not necessary at two callers return(macro_zone); } // Check for comma. If there, append to GlobalDynaBuf. static inline bool pipe_comma(void) { bool result; result = Input_accept_comma(); if(result) DYNABUF_APPEND(GlobalDynaBuf, ','); return(result); } // Return malloc'd copy of string static char* get_string_copy(const char* original) { size_t size; char* copy; size = strlen(original) + 1; copy = safe_malloc(size); memcpy(copy, original, size); return(copy); } // This function is called from both macro definition and macro call. // Terminate macro name and copy from internal_name to GlobalDynaBuf // (because that's where Tree_hard_scan() looks for the search string). // Then try to find macro and return whether it was created. static bool search_for_macro(node_ra_t** result, zone_t zone, bool create) { DynaBuf_append(internal_name, '\0'); // terminate macro name // now internal_name = macro_title SPC argument_specifiers NUL DYNABUF_CLEAR(GlobalDynaBuf); DynaBuf_add_string(GlobalDynaBuf, internal_name->buffer); DynaBuf_append(GlobalDynaBuf, '\0'); return(Tree_hard_scan(result, macro_forest, zone, create)); } // This function is called when an already existing macro is re-defined. // It first outputs a warning and then a serious error, stopping assembly. // Showing the first message as a warning guarantees that ACME does not reach // the maximum error limit inbetween. static void report_redefinition(node_ra_t* macro_node) { struct macro_t* original_macro = macro_node->body; // show warning with location of current definition Throw_warning(exception_macro_twice); // CAUTION, ugly kluge: fiddle with Input_now and Section_now // data to generate helpful error messages Input_now->original_filename = original_macro->def_filename; Input_now->line_number = original_macro->def_line_number; Section_now->type = "original"; Section_now->title = "definition"; // show serious error with location of original definition Throw_serious_error(exception_macro_twice); } // This function is only called during the first pass, so there's no need to // check whether to skip the definition or not. // Return with GotByte = '}' void Macro_parse_definition(void) {// Now GotByte = illegal char after "!macro" char* formal_parameters; node_ra_t* macro_node; struct macro_t* new_macro; zone_t macro_zone = get_zone_and_title(); // now GotByte = first non-space after title DYNABUF_CLEAR(GlobalDynaBuf); // prepare to hold formal parameters // GlobalDynaBuf = "" (will hold formal parameter list) // user_macro_name = ['.'] MacroTitle NUL // internal_name = MacroTitle ARG_SEPARATOR (grows to signature) // Accept n>=0 comma-separated formal parameters before CHAR_SOB ('{'). // Valid argument formats are: // .LOCAL_LABEL_BY_VALUE // ~.LOCAL_LABEL_BY_REFERENCE // GLOBAL_LABEL_BY_VALUE global args are very uncommon, // ~GLOBAL_LABEL_BY_REFERENCE but not forbidden // now GotByte = non-space if(GotByte != CHAR_SOB) { // any at all? do { // handle call-by-reference character ('~') if(GotByte != REFERENCE_CHAR) DynaBuf_append(internal_name, ARGTYPE_NUM_VAL); else { DynaBuf_append(internal_name, ARGTYPE_NUM_REF); DynaBuf_append(GlobalDynaBuf, REFERENCE_CHAR); GetByte(); } // handle prefix for local labels ('.') if(GotByte == '.') { DynaBuf_append(GlobalDynaBuf, '.'); GetByte(); } // handle label name Input_append_keyword_to_global_dynabuf(); } while(pipe_comma()); // ensure CHAR_SOB ('{') if(GotByte != CHAR_SOB) Throw_serious_error(exception_no_left_brace); } DynaBuf_append(GlobalDynaBuf, CHAR_EOS); // terminate param list // now GlobalDynaBuf = comma-separated parameter list without spaces, // but terminated with CHAR_EOS. formal_parameters = DynaBuf_get_copy(GlobalDynaBuf); // now GlobalDynaBuf = unused // Reading the macro body would change the line number. To have correct // error messages, we're checking for "macro twice" *now*. // Search for macro. Create if not found. // But if found, complain (macro twice). if(search_for_macro(¯o_node, macro_zone, TRUE) == FALSE) report_redefinition(macro_node);// quits with serious error // Create new macro struct and set it up. Finally we'll read the body. new_macro = safe_malloc(sizeof(struct macro_t)); new_macro->def_line_number = Input_now->line_number; new_macro->def_filename = get_string_copy(Input_now->original_filename); new_macro->original_name = get_string_copy(user_macro_name->buffer); new_macro->parameter_list = formal_parameters; new_macro->body = Input_skip_or_store_block(TRUE);// changes LineNumber macro_node->body = new_macro; // link macro struct to tree node // and that about sums it up } // Parse macro call ("+MACROTITLE"). Has to be re-entrant. void Macro_parse_call(void) { // Now GotByte = dot or first char of macro name char local_gotbyte; label_t* label; section_t new_section, *outer_section; input_t new_input, *outer_input; struct macro_t* actual_macro; node_ra_t *macro_node, *label_node; zone_t macro_zone, label_zone; int arg_count = 0; // Enter deeper nesting level // Quit program if recursion too deep. if(--macro_recursions_left < 0) Throw_serious_error("Too deeply nested. Recursive macro calls?"); macro_zone = get_zone_and_title(); // now GotByte = first non-space after title // internal_name = MacroTitle ARG_SEPARATOR (grows to signature) // Accept n>=0 comma-separated arguments before CHAR_EOS. // Valid argument formats are: // EXPRESSION (everything that does NOT start with '~' // ~.LOCAL_LABEL_BY_REFERENCE // ~GLOBAL_LABEL_BY_REFERENCE // now GotByte = non-space if(GotByte != CHAR_EOS) { // any at all? do { // if arg table cannot take another element, enlarge if(argtable_size <= arg_count) enlarge_arg_table(); // Decide whether call-by-reference or call-by-value // In both cases, GlobalDynaBuf may be used. if(GotByte == REFERENCE_CHAR) { // read call-by-reference arg DynaBuf_append(internal_name, ARGTYPE_NUM_REF); GetByte(); // skip '~' character Input_read_zone_and_keyword(&label_zone); // GotByte = illegal char arg_table[arg_count].label = Label_find(label_zone, 0); } else { // read call-by-value arg DynaBuf_append(internal_name, ARGTYPE_NUM_VAL); ALU_any_result(&(arg_table[arg_count].result)); } arg_count++; } while(Input_accept_comma()); } // now arg_table contains the arguments // now GlobalDynaBuf = unused // check for "unknown macro" // Search for macro. Do not create if not found. search_for_macro(¯o_node, macro_zone, FALSE); if(macro_node == NULL) { Throw_error("Macro not defined (or wrong signature)."); Input_skip_remainder(); } else { // make macro_node point to the macro struct actual_macro = macro_node->body; local_gotbyte = GotByte;// CAUTION - ugly kluge // set up new input new_input.original_filename = actual_macro->def_filename; new_input.line_number = actual_macro->def_line_number; new_input.source_is_ram = TRUE; new_input.state = INPUTSTATE_NORMAL; // FIXME - fix others! new_input.src.ram_ptr = actual_macro->parameter_list; // remember old input outer_input = Input_now; // activate new input Input_now = &new_input; // remember old section outer_section = Section_now; // start new section (with new zone) // FALSE = title mustn't be freed Section_new_zone(&new_section, "Macro", actual_macro->original_name, FALSE); GetByte(); // fetch first byte of parameter list // assign arguments if(GotByte != CHAR_EOS) { // any at all? arg_count = 0; do { // Decide whether call-by-reference // or call-by-value // In both cases, GlobalDynaBuf may be used. if(GotByte == REFERENCE_CHAR) { // assign call-by-reference arg GetByte(); // skip '~' character Input_read_zone_and_keyword(&label_zone); if((Tree_hard_scan(&label_node, Label_forest, label_zone, TRUE) == FALSE) && (pass_count == 0)) Throw_error("Macro parameter twice."); label_node->body = arg_table[arg_count].label; } else { // assign call-by-value arg Input_read_zone_and_keyword(&label_zone); label = Label_find(label_zone, 0); // FIXME - add a possibility to Label_find to make it possible to find out // whether label was just created. Then check for the same error message here // as above ("Macro parameter twice."). label->result = arg_table[arg_count].result; } arg_count++; } while(Input_accept_comma()); } // and now, finally, parse the actual macro body Input_now->state = INPUTSTATE_NORMAL; // FIXME - fix others! // maybe call parse_ram_block(actual_macro->def_line_number, actual_macro->body) Input_now->src.ram_ptr = actual_macro->body; Parse_until_eob_or_eof(); if(GotByte != CHAR_EOB) Bug_found("IllegalBlockTerminator", GotByte); // end section (free title memory, if needed) Section_finalize(&new_section); // restore previous section Section_now = outer_section; // restore previous input: Input_now = outer_input; // restore old Gotbyte context GotByte = local_gotbyte;// CAUTION - ugly kluge Input_ensure_EOS(); } macro_recursions_left++; // leave this nesting level } CheeseCutter-master/src/asm/macro.h000066400000000000000000000010051357241101300175440ustar00rootroot00000000000000// // ACME - a crossassembler for producing 6502/65c02/65816 code. // Copyright (C) 1998-2006 Marco Baye // Have a look at "acme.c" for further info // // Macro stuff #ifndef macro_H #define macro_H #include "config.h" // Prototypes // create dynamic buffers and arg table extern void Macro_init(void); // create private dynabuf // only call once (during first pass) extern void Macro_parse_definition(void); // Parse macro call ("+MACROTITLE"). Has to be re-entrant. extern void Macro_parse_call(void); #endif CheeseCutter-master/src/asm/mnemo.c000066400000000000000000001137651357241101300175720ustar00rootroot00000000000000// // ACME - a crossassembler for producing 6502/65c02/65816 code. // Copyright (C) 1998-2006 Marco Baye // Have a look at "acme.c" for further info // // Mnemonics stuff #include "config.h" #include "alu.h" #include "cpu.h" #include "dynabuf.h" #include "global.h" #include "input.h" #include "output.h" #include "tree.h" // Constants #define s_ror (s_error+2) // Yes, I know I'm sick #define MNEMO_DYNABUF_INITIALSIZE 8 // 4+terminator should suffice // These values are needed to recognize addressing modes. // Bits: // 7....... "Implied" no value given // .6...... "Immediate" "#" at start // ..5..... "IndirectLong" "[" at start and "]" after value // ...4.... "Indirect" Value has at least one unnecessary pair of "()" // ....32.. "Indexed-Int" Index given inside of "()" // ......10 "Indexed-Ext" Index given outside of (or without any) "()" // // Index bits: // 00 = no index // 01 = ",s" (Stack-indexed) // 10 = ",x" (X-indexed) // 11 = ",y" (Y-indexed) // Components (Values for indices) #define HAM__ (0u << 0) // No index #define HAM_S (1u << 0) // Stack-indexed #define HAM_X (2u << 0) // X-indexed #define HAM_Y (3u << 0) // Y-indexed // End values base value internal index external index #define HAM_IMP (1u << 7) #define HAM_IMM (1u << 6) #define HAM_ABS 0 #define HAM_ABSS (1u << 0) #define HAM_ABSX (2u << 0) #define HAM_ABSY (3u << 0) #define HAM_IND (1u << 4) #define HAM_XIND ((1u << 4)| (2u << 2)) #define HAM_INDY ((1u << 4)| (3u << 0)) #define HAM_SINDY ((1u << 4)| (1u << 2)| (3u << 0)) #define HAM_LIND (1u << 5) #define HAM_LINDY ((1u << 5)| (3u << 0)) // Values of internal indices equal values of external indices, shifted left // by two bits. The program relies on this ! // Constant values, used to mark the possible parameter lengths of commands. // Not all of the eight values are actually used, however (because of the // supported CPUs). #define MAYBE______ (0) #define MAYBE_1____ (MVALUE_FORCE08) #define MAYBE___2__ (MVALUE_FORCE16) #define MAYBE_1_2__ (MVALUE_FORCE08 | MVALUE_FORCE16) #define MAYBE_____3 (MVALUE_FORCE24) #define MAYBE_1___3 (MVALUE_FORCE08 | MVALUE_FORCE24) #define MAYBE___2_3 (MVALUE_FORCE16 | MVALUE_FORCE24) #define MAYBE_1_2_3 (MVALUE_FORCE08 | MVALUE_FORCE16 | MVALUE_FORCE24) // The mnemonics are split up into groups, each group has its own function to // be dealt with: // G_IMPLIED Mnemonics using only implied addressing. Byte value = opcode // G_MAIN The main accumulator stuff (plus PEI) Byte value = table index // G_MISC Most of the other opcodes Byte value = table index // G_REL_SHORT The short branch instructions. Byte value = opcode // G_REL_LONG Mnemonics with 16bit relative addressing. Byte value = opcode // G_JUMP The jump instructions Byte value = table index // G_MOVE The "move" commands. Byte value = opcode enum mnemogroup_t { G_IMPLIED, // only implied addressing G_MAIN, // main accumulator stuff (plus PEI) G_MISC, // misc G_REL_SHORT, // short relative G_REL_LONG, // long relative G_JUMP, // jump G_MOVE // MVP, MVN }; // save some space #define SCB static const unsigned char #define SCS static const unsigned short #define SCL static const unsigned long // Code tables for group G_MAIN: // These tables are used for the main accumulator-related mnemonics. By reading // the mnemonic's byte value (from the mnemotable), the assembler finds out the // column to use here. The row depends on the used addressing mode. A zero // entry in these tables means that the combination of mnemonic and addressing // mode is illegal. enum { IDX_ORA, IDX_AND, IDX_EOR, IDX_ADC, IDX_STA, IDX_LDA, IDX_CMP, IDX_SBC, IDXC_ORA, IDXC_AND, IDXC_EOR, IDXC_ADC, IDXC_STA, IDXC_LDA, IDXC_CMP, IDXC_SBC, IDX8_ORA, IDX8_AND, IDX8_EOR, IDX8_ADC, IDX8_STA, IDX8_LDA, IDX8_CMP, IDX8_SBC, IDX8_PEI, IDXI_SLO, IDXI_RLA, IDXI_SRE, IDXI_RRA, IDXI_SAX, IDXI_LAX, IDXI_DCP, IDXI_ISC}; // | 6502 | 65c02 | 65816 | 6510 | // | ora and eor adc sta lda cmp sbc| ora and eor adc sta lda cmp sbc| ora and eor adc sta lda cmp sbc pei| slo rla sre rra sax lax dcp isc| SCB accu_imm[] = { 0x09, 0x29, 0x49, 0x69, 0, 0xa9, 0xc9, 0xe9, 0x09, 0x29, 0x49, 0x69, 0, 0xa9, 0xc9, 0xe9, 0x09, 0x29, 0x49, 0x69, 0, 0xa9, 0xc9, 0xe9, 0, 0, 0, 0, 0, 0, 0, 0, 0};// #$ff/#$ffff SCB accu_sabs8[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x03, 0x23, 0x43, 0x63, 0x83, 0xa3, 0xc3, 0xe3, 0, 0, 0, 0, 0, 0, 0, 0, 0};// $ff,s SCB accu_xind8[] = { 0x01, 0x21, 0x41, 0x61, 0x81, 0xa1, 0xc1, 0xe1, 0x01, 0x21, 0x41, 0x61, 0x81, 0xa1, 0xc1, 0xe1, 0x01, 0x21, 0x41, 0x61, 0x81, 0xa1, 0xc1, 0xe1, 0, 0x03, 0x23, 0x43, 0x63, 0x83, 0xa3, 0xc3, 0xe3};// ($ff,x) SCB accu_sindy8[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x13, 0x33, 0x53, 0x73, 0x93, 0xb3, 0xd3, 0xf3, 0, 0, 0, 0, 0, 0, 0, 0, 0};// ($ff,s),y SCB accu_ind8[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0x12, 0x32, 0x52, 0x72, 0x92, 0xb2, 0xd2, 0xf2, 0x12, 0x32, 0x52, 0x72, 0x92, 0xb2, 0xd2, 0xf2,0xd4, 0, 0, 0, 0, 0, 0, 0, 0};// ($ff) SCB accu_indy8[] = { 0x11, 0x31, 0x51, 0x71, 0x91, 0xb1, 0xd1, 0xf1, 0x11, 0x31, 0x51, 0x71, 0x91, 0xb1, 0xd1, 0xf1, 0x11, 0x31, 0x51, 0x71, 0x91, 0xb1, 0xd1, 0xf1, 0, 0x13, 0x33, 0x53, 0x73, 0, 0xb3, 0xd3, 0xf3};// ($ff),y SCB accu_lind8[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x07, 0x27, 0x47, 0x67, 0x87, 0xa7, 0xc7, 0xe7, 0, 0, 0, 0, 0, 0, 0, 0, 0};// [$ff] SCB accu_lindy8[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x17, 0x37, 0x57, 0x77, 0x97, 0xb7, 0xd7, 0xf7, 0, 0, 0, 0, 0, 0, 0, 0, 0};// [$ff],y SCL accu_abs[] = {0x0d05,0x2d25,0x4d45,0x6d65,0x8d85,0xada5,0xcdc5,0xede5,0x0d05,0x2d25,0x4d45,0x6d65,0x8d85,0xada5,0xcdc5,0xede5,0x0f0d05,0x2f2d25,0x4f4d45,0x6f6d65,0x8f8d85,0xafada5,0xcfcdc5,0xefede5, 0,0x0f07,0x2f27,0x4f47,0x6f67,0x8f87,0xafa7,0xcfc7,0xefe7};// $ff /$ffff /$ffffff SCL accu_xabs[] = {0x1d15,0x3d35,0x5d55,0x7d75,0x9d95,0xbdb5,0xddd5,0xfdf5,0x1d15,0x3d35,0x5d55,0x7d75,0x9d95,0xbdb5,0xddd5,0xfdf5,0x1f1d15,0x3f3d35,0x5f5d55,0x7f7d75,0x9f9d95,0xbfbdb5,0xdfddd5,0xfffdf5, 0,0x1f17,0x3f37,0x5f57,0x7f77, 0, 0,0xdfd7,0xfff7};// $ff,x/$ffff,x/$ffffff,x SCS accu_yabs[] = {0x1900,0x3900,0x5900,0x7900,0x9900,0xb900,0xd900,0xf900,0x1900,0x3900,0x5900,0x7900,0x9900,0xb900,0xd900,0xf900, 0x1900, 0x3900, 0x5900, 0x7900, 0x9900, 0xb900, 0xd900, 0xf900, 0,0x1b00,0x3b00,0x5b00,0x7b00, 0x97,0xbfb7,0xdb00,0xfb00};// $ff,y/$ffff,y // Code tables for group G_MISC: // These tables are needed for finding out the correct code in cases when // there are no general rules. By reading the mnemonic's byte value (from the // mnemotable), the assembler finds out the column to use here. The row // depends on the used addressing mode. A zero entry in these tables means // that the combination of mnemonic and addressing mode is illegal. enum { IDX_BIT, IDX_ASL, IDX_ROL, IDX_LSR, IDX_ROR, IDX_STY, IDX_STX, IDX_LDY, IDX_LDX, IDX_CPY, IDX_CPX, IDX_DEC, IDX_INC, IDXC_TSB, IDXC_TRB, IDXC_BIT, IDXC_DEC, IDXC_INC, IDXC_STZ, IDX8_COP, IDX8_REP, IDX8_SEP, IDX8_PEA, IDXI_ANC, IDXI_ASR, IDXI_ARR, IDXI_SBX, IDXI_DOP, IDXI_TOP, IDXI_JAM}; // | 6502 | 65c02 | 65816 | 6510 | // | bit asl rol lsr ror sty stx ldy ldx cpy cpx dec inc| tsb trb bit dec inc stz| cop rep sep pea| anc asr arr sbx dop top jam| SCB misc_impl[] = { 0, 0x0a, 0x2a, 0x4a, 0x6a, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x3a, 0x1a, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x80, 0x0c,0x02};// implied/accu SCB misc_imm[] = { 0, 0, 0, 0, 0, 0, 0, 0xa0, 0xa2, 0xc0, 0xe0, 0, 0, 0, 0, 0x89, 0, 0, 0, 0,0xc2,0xe2, 0,0x2b,0x4b,0x6b,0xcb,0x80, 0, 0};// #$ff SCS misc_abs[] = {0x2c24,0x0e06,0x2e26,0x4e46,0x6e66,0x8c84,0x8e86,0xaca4,0xaea6,0xccc4,0xece4,0xcec6,0xeee6,0x0c04,0x1c14,0x2c24,0xcec6,0xeee6,0x9c64,0x02, 0, 0,0xf400, 0, 0, 0, 0,0x04,0x0c00, 0};// $ff/$ffff SCS misc_xabs[] = { 0,0x1e16,0x3e36,0x5e56,0x7e76, 0x94, 0,0xbcb4, 0, 0, 0,0xded6,0xfef6, 0, 0,0x3c34,0xded6,0xfef6,0x9e74, 0, 0, 0, 0, 0, 0, 0, 0,0x14,0x1c00, 0};// $ff,x/$ffff,x SCS misc_yabs[] = { 0, 0, 0, 0, 0, 0, 0x96, 0,0xbeb6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};// $ff,y/$ffff,y // Code tables for group G_JUMP: // // These tables are needed for finding out the correct code when the mnemonic // is "jmp" or "jsr" (or the long versions "jml" and "jsl"). // By reading the mnemonic's byte value (from the mnemotable), the assembler // finds out the column to use here. The row depends on the used addressing // mode. A zero entry in these tables means that the combination of mnemonic // and addressing mode is illegal. enum { IDX_JMP, IDX_JSR, IDXC_JMP, IDX8_JMP, IDX8_JML, IDX8_JSR, IDX8_JSL}; // | 6502 | 65c02| 65816 | // | jmp jsr | jmp | jmp jml jsr jsl | SCL jump_abs[] = {0x4c00,0x2000,0x4c00,0x5c4c00,0x5c0000,0x222000,0x220000};// $ffff/$ffffff SCS jump_ind[] = {0x6c00, 0,0x6c00, 0x6c00, 0, 0, 0};// ($ffff) SCS jump_xind[] = { 0, 0,0x7c00, 0x7c00, 0, 0xfc00, 0};// ($ffff,x) SCS jump_lind[] = { 0, 0, 0, 0xdc00, 0xdc00, 0, 0};// [$ffff] #undef SCB #undef SCS #undef SCL // error message strings static const char exception_illegal_combination[] = "Illegal combination of command and addressing mode."; static const char exception_highbyte_zero[]= "Using oversized addressing mode."; static const char exception_too_far[] = "Target out of range."; // Variables static dynabuf_t* mnemo_dyna_buf; // dynamic buffer for mnemonics // predefined stuff static node_t* mnemo_6502_tree = NULL;// holds 6502 mnemonics static node_t* mnemo_6510_tree = NULL;// holds 6510 extensions static node_t* mnemo_65c02_tree= NULL;// holds 65c02 extensions //static node_t* mnemo_Rockwell65c02_tree = NULL;// Rockwell static node_t* mnemo_WDC65c02_tree = NULL;// WDC's "stp"/"wai" static node_t* mnemo_65816_tree = NULL;// holds 65816 extensions // Command's code and group values are stored together in a single integer. // To extract the code, use "& CODEMASK". // To extract the group, use ">> GROUPSHIFT" #define CODEMASK 0xff // opcode or table index #define FLAGSMASK 0x300 // flags concerning immediate addressing: #define IMM_ACCU 0x100 // ...depends on accumulator length #define IMM_IDX 0x200 // ...depends on index register length #define GROUPSHIFT 10 // shift right by this to extract group #define MERGE(g, v) ((g << GROUPSHIFT) | v) static node_t mnemos_6502[] = { PREDEFNODE("ora", MERGE(G_MAIN , IDX_ORA | IMM_ACCU)), PREDEFNODE(s_and, MERGE(G_MAIN , IDX_AND | IMM_ACCU)), PREDEFNODE(s_eor, MERGE(G_MAIN , IDX_EOR | IMM_ACCU)), PREDEFNODE("adc", MERGE(G_MAIN , IDX_ADC | IMM_ACCU)), PREDEFNODE("sta", MERGE(G_MAIN , IDX_STA)), PREDEFNODE("lda", MERGE(G_MAIN , IDX_LDA | IMM_ACCU)), PREDEFNODE("cmp", MERGE(G_MAIN , IDX_CMP | IMM_ACCU)), PREDEFNODE("sbc", MERGE(G_MAIN , IDX_SBC | IMM_ACCU)), PREDEFNODE("bit", MERGE(G_MISC , IDX_BIT | IMM_ACCU)), PREDEFNODE(s_asl, MERGE(G_MISC , IDX_ASL)), PREDEFNODE("rol", MERGE(G_MISC , IDX_ROL)), PREDEFNODE(s_lsr, MERGE(G_MISC , IDX_LSR)), PREDEFNODE(s_ror, MERGE(G_MISC , IDX_ROR)), PREDEFNODE("sty", MERGE(G_MISC , IDX_STY)), PREDEFNODE("stx", MERGE(G_MISC , IDX_STX)), PREDEFNODE("ldy", MERGE(G_MISC , IDX_LDY | IMM_IDX)), PREDEFNODE("ldx", MERGE(G_MISC , IDX_LDX | IMM_IDX)), PREDEFNODE("cpy", MERGE(G_MISC , IDX_CPY | IMM_IDX)), PREDEFNODE("cpx", MERGE(G_MISC , IDX_CPX | IMM_IDX)), PREDEFNODE("dec", MERGE(G_MISC , IDX_DEC)), PREDEFNODE("inc", MERGE(G_MISC , IDX_INC)), PREDEFNODE("bpl", MERGE(G_REL_SHORT , 16)), PREDEFNODE("bmi", MERGE(G_REL_SHORT , 48)), PREDEFNODE("bvc", MERGE(G_REL_SHORT , 80)), PREDEFNODE("bvs", MERGE(G_REL_SHORT , 112)), PREDEFNODE("bcc", MERGE(G_REL_SHORT , 144)), PREDEFNODE("bcs", MERGE(G_REL_SHORT , 176)), PREDEFNODE("bne", MERGE(G_REL_SHORT , 208)), PREDEFNODE("beq", MERGE(G_REL_SHORT , 240)), PREDEFNODE("jmp", MERGE(G_JUMP , IDX_JMP)), PREDEFNODE("jsr", MERGE(G_JUMP , IDX_JSR)), PREDEFNODE("brk", MERGE(G_IMPLIED , 0)), PREDEFNODE("php", MERGE(G_IMPLIED , 8)), PREDEFNODE("clc", MERGE(G_IMPLIED , 24)), PREDEFNODE("plp", MERGE(G_IMPLIED , 40)), PREDEFNODE("sec", MERGE(G_IMPLIED , 56)), PREDEFNODE("rti", MERGE(G_IMPLIED , 64)), PREDEFNODE("pha", MERGE(G_IMPLIED , 72)), PREDEFNODE("cli", MERGE(G_IMPLIED , 88)), PREDEFNODE("rts", MERGE(G_IMPLIED , 96)), PREDEFNODE("pla", MERGE(G_IMPLIED , 104)), PREDEFNODE("sei", MERGE(G_IMPLIED , 120)), PREDEFNODE("dey", MERGE(G_IMPLIED , 136)), PREDEFNODE("txa", MERGE(G_IMPLIED , 138)), PREDEFNODE("tya", MERGE(G_IMPLIED , 152)), PREDEFNODE("txs", MERGE(G_IMPLIED , 154)), PREDEFNODE("tay", MERGE(G_IMPLIED , 168)), PREDEFNODE("tax", MERGE(G_IMPLIED , 170)), PREDEFNODE("clv", MERGE(G_IMPLIED , 184)), PREDEFNODE("tsx", MERGE(G_IMPLIED , 186)), PREDEFNODE("iny", MERGE(G_IMPLIED , 200)), PREDEFNODE("dex", MERGE(G_IMPLIED , 202)), PREDEFNODE("cld", MERGE(G_IMPLIED , 216)), PREDEFNODE("inx", MERGE(G_IMPLIED , 232)), PREDEFNODE("nop", MERGE(G_IMPLIED , 234)), PREDEFLAST("sed", MERGE(G_IMPLIED , 248)), // ^^^^ this marks the last element }; static node_t mnemos_6510[] = { PREDEFNODE("slo", MERGE(G_MAIN, IDXI_SLO)),// ASL+ORA, ASO PREDEFNODE("rla", MERGE(G_MAIN, IDXI_RLA)),// ROL+AND PREDEFNODE("sre", MERGE(G_MAIN, IDXI_SRE)),// LSR+EOR, LSE PREDEFNODE("rra", MERGE(G_MAIN, IDXI_RRA)),// ROR+ADC PREDEFNODE("sax", MERGE(G_MAIN, IDXI_SAX)),// STX+STA, AAX, AXS PREDEFNODE("lax", MERGE(G_MAIN, IDXI_LAX)),// LDX+LDA PREDEFNODE("dcp", MERGE(G_MAIN, IDXI_DCP)),// DEC+CMP, DCM PREDEFNODE("isc", MERGE(G_MAIN, IDXI_ISC)),// INC+SBC, ISB, INS PREDEFNODE("anc", MERGE(G_MISC, IDXI_ANC)),// ROL+AND, ASL+ORA, AAC PREDEFNODE(s_asr, MERGE(G_MISC, IDXI_ASR)),// LSR+EOR, ALR PREDEFNODE("arr", MERGE(G_MISC, IDXI_ARR)),// ROR+ADC PREDEFNODE("sbx", MERGE(G_MISC, IDXI_SBX)),// DEX+CMP, AXS, SAX PREDEFNODE("dop", MERGE(G_MISC, IDXI_DOP)),// skip next byte PREDEFNODE("top", MERGE(G_MISC, IDXI_TOP)),// skip next two bytes PREDEFLAST("jam", MERGE(G_MISC, IDXI_JAM)),// jam/crash/halt/kill // ^^^^ this marks the last element }; static node_t mnemos_65c02[] = { PREDEFNODE("ora", MERGE(G_MAIN , IDXC_ORA | IMM_ACCU)), PREDEFNODE(s_and, MERGE(G_MAIN , IDXC_AND | IMM_ACCU)), PREDEFNODE(s_eor, MERGE(G_MAIN , IDXC_EOR | IMM_ACCU)), PREDEFNODE("adc", MERGE(G_MAIN , IDXC_ADC | IMM_ACCU)), PREDEFNODE("sta", MERGE(G_MAIN , IDXC_STA)), PREDEFNODE("lda", MERGE(G_MAIN , IDXC_LDA | IMM_ACCU)), PREDEFNODE("cmp", MERGE(G_MAIN , IDXC_CMP | IMM_ACCU)), PREDEFNODE("sbc", MERGE(G_MAIN , IDXC_SBC | IMM_ACCU)), PREDEFNODE("jmp", MERGE(G_JUMP , IDXC_JMP)), PREDEFNODE("bit", MERGE(G_MISC , IDXC_BIT | IMM_ACCU)), PREDEFNODE("dec", MERGE(G_MISC , IDXC_DEC)), PREDEFNODE("inc", MERGE(G_MISC , IDXC_INC)), PREDEFNODE("bra", MERGE(G_REL_SHORT , 128)), PREDEFNODE("phy", MERGE(G_IMPLIED , 90)), PREDEFNODE("ply", MERGE(G_IMPLIED , 122)), PREDEFNODE("phx", MERGE(G_IMPLIED , 218)), PREDEFNODE("plx", MERGE(G_IMPLIED , 250)), PREDEFNODE("tsb", MERGE(G_MISC , IDXC_TSB)), PREDEFNODE("trb", MERGE(G_MISC , IDXC_TRB)), PREDEFLAST("stz", MERGE(G_MISC , IDXC_STZ)), // ^^^^ this marks the last element }; //static node_t mnemos_Rockwell65c02[] = { // PREDEFNODE("rmb0", MERGE(G_ , 0x07)), // PREDEFNODE("rmb1", MERGE(G_ , 0x17)), // PREDEFNODE("rmb2", MERGE(G_ , 0x27)), // PREDEFNODE("rmb3", MERGE(G_ , 0x37)), // PREDEFNODE("rmb4", MERGE(G_ , 0x47)), // PREDEFNODE("rmb5", MERGE(G_ , 0x57)), // PREDEFNODE("rmb6", MERGE(G_ , 0x67)), // PREDEFNODE("rmb7", MERGE(G_ , 0x77)), // PREDEFNODE("smb0", MERGE(G_ , 0x87)), // PREDEFNODE("smb1", MERGE(G_ , 0x97)), // PREDEFNODE("smb2", MERGE(G_ , 0xa7)), // PREDEFNODE("smb3", MERGE(G_ , 0xb7)), // PREDEFNODE("smb4", MERGE(G_ , 0xc7)), // PREDEFNODE("smb5", MERGE(G_ , 0xd7)), // PREDEFNODE("smb6", MERGE(G_ , 0xe7)), // PREDEFNODE("smb7", MERGE(G_ , 0xf7)), // PREDEFNODE("bbr0", MERGE(G_ , 0x0f)), // PREDEFNODE("bbr1", MERGE(G_ , 0x1f)), // PREDEFNODE("bbr2", MERGE(G_ , 0x2f)), // PREDEFNODE("bbr3", MERGE(G_ , 0x3f)), // PREDEFNODE("bbr4", MERGE(G_ , 0x4f)), // PREDEFNODE("bbr5", MERGE(G_ , 0x5f)), // PREDEFNODE("bbr6", MERGE(G_ , 0x6f)), // PREDEFNODE("bbr7", MERGE(G_ , 0x7f)), // PREDEFNODE("bbs0", MERGE(G_ , 0x8f)), // PREDEFNODE("bbs1", MERGE(G_ , 0x9f)), // PREDEFNODE("bbs2", MERGE(G_ , 0xaf)), // PREDEFNODE("bbs3", MERGE(G_ , 0xbf)), // PREDEFNODE("bbs4", MERGE(G_ , 0xcf)), // PREDEFNODE("bbs5", MERGE(G_ , 0xdf)), // PREDEFNODE("bbs6", MERGE(G_ , 0xef)), // PREDEFLAST("bbs7", MERGE(G_ , 0xff)), // // ^^^^ this marks the last element //}; static node_t mnemos_WDC65c02[] = { PREDEFNODE("stp", MERGE(G_IMPLIED , 219)), PREDEFLAST("wai", MERGE(G_IMPLIED , 203)), // ^^^^ this marks the last element }; static node_t mnemos_65816[] = { PREDEFNODE("ora", MERGE(G_MAIN , IDX8_ORA | IMM_ACCU)), PREDEFNODE(s_and, MERGE(G_MAIN , IDX8_AND | IMM_ACCU)), PREDEFNODE(s_eor, MERGE(G_MAIN , IDX8_EOR | IMM_ACCU)), PREDEFNODE("adc", MERGE(G_MAIN , IDX8_ADC | IMM_ACCU)), PREDEFNODE("sta", MERGE(G_MAIN , IDX8_STA)), PREDEFNODE("lda", MERGE(G_MAIN , IDX8_LDA | IMM_ACCU)), PREDEFNODE("cmp", MERGE(G_MAIN , IDX8_CMP | IMM_ACCU)), PREDEFNODE("sbc", MERGE(G_MAIN , IDX8_SBC | IMM_ACCU)), PREDEFNODE("pei", MERGE(G_MAIN , IDX8_PEI)), PREDEFNODE("jmp", MERGE(G_JUMP , IDX8_JMP)), PREDEFNODE("jsr", MERGE(G_JUMP , IDX8_JSR)), PREDEFNODE("jml", MERGE(G_JUMP , IDX8_JML)), PREDEFNODE("jsl", MERGE(G_JUMP , IDX8_JSL)), PREDEFNODE("mvp", MERGE(G_MOVE , 0x44)), PREDEFNODE("mvn", MERGE(G_MOVE , 0x54)), PREDEFNODE("per", MERGE(G_REL_LONG , 98)), PREDEFNODE(s_brl, MERGE(G_REL_LONG , 130)), PREDEFNODE("cop", MERGE(G_MISC , IDX8_COP)), PREDEFNODE("rep", MERGE(G_MISC , IDX8_REP)), PREDEFNODE("sep", MERGE(G_MISC , IDX8_SEP)), PREDEFNODE("pea", MERGE(G_MISC , IDX8_PEA)), PREDEFNODE("phd", MERGE(G_IMPLIED , 11)), PREDEFNODE("tcs", MERGE(G_IMPLIED , 27)), PREDEFNODE("pld", MERGE(G_IMPLIED , 43)), PREDEFNODE("tsc", MERGE(G_IMPLIED , 59)), PREDEFNODE("wdm", MERGE(G_IMPLIED , 66)), PREDEFNODE("phk", MERGE(G_IMPLIED , 75)), PREDEFNODE("tcd", MERGE(G_IMPLIED , 91)), PREDEFNODE("rtl", MERGE(G_IMPLIED , 107)), PREDEFNODE("tdc", MERGE(G_IMPLIED , 123)), PREDEFNODE("phb", MERGE(G_IMPLIED , 139)), PREDEFNODE("txy", MERGE(G_IMPLIED , 155)), PREDEFNODE("plb", MERGE(G_IMPLIED , 171)), PREDEFNODE("tyx", MERGE(G_IMPLIED , 187)), PREDEFNODE("xba", MERGE(G_IMPLIED , 235)), PREDEFLAST("xce", MERGE(G_IMPLIED , 251)), // ^^^^ this marks the last element }; // Functions // create dynamic buffer, build keyword trees void Mnemo_init(void) { mnemo_dyna_buf = DynaBuf_create(MNEMO_DYNABUF_INITIALSIZE); Tree_add_table(&mnemo_6502_tree, mnemos_6502); Tree_add_table(&mnemo_6510_tree, mnemos_6510); Tree_add_table(&mnemo_65c02_tree, mnemos_65c02); // Tree_add_table(&mnemo_Rockwell65c02_tree, mnemos_Rockwell65c02); Tree_add_table(&mnemo_WDC65c02_tree, mnemos_WDC65c02); Tree_add_table(&mnemo_65816_tree, mnemos_65816); } // Address mode parsing // Utility function for parsing indices. static int get_index(bool next) { int addressing_mode = HAM__; if(next) GetByte(); if(!Input_accept_comma()) return(addressing_mode); switch(GotByte) { case 's': case 'S': addressing_mode = HAM_S; break; case 'x': case 'X': addressing_mode = HAM_X; break; case 'y': case 'Y': addressing_mode = HAM_Y; break; default: Throw_error(exception_syntax); } if(addressing_mode != HAM__) NEXTANDSKIPSPACE(); return(addressing_mode); } // This function stores the command's argument in the given result_int_t // structure (using the valueparser). The addressing mode is returned. static int get_argument(result_int_t* result) { int open_paren, addressing_mode = HAM_ABS; SKIPSPACE(); switch(GotByte) { case '[': GetByte();// proceed with next char ALU_int_result(result); if(GotByte == ']') addressing_mode |= HAM_LIND | get_index(TRUE); else Throw_error(exception_syntax); break; case '#': GetByte();// proceed with next char addressing_mode |= HAM_IMM; ALU_int_result(result); break; default: // liberal, to allow for "(...," open_paren = ALU_liberal_int(result); // check for implied addressing if((result->flags & MVALUE_EXISTS) == 0) addressing_mode |= HAM_IMP; // check for indirect addressing if(result->flags & MVALUE_INDIRECT) addressing_mode |= HAM_IND; // check for internal index (before closing parenthesis) if(open_paren) { // in case there are still open parentheses, // read internal index addressing_mode |= (get_index(FALSE) << 2); if(GotByte == ')') GetByte();// go on with next char else Throw_error(exception_syntax); } // check for external index (after closing parenthesis) addressing_mode |= get_index(FALSE); break; } // ensure end of line Input_ensure_EOS(); //printf("AM: %x\n", addressing_mode); return(addressing_mode); } // Helper function for calc_arg_size() // Only call with "size_bit = MVALUE_FORCE16" or "size_bit = MVALUE_FORCE24" static int check_oversize(int size_bit, result_int_t* argument) { // only check if value is *defined* if((argument->flags & MVALUE_DEFINED) == 0) return(size_bit);// pass on result // value is defined, so check if(size_bit == MVALUE_FORCE16) { // check 16-bit argument for high byte zero if((argument->intval <= 255) && (argument->intval >= -128)) Throw_warning(exception_highbyte_zero); } else // check 24-bit argument for bank byte zero if((argument->intval <= 65535) && (argument->intval >= -32768)) Throw_warning(exception_highbyte_zero); return(size_bit);// pass on result } // Utility function for comparing force bits, argument value, argument size, // "unsure"-flag and possible addressing modes. Returns force bit matching // number of parameter bytes to send. If it returns zero, an error occurred // (and has already been delivered). // force_bit none, 8b, 16b, 24b // argument value and flags of parameter // addressing_modes adressing modes (8b, 16b, 24b or any combination) // Return value = force bit for number of parameter bytes to send (0 = error) static int calc_arg_size(int force_bit, result_int_t* argument, int addressing_modes) { // If there are no possible addressing modes, complain if(addressing_modes == MAYBE______) { Throw_error(exception_illegal_combination); return(0); } // If command has force bit, act upon it if(force_bit) { // If command allows this force bit, return it if(addressing_modes & force_bit) return(force_bit); // If not, complain Throw_error("Illegal combination of command and postfix."); return(0); } // Command has no force bit. Check whether value has one // If value has force bit, act upon it if(argument->flags & MVALUE_FORCEBITS) { // Value has force bit set, so return this or bigger size if(MVALUE_FORCE08 & addressing_modes & argument->flags) return(MVALUE_FORCE08); if(MVALUE_FORCE16 & addressing_modes & argument->flags) return(MVALUE_FORCE16); if(MVALUE_FORCE24 & addressing_modes) return(MVALUE_FORCE24); Throw_error(exception_number_out_of_range);// else error return(0); } // Value has no force bit. Check whether there's only one addr mode // If only one addressing mode, use that if((addressing_modes == MVALUE_FORCE08) || (addressing_modes == MVALUE_FORCE16) || (addressing_modes == MVALUE_FORCE24)) return(addressing_modes);// There's only one, so use it // There's more than one addressing mode. Check whether value is sure // If value is unsure, use default size if(argument->flags & MVALUE_UNSURE) { // If there is an 8-bit addressing mode *and* the value // is sure to fit into 8 bits, use the 8-bit mode if((addressing_modes & MVALUE_FORCE08) && (argument->flags & MVALUE_ISBYTE)) return(MVALUE_FORCE08); // If there is a 16-bit addressing, use that // Call helper function for "oversized addr mode" warning if(MVALUE_FORCE16 & addressing_modes) return(check_oversize(MVALUE_FORCE16, argument)); // If there is a 24-bit addressing, use that // Call helper function for "oversized addr mode" warning if(MVALUE_FORCE24 & addressing_modes) return(check_oversize(MVALUE_FORCE24, argument)); // otherwise, use 8-bit-addressing, which will raise an // error later on if the value won't fit return(MVALUE_FORCE08); } // Value is sure, so use its own size // If value is negative, size cannot be chosen. Complain! if(argument->intval < 0) { Throw_error("Negative value - cannot choose addressing mode."); return(0); } // Value is positive or zero. Check size ranges // If there is an 8-bit addressing mode and value fits, use 8 bits if((addressing_modes & MVALUE_FORCE08) && (argument->intval < 256)) return(MVALUE_FORCE08); // If there is a 16-bit addressing mode and value fits, use 16 bits if((addressing_modes & MVALUE_FORCE16) && (argument->intval < 65536)) return(MVALUE_FORCE16); // If there is a 24-bit addressing mode, use that. In case the // value doesn't fit, the output function will do the complaining. if(addressing_modes & MVALUE_FORCE24) return(MVALUE_FORCE24); // Value is too big for all possible addressing modes Throw_error(exception_number_out_of_range); return(0); } // Mnemonics using only implied addressing. static void group_only_implied_addressing(int opcode) { Output_byte(opcode); Input_ensure_EOS(); } // Mnemonics using only 8bit relative addressing (short branch instructions). static void group_only_relative8_addressing(int opcode) { result_int_t result; ALU_int_result(&result); if(result.flags & MVALUE_DEFINED) { result.intval -= (CPU_pc.intval + 2); if((result.intval > 127) || (result.intval < -128)) Throw_error(exception_too_far); } Output_byte(opcode); // this fn has its own range check (see above). // No reason to irritate the user with another error message, // so use Output_byte() instead of Output_8b() //Output_8b(result.value); Output_byte(result.intval); Input_ensure_EOS(); } // Mnemonics using only 16bit relative addressing (BRL and PER). static void group_only_relative16_addressing(int opcode) { result_int_t result; ALU_int_result(&result); if(result.flags & MVALUE_DEFINED) { result.intval -= (CPU_pc.intval + 3); if((result.intval > 32767) || (result.intval < -32768)) Throw_error(exception_too_far); } Output_byte(opcode); // this fn has its own range check (see above). // No reason to irritate the user with another error message, // so use Output_byte() instead of Output_16b() //Output_16b(result.value); Output_byte(result.intval); Output_byte(result.intval >> 8); Input_ensure_EOS(); } // set addressing mode bits depending on which opcodes exist, then calculate // argument size and output both opcode and argument static void make_command(int force_bit, result_int_t* result, unsigned long opcodes) { int addressing_modes = MAYBE______; if(opcodes & 0x0000ff) addressing_modes |= MAYBE_1____; if(opcodes & 0x00ff00) addressing_modes |= MAYBE___2__; if(opcodes & 0xff0000) addressing_modes |= MAYBE_____3; switch(calc_arg_size(force_bit, result, addressing_modes)) { case MVALUE_FORCE08: Output_byte(opcodes & 255); Output_8b(result->intval); break; case MVALUE_FORCE16: Output_byte((opcodes >> 8) & 255); Output_16b(result->intval); break; case MVALUE_FORCE24: Output_byte((opcodes >> 16) & 255); Output_24b(result->intval); break; } } // check whether 16bit immediate addressing is allowed. If not, return given // opcode. If it is allowed, set force bits according to CPU register length // and return given opcode for both 8- and 16-bit mode. static unsigned int imm_ops(int *force_bit, unsigned char opcode, int imm_flag) { // if the CPU does not allow 16bit immediate addressing (or if the // opcode does not allow it), return immediately. if((CPU_now->long_regs == NULL) || (imm_flag == 0)) return(opcode); // check force bits (if no force bits given, use relevant flag) if(*force_bit == 0) *force_bit = ((imm_flag & IMM_ACCU) ? CPU_now->long_regs[LONGREG_IDX_A] : CPU_now->long_regs[LONGREG_IDX_R]) ? MVALUE_FORCE16 : MVALUE_FORCE08; // return identical opcodes for 8bit and 16bit args! return((((unsigned int) opcode) << 8) | opcode); } // The main accumulator stuff (ADC, AND, CMP, EOR, LDA, ORA, SBC, STA) // plus PEI. static void group_main(int index, int imm_flag) { unsigned long imm_opcodes; result_int_t result; int force_bit = Input_get_force_bit();// skips spaces after switch(get_argument(&result)) { // #$ff or #$ffff (depending on accu length) case HAM_IMM: imm_opcodes = imm_ops(&force_bit, accu_imm[index], imm_flag); // CAUTION - do not incorporate the line above into the line // below - "fb" might be undefined (depends on compiler). make_command(force_bit, &result, imm_opcodes); break; // $ff, $ffff, $ffffff case HAM_ABS: make_command(force_bit, &result, accu_abs[index]); break; // $ff,x, $ffff,x, $ffffff,x case HAM_ABSX: make_command(force_bit, &result, accu_xabs[index]); break; // $ffff,y (in theory, "$ff,y" as well) case HAM_ABSY: make_command(force_bit, &result, accu_yabs[index]); break; // $ff,s case HAM_ABSS: make_command(force_bit, &result, accu_sabs8[index]); break; // ($ff,x) case HAM_XIND: make_command(force_bit, &result, accu_xind8[index]); break; // ($ff) case HAM_IND: make_command(force_bit, &result, accu_ind8[index]); break; // ($ff),y case HAM_INDY: make_command(force_bit, &result, accu_indy8[index]); break; // [$ff] case HAM_LIND: make_command(force_bit, &result, accu_lind8[index]); break; // [$ff],y case HAM_LINDY: make_command(force_bit, &result, accu_lindy8[index]); break; // ($ff,s),y case HAM_SINDY: make_command(force_bit, &result, accu_sindy8[index]); break; // other combinations are illegal default: Throw_error(exception_illegal_combination); } } // Various mnemonics with different addressing modes. static void group_misc(int index, int imm_flag) { unsigned long imm_opcodes; result_int_t result; int force_bit = Input_get_force_bit();// skips spaces after switch(get_argument(&result)) { // implied addressing case HAM_IMP: if(misc_impl[index]) Output_byte(misc_impl[index]); else Throw_error(exception_illegal_combination); break; // #$ff or #$ffff (depending on index register length) case HAM_IMM: imm_opcodes = imm_ops(&force_bit, misc_imm[index], imm_flag); // CAUTION - do not incorporate the line above into the line // below - force_bit might be undefined (depends on compiler). make_command(force_bit, &result, imm_opcodes); break; // $ff or $ffff case HAM_ABS: make_command(force_bit, &result, misc_abs[index]); break; // $ff,x or $ffff,x case HAM_ABSX: make_command(force_bit, &result, misc_xabs[index]); break; // $ff,y or $ffff,y case HAM_ABSY: make_command(force_bit, &result, misc_yabs[index]); break; // other combinations are illegal default: Throw_error(exception_illegal_combination); } } // Mnemonics using "8bit, 8bit" addressing. Only applies to "MVN" and "MVP". static void group_move(int opcode) { intval_t source, target; // assembler syntax: "opcode source, target" source = ALU_any_int(); if(Input_accept_comma()) { target = ALU_any_int(); // machine language: Output_byte(opcode); // opcode Output_8b(target); // target Output_8b(source); // source Input_ensure_EOS(); } else Throw_error(exception_syntax); } // The jump instructions. static void group_jump(int index) { result_int_t result; int force_bit = Input_get_force_bit();// skips spaces after switch(get_argument(&result)) { // absolute16 or absolute24 case HAM_ABS: make_command(force_bit, &result, jump_abs[index]); break; // ($ffff) case HAM_IND: make_command(force_bit, &result, jump_ind[index]); // check whether to warn about 6502's JMP() bug if(((result.intval & 0xff) == 0xff) && (result.flags & MVALUE_DEFINED) && (CPU_now->flags & CPUFLAG_INDJMPBUGGY)) Throw_warning("Assembling buggy JMP($xxff) instruction"); break; // ($ffff,x) case HAM_XIND: make_command(force_bit, &result, jump_xind[index]); break; // [$ffff] case HAM_LIND: make_command(force_bit, &result, jump_lind[index]); break; // other combinations are illegal default: Throw_error(exception_illegal_combination); } } // Work function static bool check_mnemo_tree(node_t* tree, dynabuf_t* dyna_buf) { void* node_body; int code, imm_flag; // flag for immediate addressing // search for tree item if(!Tree_easy_scan(tree, &node_body, dyna_buf)) return(FALSE); code = ((int) node_body) & CODEMASK; // get opcode or table index imm_flag = ((int) node_body) & FLAGSMASK; // get flag switch(((long) node_body) >> GROUPSHIFT) { // mnemonics with only implied addressing case G_IMPLIED: group_only_implied_addressing(code); break; // main accumulator stuff case G_MAIN: group_main(code, imm_flag); break; // misc case G_MISC: group_misc(code, imm_flag); break; // short relative case G_REL_SHORT: group_only_relative8_addressing(code); break; // long relative case G_REL_LONG: group_only_relative16_addressing(code); break; // the jump instructions case G_JUMP: group_jump(code); break; // "mvp" and "mvn" case G_MOVE: group_move(code); break; // others indicate bugs default: Bug_found("IllegalGroupIndex", code); } return(TRUE); } // Check whether mnemonic in GlobalDynaBuf is supported by 6502 cpu. bool keyword_is_6502mnemo(int length) { if(length != 3) return(FALSE); // make lower case version of mnemonic in local dynamic buffer DynaBuf_to_lower(mnemo_dyna_buf, GlobalDynaBuf); if(check_mnemo_tree(mnemo_6502_tree, mnemo_dyna_buf)) return(TRUE); return(FALSE); } // Check whether mnemonic in GlobalDynaBuf is supported by 6510 cpu. bool keyword_is_6510mnemo(int length) { if(length != 3) return(FALSE); // make lower case version of mnemonic in local dynamic buffer DynaBuf_to_lower(mnemo_dyna_buf, GlobalDynaBuf); // first check extensions... if(check_mnemo_tree(mnemo_6510_tree, mnemo_dyna_buf)) return(TRUE); // ...then check original opcodes if(check_mnemo_tree(mnemo_6502_tree, mnemo_dyna_buf)) return(TRUE); return(FALSE); } // Check whether mnemonic in GlobalDynaBuf is supported by 65c02 cpu. bool keyword_is_65c02mnemo(int length) { if(length != 3) return(FALSE); // make lower case version of mnemonic in local dynamic buffer DynaBuf_to_lower(mnemo_dyna_buf, GlobalDynaBuf); // first check extensions... if(check_mnemo_tree(mnemo_65c02_tree, mnemo_dyna_buf)) return(TRUE); // ...then check original opcodes if(check_mnemo_tree(mnemo_6502_tree, mnemo_dyna_buf)) return(TRUE); return(FALSE); } //// Check whether mnemonic in GlobalDynaBuf is supported by Rockwell 65c02 cpu. //bool keyword_is_Rockwell65c02mnemo(int length) { // if((length != 3) && (length != 4)) // return(FALSE); // // make lower case version of mnemonic in local dynamic buffer // DynaBuf_to_lower(mnemo_dyna_buf, GlobalDynaBuf); // // first check 65c02 extensions... // if(check_mnemo_tree(mnemo_65c02_tree, mnemo_dyna_buf)) // return(TRUE); // // ...then check original opcodes... // if(check_mnemo_tree(mnemo_6502_tree, mnemo_dyna_buf)) // return(TRUE); // // ...then check Rockwell/WDC extensions (rmb, smb, bbr, bbs) // if(check_mnemo_tree(mnemo_Rockwell65c02_tree, mnemo_dyna_buf)) // return(TRUE); // return(FALSE); //} //// Check whether mnemonic in GlobalDynaBuf is supported by WDC 65c02 cpu. //bool keyword_is_WDC65c02mnemo(int length) { // if((length != 3) && (length != 4)) // return(FALSE); // // make lower case version of mnemonic in local dynamic buffer // DynaBuf_to_lower(mnemo_dyna_buf, GlobalDynaBuf); // // first check 65c02 extensions... // if(check_mnemo_tree(mnemo_65c02_tree, mnemo_dyna_buf)) // return(TRUE); // // ...then check original opcodes... // if(check_mnemo_tree(mnemo_6502_tree, mnemo_dyna_buf)) // return(TRUE); // // ...then check Rockwell/WDC extensions (rmb, smb, bbr, bbs)... // if(check_mnemo_tree(mnemo_Rockwell65c02_tree, mnemo_dyna_buf)) // return(TRUE); // // ...then check WDC extensions (only two mnemonics, so do last) // if(check_mnemo_tree(mnemo_WDC65c02_tree, mnemo_dyna_buf)) // return(TRUE); // return(FALSE); //} // Check whether mnemonic in GlobalDynaBuf is supported by 65816 cpu. bool keyword_is_65816mnemo(int length) { if(length != 3) return(FALSE); // make lower case version of mnemonic in local dynamic buffer DynaBuf_to_lower(mnemo_dyna_buf, GlobalDynaBuf); // first check "new" extensions... if(check_mnemo_tree(mnemo_65816_tree, mnemo_dyna_buf)) return(TRUE); // ...then "old" extensions... if(check_mnemo_tree(mnemo_65c02_tree, mnemo_dyna_buf)) return(TRUE); // ...then check original opcodes... if(check_mnemo_tree(mnemo_6502_tree, mnemo_dyna_buf)) return(TRUE); // ...then check WDC extensions "stp" and "wai" if(check_mnemo_tree(mnemo_WDC65c02_tree, mnemo_dyna_buf)) return(TRUE); return(FALSE); } CheeseCutter-master/src/asm/mnemo.h000066400000000000000000000020141357241101300175570ustar00rootroot00000000000000// // ACME - a crossassembler for producing 6502/65c02/65816 code. // Copyright (C) 1998-2006 Marco Baye // Have a look at "acme.c" for further info // // Mnemonic definitions #ifndef mnemo_H #define mnemo_H // Prototypes // create dynamic buffer, build keyword trees extern void Mnemo_init(void); // Check whether mnemonic in GlobalDynaBuf is supported by 6502 cpu. extern bool keyword_is_6502mnemo(int length); // Check whether mnemonic in GlobalDynaBuf is supported by 6510 cpu. extern bool keyword_is_6510mnemo(int length); // Check whether mnemonic in GlobalDynaBuf is supported by 65c02 cpu. extern bool keyword_is_65c02mnemo(int length); // Check whether mnemonic in GlobalDynaBuf is supported by Rockwell 65c02 cpu. //extern bool keyword_is_Rockwell65c02mnemo(int length); // Check whether mnemonic in GlobalDynaBuf is supported by WDC 65c02 cpu. //extern bool keyword_is_WDC65c02mnemo(int length); // Check whether mnemonic in GlobalDynaBuf is supported by 65816 cpu. extern bool keyword_is_65816mnemo(int length); #endif CheeseCutter-master/src/asm/output.c000066400000000000000000000311321357241101300200020ustar00rootroot00000000000000// // ACME - a crossassembler for producing 6502/65c02/65816 code. // Copyright (C) 1998-2006 Marco Baye // Have a look at "acme.c" for further info // // Output stuff #include //#include #include // for memset() #include "acme.h" #include "alu.h" #include "config.h" #include "cpu.h" #include "dynabuf.h" #include "global.h" #include "input.h" #include "output.h" #include "platform.h" #include "tree.h" // Structure for linked list of segment data struct segment_t { struct segment_t* next; // struct segment_t* prev; intval_t start; intval_t length; }; // Constants #define OUTBUFFERSIZE 65536 enum out_format_t { OUTPUT_FORMAT_UNSPECIFIED, // default (uses "plain" actually) OUTPUT_FORMAT_PLAIN, OUTPUT_FORMAT_CBM, // default for "!to" pseudo opcode }; // Variables // segment stuff static struct segment_t* segment_list = NULL;// linked list static intval_t segment_start;// Start of current segment static intval_t segment_max;// Highest address segment may use // misc static intval_t lowest_idx; // Smallest address program uses static intval_t highest_idx; // End address of program plus one // output buffer stuff static char* output_buffer = NULL; // to hold assembled code static char* write_ptr = NULL; // points into output_buffer intval_t write_idx; // index in output buffer static bool memory_initialised = FALSE; // chosen file format static enum out_format_t output_format = OUTPUT_FORMAT_CBM; // predefined stuff static node_t* file_format_tree = NULL;// tree to hold output formats // possible file formats static node_t file_formats[] = { PREDEFNODE(s_cbm, OUTPUT_FORMAT_CBM), // PREDEFNODE("o65", OUTPUT_FORMAT_O65), PREDEFLAST("plain", OUTPUT_FORMAT_PLAIN), // ^^^^ this marks the last element }; // Functions // Fill output buffer with given byte value static void fill_completely(char value) { memset(output_buffer, value, OUTBUFFERSIZE); } // Set up new segment_max value according to the given address. Just // find the next segment start and subtract 1. static void find_segment_max(intval_t new_pc) { struct segment_t* test_segment; // may be faster if list is ordered! segment_max = OUTBUFFERSIZE;// will be decremented later! test_segment = segment_list; while(test_segment) { if((test_segment->start > new_pc) && (test_segment->start < segment_max)) segment_max = test_segment->start; test_segment = test_segment->next; } segment_max--;// last free address available } // static void border_crossed(int current_offset) { if(current_offset >= OUTBUFFERSIZE) Throw_serious_error("Produced too much code."); if(pass_count == 0) { Throw_warning("Segment reached another one, overwriting it."); find_segment_max(current_offset + 1); } } // Send low byte to output buffer void (*Output_byte)(intval_t byte); static void real_output(intval_t byte); // fn for actual output static void no_output(intval_t byte); // fn when output impossible // set output pointer (negative values deactivate output) static void set_mem_ptr(signed long index) { if(index < 0) { Output_byte = no_output; write_ptr = output_buffer; write_idx = 0; } else { Output_byte = real_output; write_ptr = output_buffer + index; write_idx = index; } } // Send low byte to output buffer, automatically increasing program counter static void real_output(intval_t byte) { if(write_idx > segment_max) border_crossed(write_idx); *write_ptr++ = byte & 0xff; write_idx++; CPU_2add++; } // fail to write to output buffer static void no_output(intval_t byte) { Throw_error(exception_pc_undefined); // set ptr to not complain again. as we have thrown an error, assembly // fails, so don't care about actual value. set_mem_ptr(512); // 512 to not garble zero page and stack. ;) CPU_2add++; } // call this if really calling Output_byte would be a waste of time void Output_fake(int size) { // check whether ptr undefined if(Output_byte == no_output) { no_output(0); size--; } if(write_idx + size - 1 > segment_max) border_crossed(write_idx + size - 1); write_ptr += size; write_idx += size; CPU_2add += size; } // Output 8-bit value with range check void Output_8b(intval_t value) { if((value <= 0xff) && (value >= -0x80)) Output_byte(value); else Throw_error(exception_number_out_of_range); } // Output 16-bit value with range check void Output_16b(intval_t value) { if((value <= 0xffff) && (value >= -0x8000)) { Output_byte(value); Output_byte(value >> 8); } else Throw_error(exception_number_out_of_range); } // Output 24-bit value with range check void Output_24b(intval_t value) { if((value <= 0xffffff) && (value >= -0x800000)) { Output_byte(value); Output_byte(value >> 8); Output_byte(value >> 16); } else Throw_error(exception_number_out_of_range); } // Output 32-bit value (without range check) void Output_32b(intval_t value) { // if((Value <= 0x7fffffff) && (Value >= -0x80000000)) { Output_byte(value); Output_byte(value >> 8); Output_byte(value >> 16); Output_byte(value >> 24); // } else // Throw_error(exception_number_out_of_range); } // Define default value for empty memory ("!initmem" pseudo opcode) static enum eos_t PO_initmem(void) { intval_t content; // ignore in all passes but in first if(pass_count) return(SKIP_REMAINDER); // if MemInit flag is already set, complain if(memory_initialised) { Throw_warning("Memory already initialised."); return(SKIP_REMAINDER); } // set MemInit flag memory_initialised = TRUE; // get value and init memory content = ALU_defined_int(); if((content > 0xff) || (content < -0x80)) Throw_error(exception_number_out_of_range); // init memory fill_completely(content); // enforce another pass if(pass_undefined_count == 0) pass_undefined_count = 1; // FIXME - enforcing another pass is not needed if there hasn't been any // output yet. But that's tricky to detect without too much overhead. // The old solution was to add &&(lowest_idx < highest_idx) to "if" above return(ENSURE_EOS); } // Try to set output format held in DynaBuf. Returns whether succeeded. bool Output_set_output_format(void) { void* node_body; if(!Tree_easy_scan(file_format_tree, &node_body, GlobalDynaBuf)) return(FALSE); output_format = (enum out_format_t) node_body; return(TRUE); } // Select output file and format ("!to" pseudo opcode) static enum eos_t PO_to(void) { // only act upon this pseudo opcode in first pass if(pass_count) return(SKIP_REMAINDER); // if output file already chosen, complain and exit if(output_filename) { Throw_warning("Output file already chosen."); return(SKIP_REMAINDER); } // read filename to global dynamic buffer // if no file name given, exit (complaining will have been done) if(Input_read_filename(FALSE)) return(SKIP_REMAINDER); // get malloc'd copy of filename output_filename = DynaBuf_get_copy(GlobalDynaBuf); // select output format // if no comma found, use default file format if(Input_accept_comma() == FALSE) { if(output_format == OUTPUT_FORMAT_UNSPECIFIED) { output_format = OUTPUT_FORMAT_CBM; // output deprecation warning Throw_warning("Used \"!to\" without file format indicator. Defaulting to \"cbm\"."); } return(ENSURE_EOS); } // parse output format name // if no keyword given, give up if(Input_read_and_lower_keyword() == 0) return(SKIP_REMAINDER); if(Output_set_output_format()) return(ENSURE_EOS); // success // error occurred Throw_error("Unknown output format."); return(SKIP_REMAINDER); } // pseudo ocpode table static node_t pseudo_opcodes[] = { PREDEFNODE("initmem", PO_initmem), PREDEFLAST("to", PO_to), // ^^^^ this marks the last element }; // Init file format tree (is done early) void Outputfile_init(void) { Tree_add_table(&file_format_tree, file_formats); } // alloc and init mem buffer, register pseudo opcodes (done later) void Output_init(signed long fill_value) { output_buffer = safe_malloc(OUTBUFFERSIZE); write_ptr = output_buffer; if(fill_value == MEMINIT_USE_DEFAULT) fill_value = FILLVALUE_INITIAL; else memory_initialised = TRUE; // init output buffer (fill memory with initial value) fill_completely(fill_value & 0xff); Tree_add_table(&pseudo_opcode_tree, pseudo_opcodes); } // Dump memory buffer into output file void Output_save_file(FILE* fd) { intval_t amount = highest_idx - lowest_idx; if(Process_verbosity) printf("Saving %ld ($%lx) bytes ($%lx - $%lx exclusive).\n", amount, amount, lowest_idx, highest_idx); // Output file header according to file format switch(output_format) { case OUTPUT_FORMAT_UNSPECIFIED: case OUTPUT_FORMAT_PLAIN: PLATFORM_SETFILETYPE_PLAIN(output_filename); break; case OUTPUT_FORMAT_CBM: PLATFORM_SETFILETYPE_CBM(output_filename); // output 16-bit load address in little-endian byte order putc(lowest_idx & 255, fd); putc(lowest_idx >> 8, fd); break; } // Dump output buffer to file fwrite(output_buffer + lowest_idx, sizeof(char), amount, fd); } char* Output_get_final_data(int *length) { intval_t amount = highest_idx - lowest_idx; int bufsize = amount * sizeof(char); if(Process_verbosity) printf("Saving %ld ($%lx) bytes ($%lx - $%lx exclusive).\n", amount, amount, lowest_idx, highest_idx); // Output file header according to file format switch(output_format) { case OUTPUT_FORMAT_UNSPECIFIED: case OUTPUT_FORMAT_PLAIN: PLATFORM_SETFILETYPE_PLAIN(output_filename); break; case OUTPUT_FORMAT_CBM: PLATFORM_SETFILETYPE_CBM(output_filename); // TODO: insert load address here // output 16-bit load address in little-endian byte order //cbm_load_address = lowest_idx; //putc(lowest_idx & 255, fd); //putc(lowest_idx >> 8, fd); bufsize += 2; break; } // Dump output buffer to file //fwrite(output_buffer + lowest_idx, sizeof(char), amount, fd); char* buffer = malloc(bufsize); if(output_format == OUTPUT_FORMAT_CBM) { buffer[0] = lowest_idx & 255; buffer[1] = lowest_idx >> 8; memcpy(buffer + 2, output_buffer + lowest_idx, amount); } else { memcpy(buffer, output_buffer + lowest_idx, amount); } *length = bufsize; return buffer; } // Link segment data into segment chain static void link_segment(intval_t start, intval_t length) { struct segment_t* new_segment; new_segment = safe_malloc(sizeof(struct segment_t)); new_segment->start = start; new_segment->length = length; new_segment->next = segment_list; segment_list = new_segment; } // Show start and end of current segment // Called whenever a new segment begins, and at end of pass. void Output_end_segment(void) { intval_t amount; if(CPU_uses_pseudo_pc()) Throw_first_pass_warning("Offset assembly still active at end of segment."); // FIXME - should be error! if(pass_count == 0) { amount = write_idx - segment_start; link_segment(segment_start, amount); if(Process_verbosity > 1) printf( "Segment size is %ld ($%lx) bytes ($%lx - $%lx exclusive).\n", amount, amount, segment_start, write_idx); } // FIXME - this was in real_output(): // check for new max address (FIXME - move to close_segment?) if(write_idx > highest_idx) highest_idx = write_idx; } // Check whether given PC is inside segment. static void check_segment(intval_t new_pc) { struct segment_t* test_segment; test_segment = segment_list; while(test_segment) { if((new_pc >= test_segment->start) && (new_pc < (test_segment->start) + (test_segment->length))) Throw_warning("Segment starts inside another one, overwriting it."); test_segment = test_segment->next; } } // init lowest and highest address static void init_borders(intval_t address) { lowest_idx = address; highest_idx = address; } // clear segment list void Output_passinit(signed long start_addr) { struct segment_t* temp; // delete segment list (and free blocks) while((temp = segment_list)) { segment_list = segment_list->next; free(temp); } set_mem_ptr(start_addr); // negative values deactivate output // if start address given, set program counter if(start_addr >= 0) { CPU_set_pc(start_addr); // FIXME - integrate next two? init_borders(start_addr); segment_start = start_addr; } else { init_borders(0); // set to _something_ (for !initmem) segment_start = 0; } // other stuff segment_max = OUTBUFFERSIZE-1; } // Called when "*=EXPRESSION" is parsed void Output_start_segment(void) { intval_t new_addr = ALU_defined_int(); if(CPU_pc.flags & MVALUE_DEFINED) { // It's a redefinition. Check some things: // check whether new low if(new_addr < lowest_idx) lowest_idx = new_addr; // show status of previous segment Output_end_segment(); // in first pass, maybe issue warning if(pass_count == 0) { check_segment(new_addr); find_segment_max(new_addr); } } else init_borders(new_addr);// it's the first pc definition CPU_set_pc(new_addr); segment_start = new_addr; set_mem_ptr(new_addr); } CheeseCutter-master/src/asm/output.h000066400000000000000000000027621357241101300200160ustar00rootroot00000000000000// // ACME - a crossassembler for producing 6502/65c02/65816 code. // Copyright (C) 1998-2006 Marco Baye // Have a look at "acme.c" for further info // // Output stuff #ifndef output_H #define output_H #include #include "config.h" // Constants #define MEMINIT_USE_DEFAULT 256 // Prototypes // Init file format tree (is done early) extern void Outputfile_init(void); // alloc and init mem buffer, register pseudo opcodes (done later) extern void Output_init(signed long fill_value); // clear segment list extern void Output_passinit(signed long start_addr); // call this if really calling Output_byte would be a waste of time extern void Output_fake(int size); // Send low byte of arg to output buffer and advance pointer extern void (*Output_byte)(intval_t); // Output 8-bit value with range check extern void Output_8b(intval_t); // Output 16-bit value with range check extern void Output_16b(intval_t); // Output 24-bit value with range check extern void Output_24b(intval_t); // Output 32-bit value (without range check) extern void Output_32b(intval_t); // Try to set output format held in DynaBuf. Returns whether succeeded. extern bool Output_set_output_format(void); // write smallest-possible part of memory buffer to file extern void Output_save_file(FILE* fd); // send final output as binary extern char* Output_get_final_data(); // Call when "*=EXPRESSION" is parsed extern void Output_start_segment(void); // Show start and end of current segment extern void Output_end_segment(void); #endif CheeseCutter-master/src/asm/platform.c000066400000000000000000000012641357241101300202710ustar00rootroot00000000000000// // ACME - a crossassembler for producing 6502/65c02/65816 code. // Copyright (C) 1998-2006 Marco Baye // Have a look at "acme.c" for further info // // Platform specific stuff #include "config.h" #include "platform.h" // Amiga #ifdef _AMIGA #ifndef platform_C #define platform_C // Nothing here - Amigas don't need no stinkin' platform-specific stuff! #endif #endif // DOS and OS/2 #ifdef __DJGPP__ #include "_dos.c" #endif #ifdef __OS2__ #include "_dos.c" #endif //#ifdef __Windows__ //#include "_dos.c" //#endif // RISC OS #ifdef __riscos__ #include "_riscos.c" #endif // add further platform files here // Unix/Linux/others (surprisingly also works on Windows) #include "_std.c" CheeseCutter-master/src/asm/platform.h000066400000000000000000000006231357241101300202740ustar00rootroot00000000000000// // ACME - a crossassembler for producing 6502/65c02/65816 code. // Copyright (C) 1998-2006 Marco Baye // Have a look at "acme.c" for further info // // Platform specific stuff // Unix/Linux/others (surprisingly also works on Windows) #ifndef PLATFORM_VERSION #define PLATFORM_VERSION "Platform independent version.\nCurrent maintainer Krzysztof Dabrowski aka BruSH/ElysiuM" #endif #include "_std.h" CheeseCutter-master/src/asm/section.c000066400000000000000000000070751357241101300201170ustar00rootroot00000000000000// // ACME - a crossassembler for producing 6502/65c02/65816 code. // Copyright (C) 1998-2006 Marco Baye // Have a look at "acme.c" for further info // // Section stuff #include "config.h" #include "dynabuf.h" #include "global.h" #include "input.h" #include "tree.h" #include "section.h" // Constants static const char type_zone[] = "Zone"; static const char s_subzone[] = "subzone"; #define s_zone (s_subzone+3) // Yes, I know I'm sick static char untitled[] = ""; // ...is actually constant, but flagging it "const" results in heap of warnings // fake section structure (for error msgs before any real section is in use) static section_t initial_section = { 0, // zone value "during", // "type" => normally "zone Title" or "init", // "title" => "macro test", now "during init" FALSE, // no, title was not malloc'd }; // Variables section_t* Section_now = &initial_section;// current section static section_t outer_section; // outermost section struct static zone_t zone_max; // Highest zone number yet // Write given info into given zone structure and activate it void Section_new_zone(section_t* section, const char* type, char* title, bool allocated) { section->zone = ++zone_max; section->type = type; section->title = title; section->allocated = allocated; // activate new section Section_now = section; } // Tidy up: If necessary, release section title. // Warning - the state of the component "Allocd" may have // changed in the meantime, so don't rely on a local variable. void Section_finalize(section_t* section) { if(section->allocated) free(section->title); } // Switch to new zone ("!zone" or "!zn"). Has to be re-entrant. static enum eos_t PO_zone(void) { section_t entry_values;// buffer for outer zone char* new_title; bool allocated; // remember everything about current structure entry_values = *Section_now; // set default values in case there is no valid title new_title = untitled; allocated = FALSE; // Check whether a zone title is given. If yes and it can be read, // get copy, remember pointer and remember to free it later on. if(BYTEFLAGS(GotByte) & CONTS_KEYWORD) { // Because we know of one character for sure, // there's no need to check the return value. Input_read_keyword(); new_title = DynaBuf_get_copy(GlobalDynaBuf); allocated = TRUE; } // setup new section // section type is "subzone", just in case a block follows Section_new_zone(Section_now, "Subzone", new_title, allocated); if(Parse_optional_block()) { // Block has been parsed, so it was a SUBzone. Section_finalize(Section_now);// end inner zone *Section_now = entry_values;// restore entry values } else { // no block found, so it's a normal zone change Section_finalize(&entry_values);// end outer zone Section_now->type = type_zone;// change type to "zone" } return(ENSURE_EOS); } // Start subzone ("!subzone" or "!sz"). Has to be re-entrant. static enum eos_t PO_subzone(void) { // output deprecation warning Throw_first_pass_warning("\"!subzone {}\" is deprecated; use \"!zone {}\" instead."); // call "!zone" instead return(PO_zone()); } // predefined stuff static node_t pseudo_opcodes[] = { PREDEFNODE(s_zone, PO_zone), PREDEFNODE("zn", PO_zone), PREDEFNODE(s_subzone, PO_subzone), PREDEFLAST("sz", PO_subzone), // ^^^^ this marks the last element }; // register pseudo opcodes void Section_init(void) { Tree_add_table(&pseudo_opcode_tree, pseudo_opcodes); } // Setup outermost section void Section_passinit(void) { zone_max = ZONE_GLOBAL;// will be incremented by next line Section_new_zone(&outer_section, type_zone, untitled, FALSE); } CheeseCutter-master/src/asm/section.h000066400000000000000000000020071357241101300201120ustar00rootroot00000000000000// // ACME - a crossassembler for producing 6502/65c02/65816 code. // Copyright (C) 1998-2006 Marco Baye // Have a look at "acme.c" for further info // // Section stuff #ifndef section_H #define section_H #include "config.h" // "section" structure type definition typedef struct { zone_t zone; // current zone value const char* type; // "Zone", "Subzone" or "Macro" char* title; // zone title, subzone title or macro title int allocated; // whether title was malloc()'d } section_t; // Constants #define ZONE_GLOBAL 0 // Number of "global zone" // Variables // current section structure extern section_t *Section_now; // Prototypes // Write given info into given zone structure and activate it extern void Section_new_zone(section_t*, const char* type, char* title, bool allocated); // register pseudo opcodes extern void Section_init(void); // Setup outermost section extern void Section_passinit(void); // Tidy up: If necessary, release section title. extern void Section_finalize(section_t* section); #endif CheeseCutter-master/src/asm/tree.c000066400000000000000000000136711357241101300174110ustar00rootroot00000000000000// // ACME - a crossassembler for producing 6502/65c02/65816 code. // Copyright (C) 1998-2006 Marco Baye // Have a look at "acme.c" for further info // // Tree stuff #include "config.h" #include "dynabuf.h" #include "global.h" #include "tree.h" #include "platform.h" // Functions // Compute hash value by exclusive ORing the node's ID string and write // output to struct. // This function is not allowed to change GlobalDynaBuf! hash_t make_hash(node_t* node) { register char byte; register const char* read; register hash_t tmp = 0; read = node->id_string; while((byte = *read++)) tmp = ((tmp << 7) | (tmp >> (8 * sizeof(hash_t) - 7))) ^ byte; node->hash_value = tmp; return(tmp); } // Link a predefined data set to a tree void add_node_to_tree(node_t** tree, node_t* node_to_add) { hash_t hash; // compute hash value hash = make_hash(node_to_add); while(*tree) { // compare HashValue if(hash > (*tree)->hash_value) tree = &((*tree)->greater_than); else tree = &((*tree)->less_than_or_equal); } *tree = node_to_add;// add new leaf to tree // New nodes are always added as leaves, so there's no need to copy a second // pointer. And because the PREDEF* macros contain NULL as init values, it is // not necessary to clear the new node's greater_than and less_than_or_equal // fields. } // Add predefined tree items to given tree. The PREDEF* macros set HashValue // to 1 in all entries but the last. The last entry contains 0. void Tree_add_table(node_t** tree, node_t* table_to_add) { // Caution when trying to optimise this. :) while(table_to_add->hash_value) add_node_to_tree(tree, table_to_add++); add_node_to_tree(tree, table_to_add); } // Search for a given ID string in a given tree. // Compute the hash of the given string and then use that to try to find a // tree item that matches the given data (HashValue and DynaBuf-String). // Store "Body" component in NodeBody and return TRUE. // Return FALSE if no matching item found. bool Tree_easy_scan(node_t* tree, void** node_body, struct dynabuf_t* dyna_buf) { node_t wanted;// temporary storage const char *p1, *p2; char b1, b2; hash_t hash; wanted.id_string = dyna_buf->buffer; hash = make_hash(&wanted); while(tree) { // compare HashValue if(hash > tree->hash_value) { // wanted hash is bigger than current, so go // to tree branch with bigger hashes tree = tree->greater_than; continue; } if(hash == tree->hash_value) { p1 = wanted.id_string; p2 = tree->id_string; do { b1 = *p1++; b2 = *p2++; } while((b1 == b2) && b1); if(b1 == b2) { // store body data *node_body = tree->body; return(TRUE); } } // either the wanted hash is smaller or // it was exact but didn't match tree = tree->less_than_or_equal; } return(FALSE); // indicate failure } // Search for a "RAM tree" item. Compute the hash of string in GlobalDynaBuf // and then use that to try to find a tree item that matches the given data // (HashValue, ID_Number, GlobalDynaBuf-String). Save pointer to found tree // item in given location. // If no matching item is found, check the "Create" flag. If it is set, create // a new tree item, link to tree, fill with data and store its pointer. If the // "Create" flag is clear, store NULL as result. // Returns whether item was created. bool Tree_hard_scan(node_ra_t** result, node_ra_t** forest, int id_number, bool create) { node_t wanted; // temporary storage node_ra_t **current_node; node_ra_t *new_leaf_node; const char *p1, *p2; char b1, b2; hash_t byte_hash; wanted.id_string = GLOBALDYNABUF_CURRENT; // incorporate ID number into hash value byte_hash = make_hash(&wanted) ^ id_number; wanted.hash_value = byte_hash;// correct struct's hash PLATFORM_UINT2CHAR(byte_hash);// transform into byte current_node = &(forest[byte_hash]);// point into table while(*current_node) { // compare HashValue if(wanted.hash_value > (*current_node)->hash_value) { // wanted hash is bigger than current, so go // to tree branch with bigger hashes current_node = &((*current_node)->greater_than); continue; } if(wanted.hash_value == (*current_node)->hash_value) { if(id_number == (*current_node)->id_number) { p1 = wanted.id_string; p2 = (*current_node)->id_string; do { b1 = *p1++; b2 = *p2++; } while((b1 == b2) && b1); if(b1 == b2) { // store node pointer *result = *current_node; // return FALSE because node // was not created return(FALSE); } } } // either the wanted hash is smaller or // it was exact but didn't match current_node = &((*current_node)->less_than_or_equal); } // node wasn't found. Check whether to create it if(create == FALSE) { *result = NULL;// indicate failure return(FALSE);// return FALSE because node was not created } // create new node new_leaf_node = safe_malloc(sizeof(node_ra_t)); new_leaf_node->greater_than = NULL; new_leaf_node->less_than_or_equal = NULL; new_leaf_node->hash_value = wanted.hash_value; new_leaf_node->id_number = id_number; new_leaf_node->id_string = DynaBuf_get_copy(GlobalDynaBuf);// make permanent copy // add new leaf to tree *current_node = new_leaf_node; // store pointer to new node in result location *result = new_leaf_node; return(TRUE);// return TRUE because node was created } // Call given function for each object of matching type in the given tree. // Calls itself recursively. void dump_tree(node_ra_t* node, int id_number, void (*fn)(node_ra_t*, FILE*), FILE* env) { if(node->id_number == id_number) fn(node, env); if(node->greater_than) dump_tree(node->greater_than, id_number, fn, env); if(node->less_than_or_equal) dump_tree(node->less_than_or_equal, id_number, fn, env); } // Calls Tree_dump_tree for each non-zero entry of the given tree table. void Tree_dump_forest(node_ra_t** forest, int id_number, void (*fn)(node_ra_t*, FILE*), FILE* env) { int i; for(i = 255; i >= 0; i--) { if(*forest) dump_tree(*forest, id_number, fn, env); forest++; } } CheeseCutter-master/src/asm/tree.h000066400000000000000000000037531357241101300174160ustar00rootroot00000000000000// // ACME - a crossassembler for producing 6502/65c02/65816 code. // Copyright (C) 1998-2006 Marco Baye // Have a look at "acme.c" for further info // // Tree stuff #ifndef tree_H #define tree_H #include #include "config.h" // Macros for pre-defining tree node tables #define PREDEFNODE(s, v) {NULL, NULL, 1, s, (void*) (v)} #define PREDEFLAST(s, v) {NULL, NULL, 0, s, (void*) (v)} // type definitions typedef unsigned int hash_t; // Must be unsigned, otherwise the hash algorithm won't be very useful! // tree node structure type definition (for easy lookups) struct node_t { node_t* greater_than; // pointer to sub-tree node_t* less_than_or_equal;// pointer to sub-tree hash_t hash_value; const char* id_string; // name, zero-terminated void* body; // bytes, handles or handler function }; // tree node structure type definition (for macros/labels) struct node_ra_t { node_ra_t* greater_than; // pointer to sub-tree node_ra_t* less_than_or_equal;// pointer to sub-tree hash_t hash_value; char* id_string; // name, zero-terminated void* body; // macro/label body unsigned int id_number; // zone number }; // Prototypes // Add predefined tree items to given tree. extern void Tree_add_table(node_t** tree, node_t* table_to_add); // Search for a given ID string in a given tree. Store "Body" component in // NodeBody and return TRUE. Return FALSE if no matching item found. extern bool Tree_easy_scan(node_t* tree, void** node_body, struct dynabuf_t* dyna_buf); // Search for a "RAM tree" item. Save pointer to found tree item in given // location. If no matching item is found, check the "Create" flag: If set, // create new tree item, link to tree, fill with data and store its pointer. // If "Create" is clear, store NULL. Returns whether item was created. extern bool Tree_hard_scan(node_ra_t**, node_ra_t**, int, bool); // Calls given function for each node of each tree of given forest. extern void Tree_dump_forest(node_ra_t**, int, void (*)(node_ra_t*, FILE*), FILE*); #endif CheeseCutter-master/src/audio/000077500000000000000000000000001357241101300166175ustar00rootroot00000000000000CheeseCutter-master/src/audio/audio.d000066400000000000000000000073351357241101300200750ustar00rootroot00000000000000/* CheeseCutter v2 (C) Abaddon. Licensed under GNU GPL. */ module audio.audio; import derelict.sdl.sdl; import audio.resid.filter; import audio.player; import audio.callback; import audio.timer; import std.stdio; import core.stdc.stdlib; import core.stdc.string; import std.conv; enum MIXBUF_MUL = 2; __gshared SDL_AudioSpec audiospec; __gshared bool audioInited = false; __gshared int framerate = 50; __gshared int multiplier; __gshared int freq = 48000, bufferSize = 2048; __gshared private int callbackCounter = 0; __gshared private int bufferUsed; // in samples __gshared private int callbackInterval; __gshared short* mixbuf = null; extern(C) { extern __gshared char[0x19] sidreg; extern __gshared int residdelay; extern __gshared int sid_init(int, Filterparams*, int, int, int, int, int); extern __gshared int sid_fillbuffer(short *, int, int); extern __gshared int sid_close(); __gshared void function() callback; int audio_init(int fr, void function() cb) { SDL_AudioSpec requested; if(audioInited) return 0; audioInited = true; framerate = fr; if(bufferSize < freq / framerate) { // fprintf(stderr,"Minimum buffer size is %d bytes.\n", freq / framerate); return -1; } requested.freq = freq; requested.format = AUDIO_S16LSB; requested.channels = 1; requested.samples = cast(ushort) bufferSize; requested.callback = &audio_callback_2; requested.userdata = null; callback = cb; if(SDL_OpenAudio(&requested, &audiospec) < 0) { writeln("Could not open audio: ", to!string(SDL_GetError())); return -1; } if(audiospec.format != AUDIO_S16LSB) { writeln("Incorrect audio format obtained."); return -1; } bufferSize = audiospec.samples; mixbuf = cast(short *)malloc(bufferSize * short.sizeof * MIXBUF_MUL); setCallMultiplier(1); return 0; } int getbufsize() { return cast(int)(bufferSize * MIXBUF_MUL); } void audio_close() { SDL_CloseAudio(); if(mixbuf) free(mixbuf); sid_close(); } void reset() { bufferUsed = callbackCounter = 0; } void setCallMultiplier(int m) { if(m < 1 || m > 16) return; if(m == multiplier) return; SDL_LockAudio(); multiplier = m; framerate = 50 * m; callbackInterval = audiospec.freq / framerate; reset(); SDL_UnlockAudio(); } void audio_callback(void *data, ubyte* stream, int len) { int samplesRequested = cast(int) (len / short.sizeof); int total = 0,todo = 0,t = 0; int steps; if(!audio.player.isPlaying()) return; while(total < samplesRequested) { todo = samplesRequested - total; assert(todo >= 0); if(callbackCounter + todo >= callbackInterval) { int c = callbackInterval - callbackCounter; assert(c > 0); t = sid_fillbuffer(cast(short*)stream + total, c, 0); (*callback)(); callbackCounter -= callbackInterval; assert(callbackCounter + todo >= 0); } else { assert(total + todo <= samplesRequested); t = sid_fillbuffer(cast(short*)stream + total, todo, 0); } total += t; callbackCounter += t; steps++; } assert(total == samplesRequested); } __gshared void audio_callback_2(void *data, ubyte* stream, int len) { int samplesRequested = cast(int) (len / short.sizeof); int i,t; if(!audio.player.isPlaying()) return; while((bufferUsed + callbackInterval) <= bufferSize * MIXBUF_MUL) { t = sid_fillbuffer(mixbuf+bufferUsed, callbackInterval, cyclesPerFrame); bufferUsed += t; (*callback)(); } memcpy(stream, cast(ubyte*)mixbuf, len); bufferUsed -= samplesRequested; if(bufferUsed < 0) { writeln("Audio buffer underrun ", bufferUsed); bufferUsed = 0; } short* pi, po; for(i = 0, pi = mixbuf, po = mixbuf + samplesRequested; i < bufferSize * MIXBUF_MUL - samplesRequested; i++) { *(pi++) = *(po++); } } } CheeseCutter-master/src/audio/callback.d000066400000000000000000000053511357241101300205240ustar00rootroot00000000000000/* CheeseCutter v2 (C) Abaddon. Licensed under GNU GPL. */ module audio.callback; import derelict.sdl.sdl; import audio.player; import com.session; import com.cpu; import ct.base; static import audio.audio, audio.timer; /+ holds the state of cpu and memory for frame debug dumps. not implemented for now. +/ class SongState { int totalFramecallCounter, subframeCounter; private CPU cpu; private ubyte[65536] data; CPUException exception; } __gshared private int frameCallCounter, totalFrameCallCounter; // for multispeed __gshared private Exception playbackStatus = null; __gshared private bool dumpFrameRequested = false; __gshared private bool dumpRequested = false; __gshared int cyclesPerFrame; __gshared int linesPerFrame; Exception getException() { Exception ex = playbackStatus; playbackStatus = null; return ex; } void reset() { frameCallCounter = 0; totalFrameCallCounter = 0; } void requestDump() { dumpRequested = true; } // called each frame from soundbuffer callback extern(C) __gshared void audio_frame() { switch(audio.player.getPlaystatus()) { case Status.Play: audio.timer.tick(); cpuCall(frameCallCounter > 0 ? 0x1006 : 0x1003, false); break; case Status.Keyjam: address call = 0x100c; song.cpu.regs.x = 0; if(song.ver > 7) { call = song.offsets[Offsets.Submplayplay]; } cpuCall(call,false); break; default: return; } frameCallCounter++; totalFrameCallCounter++; if(frameCallCounter >= audio.audio.multiplier) { frameCallCounter = 0; frameDone(); } for(int i=0; i<0x19; i++) { sidreg[i] = song.sidbuf[i]; } } private void frameDone() { static int[10] avgs; int totalCycles; foreach(idx, ref avg; avgs) { if(idx == avgs.length - 1) { avg = cyclesPerFrame; } else avg = avgs[idx+1]; totalCycles += avg; } cyclesPerFrame = 0; linesPerFrame = cast(int)(totalCycles / avgs.length / 63); if(dumpRequested) { dumpFrameRequested = true; dumpRequested = false; } else dumpFrameRequested = false; audio.timer.tickFullFrame(); } void cpuCall(ushort pc, bool lockAudio) { cpuCall(pc, lockAudio, false); } void cpuCall(ushort pc, bool lockAudio, bool forcedump) { if(lockAudio) SDL_LockAudio(); try { if(dumpFrameRequested) { // state = new SongState(song, totalFrameCallCounter, frameCallCounter); } int i = song.cpu.execute(pc, false); cyclesPerFrame += i; } catch(CPUException e) { playbackStatus = e; stop(); // < TODO: player.d should check if playback is in error state and stop by itself //UI.statusline.display(e.toString()); //stop(); } finally { if(lockAudio) SDL_UnlockAudio(); } } extern(C) { __gshared extern char[0x19] sidreg; } CheeseCutter-master/src/audio/player.d000066400000000000000000000143711357241101300202660ustar00rootroot00000000000000/* CheeseCutter v2 (C) Abaddon. Licensed under GNU GPL. */ module audio.player; import com.cpu; import com.session; private import ct.base; import audio.timer; import audio.callback; import audio.audio; import audio.resid.filter; import seq.sequencer; import ui.ui; import derelict.sdl.sdl; import std.stdio; enum Status { Stop, Play, Keyjam }; shared private int playstatus; shared int[3] muted; int usefp = 1, sidtype, interpolate = 1, badline, ntsc; __gshared Filterparams curfp; int curfp6581 = 0, curfp8580 = 0; int getPlaystatus() { return playstatus; } @property bool isPlaying() { return playstatus == Status.Play || playstatus == Status.Keyjam; } @property bool keyjamEnabled() { return playstatus == Status.Keyjam; } void init() { if(audio_init(ntsc ? 60 : 50, &audio_frame) < 0) { throw new Error("Could not init audio."); } SDL_LockAudio(); curfp = sidtype ? FP8580[curfp8580] : FP6581[curfp6581]; sid_init(usefp, &curfp, freq, sidtype, ntsc, interpolate, 0); /+ if(!audioinited) { writefln("audio init: engine=%s, freq=%d, buf=%d, sid=%d, clock=%s, interpolation=%s%s", usefp ? "resid-fp" : "resid", audio.audio.audiospec.freq, audio.audio.bufferSize, sidtype ? 8580 : 6581, ntsc ? "ntsc" : "pal", interpolate ? "on" : "off" , badline ? ", badlines=on" : ""); } if(badline) { audio.audio.residdelay = 48; // 4 } else audio.audio.residdelay = 0; +/ SDL_UnlockAudio(); } void setSidModel(int v) { assert(v == 0 || v == 1); if(sidtype == v) return; sidtype = v; init(); } void toggleSIDModel() { setSidModel(sidtype ^ 1); } void playNote(Element emt) { if(playstatus == Status.Play) return; int v = seq.sequencer.activeVoiceNum; // no audio reset if already inited if(playstatus != Status.Keyjam) { audio.callback.reset(); audio.audio.reset(); } playstatus = Status.Stop; song.setVoicon([v == 0 ? 0 : 1, v == 1 ? 0 : 1, v == 2 ? 0 : 1]); muteSID(1,1,1); song.cpu.reset(); song.cpu.regs.a = emt.note.value; song.cpu.regs.x = cast(ubyte)v; song.cpu.regs.y = emt.instr.value; if(song.ver > 8) song.memspace[song.offsets[Offsets.SHTRANS] + v] = 0; ushort call = 0x1009; if(song.ver > 7) { call = song.offsets[Offsets.Subnoteplay]; } cpuCall(call,true); playstatus = Status.Keyjam; } void playRow(Voice[] voices) { if(playstatus == Status.Play) return; int[] trk, seq; foreach(v; voices) { auto r = v.activeRow; trk ~= r.trkOffset; seq ~= r.seqOffset; } SDL_PauseAudio(1); if(SDL_GetAudioStatus() == SDL_AUDIO_PLAYING) std.stdio.writefln("Audio thread not finished!"); SDL_Delay(20); stop(); initPlayOffset(trk, seq); song.cpu.reset(); cpuCall(0x1003,true); cpuCall(0x1003,true); cpuCall(0x1003,true); playstatus = Status.Keyjam; SDL_PauseAudio(0); } void start(int[] trk, int[] seq) { SDL_PauseAudio(1); if(SDL_GetAudioStatus() == SDL_AUDIO_PLAYING) std.stdio.writefln("Audio thread not finished!"); SDL_Delay(20); stop(); initPlayOffset(trk,seq); audio.timer.start(); audio.callback.reset(); audio.audio.reset(); playstatus = Status.Play; SDL_PauseAudio(0); } void start() { start([0, 0, 0], [0, 0, 0]); } void stop() { playstatus = Status.Stop; muteSID(1,1,1); } void toggleVoice(int v) { if(v > 2 || v < 0) return; muted[v] = muted[v] ^ 1; setVoicon(muted); } void setVoicon(int v1, int v2, int v3) { setVoicon([v1, v2, v3]); } void setVoicon(int[] m) { muted[0] = m[0]; muted[1] = m[1]; muted[2] = m[2]; muteSID(m[0], m[1], m[2]); song.setVoicon(muted); } void setVoicon(shared int[] m) { muted[0] = m[0]; muted[1] = m[1]; muted[2] = m[2]; muteSID(m[0], m[1], m[2]); song.setVoicon(muted); } void initFP() { init(); song.fppres = sidtype ? curfp8580 : curfp6581; } void nextFP() { if (usefp) { if (sidtype) { ++curfp8580; curfp8580 %= FP8580.length; } else { ++curfp6581; curfp6581 %= FP6581.length; } initFP(); } } void setFP(int fp) { if (usefp) { if (sidtype) { curfp8580 = cast(int)(fp % FP8580.length); } else { curfp6581 = cast(int)(fp % FP6581.length); } initFP(); } } void prevFP() { if (usefp) { if (sidtype) { --curfp8580; if (curfp8580 < 0) curfp8580 = cast(int)(FP8580.length-1); } else { --curfp6581; if (curfp6581 < 0) curfp6581 = cast(int)(FP6581.length-1); } initFP(); } } void fastForward(int val) { int step = val * 16; SDL_LockAudio(); for(int i = 0 ; i < step; i++) { audio_frame(); } SDL_UnlockAudio(); } void dumpFrame() { if(playstatus == Status.Play || playstatus == Status.Keyjam) audio.callback.requestDump(); } void setMultiplier(int m) { if(m < 1 || m > 16) return; song.multiplier = m; audio.audio.setCallMultiplier(m); } void decMultiplier() { setMultiplier(song.multiplier - 1); } void incMultiplier() { setMultiplier(song.multiplier + 1); } private void initPlayOffset(int[] t, int[] s) { void out16b(int offs, int value) { song.buffer[offs] = value & 255; song.buffer[offs + 1] = (value >> 8) & 255; } address off1 = cast(ushort)(song.offsets[Offsets.Track1] + t[0] * 2); address off2 = cast(ushort)(song.offsets[Offsets.Track2] + t[1] * 2); address off3 = cast(ushort)(song.offsets[Offsets.Track3] + t[2] * 2); int tpoin2 = song.offsets[Offsets.Songsets]; int tpoin = song.offsets[Offsets.TRACKLO]; song.cpu.reset(); if(song.ver >= 6) { song.buffer[tpoin] = off1 & 255; song.buffer[tpoin+1] = off2 & 255; song.buffer[tpoin+2] = off3 & 255; song.buffer[tpoin+3] = off1 >> 8; song.buffer[tpoin+4] = off2 >> 8; song.buffer[tpoin+5] = off3 >> 8; out16b(tpoin2, song.offsets[Offsets.Track1]); out16b(tpoin2+2, song.offsets[Offsets.Track2]); out16b(tpoin2+4, song.offsets[Offsets.Track3]); } else { out16b(tpoin2, off1); out16b(tpoin2+2, off2); out16b(tpoin2+4, off3); } cpuCall(0x1000,false); int seqcnt = song.offsets[Offsets.NEWSEQ]; song.buffer[seqcnt] = cast(ubyte)(s[0] * 4 + 1); song.buffer[seqcnt+1] = cast(ubyte)(s[1] * 4 + 1); song.buffer[seqcnt+2] = cast(ubyte)(s[2] * 4 + 1); song.setVoicon(muted); SDL_PauseAudio(0); } private void muteSID(int v1, int v2, int v3 ) { if(v1) song.sidbuf[4] = 0x08; if(v2) song.sidbuf[7 + 4] = 0x08; if(v3) song.sidbuf[14 + 4]= 0x08; } CheeseCutter-master/src/audio/resid/000077500000000000000000000000001357241101300177255ustar00rootroot00000000000000CheeseCutter-master/src/audio/resid/filter.d000066400000000000000000000054431357241101300213650ustar00rootroot00000000000000module audio.resid.filter; struct Filterparams { float dr; float dp; float cft; float t3b; float t3o; float t3s; float t3m; float t4k; float t4b; float v; string id; } static const Filterparams[] FP6581 = [ {0.5f, 3.3e6f, 3.0e-4f, 1646009.8408527481f, 30099093.879106432f, 1.0054673476018452f, 14227.912103009101f, 5.5f, 20.0f, 0.9613160610660189f, "6581R3 2083"}, {0.5f, 3.3e6f, 3.0e-4f, 1.9e6f, 8.5e7f, 1.0058f, 2e4f, 5.5f, 20.0f, 0.9613160610660189f, "6581R3 0384"}, {0.5f, 3.3e6f, 3.0e-4f, 1.3e6f, 3.7e8f, 1.0066f, 1.8e4f, 5.5f, 20.0f, 0.9613160610660189f, "6581R3 0784"}, {0.5f, 3.3e6f, 3.0e-4f, 1.83e6f, 2.6e9f, 1.0064f, 2.5e4f, 5.5f, 20.0f, 0.9613160610660189f, "6581R3 1984"}, {0.5f, 3.3e6f, 3.0e-4f, 1.16e6f, 9.9e6f, 1.0058f, 1.48e4f, 5.5f, 20.0f, 0.9613160610660189f, "6581R3 3384"}, {0.5f, 3.3e6f, 3.0e-4f, 1.65e6f, 1.2e10f, 1.006f, 1e4f, 5.5f, 20.0f, 0.9613160610660189f, "6581R3 3684"}, {0.5f, 3.3e6f, 3.0e-4f, 1522171.922983084f, 21729926.667291082f, 1.004994802537475f, 14299.149638099827f, 5.5f, 20.0f, 0.9613160610660189f, "6581R3 3984"}, {0.5f, 3.3e6f, 3.0e-4f, 1.5e6f, 1.8e8f, 1.0065f, 1.8e4f, 5.5f, 20.0f, 0.9613160610660189f, "6581R3 3985"}, {0.5f, 3.3e6f, 3.0e-4f, 1.55e6f, 2.5e8f, 1.006f, 1.9e4f, 5.5f, 20.0f, 0.9613160610660189f, "6581R3 4285"}, {0.5f, 3.3e6f, 3.0e-4f, 1399768.3253307983f, 553018906.8926692f, 1.0051493199361266f, 11961.908870403166f, 5.5f, 20.0f, 0.9613160610660189f, "6581R3 4485"}, {0.5f, 3.3e6f, 3.0e-4f, 840577.4520801408f, 1909158.8633669745f, 1.0068865662510837f, 14858.140079688419f, 5.5f, 20.0f, 0.9613160610660189f, "6581R3 4885"}, {0.5f, 3.3e6f, 3.0e-4f, 1164920.4999651583f, 12915042.165290257f, 1.0058853753357735f, 12914.5661141159f, 5.5f, 20.0f, 0.9613160610660189f, "6581R3 0486S"}, {0.5f, 3.3e6f, 3.0e-4f, 1250736.2235895505f, 1521187976.8735676f, 1.005543646897986f, 8581.78418415723f, 5.5f, 20.0f, 0.9613160610660189f, "6581R4 1986S"}, {0.5f, 3.3e6f, 3.0e-4f, 1.3e6f, 1.9e8f, 1.0066f, 1.8e4f, 5.5f, 20.0f, 0.9613160610660189f, "6581R4AR 2286"}, {0.5f, 3.3e6f, 3.0e-4f, 1.1e6f, 8e6f, 1.0052f, 1.7e4f, 5.5f, 20.0f, 0.9613160610660189f, "6581R4AR 4486"}, {0.5f, 3.3e6f, 3.0e-4f, 1.45e6f, 1.75e8f, 1.0055f, 1e4f, 5.5f, 20.0f, 0.9613160610660189f, "6581R4AR 3488"}, {0.5f, 3.3e6f, 3.0e-4f, 1141069.9277645703f, 276016753.85303545f, 1.0066634233403395f, 16402.86712485317f, 5.5f, 20.0f, 0.9613160610660189f, "6581R4AR 3789"} ]; static const Filterparams[] FP8580 = [ {0.5f, 0f, 0f, 840577.4520801408f, 1909158.8633669745f, 1.0068865662510837f, 14858.140079688419f, 5.7f, 20.0f, 0.9613160610660189f, "8580R5 1489"}, {0.5f, 0f, 0f, 840577.4520801408f, 1909158.8633669745f, 1.0068865662510837f, 14858.140079688419f, 6.55f, 20.0f, 0.9613160610660189f, "8580R5 3691"} ]; CheeseCutter-master/src/audio/resid/residctrl.cpp000066400000000000000000000107011357241101300224230ustar00rootroot00000000000000/* reSID interface * * much of the code here is from GOATTRACKER, (c) Cadaver */ #define PALCLOCKRATE 985248 #define NTSCCLOCKRATE 1022727 #define NUMSIDREGS 0x19 #define SIDWRITEDELAY 9 // lda $xxxx,x 4 cycles, sta $d400,x 5 cycles #define SIDWAVEDELAY 4 // and $xxxx,x 4 cycles extra #include #include #include //#include #include extern "C" { typedef struct { float distortionrate; float distortionpoint; float distortioncfthreshold; float type3baseresistance; float type3offset; float type3steepness; float type3minimumfetresistance; float type4k; float type4b; float voicenonlinearity; } FILTERPARAMS; int clockrate; int samplerate; unsigned char sidreg[NUMSIDREGS]; const unsigned char sidorder[] = { 0x0e,0x0f,0x14,0x13,0x10,0x11,0x12, 0x07,0x08,0x0d,0x0c,0x09,0x0a,0x0b, 0x00,0x01,0x06,0x05,0x02,0x03,0x04, 0x16,0x17,0x18,0x15 }; SID *sid= 0; SIDFP *sidfp = 0; int residdelay = 0; int usefp = 0; void sid_close() { if(sid) delete sid; if(sidfp) delete sidfp; } void sid_init(int fp, FILTERPARAMS *fparams, int speed, unsigned m, unsigned ntsc, unsigned interpolate, unsigned customclockrate) { int c; usefp = fp; if (ntsc) clockrate = NTSCCLOCKRATE; else clockrate = PALCLOCKRATE; if (customclockrate) clockrate = customclockrate; samplerate = speed; if (!sidfp) sidfp = new SIDFP(); if (!sid) sid = new SID(); if(usefp) { switch(interpolate) { case 0: sidfp->set_sampling_parameters(clockrate, SAMPLE_INTERPOLATE, speed); break; default: sidfp->set_sampling_parameters(clockrate, SAMPLE_RESAMPLE_INTERPOLATE, speed); break; } sidfp->reset(); for (c = 0; c < NUMSIDREGS; c++) { sidreg[c] = 0x00; } if (m == 1) sidfp->set_chip_model(MOS8580); else sidfp->set_chip_model(MOS6581); sidfp->get_filter().set_distortion_properties( fparams->distortionrate, fparams->distortionpoint, fparams->distortioncfthreshold); sidfp->get_filter().set_type3_properties( fparams->type3baseresistance, fparams->type3offset, fparams->type3steepness, fparams->type3minimumfetresistance); sidfp->get_filter().set_type4_properties( fparams->type4k, fparams->type4b); sidfp->set_voice_nonlinearity( fparams->voicenonlinearity); sidfp->enable_filter(true); } else { switch(interpolate) { case 0: sid->set_sampling_parameters(clockrate, SAMPLE_FAST, speed, 20000); break; default: sid->set_sampling_parameters(clockrate, SAMPLE_INTERPOLATE, speed, 20000); break; } sid->reset(); for (c = 0; c < NUMSIDREGS; c++) { sidreg[c] = 0x00; } if (m == 1) { sid->set_chip_model(MOS8580); } else { sid->set_chip_model(MOS6581); } } } unsigned char sid_getorder(unsigned char index) { return sidorder[index]; } int sid_fillbuffer(short *ptr, int samples, const int cyc) { int os = samples; int rc = cyc / 3; // NUMVOICE int badline = rand() % NUMSIDREGS; int tdelta; int tdelta2; int result; int total = 0; int c; tdelta = clockrate * samples / samplerate; for (c = 0; c < NUMSIDREGS; c++) { unsigned char o = sid_getorder(c); // Extra delay per music routine iteration if (cyc > 0 && ((c == 0) || (c == 7) || (c == 14))) { tdelta2 = rc; if(usefp) result = sidfp->clock(tdelta2, ptr, samples); else result = sid->clock(tdelta2, ptr, samples); total += result; ptr += result; samples -= result; tdelta -= rc; } // Possible random badline delay once per writing /* if ((badline == c) && (residdelay)) { tdelta2 = residdelay; result = sid->clock(tdelta2, ptr, samples); total += result; ptr += result; samples -= result; tdelta -= residdelay; } */ if(usefp) sidfp->write(o, sidreg[o]); else sid->write(o, sidreg[o]); tdelta2 = SIDWRITEDELAY; if(usefp) result = sidfp->clock(tdelta2, ptr, samples); else result = sid->clock(tdelta2, ptr, samples); total += result; ptr += result; samples -= result; tdelta -= SIDWRITEDELAY; } if(usefp) result = sidfp->clock(tdelta, ptr, samples); else result = sid->clock(tdelta, ptr, samples); total += result; // assert(total <= os); return total; } } CheeseCutter-master/src/audio/timer.d000066400000000000000000000017531357241101300201120ustar00rootroot00000000000000/* CheeseCutter v2 (C) Abaddon. Licensed under GNU GPL. */ module audio.timer; import audio.audio; import com.session; __gshared int sec, min; __gshared private int clockCounter; __gshared private int fplayTickCounter, fplayRowCounter; // how many rows done since last fplay update? __gshared private int tickCounter; int readRowTick() { int t = fplayRowCounter; fplayRowCounter = 0; return t; } int readTick() { int t = tickCounter; tickCounter = 0; return t; } void stop() { } /+ from player.start +/ void start() { sec = min = clockCounter = 0; fplayTickCounter = fplayRowCounter = 0; } /+ should be called each on update from callback +/ void tick() { if(++clockCounter >= audio.audio.framerate) { clockCounter = 0; if(++sec > 59) { sec = 0; min++; min %= 100; } } } /+ should be called once per frame cycle, updated fplay counters +/ void tickFullFrame() { tickCounter++; if(++fplayTickCounter > song.playSpeed) { fplayRowCounter++; fplayTickCounter = 0; } } CheeseCutter-master/src/c64/000077500000000000000000000000001357241101300161125ustar00rootroot00000000000000CheeseCutter-master/src/c64/player_v4.acme000066400000000000000000000733141357241101300206560ustar00rootroot00000000000000;;; ---------------------------------------- ;;; CCUTTER 2.x musicplayer by abad ;;; Based on JCH NP 21.G4 by Laxity/VIB ;;; ---------------------------------------- !ifdef ZREG { } else { ZREG = $fb } FALSE = 0 TRUE = 1 EXPORT = FALSE ; if TRUE, editor specific code will be left out MULTISPEED = TRUE ; support for multispeed playback INSNO = 48 ; number of instruments used CIA_VALUE = $4cc7 ; for multispeed MULTIPLIER = 1 ; for multispeed BASEADDRESS = $1000 ;;; ---------------------------------------- ;;; instr table enums ;;; ---------------------------------------- INS_AD = 0 ; INS_SR = 1 * INSNO INS_HR = 2 * INSNO ; $x0 = HR type, $0x arp delay count INS_4 = 3 * INSNO ; HR waveform INS_FLTP = 4 * INSNO ; INS_PULSP = 5 * INSNO ; INS_7 = 6 * INSNO ; INS_ARP = 7 * INSNO ;;; ---------------------------------------- ;;; assembly conditionals ;;; ---------------------------------------- INCLUDE_CMD_SLUP = TRUE INCLUDE_CMD_SLDOWN = TRUE INCLUDE_CMD_VIBR = TRUE INCLUDE_CMD_PORTA = TRUE INCLUDE_CMD_SET_ADSR = TRUE INCLUDE_CMD_SET_OFFSET = TRUE INCLUDE_CMD_SET_LOVIB = TRUE INCLUDE_CMD_SET_WAVE = FALSE INCLUDE_SEQ_SET_PULSE = TRUE INCLUDE_SEQ_SET_CHORD = TRUE INCLUDE_SEQ_SET_ATT = TRUE INCLUDE_SEQ_SET_DEC = TRUE INCLUDE_SEQ_SET_SUS = TRUE INCLUDE_SEQ_SET_REL = TRUE INCLUDE_SEQ_SET_SPEED = TRUE INCLUDE_SEQ_SET_VOL = TRUE INCLUDE_DIRECT_PULSE = TRUE INCLUDE_VIBRAFEEL = TRUE INCLUDE_BREAKSPEED = TRUE INCLUDE_CHORD = TRUE INCLUDE_FILTER = TRUE INCLUDE_SYNC = TRUE USE_MDRIVER = FALSE ;;; ---------------------------------------- ;;; new effect commands ;;; ---------------------------------------- CMD_SLIDE_UP = $00 CMD_SLIDE_DOWN = $01 CMD_VIBRATO = $02 CMD_SET_OFFSET = $03 CMD_SET_ADSR = $04 CMD_SET_LOVIB = $05 CMD_SET_WAVE = $06 CMD_PORTAMENTO = $07 CMD_STOP = $08 ;stop portamento/slide ;;; ---------------------------------------- SUPERHIGH = CMD_SET_OFFSET ;;; ---------------------------------------- ;;; the following data describes the player features ;;; for the editor ;;; ---------------------------------------- !if EXPORT = FALSE { *=$e00 features = * requestedTables !8 %00001111 ;;; 1 = points to wave table ;;; 2 = points to cmd table (NOT IMPLEMENTED) ;;; 3 = points to pulse table ;;; 4 = points to filter table ;;; ... instrumentFlags !8 0,0,0,0,4,3,0,1 ;;; 1 = points to wave table ;;; 3 = points to pulse table ;;; 4 = points to filter table cmdFlags !8 0,0,0,0,0,0,0,0 !8 0,0,0,0,0,0,0,0 instrumentDescriptionsHeader !16 idescr0,idescr1,idescr2,idescr3,idescr4,idescr5,idescr6,idescr7 pulseDescriptionsHeader !16 pdescr0,pdescr1,pdescr2,pdescr3 filterDescriptionsHeader !16 fdescr0,fdescr1,fdescr2,fdescr3 waveDescriptionsHeader !16 wdescr0,wdescr1 cmdDescriptionsHeader !16 mdescr0,mdescr1 } ;;; ---------------------------------------- ;;; some pointers for the editor ;;; ---------------------------------------- !if EXPORT = FALSE { *= $0fa0 ofa0 !16 features ofa2 !16 volume ofa4 !16 editorflag ofa6 !16 songsets ofa8 !16 playspeed ofaa !16 subnoteplay ofac !16 submplayplay ofae !16 instrumentDescriptionsHeader ofb0 !16 pulseDescriptionsHeader ofb2 !16 filterDescriptionsHeader ofb4 !16 waveDescriptionsHeader ofb6 !16 cmdDescriptionsHeader ofb8 !16 dummy ofba !16 dummy ofbc !16 arp1 ofbe !16 arp2 ofc0 !16 filttab ofc2 !16 pulstab ofc4 !16 inst ofc6 !16 track1 ofc8 !16 track2 ofca !16 track3 ofcc !16 seqlo ofce !16 seqhi ofd0 !16 cmd1 ofd2 !16 s0 ofd4 !16 speed ofd6 !16 tracklo ofd8 !16 voice ;voice 1c X, for voice on/of flagging ofda !16 gate ofdc !16 chord ofde !16 trans ofe0 !16 chordindex ofe2 !16 shtrans ofe6 !16 dummy ofe8 !16 dummy ofea !16 dummy ofec !16 dummy ofee !16 newseq version !pet "cc4.07" } ;;; ---------------------------------------- ;;; editor specific player routines, will be ;;; left out from a finalized tune ;;; ---------------------------------------- !if EXPORT = FALSE { *=$f000 idescr0 !raw "Attack / Decay.",0 idescr1 !raw "Sustain / Release.",0 idescr2 !raw "Restart type / arpeggio speed.&$00 = 3 Frame Restart.&$40 = Soft restart.&$80 = Hard Restart. &$00-$0F = Arpeggio delay value.",0 idescr3 !raw "Hard Restart waveform.",0 idescr4 !raw "Filter Table pointer.",0 idescr5 !raw "Pulse Table pointer $00-$3f.",0 idescr6 !raw "Hard restart SR envelope value.",0 idescr7 !raw "Wave Table pointer.",0 pdescr0 !raw "Duration and direction.&$00-$7F = Add n frames.&$80-$FF = Subtract n frames.",0 pdescr1 !raw "Add value.",0 pdescr2 !raw "Initial pulse value.&Note: Nibbles are reversed! $48 = $8400",0 pdescr3 !raw "Pointer to next set ($00-$3F) or $7F = stop pulse program.",0 fdescr0 !raw "Duration or filter type.&$00-$7f = Duration or $90-$F0 select filter type.",0 fdescr1 !raw "Add value or filter resonance and channel mask.",0 fdescr2 !raw "Initial filter value or $FF = skip.",0 fdescr3 !raw "Pointer to next set ($00-$3F) or $7F = stop filter program.",0 ;;; wave table help wdescr0 !raw "Transpose value / Loop.&$00-$5F = Relative transpose up,&" !raw "$80-$DF = Absolute tuning (unaffected by note/transpose value).&" !raw "$7E = loop to previous row, $7F = loop to row",0 wdescr1 !raw "Waveform / Wave delay / Loop pointer&" !raw "$00 = Do nothing.&" !raw "$01 - $0F = Override instrument's Wave Delay value for this row.&" !raw "$10 - $DF = Waveform; SID Control Register value.&" !raw "$E0 - $EF = SID Control Register value $00 - $0F.&" !raw "$00 - $FF = Loop pointer, if Byte 1 = $7F.",0 ;;; Command table help mdescr0 !raw "Command number.&" !raw "$0 = Slide up.&" !raw "$1 = Slide down.&" !raw "$2 = Hi-fi Vibrato.&" !raw "$3 = Detune current note.&" !raw "$4 = Set ADSR for the current note.&" !raw "$5 = Lo-fi vibrato.&" !raw "$6 = Set wave.&" !raw "$7 = Portamento a tie note.&" !raw "$8 = Stop portamento",0 mdescr1 !raw "Parameter values.&" !raw "Slide up/down: Slide speed (signed 16-bit).&" !raw "Vibrato: 1st byte, lonibble: vibrato 'feel'&" !raw " 2nd byte, hinibble: Speed.&" !raw " lonibble: Depth divider (bigger value = narrower vibrato).&" !raw "Detune: (signed 16-bit).&" !raw "ADSR: (self-explanatory).&" !raw "Lo-fi vibrato: Speed / Depth." !raw "&Set waveform (in the last parameter byte).&" ;;; !raw "Portamento: (Portamento must be applied to tie notes only and reset with e.g. No command 8-00 00).",0 !raw "Portamento: Portamento speed. Runs until a command 8-00 00 is given).",0 *=$f800 submplayplay lda #$80 sta state ldx #2 jmp updsound ;;; ---------------------------------------- ;;; used for triggering a note from th editor ;;; ---------------------------------------- subnoteplay sta shnote,x cmp #3 lda #0 rol eor #1 sta tienote,x tya sta shinst,x lda #3 sta tsync,x lda #0 sta synccnt,x lda #1 sta newinsflag,x lda #0 sta effstate,x sta chordvalue,x lda #$80 sta state sta chordtpos,x jmp updsound } *= BASEADDRESS init !if USE_MDRIVER = TRUE { jmp cinit } else { jmp subinit } play !if USE_MDRIVER = TRUE { jmp cplay } else { jmp subplay } !if MULTISPEED = TRUE { mplay jmp submplay } sync !8 0 ;--------------------------------------- subinit asl asl asl tay ldx #0 !if INCLUDE_BREAKSPEED = TRUE { stx speedsub } !if INCLUDE_SYNC = TRUE { stx sync } subinit0 lda songsets,y sta twraplo,x iny lda songsets,y sta twraphi,x iny inx cpx #3 bne subinit0 lda songsets,y ;set song speed sta speed !if EXPORT = FALSE { cmp #2 bcs subinit00 lda chord subinit00 sta playspeed lda editorflag beq subinit3 } ldx #2 subinit1 lda songsets+1,y and bits,x sta voicon,x lda twraplo,x ; trackpointers not set from the editor sta tracklo,x lda twraphi,x sta trackhi,x lda #1 ; newseq not set from the editor sta newseq,x dex bpl subinit1 subinit3 lda #1 sta state rts ;;; ---------------------------------------- ;;; do only sound work, used for multispeed ;;; playback frames ;;; ---------------------------------------- !if MULTISPEED = TRUE { submplay lda #$40 sta state ldx #2 jmp syncskip } ;;; ---------------------------------------- ;;; regular play call ;;; ---------------------------------------- subplay lda state beq run lda #2 sta speedcnt ldx #(clrlast-clrfirst) lda #0 subinit4 dex sta clrfirst,x bne subinit4 ;; reset synchonization ldx #2 subinit5 lda #2 sta synccnt,x ; HR allowed lda #$fe sta tsync,x ; sync done dex bpl subinit5 lda #$0f sta volume !if INCLUDE_FILTER = TRUE { lda #0 sta filter sta bandpass } lda #$f0 sta $d417 lda #0 sta state rts run dec speedcnt bpl speeddone lda speed !if INCLUDE_BREAKSPEED = TRUE { cmp #2 bpl speedok speedalt ldy speedsub lda chord,y bpl nowrap ldy #0 sty speedsub lda chord,y nowrap inc speedsub sta playspeed cmp #2 bpl speedok lda #2 } speedok sta speedcnt speeddone ;--------------------------------------- ldx #2 main0 lda voicon,x bne trackon jmp next trackon inc synccnt,x lda speedcnt beq jupdseq cmp #1 beq updtrack jmp updsound jupdseq jmp updseq ;--------------------------------------- updtrack lda newseq,x beq skiptrack sec sbc #1 sta seqcnt,x lda #0 sta newseq,x tay lda tracklo,x sta ZREG lda trackhi,x sta ZREG+1 lda (ZREG),y bpl trk02 cmp #$80 ; get transpose value beq skiptrans sbc #$a0 sta shtrans2,x skiptrans inc tracklo,x bne trk01 inc trackhi,x trk01 iny lda (ZREG),y trk02 sta curseq,x iny lda (ZREG),y cmp #$f0 bcc trk03 pha iny lda (ZREG),y clc adc twraplo,x sta tracklo,x pla and #$07 adc twraphi,x ; song wrap sta trackhi,x jmp updsound trk03 inc tracklo,x bne skiptrack inc trackhi,x skiptrack jmp updsound ;--------------------------------------- updseq dec durcnt,x bmi nextnote jmp updsound nextnote ldy curseq,x lda seqlo,y sta ZREG lda seqhi,y sta ZREG+1 lda #2 sta tsync,x getseq ldy seqcnt,x seqnext lda (ZREG),y cmp #$c0 bcs command cmp #$60-1 ; command coming up? bcc nocmdbyt sbc #$60 bpl nottie inc tienote,x ; $5f = flag tienote iny jmp seqnext nottie pha ; store note value iny lda (ZREG),y ; fetch sequence command beq skipcmd sta shsuper,x inc newcmdflag,x skipcmd pla nocmdbyt sta shnote,x ; check for rest & gate flags cmp #3 bcs sequpdtrans settie inc tienote,x jmp seqdone command cmp #$f0 bmi notdur setdur and #$0f sta duration,x iny jmp seqnext notdur sbc #$c0-1 sta shinst,x inc newinsflag,x iny jmp seqnext sequpdtrans lda shtrans2,x sta shtrans,x seqdone iny beq seqsetflag ; new seq automatically if seqcnt wrapped tya sta seqcnt,x lda (ZREG),y cmp #$bf ;seq end mark bne noteos seqsetflag inc newseq,x noteos lda duration,x sta durcnt,x !if INCLUDE_CMD_PORTA = TRUE { lda newcmdflag,x beq snotporta ; ! ;; Check for super commands that ;; ;should be parsed immidiately ldy shsuper,x ;cmd byte? cpy #$40 bpl updsound lda cmd1,y cmp #CMD_PORTAMENTO bne snotporta lda cmd2,y and #$0f sta portahi,x lda cmd3,y sta portalo,x lda #$81 sta effstate,x ;; formerly clrsuper lda #0 sta newcmdflag,x jmp updsound snotporta } ;;; ---------------------------------------- ;;; sound work ;;; ---------------------------------------- updsound lda #0 sta hardon,x lda tsync,x bpl dosync jmp syncskip dosync dec tsync,x lda tienote,x beq syncnottied jmp syncskip syncnottied lda tsync,x cmp #1 bne syncgate lda synccnt,x ; hard restart possible? cmp #2 bmi syncnohr ldy shinst,x ; use hard restart? lda inst+INS_HR,y bpl syncnohr and #$20 bne laxhr ;; Hard restart lda cmd2 ;Set adsr for HR sta ad,x laxhr lda inst+INS_7,y sta sr,x syncnohr lda #$fe sta gate,x jmp dowave ;only update wavetable syncgate cmp #$ff beq syncgateon jmp syncskip syncgateon lda newinsflag,x beq checknote ldy shinst,x lda inst,y ;Store ADSR of insturmen in shadow sta shad,x ;ADSR regs lda inst+INS_SR,y sta shsr,x lda effstate,x ;don't reset porta bmi checknote lda #0 sta effstate,x checknote lda shtrans,x ;set transpose to current sta trans,x lda shnote,x clc ;get real (transposed) value of the note adc trans,x sta notereal,x ldy effstate,x ;skip if portamento bmi skipsetfrq !if INCLUDE_CMD_PORTA = TRUE { tay lda freqtable_lo,y sta plo,x lda freqtable_hi,y sta phi,x } txa sta shfreqlo,x lda #0 sta shfreqhi,x skipsetfrq ldy shinst,x lda inst+INS_ARP,y ;set wave pos sta wavepos,x lda shad,x ;set ADSR sta ad,x lda shsr,x sta sr,x lda inst+INS_PULSP,y ;set the pulse beq setflt !if INCLUDE_DIRECT_PULSE = TRUE { bpl skippdirect and #$0f sta pulsehi,x lda #0 sta pulselo,x jmp pulsdirset } skippdirect asl asl pulsdirset sta pulsenxt,x ;pointer lda #0 sta pulsecnt,x setflt !if INCLUDE_FILTER = TRUE { lda inst+INS_FLTP,y beq filterdone ;no filter reset skipcutdirect asl asl sta filtnxt lda #0 sta filtcnt filterdone } scmddone lda #0 sta newinsflag,x !if INCLUDE_CHORD = TRUE { sta chordvalue,x lda #$80 sta chordtpos,x } lda inst+INS_HR,y ;set wave timer and #$0f sta wavetime,x lda #0 sta wavecnt,x lda inst+INS_HR,y and #$c0 ;Check for soft cmp #$40 ;restart beq wavenotoff lda inst+INS_4,y ora #1 sta waveform,x inc hardon,x wavenotoff lda #$ff ;Gate on sta gate,x lda #$00 ;Reset sync sta synccnt,x ldy effstate,x bmi noeffreset sta effstate,x noeffreset jmp checksuper syncskip ;;; ---------------------------------------- ;;; pulsework ;;; ---------------------------------------- updatepulse ldy pulsecur,x dec pulsecnt,x bpl pulsenotnew lda pulsenxt,x sta pulsecur,x tay lda pulstab+2,y cmp #$ff beq pulseskipset sta ZREG and #$f0 sta pulselo,x lda ZREG and #$0f sta pulsehi,x pulseskipset lda pulstab+0,y and #$7f sta pulsecnt,x lda pulstab+3,y bne pulsenotnxt lda pulsenxt,x clc adc #4 jmp pulsesetnxt pulsenotnxt cmp #$7f bne pulsenotstop lda #0 jmp pulsesetnxt pulsenotstop asl asl pulsesetnxt sta pulsenxt,x pulsenotnew lda pulstab,y bmi pulsesub lda pulselo,x clc adc pulstab+1,y sta pulselo,x bcc pulsedone inc pulsehi,x jmp pulsedone pulsesub lda pulselo,x sec sbc pulstab+1,y sta pulselo,x bcs pulsedone dec pulsehi,x pulsedone ;;; ---------------------------------------- ;;; sfx ;;; ---------------------------------------- lda effstate,x bne effdo1 jmp effdone effdo1 !if INCLUDE_CMD_SLUP { cmp #$01 bne effdo2 effslideup lda shfreqlo,x clc adc slidelo,x sta shfreqlo,x lda shfreqhi,x adc slidehi,x sta shfreqhi,x jmp effdone } effdo2 !if INCLUDE_CMD_SLDOWN { cmp #$02 bne effdo3 effslidedown lda shfreqlo,x sec sbc slidelo,x sta shfreqlo,x lda shfreqhi,x sbc slidehi,x sta shfreqhi,x jmp effdone } effdo3 !if INCLUDE_CMD_SET_LOVIB = TRUE { cmp #$04 bne effdo3a lda vibraamp,x sta ZREG lda #0 asl ZREG rol asl ZREG rol sta ZREG+1 jmp vibrealadd } effdo3a !if INCLUDE_CMD_VIBR = FALSE { jmp effdo4 } else { ;;; !if INCLUDE_CMD_VIBR = TRUE | INCLUDE_CMD_SET_LOVIB = TRUE { cmp #$03 beq effvibrato jmp effdo4 effvibrato ldy notereal,x sec lda freqtable_lo+1,y sbc freqtable_lo,y sta ZREG lda freqtable_hi+1,y sbc freqtable_hi+0,y sta ZREG+1 lda vibracor,x clc adc vibraamp,x tay lda #0 sta vibracor,x viblessamp dey bmi vibadd lsr ZREG+1 ror ZREG jmp viblessamp vibadd lda ZREG clc adc vibrafl,x sta ZREG lda ZREG+1 adc vibrafh,x sta ZREG+1 lda vibrafl,x clc adc vibraflv,x sta vibrafl,x lda vibrafh,x adc #0 sta vibrafh,x } !if INCLUDE_CMD_VIBR = TRUE | INCLUDE_CMD_SET_LOVIB = TRUE { vibrealadd lda vibradir,x and #1 bne vibradown lda shfreqlo,x clc adc ZREG sta shfreqlo,x lda shfreqhi,x adc ZREG+1 sta shfreqhi,x jmp vibrapost vibradown lda shfreqlo,x sec sbc ZREG sta shfreqlo,x lda shfreqhi,x sbc ZREG+1 sta shfreqhi,x vibrapost clc lda vibracnt,x adc #1 cmp vibrafrq,x bcc vibradirok inc vibradir,x lda #0 vibradirok sta vibracnt,x vibradone } effdo4 !if INCLUDE_CMD_PORTA = TRUE { cmp #$81 ; Portamento beq effporta jmp effdone effporta ldy notereal,x lda freqtable_lo,y sta ZREG lda freqtable_hi,y sta ZREG+1 lda plo,x sec sbc ZREG sta plo,x lda phi,x sbc ZREG+1 sta phi,x bmi portaup lda plo,x sec sbc portalo,x sta plo,x lda phi,x sbc portahi,x sta phi,x bpl portaclc jmp portaset portaup lda plo,x clc adc portalo,x sta plo,x lda phi,x adc portahi,x sta phi,x bmi portaclc portaset lda ZREG sta plo,x lda ZREG+1 sta phi,x jmp portadone portaclc lda plo,x clc adc ZREG sta plo,x lda phi,x adc ZREG+1 sta phi,x portadone ldy notereal,x lda plo,x sec sbc freqtable_lo,y sta shfreqlo,x lda phi,x sbc freqtable_hi,y sta shfreqhi,x } effdone ;;; ---------------------------------------- ;;; update wavetable ;;; ---------------------------------------- dowave lda hardon,x beq waveok jmp wavedone waveok dec wavecnt,x bpl waveprocess lda wavetime,x sta wavecnt,x ldy wavepos,x lda arp1,y sta wavetrans,x lda arp2,y cmp #$10 bcc waveskip cmp #$e0 bcc wavereg and #$0f wavereg sta waveform,x waveskip lda arp1+1,y cmp #$7e beq wavestore iny wavenotend cmp #$7f bne wavenotend2 lda arp2,y tay wavenotend2 lda arp2,y beq wavestore cmp #$10 bcs wavestore sta wavecnt,x wavestore tya sta wavepos,x !if INCLUDE_CHORD = TRUE { ldy chordtpos,x bmi chorddone chordinit lda chord,y cmp #$40 bcc chordnotneg ora #$80 chordnotneg sta chordvalue,x inc chordtpos,x lda chord+1,y bpl chorddone and #$7f sta chordtpos,x chorddone } waveprocess lda wavetrans,x bpl wavenotabs waveabs and #$7f tay lda freqtable_lo,y sta freqlo,x lda freqtable_hi,y sta freqhi,x jmp wavedone wavenotabs clc adc notereal,x !if INCLUDE_CHORD = TRUE { adc chordvalue,x } tay lda freqtable_lo,y clc adc shfreqlo,x sta freqlo,x lda freqtable_hi,y adc shfreqhi,x sta freqhi,x wavedone ;;; ------------------------------------------------------------ checksuper lda tsync,x cmp #$ff beq supersync jmp superdone supersync lda newcmdflag,x bne superparse jmp superdone superparse lda #0 sta newcmdflag,x superparse2 ldy shsuper,x cpy #$40 bcs *+5 jmp iscmd tya cmp #$60 bcs notpulse and #$1f asl asl sta pulsenxt,x lda #0 sta pulsecnt,x jmp superdone notpulse !if INCLUDE_FILTER = TRUE { cmp #$80 bcs notfilt and #$1f asl asl sta filtnxt lda #0 sta filtcnt jmp superdone notfilt } !if INCLUDE_CHORD = TRUE { cmp #$a0 bcs notchord and #$1f tay lda chordindex,y sta chordtpos,x jmp superdone } notchord !if INCLUDE_SEQ_SET_ATT = TRUE { cmp #$b0 bcs notatt asl asl asl asl sta ZREG lda ad,x and #$0f ora ZREG sta ad,x jmp superdone } notatt !if INCLUDE_SEQ_SET_DEC = TRUE { cmp #$c0 bcs notdec and #$0f sta ZREG lda ad,x and #$f0 ora ZREG sta ad,x jmp superdone } notdec !if INCLUDE_SEQ_SET_SUS = TRUE { cmp #$d0 bcs notsus asl asl asl asl sta ZREG lda sr,x and #$0f ora ZREG sta sr,x jmp superdone } notsus !if INCLUDE_SEQ_SET_REL = TRUE { cmp #$e0 bcs notrel and #$0f sta ZREG lda sr,x and #$f0 ora ZREG sta sr,x jmp superdone } notrel !if INCLUDE_SEQ_SET_VOL = TRUE { cmp #$f0 bcs notvol and #$0f sta volume jmp superdone } notvol !if INCLUDE_SEQ_SET_SPEED = TRUE { and #$0f !if INCLUDE_SYNC = TRUE { bne notsync inc sync jmp superdone notsync } sta speed !if INCLUDE_BREAKSPEED = TRUE { cmp #2 bcs notvol2 lda #1 sta speedsub lda chord } notvol2 sta playspeed sta speedcnt dec speedcnt } jmp superdone ;;; ---------------------------------------- ;;; process a command table entry ;;; ---------------------------------------- iscmd lda cmd2,y sta ZREG lda cmd1,y ; and #$0f sta ZREG+1 cmp #SUPERHIGH bcc superlow jmp superhigh ;SLIDE UP superlow !if INCLUDE_CMD_SLUP = TRUE { cmp #0 bne snotslide1 lda ZREG sta slidehi,x lda cmd3,y sta slidelo,x lda #1 sta effstate,x jmp superdone } ;SLIDE DOWN snotslide1 !if INCLUDE_CMD_SLDOWN = TRUE { cmp #CMD_SLIDE_DOWN bne snotslide2 lda ZREG sta slidehi,x lda cmd3,y sta slidelo,x lda #2 sta effstate,x jmp superdone } ;VIBRATO snotslide2 !if INCLUDE_CMD_VIBR = TRUE { cmp #CMD_VIBRATO bne snotvibrato lda #3 sta effstate,x lda ZREG and #$0f sta vibraflv,x lda cmd3,y and #$0f sta vibraamp,x lda cmd3,y lsr lsr lsr lsr clc adc #1 sta vibrafrq,x lsr bcc novibcor inc vibracor,x ;Correction novibcor sta vibracnt,x lda #0 sta vibradir,x sta vibrafl,x sta vibrafh,x } snotvibrato jmp superdone superhigh !if INCLUDE_CMD_SET_OFFSET = TRUE { cmp #CMD_SET_OFFSET bne snotoffset lda cmd2,y sta shfreqhi,x lda cmd3,y sta shfreqlo,x jmp superdone snotoffset } !if INCLUDE_CMD_SET_ADSR = TRUE { cmp #CMD_SET_ADSR bne snotattdec lda cmd2,y sta ad,x lda cmd3,y sta sr,x jmp superdone snotattdec } !if INCLUDE_CMD_SET_LOVIB { cmp #CMD_SET_LOVIB bne snotlovib lda #4 sta effstate,x lda cmd2,y sta vibrafrq,x lsr ;; adc #0 sta vibracnt,x lda cmd3,y sta vibraamp,x lda #0 sta vibradir,x snotlovib } !if INCLUDE_CMD_SET_WAVE { cmp #CMD_SET_WAVE bne snotwave lda cmd3,y sta waveform,x snotwave } !if INCLUDE_CMD_PORTA { cmp #CMD_STOP bne snotstop lda #0 sta effstate,x snotstop } superdone ;;; ---------------------------------------- setsid ldy voice,x lda freqlo,x sta $d400,y lda freqhi,x sta $d401,y lda sr,x sta $d406,y lda ad,x sta $d405,y lda pulselo,x sta $d402,y lda pulsehi,x sta $d403,y lda waveform,x and gate,x sta $d404,y ;;; ---------------------------------------- !if MULTISPEED = TRUE { bit state bvc *+5 jmp next } ;; check tie & super lda tsync,x cmp #$ff beq postsync jmp skippostsync postsync dec tsync,x lda tienote,x bne tiednote jmp next tiednote lda shtrans,x ;check the note sta trans,x lda shnote,x beq tiestore cmp #3 bcc setgatestat clc adc trans,x sta notereal,x ldy effstate,x bmi tieclear lda #0 sta shfreqlo,x sta shfreqhi,x sta effstate,x skiptiefrq jmp tiestore setgatestat tay lda gatestat-1,y sta gate,x tieclear lda #0 tiestore sta tienote,x skippostsync ;--------------------------------------- next dex bmi maindone !if EXPORT = FALSE { bit state ; 7th bit, keyjam call bpl *+5 jmp updsound bvs *+5 ; 6th bit, multiplay call jmp main0 jmp syncskip } else { !if MULTISPEED = TRUE { bit state bvs *+5 jmp main0 jmp syncskip } else { jmp main0 } } maindone !if MULTISPEED = TRUE | EXPORT = TRUE { lda #0 sta state } ;;; ---------------------------------------- ;;; filter routine ;;; ---------------------------------------- ;;; feb '12: sweeps now in 10 bits res to allow faster sweeps ;;; ($80 in 10 bits corresponds to $20 in 8 bits) !if INCLUDE_FILTER = TRUE { dec filtcnt bpl filtnotnew lda filtnxt filtstart sta filtcur tay lda filttab,y ;byte A = duration or bandpass bpl filtsetcnt and #$70 sta bandpass lda filttab+1,y sta $d417 lda #0 filtsetcnt sta filtcnt lda filttab+1,y and #3 asl sta filtadd+1 lda filttab+1,y cmp #$80 ror cmp #$80 ror ; cmp #$80 ; ror sta filtadd filtjump lda filttab+3,y ; check jump value bne filtnotnxt lda filtnxt clc adc #4 jmp filtsetnxt filtnotnxt cmp #$7f bne filtnotstop lda #0 jmp filtsetnxt filtnotstop asl asl filtsetnxt sta filtnxt lda filttab+2,y cmp #$ff beq filtnotset sta filter lda #0 sta filtlo filtnotset jmp filterskip filtnotnew lda filtadd+1 clc adc filtlo cmp #8 and #7 sta filtlo lda filter adc filtadd sta filter filterskip lda filtlo sta $d415 lda filter sta $d416 } lda volume !if INCLUDE_FILTER = TRUE { ora bandpass } sta $d418 rts !if USE_MDRIVER = TRUE { cplay dec cntr bmi *+5 jmp submplay lda #MULTIPLIER sta cntr jmp subplay cinit ldx #0 stx cntr timerlo = *+1 ldx #CIA_VALUE sty $dc05 stx $dc04 jmp subinit cntr !8 0 } !if EXPORT = FALSE { dummy !8 0 } ;--------------------------------------- freqtable_lo !8 $16,$27,$38,$4b,$5f,$73 !8 $8a,$a1,$ba,$d4,$f0,$0e !8 $2d,$4e,$71,$96,$bd,$e7 !8 $13,$42,$74,$a9,$e0,$1b !8 $5a,$9b,$e2,$2c,$7b,$ce !8 $27,$85,$e8,$51,$c1,$37 !8 $b4,$37,$c4,$57,$f5,$9c !8 $4e,$09,$d0,$a3,$82,$6e !8 $68,$6e,$88,$af,$eb,$39 !8 $9c,$13,$a1,$46,$04,$dc !8 $d0,$dc,$10,$5e,$d6,$72 !8 $38,$26,$42,$8c,$08,$b8 !8 $a0,$b8,$20,$bc,$ac,$e4 !8 $70,$4c,$84,$18,$10,$70 !8 $40,$70,$40,$78,$58,$c8 !8 $e0,$98,$08,$30,$20,$2e freqtable_hi !8 $01,$01,$01,$01,$01,$01 !8 $01,$01,$01,$01,$01,$02 !8 $02,$02,$02,$02,$02,$02 !8 $03,$03,$03,$03,$03,$04 !8 $04,$04,$04,$05,$05,$05 !8 $06,$06,$06,$07,$07,$08 !8 $08,$09,$09,$0a,$0a,$0b !8 $0c,$0d,$0d,$0e,$0f,$10 !8 $11,$12,$13,$14,$15,$17 !8 $18,$1a,$1b,$1d,$1f,$20 !8 $22,$24,$27,$29,$2b,$2e !8 $31,$34,$37,$3a,$3e,$41 !8 $45,$49,$4e,$52,$57,$5c !8 $62,$68,$6e,$75,$7c,$83 !8 $8b,$93,$9c,$a5,$af,$b9 !8 $c4,$d0,$dd,$ea,$f8,$fd ;--------------------------------------- ;Registers voicon !8 1,1,1 ;flags channels on and off !if EXPORT = FALSE { editorflag !8 0 ; set to >0 from packer } state !8 0 bits !8 %00000001 !8 %00000010 !8 %00000100 gatestat !8 $fe,$ff voice !8 0,7,14 tracklo !8 0,0,0 ;track pointers low trackhi !8 0,0,0 ;track pointers hig twraplo !8 0,0,0 ;track wrap low twraphi !8 0,0,0 ;track wrap high speed !8 0 speedcnt !8 0 playspeed !8 0 !if INCLUDE_BREAKSPEED = TRUE { speedsub !8 0 } newseq !8 0,0,0 volume !8 $0f shtrans2 !8 0,0,0 clrfirst ;Clear variables from here ;;; ---------------------------------------- ;;; State variables ;;; ---------------------------------------- newinsflag !8 0,0,0 newcmdflag !8 0,0,0 hardon !fi 3,0 duration !8 0,0,0 durcnt !8 0,0,0 tsync !8 0,0,0 synccnt !8 0,0,0 tienote !8 0,0,0 notereal !8 0,0,0 effstate !8 0,0,0 ;; 0 = no effect ;; 1 = slide up ;; 2 = slide down ;; 3 = vibrato ;; 0x80 = portamento ;;; ---------------------------------------- ;;; Shadow variables ;;; ---------------------------------------- ;; bit 0 = instrument was set ;; bit 1 = cmd was set shtrans !8 0,0,0 shnote !8 0,0,0 shinst !8 0,0,0 shsuper !8 0,0,0 shad !8 0,0,0 shsr !8 0,0,0 shfreqlo !8 0,0,0 shfreqhi !8 0,0,0 freqlo !8 0,0,0 freqhi !8 0,0,0 trans !8 0,0,0 gate !8 0,0,0 ;Sequence curseq !8 0,0,0 seqcnt !8 0,0,0 ;Filter !if INCLUDE_FILTER = TRUE { bandpass !8 0 filter !8 0 filtcnt !8 0 filtcur !8 0 filtnxt !8 0 filtadd !8 0,0 filtlo !8 0 } ;Vibration variables !if INCLUDE_CMD_VIBR = TRUE | INCLUDE_CMD_SET_LOVIB = TRUE { vibracnt !8 0,0,0 ;Count vibradir !8 0,0,0 ;Direction vibraamp !8 0,0,0 ;Amplitude vibrafrq !8 0,0,0 ;Frequency } !if INCLUDE_CMD_VIBR = TRUE { vibracor !8 0,0,0 ;Tune correction vibrafl !8 0,0,0 ;Vibrato feel low vibrafh !8 0,0,0 ;Vibrato feel high vibraflv !8 0,0,0 ;Vibrato feel add } ;Slide variables !if INCLUDE_CMD_SLUP = TRUE | INCLUDE_CMD_SLDOWN = TRUE { slidelo !8 0,0,0 ;Low fraction slidehi !8 0,0,0 ;High fraction } ;Pulse pulsecur !8 0,0,0 pulsenxt !8 0,0,0 pulsecnt !8 0,0,0 pulselo !8 0,0,0 ;-->d402 pulsehi !8 0,0,0 ;-->d403 ;ADSR ad !8 0,0,0 ;-->d405 sr !8 0,0,0 ;-->d406 ;Waveform waveform !8 0,0,0 ;-->d404 ;Wavetable wavetrans !8 0,0,0 wavecnt !8 0,0,0 wavepos !8 0,0,0 wavetime !8 0,0,0 !if INCLUDE_CHORD = TRUE { chordtpos !8 0,0,0 chordvalue !8 0,0,0 } ;Portamento !if INCLUDE_CMD_PORTA = TRUE { portahi !8 0,0,0 portalo !8 0,0,0 plo !8 0,0,0 phi !8 0,0,0 } clrlast ;Clear variables to here !if EXPORT = FALSE { *=$2000 ;--------------------------------------- songsets !16 track1,track2,track3 !8 5,7 ;--------------------------------------- *= songsets + $200 track1 !8 $a0,$00,$f0,0 !for .v, $1fe { !8 $f0,00 } *= track1+$0400 track2 !8 $a0,$00,$f0,0 !for .v, $1fe { !8 $f0,00 } *= track2+$0400 track3 !8 $a0,$00,$f0,0 !for .v, $1fe { !8 $f0,00 } ;--------------------------------------- *= track3 + $400 seqlo !fi 128, s0+((.v-1)*256) } ;--------------------------------------- *= seqlo+$0100 !macro emptyseq { !8 $f0,$f0,$60,$00 !8 $bf } s0 +emptyseq !set curPC = s0 !for .v, 128-1 { *= curPC + $100 !set curPC = * +emptyseq } ;--------------------------------------- *= curPC + $100 arp1 !8 0 ;--------------------------------------- *= arp1+$0100 arp2 !8 0 ;--------------------------------------- *= arp2+$0100 inst !fi 48*8,0 ;;; (more or less) dynamic tables follow...... *= inst+$0200 supertab cmd1 !8 $00 *= cmd1+$40 cmd2 !8 $0f *= cmd2+$40 cmd3 !8 $00 *= cmd3+$40 ;--------------------------------------- ;--------------------------------------- *= supertab+$0100 filttab !8 $7f,$00,$ff,$7f ;--------------------------------------- *= filttab+$0100 pulstab !8 $7f,$00,$ff,$7f *= pulstab+$0100 chord !fi 128,0 chordindex !fi 32,0 } CheeseCutter-master/src/com/000077500000000000000000000000001357241101300162745ustar00rootroot00000000000000CheeseCutter-master/src/com/cpu.d000066400000000000000000000511601357241101300172330ustar00rootroot00000000000000/* CheeseCutter v2 (C) Abaddon. Licensed under GNU GPL. */ module com.cpu; import std.stdio; import std.string; alias ushort address; ubyte highbyte(ushort value) { return value >> 8; } ubyte lowbyte(ushort value) { return value & 255; } address toAddress(ubyte[] arr) { return arr[0] | (arr[1] << 8); } ubyte[] toArr(address addr) { return [lowbyte(addr), highbyte(addr)]; } alias toArr addr2arr; class CPU { protected: enum St { C = 1, Z = 2, I = 4, D = 8, B = 16, V = 64, N = 128 }; enum Am { IMPLIED, IMMEDIATE, INDIRECT_X, INDIRECT_Y, IND, Z, RELATIVE, ACC, ABSOLUTE, ABSOLUTE_X, ABSOLUTE_Y, ZEROPAGE_X, ZY }; static immutable int[] OPSIZE = [ 0, 1, 1, 1, 2, 1, 1, 0, 2, 2, 2, 1, 1 ]; static string[] AMSTR = [ " \t", " \t#$", "(,x)\t$", "(),y\t$", "() \t$", " \t$", " \t+-", " \ta", " \t$", ",x \t$", ",y \t$", ",xZ \t$", ",yZ \t$" ]; enum Op { BRK = 0, ADC, AND, ASL, EOR, ORA, LSR, JSR, JMP, BIT, ROL, PHP, PLP, PHA, RTI, BVC, CLI, RTS, ROR, PLA, BVS, SEI, STA, STY, STX, DEY, TXA, BCC, TYA, TXS, LDY, LDA, LDX, TAY, TAX, BCS, CLV, TSX, CPY, CMP, DEC, INY, DEX, BNE, CLD, CPX, SBC, INC, INX, NOP, BEQ, SED, BPL, BMI, SEC, CLC }; static string[] OPSTR = [ "BRK", "ADC", "AND", "ASL", "EOR", "ORA", "LSR", "JSR", "JMP", "BIT", "ROL", "PHP", "PLP", "PHA", "RTI", "BVC", "CLI", "RTS", "ROR", "PLA", "BVS", "SEI", "STA", "STY", "STX", "DEY", "TXA", "BCC", "TYA", "TXS", "LDY", "LDA", "LDX", "TAY", "TAX", "BCS", "CLV", "TSX", "CPY", "CMP", "DEC", "INY", "DEX", "BNE", "CLD", "CPX", "SBC", "INC", "INX", "NOP", "BEQ", "SED", "BPL", "BMI", "SEC", "CLC" ]; struct Opcode { Op op; Am am; int cyc; } static immutable Opcode[256] OPTAB = [ { Op.BRK, Am.IMPLIED, 8 }, { Op.ORA, Am.INDIRECT_X, 6 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.ORA, Am.Z , 3 }, { Op.ASL, Am.Z , 5 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.PHP, Am.IMPLIED, 3 }, { Op.ORA, Am.IMMEDIATE, 2 }, { Op.ASL, Am.ACC, 2 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.ORA, Am.ABSOLUTE , 4 }, { Op.ASL, Am.ABSOLUTE , 6 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.BPL, Am.RELATIVE, 2 }, { Op.ORA, Am.INDIRECT_Y, 5 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.ORA, Am.ZEROPAGE_X , 4 }, { Op.ASL, Am.ZEROPAGE_X , 6 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.CLC, Am.IMPLIED, 2 }, { Op.ORA, Am.ABSOLUTE_Y , 4 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.ORA, Am.ABSOLUTE_X , 4 }, { Op.ASL, Am.ABSOLUTE_X , 7 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.JSR, Am.ABSOLUTE , 6 }, { Op.AND, Am.INDIRECT_X, 6 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.BIT, Am.Z , 3 }, { Op.AND, Am.Z , 3 }, { Op.ROL, Am.Z , 3 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.PLP, Am.IMPLIED, 4 }, { Op.AND, Am.IMMEDIATE, 2 }, { Op.ROL, Am.ACC, 2 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.BIT, Am.ABSOLUTE , 4 }, { Op.AND, Am.ABSOLUTE , 4 }, { Op.ROL, Am.ABSOLUTE , 4 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.BMI, Am.RELATIVE, 2 }, { Op.AND, Am.INDIRECT_Y, 5 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.AND, Am.ZEROPAGE_X , 4 }, { Op.ROL, Am.ZEROPAGE_X , 6 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.SEC, Am.IMPLIED, 2 }, { Op.AND, Am.ABSOLUTE_Y , 4 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.AND, Am.ABSOLUTE_X , 4 }, { Op.ROL, Am.ABSOLUTE_X , 7 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.RTI, Am.IMPLIED, 7 }, { Op.EOR, Am.INDIRECT_X, 6 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.EOR, Am.Z , 3 }, { Op.LSR, Am.Z , 5 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.PHA, Am.IMPLIED, 3 }, { Op.EOR, Am.IMMEDIATE, 2 }, { Op.LSR, Am.ACC, 2 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.JMP, Am.ABSOLUTE , 3 }, { Op.EOR, Am.ABSOLUTE , 4 }, { Op.LSR, Am.ABSOLUTE , 6 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.BVC, Am.RELATIVE, 2 }, { Op.EOR, Am.INDIRECT_Y, 5 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.EOR, Am.ZEROPAGE_X , 4 }, { Op.LSR, Am.ZEROPAGE_X , 6 }, { Op.BRK, Am.IMPLIED, 4 }, { Op.CLI, Am.IMPLIED, 2 }, { Op.EOR, Am.ABSOLUTE_Y , 4 }, { Op.BRK, Am.IMPLIED, 4 }, { Op.BRK, Am.IMPLIED, 4 }, { Op.BRK, Am.IMPLIED, 4 }, { Op.EOR, Am.ABSOLUTE_X , 4 }, { Op.LSR, Am.ABSOLUTE_X , 7 }, { Op.BRK, Am.IMPLIED, 4 }, { Op.RTS, Am.IMPLIED, 6 }, { Op.ADC, Am.ZEROPAGE_X , 6 }, { Op.BRK, Am.IMPLIED, 4 }, { Op.BRK, Am.IMPLIED, 4 }, { Op.BRK, Am.IMPLIED, 4 }, { Op.ADC, Am.Z , 3 }, { Op.ROR, Am.Z , 5 }, { Op.BRK, Am.IMPLIED, 4 }, { Op.PLA, Am.IMPLIED, 4 }, { Op.ADC, Am.IMMEDIATE, 2 }, { Op.ROR, Am.ACC, 2 }, { Op.BRK, Am.IMPLIED, 4 }, { Op.JMP, Am.IND, 5 }, { Op.ADC, Am.ABSOLUTE , 4 }, { Op.ROR, Am.ABSOLUTE , 6 }, { Op.BRK, Am.IMPLIED, 4 }, { Op.BVS, Am.RELATIVE, 2 }, { Op.ADC, Am.ZY , 5 }, { Op.BRK, Am.IMPLIED, 4 }, { Op.BRK, Am.IMPLIED, 4 }, { Op.BRK, Am.IMPLIED, 4 }, { Op.ADC, Am.ZEROPAGE_X , 4 }, { Op.ROR, Am.ZEROPAGE_X , 6 }, { Op.BRK, Am.IMPLIED, 4 }, { Op.SEI, Am.IMPLIED, 2 }, { Op.ADC, Am.ABSOLUTE_Y , 4 }, { Op.BRK, Am.IMPLIED, 4 }, { Op.BRK, Am.IMPLIED, 4 }, { Op.BRK, Am.IMPLIED, 4 }, { Op.ADC, Am.ABSOLUTE_X , 4 }, { Op.ROR, Am.ABSOLUTE_X , 7 }, { Op.BRK, Am.IMPLIED, 4 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.STA, Am.INDIRECT_X, 6 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.STY, Am.Z , 3 }, { Op.STA, Am.Z , 3 }, { Op.STX, Am.Z , 3 }, { Op.BRK, Am.IMPLIED, 4 }, { Op.DEY, Am.IMPLIED, 2 }, { Op.BRK, Am.IMPLIED, 4 }, { Op.TXA, Am.IMPLIED, 2 }, { Op.BRK, Am.IMPLIED, 4 }, { Op.STY, Am.ABSOLUTE , 4 }, { Op.STA, Am.ABSOLUTE , 4 }, { Op.STX, Am.ABSOLUTE , 4 }, { Op.BRK, Am.IMPLIED, 4 }, { Op.BCC, Am.RELATIVE, 4 }, { Op.STA, Am.INDIRECT_Y, 4 }, { Op.BRK, Am.IMPLIED, 4 }, { Op.BRK, Am.IMPLIED, 4 }, { Op.STY, Am.ZEROPAGE_X , 4 }, { Op.STA, Am.ZEROPAGE_X , 4 }, { Op.STX, Am.ZY , 4 }, { Op.BRK, Am.IMPLIED, 4 }, { Op.TYA, Am.IMPLIED, 2 }, { Op.STA, Am.ABSOLUTE_Y , 5 }, { Op.TXS, Am.IMPLIED, 2 }, { Op.BRK, Am.IMPLIED, 4 }, { Op.BRK, Am.IMPLIED, 4 }, { Op.STA, Am.ABSOLUTE_X , 5 }, { Op.BRK, Am.IMPLIED, 4 }, { Op.BRK, Am.IMPLIED, 4 }, { Op.LDY, Am.IMMEDIATE, 2 }, { Op.LDA, Am.INDIRECT_X, 6 }, { Op.LDX, Am.IMMEDIATE, 2 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.LDY, Am.Z , 3 }, { Op.LDA, Am.Z , 3 }, { Op.LDX, Am.Z , 3 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.TAY, Am.IMPLIED, 2 }, { Op.LDA, Am.IMMEDIATE, 2 }, { Op.TAX, Am.IMPLIED, 2 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.LDY, Am.ABSOLUTE , 4 }, { Op.LDA, Am.ABSOLUTE , 4 }, { Op.LDX, Am.ABSOLUTE , 4 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.BCS, Am.RELATIVE, 2 }, { Op.LDA, Am.INDIRECT_Y, 5 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.LDY, Am.ZEROPAGE_X , 4 }, { Op.LDA, Am.ZEROPAGE_X , 4 }, { Op.LDX, Am.ZEROPAGE_X , 4 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.CLV, Am.IMPLIED, 2 }, { Op.LDA, Am.ABSOLUTE_Y , 4 }, { Op.TSX, Am.IMPLIED, 2 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.LDY, Am.ABSOLUTE_X , 4 }, { Op.LDA, Am.ABSOLUTE_X , 4 }, { Op.LDX, Am.ABSOLUTE_Y , 4 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.CPY, Am.IMMEDIATE, 2 }, { Op.CMP, Am.INDIRECT_X, 6 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.CPY, Am.Z , 3 }, { Op.CMP, Am.Z , 3 }, { Op.DEC, Am.Z , 5 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.INY, Am.IMPLIED, 2 }, { Op.CMP, Am.IMMEDIATE, 2 }, { Op.DEX, Am.IMPLIED, 2 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.CPY, Am.ABSOLUTE , 4 }, { Op.CMP, Am.ABSOLUTE , 4 }, { Op.DEC, Am.ABSOLUTE , 4 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.BNE, Am.RELATIVE, 2 }, { Op.CMP, Am.INDIRECT_Y, 5 }, { Op.BRK, Am.IMPLIED, 4 }, { Op.BRK, Am.IMPLIED, 4 }, { Op.BRK, Am.IMPLIED, 4 }, { Op.CMP, Am.ZEROPAGE_X , 4 }, { Op.DEC, Am.ZEROPAGE_X , 6 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.CLD, Am.IMPLIED, 2 }, { Op.CMP, Am.ABSOLUTE_Y , 4 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.CMP, Am.ABSOLUTE_X , 4 }, { Op.DEC, Am.ABSOLUTE_X , 7 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.CPX, Am.IMMEDIATE, 2 }, { Op.SBC, Am.INDIRECT_X, 6 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.CPX, Am.Z , 3 }, { Op.SBC, Am.Z , 3 }, { Op.INC, Am.Z , 5 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.INX, Am.IMPLIED, 2 }, { Op.SBC, Am.IMMEDIATE, 2 }, { Op.NOP, Am.IMPLIED, 2 }, { Op.SBC, Am.IMMEDIATE, 2 }, { Op.CPX, Am.ABSOLUTE , 4 }, { Op.SBC, Am.ABSOLUTE , 4 }, { Op.INC, Am.ABSOLUTE , 6 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.BEQ, Am.RELATIVE, 2 }, { Op.SBC, Am.INDIRECT_Y, 5 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.SBC, Am.ZEROPAGE_X , 4 }, { Op.INC, Am.ZEROPAGE_X , 6 }, { Op.BRK, Am.IMPLIED, 0 }, { Op.SED, Am.IMPLIED, 2 }, { Op.SBC, Am.ABSOLUTE_Y , 4 }, { Op.BRK, Am.IMPLIED, 4 }, { Op.BRK, Am.IMPLIED, 4 }, { Op.BRK, Am.IMPLIED, 4 }, { Op.SBC, Am.ABSOLUTE_X , 4 }, { Op.INC, Am.ABSOLUTE_X , 7 }, { Op.BRK, Am.IMPLIED, 2 } ]; struct State { int opcode, realop, addrmode, arg, value, cyc; ubyte[] chunk; } struct Regs { ubyte a, x, y, st, sp; address pc; } int counter; ubyte[] memory; public: Regs regs; this(ubyte[] m) { reset(); memory = m; } void reset() { regs.a = regs.x = regs.y = 0; regs.sp = 255; regs.st = 32; } // execute a 6502 subroutine, return number of cycles used int execute(ushort addr) { return execute(addr, false); } int execute(ushort addr, bool d) { stPush(0); stPush(0); regs.pc = addr; counter = 0; while(regs.pc > 0 && !(regs.st & St.B)) { run(d); } return counter; } protected: /* execute a 6502 instruction * d indicates that ML monitor output is required * returns the number of cycles */ int run(bool d) { string s; address pc; State state; state = decode(); if(regs.pc >= 0xfffd) throw new CPUException(this, "program counter overflow!"); int oldpc = regs.pc; executeOp(state); counter += state.cyc; if(d) { int addrmode, arg, value, opcode; opcode = state.opcode; addrmode = state.addrmode; arg = state.arg; value = state.value; s = dumpRegs(); if(OPSIZE[addrmode] == 0) { writefln(format("$%04x\t$%02X\t%s\t\t\t\t%s c=%x C=$%04X", oldpc, state.realop, OPSTR[opcode], s, state.cyc, counter)); } else { writefln(format("$%04x\t$%02X\t%s%s%02x\t\t\t%s c=%x C=$%04X", oldpc, state.realop, OPSTR[opcode], AMSTR[addrmode], arg, s, state.cyc, counter)); } } if(regs.st & St.B) return state.cyc; return state.cyc; } void dumpOpcode(ref State state) { int addrmode, arg, value, opcode; opcode = state.opcode; addrmode = state.addrmode; arg = state.arg; value = state.value; string s = dumpRegs(); if(OPSIZE[addrmode] == 0) { writefln(format("$%04x\t$%02X\t%s\t\t\t\t%s c=%x C=$%04X", regs.pc, state.realop, OPSTR[opcode], s, state.cyc, counter)); } else { writefln(format("$%04x\t$%02X\t%s%s%02x\t\t\t%s c=%x C=$%04X", regs.pc, state.realop, OPSTR[opcode], AMSTR[addrmode], arg, s, state.cyc, counter)); } } void dumpline(ref State state) { } string dumpRegs() { return format("PC=$%04x A=$%02x X=$%02x Y=$%02x SP=$%02x ST=$%02x" , regs.pc, regs.a, regs.x,regs.y,regs.sp,regs.st); } void setST(ubyte value) { regs.st &= (255 - St.N - St.Z); regs.st |= value & St.N; if (!value) regs.st |= St.Z; } void regWrite(ref ubyte reg, ushort value) { reg = cast(ubyte)value; setST(cast(ubyte)value); } void regWrite(ref ubyte reg, ubyte value) { reg = value; setST(value); } alias regWrite set; void stPush(ubyte val) { memory[0x100 + regs.sp] = val; regs.sp--; } ubyte stPull() { regs.sp++; return memory[0x100 + regs.sp]; } /* prints cpu status and a message from player * message format: * [info byte] [data....] * info byte: $00-$7f number of bytes to dump/string length * 8th bit ON = output string, else output bytes */ void handleBreak() { /+ fprintf(stdout, toStringz(dumpRegs() ~ " ( ")); int info = memory[0xdf00]; if(info) { for(int i=0; i < (info & 0x7f); i++) { if(!(info & 0x80)) { fprintf(stdout,"$%02x ", memory[0xdf01 + i]); } } } fprintf(stdout, ") "); if(!(info & 0x80)) fprintf(stdout,"\n"); +/ throw new CPUException(this, "BRK"); } void executeOp(ref State stat) { int arg = stat.arg; ushort value = cast(ushort)stat.value; int acc; int am = stat.addrmode; int p = regs.pc; regs.pc += 1 + OPSIZE[stat.addrmode]; switch(stat.opcode) { case Op.BRK: handleBreak(); regs.st |= St.B; break; case Op.SEI: regs.st |= St.I; break; case Op.CLI: regs.st &= 255 - St.I; break; case Op.CLC: regs.st &= 255 - St.C; break; case Op.SEC: regs.st |= St.C; break; case Op.CLV: regs.st &= 255 - St.V; break; case Op.SED: regs.st |= St.D; throw new CPUException(this,"Decimal mode not supported"); case Op.CLD: regs.st &= 255 - St.D; break; case Op.LDA: set(regs.a, value); break; case Op.LDX: set(regs.x, value); break; case Op.LDY: set(regs.y, value); break; case Op.INX: set(regs.x, (regs.x + 1) & 255); break; case Op.INY: set(regs.y, (regs.y + 1) & 255); break; case Op.DEX: set(regs.x, (regs.x - 1) & 255); break; case Op.DEY: set(regs.y, (regs.y - 1) & 255); break; case Op.TAX: set(regs.x, regs.a); break; case Op.TXA: set(regs.a, regs.x); break; case Op.TAY: set(regs.y, regs.a); break; case Op.TYA: set(regs.a, regs.y); break; case Op.PHA: stPush(regs.a); break; case Op.PLA: set(regs.a, stPull()); break; case Op.PHP: stPush(regs.st); break; case Op.PLP: regs.st = stPull(); break; case Op.TSX: set(regs.x,regs.sp); break; case Op.TXS: regs.sp = regs.x; break; case Op.STA: write(stat, am, arg, regs.a); break; case Op.STX: write(stat, am, arg, regs.x); break; case Op.STY: write(stat, am, arg, regs.y); break; case Op.BIT: ubyte st; st = regs.st; st &= 0xff - St.N - St.V - St.Z; st |= value & 0xc0; if (!regs.a & value) st |= St.Z; regs.st = st; break; case Op.BEQ: if (regs.st & St.Z) { regs.pc = value; stat.cyc++; } break; case Op.BNE: if (!(regs.st & St.Z)) { regs.pc = value; stat.cyc++; } break; case Op.BPL: if (!(regs.st & St.N)) { regs.pc = value; stat.cyc++; } break; case Op.BMI: if (regs.st & St.N) { regs.pc = value; stat.cyc++; } break; case Op.BCC: if (!(regs.st & St.C)) { regs.pc = value; stat.cyc++; } break; case Op.BCS: if (regs.st & St.C) { regs.pc = value; stat.cyc++; } break; case Op.BVC: if (!(regs.st & St.V)) { regs.pc = value; stat.cyc++; } break; case Op.BVS: if (regs.st & St.V) { regs.pc = value; stat.cyc++; } break; case Op.JMP: if (am == Am.IND) regs.pc = value; else regs.pc = cast(ushort)arg; break; case Op.JSR: int pc = regs.pc; stPush(cast(ubyte)(pc >> 8)); // wrong byte order? stPush(cast(ubyte)(pc & 255)); regs.pc = cast(ushort)arg; break; case Op.RTS: regs.pc = (stPull())| (stPull() << 8); break; case Op.RTI: // need to change "I" flag? regs.st = stPull(); regs.pc = (stPull() << 8) | stPull(); break; case Op.ASL: acc = value << 1; regs.st &= 255 - St.C; regs.st |= (acc >> 8) & St.C; setST(acc & 255); write(stat, am,arg,acc &255); break; case Op.LSR: acc = value; regs.st &= 255 - St.C; regs.st |= acc & St.C; acc = acc >> 1; setST(acc & 255); write(stat,am,arg,acc & 255); break; case Op.ROL: acc = value << 1; acc |= regs.st & St.C; regs.st &= 255 - St.C; regs.st |= (acc >> 8) & St.C; setST(acc & 255); write(stat,am,arg,acc & 255); break; case Op.ROR: ubyte st; acc = value; st = regs.st; regs.st &= 255 - St.C; regs.st |= acc & St.C; acc = acc >> 1; acc |= (st & St.C) << 7; setST(acc & 255); write(stat,am,arg,acc & 255); break; case Op.ADC: int t; t = regs.a + (regs.st & St.C) + value; regs.st &= 255 - St.C; regs.st |= ((t >> 8) & St.C); set(regs.a,t & 255); break; case Op.SBC: int t; t = regs.a - value - !(regs.st & St.C); regs.st &= 255 - St.C; //regs.st |= value > regs.a ? 0 : St.C; regs.st |= t < 0 ? 0 : St.C; set(regs.a,t & 255); break; case Op.CMP: int t; t = regs.a - value; regs.st &= 255 - St.C; //regs.st |= value > regs.a ? 0 : St.C; regs.st |= t < 0 ? 0 : St.C; setST(t & 255); break; case Op.CPX: int t; t = regs.x - value; regs.st &= 255 - St.C; //regs.st |= value > regs.x ? 0 : St.C; regs.st |= t < 0 ? 0 : St.C; setST(t & 255); break; case Op.CPY: int t; t = regs.y - value; regs.st &= 255 - St.C; regs.st |= value > regs.y ? 0 : St.C; //regs.st |= value > regs.y ? 0 : St.C; regs.st |= t < 0 ? 0 : St.C; setST(t & 255); break; case Op.INC: write(stat,am,arg,(value + 1) & 255); setST(cast(ubyte)(value+1)); break; case Op.DEC: write(stat,am,arg,(value - 1) & 255); setST(cast(ubyte)(value-1)); break; case Op.AND: ubyte t; t = regs.a & value; set(regs.a,t); break; case Op.EOR: acc = regs.a ^ value; set(regs.a,acc & 255); break; case Op.ORA: acc = regs.a | value; set(regs.a,acc & 255); break; case Op.NOP: break; default: throw new CPUException(this,"Illegal instruction"); } } address fetchAddress(ref State st) { int am = st.addrmode; ushort arg = cast(ushort)st.arg; switch(am) { case Am.ABSOLUTE_X: return (arg + regs.x) & 65535; case Am.ZY, Am.ABSOLUTE_Y: return (arg + regs.y) & 65535; case Am.ZEROPAGE_X: return (arg + regs.x) & 255; case Am.Z: return arg & 255; case Am.ABSOLUTE: return arg; case Am.INDIRECT_Y: return cast(address)(toAddress(memory[(arg & 0xff) .. (arg & 0xff) + 2]) + regs.y); default: throw new CPUException(this,format("Illegal addressing mode %d", am)); } assert(0); } ushort fetch(ref State st) { int am = st.addrmode; ubyte arg = cast(ubyte)st.arg; switch(am) { case Am.IMPLIED: return 0; case Am.IMMEDIATE: return arg; case Am.ABSOLUTE_X, Am.ZY, Am.ABSOLUTE_Y, Am.ZEROPAGE_X, Am.Z, Am.ABSOLUTE, Am.INDIRECT_Y: return memory[fetchAddress(st)]; case Am.ACC: return regs.a; case Am.RELATIVE: return cast(ushort)(regs.pc + (arg >= 128 ? -256 + arg : arg) + 2); case Am.INDIRECT_X: throw new CPUException(this,"(indexed,x) not implemented"); default: throw new CPUException(this,format("Illegal addressing mode %d", am)); } assert(0); } State decode() { static State st; Opcode ops; st.chunk = memory[regs.pc .. regs.pc + 3]; ops = OPTAB[st.chunk[0]]; st.realop = st.chunk[0]; st.opcode = cast(int)ops.op; st.addrmode = cast(int)ops.am; st.cyc = cast(int)ops.cyc; st.arg = 0; if(OPSIZE[st.addrmode] == 1) { st.arg = st.chunk[1]; } else if(OPSIZE[st.addrmode] == 2) { st.arg = st.chunk[1] | (st.chunk[2] << 8); } st.value = fetch(st); return st; } void write(ref State stat, int am, int arg, ubyte val) { switch(am) { case Am.Z: case Am.ZEROPAGE_X: case Am.ABSOLUTE: case Am.ABSOLUTE_X: case Am.ABSOLUTE_Y: case Am.INDIRECT_Y: memory[fetchAddress(stat)] = val; return; case Am.ACC: regs.a = val; break; case Am.INDIRECT_X: throw new CPUException(this,"(indexed,x) not implemented"); default: throw new CPUException(this,format("Unsupported addrmode %d",am)); } } } class CPUException : Exception { CPU cpu; this(CPU cpu, string msg) { super("CPU error: " ~ msg ~ " (" ~ cpu.dumpRegs() ~ ")"); this.cpu = cpu; } override string toString() { return msg; } } CheeseCutter-master/src/com/fb.d000066400000000000000000000334051357241101300170350ustar00rootroot00000000000000/* CheeseCutter v2 (C) Abaddon. Licensed under GNU GPL. */ module com.fb; import derelict.sdl.sdl; import std.string : indexOf; import com.util; immutable SDL_Color[] PALETTE = [ { 0,0,0 }, { 63 << 2,63 << 2,63 << 2 }, { 26 << 2,13 << 2,10 << 2 }, { 28 << 2,41 << 2,44 << 2 }, { 27 << 2,15 << 2,33 << 2 }, { 22 << 2,35 << 2,16 << 2 }, { 13 << 2,10 << 2,30 << 2 }, { 46 << 2,49 << 2,27 << 2 }, { 27 << 2,19 << 2,9 << 2 }, { 16 << 2,14 << 2,0 << 2 }, { 38 << 2,25 << 2,22 << 2 }, { 17 << 2,17 << 2,17 << 2 }, { 27 << 2,27 << 2,27 << 2 }, { 38 << 2,52 << 2,33 << 2 }, { 27 << 2,23 << 2,45 << 2 }, { 37 << 2,37 << 2,37 << 2 } ]; immutable FONT_X = 8, FONT_Y = 14; __gshared ubyte[] font; immutable int mode, border = 1; private bool isDirty = false; immutable CHECKX = "assert(x >= 0 && x < width);"; immutable CHECKY = "assert(y >= 0 && y < height);"; immutable CHECKS = "assert(x + y >= 0 && x + y < width*height);"; static this() { void[] arr; font.length = 256*16; // realign font data immutable rawfont = import("font.psf"); for(int i=0;i<256;i++) { font[i*16..i*16+14] = cast(ubyte[])rawfont[i*FONT_Y+4..i*FONT_Y+4+FONT_Y]; } } abstract class Video { protected { SDL_Surface* surface; bool useFullscreen; Screen screen; Visualizer vis; const int requestedWidth, requestedHeight; int height, width; // resolution of window int displayHeight, displayWidth; // resolution of the monitor SDL_Rect rect; } this(int wx, int wy, Screen scr, int fs) { const SDL_VideoInfo* vidinfo = SDL_GetVideoInfo(); screen = scr; displayHeight = vidinfo.current_h; displayWidth = vidinfo.current_w; requestedHeight = wy; requestedWidth = wx; } ~this() { if(surface !is null) SDL_FreeSurface(surface); } abstract void drawVisualizer(int); abstract void clearVisualizer(); abstract protected void enableFullscreen(bool fs); void resizeEvent(int nw, int nh) { } void toggleFullscreen() { useFullscreen ^= 1; enableFullscreen(useFullscreen); } void scalePosition(ref int x, ref int y) { x -= rect.x; y -= rect.y; x *= cast(float)requestedWidth / width; y *= cast(float)requestedHeight / height; } abstract void updateFrame(); } class VideoStandard : Video { this(int wx, int wy, Screen scr, int fs) { super(wx, wy, scr, fs); enableFullscreen(fs > 0); } override protected void enableFullscreen(bool fs) { width = requestedWidth; height = requestedHeight; useFullscreen = fs; int sdlflags = SDL_SWSURFACE; sdlflags |= fs ? SDL_FULLSCREEN : 0; surface = SDL_SetVideoMode(width, height, 0, sdlflags); if(surface is null) { throw new DisplayError("Unable to initialize graphics mode."); } SDL_SetPalette(surface, SDL_PHYSPAL|SDL_LOGPAL, cast(SDL_Color *)PALETTE, 0, 16); vis = new Oscilloscope(surface, 500, 14); screen.refresh(); } override void drawVisualizer(int n) { SDL_LockSurface(surface); vis.draw(n); SDL_UnlockSurface(surface); } override void clearVisualizer() { SDL_LockSurface(surface); vis.clear(); SDL_UnlockSurface(surface); } override void updateFrame() { int x, y; int a,b,c; Uint16* bptr = &screen.data[0]; Uint16* cptr = &screen.olddata[0]; Uint32* sptr = cast(Uint32 *)surface.pixels; Uint32* sp; Uint8* bp; Uint8 ubg, ufg; if (!isDirty) return; isDirty = false; SDL_LockSurface(surface); for(y = 0;y < screen.height; y++) { for(x = 0; x < screen.width; x++) { if(*bptr != *cptr) { *cptr = *bptr; sp = sptr; a = *bptr & 255; bp = &font[a * 16]; ufg = (*bptr >> 8) & 15; ubg = (*bptr >> 12); auto fgcolor = getColor(surface, ufg), bgcolor = getColor(surface, ubg); for(c = 4; c < 18; c++, bp++) { b = *bp; if(b & 0x80) *(sp++) = fgcolor; else *(sp++) = bgcolor; if(b & 0x40) *(sp++) = fgcolor; else *(sp++) = bgcolor; if(b & 0x20) *(sp++) = fgcolor; else *(sp++) = bgcolor; if(b & 0x10) *(sp++) = fgcolor; else *(sp++) = bgcolor; if(b & 0x08) *(sp++) = fgcolor; else *(sp++) = bgcolor; if(b & 0x04) *(sp++) = fgcolor; else *(sp++) = bgcolor; if(b & 0x02) *(sp++) = fgcolor; else *(sp++) = bgcolor; if(b & 0x01) *(sp++) = fgcolor; else *(sp++) = bgcolor; sp += width - 8; } } sptr += 8; bptr++; cptr++; } sptr += width*13; } SDL_UnlockSurface(surface); SDL_Flip(surface); } } class VideoYUV : Video { private SDL_Overlay* overlay; private int correctedHeight, correctedWidth; this(int wx, int wy, Screen scr, int fs) { super(wx, wy, scr, fs); calcAspect(); enableFullscreen(fs > 0); } ~this() { if(overlay !is null) SDL_FreeYUVOverlay(overlay); } private void calcAspect() { correctedHeight = displayHeight; correctedWidth = displayWidth; if(cast(float)displayHeight / displayWidth < 0.75) { // wide screen correctedWidth = cast(int)(correctedHeight / 0.75); correctedHeight = displayHeight; } else { correctedWidth = displayWidth; correctedHeight = cast(int)(correctedWidth * 0.75); } } override void drawVisualizer(int n) { SDL_LockSurface(surface); vis.draw(n); SDL_UnlockSurface(surface); } override void clearVisualizer() { SDL_LockSurface(surface); vis.clear(); SDL_UnlockSurface(surface); } override void resizeEvent(int nw, int nh) { if(useFullscreen) return; width = nw; height = nh; if(surface !is null) SDL_FreeSurface(surface); surface = SDL_SetVideoMode(nw, nh, 0, SDL_SWSURFACE | SDL_RESIZABLE); if(surface is null) { throw new DisplayError("Unable to initialize graphics mode."); } createOverlay(nw, nh); screen.refresh(); } override protected void enableFullscreen(bool fs) { if(fs) { // enable aspect corr. if in fullscreen width = correctedWidth; height = correctedHeight; } else { width = requestedWidth; height = requestedHeight; } int sdlflags = SDL_SWSURFACE; useFullscreen = fs; sdlflags |= fs ? SDL_FULLSCREEN : SDL_RESIZABLE; if(!fs) surface = SDL_SetVideoMode(requestedWidth, requestedHeight, 0, sdlflags); else surface = SDL_SetVideoMode(displayWidth, displayHeight, 0, sdlflags); if(surface is null) { throw new DisplayError("Unable to initialize graphics mode."); } vis = new Oscilloscope(surface, 500, 14); SDL_SetPalette(surface, SDL_PHYSPAL|SDL_LOGPAL, cast(SDL_Color *)PALETTE, 0, 16); createOverlay(width, height); screen.refresh(); } override void updateFrame() { int x, y; int a,b,c; static Uint32[32] pixbuf; Uint16* bptr = &screen.data[0]; Uint16* cptr = &screen.olddata[0]; Uint32* sp; Uint8* bp; Uint8 ubg, ufg; if (!isDirty) return; isDirty = false; SDL_LockYUVOverlay(overlay); // clear bottom stripe if necessary (mode = 800x600) /+if(video.resolution == Resolution.Res800x600)+/ { pixbuf[] = 0; for(x = 0; x < screen.width; x++) { for(y = 0; y < 12; y++) { RGBBlock2YUV(pixbuf, x * 8, screen.height * 14 + y); } } } for(y = 0;y < screen.height; y++) { for(x = 0; x < screen.width; x++) { if(*bptr != *cptr) { *cptr = *bptr; a = *bptr & 255; bp = &font[a * 16]; ufg = (*bptr >> 8) & 15; ubg = (*bptr >> 12); auto fgcolor = getColor(surface, ufg), bgcolor = getColor(surface, ubg); for(c = 4; c < 18; c++, bp++) { sp = &pixbuf[0]; b = *bp; if(b & 0x80) *(sp++) = fgcolor; else *(sp++) = bgcolor; if(b & 0x40) *(sp++) = fgcolor; else *(sp++) = bgcolor; if(b & 0x20) *(sp++) = fgcolor; else *(sp++) = bgcolor; if(b & 0x10) *(sp++) = fgcolor; else *(sp++) = bgcolor; if(b & 0x08) *(sp++) = fgcolor; else *(sp++) = bgcolor; if(b & 0x04) *(sp++) = fgcolor; else *(sp++) = bgcolor; if(b & 0x02) *(sp++) = fgcolor; else *(sp++) = bgcolor; if(b & 0x01) *(sp++) = fgcolor; else *(sp++) = bgcolor; RGBBlock2YUV(pixbuf, x * 8, y * 14 + c - 4); sp += width - 8; } } bptr++; cptr++; } } SDL_UnlockYUVOverlay(overlay); SDL_DisplayYUVOverlay(overlay, &rect); } private void RGBBlock2YUV(const Uint32[] source, int x, int y) { void RGB_to_YUV(Uint8 *rgb, Uint8* yuv) { yuv[0] = cast(ubyte)(0.299*rgb[0] + 0.587*rgb[1] + 0.114*rgb[2]); yuv[2] = cast(ubyte)((rgb[2]-yuv[0])*0.565 + 128); yuv[1] = cast(ubyte)((rgb[0]-yuv[0])*0.713 + 128); } static Uint8[3] yuv; static Uint8*[3] plane; plane[0] = overlay.pixels[0] + overlay.pitches[0] * y + x; plane[1] = overlay.pixels[1] + overlay.pitches[1] * y / 2 + x / 2; plane[2] = overlay.pixels[2] + overlay.pitches[2] * y / 2 + x / 2; for(int xc = 0; xc < 8 && xc < overlay.w; xc++) { RGB_to_YUV(cast(Uint8*)&source[xc], cast(ubyte*)&yuv); *(plane[0]++) = yuv[0]; if(xc % 2 == 0 && y % 2 == 0) { *(plane[1]++) = yuv[2]; *(plane[2]++) = yuv[1]; } } } private void createOverlay(int scaledx, int scaledy) { if(overlay !is null) SDL_FreeYUVOverlay(overlay); overlay = SDL_CreateYUVOverlay(requestedWidth, requestedHeight, SDL_YV12_OVERLAY, surface); if(overlay is null) { throw new DisplayError("Couldn't initialize YUV overlay."); } rect.w = cast(ushort)scaledx; rect.h = cast(ushort)scaledy; rect.x = rect.y = 0; if(useFullscreen) { rect.x = cast(short)(displayWidth/2 - scaledx/2); rect.y = cast(short)(displayHeight/2 - scaledy/2); } } } class Screen { Uint16[] data; private Uint16[] olddata; immutable int width, height; alias width w; alias height h; this(int xchars, int ychars) { width = xchars; height = ychars; data.length = xchars * ychars; olddata.length = xchars * ychars; refresh(); } Uint16 getChar(int x, int y) { mixin(CHECKS); return data[x + y * width]; } void setChar(int x, int y, Uint16 c) { mixin(CHECKS); data[x + y * width] = c; isDirty = true; } void setColor(int x, int y, int fg, int bg) { mixin(CHECKS); Uint16* s = &data[x + y * width]; *s &= 0xff; *s |= (fg << 8) | (bg << 12); isDirty = true; } int getbg(int x, int y) { return getChar(x, y) >> 12; } void setbg(int x, int y, int bg) { Uint16* s = &data[x + y * width]; *s &= 0xfff; *s |= (bg << 12); isDirty = true; } void clrtoeol(int y, int bg) { clrtoeol(0, y, bg); } void clrtoeol(int x, int y, int bg) { mixin(CHECKY); Uint16* s = &data[x + y * width]; Uint16 v = cast(Uint16)(0x20 | (bg << 12)); while(x++ < width) *s++ = v; isDirty = true; } void clrscr() { data[] = 0x20; isDirty = true; } void refresh() { olddata[] = 255; isDirty = true; } void cprint(int x, int y, int fg, int bg, string txt) { mixin(CHECKS); bool skipbg, skipfg; if(bg < 0) { skipbg = true; bg = 0; } if(fg < 0) { skipfg = true; fg = 0; } Uint16[] s = data[x + y * width .. x + y * width + txt.length]; Uint16 col = cast(Uint16)((fg << 8) | (bg << 12)); foreach(i, char c; txt) { if(skipbg) col = cast(Uint16)((fg << 8) | (s[i] & 0xf000)); if(skipfg) col = cast(Uint16)((bg << 12) | (s[i] & 0x0f00)); s[i] = cast(Uint16)(c | col); } isDirty = true; } void fprint(int x, int y, string str) { mixin(CHECKS); assert(str.length < 256); Uint16[] outb = data[x + y * width .. $]; int bg = 0, fg = 0; int idx; while(idx < str.length) { int getcol(char c) { return cast(int)(c == '+' ? -1 : "0123456789abcdef".indexOf(c)); } if(str[idx] == '`') { bg = getcol(str[idx + 1]); fg = getcol(str[idx + 2]); idx += 3; continue; } if(bg >= 0) { outb[0] &= 0x0fff; outb[0] |= bg << 12; } if(fg >= 0) { outb[0] &= 0xf0ff; outb[0] |= fg << 8; } outb[0] &= 0xff00; outb[0] |= str[idx] & 255; outb = outb[1 .. $]; idx++; } } } interface Visualizer { void clear(); void draw(int); } private class Oscilloscope : Visualizer { private SDL_Surface* surface; private short* samples; private const short xconst, yconst; enum width = 960/4, height = 3*14; this(SDL_Surface* surface, short xpos, short ypos) { this.surface = surface; this.xconst = xpos; this.yconst = ypos; import audio.audio; samples = audio.audio.mixbuf; assert(samples !is null); } void clear() { SDL_FillRect(surface, new SDL_Rect(xconst, yconst, width, height), 0); } void draw(int frames) { float smpofs; float n = frames * 50.0f; int count = cast(int)(48000 / n); auto colh = getColor(surface, 13), coll = getColor(surface, 5); clear(); smpofs = 0.0f; import audio.audio; int oldposition = height / 2 + samples[cast(int)smpofs] / 768; for(int i = 0; i < width; i++) { int sample = samples[cast(int)smpofs] / 768; int position = height / 2 + sample; position = com.util.umod(position, 0, height-1); int a = oldposition, b = position; if(a > b) { int temp = b; b = a; a = temp; } assert(a <= b); Uint32* pos = cast(Uint32 *)surface.pixels + xconst + i + (a + yconst) * surface.w; *pos = (i > 12 && i < width - 12) ? colh : coll; for(int k = a; k < b; k++) { *pos = (i > 12 && i < width - 12) ? colh : coll; pos += surface.w; } smpofs++; if(smpofs >= audio.audio.getbufsize()) smpofs -= cast(int)audio.audio.getbufsize(); oldposition = position; } } } class DisplayError : Error { this(string msg) { super("SDL Error: " ~ msg); } } void enableKeyRepeat() { SDL_EnableKeyRepeat(200, 10); } void disableKeyRepeat() { SDL_EnableKeyRepeat(0, 0); } Uint16 readkey() { SDL_Event evt; bool loop = true; while(loop) { while(SDL_PollEvent(&evt)) { if(evt.type == SDL_QUIT) { SDL_Quit(); return 0; } if(evt.type == SDL_KEYDOWN) { loop = false; break; } } SDL_Delay(50); } return evt.key.keysym.unicode; } private int getColor(SDL_Surface* s, int c) { return PALETTE[c].b << s.format.Bshift | (PALETTE[c].g << s.format.Gshift) | (PALETTE[c].r << s.format.Rshift); } CheeseCutter-master/src/com/kbd.d000066400000000000000000000024471357241101300172100ustar00rootroot00000000000000/* CheeseCutter v2 (C) Abaddon. Licensed under GNU GPL. */ module com.kbd; import derelict.sdl.sdl; import ui.input : Keyinfo; void translate(ref Keyinfo key) { switch(key.key) { case SDLK_KP_ENTER: // for shitty laptops and apple computers... key.key = SDLK_INSERT; break; default: break; } // do this last since platform specific translations need to be done 1st translate_super(key); } void translate_super(ref Keyinfo key) { if(key.mods & KMOD_META) { switch(key.key) { case SDLK_1: key.key = SDLK_KP1; break; case SDLK_2: key.key = SDLK_KP2; break; case SDLK_3: key.key = SDLK_KP3; break; case SDLK_4: key.key = SDLK_KP4; break; case SDLK_5: key.key = SDLK_KP5; break; case SDLK_6: key.key = SDLK_KP6; break; case SDLK_7: key.key = SDLK_KP7; break; case SDLK_8: key.key = SDLK_KP8; break; case SDLK_9: key.key = SDLK_KP9; break; case SDLK_UP: key.mods = KMOD_SHIFT; key.key = SDLK_HOME; break; case SDLK_DOWN: key.mods = KMOD_SHIFT; key.key = SDLK_END; break; default: // otherwise just translate to ctrl+shift... key.mods |= KMOD_CTRL | KMOD_SHIFT; break; } key.mods ^= KMOD_META; // meta off } } CheeseCutter-master/src/com/session.d000066400000000000000000000042431357241101300201270ustar00rootroot00000000000000/* CheeseCutter v2 (C) Abaddon. Licensed under GNU GPL. */ module com.session; import ct.base; import com.fb; import com.util; import ui.ui; import seq.sequencer; import std.typecons; interface Undoable { void undo(UndoValue); UndoValue createRedoState(UndoValue); } struct TracklistStore { Tracklist store, source; } struct UndoValue { import ct.base; alias Array = Tuple!(ubyte[], "target", ubyte[], "source"); // undo data needed by sequencer Array array; Sequence seq; // undo data needed by track editor TracklistStore[] trackLists; ushort trackValue; Track track; ubyte[][] tableData; int subtuneNum; PosDataTable posTable; bool allVoices; } struct UndoState { Undoable func; UndoValue value; } struct EditorState { __gshared Song song; PosDataTable fplayPos, seqPos; int octave = 3; int activeInstrument; bool autoinsertInstrument = true; bool shortTitles = true; bool displayHelp = true; bool keyjamStatus = false; bool allowInstabNavigation = true; string filename; auto undoQueue = Queue!UndoState(); auto redoQueue = Queue!UndoState(); } UI mainui; Video video; Screen screen; EditorState state; void insertUndo(Undoable undoable, UndoValue value) { state.undoQueue.insert(UndoState(undoable, value)); } void executeUndo() { if(state.undoQueue.empty) return; auto u = state.undoQueue.pop(); // make entry for redo (copy current state) auto redo = makeRedoOrUndo(u); state.redoQueue.insert(redo); u.func.undo(u.value); } void executeRedo() { if(state.redoQueue.empty) return; auto r = state.redoQueue.pop(); // make entry for undo (copy current state) auto undo = makeRedoOrUndo(r); state.undoQueue.insert(undo); r.func.undo(r.value); } private UndoState makeRedoOrUndo(UndoState state) { state.value = state.func.createRedoState(state.value); return state; } @property song() { return state.song; } @property seqPos() { return state.seqPos; } @property fplayPos() { return state.fplayPos; } void initSession() { state.song = new Song(); state.seqPos = new PosDataTable(); state.fplayPos = new PosDataTable(); for(int i = 0; i < 3; i++) { state.seqPos[i].tracks = song.tracks[i]; state.fplayPos[i].tracks = song.tracks[i]; } } CheeseCutter-master/src/com/util.d000066400000000000000000000120411357241101300174140ustar00rootroot00000000000000/* CheeseCutter v2 (C) Abaddon. Licensed under GNU GPL. */ module com.util; import std.stdio; import std.string; import std.conv; import std.array; alias char* PetString; //private auto regexFn = regex("[^a-zA-Z0-9_\\-\\.]"); string versionInfo() { version(DEV) return " (" ~__DATE__ ~ " git)"; return " (" ~__DATE__ ~ ")"; } struct Clip { int trans, no; } struct Queue(T) { enum NUM_UNDO_STAGES = 200; import std.container.dlist; auto stages = DList!T(); void insert(T t) { import std.range; auto r = stages[]; if(r.walkLength >= NUM_UNDO_STAGES) stages.removeBack(); stages.insertFront(t); } bool empty() { return stages.empty; } T pop() { if(stages.empty) assert(0); auto t = stages.front; stages.removeFront(); return t; } void clear() { stages.clear; } } class UserException : Exception { this(string msg) { super(msg); } override string toString() { return msg; } } int paddedStringLength(string s, char padchar) { int i; for(i = cast(int)(s.length - 1); i >= 0; i--) { if(s[i] != padchar) return cast(int)(i+1); } return 0; } void hexdump(ubyte[] buf, int rowlen) { hexdump(buf, rowlen, false); } void hexdump(ubyte[] buf, int rowlen, bool prrow) { int c, r; if(prrow) writef("%02x: ", 0); foreach(b; buf) { writef("%02X ", b); c++; if(c >= rowlen) { c = 0; writef("\n"); if(prrow) writef("%02x: ",++r); } } writef("\n"); } string petscii2D(PetString petstring) { char[] s; int idx; s.length = 512; while(*petstring != '\0') { char c = *(petstring++); if(c == '&') { s[idx] = '\n'; s[idx + 1 .. idx + 6] = ' '; idx += 6; } else s[idx++] = c; } s.length = idx; return format(s); } deprecated string getArgumentValue(string argname, string[] text) { foreach(line; text) { string[] tokens = std.array.split(line); //string[] tokens = line.split(); if(tokens.length == 0) continue; if(tokens[0] == argname && tokens.length > 2 && tokens[1] == "=") return tokens[2]; } return null; } string setArgumentValue(string argname, string value, string text) { string s; bool found; //foreach(line; text.splitLines()) { foreach(line; text.splitLines()) { //string[] tokens = line.split(); string[] tokens = std.array.split(line); if(tokens.length == 0) continue; if(tokens[0] == argname && tokens.length > 2 && tokens[1] == "=") { line = tokens[0] ~ tokens[1] ~ " " ~ value; found = true; } s ~= line ~ "\n"; } if(!found) throw new Exception("argname " ~ argname ~ " not found"); return s; } ubyte[] table2Array(string table) { static ubyte[4096] arr; int idx; foreach(strvalue; std.array.split(table)) { munch(strvalue, "\r\n\t"); arr[idx] = cast(ubyte)str2Value(strvalue); idx++; } return arr[0..idx]; } int str2Value(string s) { if(s[0] == 'x' || s[0] == '$') { return convertHex(s[1 .. $]); } return to!int(s); } int convertHex(string s) { int val, i; foreach_reverse(c; toUpper(s)) { if(c == 'x' || c == '$') break; if("0123456789ABCDEF".indexOf(c) < 0) throw new Exception("Illegal hexadecimal value in string."); val += ( (c >= '0' && c <= '9') ? c - '0' : c - ('A' - 10)) << (4 * i++); } return val; } void parseList(ref int[] array, string arg) { int index; string[] list = std.string.split(arg, ","); foreach(valueset; list) { string[] values = std.string.split(valueset, ":"); if(values.length == 0) { // length == 0, just skip index++; } else if(values.length == 1) { // the sole value is the speed array[index] = to!int(values[0]); } else { index = to!int(values[0]); if(index > 31) throw new UserException("Value list index out of bounds."); array[index] = to!int(values[1]); } index++; if(index > 31) throw new UserException("Value list too long."); } } int str2Value2(string s) { int idx; bool hexUsed; if(s[0] == 'x' || s[0] == '$') { hexUsed = true; idx = 1; } else if(s.length > 2 && s[0..2] == "0x") { hexUsed = true; idx = 2; } if(hexUsed) { int val, i; foreach_reverse(char c; toUpper(s[idx..$])) { if("0123456789ABCDEF".indexOf(c) < 0) throw new UserException("Illegal hexadecimal value in argument."); val += ( (c >= '0' && c <= '9') ? c - '0' : c - ('A' - 10)) << (4 * i++); } return val; } foreach(char c; s) { if("0123456789".indexOf(c) < 0) throw new UserException("Illegal value in argument."); } return to!int(s); } string arr2str(ubyte[] arr) { //char[] c = new string(arr.length * 2); char[] c = (new string(arr.length * 2)).dup; foreach(idx, ubyte byt; arr) { c[idx * 2 .. idx * 2 + 2] = std.string.format("%02x", byt); } return to!string(c); } /* string fnClean(string fn) { return replaceAll(fn,regexFn,"_"); } bool fnIsSane(string fn) { return matchAll(fn,regexFn).empty; }*/ string fnClean(string fn) { return tr(fn,"a-zA-Z0-9._-","_","c"); } bool fnIsSane(string fn) { return (fn == fnClean(fn)); } int clamp(int n, int l, int h) { return n > h ? h : n < l ? l : n; } int umod(int n, int l, int h) { return n > h ? l : n < l ? h : n; } // 0-terminated string to d string string ztos(char[] str) { return to!string(&str[0]); } CheeseCutter-master/src/ct/000077500000000000000000000000001357241101300161245ustar00rootroot00000000000000CheeseCutter-master/src/ct/base.d000066400000000000000000001257271357241101300172210ustar00rootroot00000000000000/* CheeseCutter v2 (C) Abaddon. Licensed under GNU GPL. */ module ct.base; import com.cpu; import com.util; import ct.purge; import std.string; import std.file; import std.zlib; enum Offsets { Features, Volume, Editorflag, Songsets, PlaySpeed, Subnoteplay, Submplayplay, InstrumentDescriptionsHeader, PulseDescriptionsHeader, FilterDescriptionsHeader, WaveDescriptionsHeader, CmdDescriptionsHeader, FREQTABLE, FINETUNE, Arp1, Arp2, FILTTAB, PULSTAB, Inst, Track1, Track2, Track3, SeqLO, SeqHI, CMD1, S00, SPEED, TRACKLO, VOICE, GATE, ChordTable, TRANS, ChordIndexTable, SHTRANS, FOO3, NEXT, CURINST, GEED, NEWSEQ } immutable string[] NOTES = [ "C-0", "C#0", "D-0", "D#0", "E-0", "F-0", "F#0", "G-0", "G#0", "A-0", "A#0", "B-0", "C-1", "C#1", "D-1", "D#1", "E-1", "F-1", "F#1", "G-1", "G#1", "A-1", "A#1", "B-1", "C-2", "C#2", "D-2", "D#2", "E-2", "F-2", "F#2", "G-2", "G#2", "A-2", "A#2", "B-2", "C-3", "C#3", "D-3", "D#3", "E-3", "F-3", "F#3", "G-3", "G#3", "A-3", "A#3", "B-3", "C-4", "C#4", "D-4", "D#4", "E-4", "F-4", "F#4", "G-4", "G#4", "A-4", "A#4", "B-4", "C-5", "C#5", "D-5", "D#5", "E-5", "F-5", "F#5", "G-5", "G#5", "A-5", "A#5", "B-5", "C-6", "C#6", "D-6", "D#6", "E-6", "F-6", "F#6", "G-6", "G#6", "A-6", "A#6", "B-6", "C-7", "C#7", "D-7", "D#7", "E-7", "F-7", "F#7", "G-7", "G#7", "A-7", "A#7", "B-7" ]; enum { MAX_SEQ_ROWS = 0x40, MAX_SEQ_NUM = 0x80, TRACK_LIST_LENGTH = 0x200, OFFSETTAB_LENGTH = 16 * 6, SEQ_END_MARK = 0xbf, SONG_REVISION = 12, NOTE_KEYOFF = 1, NOTE_KEYON = 2, SUBTUNE_MAX = 32 } immutable ubyte[] CLEAR = [0xf0, 0xf0, 0x60, 0x00]; immutable ubyte[] INITIAL_SEQ = [0xf0, 0xf0, 0x60, 0x00, 0xbf]; alias char*[] ByteDescription; struct Cmd { private ubyte[] data; static Cmd opCall() { static Cmd cmd; return cmd; } static Cmd opCall(ubyte[] d) { static Cmd cmd; cmd.data = d; return cmd; } void opAssign(ubyte cmd) { data[3] = cmd; if(cmd >= 0 && data[2] < 0x60) data[2] += 0x60; } void opAssign(Cmd cmd) { data = cmd.data; } @property ubyte value() { return data[3]; } alias value rawValue; string toString() { return toString(true); } string toString(bool colors) { ubyte v = data[3]; if(v > 0) return format("`+f%02X", v); else return "`+b--"; } string toPlainString() { ubyte v = data[3]; if(v > 0) return format("%02X", v); else return "--"; } } struct Ins { private ubyte[] data; static Ins opCall() { static Ins ins; return ins; } static Ins opCall(ubyte[] d) { static Ins ins; ins.data = d; return ins; } void opAssign(ubyte newins) { if(newins < 0x30) data[0] = cast(ubyte) (newins + 0xc0); else data[0] = cast(ubyte)0xf0; } void opAssign(Ins ins) { data = ins.data; } @property ubyte rawValue() { return data[0]; } @property ubyte value() { return cast(ubyte)(data[0] - 0xc0); } private alias value v; @property bool hasValue() { return value() < 0x30; } string toString() { if(v >= 0 && v < 0x30) return format("`+f%02X", v); else return "`+b--"; } string toPlainString() { alias value v; if(v >= 0 && v < 0x30) return format("%02X", v); else return "--"; } } struct Note { private ubyte[] data; static Note opCall(ubyte[] d) { static Note no; no.data = d; return no; } void opAssign(ubyte newnote) { if(newnote > 0x5e) newnote = 0x5e; data[2] = cast(ubyte)(newnote + 0x60); } void opAssign(Note note) { data = note.data; } @property ubyte rawValue() { return data[2]; } @property ubyte value() { return data[2] % 0x60; } private alias value v; @property bool isTied() { return data[1] == 0x5f; } void setTied(bool t) { data[1] = t ? 0x5f : 0xf0; } string toString(int trns) { string col, colh; if(isTied()) { col = "`4f"; colh = "`4b"; } else { col = "`0f"; colh = "`0b"; } switch(v) { case 0: return format("%s---", colh ); case 1: return format("%s===", col ); case 2: return format("%s+++", col ); default: if((v + trns) > 0x5e || (v + trns) < 0) return format("%s???", col); else return format("%s%s", col, NOTES[v + trns]); } } string toPlainString(int trns) { switch(v) { case 0: return "---"; case 1: return "==="; case 2: return "+++"; default: if((v + trns) > 0x5e || (v + trns) < 0) return "???"; else return NOTES[v + trns]; } } } struct Element { Ins instr; alias instr instrument; Cmd cmd; Note note; int transpose; ubyte[] data; static Element opCall(ubyte[] chunk) { static Element e; e.cmd = Cmd.opCall(chunk); e.instr = Ins(chunk); e.note = Note(chunk); e.data = chunk; return e; } string toString() { return toString(transpose); } string toString(int trans) { return format("%s`+0 %s %s", note.toString(trans), instr.toString(), cmd.toString()); } string toPlainString() { return format("%s %s %s", note.toPlainString(transpose), instr.toPlainString(), cmd.toPlainString()); } } struct Tracklist { private Track[] list; Track opIndex(int i) { if(i >= 0x400) i = 0; assert(i >= 0 && i < length); return list[i]; } static Tracklist opCall(Tracklist tl) { Tracklist t; t = tl; return t; } static Tracklist opCall(Track[] t) { Tracklist tl; tl.list = t; return tl; } Tracklist deepcopy() { auto copy = new Track[](list.length); foreach(idx, t; list) { auto tr = cast(ubyte)t.trans; auto number = cast(ubyte)t.number; copy[idx] = Track([tr, number]); } return Tracklist(copy); } void overwriteFrom(Tracklist tl) { for(int idx = 0; idx < tl.length; idx++) { auto tr = cast(ubyte)tl[idx].trans; auto number = cast(ubyte)tl[idx].number; list[idx].trans = tr; list[idx].number = number; } } void opIndexAssign(Track t, size_t il) { list[il] = t; } Track[] opSlice() { return list; } Tracklist opSlice(size_t x, size_t y) { return Tracklist(list[x .. y]); } int opApply(int delegate(ref Track) dg) { int result; for(int i = 0; i < trackLength; i++) { result = dg(list[i]); if(result) break; } return result; } int opApplyReverse(int delegate(ref Track) dg) { int result; for(int i = cast(int)(length - 1); i >= 0; i--) { result = dg(list[i]); if(result) break; } return result; } @property int length() { return cast(int) list.length; } @property void length(size_t il) { list.length = il; } @property Track lastTrack() { return list[trackLength]; } @property int trackLength() { int i; for(i = 0; i < length; i++) { Track t = list[i]; if(t.trans >= 0xf0) return i; } assert(0); } @property address wrapOffset() { return (lastTrack.smashedValue() / 2) & 0x7ff; } @property void wrapOffset(address offset) { if((offset & 0xff00) >= 0xf000) return; assert(offset >= 0 && offset < 0x400); if(offset >= trackLength) offset = cast(ushort)(trackLength - 1); offset *= 2; offset |= 0xf000; lastTrack() = [(offset & 0xff00) >> 8, offset & 0x00ff]; } void expand() { insertAt(trackLength); } void shrink() { deleteAt(trackLength-1); } // returns transpose value other than 0x80 above idx OR below(if idx == 0) ubyte getTransAt(int idx) { if(idx > 0) { do { if(list[idx].trans > 0x80 && list[idx].trans < 0xc0) return list[idx].trans; } while(idx-- > 0); } else if(idx == 0) { do { if(list[idx].trans > 0x80 && list[idx].trans < 0xc0) return list[idx].trans; } while(idx++ < trackLength); } return 0xa0; } void insertAt(int offset) { if(offset > list.length - 2) return; assert(offset >= 0 && offset < list.length); for(int i = cast(int)(list.length - 2); i >= offset; i--) { list[i+1] = list[i].dup; } list[offset].trans = getTransAt(offset); list[offset].number = 0; if(wrapOffset() >= offset) { wrapOffset = cast(address)(wrapOffset + 1); } } void deleteAt(int offset) { if(list[1].trans >= 0xf0) return; for(int i = offset; i < list.length - 2; i++) { list[i] = list[i+1].dup; } if(wrapOffset() >= offset) { wrapOffset = cast(address)(wrapOffset - 1); } } void transposeAt(int s, int e, int t) { foreach(trk; list[s .. e]) trk.transpose(t); } auto compact() { ubyte[] arr = new ubyte[1024]; int p, trans = -1, wrapptr = wrapOffset * 2; foreach(idx, track; list) { if(track.trans >= 0xf0) { wrapptr |= 0xf000; arr[p .. p + 2] = [(wrapptr & 0xff00) >> 8, wrapptr & 0x00ff]; p += 2; break; } if((track.trans != trans && track.trans != 0x80) || idx == wrapOffset) { trans = track.trans; arr[p++] = cast(ubyte)trans; } else if(idx < wrapOffset) { wrapptr--; } arr[p++] = track.number; } return arr[0..p]; } } struct Track { private ubyte[] data; static Track opCall(ubyte[] tr) { Track t; t.data = tr; assert(t.data.length == 2); return t; } void opAssign(ushort s) { data[0] = s & 255; data[1] = s >> 8; } void opAssign(ubyte[] d) { data[] = d[]; } void opAssign(Track tr) { data = tr.data; } @property void trans(ubyte t) { data[0] = t; } @property deprecated ushort dup() { return trans | (number << 8); } @property ushort smashedValue() { // "real" int value, trans = highbyte return number | (trans << 8); } @property ubyte trans() { return data[0]; } @property ubyte number() { return data[1]; } @property void number(ubyte no) { data[1] = no; } alias number trackNumber; void setValue(int tr, int no) { tr = clamp(tr, 0x80, 0xf3); if(no < 0) no = 0; if(no >= MAX_SEQ_NUM) no = MAX_SEQ_NUM-1; data[0] = tr & 255; data[1] = no & 255; } string toString() { string s = format("%02X%02X", trans, number); return s; } void transpose(int val) { if(trans == 0x80 || trans >= 0xf0) return; int t = trans + val; trans = (cast(ubyte)clamp(t, 0x80, 0xbf)); } } class Sequence { ElementArray data; int rows; static struct ElementArray { ubyte[] raw; Element opIndex(int i) { assert(i < MAX_SEQ_ROWS * 4); assert(i < (raw.length * 4)); ubyte[] chunk = raw[i * 4 .. i * 4 + 4]; return Element(chunk); } void opIndexAssign(int value, size_t il) { raw[il] = cast(ubyte)value; } int opApply(int delegate(Element) dg) { int result; for(int i = 0; i < length()/4; i++) { result = dg(opIndex(i)); if(result) break; } return result; } @property int length() { return cast(int)raw.length; } } this(ubyte[] d) { data = ElementArray(d); refresh(); if(rows*4+4 < 254) data.raw[rows*4 + 4 .. 254] = 0; } this(ubyte[] rd, int r) { data = ElementArray(rd); rows = r; } void refresh() { int p, r; // find seq length while(p < data.length) { ubyte b; b = data.raw[p+0]; if(b == SEQ_END_MARK) break; p += 4; r++; } rows = r; } override bool opEquals(Object o) const { auto rhs = cast(const Sequence)o; return (rhs && (data.raw[] == rhs.data.raw[])); } void clear() { data.raw[] = 0; data.raw[0..5] = [0xf0,0xf0,0x60,0x00,0xbf]; refresh(); } void expand(int pos, int r) { expand(pos, r, true); } void expand(int pos, int r, bool doInsert) { int i, len; int j; if(rows >= MAX_SEQ_ROWS) return; for(j=0;j= MAX_SEQ_ROWS) break; rows++; if(doInsert) insert(pos); else data.raw[(rows-1) * 4..(rows-1) * 4 + 4] = cast(ubyte[])CLEAR; } if(rows < 64) data.raw[rows*4] = SEQ_END_MARK; } void shrink(int pos, int r, bool doRemove) { if(rows <= 1 || pos >= rows - 1) return; for(int j = 0; j < r; j++) { if(doRemove) remove(pos); // clear endmark data.raw[rows * 4 .. $] = 0; rows--; data.raw[rows * 4 .. rows * 4 + 4] = cast(ubyte[])[ SEQ_END_MARK, 0, 0, 0 ]; } } void transpose(int r, int n) { for(int i = r; i < rows;i++) { Note note = data[i].note; int v = note.value; if(v < 3) continue; if(n >= 0 && (v+n) < 0x60) v += n; if(n < 0 && (v+n) >= 3) v += n; note = cast(ubyte) v; } } void insert(int pos) { int p1 = pos * 4; int p2 = rows * 4; if(p2 > 256) return; ubyte[] c = data.raw[p1 .. p2]; ubyte[] n = c.dup; c[4..$] = n[0..$-4].dup; // clear cursor pos c[0..4] = cast(ubyte[])CLEAR; } void remove(int pos) { ubyte[] tmp; int start = pos * 4; int end = rows * 4; tmp = data.raw[start + 4 .. end].dup; data.raw[start .. end - 4] = tmp; data.raw[end - 4 .. end] = cast(ubyte[])CLEAR; } void copyFrom(Sequence f) { rows = f.rows; data.raw[] = f.data.raw[].dup; } // insert seq f to offset ofs void insertFrom(Sequence f, int ofs) { // make temporary copy so that seq can be appended over itself Sequence copy = new Sequence(f.data.raw.dup); expand(ofs, f.rows); int max = MAX_SEQ_ROWS*4; int st = ofs * 4; int len = copy.rows * 4; int end = st + len; if(end >= max) { end = max; len = end - st; } data.raw[st .. end] = copy.data.raw[0..len]; } ubyte[] compact() { ubyte[] outarr = new ubyte[257]; int i, outp, olddel, oldins = -1, olddelay = -1, delay; for(i = 0; i < rows;) { Element e = data[i]; bool cmd = false; int note = e.note.rawValue; if(note >= 0x60 && e.cmd.rawValue > 0) cmd = true; else { if(note >= 0x60) note -= 0x60; } if(e.instr.value < 0x30 && oldins != e.instr.value) { oldins = e.instr.value; outarr[outp++] = cast(ubyte)(e.instr.value + 0xc0); } // calc delay delay = 0; for(int j = i + 1; j < rows; j++) { Element ee = data[j]; if((ee.note.rawValue % 0x60) == 0 && ee.cmd.rawValue == 0 && !ee.instr.hasValue()) { delay++; i++; } else break; } if(olddelay != delay) { olddelay = delay & 15; outarr[outp++] = cast(ubyte)(delay | 0xf0); olddelay = delay & 15; delay -= delay & 15; } if(e.note.isTied()) outarr[outp++] = 0x5f; outarr[outp++] = cast(ubyte)note; if(cmd) outarr[outp++] = cast(ubyte)(e.cmd.rawValue); while(delay > 15) { int d = delay; if(d > 15) d = 15; if(olddelay != d) { outarr[outp++] = cast(ubyte)(d | 0xf0); olddelay = d; } outarr[outp++] = cast(ubyte)0; delay -= 16; } i++; } outarr[outp++] = cast(ubyte)SEQ_END_MARK; return outarr[0..outp]; } } class Song { enum DatafileOffset { Binary, Header = 65536, Title = Header + 256 + 5, Author = Title + 32, Release = Author + 32, Insnames = Title + 40 * 4, Subtunes = Insnames + 1024 * 2 } private struct Features { ubyte requestedTables; ubyte[8] instrumentFlags; ubyte[16] cmdFlags; } private struct Patch { string name; ubyte[] def, wave1, wave2, filt, pulse; } static struct Chunk { int offset; ubyte[] wave1, wave2; bool used; int tokill; string toString() { return format("%x", offset); } // TODO implement .dup which copies arrasys as well Chunk dup() { assert(0); } } static class Table { ubyte[] data; this(ubyte[] data) { this.data = data; } int size() { foreach_reverse(idx, val; data) { if(val != 0) return cast(int)(idx + 1); } return 0; } int length() { return cast(int)data.length; } ubyte[] opSlice() { return data; } ubyte[] opSlice(size_t x, size_t y) { return data[x..y]; } } class WaveTable : Table { struct WaveProgram { ubyte[] wave1, wave2; int offset; } // info for each waveprogram ubyte[] wave1, wave2; this(ubyte[] data) { super(data); wave1 = data[0 .. 256]; wave2 = data[256 .. 512]; } int seekTableEnd() { for(int i = 255; i >= 1; i--) { if(wave1[i-1] != 0) { return i; } } return 0; } Chunk[] getChunks() { return getChunks(data); } Chunk[] getChunks(ubyte[] wavetab) { /+ static +/ Chunk[] chunks = new Chunk[256]; int counter; for(int i = 0, b; i < 256; i++) { if(wavetab[i] == 0x7f || wavetab[i] == 0x7e) { chunks[counter] = Chunk(b, wavetab[b .. i + 1], wavetab[b + 256 .. i + 256 + 1]); b = i + 1; counter++; } } return chunks[0 .. counter]; } bool isValid(int waveOffset) { auto chunks = getChunks(data); return whichCell(chunks, waveOffset) >= 0; } // get program starting at waveOffset // mostly copied from purgeWave WaveProgram getProgram(int waveOffset) { auto chunks = getChunks(data.dup); int topRow = 255; int cell = whichCell(chunks, waveOffset); if(cell < 0) throw new Error("Illegal waveprogram offset"); markCells(chunks, cell); WaveProgram wp; /+ get top row in used chunks, needed to recalc arpofs NB might be necessary to calc last +/ foreach(ref chunk; chunks) { if(chunk.used && chunk.offset < topRow) topRow = chunk.offset; } /+ generate arrays +/ foreach(ref chunk; chunks) { if(!chunk.used) { if(waveOffset >= chunk.offset) waveOffset -= cast(int)chunk.wave1.length; foreach(ref chunk2; chunks) { if(chunk2.wave1[$ - 1] == 0x7f && chunk2.wave2[$ - 1] >= chunk.offset) { // check that 7f-xx is not pointing WITHIN this chunk //assert(chunk2.wave2[$ - 1] > chunk.offset + chunk.wave1.length); // calc wrap int t = chunk2.wave2[$ - 1] - cast(int)chunk.wave1.length; t = com.util.clamp(t, 0, 256); chunk2.wave2[$ - 1] = cast(ubyte)t; } if(chunk2.offset >=chunk.offset) chunk2.offset -= chunk.wave1.length; } } } foreach(ref chunk; chunks) { if(!chunk.used) continue; wp.wave1 ~= chunk.wave1; wp.wave2 ~= chunk.wave2; assert(wp.wave1[$-1] == 0x7f || wp.wave1[$-1] == 0x7e); } wp.offset = waveOffset; return wp; } static int whichCell(Chunk[] chunks, int ptr) { foreach(idx, chunk; chunks) { int b = chunk.offset, e = cast(int)(chunk.offset + chunk.wave1.length); if(ptr >= b && ptr < e) { return cast(int)idx; } } return -1; } static void markCells(Chunk[] chunks, int cell) { assert(cell >= 0 && cell < chunks.length); for(;;) { if(chunks[cell].used) break; chunks[cell].used = true; Chunk c = chunks[cell]; assert(c.wave1[$-1] == 0x7e || c.wave1[$-1] == 0x7f); if(c.wave1[$-1] == 0x7e) break; cell = whichCell(chunks, c.wave2[$-1]); if(cell < 0) break; } } void deleteRow(Song song, int pos) { deleteRow(song, pos, 1); } void deleteRow(Song song, int pos, int num) { for(int n = 0; n < num; n++) { int i; assert(pos < 255 && pos >= 0); for(i = pos; i < 255; i++) { wave1[i] = wave1[i + 1]; wave2[i] = wave2[i + 1]; } for(i=0;i < 256;i++) { if((wave1[i] == 0x7f || wave1[i] == 0x7e) && wave2[i] >= pos) { if(wave2[i] > 0) --wave2[i]; } } arpPointerUpdate(song, pos, -1); } } void insertRow(Song song, int pos) { int i; for(i = 254; i >= pos; i--) { wave1[i + 1] = wave1[i]; wave2[i + 1] = wave2[i]; } for(i=0;i<256;i++) { if(wave1[i] == 0x7f && wave2[i] >= pos) wave2[i]++; } wave1[pos] = 0; wave2[pos] = 0; arpPointerUpdate(song, pos, 1); } private void arpPointerUpdate(Song song, int pos, int val) { for(int j = 0; j < 48; j++) { ubyte b7 = instrumentTable[j + 7 * 48]; if(b7 > pos) { int v = b7 + val; if(v < 0) v = 0; // TODO rewrite not to access global.. instrumentTable[j + 7 * 48] = cast(ubyte)v; } } } } class InstrumentTable : Table { this(ubyte[] data) { super(data); } ubyte[] getInstrument(int no) { ubyte[] arr = new ubyte[8]; for(int i = 0; i < 8 ; i++) { arr[i] = data[no + i * 48]; } return arr; } } class SweepTable : Table { this(ubyte[] data) { super(data); } struct SweepProgram { int offset; ubyte[] data; } bool isValid(int currentRow) { if(currentRow >= 0x80 && currentRow < 0x90) return true; bool[0x40] visited; for(int row = currentRow; row < 0x40;) { if(visited[row]) return true; visited[row] = true; int jumpValue = data[row * 4 + 3]; if(jumpValue > 0x3f && jumpValue != 0x7f) // if illegal, break return false; if(jumpValue == 0x7f) return true; else if(jumpValue == 0) row++; else row = jumpValue; } return false; } SweepProgram getProgram(int currentRow) { bool[0x40] visited; int topRow = currentRow; for(int row = currentRow; row < 0x40;) { if(row < topRow) topRow = row; if(visited[row]) break; visited[row] = true; int jumpValue = data[row * 4 + 3]; if(jumpValue > 0x3f && jumpValue != 0x7f) // if illegal, break break; if(jumpValue == 0x7f) break; // if loops or ends, break else if(jumpValue == 0) row++; else row = jumpValue; } int toremove; ubyte[] copy = data.dup; foreach(idx, vis; visited) { if(!vis && idx > 0) { for(int i = 1; i < 64; i++) { int jumpval = data[i * 4 + 3]; if(jumpval < 0x40 && jumpval >= idx) { copy[i * 4 + 3]--; } } if(currentRow >= idx) ++toremove; //--currentRow; } } ubyte[] arr; foreach(idx, vis; visited) { if(vis) { arr ~= copy[idx * 4 .. idx * 4 + 4]; } } assert(arr[$-1] > 0); return SweepProgram(currentRow - toremove, arr); } int seekTableEnd() { for(int i = 0x3c; i >= 0; i -= 4) { if(data[i + 3] > 0) { return i / 4 + 1; } } return 0; } } private class Subtunes { ubyte[1024][3][32] subtunes; private int active; this() { initArray(); } this(ubyte[] arr) { ubyte[] subts; this(); subts = cast(ubyte[])(&subtunes)[0..1]; subts[] = arr; } @property int numOf() { foreach_reverse(idx, ref tune; subtunes) { foreach(ref voice; tune) { if(voice[1 .. 4] != cast(ubyte[])[0x00, 0xf0, 0x00]) { return cast(int)(idx + 1); } } } return 0; } private void initArray() { foreach(ref tune; subtunes) { foreach(ref voice; tune) { voice[0 .. 2] = cast(ubyte[])[0xa0, 0x00]; for(int i = 2; i < voice.length; i += 2) { voice[i .. i+2] = cast(ubyte[])[0xf0, 0x00]; } } } } void clearAll() { initArray(); syncFromBuffer(); } void clear(int no) { foreach(ref voice; subtunes[no]) { voice[0 .. 2] = cast(ubyte[])[0xa0, 0x00]; for(int i = 2; i < voice.length; i += 2) { voice[i .. i+2] = cast(ubyte[])[0xf0, 0x00]; } } if(no == active) syncFromBuffer(); } void swap(int targetNo, int sourceNo) { if(targetNo == sourceNo) return; if(targetNo == active || sourceNo == active) sync(); ubyte[1024][3] sourcebuf, targetbuf; for(int i = 0; i < 3; i++) { targetbuf[i][] = subtunes[targetNo][i][]; subtunes[targetNo][i][] = subtunes[sourceNo][i][]; subtunes[sourceNo][i][] = targetbuf[i][]; } ubyte spdtemp = songspeeds[targetNo]; songspeeds[targetNo] = songspeeds[sourceNo]; songspeeds[sourceNo] = spdtemp; if(active == targetNo || active == sourceNo) syncFromBuffer(); } private void syncFromBuffer() { for(int i = 0; i < 3; i++) { data[offsets[Offsets.Track1 + i] .. offsets[Offsets.Track1 + i] + 0x400] = subtunes[active][i][0..0x400]; } } Tracklist[] opIndex(int n) { static Tracklist[3] tr; for(int i=0;i<3;i++) { tr[i].length = TRACK_LIST_LENGTH; } for(int i = 0; i < 3 ; i++) { ubyte[] b; // use array from c64 memory if getting current subtune if(n == active) b = buffer[offsets[Offsets.Track1 + i] .. offsets[Offsets.Track1 + i] + 0x400]; else b = subtunes[n][i][0..0x400]; for(int j = 0; j < b.length / 2; j++) { tr[i][j] = Track(b[j * 2 .. j * 2 + 2]); } } return tr; } void activate(int n) { activate(n, true); } void activate(int n, bool dosync) { if(n > 0x1f || n < 0) return; if(dosync) sync(); active = n; for(int i = 0; i < 3; i++) { buffer[offsets[Offsets.Track1 + i] .. offsets[Offsets.Track1 + i] + 0x400] = subtunes[active][i][0..0x400]; } if(ver >= 6) speed = songspeeds[active]; } /* sync "external" subtune array to active one (stored in c64s mem) * the correct way would be to let trackinput also update the external array */ private void sync() { for(int i = 0; i < 3; i++) { subtunes[active][i][0..0x400] = buffer[offsets[Offsets.Track1 + i] .. offsets[Offsets.Track1 + i] + 0x400]; } } // highly dubious coding here (actually, like in most of this class..) ubyte[][][] compact() { ubyte[][][] arr; arr.length = numOf(); foreach(ref subarr; arr) { subarr.length = 3; } for(int i = 0; i < numOf(); i++) { ubyte[][] subarr = arr[i]; for(int j = 0; j < 3; j++) { buffer[offsets[Offsets.Track1 + j] .. offsets[Offsets.Track1 + j] + 0x400] = subtunes[i][j][0..0x400]; } foreach(idx, ref voice; subarr) { voice = tracks[idx].compact().dup; } } return arr; } } int ver = SONG_REVISION, clock, multiplier = 1, sidModel, fppres; char[32] title = ' ', author = ' ', release = ' ', message = ' '; char[32][48] insLabels; private Features features; CPU cpu; ubyte[] sidbuf; ubyte[65536] data; alias data buffer; alias data memspace; Tracklist[] tracks; Sequence[] seqs; alias seqs sequences; address[] offsets; ubyte[32] songspeeds; ubyte[] songsets, wave1Table, wave2Table, waveTable, instrumentTable, pulseTable, filterTable, superTable, chordTable, chordIndexTable, seqlo, seqhi; ByteDescription instrumentByteDescriptions, pulseDescriptions, filterDescriptions, waveDescriptions, cmdDescriptions; // dupes of raw tables above, will eventually update all code to use these Table tSongsets, tSuper, tChord, tChordIndex, tSeqlo, tSeqhi; InstrumentTable tInstr; WaveTable tWave; SweepTable tPulse, tFilter; Table tTrack1, tTrack2, tTrack3; Table[string] tables; char[] playerID; int subtune; Subtunes subtunes; // these used to be sequencer vars but they're here now since they get saved with the tune int highlight = 4, highlightOffset = 0; private auto playerBinary = cast(ubyte[])import("player.bin"); this() { this(playerBinary); } this(ubyte[] player) { cpu = new CPU(buffer); subtunes = new Subtunes(); foreach(ref desc; insLabels) { desc[] = 0x20; } ver = SONG_REVISION; ubyte[] bin; bin.length = 65536; bin[0xdfe .. 0xdfe + player.length] = player; if(bin[0xdfe .. 0xe00] != cast(ubyte[])[ 0x00, 0x0e ]) throw new UserException("Illegal loading address."); songspeeds[] = 5; initialize(bin); sidbuf = memspace[0xd400 .. 0xd419]; } @property int numOfSeqs() { int upto; foreach(i, s; seqs) { if(s.data.raw[0 .. 5] != INITIAL_SEQ) upto = cast(int)i; } return upto + 1; } @property int speed() { return memspace[offsets[Offsets.SPEED]]; } @property void speed(int spd) { memspace[offsets[Offsets.Songsets] + 6] = cast(ubyte)spd; memspace[offsets[Offsets.SPEED]] = cast(ubyte)spd; songspeeds[subtune] = cast(ubyte)spd; if(ver >= 5 && spd >= 2) memspace[offsets[Offsets.PlaySpeed]] = cast(ubyte)spd; } @property int playSpeed() { return memspace[offsets[Offsets.PlaySpeed]]; } @property int numInstr() { int maxInsno; seqIterator((Sequence s, Element e) { int insval = e.instr.value; if(insval > 0x2f) return; if(insval > maxInsno) maxInsno = insval; }); return maxInsno; } void open(string fn) { ubyte[] inbuf = cast(ubyte[])read(fn); if(inbuf[0..3] != cast(ubyte[])"CC2"[0..3]) { throw new UserException(format("%s: Incorrect filetype.", fn)); } ubyte[] debuf = cast(ubyte[])std.zlib.uncompress(inbuf[3..$],167832); int offset = 65536; ver = debuf[offset++]; if(ver < 6) throw new UserException("The song is incompatible (too old) for this version of the editor."); if(ver >= 128) throw new UserException("The song appears to be a stereo SID file and doesn't work with this editor."); clock = debuf[offset++]; multiplier = debuf[offset++]; sidModel = debuf[offset++]; fppres = debuf[offset++]; if(ver >= 6) { songspeeds[0..32] = debuf[offset .. offset+32]; offset += 32; } if(ver > 10) { highlight = debuf[offset++]; highlightOffset = debuf[offset++]; } offset = DatafileOffset.Title; title[0..32] = cast(char[])debuf[offset .. offset + 32]; author[0..32] = cast(char[])debuf[offset + 32 .. offset + 64]; release[0..32] = cast(char[])debuf[offset + 64 .. offset + 96]; offset += 40 * 4; assert(DatafileOffset.Insnames == offset); offset = DatafileOffset.Insnames; ubyte[] insnames = cast(ubyte[])(&insLabels)[0..1]; insnames[] = debuf[offset .. offset + 48*32]; assert(DatafileOffset.Subtunes == offset + 1024 * 2); offset += 1024 * 2; int len = 1024*3*32; subtunes = new Subtunes(debuf[offset .. offset + len]); offset += len; initialize(debuf[0..65536]); } void setMultiplier(int m) { assert(m > 0 && m < 16); multiplier = m; memspace[Offsets.Volume + 1] = cast(ubyte)m; } protected void initialize(ubyte[] buf) { int voi, ofs; data[] = buf; offsets.length = 0x60; seqs.length = MAX_SEQ_NUM; tracks.length = 3; for(int i = 0; i < 3; i++) { tracks[i].length = TRACK_LIST_LENGTH; } for(int i = 0; i < OFFSETTAB_LENGTH; i++) { offsets[i] = data[0xfa0+i*2] | (data[0xfa1+i*2] << 8); } for(int no = 0; no < MAX_SEQ_NUM; no++) { int p, lo, hi; int lobyt = offsets[Offsets.SeqLO] + no, hibyt = offsets[Offsets.SeqHI] + no; p = data[lobyt] + (data[hibyt] << 8); ubyte[] raw_seq_data = data[p .. p+256]; seqs[no] = new Sequence(raw_seq_data); } for(voi = 0; voi < 3; voi++) { ubyte[] b; int t; int offset = offsets[Offsets.Track1 + voi]; b = data[offset .. offset + 0x400]; for(int i = 0; i < b.length/2; i++) { tracks[voi][i] = Track(memspace[offset + i * 2 .. offset + i * 2 + 2]); } } ofs = offsets[Offsets.Songsets]; songsets = data[ofs .. ofs + 256]; tSongsets = new Table(songsets); ofs = offsets[Offsets.Arp1]; wave1Table = data[ofs .. ofs + 256]; wave2Table = data[ofs + 256 .. ofs + 512]; waveTable = data[ofs .. ofs + 512]; // tWave1 = new Table(wave1Table); // tWave2 = new Table(wave2Table, ofs + 256); tWave = new WaveTable(waveTable); ofs = offsets[Offsets.Inst]; instrumentTable = data[ofs .. ofs + 512]; tInstr = new InstrumentTable(instrumentTable); ofs = offsets[Offsets.CMD1]; superTable = data[ofs .. ofs + 256]; tSuper = new Table(superTable); ofs = offsets[Offsets.PULSTAB]; pulseTable = data[ofs .. ofs + 256]; tPulse = new SweepTable(pulseTable); ofs = offsets[Offsets.FILTTAB]; filterTable = data[ofs .. ofs + 256]; tFilter = new SweepTable(filterTable); ofs = offsets[Offsets.SeqLO]; seqlo = data[ofs .. ofs + 256]; tSeqlo = new Table(seqlo); ofs = offsets[Offsets.SeqHI]; seqhi = data[ofs ..ofs + 256]; tSeqhi = new Table(seqhi); ofs = offsets[Offsets.ChordTable]; chordTable = data[ofs .. ofs + 128]; tChord = new Table(chordTable); ofs = offsets[Offsets.ChordIndexTable]; chordIndexTable = data[ofs .. ofs + 32]; tChordIndex = new Table(chordIndexTable); generateChordIndex(); ofs = offsets[Offsets.Track1]; tTrack1 = new Table(data[ofs .. ofs + 0x400]); ofs = offsets[Offsets.Track2]; tTrack2 = new Table(data[ofs .. ofs + 0x400]); ofs = offsets[Offsets.Track3]; tTrack3 = new Table(data[ofs .. ofs + 0x400]); playerID = cast(char[])data[0xfee .. 0xff5]; subtune = 0; ofs = offsets[Offsets.Features]; ubyte[] b = memspace[ofs .. ofs + 64]; features.requestedTables = b[0]; features.instrumentFlags[] = b[1..9]; /* ubyte* b = cast(ubyte*)&features; b[0..features.sizeof] = memspace[ofs .. ofs + features.sizeof]; */ if(ver > 7) { instrumentByteDescriptions.length = 8; ofs = offsets[Offsets.InstrumentDescriptionsHeader]; for(int j = 0; j < 8; j++) { int iofs = memspace[ofs] | (memspace[ofs+1] << 8); instrumentByteDescriptions[j] = cast(char*)&memspace[iofs]; ofs += 2; } } if(ver > 8) { int offset; filterDescriptions.length = 4; offset = offsets[Offsets.FilterDescriptionsHeader]; foreach(idx, ref descr; filterDescriptions) { int soffset = memspace[offset + idx * 2] | (memspace[offset + idx * 2 + 1] << 8); descr = cast(char*)&memspace[soffset]; } pulseDescriptions.length = 4; offset = offsets[Offsets.PulseDescriptionsHeader]; foreach(idx, ref descr; pulseDescriptions) { int soffset = memspace[offset + idx * 2] | (memspace[offset + idx * 2 + 1] << 8); descr = cast(char*)&memspace[soffset]; } waveDescriptions.length = 2; offset = offsets[Offsets.WaveDescriptionsHeader]; foreach(idx, ref descr; waveDescriptions) { int soffset = memspace[offset + idx * 2] | (memspace[offset + idx * 2 + 1] << 8); descr = cast(char*)&memspace[soffset]; } cmdDescriptions.length = 2; offset = offsets[Offsets.CmdDescriptionsHeader]; foreach(idx, ref descr; cmdDescriptions) { int soffset = memspace[offset + idx * 2] | (memspace[offset + idx * 2 + 1] << 8); descr = cast(char*)&memspace[soffset]; } } subtunes.syncFromBuffer(); speed = songspeeds[0]; cpu.reset(); cpu.execute(0x1000); tables = [ cast(string)"songsets":tSongsets, "wave":tWave, "instr":tInstr, "pulse":tPulse, "filter":tFilter, "cmd":tSuper, "chord":tChord, "chordidx":tChordIndex, "seqlo":tSeqlo, "seqhi":tSeqhi ]; } void save(string fn) { // get tracks from the c64 memory to subtunes-array subtunes.sync(); ubyte[] b; int offset; b.length = 300000; b[0..65536] = memspace; offset += 65536; foreach(val; [ver, clock, multiplier, sidModel, fppres]) { b[offset++] = val & 255; } b[offset .. offset+32] = songspeeds[]; offset += 32; b[offset++] = cast(ubyte)highlight; b[offset++] = cast(ubyte)highlightOffset; offset = DatafileOffset.Title; foreach(str; [title, author, release, message]) { b[offset .. offset + 32] = cast(ubyte[])str[]; offset += 32; } offset = DatafileOffset.Insnames; ubyte[] arr; arr = cast(ubyte[])(&insLabels)[0..1]; b[offset .. offset + arr.length] = arr[]; offset += arr.length; offset += 32 * 32 - 0x200; arr = cast(ubyte[])(&subtunes.subtunes)[0..1]; b[offset .. offset + arr.length] = arr[]; offset += arr.length; std.file.write(fn, "CC2"); append(fn, std.zlib.compress(b)); } void splitSequence(int seqnumber, int seqofs) { if(seqnumber == 0 || seqofs == 0) return; int suborig = subtune; int newseqnumber = getFreeSequence(0); Sequence s = seqs[seqnumber]; if(seqofs == s.rows - 1) return; Sequence copy = new Sequence(s.data.raw.dup); Sequence ns = seqs[newseqnumber]; ns.copyFrom(s); ns.shrink(0, seqofs, true); s.shrink(seqofs, s.rows - seqofs, true); subtunes.sync(); foreach(sIdx, st; subtunes.subtunes) { subtunes.activate(cast(int)sIdx); foreach(vIdx, voice; tracks) { for(int tIdx = voice.length - 1; tIdx >= 0; tIdx--) { Track t = voice[tIdx]; if(t.number == seqnumber) { tracks[vIdx].insertAt(tIdx+1); Track t2 = tracks[vIdx][tIdx+1]; t2.trans = 0x80; t2.number = (cast(ubyte)newseqnumber); } } } } subtunes.activate(suborig); } private int getTablepointer(ubyte[] table, ubyte[] flags, int requestedFlag, int insno) { foreach(i, flag; flags) { if(flag != requestedFlag) continue; return table[insno + i * 48]; } throw new UserException(std.string.format("Missing tablepointer %d", requestedFlag)); } int wavetablePointer(int insno) { return getTablepointer(instrumentTable, features.instrumentFlags, 1, insno); } int pulsetablePointer(int insno) { int ptr = getTablepointer(instrumentTable, features.instrumentFlags, 3, insno); if(ptr >= 0x80) return 0; return ptr; } int filtertablePointer(int insno) { return getTablepointer(instrumentTable, features.instrumentFlags, 4, insno); } void seqIterator(void delegate(Sequence s, Element e) dg) { foreach(i, s; seqs) { for(int j = 0; j < s.rows; j++) { Element e = s.data[j]; dg(s, e); } } } void seqIterator(void delegate(int seqno, Sequence s, Element e) dg) { foreach(i, s; seqs) { for(int j = 0; j < s.rows; j++) { Element e = s.data[j]; dg(cast(int)i, s, e); } } } void trackIterator(void delegate(Track t) dg) { for(int sidx = 0; sidx < 32; sidx++) { Tracklist[] subtune = subtunes[sidx]; foreach(voice; subtune) { foreach(track; voice) { dg(track); } } } } void tableIterator(void delegate(Table t) dg) { foreach(idx, table; [ "wave", "cmd", "instr", "chord", "pulse", "filter"]) { dg(tables[table]); } } void setVoicon(shared int[] m) { //setVoicon(m[0], m[1], m[2]); buffer[offsets[Offsets.VOICE]+0] = m[0] ? 0x19 : 0x00; buffer[offsets[Offsets.VOICE]+1] = m[1] ? 0x19 : 0x07; buffer[offsets[Offsets.VOICE]+2] = m[2] ? 0x19 : 0x0e; } int getFreeSequence(int start) { bool seqUsed; subtunes.sync(); for(int seqnum = start; seqnum < MAX_SEQ_NUM; seqnum++) { seqUsed = false; foreach(ist, st; subtunes.subtunes) { foreach(voice; st) { foreach(t; voice) { if(t == seqnum) seqUsed = true; } } } if(!seqUsed) return seqnum; } return -1; } void clearSeqs() { for(int i = 1; i < MAX_SEQ_NUM; i++) { seqs[i].clear(); } subtunes.clearAll(); } void incSubtune() { if(subtune < 31) subtunes.activate(++subtune); } void decSubtune() { if(subtune > 0) subtunes.activate(--subtune); } void generateChordIndex() { int crd, p; for(int i = 0; i < 128; i++) { if(chordTable[i] >= 0x80) { chordIndexTable[crd] = cast(ubyte)p; if(++crd >= 31) throw new Error("Chord index overflow"); p = i + 1; } } chordIndexTable[crd++] = cast(ubyte)(p); } void importData(Song insong) { buffer[0xdfe .. 0xdfe + playerBinary.length] = playerBinary[]; ver = SONG_REVISION; initialize(buffer.dup); // copy tables foreach(idx, table; [ "wave", "cmd", "instr", "chord", "pulse", "filter"]) { tables[table].data[] = insong.tables[table].data; } // sequences foreach(idx, ref seq; insong.seqs) { seqs[idx].data.raw[] = seq.data.raw; seqs[idx].refresh(); } // subtunes subtunes.subtunes[][][] = insong.subtunes.subtunes[][][]; subtunes.syncFromBuffer(); // labels insLabels[] = insong.insLabels[]; title[] = insong.title[]; author[] = insong.author[]; release[] = insong.release[]; // vars clock = insong.clock; multiplier = insong.multiplier; sidModel = insong.sidModel; fppres = insong.fppres; songspeeds = insong.songspeeds[]; speed = songspeeds[0]; // TODO highlight, highlightoffset generateChordIndex(); subtunes.activate(0); } // hack to help sequencer rowcounting Sequence sequence(Track t) { return seqs[t.number]; } void savePatch(string filename, int no) { import std.conv; string insname = std.string.stripRight (to!string(insLabels[no])); int waveptr = wavetablePointer(no); int pulseptr = pulsetablePointer(no); int filtptr = filtertablePointer(no); if(!tWave.isValid(waveptr)) { throw new UserException("Cannot save; instrument is not valid (wavetable does not wrap)."); } if(!tPulse.isValid(pulseptr)) { throw new UserException("Cannot save; pulse is not valid."); } if(!tFilter.isValid(filtptr)) { throw new UserException("Cannot save; filter is not valid."); } auto wp = tWave.getProgram(waveptr); auto pp = tPulse.getProgram(pulseptr); auto fp = tFilter.getProgram(filtptr); // rewrite pointers. TODO: move elsewhere auto instr = tInstr.getInstrument(no); instr[7] = cast(ubyte)wp.offset; // skipping 0-rows since it implies inactive sweep if(pp.offset > 0) instr[5] = cast(ubyte)pp.offset; if(fp.offset > 0) instr[4] = cast(ubyte)fp.offset; string csv = to!string(playerID[0..6]) ~ "`" ~ insname ~ "`" ~ com.util.arr2str(instr) ~ "`" ~ com.util.arr2str(wp.wave1) ~ "`" ~ com.util.arr2str(wp.wave2) ~ "`" ~ (pulseptr > 0 ? com.util.arr2str(pp.data) : "") ~ "`" ~ (filtptr > 0 ? com.util.arr2str(fp.data) : ""); if(filename is null) { filename = com.util.fnClean(insname ~ ".cti"); } std.file.write(filename, csv); } void insertPatch(string filename, int insno) { import std.csv : csvReader; auto conv(string s) { ubyte[] arr = new ubyte[s.length / 2]; for(int i = 0, j = 0; i < s.length; i += 2, j++) { arr[j] = cast(ubyte)com.util.convertHex(s[i .. i + 2]); } return arr; } struct Rec { string playerid, name, def, wave1, wave2, pulse, filt; } string patch = cast(string)std.file.read(filename); auto recs = csvReader!Rec(patch,'`'); foreach(rec; recs) { auto p = new Purge(this); p.deleteInstrument(insno); insertInstrument(Patch(rec.name, conv(rec.def), conv(rec.wave1), conv(rec.wave2), conv(rec.filt), conv(rec.pulse)), insno); if(rec.name.length > 31) rec.name.length = 31; insLabels[insno][] = ' '; insLabels[insno][0..rec.name.length] = rec.name; // break because only 1st row needed (though there should never be more) break; } } private void insertInstrument(Patch patch, int insno) { assert(patch.wave1.length == patch.wave2.length); // check for free space in tables int waveptr = tWave.seekTableEnd(); int pulseptr = tPulse.seekTableEnd() * 4; int filterptr = tFilter.seekTableEnd() * 4; if(patch.wave1.length + waveptr > tWave.wave1.length - 1) throw new UserException("Not enough free rows in wavetable"); if(patch.pulse.length + pulseptr > tPulse.data.length - 4) throw new UserException("Not enough free rows in pulse table"); if(patch.filt.length + filterptr > tFilter.data.length - 4) throw new UserException("Not enough free rows in filter table"); // cram loaded data into tables ubyte[] wave1 = tWave.wave1[waveptr .. waveptr + patch.wave1.length]; ubyte[] wave2 = tWave.wave2[waveptr .. waveptr + patch.wave2.length]; for(int i = 0; i < wave1.length; i++) { if(wave1[i] == 0x7f) wave2[i] += waveptr; } wave1[0..$] = patch.wave1[]; wave2[0..$] = patch.wave2[]; // ---------------------------------------- void fixSweepOffsets(ubyte[] table, int offset) { for(int i = 0; i < table.length; i += 4) { if(table[i + 3] > 0 && table[i + 3] < 0x40) { table[i + 3] += offset; assert(table[i + 3] < 0x40); } } } // insert pulse program if defined if(patch.def[5] > 0) { ubyte[] pulse = tPulse.data[pulseptr .. $]; fixSweepOffsets(pulse, pulseptr + patch.def[5]); tPulse.data[pulseptr .. pulseptr + patch.pulse.length] = patch.pulse[]; for(int i = 0; i < pulse.length - 4; i += 4) { if(pulse[i + 3] > 0 && pulse[i + 3] < 0x40) { pulse[i + 3] += pulseptr / 4 - 1; } } patch.def[5] += pulseptr / 4 - 1; } // insert filter if defined if(patch.def[4] > 0) { ubyte[] filt = tFilter.data[filterptr .. $]; fixSweepOffsets(filt, filterptr + patch.def[4]); tFilter.data[filterptr .. filterptr + patch.filt.length] = patch.filt[]; for(int i = 0; i < filt.length; i += 4) { if(filt[i + 3] > 0 && filt[i + 3] < 0x40) { filt[i + 3] += filterptr / 4 - 1; } } patch.def[4] += filterptr / 4 - 1; } // recalc wrap points for inserted data for(int i = 0; i < wave1.length; i++) { if(wave1[i] == 0x7f) wave2[i] += waveptr; } patch.def[7] += waveptr; for(int i = 0; i < 8; i++) { instrumentTable[i * 48 + insno] = patch.def[i]; } } } CheeseCutter-master/src/ct/build.d000066400000000000000000000215521357241101300173750ustar00rootroot00000000000000/* CheeseCutter v2 (C) Abaddon. Licensed under GNU GPL. */ module ct.build; import ct.base; import ct.dump; import com.cpu; import com.util; import std.stdio; import std.string; import std.conv; import core.stdc.string; import core.stdc.stdlib; import std.array; extern(C) { extern char* acme_assemble(const char*,int*,char*); } static const string playerSource = import("player_v4.acme"); const ubyte[] SIDHEADER = [ 0x50, 0x53, 0x49, 0x44, 0x00, 0x02, 0x00, 0x7c, 0x00, 0x00, 0x10, 0x00, 0x10, 0x03, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x53, 0x77, 0x61, 0x6d, 0x70, 0x20, 0x50, 0x6f, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x68, 0x6f, 0x6d, 0x61, 0x73, 0x20, 0x4d, 0x6f, 0x67, 0x65, 0x6e, 0x73, 0x65, 0x6e, 0x20, 0x28, 0x44, 0x52, 0x41, 0x58, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x30, 0x30, 0x34, 0x20, 0x4d, 0x61, 0x6e, 0x69, 0x61, 0x63, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x4e, 0x6f, 0x69, 0x73, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00 ]; enum { PSID_LOAD_ADDR_OFFSET = 0x08, PSID_INIT_OFFSET = 0x0a, PSID_PLAY_OFFSET = 0x0c, PSID_TITLE_OFFSET = 0x16, PSID_FLAGS_OFFSET = 0x76, PSID_NUM_SONGS = 0x0e, PSID_START_SONG = 0x10, PSID_SPEED_OFFSET = 0x12, // CIA_OFFSET = 0x09, // DIV_COUNTER = 0x1b, PAL_CLOCK = 0x4cc7, PSID_DATA_START = 0x7c } // quick and ugly hack to circumvent D2 phobos weirdness private int paddedStringLength(char[] s, char padchar) { int i; for(i = cast(int)(s.length - 1); i >= 0; i--) { if(s[i] != padchar) return cast(int)(i+1); } return 0; } private char[] assemble(string source) { int length; char[1024] error_message; memset(&error_message, '\0', 1024); char* input = acme_assemble(toStringz(source), &length, &error_message[0]); if(input is null) { string msg = to!string(&error_message[0]); throw new UserException(format("Could not assemble player. Message:\n%s", msg)); } char[] assembled = new char[length]; memcpy(assembled.ptr, input, length); free(input); return assembled; } private ubyte[] generatePSIDHeader(Song insong, ubyte[] data, int initAddress, int playAddress, int defaultSubtune) { /+ SID default tune indicatior starts from value 1... +/ if(defaultSubtune > insong.subtunes.numOf) throw new UserException(format("This song has only %d subtunes", insong.subtunes.numOf)); data = SIDHEADER ~ data; void outstr(char[] s, int offset) { data[offset .. offset + s.length] = cast(ubyte[])s; } data[PSID_TITLE_OFFSET .. PSID_TITLE_OFFSET + 0x20] = '\0'; data[PSID_TITLE_OFFSET + 0x20 .. PSID_TITLE_OFFSET + 0x40] = '\0'; data[PSID_TITLE_OFFSET + 0x40 .. PSID_TITLE_OFFSET + 0x60] = '\0'; // circumventing D2 phobos weirdness char[32] title = insong.title; title[paddedStringLength(title,' ') .. $] = '\0'; char[32] author = insong.author; author[paddedStringLength(author,' ') .. $] = '\0'; char[32] release = insong.release; release[paddedStringLength(release,' ') .. $] = '\0'; outstr(title,PSID_TITLE_OFFSET); outstr(author,PSID_TITLE_OFFSET + 0x20); outstr(release,PSID_TITLE_OFFSET + 0x40); data[PSID_NUM_SONGS + 1] = cast(ubyte)insong.subtunes.numOf; data[PSID_START_SONG + 1] = cast(ubyte)defaultSubtune; if(insong.multiplier > 1) { data[PSID_SPEED_OFFSET .. PSID_SPEED_OFFSET + 4] = 255; } data[PSID_INIT_OFFSET .. PSID_INIT_OFFSET + 2] = cast(ubyte[])[ initAddress >> 8, initAddress & 255 ]; data[PSID_PLAY_OFFSET .. PSID_PLAY_OFFSET + 2] = cast(ubyte[])[ playAddress >> 8, playAddress & 255 ]; int endAddr = cast(int)(initAddress + data.length); if(endAddr > 0xfff9) throw new UserException(format("The relocated tune goes past $fff9 (by $%x bytes).",endAddr-0xfff9)); data[PSID_FLAGS_OFFSET + 1] = cast(ubyte)(0x04 /+ PAL +/ | (insong.sidModel ? 0x20 : 0x10)); return data; } ubyte[] doBuild(Song song, int address, int zpAddress, bool genPSID, int defaultSubtune, bool verbose) { // Valid range for subtunes is 1 - 32. if(!(defaultSubtune >= 1 && defaultSubtune <= ct.base.SUBTUNE_MAX)) throw new UserException(format("Valid range for subtunes is 1 - %d.", ct.base.SUBTUNE_MAX)); if(song.subtunes.numOf == 0) { throw new UserException("No subtunes found"); } // Dump data to asm source string input = dumpOptimized(song, address, zpAddress, genPSID, verbose); if(verbose) writeln("Assembling..."); ubyte[] assembled = cast(ubyte[])assemble(input); if(verbose) writeln(format("Size %d bytes ($%04x-$%04x).", assembled.length - 2, address, address + assembled.length - 2)); return genPSID ? generatePSIDHeader(song, assembled, address, address + 3, defaultSubtune) : assembled; } string dumpOptimized(Song song, int address, int zpAddress, bool genPSID, bool verbose) { string input = playerSource; input ~= dumpData(song); input = setArgumentValue("INSNO", format("%d", song.numInstr+1), input); char[] linkedPlayerID = (new Song()).playerID; if(song.playerID[0..6] != linkedPlayerID[0..6] && verbose) { writeln("Warning: your song uses an old version of the player!\n", "The assembled song may sound different.\nSong player: ", to!string(song.playerID[0..6]), ", linked player: ", to!string(linkedPlayerID[0..6])); } bool chordUsed, swingUsed, filterUsed, vibratoUsed; bool setAttUsed, setDecUsed, setSusUsed, setRelUsed, setVolUsed, setSpeedUsed; bool offsetUsed, slideUpUsed, slideDnUsed, lovibUsed, portaUsed, setADSRUsed; song.seqIterator((Sequence s, Element e) { int val = e.cmd.value; int cmdval = -1; if(val == 0) return; if(val < 0x40) { cmdval = song.superTable[val]; if(cmdval < 1) slideUpUsed = true; else if(cmdval == 1) slideDnUsed = true; else if(cmdval == 2) vibratoUsed = true; else if(cmdval == 3) offsetUsed = true; else if(cmdval == 4) setADSRUsed = true; else if(cmdval == 5) lovibUsed = true; else if(cmdval == 7) portaUsed = true; return; } else if(val < 0x60) return; else if(val < 0x80) filterUsed = true; else if(val < 0xa0) chordUsed = true; else if(val < 0xb0) setAttUsed = true; else if(val < 0xc0) setDecUsed = true; else if(val < 0xd0) setSusUsed = true; else if(val < 0xe0) setRelUsed = true; else if(val < 0xf0) setVolUsed = true; else { if(val == 0xf0 || val == 0xf1) swingUsed = true; setSpeedUsed = true; } }); for(int i = 0; i < song.subtunes.numOf; i++) { if(song.songspeeds[i] < 2) swingUsed = true; } for(int i = 0; i < 48; i++) { if(song.filtertablePointer(i) > 0) filterUsed = true; } if(verbose) { string[] fxdescr = [ "slup", "sldn", "vib", "porta", "adsr", "8x", "offset", "lovib", "Ax", "Bx", "Cx", "Dx", "Ex", "Fx", "swing", "filter" ]; auto fxused = std.array.appender!string(); foreach(idx, used; [slideUpUsed, slideDnUsed, vibratoUsed, portaUsed, setADSRUsed, chordUsed, offsetUsed, lovibUsed, setAttUsed, setDecUsed, setSusUsed, setRelUsed, setVolUsed, setSpeedUsed, swingUsed, filterUsed]) { if(used) fxused.put(fxdescr[idx] ~ " "); } if(fxused.data.length > 0) { writeln("Effects used: " ~ fxused.data); } } void setArgVal(string arg, string val) { input = setArgumentValue(arg, val, input); } input = setArgumentValue("EXPORT", "TRUE", input); if(zpAddress > 0) setArgVal("ZREG", format("$%02X", zpAddress)); setArgVal("INCLUDE_CMD_SLUP", slideUpUsed ? "TRUE" : "FALSE"); setArgVal("INCLUDE_CMD_SLDOWN", slideDnUsed ? "TRUE" : "FALSE"); setArgVal("INCLUDE_CMD_VIBR", vibratoUsed ? "TRUE" : "FALSE"); setArgVal("INCLUDE_CMD_PORTA", portaUsed ? "TRUE" : "FALSE"); setArgVal("INCLUDE_CMD_SET_ADSR", setADSRUsed ? "TRUE" : "FALSE"); setArgVal("INCLUDE_SEQ_SET_CHORD", chordUsed ? "TRUE" : "FALSE"); setArgVal("INCLUDE_CHORD", chordUsed ? "TRUE" : "FALSE"); setArgVal("INCLUDE_CMD_SET_OFFSET", offsetUsed ? "TRUE" : "FALSE"); setArgVal("INCLUDE_CMD_SET_LOVIB", lovibUsed ? "TRUE" : "FALSE"); setArgVal("INCLUDE_SEQ_SET_ATT", setAttUsed ? "TRUE" : "FALSE"); setArgVal("INCLUDE_SEQ_SET_DEC", setDecUsed ? "TRUE" : "FALSE"); setArgVal("INCLUDE_SEQ_SET_SUS", setSusUsed ? "TRUE" : "FALSE"); setArgVal("INCLUDE_SEQ_SET_REL", setRelUsed ? "TRUE" : "FALSE"); setArgVal("INCLUDE_SEQ_SET_VOL", setVolUsed ? "TRUE" : "FALSE"); setArgVal("INCLUDE_SEQ_SET_SPEED", setSpeedUsed ? "TRUE" : "FALSE"); setArgVal("INCLUDE_BREAKSPEED", swingUsed ? "TRUE" : "FALSE"); setArgVal("INCLUDE_FILTER", filterUsed ? "TRUE" : "FALSE"); setArgVal("MULTISPEED", song.multiplier > 1 ? "TRUE" : "FALSE"); if(song.multiplier > 1) { setArgVal("USE_MDRIVER", genPSID ? "TRUE" : "FALSE"); setArgVal("CIA_VALUE", format("$%04x", PAL_CLOCK / song.multiplier)); setArgVal("MULTIPLIER", format("%d", song.multiplier - 1)); } setArgVal("BASEADDRESS", format("$%04x", address), ); return input; } CheeseCutter-master/src/ct/dump.d000066400000000000000000000071421357241101300172420ustar00rootroot00000000000000/* CheeseCutter v2 (C) Abaddon. Licensed under GNU GPL. */ /** date to source dumper. very ugly quick and dirty hack */ module ct.dump; import ct.base; import com.util; import std.string; import std.array; private const string byteOp = "!byte", wordOp = "!word"; string dumpData(Song sng) { auto app = appender!string(); int getHighestUsed(ubyte[] array) { for(int i = cast(int)array.length - 1; i >= 0; i--) { if(array[i] > 0) return cast(int)i; } return 0; } void append(string s) { app.put(s); } void hexdump(ubyte[] buf, int rowlen) { int c; append("\t\t" ~ byteOp ~ " "); foreach(i, b; buf) { append(format("$%02x", b)); c++; if(c >= rowlen) { c = 0; if(i < buf.length - 1) append("\n\t\t" ~ byteOp ~ " "); } else if(i < buf.length - 1) append(","); } append("\n"); } int tablen; ushort[][] trackpointers = new ushort[][sng.subtunes.numOf]; sng.subtunes.activate(0); auto packedTracks = sng.subtunes.compact(); append( "arp1 = *\n"); tablen = getHighestUsed(sng.wave1Table) + 1; hexdump(sng.wave1Table[0 .. tablen], 16); append( "arp2 = *\n"); hexdump(sng.wave2Table[0 .. tablen], 16); append( "filttab = *\n"); hexdump(sng.filterTable[0 .. getHighestUsed(sng.filterTable) + 4], 4); append( "pulstab = *\n"); hexdump(sng.pulseTable[0 .. getHighestUsed(sng.pulseTable) + 4], 4); append( "inst = *\n"); ubyte[512] instab = 0; int maxInsno; sng.seqIterator((Sequence s, Element e) { int insval = e.instr.value; if(insval > 0x2f) return; if(insval > maxInsno) maxInsno = insval; }); for(int i = 0; i < 8; i++) { append( format("\ninst%d = *\n",i)); hexdump(sng.instrumentTable[i * 48 .. i * 48 + (maxInsno+1)], 16); } // cmd ---------------------------------------- tablen = 1; append( "\nseqlo = *\n\t\t!8 "); for(int i = 0; i < sng.numOfSeqs(); i++) { append(format("s%02x", i)); if(i < sng.numOfSeqs() - 1) append(","); } sng.seqIterator((Sequence s, Element e) { int val = e.cmd.value; if(val == 0) return; if(val < 0x40 && val > tablen) { tablen = val; } }); ++tablen; append( "\ncmd1 = *\n"); hexdump(sng.superTable[0..tablen], 16); append( "cmd2 = *\n"); hexdump(sng.superTable[64..64+tablen], 16); append( "cmd3 = *\n"); hexdump(sng.superTable[128..128+tablen], 16); // songsets ------------------------------------ append( "songsets = *\n"); for(int i = 0; i < sng.subtunes.numOf; i++) { append(wordOp ~ "\t"); for(int voice = 0; voice < 3; voice++) { if(voice > 0) append(","); append(" " ~ format("track%d_%d", i, voice)); } append( format("\n\t\t" ~ byteOp ~ " %d, 7\n", sng.songspeeds[i])); } // tracks ------------------------------------- foreach(i, ref subtune; packedTracks) { foreach(j, voice; subtune) { append(format("track%d_%d = *\n", i, j)); hexdump(voice, 16); } } for(int i = 0; i < sng.numOfSeqs(); i++) { append( format("s%02x = *\n", i)); Sequence s = sng.seqs[i]; hexdump(s.compact(), 16); } // chords ------------------------------------- tablen = getHighestUsed(sng.chordTable) + 1; append("\nchord"); if(tablen < 1) tablen = 1; hexdump(sng.chordTable[0..tablen], 16); append("\nchordindex"); int highestChord = 0; sng.seqIterator((Sequence s, Element e) { if(e.cmd.value >= 0x80 && e.cmd.value <= 0x9f && (e.cmd.value & 0x1f) > highestChord) highestChord = e.cmd.value & 0x1f; }); hexdump(sng.chordIndexTable[0..highestChord+1], 16); return app.data; } CheeseCutter-master/src/ct/purge.d000066400000000000000000000305651357241101300174240ustar00rootroot00000000000000/* CheeseCutter v2 (C) Abaddon. Licensed under GNU GPL. */ /* TODO: make all purge funcs public so user can optimize selected tables. requires writing proper initialization for each func so they can be run independently. */ module ct.purge; import ct.base; import com.util; import std.string; import std.stdio; final class Purge { Song song; private { // song.seqIterator does not care if seq is in use or not // therefore purgeSeqs must be done always 1st on purgeAll - unused seqs get cleared bool[0x80] seqUsed; bool[0x30] instrUsed; bool[0x40] super_used, pulse_used, filter_used; bool verbose, initialized; } this(Song song) { this.song = song; } this(Song song, bool v) { verbose = v; this(song); } void purgeAll() { initialize(true); purgeSeqs(); purgeInstruments(); purgeWavetable(); purgeChordtable(); purgeCmdtable(); purgePulseFilter(); initialized = false; } void deleteInstrument(int insno) { initialize(false); int waveptr = song.wavetablePointer(insno); int pulseptr = song.pulsetablePointer(insno); int filtptr = song.filtertablePointer(insno); // ugly hack to not clear defined but unused instruments for(int i = 47; i >= 0; i--) { if(instrUsed[i] == false) instrUsed[i] = !instrIsEmpty(i); } instrUsed[insno] = false; purgeWavetable(); purgePulseFilter(); for(int i = 0; i < 8; i++) { song.instrumentTable[i * 48 + insno] = 0; } song.insLabels[insno][] = ' '; initialized = false; } private: bool instrIsEmpty(int insno) { for(int i = 0; i < 8; i++) { if(song.instrumentTable[i * 48 + insno] != 0) return false; } return true; } // marking unused seqs optional in case you only want to optimize some tables void initialize(bool markUnusedSeqs) { if(initialized) return; if(markUnusedSeqs) { seqUsed[] = false; song.trackIterator((Track t) { seqUsed[t.number] = true; }); } else seqUsed[] = true; instrUsed[] = false; // find out which instruments are in use foreach(i, n; seqUsed) { if(!n) continue; Sequence s = song.seqs[i]; for(int j = 0; j < s.rows; j++) { Element e = s.data[j]; if(!e.instr.hasValue()) continue; instrUsed[e.instr.value] = true; } } initialized = true; } private void purgeSeqs() { int counter; for(int i = 0x7f; i >= 1; i--) { if(!seqUsed[i]) continue; for(int j = 1; j < i; j++) { Sequence s1 = song.seqs[i]; Sequence s2 = song.seqs[j]; if (s1 == s2) { seqUsed[j] = false; replaceTrackvalue(j, i); counter++; } } } explain(format("%d identical seqs found.",counter)); counter = 0; for(int i = 0x7f; i >= 1; i--) { if(!seqUsed[i]) { song.seqs[i].clear(); continue; } for(int j = 1; j < i; j++) { if(!seqUsed[j]) { song.seqs[j].copyFrom(song.seqs[i]); song.seqs[i].clear(); seqUsed[j] = true; seqUsed[i] = false; replaceTrackvalue(i, j); counter++; break; } } } explain(format("%d unused sequences removed.",counter)); } private void purgeInstruments() { int counter; // clear unused for(int i = 0; i < 48; i++) { if(instrUsed[i]) { counter++; continue; } //instrtab[i*8 .. i*8 + 8] = 0; for(int j = 0; j < 8; j++) { song.instrumentTable[i + j * 48] = 0; } song.insLabels[i][] = ' '; } // compact for(int i = 0; i < 48; i++) { if(instrUsed[i]) continue; for(int j = i + 1; j < 48; j++) { if(instrUsed[j]) { for(int cidx = 0; cidx < 8; cidx++) { int o = cidx * 48; song.instrumentTable[i + o] = song.instrumentTable[j + o]; } song.insLabels[i][] = song.insLabels[j][]; replaceInsvalue(j, i); instrUsed[i] = true; instrUsed[j] = false; for(int k = 0; k < 8; k++) { song.instrumentTable[j + k * 48] = 0; } song.insLabels[j][] = ' '; break; } } } explain(format("%d instruments used.", counter)); } private void purgeWavetable() { Song.Chunk[] chunks = song.tWave.getChunks(); for(int i = 0; i < 48; i++) { if(!instrUsed[i]) continue; int ptr = song.wavetablePointer(i); int cell = song.tWave.whichCell(chunks, ptr); if(cell < 0) continue; song.tWave.markCells(chunks, cell); } int numcleared; // compact for(int i = cast(int)(chunks.length - 1); i >= 0; i--) { Song.Chunk chunk = chunks[i]; if(chunk.used) continue; song.tWave.deleteRow(song, chunk.offset, cast(int)chunk.wave1.length); numcleared++; } explain(format("%d wave programs removed.", numcleared)); } private void purgePulseFilter() { int i; pulse_used[] = false; filter_used[] = false; filter_used[0] = true; pulse_used[0] = true; void seekNMark(ref ubyte[] table, bool* usedflags, int pointer) { int pp = pointer; for(;;) { if(usedflags[pp]) break; usedflags[pp] = true; int newptr = table[pp*4 + 3]; if(newptr == 0x7f) break; if(newptr == 0) pp++; else pp = newptr; } } for(i = 0; i < 48; i++) { if(!instrUsed[i]) continue; try { seekNMark(song.pulseTable, &pulse_used[0], song.pulsetablePointer(i)); seekNMark(song.filterTable, &filter_used[0], song.filtertablePointer(i)); } catch(Exception e) { explain(format("Could not purge pulse / filter table: %s", e.toString())); return; } } song.seqIterator((Sequence s, Element e) { if(e.cmd.value >= 0x40 && e.cmd.value < 0x60) seekNMark(song.pulseTable, &pulse_used[0], e.cmd.value - 0x40); if(e.cmd.value >= 0x60 && e.cmd.value < 0x80) seekNMark(song.filterTable, &filter_used[0], e.cmd.value - 0x60); }); for(i = 0; i < 64; i++) { if(!pulse_used[i]) song.pulseTable[i * 4 .. i * 4 + 4] = 0; if(!filter_used[i]) song.filterTable[i * 4 .. i * 4 + 4] = 0; } // compact filter & pulse table. this is EXTREMELY slow. for(i = 0; i < 0x3e; i++) { int seek = i + 1; while(!filter_used[i] && seek < 64) { { filterDeleteRow(song, i); filter_used[i .. $-1] = filter_used[i+1 .. $].dup; } seek++; } } for(i = 0; i < 0x3e; i++) { int seek = i + 1; while(!pulse_used[i] && seek < 64) { { pulseDeleteRow(song, i); pulse_used[i .. $-1] = pulse_used[i+1 .. $].dup; } seek++; } } } private void purgeChordtable() { bool[0x20] chordsUsed; song.seqIterator((Sequence s, Element e) { if(e.cmd.value >= 0x80 && e.cmd.value <= 0x9f) { chordsUsed[e.cmd.value & 0x1f] = true; } }); struct Chunk { ubyte[] data; int oldOffset; } int getidx2(int cmdidx, int idx) { for(int i = idx; i < 128; i++) { if(song.chordTable[i] >= 0x80) return i; } throw new PurgeException(format("Could not find valid chord for value %x", cmdidx)); } song.generateChordIndex(); Chunk[] chunks; chunks ~= Chunk(song.chordTable[0 .. song.chordIndexTable[1]].dup, 0); int tablestart = 1; // TODO: find out if swingtepo is used and purge first chunk too if needed for(int i = tablestart; i < 0x20; i++) { if(chordsUsed[i]) { int idx = song.chordIndexTable[i]; int idx2 = getidx2(i,idx)+1; // FIX: check... might cause problems //int idx2 = song.chordIndexTable[i+1]; assert(idx != 0); if(idx2 == 0) break; ubyte[] chord = song.chordTable[idx .. idx2].dup; chunks ~= Chunk(chord, idx); } else { for(int j = i + 1; j < 0x20; j++) { if(chordsUsed[j]) { int idx = song.chordIndexTable[j]; int idx2 = getidx2(j, idx)+1; replaceCmdColumnvalue(song, 0x80 + j, 0x80 + i); ubyte[] chord = song.chordTable[idx .. idx2].dup; chunks ~= Chunk(chord, idx); chordsUsed[i] = true; chordsUsed[j] = false; break; } } } } int counter; int idx; int np; foreach(chunk; chunks) { if(chunk.data.length == 0) continue; int oldwrap = (chunk.data[$-1] - 0x80) - chunk.oldOffset; assert(chunk.data[$-1] >= 0x80); chunk.data[$-1] = cast(ubyte)(idx + oldwrap + 0x80); idx += chunk.data.length; counter++; } song.chordTable[] = 0; foreach(chunk; chunks) { song.chordTable[np .. np + chunk.data.length] = chunk.data; np += chunk.data.length; } song.generateChordIndex(); explain(format("%d chords used.",counter)); } private void purgeCmdtable() { song.seqIterator((Sequence s, Element e) { if(e.cmd.value == 0) return; if(e.cmd.value < 0x40) super_used[e.cmd.value] = true; }); int counter; for(int i = 1; i < 64; i++) { if(super_used[i]) { counter++; continue; } song.superTable[i] = 0; song.superTable[i+64] = 0; song.superTable[i+128] = 0; for(int j = i + 1; j < 64; j++) { if(super_used[j]) { song.superTable[i] = song.superTable[j]; song.superTable[i+64] = song.superTable[j+64]; song.superTable[i+128] = song.superTable[j+128]; replaceCmdColumnvalue(song, j, i); super_used[i] = true; super_used[j] = false; song.superTable[j] = 0; song.superTable[j+64] = 0; song.superTable[j+128] = 0; break; } } } } void replaceInsvalue(int seek, int repl) { int skipped; song.seqIterator((Sequence s, Element e) { if(!e.instr.hasValue()) return; if(e.instr.value() == seek) e.instr = cast(ubyte)repl; }); } void replaceTrackvalue(int find, int rep) { song.trackIterator((Track t) { if(t.number == find) t.number = cast(ubyte)rep; }); } void explain(string s) { if(verbose) writefln(s); } } // TODO: move to tFilter void filterDeleteRow(Song song, int row) { genericDeleteRow(song, song.filterTable, row); song.seqIterator((Sequence s, Element e) { if(row > 0x1f) return; if(e.cmd.value == 0) return; if(e.cmd.value() >= (0x60 + (row & 0x1f) + 1) && e.cmd.value() < 0x80) e.cmd = cast(ubyte)(e.cmd.value - 1); }); for(int j = 0; j < 48; j++) { int fptr = song.instrumentTable[4 * 48 + j]; if(fptr >= row && fptr < 0x40 && fptr > 0) song.instrumentTable[4 * 48 + j]--; } } // TODO: move to tPulse void pulseDeleteRow(Song song, int row) { genericDeleteRow(song, song.pulseTable, row); song.seqIterator((Sequence s, Element e) { if(row > 0x1f) return; if(e.cmd.value == 0) return; if(e.cmd.value() >= (0x40 + (row & 0x1f) + 1) && e.cmd.value() < 0x60) e.cmd = cast(ubyte)(e.cmd.value - 1); }); for(int j = 0; j < 48; j++) { int pptr = song.instrumentTable[5 * 48 + j]; if(pptr >= row && pptr < 0x40 && pptr > 0) song.instrumentTable[5 * 48 + j]--; } } // TODO: move to tFilter void filterInsertRow(Song song, int row) { genericInsertRow(song, song.filterTable, row); song.seqIterator((Sequence s, Element e) { if(row > 0x1f) return; if(e.cmd.value == 0) return; if(e.cmd.value() >= (0x60 + (row & 0x1f)) && e.cmd.value() < 0x80) e.cmd = cast(ubyte)(e.cmd.value + 1); }); for(int j = 0; j < 48; j++) { int fptr = song.instrumentTable[4 * 48 + j]; if(fptr >= row && fptr < 0x40) song.instrumentTable[4 * 48 + j]++; } } // TODO: move to tPulse void pulseInsertRow(Song song, int row) { genericInsertRow(song, song.pulseTable, row); song.seqIterator((Sequence s, Element e) { if(row > 0x1f) return; if(e.cmd.value == 0) return; if(e.cmd.value() >= (0x40 + (row & 0x1f)) && e.cmd.value() < 0x60) e.cmd = cast(ubyte)(e.cmd.value + 1); }); for(int j = 0; j < 48; j++) { int pptr = song.instrumentTable[5 * 48 + j]; if(pptr >= row && pptr < 0x40 && pptr > 0) song.instrumentTable[5 * 48 + j]++; } } private void replaceCmdColumnvalue(Song song, int seek, int repl) { int skipped; song.seqIterator((Sequence s, Element e) { if(e.cmd.value == 0) return; if(e.cmd.value() == seek) e.cmd = cast(ubyte)repl; }); } // TODO: move to Table private void genericDeleteRow(Song song, ubyte[] table, int row) { assert(row < 64 && row >= 0); int row4 = row * 4; table[row4 .. $ - 4] = table[row4 + 4 .. $].dup; for(int j = 0; j < 64; j++) { int fptr = table[j * 4 + 3]; if(fptr > 0 && fptr < 0x40) { if(fptr >= row) table[j * 4 + 3]--; } } } // TODO: move to Table private void genericInsertRow(Song song, ubyte[] table, int row) { assert(row < 64 && row >= 0); int row4 = row * 4; table[row4 + 4 .. $] = table[row4 .. $ - 4].dup; table[row4 .. row4+4] = 0; for(int j = 0; j < 64; j++) { int fptr = table[j * 4 + 3]; if(fptr > 0 && fptr < 0x40) { if(fptr >= row) table[j * 4 + 3]++; } } } class PurgeException : Exception { this(string msg) { super(msg); } override string toString() { return "Purge error: " ~ msg; } } CheeseCutter-master/src/ct2util.d000066400000000000000000000233451357241101300172600ustar00rootroot00000000000000/* CheeseCutter v2 (C) Abaddon. Licensed under GNU GPL. */ import com.cpu; import com.util; import ct.base; import ct.purge; import ct.dump; import ct.build; import std.stdio; import std.string; import std.conv; import std.file; enum Command { None, ExportPRG, ExportSID, Dump, Import, Init } const string[] exts = [ "", "prg", "sid", "s", "ct", "ct" ]; bool verbose = true; bool noPurge; void explain(string str) { if(verbose) writefln(str); } string defineOutfn(int cmd, string infn) { string name; int r = cast(int)(infn.lastIndexOf('.')); if(r <= 0) name = infn; else name = infn[0 .. infn.lastIndexOf('.')]; return name ~ "." ~ exts[cmd]; } bool doPurge(ref Song song) { if(noPurge) return true; explain("Purging data..."); Purge p = new Purge(song, verbose); try { p.purgeAll(); } catch(PurgeException e) { writeln(e); return false; } return true; } void validate(ref Song song) { explain("Checking validity..."); for(int i = 0; i < song.numInstr; i++) { //ubyte[] instr = song.getInstrument(i); int waveptr = song.wavetablePointer(i); int pulseptr = song.pulsetablePointer(i); int filtptr = song.filtertablePointer(i); if(!song.tWave.isValid(waveptr)) { throw new ValidateException(format("Error: instrument %d is not valid (wavetable does not wrap).", i)); } if(!song.tPulse.isValid(pulseptr)) { throw new ValidateException(format("Cannot save; pulse %d is not valid.", pulseptr)); } if(!song.tFilter.isValid(filtptr)) { throw new ValidateException(format("Cannot save; filter %d is not valid.", filtptr)); } song.seqIterator((int seqno, Sequence s, Element e) { if(e.cmd.value >= 0x80 && e.cmd.value <= 0x9f) { int idx = song.chordIndexTable[e.cmd.value & 0x1f]; for(int i = idx; i < 128; i++) { if(song.chordTable[i] >= 0x80) return; } throw new ValidateException(format("sequence $%02x, could not find end for chord %x. The song has a 8x command pointing to nonexistant chord program.", seqno, e.cmd.value & 0x1f)); } }); } } class ValidateException : Exception { this(string msg) { super(msg); } override string toString() { return "Validation error: " ~ msg; } } int main(string[] args) { int relocAddress = 0x1000, zpAddress = 0; int[] speeds, masks; // these two use PSID ranges (1..32) int defaultTune = 1, singleSubtune = -1; bool outfnDefined = false, infnDefined = false; int command; Song insong; string infn, outfn; string[3] infns; speeds.length = 32; masks.length = 32; void printheader() { enum hdr = "CheeseCutter 2 utilities" ~ com.util.versionInfo; writefln(hdr); writefln("\nUsage: \t%s <-o outfile>",args[0]); writefln("\t%s import <-o outfile>",args[0]); writefln("\t%s init <-o outfile>",args[0]); writefln("\nCommands:"); writefln(" prg Export song (.ct) to PRG file"); writefln(" sid Export song (.ct) to SID file"); writefln(" dump Dump song data to assembler source (BETA)"); writefln(" import Copy data from another song without overwriting the player"); writefln(" init Create a fresh .ct from player binary"); writefln("\nGeneral options:"); writefln(" -o Set output filename (by default gathered from input filename)"); writefln("\nExport options:"); // writefln(" -n Do not purge before exporting/dumping (leaves unused data)"); writefln(" -r Relocate output to address (default = $1000)"); writefln(" -d Set the default subtune (1-" ~ to!string(ct.base.SUBTUNE_MAX) ~ ")"); // writefln(" -s [subtune]:[speed],... Set speeds for subtunes"); // writefln(" -c [subtune]:[voicemask],...Set voice bitmasks for subtunes"); writefln(" -s Export single subtune (1-" ~ to!string(ct.base.SUBTUNE_MAX) ~ ") (disables -d)"); writefln(" -zp Relocate zero page (valid range 2-$fe)"); writefln(" -q Don't output information"); writefln("\nPrefix value options with '0x' or '$' to indicate a hexadecimal value."); } if(args.length < 2) { printheader(); return 0; } try { switch(args[1]) { case "prg", "buildprg": command = Command.ExportPRG; break; case "sid", "build": command = Command.ExportSID; break; case "dump": command = Command.Dump; break; case "import": command = Command.Import; break; case "init": command = Command.Init; break; default: throw new UserException(format("command '%s' not recognized.",args[1])); } int infncounter = 0; if(args.length >= 2) { for(int argp = 2; argp < args.length; argp++) { string nextArg() { if(argp+1 >= args.length || args[argp+1][0] == '-') throw new UserException("Missing value for option '" ~ args[argp] ~"'"); argp++; return args[argp]; } switch(args[argp]) { case "-n": noPurge = true; break; case "-r": if(command != Command.ExportSID && command != Command.ExportPRG) throw new UserException("Option available only with exporting commands."); int r = str2Value2(nextArg()); if(r < 0x200 || r > 0xf900) throw new UserException("-r: reloc address out of range"); relocAddress = cast(ushort)r; break; case "-s": if(command != Command.ExportSID && command != Command.ExportPRG) throw new UserException("Option available only with exporting commands."); //parseList(speeds, nextArg()); int value = str2Value2(nextArg()); if(value < 1 || value > ct.base.SUBTUNE_MAX) throw new UserException(format("Valid range for subtunes is 1 - %d.", ct.base.SUBTUNE_MAX)); singleSubtune = value; break; case "-c": if(command != Command.ExportSID && command != Command.ExportPRG) throw new UserException("Option available only with exporting commands."); parseList(masks, nextArg()); break; case "-d": if(command != Command.ExportSID) throw new UserException("Option available only when exporting to SID."); defaultTune = str2Value2(nextArg()); if(defaultTune < 1 || defaultTune > ct.base.SUBTUNE_MAX) throw new UserException(format("Valid range for subtunes is 1 - %d.", ct.base.SUBTUNE_MAX)); break; case "-z", "-zp": if(command != Command.ExportSID && command != Command.ExportPRG) throw new UserException("Option available only with exporting commands."); zpAddress = str2Value2(nextArg()); if(zpAddress < 2 || zpAddress > 0xfe) { throw new UserException("Valid range for zero page is 2 - $fe"); } break; case "-o": if(outfnDefined) throw new UserException("Output file already defined."); outfn = args[argp+1]; outfnDefined = true; argp++; break; case "-q": verbose = false; break; default: if(args[argp][0] == '-') throw new UserException("Unrecognized option '" ~ args[argp] ~ "'"); if(infnDefined && command != Command.Import) throw new UserException("Input filename already defined. Use -o to define output file."); if(command == Command.Import) { if(infncounter > 1) throw new UserException("Infile & import filename already defined."); infns[infncounter++] = args[argp]; infn = infns[0]; } else infn = args[argp]; infnDefined = true; break; } } } assert(command != Command.None); if(!infnDefined) throw new UserException("Input filename not defined."); if(command == Command.Init && !outfnDefined) { throw new UserException("Command 'init' requires output filename to be defined (option -o)."); } else if(command == Command.Import && !outfnDefined) { throw new UserException("Command 'import' requires output filename to be defined (option -o)."); } if(!outfnDefined) { outfn = defineOutfn(command, infn); } if(!std.file.exists(infn)) throw new UserException(format("File %s does not exist", infn)); explain("Input file: " ~ infn); explain("Output file: " ~ outfn); if(command == Command.ExportSID || command == Command.ExportPRG) { explain(format("Relocating data to $%x", relocAddress)); } switch(command) { case Command.ExportPRG, Command.ExportSID: insong = new Song; insong.open(infn); if(singleSubtune >= 1) { for(int i = 0; i < ct.base.SUBTUNE_MAX; i++) { if(i == singleSubtune - 1) continue; insong.subtunes.clear(i); } insong.subtunes.swap(0, singleSubtune - 1); defaultTune = 1; } if(!doPurge(insong)) { writeln("Aborting"); return -1; } try { validate(insong); } catch(ValidateException e) { writeln(e); writeln("Aborting"); return -1; } ubyte[] data = doBuild(insong, relocAddress, zpAddress, command == Command.ExportSID, defaultTune, verbose); std.file.write(outfn, data); break; case Command.Import: if(infncounter < 2) throw new UserException("Import song not defined."); explain("Importing data from " ~ infns[1]); insong = new Song; insong.open(infns[0]); Song importsong = new Song(); importsong.open(infns[1]); insong.importData(importsong); insong.save(outfn); break; case Command.Dump: insong = new Song; insong.open(infn); doPurge(insong); string dumped = dumpOptimized(insong, 0x1000, 0, true, verbose); string header = format(";;; ACME dump for %s\n\n", infn); std.file.write(outfn, header ~ dumped); break; case Command.Init: insong = new Song(cast(ubyte[])std.file.read(infn)); insong.save(outfn); break; default: assert(0); } } catch(UserException e) { writeln("error: ", e); return -1; } catch(Exception e) { writeln(e); return -1; } scope(failure) { writeln("Aborted."); } scope(success) { explain("Done."); } return 0; } CheeseCutter-master/src/derelict/000077500000000000000000000000001357241101300173115ustar00rootroot00000000000000CheeseCutter-master/src/derelict/sdl/000077500000000000000000000000001357241101300200735ustar00rootroot00000000000000CheeseCutter-master/src/derelict/sdl/image.d000066400000000000000000000200611357241101300213210ustar00rootroot00000000000000/* Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ module derelict.sdl.image; private { import derelict.util.loader; import derelict.util.exception; import derelict.util.compat; import derelict.sdl.sdl; } alias SDL_SetError IMG_SetError; alias SDL_GetError IMG_GetError; enum : Uint8 { SDL_IMAGE_MAJOR_VERSION = 1, SDL_IMAGE_MINOR_VERSION = 2, SDL_IMAGE_PATCHLEVEL = 11, } void SDL_IMAGE_VERSION(SDL_version* X) { X.major = SDL_IMAGE_MAJOR_VERSION; X.minor = SDL_IMAGE_MINOR_VERSION; X.patch = SDL_IMAGE_PATCHLEVEL; } enum { IMG_INIT_JPG = 0x00000001, IMG_INIT_PNG = 0x00000002, IMG_INIT_TIF = 0x00000004, IMG_INIT_WEBP = 0x00000008, } extern(C) { alias int function(int) da_IMG_Init; alias int function() da_IMG_Quit; alias CSDLVERPTR function() da_IMG_Linked_Version; alias SDL_Surface* function(SDL_RWops*, int, char*) da_IMG_LoadTyped_RW; alias SDL_Surface* function(in char*) da_IMG_Load; alias SDL_Surface* function(SDL_RWops*, int) da_IMG_Load_RW; alias int function(int) da_IMG_InvertAlpha; alias int function(SDL_RWops*) da_IMG_isBMP; alias int function(SDL_RWops*) da_IMG_isGIF; alias int function(SDL_RWops*) da_IMG_isJPG; alias int function(SDL_RWops*) da_IMG_isLBM; alias int function(SDL_RWops*) da_IMG_isPCX; alias int function(SDL_RWops*) da_IMG_isPNG; alias int function(SDL_RWops*) da_IMG_isPNM; alias int function(SDL_RWops*) da_IMG_isTIF; alias int function(SDL_RWops*) da_IMG_isXCF; alias int function(SDL_RWops*) da_IMG_isXPM; alias int function(SDL_RWops*) da_IMG_isXV; alias int function(SDL_RWops*) da_IMG_isICO; alias int function(SDL_RWops*) da_IMG_isCUR; alias SDL_Surface* function(SDL_RWops*) da_IMG_LoadBMP_RW; alias SDL_Surface* function(SDL_RWops*) da_IMG_LoadGIF_RW; alias SDL_Surface* function(SDL_RWops*) da_IMG_LoadJPG_RW; alias SDL_Surface* function(SDL_RWops*) da_IMG_LoadLBM_RW; alias SDL_Surface* function(SDL_RWops*) da_IMG_LoadPCX_RW; alias SDL_Surface* function(SDL_RWops*) da_IMG_LoadPNG_RW; alias SDL_Surface* function(SDL_RWops*) da_IMG_LoadPNM_RW; alias SDL_Surface* function(SDL_RWops*) da_IMG_LoadTGA_RW; alias SDL_Surface* function(SDL_RWops*) da_IMG_LoadTIF_RW; alias SDL_Surface* function(SDL_RWops*) da_IMG_LoadXCF_RW; alias SDL_Surface* function(SDL_RWops*) da_IMG_LoadXPM_RW; alias SDL_Surface* function(SDL_RWops*) da_IMG_LoadXV_RW; alias SDL_Surface* function(SDL_RWops*) da_IMG_LoadICO_RW; alias SDL_Surface* function(SDL_RWops*) da_IMG_LoadCUR_RW; alias SDL_Surface* function(char**) da_IMG_ReadXPMFromArray; } mixin(gsharedString!() ~ " da_IMG_Init IMG_Init; da_IMG_Quit IMG_Quit; da_IMG_Linked_Version IMG_Linked_Version; da_IMG_LoadTyped_RW IMG_LoadTyped_RW; da_IMG_Load IMG_Load; da_IMG_Load_RW IMG_Load_RW; da_IMG_InvertAlpha IMG_InvertAlpha; da_IMG_isBMP IMG_isBMP; da_IMG_isGIF IMG_isGIF; da_IMG_isJPG IMG_isJPG; da_IMG_isLBM IMG_isLBM; da_IMG_isPCX IMG_isPCX; da_IMG_isPNG IMG_isPNG; da_IMG_isPNM IMG_isPNM; da_IMG_isTIF IMG_isTIF; da_IMG_isXCF IMG_isXCF; da_IMG_isXPM IMG_isXPM; da_IMG_isXV IMG_isXV; da_IMG_isICO IMG_isICO; da_IMG_isCUR IMG_isCUR; da_IMG_LoadBMP_RW IMG_LoadBMP_RW; da_IMG_LoadGIF_RW IMG_LoadGIF_RW; da_IMG_LoadJPG_RW IMG_LoadJPG_RW; da_IMG_LoadLBM_RW IMG_LoadLBM_RW; da_IMG_LoadPCX_RW IMG_LoadPCX_RW; da_IMG_LoadPNG_RW IMG_LoadPNG_RW; da_IMG_LoadPNM_RW IMG_LoadPNM_RW; da_IMG_LoadTGA_RW IMG_LoadTGA_RW; da_IMG_LoadTIF_RW IMG_LoadTIF_RW; da_IMG_LoadXCF_RW IMG_LoadXCF_RW; da_IMG_LoadXPM_RW IMG_LoadXPM_RW; da_IMG_LoadXV_RW IMG_LoadXV_RW; da_IMG_LoadICO_RW IMG_LoadICO_RW; da_IMG_LoadCUR_RW IMG_LoadCUR_RW; da_IMG_ReadXPMFromArray IMG_ReadXPMFromArray; "); class DerelictSDLImageLoader : SharedLibLoader { public: this() { super( "SDL_image.dll", "libSDL_image.so, libSDL_image-1.2.so, libSDL_image-1.2.so.0", "../Frameworks/SDL_image.framework/SDL_image, /Library/Frameworks/SDL_image.framework/SDL_image, /System/Library/Frameworks/SDL_image.framework/SDL_image" ); } protected: override void loadSymbols() { if(!DerelictSDL.isLoaded) { throw new SharedLibLoadException("DerelictSDL must be loaded before attempting to load DerelictSDLImage!"); } bindFunc(cast(void**)&IMG_Init, "IMG_Init"); bindFunc(cast(void**)&IMG_Quit, "IMG_Quit"); bindFunc(cast(void**)&IMG_Linked_Version, "IMG_Linked_Version"); bindFunc(cast(void**)&IMG_LoadTyped_RW, "IMG_LoadTyped_RW"); bindFunc(cast(void**)&IMG_Load, "IMG_Load"); bindFunc(cast(void**)&IMG_Load_RW, "IMG_Load_RW"); bindFunc(cast(void**)&IMG_InvertAlpha, "IMG_InvertAlpha"); bindFunc(cast(void**)&IMG_isBMP, "IMG_isBMP"); bindFunc(cast(void**)&IMG_isGIF, "IMG_isGIF"); bindFunc(cast(void**)&IMG_isJPG, "IMG_isJPG"); bindFunc(cast(void**)&IMG_isLBM, "IMG_isLBM"); bindFunc(cast(void**)&IMG_isPCX, "IMG_isPCX"); bindFunc(cast(void**)&IMG_isPNG, "IMG_isPNG"); bindFunc(cast(void**)&IMG_isPNM, "IMG_isPNM"); bindFunc(cast(void**)&IMG_isTIF, "IMG_isTIF"); bindFunc(cast(void**)&IMG_isXCF, "IMG_isXCF"); bindFunc(cast(void**)&IMG_isXPM, "IMG_isXPM"); bindFunc(cast(void**)&IMG_isXV, "IMG_isXV"); bindFunc(cast(void**)&IMG_isICO, "IMG_isICO"); bindFunc(cast(void**)&IMG_isCUR, "IMG_isCUR"); bindFunc(cast(void**)&IMG_LoadBMP_RW, "IMG_LoadBMP_RW"); bindFunc(cast(void**)&IMG_LoadGIF_RW, "IMG_LoadGIF_RW"); bindFunc(cast(void**)&IMG_LoadJPG_RW, "IMG_LoadJPG_RW"); bindFunc(cast(void**)&IMG_LoadLBM_RW, "IMG_LoadLBM_RW"); bindFunc(cast(void**)&IMG_LoadPCX_RW, "IMG_LoadPCX_RW"); bindFunc(cast(void**)&IMG_LoadPNG_RW, "IMG_LoadPNG_RW"); bindFunc(cast(void**)&IMG_LoadPNM_RW, "IMG_LoadPNM_RW"); bindFunc(cast(void**)&IMG_LoadTGA_RW, "IMG_LoadTGA_RW"); bindFunc(cast(void**)&IMG_LoadTIF_RW, "IMG_LoadTIF_RW"); bindFunc(cast(void**)&IMG_LoadXCF_RW, "IMG_LoadXCF_RW"); bindFunc(cast(void**)&IMG_LoadXPM_RW, "IMG_LoadXPM_RW"); bindFunc(cast(void**)&IMG_LoadXV_RW, "IMG_LoadXV_RW"); bindFunc(cast(void**)&IMG_LoadICO_RW, "IMG_LoadICO_RW"); bindFunc(cast(void**)&IMG_LoadCUR_RW, "IMG_LoadCUR_RW"); bindFunc(cast(void**)&IMG_ReadXPMFromArray, "IMG_ReadXPMFromArray"); } } DerelictSDLImageLoader DerelictSDLImage; static this() { DerelictSDLImage = new DerelictSDLImageLoader(); } static ~this() { if(SharedLibLoader.isAutoUnloadEnabled()) DerelictSDLImage.unload(); }CheeseCutter-master/src/derelict/sdl/macinit/000077500000000000000000000000001357241101300215175ustar00rootroot00000000000000CheeseCutter-master/src/derelict/sdl/macinit/CoreFoundation.d000066400000000000000000000063661357241101300246160ustar00rootroot00000000000000/* Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ module derelict.sdl.macinit.CoreFoundation; version(DigitalMars) version(OSX) version = darwin; version (darwin): import derelict.util.compat; import derelict.util.loader; package: // CFBase types private struct __CFAllocator; alias __CFAllocator* CFAllocatorRef; alias int CFIndex; alias /*const*/ void* CFTypeRef; // CFBundle types private alias void* __CFBundle; alias __CFBundle *CFBundleRef; // CFDictionary types; private alias void* __CFDictionary; alias __CFDictionary* CFDictionaryRef; // CFURL types; private alias void* __CFURL; alias __CFURL* CFURLRef; extern (C) { mixin(gsharedString!() ~ " // CFBase bindings from the CoreFoundation framework void function(CFTypeRef cf) CFRelease; // CFBundle bindings from the CoreFoundation framework CFDictionaryRef function(CFBundleRef bundle) CFBundleGetInfoDictionary; CFBundleRef function() CFBundleGetMainBundle; CFURLRef function(CFBundleRef bundle) CFBundleCopyBundleURL; // CFURL bindings from the CoreFoundation framework CFURLRef function(CFAllocatorRef allocator, CFURLRef url) CFURLCreateCopyDeletingLastPathComponent; bool function(CFURLRef url, bool resolveAgainstBase, ubyte* buffer, CFIndex maxBufLen) CFURLGetFileSystemRepresentation;"); } void load (void delegate(void**, string, bool doThrow) bindFunc) { bindFunc(cast(void**)&CFRelease, "CFRelease", true); bindFunc(cast(void**)&CFBundleGetInfoDictionary, "CFBundleGetInfoDictionary", true); bindFunc(cast(void**)&CFBundleGetMainBundle, "CFBundleGetMainBundle", true); bindFunc(cast(void**)&CFBundleCopyBundleURL, "CFBundleCopyBundleURL", true); bindFunc(cast(void**)&CFURLCreateCopyDeletingLastPathComponent, "CFURLCreateCopyDeletingLastPathComponent", true); bindFunc(cast(void**)&CFURLGetFileSystemRepresentation, "CFURLGetFileSystemRepresentation", true); }CheeseCutter-master/src/derelict/sdl/macinit/DerelictSDLMacLoader.d000066400000000000000000000045561357241101300255440ustar00rootroot00000000000000/* Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ module derelict.sdl.macinit.DerelictSDLMacLoader; version(DigitalMars) version(OSX) version = darwin; version (darwin): import CoreFoundation = derelict.sdl.macinit.CoreFoundation; import derelict.util.loader; import NSZone = derelict.sdl.macinit.NSZone; import runtime = derelict.sdl.macinit.runtime; private class DerelictSDLMacLoader : SharedLibLoader { private this () { super("", "", "/System/Library/Frameworks/Cocoa.framework/Cocoa, /System/Library/Frameworks/Foundation.framework/Foundation, /System/Library/Frameworks/CoreFoundation.framework/CoreFoundation,"); } protected override void loadSymbols () { CoreFoundation.load(&bindFunc); NSZone.load(&bindFunc); runtime.load(&bindFunc); } } package: DerelictSDLMacLoader DerelictSDLMac; static this () { DerelictSDLMac = new DerelictSDLMacLoader(); DerelictSDLMac.load(); } void unload () { DerelictSDLMac.unload(); } CheeseCutter-master/src/derelict/sdl/macinit/ID.d000066400000000000000000000032111357241101300221550ustar00rootroot00000000000000/* Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ module derelict.sdl.macinit.ID; version(DigitalMars) version(OSX) version = darwin; version (darwin): import derelict.sdl.macinit.runtime; package: class ID { id id_; this () { id_ = null; } this (id id_) { this.id_ = id_; } }CheeseCutter-master/src/derelict/sdl/macinit/MacTypes.d000066400000000000000000000107321357241101300234140ustar00rootroot00000000000000/* Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ module derelict.sdl.macinit.MacTypes; version(DigitalMars) version(OSX) version = darwin; version (darwin): package: /******************************************************************************** Base integer types for all target OS's and CPU's UInt8 8-bit unsigned integer SInt8 8-bit signed integer UInt16 16-bit uinteger SInt16 16-bit signed integer UInt32 32-bit uinteger SInt32 32-bit signed integer UInt64 64-bit uinteger SInt64 64-bit integer *********************************************************************************/ alias ubyte UInt8; alias byte SInt8; alias ushort UInt16; alias short SInt16; alias uint UInt32; alias int SInt32; alias ulong UInt64; alias long SInt64; alias byte uint8_t; /******************************************************************************** Higher level basic types OSErr 16-bit result error code OSStatus 32-bit result error code LogicalAddress Address in the clients virtual address space ConstLogicalAddress Address in the clients virtual address space that will only be read PhysicalAddress Real address as used on the hardware bus BytePtr Pointer to an array of bytes ByteCount The size of an array of bytes ByteOffset An offset into an array of bytes ItemCount 32-bit iteration count OptionBits Standard 32-bit set of bit flags PBVersion ? Duration 32-bit millisecond timer for drivers AbsoluteTime 64-bit clock ScriptCode A particular set of written characters (e.g. Roman vs Cyrillic) and their encoding LangCode A particular language (e.g. English), as represented using a particular ScriptCode RegionCode Designates a language as used in a particular region (e.g. British vs American English) together with other region-dependent characteristics (e.g. date format) FourCharCode A 32-bit value made by packing four 1 byte characters together OSType A FourCharCode used in the OS and file system (e.g. creator) ResType A FourCharCode used to tag resources (e.g. 'DLOG') *********************************************************************************/ alias SInt16 OSErr; alias SInt32 OSStatus; alias void* LogicalAddress; alias /*const*/void* ConstLogicalAddress; alias void* PhysicalAddress; alias UInt8* BytePtr; alias uint ByteCount; alias uint ByteOffset; alias SInt32 Duration; alias UnsignedWide AbsoluteTime; alias UInt32 OptionBits; alias uint ItemCount; alias UInt32 PBVersion; alias SInt16 ScriptCode; alias SInt16 LangCode; alias SInt16 RegionCode; alias UInt32 FourCharCode; alias FourCharCode OSType; alias FourCharCode ResType; alias OSType* OSTypePtr; alias ResType* ResTypePtr; struct UnsignedWide { uint hi; uint lo; } struct ProcessSerialNumber { uint highLongOfPSN; uint lowLongOfPSN; } alias ProcessSerialNumber * ProcessSerialNumberPtr;CheeseCutter-master/src/derelict/sdl/macinit/NSApplication.d000066400000000000000000000066601357241101300244000ustar00rootroot00000000000000/* Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ module derelict.sdl.macinit.NSApplication; version(DigitalMars) version(OSX) version = darwin; version (darwin): import derelict.sdl.macinit.ID; import derelict.sdl.macinit.NSMenu; import derelict.sdl.macinit.NSObject; import derelict.sdl.macinit.runtime; import derelict.sdl.macinit.selectors; import derelict.sdl.macinit.string; import derelict.util.compat; import derelict.util.loader; package: NSApplication NSApp; static this () { NSApp = NSApplication.sharedApplication; } class NSApplication : NSObject { this () { id_ = null; } this (id id_) { this.id_ = id_; } static NSApplication alloc () { id result = objc_msgSend(cast(id)class_, sel_alloc); return result ? new NSApplication(result) : null; } static Class class_ () { return cast(Class) objc_getClass!(this.stringof); } NSApplication init () { id result = objc_msgSend(this.id_, sel_init); return result ? this : null; } public static NSApplication sharedApplication () { id result = objc_msgSend(class_NSApplication, sel_sharedApplication); return result ? new NSApplication(result) : null; } NSMenu mainMenu () { id result = objc_msgSend(this.id_, sel_mainMenu); return result ? new NSMenu(result) : null; } void setAppleMenu (NSMenu menu) { objc_msgSend(this.id_, sel_setAppleMenu, menu ? menu.id_ : null); } void setWindowsMenu (NSMenu menu) { objc_msgSend(this.id_, sel_setWindowsMenu, menu ? menu.id_ : null); } void setMainMenu (NSMenu menu) { objc_msgSend(this.id_, sel_setMainMenu, menu ? menu.id_ : null); } void setDelegate (ID object) { objc_msgSend(this.id_, sel_setDelegate, object ? object.id_ : null); } void run () { objc_msgSend(this.id_, sel_run); } void stop (ID sender) { objc_msgSend(this.id_, sel_stop, sender ? sender.id_ : null); } }CheeseCutter-master/src/derelict/sdl/macinit/NSArray.d000066400000000000000000000046511357241101300232110ustar00rootroot00000000000000/* Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ module derelict.sdl.macinit.NSArray; version(DigitalMars) version(OSX) version = darwin; version (darwin): import derelict.sdl.macinit.ID; import derelict.sdl.macinit.NSEnumerator; import derelict.sdl.macinit.NSObject; import derelict.sdl.macinit.runtime; import derelict.sdl.macinit.selectors; import derelict.sdl.macinit.string; import derelict.util.compat; package: class NSArray : NSObject { this () { id_ = null; } this (id id_) { this.id_ = id_; } static NSArray alloc () { id result = objc_msgSend(cast(id)class_, sel_alloc); return result ? new NSArray(result) : null; } static Class class_ () { return cast(Class) objc_getClass!(this.stringof); } NSArray init () { id result = objc_msgSend(this.id_, sel_init); return result ? this : null; } NSEnumerator objectEnumerator () { id result = objc_msgSend(this.id_, sel_objectEnumerator); return result ? new NSEnumerator(result) : null; } }CheeseCutter-master/src/derelict/sdl/macinit/NSAutoreleasePool.d000066400000000000000000000045221357241101300252330ustar00rootroot00000000000000/* Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ module derelict.sdl.macinit.NSAutoreleasePool; version(DigitalMars) version(OSX) version = darwin; version (darwin): import derelict.sdl.macinit.ID; import derelict.sdl.macinit.NSObject; import derelict.sdl.macinit.runtime; import derelict.sdl.macinit.selectors; import derelict.sdl.macinit.string; import derelict.util.compat; package: class NSAutoreleasePool : NSObject { this () { id_ = null; } this (id id_) { this.id_ = id_; } static NSAutoreleasePool alloc () { id result = objc_msgSend(cast(id)class_, sel_alloc); return result ? new NSAutoreleasePool(result) : null; } static Class class_ () { return cast(Class) objc_getClass!(this.stringof); } NSAutoreleasePool init () { id result = objc_msgSend(this.id_, sel_init); return result ? this : null; } void release () { objc_msgSend(this.id_, sel_release); } } CheeseCutter-master/src/derelict/sdl/macinit/NSDictionary.d000066400000000000000000000046271357241101300242430ustar00rootroot00000000000000/* Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ module derelict.sdl.macinit.NSDictionary; version(DigitalMars) version(OSX) version = darwin; version (darwin): import derelict.sdl.macinit.ID; import derelict.sdl.macinit.NSObject; import derelict.sdl.macinit.runtime; import derelict.sdl.macinit.selectors; import derelict.sdl.macinit.string; import derelict.util.compat; package: class NSDictionary : NSObject { this () { id_ = null; } this (id id_) { this.id_ = id_; } static NSDictionary alloc () { id result = objc_msgSend(cast(id)class_, sel_alloc); return result ? new NSDictionary(result) : null; } static Class class_ () { return cast(Class) objc_getClass!(this.stringof); } NSDictionary init () { id result = objc_msgSend(this.id_, sel_init); return result ? this : null; } ID objectForKey (ID key) { id result = objc_msgSend(this.id_, sel_objectForKey, key ? key.id_ : null); return result ? new ID(result) : null; } }CheeseCutter-master/src/derelict/sdl/macinit/NSEnumerator.d000066400000000000000000000045671357241101300242620ustar00rootroot00000000000000/* Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ module derelict.sdl.macinit.NSEnumerator; version(DigitalMars) version(OSX) version = darwin; version (darwin): import derelict.sdl.macinit.ID; import derelict.sdl.macinit.NSObject; import derelict.sdl.macinit.runtime; import derelict.sdl.macinit.selectors; import derelict.sdl.macinit.string; import derelict.util.compat; package: class NSEnumerator : NSObject { this () { id_ = null; } this (id id_) { this.id_ = id_; } static NSEnumerator alloc () { id result = objc_msgSend(cast(id)class_, sel_alloc); return result ? new NSEnumerator(result) : null; } static Class class_ () { return cast(Class) objc_getClass!(this.stringof); } NSEnumerator init () { id result = objc_msgSend(this.id_, sel_init); return result ? this : null; } ID nextObject () { id result = objc_msgSend(this.id_, sel_nextObject); return result ? new ID(result) : null; } }CheeseCutter-master/src/derelict/sdl/macinit/NSEvent.d000066400000000000000000000034361357241101300232140ustar00rootroot00000000000000/* Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ module derelict.sdl.macinit.NSEvent; version(DigitalMars) version(OSX) version = darwin; version(darwin): enum { NSAlphaShiftKeyMask = 1 << 16, NSShiftKeyMask = 1 << 17, NSControlKeyMask = 1 << 18, NSAlternateKeyMask = 1 << 19, NSCommandKeyMask = 1 << 20, NSNumericPadKeyMask = 1 << 21, NSHelpKeyMask = 1 << 22, NSFunctionKeyMask = 1 << 23, NSDeviceIndependentModifierFlagsMask = 0xffff0000U }CheeseCutter-master/src/derelict/sdl/macinit/NSGeometry.d000066400000000000000000000040031357241101300237150ustar00rootroot00000000000000/* Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ module derelict.sdl.macinit.NSGeometry; version(DigitalMars) version(OSX) version = darwin; version (darwin): package: static if ((void*).sizeof > int.sizeof) // 64bit { alias long NSInteger; alias ulong NSUInteger; } else { alias int NSInteger; alias uint NSUInteger; } static if ((void*).sizeof > int.sizeof) // 64bit alias double CGFloat; else alias float CGFloat; struct NSPoint { CGFloat x; CGFloat y; } struct NSRange { NSUInteger location; NSUInteger length; } struct NSRect { NSPoint origin; NSSize size; } struct NSSize { CGFloat width; CGFloat height; } CheeseCutter-master/src/derelict/sdl/macinit/NSMenu.d000066400000000000000000000066721357241101300230440ustar00rootroot00000000000000/* Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ module derelict.sdl.macinit.NSMenu; version(DigitalMars) version(OSX) version = darwin; version (darwin): import derelict.sdl.macinit.ID; import derelict.sdl.macinit.NSArray; import derelict.sdl.macinit.NSMenuItem; import derelict.sdl.macinit.NSObject; import derelict.sdl.macinit.NSString; import derelict.sdl.macinit.runtime; import derelict.sdl.macinit.selectors; import derelict.sdl.macinit.string; import derelict.util.compat; package: class NSMenu : NSObject { this () { id_ = null; } this (id id_) { this.id_ = id_; } static NSMenu alloc () { id result = objc_msgSend(cast(id)class_, sel_alloc); return result ? new NSMenu(result) : null; } static Class class_ () { return cast(Class) objc_getClass!(this.stringof); } NSMenu init () { id result = objc_msgSend(this.id_, sel_init); return result ? this : null; } NSString title () { id result = objc_msgSend(this.id_, sel_title); return result ? new NSString(result) : null; } NSMenu initWithTitle (NSString aTitle) { id result = objc_msgSend(this.id_, sel_initWithTitle, aTitle ? aTitle.id_ : null); return result ? new NSMenu(result) : null; } void setTitle (NSString str) { objc_msgSend(this.id_, sel_setTitle, str ? str.id_ : null); } NSArray itemArray () { id result = objc_msgSend(this.id_, sel_itemArray); return result ? new NSArray(result) : null; } void sizeToFit () { objc_msgSend(this.id_, sel_sizeToFit); } NSMenuItem addItemWithTitle (NSString str, SEL selector, NSString keyEquiv) { id result = objc_msgSend(this.id_, sel_addItemWithTitle_action_keyEquivalent, str ? str.id_ : null, selector, keyEquiv ? keyEquiv.id_ : null); return result ? new NSMenuItem(result) : null; } void addItem (NSMenuItem newItem) { objc_msgSend(this.id_, sel_addItem, newItem ? newItem.id_ : null); } }CheeseCutter-master/src/derelict/sdl/macinit/NSMenuItem.d000066400000000000000000000071421357241101300236540ustar00rootroot00000000000000/* Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ module derelict.sdl.macinit.NSMenuItem; version(DigitalMars) version(OSX) version = darwin; version (darwin): import derelict.sdl.macinit.ID; import derelict.sdl.macinit.NSGeometry; import derelict.sdl.macinit.NSMenu; import derelict.sdl.macinit.NSObject; import derelict.sdl.macinit.NSString; import derelict.sdl.macinit.runtime; import derelict.sdl.macinit.selectors; import derelict.sdl.macinit.string; import derelict.util.compat; package: class NSMenuItem : NSObject { this () { id_ = null; } this (id id_) { this.id_ = id_; } static NSMenuItem alloc () { id result = objc_msgSend(cast(id)class_, sel_alloc); return result ? new NSMenuItem(result) : null; } static Class class_ () { return cast(Class) objc_getClass!(this.stringof); } NSMenuItem init () { id result = objc_msgSend(this.id_, sel_init); return result ? this : null; } static NSMenuItem separatorItem () { id result = objc_msgSend(class_NSMenuItem, sel_separatorItem); return result ? new NSMenuItem(result) : null; } NSMenuItem initWithTitle (NSString itemName, SEL anAction, NSString charCode) { id result = objc_msgSend(this.id_, sel_initWithTitle_action_keyEquivalent, itemName ? itemName.id_ : null, anAction, charCode ? charCode.id_ : null); return result ? new NSMenuItem(result) : null; } NSString title () { id result = objc_msgSend(this.id_, sel_title); return result ? new NSString(result) : null; } void setTitle (NSString str) { objc_msgSend(this.id_, sel_setTitle, str ? str.id_ : null); } bool hasSubmenu () { return objc_msgSend(this.id_, sel_hasSubmenu) !is null; } NSMenu submenu () { id result = objc_msgSend(this.id_, sel_submenu); return result ? new NSMenu(result) : null; } void setKeyEquivalentModifierMask (NSUInteger mask) { objc_msgSend(this.id_, sel_setKeyEquivalentModifierMask, mask); } void setSubmenu (NSMenu submenu) { objc_msgSend(this.id_, sel_setSubmenu, submenu ? submenu.id_ : null); } }CheeseCutter-master/src/derelict/sdl/macinit/NSNotification.d000066400000000000000000000043561357241101300245630ustar00rootroot00000000000000/* Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ module derelict.sdl.macinit.NSNotification; version(DigitalMars) version(OSX) version = darwin; version (darwin): import derelict.sdl.macinit.ID; import derelict.sdl.macinit.NSObject; import derelict.sdl.macinit.runtime; import derelict.sdl.macinit.selectors; import derelict.sdl.macinit.string; import derelict.util.compat; package: class NSNotification : NSObject { this () { id_ = null; } this (id id_) { this.id_ = id_; } static NSNotification alloc () { id result = objc_msgSend(cast(id)class_, sel_alloc); return result ? new NSNotification(result) : null; } static Class class_ () { return cast(Class) objc_getClass!(this.stringof); } NSNotification init () { id result = objc_msgSend(this.id_, sel_init); return result ? this : null; } }CheeseCutter-master/src/derelict/sdl/macinit/NSObject.d000066400000000000000000000045621357241101300233420ustar00rootroot00000000000000/* Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ module derelict.sdl.macinit.NSObject; version(DigitalMars) version(OSX) version = darwin; version (darwin): import derelict.sdl.macinit.ID; import derelict.sdl.macinit.runtime; import derelict.sdl.macinit.selectors; import derelict.sdl.macinit.string; import derelict.util.compat; package: class NSObject : ID { this () { id_ = null; } this (id id_) { this.id_ = id_; } static NSObject alloc () { id result = objc_msgSend(cast(id)class_, sel_alloc); return result ? new NSObject(result) : null; } static Class class_ () { return cast(Class) objc_getClass!(this.stringof); } static void poseAsClass (Class aClass) { objc_msgSend(class_NSObject, sel_poseAsClass, aClass); } NSObject init () { id result = objc_msgSend(this.id_, sel_init); return result ? this : null; } void release () { objc_msgSend(this.id_, sel_release); } }CheeseCutter-master/src/derelict/sdl/macinit/NSProcessInfo.d000066400000000000000000000051601357241101300243610ustar00rootroot00000000000000/* Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ module derelict.sdl.macinit.NSProcessInfo; version(DigitalMars) version(OSX) version = darwin; version (darwin): import derelict.sdl.macinit.ID; import derelict.sdl.macinit.NSObject; import derelict.sdl.macinit.NSString; import derelict.sdl.macinit.runtime; import derelict.sdl.macinit.selectors; import derelict.sdl.macinit.string; import derelict.util.compat; package: class NSProcessInfo : NSObject { this () { id_ = null; } this (id id_) { this.id_ = id_; } static NSProcessInfo alloc () { id result = objc_msgSend(cast(id)class_, sel_alloc); return result ? new NSProcessInfo(result) : null; } static Class class_ () { return cast(Class) objc_getClass!(this.stringof); } NSProcessInfo init () { id result = objc_msgSend(this.id_, sel_init); return result ? this : null; } static NSProcessInfo processInfo () { id result = objc_msgSend(class_NSProcessInfo, sel_processInfo); return result ? new NSProcessInfo(result) : null; } NSString processName () { id result = objc_msgSend(this.id_, sel_processName); return result ? new NSString(result) : null; } } CheeseCutter-master/src/derelict/sdl/macinit/NSString.d000066400000000000000000000121601357241101300233730ustar00rootroot00000000000000/* Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ module derelict.sdl.macinit.NSString; version(DigitalMars) version(OSX) version = darwin; version (darwin): version (Tango) { import tango.text.convert.Utf : toString16; import tango.stdc.stringz : toString16z; } else import std.utf : toUTF16z; import derelict.sdl.macinit.ID; import derelict.sdl.macinit.NSGeometry; import derelict.sdl.macinit.NSObject; import derelict.sdl.macinit.NSZone; import derelict.sdl.macinit.runtime; import derelict.sdl.macinit.selectors; import derelict.sdl.macinit.string; import derelict.util.compat; package: class NSString : NSObject { this () { id_ = null; } this (id id_) { this.id_ = id_; } static NSString alloc () { id result = objc_msgSend(cast(id)class_, sel_alloc); return result ? new NSString(result) : null; } static Class class_ () { return cast(Class) objc_getClass!(this.stringof); } NSString init () { id result = objc_msgSend(this.id_, sel_init); return result ? this : null; } static NSString stringWith (string str) { version (Tango) id result = objc_msgSend(class_NSString, sel_stringWithCharacters_length, toString16z(str.toString16()), str.length); else id result = objc_msgSend(class_NSString, sel_stringWithCharacters_length, str.toUTF16z(), str.length); return result !is null ? new NSString(result) : null; } static NSString opAssign (string str) { return stringWith(str); } NSUInteger length () { return cast(NSUInteger) objc_msgSend(this.id_, sel_length); } /*const*/ char* UTF8String () { return cast(/*const*/ char*) objc_msgSend(this.id_, sel_UTF8String); } void getCharacters (wchar* buffer, NSRange range) { objc_msgSend(this.id_, sel_getCharacters_range, buffer, range); } NSString stringWithCharacters (/*const*/ wchar* chars, NSUInteger length) { id result = objc_msgSend(this.id_, sel_stringWithCharacters_length, chars, length); return result ? new NSString(result) : null; } NSRange rangeOfString (NSString aString) { return *cast(NSRange*) objc_msgSend(this.id_, sel_rangeOfString, aString ? aString.id_ : null); } NSString stringByAppendingString (NSString aString) { id result = objc_msgSend(this.id_, sel_stringByAppendingString, aString ? aString.id_ : null); return result ? new NSString(result) : null; } NSString stringByReplacingRange (NSRange aRange, NSString str) { size_t bufferSize; size_t selfLen = this.length; size_t aStringLen = str.length; wchar* buffer; NSRange localRange; NSString result; bufferSize = selfLen + aStringLen - aRange.length; buffer = cast(wchar*) NSAllocateMemoryPages(bufferSize * wchar.sizeof); /* Get first part into buffer */ localRange.location = 0; localRange.length = aRange.location; this.getCharacters(buffer, localRange); /* Get middle part into buffer */ localRange.location = 0; localRange.length = aStringLen; str.getCharacters(buffer + aRange.location, localRange); /* Get last part into buffer */ localRange.location = aRange.location + aRange.length; localRange.length = selfLen - localRange.location; this.getCharacters(buffer + aRange.location + aStringLen, localRange); /* Build output string */ result = NSString.stringWithCharacters(buffer, bufferSize); NSDeallocateMemoryPages(buffer, bufferSize); return result; } }CheeseCutter-master/src/derelict/sdl/macinit/NSZone.d000066400000000000000000000037611357241101300230470ustar00rootroot00000000000000/* Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ module derelict.sdl.macinit.NSZone; version(DigitalMars) version(OSX) version = darwin; version (darwin): import derelict.sdl.macinit.NSGeometry; import derelict.util.compat; import derelict.util.loader; package: extern (C) { mixin(gsharedString!() ~ " void* function(NSUInteger bytes) NSAllocateMemoryPages; void function (void* ptr, NSUInteger bytes) NSDeallocateMemoryPages;"); } void load (void delegate(void**, string, bool doThrow) bindFunc) { bindFunc(cast(void**)&NSAllocateMemoryPages, "NSAllocateMemoryPages", true); bindFunc(cast(void**)&NSDeallocateMemoryPages, "NSDeallocateMemoryPages", true); } CheeseCutter-master/src/derelict/sdl/macinit/SDLMain.d000066400000000000000000000361631357241101300231240ustar00rootroot00000000000000/* * SDLMain.m - main entry point for our Cocoa-ized SDL app * Initial Version: Darrell Walisser * Non-NIB-Code & other changes: Max Horn * Port to the D programming language: Jacob Carlborg * * Feel free to customize this file to suit your needs */ module derelict.sdl.macinit.SDLMain; import main; version(DigitalMars) version(OSX) version = darwin; version (darwin) { private { version (Tango) { import tango.stdc.posix.unistd; import tango.stdc.stdlib; import tango.stdc.string; } else { import std.c.linux.linux; import core.stdc.stdlib; import core.stdc.string; import core.sys.posix.unistd; static import std.string; } import derelict.sdl.sdltypes; import derelict.sdl.sdlfuncs; import derelict.sdl.macinit.CoreFoundation; import derelict.sdl.macinit.DerelictSDLMacLoader; import derelict.sdl.macinit.ID; import derelict.sdl.macinit.MacTypes; import derelict.sdl.macinit.NSApplication; import derelict.sdl.macinit.NSAutoreleasePool; import derelict.sdl.macinit.NSDictionary; import derelict.sdl.macinit.NSEnumerator; import derelict.sdl.macinit.NSEvent; import derelict.sdl.macinit.NSGeometry; import derelict.sdl.macinit.NSMenu; import derelict.sdl.macinit.NSMenuItem; import derelict.sdl.macinit.NSNotification; import derelict.sdl.macinit.NSObject; import derelict.sdl.macinit.NSProcessInfo; import derelict.sdl.macinit.NSString; import derelict.sdl.macinit.runtime; import derelict.sdl.macinit.selectors; import derelict.sdl.macinit.string; import derelict.util.compat; import derelict.util.loader; } private: enum { MAXPATHLEN = 1024 // from sys/param.h } /* Use this flag to determine whether we use CPS (docking) or not */ version = SDL_USE_CPS; version (SDL_USE_CPS) { struct CPSProcessSerNum { uint lo; uint hi; } extern (C) { mixin(gsharedString!() ~ " OSErr function (CPSProcessSerNum *psn) CPSGetCurrentProcess; OSErr function (CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5) CPSEnableForegroundOperation; OSErr function (CPSProcessSerNum *psn) CPSSetFrontProcess;"); } void load (void delegate(void**, string, bool doThrow) bindFunc) { bindFunc(cast(void**)&CPSGetCurrentProcess, "CPSGetCurrentProcess", true); bindFunc(cast(void**)&CPSEnableForegroundOperation, "CPSEnableForegroundOperation", true); bindFunc(cast(void**)&CPSSetFrontProcess, "CPSSetFrontProcess", true); } } else version = NO_SDL_USE_CPS; private { NSAutoreleasePool pool; SDLMain sdlMain; } static this () { version (SDL_USE_CPS) load(&DerelictSDLMac.bindFunc); registerSubclasses(); CustomApplicationMain(); } static ~this() { if(pool !is null) pool.release(); if(sdlMain !is null) sdlMain.release; DerelictSDLMac.unload(); } private void registerSubclasses () { objc_method terminateMethod; terminateMethod.method_imp = cast(IMP) &terminate; terminateMethod.method_name = sel_terminate; terminateMethod.method_types = "v@:"; objc_method_list* terminateMethodList = cast(objc_method_list*) calloc(1, (objc_method_list).sizeof); terminateMethodList.method_count = 1; terminateMethodList.method_list[0] = terminateMethod; objc_method setupWorkingDirectoryMethod; setupWorkingDirectoryMethod.method_imp = cast(IMP) &setupWorkingDirectory; setupWorkingDirectoryMethod.method_name = sel_setupWorkingDirectory; setupWorkingDirectoryMethod.method_types = "v@:B"; objc_method_list* setupWorkingDirectoryMethodList = cast(objc_method_list*) calloc(1, (objc_method_list).sizeof); setupWorkingDirectoryMethodList.method_count = 1; setupWorkingDirectoryMethodList.method_list[0] = setupWorkingDirectoryMethod; objc_method applicationMethod; applicationMethod.method_imp = cast(IMP) &application; applicationMethod.method_name = sel_application; applicationMethod.method_types = "B@:@@"; objc_method_list* applicationMethodList = cast(objc_method_list*) calloc(1, (objc_method_list).sizeof); applicationMethodList.method_count = 1; applicationMethodList.method_list[0] = applicationMethod; objc_method applicationDidFinishLaunchingMethod; applicationDidFinishLaunchingMethod.method_imp = cast(IMP) &applicationDidFinishLaunching; applicationDidFinishLaunchingMethod.method_name = sel_applicationDidFinishLaunching; applicationDidFinishLaunchingMethod.method_types = "v@:@"; objc_method_list* applicationDidFinishLaunchingMethodList = cast(objc_method_list*) calloc(1, (objc_method_list).sizeof); applicationDidFinishLaunchingMethodList.method_count = 1; applicationDidFinishLaunchingMethodList.method_list[0] = applicationDidFinishLaunchingMethod; auto sdlApplicationMethodList = [terminateMethodList]; auto sdlMainMethodList = [setupWorkingDirectoryMethodList, applicationMethodList, applicationDidFinishLaunchingMethodList]; registerClass!("SDLApplication")(cast(Class) class_NSApplication, sdlApplicationMethodList); registerClass!("SDLMain")(cast(Class) class_NSObject, sdlMainMethodList); class_SDLApplication = objc_getClass!("SDLApplication"); } private void registerClass (string className) (Class superClass, objc_method_list*[] methodList) { Class newClass; // Leopard and above if (!objc_addClass) { newClass = objc_allocateClassPair!(className)(cast(Class) superClass, 0); foreach (m ; methodList) { auto method = m.method_list[0]; class_addMethod(newClass, method.method_name, method.method_imp, method.method_types); } objc_registerClassPair(newClass); } // Tiger and below else { enum { CLS_CLASS = 0x1, CLS_META = 0x2 } Class metaClass; Class rootClass = superClass; // Find the root class while (rootClass.super_class !is null) rootClass = rootClass.super_class; // Allocate space for the class and its metaclass newClass = cast(Class) calloc(2, objc_class.sizeof); metaClass = &newClass[1]; // Setup class newClass.isa = metaClass; newClass.info = CLS_CLASS; metaClass.info = CLS_META; /* * Create a copy of the class name. * For efficiency, we have the metaclass and the class itself * to share this copy of the name, but this is not a requirement * imposed by the runtime. */ newClass.name = toCString(className); metaClass.name = newClass.name; // Allocate method lists. newClass.methodLists = cast(objc_method_list**) calloc(1, (objc_method_list*).sizeof); *(newClass.methodLists) = cast(objc_method_list*) -1; metaClass.methodLists = cast(objc_method_list**) calloc(1, (objc_method_list*).sizeof); *(metaClass.methodLists) = cast(objc_method_list*) -1; foreach (method ; methodList) class_addMethods(newClass, method); /* * Connect the class definition to the class hierarchy: * Connect the class to the superclass. * Connect the metaclass to the metaclass of the superclass. * Connect the metaclass of the metaclass to the metaclass of the root class. */ newClass.super_class = superClass; metaClass.super_class = superClass.isa; metaClass.isa = rootClass.isa; // Set the sizes of the class and the metaclass. newClass.instance_size = superClass.instance_size; metaClass.instance_size = metaClass.super_class.instance_size; // Finally, register the class with the runtime. objc_addClass(newClass); } } private NSString getApplicationName () { NSDictionary dict; NSString appName; /* Determine the application name */ dict = new NSDictionary(cast(id)CFBundleGetInfoDictionary(CFBundleGetMainBundle())); if (dict) appName = cast(NSString) dict.objectForKey(NSString.stringWith("CFBundleName")); if (appName is null || !appName.length) appName = NSProcessInfo.processInfo.processName; return appName; } class SDLApplication : NSApplication { this () { id_ = null; } this (id id_) { this.id_ = id_; } static SDLApplication alloc () { id result = objc_msgSend(cast(id)class_, sel_alloc); return result ? new SDLApplication(result) : null; } static Class class_ () { return cast(Class) objc_getClass!(this.stringof); } static void poseAsClass (Class aClass) { objc_msgSend(class_SDLApplication, sel_poseAsClass, aClass); } SDLApplication init () { id result = objc_msgSend(this.id_, sel_init); return result ? this : null; } /* Invoked from the Quit menu item */ void terminate () { objc_msgSend(this.id_, sel_terminate); } } /* Invoked from the Quit menu item */ extern (C) id terminate (id self, SEL selector) { /* Post a SDL_QUIT event */ SDL_Event event; event.type = SDL_QUIT; SDL_PushEvent(&event); return null; } /* The main class of the application, the application's delegate */ class SDLMain : NSObject { this () { id_ = null; } this (id id_) { this.id_ = id_; } static SDLMain alloc () { id result = objc_msgSend(cast(id)class_, sel_alloc); return result ? new SDLMain(result) : null; } static Class class_ () { return cast(Class) objc_getClass!(this.stringof); } SDLMain init () { id result = objc_msgSend(this.id_, sel_init); return result ? this : null; } void setupWorkingDirectory (bool shouldChdir) { objc_msgSend(this.id_, sel_setupWorkingDirectory, shouldChdir); } bool application (NSApplication theApplication, NSString filename) { return objc_msgSend(this.id_, sel_application, theApplication ? theApplication.id_ : null, filename ? filename.id_ : null) !is null; } /* Called when the internal event loop has just started running */ void applicationDidFinishLaunching (NSNotification note) { objc_msgSend(this.id_, sel_applicationDidFinishLaunching, note ? note.id_ : null); } } extern (C) { id setupWorkingDirectory (id sender, SEL selector, bool shouldChdir) { if (shouldChdir) { char[MAXPATHLEN] parentdir; CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle()); CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(null, url); if (CFURLGetFileSystemRepresentation(url2, true, cast(ubyte*) parentdir, MAXPATHLEN)) assert (chdir(parentdir.ptr) == 0); /* chdir to the binary app's parent */ CFRelease(url); CFRelease(url2); } return null; } id application (id sender, SEL selector, id arg0, id arg1) { if (arg1) { main.openFile((new NSString(arg1)).UTF8String()); } return cast(id) true; } /* Called when the internal event loop has just started running */ id applicationDidFinishLaunching (id sender, SEL selector, id arg0) { NSNotification note = arg0 ? new NSNotification(arg0) : null; int status; /* Set the working directory to the .app's parent directory */ setupWorkingDirectory(sender, selector, false); NSApp.stop(null); return null; } } private void setApplicationMenu () { /* warning: this code is very odd */ NSMenu appleMenu; NSMenuItem menuItem; NSString title; NSString appName; appName = getApplicationName(); appleMenu = NSMenu.alloc.initWithTitle(NSString.stringWith("")); /* Add menu items */ title = NSString.stringWith("About ").stringByAppendingString(appName); appleMenu.addItemWithTitle(title, sel_registerName!("orderFrontStandardAboutPanel:"), NSString.stringWith("")); appleMenu.addItem(NSMenuItem.separatorItem); title = NSString.stringWith("Hide ").stringByAppendingString(appName); appleMenu.addItemWithTitle(title, sel_registerName!("hide:"), NSString.stringWith("h")); menuItem = appleMenu.addItemWithTitle(NSString.stringWith("Hide Others"), sel_registerName!("hideOtherApplications:"), NSString.stringWith("h")); menuItem.setKeyEquivalentModifierMask(NSAlternateKeyMask | NSCommandKeyMask); appleMenu.addItemWithTitle(NSString.stringWith("Show All"), sel_registerName!("unhideAllApplications:"), NSString.stringWith("")); appleMenu.addItem(NSMenuItem.separatorItem); title = NSString.stringWith("Quit ").stringByAppendingString(appName); appleMenu.addItemWithTitle(title, sel_registerName!("terminate:"), NSString.stringWith("q")); /* Put menu into the menubar */ menuItem = NSMenuItem.alloc; menuItem = menuItem.initWithTitle(NSString.stringWith(""), null, NSString.stringWith("")); menuItem.setSubmenu = appleMenu; NSApp.mainMenu.addItem(menuItem); /* Tell the application object that this is now the application menu */ NSApp.setAppleMenu = appleMenu; /* Finally give up our references to the objects */ appleMenu.release; menuItem.release; } /* Create a window menu */ private void setupWindowMenu () { NSMenu windowMenu; NSMenuItem windowMenuItem; NSMenuItem menuItem; windowMenu = NSMenu.alloc.initWithTitle(NSString.stringWith("Window")); /* "Minimize" item */ menuItem = NSMenuItem.alloc; menuItem = menuItem.initWithTitle(NSString.stringWith("Minimize"), sel_registerName!("performMiniaturize:"), NSString.stringWith("m")); windowMenu.addItem(menuItem); menuItem.release; /* Put menu into the menubar */ windowMenuItem = NSMenuItem.alloc; windowMenuItem = windowMenuItem.initWithTitle(NSString.stringWith("Window"), null, NSString.stringWith("")); windowMenuItem.setSubmenu = windowMenu; NSApp.mainMenu.addItem(windowMenuItem); /* Tell the application object that this is now the window menu */ NSApp.setWindowsMenu = windowMenu; /* Finally give up our references to the objects */ windowMenu.release; windowMenuItem.release; } /* Replacement for NSApplicationMain */ private void CustomApplicationMain () { pool = NSAutoreleasePool.alloc.init; /* Ensure the application object is initialised */ SDLApplication.sharedApplication; version (SDL_USE_CPS) { CPSProcessSerNum PSN; /* Tell the dock about us */ if (!CPSGetCurrentProcess(&PSN)) if (!CPSEnableForegroundOperation(&PSN, 0x03, 0x3C, 0x2C, 0x1103)) if (!CPSSetFrontProcess(&PSN)) SDLApplication.sharedApplication; } /* Set up the menubar */ NSApp.setMainMenu = NSMenu.alloc.init; setApplicationMenu(); setupWindowMenu(); /* Create SDLMain and make it the app delegate */ sdlMain = SDLMain.alloc.init; NSApp.setDelegate = sdlMain; /* Start the main event loop */ NSApp.run; } } // version(darwin) CheeseCutter-master/src/derelict/sdl/macinit/runtime.d000066400000000000000000000123141357241101300233500ustar00rootroot00000000000000/* Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ module derelict.sdl.macinit.runtime; version(DigitalMars) version(OSX) version = darwin; version (darwin): import derelict.sdl.macinit.string; import derelict.util.compat; import derelict.sdl.macinit.NSGeometry; import derelict.util.loader; import derelict.util.exception; package: alias objc_ivar* Ivar; alias objc_method* Method; alias objc_object Protocol; alias objc_selector* SEL; alias objc_class* Class; alias objc_object* id; alias extern (C) id function(id, SEL, ...) IMP; struct objc_selector { void* sel_id; char* sel_types; } struct objc_object { Class isa; } struct objc_super { id receiver; Class clazz; } struct objc_class { Class isa; Class super_class; CCPTR name; int versionn; int info; int instance_size; objc_ivar_list* ivars; objc_method_list** methodLists; objc_cache* cache; objc_protocol_list* protocols; } struct objc_ivar { CCPTR ivar_name; CCPTR ivar_type; int ivar_offset; version (X86_64) int space; } struct objc_ivar_list { int ivar_count; version (X86_64) int space; /* variable length structure */ objc_ivar[1] ivar_list; } struct objc_method { SEL method_name; CCPTR method_types; IMP method_imp; } struct objc_method_list { objc_method_list* obsolete; int method_count; version (X86_64) int space; /* variable length structure */ objc_method[1] method_list; } struct objc_cache { uint mask /* total = mask + 1 */; uint occupied; Method[1] buckets; } struct objc_protocol_list { objc_protocol_list* next; long count; Protocol*[1] list; } // Objective-C runtime bindings from the Cocoa framework extern (C) { mixin(gsharedString!() ~ " Class function (Class superclass, CCPTR name, size_t extraBytes) c_objc_allocateClassPair; Class function (Class superclass) objc_registerClassPair; id function (CCPTR name) c_objc_getClass; id function (id theReceiver, SEL theSelector, ...) c_objc_msgSend; SEL function (CCPTR str) c_sel_registerName; bool function () NSApplicationLoad; void function (Class myClass) objc_addClass; void function (Class arg0, objc_method_list* arg1) class_addMethods; bool function (Class c13ls, SEL name, IMP imp, CCPTR types) class_addMethod;"); } void load (void delegate(void**, string, bool doThrow) bindFunc) { bindFunc(cast(void**)&c_objc_getClass, "objc_getClass", true); bindFunc(cast(void**)&c_objc_msgSend, "objc_msgSend", true); bindFunc(cast(void**)&c_sel_registerName, "sel_registerName", true); bindFunc(cast(void**)&NSApplicationLoad, "NSApplicationLoad", true); try { /* * These methods are expected to not be found in > Leopard, they have * been deprecated in favor of objc_{allocate|register}ClassPair and * class_addMethod. */ bindFunc(cast(void**)&objc_addClass, "objc_addClass", true); bindFunc(cast(void**)&class_addMethods, "class_addMethods", true); } catch (Exception e) { bindFunc(cast(void**)&class_addMethod, "class_addMethod", true); bindFunc(cast(void**)&c_objc_allocateClassPair, "objc_allocateClassPair", true); bindFunc(cast(void**)&objc_registerClassPair, "objc_registerClassPair", true); } } Class objc_allocateClassPair (string name) (Class superclass, size_t extraBytes) { return c_objc_allocateClassPair(superclass, name.ptr, extraBytes); } id objc_getClass (string name) () { return c_objc_getClass(name.ptr); } SEL sel_registerName (string str) () { return c_sel_registerName(str.ptr); } id objc_msgSend (ARGS...)(id theReceiver, SEL theSelector, ARGS args) { // the dmd import generator can't handle this //alias extern (C) id function (id, SEL, ARGS) fp; //return (cast(fp)&c_objc_msgSend)(theReceiver, theSelector, args); return c_objc_msgSend(theReceiver, theSelector, args); } CheeseCutter-master/src/derelict/sdl/macinit/selectors.d000066400000000000000000000141101357241101300236640ustar00rootroot00000000000000/* Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ module derelict.sdl.macinit.selectors; version(DigitalMars) version(OSX) version = darwin; version (darwin): import derelict.sdl.macinit.runtime; import derelict.sdl.macinit.string; import derelict.util.compat; package: version = SDL_USE_NIB_FILE; // Classes id class_NSApplication; id class_NSAutoreleasePool; id class_NSDictionary; id class_NSEnumerator; id class_NSGeometry; id class_NSMenu; id class_NSMenuItem; id class_NSNotification; id class_NSObject; id class_NSProcessInfo; id class_NSString; id class_SDLApplication; // Selectors SEL sel_stringWithCharacters_length; SEL sel_addItem; SEL sel_addItemWithTitle_action_keyEquivalent; SEL sel_alloc; SEL sel_class; SEL sel_getCharacters_range; SEL sel_hasSubmenu; SEL sel_init; SEL sel_initWithTitle; SEL sel_itemArray; SEL sel_length; SEL sel_mainMenu; SEL sel_nextObject; SEL sel_objectEnumerator; SEL sel_objectForKey; SEL sel_poseAsClass; SEL sel_processInfo; SEL sel_processName; SEL sel_rangeOfString; SEL sel_release; SEL sel_run; SEL sel_setAppleMenu; SEL sel_setDelegate; SEL sel_setKeyEquivalentModifierMask; SEL sel_setMainMenu; SEL sel_setSubmenu; SEL sel_setTitle; SEL sel_setWindowsMenu; SEL sel_sharedApplication; SEL sel_sizeToFit; SEL sel_stringByAppendingString; SEL sel_submenu; SEL sel_title; SEL sel_UTF8String; SEL sel_separatorItem; SEL sel_stop; SEL sel_terminate; SEL sel_setupWorkingDirectory; version (SDL_USE_NIB_FILE) SEL sel_fixMenu; SEL sel_application; SEL sel_applicationDidFinishLaunching; SEL sel_initWithTitle_action_keyEquivalent; static this () { class_NSApplication = objc_getClass!("NSApplication"); class_NSAutoreleasePool = objc_getClass!("NSAutoreleasePool"); class_NSDictionary = objc_getClass!("NSDictionary"); class_NSEnumerator = objc_getClass!("NSEnumerator"); class_NSGeometry = objc_getClass!("NSGeometry"); class_NSMenu = objc_getClass!("NSMenu"); class_NSMenuItem = objc_getClass!("NSMenuItem"); class_NSNotification = objc_getClass!("NSNotification"); class_NSObject = objc_getClass!("NSObject"); class_NSProcessInfo = objc_getClass!("NSProcessInfo"); class_NSString = objc_getClass!("NSString"); sel_stringWithCharacters_length = sel_registerName!("stringWithCharacters:length:"); sel_addItem = sel_registerName!("addItem:"); sel_addItemWithTitle_action_keyEquivalent = sel_registerName!("addItemWithTitle:action:keyEquivalent:"); sel_alloc = sel_registerName!("alloc"); sel_class = sel_registerName!("class"); sel_getCharacters_range = sel_registerName!("getCharacters:range:"); sel_hasSubmenu = sel_registerName!("hasSubmenu"); sel_init = sel_registerName!("init"); sel_initWithTitle = sel_registerName!("initWithTitle:"); sel_itemArray = sel_registerName!("itemArray"); sel_length = sel_registerName!("length"); sel_mainMenu = sel_registerName!("mainMenu"); sel_nextObject = sel_registerName!("nextObject"); sel_objectEnumerator = sel_registerName!("objectEnumerator"); sel_objectForKey = sel_registerName!("objectForKey:"); sel_poseAsClass = sel_registerName!("poseAsClass:"); sel_processInfo = sel_registerName!("processInfo"); sel_processName = sel_registerName!("processName"); sel_rangeOfString = sel_registerName!("rangeOfString"); sel_release = sel_registerName!("release"); sel_run = sel_registerName!("run"); sel_setAppleMenu = sel_registerName!("setAppleMenu:"); sel_setDelegate = sel_registerName!("setDelegate:"); sel_setKeyEquivalentModifierMask = sel_registerName!("setKeyEquivalentModifierMask:"); sel_setMainMenu = sel_registerName!("setMainMenu:"); sel_setSubmenu = sel_registerName!("setSubmenu:"); sel_setTitle = sel_registerName!("setTitle:"); sel_setWindowsMenu = sel_registerName!("setWindowsMenu:"); sel_sharedApplication = sel_registerName!("sharedApplication"); sel_sizeToFit = sel_registerName!("sizeToFit"); sel_stringByAppendingString = sel_registerName!("stringByAppendingString:"); sel_submenu = sel_registerName!("submenu"); sel_title = sel_registerName!("title"); sel_UTF8String = sel_registerName!("UTF8String"); sel_separatorItem = sel_registerName!("separatorItem"); sel_stop = sel_registerName!("stop:"); sel_terminate = sel_registerName!("terminate:"); sel_setupWorkingDirectory = sel_registerName!("setupWorkingDirectory"); version (SDL_USE_NIB_FILE) sel_fixMenu = sel_registerName!("fixMenu"); sel_application = sel_registerName!("application:openFile:"); sel_applicationDidFinishLaunching = sel_registerName!("applicationDidFinishLaunching:"); sel_initWithTitle_action_keyEquivalent = sel_registerName!("initWithTitle:action:keyEquivalent:"); }CheeseCutter-master/src/derelict/sdl/macinit/string.d000066400000000000000000000042431357241101300231750ustar00rootroot00000000000000/* Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ module derelict.sdl.macinit.string; version(DigitalMars) version(OSX) version = darwin; version (darwin) { version (Tango) import tango.text.Util : locatePrior; else { import std.string; import std.utf : toUTF32; } public size_t lastIndexOf (T)(T[] str, T ch) { return lastIndexOf(str, ch, str.length); } public size_t lastIndexOf (T)(T[] str, T ch, size_t formIndex) { size_t res; version (Tango) res = str.locatePrior(ch, formIndex); else { version (D_Version2) return str.lastIndexOf(toUTF32([c]), CaseSensitive.yes); else return str.rfind(toUTF32([ch])[0]); } version (Tango) if (res is str.length) res = -1; return res; } } // version(darwin)CheeseCutter-master/src/derelict/sdl/mixer.d000066400000000000000000000400461357241101300213700ustar00rootroot00000000000000/* Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ module derelict.sdl.mixer; private { import derelict.util.loader; import derelict.util.exception; import derelict.util.compat; import derelict.sdl.sdl; } enum : Uint8 { SDL_MIXER_MAJOR_VERSION = 1, SDL_MIXER_MINOR_VERSION = 2, SDL_MIXER_PATCHLEVEL = 12, } alias SDL_MIXER_MAJOR_VERSION MIX_MAJOR_VERSION; alias SDL_MIXER_MINOR_VERSION MIX_MINOR_VERSION; alias SDL_MIXER_PATCHLEVEL MIX_PATCH_LEVEL; alias SDL_SetError Mix_SetError; alias SDL_GetError Mix_GetError; alias int MIX_InitFlags; enum : int { MIX_INIT_FLAC = 0x00000001, MIX_INIT_MOD = 0x00000002, MIX_INIT_MP3 = 0x00000004, MIX_INIT_OGG = 0x00000008, } struct Mix_Chunk { int allocated; Uint8* abuf; Uint32 alen; Uint8 volume; }; alias int Mix_Fading; enum : int { MIX_NO_FADING, MIX_FADING_OUT, MIX_FADING_IN }; alias int Mix_MusicType; enum : int { MUS_NONE, MUS_CMD, MUS_WAV, MUS_MOD, MUS_MID, MUS_OGG, MUS_MP3, MUS_MP3_MAD, MUS_FLAC, MUS_MODPLUG, }; struct _Mix_Music {} alias _Mix_Music Mix_Music; enum { MIX_CHANNELS = 8, MIX_DEFAULT_FREQUENCY = 22050, MIX_DEFAULT_CHANNELS = 2, MIX_MAX_VOLUME = 128, MIX_CHANNEL_POST = -2, } version (LittleEndian) { enum { MIX_DEFAULT_FORMAT = AUDIO_S16LSB } } else { enum { MIX_DEFAULT_FORMAT = AUDIO_S16MSB } } string MIX_EFFECTSMAXSPEED = "MIX_EFFECTSMAXSPEED"; extern(C) { alias void function(int chan, void* stream, int len, void* udata) Mix_EffectFunc_t; alias void function(int chan, void* udata) Mix_EffectDone_t; } void SDL_MIXER_VERSION(SDL_version* X) { X.major = SDL_MIXER_MAJOR_VERSION; X.minor = SDL_MIXER_MINOR_VERSION; X.patch = SDL_MIXER_PATCHLEVEL; } alias SDL_MIXER_VERSION MIX_VERSION; Mix_Chunk* Mix_LoadWAV(string file) { return Mix_LoadWAV_RW(SDL_RWFromFile(toCString(file), toCString("rb")), 1); } int Mix_PlayChannel(int channel, Mix_Chunk* chunk, int loops) { return Mix_PlayChannelTimed(channel, chunk, loops, -1); } int Mix_FadeInChannel(int channel, Mix_Chunk* chunk, int loops, int ms) { return Mix_FadeInChannelTimed(channel, chunk, loops, ms, -1); } extern (C) { alias CSDLVERPTR function() da_Mix_Linked_Version; alias int function(int) da_Mix_Init; alias void function() da_Mix_Quit; alias int function (int, Uint16, int, int) da_Mix_OpenAudio; alias int function(int) da_Mix_AllocateChannels; alias int function(int*, Uint16*, int*) da_Mix_QuerySpec; alias Mix_Chunk* function(SDL_RWops*, int) da_Mix_LoadWAV_RW; alias Mix_Music* function(in char*) da_Mix_LoadMUS; alias Mix_Music* function(SDL_RWops*) da_Mix_LoadMUS_RW; alias Mix_Music* function(SDL_RWops*, Mix_MusicType, int) da_Mix_LoadMUSType_RW; alias Mix_Chunk* function(Uint8*) da_Mix_QuickLoad_WAV; alias Mix_Chunk* function(Uint8*, Uint32) da_Mix_QuickLoad_RAW; alias void function(Mix_Chunk*) da_Mix_FreeChunk; alias void function(Mix_Music*) da_Mix_FreeMusic; alias int function() da_Mix_GetNumChunkDecoders; alias CCPTR function(int) da_Mix_GetChunkDecoder; alias int function() da_Mix_GetNumMusicDecoders; alias CCPTR function(int) da_Mix_GetMusicDecoder; alias Mix_MusicType function(in Mix_Music*) da_Mix_GetMusicType; alias void function(void function(void*, Uint8*, int) da_Mix_func, void*) da_Mix_SetPostMix; alias void function(void function(void*, Uint8*, int) da_Mix_func, void*) da_Mix_HookMusic; alias void function(void function() music_finished) da_Mix_HookMusicFinished; alias void* function() da_Mix_GetMusicHookData; alias void function(void function(int channel) channel_finished) da_Mix_ChannelFinished; alias int function(int, Mix_EffectFunc_t, Mix_EffectDone_t, void*) da_Mix_RegisterEffect; alias int function(int, Mix_EffectFunc_t) da_Mix_UnregisterEffect; alias int function(int) da_Mix_UnregisterAllEffects; alias int function(int, Uint8, Uint8) da_Mix_SetPanning; alias int function(int, Sint16, Uint8) da_Mix_SetPosition; alias int function(int, Uint8) da_Mix_SetDistance; // alias int function(int, Uint8) da_Mix_SetReverb; alias int function(int, int) da_Mix_SetReverseStereo; alias int function(int) da_Mix_ReserveChannels; alias int function(int, int) da_Mix_GroupChannel; alias int function(int, int, int) da_Mix_GroupChannels; alias int function(int) da_Mix_GroupAvailable; alias int function(int) da_Mix_GroupCount; alias int function(int) da_Mix_GroupOldest; alias int function(int) da_Mix_GroupNewer; alias int function(int, Mix_Chunk*, int, int) da_Mix_PlayChannelTimed; alias int function(Mix_Music*, int) da_Mix_PlayMusic; alias int function(Mix_Music*, int, int) da_Mix_FadeInMusic; alias int function(Mix_Music*, int, int, double) da_Mix_FadeInMusicPos; alias int function(int, Mix_Chunk*, int, int, int) da_Mix_FadeInChannelTimed; alias int function(int, int) da_Mix_Volume; alias int function(Mix_Chunk*, int) da_Mix_VolumeChunk; alias int function(int) da_Mix_VolumeMusic; alias int function(int) da_Mix_HaltChannel; alias int function(int) da_Mix_HaltGroup; alias int function() da_Mix_HaltMusic; alias int function(int, int) da_Mix_ExpireChannel; alias int function(int, int) da_Mix_FadeOutChannel; alias int function(int, int) da_Mix_FadeOutGroup; alias int function(int) da_Mix_FadeOutMusic; alias Mix_Fading function() da_Mix_FadingMusic; alias Mix_Fading function(int) da_Mix_FadingChannel; alias void function(int) da_Mix_Pause; alias void function(int) da_Mix_Resume; alias int function(int) da_Mix_Paused; alias void function() da_Mix_PauseMusic; alias void function() da_Mix_ResumeMusic; alias void function() da_Mix_RewindMusic; alias int function() da_Mix_PausedMusic; alias int function(double) da_Mix_SetMusicPosition; alias int function(int) da_Mix_Playing; alias int function() da_Mix_PlayingMusic; alias int function(in char*) da_Mix_SetMusicCMD; alias int function(int) da_Mix_SetSynchroValue; alias int function() da_Mix_GetSynchroValue; alias Mix_Chunk* function(int) da_Mix_GetChunk; alias void function() da_Mix_CloseAudio; } mixin(gsharedString!() ~ " da_Mix_Linked_Version Mix_Linked_Version; da_Mix_Init Mix_Init; da_Mix_Quit Mix_Quit; da_Mix_OpenAudio Mix_OpenAudio; da_Mix_AllocateChannels Mix_AllocateChannels; da_Mix_QuerySpec Mix_QuerySpec; da_Mix_LoadWAV_RW Mix_LoadWAV_RW; da_Mix_LoadMUS Mix_LoadMUS; da_Mix_LoadMUS_RW Mix_LoadMUS_RW; da_Mix_LoadMUSType_RW Mix_LoadMUSType_RW; da_Mix_QuickLoad_WAV Mix_QuickLoad_WAV; da_Mix_QuickLoad_RAW Mix_QuickLoad_RAW; da_Mix_FreeChunk Mix_FreeChunk; da_Mix_FreeMusic Mix_FreeMusic; da_Mix_GetNumChunkDecoders Mix_GetNumChunkDecoders; da_Mix_GetChunkDecoder Mix_GetChunkDecoder; da_Mix_GetNumMusicDecoders Mix_GetNumMusicDecoders; da_Mix_GetMusicDecoder Mix_GetMusicDecoder; da_Mix_GetMusicType Mix_GetMusicType; da_Mix_SetPostMix Mix_SetPostMix; da_Mix_HookMusic Mix_HookMusic; da_Mix_HookMusicFinished Mix_HookMusicFinished; da_Mix_GetMusicHookData Mix_GetMusicHookData; da_Mix_ChannelFinished Mix_ChannelFinished; da_Mix_RegisterEffect Mix_RegisterEffect; da_Mix_UnregisterEffect Mix_UnregisterEffect; da_Mix_UnregisterAllEffects Mix_UnregisterAllEffects; da_Mix_SetPanning Mix_SetPanning; da_Mix_SetPosition Mix_SetPosition; da_Mix_SetDistance Mix_SetDistance; // da_ Mix_SetReverb; da_Mix_SetReverseStereo Mix_SetReverseStereo; da_Mix_ReserveChannels Mix_ReserveChannels; da_Mix_GroupChannel Mix_GroupChannel; da_Mix_GroupChannels Mix_GroupChannels; da_Mix_GroupAvailable Mix_GroupAvailable; da_Mix_GroupCount Mix_GroupCount; da_Mix_GroupOldest Mix_GroupOldest; da_Mix_GroupNewer Mix_GroupNewer; da_Mix_PlayChannelTimed Mix_PlayChannelTimed; da_Mix_PlayMusic Mix_PlayMusic; da_Mix_FadeInMusic Mix_FadeInMusic; da_Mix_FadeInMusicPos Mix_FadeInMusicPos; da_Mix_FadeInChannelTimed Mix_FadeInChannelTimed; da_Mix_Volume Mix_Volume; da_Mix_VolumeChunk Mix_VolumeChunk; da_Mix_VolumeMusic Mix_VolumeMusic; da_Mix_HaltChannel Mix_HaltChannel; da_Mix_HaltGroup Mix_HaltGroup; da_Mix_HaltMusic Mix_HaltMusic; da_Mix_ExpireChannel Mix_ExpireChannel; da_Mix_FadeOutChannel Mix_FadeOutChannel; da_Mix_FadeOutGroup Mix_FadeOutGroup; da_Mix_FadeOutMusic Mix_FadeOutMusic; da_Mix_FadingMusic Mix_FadingMusic; da_Mix_FadingChannel Mix_FadingChannel; da_Mix_Pause Mix_Pause; da_Mix_Resume Mix_Resume; da_Mix_Paused Mix_Paused; da_Mix_PauseMusic Mix_PauseMusic; da_Mix_ResumeMusic Mix_ResumeMusic; da_Mix_RewindMusic Mix_RewindMusic; da_Mix_PausedMusic Mix_PausedMusic; da_Mix_SetMusicPosition Mix_SetMusicPosition; da_Mix_Playing Mix_Playing; da_Mix_PlayingMusic Mix_PlayingMusic; da_Mix_SetMusicCMD Mix_SetMusicCMD; da_Mix_SetSynchroValue Mix_SetSynchroValue; da_Mix_GetSynchroValue Mix_GetSynchroValue; da_Mix_GetChunk Mix_GetChunk; da_Mix_CloseAudio Mix_CloseAudio; "); class DerelictSDLMixerLoader : SharedLibLoader { public: this() { super( "SDL_mixer.dll", "libSDL_mixer.so, libSDL_mixer-1.2.so, libSDL_mixer-1.2.so.0", "../Frameworks/SDL_mixer.framework/SDL_mixer, /Library/Frameworks/SDL_mixer.framework/SDL_mixer, /System/Library/Frameworks/SDL_mixer.framework/SDL_mixer" ); } protected: override void loadSymbols() { if(!DerelictSDL.isLoaded) { throw new SharedLibLoadException("DerelictSDL must be loaded before attempting to load DerelictSDLMixer!"); } bindFunc(cast(void**)&Mix_Linked_Version, "Mix_Linked_Version"); bindFunc(cast(void**)&Mix_Init, "Mix_Init"); bindFunc(cast(void**)&Mix_Quit, "Mix_Quit"); bindFunc(cast(void**)&Mix_OpenAudio, "Mix_OpenAudio"); bindFunc(cast(void**)&Mix_AllocateChannels, "Mix_AllocateChannels"); bindFunc(cast(void**)&Mix_QuerySpec, "Mix_QuerySpec"); bindFunc(cast(void**)&Mix_LoadWAV_RW, "Mix_LoadWAV_RW"); bindFunc(cast(void**)&Mix_LoadMUS, "Mix_LoadMUS"); bindFunc(cast(void**)&Mix_LoadMUS_RW, "Mix_LoadMUS_RW"); bindFunc(cast(void**)&Mix_LoadMUSType_RW, "Mix_LoadMUSType_RW"); bindFunc(cast(void**)&Mix_QuickLoad_WAV, "Mix_QuickLoad_WAV"); bindFunc(cast(void**)&Mix_QuickLoad_RAW, "Mix_QuickLoad_RAW"); bindFunc(cast(void**)&Mix_FreeChunk, "Mix_FreeChunk"); bindFunc(cast(void**)&Mix_FreeMusic, "Mix_FreeMusic"); bindFunc(cast(void**)&Mix_GetNumChunkDecoders, "Mix_GetNumChunkDecoders"); bindFunc(cast(void**)&Mix_GetChunkDecoder, "Mix_GetChunkDecoder"); bindFunc(cast(void**)&Mix_GetNumMusicDecoders, "Mix_GetNumMusicDecoders"); bindFunc(cast(void**)&Mix_GetMusicDecoder, "Mix_GetMusicDecoder"); bindFunc(cast(void**)&Mix_GetMusicType, "Mix_GetMusicType"); bindFunc(cast(void**)&Mix_SetPostMix, "Mix_SetPostMix"); bindFunc(cast(void**)&Mix_HookMusic, "Mix_HookMusic"); bindFunc(cast(void**)&Mix_HookMusicFinished, "Mix_HookMusicFinished"); bindFunc(cast(void**)&Mix_GetMusicHookData, "Mix_GetMusicHookData"); bindFunc(cast(void**)&Mix_ChannelFinished, "Mix_ChannelFinished"); bindFunc(cast(void**)&Mix_RegisterEffect, "Mix_RegisterEffect"); bindFunc(cast(void**)&Mix_UnregisterEffect, "Mix_UnregisterEffect"); bindFunc(cast(void**)&Mix_UnregisterAllEffects, "Mix_UnregisterAllEffects"); bindFunc(cast(void**)&Mix_SetPanning, "Mix_SetPanning"); bindFunc(cast(void**)&Mix_SetPosition, "Mix_SetPosition"); bindFunc(cast(void**)&Mix_SetDistance, "Mix_SetDistance"); // bindFunc(cast(void**)&Mix_SetReverb, "Mix_SetReverb"); bindFunc(cast(void**)&Mix_SetReverseStereo, "Mix_SetReverseStereo"); bindFunc(cast(void**)&Mix_ReserveChannels, "Mix_ReserveChannels"); bindFunc(cast(void**)&Mix_GroupChannel, "Mix_GroupChannel"); bindFunc(cast(void**)&Mix_GroupChannels, "Mix_GroupChannels"); bindFunc(cast(void**)&Mix_GroupAvailable, "Mix_GroupAvailable"); bindFunc(cast(void**)&Mix_GroupCount, "Mix_GroupCount"); bindFunc(cast(void**)&Mix_GroupOldest, "Mix_GroupOldest"); bindFunc(cast(void**)&Mix_GroupNewer, "Mix_GroupNewer"); bindFunc(cast(void**)&Mix_PlayChannelTimed, "Mix_PlayChannelTimed"); bindFunc(cast(void**)&Mix_PlayMusic, "Mix_PlayMusic"); bindFunc(cast(void**)&Mix_FadeInMusic, "Mix_FadeInMusic"); bindFunc(cast(void**)&Mix_FadeInMusicPos, "Mix_FadeInMusicPos"); bindFunc(cast(void**)&Mix_FadeInChannelTimed, "Mix_FadeInChannelTimed"); bindFunc(cast(void**)&Mix_Volume, "Mix_Volume"); bindFunc(cast(void**)&Mix_VolumeChunk, "Mix_VolumeChunk"); bindFunc(cast(void**)&Mix_VolumeMusic, "Mix_VolumeMusic"); bindFunc(cast(void**)&Mix_HaltChannel, "Mix_HaltChannel"); bindFunc(cast(void**)&Mix_HaltGroup, "Mix_HaltGroup"); bindFunc(cast(void**)&Mix_HaltMusic, "Mix_HaltMusic"); bindFunc(cast(void**)&Mix_ExpireChannel, "Mix_ExpireChannel"); bindFunc(cast(void**)&Mix_FadeOutChannel, "Mix_FadeOutChannel"); bindFunc(cast(void**)&Mix_FadeOutGroup, "Mix_FadeOutGroup"); bindFunc(cast(void**)&Mix_FadeOutMusic, "Mix_FadeOutMusic"); bindFunc(cast(void**)&Mix_FadingMusic, "Mix_FadingMusic"); bindFunc(cast(void**)&Mix_FadingChannel, "Mix_FadingChannel"); bindFunc(cast(void**)&Mix_Pause, "Mix_Pause"); bindFunc(cast(void**)&Mix_Resume, "Mix_Resume"); bindFunc(cast(void**)&Mix_Paused, "Mix_Paused"); bindFunc(cast(void**)&Mix_PauseMusic, "Mix_PauseMusic"); bindFunc(cast(void**)&Mix_ResumeMusic, "Mix_ResumeMusic"); bindFunc(cast(void**)&Mix_RewindMusic, "Mix_RewindMusic"); bindFunc(cast(void**)&Mix_PausedMusic, "Mix_PausedMusic"); bindFunc(cast(void**)&Mix_SetMusicPosition, "Mix_SetMusicPosition"); bindFunc(cast(void**)&Mix_Playing, "Mix_Playing"); bindFunc(cast(void**)&Mix_PlayingMusic, "Mix_PlayingMusic"); bindFunc(cast(void**)&Mix_SetMusicCMD, "Mix_SetMusicCMD"); bindFunc(cast(void**)&Mix_SetSynchroValue, "Mix_SetSynchroValue"); bindFunc(cast(void**)&Mix_GetSynchroValue, "Mix_GetSynchroValue"); bindFunc(cast(void**)&Mix_GetChunk, "Mix_GetChunk"); bindFunc(cast(void**)&Mix_CloseAudio, "Mix_CloseAudio"); } } DerelictSDLMixerLoader DerelictSDLMixer; static this() { DerelictSDLMixer = new DerelictSDLMixerLoader(); } static ~this() { if(SharedLibLoader.isAutoUnloadEnabled()) DerelictSDLMixer.unload(); }CheeseCutter-master/src/derelict/sdl/net.d000066400000000000000000000246641357241101300210420ustar00rootroot00000000000000/* Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ module derelict.sdl.net; private { import derelict.util.loader; import derelict.util.exception; import derelict.util.compat; import derelict.sdl.sdl; } enum : Uint8 { SDL_NET_MAJOR_VERSION = 1, SDL_NET_MINOR_VERSION = 2, SDL_NET_PATCHLEVEL = 8, } struct IPaddress { Uint32 host; Uint16 port; } // this is a hack to get around the removal of typedefs in D2. struct TCPsocketStruct {} alias TCPsocketStruct* TCPsocket; enum : uint { INADDR_ANY = 0x00000000, INADDR_NONE = 0xFFFFFFFF, INADDR_BROADCAST = 0xFFFFFFFF, SDLNET_MAX_UDPCHANNELS = 32, SDLNET_MAX_UDPADDRESSES = 4, } // hack again struct UDPsocketStruct {} alias UDPsocketStruct* UDPsocket; struct UDPpacket { int channel; Uint8 *data; int len; int maxlen; int status; IPaddress address; } alias void* SDLNet_SocketSet; struct _SDLNet_GenericSocket { int ready; } alias _SDLNet_GenericSocket* SDLNet_GenericSocket; alias SDL_SetError SDLNet_SetError; alias SDL_GetError SDLNet_GetError; void SDL_NET_VERSION(SDL_version* X) { X.major = SDL_NET_MAJOR_VERSION; X.minor = SDL_NET_MINOR_VERSION; X.patch = SDL_NET_PATCHLEVEL; } int SDLNet_TCP_AddSocket(SDLNet_SocketSet set, TCPsocket sock) { return SDLNet_AddSocket(set, cast(SDLNet_GenericSocket)sock); } int SDLNet_TCP_DelSocket(SDLNet_SocketSet set, TCPsocket sock) { return SDLNet_DelSocket(set, cast(SDLNet_GenericSocket)sock); } int SDLNet_UDP_AddSocket(SDLNet_SocketSet set, UDPsocket sock) { return SDLNet_AddSocket(set, cast(SDLNet_GenericSocket)sock); } int SDLNet_UDP_DelSocket(SDLNet_SocketSet set, UDPsocket sock) { return SDLNet_DelSocket(set, cast(SDLNet_GenericSocket)sock); } bool SDLNet_SocketReady(TCPsocket sock) { return cast(bool)((sock !is null) && (cast(SDLNet_GenericSocket)sock).ready); } bool SDLNet_SocketReady(UDPsocket sock) { return cast(bool)((sock !is null) && (cast(SDLNet_GenericSocket)sock).ready); } void SDLNet_Write16(Uint16 value, void* areap) { Uint16* areap16 = cast(Uint16*)areap; *areap16 = SDL_SwapBE16(value); } Uint16 SDLNet_Read16(void *areap) { Uint16* areap16 = cast(Uint16*)areap; return SDL_SwapBE16(*areap16); } void SDLNet_Write32(Uint32 value, void* areap) { Uint32* areap32 = cast(Uint32*)areap; *areap32 = SDL_SwapBE32(value); } Uint32 SDLNet_Read32(void* areap) { Uint32* areap32 = cast(Uint32*)areap; return SDL_SwapBE32(*areap32); } extern(C) { alias CSDLVERPTR function() da_SDLNet_Linked_Version; alias int function() da_SDLNet_Init; alias void function() da_SDLNet_Quit; alias int function(IPaddress*, in char*, Uint16) da_SDLNet_ResolveHost; alias CCPTR function(in IPaddress*) da_SDLNet_ResolveIP; alias int function(IPaddress*, int) da_SDLNet_GetLocalAddresses; alias TCPsocket function(IPaddress*) da_SDLNet_TCP_Open; alias TCPsocket function(TCPsocket) da_SDLNet_TCP_Accept; alias IPaddress* function(TCPsocket) da_SDLNet_TCP_GetPeerAddress; alias int function(TCPsocket,in void*,int) da_SDLNet_TCP_Send; alias int function(TCPsocket,void*,int) da_SDLNet_TCP_Recv; alias void function(TCPsocket) da_SDLNet_TCP_Close; alias UDPpacket* function(int) da_SDLNet_AllocPacket; alias int function(UDPpacket*) da_SDLNet_ResizePacket; alias void function(UDPpacket*) da_SDLNet_FreePacket; alias UDPpacket** function(int,int) da_SDLNet_AllocPacketV; alias void function(UDPpacket**) da_SDLNet_FreePacketV; alias UDPsocket function(Uint16) da_SDLNet_UDP_Open; alias void function(Uint16) da_SDLNet_UDP_SetPacketLoss; alias int function(UDPsocket,int,IPaddress*) da_SDLNet_UDP_Bind; alias void function(UDPsocket,int) da_SDLNet_UDP_Unbind; alias IPaddress* function(UDPsocket,int) da_SDLNet_UDP_GetPeerAddress; alias int function(UDPsocket,UDPpacket**,int) da_SDLNet_UDP_SendV; alias int function(UDPsocket,int,UDPpacket*) da_SDLNet_UDP_Send; alias int function(UDPsocket,UDPpacket**) da_SDLNet_UDP_RecvV; alias int function(UDPsocket,UDPpacket*) da_SDLNet_UDP_Recv; alias void function(UDPsocket) da_SDLNet_UDP_Close; alias SDLNet_SocketSet function(int) da_SDLNet_AllocSocketSet; alias int function(SDLNet_SocketSet,SDLNet_GenericSocket) da_SDLNet_AddSocket; alias int function(SDLNet_SocketSet,SDLNet_GenericSocket) da_SDLNet_DelSocket; alias int function(SDLNet_SocketSet,Uint32) da_SDLNet_CheckSockets; alias void function(SDLNet_SocketSet) da_SDLNet_FreeSocketSet; } mixin(gsharedString!() ~ " da_SDLNet_Linked_Version SDLNet_Linked_Version; da_SDLNet_Init SDLNet_Init; da_SDLNet_Quit SDLNet_Quit; da_SDLNet_ResolveHost SDLNet_ResolveHost; da_SDLNet_ResolveIP SDLNet_ResolveIP; da_SDLNet_GetLocalAddresses SDLNet_GetLocalAddresses; da_SDLNet_TCP_Open SDLNet_TCP_Open; da_SDLNet_TCP_Accept SDLNet_TCP_Accept; da_SDLNet_TCP_GetPeerAddress SDLNet_TCP_GetPeerAddress; da_SDLNet_TCP_Send SDLNet_TCP_Send; da_SDLNet_TCP_Recv SDLNet_TCP_Recv; da_SDLNet_TCP_Close SDLNet_TCP_Close; da_SDLNet_AllocPacket SDLNet_AllocPacket; da_SDLNet_ResizePacket SDLNet_ResizePacket; da_SDLNet_FreePacket SDLNet_FreePacket; da_SDLNet_AllocPacketV SDLNet_AllocPacketV; da_SDLNet_FreePacketV SDLNet_FreePacketV; da_SDLNet_UDP_Open SDLNet_UDP_Open; da_SDLNet_UDP_SetPacketLoss SDLNet_UDP_SetPacketLoss; da_SDLNet_UDP_Bind SDLNet_UDP_Bind; da_SDLNet_UDP_Unbind SDLNet_UDP_Unbind; da_SDLNet_UDP_GetPeerAddress SDLNet_UDP_GetPeerAddress; da_SDLNet_UDP_SendV SDLNet_UDP_SendV; da_SDLNet_UDP_Send SDLNet_UDP_Send; da_SDLNet_UDP_RecvV SDLNet_UDP_RecvV; da_SDLNet_UDP_Recv SDLNet_UDP_Recv; da_SDLNet_UDP_Close SDLNet_UDP_Close; da_SDLNet_AllocSocketSet SDLNet_AllocSocketSet; da_SDLNet_AddSocket SDLNet_AddSocket; da_SDLNet_DelSocket SDLNet_DelSocket; da_SDLNet_CheckSockets SDLNet_CheckSockets; da_SDLNet_FreeSocketSet SDLNet_FreeSocketSet; "); class DerelictSDLNetLoader : SharedLibLoader { public: this() { super( "SDL_net.dll", "libSDL_net.so, libSDL_net-1.2.so, libSDL_net-1.2.so.0", "../Frameworks/SDL_net.framework/SDL_net, /Library/Frameworks/SDL_net.framework/SDL_net, /System/Library/Frameworks/SDL_net.framework/SDL_net" ); } protected: override void loadSymbols() { if(!DerelictSDL.isLoaded) { throw new SharedLibLoadException("DerelictSDL must be loaded before attempting to load DerelictSDLNet!"); } bindFunc(cast(void**)&SDLNet_Linked_Version, "SDLNet_Linked_Version"); bindFunc(cast(void**)&SDLNet_Init, "SDLNet_Init"); bindFunc(cast(void**)&SDLNet_Quit, "SDLNet_Quit"); bindFunc(cast(void**)&SDLNet_ResolveHost, "SDLNet_ResolveHost"); bindFunc(cast(void**)&SDLNet_ResolveIP, "SDLNet_ResolveIP"); bindFunc(cast(void**)&SDLNet_GetLocalAddresses, "SDLNet_GetLocalAddresses"); bindFunc(cast(void**)&SDLNet_TCP_Open, "SDLNet_TCP_Open"); bindFunc(cast(void**)&SDLNet_TCP_Accept, "SDLNet_TCP_Accept"); bindFunc(cast(void**)&SDLNet_TCP_GetPeerAddress, "SDLNet_TCP_GetPeerAddress"); bindFunc(cast(void**)&SDLNet_TCP_Send, "SDLNet_TCP_Send"); bindFunc(cast(void**)&SDLNet_TCP_Recv, "SDLNet_TCP_Recv"); bindFunc(cast(void**)&SDLNet_TCP_Close, "SDLNet_TCP_Close"); bindFunc(cast(void**)&SDLNet_AllocPacket, "SDLNet_AllocPacket"); bindFunc(cast(void**)&SDLNet_ResizePacket, "SDLNet_ResizePacket"); bindFunc(cast(void**)&SDLNet_FreePacket, "SDLNet_FreePacket"); bindFunc(cast(void**)&SDLNet_AllocPacketV, "SDLNet_AllocPacketV"); bindFunc(cast(void**)&SDLNet_FreePacketV, "SDLNet_FreePacketV"); bindFunc(cast(void**)&SDLNet_UDP_Open, "SDLNet_UDP_Open"); bindFunc(cast(void**)&SDLNet_UDP_SetPacketLoss, "SDLNet_UDP_SetPacketLoss"); bindFunc(cast(void**)&SDLNet_UDP_Bind, "SDLNet_UDP_Bind"); bindFunc(cast(void**)&SDLNet_UDP_Unbind, "SDLNet_UDP_Unbind"); bindFunc(cast(void**)&SDLNet_UDP_GetPeerAddress, "SDLNet_UDP_GetPeerAddress"); bindFunc(cast(void**)&SDLNet_UDP_SendV, "SDLNet_UDP_SendV"); bindFunc(cast(void**)&SDLNet_UDP_Send, "SDLNet_UDP_Send"); bindFunc(cast(void**)&SDLNet_UDP_RecvV, "SDLNet_UDP_RecvV"); bindFunc(cast(void**)&SDLNet_UDP_Recv, "SDLNet_UDP_Recv"); bindFunc(cast(void**)&SDLNet_UDP_Close, "SDLNet_UDP_Close"); bindFunc(cast(void**)&SDLNet_AllocSocketSet, "SDLNet_AllocSocketSet"); bindFunc(cast(void**)&SDLNet_AddSocket, "SDLNet_AddSocket"); bindFunc(cast(void**)&SDLNet_DelSocket, "SDLNet_DelSocket"); bindFunc(cast(void**)&SDLNet_CheckSockets, "SDLNet_CheckSockets"); bindFunc(cast(void**)&SDLNet_FreeSocketSet, "SDLNet_FreeSocketSet"); } } DerelictSDLNetLoader DerelictSDLNet; static this() { DerelictSDLNet = new DerelictSDLNetLoader(); } static ~this() { if(SharedLibLoader.isAutoUnloadEnabled()) DerelictSDLNet.unload(); }CheeseCutter-master/src/derelict/sdl/sdl.d000066400000000000000000000353351357241101300210330ustar00rootroot00000000000000/* Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ module derelict.sdl.sdl; public { import derelict.sdl.sdltypes; import derelict.sdl.sdlfuncs; } private { import derelict.util.loader; version(darwin) version = MacOSX; version(OSX) version = MacOSX; version (MacOSX) import derelict.sdl.macinit.SDLMain; } class DerelictSDLLoader : SharedLibLoader { public: this() { super( "sdl.dll", "libSDL.so, libSDL.so.0, libSDL-1.2.so, libSDL-1.2.so.0", "@executable_path/../Frameworks/SDL.framework/SDL, /Library/Frameworks/SDL.framework/SDL, /System/Library/Frameworks/SDL.framework/SDL" ); } protected: override void loadSymbols() { // active.d bindFunc(cast(void**)&SDL_GetAppState, "SDL_GetAppState"); // audio.d bindFunc(cast(void**)&SDL_AudioInit, "SDL_AudioInit"); bindFunc(cast(void**)&SDL_AudioQuit, "SDL_AudioQuit"); bindFunc(cast(void**)&SDL_AudioDriverName, "SDL_AudioDriverName"); bindFunc(cast(void**)&SDL_OpenAudio, "SDL_OpenAudio"); bindFunc(cast(void**)&SDL_GetAudioStatus, "SDL_GetAudioStatus"); bindFunc(cast(void**)&SDL_PauseAudio, "SDL_PauseAudio"); bindFunc(cast(void**)&SDL_LoadWAV_RW, "SDL_LoadWAV_RW"); bindFunc(cast(void**)&SDL_FreeWAV, "SDL_FreeWAV"); bindFunc(cast(void**)&SDL_BuildAudioCVT, "SDL_BuildAudioCVT"); bindFunc(cast(void**)&SDL_ConvertAudio, "SDL_ConvertAudio"); bindFunc(cast(void**)&SDL_MixAudio, "SDL_MixAudio"); bindFunc(cast(void**)&SDL_LockAudio, "SDL_LockAudio"); bindFunc(cast(void**)&SDL_UnlockAudio, "SDL_UnlockAudio"); bindFunc(cast(void**)&SDL_CloseAudio, "SDL_CloseAudio"); // cdrom.d bindFunc(cast(void**)&SDL_CDNumDrives, "SDL_CDNumDrives"); bindFunc(cast(void**)&SDL_CDName, "SDL_CDName"); bindFunc(cast(void**)&SDL_CDOpen, "SDL_CDOpen"); bindFunc(cast(void**)&SDL_CDStatus, "SDL_CDStatus"); bindFunc(cast(void**)&SDL_CDPlayTracks, "SDL_CDPlayTracks"); bindFunc(cast(void**)&SDL_CDPlay, "SDL_CDPlay"); bindFunc(cast(void**)&SDL_CDPause, "SDL_CDPause"); bindFunc(cast(void**)&SDL_CDResume, "SDL_CDResume"); bindFunc(cast(void**)&SDL_CDStop, "SDL_CDStop"); bindFunc(cast(void**)&SDL_CDEject, "SDL_CDEject"); bindFunc(cast(void**)&SDL_CDClose, "SDL_CDClose"); // cpuinfo.d bindFunc(cast(void**)&SDL_HasRDTSC, "SDL_HasRDTSC"); bindFunc(cast(void**)&SDL_HasMMX, "SDL_HasMMX"); bindFunc(cast(void**)&SDL_HasMMXExt, "SDL_HasMMXExt"); bindFunc(cast(void**)&SDL_Has3DNow, "SDL_Has3DNow"); bindFunc(cast(void**)&SDL_Has3DNowExt, "SDL_Has3DNowExt"); bindFunc(cast(void**)&SDL_HasSSE, "SDL_HasSSE"); bindFunc(cast(void**)&SDL_HasSSE2, "SDL_HasSSE2"); bindFunc(cast(void**)&SDL_HasAltiVec, "SDL_HasAltiVec"); // error.d bindFunc(cast(void**)&SDL_SetError, "SDL_SetError"); bindFunc(cast(void**)&SDL_GetError, "SDL_GetError"); bindFunc(cast(void**)&SDL_ClearError, "SDL_ClearError"); // events.d bindFunc(cast(void**)&SDL_PumpEvents, "SDL_PumpEvents"); bindFunc(cast(void**)&SDL_PeepEvents, "SDL_PeepEvents"); bindFunc(cast(void**)&SDL_PollEvent, "SDL_PollEvent"); bindFunc(cast(void**)&SDL_WaitEvent, "SDL_WaitEvent"); bindFunc(cast(void**)&SDL_PushEvent, "SDL_PushEvent"); bindFunc(cast(void**)&SDL_SetEventFilter, "SDL_SetEventFilter"); bindFunc(cast(void**)&SDL_GetEventFilter, "SDL_GetEventFilter"); bindFunc(cast(void**)&SDL_EventState, "SDL_EventState"); // joystick.d bindFunc(cast(void**)&SDL_NumJoysticks, "SDL_NumJoysticks"); bindFunc(cast(void**)&SDL_JoystickName, "SDL_JoystickName"); bindFunc(cast(void**)&SDL_JoystickOpen, "SDL_JoystickOpen"); bindFunc(cast(void**)&SDL_JoystickOpened, "SDL_JoystickOpened"); bindFunc(cast(void**)&SDL_JoystickIndex, "SDL_JoystickIndex"); bindFunc(cast(void**)&SDL_JoystickNumAxes, "SDL_JoystickNumAxes"); bindFunc(cast(void**)&SDL_JoystickNumBalls, "SDL_JoystickNumBalls"); bindFunc(cast(void**)&SDL_JoystickNumHats, "SDL_JoystickNumHats"); bindFunc(cast(void**)&SDL_JoystickNumButtons, "SDL_JoystickNumButtons"); bindFunc(cast(void**)&SDL_JoystickUpdate, "SDL_JoystickUpdate"); bindFunc(cast(void**)&SDL_JoystickEventState, "SDL_JoystickEventState"); bindFunc(cast(void**)&SDL_JoystickGetAxis, "SDL_JoystickGetAxis"); bindFunc(cast(void**)&SDL_JoystickGetHat, "SDL_JoystickGetHat"); bindFunc(cast(void**)&SDL_JoystickGetBall, "SDL_JoystickGetBall"); bindFunc(cast(void**)&SDL_JoystickGetButton, "SDL_JoystickGetButton"); bindFunc(cast(void**)&SDL_JoystickClose, "SDL_JoystickClose"); // keyboard.d bindFunc(cast(void**)&SDL_EnableUNICODE, "SDL_EnableUNICODE"); bindFunc(cast(void**)&SDL_EnableKeyRepeat, "SDL_EnableKeyRepeat"); bindFunc(cast(void**)&SDL_GetKeyRepeat, "SDL_GetKeyRepeat"); bindFunc(cast(void**)&SDL_GetKeyState, "SDL_GetKeyState"); bindFunc(cast(void**)&SDL_GetModState, "SDL_GetModState"); bindFunc(cast(void**)&SDL_SetModState, "SDL_SetModState"); bindFunc(cast(void**)&SDL_GetKeyName, "SDL_GetKeyName"); // loadso.d bindFunc(cast(void**)&SDL_LoadObject, "SDL_LoadObject"); bindFunc(cast(void**)&SDL_LoadFunction, "SDL_LoadFunction"); bindFunc(cast(void**)&SDL_UnloadObject, "SDL_UnloadObject"); // mouse.d bindFunc(cast(void**)&SDL_GetMouseState, "SDL_GetMouseState"); bindFunc(cast(void**)&SDL_GetRelativeMouseState, "SDL_GetRelativeMouseState"); bindFunc(cast(void**)&SDL_WarpMouse, "SDL_WarpMouse"); bindFunc(cast(void**)&SDL_CreateCursor, "SDL_CreateCursor"); bindFunc(cast(void**)&SDL_SetCursor, "SDL_SetCursor"); bindFunc(cast(void**)&SDL_GetCursor, "SDL_GetCursor"); bindFunc(cast(void**)&SDL_FreeCursor, "SDL_FreeCursor"); bindFunc(cast(void**)&SDL_ShowCursor, "SDL_ShowCursor"); // mutex.d bindFunc(cast(void**)&SDL_CreateMutex, "SDL_CreateMutex"); bindFunc(cast(void**)&SDL_mutexP, "SDL_mutexP"); bindFunc(cast(void**)&SDL_mutexV, "SDL_mutexV"); bindFunc(cast(void**)&SDL_DestroyMutex, "SDL_DestroyMutex"); bindFunc(cast(void**)&SDL_CreateSemaphore, "SDL_CreateSemaphore"); bindFunc(cast(void**)&SDL_DestroySemaphore, "SDL_DestroySemaphore"); bindFunc(cast(void**)&SDL_SemWait, "SDL_SemWait"); bindFunc(cast(void**)&SDL_SemTryWait, "SDL_SemTryWait"); bindFunc(cast(void**)&SDL_SemWaitTimeout, "SDL_SemWaitTimeout"); bindFunc(cast(void**)&SDL_SemPost, "SDL_SemPost"); bindFunc(cast(void**)&SDL_SemValue, "SDL_SemValue"); bindFunc(cast(void**)&SDL_CreateCond, "SDL_CreateCond"); bindFunc(cast(void**)&SDL_DestroyCond, "SDL_DestroyCond"); bindFunc(cast(void**)&SDL_CondSignal, "SDL_CondSignal"); bindFunc(cast(void**)&SDL_CondBroadcast, "SDL_CondBroadcast"); bindFunc(cast(void**)&SDL_CondWait, "SDL_CondWait"); bindFunc(cast(void**)&SDL_CondWaitTimeout, "SDL_CondWaitTimeout"); // rwops.d bindFunc(cast(void**)&SDL_RWFromFile, "SDL_RWFromFile"); bindFunc(cast(void**)&SDL_RWFromFP, "SDL_RWFromFP"); bindFunc(cast(void**)&SDL_RWFromMem, "SDL_RWFromMem"); bindFunc(cast(void**)&SDL_RWFromConstMem, "SDL_RWFromConstMem"); bindFunc(cast(void**)&SDL_AllocRW, "SDL_AllocRW"); bindFunc(cast(void**)&SDL_FreeRW, "SDL_FreeRW"); bindFunc(cast(void**)&SDL_ReadLE16, "SDL_ReadLE16"); bindFunc(cast(void**)&SDL_ReadBE16, "SDL_ReadBE16"); bindFunc(cast(void**)&SDL_ReadLE32, "SDL_ReadLE32"); bindFunc(cast(void**)&SDL_ReadBE32, "SDL_ReadBE32"); bindFunc(cast(void**)&SDL_ReadLE64, "SDL_ReadLE64"); bindFunc(cast(void**)&SDL_ReadBE64, "SDL_ReadBE64"); bindFunc(cast(void**)&SDL_WriteLE16, "SDL_WriteLE16"); bindFunc(cast(void**)&SDL_WriteBE16, "SDL_WriteBE16"); bindFunc(cast(void**)&SDL_WriteLE32, "SDL_WriteLE32"); bindFunc(cast(void**)&SDL_WriteBE32, "SDL_WriteBE32"); bindFunc(cast(void**)&SDL_WriteLE64, "SDL_WriteLE64"); bindFunc(cast(void**)&SDL_WriteBE64, "SDL_WriteBE64"); // sdlversion.d bindFunc(cast(void**)&SDL_Linked_Version, "SDL_Linked_Version"); // thread.d bindFunc(cast(void**)&SDL_CreateThread, "SDL_CreateThread"); bindFunc(cast(void**)&SDL_ThreadID, "SDL_ThreadID"); bindFunc(cast(void**)&SDL_GetThreadID, "SDL_GetThreadID"); bindFunc(cast(void**)&SDL_WaitThread, "SDL_WaitThread"); bindFunc(cast(void**)&SDL_KillThread, "SDL_KillThread"); // timer.d bindFunc(cast(void**)&SDL_GetTicks, "SDL_GetTicks"); bindFunc(cast(void**)&SDL_Delay, "SDL_Delay"); bindFunc(cast(void**)&SDL_SetTimer, "SDL_SetTimer"); bindFunc(cast(void**)&SDL_AddTimer, "SDL_AddTimer"); bindFunc(cast(void**)&SDL_RemoveTimer, "SDL_RemoveTimer"); // video.d bindFunc(cast(void**)&SDL_VideoInit, "SDL_VideoInit"); bindFunc(cast(void**)&SDL_VideoQuit, "SDL_VideoQuit"); bindFunc(cast(void**)&SDL_VideoDriverName, "SDL_VideoDriverName"); bindFunc(cast(void**)&SDL_GetVideoSurface, "SDL_GetVideoSurface"); bindFunc(cast(void**)&SDL_GetVideoInfo, "SDL_GetVideoInfo"); bindFunc(cast(void**)&SDL_VideoModeOK, "SDL_VideoModeOK"); bindFunc(cast(void**)&SDL_ListModes, "SDL_ListModes"); bindFunc(cast(void**)&SDL_SetVideoMode, "SDL_SetVideoMode"); bindFunc(cast(void**)&SDL_UpdateRects, "SDL_UpdateRects"); bindFunc(cast(void**)&SDL_UpdateRect, "SDL_UpdateRect"); bindFunc(cast(void**)&SDL_Flip, "SDL_Flip"); bindFunc(cast(void**)&SDL_SetGamma, "SDL_SetGamma"); bindFunc(cast(void**)&SDL_SetGammaRamp, "SDL_SetGammaRamp"); bindFunc(cast(void**)&SDL_GetGammaRamp, "SDL_GetGammaRamp"); bindFunc(cast(void**)&SDL_SetColors, "SDL_SetColors"); bindFunc(cast(void**)&SDL_SetPalette, "SDL_SetPalette"); bindFunc(cast(void**)&SDL_MapRGB, "SDL_MapRGB"); bindFunc(cast(void**)&SDL_MapRGBA, "SDL_MapRGBA"); bindFunc(cast(void**)&SDL_GetRGB, "SDL_GetRGB"); bindFunc(cast(void**)&SDL_GetRGBA, "SDL_GetRGBA"); bindFunc(cast(void**)&SDL_CreateRGBSurface, "SDL_CreateRGBSurface"); bindFunc(cast(void**)&SDL_CreateRGBSurfaceFrom, "SDL_CreateRGBSurfaceFrom"); bindFunc(cast(void**)&SDL_FreeSurface, "SDL_FreeSurface"); bindFunc(cast(void**)&SDL_LockSurface, "SDL_LockSurface"); bindFunc(cast(void**)&SDL_UnlockSurface, "SDL_UnlockSurface"); bindFunc(cast(void**)&SDL_LoadBMP_RW, "SDL_LoadBMP_RW"); bindFunc(cast(void**)&SDL_SaveBMP_RW, "SDL_SaveBMP_RW"); bindFunc(cast(void**)&SDL_SetColorKey, "SDL_SetColorKey"); bindFunc(cast(void**)&SDL_SetAlpha, "SDL_SetAlpha"); bindFunc(cast(void**)&SDL_SetClipRect, "SDL_SetClipRect"); bindFunc(cast(void**)&SDL_GetClipRect, "SDL_GetClipRect"); bindFunc(cast(void**)&SDL_ConvertSurface, "SDL_ConvertSurface"); bindFunc(cast(void**)&SDL_UpperBlit, "SDL_UpperBlit"); bindFunc(cast(void**)&SDL_LowerBlit, "SDL_LowerBlit"); bindFunc(cast(void**)&SDL_FillRect, "SDL_FillRect"); bindFunc(cast(void**)&SDL_DisplayFormat, "SDL_DisplayFormat"); bindFunc(cast(void**)&SDL_DisplayFormatAlpha, "SDL_DisplayFormatAlpha"); bindFunc(cast(void**)&SDL_CreateYUVOverlay, "SDL_CreateYUVOverlay"); bindFunc(cast(void**)&SDL_LockYUVOverlay, "SDL_LockYUVOverlay"); bindFunc(cast(void**)&SDL_UnlockYUVOverlay, "SDL_UnlockYUVOverlay"); bindFunc(cast(void**)&SDL_DisplayYUVOverlay, "SDL_DisplayYUVOverlay"); bindFunc(cast(void**)&SDL_FreeYUVOverlay, "SDL_FreeYUVOverlay"); bindFunc(cast(void**)&SDL_GL_LoadLibrary, "SDL_GL_LoadLibrary"); bindFunc(cast(void**)&SDL_GL_GetProcAddress, "SDL_GL_GetProcAddress"); bindFunc(cast(void**)&SDL_GL_SetAttribute, "SDL_GL_SetAttribute"); bindFunc(cast(void**)&SDL_GL_GetAttribute, "SDL_GL_GetAttribute"); bindFunc(cast(void**)&SDL_GL_SwapBuffers, "SDL_GL_SwapBuffers"); bindFunc(cast(void**)&SDL_GL_UpdateRects, "SDL_GL_UpdateRects"); bindFunc(cast(void**)&SDL_GL_Lock, "SDL_GL_Lock"); bindFunc(cast(void**)&SDL_GL_Unlock, "SDL_GL_Unlock"); bindFunc(cast(void**)&SDL_WM_SetCaption, "SDL_WM_SetCaption"); bindFunc(cast(void**)&SDL_WM_GetCaption, "SDL_WM_GetCaption"); bindFunc(cast(void**)&SDL_WM_SetIcon, "SDL_WM_SetIcon"); bindFunc(cast(void**)&SDL_WM_IconifyWindow, "SDL_WM_IconifyWindow"); bindFunc(cast(void**)&SDL_WM_ToggleFullScreen, "SDL_WM_ToggleFullScreen"); bindFunc(cast(void**)&SDL_WM_GrabInput, "SDL_WM_GrabInput"); // sdl.d bindFunc(cast(void**)&SDL_Init, "SDL_Init"); bindFunc(cast(void**)&SDL_InitSubSystem, "SDL_InitSubSystem"); bindFunc(cast(void**)&SDL_QuitSubSystem, "SDL_QuitSubSystem"); bindFunc(cast(void**)&SDL_WasInit, "SDL_WasInit"); bindFunc(cast(void**)&SDL_Quit, "SDL_Quit"); // syswm.d version(Windows) bindFunc(cast(void**)&SDL_GetWMInfo, "SDL_GetWMInfo"); } } __gshared DerelictSDLLoader DerelictSDL; static this() { DerelictSDL = new DerelictSDLLoader(); } static ~this() { if(SharedLibLoader.isAutoUnloadEnabled()) DerelictSDL.unload(); } CheeseCutter-master/src/derelict/sdl/sdlfuncs.d000066400000000000000000000514061357241101300220670ustar00rootroot00000000000000/* Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ module derelict.sdl.sdlfuncs; private { import derelict.util.compat; import derelict.sdl.sdltypes; version(Tango) { import tango.stdc.stdio; } else { import core.stdc.stdio; } } SDL_AudioSpec* SDL_LoadWAV(in char* file, SDL_AudioSpec* spec, Uint8** buf, Uint32* len) { return SDL_LoadWAV_RW(SDL_RWFromFile(file, "rb"), 1, spec, buf, len); } int SDL_QuitRequested() { SDL_PumpEvents(); return SDL_PeepEvents(null, 0, SDL_PEEKEVENT, SDL_QUITMASK); } int SDL_LockMutex(SDL_mutex *mutex) { return SDL_mutexP(mutex); } int SDL_UnlockMutex(SDL_mutex *mutex) { return SDL_mutexV(mutex); } SDL_Surface* SDL_LoadBMP(in char* file) { return SDL_LoadBMP_RW(SDL_RWFromFile(file, "rb"), 1); } int SDL_SaveBMP(SDL_Surface* surface, in char* file) { return SDL_SaveBMP_RW(surface, SDL_RWFromFile(file,"wb"), 1); } version(D_Version2) { mixin("alias const(SDL_VideoInfo*) SDLVIPTR;"); } else { alias SDL_VideoInfo* SDLVIPTR; } extern(C) { // SDL.h alias int function(Uint32) da_SDL_Init; alias int function(Uint32) da_SDL_InitSubSystem; alias void function(Uint32) da_SDL_QuitSubSystem; alias Uint32 function(Uint32) da_SDL_WasInit; alias void function() da_SDL_Quit; // SDL_active.h alias Uint8 function() da_SDL_GetAppState; // SDL_audio.h alias int function(in char*) da_SDL_AudioInit; alias void function() da_SDL_AudioQuit; alias char* function(char*,int) da_SDL_AudioDriverName; alias int function(SDL_AudioSpec*,SDL_AudioSpec*) da_SDL_OpenAudio; alias SDL_audiostatus function() da_SDL_GetAudioStatus; alias void function(int) da_SDL_PauseAudio; alias SDL_AudioSpec* function(SDL_RWops*,int,SDL_AudioSpec*,Uint8**,Uint32*) da_SDL_LoadWAV_RW; alias void function(Uint8*) da_SDL_FreeWAV; alias int function(SDL_AudioCVT*,Uint16,Uint8,int,Uint16,Uint8,int) da_SDL_BuildAudioCVT; alias int function(SDL_AudioCVT*) da_SDL_ConvertAudio; alias void function(Uint8*,in Uint8*,Uint32,int) da_SDL_MixAudio; alias void function() da_SDL_LockAudio; alias void function() da_SDL_UnlockAudio; alias void function() da_SDL_CloseAudio; // SDL_cdrom.h alias int function() da_SDL_CDNumDrives; alias CCPTR function(int) da_SDL_CDName; alias SDL_CD* function(int) da_SDL_CDOpen; alias CDstatus function(SDL_CD*) da_SDL_CDStatus; alias int function(SDL_CD*,int,int,int,int) da_SDL_CDPlayTracks; alias int function(SDL_CD*,int,int) da_SDL_CDPlay; alias int function(SDL_CD*) da_SDL_CDPause; alias int function(SDL_CD*) da_SDL_CDResume; alias int function(SDL_CD*) da_SDL_CDStop; alias int function(SDL_CD*) da_SDL_CDEject; alias int function(SDL_CD*) da_SDL_CDClose; // SDL_cpuinfo.h alias SDL_bool function() da_SDL_HasRDTSC; alias SDL_bool function() da_SDL_HasMMX; alias SDL_bool function() da_SDL_HasMMXExt; alias SDL_bool function() da_SDL_Has3DNow; alias SDL_bool function() da_SDL_Has3DNowExt; alias SDL_bool function() da_SDL_HasSSE; alias SDL_bool function() da_SDL_HasSSE2; alias SDL_bool function() da_SDL_HasAltiVec; // SDL_error.h alias void function(in char*,...) da_SDL_SetError; alias char* function() da_SDL_GetError; alias void function() da_SDL_ClearError; // SDL_events.h alias void function() da_SDL_PumpEvents; alias int function(SDL_Event*,int,SDL_eventaction,Uint32) da_SDL_PeepEvents; alias int function(SDL_Event*) da_SDL_PollEvent; alias int function(SDL_Event*) da_SDL_WaitEvent; alias int function(SDL_Event*) da_SDL_PushEvent; alias void function(SDL_EventFilter) da_SDL_SetEventFilter; alias SDL_EventFilter function() da_SDL_GetEventFilter; alias Uint8 function(Uint8,int) da_SDL_EventState; // SDL_joystick.h alias int function() da_SDL_NumJoysticks; alias CCPTR function(int) da_SDL_JoystickName; alias SDL_Joystick* function(int) da_SDL_JoystickOpen; alias int function(int) da_SDL_JoystickOpened; alias int function(SDL_Joystick*) da_SDL_JoystickIndex; alias int function(SDL_Joystick*) da_SDL_JoystickNumAxes; alias int function(SDL_Joystick*) da_SDL_JoystickNumBalls; alias int function(SDL_Joystick*) da_SDL_JoystickNumHats; alias int function(SDL_Joystick*) da_SDL_JoystickNumButtons; alias void function() da_SDL_JoystickUpdate; alias int function(int) da_SDL_JoystickEventState; alias Sint16 function(SDL_Joystick*,int) da_SDL_JoystickGetAxis; alias Uint8 function(SDL_Joystick*,int) da_SDL_JoystickGetHat; alias int function(SDL_Joystick*,int,int*,int*) da_SDL_JoystickGetBall; alias Uint8 function(SDL_Joystick*,int) da_SDL_JoystickGetButton; alias void function(SDL_Joystick*) da_SDL_JoystickClose; // SDL_keyboard.h alias int function(int) da_SDL_EnableUNICODE; alias int function(int,int) da_SDL_EnableKeyRepeat; alias void function(int*,int*) da_SDL_GetKeyRepeat; alias Uint8* function(int*) da_SDL_GetKeyState; alias SDLMod function() da_SDL_GetModState; alias void function(SDLMod) da_SDL_SetModState; alias char* function(SDLKey key) da_SDL_GetKeyName; // SDL_loadso.h alias void* function(in char*) da_SDL_LoadObject; alias void* function(in void*,char*) da_SDL_LoadFunction; alias void function(void*) da_SDL_UnloadObject; // SDL_mouse.h alias Uint8 function(int*,int*) da_SDL_GetMouseState; alias Uint8 function(int*,int*) da_SDL_GetRelativeMouseState; alias void function(Uint16,Uint16) da_SDL_WarpMouse; alias SDL_Cursor* function(Uint8*,Uint8*,int,int,int,int) da_SDL_CreateCursor; alias void function(SDL_Cursor*) da_SDL_SetCursor; alias SDL_Cursor* function() da_SDL_GetCursor; alias void function(SDL_Cursor*) da_SDL_FreeCursor; alias int function(int) da_SDL_ShowCursor; // SDL_mutex.h alias SDL_mutex* function() da_SDL_CreateMutex; alias int function(SDL_mutex*) da_SDL_mutexP; alias int function(SDL_mutex*) da_SDL_mutexV; alias void function(SDL_mutex*) da_SDL_DestroyMutex; alias SDL_sem* function(Uint32) da_SDL_CreateSemaphore; alias void function(SDL_sem*) da_SDL_DestroySemaphore; alias int function(SDL_sem*) da_SDL_SemWait; alias int function(SDL_sem*) da_SDL_SemTryWait; alias int function(SDL_sem*,Uint32) da_SDL_SemWaitTimeout; alias int function(SDL_sem*) da_SDL_SemPost; alias Uint32 function(SDL_sem*) da_SDL_SemValue; alias SDL_cond* function() da_SDL_CreateCond; alias void function(SDL_cond*) da_SDL_DestroyCond; alias int function(SDL_cond*) da_SDL_CondSignal; alias int function(SDL_cond*) da_SDL_CondBroadcast; alias int function(SDL_cond*,SDL_mutex*) da_SDL_CondWait; alias int function(SDL_cond*,SDL_mutex*,Uint32) da_SDL_CondWaitTimeout; // SDL_rwops.h alias SDL_RWops* function(in char*,in char*) da_SDL_RWFromFile; alias SDL_RWops* function(FILE*,int) da_SDL_RWFromFP; alias SDL_RWops* function(void*,int) da_SDL_RWFromMem; alias SDL_RWops* function(in void*,int) da_SDL_RWFromConstMem; alias SDL_RWops* function() da_SDL_AllocRW; alias void function(SDL_RWops*) da_SDL_FreeRW; alias Uint16 function(SDL_RWops*) da_SDL_ReadLE16; alias Uint16 function(SDL_RWops*) da_SDL_ReadBE16; alias Uint32 function(SDL_RWops*) da_SDL_ReadLE32; alias Uint32 function(SDL_RWops*) da_SDL_ReadBE32; alias Uint64 function(SDL_RWops*) da_SDL_ReadLE64; alias Uint64 function(SDL_RWops*) da_SDL_ReadBE64; alias Uint16 function(SDL_RWops*,Uint16) da_SDL_WriteLE16; alias Uint16 function(SDL_RWops*,Uint16) da_SDL_WriteBE16; alias Uint32 function(SDL_RWops*,Uint32) da_SDL_WriteLE32; alias Uint32 function(SDL_RWops*,Uint32) da_SDL_WriteBE32; alias Uint64 function(SDL_RWops*,Uint64) da_SDL_WriteLE64; alias Uint64 function(SDL_RWops*,Uint64) da_SDL_WriteBE64; // SDL_version.h alias CSDLVERPTR function() da_SDL_Linked_Version; // SDL_syswm.h alias int function(SDL_SysWMinfo*) da_SDL_GetWMInfo; // SDL_thread.h alias SDL_Thread* function(int function(void*) fm, void*) da_SDL_CreateThread; alias Uint32 function() da_SDL_ThreadID; alias Uint32 function(SDL_Thread*) da_SDL_GetThreadID; alias void function(SDL_Thread*,int*) da_SDL_WaitThread; alias void function(SDL_Thread*) da_SDL_KillThread; // SDL_timer.h alias Uint32 function() da_SDL_GetTicks; alias void function(Uint32) da_SDL_Delay; alias int function(Uint32,SDL_TimerCallback) da_SDL_SetTimer; alias SDL_TimerID function(Uint32,SDL_NewTimerCallback,void*) da_SDL_AddTimer; alias SDL_bool function(SDL_TimerID) da_SDL_RemoveTimer; // SDL_video.h alias int function(in char*,Uint32) da_SDL_VideoInit; alias void function() da_SDL_VideoQuit; alias char* function(char*,int) da_SDL_VideoDriverName; alias SDL_Surface* function() da_SDL_GetVideoSurface; alias SDLVIPTR function() da_SDL_GetVideoInfo; alias int function(int,int,int,Uint32) da_SDL_VideoModeOK; alias SDL_Rect** function(SDL_PixelFormat*,Uint32) da_SDL_ListModes; alias SDL_Surface* function(int,int,int,Uint32) da_SDL_SetVideoMode; alias void function(SDL_Surface*,int,SDL_Rect*) da_SDL_UpdateRects; alias void function(SDL_Surface*,Sint32,Sint32,Uint32,Uint32) da_SDL_UpdateRect; alias int function(SDL_Surface*) da_SDL_Flip; alias int function(float,float,float) da_SDL_SetGamma; alias int function(in Uint16*,in Uint16*,in Uint16*) da_SDL_SetGammaRamp; alias int function(Uint16*,Uint16*,Uint16*) da_SDL_GetGammaRamp; alias int function(SDL_Surface*,SDL_Color*,int,int) da_SDL_SetColors; alias int function(SDL_Surface*,int,SDL_Color*,int,int) da_SDL_SetPalette; alias Uint32 function(in SDL_PixelFormat*,in Uint8,in Uint8,in Uint8) da_SDL_MapRGB; alias Uint32 function(in SDL_PixelFormat*, in Uint8,in Uint8,in Uint8,in Uint8) da_SDL_MapRGBA; alias void function(Uint32,SDL_PixelFormat*,Uint8*,Uint8*,Uint8*) da_SDL_GetRGB; alias void function(Uint32,SDL_PixelFormat*,Uint8*,Uint8*,Uint8*,Uint8*) da_SDL_GetRGBA; alias SDL_Surface* function(Uint32,int,int,int,Uint32,Uint32,Uint32,Uint32) da_SDL_CreateRGBSurface; alias SDL_Surface* function(void*,int,int,int,int,Uint32,Uint32,Uint32,Uint32) da_SDL_CreateRGBSurfaceFrom; alias void function(SDL_Surface*) da_SDL_FreeSurface; alias int function(SDL_Surface*) da_SDL_LockSurface; alias void function(SDL_Surface*) da_SDL_UnlockSurface; alias SDL_Surface* function(SDL_RWops*,int) da_SDL_LoadBMP_RW; alias int function(SDL_Surface*,SDL_RWops*,int) da_SDL_SaveBMP_RW; alias int function(SDL_Surface*,Uint32,Uint32) da_SDL_SetColorKey; alias int function(SDL_Surface*,Uint32,Uint8) da_SDL_SetAlpha; alias SDL_bool function(SDL_Surface*,in SDL_Rect*) da_SDL_SetClipRect; alias void function(SDL_Surface*,SDL_Rect*) da_SDL_GetClipRect; alias SDL_Surface* function(SDL_Surface*,SDL_PixelFormat*,Uint32) da_SDL_ConvertSurface; alias int function(SDL_Surface*,SDL_Rect*,SDL_Surface*,SDL_Rect*) da_SDL_UpperBlit; alias int function(SDL_Surface*,SDL_Rect*,SDL_Surface*,SDL_Rect*) da_SDL_LowerBlit; alias int function(SDL_Surface*,SDL_Rect*,Uint32) da_SDL_FillRect; alias SDL_Surface* function(SDL_Surface*) da_SDL_DisplayFormat; alias SDL_Surface* function(SDL_Surface*) da_SDL_DisplayFormatAlpha; alias SDL_Overlay* function(int,int,Uint32,SDL_Surface*) da_SDL_CreateYUVOverlay; alias int function(SDL_Overlay*) da_SDL_LockYUVOverlay; alias void function(SDL_Overlay*) da_SDL_UnlockYUVOverlay; alias int function(SDL_Overlay*,SDL_Rect*) da_SDL_DisplayYUVOverlay; alias void function(SDL_Overlay*) da_SDL_FreeYUVOverlay; alias int function(in char*) da_SDL_GL_LoadLibrary; alias void* function(in char*) da_SDL_GL_GetProcAddress; alias int function(SDL_GLattr,int) da_SDL_GL_SetAttribute; alias int function(SDL_GLattr,int*) da_SDL_GL_GetAttribute; alias void function() da_SDL_GL_SwapBuffers; alias void function(int,SDL_Rect*) da_SDL_GL_UpdateRects; alias void function() da_SDL_GL_Lock; alias void function() da_SDL_GL_Unlock; alias void function(in char*,in char*) da_SDL_WM_SetCaption; alias void function(char**,char**) da_SDL_WM_GetCaption; alias void function(SDL_Surface*,Uint8*) da_SDL_WM_SetIcon; alias int function() da_SDL_WM_IconifyWindow; alias int function(SDL_Surface*) da_SDL_WM_ToggleFullScreen; alias SDL_GrabMode function(SDL_GrabMode) da_SDL_WM_GrabInput; } mixin(gsharedString!() ~ " da_SDL_Init SDL_Init; da_SDL_InitSubSystem SDL_InitSubSystem; da_SDL_QuitSubSystem SDL_QuitSubSystem; da_SDL_WasInit SDL_WasInit; da_SDL_Quit SDL_Quit; da_SDL_GetAppState SDL_GetAppState; da_SDL_AudioInit SDL_AudioInit; da_SDL_AudioQuit SDL_AudioQuit; da_SDL_AudioDriverName SDL_AudioDriverName; da_SDL_OpenAudio SDL_OpenAudio; da_SDL_GetAudioStatus SDL_GetAudioStatus; da_SDL_PauseAudio SDL_PauseAudio; da_SDL_LoadWAV_RW SDL_LoadWAV_RW; da_SDL_FreeWAV SDL_FreeWAV; da_SDL_BuildAudioCVT SDL_BuildAudioCVT; da_SDL_ConvertAudio SDL_ConvertAudio; da_SDL_MixAudio SDL_MixAudio; da_SDL_LockAudio SDL_LockAudio; da_SDL_UnlockAudio SDL_UnlockAudio; da_SDL_CloseAudio SDL_CloseAudio; da_SDL_CDNumDrives SDL_CDNumDrives; da_SDL_CDName SDL_CDName; da_SDL_CDOpen SDL_CDOpen; da_SDL_CDStatus SDL_CDStatus; da_SDL_CDPlayTracks SDL_CDPlayTracks; da_SDL_CDPlay SDL_CDPlay; da_SDL_CDPause SDL_CDPause; da_SDL_CDResume SDL_CDResume; da_SDL_CDStop SDL_CDStop; da_SDL_CDEject SDL_CDEject; da_SDL_CDClose SDL_CDClose; da_SDL_HasRDTSC SDL_HasRDTSC; da_SDL_HasMMX SDL_HasMMX; da_SDL_HasMMXExt SDL_HasMMXExt; da_SDL_Has3DNow SDL_Has3DNow; da_SDL_Has3DNowExt SDL_Has3DNowExt; da_SDL_HasSSE SDL_HasSSE; da_SDL_HasSSE2 SDL_HasSSE2; da_SDL_HasAltiVec SDL_HasAltiVec; da_SDL_SetError SDL_SetError; da_SDL_GetError SDL_GetError; da_SDL_ClearError SDL_ClearError; da_SDL_PumpEvents SDL_PumpEvents; da_SDL_PeepEvents SDL_PeepEvents; da_SDL_PollEvent SDL_PollEvent; da_SDL_WaitEvent SDL_WaitEvent; da_SDL_PushEvent SDL_PushEvent; da_SDL_SetEventFilter SDL_SetEventFilter; da_SDL_GetEventFilter SDL_GetEventFilter; da_SDL_EventState SDL_EventState; da_SDL_NumJoysticks SDL_NumJoysticks; da_SDL_JoystickName SDL_JoystickName; da_SDL_JoystickOpen SDL_JoystickOpen; da_SDL_JoystickOpened SDL_JoystickOpened; da_SDL_JoystickIndex SDL_JoystickIndex; da_SDL_JoystickNumAxes SDL_JoystickNumAxes; da_SDL_JoystickNumBalls SDL_JoystickNumBalls; da_SDL_JoystickNumHats SDL_JoystickNumHats; da_SDL_JoystickNumButtons SDL_JoystickNumButtons; da_SDL_JoystickUpdate SDL_JoystickUpdate; da_SDL_JoystickEventState SDL_JoystickEventState; da_SDL_JoystickGetAxis SDL_JoystickGetAxis; da_SDL_JoystickGetHat SDL_JoystickGetHat; da_SDL_JoystickGetBall SDL_JoystickGetBall; da_SDL_JoystickGetButton SDL_JoystickGetButton; da_SDL_JoystickClose SDL_JoystickClose; da_SDL_EnableUNICODE SDL_EnableUNICODE; da_SDL_EnableKeyRepeat SDL_EnableKeyRepeat; da_SDL_GetKeyRepeat SDL_GetKeyRepeat; da_SDL_GetKeyState SDL_GetKeyState; da_SDL_GetModState SDL_GetModState; da_SDL_SetModState SDL_SetModState; da_SDL_GetKeyName SDL_GetKeyName; da_SDL_LoadObject SDL_LoadObject; da_SDL_LoadFunction SDL_LoadFunction; da_SDL_UnloadObject SDL_UnloadObject; da_SDL_GetMouseState SDL_GetMouseState; da_SDL_GetRelativeMouseState SDL_GetRelativeMouseState; da_SDL_WarpMouse SDL_WarpMouse; da_SDL_CreateCursor SDL_CreateCursor; da_SDL_SetCursor SDL_SetCursor; da_SDL_GetCursor SDL_GetCursor; da_SDL_FreeCursor SDL_FreeCursor; da_SDL_ShowCursor SDL_ShowCursor; da_SDL_CreateMutex SDL_CreateMutex; da_SDL_mutexP SDL_mutexP; da_SDL_mutexV SDL_mutexV; da_SDL_DestroyMutex SDL_DestroyMutex; da_SDL_CreateSemaphore SDL_CreateSemaphore; da_SDL_DestroySemaphore SDL_DestroySemaphore; da_SDL_SemWait SDL_SemWait; da_SDL_SemTryWait SDL_SemTryWait; da_SDL_SemWaitTimeout SDL_SemWaitTimeout; da_SDL_SemPost SDL_SemPost; da_SDL_SemValue SDL_SemValue; da_SDL_CreateCond SDL_CreateCond; da_SDL_DestroyCond SDL_DestroyCond; da_SDL_CondSignal SDL_CondSignal; da_SDL_CondBroadcast SDL_CondBroadcast; da_SDL_CondWait SDL_CondWait; da_SDL_CondWaitTimeout SDL_CondWaitTimeout; da_SDL_RWFromFile SDL_RWFromFile; da_SDL_RWFromFP SDL_RWFromFP; da_SDL_RWFromMem SDL_RWFromMem; da_SDL_RWFromConstMem SDL_RWFromConstMem; da_SDL_AllocRW SDL_AllocRW; da_SDL_FreeRW SDL_FreeRW; da_SDL_ReadLE16 SDL_ReadLE16; da_SDL_ReadBE16 SDL_ReadBE16; da_SDL_ReadLE32 SDL_ReadLE32; da_SDL_ReadBE32 SDL_ReadBE32; da_SDL_ReadLE64 SDL_ReadLE64; da_SDL_ReadBE64 SDL_ReadBE64; da_SDL_WriteLE16 SDL_WriteLE16; da_SDL_WriteBE16 SDL_WriteBE16; da_SDL_WriteLE32 SDL_WriteLE32; da_SDL_WriteBE32 SDL_WriteBE32; da_SDL_WriteLE64 SDL_WriteLE64; da_SDL_WriteBE64 SDL_WriteBE64; da_SDL_Linked_Version SDL_Linked_Version; da_SDL_GetWMInfo SDL_GetWMInfo; da_SDL_CreateThread SDL_CreateThread; da_SDL_ThreadID SDL_ThreadID; da_SDL_GetThreadID SDL_GetThreadID; da_SDL_WaitThread SDL_WaitThread; da_SDL_KillThread SDL_KillThread; da_SDL_GetTicks SDL_GetTicks; da_SDL_Delay SDL_Delay; da_SDL_SetTimer SDL_SetTimer; da_SDL_AddTimer SDL_AddTimer; da_SDL_RemoveTimer SDL_RemoveTimer; da_SDL_VideoInit SDL_VideoInit; da_SDL_VideoQuit SDL_VideoQuit; da_SDL_VideoDriverName SDL_VideoDriverName; da_SDL_GetVideoSurface SDL_GetVideoSurface; da_SDL_GetVideoInfo SDL_GetVideoInfo; da_SDL_VideoModeOK SDL_VideoModeOK; da_SDL_ListModes SDL_ListModes; da_SDL_SetVideoMode SDL_SetVideoMode; da_SDL_UpdateRects SDL_UpdateRects; da_SDL_UpdateRect SDL_UpdateRect; da_SDL_Flip SDL_Flip; da_SDL_SetGamma SDL_SetGamma; da_SDL_SetGammaRamp SDL_SetGammaRamp; da_SDL_GetGammaRamp SDL_GetGammaRamp; da_SDL_SetColors SDL_SetColors; da_SDL_SetPalette SDL_SetPalette; da_SDL_MapRGB SDL_MapRGB; da_SDL_MapRGBA SDL_MapRGBA; da_SDL_GetRGB SDL_GetRGB; da_SDL_GetRGBA SDL_GetRGBA; da_SDL_CreateRGBSurface SDL_CreateRGBSurface; da_SDL_CreateRGBSurfaceFrom SDL_CreateRGBSurfaceFrom; da_SDL_FreeSurface SDL_FreeSurface; da_SDL_LockSurface SDL_LockSurface; da_SDL_UnlockSurface SDL_UnlockSurface; da_SDL_LoadBMP_RW SDL_LoadBMP_RW; da_SDL_SaveBMP_RW SDL_SaveBMP_RW; da_SDL_SetColorKey SDL_SetColorKey; da_SDL_SetAlpha SDL_SetAlpha; da_SDL_SetClipRect SDL_SetClipRect; da_SDL_GetClipRect SDL_GetClipRect; da_SDL_ConvertSurface SDL_ConvertSurface; da_SDL_UpperBlit SDL_UpperBlit; da_SDL_LowerBlit SDL_LowerBlit; da_SDL_FillRect SDL_FillRect; da_SDL_DisplayFormat SDL_DisplayFormat; da_SDL_DisplayFormatAlpha SDL_DisplayFormatAlpha; da_SDL_CreateYUVOverlay SDL_CreateYUVOverlay; da_SDL_LockYUVOverlay SDL_LockYUVOverlay; da_SDL_UnlockYUVOverlay SDL_UnlockYUVOverlay; da_SDL_DisplayYUVOverlay SDL_DisplayYUVOverlay; da_SDL_FreeYUVOverlay SDL_FreeYUVOverlay; da_SDL_GL_LoadLibrary SDL_GL_LoadLibrary; da_SDL_GL_GetProcAddress SDL_GL_GetProcAddress; da_SDL_GL_SetAttribute SDL_GL_SetAttribute; da_SDL_GL_GetAttribute SDL_GL_GetAttribute; da_SDL_GL_SwapBuffers SDL_GL_SwapBuffers; da_SDL_GL_UpdateRects SDL_GL_UpdateRects; da_SDL_GL_Lock SDL_GL_Lock; da_SDL_GL_Unlock SDL_GL_Unlock; da_SDL_WM_SetCaption SDL_WM_SetCaption; da_SDL_WM_GetCaption SDL_WM_GetCaption; da_SDL_WM_SetIcon SDL_WM_SetIcon; da_SDL_WM_IconifyWindow SDL_WM_IconifyWindow; da_SDL_WM_ToggleFullScreen SDL_WM_ToggleFullScreen; da_SDL_WM_GrabInput SDL_WM_GrabInput; "); alias SDL_CreateRGBSurface SDL_AllocSurface; alias SDL_UpperBlit SDL_BlitSurface;CheeseCutter-master/src/derelict/sdl/sdltypes.d000066400000000000000000000646411357241101300221220ustar00rootroot00000000000000/* Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ module derelict.sdl.sdltypes; private { version(Tango) { import tango.stdc.stdio; } else { import core.stdc.stdio; } } // SDL.h enum : Uint32 { SDL_INIT_TIMER = 0x00000001, SDL_INIT_AUDIO = 0x00000010, SDL_INIT_VIDEO = 0x00000020, SDL_INIT_CDROM = 0x00000100, SDL_INIT_JOYSTICK = 0x00000200, SDL_INIT_NOPARACHUTE = 0x00100000, SDL_INIT_EVENTTHREAD = 0x00200000, SDL_INIT_EVERYTHING = 0x0000FFFF, } // SDL_types.h alias int SDL_bool; enum { SDL_FALSE = 0, SDL_TRUE = 1 } alias ubyte Uint8; alias byte Sint8; alias ushort Uint16; alias short Sint16; alias uint Uint32; alias int Sint32; alias ulong Uint64; alias long Sint64; enum { SDL_PRESSED = 0x01, SDL_RELEASED = 0x00 } // SDL_active.h enum : Uint8 { SDL_APPMOUSEFOCUS = 0x01, SDL_APPINPUTFOCUS = 0x02, SDL_APPACTIVE = 0x04, } // SDL_audio.h struct SDL_AudioSpec { int freq; Uint16 format; Uint8 channels; Uint8 silence; Uint16 samples; Uint16 padding; Uint32 size; extern(C) void function(void *userdata, Uint8 *stream, int len) callback; void *userdata; } enum : Uint16 { AUDIO_U8 = 0x0008, AUDIO_S8 = 0x8008, AUDIO_U16LSB = 0x0010, AUDIO_S16LSB = 0x8010, AUDIO_U16MSB = 0x1010, AUDIO_S16MSB = 0x9010, AUDIO_U16 = AUDIO_U16LSB, AUDIO_S16 = AUDIO_S16LSB, } version(LittleEndian) { enum : Uint16 { AUDIO_U16SYS = AUDIO_U16LSB, AUDIO_S16SYS = AUDIO_S16LSB, } } else { enum : Uint16 { AUDIO_U16SYS = AUDIO_U16MSB, AUDIO_S16SYS = AUDIO_S16MSB, } } struct SDL_AudioCVT { int needed; Uint16 src_format; Uint16 dst_format; double rate_incr; Uint8 *buf; int len; int len_cvt; int len_mult; double len_ratio; void function(SDL_AudioCVT *cvt, Uint16 format)[10] filters; int filter_index; } alias int SDL_audiostatus; enum { SDL_AUDIO_STOPPED = 0, SDL_AUDIO_PLAYING, SDL_AUDIO_PAUSED } enum { SDL_MIX_MAXVOLUME = 128 } // SDL_byteorder.h enum : uint { SDL_LIL_ENDIAN = 1234, SDL_BIG_ENDIAN = 4321, } version(LittleEndian) { enum : uint { SDL_BYTEORDER = SDL_LIL_ENDIAN, } } else { enum : uint { SDL_BYTEORDER = SDL_BIG_ENDIAN, } } // SDL_cdrom.h enum : Sint32 { SDL_MAX_TRACKS = 99 } enum : Uint8 { SDL_AUDIO_TRACK = 0x00, SDL_DATA_TRACK = 0x04, } alias int CDstatus; enum { CD_TRAYEMPTY, CD_STOPPED, CD_PLAYING, CD_PAUSED, CD_ERROR = -1 } struct SDL_CDtrack { Uint8 id; Uint8 type; Uint16 unused; Uint32 length; Uint32 offset; } struct SDL_CD { int id; CDstatus status; int numtracks; int cur_track; int cur_frame; SDL_CDtrack[SDL_MAX_TRACKS + 1] track; } enum { CD_FPS = 75 } int CD_INDRIVE(int status) { return (cast(int)status > 0); } void FRAMES_TO_MSF(int f, out int M, out int S, out int F) { int value = f; F = value % CD_FPS; value /= CD_FPS; S = value % 60; value /= 60; M = value; } int MSF_TO_FRAMES(int M, int S, int F) { return (M * 60 * CD_FPS + S * CD_FPS + F); } // SDL_endian.h Uint16 SDL_Swap16(Uint16 val) { return cast(Uint16)((val<<8)|(val>>8)); } Uint32 SDL_Swap32(Uint32 val) { return cast(Uint32)((val<<24)|((val<<8)&0x00FF0000)|((val>>8)&0x0000FF00)|(val>>24)); } Uint64 SDL_Swap64(Uint64 val) { Uint32 lo = cast(Uint32)(val & 0xFFFFFFFF); val >>= 32; Uint32 hi = cast(Uint32)(val & 0xFFFFFFFF); val = SDL_Swap32(lo); val <<= 32; val |= SDL_Swap32(hi); return val; } version(LittleEndian) { Uint16 SDL_SwapLE16(Uint16 val) { return val; } Uint32 SDL_SwapLE32(Uint32 val) { return val; } Uint64 SDL_SwapLE64(Uint64 val) { return val; } alias SDL_Swap16 SDL_SwapBE16; alias SDL_Swap32 SDL_SwapBE32; alias SDL_Swap64 SDL_SwapBE64; } else { alias SDL_Swap16 SDL_SwapLE16; alias SDL_Swap32 SDL_SwapLE32; alias SDL_Swap64 SDL_SwapLE64; Uint16 SDL_SwapBE16(Uint16 val) { return val; } Uint32 SDL_SwapBE32(Uint32 val) { return val; } Uint64 SDL_SwapBE64(Uint64 val) { return val; } } // SDL_events.h enum { SDL_NOEVENT = 0, SDL_ACTIVEEVENT, SDL_KEYDOWN, SDL_KEYUP, SDL_MOUSEMOTION, SDL_MOUSEBUTTONDOWN, SDL_MOUSEBUTTONUP, SDL_JOYAXISMOTION, SDL_JOYBALLMOTION, SDL_JOYHATMOTION, SDL_JOYBUTTONDOWN, SDL_JOYBUTTONUP, SDL_QUIT, SDL_SYSWMEVENT, SDL_EVENT_RESERVEDA, SDL_EVENT_RESERVEDB, SDL_VIDEORESIZE, SDL_VIDEOEXPOSE, SDL_EVENT_RESERVED2, SDL_EVENT_RESERVED3, SDL_EVENT_RESERVED4, SDL_EVENT_RESERVED5, SDL_EVENT_RESERVED6, SDL_EVENT_RESERVED7, SDL_USEREVENT = 24, SDL_NUMEVENTS = 32 } enum { SDL_ACTIVEEVENTMASK = (1<