From clauflibitFriiDump-0.5.3.1

This commit is contained in:
Braden McDaniel 2013-11-01 12:26:04 -04:00
parent fe937e7f4b
commit 87b108d6a1
63 changed files with 11067 additions and 26 deletions

161
CMakeLists.txt Normal file
View file

@ -0,0 +1,161 @@
# The name of our project is "HELLO". CMakeLists files in this project can
# refer to the root source directory of the project as ${HELLO_SOURCE_DIR} and
# to the root binary directory of the project as ${HELLO_BINARY_DIR}.
project (FriiDump)
if (MSVC)
# msvc2005 deprecated warnings
add_definitions (-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE)
else (MSVC)
if (NOT WIN32)
add_definitions (-fPIC)
endif (NOT WIN32)
endif (MSVC)
include (TestBigEndian)
test_big_endian (CMAKE_WORDS_BIGENDIAN)
include (CheckIncludeFiles)
check_include_files (stdbool.h HAVE_STDBOOL_H)
include (CheckFunctionExists)
check_function_exists (fseeko HAVE_FSEEKO)
check_function_exists (ftello HAVE_FTELLO)
check_function_exists (fseek64 HAVE_FSEEK64)
check_function_exists (ftell64 HAVE_FTELL64)
include(CheckTypeSize)
set (CMAKE_REQUIRED_DEFINITIONS -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64)
set (CMAKE_EXTRA_INCLUDE_FILES sys/types.h)
check_type_size ("off_t" OFF_T)
set (CMAKE_EXTRA_INCLUDE_FILES)
set (CMAKE_EXTRA_INCLUDE_FILES stdio.h)
check_type_size ("fpos_t" FPOS_T)
set (CMAKE_EXTRA_INCLUDE_FILES)
set (CMAKE_REQUIRED_DEFINITIONS)
option (
DEBUG
"Enable debugging messages"
OFF
)
option (
BUILD_STATIC_BINARY
"Build a static binary (has precedence over ALL_LIBS_SHARED)"
OFF
)
option (
BUILD_ALL_LIBS_SHARED
"Build all libraries as shared"
OFF
)
if (BUILD_STATIC_BINARY)
set (libmultihash_type STATIC)
set (libfriidump_type STATIC)
elseif (BUILD_ALL_LIBS_SHARED)
set (libmultihash_type SHARED)
set (libfriidump_type SHARED)
else (BUILD_STATIC_BINARY)
# This is how we build libraries by default
set (libmultihash_type STATIC)
set (libfriidump_type SHARED)
endif (BUILD_STATIC_BINARY)
# set (CMAKE_BUILD_TYPE superoptimized)
set (CMAKE_C_FLAGS_SUPEROPTIMIZED "-march=athlon-xp -m3dnow -O3 -funroll-all-loops")
set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wall")
# set (CMAKE_BUILD_TYPE release)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
add_definitions(-DHAVE_CONFIG_H)
include_directories (
${FriiDump_BINARY_DIR}
)
# Recurse into the "Hello" and "Demo" subdirectories. This does not actually
# cause another cmake executable to run. The same process will walk through
# the project's entire directory structure.
add_subdirectory (libmultihash)
add_subdirectory (libfriidump)
add_subdirectory (src)
if (WIN32)
install (FILES AUTHORS DESTINATION / RENAME Authors.txt)
#install (CODE "exec_program (${CMAKE_CURRENT_SOURCE_DIR}/utils/unix2dos.exe ${CMAKE_OUTPUT_BINARY_DIR} ARGS Authors.txt)")
install (FILES ChangeLog DESTINATION / RENAME ChangeLog.txt)
install (FILES COPYING DESTINATION / RENAME Copying.txt)
install (FILES README DESTINATION / RENAME ReadMe.txt)
install (FILES TODO DESTINATION / RENAME ToDo.txt)
endif (WIN32)
# CPack stuff
include (InstallRequiredSystemLibraries)
set (CPACK_PACKAGE_NAME "friidump")
set (CPACK_PACKAGE_DESCRIPTION_SUMMARY "Dump Nintendo GameCube/Wii discs")
set (CPACK_PACKAGE_VENDOR "Arep")
set (CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/docs/README")
set (CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/docs/COPYING")
set (CPACK_PACKAGE_VERSION_MAJOR "0")
set (CPACK_PACKAGE_VERSION_MINOR "3")
set (CPACK_PACKAGE_VERSION_PATCH "0")
set (CPACK_PACKAGE_INSTALL_DIRECTORY "FriiDump ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
set (CPACK_PACKAGE_EXECUTABLES "friidump" "FriiDump")
set (CPACK_SOURCE_GENERATOR "TBZ2;ZIP")
set (CPACK_SOURCE_IGNORE_FILES
"/CVS/"
"/\\\\.svn/"
"~$"
"tags"
"\\\\.kdevses$"
"\\\\.kdevelop\\\\.pcs$"
"/BUILD.*/"
"/RELEASES/"
"/utils/"
"/doc.*/"
)
set (CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
if(WIN32 AND NOT UNIX)
set (CPACK_GENERATOR "NSIS;ZIP")
# There is a bug in NSI that does not handle full unix paths properly. Make
# sure there is at least one set of four (4) backlasshes.
# set (CPACK_PACKAGE_ICON "${CMake_SOURCE_DIR}/Utilities/Release\\\\InstallIcon.bmp")
# set (CPACK_NSIS_INSTALLED_ICON_NAME "bin\\\\MyExecutable.exe")
set (CPACK_NSIS_DISPLAY_NAME "${CPACK_PACKAGE_INSTALL_DIRECTORY} installer")
set (CPACK_NSIS_HELP_LINK "http:\\\\\\\\wii.console-tribe.com")
set (CPACK_NSIS_URL_INFO_ABOUT "http:\\\\\\\\www.my-personal-home-page.com")
set (CPACK_NSIS_CONTACT "arep@no.net")
set (CPACK_NSIS_MODIFY_PATH ON)
set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}-Win32")
else(WIN32 AND NOT UNIX)
set (CPACK_GENERATOR "TBZ2")
set (CPACK_STRIP_FILES "bin/friidump;lib/libfriidump.so.1.0.0")
# set (CPACK_SOURCE_STRIP_FILES "")
set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}-LinuxBin")
endif(WIN32 AND NOT UNIX)
include (CPack)

284
Doxyfile Normal file
View file

@ -0,0 +1,284 @@
# Doxyfile 1.5.1-KDevelop
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
PROJECT_NAME = FriiDump
PROJECT_NUMBER = 0.3pre
OUTPUT_DIRECTORY =
CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English
USE_WINDOWS_ENCODING = NO
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ABBREVIATE_BRIEF = "The $name class" \
"The $name widget" \
"The $name file" \
is \
provides \
specifies \
contains \
represents \
a \
an \
the
ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = NO
FULL_PATH_NAMES = YES
STRIP_FROM_PATH =
STRIP_FROM_INC_PATH =
SHORT_NAMES = NO
JAVADOC_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
DETAILS_AT_TOP = YES
INHERIT_DOCS = YES
SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 8
ALIASES =
OPTIMIZE_OUTPUT_FOR_C = YES
OPTIMIZE_OUTPUT_JAVA = NO
BUILTIN_STL_SUPPORT = NO
DISTRIBUTE_GROUP_DOC = NO
SUBGROUPING = YES
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
EXTRACT_ALL = NO
EXTRACT_PRIVATE = NO
EXTRACT_STATIC = NO
EXTRACT_LOCAL_CLASSES = YES
EXTRACT_LOCAL_METHODS = NO
HIDE_UNDOC_MEMBERS = YES
HIDE_UNDOC_CLASSES = NO
HIDE_FRIEND_COMPOUNDS = NO
HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO
CASE_SENSE_NAMES = YES
HIDE_SCOPE_NAMES = NO
SHOW_INCLUDE_FILES = NO
INLINE_INFO = YES
SORT_MEMBER_DOCS = NO
SORT_BRIEF_DOCS = NO
SORT_BY_SCOPE_NAME = NO
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = NO
SHOW_DIRECTORIES = NO
FILE_VERSION_FILTER =
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
QUIET = NO
WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = NO
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = libfriidump \
libmultihash
FILE_PATTERNS = *.c \
*.cc \
*.cxx \
*.cpp \
*.c++ \
*.d \
*.java \
*.ii \
*.ixx \
*.ipp \
*.i++ \
*.inl \
*.h \
*.hh \
*.hxx \
*.hpp \
*.h++ \
*.idl \
*.odl \
*.cs \
*.php \
*.php3 \
*.inc \
*.m \
*.mm \
*.dox \
*.py \
*.C \
*.CC \
*.C++ \
*.II \
*.I++ \
*.H \
*.HH \
*.H++ \
*.CS \
*.PHP \
*.PHP3 \
*.M \
*.MM \
*.PY \
*.C \
*.H \
*.tlh \
*.diff \
*.patch \
*.moc \
*.xpm \
*.dox
RECURSIVE = YES
EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS =
EXAMPLE_PATH =
EXAMPLE_PATTERNS = *
EXAMPLE_RECURSIVE = NO
IMAGE_PATH =
INPUT_FILTER =
FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
#---------------------------------------------------------------------------
# configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER = NO
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES
REFERENCES_LINK_SOURCE = YES
USE_HTAGS = NO
VERBATIM_HEADERS = YES
#---------------------------------------------------------------------------
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
ALPHABETICAL_INDEX = YES
COLS_IN_ALPHA_INDEX = 5
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# configuration options related to the HTML output
#---------------------------------------------------------------------------
GENERATE_HTML = YES
HTML_OUTPUT = doxygen-html
HTML_FILE_EXTENSION = .html
HTML_HEADER =
HTML_FOOTER =
HTML_STYLESHEET =
HTML_ALIGN_MEMBERS = YES
GENERATE_HTMLHELP = NO
CHM_FILE =
HHC_LOCATION =
GENERATE_CHI = NO
BINARY_TOC = YES
TOC_EXPAND = NO
DISABLE_INDEX = NO
ENUM_VALUES_PER_LINE = 4
GENERATE_TREEVIEW = YES
TREEVIEW_WIDTH = 250
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------
GENERATE_LATEX = NO
LATEX_OUTPUT = latex
LATEX_CMD_NAME = latex
MAKEINDEX_CMD_NAME = makeindex
COMPACT_LATEX = NO
PAPER_TYPE = a4wide
EXTRA_PACKAGES =
LATEX_HEADER =
PDF_HYPERLINKS = NO
USE_PDFLATEX = NO
LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------
GENERATE_RTF = NO
RTF_OUTPUT = rtf
COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
#---------------------------------------------------------------------------
# configuration options related to the man page output
#---------------------------------------------------------------------------
GENERATE_MAN = NO
MAN_OUTPUT = man
MAN_EXTENSION = .3
MAN_LINKS = NO
#---------------------------------------------------------------------------
# configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML = NO
XML_OUTPUT = xml
XML_SCHEMA =
XML_DTD =
XML_PROGRAMLISTING = YES
#---------------------------------------------------------------------------
# configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# configuration options related to the Perl module output
#---------------------------------------------------------------------------
GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
PERLMOD_PRETTY = YES
PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED =
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration::additions related to external references
#---------------------------------------------------------------------------
TAGFILES =
GENERATE_TAGFILE =
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = YES
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = NO
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
GROUP_GRAPHS = YES
UML_LOOK = NO
TEMPLATE_RELATIONS = NO
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
CALL_GRAPH = NO
CALLER_GRAPH = NO
GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES
DOT_IMAGE_FORMAT = png
DOT_PATH =
DOTFILE_DIRS =
MAX_DOT_GRAPH_WIDTH = 1024
MAX_DOT_GRAPH_HEIGHT = 1024
MAX_DOT_GRAPH_DEPTH = 1000
DOT_TRANSPARENT = NO
DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
DOT_CLEANUP = YES
#---------------------------------------------------------------------------
# Configuration::additions related to the search engine
#---------------------------------------------------------------------------
SEARCHENGINE = YES

View file

@ -1,4 +0,0 @@
friidump
========
FriiDump - Dump Nintendo Wii and GameCube discs

42
config.h.cmake Normal file
View file

@ -0,0 +1,42 @@
/* Define to 1 if your processor stores words with the most significant byte
first (like Motorola and SPARC, unlike Intel and VAX). */
#cmakedefine WORDS_BIGENDIAN ${CMAKE_WORDS_BIGENDIAN}
/* Define to 1 if stdbool.h conforms to C99. */
#cmakedefine HAVE_STDBOOL_H 1
/* Debug support */
#cmakedefine DEBUG 1
#cmakedefine HAVE_FSEEKO
#cmakedefine HAVE_FTELLO
#cmakedefine HAVE_FSEEK64
#cmakedefine HAVE_FTELL64
#cmakedefine HAVE_OFF_T
#ifdef HAVE_OFF_T
#cmakedefine OFF_T ${OFF_T}
#define SIZEOF_OFF_T OFF_T
#endif
#cmakedefine HAVE_FPOS_T
#ifdef HAVE_FPOS_T
#cmakedefine FPOS_T ${FPOS_T}
#define SIZEOF_FPOS_T FPOS_T
#endif
/* Large file support - Can't this be done better with CMake!? What about on Windows? */
#define _FILE_OFFSET_BITS 64
#define _LARGEFILE_SOURCE 1
#define _LARGE_FILES
#define HAVE_LARGEFILE_SUPPORT
#if defined(_FILE_OFFSET_BITS)
# if (_FILE_OFFSET_BITS<64)
# undef _FILE_OFFSET_BITS
# define _FILE_OFFSET_BITS 64
# endif
#else
# define _FILE_OFFSET_BITS 64
#endif

41
docs/AUTHORS Normal file
View file

@ -0,0 +1,41 @@
FriiDump came to existance thanks to the work by a lot of people, most of which
are probably not aware of this fact ;). So here is proper credit:
The DVD seed bruteforcing algorithm and code were taken from unscrambler 0.4
by Victor Muñoz (xt5@ingenieria-inversa.cl,
http://www.ingenieria-inversa.cl/?lp_lang_pref=en).
The theoritical basis of the dumping methods were suggested in several comments
to Victor's post. The most important comments came from Victor himself (xt5),
FuzzyLogic and svpe.
The code to actually perform the dumping was derived from the work of Kevin
East, AKA SeventhSon (kev@kev.nu, http://www.kev.nu/360/), which, in turn,
derives from work by a lot of other people. See his page for full details.
Many hints were taken from RawDump, whose author is unknown.
A program that helped me a lot to understand the drive cache behaviour is
PLScsi by Pat LaVarre (http://members.aol.com/plscsi/).
Nintendo disc structure information was taken from:
- http://www.gc-linux.org/docs/yagcd.html
- http://www.wiili.org/index.php/GameCube_Optical_Disc
Code to tell whether a Wii disc contains an update or was inspired by a program
by wiidevel@stacktic.org. Sorry but I cannot find the URL anymore :(.
Other minor pieces of code were taken from tcpdump (www.tcpdump.org), Python
(www.python.org) and the glibc printf manpage.
GDR8163B and Windows testing was performed by tasso85.
Thanks also go out to the ConsoleTribe staff for giving me the possibility to
use their forum for the program support.
Glue, endless hours spent understanding drive cache behaviour and rest of the
code are by me, Arep <arep@no.net>.
Finally, obvious thanks go out to Nintendo for making all of their great
consoles, who constantly help me to waste the rest of my spare time I do not
spend coding ;).

View file

@ -1,12 +1,12 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
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
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
@ -15,7 +15,7 @@ software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
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
@ -55,8 +55,8 @@ 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
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
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
@ -168,7 +168,7 @@ 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
@ -225,7 +225,7 @@ 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
@ -255,7 +255,7 @@ 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
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
@ -277,9 +277,9 @@ 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
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
@ -290,8 +290,8 @@ 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.
{description}
Copyright (C) {year} {fullname}
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -303,9 +303,10 @@ the "copyright" line and a pointer to where the full notice is found.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
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.
@ -329,11 +330,11 @@ 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
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

45
docs/ChangeLog Normal file
View file

@ -0,0 +1,45 @@
0.5.3 (15/03/2010)
- Fixed failing after 1st DL media layer with non-Hitachi methods.
- Fixed still hashing with 'nohash' parameter when resuming.
- Fixed resuming larger files (~4 GB).
- Fixed unscrambling larger files.
- Faster file unscrambling.
- Slight modifications to methods;
possible performance increase with Hitachi based devices.
- Restructured methods and added some new ones.
- Added layer break information.
- Added current position output when error occurs.
- Added SH-D162A, SH-D162B, SH-D162C & SH-D162D as supported.
> Jackal, gorelord4e, themabus
0.5.2 (10/01/2010)
- Corrected handling of standard DVDs
(type should be forced to 3, when dumping or unscrambling).
- Better response to 'speed' parameter.
- Uniform raw output for all devices: unscrambled data + headers.
- Slight performance increase (~1650 MB/h on LH-18A1H).
- Added LH-18A1P, LH-20A1H, LH-20A1P to list of supported devices.
> Jackal, themabus
0.5.1 (01/12/2009)
- New command 'vanilla 2384'.
- Restructured methods, some now support optional parameters.
- Ability to select standard DVDs as source.
- Limited recognized Lite-On drives to LH-18A1H.
> Jackal, themabus
0.5.0 (27/11/2009)
- Regions: Italy, France, Germany, Spain, Australia, PAL-X, PAL-Y.
- Updated publisher list from http://wiitdb.com/Company/HomePage
- Included GDR8082N & GDR8161B as supported Hitachi drives.
- Lite-On, Renesas & vanilla memory buffer access commands.
Lite-On tested on LH-18A1H, should work on many more
(LH*, SH, DH*, DW* & possibly other MediaTek drives)
- Shifted methods 1..4 to 0..3 and added new ones 4..6
Associated known drives with default methods.
- Additional commandline parameters:
stop, speed, command, type, size
- Some minor changes and fixes.
> Jackal, Truman, themabus
0.4 (08/03/2008)
- Support for DL Wii DVDs.
> mado3689
0.3 (06/10/2007)
- First public release.

1
docs/INSTALL Normal file
View file

@ -0,0 +1 @@
See README.

53
docs/NEWS Normal file
View file

@ -0,0 +1,53 @@
Since last official version original method 1 have been renamed to method 0
and it undergone certain changes. Methods 2, 3, 4 have been renamed to 7, 8
and 9 respectively. Method 0 should work with all drives as long as they
are supported by one of memory dump commands, so if drive is unrecognized it
is preferable to keep method at 0, and try all commands. If one of such
combinations turns out to work, you can proceed then testing other methods
with this commad. In case none of commands work, you could try to determine
drive's Read Buffer command's parameters with supplied 'BruteForce3C.exe'.
Generally program's overall bahaviour regarding commandline haven't changed
and you should be able to use same options as with official versions, though
in case you were using unrecognized drive, which would nevertheless work with
Hitachi command, you'll need to set command to 2 now (e.g. --command 2) and
method to 7, 8 or 9.
Performance have increased since official release and should be now about the
same as with 'RawDump'.
Regarding supported drives:
1. Hitachi-LG GDR8161B, GDR8162B, GDR8163B, GDR8164B, GDR8082N
Those drives can read GC/Wii media without swapping. Expected performance is
1600..1900 MB/h for *4B, *3B and 2100..2600 MB/h for *2B, *1B. Custom memory
dump command is used, which returns 2064 bytes of data. It was reproted that
they can not read other (e.g. PC) discs this way though, this needs
confirmation.
2. Lite-On LH-18A1H, DVDRW LH-18A1P, DVDRW LH-20A1H, DVDRW LH-20A1P
Reading performance for PC DVDs can go up to 5000 MB/h, which means program's
core as well as new methods are capable to output data at least at this rate.
Reading performance for GC was about 1600..1700 MB/h so likely this slowdown is
caused by drive logic itself. Though I only had one GC game to test with, so
possibly better results can be achieved depending on media. Best results were
obtained, when using method 5 with parameter 16,27 (--method5=16,27). This
combination isn't set as default because it can cause noticable delays
depending on medium quality and to make methods more general for use with other
devices. Lite-On won't read GC/Wii DVDs at all without swapping. Lite-On
returns 2384 bytes of data (2064 + ECC) by means of vendor specific READ BUFFER
command. Tested with models LH-18A1H, LH-18A1P and LH-20A1H.
3. Plextor
Plextor would return 2064 bytes of already unscrambled data with READ BUFFER
command. It works good with ordinary DVDs but due the lack of streamed reading
support is practically useless for GC/Wii dumping because of very low
performance. Works nevertheless and could be used for some experiments and
testing. Results from PX-760A.
4. Toshiba Samsung SH-D162A, SH-D162B, SH-D162C, SH-D162D
Returns 2384 data bytes per sector like Lite-On does. Appears to support
streamed reading but performance with tested model (SH-D162D) was somewhat low
and unstable even with ordinary DVDs. Looks promising, if only good-working
method could be determined. Latest drives added, definitely need more testing
at this point.

187
docs/README Normal file
View file

@ -0,0 +1,187 @@
FriiDump - A program to dump Nintendo Wii and GameCube disc
===============================================================================
FriiDump is a program that lets you dump Nintendo Wii and GameCube disc from
your computer, without using original Nintendo hardware. It basically performs
the same functions as the famous "RawDump" program, but with a big difference,
which should be clear straight from its name: FriiDump is free software, where
"free" is to be intended both as in "free speech" and in "free beer". As such,
FriiDump is distributed with its sources.
This leads to a number of good consequences:
- Having the sources available, it can be easily ported to different operating
systems and hardware platforms. At the moment it is developed under a
GNU/Linux system, but it also runs natively on Windows. A MacOS X version can
be easily created, although I don't have a Mac, so I can't do it myself.
- Also, having the sources and these being well-organized (I know I'm a modest
guy) allows support for new DVD-ROM drives to be added relatively easily. At
the moment the same drives as RawDump are supported, but this might improve
in the future, if anyone takes the effort... See README.technical for
details.
- The sources might also be used as a reference for several things regarding
Nintendo Wii/GameCube discs and the hacks used to read them on an ordinary
drive.
Furthermore, FriiDump also features some functional improvements over RawDump:
- FriiDump can use 4 different methods to read the disc, with different
performance.
- FriiDump dumps a lot of useful information about the discs it dumps,
such as whether the disc contains an update or not, which can help avoid
bricking your Wii ;).
- FriiDump calculates the CRC32, MD4, MD5, SHA-1 and ED2K hashes of dumped
discs, so you can immediately know if your dump is good or not, by comparing
the hashes with the well-known ones available on several Internet sites.
- FriiDump comes in the form of a library and a command-line front-end, which
allows its functions to be easily reused in other programs.
Unfortunately, there is also a main downfall:
- Even the fastest dump method used by FriiDump is not as fast as RawDump (but
not that much slower, either, see the table below).
Anyway, I'm sure that people who cannot use RawDump (i.e.: GNU/Linux, *BSD and
MacOS X users) will be happy anyway. Besides, you get the sources, so you can
improve them yourself.
Note that FriiDump is only useful to dump *original* Nintendo discs. To dump
backup copies you can use any DVD-dumping program (i.e.: dd under UNIX ;)).
FriiDump came to existance thanks to the work by a lot of people, most of which
are probably not aware of this fact ;). Please see the AUTHORS file for the
credits.
===============================================================================
Supported drives
===============================================================================
At the moment the same drives as RawDump are supported. This is due to various
reasons, explained in the README.technical file, which also contains
information about what is needed to add support for more drives.
Currently supported drives are:
- LG GDR-8161B (untested, but should work)
- LG GDR-8162B (ditto)
- LG GDR-8163B (HL-DT-ST/DVD-ROM GDR8163B)
- LG GDR-8164B (HL-DT-ST/DVD-ROM GDR8164B)
Other drives might work, most likely those based on the Hitachi MN103
microcontroller. If you find any of them, please report so that they can be
added to the compatibility list.
===============================================================================
Installation
===============================================================================
If you are a Windows user, probably you will have downloaded the binaries,
either zipped or together with an installer, so the installation should be
straightforward.
If you downloaded the sources, you will need to compile them. FriiDump uses
CMake, for easy portability, so you will need to get it from cmake.org. On
Windows you will also need a compiler like Visual Studio (the only tested one,
so far) or CygWin/MinGW. On UNIX just do the following, from the directory
where you unpacked the sources into:
$ mkdir BUILD
$ cd BUILD
$ cmake ..
$ make
$ make install
Linux-specific note: You need root privileges to issue certain commands to the
DVD-ROM drive. Hence you have the following possibilities:
- Run FriiDump as root: discouraged.
- Run it through sudo: better but nevertheless discouraged.
- Set the setuid bit on the executable: this is the recommended way to run
FriiDump under Linux. This way, the code run with superuser privileges will
be reduced to a minimum, guaranteeing a certain level of security (note that
security-related bugs might exist anyway!!!). Also note that, even when the
setuid bit is set, the attempt to open the drive for reading will be done
after privileges have been dropped, so you will need explicit read access to
the DVD-ROM drive. Usually having the system administrator add you to the
"cdrom" group is enough. To set the setuid bit on the executable, run as
root:
$ chown root:root /usr/local/bin/friidump
$ chmod u+s /usr/local/bin/friidump
===============================================================================
Usage
===============================================================================
FriiDump is a command-line program, so you will need to run it from a terminal
or a command-prompt under Windows. The basic usage is as follows:
friidump -d <drive> -a
where <drive> will usually be something like "/dev/hda" on Unix-like systems,
and something like "e:" for Windows users. With this command, the disc will be
dumped to an ISO image file with an automatically-chosen name. Drop -a and use
the -i option if you prefer to specify the filename yourself. If you want to
resume an existing dump, use -s. If you want to dump the disc to a raw format
image file, use -r. Note that you can create a raw and an ISO image at the same
time.
Other options you might want to use are -1 through -4, to set the dump method,
although the default is method 4, which is the fastest one, so most likely you
will not need them.
Finally, use -h for a listing of all available options.
===============================================================================
Performance
===============================================================================
As stated above, FriiDump is not as fast as RawDump. On my PC (Athlon64 3200+),
performance is as follows:
-------------------------------------------------------------------------------
| Method | Dump speed | GameCube disc dump time | Wii disc dump time |
-------------------------------------------------------------------------------
| 1 | Too slow ;) | Eternity | More than eternity |
| 2 | ~570 MB/h | 2.5 hours | 8 hours |
| 3 | ~740 MB/h | 2 hours | 6 hours |
| 4 | ~1250 MB/h | 1.2 hours | 3.5 hours |
-------------------------------------------------------------------------------
===============================================================================
Support
===============================================================================
I'm releasing this program under the nickname of "Arep". This is because I am
not sure about the legal status of the program, and I do not want to encounter
any consequences. Actually, I'm pretty sure FriiDump goes against the DMCA,
being a program that circumvents copy-protection, but it might be objected that
the format used by Nintendo discs is not a copy-protection method, but just
their own, undocumented, disc format. Although, I think it can be freely used
in Europe and other coutries without laws similar to the DMCA.
For the same reason, I am not putting an e-mail address here (that @no.net you
find in the program is obviously a pun), but support will be provided through
the forums of the Italian ConsoleTribe forum, at http://wii.console-tribe.com.
If you need help, just open a thread in any section there, even in English: I
will *not* reply, but you might stand assured I will read everything you write.
FriiDump users are encouraged to help each other there ;).
Patches are welcome, too: just attach them to your post, and maybe put
something like "[PATCH]" in the topic subject, so that I can easily spot them.
New releases will be announced on that forum, and also on QJ.net, if I find a
good way to notify them.
If you want to donate to the project, do not do it, and donate to one of the
free Wii modchip projects out there, such as OpenWii, WiiFree or YAOSM.
===============================================================================
Disclaimer
===============================================================================
FriiDump is distributed under the GNU General Public License version 2. See the
COPYING file for details.
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.
Also, please note that this program is not meant to be used to spread game
piracy, but rather to be instrument to make backups of your own precious
legally-bought games.

234
docs/README.technical Normal file
View file

@ -0,0 +1,234 @@
FriiDump Techincal info
===============================================================================
This document is a reworking and unification of information found all over the
net, regarding the structure of Nintendo Gamecube/Wii Optical Discs and how to
read them on an ordinary DVD-ROM drive. All the due credits can be found in the
AUTHORS file.
===============================================================================
Nintendo Gamecube/Wii Optical Disc (GOD/WOD) structure
===============================================================================
In order to understand how a Gamecube or WII Optical Disk is made, let us
first take a look at a standard DVD-ROM. The complete standard is explained in
the ECMA-267 Standard.
The user data stored on the DVD is divided in blocks, each 2048 bytes long.
Each 2048-byte block is then encapsulated in a 2064-byte structure, adding some
other data needed for error-correction and head positioning. A 2064-byte block
is called a "Data frame", and its logical layout is as follows:
4bytes 2bytes 6bytes 2048bytes 4bytes
- - - - - - - - - - - - - - - - - - - - - - - - - -
| ID | IED | CPR_MAI | User Data Frame | EDC |
- - - - - - - - - - - - - - - - - - - - - - - - - -
- Identification Data (ID): Contains the PSN (Physical Sector Number), info
about the sector itself, like the layer, reflectivity, zone, etc.
- ID Error Detection Code (IED)
- Copyright Management Information (CPR_MAI): Its use is application-specific,
for instance it can be used to store a sector key in videos that use CSS, or
a scrambling key in the XBox and XBox360 Security Sectors.
- User Data: This is the data available for the end user.
- Error Detection Code (EDC): It is the checksum data for all the fields above,
its polinomial is x^32 + x^31 + x^4 + 1.
For various reasons (not related to copy protection), the User Data Frame is
XOR'ed with a stream cipher generated by an 15bits LFSR (Linear Feedback Shift
Register), with bits 10 and 14 used as taps. The seeds are obtained from a
table of the ECMA-267 standard, the index of the seed is the 4 MSB of the last
byte of the "ID" field of the Data Frame. The same stream cipher is then used
by 16 consecutive Data Frames: for this and other reasons (again related to
error correction), data from the DVD are always read in 16-data frame blocks.
4bytes 2bytes 6bytes 2048bytes 4bytes
- - - - - - - - - - - - - - - - - - - - - - - - - -
| ID | IED | CPR_MAI | User Data Frame | EDC |
- - - - - - - - - - - - - - - - - - - - - - - - - -
^ | 2048bytes cipher stream |
^ - - - - - - - - - -
Scrambling
seed index
Now, the first problem when dealing with Gamecube/Wii Optical Discs is that
they use a different (and yet unknown) set of seeds. This means that when an
ordinary DVD-ROM drive tries to read a GOD/WOD disc, it will unscramble the
User Data Frame with the wrong seed, causing the EDC check to fail and a read
error to be reported to the operating system, which means the inability to read
the disc.
Furthermore, Gamecube/Wii Optical Disks use a slightly different structure for
the Data Frame, as shown in the following figure:
4bytes 2bytes 2048bytes 6bytes 4bytes
- - - - - - - - - - - - - - - - - - - - - - - - - -
| ID | IED | User Data Frame | CPR_MAI | EDC |
- - - - - - - - - - - - - - - - - - - - - - - - - -
| 2048bytes cipher stream |
- - - - - - - - - -
Basically, the User Data Frame and the CPR_MAI fields are swapped, while the
scrambled bytes remain the same.
===============================================================================
Tricks used to read a GOD/WOD on a standard DVD-ROM drive.
===============================================================================
To cope with the above-mentioned problems, some methods have been suggested by
many people on the net. They vary in performance, but the basic idea is always
the same:
1. Issue a read command for the sector of interest (this is actually a
16-sector block, not a single sector, as stated above).
2. Let the read return failure.
3. At this moment, the DVD-ROM drive must have cached the data read from the
disc somewhere in its internal memory, to be able to unscramble them and to
check the EDC. So, we can dump the data from the drive's internal RAM.
Unfortunately, this is not as easy as it seems, due to the fact that there is
no standard "Dump drive memory" command. This is probably implemented in many
drives for firmware debugging purposes, but, as such, it is a vendor-specific
command, which are usually undocumented and vary from vendor to vendor (or even
from drive model to drive model).
This is where the work that many hackers around the world have done, in order
to crack the Microsoft XBox360 console, becomes useful. They needed some way to
read and write data to the XBox360 drive's internal memory, so they
disassembled the drive's firmware and patiently tried to understand what each
of the vendor-specific commands did. This way, they discovered that a certain
command could be used to read an arbitrary portion of the drive's internal RAM.
They also managed to map the RAM addresses, so that it is known where data
read from the disc are temporarily stored.
Fortunately, the XBox360 drive is not too different from some retail DVD-ROM
drives, namely some models from LG, which means that the discovered command
works on them as well. Hence, we now have some sort of access to the disc data.
Although, this comes at the price of speed: dumping the drive's internal memory
is a slow process, as it uses Programmed I/O (PIO) instead of Direct Memory
Access (DMA) to transfer data from the drive to the computer's memory. For this
reason, some have proposed the use of the "streaming read" command: it is a
standard command thought for those applications where the constant flow of data
is more important than its absolute correctness, such as audio or video
applications. Thus, this command does not perform the EDC on the data read from
the disc, but returns it immediately. Anyway, the command will only return the
User Data Frame, which means that only a portion of the data will be read this
way, while the rest (i.e.: the first 12 and the last 4 bytes) will have to be
read using the memory dump method. Nevertheless, this combined method will be
faster overall, as only some dozens of bytes have to be transfered through PIO,
instead of the whole sectors.
We still have to cope with the unknown seeds. This problem can be easily solved
through the use of brute force: as there are only 15 bits to try (and commonly
only 17 seeds per GOD/WOD), this approach only takes about 30 seconds. The
bruteforce process is very simple: the LFSR is seeded from 0 to 7FFFh and for
each seed the corresponding stream cipher is generated and XOR'ed with the
proper section of the Data Frame and the EDC is computed. If the EDC is the same
as the one in the EDC field then we have the correct seed.
===============================================================================
The FriiDump approach
===============================================================================
FriiDump can use four different disc dump methods. They have been developed
gradually, empirically and heuristically, by experimenting with the PLScsi tool
and comparing the retrieved data with a known-good dump. In this section the
inner working of every dump method will be described. The code implementing the
different methods can be found in the "disc_read_sector_X" functions of disc.c.
Please note that the desibed behaviour is that of my LG GDR8164B drive, which I
assume to be shared by similar drives. Other, more different drives, might
behave differently and require totally different methods.
Also note that all of the methods read 16-sector blocks.
Method 1
This method is very slow. So slow that I have never dumped a whole disc with
it. Although, it served me to prove that I was going in the right direction and
that my efforts could eventually come to a working end. It also showed me that
the first versions of RawDump create bad dumps, sometimes.
Basically this method is the same used by those early versions of RawDump,
which took 50+ hours to dump a whole disc. It works like this:
1. Issue a read command for the required sector. This will cause the 16-sector
block to which the sector belongs to be placed at the beginning of the
drive's cache memory. Do not even bother to see what the read command
returns, as it will surely be a data read error.
2. Dump the 16-sector block.
Method 2
Method 2 is similar to method 1, but uses the above-mentioned "streaming read"
method, which somehow allows us to dump 5 blocks at a time.
1. Issue a "streaming read" command for the required sector. This will cause
the 16-sector block to which the sector belongs to be placed at the
beginning of the drive's cache memory, together with the 4 following
16-sector blocks. Do not bother to see what the read command returns.
2. Dump the 5 16-sector blocks.
Method 3
This is similar to the previous method, but instead of dumping the whole
sectors from memory, it uses the (not EDC checked) data returned by the
"streaming read" command. and completes it dumping only the missing bits from
memory.
1. Issue a "streaming read" command for the required sector. This will cause
the 16-sector block to which the sector belongs to be placed at the
beginning of the drive's cache memory, together with the 4 following
16-sector blocks.
2. For each sector of each block, reconstruct the whole Data Frame, as follows:
- Dump 12 bytes from memory.
- Use 2048 bytes returned by the read command.
- Dump 4 more bytes from memory.
Note that this method has a small issue, as sometimes the beginning of the
cache will be dirty and contain invalid data, needing the sector to be read
again. As this seems to happen quite often, we always read a dummy sector
before the requested sector.
Method 4
Method 4 is just method 3 with a trick to use a single dump command for every
sector that has to be reconstructed, instead of two. It is the faster dump
method currently supported and, as such, the default one.
1. Issue a "streaming read" command for the required sector. This will cause
the 16-sector block to which the sector belongs to be placed at the
beginning of the drive's cache memory, together with the 4 following
16-sector blocks.
2. For each sector of each block, reconstruct the whole Data Frame, as follows:
- If this is the first sector of a block, dump 12 bytes from memory.
Otherwise, use the last 12 bytes of the preceding dump.
- Use 2048 bytes returned by the read command.
- Dump 16 bytes from memory, and use the first 4. This leaves 12 bytes to be
used for the reconstruction of the next sector.
Note that the issue of method 3 applies to this method, too.
===============================================================================
How to add support for a new drive
===============================================================================
If you read all the above stuff, it should be clear that, in order to add
support for a new DVD-ROM drive, all that is needed is a way to dump the
drive's internal memory, in particular the portion where the data read from the
disc is cached. As explained above, this function might not be present in all
drives, and might not be easy to find or to use. In case you manage to discover
it, just copy the file "hitachi.c" to a new one, and modify it opportunely.
Some modifications will also be needed in "dvd_drive.c", in order to add
autodetection for the new drive, in the "dvd_assign_functions" function.
Apart from this, the cache behaviour of the new drive might not be the same
as that of the currently supported models, so the program architecture might
need radical changes. In this case, please report.

