mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-22 05:45:38 +00:00
This commit is contained in:
parent
9788eb4750
commit
a1c9f6cf92
184
config.c
Normal file
184
config.c
Normal file
|
@ -0,0 +1,184 @@
|
|||
#include "model3.h"
|
||||
#include "expat.h"
|
||||
|
||||
enum
|
||||
{
|
||||
ELEMENT_NONE = 1,
|
||||
ELEMENT_CONFIG,
|
||||
ELEMENT_ROMPATH,
|
||||
ELEMENT_GAMELIST,
|
||||
ELEMENT_BACKUPPATH,
|
||||
ELEMENT_WIDTH,
|
||||
ELEMENT_HEIGHT,
|
||||
ELEMENT_FULLSCREEN,
|
||||
ELEMENT_FPSLIMIT,
|
||||
ELEMENT_STRETCH,
|
||||
};
|
||||
|
||||
static STRING_ID element_id[] =
|
||||
{
|
||||
{ "config", ELEMENT_CONFIG },
|
||||
{ "rom_path", ELEMENT_ROMPATH },
|
||||
{ "gamelist", ELEMENT_GAMELIST },
|
||||
{ "backup_path", ELEMENT_BACKUPPATH },
|
||||
{ "width", ELEMENT_WIDTH },
|
||||
{ "height", ELEMENT_HEIGHT },
|
||||
{ "fullscreen", ELEMENT_FULLSCREEN },
|
||||
{ "fps_limit", ELEMENT_FPSLIMIT },
|
||||
{ "stretch", ELEMENT_STRETCH },
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
static STRING_ID boolean_id[] =
|
||||
{
|
||||
{ "yes", TRUE },
|
||||
{ "no", FALSE },
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
static UINT8 *config_file;
|
||||
static int current_element;
|
||||
|
||||
|
||||
static void XMLCALL element_start(void *data, const char *el, const char **attr)
|
||||
{
|
||||
int element = get_string_id(el, element_id);
|
||||
|
||||
if (element < 0)
|
||||
{
|
||||
message(0, "Unknown element %s while parsing XML file\n", el);
|
||||
}
|
||||
else
|
||||
{
|
||||
current_element = element;
|
||||
}
|
||||
}
|
||||
|
||||
static void XMLCALL element_end(void *data, const char *el)
|
||||
{
|
||||
int element = get_string_id(el, element_id);
|
||||
|
||||
if (element < 0)
|
||||
{
|
||||
message(0, "Unknown element %s while parsing XML\n", el);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (element)
|
||||
{
|
||||
case ELEMENT_CONFIG:
|
||||
case ELEMENT_ROMPATH:
|
||||
case ELEMENT_GAMELIST:
|
||||
case ELEMENT_BACKUPPATH:
|
||||
case ELEMENT_WIDTH:
|
||||
case ELEMENT_HEIGHT:
|
||||
case ELEMENT_FULLSCREEN:
|
||||
case ELEMENT_FPSLIMIT:
|
||||
case ELEMENT_STRETCH:
|
||||
{
|
||||
current_element = ELEMENT_NONE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void XMLCALL character_data(void *data, const char *s, int len)
|
||||
{
|
||||
char temp[2000];
|
||||
memcpy(temp, s, len);
|
||||
temp[len] = 0;
|
||||
|
||||
switch (current_element)
|
||||
{
|
||||
case ELEMENT_ROMPATH:
|
||||
{
|
||||
strcpy(m3_config.rom_path, temp);
|
||||
break;
|
||||
}
|
||||
case ELEMENT_GAMELIST:
|
||||
{
|
||||
strcpy(m3_config.rom_list, temp);
|
||||
break;
|
||||
}
|
||||
case ELEMENT_BACKUPPATH:
|
||||
{
|
||||
strcpy(m3_config.backup_path, temp);
|
||||
break;
|
||||
}
|
||||
case ELEMENT_WIDTH:
|
||||
{
|
||||
int width;
|
||||
sscanf(temp, "%d", &width);
|
||||
m3_config.width = width;
|
||||
break;
|
||||
}
|
||||
case ELEMENT_HEIGHT:
|
||||
{
|
||||
int height;
|
||||
sscanf(temp, "%d", &height);
|
||||
m3_config.height = height;
|
||||
break;
|
||||
}
|
||||
case ELEMENT_FULLSCREEN:
|
||||
{
|
||||
BOOL fullscreen = get_string_id(temp, boolean_id);
|
||||
m3_config.fullscreen = fullscreen;
|
||||
break;
|
||||
}
|
||||
case ELEMENT_FPSLIMIT:
|
||||
{
|
||||
BOOL fpslimit = get_string_id(temp, boolean_id);
|
||||
m3_config.fps_limit = fpslimit;
|
||||
break;
|
||||
}
|
||||
case ELEMENT_STRETCH:
|
||||
{
|
||||
BOOL stretch = get_string_id(temp, boolean_id);
|
||||
m3_config.stretch = stretch;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOL parse_config(const char *config_name)
|
||||
{
|
||||
XML_Parser parser;
|
||||
|
||||
int length;
|
||||
FILE *file;
|
||||
|
||||
file = open_file(FILE_READ|FILE_BINARY, "%s", config_name);
|
||||
if (file == NULL)
|
||||
{
|
||||
message(0, "Couldn't open %s", config_name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
length = (int)get_open_file_size(file);
|
||||
|
||||
config_file = (UINT8*)malloc(length);
|
||||
|
||||
if (!read_from_file(file, config_file, length))
|
||||
{
|
||||
message(0, "I/O error while reading %s", config_name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
close_file(file);
|
||||
|
||||
// parse the XML file
|
||||
parser = XML_ParserCreate(NULL);
|
||||
|
||||
XML_SetElementHandler(parser, element_start, element_end);
|
||||
XML_SetCharacterDataHandler(parser, character_data);
|
||||
|
||||
if (XML_Parse(parser, config_file, length, 1) != XML_STATUS_OK)
|
||||
{
|
||||
message(0, "Error while parsing the XML file %s", config_name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
XML_ParserFree(parser);
|
||||
return TRUE;
|
||||
}
|
22
config.xml
Normal file
22
config.xml
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE config [
|
||||
<!ELEMENT config (rom_path?, gamelist?, backup_path?, width?, height?, fullscreen?, fps_limit?)>
|
||||
<!ELEMENT rom_path (#PCDATA)>
|
||||
<!ELEMENT gamelist (#PCDATA)>
|
||||
<!ELEMENT backup_path (#PCDATA)>
|
||||
<!ELEMENT width (#PCDATA)>
|
||||
<!ELEMENT height (#PCDATA)>
|
||||
<!ELEMENT fullscreen (#PCDATA)>
|
||||
<!ELEMENT fps_limit (#PCDATA)>
|
||||
]>
|
||||
|
||||
<config>
|
||||
<rom_path>c:\devmame\roms</rom_path>
|
||||
<gamelist>games.xml</gamelist>
|
||||
<backup_path>c:\code\supermodel2\backup</backup_path>
|
||||
<width>1280</width>
|
||||
<height>1024</height>
|
||||
<fullscreen>yes</fullscreen>
|
||||
<fps_limit>no</fps_limit>
|
||||
<stretch>yes</stretch>
|
||||
</config>
|
492
core/bridge.c
Normal file
492
core/bridge.c
Normal file
|
@ -0,0 +1,492 @@
|
|||
/*
|
||||
* Sega Model 3 Emulator
|
||||
* Copyright (C) 2003 Bart Trzynadlowski, Ville Linde, Stefano Teso
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 (license.txt); if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* bridge.c
|
||||
*
|
||||
* MPC105 and MPC106 PCI bridge/memory controller emulation.
|
||||
*
|
||||
* Warning: Portability hazard. Code assumes it is running on a little endian
|
||||
* machine.
|
||||
*
|
||||
* NOTE: Data written to the bridge controller is byte-reversed by the PPC.
|
||||
* This is to make it little endian.
|
||||
*/
|
||||
|
||||
#include "model3.h"
|
||||
|
||||
/******************************************************************/
|
||||
/* Internal Bridge State */
|
||||
/******************************************************************/
|
||||
|
||||
/*
|
||||
* Macros for Register Access
|
||||
*
|
||||
* Assuming a little endian system (portability hazard!)
|
||||
*/
|
||||
|
||||
#define DWORD(addr) *((UINT32 *) ®s[addr])
|
||||
#define WORD(addr) *((UINT16 *) ®s[addr])
|
||||
#define BYTE(addr) regs[addr]
|
||||
|
||||
/*
|
||||
* Bridge State
|
||||
*
|
||||
* This code is intended for use on little-endian systems. Data from the
|
||||
* registers should be returned as if a big endian read was performed (thus
|
||||
* returning the little endian word 0x1057 as 0x5710.)
|
||||
*
|
||||
* The DWORD() and WORD() macros only work on little endian systems and are
|
||||
* intended to set up the bridge state. Reads and writes using the handlers
|
||||
* are done in big endian fashion by manually breaking down the data into
|
||||
* bytes.
|
||||
*
|
||||
* To make this code fully portable, it would probably be enough to remove
|
||||
* the DWORD() and WORD() macros.
|
||||
*/
|
||||
|
||||
static UINT8 regs[0x100];
|
||||
static UINT8 config_data[4]; // data for last CONFIG_ADDR command
|
||||
static UINT32 reg_ptr; // current register address
|
||||
|
||||
/******************************************************************/
|
||||
/* Interface */
|
||||
/******************************************************************/
|
||||
|
||||
/*
|
||||
* Callback for Bus Commands
|
||||
*
|
||||
* Note that there are no callbacks for reads/writes to CONFIG_DATA yet as
|
||||
* the need for them has not yet appeared.
|
||||
*/
|
||||
|
||||
static UINT32 (*config_addr_callback)(UINT32);
|
||||
|
||||
/*
|
||||
* UINT8 bridge_read_8(UINT32 addr);
|
||||
*
|
||||
* Reads directly from a register. The lower 8 bits of the address are the
|
||||
* register to read from. This is intended for the MPC105 which can map its
|
||||
* internal registers to 0xF8FFF0xx.
|
||||
*
|
||||
* Parameters:
|
||||
* addr = Address (only lower 8 bits matter.)
|
||||
*
|
||||
* Returns:
|
||||
* Data read.
|
||||
*/
|
||||
|
||||
UINT8 bridge_read_8(UINT32 addr)
|
||||
{
|
||||
LOG("model3.log", "RB REG%02X\n", addr & 0xff);
|
||||
|
||||
return BYTE(addr & 0xff);
|
||||
}
|
||||
|
||||
/*
|
||||
* UINT16 bridge_read_16(UINT32 addr);
|
||||
*
|
||||
* Reads directly from a register. The lower 8 bits of the address are the
|
||||
* register to read from. This is intended for the MPC105 which can map its
|
||||
* internal registers to 0xF8FFF0xx.
|
||||
*
|
||||
* Bit 0 is masked off to ensure 16-bit alignment (I'm not sure how a real
|
||||
* PCIBMC would handle this.)
|
||||
*
|
||||
* Parameters:
|
||||
* addr = Address (only lower 8 bits matter.)
|
||||
*
|
||||
* Returns:
|
||||
* Data read.
|
||||
*/
|
||||
|
||||
UINT16 bridge_read_16(UINT32 addr)
|
||||
{
|
||||
LOG("model3.log", "RH REG%02X\n", addr & 0xff);
|
||||
addr &= 0xfe;
|
||||
return (BYTE(addr + 0) << 8) | BYTE(addr + 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* UINT32 bridge_read_32(UINT32 addr);
|
||||
*
|
||||
* Reads directly from a register. The lower 8 bits of the address are the
|
||||
* register to read from. This is intended for the MPC105 which can map its
|
||||
* internal registers to 0xF8FFF0xx.
|
||||
*
|
||||
* The lower 2 bits are masked off to ensure 32-bit alignment.
|
||||
*
|
||||
* Parameters:
|
||||
* addr = Address (only lower 8 bits matter.)
|
||||
*
|
||||
* Returns:
|
||||
* Data read.
|
||||
*/
|
||||
|
||||
UINT32 bridge_read_32(UINT32 addr)
|
||||
{
|
||||
LOG("model3.log", "RW REG%02X\n", addr & 0xff);
|
||||
addr &= 0xfc;
|
||||
return (BYTE(addr + 0) << 24) | (BYTE(addr + 1) << 16) |
|
||||
(BYTE(addr + 2) << 8) | BYTE(addr + 3);
|
||||
}
|
||||
|
||||
/*
|
||||
* void bridge_write_8(UINT32 addr, UINT8 data);
|
||||
*
|
||||
* Writes directly to a register. Only the lower 8 bits matter. This is
|
||||
* intended for the MPC105.
|
||||
*
|
||||
* Arguments:
|
||||
* addr = Address (only lower 8 bits matter.)
|
||||
* data = Data to write.
|
||||
*/
|
||||
|
||||
void bridge_write_8(UINT32 addr, UINT8 data)
|
||||
{
|
||||
LOG("model3.log", "REG%02X=%02X\n", addr & 0xff, data);
|
||||
BYTE(addr & 0xff) = data;
|
||||
}
|
||||
|
||||
/*
|
||||
* void bridge_write_16(UINT32 addr, UINT16 data);
|
||||
*
|
||||
* Writes directly to a register. Only the lower 8 bits matter. This is
|
||||
* intended for the MPC105.
|
||||
*
|
||||
* Bit 0 is masked off to ensure 16-bit alignment.
|
||||
*
|
||||
* Arguments:
|
||||
* addr = Address (only lower 8 bits matter.)
|
||||
* data = Data to write.
|
||||
*/
|
||||
|
||||
void bridge_write_16(UINT32 addr, UINT16 data)
|
||||
{
|
||||
LOG("model3.log", "REG%02X=%02X%02X\n", addr & 0xff, data & 0xff, (data >> 8) & 0xff);
|
||||
addr &= 0xfe;
|
||||
BYTE(addr + 0) = data >> 8;
|
||||
BYTE(addr + 1) = (UINT8) data;
|
||||
}
|
||||
|
||||
/*
|
||||
* void bridge_write_32(UINT32 addr, UINT32 data);
|
||||
*
|
||||
* Writes directly to a register. Only the lower 8 bits matter. This is
|
||||
* intended for the MPC105.
|
||||
*
|
||||
* The lower 2 bits are masked off to ensure 32-bit alignment.
|
||||
*
|
||||
* Arguments:
|
||||
* addr = Address (only lower 8 bits matter.)
|
||||
* data = Data to write.
|
||||
*/
|
||||
|
||||
void bridge_write_32(UINT32 addr, UINT32 data)
|
||||
{
|
||||
LOG("model3.log", "REG%02X=%02X%02X%02X%02X\n", addr & 0xff, data & 0xff, (data >> 8) & 0xff, (data >> 16) & 0xff, (data >> 24) & 0xff);
|
||||
addr &= 0xfc;
|
||||
BYTE(addr + 0) = data >> 24;
|
||||
BYTE(addr + 1) = data >> 16;
|
||||
BYTE(addr + 2) = data >> 8;
|
||||
BYTE(addr + 3) = data;
|
||||
}
|
||||
|
||||
/*
|
||||
* UINT8 bridge_read_config_data_8(UINT32 addr);
|
||||
*
|
||||
* Reads from CONFIG_DATA offset 0 to 3. Only the lower 2 bits of the address
|
||||
* are checked to determine which byte to read. I'm not sure whether this is
|
||||
* correct behavior (perhaps all byte offsets return the same data.)
|
||||
*
|
||||
* Parameters:
|
||||
* addr = Address to read from (only lower 2 bits matter.)
|
||||
*
|
||||
* Returns:
|
||||
* Data read.
|
||||
*/
|
||||
|
||||
UINT8 bridge_read_config_data_8(UINT32 addr)
|
||||
{
|
||||
return config_data[addr & 3];
|
||||
// return BYTE(reg_ptr + (addr & 3));
|
||||
}
|
||||
|
||||
/*
|
||||
* UINT16 bridge_read_config_data_16(UINT32 addr);
|
||||
*
|
||||
* Reads from CONFIG_DATA offset 0 or 2. Only bit 1 of the address is checked
|
||||
* to determine which word to read. I'm not sure whether this is correct
|
||||
* behavior for word reads (both words might return the same data, for
|
||||
* example.)
|
||||
*
|
||||
* Parameters:
|
||||
* addr = Address to read from (only bit 1 matters.)
|
||||
*
|
||||
* Returns:
|
||||
* Data read.
|
||||
*/
|
||||
|
||||
UINT16 bridge_read_config_data_16(UINT32 addr)
|
||||
{
|
||||
return (config_data[(addr & 2) + 0] << 8) | config_data[(addr & 2) + 1];
|
||||
// return (BYTE(reg_ptr + (addr & 2) + 0) << 8) |
|
||||
// BYTE(reg_ptr + (addr & 2) + 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* UINT32 bridge_read_config_data_32(UINT32 addr);
|
||||
*
|
||||
* Reads from CONFIG_DATA. The address argument is ignored because it is
|
||||
* assumed that this function is only called for valid CONFIG_DATA addresses.
|
||||
*
|
||||
* Parameters:
|
||||
* addr = Ignored.
|
||||
*
|
||||
* Returns:
|
||||
* Data read.
|
||||
*/
|
||||
|
||||
UINT32 bridge_read_config_data_32(UINT32 addr)
|
||||
{
|
||||
LOG("model3.log", "%08X: READ CONFIG DATA\n", ppc_get_pc());
|
||||
return (config_data[0] << 24) | (config_data[1] << 16) |
|
||||
(config_data[2] << 8) | config_data[3];
|
||||
// return (BYTE(reg_ptr + 0) << 24) | (BYTE(reg_ptr + 1) << 16) |
|
||||
// (BYTE(reg_ptr + 2) << 8) | BYTE(reg_ptr + 3);
|
||||
}
|
||||
|
||||
/*
|
||||
* void bridge_write_config_addr_32(UINT32 addr, UINT32 data);
|
||||
*
|
||||
* Writes to CONFIG_ADDR. The address argument is ignored because it is
|
||||
* assumed that this function is only called for valid CONFIG_ADDR addresses.
|
||||
*
|
||||
* Parameters:
|
||||
* addr = Ignored.
|
||||
* data = Data to write.
|
||||
*/
|
||||
|
||||
void bridge_write_config_addr_32(UINT32 addr, UINT32 data)
|
||||
{
|
||||
UINT32 callback_data;
|
||||
|
||||
/*
|
||||
* I'm not sure how the bridge controller distinguishes between indirect
|
||||
* register accesses and accesses which must be passed to some device on
|
||||
* the PCI bus.
|
||||
*
|
||||
* Currently, I test to see if the command is of the format 0x800000XX,
|
||||
* and if so, I return put register data in the return buffer
|
||||
* (config_data), otherwise I invoke the callback.
|
||||
*/
|
||||
|
||||
|
||||
// LOG("model3.log", "CONFIG_ADDR=%02X%02X%02X%02X @ %08X", data & 0xff, (data >> 8) & 0xff, (data >> 16) & 0xff, (data >> 24) & 0xff, PowerPC_ReadIntegerRegister(POWERPC_IREG_PC));
|
||||
// reg_ptr = data >> 24; // remember, data comes in little endian form
|
||||
// // see page 3-15 of MPC106UM/D REV.1
|
||||
|
||||
if ((data & 0x00ffffff) == 0x00000080) // indirect register access (little endian data, see page 3-15 of MPC106UM/D REV.1)
|
||||
{
|
||||
reg_ptr = data >> 24;
|
||||
config_data[0] = BYTE(reg_ptr + 0);
|
||||
config_data[1] = BYTE(reg_ptr + 1);
|
||||
config_data[2] = BYTE(reg_ptr + 2);
|
||||
config_data[3] = BYTE(reg_ptr + 3);
|
||||
}
|
||||
else // pass it to the callback
|
||||
{
|
||||
if (config_addr_callback != NULL)
|
||||
{
|
||||
callback_data = config_addr_callback(BSWAP32(data));
|
||||
callback_data = BSWAP32(callback_data); // so we can return as little endian
|
||||
}
|
||||
else
|
||||
callback_data = 0xFFFFFFFF;
|
||||
|
||||
config_data[0] = callback_data >> 24;
|
||||
config_data[1] = callback_data >> 16;
|
||||
config_data[2] = callback_data >> 8;
|
||||
config_data[3] = callback_data;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* void bridge_write_config_data_8(UINT32 addr, UINT8 data);
|
||||
*
|
||||
* Writes to CONFIG_DATA. The lower 2 bits determine which byte offset to
|
||||
* write to.
|
||||
*
|
||||
* Parameters:
|
||||
* addr = Address to write to (only lower 2 bits matter.)
|
||||
* data = Data to write.
|
||||
*/
|
||||
|
||||
void bridge_write_config_data_8(UINT32 addr, UINT8 data)
|
||||
{
|
||||
// LOG("model3.log", "CONFIG_DATA=%02X @ %08X", data, PowerPC_ReadIntegerRegister(POWERPC_IREG_PC));
|
||||
BYTE(reg_ptr + (addr & 3)) = data;
|
||||
config_data[addr & 3] = data;
|
||||
}
|
||||
|
||||
/*
|
||||
* void bridge_write_config_data_16(UINT32 addr, UINT16 data);
|
||||
*
|
||||
* Writes to CONFIG_DATA. Only bit 1 of the address is checked to determine
|
||||
* which word to write to.
|
||||
*
|
||||
* Parameters:
|
||||
* addr = Address to write to (only bit 1 matters.)
|
||||
* data = Data to write.
|
||||
*/
|
||||
|
||||
void bridge_write_config_data_16(UINT32 addr, UINT16 data)
|
||||
{
|
||||
BYTE(reg_ptr + (addr & 2) + 0) = data >> 8;
|
||||
BYTE(reg_ptr + (addr & 2) + 1) = (UINT8) data;
|
||||
config_data[(addr & 2) + 0] = data >> 8;
|
||||
config_data[(addr & 2) + 1] = (UINT8) data;
|
||||
// LOG("model3.log", "CONFIG_DATA=%04X @ %08X", WORD(reg_ptr), PowerPC_ReadIntegerRegister(POWERPC_IREG_PC));
|
||||
}
|
||||
|
||||
/*
|
||||
* void bridge_write_config_data_32(UINT32 addr, UINT32 data);
|
||||
*
|
||||
* Writes to CONFIG_DATA. The address argument is ignored because it is
|
||||
* assumed that this function is only called for valid CONFIG_DATA addresses.
|
||||
*
|
||||
* Parameters:
|
||||
* addr = Ignored.
|
||||
* data = Data to write.
|
||||
*/
|
||||
|
||||
void bridge_write_config_data_32(UINT32 addr, UINT32 data)
|
||||
{
|
||||
BYTE(reg_ptr + 0) = data >> 24;
|
||||
BYTE(reg_ptr + 1) = data >> 16;
|
||||
BYTE(reg_ptr + 2) = data >> 8;
|
||||
BYTE(reg_ptr + 3) = data;
|
||||
config_data[0] = data >> 24;
|
||||
config_data[1] = data >> 16;
|
||||
config_data[2] = data >> 8;
|
||||
config_data[3] = data;
|
||||
// LOG("model3.log", "CONFIG_DATA=%08X @ %08X", DWORD(reg_ptr), PowerPC_ReadIntegerRegister(POWERPC_IREG_PC));
|
||||
}
|
||||
|
||||
/*
|
||||
* void bridge_save_state(FILE *fp);
|
||||
*
|
||||
* Saves the bridge controller state by writing it out to a file.
|
||||
*
|
||||
* Parameters:
|
||||
* fp = File to write to.
|
||||
*/
|
||||
|
||||
void bridge_save_state(FILE *fp)
|
||||
{
|
||||
fwrite(regs, sizeof(UINT8), 0x100, fp);
|
||||
fwrite(config_data, sizeof(UINT8), 4, fp);
|
||||
fwrite(®_ptr, sizeof(UINT32), 1, fp);
|
||||
}
|
||||
|
||||
/*
|
||||
* void bridge_load_state(FILE *fp);
|
||||
*
|
||||
* Loads the bridge controller state by reading it in from a file.
|
||||
*
|
||||
* Parameters:
|
||||
* fp = File to read from.
|
||||
*/
|
||||
|
||||
void bridge_load_state(FILE *fp)
|
||||
{
|
||||
fread(regs, sizeof(UINT8), 0x100, fp);
|
||||
fread(config_data, sizeof(UINT8), 4, fp);
|
||||
fread(®_ptr, sizeof(UINT32), 1, fp);
|
||||
}
|
||||
|
||||
/*
|
||||
* void bridge_reset(INT device);
|
||||
*
|
||||
* Initializes the bridge controller's internal state.
|
||||
*
|
||||
* Memory control configuration 1 is to be set to 0xFFn20000, where n is data
|
||||
* sampled from signals sent by hardware to the MPC105 (see the MPC105
|
||||
* manual.) For Model 3, I'm guessing that n == 0.
|
||||
*
|
||||
* Parameters:
|
||||
* device = Device ID of the bridge to emulate (1 = MPC105, 2 = MPC106.)
|
||||
* If it is not one of these values, behavior is undefined.
|
||||
*/
|
||||
|
||||
void bridge_reset(INT device)
|
||||
{
|
||||
if (device == 1)
|
||||
LOG("model3.log", "Using MPC105\n");
|
||||
else if (device == 2)
|
||||
LOG("model3.log", "Using MPC106\n");
|
||||
else
|
||||
LOG("model3.log", "ERROR: Unknown bridge controller device ID (%d)\n", device);
|
||||
|
||||
memset(regs, 0, sizeof(UINT8) * 0x100);
|
||||
memset(config_data, 0, sizeof(UINT8) * 4);
|
||||
reg_ptr = 0;
|
||||
|
||||
/*
|
||||
* Set up common fields
|
||||
*/
|
||||
|
||||
WORD(0x00) = 0x1057; // vendor ID (Motorola)
|
||||
WORD(0x02) = device; // device ID
|
||||
WORD(0x04) = 0x0006; // PCI command
|
||||
WORD(0x06) = 0x0080; // PCI status
|
||||
BYTE(0x08) = 0x00; // revision ID (?)
|
||||
BYTE(0x0b) = 0x06; // class code
|
||||
DWORD(0xa8) = 0xff000010; // processor interface configuration 1
|
||||
DWORD(0xac) = 0x000c060c; // processor interface configuration 2
|
||||
BYTE(0xba) = 0x04; // alternate OS-visible parameters 1
|
||||
BYTE(0xc0) = 0x01; // error enabling 1
|
||||
DWORD(0xf0) = 0xff020000; // memory control configuration 1
|
||||
DWORD(0xf4) = 0x00000003; // memory control configuration 2
|
||||
DWORD(0xfc) = 0x00100000; // memory control configuration 4
|
||||
|
||||
/*
|
||||
* Additional settings for MPC106
|
||||
*/
|
||||
|
||||
if (device == 2) // MPC106
|
||||
{
|
||||
BYTE(0x0c) = 0x08; // cache line size
|
||||
BYTE(0x73) = 0xcd; // output driver control
|
||||
DWORD(0xe0) = 0x0fff0042; // emulation support configuration 1
|
||||
DWORD(0xe8) = 0x00000020; // emulation support configuration 2
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* void bridge_init(UINT32 (*config_addr_callback_ptr)(UINT32));
|
||||
*
|
||||
* Initializes the bridge controller by setting up the CONFIG_ADDR callback.
|
||||
* bridge_reset() must still be used to put the controller in a usable (reset)
|
||||
* state.
|
||||
*/
|
||||
|
||||
void bridge_init(UINT32 (*config_addr_callback_ptr)(UINT32))
|
||||
{
|
||||
config_addr_callback = config_addr_callback_ptr;
|
||||
}
|
50
core/bridge.h
Normal file
50
core/bridge.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Sega Model 3 Emulator
|
||||
* Copyright (C) 2003 Bart Trzynadlowski, Ville Linde, Stefano Teso
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 (license.txt); if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* bridge.h
|
||||
*
|
||||
* MPC105 and MPC106 PCI bridge/memory controller header.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_BRIDGE_H
|
||||
#define INCLUDED_BRIDGE_H
|
||||
|
||||
extern UINT8 bridge_read_8(UINT32);
|
||||
extern UINT16 bridge_read_16(UINT32);
|
||||
extern UINT32 bridge_read_32(UINT32);
|
||||
extern void bridge_write_8(UINT32, UINT8);
|
||||
extern void bridge_write_16(UINT32, UINT16);
|
||||
extern void bridge_write_32(UINT32, UINT32);
|
||||
|
||||
extern UINT8 bridge_read_config_data_8(UINT32);
|
||||
extern UINT16 bridge_read_config_data_16(UINT32);
|
||||
extern UINT32 bridge_read_config_data_32(UINT32);
|
||||
extern void bridge_write_config_addr_32(UINT32, UINT32);
|
||||
extern void bridge_write_config_data_8(UINT32, UINT8);
|
||||
extern void bridge_write_config_data_16(UINT32, UINT16);
|
||||
extern void bridge_write_config_data_32(UINT32, UINT32);
|
||||
|
||||
extern void bridge_save_state(FILE *);
|
||||
extern void bridge_load_state(FILE *);
|
||||
|
||||
extern void bridge_reset(INT);
|
||||
extern void bridge_init(UINT32 (*)(UINT32));
|
||||
|
||||
#endif // INCLUDED_BRIDGE_H
|
||||
|
292
core/controls.c
Normal file
292
core/controls.c
Normal file
|
@ -0,0 +1,292 @@
|
|||
/*
|
||||
* Sega Model 3 Emulator
|
||||
* Copyright (C) 2003 Bart Trzynadlowski, Ville Linde, Stefano Teso
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 (license.txt); if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
//TODO: In controls_write(): Is EEPROM only written when bank_select = 1?
|
||||
// This makes little sense because banking affects reg 4 only, right?
|
||||
// Also, should EEPROM reads only be performed when bank_select=1?
|
||||
|
||||
/*
|
||||
* controls.c
|
||||
*
|
||||
* Control emulation.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Lost World Gun Notes:
|
||||
* ---------------------
|
||||
*
|
||||
* MCU Command Reg = 0x24 (byte)
|
||||
* MCU Arg Reg = 0x28 (byte)
|
||||
*
|
||||
* Procedure for issuing commands:
|
||||
* 1. Arg written first, then command.
|
||||
* 2. Waits on reg 0x34 (see Stefano's post to model3 group for details.)
|
||||
* 3. Reads a byte from 0x2C, then a byte from 0x30.
|
||||
*
|
||||
* Command 0x00: Set address (in arg reg.)
|
||||
* Command 0x87: Read gun data.
|
||||
*
|
||||
* Virtual On 2 Notes:
|
||||
* -------------------
|
||||
*
|
||||
* Control Area Offset 0x08: Lever 1, LRUD??TS (T = Turbo, S = Shot Trigger)
|
||||
* 0x0C: Lever 2
|
||||
* 0x18: Dipswitch, bits 7-0 = DS1-8
|
||||
*
|
||||
* Dipswitch bit 0x20 (DS3) should be cleared otherwise some test is performed
|
||||
* by Virtual On 2 at boot-up.
|
||||
*/
|
||||
|
||||
#include "model3.h"
|
||||
|
||||
/******************************************************************/
|
||||
/* Privates */
|
||||
/******************************************************************/
|
||||
|
||||
/*
|
||||
* Register Set
|
||||
*/
|
||||
|
||||
static UINT8 controls_reg[0x40];
|
||||
static UINT8 controls_reg_bank[2];
|
||||
static BOOL controls_bank_select;
|
||||
|
||||
/*
|
||||
* Gun Data
|
||||
*
|
||||
* Gun data is read by communicating with the MCU. An address is passed and
|
||||
* some data is read back. The total number of data bytes that the MCU stores
|
||||
* and can address is unknown, but I assume 16 (Stefano: Is this correct?)
|
||||
*
|
||||
* Here is how gun data is stored:
|
||||
*
|
||||
* Offset 0: player 1 gun X position, lower 8 bits
|
||||
* 1: player 1 gun X position, upper 3 bits
|
||||
* 2: player 1 gun Y position, lower 8 bits
|
||||
* 3: player 1 gun Y position, upper 3 bits
|
||||
* 4: player 2 gun X position, lower 8 bits
|
||||
* 5: player 2 gun X position, upper 3 bits
|
||||
* 6: player 2 gun Y position, lower 8 bits
|
||||
* 7: player 2 gun Y position, upper 3 bits
|
||||
* 8: bit 0 = player 1 gun position status (0=aquired 1=lost)
|
||||
* bit 1 = player 2 gun position status (0=aquired 1=lost)
|
||||
*
|
||||
* I think Stefano also said that the X and Y may be reversed and that the gun
|
||||
* coordinates are only 10 bits, not 11.
|
||||
*/
|
||||
|
||||
static UINT8 gun_data[16];
|
||||
static int gun_data_ptr; // which address within gun_data[]
|
||||
|
||||
|
||||
static UINT8 analog_axis[8];
|
||||
static int analog_control = 0; // Currently used register
|
||||
|
||||
/******************************************************************/
|
||||
/* Interface */
|
||||
/******************************************************************/
|
||||
|
||||
void controls_shutdown(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void controls_init(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void controls_reset(UINT32 flags)
|
||||
{
|
||||
memset(controls_reg_bank, 0xFF, 2);
|
||||
memset(controls_reg, 0xFF, 0x40);
|
||||
memset(controls_reg, 0x00, 8);
|
||||
|
||||
// controls_reg[0x18] = 0xDF; // clear bit 0x20 for Virtual On 2
|
||||
controls_reg[0x18] = 0xff;
|
||||
}
|
||||
|
||||
void controls_update(void)
|
||||
{
|
||||
int i;
|
||||
OSD_CONTROLS *c;
|
||||
UINT gun_x, gun_y;
|
||||
|
||||
c = osd_input_update_controls();
|
||||
|
||||
controls_reg_bank[0] = c->system_controls[0];
|
||||
controls_reg_bank[1] = c->system_controls[1];
|
||||
|
||||
controls_reg[0x08] = c->game_controls[0];
|
||||
controls_reg[0x0C] = c->game_controls[1];
|
||||
|
||||
/*
|
||||
* TEMP: This should be changed so that only games with guns have this
|
||||
* updated
|
||||
*/
|
||||
|
||||
/*
|
||||
* Gun Coordinates:
|
||||
*
|
||||
* Coordinates returned by the MCU are sight position coordinates. The OSD
|
||||
* input code returns coordinates in the range of (0,0)-(485,383).
|
||||
*
|
||||
* X adjustment: 400 must be added to the sight position in order to
|
||||
* locate the gun at screen X = 0.
|
||||
*
|
||||
* Y adjustment: Sight coordinate 0 maps to screen coordinate 272. Sight
|
||||
* coordinate 272 maps to screen coordinate 0. Sight coordinate 383 maps
|
||||
* to -111.
|
||||
*/
|
||||
|
||||
gun_y = c->gun_y[0];
|
||||
// if (gun_y <= 272)
|
||||
// gun_y = 272 - gun_y;
|
||||
// else
|
||||
gun_x = c->gun_x[0];// + 400;
|
||||
gun_data[0] = gun_y & 0xFF;
|
||||
gun_data[1] = (gun_y >> 8) & 7;
|
||||
gun_data[2] = gun_x & 0xFF;
|
||||
gun_data[3] = (gun_x >> 8) & 7;
|
||||
|
||||
gun_y = c->gun_y[1];
|
||||
gun_x = c->gun_x[1] + 400;
|
||||
gun_data[4] = gun_y & 0xFF;
|
||||
gun_data[5] = (gun_y >> 8) & 7;
|
||||
gun_data[6] = gun_x & 0xFF;
|
||||
gun_data[7] = (gun_x >> 8) & 7;
|
||||
|
||||
gun_data[8] = (!!c->gun_acquired[0]) | ((!!c->gun_acquired[1]) << 1);
|
||||
|
||||
// Steering Wheel controls
|
||||
// Register 0: Steering wheel, 0x80 is center
|
||||
// Register 1: Acceleration, 0x00 - 0xFF
|
||||
// Register 2: Brake, 0x00 - 0xFF
|
||||
// Registers 3 - 7 are either unused or unknown
|
||||
|
||||
for (i=0; i < 8; i++)
|
||||
{
|
||||
analog_axis[i] = c->analog_axis[i] & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* void controls_save_state(FILE *fp);
|
||||
*
|
||||
* Saves the state of the controls to a file.
|
||||
*
|
||||
* Parameters:
|
||||
* fp = File to save to.
|
||||
*/
|
||||
|
||||
void controls_save_state(FILE *fp)
|
||||
{
|
||||
fwrite(controls_reg, sizeof(UINT8), 0x40, fp);
|
||||
fwrite(controls_reg_bank, sizeof(UINT8), 2, fp);
|
||||
fwrite(&controls_bank_select, sizeof(BOOL), 1, fp);
|
||||
}
|
||||
|
||||
/*
|
||||
* void controls_load_state(FILE *fp);
|
||||
*
|
||||
* Loads the state of the controls from a file.
|
||||
*
|
||||
* Parameters:
|
||||
* fp = File to load from.
|
||||
*/
|
||||
|
||||
void controls_load_state(FILE *fp)
|
||||
{
|
||||
fread(controls_reg, sizeof(UINT8), 0x40, fp);
|
||||
fread(controls_reg_bank, sizeof(UINT8), 2, fp);
|
||||
fread(&controls_bank_select, sizeof(BOOL), 1, fp);
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
/* Access */
|
||||
/******************************************************************/
|
||||
|
||||
/* these are only 8-bit wide, byte-aligned */
|
||||
/* additional data/address adjustement must be performed by the main handler */
|
||||
|
||||
UINT8 controls_read(UINT32 a)
|
||||
{
|
||||
a &= 0x3F;
|
||||
|
||||
switch (a)
|
||||
{
|
||||
case 0x4:
|
||||
{
|
||||
// should this only be done when bank_select = 1?
|
||||
controls_reg_bank[1] &= ~0x20; // clear data bit before ORing it in
|
||||
controls_reg_bank[1] |= (eeprom_read_bit() & 1) << 5;
|
||||
return controls_reg_bank[controls_bank_select];
|
||||
}
|
||||
case 0x3C:
|
||||
{
|
||||
// I don't know if the register to be read can be selected.
|
||||
UINT8 analog_data = analog_axis[analog_control & 0x7];
|
||||
analog_control++;
|
||||
|
||||
return analog_data;
|
||||
}
|
||||
}
|
||||
|
||||
// LOG("model3.log", "CTRL %02X READ\n", a);
|
||||
|
||||
return controls_reg[a];
|
||||
}
|
||||
|
||||
void controls_write(UINT32 a, UINT8 d)
|
||||
{
|
||||
a &= 0x3F;
|
||||
controls_reg[a] = d;
|
||||
|
||||
switch(a)
|
||||
{
|
||||
case 0x0:
|
||||
{
|
||||
controls_bank_select = d & 1;
|
||||
// if(controls_bank_select == 1)
|
||||
{
|
||||
eeprom_set_clk((d & 0x80) ? 1 : 0);
|
||||
eeprom_set_ce((d & 0x40) ? 1 : 0);
|
||||
eeprom_set_data((d & 0x20) ? 1 : 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x24: // MCU command
|
||||
{
|
||||
switch (d)
|
||||
{
|
||||
case 0x00: // set address for gun data (it's already in the arg reg)
|
||||
gun_data_ptr = controls_reg[0x28] & 0xF;
|
||||
break;
|
||||
|
||||
case 0x87: // read data back from gun
|
||||
controls_reg[0x2c] = 0; // unused?
|
||||
controls_reg[0x30] = gun_data[gun_data_ptr];
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// LOG("model3.log", "CTRL%02X = %02X\n", a, d);
|
||||
}
|
||||
|
41
core/controls.h
Normal file
41
core/controls.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Sega Model 3 Emulator
|
||||
* Copyright (C) 2003 Bart Trzynadlowski, Ville Linde, Stefano Teso
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 (license.txt); if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* controls.h
|
||||
*
|
||||
* Controls header.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_CONTROLS_H
|
||||
#define INCLUDED_CONTROLS_H
|
||||
|
||||
extern void controls_init(void);
|
||||
extern void controls_shutdown(void);
|
||||
extern void controls_reset(UINT32 flags);
|
||||
|
||||
extern void controls_update(void);
|
||||
|
||||
extern void controls_save_state(FILE *);
|
||||
extern void controls_load_state(FILE *);
|
||||
|
||||
extern UINT8 controls_read(UINT32 a);
|
||||
extern void controls_write(UINT32 a, UINT8 d);
|
||||
|
||||
#endif // INCLUDED_CONTROLS_H
|
||||
|
371
core/dma.c
Normal file
371
core/dma.c
Normal file
|
@ -0,0 +1,371 @@
|
|||
/*
|
||||
* Sega Model 3 Emulator
|
||||
* Copyright (C) 2003 Bart Trzynadlowski, Ville Linde, Stefano Teso
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 (license.txt); if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* dma.c
|
||||
*
|
||||
* Step 2.0+ DMA device emulation. We're unsure whether or not this is a SCSI
|
||||
* controller; it appears to only be used for its DMA capabilities and is
|
||||
* thought to be a Sega custom part.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 0xC2000000 32-bit -W DMA Source
|
||||
* 0xC2000004 32-bit -W DMA Destination
|
||||
* 0xC2000008 32-bit -W DMA Length (in words)
|
||||
* 0xC200000C 8-bit RW DMA Status? AxxxxxxB (A and B must be cleared)
|
||||
* 0xC200000D 8-bit -W DMA Control? xxxxxxx? (bit0 clears C200000C bit0)
|
||||
* 0xC200000E 8-bit -W DMA Config?
|
||||
* 0xC2000010 32-bit -W DMA Command? (Written, result appears at 0x14)
|
||||
* 0xC2000014 32-bit R- DMA Command Result
|
||||
*/
|
||||
|
||||
#include "model3.h"
|
||||
|
||||
/******************************************************************/
|
||||
/* Private Variables */
|
||||
/******************************************************************/
|
||||
|
||||
/*
|
||||
* Registers
|
||||
*/
|
||||
|
||||
static UINT8 dma_regs[0x20];
|
||||
|
||||
/*
|
||||
* Read/Write Handlers
|
||||
*
|
||||
* These are used as an interface to the rest of the system.
|
||||
*/
|
||||
|
||||
static UINT32 (*read_32)(UINT32);
|
||||
static void (*write_32)(UINT32, UINT32);
|
||||
|
||||
/******************************************************************/
|
||||
/* DMA Transfer */
|
||||
/******************************************************************/
|
||||
|
||||
/*
|
||||
* do_dma():
|
||||
*
|
||||
* Performs a DMA transfer. The paramaters are expected to be in the
|
||||
* appropriate registers.
|
||||
*/
|
||||
|
||||
#ifdef _PROFILE_
|
||||
extern UINT is_dma;
|
||||
#endif
|
||||
|
||||
static void do_dma(void)
|
||||
{
|
||||
UINT32 src, dest, len;
|
||||
|
||||
PROFILE_SECT_ENTRY("dma");
|
||||
|
||||
#ifdef _PROFILE_
|
||||
is_dma = 1;
|
||||
#endif
|
||||
|
||||
src = *(UINT32 *) &dma_regs[0x00];
|
||||
dest = *(UINT32 *) &dma_regs[0x04];
|
||||
len = (*(UINT32 *) &dma_regs[0x08]) * 4;
|
||||
|
||||
LOG("model3.log", "DMA %08X -> %08X, %X\n", src, dest, len);
|
||||
|
||||
if ((dma_regs[0x0E] & 0x80)) // swap words
|
||||
{
|
||||
/*while (len)
|
||||
{
|
||||
write_32(dest, BSWAP32(read_32(src)));
|
||||
src += 4;
|
||||
dest += 4;
|
||||
len -= 4;
|
||||
}*/
|
||||
|
||||
model3_dma_transfer(src, dest, len, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*while (len)
|
||||
{
|
||||
write_32(dest, read_32(src));
|
||||
src += 4;
|
||||
dest += 4;
|
||||
len -= 4;
|
||||
}*/
|
||||
|
||||
model3_dma_transfer(src, dest, len, FALSE);
|
||||
}
|
||||
|
||||
#ifdef _PROFILE_
|
||||
is_dma = 0;
|
||||
#endif
|
||||
|
||||
*(UINT32 *) &dma_regs[0x08] = 0; // not sure if this is necessary
|
||||
|
||||
/*
|
||||
* An IRQ may be generated by the DMA device after a copy is performed (or
|
||||
* at some other time.)
|
||||
*
|
||||
* Evidence for this is in Harley Davidson's ISR. The subroutine at 0x8ABE8
|
||||
* appears to check the status register bit 0 and performs a copy if it is
|
||||
* set (after first clearing it.)
|
||||
*
|
||||
* Here, bit 0 is set, an IRQ is triggered, and the code will clear bit 0 by
|
||||
* writing a 1 to bit 0 of DMA reg 0xD.
|
||||
*/
|
||||
|
||||
dma_regs[0x0C] |= 1; // this bit may indicate IRQ raised
|
||||
ppc_set_irq_line(1);
|
||||
|
||||
PROFILE_SECT_EXIT("dma");
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
/* Interface */
|
||||
/******************************************************************/
|
||||
|
||||
/*
|
||||
* void dma_shutdown(void);
|
||||
*
|
||||
* Shuts down the DMA device emulation.
|
||||
*/
|
||||
|
||||
void dma_shutdown(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* void dma_init(UINT32 (*read32)(UINT32), void (*write32)(UINT32, UINT32));
|
||||
*
|
||||
* Initializes the DMA device emulation by setting the memory access handlers.
|
||||
*
|
||||
* Parameters:
|
||||
* read32 = Handler to use for 32-bit reads.
|
||||
* write32 = Handler to use for 32-bit writes.
|
||||
*/
|
||||
|
||||
void dma_init(UINT32 (*read32)(UINT32), void (*write32)(UINT32, UINT32))
|
||||
{
|
||||
read_32 = read32;
|
||||
write_32 = write32;
|
||||
}
|
||||
|
||||
/*
|
||||
* void dma_reset(void);
|
||||
*
|
||||
* Resets the DMA device.
|
||||
*/
|
||||
|
||||
void dma_reset(void)
|
||||
{
|
||||
memset(dma_regs, 0, 0x20);
|
||||
}
|
||||
|
||||
/*
|
||||
* void dma_save_state(FILE *fp);
|
||||
*
|
||||
* Saves the state of the DMA device (for Step 2.0 or higher games only) to a
|
||||
* file.
|
||||
*
|
||||
* Parameters:
|
||||
* fp = File to save to.
|
||||
*/
|
||||
|
||||
void dma_save_state(FILE *fp)
|
||||
{
|
||||
if (m3_config.step < 0x20)
|
||||
return;
|
||||
fwrite(dma_regs, sizeof(UINT8), 0x20, fp);
|
||||
}
|
||||
|
||||
/*
|
||||
* void dma_load_state(FILE *fp);
|
||||
*
|
||||
* Loads the state of the DMA device (for Step 2.0 or higher games only) from
|
||||
* a file.
|
||||
*
|
||||
* Parameters:
|
||||
* fp = File to load from.
|
||||
*/
|
||||
|
||||
void dma_load_state(FILE *fp)
|
||||
{
|
||||
if (m3_config.step < 0x20)
|
||||
return;
|
||||
fread(dma_regs, sizeof(UINT8), 0x20, fp);
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
/* Access */
|
||||
/******************************************************************/
|
||||
|
||||
/*
|
||||
* UINT8 dma_read_8(UINT32 a);
|
||||
*
|
||||
* Reads a byte from the DMA device.
|
||||
*
|
||||
* Parameters:
|
||||
* a = Address.
|
||||
*
|
||||
* Returns:
|
||||
* Data read.
|
||||
*/
|
||||
|
||||
UINT8 dma_read_8(UINT32 a)
|
||||
{
|
||||
// message(0, "%08X: Unknown DMA read8, %08X", PPC_PC, a);
|
||||
|
||||
return dma_regs[a & 0x1F];
|
||||
}
|
||||
|
||||
/*
|
||||
* UINT32 dma_read_32(UINT32 a);
|
||||
*
|
||||
* Reads a word from the DMA device.
|
||||
*
|
||||
* Parameters:
|
||||
* a = Address.
|
||||
*
|
||||
* Returns:
|
||||
* Data read.
|
||||
*/
|
||||
|
||||
UINT32 dma_read_32(UINT32 a)
|
||||
{
|
||||
// message(0, "%08X: Unknown DMA read32, %08X", PPC_PC, a);
|
||||
|
||||
return BSWAP32(*(UINT32 *) &dma_regs[a & 0x1F]);
|
||||
}
|
||||
|
||||
/*
|
||||
* void dma_write_8(UINT32 a, UINT8 d);
|
||||
*
|
||||
* Writes a byte to the DMA device.
|
||||
*
|
||||
* Parameters:
|
||||
* a = Address.
|
||||
* d = Data to write.
|
||||
*/
|
||||
|
||||
void dma_write_8(UINT32 a, UINT8 d)
|
||||
{
|
||||
dma_regs[a & 0x1F] = d;
|
||||
|
||||
switch (a & 0x1F)
|
||||
{
|
||||
case 0xD:
|
||||
if ((d & 1)) // clear status bit 0
|
||||
dma_regs[0xC] &= ~1;
|
||||
break;
|
||||
default:
|
||||
LOG("model3.log", "%08X: Unknown DMA write8, %08X = %02X\n", ppc_get_pc(), a, d);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* void dma_write_16(UINT32 a, UINT16 d);
|
||||
*
|
||||
* Writes a half-word to the DMA device.
|
||||
*
|
||||
* Parameters:
|
||||
* a = Address.
|
||||
* d = Data to write.
|
||||
*/
|
||||
|
||||
void dma_write_16(UINT32 a, UINT16 d)
|
||||
{
|
||||
switch (a & 0x1F)
|
||||
{
|
||||
case 0x14:
|
||||
message(0, "%08X = %04X", a, d);
|
||||
LOG("model3.log", "DMA %08X = %04X\n", a, d);
|
||||
break;
|
||||
default:
|
||||
error("unknown DMA write: %08X = %04X", a, d);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* void dma_write_32(UINT32 a, UINT32 d);
|
||||
*
|
||||
* Writes a word to the DMA device.
|
||||
*
|
||||
* Parameters:
|
||||
* a = Address.
|
||||
* d = Data to write.
|
||||
*/
|
||||
|
||||
void dma_write_32(UINT32 a, UINT32 d)
|
||||
{
|
||||
d = BSWAP32(d); // this is a little endian device, only bswap here once
|
||||
|
||||
*(UINT32 *) &dma_regs[a & 0x1F] = d;
|
||||
|
||||
switch (a & 0x1F)
|
||||
{
|
||||
case 0x00: // DMA Source
|
||||
// message(0, "DMA SRC = %08X", d);
|
||||
return;
|
||||
case 0x04: // DMA Destination
|
||||
// message(0, "DMA DST = %08X", d);
|
||||
return;
|
||||
case 0x08: // DMA Length
|
||||
// message(0, "DMA LEN = %X", d * 4);
|
||||
do_dma();
|
||||
return;
|
||||
case 0x10: // DMA Command
|
||||
|
||||
/*
|
||||
* Virtual On 2 has been observed to write commands to reg 0x10 and
|
||||
* then expects particular values back from 0x14.
|
||||
*
|
||||
* Command 0x80000000 is a little strange. It is issued and twice and
|
||||
* each time, a bit of the result is expected to be different. This
|
||||
* is crudely simulated by flipping a bit.
|
||||
*
|
||||
* Virtua Striker 2 '99 does something similar, except that it writes
|
||||
* commands 0x80000000, 0x80000004, ... 0x80000020.
|
||||
*/
|
||||
|
||||
if (d & 0x20000000)
|
||||
*(UINT32 *) &dma_regs[0x14] = 0x178611db; //0x16C311DB; // PCI Vendor and Device ID
|
||||
else if ((d & 0x80000000))
|
||||
*(UINT32 *) &dma_regs[0x14] = r3d_read_32((d & 0xFF) | 0x84000000);
|
||||
#if 0
|
||||
else if (d == 0x80000000)
|
||||
{
|
||||
static UINT32 result = 0x02000000;
|
||||
result ^= 0x02000000;
|
||||
*(UINT32 *) &dma_regs[0x14] = result;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
message(0, "%08X: Unknown DMA command, %08X", ppc_get_pc(), d);
|
||||
|
||||
return;
|
||||
case 0x14:
|
||||
*(UINT32 *) &dma_regs[0x14] = 0xffffffff;
|
||||
return;
|
||||
}
|
||||
|
||||
message(0, "%08X: Unknown DMA write32, %08X = %08X", ppc_get_pc(), a, d);
|
||||
}
|
||||
|
42
core/dma.h
Normal file
42
core/dma.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Sega Model 3 Emulator
|
||||
* Copyright (C) 2003 Bart Trzynadlowski, Ville Linde, Stefano Teso
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 (license.txt); if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* dma.h
|
||||
*
|
||||
* Step 2.0+ DMA device header.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_DMA_H
|
||||
#define INCLUDED_DMA_H
|
||||
|
||||
extern void dma_init(UINT32 (*)(UINT32), void (*)(UINT32, UINT32));
|
||||
extern void dma_shutdown(void);
|
||||
extern void dma_reset(void);
|
||||
|
||||
extern void dma_save_state(FILE *);
|
||||
extern void dma_load_state(FILE *);
|
||||
|
||||
extern UINT8 dma_read_8(UINT32 a);
|
||||
extern UINT32 dma_read_32(UINT32 a);
|
||||
extern void dma_write_8(UINT32 a, UINT8 d);
|
||||
extern void dma_write_16(UINT32 a, UINT16 d);
|
||||
extern void dma_write_32(UINT32 a, UINT32 d);
|
||||
|
||||
#endif // INCLUDED_DMA_H
|
||||
|
71
core/dsb1.c
Normal file
71
core/dsb1.c
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Sega Model 3 Emulator
|
||||
* Copyright (C) 2003 Bart Trzynadlowski, Ville Linde, Stefano Teso
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 (license.txt); if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* dsb1.c
|
||||
*
|
||||
* DSB1 Digital Sound Board emulation.
|
||||
*/
|
||||
|
||||
#include "model3.h"
|
||||
|
||||
void dsb1_init(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void dsb1_reset(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void dsb1_shutdown(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* void dsb1_save_state(FILE *fp);
|
||||
*
|
||||
* Saves the state of the DSB1 (for games which have it) to a file.
|
||||
*
|
||||
* Parameters:
|
||||
* fp = File to save to.
|
||||
*/
|
||||
|
||||
void dsb1_save_state(FILE *fp)
|
||||
{
|
||||
if (!(m3_config.flags & GAME_OWN_DSB1))
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* void dsb1_load_state(FILE *fp);
|
||||
*
|
||||
* Loads the state of the DSB1 (for games which have it) from a file.
|
||||
*
|
||||
* Parameters:
|
||||
* fp = File to load from.
|
||||
*/
|
||||
|
||||
void dsb1_load_state(FILE *fp)
|
||||
{
|
||||
if (!(m3_config.flags & GAME_OWN_DSB1))
|
||||
return;
|
||||
}
|
||||
|
36
core/dsb1.h
Normal file
36
core/dsb1.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Sega Model 3 Emulator
|
||||
* Copyright (C) 2003 Bart Trzynadlowski, Ville Linde, Stefano Teso
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 (license.txt); if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* dsb1.h
|
||||
*
|
||||
* DSB1 Digital Sound Board header.
|
||||
*/
|
||||
|
||||
#ifndef _DSB1_H_
|
||||
#define _DSB1_H_
|
||||
|
||||
extern void dsb1_init(void);
|
||||
extern void dsb1_shutdown(void);
|
||||
extern void dsb1_reset(void);
|
||||
|
||||
extern void dsb1_save_state(FILE *);
|
||||
extern void dsb1_load_state(FILE *);
|
||||
|
||||
#endif /* _DSB1_H_ */
|
||||
|
391
core/eeprom.c
Normal file
391
core/eeprom.c
Normal file
|
@ -0,0 +1,391 @@
|
|||
/*
|
||||
* Sega Model 3 Emulator
|
||||
* Copyright (C) 2003 Bart Trzynadlowski, Ville Linde, Stefano Teso
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 (license.txt); if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* eeprom.c
|
||||
*
|
||||
* 93C46 EEPROM emulation courtesy of R. Belmont.
|
||||
*
|
||||
* NOTE: Save state code assumes enums will be the same across all compilers
|
||||
* and systems. The eeprom_store[] array is endian-dependent.
|
||||
*/
|
||||
|
||||
/***************************************************************************
|
||||
eeprom.cpp - handles a serial eeprom with 64 16-bit addresses and 4-bit commands
|
||||
as seen in st-v, system 32, many konami boards, etc.
|
||||
|
||||
originally written: May 20, 2000 by R. Belmont for "sim"
|
||||
update: Jan 27, 2001 (RB): implemented "erase" opcode,
|
||||
made opcode fetch check for start bit
|
||||
like the real chip.
|
||||
Mar 26, 2001 (FF): added get_image to access the eeprom
|
||||
Jan 28, 2004 (Bart): Interface changes to work with Supermodel.
|
||||
Crudely simulated busy status by setting olatch to 0 in
|
||||
ES_DESELECT.
|
||||
***************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "model3.h"
|
||||
|
||||
#define LOG_EEPROM 0 // log channel for EEPROM
|
||||
|
||||
static INT32 eeprom_state;
|
||||
|
||||
static UINT16 eeprom_store[64]; // 6 address bits times 16 bits per location
|
||||
static UINT8 opcode; // current opcode
|
||||
static UINT8 adr; // current address in eeprom_store
|
||||
static UINT8 curbit; // current bit # in read/write/addr fetch operation
|
||||
static UINT8 lastclk; // last clock
|
||||
static UINT8 dlatch; // input data latch
|
||||
static UINT8 olatch; // output data latch
|
||||
static UINT16 curio;
|
||||
|
||||
// states for the eeprom state machine
|
||||
enum
|
||||
{
|
||||
ES_DESELECT = 0,// chip select not asserted
|
||||
ES_ASSERT, // chip select asserted, waiting for opcode
|
||||
ES_OPCODE0, // got opcode bit 0
|
||||
ES_OPCODE1, // got opcode bit 1
|
||||
ES_OPCODE2, // got opcode bit 2
|
||||
ES_ADRFETCH, // fetching address
|
||||
ES_READBITS, // reading bits, 1 out every time clock goes high
|
||||
ES_WRITEBITS, // writing bits, 1 in every time clock goes high
|
||||
ES_WAITING // done with read/write, waiting for deselect to finalize
|
||||
};
|
||||
|
||||
/*
|
||||
* UINT8 eeprom_read_bit(void);
|
||||
*
|
||||
* Reads a data bit from the EEPROM.
|
||||
*
|
||||
* Returns:
|
||||
* Latched data bit.
|
||||
*/
|
||||
|
||||
UINT8 eeprom_read_bit(void)
|
||||
{
|
||||
return olatch;
|
||||
}
|
||||
|
||||
/*
|
||||
* void eeprom_set_ce(UINT8 ce);
|
||||
*
|
||||
* Passes the status of the chip enable.
|
||||
*
|
||||
* Parameters:
|
||||
* ce = Chip enable bit (must be 0 or 1.)
|
||||
*/
|
||||
|
||||
void eeprom_set_ce(UINT8 ce)
|
||||
{
|
||||
// chip enable
|
||||
if (ce)
|
||||
{
|
||||
// asserting CE - if deselected,
|
||||
// select. if selected already,
|
||||
// ignore
|
||||
if (eeprom_state == ES_DESELECT)
|
||||
{
|
||||
// printf("EEPROM: asserting chip enable\n");
|
||||
eeprom_state = ES_ASSERT;
|
||||
opcode = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// deasserting CE
|
||||
// printf("EEPROM: deasserting chip enable\n");
|
||||
eeprom_state = ES_DESELECT;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* void eeprom_set_data(UINT8 data);
|
||||
*
|
||||
* Sets the data bit latch.
|
||||
*
|
||||
* Parameters:
|
||||
* data = Data bit (must be 0 or 1.)
|
||||
*/
|
||||
|
||||
void eeprom_set_data(UINT8 data)
|
||||
{
|
||||
dlatch = (data&0x01); // latch the data
|
||||
}
|
||||
|
||||
/*
|
||||
* void eeprom_set_clk(UINT8 clk);
|
||||
*
|
||||
* Sets the clock pin.
|
||||
*
|
||||
* Parameters:
|
||||
* clk = Clock (zero or non-zero.)
|
||||
*/
|
||||
|
||||
void eeprom_set_clk(UINT8 clk)
|
||||
{
|
||||
// things only happen on the rising edge of the clock
|
||||
if ((!lastclk) && (clk))
|
||||
{
|
||||
switch (eeprom_state)
|
||||
{
|
||||
case ES_DESELECT:
|
||||
olatch = 0;
|
||||
break;
|
||||
|
||||
case ES_ASSERT:
|
||||
case ES_OPCODE0:
|
||||
case ES_OPCODE1:
|
||||
case ES_OPCODE2:
|
||||
// first command bit must be a "1" in the real device
|
||||
if ((eeprom_state == ES_OPCODE0) && (dlatch == 0))
|
||||
{
|
||||
#if LOG_EEPROM
|
||||
LOG("model3.log", "EEPROM: waiting for start bit\n");
|
||||
#endif
|
||||
olatch = 1; // assert READY
|
||||
}
|
||||
else
|
||||
{
|
||||
opcode <<= 1;
|
||||
opcode |= dlatch;
|
||||
#if LOG_EEPROM
|
||||
LOG("model3.log", "EEPROM: opcode fetch state, currently %x\n", opcode);
|
||||
#endif
|
||||
eeprom_state++;
|
||||
}
|
||||
|
||||
curbit = 0;
|
||||
adr = 0;
|
||||
break;
|
||||
|
||||
case ES_ADRFETCH: // fetch address
|
||||
adr <<= 1;
|
||||
adr |= dlatch;
|
||||
#if LOG_EEPROM
|
||||
LOG("model3.log", "EEPROM: address fetch state, cur addr = %x\n", adr);
|
||||
#endif
|
||||
curbit++;
|
||||
if (curbit == 6)
|
||||
{
|
||||
switch (opcode)
|
||||
{
|
||||
case 4: // write enable - go back to accept a new opcode immediately
|
||||
opcode = 0;
|
||||
eeprom_state = ES_ASSERT;
|
||||
//printf("EEPROM: write enable\n");
|
||||
break;
|
||||
|
||||
case 5: // write
|
||||
eeprom_state = ES_WRITEBITS;
|
||||
olatch = 0; // indicate not ready yet
|
||||
curbit = 0;
|
||||
curio = 0;
|
||||
break;
|
||||
|
||||
case 6: // read
|
||||
eeprom_state = ES_READBITS;
|
||||
curbit = 0;
|
||||
curio = eeprom_store[adr];
|
||||
//printf("EEPROM: read %04x from address %d\n", curio, adr);
|
||||
break;
|
||||
|
||||
case 7: // erase location to ffff and assert READY
|
||||
eeprom_store[adr] = 0xffff;
|
||||
olatch = 1;
|
||||
eeprom_state = ES_WAITING;
|
||||
//printf("EEPROM: erase at address %d\n", adr);
|
||||
break;
|
||||
|
||||
default:
|
||||
#if LOG_EEPROM
|
||||
LOG("model3.log", "Unknown EEPROM opcode %d!\n", opcode);
|
||||
#endif
|
||||
eeprom_state = ES_WAITING;
|
||||
olatch = 1; // assert READY anyway
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ES_READBITS:
|
||||
olatch = ((curio & 0x8000)>>15);
|
||||
curio <<= 1;
|
||||
|
||||
curbit++;
|
||||
if (curbit == 16)
|
||||
{
|
||||
eeprom_state = ES_WAITING;
|
||||
}
|
||||
break;
|
||||
|
||||
case ES_WRITEBITS:
|
||||
curio <<= 1;
|
||||
curio |= dlatch;
|
||||
|
||||
curbit++;
|
||||
if (curbit == 16)
|
||||
{
|
||||
olatch = 1; // indicate success
|
||||
eeprom_store[adr] = curio;
|
||||
#if LOG_EEPROM
|
||||
LOG("model3.log", "EEPROM: Wrote %04x to address %d\n", curio, adr);
|
||||
#endif
|
||||
eeprom_state = ES_WAITING;
|
||||
}
|
||||
break;
|
||||
|
||||
case ES_WAITING:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
lastclk = clk;
|
||||
}
|
||||
|
||||
/*
|
||||
* void eeprom_save_state(FILE *fp);
|
||||
*
|
||||
* Save the EEPROM state.
|
||||
*
|
||||
* Parameters:
|
||||
* fp = File to save to.
|
||||
*/
|
||||
|
||||
void eeprom_save_state(FILE *fp)
|
||||
{
|
||||
if (fp != NULL)
|
||||
{
|
||||
fwrite(&eeprom_state, sizeof(INT32), 1, fp);
|
||||
fwrite(eeprom_store, sizeof(UINT16), 64, fp);
|
||||
fwrite(&opcode, sizeof(UINT8), 1, fp);
|
||||
fwrite(&adr, sizeof(UINT8), 1, fp);
|
||||
fwrite(&curbit, sizeof(UINT8), 1, fp);
|
||||
fwrite(&lastclk, sizeof(UINT8), 1, fp);
|
||||
fwrite(&dlatch, sizeof(UINT8), 1, fp);
|
||||
fwrite(&olatch, sizeof(UINT8), 1, fp);
|
||||
fwrite(&curio, sizeof(UINT16), 1, fp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* void eeprom_load_state(FILE *fp);
|
||||
*
|
||||
* Load the EEPROM state.
|
||||
*
|
||||
* Parameters:
|
||||
* fp = File to load from.
|
||||
*/
|
||||
|
||||
void eeprom_load_state(FILE *fp)
|
||||
{
|
||||
if (fp != NULL)
|
||||
{
|
||||
fread(&eeprom_state, sizeof(INT32), 1, fp);
|
||||
fread(eeprom_store, sizeof(UINT16), 64, fp);
|
||||
fread(&opcode, sizeof(UINT8), 1, fp);
|
||||
fread(&adr, sizeof(UINT8), 1, fp);
|
||||
fread(&curbit, sizeof(UINT8), 1, fp);
|
||||
fread(&lastclk, sizeof(UINT8), 1, fp);
|
||||
fread(&dlatch, sizeof(UINT8), 1, fp);
|
||||
fread(&olatch, sizeof(UINT8), 1, fp);
|
||||
fread(&curio, sizeof(UINT16), 1, fp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* INT eeprom_load(CHAR *fname);
|
||||
*
|
||||
* Loads data from the file specified. If the file does not exist, the EEPROM
|
||||
* data is initialized with all 1's.
|
||||
*
|
||||
* Parameters:
|
||||
* fname = File name.
|
||||
*
|
||||
* Returns:
|
||||
* MODEL3_OKAY = Success.
|
||||
* MODEL3_ERROR = Error reading from the file.
|
||||
*/
|
||||
|
||||
INT eeprom_load(CHAR *fname)
|
||||
{
|
||||
FILE *fp;
|
||||
INT error_code = MODEL3_ERROR;
|
||||
|
||||
message(0, "loading EEPROM from %s", fname);
|
||||
|
||||
if ((fp = fopen(fname, "rb")) != NULL)
|
||||
{
|
||||
error_code = fread(eeprom_store, sizeof(UINT16), 64, fp);
|
||||
fclose(fp);
|
||||
|
||||
if (error_code == 64)
|
||||
return MODEL3_OKAY;
|
||||
}
|
||||
|
||||
memset(eeprom_store, 0xFF, sizeof(UINT16) * 64);
|
||||
|
||||
return error_code;
|
||||
}
|
||||
|
||||
/*
|
||||
* INT eeprom_save(CHAR *fname);
|
||||
*
|
||||
* Writes out the EEPROM data to the specified file.
|
||||
*
|
||||
* Parameters:
|
||||
* fname = File name to write.
|
||||
*
|
||||
* Returns:
|
||||
* MODEL3_OKAY = Success.
|
||||
* MODEL3_ERROR = Unable to open or write file.
|
||||
*/
|
||||
|
||||
INT eeprom_save(CHAR *fname)
|
||||
{
|
||||
FILE *fp;
|
||||
INT i = MODEL3_ERROR;
|
||||
|
||||
message(0, "saving EEPROM to %s", fname);
|
||||
|
||||
if ((fp = fopen(fname, "wb")) != NULL)
|
||||
{
|
||||
i = fwrite(eeprom_store, sizeof(UINT16), 64, fp);
|
||||
fclose(fp);
|
||||
|
||||
if (i == 64)
|
||||
return MODEL3_OKAY;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
* void eeprom_reset(void);
|
||||
*
|
||||
* Resets the EEPROM emulation.
|
||||
*/
|
||||
|
||||
void eeprom_reset(void)
|
||||
{
|
||||
eeprom_state = ES_DESELECT;
|
||||
lastclk = 0;
|
||||
}
|
41
core/eeprom.h
Normal file
41
core/eeprom.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Sega Model 3 Emulator
|
||||
* Copyright (C) 2003 Bart Trzynadlowski, Ville Linde, Stefano Teso
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 (license.txt); if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* eeprom.h
|
||||
*
|
||||
* 93C46 EEPROM emulation header.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_EEPROM_H
|
||||
#define INCLUDED_EEPROM_H
|
||||
|
||||
extern UINT8 eeprom_read_bit(void);
|
||||
extern void eeprom_set_clk(UINT8 clk);
|
||||
extern void eeprom_set_ce(UINT8 ce);
|
||||
extern void eeprom_set_data(UINT8 data);
|
||||
|
||||
extern void eeprom_save_state(FILE *);
|
||||
extern void eeprom_load_state(FILE *);
|
||||
|
||||
extern INT eeprom_load(CHAR *);
|
||||
extern INT eeprom_save(CHAR *);
|
||||
|
||||
extern void eeprom_reset(void);
|
||||
|
||||
#endif // INCLUDED_EEPROM_H
|
2391
core/model3.c
Normal file
2391
core/model3.c
Normal file
File diff suppressed because it is too large
Load diff
417
core/model3.h
Normal file
417
core/model3.h
Normal file
|
@ -0,0 +1,417 @@
|
|||
/*
|
||||
* Sega Model 3 Emulator
|
||||
* Copyright (C) 2003 Bart Trzynadlowski, Ville Linde, Stefano Teso
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 (license.txt); if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* model3.h
|
||||
*
|
||||
* Model 3 header. This serves as the primary header file for all modules to
|
||||
* include.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_MODEL3_H
|
||||
#define INCLUDED_MODEL3_H
|
||||
|
||||
/******************************************************************/
|
||||
/* Program Information */
|
||||
/******************************************************************/
|
||||
|
||||
#define VERSION "0.01" // program version
|
||||
#define VERSION_MAJOR 0x00 // major version number (BCD)
|
||||
#define VERSION_MINOR 0x01 // minor version number (BCD)
|
||||
|
||||
/******************************************************************/
|
||||
/* Includes */
|
||||
/******************************************************************/
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
//#include "zlib.h"
|
||||
|
||||
#include "osd.h" // provided by the port to define data types, etc.
|
||||
|
||||
#include "ppc_itp/ppc.h"
|
||||
|
||||
//#include "m68k/m68k.h"
|
||||
|
||||
#include "controls.h"
|
||||
#include "dma.h"
|
||||
#include "dsb1.h"
|
||||
#include "eeprom.h"
|
||||
#include "bridge.h"
|
||||
#include "r3d.h"
|
||||
#include "render.h"
|
||||
#include "rtc.h"
|
||||
#include "scsi.h"
|
||||
#include "scsp.h"
|
||||
#include "tilegen.h"
|
||||
#include "file.h"
|
||||
|
||||
#include "osd_common.h" // defines OSD interface (must be included last)
|
||||
|
||||
/******************************************************************/
|
||||
/* Helpful Macros */
|
||||
/******************************************************************/
|
||||
|
||||
#define MODEL3_OKAY 0 /* Everything went okay */
|
||||
#define MODEL3_ERROR -1 /* Some error happened */
|
||||
|
||||
#define MODEL3_SCREEN_WIDTH 496
|
||||
#define MODEL3_SCREEN_HEIGHT 384
|
||||
|
||||
#define SAFE_FREE(p) { if(p != NULL) free(p); p = NULL; }
|
||||
|
||||
#define PPC_PC ppc_get_reg(PPC_REG_PC)
|
||||
#define PPC_LR ppc_get_reg(PPC_REG_LR)
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#define BSWAP16(x) _byteswap_ushort(x)
|
||||
#define BSWAP32(x) _byteswap_ulong(x)
|
||||
|
||||
#else
|
||||
|
||||
static UINT16 BSWAP16(UINT16 d)
|
||||
{
|
||||
return(((d >> 8) & 0x00FF) |
|
||||
((d << 8) & 0xFF00));
|
||||
}
|
||||
|
||||
static UINT32 BSWAP32(UINT32 d)
|
||||
{
|
||||
return(((d >> 24) & 0x000000FF) |
|
||||
((d >> 8) & 0x0000FF00) |
|
||||
((d << 8) & 0x00FF0000) |
|
||||
((d << 24) & 0xFF000000));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/******************************************************************/
|
||||
/* Configuration Structure */
|
||||
/******************************************************************/
|
||||
|
||||
/*
|
||||
* Game Flags
|
||||
*
|
||||
* Identify various properties that the games can have.
|
||||
*/
|
||||
|
||||
#define GAME_OWN_STEERING_WHEEL (1 << 0) // analog steering wheel
|
||||
#define GAME_OWN_GUN (1 << 1) // light gun
|
||||
#define GAME_OWN_DSB1 (1 << 2) // DSB1 sound board
|
||||
|
||||
typedef enum
|
||||
{
|
||||
P1_BUTTON_1,
|
||||
P1_BUTTON_2,
|
||||
P1_BUTTON_3,
|
||||
P1_BUTTON_4,
|
||||
P1_BUTTON_5,
|
||||
P1_BUTTON_6,
|
||||
P1_BUTTON_7,
|
||||
P1_BUTTON_8,
|
||||
P2_BUTTON_1,
|
||||
P2_BUTTON_2,
|
||||
P2_BUTTON_3,
|
||||
P2_BUTTON_4,
|
||||
P2_BUTTON_5,
|
||||
P2_BUTTON_6,
|
||||
P2_BUTTON_7,
|
||||
P2_BUTTON_8,
|
||||
P1_JOYSTICK_UP,
|
||||
P1_JOYSTICK_DOWN,
|
||||
P1_JOYSTICK_LEFT,
|
||||
P1_JOYSTICK_RIGHT,
|
||||
P2_JOYSTICK_UP,
|
||||
P2_JOYSTICK_DOWN,
|
||||
P2_JOYSTICK_LEFT,
|
||||
P2_JOYSTICK_RIGHT,
|
||||
} GAME_BUTTON;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ANALOG_AXIS_1,
|
||||
ANALOG_AXIS_2,
|
||||
ANALOG_AXIS_3,
|
||||
ANALOG_AXIS_4,
|
||||
ANALOG_AXIS_5,
|
||||
ANALOG_AXIS_6,
|
||||
ANALOG_AXIS_7,
|
||||
ANALOG_AXIS_8,
|
||||
} GAME_ANALOG;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct
|
||||
{
|
||||
UINT8 control_set;
|
||||
UINT8 control_bit;
|
||||
GAME_BUTTON mapping;
|
||||
int enabled;
|
||||
} button[16];
|
||||
|
||||
struct
|
||||
{
|
||||
GAME_ANALOG mapping;
|
||||
int enabled;
|
||||
UINT8 center;
|
||||
} analog_axis[8];
|
||||
|
||||
} GAME_CONTROLS;
|
||||
|
||||
/*
|
||||
* CONFIG Structure
|
||||
*
|
||||
* Emulator configuration and game information.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/*
|
||||
* Emulator Configuration
|
||||
*
|
||||
* Determines the behavior of the emulator itself. These fields can be
|
||||
* loaded, saved, and modified. The user has control over these options.
|
||||
*/
|
||||
|
||||
BOOL log_enabled; // whether to log (no effect if _LOG_ not defined)
|
||||
BOOL fullscreen;
|
||||
BOOL triple_buffer;
|
||||
INT width;
|
||||
INT height;
|
||||
BOOL stretch;
|
||||
FLAGS layer_enable;
|
||||
CHAR rom_path[512];
|
||||
CHAR rom_list[512];
|
||||
CHAR backup_path[512];
|
||||
BOOL fps_limit;
|
||||
BOOL show_fps;
|
||||
|
||||
/*
|
||||
* Game Configuration
|
||||
*
|
||||
* Information on the game currently being emulated. The user has no
|
||||
* control over this stuff -- it's internal to the emulator only.
|
||||
*/
|
||||
|
||||
CHAR game_id[8+1]; // game ID string (max 8 chars + null terminator)
|
||||
CHAR game_name[128];
|
||||
INT step; // hardware step (0x15 = Step 1.5, etc.)
|
||||
INT bridge; // type of PCIBMC (1=MPC105, 2=MPC106)
|
||||
FLAGS flags; // game info flags
|
||||
BOOL has_lightgun;
|
||||
|
||||
// Game controls
|
||||
GAME_CONTROLS controls;
|
||||
|
||||
} CONFIG;
|
||||
|
||||
enum
|
||||
{
|
||||
ROMTYPE_NONE = 0,
|
||||
ROMTYPE_PROG0 = 1,
|
||||
ROMTYPE_PROG1,
|
||||
ROMTYPE_PROG2,
|
||||
ROMTYPE_PROG3,
|
||||
ROMTYPE_CROM00,
|
||||
ROMTYPE_CROM01,
|
||||
ROMTYPE_CROM02,
|
||||
ROMTYPE_CROM03,
|
||||
ROMTYPE_CROM10,
|
||||
ROMTYPE_CROM11,
|
||||
ROMTYPE_CROM12,
|
||||
ROMTYPE_CROM13,
|
||||
ROMTYPE_CROM20,
|
||||
ROMTYPE_CROM21,
|
||||
ROMTYPE_CROM22,
|
||||
ROMTYPE_CROM23,
|
||||
ROMTYPE_CROM30,
|
||||
ROMTYPE_CROM31,
|
||||
ROMTYPE_CROM32,
|
||||
ROMTYPE_CROM33,
|
||||
ROMTYPE_VROM00,
|
||||
ROMTYPE_VROM01,
|
||||
ROMTYPE_VROM02,
|
||||
ROMTYPE_VROM03,
|
||||
ROMTYPE_VROM04,
|
||||
ROMTYPE_VROM05,
|
||||
ROMTYPE_VROM06,
|
||||
ROMTYPE_VROM07,
|
||||
ROMTYPE_VROM10,
|
||||
ROMTYPE_VROM11,
|
||||
ROMTYPE_VROM12,
|
||||
ROMTYPE_VROM13,
|
||||
ROMTYPE_VROM14,
|
||||
ROMTYPE_VROM15,
|
||||
ROMTYPE_VROM16,
|
||||
ROMTYPE_VROM17,
|
||||
ROMTYPE_SPROG,
|
||||
ROMTYPE_SROM0,
|
||||
ROMTYPE_SROM1,
|
||||
ROMTYPE_SROM2,
|
||||
ROMTYPE_SROM3,
|
||||
ROMTYPE_DSBPROG,
|
||||
ROMTYPE_DSBROM0,
|
||||
ROMTYPE_DSBROM1,
|
||||
ROMTYPE_DSBROM2,
|
||||
ROMTYPE_DSBROM3,
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int type;
|
||||
char name[20];
|
||||
int size;
|
||||
UINT32 crc32;
|
||||
int load;
|
||||
} ROMFILE;
|
||||
|
||||
typedef struct {
|
||||
UINT32 address;
|
||||
UINT32 data;
|
||||
INT size; // 8, 16, or 32
|
||||
} PATCH;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char game[20];
|
||||
char parent[20];
|
||||
char title[256];
|
||||
char manufacturer[32];
|
||||
int year;
|
||||
int step;
|
||||
int bridge;
|
||||
int cromsize;
|
||||
FLAGS flags;
|
||||
int num_patches;
|
||||
PATCH patch[64];
|
||||
|
||||
ROMFILE rom[64];
|
||||
|
||||
GAME_CONTROLS controls;
|
||||
|
||||
} ROMSET;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char id[60];
|
||||
UINT32 int_id;
|
||||
} STRING_ID;
|
||||
|
||||
static int get_string_id(const char *string, STRING_ID *idtable)
|
||||
{
|
||||
int i=0;
|
||||
|
||||
while (strlen(idtable[i].id) > 0)
|
||||
{
|
||||
if (_stricmp(string, idtable[i].id) == 0)
|
||||
{
|
||||
return idtable[i].int_id;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* m3_config
|
||||
*
|
||||
* A global variable accessible by all parts of the emulator after emulation
|
||||
* begins successfully.
|
||||
*/
|
||||
|
||||
extern CONFIG m3_config;
|
||||
|
||||
extern void message(int, char * fmt, ...);
|
||||
extern void error(char * fmt, ...);
|
||||
|
||||
extern BOOL parse_config(const char *config_name);
|
||||
extern int parse_romlist(char *romlist_name, ROMSET *_romset);
|
||||
|
||||
/*
|
||||
* Profile
|
||||
*/
|
||||
|
||||
extern void profile_section_entry(CHAR * name);
|
||||
extern void profile_section_exit(CHAR * name);
|
||||
extern UINT64 profile_get_stat(CHAR * name);
|
||||
extern void profile_reset_sect(CHAR * name);
|
||||
extern void profile_cleanup(void);
|
||||
extern void profile_print(CHAR * string);
|
||||
|
||||
#ifdef _PROFILE_
|
||||
#define PROFILE_SECT_ENTRY(n) profile_section_entry(n);
|
||||
#define PROFILE_SECT_EXIT(n) profile_section_exit(n);
|
||||
#define PROFILE_SECT_RESET(n) profile_reset_sect(n);
|
||||
#else // !_PROFILE_
|
||||
#define PROFILE_SECT_ENTRY(n)
|
||||
#define PROFILE_SECT_EXIT(n)
|
||||
#define PROFILE_SECT_RESET(n)
|
||||
#endif // _PROFILE_
|
||||
|
||||
/******************************************************************/
|
||||
/* Functions */
|
||||
/******************************************************************/
|
||||
|
||||
#ifdef _LOG_
|
||||
#define LOG_INIT _log_init
|
||||
#define LOG _log
|
||||
#else // !_LOG_
|
||||
#define LOG_INIT
|
||||
#define LOG
|
||||
#endif // _LOG
|
||||
|
||||
extern void _log(char * path, char * fmt, ...);
|
||||
extern void _log_init(char * path);
|
||||
|
||||
extern BOOL model3_init(void);
|
||||
extern void model3_shutdown(void);
|
||||
|
||||
extern BOOL model3_load(void);
|
||||
|
||||
extern void model3_reset(void);
|
||||
extern void model3_run_frame(void);
|
||||
extern void model3_add_irq(UINT8);
|
||||
extern void model3_remove_irq(UINT8);
|
||||
|
||||
extern BOOL model3_save_state(CHAR *);
|
||||
extern BOOL model3_load_state(CHAR *);
|
||||
|
||||
extern void model3_load_eeprom(void);
|
||||
extern void model3_save_eeprom(void);
|
||||
extern void model3_load_bram(void);
|
||||
extern void model3_save_bram(void);
|
||||
|
||||
extern UINT8 m3_ppc_read_8(UINT32 a);
|
||||
extern UINT16 m3_ppc_read_16(UINT32 a);
|
||||
extern UINT32 m3_ppc_read_32(UINT32 a);
|
||||
extern UINT64 m3_ppc_read_64(UINT32 a);
|
||||
extern void m3_ppc_write_8(UINT32 a, UINT8 d);
|
||||
extern void m3_ppc_write_16(UINT32 a, UINT16 d);
|
||||
extern void m3_ppc_write_32(UINT32 a, UINT32 d);
|
||||
extern void m3_ppc_write_64(UINT32 a, UINT64 d);
|
||||
|
||||
extern void model3_dma_transfer(UINT32 src, UINT32 dst, int length, BOOL swap_words);
|
||||
|
||||
/******************************************************************/
|
||||
|
||||
#endif // INCLUDED_MODEL3_H
|
937
core/r3d.c
Normal file
937
core/r3d.c
Normal file
|
@ -0,0 +1,937 @@
|
|||
/*
|
||||
* Sega Model 3 Emulator
|
||||
* Copyright (C) 2003 Bart Trzynadlowski, Ville Linde, Stefano Teso
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 (license.txt); if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* r3d.c
|
||||
*
|
||||
* Real3D Model 3 graphics system emulation. The 3D hardware in Model 3 is
|
||||
* supposedly based on the Pro-1000.
|
||||
*
|
||||
* To-Do List:
|
||||
* -----------
|
||||
* - In VS2_98, in the attract mode, when the camera zooms in on the score
|
||||
* board for South Africa vs. Nigeria, the "Nigeria" text texture is
|
||||
* garbage.
|
||||
* - RAM texture uploading is too weird to be true.
|
||||
*/
|
||||
|
||||
/*
|
||||
* RAM Size:
|
||||
* ---------
|
||||
*
|
||||
* It appears that there is 2MB total of "culling RAM." 1MB appears at
|
||||
* 0x8C000000 and the other at 0x8E000000. Step 1.0 and 1.5 appear to have
|
||||
* 1MB of polygon RAM, but Step 2.0 (and probably 2.1) clearly uses 2MB.
|
||||
*/
|
||||
|
||||
#include "model3.h"
|
||||
|
||||
extern UINT8 *ram;
|
||||
|
||||
/******************************************************************/
|
||||
/* Privates */
|
||||
/******************************************************************/
|
||||
|
||||
static UINT8 *culling_ram_8e; // culling RAM at 0x8E000000
|
||||
static UINT8 *culling_ram_8c; // culling RAM at 0x8C000000
|
||||
static UINT8 *polygon_ram; // polygon RAM at 0x98000000
|
||||
static UINT8 *texture_ram; // texture RAM
|
||||
static UINT8 *vrom;
|
||||
|
||||
static UINT8 texture_buffer_ram[1*1024*1024];
|
||||
|
||||
static UINT32 vrom_texture_address;
|
||||
static UINT32 vrom_texture_header;
|
||||
|
||||
static UINT32 texture_last_addr = 0;
|
||||
static UINT32 texture_header = 0;
|
||||
|
||||
/******************************************************************/
|
||||
/* Interface */
|
||||
/******************************************************************/
|
||||
|
||||
/*
|
||||
* void r3d_init(UINT8 *culling_ram_8e_ptr, UINT8 *culling_ram_8c_ptr,
|
||||
* UINT8 *polygon_ram_ptr, UINT8 *texture_ram, UINT8 *vrom_ptr);
|
||||
*
|
||||
* Initializes the Real3D graphics emulation.
|
||||
*
|
||||
* Parameters:
|
||||
* culling_ram_8e_ptr = Pointer to 0x8E000000 culling RAM.
|
||||
* culling_ram_8c_ptr = Pointer to 0x8C000000 culling RAM.
|
||||
* polygon_ram_ptr = Pointer to polygon RAM.
|
||||
* texture_ram = Pointer to texture RAM.
|
||||
* vrom_ptr = Pointer to VROM.
|
||||
*/
|
||||
|
||||
void r3d_init(UINT8 *culling_ram_8e_ptr, UINT8 *culling_ram_8c_ptr,
|
||||
UINT8 *polygon_ram_ptr, UINT8 *texture_ram_ptr, UINT8 *vrom_ptr)
|
||||
{
|
||||
culling_ram_8e = culling_ram_8e_ptr;
|
||||
culling_ram_8c = culling_ram_8c_ptr;
|
||||
polygon_ram = polygon_ram_ptr;
|
||||
texture_ram = texture_ram_ptr;
|
||||
vrom = vrom_ptr;
|
||||
|
||||
LOG_INIT("texture.log");
|
||||
}
|
||||
|
||||
/*
|
||||
* void r3d_shutdown(void);
|
||||
*
|
||||
* Shuts down the Real3D emulation.
|
||||
*/
|
||||
|
||||
void r3d_shutdown(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* void r3d_reset(void);
|
||||
*
|
||||
* Resets the Real3D graphics hardware. RAM is cleared in order to prevent
|
||||
* the renderer from drawing garbage and possibly locking up as a result.
|
||||
*/
|
||||
|
||||
void r3d_reset(void)
|
||||
{
|
||||
memset(culling_ram_8e, 0, 1*1024*1024);
|
||||
memset(culling_ram_8c, 0, 4*1024*1024);
|
||||
memset(polygon_ram, 0, 2*1024*1024);
|
||||
memset(texture_ram, 0, 2048*2048*2);
|
||||
tap_reset();
|
||||
}
|
||||
|
||||
/*
|
||||
* void r3d_save_state(FILE *fp);
|
||||
*
|
||||
* Saves the state of the Real3D graphics hardware to a file.
|
||||
*
|
||||
* Parameters:
|
||||
* fp = File to save to.
|
||||
*/
|
||||
|
||||
void r3d_save_state(FILE *fp)
|
||||
{
|
||||
fwrite(culling_ram_8e, sizeof(UINT8), 1*1024*1024, fp);
|
||||
fwrite(culling_ram_8c, sizeof(UINT8), 4*1024*1024, fp);
|
||||
fwrite(polygon_ram, sizeof(UINT8), 2*1024*1024, fp);
|
||||
fwrite(texture_ram, sizeof(UINT8), 2048*2048*2, fp);
|
||||
}
|
||||
|
||||
/*
|
||||
* void r3d_load_state(FILE *fp);
|
||||
*
|
||||
* Loads the state of the Real3D graphics hardware from a file.
|
||||
*
|
||||
* Parameters:
|
||||
* fp = File to load from.
|
||||
*/
|
||||
|
||||
void r3d_load_state(FILE *fp)
|
||||
{
|
||||
fread(culling_ram_8e, sizeof(UINT8), 1*1024*1024, fp);
|
||||
fread(culling_ram_8c, sizeof(UINT8), 4*1024*1024, fp);
|
||||
fread(polygon_ram, sizeof(UINT8), 2*1024*1024, fp);
|
||||
fread(texture_ram, sizeof(UINT8), 2048*2048*2, fp);
|
||||
|
||||
osd_renderer_invalidate_textures(0, 0, 2048, 2048, texture_ram);
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
/* Texture Memory Management */
|
||||
/******************************************************************/
|
||||
|
||||
static const INT decode[64] =
|
||||
{
|
||||
0, 1, 4, 5, 8, 9,12,13,
|
||||
2, 3, 6, 7,10,11,14,15,
|
||||
16,17,20,21,24,25,28,29,
|
||||
18,19,22,23,26,27,30,31,
|
||||
32,33,36,37,40,41,44,45,
|
||||
34,35,38,39,42,43,46,47,
|
||||
48,49,52,53,56,57,60,61,
|
||||
50,51,54,55,58,59,62,63
|
||||
};
|
||||
|
||||
/*
|
||||
* store_texture_tile():
|
||||
*
|
||||
* Writes a single 8x8 texture tile into the appropriate part of the texture
|
||||
* sheet.
|
||||
*/
|
||||
|
||||
static void store_texture_tile(UINT x, UINT y, UINT8 *src, UINT bpp, BOOL little_endian)
|
||||
{
|
||||
UINT xi, yi, pixel_offs;
|
||||
UINT16 rgb16;
|
||||
UINT8 gray8;
|
||||
|
||||
for (yi = 0; yi < 8; yi++)
|
||||
{
|
||||
for (xi = 0; xi < 8; xi++)
|
||||
{
|
||||
/*
|
||||
* Grab the pixel offset from the decode[] array and fetch the
|
||||
* pixel word
|
||||
*/
|
||||
|
||||
if (little_endian)
|
||||
{
|
||||
if (bpp == 2)
|
||||
{
|
||||
/*
|
||||
* XOR with 1 in little endian mode -- every word contains
|
||||
* 2 16-bit pixels, thus they are swapped
|
||||
*/
|
||||
|
||||
pixel_offs = decode[(yi * 8 + xi) ^ 1] * 2;
|
||||
rgb16 = *(UINT16 *) &src[pixel_offs];
|
||||
}
|
||||
else
|
||||
{
|
||||
pixel_offs = decode[((yi ^ 1) * 8 + (xi ^ 1))];
|
||||
gray8 = src[pixel_offs];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bpp == 2)
|
||||
{
|
||||
pixel_offs = decode[yi * 8 + xi] * 2;
|
||||
rgb16 = (src[pixel_offs + 0] << 8) | src[pixel_offs + 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
pixel_offs = decode[yi * 8 + xi];
|
||||
gray8 = src[pixel_offs + 0];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Store within the texture sheet
|
||||
*/
|
||||
|
||||
if (bpp == 2)
|
||||
*(UINT16 *) &texture_ram[((y + yi) * 2048 + (x + xi)) * 2] = rgb16;
|
||||
else
|
||||
texture_ram[(((y + yi) * 2048 + x) * 2) + xi] = gray8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* store_texture():
|
||||
*
|
||||
* Writes a texture into the texture sheet. The pixel words are not decoded,
|
||||
* but the 16-bit pixels are converted into a common endianness (little.)
|
||||
* 8-bit pixels are not expanded into 16-bits.
|
||||
*
|
||||
* bpp (bytes per pixel) must be 1 or 2.
|
||||
*/
|
||||
|
||||
static void store_texture(UINT x, UINT y, UINT w, UINT h, UINT8 *src, UINT bpp, BOOL little_endian)
|
||||
{
|
||||
UINT xi, yi;
|
||||
UINT bw;
|
||||
|
||||
if(bpp == 2)
|
||||
bw = 1;
|
||||
else
|
||||
bw = 2;
|
||||
|
||||
for (yi = 0; yi < h; yi += 8)
|
||||
{
|
||||
for (xi = 0; xi < w; xi += 8)
|
||||
{
|
||||
store_texture_tile(x + (xi / bw), y + yi, src, bpp, little_endian);
|
||||
src += 8 * 8 * bpp; // each texture tile is 8x8 and 16-bit color
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* upload_texture():
|
||||
*
|
||||
* Uploads a texture to texture memory.
|
||||
*/
|
||||
|
||||
// Mipmap starting positions for each level
|
||||
static const int mipmap_xpos[11] =
|
||||
{ 1024, 1536, 1792, 1920, 1984, 2016, 2032, 2040, 2044, 2046, 2047 };
|
||||
static const int mipmap_ypos[11] =
|
||||
{ 512, 768, 896, 960, 992, 1008, 1016, 1020, 1022, 1023, 0 };
|
||||
|
||||
// Mipmap size dividers
|
||||
static const int mipmap_size[9] =
|
||||
{ 2, 4, 8, 16, 32, 64, 128, 256, 512 };
|
||||
|
||||
static void upload_texture(UINT32 header, UINT8 *src, BOOL little_endian)
|
||||
{
|
||||
UINT size_x, size_y, xpos, ypos, bit_depth, mip_ypos, page;
|
||||
int mipmap_num = 0;
|
||||
int mxpos, mypos, msize_x, msize_y;
|
||||
|
||||
PROFILE_SECT_ENTRY("real3d");
|
||||
|
||||
/*
|
||||
* Model 3 texture RAM appears as 2 2048x1024 textures. When textures are
|
||||
* uploaded, their size and position within a sheet is given. I treat the
|
||||
* texture sheet selection bit as an additional bit to the Y coordinate.
|
||||
*/
|
||||
|
||||
size_x = (header >> 14) & 7;
|
||||
size_y = (header >> 17) & 7;
|
||||
size_x = (32 << size_x); // width in pixels
|
||||
size_y = (32 << size_y); // height
|
||||
|
||||
ypos = (((header >> 7) & 0x1F) | ((header >> 15) & 0x20)) * 32;
|
||||
xpos = ((header >> 0) & 0x3F) * 32;
|
||||
|
||||
mip_ypos = ((header >> 7) & 0x1F) * 32;
|
||||
page = (header >> 15 & 0x20) ? 1 : 0;
|
||||
|
||||
if( header & 0x00800000 )
|
||||
bit_depth = 2; // 16-bit texture
|
||||
else
|
||||
bit_depth = 1; // 8-bit texture
|
||||
|
||||
LOG("texture.log", "%08X %d,%d\t%dx%d\n", header, xpos, ypos, size_x, size_y);
|
||||
|
||||
/*
|
||||
* Render the texture into the texture buffer
|
||||
*/
|
||||
|
||||
switch( (header >> 24) & 0xF )
|
||||
{
|
||||
case 0: // Texture with mipmaps
|
||||
store_texture(xpos, ypos, size_x, size_y, src, bit_depth, little_endian);
|
||||
osd_renderer_invalidate_textures(xpos, ypos, xpos, ypos, size_x, size_y, texture_ram, 0);
|
||||
|
||||
msize_x = size_x;
|
||||
msize_y = size_y;
|
||||
|
||||
// Store mipmaps
|
||||
while( msize_y > 8 && msize_x > 8 ) {
|
||||
|
||||
src += (msize_x * msize_y * bit_depth);
|
||||
msize_x /= 2;
|
||||
msize_y /= 2;
|
||||
|
||||
mxpos = mipmap_xpos[mipmap_num] + (xpos / mipmap_size[mipmap_num]);
|
||||
mypos = mipmap_ypos[mipmap_num] + (mip_ypos / mipmap_size[mipmap_num]);
|
||||
if(page)
|
||||
mypos += 1024;
|
||||
mipmap_num++;
|
||||
|
||||
store_texture(mxpos, mypos, msize_x, msize_y, src, bit_depth, little_endian);
|
||||
//osd_renderer_invalidate_textures(mxpos, mypos, xpos, ypos, size_x, size_y, texture_ram, mipmap_num);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: // Texture without mipmaps
|
||||
store_texture(xpos, ypos, size_x, size_y, src, bit_depth, little_endian);
|
||||
osd_renderer_invalidate_textures(xpos, ypos, xpos, ypos, size_x, size_y, texture_ram, 0);
|
||||
break;
|
||||
|
||||
case 2: // Only mipmaps
|
||||
msize_x = size_x;
|
||||
msize_y = size_y;
|
||||
while( msize_y > 8 && msize_x > 8 ) {
|
||||
|
||||
msize_x /= 2;
|
||||
msize_y /= 2;
|
||||
|
||||
mxpos = mipmap_xpos[mipmap_num] + (xpos / mipmap_size[mipmap_num]);
|
||||
mypos = mipmap_ypos[mipmap_num] + (mip_ypos / mipmap_size[mipmap_num]);
|
||||
if(page)
|
||||
mypos += 1024;
|
||||
mipmap_num++;
|
||||
|
||||
store_texture(mxpos, mypos, msize_x, msize_y, src, bit_depth, little_endian);
|
||||
//osd_renderer_invalidate_textures(mxpos, mypos, xpos, ypos, size_x, size_y, texture_ram, mipmap_num);
|
||||
|
||||
src += (msize_x * msize_y * bit_depth);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove any existing textures that may have been overwritten
|
||||
*/
|
||||
|
||||
//osd_renderer_invalidate_textures(xpos, ypos, size_x, size_y);
|
||||
|
||||
PROFILE_SECT_EXIT("real3d");
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
/* Access */
|
||||
/******************************************************************/
|
||||
|
||||
static BOOL trigger = 0;
|
||||
static UINT64 trigger_time;
|
||||
|
||||
/*
|
||||
* UINT32 r3d_read_32(UINT32 a);
|
||||
*
|
||||
* Reads a 32-bit word from the Real3D regions.
|
||||
*
|
||||
* Parameters:
|
||||
* a = Address.
|
||||
*
|
||||
* Returns:
|
||||
* Data read.
|
||||
*/
|
||||
|
||||
UINT32 r3d_read_32(UINT32 a)
|
||||
{
|
||||
static UINT32 _84000000 = 0;
|
||||
|
||||
// message(0, "%08X (%08X): Real3D read32 to %08X", PPC_PC, PPC_LR, a);
|
||||
|
||||
switch (a)
|
||||
{
|
||||
/*
|
||||
* In Lost World, routine at 0x1174E0 reads all the 0x840000XX status
|
||||
* registers and at 0x117A30, bit 0x02000000 is checked for.
|
||||
*/
|
||||
|
||||
case 0x84000000:
|
||||
return (_84000000 ^= 0xFFFFFFFF);
|
||||
case 0x84000004: // unknown
|
||||
case 0x84000008:
|
||||
case 0x8400000C:
|
||||
case 0x84000010:
|
||||
case 0x84000014:
|
||||
case 0x84000018:
|
||||
case 0x8400001C:
|
||||
case 0x84000020:
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
error("Unknown R3D read: %08X: %08X\n", ppc_get_pc(), a);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* void r3d_write_32(UINT32 a, UINT32 d);
|
||||
*
|
||||
* Writes a 32-bit word to the Real3D regions.
|
||||
*
|
||||
* Parameters:
|
||||
* a = Address.
|
||||
* d = Data to write.
|
||||
*/
|
||||
|
||||
UINT32 _9C000000, _9C000004, _9C000008;
|
||||
static int texture_start_pos = 8;
|
||||
static int texture_ram_ptr = 0;
|
||||
|
||||
void r3d_write_32(UINT32 a, UINT32 d)
|
||||
{
|
||||
static UINT32 last_addr;
|
||||
|
||||
if (a >= 0x8E000000 && a <= 0x8E0FFFFF) // culling RAM
|
||||
{
|
||||
*(UINT32 *) &culling_ram_8e[a & 0xFFFFF] = BSWAP32(d);
|
||||
return;
|
||||
}
|
||||
else if (a >= 0x8C000000 && a <= 0x8C3FFFFF) // culling RAM
|
||||
{
|
||||
*(UINT32 *) &culling_ram_8c[a & 0x3FFFFF] = BSWAP32(d);
|
||||
return;
|
||||
}
|
||||
else if (a >= 0x98000000 && a <= 0x981FFFFF) // polygon RAM
|
||||
{
|
||||
// if(a >= 0x98001000 && a < 0x98002000)
|
||||
// message(1, "color table: %08X = %08X", a, BSWAP32(d));
|
||||
|
||||
*(UINT32 *) &polygon_ram[a & 0x1FFFFF] = BSWAP32(d);
|
||||
return;
|
||||
}
|
||||
else if (a >= 0x94000000 && a <= 0x940FFFFF) // texture buffer
|
||||
{
|
||||
d = BSWAP32(d);
|
||||
*(UINT32 *)&texture_buffer_ram[texture_ram_ptr] = d;
|
||||
|
||||
texture_ram_ptr += 4;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (a)
|
||||
{
|
||||
case 0x88000000: // trigger?
|
||||
|
||||
//message(0, "%08X (%08X): 88000000 = %08X", PPC_PC, PPC_LR, BSWAP32(d));
|
||||
|
||||
if( texture_ram_ptr > 0 ) {
|
||||
int i=0;
|
||||
while( i < texture_ram_ptr ) {
|
||||
UINT32 length = (*(UINT32*)&texture_buffer_ram[i+0] / 2) + 2;
|
||||
UINT32 header = *(UINT32*)&texture_buffer_ram[i+4];
|
||||
upload_texture( header, &texture_buffer_ram[i+8], 1 );
|
||||
i += length;
|
||||
};
|
||||
}
|
||||
texture_ram_ptr = 0;
|
||||
|
||||
return;
|
||||
case 0x90000000: // VROM texture address
|
||||
vrom_texture_address = BSWAP32(d);
|
||||
LOG("model3.log", "VROM1 ADDR = %08X\n", BSWAP32(d));
|
||||
//message(0, "VROM texture address = %08X @ %08X (%08X)", BSWAP32(d), PPC_PC, PPC_LR);
|
||||
return;
|
||||
case 0x90000004:
|
||||
vrom_texture_header = BSWAP32(d);
|
||||
LOG("model3.log", "VROM1 HEAD = %08X\n", BSWAP32(d));
|
||||
//message(0, "VROM texture header = %08X @ %08X (%08X)", BSWAP32(d), PPC_PC, PPC_LR);
|
||||
return;
|
||||
case 0x90000008:
|
||||
upload_texture(vrom_texture_header, &vrom[(vrom_texture_address & 0xFFFFFF) * 4], 1);
|
||||
LOG("model3.log", "VROM1 SIZE = %08X\n", BSWAP32(d));
|
||||
//message(0, "VROM texture length = %08X @ %08X (%08X)", BSWAP32(d), PPC_PC, PPC_LR);
|
||||
return;
|
||||
case 0x9000000C: // ? Virtual On 2: These are almost certainly for VROM textures as well (I was too lazy to check :P)
|
||||
vrom_texture_address = BSWAP32(d);
|
||||
LOG("model3.log", "VROM2 ADDR = %08X\n", BSWAP32(d));
|
||||
//message(0, "90000000C = %08X", BSWAP32(d));
|
||||
return;
|
||||
case 0x90000010: // ?
|
||||
vrom_texture_header = BSWAP32(d);
|
||||
LOG("model3.log", "VROM2 HEAD = %08X\n", BSWAP32(d));
|
||||
//message(0, "900000010 = %08X", BSWAP32(d));
|
||||
return;
|
||||
case 0x90000014: // ?
|
||||
upload_texture(vrom_texture_header, &vrom[(vrom_texture_address & 0xFFFFFF) * 4], 1);
|
||||
LOG("model3.log", "VROM2 SIZE = %08X\n", BSWAP32(d));
|
||||
//message(0, "900000014 = %08X", BSWAP32(d));
|
||||
return;
|
||||
case 0x9C000000: // ?
|
||||
//message(0, "9C000000 = %08X", BSWAP32(d));
|
||||
LOG("model3.log", "%08X = %08X\n", a, d);
|
||||
_9C000000 = BSWAP32(d);
|
||||
return;
|
||||
case 0x9C000004: // ?
|
||||
//message(0, "9C000004 = %08X", BSWAP32(d));
|
||||
LOG("model3.log", "%08X = %08X\n", a, d);
|
||||
_9C000004 = BSWAP32(d);
|
||||
return;
|
||||
case 0x9C000008: // ?
|
||||
//message(0, "9C000008 = %08X", BSWAP32(d));
|
||||
LOG("model3.log", "%08X = %08X\n", a, d);
|
||||
_9C000008 = BSWAP32(d);
|
||||
return;
|
||||
}
|
||||
|
||||
error("Unknown R3D write: %08X: %08X = %08X\n", ppc_get_pc(), a, d);
|
||||
}
|
||||
|
||||
void r3d_dma_culling_ram_8c(UINT32 *src, UINT32 dst, int length, BOOL swap_words)
|
||||
{
|
||||
int i;
|
||||
|
||||
dst &= 0xffffff;
|
||||
|
||||
if (swap_words)
|
||||
{
|
||||
for (i=0; i < length; i+=4)
|
||||
{
|
||||
UINT32 d = BSWAP32(*src++);
|
||||
*(UINT32 *)&culling_ram_8c[dst] = d;
|
||||
dst += 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i=0; i < length; i+=4)
|
||||
{
|
||||
UINT32 d = (*src++);
|
||||
*(UINT32 *)&culling_ram_8c[dst] = d;
|
||||
dst += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void r3d_dma_culling_ram_8e(UINT32 *src, UINT32 dst, int length, BOOL swap_words)
|
||||
{
|
||||
int i;
|
||||
|
||||
dst &= 0xffffff;
|
||||
|
||||
if (swap_words)
|
||||
{
|
||||
for (i=0; i < length; i+=4)
|
||||
{
|
||||
UINT32 d = BSWAP32(*src++);
|
||||
*(UINT32 *)&culling_ram_8e[dst] = d;
|
||||
dst += 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i=0; i < length; i+=4)
|
||||
{
|
||||
UINT32 d = (*src++);
|
||||
*(UINT32 *)&culling_ram_8e[dst] = d;
|
||||
dst += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void r3d_dma_polygon_ram(UINT32 *src, UINT32 dst, int length, BOOL swap_words)
|
||||
{
|
||||
int i;
|
||||
|
||||
dst &= 0xffffff;
|
||||
|
||||
if (swap_words)
|
||||
{
|
||||
for (i=0; i < length; i+=4)
|
||||
{
|
||||
UINT32 d = BSWAP32(*src++);
|
||||
*(UINT32 *) &polygon_ram[dst] = d;
|
||||
dst += 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i=0; i < length; i+=4)
|
||||
{
|
||||
UINT32 d = (*src++);
|
||||
*(UINT32 *) &polygon_ram[dst] = d;
|
||||
dst += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void r3d_dma_texture_ram(UINT32 *src, UINT32 dst, int length, BOOL swap_words)
|
||||
{
|
||||
int i;
|
||||
|
||||
dst &= 0xffffff;
|
||||
|
||||
if (swap_words)
|
||||
{
|
||||
for (i=0; i < length; i+=4)
|
||||
{
|
||||
UINT32 d = BSWAP32(*src++);
|
||||
*(UINT32 *)&texture_buffer_ram[texture_ram_ptr] = d;
|
||||
texture_ram_ptr += 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i=0; i < length; i+=4)
|
||||
{
|
||||
UINT32 d = (*src++);
|
||||
*(UINT32 *)&texture_buffer_ram[texture_ram_ptr] = d;
|
||||
texture_ram_ptr += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
/* Real3D TAP Port */
|
||||
/******************************************************************/
|
||||
|
||||
/*
|
||||
* State (corresponding to fsm[][] Y) and Instruction Names
|
||||
*/
|
||||
|
||||
static char *state_name[] = { "Test-Logic/Reset", "Run-Test/Idle", "Select-DR-Scan",
|
||||
"Capture-DR", "Shift-DR", "Exit1-DR", "Pause-DR",
|
||||
"Exit2-DR", "Update-DR", "Select-IR-Scan",
|
||||
"Capture-IR", "Shift-IR", "Exit1-IR", "Pause-IR",
|
||||
"Exit2-IR", "Update-IR"
|
||||
};
|
||||
|
||||
/*
|
||||
* TAP Finite State Machine
|
||||
*
|
||||
* Y are states and X are outgoing paths. Constructed from information on page
|
||||
* 167 of the 3D-RAM manual.
|
||||
*/
|
||||
|
||||
#define NEXT(new_state) fsm[state][new_state]
|
||||
|
||||
static INT state; // current state
|
||||
static INT fsm[][2] = {
|
||||
{ 1, 0 }, // 0 Test-Logic/Reset
|
||||
{ 1, 2 }, // 1 Run-Test/Idle
|
||||
{ 3, 9 }, // 2 Select-DR-Scan
|
||||
{ 4, 5 }, // 3 Capture-DR
|
||||
{ 4, 5 }, // 4 Shift-DR
|
||||
{ 6, 8 }, // 5 Exit1-DR
|
||||
{ 6, 7 }, // 6 Pause-DR
|
||||
{ 4, 8 }, // 7 Exit2-DR
|
||||
{ 1, 2 }, // 8 Update-DR
|
||||
{ 10, 0 }, // 9 Select-IR-Scan
|
||||
{ 11, 12 }, // 10 Capture-IR
|
||||
{ 11, 12 }, // 11 Shift-IR
|
||||
{ 13, 15 }, // 12 Exit1-IR
|
||||
{ 13, 14 }, // 13 Pause-IR
|
||||
{ 11, 15 }, // 14 Exit2-IR
|
||||
{ 1, 2 } // 15 Update-IR
|
||||
};
|
||||
|
||||
/*
|
||||
* TAP Registers
|
||||
*/
|
||||
|
||||
static UINT64 current_instruction; // latched IR (not always equal to IR)
|
||||
static UINT64 ir; // instruction register (46 bits)
|
||||
|
||||
static UINT8 id_data[32]; // ASIC ID code data buffer
|
||||
static INT id_size; // size of ID data in bits
|
||||
static INT ptr; // current bit ptr for data
|
||||
|
||||
static BOOL tdo; // bit shifted out to TDO
|
||||
|
||||
/*
|
||||
* insert_bit():
|
||||
*
|
||||
* Inserts a bit into an arbitrarily long bit field. Bit 0 is assumed to be
|
||||
* the MSB of the first byte in the buffer.
|
||||
*/
|
||||
|
||||
static void insert_bit(UINT8 *buf, INT bit_num, INT bit)
|
||||
{
|
||||
INT bit_in_byte;
|
||||
|
||||
bit_in_byte = 7 - (bit_num & 7);
|
||||
|
||||
buf[bit_num / 8] &= ~(1 << bit_in_byte);
|
||||
buf[bit_num / 8] |= (bit << bit_in_byte);
|
||||
}
|
||||
|
||||
/*
|
||||
* insert_id():
|
||||
*
|
||||
* Inserts a 32-bit ID code into the ID bit field.
|
||||
*/
|
||||
|
||||
static void insert_id(UINT32 id, INT start_bit)
|
||||
{
|
||||
INT i;
|
||||
|
||||
for (i = 31; i >= 0; i--)
|
||||
insert_bit(id_data, start_bit++, (id >> i) & 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* shift():
|
||||
*
|
||||
* Shifts the data buffer right (towards LSB at byte 0) by 1 bit. The size of
|
||||
* the number of bits must be specified. The bit shifted out of the LSB is
|
||||
* returned.
|
||||
*/
|
||||
|
||||
static BOOL shift(UINT8 *data, INT num_bits)
|
||||
{
|
||||
INT i;
|
||||
BOOL shift_out, shift_in;
|
||||
|
||||
/*
|
||||
* This loop takes care of all the fully-filled bytes
|
||||
*/
|
||||
|
||||
shift_in = 0;
|
||||
for (i = 0; i < num_bits / 8; i++)
|
||||
{
|
||||
shift_out = data[i] & 1;
|
||||
data[i] >>= 1;
|
||||
data[i] |= (shift_in << 7);
|
||||
shift_in = shift_out; // carry over to next element's MSB
|
||||
}
|
||||
|
||||
/*
|
||||
* Take care of the last partial byte (if there is one)
|
||||
*/
|
||||
|
||||
if ((num_bits & 7) != 0)
|
||||
{
|
||||
shift_out = (data[i] >> (8 - (num_bits & 7))) & 1;
|
||||
data[i] >>= 1;
|
||||
data[i] |= (shift_in << 7);
|
||||
}
|
||||
|
||||
return shift_out;
|
||||
}
|
||||
|
||||
/*
|
||||
* BOOL tap_read(void);
|
||||
*
|
||||
* Reads TDO.
|
||||
*
|
||||
* Returns:
|
||||
* TDO.
|
||||
*/
|
||||
|
||||
BOOL tap_read(void)
|
||||
{
|
||||
return tdo;
|
||||
}
|
||||
|
||||
/*
|
||||
* void tap_write(BOOL tck, BOOL tms, BOOL tdi, BOOL trst);
|
||||
*
|
||||
* Writes to the TAP. State changes only occur on the rising edge of the clock
|
||||
* (tck = 1.)
|
||||
*
|
||||
* Parameters:
|
||||
* tck = Clock.
|
||||
* tms = Test mode select.
|
||||
* tdi = Serial data input. Must be 0 or 1 only!
|
||||
* trst = Reset.
|
||||
*/
|
||||
|
||||
void tap_write(BOOL tck, BOOL tms, BOOL tdi, BOOL trst)
|
||||
{
|
||||
if (!tck)
|
||||
return;
|
||||
|
||||
state = NEXT(tms);
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case 3: // Capture-DR
|
||||
|
||||
/*
|
||||
* Read ASIC IDs.
|
||||
*
|
||||
* The ID Sequence is:
|
||||
* - Jupiter
|
||||
* - Mercury
|
||||
* - Venus
|
||||
* - Earth
|
||||
* - Mars
|
||||
* - Mars (again)
|
||||
*
|
||||
* Note that different Model 3 steps have different chip
|
||||
* revisions, hence the different IDs returned below.
|
||||
*
|
||||
* On Step 1.5 and 1.0, instruction 0x0C631F8C7FFE is used to retrieve
|
||||
* the ID codes but Step 2.0 is a little weirder. It seems to use this
|
||||
* and either the state of the TAP after reset or other instructions
|
||||
* to read the IDs as well. This can be emulated in one of 2 ways:
|
||||
* Ignore the instruction and always load up the data or load the
|
||||
* data on TAP reset and when the instruction is issued.
|
||||
*/
|
||||
|
||||
if (m3_config.step == 0x10)
|
||||
{
|
||||
insert_id(0x116C7057, 1 + 0 * 32);
|
||||
insert_id(0x216C3057, 1 + 1 * 32);
|
||||
insert_id(0x116C4057, 1 + 2 * 32);
|
||||
insert_id(0x216C5057, 1 + 3 * 32);
|
||||
insert_id(0x116C6057, 1 + 4 * 32 + 1);
|
||||
insert_id(0x116C6057, 1 + 5 * 32 + 1);
|
||||
}
|
||||
else if (m3_config.step == 0x15)
|
||||
{
|
||||
insert_id(0x316C7057, 1 + 0 * 32);
|
||||
insert_id(0x316C3057, 1 + 1 * 32);
|
||||
insert_id(0x216C4057, 1 + 2 * 32); // Lost World may to use 0x016C4057
|
||||
insert_id(0x316C5057, 1 + 3 * 32);
|
||||
insert_id(0x216C6057, 1 + 4 * 32 + 1);
|
||||
insert_id(0x216C6057, 1 + 5 * 32 + 1);
|
||||
}
|
||||
else if (m3_config.step >= 0x20)
|
||||
{
|
||||
insert_id(0x416C7057, 1 + 0 * 32);
|
||||
insert_id(0x416C3057, 1 + 1 * 32);
|
||||
insert_id(0x316C4057, 1 + 2 * 32);
|
||||
insert_id(0x416C5057, 1 + 3 * 32);
|
||||
insert_id(0x316C6057, 1 + 4 * 32 + 1);
|
||||
insert_id(0x316C6057, 1 + 5 * 32 + 1);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 4: // Shift-DR
|
||||
|
||||
tdo = shift(id_data, id_size);
|
||||
break;
|
||||
|
||||
case 10: // Capture-IR
|
||||
|
||||
/*
|
||||
* Load lower 2 bits with 01 as per IEEE 1149.1-1990
|
||||
*/
|
||||
|
||||
ir = 1;
|
||||
break;
|
||||
|
||||
case 11: // Shift-IR
|
||||
|
||||
/*
|
||||
* Shift IR towards output and load in new data from TDI
|
||||
*/
|
||||
|
||||
tdo = ir & 1; // shift LSB to output
|
||||
ir >>= 1;
|
||||
ir |= ((UINT64) tdi << 45);
|
||||
break;
|
||||
|
||||
case 15: // Update-IR
|
||||
|
||||
/*
|
||||
* Latch IR (technically, this should occur on the falling edge of
|
||||
* TCK)
|
||||
*/
|
||||
|
||||
ir &= 0x3fffffffffff;
|
||||
current_instruction = ir;
|
||||
|
||||
#if 0
|
||||
{
|
||||
UINT8 *i = (UINT8 *) &ir;
|
||||
LOG("tap.log", "current instruction set: %02X%02X%02X%02X%02X%02X\n", i[5], i[4], i[3], i[2], i[1], i[0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (state == 4)
|
||||
LOG("tap.log", "state: Shift-DR %d\n", tdi);
|
||||
else if (state == 11)
|
||||
LOG("tap.log", "state: Shift-IR %d\n", tdi);
|
||||
else
|
||||
LOG("tap.log", "state: %s\n", state_name[state]);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* void tap_reset(void);
|
||||
*
|
||||
* Resets the TAP (simulating a power up or SCAN_RST signal.)
|
||||
*/
|
||||
|
||||
void tap_reset(void)
|
||||
{
|
||||
id_size = 197; // 197 bits
|
||||
|
||||
state = 0; // test-logic/reset
|
||||
}
|
49
core/r3d.h
Normal file
49
core/r3d.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Sega Model 3 Emulator
|
||||
* Copyright (C) 2003 Bart Trzynadlowski, Ville Linde, Stefano Teso
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 (license.txt); if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* r3d.h
|
||||
*
|
||||
* Real3D Model 3 graphics system header.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_R3D_H
|
||||
#define INCLUDED_R3D_H
|
||||
|
||||
extern void r3d_init(UINT8 *, UINT8 *, UINT8 *, UINT8 *, UINT8 *);
|
||||
extern void r3d_shutdown(void);
|
||||
extern void r3d_reset(void);
|
||||
|
||||
extern void r3d_save_state(FILE *);
|
||||
extern void r3d_load_state(FILE *);
|
||||
|
||||
extern UINT32 r3d_read_32(UINT32 a);
|
||||
extern void r3d_write_32(UINT32 a, UINT32 d);
|
||||
|
||||
extern void r3d_dma_culling_ram_8c(UINT32 *src, UINT32 dst, int length, BOOL swap_words);
|
||||
extern void r3d_dma_culling_ram_8e(UINT32 *src, UINT32 dst, int length, BOOL swap_words);
|
||||
extern void r3d_dma_polygon_ram(UINT32 *src, UINT32 dst, int length, BOOL swap_words);
|
||||
extern void r3d_dma_texture_ram(UINT32 *src, UINT32 dst, int length, BOOL swap_words);
|
||||
|
||||
|
||||
extern void tap_reset(void);
|
||||
extern BOOL tap_read(void);
|
||||
extern void tap_write(BOOL tck, BOOL tms, BOOL tdi, BOOL trst);
|
||||
|
||||
#endif // INCLUDED_R3D_H
|
||||
|
823
core/render.c
Normal file
823
core/render.c
Normal file
|
@ -0,0 +1,823 @@
|
|||
/*
|
||||
* Sega Model 3 Emulator
|
||||
* Copyright (C) 2003 Bart Trzynadlowski, Ville Linde, Stefano Teso
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 (license.txt); if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* render.c
|
||||
*
|
||||
* Rendering engine. Responsible for both Real3D graphics emulation and
|
||||
* for drawing the tile layers with correct priorities.
|
||||
*
|
||||
* NOTES:
|
||||
* ------
|
||||
*
|
||||
* - The "hardware coordinate system" is the default Model 3 coordinate system
|
||||
* before any matrices are applied. In it, +X is to the right, +Y is down,
|
||||
* and +Z is further into the screen.
|
||||
*/
|
||||
|
||||
#include "model3.h"
|
||||
|
||||
extern BOOL render_scene(void);
|
||||
|
||||
#define LOG_MODEL_ADDR 0 // logs model addresses to models.log
|
||||
|
||||
/******************************************************************/
|
||||
/* Useful Macros */
|
||||
/******************************************************************/
|
||||
|
||||
/*
|
||||
* Single-Precision Floating Point
|
||||
*/
|
||||
|
||||
#define GET_FLOAT(ptr) (*((float *) ptr))
|
||||
|
||||
/*
|
||||
* Trigonometry
|
||||
*/
|
||||
|
||||
#define PI 3.14159265358979323846264338327
|
||||
#define CONVERT_TO_DEGREES(a) (((a) * 180.0) / PI)
|
||||
|
||||
/******************************************************************/
|
||||
/* Private Data */
|
||||
/******************************************************************/
|
||||
|
||||
/*
|
||||
* Memory Regions
|
||||
*
|
||||
* These will be passed to us before rendering begins.
|
||||
*/
|
||||
|
||||
static UINT8 *culling_ram_8e; // pointer to Real3D culling RAM
|
||||
static UINT8 *culling_ram_8c; // pointer to Real3D culling RAM
|
||||
static UINT8 *polygon_ram; // pointer to Real3D polygon RAM
|
||||
static UINT8 *texture_ram; // pointer to Real3D texture RAM
|
||||
static UINT8 *vrom; // pointer to VROM
|
||||
|
||||
/*
|
||||
* Matrix Base
|
||||
*/
|
||||
|
||||
static float *matrix_base; // current scene's matrix table
|
||||
static float *lod_base; // current scene's LOD table
|
||||
|
||||
/*
|
||||
* Matrix Conversion Tables
|
||||
*
|
||||
* These tables map Model 3 matrix indices to column-major form.
|
||||
*/
|
||||
|
||||
static INT normal_matrix[4*4] = // normal matrices
|
||||
{
|
||||
3*4+0, 3*4+1, 3*4+2,
|
||||
0*4+0, 1*4+0, 2*4+0,
|
||||
0*4+1, 1*4+1, 2*4+1,
|
||||
0*4+2, 1*4+2, 2*4+2
|
||||
};
|
||||
static INT coord_matrix[4*4] = // coordinate system matrix
|
||||
{
|
||||
3*4+2, 3*4+0, 3*4+1,
|
||||
0*4+2, 1*4+2, 2*4+2,
|
||||
0*4+0, 1*4+0, 2*4+0,
|
||||
0*4+1, 1*4+1, 2*4+1
|
||||
};
|
||||
|
||||
/******************************************************************/
|
||||
/* Function Prototypes */
|
||||
/******************************************************************/
|
||||
|
||||
static void draw_block(UINT32 *);
|
||||
|
||||
/******************************************************************/
|
||||
/* TEMPORARY Model Tracking Code */
|
||||
/* */
|
||||
/* This code builds a list of VROM model addresses as they are */
|
||||
/* referenced. */
|
||||
/******************************************************************/
|
||||
|
||||
#if LOG_MODEL_ADDR
|
||||
|
||||
static struct model_addr
|
||||
{
|
||||
UINT32 addr; // model address in VROM
|
||||
INT num_polys; // number of polygons in model
|
||||
struct model_addr *next; // next in list
|
||||
} *model_addr_list = NULL;
|
||||
|
||||
static INT count_polys(UINT32 *mdl)
|
||||
{
|
||||
UINT32 link_data, mask;
|
||||
INT num_polys = 0, num_verts, i, stop;
|
||||
|
||||
do
|
||||
{
|
||||
stop = BSWAP32(mdl[1]) & 4; // get stop bit
|
||||
link_data = BSWAP32(mdl[0]); // link data
|
||||
|
||||
/*
|
||||
* Count how many vertices the polygon has by subtracting the number
|
||||
* of vertices used from the previous polygon from 4 (quad) or 3 (tri)
|
||||
*/
|
||||
|
||||
num_verts = (link_data & 0x40) ? 4 : 3;
|
||||
mask = 8;
|
||||
for (i = 0; i < 4 && num_verts; i++)
|
||||
{
|
||||
if ((link_data & mask))
|
||||
--num_verts;
|
||||
mask >>= 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Advance to next polygon
|
||||
*/
|
||||
|
||||
mdl += 7 + num_verts * 4;
|
||||
++num_polys; // increment count
|
||||
} while (!stop);
|
||||
|
||||
return num_polys;
|
||||
}
|
||||
|
||||
static void record_model(UINT32 addr)
|
||||
{
|
||||
struct model_addr *l;
|
||||
|
||||
/*
|
||||
* Search for this entry -- if already in the list, exit
|
||||
for (l = model_addr_list; l != NULL; l = l->next)
|
||||
{
|
||||
if (addr == l->addr)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add new entry
|
||||
*/
|
||||
|
||||
l = malloc(sizeof(struct model_addr));
|
||||
if (l == NULL)
|
||||
error("out of memory in record_model()");
|
||||
l->addr = addr;
|
||||
l->num_polys = count_polys((UINT32 *) &vrom[addr * 4]);
|
||||
l->next = model_addr_list;
|
||||
model_addr_list = l;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/******************************************************************/
|
||||
/* Real3D Address Translation */
|
||||
/******************************************************************/
|
||||
|
||||
/*
|
||||
* translate_scene_graph_address():
|
||||
*
|
||||
* Returns a pointer to scene graph (culling RAM) memory given a scene graph
|
||||
* address (only lower 24 bits are relevant.)
|
||||
*/
|
||||
|
||||
static UINT32 *translate_scene_graph_address(UINT32 addr)
|
||||
{
|
||||
addr &= 0x00FFFFFF; // only lower 24 bits matter
|
||||
if ((addr & 0x00800000)) // 8E culling RAM
|
||||
{
|
||||
if (addr >= 0x00840000)
|
||||
error("translate_scene_graph_address(): addr = %08X", addr);
|
||||
return (UINT32 *) &culling_ram_8e[(addr & 0x0003FFFF) * 4];
|
||||
}
|
||||
else // 8C culling RAM
|
||||
{
|
||||
if (addr >= 0x00100000)
|
||||
error("translate_scene_graph_address(): addr = %08X", addr);
|
||||
return (UINT32 *) &culling_ram_8c[(addr & 0x000FFFFF) * 4];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* draw_model():
|
||||
*
|
||||
* Translates the model address and draws the model (accounting for
|
||||
* endianness.)
|
||||
*/
|
||||
|
||||
static void draw_model(UINT32 addr)
|
||||
{
|
||||
addr &= 0x00FFFFFF; // only lower 24 bits matter
|
||||
if (addr > 0x00100000) // VROM
|
||||
{
|
||||
#if LOG_MODEL_ADDR
|
||||
record_model(addr); // TEMP: this tracks model addresses in VROM
|
||||
#endif
|
||||
osd_renderer_draw_model((UINT32 *) &vrom[(addr & 0x00FFFFFF) * 4], addr, 0);
|
||||
}
|
||||
else // polygon RAM (may actually be 4MB)
|
||||
{
|
||||
osd_renderer_draw_model((UINT32 *) &polygon_ram[(addr & 0x000FFFFF) * 4], addr, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
/* Matrices */
|
||||
/* */
|
||||
/* Model 3 matrices are 4x3 in size (they lack the translational */
|
||||
/* component.) They are layed out like this: */
|
||||
/* */
|
||||
/* 03 04 05 00 */
|
||||
/* 06 07 08 01 */
|
||||
/* 09 10 11 02 */
|
||||
/* */
|
||||
/* Matrix #0 is for coordinate system selection, it is layed out */
|
||||
/* as: */
|
||||
/* */
|
||||
/* 06 07 08 01 */
|
||||
/* 09 10 11 02 */
|
||||
/* 03 04 05 00 */
|
||||
/* */
|
||||
/* By default, the Model 3 appears to have a form of left-handed */
|
||||
/* coordinate system where positive Z means further away from the */
|
||||
/* camera and the positive Y axis points downward along the */
|
||||
/* screen. */
|
||||
/******************************************************************/
|
||||
|
||||
/*
|
||||
* get_matrix():
|
||||
*
|
||||
* Reads a Model 3 matrix and converts it to column-major 4x4 form using the
|
||||
* supplied conversion table.
|
||||
*/
|
||||
|
||||
static void get_matrix(MATRIX dest, INT convert[3*4], UINT num)
|
||||
{
|
||||
INT m = num * 12, i;
|
||||
|
||||
for (i = 0; i < 3*4; i++) // fetch Model 3 4x3 matrix
|
||||
dest[convert[i]] = matrix_base[m + i];
|
||||
dest[0*4+3] = 0.0; // fill in translation component to make 4x4
|
||||
dest[1*4+3] = 0.0;
|
||||
dest[2*4+3] = 0.0;
|
||||
dest[3*4+3] = 1.0;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************/
|
||||
/* Scene Graph Traversal */
|
||||
/******************************************************************/
|
||||
|
||||
int list_depth = 0;
|
||||
|
||||
/*
|
||||
* draw_list():
|
||||
*
|
||||
* Processes a list backwards. Each list element references a block.
|
||||
*/
|
||||
|
||||
static void draw_list(UINT32 *list)
|
||||
{
|
||||
UINT32 *list_ptr;
|
||||
UINT32 addr;
|
||||
|
||||
list_ptr = list;
|
||||
|
||||
if (list_depth > 2)
|
||||
return;
|
||||
|
||||
list_depth++;
|
||||
|
||||
/*
|
||||
* Go to end of list
|
||||
*/
|
||||
|
||||
while (1)
|
||||
{
|
||||
addr = *list_ptr;
|
||||
if ((addr & 0x02000000)) // last pointer in list
|
||||
{
|
||||
//--list_ptr;
|
||||
break;
|
||||
}
|
||||
if (addr == 0 || addr == 0x800800) // safeguard in case memory hasn't been set up
|
||||
{
|
||||
--list_ptr;
|
||||
break;
|
||||
}
|
||||
++list_ptr;
|
||||
}
|
||||
|
||||
while (list_ptr >= list)
|
||||
{
|
||||
addr = *list_ptr;
|
||||
if ((addr & 0x00FFFFFF) != 0x00FFFFFF)
|
||||
draw_block(translate_scene_graph_address(addr));
|
||||
--list_ptr; // next element
|
||||
}
|
||||
|
||||
list_depth--;
|
||||
}
|
||||
|
||||
/*
|
||||
* draw_pointer_list():
|
||||
*
|
||||
* Draws a 4-element pointer list for model LOD selection.
|
||||
*/
|
||||
|
||||
static void draw_pointer_list(UINT lod_num, UINT32* list)
|
||||
{
|
||||
float *lod_control = (float *)((UINT32)lod_base + lod_num * 8);
|
||||
|
||||
/*
|
||||
* Perform the actual LOD calculation, select the LOD model
|
||||
* to draw -- and perform additional LOD blending.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
printf( "LOD control = %f, %f\n"
|
||||
" %f, %f\n"
|
||||
" %f, %f\n"
|
||||
" %f, %f\n",
|
||||
lod_control[0], lod_control[1],
|
||||
lod_control[2], lod_control[3],
|
||||
lod_control[4], lod_control[5],
|
||||
lod_control[6], lod_control[7]
|
||||
);
|
||||
#endif
|
||||
|
||||
if(1)
|
||||
draw_model( list[0] );
|
||||
else if(0)
|
||||
draw_model( list[1] );
|
||||
else if(0)
|
||||
draw_model( list[2] );
|
||||
else
|
||||
draw_model( list[3] );
|
||||
}
|
||||
|
||||
/*
|
||||
* draw_block():
|
||||
*
|
||||
* Traverses a 10- (or 8-) word block (culling node.) The blocks have this
|
||||
* format:
|
||||
*
|
||||
* 0: ID code (upper 22 bits) and control bits
|
||||
* 1: Scaling? Not present in Step 1.0
|
||||
* 2: Flags? Not present in Step 1.0
|
||||
* 3: Lower 12 bits are matrix select. Upper bits contain flags.
|
||||
* 4: X translation (floating point)
|
||||
* 5: Y translation
|
||||
* 6: Z translation
|
||||
* 7: Pointer to model data, list, or pointer list
|
||||
* 8: Pointer to next block
|
||||
* 9: Pair of 16-bit values, related to rendering order
|
||||
*
|
||||
* Lower 16 bits of word 2 control "texture offset": -P-X XXXX X--Y YYYY, same
|
||||
* as in polygon headers. The purpose of this is unknown.
|
||||
*/
|
||||
|
||||
static void draw_block(UINT32 *block)
|
||||
{
|
||||
MATRIX m;
|
||||
UINT32 addr;
|
||||
INT offset;
|
||||
INT txoffs_x, txoffs_y, txoffs_page;
|
||||
|
||||
if (m3_config.step == 0x10) // Step 1.0 blocks are only 8 words
|
||||
offset = 2;
|
||||
else
|
||||
offset = 0;
|
||||
|
||||
addr = block[7 - offset];
|
||||
|
||||
txoffs_x = ((block[2] >> 7) & 0x3F) * 32;
|
||||
txoffs_y = (block[2] & 0x1F) * 32;
|
||||
txoffs_page = !!(block[2] & 0x4000);
|
||||
|
||||
/*
|
||||
* Apply matrix and translation
|
||||
*/
|
||||
|
||||
get_matrix(m, normal_matrix, block[3 - offset] & 0xFFF);
|
||||
osd_renderer_push_matrix();
|
||||
|
||||
if ((block[0] & 0x10)) // this bit appears to control translation
|
||||
{
|
||||
osd_renderer_translate_matrix(GET_FLOAT(&block[4 - offset]), GET_FLOAT(&block[5 - offset]), GET_FLOAT(&block[6 - offset]));
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((block[3 - offset] & 0xFFF) != 0)
|
||||
osd_renderer_multiply_matrix(m);
|
||||
}
|
||||
|
||||
/*
|
||||
* Bit 0x08 of word 0 indicates a pointer list
|
||||
*/
|
||||
|
||||
if ((block[0] & 0x08))
|
||||
draw_pointer_list((block[3 - offset] >> 12) & 127, translate_scene_graph_address(addr));
|
||||
else
|
||||
{
|
||||
if (addr != 0x0FFFFFFF && addr != 0x01000000 && addr != 0x00800800 && addr != 0) // valid?
|
||||
{
|
||||
switch ((addr >> 24) & 0xFF) // decide what address points to
|
||||
{
|
||||
case 0x00: // block
|
||||
draw_block(translate_scene_graph_address(addr));
|
||||
break;
|
||||
case 0x01: // model
|
||||
case 0x03: // model (Scud Race, model in VROM)
|
||||
draw_model(addr);
|
||||
break;
|
||||
case 0x04: // list
|
||||
draw_list(translate_scene_graph_address(addr));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
osd_renderer_pop_matrix();
|
||||
|
||||
/*
|
||||
* NOTE: This second pointer needs to be investigated further.
|
||||
*/
|
||||
|
||||
addr = block[8 - offset];
|
||||
if (addr != 0x01000000 && addr != 0x00800800 && addr != 0) // valid?
|
||||
draw_block(translate_scene_graph_address(addr));
|
||||
}
|
||||
|
||||
/*
|
||||
* get_viewport_data():
|
||||
*
|
||||
* Sets up a VIEWPORT structure. Is passed a pointer to the main node.
|
||||
*/
|
||||
|
||||
static void get_viewport_data(VIEWPORT *vp, UINT32 *node)
|
||||
{
|
||||
vp->x = (node[0x1A] & 0xFFFF) >> 4; // position is in 12.4 format
|
||||
vp->y = (node[0x1A] >> 16) >> 4;
|
||||
vp->width = (node[0x14] & 0xFFFF) >> 2; // size is in 14.2 format
|
||||
vp->height = (node[0x14] >> 16) >> 2;
|
||||
|
||||
vp->left = asin(GET_FLOAT(&node[0x0C]));
|
||||
vp->right = asin(GET_FLOAT(&node[0x10]));
|
||||
vp->up = asin(GET_FLOAT(&node[0x0E]));
|
||||
vp->down = asin(GET_FLOAT(&node[0x12]));
|
||||
|
||||
vp->left = CONVERT_TO_DEGREES(vp->left);
|
||||
vp->right = CONVERT_TO_DEGREES(vp->right);
|
||||
vp->up = CONVERT_TO_DEGREES(vp->up);
|
||||
vp->down = CONVERT_TO_DEGREES(vp->down);
|
||||
}
|
||||
|
||||
/*
|
||||
* get_light_data():
|
||||
*
|
||||
* Sets up a LIGHT structure based on ambient sun light. The sun vector
|
||||
* indicates the direction of the parallel sun light. It is specified in the
|
||||
* hardware coordinate system and must be applied before any matrices.
|
||||
*/
|
||||
|
||||
static void get_light_data(LIGHT* l, UINT32* node)
|
||||
{
|
||||
memset( l, 0, sizeof(LIGHT) );
|
||||
l->u = GET_FLOAT(&node[5]); // it seems X needs to be inverted
|
||||
l->v = GET_FLOAT(&node[6]);
|
||||
l->w = GET_FLOAT(&node[4]);
|
||||
|
||||
l->diffuse_intensity = GET_FLOAT(&node[7]);
|
||||
l->ambient_intensity = (UINT8)((node[0x24] >> 8) & 0xFF) / 256.0f;
|
||||
|
||||
LOG("model3.log", "sun light = (%f,%f,%f),%f,(%02X=%f)\n", l->u, l->v, l->w, l->diffuse_intensity, ((node[0x24] >> 8) & 0xFF), l->ambient_intensity);
|
||||
|
||||
l->color = 0xFFFFFFFF;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* draw_viewport():
|
||||
*
|
||||
* Traverses the main (scene descriptor) nodes and draws the ones with the
|
||||
* given viewport priority.
|
||||
*/
|
||||
|
||||
static void draw_viewport(UINT pri, UINT32 addr)
|
||||
{
|
||||
MATRIX m;
|
||||
VIEWPORT vp;
|
||||
LIGHT sun;
|
||||
UINT32 *node;
|
||||
UINT32 next_addr, ptr;
|
||||
|
||||
node = translate_scene_graph_address(addr);
|
||||
|
||||
/*
|
||||
* Recurse until the last node has been reached
|
||||
*/
|
||||
|
||||
next_addr = node[1];
|
||||
if (next_addr == 0) // culling RAM probably hasn't been set up yet...
|
||||
return;
|
||||
if (next_addr != 0x01000000)
|
||||
draw_viewport(pri, next_addr);
|
||||
|
||||
/*
|
||||
* Draw this node if the priority matches
|
||||
*/
|
||||
|
||||
if (pri == ((node[0] >> 3) & 3))
|
||||
{
|
||||
/*
|
||||
* Set up viewport and matrix table base
|
||||
*/
|
||||
|
||||
get_viewport_data(&vp, node);
|
||||
osd_renderer_set_viewport(&vp);
|
||||
matrix_base = (float *) translate_scene_graph_address(node[0x16]);
|
||||
lod_base = (float *) translate_scene_graph_address(node[0x17]);
|
||||
|
||||
/*
|
||||
* Lighting -- seems to work nice if applied before coordinate system
|
||||
* selection but I haven't done a thorough check.
|
||||
*/
|
||||
|
||||
get_light_data(&sun, node);
|
||||
sun.type = LIGHT_PARALLEL;
|
||||
osd_renderer_set_light( 0, &sun );
|
||||
|
||||
/*
|
||||
* Set coordinate system (matrix 0)
|
||||
*/
|
||||
|
||||
get_matrix(m, coord_matrix, 0);
|
||||
osd_renderer_set_coordinate_system(m);
|
||||
|
||||
/*
|
||||
* Process a block or list. So far, no other possibilities have been
|
||||
* seen here...
|
||||
*/
|
||||
|
||||
ptr = node[2];
|
||||
|
||||
switch ((ptr >> 24) & 0xFF)
|
||||
{
|
||||
case 0x00: // block
|
||||
draw_block(translate_scene_graph_address(node[2]));
|
||||
break;
|
||||
//case 0x04: // list
|
||||
// draw_list(translate_scene_graph_address(node[2]));
|
||||
// break;
|
||||
default: // unknown
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************/
|
||||
/* Frame Update */
|
||||
/******************************************************************/
|
||||
|
||||
/*
|
||||
* do_3d():
|
||||
*
|
||||
* Draw the complete Real3D frame.
|
||||
*/
|
||||
|
||||
static void do_3d(void)
|
||||
{
|
||||
INT i;
|
||||
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
osd_renderer_clear(0, 1); // clear Z-buffer
|
||||
osd_renderer_begin_3d_scene();
|
||||
draw_viewport(i, 0x00800000);
|
||||
osd_renderer_end_3d_scene();
|
||||
|
||||
LOG("model3.log", "GOT HERE\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* void set_color_offset(UINT32 reg);
|
||||
*
|
||||
* Sets color offset to the value specified by reg, and updates the
|
||||
* renderer status.
|
||||
*/
|
||||
|
||||
static void set_color_offset(UINT32 reg)
|
||||
{
|
||||
FLOAT32 r, g, b;
|
||||
|
||||
/*
|
||||
* Color offset is specified as a triplet of signed 8-bit values, one
|
||||
* for each color component. 0 is the default value, it doesn't modify
|
||||
* the output color. It's equal to disabling the color offset (though
|
||||
* some bit in the tilegen ports could be used for this).
|
||||
* 0x80 (-128) is the minimum value, and corresponds to complete black.
|
||||
* 0x7F (+127) is the maximum value, and corresponds to complete white.
|
||||
*/
|
||||
|
||||
r = (FLOAT32)((INT32)((INT8)(((INT32)reg >> 8) & 0xFF))) / 128.0f;
|
||||
g = (FLOAT32)((INT32)((INT8)(((INT32)reg >> 16) & 0xFF))) / 128.0f;
|
||||
b = (FLOAT32)((INT32)((INT8)(((INT32)reg >> 24) & 0xFF))) / 128.0f;
|
||||
|
||||
// osd_renderer_set_color_offset(r != 0.0f && g != 0.0f && b != 0.0f, r, g, b);
|
||||
}
|
||||
|
||||
/*
|
||||
* void render_frame(void);
|
||||
*
|
||||
* Draws the entire frame (all 3D and 2D graphics) and blits it.
|
||||
*/
|
||||
|
||||
void render_frame(void)
|
||||
{
|
||||
int i, j;
|
||||
UINT32 color_offset;
|
||||
LONGLONG counter_start, counter_end, counter_frequency;
|
||||
LOG("model3.log", "RENDER START\n");
|
||||
|
||||
QueryPerformanceFrequency((LARGE_INTEGER*)&counter_frequency);
|
||||
|
||||
tilegen_update();
|
||||
|
||||
{
|
||||
UINT32 *priority = tilegen_get_priority_buffer();
|
||||
|
||||
for (i=0; i < 4; i++)
|
||||
{
|
||||
int pitch;
|
||||
UINT8 *buffer;
|
||||
osd_renderer_get_priority_buffer(i, &buffer, &pitch);
|
||||
|
||||
for (j=0; j < 512; j++)
|
||||
{
|
||||
if (tilegen_is_priority_enabled())
|
||||
{
|
||||
buffer[j*pitch] = (priority[j] >> ((3-i) * 8)) & 0xff;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (i < 2) buffer[j*pitch] = 0xff;
|
||||
else buffer[j*pitch] = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
osd_renderer_free_priority_buffer(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
osd_renderer_clear(1, 1); // clear both the frame and Z-buffer
|
||||
|
||||
// set_color_offset(tilegen_read_32(0x44));
|
||||
|
||||
/*if (tilegen_is_layer_enabled(3))
|
||||
{
|
||||
UINT32 scroll = tilegen_get_layer_scroll_pos(3);
|
||||
color_offset = tilegen_get_layer_color_offset(3);
|
||||
osd_renderer_draw_layer(3, color_offset, scroll & 0xffff, scroll >> 16);
|
||||
}
|
||||
if (tilegen_is_layer_enabled(2))
|
||||
{
|
||||
UINT32 scroll = tilegen_get_layer_scroll_pos(2);
|
||||
color_offset = tilegen_get_layer_color_offset(2);
|
||||
osd_renderer_draw_layer(2, color_offset, scroll & 0xffff, scroll >> 16);
|
||||
}*/
|
||||
|
||||
for (i=3; i >= 0; i--)
|
||||
{
|
||||
if (tilegen_is_layer_enabled(i))
|
||||
{
|
||||
UINT32 scroll = tilegen_get_layer_scroll_pos(i);
|
||||
color_offset = tilegen_get_layer_color_offset(i);
|
||||
osd_renderer_draw_layer(i, color_offset, scroll & 0xffff, scroll >> 16, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
QueryPerformanceCounter((LARGE_INTEGER*)&counter_start);
|
||||
|
||||
do_3d();
|
||||
|
||||
QueryPerformanceCounter((LARGE_INTEGER*)&counter_end);
|
||||
|
||||
for (i=3; i >= 0; i--)
|
||||
{
|
||||
if (tilegen_is_layer_enabled(i))
|
||||
{
|
||||
UINT32 scroll = tilegen_get_layer_scroll_pos(i);
|
||||
color_offset = tilegen_get_layer_color_offset(i);
|
||||
osd_renderer_draw_layer(i, color_offset, scroll & 0xffff, scroll >> 16, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/*{
|
||||
double time = (double)(counter_end - counter_start) / (double)counter_frequency;
|
||||
printf("Rendering time: %f ms\n", time*1000.0);
|
||||
}*/
|
||||
|
||||
// set_color_offset(tilegen_read_32(0x40));
|
||||
|
||||
// osd_renderer_draw_layer(1);
|
||||
|
||||
/*if (tilegen_is_layer_enabled(1))
|
||||
{
|
||||
UINT32 scroll = tilegen_get_layer_scroll_pos(1);
|
||||
color_offset = tilegen_get_layer_color_offset(1);
|
||||
osd_renderer_draw_layer(1, color_offset, scroll & 0xffff, scroll >> 16);
|
||||
}
|
||||
if (tilegen_is_layer_enabled(0))
|
||||
{
|
||||
UINT32 scroll = tilegen_get_layer_scroll_pos(0);
|
||||
color_offset = tilegen_get_layer_color_offset(0);
|
||||
osd_renderer_draw_layer(0, color_offset, scroll & 0xffff, scroll >> 16);
|
||||
}*/
|
||||
|
||||
LOG("model3.log", "RENDER END\n");
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************/
|
||||
/* Initialization and Shutdown */
|
||||
/******************************************************************/
|
||||
|
||||
/*
|
||||
* void render_init(UINT8 *culling_ram_8e_ptr, UINT8 *culling_ram_8c_ptr,
|
||||
* UINT8 *polygon_ram_ptr, UINT8 *texture_ram_ptr,
|
||||
* UINT8 *vrom_ptr);
|
||||
*
|
||||
* Initializes the renderer by receiving the Real3D memory regions. Passes
|
||||
* the memory to the OSD renderer.
|
||||
*
|
||||
* Parameters:
|
||||
* culling_ram_8e_ptr = Pointer to Real3D culling RAM at 0x8E000000.
|
||||
* culling_ram_8c_ptr = Pointer to Real3D culling RAM at 0x8C000000.
|
||||
* polygon_ram_ptr = Pointer to Real3D polygon RAM.
|
||||
* texture_ram_ptr = Pointer to Real3D texture RAM.
|
||||
* vrom_ptr = Pointer to VROM.
|
||||
*/
|
||||
|
||||
void render_init(UINT8 *culling_ram_8e_ptr, UINT8 *culling_ram_8c_ptr,
|
||||
UINT8 *polygon_ram_ptr, UINT8 *texture_ram_ptr,
|
||||
UINT8 *vrom_ptr)
|
||||
{
|
||||
culling_ram_8e = culling_ram_8e_ptr;
|
||||
culling_ram_8c = culling_ram_8c_ptr;
|
||||
polygon_ram = polygon_ram_ptr;
|
||||
texture_ram = texture_ram_ptr;
|
||||
vrom = vrom_ptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* void render_shutdown(void);
|
||||
*
|
||||
* Shuts down the rendering engine.
|
||||
*/
|
||||
|
||||
void render_shutdown(void)
|
||||
{
|
||||
#if LOG_MODEL_ADDR
|
||||
// TEMP code to print out model list
|
||||
|
||||
FILE *fp;
|
||||
struct model_addr *l, *next;
|
||||
|
||||
fp = fopen("models.log", "w");
|
||||
if (fp == NULL)
|
||||
{
|
||||
printf("failed to write models.log\n");
|
||||
return;
|
||||
}
|
||||
|
||||
l = model_addr_list;
|
||||
while (l != NULL)
|
||||
{
|
||||
fprintf(fp, "addr = %08X\tnum_polys = %d\n", l->addr, l->num_polys);
|
||||
next = l->next;
|
||||
free(l);
|
||||
l = next;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
#endif
|
||||
}
|
86
core/render.h
Normal file
86
core/render.h
Normal file
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Sega Model 3 Emulator
|
||||
* Copyright (C) 2003 Bart Trzynadlowski, Ville Linde, Stefano Teso
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 (license.txt); if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* render.h
|
||||
*
|
||||
* Rendering engine header. OSD renderers will want to include this because
|
||||
* some important data structures are defined here.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_RENDER_H
|
||||
#define INCLUDED_RENDER_H
|
||||
|
||||
/******************************************************************/
|
||||
/* Data Structures */
|
||||
/******************************************************************/
|
||||
|
||||
/*
|
||||
* MATRIX
|
||||
*
|
||||
* A 4x4 matrix stored in column-major (OpenGL) format.
|
||||
*/
|
||||
|
||||
typedef float MATRIX [4*4];
|
||||
|
||||
/*
|
||||
* VIEWPORT
|
||||
*
|
||||
* Viewport and projection data. The field-of-view angles are in degrees. The
|
||||
* coordinates and size of the viewport are truncated from Model 3's fixed-
|
||||
* point formats to integers.
|
||||
*
|
||||
* The viewport coordinate system maps directly to the Model 3's physical
|
||||
* resolution and its origin is at the bottom-left corner of the screen.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT x, y, width, height; // viewport position and size.
|
||||
double up, down, left, right; // FOV angles from center
|
||||
} VIEWPORT;
|
||||
|
||||
/*
|
||||
* LIGHT
|
||||
*/
|
||||
|
||||
enum {
|
||||
LIGHT_PARALLEL,
|
||||
LIGHT_POSITIONAL,
|
||||
LIGHT_SPOT
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT type;
|
||||
float u,v,w; // Direction vector
|
||||
float x,y,z; // Position for point light
|
||||
float diffuse_intensity;
|
||||
float ambient_intensity;
|
||||
UINT32 color;
|
||||
} LIGHT;
|
||||
|
||||
/******************************************************************/
|
||||
/* Functions */
|
||||
/******************************************************************/
|
||||
|
||||
extern void render_frame(void);
|
||||
extern void render_init(UINT8 *, UINT8 *, UINT8 *, UINT8 *, UINT8 *);
|
||||
extern void render_shutdown(void);
|
||||
|
||||
#endif // INCLUDED_RENDER_H
|
604
core/romparse.c
Normal file
604
core/romparse.c
Normal file
|
@ -0,0 +1,604 @@
|
|||
#include "model3.h"
|
||||
#include "expat.h"
|
||||
|
||||
enum
|
||||
{
|
||||
ELEMENT_NONE = 1,
|
||||
ELEMENT_GAMELIST,
|
||||
ELEMENT_GAME,
|
||||
ELEMENT_DESCRIPTION,
|
||||
ELEMENT_YEAR,
|
||||
ELEMENT_MANUFACTURER,
|
||||
ELEMENT_STEP,
|
||||
ELEMENT_CROMSIZE,
|
||||
ELEMENT_ROM,
|
||||
ELEMENT_PATCH,
|
||||
ELEMENT_BRIDGE,
|
||||
ELEMENT_INPUT,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
ATTR_ROM_TYPE = 1,
|
||||
ATTR_ROM_NAME,
|
||||
ATTR_ROM_SIZE,
|
||||
ATTR_ROM_CRC,
|
||||
ATTR_ROM_SHA1,
|
||||
ATTR_GAME_NAME,
|
||||
ATTR_GAME_PARENT,
|
||||
ATTR_PATCH_SIZE,
|
||||
ATTR_PATCH_ADDRESS,
|
||||
ATTR_PATCH_DATA,
|
||||
ATTR_INPUT_TYPE,
|
||||
ATTR_INPUT_CENTER,
|
||||
ATTR_INPUT_MAPPING,
|
||||
};
|
||||
|
||||
static STRING_ID element_id[] =
|
||||
{
|
||||
{ "gamelist", ELEMENT_GAMELIST },
|
||||
{ "game", ELEMENT_GAME },
|
||||
{ "description", ELEMENT_DESCRIPTION },
|
||||
{ "year", ELEMENT_YEAR },
|
||||
{ "manufacturer", ELEMENT_MANUFACTURER },
|
||||
{ "step", ELEMENT_STEP },
|
||||
{ "cromsize", ELEMENT_CROMSIZE },
|
||||
{ "rom", ELEMENT_ROM },
|
||||
{ "patch", ELEMENT_PATCH },
|
||||
{ "bridge", ELEMENT_BRIDGE },
|
||||
{ "input", ELEMENT_INPUT },
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
static STRING_ID rom_attr_id[] =
|
||||
{
|
||||
{ "type", ATTR_ROM_TYPE },
|
||||
{ "name", ATTR_ROM_NAME },
|
||||
{ "size", ATTR_ROM_SIZE },
|
||||
{ "crc", ATTR_ROM_CRC },
|
||||
{ "sha1", ATTR_ROM_SHA1 },
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
static STRING_ID game_attr_id[] =
|
||||
{
|
||||
{ "name", ATTR_GAME_NAME },
|
||||
{ "parent", ATTR_GAME_PARENT },
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
static STRING_ID patch_attr_id[] =
|
||||
{
|
||||
{ "size", ATTR_PATCH_SIZE },
|
||||
{ "address", ATTR_PATCH_ADDRESS },
|
||||
{ "data", ATTR_PATCH_DATA },
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
static STRING_ID input_attr_id[] =
|
||||
{
|
||||
{ "type", ATTR_INPUT_TYPE },
|
||||
{ "center", ATTR_INPUT_CENTER },
|
||||
{ "mapping", ATTR_INPUT_MAPPING },
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
static STRING_ID step_id[] =
|
||||
{
|
||||
{ "1.0", 0x10 },
|
||||
{ "1.5", 0x15 },
|
||||
{ "2.0", 0x20 },
|
||||
{ "2.1", 0x21 },
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
static STRING_ID rom_id[] =
|
||||
{
|
||||
{ "prog0", ROMTYPE_PROG0 },
|
||||
{ "prog1", ROMTYPE_PROG1 },
|
||||
{ "prog2", ROMTYPE_PROG2 },
|
||||
{ "prog3", ROMTYPE_PROG3 },
|
||||
{ "crom00", ROMTYPE_CROM00 },
|
||||
{ "crom01", ROMTYPE_CROM01 },
|
||||
{ "crom02", ROMTYPE_CROM02 },
|
||||
{ "crom03", ROMTYPE_CROM03 },
|
||||
{ "crom10", ROMTYPE_CROM10 },
|
||||
{ "crom11", ROMTYPE_CROM11 },
|
||||
{ "crom12", ROMTYPE_CROM12 },
|
||||
{ "crom13", ROMTYPE_CROM13 },
|
||||
{ "crom20", ROMTYPE_CROM20 },
|
||||
{ "crom21", ROMTYPE_CROM21 },
|
||||
{ "crom22", ROMTYPE_CROM22 },
|
||||
{ "crom23", ROMTYPE_CROM23 },
|
||||
{ "crom30", ROMTYPE_CROM30 },
|
||||
{ "crom31", ROMTYPE_CROM31 },
|
||||
{ "crom32", ROMTYPE_CROM32 },
|
||||
{ "crom33", ROMTYPE_CROM33 },
|
||||
{ "vrom00", ROMTYPE_VROM00 },
|
||||
{ "vrom01", ROMTYPE_VROM01 },
|
||||
{ "vrom02", ROMTYPE_VROM02 },
|
||||
{ "vrom03", ROMTYPE_VROM03 },
|
||||
{ "vrom04", ROMTYPE_VROM04 },
|
||||
{ "vrom05", ROMTYPE_VROM05 },
|
||||
{ "vrom06", ROMTYPE_VROM06 },
|
||||
{ "vrom07", ROMTYPE_VROM07 },
|
||||
{ "vrom10", ROMTYPE_VROM10 },
|
||||
{ "vrom11", ROMTYPE_VROM11 },
|
||||
{ "vrom12", ROMTYPE_VROM12 },
|
||||
{ "vrom13", ROMTYPE_VROM13 },
|
||||
{ "vrom14", ROMTYPE_VROM14 },
|
||||
{ "vrom15", ROMTYPE_VROM15 },
|
||||
{ "vrom16", ROMTYPE_VROM16 },
|
||||
{ "vrom17", ROMTYPE_VROM17 },
|
||||
{ "sprog", ROMTYPE_SPROG },
|
||||
{ "srom0", ROMTYPE_SROM0 },
|
||||
{ "srom1", ROMTYPE_SROM1 },
|
||||
{ "srom2", ROMTYPE_SROM2 },
|
||||
{ "srom3", ROMTYPE_SROM3 },
|
||||
{ "dsbprog", ROMTYPE_DSBPROG },
|
||||
{ "dsbrom0", ROMTYPE_DSBROM0 },
|
||||
{ "dsbrom1", ROMTYPE_DSBROM1 },
|
||||
{ "dsbrom2", ROMTYPE_DSBROM2 },
|
||||
{ "dsbrom3", ROMTYPE_DSBROM3 },
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
#define INPUT_TYPE_BUTTON 0x10000
|
||||
#define INPUT_TYPE_ANALOG 0x20000
|
||||
|
||||
static STRING_ID input_id[] =
|
||||
{
|
||||
{ "button01", INPUT_TYPE_BUTTON | 0 },
|
||||
{ "button02", INPUT_TYPE_BUTTON | 1 },
|
||||
{ "button03", INPUT_TYPE_BUTTON | 2 },
|
||||
{ "button04", INPUT_TYPE_BUTTON | 3 },
|
||||
{ "button05", INPUT_TYPE_BUTTON | 4 },
|
||||
{ "button06", INPUT_TYPE_BUTTON | 5 },
|
||||
{ "button07", INPUT_TYPE_BUTTON | 6 },
|
||||
{ "button08", INPUT_TYPE_BUTTON | 7 },
|
||||
{ "button11", INPUT_TYPE_BUTTON | 8 },
|
||||
{ "button12", INPUT_TYPE_BUTTON | 9 },
|
||||
{ "button13", INPUT_TYPE_BUTTON | 10 },
|
||||
{ "button14", INPUT_TYPE_BUTTON | 11 },
|
||||
{ "button15", INPUT_TYPE_BUTTON | 12 },
|
||||
{ "button16", INPUT_TYPE_BUTTON | 13 },
|
||||
{ "button17", INPUT_TYPE_BUTTON | 14 },
|
||||
{ "button18", INPUT_TYPE_BUTTON | 15 },
|
||||
{ "analog1", INPUT_TYPE_ANALOG | 0 },
|
||||
{ "analog2", INPUT_TYPE_ANALOG | 1 },
|
||||
{ "analog3", INPUT_TYPE_ANALOG | 2 },
|
||||
{ "analog4", INPUT_TYPE_ANALOG | 3 },
|
||||
{ "analog5", INPUT_TYPE_ANALOG | 4 },
|
||||
{ "analog6", INPUT_TYPE_ANALOG | 5 },
|
||||
{ "analog7", INPUT_TYPE_ANALOG | 6 },
|
||||
{ "analog8", INPUT_TYPE_ANALOG | 7 },
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
static STRING_ID input_mapping_id[] =
|
||||
{
|
||||
{ "p1_button_1", P1_BUTTON_1 },
|
||||
{ "p1_button_2", P1_BUTTON_2 },
|
||||
{ "p1_button_3", P1_BUTTON_3 },
|
||||
{ "p1_button_4", P1_BUTTON_4 },
|
||||
{ "p1_button_5", P1_BUTTON_5 },
|
||||
{ "p1_button_6", P1_BUTTON_6 },
|
||||
{ "p1_button_7", P1_BUTTON_7 },
|
||||
{ "p1_button_8", P1_BUTTON_8 },
|
||||
{ "p2_button_1", P2_BUTTON_1 },
|
||||
{ "p2_button_2", P2_BUTTON_2 },
|
||||
{ "p2_button_3", P2_BUTTON_3 },
|
||||
{ "p2_button_4", P2_BUTTON_4 },
|
||||
{ "p2_button_5", P2_BUTTON_5 },
|
||||
{ "p2_button_6", P2_BUTTON_6 },
|
||||
{ "p2_button_7", P2_BUTTON_7 },
|
||||
{ "p2_button_8", P2_BUTTON_8 },
|
||||
{ "analog_axis_1", ANALOG_AXIS_1 },
|
||||
{ "analog_axis_2", ANALOG_AXIS_2 },
|
||||
{ "analog_axis_3", ANALOG_AXIS_3 },
|
||||
{ "analog_axis_4", ANALOG_AXIS_4 },
|
||||
{ "analog_axis_5", ANALOG_AXIS_5 },
|
||||
{ "analog_axis_6", ANALOG_AXIS_6 },
|
||||
{ "analog_axis_7", ANALOG_AXIS_7 },
|
||||
{ "analog_axis_8", ANALOG_AXIS_8 },
|
||||
{ "p1_joystick_up", P1_JOYSTICK_UP },
|
||||
{ "p1_joystick_down", P1_JOYSTICK_DOWN },
|
||||
{ "p1_joystick_left", P1_JOYSTICK_LEFT },
|
||||
{ "p1_joystick_right", P1_JOYSTICK_RIGHT },
|
||||
{ "p2_joystick_up", P2_JOYSTICK_UP },
|
||||
{ "p2_joystick_down", P2_JOYSTICK_DOWN },
|
||||
{ "p2_joystick_left", P2_JOYSTICK_LEFT },
|
||||
{ "p2_joystick_right", P2_JOYSTICK_RIGHT },
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
|
||||
|
||||
static UINT8 *romlist;
|
||||
|
||||
static ROMSET *romset;
|
||||
|
||||
static int current_attr;
|
||||
static int current_element;
|
||||
|
||||
static int current_rom;
|
||||
static int current_romset;
|
||||
static int current_patch;
|
||||
static int current_input;
|
||||
|
||||
|
||||
|
||||
static void XMLCALL element_start(void *data, const char *el, const char **attr)
|
||||
{
|
||||
int element = get_string_id(el, element_id);
|
||||
|
||||
if (element < 0)
|
||||
{
|
||||
message(0, "Unknown element %s while parsing XML file\n", el);
|
||||
}
|
||||
else
|
||||
{
|
||||
current_element = element;
|
||||
|
||||
switch (element)
|
||||
{
|
||||
case ELEMENT_ROM:
|
||||
{
|
||||
int i=0;
|
||||
|
||||
// handle ROM types
|
||||
while (attr[i] != NULL)
|
||||
{
|
||||
int id = get_string_id(attr[i], rom_attr_id);
|
||||
|
||||
if (id >= 0)
|
||||
{
|
||||
current_attr = id;
|
||||
}
|
||||
else
|
||||
{
|
||||
// not a type
|
||||
switch (current_attr)
|
||||
{
|
||||
case ATTR_ROM_TYPE:
|
||||
{
|
||||
int romtype = get_string_id(attr[i], rom_id);
|
||||
romset[current_romset].rom[current_rom].type = romtype;
|
||||
break;
|
||||
}
|
||||
case ATTR_ROM_NAME:
|
||||
{
|
||||
strcpy(romset[current_romset].rom[current_rom].name, attr[i]);
|
||||
break;
|
||||
}
|
||||
case ATTR_ROM_SIZE:
|
||||
{
|
||||
int romsize;
|
||||
sscanf(attr[i], "%d", &romsize);
|
||||
romset[current_romset].rom[current_rom].size = romsize;
|
||||
break;
|
||||
}
|
||||
case ATTR_ROM_CRC:
|
||||
{
|
||||
UINT32 romcrc;
|
||||
sscanf(attr[i], "%X", &romcrc);
|
||||
romset[current_romset].rom[current_rom].crc32 = romcrc;
|
||||
break;
|
||||
}
|
||||
case ATTR_ROM_SHA1:
|
||||
{
|
||||
// not handled
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
i++;
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
case ELEMENT_GAME:
|
||||
{
|
||||
int i=0;
|
||||
|
||||
while (attr[i] != NULL)
|
||||
{
|
||||
int id = get_string_id(attr[i], game_attr_id);
|
||||
|
||||
if (id >= 0)
|
||||
{
|
||||
current_attr = id;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (current_attr)
|
||||
{
|
||||
case ATTR_GAME_NAME:
|
||||
{
|
||||
strcpy(romset[current_romset].game, attr[i]);
|
||||
break;
|
||||
}
|
||||
case ATTR_GAME_PARENT:
|
||||
{
|
||||
strcpy(romset[current_romset].parent, attr[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
i++;
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
case ELEMENT_PATCH:
|
||||
{
|
||||
int i=0;
|
||||
|
||||
while (attr[i] != NULL)
|
||||
{
|
||||
int id = get_string_id(attr[i], patch_attr_id);
|
||||
|
||||
if (id >= 0)
|
||||
{
|
||||
current_attr = id;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (current_attr)
|
||||
{
|
||||
case ATTR_PATCH_SIZE:
|
||||
{
|
||||
int patch_size;
|
||||
sscanf(attr[i], "%d", &patch_size);
|
||||
romset[current_romset].patch[current_patch].size = patch_size;
|
||||
break;
|
||||
}
|
||||
case ATTR_PATCH_ADDRESS:
|
||||
{
|
||||
UINT32 address;
|
||||
sscanf(attr[i], "%X", &address);
|
||||
romset[current_romset].patch[current_patch].address = address;
|
||||
break;
|
||||
}
|
||||
case ATTR_PATCH_DATA:
|
||||
{
|
||||
UINT32 data;
|
||||
sscanf(attr[i], "%X", &data);
|
||||
romset[current_romset].patch[current_patch].data = data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
i++;
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
case ELEMENT_INPUT:
|
||||
{
|
||||
int i=0;
|
||||
|
||||
while (attr[i] != NULL)
|
||||
{
|
||||
int id = get_string_id(attr[i], input_attr_id);
|
||||
|
||||
if (id >= 0)
|
||||
{
|
||||
current_attr = id;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (current_attr)
|
||||
{
|
||||
case ATTR_INPUT_TYPE:
|
||||
{
|
||||
current_input = get_string_id(attr[i], input_id);
|
||||
|
||||
if (current_input & INPUT_TYPE_BUTTON)
|
||||
{
|
||||
int button = current_input & 0xffff;
|
||||
int set = (button / 8) & 1;
|
||||
int bit = 1 << (button % 8);
|
||||
romset[current_romset].controls.button[button].enabled = 1;
|
||||
romset[current_romset].controls.button[button].control_set = set;
|
||||
romset[current_romset].controls.button[button].control_bit = bit;
|
||||
}
|
||||
else if (current_input & INPUT_TYPE_ANALOG)
|
||||
{
|
||||
int axis = current_input & 0xffff;
|
||||
romset[current_romset].controls.analog_axis[axis].enabled = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ATTR_INPUT_CENTER:
|
||||
{
|
||||
if (current_input & INPUT_TYPE_ANALOG)
|
||||
{
|
||||
int axis = current_input & 0xffff;
|
||||
int center;
|
||||
sscanf(attr[i], "%d", ¢er);
|
||||
romset[current_romset].controls.analog_axis[axis].center = center;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ATTR_INPUT_MAPPING:
|
||||
{
|
||||
int mapping = get_string_id(attr[i], input_mapping_id);
|
||||
if (current_input & INPUT_TYPE_BUTTON)
|
||||
{
|
||||
int button = current_input & 0xffff;
|
||||
romset[current_romset].controls.button[button].mapping = mapping;
|
||||
}
|
||||
else if (current_input & INPUT_TYPE_ANALOG)
|
||||
{
|
||||
int axis = current_input & 0xffff;
|
||||
romset[current_romset].controls.analog_axis[axis].mapping = mapping;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
i++;
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void XMLCALL element_end(void *data, const char *el)
|
||||
{
|
||||
int element = get_string_id(el, element_id);
|
||||
|
||||
if (element < 0)
|
||||
{
|
||||
message(0, "Unknown element %s while parsing XML\n", el);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (element)
|
||||
{
|
||||
case ELEMENT_ROM:
|
||||
{
|
||||
current_rom++;
|
||||
current_element = ELEMENT_GAMELIST;
|
||||
break;
|
||||
}
|
||||
case ELEMENT_GAME:
|
||||
{
|
||||
romset[current_romset].num_patches = current_patch;
|
||||
current_romset++;
|
||||
current_rom = 0;
|
||||
current_patch = 0;
|
||||
current_element = ELEMENT_GAMELIST;
|
||||
break;
|
||||
}
|
||||
case ELEMENT_DESCRIPTION:
|
||||
case ELEMENT_YEAR:
|
||||
case ELEMENT_MANUFACTURER:
|
||||
case ELEMENT_STEP:
|
||||
case ELEMENT_BRIDGE:
|
||||
case ELEMENT_CROMSIZE:
|
||||
{
|
||||
current_element = ELEMENT_GAMELIST;
|
||||
break;
|
||||
}
|
||||
case ELEMENT_PATCH:
|
||||
{
|
||||
current_patch++;
|
||||
current_element = ELEMENT_GAMELIST;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void XMLCALL character_data(void *data, const char *s, int len)
|
||||
{
|
||||
char temp[2000];
|
||||
memcpy(temp, s, len);
|
||||
temp[len] = 0;
|
||||
|
||||
switch (current_element)
|
||||
{
|
||||
case ELEMENT_DESCRIPTION:
|
||||
{
|
||||
strcpy(romset[current_romset].title, temp);
|
||||
break;
|
||||
}
|
||||
case ELEMENT_YEAR:
|
||||
{
|
||||
int year;
|
||||
sscanf(temp, "%d", &year);
|
||||
romset[current_romset].year = year;
|
||||
break;
|
||||
}
|
||||
case ELEMENT_MANUFACTURER:
|
||||
{
|
||||
strcpy(romset[current_romset].manufacturer, temp);
|
||||
break;
|
||||
}
|
||||
case ELEMENT_STEP:
|
||||
{
|
||||
int step = get_string_id(temp, step_id);
|
||||
|
||||
if (step >= 0)
|
||||
{
|
||||
romset[current_romset].step = step;
|
||||
}
|
||||
else
|
||||
{
|
||||
message(0, "Invalid step %s while parsing XML file\n", temp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ELEMENT_BRIDGE:
|
||||
{
|
||||
if (_stricmp(temp, "mpc106") == 0)
|
||||
{
|
||||
romset[current_romset].bridge = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
message(0, "Unknown bridge %s while parsing XML file\n", temp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ELEMENT_CROMSIZE:
|
||||
{
|
||||
if (_stricmp(temp, "64M") == 0)
|
||||
{
|
||||
romset[current_romset].cromsize = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
message(0, "Unknown cromsize %s while parsing XML file\n", temp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int parse_romlist(char *romlist_name, ROMSET *_romset)
|
||||
{
|
||||
XML_Parser parser;
|
||||
|
||||
int length;
|
||||
FILE *file;
|
||||
|
||||
file = open_file(FILE_READ|FILE_BINARY, "%s", romlist_name);
|
||||
if (file == NULL)
|
||||
{
|
||||
message(0, "Couldn't open %s", romlist_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
length = (int)get_open_file_size(file);
|
||||
|
||||
romlist = (UINT8*)malloc(length);
|
||||
|
||||
if (!read_from_file(file, romlist, length))
|
||||
{
|
||||
message(0, "I/O error while reading %s", romlist_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
close_file(file);
|
||||
|
||||
romset = _romset;
|
||||
|
||||
// parse the XML file
|
||||
parser = XML_ParserCreate(NULL);
|
||||
|
||||
XML_SetElementHandler(parser, element_start, element_end);
|
||||
XML_SetCharacterDataHandler(parser, character_data);
|
||||
|
||||
if (XML_Parse(parser, romlist, length, 1) != XML_STATUS_OK)
|
||||
{
|
||||
message(0, "Error while parsing the XML file %s", romlist_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
XML_ParserFree(parser);
|
||||
return current_romset;
|
||||
}
|
179
core/rtc.c
Normal file
179
core/rtc.c
Normal file
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
* Sega Model 3 Emulator
|
||||
* Copyright (C) 2003 Bart Trzynadlowski, Ville Linde, Stefano Teso
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 (license.txt); if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* rtc.c
|
||||
*
|
||||
* Real-Time Clock (72421) emulation.
|
||||
*/
|
||||
|
||||
#include "model3.h"
|
||||
#include <time.h>
|
||||
|
||||
static UINT8 rtc_step = 0;
|
||||
static UINT8 rtc_reg[0x10]; /* 4-bit wide */
|
||||
|
||||
/******************************************************************/
|
||||
/* Interface */
|
||||
/******************************************************************/
|
||||
|
||||
void rtc_init(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void rtc_shutdown(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void rtc_reset(void)
|
||||
{
|
||||
rtc_step = 0;
|
||||
|
||||
memset(rtc_reg, 0, 0x10);
|
||||
}
|
||||
|
||||
void rtc_step_frame(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* void rtc_save_state(FILE *fp);
|
||||
*
|
||||
* Saves the state of the real-time clock to a file.
|
||||
*
|
||||
* Parameters:
|
||||
* fp = File to save to.
|
||||
*/
|
||||
|
||||
void rtc_save_state(FILE *fp)
|
||||
{
|
||||
// do nothing yet because this file isn't complete or used, it appears
|
||||
}
|
||||
|
||||
/*
|
||||
* void rtc_load_state(FILE *fp);
|
||||
*
|
||||
* Loads the state of the real-time clock from a file.
|
||||
*
|
||||
* Parameters:
|
||||
* fp = File to load from.
|
||||
*/
|
||||
|
||||
void rtc_load_state(FILE *fp)
|
||||
{
|
||||
// do nothing yet because this file isn't complete or used, it appears
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
/* Access */
|
||||
/******************************************************************/
|
||||
|
||||
static UINT8 get_register(int reg)
|
||||
{
|
||||
time_t current_time;
|
||||
struct tm* tms;
|
||||
|
||||
time( ¤t_time );
|
||||
tms = localtime( ¤t_time );
|
||||
|
||||
switch(reg)
|
||||
{
|
||||
case 0: // 1-second digit
|
||||
return (tms->tm_sec % 10) & 0xF;
|
||||
break;
|
||||
case 1: // 10-seconds digit
|
||||
return (tms->tm_sec / 10) & 0x7;
|
||||
break;
|
||||
case 2: // 1-minute digit
|
||||
return (tms->tm_min % 10) & 0xF;
|
||||
break;
|
||||
case 3: // 10-minute digit
|
||||
return (tms->tm_min / 10) & 0x7;
|
||||
break;
|
||||
case 4: // 1-hour digit
|
||||
return (tms->tm_hour % 10) & 0xF;
|
||||
break;
|
||||
case 5: // 10-hours digit
|
||||
return (tms->tm_hour / 10) & 0x7;
|
||||
break;
|
||||
case 6: // 1-day digit (days in month)
|
||||
return (tms->tm_mday % 10) & 0xF;
|
||||
break;
|
||||
case 7: // 10-days digit
|
||||
return (tms->tm_mday / 10) & 0x3;
|
||||
break;
|
||||
case 8: // 1-month digit
|
||||
return ((tms->tm_mon + 1) % 10) & 0xF;
|
||||
break;
|
||||
case 9: // 10-months digit
|
||||
return ((tms->tm_mon + 1) / 10) & 0x1;
|
||||
break;
|
||||
case 10: // 1-year digit
|
||||
return (tms->tm_year % 10) & 0xF;
|
||||
break;
|
||||
case 11: // 10-years digit
|
||||
return ((tms->tm_year % 100) / 10) & 0xF;
|
||||
break;
|
||||
case 12: // day of the week
|
||||
return tms->tm_wday & 0x7;
|
||||
break;
|
||||
case 13:
|
||||
return 0;
|
||||
break;
|
||||
case 14:
|
||||
return 0;
|
||||
break;
|
||||
case 15:
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
error("ERROR: invalid RTC access reg%X\n", reg);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
UINT8 rtc_read_8(UINT32 a)
|
||||
{
|
||||
int address = (a >> 2) & 0xF;
|
||||
|
||||
//message(0, "RTC: read %08X, %08X", address,ppc_get_reg(PPC_REG_PC));
|
||||
|
||||
return get_register( address );
|
||||
}
|
||||
|
||||
UINT32 rtc_read_32(UINT32 a)
|
||||
{
|
||||
int address = (a >> 2) & 0xF;
|
||||
|
||||
//message(0, "RTC: read %08X, %08X", address,ppc_get_reg(PPC_REG_PC));
|
||||
|
||||
return get_register( address) << 24 | 0x30000; // Bits 0x30000 set to get battery voltage check to pass
|
||||
}
|
||||
|
||||
void rtc_write(UINT32 a, UINT8 d)
|
||||
{
|
||||
a = (a >> 2) & 0xF;
|
||||
//message(0, "RTC: write %08X = %X", a, d);
|
||||
|
||||
a &= 0xF;
|
||||
|
||||
rtc_reg[a] = d;
|
||||
}
|
41
core/rtc.h
Normal file
41
core/rtc.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Sega Model 3 Emulator
|
||||
* Copyright (C) 2003 Bart Trzynadlowski, Ville Linde, Stefano Teso
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 (license.txt); if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* rtc.h
|
||||
*
|
||||
* Real-Time Clock (72421) header.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_RTC_H
|
||||
#define INCLUDED_RTC_H
|
||||
|
||||
extern void rtc_init(void);
|
||||
extern void rtc_shutdown(void);
|
||||
extern void rtc_reset(void);
|
||||
extern void rtc_step_frame(void);
|
||||
|
||||
extern void rtc_save_state(FILE *);
|
||||
extern void rtc_load_state(FILE *);
|
||||
|
||||
extern UINT8 rtc_read_8(UINT32 a);
|
||||
extern UINT32 rtc_read_32(UINT32 a);
|
||||
extern void rtc_write(UINT32 a, UINT8 d);
|
||||
|
||||
#endif // INCLUDED_RTC_H
|
||||
|
367
core/scsi.c
Normal file
367
core/scsi.c
Normal file
|
@ -0,0 +1,367 @@
|
|||
/*
|
||||
* Sega Model 3 Emulator
|
||||
* Copyright (C) 2003 Bart Trzynadlowski, Ville Linde, Stefano Teso
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 (license.txt); if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* scsi.c
|
||||
*
|
||||
* NCR 53C810 SCSI controller emulation.
|
||||
*
|
||||
* Multi-byte data written is assumed to be little endian and is therefore
|
||||
* reversed because the PowerPC operates in big endian mode in the Model 3.
|
||||
*
|
||||
* NOTE: scsi_run() is often called with an argument of 100. This is
|
||||
* actually incorrect. It should run until an interrupt condition. A count of
|
||||
* 100 is used as a runaway counter to prevent lock-ups.
|
||||
*/
|
||||
|
||||
#include "model3.h"
|
||||
|
||||
/*
|
||||
* Read/Write Handlers
|
||||
*
|
||||
* These are used as an interface to the rest of the system.
|
||||
*/
|
||||
|
||||
static UINT8 (*read_8)(UINT32);
|
||||
static UINT16 (*read_16)(UINT32);
|
||||
static UINT32 (*read_32)(UINT32);
|
||||
static void (*write_8)(UINT32, UINT8);
|
||||
static void (*write_16)(UINT32, UINT16);
|
||||
static void (*write_32)(UINT32, UINT32);
|
||||
|
||||
/*
|
||||
* 53C810 Context
|
||||
*
|
||||
* Offsets within the register array correspond to register addresses but the
|
||||
* endianness in which they are stored is little endian. Macros are provided
|
||||
* to access them.
|
||||
*/
|
||||
|
||||
#define REG8(r) scsi_regs[r]
|
||||
#define REG16(r) *((UINT16 *) &scsi_regs[r])
|
||||
#define REG32(r) *((UINT32 *) &scsi_regs[r])
|
||||
|
||||
static UINT8 scsi_regs[0x60];
|
||||
static BOOL scripts_exec; // true if SCRIPTS code should be executed
|
||||
|
||||
/*
|
||||
* SCRIPTS Emulation
|
||||
*/
|
||||
|
||||
#include "scsiop.h"
|
||||
|
||||
/*
|
||||
* UINT8 scsi_read_8(UINT32 addr);
|
||||
*
|
||||
* Reads from the SCSI register space.
|
||||
*
|
||||
* Parameters:
|
||||
* addr = Register address (only lower 8 bits matter.)
|
||||
*
|
||||
* Returns:
|
||||
* Returns data from the register read.
|
||||
*/
|
||||
|
||||
UINT8 scsi_read_8(UINT32 addr)
|
||||
{
|
||||
UINT8 reg;
|
||||
|
||||
addr &= 0xFF;
|
||||
//if (addr > 0x5F)
|
||||
// error("%08X: SCSI invalid read from %02X", ppc_get_reg(PPC_REG_PC), addr);
|
||||
|
||||
reg = REG8(addr);
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case 0x14:
|
||||
REG8(addr) &= 0xFE; // clear DIP
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return reg;
|
||||
}
|
||||
|
||||
/*
|
||||
* UINT32 scsi_read_32(UINT32 addr);
|
||||
*
|
||||
* Reads from the SCSI register space.
|
||||
*
|
||||
* Parameters:
|
||||
* addr = Register address (only lower 8 bits matter.)
|
||||
*
|
||||
* Returns:
|
||||
* Returns data from the register read.
|
||||
*/
|
||||
|
||||
UINT32 scsi_read_32(UINT32 addr)
|
||||
{
|
||||
UINT32 reg;
|
||||
|
||||
// error("SCSI 32-bit read from %08X", addr);
|
||||
|
||||
addr &= 0xFF;
|
||||
if (addr > 0x5F)
|
||||
error("%08X: SCSI invalid read from %02X", ppc_get_pc(), addr);
|
||||
|
||||
reg = REG32(addr);
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case 0x14:
|
||||
error("%08X: SCSI 32-bit read from reg %02X -- don't know what to do", ppc_get_pc(), addr);
|
||||
break;
|
||||
default:
|
||||
// NOTE: some registers might have to be handled to clear certain
|
||||
// bits
|
||||
break;
|
||||
}
|
||||
|
||||
return reg;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* void scsi_write_8(UINT32 addr, UINT8 data);
|
||||
*
|
||||
* Writes a byte to the SCSI register space.
|
||||
*
|
||||
* Parameters:
|
||||
* addr = Register address (only lower 8 bits matter.)
|
||||
* data = Data to write.
|
||||
*/
|
||||
|
||||
void scsi_write_8(UINT32 addr, UINT8 data)
|
||||
{
|
||||
addr &= 0xFF;
|
||||
if (addr > 0x5F)
|
||||
error("%08X: SCSI invalid write8 to %02X", ppc_get_pc(), addr);
|
||||
|
||||
//message(0, "%08X: SCSI %02X = %02X", ppc_get_pc(), addr, data);
|
||||
|
||||
REG8(addr) = data;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case 0x3B: // DCNTL: DMA Control
|
||||
|
||||
/*
|
||||
* 7 6 5 4 3 2 1 0
|
||||
* +------+------+------+------+------+------+------+------+
|
||||
* | CLSE | PFF | PFEN | SSM | IRQM | STD | IRQD | COM |
|
||||
* +------+------+------+------+------+------+------+------+
|
||||
*
|
||||
* CLSE Cache Line Size Enable
|
||||
*
|
||||
* PFF Prefetch Flush
|
||||
*
|
||||
* PFEN Prefetch Enable
|
||||
*
|
||||
* SSM Single Step Mode
|
||||
*
|
||||
* Setting this bit causes the SCSI to stop after executing
|
||||
* each SCRIPTS instruction and generate a single step
|
||||
* interrupt. To restart the SCSI after the interrupt has
|
||||
* been generated, read ISTAT and DSTAT to recognize and
|
||||
* clear the interrupt, then set STD bit in this register
|
||||
* to resume execution.
|
||||
*
|
||||
* IRQM IRQ Mode
|
||||
*
|
||||
* STD Start DMA Operation
|
||||
*
|
||||
* The SCSI fetches an instruction and executes it when this
|
||||
* bit is set. It is required when the SCSI is in one of the
|
||||
* following modes:
|
||||
*
|
||||
* - Manual start mode: Bit 0 in the DMODE register is
|
||||
* set.
|
||||
* - Single step mode: Bit 4 in the DCNTL register is
|
||||
* set.
|
||||
*
|
||||
* When in manual mode, setting this bit starts instruction
|
||||
* execution -- it remains set until an interrupt occurs. In
|
||||
* single step mode, it restarts execution after an
|
||||
* interrupt.
|
||||
*
|
||||
* IRQD IRQ Disable
|
||||
*
|
||||
* COM LSI53C700 Family Compatibility
|
||||
*/
|
||||
|
||||
/*
|
||||
* Single-stepping is checked for in scsi_run() (the number of
|
||||
* instructions to execute will be reduced to 1 there.)
|
||||
*/
|
||||
|
||||
if ((REG8(0x38) & 0x01) || // MAN=1, start SCRIPTS on STD=1
|
||||
(REG8(0x3B) & 0x10)) // single step, resume execution
|
||||
{
|
||||
scripts_exec = data & 0x04;
|
||||
scsi_run(500);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* void scsi_write_16(UINT32 addr, UINT16 data);
|
||||
*
|
||||
* Writes a word to the SCSI register space.
|
||||
*
|
||||
* Parameters:
|
||||
* addr = Register address (only lower 8 bits matter.)
|
||||
* data = Data to write.
|
||||
*/
|
||||
|
||||
void scsi_write_16(UINT32 addr, UINT16 data)
|
||||
{
|
||||
data = BSWAP16(data);
|
||||
//message(0, "%08X: SCSI %02X = %04X", ppc_get_pc(), addr, data);
|
||||
}
|
||||
|
||||
/*
|
||||
* void scsi_write_32(UINT32 addr, UINT32 data);
|
||||
*
|
||||
* Writes a byte to the SCSI register space.
|
||||
*
|
||||
* Parameters:
|
||||
* addr = Register address (only lower 8 bits matter.)
|
||||
* data = Data to write.
|
||||
*/
|
||||
|
||||
void scsi_write_32(UINT32 addr, UINT32 data)
|
||||
{
|
||||
if ((addr & 0xff) > 0x5C)
|
||||
error("%08X: SCSI invalid write32 to %08X", ppc_get_pc(), addr);
|
||||
addr &= 0xff;
|
||||
|
||||
data = BSWAP32(data);
|
||||
REG32(addr) = data;
|
||||
|
||||
// message(0, "%08X: SCSI %02X = %08X", ppc_get_reg(PPC_REG_PC), addr, data);
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case 0x2C: // DSP: DMA SCRIPTS Pointer
|
||||
if ((REG8(0x38) & 0x01) == 0) // MAN=0, start SCRIPTS automatically
|
||||
scripts_exec = 1;
|
||||
scsi_run(500);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* void scsi_save_state(FILE *fp);
|
||||
*
|
||||
* Saves the state of the SCSI controller to a file.
|
||||
*
|
||||
* Parameters:
|
||||
* fp = File to save to.
|
||||
*/
|
||||
|
||||
void scsi_save_state(FILE *fp)
|
||||
{
|
||||
fwrite(scsi_regs, sizeof(UINT8), 0x60, fp);
|
||||
fwrite(&scripts_exec, sizeof(BOOL), 1, fp);
|
||||
}
|
||||
|
||||
/*
|
||||
* void scsi_load_state(FILE *fp);
|
||||
*
|
||||
* Loads the state of the SCSI controller from a file.
|
||||
*
|
||||
* Parameters:
|
||||
* fp = File to load from.
|
||||
*/
|
||||
|
||||
void scsi_load_state(FILE *fp)
|
||||
{
|
||||
fread(scsi_regs, sizeof(UINT8), 0x60, fp);
|
||||
fread(&scripts_exec, sizeof(BOOL), 1, fp);
|
||||
}
|
||||
|
||||
/*
|
||||
* void scsi_reset(void);
|
||||
*
|
||||
* Initializes the SCSI controller to its power-on state. All bits which are
|
||||
* marked as undefined by the manual are simply set to 0 here.
|
||||
*/
|
||||
|
||||
void scsi_reset(void)
|
||||
{
|
||||
memset(scsi_regs, 0, sizeof(scsi_regs));
|
||||
scripts_exec = 0;
|
||||
|
||||
REG8(0x00) = 0xc0;
|
||||
REG8(0x0C) = 0x80;
|
||||
REG8(0x0F) = 0x02;
|
||||
REG8(0x18) = 0xff;
|
||||
REG8(0x19) = 0xf0;
|
||||
REG8(0x1A) = 0x01;
|
||||
REG8(0x46) = 0x60;
|
||||
REG8(0x47) = 0x0f;
|
||||
REG8(0x4C) = 0x03;
|
||||
}
|
||||
|
||||
/*
|
||||
* void scsi_init(UINT8 (*read8)(UINT32), UINT16 (*read16)(UINT32),
|
||||
* UINT32 (*read32)(UINT32), void (*write8)(UINT32, UINT8),
|
||||
* void (*write16)(UINT32, UINT16),
|
||||
* void (*write32)(UINT32, UINT32));
|
||||
*
|
||||
* Initializes the SCSI controller emulation by building the SCRIPTS opcode
|
||||
* table and setting the memory access handlers.
|
||||
*
|
||||
* Parameters:
|
||||
* read8 = Handler to use for 8-bit reads.
|
||||
* read16 = Handler to use for 16-bit reads.
|
||||
* read32 = Handler to use for 32-bit reads.
|
||||
* write8 = Handler to use for 8-bit writes.
|
||||
* write16 = Handler to use for 16-bit writes.
|
||||
* write32 = Handler to use for 32-bit writes.
|
||||
*/
|
||||
|
||||
void scsi_init(UINT8 (*read8)(UINT32), UINT16 (*read16)(UINT32),
|
||||
UINT32 (*read32)(UINT32), void (*write8)(UINT32, UINT8),
|
||||
void (*write16)(UINT32, UINT16),
|
||||
void (*write32)(UINT32, UINT32))
|
||||
{
|
||||
read_8 = read8;
|
||||
read_16 = read16;
|
||||
read_32 = read32;
|
||||
write_8 = write8;
|
||||
write_16 = write16;
|
||||
write_32 = write32;
|
||||
|
||||
build_opcode_table();
|
||||
}
|
||||
|
||||
/*
|
||||
* void scsi_shutdown(void);
|
||||
*
|
||||
* Shuts down the SCSI emulation (actually does nothing.)
|
||||
*/
|
||||
|
||||
void scsi_shutdown(void)
|
||||
{
|
||||
}
|
51
core/scsi.h
Normal file
51
core/scsi.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Sega Model 3 Emulator
|
||||
* Copyright (C) 2003 Bart Trzynadlowski, Ville Linde, Stefano Teso
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 (license.txt); if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* scsi.h
|
||||
*
|
||||
* NCR 53C810 SCSI controller header.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_SCSI_H
|
||||
#define INCLUDED_SCSI_H
|
||||
|
||||
/*
|
||||
* Functions
|
||||
*/
|
||||
|
||||
extern UINT8 scsi_read_8(UINT32);
|
||||
extern UINT32 scsi_read_32(UINT32);
|
||||
|
||||
extern void scsi_write_8(UINT32, UINT8);
|
||||
extern void scsi_write_16(UINT32, UINT16);
|
||||
extern void scsi_write_32(UINT32, UINT32);
|
||||
|
||||
extern void scsi_save_state(FILE *);
|
||||
extern void scsi_load_state(FILE *);
|
||||
|
||||
extern void scsi_run(INT);
|
||||
extern void scsi_reset(void);
|
||||
|
||||
extern void scsi_init(UINT8 (*)(UINT32), UINT16 (*)(UINT32),
|
||||
UINT32 (*)(UINT32), void (*)(UINT32, UINT8),
|
||||
void (*)(UINT32, UINT16),
|
||||
void (*)(UINT32, UINT32));
|
||||
extern void scsi_shutdown(void);
|
||||
|
||||
#endif // INCLUDED_SCSI_H
|
221
core/scsiop.h
Normal file
221
core/scsiop.h
Normal file
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
* Sega Model 3 Emulator
|
||||
* Copyright (C) 2003 Bart Trzynadlowski, Ville Linde, Stefano Teso
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 (license.txt); if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* scsiop.h
|
||||
*
|
||||
* NCR 53C810 SCSI controller SCRIPTS emulation. This file is intended to be
|
||||
* included by scsi.c only.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_SCSIOP_H
|
||||
#define INCLUDED_SCSIOP_H
|
||||
|
||||
/*
|
||||
* Macros
|
||||
*/
|
||||
|
||||
#define INSTRUCTION(name) static BOOL name()
|
||||
|
||||
#define FETCH(dest) do { dest = read_32(REG32(0x2c)); REG32(0x2c) += 4; dest = BSWAP32(dest); } while (0);
|
||||
|
||||
#define DBC (REG32(0x24) & 0xffffff)
|
||||
#define DSPS (REG32(0x30))
|
||||
#define TEMP (REG32(0x1c))
|
||||
|
||||
|
||||
/*
|
||||
* Opcode Table
|
||||
*
|
||||
* Use the upper 8 bits of a SCRIPTS instruction as an index into this table.
|
||||
*/
|
||||
|
||||
static BOOL (*op_table[256])();
|
||||
|
||||
|
||||
/*
|
||||
* Move Memory
|
||||
*/
|
||||
|
||||
#ifdef _PROFILE_
|
||||
extern UINT is_dma;
|
||||
#endif
|
||||
|
||||
INSTRUCTION(move_memory)
|
||||
{
|
||||
UINT32 source = DSPS, dest;
|
||||
INT num_bytes = DBC;
|
||||
|
||||
PROFILE_SECT_ENTRY("scsi");
|
||||
|
||||
#ifdef _PROFILE_
|
||||
is_dma = 1;
|
||||
#endif
|
||||
|
||||
FETCH(TEMP);
|
||||
dest = TEMP;
|
||||
|
||||
// message(0, "%08X (%08X): SCSI move memory: %08X->%08X, %X", ppc_get_reg(PPC_REG_PC), ppc_get_reg(PPC_REG_LR), source, dest, num_bytes);
|
||||
|
||||
/*
|
||||
* Perform a 32-bit copy if possible and if necessary, finish off with a
|
||||
* byte-for-byte copy
|
||||
*/
|
||||
|
||||
/*for (i = 0; i < num_bytes / 4; i++)
|
||||
{
|
||||
write_32(dest, read_32(source));
|
||||
dest += 4;
|
||||
source += 4;
|
||||
}*/
|
||||
|
||||
model3_dma_transfer(source, dest, num_bytes, FALSE);
|
||||
|
||||
if (num_bytes & 3)
|
||||
{
|
||||
error("unaligned SCSI op !!!\n");
|
||||
num_bytes &= 3;
|
||||
while (num_bytes--)
|
||||
write_8(dest++, read_8(source++));
|
||||
}
|
||||
|
||||
source += num_bytes;
|
||||
dest += num_bytes;
|
||||
|
||||
#ifdef _PROFILE_
|
||||
is_dma = 0;
|
||||
#endif
|
||||
|
||||
REG32(0x24) &= 0xff000000; // update DBC (is any of this necessary???)
|
||||
DSPS = source;
|
||||
TEMP = dest;
|
||||
|
||||
PROFILE_SECT_EXIT("scsi");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* INT and INTFLY
|
||||
*/
|
||||
|
||||
INSTRUCTION(int_and_intfly)
|
||||
{
|
||||
if ((DBC & 0x100000)) // INTFLY -- not yet emulated!
|
||||
return 1;
|
||||
|
||||
if (((REG32(0x24) >> 21) & 1) || ((REG32(0x24) >> 18) & 1) || ((REG32(0x24) >> 17) & 1))
|
||||
return 1; // conditional tests not yet emulated
|
||||
|
||||
REG8(0x14) |= 0x01; // DIP=1
|
||||
scripts_exec = 0; // halt execution
|
||||
|
||||
/*
|
||||
* NOTE: I haven't seen any games rely on this, so if you observe SCSI
|
||||
* problems, remove this to see if it helps.
|
||||
*/
|
||||
|
||||
REG8(0x14) |= 0x01; // DIP=1
|
||||
REG8(0x0c) |= 0x04; // SIR=1
|
||||
//model3_add_irq(0x60);
|
||||
ppc_set_irq_line(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Invalid Instruction
|
||||
*/
|
||||
|
||||
INSTRUCTION(invalid)
|
||||
{
|
||||
// message(0, "INVALID SCSI INSTRUCTION @ %08X", REG32(0x2c));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* void scsi_run(INT num);
|
||||
*
|
||||
* Runs SCSI SCRIPTS instructions until the code halts or the requested number
|
||||
* of instructions is executed.
|
||||
*
|
||||
* Parameters:
|
||||
* num = Number of instructions to execute.
|
||||
*/
|
||||
|
||||
void scsi_run(INT num)
|
||||
{
|
||||
LOG("model3.log", "SCSI exec %08X\n", REG32(0x2c));
|
||||
if (!scripts_exec)
|
||||
return;
|
||||
|
||||
if ((REG8(0x3B) & 0x10)) // single step mode
|
||||
num = 1;
|
||||
|
||||
while (num-- && scripts_exec)
|
||||
{
|
||||
UINT32 save_addr = REG32(0x2c); // for debugging
|
||||
|
||||
FETCH(REG32(0x24)); // first double word into DCMD and DBC
|
||||
FETCH(DSPS); // second double word into DSPS
|
||||
|
||||
if ((*op_table[REG32(0x24) >> 24])())
|
||||
error("SCSI: invalid instruction @ %08X", save_addr);
|
||||
}
|
||||
|
||||
scripts_exec = 0;
|
||||
|
||||
if ((REG8(0x3B) & 0x10)) // single step mode, trigger interrupt
|
||||
{
|
||||
REG8(0x0c) |= 0x08; // SSI=1
|
||||
REG8(0x14) |= 0x01; // DIP=1
|
||||
ppc_set_irq_line(1); // what about Model 3 IRQ status?
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* insert():
|
||||
*
|
||||
* Inserts an instruction into the appropriate elements of the opcode table
|
||||
* under the control of a mask.
|
||||
*/
|
||||
|
||||
static void insert(UINT8 match, UINT8 mask, BOOL (*handler)())
|
||||
{
|
||||
UINT32 i;
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
if ((i & mask) == match)
|
||||
op_table[i] = handler;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* build_opcode_table():
|
||||
*
|
||||
* Installs instruction handlers.
|
||||
*/
|
||||
|
||||
static void build_opcode_table(void)
|
||||
{
|
||||
insert(0, 0, &invalid);
|
||||
insert(0xc0, 0xfe, &move_memory);
|
||||
insert(0x98, 0xf8, &int_and_intfly);
|
||||
}
|
||||
|
||||
#endif // INCLUDED_SCSIOP_H
|
2494
core/scsp.c
Normal file
2494
core/scsp.c
Normal file
File diff suppressed because it is too large
Load diff
29
core/scsp.h
Normal file
29
core/scsp.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
|
||||
#ifndef _SCSP_H_
|
||||
#define _SCSP_H_
|
||||
|
||||
extern void scsp_shutdown(void);
|
||||
extern void scsp_init(UINT8 *scsp_ram, void *sint_hand, void *mint_hand);
|
||||
extern void scsp_reset(void);
|
||||
|
||||
extern void scsp_update(INT32 *bufL, INT32 *bufR, UINT32 len);
|
||||
extern void scsp_update_timer(UINT32 len);
|
||||
|
||||
extern UINT32 scsp_read_8(UINT32 a);
|
||||
extern UINT32 scsp_read_16(UINT32 a);
|
||||
extern UINT32 scsp_read_32(UINT32 a);
|
||||
|
||||
extern void scsp_write_8(UINT32 a, UINT32 d);
|
||||
extern void scsp_write_16(UINT32 a, UINT32 d);
|
||||
extern void scsp_write_32(UINT32 a, UINT32 d);
|
||||
|
||||
extern void scsp_midi_in_send(UINT8 data);
|
||||
extern void scsp_midi_out_send(UINT8 data);
|
||||
extern UINT8 scsp_midi_in_read(void);
|
||||
extern UINT8 scsp_midi_out_read(void);
|
||||
|
||||
extern char * scsp_debug_slist_on(void);
|
||||
extern char * scsp_debug_ilist(INT s_m, char * out);
|
||||
|
||||
#endif /* _SCSP_H_ */
|
||||
|
823
core/tilegen.c
Normal file
823
core/tilegen.c
Normal file
|
@ -0,0 +1,823 @@
|
|||
/*
|
||||
* Sega Model 3 Emulator
|
||||
* Copyright (C) 2003 Bart Trzynadlowski, Ville Linde, Stefano Teso
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 (license.txt); if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* tilegen.c
|
||||
*
|
||||
* Tilemap generator.
|
||||
*
|
||||
* Palette Notes:
|
||||
* - Each palette entry occupies 32 bits. Only the second 16 bits are
|
||||
* actually used.
|
||||
* - The format of a 16-bit palette entry is: AGGGGGBBBBBRRRRR
|
||||
*
|
||||
* Register Notes:
|
||||
*
|
||||
* 0x20 -- Layer Colors:
|
||||
*
|
||||
* 31 23 20 0
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* |-|-|-|-|-|-|-|-|D|C|B|A|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*
|
||||
* D = Layer 0xFE000 color control (0 = 8-bit, 1 = 4-bit)
|
||||
* C = Layer 0xFC000 color control (0 = 8-bit, 1 = 4-bit)
|
||||
* B = Layer 0xFA000 color control (0 = 8-bit, 1 = 4-bit)
|
||||
* A = Layer 0xF8000 color control (0 = 8-bit, 1 = 4-bit)
|
||||
*/
|
||||
|
||||
#include "model3.h"
|
||||
|
||||
/******************************************************************/
|
||||
/* Privates */
|
||||
/******************************************************************/
|
||||
|
||||
/*
|
||||
* NOTE: It is critical that vram be set to NULL if it has not yet been
|
||||
* allocated because tilegen_set_layer_format() will try to use it to
|
||||
* recache the palette.
|
||||
*/
|
||||
|
||||
static UINT8 *vram = NULL; // 2D VRAM (passed to tilegen_init())
|
||||
static UINT8 reg[0x100]; // tilemap generator registers
|
||||
|
||||
/*
|
||||
* Register Macros
|
||||
*/
|
||||
|
||||
#define REG_LAYER_COLORS 0x20
|
||||
|
||||
/*
|
||||
* Pre-Decoded Palette Data
|
||||
*
|
||||
* Depending on the renderer color depth, the data is either 32-bit RGBA8 or
|
||||
* 16-bit RGB5A1. The actual order of the fields is obtained from the renderer
|
||||
* but it is guaranteed that for 16-bit modes, the color components will each
|
||||
* be 5 bits and the alpha will be 1 and for the 32-bit modes, all components
|
||||
* will be 8 bits.
|
||||
*
|
||||
* For alpha channel: All bits set means the color is opaque, all bits clear
|
||||
* means the color is transparent. No other bit combinations should be used.
|
||||
*/
|
||||
|
||||
static UINT32 *pal;
|
||||
|
||||
/*
|
||||
* Layer Format
|
||||
*
|
||||
* Information that is passed by the renderer on the format of layers. Bit
|
||||
* position 0 is the LSB (none of that backwards IBM junk ;)) RGBA bit
|
||||
* positions give the position of the LSB of the field.
|
||||
*/
|
||||
|
||||
static UINT pitch; // layer pitch (in pixels)
|
||||
static UINT rpos, gpos, bpos, apos; // R, G, B, A bit positions
|
||||
static INT bpp; // 15 or 32 only
|
||||
|
||||
static int tilemap_is_dirty[4];
|
||||
static int tilemap_dirty[4][64*64];
|
||||
static int tilemap_depth[4][64*64];
|
||||
static int tilemap_redraw[4];
|
||||
|
||||
/******************************************************************/
|
||||
/* Rendering */
|
||||
/******************************************************************/
|
||||
|
||||
/*
|
||||
* PUTPIXELx_xx():
|
||||
*
|
||||
* A handy macro used within the draw_tile_xbit_xx() macros to plot a pixel
|
||||
* and advance the buffer pointer.
|
||||
*/
|
||||
|
||||
/*#define PUTPIXEL8_32(bp) \
|
||||
do { \
|
||||
pixel = pal[((pattern >> bp) & 0xFF) | pal_bits]; \
|
||||
*buf++ = pixel; \
|
||||
} while (0)
|
||||
|
||||
#define PUTPIXEL4_32(bp) \
|
||||
do { \
|
||||
pixel = pal[((pattern >> bp) & 0xF) | pal_bits]; \
|
||||
*buf++ = pixel; \
|
||||
} while (0)
|
||||
*/
|
||||
|
||||
#define PUTPIXEL8(bp) \
|
||||
do \
|
||||
{ \
|
||||
*buf++ = ((pattern >> bp) & 0xff) | pal_bits; \
|
||||
} while(0)
|
||||
|
||||
#define PUTPIXEL4(bp) \
|
||||
do \
|
||||
{ \
|
||||
*buf++ = ((pattern >> bp) & 0xf) | pal_bits; \
|
||||
} while(0)
|
||||
|
||||
/*
|
||||
* draw_tile_8bit_32():
|
||||
*
|
||||
* Draws an 8-bit tile to a 32-bit layer buffer.
|
||||
*/
|
||||
|
||||
static void draw_tile_8bit(UINT tile, UINT16 *buf)
|
||||
{
|
||||
UINT tile_offs; // offset of tile within VRAM
|
||||
UINT pal_bits; // color palette bits obtained from tile
|
||||
UINT y;
|
||||
UINT32 pattern; // 4 pattern pixels fetched at once
|
||||
|
||||
/*
|
||||
* Calculate tile offset; each tile occupies 64 bytes when using 8-bit
|
||||
* pixels
|
||||
*/
|
||||
|
||||
//tile_offs = tile & 0x3fff;
|
||||
//tile_offs *= 64;
|
||||
tile_offs = ((tile & 0x3fff) << 1) | ((tile >> 15) & 1);
|
||||
tile_offs *= 32;
|
||||
|
||||
/*
|
||||
* Obtain upper color bits; the lower 8 bits come from the tile pattern
|
||||
*/
|
||||
|
||||
pal_bits = tile & 0x7F00;
|
||||
|
||||
/*
|
||||
* Draw!
|
||||
*/
|
||||
|
||||
for (y = 0; y < 8; y++)
|
||||
{
|
||||
/*
|
||||
* Fetch first 4 pixels and draw them
|
||||
*/
|
||||
|
||||
pattern = *((UINT32 *) &vram[tile_offs]);
|
||||
tile_offs += 4;
|
||||
PUTPIXEL8(24);
|
||||
PUTPIXEL8(16);
|
||||
PUTPIXEL8(8);
|
||||
PUTPIXEL8(0);
|
||||
|
||||
/*
|
||||
* Next 4
|
||||
*/
|
||||
|
||||
pattern = *((UINT32 *) &vram[tile_offs]);
|
||||
tile_offs += 4;
|
||||
PUTPIXEL8(24);
|
||||
PUTPIXEL8(16);
|
||||
PUTPIXEL8(8);
|
||||
PUTPIXEL8(0);
|
||||
|
||||
/*
|
||||
* Move to the next line
|
||||
*/
|
||||
|
||||
buf += (pitch - 8); // next line in layer buffer
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* draw_tile_4bit_32():
|
||||
*
|
||||
* Draws a 4-bit tile to a 32-bit layer buffer.
|
||||
*/
|
||||
|
||||
static void draw_tile_4bit(UINT tile, UINT16 *buf)
|
||||
{
|
||||
UINT tile_offs; // offset of tile within VRAM
|
||||
UINT pal_bits; // color palette bits obtained from tile
|
||||
UINT y;
|
||||
UINT32 pattern; // 8 pattern pixels fetched at once
|
||||
|
||||
/*
|
||||
* Calculate tile offset; each tile occupies 32 bytes when using 4-bit
|
||||
* pixels
|
||||
*/
|
||||
|
||||
tile_offs = ((tile & 0x3fff) << 1) | ((tile >> 15) & 1);
|
||||
tile_offs *= 32;
|
||||
|
||||
/*
|
||||
* Obtain upper color bits; the lower 4 bits come from the tile pattern
|
||||
*/
|
||||
|
||||
pal_bits = tile & 0x7FF0;
|
||||
|
||||
/*
|
||||
* Draw!
|
||||
*/
|
||||
|
||||
for (y = 0; y < 8; y++)
|
||||
{
|
||||
pattern = *((UINT32 *) &vram[tile_offs]);
|
||||
|
||||
/*
|
||||
* Draw the 8 pixels we've fetched
|
||||
*/
|
||||
|
||||
PUTPIXEL4(28);
|
||||
PUTPIXEL4(24);
|
||||
PUTPIXEL4(20);
|
||||
PUTPIXEL4(16);
|
||||
PUTPIXEL4(12);
|
||||
PUTPIXEL4(8);
|
||||
PUTPIXEL4(4);
|
||||
PUTPIXEL4(0);
|
||||
|
||||
/*
|
||||
* Move to the next line
|
||||
*/
|
||||
|
||||
tile_offs += 4; // next tile pattern line
|
||||
buf += (pitch - 8); // next line in layer buffer
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* draw_layer_8bit_32():
|
||||
*
|
||||
* Draws an entire layer of 8-bit tiles to a 32-bit layer buffer.
|
||||
*/
|
||||
|
||||
static void draw_layer_8bit(UINT16 *layer, int layer_num)
|
||||
{
|
||||
int ty, tx;
|
||||
int tilenum;
|
||||
UINT32 tile;
|
||||
UINT32 addr = 0xf8000 + (layer_num * 0x2000);
|
||||
|
||||
if (tilemap_is_dirty[layer_num] == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
tilemap_is_dirty[layer_num] = 0;
|
||||
|
||||
tilenum = 0;
|
||||
for (ty = 0; ty < 64; ty++)
|
||||
{
|
||||
for (tx = 0; tx < 64; tx+=2)
|
||||
{
|
||||
if (tilemap_redraw[layer_num] || tilemap_dirty[layer_num][tilenum+0])
|
||||
{
|
||||
tilemap_depth[layer_num][tilenum+0] = 0;
|
||||
tilemap_dirty[layer_num][tilenum+0] = 0;
|
||||
tile = *((UINT32 *) &vram[addr]) >> 16;
|
||||
|
||||
draw_tile_8bit(tile & 0xffff, layer);
|
||||
}
|
||||
if (tilemap_redraw[layer_num] || tilemap_dirty[layer_num][tilenum+1])
|
||||
{
|
||||
tilemap_depth[layer_num][tilenum+1] = 0;
|
||||
tilemap_dirty[layer_num][tilenum+1] = 0;
|
||||
tile = *((UINT32 *) &vram[addr]) >> 0;
|
||||
|
||||
draw_tile_8bit(tile & 0xffff, layer+8);
|
||||
}
|
||||
|
||||
addr += 4;
|
||||
layer += 16;
|
||||
tilenum+=2;
|
||||
}
|
||||
|
||||
//addr += (64 - 62) * 2;
|
||||
layer += (7 * pitch) + (pitch - 512); // next tile row
|
||||
}
|
||||
|
||||
tilemap_redraw[layer_num] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* draw_layer_4bit_32():
|
||||
*
|
||||
* Draws an entire layer of 4-bit tiles to a 32-bit layer buffer.
|
||||
*/
|
||||
|
||||
static void draw_layer_4bit(UINT16 *layer, int layer_num)
|
||||
{
|
||||
int ty, tx;
|
||||
int tilenum;
|
||||
UINT32 tile;
|
||||
UINT32 addr = 0xf8000 + (layer_num * 0x2000);
|
||||
|
||||
if (tilemap_is_dirty[layer_num] == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
tilemap_is_dirty[layer_num] = 0;
|
||||
|
||||
tilenum = 0;
|
||||
for (ty = 0; ty < 64; ty++)
|
||||
{
|
||||
for (tx = 0; tx < 64; tx+=2)
|
||||
{
|
||||
if (tilemap_redraw[layer_num] || tilemap_dirty[layer_num][tilenum+0])
|
||||
{
|
||||
tilemap_depth[layer_num][tilenum+0] = 1;
|
||||
tilemap_dirty[layer_num][tilenum+0] = 0;
|
||||
tile = *((UINT32 *) &vram[addr]) >> 16;
|
||||
|
||||
draw_tile_4bit(tile & 0xffff, layer);
|
||||
}
|
||||
if (tilemap_redraw[layer_num] || tilemap_dirty[layer_num][tilenum+1])
|
||||
{
|
||||
tilemap_depth[layer_num][tilenum+0] = 1;
|
||||
tilemap_dirty[layer_num][tilenum+1] = 0;
|
||||
tile = *((UINT32 *) &vram[addr]) >> 0;
|
||||
|
||||
draw_tile_4bit(tile & 0xffff, layer+8);
|
||||
}
|
||||
|
||||
addr += 4;
|
||||
layer += 16;
|
||||
tilenum+=2;
|
||||
}
|
||||
|
||||
//addr += (64 - 62) * 2;
|
||||
layer += (7 * pitch) + (pitch - 512); // next tile row
|
||||
}
|
||||
|
||||
tilemap_redraw[layer_num] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* void tilegen_update(void);
|
||||
*
|
||||
* Renders up to 4 layers for the current frame.
|
||||
*/
|
||||
|
||||
void tilegen_update(void)
|
||||
{
|
||||
UINT8 *layer;
|
||||
UINT layer_colors, layer_color_mask;
|
||||
FLAGS layer_enable_mask;
|
||||
int i, j;
|
||||
|
||||
/*
|
||||
* Render layers
|
||||
*/
|
||||
|
||||
PROFILE_SECT_ENTRY("tilegen");
|
||||
|
||||
layer_colors = BSWAP32(*(UINT32 *) ®[REG_LAYER_COLORS]);
|
||||
layer_color_mask = 0x00100000; // first layer color bit (moves left)
|
||||
layer_enable_mask = 1;
|
||||
|
||||
// layer_colors = 0; // enable this to force 8-bit mode for VF3
|
||||
|
||||
{
|
||||
UINT32 *palette;
|
||||
int pwidth;
|
||||
int ppitch;
|
||||
int pheight;
|
||||
int p = 0;
|
||||
|
||||
osd_renderer_get_palette_buffer(&palette, &pwidth, &ppitch);
|
||||
|
||||
pheight = 0x10000 / pwidth;
|
||||
for (j=0; j < 128; j++)
|
||||
{
|
||||
int pindex = j * ppitch;
|
||||
p = j * 256;
|
||||
for (i=0; i < 256; i++)
|
||||
{
|
||||
int a,r,g,b;
|
||||
UINT32 rgba;
|
||||
UINT16 pix;
|
||||
|
||||
pix = pal[p];
|
||||
|
||||
a = (pix & 0x8000) ? 0x00 : 0xff;
|
||||
b = (pix >> 10) & 0x1f;
|
||||
g = (pix >> 5) & 0x1f;
|
||||
r = (pix & 0x1f);
|
||||
b = (b << 3) | (b >> 2);
|
||||
g = (g << 3) | (g >> 2);
|
||||
r = (r << 3) | (r >> 2);
|
||||
|
||||
rgba = (a << 24) | (r << 16) | (g << 8) | (b << 0);
|
||||
palette[pindex + i] = rgba;
|
||||
p++;
|
||||
|
||||
// a very hackish way to counter the effect of using colours as texture coords
|
||||
if (i == 239)
|
||||
p--;
|
||||
}
|
||||
}
|
||||
|
||||
osd_renderer_free_palette_buffer();
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
if ((m3_config.layer_enable & layer_enable_mask))
|
||||
{
|
||||
osd_renderer_get_layer_buffer(i, &layer, &pitch);
|
||||
|
||||
if ((layer_colors & layer_color_mask))
|
||||
{
|
||||
draw_layer_4bit((UINT16 *) layer, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
draw_layer_8bit((UINT16 *) layer, i);
|
||||
}
|
||||
|
||||
osd_renderer_free_layer_buffer(i);
|
||||
}
|
||||
layer_color_mask <<= 1;
|
||||
layer_enable_mask <<= 1;
|
||||
}
|
||||
|
||||
PROFILE_SECT_EXIT("tilegen");
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
/* VRAM Access */
|
||||
/******************************************************************/
|
||||
|
||||
static void mark_tilemap_dirty(int layer)
|
||||
{
|
||||
tilemap_is_dirty[layer] = 1;
|
||||
tilemap_redraw[layer] = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* UINT16 tilegen_vram_read_16(UINT32 addr);
|
||||
*
|
||||
* Reads a 16-bit word from VRAM.
|
||||
*
|
||||
* Parameters:
|
||||
* addr = Address.
|
||||
*
|
||||
* Returns:
|
||||
* Data read.
|
||||
*/
|
||||
|
||||
UINT16 tilegen_vram_read_16(UINT32 addr)
|
||||
{
|
||||
return(BSWAP16(*(UINT16 *)&vram[addr & 0x1FFFFF]));
|
||||
}
|
||||
|
||||
/*
|
||||
* UINT32 tilegen_vram_read_32(UINT32 addr);
|
||||
*
|
||||
* Reads a 32-bit word from VRAM.
|
||||
*
|
||||
* Parameters:
|
||||
* addr = Address.
|
||||
*
|
||||
* Returns:
|
||||
* Data read.
|
||||
*/
|
||||
|
||||
UINT32 tilegen_vram_read_32(UINT32 addr)
|
||||
{
|
||||
return(BSWAP32(*(UINT32 *)&vram[addr & 0x1FFFFF]));
|
||||
}
|
||||
|
||||
/*
|
||||
* void tilegen_vram_write_32(UINT32 addr, UINT32 data);
|
||||
*
|
||||
* Writes a 32-bit word to VRAM. Palette decoding is handled here.
|
||||
*
|
||||
* Parameters:
|
||||
* addr = Address.
|
||||
* data = Data.
|
||||
*/
|
||||
|
||||
void tilegen_vram_write_32(UINT32 addr, UINT32 data)
|
||||
{
|
||||
UINT color;
|
||||
|
||||
addr &= 0x1FFFFF;
|
||||
data = BSWAP32(data); // return to its natural order (as on PPC)
|
||||
|
||||
if (addr < 0xf8000)
|
||||
{
|
||||
*(UINT32 *)&vram[addr] = data;
|
||||
}
|
||||
else if (addr >= 0x0f8000 && addr < 0x100000)
|
||||
{
|
||||
UINT32 old_data;
|
||||
int ad, layer, layer_depth, old_depth;
|
||||
|
||||
ad = addr - 0xf8000;
|
||||
layer = ad / 0x2000;
|
||||
|
||||
old_data = *(UINT32 *)&vram[addr];
|
||||
layer_depth = (BSWAP32(*(UINT32 *) ®[REG_LAYER_COLORS]) >> (20+layer)) & 1;
|
||||
old_depth = tilemap_depth[layer][((ad & 0x1fff) / 2)];
|
||||
|
||||
if (data != old_data || layer_depth != old_depth)
|
||||
{
|
||||
*(UINT32 *)&vram[addr] = data;
|
||||
|
||||
//ad = addr - 0xf8000;
|
||||
//layer = ad / 0x2000;
|
||||
tilemap_dirty[layer][((ad & 0x1fff) / 2) + 0] = 1;
|
||||
tilemap_dirty[layer][((ad & 0x1fff) / 2) + 1] = 1;
|
||||
tilemap_is_dirty[layer] = 1;
|
||||
}
|
||||
}
|
||||
else if (addr >= 0x100000 && addr < 0x120000) // palette
|
||||
{
|
||||
*(UINT32 *)&vram[addr] = data;
|
||||
color = (addr - 0x100000) / 4; // color number
|
||||
|
||||
pal[color] = data;
|
||||
}
|
||||
}
|
||||
|
||||
static void recache_palette(void)
|
||||
{
|
||||
UINT32 i;
|
||||
|
||||
for (i = 0x100000; i < 0x11FFFF; i += 4)
|
||||
tilegen_vram_write_32(i, BSWAP32(*(UINT32 *) &vram[i]));
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
/* Tilegen I/O Port Access */
|
||||
/******************************************************************/
|
||||
|
||||
/*
|
||||
* UINT32 tilegen_read_32(UINT32 a);
|
||||
*
|
||||
* Reads a 32-bit word from the tilemap generator register area.
|
||||
*
|
||||
* Parameters:
|
||||
* a = Address.
|
||||
*
|
||||
* Returns:
|
||||
* Data read.
|
||||
*/
|
||||
|
||||
UINT32 tilegen_read_32(UINT32 a)
|
||||
{
|
||||
// LOG("MODEL3.LOG", "TILEGEN: %08X: read 32 %08X\n", PPC_PC, a);
|
||||
//message(0, "tilegen: %08X: read 32 %08X", PPC_PC, a);
|
||||
|
||||
a &= 0xFF;
|
||||
|
||||
switch(a)
|
||||
{
|
||||
|
||||
case 0x00: // Status/Control
|
||||
// 0x20 (latch) controls layer pairing
|
||||
return(0 << 24);
|
||||
}
|
||||
|
||||
return(BSWAP32(*(UINT32 *)®[a]));
|
||||
}
|
||||
|
||||
/*
|
||||
* void tilegen_write_32(UINT32 a, UINT32 d);
|
||||
*
|
||||
* Writes a 32-bit word to the tilemap generator register area.
|
||||
*
|
||||
* Parameters:
|
||||
* a = Address.
|
||||
* d = Data.
|
||||
*/
|
||||
|
||||
void tilegen_write_32(UINT32 a, UINT32 d)
|
||||
{
|
||||
/* data is written as 32-bit, but only higher byte is used */
|
||||
|
||||
// LOG("MODEL3.LOG", "TILEGEN: %08X: write 32 %08X = %08X\n", PPC_PC, a, d);
|
||||
|
||||
a &= 0xFF;
|
||||
|
||||
//if (a != 0x60 && a != 0x64 && a != 0x68 && a != 0x6c &&
|
||||
// a != 0x10 && a != 0x0c && a != 0x40 && a != 0x44)
|
||||
//printf("tilegen: %08X, %08X\n", a, d);
|
||||
|
||||
switch(a)
|
||||
{
|
||||
case 0x00:
|
||||
case 0x04:
|
||||
case 0x08:
|
||||
case 0x0C:
|
||||
break;
|
||||
case 0x10:
|
||||
model3_remove_irq((UINT8) (d >> 24));
|
||||
break;
|
||||
case 0x14:
|
||||
case 0x18:
|
||||
case 0x1C:
|
||||
break;
|
||||
case 0x20:
|
||||
{
|
||||
UINT32 olddata = *(UINT32 *)®[a];
|
||||
UINT32 newdata = BSWAP32(d);
|
||||
|
||||
if ((olddata & 0x100000) != (newdata & 0x100000))
|
||||
mark_tilemap_dirty(0);
|
||||
if ((olddata & 0x200000) != (newdata & 0x200000))
|
||||
mark_tilemap_dirty(1);
|
||||
if ((olddata & 0x400000) != (newdata & 0x400000))
|
||||
mark_tilemap_dirty(2);
|
||||
if ((olddata & 0x800000) != (newdata & 0x800000))
|
||||
mark_tilemap_dirty(3);
|
||||
|
||||
/**(UINT32 *)®[0x60] &= ~0x80000000;
|
||||
*(UINT32 *)®[0x64] &= ~0x80000000;
|
||||
*(UINT32 *)®[0x68] &= ~0x80000000;
|
||||
*(UINT32 *)®[0x6c] &= ~0x80000000;*/
|
||||
break;
|
||||
}
|
||||
case 0x24:
|
||||
case 0x40:
|
||||
case 0x44:
|
||||
break;
|
||||
case 0x60:
|
||||
case 0x64:
|
||||
case 0x68:
|
||||
case 0x6C:
|
||||
break;
|
||||
}
|
||||
|
||||
*(UINT32 *)®[a] = BSWAP32(d);
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
/* Set Up, Shut Down, and State Management */
|
||||
/******************************************************************/
|
||||
|
||||
/*
|
||||
* void tilegen_save_state(FILE *fp);
|
||||
*
|
||||
* Saves the state of the tile generator to a file.
|
||||
*
|
||||
* Parameters:
|
||||
* fp = File to save to.
|
||||
*/
|
||||
|
||||
void tilegen_save_state(FILE *fp)
|
||||
{
|
||||
fwrite(vram, sizeof(UINT8), 1*1024*1024+2*65536, fp);
|
||||
fwrite(reg, sizeof(UINT8), 0x100, fp);
|
||||
}
|
||||
|
||||
/*
|
||||
* void tilegen_load_state(FILE *fp);
|
||||
*
|
||||
* Loads the state of the tile generator from a file.
|
||||
*
|
||||
* Parameters:
|
||||
* fp = File to load from.
|
||||
*/
|
||||
|
||||
void tilegen_load_state(FILE *fp)
|
||||
{
|
||||
fread(vram, sizeof(UINT8), 1*1024*1024+2*65536, fp);
|
||||
fread(reg, sizeof(UINT8), 0x100, fp);
|
||||
recache_palette();
|
||||
|
||||
mark_tilemap_dirty(0);
|
||||
mark_tilemap_dirty(1);
|
||||
mark_tilemap_dirty(2);
|
||||
mark_tilemap_dirty(3);
|
||||
}
|
||||
|
||||
/*
|
||||
* void tilegen_shutdown(void);
|
||||
*
|
||||
* Shuts down the tilemap generator.
|
||||
*/
|
||||
|
||||
void tilegen_shutdown(void)
|
||||
{
|
||||
vram = NULL;
|
||||
SAFE_FREE(pal);
|
||||
}
|
||||
|
||||
/*
|
||||
* void tilegen_init(UINT8 *vramptr);
|
||||
*
|
||||
* Initializes the tilemap generator.
|
||||
*
|
||||
* Parameters:
|
||||
* vramptr = Pointer to 2D VRAM.
|
||||
*/
|
||||
|
||||
void tilegen_init(UINT8 *vramptr)
|
||||
{
|
||||
vram = vramptr;
|
||||
|
||||
mark_tilemap_dirty(0);
|
||||
mark_tilemap_dirty(1);
|
||||
mark_tilemap_dirty(2);
|
||||
mark_tilemap_dirty(3);
|
||||
|
||||
pal = malloc(sizeof(UINT32) * 65536);
|
||||
|
||||
atexit(tilegen_shutdown);
|
||||
}
|
||||
|
||||
BOOL tilegen_is_layer_enabled(int layer)
|
||||
{
|
||||
if (layer == 1 && stricmp(m3_config.game_id, "lostwsga") == 0)
|
||||
return FALSE;
|
||||
|
||||
switch (layer)
|
||||
{
|
||||
case 0:
|
||||
return *(UINT32 *)®[0x60] & 0x80000000 ? 1 : 0;
|
||||
case 1:
|
||||
return *(UINT32 *)®[0x64] & 0x80000000 ? 1 : 0;
|
||||
case 2:
|
||||
return *(UINT32 *)®[0x68] & 0x80000000 ? 1 : 0;
|
||||
case 3:
|
||||
return *(UINT32 *)®[0x6c] & 0x80000000 ? 1 : 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
UINT32 tilegen_get_layer_color_offset(int layer)
|
||||
{
|
||||
switch (layer)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
{
|
||||
INT8 r = (*(UINT32 *)®[0x40] >> 16) & 0xff;
|
||||
INT8 g = (*(UINT32 *)®[0x40] >> 8) & 0xff;
|
||||
INT8 b = (*(UINT32 *)®[0x40] >> 0) & 0xff;
|
||||
|
||||
r += 127;
|
||||
g += 127;
|
||||
b += 127;
|
||||
|
||||
return (r << 16) | (g << 8) | (b);
|
||||
}
|
||||
|
||||
case 2:
|
||||
case 3:
|
||||
{
|
||||
UINT8 r = (*(UINT32 *)®[0x44] >> 16) & 0xff;
|
||||
UINT8 g = (*(UINT32 *)®[0x44] >> 8) & 0xff;
|
||||
UINT8 b = (*(UINT32 *)®[0x44] >> 0) & 0xff;
|
||||
|
||||
r ^= 0x80;
|
||||
g ^= 0x80;
|
||||
b ^= 0x80;
|
||||
|
||||
return (r << 16) | (g << 8) | (b);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
UINT32 *tilegen_get_priority_buffer(void)
|
||||
{
|
||||
return (UINT32 *)&vram[0xf7000];
|
||||
}
|
||||
|
||||
BOOL tilegen_is_priority_enabled(void)
|
||||
{
|
||||
UINT32 v = *(UINT32 *)®[0x20];
|
||||
return (v & 0x80) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
UINT32 tilegen_get_layer_scroll_pos(int layer)
|
||||
{
|
||||
UINT32 s = *(UINT32 *)®[0x60 + (layer*4)];
|
||||
return s & 0x7fff7fff;
|
||||
}
|
||||
|
||||
/*
|
||||
* void tilegen_reset(void);
|
||||
*
|
||||
* Resets the tilemap generator. The registers are put into a reset state and
|
||||
* the palette is zeroed out.
|
||||
*/
|
||||
|
||||
void tilegen_reset(void)
|
||||
{
|
||||
memset(reg, 0xFF, 0x100);
|
||||
memset(pal, 0x00, 65536 * sizeof(UINT32));
|
||||
}
|
49
core/tilegen.h
Normal file
49
core/tilegen.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Sega Model 3 Emulator
|
||||
* Copyright (C) 2003 Bart Trzynadlowski, Ville Linde, Stefano Teso
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 (license.txt); if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* tilegen.h
|
||||
*
|
||||
* Tilemap generator header.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_TILEGEN_H
|
||||
#define INCLUDED_TILEGEN_H
|
||||
|
||||
extern void tilegen_update(void);
|
||||
|
||||
extern UINT16 tilegen_vram_read_16(UINT32 addr);
|
||||
extern UINT32 tilegen_vram_read_32(UINT32);
|
||||
extern void tilegen_vram_write_32(UINT32, UINT32);
|
||||
|
||||
extern UINT16 tilegen_read_16(UINT32);
|
||||
extern UINT32 tilegen_read_32(UINT32);
|
||||
extern void tilegen_write_32(UINT32, UINT32);
|
||||
|
||||
extern BOOL tilegen_is_layer_enabled(int);
|
||||
extern UINT32 tilegen_get_layer_color_offset(int layer);
|
||||
|
||||
extern void tilegen_save_state(FILE *);
|
||||
extern void tilegen_load_state(FILE *);
|
||||
|
||||
extern void tilegen_reset(void);
|
||||
extern void tilegen_init(UINT8 *);
|
||||
extern void tilegen_shutdown(void);
|
||||
|
||||
#endif // INCLUDED_TILEGEN_H
|
||||
|
1013
expat/expat.h
Normal file
1013
expat/expat.h
Normal file
File diff suppressed because it is too large
Load diff
115
expat/expat_external.h
Normal file
115
expat/expat_external.h
Normal file
|
@ -0,0 +1,115 @@
|
|||
/* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
|
||||
See the file COPYING for copying permission.
|
||||
*/
|
||||
|
||||
#ifndef Expat_External_INCLUDED
|
||||
#define Expat_External_INCLUDED 1
|
||||
|
||||
/* External API definitions */
|
||||
|
||||
#if defined(_MSC_EXTENSIONS) && !defined(__BEOS__) && !defined(__CYGWIN__)
|
||||
#define XML_USE_MSC_EXTENSIONS 1
|
||||
#endif
|
||||
|
||||
/* Expat tries very hard to make the API boundary very specifically
|
||||
defined. There are two macros defined to control this boundary;
|
||||
each of these can be defined before including this header to
|
||||
achieve some different behavior, but doing so it not recommended or
|
||||
tested frequently.
|
||||
|
||||
XMLCALL - The calling convention to use for all calls across the
|
||||
"library boundary." This will default to cdecl, and
|
||||
try really hard to tell the compiler that's what we
|
||||
want.
|
||||
|
||||
XMLIMPORT - Whatever magic is needed to note that a function is
|
||||
to be imported from a dynamically loaded library
|
||||
(.dll, .so, or .sl, depending on your platform).
|
||||
|
||||
The XMLCALL macro was added in Expat 1.95.7. The only one which is
|
||||
expected to be directly useful in client code is XMLCALL.
|
||||
|
||||
Note that on at least some Unix versions, the Expat library must be
|
||||
compiled with the cdecl calling convention as the default since
|
||||
system headers may assume the cdecl convention.
|
||||
*/
|
||||
#ifndef XMLCALL
|
||||
#if defined(XML_USE_MSC_EXTENSIONS)
|
||||
#define XMLCALL __cdecl
|
||||
#elif defined(__GNUC__) && defined(__i386)
|
||||
#define XMLCALL __attribute__((cdecl))
|
||||
#else
|
||||
/* For any platform which uses this definition and supports more than
|
||||
one calling convention, we need to extend this definition to
|
||||
declare the convention used on that platform, if it's possible to
|
||||
do so.
|
||||
|
||||
If this is the case for your platform, please file a bug report
|
||||
with information on how to identify your platform via the C
|
||||
pre-processor and how to specify the same calling convention as the
|
||||
platform's malloc() implementation.
|
||||
*/
|
||||
#define XMLCALL
|
||||
#endif
|
||||
#endif /* not defined XMLCALL */
|
||||
|
||||
|
||||
#if !defined(XML_STATIC) && !defined(XMLIMPORT)
|
||||
#ifndef XML_BUILDING_EXPAT
|
||||
/* using Expat from an application */
|
||||
|
||||
#ifdef XML_USE_MSC_EXTENSIONS
|
||||
#define XMLIMPORT __declspec(dllimport)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif /* not defined XML_STATIC */
|
||||
|
||||
|
||||
/* If we didn't define it above, define it away: */
|
||||
#ifndef XMLIMPORT
|
||||
#define XMLIMPORT
|
||||
#endif
|
||||
|
||||
|
||||
#define XMLPARSEAPI(type) XMLIMPORT type XMLCALL
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef XML_UNICODE_WCHAR_T
|
||||
#define XML_UNICODE
|
||||
#endif
|
||||
|
||||
#ifdef XML_UNICODE /* Information is UTF-16 encoded. */
|
||||
#ifdef XML_UNICODE_WCHAR_T
|
||||
typedef wchar_t XML_Char;
|
||||
typedef wchar_t XML_LChar;
|
||||
#else
|
||||
typedef unsigned short XML_Char;
|
||||
typedef char XML_LChar;
|
||||
#endif /* XML_UNICODE_WCHAR_T */
|
||||
#else /* Information is UTF-8 encoded. */
|
||||
typedef char XML_Char;
|
||||
typedef char XML_LChar;
|
||||
#endif /* XML_UNICODE */
|
||||
|
||||
#ifdef XML_LARGE_SIZE /* Use large integers for file/stream positions. */
|
||||
#if defined(XML_USE_MSC_EXTENSIONS) && _MSC_VER < 1400
|
||||
typedef __int64 XML_Index;
|
||||
typedef unsigned __int64 XML_Size;
|
||||
#else
|
||||
typedef long long XML_Index;
|
||||
typedef unsigned long long XML_Size;
|
||||
#endif
|
||||
#else
|
||||
typedef long XML_Index;
|
||||
typedef unsigned long XML_Size;
|
||||
#endif /* XML_LARGE_SIZE */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* not Expat_External_INCLUDED */
|
BIN
expat/libexpat.lib
Normal file
BIN
expat/libexpat.lib
Normal file
Binary file not shown.
499
file.c
Normal file
499
file.c
Normal file
|
@ -0,0 +1,499 @@
|
|||
/*
|
||||
* Sega Model 3 Emulator
|
||||
* Copyright (C) 2003 Bart Trzynadlowski, Ville Linde, Stefano Teso
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 (license.txt); if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* file.c
|
||||
*
|
||||
* File access and ZIP file support
|
||||
*
|
||||
*/
|
||||
|
||||
#include "model3.h"
|
||||
#include "file.h"
|
||||
#include "unzip/unzip.h" /* ZLIB */
|
||||
|
||||
static unzFile zip_file;
|
||||
|
||||
/* zip_get_file_size
|
||||
*
|
||||
* Gets the uncompressed size of a file in the ZIP file
|
||||
* Returns the file size or 0 if the file is not found (or the file size is 0)
|
||||
*/
|
||||
|
||||
static UINT32 zip_get_file_size(const char* file)
|
||||
{
|
||||
unz_file_info file_info;
|
||||
|
||||
if( unzLocateFile(zip_file, file, 2) != UNZ_OK )
|
||||
return 0;
|
||||
|
||||
if( unzGetCurrentFileInfo(zip_file, &file_info, NULL, 0, NULL, 0, NULL, 0) != UNZ_OK )
|
||||
return 0;
|
||||
|
||||
return file_info.uncompressed_size;
|
||||
}
|
||||
|
||||
/* zip_read_file
|
||||
*
|
||||
* Reads the specified file to a buffer
|
||||
* Returns TRUE if successful otherwise FALSE
|
||||
*/
|
||||
|
||||
static BOOL zip_read_file(const char* file, UINT8* buffer, UINT32 size)
|
||||
{
|
||||
if( unzLocateFile(zip_file, file, 2) != UNZ_OK )
|
||||
return FALSE;
|
||||
|
||||
if( unzOpenCurrentFile(zip_file) != UNZ_OK )
|
||||
return FALSE;
|
||||
|
||||
if( unzReadCurrentFile(zip_file, buffer, size) < 0 ) {
|
||||
unzCloseCurrentFile(zip_file);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
unzCloseCurrentFile(zip_file);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* zip_find_name_for_crc
|
||||
*
|
||||
* Finds a matching file name for a crc
|
||||
* Returns TRUE if crc was found. The file name is copied to the supplied string pointer.
|
||||
*
|
||||
*/
|
||||
|
||||
static BOOL zip_find_name_for_crc(UINT32 crc, char* file)
|
||||
{
|
||||
unz_file_info file_info;
|
||||
char filename[4096];
|
||||
|
||||
if( unzGoToFirstFile(zip_file) != UNZ_OK )
|
||||
return FALSE;
|
||||
|
||||
do
|
||||
{
|
||||
if( unzGetCurrentFileInfo(zip_file, &file_info, filename, sizeof(filename), NULL, 0, NULL, 0) != UNZ_OK )
|
||||
return FALSE;
|
||||
|
||||
if( file_info.crc == crc ) {
|
||||
strcpy( file, filename );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
} while( unzGoToNextFile(zip_file) == UNZ_OK );
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* zip_open
|
||||
*
|
||||
* Opens a zip file. Must be called before any of the above functions !
|
||||
*/
|
||||
|
||||
static BOOL zip_open(const char* file)
|
||||
{
|
||||
zip_file = unzOpen(file);
|
||||
if( zip_file == NULL )
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* zip_close
|
||||
*
|
||||
* Closes the zip file
|
||||
*/
|
||||
|
||||
static void zip_close(void)
|
||||
{
|
||||
unzClose(zip_file);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* File access functions */
|
||||
|
||||
static BOOL zip_directory = FALSE;
|
||||
static char directory_path[4096];
|
||||
|
||||
/* TODO: set_directory and set_directory_zip could be merged together */
|
||||
|
||||
/* set_directory
|
||||
*
|
||||
* Sets the current directory
|
||||
*
|
||||
*/
|
||||
|
||||
BOOL set_directory(char* path, ...)
|
||||
{
|
||||
char string[4096];
|
||||
va_list l;
|
||||
|
||||
va_start(l, path);
|
||||
vsprintf(string, path, l);
|
||||
va_end(l);
|
||||
|
||||
zip_directory = FALSE;
|
||||
strcpy( directory_path, string );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* set_directory_zip
|
||||
*
|
||||
* Sets a zip file as current directory
|
||||
*
|
||||
*/
|
||||
|
||||
BOOL set_directory_zip(char* file, ...)
|
||||
{
|
||||
char string[4096];
|
||||
va_list l;
|
||||
|
||||
va_start(l, file);
|
||||
vsprintf(string, file, l);
|
||||
va_end(l);
|
||||
|
||||
/* Close the old zip file */
|
||||
zip_close();
|
||||
|
||||
if( !zip_open(string) )
|
||||
return FALSE;
|
||||
|
||||
zip_directory = TRUE;
|
||||
strcpy( directory_path, string );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* get_file_size
|
||||
*
|
||||
* Returns the file size
|
||||
*
|
||||
*/
|
||||
|
||||
size_t get_file_size(const char* file)
|
||||
{
|
||||
FILE* f;
|
||||
size_t length = 0;
|
||||
char path[4096];
|
||||
|
||||
if( zip_directory ) {
|
||||
length = zip_get_file_size(file);
|
||||
}
|
||||
else {
|
||||
sprintf( path, "%s/%s", directory_path, file );
|
||||
f = fopen( path, "rb" );
|
||||
if( f == NULL )
|
||||
return 0;
|
||||
|
||||
fseek( f, 0, SEEK_END );
|
||||
length = ftell(f);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
/* read_file
|
||||
*
|
||||
* Reads the content of the file to a buffer
|
||||
*
|
||||
*/
|
||||
|
||||
BOOL read_file(const char* file, UINT8* buffer, UINT32 size)
|
||||
{
|
||||
FILE* f;
|
||||
char path[4096];
|
||||
|
||||
if( zip_directory ) {
|
||||
return zip_read_file( file, buffer, size );
|
||||
}
|
||||
else {
|
||||
/* Build a full path to file */
|
||||
strcpy( path, directory_path );
|
||||
strcat( path, "/" );
|
||||
strcat( path, file );
|
||||
|
||||
f = fopen( path, "rb" );
|
||||
if( f == NULL )
|
||||
return FALSE;
|
||||
|
||||
fseek( f, 0, SEEK_SET );
|
||||
if( fread(buffer, sizeof(UINT8), size, f) != (size_t)size ) {
|
||||
fclose(f);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* write_file
|
||||
*
|
||||
* Writes the contents of a buffer to a file
|
||||
*
|
||||
*/
|
||||
|
||||
BOOL write_file(const char* file, UINT8* buffer, UINT32 size)
|
||||
{
|
||||
FILE* f;
|
||||
char path[4096];
|
||||
|
||||
/* Whoops. No saving to a zip file :) */
|
||||
if( zip_directory )
|
||||
return FALSE;
|
||||
|
||||
/* Build a full path to file */
|
||||
strcpy( path, directory_path );
|
||||
strcat( path, "/" );
|
||||
strcat( path, file );
|
||||
|
||||
f = fopen( path, "wb" );
|
||||
|
||||
fseek( f, 0, SEEK_SET );
|
||||
if( fwrite(buffer, sizeof(UINT8), size, f) != (size_t)size ) {
|
||||
fclose(f);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* get_file_size_crc
|
||||
*
|
||||
* Returns the file size of a file specified by crc
|
||||
*
|
||||
*/
|
||||
|
||||
size_t get_file_size_crc(UINT32 crc)
|
||||
{
|
||||
char file[4096];
|
||||
|
||||
/* only zip files supported */
|
||||
if( !zip_directory )
|
||||
return 0;
|
||||
|
||||
if( !zip_find_name_for_crc(crc, file) )
|
||||
return 0;
|
||||
|
||||
return zip_get_file_size(file);
|
||||
}
|
||||
|
||||
/* read_file_crc
|
||||
*
|
||||
* Reads the contents of a file specified by crc
|
||||
*
|
||||
*/
|
||||
|
||||
BOOL read_file_crc(UINT32 crc, UINT8* buffer, UINT32 size)
|
||||
{
|
||||
char file[4096];
|
||||
|
||||
/* only zip files supported */
|
||||
if( !zip_directory )
|
||||
return FALSE;
|
||||
|
||||
if( !zip_find_name_for_crc(crc, file) )
|
||||
return FALSE;
|
||||
|
||||
return zip_read_file(file, buffer, size);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* open_file
|
||||
*
|
||||
* Opens a file
|
||||
*
|
||||
*/
|
||||
|
||||
FILE* open_file(UINT32 flags, char* file, ...)
|
||||
{
|
||||
char string[4096];
|
||||
char path[4096];
|
||||
char mode[3];
|
||||
char* m = mode;
|
||||
va_list l;
|
||||
|
||||
/* zip files are not supported this way */
|
||||
if( zip_directory )
|
||||
return 0;
|
||||
|
||||
va_start(l, file);
|
||||
vsprintf(string, file, l);
|
||||
va_end(l);
|
||||
|
||||
/* Build full path */
|
||||
if (strlen(directory_path) <= 0)
|
||||
{
|
||||
sprintf(path, "%s", string);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(path, "%s/%s", directory_path, string);
|
||||
}
|
||||
|
||||
/* Set file access mode */
|
||||
if( flags & FILE_READ )
|
||||
sprintf(&m[0], "r");
|
||||
else
|
||||
sprintf(&m[0], "w");
|
||||
|
||||
if( flags & FILE_BINARY )
|
||||
sprintf(&m[1], "b" );
|
||||
else
|
||||
sprintf(&m[1], "t" );
|
||||
|
||||
m[2] = '\0';
|
||||
return fopen(path, m);
|
||||
}
|
||||
|
||||
/* close_file
|
||||
*
|
||||
* Closes the file
|
||||
*
|
||||
*/
|
||||
|
||||
void close_file(FILE* file)
|
||||
{
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
/* read_from_file
|
||||
*
|
||||
* Reads n bytes from file to a buffer
|
||||
*
|
||||
*/
|
||||
|
||||
BOOL read_from_file(FILE* file, UINT8* buffer, UINT32 size)
|
||||
{
|
||||
if( file == NULL )
|
||||
return FALSE;
|
||||
|
||||
if( fread(buffer, sizeof(UINT8), size, file) != (size_t)size )
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* write_to_file
|
||||
*
|
||||
* Writes n bytes to file
|
||||
*
|
||||
*/
|
||||
|
||||
BOOL write_to_file(FILE* file, UINT8* buffer, UINT32 size)
|
||||
{
|
||||
if( file == NULL )
|
||||
return FALSE;
|
||||
|
||||
if( fwrite(buffer, sizeof(UINT8), size, file) != (size_t)size )
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* get_file_size
|
||||
*
|
||||
* Gets the file size
|
||||
*
|
||||
*/
|
||||
size_t get_open_file_size(FILE *file)
|
||||
{
|
||||
size_t length;
|
||||
int current_pos = ftell(file);
|
||||
fseek(file, 0, SEEK_END);
|
||||
length = ftell(file);
|
||||
fseek(file, current_pos, SEEK_SET);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Load a file to a buffer.
|
||||
*/
|
||||
|
||||
int load_file(char *path, UINT8 * dest, int size)
|
||||
{
|
||||
FILE * fp;
|
||||
int length;
|
||||
|
||||
if(path == NULL || dest == NULL)
|
||||
return(-1);
|
||||
|
||||
if((fp = fopen(path, "rb")) == NULL)
|
||||
return(-1);
|
||||
|
||||
fseek(fp, 0, SEEK_END);
|
||||
length = ftell(fp);
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
|
||||
if (length <= 0)
|
||||
return -1;
|
||||
|
||||
if (fread(dest, 1, size, fp) != (size_t)length) // file size mismatch
|
||||
return -1;
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
static void word_swap(UINT8 *src, int size)
|
||||
{
|
||||
while (size -= 4)
|
||||
{
|
||||
*((UINT32 *) src) = BSWAP32(*((UINT32 *) src));
|
||||
src += sizeof(UINT32);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Save a buffer to a file.
|
||||
*/
|
||||
|
||||
void save_file(char *path, UINT8 *src, int size, BOOL byte_reversed)
|
||||
{
|
||||
FILE * fp;
|
||||
|
||||
if (byte_reversed)
|
||||
{
|
||||
word_swap(src, size);
|
||||
}
|
||||
|
||||
fp = fopen(path, "wb");
|
||||
if(fp != NULL)
|
||||
{
|
||||
fwrite(src, 1, size, fp);
|
||||
fclose(fp);
|
||||
message(0, "Wrote %s", path);
|
||||
}
|
||||
else
|
||||
{
|
||||
message(0, "Failed to write %s", path);
|
||||
}
|
||||
|
||||
if (byte_reversed)
|
||||
{
|
||||
word_swap(src, size);
|
||||
}
|
||||
}
|
50
file.h
Normal file
50
file.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Sega Model 3 Emulator
|
||||
* Copyright (C) 2003 Bart Trzynadlowski, Ville Linde, Stefano Teso
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 (license.txt); if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_FILE_H
|
||||
#define INCLUDED_FILE_H
|
||||
|
||||
#include "model3.h"
|
||||
|
||||
#define FILE_READ 0x1
|
||||
#define FILE_WRITE 0x2
|
||||
#define FILE_BINARY 0x4
|
||||
#define FILE_TEXT 0x8
|
||||
|
||||
/* Functions */
|
||||
|
||||
FILE* open_file(UINT32, char*, ...);
|
||||
void close_file(FILE*);
|
||||
BOOL read_from_file(FILE*, UINT8*, UINT32);
|
||||
BOOL write_to_file(FILE*, UINT8*, UINT32);
|
||||
size_t get_open_file_size(FILE *);
|
||||
|
||||
size_t get_file_size(const char*);
|
||||
BOOL read_file(const char*, UINT8*, UINT32);
|
||||
BOOL write_file(const char*, UINT8*, UINT32);
|
||||
|
||||
size_t get_file_size_crc(UINT32);
|
||||
BOOL read_file_crc(UINT32, UINT8*, UINT32);
|
||||
|
||||
BOOL set_directory(char*, ...);
|
||||
BOOL set_directory_zip(char*, ...);
|
||||
|
||||
int load_file(char *path, UINT8 * dest, int size);
|
||||
void save_file(char *path, UINT8 *src, int size, BOOL byte_reversed);
|
||||
|
||||
#endif /* INCLUDED_FILE_H */
|
1256
osd_common/disasm.c
Normal file
1256
osd_common/disasm.c
Normal file
File diff suppressed because it is too large
Load diff
31
osd_common/disasm.h
Normal file
31
osd_common/disasm.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Sega Model 3 Emulator
|
||||
* Copyright (C) 2003 Bart Trzynadlowski, Ville Linde, Stefano Teso
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 (license.txt); if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* osd_common/disasm.h
|
||||
*
|
||||
* PowerPC disassembler header.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_OSD_COMMON_DISASM_H
|
||||
#define INCLUDED_OSD_COMMON_DISASM_H
|
||||
|
||||
extern BOOL DisassemblePowerPC(UINT32, UINT32, CHAR *, CHAR *, BOOL);
|
||||
|
||||
#endif // INCLUDED_OSD_COMMON_DISASM_H
|
||||
|
1571
osd_common/glrender.c
Normal file
1571
osd_common/glrender.c
Normal file
File diff suppressed because it is too large
Load diff
125
osd_common/osd_common.h
Normal file
125
osd_common/osd_common.h
Normal file
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* Sega Model 3 Emulator
|
||||
* Copyright (C) 2003 Bart Trzynadlowski, Ville Linde, Stefano Teso
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 (license.txt); if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* osd_common/osd_common.h
|
||||
*
|
||||
* Header file which defines the OSD interface. This is included last in
|
||||
* model3.h because it relies on data structures defined there.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_OSD_COMMON_OSD_H
|
||||
#define INCLUDED_OSD_COMMON_OSD_H
|
||||
|
||||
/******************************************************************/
|
||||
/* OSD Includes */
|
||||
/******************************************************************/
|
||||
|
||||
#include "disasm.h" // didn't know where to put it, so I stuck it here ;)
|
||||
|
||||
/******************************************************************/
|
||||
/* OSD Data Structures */
|
||||
/******************************************************************/
|
||||
|
||||
/*
|
||||
* OSD_CONTROLS Structure
|
||||
*
|
||||
* Holds the current state of the controls. Filled by the input code and used
|
||||
* by the control emulation code.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/*
|
||||
* Common to all games
|
||||
*/
|
||||
|
||||
UINT8 system_controls[2]; // maps directly to Fx040004 banks 0 and 1
|
||||
UINT8 game_controls[2]; // map directly to Fx040008 and Fx04000C
|
||||
|
||||
/*
|
||||
* For games with guns
|
||||
*
|
||||
* The gun positions are reported in screen coordinates. The emulator will
|
||||
* make the appropriate adjustments. Gun coordinates should range from
|
||||
* (0,0), the upper-left corner, to (495,383), the lower-right corner.
|
||||
*/
|
||||
|
||||
UINT gun_x[2], gun_y[2]; // gun positions for players 1 (0) and 2 (1)
|
||||
BOOL gun_acquired[2]; // gun acquired status for players 1 and 2
|
||||
// 0 = acquired, 1 = lost
|
||||
|
||||
// Analog controls
|
||||
int analog_axis[8];
|
||||
} OSD_CONTROLS;
|
||||
|
||||
/******************************************************************/
|
||||
/* Executable memory allocation */
|
||||
/******************************************************************/
|
||||
|
||||
extern void *malloc_exec(int length);
|
||||
extern void free_exec(void *ptr);
|
||||
|
||||
/******************************************************************/
|
||||
/* OSD GUI */
|
||||
/******************************************************************/
|
||||
|
||||
extern void osd_message();
|
||||
extern void osd_error();
|
||||
|
||||
/******************************************************************/
|
||||
/* Renderer */
|
||||
/******************************************************************/
|
||||
|
||||
extern void osd_renderer_invalidate_textures(UINT x, UINT y, UINT w, UINT h, UINT8 *texture_sheet);
|
||||
extern void osd_renderer_draw_model(UINT32 *, UINT32, BOOL);
|
||||
extern void osd_renderer_multiply_matrix(MATRIX);
|
||||
extern void osd_renderer_translate_matrix(float, float, float);
|
||||
extern void osd_renderer_push_matrix(void);
|
||||
extern void osd_renderer_pop_matrix(void);
|
||||
extern void osd_renderer_set_light(INT, LIGHT *);
|
||||
extern void osd_renderer_set_viewport(const VIEWPORT *);
|
||||
extern void osd_renderer_set_coordinate_system(const MATRIX);
|
||||
extern void osd_renderer_clear(BOOL, BOOL);
|
||||
extern void osd_renderer_set_color_offset(BOOL, FLOAT32, FLOAT32, FLOAT32);
|
||||
extern void osd_renderer_draw_layer(int layer, UINT32 color_offset);
|
||||
extern void osd_renderer_get_layer_buffer(int layer_num, UINT8 **buffer, int *pitch);
|
||||
extern void osd_renderer_free_layer_buffer(UINT);
|
||||
extern void osd_renderer_get_palette_buffer(UINT32 **, int *, int *);
|
||||
extern void osd_renderer_free_palette_buffer(void);
|
||||
extern void osd_renderer_blit(void);
|
||||
extern void osd_renderer_begin_3d_scene(void);
|
||||
extern void osd_renderer_end_3d_scene(void);
|
||||
extern void osd_renderer_draw_text(int x, int y, const char* string, DWORD color, BOOL shadow);
|
||||
|
||||
|
||||
|
||||
/******************************************************************/
|
||||
/* Sound Output */
|
||||
/******************************************************************/
|
||||
|
||||
/******************************************************************/
|
||||
/* Input */
|
||||
/******************************************************************/
|
||||
|
||||
extern OSD_CONTROLS * osd_input_update_controls(void);
|
||||
extern BOOL osd_input_init(void);
|
||||
extern void osd_input_shutdown(void);
|
||||
|
||||
#endif // INCLUDED_OSD_COMMON_OSD_H
|
||||
|
39
osd_common/osd_gl.h
Normal file
39
osd_common/osd_gl.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Sega Model 3 Emulator
|
||||
* Copyright (C) 2003 Bart Trzynadlowski, Ville Linde, Stefano Teso
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 (license.txt); if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* osd_common/osd_gl.h
|
||||
*
|
||||
* Header file which exposes the OSD OpenGL interface. These are functions
|
||||
* which the OSD code must call.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_OSD_COMMON_OSD_GL_H
|
||||
#define INCLUDED_OSD_COMMON_OSD_GL_H
|
||||
|
||||
/******************************************************************/
|
||||
/* OSD OpenGL Functions */
|
||||
/******************************************************************/
|
||||
|
||||
extern BOOL osd_gl_check_extension(CHAR *);
|
||||
extern void * osd_gl_get_proc_address(const CHAR *);
|
||||
extern void osd_gl_set_mode(UINT, UINT);
|
||||
extern void osd_gl_unset_mode(void);
|
||||
|
||||
#endif // INCLUDED_OSD_COMMON_OSD_GL_H
|
||||
|
1083
ppc_drc/genx86.c
Normal file
1083
ppc_drc/genx86.c
Normal file
File diff suppressed because it is too large
Load diff
167
ppc_drc/genx86.h
Normal file
167
ppc_drc/genx86.h
Normal file
|
@ -0,0 +1,167 @@
|
|||
typedef enum
|
||||
{
|
||||
JUMP_TYPE_NONE = 0,
|
||||
JUMP_TYPE_BACKWARDS = 1,
|
||||
JUMP_TYPE_FORWARD = 2,
|
||||
} JUMP_TYPE;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *pointer;
|
||||
JUMP_TYPE jump_type;
|
||||
} JUMP_TARGET;
|
||||
|
||||
enum
|
||||
{
|
||||
REG_EAX = 0,
|
||||
REG_ECX = 1,
|
||||
REG_EDX = 2,
|
||||
REG_EBX = 3,
|
||||
REG_ESP = 4,
|
||||
REG_EBP = 5,
|
||||
REG_ESI = 6,
|
||||
REG_EDI = 7
|
||||
} X86_REGS;
|
||||
|
||||
enum
|
||||
{
|
||||
REG_AL = 0,
|
||||
REG_CL = 1,
|
||||
REG_DL = 2,
|
||||
REG_BL = 3,
|
||||
REG_AH = 4,
|
||||
REG_CH = 5,
|
||||
REG_DH = 6,
|
||||
REG_BH = 7
|
||||
} X86_REGS8;
|
||||
|
||||
enum
|
||||
{
|
||||
REG_AX = 0,
|
||||
REG_CX = 1,
|
||||
REG_DX = 2,
|
||||
REG_BX = 3,
|
||||
REG_SP = 4,
|
||||
REG_BP = 5,
|
||||
REG_SI = 6,
|
||||
REG_DI = 7
|
||||
} X86_REGS16;
|
||||
|
||||
enum
|
||||
{
|
||||
REG_XMM0 = 0,
|
||||
REG_XMM1 = 1,
|
||||
REG_XMM2 = 2,
|
||||
REG_XMM3 = 3,
|
||||
REG_XMM4 = 4,
|
||||
REG_XMM5 = 5,
|
||||
REG_XMM6 = 6,
|
||||
REG_XMM7 = 7,
|
||||
} X86_REGS_SSE2;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ADD,
|
||||
ADDI,
|
||||
ADDIM,
|
||||
ADDMR,
|
||||
ADC,
|
||||
ADCI,
|
||||
ADCMR,
|
||||
AND,
|
||||
ANDI,
|
||||
ANDIM,
|
||||
ANDMR,
|
||||
BSR,
|
||||
BSWAP,
|
||||
BTIM,
|
||||
BTRI,
|
||||
CALL,
|
||||
CALLI,
|
||||
CMOVAMR,
|
||||
CMOVBMR,
|
||||
CMOVGMR,
|
||||
CMOVLMR,
|
||||
CMOVZMR,
|
||||
CMP,
|
||||
CMPI,
|
||||
CMPIM,
|
||||
CMPMR,
|
||||
CVTSD2SS,
|
||||
CVTSS2SD,
|
||||
IDIV,
|
||||
IMUL,
|
||||
JA,
|
||||
JAE,
|
||||
JB,
|
||||
JG,
|
||||
JL,
|
||||
JMP,
|
||||
JMPI,
|
||||
JMPM,
|
||||
JMPR,
|
||||
JNS,
|
||||
JNZ,
|
||||
JZ,
|
||||
MOV,
|
||||
MOVI,
|
||||
MOVIM,
|
||||
MOVMR,
|
||||
MOVRM,
|
||||
MOVR8M8,
|
||||
MOVM8R8,
|
||||
MOVS_R8R32,
|
||||
MOVS_R16R32,
|
||||
MOVZ_M8R32,
|
||||
MOVZ_R8R32,
|
||||
MOVZ_R16R32,
|
||||
MOVDRX,
|
||||
MOVDXR,
|
||||
MOVQMX,
|
||||
MOVQXM,
|
||||
MUL,
|
||||
NEG,
|
||||
NOT,
|
||||
OR,
|
||||
ORI,
|
||||
ORIM,
|
||||
ORMR,
|
||||
POP,
|
||||
POPAD,
|
||||
PUSH,
|
||||
PUSHAD,
|
||||
PUSHI,
|
||||
RET,
|
||||
ROLCL,
|
||||
ROLI,
|
||||
SETCR8,
|
||||
SETNCR8,
|
||||
SETZR8,
|
||||
SHLCL,
|
||||
SHLI,
|
||||
SHRCL,
|
||||
SHRI,
|
||||
SUB,
|
||||
SUBI,
|
||||
SUBIM,
|
||||
SUBMR,
|
||||
TESTI,
|
||||
XCHGR8R8,
|
||||
XOR,
|
||||
XORI,
|
||||
XORMR,
|
||||
} GENX86_OPCODE;
|
||||
|
||||
void gen(GENX86_OPCODE opcode, INT32 dst_param, INT32 src_param);
|
||||
void gen_jmp_target(JUMP_TARGET *target);
|
||||
void gen_jmp(GENX86_OPCODE opcode, JUMP_TARGET *target);
|
||||
void gen_jmp_rpr(INT32 reg1, INT32 reg2);
|
||||
void gen_mov_dpr_to_reg(INT32 dst_reg, INT32 disp, INT32 disp_reg);
|
||||
void gen_mov_dprs_to_reg(INT32 dst_reg, INT32 disp, INT32 disp_reg, INT32 disp_reg_scale);
|
||||
void gen_mov_reg_to_dpr(INT32 src_reg, INT32 disp, INT32 disp_reg);
|
||||
void gen_reset_cache(void);
|
||||
UINT8 *gen_get_cache_pos(void);
|
||||
UINT32 gen_get_instruction_amount(void);
|
||||
void init_jmp_target(JUMP_TARGET *target);
|
||||
void init_genx86(void);
|
||||
void shutdown_genx86(void);
|
1544
ppc_drc/ppc_drc.c
Normal file
1544
ppc_drc/ppc_drc.c
Normal file
File diff suppressed because it is too large
Load diff
0
ppc_drc/ppc_drc.h
Normal file
0
ppc_drc/ppc_drc.h
Normal file
4123
ppc_drc/ppc_drc_ops.c
Normal file
4123
ppc_drc/ppc_drc_ops.c
Normal file
File diff suppressed because it is too large
Load diff
808
ppc_itp/ppc.c
Normal file
808
ppc_itp/ppc.c
Normal file
|
@ -0,0 +1,808 @@
|
|||
/* IBM/Motorola PowerPC 4xx/6xx Emulator */
|
||||
|
||||
#include "model3.h"
|
||||
#include "ppc.h"
|
||||
|
||||
void ppc603_exception(int exception);
|
||||
void ppc603_check_interrupts(void);
|
||||
|
||||
#define RD ((op >> 21) & 0x1F)
|
||||
#define RT ((op >> 21) & 0x1f)
|
||||
#define RS ((op >> 21) & 0x1f)
|
||||
#define RA ((op >> 16) & 0x1f)
|
||||
#define RB ((op >> 11) & 0x1f)
|
||||
#define RC ((op >> 6) & 0x1f)
|
||||
|
||||
#define MB ((op >> 6) & 0x1f)
|
||||
#define ME ((op >> 1) & 0x1f)
|
||||
#define SH ((op >> 11) & 0x1f)
|
||||
#define BO ((op >> 21) & 0x1f)
|
||||
#define BI ((op >> 16) & 0x1f)
|
||||
#define CRFD ((op >> 23) & 0x7)
|
||||
#define CRFA ((op >> 18) & 0x7)
|
||||
#define FXM ((op >> 12) & 0xff)
|
||||
#define SPR (((op >> 16) & 0x1f) | ((op >> 6) & 0x3e0))
|
||||
|
||||
#define SIMM16 (INT32)(INT16)(op & 0xffff)
|
||||
#define UIMM16 (UINT32)(op & 0xffff)
|
||||
|
||||
#define RCBIT (op & 0x1)
|
||||
#define OEBIT (op & 0x400)
|
||||
#define AABIT (op & 0x2)
|
||||
#define LKBIT (op & 0x1)
|
||||
|
||||
#define REG(x) (ppc.r[x])
|
||||
#define LR (ppc.lr)
|
||||
#define CTR (ppc.ctr)
|
||||
#define XER (ppc.xer)
|
||||
#define CR(x) (ppc.cr[x])
|
||||
#define MSR (ppc.msr)
|
||||
#define SRR0 (ppc.srr0)
|
||||
#define SRR1 (ppc.srr1)
|
||||
#define SRR2 (ppc.srr2)
|
||||
#define SRR3 (ppc.srr3)
|
||||
#define EVPR (ppc.evpr)
|
||||
#define EXIER (ppc.exier)
|
||||
#define EXISR (ppc.exisr)
|
||||
#define DEC (ppc.dec)
|
||||
|
||||
|
||||
// Stuff added for the 6xx
|
||||
#define FPR(x) (ppc.fpr[x])
|
||||
#define FM ((op >> 17) & 0xFF)
|
||||
#define SPRF (((op >> 6) & 0x3E0) | ((op >> 16) & 0x1F))
|
||||
|
||||
|
||||
#define CHECK_SUPERVISOR() \
|
||||
if((ppc.msr & 0x4000) != 0){ \
|
||||
}
|
||||
|
||||
#define CHECK_FPU_AVAILABLE() \
|
||||
if((ppc.msr & 0x2000) == 0){ \
|
||||
}
|
||||
|
||||
static UINT32 ppc_field_xlat[256];
|
||||
|
||||
|
||||
|
||||
#define FPSCR_FX 0x80000000
|
||||
#define FPSCR_FEX 0x40000000
|
||||
#define FPSCR_VX 0x20000000
|
||||
#define FPSCR_OX 0x10000000
|
||||
#define FPSCR_UX 0x08000000
|
||||
#define FPSCR_ZX 0x04000000
|
||||
#define FPSCR_XX 0x02000000
|
||||
|
||||
|
||||
|
||||
#define BITMASK_0(n) (UINT32)(((UINT64)1 << n) - 1)
|
||||
#define CRBIT(x) ((ppc.cr[x / 4] & (1 << (3 - (x % 4)))) ? 1 : 0)
|
||||
#define _BIT(n) (1 << (n))
|
||||
#define GET_ROTATE_MASK(mb,me) (ppc_rotate_mask[mb][me])
|
||||
#define ADD_CA(r,a,b) ((UINT32)r < (UINT32)a)
|
||||
#define SUB_CA(r,a,b) (!((UINT32)a < (UINT32)b))
|
||||
#define ADD_OV(r,a,b) ((~((a) ^ (b)) & ((a) ^ (r))) & 0x80000000)
|
||||
#define SUB_OV(r,a,b) (( ((a) ^ (b)) & ((a) ^ (r))) & 0x80000000)
|
||||
|
||||
#define XER_SO 0x80000000
|
||||
#define XER_OV 0x40000000
|
||||
#define XER_CA 0x20000000
|
||||
|
||||
#define MSR_POW 0x00040000 /* Power Management Enable */
|
||||
#define MSR_WE 0x00040000
|
||||
#define MSR_CE 0x00020000
|
||||
#define MSR_ILE 0x00010000 /* Interrupt Little Endian Mode */
|
||||
#define MSR_EE 0x00008000 /* External Interrupt Enable */
|
||||
#define MSR_PR 0x00004000 /* Problem State */
|
||||
#define MSR_FP 0x00002000 /* Floating Point Available */
|
||||
#define MSR_ME 0x00001000 /* Machine Check Enable */
|
||||
#define MSR_FE0 0x00000800
|
||||
#define MSR_SE 0x00000400 /* Single Step Trace Enable */
|
||||
#define MSR_BE 0x00000200 /* Branch Trace Enable */
|
||||
#define MSR_DE 0x00000200
|
||||
#define MSR_FE1 0x00000100
|
||||
#define MSR_IP 0x00000040 /* Interrupt Prefix */
|
||||
#define MSR_IR 0x00000020 /* Instruction Relocate */
|
||||
#define MSR_DR 0x00000010 /* Data Relocate */
|
||||
#define MSR_PE 0x00000008
|
||||
#define MSR_PX 0x00000004
|
||||
#define MSR_RI 0x00000002 /* Recoverable Interrupt Enable */
|
||||
#define MSR_LE 0x00000001
|
||||
|
||||
#define TSR_ENW 0x80000000
|
||||
#define TSR_WIS 0x40000000
|
||||
|
||||
#define BYTE_REVERSE16(x) ((((x) >> 8) & 0xff) | (((x) << 8) & 0xff00))
|
||||
#define BYTE_REVERSE32(x) ((((x) >> 24) & 0xff) | (((x) >> 8) & 0xff00) | (((x) << 8) & 0xff0000) | (((x) << 24) & 0xff000000))
|
||||
|
||||
typedef union {
|
||||
UINT64 id;
|
||||
double fd;
|
||||
} FPR;
|
||||
|
||||
typedef union {
|
||||
UINT32 i;
|
||||
float f;
|
||||
} FPR32;
|
||||
|
||||
typedef struct {
|
||||
UINT32 u;
|
||||
UINT32 l;
|
||||
} BATENT;
|
||||
|
||||
|
||||
typedef struct {
|
||||
UINT32 r[32];
|
||||
UINT32 pc;
|
||||
UINT32 npc;
|
||||
|
||||
UINT32 *op;
|
||||
|
||||
UINT32 lr;
|
||||
UINT32 ctr;
|
||||
UINT32 xer;
|
||||
UINT32 msr;
|
||||
UINT8 cr[8];
|
||||
UINT32 pvr;
|
||||
UINT32 srr0;
|
||||
UINT32 srr1;
|
||||
UINT32 srr2;
|
||||
UINT32 srr3;
|
||||
UINT32 hid0;
|
||||
UINT32 hid1;
|
||||
UINT32 hid2;
|
||||
UINT32 sdr1;
|
||||
UINT32 sprg[4];
|
||||
|
||||
UINT32 dsisr;
|
||||
UINT32 dar;
|
||||
UINT32 ear;
|
||||
UINT32 dmiss;
|
||||
UINT32 dcmp;
|
||||
UINT32 hash1;
|
||||
UINT32 hash2;
|
||||
UINT32 imiss;
|
||||
UINT32 icmp;
|
||||
UINT32 rpa;
|
||||
|
||||
|
||||
BATENT ibat[4];
|
||||
BATENT dbat[4];
|
||||
|
||||
UINT32 evpr;
|
||||
UINT32 exier;
|
||||
UINT32 exisr;
|
||||
UINT32 bear;
|
||||
UINT32 besr;
|
||||
UINT32 iocr;
|
||||
UINT32 br[8];
|
||||
UINT32 iabr;
|
||||
UINT32 esr;
|
||||
UINT32 iccr;
|
||||
UINT32 dccr;
|
||||
UINT32 pit;
|
||||
UINT32 pit_counter;
|
||||
UINT32 pit_int_enable;
|
||||
UINT32 tsr;
|
||||
UINT32 dbsr;
|
||||
UINT32 sgr;
|
||||
UINT32 pid;
|
||||
|
||||
int reserved;
|
||||
UINT32 reserved_address;
|
||||
|
||||
int interrupt_pending;
|
||||
int external_int;
|
||||
|
||||
UINT64 tb; /* 56-bit timebase register */
|
||||
|
||||
int (*irq_callback)(int irqline);
|
||||
|
||||
PPC_FETCH_REGION cur_fetch;
|
||||
PPC_FETCH_REGION * fetch;
|
||||
|
||||
// STUFF added for the 6xx series
|
||||
UINT32 dec, dec_frac;
|
||||
UINT32 fpscr;
|
||||
|
||||
FPR fpr[32];
|
||||
UINT32 sr[16];
|
||||
|
||||
#if HAS_PPC603
|
||||
int is603;
|
||||
#endif
|
||||
#if HAS_PPC602
|
||||
int is602;
|
||||
#endif
|
||||
} PPC_REGS;
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
int code;
|
||||
int subcode;
|
||||
void (* handler)(UINT32);
|
||||
} PPC_OPCODE;
|
||||
|
||||
|
||||
|
||||
static int ppc_icount;
|
||||
static int ppc_tb_base_icount;
|
||||
static int ppc_dec_base_icount;
|
||||
static int ppc_dec_trigger_cycle;
|
||||
static int bus_freq_multiplier = 1;
|
||||
static PPC_REGS ppc;
|
||||
static UINT32 ppc_rotate_mask[32][32];
|
||||
|
||||
|
||||
|
||||
static void ppc_change_pc(UINT32 newpc)
|
||||
{
|
||||
UINT i;
|
||||
|
||||
if (ppc.cur_fetch.start <= newpc && newpc <= ppc.cur_fetch.end)
|
||||
{
|
||||
ppc.op = (UINT32 *)((UINT32)ppc.cur_fetch.ptr + (UINT32)(newpc - ppc.cur_fetch.start));
|
||||
return;
|
||||
}
|
||||
|
||||
for(i = 0; ppc.fetch[i].ptr != NULL; i++)
|
||||
{
|
||||
if (ppc.fetch[i].start <= newpc && newpc <= ppc.fetch[i].end)
|
||||
{
|
||||
ppc.cur_fetch.start = ppc.fetch[i].start;
|
||||
ppc.cur_fetch.end = ppc.fetch[i].end;
|
||||
ppc.cur_fetch.ptr = ppc.fetch[i].ptr;
|
||||
|
||||
ppc.op = (UINT32 *)((UINT32)ppc.cur_fetch.ptr + (UINT32)(newpc - ppc.cur_fetch.start));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
error("Invalid PC %08X, previous PC %08X\n", newpc, ppc.pc);
|
||||
}
|
||||
|
||||
INLINE UINT8 READ8(UINT32 address)
|
||||
{
|
||||
return m3_ppc_read_8(address);
|
||||
}
|
||||
|
||||
INLINE UINT16 READ16(UINT32 address)
|
||||
{
|
||||
return m3_ppc_read_16(address);
|
||||
}
|
||||
|
||||
INLINE UINT32 READ32(UINT32 address)
|
||||
{
|
||||
return m3_ppc_read_32(address);
|
||||
}
|
||||
|
||||
INLINE UINT64 READ64(UINT32 address)
|
||||
{
|
||||
return m3_ppc_read_64(address);
|
||||
}
|
||||
|
||||
INLINE void WRITE8(UINT32 address, UINT8 data)
|
||||
{
|
||||
m3_ppc_write_8(address, data);
|
||||
}
|
||||
|
||||
INLINE void WRITE16(UINT32 address, UINT16 data)
|
||||
{
|
||||
m3_ppc_write_16(address, data);
|
||||
}
|
||||
|
||||
INLINE void WRITE32(UINT32 address, UINT32 data)
|
||||
{
|
||||
m3_ppc_write_32(address, data);
|
||||
}
|
||||
|
||||
INLINE void WRITE64(UINT32 address, UINT64 data)
|
||||
{
|
||||
m3_ppc_write_64(address, data);
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************/
|
||||
|
||||
|
||||
INLINE void SET_CR0(INT32 rd)
|
||||
{
|
||||
if( rd < 0 ) {
|
||||
CR(0) = 0x8;
|
||||
} else if( rd > 0 ) {
|
||||
CR(0) = 0x4;
|
||||
} else {
|
||||
CR(0) = 0x2;
|
||||
}
|
||||
|
||||
if( XER & XER_SO )
|
||||
CR(0) |= 0x1;
|
||||
}
|
||||
|
||||
INLINE void SET_CR1(void)
|
||||
{
|
||||
CR(1) = (ppc.fpscr >> 28) & 0xf;
|
||||
}
|
||||
|
||||
INLINE void SET_ADD_OV(UINT32 rd, UINT32 ra, UINT32 rb)
|
||||
{
|
||||
if( ADD_OV(rd, ra, rb) )
|
||||
XER |= XER_SO | XER_OV;
|
||||
else
|
||||
XER &= ~XER_OV;
|
||||
}
|
||||
|
||||
INLINE void SET_SUB_OV(UINT32 rd, UINT32 ra, UINT32 rb)
|
||||
{
|
||||
if( SUB_OV(rd, ra, rb) )
|
||||
XER |= XER_SO | XER_OV;
|
||||
else
|
||||
XER &= ~XER_OV;
|
||||
}
|
||||
|
||||
INLINE void SET_ADD_CA(UINT32 rd, UINT32 ra, UINT32 rb)
|
||||
{
|
||||
if( ADD_CA(rd, ra, rb) )
|
||||
XER |= XER_CA;
|
||||
else
|
||||
XER &= ~XER_CA;
|
||||
}
|
||||
|
||||
INLINE void SET_SUB_CA(UINT32 rd, UINT32 ra, UINT32 rb)
|
||||
{
|
||||
if( SUB_CA(rd, ra, rb) )
|
||||
XER |= XER_CA;
|
||||
else
|
||||
XER &= ~XER_CA;
|
||||
}
|
||||
|
||||
INLINE UINT32 check_condition_code(UINT32 bo, UINT32 bi)
|
||||
{
|
||||
UINT32 ctr_ok;
|
||||
UINT32 condition_ok;
|
||||
UINT32 bo0 = (bo & 0x10) ? 1 : 0;
|
||||
UINT32 bo1 = (bo & 0x08) ? 1 : 0;
|
||||
UINT32 bo2 = (bo & 0x04) ? 1 : 0;
|
||||
UINT32 bo3 = (bo & 0x02) ? 1 : 0;
|
||||
|
||||
if( bo2 == 0 )
|
||||
--CTR;
|
||||
|
||||
ctr_ok = bo2 | ((CTR != 0) ^ bo3);
|
||||
condition_ok = bo0 | (CRBIT(bi) ^ (~bo1 & 0x1));
|
||||
|
||||
return ctr_ok && condition_ok;
|
||||
}
|
||||
|
||||
INLINE UINT64 ppc_read_timebase(void)
|
||||
{
|
||||
int cycles = ppc_tb_base_icount - ppc_icount;
|
||||
|
||||
// timebase is incremented once every four core clock cycles, so adjust the cycles accordingly
|
||||
return ppc.tb + (cycles / 4);
|
||||
}
|
||||
|
||||
INLINE void ppc_write_timebase_l(UINT32 tbl)
|
||||
{
|
||||
ppc_tb_base_icount = ppc_icount;
|
||||
|
||||
ppc.tb &= ~0xffffffff;
|
||||
ppc.tb |= tbl;
|
||||
}
|
||||
|
||||
INLINE void ppc_write_timebase_h(UINT32 tbh)
|
||||
{
|
||||
ppc_tb_base_icount = ppc_icount;
|
||||
|
||||
ppc.tb &= 0xffffffff;
|
||||
ppc.tb |= (UINT64)(tbh) << 32;
|
||||
}
|
||||
|
||||
INLINE UINT32 read_decrementer(void)
|
||||
{
|
||||
int cycles = ppc_dec_base_icount - ppc_icount;
|
||||
|
||||
// decrementer is decremented once every four bus clock cycles, so adjust the cycles accordingly
|
||||
return DEC - (cycles / (bus_freq_multiplier * 2));
|
||||
}
|
||||
|
||||
INLINE void write_decrementer(UINT32 value)
|
||||
{
|
||||
ppc_dec_base_icount = ppc_icount + (ppc_dec_base_icount - ppc_icount) % (bus_freq_multiplier * 2);
|
||||
|
||||
DEC = value;
|
||||
|
||||
// check if decrementer exception occurs during execution
|
||||
if ((UINT32)(DEC - (ppc_icount / (bus_freq_multiplier * 2))) > (UINT32)(DEC))
|
||||
{
|
||||
ppc_dec_trigger_cycle = ((ppc_icount / (bus_freq_multiplier * 2)) - DEC) * 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
ppc_dec_trigger_cycle = 0x7fffffff;
|
||||
}
|
||||
|
||||
printf("DEC = %08X at %08X\n", value, ppc.pc);
|
||||
}
|
||||
|
||||
/*********************************************************************/
|
||||
|
||||
INLINE void ppc_set_spr(int spr, UINT32 value)
|
||||
{
|
||||
switch (spr)
|
||||
{
|
||||
case SPR_LR: LR = value; return;
|
||||
case SPR_CTR: CTR = value; return;
|
||||
case SPR_XER: XER = value; return;
|
||||
case SPR_SRR0: ppc.srr0 = value; return;
|
||||
case SPR_SRR1: ppc.srr1 = value; return;
|
||||
case SPR_SPRG0: ppc.sprg[0] = value; return;
|
||||
case SPR_SPRG1: ppc.sprg[1] = value; return;
|
||||
case SPR_SPRG2: ppc.sprg[2] = value; return;
|
||||
case SPR_SPRG3: ppc.sprg[3] = value; return;
|
||||
case SPR_PVR: return;
|
||||
|
||||
case SPR603E_DEC:
|
||||
if(((value & 0x80000000) && !(DEC & 0x80000000)) || value == 0)
|
||||
{
|
||||
/* trigger interrupt */
|
||||
ppc.interrupt_pending |= 0x2;
|
||||
ppc603_check_interrupts();
|
||||
}
|
||||
write_decrementer(value);
|
||||
return;
|
||||
|
||||
case SPR603E_TBL_W:
|
||||
case SPR603E_TBL_R: // special 603e case
|
||||
ppc_write_timebase_l(value);
|
||||
return;
|
||||
|
||||
case SPR603E_TBU_R:
|
||||
case SPR603E_TBU_W: // special 603e case
|
||||
ppc_write_timebase_h(value);
|
||||
return;
|
||||
|
||||
case SPR603E_HID0: ppc.hid0 = value; return;
|
||||
case SPR603E_HID1: ppc.hid1 = value; return;
|
||||
case SPR603E_HID2: ppc.hid2 = value; return;
|
||||
|
||||
case SPR603E_DSISR: ppc.dsisr = value; return;
|
||||
case SPR603E_DAR: ppc.dar = value; return;
|
||||
case SPR603E_EAR: ppc.ear = value; return;
|
||||
case SPR603E_DMISS: ppc.dmiss = value; return;
|
||||
case SPR603E_DCMP: ppc.dcmp = value; return;
|
||||
case SPR603E_HASH1: ppc.hash1 = value; return;
|
||||
case SPR603E_HASH2: ppc.hash2 = value; return;
|
||||
case SPR603E_IMISS: ppc.imiss = value; return;
|
||||
case SPR603E_ICMP: ppc.icmp = value; return;
|
||||
case SPR603E_RPA: ppc.rpa = value; return;
|
||||
|
||||
case SPR603E_IBAT0L: ppc.ibat[0].l = value; return;
|
||||
case SPR603E_IBAT0U: ppc.ibat[0].u = value; return;
|
||||
case SPR603E_IBAT1L: ppc.ibat[1].l = value; return;
|
||||
case SPR603E_IBAT1U: ppc.ibat[1].u = value; return;
|
||||
case SPR603E_IBAT2L: ppc.ibat[2].l = value; return;
|
||||
case SPR603E_IBAT2U: ppc.ibat[2].u = value; return;
|
||||
case SPR603E_IBAT3L: ppc.ibat[3].l = value; return;
|
||||
case SPR603E_IBAT3U: ppc.ibat[3].u = value; return;
|
||||
case SPR603E_DBAT0L: ppc.dbat[0].l = value; return;
|
||||
case SPR603E_DBAT0U: ppc.dbat[0].u = value; return;
|
||||
case SPR603E_DBAT1L: ppc.dbat[1].l = value; return;
|
||||
case SPR603E_DBAT1U: ppc.dbat[1].u = value; return;
|
||||
case SPR603E_DBAT2L: ppc.dbat[2].l = value; return;
|
||||
case SPR603E_DBAT2U: ppc.dbat[2].u = value; return;
|
||||
case SPR603E_DBAT3L: ppc.dbat[3].l = value; return;
|
||||
case SPR603E_DBAT3U: ppc.dbat[3].u = value; return;
|
||||
|
||||
case SPR603E_SDR1:
|
||||
ppc.sdr1 = value;
|
||||
return;
|
||||
|
||||
case SPR603E_IABR: ppc.iabr = value; return;
|
||||
}
|
||||
|
||||
error("ppc: set_spr: unknown spr %d (%03X) !", spr, spr);
|
||||
}
|
||||
|
||||
INLINE UINT32 ppc_get_spr(int spr)
|
||||
{
|
||||
switch(spr)
|
||||
{
|
||||
case SPR_LR: return LR;
|
||||
case SPR_CTR: return CTR;
|
||||
case SPR_XER: return XER;
|
||||
case SPR_SRR0: return ppc.srr0;
|
||||
case SPR_SRR1: return ppc.srr1;
|
||||
case SPR_SPRG0: return ppc.sprg[0];
|
||||
case SPR_SPRG1: return ppc.sprg[1];
|
||||
case SPR_SPRG2: return ppc.sprg[2];
|
||||
case SPR_SPRG3: return ppc.sprg[3];
|
||||
case SPR_PVR: return ppc.pvr;
|
||||
case SPR603E_TBL_R:
|
||||
error("ppc: get_spr: TBL_R ");
|
||||
break;
|
||||
|
||||
case SPR603E_TBU_R:
|
||||
error("ppc: get_spr: TBU_R ");
|
||||
break;
|
||||
|
||||
case SPR603E_TBL_W: return (UINT32)(ppc_read_timebase());
|
||||
case SPR603E_TBU_W: return (UINT32)(ppc_read_timebase() >> 32);
|
||||
case SPR603E_HID0: return ppc.hid0;
|
||||
case SPR603E_HID1: return ppc.hid1;
|
||||
case SPR603E_HID2: return ppc.hid2;
|
||||
case SPR603E_DEC: return read_decrementer();
|
||||
case SPR603E_SDR1: return ppc.sdr1;
|
||||
case SPR603E_DSISR: return ppc.dsisr;
|
||||
case SPR603E_DAR: return ppc.dar;
|
||||
case SPR603E_EAR: return ppc.ear;
|
||||
case SPR603E_DMISS: return ppc.dmiss;
|
||||
case SPR603E_DCMP: return ppc.dcmp;
|
||||
case SPR603E_HASH1: return ppc.hash1;
|
||||
case SPR603E_HASH2: return ppc.hash2;
|
||||
case SPR603E_IMISS: return ppc.imiss;
|
||||
case SPR603E_ICMP: return ppc.icmp;
|
||||
case SPR603E_RPA: return ppc.rpa;
|
||||
case SPR603E_IBAT0L: return ppc.ibat[0].l;
|
||||
case SPR603E_IBAT0U: return ppc.ibat[0].u;
|
||||
case SPR603E_IBAT1L: return ppc.ibat[1].l;
|
||||
case SPR603E_IBAT1U: return ppc.ibat[1].u;
|
||||
case SPR603E_IBAT2L: return ppc.ibat[2].l;
|
||||
case SPR603E_IBAT2U: return ppc.ibat[2].u;
|
||||
case SPR603E_IBAT3L: return ppc.ibat[3].l;
|
||||
case SPR603E_IBAT3U: return ppc.ibat[3].u;
|
||||
case SPR603E_DBAT0L: return ppc.dbat[0].l;
|
||||
case SPR603E_DBAT0U: return ppc.dbat[0].u;
|
||||
case SPR603E_DBAT1L: return ppc.dbat[1].l;
|
||||
case SPR603E_DBAT1U: return ppc.dbat[1].u;
|
||||
case SPR603E_DBAT2L: return ppc.dbat[2].l;
|
||||
case SPR603E_DBAT2U: return ppc.dbat[2].u;
|
||||
case SPR603E_DBAT3L: return ppc.dbat[3].l;
|
||||
case SPR603E_DBAT3U: return ppc.dbat[3].u;
|
||||
}
|
||||
|
||||
error("ppc: get_spr: unknown spr %d (%03X) !", spr, spr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
INLINE void ppc_set_msr(UINT32 value)
|
||||
{
|
||||
if( value & (MSR_ILE | MSR_LE) )
|
||||
error("ppc: set_msr: little_endian mode not supported !");
|
||||
|
||||
MSR = value;
|
||||
|
||||
ppc603_check_interrupts();
|
||||
}
|
||||
|
||||
INLINE UINT32 ppc_get_msr(void)
|
||||
{
|
||||
return MSR;
|
||||
}
|
||||
|
||||
INLINE void ppc_set_cr(UINT32 value)
|
||||
{
|
||||
CR(0) = (value >> 28) & 0xf;
|
||||
CR(1) = (value >> 24) & 0xf;
|
||||
CR(2) = (value >> 20) & 0xf;
|
||||
CR(3) = (value >> 16) & 0xf;
|
||||
CR(4) = (value >> 12) & 0xf;
|
||||
CR(5) = (value >> 8) & 0xf;
|
||||
CR(6) = (value >> 4) & 0xf;
|
||||
CR(7) = (value >> 0) & 0xf;
|
||||
}
|
||||
|
||||
INLINE UINT32 ppc_get_cr(void)
|
||||
{
|
||||
return CR(0) << 28 | CR(1) << 24 | CR(2) << 20 | CR(3) << 16 | CR(4) << 12 | CR(5) << 8 | CR(6) << 4 | CR(7);
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
static void (* optable19[1024])(UINT32);
|
||||
static void (* optable31[1024])(UINT32);
|
||||
static void (* optable59[1024])(UINT32);
|
||||
static void (* optable63[1024])(UINT32);
|
||||
static void (* optable[64])(UINT32);
|
||||
|
||||
#include "ppc603.c"
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
#include "ppc_ops.c"
|
||||
#include "ppc_ops.h"
|
||||
|
||||
/* Initialization and shutdown */
|
||||
|
||||
void ppc_base_init(void)
|
||||
{
|
||||
int i,j;
|
||||
|
||||
memset(&ppc, 0, sizeof(ppc));
|
||||
|
||||
for( i=0; i < 64; i++ ) {
|
||||
optable[i] = ppc_invalid;
|
||||
}
|
||||
for( i=0; i < 1024; i++ ) {
|
||||
optable19[i] = ppc_invalid;
|
||||
optable31[i] = ppc_invalid;
|
||||
optable59[i] = ppc_invalid;
|
||||
optable63[i] = ppc_invalid;
|
||||
}
|
||||
|
||||
/* Fill the opcode tables */
|
||||
for( i=0; i < (sizeof(ppc_opcode_common) / sizeof(PPC_OPCODE)); i++ ) {
|
||||
|
||||
switch(ppc_opcode_common[i].code)
|
||||
{
|
||||
case 19:
|
||||
optable19[ppc_opcode_common[i].subcode] = ppc_opcode_common[i].handler;
|
||||
break;
|
||||
|
||||
case 31:
|
||||
optable31[ppc_opcode_common[i].subcode] = ppc_opcode_common[i].handler;
|
||||
break;
|
||||
|
||||
case 59:
|
||||
case 63:
|
||||
break;
|
||||
|
||||
default:
|
||||
optable[ppc_opcode_common[i].code] = ppc_opcode_common[i].handler;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Calculate rotate mask table */
|
||||
for( i=0; i < 32; i++ ) {
|
||||
for( j=0; j < 32; j++ ) {
|
||||
UINT32 mask;
|
||||
int mb = i;
|
||||
int me = j;
|
||||
mask = ((UINT32)0xFFFFFFFF >> mb) ^ ((me >= 31) ? 0 : ((UINT32)0xFFFFFFFF >> (me + 1)));
|
||||
if( mb > me )
|
||||
mask = ~mask;
|
||||
|
||||
ppc_rotate_mask[i][j] = mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ppc_init(const PPC_CONFIG *config)
|
||||
{
|
||||
int pll_config = 0;
|
||||
float multiplier;
|
||||
int i ;
|
||||
|
||||
ppc_base_init() ;
|
||||
|
||||
optable[48] = ppc_lfs;
|
||||
optable[49] = ppc_lfsu;
|
||||
optable[50] = ppc_lfd;
|
||||
optable[51] = ppc_lfdu;
|
||||
optable[52] = ppc_stfs;
|
||||
optable[53] = ppc_stfsu;
|
||||
optable[54] = ppc_stfd;
|
||||
optable[55] = ppc_stfdu;
|
||||
optable31[631] = ppc_lfdux;
|
||||
optable31[599] = ppc_lfdx;
|
||||
optable31[567] = ppc_lfsux;
|
||||
optable31[535] = ppc_lfsx;
|
||||
optable31[595] = ppc_mfsr;
|
||||
optable31[659] = ppc_mfsrin;
|
||||
optable31[371] = ppc_mftb;
|
||||
optable31[210] = ppc_mtsr;
|
||||
optable31[242] = ppc_mtsrin;
|
||||
optable31[758] = ppc_dcba;
|
||||
optable31[759] = ppc_stfdux;
|
||||
optable31[727] = ppc_stfdx;
|
||||
optable31[983] = ppc_stfiwx;
|
||||
optable31[695] = ppc_stfsux;
|
||||
optable31[663] = ppc_stfsx;
|
||||
optable31[370] = ppc_tlbia;
|
||||
optable31[306] = ppc_tlbie;
|
||||
optable31[566] = ppc_tlbsync;
|
||||
optable31[310] = ppc_eciwx;
|
||||
optable31[438] = ppc_ecowx;
|
||||
|
||||
optable63[264] = ppc_fabsx;
|
||||
optable63[21] = ppc_faddx;
|
||||
optable63[32] = ppc_fcmpo;
|
||||
optable63[0] = ppc_fcmpu;
|
||||
optable63[14] = ppc_fctiwx;
|
||||
optable63[15] = ppc_fctiwzx;
|
||||
optable63[18] = ppc_fdivx;
|
||||
optable63[72] = ppc_fmrx;
|
||||
optable63[136] = ppc_fnabsx;
|
||||
optable63[40] = ppc_fnegx;
|
||||
optable63[12] = ppc_frspx;
|
||||
optable63[26] = ppc_frsqrtex;
|
||||
optable63[22] = ppc_fsqrtx;
|
||||
optable63[20] = ppc_fsubx;
|
||||
optable63[583] = ppc_mffsx;
|
||||
optable63[70] = ppc_mtfsb0x;
|
||||
optable63[38] = ppc_mtfsb1x;
|
||||
optable63[711] = ppc_mtfsfx;
|
||||
optable63[134] = ppc_mtfsfix;
|
||||
optable63[64] = ppc_mcrfs;
|
||||
|
||||
optable59[21] = ppc_faddsx;
|
||||
optable59[18] = ppc_fdivsx;
|
||||
optable59[24] = ppc_fresx;
|
||||
optable59[22] = ppc_fsqrtsx;
|
||||
optable59[20] = ppc_fsubsx;
|
||||
|
||||
for(i = 0; i < 32; i++)
|
||||
{
|
||||
optable63[i * 32 | 29] = ppc_fmaddx;
|
||||
optable63[i * 32 | 28] = ppc_fmsubx;
|
||||
optable63[i * 32 | 25] = ppc_fmulx;
|
||||
optable63[i * 32 | 31] = ppc_fnmaddx;
|
||||
optable63[i * 32 | 30] = ppc_fnmsubx;
|
||||
optable63[i * 32 | 23] = ppc_fselx;
|
||||
|
||||
optable59[i * 32 | 29] = ppc_fmaddsx;
|
||||
optable59[i * 32 | 28] = ppc_fmsubsx;
|
||||
optable59[i * 32 | 25] = ppc_fmulsx;
|
||||
optable59[i * 32 | 31] = ppc_fnmaddsx;
|
||||
optable59[i * 32 | 30] = ppc_fnmsubsx;
|
||||
}
|
||||
|
||||
for(i = 0; i < 256; i++)
|
||||
{
|
||||
ppc_field_xlat[i] =
|
||||
((i & 0x80) ? 0xF0000000 : 0) |
|
||||
((i & 0x40) ? 0x0F000000 : 0) |
|
||||
((i & 0x20) ? 0x00F00000 : 0) |
|
||||
((i & 0x10) ? 0x000F0000 : 0) |
|
||||
((i & 0x08) ? 0x0000F000 : 0) |
|
||||
((i & 0x04) ? 0x00000F00 : 0) |
|
||||
((i & 0x02) ? 0x000000F0 : 0) |
|
||||
((i & 0x01) ? 0x0000000F : 0);
|
||||
}
|
||||
|
||||
ppc.pvr = config->pvr;
|
||||
|
||||
multiplier = (float)((config->bus_frequency_multiplier >> 4) & 0xf) +
|
||||
(float)(config->bus_frequency_multiplier & 0xf) / 10.0f;
|
||||
bus_freq_multiplier = (int)(multiplier * 2);
|
||||
|
||||
switch(config->pvr)
|
||||
{
|
||||
case PPC_MODEL_603E: pll_config = mpc603e_pll_config[bus_freq_multiplier-1][config->bus_frequency]; break;
|
||||
case PPC_MODEL_603EV: pll_config = mpc603ev_pll_config[bus_freq_multiplier-1][config->bus_frequency]; break;
|
||||
case PPC_MODEL_603R: pll_config = mpc603r_pll_config[bus_freq_multiplier-1][config->bus_frequency]; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if (pll_config == -1)
|
||||
{
|
||||
error("PPC: Invalid bus/multiplier combination (bus frequency = %d, multiplier = %1.1f)", config->bus_frequency, multiplier);
|
||||
}
|
||||
|
||||
ppc.hid1 = pll_config << 28;
|
||||
}
|
||||
|
||||
void ppc_shutdown(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ppc_set_irq_line(int irqline)
|
||||
{
|
||||
ppc.interrupt_pending |= 0x1;
|
||||
|
||||
ppc603_check_interrupts();
|
||||
}
|
||||
|
||||
UINT32 ppc_get_pc(void)
|
||||
{
|
||||
return ppc.pc;
|
||||
}
|
||||
|
||||
void ppc_set_fetch(PPC_FETCH_REGION * fetch)
|
||||
{
|
||||
ppc.fetch = fetch;
|
||||
}
|
314
ppc_itp/ppc.h
Normal file
314
ppc_itp/ppc.h
Normal file
|
@ -0,0 +1,314 @@
|
|||
#ifndef _PPC_H
|
||||
#define _PPC_H
|
||||
|
||||
#define SPR_XER 1 /* Fixed Point Exception Register Read / Write */
|
||||
#define SPR_LR 8 /* Link Register Read / Write */
|
||||
#define SPR_CTR 9 /* Count Register Read / Write */
|
||||
#define SPR_SRR0 26 /* Save/Restore Register 0 Read / Write */
|
||||
#define SPR_SRR1 27 /* Save/Restore Register 1 Read / Write */
|
||||
#define SPR_SPRG0 272 /* SPR General 0 Read / Write */
|
||||
#define SPR_SPRG1 273 /* SPR General 1 Read / Write */
|
||||
#define SPR_SPRG2 274 /* SPR General 2 Read / Write */
|
||||
#define SPR_SPRG3 275 /* SPR General 3 Read / Write */
|
||||
#define SPR_PVR 287 /* Processor Version Number Read Only */
|
||||
|
||||
#define SPR403_ICDBDR 0x3D3 /* 406GA Instruction Cache Debug Data Register Rad Only */
|
||||
#define SPR403_ESR 0x3D4 /* 406GA Exception Syndrome Register Read / Write */
|
||||
#define SPR403_DEAR 0x3D5 /* 406GA Data Exception Address Register Read Only */
|
||||
#define SPR403_EVPR 0x3D6 /* 406GA Exception Vector Prefix Register Read / Write */
|
||||
#define SPR403_CDBCR 0x3D7 /* 406GA Cache Debug Control Register Read/Write */
|
||||
#define SPR403_TSR 0x3D8 /* 406GA Timer Status Register Read / Clear */
|
||||
#define SPR403_TCR 0x3DA /* 406GA Timer Control Register Read / Write */
|
||||
#define SPR403_PIT 0x3DB /* 406GA Programmable Interval Timer Read / Write */
|
||||
#define SPR403_TBHI 988 /* 406GA Time Base High Read / Write */
|
||||
#define SPR403_TBLO 989 /* 406GA Time Base Low Read / Write */
|
||||
#define SPR403_SRR2 0x3DE /* 406GA Save/Restore Register 2 Read / Write */
|
||||
#define SPR403_SRR3 0x3DF /* 406GA Save/Restore Register 3 Read / Write */
|
||||
#define SPR403_DBSR 0x3F0 /* 406GA Debug Status Register Read / Clear */
|
||||
#define SPR403_DBCR 0x3F2 /* 406GA Debug Control Register Read / Write */
|
||||
#define SPR403_IAC1 0x3F4 /* 406GA Instruction Address Compare 1 Read / Write */
|
||||
#define SPR403_IAC2 0x3F5 /* 406GA Instruction Address Compare 2 Read / Write */
|
||||
#define SPR403_DAC1 0x3F6 /* 406GA Data Address Compare 1 Read / Write */
|
||||
#define SPR403_DAC2 0x3F7 /* 406GA Data Address Compare 2 Read / Write */
|
||||
#define SPR403_DCCR 0x3FA /* 406GA Data Cache Cacheability Register Read / Write */
|
||||
#define SPR403_ICCR 0x3FB /* 406GA I Cache Cacheability Registe Read / Write */
|
||||
#define SPR403_PBL1 0x3FC /* 406GA Protection Bound Lower 1 Read / Write */
|
||||
#define SPR403_PBU1 0x3FD /* 406GA Protection Bound Upper 1 Read / Write */
|
||||
#define SPR403_PBL2 0x3FE /* 406GA Protection Bound Lower 2 Read / Write */
|
||||
#define SPR403_PBU2 0x3FF /* 406GA Protection Bound Upper 2 Read / Write */
|
||||
|
||||
#define SPR403_SGR 0x3b9 /* 403GCX Storage Guarded Register */
|
||||
#define SPR403_DCWR 0x3ba /* 403GCX Data Cache Write Through */
|
||||
#define SPR403_PID 0x3b1 /* 403GCX Process ID */
|
||||
#define SPR403_TBHU 0x3cc /* 403GCX Time Base High User-mode */
|
||||
#define SPR403_TBLU 0x3cd /* 403GCX Time Base Low User-mode */
|
||||
|
||||
#define SPR603E_DSISR 18 /* 603E */
|
||||
#define SPR603E_DAR 19 /* 603E */
|
||||
#define SPR603E_DEC 22 /* 603E */
|
||||
#define SPR603E_SDR1 25 /* 603E */
|
||||
#define SPR603E_TBL_R 268 /* 603E Time Base Low (Read-only) */
|
||||
#define SPR603E_TBU_R 269 /* 603E Time Base High (Read-only) */
|
||||
#define SPR603E_TBL_W 284 /* 603E Time Base Low (Write-only) */
|
||||
#define SPR603E_TBU_W 285 /* 603E Time Base Hight (Write-only) */
|
||||
#define SPR603E_EAR 282 /* 603E */
|
||||
#define SPR603E_IBAT0U 528 /* 603E */
|
||||
#define SPR603E_IBAT0L 529 /* 603E */
|
||||
#define SPR603E_IBAT1U 530 /* 603E */
|
||||
#define SPR603E_IBAT1L 531 /* 603E */
|
||||
#define SPR603E_IBAT2U 532 /* 603E */
|
||||
#define SPR603E_IBAT2L 533 /* 603E */
|
||||
#define SPR603E_IBAT3U 534 /* 603E */
|
||||
#define SPR603E_IBAT3L 535 /* 603E */
|
||||
#define SPR603E_DBAT0U 536 /* 603E */
|
||||
#define SPR603E_DBAT0L 537 /* 603E */
|
||||
#define SPR603E_DBAT1U 538 /* 603E */
|
||||
#define SPR603E_DBAT1L 539 /* 603E */
|
||||
#define SPR603E_DBAT2U 540 /* 603E */
|
||||
#define SPR603E_DBAT2L 541 /* 603E */
|
||||
#define SPR603E_DBAT3U 542 /* 603E */
|
||||
#define SPR603E_DBAT3L 543 /* 603E */
|
||||
#define SPR603E_DABR 1013 /* 603E */
|
||||
#define SPR603E_DMISS 0x3d0 /* 603E */
|
||||
#define SPR603E_DCMP 0x3d1 /* 603E */
|
||||
#define SPR603E_HASH1 0x3d2 /* 603E */
|
||||
#define SPR603E_HASH2 0x3d3 /* 603E */
|
||||
#define SPR603E_IMISS 0x3d4 /* 603E */
|
||||
#define SPR603E_ICMP 0x3d5 /* 603E */
|
||||
#define SPR603E_RPA 0x3d6 /* 603E */
|
||||
#define SPR603E_HID0 1008 /* 603E */
|
||||
#define SPR603E_HID1 1009 /* 603E */
|
||||
#define SPR603E_IABR 1010 /* 603E */
|
||||
#define SPR603E_HID2 1011 /* 603E */
|
||||
|
||||
#define SPR602_TCR 984 /* 602 */
|
||||
#define SPR602_IBR 986 /* 602 */
|
||||
#define SPR602_SP 1021 /* 602 */
|
||||
#define SPR602_LT 1022 /* 602 */
|
||||
|
||||
|
||||
#define DCR_BEAR 0x90 /* bus error address */
|
||||
#define DCR_BESR 0x91 /* bus error syndrome */
|
||||
#define DCR_BR0 0x80 /* bank */
|
||||
#define DCR_BR1 0x81 /* bank */
|
||||
#define DCR_BR2 0x82 /* bank */
|
||||
#define DCR_BR3 0x83 /* bank */
|
||||
#define DCR_BR4 0x84 /* bank */
|
||||
#define DCR_BR5 0x85 /* bank */
|
||||
#define DCR_BR6 0x86 /* bank */
|
||||
#define DCR_BR7 0x87 /* bank */
|
||||
#define DCR_DMACC0 0xc4 /* dma chained count */
|
||||
#define DCR_DMACC1 0xcc /* dma chained count */
|
||||
#define DCR_DMACC2 0xd4 /* dma chained count */
|
||||
#define DCR_DMACC3 0xdc /* dma chained count */
|
||||
#define DCR_DMACR0 0xc0 /* dma channel control */
|
||||
#define DCR_DMACR1 0xc8 /* dma channel control */
|
||||
#define DCR_DMACR2 0xd0 /* dma channel control */
|
||||
#define DCR_DMACR3 0xd8 /* dma channel control */
|
||||
#define DCR_DMACT0 0xc1 /* dma destination address */
|
||||
#define DCR_DMACT1 0xc9 /* dma destination address */
|
||||
#define DCR_DMACT2 0xd1 /* dma destination address */
|
||||
#define DCR_DMACT3 0xd9 /* dma destination address */
|
||||
#define DCR_DMADA0 0xc2 /* dma destination address */
|
||||
#define DCR_DMADA1 0xca /* dma destination address */
|
||||
#define DCR_DMADA2 0xd2 /* dma source address */
|
||||
#define DCR_DMADA3 0xda /* dma source address */
|
||||
#define DCR_DMASA0 0xc3 /* dma source address */
|
||||
#define DCR_DMASA1 0xcb /* dma source address */
|
||||
#define DCR_DMASA2 0xd3 /* dma source address */
|
||||
#define DCR_DMASA3 0xdb /* dma source address */
|
||||
#define DCR_DMASR 0xe0 /* dma status */
|
||||
#define DCR_EXIER 0x42 /* external interrupt enable */
|
||||
#define DCR_EXISR 0x40 /* external interrupt status */
|
||||
#define DCR_IOCR 0xa0 /* io configuration */
|
||||
|
||||
enum {
|
||||
EXCEPTION_IRQ = 1,
|
||||
EXCEPTION_DECREMENTER = 2,
|
||||
EXCEPTION_TRAP = 3,
|
||||
EXCEPTION_SYSTEM_CALL = 4,
|
||||
EXCEPTION_SMI = 5,
|
||||
EXCEPTION_DSI = 6,
|
||||
EXCEPTION_ISI = 7,
|
||||
EXCEPTION_PROGRAMMABLE_INTERVAL_TIMER = 20,
|
||||
EXCEPTION_FIXED_INTERVAL_TIMER = 21,
|
||||
EXCEPTION_WATCHDOG_TIMER = 22,
|
||||
EXCEPTION_CRITICAL_INTERRUPT = 23,
|
||||
};
|
||||
|
||||
enum {
|
||||
PPC_INPUT_LINE_SMI = 10,
|
||||
PPC_INPUT_LINE_TLBISYNC
|
||||
};
|
||||
|
||||
enum {
|
||||
PPC_PC=1,
|
||||
PPC_MSR,
|
||||
PPC_CR,
|
||||
PPC_LR,
|
||||
PPC_CTR,
|
||||
PPC_XER,
|
||||
PPC_DEC,
|
||||
PPC_SRR0,
|
||||
PPC_SRR1,
|
||||
PPC_R0,
|
||||
PPC_R1,
|
||||
PPC_R2,
|
||||
PPC_R3,
|
||||
PPC_R4,
|
||||
PPC_R5,
|
||||
PPC_R6,
|
||||
PPC_R7,
|
||||
PPC_R8,
|
||||
PPC_R9,
|
||||
PPC_R10,
|
||||
PPC_R11,
|
||||
PPC_R12,
|
||||
PPC_R13,
|
||||
PPC_R14,
|
||||
PPC_R15,
|
||||
PPC_R16,
|
||||
PPC_R17,
|
||||
PPC_R18,
|
||||
PPC_R19,
|
||||
PPC_R20,
|
||||
PPC_R21,
|
||||
PPC_R22,
|
||||
PPC_R23,
|
||||
PPC_R24,
|
||||
PPC_R25,
|
||||
PPC_R26,
|
||||
PPC_R27,
|
||||
PPC_R28,
|
||||
PPC_R29,
|
||||
PPC_R30,
|
||||
PPC_R31
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
PPC_MODEL_403GA = 0x00200000,
|
||||
PPC_MODEL_403GB = 0x00200100,
|
||||
PPC_MODEL_403GC = 0x00200200,
|
||||
PPC_MODEL_403GCX = 0x00201400,
|
||||
PPC_MODEL_405GP = 0x40110000,
|
||||
PPC_MODEL_601 = 0x00010000,
|
||||
PPC_MODEL_603 = 0x00030000, /* "Wart" */
|
||||
PPC_MODEL_604 = 0x00040000, /* "Zephyr" */
|
||||
PPC_MODEL_602 = 0x00050000, /* "Galahad" */
|
||||
PPC_MODEL_603E = 0x00060103, /* "Stretch", version 1.3 */
|
||||
PPC_MODEL_603EV = 0x00070000, /* "Valiant" */
|
||||
PPC_MODEL_603R = 0x00071202, /* "Goldeneye", version 2.1 */
|
||||
PPC_MODEL_740 = 0x00080301, /* "Arthur", version 3.1 */
|
||||
PPC_MODEL_750 = PPC_MODEL_740,
|
||||
PPC_MODEL_740P = 0x00080202, /* "Conan Doyle", version 1.2 */
|
||||
PPC_MODEL_750P = PPC_MODEL_740P,
|
||||
PPC_MODEL_755 = 0x00083203 /* "Goldfinger", version 2.3 */
|
||||
} PPC_MODEL;
|
||||
|
||||
typedef enum {
|
||||
BUS_FREQUENCY_16MHZ = 0,
|
||||
BUS_FREQUENCY_20MHZ,
|
||||
BUS_FREQUENCY_25MHZ,
|
||||
BUS_FREQUENCY_33MHZ,
|
||||
BUS_FREQUENCY_40MHZ,
|
||||
BUS_FREQUENCY_50MHZ,
|
||||
BUS_FREQUENCY_60MHZ,
|
||||
BUS_FREQUENCY_66MHZ,
|
||||
BUS_FREQUENCY_75MHZ,
|
||||
} PPC_BUS_FREQUENCY;
|
||||
|
||||
// PLL Configuration based on the table in MPC603EUM page 7-31
|
||||
static const int mpc603e_pll_config[12][9] =
|
||||
{
|
||||
// 16, 20, 25, 33, 40, 50, 60, 66, 75
|
||||
{ -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
||||
{ 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, -1, 0x0, -1 },
|
||||
{ -1, -1, -1, -1, -1, 0xc, -1, 0xc, -1 },
|
||||
{ 0x5, 0x5, 0x5, 0x4, 0x4, 0x4, -1, -1, -1 },
|
||||
{ -1, -1, -1, 0x6, 0x6, -1, -1, -1, -1 },
|
||||
{ -1, -1, 0x8, 0x8, -1, -1, -1, -1, -1 },
|
||||
{ -1, 0xe, 0xe, -1, -1, -1, -1, -1, -1 },
|
||||
{ 0xa, 0xa, 0xa, -1, -1, -1, -1, -1, -1 },
|
||||
{ -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
||||
{ -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
||||
{ -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
||||
{ -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
||||
};
|
||||
|
||||
// PLL Configuration based on the table in MPC603E7VEC page 29
|
||||
static const int mpc603ev_pll_config[12][9] =
|
||||
{
|
||||
// 16, 20, 25, 33, 40, 50, 60, 66, 75
|
||||
{ -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
||||
{ -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
||||
{ -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
||||
// 2:1
|
||||
{ -1, -1, -1, -1, -1, -1, -1, 0x4, 0x4 },
|
||||
// 2.5:1
|
||||
{ -1, -1, -1, -1, -1, 0x6, 0x6, 0x6, 0x6 },
|
||||
// 3:1
|
||||
{ -1, -1, -1, -1, 0x8, 0x8, 0x8, 0x8, 0x8 },
|
||||
// 3.5:1
|
||||
{ -1, -1, -1, -1, 0xe, 0xe, 0xe, 0xe, -1 },
|
||||
// 4:1
|
||||
{ -1, -1, -1, 0xa, 0xa, 0xa, 0xa, -1, -1 },
|
||||
// 4.5:1
|
||||
{ -1, -1, -1, 0x7, 0x7, 0x7, -1, -1, -1 },
|
||||
// 5:1
|
||||
{ -1, -1, 0xb, 0xb, 0xb, -1, -1, -1, -1 },
|
||||
// 5.5:1
|
||||
{ -1, -1, 0x9, 0x9, 0x9, -1, -1, -1, -1 },
|
||||
// 6:1
|
||||
{ -1, -1, 0xd, 0xd, 0xd, -1, -1, -1, -1 }
|
||||
};
|
||||
|
||||
// PLL Configuration based on the table in MPC603E7TEC page 23
|
||||
static const int mpc603r_pll_config[12][9] =
|
||||
{
|
||||
// 16, 20, 25, 33, 40, 50, 60, 66, 75
|
||||
{ -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
||||
{ -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
||||
{ -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
||||
// 2:1
|
||||
{ -1, -1, -1, -1, 0x5, 0x5, 0x5, 0x5, 0x5 },
|
||||
// 2.5:1
|
||||
{ -1, -1, -1, -1, -1, -1, 0x6, 0x6, 0x6 },
|
||||
// 3:1
|
||||
{ -1, -1, -1, -1, -1, 0x8, 0x8, 0x8, 0x8 },
|
||||
// 3.5:1
|
||||
{ -1, -1, -1, -1, -1, 0xe, 0xe, 0xe, 0xe },
|
||||
// 4:1
|
||||
{ -1, -1, -1, -1, 0xa, 0xa, 0xa, 0xa, 0xa },
|
||||
// 4.5:1
|
||||
{ -1, -1, -1, 0x7, 0x7, 0x7, 0x7, 0x7, -1 },
|
||||
// 5:1
|
||||
{ -1, -1, -1, 0xb, 0xb, 0xb, 0xb, -1, -1 },
|
||||
// 5.5:1
|
||||
{ -1, -1, -1, 0x9, 0x9, 0x9, -1, -1, -1 },
|
||||
// 6:1
|
||||
{ -1, -1, 0xd, 0xd, 0xd, 0xd, -1, -1, -1 },
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
PPC_MODEL pvr;
|
||||
int bus_frequency_multiplier;
|
||||
PPC_BUS_FREQUENCY bus_frequency;
|
||||
} PPC_CONFIG;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT32 start;
|
||||
UINT32 end;
|
||||
UINT32 * ptr;
|
||||
|
||||
} PPC_FETCH_REGION;
|
||||
|
||||
UINT32 ppc_get_pc(void);
|
||||
void ppc_set_irq_line(int irqline);
|
||||
int ppc_execute(int cycles);
|
||||
void ppc_reset(void);
|
||||
void ppc_shutdown(void);
|
||||
void ppc_init(const PPC_CONFIG *config);
|
||||
void ppc_set_fetch(PPC_FETCH_REGION * fetch);
|
||||
|
||||
#endif /* _PPC_H */
|
294
ppc_itp/ppc603.c
Normal file
294
ppc_itp/ppc603.c
Normal file
|
@ -0,0 +1,294 @@
|
|||
void ppc603_exception(int exception)
|
||||
{
|
||||
switch( exception )
|
||||
{
|
||||
case EXCEPTION_IRQ: /* External Interrupt */
|
||||
if( ppc_get_msr() & MSR_EE ) {
|
||||
UINT32 msr = ppc_get_msr();
|
||||
|
||||
SRR0 = ppc.npc;
|
||||
SRR1 = msr & 0xff73;
|
||||
|
||||
msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
|
||||
if( msr & MSR_ILE )
|
||||
msr |= MSR_LE;
|
||||
else
|
||||
msr &= ~MSR_LE;
|
||||
ppc_set_msr(msr);
|
||||
|
||||
if( msr & MSR_IP )
|
||||
ppc.npc = 0xfff00000 | 0x0500;
|
||||
else
|
||||
ppc.npc = 0x00000000 | 0x0500;
|
||||
|
||||
ppc.interrupt_pending &= ~0x1;
|
||||
ppc_change_pc(ppc.npc);
|
||||
}
|
||||
break;
|
||||
|
||||
case EXCEPTION_DECREMENTER: /* Decrementer overflow exception */
|
||||
if( ppc_get_msr() & MSR_EE ) {
|
||||
UINT32 msr = ppc_get_msr();
|
||||
|
||||
SRR0 = ppc.npc;
|
||||
SRR1 = msr & 0xff73;
|
||||
|
||||
msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
|
||||
if( msr & MSR_ILE )
|
||||
msr |= MSR_LE;
|
||||
else
|
||||
msr &= ~MSR_LE;
|
||||
ppc_set_msr(msr);
|
||||
|
||||
if( msr & MSR_IP )
|
||||
ppc.npc = 0xfff00000 | 0x0900;
|
||||
else
|
||||
ppc.npc = 0x00000000 | 0x0900;
|
||||
|
||||
ppc.interrupt_pending &= ~0x2;
|
||||
ppc_change_pc(ppc.npc);
|
||||
}
|
||||
break;
|
||||
|
||||
case EXCEPTION_TRAP: /* Program exception / Trap */
|
||||
{
|
||||
UINT32 msr = ppc_get_msr();
|
||||
|
||||
SRR0 = ppc.pc;
|
||||
SRR1 = (msr & 0xff73) | 0x20000; /* 0x20000 = TRAP bit */
|
||||
|
||||
msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
|
||||
if( msr & MSR_ILE )
|
||||
msr |= MSR_LE;
|
||||
else
|
||||
msr &= ~MSR_LE;
|
||||
ppc_set_msr(msr);
|
||||
|
||||
if( msr & MSR_IP )
|
||||
ppc.npc = 0xfff00000 | 0x0700;
|
||||
else
|
||||
ppc.npc = 0x00000000 | 0x0700;
|
||||
ppc_change_pc(ppc.npc);
|
||||
}
|
||||
break;
|
||||
|
||||
case EXCEPTION_SYSTEM_CALL: /* System call */
|
||||
{
|
||||
UINT32 msr = ppc_get_msr();
|
||||
|
||||
SRR0 = ppc.npc;
|
||||
SRR1 = (msr & 0xff73);
|
||||
|
||||
msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
|
||||
if( msr & MSR_ILE )
|
||||
msr |= MSR_LE;
|
||||
else
|
||||
msr &= ~MSR_LE;
|
||||
ppc_set_msr(msr);
|
||||
|
||||
if( msr & MSR_IP )
|
||||
ppc.npc = 0xfff00000 | 0x0c00;
|
||||
else
|
||||
ppc.npc = 0x00000000 | 0x0c00;
|
||||
ppc_change_pc(ppc.npc);
|
||||
}
|
||||
break;
|
||||
|
||||
case EXCEPTION_SMI:
|
||||
if( ppc_get_msr() & MSR_EE ) {
|
||||
UINT32 msr = ppc_get_msr();
|
||||
|
||||
SRR0 = ppc.npc;
|
||||
SRR1 = msr & 0xff73;
|
||||
|
||||
msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
|
||||
if( msr & MSR_ILE )
|
||||
msr |= MSR_LE;
|
||||
else
|
||||
msr &= ~MSR_LE;
|
||||
ppc_set_msr(msr);
|
||||
|
||||
if( msr & MSR_IP )
|
||||
ppc.npc = 0xfff00000 | 0x1400;
|
||||
else
|
||||
ppc.npc = 0x00000000 | 0x1400;
|
||||
|
||||
ppc.interrupt_pending &= ~0x4;
|
||||
ppc_change_pc(ppc.npc);
|
||||
}
|
||||
break;
|
||||
|
||||
case EXCEPTION_DSI:
|
||||
{
|
||||
UINT32 msr = ppc_get_msr();
|
||||
|
||||
SRR0 = ppc.npc;
|
||||
SRR1 = msr & 0xff73;
|
||||
|
||||
msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
|
||||
if( msr & MSR_ILE )
|
||||
msr |= MSR_LE;
|
||||
else
|
||||
msr &= ~MSR_LE;
|
||||
ppc_set_msr(msr);
|
||||
|
||||
if( msr & MSR_IP )
|
||||
ppc.npc = 0xfff00000 | 0x0300;
|
||||
else
|
||||
ppc.npc = 0x00000000 | 0x0300;
|
||||
|
||||
ppc.interrupt_pending &= ~0x4;
|
||||
ppc_change_pc(ppc.npc);
|
||||
}
|
||||
break;
|
||||
|
||||
case EXCEPTION_ISI:
|
||||
{
|
||||
UINT32 msr = ppc_get_msr();
|
||||
|
||||
SRR0 = ppc.npc;
|
||||
SRR1 = msr & 0xff73;
|
||||
|
||||
msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
|
||||
if( msr & MSR_ILE )
|
||||
msr |= MSR_LE;
|
||||
else
|
||||
msr &= ~MSR_LE;
|
||||
ppc_set_msr(msr);
|
||||
|
||||
if( msr & MSR_IP )
|
||||
ppc.npc = 0xfff00000 | 0x0400;
|
||||
else
|
||||
ppc.npc = 0x00000000 | 0x0400;
|
||||
|
||||
ppc.interrupt_pending &= ~0x4;
|
||||
ppc_change_pc(ppc.npc);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
error("ppc: Unhandled exception %d", exception);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ppc603_set_smi_line(int state)
|
||||
{
|
||||
if( state ) {
|
||||
ppc.interrupt_pending |= 0x4;
|
||||
}
|
||||
}
|
||||
|
||||
static void ppc603_check_interrupts(void)
|
||||
{
|
||||
if (MSR & MSR_EE)
|
||||
{
|
||||
if (ppc.interrupt_pending != 0)
|
||||
{
|
||||
if (ppc.interrupt_pending & 0x1)
|
||||
{
|
||||
ppc603_exception(EXCEPTION_IRQ);
|
||||
}
|
||||
else if (ppc.interrupt_pending & 0x2)
|
||||
{
|
||||
ppc603_exception(EXCEPTION_DECREMENTER);
|
||||
}
|
||||
else if (ppc.interrupt_pending & 0x4)
|
||||
{
|
||||
ppc603_exception(EXCEPTION_SMI);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ppc_reset(void)
|
||||
{
|
||||
ppc.pc = ppc.npc = 0xfff00100;
|
||||
|
||||
ppc_set_msr(0x40);
|
||||
ppc_change_pc(ppc.pc);
|
||||
|
||||
ppc.hid0 = 1;
|
||||
|
||||
ppc.interrupt_pending = 0;
|
||||
}
|
||||
|
||||
int ppc_execute(int cycles)
|
||||
{
|
||||
UINT32 opcode;
|
||||
ppc_icount = cycles;
|
||||
ppc_tb_base_icount = cycles;
|
||||
ppc_dec_base_icount = cycles + ppc.dec_frac;
|
||||
|
||||
// check if decrementer exception occurs during execution
|
||||
if ((UINT32)(DEC - (cycles / (bus_freq_multiplier * 2))) > (UINT32)(DEC))
|
||||
{
|
||||
ppc_dec_trigger_cycle = ((cycles / (bus_freq_multiplier * 2)) - DEC) * 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
ppc_dec_trigger_cycle = 0x7fffffff;
|
||||
}
|
||||
|
||||
ppc_change_pc(ppc.npc);
|
||||
|
||||
/*{
|
||||
char string1[200];
|
||||
char string2[200];
|
||||
opcode = BSWAP32(*ppc.op);
|
||||
DisassemblePowerPC(opcode, ppc.npc, string1, string2, TRUE);
|
||||
printf("%08X: %s %s\n", ppc.npc, string1, string2);
|
||||
}*/
|
||||
printf("trigger cycle %d (%08X)\n", ppc_dec_trigger_cycle, ppc_dec_trigger_cycle);
|
||||
printf("tb = %08X %08X\n", (UINT32)(ppc.tb >> 32), (UINT32)(ppc.tb));
|
||||
|
||||
ppc603_check_interrupts();
|
||||
|
||||
while( ppc_icount > 0 )
|
||||
{
|
||||
ppc.pc = ppc.npc;
|
||||
|
||||
opcode = BSWAP32(*ppc.op++);
|
||||
|
||||
ppc.npc = ppc.pc + 4;
|
||||
switch(opcode >> 26)
|
||||
{
|
||||
case 19: optable19[(opcode >> 1) & 0x3ff](opcode); break;
|
||||
case 31: optable31[(opcode >> 1) & 0x3ff](opcode); break;
|
||||
case 59: optable59[(opcode >> 1) & 0x3ff](opcode); break;
|
||||
case 63: optable63[(opcode >> 1) & 0x3ff](opcode); break;
|
||||
default: optable[opcode >> 26](opcode); break;
|
||||
}
|
||||
|
||||
ppc_icount--;
|
||||
|
||||
if(ppc_icount == ppc_dec_trigger_cycle)
|
||||
{
|
||||
printf("dec int at %d\n", ppc_icount);
|
||||
ppc.interrupt_pending |= 0x2;
|
||||
ppc603_check_interrupts();
|
||||
}
|
||||
|
||||
//ppc603_check_interrupts();
|
||||
}
|
||||
|
||||
// update timebase
|
||||
// timebase is incremented once every four core clock cycles, so adjust the cycles accordingly
|
||||
ppc.tb += ((ppc_tb_base_icount - ppc_icount) / 4);
|
||||
|
||||
// update decrementer
|
||||
ppc.dec_frac = ((ppc_dec_base_icount - ppc_icount) % (bus_freq_multiplier * 2));
|
||||
DEC -= ((ppc_dec_base_icount - ppc_icount) / (bus_freq_multiplier * 2));
|
||||
|
||||
/*
|
||||
{
|
||||
char string1[200];
|
||||
char string2[200];
|
||||
opcode = BSWAP32(*ppc.op);
|
||||
DisassemblePowerPC(opcode, ppc.npc, string1, string2, TRUE);
|
||||
printf("%08X: %s %s\n", ppc.npc, string1, string2);
|
||||
}
|
||||
*/
|
||||
|
||||
return cycles - ppc_icount;
|
||||
}
|
2711
ppc_itp/ppc_ops.c
Normal file
2711
ppc_itp/ppc_ops.c
Normal file
File diff suppressed because it is too large
Load diff
143
ppc_itp/ppc_ops.h
Normal file
143
ppc_itp/ppc_ops.h
Normal file
|
@ -0,0 +1,143 @@
|
|||
static PPC_OPCODE ppc_opcode_common[] =
|
||||
{
|
||||
/*code subcode handler */
|
||||
{ 31, 266, ppc_addx },
|
||||
{ 31, 266 | 512, ppc_addx },
|
||||
{ 31, 10, ppc_addcx },
|
||||
{ 31, 10 | 512, ppc_addcx },
|
||||
{ 31, 138, ppc_addex },
|
||||
{ 31, 138 | 512, ppc_addex },
|
||||
{ 14, -1, ppc_addi },
|
||||
{ 12, -1, ppc_addic },
|
||||
{ 13, -1, ppc_addic_rc },
|
||||
{ 15, -1, ppc_addis },
|
||||
{ 31, 234, ppc_addmex },
|
||||
{ 31, 234 | 512, ppc_addmex },
|
||||
{ 31, 202, ppc_addzex },
|
||||
{ 31, 202 | 512, ppc_addzex },
|
||||
{ 31, 28, ppc_andx },
|
||||
{ 31, 28 | 512, ppc_andx },
|
||||
{ 31, 60, ppc_andcx },
|
||||
{ 28, -1, ppc_andi_rc },
|
||||
{ 29, -1, ppc_andis_rc },
|
||||
{ 18, -1, ppc_bx },
|
||||
{ 16, -1, ppc_bcx },
|
||||
{ 19, 528, ppc_bcctrx },
|
||||
{ 19, 16, ppc_bclrx },
|
||||
{ 31, 0, ppc_cmp },
|
||||
{ 11, -1, ppc_cmpi },
|
||||
{ 31, 32, ppc_cmpl },
|
||||
{ 10, -1, ppc_cmpli },
|
||||
{ 31, 26, ppc_cntlzw },
|
||||
{ 19, 257, ppc_crand },
|
||||
{ 19, 129, ppc_crandc },
|
||||
{ 19, 289, ppc_creqv },
|
||||
{ 19, 225, ppc_crnand },
|
||||
{ 19, 33, ppc_crnor },
|
||||
{ 19, 449, ppc_cror },
|
||||
{ 19, 417, ppc_crorc },
|
||||
{ 19, 193, ppc_crxor },
|
||||
{ 31, 86, ppc_dcbf },
|
||||
{ 31, 470, ppc_dcbi },
|
||||
{ 31, 54, ppc_dcbst },
|
||||
{ 31, 278, ppc_dcbt },
|
||||
{ 31, 246, ppc_dcbtst },
|
||||
{ 31, 1014, ppc_dcbz },
|
||||
{ 31, 491, ppc_divwx },
|
||||
{ 31, 491 | 512, ppc_divwx },
|
||||
{ 31, 459, ppc_divwux },
|
||||
{ 31, 459 | 512, ppc_divwux },
|
||||
{ 31, 854, ppc_eieio },
|
||||
{ 31, 284, ppc_eqvx },
|
||||
{ 31, 954, ppc_extsbx },
|
||||
{ 31, 922, ppc_extshx },
|
||||
{ 31, 982, ppc_icbi },
|
||||
{ 19, 150, ppc_isync },
|
||||
{ 34, -1, ppc_lbz },
|
||||
{ 35, -1, ppc_lbzu },
|
||||
{ 31, 119, ppc_lbzux },
|
||||
{ 31, 87, ppc_lbzx },
|
||||
{ 42, -1, ppc_lha },
|
||||
{ 43, -1, ppc_lhau },
|
||||
{ 31, 375, ppc_lhaux },
|
||||
{ 31, 343, ppc_lhax },
|
||||
{ 31, 790, ppc_lhbrx },
|
||||
{ 40, -1, ppc_lhz },
|
||||
{ 41, -1, ppc_lhzu },
|
||||
{ 31, 311, ppc_lhzux },
|
||||
{ 31, 279, ppc_lhzx },
|
||||
{ 46, -1, ppc_lmw },
|
||||
{ 31, 597, ppc_lswi },
|
||||
{ 31, 533, ppc_lswx },
|
||||
{ 31, 20, ppc_lwarx },
|
||||
{ 31, 534, ppc_lwbrx },
|
||||
{ 32, -1, ppc_lwz },
|
||||
{ 33, -1, ppc_lwzu },
|
||||
{ 31, 55, ppc_lwzux },
|
||||
{ 31, 23, ppc_lwzx },
|
||||
{ 19, 0, ppc_mcrf },
|
||||
{ 31, 512, ppc_mcrxr },
|
||||
{ 31, 19, ppc_mfcr },
|
||||
{ 31, 83, ppc_mfmsr },
|
||||
{ 31, 339, ppc_mfspr },
|
||||
{ 31, 144, ppc_mtcrf },
|
||||
{ 31, 146, ppc_mtmsr },
|
||||
{ 31, 467, ppc_mtspr },
|
||||
{ 31, 75, ppc_mulhwx },
|
||||
{ 31, 11, ppc_mulhwux },
|
||||
{ 7, -1, ppc_mulli },
|
||||
{ 31, 235, ppc_mullwx },
|
||||
{ 31, 235 | 512, ppc_mullwx },
|
||||
{ 31, 476, ppc_nandx },
|
||||
{ 31, 104, ppc_negx },
|
||||
{ 31, 104 | 512, ppc_negx },
|
||||
{ 31, 124, ppc_norx },
|
||||
{ 31, 444, ppc_orx },
|
||||
{ 31, 412, ppc_orcx },
|
||||
{ 24, -1, ppc_ori },
|
||||
{ 25, -1, ppc_oris },
|
||||
{ 19, 50, ppc_rfi },
|
||||
{ 20, -1, ppc_rlwimix },
|
||||
{ 21, -1, ppc_rlwinmx },
|
||||
{ 23, -1, ppc_rlwnmx },
|
||||
{ 17, -1, ppc_sc },
|
||||
{ 31, 24, ppc_slwx },
|
||||
{ 31, 792, ppc_srawx },
|
||||
{ 31, 824, ppc_srawix },
|
||||
{ 31, 536, ppc_srwx },
|
||||
{ 38, -1, ppc_stb },
|
||||
{ 39, -1, ppc_stbu },
|
||||
{ 31, 247, ppc_stbux },
|
||||
{ 31, 215, ppc_stbx },
|
||||
{ 44, -1, ppc_sth },
|
||||
{ 31, 918, ppc_sthbrx },
|
||||
{ 45, -1, ppc_sthu },
|
||||
{ 31, 439, ppc_sthux },
|
||||
{ 31, 407, ppc_sthx },
|
||||
{ 47, -1, ppc_stmw },
|
||||
{ 31, 725, ppc_stswi },
|
||||
{ 31, 661, ppc_stswx },
|
||||
{ 36, -1, ppc_stw },
|
||||
{ 31, 662, ppc_stwbrx },
|
||||
{ 31, 150, ppc_stwcx_rc },
|
||||
{ 37, -1, ppc_stwu },
|
||||
{ 31, 183, ppc_stwux },
|
||||
{ 31, 151, ppc_stwx },
|
||||
{ 31, 40, ppc_subfx },
|
||||
{ 31, 40 | 512, ppc_subfx },
|
||||
{ 31, 8, ppc_subfcx },
|
||||
{ 31, 8 | 512, ppc_subfcx },
|
||||
{ 31, 136, ppc_subfex },
|
||||
{ 31, 136 | 512, ppc_subfex },
|
||||
{ 8, -1, ppc_subfic },
|
||||
{ 31, 232, ppc_subfmex },
|
||||
{ 31, 232 | 512, ppc_subfmex },
|
||||
{ 31, 200, ppc_subfzex },
|
||||
{ 31, 200 | 512, ppc_subfzex },
|
||||
{ 31, 598, ppc_sync },
|
||||
{ 31, 4, ppc_tw },
|
||||
{ 3, -1, ppc_twi },
|
||||
{ 31, 316, ppc_xorx },
|
||||
{ 26, -1, ppc_xori },
|
||||
{ 27, -1, ppc_xoris }
|
||||
};
|
1298
unzip/unzip.c
Normal file
1298
unzip/unzip.c
Normal file
File diff suppressed because it is too large
Load diff
274
unzip/unzip.h
Normal file
274
unzip/unzip.h
Normal file
|
@ -0,0 +1,274 @@
|
|||
/* unzip.h -- IO for uncompress .zip files using zlib
|
||||
Version 0.15 beta, Mar 19th, 1998,
|
||||
|
||||
Copyright (C) 1998 Gilles Vollant
|
||||
|
||||
This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g
|
||||
WinZip, InfoZip tools and compatible.
|
||||
Encryption and multi volume ZipFile (span) are not supported.
|
||||
Old compressions used by old PKZip 1.x are not supported
|
||||
|
||||
THIS IS AN ALPHA VERSION. AT THIS STAGE OF DEVELOPPEMENT, SOMES API OR STRUCTURE
|
||||
CAN CHANGE IN FUTURE VERSION !!
|
||||
I WAIT FEEDBACK at mail info@winimage.com
|
||||
Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution
|
||||
|
||||
Condition of use and distribution are the same than zlib :
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* for more info about .ZIP format, see
|
||||
ftp://ftp.cdrom.com/pub/infozip/doc/appnote-970311-iz.zip
|
||||
PkWare has also a specification at :
|
||||
ftp://ftp.pkware.com/probdesc.zip */
|
||||
|
||||
#ifndef _unz_H
|
||||
#define _unz_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef _ZLIB_H
|
||||
#include "zlib.h"
|
||||
#endif
|
||||
|
||||
#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
|
||||
/* like the STRICT of WIN32, we define a pointer that cannot be converted
|
||||
from (void*) without cast */
|
||||
typedef struct TagunzFile__ { int unused; } unzFile__;
|
||||
typedef unzFile__ *unzFile;
|
||||
#else
|
||||
typedef voidp unzFile;
|
||||
#endif
|
||||
|
||||
|
||||
#define UNZ_OK (0)
|
||||
#define UNZ_END_OF_LIST_OF_FILE (-100)
|
||||
#define UNZ_ERRNO (Z_ERRNO)
|
||||
#define UNZ_EOF (0)
|
||||
#define UNZ_PARAMERROR (-102)
|
||||
#define UNZ_BADZIPFILE (-103)
|
||||
#define UNZ_INTERNALERROR (-104)
|
||||
#define UNZ_CRCERROR (-105)
|
||||
|
||||
/* tm_unz contain date/time info */
|
||||
typedef struct tm_unz_s
|
||||
{
|
||||
uInt tm_sec; /* seconds after the minute - [0,59] */
|
||||
uInt tm_min; /* minutes after the hour - [0,59] */
|
||||
uInt tm_hour; /* hours since midnight - [0,23] */
|
||||
uInt tm_mday; /* day of the month - [1,31] */
|
||||
uInt tm_mon; /* months since January - [0,11] */
|
||||
uInt tm_year; /* years - [1980..2044] */
|
||||
} tm_unz;
|
||||
|
||||
/* unz_global_info structure contain global data about the ZIPfile
|
||||
These data comes from the end of central dir */
|
||||
typedef struct unz_global_info_s
|
||||
{
|
||||
uLong number_entry; /* total number of entries in
|
||||
the central dir on this disk */
|
||||
uLong size_comment; /* size of the global comment of the zipfile */
|
||||
} unz_global_info;
|
||||
|
||||
|
||||
/* unz_file_info contain information about a file in the zipfile */
|
||||
typedef struct unz_file_info_s
|
||||
{
|
||||
uLong version; /* version made by 2 bytes */
|
||||
uLong version_needed; /* version needed to extract 2 bytes */
|
||||
uLong flag; /* general purpose bit flag 2 bytes */
|
||||
uLong compression_method; /* compression method 2 bytes */
|
||||
uLong dosDate; /* last mod file date in Dos fmt 4 bytes */
|
||||
uLong crc; /* crc-32 4 bytes */
|
||||
uLong compressed_size; /* compressed size 4 bytes */
|
||||
uLong uncompressed_size; /* uncompressed size 4 bytes */
|
||||
uLong size_filename; /* filename length 2 bytes */
|
||||
uLong size_file_extra; /* extra field length 2 bytes */
|
||||
uLong size_file_comment; /* file comment length 2 bytes */
|
||||
|
||||
uLong disk_num_start; /* disk number start 2 bytes */
|
||||
uLong internal_fa; /* internal file attributes 2 bytes */
|
||||
uLong external_fa; /* external file attributes 4 bytes */
|
||||
|
||||
tm_unz tmu_date;
|
||||
} unz_file_info;
|
||||
|
||||
extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1,
|
||||
const char* fileName2,
|
||||
int iCaseSensitivity));
|
||||
/*
|
||||
Compare two filename (fileName1,fileName2).
|
||||
If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
|
||||
If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
|
||||
or strcasecmp)
|
||||
If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
|
||||
(like 1 on Unix, 2 on Windows)
|
||||
*/
|
||||
|
||||
|
||||
extern unzFile ZEXPORT unzOpen OF((const char *path));
|
||||
/*
|
||||
Open a Zip file. path contain the full pathname (by example,
|
||||
on a Windows NT computer "c:\\zlib\\zlib111.zip" or on an Unix computer
|
||||
"zlib/zlib111.zip".
|
||||
If the zipfile cannot be opened (file don't exist or in not valid), the
|
||||
return value is NULL.
|
||||
Else, the return value is a unzFile Handle, usable with other function
|
||||
of this unzip package.
|
||||
*/
|
||||
|
||||
extern int ZEXPORT unzClose OF((unzFile file));
|
||||
/*
|
||||
Close a ZipFile opened with unzipOpen.
|
||||
If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
|
||||
these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
|
||||
return UNZ_OK if there is no problem. */
|
||||
|
||||
extern int ZEXPORT unzGetGlobalInfo OF((unzFile file,
|
||||
unz_global_info *pglobal_info));
|
||||
/*
|
||||
Write info about the ZipFile in the *pglobal_info structure.
|
||||
No preparation of the structure is needed
|
||||
return UNZ_OK if there is no problem. */
|
||||
|
||||
|
||||
extern int ZEXPORT unzGetGlobalComment OF((unzFile file,
|
||||
char *szComment,
|
||||
uLong uSizeBuf));
|
||||
/*
|
||||
Get the global comment string of the ZipFile, in the szComment buffer.
|
||||
uSizeBuf is the size of the szComment buffer.
|
||||
return the number of byte copied or an error code <0
|
||||
*/
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
/* Unzip package allow you browse the directory of the zipfile */
|
||||
|
||||
extern int ZEXPORT unzGoToFirstFile OF((unzFile file));
|
||||
/*
|
||||
Set the current file of the zipfile to the first file.
|
||||
return UNZ_OK if there is no problem
|
||||
*/
|
||||
|
||||
extern int ZEXPORT unzGoToNextFile OF((unzFile file));
|
||||
/*
|
||||
Set the current file of the zipfile to the next file.
|
||||
return UNZ_OK if there is no problem
|
||||
return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
|
||||
*/
|
||||
|
||||
extern int ZEXPORT unzLocateFile OF((unzFile file,
|
||||
const char *szFileName,
|
||||
int iCaseSensitivity));
|
||||
/*
|
||||
Try locate the file szFileName in the zipfile.
|
||||
For the iCaseSensitivity signification, see unzStringFileNameCompare
|
||||
|
||||
return value :
|
||||
UNZ_OK if the file is found. It becomes the current file.
|
||||
UNZ_END_OF_LIST_OF_FILE if the file is not found
|
||||
*/
|
||||
|
||||
|
||||
extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file,
|
||||
unz_file_info *pfile_info,
|
||||
char *szFileName,
|
||||
uLong fileNameBufferSize,
|
||||
void *extraField,
|
||||
uLong extraFieldBufferSize,
|
||||
char *szComment,
|
||||
uLong commentBufferSize));
|
||||
/*
|
||||
Get Info about the current file
|
||||
if pfile_info!=NULL, the *pfile_info structure will contain somes info about
|
||||
the current file
|
||||
if szFileName!=NULL, the filemane string will be copied in szFileName
|
||||
(fileNameBufferSize is the size of the buffer)
|
||||
if extraField!=NULL, the extra field information will be copied in extraField
|
||||
(extraFieldBufferSize is the size of the buffer).
|
||||
This is the Central-header version of the extra field
|
||||
if szComment!=NULL, the comment string of the file will be copied in szComment
|
||||
(commentBufferSize is the size of the buffer)
|
||||
*/
|
||||
|
||||
/***************************************************************************/
|
||||
/* for reading the content of the current zipfile, you can open it, read data
|
||||
from it, and close it (you can close it before reading all the file)
|
||||
*/
|
||||
|
||||
extern int ZEXPORT unzOpenCurrentFile OF((unzFile file));
|
||||
/*
|
||||
Open for reading data the current file in the zipfile.
|
||||
If there is no error, the return value is UNZ_OK.
|
||||
*/
|
||||
|
||||
extern int ZEXPORT unzCloseCurrentFile OF((unzFile file));
|
||||
/*
|
||||
Close the file in zip opened with unzOpenCurrentFile
|
||||
Return UNZ_CRCERROR if all the file was read but the CRC is not good
|
||||
*/
|
||||
|
||||
|
||||
extern int ZEXPORT unzReadCurrentFile OF((unzFile file,
|
||||
voidp buf,
|
||||
unsigned len));
|
||||
/*
|
||||
Read bytes from the current file (opened by unzOpenCurrentFile)
|
||||
buf contain buffer where data must be copied
|
||||
len the size of buf.
|
||||
|
||||
return the number of byte copied if somes bytes are copied
|
||||
return 0 if the end of file was reached
|
||||
return <0 with error code if there is an error
|
||||
(UNZ_ERRNO for IO error, or zLib error for uncompress error)
|
||||
*/
|
||||
|
||||
extern z_off_t ZEXPORT unztell OF((unzFile file));
|
||||
/*
|
||||
Give the current position in uncompressed data
|
||||
*/
|
||||
|
||||
extern int ZEXPORT unzeof OF((unzFile file));
|
||||
/*
|
||||
return 1 if the end of file was reached, 0 elsewhere
|
||||
*/
|
||||
|
||||
extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file,
|
||||
voidp buf,
|
||||
unsigned len));
|
||||
/*
|
||||
Read extra field from the current file (opened by unzOpenCurrentFile)
|
||||
This is the local-header version of the extra field (sometimes, there is
|
||||
more info in the local-header version than in the central-header)
|
||||
|
||||
if buf==NULL, it return the size of the local extra field
|
||||
|
||||
if buf!=NULL, len is the size of the buffer, the extra header is copied in
|
||||
buf.
|
||||
the return value is the number of bytes copied in buf, or (if <0)
|
||||
the error code
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _unz_H */
|
1712
win32/dx9_renderer.c
Normal file
1712
win32/dx9_renderer.c
Normal file
File diff suppressed because it is too large
Load diff
38
win32/dx_render.h
Normal file
38
win32/dx_render.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Sega Model 3 Emulator
|
||||
* Copyright (C) 2003 Bart Trzynadlowski, Ville Linde, Stefano Teso
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 (license.txt); if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* win32/dx_render.h
|
||||
*
|
||||
* DirectX9 Renderer interface
|
||||
*/
|
||||
|
||||
#include "d3d9.h"
|
||||
#include "d3dx9.h"
|
||||
|
||||
#define RGB_REG 0xFFFF0000
|
||||
#define RGB_GREEN 0xFF00FF00
|
||||
#define RGB_BLUE 0xFF0000FF
|
||||
#define RGB_YELLOW 0xFFFFFF00
|
||||
#define RGB_CYAN 0xFF00FFFF
|
||||
|
||||
BOOL d3d_init(HWND);
|
||||
BOOL d3d_pre_init(void);
|
||||
void d3d_shutdown(void);
|
||||
D3DXMATRIX d3d_matrix_stack_get_top(void);
|
||||
void d3d_matrix_stack_init(void);
|
84
win32/osd.h
Normal file
84
win32/osd.h
Normal file
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Sega Model 3 Emulator
|
||||
* Copyright (C) 2003 Bart Trzynadlowski, Ville Linde, Stefano Teso
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 (license.txt); if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* win32/osd.h
|
||||
*
|
||||
* Win32 OSD header: Defines everything an OSD header needs to provide and
|
||||
* includes some Win32-specific files.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_WIN32_OSD_H
|
||||
#define INCLUDED_WIN32_OSD_H
|
||||
|
||||
/******************************************************************/
|
||||
/* Win32-Specific Includes */
|
||||
/******************************************************************/
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
/******************************************************************/
|
||||
/* OSD Definitions */
|
||||
/******************************************************************/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define INLINE static _inline
|
||||
#endif
|
||||
|
||||
#ifdef __GCC__
|
||||
#define INLINE static __inline__
|
||||
#endif
|
||||
|
||||
/******************************************************************/
|
||||
/* OSD Fundamental Data Types */
|
||||
/******************************************************************/
|
||||
|
||||
typedef unsigned int FLAGS; // for storage of bit flags
|
||||
|
||||
#ifdef __GCC__
|
||||
|
||||
typedef int BOOL; // 0 (false) or non-zero (true)
|
||||
|
||||
typedef signed int INT; // optimal signed integer
|
||||
typedef unsigned int UINT; // optimal unsigned integer
|
||||
typedef signed char CHAR; // signed character (for text)
|
||||
typedef unsigned char UCHAR; // unsigned character
|
||||
|
||||
typedef signed char INT8;
|
||||
typedef unsigned char UINT8;
|
||||
typedef signed short INT16;
|
||||
typedef unsigned short UINT16;
|
||||
typedef signed int INT32;
|
||||
typedef unsigned int UINT32;
|
||||
|
||||
#ifdef _MSC_VER // Microsoft VisualC++ (for versions 6.0 or older, non-C99)
|
||||
typedef signed __int64 INT64;
|
||||
typedef unsigned __int64 UINT64;
|
||||
#else // assume a C99-compliant compiler
|
||||
typedef signed long long INT64;
|
||||
typedef unsigned long long UINT64;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
typedef float FLOAT32; // single precision (32-bit)
|
||||
typedef double FLOAT64; // double precision (64-bit)
|
||||
|
||||
#endif // INCLUDED_WIN32_OSD_H
|
||||
|
57
win32/pixel_shader.ps
Normal file
57
win32/pixel_shader.ps
Normal file
|
@ -0,0 +1,57 @@
|
|||
ps_3_0
|
||||
|
||||
; input declarations
|
||||
dcl_color0 v0.xyzw
|
||||
dcl_texcoord0 v1.xyzw
|
||||
dcl_texcoord1 v2.xyzw
|
||||
dcl_texcoord2 v3.xyzw
|
||||
dcl_color1 v4.xyzw
|
||||
|
||||
dcl_2d s0
|
||||
|
||||
; constants
|
||||
def c0, 1.0f, 0.0f, 0.0f, 0.5f
|
||||
def c1, 0.00048828125f, 0.000244140625f, 0.0f, 0.0f
|
||||
|
||||
|
||||
|
||||
rcp r30, v2.z ; calculate 1/width
|
||||
rcp r31, v2.w ; calculate 1/height
|
||||
|
||||
mov r31.xy, c0.yy ; r31.xy <- 0,0 \ hopefully co-issue...
|
||||
mov r31.z, r30.z ; /
|
||||
|
||||
add r1.xyzw, v1.xyxy, r31.yyzy ; texel[0][0], texel[1][0]
|
||||
add r2.xyzw, v1.xyxy, r31.ywzw ; texel[0][1], texel[1][1]
|
||||
frc r1.xyzw, r1.xyzw
|
||||
frc r2.xyzw, r2.xyzw
|
||||
mul r3, r1, v2.zwzw ; mul by width, height
|
||||
mul r4, r2, v2.zwzw ; mul by width, height
|
||||
add r10, r3, v2.xyxy ; add tex base
|
||||
add r11, r4, v2.xyxy ; add tex base
|
||||
mul r10, r10, c1.xyxy ; div by 2048
|
||||
mul r11, r11, c1.xyxy ; div by 2048
|
||||
|
||||
frc r18, r3
|
||||
|
||||
texld r5, r10.xy, s0
|
||||
texld r6, r10.zw, s0
|
||||
texld r7, r11.xy, s0
|
||||
texld r8, r11.zw, s0
|
||||
|
||||
lrp r12, r18.xxxx, r6, r5
|
||||
lrp r13, r18.xxxx, r8, r7
|
||||
lrp r15, r18.yyyy, r13, r12
|
||||
|
||||
;if_lt v0.a, c0.x ; if polygon alpha is enabled use that instead of texture alpha
|
||||
; mov r15.a, v0.a
|
||||
;endif
|
||||
|
||||
if_ne v4.x, c0.y ; if v4.x == 0 -> color, if v4.x != -> texture
|
||||
mul_sat r15, v0, r15 ; modulate with color
|
||||
else
|
||||
mov r15, v0
|
||||
endif
|
||||
;mov r15, v0
|
||||
|
||||
mov oC0, r15
|
38
win32/pixel_shader_2d.ps
Normal file
38
win32/pixel_shader_2d.ps
Normal file
|
@ -0,0 +1,38 @@
|
|||
ps_3_0
|
||||
|
||||
; parameters
|
||||
; c8 = color offset
|
||||
; c9 = (X,Y) scroll position, (Z) 0 = rendering background, 1 = rendering foreground
|
||||
|
||||
; input declarations
|
||||
dcl_color v0.xyzw
|
||||
dcl_texcoord0 v1.xy
|
||||
|
||||
dcl_2d s0
|
||||
dcl_2d s1
|
||||
dcl_2d s2
|
||||
|
||||
def c0, 1.0, 0.0, 1.0f, 1.0f
|
||||
def c1, 0.5, 0.0, 0.0, 0.0
|
||||
|
||||
add r5, v1.xy, c9.xy ; add scroll position
|
||||
frc r5, r5 ; wrap
|
||||
|
||||
texld r0, r5, s0
|
||||
|
||||
texld r10, v1, s2 ; load priority value
|
||||
mov r11.r, c9.z
|
||||
|
||||
mov r1.xy, r0.ga
|
||||
texld r2, r1, s1
|
||||
|
||||
add r2.rgb, r2.rgb, c8.yzw
|
||||
min r2, r2, c0.xxxx ; clamp to 1.0
|
||||
max r2, r2, c0.yyyy ; clamp to 0.0
|
||||
|
||||
if_eq r11.r, c0.y ; invert priority if rendering foreground
|
||||
sub r10.r, c0.x, r10.r
|
||||
endif
|
||||
mul r2.a, r2.a, r10.r ; multiply alpha with priority
|
||||
|
||||
mov oC0, r2
|
106
win32/shaders.h
Normal file
106
win32/shaders.h
Normal file
|
@ -0,0 +1,106 @@
|
|||
unsigned char pixel_shader_source[524] =
|
||||
{
|
||||
0x00, 0x03, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x02, 0x0A, 0x00, 0x00, 0x80, 0x00, 0x00, 0x0F, 0x90,
|
||||
0x1F, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x80, 0x01, 0x00, 0x0F, 0x90, 0x1F, 0x00, 0x00, 0x02,
|
||||
0x05, 0x00, 0x01, 0x80, 0x02, 0x00, 0x0F, 0x90, 0x1F, 0x00, 0x00, 0x02, 0x05, 0x00, 0x02, 0x80,
|
||||
0x03, 0x00, 0x0F, 0x90, 0x1F, 0x00, 0x00, 0x02, 0x0A, 0x00, 0x01, 0x80, 0x04, 0x00, 0x0F, 0x90,
|
||||
0x1F, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x90, 0x00, 0x08, 0x0F, 0xA0, 0x51, 0x00, 0x00, 0x05,
|
||||
0x00, 0x00, 0x0F, 0xA0, 0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x3F, 0x51, 0x00, 0x00, 0x05, 0x01, 0x00, 0x0F, 0xA0, 0x00, 0x00, 0x00, 0x3A,
|
||||
0x00, 0x00, 0x80, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02,
|
||||
0x1E, 0x00, 0x0F, 0x80, 0x02, 0x00, 0xAA, 0x90, 0x06, 0x00, 0x00, 0x02, 0x1F, 0x00, 0x0F, 0x80,
|
||||
0x02, 0x00, 0xFF, 0x90, 0x01, 0x00, 0x00, 0x02, 0x1F, 0x00, 0x03, 0x80, 0x00, 0x00, 0x55, 0xA0,
|
||||
0x01, 0x00, 0x00, 0x02, 0x1F, 0x00, 0x04, 0x80, 0x1E, 0x00, 0xAA, 0x80, 0x02, 0x00, 0x00, 0x03,
|
||||
0x01, 0x00, 0x0F, 0x80, 0x01, 0x00, 0x44, 0x90, 0x1F, 0x00, 0x65, 0x80, 0x02, 0x00, 0x00, 0x03,
|
||||
0x02, 0x00, 0x0F, 0x80, 0x01, 0x00, 0x44, 0x90, 0x1F, 0x00, 0xED, 0x80, 0x13, 0x00, 0x00, 0x02,
|
||||
0x01, 0x00, 0x0F, 0x80, 0x01, 0x00, 0xE4, 0x80, 0x13, 0x00, 0x00, 0x02, 0x02, 0x00, 0x0F, 0x80,
|
||||
0x02, 0x00, 0xE4, 0x80, 0x05, 0x00, 0x00, 0x03, 0x03, 0x00, 0x0F, 0x80, 0x01, 0x00, 0xE4, 0x80,
|
||||
0x02, 0x00, 0xEE, 0x90, 0x05, 0x00, 0x00, 0x03, 0x04, 0x00, 0x0F, 0x80, 0x02, 0x00, 0xE4, 0x80,
|
||||
0x02, 0x00, 0xEE, 0x90, 0x02, 0x00, 0x00, 0x03, 0x0A, 0x00, 0x0F, 0x80, 0x03, 0x00, 0xE4, 0x80,
|
||||
0x02, 0x00, 0x44, 0x90, 0x02, 0x00, 0x00, 0x03, 0x0B, 0x00, 0x0F, 0x80, 0x04, 0x00, 0xE4, 0x80,
|
||||
0x02, 0x00, 0x44, 0x90, 0x05, 0x00, 0x00, 0x03, 0x0A, 0x00, 0x0F, 0x80, 0x0A, 0x00, 0xE4, 0x80,
|
||||
0x01, 0x00, 0x44, 0xA0, 0x05, 0x00, 0x00, 0x03, 0x0B, 0x00, 0x0F, 0x80, 0x0B, 0x00, 0xE4, 0x80,
|
||||
0x01, 0x00, 0x44, 0xA0, 0x13, 0x00, 0x00, 0x02, 0x12, 0x00, 0x0F, 0x80, 0x03, 0x00, 0xE4, 0x80,
|
||||
0x42, 0x00, 0x00, 0x03, 0x05, 0x00, 0x0F, 0x80, 0x0A, 0x00, 0x54, 0x80, 0x00, 0x08, 0xE4, 0xA0,
|
||||
0x42, 0x00, 0x00, 0x03, 0x06, 0x00, 0x0F, 0x80, 0x0A, 0x00, 0xFE, 0x80, 0x00, 0x08, 0xE4, 0xA0,
|
||||
0x42, 0x00, 0x00, 0x03, 0x07, 0x00, 0x0F, 0x80, 0x0B, 0x00, 0x54, 0x80, 0x00, 0x08, 0xE4, 0xA0,
|
||||
0x42, 0x00, 0x00, 0x03, 0x08, 0x00, 0x0F, 0x80, 0x0B, 0x00, 0xFE, 0x80, 0x00, 0x08, 0xE4, 0xA0,
|
||||
0x12, 0x00, 0x00, 0x04, 0x0C, 0x00, 0x0F, 0x80, 0x12, 0x00, 0x00, 0x80, 0x06, 0x00, 0xE4, 0x80,
|
||||
0x05, 0x00, 0xE4, 0x80, 0x12, 0x00, 0x00, 0x04, 0x0D, 0x00, 0x0F, 0x80, 0x12, 0x00, 0x00, 0x80,
|
||||
0x08, 0x00, 0xE4, 0x80, 0x07, 0x00, 0xE4, 0x80, 0x12, 0x00, 0x00, 0x04, 0x0F, 0x00, 0x0F, 0x80,
|
||||
0x12, 0x00, 0x55, 0x80, 0x0D, 0x00, 0xE4, 0x80, 0x0C, 0x00, 0xE4, 0x80, 0x29, 0x00, 0x05, 0x02,
|
||||
0x04, 0x00, 0x00, 0x90, 0x00, 0x00, 0x55, 0xA0, 0x05, 0x00, 0x00, 0x03, 0x0F, 0x00, 0x1F, 0x80,
|
||||
0x00, 0x00, 0xE4, 0x90, 0x0F, 0x00, 0xE4, 0x80, 0x2A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02,
|
||||
0x0F, 0x00, 0x0F, 0x80, 0x00, 0x00, 0xE4, 0x90, 0x2B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02,
|
||||
0x00, 0x08, 0x0F, 0x80, 0x0F, 0x00, 0xE4, 0x80, 0xFF, 0xFF, 0x00, 0x00,
|
||||
};
|
||||
|
||||
unsigned char pixel_shader_2d_source[324] =
|
||||
{
|
||||
0x00, 0x03, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x02, 0x0A, 0x00, 0x00, 0x80, 0x00, 0x00, 0x0F, 0x90,
|
||||
0x1F, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x80, 0x01, 0x00, 0x03, 0x90, 0x1F, 0x00, 0x00, 0x02,
|
||||
0x00, 0x00, 0x00, 0x90, 0x00, 0x08, 0x0F, 0xA0, 0x1F, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x90,
|
||||
0x01, 0x08, 0x0F, 0xA0, 0x1F, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x90, 0x02, 0x08, 0x0F, 0xA0,
|
||||
0x51, 0x00, 0x00, 0x05, 0x00, 0x00, 0x0F, 0xA0, 0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x80, 0x3F, 0x51, 0x00, 0x00, 0x05, 0x01, 0x00, 0x0F, 0xA0,
|
||||
0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x02, 0x00, 0x00, 0x03, 0x05, 0x00, 0x0F, 0x80, 0x01, 0x00, 0x54, 0x90, 0x09, 0x00, 0x54, 0xA0,
|
||||
0x13, 0x00, 0x00, 0x02, 0x05, 0x00, 0x0F, 0x80, 0x05, 0x00, 0xE4, 0x80, 0x42, 0x00, 0x00, 0x03,
|
||||
0x00, 0x00, 0x0F, 0x80, 0x05, 0x00, 0xE4, 0x80, 0x00, 0x08, 0xE4, 0xA0, 0x42, 0x00, 0x00, 0x03,
|
||||
0x0A, 0x00, 0x0F, 0x80, 0x01, 0x00, 0xE4, 0x90, 0x02, 0x08, 0xE4, 0xA0, 0x01, 0x00, 0x00, 0x02,
|
||||
0x0B, 0x00, 0x01, 0x80, 0x09, 0x00, 0xAA, 0xA0, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x03, 0x80,
|
||||
0x00, 0x00, 0xFD, 0x80, 0x42, 0x00, 0x00, 0x03, 0x02, 0x00, 0x0F, 0x80, 0x01, 0x00, 0xE4, 0x80,
|
||||
0x01, 0x08, 0xE4, 0xA0, 0x02, 0x00, 0x00, 0x03, 0x02, 0x00, 0x07, 0x80, 0x02, 0x00, 0xA4, 0x80,
|
||||
0x08, 0x00, 0xF9, 0xA0, 0x0A, 0x00, 0x00, 0x03, 0x02, 0x00, 0x0F, 0x80, 0x02, 0x00, 0xE4, 0x80,
|
||||
0x00, 0x00, 0x00, 0xA0, 0x0B, 0x00, 0x00, 0x03, 0x02, 0x00, 0x0F, 0x80, 0x02, 0x00, 0xE4, 0x80,
|
||||
0x00, 0x00, 0x55, 0xA0, 0x29, 0x00, 0x02, 0x02, 0x0B, 0x00, 0x00, 0x80, 0x00, 0x00, 0x55, 0xA0,
|
||||
0x02, 0x00, 0x00, 0x03, 0x0A, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0xA0, 0x0A, 0x00, 0x00, 0x81,
|
||||
0x2B, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x02, 0x00, 0x08, 0x80, 0x02, 0x00, 0xFF, 0x80,
|
||||
0x0A, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x02, 0x00, 0x08, 0x0F, 0x80, 0x02, 0x00, 0xE4, 0x80,
|
||||
0xFF, 0xFF, 0x00, 0x00,
|
||||
};
|
||||
|
||||
unsigned char vertex_shader_source[500] =
|
||||
{
|
||||
0x00, 0x03, 0xFE, 0xFF, 0x1F, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x0F, 0x90,
|
||||
0x1F, 0x00, 0x00, 0x02, 0x0A, 0x00, 0x00, 0x80, 0x01, 0x00, 0x0F, 0x90, 0x1F, 0x00, 0x00, 0x02,
|
||||
0x05, 0x00, 0x00, 0x80, 0x02, 0x00, 0x0F, 0x90, 0x1F, 0x00, 0x00, 0x02, 0x05, 0x00, 0x01, 0x80,
|
||||
0x03, 0x00, 0x0F, 0x90, 0x1F, 0x00, 0x00, 0x02, 0x05, 0x00, 0x02, 0x80, 0x04, 0x00, 0x0F, 0x90,
|
||||
0x1F, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x80, 0x05, 0x00, 0x0F, 0x90, 0x1F, 0x00, 0x00, 0x02,
|
||||
0x0A, 0x00, 0x01, 0x80, 0x06, 0x00, 0x0F, 0x90, 0x1F, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x80,
|
||||
0x00, 0x00, 0x0F, 0xE0, 0x1F, 0x00, 0x00, 0x02, 0x0A, 0x00, 0x00, 0x80, 0x01, 0x00, 0x0F, 0xE0,
|
||||
0x1F, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x80, 0x02, 0x00, 0x0F, 0xE0, 0x1F, 0x00, 0x00, 0x02,
|
||||
0x05, 0x00, 0x01, 0x80, 0x03, 0x00, 0x0F, 0xE0, 0x1F, 0x00, 0x00, 0x02, 0x05, 0x00, 0x02, 0x80,
|
||||
0x04, 0x00, 0x0F, 0xE0, 0x1F, 0x00, 0x00, 0x02, 0x0A, 0x00, 0x01, 0x80, 0x05, 0x00, 0x0F, 0xE0,
|
||||
0x51, 0x00, 0x00, 0x05, 0x80, 0x00, 0x0F, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F,
|
||||
0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x80, 0x3F, 0x09, 0x00, 0x00, 0x03, 0x14, 0x00, 0x01, 0x80,
|
||||
0x00, 0x00, 0xE4, 0x90, 0x00, 0x00, 0xE4, 0xA0, 0x09, 0x00, 0x00, 0x03, 0x14, 0x00, 0x02, 0x80,
|
||||
0x00, 0x00, 0xE4, 0x90, 0x01, 0x00, 0xE4, 0xA0, 0x09, 0x00, 0x00, 0x03, 0x14, 0x00, 0x04, 0x80,
|
||||
0x00, 0x00, 0xE4, 0x90, 0x02, 0x00, 0xE4, 0xA0, 0x09, 0x00, 0x00, 0x03, 0x14, 0x00, 0x08, 0x80,
|
||||
0x00, 0x00, 0xE4, 0x90, 0x03, 0x00, 0xE4, 0xA0, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x0F, 0xE0,
|
||||
0x14, 0x00, 0xE4, 0x80, 0x17, 0x00, 0x00, 0x03, 0x04, 0x00, 0x07, 0x80, 0x05, 0x00, 0xE4, 0x90,
|
||||
0x04, 0x00, 0xE4, 0xA0, 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x0F, 0x80, 0x10, 0x00, 0xE4, 0xA1,
|
||||
0x08, 0x00, 0x00, 0x03, 0x03, 0x00, 0x0F, 0x80, 0x04, 0x00, 0xE4, 0x80, 0x02, 0x00, 0xE4, 0x80,
|
||||
0x0B, 0x00, 0x00, 0x03, 0x03, 0x00, 0x0F, 0x80, 0x03, 0x00, 0xE4, 0x80, 0x80, 0x00, 0x00, 0xA0,
|
||||
0x05, 0x00, 0x00, 0x03, 0x03, 0x00, 0x0F, 0x80, 0x03, 0x00, 0xE4, 0x80, 0x11, 0x00, 0x00, 0xA0,
|
||||
0x02, 0x00, 0x00, 0x03, 0x03, 0x00, 0x0F, 0x80, 0x03, 0x00, 0xE4, 0x80, 0x11, 0x00, 0x55, 0xA0,
|
||||
0x0A, 0x00, 0x00, 0x03, 0x03, 0x00, 0x0F, 0x80, 0x03, 0x00, 0xE4, 0x80, 0x80, 0x00, 0x55, 0xA0,
|
||||
0x29, 0x00, 0x05, 0x02, 0x06, 0x00, 0x00, 0x90, 0x80, 0x00, 0x00, 0xA0, 0x01, 0x00, 0x00, 0x02,
|
||||
0x03, 0x00, 0x07, 0x80, 0x06, 0x00, 0x00, 0x90, 0x2B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02,
|
||||
0x03, 0x00, 0x08, 0x80, 0x80, 0x00, 0xFF, 0xA0, 0x05, 0x00, 0x00, 0x03, 0x01, 0x00, 0x0F, 0xE0,
|
||||
0x01, 0x00, 0xE4, 0x90, 0x03, 0x00, 0xE4, 0x80, 0x01, 0x00, 0x00, 0x02, 0x0A, 0x00, 0x0F, 0x80,
|
||||
0x02, 0x00, 0xE4, 0x90, 0x01, 0x00, 0x00, 0x02, 0x0A, 0x00, 0x08, 0x80, 0x14, 0x00, 0xFF, 0x80,
|
||||
0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x0F, 0xE0, 0x0A, 0x00, 0xE4, 0x80, 0x01, 0x00, 0x00, 0x02,
|
||||
0x03, 0x00, 0x0F, 0xE0, 0x03, 0x00, 0xE4, 0x90, 0x01, 0x00, 0x00, 0x02, 0x04, 0x00, 0x0F, 0xE0,
|
||||
0x04, 0x00, 0xE4, 0x90, 0x01, 0x00, 0x00, 0x02, 0x05, 0x00, 0x01, 0xE0, 0x06, 0x00, 0x55, 0x90,
|
||||
0xFF, 0xFF, 0x00, 0x00,
|
||||
};
|
||||
|
||||
unsigned char vertex_shader_2d_source[80] =
|
||||
{
|
||||
0x00, 0x03, 0xFE, 0xFF, 0x1F, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x0F, 0x90,
|
||||
0x1F, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x80, 0x01, 0x00, 0x0F, 0x90, 0x1F, 0x00, 0x00, 0x02,
|
||||
0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x0F, 0xE0, 0x1F, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x80,
|
||||
0x01, 0x00, 0x0F, 0xE0, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0xE4, 0x90,
|
||||
0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x0F, 0xE0, 0x01, 0x00, 0xE4, 0x90, 0xFF, 0xFF, 0x00, 0x00,
|
||||
};
|
71
win32/vertex_shader.vs
Normal file
71
win32/vertex_shader.vs
Normal file
|
@ -0,0 +1,71 @@
|
|||
vs_3_0
|
||||
|
||||
; parameters
|
||||
; c0...c3 world-view-projection matrix
|
||||
; c4...c7 world-view matrix
|
||||
; c16 sun light vector
|
||||
; c17 sun ambient, diffuse intensity
|
||||
|
||||
; input declarations
|
||||
dcl_position v0
|
||||
dcl_color0 v1
|
||||
dcl_texcoord0 v2
|
||||
dcl_texcoord1 v3
|
||||
dcl_texcoord2 v4
|
||||
dcl_normal v5
|
||||
dcl_color1 v6
|
||||
|
||||
; output declarations
|
||||
dcl_position o0.xyzw
|
||||
dcl_color0 o1.xyzw
|
||||
dcl_texcoord0 o2.xyzw
|
||||
dcl_texcoord1 o3.xyzw
|
||||
dcl_texcoord2 o4.xyzw
|
||||
dcl_color1 o5.xyzw
|
||||
|
||||
; constants
|
||||
def c128, 0.0f, 1.0f, 0.5f, 1.0f
|
||||
|
||||
; transform position to projection space
|
||||
;dp4 o0.x, v0, c0
|
||||
;dp4 o0.y, v0, c1
|
||||
;dp4 o0.z, v0, c2
|
||||
;dp4 o0.w, v0, c3
|
||||
dp4 r20.x, v0, c0
|
||||
dp4 r20.y, v0, c1
|
||||
dp4 r20.z, v0, c2
|
||||
dp4 r20.w, v0, c3
|
||||
|
||||
mov o0, r20
|
||||
|
||||
; calculate parallel lighting
|
||||
m3x3 r4.xyz, v5, c4 ; transform N
|
||||
|
||||
mov r2, -c16
|
||||
dp3 r3, r4, r2 ; N dot L
|
||||
max r3, r3, c128.xxxx ; clamp negative values to 0
|
||||
|
||||
mul r3, r3, c17.xxxx ; scale with diffuse intensity
|
||||
add r3, r3, c17.yyyy ; add ambient intensity
|
||||
|
||||
min r3, r3, c128.yyyy
|
||||
|
||||
if_ne v6.xxxx, c128.xxxx ; if v6.x == 0 -> apply lighting, if v6.x != 0 -> self-luminance
|
||||
mov r3.xyz, v6.xxx ; self-luminance
|
||||
endif
|
||||
|
||||
mov r3.w, c128.w ; multiply alpha with 1
|
||||
|
||||
mul o1, v1, r3 ; modulate and write color
|
||||
;mov o1, r3
|
||||
|
||||
; move texture parameters
|
||||
mov r10,v2
|
||||
mov r10.w, r20.w
|
||||
mov o2, r10
|
||||
;mov o2, v2
|
||||
mov o3, v3
|
||||
mov o4, v4
|
||||
|
||||
; parameters (X=texture enable)
|
||||
mov o5.x, v6.g
|
14
win32/vertex_shader_2d.vs
Normal file
14
win32/vertex_shader_2d.vs
Normal file
|
@ -0,0 +1,14 @@
|
|||
vs_3_0
|
||||
|
||||
; input declarations
|
||||
dcl_position v0
|
||||
dcl_texcoord0 v1
|
||||
|
||||
; output declarations
|
||||
dcl_position o0.xyzw
|
||||
dcl_texcoord0 o1.xyzw
|
||||
|
||||
|
||||
|
||||
mov o0, v0
|
||||
mov o1, v1
|
181
win32/win_gl.c
Normal file
181
win32/win_gl.c
Normal file
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
* Sega Model 3 Emulator
|
||||
* Copyright (C) 2003 Bart Trzynadlowski, Ville Linde, Stefano Teso
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 (license.txt); if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* win32/win_gl.c
|
||||
*
|
||||
* Win32 OpenGL support. All of this will have to be rewritten to support
|
||||
* run-time mode changes and fullscreen modes.
|
||||
*
|
||||
* The only osd_renderer function implemented here is osd_renderer_blit().
|
||||
*/
|
||||
|
||||
#include "model3.h"
|
||||
#include "osd_common/osd_gl.h"
|
||||
#include <gl\gl.h>
|
||||
#include <gl\glu.h>
|
||||
#include <gl\glext.h>
|
||||
|
||||
/*
|
||||
* Window Context
|
||||
*/
|
||||
|
||||
static HGLRC hrc = 0; // OpenGL rendering context
|
||||
static HDC hdc = 0; // GDI device context
|
||||
static HINSTANCE hinstance; // application instance
|
||||
extern HWND main_window; // window handle
|
||||
|
||||
/*
|
||||
* void win_gl_init(UINT xres, UINT yres);
|
||||
*
|
||||
* Sets the rendering mode and initializes OpenGL.
|
||||
*
|
||||
* Parameters:
|
||||
* xres = Horizontal resolution in pixels.
|
||||
* yres = Vertical resolution.
|
||||
*/
|
||||
|
||||
void win_gl_init(UINT xres, UINT yres)
|
||||
{
|
||||
GLuint pixel_format;
|
||||
static PIXELFORMATDESCRIPTOR pfd = // must this be static?
|
||||
{
|
||||
sizeof(PIXELFORMATDESCRIPTOR), // size of structure
|
||||
1, // version (must be 1)
|
||||
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
|
||||
PFD_TYPE_RGBA, // RGBA pixels
|
||||
32, // color depth
|
||||
0, 0, 0, 0, 0, 0, // color bits ignored
|
||||
0, // no alpha buffer
|
||||
0, // ignore shift bit
|
||||
0, // no accumulation buffer
|
||||
0, 0, 0, 0, // accumulation bits ignored
|
||||
24, // 24-bit z-buffer
|
||||
0, // no stencil buffer
|
||||
0, // no auxilliary buffer
|
||||
PFD_MAIN_PLANE, // main drawing layer
|
||||
0, // reserved
|
||||
0, 0, 0 // layer masks ignored
|
||||
};
|
||||
|
||||
/*
|
||||
* Get window instance
|
||||
*/
|
||||
|
||||
hinstance = GetModuleHandle(NULL); // get window instance
|
||||
|
||||
/*
|
||||
* Get device context and find a pixel format
|
||||
*/
|
||||
|
||||
if (!(hdc = GetDC(main_window)))
|
||||
osd_error("Unable to create an OpenGL device context.");
|
||||
|
||||
if (!(pixel_format = ChoosePixelFormat(hdc, &pfd))) // find matching pixel format
|
||||
osd_error("Unable to find the required pixel format.");
|
||||
|
||||
if (!SetPixelFormat(hdc, pixel_format, &pfd))
|
||||
osd_error("Unable to set the required pixel format.");
|
||||
|
||||
/*
|
||||
* Get the rendering context and perform some GL initialization
|
||||
*/
|
||||
|
||||
if (!(hrc = wglCreateContext(hdc)))
|
||||
osd_error("Unable to create an OpenGL rendering context.");
|
||||
|
||||
if (!wglMakeCurrent(hdc, hrc))
|
||||
osd_error("Unable to activate the OpenGL rendering context.");
|
||||
|
||||
/*
|
||||
* Check for mirrored texture repeat extension
|
||||
*/
|
||||
|
||||
if (osd_gl_check_extension("GL_ARB_texture_mirrored_repeat"))
|
||||
osd_error("Your OpenGL implementation does not support mirrored texture repeating!");
|
||||
if (osd_gl_check_extension("GL_ARB_texture_env_combine"))
|
||||
osd_error("Your OpenGL implementation does not support texture combiner operations!");
|
||||
if (osd_gl_check_extension("GL_EXT_texture_lod_bias"))
|
||||
osd_error("Your OpenGL implementation does not support texture LOD bias selection!");
|
||||
if (osd_gl_check_extension("GL_ARB_vertex_buffer_object"))
|
||||
osd_error("Your OpenGL implementation does not support vertex buffer objects!");
|
||||
|
||||
/*
|
||||
* Initialize GL engine
|
||||
*/
|
||||
|
||||
osd_gl_set_mode(xres, yres);
|
||||
}
|
||||
|
||||
/*
|
||||
* void win_gl_shutdown(void);
|
||||
*
|
||||
* Shuts down the rendering mode mode meaning it releases the rendering and
|
||||
* device contexts.
|
||||
*/
|
||||
|
||||
void win_gl_shutdown(void)
|
||||
{
|
||||
osd_gl_unset_mode();
|
||||
|
||||
/*
|
||||
* If there is a rendering context, release it
|
||||
*/
|
||||
|
||||
if (hrc)
|
||||
{
|
||||
wglMakeCurrent(NULL, NULL);
|
||||
wglDeleteContext(hrc);
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is a device context, release it
|
||||
*/
|
||||
|
||||
if (hdc)
|
||||
ReleaseDC(main_window, hdc);
|
||||
}
|
||||
|
||||
/*
|
||||
* void osd_renderer_blit(void);
|
||||
*
|
||||
* Swaps the buffers to display what has been rendered in the last frame.
|
||||
*/
|
||||
|
||||
void osd_renderer_blit(void)
|
||||
{
|
||||
SwapBuffers(hdc);
|
||||
}
|
||||
|
||||
/*
|
||||
* void * osd_gl_get_proc_address(const char *);
|
||||
*
|
||||
* Calls wglGetProcAddress.
|
||||
*/
|
||||
|
||||
void * osd_gl_get_proc_address(const CHAR * id)
|
||||
{
|
||||
void * ptr = wglGetProcAddress(id);
|
||||
|
||||
if (ptr == NULL)
|
||||
error("GL proc %s not found!\n", id);
|
||||
else
|
||||
message(0, "found GL proc %s!", id);
|
||||
|
||||
return ptr;
|
||||
}
|
13
win32/win_gl.h
Normal file
13
win32/win_gl.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* win32/win_gl.h
|
||||
*
|
||||
* Windows OpenGL header.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_WIN32_WIN_GL_H
|
||||
#define INCLUDED_WIN32_WIN_GL_H
|
||||
|
||||
extern void win_gl_init(UINT, UINT);
|
||||
extern void win_gl_shutdown(void);
|
||||
|
||||
#endif // INCLUDED_WIN32_WIN_GL_H
|
319
win32/win_input.c
Normal file
319
win32/win_input.c
Normal file
|
@ -0,0 +1,319 @@
|
|||
/*
|
||||
* Sega Model 3 Emulator
|
||||
* Copyright (C) 2003 Bart Trzynadlowski, Ville Linde, Stefano Teso
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 (license.txt); if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/******************************************************************/
|
||||
/* DirectX 9 Input */
|
||||
/******************************************************************/
|
||||
|
||||
#include "MODEL3.H"
|
||||
#include <dinput.h>
|
||||
|
||||
static LPDIRECTINPUT8 dinput;
|
||||
static LPDIRECTINPUTDEVICE8 keyboard;
|
||||
static LPDIRECTINPUTDEVICE8 mouse;
|
||||
|
||||
static CHAR keyboard_buffer[256];
|
||||
static DIMOUSESTATE mouse_state;
|
||||
|
||||
extern HWND main_window;
|
||||
|
||||
static OSD_CONTROLS controls;
|
||||
|
||||
void osd_input_init(void)
|
||||
{
|
||||
HINSTANCE hinstance;
|
||||
HRESULT hr;
|
||||
|
||||
atexit(osd_input_shutdown);
|
||||
|
||||
hinstance = GetModuleHandle(NULL);
|
||||
hr = DirectInput8Create( hinstance, DIRECTINPUT_VERSION, &IID_IDirectInput8,
|
||||
(void**)&dinput, NULL );
|
||||
if(FAILED(hr))
|
||||
error("DirectInput8Create failed.");
|
||||
|
||||
// Create keyboard device
|
||||
hr = IDirectInput8_CreateDevice( dinput, &GUID_SysKeyboard, &keyboard, NULL );
|
||||
if(FAILED(hr))
|
||||
error("IDirectInput8_CreateDevice failed.");
|
||||
|
||||
hr = IDirectInputDevice8_SetDataFormat( keyboard, &c_dfDIKeyboard );
|
||||
if(FAILED(hr))
|
||||
error("IDirectInputDevice8_SetDataFormat failed.");
|
||||
|
||||
hr = IDirectInputDevice8_SetCooperativeLevel( keyboard, main_window, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE );
|
||||
if(FAILED(hr))
|
||||
error("IDirectInputDevice8_SetCooperativeLevel failed.");
|
||||
|
||||
if(keyboard)
|
||||
IDirectInputDevice8_Acquire( keyboard );
|
||||
|
||||
// Create mouse device
|
||||
hr = IDirectInput8_CreateDevice( dinput, &GUID_SysMouse, &mouse, NULL );
|
||||
if(FAILED(hr))
|
||||
error("IDirectInput8_CreateDevice failed.");
|
||||
|
||||
hr = IDirectInputDevice8_SetDataFormat( mouse, &c_dfDIMouse );
|
||||
if(FAILED(hr))
|
||||
error("IDirectInputDevice8_SetDataFormat failed.");
|
||||
|
||||
hr = IDirectInputDevice8_SetCooperativeLevel( mouse, main_window, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE );
|
||||
if(FAILED(hr))
|
||||
error("IDirectInputDevice8_SetCooperativeLevel failed.");
|
||||
}
|
||||
|
||||
void osd_input_shutdown(void)
|
||||
{
|
||||
if(dinput) {
|
||||
if(keyboard) {
|
||||
IDirectInputDevice8_Unacquire( keyboard );
|
||||
IDirectInputDevice8_Release( keyboard );
|
||||
keyboard = NULL;
|
||||
}
|
||||
if(mouse) {
|
||||
IDirectInputDevice8_Unacquire( mouse );
|
||||
IDirectInputDevice8_Release( mouse );
|
||||
mouse = NULL;
|
||||
}
|
||||
IDirectInput8_Release( dinput );
|
||||
dinput = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void input_update(void)
|
||||
{
|
||||
/* updates the input buffer */
|
||||
if(dinput) {
|
||||
// Get keyboard state
|
||||
IDirectInputDevice8_GetDeviceState( keyboard, sizeof(keyboard_buffer), &keyboard_buffer );
|
||||
// Get mouse state
|
||||
IDirectInputDevice8_Acquire( mouse );
|
||||
IDirectInputDevice8_GetDeviceState( mouse, sizeof(mouse_state), &mouse_state );
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL keyboard_get_key(UINT8 key)
|
||||
{
|
||||
if(keyboard_buffer[key] & 0x80)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL mouse_get_button(UINT8 button)
|
||||
{
|
||||
if(mouse_state.rgbButtons[button] & 0x80)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void mouse_get_position(INT32* xposition, INT32* yposition)
|
||||
{
|
||||
POINT mouse_pos;
|
||||
|
||||
GetCursorPos( &mouse_pos );
|
||||
ScreenToClient( main_window, &mouse_pos );
|
||||
|
||||
*xposition = mouse_pos.x + (400 - (MODEL3_SCREEN_WIDTH / 2));
|
||||
*yposition = mouse_pos.y + (272 - (MODEL3_SCREEN_HEIGHT / 2));
|
||||
}
|
||||
|
||||
OSD_CONTROLS* osd_input_update_controls(void)
|
||||
{
|
||||
INT32 mouse_x, mouse_y;
|
||||
input_update();
|
||||
|
||||
controls.game_controls[0] = 0xFF;
|
||||
controls.game_controls[1] = 0xFF;
|
||||
controls.system_controls[0] = 0xFF;
|
||||
controls.system_controls[1] = 0xFF;
|
||||
|
||||
// Lightgun
|
||||
if(mouse_get_button(0))
|
||||
controls.game_controls[0] &= ~0x01;
|
||||
|
||||
if(mouse_get_button(1))
|
||||
controls.gun_acquired[0] = TRUE;
|
||||
else
|
||||
controls.gun_acquired[0] = FALSE;
|
||||
|
||||
mouse_get_position(&mouse_x, &mouse_y);
|
||||
controls.gun_x[0] = mouse_x;
|
||||
controls.gun_y[0] = mouse_y;
|
||||
|
||||
// Game controls
|
||||
if(keyboard_get_key(DIK_A))
|
||||
controls.game_controls[0] &= ~0x01;
|
||||
if(keyboard_get_key(DIK_S))
|
||||
controls.game_controls[0] &= ~0x02;
|
||||
if(keyboard_get_key(DIK_D))
|
||||
controls.game_controls[0] &= ~0x04;
|
||||
if(keyboard_get_key(DIK_F))
|
||||
controls.game_controls[0] &= ~0x08;
|
||||
if(keyboard_get_key(DIK_G))
|
||||
controls.game_controls[0] &= ~0x80;
|
||||
if(keyboard_get_key(DIK_H))
|
||||
controls.game_controls[0] &= ~0x40;
|
||||
|
||||
if(keyboard_get_key(DIK_Q))
|
||||
controls.game_controls[0] &= ~0x80;
|
||||
if(keyboard_get_key(DIK_W))
|
||||
controls.game_controls[0] &= ~0x40;
|
||||
if(keyboard_get_key(DIK_E))
|
||||
controls.game_controls[0] &= ~0x20;
|
||||
if(keyboard_get_key(DIK_R))
|
||||
controls.game_controls[0] &= ~0x10;
|
||||
if(keyboard_get_key(DIK_T))
|
||||
controls.game_controls[1] &= ~0x80;
|
||||
if(keyboard_get_key(DIK_Y))
|
||||
controls.game_controls[1] &= ~0x40;
|
||||
if(keyboard_get_key(DIK_U))
|
||||
controls.game_controls[1] &= ~0x20;
|
||||
if(keyboard_get_key(DIK_I))
|
||||
controls.game_controls[1] &= ~0x10;
|
||||
|
||||
if(keyboard_get_key(DIK_Z)) // VON2, shot trigger 1
|
||||
controls.game_controls[0] &= ~0x01;
|
||||
if(keyboard_get_key(DIK_X)) // VON2, shot trigger 2
|
||||
controls.game_controls[1] &= ~0x01;
|
||||
if(keyboard_get_key(DIK_C)) // VON2, turbo 1
|
||||
controls.game_controls[0] &= ~0x02;
|
||||
if(keyboard_get_key(DIK_V)) // VON2, turbo 2
|
||||
controls.game_controls[1] &= ~0x02;
|
||||
|
||||
/*if(keyboard_get_key(DIK_UP) || keyboard_get_key(DIK_NUMPAD8)) {
|
||||
controls.game_controls[0] &= ~0x20; // VON2, forward
|
||||
controls.game_controls[1] &= ~0x20;
|
||||
}
|
||||
if(keyboard_get_key(DIK_DOWN) || keyboard_get_key(DIK_NUMPAD2)) {
|
||||
controls.game_controls[0] &= ~0x10; // VON2, backward
|
||||
controls.game_controls[1] &= ~0x10;
|
||||
}
|
||||
if(keyboard_get_key(DIK_LEFT) || keyboard_get_key(DIK_NUMPAD4)) {
|
||||
controls.game_controls[0] &= ~0x10; // VON2, turn left
|
||||
controls.game_controls[1] &= ~0x20;
|
||||
}
|
||||
if(keyboard_get_key(DIK_RIGHT) || keyboard_get_key(DIK_NUMPAD6)) {
|
||||
controls.game_controls[0] &= ~0x20; // VON2, turn right
|
||||
controls.game_controls[1] &= ~0x10;
|
||||
}*/
|
||||
if(keyboard_get_key(DIK_NUMPAD1)) {// VON2, strafe left
|
||||
controls.game_controls[0] &= ~0x80;
|
||||
controls.game_controls[1] &= ~0x80;
|
||||
}
|
||||
if(keyboard_get_key(DIK_NUMPAD3)) {// VON2, strafe right
|
||||
controls.game_controls[0] &= ~0x40;
|
||||
controls.game_controls[1] &= ~0x40;
|
||||
}
|
||||
if(keyboard_get_key(DIK_NUMPAD5)) {// VON2, jump
|
||||
controls.game_controls[0] &= ~0x80;
|
||||
controls.game_controls[1] &= ~0x40;
|
||||
}
|
||||
|
||||
// System controls
|
||||
if(keyboard_get_key(DIK_F1)) { // Test button
|
||||
controls.system_controls[0] &= ~0x04;
|
||||
controls.system_controls[1] &= ~0x04;
|
||||
}
|
||||
if(keyboard_get_key(DIK_F2)) { // Service button
|
||||
controls.system_controls[0] &= ~0x08;
|
||||
controls.system_controls[1] &= ~0x80;
|
||||
}
|
||||
if(keyboard_get_key(DIK_F3)) { // Start button
|
||||
controls.system_controls[0] &= ~0x10;
|
||||
}
|
||||
if(keyboard_get_key(DIK_F4)) { // Coin #1
|
||||
controls.system_controls[0] &= ~0x01;
|
||||
}
|
||||
|
||||
// Steering Wheel
|
||||
#if 0
|
||||
if(keyboard_get_key(DIK_LEFT))
|
||||
controls.steering -= 32;
|
||||
if(keyboard_get_key(DIK_RIGHT))
|
||||
controls.steering += 32;
|
||||
|
||||
if(controls.steering > 0) {
|
||||
controls.steering -= 16;
|
||||
if(controls.steering < 0)
|
||||
controls.steering = 0;
|
||||
} else {
|
||||
controls.steering += 16;
|
||||
if(controls.steering > 0)
|
||||
controls.steering = 0;
|
||||
}
|
||||
|
||||
if(controls.steering < -128)
|
||||
controls.steering = -128;
|
||||
if(controls.steering > 127)
|
||||
controls.steering = 127;
|
||||
|
||||
if(keyboard_get_key(DIK_UP))
|
||||
controls.acceleration += 32;
|
||||
else
|
||||
controls.acceleration -= 16;
|
||||
|
||||
if(controls.acceleration < 0)
|
||||
controls.acceleration = 0;
|
||||
if(controls.acceleration > 0xFF)
|
||||
controls.acceleration = 0xFF;
|
||||
|
||||
if(keyboard_get_key(DIK_DOWN))
|
||||
controls.brake += 32;
|
||||
else
|
||||
controls.brake -= 16;
|
||||
|
||||
if(controls.brake < 0)
|
||||
controls.brake = 0;
|
||||
if(controls.brake > 0xFF)
|
||||
controls.brake = 0xFF;
|
||||
#else
|
||||
|
||||
/* SWT Force Feedback joystick */
|
||||
if(keyboard_get_key(DIK_UP))
|
||||
controls.steering -= 16;
|
||||
if(keyboard_get_key(DIK_DOWN))
|
||||
controls.steering += 16;
|
||||
|
||||
if(controls.steering < -128)
|
||||
controls.steering = -128;
|
||||
if(controls.steering > 127)
|
||||
controls.steering = 127;
|
||||
|
||||
if(keyboard_get_key(DIK_RIGHT)) {
|
||||
controls.acceleration += 16;
|
||||
controls.brake -= 16;
|
||||
}
|
||||
if(keyboard_get_key(DIK_LEFT)) {
|
||||
controls.brake += 16;
|
||||
controls.acceleration -= 16;
|
||||
}
|
||||
|
||||
if(controls.acceleration < 0)
|
||||
controls.acceleration = 0;
|
||||
if(controls.acceleration > 0xFF)
|
||||
controls.acceleration = 0xFF;
|
||||
if(controls.brake < 0)
|
||||
controls.brake = 0;
|
||||
if(controls.brake > 0xFF)
|
||||
controls.brake = 0xFF;
|
||||
#endif
|
||||
|
||||
return &controls;
|
||||
}
|
463
win32/win_main.c
Normal file
463
win32/win_main.c
Normal file
|
@ -0,0 +1,463 @@
|
|||
/*
|
||||
* Sega Model 3 Emulator
|
||||
* Copyright (C) 2003 Bart Trzynadlowski, Ville Linde, Stefano Teso
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 (license.txt); if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/******************************************************************/
|
||||
/* Windows Main */
|
||||
/******************************************************************/
|
||||
|
||||
#include "model3.h"
|
||||
#ifdef RENDERER_D3D
|
||||
#include "dx_render.h"
|
||||
#else // RENDERER_GL
|
||||
#include "win_gl.h"
|
||||
#endif
|
||||
|
||||
#define XRES (496)
|
||||
#define YRES (384)
|
||||
|
||||
static CHAR app_title[] = "Supermodel";
|
||||
static CHAR app_version[] = "1.0";
|
||||
static CHAR class_name[] = "MODEL3";
|
||||
|
||||
static CHAR CONFIG_FILE[] = "config.xml";
|
||||
|
||||
HWND main_window;
|
||||
|
||||
// Window Procedure prototype
|
||||
static LRESULT CALLBACK win_window_proc(HWND, UINT, WPARAM, LPARAM);
|
||||
|
||||
static BOOL win_register_class(void)
|
||||
{
|
||||
WNDCLASSEX wcex;
|
||||
|
||||
wcex.cbSize = sizeof(WNDCLASSEX);
|
||||
wcex.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wcex.lpfnWndProc = (WNDPROC)win_window_proc;
|
||||
wcex.cbClsExtra = 0;
|
||||
wcex.cbWndExtra = 0;
|
||||
wcex.hInstance = GetModuleHandle(NULL);
|
||||
wcex.hIcon = NULL;
|
||||
wcex.hIconSm = NULL;
|
||||
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
|
||||
wcex.lpszMenuName = NULL;
|
||||
wcex.lpszClassName = class_name;
|
||||
|
||||
if (FAILED(RegisterClassEx(&wcex))) // MinGW: "comparison is always false due to limited range of data"
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL win_create_window(UINT xres, UINT yres)
|
||||
{
|
||||
DWORD frame_width, frame_height, caption_height;
|
||||
int width, height, window_width, window_height;
|
||||
|
||||
window_width = xres;
|
||||
window_height = yres;
|
||||
|
||||
frame_width = GetSystemMetrics(SM_CXSIZEFRAME);
|
||||
frame_height = GetSystemMetrics(SM_CYSIZEFRAME);
|
||||
caption_height = GetSystemMetrics(SM_CYCAPTION);
|
||||
|
||||
width = (window_width - 1) + (frame_width * 2);
|
||||
height = (window_height - 1) + (frame_height * 2) + caption_height;
|
||||
|
||||
main_window = CreateWindow(class_name,
|
||||
app_title,
|
||||
WS_CLIPSIBLINGS | WS_CLIPCHILDREN | // required for OpenGL
|
||||
WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT, // Window X & Y coords
|
||||
width - 1, height - 1, // Width & Height
|
||||
NULL, NULL, // Parent Window & Menu
|
||||
GetModuleHandle(NULL), NULL );
|
||||
|
||||
if (!main_window)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: This should actually return an error if something goes wrong, but
|
||||
* it doesn't matter now. This stuff probably needs to be rewritten anyway ;)
|
||||
*/
|
||||
static void win_destroy(void)
|
||||
{
|
||||
#ifdef RENDERER_D3D
|
||||
d3d_shutdown();
|
||||
#else // RENDERER_GL
|
||||
win_gl_shutdown();
|
||||
#endif
|
||||
DestroyWindow(main_window);
|
||||
UnregisterClass(class_name, GetModuleHandle(NULL));
|
||||
}
|
||||
|
||||
void *malloc_exec(int length)
|
||||
{
|
||||
void *ptr;
|
||||
ptr = VirtualAlloc(NULL, length, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||
|
||||
if (ptr == NULL)
|
||||
{
|
||||
error("malloc_exec %d failed\n", length);
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void free_exec(void *ptr)
|
||||
{
|
||||
if (VirtualFree(ptr, 0, MEM_RELEASE) == FALSE)
|
||||
{
|
||||
error("free_exec failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
BOOL check_cpu_features(void)
|
||||
{
|
||||
BOOL features_ok = TRUE;
|
||||
char cpuname[256];
|
||||
UINT32 cpu_version;
|
||||
UINT32 cpu_features;
|
||||
|
||||
memset(cpuname, 0, sizeof(cpuname));
|
||||
|
||||
__asm
|
||||
{
|
||||
// get cpu name string
|
||||
mov eax, 0x80000002
|
||||
cpuid
|
||||
mov dword ptr [cpuname+0 ], eax
|
||||
mov dword ptr [cpuname+4 ], ebx
|
||||
mov dword ptr [cpuname+8 ], ecx
|
||||
mov dword ptr [cpuname+12 ], edx
|
||||
mov eax, 0x80000003
|
||||
cpuid
|
||||
mov dword ptr [cpuname+16 ], eax
|
||||
mov dword ptr [cpuname+20 ], ebx
|
||||
mov dword ptr [cpuname+24 ], ecx
|
||||
mov dword ptr [cpuname+28 ], edx
|
||||
mov eax, 0x80000004
|
||||
cpuid
|
||||
mov dword ptr [cpuname+32 ], eax
|
||||
mov dword ptr [cpuname+36 ], ebx
|
||||
mov dword ptr [cpuname+40 ], ecx
|
||||
mov dword ptr [cpuname+44 ], edx
|
||||
|
||||
// get cpu version and features
|
||||
mov eax, 1
|
||||
cpuid
|
||||
mov [cpu_version], eax
|
||||
mov [cpu_features], edx
|
||||
}
|
||||
message(0, "CPU: %s", cpuname);
|
||||
if ((cpu_features & (1 << 15)) == 0)
|
||||
{
|
||||
message(0, "CPU doesn't support Conditional Move/Compare instructions");
|
||||
features_ok = FALSE;
|
||||
}
|
||||
if ((cpu_features & (1 << 23)) == 0)
|
||||
{
|
||||
message(0, "CPU doesn't support MMX instructions");
|
||||
features_ok = FALSE;
|
||||
}
|
||||
if ((cpu_features & (1 << 25)) == 0)
|
||||
{
|
||||
message(0, "CPU doesn't support SSE instructions");
|
||||
features_ok = FALSE;
|
||||
}
|
||||
if ((cpu_features & (1 << 26)) == 0)
|
||||
{
|
||||
message(0, "CPU doesn't support SSE2 instructions");
|
||||
features_ok = FALSE;
|
||||
}
|
||||
|
||||
if (features_ok == FALSE)
|
||||
{
|
||||
message(0, "The CPU doesn't meet the requirements, the program will not run further.");
|
||||
}
|
||||
return features_ok;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
MSG msg;
|
||||
BOOL quit = FALSE, do_fps;
|
||||
INT64 freq, time_start, time_end;
|
||||
char title[256];
|
||||
double fps = 0.0;
|
||||
int frame = 0;
|
||||
|
||||
if(argc < 2) {
|
||||
// Show usage
|
||||
printf("ERROR: not enough arguments.\n\n");
|
||||
printf("Usage: m3.exe [romset]\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
message(0, "%s v%s\n", app_title, app_version);
|
||||
|
||||
if (check_cpu_features() == FALSE)
|
||||
{
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (d3d_pre_init() == FALSE)
|
||||
{
|
||||
message(0, "The video card doesn't meet the requirements, the program will not run further.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
message(0, "");
|
||||
|
||||
// Load config
|
||||
|
||||
if (parse_config(CONFIG_FILE) == FALSE)
|
||||
{
|
||||
exit(1);
|
||||
}
|
||||
m3_config.layer_enable = 0xF;
|
||||
|
||||
// Parse command-line
|
||||
|
||||
strncpy(m3_config.game_id, argv[1], 8);
|
||||
m3_config.game_id[8] = '\0'; // in case game name was 8 or more chars
|
||||
|
||||
if (stricmp(m3_config.game_id, "lostwsga") == 0)
|
||||
{
|
||||
m3_config.has_lightgun = TRUE;
|
||||
}
|
||||
|
||||
// Some initialization
|
||||
|
||||
if (!win_register_class())
|
||||
{
|
||||
message(0, "win_register_class failed.");
|
||||
exit(1);
|
||||
}
|
||||
if (!win_create_window(XRES, YRES))
|
||||
{
|
||||
message(0, "win_create_window failed.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (model3_load() == FALSE)
|
||||
{
|
||||
message(0, "ROM loading failed");
|
||||
exit(1);
|
||||
}
|
||||
model3_init();
|
||||
model3_reset();
|
||||
|
||||
if (!d3d_init(main_window))
|
||||
{
|
||||
message(0, "d3d_init failed.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (osd_input_init() == FALSE)
|
||||
{
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Set window title to show the game name
|
||||
sprintf(title, "%s: %s", app_title, m3_config.game_name);
|
||||
SetWindowText(main_window, title);
|
||||
|
||||
// Now that everything works, we can show the window
|
||||
|
||||
ShowWindow(main_window, SW_SHOWNORMAL);
|
||||
SetForegroundWindow(main_window);
|
||||
SetFocus(main_window);
|
||||
UpdateWindow(main_window);
|
||||
|
||||
if (m3_config.fullscreen && !m3_config.has_lightgun)
|
||||
{
|
||||
ShowCursor(FALSE);
|
||||
}
|
||||
|
||||
if(QueryPerformanceFrequency((LARGE_INTEGER *)&freq))
|
||||
do_fps = TRUE;
|
||||
else
|
||||
do_fps = FALSE;
|
||||
|
||||
memset(&msg, 0, sizeof(MSG));
|
||||
while (quit == FALSE)
|
||||
{
|
||||
//QueryPerformanceCounter((LARGE_INTEGER *)&time_start);
|
||||
|
||||
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
|
||||
{
|
||||
if (msg.message == WM_QUIT)
|
||||
quit = TRUE;
|
||||
else
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
model3_run_frame();
|
||||
frame++;
|
||||
|
||||
// gather profiler stats
|
||||
|
||||
//QueryPerformanceCounter((LARGE_INTEGER *)&time_end);
|
||||
if (frame >= 5)
|
||||
{
|
||||
frame = 0;
|
||||
QueryPerformanceCounter((LARGE_INTEGER *)&time_end);
|
||||
fps = 5.0 / ((double)(time_end - time_start) / freq);
|
||||
|
||||
time_start = time_end;
|
||||
}
|
||||
|
||||
if (m3_config.show_fps)
|
||||
{
|
||||
//fps = 1.0 / ((double)(time_end - time_start) / freq);
|
||||
sprintf(title, "FPS: %.3f", fps);
|
||||
osd_renderer_draw_text(2, 2, title, 0xffff0000, TRUE);
|
||||
}
|
||||
|
||||
//osd_renderer_draw_text(2, 2, title, 0x00ff0000, TRUE);
|
||||
|
||||
osd_renderer_blit();
|
||||
|
||||
#ifdef _PROFILE_
|
||||
profile_print(prof);
|
||||
|
||||
printf(prof);
|
||||
#endif
|
||||
}
|
||||
|
||||
//for (i = 0; i < 32; i += 4)
|
||||
// printf("R%d=%08X\tR%d=%08X\tR%d=%08X\tR%d=%08X\n",
|
||||
// i + 0, ppc_get_reg(PPC_REG_R0 + i + 0),
|
||||
// i + 1, ppc_get_reg(PPC_REG_R0 + i + 1),
|
||||
// i + 2, ppc_get_reg(PPC_REG_R0 + i + 2),
|
||||
// i + 3, ppc_get_reg(PPC_REG_R0 + i + 3));
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void osd_warning()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void osd_error(CHAR * string)
|
||||
{
|
||||
printf("ERROR: %s\n",string);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK win_window_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
CHAR fname[13];
|
||||
static UINT xres = 496, yres = 384;
|
||||
|
||||
switch(message)
|
||||
{
|
||||
case WM_DESTROY:
|
||||
{
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_KEYDOWN:
|
||||
{
|
||||
switch (wParam)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
|
||||
case '7':
|
||||
m3_config.layer_enable ^= 1;
|
||||
break;
|
||||
case '8':
|
||||
m3_config.layer_enable ^= 2;
|
||||
break;
|
||||
case '9':
|
||||
m3_config.layer_enable ^= 4;
|
||||
break;
|
||||
case '0':
|
||||
m3_config.layer_enable ^= 8;
|
||||
break;
|
||||
case 0x36:
|
||||
m3_config.layer_enable = 0xF;
|
||||
break;
|
||||
case VK_ESCAPE:
|
||||
DestroyWindow(hWnd);
|
||||
break;
|
||||
/*case VK_F7:
|
||||
strncpy(fname, m3_config.game_id, 8);
|
||||
fname[8] = '\0';
|
||||
strcat(fname, ".sta");
|
||||
model3_save_state(fname);
|
||||
break;
|
||||
case VK_F8:
|
||||
strncpy(fname, m3_config.game_id, 8);
|
||||
fname[8] = '\0';
|
||||
strcat(fname, ".sta");
|
||||
model3_load_state(fname);
|
||||
break;*/
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_KEYUP:
|
||||
{
|
||||
switch (wParam)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
|
||||
case VK_F11:
|
||||
{
|
||||
if (m3_config.fps_limit)
|
||||
{
|
||||
m3_config.fps_limit = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
m3_config.fps_limit = TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VK_F12:
|
||||
{
|
||||
if (m3_config.show_fps)
|
||||
{
|
||||
m3_config.show_fps = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
m3_config.show_fps = TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
}
|
||||
return 0;
|
||||
}
|
463
win32/win_xinput.c
Normal file
463
win32/win_xinput.c
Normal file
|
@ -0,0 +1,463 @@
|
|||
/*
|
||||
* Sega Model 3 Emulator
|
||||
* Copyright (C) 2003 Bart Trzynadlowski, Ville Linde, Stefano Teso
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 (license.txt); if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/******************************************************************/
|
||||
/* XInput for Xbox360 controller */
|
||||
/******************************************************************/
|
||||
|
||||
#include "MODEL3.H"
|
||||
#include <dinput.h>
|
||||
#include <xinput.h>
|
||||
|
||||
static LPDIRECTINPUT8 dinput;
|
||||
static LPDIRECTINPUTDEVICE8 keyboard;
|
||||
static LPDIRECTINPUTDEVICE8 mouse;
|
||||
|
||||
static CHAR keyboard_buffer[256];
|
||||
static DIMOUSESTATE mouse_state;
|
||||
|
||||
extern HWND main_window;
|
||||
|
||||
static OSD_CONTROLS controls;
|
||||
|
||||
static int xbox_controllers[4];
|
||||
|
||||
|
||||
static int analog_axis[8];
|
||||
static BOOL button_state[16];
|
||||
|
||||
static struct
|
||||
{
|
||||
BOOL up, down, left, right;
|
||||
} joystick[4];
|
||||
|
||||
BOOL osd_input_init(void)
|
||||
{
|
||||
HINSTANCE hinstance;
|
||||
HRESULT hr;
|
||||
|
||||
DWORD result;
|
||||
XINPUT_STATE state;
|
||||
|
||||
atexit(osd_input_shutdown);
|
||||
|
||||
hinstance = GetModuleHandle(NULL);
|
||||
hr = DirectInput8Create( hinstance, DIRECTINPUT_VERSION, &IID_IDirectInput8,
|
||||
(void**)&dinput, NULL );
|
||||
if (FAILED(hr))
|
||||
{
|
||||
message(0, "DirectInput8Create failed.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Create keyboard device
|
||||
hr = IDirectInput8_CreateDevice( dinput, &GUID_SysKeyboard, &keyboard, NULL );
|
||||
if (FAILED(hr))
|
||||
{
|
||||
message(0, "IDirectInput8_CreateDevice failed.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
hr = IDirectInputDevice8_SetDataFormat( keyboard, &c_dfDIKeyboard );
|
||||
if (FAILED(hr))
|
||||
{
|
||||
message(0, "IDirectInputDevice8_SetDataFormat failed.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
hr = IDirectInputDevice8_SetCooperativeLevel( keyboard, main_window, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE );
|
||||
if (FAILED(hr))
|
||||
{
|
||||
message(0, "IDirectInputDevice8_SetCooperativeLevel failed.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (keyboard)
|
||||
{
|
||||
IDirectInputDevice8_Acquire( keyboard );
|
||||
}
|
||||
|
||||
// Create mouse device
|
||||
hr = IDirectInput8_CreateDevice( dinput, &GUID_SysMouse, &mouse, NULL );
|
||||
if (FAILED(hr))
|
||||
{
|
||||
message(0, "IDirectInput8_CreateDevice failed.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
hr = IDirectInputDevice8_SetDataFormat( mouse, &c_dfDIMouse );
|
||||
if (FAILED(hr))
|
||||
{
|
||||
message(0, "IDirectInputDevice8_SetDataFormat failed.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
hr = IDirectInputDevice8_SetCooperativeLevel( mouse, main_window, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE );
|
||||
if (FAILED(hr))
|
||||
{
|
||||
message(0, "IDirectInputDevice8_SetCooperativeLevel failed.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Init Xbox360 controllers
|
||||
ZeroMemory(&state, sizeof(XINPUT_STATE));
|
||||
|
||||
// Simply get the state of the controller from XInput.
|
||||
result = XInputGetState(0, &state);
|
||||
|
||||
if (result == ERROR_SUCCESS)
|
||||
{
|
||||
// Controller is connected
|
||||
xbox_controllers[0] = 1;
|
||||
message(0, "Xbox360 controller found!");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Controller is not connected
|
||||
xbox_controllers[0] = 0;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void osd_input_shutdown(void)
|
||||
{
|
||||
if(dinput)
|
||||
{
|
||||
if(keyboard)
|
||||
{
|
||||
IDirectInputDevice8_Unacquire( keyboard );
|
||||
IDirectInputDevice8_Release( keyboard );
|
||||
keyboard = NULL;
|
||||
}
|
||||
if(mouse)
|
||||
{
|
||||
IDirectInputDevice8_Unacquire( mouse );
|
||||
IDirectInputDevice8_Release( mouse );
|
||||
mouse = NULL;
|
||||
}
|
||||
IDirectInput8_Release( dinput );
|
||||
dinput = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void input_update(void)
|
||||
{
|
||||
/* updates the input buffer */
|
||||
if(dinput)
|
||||
{
|
||||
// Get keyboard state
|
||||
IDirectInputDevice8_GetDeviceState( keyboard, sizeof(keyboard_buffer), &keyboard_buffer );
|
||||
// Get mouse state
|
||||
IDirectInputDevice8_Acquire( mouse );
|
||||
IDirectInputDevice8_GetDeviceState( mouse, sizeof(mouse_state), &mouse_state );
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL keyboard_get_key(UINT8 key)
|
||||
{
|
||||
if (keyboard_buffer[key] & 0x80)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL mouse_get_button(UINT8 button)
|
||||
{
|
||||
if (mouse_state.rgbButtons[button] & 0x80)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void mouse_get_position(INT32* xposition, INT32* yposition)
|
||||
{
|
||||
POINT mouse_pos;
|
||||
|
||||
GetCursorPos( &mouse_pos );
|
||||
ScreenToClient( main_window, &mouse_pos );
|
||||
|
||||
*xposition = mouse_pos.x;
|
||||
*yposition = mouse_pos.y;
|
||||
}
|
||||
|
||||
static void update_controls_keyboard(void)
|
||||
{
|
||||
memset(button_state, 0, sizeof(button_state));
|
||||
memset(joystick, 0, sizeof(joystick));
|
||||
|
||||
if (keyboard_get_key(DIK_A)) button_state[0] = 1;
|
||||
if (keyboard_get_key(DIK_S)) button_state[1] = 1;
|
||||
if (keyboard_get_key(DIK_D)) button_state[2] = 1;
|
||||
if (keyboard_get_key(DIK_F)) button_state[3] = 1;
|
||||
if (keyboard_get_key(DIK_Z)) button_state[4] = 1;
|
||||
if (keyboard_get_key(DIK_X)) button_state[5] = 1;
|
||||
if (keyboard_get_key(DIK_C)) button_state[6] = 1;
|
||||
if (keyboard_get_key(DIK_V)) button_state[7] = 1;
|
||||
|
||||
if (keyboard_get_key(DIK_LEFT)) joystick[0].left = TRUE;
|
||||
if (keyboard_get_key(DIK_RIGHT)) joystick[0].right = TRUE;
|
||||
if (keyboard_get_key(DIK_UP)) joystick[0].up = TRUE;
|
||||
if (keyboard_get_key(DIK_DOWN)) joystick[0].down = TRUE;
|
||||
|
||||
if (keyboard_get_key(DIK_LEFT)) analog_axis[0] -= 16;
|
||||
if (keyboard_get_key(DIK_RIGHT)) analog_axis[0] += 16;
|
||||
if (keyboard_get_key(DIK_UP)) analog_axis[1] -= 16;
|
||||
if (keyboard_get_key(DIK_DOWN)) analog_axis[1] += 16;
|
||||
|
||||
if (analog_axis[0] < -128) analog_axis[0] = -128;
|
||||
if (analog_axis[0] > 127) analog_axis[0] = 127;
|
||||
if (analog_axis[1] < -128) analog_axis[1] = -128;
|
||||
if (analog_axis[1] > 127) analog_axis[1] = 127;
|
||||
}
|
||||
|
||||
static void update_controls_xbox(void)
|
||||
{
|
||||
XINPUT_STATE state;
|
||||
DWORD res;
|
||||
|
||||
memset(button_state, 0, sizeof(button_state));
|
||||
memset(analog_axis, 0, sizeof(analog_axis));
|
||||
memset(joystick, 0, sizeof(joystick));
|
||||
|
||||
res = XInputGetState(0, &state);
|
||||
if (res == ERROR_SUCCESS)
|
||||
{
|
||||
// Zero value if thumbsticks are within the dead zone
|
||||
if ((state.Gamepad.sThumbLX < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE &&
|
||||
state.Gamepad.sThumbLX > -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE))
|
||||
{
|
||||
state.Gamepad.sThumbLX = 0;
|
||||
}
|
||||
if ((state.Gamepad.sThumbLY < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE &&
|
||||
state.Gamepad.sThumbLY > -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE))
|
||||
{
|
||||
|
||||
state.Gamepad.sThumbLY = 0;
|
||||
}
|
||||
|
||||
if ((state.Gamepad.sThumbRX < XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE &&
|
||||
state.Gamepad.sThumbRX > -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE))
|
||||
{
|
||||
state.Gamepad.sThumbRX = 0;
|
||||
}
|
||||
if ((state.Gamepad.sThumbRY < XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE &&
|
||||
state.Gamepad.sThumbRY > -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE))
|
||||
{
|
||||
state.Gamepad.sThumbRY = 0;
|
||||
}
|
||||
|
||||
|
||||
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_A) button_state[0] = TRUE;
|
||||
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_B) button_state[1] = TRUE;
|
||||
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_X) button_state[2] = TRUE;
|
||||
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_Y) button_state[3] = TRUE;
|
||||
|
||||
if (state.Gamepad.sThumbLX < 0) joystick[0].left = TRUE;
|
||||
if (state.Gamepad.sThumbLX > 0) joystick[0].right = TRUE;
|
||||
if (state.Gamepad.sThumbLY < 0) joystick[0].up = TRUE;
|
||||
if (state.Gamepad.sThumbLY > 0) joystick[0].down = TRUE;
|
||||
|
||||
analog_axis[0] = state.Gamepad.sThumbLX / 256;
|
||||
analog_axis[1] = state.Gamepad.sThumbLY / 256;
|
||||
analog_axis[2] = state.Gamepad.bRightTrigger;
|
||||
analog_axis[3] = state.Gamepad.bLeftTrigger;
|
||||
analog_axis[4] = state.Gamepad.sThumbRX;
|
||||
analog_axis[5] = state.Gamepad.sThumbRY;
|
||||
}
|
||||
}
|
||||
|
||||
static int get_analog_axis(GAME_ANALOG axis)
|
||||
{
|
||||
switch (axis)
|
||||
{
|
||||
case ANALOG_AXIS_1: return analog_axis[0];
|
||||
case ANALOG_AXIS_2: return analog_axis[1];
|
||||
case ANALOG_AXIS_3: return analog_axis[2];
|
||||
case ANALOG_AXIS_4: return analog_axis[3];
|
||||
case ANALOG_AXIS_5: return analog_axis[4];
|
||||
case ANALOG_AXIS_6: return analog_axis[5];
|
||||
case ANALOG_AXIS_7: return analog_axis[6];
|
||||
case ANALOG_AXIS_8: return analog_axis[7];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL is_button_pressed(GAME_BUTTON button)
|
||||
{
|
||||
switch (button)
|
||||
{
|
||||
case P1_BUTTON_1: return button_state[0];
|
||||
case P1_BUTTON_2: return button_state[1];
|
||||
case P1_BUTTON_3: return button_state[2];
|
||||
case P1_BUTTON_4: return button_state[3];
|
||||
case P1_BUTTON_5: return button_state[4];
|
||||
case P1_BUTTON_6: return button_state[5];
|
||||
case P1_BUTTON_7: return button_state[6];
|
||||
case P1_BUTTON_8: return button_state[7];
|
||||
case P2_BUTTON_1: return button_state[8];
|
||||
case P2_BUTTON_2: return button_state[9];
|
||||
case P2_BUTTON_3: return button_state[10];
|
||||
case P2_BUTTON_4: return button_state[11];
|
||||
case P2_BUTTON_5: return button_state[12];
|
||||
case P2_BUTTON_6: return button_state[13];
|
||||
case P2_BUTTON_7: return button_state[14];
|
||||
case P2_BUTTON_8: return button_state[15];
|
||||
case P1_JOYSTICK_UP: return joystick[0].up;
|
||||
case P1_JOYSTICK_DOWN: return joystick[0].down;
|
||||
case P1_JOYSTICK_LEFT: return joystick[0].left;
|
||||
case P1_JOYSTICK_RIGHT: return joystick[0].right;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
OSD_CONTROLS* osd_input_update_controls(void)
|
||||
{
|
||||
int i;
|
||||
INT32 mouse_x, mouse_y;
|
||||
input_update();
|
||||
|
||||
controls.game_controls[0] = 0xFF;
|
||||
controls.game_controls[1] = 0xFF;
|
||||
controls.system_controls[0] = 0xFF;
|
||||
controls.system_controls[1] = 0xFF;
|
||||
|
||||
// Lightgun
|
||||
if(mouse_get_button(0))
|
||||
controls.game_controls[0] &= ~0x01;
|
||||
|
||||
if(mouse_get_button(1))
|
||||
controls.gun_acquired[0] = TRUE;
|
||||
else
|
||||
controls.gun_acquired[0] = FALSE;
|
||||
|
||||
mouse_get_position(&mouse_x, &mouse_y);
|
||||
if (!m3_config.fullscreen)
|
||||
{
|
||||
controls.gun_x[0] = mouse_x + (400 - (MODEL3_SCREEN_WIDTH / 2));
|
||||
controls.gun_y[0] = mouse_y + (272 - (MODEL3_SCREEN_HEIGHT / 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m3_config.stretch)
|
||||
{
|
||||
mouse_x = (mouse_x * 496) / m3_config.width;
|
||||
mouse_y = (mouse_y * 384) / m3_config.height;
|
||||
}
|
||||
|
||||
controls.gun_x[0] = mouse_x + (400 - (MODEL3_SCREEN_WIDTH / 2));
|
||||
controls.gun_y[0] = mouse_y + (272 - (MODEL3_SCREEN_HEIGHT / 2));
|
||||
}
|
||||
|
||||
// Game controls
|
||||
if (xbox_controllers[0])
|
||||
{
|
||||
update_controls_xbox();
|
||||
}
|
||||
else
|
||||
{
|
||||
update_controls_keyboard();
|
||||
}
|
||||
|
||||
// update button states
|
||||
for (i=0; i < 16; i++)
|
||||
{
|
||||
if (m3_config.controls.button[i].enabled)
|
||||
{
|
||||
if (is_button_pressed(m3_config.controls.button[i].mapping))
|
||||
{
|
||||
int set = m3_config.controls.button[i].control_set;
|
||||
controls.game_controls[set] &= ~m3_config.controls.button[i].control_bit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update analog controls
|
||||
for (i=0; i < 8; i++)
|
||||
{
|
||||
if (m3_config.controls.analog_axis[i].enabled)
|
||||
{
|
||||
int value = get_analog_axis(m3_config.controls.analog_axis[i].mapping);
|
||||
value += m3_config.controls.analog_axis[i].center;
|
||||
controls.analog_axis[i] = value;
|
||||
}
|
||||
}
|
||||
|
||||
// Lightgun hack for Star Wars Trilogy
|
||||
if (stricmp(m3_config.game_id, "swtrilgy") == 0)
|
||||
{
|
||||
mouse_get_position(&mouse_x, &mouse_y);
|
||||
|
||||
mouse_x = (mouse_x * 256) / ((m3_config.fullscreen) ? m3_config.width : 496);
|
||||
mouse_y = (mouse_y * 256) / ((m3_config.fullscreen) ? m3_config.height : 384);
|
||||
|
||||
controls.analog_axis[0] = mouse_y;
|
||||
controls.analog_axis[1] = mouse_x;
|
||||
|
||||
if (mouse_get_button(1))
|
||||
controls.game_controls[0] &= ~0x01;
|
||||
if (mouse_get_button(0))
|
||||
controls.game_controls[0] &= ~0x20;
|
||||
}
|
||||
|
||||
// System controls
|
||||
if (keyboard_get_key(DIK_F1)) // Service button
|
||||
{
|
||||
controls.system_controls[0] &= ~0x08;
|
||||
}
|
||||
if (keyboard_get_key(DIK_F2)) // Test button
|
||||
{
|
||||
controls.system_controls[0] &= ~0x04;
|
||||
}
|
||||
if (keyboard_get_key(DIK_F3)) // Service button B
|
||||
{
|
||||
controls.system_controls[1] &= ~0x40;
|
||||
}
|
||||
if (keyboard_get_key(DIK_F4)) // Test button B
|
||||
{
|
||||
controls.system_controls[1] &= ~0x80;
|
||||
}
|
||||
if (keyboard_get_key(DIK_1)) // Start button 1
|
||||
{
|
||||
controls.system_controls[0] &= ~0x10;
|
||||
}
|
||||
if (keyboard_get_key(DIK_2)) // Start button 2
|
||||
{
|
||||
controls.system_controls[0] &= ~0x20;
|
||||
}
|
||||
if (keyboard_get_key(DIK_5)) // Coin #1
|
||||
{
|
||||
controls.system_controls[0] &= ~0x01;
|
||||
}
|
||||
if (keyboard_get_key(DIK_6)) // Coin #2
|
||||
{
|
||||
controls.system_controls[0] &= ~0x02;
|
||||
}
|
||||
|
||||
return &controls;
|
||||
}
|
722
zlib/ChangeLog
Normal file
722
zlib/ChangeLog
Normal file
|
@ -0,0 +1,722 @@
|
|||
|
||||
ChangeLog file for zlib
|
||||
|
||||
Changes in 1.2.1 (17 November 2003)
|
||||
- Remove a tab in contrib/gzappend/gzappend.c
|
||||
- Update some interfaces in contrib for new zlib functions
|
||||
- Update zlib version number in some contrib entries
|
||||
- Add Windows CE definition for ptrdiff_t in zutil.h [Mai, Truta]
|
||||
- Support shared libraries on Hurd and KFreeBSD [Brown]
|
||||
- Fix error in NO_DIVIDE option of adler32.c
|
||||
|
||||
Changes in 1.2.0.8 (4 November 2003)
|
||||
- Update version in contrib/delphi/ZLib.pas and contrib/pascal/zlibpas.pas
|
||||
- Add experimental NO_DIVIDE #define in adler32.c
|
||||
- Possibly faster on some processors (let me know if it is)
|
||||
- Correct Z_BLOCK to not return on first inflate call if no wrap
|
||||
- Fix strm->data_type on inflate() return to correctly indicate EOB
|
||||
- Add deflatePrime() function for appending in the middle of a byte
|
||||
- Add contrib/gzappend for an example of appending to a stream
|
||||
- Update win32/DLL_FAQ.txt [Truta]
|
||||
- Delete Turbo C comment in README [Truta]
|
||||
- Improve some indentation in zconf.h [Truta]
|
||||
- Fix infinite loop on bad input in configure script [Church]
|
||||
- Fix gzeof() for concatenated gzip files [Johnson]
|
||||
- Add example to contrib/visual-basic.txt [Michael B.]
|
||||
- Add -p to mkdir's in Makefile.in [vda]
|
||||
- Fix configure to properly detect presence or lack of printf functions
|
||||
- Add AS400 support [Monnerat]
|
||||
- Add a little Cygwin support [Wilson]
|
||||
|
||||
Changes in 1.2.0.7 (21 September 2003)
|
||||
- Correct some debug formats in contrib/infback9
|
||||
- Cast a type in a debug statement in trees.c
|
||||
- Change search and replace delimiter in configure from % to # [Beebe]
|
||||
- Update contrib/untgz to 0.2 with various fixes [Truta]
|
||||
- Add build support for Amiga [Nikl]
|
||||
- Remove some directories in old that have been updated to 1.2
|
||||
- Add dylib building for Mac OS X in configure and Makefile.in
|
||||
- Remove old distribution stuff from Makefile
|
||||
- Update README to point to DLL_FAQ.txt, and add comment on Mac OS X
|
||||
- Update links in README
|
||||
|
||||
Changes in 1.2.0.6 (13 September 2003)
|
||||
- Minor FAQ updates
|
||||
- Update contrib/minizip to 1.00 [Vollant]
|
||||
- Remove test of gz functions in example.c when GZ_COMPRESS defined [Truta]
|
||||
- Update POSTINC comment for 68060 [Nikl]
|
||||
- Add contrib/infback9 with deflate64 decoding (unsupported)
|
||||
- For MVS define NO_vsnprintf and undefine FAR [van Burik]
|
||||
- Add pragma for fdopen on MVS [van Burik]
|
||||
|
||||
Changes in 1.2.0.5 (8 September 2003)
|
||||
- Add OF to inflateBackEnd() declaration in zlib.h
|
||||
- Remember start when using gzdopen in the middle of a file
|
||||
- Use internal off_t counters in gz* functions to properly handle seeks
|
||||
- Perform more rigorous check for distance-too-far in inffast.c
|
||||
- Add Z_BLOCK flush option to return from inflate at block boundary
|
||||
- Set strm->data_type on return from inflate
|
||||
- Indicate bits unused, if at block boundary, and if in last block
|
||||
- Replace size_t with ptrdiff_t in crc32.c, and check for correct size
|
||||
- Add condition so old NO_DEFLATE define still works for compatibility
|
||||
- FAQ update regarding the Windows DLL [Truta]
|
||||
- INDEX update: add qnx entry, remove aix entry [Truta]
|
||||
- Install zlib.3 into mandir [Wilson]
|
||||
- Move contrib/zlib_dll_FAQ.txt to win32/DLL_FAQ.txt; update [Truta]
|
||||
- Adapt the zlib interface to the new DLL convention guidelines [Truta]
|
||||
- Introduce ZLIB_WINAPI macro to allow the export of functions using
|
||||
the WINAPI calling convention, for Visual Basic [Vollant, Truta]
|
||||
- Update msdos and win32 scripts and makefiles [Truta]
|
||||
- Export symbols by name, not by ordinal, in win32/zlib.def [Truta]
|
||||
- Add contrib/ada [Anisimkov]
|
||||
- Move asm files from contrib/vstudio/vc70_32 to contrib/asm386 [Truta]
|
||||
- Rename contrib/asm386 to contrib/masmx86 [Truta, Vollant]
|
||||
- Add contrib/masm686 [Truta]
|
||||
- Fix offsets in contrib/inflate86 and contrib/masmx86/inffas32.asm
|
||||
[Truta, Vollant]
|
||||
- Update contrib/delphi; rename to contrib/pascal; add example [Truta]
|
||||
- Remove contrib/delphi2; add a new contrib/delphi [Truta]
|
||||
- Avoid inclusion of the nonstandard <memory.h> in contrib/iostream,
|
||||
and fix some method prototypes [Truta]
|
||||
- Fix the ZCR_SEED2 constant to avoid warnings in contrib/minizip
|
||||
[Truta]
|
||||
- Avoid the use of backslash (\) in contrib/minizip [Vollant]
|
||||
- Fix file time handling in contrib/untgz; update makefiles [Truta]
|
||||
- Update contrib/vstudio/vc70_32 to comply with the new DLL guidelines
|
||||
[Vollant]
|
||||
- Remove contrib/vstudio/vc15_16 [Vollant]
|
||||
- Rename contrib/vstudio/vc70_32 to contrib/vstudio/vc7 [Truta]
|
||||
- Update README.contrib [Truta]
|
||||
- Invert the assignment order of match_head and s->prev[...] in
|
||||
INSERT_STRING [Truta]
|
||||
- Compare TOO_FAR with 32767 instead of 32768, to avoid 16-bit warnings
|
||||
[Truta]
|
||||
- Compare function pointers with 0, not with NULL or Z_NULL [Truta]
|
||||
- Fix prototype of syncsearch in inflate.c [Truta]
|
||||
- Introduce ASMINF macro to be enabled when using an ASM implementation
|
||||
of inflate_fast [Truta]
|
||||
- Change NO_DEFLATE to NO_GZCOMPRESS [Truta]
|
||||
- Modify test_gzio in example.c to take a single file name as a
|
||||
parameter [Truta]
|
||||
- Exit the example.c program if gzopen fails [Truta]
|
||||
- Add type casts around strlen in example.c [Truta]
|
||||
- Remove casting to sizeof in minigzip.c; give a proper type
|
||||
to the variable compared with SUFFIX_LEN [Truta]
|
||||
- Update definitions of STDC and STDC99 in zconf.h [Truta]
|
||||
- Synchronize zconf.h with the new Windows DLL interface [Truta]
|
||||
- Use SYS16BIT instead of __32BIT__ to distinguish between
|
||||
16- and 32-bit platforms [Truta]
|
||||
- Use far memory allocators in small 16-bit memory models for
|
||||
Turbo C [Truta]
|
||||
- Add info about the use of ASMV, ASMINF and ZLIB_WINAPI in
|
||||
zlibCompileFlags [Truta]
|
||||
- Cygwin has vsnprintf [Wilson]
|
||||
- In Windows16, OS_CODE is 0, as in MSDOS [Truta]
|
||||
- In Cygwin, OS_CODE is 3 (Unix), not 11 (Windows32) [Wilson]
|
||||
|
||||
Changes in 1.2.0.4 (10 August 2003)
|
||||
- Minor FAQ updates
|
||||
- Be more strict when checking inflateInit2's windowBits parameter
|
||||
- Change NO_GUNZIP compile option to NO_GZIP to cover deflate as well
|
||||
- Add gzip wrapper option to deflateInit2 using windowBits
|
||||
- Add updated QNX rule in configure and qnx directory [Bonnefoy]
|
||||
- Make inflate distance-too-far checks more rigorous
|
||||
- Clean up FAR usage in inflate
|
||||
- Add casting to sizeof() in gzio.c and minigzip.c
|
||||
|
||||
Changes in 1.2.0.3 (19 July 2003)
|
||||
- Fix silly error in gzungetc() implementation [Vollant]
|
||||
- Update contrib/minizip and contrib/vstudio [Vollant]
|
||||
- Fix printf format in example.c
|
||||
- Correct cdecl support in zconf.in.h [Anisimkov]
|
||||
- Minor FAQ updates
|
||||
|
||||
Changes in 1.2.0.2 (13 July 2003)
|
||||
- Add ZLIB_VERNUM in zlib.h for numerical preprocessor comparisons
|
||||
- Attempt to avoid warnings in crc32.c for pointer-int conversion
|
||||
- Add AIX to configure, remove aix directory [Bakker]
|
||||
- Add some casts to minigzip.c
|
||||
- Improve checking after insecure sprintf() or vsprintf() calls
|
||||
- Remove #elif's from crc32.c
|
||||
- Change leave label to inf_leave in inflate.c and infback.c to avoid
|
||||
library conflicts
|
||||
- Remove inflate gzip decoding by default--only enable gzip decoding by
|
||||
special request for stricter backward compatibility
|
||||
- Add zlibCompileFlags() function to return compilation information
|
||||
- More typecasting in deflate.c to avoid warnings
|
||||
- Remove leading underscore from _Capital #defines [Truta]
|
||||
- Fix configure to link shared library when testing
|
||||
- Add some Windows CE target adjustments [Mai]
|
||||
- Remove #define ZLIB_DLL in zconf.h [Vollant]
|
||||
- Add zlib.3 [Rodgers]
|
||||
- Update RFC URL in deflate.c and algorithm.txt [Mai]
|
||||
- Add zlib_dll_FAQ.txt to contrib [Truta]
|
||||
- Add UL to some constants [Truta]
|
||||
- Update minizip and vstudio [Vollant]
|
||||
- Remove vestigial NEED_DUMMY_RETURN from zconf.in.h
|
||||
- Expand use of NO_DUMMY_DECL to avoid all dummy structures
|
||||
- Added iostream3 to contrib [Schwardt]
|
||||
- Replace rewind() with fseek() for WinCE [Truta]
|
||||
- Improve setting of zlib format compression level flags
|
||||
- Report 0 for huffman and rle strategies and for level == 0 or 1
|
||||
- Report 2 only for level == 6
|
||||
- Only deal with 64K limit when necessary at compile time [Truta]
|
||||
- Allow TOO_FAR check to be turned off at compile time [Truta]
|
||||
- Add gzclearerr() function [Souza]
|
||||
- Add gzungetc() function
|
||||
|
||||
Changes in 1.2.0.1 (17 March 2003)
|
||||
- Add Z_RLE strategy for run-length encoding [Truta]
|
||||
- When Z_RLE requested, restrict matches to distance one
|
||||
- Update zlib.h, minigzip.c, gzopen(), gzdopen() for Z_RLE
|
||||
- Correct FASTEST compilation to allow level == 0
|
||||
- Clean up what gets compiled for FASTEST
|
||||
- Incorporate changes to zconf.in.h [Vollant]
|
||||
- Refine detection of Turbo C need for dummy returns
|
||||
- Refine ZLIB_DLL compilation
|
||||
- Include additional header file on VMS for off_t typedef
|
||||
- Try to use _vsnprintf where it supplants vsprintf [Vollant]
|
||||
- Add some casts in inffast.c
|
||||
- Enchance comments in zlib.h on what happens if gzprintf() tries to
|
||||
write more than 4095 bytes before compression
|
||||
- Remove unused state from inflateBackEnd()
|
||||
- Remove exit(0) from minigzip.c, example.c
|
||||
- Get rid of all those darn tabs
|
||||
- Add "check" target to Makefile.in that does the same thing as "test"
|
||||
- Add "mostlyclean" and "maintainer-clean" targets to Makefile.in
|
||||
- Update contrib/inflate86 [Anderson]
|
||||
- Update contrib/testzlib, contrib/vstudio, contrib/minizip [Vollant]
|
||||
- Add msdos and win32 directories with makefiles [Truta]
|
||||
- More additions and improvements to the FAQ
|
||||
|
||||
Changes in 1.2.0 (9 March 2003)
|
||||
- New and improved inflate code
|
||||
- About 20% faster
|
||||
- Does not allocate 32K window unless and until needed
|
||||
- Automatically detects and decompresses gzip streams
|
||||
- Raw inflate no longer needs an extra dummy byte at end
|
||||
- Added inflateBack functions using a callback interface--even faster
|
||||
than inflate, useful for file utilities (gzip, zip)
|
||||
- Added inflateCopy() function to record state for random access on
|
||||
externally generated deflate streams (e.g. in gzip files)
|
||||
- More readable code (I hope)
|
||||
- New and improved crc32()
|
||||
- About 50% faster, thanks to suggestions from Rodney Brown
|
||||
- Add deflateBound() and compressBound() functions
|
||||
- Fix memory leak in deflateInit2()
|
||||
- Permit setting dictionary for raw deflate (for parallel deflate)
|
||||
- Fix const declaration for gzwrite()
|
||||
- Check for some malloc() failures in gzio.c
|
||||
- Fix bug in gzopen() on single-byte file 0x1f
|
||||
- Fix bug in gzread() on concatenated file with 0x1f at end of buffer
|
||||
and next buffer doesn't start with 0x8b
|
||||
- Fix uncompress() to return Z_DATA_ERROR on truncated input
|
||||
- Free memory at end of example.c
|
||||
- Remove MAX #define in trees.c (conflicted with some libraries)
|
||||
- Fix static const's in deflate.c, gzio.c, and zutil.[ch]
|
||||
- Declare malloc() and free() in gzio.c if STDC not defined
|
||||
- Use malloc() instead of calloc() in zutil.c if int big enough
|
||||
- Define STDC for AIX
|
||||
- Add aix/ with approach for compiling shared library on AIX
|
||||
- Add HP-UX support for shared libraries in configure
|
||||
- Add OpenUNIX support for shared libraries in configure
|
||||
- Use $cc instead of gcc to build shared library
|
||||
- Make prefix directory if needed when installing
|
||||
- Correct Macintosh avoidance of typedef Byte in zconf.h
|
||||
- Correct Turbo C memory allocation when under Linux
|
||||
- Use libz.a instead of -lz in Makefile (assure use of compiled library)
|
||||
- Update configure to check for snprintf or vsnprintf functions and their
|
||||
return value, warn during make if using an insecure function
|
||||
- Fix configure problem with compile-time knowledge of HAVE_UNISTD_H that
|
||||
is lost when library is used--resolution is to build new zconf.h
|
||||
- Documentation improvements (in zlib.h):
|
||||
- Document raw deflate and inflate
|
||||
- Update RFCs URL
|
||||
- Point out that zlib and gzip formats are different
|
||||
- Note that Z_BUF_ERROR is not fatal
|
||||
- Document string limit for gzprintf() and possible buffer overflow
|
||||
- Note requirement on avail_out when flushing
|
||||
- Note permitted values of flush parameter of inflate()
|
||||
- Add some FAQs (and even answers) to the FAQ
|
||||
- Add contrib/inflate86/ for x86 faster inflate
|
||||
- Add contrib/blast/ for PKWare Data Compression Library decompression
|
||||
- Add contrib/puff/ simple inflate for deflate format description
|
||||
|
||||
Changes in 1.1.4 (11 March 2002)
|
||||
- ZFREE was repeated on same allocation on some error conditions.
|
||||
This creates a security problem described in
|
||||
http://www.zlib.org/advisory-2002-03-11.txt
|
||||
- Returned incorrect error (Z_MEM_ERROR) on some invalid data
|
||||
- Avoid accesses before window for invalid distances with inflate window
|
||||
less than 32K.
|
||||
- force windowBits > 8 to avoid a bug in the encoder for a window size
|
||||
of 256 bytes. (A complete fix will be available in 1.1.5).
|
||||
|
||||
Changes in 1.1.3 (9 July 1998)
|
||||
- fix "an inflate input buffer bug that shows up on rare but persistent
|
||||
occasions" (Mark)
|
||||
- fix gzread and gztell for concatenated .gz files (Didier Le Botlan)
|
||||
- fix gzseek(..., SEEK_SET) in write mode
|
||||
- fix crc check after a gzeek (Frank Faubert)
|
||||
- fix miniunzip when the last entry in a zip file is itself a zip file
|
||||
(J Lillge)
|
||||
- add contrib/asm586 and contrib/asm686 (Brian Raiter)
|
||||
See http://www.muppetlabs.com/~breadbox/software/assembly.html
|
||||
- add support for Delphi 3 in contrib/delphi (Bob Dellaca)
|
||||
- add support for C++Builder 3 and Delphi 3 in contrib/delphi2 (Davide Moretti)
|
||||
- do not exit prematurely in untgz if 0 at start of block (Magnus Holmgren)
|
||||
- use macro EXTERN instead of extern to support DLL for BeOS (Sander Stoks)
|
||||
- added a FAQ file
|
||||
|
||||
- Support gzdopen on Mac with Metrowerks (Jason Linhart)
|
||||
- Do not redefine Byte on Mac (Brad Pettit & Jason Linhart)
|
||||
- define SEEK_END too if SEEK_SET is not defined (Albert Chin-A-Young)
|
||||
- avoid some warnings with Borland C (Tom Tanner)
|
||||
- fix a problem in contrib/minizip/zip.c for 16-bit MSDOS (Gilles Vollant)
|
||||
- emulate utime() for WIN32 in contrib/untgz (Gilles Vollant)
|
||||
- allow several arguments to configure (Tim Mooney, Frodo Looijaard)
|
||||
- use libdir and includedir in Makefile.in (Tim Mooney)
|
||||
- support shared libraries on OSF1 V4 (Tim Mooney)
|
||||
- remove so_locations in "make clean" (Tim Mooney)
|
||||
- fix maketree.c compilation error (Glenn, Mark)
|
||||
- Python interface to zlib now in Python 1.5 (Jeremy Hylton)
|
||||
- new Makefile.riscos (Rich Walker)
|
||||
- initialize static descriptors in trees.c for embedded targets (Nick Smith)
|
||||
- use "foo-gz" in example.c for RISCOS and VMS (Nick Smith)
|
||||
- add the OS/2 files in Makefile.in too (Andrew Zabolotny)
|
||||
- fix fdopen and halloc macros for Microsoft C 6.0 (Tom Lane)
|
||||
- fix maketree.c to allow clean compilation of inffixed.h (Mark)
|
||||
- fix parameter check in deflateCopy (Gunther Nikl)
|
||||
- cleanup trees.c, use compressed_len only in debug mode (Christian Spieler)
|
||||
- Many portability patches by Christian Spieler:
|
||||
. zutil.c, zutil.h: added "const" for zmem*
|
||||
. Make_vms.com: fixed some typos
|
||||
. Make_vms.com: msdos/Makefile.*: removed zutil.h from some dependency lists
|
||||
. msdos/Makefile.msc: remove "default rtl link library" info from obj files
|
||||
. msdos/Makefile.*: use model-dependent name for the built zlib library
|
||||
. msdos/Makefile.emx, nt/Makefile.emx, nt/Makefile.gcc:
|
||||
new makefiles, for emx (DOS/OS2), emx&rsxnt and mingw32 (Windows 9x / NT)
|
||||
- use define instead of typedef for Bytef also for MSC small/medium (Tom Lane)
|
||||
- replace __far with _far for better portability (Christian Spieler, Tom Lane)
|
||||
- fix test for errno.h in configure (Tim Newsham)
|
||||
|
||||
Changes in 1.1.2 (19 March 98)
|
||||
- added contrib/minzip, mini zip and unzip based on zlib (Gilles Vollant)
|
||||
See http://www.winimage.com/zLibDll/unzip.html
|
||||
- preinitialize the inflate tables for fixed codes, to make the code
|
||||
completely thread safe (Mark)
|
||||
- some simplifications and slight speed-up to the inflate code (Mark)
|
||||
- fix gzeof on non-compressed files (Allan Schrum)
|
||||
- add -std1 option in configure for OSF1 to fix gzprintf (Martin Mokrejs)
|
||||
- use default value of 4K for Z_BUFSIZE for 16-bit MSDOS (Tim Wegner + Glenn)
|
||||
- added os2/Makefile.def and os2/zlib.def (Andrew Zabolotny)
|
||||
- add shared lib support for UNIX_SV4.2MP (MATSUURA Takanori)
|
||||
- do not wrap extern "C" around system includes (Tom Lane)
|
||||
- mention zlib binding for TCL in README (Andreas Kupries)
|
||||
- added amiga/Makefile.pup for Amiga powerUP SAS/C PPC (Andreas Kleinert)
|
||||
- allow "make install prefix=..." even after configure (Glenn Randers-Pehrson)
|
||||
- allow "configure --prefix $HOME" (Tim Mooney)
|
||||
- remove warnings in example.c and gzio.c (Glenn Randers-Pehrson)
|
||||
- move Makefile.sas to amiga/Makefile.sas
|
||||
|
||||
Changes in 1.1.1 (27 Feb 98)
|
||||
- fix macros _tr_tally_* in deflate.h for debug mode (Glenn Randers-Pehrson)
|
||||
- remove block truncation heuristic which had very marginal effect for zlib
|
||||
(smaller lit_bufsize than in gzip 1.2.4) and degraded a little the
|
||||
compression ratio on some files. This also allows inlining _tr_tally for
|
||||
matches in deflate_slow.
|
||||
- added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier)
|
||||
|
||||
Changes in 1.1.0 (24 Feb 98)
|
||||
- do not return STREAM_END prematurely in inflate (John Bowler)
|
||||
- revert to the zlib 1.0.8 inflate to avoid the gcc 2.8.0 bug (Jeremy Buhler)
|
||||
- compile with -DFASTEST to get compression code optimized for speed only
|
||||
- in minigzip, try mmap'ing the input file first (Miguel Albrecht)
|
||||
- increase size of I/O buffers in minigzip.c and gzio.c (not a big gain
|
||||
on Sun but significant on HP)
|
||||
|
||||
- add a pointer to experimental unzip library in README (Gilles Vollant)
|
||||
- initialize variable gcc in configure (Chris Herborth)
|
||||
|
||||
Changes in 1.0.9 (17 Feb 1998)
|
||||
- added gzputs and gzgets functions
|
||||
- do not clear eof flag in gzseek (Mark Diekhans)
|
||||
- fix gzseek for files in transparent mode (Mark Diekhans)
|
||||
- do not assume that vsprintf returns the number of bytes written (Jens Krinke)
|
||||
- replace EXPORT with ZEXPORT to avoid conflict with other programs
|
||||
- added compress2 in zconf.h, zlib.def, zlib.dnt
|
||||
- new asm code from Gilles Vollant in contrib/asm386
|
||||
- simplify the inflate code (Mark):
|
||||
. Replace ZALLOC's in huft_build() with single ZALLOC in inflate_blocks_new()
|
||||
. ZALLOC the length list in inflate_trees_fixed() instead of using stack
|
||||
. ZALLOC the value area for huft_build() instead of using stack
|
||||
. Simplify Z_FINISH check in inflate()
|
||||
|
||||
- Avoid gcc 2.8.0 comparison bug a little differently than zlib 1.0.8
|
||||
- in inftrees.c, avoid cc -O bug on HP (Farshid Elahi)
|
||||
- in zconf.h move the ZLIB_DLL stuff earlier to avoid problems with
|
||||
the declaration of FAR (Gilles VOllant)
|
||||
- install libz.so* with mode 755 (executable) instead of 644 (Marc Lehmann)
|
||||
- read_buf buf parameter of type Bytef* instead of charf*
|
||||
- zmemcpy parameters are of type Bytef*, not charf* (Joseph Strout)
|
||||
- do not redeclare unlink in minigzip.c for WIN32 (John Bowler)
|
||||
- fix check for presence of directories in "make install" (Ian Willis)
|
||||
|
||||
Changes in 1.0.8 (27 Jan 1998)
|
||||
- fixed offsets in contrib/asm386/gvmat32.asm (Gilles Vollant)
|
||||
- fix gzgetc and gzputc for big endian systems (Markus Oberhumer)
|
||||
- added compress2() to allow setting the compression level
|
||||
- include sys/types.h to get off_t on some systems (Marc Lehmann & QingLong)
|
||||
- use constant arrays for the static trees in trees.c instead of computing
|
||||
them at run time (thanks to Ken Raeburn for this suggestion). To create
|
||||
trees.h, compile with GEN_TREES_H and run "make test".
|
||||
- check return code of example in "make test" and display result
|
||||
- pass minigzip command line options to file_compress
|
||||
- simplifying code of inflateSync to avoid gcc 2.8 bug
|
||||
|
||||
- support CC="gcc -Wall" in configure -s (QingLong)
|
||||
- avoid a flush caused by ftell in gzopen for write mode (Ken Raeburn)
|
||||
- fix test for shared library support to avoid compiler warnings
|
||||
- zlib.lib -> zlib.dll in msdos/zlib.rc (Gilles Vollant)
|
||||
- check for TARGET_OS_MAC in addition to MACOS (Brad Pettit)
|
||||
- do not use fdopen for Metrowerks on Mac (Brad Pettit))
|
||||
- add checks for gzputc and gzputc in example.c
|
||||
- avoid warnings in gzio.c and deflate.c (Andreas Kleinert)
|
||||
- use const for the CRC table (Ken Raeburn)
|
||||
- fixed "make uninstall" for shared libraries
|
||||
- use Tracev instead of Trace in infblock.c
|
||||
- in example.c use correct compressed length for test_sync
|
||||
- suppress +vnocompatwarnings in configure for HPUX (not always supported)
|
||||
|
||||
Changes in 1.0.7 (20 Jan 1998)
|
||||
- fix gzseek which was broken in write mode
|
||||
- return error for gzseek to negative absolute position
|
||||
- fix configure for Linux (Chun-Chung Chen)
|
||||
- increase stack space for MSC (Tim Wegner)
|
||||
- get_crc_table and inflateSyncPoint are EXPORTed (Gilles Vollant)
|
||||
- define EXPORTVA for gzprintf (Gilles Vollant)
|
||||
- added man page zlib.3 (Rick Rodgers)
|
||||
- for contrib/untgz, fix makedir() and improve Makefile
|
||||
|
||||
- check gzseek in write mode in example.c
|
||||
- allocate extra buffer for seeks only if gzseek is actually called
|
||||
- avoid signed/unsigned comparisons (Tim Wegner, Gilles Vollant)
|
||||
- add inflateSyncPoint in zconf.h
|
||||
- fix list of exported functions in nt/zlib.dnt and mdsos/zlib.def
|
||||
|
||||
Changes in 1.0.6 (19 Jan 1998)
|
||||
- add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and
|
||||
gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code)
|
||||
- Fix a deflate bug occuring only with compression level 0 (thanks to
|
||||
Andy Buckler for finding this one).
|
||||
- In minigzip, pass transparently also the first byte for .Z files.
|
||||
- return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress()
|
||||
- check Z_FINISH in inflate (thanks to Marc Schluper)
|
||||
- Implement deflateCopy (thanks to Adam Costello)
|
||||
- make static libraries by default in configure, add --shared option.
|
||||
- move MSDOS or Windows specific files to directory msdos
|
||||
- suppress the notion of partial flush to simplify the interface
|
||||
(but the symbol Z_PARTIAL_FLUSH is kept for compatibility with 1.0.4)
|
||||
- suppress history buffer provided by application to simplify the interface
|
||||
(this feature was not implemented anyway in 1.0.4)
|
||||
- next_in and avail_in must be initialized before calling inflateInit or
|
||||
inflateInit2
|
||||
- add EXPORT in all exported functions (for Windows DLL)
|
||||
- added Makefile.nt (thanks to Stephen Williams)
|
||||
- added the unsupported "contrib" directory:
|
||||
contrib/asm386/ by Gilles Vollant <info@winimage.com>
|
||||
386 asm code replacing longest_match().
|
||||
contrib/iostream/ by Kevin Ruland <kevin@rodin.wustl.edu>
|
||||
A C++ I/O streams interface to the zlib gz* functions
|
||||
contrib/iostream2/ by Tyge Løvset <Tyge.Lovset@cmr.no>
|
||||
Another C++ I/O streams interface
|
||||
contrib/untgz/ by "Pedro A. Aranda Guti\irrez" <paag@tid.es>
|
||||
A very simple tar.gz file extractor using zlib
|
||||
contrib/visual-basic.txt by Carlos Rios <c_rios@sonda.cl>
|
||||
How to use compress(), uncompress() and the gz* functions from VB.
|
||||
- pass params -f (filtered data), -h (huffman only), -1 to -9 (compression
|
||||
level) in minigzip (thanks to Tom Lane)
|
||||
|
||||
- use const for rommable constants in deflate
|
||||
- added test for gzseek and gztell in example.c
|
||||
- add undocumented function inflateSyncPoint() (hack for Paul Mackerras)
|
||||
- add undocumented function zError to convert error code to string
|
||||
(for Tim Smithers)
|
||||
- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code.
|
||||
- Use default memcpy for Symantec MSDOS compiler.
|
||||
- Add EXPORT keyword for check_func (needed for Windows DLL)
|
||||
- add current directory to LD_LIBRARY_PATH for "make test"
|
||||
- create also a link for libz.so.1
|
||||
- added support for FUJITSU UXP/DS (thanks to Toshiaki Nomura)
|
||||
- use $(SHAREDLIB) instead of libz.so in Makefile.in (for HPUX)
|
||||
- added -soname for Linux in configure (Chun-Chung Chen,
|
||||
- assign numbers to the exported functions in zlib.def (for Windows DLL)
|
||||
- add advice in zlib.h for best usage of deflateSetDictionary
|
||||
- work around compiler bug on Atari (cast Z_NULL in call of s->checkfn)
|
||||
- allow compilation with ANSI keywords only enabled for TurboC in large model
|
||||
- avoid "versionString"[0] (Borland bug)
|
||||
- add NEED_DUMMY_RETURN for Borland
|
||||
- use variable z_verbose for tracing in debug mode (L. Peter Deutsch).
|
||||
- allow compilation with CC
|
||||
- defined STDC for OS/2 (David Charlap)
|
||||
- limit external names to 8 chars for MVS (Thomas Lund)
|
||||
- in minigzip.c, use static buffers only for 16-bit systems
|
||||
- fix suffix check for "minigzip -d foo.gz"
|
||||
- do not return an error for the 2nd of two consecutive gzflush() (Felix Lee)
|
||||
- use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau)
|
||||
- added makelcc.bat for lcc-win32 (Tom St Denis)
|
||||
- in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe)
|
||||
- Avoid expanded $Id$. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion.
|
||||
- check for unistd.h in configure (for off_t)
|
||||
- remove useless check parameter in inflate_blocks_free
|
||||
- avoid useless assignment of s->check to itself in inflate_blocks_new
|
||||
- do not flush twice in gzclose (thanks to Ken Raeburn)
|
||||
- rename FOPEN as F_OPEN to avoid clash with /usr/include/sys/file.h
|
||||
- use NO_ERRNO_H instead of enumeration of operating systems with errno.h
|
||||
- work around buggy fclose on pipes for HP/UX
|
||||
- support zlib DLL with BORLAND C++ 5.0 (thanks to Glenn Randers-Pehrson)
|
||||
- fix configure if CC is already equal to gcc
|
||||
|
||||
Changes in 1.0.5 (3 Jan 98)
|
||||
- Fix inflate to terminate gracefully when fed corrupted or invalid data
|
||||
- Use const for rommable constants in inflate
|
||||
- Eliminate memory leaks on error conditions in inflate
|
||||
- Removed some vestigial code in inflate
|
||||
- Update web address in README
|
||||
|
||||
Changes in 1.0.4 (24 Jul 96)
|
||||
- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF
|
||||
bit, so the decompressor could decompress all the correct data but went
|
||||
on to attempt decompressing extra garbage data. This affected minigzip too.
|
||||
- zlibVersion and gzerror return const char* (needed for DLL)
|
||||
- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno)
|
||||
- use z_error only for DEBUG (avoid problem with DLLs)
|
||||
|
||||
Changes in 1.0.3 (2 Jul 96)
|
||||
- use z_streamp instead of z_stream *, which is now a far pointer in MSDOS
|
||||
small and medium models; this makes the library incompatible with previous
|
||||
versions for these models. (No effect in large model or on other systems.)
|
||||
- return OK instead of BUF_ERROR if previous deflate call returned with
|
||||
avail_out as zero but there is nothing to do
|
||||
- added memcmp for non STDC compilers
|
||||
- define NO_DUMMY_DECL for more Mac compilers (.h files merged incorrectly)
|
||||
- define __32BIT__ if __386__ or i386 is defined (pb. with Watcom and SCO)
|
||||
- better check for 16-bit mode MSC (avoids problem with Symantec)
|
||||
|
||||
Changes in 1.0.2 (23 May 96)
|
||||
- added Windows DLL support
|
||||
- added a function zlibVersion (for the DLL support)
|
||||
- fixed declarations using Bytef in infutil.c (pb with MSDOS medium model)
|
||||
- Bytef is define's instead of typedef'd only for Borland C
|
||||
- avoid reading uninitialized memory in example.c
|
||||
- mention in README that the zlib format is now RFC1950
|
||||
- updated Makefile.dj2
|
||||
- added algorithm.doc
|
||||
|
||||
Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion]
|
||||
- fix array overlay in deflate.c which sometimes caused bad compressed data
|
||||
- fix inflate bug with empty stored block
|
||||
- fix MSDOS medium model which was broken in 0.99
|
||||
- fix deflateParams() which could generated bad compressed data.
|
||||
- Bytef is define'd instead of typedef'ed (work around Borland bug)
|
||||
- added an INDEX file
|
||||
- new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32),
|
||||
Watcom (Makefile.wat), Amiga SAS/C (Makefile.sas)
|
||||
- speed up adler32 for modern machines without auto-increment
|
||||
- added -ansi for IRIX in configure
|
||||
- static_init_done in trees.c is an int
|
||||
- define unlink as delete for VMS
|
||||
- fix configure for QNX
|
||||
- add configure branch for SCO and HPUX
|
||||
- avoid many warnings (unused variables, dead assignments, etc...)
|
||||
- no fdopen for BeOS
|
||||
- fix the Watcom fix for 32 bit mode (define FAR as empty)
|
||||
- removed redefinition of Byte for MKWERKS
|
||||
- work around an MWKERKS bug (incorrect merge of all .h files)
|
||||
|
||||
Changes in 0.99 (27 Jan 96)
|
||||
- allow preset dictionary shared between compressor and decompressor
|
||||
- allow compression level 0 (no compression)
|
||||
- add deflateParams in zlib.h: allow dynamic change of compression level
|
||||
and compression strategy.
|
||||
- test large buffers and deflateParams in example.c
|
||||
- add optional "configure" to build zlib as a shared library
|
||||
- suppress Makefile.qnx, use configure instead
|
||||
- fixed deflate for 64-bit systems (detected on Cray)
|
||||
- fixed inflate_blocks for 64-bit systems (detected on Alpha)
|
||||
- declare Z_DEFLATED in zlib.h (possible parameter for deflateInit2)
|
||||
- always return Z_BUF_ERROR when deflate() has nothing to do
|
||||
- deflateInit and inflateInit are now macros to allow version checking
|
||||
- prefix all global functions and types with z_ with -DZ_PREFIX
|
||||
- make falloc completely reentrant (inftrees.c)
|
||||
- fixed very unlikely race condition in ct_static_init
|
||||
- free in reverse order of allocation to help memory manager
|
||||
- use zlib-1.0/* instead of zlib/* inside the tar.gz
|
||||
- make zlib warning-free with "gcc -O3 -Wall -Wwrite-strings -Wpointer-arith
|
||||
-Wconversion -Wstrict-prototypes -Wmissing-prototypes"
|
||||
- allow gzread on concatenated .gz files
|
||||
- deflateEnd now returns Z_DATA_ERROR if it was premature
|
||||
- deflate is finally (?) fully deterministic (no matches beyond end of input)
|
||||
- Document Z_SYNC_FLUSH
|
||||
- add uninstall in Makefile
|
||||
- Check for __cpluplus in zlib.h
|
||||
- Better test in ct_align for partial flush
|
||||
- avoid harmless warnings for Borland C++
|
||||
- initialize hash_head in deflate.c
|
||||
- avoid warning on fdopen (gzio.c) for HP cc -Aa
|
||||
- include stdlib.h for STDC compilers
|
||||
- include errno.h for Cray
|
||||
- ignore error if ranlib doesn't exist
|
||||
- call ranlib twice for NeXTSTEP
|
||||
- use exec_prefix instead of prefix for libz.a
|
||||
- renamed ct_* as _tr_* to avoid conflict with applications
|
||||
- clear z->msg in inflateInit2 before any error return
|
||||
- initialize opaque in example.c, gzio.c, deflate.c and inflate.c
|
||||
- fixed typo in zconf.h (_GNUC__ => __GNUC__)
|
||||
- check for WIN32 in zconf.h and zutil.c (avoid farmalloc in 32-bit mode)
|
||||
- fix typo in Make_vms.com (f$trnlnm -> f$getsyi)
|
||||
- in fcalloc, normalize pointer if size > 65520 bytes
|
||||
- don't use special fcalloc for 32 bit Borland C++
|
||||
- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc...
|
||||
- use Z_BINARY instead of BINARY
|
||||
- document that gzclose after gzdopen will close the file
|
||||
- allow "a" as mode in gzopen.
|
||||
- fix error checking in gzread
|
||||
- allow skipping .gz extra-field on pipes
|
||||
- added reference to Perl interface in README
|
||||
- put the crc table in FAR data (I dislike more and more the medium model :)
|
||||
- added get_crc_table
|
||||
- added a dimension to all arrays (Borland C can't count).
|
||||
- workaround Borland C bug in declaration of inflate_codes_new & inflate_fast
|
||||
- guard against multiple inclusion of *.h (for precompiled header on Mac)
|
||||
- Watcom C pretends to be Microsoft C small model even in 32 bit mode.
|
||||
- don't use unsized arrays to avoid silly warnings by Visual C++:
|
||||
warning C4746: 'inflate_mask' : unsized array treated as '__far'
|
||||
(what's wrong with far data in far model?).
|
||||
- define enum out of inflate_blocks_state to allow compilation with C++
|
||||
|
||||
Changes in 0.95 (16 Aug 95)
|
||||
- fix MSDOS small and medium model (now easier to adapt to any compiler)
|
||||
- inlined send_bits
|
||||
- fix the final (:-) bug for deflate with flush (output was correct but
|
||||
not completely flushed in rare occasions).
|
||||
- default window size is same for compression and decompression
|
||||
(it's now sufficient to set MAX_WBITS in zconf.h).
|
||||
- voidp -> voidpf and voidnp -> voidp (for consistency with other
|
||||
typedefs and because voidnp was not near in large model).
|
||||
|
||||
Changes in 0.94 (13 Aug 95)
|
||||
- support MSDOS medium model
|
||||
- fix deflate with flush (could sometimes generate bad output)
|
||||
- fix deflateReset (zlib header was incorrectly suppressed)
|
||||
- added support for VMS
|
||||
- allow a compression level in gzopen()
|
||||
- gzflush now calls fflush
|
||||
- For deflate with flush, flush even if no more input is provided.
|
||||
- rename libgz.a as libz.a
|
||||
- avoid complex expression in infcodes.c triggering Turbo C bug
|
||||
- work around a problem with gcc on Alpha (in INSERT_STRING)
|
||||
- don't use inline functions (problem with some gcc versions)
|
||||
- allow renaming of Byte, uInt, etc... with #define.
|
||||
- avoid warning about (unused) pointer before start of array in deflate.c
|
||||
- avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c
|
||||
- avoid reserved word 'new' in trees.c
|
||||
|
||||
Changes in 0.93 (25 June 95)
|
||||
- temporarily disable inline functions
|
||||
- make deflate deterministic
|
||||
- give enough lookahead for PARTIAL_FLUSH
|
||||
- Set binary mode for stdin/stdout in minigzip.c for OS/2
|
||||
- don't even use signed char in inflate (not portable enough)
|
||||
- fix inflate memory leak for segmented architectures
|
||||
|
||||
Changes in 0.92 (3 May 95)
|
||||
- don't assume that char is signed (problem on SGI)
|
||||
- Clear bit buffer when starting a stored block
|
||||
- no memcpy on Pyramid
|
||||
- suppressed inftest.c
|
||||
- optimized fill_window, put longest_match inline for gcc
|
||||
- optimized inflate on stored blocks.
|
||||
- untabify all sources to simplify patches
|
||||
|
||||
Changes in 0.91 (2 May 95)
|
||||
- Default MEM_LEVEL is 8 (not 9 for Unix) as documented in zlib.h
|
||||
- Document the memory requirements in zconf.h
|
||||
- added "make install"
|
||||
- fix sync search logic in inflateSync
|
||||
- deflate(Z_FULL_FLUSH) now works even if output buffer too short
|
||||
- after inflateSync, don't scare people with just "lo world"
|
||||
- added support for DJGPP
|
||||
|
||||
Changes in 0.9 (1 May 95)
|
||||
- don't assume that zalloc clears the allocated memory (the TurboC bug
|
||||
was Mark's bug after all :)
|
||||
- let again gzread copy uncompressed data unchanged (was working in 0.71)
|
||||
- deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented
|
||||
- added a test of inflateSync in example.c
|
||||
- moved MAX_WBITS to zconf.h because users might want to change that.
|
||||
- document explicitly that zalloc(64K) on MSDOS must return a normalized
|
||||
pointer (zero offset)
|
||||
- added Makefiles for Microsoft C, Turbo C, Borland C++
|
||||
- faster crc32()
|
||||
|
||||
Changes in 0.8 (29 April 95)
|
||||
- added fast inflate (inffast.c)
|
||||
- deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this
|
||||
is incompatible with previous versions of zlib which returned Z_OK.
|
||||
- work around a TurboC compiler bug (bad code for b << 0, see infutil.h)
|
||||
(actually that was not a compiler bug, see 0.81 above)
|
||||
- gzread no longer reads one extra byte in certain cases
|
||||
- In gzio destroy(), don't reference a freed structure
|
||||
- avoid many warnings for MSDOS
|
||||
- avoid the ERROR symbol which is used by MS Windows
|
||||
|
||||
Changes in 0.71 (14 April 95)
|
||||
- Fixed more MSDOS compilation problems :( There is still a bug with
|
||||
TurboC large model.
|
||||
|
||||
Changes in 0.7 (14 April 95)
|
||||
- Added full inflate support.
|
||||
- Simplified the crc32() interface. The pre- and post-conditioning
|
||||
(one's complement) is now done inside crc32(). WARNING: this is
|
||||
incompatible with previous versions; see zlib.h for the new usage.
|
||||
|
||||
Changes in 0.61 (12 April 95)
|
||||
- workaround for a bug in TurboC. example and minigzip now work on MSDOS.
|
||||
|
||||
Changes in 0.6 (11 April 95)
|
||||
- added minigzip.c
|
||||
- added gzdopen to reopen a file descriptor as gzFile
|
||||
- added transparent reading of non-gziped files in gzread.
|
||||
- fixed bug in gzread (don't read crc as data)
|
||||
- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose).
|
||||
- don't allocate big arrays in the stack (for MSDOS)
|
||||
- fix some MSDOS compilation problems
|
||||
|
||||
Changes in 0.5:
|
||||
- do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but
|
||||
not yet Z_FULL_FLUSH.
|
||||
- support decompression but only in a single step (forced Z_FINISH)
|
||||
- added opaque object for zalloc and zfree.
|
||||
- added deflateReset and inflateReset
|
||||
- added a variable zlib_version for consistency checking.
|
||||
- renamed the 'filter' parameter of deflateInit2 as 'strategy'.
|
||||
Added Z_FILTERED and Z_HUFFMAN_ONLY constants.
|
||||
|
||||
Changes in 0.4:
|
||||
- avoid "zip" everywhere, use zlib instead of ziplib.
|
||||
- suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush
|
||||
if compression method == 8.
|
||||
- added adler32 and crc32
|
||||
- renamed deflateOptions as deflateInit2, call one or the other but not both
|
||||
- added the method parameter for deflateInit2.
|
||||
- added inflateInit2
|
||||
- simplied considerably deflateInit and inflateInit by not supporting
|
||||
user-provided history buffer. This is supported only in deflateInit2
|
||||
and inflateInit2.
|
||||
|
||||
Changes in 0.3:
|
||||
- prefix all macro names with Z_
|
||||
- use Z_FINISH instead of deflateEnd to finish compression.
|
||||
- added Z_HUFFMAN_ONLY
|
||||
- added gzerror()
|
315
zlib/FAQ
Normal file
315
zlib/FAQ
Normal file
|
@ -0,0 +1,315 @@
|
|||
|
||||
Frequently Asked Questions about zlib
|
||||
|
||||
|
||||
If your question is not there, please check the zlib home page
|
||||
http://www.zlib.org which may have more recent information.
|
||||
The lastest zlib FAQ is at http://www.gzip.org/zlib/zlib_faq.html
|
||||
|
||||
|
||||
1. Is zlib Y2K-compliant?
|
||||
|
||||
Yes. zlib doesn't handle dates.
|
||||
|
||||
2. Where can I get a Windows DLL version?
|
||||
|
||||
The zlib sources can be compiled without change to produce a DLL.
|
||||
See the file win32/DLL_FAQ.txt in the zlib distribution.
|
||||
Pointers to the precompiled DLL are found in the zlib web site at
|
||||
http://www.zlib.org.
|
||||
|
||||
3. Where can I get a Visual Basic interface to zlib?
|
||||
|
||||
See
|
||||
* http://www.winimage.com/zLibDll/
|
||||
* http://www.dogma.net/markn/articles/zlibtool/zlibtool.htm
|
||||
* contrib/visual-basic.txt in the zlib distribution
|
||||
|
||||
4. compress() returns Z_BUF_ERROR
|
||||
|
||||
Make sure that before the call of compress, the length of the compressed
|
||||
buffer is equal to the total size of the compressed buffer and not
|
||||
zero. For Visual Basic, check that this parameter is passed by reference
|
||||
("as any"), not by value ("as long").
|
||||
|
||||
5. deflate() or inflate() returns Z_BUF_ERROR
|
||||
|
||||
Before making the call, make sure that avail_in and avail_out are not
|
||||
zero. When setting the parameter flush equal to Z_FINISH, also make sure
|
||||
that avail_out is big enough to allow processing all pending input.
|
||||
Note that a Z_BUF_ERROR is not fatal--another call to deflate() or
|
||||
inflate() can be made with more input or output space. A Z_BUF_ERROR
|
||||
may in fact be unavoidable depending on how the functions are used, since
|
||||
it is not possible to tell whether or not there is more output pending
|
||||
when strm.avail_out returns with zero.
|
||||
|
||||
6. Where's the zlib documentation (man pages, etc.)?
|
||||
|
||||
It's in zlib.h for the moment, and Francis S. Lin has converted it to a
|
||||
web page zlib.html. Volunteers to transform this to Unix-style man pages,
|
||||
please contact Jean-loup Gailly (jloup@gzip.org). Examples of zlib usage
|
||||
are in the files example.c and minigzip.c.
|
||||
|
||||
7. Why don't you use GNU autoconf or libtool or ...?
|
||||
|
||||
Because we would like to keep zlib as a very small and simple
|
||||
package. zlib is rather portable and doesn't need much configuration.
|
||||
|
||||
8. I found a bug in zlib.
|
||||
|
||||
Most of the time, such problems are due to an incorrect usage of
|
||||
zlib. Please try to reproduce the problem with a small program and send
|
||||
the corresponding source to us at zlib@gzip.org . Do not send
|
||||
multi-megabyte data files without prior agreement.
|
||||
|
||||
9. Why do I get "undefined reference to gzputc"?
|
||||
|
||||
If "make test" produces something like
|
||||
|
||||
example.o(.text+0x154): undefined reference to `gzputc'
|
||||
|
||||
check that you don't have old files libz.* in /usr/lib, /usr/local/lib or
|
||||
/usr/X11R6/lib. Remove any old versions, then do "make install".
|
||||
|
||||
10. I need a Delphi interface to zlib.
|
||||
|
||||
See the contrib/delphi directory in the zlib distribution.
|
||||
|
||||
11. Can zlib handle .zip archives?
|
||||
|
||||
See the directory contrib/minizip in the zlib distribution.
|
||||
|
||||
12. Can zlib handle .Z files?
|
||||
|
||||
No, sorry. You have to spawn an uncompress or gunzip subprocess, or adapt
|
||||
the code of uncompress on your own.
|
||||
|
||||
13. How can I make a Unix shared library?
|
||||
|
||||
make clean
|
||||
./configure -s
|
||||
make
|
||||
|
||||
14. How do I install a shared zlib library on Unix?
|
||||
|
||||
make install
|
||||
|
||||
However, many flavors of Unix come with a shared zlib already installed.
|
||||
Before going to the trouble of compiling a shared version of zlib and
|
||||
trying to install it, you may want to check if it's already there! If you
|
||||
can #include <zlib.h>, it's there. The -lz option will probably link to it.
|
||||
|
||||
15. I have a question about OttoPDF
|
||||
|
||||
We are not the authors of OttoPDF. The real author is on the OttoPDF web
|
||||
site Joel Hainley jhainley@myndkryme.com.
|
||||
|
||||
16. Why does gzip give an error on a file I make with compress/deflate?
|
||||
|
||||
The compress and deflate functions produce data in the zlib format, which
|
||||
is different and incompatible with the gzip format. The gz* functions in
|
||||
zlib on the other hand use the gzip format. Both the zlib and gzip
|
||||
formats use the same compressed data format internally, but have different
|
||||
headers and trailers around the compressed data.
|
||||
|
||||
17. Ok, so why are there two different formats?
|
||||
|
||||
The gzip format was designed to retain the directory information about
|
||||
a single file, such as the name and last modification date. The zlib
|
||||
format on the other hand was designed for in-memory and communication
|
||||
channel applications, and has a much more compact header and trailer and
|
||||
uses a faster integrity check than gzip.
|
||||
|
||||
18. Well that's nice, but how do I make a gzip file in memory?
|
||||
|
||||
You can request that deflate write the gzip format instead of the zlib
|
||||
format using deflateInit2(). You can also request that inflate decode
|
||||
the gzip format using inflateInit2(). Read zlib.h for more details.
|
||||
|
||||
Note that you cannot specify special gzip header contents (e.g. a file
|
||||
name or modification date), nor will inflate tell you what was in the
|
||||
gzip header. If you need to customize the header or see what's in it,
|
||||
you can use the raw deflate and inflate operations and the crc32()
|
||||
function and roll your own gzip encoding and decoding. Read the gzip
|
||||
RFC 1952 for details of the header and trailer format.
|
||||
|
||||
19. Is zlib thread-safe?
|
||||
|
||||
Yes. However any library routines that zlib uses and any application-
|
||||
provided memory allocation routines must also be thread-safe. zlib's gz*
|
||||
functions use stdio library routines, and most of zlib's functions use the
|
||||
library memory allocation routines by default. zlib's Init functions allow
|
||||
for the application to provide custom memory allocation routines.
|
||||
|
||||
Of course, you should only operate on any given zlib or gzip stream from a
|
||||
single thread at a time.
|
||||
|
||||
20. Can I use zlib in my commercial application?
|
||||
|
||||
Yes. Please read the license in zlib.h.
|
||||
|
||||
21. Is zlib under the GNU license?
|
||||
|
||||
No. Please read the license in zlib.h.
|
||||
|
||||
22. The license says that altered source versions must be "plainly marked". So
|
||||
what exactly do I need to do to meet that requirement?
|
||||
|
||||
You need to change the ZLIB_VERSION and ZLIB_VERNUM #defines in zlib.h. In
|
||||
particular, the final version number needs to be changed to "f", and an
|
||||
identification string should be appended to ZLIB_VERSION. Version numbers
|
||||
x.x.x.f are reserved for modifications to zlib by others than the zlib
|
||||
maintainers. For example, if the version of the base zlib you are altering
|
||||
is "1.2.3.4", then in zlib.h you should change ZLIB_VERNUM to 0x123f, and
|
||||
ZLIB_VERSION to something like "1.2.3.f-zachary-mods-v3". You can also
|
||||
update the version strings in deflate.c and inftrees.c.
|
||||
|
||||
For altered source distributions, you should also note the origin and
|
||||
nature of the changes in zlib.h, as well as in ChangeLog and README, along
|
||||
with the dates of the alterations. The origin should include at least your
|
||||
name (or your company's name), and an email address to contact for help or
|
||||
issues with the library.
|
||||
|
||||
Note that distributing a compiled zlib library along with zlib.h and
|
||||
zconf.h is also a source distribution, and so you should change
|
||||
ZLIB_VERSION and ZLIB_VERNUM and note the origin and nature of the changes
|
||||
in zlib.h as you would for a full source distribution.
|
||||
|
||||
23. Will zlib work on a big-endian or little-endian architecture, and can I
|
||||
exchange compressed data between them?
|
||||
|
||||
Yes and yes.
|
||||
|
||||
24. Will zlib work on a 64-bit machine?
|
||||
|
||||
It should. It has been tested on 64-bit machines, and has no dependence
|
||||
on any data types being limited to 32-bits in length. If you have any
|
||||
difficulties, please provide a complete problem report to zlib@gzip.org
|
||||
|
||||
25. Will zlib decompress data from the PKWare Data Compression Library?
|
||||
|
||||
No. The PKWare DCL uses a completely different compressed data format
|
||||
than does PKZIP and zlib. However, you can look in zlib's contrib/blast
|
||||
directory for a possible solution to your problem.
|
||||
|
||||
26. Can I access data randomly in a compressed stream?
|
||||
|
||||
No, not without some preparation. If when compressing you periodically
|
||||
use Z_FULL_FLUSH, carefully write all the pending data at those points,
|
||||
and keep an index of those locations, then you can start decompression
|
||||
at those points. You have to be careful to not use Z_FULL_FLUSH too
|
||||
often, since it can significantly degrade compression.
|
||||
|
||||
27. Does zlib work on MVS, OS/390, CICS, etc.?
|
||||
|
||||
We don't know for sure. We have heard occasional reports of success on
|
||||
these systems. If you do use it on one of these, please provide us with
|
||||
a report, instructions, and patches that we can reference when we get
|
||||
these questions. Thanks.
|
||||
|
||||
28. Is there some simpler, easier to read version of inflate I can look at
|
||||
to understand the deflate format?
|
||||
|
||||
First off, you should read RFC 1951. Second, yes. Look in zlib's
|
||||
contrib/puff directory.
|
||||
|
||||
29. Does zlib infringe on any patents?
|
||||
|
||||
As far as we know, no. In fact, that was originally the whole point behind
|
||||
zlib. Look here for some more information:
|
||||
|
||||
http://www.gzip.org/#faq11
|
||||
|
||||
30. Can zlib work with greater than 4 GB of data?
|
||||
|
||||
Yes. inflate() and deflate() will process any amount of data correctly.
|
||||
Each call of inflate() or deflate() is limited to input and output chunks
|
||||
of the maximum value that can be stored in the compiler's "unsigned int"
|
||||
type, but there is no limit to the number of chunks. Note however that the
|
||||
strm.total_in and strm_total_out counters may be limited to 4 GB. These
|
||||
counters are provided as a convenience and are not used internally by
|
||||
inflate() or deflate(). The application can easily set up its own counters
|
||||
updated after each call of inflate() or deflate() to count beyond 4 GB.
|
||||
compress() and uncompress() may be limited to 4 GB, since they operate in a
|
||||
single call. gzseek() and gztell() may be limited to 4 GB depending on how
|
||||
zlib is compiled. See the zlibCompileFlags() function in zlib.h.
|
||||
|
||||
The word "may" appears several times above since there is a 4 GB limit
|
||||
only if the compiler's "long" type is 32 bits. If the compiler's "long"
|
||||
type is 64 bits, then the limit is 16 exabytes.
|
||||
|
||||
31. Does zlib have any security vulnerabilities?
|
||||
|
||||
The only one that we are aware of is potentially in gzprintf(). If zlib
|
||||
is compiled to use sprintf() or vsprintf(), then there is no protection
|
||||
against a buffer overflow of a 4K string space, other than the caller of
|
||||
gzprintf() assuring that the output will not exceed 4K. On the other
|
||||
hand, if zlib is compiled to use snprintf() or vsnprintf(), which should
|
||||
normally be the case, then there is no vulnerability. The ./configure
|
||||
script will display warnings if an insecure variation of sprintf() will
|
||||
be used by gzprintf(). Also the zlibCompileFlags() function will return
|
||||
information on what variant of sprintf() is used by gzprintf().
|
||||
|
||||
If you don't have snprintf() or vsnprintf() and would like one, you can
|
||||
find a portable implementation here:
|
||||
|
||||
http://www.ijs.si/software/snprintf/
|
||||
|
||||
Note that you should be using the most recent version of zlib. Versions
|
||||
1.1.3 and before were subject to a double-free vulnerability.
|
||||
|
||||
32. Is there a Java version of zlib?
|
||||
|
||||
Probably what you want is to use zlib in Java. zlib is already included
|
||||
as part of the Java SDK in the java.util.zip package. If you really want
|
||||
a version of zlib written in the Java language, look on the zlib home
|
||||
page for links: http://www.zlib.org/
|
||||
|
||||
33. I get this or that compiler or source-code scanner warning when I crank it
|
||||
up to maximally-pendantic. Can't you guys write proper code?
|
||||
|
||||
Many years ago, we gave up attempting to avoid warnings on every compiler
|
||||
in the universe. It just got to be a waste of time, and some compilers
|
||||
were downright silly. So now, we simply make sure that the code always
|
||||
works.
|
||||
|
||||
34. Will zlib read the (insert any ancient or arcane format here) compressed
|
||||
data format?
|
||||
|
||||
Probably not. Look in the comp.compression FAQ for pointers to various
|
||||
formats and associated software.
|
||||
|
||||
35. How can I encrypt/decrypt zip files with zlib?
|
||||
|
||||
zlib doesn't support encryption. The original PKZIP encryption is very weak
|
||||
and can be broken with freely available programs. To get strong encryption,
|
||||
use gpg ( http://www.gnupg.org/ ) which already includes zlib compression.
|
||||
For PKZIP compatible "encryption", look at http://www.info-zip.org/
|
||||
|
||||
36. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings?
|
||||
|
||||
"gzip" is the gzip format, and "deflate" is the zlib format. They should
|
||||
probably have called the second one "zlib" instead to avoid confusion
|
||||
with the raw deflate compressed data format. While the HTTP 1.1 RFC 2616
|
||||
correctly points to the zlib specification in RFC 1950 for the "deflate"
|
||||
transfer encoding, there have been reports of servers and browsers that
|
||||
incorrectly produce or expect raw deflate data per the deflate
|
||||
specficiation in RFC 1951, most notably Microsoft. So even though the
|
||||
"deflate" transfer encoding using the zlib format would be the more
|
||||
efficient approach (and in fact exactly what the zlib format was designed
|
||||
for), using the "gzip" transfer encoding is probably more reliable due to
|
||||
an unfortunate choice of name on the part of the HTTP 1.1 authors.
|
||||
|
||||
Bottom line: use the gzip format for HTTP 1.1 encoding.
|
||||
|
||||
37. Does zlib support the new "Deflate64" format introduced by PKWare?
|
||||
|
||||
No. PKWare has apparently decided to keep that format proprietary, since
|
||||
they have not documented it as they have previous compression formats.
|
||||
In any case, the compression improvements are so modest compared to other
|
||||
more modern approaches, that it's not worth the effort to implement.
|
||||
|
||||
38. Can you please sign these lengthy legal documents and fax them back to us
|
||||
so that we can use your software in our product?
|
||||
|
||||
No. Go away. Shoo.
|
48
zlib/INDEX
Normal file
48
zlib/INDEX
Normal file
|
@ -0,0 +1,48 @@
|
|||
ChangeLog history of changes
|
||||
FAQ Frequently Asked Questions about zlib
|
||||
INDEX this file
|
||||
Makefile makefile for Unix (generated by configure)
|
||||
Makefile.in makefile for Unix (template for configure)
|
||||
README guess what
|
||||
algorithm.txt description of the (de)compression algorithm
|
||||
configure configure script for Unix
|
||||
zconf.in.h template for zconf.h (used by configure)
|
||||
|
||||
msdos/ makefiles for MSDOS
|
||||
old/ makefiles for various architectures and zlib documentation
|
||||
files that have not yet been updated for zlib 1.2.x
|
||||
qnx/ makefiles for QNX
|
||||
win32/ makefiles for Windows
|
||||
|
||||
zlib public header files (must be kept):
|
||||
zconf.h
|
||||
zlib.h
|
||||
|
||||
private source files used to build the zlib library:
|
||||
adler32.c
|
||||
compress.c
|
||||
crc32.c
|
||||
crc32.h
|
||||
deflate.c
|
||||
deflate.h
|
||||
gzio.c
|
||||
infback.c
|
||||
inffast.c
|
||||
inffast.h
|
||||
inffixed.h
|
||||
inflate.c
|
||||
inflate.h
|
||||
inftrees.c
|
||||
inftrees.h
|
||||
trees.c
|
||||
trees.h
|
||||
uncompr.c
|
||||
zutil.c
|
||||
zutil.h
|
||||
|
||||
source files for sample programs:
|
||||
example.c
|
||||
minigzip.c
|
||||
|
||||
unsupported contribution by third parties
|
||||
See contrib/README.contrib
|
154
zlib/Makefile
Normal file
154
zlib/Makefile
Normal file
|
@ -0,0 +1,154 @@
|
|||
# Makefile for zlib
|
||||
# Copyright (C) 1995-2003 Jean-loup Gailly.
|
||||
# For conditions of distribution and use, see copyright notice in zlib.h
|
||||
|
||||
# To compile and test, type:
|
||||
# ./configure; make test
|
||||
# The call of configure is optional if you don't have special requirements
|
||||
# If you wish to build zlib as a shared library, use: ./configure -s
|
||||
|
||||
# To use the asm code, type:
|
||||
# cp contrib/asm?86/match.S ./match.S
|
||||
# make LOC=-DASMV OBJA=match.o
|
||||
|
||||
# To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type:
|
||||
# make install
|
||||
# To install in $HOME instead of /usr/local, use:
|
||||
# make install prefix=$HOME
|
||||
|
||||
CC=cc
|
||||
|
||||
CFLAGS=-O
|
||||
#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7
|
||||
#CFLAGS=-g -DDEBUG
|
||||
#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
|
||||
# -Wstrict-prototypes -Wmissing-prototypes
|
||||
|
||||
LDFLAGS=libz.a
|
||||
LDSHARED=$(CC)
|
||||
CPP=$(CC) -E
|
||||
|
||||
LIBS=libz.a
|
||||
SHAREDLIB=libz.so
|
||||
SHAREDLIBV=libz.so.1.2.1
|
||||
SHAREDLIBM=libz.so.1
|
||||
|
||||
AR=ar rc
|
||||
RANLIB=ranlib
|
||||
TAR=tar
|
||||
SHELL=/bin/sh
|
||||
EXE=
|
||||
|
||||
prefix = /usr/local
|
||||
exec_prefix = ${prefix}
|
||||
libdir = ${exec_prefix}/lib
|
||||
includedir = ${prefix}/include
|
||||
mandir = ${prefix}/share/man
|
||||
man3dir = ${mandir}/man3
|
||||
|
||||
OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \
|
||||
zutil.o inflate.o infback.o inftrees.o inffast.o
|
||||
|
||||
OBJA =
|
||||
# to use the asm code: make OBJA=match.o
|
||||
|
||||
TEST_OBJS = example.o minigzip.o
|
||||
|
||||
all: example$(EXE) minigzip$(EXE)
|
||||
|
||||
check: test
|
||||
test: all
|
||||
@LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \
|
||||
echo hello world | ./minigzip | ./minigzip -d || \
|
||||
echo ' *** minigzip test FAILED ***' ; \
|
||||
if ./example; then \
|
||||
echo ' *** zlib test OK ***'; \
|
||||
else \
|
||||
echo ' *** zlib test FAILED ***'; \
|
||||
fi
|
||||
|
||||
libz.a: $(OBJS) $(OBJA)
|
||||
$(AR) $@ $(OBJS) $(OBJA)
|
||||
-@ ($(RANLIB) $@ || true) >/dev/null 2>&1
|
||||
|
||||
match.o: match.S
|
||||
$(CPP) match.S > _match.s
|
||||
$(CC) -c _match.s
|
||||
mv _match.o match.o
|
||||
rm -f _match.s
|
||||
|
||||
$(SHAREDLIBV): $(OBJS)
|
||||
$(LDSHARED) -o $@ $(OBJS)
|
||||
rm -f $(SHAREDLIB) $(SHAREDLIBM)
|
||||
ln -s $@ $(SHAREDLIB)
|
||||
ln -s $@ $(SHAREDLIBM)
|
||||
|
||||
example$(EXE): example.o $(LIBS)
|
||||
$(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS)
|
||||
|
||||
minigzip$(EXE): minigzip.o $(LIBS)
|
||||
$(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS)
|
||||
|
||||
install: $(LIBS)
|
||||
-@if [ ! -d $(exec_prefix) ]; then mkdir -p $(exec_prefix); fi
|
||||
-@if [ ! -d $(includedir) ]; then mkdir -p $(includedir); fi
|
||||
-@if [ ! -d $(libdir) ]; then mkdir -p $(libdir); fi
|
||||
-@if [ ! -d $(man3dir) ]; then mkdir -p $(man3dir); fi
|
||||
cp zlib.h zconf.h $(includedir)
|
||||
chmod 644 $(includedir)/zlib.h $(includedir)/zconf.h
|
||||
cp $(LIBS) $(libdir)
|
||||
cd $(libdir); chmod 755 $(LIBS)
|
||||
-@(cd $(libdir); $(RANLIB) libz.a || true) >/dev/null 2>&1
|
||||
cd $(libdir); if test -f $(SHAREDLIBV); then \
|
||||
rm -f $(SHAREDLIB) $(SHAREDLIBM); \
|
||||
ln -s $(SHAREDLIBV) $(SHAREDLIB); \
|
||||
ln -s $(SHAREDLIBV) $(SHAREDLIBM); \
|
||||
(ldconfig || true) >/dev/null 2>&1; \
|
||||
fi
|
||||
cp zlib.3 $(man3dir)
|
||||
chmod 644 $(man3dir)/zlib.3
|
||||
# The ranlib in install is needed on NeXTSTEP which checks file times
|
||||
# ldconfig is for Linux
|
||||
|
||||
uninstall:
|
||||
cd $(includedir); \
|
||||
cd $(libdir); rm -f libz.a; \
|
||||
if test -f $(SHAREDLIBV); then \
|
||||
rm -f $(SHAREDLIBV) $(SHAREDLIB) $(SHAREDLIBM); \
|
||||
fi
|
||||
cd $(man3dir); rm -f zlib.3
|
||||
|
||||
mostlyclean: clean
|
||||
clean:
|
||||
rm -f *.o *~ example$(EXE) minigzip$(EXE) \
|
||||
libz.* foo.gz so_locations \
|
||||
_match.s maketree contrib/infback9/*.o
|
||||
|
||||
maintainer-clean: distclean
|
||||
distclean: clean
|
||||
cp -p Makefile.in Makefile
|
||||
cp -p zconf.in.h zconf.h
|
||||
rm -f .DS_Store
|
||||
|
||||
tags:
|
||||
etags *.[ch]
|
||||
|
||||
depend:
|
||||
makedepend -- $(CFLAGS) -- *.[ch]
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
|
||||
adler32.o: zlib.h zconf.h
|
||||
compress.o: zlib.h zconf.h
|
||||
crc32.o: crc32.h zlib.h zconf.h
|
||||
deflate.o: deflate.h zutil.h zlib.h zconf.h
|
||||
example.o: zlib.h zconf.h
|
||||
gzio.o: zutil.h zlib.h zconf.h
|
||||
inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
inftrees.o: zutil.h zlib.h zconf.h inftrees.h
|
||||
minigzip.o: zlib.h zconf.h
|
||||
trees.o: deflate.h zutil.h zlib.h zconf.h trees.h
|
||||
uncompr.o: zlib.h zconf.h
|
||||
zutil.o: zutil.h zlib.h zconf.h
|
154
zlib/Makefile.in
Normal file
154
zlib/Makefile.in
Normal file
|
@ -0,0 +1,154 @@
|
|||
# Makefile for zlib
|
||||
# Copyright (C) 1995-2003 Jean-loup Gailly.
|
||||
# For conditions of distribution and use, see copyright notice in zlib.h
|
||||
|
||||
# To compile and test, type:
|
||||
# ./configure; make test
|
||||
# The call of configure is optional if you don't have special requirements
|
||||
# If you wish to build zlib as a shared library, use: ./configure -s
|
||||
|
||||
# To use the asm code, type:
|
||||
# cp contrib/asm?86/match.S ./match.S
|
||||
# make LOC=-DASMV OBJA=match.o
|
||||
|
||||
# To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type:
|
||||
# make install
|
||||
# To install in $HOME instead of /usr/local, use:
|
||||
# make install prefix=$HOME
|
||||
|
||||
CC=cc
|
||||
|
||||
CFLAGS=-O
|
||||
#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7
|
||||
#CFLAGS=-g -DDEBUG
|
||||
#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
|
||||
# -Wstrict-prototypes -Wmissing-prototypes
|
||||
|
||||
LDFLAGS=libz.a
|
||||
LDSHARED=$(CC)
|
||||
CPP=$(CC) -E
|
||||
|
||||
LIBS=libz.a
|
||||
SHAREDLIB=libz.so
|
||||
SHAREDLIBV=libz.so.1.2.1
|
||||
SHAREDLIBM=libz.so.1
|
||||
|
||||
AR=ar rc
|
||||
RANLIB=ranlib
|
||||
TAR=tar
|
||||
SHELL=/bin/sh
|
||||
EXE=
|
||||
|
||||
prefix = /usr/local
|
||||
exec_prefix = ${prefix}
|
||||
libdir = ${exec_prefix}/lib
|
||||
includedir = ${prefix}/include
|
||||
mandir = ${prefix}/share/man
|
||||
man3dir = ${mandir}/man3
|
||||
|
||||
OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \
|
||||
zutil.o inflate.o infback.o inftrees.o inffast.o
|
||||
|
||||
OBJA =
|
||||
# to use the asm code: make OBJA=match.o
|
||||
|
||||
TEST_OBJS = example.o minigzip.o
|
||||
|
||||
all: example$(EXE) minigzip$(EXE)
|
||||
|
||||
check: test
|
||||
test: all
|
||||
@LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \
|
||||
echo hello world | ./minigzip | ./minigzip -d || \
|
||||
echo ' *** minigzip test FAILED ***' ; \
|
||||
if ./example; then \
|
||||
echo ' *** zlib test OK ***'; \
|
||||
else \
|
||||
echo ' *** zlib test FAILED ***'; \
|
||||
fi
|
||||
|
||||
libz.a: $(OBJS) $(OBJA)
|
||||
$(AR) $@ $(OBJS) $(OBJA)
|
||||
-@ ($(RANLIB) $@ || true) >/dev/null 2>&1
|
||||
|
||||
match.o: match.S
|
||||
$(CPP) match.S > _match.s
|
||||
$(CC) -c _match.s
|
||||
mv _match.o match.o
|
||||
rm -f _match.s
|
||||
|
||||
$(SHAREDLIBV): $(OBJS)
|
||||
$(LDSHARED) -o $@ $(OBJS)
|
||||
rm -f $(SHAREDLIB) $(SHAREDLIBM)
|
||||
ln -s $@ $(SHAREDLIB)
|
||||
ln -s $@ $(SHAREDLIBM)
|
||||
|
||||
example$(EXE): example.o $(LIBS)
|
||||
$(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS)
|
||||
|
||||
minigzip$(EXE): minigzip.o $(LIBS)
|
||||
$(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS)
|
||||
|
||||
install: $(LIBS)
|
||||
-@if [ ! -d $(exec_prefix) ]; then mkdir -p $(exec_prefix); fi
|
||||
-@if [ ! -d $(includedir) ]; then mkdir -p $(includedir); fi
|
||||
-@if [ ! -d $(libdir) ]; then mkdir -p $(libdir); fi
|
||||
-@if [ ! -d $(man3dir) ]; then mkdir -p $(man3dir); fi
|
||||
cp zlib.h zconf.h $(includedir)
|
||||
chmod 644 $(includedir)/zlib.h $(includedir)/zconf.h
|
||||
cp $(LIBS) $(libdir)
|
||||
cd $(libdir); chmod 755 $(LIBS)
|
||||
-@(cd $(libdir); $(RANLIB) libz.a || true) >/dev/null 2>&1
|
||||
cd $(libdir); if test -f $(SHAREDLIBV); then \
|
||||
rm -f $(SHAREDLIB) $(SHAREDLIBM); \
|
||||
ln -s $(SHAREDLIBV) $(SHAREDLIB); \
|
||||
ln -s $(SHAREDLIBV) $(SHAREDLIBM); \
|
||||
(ldconfig || true) >/dev/null 2>&1; \
|
||||
fi
|
||||
cp zlib.3 $(man3dir)
|
||||
chmod 644 $(man3dir)/zlib.3
|
||||
# The ranlib in install is needed on NeXTSTEP which checks file times
|
||||
# ldconfig is for Linux
|
||||
|
||||
uninstall:
|
||||
cd $(includedir); \
|
||||
cd $(libdir); rm -f libz.a; \
|
||||
if test -f $(SHAREDLIBV); then \
|
||||
rm -f $(SHAREDLIBV) $(SHAREDLIB) $(SHAREDLIBM); \
|
||||
fi
|
||||
cd $(man3dir); rm -f zlib.3
|
||||
|
||||
mostlyclean: clean
|
||||
clean:
|
||||
rm -f *.o *~ example$(EXE) minigzip$(EXE) \
|
||||
libz.* foo.gz so_locations \
|
||||
_match.s maketree contrib/infback9/*.o
|
||||
|
||||
maintainer-clean: distclean
|
||||
distclean: clean
|
||||
cp -p Makefile.in Makefile
|
||||
cp -p zconf.in.h zconf.h
|
||||
rm -f .DS_Store
|
||||
|
||||
tags:
|
||||
etags *.[ch]
|
||||
|
||||
depend:
|
||||
makedepend -- $(CFLAGS) -- *.[ch]
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
|
||||
adler32.o: zlib.h zconf.h
|
||||
compress.o: zlib.h zconf.h
|
||||
crc32.o: crc32.h zlib.h zconf.h
|
||||
deflate.o: deflate.h zutil.h zlib.h zconf.h
|
||||
example.o: zlib.h zconf.h
|
||||
gzio.o: zutil.h zlib.h zconf.h
|
||||
inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
inftrees.o: zutil.h zlib.h zconf.h inftrees.h
|
||||
minigzip.o: zlib.h zconf.h
|
||||
trees.o: deflate.h zutil.h zlib.h zconf.h trees.h
|
||||
uncompr.o: zlib.h zconf.h
|
||||
zutil.o: zutil.h zlib.h zconf.h
|
126
zlib/README
Normal file
126
zlib/README
Normal file
|
@ -0,0 +1,126 @@
|
|||
ZLIB DATA COMPRESSION LIBRARY
|
||||
|
||||
zlib 1.2.1 is a general purpose data compression library. All the code is
|
||||
thread safe. The data format used by the zlib library is described by RFCs
|
||||
(Request for Comments) 1950 to 1952 in the files
|
||||
http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format)
|
||||
and rfc1952.txt (gzip format). These documents are also available in other
|
||||
formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html
|
||||
|
||||
All functions of the compression library are documented in the file zlib.h
|
||||
(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example
|
||||
of the library is given in the file example.c which also tests that the library
|
||||
is working correctly. Another example is given in the file minigzip.c. The
|
||||
compression library itself is composed of all source files except example.c and
|
||||
minigzip.c.
|
||||
|
||||
To compile all files and run the test program, follow the instructions given at
|
||||
the top of Makefile. In short "make test; make install" should work for most
|
||||
machines. For Unix: "./configure; make test; make install" For MSDOS, use one
|
||||
of the special makefiles such as Makefile.msc. For VMS, use Make_vms.com or
|
||||
descrip.mms.
|
||||
|
||||
Questions about zlib should be sent to <zlib@gzip.org>, or to Gilles Vollant
|
||||
<info@winimage.com> for the Windows DLL version. The zlib home page is
|
||||
http://www.zlib.org or http://www.gzip.org/zlib/ Before reporting a problem,
|
||||
please check this site to verify that you have the latest version of zlib;
|
||||
otherwise get the latest version and check whether the problem still exists or
|
||||
not.
|
||||
|
||||
PLEASE read the zlib FAQ http://www.gzip.org/zlib/zlib_faq.html before asking
|
||||
for help.
|
||||
|
||||
Mark Nelson <markn@ieee.org> wrote an article about zlib for the Jan. 1997
|
||||
issue of Dr. Dobb's Journal; a copy of the article is available in
|
||||
http://dogma.net/markn/articles/zlibtool/zlibtool.htm
|
||||
|
||||
The changes made in version 1.2.1 are documented in the file ChangeLog.
|
||||
|
||||
Unsupported third party contributions are provided in directory "contrib".
|
||||
|
||||
A Java implementation of zlib is available in the Java Development Kit
|
||||
http://java.sun.com/j2se/1.4.2/docs/api/java/util/zip/package-summary.html
|
||||
See the zlib home page http://www.zlib.org for details.
|
||||
|
||||
A Perl interface to zlib written by Paul Marquess <pmqs@cpan.org> is in the
|
||||
CPAN (Comprehensive Perl Archive Network) sites
|
||||
http://www.cpan.org/modules/by-module/Compress/
|
||||
|
||||
A Python interface to zlib written by A.M. Kuchling <amk@magnet.com> is
|
||||
available in Python 1.5 and later versions, see
|
||||
http://www.python.org/doc/lib/module-zlib.html
|
||||
|
||||
A zlib binding for TCL written by Andreas Kupries <a.kupries@westend.com> is
|
||||
availlable at http://www.oche.de/~akupries/soft/trf/trf_zip.html
|
||||
|
||||
An experimental package to read and write files in .zip format, written on top
|
||||
of zlib by Gilles Vollant <info@winimage.com>, is available in the
|
||||
contrib/minizip directory of zlib.
|
||||
|
||||
|
||||
Notes for some targets:
|
||||
|
||||
- For Windows DLL versions, please see win32/DLL_FAQ.txt
|
||||
|
||||
- For 64-bit Irix, deflate.c must be compiled without any optimization. With
|
||||
-O, one libpng test fails. The test works in 32 bit mode (with the -n32
|
||||
compiler flag). The compiler bug has been reported to SGI.
|
||||
|
||||
- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works
|
||||
when compiled with cc.
|
||||
|
||||
- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is
|
||||
necessary to get gzprintf working correctly. This is done by configure.
|
||||
|
||||
- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with
|
||||
other compilers. Use "make test" to check your compiler.
|
||||
|
||||
- gzdopen is not supported on RISCOS, BEOS and by some Mac compilers.
|
||||
|
||||
- For PalmOs, see http://palmzlib.sourceforge.net/
|
||||
|
||||
- When building a shared, i.e. dynamic library on Mac OS X, the library must be
|
||||
installed before testing (do "make install" before "make test"), since the
|
||||
library location is specified in the library.
|
||||
|
||||
|
||||
Acknowledgments:
|
||||
|
||||
The deflate format used by zlib was defined by Phil Katz. The deflate
|
||||
and zlib specifications were written by L. Peter Deutsch. Thanks to all the
|
||||
people who reported problems and suggested various improvements in zlib;
|
||||
they are too numerous to cite here.
|
||||
|
||||
Copyright notice:
|
||||
|
||||
(C) 1995-2003 Jean-loup Gailly and Mark Adler
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Jean-loup Gailly Mark Adler
|
||||
jloup@gzip.org madler@alumni.caltech.edu
|
||||
|
||||
If you use the zlib library in a product, we would appreciate *not*
|
||||
receiving lengthy legal documents to sign. The sources are provided
|
||||
for free but without warranty of any kind. The library has been
|
||||
entirely written by Jean-loup Gailly and Mark Adler; it does not
|
||||
include third-party code.
|
||||
|
||||
If you redistribute modified sources, we would appreciate that you include
|
||||
in the file ChangeLog history information documenting your changes. Please
|
||||
read the FAQ for more information on the distribution of modified source
|
||||
versions.
|
74
zlib/adler32.c
Normal file
74
zlib/adler32.c
Normal file
|
@ -0,0 +1,74 @@
|
|||
/* adler32.c -- compute the Adler-32 checksum of a data stream
|
||||
* Copyright (C) 1995-2003 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#define ZLIB_INTERNAL
|
||||
#include "zlib.h"
|
||||
|
||||
#define BASE 65521UL /* largest prime smaller than 65536 */
|
||||
#define NMAX 5552
|
||||
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
|
||||
|
||||
#define DO1(buf,i) {s1 += buf[i]; s2 += s1;}
|
||||
#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
|
||||
#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
|
||||
#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
|
||||
#define DO16(buf) DO8(buf,0); DO8(buf,8);
|
||||
|
||||
#ifdef NO_DIVIDE
|
||||
# define MOD(a) \
|
||||
do { \
|
||||
if (a >= (BASE << 16)) a -= (BASE << 16); \
|
||||
if (a >= (BASE << 15)) a -= (BASE << 15); \
|
||||
if (a >= (BASE << 14)) a -= (BASE << 14); \
|
||||
if (a >= (BASE << 13)) a -= (BASE << 13); \
|
||||
if (a >= (BASE << 12)) a -= (BASE << 12); \
|
||||
if (a >= (BASE << 11)) a -= (BASE << 11); \
|
||||
if (a >= (BASE << 10)) a -= (BASE << 10); \
|
||||
if (a >= (BASE << 9)) a -= (BASE << 9); \
|
||||
if (a >= (BASE << 8)) a -= (BASE << 8); \
|
||||
if (a >= (BASE << 7)) a -= (BASE << 7); \
|
||||
if (a >= (BASE << 6)) a -= (BASE << 6); \
|
||||
if (a >= (BASE << 5)) a -= (BASE << 5); \
|
||||
if (a >= (BASE << 4)) a -= (BASE << 4); \
|
||||
if (a >= (BASE << 3)) a -= (BASE << 3); \
|
||||
if (a >= (BASE << 2)) a -= (BASE << 2); \
|
||||
if (a >= (BASE << 1)) a -= (BASE << 1); \
|
||||
if (a >= BASE) a -= BASE; \
|
||||
} while (0)
|
||||
#else
|
||||
# define MOD(a) a %= BASE
|
||||
#endif
|
||||
|
||||
/* ========================================================================= */
|
||||
uLong ZEXPORT adler32(adler, buf, len)
|
||||
uLong adler;
|
||||
const Bytef *buf;
|
||||
uInt len;
|
||||
{
|
||||
unsigned long s1 = adler & 0xffff;
|
||||
unsigned long s2 = (adler >> 16) & 0xffff;
|
||||
int k;
|
||||
|
||||
if (buf == Z_NULL) return 1L;
|
||||
|
||||
while (len > 0) {
|
||||
k = len < NMAX ? (int)len : NMAX;
|
||||
len -= k;
|
||||
while (k >= 16) {
|
||||
DO16(buf);
|
||||
buf += 16;
|
||||
k -= 16;
|
||||
}
|
||||
if (k != 0) do {
|
||||
s1 += *buf++;
|
||||
s2 += s1;
|
||||
} while (--k);
|
||||
MOD(s1);
|
||||
MOD(s2);
|
||||
}
|
||||
return (s2 << 16) | s1;
|
||||
}
|
209
zlib/algorithm.txt
Normal file
209
zlib/algorithm.txt
Normal file
|
@ -0,0 +1,209 @@
|
|||
1. Compression algorithm (deflate)
|
||||
|
||||
The deflation algorithm used by gzip (also zip and zlib) is a variation of
|
||||
LZ77 (Lempel-Ziv 1977, see reference below). It finds duplicated strings in
|
||||
the input data. The second occurrence of a string is replaced by a
|
||||
pointer to the previous string, in the form of a pair (distance,
|
||||
length). Distances are limited to 32K bytes, and lengths are limited
|
||||
to 258 bytes. When a string does not occur anywhere in the previous
|
||||
32K bytes, it is emitted as a sequence of literal bytes. (In this
|
||||
description, `string' must be taken as an arbitrary sequence of bytes,
|
||||
and is not restricted to printable characters.)
|
||||
|
||||
Literals or match lengths are compressed with one Huffman tree, and
|
||||
match distances are compressed with another tree. The trees are stored
|
||||
in a compact form at the start of each block. The blocks can have any
|
||||
size (except that the compressed data for one block must fit in
|
||||
available memory). A block is terminated when deflate() determines that
|
||||
it would be useful to start another block with fresh trees. (This is
|
||||
somewhat similar to the behavior of LZW-based _compress_.)
|
||||
|
||||
Duplicated strings are found using a hash table. All input strings of
|
||||
length 3 are inserted in the hash table. A hash index is computed for
|
||||
the next 3 bytes. If the hash chain for this index is not empty, all
|
||||
strings in the chain are compared with the current input string, and
|
||||
the longest match is selected.
|
||||
|
||||
The hash chains are searched starting with the most recent strings, to
|
||||
favor small distances and thus take advantage of the Huffman encoding.
|
||||
The hash chains are singly linked. There are no deletions from the
|
||||
hash chains, the algorithm simply discards matches that are too old.
|
||||
|
||||
To avoid a worst-case situation, very long hash chains are arbitrarily
|
||||
truncated at a certain length, determined by a runtime option (level
|
||||
parameter of deflateInit). So deflate() does not always find the longest
|
||||
possible match but generally finds a match which is long enough.
|
||||
|
||||
deflate() also defers the selection of matches with a lazy evaluation
|
||||
mechanism. After a match of length N has been found, deflate() searches for
|
||||
a longer match at the next input byte. If a longer match is found, the
|
||||
previous match is truncated to a length of one (thus producing a single
|
||||
literal byte) and the process of lazy evaluation begins again. Otherwise,
|
||||
the original match is kept, and the next match search is attempted only N
|
||||
steps later.
|
||||
|
||||
The lazy match evaluation is also subject to a runtime parameter. If
|
||||
the current match is long enough, deflate() reduces the search for a longer
|
||||
match, thus speeding up the whole process. If compression ratio is more
|
||||
important than speed, deflate() attempts a complete second search even if
|
||||
the first match is already long enough.
|
||||
|
||||
The lazy match evaluation is not performed for the fastest compression
|
||||
modes (level parameter 1 to 3). For these fast modes, new strings
|
||||
are inserted in the hash table only when no match was found, or
|
||||
when the match is not too long. This degrades the compression ratio
|
||||
but saves time since there are both fewer insertions and fewer searches.
|
||||
|
||||
|
||||
2. Decompression algorithm (inflate)
|
||||
|
||||
2.1 Introduction
|
||||
|
||||
The key question is how to represent a Huffman code (or any prefix code) so
|
||||
that you can decode fast. The most important characteristic is that shorter
|
||||
codes are much more common than longer codes, so pay attention to decoding the
|
||||
short codes fast, and let the long codes take longer to decode.
|
||||
|
||||
inflate() sets up a first level table that covers some number of bits of
|
||||
input less than the length of longest code. It gets that many bits from the
|
||||
stream, and looks it up in the table. The table will tell if the next
|
||||
code is that many bits or less and how many, and if it is, it will tell
|
||||
the value, else it will point to the next level table for which inflate()
|
||||
grabs more bits and tries to decode a longer code.
|
||||
|
||||
How many bits to make the first lookup is a tradeoff between the time it
|
||||
takes to decode and the time it takes to build the table. If building the
|
||||
table took no time (and if you had infinite memory), then there would only
|
||||
be a first level table to cover all the way to the longest code. However,
|
||||
building the table ends up taking a lot longer for more bits since short
|
||||
codes are replicated many times in such a table. What inflate() does is
|
||||
simply to make the number of bits in the first table a variable, and then
|
||||
to set that variable for the maximum speed.
|
||||
|
||||
For inflate, which has 286 possible codes for the literal/length tree, the size
|
||||
of the first table is nine bits. Also the distance trees have 30 possible
|
||||
values, and the size of the first table is six bits. Note that for each of
|
||||
those cases, the table ended up one bit longer than the ``average'' code
|
||||
length, i.e. the code length of an approximately flat code which would be a
|
||||
little more than eight bits for 286 symbols and a little less than five bits
|
||||
for 30 symbols.
|
||||
|
||||
|
||||
2.2 More details on the inflate table lookup
|
||||
|
||||
Ok, you want to know what this cleverly obfuscated inflate tree actually
|
||||
looks like. You are correct that it's not a Huffman tree. It is simply a
|
||||
lookup table for the first, let's say, nine bits of a Huffman symbol. The
|
||||
symbol could be as short as one bit or as long as 15 bits. If a particular
|
||||
symbol is shorter than nine bits, then that symbol's translation is duplicated
|
||||
in all those entries that start with that symbol's bits. For example, if the
|
||||
symbol is four bits, then it's duplicated 32 times in a nine-bit table. If a
|
||||
symbol is nine bits long, it appears in the table once.
|
||||
|
||||
If the symbol is longer than nine bits, then that entry in the table points
|
||||
to another similar table for the remaining bits. Again, there are duplicated
|
||||
entries as needed. The idea is that most of the time the symbol will be short
|
||||
and there will only be one table look up. (That's whole idea behind data
|
||||
compression in the first place.) For the less frequent long symbols, there
|
||||
will be two lookups. If you had a compression method with really long
|
||||
symbols, you could have as many levels of lookups as is efficient. For
|
||||
inflate, two is enough.
|
||||
|
||||
So a table entry either points to another table (in which case nine bits in
|
||||
the above example are gobbled), or it contains the translation for the symbol
|
||||
and the number of bits to gobble. Then you start again with the next
|
||||
ungobbled bit.
|
||||
|
||||
You may wonder: why not just have one lookup table for how ever many bits the
|
||||
longest symbol is? The reason is that if you do that, you end up spending
|
||||
more time filling in duplicate symbol entries than you do actually decoding.
|
||||
At least for deflate's output that generates new trees every several 10's of
|
||||
kbytes. You can imagine that filling in a 2^15 entry table for a 15-bit code
|
||||
would take too long if you're only decoding several thousand symbols. At the
|
||||
other extreme, you could make a new table for every bit in the code. In fact,
|
||||
that's essentially a Huffman tree. But then you spend two much time
|
||||
traversing the tree while decoding, even for short symbols.
|
||||
|
||||
So the number of bits for the first lookup table is a trade of the time to
|
||||
fill out the table vs. the time spent looking at the second level and above of
|
||||
the table.
|
||||
|
||||
Here is an example, scaled down:
|
||||
|
||||
The code being decoded, with 10 symbols, from 1 to 6 bits long:
|
||||
|
||||
A: 0
|
||||
B: 10
|
||||
C: 1100
|
||||
D: 11010
|
||||
E: 11011
|
||||
F: 11100
|
||||
G: 11101
|
||||
H: 11110
|
||||
I: 111110
|
||||
J: 111111
|
||||
|
||||
Let's make the first table three bits long (eight entries):
|
||||
|
||||
000: A,1
|
||||
001: A,1
|
||||
010: A,1
|
||||
011: A,1
|
||||
100: B,2
|
||||
101: B,2
|
||||
110: -> table X (gobble 3 bits)
|
||||
111: -> table Y (gobble 3 bits)
|
||||
|
||||
Each entry is what the bits decode as and how many bits that is, i.e. how
|
||||
many bits to gobble. Or the entry points to another table, with the number of
|
||||
bits to gobble implicit in the size of the table.
|
||||
|
||||
Table X is two bits long since the longest code starting with 110 is five bits
|
||||
long:
|
||||
|
||||
00: C,1
|
||||
01: C,1
|
||||
10: D,2
|
||||
11: E,2
|
||||
|
||||
Table Y is three bits long since the longest code starting with 111 is six
|
||||
bits long:
|
||||
|
||||
000: F,2
|
||||
001: F,2
|
||||
010: G,2
|
||||
011: G,2
|
||||
100: H,2
|
||||
101: H,2
|
||||
110: I,3
|
||||
111: J,3
|
||||
|
||||
So what we have here are three tables with a total of 20 entries that had to
|
||||
be constructed. That's compared to 64 entries for a single table. Or
|
||||
compared to 16 entries for a Huffman tree (six two entry tables and one four
|
||||
entry table). Assuming that the code ideally represents the probability of
|
||||
the symbols, it takes on the average 1.25 lookups per symbol. That's compared
|
||||
to one lookup for the single table, or 1.66 lookups per symbol for the
|
||||
Huffman tree.
|
||||
|
||||
There, I think that gives you a picture of what's going on. For inflate, the
|
||||
meaning of a particular symbol is often more than just a letter. It can be a
|
||||
byte (a "literal"), or it can be either a length or a distance which
|
||||
indicates a base value and a number of bits to fetch after the code that is
|
||||
added to the base value. Or it might be the special end-of-block code. The
|
||||
data structures created in inftrees.c try to encode all that information
|
||||
compactly in the tables.
|
||||
|
||||
|
||||
Jean-loup Gailly Mark Adler
|
||||
jloup@gzip.org madler@alumni.caltech.edu
|
||||
|
||||
|
||||
References:
|
||||
|
||||
[LZ77] Ziv J., Lempel A., ``A Universal Algorithm for Sequential Data
|
||||
Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3,
|
||||
pp. 337-343.
|
||||
|
||||
``DEFLATE Compressed Data Format Specification'' available in
|
||||
http://www.ietf.org/rfc/rfc1951.txt
|
66
zlib/amiga/Makefile.pup
Normal file
66
zlib/amiga/Makefile.pup
Normal file
|
@ -0,0 +1,66 @@
|
|||
# Amiga powerUP (TM) Makefile
|
||||
# makefile for libpng and SAS C V6.58/7.00 PPC compiler
|
||||
# Copyright (C) 1998 by Andreas R. Kleinert
|
||||
|
||||
LIBNAME = libzip.a
|
||||
|
||||
CC = scppc
|
||||
CFLAGS = NOSTKCHK NOSINT OPTIMIZE OPTGO OPTPEEP OPTINLOCAL OPTINL \
|
||||
OPTLOOP OPTRDEP=8 OPTDEP=8 OPTCOMP=8 NOVER
|
||||
AR = ppc-amigaos-ar cr
|
||||
RANLIB = ppc-amigaos-ranlib
|
||||
LD = ppc-amigaos-ld -r
|
||||
LDFLAGS = -o
|
||||
LDLIBS = LIB:scppc.a LIB:end.o
|
||||
RM = delete quiet
|
||||
|
||||
OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \
|
||||
zutil.o inflate.o infback.o inftrees.o inffast.o
|
||||
|
||||
TEST_OBJS = example.o minigzip.o
|
||||
|
||||
all: example minigzip
|
||||
|
||||
check: test
|
||||
test: all
|
||||
example
|
||||
echo hello world | minigzip | minigzip -d
|
||||
|
||||
$(LIBNAME): $(OBJS)
|
||||
$(AR) $@ $(OBJS)
|
||||
-$(RANLIB) $@
|
||||
|
||||
example: example.o $(LIBNAME)
|
||||
$(LD) $(LDFLAGS) $@ LIB:c_ppc.o $@.o $(LIBNAME) $(LDLIBS)
|
||||
|
||||
minigzip: minigzip.o $(LIBNAME)
|
||||
$(LD) $(LDFLAGS) $@ LIB:c_ppc.o $@.o $(LIBNAME) $(LDLIBS)
|
||||
|
||||
mostlyclean: clean
|
||||
clean:
|
||||
$(RM) *.o example minigzip $(LIBNAME) foo.gz
|
||||
|
||||
zip:
|
||||
zip -ul9 zlib README ChangeLog Makefile Make????.??? Makefile.?? \
|
||||
descrip.mms *.[ch]
|
||||
|
||||
tgz:
|
||||
cd ..; tar cfz zlib/zlib.tgz zlib/README zlib/ChangeLog zlib/Makefile \
|
||||
zlib/Make????.??? zlib/Makefile.?? zlib/descrip.mms zlib/*.[ch]
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
|
||||
adler32.o: zlib.h zconf.h
|
||||
compress.o: zlib.h zconf.h
|
||||
crc32.o: crc32.h zlib.h zconf.h
|
||||
deflate.o: deflate.h zutil.h zlib.h zconf.h
|
||||
example.o: zlib.h zconf.h
|
||||
gzio.o: zutil.h zlib.h zconf.h
|
||||
inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
inftrees.o: zutil.h zlib.h zconf.h inftrees.h
|
||||
minigzip.o: zlib.h zconf.h
|
||||
trees.o: deflate.h zutil.h zlib.h zconf.h trees.h
|
||||
uncompr.o: zlib.h zconf.h
|
||||
zutil.o: zutil.h zlib.h zconf.h
|
65
zlib/amiga/Makefile.sas
Normal file
65
zlib/amiga/Makefile.sas
Normal file
|
@ -0,0 +1,65 @@
|
|||
# SMakefile for zlib
|
||||
# Modified from the standard UNIX Makefile Copyright Jean-loup Gailly
|
||||
# Osma Ahvenlampi <Osma.Ahvenlampi@hut.fi>
|
||||
# Amiga, SAS/C 6.56 & Smake
|
||||
|
||||
CC=sc
|
||||
CFLAGS=OPT
|
||||
#CFLAGS=OPT CPU=68030
|
||||
#CFLAGS=DEBUG=LINE
|
||||
LDFLAGS=LIB z.lib
|
||||
|
||||
SCOPTIONS=OPTSCHED OPTINLINE OPTALIAS OPTTIME OPTINLOCAL STRMERGE \
|
||||
NOICONS PARMS=BOTH NOSTACKCHECK UTILLIB NOVERSION ERRORREXX \
|
||||
DEF=POSTINC
|
||||
|
||||
OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \
|
||||
zutil.o inflate.o infback.o inftrees.o inffast.o
|
||||
|
||||
TEST_OBJS = example.o minigzip.o
|
||||
|
||||
all: SCOPTIONS example minigzip
|
||||
|
||||
check: test
|
||||
test: all
|
||||
example
|
||||
echo hello world | minigzip | minigzip -d
|
||||
|
||||
install: z.lib
|
||||
copy clone zlib.h zconf.h INCLUDE:
|
||||
copy clone z.lib LIB:
|
||||
|
||||
z.lib: $(OBJS)
|
||||
oml z.lib r $(OBJS)
|
||||
|
||||
example: example.o z.lib
|
||||
$(CC) $(CFLAGS) LINK TO $@ example.o $(LDFLAGS)
|
||||
|
||||
minigzip: minigzip.o z.lib
|
||||
$(CC) $(CFLAGS) LINK TO $@ minigzip.o $(LDFLAGS)
|
||||
|
||||
mostlyclean: clean
|
||||
clean:
|
||||
-delete force quiet example minigzip *.o z.lib foo.gz *.lnk SCOPTIONS
|
||||
|
||||
SCOPTIONS: Makefile.sas
|
||||
copy to $@ <from <
|
||||
$(SCOPTIONS)
|
||||
<
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
|
||||
adler32.o: zlib.h zconf.h
|
||||
compress.o: zlib.h zconf.h
|
||||
crc32.o: crc32.h zlib.h zconf.h
|
||||
deflate.o: deflate.h zutil.h zlib.h zconf.h
|
||||
example.o: zlib.h zconf.h
|
||||
gzio.o: zutil.h zlib.h zconf.h
|
||||
inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
inftrees.o: zutil.h zlib.h zconf.h inftrees.h
|
||||
minigzip.o: zlib.h zconf.h
|
||||
trees.o: deflate.h zutil.h zlib.h zconf.h trees.h
|
||||
uncompr.o: zlib.h zconf.h
|
||||
zutil.o: zutil.h zlib.h zconf.h
|
132
zlib/as400/bndsrc
Normal file
132
zlib/as400/bndsrc
Normal file
|
@ -0,0 +1,132 @@
|
|||
STRPGMEXP PGMLVL(*CURRENT) SIGNATURE('ZLIB')
|
||||
|
||||
/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
|
||||
/* Version 1.1.3 entry points. */
|
||||
/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
|
||||
|
||||
/********************************************************************/
|
||||
/* *MODULE ADLER32 ZLIB 01/02/01 00:15:09 */
|
||||
/********************************************************************/
|
||||
|
||||
EXPORT SYMBOL("adler32")
|
||||
|
||||
/********************************************************************/
|
||||
/* *MODULE COMPRESS ZLIB 01/02/01 00:15:09 */
|
||||
/********************************************************************/
|
||||
|
||||
EXPORT SYMBOL("compress")
|
||||
EXPORT SYMBOL("compress2")
|
||||
|
||||
/********************************************************************/
|
||||
/* *MODULE CRC32 ZLIB 01/02/01 00:15:09 */
|
||||
/********************************************************************/
|
||||
|
||||
EXPORT SYMBOL("crc32")
|
||||
EXPORT SYMBOL("get_crc_table")
|
||||
|
||||
/********************************************************************/
|
||||
/* *MODULE DEFLATE ZLIB 01/02/01 00:15:09 */
|
||||
/********************************************************************/
|
||||
|
||||
EXPORT SYMBOL("deflate")
|
||||
EXPORT SYMBOL("deflateEnd")
|
||||
EXPORT SYMBOL("deflateSetDictionary")
|
||||
EXPORT SYMBOL("deflateCopy")
|
||||
EXPORT SYMBOL("deflateReset")
|
||||
EXPORT SYMBOL("deflateParams")
|
||||
EXPORT SYMBOL("deflatePrime")
|
||||
EXPORT SYMBOL("deflateInit_")
|
||||
EXPORT SYMBOL("deflateInit2_")
|
||||
|
||||
/********************************************************************/
|
||||
/* *MODULE GZIO ZLIB 01/02/01 00:15:09 */
|
||||
/********************************************************************/
|
||||
|
||||
EXPORT SYMBOL("gzopen")
|
||||
EXPORT SYMBOL("gzdopen")
|
||||
EXPORT SYMBOL("gzsetparams")
|
||||
EXPORT SYMBOL("gzread")
|
||||
EXPORT SYMBOL("gzwrite")
|
||||
EXPORT SYMBOL("gzprintf")
|
||||
EXPORT SYMBOL("gzputs")
|
||||
EXPORT SYMBOL("gzgets")
|
||||
EXPORT SYMBOL("gzputc")
|
||||
EXPORT SYMBOL("gzgetc")
|
||||
EXPORT SYMBOL("gzflush")
|
||||
EXPORT SYMBOL("gzseek")
|
||||
EXPORT SYMBOL("gzrewind")
|
||||
EXPORT SYMBOL("gztell")
|
||||
EXPORT SYMBOL("gzeof")
|
||||
EXPORT SYMBOL("gzclose")
|
||||
EXPORT SYMBOL("gzerror")
|
||||
|
||||
/********************************************************************/
|
||||
/* *MODULE INFLATE ZLIB 01/02/01 00:15:09 */
|
||||
/********************************************************************/
|
||||
|
||||
EXPORT SYMBOL("inflate")
|
||||
EXPORT SYMBOL("inflateEnd")
|
||||
EXPORT SYMBOL("inflateSetDictionary")
|
||||
EXPORT SYMBOL("inflateSync")
|
||||
EXPORT SYMBOL("inflateReset")
|
||||
EXPORT SYMBOL("inflateInit_")
|
||||
EXPORT SYMBOL("inflateInit2_")
|
||||
EXPORT SYMBOL("inflateSyncPoint")
|
||||
|
||||
/********************************************************************/
|
||||
/* *MODULE UNCOMPR ZLIB 01/02/01 00:15:09 */
|
||||
/********************************************************************/
|
||||
|
||||
EXPORT SYMBOL("uncompress")
|
||||
|
||||
/********************************************************************/
|
||||
/* *MODULE ZUTIL ZLIB 01/02/01 00:15:09 */
|
||||
/********************************************************************/
|
||||
|
||||
EXPORT SYMBOL("zlibVersion")
|
||||
EXPORT SYMBOL("zError")
|
||||
|
||||
/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
|
||||
/* Version 1.2.1 additional entry points. */
|
||||
/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
|
||||
|
||||
/********************************************************************/
|
||||
/* *MODULE COMPRESS ZLIB 01/02/01 00:15:09 */
|
||||
/********************************************************************/
|
||||
|
||||
EXPORT SYMBOL("compressBound")
|
||||
|
||||
/********************************************************************/
|
||||
/* *MODULE DEFLATE ZLIB 01/02/01 00:15:09 */
|
||||
/********************************************************************/
|
||||
|
||||
EXPORT SYMBOL("deflateBound")
|
||||
|
||||
/********************************************************************/
|
||||
/* *MODULE GZIO ZLIB 01/02/01 00:15:09 */
|
||||
/********************************************************************/
|
||||
|
||||
EXPORT SYMBOL("gzungetc")
|
||||
EXPORT SYMBOL("gzclearerr")
|
||||
|
||||
/********************************************************************/
|
||||
/* *MODULE INFBACK ZLIB 01/02/01 00:15:09 */
|
||||
/********************************************************************/
|
||||
|
||||
EXPORT SYMBOL("inflateBack")
|
||||
EXPORT SYMBOL("inflateBackEnd")
|
||||
EXPORT SYMBOL("inflateBackInit_")
|
||||
|
||||
/********************************************************************/
|
||||
/* *MODULE INFLATE ZLIB 01/02/01 00:15:09 */
|
||||
/********************************************************************/
|
||||
|
||||
EXPORT SYMBOL("inflateCopy")
|
||||
|
||||
/********************************************************************/
|
||||
/* *MODULE ZUTIL ZLIB 01/02/01 00:15:09 */
|
||||
/********************************************************************/
|
||||
|
||||
EXPORT SYMBOL("zlibCompileFlags")
|
||||
|
||||
ENDPGMEXP
|
123
zlib/as400/compile.clp
Normal file
123
zlib/as400/compile.clp
Normal file
|
@ -0,0 +1,123 @@
|
|||
/******************************************************************************/
|
||||
/* */
|
||||
/* ZLIB */
|
||||
/* */
|
||||
/* Compile sources into modules and link them into a service program. */
|
||||
/* */
|
||||
/******************************************************************************/
|
||||
|
||||
PGM
|
||||
|
||||
/* Configuration adjustable parameters. */
|
||||
|
||||
DCL VAR(&SRCLIB) TYPE(*CHAR) LEN(10) +
|
||||
VALUE('ZLIB') /* Source library. */
|
||||
DCL VAR(&SRCFILE) TYPE(*CHAR) LEN(10) +
|
||||
VALUE('SOURCES') /* Source member file. */
|
||||
DCL VAR(&CTLFILE) TYPE(*CHAR) LEN(10) +
|
||||
VALUE('TOOLS') /* Control member file. */
|
||||
|
||||
DCL VAR(&MODLIB) TYPE(*CHAR) LEN(10) +
|
||||
VALUE('ZLIB') /* Module library. */
|
||||
|
||||
DCL VAR(&SRVLIB) TYPE(*CHAR) LEN(10) +
|
||||
VALUE('LGPL') /* Service program library. */
|
||||
|
||||
DCL VAR(&CFLAGS) TYPE(*CHAR) +
|
||||
VALUE('OPTIMIZE(40)') /* Compile options. */
|
||||
|
||||
|
||||
/* Working storage. */
|
||||
|
||||
DCL VAR(&CMDLEN) TYPE(*DEC) LEN(15 5) VALUE(300) /* Command length. */
|
||||
DCL VAR(&CMD) TYPE(*CHAR) LEN(512)
|
||||
|
||||
|
||||
/* Compile sources into modules. */
|
||||
|
||||
CHGVAR VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT +
|
||||
'/ADLER32) SRCFILE(' *TCAT +
|
||||
&SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT +
|
||||
') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
|
||||
CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
|
||||
|
||||
CHGVAR VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT +
|
||||
'/COMPRESS) SRCFILE(' *TCAT +
|
||||
&SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT +
|
||||
') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
|
||||
CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
|
||||
|
||||
CHGVAR VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT +
|
||||
'/CRC32) SRCFILE(' *TCAT +
|
||||
&SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT +
|
||||
') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
|
||||
CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
|
||||
|
||||
CHGVAR VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT +
|
||||
'/DEFLATE) SRCFILE(' *TCAT +
|
||||
&SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT +
|
||||
') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
|
||||
CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
|
||||
|
||||
CHGVAR VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT +
|
||||
'/GZIO) SRCFILE(' *TCAT +
|
||||
&SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT +
|
||||
') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
|
||||
CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
|
||||
|
||||
CHGVAR VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT +
|
||||
'/INFBACK) SRCFILE(' *TCAT +
|
||||
&SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT +
|
||||
') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
|
||||
CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
|
||||
|
||||
CHGVAR VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT +
|
||||
'/INFFAST) SRCFILE(' *TCAT +
|
||||
&SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT +
|
||||
') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
|
||||
CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
|
||||
|
||||
CHGVAR VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT +
|
||||
'/INFLATE) SRCFILE(' *TCAT +
|
||||
&SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT +
|
||||
') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
|
||||
CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
|
||||
|
||||
CHGVAR VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT +
|
||||
'/INFTREES) SRCFILE(' *TCAT +
|
||||
&SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT +
|
||||
') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
|
||||
CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
|
||||
|
||||
CHGVAR VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT +
|
||||
'/TREES) SRCFILE(' *TCAT +
|
||||
&SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT +
|
||||
') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
|
||||
CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
|
||||
|
||||
CHGVAR VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT +
|
||||
'/UNCOMPR) SRCFILE(' *TCAT +
|
||||
&SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT +
|
||||
') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
|
||||
CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
|
||||
|
||||
CHGVAR VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT +
|
||||
'/ZUTIL) SRCFILE(' *TCAT +
|
||||
&SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT +
|
||||
') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
|
||||
CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
|
||||
|
||||
|
||||
/* Link modules into a service program. */
|
||||
|
||||
CRTSRVPGM SRVPGM(&SRVLIB/ZLIB) +
|
||||
MODULE(&MODLIB/ADLER32 &MODLIB/COMPRESS +
|
||||
&MODLIB/CRC32 &MODLIB/DEFLATE +
|
||||
&MODLIB/GZIO &MODLIB/INFBACK +
|
||||
&MODLIB/INFFAST &MODLIB/INFLATE +
|
||||
&MODLIB/INFTREES &MODLIB/TREES +
|
||||
&MODLIB/UNCOMPR &MODLIB/ZUTIL) +
|
||||
SRCFILE(&SRCLIB/&CTLFILE) SRCMBR(BNDSRC) +
|
||||
TEXT('ZLIB 1.2.1') TGTRLS(V4R4M0)
|
||||
|
||||
ENDPGM
|
111
zlib/as400/readme.txt
Normal file
111
zlib/as400/readme.txt
Normal file
|
@ -0,0 +1,111 @@
|
|||
ZLIB version 1.2.1 for AS400 installation instructions
|
||||
|
||||
I) From an AS400 *SAVF file:
|
||||
|
||||
1) Unpacking archive to an AS400 save file
|
||||
|
||||
On the AS400:
|
||||
|
||||
_ Create the ZLIB AS400 library:
|
||||
|
||||
CRTLIB LIB(ZLIB) TYPE(PROD) TEXT('ZLIB compression API library')
|
||||
|
||||
_ Create a work save file, for example:
|
||||
|
||||
CRTSAVF FILE(ZLIB/ZLIBSAVF)
|
||||
|
||||
On a PC connected to the target AS400:
|
||||
|
||||
_ Unpack the save file image to a PC file "ZLIBSAVF"
|
||||
_ Upload this file into the save file on the AS400, for example
|
||||
using ftp in BINARY mode.
|
||||
|
||||
|
||||
2) Populating the ZLIB AS400 source library
|
||||
|
||||
On the AS400:
|
||||
|
||||
_ Extract the saved objects into the ZLIB AS400 library using:
|
||||
|
||||
RSTOBJ OBJ(*ALL) SAVLIB(ZLIB) DEV(*SAVF) SAVF(ZLIB/ZLIBSAVF) RSTLIB(ZLIB)
|
||||
|
||||
|
||||
3) Customize installation:
|
||||
|
||||
_ Edit CL member ZLIB/TOOLS(COMPILE) and change parameters if needed,
|
||||
according to the comments.
|
||||
|
||||
_ Compile this member with:
|
||||
|
||||
CRTCLPGM PGM(ZLIB/COMPILE) SRCFILE(ZLIB/TOOLS) SRCMBR(COMPILE)
|
||||
|
||||
|
||||
4) Compile and generate the service program:
|
||||
|
||||
_ This can now be done by executing:
|
||||
|
||||
CALL PGM(ZLIB/COMPILE)
|
||||
|
||||
|
||||
|
||||
II) From the original source distribution:
|
||||
|
||||
1) On the AS400, create the source library:
|
||||
|
||||
CRTLIB LIB(ZLIB) TYPE(PROD) TEXT('ZLIB compression API library')
|
||||
|
||||
2) Create the source files:
|
||||
|
||||
CRTSRCPF FILE(ZLIB/SOURCES) RCDLEN(112) TEXT('ZLIB library modules')
|
||||
CRTSRCPF FILE(ZLIB/H) RCDLEN(112) TEXT('ZLIB library includes')
|
||||
CRTSRCPF FILE(ZLIB/TOOLS) RCDLEN(112) TEXT('ZLIB library control utilities')
|
||||
|
||||
3) From the machine hosting the distribution files, upload them (with
|
||||
FTP in text mode, for example) according to the following table:
|
||||
|
||||
Original AS400 AS400 AS400 AS400
|
||||
file file member type description
|
||||
SOURCES Original ZLIB C subprogram sources
|
||||
adler32.c ADLER32 C ZLIB - Compute the Adler-32 checksum of a dta strm
|
||||
compress.c COMPRESS C ZLIB - Compress a memory buffer
|
||||
crc32.c CRC32 C ZLIB - Compute the CRC-32 of a data stream
|
||||
deflate.c DEFLATE C ZLIB - Compress data using the deflation algorithm
|
||||
gzio.c GZIO C ZLIB - IO on .gz files
|
||||
infback.c INFBACK C ZLIB - Inflate using a callback interface
|
||||
inffast.c INFFAST C ZLIB - Fast proc. literals & length/distance pairs
|
||||
inflate.c INFLATE C ZLIB - Interface to inflate modules
|
||||
inftrees.c INFTREES C ZLIB - Generate Huffman trees for efficient decode
|
||||
trees.c TREES C ZLIB - Output deflated data using Huffman coding
|
||||
uncompr.c UNCOMPR C ZLIB - Decompress a memory buffer
|
||||
zutil.c ZUTIL C ZLIB - Target dependent utility functions
|
||||
H Original ZLIB C and ILE/RPG include files
|
||||
crc32.h CRC32 C ZLIB - CRC32 tables
|
||||
deflate.h DEFLATE C ZLIB - Internal compression state
|
||||
inffast.h INFFAST C ZLIB - Header to use inffast.c
|
||||
inffixed.h INFFIXED C ZLIB - Table for decoding fixed codes
|
||||
inflate.h INFLATE C ZLIB - Internal inflate state definitions
|
||||
inftrees.h INFTREES C ZLIB - Header to use inftrees.c
|
||||
trees.h TREES C ZLIB - Created automatically with -DGEN_TREES_H
|
||||
zconf.h ZCONF C ZLIB - Compression library configuration
|
||||
zlib.h ZLIB C ZLIB - Compression library C user interface
|
||||
as400/zlib.inc ZLIB.INC RPGLE ZLIB - Compression library ILE RPG user interface
|
||||
zutil.h ZUTIL C ZLIB - Internal interface and configuration
|
||||
TOOLS Building source software & AS/400 README
|
||||
as400/bndsrc BNDSRC Entry point exportation list
|
||||
as400/compile.clp COMPILE CLP Compile sources & generate service program
|
||||
as400/readme.txt README TXT Installation instructions
|
||||
|
||||
4) Continue as in I)3).
|
||||
|
||||
|
||||
|
||||
|
||||
Notes: For AS400 ILE RPG programmers, a /copy member defining the ZLIB
|
||||
API prototypes for ILE RPG can be found in ZLIB/H(ZLIB.INC).
|
||||
Please read comments in this member for more information.
|
||||
|
||||
Remember that most foreign textual data are ASCII coded: this
|
||||
implementation does not handle conversion from/to ASCII, so
|
||||
text data code conversions must be done explicitely.
|
||||
|
||||
Always open zipped files in binary mode.
|
327
zlib/as400/zlib.inc
Normal file
327
zlib/as400/zlib.inc
Normal file
|
@ -0,0 +1,327 @@
|
|||
* ZLIB.INC - Interface to the general purpose compression library
|
||||
*
|
||||
* ILE RPG400 version by Patrick Monnerat, DATASPHERE.
|
||||
* Version 1.2.1
|
||||
*
|
||||
*
|
||||
* WARNING:
|
||||
* Procedures inflateInit(), inflateInit2(), deflateInit(),
|
||||
* deflateInit2() and inflateBackInit() need to be called with
|
||||
* two additional arguments:
|
||||
* the package version string and the stream control structure.
|
||||
* size. This is needed because RPG lacks some macro feature.
|
||||
* Call these procedures as:
|
||||
* inflateInit(...: ZLIB_VERSION: %size(z_stream))
|
||||
*
|
||||
/if not defined(ZLIB_H_)
|
||||
/define ZLIB_H_
|
||||
*
|
||||
**************************************************************************
|
||||
* Constants
|
||||
**************************************************************************
|
||||
*
|
||||
D ZLIB_VERSION C '1.2.1' Header's version
|
||||
D ZLIB_VERNUM C X'1210'
|
||||
*
|
||||
D Z_NO_FLUSH C 0
|
||||
D Z_SYNC_FLUSH C 2
|
||||
D Z_FULL_FLUSH C 3
|
||||
D Z_FINISH C 4
|
||||
D Z_BLOCK C 5
|
||||
*
|
||||
D Z_OK C 0
|
||||
D Z_STREAM_END C 1
|
||||
D Z_NEED_DICT C 2
|
||||
D Z_ERRNO C -1
|
||||
D Z_STREAM_ERROR C -2
|
||||
D Z_DATA_ERROR C -3
|
||||
D Z_MEM_ERROR C -4
|
||||
D Z_BUF_ERROR C -5
|
||||
DZ_VERSION_ERROR C -6
|
||||
*
|
||||
D Z_NO_COMPRESSION...
|
||||
D C 0
|
||||
D Z_BEST_SPEED C 1
|
||||
D Z_BEST_COMPRESSION...
|
||||
D C 9
|
||||
D Z_DEFAULT_COMPRESSION...
|
||||
D C -1
|
||||
*
|
||||
D Z_FILTERED C 1
|
||||
D Z_HUFFMAN_ONLY C 2
|
||||
D Z_RLE C 3
|
||||
D Z_DEFAULT_STRATEGY...
|
||||
D C 0
|
||||
*
|
||||
D Z_BINARY C 0
|
||||
D Z_ASCII C 1
|
||||
D Z_UNKNOWN C 2
|
||||
*
|
||||
D Z_DEFLATED C 8
|
||||
*
|
||||
D Z_NULL C 0
|
||||
*
|
||||
**************************************************************************
|
||||
* Types
|
||||
**************************************************************************
|
||||
*
|
||||
D z_streamp S * Stream struct ptr
|
||||
D gzFile S * File pointer
|
||||
D z_off_t S 10i 0 Stream offsets
|
||||
*
|
||||
**************************************************************************
|
||||
* Structures
|
||||
**************************************************************************
|
||||
*
|
||||
* The GZIP encode/decode stream support structure.
|
||||
*
|
||||
D z_stream DS align based(z_streamp)
|
||||
D zs_next_in * Next input byte
|
||||
D zs_avail_in 10U 0 Byte cnt at next_in
|
||||
D zs_total_in 10U 0 Total bytes read
|
||||
D zs_next_out * Output buffer ptr
|
||||
D zs_avail_out 10U 0 Room left @ next_out
|
||||
D zs_total_out 10U 0 Total bytes written
|
||||
D zs_msg * Last errmsg or null
|
||||
D zs_state * Internal state
|
||||
D zs_zalloc * procptr Int. state allocator
|
||||
D zs_free * procptr Int. state dealloc.
|
||||
D zs_opaque * Private alloc. data
|
||||
D zs_data_type 10i 0 ASC/BIN best guess
|
||||
D zs_adler 10u 0 Uncompr. adler32 val
|
||||
D 10U 0 Reserved
|
||||
D 10U 0 Ptr. alignment
|
||||
*
|
||||
**************************************************************************
|
||||
* Utility function prototypes
|
||||
**************************************************************************
|
||||
*
|
||||
D compress PR 10I 0 extproc('compress')
|
||||
D dest 32767 options(*varsize) Destination buffer
|
||||
D destLen 10U 0 Destination length
|
||||
D source 32767 const options(*varsize) Source buffer
|
||||
D sourceLen 10u 0 value Source length
|
||||
*
|
||||
D compress2 PR 10I 0 extproc('compress2')
|
||||
D dest 32767 options(*varsize) Destination buffer
|
||||
D destLen 10U 0 Destination length
|
||||
D source 32767 const options(*varsize) Source buffer
|
||||
D sourceLen 10U 0 value Source length
|
||||
D level 10I 0 value Compression level
|
||||
*
|
||||
D compressBound PR 10U 0 extproc('compressBound')
|
||||
D sourceLen 10U 0 value
|
||||
*
|
||||
D uncompress PR 10I 0 extproc('uncompress')
|
||||
D dest 32767 options(*varsize) Destination buffer
|
||||
D destLen 10U 0 Destination length
|
||||
D source 32767 const options(*varsize) Source buffer
|
||||
D sourceLen 10U 0 value Source length
|
||||
*
|
||||
D gzopen PR extproc('gzopen')
|
||||
D like(gzFile)
|
||||
D path * value options(*string) File pathname
|
||||
D mode * value options(*string) Open mode
|
||||
*
|
||||
D gzdopen PR extproc('gzdopen')
|
||||
D like(gzFile)
|
||||
D fd 10i 0 value File descriptor
|
||||
D mode * value options(*string) Open mode
|
||||
*
|
||||
D gzsetparams PR 10I 0 extproc('gzsetparams')
|
||||
D file value like(gzFile) File pointer
|
||||
D level 10I 0 value
|
||||
D strategy 10i 0 value
|
||||
*
|
||||
D gzread PR 10I 0 extproc('gzread')
|
||||
D file value like(gzFile) File pointer
|
||||
D buf 32767 options(*varsize) Buffer
|
||||
D len 10u 0 value Buffer length
|
||||
*
|
||||
D gzwrite PR 10I 0 extproc('gzwrite')
|
||||
D file value like(gzFile) File pointer
|
||||
D buf 32767 const options(*varsize) Buffer
|
||||
D len 10u 0 value Buffer length
|
||||
*
|
||||
D gzputs PR 10I 0 extproc('gzputs')
|
||||
D file value like(gzFile) File pointer
|
||||
D s * value options(*string) String to output
|
||||
*
|
||||
D gzgets PR * extproc('gzgets')
|
||||
D file value like(gzFile) File pointer
|
||||
D buf 32767 options(*varsize) Read buffer
|
||||
D len 10i 0 value Buffer length
|
||||
*
|
||||
D gzflush PR 10i 0 extproc('gzflush')
|
||||
D file value like(gzFile) File pointer
|
||||
D flush 10I 0 value Type of flush
|
||||
*
|
||||
D gzseek PR extproc('gzseek')
|
||||
D like(z_off_t)
|
||||
D file value like(gzFile) File pointer
|
||||
D offset value like(z_off_t) Offset
|
||||
D whence 10i 0 value Origin
|
||||
*
|
||||
D gzrewind PR 10i 0 extproc('gzrewind')
|
||||
D file value like(gzFile) File pointer
|
||||
*
|
||||
D gztell PR extproc('gztell')
|
||||
D like(z_off_t)
|
||||
D file value like(gzFile) File pointer
|
||||
*
|
||||
D gzeof PR 10i 0 extproc('gzeof')
|
||||
D file value like(gzFile) File pointer
|
||||
*
|
||||
D gzclose PR 10i 0 extproc('gzclose')
|
||||
D file value like(gzFile) File pointer
|
||||
*
|
||||
D gzerror PR * extproc('gzerror') Error string
|
||||
D file value like(gzFile) File pointer
|
||||
D errnum 10I 0 Error code
|
||||
*
|
||||
D gzclearerr PR extproc('gzclearerr')
|
||||
D file value like(gzFile) File pointer
|
||||
*
|
||||
**************************************************************************
|
||||
* Basic function prototypes
|
||||
**************************************************************************
|
||||
*
|
||||
D zlibVersion PR * extproc('zlibVersion') Version string
|
||||
*
|
||||
D deflateInit PR 10I 0 extproc('deflateInit_') Init. compression
|
||||
D strm like(z_stream) Compression stream
|
||||
D level 10I 0 value Compression level
|
||||
D version * value options(*string) Version string
|
||||
D stream_size 10i 0 value Stream struct. size
|
||||
*
|
||||
D deflate PR 10I 0 extproc('deflate') Compress data
|
||||
D strm like(z_stream) Compression stream
|
||||
D flush 10I 0 value Flush type required
|
||||
*
|
||||
D deflateEnd PR 10I 0 extproc('deflateEnd') Termin. compression
|
||||
D strm like(z_stream) Compression stream
|
||||
*
|
||||
D inflateInit PR 10I 0 extproc('inflateInit_') Init. expansion
|
||||
D strm like(z_stream) Expansion stream
|
||||
D version * value options(*string) Version string
|
||||
D stream_size 10i 0 value Stream struct. size
|
||||
*
|
||||
D inflate PR 10I 0 extproc('inflate') Expand data
|
||||
D strm like(z_stream) Expansion stream
|
||||
D flush 10I 0 value Flush type required
|
||||
*
|
||||
D inflateEnd PR 10I 0 extproc('inflateEnd') Termin. expansion
|
||||
D strm like(z_stream) Expansion stream
|
||||
*
|
||||
**************************************************************************
|
||||
* Advanced function prototypes
|
||||
**************************************************************************
|
||||
*
|
||||
D deflateInit2 PR 10I 0 extproc('deflateInit2_') Init. compression
|
||||
D strm like(z_stream) Compression stream
|
||||
D level 10I 0 value Compression level
|
||||
D method 10I 0 value Compression method
|
||||
D windowBits 10I 0 value log2(window size)
|
||||
D memLevel 10I 0 value Mem/cmpress tradeoff
|
||||
D strategy 10I 0 value Compression stategy
|
||||
D version * value options(*string) Version string
|
||||
D stream_size 10i 0 value Stream struct. size
|
||||
*
|
||||
D deflateSetDictionary...
|
||||
D PR 10I 0 extproc('deflateSetDictionary') Init. dictionary
|
||||
D strm like(z_stream) Compression stream
|
||||
D dictionary 32767 const options(*varsize) Dictionary bytes
|
||||
D dictLength 10U 0 value Dictionary length
|
||||
*
|
||||
D deflateCopy PR 10I 0 extproc('deflateCopy') Compress strm 2 strm
|
||||
D dest like(z_stream) Destination stream
|
||||
D source like(z_stream) Source stream
|
||||
*
|
||||
D deflateReset PR 10I 0 extproc('deflateReset') End and init. stream
|
||||
D strm like(z_stream) Compression stream
|
||||
*
|
||||
D deflateParams PR 10I 0 extproc('deflateParams') Change level & strat
|
||||
D strm like(z_stream) Compression stream
|
||||
D level 10I 0 value Compression level
|
||||
D strategy 10I 0 value Compression stategy
|
||||
*
|
||||
D deflateBound PR 10U 0 extproc('deflateBound') Change level & strat
|
||||
D strm like(z_stream) Compression stream
|
||||
D sourcelen 10U 0 value Compression level
|
||||
*
|
||||
D deflatePrime PR 10I 0 extproc('deflatePrime') Change level & strat
|
||||
D strm like(z_stream) Compression stream
|
||||
D bits 10I 0 value Number of bits to insert
|
||||
D value 10I 0 value Bits to insert
|
||||
*
|
||||
D inflateInit2 PR 10I 0 extproc('inflateInit2_') Init. expansion
|
||||
D strm like(z_stream) Expansion stream
|
||||
D windowBits 10I 0 value log2(window size)
|
||||
D version * value options(*string) Version string
|
||||
D stream_size 10i 0 value Stream struct. size
|
||||
*
|
||||
D inflateSetDictionary...
|
||||
D PR 10I 0 extproc('inflateSetDictionary') Init. dictionary
|
||||
D strm like(z_stream) Expansion stream
|
||||
D dictionary 32767 const options(*varsize) Dictionary bytes
|
||||
D dictLength 10U 0 value Dictionary length
|
||||
*
|
||||
D inflateSync PR 10I 0 extproc('inflateSync') Sync. expansion
|
||||
D strm like(z_stream) Expansion stream
|
||||
*
|
||||
D inflateCopy PR 10I 0 extproc('inflateCopy')
|
||||
D dest like(z_stream) Destination stream
|
||||
D source like(z_stream) Source stream
|
||||
*
|
||||
D inflateReset PR 10I 0 extproc('inflateReset') End and init. stream
|
||||
D strm like(z_stream) Expansion stream
|
||||
*
|
||||
D inflateBackInit...
|
||||
D PR 10I 0 extproc('inflateBackInit_')
|
||||
D strm like(z_stream) Expansion stream
|
||||
D windowBits 10I 0 value Log2(buffer size)
|
||||
D window 32767 options(*varsize) Buffer
|
||||
D version * value options(*string) Version string
|
||||
D stream_size 10i 0 value Stream struct. size
|
||||
*
|
||||
D inflateBack PR 10I 0 extproc('inflateBack')
|
||||
D strm like(z_stream) Expansion stream
|
||||
D in * value procptr Input function
|
||||
D in_desc * value Input descriptor
|
||||
D out * value procptr Output function
|
||||
D out_desc * value Output descriptor
|
||||
*
|
||||
D inflateBackEnd PR 10I 0 extproc('inflateBackEnd')
|
||||
D strm like(z_stream) Expansion stream
|
||||
*
|
||||
D zlibCompileFlags...
|
||||
D PR 10U 0 extproc('zlibCompileFlags')
|
||||
*
|
||||
**************************************************************************
|
||||
* Checksum function prototypes
|
||||
**************************************************************************
|
||||
*
|
||||
D adler32 PR 10U 0 extproc('adler32') New checksum
|
||||
D adler 10U 0 value Old checksum
|
||||
D buf 32767 const options(*varsize) Bytes to accumulate
|
||||
D len 10U 0 value Buffer length
|
||||
*
|
||||
D crc32 PR 10U 0 extproc('crc32') New checksum
|
||||
D crc 10U 0 value Old checksum
|
||||
D buf 32767 const options(*varsize) Bytes to accumulate
|
||||
D len 10U 0 value Buffer length
|
||||
*
|
||||
**************************************************************************
|
||||
* Miscellaneous function prototypes
|
||||
**************************************************************************
|
||||
*
|
||||
D zError PR * extproc('zError') Error string
|
||||
D err 10I 0 value Error code
|
||||
*
|
||||
D inflateSyncPoint...
|
||||
D PR 10I 0 extproc('inflateSyncPoint')
|
||||
D strm like(z_stream) Expansion stream
|
||||
*
|
||||
D get_crc_table PR * extproc('get_crc_table') Ptr to ulongs
|
||||
*
|
||||
/endif
|
79
zlib/compress.c
Normal file
79
zlib/compress.c
Normal file
|
@ -0,0 +1,79 @@
|
|||
/* compress.c -- compress a memory buffer
|
||||
* Copyright (C) 1995-2002 Jean-loup Gailly.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#define ZLIB_INTERNAL
|
||||
#include "zlib.h"
|
||||
|
||||
/* ===========================================================================
|
||||
Compresses the source buffer into the destination buffer. The level
|
||||
parameter has the same meaning as in deflateInit. sourceLen is the byte
|
||||
length of the source buffer. Upon entry, destLen is the total size of the
|
||||
destination buffer, which must be at least 0.1% larger than sourceLen plus
|
||||
12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
|
||||
|
||||
compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
|
||||
memory, Z_BUF_ERROR if there was not enough room in the output buffer,
|
||||
Z_STREAM_ERROR if the level parameter is invalid.
|
||||
*/
|
||||
int ZEXPORT compress2 (dest, destLen, source, sourceLen, level)
|
||||
Bytef *dest;
|
||||
uLongf *destLen;
|
||||
const Bytef *source;
|
||||
uLong sourceLen;
|
||||
int level;
|
||||
{
|
||||
z_stream stream;
|
||||
int err;
|
||||
|
||||
stream.next_in = (Bytef*)source;
|
||||
stream.avail_in = (uInt)sourceLen;
|
||||
#ifdef MAXSEG_64K
|
||||
/* Check for source > 64K on 16-bit machine: */
|
||||
if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
|
||||
#endif
|
||||
stream.next_out = dest;
|
||||
stream.avail_out = (uInt)*destLen;
|
||||
if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
|
||||
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
stream.opaque = (voidpf)0;
|
||||
|
||||
err = deflateInit(&stream, level);
|
||||
if (err != Z_OK) return err;
|
||||
|
||||
err = deflate(&stream, Z_FINISH);
|
||||
if (err != Z_STREAM_END) {
|
||||
deflateEnd(&stream);
|
||||
return err == Z_OK ? Z_BUF_ERROR : err;
|
||||
}
|
||||
*destLen = stream.total_out;
|
||||
|
||||
err = deflateEnd(&stream);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
*/
|
||||
int ZEXPORT compress (dest, destLen, source, sourceLen)
|
||||
Bytef *dest;
|
||||
uLongf *destLen;
|
||||
const Bytef *source;
|
||||
uLong sourceLen;
|
||||
{
|
||||
return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
If the default memLevel or windowBits for deflateInit() is changed, then
|
||||
this function needs to be updated.
|
||||
*/
|
||||
uLong ZEXPORT compressBound (sourceLen)
|
||||
uLong sourceLen;
|
||||
{
|
||||
return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11;
|
||||
}
|
445
zlib/configure
vendored
Normal file
445
zlib/configure
vendored
Normal file
|
@ -0,0 +1,445 @@
|
|||
#!/bin/sh
|
||||
# configure script for zlib. This script is needed only if
|
||||
# you wish to build a shared library and your system supports them,
|
||||
# of if you need special compiler, flags or install directory.
|
||||
# Otherwise, you can just use directly "make test; make install"
|
||||
#
|
||||
# To create a shared library, use "configure --shared"; by default a static
|
||||
# library is created. If the primitive shared library support provided here
|
||||
# does not work, use ftp://prep.ai.mit.edu/pub/gnu/libtool-*.tar.gz
|
||||
#
|
||||
# To impose specific compiler or flags or install directory, use for example:
|
||||
# prefix=$HOME CC=cc CFLAGS="-O4" ./configure
|
||||
# or for csh/tcsh users:
|
||||
# (setenv prefix $HOME; setenv CC cc; setenv CFLAGS "-O4"; ./configure)
|
||||
# LDSHARED is the command to be used to create a shared library
|
||||
|
||||
# Incorrect settings of CC or CFLAGS may prevent creating a shared library.
|
||||
# If you have problems, try without defining CC and CFLAGS before reporting
|
||||
# an error.
|
||||
|
||||
LIBS=libz.a
|
||||
LDFLAGS="-L. ${LIBS}"
|
||||
VER=`sed -n -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`
|
||||
VER2=`sed -n -e '/VERSION "/s/.*"\([0-9]*\\.[0-9]*\)\\..*/\1/p' < zlib.h`
|
||||
VER1=`sed -n -e '/VERSION "/s/.*"\([0-9]*\)\\..*/\1/p' < zlib.h`
|
||||
AR=${AR-"ar rc"}
|
||||
RANLIB=${RANLIB-"ranlib"}
|
||||
prefix=${prefix-/usr/local}
|
||||
exec_prefix=${exec_prefix-'${prefix}'}
|
||||
libdir=${libdir-'${exec_prefix}/lib'}
|
||||
includedir=${includedir-'${prefix}/include'}
|
||||
mandir=${mandir-'${prefix}/share/man'}
|
||||
shared_ext='.so'
|
||||
shared=0
|
||||
gcc=0
|
||||
old_cc="$CC"
|
||||
old_cflags="$CFLAGS"
|
||||
|
||||
while test $# -ge 1
|
||||
do
|
||||
case "$1" in
|
||||
-h* | --h*)
|
||||
echo 'usage:'
|
||||
echo ' configure [--shared] [--prefix=PREFIX] [--exec_prefix=EXPREFIX]'
|
||||
echo ' [--libdir=LIBDIR] [--includedir=INCLUDEDIR]'
|
||||
exit 0;;
|
||||
-p*=* | --p*=*) prefix=`echo $1 | sed 's/[-a-z_]*=//'`; shift;;
|
||||
-e*=* | --e*=*) exec_prefix=`echo $1 | sed 's/[-a-z_]*=//'`; shift;;
|
||||
-l*=* | --libdir=*) libdir=`echo $1 | sed 's/[-a-z_]*=//'`; shift;;
|
||||
-i*=* | --includedir=*) includedir=`echo $1 | sed 's/[-a-z_]*=//'`;shift;;
|
||||
-p* | --p*) prefix="$2"; shift; shift;;
|
||||
-e* | --e*) exec_prefix="$2"; shift; shift;;
|
||||
-l* | --l*) libdir="$2"; shift; shift;;
|
||||
-i* | --i*) includedir="$2"; shift; shift;;
|
||||
-s* | --s*) shared=1; shift;;
|
||||
*) echo "unknown option: $1"; echo "$0 --help for help"; exit 1;;
|
||||
esac
|
||||
done
|
||||
|
||||
test=ztest$$
|
||||
cat > $test.c <<EOF
|
||||
extern int getchar();
|
||||
int hello() {return getchar();}
|
||||
EOF
|
||||
|
||||
test -z "$CC" && echo Checking for gcc...
|
||||
cc=${CC-gcc}
|
||||
cflags=${CFLAGS-"-O3"}
|
||||
# to force the asm version use: CFLAGS="-O3 -DASMV" ./configure
|
||||
case "$cc" in
|
||||
*gcc*) gcc=1;;
|
||||
esac
|
||||
|
||||
if test "$gcc" -eq 1 && ($cc -c $cflags $test.c) 2>/dev/null; then
|
||||
CC="$cc"
|
||||
SFLAGS=${CFLAGS-"-fPIC -O3"}
|
||||
CFLAGS="$cflags"
|
||||
case `(uname -s || echo unknown) 2>/dev/null` in
|
||||
Linux | linux | GNU | GNU/*) LDSHARED=${LDSHARED-"$cc -shared -Wl,-soname,libz.so.1"};;
|
||||
CYGWIN* | Cygwin* | cygwin* )
|
||||
EXE='.exe';;
|
||||
QNX*) # This is for QNX6. I suppose that the QNX rule below is for QNX2,QNX4
|
||||
# (alain.bonnefoy@icbt.com)
|
||||
LDSHARED=${LDSHARED-"$cc -shared -Wl,-hlibz.so.1"};;
|
||||
HP-UX*) LDSHARED=${LDSHARED-"$cc -shared $SFLAGS"}
|
||||
shared_ext='.sl'
|
||||
SHAREDLIB='libz.sl';;
|
||||
Darwin*) shared_ext='.dylib'
|
||||
SHAREDLIB=libz$shared_ext
|
||||
SHAREDLIBV=libz.$VER$shared_ext
|
||||
SHAREDLIBM=libz.$VER1$shared_ext
|
||||
LDSHARED=${LDSHARED-"$cc -dynamiclib -install_name /usr/lib/$SHAREDLIBV -compatibility_version $VER2 -current_version $VER"}
|
||||
libdir='/usr/lib'
|
||||
includedir='/usr/include';;
|
||||
*) LDSHARED=${LDSHARED-"$cc -shared"};;
|
||||
esac
|
||||
else
|
||||
# find system name and corresponding cc options
|
||||
CC=${CC-cc}
|
||||
case `(uname -sr || echo unknown) 2>/dev/null` in
|
||||
HP-UX*) SFLAGS=${CFLAGS-"-O +z"}
|
||||
CFLAGS=${CFLAGS-"-O"}
|
||||
# LDSHARED=${LDSHARED-"ld -b +vnocompatwarnings"}
|
||||
LDSHARED=${LDSHARED-"ld -b"}
|
||||
shared_ext='.sl'
|
||||
SHAREDLIB='libz.sl';;
|
||||
IRIX*) SFLAGS=${CFLAGS-"-ansi -O2 -rpath ."}
|
||||
CFLAGS=${CFLAGS-"-ansi -O2"}
|
||||
LDSHARED=${LDSHARED-"cc -shared"};;
|
||||
OSF1\ V4*) SFLAGS=${CFLAGS-"-O -std1"}
|
||||
CFLAGS=${CFLAGS-"-O -std1"}
|
||||
LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so -Wl,-msym -Wl,-rpath,$(libdir) -Wl,-set_version,${VER}:1.0"};;
|
||||
OSF1*) SFLAGS=${CFLAGS-"-O -std1"}
|
||||
CFLAGS=${CFLAGS-"-O -std1"}
|
||||
LDSHARED=${LDSHARED-"cc -shared"};;
|
||||
QNX*) SFLAGS=${CFLAGS-"-4 -O"}
|
||||
CFLAGS=${CFLAGS-"-4 -O"}
|
||||
LDSHARED=${LDSHARED-"cc"}
|
||||
RANLIB=${RANLIB-"true"}
|
||||
AR="cc -A";;
|
||||
SCO_SV\ 3.2*) SFLAGS=${CFLAGS-"-O3 -dy -KPIC "}
|
||||
CFLAGS=${CFLAGS-"-O3"}
|
||||
LDSHARED=${LDSHARED-"cc -dy -KPIC -G"};;
|
||||
SunOS\ 5*) SFLAGS=${CFLAGS-"-fast -xcg89 -KPIC -R."}
|
||||
CFLAGS=${CFLAGS-"-fast -xcg89"}
|
||||
LDSHARED=${LDSHARED-"cc -G"};;
|
||||
SunOS\ 4*) SFLAGS=${CFLAGS-"-O2 -PIC"}
|
||||
CFLAGS=${CFLAGS-"-O2"}
|
||||
LDSHARED=${LDSHARED-"ld"};;
|
||||
UNIX_System_V\ 4.2.0)
|
||||
SFLAGS=${CFLAGS-"-KPIC -O"}
|
||||
CFLAGS=${CFLAGS-"-O"}
|
||||
LDSHARED=${LDSHARED-"cc -G"};;
|
||||
UNIX_SV\ 4.2MP)
|
||||
SFLAGS=${CFLAGS-"-Kconform_pic -O"}
|
||||
CFLAGS=${CFLAGS-"-O"}
|
||||
LDSHARED=${LDSHARED-"cc -G"};;
|
||||
OpenUNIX\ 5)
|
||||
SFLAGS=${CFLAGS-"-KPIC -O"}
|
||||
CFLAGS=${CFLAGS-"-O"}
|
||||
LDSHARED=${LDSHARED-"cc -G"};;
|
||||
AIX*) # Courtesy of dbakker@arrayasolutions.com
|
||||
SFLAGS=${CFLAGS-"-O -qmaxmem=8192"}
|
||||
CFLAGS=${CFLAGS-"-O -qmaxmem=8192"}
|
||||
LDSHARED=${LDSHARED-"xlc -G"};;
|
||||
# send working options for other systems to support@gzip.org
|
||||
*) SFLAGS=${CFLAGS-"-O"}
|
||||
CFLAGS=${CFLAGS-"-O"}
|
||||
LDSHARED=${LDSHARED-"cc -shared"};;
|
||||
esac
|
||||
fi
|
||||
|
||||
SHAREDLIB=${SHAREDLIB-"libz$shared_ext"}
|
||||
SHAREDLIBV=${SHAREDLIBV-"libz$shared_ext.$VER"}
|
||||
SHAREDLIBM=${SHAREDLIBM-"libz$shared_ext.$VER1"}
|
||||
|
||||
if test $shared -eq 1; then
|
||||
echo Checking for shared library support...
|
||||
# we must test in two steps (cc then ld), required at least on SunOS 4.x
|
||||
if test "`($CC -c $SFLAGS $test.c) 2>&1`" = "" &&
|
||||
test "`($LDSHARED -o $test$shared_ext $test.o) 2>&1`" = ""; then
|
||||
CFLAGS="$SFLAGS"
|
||||
LIBS="$SHAREDLIBV"
|
||||
echo Building shared library $SHAREDLIBV with $CC.
|
||||
elif test -z "$old_cc" -a -z "$old_cflags"; then
|
||||
echo No shared library support.
|
||||
shared=0;
|
||||
else
|
||||
echo 'No shared library support; try without defining CC and CFLAGS'
|
||||
shared=0;
|
||||
fi
|
||||
fi
|
||||
if test $shared -eq 0; then
|
||||
LDSHARED="$CC"
|
||||
echo Building static library $LIBS version $VER with $CC.
|
||||
else
|
||||
LDFLAGS="-L. ${SHAREDLIBV}"
|
||||
fi
|
||||
|
||||
cat > $test.c <<EOF
|
||||
#include <unistd.h>
|
||||
int main() { return 0; }
|
||||
EOF
|
||||
if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
|
||||
sed < zconf.in.h "/HAVE_UNISTD_H/s%0%1%" > zconf.h
|
||||
echo "Checking for unistd.h... Yes."
|
||||
else
|
||||
cp -p zconf.in.h zconf.h
|
||||
echo "Checking for unistd.h... No."
|
||||
fi
|
||||
|
||||
cat > $test.c <<EOF
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include "zconf.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifndef STDC
|
||||
choke me
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
|
||||
if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
|
||||
echo "Checking whether to use vs[n]printf() or s[n]printf()... using vs[n]printf()"
|
||||
|
||||
cat > $test.c <<EOF
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
int mytest(char *fmt, ...)
|
||||
{
|
||||
char buf[20];
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
return (mytest("Hello%d\n", 1));
|
||||
}
|
||||
EOF
|
||||
|
||||
if test "`($CC $CFLAGS -o $test $test.c) 2>&1`" = ""; then
|
||||
echo "Checking for vsnprintf() in stdio.h... Yes."
|
||||
|
||||
cat >$test.c <<EOF
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
int mytest(char *fmt, ...)
|
||||
{
|
||||
int n;
|
||||
char buf[20];
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
n = vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
return n;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
return (mytest("Hello%d\n", 1));
|
||||
}
|
||||
EOF
|
||||
|
||||
if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
|
||||
echo "Checking for return value of vsnprintf()... Yes."
|
||||
else
|
||||
CFLAGS="$CFLAGS -DHAS_vsnprintf_void"
|
||||
echo "Checking for return value of vsnprintf()... No."
|
||||
echo " WARNING: apparently vsnprintf() does not return a value. zlib"
|
||||
echo " can build but will be open to possible string-format security"
|
||||
echo " vulnerabilities."
|
||||
fi
|
||||
else
|
||||
CFLAGS="$CFLAGS -DNO_vsnprintf"
|
||||
echo "Checking for vsnprintf() in stdio.h... No."
|
||||
echo " WARNING: vsnprintf() not found, falling back to vsprintf(). zlib"
|
||||
echo " can build but will be open to possible buffer-overflow security"
|
||||
echo " vulnerabilities."
|
||||
|
||||
cat >$test.c <<EOF
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
int mytest(char *fmt, ...)
|
||||
{
|
||||
int n;
|
||||
char buf[20];
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
n = vsprintf(buf, fmt, ap);
|
||||
va_end(ap);
|
||||
return n;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
return (mytest("Hello%d\n", 1));
|
||||
}
|
||||
EOF
|
||||
|
||||
if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
|
||||
echo "Checking for return value of vsprintf()... Yes."
|
||||
else
|
||||
CFLAGS="$CFLAGS -DHAS_vsprintf_void"
|
||||
echo "Checking for return value of vsprintf()... No."
|
||||
echo " WARNING: apparently vsprintf() does not return a value. zlib"
|
||||
echo " can build but will be open to possible string-format security"
|
||||
echo " vulnerabilities."
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "Checking whether to use vs[n]printf() or s[n]printf()... using s[n]printf()"
|
||||
|
||||
cat >$test.c <<EOF
|
||||
#include <stdio.h>
|
||||
|
||||
int mytest()
|
||||
{
|
||||
char buf[20];
|
||||
|
||||
snprintf(buf, sizeof(buf), "%s", "foo");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
return (mytest());
|
||||
}
|
||||
EOF
|
||||
|
||||
if test "`($CC $CFLAGS -o $test $test.c) 2>&1`" = ""; then
|
||||
echo "Checking for snprintf() in stdio.h... Yes."
|
||||
|
||||
cat >$test.c <<EOF
|
||||
#include <stdio.h>
|
||||
|
||||
int mytest()
|
||||
{
|
||||
char buf[20];
|
||||
|
||||
return snprintf(buf, sizeof(buf), "%s", "foo");
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
return (mytest());
|
||||
}
|
||||
EOF
|
||||
|
||||
if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
|
||||
echo "Checking for return value of snprintf()... Yes."
|
||||
else
|
||||
CFLAGS="$CFLAGS -DHAS_snprintf_void"
|
||||
echo "Checking for return value of snprintf()... No."
|
||||
echo " WARNING: apparently snprintf() does not return a value. zlib"
|
||||
echo " can build but will be open to possible string-format security"
|
||||
echo " vulnerabilities."
|
||||
fi
|
||||
else
|
||||
CFLAGS="$CFLAGS -DNO_snprintf"
|
||||
echo "Checking for snprintf() in stdio.h... No."
|
||||
echo " WARNING: snprintf() not found, falling back to sprintf(). zlib"
|
||||
echo " can build but will be open to possible buffer-overflow security"
|
||||
echo " vulnerabilities."
|
||||
|
||||
cat >$test.c <<EOF
|
||||
#include <stdio.h>
|
||||
|
||||
int mytest()
|
||||
{
|
||||
char buf[20];
|
||||
|
||||
return sprintf(buf, "%s", "foo");
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
return (mytest());
|
||||
}
|
||||
EOF
|
||||
|
||||
if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
|
||||
echo "Checking for return value of sprintf()... Yes."
|
||||
else
|
||||
CFLAGS="$CFLAGS -DHAS_sprintf_void"
|
||||
echo "Checking for return value of sprintf()... No."
|
||||
echo " WARNING: apparently sprintf() does not return a value. zlib"
|
||||
echo " can build but will be open to possible string-format security"
|
||||
echo " vulnerabilities."
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
cat >$test.c <<EOF
|
||||
#include <errno.h>
|
||||
int main() { return 0; }
|
||||
EOF
|
||||
if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
|
||||
echo "Checking for errno.h... Yes."
|
||||
else
|
||||
echo "Checking for errno.h... No."
|
||||
CFLAGS="$CFLAGS -DNO_ERRNO_H"
|
||||
fi
|
||||
|
||||
cat > $test.c <<EOF
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
caddr_t hello() {
|
||||
return mmap((caddr_t)0, (off_t)0, PROT_READ, MAP_SHARED, 0, (off_t)0);
|
||||
}
|
||||
EOF
|
||||
if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
|
||||
CFLAGS="$CFLAGS -DUSE_MMAP"
|
||||
echo Checking for mmap support... Yes.
|
||||
else
|
||||
echo Checking for mmap support... No.
|
||||
fi
|
||||
|
||||
CPP=${CPP-"$CC -E"}
|
||||
case $CFLAGS in
|
||||
*ASMV*)
|
||||
if test "`nm $test.o | grep _hello`" = ""; then
|
||||
CPP="$CPP -DNO_UNDERLINE"
|
||||
echo Checking for underline in external names... No.
|
||||
else
|
||||
echo Checking for underline in external names... Yes.
|
||||
fi;;
|
||||
esac
|
||||
|
||||
rm -f $test.[co] $test $test$shared_ext
|
||||
|
||||
# udpate Makefile
|
||||
sed < Makefile.in "
|
||||
/^CC *=/s#=.*#=$CC#
|
||||
/^CFLAGS *=/s#=.*#=$CFLAGS#
|
||||
/^CPP *=/s#=.*#=$CPP#
|
||||
/^LDSHARED *=/s#=.*#=$LDSHARED#
|
||||
/^LIBS *=/s#=.*#=$LIBS#
|
||||
/^SHAREDLIB *=/s#=.*#=$SHAREDLIB#
|
||||
/^SHAREDLIBV *=/s#=.*#=$SHAREDLIBV#
|
||||
/^SHAREDLIBM *=/s#=.*#=$SHAREDLIBM#
|
||||
/^AR *=/s#=.*#=$AR#
|
||||
/^RANLIB *=/s#=.*#=$RANLIB#
|
||||
/^EXE *=/s#=.*#=$EXE#
|
||||
/^prefix *=/s#=.*#=$prefix#
|
||||
/^exec_prefix *=/s#=.*#=$exec_prefix#
|
||||
/^libdir *=/s#=.*#=$libdir#
|
||||
/^includedir *=/s#=.*#=$includedir#
|
||||
/^mandir *=/s#=.*#=$mandir#
|
||||
/^LDFLAGS *=/s#=.*#=$LDFLAGS#
|
||||
" > Makefile
|
70
zlib/contrib/README.contrib
Normal file
70
zlib/contrib/README.contrib
Normal file
|
@ -0,0 +1,70 @@
|
|||
All files under this contrib directory are UNSUPPORTED. There were
|
||||
provided by users of zlib and were not tested by the authors of zlib.
|
||||
Use at your own risk. Please contact the authors of the contributions
|
||||
for help about these, not the zlib authors. Thanks.
|
||||
|
||||
|
||||
ada/ by Dmitriy Anisimkov <anisimkov@yahoo.com>
|
||||
Support for Ada
|
||||
See http://zlib-ada.sourceforge.net/
|
||||
|
||||
asm586/
|
||||
asm686/ by Brian Raiter <breadbox@muppetlabs.com>
|
||||
asm code for Pentium and PPro/PII, using the AT&T (GNU as) syntax
|
||||
See http://www.muppetlabs.com/~breadbox/software/assembly.html
|
||||
|
||||
blast/ by Mark Adler <madler@alumni.caltech.edu>
|
||||
Decompressor for output of PKWare Data Compression Library (DCL)
|
||||
|
||||
delphi/ by Cosmin Truta <cosmint@cs.ubbcluj.ro>
|
||||
Support for Delphi and C++ Builder
|
||||
|
||||
gzappend/ by Mark Adler <madler@alumni.caltech.edu>
|
||||
append to a gzip file -- illustrates the use of Z_BLOCK
|
||||
|
||||
infback9/ by Mark Adler <madler@alumni.caltech.edu>
|
||||
Unsupported diffs to infback to decode the deflate64 format
|
||||
|
||||
inflate86/ by Chris Anderson <christop@charm.net>
|
||||
Tuned x86 gcc asm code to replace inflate_fast()
|
||||
|
||||
iostream/ by Kevin Ruland <kevin@rodin.wustl.edu>
|
||||
A C++ I/O streams interface to the zlib gz* functions
|
||||
|
||||
iostream2/ by Tyge Løvset <Tyge.Lovset@cmr.no>
|
||||
Another C++ I/O streams interface
|
||||
|
||||
iostream3/ by Ludwig Schwardt <schwardt@sun.ac.za>
|
||||
and Kevin Ruland <kevin@rodin.wustl.edu>
|
||||
Yet another C++ I/O streams interface
|
||||
|
||||
masm686/ by Dan Higdon <hdan@kinesoft.com>
|
||||
and Chuck Walbourn <chuckw@kinesoft.com>
|
||||
asm code for Pentium Pro/PII, using the MASM syntax
|
||||
|
||||
masmx86/ by Gilles Vollant <info@winimage.com>
|
||||
x86 asm code to replace longest_match() and inflate_fast(),
|
||||
for Visual C++ and MASM
|
||||
|
||||
minizip/ by Gilles Vollant <info@winimage.com>
|
||||
Mini zip and unzip based on zlib
|
||||
See http://www.winimage.com/zLibDll/unzip.html
|
||||
|
||||
pascal/ by Bob Dellaca <bobdl@xtra.co.nz> et al.
|
||||
Support for Pascal
|
||||
|
||||
puff/ by Mark Adler <madler@alumni.caltech.edu>
|
||||
Small, low memory usage inflate. Also serves to provide an
|
||||
unambiguous description of the deflate format.
|
||||
|
||||
testzlib/ by Gilles Vollant <info@winimage.com>
|
||||
Example of the use of zlib
|
||||
|
||||
untgz/ by "Pedro A. Aranda Guti\irrez" <paag@tid.es>
|
||||
A very simple tar.gz file extractor using zlib
|
||||
|
||||
visual-basic.txt by Carlos Rios <c_rios@sonda.cl>
|
||||
How to use compress(), uncompress() and the gz* functions from VB
|
||||
|
||||
vstudio/ by Gilles Vollant <info@winimage.com>
|
||||
Building zlib with Visual Studio .NET
|
153
zlib/contrib/ada/mtest.adb
Normal file
153
zlib/contrib/ada/mtest.adb
Normal file
|
@ -0,0 +1,153 @@
|
|||
----------------------------------------------------------------
|
||||
-- ZLib for Ada thick binding. --
|
||||
-- --
|
||||
-- Copyright (C) 2002-2003 Dmitriy Anisimkov --
|
||||
-- --
|
||||
-- Open source license information is in the zlib.ads file. --
|
||||
----------------------------------------------------------------
|
||||
-- Continuous test for ZLib multithreading. If the test is fail
|
||||
-- Wou should provide thread safe allocation routines for the Z_Stream.
|
||||
--
|
||||
-- $Id: mtest.adb,v 1.2 2003/08/12 12:11:05 vagul Exp $
|
||||
|
||||
with ZLib;
|
||||
with Ada.Streams;
|
||||
with Ada.Numerics.Discrete_Random;
|
||||
with Ada.Text_IO;
|
||||
with Ada.Exceptions;
|
||||
with Ada.Task_Identification;
|
||||
|
||||
procedure MTest is
|
||||
use Ada.Streams;
|
||||
use ZLib;
|
||||
|
||||
Stop : Boolean := False;
|
||||
|
||||
pragma Atomic (Stop);
|
||||
|
||||
subtype Visible_Symbols is Stream_Element range 16#20# .. 16#7E#;
|
||||
|
||||
package Random_Elements is
|
||||
new Ada.Numerics.Discrete_Random (Visible_Symbols);
|
||||
|
||||
task type Test_Task;
|
||||
|
||||
task body Test_Task is
|
||||
Buffer : Stream_Element_Array (1 .. 100_000);
|
||||
Gen : Random_Elements.Generator;
|
||||
|
||||
Buffer_First : Stream_Element_Offset;
|
||||
Compare_First : Stream_Element_Offset;
|
||||
|
||||
Deflate : Filter_Type;
|
||||
Inflate : Filter_Type;
|
||||
|
||||
procedure Further (Item : in Stream_Element_Array);
|
||||
|
||||
procedure Read_Buffer
|
||||
(Item : out Ada.Streams.Stream_Element_Array;
|
||||
Last : out Ada.Streams.Stream_Element_Offset);
|
||||
|
||||
-------------
|
||||
-- Further --
|
||||
-------------
|
||||
|
||||
procedure Further (Item : in Stream_Element_Array) is
|
||||
|
||||
procedure Compare (Item : in Stream_Element_Array);
|
||||
|
||||
-------------
|
||||
-- Compare --
|
||||
-------------
|
||||
|
||||
procedure Compare (Item : in Stream_Element_Array) is
|
||||
Next_First : Stream_Element_Offset := Compare_First + Item'Length;
|
||||
begin
|
||||
if Buffer (Compare_First .. Next_First - 1) /= Item then
|
||||
raise Program_Error;
|
||||
end if;
|
||||
|
||||
Compare_First := Next_First;
|
||||
end Compare;
|
||||
|
||||
procedure Compare_Write is new ZLib.Write (Write => Compare);
|
||||
begin
|
||||
Compare_Write (Inflate, Item, No_Flush);
|
||||
end Further;
|
||||
|
||||
-----------------
|
||||
-- Read_Buffer --
|
||||
-----------------
|
||||
|
||||
procedure Read_Buffer
|
||||
(Item : out Ada.Streams.Stream_Element_Array;
|
||||
Last : out Ada.Streams.Stream_Element_Offset)
|
||||
is
|
||||
Buff_Diff : Stream_Element_Offset := Buffer'Last - Buffer_First;
|
||||
Next_First : Stream_Element_Offset;
|
||||
begin
|
||||
if Item'Length <= Buff_Diff then
|
||||
Last := Item'Last;
|
||||
|
||||
Next_First := Buffer_First + Item'Length;
|
||||
|
||||
Item := Buffer (Buffer_First .. Next_First - 1);
|
||||
|
||||
Buffer_First := Next_First;
|
||||
else
|
||||
Last := Item'First + Buff_Diff;
|
||||
Item (Item'First .. Last) := Buffer (Buffer_First .. Buffer'Last);
|
||||
Buffer_First := Buffer'Last + 1;
|
||||
end if;
|
||||
end Read_Buffer;
|
||||
|
||||
procedure Translate is new Generic_Translate
|
||||
(Data_In => Read_Buffer,
|
||||
Data_Out => Further);
|
||||
|
||||
begin
|
||||
Random_Elements.Reset (Gen);
|
||||
|
||||
Buffer := (others => 20);
|
||||
|
||||
Main : loop
|
||||
for J in Buffer'Range loop
|
||||
Buffer (J) := Random_Elements.Random (Gen);
|
||||
|
||||
Deflate_Init (Deflate);
|
||||
Inflate_Init (Inflate);
|
||||
|
||||
Buffer_First := Buffer'First;
|
||||
Compare_First := Buffer'First;
|
||||
|
||||
Translate (Deflate);
|
||||
|
||||
if Compare_First /= Buffer'Last + 1 then
|
||||
raise Program_Error;
|
||||
end if;
|
||||
|
||||
Ada.Text_IO.Put_Line
|
||||
(Ada.Task_Identification.Image
|
||||
(Ada.Task_Identification.Current_Task)
|
||||
& Stream_Element_Offset'Image (J)
|
||||
& ZLib.Count'Image (Total_Out (Deflate)));
|
||||
|
||||
Close (Deflate);
|
||||
Close (Inflate);
|
||||
|
||||
exit Main when Stop;
|
||||
end loop;
|
||||
end loop Main;
|
||||
exception
|
||||
when E : others =>
|
||||
Ada.Text_IO.Put_Line (Ada.Exceptions.Exception_Information (E));
|
||||
Stop := True;
|
||||
end Test_Task;
|
||||
|
||||
Test : array (1 .. 4) of Test_Task;
|
||||
|
||||
pragma Unreferenced (Test);
|
||||
|
||||
begin
|
||||
null;
|
||||
end MTest;
|
151
zlib/contrib/ada/read.adb
Normal file
151
zlib/contrib/ada/read.adb
Normal file
|
@ -0,0 +1,151 @@
|
|||
----------------------------------------------------------------
|
||||
-- ZLib for Ada thick binding. --
|
||||
-- --
|
||||
-- Copyright (C) 2002-2003 Dmitriy Anisimkov --
|
||||
-- --
|
||||
-- Open source license information is in the zlib.ads file. --
|
||||
----------------------------------------------------------------
|
||||
|
||||
-- $Id: read.adb,v 1.7 2003/08/12 12:12:35 vagul Exp $
|
||||
|
||||
-- Test/demo program for the generic read interface.
|
||||
|
||||
with Ada.Numerics.Discrete_Random;
|
||||
with Ada.Streams;
|
||||
with Ada.Text_IO;
|
||||
|
||||
with ZLib;
|
||||
|
||||
procedure Read is
|
||||
|
||||
use Ada.Streams;
|
||||
|
||||
------------------------------------
|
||||
-- Test configuration parameters --
|
||||
------------------------------------
|
||||
|
||||
File_Size : Stream_Element_Offset := 100_000;
|
||||
|
||||
Continuous : constant Boolean := False;
|
||||
-- If this constant is True, the test would be repeated again and again,
|
||||
-- with increment File_Size for every iteration.
|
||||
|
||||
Header : constant ZLib.Header_Type := ZLib.Default;
|
||||
-- Do not use Header other than Default in ZLib versions 1.1.4 and older.
|
||||
|
||||
Init_Random : constant := 8;
|
||||
-- We are using the same random sequence, in case of we catch bug,
|
||||
-- so we would be able to reproduce it.
|
||||
|
||||
-- End --
|
||||
|
||||
Pack_Size : Stream_Element_Offset;
|
||||
Offset : Stream_Element_Offset;
|
||||
|
||||
Filter : ZLib.Filter_Type;
|
||||
|
||||
subtype Visible_Symbols
|
||||
is Stream_Element range 16#20# .. 16#7E#;
|
||||
|
||||
package Random_Elements is new
|
||||
Ada.Numerics.Discrete_Random (Visible_Symbols);
|
||||
|
||||
Gen : Random_Elements.Generator;
|
||||
Period : constant Stream_Element_Offset := 200;
|
||||
-- Period constant variable for random generator not to be very random.
|
||||
-- Bigger period, harder random.
|
||||
|
||||
Read_Buffer : Stream_Element_Array (1 .. 2048);
|
||||
Read_First : Stream_Element_Offset;
|
||||
Read_Last : Stream_Element_Offset;
|
||||
|
||||
procedure Reset;
|
||||
|
||||
procedure Read
|
||||
(Item : out Stream_Element_Array;
|
||||
Last : out Stream_Element_Offset);
|
||||
-- this procedure is for generic instantiation of
|
||||
-- ZLib.Read
|
||||
-- reading data from the File_In.
|
||||
|
||||
procedure Read is new ZLib.Read (Read, Read_Buffer, Read_First, Read_Last);
|
||||
|
||||
----------
|
||||
-- Read --
|
||||
----------
|
||||
|
||||
procedure Read
|
||||
(Item : out Stream_Element_Array;
|
||||
Last : out Stream_Element_Offset) is
|
||||
begin
|
||||
Last := Stream_Element_Offset'Min
|
||||
(Item'Last,
|
||||
Item'First + File_Size - Offset);
|
||||
|
||||
for J in Item'First .. Last loop
|
||||
if J < Item'First + Period then
|
||||
Item (J) := Random_Elements.Random (Gen);
|
||||
else
|
||||
Item (J) := Item (J - Period);
|
||||
end if;
|
||||
|
||||
Offset := Offset + 1;
|
||||
end loop;
|
||||
end Read;
|
||||
|
||||
-----------
|
||||
-- Reset --
|
||||
-----------
|
||||
|
||||
procedure Reset is
|
||||
begin
|
||||
Random_Elements.Reset (Gen, Init_Random);
|
||||
Pack_Size := 0;
|
||||
Offset := 1;
|
||||
Read_First := Read_Buffer'Last + 1;
|
||||
end Reset;
|
||||
|
||||
begin
|
||||
Ada.Text_IO.Put_Line ("ZLib " & ZLib.Version);
|
||||
|
||||
loop
|
||||
for Level in ZLib.Compression_Level'Range loop
|
||||
|
||||
Ada.Text_IO.Put ("Level ="
|
||||
& ZLib.Compression_Level'Image (Level));
|
||||
|
||||
-- Deflate using generic instantiation.
|
||||
|
||||
ZLib.Deflate_Init
|
||||
(Filter,
|
||||
Level,
|
||||
Header => Header);
|
||||
|
||||
Reset;
|
||||
|
||||
Ada.Text_IO.Put
|
||||
(Stream_Element_Offset'Image (File_Size) & " ->");
|
||||
|
||||
loop
|
||||
declare
|
||||
Buffer : Stream_Element_Array (1 .. 1024);
|
||||
Last : Stream_Element_Offset;
|
||||
begin
|
||||
Read (Filter, Buffer, Last);
|
||||
|
||||
Pack_Size := Pack_Size + Last - Buffer'First + 1;
|
||||
|
||||
exit when Last < Buffer'Last;
|
||||
end;
|
||||
end loop;
|
||||
|
||||
Ada.Text_IO.Put_Line (Stream_Element_Offset'Image (Pack_Size));
|
||||
|
||||
ZLib.Close (Filter);
|
||||
end loop;
|
||||
|
||||
exit when not Continuous;
|
||||
|
||||
File_Size := File_Size + 1;
|
||||
end loop;
|
||||
end Read;
|
52
zlib/contrib/ada/readme.txt
Normal file
52
zlib/contrib/ada/readme.txt
Normal file
|
@ -0,0 +1,52 @@
|
|||
|
||||
ZLib for Ada thick binding (ZLib.Ada)
|
||||
Release 1.2
|
||||
|
||||
ZLib.Ada is a thick binding interface to the popular ZLib data
|
||||
compression library, available at http://www.gzip.org/zlib/.
|
||||
It provides Ada-style access to the ZLib C library.
|
||||
|
||||
|
||||
Here are the main changes since ZLib.Ada 1.1:
|
||||
|
||||
- The default header type has a name "Default" now. Auto is used only for
|
||||
automatic GZip/ZLib header detection.
|
||||
|
||||
- Added test for multitasking mtest.adb.
|
||||
|
||||
- Added GNAT project file zlib.gpr.
|
||||
|
||||
|
||||
How to build ZLib.Ada under GNAT
|
||||
|
||||
You should have the ZLib library already build on your computer, before
|
||||
building ZLib.Ada. Make the directory of ZLib.Ada sources current and
|
||||
issue the command:
|
||||
|
||||
gnatmake test -largs -L<directory where libz.a is> -lz
|
||||
|
||||
Or use the GNAT project file build for GNAT 3.15 or later:
|
||||
|
||||
gnatmake -Pzlib.gpr -L<directory where libz.a is>
|
||||
|
||||
|
||||
How to build ZLib.Ada under Aonix ObjectAda for Win32 7.2.2
|
||||
|
||||
1. Make a project with all *.ads and *.adb files from the distribution.
|
||||
2. Build the libz.a library from the ZLib C sources.
|
||||
3. Rename libz.a to z.lib.
|
||||
4. Add the library z.lib to the project.
|
||||
5. Add the libc.lib library from the ObjectAda distribution to the project.
|
||||
6. Build the executable using test.adb as a main procedure.
|
||||
|
||||
|
||||
How to use ZLib.Ada
|
||||
|
||||
The source files test.adb and read.adb are small demo programs that show
|
||||
the main functionality of ZLib.Ada.
|
||||
|
||||
The routines from the package specifications are commented.
|
||||
|
||||
|
||||
Homepage: http://zlib-ada.sourceforge.net/
|
||||
Author: Dmitriy Anisimkov <anisimkov@yahoo.com>
|
463
zlib/contrib/ada/test.adb
Normal file
463
zlib/contrib/ada/test.adb
Normal file
|
@ -0,0 +1,463 @@
|
|||
----------------------------------------------------------------
|
||||
-- ZLib for Ada thick binding. --
|
||||
-- --
|
||||
-- Copyright (C) 2002-2003 Dmitriy Anisimkov --
|
||||
-- --
|
||||
-- Open source license information is in the zlib.ads file. --
|
||||
----------------------------------------------------------------
|
||||
|
||||
-- $Id: test.adb,v 1.17 2003/08/12 12:13:30 vagul Exp $
|
||||
|
||||
-- The program has a few aims.
|
||||
-- 1. Test ZLib.Ada95 thick binding functionality.
|
||||
-- 2. Show the example of use main functionality of the ZLib.Ada95 binding.
|
||||
-- 3. Build this program automatically compile all ZLib.Ada95 packages under
|
||||
-- GNAT Ada95 compiler.
|
||||
|
||||
with ZLib.Streams;
|
||||
with Ada.Streams.Stream_IO;
|
||||
with Ada.Numerics.Discrete_Random;
|
||||
|
||||
with Ada.Text_IO;
|
||||
|
||||
with Ada.Calendar;
|
||||
|
||||
procedure Test is
|
||||
|
||||
use Ada.Streams;
|
||||
use Stream_IO;
|
||||
|
||||
------------------------------------
|
||||
-- Test configuration parameters --
|
||||
------------------------------------
|
||||
|
||||
File_Size : Count := 100_000;
|
||||
Continuous : constant Boolean := False;
|
||||
|
||||
Header : constant ZLib.Header_Type := ZLib.Default;
|
||||
-- ZLib.None;
|
||||
-- ZLib.Auto;
|
||||
-- ZLib.GZip;
|
||||
-- Do not use Header other then Default in ZLib versions 1.1.4
|
||||
-- and older.
|
||||
|
||||
Strategy : constant ZLib.Strategy_Type := ZLib.Default_Strategy;
|
||||
Init_Random : constant := 10;
|
||||
|
||||
-- End --
|
||||
|
||||
In_File_Name : constant String := "testzlib.in";
|
||||
-- Name of the input file
|
||||
|
||||
Z_File_Name : constant String := "testzlib.zlb";
|
||||
-- Name of the compressed file.
|
||||
|
||||
Out_File_Name : constant String := "testzlib.out";
|
||||
-- Name of the decompressed file.
|
||||
|
||||
File_In : File_Type;
|
||||
File_Out : File_Type;
|
||||
File_Back : File_Type;
|
||||
File_Z : ZLib.Streams.Stream_Type;
|
||||
|
||||
Filter : ZLib.Filter_Type;
|
||||
|
||||
Time_Stamp : Ada.Calendar.Time;
|
||||
|
||||
procedure Generate_File;
|
||||
-- Generate file of spetsified size with some random data.
|
||||
-- The random data is repeatable, for the good compression.
|
||||
|
||||
procedure Compare_Streams
|
||||
(Left, Right : in out Root_Stream_Type'Class);
|
||||
-- The procedure compearing data in 2 streams.
|
||||
-- It is for compare data before and after compression/decompression.
|
||||
|
||||
procedure Compare_Files (Left, Right : String);
|
||||
-- Compare files. Based on the Compare_Streams.
|
||||
|
||||
procedure Copy_Streams
|
||||
(Source, Target : in out Root_Stream_Type'Class;
|
||||
Buffer_Size : in Stream_Element_Offset := 1024);
|
||||
-- Copying data from one stream to another. It is for test stream
|
||||
-- interface of the library.
|
||||
|
||||
procedure Data_In
|
||||
(Item : out Stream_Element_Array;
|
||||
Last : out Stream_Element_Offset);
|
||||
-- this procedure is for generic instantiation of
|
||||
-- ZLib.Generic_Translate.
|
||||
-- reading data from the File_In.
|
||||
|
||||
procedure Data_Out (Item : in Stream_Element_Array);
|
||||
-- this procedure is for generic instantiation of
|
||||
-- ZLib.Generic_Translate.
|
||||
-- writing data to the File_Out.
|
||||
|
||||
procedure Stamp;
|
||||
-- Store the timestamp to the local variable.
|
||||
|
||||
procedure Print_Statistic (Msg : String; Data_Size : ZLib.Count);
|
||||
-- Print the time statistic with the message.
|
||||
|
||||
procedure Translate is new ZLib.Generic_Translate
|
||||
(Data_In => Data_In,
|
||||
Data_Out => Data_Out);
|
||||
-- This procedure is moving data from File_In to File_Out
|
||||
-- with compression or decompression, depend on initialization of
|
||||
-- Filter parameter.
|
||||
|
||||
-------------------
|
||||
-- Compare_Files --
|
||||
-------------------
|
||||
|
||||
procedure Compare_Files (Left, Right : String) is
|
||||
Left_File, Right_File : File_Type;
|
||||
begin
|
||||
Open (Left_File, In_File, Left);
|
||||
Open (Right_File, In_File, Right);
|
||||
Compare_Streams (Stream (Left_File).all, Stream (Right_File).all);
|
||||
Close (Left_File);
|
||||
Close (Right_File);
|
||||
end Compare_Files;
|
||||
|
||||
---------------------
|
||||
-- Compare_Streams --
|
||||
---------------------
|
||||
|
||||
procedure Compare_Streams
|
||||
(Left, Right : in out Ada.Streams.Root_Stream_Type'Class)
|
||||
is
|
||||
Left_Buffer, Right_Buffer : Stream_Element_Array (0 .. 16#FFF#);
|
||||
Left_Last, Right_Last : Stream_Element_Offset;
|
||||
begin
|
||||
loop
|
||||
Read (Left, Left_Buffer, Left_Last);
|
||||
Read (Right, Right_Buffer, Right_Last);
|
||||
|
||||
if Left_Last /= Right_Last then
|
||||
Ada.Text_IO.Put_Line ("Compare error :"
|
||||
& Stream_Element_Offset'Image (Left_Last)
|
||||
& " /= "
|
||||
& Stream_Element_Offset'Image (Right_Last));
|
||||
|
||||
raise Constraint_Error;
|
||||
|
||||
elsif Left_Buffer (0 .. Left_Last)
|
||||
/= Right_Buffer (0 .. Right_Last)
|
||||
then
|
||||
Ada.Text_IO.Put_Line ("ERROR: IN and OUT files is not equal.");
|
||||
raise Constraint_Error;
|
||||
|
||||
end if;
|
||||
|
||||
exit when Left_Last < Left_Buffer'Last;
|
||||
end loop;
|
||||
end Compare_Streams;
|
||||
|
||||
------------------
|
||||
-- Copy_Streams --
|
||||
------------------
|
||||
|
||||
procedure Copy_Streams
|
||||
(Source, Target : in out Ada.Streams.Root_Stream_Type'Class;
|
||||
Buffer_Size : in Stream_Element_Offset := 1024)
|
||||
is
|
||||
Buffer : Stream_Element_Array (1 .. Buffer_Size);
|
||||
Last : Stream_Element_Offset;
|
||||
begin
|
||||
loop
|
||||
Read (Source, Buffer, Last);
|
||||
Write (Target, Buffer (1 .. Last));
|
||||
|
||||
exit when Last < Buffer'Last;
|
||||
end loop;
|
||||
end Copy_Streams;
|
||||
|
||||
-------------
|
||||
-- Data_In --
|
||||
-------------
|
||||
|
||||
procedure Data_In
|
||||
(Item : out Stream_Element_Array;
|
||||
Last : out Stream_Element_Offset) is
|
||||
begin
|
||||
Read (File_In, Item, Last);
|
||||
end Data_In;
|
||||
|
||||
--------------
|
||||
-- Data_Out --
|
||||
--------------
|
||||
|
||||
procedure Data_Out (Item : in Stream_Element_Array) is
|
||||
begin
|
||||
Write (File_Out, Item);
|
||||
end Data_Out;
|
||||
|
||||
-------------------
|
||||
-- Generate_File --
|
||||
-------------------
|
||||
|
||||
procedure Generate_File is
|
||||
subtype Visible_Symbols is Stream_Element range 16#20# .. 16#7E#;
|
||||
|
||||
package Random_Elements is
|
||||
new Ada.Numerics.Discrete_Random (Visible_Symbols);
|
||||
|
||||
Gen : Random_Elements.Generator;
|
||||
Buffer : Stream_Element_Array := (1 .. 77 => 16#20#) & 10;
|
||||
|
||||
Buffer_Count : constant Count := File_Size / Buffer'Length;
|
||||
-- Number of same buffers in the packet.
|
||||
|
||||
Density : constant Count := 30; -- from 0 to Buffer'Length - 2;
|
||||
|
||||
procedure Fill_Buffer (J, D : in Count);
|
||||
-- Change the part of the buffer.
|
||||
|
||||
-----------------
|
||||
-- Fill_Buffer --
|
||||
-----------------
|
||||
|
||||
procedure Fill_Buffer (J, D : in Count) is
|
||||
begin
|
||||
for K in 0 .. D loop
|
||||
Buffer
|
||||
(Stream_Element_Offset ((J + K) mod (Buffer'Length - 1) + 1))
|
||||
:= Random_Elements.Random (Gen);
|
||||
|
||||
end loop;
|
||||
end Fill_Buffer;
|
||||
|
||||
begin
|
||||
Random_Elements.Reset (Gen, Init_Random);
|
||||
|
||||
Create (File_In, Out_File, In_File_Name);
|
||||
|
||||
Fill_Buffer (1, Buffer'Length - 2);
|
||||
|
||||
for J in 1 .. Buffer_Count loop
|
||||
Write (File_In, Buffer);
|
||||
|
||||
Fill_Buffer (J, Density);
|
||||
end loop;
|
||||
|
||||
-- fill remain size.
|
||||
|
||||
Write
|
||||
(File_In,
|
||||
Buffer
|
||||
(1 .. Stream_Element_Offset
|
||||
(File_Size - Buffer'Length * Buffer_Count)));
|
||||
|
||||
Flush (File_In);
|
||||
Close (File_In);
|
||||
end Generate_File;
|
||||
|
||||
---------------------
|
||||
-- Print_Statistic --
|
||||
---------------------
|
||||
|
||||
procedure Print_Statistic (Msg : String; Data_Size : ZLib.Count) is
|
||||
use Ada.Calendar;
|
||||
use Ada.Text_IO;
|
||||
|
||||
package Count_IO is new Integer_IO (ZLib.Count);
|
||||
|
||||
Curr_Dur : Duration := Clock - Time_Stamp;
|
||||
begin
|
||||
Put (Msg);
|
||||
|
||||
Set_Col (20);
|
||||
Ada.Text_IO.Put ("size =");
|
||||
|
||||
Count_IO.Put
|
||||
(Data_Size,
|
||||
Width => Stream_IO.Count'Image (File_Size)'Length);
|
||||
|
||||
Put_Line (" duration =" & Duration'Image (Curr_Dur));
|
||||
end Print_Statistic;
|
||||
|
||||
-----------
|
||||
-- Stamp --
|
||||
-----------
|
||||
|
||||
procedure Stamp is
|
||||
begin
|
||||
Time_Stamp := Ada.Calendar.Clock;
|
||||
end Stamp;
|
||||
|
||||
begin
|
||||
Ada.Text_IO.Put_Line ("ZLib " & ZLib.Version);
|
||||
|
||||
loop
|
||||
Generate_File;
|
||||
|
||||
for Level in ZLib.Compression_Level'Range loop
|
||||
|
||||
Ada.Text_IO.Put_Line ("Level ="
|
||||
& ZLib.Compression_Level'Image (Level));
|
||||
|
||||
-- Test generic interface.
|
||||
Open (File_In, In_File, In_File_Name);
|
||||
Create (File_Out, Out_File, Z_File_Name);
|
||||
|
||||
Stamp;
|
||||
|
||||
-- Deflate using generic instantiation.
|
||||
|
||||
ZLib.Deflate_Init
|
||||
(Filter => Filter,
|
||||
Level => Level,
|
||||
Strategy => Strategy,
|
||||
Header => Header);
|
||||
|
||||
Translate (Filter);
|
||||
Print_Statistic ("Generic compress", ZLib.Total_Out (Filter));
|
||||
ZLib.Close (Filter);
|
||||
|
||||
Close (File_In);
|
||||
Close (File_Out);
|
||||
|
||||
Open (File_In, In_File, Z_File_Name);
|
||||
Create (File_Out, Out_File, Out_File_Name);
|
||||
|
||||
Stamp;
|
||||
|
||||
-- Inflate using generic instantiation.
|
||||
|
||||
ZLib.Inflate_Init (Filter, Header => Header);
|
||||
|
||||
Translate (Filter);
|
||||
Print_Statistic ("Generic decompress", ZLib.Total_Out (Filter));
|
||||
|
||||
ZLib.Close (Filter);
|
||||
|
||||
Close (File_In);
|
||||
Close (File_Out);
|
||||
|
||||
Compare_Files (In_File_Name, Out_File_Name);
|
||||
|
||||
-- Test stream interface.
|
||||
|
||||
-- Compress to the back stream.
|
||||
|
||||
Open (File_In, In_File, In_File_Name);
|
||||
Create (File_Back, Out_File, Z_File_Name);
|
||||
|
||||
Stamp;
|
||||
|
||||
ZLib.Streams.Create
|
||||
(Stream => File_Z,
|
||||
Mode => ZLib.Streams.Out_Stream,
|
||||
Back => ZLib.Streams.Stream_Access
|
||||
(Stream (File_Back)),
|
||||
Back_Compressed => True,
|
||||
Level => Level,
|
||||
Strategy => Strategy,
|
||||
Header => Header);
|
||||
|
||||
Copy_Streams
|
||||
(Source => Stream (File_In).all,
|
||||
Target => File_Z);
|
||||
|
||||
-- Flushing internal buffers to the back stream.
|
||||
|
||||
ZLib.Streams.Flush (File_Z, ZLib.Finish);
|
||||
|
||||
Print_Statistic ("Write compress",
|
||||
ZLib.Streams.Write_Total_Out (File_Z));
|
||||
|
||||
ZLib.Streams.Close (File_Z);
|
||||
|
||||
Close (File_In);
|
||||
Close (File_Back);
|
||||
|
||||
-- Compare reading from original file and from
|
||||
-- decompression stream.
|
||||
|
||||
Open (File_In, In_File, In_File_Name);
|
||||
Open (File_Back, In_File, Z_File_Name);
|
||||
|
||||
ZLib.Streams.Create
|
||||
(Stream => File_Z,
|
||||
Mode => ZLib.Streams.In_Stream,
|
||||
Back => ZLib.Streams.Stream_Access
|
||||
(Stream (File_Back)),
|
||||
Back_Compressed => True,
|
||||
Header => Header);
|
||||
|
||||
Stamp;
|
||||
Compare_Streams (Stream (File_In).all, File_Z);
|
||||
|
||||
Print_Statistic ("Read decompress",
|
||||
ZLib.Streams.Read_Total_Out (File_Z));
|
||||
|
||||
ZLib.Streams.Close (File_Z);
|
||||
Close (File_In);
|
||||
Close (File_Back);
|
||||
|
||||
-- Compress by reading from compression stream.
|
||||
|
||||
Open (File_Back, In_File, In_File_Name);
|
||||
Create (File_Out, Out_File, Z_File_Name);
|
||||
|
||||
ZLib.Streams.Create
|
||||
(Stream => File_Z,
|
||||
Mode => ZLib.Streams.In_Stream,
|
||||
Back => ZLib.Streams.Stream_Access
|
||||
(Stream (File_Back)),
|
||||
Back_Compressed => False,
|
||||
Level => Level,
|
||||
Strategy => Strategy,
|
||||
Header => Header);
|
||||
|
||||
Stamp;
|
||||
Copy_Streams
|
||||
(Source => File_Z,
|
||||
Target => Stream (File_Out).all);
|
||||
|
||||
Print_Statistic ("Read compress",
|
||||
ZLib.Streams.Read_Total_Out (File_Z));
|
||||
|
||||
ZLib.Streams.Close (File_Z);
|
||||
|
||||
Close (File_Out);
|
||||
Close (File_Back);
|
||||
|
||||
-- Decompress to decompression stream.
|
||||
|
||||
Open (File_In, In_File, Z_File_Name);
|
||||
Create (File_Back, Out_File, Out_File_Name);
|
||||
|
||||
ZLib.Streams.Create
|
||||
(Stream => File_Z,
|
||||
Mode => ZLib.Streams.Out_Stream,
|
||||
Back => ZLib.Streams.Stream_Access
|
||||
(Stream (File_Back)),
|
||||
Back_Compressed => False,
|
||||
Header => Header);
|
||||
|
||||
Stamp;
|
||||
|
||||
Copy_Streams
|
||||
(Source => Stream (File_In).all,
|
||||
Target => File_Z);
|
||||
|
||||
Print_Statistic ("Write decompress",
|
||||
ZLib.Streams.Write_Total_Out (File_Z));
|
||||
|
||||
ZLib.Streams.Close (File_Z);
|
||||
Close (File_In);
|
||||
Close (File_Back);
|
||||
|
||||
Compare_Files (In_File_Name, Out_File_Name);
|
||||
end loop;
|
||||
|
||||
Ada.Text_IO.Put_Line (Count'Image (File_Size) & " Ok.");
|
||||
|
||||
exit when not Continuous;
|
||||
|
||||
File_Size := File_Size + 1;
|
||||
end loop;
|
||||
end Test;
|
215
zlib/contrib/ada/zlib-streams.adb
Normal file
215
zlib/contrib/ada/zlib-streams.adb
Normal file
|
@ -0,0 +1,215 @@
|
|||
----------------------------------------------------------------
|
||||
-- ZLib for Ada thick binding. --
|
||||
-- --
|
||||
-- Copyright (C) 2002-2003 Dmitriy Anisimkov --
|
||||
-- --
|
||||
-- Open source license information is in the zlib.ads file. --
|
||||
----------------------------------------------------------------
|
||||
|
||||
-- $Id: zlib-streams.adb,v 1.9 2003/08/12 13:15:31 vagul Exp $
|
||||
|
||||
with Ada.Unchecked_Deallocation;
|
||||
|
||||
package body ZLib.Streams is
|
||||
|
||||
-----------
|
||||
-- Close --
|
||||
-----------
|
||||
|
||||
procedure Close (Stream : in out Stream_Type) is
|
||||
procedure Free is new Ada.Unchecked_Deallocation
|
||||
(Stream_Element_Array, Buffer_Access);
|
||||
begin
|
||||
if Stream.Mode = Out_Stream or Stream.Mode = Duplex then
|
||||
-- We should flush the data written by the writer.
|
||||
|
||||
Flush (Stream, Finish);
|
||||
|
||||
Close (Stream.Writer);
|
||||
end if;
|
||||
|
||||
if Stream.Mode = In_Stream or Stream.Mode = Duplex then
|
||||
Close (Stream.Reader);
|
||||
Free (Stream.Buffer);
|
||||
end if;
|
||||
end Close;
|
||||
|
||||
------------
|
||||
-- Create --
|
||||
------------
|
||||
|
||||
procedure Create
|
||||
(Stream : out Stream_Type;
|
||||
Mode : in Stream_Mode;
|
||||
Back : in Stream_Access;
|
||||
Back_Compressed : in Boolean;
|
||||
Level : in Compression_Level := Default_Compression;
|
||||
Strategy : in Strategy_Type := Default_Strategy;
|
||||
Header : in Header_Type := Default;
|
||||
Read_Buffer_Size : in Ada.Streams.Stream_Element_Offset
|
||||
:= Default_Buffer_Size;
|
||||
Write_Buffer_Size : in Ada.Streams.Stream_Element_Offset
|
||||
:= Default_Buffer_Size)
|
||||
is
|
||||
|
||||
subtype Buffer_Subtype is Stream_Element_Array (1 .. Read_Buffer_Size);
|
||||
|
||||
procedure Init_Filter
|
||||
(Filter : in out Filter_Type;
|
||||
Compress : in Boolean);
|
||||
|
||||
-----------------
|
||||
-- Init_Filter --
|
||||
-----------------
|
||||
|
||||
procedure Init_Filter
|
||||
(Filter : in out Filter_Type;
|
||||
Compress : in Boolean) is
|
||||
begin
|
||||
if Compress then
|
||||
Deflate_Init
|
||||
(Filter, Level, Strategy, Header => Header);
|
||||
else
|
||||
Inflate_Init (Filter, Header => Header);
|
||||
end if;
|
||||
end Init_Filter;
|
||||
|
||||
begin
|
||||
Stream.Back := Back;
|
||||
Stream.Mode := Mode;
|
||||
|
||||
if Mode = Out_Stream or Mode = Duplex then
|
||||
Init_Filter (Stream.Writer, Back_Compressed);
|
||||
Stream.Buffer_Size := Write_Buffer_Size;
|
||||
else
|
||||
Stream.Buffer_Size := 0;
|
||||
end if;
|
||||
|
||||
if Mode = In_Stream or Mode = Duplex then
|
||||
Init_Filter (Stream.Reader, not Back_Compressed);
|
||||
|
||||
Stream.Buffer := new Buffer_Subtype;
|
||||
Stream.Rest_First := Stream.Buffer'Last + 1;
|
||||
end if;
|
||||
end Create;
|
||||
|
||||
-----------
|
||||
-- Flush --
|
||||
-----------
|
||||
|
||||
procedure Flush
|
||||
(Stream : in out Stream_Type;
|
||||
Mode : in Flush_Mode := Sync_Flush)
|
||||
is
|
||||
Buffer : Stream_Element_Array (1 .. Stream.Buffer_Size);
|
||||
Last : Stream_Element_Offset;
|
||||
begin
|
||||
loop
|
||||
Flush (Stream.Writer, Buffer, Last, Mode);
|
||||
|
||||
Ada.Streams.Write (Stream.Back.all, Buffer (1 .. Last));
|
||||
|
||||
exit when Last < Buffer'Last;
|
||||
end loop;
|
||||
end Flush;
|
||||
|
||||
----------
|
||||
-- Read --
|
||||
----------
|
||||
|
||||
procedure Read
|
||||
(Stream : in out Stream_Type;
|
||||
Item : out Stream_Element_Array;
|
||||
Last : out Stream_Element_Offset)
|
||||
is
|
||||
|
||||
procedure Read
|
||||
(Item : out Stream_Element_Array;
|
||||
Last : out Stream_Element_Offset);
|
||||
|
||||
----------
|
||||
-- Read --
|
||||
----------
|
||||
|
||||
procedure Read
|
||||
(Item : out Stream_Element_Array;
|
||||
Last : out Stream_Element_Offset) is
|
||||
begin
|
||||
Ada.Streams.Read (Stream.Back.all, Item, Last);
|
||||
end Read;
|
||||
|
||||
procedure Read is new ZLib.Read
|
||||
(Read => Read,
|
||||
Buffer => Stream.Buffer.all,
|
||||
Rest_First => Stream.Rest_First,
|
||||
Rest_Last => Stream.Rest_Last);
|
||||
|
||||
begin
|
||||
Read (Stream.Reader, Item, Last);
|
||||
end Read;
|
||||
|
||||
-------------------
|
||||
-- Read_Total_In --
|
||||
-------------------
|
||||
|
||||
function Read_Total_In (Stream : in Stream_Type) return Count is
|
||||
begin
|
||||
return Total_In (Stream.Reader);
|
||||
end Read_Total_In;
|
||||
|
||||
--------------------
|
||||
-- Read_Total_Out --
|
||||
--------------------
|
||||
|
||||
function Read_Total_Out (Stream : in Stream_Type) return Count is
|
||||
begin
|
||||
return Total_Out (Stream.Reader);
|
||||
end Read_Total_Out;
|
||||
|
||||
-----------
|
||||
-- Write --
|
||||
-----------
|
||||
|
||||
procedure Write
|
||||
(Stream : in out Stream_Type;
|
||||
Item : in Stream_Element_Array)
|
||||
is
|
||||
|
||||
procedure Write (Item : in Stream_Element_Array);
|
||||
|
||||
-----------
|
||||
-- Write --
|
||||
-----------
|
||||
|
||||
procedure Write (Item : in Stream_Element_Array) is
|
||||
begin
|
||||
Ada.Streams.Write (Stream.Back.all, Item);
|
||||
end Write;
|
||||
|
||||
procedure Write is new ZLib.Write
|
||||
(Write => Write,
|
||||
Buffer_Size => Stream.Buffer_Size);
|
||||
|
||||
begin
|
||||
Write (Stream.Writer, Item, No_Flush);
|
||||
end Write;
|
||||
|
||||
--------------------
|
||||
-- Write_Total_In --
|
||||
--------------------
|
||||
|
||||
function Write_Total_In (Stream : in Stream_Type) return Count is
|
||||
begin
|
||||
return Total_In (Stream.Writer);
|
||||
end Write_Total_In;
|
||||
|
||||
---------------------
|
||||
-- Write_Total_Out --
|
||||
---------------------
|
||||
|
||||
function Write_Total_Out (Stream : in Stream_Type) return Count is
|
||||
begin
|
||||
return Total_Out (Stream.Writer);
|
||||
end Write_Total_Out;
|
||||
|
||||
end ZLib.Streams;
|
112
zlib/contrib/ada/zlib-streams.ads
Normal file
112
zlib/contrib/ada/zlib-streams.ads
Normal file
|
@ -0,0 +1,112 @@
|
|||
----------------------------------------------------------------
|
||||
-- ZLib for Ada thick binding. --
|
||||
-- --
|
||||
-- Copyright (C) 2002-2003 Dmitriy Anisimkov --
|
||||
-- --
|
||||
-- Open source license information is in the zlib.ads file. --
|
||||
----------------------------------------------------------------
|
||||
|
||||
-- $Id: zlib-streams.ads,v 1.11 2003/08/12 13:15:31 vagul Exp $
|
||||
|
||||
package ZLib.Streams is
|
||||
|
||||
type Stream_Mode is (In_Stream, Out_Stream, Duplex);
|
||||
|
||||
type Stream_Access is access all Ada.Streams.Root_Stream_Type'Class;
|
||||
|
||||
type Stream_Type is
|
||||
new Ada.Streams.Root_Stream_Type with private;
|
||||
|
||||
procedure Read
|
||||
(Stream : in out Stream_Type;
|
||||
Item : out Ada.Streams.Stream_Element_Array;
|
||||
Last : out Ada.Streams.Stream_Element_Offset);
|
||||
|
||||
procedure Write
|
||||
(Stream : in out Stream_Type;
|
||||
Item : in Ada.Streams.Stream_Element_Array);
|
||||
|
||||
procedure Flush
|
||||
(Stream : in out Stream_Type;
|
||||
Mode : in Flush_Mode := Sync_Flush);
|
||||
-- Flush the written data to the back stream,
|
||||
-- all data placed to the compressor is flushing to the Back stream.
|
||||
-- Should not be used untill necessary, becouse it is decreasing
|
||||
-- compression.
|
||||
|
||||
function Read_Total_In (Stream : in Stream_Type) return Count;
|
||||
pragma Inline (Read_Total_In);
|
||||
-- Return total number of bytes read from back stream so far.
|
||||
|
||||
function Read_Total_Out (Stream : in Stream_Type) return Count;
|
||||
pragma Inline (Read_Total_Out);
|
||||
-- Return total number of bytes read so far.
|
||||
|
||||
function Write_Total_In (Stream : in Stream_Type) return Count;
|
||||
pragma Inline (Write_Total_In);
|
||||
-- Return total number of bytes written so far.
|
||||
|
||||
function Write_Total_Out (Stream : in Stream_Type) return Count;
|
||||
pragma Inline (Write_Total_Out);
|
||||
-- Return total number of bytes written to the back stream.
|
||||
|
||||
procedure Create
|
||||
(Stream : out Stream_Type;
|
||||
Mode : in Stream_Mode;
|
||||
Back : in Stream_Access;
|
||||
Back_Compressed : in Boolean;
|
||||
Level : in Compression_Level := Default_Compression;
|
||||
Strategy : in Strategy_Type := Default_Strategy;
|
||||
Header : in Header_Type := Default;
|
||||
Read_Buffer_Size : in Ada.Streams.Stream_Element_Offset
|
||||
:= Default_Buffer_Size;
|
||||
Write_Buffer_Size : in Ada.Streams.Stream_Element_Offset
|
||||
:= Default_Buffer_Size);
|
||||
-- Create the Comression/Decompression stream.
|
||||
-- If mode is In_Stream then Write operation is disabled.
|
||||
-- If mode is Out_Stream then Read operation is disabled.
|
||||
|
||||
-- If Back_Compressed is true then
|
||||
-- Data written to the Stream is compressing to the Back stream
|
||||
-- and data read from the Stream is decompressed data from the Back stream.
|
||||
|
||||
-- If Back_Compressed is false then
|
||||
-- Data written to the Stream is decompressing to the Back stream
|
||||
-- and data read from the Stream is compressed data from the Back stream.
|
||||
|
||||
-- !!! When the Need_Header is False ZLib-Ada is using undocumented
|
||||
-- ZLib 1.1.4 functionality to do not create/wait for ZLib headers.
|
||||
|
||||
procedure Close (Stream : in out Stream_Type);
|
||||
|
||||
private
|
||||
|
||||
use Ada.Streams;
|
||||
|
||||
type Buffer_Access is access all Stream_Element_Array;
|
||||
|
||||
type Stream_Type
|
||||
is new Root_Stream_Type with
|
||||
record
|
||||
Mode : Stream_Mode;
|
||||
|
||||
Buffer : Buffer_Access;
|
||||
Rest_First : Stream_Element_Offset;
|
||||
Rest_Last : Stream_Element_Offset;
|
||||
-- Buffer for Read operation.
|
||||
-- We need to have this buffer in the record
|
||||
-- becouse not all read data from back stream
|
||||
-- could be processed during the read operation.
|
||||
|
||||
Buffer_Size : Stream_Element_Offset;
|
||||
-- Buffer size for write operation.
|
||||
-- We do not need to have this buffer
|
||||
-- in the record becouse all data could be
|
||||
-- processed in the write operation.
|
||||
|
||||
Back : Stream_Access;
|
||||
Reader : Filter_Type;
|
||||
Writer : Filter_Type;
|
||||
end record;
|
||||
|
||||
end ZLib.Streams;
|
185
zlib/contrib/ada/zlib-thin.adb
Normal file
185
zlib/contrib/ada/zlib-thin.adb
Normal file
|
@ -0,0 +1,185 @@
|
|||
----------------------------------------------------------------
|
||||
-- ZLib for Ada thick binding. --
|
||||
-- --
|
||||
-- Copyright (C) 2002-2003 Dmitriy Anisimkov --
|
||||
-- --
|
||||
-- Open source license information is in the zlib.ads file. --
|
||||
----------------------------------------------------------------
|
||||
|
||||
-- $Id: zlib-thin.adb,v 1.6 2003/01/21 15:26:37 vagul Exp $
|
||||
|
||||
package body ZLib.Thin is
|
||||
|
||||
ZLIB_VERSION : constant Chars_Ptr :=
|
||||
Interfaces.C.Strings.New_String ("1.1.4");
|
||||
|
||||
Z_Stream_Size : constant Int := Z_Stream'Size / System.Storage_Unit;
|
||||
|
||||
--------------
|
||||
-- Avail_In --
|
||||
--------------
|
||||
|
||||
function Avail_In (Strm : in Z_Stream) return UInt is
|
||||
begin
|
||||
return Strm.Avail_In;
|
||||
end Avail_In;
|
||||
|
||||
---------------
|
||||
-- Avail_Out --
|
||||
---------------
|
||||
|
||||
function Avail_Out (Strm : in Z_Stream) return UInt is
|
||||
begin
|
||||
return Strm.Avail_Out;
|
||||
end Avail_Out;
|
||||
|
||||
------------------
|
||||
-- Deflate_Init --
|
||||
------------------
|
||||
|
||||
function Deflate_Init
|
||||
(strm : in Z_Streamp;
|
||||
level : in Int := Z_DEFAULT_COMPRESSION)
|
||||
return Int is
|
||||
begin
|
||||
return deflateInit (strm, level, ZLIB_VERSION, Z_Stream_Size);
|
||||
end Deflate_Init;
|
||||
|
||||
function Deflate_Init
|
||||
(strm : Z_Streamp;
|
||||
level : Int;
|
||||
method : Int;
|
||||
windowBits : Int;
|
||||
memLevel : Int;
|
||||
strategy : Int)
|
||||
return Int is
|
||||
begin
|
||||
return deflateInit2
|
||||
(strm,
|
||||
level,
|
||||
method,
|
||||
windowBits,
|
||||
memLevel,
|
||||
strategy,
|
||||
ZLIB_VERSION,
|
||||
Z_Stream_Size);
|
||||
end Deflate_Init;
|
||||
|
||||
------------------
|
||||
-- Inflate_Init --
|
||||
------------------
|
||||
|
||||
function Inflate_Init (strm : Z_Streamp) return Int is
|
||||
begin
|
||||
return inflateInit (strm, ZLIB_VERSION, Z_Stream_Size);
|
||||
end Inflate_Init;
|
||||
|
||||
function Inflate_Init (strm : Z_Streamp; windowBits : Int) return Int is
|
||||
begin
|
||||
return inflateInit2 (strm, windowBits, ZLIB_VERSION, Z_Stream_Size);
|
||||
end Inflate_Init;
|
||||
|
||||
function Last_Error_Message (Strm : in Z_Stream) return String is
|
||||
use Interfaces.C.Strings;
|
||||
begin
|
||||
if Strm.msg = Null_Ptr then
|
||||
return "";
|
||||
else
|
||||
return Value (Strm.msg);
|
||||
end if;
|
||||
end Last_Error_Message;
|
||||
|
||||
-------------
|
||||
-- Need_In --
|
||||
-------------
|
||||
|
||||
function Need_In (strm : Z_Stream) return Boolean is
|
||||
begin
|
||||
return strm.Avail_In = 0;
|
||||
end Need_In;
|
||||
|
||||
--------------
|
||||
-- Need_Out --
|
||||
--------------
|
||||
|
||||
function Need_Out (strm : Z_Stream) return Boolean is
|
||||
begin
|
||||
return strm.Avail_Out = 0;
|
||||
end Need_Out;
|
||||
|
||||
------------
|
||||
-- Set_In --
|
||||
------------
|
||||
|
||||
procedure Set_In
|
||||
(Strm : in out Z_Stream;
|
||||
Buffer : in Byte_Access;
|
||||
Size : in UInt) is
|
||||
begin
|
||||
Strm.Next_In := Buffer;
|
||||
Strm.Avail_In := Size;
|
||||
end Set_In;
|
||||
|
||||
procedure Set_In
|
||||
(Strm : in out Z_Stream;
|
||||
Buffer : in Voidp;
|
||||
Size : in UInt) is
|
||||
begin
|
||||
Set_In (Strm, Bytes.To_Pointer (Buffer), Size);
|
||||
end Set_In;
|
||||
|
||||
------------------
|
||||
-- Set_Mem_Func --
|
||||
------------------
|
||||
|
||||
procedure Set_Mem_Func
|
||||
(Strm : in out Z_Stream;
|
||||
Opaque : in Voidp;
|
||||
Alloc : in alloc_func;
|
||||
Free : in free_func) is
|
||||
begin
|
||||
Strm.opaque := Opaque;
|
||||
Strm.zalloc := Alloc;
|
||||
Strm.zfree := Free;
|
||||
end Set_Mem_Func;
|
||||
|
||||
-------------
|
||||
-- Set_Out --
|
||||
-------------
|
||||
|
||||
procedure Set_Out
|
||||
(Strm : in out Z_Stream;
|
||||
Buffer : in Byte_Access;
|
||||
Size : in UInt) is
|
||||
begin
|
||||
Strm.Next_Out := Buffer;
|
||||
Strm.Avail_Out := Size;
|
||||
end Set_Out;
|
||||
|
||||
procedure Set_Out
|
||||
(Strm : in out Z_Stream;
|
||||
Buffer : in Voidp;
|
||||
Size : in UInt) is
|
||||
begin
|
||||
Set_Out (Strm, Bytes.To_Pointer (Buffer), Size);
|
||||
end Set_Out;
|
||||
|
||||
--------------
|
||||
-- Total_In --
|
||||
--------------
|
||||
|
||||
function Total_In (Strm : in Z_Stream) return ULong is
|
||||
begin
|
||||
return Strm.Total_In;
|
||||
end Total_In;
|
||||
|
||||
---------------
|
||||
-- Total_Out --
|
||||
---------------
|
||||
|
||||
function Total_Out (Strm : in Z_Stream) return ULong is
|
||||
begin
|
||||
return Strm.Total_Out;
|
||||
end Total_Out;
|
||||
|
||||
end ZLib.Thin;
|
485
zlib/contrib/ada/zlib-thin.ads
Normal file
485
zlib/contrib/ada/zlib-thin.ads
Normal file
|
@ -0,0 +1,485 @@
|
|||
----------------------------------------------------------------
|
||||
-- ZLib for Ada thick binding. --
|
||||
-- --
|
||||
-- Copyright (C) 2002-2003 Dmitriy Anisimkov --
|
||||
-- --
|
||||
-- Open source license information is in the zlib.ads file. --
|
||||
----------------------------------------------------------------
|
||||
|
||||
-- $Id: zlib-thin.ads,v 1.8 2003/08/12 13:16:51 vagul Exp $
|
||||
|
||||
with Interfaces.C.Strings;
|
||||
with System.Address_To_Access_Conversions;
|
||||
|
||||
private package ZLib.Thin is
|
||||
|
||||
-- From zconf.h
|
||||
|
||||
MAX_MEM_LEVEL : constant := 9; -- zconf.h:105
|
||||
-- zconf.h:105
|
||||
MAX_WBITS : constant := 15; -- zconf.h:115
|
||||
-- 32K LZ77 window
|
||||
-- zconf.h:115
|
||||
SEEK_SET : constant := 8#0000#; -- zconf.h:244
|
||||
-- Seek from beginning of file.
|
||||
-- zconf.h:244
|
||||
SEEK_CUR : constant := 1; -- zconf.h:245
|
||||
-- Seek from current position.
|
||||
-- zconf.h:245
|
||||
SEEK_END : constant := 2; -- zconf.h:246
|
||||
-- Set file pointer to EOF plus "offset"
|
||||
-- zconf.h:246
|
||||
|
||||
type Byte is new Interfaces.C.unsigned_char; -- 8 bits
|
||||
-- zconf.h:214
|
||||
type UInt is new Interfaces.C.unsigned; -- 16 bits or more
|
||||
-- zconf.h:216
|
||||
type Int is new Interfaces.C.int;
|
||||
|
||||
type ULong is new Interfaces.C.unsigned; -- 32 bits or more
|
||||
-- zconf.h:217
|
||||
subtype Chars_Ptr is Interfaces.C.Strings.chars_ptr;
|
||||
|
||||
type ULong_Access is access ULong;
|
||||
type Int_Access is access Int;
|
||||
subtype Voidp is System.Address; -- zconf.h:232
|
||||
|
||||
package Bytes is new System.Address_To_Access_Conversions (Byte);
|
||||
|
||||
subtype Byte_Access is Bytes.Object_Pointer;
|
||||
|
||||
-- end from zconf
|
||||
|
||||
Z_NO_FLUSH : constant := 8#0000#; -- zlib.h:125
|
||||
-- zlib.h:125
|
||||
Z_PARTIAL_FLUSH : constant := 1; -- zlib.h:126
|
||||
-- will be removed, use
|
||||
-- Z_SYNC_FLUSH instead
|
||||
-- zlib.h:126
|
||||
Z_SYNC_FLUSH : constant := 2; -- zlib.h:127
|
||||
-- zlib.h:127
|
||||
Z_FULL_FLUSH : constant := 3; -- zlib.h:128
|
||||
-- zlib.h:128
|
||||
Z_FINISH : constant := 4; -- zlib.h:129
|
||||
-- zlib.h:129
|
||||
Z_OK : constant := 8#0000#; -- zlib.h:132
|
||||
-- zlib.h:132
|
||||
Z_STREAM_END : constant := 1; -- zlib.h:133
|
||||
-- zlib.h:133
|
||||
Z_NEED_DICT : constant := 2; -- zlib.h:134
|
||||
-- zlib.h:134
|
||||
Z_ERRNO : constant := -1; -- zlib.h:135
|
||||
-- zlib.h:135
|
||||
Z_STREAM_ERROR : constant := -2; -- zlib.h:136
|
||||
-- zlib.h:136
|
||||
Z_DATA_ERROR : constant := -3; -- zlib.h:137
|
||||
-- zlib.h:137
|
||||
Z_MEM_ERROR : constant := -4; -- zlib.h:138
|
||||
-- zlib.h:138
|
||||
Z_BUF_ERROR : constant := -5; -- zlib.h:139
|
||||
-- zlib.h:139
|
||||
Z_VERSION_ERROR : constant := -6; -- zlib.h:140
|
||||
-- zlib.h:140
|
||||
Z_NO_COMPRESSION : constant := 8#0000#; -- zlib.h:145
|
||||
-- zlib.h:145
|
||||
Z_BEST_SPEED : constant := 1; -- zlib.h:146
|
||||
-- zlib.h:146
|
||||
Z_BEST_COMPRESSION : constant := 9; -- zlib.h:147
|
||||
-- zlib.h:147
|
||||
Z_DEFAULT_COMPRESSION : constant := -1; -- zlib.h:148
|
||||
-- zlib.h:148
|
||||
Z_FILTERED : constant := 1; -- zlib.h:151
|
||||
-- zlib.h:151
|
||||
Z_HUFFMAN_ONLY : constant := 2; -- zlib.h:152
|
||||
-- zlib.h:152
|
||||
Z_DEFAULT_STRATEGY : constant := 8#0000#; -- zlib.h:153
|
||||
-- zlib.h:153
|
||||
Z_BINARY : constant := 8#0000#; -- zlib.h:156
|
||||
-- zlib.h:156
|
||||
Z_ASCII : constant := 1; -- zlib.h:157
|
||||
-- zlib.h:157
|
||||
Z_UNKNOWN : constant := 2; -- zlib.h:158
|
||||
-- zlib.h:158
|
||||
Z_DEFLATED : constant := 8; -- zlib.h:161
|
||||
-- zlib.h:161
|
||||
Z_NULL : constant := 8#0000#; -- zlib.h:164
|
||||
-- for initializing zalloc, zfree, opaque
|
||||
-- zlib.h:164
|
||||
type gzFile is new Voidp; -- zlib.h:646
|
||||
|
||||
type Z_Stream is private;
|
||||
|
||||
type Z_Streamp is access all Z_Stream; -- zlib.h:89
|
||||
|
||||
type alloc_func is access function
|
||||
(Opaque : Voidp;
|
||||
Items : UInt;
|
||||
Size : UInt)
|
||||
return Voidp; -- zlib.h:63
|
||||
|
||||
type free_func is access procedure (opaque : Voidp; address : Voidp);
|
||||
|
||||
function zlibVersion return Chars_Ptr;
|
||||
|
||||
function Deflate (strm : Z_Streamp; flush : Int) return Int;
|
||||
|
||||
function DeflateEnd (strm : Z_Streamp) return Int;
|
||||
|
||||
function Inflate (strm : Z_Streamp; flush : Int) return Int;
|
||||
|
||||
function InflateEnd (strm : Z_Streamp) return Int;
|
||||
|
||||
function deflateSetDictionary
|
||||
(strm : Z_Streamp;
|
||||
dictionary : Byte_Access;
|
||||
dictLength : UInt)
|
||||
return Int;
|
||||
|
||||
function deflateCopy (dest : Z_Streamp; source : Z_Streamp) return Int;
|
||||
-- zlib.h:478
|
||||
|
||||
function deflateReset (strm : Z_Streamp) return Int; -- zlib.h:495
|
||||
|
||||
function deflateParams
|
||||
(strm : Z_Streamp;
|
||||
level : Int;
|
||||
strategy : Int)
|
||||
return Int; -- zlib.h:506
|
||||
|
||||
function inflateSetDictionary
|
||||
(strm : Z_Streamp;
|
||||
dictionary : Byte_Access;
|
||||
dictLength : UInt)
|
||||
return Int; -- zlib.h:548
|
||||
|
||||
function inflateSync (strm : Z_Streamp) return Int; -- zlib.h:565
|
||||
|
||||
function inflateReset (strm : Z_Streamp) return Int; -- zlib.h:580
|
||||
|
||||
function compress
|
||||
(dest : Byte_Access;
|
||||
destLen : ULong_Access;
|
||||
source : Byte_Access;
|
||||
sourceLen : ULong)
|
||||
return Int; -- zlib.h:601
|
||||
|
||||
function compress2
|
||||
(dest : Byte_Access;
|
||||
destLen : ULong_Access;
|
||||
source : Byte_Access;
|
||||
sourceLen : ULong;
|
||||
level : Int)
|
||||
return Int; -- zlib.h:615
|
||||
|
||||
function uncompress
|
||||
(dest : Byte_Access;
|
||||
destLen : ULong_Access;
|
||||
source : Byte_Access;
|
||||
sourceLen : ULong)
|
||||
return Int;
|
||||
|
||||
function gzopen (path : Chars_Ptr; mode : Chars_Ptr) return gzFile;
|
||||
|
||||
function gzdopen (fd : Int; mode : Chars_Ptr) return gzFile;
|
||||
|
||||
function gzsetparams
|
||||
(file : gzFile;
|
||||
level : Int;
|
||||
strategy : Int)
|
||||
return Int;
|
||||
|
||||
function gzread
|
||||
(file : gzFile;
|
||||
buf : Voidp;
|
||||
len : UInt)
|
||||
return Int;
|
||||
|
||||
function gzwrite
|
||||
(file : in gzFile;
|
||||
buf : in Voidp;
|
||||
len : in UInt)
|
||||
return Int;
|
||||
|
||||
function gzprintf (file : in gzFile; format : in Chars_Ptr) return Int;
|
||||
|
||||
function gzputs (file : in gzFile; s : in Chars_Ptr) return Int;
|
||||
|
||||
function gzgets
|
||||
(file : gzFile;
|
||||
buf : Chars_Ptr;
|
||||
len : Int)
|
||||
return Chars_Ptr;
|
||||
|
||||
function gzputc (file : gzFile; char : Int) return Int;
|
||||
|
||||
function gzgetc (file : gzFile) return Int;
|
||||
|
||||
function gzflush (file : gzFile; flush : Int) return Int;
|
||||
|
||||
function gzseek
|
||||
(file : gzFile;
|
||||
offset : Int;
|
||||
whence : Int)
|
||||
return Int;
|
||||
|
||||
function gzrewind (file : gzFile) return Int;
|
||||
|
||||
function gztell (file : gzFile) return Int;
|
||||
|
||||
function gzeof (file : gzFile) return Int;
|
||||
|
||||
function gzclose (file : gzFile) return Int;
|
||||
|
||||
function gzerror (file : gzFile; errnum : Int_Access) return Chars_Ptr;
|
||||
|
||||
function adler32
|
||||
(adler : ULong;
|
||||
buf : Byte_Access;
|
||||
len : UInt)
|
||||
return ULong;
|
||||
|
||||
function crc32
|
||||
(crc : ULong;
|
||||
buf : Byte_Access;
|
||||
len : UInt)
|
||||
return ULong;
|
||||
|
||||
function deflateInit
|
||||
(strm : Z_Streamp;
|
||||
level : Int;
|
||||
version : Chars_Ptr;
|
||||
stream_size : Int)
|
||||
return Int;
|
||||
|
||||
function Deflate_Init
|
||||
(strm : in Z_Streamp;
|
||||
level : in Int := Z_DEFAULT_COMPRESSION)
|
||||
return Int;
|
||||
pragma Inline (Deflate_Init);
|
||||
|
||||
function deflateInit2
|
||||
(strm : Z_Streamp;
|
||||
level : Int;
|
||||
method : Int;
|
||||
windowBits : Int;
|
||||
memLevel : Int;
|
||||
strategy : Int;
|
||||
version : Chars_Ptr;
|
||||
stream_size : Int)
|
||||
return Int;
|
||||
|
||||
function Deflate_Init
|
||||
(strm : Z_Streamp;
|
||||
level : Int;
|
||||
method : Int;
|
||||
windowBits : Int;
|
||||
memLevel : Int;
|
||||
strategy : Int)
|
||||
return Int;
|
||||
pragma Inline (Deflate_Init);
|
||||
|
||||
function inflateInit
|
||||
(strm : Z_Streamp;
|
||||
version : Chars_Ptr;
|
||||
stream_size : Int)
|
||||
return Int;
|
||||
|
||||
function Inflate_Init (strm : Z_Streamp) return Int;
|
||||
pragma Inline (Inflate_Init);
|
||||
|
||||
function inflateInit2
|
||||
(strm : in Z_Streamp;
|
||||
windowBits : in Int;
|
||||
version : in Chars_Ptr;
|
||||
stream_size : in Int)
|
||||
return Int;
|
||||
|
||||
function inflateBackInit
|
||||
(strm : in Z_Streamp;
|
||||
windowBits : in Int;
|
||||
window : in Byte_Access;
|
||||
version : in Chars_Ptr;
|
||||
stream_size : in Int)
|
||||
return Int;
|
||||
-- Size of window have to be 2**windowBits.
|
||||
|
||||
function Inflate_Init (strm : Z_Streamp; windowBits : Int) return Int;
|
||||
pragma Inline (Inflate_Init);
|
||||
|
||||
function zError (err : Int) return Chars_Ptr;
|
||||
|
||||
function inflateSyncPoint (z : Z_Streamp) return Int;
|
||||
|
||||
function get_crc_table return ULong_Access;
|
||||
|
||||
-- Interface to the available fields of the z_stream structure.
|
||||
-- The application must update next_in and avail_in when avail_in has
|
||||
-- dropped to zero. It must update next_out and avail_out when avail_out
|
||||
-- has dropped to zero. The application must initialize zalloc, zfree and
|
||||
-- opaque before calling the init function.
|
||||
|
||||
function Need_In (strm : in Z_Stream) return Boolean;
|
||||
-- return true when we do not need to setup Next_In and Avail_In fields.
|
||||
pragma Inline (Need_In);
|
||||
|
||||
function Need_Out (strm : in Z_Stream) return Boolean;
|
||||
-- return true when we do not need to setup Next_Out and Avail_Out field.
|
||||
pragma Inline (Need_Out);
|
||||
|
||||
procedure Set_In
|
||||
(Strm : in out Z_Stream;
|
||||
Buffer : in Byte_Access;
|
||||
Size : in UInt);
|
||||
pragma Inline (Set_In);
|
||||
|
||||
procedure Set_In
|
||||
(Strm : in out Z_Stream;
|
||||
Buffer : in Voidp;
|
||||
Size : in UInt);
|
||||
pragma Inline (Set_In);
|
||||
|
||||
procedure Set_Out
|
||||
(Strm : in out Z_Stream;
|
||||
Buffer : in Byte_Access;
|
||||
Size : in UInt);
|
||||
pragma Inline (Set_Out);
|
||||
|
||||
procedure Set_Out
|
||||
(Strm : in out Z_Stream;
|
||||
Buffer : in Voidp;
|
||||
Size : in UInt);
|
||||
pragma Inline (Set_Out);
|
||||
|
||||
procedure Set_Mem_Func
|
||||
(Strm : in out Z_Stream;
|
||||
Opaque : in Voidp;
|
||||
Alloc : in alloc_func;
|
||||
Free : in free_func);
|
||||
pragma Inline (Set_Mem_Func);
|
||||
|
||||
function Last_Error_Message (Strm : in Z_Stream) return String;
|
||||
pragma Inline (Last_Error_Message);
|
||||
|
||||
function Avail_Out (Strm : in Z_Stream) return UInt;
|
||||
pragma Inline (Avail_Out);
|
||||
|
||||
function Avail_In (Strm : in Z_Stream) return UInt;
|
||||
pragma Inline (Avail_In);
|
||||
|
||||
function Total_In (Strm : in Z_Stream) return ULong;
|
||||
pragma Inline (Total_In);
|
||||
|
||||
function Total_Out (Strm : in Z_Stream) return ULong;
|
||||
pragma Inline (Total_Out);
|
||||
|
||||
function inflateCopy
|
||||
(dest : in Z_Streamp;
|
||||
Source : in Z_Streamp)
|
||||
return Int;
|
||||
|
||||
function compressBound (Source_Len : in ULong) return ULong;
|
||||
|
||||
function deflateBound
|
||||
(Strm : in Z_Streamp;
|
||||
Source_Len : in ULong)
|
||||
return ULong;
|
||||
|
||||
function gzungetc (C : in Int; File : in gzFile) return Int;
|
||||
|
||||
function zlibCompileFlags return ULong;
|
||||
|
||||
function deflatePrime
|
||||
(strm : Z_Streamp;
|
||||
bits : Int;
|
||||
value : Int)
|
||||
return Int;
|
||||
|
||||
private
|
||||
|
||||
type Z_Stream is record -- zlib.h:68
|
||||
Next_In : Byte_Access; -- next input byte
|
||||
Avail_In : UInt := 0; -- number of bytes available at next_in
|
||||
Total_In : ULong := 0; -- total nb of input bytes read so far
|
||||
Next_Out : Byte_Access; -- next output byte should be put there
|
||||
Avail_Out : UInt := 0; -- remaining free space at next_out
|
||||
Total_Out : ULong := 0; -- total nb of bytes output so far
|
||||
msg : Chars_Ptr; -- last error message, NULL if no error
|
||||
state : Voidp; -- not visible by applications
|
||||
zalloc : alloc_func := null; -- used to allocate the internal state
|
||||
zfree : free_func := null; -- used to free the internal state
|
||||
opaque : Voidp; -- private data object passed to
|
||||
-- zalloc and zfree
|
||||
data_type : Int; -- best guess about the data type:
|
||||
-- ascii or binary
|
||||
adler : ULong; -- adler32 value of the uncompressed
|
||||
-- data
|
||||
reserved : ULong; -- reserved for future use
|
||||
end record;
|
||||
|
||||
pragma Convention (C, Z_Stream);
|
||||
|
||||
pragma Import (C, zlibVersion, "zlibVersion");
|
||||
pragma Import (C, Deflate, "deflate");
|
||||
pragma Import (C, DeflateEnd, "deflateEnd");
|
||||
pragma Import (C, Inflate, "inflate");
|
||||
pragma Import (C, InflateEnd, "inflateEnd");
|
||||
pragma Import (C, deflateSetDictionary, "deflateSetDictionary");
|
||||
pragma Import (C, deflateCopy, "deflateCopy");
|
||||
pragma Import (C, deflateReset, "deflateReset");
|
||||
pragma Import (C, deflateParams, "deflateParams");
|
||||
pragma Import (C, inflateSetDictionary, "inflateSetDictionary");
|
||||
pragma Import (C, inflateSync, "inflateSync");
|
||||
pragma Import (C, inflateReset, "inflateReset");
|
||||
pragma Import (C, compress, "compress");
|
||||
pragma Import (C, compress2, "compress2");
|
||||
pragma Import (C, uncompress, "uncompress");
|
||||
pragma Import (C, gzopen, "gzopen");
|
||||
pragma Import (C, gzdopen, "gzdopen");
|
||||
pragma Import (C, gzsetparams, "gzsetparams");
|
||||
pragma Import (C, gzread, "gzread");
|
||||
pragma Import (C, gzwrite, "gzwrite");
|
||||
pragma Import (C, gzprintf, "gzprintf");
|
||||
pragma Import (C, gzputs, "gzputs");
|
||||
pragma Import (C, gzgets, "gzgets");
|
||||
pragma Import (C, gzputc, "gzputc");
|
||||
pragma Import (C, gzgetc, "gzgetc");
|
||||
pragma Import (C, gzflush, "gzflush");
|
||||
pragma Import (C, gzseek, "gzseek");
|
||||
pragma Import (C, gzrewind, "gzrewind");
|
||||
pragma Import (C, gztell, "gztell");
|
||||
pragma Import (C, gzeof, "gzeof");
|
||||
pragma Import (C, gzclose, "gzclose");
|
||||
pragma Import (C, gzerror, "gzerror");
|
||||
pragma Import (C, adler32, "adler32");
|
||||
pragma Import (C, crc32, "crc32");
|
||||
pragma Import (C, deflateInit, "deflateInit_");
|
||||
pragma Import (C, inflateInit, "inflateInit_");
|
||||
pragma Import (C, deflateInit2, "deflateInit2_");
|
||||
pragma Import (C, inflateInit2, "inflateInit2_");
|
||||
pragma Import (C, zError, "zError");
|
||||
pragma Import (C, inflateSyncPoint, "inflateSyncPoint");
|
||||
pragma Import (C, get_crc_table, "get_crc_table");
|
||||
|
||||
-- added in zlib 1.2.1:
|
||||
|
||||
pragma Import (C, inflateCopy, "inflateCopy");
|
||||
pragma Import (C, compressBound, "compressBound");
|
||||
pragma Import (C, deflateBound, "deflateBound");
|
||||
pragma Import (C, gzungetc, "gzungetc");
|
||||
pragma Import (C, zlibCompileFlags, "zlibCompileFlags");
|
||||
pragma Import (C, deflatePrime, "deflatePrime");
|
||||
|
||||
pragma Import (C, inflateBackInit, "inflateBackInit_");
|
||||
|
||||
-- I stopped binding the inflateBack routines, becouse realize that
|
||||
-- it does not support zlib and gzip headers for now, and have no
|
||||
-- symmetric deflateBack routines.
|
||||
-- ZLib-Ada is symmetric regarding deflate/inflate data transformation
|
||||
-- and has a similar generic callback interface for the
|
||||
-- deflate/inflate transformation based on the regular Deflate/Inflate
|
||||
-- routines.
|
||||
|
||||
-- pragma Import (C, inflateBack, "inflateBack");
|
||||
-- pragma Import (C, inflateBackEnd, "inflateBackEnd");
|
||||
|
||||
end ZLib.Thin;
|
674
zlib/contrib/ada/zlib.adb
Normal file
674
zlib/contrib/ada/zlib.adb
Normal file
|
@ -0,0 +1,674 @@
|
|||
----------------------------------------------------------------
|
||||
-- ZLib for Ada thick binding. --
|
||||
-- --
|
||||
-- Copyright (C) 2002-2003 Dmitriy Anisimkov --
|
||||
-- --
|
||||
-- Open source license information is in the zlib.ads file. --
|
||||
----------------------------------------------------------------
|
||||
|
||||
-- $Id: zlib.adb,v 1.19 2003/07/13 16:02:19 vagul Exp $
|
||||
|
||||
with Ada.Exceptions;
|
||||
with Ada.Unchecked_Conversion;
|
||||
with Ada.Unchecked_Deallocation;
|
||||
|
||||
with Interfaces.C.Strings;
|
||||
|
||||
with ZLib.Thin;
|
||||
|
||||
package body ZLib is
|
||||
|
||||
use type Thin.Int;
|
||||
|
||||
type Z_Stream is new Thin.Z_Stream;
|
||||
|
||||
type Return_Code_Enum is
|
||||
(OK,
|
||||
STREAM_END,
|
||||
NEED_DICT,
|
||||
ERRNO,
|
||||
STREAM_ERROR,
|
||||
DATA_ERROR,
|
||||
MEM_ERROR,
|
||||
BUF_ERROR,
|
||||
VERSION_ERROR);
|
||||
|
||||
type Flate_Step_Function is access
|
||||
function (Strm : Thin.Z_Streamp; flush : Thin.Int) return Thin.Int;
|
||||
pragma Convention (C, Flate_Step_Function);
|
||||
|
||||
type Flate_End_Function is access
|
||||
function (Ctrm : in Thin.Z_Streamp) return Thin.Int;
|
||||
pragma Convention (C, Flate_End_Function);
|
||||
|
||||
type Flate_Type is record
|
||||
Step : Flate_Step_Function;
|
||||
Done : Flate_End_Function;
|
||||
end record;
|
||||
|
||||
subtype Footer_Array is Stream_Element_Array (1 .. 8);
|
||||
|
||||
Simple_GZip_Header : constant Stream_Element_Array (1 .. 10)
|
||||
:= (16#1f#, 16#8b#, -- Magic header
|
||||
16#08#, -- Z_DEFLATED
|
||||
16#00#, -- Flags
|
||||
16#00#, 16#00#, 16#00#, 16#00#, -- Time
|
||||
16#00#, -- XFlags
|
||||
16#03# -- OS code
|
||||
);
|
||||
-- The simplest gzip header is not for informational, but just for
|
||||
-- gzip format compatibility.
|
||||
-- Note that some code below is using assumption
|
||||
-- Simple_GZip_Header'Last > Footer_Array'Last, so do not make
|
||||
-- Simple_GZip_Header'Last <= Footer_Array'Last.
|
||||
|
||||
Return_Code : constant array (Thin.Int range <>) of Return_Code_Enum
|
||||
:= (0 => OK,
|
||||
1 => STREAM_END,
|
||||
2 => NEED_DICT,
|
||||
-1 => ERRNO,
|
||||
-2 => STREAM_ERROR,
|
||||
-3 => DATA_ERROR,
|
||||
-4 => MEM_ERROR,
|
||||
-5 => BUF_ERROR,
|
||||
-6 => VERSION_ERROR);
|
||||
|
||||
Flate : constant array (Boolean) of Flate_Type
|
||||
:= (True => (Step => Thin.Deflate'Access,
|
||||
Done => Thin.DeflateEnd'Access),
|
||||
False => (Step => Thin.Inflate'Access,
|
||||
Done => Thin.InflateEnd'Access));
|
||||
|
||||
Flush_Finish : constant array (Boolean) of Flush_Mode
|
||||
:= (True => Finish, False => No_Flush);
|
||||
|
||||
procedure Raise_Error (Stream : Z_Stream);
|
||||
pragma Inline (Raise_Error);
|
||||
|
||||
procedure Raise_Error (Message : String);
|
||||
pragma Inline (Raise_Error);
|
||||
|
||||
procedure Check_Error (Stream : Z_Stream; Code : Thin.Int);
|
||||
|
||||
procedure Free is new Ada.Unchecked_Deallocation
|
||||
(Z_Stream, Z_Stream_Access);
|
||||
|
||||
function To_Thin_Access is new Ada.Unchecked_Conversion
|
||||
(Z_Stream_Access, Thin.Z_Streamp);
|
||||
|
||||
procedure Translate_GZip
|
||||
(Filter : in out Filter_Type;
|
||||
In_Data : in Ada.Streams.Stream_Element_Array;
|
||||
In_Last : out Ada.Streams.Stream_Element_Offset;
|
||||
Out_Data : out Ada.Streams.Stream_Element_Array;
|
||||
Out_Last : out Ada.Streams.Stream_Element_Offset;
|
||||
Flush : in Flush_Mode);
|
||||
-- Separate translate routine for make gzip header.
|
||||
|
||||
procedure Translate_Auto
|
||||
(Filter : in out Filter_Type;
|
||||
In_Data : in Ada.Streams.Stream_Element_Array;
|
||||
In_Last : out Ada.Streams.Stream_Element_Offset;
|
||||
Out_Data : out Ada.Streams.Stream_Element_Array;
|
||||
Out_Last : out Ada.Streams.Stream_Element_Offset;
|
||||
Flush : in Flush_Mode);
|
||||
-- translate routine without additional headers.
|
||||
|
||||
-----------------
|
||||
-- Check_Error --
|
||||
-----------------
|
||||
|
||||
procedure Check_Error (Stream : Z_Stream; Code : Thin.Int) is
|
||||
use type Thin.Int;
|
||||
begin
|
||||
if Code /= Thin.Z_OK then
|
||||
Raise_Error
|
||||
(Return_Code_Enum'Image (Return_Code (Code))
|
||||
& ": " & Last_Error_Message (Stream));
|
||||
end if;
|
||||
end Check_Error;
|
||||
|
||||
-----------
|
||||
-- Close --
|
||||
-----------
|
||||
|
||||
procedure Close
|
||||
(Filter : in out Filter_Type;
|
||||
Ignore_Error : in Boolean := False)
|
||||
is
|
||||
Code : Thin.Int;
|
||||
begin
|
||||
Code := Flate (Filter.Compression).Done
|
||||
(To_Thin_Access (Filter.Strm));
|
||||
|
||||
Filter.Opened := False;
|
||||
|
||||
if Ignore_Error or else Code = Thin.Z_OK then
|
||||
Free (Filter.Strm);
|
||||
else
|
||||
declare
|
||||
Error_Message : constant String
|
||||
:= Last_Error_Message (Filter.Strm.all);
|
||||
begin
|
||||
Free (Filter.Strm);
|
||||
Ada.Exceptions.Raise_Exception
|
||||
(ZLib_Error'Identity,
|
||||
Return_Code_Enum'Image (Return_Code (Code))
|
||||
& ": " & Error_Message);
|
||||
end;
|
||||
end if;
|
||||
end Close;
|
||||
|
||||
-----------
|
||||
-- CRC32 --
|
||||
-----------
|
||||
|
||||
function CRC32
|
||||
(CRC : in Unsigned_32;
|
||||
Data : in Ada.Streams.Stream_Element_Array)
|
||||
return Unsigned_32
|
||||
is
|
||||
use Thin;
|
||||
begin
|
||||
return Unsigned_32 (crc32
|
||||
(ULong (CRC),
|
||||
Bytes.To_Pointer (Data'Address),
|
||||
Data'Length));
|
||||
end CRC32;
|
||||
|
||||
procedure CRC32
|
||||
(CRC : in out Unsigned_32;
|
||||
Data : in Ada.Streams.Stream_Element_Array) is
|
||||
begin
|
||||
CRC := CRC32 (CRC, Data);
|
||||
end CRC32;
|
||||
|
||||
------------------
|
||||
-- Deflate_Init --
|
||||
------------------
|
||||
|
||||
procedure Deflate_Init
|
||||
(Filter : in out Filter_Type;
|
||||
Level : in Compression_Level := Default_Compression;
|
||||
Strategy : in Strategy_Type := Default_Strategy;
|
||||
Method : in Compression_Method := Deflated;
|
||||
Window_Bits : in Window_Bits_Type := 15;
|
||||
Memory_Level : in Memory_Level_Type := 8;
|
||||
Header : in Header_Type := Default)
|
||||
is
|
||||
use type Thin.Int;
|
||||
Win_Bits : Thin.Int := Thin.Int (Window_Bits);
|
||||
begin
|
||||
-- We allow ZLib to make header only in case of default header type.
|
||||
-- Otherwise we would either do header by ourselfs, or do not do
|
||||
-- header at all.
|
||||
|
||||
if Header = None or else Header = GZip then
|
||||
Win_Bits := -Win_Bits;
|
||||
end if;
|
||||
|
||||
-- For the GZip CRC calculation and make headers.
|
||||
|
||||
if Header = GZip then
|
||||
Filter.CRC := 0;
|
||||
Filter.Offset := Simple_GZip_Header'First;
|
||||
else
|
||||
Filter.Offset := Simple_GZip_Header'Last + 1;
|
||||
end if;
|
||||
|
||||
Filter.Strm := new Z_Stream;
|
||||
Filter.Compression := True;
|
||||
Filter.Stream_End := False;
|
||||
Filter.Opened := True;
|
||||
Filter.Header := Header;
|
||||
|
||||
if Thin.Deflate_Init
|
||||
(To_Thin_Access (Filter.Strm),
|
||||
Level => Thin.Int (Level),
|
||||
method => Thin.Int (Method),
|
||||
windowBits => Win_Bits,
|
||||
memLevel => Thin.Int (Memory_Level),
|
||||
strategy => Thin.Int (Strategy)) /= Thin.Z_OK
|
||||
then
|
||||
Raise_Error (Filter.Strm.all);
|
||||
end if;
|
||||
end Deflate_Init;
|
||||
|
||||
-----------
|
||||
-- Flush --
|
||||
-----------
|
||||
|
||||
procedure Flush
|
||||
(Filter : in out Filter_Type;
|
||||
Out_Data : out Ada.Streams.Stream_Element_Array;
|
||||
Out_Last : out Ada.Streams.Stream_Element_Offset;
|
||||
Flush : in Flush_Mode)
|
||||
is
|
||||
No_Data : Stream_Element_Array := (1 .. 0 => 0);
|
||||
Last : Stream_Element_Offset;
|
||||
begin
|
||||
Translate (Filter, No_Data, Last, Out_Data, Out_Last, Flush);
|
||||
end Flush;
|
||||
|
||||
-----------------------
|
||||
-- Generic_Translate --
|
||||
-----------------------
|
||||
|
||||
procedure Generic_Translate
|
||||
(Filter : in out ZLib.Filter_Type;
|
||||
In_Buffer_Size : Integer := Default_Buffer_Size;
|
||||
Out_Buffer_Size : Integer := Default_Buffer_Size)
|
||||
is
|
||||
In_Buffer : Stream_Element_Array
|
||||
(1 .. Stream_Element_Offset (In_Buffer_Size));
|
||||
Out_Buffer : Stream_Element_Array
|
||||
(1 .. Stream_Element_Offset (Out_Buffer_Size));
|
||||
Last : Stream_Element_Offset;
|
||||
In_Last : Stream_Element_Offset;
|
||||
In_First : Stream_Element_Offset;
|
||||
Out_Last : Stream_Element_Offset;
|
||||
begin
|
||||
Main : loop
|
||||
Data_In (In_Buffer, Last);
|
||||
|
||||
In_First := In_Buffer'First;
|
||||
|
||||
loop
|
||||
Translate
|
||||
(Filter,
|
||||
In_Buffer (In_First .. Last),
|
||||
In_Last,
|
||||
Out_Buffer,
|
||||
Out_Last,
|
||||
Flush_Finish (Last < In_Buffer'First));
|
||||
|
||||
Data_Out (Out_Buffer (Out_Buffer'First .. Out_Last));
|
||||
|
||||
exit Main when Stream_End (Filter);
|
||||
|
||||
-- The end of in buffer.
|
||||
exit when In_Last = Last;
|
||||
|
||||
In_First := In_Last + 1;
|
||||
end loop;
|
||||
end loop Main;
|
||||
|
||||
end Generic_Translate;
|
||||
|
||||
------------------
|
||||
-- Inflate_Init --
|
||||
------------------
|
||||
|
||||
procedure Inflate_Init
|
||||
(Filter : in out Filter_Type;
|
||||
Window_Bits : in Window_Bits_Type := 15;
|
||||
Header : in Header_Type := Default)
|
||||
is
|
||||
use type Thin.Int;
|
||||
Win_Bits : Thin.Int := Thin.Int (Window_Bits);
|
||||
|
||||
procedure Check_Version;
|
||||
-- Check the latest header types compatibility.
|
||||
|
||||
procedure Check_Version is
|
||||
begin
|
||||
if Version <= "1.1.4" then
|
||||
Raise_Error
|
||||
("Inflate header type " & Header_Type'Image (Header)
|
||||
& " incompatible with ZLib version " & Version);
|
||||
end if;
|
||||
end Check_Version;
|
||||
|
||||
begin
|
||||
case Header is
|
||||
when None =>
|
||||
Check_Version;
|
||||
|
||||
-- Inflate data without headers determined
|
||||
-- by negative Win_Bits.
|
||||
|
||||
Win_Bits := -Win_Bits;
|
||||
when GZip =>
|
||||
Check_Version;
|
||||
|
||||
-- Inflate gzip data defined by flag 16.
|
||||
|
||||
Win_Bits := Win_Bits + 16;
|
||||
when Auto =>
|
||||
Check_Version;
|
||||
|
||||
-- Inflate with automatic detection
|
||||
-- of gzip or native header defined by flag 32.
|
||||
|
||||
Win_Bits := Win_Bits + 32;
|
||||
when Default => null;
|
||||
end case;
|
||||
|
||||
Filter.Strm := new Z_Stream;
|
||||
Filter.Compression := False;
|
||||
Filter.Stream_End := False;
|
||||
Filter.Opened := True;
|
||||
Filter.Header := Header;
|
||||
|
||||
if Thin.Inflate_Init
|
||||
(To_Thin_Access (Filter.Strm), Win_Bits) /= Thin.Z_OK
|
||||
then
|
||||
Raise_Error (Filter.Strm.all);
|
||||
end if;
|
||||
end Inflate_Init;
|
||||
|
||||
-----------------
|
||||
-- Raise_Error --
|
||||
-----------------
|
||||
|
||||
procedure Raise_Error (Message : String) is
|
||||
begin
|
||||
Ada.Exceptions.Raise_Exception (ZLib_Error'Identity, Message);
|
||||
end Raise_Error;
|
||||
|
||||
procedure Raise_Error (Stream : Z_Stream) is
|
||||
begin
|
||||
Raise_Error (Last_Error_Message (Stream));
|
||||
end Raise_Error;
|
||||
|
||||
----------
|
||||
-- Read --
|
||||
----------
|
||||
|
||||
procedure Read
|
||||
(Filter : in out Filter_Type;
|
||||
Item : out Ada.Streams.Stream_Element_Array;
|
||||
Last : out Ada.Streams.Stream_Element_Offset)
|
||||
is
|
||||
In_Last : Stream_Element_Offset;
|
||||
Item_First : Ada.Streams.Stream_Element_Offset := Item'First;
|
||||
|
||||
begin
|
||||
pragma Assert (Rest_First in Buffer'First .. Buffer'Last + 1);
|
||||
|
||||
loop
|
||||
if Rest_First > Buffer'Last then
|
||||
Read (Buffer, Rest_Last);
|
||||
Rest_First := Buffer'First;
|
||||
end if;
|
||||
|
||||
pragma Assert (Rest_Last in Buffer'First - 1 .. Buffer'Last);
|
||||
|
||||
Translate
|
||||
(Filter => Filter,
|
||||
In_Data => Buffer (Rest_First .. Rest_Last),
|
||||
In_Last => In_Last,
|
||||
Out_Data => Item (Item_First .. Item'Last),
|
||||
Out_Last => Last,
|
||||
Flush => Flush_Finish (Rest_Last < Rest_First));
|
||||
|
||||
Rest_First := In_Last + 1;
|
||||
|
||||
exit when Last = Item'Last or else Stream_End (Filter);
|
||||
|
||||
Item_First := Last + 1;
|
||||
end loop;
|
||||
end Read;
|
||||
|
||||
----------------
|
||||
-- Stream_End --
|
||||
----------------
|
||||
|
||||
function Stream_End (Filter : in Filter_Type) return Boolean is
|
||||
begin
|
||||
if Filter.Header = GZip and Filter.Compression then
|
||||
return Filter.Stream_End
|
||||
and then Filter.Offset = Footer_Array'Last + 1;
|
||||
else
|
||||
return Filter.Stream_End;
|
||||
end if;
|
||||
end Stream_End;
|
||||
|
||||
--------------
|
||||
-- Total_In --
|
||||
--------------
|
||||
|
||||
function Total_In (Filter : in Filter_Type) return Count is
|
||||
begin
|
||||
return Count (Thin.Total_In (To_Thin_Access (Filter.Strm).all));
|
||||
end Total_In;
|
||||
|
||||
---------------
|
||||
-- Total_Out --
|
||||
---------------
|
||||
|
||||
function Total_Out (Filter : in Filter_Type) return Count is
|
||||
begin
|
||||
return Count (Thin.Total_Out (To_Thin_Access (Filter.Strm).all));
|
||||
end Total_Out;
|
||||
|
||||
---------------
|
||||
-- Translate --
|
||||
---------------
|
||||
|
||||
procedure Translate
|
||||
(Filter : in out Filter_Type;
|
||||
In_Data : in Ada.Streams.Stream_Element_Array;
|
||||
In_Last : out Ada.Streams.Stream_Element_Offset;
|
||||
Out_Data : out Ada.Streams.Stream_Element_Array;
|
||||
Out_Last : out Ada.Streams.Stream_Element_Offset;
|
||||
Flush : in Flush_Mode) is
|
||||
begin
|
||||
if Filter.Header = GZip and then Filter.Compression then
|
||||
Translate_GZip
|
||||
(Filter => Filter,
|
||||
In_Data => In_Data,
|
||||
In_Last => In_Last,
|
||||
Out_Data => Out_Data,
|
||||
Out_Last => Out_Last,
|
||||
Flush => Flush);
|
||||
else
|
||||
Translate_Auto
|
||||
(Filter => Filter,
|
||||
In_Data => In_Data,
|
||||
In_Last => In_Last,
|
||||
Out_Data => Out_Data,
|
||||
Out_Last => Out_Last,
|
||||
Flush => Flush);
|
||||
end if;
|
||||
end Translate;
|
||||
|
||||
--------------------
|
||||
-- Translate_Auto --
|
||||
--------------------
|
||||
|
||||
procedure Translate_Auto
|
||||
(Filter : in out Filter_Type;
|
||||
In_Data : in Ada.Streams.Stream_Element_Array;
|
||||
In_Last : out Ada.Streams.Stream_Element_Offset;
|
||||
Out_Data : out Ada.Streams.Stream_Element_Array;
|
||||
Out_Last : out Ada.Streams.Stream_Element_Offset;
|
||||
Flush : in Flush_Mode)
|
||||
is
|
||||
use type Thin.Int;
|
||||
Code : Thin.Int;
|
||||
|
||||
begin
|
||||
if Filter.Opened = False then
|
||||
raise ZLib_Error;
|
||||
end if;
|
||||
|
||||
if Out_Data'Length = 0 then
|
||||
raise Constraint_Error;
|
||||
end if;
|
||||
|
||||
Set_Out (Filter.Strm.all, Out_Data'Address, Out_Data'Length);
|
||||
Set_In (Filter.Strm.all, In_Data'Address, In_Data'Length);
|
||||
|
||||
Code := Flate (Filter.Compression).Step
|
||||
(To_Thin_Access (Filter.Strm),
|
||||
Thin.Int (Flush));
|
||||
|
||||
if Code = Thin.Z_STREAM_END then
|
||||
Filter.Stream_End := True;
|
||||
else
|
||||
Check_Error (Filter.Strm.all, Code);
|
||||
end if;
|
||||
|
||||
In_Last := In_Data'Last
|
||||
- Stream_Element_Offset (Avail_In (Filter.Strm.all));
|
||||
Out_Last := Out_Data'Last
|
||||
- Stream_Element_Offset (Avail_Out (Filter.Strm.all));
|
||||
|
||||
end Translate_Auto;
|
||||
|
||||
--------------------
|
||||
-- Translate_GZip --
|
||||
--------------------
|
||||
|
||||
procedure Translate_GZip
|
||||
(Filter : in out Filter_Type;
|
||||
In_Data : in Ada.Streams.Stream_Element_Array;
|
||||
In_Last : out Ada.Streams.Stream_Element_Offset;
|
||||
Out_Data : out Ada.Streams.Stream_Element_Array;
|
||||
Out_Last : out Ada.Streams.Stream_Element_Offset;
|
||||
Flush : in Flush_Mode)
|
||||
is
|
||||
Out_First : Stream_Element_Offset;
|
||||
|
||||
procedure Add_Data (Data : in Stream_Element_Array);
|
||||
-- Add data to stream from the Filter.Offset till necessary,
|
||||
-- used for add gzip headr/footer.
|
||||
|
||||
procedure Put_32
|
||||
(Item : in out Stream_Element_Array;
|
||||
Data : in Unsigned_32);
|
||||
pragma Inline (Put_32);
|
||||
|
||||
--------------
|
||||
-- Add_Data --
|
||||
--------------
|
||||
|
||||
procedure Add_Data (Data : in Stream_Element_Array) is
|
||||
Data_First : Stream_Element_Offset renames Filter.Offset;
|
||||
Data_Last : Stream_Element_Offset;
|
||||
Data_Len : Stream_Element_Offset; -- -1
|
||||
Out_Len : Stream_Element_Offset; -- -1
|
||||
begin
|
||||
Out_First := Out_Last + 1;
|
||||
|
||||
if Data_First > Data'Last then
|
||||
return;
|
||||
end if;
|
||||
|
||||
Data_Len := Data'Last - Data_First;
|
||||
Out_Len := Out_Data'Last - Out_First;
|
||||
|
||||
if Data_Len <= Out_Len then
|
||||
Out_Last := Out_First + Data_Len;
|
||||
Data_Last := Data'Last;
|
||||
else
|
||||
Out_Last := Out_Data'Last;
|
||||
Data_Last := Data_First + Out_Len;
|
||||
end if;
|
||||
|
||||
Out_Data (Out_First .. Out_Last) := Data (Data_First .. Data_Last);
|
||||
|
||||
Data_First := Data_Last + 1;
|
||||
Out_First := Out_Last + 1;
|
||||
end Add_Data;
|
||||
|
||||
------------
|
||||
-- Put_32 --
|
||||
------------
|
||||
|
||||
procedure Put_32
|
||||
(Item : in out Stream_Element_Array;
|
||||
Data : in Unsigned_32)
|
||||
is
|
||||
D : Unsigned_32 := Data;
|
||||
begin
|
||||
for J in Item'First .. Item'First + 3 loop
|
||||
Item (J) := Stream_Element (D and 16#FF#);
|
||||
D := Shift_Right (D, 8);
|
||||
end loop;
|
||||
end Put_32;
|
||||
|
||||
begin
|
||||
Out_Last := Out_Data'First - 1;
|
||||
|
||||
if not Filter.Stream_End then
|
||||
Add_Data (Simple_GZip_Header);
|
||||
|
||||
Translate_Auto
|
||||
(Filter => Filter,
|
||||
In_Data => In_Data,
|
||||
In_Last => In_Last,
|
||||
Out_Data => Out_Data (Out_First .. Out_Data'Last),
|
||||
Out_Last => Out_Last,
|
||||
Flush => Flush);
|
||||
|
||||
CRC32 (Filter.CRC, In_Data (In_Data'First .. In_Last));
|
||||
|
||||
end if;
|
||||
|
||||
if Filter.Stream_End and then Out_Last <= Out_Data'Last then
|
||||
-- This detection method would work only when
|
||||
-- Simple_GZip_Header'Last > Footer_Array'Last
|
||||
|
||||
if Filter.Offset = Simple_GZip_Header'Last + 1 then
|
||||
Filter.Offset := Footer_Array'First;
|
||||
end if;
|
||||
|
||||
declare
|
||||
Footer : Footer_Array;
|
||||
begin
|
||||
Put_32 (Footer, Filter.CRC);
|
||||
Put_32 (Footer (Footer'First + 4 .. Footer'Last),
|
||||
Unsigned_32 (Total_In (Filter)));
|
||||
Add_Data (Footer);
|
||||
end;
|
||||
end if;
|
||||
end Translate_GZip;
|
||||
|
||||
-------------
|
||||
-- Version --
|
||||
-------------
|
||||
|
||||
function Version return String is
|
||||
begin
|
||||
return Interfaces.C.Strings.Value (Thin.zlibVersion);
|
||||
end Version;
|
||||
|
||||
-----------
|
||||
-- Write --
|
||||
-----------
|
||||
|
||||
procedure Write
|
||||
(Filter : in out Filter_Type;
|
||||
Item : in Ada.Streams.Stream_Element_Array;
|
||||
Flush : in Flush_Mode)
|
||||
is
|
||||
Buffer : Stream_Element_Array (1 .. Buffer_Size);
|
||||
In_Last, Out_Last : Stream_Element_Offset;
|
||||
In_First : Stream_Element_Offset := Item'First;
|
||||
begin
|
||||
if Item'Length = 0 and Flush = No_Flush then
|
||||
return;
|
||||
end if;
|
||||
|
||||
loop
|
||||
Translate
|
||||
(Filter => Filter,
|
||||
In_Data => Item (In_First .. Item'Last),
|
||||
In_Last => In_Last,
|
||||
Out_Data => Buffer,
|
||||
Out_Last => Out_Last,
|
||||
Flush => Flush);
|
||||
|
||||
if Out_Last >= Buffer'First then
|
||||
Write (Buffer (1 .. Out_Last));
|
||||
end if;
|
||||
|
||||
exit when In_Last = Item'Last or Stream_End (Filter);
|
||||
|
||||
In_First := In_Last + 1;
|
||||
end loop;
|
||||
end Write;
|
||||
|
||||
end ZLib;
|
311
zlib/contrib/ada/zlib.ads
Normal file
311
zlib/contrib/ada/zlib.ads
Normal file
|
@ -0,0 +1,311 @@
|
|||
------------------------------------------------------------------------------
|
||||
-- ZLib for Ada thick binding. --
|
||||
-- --
|
||||
-- Copyright (C) 2002-2003 Dmitriy Anisimkov --
|
||||
-- --
|
||||
-- This library 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 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 --
|
||||
-- General Public License for more details. --
|
||||
-- --
|
||||
-- You should have received a copy of the GNU General Public License --
|
||||
-- along with this library; if not, write to the Free Software Foundation, --
|
||||
-- Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. --
|
||||
-- --
|
||||
-- As a special exception, if other files instantiate generics from this --
|
||||
-- unit, or you link this unit with other files to produce an executable, --
|
||||
-- this unit does not by itself cause the resulting executable to be --
|
||||
-- covered by the GNU General Public License. This exception does not --
|
||||
-- however invalidate any other reasons why the executable file might be --
|
||||
-- covered by the GNU Public License. --
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
-- $Id: zlib.ads,v 1.17 2003/08/12 13:19:07 vagul Exp $
|
||||
|
||||
with Ada.Streams;
|
||||
|
||||
with Interfaces;
|
||||
|
||||
package ZLib is
|
||||
|
||||
ZLib_Error : exception;
|
||||
|
||||
type Compression_Level is new Integer range -1 .. 9;
|
||||
|
||||
type Flush_Mode is private;
|
||||
|
||||
type Compression_Method is private;
|
||||
|
||||
type Window_Bits_Type is new Integer range 8 .. 15;
|
||||
|
||||
type Memory_Level_Type is new Integer range 1 .. 9;
|
||||
|
||||
type Unsigned_32 is new Interfaces.Unsigned_32;
|
||||
|
||||
type Strategy_Type is private;
|
||||
|
||||
type Header_Type is (None, Auto, Default, GZip);
|
||||
-- Header type usage have a some limitation for inflate.
|
||||
-- See comment for Inflate_Init.
|
||||
|
||||
subtype Count is Ada.Streams.Stream_Element_Count;
|
||||
|
||||
----------------------------------
|
||||
-- Compression method constants --
|
||||
----------------------------------
|
||||
|
||||
Deflated : constant Compression_Method;
|
||||
-- Only one method allowed in this ZLib version.
|
||||
|
||||
---------------------------------
|
||||
-- Compression level constants --
|
||||
---------------------------------
|
||||
|
||||
No_Compression : constant Compression_Level := 0;
|
||||
Best_Speed : constant Compression_Level := 1;
|
||||
Best_Compression : constant Compression_Level := 9;
|
||||
Default_Compression : constant Compression_Level := -1;
|
||||
|
||||
--------------------------
|
||||
-- Flush mode constants --
|
||||
--------------------------
|
||||
|
||||
No_Flush : constant Flush_Mode;
|
||||
-- Regular way for compression, no flush
|
||||
|
||||
Partial_Flush : constant Flush_Mode;
|
||||
-- will be removed, use Z_SYNC_FLUSH instead
|
||||
|
||||
Sync_Flush : constant Flush_Mode;
|
||||
-- all pending output is flushed to the output buffer and the output
|
||||
-- is aligned on a byte boundary, so that the decompressor can get all
|
||||
-- input data available so far. (In particular avail_in is zero after the
|
||||
-- call if enough output space has been provided before the call.)
|
||||
-- Flushing may degrade compression for some compression algorithms and so
|
||||
-- it should be used only when necessary.
|
||||
|
||||
Full_Flush : constant Flush_Mode;
|
||||
-- all output is flushed as with SYNC_FLUSH, and the compression state
|
||||
-- is reset so that decompression can restart from this point if previous
|
||||
-- compressed data has been damaged or if random access is desired. Using
|
||||
-- FULL_FLUSH too often can seriously degrade the compression.
|
||||
|
||||
Finish : constant Flush_Mode;
|
||||
-- Just for tell the compressor that input data is complete.
|
||||
|
||||
------------------------------------
|
||||
-- Compression strategy constants --
|
||||
------------------------------------
|
||||
|
||||
-- RLE stategy could be used only in version 1.2.0 and later.
|
||||
|
||||
Filtered : constant Strategy_Type;
|
||||
Huffman_Only : constant Strategy_Type;
|
||||
RLE : constant Strategy_Type;
|
||||
Default_Strategy : constant Strategy_Type;
|
||||
|
||||
Default_Buffer_Size : constant := 4096;
|
||||
|
||||
type Filter_Type is limited private;
|
||||
-- The filter is for compression and for decompression.
|
||||
-- The usage of the type is depend of its initialization.
|
||||
|
||||
function Version return String;
|
||||
pragma Inline (Version);
|
||||
-- Return string representation of the ZLib version.
|
||||
|
||||
procedure Deflate_Init
|
||||
(Filter : in out Filter_Type;
|
||||
Level : in Compression_Level := Default_Compression;
|
||||
Strategy : in Strategy_Type := Default_Strategy;
|
||||
Method : in Compression_Method := Deflated;
|
||||
Window_Bits : in Window_Bits_Type := 15;
|
||||
Memory_Level : in Memory_Level_Type := 8;
|
||||
Header : in Header_Type := Default);
|
||||
-- Compressor initialization.
|
||||
-- When Header parameter is Auto or Default, then default zlib header
|
||||
-- would be provided for compressed data.
|
||||
-- When Header is GZip, then gzip header would be set instead of
|
||||
-- default header.
|
||||
-- When Header is None, no header would be set for compressed data.
|
||||
|
||||
procedure Inflate_Init
|
||||
(Filter : in out Filter_Type;
|
||||
Window_Bits : in Window_Bits_Type := 15;
|
||||
Header : in Header_Type := Default);
|
||||
-- Decompressor initialization.
|
||||
-- Default header type mean that ZLib default header is expecting in the
|
||||
-- input compressed stream.
|
||||
-- Header type None mean that no header is expecting in the input stream.
|
||||
-- GZip header type mean that GZip header is expecting in the
|
||||
-- input compressed stream.
|
||||
-- Auto header type mean that header type (GZip or Native) would be
|
||||
-- detected automatically in the input stream.
|
||||
-- Note that header types parameter values None, GZip and Auto is
|
||||
-- supporting for inflate routine only in ZLib versions 1.2.0.2 and later.
|
||||
-- Deflate_Init is supporting all header types.
|
||||
|
||||
procedure Close
|
||||
(Filter : in out Filter_Type;
|
||||
Ignore_Error : in Boolean := False);
|
||||
-- Closing the compression or decompressor.
|
||||
-- If stream is closing before the complete and Ignore_Error is False,
|
||||
-- The exception would be raised.
|
||||
|
||||
generic
|
||||
with procedure Data_In
|
||||
(Item : out Ada.Streams.Stream_Element_Array;
|
||||
Last : out Ada.Streams.Stream_Element_Offset);
|
||||
with procedure Data_Out
|
||||
(Item : in Ada.Streams.Stream_Element_Array);
|
||||
procedure Generic_Translate
|
||||
(Filter : in out Filter_Type;
|
||||
In_Buffer_Size : in Integer := Default_Buffer_Size;
|
||||
Out_Buffer_Size : in Integer := Default_Buffer_Size);
|
||||
-- Compressing/decompressing data arrived from Data_In routine
|
||||
-- to the Data_Out routine. User should provide Data_In and Data_Out
|
||||
-- for compression/decompression data flow.
|
||||
-- Compression or decompression depend on initialization of Filter.
|
||||
|
||||
function Total_In (Filter : in Filter_Type) return Count;
|
||||
pragma Inline (Total_In);
|
||||
-- Return total number of input bytes read so far.
|
||||
|
||||
function Total_Out (Filter : in Filter_Type) return Count;
|
||||
pragma Inline (Total_Out);
|
||||
-- Return total number of bytes output so far.
|
||||
|
||||
function CRC32
|
||||
(CRC : in Unsigned_32;
|
||||
Data : in Ada.Streams.Stream_Element_Array)
|
||||
return Unsigned_32;
|
||||
pragma Inline (CRC32);
|
||||
-- Calculate CRC32, it could be necessary for make gzip format.
|
||||
|
||||
procedure CRC32
|
||||
(CRC : in out Unsigned_32;
|
||||
Data : in Ada.Streams.Stream_Element_Array);
|
||||
pragma Inline (CRC32);
|
||||
-- Calculate CRC32, it could be necessary for make gzip format.
|
||||
|
||||
-------------------------------------------------
|
||||
-- Below is more complex low level routines. --
|
||||
-------------------------------------------------
|
||||
|
||||
procedure Translate
|
||||
(Filter : in out Filter_Type;
|
||||
In_Data : in Ada.Streams.Stream_Element_Array;
|
||||
In_Last : out Ada.Streams.Stream_Element_Offset;
|
||||
Out_Data : out Ada.Streams.Stream_Element_Array;
|
||||
Out_Last : out Ada.Streams.Stream_Element_Offset;
|
||||
Flush : in Flush_Mode);
|
||||
-- Compressing/decompressing the datas from In_Data buffer to the
|
||||
-- Out_Data buffer.
|
||||
-- In_Data is incoming data portion,
|
||||
-- In_Last is the index of last element from In_Data accepted by the
|
||||
-- Filter.
|
||||
-- Out_Data is the buffer for output data from the filter.
|
||||
-- Out_Last is the last element of the received data from Filter.
|
||||
-- To tell the filter that incoming data is complete put the
|
||||
-- Flush parameter to FINISH.
|
||||
|
||||
function Stream_End (Filter : in Filter_Type) return Boolean;
|
||||
pragma Inline (Stream_End);
|
||||
-- Return the true when the stream is complete.
|
||||
|
||||
procedure Flush
|
||||
(Filter : in out Filter_Type;
|
||||
Out_Data : out Ada.Streams.Stream_Element_Array;
|
||||
Out_Last : out Ada.Streams.Stream_Element_Offset;
|
||||
Flush : in Flush_Mode);
|
||||
pragma Inline (Flush);
|
||||
-- Flushing the data from the compressor.
|
||||
|
||||
generic
|
||||
with procedure Write
|
||||
(Item : in Ada.Streams.Stream_Element_Array);
|
||||
-- User should provide this routine for accept
|
||||
-- compressed/decompressed data.
|
||||
|
||||
Buffer_Size : in Ada.Streams.Stream_Element_Offset
|
||||
:= Default_Buffer_Size;
|
||||
-- Buffer size for Write user routine.
|
||||
|
||||
procedure Write
|
||||
(Filter : in out Filter_Type;
|
||||
Item : in Ada.Streams.Stream_Element_Array;
|
||||
Flush : in Flush_Mode);
|
||||
-- Compressing/Decompressing data from Item to the
|
||||
-- generic parameter procedure Write.
|
||||
-- Output buffer size could be set in Buffer_Size generic parameter.
|
||||
|
||||
generic
|
||||
with procedure Read
|
||||
(Item : out Ada.Streams.Stream_Element_Array;
|
||||
Last : out Ada.Streams.Stream_Element_Offset);
|
||||
-- User should provide data for compression/decompression
|
||||
-- thru this routine.
|
||||
|
||||
Buffer : in out Ada.Streams.Stream_Element_Array;
|
||||
-- Buffer for keep remaining data from the previous
|
||||
-- back read.
|
||||
|
||||
Rest_First, Rest_Last : in out Ada.Streams.Stream_Element_Offset;
|
||||
-- Rest_First have to be initialized to Buffer'Last + 1
|
||||
-- before usage.
|
||||
|
||||
procedure Read
|
||||
(Filter : in out Filter_Type;
|
||||
Item : out Ada.Streams.Stream_Element_Array;
|
||||
Last : out Ada.Streams.Stream_Element_Offset);
|
||||
-- Compressing/Decompressing data from generic parameter
|
||||
-- procedure Read to the Item.
|
||||
-- User should provide Buffer for the operation
|
||||
-- and Rest_First variable first time initialized to the Buffer'Last + 1.
|
||||
|
||||
private
|
||||
|
||||
use Ada.Streams;
|
||||
|
||||
type Flush_Mode is new Integer range 0 .. 4;
|
||||
|
||||
type Compression_Method is new Integer range 8 .. 8;
|
||||
|
||||
type Strategy_Type is new Integer range 0 .. 3;
|
||||
|
||||
No_Flush : constant Flush_Mode := 0;
|
||||
Sync_Flush : constant Flush_Mode := 2;
|
||||
Full_Flush : constant Flush_Mode := 3;
|
||||
Finish : constant Flush_Mode := 4;
|
||||
Partial_Flush : constant Flush_Mode := 1;
|
||||
-- will be removed, use Z_SYNC_FLUSH instead
|
||||
|
||||
Filtered : constant Strategy_Type := 1;
|
||||
Huffman_Only : constant Strategy_Type := 2;
|
||||
RLE : constant Strategy_Type := 3;
|
||||
Default_Strategy : constant Strategy_Type := 0;
|
||||
|
||||
Deflated : constant Compression_Method := 8;
|
||||
|
||||
type Z_Stream;
|
||||
|
||||
type Z_Stream_Access is access all Z_Stream;
|
||||
|
||||
type Filter_Type is record
|
||||
Strm : Z_Stream_Access;
|
||||
Compression : Boolean;
|
||||
Stream_End : Boolean;
|
||||
Header : Header_Type;
|
||||
CRC : Unsigned_32;
|
||||
Offset : Stream_Element_Offset;
|
||||
-- Offset for gzip header/footer output.
|
||||
|
||||
Opened : Boolean := False;
|
||||
end record;
|
||||
|
||||
end ZLib;
|
21
zlib/contrib/ada/zlib.gpr
Normal file
21
zlib/contrib/ada/zlib.gpr
Normal file
|
@ -0,0 +1,21 @@
|
|||
project Zlib is
|
||||
|
||||
for Languages use ("Ada");
|
||||
for Source_Dirs use (".");
|
||||
for Object_Dir use ".";
|
||||
for Main use ("test.adb", "mtest.adb", "read.adb");
|
||||
|
||||
package Compiler is
|
||||
for Default_Switches ("ada") use ("-gnatwbcfilopru", "-gnatVcdfimorst", "-gnatyabcefhiklmnoprst");
|
||||
end Compiler;
|
||||
|
||||
package Linker is
|
||||
for Default_Switches ("ada") use ("-lz");
|
||||
end Linker;
|
||||
|
||||
package Builder is
|
||||
for Default_Switches ("ada") use ("-s", "-gnatQ");
|
||||
end Builder;
|
||||
|
||||
end Zlib;
|
||||
|
43
zlib/contrib/asm586/README.586
Normal file
43
zlib/contrib/asm586/README.586
Normal file
|
@ -0,0 +1,43 @@
|
|||
This is a patched version of zlib modified to use
|
||||
Pentium-optimized assembly code in the deflation algorithm. The files
|
||||
changed/added by this patch are:
|
||||
|
||||
README.586
|
||||
match.S
|
||||
|
||||
The effectiveness of these modifications is a bit marginal, as the the
|
||||
program's bottleneck seems to be mostly L1-cache contention, for which
|
||||
there is no real way to work around without rewriting the basic
|
||||
algorithm. The speedup on average is around 5-10% (which is generally
|
||||
less than the amount of variance between subsequent executions).
|
||||
However, when used at level 9 compression, the cache contention can
|
||||
drop enough for the assembly version to achieve 10-20% speedup (and
|
||||
sometimes more, depending on the amount of overall redundancy in the
|
||||
files). Even here, though, cache contention can still be the limiting
|
||||
factor, depending on the nature of the program using the zlib library.
|
||||
This may also mean that better improvements will be seen on a Pentium
|
||||
with MMX, which suffers much less from L1-cache contention, but I have
|
||||
not yet verified this.
|
||||
|
||||
Note that this code has been tailored for the Pentium in particular,
|
||||
and will not perform well on the Pentium Pro (due to the use of a
|
||||
partial register in the inner loop).
|
||||
|
||||
If you are using an assembler other than GNU as, you will have to
|
||||
translate match.S to use your assembler's syntax. (Have fun.)
|
||||
|
||||
Brian Raiter
|
||||
breadbox@muppetlabs.com
|
||||
April, 1998
|
||||
|
||||
|
||||
Added for zlib 1.1.3:
|
||||
|
||||
The patches come from
|
||||
http://www.muppetlabs.com/~breadbox/software/assembly.html
|
||||
|
||||
To compile zlib with this asm file, copy match.S to the zlib directory
|
||||
then do:
|
||||
|
||||
CFLAGS="-O3 -DASMV" ./configure
|
||||
make OBJA=match.o
|
354
zlib/contrib/asm586/match.S
Normal file
354
zlib/contrib/asm586/match.S
Normal file
|
@ -0,0 +1,354 @@
|
|||
/* match.s -- Pentium-optimized version of longest_match()
|
||||
* Written for zlib 1.1.2
|
||||
* Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License.
|
||||
*/
|
||||
|
||||
#ifndef NO_UNDERLINE
|
||||
#define match_init _match_init
|
||||
#define longest_match _longest_match
|
||||
#endif
|
||||
|
||||
#define MAX_MATCH (258)
|
||||
#define MIN_MATCH (3)
|
||||
#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1)
|
||||
#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7)
|
||||
|
||||
/* stack frame offsets */
|
||||
|
||||
#define wmask 0 /* local copy of s->wmask */
|
||||
#define window 4 /* local copy of s->window */
|
||||
#define windowbestlen 8 /* s->window + bestlen */
|
||||
#define chainlenscanend 12 /* high word: current chain len */
|
||||
/* low word: last bytes sought */
|
||||
#define scanstart 16 /* first two bytes of string */
|
||||
#define scanalign 20 /* dword-misalignment of string */
|
||||
#define nicematch 24 /* a good enough match size */
|
||||
#define bestlen 28 /* size of best match so far */
|
||||
#define scan 32 /* ptr to string wanting match */
|
||||
|
||||
#define LocalVarsSize (36)
|
||||
/* saved ebx 36 */
|
||||
/* saved edi 40 */
|
||||
/* saved esi 44 */
|
||||
/* saved ebp 48 */
|
||||
/* return address 52 */
|
||||
#define deflatestate 56 /* the function arguments */
|
||||
#define curmatch 60
|
||||
|
||||
/* Offsets for fields in the deflate_state structure. These numbers
|
||||
* are calculated from the definition of deflate_state, with the
|
||||
* assumption that the compiler will dword-align the fields. (Thus,
|
||||
* changing the definition of deflate_state could easily cause this
|
||||
* program to crash horribly, without so much as a warning at
|
||||
* compile time. Sigh.)
|
||||
*/
|
||||
#define dsWSize 36
|
||||
#define dsWMask 44
|
||||
#define dsWindow 48
|
||||
#define dsPrev 56
|
||||
#define dsMatchLen 88
|
||||
#define dsPrevMatch 92
|
||||
#define dsStrStart 100
|
||||
#define dsMatchStart 104
|
||||
#define dsLookahead 108
|
||||
#define dsPrevLen 112
|
||||
#define dsMaxChainLen 116
|
||||
#define dsGoodMatch 132
|
||||
#define dsNiceMatch 136
|
||||
|
||||
|
||||
.file "match.S"
|
||||
|
||||
.globl match_init, longest_match
|
||||
|
||||
.text
|
||||
|
||||
/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */
|
||||
|
||||
longest_match:
|
||||
|
||||
/* Save registers that the compiler may be using, and adjust %esp to */
|
||||
/* make room for our stack frame. */
|
||||
|
||||
pushl %ebp
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
pushl %ebx
|
||||
subl $LocalVarsSize, %esp
|
||||
|
||||
/* Retrieve the function arguments. %ecx will hold cur_match */
|
||||
/* throughout the entire function. %edx will hold the pointer to the */
|
||||
/* deflate_state structure during the function's setup (before */
|
||||
/* entering the main loop). */
|
||||
|
||||
movl deflatestate(%esp), %edx
|
||||
movl curmatch(%esp), %ecx
|
||||
|
||||
/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */
|
||||
|
||||
movl dsNiceMatch(%edx), %eax
|
||||
movl dsLookahead(%edx), %ebx
|
||||
cmpl %eax, %ebx
|
||||
jl LookaheadLess
|
||||
movl %eax, %ebx
|
||||
LookaheadLess: movl %ebx, nicematch(%esp)
|
||||
|
||||
/* register Bytef *scan = s->window + s->strstart; */
|
||||
|
||||
movl dsWindow(%edx), %esi
|
||||
movl %esi, window(%esp)
|
||||
movl dsStrStart(%edx), %ebp
|
||||
lea (%esi,%ebp), %edi
|
||||
movl %edi, scan(%esp)
|
||||
|
||||
/* Determine how many bytes the scan ptr is off from being */
|
||||
/* dword-aligned. */
|
||||
|
||||
movl %edi, %eax
|
||||
negl %eax
|
||||
andl $3, %eax
|
||||
movl %eax, scanalign(%esp)
|
||||
|
||||
/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */
|
||||
/* s->strstart - (IPos)MAX_DIST(s) : NIL; */
|
||||
|
||||
movl dsWSize(%edx), %eax
|
||||
subl $MIN_LOOKAHEAD, %eax
|
||||
subl %eax, %ebp
|
||||
jg LimitPositive
|
||||
xorl %ebp, %ebp
|
||||
LimitPositive:
|
||||
|
||||
/* unsigned chain_length = s->max_chain_length; */
|
||||
/* if (s->prev_length >= s->good_match) { */
|
||||
/* chain_length >>= 2; */
|
||||
/* } */
|
||||
|
||||
movl dsPrevLen(%edx), %eax
|
||||
movl dsGoodMatch(%edx), %ebx
|
||||
cmpl %ebx, %eax
|
||||
movl dsMaxChainLen(%edx), %ebx
|
||||
jl LastMatchGood
|
||||
shrl $2, %ebx
|
||||
LastMatchGood:
|
||||
|
||||
/* chainlen is decremented once beforehand so that the function can */
|
||||
/* use the sign flag instead of the zero flag for the exit test. */
|
||||
/* It is then shifted into the high word, to make room for the scanend */
|
||||
/* scanend value, which it will always accompany. */
|
||||
|
||||
decl %ebx
|
||||
shll $16, %ebx
|
||||
|
||||
/* int best_len = s->prev_length; */
|
||||
|
||||
movl dsPrevLen(%edx), %eax
|
||||
movl %eax, bestlen(%esp)
|
||||
|
||||
/* Store the sum of s->window + best_len in %esi locally, and in %esi. */
|
||||
|
||||
addl %eax, %esi
|
||||
movl %esi, windowbestlen(%esp)
|
||||
|
||||
/* register ush scan_start = *(ushf*)scan; */
|
||||
/* register ush scan_end = *(ushf*)(scan+best_len-1); */
|
||||
|
||||
movw (%edi), %bx
|
||||
movw %bx, scanstart(%esp)
|
||||
movw -1(%edi,%eax), %bx
|
||||
movl %ebx, chainlenscanend(%esp)
|
||||
|
||||
/* Posf *prev = s->prev; */
|
||||
/* uInt wmask = s->w_mask; */
|
||||
|
||||
movl dsPrev(%edx), %edi
|
||||
movl dsWMask(%edx), %edx
|
||||
mov %edx, wmask(%esp)
|
||||
|
||||
/* Jump into the main loop. */
|
||||
|
||||
jmp LoopEntry
|
||||
|
||||
.balign 16
|
||||
|
||||
/* do {
|
||||
* match = s->window + cur_match;
|
||||
* if (*(ushf*)(match+best_len-1) != scan_end ||
|
||||
* *(ushf*)match != scan_start) continue;
|
||||
* [...]
|
||||
* } while ((cur_match = prev[cur_match & wmask]) > limit
|
||||
* && --chain_length != 0);
|
||||
*
|
||||
* Here is the inner loop of the function. The function will spend the
|
||||
* majority of its time in this loop, and majority of that time will
|
||||
* be spent in the first ten instructions.
|
||||
*
|
||||
* Within this loop:
|
||||
* %ebx = chainlenscanend - i.e., ((chainlen << 16) | scanend)
|
||||
* %ecx = curmatch
|
||||
* %edx = curmatch & wmask
|
||||
* %esi = windowbestlen - i.e., (window + bestlen)
|
||||
* %edi = prev
|
||||
* %ebp = limit
|
||||
*
|
||||
* Two optimization notes on the choice of instructions:
|
||||
*
|
||||
* The first instruction uses a 16-bit address, which costs an extra,
|
||||
* unpairable cycle. This is cheaper than doing a 32-bit access and
|
||||
* zeroing the high word, due to the 3-cycle misalignment penalty which
|
||||
* would occur half the time. This also turns out to be cheaper than
|
||||
* doing two separate 8-bit accesses, as the memory is so rarely in the
|
||||
* L1 cache.
|
||||
*
|
||||
* The window buffer, however, apparently spends a lot of time in the
|
||||
* cache, and so it is faster to retrieve the word at the end of the
|
||||
* match string with two 8-bit loads. The instructions that test the
|
||||
* word at the beginning of the match string, however, are executed
|
||||
* much less frequently, and there it was cheaper to use 16-bit
|
||||
* instructions, which avoided the necessity of saving off and
|
||||
* subsequently reloading one of the other registers.
|
||||
*/
|
||||
LookupLoop:
|
||||
/* 1 U & V */
|
||||
movw (%edi,%edx,2), %cx /* 2 U pipe */
|
||||
movl wmask(%esp), %edx /* 2 V pipe */
|
||||
cmpl %ebp, %ecx /* 3 U pipe */
|
||||
jbe LeaveNow /* 3 V pipe */
|
||||
subl $0x00010000, %ebx /* 4 U pipe */
|
||||
js LeaveNow /* 4 V pipe */
|
||||
LoopEntry: movb -1(%esi,%ecx), %al /* 5 U pipe */
|
||||
andl %ecx, %edx /* 5 V pipe */
|
||||
cmpb %bl, %al /* 6 U pipe */
|
||||
jnz LookupLoop /* 6 V pipe */
|
||||
movb (%esi,%ecx), %ah
|
||||
cmpb %bh, %ah
|
||||
jnz LookupLoop
|
||||
movl window(%esp), %eax
|
||||
movw (%eax,%ecx), %ax
|
||||
cmpw scanstart(%esp), %ax
|
||||
jnz LookupLoop
|
||||
|
||||
/* Store the current value of chainlen. */
|
||||
|
||||
movl %ebx, chainlenscanend(%esp)
|
||||
|
||||
/* Point %edi to the string under scrutiny, and %esi to the string we */
|
||||
/* are hoping to match it up with. In actuality, %esi and %edi are */
|
||||
/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */
|
||||
/* initialized to -(MAX_MATCH_8 - scanalign). */
|
||||
|
||||
movl window(%esp), %esi
|
||||
movl scan(%esp), %edi
|
||||
addl %ecx, %esi
|
||||
movl scanalign(%esp), %eax
|
||||
movl $(-MAX_MATCH_8), %edx
|
||||
lea MAX_MATCH_8(%edi,%eax), %edi
|
||||
lea MAX_MATCH_8(%esi,%eax), %esi
|
||||
|
||||
/* Test the strings for equality, 8 bytes at a time. At the end,
|
||||
* adjust %edx so that it is offset to the exact byte that mismatched.
|
||||
*
|
||||
* We already know at this point that the first three bytes of the
|
||||
* strings match each other, and they can be safely passed over before
|
||||
* starting the compare loop. So what this code does is skip over 0-3
|
||||
* bytes, as much as necessary in order to dword-align the %edi
|
||||
* pointer. (%esi will still be misaligned three times out of four.)
|
||||
*
|
||||
* It should be confessed that this loop usually does not represent
|
||||
* much of the total running time. Replacing it with a more
|
||||
* straightforward "rep cmpsb" would not drastically degrade
|
||||
* performance.
|
||||
*/
|
||||
LoopCmps:
|
||||
movl (%esi,%edx), %eax
|
||||
movl (%edi,%edx), %ebx
|
||||
xorl %ebx, %eax
|
||||
jnz LeaveLoopCmps
|
||||
movl 4(%esi,%edx), %eax
|
||||
movl 4(%edi,%edx), %ebx
|
||||
xorl %ebx, %eax
|
||||
jnz LeaveLoopCmps4
|
||||
addl $8, %edx
|
||||
jnz LoopCmps
|
||||
jmp LenMaximum
|
||||
LeaveLoopCmps4: addl $4, %edx
|
||||
LeaveLoopCmps: testl $0x0000FFFF, %eax
|
||||
jnz LenLower
|
||||
addl $2, %edx
|
||||
shrl $16, %eax
|
||||
LenLower: subb $1, %al
|
||||
adcl $0, %edx
|
||||
|
||||
/* Calculate the length of the match. If it is longer than MAX_MATCH, */
|
||||
/* then automatically accept it as the best possible match and leave. */
|
||||
|
||||
lea (%edi,%edx), %eax
|
||||
movl scan(%esp), %edi
|
||||
subl %edi, %eax
|
||||
cmpl $MAX_MATCH, %eax
|
||||
jge LenMaximum
|
||||
|
||||
/* If the length of the match is not longer than the best match we */
|
||||
/* have so far, then forget it and return to the lookup loop. */
|
||||
|
||||
movl deflatestate(%esp), %edx
|
||||
movl bestlen(%esp), %ebx
|
||||
cmpl %ebx, %eax
|
||||
jg LongerMatch
|
||||
movl chainlenscanend(%esp), %ebx
|
||||
movl windowbestlen(%esp), %esi
|
||||
movl dsPrev(%edx), %edi
|
||||
movl wmask(%esp), %edx
|
||||
andl %ecx, %edx
|
||||
jmp LookupLoop
|
||||
|
||||
/* s->match_start = cur_match; */
|
||||
/* best_len = len; */
|
||||
/* if (len >= nice_match) break; */
|
||||
/* scan_end = *(ushf*)(scan+best_len-1); */
|
||||
|
||||
LongerMatch: movl nicematch(%esp), %ebx
|
||||
movl %eax, bestlen(%esp)
|
||||
movl %ecx, dsMatchStart(%edx)
|
||||
cmpl %ebx, %eax
|
||||
jge LeaveNow
|
||||
movl window(%esp), %esi
|
||||
addl %eax, %esi
|
||||
movl %esi, windowbestlen(%esp)
|
||||
movl chainlenscanend(%esp), %ebx
|
||||
movw -1(%edi,%eax), %bx
|
||||
movl dsPrev(%edx), %edi
|
||||
movl %ebx, chainlenscanend(%esp)
|
||||
movl wmask(%esp), %edx
|
||||
andl %ecx, %edx
|
||||
jmp LookupLoop
|
||||
|
||||
/* Accept the current string, with the maximum possible length. */
|
||||
|
||||
LenMaximum: movl deflatestate(%esp), %edx
|
||||
movl $MAX_MATCH, bestlen(%esp)
|
||||
movl %ecx, dsMatchStart(%edx)
|
||||
|
||||
/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */
|
||||
/* return s->lookahead; */
|
||||
|
||||
LeaveNow:
|
||||
movl deflatestate(%esp), %edx
|
||||
movl bestlen(%esp), %ebx
|
||||
movl dsLookahead(%edx), %eax
|
||||
cmpl %eax, %ebx
|
||||
jg LookaheadRet
|
||||
movl %ebx, %eax
|
||||
LookaheadRet:
|
||||
|
||||
/* Restore the stack and return from whence we came. */
|
||||
|
||||
addl $LocalVarsSize, %esp
|
||||
popl %ebx
|
||||
popl %esi
|
||||
popl %edi
|
||||
popl %ebp
|
||||
match_init: ret
|
34
zlib/contrib/asm686/README.686
Normal file
34
zlib/contrib/asm686/README.686
Normal file
|
@ -0,0 +1,34 @@
|
|||
This is a patched version of zlib, modified to use
|
||||
Pentium-Pro-optimized assembly code in the deflation algorithm. The
|
||||
files changed/added by this patch are:
|
||||
|
||||
README.686
|
||||
match.S
|
||||
|
||||
The speedup that this patch provides varies, depending on whether the
|
||||
compiler used to build the original version of zlib falls afoul of the
|
||||
PPro's speed traps. My own tests show a speedup of around 10-20% at
|
||||
the default compression level, and 20-30% using -9, against a version
|
||||
compiled using gcc 2.7.2.3. Your mileage may vary.
|
||||
|
||||
Note that this code has been tailored for the PPro/PII in particular,
|
||||
and will not perform particuarly well on a Pentium.
|
||||
|
||||
If you are using an assembler other than GNU as, you will have to
|
||||
translate match.S to use your assembler's syntax. (Have fun.)
|
||||
|
||||
Brian Raiter
|
||||
breadbox@muppetlabs.com
|
||||
April, 1998
|
||||
|
||||
|
||||
Added for zlib 1.1.3:
|
||||
|
||||
The patches come from
|
||||
http://www.muppetlabs.com/~breadbox/software/assembly.html
|
||||
|
||||
To compile zlib with this asm file, copy match.S to the zlib directory
|
||||
then do:
|
||||
|
||||
CFLAGS="-O3 -DASMV" ./configure
|
||||
make OBJA=match.o
|
327
zlib/contrib/asm686/match.S
Normal file
327
zlib/contrib/asm686/match.S
Normal file
|
@ -0,0 +1,327 @@
|
|||
/* match.s -- Pentium-Pro-optimized version of longest_match()
|
||||
* Written for zlib 1.1.2
|
||||
* Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License.
|
||||
*/
|
||||
|
||||
#ifndef NO_UNDERLINE
|
||||
#define match_init _match_init
|
||||
#define longest_match _longest_match
|
||||
#endif
|
||||
|
||||
#define MAX_MATCH (258)
|
||||
#define MIN_MATCH (3)
|
||||
#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1)
|
||||
#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7)
|
||||
|
||||
/* stack frame offsets */
|
||||
|
||||
#define chainlenwmask 0 /* high word: current chain len */
|
||||
/* low word: s->wmask */
|
||||
#define window 4 /* local copy of s->window */
|
||||
#define windowbestlen 8 /* s->window + bestlen */
|
||||
#define scanstart 16 /* first two bytes of string */
|
||||
#define scanend 12 /* last two bytes of string */
|
||||
#define scanalign 20 /* dword-misalignment of string */
|
||||
#define nicematch 24 /* a good enough match size */
|
||||
#define bestlen 28 /* size of best match so far */
|
||||
#define scan 32 /* ptr to string wanting match */
|
||||
|
||||
#define LocalVarsSize (36)
|
||||
/* saved ebx 36 */
|
||||
/* saved edi 40 */
|
||||
/* saved esi 44 */
|
||||
/* saved ebp 48 */
|
||||
/* return address 52 */
|
||||
#define deflatestate 56 /* the function arguments */
|
||||
#define curmatch 60
|
||||
|
||||
/* Offsets for fields in the deflate_state structure. These numbers
|
||||
* are calculated from the definition of deflate_state, with the
|
||||
* assumption that the compiler will dword-align the fields. (Thus,
|
||||
* changing the definition of deflate_state could easily cause this
|
||||
* program to crash horribly, without so much as a warning at
|
||||
* compile time. Sigh.)
|
||||
*/
|
||||
#define dsWSize 36
|
||||
#define dsWMask 44
|
||||
#define dsWindow 48
|
||||
#define dsPrev 56
|
||||
#define dsMatchLen 88
|
||||
#define dsPrevMatch 92
|
||||
#define dsStrStart 100
|
||||
#define dsMatchStart 104
|
||||
#define dsLookahead 108
|
||||
#define dsPrevLen 112
|
||||
#define dsMaxChainLen 116
|
||||
#define dsGoodMatch 132
|
||||
#define dsNiceMatch 136
|
||||
|
||||
|
||||
.file "match.S"
|
||||
|
||||
.globl match_init, longest_match
|
||||
|
||||
.text
|
||||
|
||||
/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */
|
||||
|
||||
longest_match:
|
||||
|
||||
/* Save registers that the compiler may be using, and adjust %esp to */
|
||||
/* make room for our stack frame. */
|
||||
|
||||
pushl %ebp
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
pushl %ebx
|
||||
subl $LocalVarsSize, %esp
|
||||
|
||||
/* Retrieve the function arguments. %ecx will hold cur_match */
|
||||
/* throughout the entire function. %edx will hold the pointer to the */
|
||||
/* deflate_state structure during the function's setup (before */
|
||||
/* entering the main loop). */
|
||||
|
||||
movl deflatestate(%esp), %edx
|
||||
movl curmatch(%esp), %ecx
|
||||
|
||||
/* uInt wmask = s->w_mask; */
|
||||
/* unsigned chain_length = s->max_chain_length; */
|
||||
/* if (s->prev_length >= s->good_match) { */
|
||||
/* chain_length >>= 2; */
|
||||
/* } */
|
||||
|
||||
movl dsPrevLen(%edx), %eax
|
||||
movl dsGoodMatch(%edx), %ebx
|
||||
cmpl %ebx, %eax
|
||||
movl dsWMask(%edx), %eax
|
||||
movl dsMaxChainLen(%edx), %ebx
|
||||
jl LastMatchGood
|
||||
shrl $2, %ebx
|
||||
LastMatchGood:
|
||||
|
||||
/* chainlen is decremented once beforehand so that the function can */
|
||||
/* use the sign flag instead of the zero flag for the exit test. */
|
||||
/* It is then shifted into the high word, to make room for the wmask */
|
||||
/* value, which it will always accompany. */
|
||||
|
||||
decl %ebx
|
||||
shll $16, %ebx
|
||||
orl %eax, %ebx
|
||||
movl %ebx, chainlenwmask(%esp)
|
||||
|
||||
/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */
|
||||
|
||||
movl dsNiceMatch(%edx), %eax
|
||||
movl dsLookahead(%edx), %ebx
|
||||
cmpl %eax, %ebx
|
||||
jl LookaheadLess
|
||||
movl %eax, %ebx
|
||||
LookaheadLess: movl %ebx, nicematch(%esp)
|
||||
|
||||
/* register Bytef *scan = s->window + s->strstart; */
|
||||
|
||||
movl dsWindow(%edx), %esi
|
||||
movl %esi, window(%esp)
|
||||
movl dsStrStart(%edx), %ebp
|
||||
lea (%esi,%ebp), %edi
|
||||
movl %edi, scan(%esp)
|
||||
|
||||
/* Determine how many bytes the scan ptr is off from being */
|
||||
/* dword-aligned. */
|
||||
|
||||
movl %edi, %eax
|
||||
negl %eax
|
||||
andl $3, %eax
|
||||
movl %eax, scanalign(%esp)
|
||||
|
||||
/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */
|
||||
/* s->strstart - (IPos)MAX_DIST(s) : NIL; */
|
||||
|
||||
movl dsWSize(%edx), %eax
|
||||
subl $MIN_LOOKAHEAD, %eax
|
||||
subl %eax, %ebp
|
||||
jg LimitPositive
|
||||
xorl %ebp, %ebp
|
||||
LimitPositive:
|
||||
|
||||
/* int best_len = s->prev_length; */
|
||||
|
||||
movl dsPrevLen(%edx), %eax
|
||||
movl %eax, bestlen(%esp)
|
||||
|
||||
/* Store the sum of s->window + best_len in %esi locally, and in %esi. */
|
||||
|
||||
addl %eax, %esi
|
||||
movl %esi, windowbestlen(%esp)
|
||||
|
||||
/* register ush scan_start = *(ushf*)scan; */
|
||||
/* register ush scan_end = *(ushf*)(scan+best_len-1); */
|
||||
/* Posf *prev = s->prev; */
|
||||
|
||||
movzwl (%edi), %ebx
|
||||
movl %ebx, scanstart(%esp)
|
||||
movzwl -1(%edi,%eax), %ebx
|
||||
movl %ebx, scanend(%esp)
|
||||
movl dsPrev(%edx), %edi
|
||||
|
||||
/* Jump into the main loop. */
|
||||
|
||||
movl chainlenwmask(%esp), %edx
|
||||
jmp LoopEntry
|
||||
|
||||
.balign 16
|
||||
|
||||
/* do {
|
||||
* match = s->window + cur_match;
|
||||
* if (*(ushf*)(match+best_len-1) != scan_end ||
|
||||
* *(ushf*)match != scan_start) continue;
|
||||
* [...]
|
||||
* } while ((cur_match = prev[cur_match & wmask]) > limit
|
||||
* && --chain_length != 0);
|
||||
*
|
||||
* Here is the inner loop of the function. The function will spend the
|
||||
* majority of its time in this loop, and majority of that time will
|
||||
* be spent in the first ten instructions.
|
||||
*
|
||||
* Within this loop:
|
||||
* %ebx = scanend
|
||||
* %ecx = curmatch
|
||||
* %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
|
||||
* %esi = windowbestlen - i.e., (window + bestlen)
|
||||
* %edi = prev
|
||||
* %ebp = limit
|
||||
*/
|
||||
LookupLoop:
|
||||
andl %edx, %ecx
|
||||
movzwl (%edi,%ecx,2), %ecx
|
||||
cmpl %ebp, %ecx
|
||||
jbe LeaveNow
|
||||
subl $0x00010000, %edx
|
||||
js LeaveNow
|
||||
LoopEntry: movzwl -1(%esi,%ecx), %eax
|
||||
cmpl %ebx, %eax
|
||||
jnz LookupLoop
|
||||
movl window(%esp), %eax
|
||||
movzwl (%eax,%ecx), %eax
|
||||
cmpl scanstart(%esp), %eax
|
||||
jnz LookupLoop
|
||||
|
||||
/* Store the current value of chainlen. */
|
||||
|
||||
movl %edx, chainlenwmask(%esp)
|
||||
|
||||
/* Point %edi to the string under scrutiny, and %esi to the string we */
|
||||
/* are hoping to match it up with. In actuality, %esi and %edi are */
|
||||
/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */
|
||||
/* initialized to -(MAX_MATCH_8 - scanalign). */
|
||||
|
||||
movl window(%esp), %esi
|
||||
movl scan(%esp), %edi
|
||||
addl %ecx, %esi
|
||||
movl scanalign(%esp), %eax
|
||||
movl $(-MAX_MATCH_8), %edx
|
||||
lea MAX_MATCH_8(%edi,%eax), %edi
|
||||
lea MAX_MATCH_8(%esi,%eax), %esi
|
||||
|
||||
/* Test the strings for equality, 8 bytes at a time. At the end,
|
||||
* adjust %edx so that it is offset to the exact byte that mismatched.
|
||||
*
|
||||
* We already know at this point that the first three bytes of the
|
||||
* strings match each other, and they can be safely passed over before
|
||||
* starting the compare loop. So what this code does is skip over 0-3
|
||||
* bytes, as much as necessary in order to dword-align the %edi
|
||||
* pointer. (%esi will still be misaligned three times out of four.)
|
||||
*
|
||||
* It should be confessed that this loop usually does not represent
|
||||
* much of the total running time. Replacing it with a more
|
||||
* straightforward "rep cmpsb" would not drastically degrade
|
||||
* performance.
|
||||
*/
|
||||
LoopCmps:
|
||||
movl (%esi,%edx), %eax
|
||||
xorl (%edi,%edx), %eax
|
||||
jnz LeaveLoopCmps
|
||||
movl 4(%esi,%edx), %eax
|
||||
xorl 4(%edi,%edx), %eax
|
||||
jnz LeaveLoopCmps4
|
||||
addl $8, %edx
|
||||
jnz LoopCmps
|
||||
jmp LenMaximum
|
||||
LeaveLoopCmps4: addl $4, %edx
|
||||
LeaveLoopCmps: testl $0x0000FFFF, %eax
|
||||
jnz LenLower
|
||||
addl $2, %edx
|
||||
shrl $16, %eax
|
||||
LenLower: subb $1, %al
|
||||
adcl $0, %edx
|
||||
|
||||
/* Calculate the length of the match. If it is longer than MAX_MATCH, */
|
||||
/* then automatically accept it as the best possible match and leave. */
|
||||
|
||||
lea (%edi,%edx), %eax
|
||||
movl scan(%esp), %edi
|
||||
subl %edi, %eax
|
||||
cmpl $MAX_MATCH, %eax
|
||||
jge LenMaximum
|
||||
|
||||
/* If the length of the match is not longer than the best match we */
|
||||
/* have so far, then forget it and return to the lookup loop. */
|
||||
|
||||
movl deflatestate(%esp), %edx
|
||||
movl bestlen(%esp), %ebx
|
||||
cmpl %ebx, %eax
|
||||
jg LongerMatch
|
||||
movl windowbestlen(%esp), %esi
|
||||
movl dsPrev(%edx), %edi
|
||||
movl scanend(%esp), %ebx
|
||||
movl chainlenwmask(%esp), %edx
|
||||
jmp LookupLoop
|
||||
|
||||
/* s->match_start = cur_match; */
|
||||
/* best_len = len; */
|
||||
/* if (len >= nice_match) break; */
|
||||
/* scan_end = *(ushf*)(scan+best_len-1); */
|
||||
|
||||
LongerMatch: movl nicematch(%esp), %ebx
|
||||
movl %eax, bestlen(%esp)
|
||||
movl %ecx, dsMatchStart(%edx)
|
||||
cmpl %ebx, %eax
|
||||
jge LeaveNow
|
||||
movl window(%esp), %esi
|
||||
addl %eax, %esi
|
||||
movl %esi, windowbestlen(%esp)
|
||||
movzwl -1(%edi,%eax), %ebx
|
||||
movl dsPrev(%edx), %edi
|
||||
movl %ebx, scanend(%esp)
|
||||
movl chainlenwmask(%esp), %edx
|
||||
jmp LookupLoop
|
||||
|
||||
/* Accept the current string, with the maximum possible length. */
|
||||
|
||||
LenMaximum: movl deflatestate(%esp), %edx
|
||||
movl $MAX_MATCH, bestlen(%esp)
|
||||
movl %ecx, dsMatchStart(%edx)
|
||||
|
||||
/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */
|
||||
/* return s->lookahead; */
|
||||
|
||||
LeaveNow:
|
||||
movl deflatestate(%esp), %edx
|
||||
movl bestlen(%esp), %ebx
|
||||
movl dsLookahead(%edx), %eax
|
||||
cmpl %eax, %ebx
|
||||
jg LookaheadRet
|
||||
movl %ebx, %eax
|
||||
LookaheadRet:
|
||||
|
||||
/* Restore the stack and return from whence we came. */
|
||||
|
||||
addl $LocalVarsSize, %esp
|
||||
popl %ebx
|
||||
popl %esi
|
||||
popl %edi
|
||||
popl %ebp
|
||||
match_init: ret
|
8
zlib/contrib/blast/Makefile
Normal file
8
zlib/contrib/blast/Makefile
Normal file
|
@ -0,0 +1,8 @@
|
|||
blast: blast.c blast.h
|
||||
cc -DTEST -o blast blast.c
|
||||
|
||||
test: blast
|
||||
blast < test.pk | cmp - test.txt
|
||||
|
||||
clean:
|
||||
rm -f blast blast.o
|
4
zlib/contrib/blast/README
Normal file
4
zlib/contrib/blast/README
Normal file
|
@ -0,0 +1,4 @@
|
|||
Read blast.h for purpose and usage.
|
||||
|
||||
Mark Adler
|
||||
madler@alumni.caltech.edu
|
444
zlib/contrib/blast/blast.c
Normal file
444
zlib/contrib/blast/blast.c
Normal file
|
@ -0,0 +1,444 @@
|
|||
/* blast.c
|
||||
* Copyright (C) 2003 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in blast.h
|
||||
* version 1.1, 16 Feb 2003
|
||||
*
|
||||
* blast.c decompresses data compressed by the PKWare Compression Library.
|
||||
* This function provides functionality similar to the explode() function of
|
||||
* the PKWare library, hence the name "blast".
|
||||
*
|
||||
* This decompressor is based on the excellent format description provided by
|
||||
* Ben Rudiak-Gould in comp.compression on August 13, 2001. Interestingly, the
|
||||
* example Ben provided in the post is incorrect. The distance 110001 should
|
||||
* instead be 111000. When corrected, the example byte stream becomes:
|
||||
*
|
||||
* 00 04 82 24 25 8f 80 7f
|
||||
*
|
||||
* which decompresses to "AIAIAIAIAIAIA" (without the quotes).
|
||||
*/
|
||||
|
||||
/*
|
||||
* Change history:
|
||||
*
|
||||
* 1.0 12 Feb 2003 - First version
|
||||
* 1.1 16 Feb 2003 - Fixed distance check for > 4 GB uncompressed data
|
||||
*/
|
||||
|
||||
#include <setjmp.h> /* for setjmp(), longjmp(), and jmp_buf */
|
||||
#include "blast.h" /* prototype for blast() */
|
||||
|
||||
#define local static /* for local function definitions */
|
||||
#define MAXBITS 13 /* maximum code length */
|
||||
#define MAXWIN 4096 /* maximum window size */
|
||||
|
||||
/* input and output state */
|
||||
struct state {
|
||||
/* input state */
|
||||
blast_in infun; /* input function provided by user */
|
||||
void *inhow; /* opaque information passed to infun() */
|
||||
unsigned char *in; /* next input location */
|
||||
unsigned left; /* available input at in */
|
||||
int bitbuf; /* bit buffer */
|
||||
int bitcnt; /* number of bits in bit buffer */
|
||||
|
||||
/* input limit error return state for bits() and decode() */
|
||||
jmp_buf env;
|
||||
|
||||
/* output state */
|
||||
blast_out outfun; /* output function provided by user */
|
||||
void *outhow; /* opaque information passed to outfun() */
|
||||
unsigned next; /* index of next write location in out[] */
|
||||
int first; /* true to check distances (for first 4K) */
|
||||
unsigned char out[MAXWIN]; /* output buffer and sliding window */
|
||||
};
|
||||
|
||||
/*
|
||||
* Return need bits from the input stream. This always leaves less than
|
||||
* eight bits in the buffer. bits() works properly for need == 0.
|
||||
*
|
||||
* Format notes:
|
||||
*
|
||||
* - Bits are stored in bytes from the least significant bit to the most
|
||||
* significant bit. Therefore bits are dropped from the bottom of the bit
|
||||
* buffer, using shift right, and new bytes are appended to the top of the
|
||||
* bit buffer, using shift left.
|
||||
*/
|
||||
local int bits(struct state *s, int need)
|
||||
{
|
||||
int val; /* bit accumulator */
|
||||
|
||||
/* load at least need bits into val */
|
||||
val = s->bitbuf;
|
||||
while (s->bitcnt < need) {
|
||||
if (s->left == 0) {
|
||||
s->left = s->infun(s->inhow, &(s->in));
|
||||
if (s->left == 0) longjmp(s->env, 1); /* out of input */
|
||||
}
|
||||
val |= (int)(*(s->in)++) << s->bitcnt; /* load eight bits */
|
||||
s->left--;
|
||||
s->bitcnt += 8;
|
||||
}
|
||||
|
||||
/* drop need bits and update buffer, always zero to seven bits left */
|
||||
s->bitbuf = val >> need;
|
||||
s->bitcnt -= need;
|
||||
|
||||
/* return need bits, zeroing the bits above that */
|
||||
return val & ((1 << need) - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Huffman code decoding tables. count[1..MAXBITS] is the number of symbols of
|
||||
* each length, which for a canonical code are stepped through in order.
|
||||
* symbol[] are the symbol values in canonical order, where the number of
|
||||
* entries is the sum of the counts in count[]. The decoding process can be
|
||||
* seen in the function decode() below.
|
||||
*/
|
||||
struct huffman {
|
||||
short *count; /* number of symbols of each length */
|
||||
short *symbol; /* canonically ordered symbols */
|
||||
};
|
||||
|
||||
/*
|
||||
* Decode a code from the stream s using huffman table h. Return the symbol or
|
||||
* a negative value if there is an error. If all of the lengths are zero, i.e.
|
||||
* an empty code, or if the code is incomplete and an invalid code is received,
|
||||
* then -9 is returned after reading MAXBITS bits.
|
||||
*
|
||||
* Format notes:
|
||||
*
|
||||
* - The codes as stored in the compressed data are bit-reversed relative to
|
||||
* a simple integer ordering of codes of the same lengths. Hence below the
|
||||
* bits are pulled from the compressed data one at a time and used to
|
||||
* build the code value reversed from what is in the stream in order to
|
||||
* permit simple integer comparisons for decoding.
|
||||
*
|
||||
* - The first code for the shortest length is all ones. Subsequent codes of
|
||||
* the same length are simply integer decrements of the previous code. When
|
||||
* moving up a length, a one bit is appended to the code. For a complete
|
||||
* code, the last code of the longest length will be all zeros. To support
|
||||
* this ordering, the bits pulled during decoding are inverted to apply the
|
||||
* more "natural" ordering starting with all zeros and incrementing.
|
||||
*/
|
||||
local int decode(struct state *s, struct huffman *h)
|
||||
{
|
||||
int len; /* current number of bits in code */
|
||||
int code; /* len bits being decoded */
|
||||
int first; /* first code of length len */
|
||||
int count; /* number of codes of length len */
|
||||
int index; /* index of first code of length len in symbol table */
|
||||
int bitbuf; /* bits from stream */
|
||||
int left; /* bits left in next or left to process */
|
||||
short *next; /* next number of codes */
|
||||
|
||||
bitbuf = s->bitbuf;
|
||||
left = s->bitcnt;
|
||||
code = first = index = 0;
|
||||
len = 1;
|
||||
next = h->count + 1;
|
||||
while (1) {
|
||||
while (left--) {
|
||||
code |= (bitbuf & 1) ^ 1; /* invert code */
|
||||
bitbuf >>= 1;
|
||||
count = *next++;
|
||||
if (code < first + count) { /* if length len, return symbol */
|
||||
s->bitbuf = bitbuf;
|
||||
s->bitcnt = (s->bitcnt - len) & 7;
|
||||
return h->symbol[index + (code - first)];
|
||||
}
|
||||
index += count; /* else update for next length */
|
||||
first += count;
|
||||
first <<= 1;
|
||||
code <<= 1;
|
||||
len++;
|
||||
}
|
||||
left = (MAXBITS+1) - len;
|
||||
if (left == 0) break;
|
||||
if (s->left == 0) {
|
||||
s->left = s->infun(s->inhow, &(s->in));
|
||||
if (s->left == 0) longjmp(s->env, 1); /* out of input */
|
||||
}
|
||||
bitbuf = *(s->in)++;
|
||||
s->left--;
|
||||
if (left > 8) left = 8;
|
||||
}
|
||||
return -9; /* ran out of codes */
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a list of repeated code lengths rep[0..n-1], where each byte is a
|
||||
* count (high four bits + 1) and a code length (low four bits), generate the
|
||||
* list of code lengths. This compaction reduces the size of the object code.
|
||||
* Then given the list of code lengths length[0..n-1] representing a canonical
|
||||
* Huffman code for n symbols, construct the tables required to decode those
|
||||
* codes. Those tables are the number of codes of each length, and the symbols
|
||||
* sorted by length, retaining their original order within each length. The
|
||||
* return value is zero for a complete code set, negative for an over-
|
||||
* subscribed code set, and positive for an incomplete code set. The tables
|
||||
* can be used if the return value is zero or positive, but they cannot be used
|
||||
* if the return value is negative. If the return value is zero, it is not
|
||||
* possible for decode() using that table to return an error--any stream of
|
||||
* enough bits will resolve to a symbol. If the return value is positive, then
|
||||
* it is possible for decode() using that table to return an error for received
|
||||
* codes past the end of the incomplete lengths.
|
||||
*/
|
||||
local int construct(struct huffman *h, const unsigned char *rep, int n)
|
||||
{
|
||||
int symbol; /* current symbol when stepping through length[] */
|
||||
int len; /* current length when stepping through h->count[] */
|
||||
int left; /* number of possible codes left of current length */
|
||||
short offs[MAXBITS+1]; /* offsets in symbol table for each length */
|
||||
short length[256]; /* code lengths */
|
||||
|
||||
/* convert compact repeat counts into symbol bit length list */
|
||||
symbol = 0;
|
||||
do {
|
||||
len = *rep++;
|
||||
left = (len >> 4) + 1;
|
||||
len &= 15;
|
||||
do {
|
||||
length[symbol++] = len;
|
||||
} while (--left);
|
||||
} while (--n);
|
||||
n = symbol;
|
||||
|
||||
/* count number of codes of each length */
|
||||
for (len = 0; len <= MAXBITS; len++)
|
||||
h->count[len] = 0;
|
||||
for (symbol = 0; symbol < n; symbol++)
|
||||
(h->count[length[symbol]])++; /* assumes lengths are within bounds */
|
||||
if (h->count[0] == n) /* no codes! */
|
||||
return 0; /* complete, but decode() will fail */
|
||||
|
||||
/* check for an over-subscribed or incomplete set of lengths */
|
||||
left = 1; /* one possible code of zero length */
|
||||
for (len = 1; len <= MAXBITS; len++) {
|
||||
left <<= 1; /* one more bit, double codes left */
|
||||
left -= h->count[len]; /* deduct count from possible codes */
|
||||
if (left < 0) return left; /* over-subscribed--return negative */
|
||||
} /* left > 0 means incomplete */
|
||||
|
||||
/* generate offsets into symbol table for each length for sorting */
|
||||
offs[1] = 0;
|
||||
for (len = 1; len < MAXBITS; len++)
|
||||
offs[len + 1] = offs[len] + h->count[len];
|
||||
|
||||
/*
|
||||
* put symbols in table sorted by length, by symbol order within each
|
||||
* length
|
||||
*/
|
||||
for (symbol = 0; symbol < n; symbol++)
|
||||
if (length[symbol] != 0)
|
||||
h->symbol[offs[length[symbol]]++] = symbol;
|
||||
|
||||
/* return zero for complete set, positive for incomplete set */
|
||||
return left;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode PKWare Compression Library stream.
|
||||
*
|
||||
* Format notes:
|
||||
*
|
||||
* - First byte is 0 if literals are uncoded or 1 if they are coded. Second
|
||||
* byte is 4, 5, or 6 for the number of extra bits in the distance code.
|
||||
* This is the base-2 logarithm of the dictionary size minus six.
|
||||
*
|
||||
* - Compressed data is a combination of literals and length/distance pairs
|
||||
* terminated by an end code. Literals are either Huffman coded or
|
||||
* uncoded bytes. A length/distance pair is a coded length followed by a
|
||||
* coded distance to represent a string that occurs earlier in the
|
||||
* uncompressed data that occurs again at the current location.
|
||||
*
|
||||
* - A bit preceding a literal or length/distance pair indicates which comes
|
||||
* next, 0 for literals, 1 for length/distance.
|
||||
*
|
||||
* - If literals are uncoded, then the next eight bits are the literal, in the
|
||||
* normal bit order in th stream, i.e. no bit-reversal is needed. Similarly,
|
||||
* no bit reversal is needed for either the length extra bits or the distance
|
||||
* extra bits.
|
||||
*
|
||||
* - Literal bytes are simply written to the output. A length/distance pair is
|
||||
* an instruction to copy previously uncompressed bytes to the output. The
|
||||
* copy is from distance bytes back in the output stream, copying for length
|
||||
* bytes.
|
||||
*
|
||||
* - Distances pointing before the beginning of the output data are not
|
||||
* permitted.
|
||||
*
|
||||
* - Overlapped copies, where the length is greater than the distance, are
|
||||
* allowed and common. For example, a distance of one and a length of 518
|
||||
* simply copies the last byte 518 times. A distance of four and a length of
|
||||
* twelve copies the last four bytes three times. A simple forward copy
|
||||
* ignoring whether the length is greater than the distance or not implements
|
||||
* this correctly.
|
||||
*/
|
||||
local int decomp(struct state *s)
|
||||
{
|
||||
int lit; /* true if literals are coded */
|
||||
int dict; /* log2(dictionary size) - 6 */
|
||||
int symbol; /* decoded symbol, extra bits for distance */
|
||||
int len; /* length for copy */
|
||||
int dist; /* distance for copy */
|
||||
int copy; /* copy counter */
|
||||
unsigned char *from, *to; /* copy pointers */
|
||||
static int virgin = 1; /* build tables once */
|
||||
static short litcnt[MAXBITS+1], litsym[256]; /* litcode memory */
|
||||
static short lencnt[MAXBITS+1], lensym[16]; /* lencode memory */
|
||||
static short distcnt[MAXBITS+1], distsym[64]; /* distcode memory */
|
||||
static struct huffman litcode = {litcnt, litsym}; /* length code */
|
||||
static struct huffman lencode = {lencnt, lensym}; /* length code */
|
||||
static struct huffman distcode = {distcnt, distsym};/* distance code */
|
||||
/* bit lengths of literal codes */
|
||||
static const unsigned char litlen[] = {
|
||||
11, 124, 8, 7, 28, 7, 188, 13, 76, 4, 10, 8, 12, 10, 12, 10, 8, 23, 8,
|
||||
9, 7, 6, 7, 8, 7, 6, 55, 8, 23, 24, 12, 11, 7, 9, 11, 12, 6, 7, 22, 5,
|
||||
7, 24, 6, 11, 9, 6, 7, 22, 7, 11, 38, 7, 9, 8, 25, 11, 8, 11, 9, 12,
|
||||
8, 12, 5, 38, 5, 38, 5, 11, 7, 5, 6, 21, 6, 10, 53, 8, 7, 24, 10, 27,
|
||||
44, 253, 253, 253, 252, 252, 252, 13, 12, 45, 12, 45, 12, 61, 12, 45,
|
||||
44, 173};
|
||||
/* bit lengths of length codes 0..15 */
|
||||
static const unsigned char lenlen[] = {2, 35, 36, 53, 38, 23};
|
||||
/* bit lengths of distance codes 0..63 */
|
||||
static const unsigned char distlen[] = {2, 20, 53, 230, 247, 151, 248};
|
||||
static const short base[16] = { /* base for length codes */
|
||||
3, 2, 4, 5, 6, 7, 8, 9, 10, 12, 16, 24, 40, 72, 136, 264};
|
||||
static const char extra[16] = { /* extra bits for length codes */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8};
|
||||
|
||||
/* set up decoding tables (once--might not be thread-safe) */
|
||||
if (virgin) {
|
||||
construct(&litcode, litlen, sizeof(litlen));
|
||||
construct(&lencode, lenlen, sizeof(lenlen));
|
||||
construct(&distcode, distlen, sizeof(distlen));
|
||||
virgin = 0;
|
||||
}
|
||||
|
||||
/* read header */
|
||||
lit = bits(s, 8);
|
||||
if (lit > 1) return -1;
|
||||
dict = bits(s, 8);
|
||||
if (dict < 4 || dict > 6) return -2;
|
||||
|
||||
/* decode literals and length/distance pairs */
|
||||
do {
|
||||
if (bits(s, 1)) {
|
||||
/* get length */
|
||||
symbol = decode(s, &lencode);
|
||||
len = base[symbol] + bits(s, extra[symbol]);
|
||||
if (len == 519) break; /* end code */
|
||||
|
||||
/* get distance */
|
||||
symbol = len == 2 ? 2 : dict;
|
||||
dist = decode(s, &distcode) << symbol;
|
||||
dist += bits(s, symbol);
|
||||
dist++;
|
||||
if (s->first && dist > s->next)
|
||||
return -3; /* distance too far back */
|
||||
|
||||
/* copy length bytes from distance bytes back */
|
||||
do {
|
||||
to = s->out + s->next;
|
||||
from = to - dist;
|
||||
copy = MAXWIN;
|
||||
if (s->next < dist) {
|
||||
from += copy;
|
||||
copy = dist;
|
||||
}
|
||||
copy -= s->next;
|
||||
if (copy > len) copy = len;
|
||||
len -= copy;
|
||||
s->next += copy;
|
||||
do {
|
||||
*to++ = *from++;
|
||||
} while (--copy);
|
||||
if (s->next == MAXWIN) {
|
||||
if (s->outfun(s->outhow, s->out, s->next)) return 1;
|
||||
s->next = 0;
|
||||
s->first = 0;
|
||||
}
|
||||
} while (len != 0);
|
||||
}
|
||||
else {
|
||||
/* get literal and write it */
|
||||
symbol = lit ? decode(s, &litcode) : bits(s, 8);
|
||||
s->out[s->next++] = symbol;
|
||||
if (s->next == MAXWIN) {
|
||||
if (s->outfun(s->outhow, s->out, s->next)) return 1;
|
||||
s->next = 0;
|
||||
s->first = 0;
|
||||
}
|
||||
}
|
||||
} while (1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* See comments in blast.h */
|
||||
int blast(blast_in infun, void *inhow, blast_out outfun, void *outhow)
|
||||
{
|
||||
struct state s; /* input/output state */
|
||||
int err; /* return value */
|
||||
|
||||
/* initialize input state */
|
||||
s.infun = infun;
|
||||
s.inhow = inhow;
|
||||
s.left = 0;
|
||||
s.bitbuf = 0;
|
||||
s.bitcnt = 0;
|
||||
|
||||
/* initialize output state */
|
||||
s.outfun = outfun;
|
||||
s.outhow = outhow;
|
||||
s.next = 0;
|
||||
s.first = 1;
|
||||
|
||||
/* return if bits() or decode() tries to read past available input */
|
||||
if (setjmp(s.env) != 0) /* if came back here via longjmp(), */
|
||||
err = 2; /* then skip decomp(), return error */
|
||||
else
|
||||
err = decomp(&s); /* decompress */
|
||||
|
||||
/* write any leftover output and update the error code if needed */
|
||||
if (err != 1 && s.next && s.outfun(s.outhow, s.out, s.next) && err == 0)
|
||||
err = 1;
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
/* Example of how to use blast() */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define CHUNK 16384
|
||||
|
||||
local unsigned inf(void *how, unsigned char **buf)
|
||||
{
|
||||
static unsigned char hold[CHUNK];
|
||||
|
||||
*buf = hold;
|
||||
return fread(hold, 1, CHUNK, (FILE *)how);
|
||||
}
|
||||
|
||||
local int outf(void *how, unsigned char *buf, unsigned len)
|
||||
{
|
||||
return fwrite(buf, 1, len, (FILE *)how) != len;
|
||||
}
|
||||
|
||||
/* Decompress a PKWare Compression Library stream from stdin to stdout */
|
||||
int main(void)
|
||||
{
|
||||
int ret, n;
|
||||
|
||||
/* decompress to stdout */
|
||||
ret = blast(inf, stdin, outf, stdout);
|
||||
if (ret != 0) fprintf(stderr, "blast error: %d\n", ret);
|
||||
|
||||
/* see if there are any leftover bytes */
|
||||
n = 0;
|
||||
while (getchar() != EOF) n++;
|
||||
if (n) fprintf(stderr, "blast warning: %d unused bytes of input\n", n);
|
||||
|
||||
/* return blast() error code */
|
||||
return ret;
|
||||
}
|
||||
#endif
|
71
zlib/contrib/blast/blast.h
Normal file
71
zlib/contrib/blast/blast.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
/* blast.h -- interface for blast.c
|
||||
Copyright (C) 2003 Mark Adler
|
||||
version 1.1, 16 Feb 2003
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the author be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Mark Adler madler@alumni.caltech.edu
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* blast() decompresses the PKWare Data Compression Library (DCL) compressed
|
||||
* format. It provides the same functionality as the explode() function in
|
||||
* that library. (Note: PKWare overused the "implode" verb, and the format
|
||||
* used by their library implode() function is completely different and
|
||||
* incompatible with the implode compression method supported by PKZIP.)
|
||||
*/
|
||||
|
||||
|
||||
typedef unsigned (*blast_in)(void *how, unsigned char **buf);
|
||||
typedef int (*blast_out)(void *how, unsigned char *buf, unsigned len);
|
||||
/* Definitions for input/output functions passed to blast(). See below for
|
||||
* what the provided functions need to do.
|
||||
*/
|
||||
|
||||
|
||||
int blast(blast_in infun, void *inhow, blast_out outfun, void *outhow);
|
||||
/* Decompress input to output using the provided infun() and outfun() calls.
|
||||
* On success, the return value of blast() is zero. If there is an error in
|
||||
* the source data, i.e. it is not in the proper format, then a negative value
|
||||
* is returned. If there is not enough input available or there is not enough
|
||||
* output space, then a positive error is returned.
|
||||
*
|
||||
* The input function is invoked: len = infun(how, &buf), where buf is set by
|
||||
* infun() to point to the input buffer, and infun() returns the number of
|
||||
* available bytes there. If infun() returns zero, then blast() returns with
|
||||
* an input error. (blast() only asks for input if it needs it.) inhow is for
|
||||
* use by the application to pass an input descriptor to infun(), if desired.
|
||||
*
|
||||
* The output function is invoked: err = outfun(how, buf, len), where the bytes
|
||||
* to be written are buf[0..len-1]. If err is not zero, then blast() returns
|
||||
* with an output error. outfun() is always called with len <= 4096. outhow
|
||||
* is for use by the application to pass an output descriptor to outfun(), if
|
||||
* desired.
|
||||
*
|
||||
* The return codes are:
|
||||
*
|
||||
* 2: ran out of input before completing decompression
|
||||
* 1: output error before completing decompression
|
||||
* 0: successful decompression
|
||||
* -1: literal flag not zero or one
|
||||
* -2: dictionary size not in 4..6
|
||||
* -3: distance is too far back
|
||||
*
|
||||
* At the bottom of blast.c is an example program that uses blast() that can be
|
||||
* compiled to produce a command-line decompression filter by defining TEST.
|
||||
*/
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue