aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorJuan J. Martinez <jjm@usebox.net>2021-05-03 08:21:10 +0100
committerJuan J. Martinez <jjm@usebox.net>2021-05-03 10:00:00 +0100
commitc3b0fa04a663fe233765b83d3be41a42aa08c25d (patch)
tree0befda349001ef6ce306b39378f9c70ad917363e /tools
downloadreturn-of-traxtor-cpc-c3b0fa04a663fe233765b83d3be41a42aa08c25d.tar.gz
return-of-traxtor-cpc-c3b0fa04a663fe233765b83d3be41a42aa08c25d.zip
Initial import for public releaseHEADmain
Diffstat (limited to 'tools')
-rw-r--r--tools/2CDT/2cdt.cbp43
-rw-r--r--tools/2CDT/2cdt.depend22
-rw-r--r--tools/2CDT/2cdt.layout7
-rw-r--r--tools/2CDT/COPYING340
-rw-r--r--tools/2CDT/Makefile24
-rw-r--r--tools/2CDT/Makefile.win33
-rw-r--r--tools/2CDT/file_id.diz16
-rw-r--r--tools/2CDT/readme.txt135
-rw-r--r--tools/2CDT/src/2cdt.c1290
-rw-r--r--tools/2CDT/src/defs.h36
-rw-r--r--tools/2CDT/src/tzxfile.c445
-rw-r--r--tools/2CDT/src/tzxfile.h79
-rw-r--r--tools/Makefile38
-rw-r--r--tools/README.ucl7
-rwxr-xr-xtools/bin2h.py34
-rwxr-xr-xtools/chksize42
-rwxr-xr-xtools/dump-pal.py95
-rw-r--r--tools/encrypt.py25
-rw-r--r--tools/gfx2crtc/AUTHORS5
-rw-r--r--tools/gfx2crtc/LICENCE512
-rw-r--r--tools/gfx2crtc/LICENSE506
-rw-r--r--tools/gfx2crtc/README36
-rw-r--r--tools/gfx2crtc/TODO9
-rw-r--r--tools/gfx2crtc/libraw2crtc.c186
-rw-r--r--tools/gfx2crtc/libraw2crtc.h12
-rw-r--r--tools/gfx2crtc/makefile29
-rw-r--r--tools/gfx2crtc/png2crtc.c204
-rw-r--r--tools/gfx2crtc/raw2crtc.c86
-rwxr-xr-xtools/hex2bin-2.0/Makefile42
-rw-r--r--tools/hex2bin-2.0/bin/.deleteme0
-rwxr-xr-xtools/hex2bin-2.0/bin/hex2binbin0 -> 33200 bytes
-rwxr-xr-xtools/hex2bin-2.0/bin/mot2binbin0 -> 33200 bytes
-rw-r--r--tools/hex2bin-2.0/doc/CRC list.txt542
-rw-r--r--tools/hex2bin-2.0/doc/ChangeLog_hex2bin57
-rw-r--r--tools/hex2bin-2.0/doc/ChangeLog_mot2bin49
-rw-r--r--tools/hex2bin-2.0/doc/README225
-rw-r--r--tools/hex2bin-2.0/doc/S-record.txt361
-rw-r--r--tools/hex2bin-2.0/doc/formats.txt72
-rw-r--r--tools/hex2bin-2.0/doc/intelhex.spc409
-rw-r--r--tools/hex2bin-2.0/doc/srec.txt447
-rw-r--r--tools/hex2bin-2.0/src/binary.c196
-rw-r--r--tools/hex2bin-2.0/src/binary.h36
-rw-r--r--tools/hex2bin-2.0/src/common.c527
-rw-r--r--tools/hex2bin-2.0/src/common.h116
-rw-r--r--tools/hex2bin-2.0/src/hex2bin.1294
-rw-r--r--tools/hex2bin-2.0/src/hex2bin.c587
-rw-r--r--tools/hex2bin-2.0/src/hex2bin.pod161
-rw-r--r--tools/hex2bin-2.0/src/libcrc.c204
-rw-r--r--tools/hex2bin-2.0/src/libcrc.h44
-rw-r--r--tools/hex2bin-2.0/src/mot2bin.c518
-rw-r--r--tools/iDSK/.gitignore7
-rw-r--r--tools/iDSK/AUTHORS3
-rw-r--r--tools/iDSK/CMakeLists.txt14
-rw-r--r--tools/iDSK/COPYING1
-rw-r--r--tools/iDSK/src/Basic.cpp350
-rw-r--r--tools/iDSK/src/Basic.h8
-rw-r--r--tools/iDSK/src/BitmapCPC.cpp264
-rw-r--r--tools/iDSK/src/BitmapCPC.h46
-rw-r--r--tools/iDSK/src/Dams.cpp184
-rw-r--r--tools/iDSK/src/Dams.h8
-rw-r--r--tools/iDSK/src/Desass.cpp532
-rw-r--r--tools/iDSK/src/Desass.h8
-rw-r--r--tools/iDSK/src/GestDsk.cpp1183
-rw-r--r--tools/iDSK/src/GestDsk.h168
-rw-r--r--tools/iDSK/src/Main.cpp284
-rw-r--r--tools/iDSK/src/Main.h19
-rw-r--r--tools/iDSK/src/MyType.h19
-rw-r--r--tools/iDSK/src/Outils.cpp165
-rw-r--r--tools/iDSK/src/Outils.h19
-rw-r--r--tools/iDSK/src/ViewFile.cpp36
-rw-r--r--tools/iDSK/src/ViewFile.h13
-rw-r--r--tools/iDSK/src/endianPPC.cpp20
-rw-r--r--tools/iDSK/src/endianPPC.h22
-rw-r--r--tools/iDSK/src/getopt_pp.cpp307
-rw-r--r--tools/iDSK/src/getopt_pp.h745
-rwxr-xr-xtools/img2f.py54
-rwxr-xr-xtools/img2sprite.py115
-rwxr-xr-xtools/map.py162
-rw-r--r--tools/ucl.c94
79 files changed, 14033 insertions, 0 deletions
diff --git a/tools/2CDT/2cdt.cbp b/tools/2CDT/2cdt.cbp
new file mode 100644
index 0000000..41deaf1
--- /dev/null
+++ b/tools/2CDT/2cdt.cbp
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="4" />
+ <Project>
+ <Option title="2cdt" />
+ <Option makefile="makefile" />
+ <Option pch_mode="0" />
+ <Option compiler="gcc" />
+ <Build>
+ <Target title="default">
+ <Option output="C:\2cdt\2cdt.exe" />
+ <Option type="1" />
+ <Option compiler="gcc" />
+ <Option parameters="-m 2 -r snake c:\blocks.bin c:\tester.cdt" />
+ <Option includeInTargetAll="1" />
+ <Option projectResourceIncludeDirsRelation="1" />
+ </Target>
+ </Build>
+ <Compiler>
+ <Add option="-g" />
+ </Compiler>
+ <Unit filename="src\2cdt.c">
+ <Option compilerVar="CC" />
+ <Option target="default" />
+ </Unit>
+ <Unit filename="src\defs.h">
+ <Option compilerVar="CC" />
+ <Option compile="0" />
+ <Option link="0" />
+ <Option target="default" />
+ </Unit>
+ <Unit filename="src\tzxfile.c">
+ <Option compilerVar="CC" />
+ <Option target="default" />
+ </Unit>
+ <Unit filename="src\tzxfile.h">
+ <Option compilerVar="CC" />
+ <Option compile="0" />
+ <Option link="0" />
+ <Option target="default" />
+ </Unit>
+ </Project>
+</CodeBlocks_project_file> \ No newline at end of file
diff --git a/tools/2CDT/2cdt.depend b/tools/2CDT/2cdt.depend
new file mode 100644
index 0000000..7427b7c
--- /dev/null
+++ b/tools/2CDT/2cdt.depend
@@ -0,0 +1,22 @@
+# depslib dependency file v1.0
+1137940710 source:d:\www\download\2cdt\2cdt\src\tzxfile.c
+ <stdio.h>
+ <stdlib.h>
+ <memory.h>
+ "tzxfile.h"
+
+991048958 d:\www\download\2cdt\2cdt\src\tzxfile.h
+ "defs.h"
+
+1014464942 d:\www\download\2cdt\2cdt\src\defs.h
+
+1280219172 source:d:\www\download\2cdt\2cdt\src\2cdt.c
+ <stdio.h>
+ <stdlib.h>
+ <string.h>
+ <sys/io.h>
+ <io.h>
+ "defs.h"
+ "tzxfile.h"
+ "getopt.h"
+
diff --git a/tools/2CDT/2cdt.layout b/tools/2CDT/2cdt.layout
new file mode 100644
index 0000000..b5fceb8
--- /dev/null
+++ b/tools/2CDT/2cdt.layout
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <ActiveTarget name="All" />
+ <File name="src\2cdt.c" open="1" top="1" tabpos="1">
+ <Cursor position="26859" topLine="1012" />
+ </File>
+</CodeBlocks_layout_file>
diff --git a/tools/2CDT/COPYING b/tools/2CDT/COPYING
new file mode 100644
index 0000000..196760e
--- /dev/null
+++ b/tools/2CDT/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/tools/2CDT/Makefile b/tools/2CDT/Makefile
new file mode 100644
index 0000000..379c9c6
--- /dev/null
+++ b/tools/2CDT/Makefile
@@ -0,0 +1,24 @@
+# Makefile for 2cdt utility
+
+.PHONY: clean
+CC = gcc
+BIND = gcc
+RM = rm
+
+# CFLAGS flags for C compile
+# LFLAGS1 flags after output file spec, before obj file list
+# LFLAGS2 flags after obj file list (libraries, etc)
+
+CFLAGS = -O2 -O3 -DUNIX
+LFLAGS1 =
+LFLAGS2 = -s
+
+CDT_O= src/2cdt.o src/tzxfile.o
+
+2cdt: $(CDT_O)
+ $(BIND) $(CDT_O) -o 2cdt $(LFLAGS1) $(LFLAGS2) $(LIBS)
+
+clean:
+ rm -rf src/*.o
+ rm -f 2cdt
+ rm -f 2cdt.exe
diff --git a/tools/2CDT/Makefile.win b/tools/2CDT/Makefile.win
new file mode 100644
index 0000000..39714b8
--- /dev/null
+++ b/tools/2CDT/Makefile.win
@@ -0,0 +1,33 @@
+# Project: 2cdt
+# Makefile created by Dev-C++ 4.9.9.2
+
+CPP = g++.exe
+CC = gcc.exe
+WINDRES = windres.exe
+RES =
+OBJ = src/2cdt.o src/tzxfile.o $(RES)
+LINKOBJ = src/2cdt.o src/tzxfile.o $(RES)
+LIBS = -L"C:/Dev-Cpp/lib"
+INCS = -I"C:/Dev-Cpp/include"
+CXXINCS = -I"C:/Dev-Cpp/lib/gcc/mingw32/3.4.2/include" -I"C:/Dev-Cpp/include/c++/3.4.2/backward" -I"C:/Dev-Cpp/include/c++/3.4.2/mingw32" -I"C:/Dev-Cpp/include/c++/3.4.2" -I"C:/Dev-Cpp/include"
+BIN = 2cdt.exe
+CXXFLAGS = $(CXXINCS)
+CFLAGS = $(INCS)
+RM = rm -f
+
+.PHONY: all all-before all-after clean clean-custom
+
+all: all-before 2cdt.exe all-after
+
+
+clean: clean-custom
+ ${RM} $(OBJ) $(BIN)
+
+$(BIN): $(OBJ)
+ $(CC) $(LINKOBJ) -o "2cdt.exe" $(LIBS)
+
+src/2cdt.o: src/2cdt.c
+ $(CC) -c src/2cdt.c -o src/2cdt.o $(CFLAGS)
+
+src/tzxfile.o: src/tzxfile.c
+ $(CC) -c src/tzxfile.c -o src/tzxfile.o $(CFLAGS)
diff --git a/tools/2CDT/file_id.diz b/tools/2CDT/file_id.diz
new file mode 100644
index 0000000..e1ff8f5
--- /dev/null
+++ b/tools/2CDT/file_id.diz
@@ -0,0 +1,16 @@
+2CDT
+Copyright (C) Kevin Thacker, 2000-2002
+
+23-February-2002
+
+2CDT is a tool to create a ".CDT"
+tape image from a file in the Amstrad
+operating system cassette format.
+It can be used to test support
+for ".TZX" in Amstrad emulators
+and a starting point for a Amstrad
+".CDT" tool.
+
+Source included.
+
+makefile included for UNIX \ No newline at end of file
diff --git a/tools/2CDT/readme.txt b/tools/2CDT/readme.txt
new file mode 100644
index 0000000..b10fcc2
--- /dev/null
+++ b/tools/2CDT/readme.txt
@@ -0,0 +1,135 @@
+2CDT
+====
+
+(c) Kevin Thacker
+
+(Original code written in May 2000, fixed and released in May 2001)
+
+2CDT is a utility to transfer files into a ".CDT" Tape-Image.
+
+A ".CDT" is a tape-image file which describes the data stored on a cassette tape.
+
+This file format is very powerful and can describe fast and custom loaders as well
+as standard operating system formats.
+
+The ".CDT" file format is identical to the ".TZX" format. The extension is used
+to differentiate between Spectrum and Amstrad Tape-Images.
+
+The ".TZX" file format was originally designed to store Spectrum tape programs,
+it's format can be found from various sources, one of these is "World Of Spectrum":
+http://www.void.jump.org/
+
+There are a number of tools which already create .TZX files, Taper, Voc2TZX and MakeTZX.
+However, these are designed to recognise Spectrum tape loaders, and so do not do well
+at creating a tape-image for Amstrad formats.
+
+This tool has been designed as a starting point for furthur Amstrad CDT tools,
+and as a program to generate reference tape-images which can be used by emulator
+authors to support this tape-image format in their programs.
+
+This tool is designed to "inject" one or more file into a ".CDT" in the format written
+by the Amstrad operating system. The tool allows the user to define the ".CDT" "recording"
+method and baud rate.
+
+2CDT [parameters] <source file> <output CDT filename>
+
+parameters:
+ -n
+ - Blank CDT file before use
+
+ Use this to create a new CDT, otherwise file
+ will be added to the end of an existing CDT.
+
+ -s <speed write>
+ - Write data with 'speed write' 0 or 1.
+
+ This is the same as typing "SPEED WRITE 0" or "SPEED WRITE 1"
+ in BASIC. Speed Write '0' is 1000 baud. Speed write '1' is
+ 2000 baud.
+
+ -b <baud rate>
+ - Specify Baud Rate.
+
+ Allows you to specify faster or slower loading.
+
+ -t <method>
+ - Method to write data into TZX (for Amstrad blocks)
+ 0 = Pure Data Block
+ 1 = Turbo Loading Data Block (default)
+
+ -m <method>
+ - Method to write CPC data
+ 0 = blocks (default)
+ 1 = headerless (Firmware function CAS READ for reading, CAS WRITE for writing )
+ To be loaded with firmware function CAS READ.
+ Not readable from BASIC. Allows entire program
+ to be stored as a single continuous block.
+ 2 = Spectrum ROM loader
+
+ -r <tape filename>
+ - Give the tape file a name. Up to 16 characters.
+
+ This allows you to give the file on tape a different
+ name to the name given on your local filesystem.
+
+ If no name is defined, the file will be unnamed.
+ This option applies to CPC 'blocks' methods only.
+
+ -X <address>
+ Define execution address (where file doesn't have header), or
+ override execution address (where file has a header)
+
+ -L <address>
+ Define load address (where file doesn't have header), or
+ override load address (where file has a header)
+
+ -T <address>
+ Define type (where file doesn't have header), or
+ override type address (where file has a header)
+ 0 = BASIC, 2 = BINARY
+
+ -p <number>
+ Set initial pause (default 3000ms)
+
+ -P
+ Add a small initial pause block for buggy emulators (e.g. old versions of Arnold)
+ Not recommended. Please use newer version of this emulator.
+
+Examples:
+
+The following in a bacth file will create the master tape for 'Stranded':
+
+REM create new CDT and put binary loader
+2cdt -n -r stranded strandlod.bin stranded.cdt
+REM add screen to existing CDT data
+2cdt -r screen loading.bin stranded.cdt
+REM add code to existing CDT data
+2cdt -r code stranded.bin stranded.cdt
+
+If you wanted to create a master tape for a game called 'Columns':
+
+REM create new CDT and put binary loader
+2cdt -n -r loader colload.bin columns.cdt
+REM put binary file as headerless
+2cdt -m 1 colcode.bin columns.cdt
+
+
+
+This archive contains a Windows command-line executable that will run under Win95, Win98,
+Win2000 and WinNT.
+
+License:
+
+ 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, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. \ No newline at end of file
diff --git a/tools/2CDT/src/2cdt.c b/tools/2CDT/src/2cdt.c
new file mode 100644
index 0000000..c3fb520
--- /dev/null
+++ b/tools/2CDT/src/2cdt.c
@@ -0,0 +1,1290 @@
+/*
+ * 2CDT Copyright (c) Kevin Thacker
+ *
+ * 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.
+ */
+
+
+/* The following program is designed to create a .tzx/.cdt from a tape-file stored
+on the PC */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef UNIX
+#include <sys/io.h>
+#else
+#include <io.h>
+#endif
+#include "defs.h"
+#include "tzxfile.h"
+#include "getopt.h"
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+typedef unsigned __int64 ulong64;
+typedef signed __int64 long64;
+#else
+typedef unsigned long long ulong64;
+typedef signed long long long64;
+#endif
+
+enum
+{
+ CPC_METHOD_BLOCKS = 0,
+ CPC_METHOD_HEADERLESS,
+ CPC_METHOD_SPECTRUM,
+};
+
+static int ExecutionAddress;
+static BOOL ExecutionAddressOverride;
+static int LoadAddress;
+static BOOL LoadAddressOverride;
+static int Type;
+static BOOL TypeOverride;
+static int Pause;
+static BOOL BuggyEmuExtraPause;
+
+#define MAXFILELEN 16
+
+static int BaudRate; /* baud rate to write data */
+static int TZXWriteMethod; /* method to write data into TZX file */
+static BOOL BlankBeforeUse; /* blank existing CDT file before use */
+static int CPCMethod = CPC_METHOD_BLOCKS;
+
+/* I am using a enum, so that I can poke data into structures without
+worrying how the compiler has aligned it */
+enum
+{
+ CPC_TAPE_HEADER_FILENAME_BYTE0 = 0,
+ CPC_TAPE_HEADER_FILENAME_BYTE1,
+ CPC_TAPE_HEADER_FILENAME_BYTE2,
+ CPC_TAPE_HEADER_FILENAME_BYTE3,
+ CPC_TAPE_HEADER_FILENAME_BYTE4,
+ CPC_TAPE_HEADER_FILENAME_BYTE5,
+ CPC_TAPE_HEADER_FILENAME_BYTE6,
+ CPC_TAPE_HEADER_FILENAME_BYTE7,
+ CPC_TAPE_HEADER_FILENAME_BYTE8,
+ CPC_TAPE_HEADER_FILENAME_BYTE9,
+ CPC_TAPE_HEADER_FILENAME_BYTE10,
+ CPC_TAPE_HEADER_FILENAME_BYTE11,
+ CPC_TAPE_HEADER_FILENAME_BYTE12,
+ CPC_TAPE_HEADER_FILENAME_BYTE13,
+ CPC_TAPE_HEADER_FILENAME_BYTE14,
+ CPC_TAPE_HEADER_FILENAME_BYTE15,
+ CPC_TAPE_HEADER_BLOCK_NUMBER,
+ CPC_TAPE_HEADER_LAST_BLOCK_FLAG,
+ CPC_TAPE_HEADER_FILE_TYPE,
+ CPC_TAPE_HEADER_DATA_LENGTH_LOW,
+ CPC_TAPE_HEADER_DATA_LENGTH_HIGH,
+ CPC_TAPE_HEADER_DATA_LOCATION_LOW,
+ CPC_TAPE_HEADER_DATA_LOCATION_HIGH,
+ CPC_TAPE_HEADER_FIRST_BLOCK_FLAG,
+ CPC_TAPE_HEADER_DATA_LOGICAL_LENGTH_LOW,
+ CPC_TAPE_HEADER_DATA_LOGICAL_LENGTH_HIGH,
+ CPC_TAPE_HEADER_DATA_EXECUTION_ADDRESS_LOW,
+ CPC_TAPE_HEADER_DATA_EXECUTION_ADDRESS_HIGH,
+} CPC_TAPE_HEADER_ENUM;
+
+/* size of header */
+#define CPC_TAPE_HEADER_SIZE 64
+
+/* load a file into memory */
+BOOL Host_LoadFile(const char *Filename, unsigned char **pLocation, unsigned long *pLength)
+{
+ FILE *fh;
+ unsigned char *pData;
+
+ *pLocation = NULL;
+ *pLength = 0;
+
+ if (Filename!=NULL)
+ {
+ if (strlen(Filename)!=0)
+ {
+ fh = fopen(Filename,"rb");
+
+ if (fh!=NULL)
+ {
+ int FileSize;
+
+#ifdef WIN32
+ int FNo;
+
+ FNo = _fileno(fh);
+ FileSize = _filelength(FNo);
+#else
+ unsigned long CurrentPosition;
+ CurrentPosition = ftell(fh);
+ fseek(fh, 0, SEEK_END);
+ FileSize = ftell(fh);
+ fseek(fh, CurrentPosition, SEEK_SET);
+#endif
+ if (FileSize!=0)
+ {
+ pData = (unsigned char *)malloc(FileSize);
+
+ if (pData!=NULL)
+ {
+ if (fread(pData,1,FileSize,fh)==FileSize)
+ {
+ *pLocation = pData;
+ *pLength = FileSize;
+ fclose(fh);
+ return TRUE;
+ }
+
+ free(pData);
+ }
+ }
+
+ fclose(fh);
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+
+/* calculate checksum as AMSDOS would for the first 66 bytes of a datablock */
+/* this is used to determine if a file has a AMSDOS header */
+unsigned int AMSDOS_CalculateChecksum(unsigned char *pHeader)
+{
+ unsigned int Checksum;
+ int i;
+
+ Checksum = 0;
+
+ for (i=0; i<67; i++)
+ {
+ unsigned int CheckSumByte;
+
+ CheckSumByte = pHeader[i] & 0x0ff;
+
+ Checksum+=CheckSumByte;
+ }
+
+ return Checksum;
+}
+
+/* CRC code shamelessly taken from Pierre Guerrier's AIFF decoder! */
+#define kCRCpoly 4129 /* used for binary long division in CRC */
+
+/* CRC polynomial: X^16+X^12+X^5+1 */
+unsigned int CRCupdate(unsigned int CRC, unsigned char new)
+{
+ unsigned int aux = CRC ^ (new << 8);
+ int i;
+
+ for(i=0; i<8; i++)
+ if (aux & 0x8000)
+ aux = (aux <<= 1) ^ kCRCpoly;
+ else
+ aux <<= 1;
+
+ return(aux);
+}
+
+/*
+ID : 11 - Turbo loading data block
+-------
+ This block is very similar to the normal TAP block but with some
+ additional info on the timings and other important differences.
+ The same tape encoding is used as for the standard speed data block.
+ If a block should use some non-standard sync or pilot tones (for
+ example all sorts of protection schemes) then use the next three blocks
+ to describe it.
+
+00 2 Length of PILOT pulse [2168]
+02 2 Length of SYNC First pulse [667]
+04 2 Length of SYNC Second pulse [735]
+06 2 Length of ZERO bit pulse [855]
+08 2 Length of ONE bit pulse [1710]
+0A 2 Length of PILOT tone (in PILOT pulses) [8064 Header, 3220 Data]
+0C 1 Used bits in last byte (other bits should be 0) [8]
+ i.e. if this is 6 then the bits (x) used in last byte are: xxxxxx00
+0D 2 Pause After this block in milliseconds (ms) [1000]
+0F 3 Length of following data
+12 x Data; format is as for TAP (MSb first)
+
+- Length: [0F,10,11]+12
+*/
+
+/* 2 pulses per bit, tone is composed of 1 bits */
+#define CPC_PILOT_TONE_NUM_WAVES (2048)
+#define CPC_PILOT_TONE_NUM_PULSES (CPC_PILOT_TONE_NUM_WAVES*2)
+
+#define CPC_NOPS_PER_FRAME (19968)
+#define CPC_NOPS_PER_SECOND (CPC_NOPS_PER_FRAME*50)
+#define CPC_T_STATES (CPC_NOPS_PER_SECOND*4)
+
+#define T_STATE_CONVERSION_FACTOR (TZX_T_STATES<<8)/(CPC_T_STATES>>8)
+/* pause between each block */
+#define CPC_PAUSE_AFTER_BLOCK_IN_MS 2500
+/* pause between tape header and data for block */
+#define CPC_PAUSE_AFTER_HEADER_IN_MS 14
+
+void InitialiseStandardSpeedDataBlock(TZX_BLOCK *pBlock, int Pause)
+{
+ unsigned char *pHeader = TZX_GetBlockHeaderPtr(pBlock);
+
+ if (pHeader!=NULL)
+ {
+ /* check it is a turbo-loading data block */
+ if (pHeader[0] == TZX_STANDARD_SPEED_DATA_BLOCK)
+ {
+ pHeader++;
+
+ pHeader[0x00] = (Pause & 0x0ff);
+ pHeader[0x01] = (Pause>>8);
+
+
+ }
+ }
+}
+
+void CPC_InitialiseTurboLoadingDataBlock(TZX_BLOCK *pBlock, int BaudRate,int Pause)
+{
+ unsigned char *pHeader = TZX_GetBlockHeaderPtr(pBlock);
+
+ if (pHeader!=NULL)
+ {
+ /* check it is a turbo-loading data block */
+ if (pHeader[0] == TZX_TURBO_LOADING_DATA_BLOCK)
+ {
+ int ZeroPulseLengthInMicroseconds;
+ long64 ZeroPulseLengthInCPCTStates;
+ int OnePulseLength;
+ int ZeroPulseLength;
+
+ pHeader++;
+ /* equation from CPC firmware guide:
+ Average baud rate: = 1 000 000/(3*half zero length) = 333 333/Half zero length
+ */
+
+ ZeroPulseLengthInMicroseconds = 333333/BaudRate;
+ ZeroPulseLengthInCPCTStates = ZeroPulseLengthInMicroseconds<<2;
+
+ ZeroPulseLength = (ZeroPulseLengthInCPCTStates*
+ (T_STATE_CONVERSION_FACTOR>>8))>>8;
+
+ /* one pulse is twice the size of a zero pulse */
+ OnePulseLength = ZeroPulseLength<<1;
+
+ /* PILOT pulse on CPC is a one bit */
+ pHeader[0x00] = (unsigned char)OnePulseLength;
+ pHeader[0x01] = (unsigned char)(OnePulseLength>>8);
+
+ /* SYNC on CPC is a zero bit, both sync pulses will be the same */
+ pHeader[0x02] = pHeader[0x04] = (unsigned char)ZeroPulseLength;
+ pHeader[0x03] = pHeader[0x05] = (unsigned char)(ZeroPulseLength>>8);
+
+ /* write zero pulse length */
+ pHeader[0x06] = (unsigned char)ZeroPulseLength;
+ pHeader[0x07] = (unsigned char)(ZeroPulseLength>>8);
+
+ /* write one pulse length */
+ pHeader[0x08] = (unsigned char)OnePulseLength;
+ pHeader[0x09] = (unsigned char)(OnePulseLength>>8);
+
+ /* PILOT pulse is same as 1 Pulse */
+ /* pilot tone is 2048 bits long */
+ pHeader[0x0a] = CPC_PILOT_TONE_NUM_PULSES & 0x0ff;
+ pHeader[0x0b] = (CPC_PILOT_TONE_NUM_PULSES>>8);
+
+ /* the end of the block will be the trailer bytes. Say all bits are
+ used, although, because it doesn't contain useful data it doesn't matter */
+ pHeader[0x0c] = 8;
+
+ pHeader[0x0d] = (Pause & 0x0ff);
+ pHeader[0x0e] = (Pause>>8);
+
+
+ }
+ }
+}
+
+
+
+void WriteStandardSpeedDataBlock(TZX_FILE *pFile, unsigned char SyncPattern, unsigned char *pData, int DataSize, int Pause)
+{
+ TZX_BLOCK *pBlock;
+ unsigned char *pBlockData;
+
+ pBlock = TZX_CreateBlock(TZX_STANDARD_SPEED_DATA_BLOCK);
+ InitialiseStandardSpeedDataBlock(pBlock, Pause);
+
+ if (pBlock!=NULL)
+ {
+ /* one byte for sync, one byte for checksum */
+ int TZX_DataBlockSize = DataSize+2;
+
+ /* add block to end of file */
+ TZX_AddBlockToEndOfFile(pFile,pBlock);
+
+ /* allocate data in block */
+ TZX_AddDataToBlock(pBlock, TZX_DataBlockSize);
+
+ pBlockData= TZX_GetBlockDataPtr(pBlock);
+
+ if (pBlockData!=NULL)
+ {
+ char CheckSum = SyncPattern;
+ int i;
+
+ /* write pattern */
+ *pBlockData = SyncPattern;
+ ++pBlockData;
+
+ for (i=0; i<DataSize; i++)
+ {
+ char ch = *pData;
+ ++pData;
+ CheckSum^=ch;
+ *pBlockData = ch;
+ ++pBlockData;
+ }
+ *pBlockData = CheckSum&0x0ff;
+ }
+ }
+}
+
+
+#define CPC_DATA_CHUNK_SIZE 256
+#define CPC_DATA_BLOCK_SIZE 2048
+
+/* write a block of data to a file */
+void CPC_WriteTurboLoadingDataBlock(TZX_FILE *pFile, unsigned char SyncPattern, unsigned char *pData, int DataSize, int Pause)
+{
+ TZX_BLOCK *pBlock;
+ unsigned char *pBlockData;
+
+ int NumChunks;
+ int TZX_DataBlockSize;
+
+ /* divide into complete 256 byte blocks */
+ NumChunks = (DataSize+255)>>8;
+
+ /* each tape block is split into 256 chunks, each chunk has a CRC */
+
+ /* size of all chunks, plus CRC's for each block */
+ TZX_DataBlockSize =
+ /* size of all chunks */
+ (NumChunks<<8) +
+ /* size of CRC's for all chunks */
+ (NumChunks<<1) +
+ /* size of trailer in bytes */
+ 4 +
+ /* size of sync pattern */
+ 1;
+
+
+
+ pBlock = TZX_CreateBlock(TZX_TURBO_LOADING_DATA_BLOCK);
+ CPC_InitialiseTurboLoadingDataBlock(pBlock, BaudRate,Pause);
+
+
+ if (pBlock!=NULL)
+ {
+ /* add block to end of file */
+ TZX_AddBlockToEndOfFile(pFile,pBlock);
+
+ /* allocate data in block */
+ TZX_AddDataToBlock(pBlock, TZX_DataBlockSize);
+
+ pBlockData= TZX_GetBlockDataPtr(pBlock);
+
+ if (pBlockData!=NULL)
+ {
+ int i,j;
+ unsigned char *pDataPtr;
+ int DataSizeRemaining;
+ unsigned char *pBlockPtr;
+ unsigned short CRC;
+
+ pDataPtr = pData;
+ DataSizeRemaining = DataSize;
+ pBlockPtr = pBlockData;
+
+ /* write pattern */
+ pBlockPtr[0] = SyncPattern;
+ pBlockPtr++;
+
+ /* write each chunk in turn and calculate CRC */
+ for (i=0; i<NumChunks; i++)
+ {
+ /* copy data into block */
+ if (DataSizeRemaining<CPC_DATA_CHUNK_SIZE)
+ {
+ /* less than CPC_DATA_CHUNK_SIZE */
+ /* copy data, and fill rest with zeros */
+
+ /* copy less than 256 bytes */
+ memcpy(pBlockPtr, pDataPtr, DataSizeRemaining);
+ /* fill reset of chunk with zero's */
+ memset(pBlockPtr + DataSizeRemaining, 0, CPC_DATA_CHUNK_SIZE-DataSizeRemaining);
+ /* update source pointer */
+ pDataPtr+=DataSizeRemaining;
+ /* update size remaining - nothing */
+ DataSizeRemaining = 0;
+ }
+ else
+ {
+ /* greater or equal to CPC_DATA_CHUNK_SIZE */
+ /* copy CPC_DATA_CHUNK_SIZE max */
+ memcpy(pBlockPtr, pDataPtr, CPC_DATA_CHUNK_SIZE);
+ /* update source pointer */
+ pDataPtr += CPC_DATA_CHUNK_SIZE;
+ /* update size remaining */
+ DataSizeRemaining-=CPC_DATA_CHUNK_SIZE;
+ }
+
+ /* reset CRC */
+ CRC = 0x0ffff;
+
+ /* calculate CRC for block */
+ for (j=0; j<CPC_DATA_CHUNK_SIZE; j++)
+ {
+ char ch;
+
+ ch = pBlockPtr[0];
+ pBlockPtr++;
+ CRC = CRCupdate(CRC, ch);
+ }
+
+ /* store CRC inverted */
+ pBlockPtr[0] = (CRC>>8)^0x0ff;
+ pBlockPtr++;
+ pBlockPtr[0] = CRC^0x0ff;
+ pBlockPtr++;
+ }
+
+
+ /* write trailer */
+ memset(pBlockPtr, 0x0ff, 4);
+ }
+ }
+}
+
+/*
+ID : 14 - Pure data block
+-------
+ This is the same as in the turbo loading data block, except that it has
+ no pilot or sync pulses.
+
+00 2 Length of ZERO bit pulse
+02 2 Length of ONE bit pulse
+04 1 Used bits in LAST Byte
+05 2 Pause after this block in milliseconds (ms)
+07 3 Length of following data
+0A x Data
+*/
+
+void CPC_InitialisePureDataBlock(TZX_BLOCK *pBlock, int BaudRate, int Pause)
+{
+ unsigned char *pHeader = TZX_GetBlockHeaderPtr(pBlock);
+
+ if (pHeader!=NULL)
+ {
+ /* check it is a turbo-loading data block */
+ if (pHeader[0] == TZX_PURE_DATA_BLOCK)
+ {
+ int ZeroPulseLengthInMicroseconds;
+ long64 ZeroPulseLengthInCPCTStates;
+ int OnePulseLength;
+ int ZeroPulseLength;
+
+ pHeader++;
+ /* equation from CPC firmware guide:
+ Average baud rate: = 1 000 000/(3*half zero length) = 333 333/Half zero length
+ */
+
+ ZeroPulseLengthInMicroseconds = 333333/BaudRate;
+ ZeroPulseLengthInCPCTStates = ZeroPulseLengthInMicroseconds<<2;
+
+ ZeroPulseLength = (ZeroPulseLengthInCPCTStates*
+ (T_STATE_CONVERSION_FACTOR>>8))>>8;
+
+ /* one pulse is twice the size of a zero pulse */
+ OnePulseLength = ZeroPulseLength<<1;
+ /* write zero pulse length */
+ pHeader[0x00] = ZeroPulseLength;
+ pHeader[0x01] = ZeroPulseLength>>8;
+
+ /* write one pulse length */
+ pHeader[0x02] = OnePulseLength;
+ pHeader[0x03] = OnePulseLength>>8;
+
+ /* the end of the block will be the trailer bytes. Say all bits are
+ used, although, because it doesn't contain useful data it doesn't matter */
+ pHeader[0x04] = 8;
+
+ /* write pause */
+ pHeader[0x05] = (Pause & 0x0ff);
+ pHeader[0x06] = (Pause>>8) & 0x0ff;
+
+
+ }
+ }
+}
+
+
+/* the following is for a bitstream */
+unsigned char *pData;
+unsigned long ByteCount;
+unsigned long BitCount;
+
+/* initialise bit stream with buffer to write data to */
+void BitStream_Initialise(unsigned char *pBuffer)
+{
+ pData = pBuffer;
+ ByteCount = 0;
+ BitCount = 0;
+}
+
+/* write bit to stream */
+void BitStream_WriteBit(int Bit)
+{
+ unsigned char Data;
+
+ /* get current data written */
+ Data = pData[ByteCount];
+ Data &= ~(1<<(7-BitCount));
+ Data |= (Bit<<(7-BitCount));
+ pData[ByteCount] = Data;
+
+ /* increment bit count */
+ BitCount++;
+ /* if we overrun 8-bits, then bit 3 will be set, add this on */
+ ByteCount += (BitCount>>3);
+ /* mask off bit count */
+ BitCount &= 0x07;
+}
+
+/* write byte to stream */
+void BitStream_WriteByte(unsigned char Byte)
+{
+ int b;
+ int Bit;
+ unsigned char LocalByte;
+
+ LocalByte = Byte;
+
+ for (b=0; b<8; b++)
+ {
+ Bit = LocalByte & 0x080;
+ Bit = Bit>>7;
+ BitStream_WriteBit(Bit);
+ LocalByte = LocalByte<<1;
+ }
+}
+
+
+
+/* write a block of data to a file */
+void CPC_WritePureDataBlock(TZX_FILE *pFile, unsigned char SyncPattern, unsigned char *pData, int DataSize, int Pause)
+{
+ TZX_BLOCK *pBlock;
+ unsigned char *pBlockData;
+
+ int NumChunks;
+ int TZX_DataBlockSize;
+
+ /* divide into complete 256 byte blocks */
+ NumChunks = (DataSize+255)>>8;
+
+ /* each tape block is split into 256 chunks, each chunk has a CRC */
+
+ /* size of all chunks, plus CRC's for each block */
+ TZX_DataBlockSize =
+ /* size of all chunks */
+ (NumChunks<<8) +
+ /* size of CRC's for all chunks */
+ (NumChunks<<1) +
+ /* size of trailer in bytes */
+ 4 +
+ /* size of sync pattern */
+ 1;
+
+ TZX_DataBlockSize+=
+ /* pilot tone - CPC_PILOT_TONE_NUM_WAVES 1 bit's, a zero bit then data as before ... */
+ ((CPC_PILOT_TONE_NUM_WAVES + 1)+7)>>3;
+
+ pBlock = TZX_CreateBlock(TZX_PURE_DATA_BLOCK);
+ CPC_InitialisePureDataBlock(pBlock, BaudRate,Pause);
+
+
+ if (pBlock!=NULL)
+ {
+ /* add block to end of file */
+ TZX_AddBlockToEndOfFile(pFile,pBlock);
+
+ /* allocate data in block */
+ TZX_AddDataToBlock(pBlock, TZX_DataBlockSize);
+
+ pBlockData= TZX_GetBlockDataPtr(pBlock);
+
+ if (pBlockData!=NULL)
+ {
+ int i,j;
+ unsigned char *pDataPtr;
+ int DataSizeRemaining;
+ unsigned char *pBlockPtr;
+ unsigned short CRC;
+
+ pDataPtr = pData;
+ DataSizeRemaining = DataSize;
+ pBlockPtr = pBlockData;
+
+ BitStream_Initialise(pBlockPtr);
+
+ /* write leader */
+ for (i=0; i<CPC_PILOT_TONE_NUM_WAVES; i++)
+ {
+ BitStream_WriteBit(1);
+ }
+
+ BitStream_WriteBit(0);
+
+
+ BitStream_WriteByte(SyncPattern);
+
+ /* write each chunk in turn and calculate CRC */
+ for (i=0; i<NumChunks; i++)
+ {
+ int BlockSizeToWrite;
+
+ /* copy data into block */
+ if (DataSizeRemaining<CPC_DATA_CHUNK_SIZE)
+ {
+ BlockSizeToWrite = DataSizeRemaining;
+ }
+ else
+ {
+ BlockSizeToWrite = CPC_DATA_CHUNK_SIZE;
+ }
+
+ CRC = 0x0ffff;
+
+ for (j=0; j<BlockSizeToWrite; j++)
+ {
+ char ch;
+
+ /* get byte */
+ ch = pDataPtr[0];
+ pDataPtr++;
+ /* update CRC */
+ CRC = CRCupdate(CRC, ch);
+ /* write byte to stream */
+ BitStream_WriteByte(ch);
+ }
+
+ if (BlockSizeToWrite!=CPC_DATA_CHUNK_SIZE)
+ {
+ /* write padding zero's */
+ for (j=0; j<(CPC_DATA_CHUNK_SIZE-BlockSizeToWrite); j++)
+ {
+ char ch;
+
+ ch = 0;
+ /* update CRC */
+ CRC = CRCupdate(CRC, ch);
+ /* write byte to stream */
+ BitStream_WriteByte(ch);
+ }
+ }
+
+ DataSizeRemaining-=BlockSizeToWrite;
+
+ CRC = CRC^0x0ffff;
+
+ BitStream_WriteByte((CRC>>8));
+ BitStream_WriteByte(CRC);
+ }
+
+ /* write trailer */
+ for (i=0; i<32; i++)
+ {
+ BitStream_WriteBit(1);
+ }
+ }
+ }
+}
+
+/* write a data block in format specified */
+void CPC_WriteDataBlock(TZX_FILE *pFile, unsigned char SyncByte, unsigned char *pData, unsigned long DataSize, int Pause)
+{
+ switch (TZXWriteMethod)
+ {
+ case TZX_TURBO_LOADING_DATA_BLOCK:
+ {
+ CPC_WriteTurboLoadingDataBlock(pFile, SyncByte, pData, DataSize,Pause);
+ }
+ break;
+
+ case TZX_PURE_DATA_BLOCK:
+ {
+ /* write header */
+ CPC_WritePureDataBlock(pFile, SyncByte, pData, DataSize,Pause);
+ }
+ break;
+ }
+}
+
+#define UTILITY_NAME "2CDT"
+
+void DisplayInfo()
+{
+ printf("%s will transfer files into a .CDT/.TZX tape image, in Amstrad CPC/CPC+\r\n", UTILITY_NAME);
+ printf("KC Compact form.\r\n\r\n");
+ printf("Usage: %s [arguments] <input filename> <.cdt image>\r\n\r\n", UTILITY_NAME);
+ printf("-n - Blank CDT file before use\n");
+ printf("-b <number> - Specify Baud rate (default 2000)\n");
+ printf("-s <0 or 1> - Specify 'Speed Write'.\n");
+ printf(" 0 = 1000 baud, 1 = 2000 baud (default)\n");
+ printf("-t <method> - TZX Block Write Method.\n");
+ printf(" 0 = Pure Data, 1 = Turbo Loading (default)\n");
+ printf("-m <method> - Data method\n");
+ printf(" 0 = blocks (default)\n");
+ printf(" 1 = headerless (Firmware function: CAS READ - &BCA1) \n");
+ printf(" 2 = spectrum \n");
+ printf(" 3 = Two blocks. First block of 2K, second block has remainder\n");
+ printf(" 4 = Two blocks. First block of 1 byte, second block has remainder\n");
+ printf("-X <number> = Define or override execution address (default is &1000 if no header)\r\n");
+ printf("-L <number> = Define or override load address (default is &1000 if no header)\r\n");
+ printf("-F <number> = Define or override file type (0=BASIC, 2=Binary (default if no header)) etc. Applies to Data method 0\r\n");
+ printf("-p <number> = Set initial pause in milliseconds (default 3000ms)\r\n");
+ printf("-P = Add a 1ms pause for buggy emulators that ignore first block\r\n");
+ printf("-r <tape filename>\n");
+ printf(" - Add <input filename> as <tape filename> to CDT (rename file)\n");
+}
+
+extern char *optarg;
+
+int ReadNumberParameter(char *param)
+{
+ int Length = strlen(param);
+ BOOL bIsHex = FALSE;
+ int Offset = 0;
+ unsigned long Value = 0;
+ char ch;
+
+ if (Length==0)
+ return 0;
+
+ /* check for common prefixs for hex numbers */
+ if ((Length>1) && ((param[0]=='&') || (param[0]=='$')))
+ {
+ Offset = 1;
+ bIsHex = TRUE;
+ }
+ else if ((Length>2) && (param[0]=='0') && ((param[1]=='x') || (param[1]=='X')))
+ {
+ Offset = 2;
+ bIsHex = TRUE;
+ }
+
+ if (!bIsHex)
+ {
+ return atoi(param);
+ }
+
+ ch = param[Offset];
+ while (ch!='\0')
+ {
+ Value = Value<<4;
+ if ((ch>='0') && (ch<='9'))
+ {
+ Value = Value | (ch-'0');
+ }
+ else if ((ch>='a') && (ch<='f'))
+ {
+ Value = Value | ((ch-'a')+10);
+ }
+ else if ((ch>='A') && (ch<='F'))
+ {
+ Value = Value | ((ch-'A')+10);
+ }
+ Offset++;
+ ch = param[Offset];
+ }
+
+ return Value;
+}
+
+int main(int argc, char *argv[])
+{
+ unsigned char *pTapeFilename = NULL;
+
+ if (argc==1)
+ {
+ DisplayInfo();
+ }
+ else
+ {
+ TZX_FILE *pTZXFile;
+ unsigned char *pSourceFilename;
+ unsigned char *pDestFilename;
+ unsigned char *pData;
+ unsigned long DataLength;
+ char c;
+
+ /* initialise defaults */
+ BaudRate = 2000;
+ Pause = 3000;
+ Type = 2;
+ TypeOverride = FALSE;
+ LoadAddressOverride = FALSE;
+ TZXWriteMethod = TZX_TURBO_LOADING_DATA_BLOCK;
+ BlankBeforeUse = FALSE;
+ ExecutionAddress = LoadAddress = 0x01000;
+ ExecutionAddressOverride = FALSE;
+ LoadAddressOverride = FALSE;
+
+ printf("-n - Blank CDT file before use\n");
+ printf("-b <number> - Specify Baud rate (default 2000)\n");
+ printf("-s <0 or 1> - Specify 'Speed Write'.\n");
+ printf(" 0 = 1000 baud, 1 = 2000 baud (default)\n");
+ printf("-t <method> - TZX Block Write Method.\n");
+ printf(" 0 = Pure Data, 1 = Turbo Loading (default)\n");
+ printf("-m <method> - Data method\n");
+ printf(" 0 = blocks (default)\n");
+ printf(" 1 = headerless (Firmware function: CAS READ - &BCA1) \n");
+ printf(" 2 = spectrum \n");
+ printf(" 3 = Two blocks. First block of 2K, second block has remainder\n");
+ printf(" 4 = Two blocks. First block of 1 byte, second block has remainder\n");
+ printf("-X <number> = Define or override execution address (default is &1000 if no header)\r\n");
+ printf("-L <number> = Define or override load address (default is &1000 if no header)\r\n");
+ printf("-F <number> = Define or override file type (0=BASIC, 2=Binary (default if no header)) etc. Applies to Data method 0\r\n");
+ printf("-p <number> = Set initial pause in milliseconds (default 3000ms)\r\n");
+ printf("-P = Add a 1ms pause for buggy emulators that ignore first block\r\n");
+ printf("-r <tape filename>\n");
+ printf(" - Add <input filename> as <tape filename> to CDT (rename file)\n");
+
+
+ do
+ {
+ c = getopt(argc, argv,"r:nb:p:m:t:F:L:s:X:p:P");
+
+ switch (c)
+ {
+ case 'm':
+ {
+ int nMethod = atoi(optarg);
+ CPCMethod = nMethod;
+
+ }
+ break;
+
+ case 'p':
+ {
+ Pause = atoi(optarg);
+ if (Pause<0)
+ {
+ Pause = 0;
+ }
+ }
+ break;
+
+ case 'r':
+ {
+ pTapeFilename = optarg;
+ }
+ break;
+
+ case 'n':
+ {
+ BlankBeforeUse = TRUE;
+ }
+ break;
+
+ case 'b':
+ {
+ int Baud = atoi(optarg);
+ if ((Baud>0) && (Baud<6000))
+ BaudRate = Baud;
+ }
+ break;
+
+ case 'X':
+ {
+ ExecutionAddress = ReadNumberParameter(optarg) & 0x0ffff;
+ ExecutionAddressOverride = TRUE;
+ }
+ break;
+
+ case 'L':
+ {
+ LoadAddress = ReadNumberParameter(optarg) & 0x0ffff;
+ LoadAddressOverride = TRUE;
+ }
+ break;
+
+ case 's':
+ {
+ int SpeedWrite = atoi(optarg);
+ if (SpeedWrite==1)
+ {
+ BaudRate = 2000;
+ }
+ else
+ {
+ BaudRate = 1000;
+ }
+ }
+ break;
+
+ case 'F':
+ {
+ Type = atoi(optarg) & 0x0ff;
+ TypeOverride = TRUE;
+
+
+ }
+ break;
+
+
+ case 'P':
+ {
+ BuggyEmuExtraPause = TRUE;
+
+ }
+ break;
+
+ case 't':
+ {
+ int nMethod = atoi(optarg);
+ if (nMethod==0)
+ {
+ TZXWriteMethod = TZX_PURE_DATA_BLOCK;
+ }
+ else if (nMethod==1)
+ {
+ TZXWriteMethod = TZX_TURBO_LOADING_DATA_BLOCK;
+ }
+ else if (nMethod==2)
+ {
+ TZXWriteMethod = TZX_STANDARD_SPEED_DATA_BLOCK;
+ }
+ }
+ break;
+
+ default:
+ {
+ }
+ break;
+ }
+
+ }
+ while (c!=-1);
+
+ if ((argc-optind)==0)
+ {
+ printf("No source file or destination file have been specified!\n");
+ exit(1);
+ }
+
+ if ((argc-optind)==1)
+ {
+ printf("No destination file has been specified\n");
+ exit(1);
+ }
+
+ pSourceFilename = argv[optind];
+ pDestFilename = argv[optind+1];
+
+ /* create TZX file */
+ pTZXFile = TZX_CreateFile(TZX_VERSION_MAJOR,TZX_VERSION_MINOR);
+
+ if (pTZXFile!=NULL)
+ {
+ int nFile;
+
+
+ if (BlankBeforeUse)
+ {
+ TZX_BLOCK *pBlock;
+
+ /* if buggy emu, add an extra small pause */
+ if (BuggyEmuExtraPause)
+ {
+ pBlock = TZX_CreateBlock(TZX_PAUSE_BLOCK);
+
+ if (pBlock!=NULL)
+ {
+ /* add a 1ms initial pause for buggy emus */
+ TZX_SetupPauseBlock(pBlock, 1);
+ TZX_AddBlockToEndOfFile(pTZXFile,pBlock);
+ }
+ }
+
+
+ /* correct pause */
+ pBlock = TZX_CreateBlock(TZX_PAUSE_BLOCK);
+
+ if (pBlock!=NULL)
+ {
+ TZX_SetupPauseBlock(pBlock, Pause);
+ TZX_AddBlockToEndOfFile(pTZXFile,pBlock);
+ }
+ }
+
+
+ if (Host_LoadFile(pSourceFilename, &pData, &DataLength))
+ {
+ int FileOffset;
+ int FileLengthRemaining;
+ int TapeBlockSize;
+ BOOL FirstBlock,LastBlock;
+ int BlockIndex;
+ unsigned short BlockLocation;
+
+ /* header for tape file */
+ unsigned char TapeHeader[CPC_TAPE_HEADER_SIZE];
+
+ /* calculate checksum from loaded file */
+ unsigned short CalculatedChecksum = (unsigned short)AMSDOS_CalculateChecksum(pData);
+
+ /* get stored checksum */
+ unsigned short StoredChecksum =
+ (pData[67] & 0x0ff) |
+ (pData[68] & 0x0ff)<<8;
+
+ FileOffset = 0;
+ FileLengthRemaining = DataLength;
+ BlockIndex = 1;
+ FirstBlock =TRUE;
+
+ /* insert a pause block - 1 second, this is added onto the end of the previous block */
+ /* if (BlankBeforeUse == FALSE)
+ {
+ TZX_BLOCK *pBlock;
+
+ pBlock = TZX_CreateBlock(TZX_PAUSE_BLOCK);
+
+ if (pBlock!=NULL)
+ {
+ TZX_SetupPauseBlock(pBlock, 2000);
+ TZX_AddBlockToEndOfFile(pTZXFile,pBlock);
+ }
+ }
+*/
+
+
+ /* clear tape header */
+ memset(TapeHeader, 0, CPC_TAPE_HEADER_SIZE);
+
+ /* checksum's match? */
+ if (CalculatedChecksum==StoredChecksum)
+ {
+ /* copy file type */
+ TapeHeader[CPC_TAPE_HEADER_FILE_TYPE] = pData[CPC_TAPE_HEADER_FILE_TYPE];
+ /* copy execution address */
+ TapeHeader[CPC_TAPE_HEADER_DATA_EXECUTION_ADDRESS_LOW] = pData[CPC_TAPE_HEADER_DATA_EXECUTION_ADDRESS_LOW];
+ TapeHeader[CPC_TAPE_HEADER_DATA_EXECUTION_ADDRESS_HIGH] = pData[CPC_TAPE_HEADER_DATA_EXECUTION_ADDRESS_HIGH];
+ /* copy data location */
+ TapeHeader[CPC_TAPE_HEADER_DATA_LOCATION_LOW] = pData[CPC_TAPE_HEADER_DATA_LOCATION_LOW];
+ TapeHeader[CPC_TAPE_HEADER_DATA_LOCATION_HIGH] = pData[CPC_TAPE_HEADER_DATA_LOCATION_HIGH];
+
+ FileOffset+=128;
+ FileLengthRemaining-=128;
+
+ /* override execution address? */
+ if (ExecutionAddressOverride)
+ {
+ TapeHeader[CPC_TAPE_HEADER_DATA_EXECUTION_ADDRESS_LOW] = ExecutionAddress&0xFF;
+ TapeHeader[CPC_TAPE_HEADER_DATA_EXECUTION_ADDRESS_HIGH] = (ExecutionAddress>>8)&0xFF;
+ }
+
+ /* override type? */
+ if (TypeOverride)
+ {
+ TapeHeader[CPC_TAPE_HEADER_FILE_TYPE] = Type;
+ }
+
+ /* override load address? */
+ if (LoadAddressOverride)
+ {
+ TapeHeader[CPC_TAPE_HEADER_DATA_LOCATION_LOW] = LoadAddress&0xFF;
+ TapeHeader[CPC_TAPE_HEADER_DATA_LOCATION_HIGH] = (LoadAddress>>8)&0xFF;
+ }
+
+ }
+ else
+ {
+ /* set type */
+ TapeHeader[CPC_TAPE_HEADER_FILE_TYPE] = Type;
+
+ /* set execution address */
+ TapeHeader[CPC_TAPE_HEADER_DATA_EXECUTION_ADDRESS_LOW] = ExecutionAddress&0xFF;
+ TapeHeader[CPC_TAPE_HEADER_DATA_EXECUTION_ADDRESS_HIGH] = (ExecutionAddress>>8)&0xFF;
+
+ /* set load address */
+ TapeHeader[CPC_TAPE_HEADER_DATA_LOCATION_LOW] = LoadAddress&0xFF;
+ TapeHeader[CPC_TAPE_HEADER_DATA_LOCATION_HIGH] = (LoadAddress>>8)&0xFF;
+ }
+
+ if (pTapeFilename!=NULL)
+ {
+ int i;
+ int nLength = strlen(pTapeFilename);
+ if (nLength>16)
+ nLength = 16;
+ for (i=0; i<nLength; i++)
+ {
+ TapeHeader[i] = toupper(pTapeFilename[i]);
+ }
+ }
+ TapeHeader[CPC_TAPE_HEADER_DATA_LOGICAL_LENGTH_LOW] = (FileLengthRemaining & 0x0ff);
+ TapeHeader[CPC_TAPE_HEADER_DATA_LOGICAL_LENGTH_HIGH] = (FileLengthRemaining>>8) & 0x0ff;
+
+
+ BlockLocation = TapeHeader[CPC_TAPE_HEADER_DATA_LOCATION_LOW] |
+ (TapeHeader[CPC_TAPE_HEADER_DATA_LOCATION_HIGH]<<8);
+
+ if (CPCMethod == CPC_METHOD_SPECTRUM)
+ {
+ /* write data into block */
+ WriteStandardSpeedDataBlock(pTZXFile, 0x0ff, &pData[FileOffset], FileLengthRemaining, 1000);
+ }
+ else
+ {
+ do
+ {
+ unsigned char Flag;
+ /*
+ CPC can't handle this one
+ if (CPCMethod == CPC_METHOD_2BLOCKS)
+ {
+ if (FirstBlock)
+ {
+ TapeBlockSize=CPC_DATA_BLOCK_SIZE;
+ LastBlock = FALSE;
+ }
+ else
+ {
+ TapeBlockSize = FileLengthRemaining;
+ LastBlock = TRUE;
+ }
+ }
+ else
+ */
+ if (CPCMethod == CPC_METHOD_BLOCKS)
+ {
+ /* calc size of tape data block */
+ if (FileLengthRemaining>CPC_DATA_BLOCK_SIZE)
+ {
+ TapeBlockSize = CPC_DATA_BLOCK_SIZE;
+ LastBlock = FALSE;
+ }
+ else
+ {
+ TapeBlockSize = FileLengthRemaining;
+ LastBlock = TRUE;
+ }
+ }
+ else
+ if (CPCMethod == CPC_METHOD_HEADERLESS)
+ {
+ TapeBlockSize = FileLengthRemaining;
+ }
+
+
+
+ /**** HEADER ****/
+ /* SETUP TAPE RELATED DATA */
+ /* block index */
+ TapeHeader[CPC_TAPE_HEADER_BLOCK_NUMBER] = BlockIndex;
+
+ /* first block? */
+ if (FirstBlock)
+ {
+ FirstBlock = FALSE;
+
+ Flag = 0x0ff;
+ }
+ else
+ {
+ Flag = 0;
+ }
+
+ TapeHeader[CPC_TAPE_HEADER_FIRST_BLOCK_FLAG] = Flag;
+
+ /* last block? */
+ if (LastBlock)
+ {
+ Flag = 0x0ff;
+ }
+ else
+ {
+ Flag = 0;
+ }
+
+ TapeHeader[CPC_TAPE_HEADER_LAST_BLOCK_FLAG] = Flag;
+
+ /* size of data following */
+ TapeHeader[CPC_TAPE_HEADER_DATA_LENGTH_LOW] = (unsigned char)TapeBlockSize;
+ TapeHeader[CPC_TAPE_HEADER_DATA_LENGTH_HIGH] = (unsigned char)(TapeBlockSize>>8);
+
+ /* location of block */
+ TapeHeader[CPC_TAPE_HEADER_DATA_LOCATION_LOW] = (unsigned char)BlockLocation;
+ TapeHeader[CPC_TAPE_HEADER_DATA_LOCATION_HIGH] = (unsigned char)(BlockLocation>>8);
+
+ /* don't write a header if headerless */
+ if (CPCMethod!=CPC_METHOD_HEADERLESS)
+ {
+ /* write header */
+ CPC_WriteDataBlock(pTZXFile, 0x02c, TapeHeader, CPC_TAPE_HEADER_SIZE,10);
+ }
+
+ /* write data into block */
+ CPC_WriteDataBlock(pTZXFile, 0x016, &pData[FileOffset], TapeBlockSize,CPC_PAUSE_AFTER_BLOCK_IN_MS);
+
+ BlockLocation+=TapeBlockSize;
+ BlockIndex++;
+ FileOffset+=TapeBlockSize;
+ FileLengthRemaining -= TapeBlockSize;
+ }
+ while (FileLengthRemaining!=0);
+ }
+
+ free(pData);
+ }
+
+ /* write file */
+ if (BlankBeforeUse)
+ {
+ TZX_WriteFile(pTZXFile, pDestFilename);
+ }
+ else
+ {
+ TZX_AppendFile(pTZXFile, pDestFilename);
+ }
+
+ /* free it */
+ TZX_FreeFile(pTZXFile);
+ }
+ else
+ {
+ printf("Failed to open output file!\r\n");
+ exit(1);
+ }
+
+ }
+
+ exit(0);
+
+ return 0;
+}
diff --git a/tools/2CDT/src/defs.h b/tools/2CDT/src/defs.h
new file mode 100644
index 0000000..f042dde
--- /dev/null
+++ b/tools/2CDT/src/defs.h
@@ -0,0 +1,36 @@
+/*
+ * 2CDT Copyright (c) Kevin Thacker
+ *
+ * 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.
+ */
+#ifndef __DEFS_HEADER_INCLUDED__
+#define __DEFS_HEADER_INCLUDED__
+
+
+typedef int BOOL;
+
+#ifndef TRUE
+#define TRUE (1==1)
+#endif
+
+#ifndef FALSE
+#define FALSE (1==0)
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#endif
diff --git a/tools/2CDT/src/tzxfile.c b/tools/2CDT/src/tzxfile.c
new file mode 100644
index 0000000..3f550b0
--- /dev/null
+++ b/tools/2CDT/src/tzxfile.c
@@ -0,0 +1,445 @@
+/*
+ * 2CDT Copyright (c) Kevin Thacker
+ *
+ * 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <memory.h>
+/* TZX file support */
+#include "tzxfile.h"
+/* header for TZX file */
+const unsigned char *TZX_FileHeader = (const unsigned char *)"ZXTape!\x1a";
+
+/* the internal format for the TZX is a link-list system.
+Blocks can be edited. A new file can be written with the new data */
+
+
+
+/**************************************/
+/* insert block after block specified */
+void TZX_InsertBlockAfter(TZX_FILE *pFile,TZX_BLOCK *pBlock, TZX_BLOCK *pPrev)
+{
+ /* setup block pointers */
+ pBlock->pPrev = pPrev;
+ pBlock->pNext = pPrev->pNext;
+
+ /* setup pointers for block before */
+ pPrev->pNext = pBlock;
+}
+
+/***************************************/
+/* insert block before block specified */
+void TZX_InsertBlockBefore(TZX_FILE *pFile, TZX_BLOCK *pBlock, TZX_BLOCK *pNext)
+{
+ /* setup block pointers */
+ pBlock->pNext = pNext;
+ pBlock->pPrev = pNext->pPrev;
+
+ /* setup pointers for block before */
+ pNext->pPrev = pBlock;
+
+ /* is block we are inserting after the first in the list? */
+ if (pFile->pFirstBlock == pNext)
+ {
+ /* yes. New block is now the start of the list */
+ pFile->pFirstBlock = pBlock;
+ }
+}
+
+
+/*****************************************/
+/* insert a block at the end of the file */
+void TZX_AddBlockToEndOfFile(TZX_FILE *pFile, TZX_BLOCK *pBlock)
+{
+ /* blocks in file? */
+ if (pFile->pFirstBlock==NULL)
+ {
+ /* no */
+ pFile->pFirstBlock = pBlock;
+ }
+ else
+ {
+ /* yes */
+ TZX_BLOCK *pCurrentBlock;
+
+ /* search for last block in list */
+ pCurrentBlock = pFile->pFirstBlock;
+
+ while (pCurrentBlock->pNext!=NULL)
+ pCurrentBlock = pCurrentBlock->pNext;
+
+ TZX_InsertBlockAfter(pFile,pBlock, pCurrentBlock);
+ }
+}
+
+/********************************/
+/* detach block from block list */
+void TZX_DetachBlock(TZX_FILE *pFile,TZX_BLOCK *pBlock)
+{
+ /* block before this block? */
+ if (pBlock->pPrev!=NULL)
+ {
+ /* yes */
+ pBlock->pPrev->pNext = pBlock->pNext;
+ }
+ else
+ {
+ /* no, this block is first in list */
+ pFile->pFirstBlock = pBlock->pNext;
+ }
+
+ /* block after this block? */
+ if (pBlock->pNext!=NULL)
+ {
+ /* yes */
+ pBlock->pNext->pPrev = pBlock->pPrev;
+ }
+}
+
+/************************/
+/* free data in a block */
+void TZX_FreeBlock(TZX_BLOCK *pBlock)
+{
+ /* free it */
+ free(pBlock);
+}
+
+
+
+/******************************/
+/* create a internal TZX file */
+
+TZX_FILE *TZX_CreateFile(unsigned char VersionMajor, unsigned char VersionMinor)
+{
+ TZX_FILE *pTZXFile;
+
+ /* alloc the header */
+ pTZXFile = malloc(sizeof(TZX_FILE));
+
+ if (pTZXFile!=NULL)
+ {
+ /* set version */
+ pTZXFile->VersionMajor = VersionMajor;
+ pTZXFile->VersionMinor = VersionMinor;
+
+ /* initialise block linked list */
+ pTZXFile->pFirstBlock = NULL;
+ }
+
+ return pTZXFile;
+}
+
+/*******************/
+/* free a TZX file */
+
+void TZX_FreeFile(TZX_FILE *pFile)
+{
+ TZX_BLOCK *pBlock;
+
+ pBlock = pFile->pFirstBlock;
+
+ while (pBlock!=NULL)
+ {
+ TZX_BLOCK *pNextBlock = pBlock->pNext;
+
+ /* remove block from list */
+ TZX_DetachBlock(pFile, pBlock);
+
+ /* free TZX block */
+ TZX_FreeBlock(pBlock);
+
+ pBlock = pNextBlock;
+ }
+
+ /* free TZX file header */
+ free(pFile);
+}
+
+/*****************************************************************************************************/
+/* write a TZX file */
+
+void TZX_WriteBlocks(TZX_FILE *pTZXFile, FILE *fh)
+{
+ TZX_BLOCK *pBlock;
+
+ /* get pointer to first block */
+ pBlock = pTZXFile->pFirstBlock;
+
+ /* write each block in turn to file */
+ while (pBlock!=NULL)
+ {
+ if (pBlock->pBlockHeader!=NULL)
+ {
+ BOOL BlockHasData;
+ int BlockHeaderSize;
+ unsigned char BlockID;
+
+ /* get block ID */
+ BlockID = pBlock->pBlockHeader[0];
+ /* get size of header */
+ BlockHeaderSize = TZX_GetBlockHeaderSize(BlockID);
+ /* does block have additional data ? */
+ BlockHasData = TZX_BlockHasData(BlockID);
+
+ if ((!BlockHasData) || ((BlockHasData) && (pBlock->pBlockData!=NULL)))
+ {
+ /* block requires data and has data, or block doesn't require data */
+
+ /* write the header */
+ fwrite(pBlock->pBlockHeader, BlockHeaderSize, sizeof(unsigned char), fh);
+
+ if (pBlock->pBlockData!=NULL)
+ {
+ /* write the data */
+
+ fwrite(pBlock->pBlockData, pBlock->DataBlockSize, sizeof(unsigned char), fh);
+ }
+ }
+ }
+
+ /* next block */
+ pBlock = pBlock->pNext;
+ }
+}
+
+
+void TZX_AppendFile(TZX_FILE *pTZXFile, unsigned char *pFilename)
+{
+ FILE *fh;
+
+ /* open TZX file */
+ fh = fopen((const char *)pFilename,"r+b");
+
+ if (fh!=NULL)
+ {
+ TZX_BLOCK *pBlock;
+
+ fseek(fh, 0, SEEK_END);
+
+ TZX_WriteBlocks(pTZXFile, fh);
+
+ /* close TZX file */
+ fclose(fh);
+ }
+}
+
+
+void TZX_WriteFile(TZX_FILE *pTZXFile, unsigned char *pFilename)
+{
+ FILE *fh;
+
+ /* open TZX file */
+ fh = fopen((const char *)pFilename,"wb");
+
+ if (fh!=NULL)
+ {
+ TZX_BLOCK *pBlock;
+
+ /* write header */
+ fwrite(TZX_FileHeader, 8, sizeof(unsigned char), fh);
+ /* write version numbers */
+ fwrite(&pTZXFile->VersionMajor, 1, sizeof(unsigned char), fh);
+ fwrite(&pTZXFile->VersionMinor, 1, sizeof(unsigned char), fh);
+
+ TZX_WriteBlocks(pTZXFile, fh);
+
+ /* close TZX file */
+ fclose(fh);
+ }
+}
+
+void TZX_SetupPauseBlock(TZX_BLOCK *pBlock,unsigned long PauseInMilliseconds)
+{
+ unsigned char *pHeader = TZX_GetBlockHeaderPtr(pBlock);
+
+ if (pHeader!=NULL)
+ {
+ if (pHeader[0] == TZX_PAUSE_BLOCK)
+ {
+ pHeader[1] = (unsigned char)PauseInMilliseconds;
+ pHeader[2] = (unsigned char)(PauseInMilliseconds>>8);
+ }
+ }
+}
+
+/*****************************************************************************************************/
+
+/* given a TZX block ID, this returns the size of the header */
+int TZX_GetBlockHeaderSize(unsigned char ID)
+{
+ switch (ID)
+ {
+ case TZX_STANDARD_SPEED_DATA_BLOCK:
+ return 4+1;
+ case TZX_TURBO_LOADING_DATA_BLOCK:
+ return 18+1;
+
+ case TZX_PAUSE_BLOCK:
+ return 2+1;
+ case TZX_PURE_DATA_BLOCK:
+ return 0x0a + 1;
+ case TZX_DIRECT_RECORDING_BLOCK:
+ return 0x08 + 1;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************************************/
+/* return TRUE if the block has additional data, false if not */
+BOOL TZX_BlockHasData(unsigned char ID)
+{
+ switch (ID)
+ {
+ case TZX_STANDARD_SPEED_DATA_BLOCK:
+ case TZX_TURBO_LOADING_DATA_BLOCK:
+ case TZX_PURE_DATA_BLOCK:
+ case TZX_DIRECT_RECORDING_BLOCK:
+ return TRUE;
+
+ case TZX_PAUSE_BLOCK:
+ return FALSE;
+
+ default:
+ break;
+ }
+
+ return FALSE;
+
+}
+
+/*****************************************************************************************************/
+/* set block size */
+void TZX_SetBlockSizeInHeader(TZX_BLOCK *pBlock, unsigned long Size)
+{
+ unsigned char ID = pBlock->pBlockHeader[0];
+ unsigned char *pBlockData;
+
+ pBlockData = &pBlock->pBlockHeader[1];
+
+ switch (ID)
+ {
+ case TZX_STANDARD_SPEED_DATA_BLOCK:
+ {
+ pBlockData[2] = (unsigned char)Size;
+ pBlockData[3] = (unsigned char)(Size>>8);
+
+ }
+ break;
+
+ case TZX_TURBO_LOADING_DATA_BLOCK:
+ {
+ pBlockData[0x0f] = (unsigned char)Size;
+ pBlockData[0x010] = (unsigned char)(Size>>8);
+ pBlockData[0x011] = (unsigned char)(Size>>16);
+
+ }
+ break;
+
+ case TZX_PURE_DATA_BLOCK:
+ {
+ pBlockData[0x07] = (unsigned char)Size;
+ pBlockData[0x08] = (unsigned char)(Size>>8);
+ pBlockData[0x09] = (unsigned char)(Size>>16);
+ }
+ break;
+
+ case TZX_DIRECT_RECORDING_BLOCK:
+ {
+ pBlockData[0x05] = (unsigned char)Size;
+ pBlockData[0x06] = (unsigned char)(Size>>8);
+ pBlockData[0x07] = (unsigned char)(Size>>16);
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+/*****************************************************************************************************/
+/* create a block of the specified ID in the TZX image file */
+TZX_BLOCK *TZX_CreateBlock(unsigned char ID)
+{
+ TZX_BLOCK *pBlock;
+
+ pBlock = malloc(sizeof(TZX_BLOCK));
+
+ if (pBlock!=NULL)
+ {
+ int BlockHeaderSize;
+
+ /* reset block data */
+ memset(pBlock, 0, sizeof(TZX_BLOCK));
+
+ BlockHeaderSize = TZX_GetBlockHeaderSize(ID);
+
+ pBlock->pBlockHeader = malloc(BlockHeaderSize);
+
+ if (pBlock->pBlockHeader!=NULL)
+ {
+ pBlock->pBlockHeader[0] = ID;
+ }
+ }
+
+ return pBlock;
+}
+
+/*****************************************************************************************************/
+/* create a block of the specified ID in the TZX image file */
+void TZX_AddDataToBlock(TZX_BLOCK *pBlock, int DataSize)
+{
+ /* only add data if a header exists */
+ if (pBlock->pBlockHeader!=NULL)
+ {
+ /* get block id */
+ unsigned char BlockID = pBlock->pBlockHeader[0];
+
+ /* does this block ID have additional data? */
+ if (TZX_BlockHasData(BlockID))
+ {
+ /* allocate memory for the additional data */
+ pBlock->pBlockData = malloc(DataSize);
+
+ if (pBlock->pBlockData!=NULL)
+ {
+ pBlock->DataBlockSize = DataSize;
+
+ /* set size in TZX header */
+ TZX_SetBlockSizeInHeader(pBlock, DataSize);
+ }
+ }
+ }
+}
+
+/*****************************************************************************************************/
+/* get pointer to TZX data block */
+unsigned char *TZX_GetBlockDataPtr(TZX_BLOCK *pBlock)
+{
+ return pBlock->pBlockData;
+}
+
+/*****************************************************************************************************/
+/* get pointer to TZX data block */
+unsigned char *TZX_GetBlockHeaderPtr(TZX_BLOCK *pBlock)
+{
+ return pBlock->pBlockHeader;
+}
diff --git a/tools/2CDT/src/tzxfile.h b/tools/2CDT/src/tzxfile.h
new file mode 100644
index 0000000..397f5d1
--- /dev/null
+++ b/tools/2CDT/src/tzxfile.h
@@ -0,0 +1,79 @@
+/*
+ * 2CDT Copyright (c) Kevin Thacker
+ *
+ * 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.
+ */
+
+#ifndef __TZX_FILE_HEADER__
+#define __TZX_FILE_HEADER__
+
+#include "defs.h"
+
+#define TZX_VERSION_MAJOR 1
+#define TZX_VERSION_MINOR 10
+
+#define TZX_STANDARD_SPEED_DATA_BLOCK 0x010
+#define TZX_TURBO_LOADING_DATA_BLOCK 0x011
+#define TZX_PAUSE_BLOCK 0x020
+#define TZX_PURE_DATA_BLOCK 0x014
+#define TZX_DIRECT_RECORDING_BLOCK 0x015
+
+#define TZX_T_STATES 3500000
+
+
+#define TZX_HARDWARE_COMPUTER_CPC464 0x015 /* Amstrad CPC 464 */
+#define TZX_HARDWARE_COMPUTER_CPC664 0x016 /* Amstrad CPC 664 */
+#define TZX_HARDWARE_COMPUTER_CPC6128 0x017 /* Amstrad CPC 6128 */
+#define TZX_HARDWARE_COMPUTER_CPC464PLUS 0x018 /* Amstrad CPC 464+ */
+#define TZX_HARDWARE_COMPUTER_CPC6128PLUS 0x019 /* Amstrad CPC 6128+ */
+
+typedef struct TZX_BLOCK
+{
+ /* previous TZX block */
+ struct TZX_BLOCK *pPrev;
+ /* next TZX block */
+ struct TZX_BLOCK *pNext;
+ /* pointer to header data allocated for this block */
+ unsigned char *pBlockHeader;
+ /* size of data block */
+ unsigned long DataBlockSize;
+ /* pointer to data added to this block */
+ unsigned char *pBlockData;
+} TZX_BLOCK;
+
+typedef struct TZX_FILE
+{
+ /* version of TZX file */
+ unsigned char VersionMajor;
+ unsigned char VersionMinor;
+ /* pointer to first block */
+ TZX_BLOCK *pFirstBlock;
+} TZX_FILE;
+
+void TZX_WriteFile(TZX_FILE *pTZXFile, unsigned char *pFilename);
+unsigned char *TZX_GetBlockDataPtr(TZX_BLOCK *);
+unsigned char *TZX_GetBlockHeaderPtr(TZX_BLOCK *);
+
+TZX_FILE *TZX_CreateFile(unsigned char VersionMajor, unsigned char VersionMinor);
+void TZX_FreeFile(TZX_FILE *pFile);
+void TZX_AddDataToBlock(TZX_BLOCK *pBlock, int DataSize);
+unsigned char *TZX_GetDataBlockPtr(TZX_BLOCK *pBlock);
+void TZX_AddBlockToEndOfFile(TZX_FILE *pFile, TZX_BLOCK *pBlock);
+int TZX_GetBlockHeaderSize(unsigned char ID);
+BOOL TZX_BlockHasData(unsigned char ID);
+TZX_BLOCK *TZX_CreateBlock(unsigned char ID);
+void TZX_SetupPauseBlock(TZX_BLOCK *pBlock,unsigned long PauseInMilliseconds);
+#endif
+
diff --git a/tools/Makefile b/tools/Makefile
new file mode 100644
index 0000000..fa59614
--- /dev/null
+++ b/tools/Makefile
@@ -0,0 +1,38 @@
+BIN=idsk 2cdt ucl png2crtc hex2bin
+
+all: $(BIN)
+CC=gcc
+CFLAGS=-s -O3 -Wall
+
+idsk:
+ mkdir iDSK/build
+ cd iDSK/build && cmake ../
+ make -C iDSK/build
+ cp iDSK/build/iDSK idsk
+ rm -rf iDSK/build
+
+2cdt:
+ make -C 2CDT
+ cp 2CDT/2cdt .
+
+png2crtc:
+ make -C gfx2crtc
+ cp gfx2crtc/png2crtc .
+
+%.o: %.c
+ $(CC) $(CFLAGS) $< -o $@ -c
+
+ucl: ucl.o
+ $(CC) -lucl $< -o $@
+
+hex2bin:
+ make -C hex2bin-2.0
+ cp hex2bin-2.0/bin/hex2bin .
+
+.PHONY: clean
+clean:
+ make -C 2CDT clean
+ make -C gfx2crtc clean
+ make -C hex2bin-2.0 clean
+ rm -f $(BIN) *.o
+
diff --git a/tools/README.ucl b/tools/README.ucl
new file mode 100644
index 0000000..ade95f9
--- /dev/null
+++ b/tools/README.ucl
@@ -0,0 +1,7 @@
+This is a simple compressor using the UCL library.
+
+It takes the data from stdin and writes to stdout.
+
+It is limited to MAX_MEM (64kb), but you should be compressing
+way less than that anyway!
+
diff --git a/tools/bin2h.py b/tools/bin2h.py
new file mode 100755
index 0000000..c430538
--- /dev/null
+++ b/tools/bin2h.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python
+
+from argparse import ArgumentParser
+
+__version__ = "1.0"
+
+def main():
+
+ parser = ArgumentParser(description="Bin to H converter",
+ epilog="Copyright (C) 2014 Juan J Martinez <jjm@usebox.net>",
+ )
+
+ parser.add_argument("--version", action="version", version="%(prog)s " + __version__)
+ parser.add_argument("file", help="file to convert")
+ parser.add_argument("id", help="variable to use")
+
+ args = parser.parse_args()
+
+ with open(args.file, "rb") as fd:
+ data = bytearray(fd.read())
+
+ data_out = ""
+ for part in range(0, len(data), 8):
+ if data_out:
+ data_out += ",\n"
+ data_out += ', '.join(["0x%02x" % b for b in data[part: part + 8]])
+
+ print("/* file: %s */" % args.file)
+ print("#define %s_LEN %d\n" % (args.id.upper(), len(data)))
+ print("const unsigned char %s[] = {\n%s\n};\n" % (args.id, data_out))
+
+if __name__ == "__main__":
+ main()
+
diff --git a/tools/chksize b/tools/chksize
new file mode 100755
index 0000000..6f2c9b8
--- /dev/null
+++ b/tools/chksize
@@ -0,0 +1,42 @@
+#!/usr/bin/env python3
+
+import sys
+
+# video memory + back buffer (stack in 0x200)
+TOP_MEM = 0xc000
+
+
+def main():
+ if len(sys.argv) != 3:
+ sys.exit("usage: %s load_addr filename.map" % sys.argv[0])
+
+ load_addr = int(sys.argv[1])
+
+ with open(sys.argv[2], "r") as fd:
+ lines = fd.readlines()
+ # warnings
+ for line in lines:
+ if "l__INITIALIZED" in line:
+ init_size = int(line.split()[0], base=16)
+ if init_size != 0:
+ print("*WARNING* Initialized data found")
+ # search for HEAP
+ for line in lines:
+ if "s__HEAP" in line:
+ heap_addr = int(line.split()[0], base=16)
+ max_mem = TOP_MEM - load_addr
+ cur_mem = heap_addr - load_addr
+ left_mem = max_mem - cur_mem
+ print("""\
+***
+ Max: {} bytes
+ Current: {} bytes ({} bytes left)
+***
+""".format(max_mem, cur_mem, left_mem))
+ sys.exit(0)
+
+ sys.exit("HEAP size not found")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tools/dump-pal.py b/tools/dump-pal.py
new file mode 100755
index 0000000..c87d7e7
--- /dev/null
+++ b/tools/dump-pal.py
@@ -0,0 +1,95 @@
+#!/usr/bin/env python
+
+__version__ = "1.0"
+
+from argparse import ArgumentParser
+from PIL import Image
+
+# firmware
+CPC_PAL = (
+ [0, 0, 0],
+ [0, 0, 128],
+ [0, 0, 255],
+ [128, 0, 0],
+ [128, 0, 128],
+ [128, 0, 255],
+ [255, 0, 0],
+ [255, 0, 128],
+ [255, 0, 255],
+ [0, 128, 0],
+ [0, 128, 128],
+ [0, 128, 255],
+ [128, 128, 0],
+ [128, 128, 128],
+ [128, 128, 255],
+ [255, 128, 0],
+ [255, 128, 128],
+ [255, 128, 255],
+ [0, 255, 0],
+ [0, 255, 128],
+ [0, 255, 255],
+ [128, 255, 0],
+ [128, 255, 128],
+ [128, 255, 255],
+ [255, 255, 0],
+ [255, 255, 128],
+ [255, 255, 255],
+ )
+
+# hardware
+CPC_PAL_HW = (
+ 0x54, 0x44, 0x55, 0x5c, 0x58, 0x5d, 0x4c, 0x45, 0x4d,
+ 0x56, 0x46, 0x57, 0x5e, 0x40, 0x5f, 0x4e, 0x47, 0x4f,
+ 0x52, 0x42, 0x53, 0x5a, 0x59, 0x5b, 0x4a, 0x43, 0x4b,
+ )
+
+def main():
+
+ parser = ArgumentParser(description="PNG to CPC palette (firmware)",
+ epilog="Copyright (C) 2015 Juan J Martinez <jjm@usebox.net>",
+ )
+
+ parser.add_argument("--version", action="version", version="%(prog)s " + __version__)
+ parser.add_argument("--hw", action="store_true", dest="hardware")
+ parser.add_argument("image", help="image to convert")
+ parser.add_argument("pal_dump", help="filename for the palette dump")
+
+ args = parser.parse_args()
+
+ try:
+ image = Image.open(args.image)
+ except IOError:
+ parser.error("failed to open the image")
+
+ if image.mode != "P":
+ parser.error("not an indexed image (no palette)")
+
+ palette = image.getpalette()
+ if not palette:
+ parser.error("failed to extract the palette (is this an indexed image?)")
+
+ colors = image.getcolors(maxcolors=16)
+ if not colors:
+ parser.error("failed to extract the palette (color limit is 16)")
+
+ rgb = []
+ for _, i in colors:
+ c = palette[i * 3:i * 3 + 3]
+ if c not in CPC_PAL:
+ parser.error("%r not in the CPC palette" % c)
+ if c not in rgb:
+ rgb.append(c)
+
+ out = [CPC_PAL.index(c) for c in rgb]
+ if len(out) < 16:
+ out.extend([i for i in range(16 - len(out))])
+
+ if args.hardware:
+ out = [CPC_PAL_HW[c] for c in out]
+
+ with open(args.pal_dump, "wb") as fd:
+ fd.write(bytearray(out))
+
+if __name__ == "__main__":
+ main()
+
diff --git a/tools/encrypt.py b/tools/encrypt.py
new file mode 100644
index 0000000..6e03336
--- /dev/null
+++ b/tools/encrypt.py
@@ -0,0 +1,25 @@
+
+def enc(key, text):
+ p = 0x59
+ r = []
+ for c in text:
+ new = ((ord(c) ^ p) ^ key) & 0xff
+ r.append(new)
+ p = new
+ return r
+
+def dec(key, text):
+ p = 0x59
+ r = []
+ for c in text:
+ new = ((c ^ key) ^ p) & 0xff
+ r.append(new)
+ p = c
+ return r
+
+res = enc(0xfe, "THE WAR IS OVER AND\nWE PREVAILED.\n\nFOR NOW...\n\nYOU ARE A LEGEND!\n\nTHANKS FOR PLAYING\nTHE GAME.\0")
+print ", ".join("0x%02x" % r for r in res)
+
+res = dec(0xfe, res)
+print "".join(chr(r) for r in res)
+
diff --git a/tools/gfx2crtc/AUTHORS b/tools/gfx2crtc/AUTHORS
new file mode 100644
index 0000000..4cb7787
--- /dev/null
+++ b/tools/gfx2crtc/AUTHORS
@@ -0,0 +1,5 @@
+Logiciel Initial :
+CloudStrife/Shinra (Quentin Carlier) <cloudstrife@cpcscene.com>
+
+Contributors:
+PulkoMandy/Shinra (Adrien Destugues) <pulkomandy@gmail.com>
diff --git a/tools/gfx2crtc/LICENCE b/tools/gfx2crtc/LICENCE
new file mode 100644
index 0000000..1613fca
--- /dev/null
+++ b/tools/gfx2crtc/LICENCE
@@ -0,0 +1,512 @@
+
+CONTRAT DE LICENCE DE LOGICIEL LIBRE CeCILL
+
+
+ Avertissement
+
+Ce contrat est une licence de logiciel libre issue d'une concertation
+entre ses auteurs afin que le respect de deux grands principes préside à
+sa rédaction:
+
+ * d'une part, le respect des principes de diffusion des logiciels
+ libres: accès au code source, droits étendus conférés aux
+ utilisateurs,
+ * d'autre part, la désignation d'un droit applicable, le droit
+ français, auquel elle est conforme, tant au regard du droit de la
+ responsabilité civile que du droit de la propriété intellectuelle
+ et de la protection qu'il offre aux auteurs et titulaires des
+ droits patrimoniaux sur un logiciel.
+
+Les auteurs de la licence CeCILL (pour Ce[a] C[nrs] I[nria] L[ogiciel]
+L[ibre]) sont:
+
+Commissariat à l'Energie Atomique - CEA, établissement public de
+recherche à caractère scientifique, technique et industriel, dont le
+siège est situé 25 rue Leblanc, immeuble Le Ponant D, 75015 Paris.
+
+Centre National de la Recherche Scientifique - CNRS, établissement
+public à caractère scientifique et technologique, dont le siège est
+situé 3 rue Michel-Ange, 75794 Paris cedex 16.
+
+Institut National de Recherche en Informatique et en Automatique -
+INRIA, établissement public à caractère scientifique et technologique,
+dont le siège est situé Domaine de Voluceau, Rocquencourt, BP 105, 78153
+Le Chesnay cedex.
+
+
+ Préambule
+
+Ce contrat est une licence de logiciel libre dont l'objectif est de
+conférer aux utilisateurs la liberté de modification et de
+redistribution du logiciel régi par cette licence dans le cadre d'un
+modèle de diffusion en logiciel libre.
+
+L'exercice de ces libertés est assorti de certains devoirs à la charge
+des utilisateurs afin de préserver ce statut au cours des
+redistributions ultérieures.
+
+L'accessibilité au code source et les droits de copie, de modification
+et de redistribution qui en découlent ont pour contrepartie de n'offrir
+aux utilisateurs qu'une garantie limitée et de ne faire peser sur
+l'auteur du logiciel, le titulaire des droits patrimoniaux et les
+concédants successifs qu'une responsabilité restreinte.
+
+A cet égard l'attention de l'utilisateur est attirée sur les risques
+associés au chargement, à l'utilisation, à la modification et/ou au
+développement et à la reproduction du logiciel par l'utilisateur étant
+donné sa spécificité de logiciel libre, qui peut le rendre complexe à
+manipuler et qui le réserve donc à des développeurs ou des
+professionnels avertis possédant des connaissances informatiques
+approfondies. Les utilisateurs sont donc invités à charger et tester
+l'adéquation du logiciel à leurs besoins dans des conditions permettant
+d'assurer la sécurité de leurs systèmes et/ou de leurs données et, plus
+généralement, à l'utiliser et l'exploiter dans les mêmes conditions de
+sécurité. Ce contrat peut être reproduit et diffusé librement, sous
+réserve de le conserver en l'état, sans ajout ni suppression de clauses.
+
+Ce contrat est susceptible de s'appliquer à tout logiciel dont le
+titulaire des droits patrimoniaux décide de soumettre l'exploitation aux
+dispositions qu'il contient.
+
+
+ Article 1 - DEFINITIONS
+
+Dans ce contrat, les termes suivants, lorsqu'ils seront écrits avec une
+lettre capitale, auront la signification suivante:
+
+Contrat: désigne le présent contrat de licence, ses éventuelles versions
+postérieures et annexes.
+
+Logiciel: désigne le logiciel sous sa forme de Code Objet et/ou de Code
+Source et le cas échéant sa documentation, dans leur état au moment de
+l'acceptation du Contrat par le Licencié.
+
+Logiciel Initial: désigne le Logiciel sous sa forme de Code Source et
+éventuellement de Code Objet et le cas échéant sa documentation, dans
+leur état au moment de leur première diffusion sous les termes du Contrat.
+
+Logiciel Modifié: désigne le Logiciel modifié par au moins une
+Contribution.
+
+Code Source: désigne l'ensemble des instructions et des lignes de
+programme du Logiciel et auquel l'accès est nécessaire en vue de
+modifier le Logiciel.
+
+Code Objet: désigne les fichiers binaires issus de la compilation du
+Code Source.
+
+Titulaire: désigne le ou les détenteurs des droits patrimoniaux d'auteur
+sur le Logiciel Initial.
+
+Licencié: désigne le ou les utilisateurs du Logiciel ayant accepté le
+Contrat.
+
+Contributeur: désigne le Licencié auteur d'au moins une Contribution.
+
+Concédant: désigne le Titulaire ou toute personne physique ou morale
+distribuant le Logiciel sous le Contrat.
+
+Contribution: désigne l'ensemble des modifications, corrections,
+traductions, adaptations et/ou nouvelles fonctionnalités intégrées dans
+le Logiciel par tout Contributeur, ainsi que tout Module Interne.
+
+Module: désigne un ensemble de fichiers sources y compris leur
+documentation qui permet de réaliser des fonctionnalités ou services
+supplémentaires à ceux fournis par le Logiciel.
+
+Module Externe: désigne tout Module, non dérivé du Logiciel, tel que ce
+Module et le Logiciel s'exécutent dans des espaces d'adressage
+différents, l'un appelant l'autre au moment de leur exécution.
+
+Module Interne: désigne tout Module lié au Logiciel de telle sorte
+qu'ils s'exécutent dans le même espace d'adressage.
+
+GNU GPL: désigne la GNU General Public License dans sa version 2 ou
+toute version ultérieure, telle que publiée par Free Software Foundation
+Inc.
+
+Parties: désigne collectivement le Licencié et le Concédant.
+
+Ces termes s'entendent au singulier comme au pluriel.
+
+
+ Article 2 - OBJET
+
+Le Contrat a pour objet la concession par le Concédant au Licencié d'une
+licence non exclusive, cessible et mondiale du Logiciel telle que
+définie ci-après à l'article 5 pour toute la durée de protection des droits
+portant sur ce Logiciel.
+
+
+ Article 3 - ACCEPTATION
+
+3.1 L'acceptation par le Licencié des termes du Contrat est réputée
+acquise du fait du premier des faits suivants:
+
+ * (i) le chargement du Logiciel par tout moyen notamment par
+ téléchargement à partir d'un serveur distant ou par chargement à
+ partir d'un support physique;
+ * (ii) le premier exercice par le Licencié de l'un quelconque des
+ droits concédés par le Contrat.
+
+3.2 Un exemplaire du Contrat, contenant notamment un avertissement
+relatif aux spécificités du Logiciel, à la restriction de garantie et à
+la limitation à un usage par des utilisateurs expérimentés a été mis à
+disposition du Licencié préalablement à son acceptation telle que
+définie à l'article 3.1 ci dessus et le Licencié reconnaît en avoir pris
+connaissance.
+
+
+ Article 4 - ENTREE EN VIGUEUR ET DUREE
+
+
+ 4.1 ENTREE EN VIGUEUR
+
+Le Contrat entre en vigueur à la date de son acceptation par le Licencié
+telle que définie en 3.1.
+
+
+ 4.2 DUREE
+
+Le Contrat produira ses effets pendant toute la durée légale de
+protection des droits patrimoniaux portant sur le Logiciel.
+
+
+ Article 5 - ETENDUE DES DROITS CONCEDES
+
+Le Concédant concède au Licencié, qui accepte, les droits suivants sur
+le Logiciel pour toutes destinations et pour la durée du Contrat dans
+les conditions ci-après détaillées.
+
+Par ailleurs, si le Concédant détient ou venait à détenir un ou
+plusieurs brevets d'invention protégeant tout ou partie des
+fonctionnalités du Logiciel ou de ses composants, il s'engage à ne pas
+opposer les éventuels droits conférés par ces brevets aux Licenciés
+successifs qui utiliseraient, exploiteraient ou modifieraient le
+Logiciel. En cas de cession de ces brevets, le Concédant s'engage à
+faire reprendre les obligations du présent alinéa aux cessionnaires.
+
+
+ 5.1 DROIT D'UTILISATION
+
+Le Licencié est autorisé à utiliser le Logiciel, sans restriction quant
+aux domaines d'application, étant ci-après précisé que cela comporte:
+
+ 1. la reproduction permanente ou provisoire du Logiciel en tout ou
+ partie par tout moyen et sous toute forme.
+
+ 2. le chargement, l'affichage, l'exécution, ou le stockage du
+ Logiciel sur tout support.
+
+ 3. la possibilité d'en observer, d'en étudier, ou d'en tester le
+ fonctionnement afin de déterminer les idées et principes qui sont
+ à la base de n'importe quel élément de ce Logiciel; et ceci,
+ lorsque le Licencié effectue toute opération de chargement,
+ d'affichage, d'exécution, de transmission ou de stockage du
+ Logiciel qu'il est en droit d'effectuer en vertu du Contrat.
+
+
+ 5.2 DROIT D'APPORTER DES CONTRIBUTIONS
+
+Le droit d'apporter des Contributions comporte le droit de traduire,
+d'adapter, d'arranger ou d'apporter toute autre modification au Logiciel
+et le droit de reproduire le logiciel en résultant.
+
+Le Licencié est autorisé à apporter toute Contribution au Logiciel sous
+réserve de mentionner, de façon explicite, son nom en tant qu'auteur de
+cette Contribution et la date de création de celle-ci.
+
+
+ 5.3 DROIT DE DISTRIBUTION
+
+Le droit de distribution comporte notamment le droit de diffuser, de
+transmettre et de communiquer le Logiciel au public sur tout support et
+par tout moyen ainsi que le droit de mettre sur le marché à titre
+onéreux ou gratuit, un ou des exemplaires du Logiciel par tout procédé.
+
+Le Licencié est autorisé à distribuer des copies du Logiciel, modifié ou
+non, à des tiers dans les conditions ci-après détaillées.
+
+
+ 5.3.1 DISTRIBUTION DU LOGICIEL SANS MODIFICATION
+
+Le Licencié est autorisé à distribuer des copies conformes du Logiciel,
+sous forme de Code Source ou de Code Objet, à condition que cette
+distribution respecte les dispositions du Contrat dans leur totalité et
+soit accompagnée:
+
+ 1. d'un exemplaire du Contrat,
+
+ 2. d'un avertissement relatif à la restriction de garantie et de
+ responsabilité du Concédant telle que prévue aux articles 8
+ et 9,
+
+et que, dans le cas où seul le Code Objet du Logiciel est redistribué,
+le Licencié permette aux futurs Licenciés d'accéder facilement au Code
+Source complet du Logiciel en indiquant les modalités d'accès, étant
+entendu que le coût additionnel d'acquisition du Code Source ne devra
+pas excéder le simple coût de transfert des données.
+
+
+ 5.3.2 DISTRIBUTION DU LOGICIEL MODIFIE
+
+Lorsque le Licencié apporte une Contribution au Logiciel, les conditions
+de distribution du Logiciel Modifié en résultant sont alors soumises à
+l'intégralité des dispositions du Contrat.
+
+Le Licencié est autorisé à distribuer le Logiciel Modifié, sous forme de
+code source ou de code objet, à condition que cette distribution
+respecte les dispositions du Contrat dans leur totalité et soit
+accompagnée:
+
+ 1. d'un exemplaire du Contrat,
+
+ 2. d'un avertissement relatif à la restriction de garantie et de
+ responsabilité du Concédant telle que prévue aux articles 8
+ et 9,
+
+et que, dans le cas où seul le code objet du Logiciel Modifié est
+redistribué, le Licencié permette aux futurs Licenciés d'accéder
+facilement au code source complet du Logiciel Modifié en indiquant les
+modalités d'accès, étant entendu que le coût additionnel d'acquisition
+du code source ne devra pas excéder le simple coût de transfert des données.
+
+
+ 5.3.3 DISTRIBUTION DES MODULES EXTERNES
+
+Lorsque le Licencié a développé un Module Externe les conditions du
+Contrat ne s'appliquent pas à ce Module Externe, qui peut être distribué
+sous un contrat de licence différent.
+
+
+ 5.3.4 COMPATIBILITE AVEC LA LICENCE GNU GPL
+
+Le Licencié peut inclure un code soumis aux dispositions d'une des
+versions de la licence GNU GPL dans le Logiciel modifié ou non et
+distribuer l'ensemble sous les conditions de la même version de la
+licence GNU GPL.
+
+Le Licencié peut inclure le Logiciel modifié ou non dans un code soumis
+aux dispositions d'une des versions de la licence GNU GPL et distribuer
+l'ensemble sous les conditions de la même version de la licence GNU GPL.
+
+
+ Article 6 - PROPRIETE INTELLECTUELLE
+
+
+ 6.1 SUR LE LOGICIEL INITIAL
+
+Le Titulaire est détenteur des droits patrimoniaux sur le Logiciel
+Initial. Toute utilisation du Logiciel Initial est soumise au respect
+des conditions dans lesquelles le Titulaire a choisi de diffuser son
+oeuvre et nul autre n'a la faculté de modifier les conditions de
+diffusion de ce Logiciel Initial.
+
+Le Titulaire s'engage à ce que le Logiciel Initial reste au moins régi
+par le Contrat et ce, pour la durée visée à l'article 4.2.
+
+
+ 6.2 SUR LES CONTRIBUTIONS
+
+Le Licencié qui a développé une Contribution est titulaire sur celle-ci
+des droits de propriété intellectuelle dans les conditions définies par
+la législation applicable.
+
+
+ 6.3 SUR LES MODULES EXTERNES
+
+Le Licencié qui a développé un Module Externe est titulaire sur celui-ci
+des droits de propriété intellectuelle dans les conditions définies par
+la législation applicable et reste libre du choix du contrat régissant
+sa diffusion.
+
+
+ 6.4 DISPOSITIONS COMMUNES
+
+Le Licencié s'engage expressément:
+
+ 1. à ne pas supprimer ou modifier de quelque manière que ce soit les
+ mentions de propriété intellectuelle apposées sur le Logiciel;
+
+ 2. à reproduire à l'identique lesdites mentions de propriété
+ intellectuelle sur les copies du Logiciel modifié ou non.
+
+Le Licencié s'engage à ne pas porter atteinte, directement ou
+indirectement, aux droits de propriété intellectuelle du Titulaire et/ou
+des Contributeurs sur le Logiciel et à prendre, le cas échéant, à
+l'égard de son personnel toutes les mesures nécessaires pour assurer le
+respect des dits droits de propriété intellectuelle du Titulaire et/ou
+des Contributeurs.
+
+
+ Article 7 - SERVICES ASSOCIES
+
+7.1 Le Contrat n'oblige en aucun cas le Concédant à la réalisation de
+prestations d'assistance technique ou de maintenance du Logiciel.
+
+Cependant le Concédant reste libre de proposer ce type de services. Les
+termes et conditions d'une telle assistance technique et/ou d'une telle
+maintenance seront alors déterminés dans un acte séparé. Ces actes de
+maintenance et/ou assistance technique n'engageront que la seule
+responsabilité du Concédant qui les propose.
+
+7.2 De même, tout Concédant est libre de proposer, sous sa seule
+responsabilité, à ses licenciés une garantie, qui n'engagera que lui,
+lors de la redistribution du Logiciel et/ou du Logiciel Modifié et ce,
+dans les conditions qu'il souhaite. Cette garantie et les modalités
+financières de son application feront l'objet d'un acte séparé entre le
+Concédant et le Licencié.
+
+
+ Article 8 - RESPONSABILITE
+
+8.1 Sous réserve des dispositions de l'article 8.2, le Licencié a la
+faculté, sous réserve de prouver la faute du Concédant concerné, de
+solliciter la réparation du préjudice direct qu'il subirait du fait du
+Logiciel et dont il apportera la preuve.
+
+8.2 La responsabilité du Concédant est limitée aux engagements pris en
+application du Contrat et ne saurait être engagée en raison notamment:
+(i) des dommages dus à l'inexécution, totale ou partielle, de ses
+obligations par le Licencié, (ii) des dommages directs ou indirects
+découlant de l'utilisation ou des performances du Logiciel subis par le
+Licencié et (iii) plus généralement d'un quelconque dommage indirect. En
+particulier, les Parties conviennent expressément que tout préjudice
+financier ou commercial (par exemple perte de données, perte de
+bénéfices, perte d'exploitation, perte de clientèle ou de commandes,
+manque à gagner, trouble commercial quelconque) ou toute action dirigée
+contre le Licencié par un tiers, constitue un dommage indirect et
+n'ouvre pas droit à réparation par le Concédant.
+
+
+ Article 9 - GARANTIE
+
+9.1 Le Licencié reconnaît que l'état actuel des connaissances
+scientifiques et techniques au moment de la mise en circulation du
+Logiciel ne permet pas d'en tester et d'en vérifier toutes les
+utilisations ni de détecter l'existence d'éventuels défauts. L'attention
+du Licencié a été attirée sur ce point sur les risques associés au
+chargement, à l'utilisation, la modification et/ou au développement et à
+la reproduction du Logiciel qui sont réservés à des utilisateurs avertis.
+
+Il relève de la responsabilité du Licencié de contrôler, par tous
+moyens, l'adéquation du produit à ses besoins, son bon fonctionnement et
+de s'assurer qu'il ne causera pas de dommages aux personnes et aux biens.
+
+9.2 Le Concédant déclare de bonne foi être en droit de concéder
+l'ensemble des droits attachés au Logiciel (comprenant notamment les
+droits visés à l'article 5).
+
+9.3 Le Licencié reconnaît que le Logiciel est fourni "en l'état" par le
+Concédant sans autre garantie, expresse ou tacite, que celle prévue à
+l'article 9.2 et notamment sans aucune garantie sur sa valeur commerciale,
+son caractère sécurisé, innovant ou pertinent.
+
+En particulier, le Concédant ne garantit pas que le Logiciel est exempt
+d'erreur, qu'il fonctionnera sans interruption, qu'il sera compatible
+avec l'équipement du Licencié et sa configuration logicielle ni qu'il
+remplira les besoins du Licencié.
+
+9.4 Le Concédant ne garantit pas, de manière expresse ou tacite, que le
+Logiciel ne porte pas atteinte à un quelconque droit de propriété
+intellectuelle d'un tiers portant sur un brevet, un logiciel ou sur tout
+autre droit de propriété. Ainsi, le Concédant exclut toute garantie au
+profit du Licencié contre les actions en contrefaçon qui pourraient être
+diligentées au titre de l'utilisation, de la modification, et de la
+redistribution du Logiciel. Néanmoins, si de telles actions sont
+exercées contre le Licencié, le Concédant lui apportera son aide
+technique et juridique pour sa défense. Cette aide technique et
+juridique est déterminée au cas par cas entre le Concédant concerné et
+le Licencié dans le cadre d'un protocole d'accord. Le Concédant dégage
+toute responsabilité quant à l'utilisation de la dénomination du
+Logiciel par le Licencié. Aucune garantie n'est apportée quant à
+l'existence de droits antérieurs sur le nom du Logiciel et sur
+l'existence d'une marque.
+
+
+ Article 10 - RESILIATION
+
+10.1 En cas de manquement par le Licencié aux obligations mises à sa
+charge par le Contrat, le Concédant pourra résilier de plein droit le
+Contrat trente (30) jours après notification adressée au Licencié et
+restée sans effet.
+
+10.2 Le Licencié dont le Contrat est résilié n'est plus autorisé à
+utiliser, modifier ou distribuer le Logiciel. Cependant, toutes les
+licences qu'il aura concédées antérieurement à la résiliation du Contrat
+resteront valides sous réserve qu'elles aient été effectuées en
+conformité avec le Contrat.
+
+
+ Article 11 - DISPOSITIONS DIVERSES
+
+
+ 11.1 CAUSE EXTERIEURE
+
+Aucune des Parties ne sera responsable d'un retard ou d'une défaillance
+d'exécution du Contrat qui serait dû à un cas de force majeure, un cas
+fortuit ou une cause extérieure, telle que, notamment, le mauvais
+fonctionnement ou les interruptions du réseau électrique ou de
+télécommunication, la paralysie du réseau liée à une attaque
+informatique, l'intervention des autorités gouvernementales, les
+catastrophes naturelles, les dégâts des eaux, les tremblements de terre,
+le feu, les explosions, les grèves et les conflits sociaux, l'état de
+guerre...
+
+11.2 Le fait, par l'une ou l'autre des Parties, d'omettre en une ou
+plusieurs occasions de se prévaloir d'une ou plusieurs dispositions du
+Contrat, ne pourra en aucun cas impliquer renonciation par la Partie
+intéressée à s'en prévaloir ultérieurement.
+
+11.3 Le Contrat annule et remplace toute convention antérieure, écrite
+ou orale, entre les Parties sur le même objet et constitue l'accord
+entier entre les Parties sur cet objet. Aucune addition ou modification
+aux termes du Contrat n'aura d'effet à l'égard des Parties à moins
+d'être faite par écrit et signée par leurs représentants dûment habilités.
+
+11.4 Dans l'hypothèse où une ou plusieurs des dispositions du Contrat
+s'avèrerait contraire à une loi ou à un texte applicable, existants ou
+futurs, cette loi ou ce texte prévaudrait, et les Parties feraient les
+amendements nécessaires pour se conformer à cette loi ou à ce texte.
+Toutes les autres dispositions resteront en vigueur. De même, la
+nullité, pour quelque raison que ce soit, d'une des dispositions du
+Contrat ne saurait entraîner la nullité de l'ensemble du Contrat.
+
+
+ 11.5 LANGUE
+
+Le Contrat est rédigé en langue française et en langue anglaise, ces
+deux versions faisant également foi.
+
+
+ Article 12 - NOUVELLES VERSIONS DU CONTRAT
+
+12.1 Toute personne est autorisée à copier et distribuer des copies de
+ce Contrat.
+
+12.2 Afin d'en préserver la cohérence, le texte du Contrat est protégé
+et ne peut être modifié que par les auteurs de la licence, lesquels se
+réservent le droit de publier périodiquement des mises à jour ou de
+nouvelles versions du Contrat, qui posséderont chacune un numéro
+distinct. Ces versions ultérieures seront susceptibles de prendre en
+compte de nouvelles problématiques rencontrées par les logiciels libres.
+
+12.3 Tout Logiciel diffusé sous une version donnée du Contrat ne pourra
+faire l'objet d'une diffusion ultérieure que sous la même version du
+Contrat ou une version postérieure, sous réserve des dispositions de
+l'article 5.3.4.
+
+
+ Article 13 - LOI APPLICABLE ET COMPETENCE TERRITORIALE
+
+13.1 Le Contrat est régi par la loi française. Les Parties conviennent
+de tenter de régler à l'amiable les différends ou litiges qui
+viendraient à se produire par suite ou à l'occasion du Contrat.
+
+13.2 A défaut d'accord amiable dans un délai de deux (2) mois à compter
+de leur survenance et sauf situation relevant d'une procédure d'urgence,
+les différends ou litiges seront portés par la Partie la plus diligente
+devant les Tribunaux compétents de Paris.
+
+
+Version 2.0 du 2006-09-05.
diff --git a/tools/gfx2crtc/LICENSE b/tools/gfx2crtc/LICENSE
new file mode 100644
index 0000000..fcc8df2
--- /dev/null
+++ b/tools/gfx2crtc/LICENSE
@@ -0,0 +1,506 @@
+
+CeCILL FREE SOFTWARE LICENSE AGREEMENT
+
+
+ Notice
+
+This Agreement is a Free Software license agreement that is the result
+of discussions between its authors in order to ensure compliance with
+the two main principles guiding its drafting:
+
+ * firstly, compliance with the principles governing the distribution
+ of Free Software: access to source code, broad rights granted to
+ users,
+ * secondly, the election of a governing law, French law, with which
+ it is conformant, both as regards the law of torts and
+ intellectual property law, and the protection that it offers to
+ both authors and holders of the economic rights over software.
+
+The authors of the CeCILL (for Ce[a] C[nrs] I[nria] L[ogiciel] L[ibre])
+license are:
+
+Commissariat à l'Energie Atomique - CEA, a public scientific, technical
+and industrial research establishment, having its principal place of
+business at 25 rue Leblanc, immeuble Le Ponant D, 75015 Paris, France.
+
+Centre National de la Recherche Scientifique - CNRS, a public scientific
+and technological establishment, having its principal place of business
+at 3 rue Michel-Ange, 75794 Paris cedex 16, France.
+
+Institut National de Recherche en Informatique et en Automatique -
+INRIA, a public scientific and technological establishment, having its
+principal place of business at Domaine de Voluceau, Rocquencourt, BP
+105, 78153 Le Chesnay cedex, France.
+
+
+ Preamble
+
+The purpose of this Free Software license agreement is to grant users
+the right to modify and redistribute the software governed by this
+license within the framework of an open source distribution model.
+
+The exercising of these rights is conditional upon certain obligations
+for users so as to preserve this status for all subsequent redistributions.
+
+In consideration of access to the source code and the rights to copy,
+modify and redistribute granted by the license, users are provided only
+with a limited warranty and the software's author, the holder of the
+economic rights, and the successive licensors only have limited liability.
+
+In this respect, the risks associated with loading, using, modifying
+and/or developing or reproducing the software by the user are brought to
+the user's attention, given its Free Software status, which may make it
+complicated to use, with the result that its use is reserved for
+developers and experienced professionals having in-depth computer
+knowledge. Users are therefore encouraged to load and test the
+suitability of the software as regards their requirements in conditions
+enabling the security of their systems and/or data to be ensured and,
+more generally, to use and operate it in the same conditions of
+security. This Agreement may be freely reproduced and published,
+provided it is not altered, and that no provisions are either added or
+removed herefrom.
+
+This Agreement may apply to any or all software for which the holder of
+the economic rights decides to submit the use thereof to its provisions.
+
+
+ Article 1 - DEFINITIONS
+
+For the purpose of this Agreement, when the following expressions
+commence with a capital letter, they shall have the following meaning:
+
+Agreement: means this license agreement, and its possible subsequent
+versions and annexes.
+
+Software: means the software in its Object Code and/or Source Code form
+and, where applicable, its documentation, "as is" when the Licensee
+accepts the Agreement.
+
+Initial Software: means the Software in its Source Code and possibly its
+Object Code form and, where applicable, its documentation, "as is" when
+it is first distributed under the terms and conditions of the Agreement.
+
+Modified Software: means the Software modified by at least one
+Contribution.
+
+Source Code: means all the Software's instructions and program lines to
+which access is required so as to modify the Software.
+
+Object Code: means the binary files originating from the compilation of
+the Source Code.
+
+Holder: means the holder(s) of the economic rights over the Initial
+Software.
+
+Licensee: means the Software user(s) having accepted the Agreement.
+
+Contributor: means a Licensee having made at least one Contribution.
+
+Licensor: means the Holder, or any other individual or legal entity, who
+distributes the Software under the Agreement.
+
+Contribution: means any or all modifications, corrections, translations,
+adaptations and/or new functions integrated into the Software by any or
+all Contributors, as well as any or all Internal Modules.
+
+Module: means a set of sources files including their documentation that
+enables supplementary functions or services in addition to those offered
+by the Software.
+
+External Module: means any or all Modules, not derived from the
+Software, so that this Module and the Software run in separate address
+spaces, with one calling the other when they are run.
+
+Internal Module: means any or all Module, connected to the Software so
+that they both execute in the same address space.
+
+GNU GPL: means the GNU General Public License version 2 or any
+subsequent version, as published by the Free Software Foundation Inc.
+
+Parties: mean both the Licensee and the Licensor.
+
+These expressions may be used both in singular and plural form.
+
+
+ Article 2 - PURPOSE
+
+The purpose of the Agreement is the grant by the Licensor to the
+Licensee of a non-exclusive, transferable and worldwide license for the
+Software as set forth in Article 5 hereinafter for the whole term of the
+protection granted by the rights over said Software.
+
+
+ Article 3 - ACCEPTANCE
+
+3.1 The Licensee shall be deemed as having accepted the terms and
+conditions of this Agreement upon the occurrence of the first of the
+following events:
+
+ * (i) loading the Software by any or all means, notably, by
+ downloading from a remote server, or by loading from a physical
+ medium;
+ * (ii) the first time the Licensee exercises any of the rights
+ granted hereunder.
+
+3.2 One copy of the Agreement, containing a notice relating to the
+characteristics of the Software, to the limited warranty, and to the
+fact that its use is restricted to experienced users has been provided
+to the Licensee prior to its acceptance as set forth in Article 3.1
+hereinabove, and the Licensee hereby acknowledges that it has read and
+understood it.
+
+
+ Article 4 - EFFECTIVE DATE AND TERM
+
+
+ 4.1 EFFECTIVE DATE
+
+The Agreement shall become effective on the date when it is accepted by
+the Licensee as set forth in Article 3.1.
+
+
+ 4.2 TERM
+
+The Agreement shall remain in force for the entire legal term of
+protection of the economic rights over the Software.
+
+
+ Article 5 - SCOPE OF RIGHTS GRANTED
+
+The Licensor hereby grants to the Licensee, who accepts, the following
+rights over the Software for any or all use, and for the term of the
+Agreement, on the basis of the terms and conditions set forth hereinafter.
+
+Besides, if the Licensor owns or comes to own one or more patents
+protecting all or part of the functions of the Software or of its
+components, the Licensor undertakes not to enforce the rights granted by
+these patents against successive Licensees using, exploiting or
+modifying the Software. If these patents are transferred, the Licensor
+undertakes to have the transferees subscribe to the obligations set
+forth in this paragraph.
+
+
+ 5.1 RIGHT OF USE
+
+The Licensee is authorized to use the Software, without any limitation
+as to its fields of application, with it being hereinafter specified
+that this comprises:
+
+ 1. permanent or temporary reproduction of all or part of the Software
+ by any or all means and in any or all form.
+
+ 2. loading, displaying, running, or storing the Software on any or
+ all medium.
+
+ 3. entitlement to observe, study or test its operation so as to
+ determine the ideas and principles behind any or all constituent
+ elements of said Software. This shall apply when the Licensee
+ carries out any or all loading, displaying, running, transmission
+ or storage operation as regards the Software, that it is entitled
+ to carry out hereunder.
+
+
+ 5.2 ENTITLEMENT TO MAKE CONTRIBUTIONS
+
+The right to make Contributions includes the right to translate, adapt,
+arrange, or make any or all modifications to the Software, and the right
+to reproduce the resulting software.
+
+The Licensee is authorized to make any or all Contributions to the
+Software provided that it includes an explicit notice that it is the
+author of said Contribution and indicates the date of the creation thereof.
+
+
+ 5.3 RIGHT OF DISTRIBUTION
+
+In particular, the right of distribution includes the right to publish,
+transmit and communicate the Software to the general public on any or
+all medium, and by any or all means, and the right to market, either in
+consideration of a fee, or free of charge, one or more copies of the
+Software by any means.
+
+The Licensee is further authorized to distribute copies of the modified
+or unmodified Software to third parties according to the terms and
+conditions set forth hereinafter.
+
+
+ 5.3.1 DISTRIBUTION OF SOFTWARE WITHOUT MODIFICATION
+
+The Licensee is authorized to distribute true copies of the Software in
+Source Code or Object Code form, provided that said distribution
+complies with all the provisions of the Agreement and is accompanied by:
+
+ 1. a copy of the Agreement,
+
+ 2. a notice relating to the limitation of both the Licensor's
+ warranty and liability as set forth in Articles 8 and 9,
+
+and that, in the event that only the Object Code of the Software is
+redistributed, the Licensee allows future Licensees unhindered access to
+the full Source Code of the Software by indicating how to access it, it
+being understood that the additional cost of acquiring the Source Code
+shall not exceed the cost of transferring the data.
+
+
+ 5.3.2 DISTRIBUTION OF MODIFIED SOFTWARE
+
+When the Licensee makes a Contribution to the Software, the terms and
+conditions for the distribution of the resulting Modified Software
+become subject to all the provisions of this Agreement.
+
+The Licensee is authorized to distribute the Modified Software, in
+source code or object code form, provided that said distribution
+complies with all the provisions of the Agreement and is accompanied by:
+
+ 1. a copy of the Agreement,
+
+ 2. a notice relating to the limitation of both the Licensor's
+ warranty and liability as set forth in Articles 8 and 9,
+
+and that, in the event that only the object code of the Modified
+Software is redistributed, the Licensee allows future Licensees
+unhindered access to the full source code of the Modified Software by
+indicating how to access it, it being understood that the additional
+cost of acquiring the source code shall not exceed the cost of
+transferring the data.
+
+
+ 5.3.3 DISTRIBUTION OF EXTERNAL MODULES
+
+When the Licensee has developed an External Module, the terms and
+conditions of this Agreement do not apply to said External Module, that
+may be distributed under a separate license agreement.
+
+
+ 5.3.4 COMPATIBILITY WITH THE GNU GPL
+
+The Licensee can include a code that is subject to the provisions of one
+of the versions of the GNU GPL in the Modified or unmodified Software,
+and distribute that entire code under the terms of the same version of
+the GNU GPL.
+
+The Licensee can include the Modified or unmodified Software in a code
+that is subject to the provisions of one of the versions of the GNU GPL,
+and distribute that entire code under the terms of the same version of
+the GNU GPL.
+
+
+ Article 6 - INTELLECTUAL PROPERTY
+
+
+ 6.1 OVER THE INITIAL SOFTWARE
+
+The Holder owns the economic rights over the Initial Software. Any or
+all use of the Initial Software is subject to compliance with the terms
+and conditions under which the Holder has elected to distribute its work
+and no one shall be entitled to modify the terms and conditions for the
+distribution of said Initial Software.
+
+The Holder undertakes that the Initial Software will remain ruled at
+least by this Agreement, for the duration set forth in Article 4.2.
+
+
+ 6.2 OVER THE CONTRIBUTIONS
+
+The Licensee who develops a Contribution is the owner of the
+intellectual property rights over this Contribution as defined by
+applicable law.
+
+
+ 6.3 OVER THE EXTERNAL MODULES
+
+The Licensee who develops an External Module is the owner of the
+intellectual property rights over this External Module as defined by
+applicable law and is free to choose the type of agreement that shall
+govern its distribution.
+
+
+ 6.4 JOINT PROVISIONS
+
+The Licensee expressly undertakes:
+
+ 1. not to remove, or modify, in any manner, the intellectual property
+ notices attached to the Software;
+
+ 2. to reproduce said notices, in an identical manner, in the copies
+ of the Software modified or not.
+
+The Licensee undertakes not to directly or indirectly infringe the
+intellectual property rights of the Holder and/or Contributors on the
+Software and to take, where applicable, vis-à-vis its staff, any and all
+measures required to ensure respect of said intellectual property rights
+of the Holder and/or Contributors.
+
+
+ Article 7 - RELATED SERVICES
+
+7.1 Under no circumstances shall the Agreement oblige the Licensor to
+provide technical assistance or maintenance services for the Software.
+
+However, the Licensor is entitled to offer this type of services. The
+terms and conditions of such technical assistance, and/or such
+maintenance, shall be set forth in a separate instrument. Only the
+Licensor offering said maintenance and/or technical assistance services
+shall incur liability therefor.
+
+7.2 Similarly, any Licensor is entitled to offer to its licensees, under
+its sole responsibility, a warranty, that shall only be binding upon
+itself, for the redistribution of the Software and/or the Modified
+Software, under terms and conditions that it is free to decide. Said
+warranty, and the financial terms and conditions of its application,
+shall be subject of a separate instrument executed between the Licensor
+and the Licensee.
+
+
+ Article 8 - LIABILITY
+
+8.1 Subject to the provisions of Article 8.2, the Licensee shall be
+entitled to claim compensation for any direct loss it may have suffered
+from the Software as a result of a fault on the part of the relevant
+Licensor, subject to providing evidence thereof.
+
+8.2 The Licensor's liability is limited to the commitments made under
+this Agreement and shall not be incurred as a result of in particular:
+(i) loss due the Licensee's total or partial failure to fulfill its
+obligations, (ii) direct or consequential loss that is suffered by the
+Licensee due to the use or performance of the Software, and (iii) more
+generally, any consequential loss. In particular the Parties expressly
+agree that any or all pecuniary or business loss (i.e. loss of data,
+loss of profits, operating loss, loss of customers or orders,
+opportunity cost, any disturbance to business activities) or any or all
+legal proceedings instituted against the Licensee by a third party,
+shall constitute consequential loss and shall not provide entitlement to
+any or all compensation from the Licensor.
+
+
+ Article 9 - WARRANTY
+
+9.1 The Licensee acknowledges that the scientific and technical
+state-of-the-art when the Software was distributed did not enable all
+possible uses to be tested and verified, nor for the presence of
+possible defects to be detected. In this respect, the Licensee's
+attention has been drawn to the risks associated with loading, using,
+modifying and/or developing and reproducing the Software which are
+reserved for experienced users.
+
+The Licensee shall be responsible for verifying, by any or all means,
+the suitability of the product for its requirements, its good working
+order, and for ensuring that it shall not cause damage to either persons
+or properties.
+
+9.2 The Licensor hereby represents, in good faith, that it is entitled
+to grant all the rights over the Software (including in particular the
+rights set forth in Article 5).
+
+9.3 The Licensee acknowledges that the Software is supplied "as is" by
+the Licensor without any other express or tacit warranty, other than
+that provided for in Article 9.2 and, in particular, without any warranty
+as to its commercial value, its secured, safe, innovative or relevant
+nature.
+
+Specifically, the Licensor does not warrant that the Software is free
+from any error, that it will operate without interruption, that it will
+be compatible with the Licensee's own equipment and software
+configuration, nor that it will meet the Licensee's requirements.
+
+9.4 The Licensor does not either expressly or tacitly warrant that the
+Software does not infringe any third party intellectual property right
+relating to a patent, software or any other property right. Therefore,
+the Licensor disclaims any and all liability towards the Licensee
+arising out of any or all proceedings for infringement that may be
+instituted in respect of the use, modification and redistribution of the
+Software. Nevertheless, should such proceedings be instituted against
+the Licensee, the Licensor shall provide it with technical and legal
+assistance for its defense. Such technical and legal assistance shall be
+decided on a case-by-case basis between the relevant Licensor and the
+Licensee pursuant to a memorandum of understanding. The Licensor
+disclaims any and all liability as regards the Licensee's use of the
+name of the Software. No warranty is given as regards the existence of
+prior rights over the name of the Software or as regards the existence
+of a trademark.
+
+
+ Article 10 - TERMINATION
+
+10.1 In the event of a breach by the Licensee of its obligations
+hereunder, the Licensor may automatically terminate this Agreement
+thirty (30) days after notice has been sent to the Licensee and has
+remained ineffective.
+
+10.2 A Licensee whose Agreement is terminated shall no longer be
+authorized to use, modify or distribute the Software. However, any
+licenses that it may have granted prior to termination of the Agreement
+shall remain valid subject to their having been granted in compliance
+with the terms and conditions hereof.
+
+
+ Article 11 - MISCELLANEOUS
+
+
+ 11.1 EXCUSABLE EVENTS
+
+Neither Party shall be liable for any or all delay, or failure to
+perform the Agreement, that may be attributable to an event of force
+majeure, an act of God or an outside cause, such as defective
+functioning or interruptions of the electricity or telecommunications
+networks, network paralysis following a virus attack, intervention by
+government authorities, natural disasters, water damage, earthquakes,
+fire, explosions, strikes and labor unrest, war, etc.
+
+11.2 Any failure by either Party, on one or more occasions, to invoke
+one or more of the provisions hereof, shall under no circumstances be
+interpreted as being a waiver by the interested Party of its right to
+invoke said provision(s) subsequently.
+
+11.3 The Agreement cancels and replaces any or all previous agreements,
+whether written or oral, between the Parties and having the same
+purpose, and constitutes the entirety of the agreement between said
+Parties concerning said purpose. No supplement or modification to the
+terms and conditions hereof shall be effective as between the Parties
+unless it is made in writing and signed by their duly authorized
+representatives.
+
+11.4 In the event that one or more of the provisions hereof were to
+conflict with a current or future applicable act or legislative text,
+said act or legislative text shall prevail, and the Parties shall make
+the necessary amendments so as to comply with said act or legislative
+text. All other provisions shall remain effective. Similarly, invalidity
+of a provision of the Agreement, for any reason whatsoever, shall not
+cause the Agreement as a whole to be invalid.
+
+
+ 11.5 LANGUAGE
+
+The Agreement is drafted in both French and English and both versions
+are deemed authentic.
+
+
+ Article 12 - NEW VERSIONS OF THE AGREEMENT
+
+12.1 Any person is authorized to duplicate and distribute copies of this
+Agreement.
+
+12.2 So as to ensure coherence, the wording of this Agreement is
+protected and may only be modified by the authors of the License, who
+reserve the right to periodically publish updates or new versions of the
+Agreement, each with a separate number. These subsequent versions may
+address new issues encountered by Free Software.
+
+12.3 Any Software distributed under a given version of the Agreement may
+only be subsequently distributed under the same version of the Agreement
+or a subsequent version, subject to the provisions of Article 5.3.4.
+
+
+ Article 13 - GOVERNING LAW AND JURISDICTION
+
+13.1 The Agreement is governed by French law. The Parties agree to
+endeavor to seek an amicable solution to any disagreements or disputes
+that may arise during the performance of the Agreement.
+
+13.2 Failing an amicable solution within two (2) months as from their
+occurrence, and unless emergency proceedings are necessary, the
+disagreements or disputes shall be referred to the Paris Courts having
+jurisdiction, by the more diligent Party.
+
+
+Version 2.0 dated 2006-09-05.
diff --git a/tools/gfx2crtc/README b/tools/gfx2crtc/README
new file mode 100644
index 0000000..596349d
--- /dev/null
+++ b/tools/gfx2crtc/README
@@ -0,0 +1,36 @@
+English Version at the end.
+
+Version Française (French Version)
+----------------------------------------------------------------------
+ gfx2crtc - utilitaire de convertion d'image vers image au format cpc
+----------------------------------------------------------------------
+
+gfx2crtc est un utilitaire qui permet la convertion d'image (format brut
+lineaire 8bits par pixel ou PNG 1,2 ou 4 bits) dans un format compatible avec
+l'Amstrad CPC et Plus.
+
+Logiciel Initial écrit par :
+CloudStrife/Shinra (Quentin Carlier) <cloudstrife@cpcscene.com>.
+Il est diffusé sur la Licence de Logiciel Libre CeCILL version 2,
+Voire LICENCE pour plus d'information.
+Voire le fichier AUTHORS pour voire la liste des differents Contributeur.
+
+Utilisation :
+-------------
+
+English Version
+----------------------------------------------------
+ gfx2crtc - gfx convert tools to amstrad cpc format
+----------------------------------------------------
+
+gfx2crtc is a tools program for convert gfx (linear raw 8bits per pixel or
+PNG 1,2 ou 4 bits) in a compatible format for Amstrad CPC and Plus.
+
+Initial Software write by :
+CloudStrife/Shinra (Quentin Carlier) <cloudstrife@cpcscene.com>.
+It is diffused on the CeCILL Free Software License v2,
+See LICENSE for more information.
+See AUTHORS for the list of Contributor.
+
+Usage :
+------- \ No newline at end of file
diff --git a/tools/gfx2crtc/TODO b/tools/gfx2crtc/TODO
new file mode 100644
index 0000000..a394ead
--- /dev/null
+++ b/tools/gfx2crtc/TODO
@@ -0,0 +1,9 @@
+- Ajouter un mode de convertion lineaire (équivalent à R9=0)
+- Extraire la palette d'un png si palette CPC
+- Gestion du registre 13 // Fait r47
+- Possibilité de ne garder qu'un pixel sur 2 (exemple pour Mode 0)
+- Possibilité de ne garder qu'une ligne sur 2 (exemple pour Mode 2)
+- Sprite plus (4bits/pixel, 1pixel/octets, 16x16, gauche a droite, haut en bas)
+- Gestion mode entrelacé
+- Visualisation ?
+- Version Drag'n'drop pour windows ?
diff --git a/tools/gfx2crtc/libraw2crtc.c b/tools/gfx2crtc/libraw2crtc.c
new file mode 100644
index 0000000..b7d2f97
--- /dev/null
+++ b/tools/gfx2crtc/libraw2crtc.c
@@ -0,0 +1,186 @@
+/* GFX2CRTC - libraw2crtc.c
+ * CloudStrife - 20080921
+ * Diffusé sous licence libre CeCILL v2
+ * Voire LICENCE
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+unsigned short addrCalc(unsigned char vcc, unsigned char rcc, unsigned char hcc, unsigned char cclk, unsigned char r1, unsigned char r12, unsigned char r13)
+{
+ unsigned short MA;
+ unsigned short addr;
+
+ //MA = vcc*r1 + hcc + (0x0C)*256;
+ MA = vcc*r1 + hcc + r12*256 + r13;
+ addr = cclk | ((MA & 0x03FF) << 1);
+ addr = addr | ((rcc & 0x07) << 11);
+ addr = addr | ((MA & 0x3000) << 2);
+
+ return addr;
+}
+
+unsigned char mode0interlace(unsigned char *x)
+{
+ unsigned char mode0pixel[] = {0, 64, 4, 68, 16, 80, 20, 84, 1, 65, 5, 69, 17, 81, 21, 85};
+ return mode0pixel[x[0]] << 1 | mode0pixel[x[1]];
+}
+
+unsigned char mode1interlace(unsigned char *x)
+{
+ unsigned char mode1pixel[] = {0, 16, 1, 17};
+ return mode1pixel[x[0]] << 3 | mode1pixel[x[1]] << 2 | mode1pixel[x[2]] << 1 | mode1pixel[x[3]];
+}
+
+unsigned char mode2interlace(unsigned char *x)
+{
+ unsigned char out = 0;
+ int i;
+ for(i = 0; i < 8; i++) out += ((x[7-i]&1) << i);
+ return out;
+}
+
+unsigned char mode3interlace(unsigned char *x)
+{
+ unsigned char mode3pixel[] = {0, 16, 1, 17};
+ return mode3pixel[x[0]] << 3 | mode3pixel[x[1]] << 2;
+}
+
+unsigned char (*ptrMode)(unsigned char *x);
+
+unsigned char *raw2crtc(unsigned char *input, unsigned short width, unsigned short height, unsigned char mode, unsigned char r9, unsigned long *outSize, unsigned char *r1, unsigned char r12, unsigned char r13, unsigned char* reg6)
+{
+ unsigned char *outBuffer;
+ unsigned char *tmpBuffer;
+ unsigned char *allocationBuffer;
+ unsigned short minAddr = 0;
+ unsigned char minAddrIsDefined = 0;
+ unsigned short maxAddr;
+
+ unsigned char nbPixPerByte;
+ int y,x;
+
+ switch(mode)
+ {
+ case 0:
+ {
+ *r1 = (width+3)/4;
+ nbPixPerByte = 2;
+ ptrMode = mode0interlace;
+ break;
+ }
+ case 1:
+ {
+ *r1 = (width+7)/8;
+ nbPixPerByte = 4;
+ ptrMode = mode1interlace;
+ break;
+ }
+ case 2:
+ {
+ *r1 = (width+15)/16;
+ nbPixPerByte = 8;
+ ptrMode = mode2interlace;
+ break;
+ }
+ case 3:
+ {
+ *r1 = (width+3)/4;
+ nbPixPerByte = 2;
+ ptrMode = mode3interlace;
+ break;
+ }
+ default:
+ {
+ exit(4);
+ }
+ }
+
+ tmpBuffer = (unsigned char*)malloc(0xFFFF);
+ if (tmpBuffer == NULL)
+ {
+ printf("Allocation tmpBuffer raté\n");
+ exit(4);
+ }
+
+ allocationBuffer = (unsigned char*)calloc(0xFFFF, 1);
+ if(allocationBuffer == NULL)
+ {
+ printf("Allocation allocationBuffer raté\n");
+ exit(4);
+ }
+
+ {
+ unsigned char r6;
+ unsigned char vcc,rcc,hcc,cclk;
+ r6 = (height+r9)/(r9+1);
+ *reg6 = r6;
+
+ for(vcc = 0; vcc < r6; vcc++)
+ {
+ for(rcc = 0; rcc < (r9+1); rcc++)
+ {
+ for(hcc = 0; hcc < *r1; hcc++)
+ {
+ for(cclk = 0; cclk < 2; cclk++)
+ {
+ x = (hcc << 1 | cclk);
+ y = vcc*(r9+1) + rcc;
+ *(tmpBuffer + addrCalc(vcc, rcc, hcc, cclk, *r1, r12, r13)) = (*ptrMode)(input + y*width + x*nbPixPerByte);
+ *(allocationBuffer + addrCalc(vcc, rcc, hcc, cclk, *r1, r12, r13)) += 1;
+ }
+ }
+ }
+ }
+ }
+
+ {
+ unsigned short i;
+ for(i = 0; i < 0xFFFF; i++)
+ {
+ if(*(allocationBuffer + i) > 1)
+ {
+ printf("Attention : Ecriture multiple a l'adresse mémoire %d\n",i);
+ }
+ if(*(allocationBuffer + i) > 0)
+ {
+ maxAddr = i;
+ }
+ if((*(allocationBuffer + i) == 1) && (minAddrIsDefined == 0))
+ {
+ minAddr = i;
+ minAddrIsDefined = 1;
+ }
+ }
+ }
+
+ *outSize = (maxAddr + 1) - minAddr;
+
+ outBuffer = (unsigned char*)malloc((*outSize));
+ if (outBuffer == NULL)
+ {
+ printf("Allocation outBuffer raté\n");
+ exit(4);
+ }
+
+ {
+ unsigned char *ptrTmp;
+ unsigned char *ptrOut;
+ unsigned short i;
+ ptrTmp = tmpBuffer + minAddr;
+ ptrOut = outBuffer;
+
+ for(i = minAddr; i <= maxAddr; i++)
+ {
+ *(ptrOut++) = *(ptrTmp++);
+ }
+ }
+ free(tmpBuffer);
+ tmpBuffer = NULL;
+ free(allocationBuffer);
+ allocationBuffer = NULL;
+
+ return outBuffer;
+}
diff --git a/tools/gfx2crtc/libraw2crtc.h b/tools/gfx2crtc/libraw2crtc.h
new file mode 100644
index 0000000..8bab0e5
--- /dev/null
+++ b/tools/gfx2crtc/libraw2crtc.h
@@ -0,0 +1,12 @@
+/* GFX2CRTC - libraw2crtc.h
+ * CloudStrife - 20080921
+ * Diffusé sous licence libre CeCILL v2
+ * Voire LICENCE
+ */
+
+#ifndef LIBRAW2CRTC_H
+#define LIBRAW2CRTC_H 1
+
+unsigned char * raw2crtc(unsigned char *input, unsigned short width, unsigned short height, unsigned char mode, unsigned char r9, unsigned long *outSize, unsigned char *r1, unsigned char r12, unsigned char r13, unsigned char* reg6);
+
+#endif
diff --git a/tools/gfx2crtc/makefile b/tools/gfx2crtc/makefile
new file mode 100644
index 0000000..8e4b2e2
--- /dev/null
+++ b/tools/gfx2crtc/makefile
@@ -0,0 +1,29 @@
+ALL= raw2crtc png2crtc
+
+
+CC=gcc
+
+# Detect gcc2, if we're running it, use gnu9x standard instead of c99...
+GCC_MAJOR = $(shell $(CC) -v 2>&1 |grep version |cut -d' ' -f3 |cut -d'.' -f1)
+
+ifeq ($(GCC_MAJOR),2)
+ CCFLAGS=-Os -W -Wall -std=gnu9x -g
+else
+ CCFLAGS=-Os -W -Wall -std=c99 -g
+endif
+
+#CCFLAGS=-O3 -W -Wall -pedantic -ansi
+
+all: $(ALL)
+
+clean :
+ rm -f a.out *.o core $(ALL)
+
+raw2crtc : raw2crtc.o libraw2crtc.o
+ $(CC) $(CCFLAGS) raw2crtc.o libraw2crtc.o -o raw2crtc
+
+png2crtc : png2crtc.o libraw2crtc.o
+ $(CC) $(CCFLAGS) png2crtc.o libraw2crtc.o -o png2crtc -lpng -lz
+
+.c.o :
+ $(CC) $(CCFLAGS) -c $<
diff --git a/tools/gfx2crtc/png2crtc.c b/tools/gfx2crtc/png2crtc.c
new file mode 100644
index 0000000..9742960
--- /dev/null
+++ b/tools/gfx2crtc/png2crtc.c
@@ -0,0 +1,204 @@
+/* GFX2CRTC - png2crtc.c
+ * CloudStrife - 20080921
+ * Diffusé sous licence libre CeCILL v2
+ * Voire LICENCE
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <png.h>
+#include "libraw2crtc.h"
+
+#define ERROR 1
+
+int main(int argc, char **argv)
+{
+ FILE *inFile, *outFile;
+ unsigned char *inBuffer, *outBuffer;
+ unsigned long outSize;
+
+ unsigned char r1, r6, r9, r12, r13;
+ png_uint_32 width;
+ png_uint_32 height;
+ int bitdepth;
+ int colorType;
+ unsigned char mode;
+ unsigned char forcemode = 0;
+ unsigned char forcer12 = 0, forcer13 = 0;
+
+ unsigned char header[8];
+ unsigned char is_png;
+
+ unsigned int y;
+ png_structp png_ptr;
+ png_infop info_ptr;
+ png_infop end_info;
+
+ png_bytep * ptrRow;
+
+ // We have to use this temporary variable insted of scanning directly into
+ // 8 bit integers using %hhu because mingW, relying on MSVCRT, is not C99
+ // compliant and can't handle this "modern" stuff.
+ unsigned int stupid_mingw_isnt_c99;
+
+ if((argc != 3) && (argc != 4) && (argc != 5) && (argc != 6) && (argc != 7))
+ {
+ printf("Utilisation : %s input_filename output_filename [registre9] [mode] "
+ "[r12] [r13]\n",argv[0]);
+ exit(0);
+ }
+
+ inFile = fopen(argv[1],"rb");
+
+ if(argc >= 4)
+ /*{sscanf(argv[3],"%hhu",&r9);}*/
+ {sscanf(argv[3],"%u",&stupid_mingw_isnt_c99); r9=stupid_mingw_isnt_c99;}
+ else
+ {r9 = 7;}
+ if(argc >= 5)
+ {
+ // sscanf(argv[4],"%hhu",&mode);
+ sscanf(argv[4],"%u",&stupid_mingw_isnt_c99); mode = stupid_mingw_isnt_c99;
+ forcemode = 1;
+ if(mode > 3) puts("mode doit être compris entre 0 et 3");
+ mode = mode & 3;
+ }
+
+ // Registre r12 et r13 par défaut :
+ r12 = 0x0C;
+ r13 = 0x00;
+
+ if(argc >= 6)
+ {
+ // sscanf(argv[5],"%hhu",&r12);
+ sscanf(argv[5],"%u",&stupid_mingw_isnt_c99); r12 = stupid_mingw_isnt_c99;
+ forcer12 = 1;
+ }
+ if(argc >= 7)
+ {
+ // sscanf(argv[6],"%hhu",&r13);
+ sscanf(argv[6],"%u",&stupid_mingw_isnt_c99); r13=stupid_mingw_isnt_c99;
+ forcer13 = 1;
+ }
+
+ if (inFile == NULL)
+ {
+ printf("Fichier Inexistant\n");
+ exit(1);
+ }
+
+ fread(header, 1, 8, inFile);
+ is_png = !png_sig_cmp(header, 0, 8);
+ if (!is_png)
+ {
+ printf("Ce n'est pas un png\n");
+ exit(2);
+ }
+
+ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL,
+ NULL);
+ if (!png_ptr) return (ERROR);
+
+ info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr)
+ {
+ png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
+ return (ERROR);
+ }
+
+ end_info = png_create_info_struct(png_ptr);
+ if (!end_info)
+ {
+ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
+ return (ERROR);
+ }
+
+ if (setjmp(png_jmpbuf(png_ptr)))
+ {
+ png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+ fclose(inFile);
+ return (ERROR);
+ }
+
+ png_init_io(png_ptr, inFile);
+ png_set_sig_bytes(png_ptr, 8);
+
+ png_read_info(png_ptr, info_ptr);
+
+ png_get_IHDR(png_ptr, info_ptr, &width, &height, &bitdepth, &colorType, NULL,
+ NULL, NULL);
+
+ if(!((colorType == PNG_COLOR_TYPE_GRAY)
+ || (colorType == PNG_COLOR_TYPE_PALETTE)))
+ {
+ puts("Ce PNG n'est pas dans un format exploitable "
+ "(niveaux de gris ou palette)");
+ return (ERROR);
+ }
+
+ if(forcemode == 0)
+ {
+ switch(bitdepth)
+ {
+ case 1:
+ {
+ mode = 2;
+ break;
+ }
+ case 2:
+ {
+ mode = 1;
+ break;
+ }
+ case 4:
+ {
+ mode = 0;
+ break;
+ }
+ default:
+ {
+ puts("Ce PNG n'est pas dans un format exploitable"
+ "(bitdepth = 1, 2 ou 4)");
+ return (ERROR);
+ }
+ }
+ }
+
+ png_set_packing(png_ptr); /* Convertir en mode 1 pixel par octets */
+ png_read_update_info(png_ptr, info_ptr);
+
+ inBuffer = (unsigned char*)malloc(width*height);
+ if (inBuffer == NULL)
+ {
+ printf("Allocation inBuffer raté\n");
+ exit(3);
+ }
+
+ ptrRow = (png_bytep*)malloc(sizeof(png_bytep)*height);
+ for(y = 0; y < height; y++)
+ {
+ ptrRow[y] = (inBuffer + width*y);
+ }
+
+ png_read_image(png_ptr, ptrRow);
+
+ outBuffer = raw2crtc(inBuffer, width, height, mode, r9, &outSize, &r1, r12, r13, &r6);
+
+ printf("Taille de l'écran de sortie : %lu\n",outSize);
+ printf("Mode = %d Largeur = %d Hauteur = %d R1 = %d R9 = %d R6 = %d\n",mode,(int)width,(int)height,r1,r9,r6);
+
+ outFile = fopen(argv[2], "wb");
+ fwrite(outBuffer, 1, outSize, outFile);
+ fclose(outFile);
+
+ png_read_end(png_ptr, end_info);
+ png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+
+ free(inBuffer);
+ inBuffer = NULL;
+
+ free(outBuffer);
+ outBuffer = NULL;
+
+ return 0;
+}
diff --git a/tools/gfx2crtc/raw2crtc.c b/tools/gfx2crtc/raw2crtc.c
new file mode 100644
index 0000000..c8738dc
--- /dev/null
+++ b/tools/gfx2crtc/raw2crtc.c
@@ -0,0 +1,86 @@
+/* GFX2CRTC - raw2crtc.c
+ * CloudStrife - 20080921
+ * Diffusé sous licence libre CeCILL v2
+ * Voire LICENCE
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "libraw2crtc.h"
+
+int main(int argc, char **argv)
+{
+ FILE *inFile, *outFile;
+ unsigned char *inBuffer, *outBuffer;
+ unsigned long inSize;
+ unsigned long outSize;
+
+ unsigned char r1, r6, r9;
+ unsigned short width;
+ unsigned short height;
+ unsigned char mode;
+
+ if((argc != 6) && (argc != 7))
+ {
+ printf("Utilisation : %s input_filename output_filename width height mode [registre9]\n",argv[0]);
+ printf("Exemple : Convertir une image en 176 sur 224 en mode 0 :\n");
+ printf("%s image.raw image.scr 176 224 0\n",argv[0]);
+ printf("Exemple : Convertir une image en 256 sur 128 en mode 1 avec R9 = 3 :\n");
+ printf("%s image.raw image.scr 256 128 1 3\n",argv[0]);
+ exit(0);
+ }
+
+ inFile = fopen(argv[1],"rb");
+
+ sscanf(argv[3],"%hud",&width);
+ sscanf(argv[4],"%hud",&height);
+ sscanf(argv[5],"%hhud",&mode);
+ if(mode > 3) printf("mode doit être compris entre 0 et 3");
+ mode = mode & 3;
+ if(argc == 7)
+ {sscanf(argv[6],"%hhud",&r9);}
+ else
+ {r9 = 7;}
+
+ if (inFile == NULL)
+ {
+ printf("Fichier Inexistant\n");
+ exit(1);
+ }
+
+ fseek(inFile, 0, SEEK_END);
+ inSize = ftell(inFile);
+ rewind(inFile);
+
+ if (inSize != (unsigned long)(width*height))
+ {
+ printf("Attention ! Mauvaise taille du fichier d'entré\n");
+ }
+
+ inBuffer = (unsigned char*)malloc(inSize);
+ if (inBuffer == NULL)
+ {
+ printf("Allocation inBuffer raté\n");
+ exit(3);
+ }
+
+ fread(inBuffer, 1, inSize, inFile);
+ fclose(inFile);
+
+ outBuffer = raw2crtc(inBuffer, width, height, mode, r9, &outSize, &r1, 0, 0, &r6);
+
+ printf("Taille de l'écran de sortie : %lu\n",outSize);
+ printf("Mode = %d Largeur = %d Hauteur = %d R1 = %d R9 = %d R6 = %d\n",mode,width,height,r1,r9,r6);
+
+ outFile = fopen(argv[2], "wb");
+ fwrite(outBuffer, 1, outSize, outFile);
+ fclose(outFile);
+
+ free(inBuffer);
+ inBuffer = NULL;
+
+ free(outBuffer);
+ outBuffer = NULL;
+
+ return 0;
+}
diff --git a/tools/hex2bin-2.0/Makefile b/tools/hex2bin-2.0/Makefile
new file mode 100755
index 0000000..c8ef10b
--- /dev/null
+++ b/tools/hex2bin-2.0/Makefile
@@ -0,0 +1,42 @@
+# Makefile hex2bin/mot2bin
+SRCDIR = src
+BINDIR = bin
+OBJDIR = obj
+TGTDIR = $(BINDIR)
+B_SRCFILES= $(foreach F, hex2bin.c common.c libcrc.c binary.c, $(SRCDIR)/$(F))
+B_OBJFILES= $(foreach F, hex2bin.o common.o libcrc.o binary.o, $(OBJDIR)/$(F))
+M_SRCFILES= $(foreach F, mot2bin.c common.c libcrc.c binary.c, $(SRCDIR)/$(F))
+M_OBJFILES= $(foreach F, mot2bin.o common.o libcrc.o binary.o, $(OBJDIR)/$(F))
+
+# For generating documentation (hex2bin.1, select the second line)
+# -- You will require pod2man installed for this to work
+TGT_FILES = $(foreach F, hex2bin mot2bin, $(TGTDIR)/$(F))
+#TGT_FILES = $(foreach F, hex2bin mot2bin hex2bin.1, $(TGTDIR)/$(F))
+
+CPFLAGS = -std=gnu99 -O3 -fsigned-char -Wall -pedantic
+# Compile
+all: objectdir $(TGT_FILES)
+
+$(OBJDIR)/%.o: $(SRCDIR)/%.c
+ gcc -c $(CPFLAGS) $< -o $@
+
+objectdir:
+ @echo "Creating directory $(OBJDIR)..."
+ mkdir -p $(OBJDIR)
+
+$(TGTDIR)/hex2bin.1: $(SRCDIR)/hex2bin.pod
+ pod2man $(SRCDIR)/hex2bin.pod > $(TGTDIR)/hex2bin.1
+
+$(TGTDIR)/hex2bin: $(B_OBJFILES)
+ gcc $(CPFLAGS) -o $(TGTDIR)/hex2bin $(B_OBJFILES)
+
+$(TGTDIR)/mot2bin: $(M_OBJFILES)
+ gcc $(CPFLAGS) -o $(TGTDIR)/mot2bin $(M_OBJFILES)
+
+clean:
+ @echo "Removing objects directory $(OBJDIR)/ ..."
+ @rm -rf $(OBJDIR)
+
+cleanall: clean
+ @echo "Removing binary files in $(BINDIR)/ ..."
+ @rm -f $(BINDIR)/*
diff --git a/tools/hex2bin-2.0/bin/.deleteme b/tools/hex2bin-2.0/bin/.deleteme
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tools/hex2bin-2.0/bin/.deleteme
diff --git a/tools/hex2bin-2.0/bin/hex2bin b/tools/hex2bin-2.0/bin/hex2bin
new file mode 100755
index 0000000..c6967d7
--- /dev/null
+++ b/tools/hex2bin-2.0/bin/hex2bin
Binary files differ
diff --git a/tools/hex2bin-2.0/bin/mot2bin b/tools/hex2bin-2.0/bin/mot2bin
new file mode 100755
index 0000000..18400f4
--- /dev/null
+++ b/tools/hex2bin-2.0/bin/mot2bin
Binary files differ
diff --git a/tools/hex2bin-2.0/doc/CRC list.txt b/tools/hex2bin-2.0/doc/CRC list.txt
new file mode 100644
index 0000000..8549799
--- /dev/null
+++ b/tools/hex2bin-2.0/doc/CRC list.txt
@@ -0,0 +1,542 @@
+http://regregex.bbcmicro.net/crc-catalogue.htm
+
+CRC-8
+07
+<crc-8-atm>
+ Name : "CRC-8"
+ Width : 8
+ Poly : 07
+ Init : 00
+ RefIn : False
+ RefOut : False
+ XorOut : 00
+ Check : F4
+
+<crc-8-itu>
+ Name : "CRC-8/ITU"
+ Width : 8
+ Poly : 07
+ Init : 00
+ RefIn : False
+ RefOut : False
+ XorOut : 55
+ Check : A1
+
+<crc-8-rohc>
+ Name : "CRC-8/ROHC"
+ Width : 8
+ Poly : 07
+ Init : FF
+ RefIn : True
+ RefOut : True
+ XorOut : 0
+ Check : D0
+
+39
+<crc-8-darc>
+ Name : "CRC-8/DARC"
+ Width : 8
+ Poly : 39
+ Init : 00
+ RefIn : True
+ RefOut : True
+ XorOut : 00
+ Check : 15
+
+1D
+<crc-8-icode>
+ Name : "CRC-8/I-CODE"
+ Width : 8
+ Poly : 1D
+ Init : FD
+ RefIn : False
+ RefOut : False
+ XorOut : 00
+ Check : 7E
+
+<crc-8-j1850>
+ Name : "CRC-8/J1850" (new entry)
+ Width : 8
+ Poly : 1D
+ Init : FF
+ RefIn : False
+ RefOut : False
+ XorOut : FF
+ Check : 4B
+
+31
+<crc-8-maxim>
+ Name : "CRC-8/MAXIM"
+ Alias : "DOW-CRC"
+ Width : 8
+ Poly : 31
+ Init : 00
+ RefIn : True
+ RefOut : True
+ XorOut : 00
+ Check : A1
+
+9B
+<crc-8-wcdma>
+ Name : "CRC-8/WCDMA"
+ Width : 8
+ Poly : 9B
+ Init : 00
+ RefIn : True
+ RefOut : True
+ XorOut : 00
+ Check : 25
+
+8D
+<crc-8-ccitt>
+ Name : "CRC-8/CCITT" (new entry) 1-Wire?
+ Width : 8
+ Poly : 8D
+ Init : 00?
+ RefIn : False?
+ RefOut : False?
+ XorOut : 00?
+ Check : D2
+
+D5
+<crc-8>
+ Name : "CRC-8" (new entry)
+ Width : 8
+ Poly : D5
+ Init : 00?
+ RefIn : False?
+ RefOut : False?
+ XorOut : 00?
+ Check : BC
+
+CRC-16
+8005
+<crc-16>
+ Name : "ARC"
+ Alias : "CRC-16"
+ Alias : "CRC-IBM"
+ Alias : "CRC-16/ARC"
+ Alias : "CRC-16/LHA"
+ Width : 16
+ Poly : 8005
+ Init : 0000
+ RefIn : True
+ RefOut : True
+ XorOut : 0000
+ Check : BB3D
+
+<crc-16-buypass>
+ Name : "CRC-16/BUYPASS"
+ Alias : "CRC-16/VERIFONE"
+ Width : 16
+ Poly : 8005
+ Init : 0000
+ RefIn : False
+ RefOut : False
+ XorOut : 0000
+ Check : FEE8
+
+<crc-dds-110>
+ Name : "CRC-16/DDS-110"
+ Width : 16
+ Poly : 8005
+ Init : 800D
+ RefIn : False
+ RefOut : False
+ XorOut : 0000
+ Check : 9ECF
+ XCheck : CFE9
+
+<crc-16-maxim>
+ Name : "CRC-16/MAXIM"
+ Width : 16
+ Poly : 8005
+ Init : 0000
+ RefIn : True
+ RefOut : True
+ XorOut : FFFF
+ Check : 44C2
+
+<crc-usb>
+ Name : "CRC-16/USB"
+ Width : 16
+ Poly : 8005
+ Init : FFFF
+ RefIn : True
+ RefOut : True
+ XorOut : FFFF
+ Check : B4C8
+
+<crc-modbus>
+ Name : "MODBUS"
+ Width : 16
+ Poly : 8005
+ Init : FFFF
+ RefIn : True
+ RefOut : True
+ XorOut : 0000
+ Check : 4B37
+
+1021
+<crc-ccitt-1d0f>
+ Name : "CRC-16/AUG-CCITT"
+ Alias : "CRC-16/SPI-FUJITSU"
+ Width : 16
+ Poly : 1021
+ Init : 1D0F
+ RefIn : False
+ RefOut : False
+ XorOut : 0000
+ Check : E5CC
+
+<crc-ccitt-ffff>
+ Name : "CRC-16/CCITT-FALSE"
+ Width : 16
+ Poly : 1021
+ Init : FFFF
+ RefIn : False
+ RefOut : False
+ XorOut : 0000
+ Check : 29B1
+
+<crc-genibus>
+ Name : "CRC-16/GENIBUS"
+ Alias : "CRC-16/I-CODE"
+ Alias : "CRC-16/DARC"
+ Width : 16
+ Poly : 1021
+ Init : FFFF
+ RefIn : False
+ RefOut : False
+ XorOut : FFFF
+ Check : D64E
+
+<crc-ccitt-xmodem>
+ Name : "XMODEM"
+ Alias : "ZMODEM"
+ Alias : "CRC-16/ACORN"
+ Width : 16
+ Poly : 1021
+ Init : 0000
+ RefIn : False
+ RefOut : False
+ XorOut : 0000
+ Check : 31C3
+
+<crc-mcrf4xx>
+ Name : "CRC-16/MCRF4XX"
+ Width : 16
+ Poly : 1021
+ Init : FFFF
+ RefIn : True
+ RefOut : True
+ XorOut : 0000
+ Check : 6F91
+
+<crc-riello>
+ Name : "CRC-16/RIELLO"
+ Width : 16
+ Poly : 1021
+ Init : B2AA
+ RefIn : True
+ RefOut : True
+ XorOut : 0000
+ Check : 63D0
+
+ <crc-ccitt-kermit>
+ Name : "KERMIT"
+ Alias : "CRC-16/CCITT"
+ Alias : "CRC-16/CCITT-TRUE"
+ Alias : "CRC-CCITT"
+ Width : 16
+ Poly : 1021
+ Init : 0000
+ RefIn : True
+ RefOut : True
+ XorOut : 0000
+ Check : 2189
+ XCheck : 8921
+
+<crc-x25>
+ Name : "X-25"
+ Alias : "CRC-16/IBM-SDLC"
+ Alias : "CRC-16/ISO-HDLC"
+ Width : 16
+ Poly : 1021
+ Init : FFFF
+ RefIn : True
+ RefOut : True
+ XorOut : FFFF
+ Check : 906E
+ XCheck : 6E90
+
+0589
+<crc-dect-r>
+ Name : "CRC-16/DECT-R"
+ Alias : "R-CRC-16"
+ Width : 16
+ Poly : 0589
+ Init : 0000
+ RefIn : False
+ RefOut : False
+ XorOut : 0001
+ Check : 007E
+
+<crc-dect-x>
+ Name : "CRC-16/DECT-X"
+ Alias : "X-CRC-16"
+ Width : 16
+ Poly : 0589
+ Init : 0000
+ RefIn : False
+ RefOut : False
+ XorOut : 0000
+ Check : 007F
+
+3D65
+<crc-dnp>
+ Name : "CRC-16/DNP"
+ Width : 16
+ Poly : 3D65
+ Init : 0000
+ RefIn : True
+ RefOut : True
+ XorOut : FFFF
+ Check : EA82
+ XCheck : 82EA
+
+<crc-en-13757>
+ Name : "CRC-16/EN-13757"
+ Width : 16
+ Poly : 3D65
+ Init : 0000
+ RefIn : False
+ RefOut : False
+ XorOut : FFFF
+ Check : C2B7
+
+8BB7
+<crc-t10-dif>
+ Name : "CRC-16/T10-DIF"
+ Width : 16
+ Poly : 8BB7
+ Init : 0000
+ RefIn : False
+ RefOut : False
+ XorOut : 0000
+ Check : D0DB
+
+A097
+<crc-teledisk>
+ Name : "CRC-16/TELEDISK"
+ Width : 16
+ Poly : A097
+ Init : 0000
+ RefIn : False
+ RefOut : False
+ XorOut : 0000
+ Check : 0FB3
+
+CRC-24
+864CFB
+<crc-24>
+ Name : "CRC-24"
+ Alias : "CRC-24/OPENPGP"
+ Width : 24
+ Poly : 864CFB
+ Init : B704CE
+ RefIn : False
+ RefOut : False
+ XorOut : 000000
+ Check : 21CF02
+
+5D6DCB
+<crc-24-flexray-a>
+ Name : "CRC-24/FLEXRAY-A"
+ Width : 24
+ Poly : 5D6DCB
+ Init : FEDCBA
+ RefIn : False
+ RefOut : False
+ XorOut : 000000
+ Check : 7979BD
+
+<crc-24-flexray-b>
+ Name : "CRC-24/FLEXRAY-B"
+ Width : 24
+ Poly : 5D6DCB
+ Init : ABCDEF
+ RefIn : False
+ RefOut : False
+ XorOut : 000000
+ Check : 1F23B8
+
+CRC-32
+04C11DB7
+<crc-32>
+ Name : "CRC-32"
+ Alias : "CRC-32/ADCCP"
+ Alias : "PKZIP"
+ Width : 32
+ Poly : 04C11DB7
+ Init : FFFFFFFF
+ RefIn : True
+ RefOut : True
+ XorOut : FFFFFFFF
+ Check : CBF43926
+
+<crc-32-bzip2>
+ Name : "CRC-32/BZIP2"
+ Alias : "B-CRC-32"
+ Width : 32
+ Poly : 04C11DB7
+ Init : FFFFFFFF
+ RefIn : False
+ RefOut : False
+ XorOut : FFFFFFFF
+ Check : FC891918
+
+<crc-32-mpeg-2>
+ Name : "CRC-32/MPEG-2"
+ Width : 32
+ Poly : 04C11DB7
+ Init : FFFFFFFF
+ RefIn : False
+ RefOut : False
+ XorOut : 00000000
+ Check : 0376E6E7
+
+<crc-32-posix>
+ Name : "CRC-32/POSIX"
+ Alias : "CKSUM"
+ Width : 32
+ Poly : 04C11DB7
+ Init : 00000000
+ RefIn : False
+ RefOut : False
+ XorOut : FFFFFFFF
+ Check : 765E7680
+ LCheck : 377A6011
+
+<crc-32-jamcrc>
+ Name : "JAMCRC"
+ Width : 32
+ Poly : 04C11DB7
+ Init : FFFFFFFF
+ RefIn : True
+ RefOut : True
+ XorOut : 00000000
+ Check : 340BC6D9
+
+1EDC6F41
+<crc-32-C>
+ Name : "CRC-32C"
+ Alias : "CRC-32/ISCSI"
+ Alias : "CRC-32/CASTAGNOLI"
+ Width : 32
+ Poly : 1EDC6F41
+ Init : FFFFFFFF
+ RefIn : True
+ RefOut : True
+ XorOut : FFFFFFFF
+ Check : E3069283
+
+A833982B
+<crc-32-D>
+ Name : "CRC-32D"
+ Width : 32
+ Poly : A833982B
+ Init : FFFFFFFF
+ RefIn : True
+ RefOut : True
+ XorOut : FFFFFFFF
+ Check : 87315576
+
+741B8CD7
+<crc-32-K> (new entry)
+ Name : "CRC-32K"
+ Alias : "CRC-32/KOOPMAN"
+ Width : 32
+ Poly : 741B8CD7
+ Init : 00000000?
+ RefIn : False?
+ RefOut : False?
+ XorOut : 00000000?
+ Check : 085A3197 ?
+
+814141AB
+<crc-32-Q>
+ Name : "CRC-32Q"
+ Width : 32
+ Poly : 814141AB
+ Init : 00000000
+ RefIn : False
+ RefOut : False
+ XorOut : 00000000
+ Check : 3010BF7F
+
+000000AF
+<crc-32-xfer>
+ Name : "XFER"
+ Width : 32
+ Poly : 000000AF
+ Init : 00000000
+ RefIn : False
+ RefOut : False
+ XorOut : 00000000
+ Check : BD0BE338
+
+CRC-40
+<crc-40-gsm>
+ Name : "CRC-40/GSM"
+ Width : 40
+ Poly : 0004820009
+ Init : 0000000000
+ RefIn : False
+ RefOut : False
+ XorOut : 0000000000
+ Check : 2BE9B039B9
+
+CRC-64
+42F0E1EBA9EA3693
+<crc-64>
+ Name : "CRC-64"
+ Width : 64
+ Poly : 42F0E1EBA9EA3693
+ Init : 0000000000000000
+ RefIn : False
+ RefOut : False
+ XorOut : 0000000000000000
+ Check : 6C40DF5F0B497347
+
+<crc-64-we>
+ Name : "CRC-64/WE"
+ Width : 64
+ Poly : 42F0E1EBA9EA3693
+ Init : FFFFFFFFFFFFFFFF
+ RefIn : False
+ RefOut : False
+ XorOut : FFFFFFFFFFFFFFFF
+ Check : 62EC59E3F1A4F00A
+
+000000000000001B
+<crc-64-1b>
+ Name : "CRC-64/1B" (New entry)
+ Width : 64
+ Poly : 000000000000001B
+ Init : 0000000000000000
+ RefIn : True
+ RefOut : True
+ XorOut : 0000000000000000
+ Check : 46A5A9388A5BEFFE
+
+AD93D23594C935A9
+<crc-64-jones>
+ Name : "CRC-64/Jones" (New entry)
+ Width : 64
+ Poly : AD93D23594C935A9
+ Init : FFFFFFFFFFFFFFFF
+ RefIn : True
+ RefOut : True
+ XorOut : 0000000000000000
+ Check : CAA717168609F281
diff --git a/tools/hex2bin-2.0/doc/ChangeLog_hex2bin b/tools/hex2bin-2.0/doc/ChangeLog_hex2bin
new file mode 100644
index 0000000..3339250
--- /dev/null
+++ b/tools/hex2bin-2.0/doc/ChangeLog_hex2bin
@@ -0,0 +1,57 @@
+(UTF8 encoding)
+
+- hex2bin 1.0.12 - 20141122 Simone Fratini
+ small feature added
+ 20141121 Slucx
+ added line for removing extra CR when entering file name at run time.
+ 20141008 JP
+ removed junk code
+
+- hex2bin 1.0.11 - 20141005 Jacques Pelletier
+ added option to support byte-swapped hex used by Microchip's MPLAB IDE
+ corrected bug caused by extra LF at end or within file
+
+- hex2bin 1.0.10 - 20120509 Yoshimasa Nakane
+ modified error checking (also for output file, JP)
+ modified option parser (JP)
+
+- hex2bin 1.0.9 - 20120125 - Danny Schneider
+ Added code for filling a binary file to a given Max_Length relative to
+ Starting Address if Max-Address is larger than Highest-Address
+
+- hex2bin 1.0.8 - 20100402 - Jacques Pelletier
+ Fixed a bug with physical address calculation with extended linear address records
+ ADDRESS_MASK is now calculated from MEMORY_SIZE
+
+- hex2bin 1.0.7 - 20091212 - Jacques Pelletier
+ Fixed the crash on 0 byte length data records
+
+- hex2bin 1.0.6 - 20080103 - Jacques Pelletier
+ Fixed a bug when generating binary files near the end of the buffer
+
+- hex2bin 1.0.5 - 20071005 - Paweł Grabski -
+ Improved parsing of options.
+
+- hex2bin 1.0.4 - 20050126 - Jacques Pelletier -
+ Corrected the conversion LF -> CR+LF bug
+ applied patch for correcting the incorrect handling of
+ extended segment address record
+ added the Rockwell checksum extensions, and modified them a bit to allow
+ other types later.
+
+- hex2bin 1.0.3 - 20040617 - Alf Lacis -
+ Added pad byte (may not always want FF).
+ Added 'break;' to remove GNU compiler warning about label at
+ end of compound statement
+ Added PROGRAM & VERSION strings.
+
+- hex2bin 1.0.2 -
+ Corrected Bug in checksum verification
+
+- hex2bin 1.0.1 -
+ Added checking for memory indexing out of bound.
+ Added segmented and linear extended addressing in hex2bin.
+ Corrected an error: & were interverted with && (and bitwise, logical and).
+
+- hex2bin 1.0.0 -
+ Initial release
diff --git a/tools/hex2bin-2.0/doc/ChangeLog_mot2bin b/tools/hex2bin-2.0/doc/ChangeLog_mot2bin
new file mode 100644
index 0000000..4e3c7b3
--- /dev/null
+++ b/tools/hex2bin-2.0/doc/ChangeLog_mot2bin
@@ -0,0 +1,49 @@
+(UTF8 encoding tab = 4)
+- mot2bin 1.0.12 - 20141122 Simone Fratini
+ small feature added
+ 20141121 Slucx
+ added line for removing extra CR when entering file name at run time.
+
+- mot2bin 1.0.11 - 20141005 Jacques Pelletier
+ added option to support byte-swapped hex used by Microchip's MPLAB IDE
+ corrected bug caused by extra LF at end or within file
+
+- mot2bin 1.0.10 - 20120509 Yoshimasa Nakane
+ modified error checking (also for output file, JP)
+
+- mot2bin 1.0.9 - 20120125 - Danny Schneider
+ Added code for filling a binary file to a given Max_Length relative to
+ Starting Address if Max-Address is larger than Highest-Address
+ (JP) corrected a bug in the checksum checking
+ (JP) added code for record types 0,5,7,8,9
+
+- mot2bin 1.0.8 - 20100402 - Jacques Pelletier
+ ADDRESS_MASK is now calculated from MEMORY_SIZE
+
+- mot2bin 1.0.7 - 20091212 - Jacques Pelletier
+ Fixed the crash on 0 byte length data records
+
+- mot2bin 1.0.6 - 20080103 - Jacques Pelletier
+ Corrected a bug when generating a binary file near the end of the buffer.
+
+- mot2bin 1.0.5 - 20071005 - Paweł Grabski -
+ Improved parsing of options (same code as hex2bin).
+
+- mot2bin 1.0.4 - 20050128 - Jacques Pelletier -
+ Modified the checksum code to be able to generate other checksum types
+ later (ex. CRC).
+
+- mot2bin 1.0.3 - 20041026 - Scott A. Mintz -
+ Modified the MOT2BIN file to compute a checksum over a range using
+ 8bit, 16bit little endian, or 16bit big endian and optionally forcing
+ the checksum to a specific value by modifying a memory location.
+
+- mot2bin 1.0.2 - 20040617 - Alf Lacis -
+ Added pad byte (may not always want FF).
+ Added initialisation to Checksum to remove GNU
+ compiler warning about possible uninitialised usage
+ Added 2x'break;' to remove GNU compiler warning about label at
+ end of compound statement
+ Added PROGRAM & VERSION strings.
+
+- no previous ChangeLog -
diff --git a/tools/hex2bin-2.0/doc/README b/tools/hex2bin-2.0/doc/README
new file mode 100644
index 0000000..78ee7e7
--- /dev/null
+++ b/tools/hex2bin-2.0/doc/README
@@ -0,0 +1,225 @@
+Yet Another Hex to bin converter
+
+It can handle the extended Intel hex format in segmented and linear address
+modes. Records need not be sorted and there can be gaps between records.
+
+Some hex files are produced by compilers. They generate objects files for each
+module in a project, and when the linker generates the final hex file, the
+object files are stored within the hex files, but modules can appear not
+necessary in order of address.
+
+How does it work?
+
+Hex2bin/mot2bin allocates a 4 MBytes buffer and just place the converted bytes
+in its buffer. At the end, the buffer is written to disk. Using a buffer elimi-
+nates the need to sort records. If the option l is used (3), the buffer will be
+allocated with the maximum size specified if over 4Mbytes.
+
+Before reading the hex file, the buffer is filled with a default value. These
+padding bytes are all FF by default so an EPROM programmer can skip these bytes
+when programming. The padding value can be changed with the -p option.
+
+1. Compiling on Linux or other unix platforms
+
+ make
+
+ then
+
+ make install
+
+ This will install the program to /usr/local/bin.
+
+1a. Compiling for Windows on Msys, Cygwin or DOS prompt
+
+ The programs can be compiled as follows:
+ gcc -O2 -Wall -o hex2bin.exe hex2bin.c common.c libcrc.c binary.c
+ gcc -O2 -Wall -o mot2bin.exe mot2bin.c common.c libcrc.c binary.c
+
+2. Using hex2bin
+
+ hex2bin example.hex
+
+ hex2bin will generate a binary file example.bin starting at the
+ lowest address in the hex file.
+
+3. Binary file starting address and length
+
+ If the lowest address isn't 0000,
+ ex: 0100: (the first record begins with :nn010000xxx )
+
+ there will be problems when using the binary file to program a EPROM
+ since the first byte supposed to be at 0100 is stored in the binary file
+ at 0000.
+
+ you can specify a starting address for the binary file on the command line:
+
+ hex2bin -s 0000 start_at_0100.hex
+
+ This start address is not the same thing as the start address record in
+ the hex file. The start address record is used to specify the starting
+ address for execution of the binary code.
+
+ The bytes will be stored in the binary file with a padding from 0000
+ to the lowest address minus 1 (00FF in this case).
+
+ Similarly, the binary file can be padded up to Length -1 with FF or another byte.
+
+ Here, the space between the last byte and 07FF will be filled with FF.
+ hex2bin -l 0800 ends_before_07FF.hex
+
+ EPROM, EEPROM and Flash memories contain all FF when erased.
+
+ This program does minimal error checking since many hex files are
+ generated by known good assemblers.
+
+ When the source file name is
+ for-example.test.hex
+ the binary created will have the name
+ for-example.bin
+ the ".test" part will be dropped.
+
+ Hex2bin/mot2bin assume the source file doesn't contain overlapping records,
+ if so, overlaps will be reported.
+
+4. Checksum of source file
+
+ By default, it ignores record checksum errors, so that someone can change
+ by hand some bytes allowing quick and dirty changes.
+ If you want checksum error reporting, specify the option -c.
+
+ hex2bin -c example.hex
+
+ If there is a record checksum error somewhere, the program will continue the
+ conversion anyway.
+
+ The example file example.hex contains some records with checksum errors.
+
+5. Check value inserted inside binary file
+
+ A check value can be inserted in the resulting binary file.
+
+ hex2bin -k [0-4] -r [start] [end] -f [address] -C [Poly] [Init] [RefIn] [RefOut] [XorOut]
+
+ -k Select the check method:
+ 0: Checksum 8-bit
+ 1: Checksum 16-bit
+ 2: CRC8
+ 3: CRC16
+ 4: CRC32
+
+ -r Range to compute checksum over (default is min and max addresses)
+
+ -f Address of the result to write
+
+ -C Parameters for CRC
+ Parameters for common CRCs are listed in doc/CRC list.txt. They appear in
+ the same order. Feed them as is and use t for TRUE, f for FALSE.
+
+ See also the test/Makefile for these common CRCs; since they're tested,
+ you'll have the command line figured out.
+
+ -E Endian for storing the check result or forcing it
+ 0: little
+ 1: big
+
+ Change from previous versions of hex2bin/mot2bin:
+ Replace former options to this version
+ -k 1 -> -k 1 -E 0
+ -k 2 -> -k 1 -E 1
+
+6. Value inserted directly inside binary file
+ Instead of calculating a value, it can be inserted directly into the file at a specified address.
+
+ hex2bin -k [0|1|2] -F [address] [value]
+
+ -k Select the value format:
+
+ 0 = 8-bit
+ 1 = 16-bit
+ 2 = 32-bit
+
+ -F Address and value of checksum to force
+
+ -E Endian for storing the check result or forcing it
+ 0: little
+ 1: big
+
+7. Motorola S files
+
+ mot2bin example.s19
+
+ Options for mot2bin are the same as hex2bin. Executing the program
+ without argument will display available options. Some are specific to
+ Motorola files.
+
+ This program will handle S19 files generated for Motorola micropro-
+ cessors. Since I use this program for an EPROM programmer, I will
+ rarely need to have more than 4M, I limited the source program for
+ 24 bits or 16 bits address records.
+
+ 32 bits records are now supported, but obviously I can't allocate all
+ the memory for the binary target. What I did is simply assume that the
+ binary file will occupy less than 4M. For binary files greater than 4M,
+ see length option (section 3).
+
+8. Support for byte-swapped hex/S19 files
+
+ -w Wordwise swap: for each pair of bytes, exchange the low and high part.
+ If a checksum needs to be generated to insert in the binary file, select
+ one of the 16-bit checksums.
+
+ hex2bin -w test-byte-swap.hex
+
+9. Goodies
+
+ Description of the file formats is included.
+ Added examples files for extended addressing.
+
+ Check for overlapping records. The check is rather basic: supposing
+ that the buffer is filled with pad bytes, when a record overlaps a
+ previous one, value in the buffer will be different from the pad bytes.
+ This will not detect the case when the previous value equals the pad byte,
+ but it's more likely that more than one byte will be overlapped.
+
+
+10. Error messages
+
+ "Can't allocate memory."
+
+ Can't do anything in this case, so the program simply exits.
+
+ "Error occurred while reading from file"
+
+ Problem with fgets.
+
+ "Input/Output file %s cannot be opened. Enter new filename: "
+
+ The user may not have permissions to open the file.
+
+ "0 byte length data record ignored"
+
+ This means that an empty data record was read. Since it's empty, it's simply
+ ignored and should have no impact on the binary file.
+
+ "Data record skipped at ..."
+
+ This means that the records are falling outside the memory buffer.
+
+ "Overlapped record detected"
+
+ A record is overwritten by a subsequent record. If you're using SDCC, check
+ if more than one area is specified with a starting address. Checking the map
+ file generated by the linker can help.
+
+ "Some error occurred when parsing options."
+
+
+
+11. History
+
+ See ChangeLog
+
+12. Other hex tool
+
+ There is a program that supports more formats and has more features.
+ See SRecord at http://srecord.sourceforge.net/
diff --git a/tools/hex2bin-2.0/doc/S-record.txt b/tools/hex2bin-2.0/doc/S-record.txt
new file mode 100644
index 0000000..ba4abc1
--- /dev/null
+++ b/tools/hex2bin-2.0/doc/S-record.txt
@@ -0,0 +1,361 @@
+S-Record Format
+
+ A file in Motorola S-record format is an ASCII file. There are three different
+ formats:
+
+ S19 for 16-bit address
+ S2 for 24-bit address
+ S3 for 32-bit address
+
+
+ The files consist of optional symbol table information, data specifications
+ for loading memory, and a terminator record.
+
+ [ $$ {module_record}
+ symbol records
+ $$ [ module_record ]
+ symbol_records
+ $$]
+ header_record
+ data_records
+ record_count_record
+ terminator_record
+
+
+Module Record (Optional)
+
+ Each object file contains one record for each module that is a component of it. This
+ record contains the name of the module. There is one module record for each relocatable
+ object created by the assembler. The name of the relocatable object module
+ contained in the record comes from the IDNT directive. For absolute objects created
+ by the linker, there is one module record for each relocatable object file linked,
+ plus an additional record whose name comes from the NAME command for the
+ linker.
+
+ Example:
+
+ $$ MODNAME
+
+
+Symbol Record (Optional)
+
+ As many symbol records as needed can be contained in the object module. Up to 4
+ symbols per line can be used, but it is not mandatory that each line contain 4
+ symbols. A module can contain only symbol records.
+
+ Example:
+
+ APPLE $00000 LABEL1 $ODOC3
+ MEM $OFFFF ZEEK $01947
+
+ The module name associated with the symbols can be specified in the
+ module_record preceding the symbol records.
+
+ Example:
+
+ $$MAIN
+
+ Symbols are assumed to be in the module named in the preceding module_record
+ until another module is specified with another module_record. Symbols defined by
+ the linker's PUBLIC command appear following the first module record, which
+ indicates the name of the output object module specified by the linker's NAME
+ command.
+
+
+*****************************************************************************************
+
+Header Record (SO)
+
+ Each object module has exactly one header record with the following format:
+
+ S00600004844521B
+
+ Description:
+
+ S0 Identifies the record as a header record
+ 06 The number of bytes following this one
+ 0000 The address field, which is ignored
+ 484452 The string HDR in ASCII
+ 1B The checksum
+
+
+
+*****************************************************************************************
+
+Data Record (S1)
+
+ A data record specifies data bytes that are to be loaded into memory. Figure 1
+ shows the format for such a record. The columns shown in the figure represent half
+ of a byte (4 bits).
+
+ ---------------------------------------------
+ | 1 2 3 4 5 6 7 8 9 ... 40 41 42 |
+ | |
+ | S ID byte load data...data checksum |
+ | count address 1 n |
+ ---------------------------------------------
+ Figure 1: Data Record Formatter 16-Bit Load Address
+
+
+ Column Description
+
+ 1 Contains the ASCII character S, which indicates the start of
+ a record in Motorola S-record format.
+
+ 2 Contains the ASCII character identifying the record type.
+ For data records, this character is 1.
+
+ 3 to 4 Contain the count of the number of bytes following this one
+ within the record. The count includes the checksum and the
+ load address bytes but not the byte count itself.
+
+ 5 to 8 Contain the load address. The first data byte is to be loaded
+ into this address and subsequent bytes into the next sequential
+ address. Columns 5 and 6 contain the high-order address
+ byte, and columns 7 and 8 contain the low-order address byte.
+
+ 9 to 40 Contain the specifications for up to 16 bytes of data.
+
+ 41 to 42 Contain a checksum for the record. To calculate this, take the
+ sum of the values of all bytes from the byte count up to the
+ last data byte, inclusive, modulo 256. Subtract this result
+ from 255.
+
+
+*****************************************************************************************
+
+Data Record (S2)
+
+
+ A data record specifies data bytes that are to be loaded into memory. Figure 2
+ shows the format for such a record. The columns shown in the figure represent half
+ of a byte (4 bits).
+
+
+ ----------------------------------------------------
+ | 1 2 3 4 5 6 7 8 9 10 11 ... 42 43 44 |
+ | |
+ | S ID byte load data...data checksum |
+ | count address 1 n |
+ ----------------------------------------------------
+ Figure 2: Data Record Format for 24-Bit Load Address
+
+ Column Description
+
+ 1 Contains the ASCII character S, which indicates the start of
+ a record in Motorola S-record format.
+
+ 2 Contains the ASCII character identifying the record type.
+ For data records, this character is 2.
+
+ 3 to 4 Contain the count of the number of bytes following this one
+ within the record. The count includes the checksum and the
+ load address bytes but not the byte count itself.
+
+ 5 to 10 Contain the load address. The first data byte is to be loaded
+ into this address and subsequent bytes into the next sequential
+ address. Columns 5 and 6 contain the high-order address
+ byte, and columns 9 and 10 contain the low-order address byte.
+
+ 11 to 42 Contain the specifications for up to 16 bytes of data.
+
+ 43 to 44 Contain a checksum for the record. To calculate this, take the
+ sum of the values of all bytes from the byte count up to the
+ last data byte, inclusive, modulo 256. Subtract this result
+ from 255.
+
+
+*****************************************************************************************
+
+Data Record (S3)
+
+
+ A data record specifies data bytes that are to be loaded into memory. Figure 3
+ shows the format for such a record. The columns shown in the figure represent half
+ of a byte (4 bits).
+
+ ----------------------------------------------------------
+ | 1 2 3 4 5 6 7 8 9 10 11 12 13 ... 44 45 46 |
+ | |
+ | S ID byte load data...data checksum |
+ | count address 1 n |
+ ----------------------------------------------------------
+ Figure 3: Data Record Format for 32-Bit Load Address
+
+ Column Description
+
+ 1 Contains the ASCII character S, which indicates the start of
+ a record in Motorola S-record format.
+
+ 2 Contains the ASCII character identifying the record type.
+ For data records, this digit is 3 for 32-bit addresses.
+
+ 3 to 4 Contain the count of the number of bytes following this one
+ within the record. The count includes the checksum and the
+ load address bytes but not the byte count itself.
+
+ 5 to 12 Contain the load address. The first data byte is to be loaded
+ into this address and subsequent bytes into the next sequential
+ address. Columns 5 and 6 contain the high-order address
+ byte, and columns 11 and 12 contain the low-order address byte.
+
+ 13 to 44 Contain the specifications for up to 15 bytes of data.
+
+ 45 to 46 Contain a checksum for the record. To calculate this, take the
+ sum of the values of all bytes from the byte count up to the
+ last data byte, inclusive, modulo 256. Subtract this result
+ from 255.
+
+
+*****************************************************************************************
+
+Record Count Record (S5)
+
+
+ The record count record verifies the number of data records preceding it. Figure 4
+ shows the format for such a record. The columns shown in the figure represent half
+ of a byte (4 bits).
+
+ --------------------------------------
+ | 1 2 3 4 5 6 7 8 9 10 |
+ | |
+ | S ID byte # of data checksum |
+ | count records |
+ --------------------------------------
+ Figure 4: Record Count Record Format
+
+ Column Description
+
+ 1 Contains the ASCII character S, which indicates the start of
+ a record in Motorola S-record format.
+
+ 2 Contains the ASCII character 5, which indicates a record
+ count record.
+
+ 3 to 4 Contain the byte count, ASCII string 03.
+
+ 5 to 8 Contain the number of data records in this file. The high-
+ order byte is in columns 5 and 6.
+
+ 9 to 10 Contain the checksum for the record.
+
+ Example:
+
+ S503010DEE
+
+ The example above shows a record count record indicating a total of 269 records
+ (0x010D) and a checksum of 0xEE.
+
+
+
+*****************************************************************************************
+
+Terminator Record for 32-bit address (S7)
+
+ A terminator record specifies the end of the data records. Figure 5 shows the
+ format for such a record. The columns shown in the figure represent half of a byte
+ (4 bits).
+
+ -------------------------------------
+ | 1 2 3 4 5...12 13 14 |
+ | |
+ | S ID byte load checksum |
+ | count address |
+ -------------------------------------
+ Figure5: Terminator Record Format for 32-Bit Load Address
+
+ Column Description
+
+ 1 Contains the ASCII character S, which indicates the start of
+ a record in Motorola S-record format.
+
+ 2 Contains the ASCII character 7, which indicates a 32-bit
+ load address.
+
+ 3 to 4 Contain the byte count, ASCII string 04.
+
+ 5 to 12 Contain the load address that is either set to zero or to the
+ starting address specified in the END directive or START
+ command (there are no data bytes).
+
+ 13 to 14 Contain the checksum for the record.
+
+*****************************************************************************************
+
+Terminator Record for 24-bit address (S8)
+
+
+ A terminator record specifies the end of the data records. Figure 6 shows the
+ format for such a record. The columns shown in the figure represent half of a byte
+ (4 bits).
+
+ ----------------------------------------
+ | 1 2 3 4 5 6 7 8 9 10 11 12 |
+ | |
+ | S ID byte load checksum |
+ | count address |
+ ----------------------------------------
+ Figure 6: Terminator Record Format for 24-Bit Load Address
+
+ Column Description
+
+ 1 Contains the ASCII character S, which indicates the start of
+ a record in Motorola S-record format.
+
+ 2 Contains the ASCII character 8, which indicates a 24-bit
+ load address.
+
+ 3 to 4 Contain the byte count, ASCII string 04.
+
+ 5 to 10 Contain the load address, which is either set to zero or to the
+ starting address specified in the END directive or START
+ command. There are no data bytes.
+
+ 11 to 12 Contain the checksum for the record.
+
+ Example:
+
+ S804000AF0001
+
+ The previous example shows a terminator record with a 24-bit load address of
+ 0x000AF0 and a checksum of 0x01.
+
+
+*****************************************************************************************
+
+Terminator Record for 16-bit address (S9)
+
+
+ A terminator record specifies the end of the data records. Figure 7 shows the
+ format for such a record. The columns shown in the figure represent half of a byte
+ (4 bits).
+
+ -------------------------------------
+ | 1 2 3 4 5 6 7 8 9 10 |
+ | |
+ | S ID byte load checksum |
+ | count address |
+ -------------------------------------
+ Figure 7: Terminator Record Format for 16-Bit Load Address
+
+
+ Column Description
+
+ 1 Contains the ASCII character S, which indicates the start of
+ a record in Motorola S-record format.
+
+ 2 Contains the ASCII character 9, which indicates a 16-bit
+ load address.
+
+ 3 to 4 Contain the byte count, ASCII string 04.
+
+ 5 to 8 Contain the load address, which is either set to zero or to the
+ starting address specified in the END directive or START
+ command (there are no data bytes).
+
+ 9 to 10 Contain the checksum for the record.
+
+
+
+*****************************************************************************************
+ hagen.v.tronje@on-line.de
diff --git a/tools/hex2bin-2.0/doc/formats.txt b/tools/hex2bin-2.0/doc/formats.txt
new file mode 100644
index 0000000..25e5e37
--- /dev/null
+++ b/tools/hex2bin-2.0/doc/formats.txt
@@ -0,0 +1,72 @@
+Hex formats
+
+Intel
+=====
+
+Hexadecimal values are always in uppercase. Each line is a record.
+The sum of all the bytes in each record should be 00 (modulo 256).
+
+Record types:
+
+00: data records
+01: end-of-file record
+02: extended address record
+
+Data record
+-----------
+
+ :0D011C0000000000C3E0FF0000000000C30F
+
+: 0D 011C 00 00000000C3E0FF0000000000C3 0F
+| | | | -------------+------------ |
+| | | | | +--- Checksum
+| | | | +------------------ Data bytes
+| | | +--------------------------------- Record type
+| | +------------------------------------- Address
+| +----------------------------------------- Number of data bytes
++-------------------------------------------- Start of record
+
+
+End of file record
+------------------
+
+ :00000001FE
+
+: 00 0000 01 FE
+| | | | |
+| | | | +--- Checksum
+| | | +------ Record type
+| | +---------- Address
+| +-------------- Number of data bytes
++----------------- Start of record
+
+
+
+Extended address record
+-----------------------
+
+ :02010002E0001B
+
+: 02 0100 02 E000 1B
+| | | | | |
+| | | | | +--- Checksum
+| | | | +-------- Segment address
+| | | +----------- Record type
+| | +--------------- Address
+| +------------------- Number of data bytes
++---------------------- Start of record
+
+Following data records will start at E000:0100 or E0100
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tools/hex2bin-2.0/doc/intelhex.spc b/tools/hex2bin-2.0/doc/intelhex.spc
new file mode 100644
index 0000000..946d586
--- /dev/null
+++ b/tools/hex2bin-2.0/doc/intelhex.spc
@@ -0,0 +1,409 @@
+
+======================================================================
+
+Intel
+Hexadecimal Object File
+Format Specification
+Revision A, 1/6/88
+
+
+
+DISCLAIMER
+
+Intel makes no representation or warranties with respect to the contents
+hereof and specifically disclaims any implied warranties of
+merchantability or fitness for any particular purpose. Further, Intel
+reserves the right to revise this publication from time to time in the
+content hereof without obligation of Intel to notify any person of such
+revision or changes. The publication of this specification should not
+be construed as a commitment on Intel's part to implement any product.
+
+
+1. Introduction
+This document describes the hexadecimal object file format for the Intel
+8- bit, 16-bit, and 32-bit microprocessors. The hexadecimal format is
+suitable as input to PROM programmers or hardware emulators.
+Hexadecimal object file format is a way of representing an absolute
+binary object file in ASCII. Because the file is in ASCII instead of
+binary, it is possible to store the file is non-binary medium such as
+paper-tape, punch cards, etc.; and the file can also be displayed on CRT
+terminals, line printers, etc.. The 8-bit hexadecimal object file
+format allows for the placement of code and data within the 16-bit
+linear address space of the Intel 8-bit processors. The 16-bit
+hexadecimal format allows for the 20-bit segmented address space of the
+Intel 16-bit processors. And the 32-bit format allows for the 32-bit
+linear address space of the Intel 32-bit processors.
+The hexadecimal representation of binary is coded in ASCII alphanumeric
+characters. For example, the 8-bit binary value 0011-1111 is 3F in
+hexadecimal. To code this in ASCII, one 8-bit byte containing the ASCII
+code for the character '3' (0011-0011 or 033H) and one 8-bit byte
+containing the ASCII code for the character 'F' (0100-0110 or 046H) are
+required. For each byte value, the high-order hexadecimal digit is
+always the first digit of the pair of hexadecimal digits. This
+representation (ASCII hexadecimal) requires twice as ma ny bytes as the
+binary representation.
+A hexadecimal object file is blocked into records, each of which
+contains the record type, length, memory load address and checksum in
+addition to the data. There are currently six (6) different types of
+records that are defined, not all combinations of these records are
+meaningful, however. The records are:
+
+Data Record (8-, 16-, or 32-bit formats)
+End of File Record (8-, 16-, or 32-bit formats)
+Extended Segment Address Record (16- or 32-bit formats)
+Start Segment Address Record (16- or 32-bit formats)
+Extended Linear Address Record (32-bit format only)
+Start Linear Address Record (32-bit format only)
+
+
+2. General Record Format
+| RECORD | LOAD | | | INFO | |
+| MARK | RECLEN | OFFSET | RECTYP | or | CHKSUM |
+| ':' | | | | DATA | |
+ 1-byte 1-byte 2-bytes 1-byte n-bytes 1-byte
+
+Each record begins with a RECORD MARK field containing 03AH, the ASCII
+code for the colon (':') character.
+Each record has a RECLEN field which specifies the number of bytes of
+information or data which follows the RECTYP field of the record. Note
+that one data byte is represented by two ASCII characters. The maximum
+value of the RECLEN field is hexadecimal 'FF' or 255.
+Each record has a LOAD OFFSET field which specifies the 16-bit starting
+load offset of the data bytes, therefore this field is only used for
+Data Records. In other records where this field is not used, it should
+be coded as four ASCII zero characters ('0000' or 030303030H).
+Each record has a RECTYP field which specifies the record type of this
+record. The RECTYP field is used to interpret the remaining information
+within the record. The encoding for all the current record types are:
+
+'00' Data Record
+'01' End of File Record
+'02' Extended Segment Address Record
+'03' Start Segment Address Record
+'04' Extended Linear Address Record
+'05' Start Linear Address Record
+
+Each record has a variable length INFO/DATA field, it consists of zero
+or more bytes encoded as pairs of hexadecimal digits. The
+interpretation of this field depends on the RECTYP field.
+Each record ends with a CHKSUM field that contains the ASCII hexadecimal
+representation of the two's complement of the 8-bit bytes that result
+from converting each pair of ASCII hexadecimal digits to one byte of
+binary, from and including the RECLEN field to and including the last
+byte of the INFO/DATA field. Therefore, the sum of all the ASCII pairs
+in a record after converting to binary, from the RECLEN field to and
+including the CHKSUM field, is zero.
+
+
+3. Extended Linear Address Record (32-bit format only)
+| RECORD | LOAD | | | | |
+| MARK | RECLEN | OFFSET | RECTYP | ULBA | CHKSUM |
+| ':' | '02' | '0000' | '04' | | |
+ 1-byte 1-byte 2-bytes 1-byte 2-bytes 1-byte
+
+The 32-bit Extended Linear Address Record is used to specify bits 16-31
+of the Linear Base Address (LBA), where bits 0-15 of the LBA are zero.
+Bits 16-31 of the LBA are referred to as the Upper Linear Base Address
+(ULBA). The absolute memory address of a content byte in a subsequent
+Data Record is obtained by adding the LBA to an offset calculated by
+adding the LOAD OFFSET field of the containing Data Record to the index
+of the byte in the Data Record (0, 1, 2, ... n). This offset addition
+is done modulo 4G (i.e., 32-bits), ignoring any carry, so that offset
+wrap-around loading (from OFFFFFFFFH to OOOOOOOOOH) results in wrapping
+around from the end to the beginning of the 4G linear address defined by
+the LBA. The linear address at which a particular byte is loaded is
+calculated as:
+(LBA + DRLO + DRI) MOD 4G
+where:
+DRLO is the LOAD OFFSET field of a Data Record.
+DRI is the data byte index within the Data Record.
+
+When an Extended Linear Address Record defines the value of LBA, it may
+appear anywhere within a 32-bit hexadecimal object file. This value
+remains in effect until another Extended Linear Address Record is
+encountered. The LBA defaults to zero until an Extended Linear Address
+Record is encountered.
+The contents of the individual fields within the record are:
+
+RECORD MARK
+This field contains 03AH, the hexadecimal encoding of the ASCII colon
+(':') character.
+
+RECLEN
+The field contains 03032H, the hexadecimal encoding of the ASCII
+characters '02', which is the length, in bytes, of the ULBA data
+information within this record.
+
+LOAD OFFSET
+This field contains 030303030H, the hexadecimal encoding of the ASCII
+characters '0000', since this field is not used for this record.
+
+RECTYP
+This field contains 03034H, the hexadecimal encoding of the ASCII
+character '04', which specifies the record type to be an Extended Linear
+Address Record.
+
+ULBA
+This field contains four ASCII hexadecimal digits that specify the
+16-bit Upper Linear Base Address value. The high-order byte is the
+10th/llth character pair of the record. The low-order byte is the
+12th/13th character pair of the record.
+
+CHKSUM
+This field contains the check sum on the RECLEN, LOAD OFFSET, RECTYP,
+and ULBA fields.
+
+
+4. Extended Segment Address Record (16- or 32-bit formats)
+| RECORD | LOAD | | | | |
+| MARK | RECLEN | OFFSET | RECTYP | USBA | CHKSUM |
+| ':' | '02' | '0000' | '02' | | |
+ 1-byte 1-byte 2-bytes 1-byte 2-bytes 1-byte
+
+The 16-bit Extended Segment Address Record is used to specify bits 4-19
+of the Segment Base Address (SBA), where bits 0-3 of the SBA are zero.
+Bits 4-19 of the SBA are referred to as the Upper Segment Base Address
+(USBA). The absolute memory address of a content byte in a subsequent
+Data Record is obtained by adding the SBA to an offset calculated by
+adding the LOAD OFFSET field of the containing Data Record to the index
+of the byte in the Data Record (0, 1, 2, ... n). This offset addition
+is done modulo 64K (i.e., 16-bits), ignoring any carry, so that offset
+wraparound loading (from OFFFFH to OOOOOH) results in wrapping around
+from the end to the beginning of the 64K segment defined by the SBA.
+The address at which a particular byte is loaded is calculated as:
+
+ SBA + ([DRLO + DRI] MOD 64K)
+
+where:
+ DRLO is the LOAD OFFSET field of a Data Record.
+ DRI is the data byte index within the Data Record.
+
+When an Extended Segment Address Record defines the value of SBA, it
+may appear anywhere within a 16-bit hexadecimal object file. This
+value remains in effect until another Extended Segment Address
+Record is encountered. The SBA defaults to zero until an Extended
+Segment Address Record is encountered.
+
+The contents of the individual fields within the record are:
+
+RECORD MARK
+This field contains 03AH, the hexadecimal encoding of the ASCII
+colon (':') character.
+
+RECLEN
+The field contains 03032H, the hexadecimal encoding of the ASCII
+characters '02', which is the length, in bytes, of the USBA data
+information within this record.
+
+LOAD OFFSET
+This field contains 030303030H, the hexadecimal encoding of the
+ASCII characters '0000', since this field is not used for this
+record.
+
+RECTYP
+This field contains 03032H, the hexadecimal encoding of the ASCII
+character '02', which specifies the record type to be an Extended
+Segment Address Record.
+
+USBA
+This field contains four ASCII hexadecimal digits that specify the
+16-bit Upper Segment Base Address value. The high-order byte is the
+10th/1lth character pair of the record. The low-order byte is the
+12th/13th character pair of the record.
+
+CHKSUM
+This field contains the check sum on the RECLEN, LOAD OFFSET,
+RECTYP, and USBA fields.
+
+5. Data Record (8-, 16-, or 32-bit formats)
+
+| RECORD | LOAD | | | | |
+| MARK | RECLEN | OFFSET | RECTYP | DATA | CHKSUM |
+| ':' | | | '00' | | |
+ 1-byte 1-byte 2-bytes 1-byte n-bytes 1-byte
+
+
+The Data Record provides a set of hexadecimal digits that represent
+the ASCII code for data bytes that make up a portion of a memory
+image. The method for calculating the absolute address (linear in
+the 8-bit and 32-bit case and segmented in the 16-bit case) for each
+byte of data is described in the discussions of the Extended Linear
+Address Record and the Extended Segment Address Record.
+
+The contents of the individual fields within the record are:
+
+RECORD MARK
+This field contains 03AH, the hexadecimal encoding of the ASCII
+colon (':') character.
+
+RECLEN
+The field contains two ASCII hexadecimal digits that specify the
+number of data bytes in the record. The maximum value is 'FF' or
+04646H (255 decimal).
+
+LOAD OFFSET
+This field contains four ASCII hexadecimal digits representing the
+offset from the LBA (see Extended Linear Address Record) or SBA (see
+Extended Segment Address Record) defining the address which the
+first byte of the data is to be placed.
+
+RECTYP
+This field contains 03030H, the hexadecimal encoding of the ASCII
+character '00', which specifies the record type to be a Data Record.
+
+DATA
+This field contains pairs of ASCII hexadecimal digits, one pair for
+each data byte.
+
+CHKSUM
+This field contains the check sum on the RECLEN, LOAD OFFSET,
+RECTYP, and DATA fields.
+
+
+6. Start Linear Address Record (32-bit format only)
+
+| RECORD | LOAD | | | | |
+| MARK | RECLEN | OFFSET | RECTYP | EIP | CHKSUM |
+| ':' | '04' | '0000' | '05' | | |
+ 1-byte 1-byte 2-bytes 1-byte 4-bytes 1-byte
+
+
+The Start Linear Address Record is used to specify the execution
+start address for the object file. The value given is the 32-bit
+linear address for the EIP register. Note that this record only
+specifies the code address within the 32-bit linear address space of
+the 80386. If the code is to start execution in the real mode of
+the 80386, then the Start Segment Address Record should be used
+instead, since that record specifies both the CS and IP register
+contents necessary for real mode.
+
+The Start Linear Address Record can appear anywhere in a 32-bit
+hexadecimal object file. If such a record is not present in a
+hexadecimal object file, a loader is free to assign a default start
+address.
+
+The contents of the individual fields within the record are:
+
+RECORD MARK
+This field contains 03AH, the hexadecimal encoding of the ASCII
+colon (':') character.
+
+RECLEN
+The field contains 03034H, the hexadecimal encoding of the ASCII
+characters '04', which is the length, in bytes, of the EIP register
+content within this record.
+
+LOAD OFFSET
+This field contains 030303030H, the hexadecimal encoding of the
+ASCII characters '0000', since this field is not used for this
+record.
+
+RECTYP
+This field contains 03035H, the hexadecimal encoding of the ASCII
+character '05', which specifies the record type to be a Start Linear
+Address Record.
+
+EIP
+This field contains eight ASCII hexadecimal digits that specify the
+32-bit EIP register contents. The high-order byte is the 10th/1lth
+character pair.
+
+CHKSUM
+This field contains the check sum on the RECLEN, LOAD OFFSET,
+RECTYP, and EIP fields.
+
+
+7. Start Segment Address Record (16- or 32-bit formats)
+
+| RECORD | LOAD | | | | |
+| MARK | RECLEN | OFFSET | RECTYP | CS/IP | CHKSUM |
+| ':' | '04' | '0000' | '03' | | |
+ 1-byte 1-byte 2-bytes 1-byte 4-bytes 1-byte
+
+
+The Start Segment Address Record is used to specify the execution
+start address for the object file. The value given is the 20-bit
+segment address for the CS and IP registers. Note that this record
+only specifies the code address within the 20-bit segmented address
+space of the 8086/80186.
+
+The Start Segment Address Record can appear anywhere in a 16-bit
+hexadecimal object file. If such a record is not present in a
+hexadecimal object file, a loader is free to assign a default start
+address.
+
+The contents of the individual fields within the record are:
+
+RECORD MARK
+This field contains 03AH, the hexadecimal encoding of the ASCII
+colon (':') character.
+
+RECLEN
+The field contains 03034H, the hexadecimal encoding of the ASCII
+characters '04', which is the length, in bytes, of the CS/IP
+register contents within this record.
+
+LOAD OFFSET
+This field contains 030303030H, the hexadecimal encoding of the
+ASCII characters '0000', since this field is not used for this
+record.
+
+RECTYP
+This field contains 03033H, the hexadecimal encoding of the ASCII
+character '03', which specifies the record type to be a Start
+Segment Address Record.
+
+CS/IP
+This field contains eight ASCII hexadecimal digits that specify the
+16-bit CS register and 16-bit IP register contents. The high-order
+byte of the CS register content is the 10th/llth character pair, the
+low-order byte is the 12th/13th character pair of the record. The
+high-order byte of the IP register content is the 14th/15th
+character pair, the low-order byte is the 16th/17th character pair
+of the record.
+
+CHKSUM
+This field contains the check sum on the RECLEN, LOAD OFFSET,
+RECTYP, and CS/IP fields.
+
+
+
+8. End of File Record (8-, 16-, or 32-bit formats)
+
+| RECORD | LOAD | | | |
+| MARK | RECLEN | OFFSET | RECTYP | CHKSUM |
+| ':' | '00' | '0000' | '01' | |
+ 1-byte 1-byte 2-bytes 1-byte 1-byte
+
+The End of File Record specifies the end of the hexadecimal object
+file.
+
+The contents of the individual fields within the record are:
+
+RECORD MARK
+This field contains 03AH, the hexadecimal encoding of the ASCII
+colon (':') character.
+
+RECLEN
+The field contains 03030H, the hexadecimal encoding of the ASCII
+characters '00'. Since this record does not contain any INFO/DATA
+bytes, the length is zero.
+
+LOAD OFFSET
+This field contains 030303030H, the hexadecimal encoding of the
+ASCII characters '0000', since this field is not used for this
+record.
+
+RECTYP
+This field contains 03031H, the hexadecimal encoding of the ASCII
+character '01', which specifies the record type to be an End of File
+Record.
+
+CHKSUM
+This field contains the check sum an the RECLEN, LOAD OFFSET, and
+RECTYP fields. Since all the fields are static, the check sum can
+also be calculated statically, and the value is 04646H, the
+hexadecimal encoding of the ASCII characters 'FF'.
+
+========================================================================
+END
diff --git a/tools/hex2bin-2.0/doc/srec.txt b/tools/hex2bin-2.0/doc/srec.txt
new file mode 100644
index 0000000..ea63d31
--- /dev/null
+++ b/tools/hex2bin-2.0/doc/srec.txt
@@ -0,0 +1,447 @@
+S-Records
+
+
+ -S-Record Format-
+
+ Chaplin@keinstr.uucp (Roger Chaplin) reposted an article written
+ by mcdchg!motmpl!ron (Ron Widell) that explained how Motorola
+ S-Records are formatted. This comes from a unix man page. No
+ mention of which version of Unix is specified. This section
+ of the FAQ is a bit long. An anonymous ftp archive is currently
+ being sought. When one is found, the section will be placed in
+ the archive.
+
+
+ SREC(4) UNIX 5.0 (03/21/84) SREC(4)
+
+
+ An S-record file consists of a sequence of specially formatted
+ ASCII character strings. An S-record will be less than or equal to
+ 78 bytes in length.
+
+ The order of S-records within a file is of no significance and no
+ particular order may be assumed.
+
+ The general format of an S-record follow:
+
+ +------------------//-------------------//-----------------------+
+ | type | count | address | data | checksum |
+ +------------------//-------------------//-----------------------+
+
+ type A char-2- field. These characters describe the
+ type of record (S0, S1, S2, S3, S5, S7, S8, or
+ S9).
+ count A char-2- field. These characters when paired and
+ interpreted as a hexadecimal value, display the
+ count of remaining character pairs in the record.
+
+ address A char-4,6, or 8- field. These characters grouped
+ and interpreted as a hexadecimal value, display
+ the address at which the data field is to be
+ loaded into memory. The length of the field
+ depends on the number of bytes necessary to hold
+ the address. A 2-byte address uses 4 characters,
+ a 3-byte address uses 6 characters, and a 4-byte
+ address uses 8 characters.
+ data A char -0-64- field. These characters when paired
+ and interpreted as hexadecimal values represent
+ the memory loadable data or descriptive
+ information.
+
+ checksum A char-2- field. These characters when paired and
+ interpreted as a hexadecimal value display the
+ least significant byte of the ones complement of
+ the sum of the byte values represented by the
+ pairs of characters making up the count, the
+ address, and the data fields.
+
+ Each record is terminated with a line feed. If any
+ additional or different record terminator(s) or delay
+ characters are needed during transmission to the target
+ system it is the responsibility of the transmitting program
+ to provide them.
+
+ S0 Record The type of record is 'S0' (0x5330). The address
+
+
+ field is unused and will be filled with zeros
+ (0x0000). The header information within the data
+ field is divided into the following subfields.
+
+ mname is char-20- and is the
+ module name.
+ ver is char-2- and is the
+ version number.
+
+ rev is char-2- and is the
+ revision number.
+ description is char-0-36- and is a
+ text comment.
+
+ Each of the subfields is composed of ASCII bytes
+ whose associated characters, when paired,
+ represent one byte hexadecimal values in the case
+ of the version and revision numbers, or represent
+ the hexadecimal values of the ASCII characters
+ comprising the module name and description.
+
+ S1 Record The type of record field is 'S1' (0x5331). The
+ address field is interpreted as a 2-byte address.
+ The data field is composed of memory loadable
+ data.
+ S2 Record The type of record field is 'S2' (0x5332). The
+ address field is interpreted as a 3-byte address.
+ The data field is composed of memory loadable
+ data.
+
+ S3 Record The type of record field is 'S3' (0x5333). The
+ address field is interpreted as a 4-byte address.
+ The data field is composed of memory loadable
+ data.
+ S5 Record The type of record field is 'S5' (0x5335). The
+ address field is interpreted as a 2-byte value
+ and contains the count of S1, S2, and S3 records
+ previously transmitted. There is no data field.
+
+ S7 Record The type of record field is 'S7' (0x5337). The
+ address field contains the starting execution
+ address and is interpreted as 4-byte address.
+ There is no data field.
+ S8 Record The type of record field is 'S8' (0x5338). The
+ address field contains the starting execution
+ address and is interpreted as 3-byte address.
+ There is no data field.
+
+ S9 Record The type of record field is 'S9' (0x5339). The
+ address field contains the starting execution
+ address and is interpreted as 2-byte address.
+ There is no data field.
+
+ EXAMPLE
+
+ Shown below is a typical S-record format file.
+
+ S00600004844521B
+ S1130000285F245F2212226A000424290008237C2A
+ S11300100002000800082629001853812341001813
+ S113002041E900084E42234300182342000824A952
+ S107003000144ED492
+ S5030004F8
+ S9030000FC
+
+ The file consists of one S0 record, four S1 records, one S5
+ record and an S9 record.
+
+ The S0 record is comprised as follows:
+
+ S0 S-record type S0, indicating it is a header
+ record.
+ 06 Hexadecimal 06 (decimal 6), indicating that six
+ character pairs (or ASCII bytes) follow.
+
+ 00 00 Four character 2-byte address field, zeroes in
+ this example.
+ 48 ASCII H, D, and R - "HDR".
+
+ 1B The checksum.
+
+ The first S1 record is comprised as follows:
+ S1 S-record type S1, indicating it is a data record
+ to be loaded at a 2-byte address.
+
+ 13 Hexadecimal 13 (decimal 19), indicating that
+ nineteen character pairs, representing a 2 byte
+ address, 16 bytes of binary data, and a 1 byte
+ checksum, follow.
+ 00 00 Four character 2-byte address field; hexadecimal
+ address 0x0000, where the data which follows is to
+ be loaded.
+
+ 28 5F 24 5F 22 12 22 6A 00 04 24 29 00 08 23 7C Sixteen
+ character pairs representing the actual binary
+ data.
+ 2A The checksum.
+
+ The second and third S1 records each contain 0x13 (19)
+ character pairs and are ended with checksums of 13 and 52,
+ respectively. The fourth S1 record contains 07 character
+ pairs and has a checksum of 92.
+
+ The S5 record is comprised as follows:
+
+ S5 S-record type S5, indicating it is a count record
+ indicating the number of S1 records.
+
+
+
+ 03 Hexadecimal 03 (decimal 3), indicating that three
+ character pairs follow.
+
+ 00 04 Hexadecimal 0004 (decimal 4), indicating that
+ there are four data records previous to this
+ record.
+ F8 The checksum.
+
+ The S9 record is comprised as follows:
+
+ S9 S-record type S9, indicating it is a termination
+ record.
+ 03 Hexadecimal 03 (decimal 3), indicating that three
+ character pairs follow.
+
+ 00 00 The address field, hexadecimal 0 (decimal 0)
+ indicating the starting execution address.
+ FC The checksum.
+
+
+ -Intel Hex ASCII Format-
+
+ Intel HEX-ASCII format takes the form:
+
+ +----------------------------------- Start Character
+ |
+ | +-------------------------------- Byte Count
+ | | (# of data bytes)
+ | |
+ | | +-------------------------- Address of first data.
+ | | |
+ | | | +-------------------- Record Type (00 data,
+ | | | | 01 end of record)
+ | | | |
+ | | | | +------------ Data Bytes
+ | | | | |
+ | | | | | +---- Checksum
+ | | | | | |
+ | / \ / \ / \ / \ / \
+ : B C A A A A T T H H ... H H C C
+
+ An examples:
+
+ :10000000DB00E60F5F1600211100197ED300C3004C
+ :1000100000000101030307070F0F1F1F3F3F7F7FF2
+ :01002000FFE0
+ :00000001FF
+
+ This information comes from _Microprocessors and Programmed
+ Logic_, Second Edition, Kenneth L. Short, 1987, Prentice-Hall,
+ ISBN 0-13-580606-2.
+
+ Provisions have been made for data spaces larger than 64 kBytes.
+ The above reference does not discuss them. I suspect there is
+ a start of segment type record, but I do not know how it is
+ implemented.
+
+----------------------------------------------------------------------------
+
+/* This file contains source code to read a Motorola S-record file into
+** a memory image. The size of the file cannot exceed BUFSIZE of data.
+** The image is then written to disk either as binary data starting at
+** address 0 with no data gaps, or as a C array of unsigned longs.
+** Input lines must be no longer than MAXLINE. No check is made!
+**
+** Author: Eric McRae, Electro-Logic Machines, Inc.
+** Date: Copyright 1994
+**
+** This source code is made available to the public "as is". No
+** warranty is given or implied for it's proper operation. This source
+** code may be used in whole or in part as long as this copyright is
+** included.
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Comment the following line for non PC applications */
+#define PCDOS
+
+/* Uncomment the following line if you want a binary output instead of
+** a structure
+*/
+/* #define BINARY */
+
+#ifdef PCDOS /* Intel x86 architecture */
+#define BUFSIZE 49152 /* 48K to avoid segment hopping */
+#else /* Any reasonable (non-segmented) arch... */
+#define BUFSIZE 65536 /* As big as you want */
+#endif
+
+#define MAXLINE 256 /* Length of longest input line + 1 */
+/* Globals */
+FILE *infilePH, *outfilePH; /* Handles for input and output files */
+unsigned char *bufAC, /* Allocated image buffer */
+ *highestPC = NULL; /* Highest buffer address written */
+
+/* Change this string to reflect the name of the output array */
+char headerAC[] = "unsigned long sRec[] =\n{\n";
+
+/* Predeclarations */
+int parsebufN( char * ); /* Does the actual parsing */
+
+void main(int argc, const char * argv[])
+{
+ int c, /* Temp char storage */
+ resN; /* result status */
+ char *lbufPC, lbufAC[MAXLINE];
+ int linectrN = 0; /* Used to correlate parse fail to input line */
+
+#ifndef BINARY
+ int i;
+ unsigned long *codePL;
+ unsigned char *codePC;
+#endif
+
+ /* Check the argument count */
+ if( argc != 3 ) /* If didn't specify input and output files */
+ {
+ printf("Usage: %s: infile outfile\n", argv[0] );
+ exit(1);
+ }
+
+ /* OK, let's open some files */
+ if( ( infilePH = fopen( argv[1], "r" ) )== NULL )
+ {
+ printf("%s: Couldn't open input file %s\n", argv[0], argv[1] );
+ exit(2);
+ }
+
+ if( ( outfilePH = fopen( argv[2], "w" ) ) == NULL )
+ {
+ printf("%s: Couldn't open output file %s\n", argv[0], argv[3] );
+ exit(3);
+ }
+
+ /* OK, get a buffer and clear it. */
+ if( (bufAC = calloc( (size_t)BUFSIZE, (size_t)1 )) == NULL )
+ {
+ printf("%s: Couldn't malloc memory for buffer\n", argv[0] );
+ exit(4);
+ }
+
+ lbufPC = lbufAC; /* Point at beginning of line buffer */
+ while( c = fgetc( infilePH ))
+ {
+ if( (c == '\n') || (c == EOF) ) /* If found end of line or file */
+ { /* Parse the Line */
+ if( ( c == EOF ) && ( ferror( infilePH ) ) )
+ {
+ printf("%s: Error reading input file\n", argv[0] );
+ exit(5);
+ }
+ else
+ { /* OK, have a complete line in buffer */
+ linectrN++; /* Increment line counter */
+ if( lbufPC == lbufAC )
+ break; /* ignore blank lines */
+ *lbufPC = 0; /* Terminate the line string */
+ if( resN = parsebufN( lbufAC ) ) /* Parse data record to mem */
+ {
+ printf("%s: Error reading input file at line %d, return code = %d\n",
+ argv[0], linectrN, resN );
+ exit( resN );
+ }
+ lbufPC = lbufAC; /* Repoint line buffer pointer */
+ } /* End of have a complete line */
+ }
+ else
+ *lbufPC++ = c; /* Place char into line buffer */
+ }
+
+ /* At this point, the input file has been emptied. Now dispose of the
+ ** output data according to compilation mode.
+ */
+
+#ifdef BINARY
+
+ /* Write the buffer back to disk as a binary image */
+ resN = fwrite( bufAC, 1, (size_t)((highestPC - bufAC) + 1), outfilePH );
+ if( resN != (int)( (highestPC - bufAC) + 1) )
+ {
+ printf("%s: Error writing output file\n", argv[0] );
+ exit( 6 );
+ }
+
+#else
+ /* Produce a file that can be included in a C program. Data is read
+ ** from buffer as bytes to avoid portability/endian problems with
+ ** this program.
+ */
+ /* Output header first, then 1 long per line */
+ fwrite( (void *)headerAC, 1, (size_t)(sizeof( headerAC )-1), outfilePH );
+
+ codePL = (unsigned long *)bufAC;
+ for( i = (highestPC - bufAC + 1) / 4; i; i-- ) /* for each long */
+ {
+ codePC = (unsigned char *)codePL++;
+ sprintf(lbufAC, "0x%02x%02x%02x%02x%s",
+ *codePC, *(codePC + 1), *(codePC + 2), *(codePC + 3),
+ i == 1 ? "\n" : ",\n" ); /* No comma after final long */
+ fwrite( lbufAC, 1, (size_t)(strlen( lbufAC )), outfilePH );
+ }
+ /* OK, data has been written out, close end of array */
+ fwrite( "};\n", 1, (size_t)3, outfilePH );
+#endif
+}
+
+/* Function: parsebufV
+** Parses an S-record in the buffer and writes it into the buffer
+** if it is has a valid checksum.
+**
+** Args: pointer to character buffer for null terminated line
+** Returns: int result code: 0 = success, else failure
+*/
+int parsebufN( char *lbufPC )
+{
+ unsigned long addrL;
+ unsigned char cksmB, /* checksum of addr, count, & data length */
+ *bufPC; /* Pointer into memory array */
+ int i, countN, /* Number of bytes represented in record */
+ oheadN, /* Number of overhead (addr + chksum) bytes */
+ tvalN; /* Temp for check checksum */
+
+ switch( *(lbufPC+1) ) /* examine 2nd character on the line */
+ {
+ case '1': /* 16 bit address field */
+ if( sscanf(lbufPC, "S1%2x%4lx", &countN, &addrL ) != 2 )
+ return( 10 ); /* Flag error in S1 record */
+ oheadN = 3; /* 2 address + 1 checksum */
+ break;
+
+ case '2': /* 24 bit address field */
+ if( sscanf(lbufPC, "S2%2x%6lx", &countN, &addrL ) != 2 )
+ return( 11 ); /* Flag error in S2 record */
+ oheadN = 4; /* 3 address + 1 checksum */
+ break;
+
+ case '3': /* 32 bit address field */
+ if( sscanf(lbufPC, "S3%2x%8lx", &countN, &addrL ) != 2 )
+ return( 12 ); /* Flag error in S3 record */
+ oheadN = 5; /* 4 address + 1 checksum */
+ break;
+
+ default: /* ignore all but S1,2,3 records. */
+ return( 0 );
+ }
+
+ if( addrL > BUFSIZE ) return( 13 ); /* if address exceeds buffer size */
+ bufPC = bufAC + addrL; /* otherwise, point to right spot in buffer */
+
+ /* OK now see if checksum is OK, while reading data to buffer */
+ cksmB = 0;
+ countN++; /* Bump counter to read final checksum too */
+ for( i = 1; i <= countN; i++ )
+ {
+ sscanf( lbufPC + i*2, "%2x", &tvalN ); /* Scan a 2 hex digit byte */
+ cksmB += (unsigned char)tvalN;
+ if( ( i > oheadN ) && ( i < countN ) ) /* If scanned a data byte */
+ *bufPC++ = (unsigned char) tvalN; /* write it to the buffer */
+ }
+ if( cksmB += 1 ) return( 14 ); /* flag checksum error */
+
+ if( (bufPC - 1) > highestPC )
+ highestPC = bufPC - 1; /* track highest address loaded */
+
+ return( 0 ); /* Successful return */
+}
+
+
+
diff --git a/tools/hex2bin-2.0/src/binary.c b/tools/hex2bin-2.0/src/binary.c
new file mode 100644
index 0000000..63ead0d
--- /dev/null
+++ b/tools/hex2bin-2.0/src/binary.c
@@ -0,0 +1,196 @@
+/*---------------------------------------------------------------------------*
+ * binary.c *
+ * Copyright (C) 2014 Jacques Pelletier *
+ * *
+ * 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. *
+ *---------------------------------------------------------------------------*/
+
+#include <stdint.h>
+
+#include "binary.h"
+
+const uint8_t Reflect8[256] = {
+ 0x00,0x80,0x40,0xC0,0x20,0xA0,0x60,0xE0,0x10,0x90,0x50,0xD0,0x30,0xB0,0x70,0xF0,
+ 0x08,0x88,0x48,0xC8,0x28,0xA8,0x68,0xE8,0x18,0x98,0x58,0xD8,0x38,0xB8,0x78,0xF8,
+ 0x04,0x84,0x44,0xC4,0x24,0xA4,0x64,0xE4,0x14,0x94,0x54,0xD4,0x34,0xB4,0x74,0xF4,
+ 0x0C,0x8C,0x4C,0xCC,0x2C,0xAC,0x6C,0xEC,0x1C,0x9C,0x5C,0xDC,0x3C,0xBC,0x7C,0xFC,
+ 0x02,0x82,0x42,0xC2,0x22,0xA2,0x62,0xE2,0x12,0x92,0x52,0xD2,0x32,0xB2,0x72,0xF2,
+ 0x0A,0x8A,0x4A,0xCA,0x2A,0xAA,0x6A,0xEA,0x1A,0x9A,0x5A,0xDA,0x3A,0xBA,0x7A,0xFA,
+ 0x06,0x86,0x46,0xC6,0x26,0xA6,0x66,0xE6,0x16,0x96,0x56,0xD6,0x36,0xB6,0x76,0xF6,
+ 0x0E,0x8E,0x4E,0xCE,0x2E,0xAE,0x6E,0xEE,0x1E,0x9E,0x5E,0xDE,0x3E,0xBE,0x7E,0xFE,
+ 0x01,0x81,0x41,0xC1,0x21,0xA1,0x61,0xE1,0x11,0x91,0x51,0xD1,0x31,0xB1,0x71,0xF1,
+ 0x09,0x89,0x49,0xC9,0x29,0xA9,0x69,0xE9,0x19,0x99,0x59,0xD9,0x39,0xB9,0x79,0xF9,
+ 0x05,0x85,0x45,0xC5,0x25,0xA5,0x65,0xE5,0x15,0x95,0x55,0xD5,0x35,0xB5,0x75,0xF5,
+ 0x0D,0x8D,0x4D,0xCD,0x2D,0xAD,0x6D,0xED,0x1D,0x9D,0x5D,0xDD,0x3D,0xBD,0x7D,0xFD,
+ 0x03,0x83,0x43,0xC3,0x23,0xA3,0x63,0xE3,0x13,0x93,0x53,0xD3,0x33,0xB3,0x73,0xF3,
+ 0x0B,0x8B,0x4B,0xCB,0x2B,0xAB,0x6B,0xEB,0x1B,0x9B,0x5B,0xDB,0x3B,0xBB,0x7B,0xFB,
+ 0x07,0x87,0x47,0xC7,0x27,0xA7,0x67,0xE7,0x17,0x97,0x57,0xD7,0x37,0xB7,0x77,0xF7,
+ 0x0F,0x8F,0x4F,0xCF,0x2F,0xAF,0x6F,0xEF,0x1F,0x9F,0x5F,0xDF,0x3F,0xBF,0x7F,0xFF,
+};
+
+uint16_t Reflect16(uint16_t Value16)
+{
+ return (((uint16_t) Reflect8[u16_lo(Value16)]) << 8) | ((uint16_t) Reflect8[u16_hi(Value16)]);
+}
+
+uint32_t Reflect24(uint32_t Value24)
+{
+ return (
+ (((uint32_t) Reflect8[u32_b0(Value24)]) << 16) |
+ (((uint32_t) Reflect8[u32_b1(Value24)]) << 8) |
+ ((uint32_t) Reflect8[u32_b2(Value24)])
+ );
+}
+
+uint32_t Reflect32(uint32_t Value32)
+{
+ return (
+ (((uint32_t) Reflect8[u32_b0(Value32)]) << 24) |
+ (((uint32_t) Reflect8[u32_b1(Value32)]) << 16) |
+ (((uint32_t) Reflect8[u32_b2(Value32)]) << 8) |
+ ((uint32_t) Reflect8[u32_b3(Value32)])
+ );
+}
+
+uint64_t Reflect40(uint64_t Value40)
+{
+ return (
+ (((uint64_t) Reflect8[u64_b0(Value40)]) << 32) |
+ (((uint64_t) Reflect8[u64_b1(Value40)]) << 24) |
+ (((uint64_t) Reflect8[u64_b2(Value40)]) << 16) |
+ (((uint64_t) Reflect8[u64_b3(Value40)]) << 8) |
+ ((uint64_t) Reflect8[u64_b4(Value40)])
+ );
+}
+
+uint64_t Reflect64(uint64_t Value64)
+{
+ return (
+ (((uint64_t) Reflect8[u64_b0(Value64)]) << 56) |
+ (((uint64_t) Reflect8[u64_b1(Value64)]) << 48) |
+ (((uint64_t) Reflect8[u64_b2(Value64)]) << 40) |
+ (((uint64_t) Reflect8[u64_b3(Value64)]) << 32) |
+ (((uint64_t) Reflect8[u64_b4(Value64)]) << 24) |
+ (((uint64_t) Reflect8[u64_b5(Value64)]) << 16) |
+ (((uint64_t) Reflect8[u64_b6(Value64)]) << 8) |
+ ((uint64_t) Reflect8[u64_b7(Value64)])
+ );
+}
+
+uint8_t u16_hi(uint16_t value)
+{
+ return (uint8_t)((value & 0xFF00) >> 8);
+}
+
+uint8_t u16_lo(uint16_t value)
+{
+ return (uint8_t)(value & 0x00FF);
+}
+
+uint8_t u32_b3(uint32_t value)
+{
+ return (uint8_t)((value & 0xFF000000) >> 24);
+}
+
+uint8_t u32_b2(uint32_t value)
+{
+ return (uint8_t)((value & 0x00FF0000) >> 16);
+}
+
+uint8_t u32_b1(uint32_t value)
+{
+ return (uint8_t)((value & 0x0000FF00) >> 8);
+}
+
+uint8_t u32_b0(uint32_t value)
+{
+ return (uint8_t)(value & 0x000000FF);
+}
+
+uint8_t u64_b7(uint64_t value)
+{
+ return (uint8_t)((value & 0xFF00000000000000) >> 56);
+}
+
+uint8_t u64_b6(uint64_t value)
+{
+ return (uint8_t)((value & 0x00FF000000000000) >> 48);
+}
+
+uint8_t u64_b5(uint64_t value)
+{
+ return (uint8_t)((value & 0x0000FF0000000000) >> 40);
+}
+
+uint8_t u64_b4(uint64_t value)
+{
+ return (uint8_t)((value & 0x000000FF00000000) >> 32);
+}
+
+uint8_t u64_b3(uint64_t value)
+{
+ return (uint8_t)((value & 0x00000000FF000000) >> 24);
+}
+
+uint8_t u64_b2(uint64_t value)
+{
+ return (uint8_t)((value & 0x0000000000FF0000) >> 16);
+}
+
+uint8_t u64_b1(uint64_t value)
+{
+ return (uint8_t)((value & 0x000000000000FF00) >> 8);
+}
+
+uint8_t u64_b0(uint64_t value)
+{
+ return (uint8_t)(value & 0x00000000000000FF);
+}
+
+/* Checksum/CRC conversion to ASCII */
+uint8_t nibble2ascii(uint8_t value)
+{
+ uint8_t result = value & 0x0f;
+
+ if (result > 9) return result + 0x41-0x0A;
+ else return result + 0x30;
+}
+
+bool cs_isdecdigit(char c)
+{
+ return (c >= 0x30) && (c < 0x3A);
+}
+
+unsigned char tohex(unsigned char c)
+{
+ if ((c >= '0') && (c < '9'+1))
+ return (c - '0');
+ if ((c >= 'A') && (c < 'F'+1))
+ return (c - 'A' + 0x0A);
+ if ((c >= 'a') && (c < 'f'+1))
+ return (c - 'a' + 0x0A);
+
+ return 0;
+}
+
+unsigned char todecimal(unsigned char c)
+{
+ if ((c >= '0') && (c < '9'+1))
+ return (c - '0');
+
+ return 0;
+}
+
+
diff --git a/tools/hex2bin-2.0/src/binary.h b/tools/hex2bin-2.0/src/binary.h
new file mode 100644
index 0000000..198589b
--- /dev/null
+++ b/tools/hex2bin-2.0/src/binary.h
@@ -0,0 +1,36 @@
+#ifndef _BINARY_H_
+#define _BINARY_H_
+
+typedef enum {false, true} bool;
+
+extern const unsigned char Reflect8[256];
+
+uint16_t Reflect16(uint16_t Value16);
+uint32_t Reflect24(uint32_t Value24);
+uint32_t Reflect32(uint32_t Value32);
+uint64_t Reflect40(uint64_t Value40);
+uint64_t Reflect64(uint64_t Value64);
+
+uint8_t u16_hi(uint16_t value);
+uint8_t u16_lo(uint16_t value);
+
+uint8_t u32_b3(uint32_t value);
+uint8_t u32_b2(uint32_t value);
+uint8_t u32_b1(uint32_t value);
+uint8_t u32_b0(uint32_t value);
+
+uint8_t u64_b7(uint64_t value);
+uint8_t u64_b6(uint64_t value);
+uint8_t u64_b5(uint64_t value);
+uint8_t u64_b4(uint64_t value);
+uint8_t u64_b3(uint64_t value);
+uint8_t u64_b2(uint64_t value);
+uint8_t u64_b1(uint64_t value);
+uint8_t u64_b0(uint64_t value);
+
+uint8_t nibble2ascii(uint8_t value);
+bool cs_isdecdigit(char c);
+unsigned char tohex(unsigned char c);
+unsigned char todecimal(unsigned char c);
+
+#endif /* _BINARY_H_ */
diff --git a/tools/hex2bin-2.0/src/common.c b/tools/hex2bin-2.0/src/common.c
new file mode 100644
index 0000000..f453dc4
--- /dev/null
+++ b/tools/hex2bin-2.0/src/common.c
@@ -0,0 +1,527 @@
+#include "common.h"
+
+filetype Filename; /* string for opening files */
+char Extension[MAX_EXTENSION_SIZE]; /* filename extension for output files */
+
+FILE *Filin, /* input files */
+ *Filout; /* output files */
+
+#ifdef USE_FILE_BUFFERS
+char *FilinBuf, /* text buffer for file input */
+ *FiloutBuf; /* text buffer for file output */
+#endif
+
+int Pad_Byte = 0xFF;
+bool Enable_Checksum_Error = false;
+bool Status_Checksum_Error = false;
+byte Checksum;
+unsigned int Record_Nb;
+
+/* This will hold binary codes translated from hex file. */
+byte *Memory_Block;
+unsigned int Lowest_Address, Highest_Address;
+unsigned int Starting_Address;
+unsigned int Max_Length = 0;
+unsigned int Minimum_Block_Size = 0x1000; // 4096 byte
+int Module;
+bool Minimum_Block_Size_Setted = false;
+bool Starting_Address_Setted = false;
+bool Max_Length_Setted = false;
+bool Swap_Wordwise = false;
+
+int Endian = 0;
+
+t_CRC Cks_Type = CHK8_SUM;
+unsigned int Cks_Start = 0, Cks_End = 0, Cks_Addr = 0, Cks_Value = 0;
+bool Cks_range_set = false;
+bool Cks_Addr_set = false;
+bool Force_Value = false;
+
+unsigned int Crc_Poly = 0x07, Crc_Init = 0, Crc_XorOut = 0;
+bool Crc_RefIn = false;
+bool Crc_RefOut = false;
+
+void usage(void)
+{
+ fprintf (stderr,
+ "\n"
+ "usage: %s [OPTIONS] filename\n"
+ "Options:\n"
+ " -c Enable record checksum verification\n"
+ " -C [Poly][Init][RefIn][RefOut][XorOut]\n CRC parameters"
+ " -e [ext] Output filename extension (without the dot)\n"
+ " -E [0|1] Endian for checksum/CRC, 0: little, 1: big\n"
+ " -f [address] Address of check result to write\n"
+ " -F [address] [value]\n Address and value to force\n"
+ " -k [0-4] Select check method (checksum or CRC) and size\n"
+ " -d display list of check methods/value size\n"
+ " -l [length] Maximal Length (Starting address + Length -1 is Max Address)\n"
+ " File will be filled with Pattern until Max Address is reached\n"
+ " -m [size] Minimum Block Size\n"
+ " File Size Dimension will be a multiple of Minimum block size\n"
+ " File will be filled with Pattern\n"
+ " Length must be a power of 2 in hexadecimal [see -l option]\n"
+ " Attention this option is STRONGER than Maximal Length \n"
+ " -p [value] Pad-byte value in hex (default: %x)\n"
+ " -r [start] [end]\n"
+ " Range to compute checksum over (default is min and max addresses)\n"
+ " -s [address] Starting address in hex (default: 0)\n"
+ " -w Swap wordwise (low <-> high)\n\n",
+ Pgm_Name,Pad_Byte);
+ exit(1);
+} /* procedure USAGE */
+
+void DisplayCheckMethods(void)
+{
+ fprintf (stderr,
+ "Check methods/value size:\n"
+ "0: Checksum 8-bit\n"
+ "1: Checksum 16-bit\n"
+ "2: CRC8\n"
+ "3: CRC16\n"
+ "4: CRC32\n");
+ exit(1);
+}
+
+#define LAST_CHECK_METHOD 4
+
+void *NoFailMalloc (size_t size)
+{
+ void *result;
+
+ if ((result = malloc (size)) == NULL)
+ {
+ fprintf (stderr,"Can't allocate memory.\n");
+ exit(1);
+ }
+ return (result);
+}
+
+/* Open the input file, with error checking */
+void NoFailOpenInputFile (char *Flnm)
+{
+ while ((Filin = fopen(Flnm,"r")) == NULL)
+ {
+ fprintf (stderr,"Input file %s cannot be opened. Enter new filename: ",Flnm);
+ if (fgets (Flnm,MAX_FILE_NAME_SIZE,stdin) == NULL) exit(1); /* modified error checking */
+
+ if (Flnm[strlen(Flnm) - 1] == '\n') Flnm[strlen(Flnm) - 1] = '\0';
+ }
+
+#ifdef USE_FILE_BUFFERS
+ FilinBuf = (char *) NoFailMalloc (BUFFSZ);
+ setvbuf(Filin, FilinBuf, _IOFBF, BUFFSZ);
+#endif
+} /* procedure OPENFILIN */
+
+/* Open the output file, with error checking */
+void NoFailOpenOutputFile (char *Flnm)
+{
+ while ((Filout = fopen(Flnm,"wb")) == NULL)
+ {
+ /* Failure to open the output file may be
+ simply due to an insufficiant permission setting. */
+ fprintf(stderr,"Output file %s cannot be opened. Enter new file name: ", Flnm);
+ if (fgets(Flnm,MAX_FILE_NAME_SIZE,stdin) == NULL) exit(1);
+
+ if (Flnm[strlen(Flnm) - 1] == '\n') Flnm[strlen(Flnm) - 1] = '\0';
+ }
+
+#ifdef USE_FILE_BUFFERS
+ FiloutBuf = (char *) NoFailMalloc (BUFFSZ);
+ setvbuf(Filout, FiloutBuf, _IOFBF, BUFFSZ);
+#endif
+
+} /* procedure OPENFILOUT */
+
+void GetLine(char* str,FILE *in)
+{
+ char *result;
+
+ result = fgets(str,MAX_LINE_SIZE,in);
+ if ((result == NULL) && !feof (in)) fprintf(stderr,"Error occurred while reading from file\n");
+}
+
+// 0 or 1
+int GetBin(const char *str)
+{
+ int result;
+ unsigned int value;
+
+ result = sscanf(str,"%u",&value);
+
+ if (result == 1) return value & 1;
+ else
+ {
+ fprintf(stderr,"GetBin: some error occurred when parsing options.\n");
+ exit (1);
+ }
+}
+
+int GetDec(const char *str)
+{
+ int result;
+ unsigned int value;
+
+ result = sscanf(str,"%u",&value);
+
+ if (result == 1) return value;
+ else
+ {
+ fprintf(stderr,"GetDec: some error occurred when parsing options.\n");
+ exit (1);
+ }
+}
+
+int GetHex(const char *str)
+{
+ int result;
+ unsigned int value;
+
+ result = sscanf(str,"%x",&value);
+
+ if (result == 1) return value;
+ else
+ {
+ fprintf(stderr,"GetHex: some error occurred when parsing options.\n");
+ exit (1);
+ }
+}
+
+// Char t/T: true f/F: false
+bool GetBoolean(const char *str)
+{
+ int result;
+ unsigned char value, temp;
+
+ result = sscanf(str,"%c",&value);
+ temp = tolower(value);
+
+ if ((result == 1) && ((temp == 't') || (temp == 'f')))
+ {
+ return (temp == 't');
+ }
+ else
+ {
+ fprintf(stderr,"GetBoolean: some error occurred when parsing options.\n");
+ exit (1);
+ }
+}
+
+void GetExtension(const char *str,char *ext)
+{
+ if (strlen(str) > MAX_EXTENSION_SIZE)
+ usage();
+
+ strcpy(ext, str);
+}
+
+/* Adds an extension to a file name */
+void PutExtension(char *Flnm, char *Extension)
+{
+ char *Period; /* location of period in file name */
+ bool Samename;
+
+ /* This assumes DOS like file names */
+ /* Don't use strchr(): consider the following filename:
+ ../my.dir/file.hex
+ */
+ if ((Period = strrchr(Flnm,'.')) != NULL)
+ *(Period) = '\0';
+
+ Samename = false;
+ if (strcmp(Extension, Period+1) == 0)
+ Samename = true;
+
+ strcat(Flnm,".");
+ strcat(Flnm, Extension);
+ if (Samename)
+ {
+ fprintf (stderr,"Input and output filenames (%s) are the same.", Flnm);
+ exit(1);
+ }
+}
+
+void VerifyChecksumValue(void)
+{
+ if ((Checksum != 0) && Enable_Checksum_Error)
+ {
+ fprintf(stderr,"Checksum error in record %d: should be %02X\n",
+ Record_Nb, (256 - Checksum) & 0xFF);
+ Status_Checksum_Error = true;
+ }
+}
+
+void CrcParamsCheck(void)
+{
+ switch (Cks_Type)
+ {
+ case CRC8:
+ Crc_Poly &= 0xFF;
+ Crc_Init &= 0xFF;
+ Crc_XorOut &= 0xFF;
+ break;
+ case CRC16:
+ Crc_Poly &= 0xFFFF;
+ Crc_Init &= 0xFFFF;
+ Crc_XorOut &= 0xFFFF;
+ break;
+ case CRC32:
+ break;
+ default:
+ fprintf (stderr,"See file CRC list.txt for parameters\n");
+ exit(1);
+ }
+}
+
+void WriteMemBlock16(uint16_t Value)
+{
+ if (Endian == 1)
+ {
+ Memory_Block[Cks_Addr - Lowest_Address] = u16_hi(Value);
+ Memory_Block[Cks_Addr - Lowest_Address +1] = u16_lo(Value);
+ }
+ else
+ {
+ Memory_Block[Cks_Addr - Lowest_Address +1] = u16_hi(Value);
+ Memory_Block[Cks_Addr - Lowest_Address] = u16_lo(Value);
+ }
+}
+
+void WriteMemBlock32(uint32_t Value)
+{
+ if (Endian == 1)
+ {
+ Memory_Block[Cks_Addr - Lowest_Address] = u32_b3(Value);
+ Memory_Block[Cks_Addr - Lowest_Address +1] = u32_b2(Value);
+ Memory_Block[Cks_Addr - Lowest_Address +2] = u32_b1(Value);
+ Memory_Block[Cks_Addr - Lowest_Address +3] = u32_b0(Value);
+ }
+ else
+ {
+ Memory_Block[Cks_Addr - Lowest_Address +3] = u32_b3(Value);
+ Memory_Block[Cks_Addr - Lowest_Address +2] = u32_b2(Value);
+ Memory_Block[Cks_Addr - Lowest_Address +1] = u32_b1(Value);
+ Memory_Block[Cks_Addr - Lowest_Address] = u32_b0(Value);
+ }
+}
+
+void WriteMemory(void)
+{
+ if ((Cks_Addr >= Lowest_Address) || (Cks_Addr < Highest_Address))
+ {
+ if(Force_Value)
+ {
+ switch (Cks_Type)
+ {
+ case 0:
+ Memory_Block[Cks_Addr - Lowest_Address] = Cks_Value;
+ fprintf(stdout,"Addr %08X set to %02X\n",Cks_Addr, Cks_Value);
+ break;
+ case 1:
+ WriteMemBlock16(Cks_Value);
+ fprintf(stdout,"Addr %08X set to %04X\n",Cks_Addr, Cks_Value);
+ break;
+ case 2:
+ WriteMemBlock32(Cks_Value);
+ fprintf(stdout,"Addr %08X set to %08X\n",Cks_Addr, Cks_Value);
+ break;
+ default:;
+ }
+ }
+ else if (Cks_Addr_set)
+ {
+ /* Add a checksum to the binary file */
+ if (!Cks_range_set)
+ {
+ Cks_Start = Lowest_Address;
+ Cks_End = Highest_Address;
+ }
+ /* checksum range MUST BE in the array bounds */
+
+ if (Cks_Start < Lowest_Address)
+ {
+ fprintf(stdout,"Modifying range start from %X to %X\n",Cks_Start,Lowest_Address);
+ Cks_Start = Lowest_Address;
+ }
+ if (Cks_End > Highest_Address)
+ {
+ fprintf(stdout,"Modifying range end from %X to %X\n",Cks_End,Highest_Address);
+ Cks_End = Highest_Address;
+ }
+
+ switch (Cks_Type)
+ {
+ case CHK8_SUM:
+ {
+ uint8_t wCKS = 0;
+
+ for (unsigned int i=Cks_Start; i<=Cks_End; i++)
+ {
+ wCKS += Memory_Block[i - Lowest_Address];
+ }
+
+ fprintf(stdout,"8-bit Checksum = %02X\n",wCKS & 0xff);
+ Memory_Block[Cks_Addr - Lowest_Address] = wCKS;
+ fprintf(stdout,"Addr %08X set to %02X\n",Cks_Addr, wCKS);
+ }
+ break;
+
+ case CHK16:
+ {
+ uint16_t wCKS, w;
+
+ wCKS = 0;
+
+ if (Endian == 1)
+ {
+ for (unsigned int i=Cks_Start; i<=Cks_End; i+=2)
+ {
+ w = Memory_Block[i - Lowest_Address +1] | ((word)Memory_Block[i - Lowest_Address] << 8);
+ wCKS += w;
+ }
+ }
+ else
+ {
+ for (unsigned int i=Cks_Start; i<=Cks_End; i+=2)
+ {
+ w = Memory_Block[i - Lowest_Address] | ((word)Memory_Block[i - Lowest_Address +1] << 8);
+ wCKS += w;
+ }
+ }
+ fprintf(stdout,"16-bit Checksum = %04X\n",wCKS);
+ WriteMemBlock16(wCKS);
+ fprintf(stdout,"Addr %08X set to %04X\n",Cks_Addr, wCKS);
+ }
+ break;
+
+ case CRC8:
+ {
+ uint8_t CRC8;
+ crc_table = NoFailMalloc(256);
+
+ if (Crc_RefIn)
+ {
+ init_crc8_reflected_tab(Reflect8[Crc_Poly]);
+ CRC8 = Reflect8[Crc_Init];
+ }
+ else
+ {
+ init_crc8_normal_tab(Crc_Poly);
+ CRC8 = Crc_Init;
+ }
+
+ for (unsigned int i=Cks_Start; i<=Cks_End; i++)
+ {
+ CRC8 = update_crc8(CRC8,Memory_Block[i - Lowest_Address]);
+ }
+
+ CRC8 = (CRC8 ^ Crc_XorOut) & 0xff;
+ Memory_Block[Cks_Addr - Lowest_Address] = CRC8;
+ fprintf(stdout,"Addr %08X set to %02X\n",Cks_Addr, CRC8);
+ }
+ break;
+
+ case CRC16:
+ {
+ uint16_t CRC16;
+ crc_table = NoFailMalloc(256 * 2);
+
+ if (Crc_RefIn)
+ {
+ init_crc16_reflected_tab(Reflect16(Crc_Poly));
+ CRC16 = Reflect16(Crc_Init);
+
+ for (unsigned int i=Cks_Start; i<=Cks_End; i++)
+ {
+ CRC16 = update_crc16_reflected(CRC16,Memory_Block[i - Lowest_Address]);
+ }
+ }
+ else
+ {
+ init_crc16_normal_tab(Crc_Poly);
+ CRC16 = Crc_Init;
+
+
+ for (unsigned int i=Cks_Start; i<=Cks_End; i++)
+ {
+ CRC16 = update_crc16_normal(CRC16,Memory_Block[i - Lowest_Address]);
+ }
+ }
+
+ CRC16 = (CRC16 ^ Crc_XorOut) & 0xffff;
+ WriteMemBlock16(CRC16);
+ fprintf(stdout,"Addr %08X set to %04X\n",Cks_Addr, CRC16);
+ }
+ break;
+
+ case CRC32:
+ {
+ uint32_t CRC32;
+
+ crc_table = NoFailMalloc(256 * 4);
+ if (Crc_RefIn)
+ {
+ init_crc32_reflected_tab(Reflect32(Crc_Poly));
+ CRC32 = Reflect32(Crc_Init);
+
+ for (unsigned int i=Cks_Start; i<=Cks_End; i++)
+ {
+ CRC32 = update_crc32_reflected(CRC32,Memory_Block[i - Lowest_Address]);
+ }
+ }
+ else
+ {
+ init_crc32_normal_tab(Crc_Poly);
+ CRC32 = Crc_Init;
+
+ for (unsigned int i=Cks_Start; i<=Cks_End; i++)
+ {
+ CRC32 = update_crc32_normal(CRC32,Memory_Block[i - Lowest_Address]);
+ }
+ }
+
+ CRC32 ^= Crc_XorOut;
+ WriteMemBlock32(CRC32);
+ fprintf(stdout,"Addr %08X set to %08X\n",Cks_Addr, CRC32);
+ }
+ break;
+
+ default:
+ ;
+ }
+
+ free(crc_table);
+ }
+ }
+ else
+ {
+ fprintf (stderr,"Force/Check address outside of memory range\n");
+ }
+
+ /* write binary file */
+ fwrite (Memory_Block,
+ Max_Length,
+ 1,
+ Filout);
+
+ free (Memory_Block);
+
+ // Minimum_Block_Size is set; the memory buffer is multiple of this?
+ if (Minimum_Block_Size_Setted==true)
+ {
+ Module = Max_Length % Minimum_Block_Size;
+ if (Module)
+ {
+ Memory_Block = (byte *) NoFailMalloc(Module);
+ memset (Memory_Block,Pad_Byte,Module);
+ fwrite (Memory_Block,
+ Module,
+ 1,
+ Filout);
+ free (Memory_Block);
+ if (Max_Length_Setted==true)
+ fprintf(stdout,"Attention Max Length changed by Minimum Block Size\n");
+ }
+ }
+}
diff --git a/tools/hex2bin-2.0/src/common.h b/tools/hex2bin-2.0/src/common.h
new file mode 100644
index 0000000..64caff5
--- /dev/null
+++ b/tools/hex2bin-2.0/src/common.h
@@ -0,0 +1,116 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "binary.h"
+#include "libcrc.h"
+
+/* To compile with Microsoft Visual Studio */
+#ifdef _MSC_VER
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#if defined(MSDOS) || defined(__DOS__) || defined(__MSDOS__) || defined(_MSDOS)
+#define _IS_OPTION_(x) (((x) == '-') || ((x) == '/'))
+#else
+/* Assume unix and similar */
+/* We don't accept an option beginning with a '/' because it could be a file name. */
+#define _IS_OPTION_(x) ((x) == '-')
+#endif
+
+/* We use buffer to speed disk access. */
+#ifdef USE_FILE_BUFFERS
+#define BUFFSZ 4096
+#endif
+
+/* FIXME how to get it from the system/OS? */
+#define MAX_FILE_NAME_SIZE 81
+
+#ifdef DOS
+#define MAX_EXTENSION_SIZE 4
+#else
+#define MAX_EXTENSION_SIZE 16
+#endif
+
+/* The data records can contain 255 bytes: this means 512 characters. */
+#define MAX_LINE_SIZE 1024
+
+typedef char filetype[MAX_FILE_NAME_SIZE];
+typedef unsigned char byte;
+typedef unsigned short word;
+
+#define LAST_CHECK_METHOD 4
+
+typedef enum Crc
+{
+ CHK8_SUM =0,
+ CHK16,
+ CRC8,
+ CRC16,
+ CRC32
+} t_CRC;
+
+extern const char *Pgm_Name;
+void usage(void);
+void DisplayCheckMethods(void);
+
+void *NoFailMalloc (size_t size);
+void NoFailOpenInputFile (char *Flnm);
+void NoFailOpenOutputFile (char *Flnm);
+void GetLine(char* str,FILE *in);
+int GetBin(const char *str);
+int GetDec(const char *str);
+int GetHex(const char *str);
+bool GetBoolean(const char *str);
+void GetExtension(const char *str,char *ext);
+void PutExtension(char *Flnm, char *Extension);
+
+filetype Filename; /* string for opening files */
+char Extension[MAX_EXTENSION_SIZE]; /* filename extension for output files */
+
+FILE *Filin, /* input files */
+ *Filout; /* output files */
+
+#ifdef USE_FILE_BUFFERS
+char *FilinBuf, /* text buffer for file input */
+ *FiloutBuf; /* text buffer for file output */
+#endif
+
+int Pad_Byte;
+bool Enable_Checksum_Error;
+bool Status_Checksum_Error;
+byte Checksum;
+unsigned int Record_Nb;
+
+/* This will hold binary codes translated from hex file. */
+byte *Memory_Block;
+unsigned int Lowest_Address, Highest_Address;
+unsigned int Starting_Address;
+unsigned int Max_Length;
+unsigned int Minimum_Block_Size;
+int Module;
+bool Minimum_Block_Size_Setted;
+bool Starting_Address_Setted;
+bool Max_Length_Setted;
+bool Swap_Wordwise;
+
+int Endian;
+
+t_CRC Cks_Type;
+unsigned int Cks_Start, Cks_End, Cks_Addr, Cks_Value;
+bool Cks_range_set;
+bool Cks_Addr_set;
+bool Force_Value;
+
+unsigned int Crc_Poly, Crc_Init, Crc_XorOut;
+bool Crc_RefIn;
+bool Crc_RefOut;
+
+void VerifyChecksumValue(void);
+void CrcParamsCheck(void);
+void WriteMemBlock16(uint16_t Value);
+void WriteMemBlock32(uint32_t Value);
+void WriteMemory(void);
+
diff --git a/tools/hex2bin-2.0/src/hex2bin.1 b/tools/hex2bin-2.0/src/hex2bin.1
new file mode 100644
index 0000000..c2e5e89
--- /dev/null
+++ b/tools/hex2bin-2.0/src/hex2bin.1
@@ -0,0 +1,294 @@
+.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings. \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote. \*(C+ will
+.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
+.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
+.\" nothing in troff, for use with C<>.
+.tr \(*W-
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+. ds -- \(*W-
+. ds PI pi
+. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+. ds L" ""
+. ds R" ""
+. ds C` ""
+. ds C' ""
+'br\}
+.el\{\
+. ds -- \|\(em\|
+. ds PI \(*p
+. ds L" ``
+. ds R" ''
+. ds C`
+. ds C'
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\"
+.\" If the F register is turned on, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD. Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.\"
+.\" Avoid warning from groff about undefined register 'F'.
+.de IX
+..
+.nr rF 0
+.if \n(.g .if rF .nr rF 1
+.if (\n(rF:(\n(.g==0)) \{
+. if \nF \{
+. de IX
+. tm Index:\\$1\t\\n%\t"\\$2"
+..
+. if !\nF==2 \{
+. nr % 0
+. nr F 2
+. \}
+. \}
+.\}
+.rr rF
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear. Run. Save yourself. No user-serviceable parts.
+. \" fudge factors for nroff and troff
+.if n \{\
+. ds #H 0
+. ds #V .8m
+. ds #F .3m
+. ds #[ \f1
+. ds #] \fP
+.\}
+.if t \{\
+. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+. ds #V .6m
+. ds #F 0
+. ds #[ \&
+. ds #] \&
+.\}
+. \" simple accents for nroff and troff
+.if n \{\
+. ds ' \&
+. ds ` \&
+. ds ^ \&
+. ds , \&
+. ds ~ ~
+. ds /
+.\}
+.if t \{\
+. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+. \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+. \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+. \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+. ds : e
+. ds 8 ss
+. ds o a
+. ds d- d\h'-1'\(ga
+. ds D- D\h'-1'\(hy
+. ds th \o'bp'
+. ds Th \o'LP'
+. ds ae ae
+. ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "HEX2BIN 1"
+.TH HEX2BIN 1 "2015-02-28" "perl v5.18.2" "User Contributed Perl Documentation"
+.\" For nroff, turn off justification. Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH "NAME"
+hex2bin/mot2bin \e\- converts Intel/Motorola hex files into binary
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+hex2bin [options] file
+.PP
+Option list:
+ [\-c]
+ [\-C Poly Init RefIn RefOut XorOut]
+ [\-e extension]
+ [\-E 0|1]
+ [\-f address]
+ [\-F address value]
+ [\-k checksum type]
+ [\-l length]
+ [\-m minimum block size]
+ [\-p pad byte]
+ [\-r start end]
+ [\-s address]
+ [\-w]
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+\&\fBHex2bin\fR
+is a program that converts an Intel hex format into binary.
+It can handle the extended Intel hex format. Both the segmented
+and linear address records are supported.
+Records need not be sorted and there can be gaps between records.
+Records are assumed to be non-overlapping.
+Padding bytes may be specified and a checksum may be inserted in the
+binary file.
+.PP
+\&\fBMot2bin\fR
+does the same with Motorola hex files. It has the same features and command line
+options. 24 bit and 32 bit records are supported.
+.SH "OPTIONS"
+.IX Header "OPTIONS"
+Options can be specified in any order, with the file name at the end. Options are
+now case sensitive. All option values are specified in hexadecimal.
+.PP
+\&\fB\-c\fR
+.PP
+Enables checksum verification.
+.PP
+By default, it ignores checksum errors in the hex file, so that someone can change
+by hand some bytes with a text editor, allowing quick fixes without recompiling a source
+code all over again. This is useful when tweaking constants directly in the code or
+something similar. If you want checksum error reporting, specify the option \-c.
+.PP
+\&\fBEx.: hex2bin \-c example.hex\fR
+.PP
+If there is a checksum error somewhere, the program will continue the
+conversion anyway.
+.PP
+\&\fB\-C Poly Init RefIn RefOut XorOut\fR
+.PP
+\&\s-1CRC\s0 parameters. See the doc/CRC list.txt file for a description of common CRCs. See also
+the test/Makefile for examples of command lines. Needs \fB\-k\fR and \fB\-f\fR option.
+RefIn and RefOut parameters are specified by \fBt\fR or \fBf\fR for true or false.
+.PP
+\&\fB\-d\fR
+.PP
+Display the list of available check methods and sizes.
+.PP
+\&\fB\-e extension\fR
+.PP
+By default, the output file will have an extension \fBfilename.bin\fR.
+Another extension may be specified with this command:
+.PP
+\&\fBEx.: hex2bin \-e com example.hex\fR
+.PP
+The output file will be example.com
+.PP
+\&\fB\-E 0|1\fR
+.PP
+Endianness for writing the check result or forcing a 16\-bit value.
+ \fB0\fR: little, \fB1\fR: big.
+.PP
+By default, little endian is used.
+.PP
+\&\fB\-f address\fR
+.PP
+Address in hexadecimal for inserting the check value in the binary file. Needs \fB\-k\fR
+option to specify the check method. A range can be specified with option \fB\-r\fR.
+.PP
+\&\fB\-F address value\fR
+.PP
+Address and value of checksum to insert (force) in the binary file. Needs \fB\-k\fR
+option to specify the size. The value is written as is.
+.PP
+\&\fB\-k 0\-4\fR
+.PP
+In many cases, someone needs to insert a check value in the binary file. For example,
+a boot rom is programmed with a checksum which is verified at power-up. This feature
+uses also options \fB\-r\fR, \fB\-C\fR and \fB\-f\fR. Display the list with \fB\-d\fR.
+.PP
+Select the checksum type to insert into the binary file
+ 0: Checksum 8\-bit
+ 1: Checksum 16\-bit
+ 2: \s-1CRC8
+ 3: CRC16
+ 4: CRC32\s0
+.PP
+\&\fB\-l length\fR
+.PP
+The binary file will be padded with \s-1FF\s0 or pad bytes as specified by the option
+below, up to a maximal Length (Starting address + Length \-1 is Max Address)
+.PP
+\&\fB\-m minimum_block_size\fR
+.PP
+File Size Dimension will be a multiple of Minimum block size.
+File will be filled with Pattern.
+Length must be a power of 2 in hexadecimal [see \fB\-l\fR option]
+Attention this option is \s-1STRONGER\s0 than Maximal Length
+.PP
+\&\fB\-p pad_byte\fR
+.PP
+Pads unused locations with the specified byte.
+.PP
+By default, this byte is \s-1FF,\s0 which is the unprogrammed value for most EPROM/EEPROM/Flash.
+.PP
+\&\fBEx.: hex2bin \-p 3E example.hex\fR
+.PP
+\&\fB\-r [start] [end]\fR
+.PP
+Range to compute binary checksum over (default is min and max addresses)
+.PP
+\&\fB\-s address\fR
+.PP
+Specify the starting address of the binary file.
+.PP
+Normally, hex2bin will generate a binary file starting at the lowest address in
+the hex file. If the lowest address isn't 0000, ex: 0100, the first byte that
+should be at 0100 will be stored at address 0000 in the binary file. This may
+cause problems when using the binary file to program an \s-1EPROM.\s0
+.PP
+If you can't specify the starting address (or offset) to your \s-1EPROM\s0 programmer,
+you can specify a starting address on the command line:
+.PP
+\&\fBEx.: hex2bin \-s 0000 records_start_at_0100.hex\fR
+.PP
+The bytes will be stored in the binary file with a padding from 0000 to the
+lowest address (00FF in this case). Padding bytes are all \s-1FF\s0 by default so an \s-1EPROM\s0
+programmer can skip these bytes when programming. The padding value can be changed
+with the \-p option.
+.PP
+\&\fB\-w\fR
+.PP
+Swap wordwise (low <\-> high). Used by Microchip's \s-1MPLAB IDE\s0
+.SH "NOTES"
+.IX Header "NOTES"
+This program does minimal error checking since many hex files are
+generated by known good assemblers.
+.SH "AUTHOR Jacques Pelletier (jpelletier@ieee.org) \- version 2.0"
+.IX Header "AUTHOR Jacques Pelletier (jpelletier@ieee.org) - version 2.0"
diff --git a/tools/hex2bin-2.0/src/hex2bin.c b/tools/hex2bin-2.0/src/hex2bin.c
new file mode 100644
index 0000000..7537d8c
--- /dev/null
+++ b/tools/hex2bin-2.0/src/hex2bin.c
@@ -0,0 +1,587 @@
+/*
+ hex2bin converts an Intel hex file to binary.
+
+ Copyright (C) 2015, Jacques Pelletier
+ checksum extensions Copyright (C) 2004 Rockwell Automation
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+ Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ 20040617 Alf Lacis: Added pad byte (may not always want FF).
+ Added 'break;' to remove GNU compiler warning about label at
+ end of compound statement
+ Added PROGRAM & VERSION strings.
+
+ 20071005 PG: Improvements on options parsing
+ 20091212 JP: Corrected crash on 0 byte length data records
+ 20100402 JP: Corrected bug on physical address calculation for extended
+ linear address record.
+ ADDRESS_MASK is now calculated from MEMORY_SIZE
+
+ 20120125 Danny Schneider:
+ Added code for filling a binary file to a given Max_Length relative to
+ Starting Address if Max-Address is larger than Highest-Address
+ 20120509 Yoshimasa Nakane:
+ modified error checking (also for output file, JP)
+ 20141005 JP: added support for byte swapped hex files
+ corrected bug caused by extra LF at end or within file
+ 20141008 JP: removed junk code
+ 20141121 Slucx: added line for removing extra CR when entering file name at run time.
+ 20141122 Simone Fratini: small feature added
+ 20150116 Richard Genoud (Paratronic): correct buffer overflows/wrong results with the -l flag
+ 20150122 JP: added support for different check methods
+ 20150221 JP: rewrite of the checksum write/force value
+*/
+
+#define PROGRAM "hex2bin"
+#define VERSION "2.0"
+
+#include "common.h"
+
+#define NO_ADDRESS_TYPE_SELECTED 0
+#define LINEAR_ADDRESS 1
+#define SEGMENTED_ADDRESS 2
+
+const char *Pgm_Name = PROGRAM;
+
+int main (int argc, char *argv[])
+{
+ /* line inputted from file */
+ char Line[MAX_LINE_SIZE];
+
+ /* flag that a file was read */
+ bool Fileread;
+
+ /* cmd-line parameter # */
+ char *p;
+
+ int Param,result;
+
+ /* Application specific */
+
+ unsigned int Nb_Bytes;
+ unsigned int First_Word, Address, Segment, Upper_Address;
+ unsigned int Phys_Addr, Type;
+ unsigned int temp;
+ unsigned int Records_Start; // Lowest address of the records
+
+ /* We will assume that when one type of addressing is selected, it will be valid for all the
+ current file. Records for the other type will be ignored. */
+ unsigned int Seg_Lin_Select = NO_ADDRESS_TYPE_SELECTED;
+
+ unsigned int temp2;
+
+ byte Data_Str[MAX_LINE_SIZE];
+
+ fprintf (stdout,PROGRAM" v"VERSION", Copyright (C) 2015 Jacques Pelletier & contributors\n\n");
+
+ if (argc == 1)
+ usage();
+
+ strcpy(Extension, "bin"); /* default is for binary file extension */
+
+ /* read file */
+ Starting_Address = 0;
+
+ /*
+ use p for parsing arguments
+ use i for number of parameters to skip
+ use c for the current option
+ */
+ for (Param = 1; Param < argc; Param++)
+ {
+ int i = 0;
+ char c;
+
+ p = argv[Param];
+ c = *(p+1); /* Get option character */
+
+ if ( _IS_OPTION_(*p) )
+ {
+ // test for no space between option and parameter
+ if (strlen(p) != 2) usage();
+
+ switch(c)
+ {
+ /* file extension */
+ case 'c':
+ Enable_Checksum_Error = true;
+ i = 0;
+ break;
+ case 'd':
+ DisplayCheckMethods();
+ case 'e':
+ GetExtension(argv[Param + 1],Extension);
+ i = 1; /* add 1 to Param */
+ break;
+ case 'E':
+ Endian = GetBin(argv[Param + 1]);
+ i = 1; /* add 1 to Param */
+ break;
+ case 'f':
+ Cks_Addr = GetHex(argv[Param + 1]);
+ Cks_Addr_set = true;
+ i = 1; /* add 1 to Param */
+ break;
+ case 'F':
+ Cks_Addr = GetHex(argv[Param + 1]);
+ Cks_Value = GetHex(argv[Param + 2]);
+ Force_Value = true;
+ i = 2; /* add 2 to Param */
+ break;
+ case 'k':
+ Cks_Type = GetHex(argv[Param + 1]);
+ {
+ if (Cks_Type > LAST_CHECK_METHOD) usage();
+ }
+ i = 1; /* add 1 to Param */
+ break;
+ case 'l':
+ Max_Length = GetHex(argv[Param + 1]);
+ if (Max_Length > 0x800000)
+ {
+ fprintf(stderr,"Max_Length = %u\n", Max_Length);
+ exit(1);
+ }
+ Max_Length_Setted = true;
+ i = 1; /* add 1 to Param */
+ break;
+ case 'm':
+ Minimum_Block_Size = GetHex(argv[Param + 1]);
+ Minimum_Block_Size_Setted = true;
+ i = 1; /* add 1 to Param */
+ break;
+ case 'p':
+ Pad_Byte = GetHex(argv[Param + 1]);
+ i = 1; /* add 1 to Param */
+ break;
+ case 'r':
+ Cks_Start = GetHex(argv[Param + 1]);
+ Cks_End = GetHex(argv[Param + 2]);
+ Cks_range_set = true;
+ i = 2; /* add 2 to Param */
+ break;
+ case 's':
+ Starting_Address = GetHex(argv[Param + 1]);
+ Starting_Address_Setted = true;
+ i = 1; /* add 1 to Param */
+ break;
+ case 'w':
+ Swap_Wordwise = true;
+ i = 0;
+ break;
+ case 'C':
+ Crc_Poly = GetHex(argv[Param + 1]);
+ Crc_Init = GetHex(argv[Param + 2]);
+ Crc_RefIn = GetBoolean(argv[Param + 3]);
+ Crc_RefOut = GetBoolean(argv[Param + 4]);
+ Crc_XorOut = GetHex(argv[Param + 5]);
+ CrcParamsCheck();
+ i = 5; /* add 5 to Param */
+ break;
+
+ case '?':
+ case 'h':
+ default:
+ usage();
+ } /* switch */
+
+ /* Last parameter is not a filename */
+ if (Param == argc-1) usage();
+
+ /* if (Param + i) < (argc -1) */
+ if (Param < argc -1 -i) Param += i;
+ else usage();
+
+ }
+ else
+ break;
+ /* if option */
+ } /* for Param */
+
+ /* when user enters input file name */
+
+ /* Assume last parameter is filename */
+ strcpy(Filename,argv[argc -1]);
+
+ /* Just a normal file name */
+ NoFailOpenInputFile (Filename);
+ PutExtension(Filename, Extension);
+ NoFailOpenOutputFile(Filename);
+ Fileread = true;
+
+ /* To begin, assume the lowest address is at the end of the memory.
+ While reading each records, subsequent addresses will lower this number.
+ At the end of the input file, this value will be the lowest address.
+
+ A similar assumption is made for highest address. It starts at the
+ beginning of memory. While reading each records, subsequent addresses will raise this number.
+ At the end of the input file, this value will be the highest address. */
+ Lowest_Address = (unsigned int)-1;
+ Highest_Address = 0;
+ Records_Start = 0;
+ Segment = 0;
+ Upper_Address = 0;
+ Record_Nb = 0; // Used for reporting errors
+
+ /* get highest and lowest addresses so that we can allocate the right size */
+ do
+ {
+ unsigned int i;
+
+ /* Read a line from input file. */
+ GetLine(Line,Filin);
+ Record_Nb++;
+
+ /* Remove carriage return/line feed at the end of line. */
+ i = strlen(Line);
+
+ if (--i != 0)
+ {
+ if (Line[i] == '\n') Line[i] = '\0';
+
+ /* Scan the first two bytes and nb of bytes.
+ The two bytes are read in First_Word since its use depend on the
+ record type: if it's an extended address record or a data record.
+ */
+ result = sscanf (Line, ":%2x%4x%2x%s",&Nb_Bytes,&First_Word,&Type,Data_Str);
+ if (result != 4) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+
+ p = (char *) Data_Str;
+
+ /* If we're reading the last record, ignore it. */
+ switch (Type)
+ {
+ /* Data record */
+ case 0:
+ if (Nb_Bytes == 0)
+ break;
+
+ Address = First_Word;
+
+ if (Seg_Lin_Select == SEGMENTED_ADDRESS)
+ {
+ Phys_Addr = (Segment << 4) + Address;
+ }
+ else
+ {
+ /* LINEAR_ADDRESS or NO_ADDRESS_TYPE_SELECTED
+ Upper_Address = 0 as specified in the Intel spec. until an extended address
+ record is read. */
+ Phys_Addr = ((Upper_Address << 16) + Address);
+ }
+
+ /* Set the lowest address as base pointer. */
+ if (Phys_Addr < Lowest_Address)
+ Lowest_Address = Phys_Addr;
+
+ /* Same for the top address. */
+ temp = Phys_Addr + Nb_Bytes -1;
+
+ if (temp > Highest_Address)
+ Highest_Address = temp;
+
+ break;
+
+ case 2:
+ /* First_Word contains the offset. It's supposed to be 0000 so
+ we ignore it. */
+
+ /* First extended segment address record ? */
+ if (Seg_Lin_Select == NO_ADDRESS_TYPE_SELECTED)
+ Seg_Lin_Select = SEGMENTED_ADDRESS;
+
+ /* Then ignore subsequent extended linear address records */
+ if (Seg_Lin_Select == SEGMENTED_ADDRESS)
+ {
+ result = sscanf (p, "%4x%2x",&Segment,&temp2);
+ if (result != 2) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+
+ /* Update the current address. */
+ Phys_Addr = (Segment << 4);
+ }
+ else
+ {
+ fprintf(stderr,"Ignored extended linear address record %d\n", Record_Nb);
+ }
+ break;
+
+ case 4:
+ /* First_Word contains the offset. It's supposed to be 0000 so
+ we ignore it. */
+
+ /* First extended linear address record ? */
+ if (Seg_Lin_Select == NO_ADDRESS_TYPE_SELECTED)
+ Seg_Lin_Select = LINEAR_ADDRESS;
+
+ /* Then ignore subsequent extended segment address records */
+ if (Seg_Lin_Select == LINEAR_ADDRESS)
+ {
+ result = sscanf (p, "%4x%2x",&Upper_Address,&temp2);
+ if (result != 2) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+
+ /* Update the current address. */
+ Phys_Addr = (Upper_Address << 16);
+ }
+ else
+ {
+ fprintf(stderr,"Ignored extended segment address record %d\n", Record_Nb);
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ while (!feof (Filin));
+
+ rewind(Filin);
+ Segment = 0;
+ Upper_Address = 0;
+ Record_Nb = 0;
+
+ if (Starting_Address_Setted == true)
+ {
+ Records_Start = Lowest_Address;
+ Lowest_Address = Starting_Address;
+ }
+ else
+ {
+ Records_Start = Lowest_Address;
+ Starting_Address = Lowest_Address;
+ }
+
+ if (Max_Length_Setted == false)
+ Max_Length = Highest_Address - Lowest_Address + 1;
+ else
+ Highest_Address = Lowest_Address + Max_Length - 1;
+
+ /* Now, that we know the buffer size, we can allocate it. */
+ /* allocate a buffer */
+ Memory_Block = (byte *) NoFailMalloc(Max_Length);
+
+ /* For EPROM or FLASH memory types, fill unused bytes with FF or the value specified by the p option */
+ memset (Memory_Block,Pad_Byte,Max_Length);
+
+ /* Read the file & process the lines. */
+ do /* repeat until EOF(Filin) */
+ {
+ unsigned int i;
+
+ /* Read a line from input file. */
+ GetLine(Line,Filin);
+ Record_Nb++;
+
+ /* Remove carriage return/line feed at the end of line. */
+ i = strlen(Line);
+
+ //fprintf(stderr,"Record: %d; length: %d\n", Record_Nb, i);
+
+ if (--i != 0)
+ {
+ if (Line[i] == '\n') Line[i] = '\0';
+
+ /* Scan the first two bytes and nb of bytes.
+ The two bytes are read in First_Word since its use depend on the
+ record type: if it's an extended address record or a data record.
+ */
+ result = sscanf (Line, ":%2x%4x%2x%s",&Nb_Bytes,&First_Word,&Type,Data_Str);
+ if (result != 4) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+
+ Checksum = Nb_Bytes + (First_Word >> 8) + (First_Word & 0xFF) + Type;
+
+ p = (char *) Data_Str;
+
+ /* If we're reading the last record, ignore it. */
+ switch (Type)
+ {
+ /* Data record */
+ case 0:
+ if (Nb_Bytes == 0)
+ {
+ fprintf(stderr,"0 byte length Data record ignored\n");
+ break;
+ }
+
+ Address = First_Word;
+
+ if (Seg_Lin_Select == SEGMENTED_ADDRESS)
+ Phys_Addr = (Segment << 4) + Address;
+ else
+ /* LINEAR_ADDRESS or NO_ADDRESS_TYPE_SELECTED
+ Upper_Address = 0 as specified in the Intel spec. until an extended address
+ record is read. */
+ Phys_Addr = ((Upper_Address << 16) + Address);
+
+ /* Check that the physical address stays in the buffer's range. */
+ if ((Phys_Addr >= Lowest_Address) && (Phys_Addr <= Highest_Address))
+ {
+ /* The memory block begins at Lowest_Address */
+ Phys_Addr -= Lowest_Address;
+
+ /* Read the Data bytes. */
+ /* Bytes are written in the Memory block even if checksum is wrong. */
+ i = Nb_Bytes;
+
+ do
+ {
+ result = sscanf (p, "%2x",&temp2);
+ if (result != 1) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+ p += 2;
+
+ /* Check that the physical address stays in the buffer's range. */
+ if (Phys_Addr < Max_Length)
+ {
+ /* Overlapping record will erase the pad bytes */
+ if (Swap_Wordwise)
+ {
+ if (Memory_Block[Phys_Addr ^ 1] != Pad_Byte) fprintf(stderr,"Overlapped record detected\n");
+ Memory_Block[Phys_Addr++ ^ 1] = temp2;
+ }
+ else
+ {
+ if (Memory_Block[Phys_Addr] != Pad_Byte) fprintf(stderr,"Overlapped record detected\n");
+ Memory_Block[Phys_Addr++] = temp2;
+ }
+
+ Checksum = (Checksum + temp2) & 0xFF;
+ }
+ }
+ while (--i != 0);
+
+ /* Read the Checksum value. */
+ result = sscanf (p, "%2x",&temp2);
+ if (result != 1) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+
+ /* Verify Checksum value. */
+ Checksum = (Checksum + temp2) & 0xFF;
+ VerifyChecksumValue();
+ }
+ else
+ {
+ if (Seg_Lin_Select == SEGMENTED_ADDRESS)
+ fprintf(stderr,"Data record skipped at %4X:%4X\n",Segment,Address);
+ else
+ fprintf(stderr,"Data record skipped at %8X\n",Phys_Addr);
+ }
+
+ break;
+
+ /* End of file record */
+ case 1:
+ /* Simply ignore checksum errors in this line. */
+ break;
+
+ /* Extended segment address record */
+ case 2:
+ /* First_Word contains the offset. It's supposed to be 0000 so
+ we ignore it. */
+
+ /* First extended segment address record ? */
+ if (Seg_Lin_Select == NO_ADDRESS_TYPE_SELECTED)
+ Seg_Lin_Select = SEGMENTED_ADDRESS;
+
+ /* Then ignore subsequent extended linear address records */
+ if (Seg_Lin_Select == SEGMENTED_ADDRESS)
+ {
+ result = sscanf (p, "%4x%2x",&Segment,&temp2);
+ if (result != 2) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+
+ /* Update the current address. */
+ Phys_Addr = (Segment << 4);
+
+ /* Verify Checksum value. */
+ Checksum = (Checksum + (Segment >> 8) + (Segment & 0xFF) + temp2) & 0xFF;
+ VerifyChecksumValue();
+ }
+ break;
+
+ /* Start segment address record */
+ case 3:
+ /* Nothing to be done since it's for specifying the starting address for
+ execution of the binary code */
+ break;
+
+ /* Extended linear address record */
+ case 4:
+ /* First_Word contains the offset. It's supposed to be 0000 so
+ we ignore it. */
+
+ /* First extended linear address record ? */
+ if (Seg_Lin_Select == NO_ADDRESS_TYPE_SELECTED)
+ Seg_Lin_Select = LINEAR_ADDRESS;
+
+ /* Then ignore subsequent extended segment address records */
+ if (Seg_Lin_Select == LINEAR_ADDRESS)
+ {
+ result = sscanf (p, "%4x%2x",&Upper_Address,&temp2);
+ if (result != 2) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+
+ /* Update the current address. */
+ Phys_Addr = (Upper_Address << 16);
+
+ /* Verify Checksum value. */
+ Checksum = (Checksum + (Upper_Address >> 8) + (Upper_Address & 0xFF) + temp2)
+ & 0xFF;
+ VerifyChecksumValue();
+ }
+ break;
+
+ /* Start linear address record */
+ case 5:
+ /* Nothing to be done since it's for specifying the starting address for
+ execution of the binary code */
+ break;
+ default:
+ fprintf(stderr,"Unknown record type\n");
+ break;
+ }
+ }
+ }
+ while (!feof (Filin));
+ /*-----------------------------------------------------------------------------*/
+
+ fprintf(stdout,"Binary file start = %08X\n",Lowest_Address);
+ fprintf(stdout,"Records start = %08X\n",Records_Start);
+ fprintf(stdout,"Highest address = %08X\n",Highest_Address);
+ fprintf(stdout,"Pad Byte = %X\n", Pad_Byte);
+
+ WriteMemory();
+
+#ifdef USE_FILE_BUFFERS
+ free (FilinBuf);
+ free (FiloutBuf);
+#endif
+
+ fclose (Filin);
+ fclose (Filout);
+
+ if (Status_Checksum_Error && Enable_Checksum_Error)
+ {
+ fprintf(stderr,"Checksum error detected.\n");
+ return 1;
+ }
+
+ if (!Fileread)
+ usage();
+ return 0;
+}
diff --git a/tools/hex2bin-2.0/src/hex2bin.pod b/tools/hex2bin-2.0/src/hex2bin.pod
new file mode 100644
index 0000000..a8eb238
--- /dev/null
+++ b/tools/hex2bin-2.0/src/hex2bin.pod
@@ -0,0 +1,161 @@
+HEX2BIN 1 "2015 february 22nd" "Hex2bin Version 2.0"
+=head1 NAME
+
+hex2bin/mot2bin \- converts Intel/Motorola hex files into binary
+
+=head1 SYNOPSIS
+
+hex2bin [options] file
+
+Option list:
+ [-c]
+ [-C Poly Init RefIn RefOut XorOut]
+ [-e extension]
+ [-E 0|1]
+ [-f address]
+ [-F address value]
+ [-k checksum type]
+ [-l length]
+ [-m minimum block size]
+ [-p pad byte]
+ [-r start end]
+ [-s address]
+ [-w]
+
+=head1 DESCRIPTION
+
+B<Hex2bin>
+is a program that converts an Intel hex format into binary.
+It can handle the extended Intel hex format. Both the segmented
+and linear address records are supported.
+Records need not be sorted and there can be gaps between records.
+Records are assumed to be non-overlapping.
+Padding bytes may be specified and a checksum may be inserted in the
+binary file.
+
+B<Mot2bin>
+does the same with Motorola hex files. It has the same features and command line
+options. 24 bit and 32 bit records are supported.
+
+=head1 OPTIONS
+
+Options can be specified in any order, with the file name at the end. Options are
+now case sensitive. All option values are specified in hexadecimal.
+
+B<-c>
+
+Enables checksum verification.
+
+By default, it ignores checksum errors in the hex file, so that someone can change
+by hand some bytes with a text editor, allowing quick fixes without recompiling a source
+code all over again. This is useful when tweaking constants directly in the code or
+something similar. If you want checksum error reporting, specify the option -c.
+
+B<Ex.: hex2bin -c example.hex>
+
+If there is a checksum error somewhere, the program will continue the
+conversion anyway.
+
+B<-C Poly Init RefIn RefOut XorOut>
+
+CRC parameters. See the doc/CRC list.txt file for a description of common CRCs. See also
+the test/Makefile for examples of command lines. Needs B<-k> and B<-f> option.
+RefIn and RefOut parameters are specified by B<t> or B<f> for true or false.
+
+B<-d>
+
+Display the list of available check methods and sizes.
+
+B<-e extension>
+
+By default, the output file will have an extension B<filename.bin>.
+Another extension may be specified with this command:
+
+B<Ex.: hex2bin -e com example.hex>
+
+The output file will be example.com
+
+B<-E 0|1>
+
+Endianness for writing the check result or forcing a 16-bit value.
+ B<0>: little, B<1>: big.
+
+By default, little endian is used.
+
+B<-f address>
+
+Address in hexadecimal for inserting the check value in the binary file. Needs B<-k>
+option to specify the check method. A range can be specified with option B<-r>.
+
+B<-F address value>
+
+Address and value of checksum to insert (force) in the binary file. Needs B<-k>
+option to specify the size. The value is written as is.
+
+B<-k 0-4>
+
+In many cases, someone needs to insert a check value in the binary file. For example,
+a boot rom is programmed with a checksum which is verified at power-up. This feature
+uses also options B<-r>, B<-C> and B<-f>. Display the list with B<-d>.
+
+Select the checksum type to insert into the binary file
+ 0: Checksum 8-bit
+ 1: Checksum 16-bit
+ 2: CRC8
+ 3: CRC16
+ 4: CRC32
+
+B<-l length>
+
+The binary file will be padded with FF or pad bytes as specified by the option
+below, up to a maximal Length (Starting address + Length -1 is Max Address)
+
+B<-m minimum_block_size>
+
+File Size Dimension will be a multiple of Minimum block size.
+File will be filled with Pattern.
+Length must be a power of 2 in hexadecimal [see B<-l> option]
+Attention this option is STRONGER than Maximal Length
+
+B<-p pad_byte>
+
+Pads unused locations with the specified byte.
+
+By default, this byte is FF, which is the unprogrammed value for most EPROM/EEPROM/Flash.
+
+B<Ex.: hex2bin -p 3E example.hex>
+
+B<-r [start] [end]>
+
+Range to compute binary checksum over (default is min and max addresses)
+
+B<-s address>
+
+Specify the starting address of the binary file.
+
+Normally, hex2bin will generate a binary file starting at the lowest address in
+the hex file. If the lowest address isn't 0000, ex: 0100, the first byte that
+should be at 0100 will be stored at address 0000 in the binary file. This may
+cause problems when using the binary file to program an EPROM.
+
+If you can't specify the starting address (or offset) to your EPROM programmer,
+you can specify a starting address on the command line:
+
+B<Ex.: hex2bin -s 0000 records_start_at_0100.hex>
+
+The bytes will be stored in the binary file with a padding from 0000 to the
+lowest address (00FF in this case). Padding bytes are all FF by default so an EPROM
+programmer can skip these bytes when programming. The padding value can be changed
+with the -p option.
+
+B<-w>
+
+Swap wordwise (low <-> high). Used by Microchip's MPLAB IDE
+
+=head1 NOTES
+
+This program does minimal error checking since many hex files are
+generated by known good assemblers.
+
+=head1 AUTHOR
+Jacques Pelletier (jpelletier@ieee.org) - version 2.0
diff --git a/tools/hex2bin-2.0/src/libcrc.c b/tools/hex2bin-2.0/src/libcrc.c
new file mode 100644
index 0000000..02bcd4b
--- /dev/null
+++ b/tools/hex2bin-2.0/src/libcrc.c
@@ -0,0 +1,204 @@
+/*********************************************************************
+ * *
+ * Library : lib_crc *
+ * File : lib_crc.c *
+ * Author : Lammert Bies 1999-2008 *
+ * E-mail : info@lammertbies.nl *
+ * Language : ANSI C *
+ * *
+ * *
+ * Description *
+ * =========== *
+ * *
+ * The file lib_crc.c contains the private and public func- *
+ * tions used for the calculation of CRC-16, CRC-CCITT and *
+ * CRC-32 cyclic redundancy values. *
+ * *
+ * *
+ * Dependencies *
+ * ============ *
+ * *
+ * libcrc.h CRC definitions and prototypes *
+ * *
+ ********************************************************************/
+#include <stdint.h>
+
+#ifndef G_GUINT64_CONSTANT
+#define G_GUINT64_CONSTANT(val) (val##UL)
+#endif
+
+void *crc_table;
+
+/* private */
+
+void init_crc8_normal_tab(uint8_t polynom)
+{
+ int i, j;
+ uint8_t crc;
+ uint8_t *p;
+
+ p = (uint8_t *) crc_table;
+
+ for (i=0; i<256; i++)
+ {
+ crc = (uint8_t) i;
+
+ for (j=0; j<8; j++)
+ {
+ if (crc & 0x80) crc = (crc << 1) ^ polynom;
+ else crc <<= 1;
+ }
+ *p++ = crc;
+ }
+}
+
+void init_crc8_reflected_tab(uint8_t polynom)
+{
+ int i, j;
+ uint8_t crc;
+ uint8_t *p;
+
+ p = (uint8_t *) crc_table;
+
+ for (i=0; i<256; i++)
+ {
+ crc = (uint8_t) i;
+
+ for (j=0; j<8; j++)
+ {
+ if (crc & 0x01) crc = (crc >> 1) ^ polynom;
+ else crc >>= 1;
+ }
+ *p++ = crc;
+ }
+}
+
+/* Common routines for calculations */
+void init_crc16_normal_tab(uint16_t polynom)
+{
+ int i, j;
+ uint16_t crc;
+ uint16_t *p;
+
+ p = (uint16_t *) crc_table;
+
+ for (i=0; i<256; i++)
+ {
+ crc = ((uint16_t) i) << 8;
+
+ for (j=0; j<8; j++)
+ {
+ if ( crc & 0x8000 ) crc = ( crc << 1 ) ^ polynom;
+ else crc <<= 1;
+ }
+ *p++ = crc;
+ }
+}
+
+void init_crc16_reflected_tab(uint16_t polynom)
+{
+ int i, j;
+ uint16_t crc;
+ uint16_t *p;
+
+ p = (uint16_t *) crc_table;
+
+ for (i=0; i<256; i++)
+ {
+ crc = (uint16_t) i;
+
+ for (j=0; j<8; j++)
+ {
+ if ( crc & 0x0001 ) crc = ( crc >> 1 ) ^ polynom;
+ else crc >>= 1;
+ }
+ *p++ = crc;
+ }
+}
+
+void init_crc32_normal_tab(uint32_t polynom)
+{
+ int i, j;
+ uint32_t crc;
+ uint32_t *p;
+
+ p = (uint32_t *) crc_table;
+
+ for (i=0; i<256; i++)
+ {
+ crc = ((uint32_t) i) << 24;
+
+ for (j=0; j<8; j++)
+ {
+ if ( crc & 0x80000000L ) crc = ( crc << 1 ) ^ polynom;
+ else crc <<= 1;
+ }
+ *p++ = crc;
+ }
+}
+
+void init_crc32_reflected_tab(uint32_t polynom)
+{
+ int i, j;
+ uint32_t crc;
+ uint32_t *p;
+
+ p = (uint32_t *) crc_table;
+
+ for (i=0; i<256; i++)
+ {
+ crc = (uint32_t) i;
+
+ for (j=0; j<8; j++)
+ {
+ if ( crc & 0x00000001L ) crc = ( crc >> 1 ) ^ polynom;
+ else crc >>= 1;
+ }
+ *p++ = crc;
+ }
+}
+
+/* Common routines for calculations */
+
+uint8_t update_crc8(uint8_t crc, uint8_t c)
+{
+ return (((uint8_t *) crc_table)[crc ^ c]);
+}
+
+uint16_t update_crc16_normal(uint16_t crc, char c )
+{
+ uint16_t short_c;
+
+ short_c = 0x00ff & (uint16_t) c;
+
+ /* Normal form */
+ return (crc << 8) ^ ((uint16_t *) crc_table)[(crc >> 8) ^ short_c];
+}
+
+uint16_t update_crc16_reflected(uint16_t crc, char c )
+{
+ uint16_t short_c;
+
+ short_c = 0x00ff & (uint16_t) c;
+
+ /* Reflected form */
+ return (crc >> 8) ^ ((uint16_t *) crc_table)[(crc ^ short_c) & 0xff];
+}
+
+uint32_t update_crc32_normal(uint32_t crc, char c )
+{
+ uint32_t long_c;
+
+ long_c = 0x000000ffL & (uint32_t) c;
+
+ return (crc << 8) ^ ((uint32_t *) crc_table)[((crc >> 24) ^ long_c) & 0xff];
+}
+
+uint32_t update_crc32_reflected(uint32_t crc, char c )
+{
+ uint32_t long_c;
+
+ long_c = 0x000000ffL & (uint32_t) c;
+
+ return (crc >> 8) ^ ((uint32_t *) crc_table)[(crc ^ long_c) & 0xff];
+}
diff --git a/tools/hex2bin-2.0/src/libcrc.h b/tools/hex2bin-2.0/src/libcrc.h
new file mode 100644
index 0000000..39f20d0
--- /dev/null
+++ b/tools/hex2bin-2.0/src/libcrc.h
@@ -0,0 +1,44 @@
+ /********************************************************************
+ * *
+ * Library : lib_crc *
+ * File : lib_crc.h *
+ * Author : Lammert Bies 1999-2008 *
+ * E-mail : info@lammertbies.nl *
+ * Language : ANSI C *
+ * *
+ * *
+ * Description *
+ * =========== *
+ * *
+ * The file lib_crc.h contains public definitions and proto- *
+ * types for the CRC functions present in lib_crc.c. *
+ * *
+ * *
+ * Dependencies *
+ * ============ *
+ * *
+ * none *
+ * *
+ * *
+ ********************************************************************/
+#ifndef _LIBCRC_H_
+#define _LIBCRC_H_
+
+void *crc_table;
+
+void init_crc8_normal_tab(uint8_t polynom);
+void init_crc8_reflected_tab(uint8_t polynom);
+
+void init_crc16_normal_tab(uint16_t polynom);
+void init_crc16_reflected_tab(uint16_t polynom);
+void init_crc32_normal_tab(uint32_t polynom);
+void init_crc32_reflected_tab(uint32_t polynom);
+
+uint8_t update_crc8(uint8_t crc, uint8_t c);
+
+uint16_t update_crc16_normal(uint16_t crc, char c );
+uint16_t update_crc16_reflected(uint16_t crc, char c );
+uint32_t update_crc32_normal(uint32_t crc, char c );
+uint32_t update_crc32_reflected(uint32_t crc, char c );
+
+#endif /* _LIBCRC_H_ */
diff --git a/tools/hex2bin-2.0/src/mot2bin.c b/tools/hex2bin-2.0/src/mot2bin.c
new file mode 100644
index 0000000..9e0e23c
--- /dev/null
+++ b/tools/hex2bin-2.0/src/mot2bin.c
@@ -0,0 +1,518 @@
+/*
+mot2bin converts a Motorola hex file to binary.
+
+Copyright (C) 2015, Jacques Pelletier
+checksum extensions Copyright (C) 2004 Rockwell Automation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+20040617 Alf Lacis: Added pad byte (may not always want FF).
+ Added initialisation to Checksum to remove GNU
+ compiler warning about possible uninitialised usage
+ Added 2x'break;' to remove GNU compiler warning about label at
+ end of compound statement
+ Added PROGRAM & VERSION strings.
+
+20071005 PG: Improvements on options parsing
+20091212 JP: Corrected crash on 0 byte length data records
+20100402 JP: ADDRESS_MASK is now calculated from MEMORY_SIZE
+
+20120125 Danny Schneider:
+ Added code for filling a binary file to a given Max_Length relative to
+ Starting Address if Max-Address is larger than Highest-Address
+20120509 Yoshimasa Nakane:
+ modified error checking (also for output file, JP)
+20141005 JP: added support for byte swapped hex files
+ corrected bug caused by extra LF at end or within file
+20141121 Slucx: added line for removing extra CR when entering file name at run time.
+20150116 Richard Genoud (Paratronic): correct buffer overflows/wrong results with the -l flag
+20150122 JP: added support for different check methods
+20150221 JP: rewrite of the checksum write/force value
+*/
+
+#define PROGRAM "mot2bin"
+#define VERSION "2.0"
+
+#include "common.h"
+
+const char *Pgm_Name = PROGRAM;
+
+int main (int argc, char *argv[])
+{
+ /* line inputted from file */
+ char Line[MAX_LINE_SIZE];
+
+ /* flag that a file was read */
+ bool Fileread;
+
+ /* cmd-line parameter # */
+ char *p;
+
+ int Param, result;
+
+ /* Application specific */
+
+ unsigned int Nb_Bytes;
+ unsigned int First_Word, Address;
+
+ unsigned int Phys_Addr, Type;
+ unsigned int Exec_Address;
+ unsigned int temp;
+ unsigned int Record_Count, Record_Checksum;
+ unsigned int Records_Start; // Lowest address of the records
+
+ unsigned int temp2;
+
+ byte Data_Str[MAX_LINE_SIZE];
+
+ fprintf (stdout,PROGRAM" v"VERSION", Copyright (C) 2015 Jacques Pelletier & contributors\n\n");
+
+ if (argc == 1)
+ usage();
+
+ strcpy(Extension, "bin"); /* default is for binary file extension */
+
+ /* read file */
+ Starting_Address = 0;
+
+ /*
+ use p for parsing arguments
+ use i for number of parameters to skip
+ use c for the current option
+ */
+ for (Param = 1; Param < argc; Param++)
+ {
+ int i = 0;
+ char c;
+
+ p = argv[Param];
+ c = *(p+1); /* Get option character */
+
+ if ( _IS_OPTION_(*p) )
+ {
+ // test for no space between option and parameter
+ if (strlen(p) != 2) usage();
+
+ switch(c)
+ {
+ /* file extension */
+ case 'c':
+ Enable_Checksum_Error = true;
+ i = 0;
+ break;
+ case 'd':
+ DisplayCheckMethods();
+ case 'e':
+ GetExtension(argv[Param + 1],Extension);
+ i = 1; /* add 1 to Param */
+ break;
+ case 'f':
+ Cks_Addr = GetHex(argv[Param + 1]);
+ Cks_Addr_set = true;
+ i = 1; /* add 1 to Param */
+ break;
+ case 'F':
+ Cks_Addr = GetHex(argv[Param + 1]);
+ Cks_Value = GetHex(argv[Param + 2]);
+ Force_Value = true;
+ i = 2; /* add 2 to Param */
+ break;
+ case 'k':
+ Cks_Type = GetHex(argv[Param + 1]);
+ {
+ if (Cks_Type > LAST_CHECK_METHOD) usage();
+ }
+ i = 1; /* add 1 to Param */
+ break;
+ case 'l':
+ Max_Length = GetHex(argv[Param + 1]);
+ Max_Length_Setted = true;
+ i = 1; /* add 1 to Param */
+ break;
+ case 'm':
+ Minimum_Block_Size = GetHex(argv[Param + 1]);
+ Minimum_Block_Size_Setted = true;
+ i = 1; /* add 1 to Param */
+ break;
+ case 'p':
+ Pad_Byte = GetHex(argv[Param + 1]);
+ i = 1; /* add 1 to Param */
+ break;
+ case 'r':
+ Cks_Start = GetHex(argv[Param + 1]);
+ Cks_End = GetHex(argv[Param + 2]);
+ Cks_range_set = true;
+ i = 2; /* add 2 to Param */
+ break;
+ case 's':
+ Starting_Address = GetHex(argv[Param + 1]);
+ Starting_Address_Setted = true;
+ i = 1; /* add 1 to Param */
+ break;
+ case 'w':
+ Swap_Wordwise = true;
+ i = 0;
+ break;
+ case 'C':
+ Crc_Poly = GetHex(argv[Param + 1]);
+ Crc_Init = GetHex(argv[Param + 2]);
+ Crc_RefIn = GetBoolean(argv[Param + 3]);
+ Crc_RefOut = GetBoolean(argv[Param + 4]);
+ Crc_XorOut = GetHex(argv[Param + 5]);
+ CrcParamsCheck();
+ i = 5; /* add 5 to Param */
+ break;
+
+ case '?':
+ case 'h':
+ default:
+ usage();
+ } /* switch */
+
+ /* Last parameter is not a filename */
+ if (Param == argc-1) usage();
+
+ // fprintf(stderr,"Param: %d, option: %c\n",Param,c);
+
+ /* if (Param + i) < (argc -1) */
+ if (Param < argc -1 -i) Param += i;
+ else usage();
+
+ }
+ else
+ break;
+ /* if option */
+ } /* for Param */
+
+ /* when user enters input file name */
+
+ /* Assume last parameter is filename */
+ strcpy(Filename,argv[argc -1]);
+
+ /* Just a normal file name */
+ NoFailOpenInputFile (Filename);
+ PutExtension(Filename, Extension);
+ NoFailOpenOutputFile(Filename);
+ Fileread = true;
+
+ /* To begin, assume the lowest address is at the end of the memory.
+ While reading each records, subsequent addresses will lower this number.
+ At the end of the input file, this value will be the lowest address.
+
+ A similar assumption is made for highest address. It starts at the
+ beginning of memory. While reading each records, subsequent addresses will raise this number.
+ At the end of the input file, this value will be the highest address. */
+ Lowest_Address = (unsigned int)-1;
+ Highest_Address = 0;
+ Records_Start = 0;
+ Record_Nb = 0;
+
+ /* get highest and lowest addresses so that we can allocate the right size */
+ do
+ {
+ unsigned int i;
+
+ /* Read a line from input file. */
+ GetLine(Line,Filin);
+ Record_Nb++;
+
+ /* Remove carriage return/line feed at the end of line. */
+ i = strlen(Line);
+
+ if (--i != 0)
+ {
+ if (Line[i] == '\n') Line[i] = '\0';
+
+ p = (char *) Data_Str;
+
+ switch(Line[1])
+ {
+ case '0':
+ break;
+
+ /* 16 bits address */
+ case '1':
+ result = sscanf (Line,"S%1x%2x%4x",&Type,&Nb_Bytes,&First_Word);
+ if (result != 3) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+
+ /* Adjust Nb_Bytes for the number of data bytes */
+ Nb_Bytes = Nb_Bytes - 3;
+ break;
+
+ /* 24 bits address */
+ case '2':
+ result = sscanf (Line,"S%1x%2x%6x",&Type,&Nb_Bytes,&First_Word);
+ if (result != 3) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+
+ /* Adjust Nb_Bytes for the number of data bytes */
+ Nb_Bytes = Nb_Bytes - 4;
+ break;
+
+ /* 32 bits address */
+ case '3':
+ result = sscanf (Line,"S%1x%2x%8x",&Type,&Nb_Bytes,&First_Word);
+ if (result != 3) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+
+ /* Adjust Nb_Bytes for the number of data bytes */
+ Nb_Bytes = Nb_Bytes - 5;
+ break;
+ }
+
+ Phys_Addr = First_Word;
+
+ /* Set the lowest address as base pointer. */
+ if (Phys_Addr < Lowest_Address)
+ Lowest_Address = Phys_Addr;
+
+ /* Same for the top address. */
+ temp = Phys_Addr + Nb_Bytes -1;
+
+ if (temp > Highest_Address)
+ Highest_Address = temp;
+ }
+ }
+ while (!feof (Filin));
+
+ if (Starting_Address_Setted == true)
+ {
+ Records_Start = Lowest_Address;
+ Lowest_Address = Starting_Address;
+ }
+ else
+ {
+ Records_Start = Lowest_Address;
+ Starting_Address = Lowest_Address;
+ }
+
+ if (Max_Length_Setted == false)
+ Max_Length = Highest_Address - Lowest_Address + 1;
+ else
+ Highest_Address = Lowest_Address + Max_Length - 1;
+
+ /* Now, that we know the buffer size, we can allocate it. */
+ /* allocate a buffer */
+ Memory_Block = (byte *) NoFailMalloc(Max_Length);
+
+ /* For EPROM or FLASH memory types, fill unused bytes with FF or the value specified by the p option */
+ memset (Memory_Block,Pad_Byte,Max_Length);
+
+ rewind(Filin);
+ Record_Nb = 0;
+
+ /* Read the file & process the lines. */
+ do /* repeat until EOF(Filin) */
+ {
+ int i;
+
+ Checksum = 0;
+
+ /* Read a line from input file. */
+ GetLine(Line,Filin);
+ Record_Nb++;
+
+ /* Remove carriage return/line feed at the end of line. */
+ i = strlen(Line);
+
+ if (--i != 0)
+ {
+ if (Line[i] == '\n') Line[i] = '\0';
+
+ /* Scan starting address and nb of bytes. */
+ /* Look at the record type after the 'S' */
+ Type = 0;
+
+ switch(Line[1])
+ {
+ case '0':
+ result = sscanf (Line,"S0%2x0000484452%2x",&Nb_Bytes,&Record_Checksum);
+ if (result != 2) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+ Checksum = Nb_Bytes + 0x48 + 0x44 + 0x52;
+
+ /* Adjust Nb_Bytes for the number of data bytes */
+ Nb_Bytes = 0;
+ break;
+
+ /* 16 bits address */
+ case '1':
+ result = sscanf (Line,"S%1x%2x%4x%s",&Type,&Nb_Bytes,&Address,Data_Str);
+ if (result != 4) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+ Checksum = Nb_Bytes + (Address >> 8) + (Address & 0xFF);
+
+ /* Adjust Nb_Bytes for the number of data bytes */
+ Nb_Bytes = Nb_Bytes - 3;
+ break;
+
+ /* 24 bits address */
+ case '2':
+ result = sscanf (Line,"S%1x%2x%6x%s",&Type,&Nb_Bytes,&Address,Data_Str);
+ if (result != 4) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+ Checksum = Nb_Bytes + (Address >> 16) + (Address >> 8) + (Address & 0xFF);
+
+ /* Adjust Nb_Bytes for the number of data bytes */
+ Nb_Bytes = Nb_Bytes - 4;
+ break;
+
+ /* 32 bits address */
+ case '3':
+ result = sscanf (Line,"S%1x%2x%8x%s",&Type,&Nb_Bytes,&Address,Data_Str);
+ if (result != 4) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+ Checksum = Nb_Bytes + (Address >> 24) + (Address >> 16) + (Address >> 8) + (Address & 0xFF);
+
+ /* Adjust Nb_Bytes for the number of data bytes */
+ Nb_Bytes = Nb_Bytes - 5;
+ break;
+
+ case '5':
+ result = sscanf (Line,"S%1x%2x%4x%2x",&Type,&Nb_Bytes,&Record_Count,&Record_Checksum);
+ if (result != 4) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+ Checksum = Nb_Bytes + (Record_Count >> 8) + (Record_Count & 0xFF);
+
+ /* Adjust Nb_Bytes for the number of data bytes */
+ Nb_Bytes = 0;
+ break;
+
+ case '7':
+ result = sscanf (Line,"S%1x%2x%8x%2x",&Type,&Nb_Bytes,&Exec_Address,&Record_Checksum);
+ if (result != 4) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+ Checksum = Nb_Bytes + (Exec_Address >> 24) + (Exec_Address >> 16) + (Exec_Address >> 8) + (Exec_Address & 0xFF);
+ Nb_Bytes = 0;
+ break;
+
+ case '8':
+ result = sscanf (Line,"S%1x%2x%6x%2x",&Type,&Nb_Bytes,&Exec_Address,&Record_Checksum);
+ if (result != 4) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+ Checksum = Nb_Bytes + (Exec_Address >> 16) + (Exec_Address >> 8) + (Exec_Address & 0xFF);
+ Nb_Bytes = 0;
+ break;
+ case '9':
+ result = sscanf (Line,"S%1x%2x%4x%2x",&Type,&Nb_Bytes,&Exec_Address,&Record_Checksum);
+ if (result != 4) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+ Checksum = Nb_Bytes + (Exec_Address >> 8) + (Exec_Address & 0xFF);
+ Nb_Bytes = 0;
+ break;
+ }
+
+ p = (char *) Data_Str;
+
+ /* If we're reading the last record, ignore it. */
+ switch (Type)
+ {
+ /* Data record */
+ case 1:
+ case 2:
+ case 3:
+ if (Nb_Bytes == 0)
+ {
+ fprintf(stderr,"0 byte length Data record ignored\n");
+ break;
+ }
+
+ Phys_Addr = Address;
+
+ /* Read the Data bytes. */
+ i = Nb_Bytes;
+
+ do
+ {
+ result = sscanf (p, "%2x",&temp2);
+ if (result != 1) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+ p += 2;
+
+ /* Overlapping record will erase the pad bytes */
+ if (Swap_Wordwise)
+ {
+ if (Memory_Block[Phys_Addr ^ 1] != Pad_Byte) fprintf(stderr,"Overlapped record detected\n");
+ Memory_Block[Phys_Addr++ ^ 1] = temp2;
+ }
+ else
+ {
+ if (Memory_Block[Phys_Addr] != Pad_Byte) fprintf(stderr,"Overlapped record detected\n");
+ Memory_Block[Phys_Addr++] = temp2;
+ }
+
+ Checksum = (Checksum + temp2) & 0xFF;
+ }
+ while (--i != 0);
+
+ /* Read the Checksum value. */
+ result = sscanf (p, "%2x",&Record_Checksum);
+ if (result != 1) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+ break;
+
+ case 5:
+ fprintf(stderr,"Record total: %d\n",Record_Count);
+ break;
+
+ case 7:
+ fprintf(stderr,"Execution Address (unused): %08X\n",Exec_Address);
+ break;
+
+ case 8:
+ fprintf(stderr,"Execution Address (unused): %06X\n",Exec_Address);
+ break;
+
+ case 9:
+ fprintf(stderr,"Execution Address (unused): %04X\n",Exec_Address);
+ break;
+
+ /* Ignore all other records */
+ default:;
+ }
+
+ Record_Checksum &= 0xFF;
+
+ /* Verify Checksum value. */
+ if (((Record_Checksum + Checksum) != 0xFF) && Enable_Checksum_Error)
+ {
+ fprintf(stderr,"Checksum error in record %d: should be %02X\n",Record_Nb, 255-Checksum);
+ Status_Checksum_Error = true;
+ }
+ }
+ }
+ while (!feof (Filin));
+ /*-----------------------------------------------------------------------------*/
+
+ fprintf(stdout,"Binary file start = %08X\n",Lowest_Address);
+ fprintf(stdout,"Records start = %08X\n",Records_Start);
+ fprintf(stdout,"Highest address = %08X\n",Highest_Address);
+ fprintf(stdout,"Pad Byte = %X\n", Pad_Byte);
+
+ WriteMemory();
+
+#ifdef USE_FILE_BUFFERS
+ free (FilinBuf);
+ free (FiloutBuf);
+#endif
+
+ fclose (Filin);
+ fclose (Filout);
+
+ if (Status_Checksum_Error && Enable_Checksum_Error)
+ {
+ fprintf(stderr,"Checksum error detected.\n");
+ return 1;
+ }
+
+ if (!Fileread)
+ usage();
+ return 0;
+}
diff --git a/tools/iDSK/.gitignore b/tools/iDSK/.gitignore
new file mode 100644
index 0000000..4d731b8
--- /dev/null
+++ b/tools/iDSK/.gitignore
@@ -0,0 +1,7 @@
+CMakeFiles
+CMakeCache.txt
+*.cmake
+iDSK.*
+Makefile
+*.swp
+*.dsk
diff --git a/tools/iDSK/AUTHORS b/tools/iDSK/AUTHORS
new file mode 100644
index 0000000..0c18ff6
--- /dev/null
+++ b/tools/iDSK/AUTHORS
@@ -0,0 +1,3 @@
+cpcemu - Marco Vieth
+manageDSK - Ludovic Deplanque
+iDSK - Sid from IMPACT / PulkoMandy from the Shinra Team
diff --git a/tools/iDSK/CMakeLists.txt b/tools/iDSK/CMakeLists.txt
new file mode 100644
index 0000000..b15c716
--- /dev/null
+++ b/tools/iDSK/CMakeLists.txt
@@ -0,0 +1,14 @@
+PROJECT(iDSK)
+
+add_executable(iDSK
+ src/Basic.cpp
+ src/BitmapCPC.cpp
+ src/Dams.cpp
+ src/Desass.cpp
+ src/endianPPC.cpp
+ src/GestDsk.cpp
+ src/getopt_pp.cpp
+ src/Main.cpp
+ src/Outils.cpp
+ src/ViewFile.cpp
+)
diff --git a/tools/iDSK/COPYING b/tools/iDSK/COPYING
new file mode 100644
index 0000000..b515066
--- /dev/null
+++ b/tools/iDSK/COPYING
@@ -0,0 +1 @@
+Well, ask Sid before doing anything...
diff --git a/tools/iDSK/src/Basic.cpp b/tools/iDSK/src/Basic.cpp
new file mode 100644
index 0000000..4aeb314
--- /dev/null
+++ b/tools/iDSK/src/Basic.cpp
@@ -0,0 +1,350 @@
+#include <iostream>
+using namespace std;
+#include <cmath>
+#include <cstring>
+#include <cstdio>
+#include <ctype.h>
+
+#include "MyType.h"
+#include "Basic.h"
+
+
+//static char ConvCpcFr[ 128 ] = " !\"#$%&'()*+,-./0123456789:;<=>?àABCDEFGHIJKLMNOPQRSTUVWXYZ[ç]^_`abcdefghijklmnopqrstuvwxyzéùè~";
+
+
+//
+// Tableau de décryptage d'un programme en basic protégé
+//
+static BYTE DproBasic[ 128 ] =
+ {
+ 0xAB, 0x2C, 0xED, 0xEA, 0x6C, 0x37, 0x3F, 0xEC,
+ 0x9B, 0xDF, 0x7A, 0x0C, 0x3B, 0xD4, 0x6D, 0xF5,
+ 0x04, 0x44, 0x03, 0x11, 0xDF, 0x59, 0x8F, 0x21,
+ 0x73, 0x7A, 0xCC, 0x83, 0xDD, 0x30, 0x6A, 0x30,
+ 0xD3, 0x8F, 0x02, 0xF0, 0x60, 0x6B, 0x94, 0xE4,
+ 0xB7, 0xF3, 0x03, 0xA8, 0x60, 0x88, 0xF0, 0x43,
+ 0xE8, 0x8E, 0x43, 0xA0, 0xCA, 0x84, 0x31, 0x53,
+ 0xF3, 0x1F, 0xC9, 0xE8, 0xAD, 0xC0, 0xBA, 0x6D,
+ 0x93, 0x08, 0xD4, 0x6A, 0x2C, 0xB2, 0x07, 0x27,
+ 0xC0, 0x99, 0xEE, 0x89, 0xAF, 0xC3, 0x53, 0xAB,
+ 0x2B, 0x34, 0x5C, 0x2F, 0x13, 0xEE, 0xAA, 0x2C,
+ 0xD9, 0xF4, 0xBC, 0x12, 0xB3, 0xC5, 0x1C, 0x68,
+ 0x01, 0x20, 0x2C, 0xFA, 0x77, 0xA6, 0xB5, 0xA4,
+ 0xFC, 0x9B, 0xF1, 0x32, 0x5B, 0xC3, 0x70, 0x77,
+ 0x85, 0x36, 0xBE, 0x5B, 0x8C, 0xC8, 0xB5, 0xC2,
+ 0xF0, 0x0B, 0x98, 0x0F, 0x36, 0x9D, 0xD8, 0x96
+ };
+
+
+BYTE GetByte( BYTE * BufFile, int Pos, int Deprotect )
+{
+ //BYTE b = ( BYTE )( BufFile[ Pos ] ^ ( DproBasic[ Pos & 0x7F ] * Deprotect ) );
+ //cout << "GetByte:"<<hex<<b<<endl;
+ return( BYTE )( BufFile[ Pos ] ^ ( DproBasic[ Pos & 0x7F ] * Deprotect ) );
+}
+
+
+int GetWord( BYTE * BufFile, int Pos, int Deprotect )
+{
+ int Ret = BufFile[ Pos ] ^ ( DproBasic[ Pos & 0x7F ] * Deprotect );
+ Pos++;
+ Ret += ( ( BufFile[ Pos ] ^ ( DproBasic[ Pos & 0x7F ] * Deprotect ) ) << 8 );
+ return( Ret );
+}
+
+
+//
+// Ajoute un "mot" (nom d'une variable, RSX...) dans la chaine "Listing"
+//
+int AddWord( BYTE * BufFile, int Pos, char * Listing, int Deprotect )
+{
+ int LenVar = 0, l = strlen( Listing );
+ BYTE b;
+
+ do
+ {
+ b = GetByte( BufFile, Pos++, Deprotect );
+ Listing[ l++ ] = ( char )( b & 0x7F );
+ }
+ while( ! ( b & 0x80 ) && LenVar++ < 0xFF );
+ Listing[ l ] = 0;
+ return( Pos );
+}
+
+
+//
+// Convertir le buffer en listing basic
+//
+void Basic( BYTE * BufFile, char * Listing, bool IsBasic, bool CrLf )
+{
+ static char Tmp[ 32 ];
+ int Pos = 0, Token = 0;
+ int StartLigne = 0, EndLigne;
+ char * p;
+ double f;
+ int exp;
+ int Deprotect=0;
+ //cout << BufFile <<endl;
+ static const char * Nbre[ 11 ] =
+ {
+ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"
+ };
+ static const char * MotsClefs[ 0x80 ] =
+ {
+ "AFTER", "AUTO", "BORDER", "CALL", "CAT", "CHAIN", "CLEAR", "CLG",
+ "CLOSEIN", "CLOSEOUT", "CLS", "CONT", "DATA", "DEF", "DEFINT",
+ "DEFREAL", "DEFSTR", "DEG", "DELETE", "DIM", "DRAW", "DRAWR", "EDIT",
+ "ELSE", "END", "ENT", "ENV", "ERASE", "ERROR", "EVERY", "FOR",
+ "GOSUB", "GOTO", "IF", "INK", "INPUT", "KEY", "LET", "LINE", "LIST",
+ "LOAD", "LOCATE", "MEMORY", "MERGE", "MID$", "MODE", "MOVE", "MOVER",
+ "NEXT", "NEW", "ON", "ON BREAK", "ON ERROR GOTO", "SQ", "OPENIN",
+ "OPENOUT", "ORIGIN", "OUT", "PAPER", "PEN", "PLOT", "PLOTR", "POKE",
+ "PRINT", "'", "RAD", "RANDOMIZE", "READ", "RELEASE", "REM", "RENUM",
+ "RESTORE", "RESUME", "RETURN", "RUN", "SAVE", "SOUND", "SPEED", "STOP",
+ "SYMBOL", "TAG", "TAGOFF", "TROFF", "TRON", "WAIT", "WEND", "WHILE",
+ "WIDTH", "WINDOW", "WRITE", "ZONE", "DI", "EI", "FILL", "GRAPHICS",
+ "MASK", "FRAME", "CURSOR", "#E2", "ERL", "FN", "SPC", "STEP", "SWAP",
+ "#E8", "#E9", "TAB", "THEN", "TO", "USING", ">", "=", ">=", "<", "<>",
+ "<=", "+", "-", "*", "/", "^", "\\ ", "AND", "MOD", "OR", "XOR", "NOT",
+ "#FF"
+ };
+
+ static const char * Fcts[ 0x80 ] =
+ {
+ "ABS", "ASC", "ATN", "CHR$", "CINT", "COS", "CREAL", "EXP", "FIX",
+ "FRE", "INKEY", "INP", "INT", "JOY", "LEN", "LOG", "LOG10", "LOWER$",
+ "PEEK", "REMAIN", "SGN", "SIN", "SPACE$", "SQ", "SQR", "STR$", "TAN",
+ "UNT", "UPPER$", "VAL", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "EOF", "ERR", "HIMEM", "INKEY$", "PI", "RND",
+ "TIME", "XPOS", "YPOS", "DERR", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "BIN$", "DEC$", "HEX$",
+ "INSTR", "LEFT$", "MAX", "MIN", "POS", "RIGHT$", "ROUND", "STRING$",
+ "TEST", "TESTR", "COPYCHR$", "VPOS"
+ };
+
+
+ * Listing = 0;
+ Token = GetByte( BufFile, 0, Deprotect );
+ for ( ;; )
+ {
+ //cout << "Listing : " <<Listing << endl;
+ if ( IsBasic )
+ {
+ int lg = GetWord( BufFile, Pos, Deprotect );
+ Pos += 2;
+ if ( ! lg )
+ break;
+
+ int NumLigne = GetWord( BufFile, Pos, Deprotect );
+ Pos += 2;
+ sprintf( Tmp, "%d ", NumLigne );
+ strcat( Listing, Tmp );
+ }
+ else
+ if ( ! Token || Token == 0x1A )
+ break;
+
+ int DansChaine = 0; // #### Hum, plus compliqué que ça je pense...
+ do
+ {
+ //cout << "Tmp:"<<Tmp<<endl;
+ Token = GetByte( BufFile, Pos++, Deprotect );
+ if ( ! IsBasic && Token == 0x1A )
+ break;
+
+ if ( DansChaine || ! IsBasic )
+ {
+ Tmp[ 0 ] = ( char )Token;
+ Tmp[ 1 ] = 0;
+ strcat( Listing, Tmp );
+ if ( Token == '"' )
+ DansChaine ^= 1;
+ // cout << " DansChaine Tmp:"<<Tmp<<endl;
+ }
+ else
+ if ( Token > 0x7F && Token < 0xFF )
+ {
+ // #### Traitement particulier du ':' avant le ELSE
+ if ( Listing[ strlen( Listing ) - 1 ] == ':'
+ && Token == 0x97
+ )
+ Listing[ strlen( Listing ) - 1 ] = 0;
+
+ strcat( Listing
+ , MotsClefs[ Token & 0x7F ]
+ );
+ }
+ else
+ if ( Token >= 0x0E && Token <= 0x18 )
+ strcat( Listing
+ , Nbre[ Token - 0x0E ]
+ );
+ else
+ if ( Token >= 0x20 && Token < 0x7C )
+ {
+ Tmp[ 0 ] = ( char )Token;
+ Tmp[ 1 ] = 0;
+ strcat( Listing, Tmp );
+ if ( Token == '"' )
+ DansChaine ^= 1;
+ }
+ else
+ {
+ //cout << "Token:" << Token <<endl;
+ switch( Token )
+ {
+ case 0x01 :
+ Tmp[ 0 ] = ':';
+ Tmp[ 1 ] = 0;
+ strcat( Listing, Tmp );
+ break;
+
+ case 0x02 : // Variable entière (type %)
+ Pos = AddWord( BufFile
+ , 2 + Pos
+ , Listing
+ , Deprotect
+ );
+ strcat( Listing, "%" );
+ break;
+
+
+ case 0x03 : // Variable chaine (type $)
+ Pos = AddWord( BufFile
+ , 2 + Pos
+ , Listing
+ , Deprotect
+ );
+ strcat( Listing, "$" );
+ break;
+
+ case 0x0B :
+ case 0x0C :
+ case 0x0D : // Variable "standard"
+ Pos = AddWord( BufFile
+ , 2 + Pos
+ , Listing
+ , Deprotect
+ );
+ break;
+
+ case 0x19 : // Constante entière 8 bits
+ sprintf(Listing+strlen(Listing),"%d",(BYTE)GetByte( BufFile, Pos, Deprotect));
+ Pos++;
+ break;
+
+ case 0x1A :
+ case 0x1E : // Constante entière 16 bits
+ sprintf(Listing+strlen(Listing),"%d",GetWord( BufFile, Pos, Deprotect));
+ Pos += 2;
+ break;
+
+ case 0x1B :
+ sprintf( Tmp
+ , "&X%X"
+ , GetWord( BufFile, Pos, Deprotect )
+ );
+ strcat( Listing, Tmp );
+ Pos += 2;
+ break;
+
+ case 0x1C :
+ sprintf( Tmp
+ , "&%X"
+ , GetWord( BufFile, Pos, Deprotect )
+ );
+ strcat( Listing, Tmp );
+ Pos += 2;
+ break;
+
+ case 0x1F : // Constante flottante
+ f = ( GetByte( BufFile, Pos + 2, Deprotect ) << 16 )
+ + ( GetByte( BufFile, Pos + 1, Deprotect ) << 8 )
+ + GetByte( BufFile, Pos, Deprotect )
+ + ( ( GetByte( BufFile, Pos + 3, Deprotect ) & 0x7F ) << 24 );
+ f = 1 + ( f / 0x80000000 );
+
+ if ( GetByte( BufFile, Pos + 3, Deprotect ) & 0x80 )
+ f = -f;
+
+ exp = GetByte( BufFile, Pos + 4, Deprotect ) - 129;
+ Pos += 5;
+ sprintf( Tmp, "%f", f * pow( (double) 2, exp ) );
+ // Suppression des '0' inutiles
+ p = &Tmp[ strlen( Tmp ) - 1 ];
+ while( * p == '0' )
+ * p-- = 0;
+
+ if ( * p == '.' )
+ * p = 0;
+
+ strcat( Listing, Tmp );
+ break;
+
+ case 0x7C :
+ strcat( Listing, "|" );
+ Pos = AddWord( BufFile
+ , 1 + Pos
+ , Listing
+ , Deprotect
+ );
+ break;
+
+ case 0xFF :
+ if ( GetByte( BufFile, Pos, Deprotect ) < 0x80 )
+ strcat( Listing
+ , Fcts[ GetByte( BufFile
+ , Pos++
+ , Deprotect
+ )
+ ]
+ );
+ else
+ {
+ Tmp[ 1 ] = 0;
+ Tmp[ 0 ] = ( char )( GetByte( BufFile
+ , Pos++
+ , Deprotect
+ ) & 0x7F
+ );
+ strcat( Listing, Tmp );
+ }
+ break;
+
+ default :
+ Token = Token;
+ }
+ }
+ }
+ while( Token );
+ if ( CrLf )
+ {
+ //
+ // Retour à la ligne si > 80 caractères
+ //
+ EndLigne = strlen( &Listing[ StartLigne ] );
+ while( EndLigne > 80 )
+ {
+ memmove( &Listing[ StartLigne + 82 ]
+ , &Listing[ StartLigne + 80 ]
+ , EndLigne
+ );
+ memcpy( &Listing[ StartLigne + 80 ], "\r\n", 2 );
+ StartLigne += 82;
+ EndLigne -= 80;
+ }
+ }
+ strcat( Listing, "\r\n" );
+ StartLigne = strlen( Listing );
+ }
+ // Conversion des caractères accentués si nécessaire
+
+ for ( int i = strlen( Listing); i--; )
+ {
+ //cout << i << " ";
+
+ if ( ! isprint(Listing[ i ]) && Listing[ i ] != '\n' && Listing[ i ] != '\r' ) Listing[ i ] = '?';
+ }
+}
diff --git a/tools/iDSK/src/Basic.h b/tools/iDSK/src/Basic.h
new file mode 100644
index 0000000..bb99181
--- /dev/null
+++ b/tools/iDSK/src/Basic.h
@@ -0,0 +1,8 @@
+#ifndef BASIC_H
+#define BASIC_H
+
+
+void Basic( unsigned char * BufFile, char * Listing, bool IsBasic, bool CrLf );
+
+
+#endif
diff --git a/tools/iDSK/src/BitmapCPC.cpp b/tools/iDSK/src/BitmapCPC.cpp
new file mode 100644
index 0000000..19b39a6
--- /dev/null
+++ b/tools/iDSK/src/BitmapCPC.cpp
@@ -0,0 +1,264 @@
+#include <iostream>
+#include <cstdio>
+#include "MyType.h"
+#include "BitmapCPC.h"
+#include "GestDsk.h"
+#include <string>
+#include <cstring>
+using namespace std;
+
+
+//
+// Couleurs du CPC converties en composantes r, v, b
+//
+static StRVB RgbCPC[ 27 ] =
+ {
+ { 0x00, 0x00, 0x00, 0x00 },
+ { 0x7F, 0x00, 0x00, 0x00 },
+ { 0xFF, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x7F, 0x00 },
+ { 0x7F, 0x00, 0x7F, 0x00 },
+ { 0xFF, 0x00, 0x7F, 0x00 },
+ { 0x00, 0x00, 0xFF, 0x00 },
+ { 0x7F, 0x00, 0xFF, 0x00 },
+ { 0xFF, 0x00, 0xFF, 0x00 },
+ { 0x00, 0x7F, 0x00, 0x00 },
+ { 0x7F, 0x7F, 0x00, 0x00 },
+ { 0xFF, 0x7F, 0x00, 0x00 },
+ { 0x00, 0x7F, 0x7F, 0x00 },
+ { 0x7F, 0x7F, 0x7F, 0x00 },
+ { 0xFF, 0x7F, 0x7F, 0x00 },
+ { 0x00, 0x7F, 0xFF, 0x00 },
+ { 0x7F, 0x7F, 0xFF, 0x00 },
+ { 0xFF, 0x7F, 0xFF, 0x00 },
+ { 0x00, 0xFF, 0x00, 0x00 },
+ { 0x7F, 0xFF, 0x00, 0x00 },
+ { 0xFF, 0xFF, 0x00, 0x00 },
+ { 0x00, 0xFF, 0x7F, 0x00 },
+ { 0x7F, 0xFF, 0x7F, 0x00 },
+ { 0xFF, 0xFF, 0x7F, 0x00 },
+ { 0x00, 0xFF, 0xFF, 0x00 },
+ { 0x7F, 0xFF, 0xFF, 0x00 },
+ { 0xFF, 0xFF, 0xFF, 0x00 }
+ };
+
+
+int GetRgbCPC( int Coul )
+{
+ if ( Coul >= 0 && Coul < 27 )
+ {
+ StRVB i = RgbCPC[ Coul ];
+ return( ( i.b << 16 ) + ( i.v << 8 ) + i.r );
+ }
+ return( -1 );
+}
+
+
+StRVB GetPalCPC( int Coul )
+{
+ if ( Coul >= 0 && Coul < 27 )
+ return( RgbCPC[ Coul ] );
+
+ return( RgbCPC[ 0 ] );
+}
+
+
+void InitPalette( unsigned char NewPal[ 16 ], bool SetNewPal )
+{
+ /*
+ Si sauvegard� avec ConvImgCpc, alors la palette se trouve
+ dans l'image...
+ */
+ int i;
+ if ( BitmapCPC[ 0x7D0 ] == 0x3A
+ && BitmapCPC[ 0x7D1 ] == 0xD0
+ && BitmapCPC[ 0x7D2 ] == 0xD7
+ && BitmapCPC[ 0x7D3 ] == 0xCD
+ )
+ {
+ Mode = BitmapCPC[ 0x17D0 ];
+ for ( i = 0; i < 16; i++ )
+ Palette[ i ] = BitmapCPC[ 0x17D1 + i ];
+ }
+ if ( SetNewPal )
+ for ( i = 0; i < 16; i++ )
+ Palette[ i ] = NewPal[ i ];
+}
+
+
+//
+// D�compacter une image au format OCP
+//
+void DepactOCP( void )
+{
+ static unsigned char BufTmp[ 0x4000 ];
+ int PosIn = 0, PosOut = 0;
+ int LgOut, CntBlock = 0;
+ int c,i;
+ unsigned char a;
+ memcpy( BufTmp, BitmapCPC, sizeof( BufTmp ) );
+ memset( BitmapCPC, 0, 0x4000 );
+ while( PosOut < 0x4000 )
+ {
+ if ( ! strncmp( ( char * )&BufTmp[ PosIn ], "MJH", 3 ) )
+ {
+ PosIn += 3;
+ LgOut = BufTmp[ PosIn++ ];
+ LgOut += ( BufTmp[ PosIn++ ] << 8 );
+ CntBlock = 0;
+ while( CntBlock < LgOut )
+ {
+ if ( ! strncmp( ( char * )&BufTmp[ PosIn ], "MJH", 3 ) )
+ break;
+
+ a = BufTmp[ PosIn++ ];
+ if ( a == MARKER_OCP )
+ {
+ c = BufTmp[ PosIn++ ];
+ a = BufTmp[ PosIn++ ];
+ if ( ! c )
+ c = 0x100;
+
+ for ( i = 0; i < c && CntBlock < LgOut; i++ )
+ {
+ BitmapCPC[ PosOut++ ] = a;
+ CntBlock++;
+ }
+ }
+ else
+ {
+ BitmapCPC[ PosOut++ ] = a;
+ CntBlock++;
+ }
+ }
+ }
+ else
+ PosOut = 0x4000;
+ }
+}
+
+
+bool LireImage( char * Nom, StRVB * Bitmap )
+{
+ static unsigned char Entete[ 0x80 ];
+ bool Ret = FALSE;
+ //DWORD Nb;
+ FILE* hFile;
+
+
+ if ( (hFile=fopen(Nom,"rb"))!=NULL )
+ {
+ fread(Entete,sizeof(Entete),1,hFile);
+ // ReadFile( hFile, Entete, sizeof( Entete ), &Nb, NULL );
+ if ( CheckAmsdos( Entete ) )
+ {
+ fread(BitmapCPC,sizeof( BitmapCPC ),1,hFile);
+ // ReadFile( hFile, BitmapCPC, sizeof( BitmapCPC ), &Nb, NULL );
+ if ( ! strncmp( ( char * )BitmapCPC, "MJH", 3 ) )
+ DepactOCP();
+
+ InitPalette( NULL, FALSE );
+ Ret = TRUE;
+ }
+ // CloseHandle( hFile );
+ fclose(hFile);
+ if ( Ret )
+ Render( Bitmap, 1 );
+ }
+ return( Ret );
+
+}
+
+
+//
+// Affiche l'image � l'�cran
+//
+void Render( StRVB * Bitmap, bool Flat )
+{
+ int AdrCPC = 0, i, p0, p1, p2, p3;
+ int y,x,AdrBitmap;
+ unsigned char Octet;
+ for ( y = 0; y < NbLignes; y++ )
+ {
+ AdrBitmap = TAILLE_CPC_X * ( y + ( ( 200 - NbLignes ) >> 1 ) )
+ + ( ( ( 80 - NbCol ) >> 1 ) << 3 );
+ for ( x = 0; x < NbCol; x++ )
+ {
+ Octet = BitmapCPC[ AdrCPC + x ];
+ switch( Mode )
+ {
+ case 0 :
+ case 3 : // Mode 3 = Mode 0
+ p0 = ( Octet >> 7 )
+ + ( ( Octet & 0x20 ) >> 3 )
+ + ( ( Octet & 0x08 ) >> 2 )
+ + ( ( Octet & 0x02 ) << 2 );
+ p1 = ( ( Octet & 0x40 ) >> 6 )
+ + ( ( Octet & 0x10 ) >> 2 )
+ + ( ( Octet & 0x04 ) >> 1 )
+ + ( ( Octet & 0x01 ) << 3 );
+ Bitmap[ AdrBitmap++ ] = GetPalCPC( Palette[ p0 ] );
+ Bitmap[ AdrBitmap++ ] = GetPalCPC( Palette[ p0 ] );
+ Bitmap[ AdrBitmap++ ] = GetPalCPC( Palette[ p0 ] );
+ Bitmap[ AdrBitmap++ ] = GetPalCPC( Palette[ p0 ] );
+ Bitmap[ AdrBitmap++ ] = GetPalCPC( Palette[ p1 ] );
+ Bitmap[ AdrBitmap++ ] = GetPalCPC( Palette[ p1 ] );
+ Bitmap[ AdrBitmap++ ] = GetPalCPC( Palette[ p1 ] );
+ Bitmap[ AdrBitmap++ ] = GetPalCPC( Palette[ p1 ] );
+ break;
+
+ case 1 :
+ p0 = ( ( Octet >> 7 ) & 1 ) + ( ( Octet >> 2 ) & 2 );
+ p1 = ( ( Octet >> 6 ) & 1 ) + ( ( Octet >> 1 ) & 2 );
+ p2 = ( ( Octet >> 5 ) & 1 ) + ( ( Octet >> 0 ) & 2 );
+ p3 = ( ( Octet >> 4 ) & 1 ) + ( ( Octet << 1 ) & 2 );
+ Bitmap[ AdrBitmap++ ] = GetPalCPC( Palette[ p0 ] );
+ Bitmap[ AdrBitmap++ ] = GetPalCPC( Palette[ p0 ] );
+ Bitmap[ AdrBitmap++ ] = GetPalCPC( Palette[ p1 ] );
+ Bitmap[ AdrBitmap++ ] = GetPalCPC( Palette[ p1 ] );
+ Bitmap[ AdrBitmap++ ] = GetPalCPC( Palette[ p2 ] );
+ Bitmap[ AdrBitmap++ ] = GetPalCPC( Palette[ p2 ] );
+ Bitmap[ AdrBitmap++ ] = GetPalCPC( Palette[ p3 ] );
+ Bitmap[ AdrBitmap++ ] = GetPalCPC( Palette[ p3 ] );
+ break;
+
+ case 2 :
+ for ( i = 8; i--; )
+ Bitmap[ AdrBitmap++ ] = GetPalCPC( Palette[ ( Octet >> i ) & 1 ] );
+ break;
+ }
+ }
+ if ( Flat )
+ AdrCPC += NbCol;
+ else
+ {
+ AdrCPC += 0x800;
+ if ( AdrCPC > 0x3FFF )
+ AdrCPC -= 0x3FB0;
+ }
+ }
+}
+
+
+void SetBitmapCPC( unsigned char * BitmapSource )
+{
+ memcpy( BitmapCPC, BitmapSource, 0x4000 );
+ if ( ! strncmp( ( char * )BitmapCPC, "MJH", 3 ) )
+ DepactOCP();
+
+ InitPalette( NULL, FALSE );
+}
+
+
+void SetNbCol( int n )
+{
+ if ( n > 0 && n <= 80 )
+ NbCol = n;
+}
+
+
+void SetNbLignes( int n )
+{
+ if ( n > 0 && n <= 200 )
+ NbLignes = n;
+}
diff --git a/tools/iDSK/src/BitmapCPC.h b/tools/iDSK/src/BitmapCPC.h
new file mode 100644
index 0000000..2af2bab
--- /dev/null
+++ b/tools/iDSK/src/BitmapCPC.h
@@ -0,0 +1,46 @@
+#ifndef BITMAPCPC_H
+#define BITMAPCPC_H
+
+
+#define TAILLE_CPC_X 640
+
+#define TAILLE_CPC_Y 200
+
+#define MARKER_OCP 1 // Marker pour compression RLE
+int Mode, NbCol, NbLignes;
+unsigned char BitmapCPC[ 0x4000 ];
+unsigned char Palette[ 16 ];
+typedef struct
+ {
+ unsigned char b, v, r, a;
+ } StRVB;
+
+
+
+void CBitmapCPC( void ) { NbCol = 80; NbLignes = 200; }
+bool LireImage( char * Nom, StRVB * Bitmap );
+void Render( StRVB * Bitmap, bool Flat );
+void SetBitmapCPC( unsigned char * BitmapSource );
+unsigned char * GetBitmapCPC( void ) { return( BitmapCPC ); }
+void SetMode( int m ) { Mode = m; }
+void InitPalette( unsigned char Pal[ 16 ], bool SetPal );
+unsigned char * GetPalette( void ) { return( Palette ); }
+int GetMode( void ) { return( Mode ); }
+void SetNbCol( int n );
+void SetNbLignes( int n );
+
+
+void DepactOCP( void );
+void LisseBitmap( StRVB * Bitmap );
+
+
+
+
+
+
+StRVB GetPalCPC( int Coul );
+
+int GetRgbCPC( int Coul );
+
+
+#endif
diff --git a/tools/iDSK/src/Dams.cpp b/tools/iDSK/src/Dams.cpp
new file mode 100644
index 0000000..9b24813
--- /dev/null
+++ b/tools/iDSK/src/Dams.cpp
@@ -0,0 +1,184 @@
+#include <iostream>
+#include <cstdio>
+#include <cstring>
+using namespace std;
+
+
+//
+// Convertir le buffer en listing au format Dams
+// Adaptation des sources de Thierry JOUIN ( Ramlaid )
+//
+void Dams( unsigned char * BufFile, int TailleFic, char * Listing )
+{
+ const char * MotCleDams[ 0x80 ] =
+ {
+ "LD","INC","DEC","ADD","ADC","SUB","SBC","AND","XOR","OR","CP",
+ "PUSH","POP","BIT","RES","SET","RLC","RRC","RL","RR","SLA","SRA",
+ "SRL","IN","OUT","RST","DJNZ","EX","IM","JR","CALL","RET","JP",
+ "NOP","RLCA","RRCA","RLA","RRA","DAA","CPL","SCF","CCF","HALT",
+ "EXX","DI","EI","NEG","RETN","RETI","RRD","RLD","LDI","CPI","INI",
+ "OUTI","LDD","CPD","IND","OUTD","LDIR","CPIR","INIR","OTIR","LDDR",
+ "CPDR","INDR","OTDR","DB","DW","DM","DS","EQU","ORG","ENT",
+ "IF","ELSE","END"
+ };
+ char Tmp[ 32 ];
+ int PosFile = 0;
+ int PosDest = 0;
+ unsigned char c;
+
+ * Listing = 0;
+ c = BufFile[ PosFile++ ];
+ while( c )
+ {
+ if ( c == 0xFF )
+ {
+ // Commentaire ligne
+ Listing[ PosDest++ ] = ';';
+ c = BufFile[ PosFile++ ];
+ while( c != 0x0D && PosFile < TailleFic )
+ {
+ Listing[ PosDest++ ] = c;
+ c = BufFile[ PosFile++ ];
+ }
+ Listing[ PosDest++ ] = '\r';
+ Listing[ PosDest++ ] = '\n';
+ }
+ else
+ {
+ if ( c >= 0x80 && c != 0x0D )
+ {
+ // Mnemonique sans label
+ // ENT
+ if ( c == 0xC9 )
+ Listing[ PosDest++ ] = ';';
+
+ sprintf( Tmp, "\t%s\t", MotCleDams[ c & 0x7F ] );
+ int l = strlen( Tmp );
+ memcpy( &Listing[ PosDest ], Tmp, l );
+ PosDest += l;
+ // DS ?,?
+ if ( c == 0xC6 )
+ {
+ c = BufFile[ PosFile++ ];
+ // Fin de ligne
+ while( c != 0x0D && PosFile < TailleFic )
+ {
+ if ( c == ',' )
+ {
+ while( c != 0x0D && c != 0xFF && PosFile < TailleFic )
+ c = BufFile[ PosFile++ ];
+ }
+ if ( c != 0x0D )
+ {
+ if ( c == 0xFF )
+ Listing[ PosDest++ ] = '\t';
+ else
+ Listing[ PosDest++ ] = c;
+
+ c = BufFile[ PosFile++ ];
+ }
+ }
+ }
+ else
+ {
+ c = BufFile[ PosFile++ ];
+ // Fin de ligne
+ while( c != 0x0D && PosFile < TailleFic )
+ {
+ if ( c == 0xFF )
+ Listing[ PosDest++ ] = '\t';
+ else
+ Listing[ PosDest++ ] = c;
+
+ c = BufFile[ PosFile++ ];
+ }
+ }
+ Listing[ PosDest++ ] = '\r';
+ Listing[ PosDest++ ] = '\n';
+ }
+ else
+ {
+ // Label
+ while( c < 0x80 && c != 0x0D && PosFile < TailleFic )
+ {
+ Listing[ PosDest++ ] = c;
+ c = BufFile[ PosFile++ ];
+ }
+ if ( c != 0x0D )
+ {
+ // Mnemonique apres label
+ // ENT
+ if ( c == 0xC9 )
+ Listing[ PosDest++ ] = ';';
+
+ if ( c != 0xFF )
+ {
+ sprintf( Tmp, "\t%s\t", MotCleDams[ c & 0x7F ] );
+ int l = strlen( Tmp );
+ memcpy( &Listing[ PosDest ], Tmp, l );
+ PosDest += l;
+ }
+ else
+ {
+ Listing[ PosDest++ ] = '\t';
+ Listing[ PosDest++ ] = '\t';
+ Listing[ PosDest++ ] = '\t';
+ }
+ // DS ?,?
+ if ( c == 0xC6 )
+ {
+ c = BufFile[ PosFile++ ];
+ // Fin de ligne
+ while( c != 0x0D && PosFile < TailleFic )
+ {
+ if ( c == ',' )
+ {
+ while( c != 0x0D && c != 0xFF && PosFile < TailleFic )
+ c = BufFile[ PosFile++ ];
+ }
+ if ( c != 0x0D )
+ {
+ if ( c == 0xFF )
+ {
+ Listing[ PosDest++ ] = '\t';
+ Listing[ PosDest++ ] = ';';
+ }
+ else
+ Listing[ PosDest++ ] = c;
+
+ c = BufFile[ PosFile++ ];
+ }
+ }
+ }
+ else
+ {
+ c = BufFile[ PosFile++ ];
+ // Fin de ligne
+ while( c != 0x0D && PosFile < TailleFic )
+ {
+ if ( c == 0xFF )
+ {
+ Listing[ PosDest++ ] = '\t';
+ Listing[ PosDest++ ] = ';';
+ }
+ else
+ Listing[ PosDest++ ] = c;
+
+ c = BufFile[ PosFile++ ];
+ }
+ }
+ Listing[ PosDest++ ] = '\r';
+ Listing[ PosDest++ ] = '\n';
+ }
+ else
+ {
+ Listing[ PosDest++ ] = '\r';
+ Listing[ PosDest++ ] = '\n';
+ }
+ }
+ }
+ c = BufFile[ PosFile++ ];
+ if ( PosFile > TailleFic )
+ break;
+ }
+}
diff --git a/tools/iDSK/src/Dams.h b/tools/iDSK/src/Dams.h
new file mode 100644
index 0000000..6610ef7
--- /dev/null
+++ b/tools/iDSK/src/Dams.h
@@ -0,0 +1,8 @@
+#ifndef DAMS_H
+#define DAMS_H
+
+
+void Dams( unsigned char * BufFile, int TailleFic, char * Listing );
+
+
+#endif
diff --git a/tools/iDSK/src/Desass.cpp b/tools/iDSK/src/Desass.cpp
new file mode 100644
index 0000000..a2030a0
--- /dev/null
+++ b/tools/iDSK/src/Desass.cpp
@@ -0,0 +1,532 @@
+#include <iostream>
+#include <cstdio>
+#include <cstring>
+
+#include "Outils.h"
+using namespace std;
+
+
+//
+// Tableau des OP-Codes Z80...
+//
+const char * TabInstrCB[ 256 ] =
+ {
+ "RLC B","RLC C","RLC D","RLC E",
+ "RLC H","RLC L","RLC (HL)","RLC A",
+ "RRC B","RRC C","RRC D","RRC E",
+ "RRC H","RRC L","RRC (HL)","RRC A",
+ "RL B","RL C","RL D","RL E",
+ "RL H","RL L","RL (HL)","RL A",
+ "RR B","RR C","RR D","RR E",
+ "RR H","RR L","RR (HL)","RR A",
+ "SLA B","SLA C","SLA D","SLA E",
+ "SLA H","SLA L","SLA (HL)","SLA A",
+ "SRA B","SRA C","SRA D","SRA E",
+ "SRA H","SRA L","SRA (HL)","SRA A",
+ "SLL B","SLL C","SLL D","SLL E",
+ "SLL H","SLL L","SLL (HL)","SLL A",
+ "SRL B","SRL C","SRL D","SRL E",
+ "SRL H","SRL L","SRL (HL)","SRL A",
+ "BIT 0,B","BIT 0,C","BIT 0,D","BIT 0,E",
+ "BIT 0,H","BIT 0,L","BIT 0,(HL)","BIT 0,A",
+ "BIT 1,B","BIT 1,C","BIT 1,D","BIT 1,E",
+ "BIT 1,H","BIT 1,L","BIT 1,(HL)","BIT 1,A",
+ "BIT 2,B","BIT 2,C","BIT 2,D","BIT 2,E",
+ "BIT 2,H","BIT 2,L","BIT 2,(HL)","BIT 2,A",
+ "BIT 3,B","BIT 3,C","BIT 3,D","BIT 3,E",
+ "BIT 3,H","BIT 3,L","BIT 3,(HL)","BIT 3,A",
+ "BIT 4,B","BIT 4,C","BIT 4,D","BIT 4,E",
+ "BIT 4,H","BIT 4,L","BIT 4,(HL)","BIT 4,A",
+ "BIT 5,B","BIT 5,C","BIT 5,D","BIT 5,E",
+ "BIT 5,H","BIT 5,L","BIT 5,(HL)","BIT 5,A",
+ "BIT 6,B","BIT 6,C","BIT 6,D","BIT 6,E",
+ "BIT 6,H","BIT 6,L","BIT 6,(HL)","BIT 6,A",
+ "BIT 7,B","BIT 7,C","BIT 7,D","BIT 7,E",
+ "BIT 7,H","BIT 7,L","BIT 7,(HL)","BIT 7,A",
+ "RES 0,B","RES 0,C","RES 0,D","RES 0,E",
+ "RES 0,H","RES 0,L","RES 0,(HL)","RES 0,A",
+ "RES 1,B","RES 1,C","RES 1,D","RES 1,E",
+ "RES 1,H","RES 1,L","RES 1,(HL)","RES 1,A",
+ "RES 2,B","RES 2,C","RES 2,D","RES 2,E",
+ "RES 2,H","RES 2,L","RES 2,(HL)","RES 2,A",
+ "RES 3,B","RES 3,C","RES 3,D","RES 3,E",
+ "RES 3,H","RES 3,L","RES 3,(HL)","RES 3,A",
+ "RES 4,B","RES 4,C","RES 4,D","RES 4,E",
+ "RES 4,H","RES 4,L","RES 4,(HL)","RES 4,A",
+ "RES 5,B","RES 5,C","RES 5,D","RES 5,E",
+ "RES 5,H","RES 5,L","RES 5,(HL)","RES 5,A",
+ "RES 6,B","RES 6,C","RES 6,D","RES 6,E",
+ "RES 6,H","RES 6,L","RES 6,(HL)","RES 6,A",
+ "RES 7,B","RES 7,C","RES 7,D","RES 7,E",
+ "RES 7,H","RES 7,L","RES 7,(HL)","RES 7,A",
+ "SET 0,B","SET 0,C","SET 0,D","SET 0,E",
+ "SET 0,H","SET 0,L","SET 0,(HL)","SET 0,A",
+ "SET 1,B","SET 1,C","SET 1,D","SET 1,E",
+ "SET 1,H","SET 1,L","SET 1,(HL)","SET 1,A",
+ "SET 2,B","SET 2,C","SET 2,D","SET 2,E",
+ "SET 2,H","SET 2,L","SET 2,(HL)","SET 2,A",
+ "SET 3,B","SET 3,C","SET 3,D","SET 3,E",
+ "SET 3,H","SET 3,L","SET 3,(HL)","SET 3,A",
+ "SET 4,B","SET 4,C","SET 4,D","SET 4,E",
+ "SET 4,H","SET 4,L","SET 4,(HL)","SET 4,A",
+ "SET 5,B","SET 5,C","SET 5,D","SET 5,E",
+ "SET 5,H","SET 5,L","SET 5,(HL)","SET 5,A",
+ "SET 6,B","SET 6,C","SET 6,D","SET 6,E",
+ "SET 6,H","SET 6,L","SET 6,(HL)","SET 6,A",
+ "SET 7,B","SET 7,C","SET 7,D","SET 7,E",
+ "SET 7,H","SET 7,L","SET 7,(HL)","SET 7,A"
+ };
+
+
+const char * TabInstrED[ 256 ] =
+ {
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ "IN B,(C)","OUT (C),B","SBC HL,BC","LD (nnnn),BC",
+ "NEG","RETN","IM 0","LD I,A",
+ "IN C,(C)","OUT (C),C","ADC HL,BC","LD BC,(nnnn)",
+ 0,"RETI",0,"LD R,A",
+ "IN D,(C)","OUT (C),D","SBC HL,DE","LD (nnnn),DE",
+ 0,0,"IM 1","LD A,I",
+ "IN E,(C)","OUT (C),E","ADC HL,DE","LD DE,(nnnn)",
+ 0,0,"IM 2","LD A,R",
+ "IN H,(C)","OUT (C),H","SBC HL,HL",0,
+ 0,0,0,"RRD",
+ "IN L,(C)","OUT (C),L","ADC HL,HL",0,
+ 0,0,0,"RLD",
+ 0,"OUT (C),0","SBC HL,SP","LD (nnnn),SP",
+ 0,0,0,0,
+ "IN A,(C)","OUT (C),A","ADC HL,SP","LD SP,(nnnn)",
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ "LDI","CPI","INI","OUTI",
+ 0,0,0,0,
+ "LDD","CPD","IND","OUTD",
+ 0,0,0,0,
+ "LDIR","CPIR","INIR","OTIR",
+ 0,0,0,0,
+ "LDDR","CPDR","INDR","OTDR",
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0
+ };
+
+
+const char * TabInstrDD[ 256 ] =
+ {
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,"ADD IX,BC",0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,"ADD IX,DE",0,0,
+ 0,0,0,0,
+ 0,"LD IX,nnnn","LD (nnnn),IX","INC IX",
+ "INC IXh","DEC IXh","LD IXh,nn",0,
+ 0,"ADD IX,HL","LD IX,(nnnn)","DEC IX",
+ "INC IXl","DEC IXl","LD IXl,nn",0,
+ 0,0,0,0,
+ "INC (IX+nn)","DEC (IX+nn)","LD (IX+nn),nn",0,
+ 0,"ADD IX,SP",0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ "LD B,IXh","LD B,IXl","LD B,(IX+nn)",0,
+ 0,0,0,0,
+ "LD C,IXh","LD C,IXl","LD C,(IX+nn)",0,
+ 0,0,0,0,
+ "LD D,IXh","LD D,IXl","LD D,(IX+nn)",0,
+ 0,0,0,0,
+ "LD E,IXh","LD E,IXl","LD E,(IX+nn)",0,
+ "LD IXh,B","LD IXh,C","LD IXh,D","LD IXh,E",
+ "LD IXh,IXh","LD IXh,IXl","LD H,(IX+nn)","LD IXh,A",
+ "LD IXl,B","LD IXl,C","LD IXl,D","LD IXl,E",
+ "LD IXl,IXh","LD IXl,IXl","LD L,(IX+nn)","LD IXl,A",
+ "LD (IX+nn),B","LD (IX+nn),C","LD (IX+nn),D","LD (IX+nn),E",
+ "LD (IX+nn),H","LD (IX+nn),L",0,"LD (IX+nn),A",
+ 0,0,0,0,
+ "LD A,IXh","LD A,IXl","LD A,(IX+nn)",0,
+ 0,0,0,0,
+ "ADD A,IXh","ADD A,IXl","ADD A,(IX+nn)",0,
+ 0,0,0,0,
+ "ADC A,IXh","ADC A,IXl","ADC A,(IX+nn)",0,
+ 0,0,0,0,
+ "SUB IXh","SUB IXl","SUB (IX+nn)",0,
+ 0,0,0,0,
+ "SBC A,IXh","SBC A,IXl","SBC A,(IX+nn)",0,
+ 0,0,0,0,
+ "AND IXh","AND IXl","AND (IX+nn)",0,
+ 0,0,0,0,
+ "XOR IXh","XOR IXl","XOR (IX+nn)",0,
+ 0,0,0,0,
+ "OR IXh","OR IXl","OR (IX+nn)",0,
+ 0,0,0,0,
+ "CP IXh","CP IXl","CP (IX+nn)",0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,"POP IX",0,"EX (SP),IX",
+ 0,"PUSH IX",0,0,
+ 0,"JP (IX)",0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,"LD SP,IX",0,0,
+ 0,0,0,0
+ };
+
+
+const char * TabInstrDDCB[ 256 ] =
+ {
+ 0,0,0,0,0,0,"RLC (IX+nn)",0,
+ 0,0,0,0,0,0,"RRC (IX+nn)",0,
+ 0,0,0,0,0,0,"RL (IX+nn)",0,
+ 0,0,0,0,0,0,"RR (IX+nn)",0,
+ 0,0,0,0,0,0,"SLA (IX+nn)",0,
+ 0,0,0,0,0,0,"SRA (IX+nn)",0,
+ 0,0,0,0,0,0,"SLL (IX+nn)",0,
+ 0,0,0,0,0,0,"SRL (IX+nn)",0,
+ 0,0,0,0,0,0,"BIT 0,(IX+nn)",0,
+ 0,0,0,0,0,0,"BIT 1,(IX+nn)",0,
+ 0,0,0,0,0,0,"BIT 2,(IX+nn)",0,
+ 0,0,0,0,0,0,"BIT 3,(IX+nn)",0,
+ 0,0,0,0,0,0,"BIT 4,(IX+nn)",0,
+ 0,0,0,0,0,0,"BIT 5,(IX+nn)",0,
+ 0,0,0,0,0,0,"BIT 6,(IX+nn)",0,
+ 0,0,0,0,0,0,"BIT 7,(IX+nn)",0,
+ 0,0,0,0,0,0,"RES 0,(IX+nn)",0,
+ 0,0,0,0,0,0,"RES 1,(IX+nn)",0,
+ 0,0,0,0,0,0,"RES 2,(IX+nn)",0,
+ 0,0,0,0,0,0,"RES 3,(IX+nn)",0,
+ 0,0,0,0,0,0,"RES 4,(IX+nn)",0,
+ 0,0,0,0,0,0,"RES 5,(IX+nn)",0,
+ 0,0,0,0,0,0,"RES 6,(IX+nn)",0,
+ 0,0,0,0,0,0,"RES 7,(IX+nn)",0,
+ 0,0,0,0,0,0,"SET 0,(IX+nn)",0,
+ 0,0,0,0,0,0,"SET 1,(IX+nn)",0,
+ 0,0,0,0,0,0,"SET 2,(IX+nn)",0,
+ 0,0,0,0,0,0,"SET 3,(IX+nn)",0,
+ 0,0,0,0,0,0,"SET 4,(IX+nn)",0,
+ 0,0,0,0,0,0,"SET 5,(IX+nn)",0,
+ 0,0,0,0,0,0,"SET 6,(IX+nn)",0,
+ 0,0,0,0,0,0,"SET 7,(IX+nn)",0
+ };
+
+
+const char * TabInstrFD[ 256 ] =
+ {
+ 0,0,0,0,0,0,0,0,
+ 0,"ADD IY,BC",0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,"ADD IY,DE",0,0,0,0,0,0,
+ 0,"LD IY,nnnn","LD (nnnn),IY","INC IY","INC IYh","DEC IYh","LD IYh,nn",0,
+ 0,"ADD IY,HL","LD IY,(nnnn)","DEC IY","INC IYl","DEC IYl","LD IYl,nn",0,
+ 0,0,0,0,"INC (IY+nn)","DEC (IY+nn)","LD (IY+nn),nn",0,
+ 0,"ADD IY,SP",0,0,0,0,0,0,
+ 0,0,0,0,"LD B,IYh","LD B,IYl","LD B,(IY+nn)",0,
+ 0,0,0,0,"LD C,IYh","LD C,IYl","LD C,(IY+nn)",0,
+ 0,0,0,0,"LD D,IYh","LD D,IYl","LD D,(IY+nn)",0,
+ 0,0,0,0,"LD E,IYh","LD E,IYl","LD E,(IY+nn)",0,
+ "LD IYh,B","LD IYh,C","LD IYh,D","LD IYh,E","LD IYh,IYh","LD IYh,IYl","LD H,(IY+nn)","LD IYh,A",
+ "LD IYl,B","LD IYl,C","LD IYl,D","LD IYl,E","LD IYl,IYh","LD IYl,IYl","LD L,(IY+nn)","LD IYl,A",
+ "LD (IY+nn),B","LD (IY+nn),C","LD (IY+nn),D","LD (IY+nn),E","LD (IY+nn),H","LD (IY+nn),L",0,"LD (IY+nn),A",
+ 0,0,0,0,"LD A,IYh","LD A,IYl","LD A,(IY+nn)",0,
+ 0,0,0,0,"ADD A,IYh","ADD A,IYl","ADD A,(IY+nn)",0,
+ 0,0,0,0,"ADC A,IYh","ADC A,IYl","ADC A,(IY+nn)",0,
+ 0,0,0,0,"SUB IYh","SUB IYl","SUB (IY+nn)",0,
+ 0,0,0,0,"SBC A,IYh","SBC A,IYl","SBC A,(IY+nn)",0,
+ 0,0,0,0,"AND IYh","AND IYl","AND (IY+nn)",0,
+ 0,0,0,0,"XOR IYh","XOR IYl","XOR (IY+nn)",0,
+ 0,0,0,0,"OR IYh","OR IYl","OR (IY+nn)",0,
+ 0,0,0,0,"CP IYh","CP IYl","CP (IY+nn)",0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,"POP IY",0,"EX (SP),IY",0,"PUSH IY",0,0,
+ 0,"JP (IY)",0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,"LD SP,IY",0,0,0,0,0,0
+ };
+
+
+const char * TabInstrFDCB[ 256 ] =
+ {
+ 0,0,0,0,0,0,"RLC (IY+nn)",0,
+ 0,0,0,0,0,0,"RRC (IY+nn)",0,
+ 0,0,0,0,0,0,"RL (IY+nn)",0,
+ 0,0,0,0,0,0,"RR (IY+nn)",0,
+ 0,0,0,0,0,0,"SLA (IY+nn)",0,
+ 0,0,0,0,0,0,"SRA (IY+nn)",0,
+ 0,0,0,0,0,0,"SLL (IY+nn)",0,
+ 0,0,0,0,0,0,"SRL (IY+nn)",0,
+ 0,0,0,0,0,0,"BIT 0,(IY+nn)",0,
+ 0,0,0,0,0,0,"BIT 1,(IY+nn)",0,
+ 0,0,0,0,0,0,"BIT 2,(IY+nn)",0,
+ 0,0,0,0,0,0,"BIT 3,(IY+nn)",0,
+ 0,0,0,0,0,0,"BIT 4,(IY+nn)",0,
+ 0,0,0,0,0,0,"BIT 5,(IY+nn)",0,
+ 0,0,0,0,0,0,"BIT 6,(IY+nn)",0,
+ 0,0,0,0,0,0,"BIT 7,(IY+nn)",0,
+ 0,0,0,0,0,0,"RES 0,(IY+nn)",0,
+ 0,0,0,0,0,0,"RES 1,(IY+nn)",0,
+ 0,0,0,0,0,0,"RES 2,(IY+nn)",0,
+ 0,0,0,0,0,0,"RES 3,(IY+nn)",0,
+ 0,0,0,0,0,0,"RES 4,(IY+nn)",0,
+ 0,0,0,0,0,0,"RES 5,(IY+nn)",0,
+ 0,0,0,0,0,0,"RES 6,(IY+nn)",0,
+ 0,0,0,0,0,0,"RES 7,(IY+nn)",0,
+ 0,0,0,0,0,0,"SET 0,(IY+nn)",0,
+ 0,0,0,0,0,0,"SET 1,(IY+nn)",0,
+ 0,0,0,0,0,0,"SET 2,(IY+nn)",0,
+ 0,0,0,0,0,0,"SET 3,(IY+nn)",0,
+ 0,0,0,0,0,0,"SET 4,(IY+nn)",0,
+ 0,0,0,0,0,0,"SET 5,(IY+nn)",0,
+ 0,0,0,0,0,0,"SET 6,(IY+nn)",0,
+ 0,0,0,0,0,0,"SET 7,(IY+nn)",0
+ };
+
+
+const char * TabInstr[ 256 ] =
+ {
+ "NOP","LD BC,nnnn","LD (BC),A","INC BC",
+ "INC B","DEC B","LD B,nn","RLCA",
+ "EX AF,AF","ADD HL,BC","LD A,(BC)","DEC BC",
+ "INC C","DEC C","LD C,nn","RRCA",
+ "DJNZ eeee","LD DE,nnnn","LD (DE),A","INC DE",
+ "INC D","DEC D","LD D,nn","RLA",
+ "JR eeee","ADD HL,DE","LD A,(DE)","DEC DE",
+ "INC E","DEC E","LD E,nn","RRA",
+ "JR NZ,eeee","LD HL,nnnn","LD (nnnn),HL","INC HL",
+ "INC H","DEC H","LD H,nn","DAA",
+ "JR Z,eeee","ADD HL,HL","LD HL,(nnnn)","DEC HL",
+ "INC L","DEC L","LD L,nn","CPL",
+ "JR NC,eeee","LD SP,nnnn","LD (nnnn),A","INC SP",
+ "INC (HL)","DEC (HL)","LD (HL),nn","SCF",
+ "JR C,eeee","ADD HL,SP","LD A,(nnnn)","DEC SP",
+ "INC A","DEC A","LD A,nn","CCF",
+ "LD B,B","LD B,C","LD B,D","LD B,E",
+ "LD B,H","LD B,L","LD B,(HL)","LD B,A",
+ "LD C,B","LD C,C","LD C,D","LD C,E",
+ "LD C,H","LD C,L","LD C,(HL)","LD C,A",
+ "LD D,B","LD D,C","LD D,D","LD D,E",
+ "LD D,H","LD D,L","LD D,(HL)","LD D,A",
+ "LD E,B","LD E,C","LD E,D","LD E,E",
+ "LD E,H","LD E,L","LD E,(HL)","LD E,A",
+ "LD H,B","LD H,C","LD H,D","LD H,E",
+ "LD H,H","LD H,L","LD H,(HL)","LD H,A",
+ "LD L,B","LD L,C","LD L,D","LD L,E",
+ "LD L,H","LD L,L","LD L,(HL)","LD L,A",
+ "LD (HL),B","LD (HL),C","LD (HL),D","LD (HL),E",
+ "LD (HL),H","LD (HL),L","HALT","LD (HL),A",
+ "LD A,B","LD A,C","LD A,D","LD A,E",
+ "LD A,H","LD A,L","LD A,(HL)","LD A,A",
+ "ADD A,B","ADD A,C","ADD A,D","ADD A,E",
+ "ADD A,H","ADD A,L","ADD A,(HL)","ADD A,A",
+ "ADC A,B","ADC A,C","ADC A,D","ADC A,E",
+ "ADC A,H","ADC A,L","ADC A,(HL)","ADC A,A",
+ "SUB B","SUB C","SUB D","SUB E",
+ "SUB H","SUB L","SUB (HL)","SUB A",
+ "SBC A,B","SBC A,C","SBC A,D","SBC A,E",
+ "SBC A,H","SBC A,L","SBC A,(HL)","SBC A,A",
+ "AND B","AND C","AND D","AND E",
+ "AND H","AND L","AND (HL)","AND A",
+ "XOR B","XOR C","XOR D","XOR E",
+ "XOR H","XOR L","XOR (HL)","XOR A",
+ "OR B","OR C","OR D","OR E",
+ "OR H","OR L","OR (HL)","OR A",
+ "CP B","CP C","CP D","CP E",
+ "CP H","CP L","CP (HL)","CP A",
+ "RET NZ","POP BC","JP NZ,nnnn","JP nnnn",
+ "CALL NZ,nnnn","PUSH BC","ADD A,nn","RST 00",
+ "RET Z","RET","JP Z,nnnn",0,
+ "CALL Z,nnnn","CALL nnnn","ADC A,nn","RST 08",
+ "RET NC","POP DE","JP NC,nnnn","OUT (nn),A",
+ "CALL NC,nnnn","PUSH DE","SUB nn","RST 10",
+ "RET C","EXX","JP C,nnnn","IN A,(nn)",
+ "CALL C,nnnn",0,"SBC A,nn","RST 18",
+ "RET PE","POP HL","JP PE,nnnn","EX (SP),HL",
+ "CALL PE,nnnn","PUSH HL","AND nn","RST 20",
+ "RET PO","JP (HL)","JP PO,nnnn","EX DE,HL",
+ "CALL PO,nnnn",0,"XOR nn","RST 28",
+ "RET P","POP AF","JP P,nnnn","DI",
+ "CALL P,nnnn","PUSH AF","OR nn","RST 30",
+ "RET M","LD SP,HL","JP M,nnnn","EI",
+ "CALL M,nnnn",0,"CP nn","RST 38"
+ };
+
+
+//
+// Convertir le buffer en listing d�sassembl�
+//
+void Desass( unsigned char * Prg, char * Listing, int Longueur )
+{
+ int i, Instr, Inst2 = 0, Inst3 = 0, Inst4 = 0, Ad16;
+ const char * Chaine;
+ char *p;
+ char Inst[ 1024 ];
+
+ int Adr, OldAdr, PosD = 0;
+ char Ad8;
+
+ * Listing = 0;
+ for ( Adr = 0; Adr < Longueur; )
+ {
+ OldAdr = Adr;
+ Instr = Prg[ Adr++ ];
+ Chaine = TabInstr[ Instr ];
+ if ( Instr == 0xCB )
+ {
+ Inst2 = Prg[ Adr++ ];
+ Chaine = TabInstrCB[ Inst2 ];
+ }
+ else
+ if ( Instr == 0xDD )
+ {
+ Inst2 = Prg[ Adr++ ];
+ if ( Inst2 == 0xCB )
+ {
+ Inst3 = Prg[ Adr++ ];
+ Inst4 = Prg[ Adr++ ];
+ Chaine = TabInstrDDCB[ Inst4 ];
+ strcpy( Inst, Chaine );
+ p = strstr( Inst, "nn" );
+ if ( p )
+ {
+ if ( Inst3 < 0x80 )
+ Hex( p, Inst3, 2 );
+ else
+ {
+ Hex( p, -Inst3, 2 );
+ p[ -1 ] = '-';
+ }
+ }
+ Chaine = Inst;
+ }
+ else
+ Chaine = TabInstrDD[ Inst2 ];
+ }
+ else
+ if ( Instr == 0xED )
+ {
+ Inst2 = Prg[ Adr++ ];
+ Chaine = TabInstrED[ Inst2 ];
+ }
+ else
+ if ( Instr == 0xFD )
+ {
+ Inst2 = Prg[ Adr++ ];
+ if ( Inst2 == 0xCB )
+ {
+ Ad8 = Prg[ Adr++ ];
+ Inst3 = Prg[ Adr++ ];
+ Chaine = TabInstrFDCB[ Inst3 ];
+ if ( Chaine )
+ {
+ strcpy( Inst, Chaine );
+ Chaine = Inst;
+ p = strstr( Inst, "nn" );
+ if ( p )
+ Hex( p, Ad8, 2 );
+ }
+ }
+ else
+ Chaine = TabInstrFD[ Inst2 ];
+ }
+ if ( Chaine )
+ {
+ strcpy( Inst, Chaine );
+ p = strstr( Inst, "nnnn" );
+ Ad16 = Prg[ Adr++ ];
+ Ad16 += Prg[ Adr ] << 8;
+ Ad8 = ( char ) Ad16;
+ if ( p )
+ {
+ Hex( p, Ad16, 4 );
+ Adr++;
+ }
+ else
+ {
+ p = strstr( Inst, "nn" );
+ if ( p )
+ {
+ Hex( p, Ad16, 2 );
+ p = strstr( Inst, "nn" );
+ if ( p )
+ Hex( p, Ad16 >> 8, 2 );
+ }
+ else
+ {
+ p = strstr( Inst, "eeee" );
+ if ( p )
+ Hex( p, Adr + Ad8, 4 );
+ else
+ Adr--;
+ }
+ }
+ }
+ else
+ sprintf( Inst, "%02X %02X %02X ????", Instr, Inst2, Inst3 );
+
+ Hex( &Listing[ PosD ], OldAdr, 4 );
+ Listing[ PosD + 4 ] = ' ';
+ PosD += 5;
+ for ( i = OldAdr; i < Adr; i++ )
+ {
+ Hex( &Listing[ PosD ], Prg[ i ], 2 );
+ Listing[ PosD + 2 ] = ' ';
+ PosD += 3;
+ }
+ for ( i = 0; i < 5 - Adr + OldAdr; i++ )
+ {
+ Listing[ PosD ] = Listing[ PosD + 1 ] = Listing[ PosD + 2 ] = ' ';
+ PosD += 3;
+ }
+ char * p = Inst;
+ while( * p )
+ Listing[ PosD++ ] = * p++;
+
+ Listing[ PosD++ ] = '\r';
+ Listing[ PosD++ ] = '\n';
+ }
+}
diff --git a/tools/iDSK/src/Desass.h b/tools/iDSK/src/Desass.h
new file mode 100644
index 0000000..647f535
--- /dev/null
+++ b/tools/iDSK/src/Desass.h
@@ -0,0 +1,8 @@
+#ifndef DESASS_H
+#define DESASS_H
+
+
+void Desass( unsigned char * Prg, char * Desass, int Longueur );
+
+
+#endif
diff --git a/tools/iDSK/src/GestDsk.cpp b/tools/iDSK/src/GestDsk.cpp
new file mode 100644
index 0000000..f1063cd
--- /dev/null
+++ b/tools/iDSK/src/GestDsk.cpp
@@ -0,0 +1,1183 @@
+#include <iostream>
+#include <string.h>
+#include <cstdlib>
+#include <cstdio>
+#include <algorithm>
+#include <sstream>
+
+#include "MyType.h"
+#include "GestDsk.h"
+#include "endianPPC.h"
+#include "Outils.h"
+#include <cerrno>
+
+#ifdef _MSC_VER
+#define snprintf _snprintf
+#endif
+
+using namespace std;
+
+char Listing[ 0x280000 ];
+unsigned char BufFile[ 0x10000 ];
+int TailleFic, CurLigne;
+
+
+//
+// Verifie si en-tete AMSDOS est valide
+//
+bool CheckAmsdos( unsigned char * Buf ) {
+ int i, Checksum = 0;
+ bool ModeAmsdos = false;
+ unsigned short CheckSumFile;
+ CheckSumFile = Buf[ 0x43 ] + Buf[ 0x43 +1 ] *256;
+ for ( i = 0; i < 67; i++ )
+ Checksum += Buf[ i ];
+
+ if ( ( CheckSumFile == ( unsigned short )Checksum ) && Checksum )
+ ModeAmsdos = true;
+
+ return( ModeAmsdos );
+}
+
+
+
+//
+// CrŽe une en-tte AMSDOS par dŽfaut
+//
+StAmsdos * CreeEnteteAmsdos( char * NomFic, unsigned short Longueur ) {
+ static char NomReel[ 256 ];
+ static StAmsdos Entete;
+ static char Nom[ 12 ];
+ int i;
+
+ strcpy( NomReel, NomFic );
+ memset( &Entete, 0, sizeof( Entete ) );
+ memset( Nom, ' ', sizeof( Nom ) );
+ char * p = NULL;
+ do {
+ p = strchr( NomReel, '/' ); //Sous linux c'est le / qu'il faut enlever ...
+ if ( p )
+ strcpy( NomReel, ++p );
+ } while( p );
+ p = strchr( NomReel, '.' );
+ if ( p )
+ * p++ = 0;
+
+ int l = strlen( NomReel );
+ if ( l > 8 )
+ l = 8;
+
+ for ( int i = 0; i < l; i++ )
+ Nom[ i ] = ( char )toupper( NomReel[ i ] );
+
+ if ( p )
+ for ( i = 0; i < 3; i++ )
+ Nom[ i + 8 ] = ( char )toupper( p[ i ] );
+
+ memcpy( Entete.FileName, Nom, 11 );
+ Entete.Length = 0; //Non renseigné par AMSDos !!
+ Entete.RealLength = Entete.LogicalLength = Longueur;
+ Entete.FileType = 2; //Fichier binaire
+
+ SetChecksum(&Entete);
+
+ return( &Entete );
+}
+
+
+//
+// Calcule et positionne le checksum AMSDOS
+//
+void SetChecksum( StAmsdos * pEntete ) {
+ int i, Checksum = 0;
+ unsigned char * p = ( unsigned char * )pEntete;
+ for ( i = 0; i < 67; i++ )
+ Checksum += * (p+i);
+
+ pEntete->CheckSum = ( unsigned short )Checksum;
+}
+
+
+//
+// Effectue un "nettoyage" de l'en-tete Amsdos :
+// remet a zero les octets inutilises
+//
+void ClearAmsdos( unsigned char * Buf ) {
+ if ( CheckAmsdos( Buf ) ) {
+ int i, Checksum = 0;
+ StAmsdos * pEntete = ( StAmsdos * )Buf;
+ memset( pEntete->Unused, 0, sizeof( pEntete->Unused ) );
+ memset( pEntete->Unused2, 0, sizeof( pEntete->Unused2 ) );
+ for ( i = 0; i < 67; i++ )
+ Checksum += Buf[ i ];
+
+ Buf[ 0x43 ] = ( unsigned short )Checksum;
+ }
+}
+
+//
+// Recherche le plus petit secteur d'une piste
+//
+int DSK::GetMinSect( void ) {
+ int Sect = 0x100;
+ CPCEMUTrack * tr = ( CPCEMUTrack * )&ImgDsk[ sizeof( CPCEMUEnt ) ];
+ for ( int s = 0; s < tr->NbSect; s++ )
+ if ( Sect > tr->Sect[ s ].R )
+ Sect = tr->Sect[ s ].R;
+
+ return( Sect );
+}
+
+
+//
+// Retourne la position d'un secteur dans le fichier DSK
+//
+int DSK::GetPosData( int track, int sect, bool SectPhysique ) {
+ // Recherche position secteur
+ int Pos = sizeof( CPCEMUEnt );
+ CPCEMUTrack * tr = ( CPCEMUTrack * )&ImgDsk[ Pos ];
+ short SizeByte;
+ for ( int t = 0; t <= track; t++ ) {
+ Pos += sizeof( CPCEMUTrack );
+ for ( int s = 0; s < tr->NbSect; s++ ) {
+ if ( t == track ) {
+ if ( ( ( tr->Sect[ s ].R == sect ) && SectPhysique )
+ || ( ( s == sect ) && ! SectPhysique )
+ )
+ break;
+ }
+ SizeByte = tr->Sect[ s ].SizeByte ;
+ if (SizeByte)
+ Pos += SizeByte;
+ else
+ Pos += ( 128 << tr->Sect[ s ].N );
+ }
+ }
+ return( Pos );
+}
+
+
+//
+// Recherche un bloc libre et le remplit
+//
+int DSK::RechercheBlocLibre( int MaxBloc ) {
+ for ( int i = 2; i < MaxBloc; i++ )
+ if ( ! Bitmap[ i ] ) {
+ Bitmap[ i ] = 1;
+ return( i );
+ }
+ return( 0 );
+}
+
+
+//
+// Recherche une entrŽe de rŽpertoire libre
+//
+int DSK::RechercheDirLibre( void ) {
+ for ( int i = 0; i < 64; i++ ) {
+ StDirEntry * Dir = GetInfoDirEntry( i );
+ if ( Dir->User == USER_DELETED )
+ return( i );
+ }
+ return( -1 );
+}
+
+
+//
+// Retourne les donnŽes "brutes" de l'image disquette
+//
+unsigned char * DSK::GetRawData( int Pos ) {
+ return( &ImgDsk[ Pos ] );
+}
+
+
+//
+// Ecriture de donnŽes "brutes" dans l'image disquette
+//
+void DSK::WriteRawData( int Pos, unsigned char * Data, int Longueur ) {
+ memcpy( &ImgDsk[ Pos ], Data, Longueur );
+}
+
+
+//
+// Retourne la taille du fichier image
+//
+int DSK::GetTailleDsk( void ) {
+ CPCEMUEnt * Infos = ( CPCEMUEnt * )ImgDsk;
+ int NbTracks = Infos->NbTracks;
+ int Pos = sizeof( CPCEMUEnt );
+ CPCEMUTrack * tr = ( CPCEMUTrack * )&ImgDsk[ Pos ];
+ for ( int t = 0; t < NbTracks; t++ ) {
+ Pos += sizeof( CPCEMUTrack );
+ for ( int s = 0; s < tr->NbSect; s++ ) {
+ if ( tr->Sect[ s ].SizeByte )
+ Pos += tr->Sect[ s ].SizeByte;
+ else
+ Pos += ( 128 << tr->Sect[ s ].N );
+ }
+ }
+ return( Pos );
+}
+
+
+//
+// Retourne le nombre de pistes de la disquette
+//
+int DSK::GetNbTracks( void ) {
+ CPCEMUEnt * Infos = ( CPCEMUEnt * )ImgDsk;
+ return( Infos->NbTracks );
+}
+
+
+//
+// Lecture d'un bloc AMSDOS (1 block = 2 secteurs)
+//
+unsigned char * DSK::ReadBloc( int bloc ) {
+ static unsigned char BufBloc[ SECTSIZE * 2 ];
+ int track = ( bloc << 1 ) / 9;
+ int sect = ( bloc << 1 ) % 9;
+ int MinSect = GetMinSect();
+ if ( MinSect == 0x41 )
+ track += 2;
+ else
+ if ( MinSect == 0x01 )
+ track++;
+
+ int Pos = GetPosData( track, sect + MinSect, true );
+ memcpy( BufBloc, &ImgDsk[ Pos ], SECTSIZE );
+ if ( ++sect > 8 ) {
+ track++;
+ sect = 0;
+ }
+
+ Pos = GetPosData( track, sect + MinSect, true );
+ memcpy( &BufBloc[ SECTSIZE ], &ImgDsk[ Pos ], SECTSIZE );
+ return( BufBloc );
+}
+
+
+//
+// Formatter une piste
+//
+void DSK::FormatTrack( CPCEMUEnt * Infos, int t, int MinSect, int NbSect ) {
+ CPCEMUTrack * tr = ( CPCEMUTrack * )&ImgDsk[ sizeof( CPCEMUEnt ) + t * Infos->DataSize ];
+ memset( &ImgDsk[ sizeof( CPCEMUEnt )
+ + sizeof( CPCEMUTrack )
+ + ( t * Infos->DataSize )
+ ]
+ , 0xE5
+ , 0x200 * NbSect
+ );
+ strcpy( tr->ID, "Track-Info\r\n" );
+ tr->Track = ( unsigned char )t;
+ tr->Head = 0;
+ tr->SectSize = 2;
+ tr->NbSect = ( unsigned char )NbSect;
+ tr->Gap3 = 0x4E;
+ tr->OctRemp = 0xE5;
+ int ss = 0;
+ //
+ // Gestion "entrelacement" des secteurs
+ //
+ for ( int s = 0; s < NbSect; ) {
+ tr->Sect[ s ].C = ( unsigned char )t;
+ tr->Sect[ s ].H = 0;
+ tr->Sect[ s ].R = ( unsigned char )( ss + MinSect );
+ tr->Sect[ s ].N = 2;
+ tr->Sect[ s ].SizeByte = 0x200;
+ ss++;
+ if ( ++s < NbSect ) {
+ tr->Sect[ s ].C = ( unsigned char )t;
+ tr->Sect[ s ].H = 0;
+ tr->Sect[ s ].R = ( unsigned char )( ss + MinSect + 4 );
+ tr->Sect[ s ].N = 2;
+ tr->Sect[ s ].SizeByte = 0x200;
+ s++;
+ }
+ }
+}
+
+
+//
+// Ecriture d'un bloc AMSDOS (1 block = 2 secteurs)
+//
+void DSK::WriteBloc( int bloc, unsigned char BufBloc[ SECTSIZE * 2 ] ) {
+ int track = ( bloc << 1 ) / 9;
+ int sect = ( bloc << 1 ) % 9;
+ int MinSect = GetMinSect();
+ if ( MinSect == 0x41 )
+ track += 2;
+ else
+ if ( MinSect == 0x01 )
+ track++;
+
+ //
+ // Ajuste le nombre de pistes si dŽpassement capacitŽ
+ //
+ CPCEMUEnt * Entete = ( CPCEMUEnt * )ImgDsk;
+ if ( track > Entete->NbTracks - 1 ) {
+ Entete->NbTracks = ( unsigned char )( track + 1 );
+ FormatTrack( Entete, track, MinSect, 9 );
+ }
+
+ int Pos = GetPosData( track, sect + MinSect, true );
+ memcpy( &ImgDsk[ Pos ], BufBloc, SECTSIZE );
+ if ( ++sect > 8 ) {
+ track++;
+ sect = 0;
+ }
+ Pos = GetPosData( track, sect + MinSect, true );
+ memcpy( &ImgDsk[ Pos ], &BufBloc[ SECTSIZE ], SECTSIZE );
+}
+
+
+//
+// Ecriture d'un secteur
+//
+void DSK::WriteSect( int Track, int Sect, unsigned char * Buff, int AmsdosMode ) {
+ int MinSect = AmsdosMode ? GetMinSect() : 0;
+ if ( ( MinSect == 0x41 ) && AmsdosMode )
+ Track += 2;
+ else
+ if ( ( MinSect == 0x01 ) && AmsdosMode )
+ Track++;
+
+ int Pos = GetPosData( Track, Sect + MinSect, AmsdosMode );
+ memcpy( &ImgDsk[ Pos ], Buff, SECTSIZE );
+}
+
+
+//
+// Lecture d'un secteur
+//
+unsigned char * DSK::ReadSect( int Track, int Sect, int AmsdosMode ) {
+ int MinSect = AmsdosMode ? GetMinSect() : 0;
+ if ( ( MinSect == 0x41 ) && AmsdosMode )
+ Track += 2;
+ else
+ if ( ( MinSect == 0x01 ) && AmsdosMode )
+ Track++;
+
+ int Pos = GetPosData( Track, Sect + MinSect, AmsdosMode );
+ return( &ImgDsk[ Pos ] );
+}
+
+
+//
+// Retourne les informations d'une piste
+//
+CPCEMUTrack * DSK::GetInfoTrack( int Track ) {
+ int Pos = sizeof( CPCEMUEnt );
+ CPCEMUTrack * tr = ( CPCEMUTrack * )&ImgDsk[ Pos ];
+ for ( int t = 0; t < Track; t++ ) {
+ Pos += sizeof( CPCEMUTrack );
+
+ for ( int s = 0; s < tr->NbSect; s++ ) {
+ if ( tr->Sect[ s ].SizeByte )
+ Pos += tr->Sect[ s ].SizeByte;
+ else
+ Pos += ( 128 << tr->Sect[ s ].N );
+ }
+ }
+ return( ( CPCEMUTrack * )&ImgDsk[ Pos ] );
+}
+
+//
+// Remplit un "bitmap" pour savoir o il y a des fichiers sur la disquette
+// Retourne Žgalement le nombre de Ko utilisŽs sur la disquette
+//
+int DSK::FillBitmap( void ) {
+ int NbKo = 0;
+
+ memset( Bitmap, 0, sizeof( Bitmap ) );
+ Bitmap[ 0 ] = Bitmap[ 1 ] = 1;
+ for ( int i = 0; i < 64; i++ ) {
+ StDirEntry * Dir = GetInfoDirEntry( i );
+ if ( Dir->User != USER_DELETED ) {
+ for ( int j = 0; j < 16; j++ ) {
+ int b = Dir->Blocks[ j ];
+ if ( b > 1 && ( ! Bitmap[ b ] ) ) {
+ Bitmap[ b ] = 1;
+ NbKo++;
+ }
+ }
+ }
+ }
+ return( NbKo );
+}
+
+
+//
+// Positionne une entrŽe dans le rŽpertoire
+//
+void DSK::SetInfoDirEntry( int NumDir, StDirEntry * Dir ) {
+ int MinSect = GetMinSect();
+ int s = ( NumDir >> 4 ) + MinSect;
+ int t = ( MinSect == 0x41 ? 2 : 0 );
+ if ( MinSect == 1 )
+ t = 1;
+
+ for (int i =0; i<16; i++)
+ memcpy( &ImgDsk[ ( ( NumDir & 15 ) << 5 ) + GetPosData( t, s, true ) ]
+ , Dir
+ , sizeof( StDirEntry )
+ );
+}
+
+
+//
+// VŽrifie l'existente d'un fichier, retourne l'indice du fichier si existe,
+// -1 sinon
+//
+int DSK::FileExist( char * Nom ) {
+ int i;
+ for ( i = 0; i < 64; i++ ) {
+ StDirEntry * Dir = GetInfoDirEntry( i );
+ for(int q=0;q<12;q++)
+ Dir->Nom[q]=Dir->Nom[q]&127; // Avoid missing hidden files
+ if ( Dir->User != USER_DELETED
+ && ! strncmp( Nom, ( char * )Dir->Nom, 11 ) // 11 = 8+3 car le point est enlevé
+ )
+ return( i );
+ }
+ return( -1 );
+}
+
+
+StDirEntry * DSK::GetNomDir( string NomFic ) {
+ static StDirEntry DirLoc;
+ int i;
+
+ memset( &DirLoc, 0, sizeof( DirLoc ) );
+ memset( DirLoc.Nom, ' ', 8 );
+ memset( DirLoc.Ext, ' ', 3 );
+ size_t p = NomFic.find('.');
+ if ( p!=std::string::npos )
+ {
+ NomFic.copy( DirLoc.Nom, std::min((int)p,8), 0);
+ p++;
+ NomFic.copy( DirLoc.Ext, std::min( (int)(NomFic.size()-p), 3 ), p );
+ }
+ else
+ NomFic.copy( DirLoc.Nom, std::min((int)NomFic.size(), 8 ),0);
+
+ for ( i = 0; i < 11; i++ )
+ DirLoc.Nom[ i ] = ( unsigned char )toupper( DirLoc.Nom[ i ] );
+
+ return( &DirLoc );
+}
+
+
+int DSK::FileIsIn( string FileName ) {
+ StDirEntry * DirLoc = GetNomDir( FileName );
+ return FileExist( ( char*) DirLoc->Nom );
+}
+
+//
+// Copie un fichier sur le DSK
+//
+// la taille est determine par le nombre de NbPages
+// regarder pourquoi different d'une autre DSK
+int DSK::CopieFichier( unsigned char * BufFile, char * NomFic, int TailleFic, int MaxBloc, int UserNumber, bool System_file, bool Read_only ) {
+ int j, l, Bloc, PosFile, NbPages = 0, PosDir, TaillePage;
+ FillBitmap();
+ StDirEntry * DirLoc = GetNomDir( NomFic ); //Construit l'entrée pour mettre dans le catalogue
+ for ( PosFile = 0; PosFile < TailleFic; ) { //Pour chaque bloc du fichier
+ PosDir = RechercheDirLibre(); //Trouve une entrée libre dans le CAT
+ if ( PosDir != -1 ) {
+ DirLoc->User = UserNumber; //Remplit l'entrée : User 0
+ if(System_file) DirLoc->Nom[9]|=0x80;
+ if(Read_only) DirLoc->Nom[8]|=0x80;
+ DirLoc->NumPage = ( unsigned char )NbPages++; // Numéro de l'entrée dans le fichier
+ TaillePage = (TailleFic - PosFile + 127) >> 7 ; // Taille de la page (on arrondit par le haut)
+ if ( TaillePage > 128 ) // Si y'a plus de 16k il faut plusieurs pages
+ TaillePage = 128;
+
+ DirLoc->NbPages = ( unsigned char )TaillePage;
+ l = ( DirLoc->NbPages + 7 ) >> 3; //Nombre de blocs=TaillePage/8 arrondi par le haut
+ memset( DirLoc->Blocks, 0, 16 );
+ for ( j = 0; j < l; j++ ) { //Pour chaque bloc de la page
+ Bloc = RechercheBlocLibre( MaxBloc ); //Met le fichier sur la disquette
+ if ( Bloc ) {
+ DirLoc->Blocks[ j ] = ( unsigned char )Bloc;
+ WriteBloc( Bloc, &BufFile[ PosFile ] );
+ PosFile += 1024; // Passe au bloc suivant
+ }
+ else
+ return( ERR_NO_BLOCK );
+
+ }
+ SetInfoDirEntry( PosDir, DirLoc );
+ }
+ else
+ return( ERR_NO_DIRENTRY );
+ }
+ return( ERR_NO_ERR );
+}
+
+
+//
+// Retourne une entrŽe du rŽpertoire
+//
+StDirEntry * DSK::GetInfoDirEntry( int NumDir ) {
+ static StDirEntry Dir;
+ int MinSect = GetMinSect();
+ int s = ( NumDir >> 4 ) + MinSect;
+ int t = ( MinSect == 0x41 ? 2 : 0 );
+ if ( MinSect == 1 )
+ t = 1;
+
+ memcpy( &Dir
+ , &ImgDsk[ ( ( NumDir & 15 ) << 5 ) + GetPosData( t, s, true ) ]
+ , sizeof( StDirEntry )
+ );
+ return( &Dir );
+}
+
+
+//
+// VŽrifier si DSK est "standard" (DATA ou VENDOR)
+//
+bool DSK::CheckDsk( void ) {
+ CPCEMUEnt * Infos = ( CPCEMUEnt * )ImgDsk;
+ if ( Infos->NbHeads == 1 ) {
+ int MinSectFirst = GetMinSect();
+ if ( MinSectFirst != 0x41 && MinSectFirst != 0xC1 && MinSectFirst != 0x01 )
+ {
+ cout << "DSK has wrong sector number!" << endl;
+ return( false );
+ }
+
+
+ if ( Infos->NbTracks > 42 )
+ Infos->NbTracks = 42;
+
+ for ( int track = 0; track < Infos->NbTracks; track++ ) {
+ // Recherche position secteur
+ int Pos = sizeof( CPCEMUEnt ) + ( 0x1200 + sizeof( CPCEMUTrack ) ) * track;
+ CPCEMUTrack * tr = ( CPCEMUTrack * )&ImgDsk[ Pos ];
+
+ int MinSect = 0xFF, MaxSect = 0;
+ if ( tr->NbSect != 9 )
+ {
+ cout << "Warning : track " << track <<" has "<<tr->NbSect<<" sectors ! (wanted 9)" << endl;
+ // return( false );
+ }
+ for ( int s = 0; s < (int)tr->NbSect; s++ ) {
+ if ( MinSect > tr->Sect[ s ].R )
+ MinSect = tr->Sect[ s ].R;
+
+ if ( MaxSect < tr->Sect[ s ].R )
+ MaxSect = tr->Sect[ s ].R;
+ }
+ if ( MaxSect - MinSect != 8 )
+ {
+ cout << "Warning : trange sector numbering in track "<<track<<"!" << endl;
+ // return( false );
+ }
+ if ( MinSect != MinSectFirst )
+ {
+ cout << "Warning : track "<<track<<" start at sector"<<MinSect<<" while track 0 starts at "<<MinSectFirst << endl;
+ //return( false );
+ }
+ }
+ return( true );
+ }
+ cout << "Multi-side dsk ! Expected 1 head, got " << (int)Infos->NbHeads << endl;
+ return( false );
+}
+
+
+//
+// Lire un fichier DSK
+//
+bool DSK::ReadDsk( std::string NomFic ) {
+ bool Ret = false;
+ CPCEMUEnt * Infos;
+ if(sizeof(CPCEMUEnt) != 0x100) cout << "INVALID DSK BUILD" << endl;
+ FILE* fp ;
+
+ if ( (fp=fopen(NomFic.c_str(),"rb"))!=NULL ) {
+ fread(ImgDsk,sizeof(ImgDsk),1,fp);
+ Infos = ( CPCEMUEnt * )ImgDsk;
+ if ( isBigEndian( ) ) FixEndianDsk( false ); // fix endian for Big endianness machines (PPC)
+ if ( ! strncmp( Infos->debut, "MV -", 4 )
+ || ! strncmp( Infos->debut, "EXTENDED CPC DSK", 16 )
+ )
+ Ret = true;
+ fclose(fp);
+ }
+ return( Ret );
+}
+
+
+//
+// Formatter une disquette
+//
+void DSK::FormatDsk( int NbSect, int NbTrack ) {
+ CPCEMUEnt * Infos = ( CPCEMUEnt * )ImgDsk;
+
+ strcpy( Infos->debut, "MV - CPCEMU Disk-File\r\nDisk-Info\r\n" );
+ Infos->DataSize = ( short )( sizeof( CPCEMUTrack ) + (0x200 * NbSect) );
+ Infos->NbTracks = ( unsigned char ) NbTrack;
+ Infos->NbHeads = 1;
+ for ( int t = 0; t < NbTrack; t++ )
+ FormatTrack( Infos, t, 0xC1, NbSect );
+
+
+ FillBitmap();
+}
+
+
+
+//
+// Modifie le endianness de la disquette
+//
+void DSK::FixEndianDsk( bool littleToBig) {
+ CPCEMUEnt * Infos = ( CPCEMUEnt * )ImgDsk;
+ //std::cerr<< "FixEndianDsk() Infos->DataSize : " << Infos->DataSize <<std::endl;
+
+ if ( ! littleToBig )
+ Infos->DataSize = FIX_SHORT( Infos->DataSize );
+ for ( int t = 0; t < Infos->NbTracks; t++ )
+ FixEndianTrack( Infos, t, 9 );
+ if ( littleToBig )
+ Infos->DataSize = FIX_SHORT( Infos->DataSize );
+ FillBitmap();
+}
+
+//
+// Modifie le endianness de la piste
+//
+void DSK::FixEndianTrack( CPCEMUEnt * Infos, int t, int NbSect ) {
+ CPCEMUTrack *tr;
+ if ( Infos->DataSize != 0 )
+ tr = ( CPCEMUTrack * )&ImgDsk[ sizeof( CPCEMUEnt ) + t * Infos->DataSize ];
+ else {
+ int ExtendedDataSize = ImgDsk[ 0x34 + t ] *256; //case of a extended dsk image
+ tr = ( CPCEMUTrack * )&ImgDsk[ sizeof( CPCEMUEnt ) + t * ExtendedDataSize ];
+ }
+ int ss = 0;
+
+ //
+ // Gestion "entrelacement" des secteurs
+ //
+ for ( int s = 0; s < NbSect; ) {
+ tr->Sect[ s ].SizeByte = FIX_SHORT( tr->Sect[ s ].SizeByte );
+ tr->Sect[ s ].Un1 = FIX_SHORT( tr->Sect[ s ].Un1 );
+ ss++;
+ if ( ++s < NbSect ) {
+ tr->Sect[ s ].SizeByte = FIX_SHORT( tr->Sect[ s ].SizeByte );
+ tr->Sect[ s ].Un1 = FIX_SHORT( tr->Sect[ s ].Un1 );
+ s++;
+ }
+ }
+ tr->Unused = FIX_SHORT( tr->Unused );
+}
+
+
+//
+// Ecriture du fichier DSK
+//
+bool DSK::WriteDsk( string NomDsk ) {
+ CPCEMUEnt * Infos = ( CPCEMUEnt * )ImgDsk;
+ FILE* fp;
+ int Taille,Copie;
+
+
+ if ( (fp=fopen(NomDsk.c_str(),"wb+")) != NULL) {
+ if ( ! Infos->DataSize ) Infos->DataSize = 0x100 + SECTSIZE * 9;
+ Taille = Infos->NbTracks * Infos->DataSize + sizeof( * Infos );
+ if ( isBigEndian() ) FixEndianDsk( true ) ; // Fix endianness for Big endian machines (PPC)
+
+ if ( (Copie=(fwrite(ImgDsk,1,Taille,fp))) !=Taille ) ;
+ fclose(fp);
+ // in case of the same DSK image stay in memory
+ if ( isBigEndian() ) FixEndianDsk( false ) ; // unFix endianness for Big endian machines (PPC)
+
+ return( true );
+ }
+ return( false );
+}
+
+
+void DSK::DskEndian() {
+ CPCEMUEnt * Infos = ( CPCEMUEnt * )ImgDsk;
+ for ( int i=1 ; i<(int)Infos->NbTracks ; i++) {
+ CPCEMUTrack * TrackData = GetInfoTrack( i );
+ TrackData = CPCEMUTrackEndian ( TrackData ) ;
+ }
+ Infos = CPCEMUEntEndian ( Infos ) ;
+}
+
+
+StAmsdos* DSK::StAmsdosEndian ( StAmsdos * pEntete ){
+ pEntete->Length = FIX_SHORT( pEntete->Length );
+ pEntete->Adress = FIX_SHORT( pEntete->Adress );
+ pEntete->LogicalLength = FIX_SHORT( pEntete->LogicalLength);
+ pEntete->EntryAdress = FIX_SHORT( pEntete->EntryAdress );
+ pEntete->RealLength = FIX_SHORT( pEntete->RealLength );
+ pEntete->CheckSum = FIX_SHORT( pEntete->CheckSum ) ;
+ return ( pEntete );
+}
+
+
+CPCEMUEnt* DSK::CPCEMUEntEndian ( CPCEMUEnt* Infos ) {
+ Infos->DataSize = FIX_SHORT( Infos->DataSize );
+ return (Infos);
+}
+
+
+CPCEMUTrack* DSK::CPCEMUTrackEndian ( CPCEMUTrack* tr ) {
+ for ( int i=0;i < (int)tr->NbSect ; i++) {
+ tr->Sect[i] = CPCEMUSectEndian( tr->Sect[i] );
+ }
+
+ return ( tr);
+
+}
+
+
+CPCEMUSect DSK::CPCEMUSectEndian ( CPCEMUSect Sect) {
+ Sect.Un1 = FIX_SHORT( Sect.Un1 );
+ Sect.SizeByte = FIX_SHORT( Sect.SizeByte );
+ return (Sect);
+}
+
+// Retourne le type de fichier sous forme de chaine
+//
+const char * DSK::GetType( int Langue, StAmsdos * Ams ) {
+ if ( CheckAmsdos( ( unsigned char * )Ams ) ) {
+ switch( Ams->FileType ) {
+ case 0 : // BASIC
+ return( "BASIC"); //GetTexteLoc( 22, Langue ) );
+
+ case 1 : // BASIC (P)
+ return( "BASIC(P)"); // GetTexteLoc( 23, Langue ) );
+
+ case 2 : // BINAIRE
+ return("BINAIRE"); // GetTexteLoc( 24, Langue ) );
+
+ case 3 : // BINAIRE (P)
+ return( "BINAIRE(P)"); //GetTexteLoc( 25, Langue ) );
+
+ default :
+ return( "INCONNU"); // GetTexteLoc( 26, Langue ) );
+ }
+ }
+ return("ASCII"); // GetTexteLoc( 27, Langue ) );
+}
+
+char * DSK::GetEntryNameInCatalogue ( int num , char* Nom ) {
+ int PosItem[ 64 ];
+ StDirEntry TabDir[ 64 ];
+
+ memset( PosItem, 0, sizeof( PosItem ) );
+
+ for ( int i = 0; i < 64; i++ )
+ memcpy( &TabDir[ i ], GetInfoDirEntry( i ), sizeof( StDirEntry ));
+
+ for ( int i = 0; i < 64; i++ ) {
+ SetInfoDirEntry( i, &TabDir[ i ] );
+
+ if ( TabDir[ i ].User != USER_DELETED && ! TabDir[ i ].NumPage && num == i) {
+ memcpy( Nom, TabDir[ i ].Nom, 8 );
+ memcpy( &Nom[ 9 ], TabDir[ i ].Ext, 3 );
+ Nom[ 8 ] = '.';
+ Nom[ 12 ] = 0;
+ for ( int j = 0; j < 12; j++ )
+ Nom[ j ] &= 0x7F;
+ for ( int j = 0; j < 12; j++ )
+ if ( ! isprint( Nom[ j ] ) )
+ Nom[ j ] = '?' ;
+ return Nom;
+ }
+ }
+ return Nom;
+}
+
+char * DSK::GetEntrySizeInCatalogue ( int num , char* Size ) {
+ int PosItem[ 64 ];
+ StDirEntry TabDir[ 64 ];
+
+
+ memset( PosItem, 0, sizeof( PosItem ) );
+
+ for ( int i = 0; i < 64; i++ )
+ memcpy( &TabDir[ i ], GetInfoDirEntry( i ), sizeof( StDirEntry ));
+
+ for ( int i = 0; i < 64; i++ ) {
+ SetInfoDirEntry( i, &TabDir[ i ] );
+
+ if ( TabDir[ i ].User != USER_DELETED && ! TabDir[ i ].NumPage && num == i) {
+ int p = 0, t = 0;
+ do {
+ if ( TabDir[ p + i ].User == TabDir[ i ].User ) {
+ t += TabDir[ p + i ].NbPages;
+ }
+ p++;
+ }
+ while( TabDir[ p + i ].NumPage && ( p + i ) < 64 );
+ sprintf( Size, "%d Ko", ( t + 7 ) >>3 );
+ return Size;
+ }
+ }
+ return Size;
+}
+
+
+bool DSK::GetFileInDsk( char* path, int Indice ){
+ int i = Indice;
+ char current[ 16 ];
+ char NomIndice[ 16 ];
+ int lMax = 0x1000000;
+ int cumul=0;
+ FILE* f;
+ StDirEntry TabDir[ 64 ];
+
+ if ( (f=fopen(path,"wb"))==NULL )
+ return false;
+
+ for ( int i = 0; i < 64; i++ )
+ memcpy( &TabDir[ i ], GetInfoDirEntry( i ), sizeof( StDirEntry ));
+
+
+ memset( NomIndice, 0 , sizeof( NomIndice ) );
+ strncpy( NomIndice, GetNomAmsdos( TabDir[ i ].Nom ), 16);
+ strncat( NomIndice, GetNomAmsdos( TabDir[ i ].Ext), 3);
+
+ do
+ {
+ // Longueur du fichier
+ int l = ( TabDir[ i ].NbPages + 7 ) >> 3;
+ for ( int j = 0; j < l; j++ ) {
+ int TailleBloc = 1024;
+ unsigned char * p = ReadBloc( TabDir[ i ].Blocks[ j ] );
+ int NbOctets = min( lMax, TailleBloc );
+ if ( NbOctets > 0 ) {
+ fwrite(p,1,NbOctets,f);
+ cumul+=NbOctets;
+ }
+ lMax -= 1024;
+ }
+ memset( current , 0, sizeof( current ) );
+ i++;
+ strncpy(current, GetNomAmsdos( TabDir[ i ].Nom ), 16 );
+ strncat(current, GetNomAmsdos( TabDir[ i ].Ext ), 3);
+
+ if ( i > 64 ) return false;
+ }while (! strncmp( NomIndice, current , max( strlen( NomIndice ), strlen( current ) )));
+
+ fclose (f);
+ return true;
+}
+
+
+bool DSK::PutFileInDsk( string Masque ,int TypeModeImport ,int loadAdress, int exeAdress, int UserNumber, bool System_file, bool Read_only ) {
+ static unsigned char Buff[ 0x20000 ];
+ static char *cFileName;
+ unsigned long Lg;
+ bool ret;
+ FILE* Hfile;
+ if ( NULL==(cFileName = (char*)malloc(16*sizeof(char))) )
+ return false;
+
+ cFileName = GetNomAmsdos((char *)Masque.c_str());
+ if (( Hfile = fopen(Masque.c_str(),"rb")) == NULL ) return false;
+ Lg=fread(Buff,1, 0x20000 ,Hfile);
+ fclose( Hfile );
+ bool AjouteEntete = false;
+ StAmsdos * e = ( StAmsdos * )Buff;
+ // Attention : longueur > 64Ko !
+ if ( Lg > 0x10080 ) {
+ free(cFileName);
+ return false;
+ }
+
+ //
+ // Regarde si le fichier contient une en-tete ou non
+ //
+ bool IsAmsdos = CheckAmsdos( Buff );
+
+ if ( ! IsAmsdos ) {
+ // Creer une en-tete amsdos par defaut
+ cout << "Création automatique d'une en-tête pour le fichier ...\n";
+ e = CreeEnteteAmsdos( cFileName, ( unsigned short )Lg );
+ if ( loadAdress != 0)
+ {
+ e->Adress = (unsigned short)loadAdress;
+ TypeModeImport = MODE_BINAIRE;
+ }
+ if ( exeAdress != 0 )
+ {
+ e->EntryAdress = (unsigned short)exeAdress;
+ TypeModeImport = MODE_BINAIRE;
+ }
+ // Il faut recalculer le checksum en comptant es adresses !
+ SetChecksum(e);
+ // fix the endianness of the input file
+ if ( isBigEndian() ) e = StAmsdosEndian(e);
+ }
+ else
+ cout << "Le fichier a déjà une en-tête\n";
+ //
+ // En fonction du mode d'importation...
+ //
+ switch( TypeModeImport ) {
+ case MODE_ASCII :
+ //
+ // Importation en mode ASCII
+ //
+ if ( IsAmsdos ) {
+ // Supprmier en-tete si elle existe
+ memcpy( Buff, &Buff[ sizeof( StAmsdos ) ], Lg - sizeof( StAmsdos ));
+ Lg -= sizeof( StAmsdos );
+ }
+ break;
+
+ case MODE_BINAIRE :
+ //
+ // Importation en mode BINAIRE
+ //
+
+ if ( ! IsAmsdos )
+ //
+ // Indique qu'il faudra ajouter une en-tete
+ //
+ AjouteEntete = true;
+ break;
+
+ }
+
+ //
+ // Si fichier ok pour etre import
+ //
+ if ( AjouteEntete ) {
+ // Ajoute l'en-tete amsdos si necessaire
+
+ memmove( &Buff[ sizeof( StAmsdos ) ], Buff, Lg );
+ memcpy( Buff, e, sizeof( StAmsdos ) );
+ Lg += sizeof( StAmsdos );
+ }
+
+ //if (MODE_BINAIRE) ClearAmsdos(Buff); //Remplace les octets inutilisés par des 0 dans l'en-tête
+
+ if ( CopieFichier( Buff,cFileName,Lg,256, UserNumber, System_file, Read_only) != ERR_NO_ERR )
+ ret = false;
+ else
+ ret = true;
+
+ return ret;
+}
+
+
+bool DSK::OnViewFic(int nItem) {
+ int LongFic = 0;
+ memset( BufFile, 0, sizeof( BufFile ) );
+ memset( Listing, 0, sizeof( Listing ) );
+ char NomFic[ 16 ];
+ char current[ 16 ];
+ int i = nItem;
+ bool FirstBlock = true;
+ StDirEntry TabDir[ 64 ];
+
+ for ( int j = 0; j < 64; j++ )
+ memcpy( &TabDir[ j ], GetInfoDirEntry( j ), sizeof( StDirEntry ));
+
+ memset( NomFic, 0 , sizeof( NomFic ) );
+ strncpy( NomFic, GetNomAmsdos( TabDir[ i ].Nom ), 16);
+ strncat( NomFic, GetNomAmsdos( TabDir[ i ].Ext), 3);
+
+ int lMax = sizeof( BufFile );
+
+ TailleFic = 0;
+
+
+ do
+ {
+ // Longueur du fichier
+ int l = ( TabDir[ i ].NbPages + 7 ) >> 3;
+ for ( int j = 0; j < l; j++ ) {
+ int TailleBloc = 1024;
+ unsigned char * p = ReadBloc( TabDir[ i ].Blocks[ j ] );
+ if ( FirstBlock ) {
+ if ( CheckAmsdos( p ) ) {
+ TailleFic = p[ 0x18 +1 ] *256 + p[ 0x18 ];
+ TailleBloc -= sizeof( StAmsdos );
+ memcpy( p , &p[ 0x80 ] , TailleBloc );
+ }
+ FirstBlock = false;
+
+ }
+ int NbOctets = min( lMax, TailleBloc );
+ if ( NbOctets > 0 ) {
+ memcpy( &BufFile[ LongFic ], p, NbOctets );
+ LongFic += NbOctets;
+ }
+ lMax -= 1024;
+ }
+ memset( current , 0, sizeof( current ) );
+ i++;
+ strncpy(current, GetNomAmsdos( TabDir[ i ].Nom ), 16 );
+ strncat(current, GetNomAmsdos( TabDir[ i ].Ext ), 3);
+ if ( i > 64 ) return false;
+ }while( ! strncmp( NomFic, current, max( strlen( current ), strlen( NomFic ) ) ) );
+
+ if ( TailleFic == 0 )
+ TailleFic = LongFic;
+ return true;
+}
+
+
+bool DSK::Hexdecimal() {
+
+ int TailleCourante=0;
+ char OffSet[ 7 ];
+ const char * CodeHexa = "0123456789ABCDEF";
+
+ while (TailleCourante <= TailleFic ) {
+ // display the offset
+ memset( OffSet, 0 , 7 );
+ snprintf( OffSet,6,"#%.4X:", TailleCourante );
+ strcat( Listing, OffSet );
+ strcat( Listing, " ");
+ char Ascii[ 18 ];
+ char Hex[ 16 *3 +1 ];
+ memset( Ascii, 0 , 18 );
+ memset( Hex , 0 , ( 16*3 +1) );
+ for ( int i=0; i<16 ; ++i ) {
+ unsigned char cur = BufFile[ TailleCourante + i ];
+ // manage the ascii display
+ if ( cur > 32 && cur < 125 )
+ Ascii[ i ] = cur;
+ else
+ Ascii[ i ] = '.';
+ char Val[ 4 ];
+ // manage the hexadeciaml display
+ Val[ 0 ] = CodeHexa[ cur >> 4 ];
+ Val[ 1 ] = CodeHexa[ cur & 0x0F ];
+ Val[ 2 ] = ' ';
+ Val[ 3 ] ='\0';
+ strcat( Hex, Val );
+ }
+ Ascii[ 16 ] = '\n';
+ strcat( Listing, Hex );
+ strcat( Listing, "| ");
+ strcat( Listing, Ascii );
+ TailleCourante += 16;
+ }
+
+ return true;
+}
+
+
+void DSK::RemoveFile ( int item ) {
+ char NomFic[ 16 ];
+ int i = item;
+ StDirEntry TabDir[ 64 ];
+
+ for ( int j = 0; j < 64; j++ )
+ memcpy( &TabDir[ j ], GetInfoDirEntry( j ), sizeof( StDirEntry ));
+
+ strcpy( NomFic, GetNomAmsdos( TabDir[ i ].Nom ) );
+ char *p ;
+
+ do {
+ TabDir[ i ].User = USER_DELETED;
+ SetInfoDirEntry( i, &TabDir[ i ]);
+ p = GetNomAmsdos( TabDir[ ++i ].Nom) ;
+ } while ( ! strncmp( NomFic, p , max(strlen( p ), strlen( NomFic ) )) );
+
+
+ return ;
+}
+
+
+
+void DSK::RenameFile( int item , char *NewName) {
+ char NomFic[ 16 ];
+ StDirEntry TabDir[ 64 ];
+ StDirEntry DirLoc;
+ int c = item;
+ for ( int j = 0; j < 64; j++ )
+ memcpy( &TabDir[ j ], GetInfoDirEntry( j ), sizeof( StDirEntry ));
+
+ memset( DirLoc.Nom, ' ', 8);
+ memset( DirLoc.Ext, ' ', 3);
+ for ( int i=0; i<(int) strlen( NewName ) ; ++i)
+ NewName[ i ] = toupper( NewName[ i ] );
+
+ char *p = strchr( NewName, '.');
+
+ if ( p ) {
+ p++;
+ memcpy( DirLoc.Nom, NewName, p - NewName -1);
+ memcpy( DirLoc.Ext, p, std::min((int)strlen(p),3) );
+ }
+ else {
+ memcpy( DirLoc.Nom, NewName, min( (int)strlen( NewName) , 8 ) );
+ }
+ strcpy( NomFic, GetNomAmsdos( TabDir[ c ].Nom ));
+
+ do {
+ memcpy( TabDir[ c ].Nom , DirLoc.Nom , 8 );
+ memcpy( TabDir[ c ].Ext , DirLoc.Ext, 3 );
+ SetInfoDirEntry( c, &TabDir[ c ]);
+ p = GetNomAmsdos( TabDir[ ++c ].Nom );
+ }while (!strncmp( NomFic, p , max(strlen(p),strlen(NomFic))));
+}
+
+
+std::string DSK::ReadDskDir( void ) {
+ StDirEntry TabDir[ 64 ];
+ string catalogue;
+ for ( int i = 0; i < 64; i++ ) {
+ memcpy( &TabDir[ i ]
+ , GetInfoDirEntry( i )
+ , sizeof( StDirEntry )
+ );
+ }
+ // Trier les fichiers
+ for ( int i = 0; i < 64; i++ ) {
+ //
+ // Afficher les fichiers non effacés
+ //
+ if ( TabDir[ i ].User != USER_DELETED && ! TabDir[ i ].NumPage ) {
+ char Nom[ 13 ];
+ memcpy( Nom, TabDir[ i ].Nom, 8 );
+ memcpy( &Nom[ 9 ], TabDir[ i ].Ext, 3 );
+ Nom[ 8 ] = '.';
+ Nom[ 12 ] = 0;
+ //
+ // Masquer les bits d'attributs
+ //
+ for ( int j = 0; j < 12; j++ )
+ {
+ Nom[ j ] &= 0x7F;
+
+ if ( ! isprint( Nom[ j ] ) )
+ Nom[ j ] = '?' ;
+ }
+
+ catalogue += Nom;
+ catalogue += " ";
+ ostringstream c;
+ c << (int)TabDir[i].User;
+ catalogue += c.str();
+ //
+ // Calcule la taille du fichier en fonction du nombre de blocs
+ //
+ int p = 0, t = 0;
+ do {
+ if ( TabDir[ p + i ].User == TabDir[ i ].User )
+ t += TabDir[ p + i ].NbPages;
+ p++;
+ } while( TabDir[ p + i ].NumPage && ( p + i ) < 64 );
+ //string size = GetTaille( ( t + 7 ) >> 3 );
+ //catalogue+= " : " + size + "\n";
+ catalogue += "\n";
+
+ }
+ }
+ return catalogue;
+}
diff --git a/tools/iDSK/src/GestDsk.h b/tools/iDSK/src/GestDsk.h
new file mode 100644
index 0000000..b825ab4
--- /dev/null
+++ b/tools/iDSK/src/GestDsk.h
@@ -0,0 +1,168 @@
+#ifndef GESTDSK_H
+#define GESTDSK_H
+
+#include <string>
+
+#define USER_DELETED 0xE5
+
+
+extern char Listing[ 0x280000 ];
+extern unsigned char BufFile[ 0x10000 ];
+
+
+extern int TailleFic, CurLigne;
+
+#pragma pack(1) //evite le padding des structures qui sont utilisées dans des memcpy par la suite
+
+//
+// Structure d'une entree AMSDOS
+//
+typedef struct
+{
+ unsigned char UserNumber; // 00 User
+ unsigned char FileName[15]; // 01-0F Nom + extension
+ unsigned char BlockNum; // 10 Numéro du bloc (disquette)
+ unsigned char LastBlock; // 11 Flag "dernier bloc" bloc (disquette)
+ unsigned char FileType; // 12 Type de fichier
+ unsigned short Length; // 13-14 Longueur
+ unsigned short Adress; // 15-16 Adresse
+ unsigned char FirstBlock; // 17 Flag premier bloc de fichier (disquette)
+ unsigned short LogicalLength; // 18-19 Longueur logique
+ unsigned short EntryAdress; // 1A-1B Point d'entree
+ unsigned char Unused[0x24];
+ unsigned short RealLength; // 40-42 Longueur reelle
+ unsigned char BigLength; // Longueur reelle (3 octets)
+ unsigned short CheckSum; // 43-44 CheckSum Amsdos
+ unsigned char Unused2[0x3B];
+} StAmsdos;
+
+
+#define SECTSIZE 512
+
+
+typedef struct
+{
+ char debut[0x30]; // "MV - CPCEMU Disk-File\r\nDisk-Info\r\n"
+ unsigned char NbTracks;
+ unsigned char NbHeads;
+ unsigned short DataSize; // 0x1300 = 256 + ( 512 * nbsecteurs )
+ unsigned char Unused[0xCC];
+} CPCEMUEnt;
+
+
+typedef struct
+{
+ unsigned char C; // track
+ unsigned char H; // head
+ unsigned char R; // sect
+ unsigned char N; // size
+ short Un1;
+ short SizeByte; // Taille secteur en octets
+} CPCEMUSect;
+
+
+typedef struct
+{
+ char ID[0x10]; // "Track-Info\r\n"
+ unsigned char Track;
+ unsigned char Head;
+ short Unused;
+ unsigned char SectSize; // 2
+ unsigned char NbSect; // 9
+ unsigned char Gap3; // 0x4E
+ unsigned char OctRemp; // 0xE5
+ CPCEMUSect Sect[29];
+} CPCEMUTrack;
+
+#ifdef __GNUC__
+#define PACK( __Declaration__ ) __Declaration__ __attribute__((__packed__))
+#else
+#define PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop) )
+#endif
+
+PACK(typedef struct
+{
+ unsigned char User;
+ char Nom[8];
+ char Ext[3];
+ unsigned char NumPage;
+ unsigned char Unused[2];
+ unsigned char NbPages;
+ unsigned char Blocks[16];
+}) StDirEntry;
+
+#pragma pack()
+
+enum { ERR_NO_ERR = 0, ERR_NO_DIRENTRY, ERR_NO_BLOCK, ERR_FILE_EXIST };
+
+bool CheckAmsdos( unsigned char * Buf );
+StAmsdos * CreeEnteteAmsdos( char * NomFic, unsigned short Length );
+void ClearAmsdos( unsigned char * Buf );
+void SetChecksum( StAmsdos * pEntete );
+bool CheckAmsdos( unsigned char * Buf );
+
+
+class DSK
+{
+ unsigned char ImgDsk[ 0x80000 ];
+ unsigned char Bitmap[ 256 ];
+
+ unsigned char * GetRawData( int Pos );
+ void WriteRawData( int Pos, unsigned char * Data, int Longueur );
+ int GetNbTracks( void );
+ void WriteBloc( int bloc, unsigned char * BufBloc );
+ void WriteSect( int Track, int Sect, unsigned char * Buff, int AmsdosMode );
+ unsigned char * ReadSect( int Track, int Sect, int AmsdosMode );
+ CPCEMUTrack * GetInfoTrack( int Track );
+ int FillBitmap( void );
+ void DskEndian();
+ CPCEMUEnt* CPCEMUEntEndian ( CPCEMUEnt* Infos );
+ CPCEMUTrack* CPCEMUTrackEndian ( CPCEMUTrack* tr );
+ CPCEMUSect CPCEMUSectEndian ( CPCEMUSect Sect);
+ const char * GetType( int Langue, StAmsdos * Ams );
+ int GetMinSect( void );
+ int GetPosData( int track, int sect, bool SectPhysique );
+ int RechercheBlocLibre( int MaxBloc );
+ void FormatTrack( CPCEMUEnt * Infos, int t, int MinSect, int NbSect );
+
+public:
+ DSK(){}
+ DSK(const DSK& d)
+ {
+ for (int i=0; i< 0x80000; i++)
+ ImgDsk[i]=d.ImgDsk[i];
+ for (int j=0; j< 256 ; j++ )
+ Bitmap[j]=d.Bitmap[j];
+ }
+
+ ~DSK(){}
+
+ int GetTailleDsk();
+ StDirEntry * GetNomDir(std::string Nom );
+ int CopieFichier( unsigned char * BufFile, char * NomFic, int TailleFic, int MaxBloc, int, bool,bool );
+ bool WriteDsk( std::string NomDsk );
+ unsigned char * ReadBloc( int bloc );
+ bool ReadDsk( std::string NomFic );
+ bool CheckDsk( void );
+ int FileExist( char * Nom );
+ StDirEntry * GetInfoDirEntry( int NumDir );
+ int FileIsIn( std::string FileName );
+ int RechercheDirLibre( void );
+ void FormatDsk( int NbSect, int NbTrack );
+ StAmsdos* StAmsdosEndian ( StAmsdos * pEntete );
+ void SetInfoDirEntry( int NumDir, StDirEntry * Dir );
+ char * GetEntryNameInCatalogue ( int num , char* Nom );
+ char * GetEntrySizeInCatalogue ( int num , char* Size );
+ bool GetFileInDsk( char* path, int Indice );
+ bool PutFileInDsk( std::string Masque ,int TypeModeImport ,int loadAdress, int exeAdress, int,bool,bool );
+ bool OnViewFic(int nItem);
+ bool Hexdecimal();
+ void RemoveFile ( int item );
+ void FixEndianDsk( bool LittleToBig );
+ void FixEndianTrack( CPCEMUEnt * Infos, int t, int NbSect );
+ void RenameFile( int item , char *NewName);
+ std::string ReadDskDir(void);
+
+};
+
+#endif
diff --git a/tools/iDSK/src/Main.cpp b/tools/iDSK/src/Main.cpp
new file mode 100644
index 0000000..f8bcdce
--- /dev/null
+++ b/tools/iDSK/src/Main.cpp
@@ -0,0 +1,284 @@
+#include <iostream>
+#include <cstdlib>
+#include <cstring>
+#include <algorithm> // pour contourner un bug de std::vector ...
+
+#include "getopt_pp.h" /* Command line handling */
+
+using namespace std;
+
+#include "MyType.h"
+#include "GestDsk.h"
+#include "Outils.h"
+#include "Main.h"
+#include "endianPPC.h"
+#include "ViewFile.h"
+
+int main(int argc, char** argv) {
+ bool IsDskLoc, IsDskSet,
+ ModeListDsk, ModeImportFile,
+ ModeRemoveFile,
+ ModeDisaFile, ModeListBasic,
+ ModeListDams,ModeListHex,
+ ModeGetFile, ModeNewDsk, Force_Overwrite,
+ Read_only, System_file;
+
+ ModeListDsk = ModeImportFile =
+ ModeRemoveFile = ModeDisaFile =
+ ModeListBasic = ModeListDams = ModeListHex = ModeNewDsk =
+ ModeGetFile = IsDskLoc = IsDskSet = Force_Overwrite = Read_only = System_file = false ;
+
+ string DskFile, AmsdosFile;
+ vector<string> AmsdosFileList;
+
+ int exeAdress=0,loadAdress=0,AmsdosType=1, UserNumber=0;
+
+ DSK MyDsk;
+
+ IsDsk = IsDskValid = false;
+ IsDskSaved = true;
+
+ // Récupération des arguments avec getopt_pp
+{using namespace GetOpt;
+ GetOpt_pp opts(argc,argv);
+
+ opts >> GlobalOption(DskFile);
+ if (DskFile != "")
+ IsDskSet = true;
+
+ opts >> OptionPresent('l',"list",ModeListDsk)
+
+ >> OptionPresent('i',"import",ModeImportFile)
+ >> Option('i',"import",AmsdosFileList)
+
+ >> OptionPresent('r',"remove",ModeRemoveFile)
+ >> Option('r',"remove",AmsdosFileList)
+
+ >> OptionPresent('n',"new",ModeNewDsk)
+
+ >> OptionPresent('z',"disassemble",ModeDisaFile)
+ >> Option('z',"disassemble",AmsdosFileList)
+
+ >> OptionPresent('b',"basic",ModeListBasic)
+ >> Option('b',"basic",AmsdosFileList)
+
+ >> OptionPresent('d',"dams",ModeListDams)
+ >> Option('d',"dams",AmsdosFileList)
+
+ >> OptionPresent('h',"hex",ModeListHex)
+ >> Option('h',"hex",AmsdosFileList)
+
+ >> std::hex >> Option('e',"exec",exeAdress)
+ >> Option('c',"load",loadAdress)
+ >> std::dec >> Option('t',"type",AmsdosType)
+
+ >> OptionPresent('g',"get",ModeGetFile)
+ >> Option('g',"get",AmsdosFileList)
+
+ >> OptionPresent('f',"force",Force_Overwrite)
+ >> OptionPresent('o',"write-protect",Read_only)
+ >> OptionPresent('s',"system",System_file)
+ >> Option('u',"user",UserNumber)
+ ;
+
+ if(opts.options_remain())
+ {
+ cout << "Unhandled option ! Check the syntax." << endl;
+ exit(EXIT_FAILURE);
+ }
+
+}//namespace getopt
+
+ if ( ! IsDskSet ) {
+ cerr << "You did not select a DSK file to work with !" << endl;
+ help();
+ }
+ else cerr << "DSK : " << DskFile << endl;
+
+ if ( ModeListBasic || ModeListHex || ModeListDams || ModeDisaFile )
+ {
+ if ( ! MyDsk.ReadDsk(DskFile))
+ {
+ cerr<< "Error reading file ("<< DskFile << ")."<<endl;
+ exit(EXIT_FAILURE);
+ }
+ if ( ! MyDsk.CheckDsk() ) {
+ cerr <<"Fichier image non supporté ("<< DskFile << ")."<<endl;
+ exit(EXIT_FAILURE);
+ }
+ int Indice;
+ for(vector<string>::iterator iter=AmsdosFileList.begin(); iter!=AmsdosFileList.end(); iter++)
+ {
+ char* amsdosF = GetNomAmsdos(iter->c_str());
+ cerr << "Amsdos file : " << amsdosF << endl;
+ if ( (Indice= MyDsk.FileIsIn( amsdosF ))<0) {
+ cerr << "Error: File "<< amsdosF << " not found."<< endl;
+ exit(EXIT_FAILURE);
+ }
+ MyDsk.OnViewFic(Indice);
+
+ if ( ModeListBasic )
+ cout << ViewBasic( ) << endl;
+ else if ( ModeListDams )
+ cout << "Not yet coded ! Please try a newer version of iDSK ! Sorry !"<<endl;
+ else if ( ModeListHex ) {
+ MyDsk.Hexdecimal();
+ cout << Listing << endl;
+ }
+ else if ( ModeDisaFile )
+ cout << ViewDesass( )<<endl;
+ }
+ }
+
+ if(ModeNewDsk)
+ {
+ MyDsk.FormatDsk( 9, 42 );
+ if (! MyDsk.WriteDsk(DskFile))
+ {
+ cerr << "Error writing file " << DskFile << endl;
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if ( ModeListDsk ) { // lire Dsk
+ if ( ! MyDsk.ReadDsk(DskFile) ) {
+ cerr<< "Error reading file ("<< DskFile << ")."<<endl;
+ exit(EXIT_FAILURE);
+ }
+ if ( ! MyDsk.CheckDsk() ) {
+ cerr <<"Unsupported dsk file ("<< DskFile << ")."<<endl;
+ exit(EXIT_FAILURE);
+ }
+ cout << MyDsk.ReadDskDir();
+ }
+
+ if ( ModeImportFile ) { // Ajouter fichiers sur dsk
+ if ( ! MyDsk.ReadDsk(DskFile) ) {
+ cerr<< "Error reading file ("<< DskFile << ")."<<endl;
+ exit(EXIT_FAILURE);
+ }
+
+ if ( ! MyDsk.CheckDsk() ) {
+ cerr <<"Unsupported dsk file ("<< DskFile << ")."<<endl;
+ exit(EXIT_FAILURE);
+ }
+
+ for(vector<string>::iterator iter=AmsdosFileList.begin(); iter!=AmsdosFileList.end(); iter++)
+ {
+ string amsdosfile = GetNomAmsdos(iter->c_str());
+ int Indice;
+ if ( ( Indice = MyDsk.FileIsIn( amsdosfile ) ) != -1 && !Force_Overwrite) {
+ cerr << "(" << amsdosfile <<") File exists, replace ? (Y/N) (try -f switch for autoreplace...):";
+ string answer ;
+ cin >> answer;
+ if ( toupper(answer[0]) == 'Y')
+ MyDsk.RemoveFile(Indice);
+ else {
+ cerr<<"Import cancelled, dsk unchanged."<<endl;
+ cout << MyDsk.ReadDskDir();
+ exit(EXIT_SUCCESS);
+ }
+ }
+ else if(Force_Overwrite)
+ MyDsk.RemoveFile(Indice);
+
+ cerr << "Amsdos file : "<< *iter << endl;
+
+ MyDsk.PutFileInDsk(*iter,AmsdosType,loadAdress,exeAdress,UserNumber,System_file,Read_only);
+ }
+ if ( MyDsk.WriteDsk (DskFile) )
+ cout << MyDsk.ReadDskDir();
+ else cerr<< "Error writing file : " << DskFile << endl;
+ }
+
+ if ( ModeRemoveFile ) {
+ if ( ! MyDsk.ReadDsk( (char*)DskFile.c_str() ) ) {
+ cerr<< "Error reading file ("<< DskFile << ")."<<endl;
+ exit(EXIT_FAILURE);
+ }
+ if ( ! MyDsk.CheckDsk() ) {
+ cerr <<"unsupported DSK file ("<< DskFile << ")."<<endl;
+ exit(EXIT_FAILURE);
+ }
+ int Indice;
+ for(vector<string>::iterator iter=AmsdosFileList.begin(); iter!=AmsdosFileList.end(); iter++)
+ {
+ char* amsdosF = GetNomAmsdos(iter->c_str());
+ cerr << "Amsdos file : " << amsdosF << endl;
+ if ( (Indice= MyDsk.FileIsIn( amsdosF ))<0) {
+ cerr << "Error : file "<< amsdosF << " not found."<< endl;
+ exit(EXIT_FAILURE);
+ }
+ MyDsk.RemoveFile(Indice);
+ if ( MyDsk.WriteDsk ((char*)DskFile.c_str()) )
+ cout << MyDsk.ReadDskDir();
+ else cerr<< "Error writing file " << (*iter) << endl;
+ }
+ }
+
+ if ( ModeGetFile ) {
+ if ( ! MyDsk.ReadDsk( (char*)DskFile.c_str() ) ) {
+ cerr<< "Error reading dskfile ("<< DskFile << ")."<<endl;
+ exit(EXIT_FAILURE);
+ }
+ if ( ! MyDsk.CheckDsk() ) {
+ cerr <<"Unsupported dsk ("<< DskFile << ")."<<endl;
+ exit(EXIT_FAILURE);
+ }
+ int Indice;
+
+ for(vector<string>::iterator iter=AmsdosFileList.begin(); iter!=AmsdosFileList.end(); iter++)
+ {
+ char* amsdosF = GetNomAmsdos(iter->c_str());
+ cerr << "Fichier Amsdos : " << amsdosF << endl;
+ if ( (Indice= MyDsk.FileIsIn( amsdosF ))<0) {
+ cerr << "Error : file "<< amsdosF << " not found."<< endl;
+ exit(EXIT_FAILURE);
+ }
+ if ( ! MyDsk.GetFileInDsk((char*)(*iter).c_str(),Indice) ) {
+ cerr <<"System error : unable to copy ("<<AmsdosFile<<")."<<endl;
+ exit(EXIT_FAILURE);
+ }
+ }
+ }
+
+ cerr << "------------------------------------" << endl;
+
+ return(EXIT_SUCCESS);
+}
+
+
+
+
+void help(void)
+{
+ cout <<endl;
+ cout << "--------------------------------------------------------------------------------" << endl;
+ cout << "################################################################################"<< endl;
+ cout << VERSION <<" (by Demoniak, Sid, PulkoMandy), http://github.com/cpcsdk " << endl;
+ cout << "################################################################################"<< endl;
+ cout << endl;
+ cout << "Usage : " << endl;
+ cout << "\t"<< PROGNAME << " <DSKfile> [OPTIONS] [files to process]" << endl;
+ cout << "OPTIONS : EXAMPLE" << endl;
+ cout << "-l : List disk catalog iDSK floppy.dsk -l" << endl;
+ cout << "-g : export ('Get') file iDSK floppy.dsk -g myprog.bas"<<endl;
+ cout << "-r : Remove file iDSK floppy.dsk -r myprog.bas" << endl;
+ cout << "-n : create New dsk file iDSK floppy2.dsk -n" << endl;
+ cout << "-z : disassemble a binary file iDSK floppy.dsk -z myprog.bin" << endl;
+ cout << "-b : list a Basic file iDSK floppy.dsk -b myprog.bas" << endl;
+ cout << "-d : list a Dams file iDSK floppy.dsk -d myprog.dms" << endl;
+ cout << "-h : list a binary file as Hexadecimal iDSK floppy.dsk -h myprog.bin" << endl;
+ cout << "-i : Import file iDSK floppy.dsk -i myprog.bas" << endl
+ << " -t : fileType (0=ASCII/1=BINARY) ... -t 1" << endl;
+ cout << " -e : hex Execute address of file ... -e C000 -t 1" << endl;
+ cout << " -c : hex loading address of file ... -e C000 -c 4000 -t 1" << endl;
+ cout << " -f : Force overwriting if file exists ... -f" << endl
+ << " -o : insert a read-Only file ... -o" << endl
+ << " -s : insert a System file ... -s" << endl
+ << " -u : insert file with User number ... -u 3" << endl;
+ cout << "--------------------------------------------------------------------------------" << endl;
+ cout << "Please report bugs ! - Demoniak/Sid/PulkoMandy" << endl;
+ exit (0);
+}
+
diff --git a/tools/iDSK/src/Main.h b/tools/iDSK/src/Main.h
new file mode 100644
index 0000000..d6d25b6
--- /dev/null
+++ b/tools/iDSK/src/Main.h
@@ -0,0 +1,19 @@
+#ifndef __MAIN_CPP__
+#define __MAIN_CPP__
+#define VERSION "iDSK version 0.16"
+#define PROGNAME "iDSK"
+char Nom[ 256 ];
+char Msg[ 128 ];
+StDirEntry TabDir[ 64 ];
+int PosItem[ 64 ];
+int Langue;
+bool IsDsk, IsDskValid, IsDskSaved;
+int TypeModeImport, TypeModeExport;
+
+
+
+void help(void);
+void DecomposeArg (char **argv,int argc);
+
+
+#endif
diff --git a/tools/iDSK/src/MyType.h b/tools/iDSK/src/MyType.h
new file mode 100644
index 0000000..132a1fd
--- /dev/null
+++ b/tools/iDSK/src/MyType.h
@@ -0,0 +1,19 @@
+#ifndef MYTYPE_H_
+#define MYTYPE_H_
+
+/* types definitions to be coherent with Visual Basic C++ types */
+
+typedef unsigned char BYTE; /* unsigned 8-bit type */
+typedef unsigned short WORD; /* unsigned 16-bit type */
+typedef unsigned long DWORD; /* unsigned 32-bit type */
+
+
+/* constant defintion usefull in the code */
+
+#define TRUE 1
+#define FALSE 0
+#define MODE_ASCII 0
+#define MODE_BINAIRE 1
+
+
+#endif /*MYTYPE_H_*/
diff --git a/tools/iDSK/src/Outils.cpp b/tools/iDSK/src/Outils.cpp
new file mode 100644
index 0000000..54e3c22
--- /dev/null
+++ b/tools/iDSK/src/Outils.cpp
@@ -0,0 +1,165 @@
+#include <iostream>
+#include <cstring>
+#include <cstdio>
+using namespace std;
+#include "Outils.h"
+
+//
+// Initialise une chaine au format hexad�cimal en fonction de la valeur d'entr�e
+//
+void Hex( char Chaine[], int Valeur, int Digit )
+{
+ static char TabDigit[ 17 ] = "0123456789ABCDEF";
+
+ while( Digit )
+ * Chaine++ = TabDigit[ ( Valeur >> ( 4 * ( --Digit ) ) ) & 0x0F ];
+}
+
+
+//
+// Conversion hexa->d�cimal
+//
+int HexToDec( char * Valeur )
+{
+ char * p = strchr( Valeur, 'X' );
+ if ( p )
+ Valeur = ++p;
+
+ p = strchr( Valeur, 'x' );
+ if ( p )
+ Valeur = ++p;
+
+ p = strchr( Valeur, '#' );
+ if ( p )
+ Valeur = ++p;
+
+ p = strchr( Valeur, '$' );
+ if ( p )
+ Valeur = ++p;
+
+ p = strchr( Valeur, '&' );
+ if ( p )
+ Valeur = ++p;
+
+ int Ret = 0, i = 0;
+ while( Valeur[ i ] )
+ {
+ Ret <<= 4;
+ char c = Valeur[ i++ ];
+ if ( c >= '0' && c <= '9' )
+ Ret += c - '0';
+ else
+ Ret += ( c & 0x5F ) - 0x37;
+ }
+ return( Ret );
+}
+
+
+//
+// Conversion d'un secteur (512 octets) en affichage Hexa et ASCII
+//
+void SetBuffViewHexa( unsigned char * src, char * Hex, char * Ascii, unsigned short Offset, int AddOffset)
+{
+ const char * CodeHexa = "0123456789ABCDEF";
+ int q = 0,i;
+
+ //
+ // Parcourir les 512 octets de la source et remplir les buffers
+ //
+ for ( i = 0; i < 512; i++ )
+ {
+ unsigned char b = * src++;
+ if ( b > 32 && b < 127 )
+ {
+ Ascii[ i ] = b;
+ // cout << "b32:" << (int)b <<" Ascii["<<i<<"]:"<< Ascii[ i ] << endl;
+ }
+ else
+ {
+ Ascii[ i ] = '.';
+ }
+ if ( AddOffset && ( ! ( i & 0x0F ) ) )
+ {
+ Hex[ q++ ] = '#';
+ Hex[ q++ ] = CodeHexa[ Offset >> 12 ];
+ Hex[ q++ ] = CodeHexa[ ( Offset >> 8 ) & 0x0F ];
+ Hex[ q++ ] = CodeHexa[ ( Offset >> 4 ) & 0x0F ];
+ Hex[ q++ ] = CodeHexa[ Offset & 0x0F ];
+ Hex[ q++ ] = ':';
+ }
+ Offset++;
+ Hex[ q++ ] = CodeHexa[ b >> 4 ];
+ Hex[ q++ ] = CodeHexa[ b & 0x0F ];
+ Hex[ q++ ] = ' ';
+ }
+ Hex[ q ] = 0;
+ Ascii[ i ] = 0;
+}
+
+
+//
+// Retourne le num�ro d'user sous forme de chaine
+//
+char * GetUser( int u )
+{
+ static char User[ 8 ];
+ sprintf(User, "%d", u);
+ return( User);
+}
+
+
+
+//
+// Retourne la taille du fichier sous forme de chaine
+//
+char * GetTaille( int t )
+{
+ static char Taille[ 16 ];
+
+ sprintf( Taille, "%d Ko", t );
+ return( Taille );
+}
+
+
+//
+// Retourne le nom du fichier formatt� amsdos (8+3)
+//
+char * GetNomAmsdos(const char * AmsName )
+{
+ // Extract the name (without directory components)
+ const char* lastSlash = strrchr(AmsName, '/');
+ const char* lastBackslash = strrchr(AmsName, '\\');
+ if (lastSlash > lastBackslash)
+ AmsName = lastSlash + 1;
+ else if (lastSlash < lastBackslash)
+ AmsName = lastBackslash + 1;
+
+ static char NomAmsdos[ 16 ];
+ int i;
+
+ char * p = NomAmsdos;
+ for ( i = 0; i < 8; i++ ) {
+ if ( * AmsName != ' ' && *AmsName != '.' )
+ * p++ = * AmsName++;
+ /*if ( * AmsName == '-' )
+ * p++ = * AmsName++;*/
+ }
+
+ while( * AmsName != '.' && * AmsName )
+ AmsName++;
+
+ AmsName++;
+
+ * p = 0;
+ strcat( NomAmsdos, "." );
+
+ for ( i = 0; * AmsName && i < 3; i++ )
+ *++p = * AmsName++;
+
+ * ++p = 0;
+ i = 0;
+ while( NomAmsdos[ i ] )
+ NomAmsdos[ i++ ] &= 0x7F;
+
+ return( NomAmsdos );
+}
diff --git a/tools/iDSK/src/Outils.h b/tools/iDSK/src/Outils.h
new file mode 100644
index 0000000..3e64dc4
--- /dev/null
+++ b/tools/iDSK/src/Outils.h
@@ -0,0 +1,19 @@
+#ifndef __OUTILS_H__
+#define __OUTILS_H__
+
+
+void Hex( char Chaine[], int Valeur, int Digit );
+
+int HexToDec( char * Valeur );
+
+void SetBuffViewHexa( unsigned char * src, char * Hex, char * Ascii,unsigned short Offset, int AddOffset);
+
+char * GetNomAmsdos( const char * AmsName );
+
+char * GetUser( int u );
+
+char * GetTaille( int t );
+
+
+
+#endif
diff --git a/tools/iDSK/src/ViewFile.cpp b/tools/iDSK/src/ViewFile.cpp
new file mode 100644
index 0000000..9ad2de7
--- /dev/null
+++ b/tools/iDSK/src/ViewFile.cpp
@@ -0,0 +1,36 @@
+#include <iostream>
+using namespace std;
+#include "GestDsk.h"
+#include "Outils.h"
+#include "Basic.h"
+#include "Desass.h"
+#include "Dams.h"
+#include "endianPPC.h"
+#include "ViewFile.h"
+
+string ViewDams( )
+{
+ cerr << "Taille du fichier : " << TailleFic << endl;
+ Dams( BufFile, TailleFic , Listing );
+ return Listing;
+ //cout << Listing << endl;
+}
+
+
+string ViewDesass( )
+{
+ cerr << "Taille du fichier : " << TailleFic << endl;
+ Desass( BufFile, Listing, TailleFic );
+ return Listing;
+ //cout << Listing << endl;
+}
+string ViewBasic( )
+{
+ bool IsBasic=true;
+ //cout << "Entre Ici\n";
+ cerr << "Taille du fichier : " << TailleFic << endl;
+ Basic( BufFile, Listing, IsBasic, true );
+ //cout << Listing << endl;
+ return Listing;
+
+}
diff --git a/tools/iDSK/src/ViewFile.h b/tools/iDSK/src/ViewFile.h
new file mode 100644
index 0000000..fd9b645
--- /dev/null
+++ b/tools/iDSK/src/ViewFile.h
@@ -0,0 +1,13 @@
+#ifndef __VIEWFILE_H__
+#define __VIEWFILE_H__
+
+
+
+
+string ViewDams();
+string ViewLine();
+string ViewDesass();
+string ViewBasic();
+
+
+#endif
diff --git a/tools/iDSK/src/endianPPC.cpp b/tools/iDSK/src/endianPPC.cpp
new file mode 100644
index 0000000..7b51225
--- /dev/null
+++ b/tools/iDSK/src/endianPPC.cpp
@@ -0,0 +1,20 @@
+#include <iostream>
+#include <cstdlib>
+using namespace std;
+#include "endianPPC.h"
+
+#ifndef _MSC_VER
+#include <sys/param.h>
+#include <endian.h>
+#endif
+
+bool isBigEndian(void)
+{
+#ifdef BYTE_ORDER
+ return BYTE_ORDER == BIG_ENDIAN;
+#elif defined _MSC_VER
+ return true; // It doesn't run on anything except x86, right?
+#else
+ return __BYTE_ORDER == __BIG_ENDIAN;
+#endif
+}
diff --git a/tools/iDSK/src/endianPPC.h b/tools/iDSK/src/endianPPC.h
new file mode 100644
index 0000000..9def637
--- /dev/null
+++ b/tools/iDSK/src/endianPPC.h
@@ -0,0 +1,22 @@
+#ifndef __ENDIANPPC_H__
+#define __ENDIANPPC_H__
+
+/* macros convertion little endian convertion to big endian convertion */
+
+
+#define SWAP_2(x) ( (((x) & 0xff) << 8) | ((unsigned short)(x) >> 8) )
+#define SWAP_4(x) ( ((x) << 24) | \
+ (((x) << 8) & 0x00ff0000) | \
+ (((x) >> 8) & 0x0000ff00) | \
+ ((x) >> 24) )
+#define FIX_SHORT(x) (*(unsigned short *)&(x) = SWAP_2(*(unsigned short *)&(x)))
+#define FIX_INT(x) (*(unsigned int *)&(x) = SWAP_4(*(unsigned int *)&(x)))
+#define FIX_FLOAT(x) FIX_INT(x)
+
+
+
+/* endianness test function */
+
+bool isBigEndian(void);
+
+#endif
diff --git a/tools/iDSK/src/getopt_pp.cpp b/tools/iDSK/src/getopt_pp.cpp
new file mode 100644
index 0000000..b22c81f
--- /dev/null
+++ b/tools/iDSK/src/getopt_pp.cpp
@@ -0,0 +1,307 @@
+/*
+GetOpt_pp: Yet another C++ version of getopt.
+ This file is part of GetOpt_pp.
+
+ Copyright (C) Daniel Gutson, FuDePAN 2007-2010
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt in the root directory or
+ copy at http://www.boost.org/LICENSE_1_0.txt)
+
+ GetOpt_pp 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.
+*/
+
+#include <fstream>
+
+#if __APPLE__
+#include <crt_externs.h>
+#define environ (*_NSGetEnviron())
+#elif _WIN32
+#include <Stdio.h>
+#define environ _environ
+#else
+#include <unistd.h>
+#endif
+
+#include "getopt_pp.h"
+
+namespace GetOpt
+{
+
+GETOPT_INLINE Token* GetOpt_pp::_add_token(const std::string& value, Token::Type type)
+{
+ Token* const ret = new Token(value, type);
+ if (_first_token == NULL)
+ _first_token = ret;
+ else
+ _last_token->link_to(ret);
+ _last_token = ret;
+ return ret;
+}
+
+GETOPT_INLINE void GetOpt_pp::_init_flags()
+{
+ std::stringstream ss;
+ _flags = ss.flags();
+}
+
+GETOPT_INLINE void GetOpt_pp::_parse_sub_file(const std::string& file)
+{
+ std::ifstream ifile(file.c_str());
+ if (!ifile)
+ throw OptionsFileNotFoundEx(file);
+
+ std::vector<std::string> args;
+ std::string arg;
+
+ while (ifile >> arg)
+ args.push_back(arg);
+
+ _parse(args);
+}
+
+GETOPT_INLINE void GetOpt_pp::_parse(const std::vector<std::string>& args)
+{
+ bool any_option_processed = false;
+ const size_t argc = args.size();
+
+ size_t start = 0;
+ if ( _app_name.empty() )
+ {
+ _app_name = args[0];
+ start = 1;
+ }
+
+ // parse arguments by their '-' or '--':
+ // (this will be a state machine soon)
+ for (size_t i = start; i < argc; i++)
+ {
+ const std::string& currentArg = args[i];
+
+ if (currentArg[0] == '-' && currentArg.size() > 1)
+ {
+ // see what's next, differentiate whether it's short or long:
+ if (currentArg[1] == '-')
+ {
+ if ( currentArg.size() > 2 )
+ {
+ // long option
+ _longOps[currentArg.substr(2)].token = _add_token(currentArg.substr(2), Token::LongOption);
+ }
+ else
+ {
+ // it's the -- option alone
+ _longOps[currentArg].token = _add_token(currentArg, Token::GlobalArgument);
+ }
+
+ any_option_processed = true;
+ }
+ else
+ {
+ // check if it is a negative number: rules
+ // * floating point negative numbers are straight classified as 'arguments'
+ // * integer negative numbers of more than 1 digit length are also 'arguments'
+ // * integer negatives of 1 digit length can be either arguments or short options.
+ // * anything else: short options.
+ int anInt;
+ float aFloat;
+ std::stringstream dummy;
+ if ( convert(currentArg, anInt, dummy.flags()) == _Option::OK )
+ {
+ if ( currentArg.size() > 2 ) // if it's larger than -d (d=digit), then assume it's a negative number:
+ _add_token(currentArg, any_option_processed ? Token::UnknownYet : Token::GlobalArgument);
+ else // size == 2: it's a 1 digit negative number
+ _shortOps[currentArg[1]].token = _add_token(currentArg, Token::PossibleNegativeArgument);
+ }
+ else if ( convert(currentArg, aFloat, dummy.flags()) == _Option::OK )
+ _add_token(currentArg, any_option_processed ? Token::UnknownYet : Token::GlobalArgument);
+ else
+ {
+ // short option
+ // iterate over all of them, keeping the last one in currentData
+ // (so the intermediates will generate 'existent' arguments, as of '-abc')
+ for( size_t j = 1; j < currentArg.size(); j++ )
+ _shortOps[currentArg[j]].token = _add_token(std::string(currentArg, j, 1), Token::ShortOption);
+ }
+
+ any_option_processed = true;
+ }
+ }
+ else if ( currentArg[0] == '@' && currentArg.size() > 1 )
+ {
+ // suboptions file
+ _parse_sub_file(currentArg.substr(1));
+ }
+ else
+ {
+ _add_token(currentArg, any_option_processed ? Token::UnknownYet : Token::GlobalArgument);
+ }
+ }
+
+ _last = _Option::OK; // TODO: IMPROVE!!
+}
+
+GETOPT_INLINE void GetOpt_pp::_parse_env()
+{
+ // this will be optimized in version 3
+ std::string var_name;
+ std::string var_value;
+ size_t var = 0;
+ std::string::size_type pos;
+ OptionData* data;
+
+ while (environ[var] != NULL)
+ {
+ var_name = environ[var];
+ pos = var_name.find('=');
+
+ if (pos != std::string::npos)
+ {
+ var_value = var_name.substr(pos + 1);
+ var_name = var_name.substr(0, pos);
+
+ if (_longOps.find(var_name) == _longOps.end())
+ {
+ data = &_longOps[var_name];
+ data->token = _add_token(var_name, Token::LongOption);
+ data->flags = OptionData::Envir;
+ _add_token(var_value, Token::OptionArgument);
+ }
+ }
+ else
+ (data = &_longOps[var_name])->flags = OptionData::Envir;
+
+ var++;
+ }
+}
+
+
+GETOPT_INLINE void GetOpt_pp::_argc_argv_to_vector(int argc, const char* const* const argv, std::vector<std::string>& args)
+{
+ for (int i = 0; i < argc; i++)
+ args.push_back(argv[i]);
+}
+
+GETOPT_INLINE GetOpt_pp::TokensDeleter::~TokensDeleter()
+{
+ Token* next;
+ Token* current(_first);
+ while (current != NULL)
+ {
+ next = current->next;
+ delete current;
+ current = next;
+ }
+}
+
+GETOPT_INLINE GetOpt_pp::GetOpt_pp(int argc, const char* const* const argv)
+ : _exc(std::ios_base::goodbit), _first_token(NULL), _last_token(NULL), _tokens_deleter(_first_token)
+{
+ _init_flags();
+ std::vector<std::string> args;
+ _argc_argv_to_vector(argc, argv, args);
+ _parse(args);
+}
+
+GETOPT_INLINE GetOpt_pp::GetOpt_pp(int argc, const char* const* const argv, _EnvTag)
+ : _first_token(NULL), _last_token(NULL), _tokens_deleter(_first_token)
+{
+ _init_flags();
+ std::vector<std::string> args;
+ _argc_argv_to_vector(argc, argv, args);
+ _parse(args);
+ _parse_env();
+}
+
+GETOPT_INLINE GetOpt_pp& GetOpt_pp::operator >> (const _Option& opt) throw(GetOptEx)
+{
+ if (_last != _Option::ParsingError)
+ {
+ _last = opt(_shortOps, _longOps, _first_token, _flags);
+
+ switch (_last)
+ {
+ case _Option::OK:
+ break;
+
+ case _Option::OptionNotFound:
+ if (_exc & std::ios_base::eofbit)
+ throw OptionNotFoundEx();
+ break;
+
+ case _Option::BadType:
+ if (_exc & std::ios_base::failbit)
+ throw InvalidFormatEx();
+ break;
+
+ case _Option::NoArgs:
+ if (_exc & std::ios_base::eofbit)
+ throw ArgumentNotFoundEx();
+ break;
+
+ case _Option::TooManyArgs:
+ if (_exc & std::ios_base::failbit)
+ throw TooManyArgumentsEx();
+ break;
+
+ case _Option::OptionNotFound_NoEx:
+ break; // Ok, it will be read by casting to bool
+
+ case _Option::ParsingError:
+ break; // just to disable warning
+ }
+ }
+ else if (_exc & std::ios_base::failbit)
+ throw ParsingErrorEx();
+
+ return *this;
+}
+
+GETOPT_INLINE GetOpt_pp& GetOpt_pp::operator >> (std::ios_base & (*iomanip)(std::ios_base&))
+{
+ std::stringstream ss;
+ ss.flags(_flags);
+ _flags = (ss << iomanip).flags();
+ return *this;
+}
+
+GETOPT_INLINE bool GetOpt_pp::options_remain() const
+{
+ bool remain = false;
+ ShortOptions::const_iterator it = _shortOps.begin();
+ while (it != _shortOps.end() && !remain)
+ {
+ remain = (it->second.flags == OptionData::CmdLine_NotExtracted);
+ ++it;
+ }
+
+ if (!remain)
+ {
+ LongOptions::const_iterator it = _longOps.begin();
+ while (it != _longOps.end() && !remain)
+ {
+ remain = (it->second.flags == OptionData::CmdLine_NotExtracted);
+ ++it;
+ }
+ }
+
+ if (!remain)
+ {
+ // check for the global arguments:
+ Token* token = _first_token;
+ while (!remain && token != NULL)
+ {
+ remain = (token->type == Token::GlobalArgument || token->type == Token::UnknownYet);
+ token = token->next;
+ }
+ }
+
+ return remain;
+}
+
+}
diff --git a/tools/iDSK/src/getopt_pp.h b/tools/iDSK/src/getopt_pp.h
new file mode 100644
index 0000000..e0f991a
--- /dev/null
+++ b/tools/iDSK/src/getopt_pp.h
@@ -0,0 +1,745 @@
+/*
+GetOpt_pp: Yet another C++ version of getopt.
+ This file is part of GetOpt_pp.
+
+ Copyright (C) Daniel Gutson, FuDePAN 2007-2010
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt in the root directory or
+ copy at http://www.boost.org/LICENSE_1_0.txt)
+
+ GetOpt_pp 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.
+*/
+
+#ifndef GETOPT_PP_H
+#define GETOPT_PP_H
+
+#include <string>
+#include <vector> // candidate to be removed
+#include <map>
+#include <sstream>
+#include <list>
+
+/*
+ DESIGN GOALS:
+ - EASY to use
+ - EASY to learn
+ - mimc STL's streams
+ - EASY to extend
+*/
+
+#ifndef GETOPT_INLINE
+# define GETOPT_INLINE
+#endif
+
+namespace GetOpt
+{
+
+struct Token
+{
+ enum Type
+ {
+ ShortOption,
+ LongOption,
+ GlobalArgument,
+ GlobalArgumentUsed, // already read, skip in the next read
+ OptionArgument,
+ PossibleNegativeArgument,
+ UnknownYet // can be a global option, or an option of the previous one
+ };
+
+ Type type;
+ std::string value;
+ Token* next;
+
+ Token(const std::string& value, Type type = UnknownYet)
+ : type(type), value(value), next(NULL)
+ {}
+
+ bool is_last() const
+ {
+ return next == NULL;
+ }
+
+ void link_to(Token* new_next)
+ {
+ next = new_next;
+ }
+
+ Token* get_next_option_argument() const
+ {
+ if (is_last())
+ return NULL;
+ else
+ {
+ if (next->type == UnknownYet || next->type == OptionArgument || next->type == PossibleNegativeArgument)
+ return next;
+ else
+ return NULL;
+ }
+ }
+};
+
+struct OptionData
+{
+ enum _Flags
+ {
+ CmdLine_NotExtracted,
+ CmdLine_Extracted,
+ Envir
+ };
+
+ _Flags flags;
+ Token* token;
+ OptionData() : flags(CmdLine_NotExtracted) {}
+};
+
+typedef std::map<std::string, OptionData> LongOptions;
+typedef std::map<char, OptionData> ShortOptions;
+
+
+struct _Option
+{
+ enum Result
+ {
+ OK,
+ ParsingError,
+ OptionNotFound,
+ BadType,
+ NoArgs,
+ TooManyArgs,
+ OptionNotFound_NoEx
+ };
+
+ virtual Result operator()(ShortOptions& short_ops, LongOptions& long_ops, Token* first, std::ios::fmtflags flags) const = 0;
+ virtual ~_Option() {}
+
+ static const char NO_SHORT_OPT = 0;
+protected:
+ static void setTokenAsUsed(Token* token, ShortOptions& short_ops, Token::Type usedAs)
+ {
+ if (token->type == Token::PossibleNegativeArgument)
+ short_ops.erase(token->value[1]);
+
+ token->type = usedAs;
+ }
+};
+
+template <class T> inline _Option::Result convert(const std::string& s, T& result, std::ios::fmtflags flags)
+{
+ std::stringstream ss;
+ ss.clear();
+ ss.flags(flags);
+ ss << s;
+ ss >> result;
+ if (ss.fail() || !ss.eof())
+ return _Option::BadType;
+ else
+ return _Option::OK;
+}
+
+template <> inline _Option::Result convert<std::string>(const std::string& s, std::string& result, std::ios::fmtflags /*flags*/)
+{
+ result = s;
+ return _Option::OK;
+}
+
+
+template <class T> class _OptionTBase : public _Option
+{
+ const char short_opt;
+ const std::string long_opt;
+protected:
+ T& target;
+ virtual Result _assign(Token* token, std::ios::fmtflags flags, ShortOptions& short_ops) const = 0;
+
+public:
+ _OptionTBase(const _OptionTBase<T>& other)
+ : _Option(), short_opt(other.short_opt), long_opt(other.long_opt), target(other.target)
+ {}
+
+ _OptionTBase(char short_opt, const std::string& long_opt, T& target)
+ : short_opt(short_opt), long_opt(long_opt), target(target)
+ {}
+
+ virtual Result operator()(ShortOptions& short_ops, LongOptions& long_ops, Token* /*first*/, std::ios::fmtflags flags) const
+ {
+ Result ret = OptionNotFound;
+ ShortOptions::iterator it;
+ if (short_opt == _Option::NO_SHORT_OPT)
+ it = short_ops.end();
+ else
+ it = short_ops.find(short_opt);
+
+ if (it != short_ops.end())
+ {
+ it->second.flags = OptionData::CmdLine_Extracted;
+ ret = _assign(it->second.token, flags, short_ops);
+ }
+ else if (!long_opt.empty())
+ {
+ LongOptions::iterator it = long_ops.find(long_opt);
+ if (it != long_ops.end())
+ {
+ it->second.flags = OptionData::CmdLine_Extracted;
+ ret = _assign(it->second.token, flags, short_ops);
+ }
+ }
+
+ return ret;
+ }
+};
+
+
+template <class T> class _OptionT : public _OptionTBase<T>
+{
+protected:
+ virtual _Option::Result _assign(Token* token, std::ios::fmtflags flags, ShortOptions& short_ops) const
+ {
+ Token* const option_token = token->get_next_option_argument();
+ if (option_token == NULL)
+ return _Option::NoArgs;
+ else
+ {
+ this->setTokenAsUsed(option_token, short_ops, Token::OptionArgument);
+ return convert<T>(option_token->value, this->target, flags);
+ }
+ }
+public:
+ _OptionT(const _OptionT<T>& other)
+ : _OptionTBase<T>(other)
+ {}
+
+ _OptionT(char short_opt, const std::string& long_opt, T& target)
+ : _OptionTBase<T>(short_opt, long_opt, target)
+ {}
+
+};
+
+template <class T> class _OptionT<std::vector<T> > : public _OptionTBase<std::vector<T> >
+{
+protected:
+ virtual _Option::Result _assign(Token* token, std::ios::fmtflags flags, ShortOptions& short_ops) const
+ {
+ Token* option_token = token->get_next_option_argument();
+ if (option_token != NULL)
+ {
+ _Option::Result result;
+ //OptionArgs::const_iterator it = args.begin();
+ T temp;
+
+ do
+ {
+ this->setTokenAsUsed(option_token, short_ops, Token::OptionArgument);
+ result = convert<T>(option_token->value, temp, flags);
+ if (result == _Option::OK)
+ this->target.push_back(temp);
+
+ option_token = option_token->get_next_option_argument();
+ }
+ while (option_token != NULL && result == _Option::OK);
+
+ return result;
+ }
+ else
+ return _Option::NoArgs;
+ }
+
+public:
+ _OptionT(const _OptionT<std::vector<T> >& other)
+ : _OptionTBase<std::vector<T> >(other)
+ {}
+
+ _OptionT(char short_opt, const std::string& long_opt, std::vector<T>& target)
+ : _OptionTBase<std::vector<T> >(short_opt, long_opt, target)
+ {}
+};
+
+
+template <class T, class BaseOption>
+class _DefValOption : public BaseOption
+{
+ const T default_value;
+public:
+
+ _DefValOption(const _DefValOption<T, BaseOption>& other)
+ : BaseOption(other), default_value(other.default_value)
+ {}
+
+ _DefValOption(char short_opt, const std::string& long_opt, T& target, const T& default_value)
+ : BaseOption(short_opt, long_opt, target), default_value(default_value)
+ {}
+
+ virtual _Option::Result operator()(ShortOptions& short_ops, LongOptions& long_ops, Token* first, std::ios::fmtflags flags) const
+ {
+ _Option::Result ret = BaseOption::operator()(short_ops, long_ops, first, flags);
+
+ if (ret == _Option::OptionNotFound)
+ {
+ this->target = default_value;
+ ret = _Option::OK;
+ }
+
+ return ret;
+ }
+};
+
+template <class T>
+class _GlobalOption : public _Option
+{
+ T& target;
+ virtual Result operator()(ShortOptions& short_ops, LongOptions& long_ops, Token* first, std::ios::fmtflags flags) const
+ {
+ // find first token GlobalArgument or UnknownYet (candidate) or PossibleNegativeArgument (candidate too)
+ Token* token(first);
+ bool found(false);
+ while (token != NULL && !found)
+ {
+ found = (token->type == Token::GlobalArgument || token->type == Token::UnknownYet || token->type == Token::PossibleNegativeArgument);
+ if (!found)
+ token = token->next;
+ }
+ if (found)
+ {
+ this->setTokenAsUsed(token, short_ops, Token::GlobalArgumentUsed);
+ return convert<T>(token->value, target, flags);
+ }
+ else
+ return OptionNotFound;
+ }
+public:
+ _GlobalOption(const _GlobalOption<T>& other)
+ : target(other.target)
+ {}
+
+ _GlobalOption(T& target)
+ : target(target)
+ {}
+};
+
+template <class T>
+class _GlobalOption<std::vector<T> > : public _Option
+{
+ std::vector<T>& target;
+ virtual Result operator()(ShortOptions& short_ops, LongOptions& /*long_ops*/, Token* first, std::ios::fmtflags flags) const
+ {
+ // find first token GlobalArgument or UnknownYet (candidate) or PossibleNegativeArgument (candidate too)
+ Token* token(first);
+ bool found_any(false);
+ T tmp;
+ Result res(OK);
+
+ while (token != NULL && res == OK)
+ {
+ if (token->type == Token::GlobalArgument || token->type == Token::UnknownYet || token->type == Token::PossibleNegativeArgument)
+ {
+ res = convert<T>(token->value, tmp, flags);
+ if (res == OK)
+ {
+ this->setTokenAsUsed(token, short_ops, Token::GlobalArgumentUsed);
+ found_any = true;
+ target.push_back(tmp);
+ }
+ }
+ token = token->next;
+ }
+ if (res == OK)
+ {
+ if (found_any)
+ return res;
+ else
+ return OptionNotFound;
+ }
+ else
+ return res;
+ }
+public:
+ _GlobalOption(const _GlobalOption<std::vector<T> >& other)
+ : target(other.target)
+ {}
+
+ _GlobalOption(std::vector<T>& target)
+ : target(target)
+ {}
+};
+
+template <class T>
+inline _OptionT<T> Option(char short_opt, const std::string& long_opt, T& target)
+{
+ return _OptionT<T>(short_opt, long_opt, target);
+}
+
+template <class T>
+inline _OptionT<T> Option(char short_opt, T& target)
+{
+ return _OptionT<T>(short_opt, std::string(), target);
+}
+
+// LongOpt only
+template <class T>
+inline _OptionT<T> Option(const std::string& long_opt, T& target)
+{
+ return _OptionT<T>(_Option::NO_SHORT_OPT, long_opt, target);
+}
+
+// Defaulted version
+template <class T>
+inline _DefValOption<T, _OptionT<T> >
+Option(char short_opt, const std::string& long_opt, T& target, const T& def)
+{
+ return _DefValOption<T, _OptionT<T> >(short_opt, long_opt, target, def);
+}
+
+template <class T>
+inline _DefValOption<T, _OptionT<T> > Option(char short_opt, T& target, const T& def)
+{
+ return _DefValOption<T, _OptionT<T> >(short_opt, std::string(), target, def);
+}
+
+// no short opt.
+template <class T>
+inline _DefValOption<T, _OptionT<T> >
+Option(const std::string& long_opt, T& target, const T& def)
+{
+ return _DefValOption<T, _OptionT<T> >(_Option::NO_SHORT_OPT, long_opt, target, def);
+}
+
+// Defaults for strings:
+inline _DefValOption<std::string, _OptionT<std::string> >
+Option(char short_opt, const std::string& long_opt, std::string& target, const char* def)
+{
+ return _DefValOption<std::string, _OptionT<std::string> >(short_opt, long_opt, target, def);
+}
+
+inline _OptionT<std::string> Option(char short_opt, std::string& target, const char* def)
+{
+ return _DefValOption<std::string, _OptionT<std::string> >(short_opt, std::string(), target, def);
+}
+
+// no short opt.
+inline _DefValOption<std::string, _OptionT<std::string> >
+Option(const std::string& long_opt, std::string& target, const char* def)
+{
+ return _DefValOption<std::string, _OptionT<std::string> >(_Option::NO_SHORT_OPT, long_opt, target, def);
+}
+
+// Global Option:
+template <class T>
+inline _GlobalOption<T> GlobalOption(T& target)
+{
+ return _GlobalOption<T>(target);
+}
+
+class OptionPresent : public _Option
+{
+ const char short_opt;
+ const std::string long_opt;
+ bool* const present;
+public:
+ // two combinations: with/without target, and with/without long opt.
+
+ // WITH long_opt:
+ OptionPresent(char short_opt, const std::string& long_opt, bool& present)
+ : short_opt(short_opt), long_opt(long_opt), present(&present)
+ {}
+
+ OptionPresent(char short_opt, const std::string& long_opt)
+ : short_opt(short_opt), long_opt(long_opt), present(NULL)
+ {}
+
+ // WITHOUT long_opt:
+ OptionPresent(char short_opt, bool& present)
+ : short_opt(short_opt), present(&present)
+ {}
+
+ OptionPresent(char short_opt)
+ : short_opt(short_opt), present(NULL)
+ {}
+
+ // WITHOUT short_opt
+ OptionPresent(const std::string& long_opt, bool& present)
+ : short_opt(_Option::NO_SHORT_OPT), long_opt(long_opt), present(&present)
+ {}
+
+ OptionPresent(const std::string& long_opt)
+ : short_opt(_Option::NO_SHORT_OPT), long_opt(long_opt), present(NULL)
+ {}
+protected:
+ virtual Result operator()(ShortOptions& short_ops, LongOptions& long_ops, Token* /*first*/, std::ios::fmtflags /*flags*/) const
+ {
+ bool found;
+ ShortOptions::iterator it = short_ops.find(short_opt);
+
+ found = (it != short_ops.end());
+ if (found)
+ {
+ it->second.flags = OptionData::CmdLine_Extracted;
+ }
+ else if (!long_opt.empty())
+ {
+ LongOptions::iterator it = long_ops.find(long_opt);
+ found = (it != long_ops.end());
+ if (found)
+ {
+ it->second.flags = OptionData::CmdLine_Extracted;
+ }
+ }
+
+ if (present != NULL)
+ {
+ *present = found;
+ return OK;
+ }
+ else
+ {
+ return found ? OK : OptionNotFound_NoEx;
+ }
+ }
+};
+
+class GetOptEx : public std::exception {};
+struct ParsingErrorEx : GetOptEx {};
+struct InvalidFormatEx : GetOptEx {};
+struct ArgumentNotFoundEx : GetOptEx {};
+struct TooManyArgumentsEx : GetOptEx {};
+struct OptionNotFoundEx : GetOptEx {};
+struct TooManyOptionsEx : GetOptEx {};
+struct OptionsFileNotFoundEx : GetOptEx
+{
+ const std::string targetFile;
+ OptionsFileNotFoundEx(const std::string& file) : targetFile(file) {}
+ ~OptionsFileNotFoundEx() throw() {}
+};
+
+enum _EnvTag
+{
+ Include_Environment
+};
+
+class GetOpt_pp
+{
+ ShortOptions _shortOps;
+ LongOptions _longOps;
+ std::ios_base::iostate _exc;
+ _Option::Result _last;
+ std::ios::fmtflags _flags;
+ std::string _app_name;
+ Token* _first_token;
+ Token* _last_token;
+
+ class TokensDeleter
+ {
+ Token*& _first;
+ public:
+ TokensDeleter(Token*& first) : _first(first) {}
+
+ GETOPT_INLINE ~TokensDeleter();
+ };
+
+ TokensDeleter _tokens_deleter;
+
+ GETOPT_INLINE Token* _add_token(const std::string& value, Token::Type type);
+ GETOPT_INLINE void _init_flags();
+ GETOPT_INLINE void _parse(const std::vector<std::string>& args);
+ GETOPT_INLINE void _parse_env();
+ static GETOPT_INLINE void _argc_argv_to_vector(int argc, const char* const* const argv, std::vector<std::string>& args);
+ GETOPT_INLINE void _parse_sub_file(const std::string& file);
+public:
+ GETOPT_INLINE GetOpt_pp(int argc, const char* const* const argv);
+ GETOPT_INLINE GetOpt_pp(int argc, const char* const* const argv, _EnvTag);
+
+ std::ios_base::iostate exceptions() const
+ {
+ return _exc;
+ }
+ void exceptions(std::ios_base::iostate except)
+ {
+ _exc = except;
+ }
+ void exceptions_all()
+ {
+ _exc = std::ios_base::failbit | std::ios_base::eofbit;
+ }
+
+ operator bool() const
+ {
+ return _last == _Option::OK;
+ }
+
+ GETOPT_INLINE bool options_remain() const;
+
+ void end_of_options() const throw(GetOptEx)
+ {
+ if (options_remain() && (_exc & std::ios_base::eofbit))
+ throw TooManyOptionsEx();
+ }
+
+ std::ios::fmtflags flags() const
+ {
+ return _flags;
+ }
+ void flags(std::ios::fmtflags flags)
+ {
+ _flags = flags;
+ }
+
+ const std::string& app_name() const
+ {
+ return _app_name;
+ }
+
+ GETOPT_INLINE GetOpt_pp& operator >> (const _Option& opt) throw(GetOptEx);
+
+ GETOPT_INLINE GetOpt_pp& operator >> (std::ios_base& (*iomanip)(std::ios_base&));
+
+ // Alternative to manipulators, for those who don't like them: the 'getopt' method :)
+ // Combination 1: with long option:
+ template <class T> inline T getopt(char short_opt, const std::string& long_opt) throw(GetOptEx)
+ {
+ T result;
+ operator >> (Option(short_opt, long_opt, result));
+ return result;
+ }
+
+ template <class T> inline T getopt(char short_opt, const std::string& long_opt, const T& def_value)
+ {
+ T result;
+ operator >> (Option(short_opt, long_opt, result, def_value));
+ return result;
+ }
+
+ // Combination 2: without long option:
+ template <class T> inline T getopt(char short_opt) throw(GetOptEx)
+ {
+ T result;
+ operator >> (Option(short_opt, result));
+ return result;
+ }
+
+ template <class T> inline T getopt(char short_opt, const T& def_value)
+ {
+ T result;
+ operator >> (Option(short_opt, result, def_value));
+ return result;
+ }
+
+ struct ItCtorData
+ {
+ ShortOptions::const_iterator short_iter;
+ LongOptions::const_iterator long_iter;
+ GetOpt_pp* getopt_pp;
+ };
+
+ template <class Container, class Adapter, class OptionType>
+ class _iterator
+ {
+ typename Container::const_iterator _it;
+ GetOpt_pp* _getopt_pp;
+ public:
+ _iterator(const ItCtorData& ctor_data)
+ {
+ _it = Adapter::adapt(ctor_data);
+ _getopt_pp = ctor_data.getopt_pp;
+ }
+
+ _iterator() : _getopt_pp(NULL)
+ {}
+
+ _iterator<Container, Adapter, OptionType>& operator = (const _iterator<Container, Adapter, OptionType>& other)
+ {
+ _it = other._it;
+ _getopt_pp = other._getopt_pp;
+ return *this;
+ }
+
+ bool operator != (const _iterator<Container, Adapter, OptionType>& other) const
+ {
+ return _it != other._it;
+ }
+
+ OptionType option() const
+ {
+ return _it->first;
+ }
+ OptionType operator*() const
+ {
+ return option();
+ }
+
+ _iterator<Container, Adapter, OptionType>& operator ++()
+ {
+ ++_it;
+ return *this;
+ }
+
+ template <class T>
+ GetOpt_pp& operator >> (T& t)
+ {
+ Adapter::extract(t, *_getopt_pp, option());
+ return *_getopt_pp;
+ }
+ };
+
+ ItCtorData begin()
+ {
+ ItCtorData ret;
+ ret.short_iter = _shortOps.begin();
+ ret.long_iter = _longOps.begin();
+ ret.getopt_pp = this;
+ return ret;
+ }
+
+ ItCtorData end()
+ {
+ ItCtorData ret;
+ ret.short_iter = _shortOps.end();
+ ret.long_iter = _longOps.end();
+ ret.getopt_pp = this;
+ return ret;
+ }
+
+ struct ShortAdapter
+ {
+ static ShortOptions::const_iterator adapt(const ItCtorData& data)
+ {
+ return data.short_iter;
+ }
+
+ template <class T>
+ static void extract(T& t, GetOpt_pp& getopt_pp, char option)
+ {
+ getopt_pp >> Option(option, t);
+ }
+ };
+
+ struct LongAdapter
+ {
+ static LongOptions::const_iterator adapt(const ItCtorData& data)
+ {
+ return data.long_iter;
+ }
+
+ template <class T>
+ static void extract(T& t, GetOpt_pp& getopt_pp, const std::string& option)
+ {
+ getopt_pp >> Option('\0', option, t);
+ }
+ };
+
+ typedef _iterator<ShortOptions, ShortAdapter, char> short_iterator;
+ typedef _iterator<LongOptions, LongAdapter, const std::string&> long_iterator;
+};
+
+class Environment
+{
+ // Coming soon!
+};
+
+}
+
+#endif
diff --git a/tools/img2f.py b/tools/img2f.py
new file mode 100755
index 0000000..23ac1a7
--- /dev/null
+++ b/tools/img2f.py
@@ -0,0 +1,54 @@
+#!/usr/bin/env python
+
+__version__ = "1.0"
+
+from argparse import ArgumentParser
+from PIL import Image
+
+def main():
+
+ parser = ArgumentParser(description="Image to cpcrslib font",
+ epilog="Copyright (C) 2015 Juan J Martinez <jjm@usebox.net>",
+ )
+
+ parser.add_argument("--version", action="version", version="%(prog)s " + __version__)
+ parser.add_argument("image", help="image to convert")
+ parser.add_argument("id", help="variable name")
+ parser.add_argument("--effect", dest="effect", action="store_true")
+
+ args = parser.parse_args()
+
+ try:
+ image = Image.open(args.image)
+ except IOError:
+ parser.error("failed to open the image")
+
+ if image.mode != "P":
+ parser.error("not an indexed image (no palette)")
+
+ (w, h) = image.size
+ data = image.getdata()
+
+ out = []
+ for y in range(0, h, 8):
+ for x in range(0, w, 4):
+ for j in range(8):
+ row = 0
+ for i in range(4):
+ if data[x + i + (j + y) * w] != 0:
+ if args.effect and j in (2, 3, 4, 5):
+ row |= 1 << (7 - ((i * 2) + 1))
+ row |= 1 << (7 - (i * 2))
+ out.append(row)
+
+ data_out = ""
+ for part in range(0, len(out), 8):
+ if data_out:
+ data_out += ",\n"
+ data_out += ', '.join(["0x%02x" % b for b in out[part: part + 8]])
+
+ print("const unsigned char %s[] = {\n%s\n};\n" % (args.id, data_out))
+
+if __name__ == "__main__":
+ main()
+
diff --git a/tools/img2sprite.py b/tools/img2sprite.py
new file mode 100755
index 0000000..6463e0c
--- /dev/null
+++ b/tools/img2sprite.py
@@ -0,0 +1,115 @@
+#!/usr/bin/env python
+
+__version__ = "1.0"
+
+import sys
+from argparse import ArgumentParser
+from PIL import Image
+
+DEF_W = 8
+DEF_H = 16
+
+def encode_byte(a, b):
+ return (a & 1) << 7 | (b & 1) << 6 \
+ | (a & 4) << 3 | (b & 4) << 2 \
+ | (a & 2) << 2 | (b & 2) << 1 \
+ | (a & 8) >> 2 | (b & 8) >> 3
+
+def main():
+
+ parser = ArgumentParser(description="Image cpcrslib sprite",
+ epilog="Copyright (C) 2015 Juan J Martinez <jjm@usebox.net>",
+ )
+
+ parser.add_argument("--version", action="version", version="%(prog)s " + __version__)
+ parser.add_argument("-i", "--id", dest="id", default="sprite", type=str,
+ help="variable name (default: sprite)")
+ parser.add_argument("--width", dest="w", default=DEF_W, type=int,
+ help="sprite width (default: %s)" % DEF_W)
+ parser.add_argument("--height", dest="h", default=DEF_H, type=int,
+ help="sprite height (default: %s)" % DEF_H)
+ parser.add_argument("--transparent-color", dest="tc", default=None, type=int,
+ help="palette index for the transparent color (default: None)")
+ parser.add_argument("-d", "--dimension", dest="dim", action="store_true",
+ help="include the sprite dimensions in the output")
+ parser.add_argument("-b", "--binary", dest="binary", action="store_true",
+ help="output binary instead of C code")
+
+
+ parser.add_argument("image", help="image to convert", nargs="?")
+
+ args = parser.parse_args()
+
+ if not args.image:
+ parser.error("required parameter: image")
+
+ if args.tc:
+ try:
+ args.tc = int(args.tc)
+ if args.tc < 0 or args.tc > 15:
+ raise ValueError()
+ except ValueError:
+ parser.error("--transparent-color expects an integer in [0, 15]")
+
+ try:
+ image = Image.open(args.image)
+ except IOError:
+ parser.error("failed to open the image")
+
+ if image.mode != "P":
+ parser.error("not an indexed image (no palette)")
+
+ (w, h) = image.size
+
+ if w % args.w or h % args.h:
+ parser.error("%s size is not multiple of the image size" % args.image)
+
+ data = image.getdata()
+
+ out = []
+ for x in range(0, w, args.w):
+ frame = []
+ for y in range(h): # FIXME: different heights!
+ if args.dim:
+ out.extend([args.w // 2, args.h])
+ for i in range(0, args.w, 2):
+ a = data[x + i + (y * w)]
+ b = data[x + i + 1 + (y * w)]
+
+ if args.tc is not None:
+ mask_a = mask_b = 0
+ if a == args.tc:
+ mask_a = 0xf
+ a = 0
+ if b == args.tc:
+ mask_b = 0xf
+ b = 0
+ frame.append(encode_byte(mask_a, mask_b))
+
+ frame.append(encode_byte(a, b))
+ out.append(frame)
+
+ if args.binary:
+ for frame in out:
+ sys.stdout.write(bytearray(frame))
+ return
+
+ frames = len(out)
+
+ data_out = ""
+ for block in out:
+ if data_out:
+ data_out += ",\n"
+ data_out += "{"
+ for part in range(0, len(block), 4):
+ if data_out and data_out[-1] != "{":
+ data_out += ",\n"
+ data_out += ', '.join(["0x%02x" % b for b in block[part: part + 4]])
+ data_out += "}"
+
+ print("/* %sx%s (frames: %s, mask: %s, dim: %s) */" % (args.w, args.h, frames, args.tc is not None, args.dim))
+ print("const unsigned char %s[%d][%d] = {\n%s\n};\n" % (args.id, len(out), len(out[0]), data_out))
+
+if __name__ == "__main__":
+ main()
+
diff --git a/tools/map.py b/tools/map.py
new file mode 100755
index 0000000..e5d3199
--- /dev/null
+++ b/tools/map.py
@@ -0,0 +1,162 @@
+#!/usr/bin/env python
+
+__version__ = "1.0"
+
+import sys
+from argparse import ArgumentParser
+import json
+import subprocess
+from collections import defaultdict
+
+DEF_ROOM_WIDTH = 20
+DEF_ROOM_HEIGHT = 10
+
+def find_name(data, name):
+ for item in data:
+ if item.get("name").lower() == name.lower():
+ return item
+ raise ValueError("%r not found" % name)
+
+def main():
+
+ parser = ArgumentParser(description="Map importer",
+ epilog="Copyright (C) 2015 Juan J Martinez <jjm@usebox.net>",
+ )
+
+ parser.add_argument("--version", action="version", version="%(prog)s " + __version__)
+ parser.add_argument("--room-width", dest="rw", default=DEF_ROOM_WIDTH, type=int,
+ help="room width (default: %s)" % DEF_ROOM_WIDTH)
+ parser.add_argument("--room-height", dest="rh", default=DEF_ROOM_HEIGHT, type=int,
+ help="room height (default: %s)" % DEF_ROOM_HEIGHT)
+ parser.add_argument("-b", dest="bin", action="store_true",
+ help="output binary data (default: C code)")
+ parser.add_argument("--ucl", dest="ucl", action="store_true",
+ help="UCL compress (requires ucl binary in the path)")
+ parser.add_argument("map_json", help="Map to import")
+ parser.add_argument("id", help="variable name")
+
+ args = parser.parse_args()
+
+ with open(args.map_json, "rt") as fd:
+ data = json.load(fd)
+
+ mh = data.get("height", 0)
+ mw = data.get("width", 0)
+
+ if mh < args.rh or mh % args.rh:
+ parser.error("Map size in not multiple of the room size")
+ if mw < args.rw or mw % args.rw:
+ parser.error("Map size in not multiple of the room size")
+
+ tilewidth = data["tilewidth"]
+ tileheight = data["tileheight"]
+
+ tile_layer = find_name(data["layers"], "Map")["data"]
+
+ def_tileset = find_name(data["tilesets"], "default")
+ tileprops = def_tileset.get("tileproperties", {})
+ firstgid = def_tileset.get("firstgid")
+
+ out = []
+ for y in range(0, mh, args.rh):
+ for x in range(0, mw, args.rw):
+ current = []
+ for j in range(args.rh):
+ for i in range(args.rw / 2):
+ a = (tile_layer[x + (i * 2) + (y + j) * mw] - firstgid) & 0b111
+ if str(a) in tileprops and tileprops[str(a)].get("blocked"):
+ a |= 0b1000
+
+ b = (tile_layer[x + (i * 2) + 1 + (y + j) * mw] - firstgid) & 0b111
+ if str(b) in tileprops and tileprops[str(b)].get("blocked"):
+ b |= 0b1000
+
+ current.append((a << 4) | b)
+ out.append(current)
+
+ if args.ucl:
+ compressed = []
+ for block in out:
+ p = subprocess.Popen(["ucl",], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
+ output, err = p.communicate(bytearray(block))
+ compressed.append([ord(b) for b in output])
+ out = compressed
+
+ if args.bin:
+ sys.stdout.write(bytearray(out))
+ return
+
+ print("#define WMAPS %d" % (mw // args.rw))
+
+ if args.ucl:
+ data_out = ""
+ for i, block in enumerate(out):
+ data_out_part = ""
+ for part in range(0, len(block), args.rw // 2):
+ if data_out_part:
+ data_out_part += ",\n"
+ data_out_part += ', '.join(["0x%02x" % b for b in block[part: part + args.rw // 2]])
+ data_out += "const unsigned char %s_%d[%d] = {\n" % (args.id, i, len(block))
+ data_out += data_out_part + "\n};\n"
+
+ data_out += "const unsigned char *%s[%d] = { " % (args.id, len(out))
+ data_out += ', '.join(["%s_%d" % (args.id, i) for i in range(len(out))])
+ data_out += " };\n"
+ print(data_out)
+
+ else:
+ data_out = ""
+ for block in out:
+ if data_out:
+ data_out += ",\n"
+ data_out += "{"
+ for part in range(0, len(block), args.rw // 2):
+ if data_out and data_out[-1] != "{":
+ data_out += ",\n"
+ data_out += ', '.join(["0x%02x" % b for b in block[part: part + args.rw // 2]])
+ data_out += "}\n"
+
+ print("const unsigned char %s[%d][%d] = {\n%s\n};\n" % (args.id,
+ len(out), args.rh * args.rw / 2, data_out))
+
+ enemies = 0
+ entities_layer = find_name(data["layers"], "Entities")
+ if len(entities_layer):
+ map_ents = defaultdict(list)
+ ent_tileset = find_name(data["tilesets"], "Entities")
+ firstgid = ent_tileset.get("firstgid")
+ for obj in entities_layer["objects"]:
+ m = ((obj["x"] // tilewidth) // args.rw) \
+ + (((obj["y"] // tileheight) // args.rh) * (mw // args.rw))
+ x = obj["x"] % (args.rw * tilewidth)
+ y = obj["y"] % (args.rh * tileheight) - ent_tileset["tileheight"]
+ t = int(ent_tileset["tileproperties"][str(obj["gid"] - firstgid)]["id"])
+ # enemies start at id 10
+ if t > 9:
+ enemies += 1
+ map_ents[m].extend([t, x, y])
+ if "teleport" in obj.get("properties", {}):
+ tele = json.loads(obj["properties"]["teleport"])
+ tm = ((tele[0] // tilewidth) // args.rw) \
+ + (((tele[1] // tileheight) // args.rh) * (mw // args.rw))
+ map_ents[m].extend([tm, tele[0] % (tilewidth * args.rw), tele[1] % (tileheight * args.rh) - ent_tileset["tileheight"]])
+
+ for m, ents in map_ents.items():
+ data_out = ", ".join(["0x%02x" % e for e in ents]) + ", 0xff"
+ print("const unsigned char %s_e%d[%d] = { %s };" % (args.id, m, len(ents) + 1, data_out))
+
+ map_map = []
+ for i in range(len(out)):
+ if i in map_ents:
+ map_map.append("%s_e%d" % (args.id, i))
+ else:
+ map_map.append("(unsigned char *)0")
+
+ print("const unsigned char *%s_ents[%d] = { %s };\n" % (args.id,
+ len(out), ", ".join(map_map)))
+
+ print("const unsigned char %s_enemies = %s;" % (args.id, enemies))
+
+if __name__ == "__main__":
+ main()
+
diff --git a/tools/ucl.c b/tools/ucl.c
new file mode 100644
index 0000000..e61e0e0
--- /dev/null
+++ b/tools/ucl.c
@@ -0,0 +1,94 @@
+/*
+ucl compression tool
+Copyright (C) 2015 by Juan J. Martinez - usebox.net
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+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 AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include <stdio.h>
+#include <string.h>
+
+#include <ucl/ucl.h>
+
+#define MAX_MEM 65536
+
+ucl_byte buffer[MAX_MEM];
+
+int
+main()
+{
+ ucl_uint in_len = 0;
+ ucl_uint out_len;
+ ucl_byte *in;
+ ucl_byte *out;
+
+ if (ucl_init() != UCL_E_OK)
+ {
+ fprintf(stderr, "ucl: failed to init UCL\n");
+ return 1;
+ }
+
+ while(!feof(stdin))
+ {
+ buffer[in_len++] = getc(stdin);
+ if (in_len > MAX_MEM)
+ {
+ fprintf(stderr, "input too large (limit %i)\n", MAX_MEM);
+ return 1;
+ }
+ }
+ in_len--;
+
+ out_len = in_len + in_len / 8 + 256;
+
+ in = ucl_malloc(in_len + 8192);
+ out = ucl_malloc(out_len + 8192);
+ if (!in || !out)
+ {
+ fprintf(stderr, "ucl: out of memory\n");
+ return 1;
+ }
+
+ memcpy(in, buffer, in_len);
+
+ if (ucl_nrv2b_99_compress(in, in_len, out, &out_len, NULL, 10, NULL, NULL) != UCL_E_OK)
+ {
+ fprintf(stderr, "ucl: compress error\n");
+ return 1;
+ }
+
+ if (out_len >= in_len)
+ {
+ fprintf(stderr, "ucl: content can't be compressed\n");
+ return 1;
+ }
+
+ fwrite(out, 1, out_len, stdout);
+ fclose(stdout);
+
+ ucl_free(out);
+ ucl_free(in);
+
+ fprintf(stderr, "ucl: %i bytes compressed into %i bytes\n", in_len, out_len);
+
+ return 0;
+}
+
+
+