13
docs/TODO Normal file
View file

@ -0,0 +1,13 @@
- Hashes are wrongly calculated on big-endian machines. This just needs fixing
of some #define's in the multihash library.
- Add MacOS X-specific code. All that is needed is a way to send MMC commands
to the DVD-ROM drive. Inspiration can be taken from the libcdio sources. If
only I had a Mac... Same goes for *BSD, anyway.
- Maybe write a graphical client. I will not do this as I am no GUI fanatic,
but I am sure many Windows users will still use RawDump as it has a GUI,
while we do not. This is actually quite easy, as the program is split into a
library (libfriidump) and a frontend. If anybody does it, please try to make
a portable GUI, maybe by using GTK+, qt, wxWidgets or whatever similar
toolkit you might find.
- Make FriiDump as fast as RawDump (i.e.: 2.5 hours for a Wii disc).
- Improve and better document the library API.

64
docs/options Normal file
View file

@ -0,0 +1,64 @@
FriiDump 0.5.3 - Copyright (C) 2007 Arep
This software comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions; see COPYING for details.
Official support forum: http://wii.console-tribe.com
Forum for this UNOFFICIAL VERSION: http://forum.redump.org
Available command line options:
-h, --help Show this help
-a, --autodump Dump the disc to an ISO file with an
automatically-generated name, resuming the dump
if possible
-g, --gui Use more verbose output that can be easily
parsed by a GUI frontend
-d, --device <device> Dump disc from device <device>
-p, --stop Instruct device to stop disc rotation
-c, --command <nr> Force memory dump command:
0 - vanilla 2064
1 - vanilla 2384
2 - Hitachi
3 - Lite-On
4 - Renesas
-x, --speed <x> Set streaming speed (1, 24, 32, 64, etc.,
where 1 = 150 KiB/s and so on)
-T, --type <nr> Force disc type:
0 - GameCube
1 - Wii
2 - Wii_DL
3 - DVD
-S, --size <sectors> Force disc size
-r, --raw <file> Output to file <file> in raw format (2064-byte
sectors)
-i, --iso <file> Output to file <file> in ISO format (2048-byte
sectors)
-u, --unscramble <file> Convert (unscramble) raw image contained in
<file> to ISO format
-H, --nohash Do not compute CRC32/MD5/SHA-1 hashes
for generated files
-s, --resume Resume partial dump
- General -----------------------------------
-0, --method0[=<req>,<exp>] Use dumping method 0 (Optional argument
specifies how many sectors to request from disc
and read from cache at a time. Values should be
separated with a comma. Default 16,16)
- Non-Streaming -----------------------------
-1, --method1[=<req>,<exp>] Use dumping method 1 (Default 16,16)
-2, --method2[=<req>,<exp>] Use dumping method 2 (Default 16,16)
-3, --method3[=<req>,<exp>] Use dumping method 3 (Default 16,16)
- Streaming ---------------------------------
-4, --method4[=<req>,<exp>] Use dumping method 4 (Default 27,27)
-5, --method5[=<req>,<exp>] Use dumping method 5 (Default 27,27)
-6, --method6[=<req>,<exp>] Use dumping method 6 (Default 27,27)
- Hitachi -----------------------------------
-7, --method7 Use dumping method 7 (Read and dump 5 blocks
at a time, using streaming read)
-8, --method8 Use dumping method 8 (Read and dump 5 blocks
at a time, using streaming read, using DMA)
-9, --method9 Use dumping method 9 (Read and dump 5 blocks
at a time, using streaming read, using DMA and
some speed tricks)

11
libfriidump.pc.in Normal file
View file

@ -0,0 +1,11 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: LibFriiDump
Description: Library to dump Nintendo GameCube/Wii discs
Version: @VERSION@
URL: http://wii.console-tribe.com
Libs: -L${libdir} -lfriidump
Cflags: -I${includedir}/libfriidump

105
libfriidump/CMakeLists.txt Normal file
View file

@ -0,0 +1,105 @@
# Create a library called "Hello" which includes the source file "hello.cxx".
# The extension is already found. Any number of sources could be listed here.
add_library (
friidumplib
${libfriidump_type}
#SHARED
#STATIC
brickblocker.h
brickblocker.c
byteorder.h
constants.h
disc.h
disc.c
dumper.h
dumper.c
dvd_drive.h
dvd_drive.c
hitachi.c
ecma-267.h
ecma-267.c
lite-on.c
misc.h
misc.c
renesas.c
rs.h
rs.c
unscrambler.h
unscrambler.c
vanilla_2064.c
vanilla_2384.c
win32compat.h
win32compat.c
)
set_target_properties (friidumplib PROPERTIES OUTPUT_NAME "friidump")
include_directories (
${FriiDump_SOURCE_DIR}/libmultihash
)
# Make sure the linker can find the Hello library once it is built.
link_directories (
${FriiDump_BINARY_DIR}/libmultihash
)
# Link the executable to the Hello library.
target_link_libraries (
friidumplib
multihashlib
)
# Before making a release, the LTVERSION string should be modified.
# The string is of the form CURRENT:REVISION:AGE.
#
# CURRENT (C)
# The most recent interface number that this library implements.
#
# REVISION (R)
# The implementation number that this library implements.
#
# AGE (A)
# The difference between the newest and oldest interfaces that this
# library implements. In other works, the library implements all the
# interface numbers in the range from number 'CURRENT - AGE' to
# 'CURRENT'.
#
# This means that:
#
# - If interfaces have been changed or added, but binary compatibility has
# been preserved, change to C+1:0:A+1
#
# - If binary compatibility has been broken (eg removed or changed
# interfaces) change to C+1:0:0
#
# - If the interface is the same as the previous version, change to C:R+1:A
#
#set_target_properties (friidumplib PROPERTIES SOVERSION 1.0.0)
# Windows stuff to correctly build DLL or static library
#get_target_property (libfriidump_type friidumplib TYPE)
if (WIN32)
if (libfriidump_type STREQUAL "SHARED")
# MESSAGE ("Building libfriidump DLL")
ADD_DEFINITIONS (-DFRIIDUMPLIB_BUILD_DLL)
set_target_properties (friidumplib PROPERTIES DEFINE_SYMBOL FRIIDUMPLIB_EXPORTS)
install (
TARGETS friidumplib
RUNTIME DESTINATION /
#ARCHIVE DESTINATION lib
)
endif (libfriidump_type STREQUAL "SHARED")
else (WIN32)
# Install stuff, only if a shared library is being built
if (libfriidump_type STREQUAL "SHARED")
install (
TARGETS friidumplib
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib/static
)
endif (libfriidump_type STREQUAL "SHARED")
endif (WIN32)

View file

@ -0,0 +1,22 @@
/***************************************************************************
* Copyright (C) 2007 by Arep *
* Support is provided through the forums at *
* http://wii.console-tribe.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
/* wiidevel@stacktic.org */

View file

@ -0,0 +1,20 @@
/***************************************************************************
* Copyright (C) 2007 by Arep *
* Support is provided through the forums at *
* http://wii.console-tribe.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/

77
libfriidump/byteorder.h Normal file
View file

@ -0,0 +1,77 @@
/***************************************************************************
* Copyright (C) 2007 by Arep *
* Support is provided through the forums at *
* http://wii.console-tribe.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "misc.h"
#include <sys/types.h>
/*************************** BYTE SWAPPING MACROS ***************************/
// WORDS_BIGENDIAN is defined by the AC_C_BIGENDIAN autoconf macro, in case. On Windows please (un)define manually.
#ifdef WORDS_BIGENDIAN //!< Swapping macros on big endian systems (Where host b. o. = network b. o.)
/* This machine's order to big endian */
#define bo_my2big_16(a) ((u_int16_t)(a))
#define bo_my2big_32(a) ((u_int32_t)(a))
/* This machine's order to little endian */
#define bo_my2little_16(a) ( \
((((u_int16_t) (a)) & 0x00FF) << 8) + \
(((u_int16_t) (a)) >> 8) \
)
#define bo_my2little_32(a) ( \
((((u_int32_t) (a)) & 0x000000FF) << 24) + \
((((u_int32_t) (a)) & 0x0000FF00) << 8) + \
((((u_int32_t) (a)) & 0x00FF0000) >> 8) + \
(((u_int32_t) (a)) >> 24) \
)
#else //!< Swapping macros on little endian systems
/* This machine's order to big endian */
#define bo_my2big_16(a) ( \
((((u_int16_t) (a)) & 0x00FF) << 8) + \
(((u_int16_t) (a)) >> 8) \
)
#define bo_my2big_32(a) ( \
((((u_int32_t) (a)) & 0x000000FF) << 24) + \
((((u_int32_t) (a)) & 0x0000FF00) << 8) + \
((((u_int32_t) (a)) & 0x00FF0000) >> 8) + \
(((u_int32_t) (a)) >> 24) \
)
/* This machine's order to little endian */
#define bo_my2little_16(a) ((u_int16_t)(a))
#define bo_my2little_32(a) ((u_int32_t)(a))
#endif
/* These will be handy */
/* Big endian to this machine's order */
#define bo_big2my_16(x) bo_my2big_16(x)
#define bo_big2my_32(x) bo_my2big_32(x)
/* Little endian to this machine's order */
#define bo_little2my_16(x) bo_my2little_16(x)
#define bo_little2my_32(x) bo_my2little_32(x)
/* There are the most useful ones */
#define my_htons(x) bo_my2big_16(x)
#define my_htonl(x) bo_my2big_32(x)
#define my_ntohs(x) my_htons(x)
#define my_ntohl(x) my_htonl(x)
/************************ END OF BYTE SWAPPING MACROS ***********************/

46
libfriidump/constants.h Normal file
View file

@ -0,0 +1,46 @@
/***************************************************************************
* Copyright (C) 2007 by Arep *
* Support is provided through the forums at *
* http://wii.console-tribe.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
/*! \file
* \brief Nintendo GameCube/Wii disc geometry constants.
*
* This file contains constants that describe the general layout of Nintendo GameCube/Wii discs and that can be used throughout the whole program.
*/
#ifndef CONSTANTS_H_INCLUDED
#define CONSTANTS_H_INCLUDED
/*! \brief Size of a scrambled sector */
#define RAW_SECTOR_SIZE 2064
/*! \brief Size of an unscrambled sector */
#define SECTOR_SIZE 2048
/*! \brief Number of sectors in a block */
#define SECTORS_PER_BLOCK 16
/*! \brief Size of a scrambled block */
#define RAW_BLOCK_SIZE (RAW_SECTOR_SIZE * SECTORS_PER_BLOCK)
/*! \brief Size of an unscrambled block */
#define BLOCK_SIZE (SECTOR_SIZE * SECTORS_PER_BLOCK)
#endif

1675
libfriidump/disc.c Normal file

File diff suppressed because it is too large Load diff

94
libfriidump/disc.h Normal file
View file

@ -0,0 +1,94 @@
/***************************************************************************
* Copyright (C) 2007 by Arep *
* Support is provided through the forums at *
* http://wii.console-tribe.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef DISC_H_INCLUDED
#define DISC_H_INCLUDED
#include "misc.h"
#include <sys/types.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
DISC_TYPE_GAMECUBE,
DISC_TYPE_WII,
DISC_TYPE_WII_DL,
DISC_TYPE_DVD
} disc_type;
typedef enum {
DISC_REGION_PAL,
DISC_REGION_NTSC,
DISC_REGION_JAPAN,
DISC_REGION_AUSTRALIA,
DISC_REGION_FRANCE,
DISC_REGION_GERMANY,
DISC_REGION_ITALY,
DISC_REGION_SPAIN,
DISC_REGION_PAL_X,
DISC_REGION_PAL_Y,
DISC_REGION_UNKNOWN
} disc_region;
typedef struct disc_s disc;
/* Functions */
FRIIDUMPLIB_EXPORT disc *disc_new (char *dvd_device, u_int32_t command);
FRIIDUMPLIB_EXPORT bool disc_init (disc *d, u_int32_t forced_type, u_int32_t sectors_no);
FRIIDUMPLIB_EXPORT void *disc_destroy (disc *d);
FRIIDUMPLIB_EXPORT int disc_read_sector (disc *d, u_int32_t sector_no, u_int8_t **data, u_int8_t **rawdata);
FRIIDUMPLIB_EXPORT bool disc_set_read_method (disc *d, int method);
FRIIDUMPLIB_EXPORT void disc_set_unscrambling (disc *d, bool unscramble);
FRIIDUMPLIB_EXPORT void disc_set_speed (disc *d, u_int32_t speed);
FRIIDUMPLIB_EXPORT void disc_set_streaming_speed (disc *d, u_int32_t speed);
FRIIDUMPLIB_EXPORT bool disc_stop_unit (disc *d, bool start);
FRIIDUMPLIB_EXPORT void init_range (disc *d, u_int32_t sec_disc, u_int32_t sec_mem);
/* Getters */
FRIIDUMPLIB_EXPORT u_int32_t disc_get_sectors_no (disc *d);
FRIIDUMPLIB_EXPORT u_int32_t disc_get_layerbreak (disc *d);
FRIIDUMPLIB_EXPORT u_int32_t disc_get_command (disc *d);
FRIIDUMPLIB_EXPORT u_int32_t disc_get_method (disc *d);
FRIIDUMPLIB_EXPORT u_int32_t disc_get_def_method (disc *d);
FRIIDUMPLIB_EXPORT u_int32_t disc_get_sec_disc (disc *d);
FRIIDUMPLIB_EXPORT u_int32_t disc_get_sec_mem (disc *d);
FRIIDUMPLIB_EXPORT char *disc_get_type (disc *d, disc_type *dt, char **dt_s);
FRIIDUMPLIB_EXPORT char *disc_get_gameid (disc *d, char **gid_s);
FRIIDUMPLIB_EXPORT char *disc_get_region (disc *d, disc_region *dr, char **dr_s);
FRIIDUMPLIB_EXPORT char *disc_get_maker (disc *d, char **m, char **m_s);
FRIIDUMPLIB_EXPORT char *disc_get_version (disc *d, u_int8_t *v, char **v_s);
FRIIDUMPLIB_EXPORT char *disc_get_title (disc *d, char **t_s);
FRIIDUMPLIB_EXPORT bool disc_get_update (disc *d);
FRIIDUMPLIB_EXPORT char *disc_get_drive_model_string (disc *d);
FRIIDUMPLIB_EXPORT bool disc_get_drive_support_status (disc *d);
#ifdef __cplusplus
}
#endif
#endif

439
libfriidump/dumper.c Normal file
View file

@ -0,0 +1,439 @@
/***************************************************************************
* Copyright (C) 2007 by Arep *
* Support is provided through the forums at *
* http://www.console-tribe.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "misc.h"
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <multihash.h>
#include "constants.h"
#include "disc.h"
#include "dumper.h"
#ifndef WIN32
#include <unistd.h>
#include <sys/types.h>
#endif
struct dumper_s {
disc *dsk;
char *outfile_raw;
u_int32_t start_sector_raw;
FILE *fp_raw;
char *outfile_iso;
u_int32_t start_sector_iso;
FILE *fp_iso;
u_int32_t start_sector;
bool hashing;
bool flushing;
multihash hash_raw;
multihash hash_iso;
progress_func progress;
void *progress_data;
};
/**
* Tries to open the output file for writing and to find out if it contains valid data so that the dump can continue.
* @param dvd
* @param outfile
* @param[out] fp The file pointer to write to.
* @param[out] start_sector The sector to start reading from.
* @return true if the dumping can start/continue, false otherwise (for instance if outfile cannot be written to).
*/
bool dumper_set_raw_output_file (dumper *dmp, char *outfile_raw, bool resume) {
bool out;
my_off_t filesize;
FILE *fp;
if (!outfile_raw) {
/* Raw output disabled */
out = true;
dmp -> start_sector_raw = -1;
my_free (dmp -> outfile_raw);
dmp -> outfile_raw = NULL;
} else if (dmp -> outfile_raw) {
error ("Raw output file already defined");
out = false;
} else if (!(fp = fopen (outfile_raw, "rb"))) { /** @todo Maybe we could not open file for permission problems */
/* Raw output file does not exist, start from scratch */
out = true;
dmp -> start_sector_raw = 0;
my_strdup (dmp -> outfile_raw, outfile_raw);
} else if (resume) {
/* Raw output file exists and resume was requested, so see how many dumped sectors it contains */
my_fseek (fp, 0, SEEK_END);
filesize = my_ftell (fp);
fclose (fp);
out = true;
dmp -> start_sector_raw = (u_int32_t) (filesize / RAW_SECTOR_SIZE / SECTORS_PER_BLOCK) * SECTORS_PER_BLOCK;
debug ("Raw output can restart from sector %u", dmp -> start_sector_raw);
my_strdup (dmp -> outfile_raw, outfile_raw);
} else {
/* Raw output file exists but resume was not requested, error */
fclose (fp);
error ("Raw output file exists, but resume was not requested.");
out = false;
dmp -> start_sector_raw = -1;
my_free (dmp -> outfile_raw);
dmp -> outfile_raw = NULL;
}
return (out);
}
bool dumper_set_iso_output_file (dumper *dmp, char *outfile_iso, bool resume) {
bool out;
my_off_t filesize;
FILE *fp;
if (!outfile_iso) {
/* Raw output disabled */
out = true;
dmp -> start_sector_iso = -1;
my_free (dmp -> outfile_iso);
dmp -> outfile_iso = NULL;
} else if (dmp -> outfile_iso) {
error ("ISO output file already defined");
out = false;
} else if (!(fp = fopen (outfile_iso, "rb"))) { /** @todo Maybe we could not open file for permission problems */
/* Raw output file does not exist, start from scratch */
out = true;
dmp -> start_sector_iso = 0;
my_strdup (dmp -> outfile_iso, outfile_iso);
} else if (resume) {
/* Raw output file exists and resume was requested, so see how many dumped sectors it contains */
my_fseek (fp, 0, SEEK_END);
filesize = my_ftell (fp);
fclose (fp);
out = true;
dmp -> start_sector_iso = (u_int32_t) (filesize / SECTOR_SIZE / SECTORS_PER_BLOCK) * SECTORS_PER_BLOCK;
debug ("ISO output can restart from sector %u", dmp -> start_sector_iso);
my_strdup (dmp -> outfile_iso, outfile_iso);
} else {
/* Raw output file exists but resume was not requested, error */
fclose (fp);
error ("ISO output file exists, but resume was not requested.");
out = false;
dmp -> start_sector_iso = -1;
my_free (dmp -> outfile_iso);
dmp -> outfile_iso = NULL;
}
return (out);
}
bool dumper_prepare (dumper *dmp) {
bool out;
u_int8_t buf[RAW_SECTOR_SIZE];
size_t r;
u_int32_t i;
/* Outputting to both files, resume must start from the file with the least sectors. Hopefully they will have the same number of sectors, anyway... */
if (dmp -> outfile_raw && dmp -> outfile_iso && dmp -> start_sector_raw != dmp -> start_sector_iso) {
if (dmp -> start_sector_raw < dmp -> start_sector_iso)
dmp -> start_sector = dmp -> start_sector_raw;
else
dmp -> start_sector = dmp -> start_sector_iso;
} else if (dmp -> outfile_raw) {
dmp -> start_sector = dmp -> start_sector_raw;
} else if (dmp -> outfile_iso) {
dmp -> start_sector = dmp -> start_sector_iso;
} else {
MY_ASSERT (0);
}
/* Prepare hashes */
if (dmp -> hashing) {
multihash_init (&(dmp -> hash_raw));
multihash_init (&(dmp -> hash_iso));
}
/* Setup raw output file */
if (dmp -> outfile_raw) {
dmp -> fp_raw = fopen (dmp -> outfile_raw, "a+b");
if (dmp -> hashing) {
debug ("Calculating hashes for pre-existing raw dump data");
if (dmp -> start_sector > 0) {
for (i = 0; i < dmp -> start_sector && (r = fread (buf, RAW_SECTOR_SIZE, 1, dmp -> fp_raw)) > 0; i++)
multihash_update (&(dmp -> hash_raw), buf, RAW_SECTOR_SIZE);
MY_ASSERT (r > 0);
}
}
/* Now call fseek as file will only be written, from now on */
if (my_fseek (dmp -> fp_raw, dmp -> start_sector * RAW_SECTOR_SIZE, SEEK_SET) == 0 &&
ftruncate (fileno (dmp -> fp_raw), (int64_t) dmp -> start_sector * RAW_SECTOR_SIZE) == 0) {
out = true;
debug ("Writing to file \"%s\" in raw format (fseeked() to %lld)", dmp -> outfile_raw, my_ftell (dmp -> fp_raw));
} else {
out = false;
fclose (dmp -> fp_raw);
dmp -> fp_raw = NULL;
}
} else {
dmp -> fp_raw = NULL;
}
/* Setup ISO output file */
if (dmp -> outfile_iso) {
dmp -> fp_iso = fopen (dmp -> outfile_iso, "a+b");
if (dmp -> hashing) {
debug ("Calculating hashes for pre-existing ISO dump data");
if (dmp -> start_sector > 0) {
for (i = 0; i < dmp -> start_sector && (r = fread (buf, SECTOR_SIZE, 1, dmp -> fp_iso)) > 0; i++)
multihash_update (&(dmp -> hash_iso), buf, SECTOR_SIZE);
MY_ASSERT (r > 0);
}
}
if (my_fseek (dmp -> fp_iso, dmp -> start_sector * SECTOR_SIZE, SEEK_SET) == 0 &&
ftruncate (fileno (dmp -> fp_iso), (int64_t) dmp -> start_sector * SECTOR_SIZE) == 0) {
out = true;
debug ("Writing to file \"%s\" in ISO format (fseeked() to %lld)", dmp -> outfile_iso, my_ftell (dmp -> fp_iso));
} else {
out = false;
fclose (dmp -> fp_iso);
dmp -> fp_iso = NULL;
}
} else {
dmp -> fp_iso = NULL;
}
return (out);
}
int dumper_dump (dumper *dmp, u_int32_t *current_sector) {
bool out;
u_int8_t *rawbuf, *isobuf;
u_int32_t i, sectors_no, last_sector;
#ifdef DEBUGaa
bool no_unscrambling;
#endif
#ifdef DEBUGaa
no_unscrambling = dd -> no_unscrambling;
if (fp_iso && no_unscrambling) {
warning ("Output to ISO format requested, ignoring no_unscrambling!");
no_unscrambling = false;
}
#endif
sectors_no = disc_get_sectors_no (dmp -> dsk);
#if 0
if (dd -> start_sector != -1) {
if (dd -> start_sector >= sectors_no) {
error ("Cannot start dumping from sector %u as the inserted disc only has %u sectors\n", dd -> start_sector, sectors_no);
out = false;
} else {
warning ("Start sector forced to %u\n", dd -> start_sector);
ss = dd -> start_sector;
if (fp_iso)
fseek (fp_iso, ss * 2048, SEEK_SET);
if (fp_raw)
fseek (fp_raw, ss * 2064, SEEK_SET);
}
}
#endif
if (true) {
debug ("Starting dump process from sector %u...\n", dmp -> start_sector);
/* First call to progress function */
if (dmp -> progress)
dmp -> progress (true, dmp -> start_sector, sectors_no, dmp -> progress_data);
last_sector=sectors_no-1;
for (i = dmp -> start_sector, out = true; i < sectors_no && out; i++) {
disc_read_sector (dmp -> dsk, i, &isobuf, &rawbuf);
if (dmp -> fp_raw) {
clearerr (dmp -> fp_raw);
if (!rawbuf) {
error ("NULL buffer");
out = false;
*(current_sector) = i;
}
else fwrite (rawbuf, RAW_SECTOR_SIZE, 1, dmp -> fp_raw);
if (ferror (dmp -> fp_raw)) {
error ("fwrite() to raw output file failed");
out = false;
*(current_sector) = i;
}
if (dmp -> flushing)
fflush (dmp -> fp_raw);
if (dmp -> hashing && out)
multihash_update (&(dmp -> hash_raw), rawbuf, RAW_SECTOR_SIZE);
}
if (dmp -> fp_iso) {
clearerr (dmp -> fp_iso);
if (!isobuf) {
error ("NULL buffer");
out = false;
*(current_sector) = i;
}
else fwrite (isobuf, SECTOR_SIZE, 1, dmp -> fp_iso);
if (ferror (dmp -> fp_iso)) {
error ("fwrite() to ISO output file failed");
out = false;
*(current_sector) = i;
}
if (dmp -> flushing)
fflush (dmp -> fp_iso);
if (dmp -> hashing && out)
multihash_update (&(dmp -> hash_iso), isobuf, SECTOR_SIZE);
}
if ((i % 320 == 0) || (i == last_sector)) { //speedhack
if (dmp -> progress)
dmp -> progress (false, i + 1, sectors_no, dmp -> progress_data); /* i + 1 'cause sectors range from 0 to N */
}
}
if (dmp -> hashing) {
multihash_finish (&(dmp -> hash_raw));
multihash_finish (&(dmp -> hash_iso));
}
if (dmp -> fp_raw)
fclose (dmp -> fp_raw);
if (dmp -> fp_iso)
fclose (dmp -> fp_iso);
if (out) {
}
}
return (out);
}
dumper *dumper_new (disc *d) {
dumper *dmp;
dmp = (dumper *) malloc (sizeof (dumper));
memset (dmp, 0, sizeof (dumper));
dmp -> dsk = d;
dumper_set_hashing (dmp, true);
dumper_set_flushing (dmp, true);
return (dmp);
}
void dumper_set_progress_callback (dumper *dmp, progress_func progress, void *progress_data) {
dmp -> progress = progress;
dmp -> progress_data = progress_data;
return;
}
void dumper_set_hashing (dumper *dmp, bool h) {
dmp -> hashing = h;
debug ("Hashing %s", h ? "enabled" : "disabled");
return;
}
void dumper_set_flushing (dumper *dmp, bool f) {
dmp -> flushing = f;
debug ("Flushing %s", f ? "enabled" : "disabled");
return;
}
void *dumper_destroy (dumper *dmp) {
my_free (dmp -> outfile_raw);
my_free (dmp -> outfile_iso);
my_free (dmp);
return (NULL);
}
char *dumper_get_iso_crc32 (dumper *dmp) {
return ((dmp -> hash_iso).crc32_s);
}
char *dumper_get_raw_crc32 (dumper *dmp) {
return ((dmp -> hash_raw).crc32_s);
}
char *dumper_get_iso_md4 (dumper *dmp) {
return ((dmp -> hash_iso).md4_s);
}
char *dumper_get_raw_md4 (dumper *dmp) {
return ((dmp -> hash_raw).md4_s);
}
char *dumper_get_iso_md5 (dumper *dmp) {
return ((dmp -> hash_iso).md5_s);
}
char *dumper_get_raw_md5 (dumper *dmp) {
return ((dmp -> hash_raw).md5_s);
}
char *dumper_get_iso_ed2k (dumper *dmp) {
return ((dmp -> hash_iso).ed2k_s);
}
char *dumper_get_raw_ed2k (dumper *dmp) {
return ((dmp -> hash_raw).ed2k_s);
}
char *dumper_get_iso_sha1 (dumper *dmp) {
return ((dmp -> hash_iso).sha1_s);
}
char *dumper_get_raw_sha1 (dumper *dmp) {
return ((dmp -> hash_raw).sha1_s);
}

60
libfriidump/dumper.h Normal file
View file

