Commit e10982fa authored by Derrick Sobodash's avatar Derrick Sobodash

Merging into Github.

parents
<?php
/**
* Methods for converting bases and addressing modes.
*
* These conversion functions handle values of the types integer or string
* only. They will not work with float values. For calculations over 64-bit,
* you must have the {@link http://www.php.net/gmp GMP library} installed. If
* GMP is not installed, the upper limit will be 32-bits.
*
* It should be noted that when submitting decimals larger than 32-bits, they
* must be enclosed in quote marks or flagged with (string) to prevent PHP
* from automatically converting them to the type float while passing them to
* the method.
*
* @author Derrick Sobodash <dsobodash@sina.com>
* @package Conversion
* @since Version 1.0.0
*/
class pirConvert
{
/**
* Returns a string containing the binary (base-2) representation of the
* given hexadecimal <i>value</i>. This method is safe to use with 64-bit
* integers. The largest number that can be converted is 18446744073709551615.
*
* pirConvert::hexbin() example:
* <code>
* <?php
* echo pirConvert::hexbin("809C");
* ?>
* </code>
*
* The above example will output:
* <pre>
* 1000000010011100
* </pre>
*
* @author Derrick Sobodash <dsobodash@sina.com>
* @since Version 1.0.0
* @return string
* @access public
* @see pirConvert::dechex, pirConvert::decbin, pirConvert::bindec, pirConvert::hexdec
*/
public function hexbin($value)
{
if(eregi("[G-Z][g-z][!--]", $value))
echo("Warning: pirConvert::hexbin(): Value is not a hexadecimal string" . LBREAK);
else if(gmp_cmp("0x$value", "0xffffffffffffffff") > 0)
echo("Warning: pirConvert::hexbin(): Value is greater than 64-bits" . LBREAK);
if(strlen($value) <= 8)
return(decbin(hexdec($value)));
else if(extension_loaded('gmp'))
{
$low = hexdec(substr($value, -8));
$high = hexdec(substr($value, 0, strlen($value) - 8));
return gmp_strval(gmp_add(gmp_mul("$high", "0x100000000"), "$low"), 2);
}
else
echo("Warning: pirConvert::hexbin(): GMP is required for integers over 32-bits" . LBREAK);
}
/**
* Returns a string containing the hexadecimal (base-16) representation of
* the given decimal <i>value</i>. This method is safe to use with 64-bit
* integers. The largest number that can be converted is 18446744073709551615.
*
* pirConvert::dechex() example:
* <code>
* <?php
* echo pirConvert::dechex("123456789123456789");
* ?>
* </code>
*
* The above example will output:
* <pre>
* 1B69B4BACD05F15
* </pre>
*
* @author Derrick Sobodash <dsobodash@sina.com>
* @since Version 1.0.0
* @return string
* @access public
* @see pirConvert::hexbin, pirConvert::decbin, pirConvert::bindec, pirConvert::hexdec
*/
public function dechex($value)
{
if(gmp_cmp("$value", "0xffffffffffffffff") > 0)
echo("Warning: pirConvert::dechex(): Value is greater than 64-bits" . LBREAK);
if(is_numeric($value) && $value <= 0xffffffff)
return dechex($value);
else if(extension_loaded('gmp'))
return gmp_strval($value, 16);
else
echo("Warning: pirConvert::dechex(): GMP is required for integers over 32-bits" . LBREAK);
}
/**
* Returns a string containing the binary (base-2) representation of the
* given decimal <i>value</i>. This method is safe to use with 64-bit
* integers. The largest number that can be converted is 18446744073709551615.
*
* pirConvert::decbin() example:
* <code>
* <?php
* echo pirConvert::decbin("123456789123456789");
* ?>
* </code>
*
* The above example will output:
* <pre>
* 110110110100110110100101110101100110100000101111100010101
* </pre>
*
* @author Derrick Sobodash <dsobodash@sina.com>
* @since Version 1.0.0
* @return string
* @access public
* @see pirConvert::hexbin, pirConvert::dechex, pirConvert::bindec, pirConvert::hexdec
*/
public function decbin($value)
{
if(gmp_cmp("$value", "0xffffffffffffffff") > 0)
echo("Warning: pirConvert::decbin(): Value is greater than 64-bits" . LBREAK);
if(is_numeric($value) && $value <= 0xffffffff)
return decbin($value);
else if(extension_loaded('gmp'))
return gmp_strval($value, 2);
else
echo("Warning: pirConvert::decbin(): GMP is required for integers over 32-bits" . LBREAK);
}
/**
* Returns an integer or string containing the decimal representation of the
* given binary string <i>value</i>. Values greater than 4294967295 will be
* returned as a string value. This method is safe to use with 64-bit
* integers. The largest number that can be converted is 18446744073709551615.
*
* pirConvert::bindec() example:
* <code>
* <?php
* echo pirConvert::bindec("110110110100110110100101110");
* ?>
* </code>
*
* The above example will output:
* <pre>
* 114978094
* </pre>
*
* @author Derrick Sobodash <dsobodash@sina.com>
* @since Version 1.0.0
* @return mixed
* @access public
* @see pirConvert::hexbin, pirConvert::dechex, pirConvert::decbin, pirConvert::hexdec
*/
public function bindec($value)
{
if(eregi("[2-9][A-Z][a-z][!--]", $bitstring))
echo("Warning: pirConvert::bindec(): bitstring is not a binary string" . LBREAK);
if(strlen($value) > 64)
echo("Warning: pirConvert::bindec(): Value is greater than 64-bits" . LBREAK);
if(strlen($value) <= 32)
return bindec($value);
else if(extension_loaded('gmp'))
{
$low = bindec(substr($value, -32));
$high = bindec(substr($value, 0, strlen($value) - 32));
return gmp_strval(gmp_add(gmp_mul("$high", "0x100000000"), "$low"));
}
else
echo("Warning: pirConvert::bindec(): GMP is required for integers over 32-bits" . LBREAK);
}
/**
* Returns an integer or string containing the decimal representation of the
* given hexadecimal string <i>value</i>. Values greater than 4294967295 will
* be returned as a string value. This method is safe to use with 64-bit
* integers. The largest number that can be converted is 18446744073709551615.
*
* pirConvert::hexdec() example:
* <code>
* <?php
* echo pirConvert::hexdec("1B69B4BACD05F15");
* ?>
* </code>
*
* The above example will output:
* <pre>
* 123456789123456789
* </pre>
*
* @author Derrick Sobodash <dsobodash@sina.com>
* @since Version 1.0.0
* @return mixed
* @access public
* @see pirConvert::hexbin, pirConvert::dechex, pirConvert::decbin, pirConvert::bindec
*/
public function hexdec($value)
{
if(strlen($value) > 16)
echo("Warning: pirConvert::hexdec(): Value is greater than 64-bits" . LBREAK);
if(strlen($value) <= 8)
return bindec($value);
else if(extension_loaded('gmp'))
{
$low = hexdec(substr($value, -8));
$high = hexdec(substr($value, 0, strlen($value) - 8));
return gmp_strval(gmp_add(gmp_mul("$high", "0x100000000"), "$low"));
}
else
echo("Warning: pirConvert::hexdec(): GMP is required for integers over 32-bits" . LBREAK);
}
/**
* Returns an integer containing a representation of the given <i>address</i>
* as it would be stored in a Super Famicom HiROM memory map. The largest
* address that can be converted is 16777215 (24-bits).
*
* pirConvert::hi2lorom() example:
* <code>
* <?php
* echo "0x" . dechex(pirConvert::hi2lorom(0x12f90));
* ?>
* </code>
*
* The above example will output:
* <pre>
* 0x2af90
* </pre>
*
* @author Derrick Sobodash <dsobodash@sina.com>
* @since Version 1.0.0
* @return int
* @access public
* @see pirConvert::lo2hirom
*/
public function hi2lorom($address)
{
if($address > 0xffffff)
echo("Warning: pirConvert::hi2lorom(): Cannot accept values greater than 24-bits" . LBREAK);
$address = ((int) ($address / 0x10000)) * 2 * 0x10000 + ($address % 0x10000);
if(($address % 0x10000) > 0x8000)
$address += 0x10000;
else
$address += 0x8000;
return(((int) ($address / 0x10000) * 0x10000) + ($address % 0x10000));
}
/**
* Returns an integer containing a representation of the given <i>address</i>
* as it would be stored in a Super Famicom LoROM memory map. The largest
* address that can be converted is 16777215 (24-bits).
*
* pirConvert::lo2hirom() example:
* <code>
* <?php
* echo "0x" . dechex(pirConvert::lo2hirom(0xb9f90));
* ?>
* </code>
*
* The above example will output:
* <pre>
* 0x59f90
* </pre>
*
* @author Derrick Sobodash <dsobodash@sina.com>
* @since Version 1.0.0
* @return int
* @access public
* @see pirConvert::hi2lorom
*/
public function lo2hirom($address)
{
if($address > 0xffffff)
echo("Warning: pirConvert::hi2lorom(): Cannot accept values greater than 24-bits" . LBREAK);
// We need to cast this calue to int type, otherwise we will get
// a floating point number
if((int) ($address / 0x10000) % 2 != 0)
$address -= 0x10000;
else
$address -= 0x8000;
return((int) ($address / 0x10000) * 0x8000 + ($address % 0x10000));
}
}
?>
<?
/**
* Methods for serializing and unserializing data.
*
* These data functions are used for serializing integers to binary strings. An
* unserialize function is provided to unserialize a single binary string to
* an integer.
*
* The serialize and unserialize members of this function are related to PHP's
* native {@link http://www.php.net/manual/en/function.pack.php pack()} and
* {@link http://www.php.net/manual/en/function.unpack.php unpack()} functions.
* However, libPirate's functions serialize and unserialize only a single
* value, not a repeating pattern of values.
*
* @author Derrick Sobodash <dsobodash@sina.com>
* @package Data
* @since Version 1.0.0
*/
class pirData
{
/**
* Returns a byte string containing a serialized representation of the given
* <i>number</i>. The largest number that can be serialized is 255.
*
* pirData::byte() example:
* <code>
* <?php
* echo bin2hex(pirData::byte(19));
* ?>
* </code>
*
* The above example will output:
* <pre>
* 13
* </pre>
*
* @author Derrick Sobodash <dsobodash@sina.com>
* @since Version 1.0.0
* @return string
* @access public
* @see pirData::word(), pirData::dword()
*/
public function byte($number)
{
if($number > 0xff)
echo("Warning: pirData::byte(): Integer cannot exceed 0xff" . LBREAK);
return(chr($number));
}
/**
* Returns a byte string containing a serialized representation of the given
* <i>number</i>. The largest number that can be serialized is 65535.
*
* pirData::word() example:
* <code>
* <?php
* echo bin2hex(pirData::word(359));
* ?>
* </code>
*
* The above example will output:
* <pre>
* 6701
* </pre>
*
* @author Derrick Sobodash <dsobodash@sina.com>
* @since Version 1.0.0
* @return string
* @access public
* @see pirData::byte(), pirData::dword()
*/
public function word($number, $endian = "little")
{
if($number > 0xffff)
echo("Warning: pirData::word(): Integer cannot exceed 0xffff" . LBREAK);
if($endian == "big")
return(pack("n", $number));
else
return(pack("v", $number));
}
/**
* Returns a byte string containing a serialized representation of the given
* <i>number</i>. The largest number that can be serialized is 4294967295.
*
* pirData::dword() example:
* <code>
* <?php
* echo bin2hex(pirData::dword(62670109));
* ?>
* </code>
*
* The above example will output:
* <pre>
* 1D45BC01
* </pre>
*
* @author Derrick Sobodash <dsobodash@sina.com>
* @since Version 1.0.0
* @return string
* @access public
* @see pirData::byte(), pirData::word()
*/
public function dword($number, $endian = "little")
{
if($number > 0xffffffff)
echo("Warning: pirData::dword(): Integer cannot exceed 0xffffffff" . LBREAK);
if($endian == "big")
return(pack("N", $number));
else
return(pack("V", $number));
}
/**
* Returns a byte string containing a serialized representation of the given
* <i>number</i> into a <i>bits</i>-bit byte string. This method is safe to
* use with 64-bit integers. The largest number that can be serialized is
* 18446744073709551615.
*
* pirData::serialize() example:
* <code>
* <?php
* echo bin2hex(pirData::serialize(31092, 48));
* ?>
* </code>
*
* The above example will output:
* <pre>
* 747900000000
* </pre>
*
* @author Derrick Sobodash <dsobodash@sina.com>
* @since Version 1.0.0
* @return string
* @access public
* @see pirData::unserialize()
*/
public function serialize($number, $bits = 16, $endian = "little")
{
if(
$bits > 64 ||
gmp_cmp("$number", "0xffffffffffffffff") > 0
)
echo("Warning: pirData::serialize(): Bits specified exceed 64" . LBREAK);
else if(
($bits == 8 && $number > 0xff) ||
($bits == 16 && $number > 0xffff) ||
($bits == 24 && $number > 0xffffff) ||
($bits == 32 && $number > 0xffffffff) ||
($bits == 40 && gmp_cmp("$number", "0xffffffffff") > 0) ||
($bits == 48 && gmp_cmp("$number", "0xffffffffffff") > 0) ||
($bits == 56 && gmp_cmp("$number", "0xffffffffffffff") > 0) ||
($bits == 64 && gmp_cmp("$number", "0xffffffffffffffff") > 0)
)
echo("Warning: pirData::serialize(): Integer exceeds specified bits" . LBREAK);
if(is_numeric($number) && $number <= 0xffffffff)
{
if($endian == "big")
return(substr(pack("N", $number), 4 - $bits / 8));
else
return(substr(pack("V", $number), 0, $bits / 8));
}
else if(extension_loaded('gmp'))
{
$high = gmp_strval(gmp_div($number, "0x100000000"), 16);
$low = gmp_strval(gmp_mod($number, "0x100000000"), 16);
if(strlen($high) % 2 > 0)
$high = "0" . $high;
if($endian == "big")
return(substr(pack("H*", $high) . pack("H*", $low), 8 - $bits / 8));
else
return(substr(strrev(pack("H*", $low)) . strrev(pack("H*", $high)), 0, $bits / 8));
}
else
echo("Warning: pirData:serial(): GMP is required for integers over 32-bits" . LBREAK);
}
/**
* Returns an integer or string containing an unserialized representation of
* the given <i>bytes</i>. Values greater than 4294967295 will be returned
* as a string value. This method is safe to use with 64-bit binary strings.
* The longest binary string that can be handled is 8 characters.
*
* pirData::unserialize() example:
* <code>
* <?php
* echo pirData::unserialize("\x34\x90\xCB\xC7");
* ?>
* </code>
*
* The above example will output:
* <pre>
* 3352006708
* </pre>
*
* @author Derrick Sobodash <dsobodash@sina.com>
* @since Version 1.0.0
* @return int
* @access public
* @see pirData::serialize()
*/
public function unserialize($bytes, $endian = "little")
{
if($this->endian != "big")
$bytes = strrev($bytes);
if(strlen($bytes) <= 4)
return(hexdec(bin2hex($bytes)));
else if(extension_loaded('gmp'))
{
$low = hexdec(bin2hex((substr($bytes, -4))));
$high = hexdec(bin2hex((substr($bytes, 0, strlen($bytes) - 4))));
return(gmp_strval(gmp_add(gmp_mul("$high", "0x100000000"), "$low")));
}
else
echo("Warning: pirData::unserialize(): GMP is required for byte strings over 32-bits" . LBREAK);
}
}
?>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
<?php
/**
* libPirate PHP Library
*
* libPirate is the library result of my last 10 years of translating video
* games and working with bitplane graphics.
*
* Unlike most people in the scene, I chose PHP as the primary language for
* all my programming tasks. What drew me to PHP over more common languages
* like C/C++/C# is its powerful string handling. Its loose typing and built
* in library of hundreds of string and array handling functions make it
* ideal for small tasks like script dumping, insertion, and simple graphic
* conversion and manipulation.
*
* Over the last several years, I have developed FEIDIAN, one of the more
* powerful bitplane graphic extractors around due it its user-friendly custom
* tile format which requires no programming knowledge nor even a development
* environment to use and extend, and NINJA, an implementation for my patch
* format and many others. I have also written my own tools for every project
* I've worked on and some commercial projects for SuperFighter.com.
*
* Over the years, I found myself constantly recycling the same code: so in
* late 2005, I decided to begin a library to make this code more accessible
* to myself and to others. libPirate provides a powerful back-end for any
* ROM hacking project. Due to PHP's scriptable nature and inclusion of
* sysem() and exec() functions, you could easily make one PHP script to
* double-click and perform the entire process for your game rather than a
* batch file shelling dozens of small, recycled console applications.
*
* Please thoroughly review libPirate's packages. They have been categorized
* based on what they do. All functions are grouped together as class methods.
* I chose to do this rather than have free-floating functions because it
* allows me to use some more logical names that have been gobbled up by
* PHP's internal functions, and it prevents libPirate's functions from
* colliding with any in your application.
*
* I hope you will find this library useful for your own projects.
*
* @copyright (c) 2006, Derrick Sobodash
* @link http://www.libpirate.org/
* @version 1.0.0
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
* @package Default
*/
/**
* ----------------------------------------------
* SETUP
* ----------------------------------------------
*/
/**
* Define the current version so people using libPirate have something they
* can check to be sure of compatability.
* @ignore
*/
define("LIBPIRATE_VER", 20060727);
/**
* Define what kinds of line breaks to render to console output. This variable
* is used with verbose output and error messages.
*/
define("LBREAK", "\r\n");
/**
* Print a notice the currenct shell script is using libPirate.
* You are free to comment this out.
*/
echo "libPirate v" . LIBPIRATE_VER . " (http://www.libpirate.org/)" . LBREAK;
/**
* Initialize the PHP GMP module before starting libPirate, warn if GMP is
* not found in the user's path.
*/
if(!extension_loaded('gmp'))
{
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN')
dl('php_gmp.dll');
else
dl('gmp.so');
}
if(!extension_loaded('gmp'))
echo("Warning: The GNU MP library was not loaded; 64-bit aritmatic will not be available\n\n");
/**
* ----------------------------------------------
* DEFINES
* ----------------------------------------------
*/
/**
* Define KBIT as meaning 0x80 bytes
*/
define("KBIT", 0x80);
/**
* Define MBIT as meaning 0x20000 bytes
*/
define("MBIT", 0x20000);
/**
* Define GBIT as meaning 0x8000000 bytes
*/
define("GBIT", 0x8000000);
/**
* Define KBYTE as meaning 0x400 bytes
*/
define("KBYTE", 0x400);
/**
* Define MBYTE as meaning 0x100000 bytes
*/
define("MBYTE", 0x100000);
/**
* Define GBYTE as meaning 0x40000000 bytes
*/
define("GBYTE", 0x40000000);
/**
* Define a SNES header as 512 bytes. The SNES header size is shared by
* several other system's ROM images.
*/
define("SNES_HEADER", 0x200);
/**
* ----------------------------------------------
* HELPER CLASSES
* ----------------------------------------------
*/
include_once("classes/pirData.php");
include_once("classes/pirConvert.php");
/**
* ----------------------------------------------
* HANDLER CLASSES
* ----------------------------------------------
*/
include_once("classes/pirRead.php");
include_once("classes/pirPatch.php");
include_once("classes/pirString.php");
/**
* ----------------------------------------------
* STRUCTURES
* ----------------------------------------------
*/
include_once("types/pirTypeFile.php");
include_once("types/pirTypeFileSFAM.php");
include_once("types/pirTypeFileFAM.php");
include_once("types/pirTypeFileMEGA.php");
include_once("types/pirTypeFileSMS.php");
include_once("types/pirTypeFileGB.php");
include_once("types/pirTypeFileLYNX.php");
include_once("types/pirTypeFilePCE.php");
include_once("types/pirTypeFileN64.php");
include_once("types/pirTypePatch.php");