@ -0,0 +1,60 @@
/***************************************************************************
* Copyright (C) 2007 by Arep *
* Support is provided through the forums at *
* http://www.console-tribe.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef DUMPER_H_INCLUDED
#define DUMPER_H_INCLUDED
#include "misc.h"
#include <sys/types.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct dumper_s dumper;
typedef void (*progress_func) (bool start, u_int32_t current_sector, u_int32_t total_sectors, void *progress_data);
FRIIDUMPLIB_EXPORT bool dumper_set_raw_output_file (dumper *dmp, char *outfile_raw, bool resume);
FRIIDUMPLIB_EXPORT bool dumper_set_iso_output_file (dumper *dmp, char *outfile_iso, bool resume);
FRIIDUMPLIB_EXPORT bool dumper_prepare (dumper *dmp);
FRIIDUMPLIB_EXPORT int dumper_dump (dumper *dmp, u_int32_t *current_sector);
FRIIDUMPLIB_EXPORT dumper *dumper_new (disc *d);
FRIIDUMPLIB_EXPORT void dumper_set_progress_callback (dumper *dmp, progress_func progress, void *progress_data);
FRIIDUMPLIB_EXPORT void dumper_set_hashing (dumper *dmp, bool h);
FRIIDUMPLIB_EXPORT void dumper_set_flushing (dumper *dmp, bool f);
FRIIDUMPLIB_EXPORT void *dumper_destroy (dumper *dmp);
FRIIDUMPLIB_EXPORT char *dumper_get_iso_crc32 (dumper *dmp);
FRIIDUMPLIB_EXPORT char *dumper_get_raw_crc32 (dumper *dmp);
FRIIDUMPLIB_EXPORT char *dumper_get_iso_md4 (dumper *dmp);
FRIIDUMPLIB_EXPORT char *dumper_get_raw_md4 (dumper *dmp);
FRIIDUMPLIB_EXPORT char *dumper_get_iso_md5 (dumper *dmp);
FRIIDUMPLIB_EXPORT char *dumper_get_raw_md5 (dumper *dmp);
FRIIDUMPLIB_EXPORT char *dumper_get_iso_ed2k (dumper *dmp);
FRIIDUMPLIB_EXPORT char *dumper_get_raw_ed2k (dumper *dmp);
FRIIDUMPLIB_EXPORT char *dumper_get_iso_sha1 (dumper *dmp);
FRIIDUMPLIB_EXPORT char *dumper_get_raw_sha1 (dumper *dmp);
#ifdef __cplusplus
}
#endif
#endif

755
libfriidump/dvd_drive.c Normal file
View file

@ -0,0 +1,755 @@
/***************************************************************************
* Copyright (C) 2007 by Arep *
* Support is provided through the forums at *
* http://wii.console-tribe.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
/*! \file
* \brief A class to send raw MMC commands to a CD/DVD-ROM drive.
*
* This class can be used to send raw MMC commands to a CD/DVD-ROM drive. It uses own structures and data types to represent the commands, which are
* then transformed in the proper OS-dependent structures when the command is executed, achieving portability. Currently Linux and Windows are supported, but
* all that is needed to add support to a new OS is a proper <code>dvd_execute_cmd()</code> function, so it should be very easy. I hope that someone can add
* compatibility with MacOS X and *BSD: libcdio is a good place to understand how it should be done :). Actally, we could have used libcdio right from the start,
* but I didn't want to add a dependency on a library that cannot be easily found in binary format for all the target OS's.
*
* This file contains code derived from the work of Kevin East (SeventhSon), kev@kev.nu, http://www.kev.nu/360/ , which, in turn, derives from work by
* a lot of other people. See his page for full details.
*/
#include "rs.h"
#include "misc.h"
#include <stdio.h>
#include <sys/types.h>
//#include <sys/time.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include "dvd_drive.h"
#include "disc.h"
#ifdef WIN32
#include <windows.h>
#include <ntddscsi.h>
#else
#include <linux/cdrom.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#endif
/*! \brief Timeout for MMC commands.
*
* This must be expressed in seconds (Windows uses seconds, right?).
*/
#define MMC_CMD_TIMEOUT 10
/* Imported drive-specific functions */
int vanilla_2064_dvd_dump_mem (dvd_drive *dvd, u_int32_t block_off, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf);
int vanilla_2384_dvd_dump_mem (dvd_drive *dvd, u_int32_t block_off, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf);
int hitachi_dvd_dump_mem (dvd_drive *dvd, u_int32_t block_off, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf);
int liteon_dvd_dump_mem (dvd_drive *dvd, u_int32_t block_off, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf);
int renesas_dvd_dump_mem (dvd_drive *dvd, u_int32_t block_off, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf);
/*! \brief A structure that represents a CD/DVD-ROM drive.
*/
struct dvd_drive_s {
/* Device special file */
char *device; //!< The path to the drive (i.e.: /dev/something on Unix, x: on Windows).
/* Data about the drive */
char *vendor; //!< The drive vendor.
char *prod_id; //!< The drive product ID.
char *prod_rev; //!< The drive product revision (Usually firmware version).
char *model_string; //!< The above three strings, joined in a single one.
u_int32_t def_method;
u_int32_t command;
/* Device-dependent internal memory dump function */
/*! The intended area should start where sector data is stored upon a READ command. Here we assume that sectors are
* stored one after the other, as heuristics showed it is the case for the Hitachi MN103-based drives, but this model
* might be changed in the future, if we get support for other drives.
*/
dvd_drive_memdump_func memdump; //!< A pointer to a function that is able to dump the drive's internal memory area.
bool supported; //!< True if the drive is a supported model, false otherwise.
/* File descriptor & stuff used to access drive */
#ifdef WIN32
HANDLE fd; //!< The HANDLE to interact with the drive on Windows.
#else
int fd; //!< The file descriptor to interact with the drive on Unix.
#endif
};
/** \brief Supported MMC commands.
*/
enum mmc_commands_e {
SPC_INQUIRY = 0x12,
MMC_READ_12 = 0xA8,
};
/**
* Initializes a structure representing an MMC command.
* @param mmc A pointer to the MMC command structure.
* @param buf The buffer where results of the MMC command execution provided by the drive should be stored, or NULL if no buffer will be provided.
* @param len The length of the buffer (ignored in case buf is NULL).
* @param sense A pointer to a structure which will hold the SENSE DATA got from the drive after the command has been executed, or NULL.
*/
void dvd_init_command (mmc_command *mmc, u_int8_t *buf, int len, req_sense *sense) {
memset (mmc, 0, sizeof (mmc_command));
if (buf)
memset (buf, 0, len);
mmc -> buffer = buf;
mmc -> buflen = buf ? len : 0;
mmc -> sense = sense;
return;
}
#ifdef WIN32
/* Doc is under the UNIX function */
int dvd_execute_cmd (dvd_drive *dvd, mmc_command *mmc, bool ignore_errors) {
SCSI_PASS_THROUGH_DIRECT *sptd;
unsigned char sptd_sense[sizeof (*sptd) + 18], *sense;
DWORD bytes;
int out;
sptd = (SCSI_PASS_THROUGH_DIRECT *) sptd_sense;
sense = &sptd_sense[sizeof (*sptd)];
memset (sptd, 0, sizeof (sptd_sense));
memcpy (sptd -> Cdb, mmc -> cmd, sizeof (mmc -> cmd));
sptd -> Length = sizeof (SCSI_PASS_THROUGH);
sptd -> CdbLength = 12;
sptd -> SenseInfoLength = 18;
sptd -> DataIn = SCSI_IOCTL_DATA_IN;
sptd -> DataBuffer = mmc -> buffer;
// Quick hack: Windows hates sptd->DataTransferLength = 1, so we set it to 2 and ignore the second byte.
if (mmc -> buflen == 1) // TODO
sptd -> DataTransferLength = 2;
else
sptd -> DataTransferLength = mmc -> buflen;
sptd -> TimeOutValue = MMC_CMD_TIMEOUT;
sptd -> SenseInfoOffset = sizeof (*sptd);
//fprintf (stdout,"mmc->cmd[00] = %d \n",mmc->cmd[00]);
//Set streaming hack
if (mmc->cmd[00]==0xB6) {
sptd -> DataIn = SCSI_IOCTL_DATA_OUT;
sptd -> DataTransferLength = 28;
}
if (!DeviceIoControl (dvd -> fd, IOCTL_SCSI_PASS_THROUGH_DIRECT, sptd, sizeof (*sptd) + 18, sptd, sizeof (*sptd) + 18, &bytes, NULL) && !ignore_errors) {
out = -1; /* Failure */
error ("Execution of MMC command failed: %s", strerror (errno));
// error ("DeviceIOControl() failed with %d\n", GetLastError());
debug ("Command was: ");
hex_and_ascii_print ("", mmc -> cmd, sizeof (mmc -> cmd));
debug ("Sense data: %02X/%02X/%02X\n", sense[2] & 0x0F, sense[12], sense[13]);
} else {
out = 0;
}
if (mmc -> sense) {
mmc -> sense -> sense_key = sense[2];
mmc -> sense -> asc = sense[12];
mmc -> sense -> ascq = sense[13];
}
return (out);
}
#else
/**
* Executes an MMC command.
* @param dvd The DVD drive the command should be exectued on.
* @param mmc The command to be executed.
* @param ignore_errors If set to true, no error will be printed if the command fails.
* @return 0 if the command was executed successfully, < 0 otherwise.
*/
int dvd_execute_cmd (dvd_drive *dvd, mmc_command *mmc, bool ignore_errors) {
int out;
struct cdrom_generic_command cgc;
struct request_sense sense;
#if 0
debug ("Executing MMC command: ");
hex_and_ascii_print ("", mmc -> cmd, sizeof (mmc -> cmd));
#endif
/* Init Linux-format MMC command */
memset (&cgc, 0, sizeof (struct cdrom_generic_command));
memcpy (cgc.cmd, mmc -> cmd, sizeof (mmc -> cmd));
cgc.buffer = (unsigned char *) mmc -> buffer;
cgc.buflen = mmc -> buflen;
cgc.data_direction = CGC_DATA_READ;
cgc.timeout = MMC_CMD_TIMEOUT * 1000; /* Linux uses milliseconds */
cgc.sense = &sense;
if (ioctl (dvd -> fd, CDROM_SEND_PACKET, &cgc) < 0 && !ignore_errors) {
out = -1; /* Failure */
error ("Execution of MMC command failed: %s", strerror (errno));
debug ("Command was:");
hex_and_ascii_print ("", cgc.cmd, sizeof (cgc.cmd));
debug ("Sense data: %02X/%02X/%02X", sense.sense_key, sense.asc, sense.ascq);
} else {
out = 0;
}
if (mmc -> sense) {
mmc -> sense -> sense_key = sense.sense_key;
mmc -> sense -> asc = sense.asc;
mmc -> sense -> ascq = sense.ascq;
}
return (out);
}
#endif
/**
* Sends an INQUIRY command to the drive to retrieve drive identification strings.
* @param dvd The DVD drive the command should be exectued on.
* @return 0 if the command was executed successfully, < 0 otherwise.
*/
static int dvd_get_drive_info (dvd_drive *dvd) {
mmc_command mmc;
int out;
u_int8_t buf[36];
char tmp[36 * 4];
dvd_init_command (&mmc, buf, sizeof (buf), NULL);
mmc.cmd[0] = SPC_INQUIRY;
mmc.cmd[4] = sizeof (buf);
if ((out = dvd_execute_cmd (dvd, &mmc, false)) >= 0) {
my_strndup (dvd -> vendor, buf + 8, 8);
strtrimr (dvd -> vendor);
my_strndup (dvd -> prod_id, buf + 16, 16);
strtrimr (dvd -> prod_id);
my_strndup (dvd -> prod_rev, buf + 32, 4);
strtrimr (dvd -> prod_rev);
snprintf (tmp, sizeof (tmp), "%s/%s/%s", dvd -> vendor, dvd -> prod_id, dvd -> prod_rev);
my_strdup (dvd -> model_string, tmp);
debug ("DVD drive is \"%s\"", dvd -> model_string);
} else {
error ("Cannot identify DVD drive\n");
}
return (out);
}
/**
* Assigns the proper memory dump functions to a dvd_drive object, according to vendor, model and other parameters. Actually this scheme probably needs to
* to be improved, but it is enough for the moment.
* @param dvd The DVD drive the command should be exectued on.
*/
static void dvd_assign_functions (dvd_drive *dvd, u_int32_t command) {
dvd -> def_method = 0;
if (strcmp (dvd -> vendor, "HL-DT-ST") == 0 && (
// strcmp (dvd -> prod_id, "DVDRAM GSA-T10N") == 0 ||
strcmp (dvd -> prod_id, "DVD-ROM GDR8082N") == 0 ||
strcmp (dvd -> prod_id, "DVD-ROM GDR8161B") == 0 ||
strcmp (dvd -> prod_id, "DVD-ROM GDR8162B") == 0 ||
strcmp (dvd -> prod_id, "DVD-ROM GDR8163B") == 0 ||
strcmp (dvd -> prod_id, "DVD-ROM GDR8164B") == 0
)) {
debug ("Hitachi MN103-based DVD drive detected, using Hitachi memory dump command");
dvd -> memdump = &hitachi_dvd_dump_mem;
dvd -> command = 2;
dvd -> supported = true;
dvd -> def_method = 9;
} else if (strcmp (dvd -> vendor, "LITE-ON") == 0 && (
strcmp (dvd ->prod_id, "DVDRW LH-18A1H") == 0 ||
strcmp (dvd ->prod_id, "DVDRW LH-18A1P") == 0 ||
strcmp (dvd ->prod_id, "DVDRW LH-20A1H") == 0 ||
strcmp (dvd ->prod_id, "DVDRW LH-20A1P") == 0
)) {
debug ("Lite-On DVD drive detected, using Lite-On memory dump command");
dvd -> memdump = &liteon_dvd_dump_mem;
dvd -> command = 3;
dvd -> supported = true;
dvd -> def_method = 5;
} else if (strcmp (dvd -> vendor, "TSSTcorp") == 0 && (
strcmp (dvd ->prod_id, "DVD-ROM SH-D162A") == 0 ||
strcmp (dvd ->prod_id, "DVD-ROM SH-D162B") == 0 ||
strcmp (dvd ->prod_id, "DVD-ROM SH-D162C") == 0 ||
strcmp (dvd ->prod_id, "DVD-ROM SH-D162D") == 0
)) {
debug ("Toshiba Samsung DVD drive detected, using vanilla 2384 memory dump command");
dvd -> memdump = &vanilla_2384_dvd_dump_mem;
dvd -> command = 1;
dvd -> supported = true;
dvd -> def_method = 0;
} else if (strcmp (dvd -> vendor, "PLEXTOR") == 0) {
debug ("Plextor DVD drive detected, using vanilla 2064 memory dump command");
dvd -> memdump = &vanilla_2064_dvd_dump_mem;
dvd -> command = 0;
dvd -> supported = true;
dvd -> def_method = 2;
} else {
/* This is an unsupported drive (yet). */
dvd -> memdump = &vanilla_2064_dvd_dump_mem;
dvd -> command = 0;
dvd -> supported = false;
}
if (command!=-1) {
dvd -> command = command;
if (command == 0) dvd -> memdump = &vanilla_2064_dvd_dump_mem;
else if (command == 1) dvd -> memdump = &vanilla_2384_dvd_dump_mem;
else if (command == 2) dvd -> memdump = &hitachi_dvd_dump_mem;
else if (command == 3) dvd -> memdump = &liteon_dvd_dump_mem;
else if (command == 4) dvd -> memdump = &renesas_dvd_dump_mem;
}
//init Reed-Solomon for Lite-On
generate_gf();
gen_poly();
return;
}
/**
* Creates a new structure representing a CD/DVD-ROM drive.
* @param device The CD/DVD-ROM device, in OS-dependent format (i.e.: /dev/something on Unix, x: on Windows).
* @return The newly-created structure, to be used with the other commands, or NULL if the drive could not be initialized.
*/
dvd_drive *dvd_drive_new (char *device, u_int32_t command) {
dvd_drive *dvd;
#ifdef WIN32
HANDLE fd;
char dev[40];
#else
int fd;
#endif
/* Force the dropping of privileges: in our model, privileges are only used to execute memory dump commands, the user
must gain access to the device somehow else (i. e. get added to the "cdrom" group or similar things) */
drop_euid ();
debug ("Trying to open DVD device %s", device);
#ifdef WIN32
sprintf (dev, "\\\\.\\%c:", device[0]);
if ((fd = CreateFile (dev, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) {
error ("Cannot open drive: %d", GetLastError ());
#else
if ((fd = open (device, O_RDONLY | O_NONBLOCK)) < 0) {
perror ("Cannot open drive");
#endif
dvd = NULL;
} else {
debug ("Opened successfully");
drop_euid ();
dvd = (dvd_drive *) malloc (sizeof (dvd_drive));
my_strdup (dvd -> device, device);
dvd -> fd = fd;
dvd_get_drive_info (dvd);
dvd_assign_functions (dvd, command);
}
return (dvd);
}
/**
* Frees resources used by a DVD drive structure and destroys it.
* @param dvd The DVD drive structure to be destroyed.
* @return NULL.
*/
void *dvd_drive_destroy (dvd_drive *dvd) {
if (dvd) {
#ifdef WIN32
CloseHandle (dvd -> fd);
#else
close (dvd -> fd);
#endif
my_free (dvd -> device);
my_free (dvd -> vendor);
my_free (dvd -> prod_id);
my_free (dvd -> prod_rev);
my_free (dvd);
}
return (NULL);
}
/**
* Executes the drive-dependent function to dump the drive sector cache, and returns the dumped data.
* @param dvd The DVD drive the command should be exectued on.
* @param block_off The offset to start dumping, WRT the beginning of the sector cache.
* @param block_len The number of blocks to dump.
* @param block_size The block size to be used for dumping.
* @param buf A buffer where to store the dumped data. Note that this must be able to hold at least block_len * block_size bytes.
* @return 0 if the command was executed successfully, < 0 otherwise.
*/
int dvd_memdump (dvd_drive *dvd, u_int32_t block_off, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf) {
int out;
/* Upgrade privileges and call actual dump functions */
upgrade_euid ();
out = dvd -> memdump (dvd, block_off, block_len, block_size, buf);
drop_euid ();
return (out);
}
/**
* Issues a READ(12) command without bothering to return the results. Uses the FUA (Force Unit Access bit) so that the requested sectors are actually read
* at the beginning of the cache and can be dumped later.
* @param dvd The DVD drive the command should be exectued on.
* @param sector The sector to be read. What will be cached is the 16-sectors block to which the sector belongs.
* @param sense A pointer to a structure which will hold the SENSE DATA got from the drive after the command has been executed.
* @return 0 if the command was executed successfully, < 0 otherwise.
*/
int dvd_read_sector_dummy (dvd_drive *dvd, u_int32_t sector, u_int32_t sectors, req_sense *sense, u_int8_t *extbuf, size_t extbufsize) {
mmc_command mmc;
int out;
u_int8_t intbuf[64 * 1024], *buf;
size_t bufsize;
/* We need some buffer, be it provided externally or not */
if (extbuf) {
buf = extbuf;
bufsize = extbufsize;
} else {
buf = intbuf;
bufsize = sizeof (intbuf);
}
dvd_init_command (&mmc, buf, bufsize, sense);
mmc.cmd[0] = MMC_READ_12;
mmc.cmd[1] = 0x08; /* FUA bit set */
mmc.cmd[2] = (u_int8_t) ((sector & 0xFF000000) >> 24); /* LBA from MSB to LSB */
mmc.cmd[3] = (u_int8_t) ((sector & 0x00FF0000) >> 16);
mmc.cmd[4] = (u_int8_t) ((sector & 0x0000FF00) >> 8);
mmc.cmd[5] = (u_int8_t) (sector & 0x000000FF);
mmc.cmd[6] = (u_int8_t) ((sectors & 0xFF000000) >> 24); /* Size from MSB to LSB */
mmc.cmd[7] = (u_int8_t) ((sectors & 0x00FF0000) >> 16);
mmc.cmd[8] = (u_int8_t) ((sectors & 0x0000FF00) >> 8);
mmc.cmd[9] = (u_int8_t) (sectors & 0x000000FF);
out = dvd_execute_cmd (dvd, &mmc, true); /* Ignore errors! */
return (out);
}
/**
* Issues a READ(12) command using the STREAMING bit, which causes the requested 16-sector block to be read into memory,
* together with the following four. This way we will be able to dump 5 sector with a single READ request.
*
* Note the strange need for a big buffer even though we must only pass 0x10 as the transfer length, otherwise the drive will hang (!?).
* @param dvd The DVD drive the command should be exectued on.
* @param sector The sector to be read. What will be cached is the 16-sectors block to which the sector belongs, and the following 4 blocks.
* @param sense A pointer to a structure which will hold the SENSE DATA got from the drive after the command has been executed.
* @param extbuf A buffer where to store the read data, or NULL.
* @param extbufsize The size of the buffer.
* @return
*/
int dvd_read_sector_streaming (dvd_drive *dvd, u_int32_t sector, req_sense *sense, u_int8_t *extbuf, size_t extbufsize) {
mmc_command mmc;
int out;
u_int8_t intbuf[2048 * 16], *buf;
size_t bufsize;
/* We need some buffer, be it provided externally or not */
if (extbuf) {
buf = extbuf;
bufsize = extbufsize;
} else {
buf = intbuf;
bufsize = sizeof (intbuf);
}
dvd_init_command (&mmc, buf, bufsize, sense);
mmc.cmd[0] = MMC_READ_12;
mmc.cmd[2] = (u_int8_t) ((sector & 0xFF000000) >> 24); /* LBA from MSB to LSB */
mmc.cmd[3] = (u_int8_t) ((sector & 0x00FF0000) >> 16);
mmc.cmd[4] = (u_int8_t) ((sector & 0x0000FF00) >> 8);
mmc.cmd[5] = (u_int8_t) (sector & 0x000000FF);
mmc.cmd[6] = 0;
mmc.cmd[7] = 0;
mmc.cmd[8] = 0;
mmc.cmd[9] = 0x10;
mmc.cmd[10] = 0x80; /* STREAMING bit set */
out = dvd_execute_cmd (dvd, &mmc, true); /* Ignore errors! */
return (out);
}
int dvd_read_streaming (dvd_drive *dvd, u_int32_t sector, u_int32_t sectors, req_sense *sense, u_int8_t *extbuf, size_t extbufsize) {
mmc_command mmc;
int out;
u_int8_t intbuf[64 * 1024], *buf;
size_t bufsize;
/* We need some buffer, be it provided externally or not */
if (extbuf) {
buf = extbuf;
bufsize = extbufsize;
} else {
buf = intbuf;
bufsize = sizeof (intbuf);
}
dvd_init_command (&mmc, buf, bufsize, sense);
mmc.cmd[0] = MMC_READ_12;
mmc.cmd[2] = (u_int8_t) ((sector & 0xFF000000) >> 24); /* LBA from MSB to LSB */
mmc.cmd[3] = (u_int8_t) ((sector & 0x00FF0000) >> 16);
mmc.cmd[4] = (u_int8_t) ((sector & 0x0000FF00) >> 8);
mmc.cmd[5] = (u_int8_t) (sector & 0x000000FF);
mmc.cmd[6] = (u_int8_t) ((sectors & 0xFF000000) >> 24); /* Size from MSB to LSB */
mmc.cmd[7] = (u_int8_t) ((sectors & 0x00FF0000) >> 16);
mmc.cmd[8] = (u_int8_t) ((sectors & 0x0000FF00) >> 8);
mmc.cmd[9] = (u_int8_t) (sectors & 0x000000FF);
mmc.cmd[10] = 0x80; /* STREAMING bit set */
out = dvd_execute_cmd (dvd, &mmc, true); /* Ignore errors! */
return (out);
}
int dvd_flush_cache_READ12 (dvd_drive *dvd, u_int32_t sector, req_sense *sense) {
mmc_command mmc;
int out;
u_int8_t intbuf[64], *buf;
size_t bufsize;
buf = intbuf;
bufsize = 0;
dvd_init_command (&mmc, buf, bufsize, sense);
mmc.cmd[0] = MMC_READ_12;
mmc.cmd[1] = 0x08;
mmc.cmd[2] = (u_int8_t) ((sector & 0xFF000000) >> 24); /* LBA from MSB to LSB */
mmc.cmd[3] = (u_int8_t) ((sector & 0x00FF0000) >> 16);
mmc.cmd[4] = (u_int8_t) ((sector & 0x0000FF00) >> 8);
mmc.cmd[5] = (u_int8_t) (sector & 0x000000FF);
out = dvd_execute_cmd (dvd, &mmc, true);
return (out);
}
int dvd_stop_unit (dvd_drive *dvd, bool start, req_sense *sense) {
mmc_command mmc;
int out;
u_int8_t intbuf[64], *buf;
size_t bufsize;
buf = intbuf;
bufsize = 0;
dvd_init_command (&mmc, buf, bufsize, sense);
mmc.cmd[0] = 0x1B;
if (start) mmc.cmd[4] = 1;
else mmc.cmd[4] = 0;
out = dvd_execute_cmd (dvd, &mmc, true);
return (out);
}
int dvd_set_speed (dvd_drive *dvd, u_int32_t speed, req_sense *sense) {
mmc_command mmc;
int out;
u_int8_t intbuf[64], *buf;
size_t bufsize;
buf = intbuf;
bufsize = 0;
dvd_init_command (&mmc, buf, bufsize, sense);
mmc.cmd[0] = 0xBB;
mmc.cmd[2] = (u_int8_t) ((speed & 0x0000FF00) >> 8);
mmc.cmd[3] = (u_int8_t) (speed & 0x000000FF);
out = dvd_execute_cmd (dvd, &mmc, true);
return (out);
}
int dvd_get_size (dvd_drive *dvd, u_int32_t *size, req_sense *sense) {
mmc_command mmc;
int out;
u_int8_t intbuf[64], *buf;
size_t bufsize;
buf = intbuf;
bufsize = 0x22;
dvd_init_command (&mmc, buf, bufsize, sense);
mmc.cmd[0] = 0x52;
mmc.cmd[1] = 0x01;
mmc.cmd[5] = 0x01;
mmc.cmd[8] = 0x22;
out = dvd_execute_cmd (dvd, &mmc, true);
*(size)=*(size) << 8 | intbuf[0x18];
*(size)=*(size) << 8 | intbuf[0x19];
*(size)=*(size) << 8 | intbuf[0x1a];
*(size)=*(size) << 8 | intbuf[0x1b];
return (out);
}
int dvd_get_layerbreak (dvd_drive *dvd, u_int32_t *layerbreak, req_sense *sense) {
mmc_command mmc;
int out;
u_int8_t intbuf[2052], *buf;
size_t bufsize;
buf = intbuf;
bufsize = 2052;
dvd_init_command (&mmc, buf, bufsize, sense);
mmc.cmd[0] = 0xad;
mmc.cmd[8] = 0x08;
mmc.cmd[9] = 0x04;
out = dvd_execute_cmd (dvd, &mmc, true);
*(layerbreak)=*(layerbreak) << 8;
*(layerbreak)=*(layerbreak) << 8 | intbuf[0x11];
*(layerbreak)=*(layerbreak) << 8 | intbuf[0x12];
*(layerbreak)=*(layerbreak) << 8 | intbuf[0x13];
if (*(layerbreak) > 0) *(layerbreak)=*(layerbreak) - 0x30000 + 1;
return (out);
}
int dvd_set_streaming (dvd_drive *dvd, u_int32_t speed, req_sense *sense) {
/*
DVD Decrypter->
DeviceIoControl : \Device\CdRom5
Command : IOCTL_SCSI_PASS_THROUGH_DIRECT
Length : 44 (0x002C)
ScsiStatus : 0
PathId : 0
TargedId : 0
Lun : 0
CdbLength : 12 (0x0C)
SenseInfoLength : 24 (0x18)
DataTransferLength : 28 (0x0000001C)
DataIn : 0
TimeOutValue : 5000
CDB:
00000000 B6 00 00 00 00 00 00 00 00 00 1C 00 ...........
Data Sent:
00000000 00 00 00 00 00 00 00 00 00 00 00 00 FF FF FF FF ............____
00000010 00 00 03 E8 FF FF FF FF 00 00 03 E8 ...è____...è
*/
mmc_command mmc;
int out;
u_int8_t inbuf[28], *buf;
size_t bufsize;
buf = inbuf;
bufsize = 28;
dvd_init_command (&mmc, buf, bufsize, sense);
mmc.cmd[00] = 0xB6;
mmc.cmd[10] = 28;
*(buf+ 0)=0;//2
*(buf+ 1)=0;
*(buf+ 2)=0;
*(buf+ 3)=0;
*(buf+ 4)=0; //MSB
*(buf+ 5)=0; //
*(buf+ 6)=0; //
*(buf+ 7)=0; //LSB
*(buf+ 8)=0xff; //MSB
*(buf+ 9)=0xff; //
*(buf+10)=0xff; //
*(buf+11)=0xff; //LSB
*(buf+12)=(u_int8_t) ((speed & 0xFF000000) >> 24);
*(buf+13)=(u_int8_t) ((speed & 0x00FF0000) >> 16);
*(buf+14)=(u_int8_t) ((speed & 0x0000FF00) >> 8);
*(buf+15)=(u_int8_t) (speed & 0x000000FF);
*(buf+16)=(u_int8_t) ((1000 & 0xFF000000) >> 24);
*(buf+17)=(u_int8_t) ((1000 & 0x00FF0000) >> 16);
*(buf+18)=(u_int8_t) ((1000 & 0x0000FF00) >> 8);
*(buf+19)=(u_int8_t) (1000 & 0x000000FF);
*(buf+20)=(u_int8_t) ((speed & 0xFF000000) >> 24);
*(buf+21)=(u_int8_t) ((speed & 0x00FF0000) >> 16);
*(buf+22)=(u_int8_t) ((speed & 0x0000FF00) >> 8);
*(buf+23)=(u_int8_t) (speed & 0x000000FF);
*(buf+24)=(u_int8_t) ((1000 & 0xFF000000) >> 24);
*(buf+25)=(u_int8_t) ((1000 & 0x00FF0000) >> 16);
*(buf+26)=(u_int8_t) ((1000 & 0x0000FF00) >> 8);
*(buf+27)=(u_int8_t) (1000 & 0x000000FF);
out = dvd_execute_cmd (dvd, &mmc, true);
return (out);
}
char *dvd_get_vendor (dvd_drive *dvd) {
return (dvd -> vendor);
}
char *dvd_get_product_id (dvd_drive *dvd) {
return (dvd -> prod_id);
}
char *dvd_get_product_revision (dvd_drive *dvd) {
return (dvd -> prod_rev);
}
char *dvd_get_model_string (dvd_drive *dvd) {
return (dvd -> model_string);
}
bool dvd_get_support_status (dvd_drive *dvd) {
return (dvd -> supported);
}
u_int32_t dvd_get_def_method (dvd_drive *dvd){
return (dvd -> def_method);
}
u_int32_t dvd_get_command (dvd_drive *dvd){
return (dvd -> command);
}

73
libfriidump/dvd_drive.h Normal file
View file

@ -0,0 +1,73 @@
/***************************************************************************
* Copyright (C) 2007 by Arep *
* Support is provided through the forums at *
* http://wii.console-tribe.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef DVD_DRIVE_H_INCLUDED
#define DVD_DRIVE_H_INCLUDED
#include "misc.h"
#include <sys/types.h>
typedef struct dvd_drive_s dvd_drive;
typedef struct {
int sense_key;
int asc;
int ascq;
} req_sense;
typedef struct {
u_int8_t cmd[12];
req_sense *sense;
u_int8_t *buffer;
int buflen;
} mmc_command;
/* Functions */
dvd_drive *dvd_drive_new (char *device, u_int32_t command);
void *dvd_drive_destroy (dvd_drive *d);
int dvd_read_sector_dummy (dvd_drive *dvd, u_int32_t sector, u_int32_t sectors, req_sense *sense, u_int8_t *extbuf, size_t extbufsize);
int dvd_read_sector_streaming (dvd_drive *dvd, u_int32_t sector, req_sense *sense, u_int8_t *extbuf, size_t extbufsize);
int dvd_read_streaming (dvd_drive *dvd, u_int32_t sector, u_int32_t sectors, req_sense *sense, u_int8_t *extbuf, size_t extbufsize);
int dvd_flush_cache_READ12 (dvd_drive *dvd, u_int32_t sector, req_sense *sense);
int dvd_stop_unit (dvd_drive *dvd, bool start, req_sense *sense);
int dvd_set_speed (dvd_drive *dvd, u_int32_t speed, req_sense *sense);
int dvd_get_size (dvd_drive *dvd, u_int32_t *size, req_sense *sense);
int dvd_get_layerbreak (dvd_drive *dvd, u_int32_t *layerbreak, req_sense *sense);
int dvd_set_streaming (dvd_drive *dvd, u_int32_t speed, req_sense *sense);
int dvd_memdump (dvd_drive *dvd, u_int32_t block_off, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf);
char *dvd_get_vendor (dvd_drive *dvd);
char *dvd_get_product_id (dvd_drive *dvd);
char *dvd_get_product_revision (dvd_drive *dvd);
char *dvd_get_model_string (dvd_drive *dvd);
bool dvd_get_support_status (dvd_drive *dvd);
u_int32_t dvd_get_def_method (dvd_drive *dvd);
u_int32_t dvd_get_command (dvd_drive *dvd);
/* The following are exported for use by drive-specific functions */
typedef int (*dvd_drive_memdump_func) (dvd_drive *dvd, u_int32_t block_off, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf);
void dvd_init_command (mmc_command *mmc, u_int8_t *buf, int len, req_sense *sense);
int dvd_execute_cmd (dvd_drive *dvd, mmc_command *mmc, bool ignore_errors);
#endif

109
libfriidump/ecma-267.c Normal file
View file

@ -0,0 +1,109 @@
/*
unscrambler 0.4: unscramble not standard IVs scrambled DVDs thru
bruteforce, intended for Gamecube/WII Optical Disks.
Copyright (C) 2006 Victor Muñoz (xt5@ingenieria-inversa.cl)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "ecma-267.h"
/* EDC stuff */
unsigned int edc_table[256] = {
0x00000000, 0x80000011, 0x80000033, 0x00000022, 0x80000077, 0x00000066, 0x00000044, 0x80000055,
0x800000FF, 0x000000EE, 0x000000CC, 0x800000DD, 0x00000088, 0x80000099, 0x800000BB, 0x000000AA,
0x800001EF, 0x000001FE, 0x000001DC, 0x800001CD, 0x00000198, 0x80000189, 0x800001AB, 0x000001BA,
0x00000110, 0x80000101, 0x80000123, 0x00000132, 0x80000167, 0x00000176, 0x00000154, 0x80000145,
0x800003CF, 0x000003DE, 0x000003FC, 0x800003ED, 0x000003B8, 0x800003A9, 0x8000038B, 0x0000039A,
0x00000330, 0x80000321, 0x80000303, 0x00000312, 0x80000347, 0x00000356, 0x00000374, 0x80000365,
0x00000220, 0x80000231, 0x80000213, 0x00000202, 0x80000257, 0x00000246, 0x00000264, 0x80000275,
0x800002DF, 0x000002CE, 0x000002EC, 0x800002FD, 0x000002A8, 0x800002B9, 0x8000029B, 0x0000028A,
0x8000078F, 0x0000079E, 0x000007BC, 0x800007AD, 0x000007F8, 0x800007E9, 0x800007CB, 0x000007DA,
0x00000770, 0x80000761, 0x80000743, 0x00000752, 0x80000707, 0x00000716, 0x00000734, 0x80000725,
0x00000660, 0x80000671, 0x80000653, 0x00000642, 0x80000617, 0x00000606, 0x00000624, 0x80000635,
0x8000069F, 0x0000068E, 0x000006AC, 0x800006BD, 0x000006E8, 0x800006F9, 0x800006DB, 0x000006CA,
0x00000440, 0x80000451, 0x80000473, 0x00000462, 0x80000437, 0x00000426, 0x00000404, 0x80000415,
0x800004BF, 0x000004AE, 0x0000048C, 0x8000049D, 0x000004C8, 0x800004D9, 0x800004FB, 0x000004EA,
0x800005AF, 0x000005BE, 0x0000059C, 0x8000058D, 0x000005D8, 0x800005C9, 0x800005EB, 0x000005FA,
0x00000550, 0x80000541, 0x80000563, 0x00000572, 0x80000527, 0x00000536, 0x00000514, 0x80000505,
0x80000F0F, 0x00000F1E, 0x00000F3C, 0x80000F2D, 0x00000F78, 0x80000F69, 0x80000F4B, 0x00000F5A,
0x00000FF0, 0x80000FE1, 0x80000FC3, 0x00000FD2, 0x80000F87, 0x00000F96, 0x00000FB4, 0x80000FA5,
0x00000EE0, 0x80000EF1, 0x80000ED3, 0x00000EC2, 0x80000E97, 0x00000E86, 0x00000EA4, 0x80000EB5,
0x80000E1F, 0x00000E0E, 0x00000E2C, 0x80000E3D, 0x00000E68, 0x80000E79, 0x80000E5B, 0x00000E4A,
0x00000CC0, 0x80000CD1, 0x80000CF3, 0x00000CE2, 0x80000CB7, 0x00000CA6, 0x00000C84, 0x80000C95,
0x80000C3F, 0x00000C2E, 0x00000C0C, 0x80000C1D, 0x00000C48, 0x80000C59, 0x80000C7B, 0x00000C6A,
0x80000D2F, 0x00000D3E, 0x00000D1C, 0x80000D0D, 0x00000D58, 0x80000D49, 0x80000D6B, 0x00000D7A,
0x00000DD0, 0x80000DC1, 0x80000DE3, 0x00000DF2, 0x80000DA7, 0x00000DB6, 0x00000D94, 0x80000D85,
0x00000880, 0x80000891, 0x800008B3, 0x000008A2, 0x800008F7, 0x000008E6, 0x000008C4, 0x800008D5,
0x8000087F, 0x0000086E, 0x0000084C, 0x8000085D, 0x00000808, 0x80000819, 0x8000083B, 0x0000082A,
0x8000096F, 0x0000097E, 0x0000095C, 0x8000094D, 0x00000918, 0x80000909, 0x8000092B, 0x0000093A,
0x00000990, 0x80000981, 0x800009A3, 0x000009B2, 0x800009E7, 0x000009F6, 0x000009D4, 0x800009C5,
0x80000B4F, 0x00000B5E, 0x00000B7C, 0x80000B6D, 0x00000B38, 0x80000B29, 0x80000B0B, 0x00000B1A,
0x00000BB0, 0x80000BA1, 0x80000B83, 0x00000B92, 0x80000BC7, 0x00000BD6, 0x00000BF4, 0x80000BE5,
0x00000AA0, 0x80000AB1, 0x80000A93, 0x00000A82, 0x80000AD7, 0x00000AC6, 0x00000AE4, 0x80000AF5,
0x80000A5F, 0x00000A4E, 0x00000A6C, 0x80000A7D, 0x00000A28, 0x80000A39, 0x80000A1B, 0x00000A0AL
};
u32 edc_calc(u32 edc, u8 *ptr, u32 len) {
while (len--) edc=edc_table[((edc>>24)^*ptr++)&0xFF]^(edc<<8);
return edc;
}
/* end of EDC stuff */
/* LFSR stuff */
u16 ecma267_ivs[]= {
0x0001, 0x5500, 0x0002, 0x2A00,
0x0004, 0x5400, 0x0008, 0x2800,
0x0010, 0x5000, 0x0020, 0x2001,
0x0040, 0x4002, 0x0080, 0x0005
};
unsigned short LFSR;
void LFSR_ecma_init(int iv) {
LFSR=ecma267_ivs[iv];
}
void LFSR_init(u16 seed) {
LFSR=seed;
}
int LFSR_tick() {
int ret;
int n;
ret=LFSR>>14;
n=ret^((LFSR>>10)&1);
LFSR=((LFSR<<1)|n)&0x7FFF;
return ret;
}
unsigned char LFSR_byte() {
u8 ret;
int i;
ret=0;
for(i=0; i<8; i++) ret=(ret<<1)|LFSR_tick();
return ret;
}
/* end of LFSR stuff */

47
libfriidump/ecma-267.h Normal file
View file

@ -0,0 +1,47 @@
/*
unscrambler 0.4: unscramble not standard IVs scrambled DVDs thru
bruteforce, intended for Gamecube/WII Optical Disks.
Copyright (C) 2006 Victor Muñoz (xt5@ingenieria-inversa.cl)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
typedef unsigned int u32;
typedef int s32;
typedef unsigned short u16;
typedef short s16;
typedef unsigned char u8;
typedef char s8;
/* EDC stuff */
u32 edc_calc(u32 edc, u8 *ptr, u32 len);
/* end of EDC stuff */
/* LFSR stuff */
void LFSR_ecma_init(int iv);
void LFSR_init(u16 seed);
int LFSR_tick();
u8 LFSR_byte();
/* end of LFSR stuff */

147
libfriidump/hitachi.c Normal file
View file

@ -0,0 +1,147 @@
/***************************************************************************
* Copyright (C) 2007 by Arep *
* Support is provided through the forums at *
* http://wii.console-tribe.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
/*! \file
* \brief Memory dump functions specific to drives based on the Hitachi MN103 chip.
*
* Drives which are supported by this set of functions are, for instance, the LG GDR-8161B, GDR-8162B, GDR-8163B and GDR-8164B. All testing has been performed
* with the latter model, so I'm not really sure about the others, but they should work ;). Please report any issues and more compatible drives!
*
* This file contains code derived from the work of Kevin East (SeventhSon), kev@kev.nu, http://www.kev.nu/360/ , which, in turn, derives from work by
* a lot of other people. See his page for full details.
*/
#include <stdio.h>
#include <sys/types.h>
#include "misc.h"
#include "dvd_drive.h"
/*! \brief Memory offset at which the drive cache memory is mapped.
*
* During READ, sector data is cached beginning at this address.
*/
#define HITACHI_MEM_BASE 0x80000000
/**
* Dumps a single block (with arbitrary size) of the address space of the MN103 microcontroller within the Hitachi-LG Xbox 360 DVD drive and similar drives.
* This function is derived from the work of Kevin East (SeventhSon), kev@kev.nu, http://www.kev.nu/360/.
* @param dvd The DVD drive the command should be exectued on.
* @param offset The absolute memory offset to start dumping.
* @param block_size The block size for the dump.
* @param buf Where to place the dumped data. This must have been setup by the caller to store up to block_size bytes.
* @return < 0 if an error occurred, 0 otherwise.
*/
int hitachi_dvd_dump_memblock (dvd_drive *dvd, u_int32_t offset, u_int32_t block_size, u_int8_t *buf) {
mmc_command mmc;
int out;
if (!buf) {
error ("NULL buffer");
out = -1;
} else if (!block_size || block_size > 65535) {
error ("invalid block_size (valid: 1 - 65535)");
out = -2;
} else {
dvd_init_command (&mmc, buf, block_size, NULL);
mmc.cmd[0] = 0xE7; // vendor specific command (discovered by DaveX)
mmc.cmd[1] = 0x48; // H
mmc.cmd[2] = 0x49; // I
mmc.cmd[3] = 0x54; // T
mmc.cmd[4] = 0x01; // read MCU memory sub-command
mmc.cmd[6] = (unsigned char) ((offset & 0xFF000000) >> 24); // address MSB
mmc.cmd[7] = (unsigned char) ((offset & 0x00FF0000) >> 16); // address
mmc.cmd[8] = (unsigned char) ((offset & 0x0000FF00) >> 8); // address
mmc.cmd[9] = (unsigned char) (offset & 0x000000FF); // address LSB
mmc.cmd[10] = (unsigned char) ((block_size & 0xFF00) >> 8); // length MSB
mmc.cmd[11] = (unsigned char) (block_size & 0x00FF); // length LSB
out = dvd_execute_cmd (dvd, &mmc, false);
}
return (out);
}
/**
* Dumps a given portion of the address space of the MN103 microcontroller within the Hitachi-LG Xbox 360 DVD drive.
* WARNING: it can take a while to dump a lot of data.
* @param dvd The DVD drive the command should be exectued on.
* @param offset The absolute memory offset to start dumping.
* @param block_len The number of blocks to dump.
* @param block_size The block size for the dump.
* @param buf Where to place the dumped data. This must have been setup by the caller to store up to block_size bytes.
* @return < 0 if an error occurred, 0 otherwise.
*/
int hitachi_dvd_dump_mem_generic (dvd_drive *dvd, u_int32_t offset, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf) {
u_int32_t i;
int r, out;
if (!buf) {
error ("NULL buffer");
out = -1;
} else {
r = -10;
for (i = 0; i < block_len; i++) {
if ((r = hitachi_dvd_dump_memblock (dvd, offset + i * block_size, block_size, buf + i * block_size)) < 0) {
error ("hitachi_dvd_read_block() failed with %d", r);
break;
}
}
out = r;
}
return (out);
}
/**
* Dumps a given portion of the address space of the MN103 microcontroller within the Hitachi-LG Xbox 360 DVD drive, starting at the offset at which
* sector data are cached.
* WARNING: it can take a while to dump a lot of data.
* @param dvd The DVD drive the command should be exectued on.
* @param offset The memory offset to start dumping, relative to the cache start offset.
* @param block_len The number of blocks to dump.
* @param block_size The block size for the dump.
* @param buf Where to place the dumped data. This must have been setup by the caller to store up to block_size bytes.
* @return < 0 if an error occurred, 0 otherwise.
*/
int hitachi_dvd_dump_mem (dvd_drive *dvd, u_int32_t offset, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf) {
u_int32_t i;
int r, out;
if (!buf) {
error ("NULL buffer");
out = -1;
} else {
r = -10;
for (i = 0; i < block_len; i++) {
if ((r = hitachi_dvd_dump_memblock (dvd, HITACHI_MEM_BASE + offset + i * block_size, block_size, buf + i * block_size)) < 0) {
error ("hitachi_dvd_read_block() failed with %d", r);
break;
}
}
out = r;
}
return (out);
}

154
libfriidump/lite-on.c Normal file
View file

@ -0,0 +1,154 @@
/***************************************************************************
* Copyright (C) 2007 by Arep *
* Support is provided through the forums at *
* http://wii.console-tribe.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "rs.h"
#include <stdio.h>
#include <sys/types.h>
#include "misc.h"
#include "dvd_drive.h"
/**
* Command found in Lite-On LH-18A1H; verified with LH-18A1P and LH-20A1H
* Expected to work with: DH*, DW*, LH*, SH* series
* Possibly would work with other Mediatek based drives:
* Samsung SE*, SH* series
* Some Dell drives
* Some Sony drives
* Asus DRW-1814* (DRW* series?)
*/
//u_int8_t tmp[64*1024];
/**
* @param dvd The DVD drive the command should be exectued on.
* @param offset The absolute memory offset to start dumping.
* @param block_size The block size for the dump.
* @param buf Where to place the dumped data. This must have been setup by the caller to store up to block_size bytes.
* @return < 0 if an error occurred, 0 otherwise.
*/
int liteon_dvd_dump_memblock (dvd_drive *dvd, u_int32_t offset, u_int32_t block_size, u_int8_t *buf) {
mmc_command mmc;
int out;
u_int32_t raw_block_size;
u_int32_t raw_offset;
u_int32_t src_offset;
u_int32_t dst_offset;
u_int32_t row_nr;
u_int32_t sec_nr;
u_int32_t sec_cnt;
u_int32_t first_sec_nr;
u_int8_t tmp[64*1024];
//u_int8_t *tmp;
raw_block_size = (block_size / 2064) * 0x950;
raw_offset = (offset / 2064) * 0x950;
if (!buf) {
error ("NULL buffer");
out = -1;
} else if (!block_size || raw_block_size >= 65535) {
error ("invalid raw_block_size (valid: 1 - 65534)");
error ("raw_block_size = (block_size / 2064) * 2384");
out = -2;
} else {
//tmp = malloc(64*1024);
dvd_init_command (&mmc, tmp, raw_block_size, NULL); //64*1024
mmc.cmd[0] = 0x3C; // READ BUFFER
mmc.cmd[1] = 0x01; // Vendor specific - sole parameter supported by Lite-On
mmc.cmd[2] = 0x01; // == 0x02; 0xE2 = EEPROM; 0xF1 = KEYPARA;
mmc.cmd[3] = (unsigned char) ((raw_offset & 0x00FF0000) >> 16);// address MSB
mmc.cmd[4] = (unsigned char) ((raw_offset & 0x0000FF00) >> 8); // address
mmc.cmd[5] = (unsigned char) ( raw_offset & 0x000000FF); // address LSB
mmc.cmd[6] = (unsigned char) ((raw_block_size & 0x00FF0000) >> 16); // length MSB
mmc.cmd[7] = (unsigned char) ((raw_block_size & 0x0000FF00) >> 8); // length
mmc.cmd[8] = (unsigned char) ( raw_block_size & 0x000000FF); // length LSB
out = dvd_execute_cmd (dvd, &mmc, false);
src_offset = 0;
dst_offset = 0;
first_sec_nr = 0x55555555;
sec_cnt = 0;
while (src_offset < raw_block_size) {
sec_nr=(*(tmp+src_offset+1)<<16)+(*(tmp+src_offset+2)<<8)+(*(tmp+src_offset+3));
//fprintf (stdout,"sec_nr: %x\n", sec_nr);
if (first_sec_nr==0x55555555) {
first_sec_nr=sec_nr;
rs_decode(tmp+src_offset, 0, 0);
}
else
if (sec_nr==first_sec_nr+sec_cnt) {
rs_decode(tmp+src_offset, 0, 0); //sector seq = ok
}
else { //sector seq broken -> corrupt
error ("sector sequence broken");
out = -3;
*(tmp+src_offset+0)=0xff;
*(tmp+src_offset+1)=0xff;
*(tmp+src_offset+2)=0xff;
*(tmp+src_offset+3)=0xff;
break;
}
for (row_nr=0; row_nr<12; row_nr++) {
memcpy(buf+dst_offset, tmp+src_offset, 172);
dst_offset += 172;
src_offset += 182;
}
src_offset += 200;
sec_cnt += 1;
}
//free(tmp);
}
return (out);
}
/**
* WARNING: it can take a while to dump a lot of data.
* @param dvd The DVD drive the command should be exectued on.
* @param offset The memory offset to start dumping, relative to the cache start offset.
* @param block_len The number of blocks to dump.
* @param block_size The block size for the dump.
* @param buf Where to place the dumped data. This must have been setup by the caller to store up to block_size bytes.
* @return < 0 if an error occurred, 0 otherwise.
*/
int liteon_dvd_dump_mem (dvd_drive *dvd, u_int32_t offset, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf) {
u_int32_t i;
int r, out;
if (!buf) {
error ("NULL buffer");
out = -1;
} else {
r = -10;
for (i = 0; i < block_len; i++) {
if ((r = liteon_dvd_dump_memblock (dvd, offset + i * block_size, block_size, buf + i * block_size)) < 0) {
error ("liteon_dvd_dump_memblock() failed with %d", r);
break;
}
}
out = r;
}
return (out);
}

314
libfriidump/misc.c Normal file
View file

@ -0,0 +1,314 @@
/***************************************************************************
* Copyright (C) 2007 by Arep *
* Support is provided through the forums at *
* http://wii.console-tribe.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "misc.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
//#include <sys/time.h>
#include <time.h>
/*** LOGGING STUFF ***/
/* Uses code from the printf man page */
static int my_vasprintf (char **dst, const char *fmt, va_list ap) {
char *p;
int n, size;
bool done;
va_list ap2;
/* Guess we need no more than 100 bytes. */
size = 100;
if ((p = (char *) malloc (size)) != NULL) {
do {
done = false;
va_copy (ap2, ap);
n = vsnprintf (p, size, fmt, ap2);
va_end (ap2);
/* If that worked, return the string. */
if (n > -1 && n < size)
done = true;
else {
/* Else try again with more space. */
if (n > -1) /* glibc 2.1 */
size = n + 1; /* precisely what is needed */
else /* glibc 2.0 */
size *= 2; /* twice the old size */
if ((p = (char *) realloc (p, size)) == NULL)
done = true;
}
} while (!done);
}
/* Return -1 if memory allocation failed */
if (!(*dst = p))
n = -1;
return (n);
}
/* Appends a print-like string to the log file, with respect to the verbosity setting */
void _logprintf (int level, char tag[], char format[], ...) {
static bool last_nocr = false;
char *buffer, t[50];
va_list ap;
struct timeval now;
time_t nowtt;
struct tm nowtm;
va_start (ap, format);
my_vasprintf (&buffer, format, ap);
va_end (ap);
/* Start of line, including time and tag */
if (!last_nocr) {
gettimeofday (&now, NULL);
nowtt = (time_t) now.tv_sec;
if (localtime_r (&nowtt, &nowtm))
strftime (t, 50, "%H:%M:%S", &nowtm);
if (tag)
fprintf (stderr, "[%s/%s] ", t, tag);
else
fprintf (stderr, "[%s] ", t);
/* Debug level tag */
if (level & LOG_WARNING)
fprintf (stderr, "WARNING: ");
else if (level & LOG_ERROR)
fprintf (stderr, "ERROR: ");
#ifdef DEBUG
else if (level & LOG_DEBUG)
fprintf (stderr, "DEBUG: ");
#endif
}
/* Actual message */
fprintf (stderr, "%s%s", buffer, level & LOG_NOCR ? "" : "\n");
fflush (stderr);
free (buffer);
if (level & LOG_NOCR)
last_nocr = true;
else
last_nocr = false;
return;
}
/******/
/***************** TAKEN FROM TCPDUMP ****************/
#define ASCII_LINELENGTH 300
#define HEXDUMP_BYTES_PER_LINE 16
#define HEXDUMP_SHORTS_PER_LINE (HEXDUMP_BYTES_PER_LINE / 2)
#define HEXDUMP_HEXSTUFF_PER_SHORT 5 /* 4 hex digits and a space */
#define HEXDUMP_HEXSTUFF_PER_LINE (HEXDUMP_HEXSTUFF_PER_SHORT * HEXDUMP_SHORTS_PER_LINE)
void hex_and_ascii_print_with_offset (const char *ident, register const u_int8_t *cp,
register u_int16_t length, register u_int16_t oset) {
register u_int16_t i;
register int s1, s2;
register int nshorts;
char hexstuff[HEXDUMP_SHORTS_PER_LINE*HEXDUMP_HEXSTUFF_PER_SHORT+1], *hsp;
char asciistuff[ASCII_LINELENGTH+1], *asp;
nshorts = length / sizeof(unsigned short);
i = 0;
hsp = hexstuff;
asp = asciistuff;
while (--nshorts >= 0) {
s1 = *cp++;
s2 = *cp++;
(void)snprintf(hsp, sizeof(hexstuff) - (hsp - hexstuff),
" %02x%02x", s1, s2);
hsp += HEXDUMP_HEXSTUFF_PER_SHORT;
*(asp++) = (isgraph(s1) ? s1 : '.');
*(asp++) = (isgraph(s2) ? s2 : '.');
i++;
if (i >= HEXDUMP_SHORTS_PER_LINE) {
*hsp = *asp = '\0';
(void)printf("%s0x%04x: %-*s %s",
ident, oset, HEXDUMP_HEXSTUFF_PER_LINE,
hexstuff, asciistuff);
i = 0;
hsp = hexstuff;
asp = asciistuff;
oset += HEXDUMP_BYTES_PER_LINE;
}
}
if (length & 1) {
s1 = *cp++;
(void)snprintf(hsp, sizeof(hexstuff) - (hsp - hexstuff),
" %02x", s1);
hsp += 3;
*(asp++) = (isgraph(s1) ? s1 : '.');
++i;
}
if (i > 0) {
*hsp = *asp = '\0';
debug ("%s0x%04x: %-*s %s",
ident, oset, HEXDUMP_HEXSTUFF_PER_LINE,
hexstuff, asciistuff);
}
debug ("\n"); // Final spacing
}
char *strtrimr (char *s) {
int i;
for (i = strlen (s) - 1; i >= 0 && isspace (s[i]); i--)
s[i] = '\0';
return (s);
}
/*** The following was taken from the Python sources */
#if !defined(HAVE_LARGEFILE_SUPPORT)
#error "Large file support must be enabled for this program"
#else
/* A portable fseek() function
return 0 on success, non-zero on failure (with errno set) */
int my_fseek (FILE *fp, my_off_t offset, int whence) {
#if defined(HAVE_FSEEKO) && SIZEOF_OFF_T >= 8
return fseeko(fp, offset, whence);
#elif defined(_MSC_VER)
return _fseeki64(fp, (__int64) offset, whence);
#elif defined(HAVE_FSEEK64)
return fseek64(fp, offset, whence);
#elif defined(__BEOS__)
return _fseek(fp, offset, whence);
#elif SIZEOF_FPOS_T >= 8
/* lacking a 64-bit capable fseek(), use a 64-bit capable fsetpos()
and fgetpos() to implement fseek()*/
fpos_t pos;
switch (whence) {
case SEEK_END:
#ifdef MS_WINDOWS
fflush (fp);
if (_lseeki64 (fileno(fp), 0, 2) == -1)
return -1;
#else
if (fseek (fp, 0, SEEK_END) != 0)
return -1;
#endif
// fall through
case SEEK_CUR:
if (fgetpos (fp, &pos) != 0)
return -1;
offset += pos;
break;
// case SEEK_SET: break;
}
return fsetpos(fp, &offset);
#else
#error "Large file support, but no way to fseek."
#endif
}
/* A portable ftell() function
Return -1 on failure with errno set appropriately, current file
position on success */
my_off_t my_ftell (FILE* fp) {
#if defined(HAVE_FTELLO) && SIZEOF_OFF_T >= 8
return ftello (fp);
#elif defined(_MSC_VER)
return _ftelli64 (fp);
#elif defined(HAVE_FTELL64)
return ftell64 (fp);
#elif SIZEOF_FPOS_T >= 8
fpos_t pos;
if (fgetpos (fp, &pos) != 0)
return -1;
return pos;
#else
#error "Large file support, but no way to ftell."
#endif
}
#endif
/*** STUFF FOR DROPPING PRIVILEGES ***/
/* WARNING: I'm not sure at all that the privileges-dropping system I have implemented is secure, so don't rely too much on it. */
#ifndef WIN32
#include <unistd.h>
#endif
/**
* Drops privileges to those of the real user (i. e. set euid to ruid).
*/
void drop_euid () {
#ifndef WIN32
uid_t uid, euid;
uid = getuid ();
euid = geteuid ();
if (uid != 0 && uid != euid) {
#if 1
seteuid (uid);
#else
if (seteuid (uid) != 0)
debug ("seteuid() to uid %d failed", uid);
else
debug ("Changed euid from %d to %d", euid, uid);
#endif
}
#endif
return;
}
/**
* Upgrades priviles to those of root (i. e. set euid to 0).
*/
void upgrade_euid () {
#ifndef WIN32
if (getuid () != 0) {
#if 1
seteuid (0);
#else
if (seteuid (0) != 0)
debug ("seteuid() to root failed");
else
debug ("Changed euid to root");
#endif
}
#endif
return;
}

140
libfriidump/misc.h Normal file
View file

@ -0,0 +1,140 @@
/***************************************************************************
* Copyright (C) 2007 by Arep *
* Support is provided through the forums at *
* http://wii.console-tribe.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef MISC_H_INCLUDED
#define MISC_H_INCLUDED
/*** Include site configuration ***/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
/******/
/*** Windows stuff ***/
#include "win32compat.h"
#define _GNU_SOURCE // For strndup()
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
/*** ASSERTIONS ***/
#define MY_ASSERT(cond) \
if (!(cond)) { \
fprintf (stderr, "*** ASSERTION FAILED at " __FILE__ ":%d: " # cond "\n", __LINE__); \
exit (9); \
}
/*** LOGGING STUFF ***/
enum {
LOG_NORMAL = 1 << 0,
LOG_WARNING = 1 << 1,
LOG_ERROR = 1 << 2,
#ifdef DEBUG
LOG_DEBUG = 1 << 4,
#endif
LOG_NOCR = 1 << 15 /* Use in OR to avoid a trailing newline */
};
/* Don't use this function explicitly. Use the macros below. */
void _logprintf (int level, char tag[], char format[], ...);
#ifdef DEBUG
#define logprintf(level, ...) _logprintf (level, (char *) __FUNCTION__, __VA_ARGS__)
#define debug(...) logprintf(LOG_DEBUG, __VA_ARGS__)
#define debug_nocr(...) logprintf(LOG_DEBUG | LOG_NOCR, __VA_ARGS__)
#else
#define logprintf(level, ...) _logprintf (level, NULL, __VA_ARGS__)
#define debug(...) do {;} while (0);
#define debug_nocr(...) do {;} while (0);
#endif
#if defined (DEBUG) || defined (VERBOSE)
#define log(...) logprintf (LOG_NORMAL, __VA_ARGS__)
#define warning(...) logprintf (LOG_WARNING, __VA_ARGS__)
#define error(...) logprintf (LOG_ERROR, __VA_ARGS__)
#else
#define log(...)
#define warning(...)
#define error(...)
#endif
/******/
void hex_and_ascii_print_with_offset(const char *ident, register const u_int8_t *cp,
register u_int16_t length, register u_int16_t oset);
#define hex_and_ascii_print(ident, cp, length) hex_and_ascii_print_with_offset(ident, cp, length, 0)
#define my_strdup(dest, src) \
if (!(dest = strdup (src))) { \
fprintf (stderr, "strdup() failed\n"); \
exit (101); \
}
#define my_strndup(dest, src, c) \
if (!(dest = strndup ((const char *) src, c))) { \
fprintf (stderr, "strndup() failed\n"); \
exit (102); \
}
char *strtrimr (char *s);
#define my_free(p) \
if (p) { \
free (p); \
p = NULL; \
}
/*** STUFF FOR PORTABLE LARGE-FILES FSEEK ***/
#if defined (HAVE_OFF_T) && SIZEOF_OFF_T >= 8
typedef off_t my_off_t;
#elif defined (HAVE_FPOS_T) && SIZEOF_FPOS_T >= 8
typedef fpos_t my_off_t;
#else
typedef u_int64_t my_off_t;
#endif
int my_fseek (FILE *fp, my_off_t offset, int whence);
my_off_t my_ftell (FILE* fp);
/*******/
/*** STUFF FOR DROPPING PRIVILEGES ***/
FRIIDUMPLIB_EXPORT void drop_euid ();
FRIIDUMPLIB_EXPORT void upgrade_euid ();
/******/
/*** STUFF FOR BOOLEAN DATA TYPE ***/
#ifdef HAVE_STDBOOL_H
/* If using a C99 compiler, use the builtin boolean type */
#include <stdbool.h>
#else
typedef enum {false,true} bool;
#endif
/******/
#endif

132
libfriidump/renesas.c Normal file
View file

@ -0,0 +1,132 @@
/***************************************************************************
* Copyright (C) 2007 by Arep *
* Support is provided through the forums at *
* http://wii.console-tribe.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "rs.h"
#include <stdio.h>
#include <sys/types.h>
#include "misc.h"
#include "dvd_drive.h"
/**
* Command found in Lite-On LH-18A1H
* Expected to work with: DH*, DW*, LH*, SH* series
* Possibly would work with other Mediatek based drives:
* Samsung SE*, SH* series
* Some Dell drives
* Some Sony drives
* Asus DRW-1814* (DRW* series?)
*/
/**
* @param dvd The DVD drive the command should be exectued on.
* @param offset The absolute memory offset to start dumping.
* @param block_size The block size for the dump.
* @param buf Where to place the dumped data. This must have been setup by the caller to store up to block_size bytes.
* @return < 0 if an error occurred, 0 otherwise.
*/
int renesas_dvd_dump_memblock (dvd_drive *dvd, u_int32_t offset, u_int32_t block_size, u_int8_t *buf) {
mmc_command mmc;
int out;
u_int32_t src_offset;
u_int32_t sec_nr;
u_int32_t sec_cnt;
u_int32_t first_sec_nr;
if (!buf) {
error ("NULL buffer");
out = -1;
} else if (!block_size || block_size > 65535) {
error ("invalid block_size (valid: 1 - 65535)");
out = -2;
} else {
dvd_init_command (&mmc, buf, block_size, NULL);
mmc.cmd[0] = 0x3C;
mmc.cmd[1] = 0x05;
mmc.cmd[2] = (unsigned char) ((offset & 0xFF000000) >> 24); // address MSB
mmc.cmd[3] = (unsigned char) ((offset & 0x00FF0000) >> 16); // address MSB
mmc.cmd[4] = (unsigned char) ((offset & 0x0000FF00) >> 8); // address
mmc.cmd[5] = (unsigned char) ( offset & 0x000000FF); // address LSB
// mmc.cmd[6] = (unsigned char) ((block_size & 0x00FF0000) >> 16);// length MSB
mmc.cmd[6] = 0;
mmc.cmd[7] = (unsigned char) ((block_size & 0x0000FF00) >> 8); // length
mmc.cmd[8] = (unsigned char) ( block_size & 0x000000FF); // length LSB
mmc.cmd[9] = 0x44;
out = dvd_execute_cmd (dvd, &mmc, false);
src_offset = 0;
first_sec_nr = 0x55555555;
sec_cnt = 0;
while (src_offset < block_size) {
sec_nr=(*(buf+src_offset+1)<<16)+(*(buf+src_offset+2)<<8)+(*(buf+src_offset+3));
if (first_sec_nr==0x55555555) {
first_sec_nr=sec_nr;
}
else
if (sec_nr!=first_sec_nr+sec_cnt) {
error ("sector sequence broken");
out = -3;
*(buf+src_offset+0)=0xff;
*(buf+src_offset+1)=0xff;
*(buf+src_offset+2)=0xff;
*(buf+src_offset+3)=0xff;
break;
}
src_offset += 2064;
sec_cnt += 1;
}
}
return (out);
}
/**
* WARNING: it can take a while to dump a lot of data.
* @param dvd The DVD drive the command should be exectued on.
* @param offset The memory offset to start dumping, relative to the cache start offset.
* @param block_len The number of blocks to dump.
* @param block_size The block size for the dump.
* @param buf Where to place the dumped data. This must have been setup by the caller to store up to block_size bytes.
* @return < 0 if an error occurred, 0 otherwise.
*/
int renesas_dvd_dump_mem (dvd_drive *dvd, u_int32_t offset, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf) {
u_int32_t i;
int r, out;
if (!buf) {
error ("NULL buffer");
out = -1;
} else {
r = -10;
for (i = 0; i < block_len; i++) {
if ((r = renesas_dvd_dump_memblock (dvd, offset + i * block_size, block_size, buf + i * block_size)) < 0) {
error ("renesas_dvd_dump_memblock() failed with %d", r);
break;
}
}
out = r;
}
return (out);
}

316
libfriidump/rs.c Normal file
View file

@ -0,0 +1,316 @@
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
#define mm 8 /* RS code over GF(2**mm) - change to suit */
#define n 256 /* n = size of the field */
#define nn 182 /* nn=2**mm -1 length of codeword */
#define kk 172 /* kk = nn-2*tt */ /* Degree of g(x) = 2*tt */
//#define NN n-1
//#define FCR 0
//#define PRIM 1
#define _NROOTS nn-kk
//#define PAD NN-nn
//#define A0 NN
//#define IPRIM 1
const int NN = n-1;
const int FCR = 0;
const int PRIM = 1;
const int NROOTS = nn-kk;
const int PAD = (n-1)-nn;
const int A0 = n-1;
const int IPRIM = 1;
#ifndef min
#define min(a,b) ((a) < (b) ? (a) : (b))
#endif
/**** Primitive polynomial ****/
int pp [mm+1] = { 1, 0, 1, 1, 1, 0, 0, 0, 1}; /* 1+x^2+x^3+x^4+x^8 */
/* generator polynomial, tables for Galois field */
int alpha_to[n], index_of[n], gg[nn-kk+1];
int b0 = 1;
/* data[] is the info vector, bb[] is the parity vector, recd[] is the
noise corrupted received vector */
int recd[nn], data[kk], bb[nn-kk];
int modnn(int x){
while (x >= 0xff) {
x -= 0xff;
x = (x >> 0xff) + (x & 0xff);
}
return x;
}
void generate_gf()
{
register int i, mask ;
mask = 1 ;
alpha_to[mm] = 0 ;
for (i=0; i<mm; i++)
{ alpha_to[i] = mask ;
index_of[alpha_to[i]] = i ;
if (pp[i]!=0) /* If pp[i] == 1 then, term @^i occurs in poly-repr of @^mm */
alpha_to[mm] ^= mask ; /* Bit-wise EXOR operation */
mask <<= 1 ; /* single left-shift */
}
index_of[alpha_to[mm]] = mm ;
/* Have obtained poly-repr of @^mm. Poly-repr of @^(i+1) is given by
poly-repr of @^i shifted left one-bit and accounting for any @^mm
term that may occur when poly-repr of @^i is shifted. */
mask >>= 1 ;
for (i=mm+1; i<255; i++)
{ if (alpha_to[i-1] >= mask)
alpha_to[i] = alpha_to[mm] ^ ((alpha_to[i-1]^mask)<<1) ;
else alpha_to[i] = alpha_to[i-1]<<1 ;
index_of[alpha_to[i]] = i ;
}
index_of[0] = A0 ;//-1
}
void gen_poly()
/* Obtain the generator polynomial of the tt-error correcting, length */
{
register int i, j, root;
gg[0] = 1;
for (i = 0,root=0*1; i < nn-kk; i++,root += 1) {
gg[i+1] = 1;
for (j = i; j > 0; j--){
if (gg[j] != 0)
gg[j] = gg[j-1] ^ alpha_to[modnn(index_of[gg[j]] + root)];
else
gg[j] = gg[j-1];
}
gg[0] = alpha_to[modnn(index_of[gg[0]] + root)];
}
for (i=0; i <= nn-kk; i++) {
gg[i] = index_of[gg[i]];
}
}
void rs_encode(unsigned char *data, unsigned char *bb)
{
register int i,j ;
int feedback;
for (i=0; i<NROOTS; i++) bb[i] = 0; //nullify result
for(i=0;i<NN-NROOTS-PAD;i++){
feedback = index_of[data[i] ^ bb[0]];
if(feedback != A0){ /* feedback term is non-zero */
for(j=1;j<NROOTS;j++) {
bb[j] ^= alpha_to[modnn(feedback + gg[NROOTS-j])];
}
}
/* Shift */
memmove(&bb[0],&bb[1], NROOTS-1);
//for (j=0; j<NROOTS-1; j++) bb[j] = bb[j+1];
if(feedback != A0)
bb[NROOTS-1] = alpha_to[modnn(feedback + gg[0])];
else
bb[NROOTS-1] = 0;
}
}
///*
int rs_decode(unsigned char *data, int *eras_pos, int no_eras){
int deg_lambda, el, deg_omega;
int i, j, r,k;
unsigned char u,q,tmp,num1,num2,den,discr_r;
unsigned char lambda[_NROOTS+1], s[_NROOTS];
unsigned char b[_NROOTS+1], t[_NROOTS+1], omega[_NROOTS+1];
unsigned char root[_NROOTS], reg[_NROOTS+1], loc[_NROOTS];
int syn_error, count;
// form the syndromes; i.e., evaluate data(x) at roots of g(x)
for(i=0;i<NROOTS;i++)
s[i] = data[0];
for(j=1;j<NN-PAD;j++){
for(i=0;i<NROOTS;i++){
if(s[i] == 0){
s[i] = data[j];
} else {
s[i] = data[j] ^ alpha_to[modnn(index_of[s[i]] + (FCR+i)*PRIM)];
}
}
}
// Convert syndromes to index form, checking for nonzero condition
syn_error = 0;
for(i=0;i<NROOTS;i++){
syn_error |= s[i];
s[i] = index_of[s[i]];
}
if (!syn_error) {
// if syndrome is zero, data[] is a codeword and there are no
// errors to correct. So return data[] unmodified
//
count = 0;
goto finish;
}
memset(&lambda[1],0,NROOTS*sizeof(lambda[0]));
lambda[0] = 1;
if (no_eras > 0) {
/* Init lambda to be the erasure locator polynomial */
lambda[1] = alpha_to[modnn(PRIM*(NN-1-eras_pos[0]))];
for (i = 1; i < no_eras; i++) {
u = modnn(PRIM*(NN-1-eras_pos[i]));
for (j = i+1; j > 0; j--) {
tmp = index_of[lambda[j - 1]];
if(tmp != A0)
lambda[j] ^= alpha_to[modnn(u + tmp)];
}
}
}
for(i=0;i<NROOTS+1;i++)
b[i] = index_of[lambda[i]];
/*
* Begin Berlekamp-Massey algorithm to determine error+erasure
* locator polynomial
*/
r = no_eras;
el = no_eras;
while (++r <= NROOTS) { /* r is the step number */
/* Compute discrepancy at the r-th step in poly-form */
discr_r = 0;
for (i = 0; i < r; i++){
if ((lambda[i] != 0) && (s[r-i-1] != A0)) {
discr_r ^= alpha_to[modnn(index_of[lambda[i]] + s[r-i-1])];
}
}
discr_r = index_of[discr_r]; /* Index form */
if (discr_r == A0) {
/* 2 lines below: B(x) <-- x*B(x) */
memmove(&b[1],b,NROOTS*sizeof(b[0]));
b[0] = A0;
} else {
/* 7 lines below: T(x) <-- lambda(x) - discr_r*x*b(x) */
t[0] = lambda[0];
for (i = 0 ; i < NROOTS; i++) {
if(b[i] != A0)
t[i+1] = lambda[i+1] ^ alpha_to[modnn(discr_r + b[i])];
else
t[i+1] = lambda[i+1];
}
if (2 * el <= r + no_eras - 1) {
el = r + no_eras - el;
/*
* 2 lines below: B(x) <-- inv(discr_r) *
* lambda(x)
*/
for (i = 0; i <= NROOTS; i++)
b[i] = (lambda[i] == 0) ? A0 : modnn(index_of[lambda[i]] - discr_r + NN);
} else {
/* 2 lines below: B(x) <-- x*B(x) */
memmove(&b[1],b,NROOTS*sizeof(b[0]));
b[0] = A0;
}
memcpy(lambda,t,(NROOTS+1)*sizeof(t[0]));
}
}
/* Convert lambda to index form and compute deg(lambda(x)) */
deg_lambda = 0;
for(i=0;i<NROOTS+1;i++){
lambda[i] = index_of[lambda[i]];
if(lambda[i] != A0)
deg_lambda = i;
}
/* Find roots of the error+erasure locator polynomial by Chien search */
memcpy(&reg[1],&lambda[1],NROOTS*sizeof(reg[0]));
count = 0; /* Number of roots of lambda(x) */
for (i = 1,k=IPRIM-1; i <= NN; i++,k = modnn(k+IPRIM)) {
q = 1; /* lambda[0] is always 0 */
for (j = deg_lambda; j > 0; j--){
if (reg[j] != A0) {
reg[j] = modnn(reg[j] + j);
q ^= alpha_to[reg[j]];
}
}
if (q != 0)
continue; /* Not a root */
/* store root (index-form) and error location number */
root[count] = i;
loc[count] = k;
/* If we've already found max possible roots,
* abort the search to save time
*/
if(++count == deg_lambda)
break;
}
if (deg_lambda != count) {
/*
* deg(lambda) unequal to number of roots => uncorrectable
* error detected
*/
count = -1;
goto finish;
}
/*
* Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo
* x**NROOTS). in index form. Also find deg(omega).
*/
deg_omega = deg_lambda-1;
for (i = 0; i <= deg_omega;i++){
tmp = 0;
for(j=i;j >= 0; j--){
if ((s[i - j] != A0) && (lambda[j] != A0))
tmp ^= alpha_to[modnn(s[i - j] + lambda[j])];
}
omega[i] = index_of[tmp];
}
/*
* Compute error values in poly-form. num1 = omega(inv(X(l))), num2 =
* inv(X(l))**(FCR-1) and den = lambda_pr(inv(X(l))) all in poly-form
*/
for (j = count-1; j >=0; j--) {
num1 = 0;
for (i = deg_omega; i >= 0; i--) {
if (omega[i] != A0)
num1 ^= alpha_to[modnn(omega[i] + i * root[j])];
}
num2 = alpha_to[modnn(root[j] * (FCR - 1) + NN)];
den = 0;
/* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */
for (i = min(deg_lambda,NROOTS-1) & ~1; i >= 0; i -=2) {
if(lambda[i+1] != A0)
den ^= alpha_to[modnn(lambda[i+1] + i * root[j])];
}
/* Apply error to data */
if (num1 != 0 && loc[j] >= PAD) {
data[loc[j]-PAD] ^= alpha_to[modnn(index_of[num1] + index_of[num2] + NN - index_of[den])];
}
}
finish:
if(eras_pos != NULL){
for(i=0;i<count;i++)
eras_pos[i] = loc[i];
}
return count;
}

10
libfriidump/rs.h Normal file
View file

@ -0,0 +1,10 @@
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
int modnn(int x);
void generate_gf();
void gen_poly();
void rs_encode(unsigned char *data, unsigned char *bb);
int rs_decode(unsigned char *data, int *eras_pos, int no_eras);

370
libfriidump/unscrambler.c Normal file
View file

@ -0,0 +1,370 @@
/***************************************************************************
* Copyright (C) 2007 by Arep *
* Support is provided through the forums at *
* http://wii.console-tribe.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
/*! \file
* \brief Unscrambler for Nintendo GameCube/Wii discs.
*
* As Nintendo GameCube/Wii discs use the standars DVD-ROM scrambling algorithm, but with different, unknown, seeds, the actual seeds have to be brute-forced.
* The functions in this file take care of the brute-forcing and of the actual unscrambling of the read sectors.
*
* The code in this file has been derived from unscrambler 0.4, Copyright (C) 2006 Victor Muñoz (xt5@ingenieria-inversa.cl), GPL v2+,
* http://www.ingenieria-inversa.cl/?lp_lang_pref=en .
*/
#include "misc.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "constants.h"
#include "byteorder.h"
#include "ecma-267.h"
#include "unscrambler.h"
// #define unscramblerdebug(...) debug (__VA_ARGS__);
#define unscramblerdebug(...)
/*! \brief Size of the seeds cache (Do not touch) */
#define MAX_SEEDS 4
/*! \brief Number of bytes of a sector on which the EDC is calculated */
#define EDC_LENGTH (RAW_SECTOR_SIZE - 4) /* The EDC value is contained in the bottom 4 bytes of a frame */
/*! \brief A structure that represents a seed
*/
typedef struct t_seed {
int seed; //!< The seed, in numeric format.
unsigned char streamcipher[SECTOR_SIZE]; //!< The stream cipher generated from the seed through the LFSR.
} t_seed;
/*! \brief A structure that represents an unscrambler
*/
struct unscrambler_s {
t_seed seeds[(MAX_SEEDS + 1) * 16]; //!< The seeds cache.
bool bruteforce_seeds; //!< If true, whenever a seed for a sector is not cached, it will be found via a bruteforce attack, otherwise an error will be returned.
};
void unscrambler_set_disctype (u_int8_t disc_type){
disctype = disc_type;
// fprintf (stdout,"%d",disctype);
}
/**
* Adds a seed to the cache, calculating its streamcipher.
* @param seeds The seed cache.
* @param seed The seed to add.
* @return A structure representing the added seed, or NULL if it could not be added.
*/
static t_seed *add_seed (t_seed *seeds, unsigned short seed) {
int i;
t_seed *out;
unscramblerdebug ("Caching seed %04x\n", seed);
if (seeds -> seed == -2) {
out = NULL;
} else {
seeds -> seed = seed;
LFSR_init (seed);
for (i = 0; i < SECTOR_SIZE; i++)
seeds -> streamcipher[i] = LFSR_byte ();
out = seeds;
}
return (out);
}
/**
* Tests if the specified seed is the one used for the specified sector block: the check is done comparing the generated EDC with the one at the bottom of each
* sector. Sectors are processed in blocks, as the same seed is used for 16 consecutive sectors.
* @param buf The sector.
* @param j The seed.
* @return true if the seed is correct, false otherwise.
*/
static bool test_seed (u_int8_t *buf, int j) {
int i;
u_int8_t tmp[RAW_SECTOR_SIZE];
u_int32_t edc_calculated, edc_correct;
bool out;
memcpy (tmp, buf, RAW_SECTOR_SIZE);
LFSR_init (j);
for (i = 12; i < EDC_LENGTH; i++)
tmp[i] ^= LFSR_byte ();
edc_calculated = edc_calc (0x00000000, tmp, EDC_LENGTH);
edc_correct = my_ntohl (*((u_int32_t *) (&tmp[EDC_LENGTH])));
if (edc_calculated == edc_correct)
out = true;
else
out = false;
return (out);
}
/**
* Unscramble a complete block, using an already-cached seed.
* @param seed The seed to use for the unscrambling.
* @param _bin The 16-sector block to unscramble (RAW_BLOCK_SIZE).
* @param _bout The unscrambled 16-sector block (BLOCK_SIZE).
* @return True if the unscrambling was successful, false otherwise.
*/
static bool unscramble_frame (t_seed *seed, u_int8_t *_bin, u_int8_t *_bout) {
int i, j;
u_int8_t tmp[RAW_SECTOR_SIZE], *bin, *bout;
u_int32_t *_4bin, *_4cipher, edc_calculated, edc_correct;
bool out;
out = true;
for(j = 0; j < 16; j++) {
bin = &_bin[RAW_SECTOR_SIZE * j];
bout = &_bout[SECTOR_SIZE * j];
memcpy (tmp, bin, RAW_SECTOR_SIZE);
_4bin = (u_int32_t *) &tmp[12]; /* Scrambled data begin at byte 12 */
_4cipher = (u_int32_t *) seed -> streamcipher;
for (i = 0; i < 512; i++) /* Well, the scrambling algorithm is just a bitwise XOR... */
_4bin[i] ^= _4cipher[i];
//memcpy (bout, tmp + 6, SECTOR_SIZE); // copy CPR_MAI bytes
if (disctype==3) { //Regular
memcpy (bout, tmp + 12, SECTOR_SIZE); // DVD: copy 2048 bytes (starting from CPR_MAI)
}
else { //Nintendo
memcpy (bout, tmp + 6, SECTOR_SIZE); // Nintendo: copy 2048 bytes (up to CPR_MAI)
memcpy (&_bin[(RAW_SECTOR_SIZE * j)+2054], &tmp[2054], 6);
}
edc_calculated = edc_calc (0x00000000, tmp, EDC_LENGTH);
edc_correct = my_ntohl (*((u_int32_t *) (&tmp[EDC_LENGTH])));
if (edc_calculated != edc_correct) {
debug ("Bad EDC (%08x), must be %08x (sector = %d)", edc_calculated, edc_correct, j);
out = false;
}
}
return (out);
}
/**
* Initializes the seed cache.
* @param u The unscrambler structure.
*/
static void unscrambler_init_seeds (unscrambler *u) {
int i, j;
for (i = 0; i < 16; i++) {
for (j = 0; j < MAX_SEEDS; j++)
u -> seeds[i * MAX_SEEDS + j].seed = -1;
u -> seeds[i * MAX_SEEDS + j].seed = -2; // TODO Check what this does
}
return;
}
/**
* Creates a new structure representing an unscrambler.
* @return The newly-created structure, to be used with the other commands.
*/
unscrambler *unscrambler_new (void) {
unscrambler *u;
u = (unscrambler *) malloc (sizeof (unscrambler));
unscrambler_init_seeds (u);
u -> bruteforce_seeds = true;
return (u);
}
/**
* Frees resources used by an unscrambler structure and destroys it.
* @param u The unscrambler structure.
* @return NULL.
*/
void *unscrambler_destroy (unscrambler *u) {
my_free (u);
return (NULL);
}
void unscrambler_set_bruteforce (unscrambler *u, bool b) {
u -> bruteforce_seeds = b;
debug ("Seed bruteforcing %s", b ? "enabled" : "disabled");
return;
}
/**
* Unscrambles a 16-sector block.
* @param u The unscrambler structure.
* @param sector_no The number of the first sector in the block.
* @param inbuf The 16-sector block to unscramble. Each block must be RAW_SECTOR_SIZE bytes long, so that the total size is RAW_BLOCK_SIZE.
* @param outbuf The unscrambled 16-sector block. Each block will be SECTOR_SIZE bytes long, so that the total size is BLOCK_SIZE.
* @return True if the unscrambling was successful, false otherwise.
*/
bool unscrambler_unscramble_16sectors (unscrambler *u, u_int32_t sector_no, u_int8_t *inbuf, u_int8_t *outbuf) {
t_seed *seeds;
t_seed *current_seed;
int j;
bool out;
out = true;
seeds = &(u -> seeds[((sector_no / 16) & 0x0F) * MAX_SEEDS]);
/* Try to find the seed used for this sector */
current_seed = NULL;
while (!current_seed && (seeds -> seed) >= 0) {
if (test_seed (inbuf, seeds -> seed))
current_seed = seeds;
else
seeds++;
}
if (!current_seed && u -> bruteforce_seeds) {
/* The seed is not cached, yet. Try to find it with brute force... */
unscramblerdebug ("Brute-forcing seed for sector %d...", sector_no);
for (j = 0; !current_seed && j < 0x7FFF; j++) {
if (test_seed (inbuf, j)) {
if (!(current_seed = add_seed (seeds, j))) {
error ("No enough cache space for caching seed");
out = false;
}
}
}
if (current_seed)
unscramblerdebug ("Seed found: %04x", --j);
}
if (current_seed) {
/* OK, somehow seed was found: unscramble frame, write it and go on */
if (!unscramble_frame (current_seed, inbuf, outbuf)) {
error ("Error unscrambling frame %u\n", sector_no);
out = false;
} else {
out = true;
}
} else {
/* Well, we only get here if there are read errors */
error ("Cannot find seed for frame %u", sector_no);
out = false;
}
return (out);
}
/**
* Unscrambles a complete file.
* @param u The unscrambler structure.
* @param infile The input file name.
* @param outfile The output file name.
* @param progress A function to be called repeatedly during the operation, useful to report progress data/statistics.
* @param progress_data Data to be passed as-is to the progress function.
* @return True if the unscrambling was successful, false otherwise.
*/
bool unscrambler_unscramble_file (unscrambler *u, char *infile, char *outfile, unscrambler_progress_func progress, void *progress_data, u_int32_t *current_sector) {
FILE *in, *outfp;
bool out;
u_int8_t b_in[RAW_BLOCK_SIZE], b_out[BLOCK_SIZE];
size_t r;
my_off_t filesize;
int s;
u_int32_t total_sectors;
out = false;
if(!(in = fopen (infile ? infile : "", "rb"))) {
error ("Cannot open input file \"%s\"", infile);
} else if (!(outfp = fopen (outfile ? outfile : "", "wb"))) {
error ("Cannot open output file \"%s\"", outfile);
fclose (in);
} else {
/* Find out how many sectors we need to process */
my_fseek (in, 0, SEEK_END);
filesize = my_ftell (in);
total_sectors = (u_int32_t) (filesize / RAW_SECTOR_SIZE);
rewind (in);
/* First call to progress function */
if (progress)
progress (true, 0, total_sectors, progress_data);
s = 0, out = true;
while ((r = fread (b_in, 1, RAW_BLOCK_SIZE, in)) > 0 && out) {
if (r < RAW_BLOCK_SIZE) {
warning ("Short block read (%u bytes), padding with zeroes!", r);
memset (b_in + r, 0, sizeof (b_in) - r);
}
if (unscrambler_unscramble_16sectors (u, s, b_in, b_out)) {
clearerr (outfp);
if (!b_out) {
error ("NULL buffer");
out = false;
*(current_sector) = s;
}
else fwrite (b_out, SECTOR_SIZE, SECTORS_PER_BLOCK, outfp);
if (ferror (outfp)) {
error ("fwrite() to ISO output file failed");
out = false;
*(current_sector) = s;
}
} else {
debug ("unscrambler_unscramble_16sectors() failed");
out = false;
*(current_sector) = s;
}
s += 16;
if ((s % 320 == 0) || (s == total_sectors)) { //speedhack
if (progress)
progress (false, s, total_sectors, progress_data);
}
}
if (out) {
debug ("Image successfully unscrambled");
}
fclose (in);
fclose (outfp);
}
return (out);
}

43
libfriidump/unscrambler.h Normal file
View file

@ -0,0 +1,43 @@
/***************************************************************************
* Copyright (C) 2007 by Arep *
* Support is provided through the forums at *
* http://wii.console-tribe.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef UNSCRAMBLER_H_INCLUDED
#define UNSCRAMBLER_H_INCLUDED
#include "misc.h"
#include <sys/types.h>
typedef struct unscrambler_s unscrambler;
/* We want this module to be independent of the library framework, so that it can be easily recycled. Hence we just define the type of
the progress function the same format we use elsewhere */
typedef void (*unscrambler_progress_func) (bool start, u_int32_t current_sector, u_int32_t total_sectors, void *progress_data);
u_int8_t disctype;
FRIIDUMPLIB_EXPORT unscrambler *unscrambler_new (void);
FRIIDUMPLIB_EXPORT void *unscrambler_destroy (unscrambler *u);
FRIIDUMPLIB_EXPORT bool unscrambler_unscramble_16sectors (unscrambler *u, u_int32_t sector_no, u_int8_t *inbuf, u_int8_t *outbuf);
FRIIDUMPLIB_EXPORT bool unscrambler_unscramble_file (unscrambler *u, char *infile, char *outfile, unscrambler_progress_func progress, void *progress_data, u_int32_t *current_sector);
FRIIDUMPLIB_EXPORT void unscrambler_set_bruteforce (unscrambler *u, bool b);
FRIIDUMPLIB_EXPORT void unscrambler_set_disctype (u_int8_t disc_type);
#endif

131
libfriidump/vanilla_2064.c Normal file
View file

@ -0,0 +1,131 @@
/***************************************************************************
* Copyright (C) 2007 by Arep *
* Support is provided through the forums at *
* http://wii.console-tribe.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
//#include "rs.h"
#include <stdio.h>
#include <sys/types.h>
#include "misc.h"
#include "dvd_drive.h"
/**
* Command found in Lite-On LH-18A1H
* Expected to work with: DH*, DW*, LH*, SH* series
* Possibly would work with other Mediatek based drives:
* Samsung SE*, SH* series
* Some Dell drives
* Some Sony drives
* Asus DRW-1814* (DRW* series?)
*/
/**
* @param dvd The DVD drive the command should be exectued on.
* @param offset The absolute memory offset to start dumping.
* @param block_size The block size for the dump.
* @param buf Where to place the dumped data. This must have been setup by the caller to store up to block_size bytes.
* @return < 0 if an error occurred, 0 otherwise.
*/
int vanilla_2064_dvd_dump_memblock (dvd_drive *dvd, u_int32_t offset, u_int32_t block_size, u_int8_t *buf) {
mmc_command mmc;
int out;
u_int32_t src_offset;
u_int32_t sec_nr;
u_int32_t sec_cnt;
u_int32_t first_sec_nr;
if (!buf) {
error ("NULL buffer");
out = -1;
} else if (!block_size || block_size > 65535) {
error ("invalid block_size (valid: 1 - 65535)");
out = -2;
} else {
dvd_init_command (&mmc, buf, block_size, NULL);
mmc.cmd[0] = 0x3C;
mmc.cmd[1] = 0x02;
mmc.cmd[2] = 0x00;
mmc.cmd[3] = (unsigned char) ((offset & 0x00FF0000) >> 16); // address MSB
mmc.cmd[4] = (unsigned char) ((offset & 0x0000FF00) >> 8); // address
mmc.cmd[5] = (unsigned char) ( offset & 0x000000FF); // address LSB
mmc.cmd[6] = (unsigned char) ((block_size & 0x00FF0000) >> 16);// length MSB
mmc.cmd[7] = (unsigned char) ((block_size & 0x0000FF00) >> 8); // length
mmc.cmd[8] = (unsigned char) ( block_size & 0x000000FF); // length LSB
out = dvd_execute_cmd (dvd, &mmc, false);
src_offset = 0;
first_sec_nr = 0x55555555;
sec_cnt = 0;
while (src_offset < block_size) {
sec_nr=(*(buf+src_offset+1)<<16)+(*(buf+src_offset+2)<<8)+(*(buf+src_offset+3));
if (first_sec_nr==0x55555555) {
first_sec_nr=sec_nr;
}
else
if (sec_nr!=first_sec_nr+sec_cnt) {
error ("sector sequence broken");
out = -3;
*(buf+src_offset+0)=0xff;
*(buf+src_offset+1)=0xff;
*(buf+src_offset+2)=0xff;
*(buf+src_offset+3)=0xff;
break;
}
src_offset += 2064;
sec_cnt += 1;
}
}
return (out);
}
/**
* WARNING: it can take a while to dump a lot of data.
* @param dvd The DVD drive the command should be exectued on.
* @param offset The memory offset to start dumping, relative to the cache start offset.
* @param block_len The number of blocks to dump.
* @param block_size The block size for the dump.
* @param buf Where to place the dumped data. This must have been setup by the caller to store up to block_size bytes.
* @return < 0 if an error occurred, 0 otherwise.
*/
int vanilla_2064_dvd_dump_mem (dvd_drive *dvd, u_int32_t offset, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf) {
u_int32_t i;
int r, out;
if (!buf) {
error ("NULL buffer");
out = -1;
} else {
r = -10;
for (i = 0; i < block_len; i++) {
if ((r = vanilla_2064_dvd_dump_memblock (dvd, offset + i * block_size, block_size, buf + i * block_size)) < 0) {
error ("vanilla_2064_dvd_dump_memblock() failed with %d", r);
break;
}
}
out = r;
}
return (out);
}

153
libfriidump/vanilla_2384.c Normal file
View file

@ -0,0 +1,153 @@
/***************************************************************************
* Copyright (C) 2007 by Arep *
* Support is provided through the forums at *
* http://wii.console-tribe.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
//#include "rs.h"
#include <stdio.h>
#include <sys/types.h>
#include "misc.h"
#include "dvd_drive.h"
/**
* Command found in Lite-On LH-18A1H
* Expected to work with: DH*, DW*, LH*, SH* series
* Possibly would work with other Mediatek based drives:
* Samsung SE*, SH* series
* Some Dell drives
* Some Sony drives
* Asus DRW-1814* (DRW* series?)
*/
//u_int8_t tmp[64*1024];
/**
* @param dvd The DVD drive the command should be exectued on.
* @param offset The absolute memory offset to start dumping.
* @param block_size The block size for the dump.
* @param buf Where to place the dumped data. This must have been setup by the caller to store up to block_size bytes.
* @return < 0 if an error occurred, 0 otherwise.
*/
int vanilla_2384_dvd_dump_memblock (dvd_drive *dvd, u_int32_t offset, u_int32_t block_size, u_int8_t *buf) {
mmc_command mmc;
int out;
u_int32_t raw_block_size;
u_int32_t raw_offset;
u_int32_t src_offset;
u_int32_t dst_offset;
u_int32_t row_nr;
u_int32_t sec_nr;
u_int32_t sec_cnt;
u_int32_t first_sec_nr;
u_int8_t tmp[64*1024];
//u_int8_t *tmp;
raw_block_size = (block_size / 2064) * 0x950;
raw_offset = (offset / 2064) * 0x950;
if (!buf) {
error ("NULL buffer");
out = -1;
} else if (!block_size || raw_block_size > 65535) {
error ("invalid raw_block_size (valid: 1 - 65535)");
error ("raw_block_size = (block_size / 2064) * 2384");
out = -2;
} else {
//tmp = malloc(64*1024);
dvd_init_command (&mmc, tmp, raw_block_size, NULL);
mmc.cmd[0] = 0x3C;
mmc.cmd[1] = 0x02;
mmc.cmd[2] = 0x00;
mmc.cmd[3] = (unsigned char) ((raw_offset & 0x00FF0000) >> 16);// address MSB
mmc.cmd[4] = (unsigned char) ((raw_offset & 0x0000FF00) >> 8); // address
mmc.cmd[5] = (unsigned char) ( raw_offset & 0x000000FF); // address LSB
mmc.cmd[6] = (unsigned char) ((raw_block_size & 0x00FF0000) >> 16); // length MSB
mmc.cmd[7] = (unsigned char) ((raw_block_size & 0x0000FF00) >> 8); // length
mmc.cmd[8] = (unsigned char) ( raw_block_size & 0x000000FF); // length LSB
out = dvd_execute_cmd (dvd, &mmc, false);
src_offset = 0;
dst_offset = 0;
first_sec_nr = 0x55555555;
sec_cnt = 0;
while (src_offset < raw_block_size) {
sec_nr=(*(tmp+src_offset+1)<<16)+(*(tmp+src_offset+2)<<8)+(*(tmp+src_offset+3));
if (first_sec_nr==0x55555555) {
first_sec_nr=sec_nr;
// rs_decode(tmp+src_offset, 0, 0);
}
else
if (sec_nr==first_sec_nr+sec_cnt) {
// rs_decode(tmp+src_offset, 0, 0); //sector seq = ok
}
else { //sector seq broken -> corrupt
error ("sector sequence broken");
out = -3;
*(tmp+src_offset+0)=0xff;
*(tmp+src_offset+1)=0xff;
*(tmp+src_offset+2)=0xff;
*(tmp+src_offset+3)=0xff;
break;
}
for (row_nr=0; row_nr<12; row_nr++) {
memcpy(buf+dst_offset, tmp+src_offset, 172);
dst_offset += 172;
src_offset += 182;
}
src_offset += 200;
sec_cnt += 1;
}
//free(tmp);
}
return (out);
}
/**
* WARNING: it can take a while to dump a lot of data.
* @param dvd The DVD drive the command should be exectued on.
* @param offset The memory offset to start dumping, relative to the cache start offset.
* @param block_len The number of blocks to dump.
* @param block_size The block size for the dump.
* @param buf Where to place the dumped data. This must have been setup by the caller to store up to block_size bytes.
* @return < 0 if an error occurred, 0 otherwise.
*/
int vanilla_2384_dvd_dump_mem (dvd_drive *dvd, u_int32_t offset, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf) {
u_int32_t i;
int r, out;
if (!buf) {
error ("NULL buffer");
out = -1;
} else {
r = -10;
for (i = 0; i < block_len; i++) {
if ((r = vanilla_2384_dvd_dump_memblock (dvd, offset + i * block_size, block_size, buf + i * block_size)) < 0) {
error ("vanilla_2384_dvd_dump_memblock() failed with %d", r);
break;
}
}
out = r;
}
return (out);
}

75
libfriidump/win32compat.c Normal file
View file

@ -0,0 +1,75 @@
/***************************************************************************
* Copyright (C) 2007 by Arep *
* Support is provided through the forums at *
* http://www.console-tribe.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifdef WIN32
#include "win32compat.h"
#include <stdio.h>
#include <windows.h>
#include <io.h>
#include <sys/timeb.h>
char *strndup (const char *src, int c) {
char *dest;
if ((dest = (char *) malloc ((c + 1) * sizeof (char)))) {
memcpy (dest, src, c);
dest[c] = '\0';
}
return (dest);
}
int ftruncate (int fd, __int64 size) {
return (_chsize_s (fd, size));
}
/* The following gettimeofday() replacement function was taken from Snort, GPLv2 */
/****************************************************************************
*
* Function: gettimeofday(struct timeval *, struct timezone *)
*
* Purpose: Get current time of day.
*
* Arguments: tv => Place to store the curent time of day.
* tz => Ignored.
*
* Returns: 0 => Success.
*
****************************************************************************/
int gettimeofday(struct timeval *tv, struct timezone *tz) {
struct _timeb tb;
if (tv == NULL) {
return -1;
}
_ftime(&tb);
tv->tv_sec = (long) tb.time;
tv->tv_usec = ((int) tb.millitm) * 1000;
return 0;
}
#endif

68
libfriidump/win32compat.h Normal file
View file

@ -0,0 +1,68 @@
/***************************************************************************
* Copyright (C) 2007 by Arep *
* Support is provided through the forums at *
* http://www.console-tribe.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
/*** WINDOWS COMPATIBILITY STUFF ***/
#ifdef WIN32
#include <windows.h>
#include <time.h>
/* Stuff to export library symbols */
#ifdef FRIIDUMPLIB_BUILD_DLL
#ifdef FRIIDUMPLIB_EXPORTS
#define FRIIDUMPLIB_EXPORT __declspec(dllexport) /* Building the lib */
#else
#define FRIIDUMPLIB_EXPORT __declspec(dllimport) /* Building user code */
#endif
#else
#define FRIIDUMPLIB_EXPORT
#endif
/* Definition of the types we use for Windows */
#define u_int8_t BYTE
#define u_int16_t WORD
#define int32_t INT32
#define u_int32_t DWORD
#define int64_t INT64
#define u_int64_t ULONGLONG
typedef long suseconds_t;
/* Some functions have different names */
#define snprintf _snprintf
#define strdup _strdup
#define strcasecmp lstrcmpi
#define va_copy(ap1, ap2) ((ap1) = (ap2)) // MSVC doesn't have va_copy, how crap...
/* Some functions do not exist (export them for applications, too) */
FRIIDUMPLIB_EXPORT char *strndup (const char *src, int c);
FRIIDUMPLIB_EXPORT int ftruncate (int fd, __int64 size);
FRIIDUMPLIB_EXPORT int gettimeofday(struct timeval *tv, struct timezone *tz);
/* Windows does have a different localtime() */
#define localtime_r(x, y) !localtime_s (y, x)
#else
#define FRIIDUMPLIB_EXPORT
#endif
/******/

View file

@ -0,0 +1,77 @@
# Create a library called "Hello" which includes the source file "hello.cxx".
# The extension is already found. Any number of sources could be listed here.
add_library (
multihashlib
${libmultihash_type}
#SHARED
#STATIC
crc32.c
edonkey.c
md4.c
md5.c
multihash.c
sha1.c
crc32.h
edonkey.h
md4.h
md5.h
multihash.h
sha1.h
)
set_target_properties (multihashlib PROPERTIES OUTPUT_NAME "multihash")
# Before making a release, the LTVERSION string should be modified.
# The string is of the form CURRENT:REVISION:AGE.
#
# CURRENT (C)
# The most recent interface number that this library implements.
#
# REVISION (R)
# The implementation number that this library implements.
#
# AGE (A)
# The difference between the newest and oldest interfaces that this
# library implements. In other works, the library implements all the
# interface numbers in the range from number 'CURRENT - AGE' to
# 'CURRENT'.
#
# This means that:
#
# - If interfaces have been changed or added, but binary compatibility has
# been preserved, change to C+1:0:A+1
#
# - If binary compatibility has been broken (eg removed or changed
# interfaces) change to C+1:0:0
#
# - If the interface is the same as the previous version, change to C:R+1:A
#
set_target_properties (multihashlib PROPERTIES SOVERSION 1.0.0)
#get_target_property(libhash_type multihashlib TYPE)
if (WIN32)
if (libhash_type STREQUAL "SHARED")
# MESSAGE ("Building libmultihash DLL")
ADD_DEFINITIONS (-DMULTIHASH_BUILD_DLL)
set_target_properties (multihashlib PROPERTIES DEFINE_SYMBOL MULTIHASH_EXPORTS)
install (
TARGETS multihashlib
RUNTIME DESTINATION /
#ARCHIVE DESTINATION lib
)
endif (libhash_type STREQUAL "SHARED")
else (WIN32)
# Install stuff, only if a shared library is being built
if (libhash_type STREQUAL "SHARED")
install (
TARGETS multihashlib
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib/static
)
endif (libhash_type STREQUAL "SHARED")
endif (WIN32)

120
libmultihash/crc32.c Normal file
View file

@ -0,0 +1,120 @@
/*
* Copyright (c) 1995, Edward B. Hamrick
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee, provided
* that
*
* (i) the above copyright notice and the text in this "C" comment block
* appear in all copies of the software and related documentation, and
*
* (ii) any modifications to this source file must be sent, via e-mail
* to the copyright owner (currently hamrick@primenet.com) within
* 30 days of such modification.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL EDWARD B. HAMRICK BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
* THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "crc32.h"
/* This is a pre-computed table to make crc computations efficient */
static unsigned long crctable[] = {
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL,
0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L,
0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L,
0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L,
0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L,
0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL,
0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L,
0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L,
0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L,
0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L,
0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L,
0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL,
0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL,
0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL,
0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L,
0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L,
0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL,
0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L,
0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL,
0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L,
0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL,
0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L,
0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L,
0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L,
0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L,
0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL,
0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL,
0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L,
0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L,
0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL,
0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L,
0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL,
0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L,
0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL,
0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L,
0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L,
0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL,
0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L,
0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL,
0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL,
0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L,
0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L,
0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL,
0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L,
0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L,
0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L,
0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL,
0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L,
0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L,
0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL,
0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L,
0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL
};
/*
* This CRC algorithm is the same as that used in zip. Normally it
* should be initialized with 0xffffffff, and the final CRC stored
* should be crc ^ 0xffffffff.
*
* It implements the polynomial:
*
* x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1
*/
unsigned long CrcUpdate( /* returns updated crc */
unsigned long crc, /* starting crc */
unsigned char *buffer, /* buffer to use to update crc */
long length /* length of buffer */
)
{
long i;
for (i=0; i<length; i++)
{
crc = crctable[buffer[i] ^ ((unsigned char) crc)] ^ (crc >> 8);
}
return crc;
}

53
libmultihash/crc32.h Normal file
View file

@ -0,0 +1,53 @@
/*
* Copyright (c) 1995, Edward B. Hamrick
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee, provided
* that
*
* (i) the above copyright notice and the text in this "C" comment block
* appear in all copies of the software and related documentation, and
*
* (ii) any modifications to this source file must be sent, via e-mail
* to the copyright owner (currently hamrick@primenet.com) within
* 30 days of such modification.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL EDWARD B. HAMRICK BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
* THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* This CRC algorithm is the same as that used in zip. Normally it
* should be initialized with 0xffffffff, and the final CRC stored
* should be crc ^ 0xffffffff.
*
* It implements the polynomial:
*
* x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1
*/
#ifndef __CRC_H
#define __CRC_H
#ifdef __cplusplus
extern "C" {
#endif
unsigned long CrcUpdate( /* returns updated crc */
unsigned long crc, /* starting crc */
unsigned char *buffer, /* buffer to use to update crc */
long length /* length of buffer */
);
#ifdef __cplusplus
}
#endif
#endif

83
libmultihash/edonkey.c Normal file
View file

@ -0,0 +1,83 @@
/***************************************************************************
* Copyright (C) 2007 by SukkoPera *
* sukkopera@sukkology.net *
* *
* 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. *
***************************************************************************/
/* As Wikipedia (http://en.wikipedia.org/wiki/Ed2k_link) says:
* The ed2k hash function is a MD4 root hash of a MD4 hash list, and gives a
* different result than simply MD4: The file data is divided into full
* chunks of 9728000 bytes plus a remainder chunk, and a separate 128-bit
* MD4 checksum is computed for each. The ed2k hash is computed by
* concatenating the chunks' MD4 checksums in order and hashing the result
*using MD4.
*/
#include <stdio.h>
#include "edonkey.h"
#include "md4.h"
void ed2khash_starts (ed2khash_context *ctx) {
md4_starts (&(ctx -> md4cur));
md4_starts (&(ctx -> md4final));
ctx -> bytes_processed = 0;
ctx -> chunks = 0;
return;
}
void ed2khash_update (ed2khash_context *ctx, unsigned char *input, int ilen) {
unsigned long x;
while (ilen > 0) {
if (ctx -> bytes_processed + ilen >= ED2KHASH_CHUNKSIZE)
x = ED2KHASH_CHUNKSIZE - ctx -> bytes_processed;
else
x = ilen;
md4_update (&(ctx -> md4cur), input, x);
if ((ctx -> bytes_processed += x) % ED2KHASH_CHUNKSIZE == 0) {
/* End of a chunk, save current MD4 and start a new one */
md4_finish (&(ctx -> md4cur), ctx -> lastmd4);
md4_starts (&(ctx -> md4cur));
ctx -> bytes_processed = 0;
ctx -> chunks++;
md4_update (&(ctx -> md4final), ctx -> lastmd4, MD4_DIGESTSIZE);
}
ilen -= x;
input += x;
}
return;
}
void ed2khash_finish (ed2khash_context *ctx, unsigned char *output) {
if (ctx -> chunks > 0) {
md4_finish (&(ctx -> md4cur), ctx -> lastmd4);
md4_update (&(ctx -> md4final), ctx -> lastmd4, MD4_DIGESTSIZE);
md4_finish (&(ctx -> md4final), output);
} else {
/* If we have a single chunk, use its MD4 straight away */
md4_finish (&(ctx -> md4cur), output);
}
return;
}

36
libmultihash/edonkey.h Normal file
View file

@ -0,0 +1,36 @@
/***************************************************************************
* Copyright (C) 2007 by SukkoPera *
* sukkopera@sukkology.net *
* *
* 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 "md4.h"
#define ED2KHASH_CHUNKSIZE 9728000
#define MD4_DIGESTSIZE 16
typedef struct {
unsigned long bytes_processed;
unsigned int chunks;
md4_context md4cur;
md4_context md4final;
unsigned char lastmd4[MD4_DIGESTSIZE];
} ed2khash_context;
void ed2khash_starts (ed2khash_context *ctx);
void ed2khash_update (ed2khash_context *ctx, unsigned char *input, int ilen);
void ed2khash_finish (ed2khash_context *ctx, unsigned char *output);

441
libmultihash/md4.c Normal file
View file

@ -0,0 +1,441 @@
/*
* RFC 1186/1320 compliant MD4 implementation
*
* Copyright (C) 2006-2007 Christophe Devine
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License, version 2.1 as published by the Free Software Foundation.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
/*
* The MD4 algorithm was designed by Ron Rivest in 1990.
*
* http://www.ietf.org/rfc/rfc1186.txt
* http://www.ietf.org/rfc/rfc1320.txt
*/
#ifndef _CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_DEPRECATE 1
#endif
#include <string.h>
#include <stdio.h>
#include "md4.h"
/*
* 32-bit integer manipulation macros (little endian)
*/
#ifndef GET_UINT32_LE
#define GET_UINT32_LE(n,b,i) \
{ \
(n) = ( (unsigned long) (b)[(i) ] ) \
| ( (unsigned long) (b)[(i) + 1] << 8 ) \
| ( (unsigned long) (b)[(i) + 2] << 16 ) \
| ( (unsigned long) (b)[(i) + 3] << 24 ); \
}
#endif
#ifndef PUT_UINT32_LE
#define PUT_UINT32_LE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( (n) ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
}
#endif
/*
* MD4 context setup
*/
void md4_starts( md4_context *ctx )
{
ctx->total[0] = 0;
ctx->total[1] = 0;
ctx->state[0] = 0x67452301;
ctx->state[1] = 0xEFCDAB89;
ctx->state[2] = 0x98BADCFE;
ctx->state[3] = 0x10325476;
}
static void md4_process( md4_context *ctx, unsigned char data[64] )
{
unsigned long X[16], A, B, C, D;
GET_UINT32_LE( X[ 0], data, 0 );
GET_UINT32_LE( X[ 1], data, 4 );
GET_UINT32_LE( X[ 2], data, 8 );
GET_UINT32_LE( X[ 3], data, 12 );
GET_UINT32_LE( X[ 4], data, 16 );
GET_UINT32_LE( X[ 5], data, 20 );
GET_UINT32_LE( X[ 6], data, 24 );
GET_UINT32_LE( X[ 7], data, 28 );
GET_UINT32_LE( X[ 8], data, 32 );
GET_UINT32_LE( X[ 9], data, 36 );
GET_UINT32_LE( X[10], data, 40 );
GET_UINT32_LE( X[11], data, 44 );
GET_UINT32_LE( X[12], data, 48 );
GET_UINT32_LE( X[13], data, 52 );
GET_UINT32_LE( X[14], data, 56 );
GET_UINT32_LE( X[15], data, 60 );
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
#define F(x, y, z) ((x & y) | ((~x) & z))
#define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); }
P( A, B, C, D, X[ 0], 3 );
P( D, A, B, C, X[ 1], 7 );
P( C, D, A, B, X[ 2], 11 );
P( B, C, D, A, X[ 3], 19 );
P( A, B, C, D, X[ 4], 3 );
P( D, A, B, C, X[ 5], 7 );
P( C, D, A, B, X[ 6], 11 );
P( B, C, D, A, X[ 7], 19 );
P( A, B, C, D, X[ 8], 3 );
P( D, A, B, C, X[ 9], 7 );
P( C, D, A, B, X[10], 11 );
P( B, C, D, A, X[11], 19 );
P( A, B, C, D, X[12], 3 );
P( D, A, B, C, X[13], 7 );
P( C, D, A, B, X[14], 11 );
P( B, C, D, A, X[15], 19 );
#undef P
#undef F
#define F(x,y,z) ((x & y) | (x & z) | (y & z))
#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); }
P( A, B, C, D, X[ 0], 3 );
P( D, A, B, C, X[ 4], 5 );
P( C, D, A, B, X[ 8], 9 );
P( B, C, D, A, X[12], 13 );
P( A, B, C, D, X[ 1], 3 );
P( D, A, B, C, X[ 5], 5 );
P( C, D, A, B, X[ 9], 9 );
P( B, C, D, A, X[13], 13 );
P( A, B, C, D, X[ 2], 3 );
P( D, A, B, C, X[ 6], 5 );
P( C, D, A, B, X[10], 9 );
P( B, C, D, A, X[14], 13 );
P( A, B, C, D, X[ 3], 3 );
P( D, A, B, C, X[ 7], 5 );
P( C, D, A, B, X[11], 9 );
P( B, C, D, A, X[15], 13 );
#undef P
#undef F
#define F(x,y,z) (x ^ y ^ z)
#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); }
P( A, B, C, D, X[ 0], 3 );
P( D, A, B, C, X[ 8], 9 );
P( C, D, A, B, X[ 4], 11 );
P( B, C, D, A, X[12], 15 );
P( A, B, C, D, X[ 2], 3 );
P( D, A, B, C, X[10], 9 );
P( C, D, A, B, X[ 6], 11 );
P( B, C, D, A, X[14], 15 );
P( A, B, C, D, X[ 1], 3 );
P( D, A, B, C, X[ 9], 9 );
P( C, D, A, B, X[ 5], 11 );
P( B, C, D, A, X[13], 15 );
P( A, B, C, D, X[ 3], 3 );
P( D, A, B, C, X[11], 9 );
P( C, D, A, B, X[ 7], 11 );
P( B, C, D, A, X[15], 15 );
#undef F
#undef P
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
}
/*
* MD4 process buffer
*/
void md4_update( md4_context *ctx, unsigned char *input, int ilen )
{
int fill;
unsigned long left;
if( ilen <= 0 )
return;
left = ctx->total[0] & 0x3F;
fill = 64 - left;
ctx->total[0] += ilen;
ctx->total[0] &= 0xFFFFFFFF;
if( ctx->total[0] < (unsigned long) ilen )
ctx->total[1]++;
if( left && ilen >= fill )
{
memcpy( (void *) (ctx->buffer + left),
(void *) input, fill );
md4_process( ctx, ctx->buffer );
input += fill;
ilen -= fill;
left = 0;
}
while( ilen >= 64 )
{
md4_process( ctx, input );
input += 64;
ilen -= 64;
}
if( ilen > 0 )
{
memcpy( (void *) (ctx->buffer + left),
(void *) input, ilen );
}
}
static const unsigned char md4_padding[64] =
{
0x80, 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
};
/*
* MD4 final digest
*/
void md4_finish( md4_context *ctx, unsigned char *output )
{
unsigned long last, padn;
unsigned long high, low;
unsigned char msglen[8];
high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_UINT32_LE( low, msglen, 0 );
PUT_UINT32_LE( high, msglen, 4 );
last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
md4_update( ctx, (unsigned char *) md4_padding, padn );
md4_update( ctx, msglen, 8 );
PUT_UINT32_LE( ctx->state[0], output, 0 );
PUT_UINT32_LE( ctx->state[1], output, 4 );
PUT_UINT32_LE( ctx->state[2], output, 8 );
PUT_UINT32_LE( ctx->state[3], output, 12 );
}
/*
* Output = MD4( input buffer )
*/
void md4( unsigned char *input, int ilen,
unsigned char *output )
{
md4_context ctx;
md4_starts( &ctx );
md4_update( &ctx, input, ilen );
md4_finish( &ctx, output );
memset( &ctx, 0, sizeof( md4_context ) );
}
/*
* Output = MD4( file contents )
*/
int md4_file( char *path, unsigned char *output )
{
FILE *f;
size_t n;
md4_context ctx;
unsigned char buf[1024];
if( ( f = fopen( path, "rb" ) ) == NULL )
return( 1 );
md4_starts( &ctx );
while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
md4_update( &ctx, buf, (int) n );
md4_finish( &ctx, output );
memset( &ctx, 0, sizeof( md4_context ) );
if( ferror( f ) != 0 )
{
fclose( f );
return( 2 );
}
fclose( f );
return( 0 );
}
/*
* MD4 HMAC context setup
*/
void md4_hmac_starts( md4_context *ctx,
unsigned char *key, int keylen )
{
int i;
memset( ctx->ipad, 0x36, 64 );
memset( ctx->opad, 0x5C, 64 );
for( i = 0; i < keylen; i++ )
{
if( i >= 64 ) break;
ctx->ipad[i] ^= key[i];
ctx->opad[i] ^= key[i];
}
md4_starts( ctx );
md4_update( ctx, ctx->ipad, 64 );
}
/*
* MD4 HMAC process buffer
*/
void md4_hmac_update( md4_context *ctx,
unsigned char *input, int ilen )
{
md4_update( ctx, input, ilen );
}
/*
* MD4 HMAC final digest
*/
void md4_hmac_finish( md4_context *ctx, unsigned char *output )
{
unsigned char tmpbuf[16];
md4_finish( ctx, tmpbuf );
md4_starts( ctx );
md4_update( ctx, ctx->opad, 64 );
md4_update( ctx, tmpbuf, 16 );
md4_finish( ctx, output );
memset( tmpbuf, 0, sizeof( tmpbuf ) );
}
/*
* Output = HMAC-MD4( hmac key, input buffer )
*/
void md4_hmac( unsigned char *key, int keylen,
unsigned char *input, int ilen,
unsigned char *output )
{
md4_context ctx;
md4_hmac_starts( &ctx, key, keylen );
md4_hmac_update( &ctx, input, ilen );
md4_hmac_finish( &ctx, output );
memset( &ctx, 0, sizeof( md4_context ) );
}
static const char _md4_src[] = "_md4_src";
#if defined(SELF_TEST)
/*
* RFC 1320 test vectors
*/
static const char md4_test_str[7][81] =
{
{ "" },
{ "a" },
{ "abc" },
{ "message digest" },
{ "abcdefghijklmnopqrstuvwxyz" },
{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
{ "12345678901234567890123456789012345678901234567890123456789012" \
"345678901234567890" }
};
static const unsigned char md4_test_sum[7][16] =
{
{ 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
{ 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
{ 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
{ 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
{ 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
{ 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
{ 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
};
/*
* Checkup routine
*/
int md4_self_test( int verbose )
{
int i;
unsigned char md4sum[16];
for( i = 0; i < 7; i++ )
{
if( verbose != 0 )
printf( " MD4 test #%d: ", i + 1 );
md4( (unsigned char *) md4_test_str[i],
strlen( md4_test_str[i] ), md4sum );
if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
if( verbose != 0 )
printf( "passed\n" );
}
if( verbose != 0 )
printf( "\n" );
return( 0 );
}
#else
int md4_self_test( int verbose )
{
return( 0 );
}
#endif

121
libmultihash/md4.h Normal file
View file

@ -0,0 +1,121 @@
/**
* \file md4.h
*/
#ifndef _MD4_H
#define _MD4_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief MD4 context structure
*/
typedef struct
{
unsigned long total[2]; /*!< number of bytes processed */
unsigned long state[4]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */
unsigned char ipad[64]; /*!< HMAC: inner padding */
unsigned char opad[64]; /*!< HMAC: outer padding */
}
md4_context;
/**
* \brief MD4 context setup
*
* \param ctx context to be initialized
*/
void md4_starts( md4_context *ctx );
/**
* \brief MD4 process buffer
*
* \param ctx MD4 context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void md4_update( md4_context *ctx, unsigned char *input, int ilen );
/**
* \brief MD4 final digest
*
* \param ctx MD4 context
* \param output MD4 checksum result
*/
void md4_finish( md4_context *ctx, unsigned char *output );
/**
* \brief Output = MD4( input buffer )
*
* \param input buffer holding the data
* \param ilen length of the input data
* \param output MD4 checksum result
*/
void md4( unsigned char *input, int ilen,
unsigned char *output );
/**
* \brief Output = MD4( file contents )
*
* \param path input file name
* \param output MD4 checksum result
*
* \return 0 if successful, 1 if fopen failed,
* or 2 if fread failed
*/
int md4_file( char *path, unsigned char *output );
/**
* \brief MD4 HMAC context setup
*
* \param ctx HMAC context to be initialized
* \param key HMAC secret key
* \param keylen length of the HMAC key
*/
void md4_hmac_starts( md4_context *ctx,
unsigned char *key, int keylen );
/**
* \brief MD4 HMAC process buffer
*
* \param ctx HMAC context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void md4_hmac_update( md4_context *ctx,
unsigned char *input, int ilen );
/**
* \brief MD4 HMAC final digest
*
* \param ctx HMAC context
* \param output MD4 HMAC checksum result
*/
void md4_hmac_finish( md4_context *ctx, unsigned char *output );
/**
* \brief Output = HMAC-MD4( hmac key, input buffer )
*
* \param key HMAC secret key
* \param keylen length of the HMAC key
* \param input buffer holding the data
* \param ilen length of the input data
* \param output HMAC-MD4 result
*/
void md4_hmac( unsigned char *key, int keylen,
unsigned char *input, int ilen,
unsigned char *output );
/**
* \brief Checkup routine
*
* \return 0 if successful, or 1 if the test failed
*/
int md4_self_test( int verbose );
#ifdef __cplusplus
}
#endif
#endif /* md4.h */

477
libmultihash/md5.c Normal file
View file

@ -0,0 +1,477 @@
/*
**********************************************************************
** md5.c **
** RSA Data Security, Inc. MD5 Message Digest Algorithm **
** Created: 2/17/90 RLR **
** Revised: 1/91 SRD,AJ,BSK,JT Reference C Version **
**********************************************************************
*/
/*
**********************************************************************
** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
** **
** License to copy and use this software is granted provided that **
** it is identified as the "RSA Data Security, Inc. MD5 Message **
** Digest Algorithm" in all material mentioning or referencing this **
** software or this function. **
** **
** License is also granted to make and use derivative works **
** provided that such works are identified as "derived from the RSA **
** Data Security, Inc. MD5 Message Digest Algorithm" in all **
** material mentioning or referencing the derived work. **
** **
** RSA Data Security, Inc. makes no representations concerning **
** either the merchantability of this software or the suitability **
** of this software for any particular purpose. It is provided "as **
** is" without express or implied warranty of any kind. **
** **
** These notices must be retained in any copies of any part of this **
** documentation and/or software. **
**********************************************************************
*/
/* -- include the following line if the md5.h header file is separate -- */
#include "md5.h"
/* forward declaration */
static void Transform ();
static unsigned char PADDING[64] = {
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/* F, G and H are basic MD5 functions: selection, majority, parity */
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))
/* ROTATE_LEFT rotates x left n bits */
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */
/* Rotation is separate from addition to prevent recomputation */
#define FF(a, b, c, d, x, s, ac) \
{(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define GG(a, b, c, d, x, s, ac) \
{(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define HH(a, b, c, d, x, s, ac) \
{(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define II(a, b, c, d, x, s, ac) \
{(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
void MD5Init (mdContext)
MD5_CTX *mdContext;
{
mdContext->i[0] = mdContext->i[1] = (UINT4)0;
/* Load magic initialization constants.
*/
mdContext->buf[0] = (UINT4)0x67452301;
mdContext->buf[1] = (UINT4)0xefcdab89;
mdContext->buf[2] = (UINT4)0x98badcfe;
mdContext->buf[3] = (UINT4)0x10325476;
}
void MD5Update (mdContext, inBuf, inLen)
MD5_CTX *mdContext;
unsigned char *inBuf;
unsigned int inLen;
{
UINT4 in[16];
int mdi;
unsigned int i, ii;
/* compute number of bytes mod 64 */
mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
/* update number of bits */
if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0])
mdContext->i[1]++;
mdContext->i[0] += ((UINT4)inLen << 3);
mdContext->i[1] += ((UINT4)inLen >> 29);
while (inLen--) {
/* add new character to buffer, increment mdi */
mdContext->in[mdi++] = *inBuf++;
/* transform if necessary */
if (mdi == 0x40) {
for (i = 0, ii = 0; i < 16; i++, ii += 4)
in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
(((UINT4)mdContext->in[ii+2]) << 16) |
(((UINT4)mdContext->in[ii+1]) << 8) |
((UINT4)mdContext->in[ii]);
Transform (mdContext->buf, in);
mdi = 0;
}
}
}
void MD5Final (mdContext)
MD5_CTX *mdContext;
{
UINT4 in[16];
int mdi;
unsigned int i, ii;
unsigned int padLen;
/* save number of bits */
in[14] = mdContext->i[0];
in[15] = mdContext->i[1];
/* compute number of bytes mod 64 */
mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
/* pad out to 56 mod 64 */
padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi);
MD5Update (mdContext, PADDING, padLen);
/* append length in bits and transform */
for (i = 0, ii = 0; i < 14; i++, ii += 4)
in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
(((UINT4)mdContext->in[ii+2]) << 16) |
(((UINT4)mdContext->in[ii+1]) << 8) |
((UINT4)mdContext->in[ii]);
Transform (mdContext->buf, in);
/* store buffer in digest */
for (i = 0, ii = 0; i < 4; i++, ii += 4) {
mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF);
mdContext->digest[ii+1] =
(unsigned char)((mdContext->buf[i] >> 8) & 0xFF);
mdContext->digest[ii+2] =
(unsigned char)((mdContext->buf[i] >> 16) & 0xFF);
mdContext->digest[ii+3] =
(unsigned char)((mdContext->buf[i] >> 24) & 0xFF);
}
}
/* Basic MD5 step. Transform buf based on in.
*/
static void Transform (buf, in)
UINT4 *buf;
UINT4 *in;
{
UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
/* Round 1 */
#define S11 7
#define S12 12
#define S13 17
#define S14 22
FF ( a, b, c, d, in[ 0], S11, 3614090360U); /* 1 */
FF ( d, a, b, c, in[ 1], S12, 3905402710U); /* 2 */
FF ( c, d, a, b, in[ 2], S13, 606105819U); /* 3 */
FF ( b, c, d, a, in[ 3], S14, 3250441966U); /* 4 */
FF ( a, b, c, d, in[ 4], S11, 4118548399U); /* 5 */
FF ( d, a, b, c, in[ 5], S12, 1200080426U); /* 6 */
FF ( c, d, a, b, in[ 6], S13, 2821735955U); /* 7 */
FF ( b, c, d, a, in[ 7], S14, 4249261313U); /* 8 */
FF ( a, b, c, d, in[ 8], S11, 1770035416U); /* 9 */
FF ( d, a, b, c, in[ 9], S12, 2336552879U); /* 10 */
FF ( c, d, a, b, in[10], S13, 4294925233U); /* 11 */
FF ( b, c, d, a, in[11], S14, 2304563134U); /* 12 */
FF ( a, b, c, d, in[12], S11, 1804603682U); /* 13 */
FF ( d, a, b, c, in[13], S12, 4254626195U); /* 14 */
FF ( c, d, a, b, in[14], S13, 2792965006U); /* 15 */
FF ( b, c, d, a, in[15], S14, 1236535329U); /* 16 */
/* Round 2 */
#define S21 5
#define S22 9
#define S23 14
#define S24 20
GG ( a, b, c, d, in[ 1], S21, 4129170786U); /* 17 */
GG ( d, a, b, c, in[ 6], S22, 3225465664U); /* 18 */
GG ( c, d, a, b, in[11], S23, 643717713U); /* 19 */
GG ( b, c, d, a, in[ 0], S24, 3921069994U); /* 20 */
GG ( a, b, c, d, in[ 5], S21, 3593408605U); /* 21 */
GG ( d, a, b, c, in[10], S22, 38016083U); /* 22 */
GG ( c, d, a, b, in[15], S23, 3634488961U); /* 23 */
GG ( b, c, d, a, in[ 4], S24, 3889429448U); /* 24 */
GG ( a, b, c, d, in[ 9], S21, 568446438U); /* 25 */
GG ( d, a, b, c, in[14], S22, 3275163606U); /* 26 */
GG ( c, d, a, b, in[ 3], S23, 4107603335U); /* 27 */
GG ( b, c, d, a, in[ 8], S24, 1163531501U); /* 28 */
GG ( a, b, c, d, in[13], S21, 2850285829U); /* 29 */
GG ( d, a, b, c, in[ 2], S22, 4243563512U); /* 30 */
GG ( c, d, a, b, in[ 7], S23, 1735328473U); /* 31 */
GG ( b, c, d, a, in[12], S24, 2368359562U); /* 32 */
/* Round 3 */
#define S31 4
#define S32 11
#define S33 16
#define S34 23
HH ( a, b, c, d, in[ 5], S31, 4294588738U); /* 33 */
HH ( d, a, b, c, in[ 8], S32, 2272392833U); /* 34 */
HH ( c, d, a, b, in[11], S33, 1839030562U); /* 35 */
HH ( b, c, d, a, in[14], S34, 4259657740U); /* 36 */
HH ( a, b, c, d, in[ 1], S31, 2763975236U); /* 37 */
HH ( d, a, b, c, in[ 4], S32, 1272893353U); /* 38 */
HH ( c, d, a, b, in[ 7], S33, 4139469664U); /* 39 */
HH ( b, c, d, a, in[10], S34, 3200236656U); /* 40 */
HH ( a, b, c, d, in[13], S31, 681279174U); /* 41 */
HH ( d, a, b, c, in[ 0], S32, 3936430074U); /* 42 */
HH ( c, d, a, b, in[ 3], S33, 3572445317U); /* 43 */
HH ( b, c, d, a, in[ 6], S34, 76029189U); /* 44 */
HH ( a, b, c, d, in[ 9], S31, 3654602809U); /* 45 */
HH ( d, a, b, c, in[12], S32, 3873151461U); /* 46 */
HH ( c, d, a, b, in[15], S33, 530742520U); /* 47 */
HH ( b, c, d, a, in[ 2], S34, 3299628645U); /* 48 */
/* Round 4 */
#define S41 6
#define S42 10
#define S43 15
#define S44 21
II ( a, b, c, d, in[ 0], S41, 4096336452U); /* 49 */
II ( d, a, b, c, in[ 7], S42, 1126891415U); /* 50 */
II ( c, d, a, b, in[14], S43, 2878612391U); /* 51 */
II ( b, c, d, a, in[ 5], S44, 4237533241U); /* 52 */
II ( a, b, c, d, in[12], S41, 1700485571U); /* 53 */
II ( d, a, b, c, in[ 3], S42, 2399980690U); /* 54 */
II ( c, d, a, b, in[10], S43, 4293915773U); /* 55 */
II ( b, c, d, a, in[ 1], S44, 2240044497U); /* 56 */
II ( a, b, c, d, in[ 8], S41, 1873313359U); /* 57 */
II ( d, a, b, c, in[15], S42, 4264355552U); /* 58 */
II ( c, d, a, b, in[ 6], S43, 2734768916U); /* 59 */
II ( b, c, d, a, in[13], S44, 1309151649U); /* 60 */
II ( a, b, c, d, in[ 4], S41, 4149444226U); /* 61 */
II ( d, a, b, c, in[11], S42, 3174756917U); /* 62 */
II ( c, d, a, b, in[ 2], S43, 718787259U); /* 63 */
II ( b, c, d, a, in[ 9], S44, 3951481745U); /* 64 */
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
}
/*
**********************************************************************
** End of md5.c **
******************************* (cut) ********************************
*/
#if 0
/*
**********************************************************************
** md5driver.c -- sample routines to test **
** RSA Data Security, Inc. MD5 message digest algorithm. **
** Created: 2/16/90 RLR **
** Updated: 1/91 SRD **
**********************************************************************
*/
/*
**********************************************************************
** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
** **
** RSA Data Security, Inc. makes no representations concerning **
** either the merchantability of this software or the suitability **
** of this software for any particular purpose. It is provided "as **
** is" without express or implied warranty of any kind. **
** **
** These notices must be retained in any copies of any part of this **
** documentation and/or software. **
**********************************************************************
*/
#include <stdio.h>
#include <sys/types.h>
#include <time.h>
#include <string.h>
/* -- include the following file if the file md5.h is separate -- */
/* #include "md5.h" */
/* Prints message digest buffer in mdContext as 32 hexadecimal digits.
Order is from low-order byte to high-order byte of digest.
Each byte is printed with high-order hexadecimal digit first.
*/
static void MDPrint (mdContext)
MD5_CTX *mdContext;
{
int i;
for (i = 0; i < 16; i++)
printf ("%02x", mdContext->digest[i]);
}
/* size of test block */
#define TEST_BLOCK_SIZE 1000
/* number of blocks to process */
#define TEST_BLOCKS 10000
/* number of test bytes = TEST_BLOCK_SIZE * TEST_BLOCKS */
static long TEST_BYTES = (long)TEST_BLOCK_SIZE * (long)TEST_BLOCKS;
/* A time trial routine, to measure the speed of MD5.
Measures wall time required to digest TEST_BLOCKS * TEST_BLOCK_SIZE
characters.
*/
static void MDTimeTrial ()
{
MD5_CTX mdContext;
time_t endTime, startTime;
unsigned char data[TEST_BLOCK_SIZE];
unsigned int i;
/* initialize test data */
for (i = 0; i < TEST_BLOCK_SIZE; i++)
data[i] = (unsigned char)(i & 0xFF);
/* start timer */
printf ("MD5 time trial. Processing %ld characters...\n", TEST_BYTES);
time (&startTime);
/* digest data in TEST_BLOCK_SIZE byte blocks */
MD5Init (&mdContext);
for (i = TEST_BLOCKS; i > 0; i--)
MD5Update (&mdContext, data, TEST_BLOCK_SIZE);
MD5Final (&mdContext);
/* stop timer, get time difference */
time (&endTime);
MDPrint (&mdContext);
printf (" is digest of test input.\n");
printf
("Seconds to process test input: %ld\n", (long)(endTime-startTime));
printf
("Characters processed per second: %ld\n",
TEST_BYTES/(endTime-startTime));
}
/* Computes the message digest for string inString.
Prints out message digest, a space, the string (in quotes) and a
carriage return.
*/
static void MDString (inString)
char *inString;
{
MD5_CTX mdContext;
unsigned int len = strlen (inString);
MD5Init (&mdContext);
MD5Update (&mdContext, inString, len);
MD5Final (&mdContext);
MDPrint (&mdContext);
printf (" \"%s\"\n\n", inString);
}
/* Computes the message digest for a specified file.
Prints out message digest, a space, the file name, and a carriage
return.
*/
static void MDFile (filename)
char *filename;
{
FILE *inFile = fopen (filename, "rb");
MD5_CTX mdContext;
int bytes;
unsigned char data[1024];
if (inFile == NULL) {
printf ("%s can't be opened.\n", filename);
return;
}
MD5Init (&mdContext);
while ((bytes = fread (data, 1, 1024, inFile)) != 0)
MD5Update (&mdContext, data, bytes);
MD5Final (&mdContext);
MDPrint (&mdContext);
printf (" %s\n", filename);
fclose (inFile);
}
/* Writes the message digest of the data from stdin onto stdout,
followed by a carriage return.
*/
static void MDFilter ()
{
MD5_CTX mdContext;
int bytes;
unsigned char data[16];
MD5Init (&mdContext);
while ((bytes = fread (data, 1, 16, stdin)) != 0)
MD5Update (&mdContext, data, bytes);
MD5Final (&mdContext);
MDPrint (&mdContext);
printf ("\n");
}
/* Runs a standard suite of test data.
*/
static void MDTestSuite ()
{
printf ("MD5 test suite results:\n\n");
MDString ("");
MDString ("a");
MDString ("abc");
MDString ("message digest");
MDString ("abcdefghijklmnopqrstuvwxyz");
MDString
("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
MDString
("1234567890123456789012345678901234567890\
1234567890123456789012345678901234567890");
/* Contents of file foo are "abc" */
MDFile ("foo");
}
void main (argc, argv)
int argc;
char *argv[];
{
int i;
/* For each command line argument in turn:
** filename -- prints message digest and name of file
** -sstring -- prints message digest and contents of string
** -t -- prints time trial statistics for 1M characters
** -x -- execute a standard suite of test data
** (no args) -- writes messages digest of stdin onto stdout
*/
if (argc == 1)
MDFilter ();
else
for (i = 1; i < argc; i++)
if (argv[i][0] == '-' && argv[i][1] == 's')
MDString (argv[i] + 2);
else if (strcmp (argv[i], "-t") == 0)
MDTimeTrial ();
else if (strcmp (argv[i], "-x") == 0)
MDTestSuite ();
else MDFile (argv[i]);
}
/*
**********************************************************************
** End of md5driver.c **
******************************* (cut) ********************************
*/
#endif

59
libmultihash/md5.h Normal file
View file

@ -0,0 +1,59 @@
/*
**********************************************************************
** md5.h -- Header file for implementation of MD5 **
** RSA Data Security, Inc. MD5 Message Digest Algorithm **
** Created: 2/17/90 RLR **
** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version **
** Revised (for MD5): RLR 4/27/91 **
** -- G modified to have y&~z instead of y&z **
** -- FF, GG, HH modified to add in last register done **
** -- Access pattern: round 2 works mod 5, round 3 works mod 3 **
** -- distinct additive constant for each step **
** -- round 4 added, working mod 7 **
**********************************************************************
*/
/*
**********************************************************************
** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
** **
** License to copy and use this software is granted provided that **
** it is identified as the "RSA Data Security, Inc. MD5 Message **
** Digest Algorithm" in all material mentioning or referencing this **
** software or this function. **
** **
** License is also granted to make and use derivative works **
** provided that such works are identified as "derived from the RSA **
** Data Security, Inc. MD5 Message Digest Algorithm" in all **
** material mentioning or referencing the derived work. **
** **
** RSA Data Security, Inc. makes no representations concerning **
** either the merchantability of this software or the suitability **
** of this software for any particular purpose. It is provided "as **
** is" without express or implied warranty of any kind. **
** **
** These notices must be retained in any copies of any part of this **
** documentation and/or software. **
**********************************************************************
*/
/* typedef a 32 bit type */
typedef unsigned long int UINT4;
/* Data structure for MD5 (Message Digest) computation */
typedef struct {
UINT4 i[2]; /* number of _bits_ handled mod 2^64 */
UINT4 buf[4]; /* scratch buffer */
unsigned char in[64]; /* input buffer */
unsigned char digest[16]; /* actual digest after MD5Final call */
} MD5_CTX;
void MD5Init ();
void MD5Update ();
void MD5Final ();
/*
**********************************************************************
** End of md5.h **
******************************* (cut) ********************************
*/

130
libmultihash/multihash.c Normal file
View file

@ -0,0 +1,130 @@
/***************************************************************************
* Copyright (C) 2007 by SukkoPera *
* sukkopera@sukkology.net *
* *
* 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 "multihash.h"
#include <stdio.h>
#define READBUF_SIZE 8192
void multihash_init (multihash *mh) {
#ifdef USE_CRC32
(mh -> crc32_s)[0] = '\0';
mh -> crc32 = 0xffffffff;
#endif
#ifdef USE_MD4
(mh -> md4_s)[0] = '\0';
md4_starts (&(mh -> md4));
#endif
#ifdef USE_MD5
(mh -> md5_s)[0] = '\0';
MD5Init (&(mh -> md5));
#endif
#ifdef USE_ED2K
(mh -> ed2k_s)[0] = '\0';
ed2khash_starts (&(mh -> ed2k));
#endif
#ifdef USE_SHA1
(mh -> sha1_s)[0] = '\0';
SHA1Init (&(mh -> sha1));
#endif
return;
}
void multihash_update (multihash *mh, unsigned char *data, int bytes) {
#ifdef USE_CRC32
mh -> crc32 = CrcUpdate (mh -> crc32, data, bytes);
#endif
#ifdef USE_MD4
// md4_update (&(mh -> md4), data, bytes);
#endif
#ifdef USE_MD5
MD5Update (&(mh -> md5), data, bytes);
#endif
#ifdef USE_ED2K
// ed2khash_update (&(mh -> ed2k), data, bytes);
#endif
#ifdef USE_SHA1
SHA1Update (&(mh -> sha1), data, bytes); /* WARNING: SHA1Update() destroys data! */
#endif
return;
}
void multihash_finish (multihash *mh) {
unsigned char buf[MAX_DIGESTSIZE];
int bytes;
#ifdef USE_CRC32
mh -> crc32 ^= 0xffffffff;
snprintf (mh -> crc32_s, LEN_CRC32 + 1, "%08x", mh -> crc32);
#endif
#ifdef USE_MD4
md4_finish (&(mh -> md4), buf);
for (bytes = 0; bytes < LEN_MD4 / 2; bytes++)
sprintf (mh -> md4_s, "%s%02x", mh -> md4_s, buf[bytes]);
(mh -> md4_s)[LEN_MD4] = '\0';
#endif
#ifdef USE_MD5
MD5Final (&(mh -> md5));
for (bytes = 0; bytes < LEN_MD5 / 2; bytes++)
sprintf (mh -> md5_s, "%s%02x", mh -> md5_s, (mh -> md5).digest[bytes]);
(mh -> md5_s)[LEN_MD5] = '\0';
#endif
#ifdef USE_ED2K
ed2khash_finish (&(mh -> ed2k), buf);
for (bytes = 0; bytes < LEN_ED2K / 2; bytes++)
sprintf (mh -> ed2k_s, "%s%02x", mh -> ed2k_s, buf[bytes]);
(mh -> ed2k_s)[LEN_ED2K] = '\0';
#endif
#ifdef USE_SHA1
SHA1Final (buf, &(mh -> sha1));
for (bytes = 0; bytes < LEN_SHA1 / 2; bytes++)
sprintf (mh -> sha1_s, "%s%02x", mh -> sha1_s, buf[bytes]);
(mh -> sha1_s)[LEN_SHA1] = '\0';
#endif
return;
}
int multihash_file (multihash *mh, char *filename) {
FILE *fp;
int bytes, out;
unsigned char data[READBUF_SIZE];
multihash_init (mh);
if ((fp = fopen (filename, "r"))) {
while ((bytes = fread (data, 1, READBUF_SIZE, fp)) != 0)
multihash_update (mh, data, bytes);
multihash_finish (mh);
fclose (fp);
out = 0;
} else {
/* Cannot open file */
out = -1;
}
return (out);
}

127
libmultihash/multihash.h Normal file
View file

@ -0,0 +1,127 @@
/***************************************************************************
* Copyright (C) 2007 by SukkoPera *
* sukkopera@sukkology.net *
* *
* 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 MULTIHASH_H_INCLUDED
#define MULTIHASH_H_INCLUDED
#ifdef WIN32
#include <windows.h>
/* Definition of the types we use for Windows */
#define u_int8_t BYTE
#define u_int16_t WORD
#define u_int32_t DWORD
/* Some functions have different names */
#define snprintf _snprintf
/* Stuff to export library symbols */
#ifdef MULTIHASH_BUILD_DLL
#ifdef MULTIHASH_EXPORTS
#define MULTIHASH_EXPORT __declspec(dllexport) /* Building the lib */
#else
#define MULTIHASH_EXPORT __declspec(dllimport) /* Building user code */
#endif
#else
#define MULTIHASH_EXPORT
#endif
#else /* !WIN32 */
#define MULTIHASH_EXPORT
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define USE_CRC32
#define USE_MD4
#define USE_MD5
#define USE_ED2K
#define USE_SHA1
#ifdef USE_CRC32
#include <sys/types.h>
#include "crc32.h"
#define LEN_CRC32 8
#endif
#ifdef USE_MD4
#include "md4.h"
#define LEN_MD4 32
#define MD4_DIGESTSIZE 16
#endif
#ifdef USE_MD5
#include "md5.h"
#define LEN_MD5 32
#endif
#ifdef USE_ED2K
#include "edonkey.h"
#define LEN_ED2K 32
#endif
#ifdef USE_SHA1
#include "sha1.h"
#define LEN_SHA1 40
#endif
/* This must be as long as the longest hash (in bytes) */
#define MAX_DIGESTSIZE 20
typedef struct {
#ifdef USE_CRC32
u_int32_t crc32;
char crc32_s[LEN_CRC32 + 1];
#endif
#ifdef USE_MD4
md4_context md4;
char md4_s[LEN_MD4 + 1];
#endif
#ifdef USE_MD5
MD5_CTX md5;
char md5_s[LEN_MD5 + 1];
#endif
#ifdef USE_ED2K
ed2khash_context ed2k;
char ed2k_s[LEN_ED2K + 1];
#endif
#ifdef USE_SHA1
SHA1_CTX sha1;
char sha1_s[LEN_SHA1 + 1];
#endif
} multihash;
/* Prototypes */
MULTIHASH_EXPORT void multihash_init (multihash *mh);
MULTIHASH_EXPORT void multihash_update (multihash *mh, unsigned char *data, int bytes);
MULTIHASH_EXPORT void multihash_finish (multihash *mh);
MULTIHASH_EXPORT int multihash_file (multihash *mh, char *filename);
#ifdef __cplusplus
}
#endif
#endif

231
libmultihash/sha1.c Normal file
View file

@ -0,0 +1,231 @@
/*
** sha1.c
**
** Contains all of the SHA1 functions: SHA1Transform, SHA1Init, SHA1Update, and SHA1Final.
** Make sure to define _LITTLE_ENDIAN if running on a little endian machine and NOT to
** define it otherwise.
**
** Copyright NTT MCL, 2000.
**
** Satomi Okazaki
** Security Group, NTT MCL
** November 1999
**
**************************
** 13 December 1999. In SHA1Transform, changed "buffer" to be const.
** In SHA1Update, changed "data to be const. -- S.O.
*/
#include "sha1.h"
#define _LITTLE_ENDIAN /* should be defined if so */
/* Rotation of "value" by "bits" to the left */
#define rotLeft(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
/* Basic SHA1 functions */
#define f(u,v,w) (((u) & (v)) | ((~u) & (w)))
#define g(u,v,w) (((u) & (v)) | ((u) & (w)) | ((v) & (w)))
#define h(u,v,w) ((u) ^ (v) ^ (w))
/* These are the 16 4-byte words of the 64-byte block */
#ifdef _LITTLE_ENDIAN
/* Reverse the order of the bytes in the i-th 4-byte word */
#define x(i) (block->l[i] = (rotLeft(block->l[i], 24)& 0xff00ff00) \
| (rotLeft(block->l[i], 8) & 0x00ff00ff))
#else
#define x(i) (block->l[i])
#endif
/* Used in expanding from a 16 word block into an 80 word block */
#define X(i) (block->l[(i)%16] = rotLeft (block->l[((i)-3)%16] ^ block->l[((i)-8)%16] \
^ block->l[((i)-14)%16] ^ block->l[((i)-16)%16],1))
/* (R0+R1), R2, R3, R4 are the different round operations used in SHA1 */
#define R0(a, b, c, d, e, i) { \
(e) += f((b), (c), (d)) + (x(i)) + 0x5A827999 + rotLeft((a),5); \
(b) = rotLeft((b), 30); \
}
#define R1(a, b, c, d, e, i) { \
(e) += f((b), (c), (d)) + (X(i)) + 0x5A827999 + rotLeft((a),5); \
(b) = rotLeft((b), 30); \
}
#define R2(a, b, c, d, e, i) { \
(e) += h((b), (c), (d)) + (X(i)) + 0x6ED9EBA1 + rotLeft((a),5); \
(b) = rotLeft((b), 30); \
}
#define R3(a, b, c, d, e, i) { \
(e) += g((b), (c), (d)) + (X(i)) + 0x8F1BBCDC + rotLeft((a),5); \
(b) = rotLeft((b), 30); \
}
#define R4(a, b, c, d, e, i) { \
(e) += h((b), (c), (d)) + (X(i)) + 0xCA62C1D6 + rotLeft((a),5); \
(b) = rotLeft((b), 30); \
}
/* Hashes a single 512-bit block. This is the compression function - the core of the algorithm.
**/
void SHA1Transform(
unsigned long state[5],
const unsigned char buffer[SHA1_BLOCKSIZE]
)
{
unsigned long a, b, c, d, e;
typedef union {
unsigned char c[64];
unsigned long l[16];
} CHAR64LONG16;
/* This is for the X array */
CHAR64LONG16* block = (CHAR64LONG16*)buffer;
/* Initialize working variables */
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
/* 4 rounds of 20 operations each. */
/* Round 1 */
R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e, 10); R0(e,a,b,c,d, 11);
R0(d,e,a,b,c, 12); R0(c,d,e,a,b, 13); R0(b,c,d,e,a, 14); R0(a,b,c,d,e, 15);
R1(e,a,b,c,d, 16); R1(d,e,a,b,c, 17); R1(c,d,e,a,b, 18); R1(b,c,d,e,a, 19);
/* Round 2 */
R2(a,b,c,d,e, 20); R2(e,a,b,c,d, 21); R2(d,e,a,b,c, 22); R2(c,d,e,a,b, 23);
R2(b,c,d,e,a, 24); R2(a,b,c,d,e, 25); R2(e,a,b,c,d, 26); R2(d,e,a,b,c, 27);
R2(c,d,e,a,b, 28); R2(b,c,d,e,a, 29); R2(a,b,c,d,e, 30); R2(e,a,b,c,d, 31);
R2(d,e,a,b,c, 32); R2(c,d,e,a,b, 33); R2(b,c,d,e,a, 34); R2(a,b,c,d,e, 35);
R2(e,a,b,c,d, 36); R2(d,e,a,b,c, 37); R2(c,d,e,a,b, 38); R2(b,c,d,e,a, 39);
/* Round 3 */
R3(a,b,c,d,e, 40); R3(e,a,b,c,d, 41); R3(d,e,a,b,c, 42); R3(c,d,e,a,b, 43);
R3(b,c,d,e,a, 44); R3(a,b,c,d,e, 45); R3(e,a,b,c,d, 46); R3(d,e,a,b,c, 47);
R3(c,d,e,a,b, 48); R3(b,c,d,e,a, 49); R3(a,b,c,d,e, 50); R3(e,a,b,c,d, 51);
R3(d,e,a,b,c, 52); R3(c,d,e,a,b, 53); R3(b,c,d,e,a, 54); R3(a,b,c,d,e, 55);
R3(e,a,b,c,d, 56); R3(d,e,a,b,c, 57); R3(c,d,e,a,b, 58); R3(b,c,d,e,a, 59);
/* Round 4 */
R4(a,b,c,d,e, 60); R4(e,a,b,c,d, 61); R4(d,e,a,b,c, 62); R4(c,d,e,a,b, 63);
R4(b,c,d,e,a, 64); R4(a,b,c,d,e, 65); R4(e,a,b,c,d, 66); R4(d,e,a,b,c, 67);
R4(c,d,e,a,b, 68); R4(b,c,d,e,a, 69); R4(a,b,c,d,e, 70); R4(e,a,b,c,d, 71);
R4(d,e,a,b,c, 72); R4(c,d,e,a,b, 73); R4(b,c,d,e,a, 74); R4(a,b,c,d,e, 75);
R4(e,a,b,c,d, 76); R4(d,e,a,b,c, 77); R4(c,d,e,a,b, 78); R4(b,c,d,e,a, 79);
/* Update the chaining values */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
/* Wipe variables */
a = b = c = d = e = 0;
}
/* SHA1Init - Initialize new context.
**/
void SHA1Init(
SHA1_CTX* context
)
{
/* SHA1 initialization constants */
context->state[0] = 0x67452301;
context->state[1] = 0xEFCDAB89;
context->state[2] = 0x98BADCFE;
context->state[3] = 0x10325476;
context->state[4] = 0xC3D2E1F0;
context->count[0] = context->count[1] = 0;
}
/* Run your data through this. This will call the compression function SHA1Transform for each
** 64-byte block of data.
**/
void SHA1Update(
SHA1_CTX* context,
const unsigned char* data,
unsigned long dataLen
)
{
unsigned long numByteDataProcessed; /* Number of bytes processed so far */
unsigned long numByteInBuffMod64; /* Number of bytes in the buffer mod 64 */
numByteInBuffMod64 = (context->count[0] >> 3) % 64;
/* Adding in the number of bits of data */
if ((context->count[0] += dataLen << 3) < (dataLen << 3)) {
context->count[1]++; /* add in the carry bit */
}
context->count[1] += (dataLen >> 29);
/* If there is at least one block to be processed... */
if ((numByteInBuffMod64 + dataLen) > 63) {
/* Copy over 64-numByteInBuffMod64 bytes of data to the end of buffer */
memcpy(&context->buffer[numByteInBuffMod64], data,
(numByteDataProcessed = 64 - numByteInBuffMod64));
/* Perform the transform on the buffer */
SHA1Transform(context->state, context->buffer);
/* As long as there are 64-bit blocks of data remaining, transform each one. */
for ( ; numByteDataProcessed + 63 < dataLen; numByteDataProcessed += 64) {
SHA1Transform(context->state, &data[numByteDataProcessed]);
}
numByteInBuffMod64 = 0;
}
/* Else there is not enough to process one block. */
else
numByteDataProcessed = 0;
/* Copy over the remaining data into the buffer */
memcpy(&context->buffer[numByteInBuffMod64], &data[numByteDataProcessed],
dataLen - numByteDataProcessed);
}
/* Add padding and return the message digest.
**/
void SHA1Final(
unsigned char digest[SHA1_DIGESTSIZE],
SHA1_CTX* context
)
{
unsigned long i, j;
unsigned char numBits[8];
/* Record the number of bits */
for (i = 1, j = 0; j < 8; i--, j += 4) {
numBits[j] = (unsigned char)((context->count[i] >> 24) & 0xff);
numBits[j+1] = (unsigned char)((context->count[i] >> 16) & 0xff);
numBits[j+2] = (unsigned char)((context->count[i] >> 8) & 0xff);
numBits[j+3] = (unsigned char)(context->count[i] & 0xff);
}
/* Add padding */
SHA1Update(context, (unsigned char *)"\200", 1);
while ((context->count[0] & 504) != 448)
SHA1Update(context, (unsigned char *)"\0", 1);
/* Append length */
SHA1Update(context, numBits, 8); /* Should cause a SHA1Transform() */
/* Store state in digest */
for (i = 0, j = 0; j < 20; i++, j += 4) {
digest[j] = (unsigned char)((context->state[i] >> 24) & 0xff);
digest[j+1] = (unsigned char)((context->state[i] >> 16) & 0xff);
digest[j+2] = (unsigned char)((context->state[i] >> 8) & 0xff);
digest[j+3] = (unsigned char)((context->state[i]) & 0xff);
}
/* Wipe variables */
i = 0;
j = 0;
memset(context->buffer, 0, 64);
memset(context->state, 0, 20);
memset(context->count, 0, 8);
memset(&numBits, 0, 8);
}

39
libmultihash/sha1.h Normal file
View file

@ -0,0 +1,39 @@
/*
** sha1.h
**
** Copyright NTT MCL, 2000.
**
** Satomi Okazaki
** Security Group, NTT MCL
** November 1999
**
**************************
** 13 December 1999. In SHA1Transform, changed "buffer" to be const.
** In SHA1Update, changed "data to be const. -- S.O.
*/
#ifndef __SHA1_H__
#define __SHA1_H__
#include <stdio.h>
#include <string.h>
#ifndef SHA1_DIGESTSIZE
#define SHA1_DIGESTSIZE 20
#endif
#ifndef SHA1_BLOCKSIZE
#define SHA1_BLOCKSIZE 64
#endif
typedef struct {
unsigned long state[5];
unsigned long count[2]; /* stores the number of bits */
unsigned char buffer[SHA1_BLOCKSIZE];
} SHA1_CTX;
void SHA1Transform(unsigned long state[5], const unsigned char buffer[SHA1_BLOCKSIZE]);
void SHA1Init(SHA1_CTX *context);
void SHA1Update(SHA1_CTX *context, const unsigned char *data, unsigned long len);
void SHA1Final(unsigned char digest[SHA1_DIGESTSIZE], SHA1_CTX *context);
#endif /* __SHA1_H__ */

50
src/CMakeLists.txt Normal file
View file

@ -0,0 +1,50 @@
# Make sure the compiler can find include files from our Hello library.
include_directories (
${FriiDump_SOURCE_DIR}/libfriidump
)
# Make sure the linker can find the Hello library once it is built.
link_directories (
${FriiDump_BINARY_DIR}/libfriidump
)
# Add executable called "helloDemo" that is built from the source files
# "demo.cxx" and "demo_b.cxx". The extensions are automatically found.
if (WIN32)
set(
additional_sources
getopt-win32.h
getopt-win32.c
getopt_long-win32.c
)
endif (WIN32)
add_executable (
friidump
friidump.c
${additional_sources}
)
# Link the executable to the Hello library.
target_link_libraries (
friidump
friidumplib
)
if (WIN32)
# We only want a version number on Windows (Is it any use?)
set_target_properties (friidump PROPERTIES VERSION 0.2)
install(
TARGETS friidump
RUNTIME DESTINATION /
)
else (WIN32)
install(
TARGETS friidump
RUNTIME DESTINATION bin
)
endif (WIN32)

11
src/Makefile.am Normal file
View file

@ -0,0 +1,11 @@
mylibdir = $(top_builddir)/libfriidump
myincludedir = $(top_srcdir)/libfriidump
bin_PROGRAMS = friidump
friidump_SOURCES = config.h.cmake friidump.c
friidump_LDADD = $(mylibdir)/libfriidump.la
friidump_LDFLAGS = $(all_libraries)
# noinst_HEADERS =
INCLUDES = $(all_includes) -I$(myincludedir)

455
src/Makefile.in Normal file
View file

@ -0,0 +1,455 @@
# Makefile.in generated by automake 1.9.6 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
bin_PROGRAMS = friidump$(EXEEXT)
subdir = src
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/configure.in
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
am__installdirs = "$(DESTDIR)$(bindir)"
binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
PROGRAMS = $(bin_PROGRAMS)
am_friidump_OBJECTS = friidump.$(OBJEXT)
friidump_OBJECTS = $(am_friidump_OBJECTS)
friidump_DEPENDENCIES = $(mylibdir)/libfriidump.la
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
$(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
SOURCES = $(friidump_SOURCES)
DIST_SOURCES = $(friidump_SOURCES)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMDEP_FALSE = @AMDEP_FALSE@
AMDEP_TRUE = @AMDEP_TRUE@
AMTAR = @AMTAR@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
ECHO = @ECHO@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
F77 = @F77@
FFLAGS = @FFLAGS@
GREP = @GREP@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_F77 = @ac_ct_F77@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
mylibdir = $(top_builddir)/libfriidump
myincludedir = $(top_srcdir)/libfriidump
friidump_SOURCES = config.h.cmake friidump.c
friidump_LDADD = $(mylibdir)/libfriidump.la
friidump_LDFLAGS = $(all_libraries)
# noinst_HEADERS =
INCLUDES = $(all_includes) -I$(myincludedir)
all: all-am
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
&& exit 0; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
cd $(top_srcdir) && \
$(AUTOMAKE) --gnu src/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
install-binPROGRAMS: $(bin_PROGRAMS)
@$(NORMAL_INSTALL)
test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)"
@list='$(bin_PROGRAMS)'; for p in $$list; do \
p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
if test -f $$p \
|| test -f $$p1 \
; then \
f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
$(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
else :; fi; \
done
uninstall-binPROGRAMS:
@$(NORMAL_UNINSTALL)
@list='$(bin_PROGRAMS)'; for p in $$list; do \
f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
rm -f "$(DESTDIR)$(bindir)/$$f"; \
done
clean-binPROGRAMS:
@list='$(bin_PROGRAMS)'; for p in $$list; do \
f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
echo " rm -f $$p $$f"; \
rm -f $$p $$f ; \
done
friidump$(EXEEXT): $(friidump_OBJECTS) $(friidump_DEPENDENCIES)
@rm -f friidump$(EXEEXT)
$(LINK) $(friidump_LDFLAGS) $(friidump_OBJECTS) $(friidump_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/friidump.Po@am__quote@
.c.o:
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c $<
.c.obj:
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
.c.lo:
@am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
distclean-libtool:
-rm -f libtool
uninstall-info-am:
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
mkid -fID $$unique
tags: TAGS
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique; \
fi
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$tags $$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& cd $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) $$here
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
list='$(DISTFILES)'; for file in $$list; do \
case $$file in \
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
esac; \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkdir_p) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(PROGRAMS)
installdirs:
for dir in "$(DESTDIR)$(bindir)"; do \
test -z "$$dir" || $(mkdir_p) "$$dir"; \
done
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-libtool distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
info: info-am
info-am:
install-data-am:
install-exec-am: install-binPROGRAMS
install-info: install-info-am
install-man:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-binPROGRAMS uninstall-info-am
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
clean-generic clean-libtool ctags distclean distclean-compile \
distclean-generic distclean-libtool distclean-tags distdir dvi \
dvi-am html html-am info info-am install install-am \
install-binPROGRAMS install-data install-data-am install-exec \
install-exec-am install-info install-info-am install-man \
install-strip installcheck installcheck-am installdirs \
maintainer-clean maintainer-clean-generic mostlyclean \
mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
pdf pdf-am ps ps-am tags uninstall uninstall-am \
uninstall-binPROGRAMS uninstall-info-am
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

760
src/friidump.c Normal file
View file

@ -0,0 +1,760 @@
/***************************************************************************
* Copyright (C) 2007 by Arep *
* Support is provided through the forums at *
* http://wii.console-tribe.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "misc.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include "disc.h"
#include "dumper.h"
#include "unscrambler.h"
#define USECS_PER_SEC 1000000
/* Name of package */
#define PACKAGE "friidump"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "arep@no.net"
/* Define to the full name of this package. */
#define PACKAGE_NAME "FriiDump"
/* Define to the version of this package. */
#define PACKAGE_VERSION "0.5.3.1"
#ifdef WIN32
#include "getopt-win32.h"
#else
#include <sys/time.h>
#include <getopt.h>
#endif
/* Struct for program options */
struct {
char *device;
bool autodump;
bool gui;
char *raw_in;
char *raw_out;
char *iso_out;
bool resume;
int dump_method;
u_int32_t command;
u_int32_t start_sector;
u_int32_t sectors_no;
u_int32_t speed;
u_int32_t disctype;
u_int32_t sec_disc;
u_int32_t sec_mem;
bool no_hashing;
bool no_unscrambling;
bool no_flushing;
bool stop_unit;
bool allmethods;
} options;
/* Struct for progress data */
typedef struct {
struct timeval start_time;
struct timeval end_time;
double mb_total;
double mb_total_real;
u_int32_t sectors_skipped;
} progstats;
void progress_for_guis (bool start, u_int32_t sectors_done, u_int32_t total_sectors, progstats *stats) {
int perc;
double elapsed, mb_done, mb_done_real, mb_hour, seconds_left;
struct timeval now;
time_t eta;
struct tm etatm;
char buf[50];
if (start) {
gettimeofday (&(stats -> start_time), NULL);
stats -> mb_total = (double) total_sectors * 2064 / 1024 / 1024;
stats -> mb_total_real = (double) (total_sectors - sectors_done) * 2064 / 1024 / 1024;
stats -> sectors_skipped = sectors_done;
} else {
perc = (int) (100.0 * sectors_done / total_sectors);
gettimeofday (&now, NULL);
elapsed = difftime (now.tv_sec, (stats -> start_time).tv_sec);
mb_done = (double) sectors_done * 2064 / 1024 / 1024;
mb_done_real = (double) (sectors_done - stats -> sectors_skipped) * 2064 / 1024 / 1024;
mb_hour = mb_done_real / elapsed * 60 * 60;
seconds_left = stats -> mb_total_real / mb_hour * 60 * 60;
eta = (time_t) ((stats -> start_time).tv_sec + seconds_left);
if (localtime_r (&eta, &etatm))
strftime (buf, 50, "%d/%m/%Y %H:%M:%S", &etatm);
else
sprintf (buf, "N/A");
/* This is the only thing we print to stdout, so that other programs can easily capture and parse our output */
fprintf (stdout, "%d%%|%u/%u sectors|%.2lf/%.0lf MB|%.0lf/%.0lf seconds|%.2lf MB/h|%s\n",
perc, sectors_done, total_sectors, mb_done, stats -> mb_total, elapsed, seconds_left, mb_hour, buf);
fflush (stdout);
}
/* Save return time, in case this will be the last call */
gettimeofday (&(stats -> end_time), NULL);
return;
}
void progress (bool start, u_int32_t sectors_done, u_int32_t total_sectors, progstats *stats) {
int perc, i;
double elapsed, mb_done, mb_done_real, mb_hour, seconds_left;
struct timeval now;
time_t eta;
struct tm etatm;
char buf[50];
if (start) {
gettimeofday (&(stats -> start_time), NULL);
stats -> mb_total = (double) total_sectors * 2064 / 1024 / 1024;
stats -> mb_total_real = (double) (total_sectors - sectors_done) * 2064 / 1024 / 1024;
stats -> sectors_skipped = sectors_done;
} else {
perc = (int) (100.0 * sectors_done / total_sectors);
gettimeofday (&now, NULL);
elapsed = difftime (now.tv_sec, (stats -> start_time).tv_sec);
mb_done = (double) sectors_done * 2064 / 1024 / 1024;
mb_done_real = (double) (sectors_done - stats -> sectors_skipped) * 2064 / 1024 / 1024;
mb_hour = mb_done_real / elapsed * 60 * 60;
seconds_left = stats -> mb_total_real / mb_hour * 60 * 60;
eta = (time_t) ((stats -> start_time).tv_sec + seconds_left);
if (localtime_r (&eta, &etatm))
strftime (buf, 50, "%d/%m/%Y %H:%M:%S", &etatm);
else
sprintf (buf, "N/A");
fprintf (stdout, "\r%3d%% ", perc);
fprintf (stdout, "|");
for (i = 0; i < 100 / 3; i++) {
if (i == perc / 3)
fprintf (stdout, "*");
else
fprintf (stdout, "-");
}
fprintf (stdout, "| ");
fprintf (stdout, "%.2lf MB/h, ETA: %s", mb_hour, buf);
fflush (stdout);
}
if (sectors_done == total_sectors)
printf ("\n");
/* Save return time, in case this will be the last call */
gettimeofday (&(stats -> end_time), NULL);
return;
}
void welcome (void) {
/* Welcome text */
fprintf (stderr,
"FriiDump " PACKAGE_VERSION " - Copyright (C) 2007 Arep\n"
"This software comes with ABSOLUTELY NO WARRANTY.\n"
"This is free software, and you are welcome to redistribute it\n"
"under certain conditions; see COPYING for details.\n"
"\n"
"Official support forum: http://wii.console-tribe.com\n"
"\n"
"Forum for this UNOFFICIAL VERSION: http://forum.redump.org\n"
"\n"
);
fflush (stderr);
return;
}
void help (void) {
/* 80 cols guide:
* |-------------------------------------------------------------------------------|
*/
fprintf (stderr, "\n"
"Available command line options:\n"
"\n"
" -h, --help Show this help\n"
" -a, --autodump Dump the disc to an ISO file with an\n"
" automatically-generated name, resuming the dump\n"
" if possible\n"
" -g, --gui Use more verbose output that can be easily\n"
" parsed by a GUI frontend\n"
" -d, --device <device> Dump disc from device <device>\n"
" -p, --stop Instruct device to stop disc rotation\n"
" -c, --command <nr> Force memory dump command:\n"
" 0 - vanilla 2064\n"
" 1 - vanilla 2384\n"
" 2 - Hitachi\n"
" 3 - Lite-On\n"
" 4 - Renesas\n"
" -x, --speed <x> Set streaming speed (1, 24, 32, 64, etc.,\n"
" where 1 = 150 KiB/s and so on)\n"
" -T, --type <nr> Force disc type:\n"
" 0 - GameCube\n"
" 1 - Wii\n"
" 2 - Wii_DL\n"
" 3 - DVD\n"
" -S, --size <sectors> Force disc size\n"
" -r, --raw <file> Output to file <file> in raw format (2064-byte\n"
" sectors)\n"
" -i, --iso <file> Output to file <file> in ISO format (2048-byte\n"
" sectors)\n"
" -u, --unscramble <file> Convert (unscramble) raw image contained in\n"
" <file> to ISO format\n"
" -H, --nohash Do not compute CRC32/MD5/SHA-1 hashes\n"
" for generated files\n"
" -s, --resume Resume partial dump\n"
" - General -----------------------------------\n"
" -0, --method0[=<req>,<exp>] Use dumping method 0 (Optional argument\n"
" specifies how many sectors to request from disc\n"
" and read from cache at a time. Values should be\n"
" separated with a comma. Default 16,16)\n"
" - Non-Streaming -----------------------------\n"
" -1, --method1[=<req>,<exp>] Use dumping method 1 (Default 16,16)\n"
" -2, --method2[=<req>,<exp>] Use dumping method 2 (Default 16,16)\n"
" -3, --method3[=<req>,<exp>] Use dumping method 3 (Default 16,16)\n"
" - Streaming ---------------------------------\n"
" -4, --method4[=<req>,<exp>] Use dumping method 4 (Default 27,27)\n"
" -5, --method5[=<req>,<exp>] Use dumping method 5 (Default 27,27)\n"
" -6, --method6[=<req>,<exp>] Use dumping method 6 (Default 27,27)\n"
" - Hitachi -----------------------------------\n"
" -7, --method7 Use dumping method 7 (Read and dump 5 blocks\n"
" at a time, using streaming read)\n"
" -8, --method8 Use dumping method 8 (Read and dump 5 blocks\n"
" at a time, using streaming read, using DMA)\n"
" -9, --method9 Use dumping method 9 (Read and dump 5 blocks\n"
" at a time, using streaming read, using DMA and\n"
" some speed tricks)\n"
" -A, --allmethods Try all known methods and commands until\n"
" one works.\n"
#ifdef DEBUG
" -n, --donottunscramble Do not try unscrambling to check EDC. Only\n"
" useful for testing the raw performance of the\n"
" different methods\n"
" -f, --donottflush Do not call fflush() after every fwrite()\n"
#endif
);
return;
}
bool optparse (int argc, char **argv) {
bool out;
char *result = NULL;
int c;
int option_index = 0;
static struct option long_options[] = {
{"help", 0, 0, 'h'}, //0 - no_argument
{"autodump", 0, 0, 'a'},
{"gui", 0, 0, 'g'},
{"device", 1, 0, 'd'}, //1 - required_argument
{"raw", 1, 0, 'r'},
{"iso", 1, 0, 'i'},
{"unscramble", 1, 0, 'u'},
{"nohash", 0, 0, 'H'},
{"resume", 0, 0, 's'},
{"method0", 2, 0, '0'}, //2 - optional_argument
{"method1", 2, 0, '1'},
{"method2", 2, 0, '2'},
{"method3", 2, 0, '3'},
{"method4", 2, 0, '4'},
{"method5", 2, 0, '5'},
{"method6", 2, 0, '6'},
{"method7", 0, 0, '7'},
{"method8", 0, 0, '8'},
{"method9", 0, 0, '9'},
{"stop", 0, 0, 'p'},
{"command", 1, 0, 'c'},
{"startsector", 1, 0, 't'},
{"size", 1, 0, 'S'},
{"speed", 1, 0, 'x'},
{"type", 1, 0, 'T'},
{"allmethods", 0, 0, 'A'},
#ifdef DEBUG
/* We don't want newbies to generate and put into circulation bad dumps, so this options are disabled for releases */
{"donottunscramble", 0, 0, 'n'},
{"donottflush", 0, 0, 'f'},
#endif
{0, 0, 0, 0}
};
if (argc == 1) {
help ();
exit (1);
}
/* Init options to default values */
options.device = NULL;
options.autodump = false;
options.gui = false;
options.raw_in = NULL;
options.raw_out = NULL;
options.iso_out = NULL;
options.no_hashing = false;
options.resume = false;
options.dump_method = -1;
options.command = -1;
options.start_sector = -1;
options.sectors_no = -1;
options.speed = -1;
options.disctype = -1;
options.sec_disc = -1;
options.sec_mem = -1;
options.no_unscrambling = false;
options.no_flushing = false;
options.stop_unit = false;
options.allmethods = false;
do {
#ifdef DEBUG
c = getopt_long (argc, argv, "hpagd:r:i:u:Hs0::1::2::3::4::5::6::789c:t:S:x:T:Anf", long_options, &option_index);
#else
c = getopt_long (argc, argv, "hpagd:r:i:u:Hs0::1::2::3::4::5::6::789c:t:S:x:T:A", long_options, &option_index);
#endif
switch (c) {
case 'h':
help ();
exit (1);
break;
case 'p':
options.stop_unit = true;
break;
case 'a':
options.autodump = true;
options.resume = true;
break;
case 'g':
options.gui = true;
break;
case 'd':
my_strdup (options.device, optarg);
break;
case 'r':
my_strdup (options.raw_out, optarg);
break;
case 'i':
my_strdup (options.iso_out, optarg);
break;
case 'u':
my_strdup (options.raw_in, optarg);
break;
case 'H':
options.no_hashing = true;
break;
case 's':
options.resume = true;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
options.dump_method = c - '0';
if (optarg) {
result = strtok(optarg, ",");
result = strtok(NULL, ",");
options.sec_disc = atol(strpbrk(optarg,"1234567890"));
if (result) options.sec_mem = atol(result);
else {
help ();
exit (1);
}
}
break;
case '7':
case '8':
case '9':
options.dump_method = c - '0';
break;
case 'c':
options.command = atol (optarg);
if (options.command > 4) {
help ();
exit (1);
};
break;
case 't':
options.start_sector = atol (optarg);
break;
case 'S':
options.sectors_no = atol (optarg);
break;
case 'x':
options.speed = atol (optarg);
break;
case 'T':
options.disctype = atol (optarg);
if (options.disctype > 3) {
help ();
exit (1);
};
unscrambler_set_disctype (options.disctype);
break;
case 'A':
options.allmethods = true;
options.resume = true;
break;
#ifdef DEBUG
case 'n':
options.no_unscrambling = true;
break;
case 'f':
options.no_flushing = true;
break;
#endif
case -1:
break;
default:
// fprintf (stderr, "?? getopt returned character code 0%o ??\n", c);
exit (7);
break;
}
} while (c != -1);
if (optind < argc) {
/* Command-line arguments remaining. Ignore them, warning the user. */
fprintf (stderr, "WARNING: Extra parameters ignored\n");
}
/* Sanity checks... */
out = false;
if (!options.device && !options.raw_in) {
fprintf (stderr, "No operation specified. Please use the -d or -u options.\n");
} else if (options.raw_in && options.raw_out) {
fprintf (stderr,
"Are you sure you want to convert a raw image to another raw image? ;)\n"
"Take a look at the -i and -a options!\n"
);
} else if (options.autodump && (options.raw_out || options.iso_out)) {
fprintf (stderr, "The -r and -i options cannot be used together with -a.\n");
} else {
/* Specified options seem to make sense */
out = true;
}
return (out);
}
int dologic (disc *d, progstats stats) {
disc_type type_id;
char *type, *game_id, *region, *maker_id, *maker, *version, *title, tmp[0x03E0 + 4 + 1];
bool drive_supported;
int out;
dumper *dmp;
u_int32_t current_sector;
if (options.stop_unit) { //stop rotation, if requested
fprintf (stderr, "Issuing STOP command... %s\n", (disc_stop_unit (d, false)) ? "OK" : "Failed");
exit (1);
}
else disc_stop_unit(d, true); //else start rotation
drive_supported = disc_get_drive_support_status (d);
fprintf (stderr,
"\n"
"Drive information:\n"
"----------------------------------------------------------------------\n"
"Drive model........: %s\n"
"Supported..........: %s\n", disc_get_drive_model_string (d), drive_supported ? "Yes" : "No"
);
init_range(d, options.sec_disc, options.sec_mem);
if (!(disc_set_read_method (d, options.dump_method)))
exit (2);
if (options.command!=-1) fprintf (stderr,
"Command............: %d (forced)\n", disc_get_command(d));
else fprintf (stderr,
"Command............: %d\n", disc_get_command(d));
options.dump_method=disc_get_method(d);
if (disc_get_def_method(d)!=options.dump_method) fprintf (stderr,
"Method.............: %d (forced)\n", options.dump_method);
else fprintf (stderr,
"Method.............: %d\n", options.dump_method);
if ((options.dump_method==0)
|| (options.dump_method==1) || (options.dump_method==2) || (options.dump_method==3)
|| (options.dump_method==4) || (options.dump_method==5) || (options.dump_method==6)
){
fprintf (stderr,
"Requested sectors..: %d\n", disc_get_sec_disc(d));
fprintf (stderr,
"Expected sectors...: %d\n", disc_get_sec_mem(d));
}
fprintf (stderr, "\nPress Ctrl+C at any time to terminate\n");
fprintf (stderr, "\nRetrieving disc seeds, this might take a while... ");
//set speed for 1st time
if (options.speed != -1) disc_set_speed(d, options.speed * 177);
if (options.speed != -1) disc_set_streaming_speed(d, options.speed * 177);
// disc_set_speed(d, 0xffff);
if (!disc_init (d, options.disctype, options.sectors_no)) {
fprintf (stderr, "Failed\n");
out = false;
} else {
fprintf (stderr, "OK\n");
disc_get_type (d, &type_id, &type);
disc_get_gameid (d, &game_id);
disc_get_region (d, NULL, &region);
disc_get_maker (d, &maker_id, &maker);
disc_get_version (d, NULL, &version);
disc_get_title (d, &title);
fprintf (stderr,
"\n"
"Disc information:\n"
"----------------------------------------------------------------------\n");
if (options.disctype!=-1) fprintf (stderr,
"Disc type..........: %s (forced)\n", type);
else fprintf (stderr,
"Disc type..........: %s\n", type);
if (options.sectors_no!=-1) fprintf (stderr,
"Disc size..........: %d (forced)\n", disc_get_sectors_no(d));
else fprintf (stderr,
"Disc size..........: %d\n", disc_get_sectors_no(d));
if (disc_get_layerbreak(d)>0 && type_id==DISC_TYPE_DVD) fprintf (stderr,
"Layer break........: %d\n", disc_get_layerbreak(d));
if ((type_id==DISC_TYPE_GAMECUBE) || (type_id==DISC_TYPE_WII) || (type_id==DISC_TYPE_WII_DL)) fprintf (stderr,
"Game ID............: %s\n"
"Region.............: %s\n"
"Maker..............: %s - %s\n"
"Version............: %s\n"
"Game title.........: %s\n", game_id, region, maker_id, maker, version, title
);
if (type_id == DISC_TYPE_WII || type_id == DISC_TYPE_WII_DL)
fprintf (stderr, "Contains update....: %s\n" , disc_get_update (d) ? "Yes" : "No");
fprintf (stderr, "\n");
disc_set_unscrambling (d, !options.no_unscrambling);
unscrambler_set_disctype (type_id);
if (options.autodump) {
snprintf (tmp, sizeof (tmp), "%s.iso", title);
my_strdup (options.iso_out, tmp);
}
//set speed 2nd time after rotation is started and some sectors read
if (options.speed != -1) disc_set_streaming_speed(d, options.speed * 177);
if (options.speed != -1) disc_set_speed(d, options.speed * 177);
/* If at least an output file was specified, proceed dumping, otherwise stop here */
if (options.raw_out || options.iso_out) {
if (options.raw_out)
fprintf (stderr, "Writing to file \"%s\" in raw format\n", options.raw_out);
if (options.iso_out)
fprintf (stderr, "Writing to file \"%s\" in ISO format\n", options.iso_out);
fprintf (stderr, "\n");
dmp = dumper_new (d);
dumper_set_hashing (dmp, !options.no_hashing);
dumper_set_flushing (dmp, !options.no_flushing);
if (!dumper_set_raw_output_file (dmp, options.raw_out, options.resume)) {
fprintf (stderr, "Cannot setup raw output file\n");
} else if (!dumper_set_iso_output_file (dmp, options.iso_out, options.resume)) {
fprintf (stderr, "Cannot setup ISO output file\n");
} else if (!dumper_prepare (dmp)) {
fprintf (stderr, "Cannot prepare dumper");
} else {
// fprintf (stderr, "Starting dump process from sector %u...\n", dmp -> start_sector);
// opdd.start_sector = options.start_sector;
if (options.gui)
dumper_set_progress_callback (dmp, (progress_func) progress_for_guis, &stats);
else
dumper_set_progress_callback (dmp, (progress_func) progress, &stats);
if (dumper_dump (dmp, &current_sector)) {
fprintf (stderr, "Dump completed successfully!\n");
if (!options.no_hashing && options.raw_out)
fprintf (stderr,
"Raw image hashes:\n"
"CRC32...: %s\n"
//"MD4.....: %s\n"
"MD5.....: %s\n"
"SHA-1...: %s\n"
/*"ED2K....: %s\n"*/,
dumper_get_raw_crc32 (dmp), /*dumper_get_raw_md4 (dmp),*/ dumper_get_raw_md5 (dmp),
dumper_get_raw_sha1 (dmp)/*, dumper_get_raw_ed2k (dmp)*/
);
if (!options.no_hashing && options.iso_out)
fprintf (stderr,
"ISO image hashes:\n"
"CRC32...: %s\n"
//"MD4.....: %s\n"
"MD5.....: %s\n"
"SHA-1...: %s\n"
/*"ED2K....: %s\n"*/,
dumper_get_iso_crc32 (dmp), /*dumper_get_iso_md4 (dmp),*/ dumper_get_iso_md5 (dmp),
dumper_get_iso_sha1 (dmp)/*, dumper_get_iso_ed2k (dmp)*/
);
out = true;
disc_stop_unit (d, 0);
} else {
fprintf (stderr, "\nDump failed at sectors: %u..%u\n", current_sector, current_sector+15);
out = false;
//disc_stop_unit (d, 0);
}
}
dmp = dumper_destroy (dmp);
} else {
fprintf (stderr, "No output file for dumping specified, please take a look at the -i, -r and -a options\n");
}
}
return out;
}
int main (int argc, char *argv[]) {
disc *d;
progstats stats;
double duration;
suseconds_t us;
int out, ret;
unscrambler *u;
unscrambler_progress_func pfunc;
u_int32_t current_sector;
/* First of all... */
drop_euid ();
welcome ();
d = NULL;
out = false;
if (optparse (argc, argv)) {
if (options.device) {
/* Dump DVD to file */
fprintf (stderr, "Initializing DVD drive... ");
if (!(d = disc_new (options.device, options.command))) {
fprintf (stderr, "Failed\n");
#ifndef WIN32
fprintf (stderr,
"Probably you do not have access to the DVD device. Ask the administrator\n"
"to add you to the proper group, or use 'sudo'.\n"
);
#endif
} else {
fprintf (stderr, "OK\n");
if(options.allmethods)
{
fprintf (stderr, "Trying all methods... This will take a LOOOONG time and generate an insanely long console output :p\n");
for(options.command=0;options.command<=4;options.command++)
{
for(options.dump_method=0;options.dump_method<=9;options.dump_method++)
{
fprintf (stderr, "Trying with command %d, method %d\n", options.command, options.dump_method);
out = dologic(d, stats);
if(out==true)
{
break;
}
}
if(out==true)
{
fprintf (stderr, "Command %d and method %d combination worked!\n", options.command, options.dump_method);
break;
}
}
} else {
out = dologic(d, stats);
}
d = disc_destroy (d);
}
} else if (options.raw_in) {
/* Convert raw image to ISO format */
u = unscrambler_new ();
if (options.gui)
pfunc = (unscrambler_progress_func) progress_for_guis;
else
pfunc = (unscrambler_progress_func) progress;
if ((out = unscrambler_unscramble_file (u, options.raw_in, options.iso_out, pfunc, &stats, &current_sector)))
fprintf (stderr, "Unscrambling completed successfully!\n");
else
fprintf (stderr, "\nUnscrambling failed at sectors: %u..%u\n", current_sector, current_sector+15);
u = unscrambler_destroy (u);
} else {
MY_ASSERT (0);
}
if (out) {
duration = stats.end_time.tv_sec - stats.start_time.tv_sec;
if (stats.end_time.tv_usec >= stats.start_time.tv_usec) {
us = stats.end_time.tv_usec - stats.start_time.tv_usec;
} else {
if (duration > 0)
duration--;
us = USECS_PER_SEC + stats.end_time.tv_usec - stats.start_time.tv_usec;
}
duration += ((double) us / (double) USECS_PER_SEC);
if (duration < 0)
duration = 0;
fprintf (stderr, "Operation took %.2f seconds\n", duration);
ret = EXIT_SUCCESS;
} else {
ret = EXIT_FAILURE;
}
my_free (options.device);
my_free (options.iso_out);
my_free (options.raw_out);
my_free (options.raw_in);
}
return (out);
}

130
src/getopt-win32.c Normal file
View file

@ -0,0 +1,130 @@
/* $Id$ */
/*
** Copyright (C) 2002 Martin Roesch <roesch@sourcefire.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License Version 2 as
** published by the Free Software Foundation. You may not use, modify or
** distribute this program under any other version of the GNU General
** Public License.
**
** 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.
*/
#ifdef SNORT_GETOPT
#include <stdio.h> /* for EOF */
#include <string.h> /* for strchr() */
#include "getopt.h"
/* static (global) variables that are specified as exported by getopt() */
char *optarg = NULL; /* pointer to the start of the option argument */
int optind = 1; /* number of the next argv[] to be evaluated */
int opterr = 1; /* non-zero if a question mark should be returned
when a non-valid option character is detected */
int optopt;
int getopt(int argc, char *argv[], char *opstring)
{
static char *pIndexPosition = NULL; /* place inside current argv string */
char *pArgString = NULL; /* where to start from next */
char *pOptString; /* the string in our program */
if (pIndexPosition != NULL) {
/* we last left off inside an argv string */
if (*(++pIndexPosition)) {
/* there is more to come in the most recent argv */
pArgString = pIndexPosition;
}
}
if (pArgString == NULL) {
/* we didn't leave off in the middle of an argv string */
if (optind >= argc) {
/* more command-line arguments than the argument count */
pIndexPosition = NULL; /* not in the middle of anything */
return EOF; /* used up all command-line arguments */
}
/*---------------------------------------------------------------------
* If the next argv[] is not an option, there can be no more options.
*-------------------------------------------------------------------*/
pArgString = argv[optind++]; /* set this to the next argument ptr */
if (('/' != *pArgString) && /* doesn't start with a slash or a dash? */
('-' != *pArgString)) {
--optind; /* point to current arg once we're done */
optarg = NULL; /* no argument follows the option */
pIndexPosition = NULL; /* not in the middle of anything */
return EOF; /* used up all the command-line flags */
}
/* check for special end-of-flags markers */
if ((strcmp(pArgString, "-") == 0) ||
(strcmp(pArgString, "--") == 0)) {
optarg = NULL; /* no argument follows the option */
pIndexPosition = NULL; /* not in the middle of anything */
return EOF; /* encountered the special flag */
}
pArgString++; /* look past the / or - */
}
if (':' == *pArgString) { /* is it a colon? */
/*---------------------------------------------------------------------
* Rare case: if opterr is non-zero, return a question mark;
* otherwise, just return the colon we're on.
*-------------------------------------------------------------------*/
return (opterr ? (int)'?' : (int)':');
}
else if ((pOptString = strchr(opstring, *pArgString)) == 0) {
/*---------------------------------------------------------------------
* The letter on the command-line wasn't any good.
*-------------------------------------------------------------------*/
optarg = NULL; /* no argument follows the option */
pIndexPosition = NULL; /* not in the middle of anything */
return (opterr ? (int)'?' : (int)*pArgString);
}
else {
/*---------------------------------------------------------------------
* The letter on the command-line matches one we expect to see
*-------------------------------------------------------------------*/
if (':' == _next_char(pOptString)) { /* is the next letter a colon? */
/* It is a colon. Look for an argument string. */
if ('\0' != _next_char(pArgString)) { /* argument in this argv? */
optarg = &pArgString[1]; /* Yes, it is */
}
else {
/*-------------------------------------------------------------
* The argument string must be in the next argv.
* But, what if there is none (bad input from the user)?
* In that case, return the letter, and optarg as NULL.
*-----------------------------------------------------------*/
if (optind < argc)
optarg = argv[optind++];
else {
optarg = NULL;
return (opterr ? (int)'?' : (int)*pArgString);
}
}
pIndexPosition = NULL; /* not in the middle of anything */
}
else {
/* it's not a colon, so just return the letter */
optarg = NULL; /* no argument follows the option */
pIndexPosition = pArgString; /* point to the letter we're on */
}
return (int)*pArgString; /* return the letter that matched */
}
}
#endif

36
src/getopt-win32.h Normal file
View file

@ -0,0 +1,36 @@
/* $Id$ */
/*
** Copyright (C) 2002 Martin Roesch <roesch@sourcefire.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License Version 2 as
** published by the Free Software Foundation. You may not use, modify or
** distribute this program under any other version of the GNU General
** Public License.
**
** 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 _SNORT_GETOPT_H_
#define _SNORT_GETOPT_H_
#ifdef SNORT_GETOPT
#define _next_char(string) (char)(*(string+1))
extern char * optarg;
extern int optind;
int getopt(int, char**, char*);
#else
#include "getopt1.h"
#endif
#endif /* _SNORT_GETOPT_H_ */

130
src/getopt1.h Normal file
View file

@ -0,0 +1,130 @@
/* Declarations for getopt.
Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
it under the terms of the GNU General Public License Version 2 as
published by the Free Software Foundation. You may not use, modify or
distribute this program under any other version of the GNU General
Public License.
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. */
#ifndef _GETOPT1_H
#define _GETOPT1_H 1
#ifndef HAVE_GETOPT_LONG
#ifdef __cplusplus
extern "C" {
#endif
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
extern char *optarg;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns EOF, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
extern int optind;
/* Callers store zero here to inhibit the error message `getopt' prints
for unrecognized options. */
extern int opterr;
/* Set to an option character which was unrecognized. */
extern int optopt;
/* Describe the long-named options requested by the application.
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
of `struct option' terminated by an element containing a name which is
zero.
The field `has_arg' is:
no_argument (or 0) if the option does not take an argument,
required_argument (or 1) if the option requires an argument,
optional_argument (or 2) if the option takes an optional argument.
If the field `flag' is not NULL, it points to a variable that is set
to the value given in the field `val' when the option is found, but
left unchanged if the option is not found.
To have a long-named option do something other than set an `int' to
a compiled-in constant, such as set a value from `optarg', set the
option's `flag' field to zero and its `val' field to a nonzero
value (the equivalent single-letter option character, if there is
one). For long options that have a zero `flag' field, `getopt'
returns the contents of the `val' field. */
struct option
{
#if __STDC__
const char *name;
#else
char *name;
#endif
/* has_arg can't be an enum because some compilers complain about
type mismatches in all the code that assumes it is an int. */
int has_arg;
int *flag;
int val;
};
/* Names for the values of the `has_arg' field of `struct option'. */
#define no_argument 0
#define required_argument 1
#define optional_argument 2
#if __STDC__
#ifndef HAVE_GETOPT
extern int getopt (int argc, char *const *argv, const char *optstring);
#endif
extern int getopt_long (int argc, char *const *argv, const char *shortopts,
const struct option *longopts, int *longind);
extern int getopt_long_only (int argc, char *const *argv,
const char *shortopts,
const struct option *longopts, int *longind);
/* Internal only. Users should not call this directly. */
extern int _getopt_internal (int argc, char *const *argv,
const char *shortopts,
const struct option *longopts, int *longind,
int long_only);
#else /* not __STDC__ */
#ifndef HAVE_GETOPT
extern int getopt ();
#endif
extern int getopt_long ();
extern int getopt_long_only ();
extern int _getopt_internal ();
#endif /* not __STDC__ */
#ifdef __cplusplus
}
#endif
#endif /* HAVE_GETOPT_LONG */
#endif /* _GETOPT_H */

727
src/getopt_long-win32.c Normal file
View file

@ -0,0 +1,727 @@
/* Getopt for GNU.
NOTE: getopt is now part of the C library, so if you don't know what
"Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
before changing it!
Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94
Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
it under the terms of the GNU General Public License Version 2 as
published by the Free Software Foundation. You may not use, modify or
distribute this program under any other version of the GNU General
Public License.
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. */
/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
Ditto for AIX 3.2 and <stdlib.h>. */
#ifndef _NO_PROTO
#define _NO_PROTO
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifdef HAVE_CONFIG_H
#if defined (emacs) || defined (CONFIG_BROKETS)
/* We use <config.h> instead of "config.h" so that a compilation
using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
(which it would do because it found this file in $srcdir). */
#include <config.h>
#else
#include "config.h"
#endif
#endif
#ifndef __STDC__
/* This is a separate conditional since some stdc systems
reject `defined (const)'. */
#ifndef const
#define const
#endif
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
/* Comment out all this code if we are using the GNU C Library, and are not
actually compiling the library itself. This code is part of the GNU C
Library, but also included in many other GNU distributions. Compiling
and linking in this code is a waste when using the GNU C library
(especially if it is a shared library). Rather than having every GNU
program understand `configure --with-gnu-libc' and omit the object files,
it is simpler to just do this in the source for each such file. */
#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
/* This needs to come after some library #include
to get __GNU_LIBRARY__ defined. */
#ifdef __GNU_LIBRARY__
/* Don't include stdlib.h for non-GNU C libraries because some of them
contain conflicting prototypes for getopt. */
#include <stdlib.h>
#endif /* GNU C library. */
/* This version of `getopt' appears to the caller like standard Unix `getopt'
but it behaves differently for the user, since it allows the user
to intersperse the options with the other arguments.
As `getopt' works, it permutes the elements of ARGV so that,
when it is done, all the options precede everything else. Thus
all application programs are extended to handle flexible argument order.
Setting the environment variable POSIXLY_CORRECT disables permutation.
Then the behavior is completely standard.
GNU application programs can use a third alternative mode in which
they can distinguish the relative order of options and other arguments. */
#include "getopt1.h"
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
char *optarg = NULL;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns EOF, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
/* XXX 1003.2 says this must be 1 before any call. */
int optind = 0;
/* The next char to be scanned in the option-element
in which the last option character we returned was found.
This allows us to pick up the scan where we left off.
If this is zero, or a null string, it means resume the scan
by advancing to the next ARGV-element. */
static char *nextchar;
/* Callers store zero here to inhibit the error message
for unrecognized options. */
int opterr = 1;
/* Set to an option character which was unrecognized.
This must be initialized on some systems to avoid linking in the
system's own getopt implementation. */
int optopt = '?';
/* Describe how to deal with options that follow non-option ARGV-elements.
If the caller did not specify anything,
the default is REQUIRE_ORDER if the environment variable
POSIXLY_CORRECT is defined, PERMUTE otherwise.
REQUIRE_ORDER means don't recognize them as options;
stop option processing when the first non-option is seen.
This is what Unix does.
This mode of operation is selected by either setting the environment
variable POSIXLY_CORRECT, or using `+' as the first character
of the list of option characters.
PERMUTE is the default. We permute the contents of ARGV as we scan,
so that eventually all the non-options are at the end. This allows options
to be given in any order, even with programs that were not written to
expect this.
RETURN_IN_ORDER is an option available to programs that were written
to expect options and other ARGV-elements in any order and that care about
the ordering of the two. We describe each non-option ARGV-element
as if it were the argument of an option with character code 1.
Using `-' as the first character of the list of option characters
selects this mode of operation.
The special argument `--' forces an end of option-scanning regardless
of the value of `ordering'. In the case of RETURN_IN_ORDER, only
`--' can cause `getopt' to return EOF with `optind' != ARGC. */
static enum
{
REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
} ordering;
/* Value of POSIXLY_CORRECT environment variable. */
static char *posixly_correct;
#ifdef __GNU_LIBRARY__
/* We want to avoid inclusion of string.h with non-GNU libraries
because there are many ways it can cause trouble.
On some systems, it contains special magic macros that don't work
in GCC. */
#include <string.h>
#define my_index strchr
#else
/* Avoid depending on library functions or files
whose names are inconsistent. */
#if !defined(_WIN32)
char *getenv ();
#endif
static char *
my_index (str, chr)
const char *str;
int chr;
{
while (*str)
{
if (*str == chr)
return (char *) str;
str++;
}
return 0;
}
/* If using GCC, we can safely declare strlen this way.
If not using GCC, it is ok not to declare it. */
#ifdef __GNUC__
/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
That was relevant to code that was here before. */
#ifndef __STDC__
/* gcc with -traditional declares the built-in strlen to return int,
and has done so at least since version 2.4.5. -- rms. */
extern int strlen (const char *);
#endif /* not __STDC__ */
#endif /* __GNUC__ */
#endif /* not __GNU_LIBRARY__ */
/* Handle permutation of arguments. */
/* Describe the part of ARGV that contains non-options that have
been skipped. `first_nonopt' is the index in ARGV of the first of them;
`last_nonopt' is the index after the last of them. */
static int first_nonopt;
static int last_nonopt;
/* Exchange two adjacent subsequences of ARGV.
One subsequence is elements [first_nonopt,last_nonopt)
which contains all the non-options that have been skipped so far.
The other is elements [last_nonopt,optind), which contains all
the options processed since those non-options were skipped.
`first_nonopt' and `last_nonopt' are relocated so that they describe
the new indices of the non-options in ARGV after they are moved. */
static void
exchange (argv)
char **argv;
{
int bottom = first_nonopt;
int middle = last_nonopt;
int top = optind;
char *tem;
/* Exchange the shorter segment with the far end of the longer segment.
That puts the shorter segment into the right place.
It leaves the longer segment in the right place overall,
but it consists of two parts that need to be swapped next. */
while (top > middle && middle > bottom)
{
if (top - middle > middle - bottom)
{
/* Bottom segment is the short one. */
int len = middle - bottom;
register int i;
/* Swap it with the top part of the top segment. */
for (i = 0; i < len; i++)
{
tem = argv[bottom + i];
argv[bottom + i] = argv[top - (middle - bottom) + i];
argv[top - (middle - bottom) + i] = tem;
}
/* Exclude the moved bottom segment from further swapping. */
top -= len;
}
else
{
/* Top segment is the short one. */
int len = top - middle;
register int i;
/* Swap it with the bottom part of the bottom segment. */
for (i = 0; i < len; i++)
{
tem = argv[bottom + i];
argv[bottom + i] = argv[middle + i];
argv[middle + i] = tem;
}
/* Exclude the moved top segment from further swapping. */
bottom += len;
}
}
/* Update records for the slots the non-options now occupy. */
first_nonopt += (optind - last_nonopt);
last_nonopt = optind;
}
/* Initialize the internal data when the first call is made. */
static const char *
_getopt_initialize (optstring)
const char *optstring;
{
/* Start processing options with ARGV-element 1 (since ARGV-element 0
is the program name); the sequence of previously skipped
non-option ARGV-elements is empty. */
first_nonopt = last_nonopt = optind = 1;
nextchar = NULL;
posixly_correct = getenv ("POSIXLY_CORRECT");
/* Determine how to handle the ordering of options and nonoptions. */
if (optstring[0] == '-')
{
ordering = RETURN_IN_ORDER;
++optstring;
}
else if (optstring[0] == '+')
{
ordering = REQUIRE_ORDER;
++optstring;
}
else if (posixly_correct != NULL)
ordering = REQUIRE_ORDER;
else
ordering = PERMUTE;
return optstring;
}
/* Scan elements of ARGV (whose length is ARGC) for option characters
given in OPTSTRING.
If an element of ARGV starts with '-', and is not exactly "-" or "--",
then it is an option element. The characters of this element
(aside from the initial '-') are option characters. If `getopt'
is called repeatedly, it returns successively each of the option characters
from each of the option elements.
If `getopt' finds another option character, it returns that character,
updating `optind' and `nextchar' so that the next call to `getopt' can
resume the scan with the following option character or ARGV-element.
If there are no more option characters, `getopt' returns `EOF'.
Then `optind' is the index in ARGV of the first ARGV-element
that is not an option. (The ARGV-elements have been permuted
so that those that are not options now come last.)
OPTSTRING is a string containing the legitimate option characters.
If an option character is seen that is not listed in OPTSTRING,
return '?' after printing an error message. If you set `opterr' to
zero, the error message is suppressed but we still return '?'.
If a char in OPTSTRING is followed by a colon, that means it wants an arg,
so the following text in the same ARGV-element, or the text of the following
ARGV-element, is returned in `optarg'. Two colons mean an option that
wants an optional arg; if there is text in the current ARGV-element,
it is returned in `optarg', otherwise `optarg' is set to zero.
If OPTSTRING starts with `-' or `+', it requests different methods of
handling the non-option ARGV-elements.
See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
Long-named options begin with `--' instead of `-'.
Their names may be abbreviated as long as the abbreviation is unique
or is an exact match for some defined option. If they have an
argument, it follows the option name in the same ARGV-element, separated
from the option name by a `=', or else the in next ARGV-element.
When `getopt' finds a long-named option, it returns 0 if that option's
`flag' field is nonzero, the value of the option's `val' field
if the `flag' field is zero.
The elements of ARGV aren't really const, because we permute them.
But we pretend they're const in the prototype to be compatible
with other systems.
LONGOPTS is a vector of `struct option' terminated by an
element containing a name which is zero.
LONGIND returns the index in LONGOPT of the long-named option found.
It is only valid when a long-named option has been found by the most
recent call.
If LONG_ONLY is nonzero, '-' as well as '--' can introduce
long-named options. */
int
_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
int argc;
char *const *argv;
const char *optstring;
const struct option *longopts;
int *longind;
int long_only;
{
optarg = NULL;
if (optind == 0)
optstring = _getopt_initialize (optstring);
if (nextchar == NULL || *nextchar == '\0')
{
/* Advance to the next ARGV-element. */
if (ordering == PERMUTE)
{
/* If we have just processed some options following some non-options,
exchange them so that the options come first. */
if (first_nonopt != last_nonopt && last_nonopt != optind)
exchange ((char **) argv);
else if (last_nonopt != optind)
first_nonopt = optind;
/* Skip any additional non-options
and extend the range of non-options previously skipped. */
while (optind < argc
&& (argv[optind][0] != '-' || argv[optind][1] == '\0'))
optind++;
last_nonopt = optind;
}
/* The special ARGV-element `--' means premature end of options.
Skip it like a null option,
then exchange with previous non-options as if it were an option,
then skip everything else like a non-option. */
if (optind != argc && !strcmp (argv[optind], "--"))
{
optind++;
if (first_nonopt != last_nonopt && last_nonopt != optind)
exchange ((char **) argv);
else if (first_nonopt == last_nonopt)
first_nonopt = optind;
last_nonopt = argc;
optind = argc;
}
/* If we have done all the ARGV-elements, stop the scan
and back over any non-options that we skipped and permuted. */
if (optind == argc)
{
/* Set the next-arg-index to point at the non-options
that we previously skipped, so the caller will digest them. */
if (first_nonopt != last_nonopt)
optind = first_nonopt;
return EOF;
}
/* If we have come to a non-option and did not permute it,
either stop the scan or describe it to the caller and pass it by. */
if ((argv[optind][0] != '-' || argv[optind][1] == '\0'))
{
if (ordering == REQUIRE_ORDER)
return EOF;
optarg = argv[optind++];
return 1;
}
/* We have found another option-ARGV-element.
Skip the initial punctuation. */
nextchar = (argv[optind] + 1
+ (longopts != NULL && argv[optind][1] == '-'));
}
/* Decode the current option-ARGV-element. */
/* Check whether the ARGV-element is a long option.
If long_only and the ARGV-element has the form "-f", where f is
a valid short option, don't consider it an abbreviated form of
a long option that starts with f. Otherwise there would be no
way to give the -f short option.
On the other hand, if there's a long option "fubar" and
the ARGV-element is "-fu", do consider that an abbreviation of
the long option, just like "--fu", and not "-f" with arg "u".
This distinction seems to be the most useful approach. */
if (longopts != NULL
&& (argv[optind][1] == '-'
|| (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
{
char *nameend;
const struct option *p;
const struct option *pfound = NULL;
int exact = 0;
int ambig = 0;
int indfound;
int option_index;
for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
/* Do nothing. */ ;
/* Test all long options for either exact match
or abbreviated matches. */
for (p = longopts, option_index = 0; p->name; p++, option_index++)
if (!strncmp (p->name, nextchar, nameend - nextchar))
{
if (nameend - nextchar == (int) strlen (p->name))
{
/* Exact match found. */
pfound = p;
indfound = option_index;
exact = 1;
break;
}
else if (pfound == NULL)
{
/* First nonexact match found. */
pfound = p;
indfound = option_index;
}
else
/* Second or later nonexact match found. */
ambig = 1;
}
if (ambig && !exact)
{
if (opterr)
fprintf (stderr, "%s: option `%s' is ambiguous\n",
argv[0], argv[optind]);
nextchar += strlen (nextchar);
optind++;
return '?';
}
if (pfound != NULL)
{
option_index = indfound;
optind++;
if (*nameend)
{
/* Don't test has_arg with >, because some C compilers don't
allow it to be used on enums. */
if (pfound->has_arg)
optarg = nameend + 1;
else
{
if (opterr)
{
if (argv[optind - 1][1] == '-')
/* --option */
fprintf (stderr,
"%s: option `--%s' doesn't allow an argument\n",
argv[0], pfound->name);
else
/* +option or -option */
fprintf (stderr,
"%s: option `%c%s' doesn't allow an argument\n",
argv[0], argv[optind - 1][0], pfound->name);
}
nextchar += strlen (nextchar);
return '?';
}
}
else if (pfound->has_arg == 1)
{
if (optind < argc)
optarg = argv[optind++];
else
{
if (opterr)
fprintf (stderr, "%s: option `%s' requires an argument\n",
argv[0], argv[optind - 1]);
nextchar += strlen (nextchar);
return optstring[0] == ':' ? ':' : '?';
}
}
nextchar += strlen (nextchar);
if (longind != NULL)
*longind = option_index;
if (pfound->flag)
{
*(pfound->flag) = pfound->val;
return 0;
}
return pfound->val;
}
/* Can't find it as a long option. If this is not getopt_long_only,
or the option starts with '--' or is not a valid short
option, then it's an error.
Otherwise interpret it as a short option. */
if (!long_only || argv[optind][1] == '-'
|| my_index (optstring, *nextchar) == NULL)
{
if (opterr)
{
if (argv[optind][1] == '-')
/* --option */
fprintf (stderr, "%s: unrecognized option `--%s'\n",
argv[0], nextchar);
else
/* +option or -option */
fprintf (stderr, "%s: unrecognized option `%c%s'\n",
argv[0], argv[optind][0], nextchar);
}
nextchar = (char *) "";
optind++;
return '?';
}
}
/* Look at and handle the next short option-character. */
{
char c = *nextchar++;
char *temp = my_index (optstring, c);
/* Increment `optind' when we start to process its last character. */
if (*nextchar == '\0')
++optind;
if (temp == NULL || c == ':')
{
if (opterr)
{
if (posixly_correct)
/* 1003.2 specifies the format of this message. */
fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
else
fprintf (stderr, "%s: invalid option -- %c\n", argv[0], c);
}
optopt = c;
return '?';
}
if (temp[1] == ':')
{
if (temp[2] == ':')
{
/* This is an option that accepts an argument optionally. */
if (*nextchar != '\0')
{
optarg = nextchar;
optind++;
}
else
optarg = NULL;
nextchar = NULL;
}
else
{
/* This is an option that requires an argument. */
if (*nextchar != '\0')
{
optarg = nextchar;
/* If we end this ARGV-element by taking the rest as an arg,
we must advance to the next element now. */
optind++;
}
else if (optind == argc)
{
if (opterr)
{
/* 1003.2 specifies the format of this message. */
fprintf (stderr, "%s: option requires an argument -- %c\n",
argv[0], c);
}
optopt = c;
if (optstring[0] == ':')
c = ':';
else
c = '?';
}
else
/* We already incremented `optind' once;
increment it again when taking next ARGV-elt as argument. */
optarg = argv[optind++];
nextchar = NULL;
}
}
return c;
}
}
int
getopt (argc, argv, optstring)
int argc;
char *const *argv;
const char *optstring;
{
return _getopt_internal (argc, argv, optstring,
(const struct option *) 0,
(int *) 0,
0);
}
/* getopt_long and getopt_long_only entry points for GNU getopt.
Copyright (C) 1987, 88, 89, 90, 91, 92, 1993
Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
it under the terms of the GNU General Public License Version 2 as
published by the Free Software Foundation. You may not use, modify or
distribute this program under any other version of the GNU General
Public License.
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. */
int
getopt_long (argc, argv, options, long_options, opt_index)
int argc;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
}
/* Like getopt_long, but '-' as well as '--' can indicate a long option.
If an option that starts with '-' (not '--') doesn't match a long option,
but does match a short option, it is parsed as a short option
instead. */
int
getopt_long_only (argc, argv, options, long_options, opt_index)
int argc;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
}
#endif /* _LIBC or not __GNU_LIBRARY__. */

20
templates/c Normal file
View file

@ -0,0 +1,20 @@
/***************************************************************************
* Copyright (C) 2007 by Arep *
* Support is provided through the forums at *
* http://www.console-tribe.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/

20
templates/h Normal file
View file

@ -0,0 +1,20 @@
/***************************************************************************
* Copyright (C) 2007 by Arep *
* Support is provided through the forums at *
* http://www.console-tribe.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/