From 50f0dd331f8168fb5b2cd60c70178fad627b7fb6 Mon Sep 17 00:00:00 2001 From: pixel Date: Sat, 27 Nov 2004 21:44:15 +0000 Subject: Large dos2unix commit... --- lib/cdabstract.cpp | 384 +++++----- lib/cdreader.cpp | 668 ++++++++-------- lib/dteutils.cpp | 638 ++++++++-------- lib/luapsx.cpp | 614 +++++++-------- lib/lzss.cpp | 928 +++++++++++------------ lib/mips.cpp | 2136 ++++++++++++++++++++++++++-------------------------- lib/mipsdis.cpp | 360 ++++----- lib/mipsdump.cpp | 414 +++++----- lib/mipsmem.cpp | 698 ++++++++--------- lib/mipsobj.cpp | 538 ++++++------- lib/yazedc.cpp | 546 +++++++------- 11 files changed, 3962 insertions(+), 3962 deletions(-) (limited to 'lib') diff --git a/lib/cdabstract.cpp b/lib/cdabstract.cpp index ff438c4..ceb5f70 100644 --- a/lib/cdabstract.cpp +++ b/lib/cdabstract.cpp @@ -1,192 +1,192 @@ -/* - * PSX-Tools Bundle Pack - * Copyright (C) 2002-2003 Nicolas "Pixel" Noble - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* $Id: cdabstract.cpp,v 1.7 2003-12-11 16:53:43 pixel Exp $ */ - -#include "cdabstract.h" -#include "Input.h" -#include "cdreader.h" - -#ifdef __linux__ -#include -#include -#include -#include -#endif - -#if defined (_MSC_VER) || defined (__MINGW32__) -#include -#endif - -Handle * cdabstract::open_cd(const String & nom) { - if (nom.extract(0, 2).toupper() == "CD:") { - return new cdreader(nom.extract(3)); - } else { - return new Input(nom); - } -} - -bool cdabstract::canprobe() { -#ifdef __linux__ - return true; -#endif -#ifdef _WIN32 - OSVERSIONINFO ov; - memset(&ov, 0, sizeof(OSVERSIONINFO)); - ov.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - - GetVersionEx(&ov); - - return ((ov.dwPlatformId == VER_PLATFORM_WIN32_NT) && (ov.dwMajorVersion > 4)); -#endif - return false; -} - -std::vector cdabstract::probe() throw (GeneralException) { - int i; - std::vector r; - String probed; - - if (!canprobe()) - throw GeneralException("Can't probe CD devices on this platform."); - -#ifdef __linux__ - if (subprobe(probed = "/dev/cdrom")) - r.push_back(probed); - - for (i = 0; i < 63; i++) { - probed.set("/dev/cdroms/cdrom%i", i); - if (subprobe(probed)) - r.push_back(probed); - } - for (i = 'a'; i <= 'z'; i++) { - probed.set("/dev/hd%c", i); - if (subprobe(probed)) - r.push_back(probed); - } -#endif - -#ifdef _WIN32 - for (i = 'A'; i <= 'Z'; i++) { - probed.set("%c:\\", i); - if (subprobe(probed)) - r.push_back(probed); - } -#endif - - return r; -} - -#ifdef _WIN32 -HANDLE cdabstract::OpenIOCTLFile(char cLetter) { - HANDLE hF; - char szFName[16]; - OSVERSIONINFO ov; - DWORD dwFlags; - DWORD dwIOCTLAttr = 0; - - memset(&ov, 0, sizeof(OSVERSIONINFO)); - ov.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&ov); - - if((ov.dwPlatformId == VER_PLATFORM_WIN32_NT) && (ov.dwMajorVersion > 4)) - dwFlags = GENERIC_READ | GENERIC_WRITE; // add gen write on W2k/XP - else dwFlags = GENERIC_READ; - - sprintf(szFName, "\\\\.\\%c:", cLetter); - - hF = CreateFile(szFName, dwFlags, FILE_SHARE_READ, // open drive - NULL, OPEN_EXISTING, dwIOCTLAttr, NULL); - - if (hF == INVALID_HANDLE_VALUE) { // mmm... no success? - dwFlags ^= GENERIC_WRITE; // -> try write toggle - hF = CreateFile(szFName, dwFlags, FILE_SHARE_READ, // -> open drive again - NULL, OPEN_EXISTING, dwIOCTLAttr, NULL); - if (hF == INVALID_HANDLE_VALUE) - return NULL; - } - return hF; -} - -typedef struct { - ULONG Length; - UCHAR PortNumber; - UCHAR PathId; - UCHAR TargetId; - UCHAR Lun; -} SCSI_ADDRESS, *PSCSI_ADDRESS; - -void cdabstract::GetIOCTLAdapter(HANDLE hF, int * iDA, int * iDT, int * iDL) { - char szBuf[1024]; - PSCSI_ADDRESS pSA; - DWORD dwRet; - - *iDA = *iDT = *iDL = -1; - - if (hF == NULL) - return; - - memset(szBuf,0,1024); - - pSA = (PSCSI_ADDRESS)szBuf; - pSA->Length = sizeof(SCSI_ADDRESS); - - if (!DeviceIoControl(hF, IOCTL_SCSI_GET_ADDRESS, NULL, 0, pSA, - sizeof(SCSI_ADDRESS), &dwRet, NULL)) - return; - - *iDA = pSA->PortNumber; - *iDT = pSA->TargetId; - *iDL = pSA->Lun; -} -#endif - -bool cdabstract::subprobe(String & probed) { -#ifdef __linux__ - int h, caps; - - h = open(probed.to_charp(), O_RDONLY | O_NONBLOCK); - - if (ioctl(h, CDROM_GET_CAPABILITY, &caps) < 0) { - close(h); - return false; - } else { - close(h); - return true; - } -#endif - -#ifdef _WIN32 - int iDA, iDT, iDL; - char letter[4]; - HANDLE h; - - if (GetDriveType(probed.to_charp()) == DRIVE_CDROM) { - h = OpenIOCTLFile(probed[0]); - GetIOCTLAdapter(h, &iDA, &iDT, &iDL); - CloseHandle(h); - if ((iDA != -1) && (iDT != -1) && (iDL != -1)) { - probed += String().set(" [%i:%i:%i]", iDA, iDT, iDL); - return true; - } - } -#endif - - return false; -} +/* + * PSX-Tools Bundle Pack + * Copyright (C) 2002-2003 Nicolas "Pixel" Noble + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id: cdabstract.cpp,v 1.8 2004-11-27 21:44:48 pixel Exp $ */ + +#include "cdabstract.h" +#include "Input.h" +#include "cdreader.h" + +#ifdef __linux__ +#include +#include +#include +#include +#endif + +#if defined (_MSC_VER) || defined (__MINGW32__) +#include +#endif + +Handle * cdabstract::open_cd(const String & nom) { + if (nom.extract(0, 2).toupper() == "CD:") { + return new cdreader(nom.extract(3)); + } else { + return new Input(nom); + } +} + +bool cdabstract::canprobe() { +#ifdef __linux__ + return true; +#endif +#ifdef _WIN32 + OSVERSIONINFO ov; + memset(&ov, 0, sizeof(OSVERSIONINFO)); + ov.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + + GetVersionEx(&ov); + + return ((ov.dwPlatformId == VER_PLATFORM_WIN32_NT) && (ov.dwMajorVersion > 4)); +#endif + return false; +} + +std::vector cdabstract::probe() throw (GeneralException) { + int i; + std::vector r; + String probed; + + if (!canprobe()) + throw GeneralException("Can't probe CD devices on this platform."); + +#ifdef __linux__ + if (subprobe(probed = "/dev/cdrom")) + r.push_back(probed); + + for (i = 0; i < 63; i++) { + probed.set("/dev/cdroms/cdrom%i", i); + if (subprobe(probed)) + r.push_back(probed); + } + for (i = 'a'; i <= 'z'; i++) { + probed.set("/dev/hd%c", i); + if (subprobe(probed)) + r.push_back(probed); + } +#endif + +#ifdef _WIN32 + for (i = 'A'; i <= 'Z'; i++) { + probed.set("%c:\\", i); + if (subprobe(probed)) + r.push_back(probed); + } +#endif + + return r; +} + +#ifdef _WIN32 +HANDLE cdabstract::OpenIOCTLFile(char cLetter) { + HANDLE hF; + char szFName[16]; + OSVERSIONINFO ov; + DWORD dwFlags; + DWORD dwIOCTLAttr = 0; + + memset(&ov, 0, sizeof(OSVERSIONINFO)); + ov.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&ov); + + if((ov.dwPlatformId == VER_PLATFORM_WIN32_NT) && (ov.dwMajorVersion > 4)) + dwFlags = GENERIC_READ | GENERIC_WRITE; // add gen write on W2k/XP + else dwFlags = GENERIC_READ; + + sprintf(szFName, "\\\\.\\%c:", cLetter); + + hF = CreateFile(szFName, dwFlags, FILE_SHARE_READ, // open drive + NULL, OPEN_EXISTING, dwIOCTLAttr, NULL); + + if (hF == INVALID_HANDLE_VALUE) { // mmm... no success? + dwFlags ^= GENERIC_WRITE; // -> try write toggle + hF = CreateFile(szFName, dwFlags, FILE_SHARE_READ, // -> open drive again + NULL, OPEN_EXISTING, dwIOCTLAttr, NULL); + if (hF == INVALID_HANDLE_VALUE) + return NULL; + } + return hF; +} + +typedef struct { + ULONG Length; + UCHAR PortNumber; + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; +} SCSI_ADDRESS, *PSCSI_ADDRESS; + +void cdabstract::GetIOCTLAdapter(HANDLE hF, int * iDA, int * iDT, int * iDL) { + char szBuf[1024]; + PSCSI_ADDRESS pSA; + DWORD dwRet; + + *iDA = *iDT = *iDL = -1; + + if (hF == NULL) + return; + + memset(szBuf,0,1024); + + pSA = (PSCSI_ADDRESS)szBuf; + pSA->Length = sizeof(SCSI_ADDRESS); + + if (!DeviceIoControl(hF, IOCTL_SCSI_GET_ADDRESS, NULL, 0, pSA, + sizeof(SCSI_ADDRESS), &dwRet, NULL)) + return; + + *iDA = pSA->PortNumber; + *iDT = pSA->TargetId; + *iDL = pSA->Lun; +} +#endif + +bool cdabstract::subprobe(String & probed) { +#ifdef __linux__ + int h, caps; + + h = open(probed.to_charp(), O_RDONLY | O_NONBLOCK); + + if (ioctl(h, CDROM_GET_CAPABILITY, &caps) < 0) { + close(h); + return false; + } else { + close(h); + return true; + } +#endif + +#ifdef _WIN32 + int iDA, iDT, iDL; + char letter[4]; + HANDLE h; + + if (GetDriveType(probed.to_charp()) == DRIVE_CDROM) { + h = OpenIOCTLFile(probed[0]); + GetIOCTLAdapter(h, &iDA, &iDT, &iDL); + CloseHandle(h); + if ((iDA != -1) && (iDT != -1) && (iDL != -1)) { + probed += String().set(" [%i:%i:%i]", iDA, iDT, iDL); + return true; + } + } +#endif + + return false; +} diff --git a/lib/cdreader.cpp b/lib/cdreader.cpp index 83bd1b3..7777c4d 100644 --- a/lib/cdreader.cpp +++ b/lib/cdreader.cpp @@ -1,334 +1,334 @@ -/* - * PSX-Tools Bundle Pack - * Copyright (C) 2002-2003 Nicolas "Pixel" Noble - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* $Id: cdreader.cpp,v 1.19 2003-12-26 19:05:31 pixel Exp $ */ - -#include -#include -#include -#include -#include -#include -#include "cdreader.h" -#include "Exceptions.h" -#include "generic.h" -#ifdef HAVE_CONFIG_H -#include "config.h" -#else -#define _(x) x -#endif -#include "cdabstract.h" - -#define nsectorsarow 1 -#define cachesize 2048 - -bool cdreader::CanWrite() const { - return 0; -} - -bool cdreader::CanRead() const { - return 1; -} - -bool cdreader::CanSeek() const { - return 1; -} - -String cdreader::GetName() const { - return n + " raw reading"; -} - -ssize_t cdreader::GetSize() const { - return -1; -} - -off_t cdreader::seek(off_t offset, int whence) throw (GeneralException) { - switch (whence) { - case SEEK_SET: - itell = offset; - break; - case SEEK_CUR: - itell += offset; - break; - case SEEK_END: - throw GeneralException("Can not yet seek from the end of a CD."); - } - return itell; -} - -ssize_t cdreader::read(void *buf, size_t count) throw (GeneralException) { - char sector[2352]; - size_t r = count; - - size_t remain = itell % 2352; - sectorseek(itell / 2352); - - while (count > 0) { - size_t n = MIN(2352 - remain, count); - fetchsector(sector); - bcopy(sector + remain, buf, n); - buf = ((char *) buf) + n; - itell += n; - count -= n; - remain = 0; - } - - return r; -} - -void cdreader::sectorseek(int sec) { - sector = sec; -} - -void cdreader::fetchsector(void * buf, int sec) { - if (sec >= 0) - sector = sec; - - if (sectors[sector]) { - actualize(sectors[sector]); - memcpy(buf, sectors[sector]->sector, 2352); - return; - } - - Byte buffers[2352 * nsectorsarow]; - - getsector(buffers, sec = sector, nsectorsarow); - - for (int i = nsectorsarow - 1; i >= 0; i--) { - introduce(buffers + i * 2352, sec + i); - } - - memcpy(buf, buffers, 2352); - - while (nsectors > cachesize) { - removetail(); - } -} - -cdreader::~cdreader() { - while (nsectors) { - removetail(); - } -} - -void cdreader::removetail() { - if (!tail) - return; - - sectors[tail->n] = 0; - - if (head == tail) { - free(tail); - head = tail = 0; - nsectors = 0; - } else { - cachedsector * p; - (p = tail->prev)->next = 0; - free(tail); - tail = p; - nsectors--; - } -} - -void cdreader::actualize(cachedsector * s) { - if (s == head) - return; - - if (s != tail) { - s->next->prev = s->prev; - } else { - tail = s->prev; - } - s->prev->next = s->next; - - head->prev = s; - s->prev = 0; - s->next = head; - head = s; -} - -void cdreader::introduce(Byte * datas, int n) { - cachedsector * s; - - s = (cachedsector *) malloc(sizeof(cachedsector)); - memcpy(s->sector, datas, 2352); - s->n = n; - - if (head) { - s->next = head; - head->prev = s; - head = s; - } else { - head = tail = s; - s->prev = s->next = 0; - } - sectors[n] = s; - - nsectors++; -} - -#ifdef __linux__ -#include -#include -#include - -cdreader::cdreader(const String & no) throw (GeneralException) : - Handle(open(no.to_charp(), O_RDONLY)), n(no), sector(0) { - int i; - -#ifdef DEBUG - printm(M_INFO, "Opening cdrom device " + no + "\n"); -#endif - - if (GetHandle() < 0) { - throw IOGeneral(String(_("Error opening file ")) + no + _(" for reading: ") + strerror(errno)); - } - - struct stat s; - fstat(GetHandle(), &s); - - if (!S_ISBLK(s.st_mode)) { - throw GeneralException(no + " is not a block device."); - } - - for (i = 0; i < 400000; i++) { - sectors[i] = 0; - } - head = tail = 0; - nsectors = 0; -} - -cdreader::cdreader(const cdreader & inp) : Handle(inp), n(inp.n) { - int i; - - for (i = 0; i < 400000; i++) { - sectors[i] = 0; - } - head = tail = 0; - nsectors = 0; -} - -void cdreader::getsector(void *buf, int sec, int nb) throw (GeneralException) { - struct cdrom_msf * msf = (struct cdrom_msf *) buf; - if (sec >= 0) - sector = sec; - - sector += 150; - - msf->cdmsf_min0 = sector /CD_SECS /CD_FRAMES; - msf->cdmsf_sec0 = (sector /CD_FRAMES)%CD_SECS; - msf->cdmsf_frame0= sector %CD_FRAMES; - msf->cdmsf_min1 = (sector + nb)/CD_SECS /CD_FRAMES; - msf->cdmsf_sec1 = ((sector + nb)/CD_FRAMES)%CD_SECS; - msf->cdmsf_frame1= (sector + nb)%CD_FRAMES; - - sector -= 150; - - if (ioctl(GetHandle(), CDROMREADRAW, buf) < 0) { - throw GeneralException(String("unable to read cd sector ") + sector + ": " + strerror(errno)); - } - - sector += nb; -} -#endif - -#if defined (_MSC_VER) || defined (__MINGW32__) -cdreader::cdreader(const String & no) throw (GeneralException) : - Handle(-1), n(no), sector(0) { - if (!(hFile = cdabstract::OpenIOCTLFile(no[0]))) - throw GeneralException("Error opening device " + no); - for (int i = 0; i < 400000; i++) { - sectors[i] = 0; - } - head = tail = 0; - nsectors = 0; -} - -cdreader::cdreader(const cdreader & i) : Handle(i), n(i.n) { - hFile = i.hFile; - for (int x = 0; x < 400000; x++) { - sectors[x] = 0; - } - head = tail = 0; - nsectors = 0; -} - -void cdreader::close() throw (GeneralException) { - CloseHandle(hFile); -} - -typedef enum _TRACK_MODE_TYPE { - YellowMode2, - XAForm2, - CDDA -} TRACK_MODE_TYPE, *PTRACK_MODE_TYPE; - -typedef struct _RAW_READ_INFO { - LARGE_INTEGER DiskOffset; - ULONG SectorCount; - TRACK_MODE_TYPE TrackMode; -} RAW_READ_INFO, *PRAW_READ_INFO; - -void cdreader::getsector(void *buf, int sec, int nb) throw (GeneralException) { - RAW_READ_INFO rawIOCTL; - DWORD dwRet; - BOOL bStat; - bool done = false; - if (sec >= 0) - sector = sec; - - rawIOCTL.DiskOffset.QuadPart = sector * 2048; - rawIOCTL.SectorCount = nb; - rawIOCTL.TrackMode = YellowMode2; - - while (!done) { - SetLastError(0); - bStat = DeviceIoControl(hFile, IOCTL_CDROM_RAW_READ, - &rawIOCTL, sizeof(RAW_READ_INFO), - buf, 2352 * nb, &dwRet, NULL); - if (!bStat) { - DWORD dwErrCode = GetLastError(); - if (dwErrCode == ERROR_INVALID_FUNCTION) { - if (rawIOCTL.TrackMode == YellowMode2) { - rawIOCTL.TrackMode = XAForm2; - continue; - } - } - if (dwErrCode != ERROR_IO_PENDING) { - LPVOID lpMsgBuf; - if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - (LPTSTR) &lpMsgBuf, 0, NULL )) - throw GeneralException("Gave up on reading CD: unknown error"); - String errmsg = (LPCTSTR) lpMsgBuf; - LocalFree(lpMsgBuf); - throw GeneralException("Gave up on reading CD: " + errmsg); - } - } else { - done = true; - } - } - - sector += nb; -} - -#endif +/* + * PSX-Tools Bundle Pack + * Copyright (C) 2002-2003 Nicolas "Pixel" Noble + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id: cdreader.cpp,v 1.20 2004-11-27 21:44:48 pixel Exp $ */ + +#include +#include +#include +#include +#include +#include +#include "cdreader.h" +#include "Exceptions.h" +#include "generic.h" +#ifdef HAVE_CONFIG_H +#include "config.h" +#else +#define _(x) x +#endif +#include "cdabstract.h" + +#define nsectorsarow 1 +#define cachesize 2048 + +bool cdreader::CanWrite() const { + return 0; +} + +bool cdreader::CanRead() const { + return 1; +} + +bool cdreader::CanSeek() const { + return 1; +} + +String cdreader::GetName() const { + return n + " raw reading"; +} + +ssize_t cdreader::GetSize() const { + return -1; +} + +off_t cdreader::seek(off_t offset, int whence) throw (GeneralException) { + switch (whence) { + case SEEK_SET: + itell = offset; + break; + case SEEK_CUR: + itell += offset; + break; + case SEEK_END: + throw GeneralException("Can not yet seek from the end of a CD."); + } + return itell; +} + +ssize_t cdreader::read(void *buf, size_t count) throw (GeneralException) { + char sector[2352]; + size_t r = count; + + size_t remain = itell % 2352; + sectorseek(itell / 2352); + + while (count > 0) { + size_t n = MIN(2352 - remain, count); + fetchsector(sector); + bcopy(sector + remain, buf, n); + buf = ((char *) buf) + n; + itell += n; + count -= n; + remain = 0; + } + + return r; +} + +void cdreader::sectorseek(int sec) { + sector = sec; +} + +void cdreader::fetchsector(void * buf, int sec) { + if (sec >= 0) + sector = sec; + + if (sectors[sector]) { + actualize(sectors[sector]); + memcpy(buf, sectors[sector]->sector, 2352); + return; + } + + Byte buffers[2352 * nsectorsarow]; + + getsector(buffers, sec = sector, nsectorsarow); + + for (int i = nsectorsarow - 1; i >= 0; i--) { + introduce(buffers + i * 2352, sec + i); + } + + memcpy(buf, buffers, 2352); + + while (nsectors > cachesize) { + removetail(); + } +} + +cdreader::~cdreader() { + while (nsectors) { + removetail(); + } +} + +void cdreader::removetail() { + if (!tail) + return; + + sectors[tail->n] = 0; + + if (head == tail) { + free(tail); + head = tail = 0; + nsectors = 0; + } else { + cachedsector * p; + (p = tail->prev)->next = 0; + free(tail); + tail = p; + nsectors--; + } +} + +void cdreader::actualize(cachedsector * s) { + if (s == head) + return; + + if (s != tail) { + s->next->prev = s->prev; + } else { + tail = s->prev; + } + s->prev->next = s->next; + + head->prev = s; + s->prev = 0; + s->next = head; + head = s; +} + +void cdreader::introduce(Byte * datas, int n) { + cachedsector * s; + + s = (cachedsector *) malloc(sizeof(cachedsector)); + memcpy(s->sector, datas, 2352); + s->n = n; + + if (head) { + s->next = head; + head->prev = s; + head = s; + } else { + head = tail = s; + s->prev = s->next = 0; + } + sectors[n] = s; + + nsectors++; +} + +#ifdef __linux__ +#include +#include +#include + +cdreader::cdreader(const String & no) throw (GeneralException) : + Handle(open(no.to_charp(), O_RDONLY)), n(no), sector(0) { + int i; + +#ifdef DEBUG + printm(M_INFO, "Opening cdrom device " + no + "\n"); +#endif + + if (GetHandle() < 0) { + throw IOGeneral(String(_("Error opening file ")) + no + _(" for reading: ") + strerror(errno)); + } + + struct stat s; + fstat(GetHandle(), &s); + + if (!S_ISBLK(s.st_mode)) { + throw GeneralException(no + " is not a block device."); + } + + for (i = 0; i < 400000; i++) { + sectors[i] = 0; + } + head = tail = 0; + nsectors = 0; +} + +cdreader::cdreader(const cdreader & inp) : Handle(inp), n(inp.n) { + int i; + + for (i = 0; i < 400000; i++) { + sectors[i] = 0; + } + head = tail = 0; + nsectors = 0; +} + +void cdreader::getsector(void *buf, int sec, int nb) throw (GeneralException) { + struct cdrom_msf * msf = (struct cdrom_msf *) buf; + if (sec >= 0) + sector = sec; + + sector += 150; + + msf->cdmsf_min0 = sector /CD_SECS /CD_FRAMES; + msf->cdmsf_sec0 = (sector /CD_FRAMES)%CD_SECS; + msf->cdmsf_frame0= sector %CD_FRAMES; + msf->cdmsf_min1 = (sector + nb)/CD_SECS /CD_FRAMES; + msf->cdmsf_sec1 = ((sector + nb)/CD_FRAMES)%CD_SECS; + msf->cdmsf_frame1= (sector + nb)%CD_FRAMES; + + sector -= 150; + + if (ioctl(GetHandle(), CDROMREADRAW, buf) < 0) { + throw GeneralException(String("unable to read cd sector ") + sector + ": " + strerror(errno)); + } + + sector += nb; +} +#endif + +#if defined (_MSC_VER) || defined (__MINGW32__) +cdreader::cdreader(const String & no) throw (GeneralException) : + Handle(-1), n(no), sector(0) { + if (!(hFile = cdabstract::OpenIOCTLFile(no[0]))) + throw GeneralException("Error opening device " + no); + for (int i = 0; i < 400000; i++) { + sectors[i] = 0; + } + head = tail = 0; + nsectors = 0; +} + +cdreader::cdreader(const cdreader & i) : Handle(i), n(i.n) { + hFile = i.hFile; + for (int x = 0; x < 400000; x++) { + sectors[x] = 0; + } + head = tail = 0; + nsectors = 0; +} + +void cdreader::close() throw (GeneralException) { + CloseHandle(hFile); +} + +typedef enum _TRACK_MODE_TYPE { + YellowMode2, + XAForm2, + CDDA +} TRACK_MODE_TYPE, *PTRACK_MODE_TYPE; + +typedef struct _RAW_READ_INFO { + LARGE_INTEGER DiskOffset; + ULONG SectorCount; + TRACK_MODE_TYPE TrackMode; +} RAW_READ_INFO, *PRAW_READ_INFO; + +void cdreader::getsector(void *buf, int sec, int nb) throw (GeneralException) { + RAW_READ_INFO rawIOCTL; + DWORD dwRet; + BOOL bStat; + bool done = false; + if (sec >= 0) + sector = sec; + + rawIOCTL.DiskOffset.QuadPart = sector * 2048; + rawIOCTL.SectorCount = nb; + rawIOCTL.TrackMode = YellowMode2; + + while (!done) { + SetLastError(0); + bStat = DeviceIoControl(hFile, IOCTL_CDROM_RAW_READ, + &rawIOCTL, sizeof(RAW_READ_INFO), + buf, 2352 * nb, &dwRet, NULL); + if (!bStat) { + DWORD dwErrCode = GetLastError(); + if (dwErrCode == ERROR_INVALID_FUNCTION) { + if (rawIOCTL.TrackMode == YellowMode2) { + rawIOCTL.TrackMode = XAForm2; + continue; + } + } + if (dwErrCode != ERROR_IO_PENDING) { + LPVOID lpMsgBuf; + if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, 0, NULL )) + throw GeneralException("Gave up on reading CD: unknown error"); + String errmsg = (LPCTSTR) lpMsgBuf; + LocalFree(lpMsgBuf); + throw GeneralException("Gave up on reading CD: " + errmsg); + } + } else { + done = true; + } + } + + sector += nb; +} + +#endif diff --git a/lib/dteutils.cpp b/lib/dteutils.cpp index 85a7df2..42f36bf 100644 --- a/lib/dteutils.cpp +++ b/lib/dteutils.cpp @@ -1,319 +1,319 @@ -/* - * PSX-Tools Bundle Pack - * Copyright (C) 2002 Nicolas "Pixel" Noble - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include "generic.h" -#include "Handle.h" - -class thingtree : public Base { - public: - static void addstring(const String, long); - static long look(const String); - static void destroy(); - private: - thingtree(); - thingtree(char, bool, thingtree *, long); - ~thingtree(); - char thischar; - bool terminal; - thingtree * father, * child, * brother; - long thingentry; - static thingtree * root; -}; - -thingtree * thingtree::root = 0; - -thingtree::thingtree(char gchar, bool gterm, thingtree * gfather, long gthingentry) : thischar(gchar), terminal(gterm), thingentry(gthingentry) { - if (!gfather) { - if (!root) { - root = new thingtree(); - } - father = root; - } else { - father = gfather; - } - brother = father->child; - father->child = this; -} - -thingtree::thingtree() : thischar(0), terminal(false), father(0), child(0), brother(0) { } - -long thingtree::look(const String s) { - long currentthing = -1; - thingtree * ptr = root; - int i; - - if (!ptr) { - printm(M_ERROR, "Error: thingtree not initialised\n"); - exit(-1); - } - - for (i = 0; s[i]; i++) { -// printm(M_INFO, "Looking for '%c'\n", *p); - for (ptr = ptr->child; ptr; ptr = ptr->brother) { -// printm(M_INFO, "Looking in %p: %c\n", ptr, ptr->thischar); - if (ptr->thischar == s[i]) { - if (ptr->terminal) { - currentthing = ptr->thingentry; - } - break; - } - } - if (!ptr) { -// printm(M_INFO, "Not found.\n"); - break; - } - } - - if (currentthing == -1) { - printm(M_ERROR, "Error, can't find any entry for string '" + s + "'\n"); - } - - return currentthing; -} - -void thingtree::addstring(const String s, long thingentry) { - thingtree * ptr, * fptr; - int i; - - if (!root) { - root = new thingtree(); - } - -// printm(M_INFO, "Creating new thingtree entry: %li='%s'\n", thingentry, s); - - ptr = root; - for (i = 0; s[i]; i++) { - fptr = ptr; -// printm(M_INFO, "Finding entry for '%c'\n", *p); - for (ptr = ptr->child; ptr; ptr = ptr->brother) { -// printm(M_INFO, "Browsing childs: %p = %c\n", ptr, ptr->thischar); - if (ptr->thischar == s[i]) - break; - } - - if (!ptr) { -// printm(M_INFO, "Creating new branch for %c\n", *p); - ptr = new thingtree(s[i], s[i + 1] == 0, fptr, thingentry); -// printm(M_INFO, "Created branch %p\n", ptr); - } else { - if (s[i + 1] == 0) { - ptr->terminal = true; - ptr->thingentry = thingentry; - } - } - } -} - -void thingtree::destroy() { - delete root; - root = 0; -} - -thingtree::~thingtree() { - if (father->child == this) - father->child = brother; - - while (child) - delete child; -} - -String things[256]; - -char * dte_text; -char dte_flags[256 * 256]; -long dte_counters[256 * 256]; -long dte_entries[256]; -char alloweds[256]; -long dte_usage[256]; - -long dte_most; -long dte_counter; -long dte_text_size; -int dte_size; -long gain; -long nb_dte = 0; -long tnb_dte = 0; - -void dte_reset(void) { - memset(dte_counters, 0, 0x40000); - dte_most = 0; - dte_counter = 0; -} - -void build_dte(void) { - int i; - Uint16 t, t2; - unsigned short p = 0; - - for (i = 0; i < dte_text_size; i++) { - t = *((Uint16 *) (dte_text + i)); - t2 = *((Uint16 *) (dte_text + i + 1)); - if (t == p) { - p = 0; - continue; - } - p = t; - if (!dte_flags[t]) { -// if ((!dte_flags[t]) && (dte_flags[t2] != 3)) { - if ((dte_counters[t]++) == 0) { - nb_dte++; - } - if (dte_counters[t] > dte_counter) { - dte_most = t; - dte_counter = dte_counters[t]; - } -// } else if (dte_flags[t] == 3) { -// i++; - } - } -} - -void push_entry(long entry) { - int i; - char t[3], c1, c2; - t[2] = 0; - - c1 = dte_most & 0xff; - c2 = dte_most >> 8; - t[0] = things[c1][0]; - t[1] = things[c2][0]; - - for (i = 0; i < 256; i++) { - if (!dte_entries[i]) { - dte_entries[i] = entry; - things[i] = strdup(t); - thingtree::addstring(t, i); - break; - } - } -} - -void dte_compress() { - int i, j; - char c1, c2; - - for (i = 0; i < 256; i++) { - for (j = 0; j < 256; j++) { - dte_flags[i * 256 + j] = alloweds[i] ? alloweds[j] ? 0 : 1 : 1; - } - } - - gain = 0; - - printm(M_STATUS, "Going for it: dte_size = %i\n", dte_size); - for (i = 0; i < dte_size; i++) { - dte_reset(); - build_dte(); - if (!tnb_dte) - tnb_dte = nb_dte; - c1 = dte_most & 0xff; - c2 = dte_most >> 8; - c1 = things[c1][0]; - c2 = things[c2][0]; - printm(M_INFO, "Entry #%i, most count: %li, couple = 0x%04x = (%c %c)\n", i, dte_counter, (int) dte_most, c1, c2); - dte_flags[dte_most] = 3; - gain += dte_counter; - push_entry(dte_most); - } - - printm(M_STATUS, "Estimated gain: %li bytes, new file size = %li\n", gain, dte_text_size - gain); -} - -void read_thingy(Handle * f) { - String line, st, thing; - long code; - int i; - - dte_size = 0; - - for (i = 0; i < 256; i++) { - dte_entries[i] = -1; - } - - while (1) { - line = "0x"; - *f >> st; - if (st.strlen()) { - line += st.extract(0, 1); - code = line.to_int(); - thing = st.extract(3); - switch (thing.strlen()) { - case 0: - dte_size++; - dte_entries[code] = 0; - break; - case 1: - alloweds[code] = 1; - default: - things[code] = thing; - thingtree::addstring(thing, code); - } - } - } -} - -void read_thingy_file(Handle * f) { - String line, trans; - long code; - int ptr = 0, i, c; - - for (i = 0; i < 256; i++) { - dte_usage[i] = 0; - } - - while (1) { - *f >> line; - if (!line.strlen()) - continue; - i = 0; - while (line[i]) { - if (line[i] == '<') { - if ((c = line.strchr('>', i)) < 0) { - printm(M_ERROR, "Error in file: '<' not closed.\n"); - exit(-1); - } - i++; - if (c == 2) { - trans = "0x" + line.extract(i, 2); - code = line.to_int(); - dte_text[ptr++] = code; - printm(M_BARE, "0x%02x-", code); - } else { - printm(M_BARE, "Unknow " + trans.extract(2) + "-"); - } - i += c; - } else { - if ((code = thingtree::look(line.extract(i))) == -1) - exit(-1); - dte_text[ptr++] = code; - i += things[code].strlen(); - printm(M_BARE, things[code] + "-"); - dte_usage[code]++; - } - } - printm(M_BARE, "\n"); - } - - dte_text[ptr] = dte_text[ptr + 1] = dte_text[ptr + 2] = dte_text[ptr + 3] = 0; - dte_text_size = ptr; -} +/* + * PSX-Tools Bundle Pack + * Copyright (C) 2002 Nicolas "Pixel" Noble + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include "generic.h" +#include "Handle.h" + +class thingtree : public Base { + public: + static void addstring(const String, long); + static long look(const String); + static void destroy(); + private: + thingtree(); + thingtree(char, bool, thingtree *, long); + ~thingtree(); + char thischar; + bool terminal; + thingtree * father, * child, * brother; + long thingentry; + static thingtree * root; +}; + +thingtree * thingtree::root = 0; + +thingtree::thingtree(char gchar, bool gterm, thingtree * gfather, long gthingentry) : thischar(gchar), terminal(gterm), thingentry(gthingentry) { + if (!gfather) { + if (!root) { + root = new thingtree(); + } + father = root; + } else { + father = gfather; + } + brother = father->child; + father->child = this; +} + +thingtree::thingtree() : thischar(0), terminal(false), father(0), child(0), brother(0) { } + +long thingtree::look(const String s) { + long currentthing = -1; + thingtree * ptr = root; + int i; + + if (!ptr) { + printm(M_ERROR, "Error: thingtree not initialised\n"); + exit(-1); + } + + for (i = 0; s[i]; i++) { +// printm(M_INFO, "Looking for '%c'\n", *p); + for (ptr = ptr->child; ptr; ptr = ptr->brother) { +// printm(M_INFO, "Looking in %p: %c\n", ptr, ptr->thischar); + if (ptr->thischar == s[i]) { + if (ptr->terminal) { + currentthing = ptr->thingentry; + } + break; + } + } + if (!ptr) { +// printm(M_INFO, "Not found.\n"); + break; + } + } + + if (currentthing == -1) { + printm(M_ERROR, "Error, can't find any entry for string '" + s + "'\n"); + } + + return currentthing; +} + +void thingtree::addstring(const String s, long thingentry) { + thingtree * ptr, * fptr; + int i; + + if (!root) { + root = new thingtree(); + } + +// printm(M_INFO, "Creating new thingtree entry: %li='%s'\n", thingentry, s); + + ptr = root; + for (i = 0; s[i]; i++) { + fptr = ptr; +// printm(M_INFO, "Finding entry for '%c'\n", *p); + for (ptr = ptr->child; ptr; ptr = ptr->brother) { +// printm(M_INFO, "Browsing childs: %p = %c\n", ptr, ptr->thischar); + if (ptr->thischar == s[i]) + break; + } + + if (!ptr) { +// printm(M_INFO, "Creating new branch for %c\n", *p); + ptr = new thingtree(s[i], s[i + 1] == 0, fptr, thingentry); +// printm(M_INFO, "Created branch %p\n", ptr); + } else { + if (s[i + 1] == 0) { + ptr->terminal = true; + ptr->thingentry = thingentry; + } + } + } +} + +void thingtree::destroy() { + delete root; + root = 0; +} + +thingtree::~thingtree() { + if (father->child == this) + father->child = brother; + + while (child) + delete child; +} + +String things[256]; + +char * dte_text; +char dte_flags[256 * 256]; +long dte_counters[256 * 256]; +long dte_entries[256]; +char alloweds[256]; +long dte_usage[256]; + +long dte_most; +long dte_counter; +long dte_text_size; +int dte_size; +long gain; +long nb_dte = 0; +long tnb_dte = 0; + +void dte_reset(void) { + memset(dte_counters, 0, 0x40000); + dte_most = 0; + dte_counter = 0; +} + +void build_dte(void) { + int i; + Uint16 t, t2; + unsigned short p = 0; + + for (i = 0; i < dte_text_size; i++) { + t = *((Uint16 *) (dte_text + i)); + t2 = *((Uint16 *) (dte_text + i + 1)); + if (t == p) { + p = 0; + continue; + } + p = t; + if (!dte_flags[t]) { +// if ((!dte_flags[t]) && (dte_flags[t2] != 3)) { + if ((dte_counters[t]++) == 0) { + nb_dte++; + } + if (dte_counters[t] > dte_counter) { + dte_most = t; + dte_counter = dte_counters[t]; + } +// } else if (dte_flags[t] == 3) { +// i++; + } + } +} + +void push_entry(long entry) { + int i; + char t[3], c1, c2; + t[2] = 0; + + c1 = dte_most & 0xff; + c2 = dte_most >> 8; + t[0] = things[c1][0]; + t[1] = things[c2][0]; + + for (i = 0; i < 256; i++) { + if (!dte_entries[i]) { + dte_entries[i] = entry; + things[i] = strdup(t); + thingtree::addstring(t, i); + break; + } + } +} + +void dte_compress() { + int i, j; + char c1, c2; + + for (i = 0; i < 256; i++) { + for (j = 0; j < 256; j++) { + dte_flags[i * 256 + j] = alloweds[i] ? alloweds[j] ? 0 : 1 : 1; + } + } + + gain = 0; + + printm(M_STATUS, "Going for it: dte_size = %i\n", dte_size); + for (i = 0; i < dte_size; i++) { + dte_reset(); + build_dte(); + if (!tnb_dte) + tnb_dte = nb_dte; + c1 = dte_most & 0xff; + c2 = dte_most >> 8; + c1 = things[c1][0]; + c2 = things[c2][0]; + printm(M_INFO, "Entry #%i, most count: %li, couple = 0x%04x = (%c %c)\n", i, dte_counter, (int) dte_most, c1, c2); + dte_flags[dte_most] = 3; + gain += dte_counter; + push_entry(dte_most); + } + + printm(M_STATUS, "Estimated gain: %li bytes, new file size = %li\n", gain, dte_text_size - gain); +} + +void read_thingy(Handle * f) { + String line, st, thing; + long code; + int i; + + dte_size = 0; + + for (i = 0; i < 256; i++) { + dte_entries[i] = -1; + } + + while (1) { + line = "0x"; + *f >> st; + if (st.strlen()) { + line += st.extract(0, 1); + code = line.to_int(); + thing = st.extract(3); + switch (thing.strlen()) { + case 0: + dte_size++; + dte_entries[code] = 0; + break; + case 1: + alloweds[code] = 1; + default: + things[code] = thing; + thingtree::addstring(thing, code); + } + } + } +} + +void read_thingy_file(Handle * f) { + String line, trans; + long code; + int ptr = 0, i, c; + + for (i = 0; i < 256; i++) { + dte_usage[i] = 0; + } + + while (1) { + *f >> line; + if (!line.strlen()) + continue; + i = 0; + while (line[i]) { + if (line[i] == '<') { + if ((c = line.strchr('>', i)) < 0) { + printm(M_ERROR, "Error in file: '<' not closed.\n"); + exit(-1); + } + i++; + if (c == 2) { + trans = "0x" + line.extract(i, 2); + code = line.to_int(); + dte_text[ptr++] = code; + printm(M_BARE, "0x%02x-", code); + } else { + printm(M_BARE, "Unknow " + trans.extract(2) + "-"); + } + i += c; + } else { + if ((code = thingtree::look(line.extract(i))) == -1) + exit(-1); + dte_text[ptr++] = code; + i += things[code].strlen(); + printm(M_BARE, things[code] + "-"); + dte_usage[code]++; + } + } + printm(M_BARE, "\n"); + } + + dte_text[ptr] = dte_text[ptr + 1] = dte_text[ptr + 2] = dte_text[ptr + 3] = 0; + dte_text_size = ptr; +} diff --git a/lib/luapsx.cpp b/lib/luapsx.cpp index b68d3ab..eb1473b 100644 --- a/lib/luapsx.cpp +++ b/lib/luapsx.cpp @@ -1,307 +1,307 @@ -/* - * PSX-Tools Bundle Pack - * Copyright (C) 2002-2003 Nicolas "Pixel" Noble - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* $Id: luapsx.cpp,v 1.5 2004-07-16 15:04:52 pixel Exp $ */ - -#include -#include "luapsx.h" -#include "generic.h" - -void over(Byte * d, Byte R, Byte G, Byte B, Byte A) { - d[0] = R; - d[1] = G; - d[2] = B; -} - -void alpha(Byte * d, Byte R, Byte G, Byte B, Byte A) { - A = MIN(A, (Byte) 128); - d[0] = ((int)d[0] * (128 - A) + R * A) >> 7; - d[1] = ((int)d[1] * (128 - A) + G * A) >> 7; - d[2] = ((int)d[2] * (128 - A) + B * A) >> 7; -} - -void lighten(Byte * d, Byte R, Byte G, Byte B, Byte A) { - A = MIN(A, (Byte) 128); - R = ((int)d[0] * (128 - A) + R * A) >> 7; - G = ((int)d[1] * (128 - A) + G * A) >> 7; - B = ((int)d[2] * (128 - A) + B * A) >> 7; - d[0] = MAX(R, d[0]); - d[1] = MAX(G, d[1]); - d[2] = MAX(B, d[2]); -} - -void darken(Byte * d, Byte R, Byte G, Byte B, Byte A) { - A = MIN(A, (Byte) 128); - R = ((int)d[0] * (128 - A) + R * A) >> 7; - G = ((int)d[1] * (128 - A) + G * A) >> 7; - B = ((int)d[2] * (128 - A) + B * A) >> 7; - d[0] = MIN(R, d[0]); - d[1] = MIN(G, d[1]); - d[2] = MIN(B, d[2]); -} - -enum { - BLIT_OVER = 0, - BLIT_OVER32, - BLIT_ALPHA, - BLIT_LIGHTEN, - BLIT_LIGHTEN32, - BLIT_DARKEN, - BLIT_DARKEN32, -}; - -typedef void psx; - -enum psx_functions_t { - PSX_BSDECODE = 0, - PSX_BSENCODE, - PSX_BLIT, -}; - -struct lua_functypes_t psx_functions[] = { - { PSX_BSDECODE, "bsdecode", 3, 3, { LUA_OBJECT, LUA_NUMBER, LUA_NUMBER } }, - { PSX_BSENCODE, "bsencode", 3, 5, { LUA_OBJECT, LUA_NUMBER, LUA_NUMBER, LUA_NUMBER, LUA_NUMBER } }, - { PSX_BLIT, "blit", 9, 9, { LUA_OBJECT, LUA_OBJECT, LUA_NUMBER, LUA_NUMBER, LUA_NUMBER, LUA_NUMBER, LUA_NUMBER, LUA_NUMBER, LUA_NUMBER } }, - { -1, 0, 0, 0, 0 } -}; - -class sLua_psx : public Base { - public: - DECLARE_FUNCTION(psx, PSX_BSDECODE); - DECLARE_FUNCTION(psx, PSX_BSENCODE); - DECLARE_FUNCTION(psx, PSX_BLIT); - private: - static int psx_proceed_statics(Lua * L, int n, int caller); -}; - -void Luapsx::pushstatics(Lua * L) throw (GeneralException ) { - CHECK_FUNCTIONS(psx); - - PUSH_FUNCTION(psx, PSX_BSDECODE); - PUSH_FUNCTION(psx, PSX_BSENCODE); - PUSH_FUNCTION(psx, PSX_BLIT); - - L->push("BLIT_OVER"); - L->push((lua_Number) BLIT_OVER); - L->settable(LUA_GLOBALSINDEX); - - L->push("BLIT_OVER32"); - L->push((lua_Number) BLIT_OVER32); - L->settable(LUA_GLOBALSINDEX); - - L->push("BLIT_ALPHA"); - L->push((lua_Number) BLIT_ALPHA); - L->settable(LUA_GLOBALSINDEX); - - L->push("BLIT_LIGHTEN"); - L->push((lua_Number) BLIT_LIGHTEN); - L->settable(LUA_GLOBALSINDEX); - - L->push("BLIT_LIGHTEN32"); - L->push((lua_Number) BLIT_LIGHTEN32); - L->settable(LUA_GLOBALSINDEX); - - L->push("BLIT_DARKEN"); - L->push((lua_Number) BLIT_DARKEN); - L->settable(LUA_GLOBALSINDEX); - - L->push("BLIT_DARKEN32"); - L->push((lua_Number) BLIT_DARKEN32); - L->settable(LUA_GLOBALSINDEX); -} - -int sLua_psx::psx_proceed_statics(Lua * L, int n, int caller) { - int r = 0; - - switch (caller) { - case PSX_BSDECODE: - r = 1; - { - Buffer * b = new Buffer(true); - Handle * f = (Handle *) LuaObject::getme(L, 1); - int width = L->tonumber(2); - int height = L->tonumber(3); - Byte * in = (Byte *) malloc(f->GetSize() + 10); - Byte * out = (Byte *) malloc(width * height * 3); - LuaBuffer lb(b); - lb.pushdestruct(L); - f->read(in, f->GetSize()); - bs_decode_rgb24(out, (bs_header_t *) in, width, height, 0); - for (int i = 0; i < width * height * 3; i++) { - b[i] = out[i]; - } - free(out); - free(in); - } - case PSX_BSENCODE: - r = 3; - { - unsigned short out[0x80000]; - Buffer * b = new Buffer(true); - LuaBuffer lb(b); - lb.pushdestruct(L); - Handle * f = (Handle *) LuaObject::getme(L, 1); - bs_input_image_t img; - img.width = L->tonumber(2); - img.height = L->tonumber(3); - int max_size = 14112, cur_size; - int q_scale = 1; - if (n >= 4) - max_size = L->tonumber(4); - if (n >= 5) - q_scale = L->tonumber(5); - img.lpbits = (Byte *) malloc(f->GetSize()); - img.top = img.lpbits; - img.nextline = img.width * 3; - img.bit = 24; - - f->read(img.lpbits, f->GetSize()); - - bs_init(); - - cur_size = max_size + 1; - - for (cur_size = max_size + 1; max_size < cur_size; q_scale++) { - cur_size = bs_encode((bs_header_t *) out, &img, 2, q_scale, 0); - } - - for (int i = 0; i < cur_size; i++) { - b[i] = out[i]; - } - - L->push((lua_Number) cur_size); - L->push((lua_Number) q_scale); - } - case PSX_BLIT: - r = 0; - { - Handle * d = (Handle *) LuaObject::getme(L, 1); - Handle * s = (Handle *) LuaObject::getme(L, 2); - int dw = L->tonumber(3), - dh = L->tonumber(4), - sw = L->tonumber(5), - sh = L->tonumber(6), - sx = L->tonumber(7), - sy = L->tonumber(8), - bl = L->tonumber(9); - int bytes, dstart = 0, dskip = 0, sstart = 0, sskip = 0, i, j; - Byte RGB[3], R, G, B, A = 128; - void (*op_func)(Byte *, Byte, Byte, Byte, Byte); - - switch(bl) { - case BLIT_OVER: - bytes = 3; - op_func = over; - break; - case BLIT_OVER32: - bytes = 4; - op_func = over; - break; - case BLIT_ALPHA: - bytes = 4; - op_func = alpha; - break; - case BLIT_LIGHTEN: - bytes = 3; - op_func = lighten; - break; - case BLIT_LIGHTEN32: - bytes = 4; - op_func = lighten; - break; - case BLIT_DARKEN: - bytes = 3; - op_func = darken; - break; - case BLIT_DARKEN32: - bytes = 4; - op_func = darken; - break; - default: - L->error("Blitting operation unknown."); - return 0; - } - -#if 0 - if ((sx + sw) < 0) - return; - - if (sx >= dw) - return; - - if ((sy + sh) < 0) - return; - - if (sy >= dh) - return; -#endif - - if (sy < 0) { - sstart -= sw * bytes * sy; - sh += sy; - sy = 0; - } else { - dstart += dw * 3 * sy; - } - - if ((sy + sh) > dh) { - sh -= (sy + sh) - dh; - } - - if (sx < 0) { - sstart -= sx * bytes; - sskip -= sx * bytes; - sw += sx; - sx = 0; - } else { - dstart += sx * 3; - } - - if ((sx + sw) > dw) { - sskip += (sx + sw) - dw; - sw -= (sx + sw) - dw; - } - - dskip = (dw - sw) * 3; - - d->seek(dstart); - s->seek(sstart); - - for (i = 0; i < sh; i++, s->seek(sskip, SEEK_CUR), d->seek(dskip, SEEK_CUR)) { - for (j = 0; j < sw; j++) { - RGB[0] = d->readU8(); - RGB[1] = d->readU8(); - RGB[2] = d->readU8(); - d->seek(-3, SEEK_CUR); - R = s->readU8(); - G = s->readU8(); - B = s->readU8(); - if (bytes == 4) - A = s->readU8(); - op_func(RGB, R, G, B, A); - d->writeU8(R); - d->writeU8(G); - d->writeU8(B); - } - } - - } - } - return r; -} +/* + * PSX-Tools Bundle Pack + * Copyright (C) 2002-2003 Nicolas "Pixel" Noble + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id: luapsx.cpp,v 1.6 2004-11-27 21:44:48 pixel Exp $ */ + +#include +#include "luapsx.h" +#include "generic.h" + +void over(Byte * d, Byte R, Byte G, Byte B, Byte A) { + d[0] = R; + d[1] = G; + d[2] = B; +} + +void alpha(Byte * d, Byte R, Byte G, Byte B, Byte A) { + A = MIN(A, (Byte) 128); + d[0] = ((int)d[0] * (128 - A) + R * A) >> 7; + d[1] = ((int)d[1] * (128 - A) + G * A) >> 7; + d[2] = ((int)d[2] * (128 - A) + B * A) >> 7; +} + +void lighten(Byte * d, Byte R, Byte G, Byte B, Byte A) { + A = MIN(A, (Byte) 128); + R = ((int)d[0] * (128 - A) + R * A) >> 7; + G = ((int)d[1] * (128 - A) + G * A) >> 7; + B = ((int)d[2] * (128 - A) + B * A) >> 7; + d[0] = MAX(R, d[0]); + d[1] = MAX(G, d[1]); + d[2] = MAX(B, d[2]); +} + +void darken(Byte * d, Byte R, Byte G, Byte B, Byte A) { + A = MIN(A, (Byte) 128); + R = ((int)d[0] * (128 - A) + R * A) >> 7; + G = ((int)d[1] * (128 - A) + G * A) >> 7; + B = ((int)d[2] * (128 - A) + B * A) >> 7; + d[0] = MIN(R, d[0]); + d[1] = MIN(G, d[1]); + d[2] = MIN(B, d[2]); +} + +enum { + BLIT_OVER = 0, + BLIT_OVER32, + BLIT_ALPHA, + BLIT_LIGHTEN, + BLIT_LIGHTEN32, + BLIT_DARKEN, + BLIT_DARKEN32, +}; + +typedef void psx; + +enum psx_functions_t { + PSX_BSDECODE = 0, + PSX_BSENCODE, + PSX_BLIT, +}; + +struct lua_functypes_t psx_functions[] = { + { PSX_BSDECODE, "bsdecode", 3, 3, { LUA_OBJECT, LUA_NUMBER, LUA_NUMBER } }, + { PSX_BSENCODE, "bsencode", 3, 5, { LUA_OBJECT, LUA_NUMBER, LUA_NUMBER, LUA_NUMBER, LUA_NUMBER } }, + { PSX_BLIT, "blit", 9, 9, { LUA_OBJECT, LUA_OBJECT, LUA_NUMBER, LUA_NUMBER, LUA_NUMBER, LUA_NUMBER, LUA_NUMBER, LUA_NUMBER, LUA_NUMBER } }, + { -1, 0, 0, 0, 0 } +}; + +class sLua_psx : public Base { + public: + DECLARE_FUNCTION(psx, PSX_BSDECODE); + DECLARE_FUNCTION(psx, PSX_BSENCODE); + DECLARE_FUNCTION(psx, PSX_BLIT); + private: + static int psx_proceed_statics(Lua * L, int n, int caller); +}; + +void Luapsx::pushstatics(Lua * L) throw (GeneralException ) { + CHECK_FUNCTIONS(psx); + + PUSH_FUNCTION(psx, PSX_BSDECODE); + PUSH_FUNCTION(psx, PSX_BSENCODE); + PUSH_FUNCTION(psx, PSX_BLIT); + + L->push("BLIT_OVER"); + L->push((lua_Number) BLIT_OVER); + L->settable(LUA_GLOBALSINDEX); + + L->push("BLIT_OVER32"); + L->push((lua_Number) BLIT_OVER32); + L->settable(LUA_GLOBALSINDEX); + + L->push("BLIT_ALPHA"); + L->push((lua_Number) BLIT_ALPHA); + L->settable(LUA_GLOBALSINDEX); + + L->push("BLIT_LIGHTEN"); + L->push((lua_Number) BLIT_LIGHTEN); + L->settable(LUA_GLOBALSINDEX); + + L->push("BLIT_LIGHTEN32"); + L->push((lua_Number) BLIT_LIGHTEN32); + L->settable(LUA_GLOBALSINDEX); + + L->push("BLIT_DARKEN"); + L->push((lua_Number) BLIT_DARKEN); + L->settable(LUA_GLOBALSINDEX); + + L->push("BLIT_DARKEN32"); + L->push((lua_Number) BLIT_DARKEN32); + L->settable(LUA_GLOBALSINDEX); +} + +int sLua_psx::psx_proceed_statics(Lua * L, int n, int caller) { + int r = 0; + + switch (caller) { + case PSX_BSDECODE: + r = 1; + { + Buffer * b = new Buffer(true); + Handle * f = (Handle *) LuaObject::getme(L, 1); + int width = L->tonumber(2); + int height = L->tonumber(3); + Byte * in = (Byte *) malloc(f->GetSize() + 10); + Byte * out = (Byte *) malloc(width * height * 3); + LuaBuffer lb(b); + lb.pushdestruct(L); + f->read(in, f->GetSize()); + bs_decode_rgb24(out, (bs_header_t *) in, width, height, 0); + for (int i = 0; i < width * height * 3; i++) { + b[i] = out[i]; + } + free(out); + free(in); + } + case PSX_BSENCODE: + r = 3; + { + unsigned short out[0x80000]; + Buffer * b = new Buffer(true); + LuaBuffer lb(b); + lb.pushdestruct(L); + Handle * f = (Handle *) LuaObject::getme(L, 1); + bs_input_image_t img; + img.width = L->tonumber(2); + img.height = L->tonumber(3); + int max_size = 14112, cur_size; + int q_scale = 1; + if (n >= 4) + max_size = L->tonumber(4); + if (n >= 5) + q_scale = L->tonumber(5); + img.lpbits = (Byte *) malloc(f->GetSize()); + img.top = img.lpbits; + img.nextline = img.width * 3; + img.bit = 24; + + f->read(img.lpbits, f->GetSize()); + + bs_init(); + + cur_size = max_size + 1; + + for (cur_size = max_size + 1; max_size < cur_size; q_scale++) { + cur_size = bs_encode((bs_header_t *) out, &img, 2, q_scale, 0); + } + + for (int i = 0; i < cur_size; i++) { + b[i] = out[i]; + } + + L->push((lua_Number) cur_size); + L->push((lua_Number) q_scale); + } + case PSX_BLIT: + r = 0; + { + Handle * d = (Handle *) LuaObject::getme(L, 1); + Handle * s = (Handle *) LuaObject::getme(L, 2); + int dw = L->tonumber(3), + dh = L->tonumber(4), + sw = L->tonumber(5), + sh = L->tonumber(6), + sx = L->tonumber(7), + sy = L->tonumber(8), + bl = L->tonumber(9); + int bytes, dstart = 0, dskip = 0, sstart = 0, sskip = 0, i, j; + Byte RGB[3], R, G, B, A = 128; + void (*op_func)(Byte *, Byte, Byte, Byte, Byte); + + switch(bl) { + case BLIT_OVER: + bytes = 3; + op_func = over; + break; + case BLIT_OVER32: + bytes = 4; + op_func = over; + break; + case BLIT_ALPHA: + bytes = 4; + op_func = alpha; + break; + case BLIT_LIGHTEN: + bytes = 3; + op_func = lighten; + break; + case BLIT_LIGHTEN32: + bytes = 4; + op_func = lighten; + break; + case BLIT_DARKEN: + bytes = 3; + op_func = darken; + break; + case BLIT_DARKEN32: + bytes = 4; + op_func = darken; + break; + default: + L->error("Blitting operation unknown."); + return 0; + } + +#if 0 + if ((sx + sw) < 0) + return; + + if (sx >= dw) + return; + + if ((sy + sh) < 0) + return; + + if (sy >= dh) + return; +#endif + + if (sy < 0) { + sstart -= sw * bytes * sy; + sh += sy; + sy = 0; + } else { + dstart += dw * 3 * sy; + } + + if ((sy + sh) > dh) { + sh -= (sy + sh) - dh; + } + + if (sx < 0) { + sstart -= sx * bytes; + sskip -= sx * bytes; + sw += sx; + sx = 0; + } else { + dstart += sx * 3; + } + + if ((sx + sw) > dw) { + sskip += (sx + sw) - dw; + sw -= (sx + sw) - dw; + } + + dskip = (dw - sw) * 3; + + d->seek(dstart); + s->seek(sstart); + + for (i = 0; i < sh; i++, s->seek(sskip, SEEK_CUR), d->seek(dskip, SEEK_CUR)) { + for (j = 0; j < sw; j++) { + RGB[0] = d->readU8(); + RGB[1] = d->readU8(); + RGB[2] = d->readU8(); + d->seek(-3, SEEK_CUR); + R = s->readU8(); + G = s->readU8(); + B = s->readU8(); + if (bytes == 4) + A = s->readU8(); + op_func(RGB, R, G, B, A); + d->writeU8(R); + d->writeU8(G); + d->writeU8(B); + } + } + + } + } + return r; +} diff --git a/lib/lzss.cpp b/lib/lzss.cpp index 1d7ecfb..7b134aa 100644 --- a/lib/lzss.cpp +++ b/lib/lzss.cpp @@ -1,464 +1,464 @@ -/* - * PSX-Tools Bundle Pack - * Copyright (C) 2002 Nicolas "Pixel" Noble - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include "generic.h" -#include "lzss.h" -#include "Handle.h" - -lzss::lzss() : tolerate(1), blockb(0), scheme(schemes[0]), lzss_maxsize(18), lzss_maxptr(0x0fff) { - compute_limits(); -} - -/* - -Valkyrie Profile V2: - -JJJJJJJJ LLLLJJJJ -VVVVVVVV 1111RRRR -RRRRRRRR 11110000 VVVVVVVV - -*/ - -const lzss::scheme_t lzss::schemes[] = { -/* Nom 1 I J O N 16 P F W Lm1 Ls1 Lm2 Ls2 Jm1 Js1 Jm2 Js2 Fm1 Fs1 Fm2 Fs2 Vm1 Vs1 Vm2 Vs2 Flags*/ -#if 0 /* Zelda GC */ - {"Yaz0", 0, 1, 1, 0, 0, 0, 0, 0, 0, 0xf0, -4, 0x00, 0, 0x0f, 8, 0xff, 0, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0}, -#endif - {"Xenogears", 1, 0, 0, 1, 0, 0, 0, 0, 0, 0x00, 0, 0xf0, -4, 0xff, 0, 0x0f, 8, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0}, - {"DBZ RPG", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0f, 0, 0x00, 0, 0xf0, -4, 0xff, 4, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0}, - {"FF7", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0, 0x0f, 0, 0xff, 0, 0xf0, 4, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0}, - {"Leen Mean", 1, 1, 1, 1, 0, 0, 0, 0, 0, 0x0f, 0, 0x00, 0, 0xf0, 4, 0xff, 0, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0}, - {"Metal Max", 0, 0, 0, 1, 0, 0, 2, 0, 0x12, 0x00, 0, 0x0f, 0, 0xff, 0, 0xf0, 4, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0}, - {"Ogre Battle", 0, 0, 0, 1, 0, 0, 1, 0, 0, 0xf8, -3, 0x00, 0, 0x07, 8, 0xff, 0, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0}, - {"Lodoss Wars", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0, 0x7f, 0, 0xff, 0, 0x80, 1, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0}, - {"FF6 PSX", 0, 0, 0, 1, 1, 1, 0, 0, 0, 0x1f, 1, 0x00, 0, 0xe0, -4, 0xff, 4, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0}, - {"Valkyrie-1", 0, 0, 0, 1, 1, 0, 0, 0, 0, 0x00, 0, 0xf0, -4, 0xff, 0, 0x0f, 8, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0}, - {"Valkyrie-2", 0, 0, 0, 1, 1, 0, 0, 2, 0, 0x00, 0, 0xf0, -4, 0xff, 0, 0x0f, 8, 0x00, 0, 0x0f, 0, 0xff, 0, 0x00, 0}, - {"ToD", 0, 0, 0,-1, 1, 0, 1, 1, 3, 0x00, 0, 0x0f, 0, 0xff, 0, 0xf0, 4, 0x00, 0, 0xf0, -4, 0xff, 0, 0x00, 0}, - {0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0} -}; - -Byte lzss::swap_bits(Byte i) { - i = ((i >> 1) & 0x55) | ((i << 1) & 0xaa); - i = ((i >> 2) & 0x33) | ((i << 2) & 0xcc); - i = ((i >> 4) & 0x0f) | ((i << 4) & 0xf0); - return i; -} - -unsigned int lzss::shift(unsigned int c, int s) { - return s > 0 ? (c << s) : c >> (-s); -} - -void lzss::compute_limits(void) { - unsigned char val1, val2; - - val1 = val2 = 0xff; - - lzss_maxsize = shift(val1 & scheme.l_mask_1, scheme.l_shft_1) | - shift(val2 & scheme.l_mask_2, scheme.l_shft_2); - lzss_maxptr = shift(val1 & scheme.j_mask_1, scheme.j_shft_1) | - shift(val2 & scheme.j_mask_2, scheme.j_shft_2); - - lzss_maxsize = lzss_maxsize + 3 + scheme.sixteen_bits; - lzss_maxptr += scheme.one_jump; - - if (scheme.l_mask_1 & scheme.j_mask_1) { - printm(M_ERROR, "Masks are overlapping for value 1\n"); - exit(-1); - } - - if (scheme.l_mask_2 & scheme.j_mask_2) { - printm(M_ERROR, "Masks are overlapping for value 2\n"); - exit(-1); - } - - if (shift(scheme.l_mask_1, scheme.l_shft_1) & shift(scheme.l_mask_2, scheme.l_shft_2)) { - printm(M_ERROR, "Shifts build an overlap for lenght\n"); - exit(-1); - } - - if (shift(scheme.j_mask_1, scheme.j_shft_1) & shift(scheme.j_mask_2, scheme.j_shft_2)) { - printm(M_ERROR, "Shifts build an overlap for jump\n"); - exit(-1); - } - - printm(M_INFO, "Computed values: maxsize = %i, maxptr = 0x%06x\n", lzss_maxsize, lzss_maxptr); -} - -unsigned int lzss::lzss_decomp(Handle * f_source, Handle * f_cible, int true_length) -{ - unsigned char bitmap, fbitmap; - unsigned char valeur; - unsigned char * text_buf; - unsigned char val1, val2, val3; - int negative_error = scheme.negative_trick, overlap_error = scheme.overlap_trick == 1; - int r = 0; - int decomp_count; - int decomp_length; - int decomp_fill; - int decomp_jump; - int decomp_offset = 0; - int loop_length; - int whole_count; - int i, j; - int length, reads; - - compute_limits(); - - f_source->read(&length, 4); - if (true_length >= 0) { - length = true_length; - } - whole_count = 0; - - printm(M_INFO, "Decompressing %i bytes\n", length); - - text_buf = (unsigned char *) malloc(length + 8); - - do { - f_source->read(&bitmap, 1); - if (scheme.sixteen_bits) { - f_source->read(&fbitmap, 1); - printm(M_INFO, "16bits behavior, false bitmap = %02x\n", fbitmap); - } - printm(M_INFO, "Begin of block, bitmap = %02x\n", bitmap); - if (scheme.bitmap_inversed) { - bitmap = swap_bits(bitmap); - } - for (i = 0; i < 8; i++) { - printm(M_INFO, " - Chunk %i (offset cible = %li = 0x%04x, offset source = %li = 0x%04x)\n", i, f_cible->tell(), f_cible->tell(), f_source->tell(), f_source->tell()); - if (whole_count >= length) - break; - if ((bitmap & 1) ^ scheme.one_is_compressed) { - for (j = 0; j < (scheme.sixteen_bits ? 2 : 1); j++) { - reads = f_source->read(&valeur, 1); - if (!reads) { - printm(M_WARNING, " WARNING! PADDING!\n"); - free(text_buf); - return length; - } - printm(M_INFO, " Copying 0x%02x\n", valeur); - f_cible->write(&valeur, 1); - text_buf[r++] = valeur; - whole_count++; - } - } else { - f_source->read(&val1, 1); - f_source->read(&val2, 1); - decomp_length = shift(val1 & scheme.l_mask_1, scheme.l_shft_1) | - shift(val2 & scheme.l_mask_2, scheme.l_shft_2); - decomp_fill = shift(val1 & scheme.f_mask_1, scheme.f_shft_1) | - shift(val2 & scheme.f_mask_2, scheme.f_shft_2); - decomp_jump = shift(val1 & scheme.j_mask_1, scheme.j_shft_1) | - shift(val2 & scheme.j_mask_2, scheme.j_shft_2); - valeur = shift(val1 & scheme.v_mask_1, scheme.v_shft_1) | - shift(val2 & scheme.v_mask_2, scheme.v_shft_2); -// decomp_jump &= lzss_maxptr; bad, ugly, non working - decomp_jump += scheme.one_jump; - decomp_length = decomp_length + 3 + scheme.sixteen_bits; - decomp_fill = decomp_fill + 3 + scheme.sixteen_bits; -#if 0 /* Zelda GC */ - decomp_length--; - if (decomp_length == 2) { - printm(M_INFO, "Big jump\n"); - decomp_length = f_source->readU8() + 18; - } -#endif - if ((decomp_length == lzss_maxsize) && (scheme.filling)) { - if ((decomp_fill == 3) && (scheme.filling == 2)) { - f_source->read(&val3, 1); - printm(M_INFO, " Found an extended needle (val1 = 0x%02x, val2 = 0x%02x, val3 = 0x%02x)\n", val1, val2, val3); - decomp_fill = val1 + 19; - valeur = val3; - } else { - printm(M_INFO, " Found a 0x%02x-filling needle of %li bytes (val1 = 0x%02x, val2 = 0x%02x)\n", valeur, decomp_fill, val1, val2); - } - for (decomp_count = 0; decomp_count < decomp_fill; decomp_count++) { - f_cible->write(&valeur, 1); - text_buf[r++] = valeur; - if (!blockb) - whole_count++; - } - if (blockb) - whole_count++; - } else { - switch (scheme.ptrb) { - case 0: - decomp_offset = r - decomp_jump; - break; - case 1: - decomp_offset = r - lzss_maxptr - 1 + decomp_jump - scheme.window_start; - break; - case 2: - decomp_offset = decomp_jump - scheme.window_start; - break; - } - decomp_offset += scheme.overlap_trick == -1 ? decomp_length : 0; - loop_length = decomp_offset + decomp_length; - if ((loop_length >= r) && (!overlap_error)) { - if (!tolerate) { - free(text_buf); - return 0; - } - printm(M_ERROR, "Overlap trick used without it beeing enabled in the scheme.\n"); - overlap_error = 1; - } - printm(M_INFO, " Found a needle of %li bytes at %li = 0x%04x, jump of %li = 0x%04x (val1 = 0x%02x, val2 = 0x%02x)\n", decomp_length, decomp_offset, decomp_offset, decomp_jump, decomp_jump, val1, val2); - for (decomp_count = decomp_offset; decomp_count < loop_length; decomp_count++) { - if (!blockb) - whole_count++; - if (decomp_count < 0) { - valeur = 0; - f_cible->write(&valeur, 1); - text_buf[r++] = 0; - if (!negative_error) { - if (!tolerate) { - free(text_buf); - return 0; - } - printm(M_ERROR, "Negative trick used without it beeing enabled in the scheme.\n"); - negative_error = 1; - } - printm(M_INFO, "Filling with 0\n"); - } else { - f_cible->write(&text_buf[decomp_count], 1); - printm(M_INFO, "@0x%04x: 0x%02x\n", decomp_count, text_buf[decomp_count]); - text_buf[r++] = text_buf[decomp_count]; - } - if (whole_count >= length) - break; - } - if (blockb) - whole_count++; - } - } - bitmap >>= 1; - } - } while (whole_count < length); - free(text_buf); - - return length; -} - -unsigned char lzss::lzss_rd(unsigned char * t, int p) { - return ((p < 0) ? 0 : (t[p])); -} - -int lzss::lzss_comp_strstr(unsigned char * needle, unsigned char * r, int * l, int sp) { - char redo[256]; - int length, i, p, ptr, maxlength; - - i = 1; - redo[0] = p = 0; - while (i < lzss_maxsize) { - if (needle[i] == needle[p]) { - redo[i++] = ++p; - } else if (p > 0) { - p = redo[p - 1]; - } else { - redo[i++] = 0; - } - } - - length = maxlength = 0; - i = sp; - p = 0; - ptr = 0; - - while ((i - sp - (scheme.overlap_trick ? p : 0)) < *l) { - if (needle[p] == lzss_rd(r, i)) { - if (p == (lzss_maxsize - 1)) { - *l = lzss_maxsize; - return i - lzss_maxsize + 1; - } - i++; - p++; - } else if (p > 0) { - if (p > maxlength) { - if (!((i - p) & scheme.sixteen_bits)) { - ptr = i - (maxlength = p); - } - } - p = redo[p - 1]; - } else { - i++; - } - } - - *l = maxlength; - return ptr; -} - -unsigned char * lzss::lzss_memcomp(unsigned char * r, int * l, int * delta) { - unsigned char bitmap, * comp; - int ptr, needle, needle_length, comp_ptr, bitmap_ptr, val1, val2; - int jump, farest, remaining; - int j; - - comp = (unsigned char *) malloc(3 * *l); - - compute_limits(); - - ptr = 0; - blk = 0; - bitmap_count = 0; - comp_ptr = 1 + scheme.sixteen_bits; - bitmap = 0; - bitmap_ptr = 0; - printm(M_INFO, "Begin of block 0.\n"); - while ((remaining = *l - ptr) > 0) { - printm(M_INFO, " Remaining bytes: %li\n", remaining); - lzss_maxsize = MIN(lzss_maxsize, remaining); - bitmap_count++; - bitmap >>= 1; - farest = ptr - lzss_maxptr; - farest = farest > ((-lzss_maxsize) * scheme.negative_trick) ? farest : -lzss_maxsize * scheme.negative_trick; - needle_length = ptr - farest; - if (scheme.ptrb == 2) { - farest = 0; - needle_length = MIN(lzss_maxptr - scheme.window_start, ptr); - } - needle = lzss_comp_strstr(&r[ptr], r, &needle_length, farest); - if ((needle < 0) && ((-needle) > needle_length)) { - needle = -needle_length; - } - printm(M_INFO, " - Chunk %i (offset source = %li = 0x%04x, offset cible = %li = 0x%04x)\n", bitmap_count - 1, ptr, ptr, comp_ptr, comp_ptr); - jump = ptr - needle; - needle_length = needle_length > remaining ? remaining : needle_length; - - if (needle_length & scheme.sixteen_bits) { - needle_length--; - } - - if ((needle < 0) || (!jump)) { - printm(M_INFO, " Nothing found.\n"); - } else { - printm(M_INFO, " Found a needle of %i bytes at offset %i (jump = %i = 0x%04x)\n", needle_length, needle, jump, jump); - } - - if ((needle_length <= (2 + scheme.sixteen_bits)) || (!jump)) { - if (needle_length > 2) { - printm(M_ERROR, " ** REJECTED **\n"); - } - for (j = 0; j < (scheme.sixteen_bits ? 2 : 1); j++) { - printm(M_INFO, " Repeating 0x%02x\n", r[ptr]); - comp[comp_ptr] = r[ptr]; - ptr++; - comp_ptr++; - } - bitmap |= 0x80; - } else { - int j; - printm(M_INFO, " Found a needle of %li bytes at %li = 0x%04x\n", needle_length, needle, needle); - for (j = 0; j < needle_length; j++) { - printm(M_INFO, "@0x%04x: 0x%02x - @0x%04x: 0x%02x\n", needle + j, lzss_rd(r, needle + j - scheme.window_start), ptr + j, lzss_rd(r, ptr + j)); - if (lzss_rd(r, needle + j) != lzss_rd(r, ptr + j)) { - printm(M_ERROR, "ERROR!!\n"); - } - } - jump -= scheme.one_jump; - printm(M_INFO, "ptr = %li, needle = %li, jump = %li = 0x%03x\n", ptr, needle, jump, jump); - ptr += needle_length; - needle_length -= 3; - switch (scheme.ptrb) { - case 0: - break; - case 1: - jump = lzss_maxptr + 1 - jump; - break; - case 2: - jump = needle + scheme.window_start; - break; - } - val1 = comp[comp_ptr++] = (shift(jump, -scheme.j_shft_1) & scheme.j_mask_1) | - (shift(needle_length, -scheme.l_shft_1) & scheme.l_mask_1); - val2 = comp[comp_ptr++] = (shift(jump, -scheme.j_shft_2) & scheme.j_mask_2) | - (shift(needle_length, -scheme.l_shft_2) & scheme.l_mask_2); - printm(M_INFO, " writing info1 = 0x%02x, info2 = 0x%02x\n", val1, val2); - } - - bitmap ^= scheme.one_is_compressed << 7; - - if (bitmap_count == 8) { - blk++; - printm(M_INFO, "End of block, writing bitmap = 0x%02x\n", bitmap); - printm(M_INFO, "Begin of block %li.\n", blk); - bitmap_count = 0; - if (scheme.bitmap_inversed) - bitmap = swap_bits(bitmap); - comp[bitmap_ptr] = bitmap; - if (scheme.sixteen_bits) { - comp[bitmap_ptr + 1] = 0; - } - bitmap_ptr = comp_ptr; - comp_ptr += (scheme.sixteen_bits ? 2 : 1); - } - } - - if (bitmap_count) { - bitmap >>= (8 - bitmap_count); - if (scheme.bitmap_inversed) - bitmap = swap_bits(bitmap); - comp[bitmap_ptr] = bitmap; - if (scheme.sixteen_bits) { - comp[bitmap_ptr + 1] = 0; - } - } else { - comp_ptr--; - } - - if (delta) { - *delta = (bitmap_count ? 8 - bitmap_count : 0); - } - - *l = comp_ptr; - return comp; -} - -void lzss::lzss_comp(Handle * f_source, Handle * f_cible, int * delta) { - int length = f_source->GetSize(), l; - unsigned char * r = (unsigned char *) malloc(length), * c; - - f_source->read(r, length); - l = length; - c = lzss_memcomp(r, &l, delta); - if (delta) { - length += *delta; - } - f_cible->write(&length, 4); - if (delta) { - length -= *delta; - } - f_cible->write(c, l); - free(c); - free(r); -} - -void lzss::change_scheme(scheme_t new_scheme) { - scheme = new_scheme; - compute_limits(); -} - -lzss::scheme_t lzss::get_scheme() { - return scheme; -} +/* + * PSX-Tools Bundle Pack + * Copyright (C) 2002 Nicolas "Pixel" Noble + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include "generic.h" +#include "lzss.h" +#include "Handle.h" + +lzss::lzss() : tolerate(1), blockb(0), scheme(schemes[0]), lzss_maxsize(18), lzss_maxptr(0x0fff) { + compute_limits(); +} + +/* + +Valkyrie Profile V2: + +JJJJJJJJ LLLLJJJJ +VVVVVVVV 1111RRRR +RRRRRRRR 11110000 VVVVVVVV + +*/ + +const lzss::scheme_t lzss::schemes[] = { +/* Nom 1 I J O N 16 P F W Lm1 Ls1 Lm2 Ls2 Jm1 Js1 Jm2 Js2 Fm1 Fs1 Fm2 Fs2 Vm1 Vs1 Vm2 Vs2 Flags*/ +#if 0 /* Zelda GC */ + {"Yaz0", 0, 1, 1, 0, 0, 0, 0, 0, 0, 0xf0, -4, 0x00, 0, 0x0f, 8, 0xff, 0, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0}, +#endif + {"Xenogears", 1, 0, 0, 1, 0, 0, 0, 0, 0, 0x00, 0, 0xf0, -4, 0xff, 0, 0x0f, 8, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0}, + {"DBZ RPG", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0f, 0, 0x00, 0, 0xf0, -4, 0xff, 4, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0}, + {"FF7", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0, 0x0f, 0, 0xff, 0, 0xf0, 4, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0}, + {"Leen Mean", 1, 1, 1, 1, 0, 0, 0, 0, 0, 0x0f, 0, 0x00, 0, 0xf0, 4, 0xff, 0, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0}, + {"Metal Max", 0, 0, 0, 1, 0, 0, 2, 0, 0x12, 0x00, 0, 0x0f, 0, 0xff, 0, 0xf0, 4, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0}, + {"Ogre Battle", 0, 0, 0, 1, 0, 0, 1, 0, 0, 0xf8, -3, 0x00, 0, 0x07, 8, 0xff, 0, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0}, + {"Lodoss Wars", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0, 0x7f, 0, 0xff, 0, 0x80, 1, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0}, + {"FF6 PSX", 0, 0, 0, 1, 1, 1, 0, 0, 0, 0x1f, 1, 0x00, 0, 0xe0, -4, 0xff, 4, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0}, + {"Valkyrie-1", 0, 0, 0, 1, 1, 0, 0, 0, 0, 0x00, 0, 0xf0, -4, 0xff, 0, 0x0f, 8, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0}, + {"Valkyrie-2", 0, 0, 0, 1, 1, 0, 0, 2, 0, 0x00, 0, 0xf0, -4, 0xff, 0, 0x0f, 8, 0x00, 0, 0x0f, 0, 0xff, 0, 0x00, 0}, + {"ToD", 0, 0, 0,-1, 1, 0, 1, 1, 3, 0x00, 0, 0x0f, 0, 0xff, 0, 0xf0, 4, 0x00, 0, 0xf0, -4, 0xff, 0, 0x00, 0}, + {0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0} +}; + +Byte lzss::swap_bits(Byte i) { + i = ((i >> 1) & 0x55) | ((i << 1) & 0xaa); + i = ((i >> 2) & 0x33) | ((i << 2) & 0xcc); + i = ((i >> 4) & 0x0f) | ((i << 4) & 0xf0); + return i; +} + +unsigned int lzss::shift(unsigned int c, int s) { + return s > 0 ? (c << s) : c >> (-s); +} + +void lzss::compute_limits(void) { + unsigned char val1, val2; + + val1 = val2 = 0xff; + + lzss_maxsize = shift(val1 & scheme.l_mask_1, scheme.l_shft_1) | + shift(val2 & scheme.l_mask_2, scheme.l_shft_2); + lzss_maxptr = shift(val1 & scheme.j_mask_1, scheme.j_shft_1) | + shift(val2 & scheme.j_mask_2, scheme.j_shft_2); + + lzss_maxsize = lzss_maxsize + 3 + scheme.sixteen_bits; + lzss_maxptr += scheme.one_jump; + + if (scheme.l_mask_1 & scheme.j_mask_1) { + printm(M_ERROR, "Masks are overlapping for value 1\n"); + exit(-1); + } + + if (scheme.l_mask_2 & scheme.j_mask_2) { + printm(M_ERROR, "Masks are overlapping for value 2\n"); + exit(-1); + } + + if (shift(scheme.l_mask_1, scheme.l_shft_1) & shift(scheme.l_mask_2, scheme.l_shft_2)) { + printm(M_ERROR, "Shifts build an overlap for lenght\n"); + exit(-1); + } + + if (shift(scheme.j_mask_1, scheme.j_shft_1) & shift(scheme.j_mask_2, scheme.j_shft_2)) { + printm(M_ERROR, "Shifts build an overlap for jump\n"); + exit(-1); + } + + printm(M_INFO, "Computed values: maxsize = %i, maxptr = 0x%06x\n", lzss_maxsize, lzss_maxptr); +} + +unsigned int lzss::lzss_decomp(Handle * f_source, Handle * f_cible, int true_length) +{ + unsigned char bitmap, fbitmap; + unsigned char valeur; + unsigned char * text_buf; + unsigned char val1, val2, val3; + int negative_error = scheme.negative_trick, overlap_error = scheme.overlap_trick == 1; + int r = 0; + int decomp_count; + int decomp_length; + int decomp_fill; + int decomp_jump; + int decomp_offset = 0; + int loop_length; + int whole_count; + int i, j; + int length, reads; + + compute_limits(); + + f_source->read(&length, 4); + if (true_length >= 0) { + length = true_length; + } + whole_count = 0; + + printm(M_INFO, "Decompressing %i bytes\n", length); + + text_buf = (unsigned char *) malloc(length + 8); + + do { + f_source->read(&bitmap, 1); + if (scheme.sixteen_bits) { + f_source->read(&fbitmap, 1); + printm(M_INFO, "16bits behavior, false bitmap = %02x\n", fbitmap); + } + printm(M_INFO, "Begin of block, bitmap = %02x\n", bitmap); + if (scheme.bitmap_inversed) { + bitmap = swap_bits(bitmap); + } + for (i = 0; i < 8; i++) { + printm(M_INFO, " - Chunk %i (offset cible = %li = 0x%04x, offset source = %li = 0x%04x)\n", i, f_cible->tell(), f_cible->tell(), f_source->tell(), f_source->tell()); + if (whole_count >= length) + break; + if ((bitmap & 1) ^ scheme.one_is_compressed) { + for (j = 0; j < (scheme.sixteen_bits ? 2 : 1); j++) { + reads = f_source->read(&valeur, 1); + if (!reads) { + printm(M_WARNING, " WARNING! PADDING!\n"); + free(text_buf); + return length; + } + printm(M_INFO, " Copying 0x%02x\n", valeur); + f_cible->write(&valeur, 1); + text_buf[r++] = valeur; + whole_count++; + } + } else { + f_source->read(&val1, 1); + f_source->read(&val2, 1); + decomp_length = shift(val1 & scheme.l_mask_1, scheme.l_shft_1) | + shift(val2 & scheme.l_mask_2, scheme.l_shft_2); + decomp_fill = shift(val1 & scheme.f_mask_1, scheme.f_shft_1) | + shift(val2 & scheme.f_mask_2, scheme.f_shft_2); + decomp_jump = shift(val1 & scheme.j_mask_1, scheme.j_shft_1) | + shift(val2 & scheme.j_mask_2, scheme.j_shft_2); + valeur = shift(val1 & scheme.v_mask_1, scheme.v_shft_1) | + shift(val2 & scheme.v_mask_2, scheme.v_shft_2); +// decomp_jump &= lzss_maxptr; bad, ugly, non working + decomp_jump += scheme.one_jump; + decomp_length = decomp_length + 3 + scheme.sixteen_bits; + decomp_fill = decomp_fill + 3 + scheme.sixteen_bits; +#if 0 /* Zelda GC */ + decomp_length--; + if (decomp_length == 2) { + printm(M_INFO, "Big jump\n"); + decomp_length = f_source->readU8() + 18; + } +#endif + if ((decomp_length == lzss_maxsize) && (scheme.filling)) { + if ((decomp_fill == 3) && (scheme.filling == 2)) { + f_source->read(&val3, 1); + printm(M_INFO, " Found an extended needle (val1 = 0x%02x, val2 = 0x%02x, val3 = 0x%02x)\n", val1, val2, val3); + decomp_fill = val1 + 19; + valeur = val3; + } else { + printm(M_INFO, " Found a 0x%02x-filling needle of %li bytes (val1 = 0x%02x, val2 = 0x%02x)\n", valeur, decomp_fill, val1, val2); + } + for (decomp_count = 0; decomp_count < decomp_fill; decomp_count++) { + f_cible->write(&valeur, 1); + text_buf[r++] = valeur; + if (!blockb) + whole_count++; + } + if (blockb) + whole_count++; + } else { + switch (scheme.ptrb) { + case 0: + decomp_offset = r - decomp_jump; + break; + case 1: + decomp_offset = r - lzss_maxptr - 1 + decomp_jump - scheme.window_start; + break; + case 2: + decomp_offset = decomp_jump - scheme.window_start; + break; + } + decomp_offset += scheme.overlap_trick == -1 ? decomp_length : 0; + loop_length = decomp_offset + decomp_length; + if ((loop_length >= r) && (!overlap_error)) { + if (!tolerate) { + free(text_buf); + return 0; + } + printm(M_ERROR, "Overlap trick used without it beeing enabled in the scheme.\n"); + overlap_error = 1; + } + printm(M_INFO, " Found a needle of %li bytes at %li = 0x%04x, jump of %li = 0x%04x (val1 = 0x%02x, val2 = 0x%02x)\n", decomp_length, decomp_offset, decomp_offset, decomp_jump, decomp_jump, val1, val2); + for (decomp_count = decomp_offset; decomp_count < loop_length; decomp_count++) { + if (!blockb) + whole_count++; + if (decomp_count < 0) { + valeur = 0; + f_cible->write(&valeur, 1); + text_buf[r++] = 0; + if (!negative_error) { + if (!tolerate) { + free(text_buf); + return 0; + } + printm(M_ERROR, "Negative trick used without it beeing enabled in the scheme.\n"); + negative_error = 1; + } + printm(M_INFO, "Filling with 0\n"); + } else { + f_cible->write(&text_buf[decomp_count], 1); + printm(M_INFO, "@0x%04x: 0x%02x\n", decomp_count, text_buf[decomp_count]); + text_buf[r++] = text_buf[decomp_count]; + } + if (whole_count >= length) + break; + } + if (blockb) + whole_count++; + } + } + bitmap >>= 1; + } + } while (whole_count < length); + free(text_buf); + + return length; +} + +unsigned char lzss::lzss_rd(unsigned char * t, int p) { + return ((p < 0) ? 0 : (t[p])); +} + +int lzss::lzss_comp_strstr(unsigned char * needle, unsigned char * r, int * l, int sp) { + char redo[256]; + int length, i, p, ptr, maxlength; + + i = 1; + redo[0] = p = 0; + while (i < lzss_maxsize) { + if (needle[i] == needle[p]) { + redo[i++] = ++p; + } else if (p > 0) { + p = redo[p - 1]; + } else { + redo[i++] = 0; + } + } + + length = maxlength = 0; + i = sp; + p = 0; + ptr = 0; + + while ((i - sp - (scheme.overlap_trick ? p : 0)) < *l) { + if (needle[p] == lzss_rd(r, i)) { + if (p == (lzss_maxsize - 1)) { + *l = lzss_maxsize; + return i - lzss_maxsize + 1; + } + i++; + p++; + } else if (p > 0) { + if (p > maxlength) { + if (!((i - p) & scheme.sixteen_bits)) { + ptr = i - (maxlength = p); + } + } + p = redo[p - 1]; + } else { + i++; + } + } + + *l = maxlength; + return ptr; +} + +unsigned char * lzss::lzss_memcomp(unsigned char * r, int * l, int * delta) { + unsigned char bitmap, * comp; + int ptr, needle, needle_length, comp_ptr, bitmap_ptr, val1, val2; + int jump, farest, remaining; + int j; + + comp = (unsigned char *) malloc(3 * *l); + + compute_limits(); + + ptr = 0; + blk = 0; + bitmap_count = 0; + comp_ptr = 1 + scheme.sixteen_bits; + bitmap = 0; + bitmap_ptr = 0; + printm(M_INFO, "Begin of block 0.\n"); + while ((remaining = *l - ptr) > 0) { + printm(M_INFO, " Remaining bytes: %li\n", remaining); + lzss_maxsize = MIN(lzss_maxsize, remaining); + bitmap_count++; + bitmap >>= 1; + farest = ptr - lzss_maxptr; + farest = farest > ((-lzss_maxsize) * scheme.negative_trick) ? farest : -lzss_maxsize * scheme.negative_trick; + needle_length = ptr - farest; + if (scheme.ptrb == 2) { + farest = 0; + needle_length = MIN(lzss_maxptr - scheme.window_start, ptr); + } + needle = lzss_comp_strstr(&r[ptr], r, &needle_length, farest); + if ((needle < 0) && ((-needle) > needle_length)) { + needle = -needle_length; + } + printm(M_INFO, " - Chunk %i (offset source = %li = 0x%04x, offset cible = %li = 0x%04x)\n", bitmap_count - 1, ptr, ptr, comp_ptr, comp_ptr); + jump = ptr - needle; + needle_length = needle_length > remaining ? remaining : needle_length; + + if (needle_length & scheme.sixteen_bits) { + needle_length--; + } + + if ((needle < 0) || (!jump)) { + printm(M_INFO, " Nothing found.\n"); + } else { + printm(M_INFO, " Found a needle of %i bytes at offset %i (jump = %i = 0x%04x)\n", needle_length, needle, jump, jump); + } + + if ((needle_length <= (2 + scheme.sixteen_bits)) || (!jump)) { + if (needle_length > 2) { + printm(M_ERROR, " ** REJECTED **\n"); + } + for (j = 0; j < (scheme.sixteen_bits ? 2 : 1); j++) { + printm(M_INFO, " Repeating 0x%02x\n", r[ptr]); + comp[comp_ptr] = r[ptr]; + ptr++; + comp_ptr++; + } + bitmap |= 0x80; + } else { + int j; + printm(M_INFO, " Found a needle of %li bytes at %li = 0x%04x\n", needle_length, needle, needle); + for (j = 0; j < needle_length; j++) { + printm(M_INFO, "@0x%04x: 0x%02x - @0x%04x: 0x%02x\n", needle + j, lzss_rd(r, needle + j - scheme.window_start), ptr + j, lzss_rd(r, ptr + j)); + if (lzss_rd(r, needle + j) != lzss_rd(r, ptr + j)) { + printm(M_ERROR, "ERROR!!\n"); + } + } + jump -= scheme.one_jump; + printm(M_INFO, "ptr = %li, needle = %li, jump = %li = 0x%03x\n", ptr, needle, jump, jump); + ptr += needle_length; + needle_length -= 3; + switch (scheme.ptrb) { + case 0: + break; + case 1: + jump = lzss_maxptr + 1 - jump; + break; + case 2: + jump = needle + scheme.window_start; + break; + } + val1 = comp[comp_ptr++] = (shift(jump, -scheme.j_shft_1) & scheme.j_mask_1) | + (shift(needle_length, -scheme.l_shft_1) & scheme.l_mask_1); + val2 = comp[comp_ptr++] = (shift(jump, -scheme.j_shft_2) & scheme.j_mask_2) | + (shift(needle_length, -scheme.l_shft_2) & scheme.l_mask_2); + printm(M_INFO, " writing info1 = 0x%02x, info2 = 0x%02x\n", val1, val2); + } + + bitmap ^= scheme.one_is_compressed << 7; + + if (bitmap_count == 8) { + blk++; + printm(M_INFO, "End of block, writing bitmap = 0x%02x\n", bitmap); + printm(M_INFO, "Begin of block %li.\n", blk); + bitmap_count = 0; + if (scheme.bitmap_inversed) + bitmap = swap_bits(bitmap); + comp[bitmap_ptr] = bitmap; + if (scheme.sixteen_bits) { + comp[bitmap_ptr + 1] = 0; + } + bitmap_ptr = comp_ptr; + comp_ptr += (scheme.sixteen_bits ? 2 : 1); + } + } + + if (bitmap_count) { + bitmap >>= (8 - bitmap_count); + if (scheme.bitmap_inversed) + bitmap = swap_bits(bitmap); + comp[bitmap_ptr] = bitmap; + if (scheme.sixteen_bits) { + comp[bitmap_ptr + 1] = 0; + } + } else { + comp_ptr--; + } + + if (delta) { + *delta = (bitmap_count ? 8 - bitmap_count : 0); + } + + *l = comp_ptr; + return comp; +} + +void lzss::lzss_comp(Handle * f_source, Handle * f_cible, int * delta) { + int length = f_source->GetSize(), l; + unsigned char * r = (unsigned char *) malloc(length), * c; + + f_source->read(r, length); + l = length; + c = lzss_memcomp(r, &l, delta); + if (delta) { + length += *delta; + } + f_cible->write(&length, 4); + if (delta) { + length -= *delta; + } + f_cible->write(c, l); + free(c); + free(r); +} + +void lzss::change_scheme(scheme_t new_scheme) { + scheme = new_scheme; + compute_limits(); +} + +lzss::scheme_t lzss::get_scheme() { + return scheme; +} diff --git a/lib/mips.cpp b/lib/mips.cpp index 1378227..05a1201 100644 --- a/lib/mips.cpp +++ b/lib/mips.cpp @@ -1,1068 +1,1068 @@ -/* - * PSX-Tools Bundle Pack - * Copyright (C) 2002-2003 Nicolas "Pixel" Noble - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* $Id: mips.cpp,v 1.3 2004-01-03 15:04:47 pixel Exp $ */ - -#include "mips.h" - -/* Code HIGHLY ripped off^W^W inspired from PCSX. */ - -#if 1 -char * registers[] = { - "0", "at", "v0", "v1", "a0", "a1", "a2", "a3", - "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", - "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", - "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra", -}; -#else -char * registers[] = { - "00", "01", "02", "03", "04", "05", "06", "07", - "08", "09", "0a", "0b", "0c", "0d", "0e", "0f", - "10", "11", "12", "13", "14", "15", "16", "17", - "18", "19", "1a", "1b", "1c", "1d", "1e", "1f", -}; -#endif - -char * CP0registers[] = { - "Index" , "Random" , "EntryLo0", "EntryLo1", "Context" , "PageMask" , "Wired" , "*Check me*", - "BadVAddr" , "Count" , "EntryHi" , "Compare" , "Status" , "Cause" , "ExceptPC" , "PRevID" , - "Config" , "LLAddr" , "WatchLo" , "WatchHi" , "XContext", "*RES*" , "*RES*" , "*RES*" , - "*RES*" , "*RES* " , "PErr" , "CacheErr", "TagLo" , "TagHi" , "ErrorEPC" , "*RES*" }; - -typedef void (*TdisR3000AF)(TDis *, Uint32 code, Uint32 pc); - -// These macros are used to assemble the disassembler functions -#define MakeDisF(fn, b) \ - static void fn(TDis * d, Uint32 code, Uint32 pc) { \ - d->pc = pc; \ - b; \ - } - -#define _Funct_ ((code ) & 0x3F) // The funct part of the instruction register -#define _Rd_ ((code >> 11) & 0x1F) // The rd part of the instruction register -#define _Rt_ ((code >> 16) & 0x1F) // The rt part of the instruction register -#define _Rs_ ((code >> 21) & 0x1F) // The rs part of the instruction register -#define _Sa_ ((code >> 6) & 0x1F) // The sa part of the instruction register -#define _Im_ ( code & 0xFFFF) // The immediate part of the instruction register - // The signed immediate part of the instruction register -#define _sIm_ (code & 0x8000 ? - (((~code) & 0x7FFF) + 1) : ( code & 0x7FFF)) - -#define _Target_ (0x80000000 + ((code & 0x03ffffff) * 4)) -#define _Branch_ (pc + 4 + ((short)_Im_ * 4)) -#define _OfB_ _Im_, _nRs_ - -#define dName(n) { d->Name(n); } -#define dGPR(i) { d->PushGPReg(i); } -#define dCP0(i) { d->PushCPReg(i); } -#define dImm() { d->PushImm(_Im_); } -#define dTarget() { d->PushTarget(_Target_); } -#define dSa() { d->PushSa(_Sa_); } -#if 0 -#define dOfB() { \ - Uint32 pcode = d->getmem()->Read32(pc - 4); \ - if ((((pcode >> 16) & 0x1F) == _Rs_) && ((pcode >> 26) == 0xf)) { \ - Uint32 full; \ - Uint16 lower; \ - int16 slower; \ - lower = _Im_; \ - slower = *((int16 *) &lower); \ - \ - full = ((pcode & 0xffff) << 16) + slower; \ - \ - d->PushOfB(_Rs_, full, width); \ - \ - dMemRefer(full, width); \ - } else { \ - d->PushOfB(_Rs_, _Im_, width); \ - } \ -} -#else -#define dOfB() { \ - d->PushOfB(_Rs_, _Im_, width); \ -} -#endif -#define dOffset() { \ - d->PushOffset(_Branch_); \ -} -// printf(" ; Maybe RefTo %8.8lX", offset); -#define dFull(full) { \ - d->PushFull(full); \ - d->Comment("MaybeRefTo..."); \ -} - -#define sep - -#define dInvalid() { \ - d->SetTag(pc, CODE, false); \ - d->SetTag(pc, STOP, true); \ - d->Invalid(); \ -} - -#define dSuspect() { \ - d->Suspect(); \ - d->Comment("Suspect!"); \ -} -#if 0 // with OfB... -// printf(" ; RefTo %8.8lX - %i bits", offset, width); -#define dMemRefer(offset, width) { \ - d->PushMemref(offset, width); \ - d->Comment("RefTo..."); \ -} -#endif - -#define Invalidate(reg) { \ - if (!reg) \ - dSuspect(); \ -} - -#define SetReg(reg, val) { \ - if (!reg) \ - dSuspect(); \ -} - -#define MarkFunction(target) { \ - d->add_function(target); \ -} - -#define Branch(branch) { \ - d->add_branch(branch); \ -} - -#define Jump(target) { \ - d->add_jump(target); \ -} - -#define Stop(target) { \ - d->SetTag(target, STOP, true); \ -} - -/********************************************************* -* Arithmetic with immediate operand * -* Format: OP rt, rs, immediate * -*********************************************************/ - -MakeDisF(disADDI, - dName("addi"); - - dGPR(_Rt_); sep; - if (_Rt_ != _Rs_) { - dGPR(_Rs_); sep; - } - dImm(); - - Invalidate(_Rt_); - - d->Comment("Add immediate"); -) - -MakeDisF(disADDIU, - if (!_Rs_) { - dName("li"); - - dGPR(_Rt_); sep; - dImm(); - - Uint32 full; - int32 sfull; - Uint16 lower; - int16 slower; - lower = _Im_; - slower = *((int16 *) &lower); - - sfull = slower; - full = *((Uint32 *) &sfull); - - SetReg(_Rt_, full); - - d->Comment("Load immediate"); - } else { - Uint32 pcode = d->getmem()->Read32(pc - 4); - if ((((pcode >> 16) & 0x1F) == _Rt_) && (_Rt_ == _Rs_) && ((pcode >> 26) == 0xf)) { - Uint32 full; - Uint16 lower; - int16 slower; - lower = _Im_; - slower = *((int16 *) &lower); - - full = ((pcode & 0xffff) << 16) + slower; - - dName("li"); - dGPR(_Rt_); sep; - dFull(full); - SetReg(_Rt_, full); - d->Comment("Load immediate (aggregate)"); - } else { - dName("addiu"); - - dGPR(_Rt_); sep; - if (_Rt_ != _Rs_) { - dGPR(_Rs_); sep; - } - dImm(); - - Invalidate(_Rt_); - - d->Comment("Add immediate"); - } - } -) - -MakeDisF(disANDI, - dName("andi"); - - dGPR(_Rt_); sep; - if (_Rt_ != _Rs_) { - dGPR(_Rs_); sep; - } - dImm(); - - Invalidate(_Rt_); - - d->Comment("And immediate"); -) - -MakeDisF(disORI, - if (!_Rs_) { - dName("liu"); - - dGPR(_Rt_); sep; - dImm(); - SetReg(_Rt_, _Im_); - - d->Comment("Load immediate without sign extension"); - } else { - dName("ori"); - - dGPR(_Rt_); sep; - if (_Rt_ != _Rs_) { - dGPR(_Rs_); sep; - } - dImm(); - Invalidate(_Rt_); - d->Comment("Or immediate"); - } -) - -MakeDisF(disSLTI, - dName("slti"); - - dGPR(_Rt_); sep; - if (_Rt_ != _Rs_) { - dGPR(_Rs_); sep; - } - dImm(); - - Invalidate(_Rt_); - - d->Comment(registers[_Rt_] + String(" = ") + registers[_Rs_] + " < immediate ? 1 : 0 (signed)"); -) - -MakeDisF(disSLTIU, - dName("sltiu"); - - dGPR(_Rt_); sep; - if (_Rt_ != _Rs_) { - dGPR(_Rs_); sep; - } - dImm(); - - Invalidate(_Rt_); - - d->Comment(registers[_Rt_] + String(" = ") + registers[_Rs_] + " < immediate ? 1 : 0 (unsigned)"); -) - -MakeDisF(disXORI, - dName("xori"); - - dGPR(_Rt_); sep; - if (_Rt_ != _Rs_) { - dGPR(_Rs_); sep; - } - dImm(); - - Invalidate(_Rt_); - - d->Comment("XOr immediate"); -) - -/********************************************************* -* Register arithmetic * -* Format: OP rd, rs, rt * -*********************************************************/ -MakeDisF(disADD, - dName("add"); - - dGPR(_Rd_); sep; - if (_Rd_ != _Rs_) { - dGPR(_Rs_); sep; - } - dGPR(_Rt_); - - Invalidate(_Rt_); - - d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " + " + registers[_Rt_]); -) - -MakeDisF(disADDU, - if (!_Rt_) { - dName("move"); - - dGPR(_Rd_); sep; - dGPR(_Rs_); - if (_Rs_) { - Invalidate(_Rd_); - } else { - SetReg(_Rd_, 0); - } - d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_]); - } else { - dName("addu"); - - dGPR(_Rd_); sep; - if (_Rd_ != _Rs_) { - dGPR(_Rs_); sep; - } - dGPR(_Rt_); - Invalidate(_Rd_); - d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " + " + registers[_Rt_]); - } -) - -MakeDisF(disAND, - dName("and"); - - dGPR(_Rd_); sep; - if (_Rd_ != _Rs_) { - dGPR(_Rs_); sep; - } - dGPR(_Rt_); - Invalidate(_Rd_); - d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " & " + registers[_Rt_]); -) - -MakeDisF(disNOR, - dName("nor"); - - dGPR(_Rd_); sep; - if (_Rd_ != _Rs_) { - dGPR(_Rs_); sep; - } - dGPR(_Rt_); - Invalidate(_Rd_); - d->Comment(String(registers[_Rd_]) + " = ~(" + registers[_Rs_] + " & " + registers[_Rt_] + ")"); -) - -MakeDisF(disOR, - dName("or"); - - dGPR(_Rd_); sep; - if (_Rd_ != _Rs_) { - dGPR(_Rs_); sep; - } - dGPR(_Rt_); - Invalidate(_Rd_); - d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " | " + registers[_Rt_]); -) - -MakeDisF(disSLT, - dName("slt"); - - dGPR(_Rd_); sep; - if (_Rd_ != _Rs_) { - dGPR(_Rs_); sep; - } - dGPR(_Rt_); - Invalidate(_Rd_); - d->Comment(registers[_Rd_] + String(" = ") + registers[_Rs_] + " < " + registers[_Rt_] + " ? 1 : 0 (signed)"); -) - -MakeDisF(disSLTU, - dName("sltu"); - - dGPR(_Rd_); sep; - if (_Rd_ != _Rs_) { - dGPR(_Rs_); sep; - } - dGPR(_Rt_); - Invalidate(_Rd_); - d->Comment(registers[_Rd_] + String(" = ") + registers[_Rs_] + " < " + registers[_Rt_] + " ? 1 : 0 (unsigned)"); -) - -MakeDisF(disSUB, - dName("sub"); - - dGPR(_Rd_); sep; - if (_Rd_ != _Rs_) { - dGPR(_Rs_); sep; - } - dGPR(_Rt_); - Invalidate(_Rd_); - d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " - " + registers[_Rt_]); -) - -MakeDisF(disSUBU, - dName("subu"); - - dGPR(_Rd_); sep; - if (_Rd_ != _Rs_) { - dGPR(_Rs_); sep; - } - dGPR(_Rt_); - Invalidate(_Rd_); - d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " - " + registers[_Rt_]); -) - -MakeDisF(disXOR, - dName("xor"); - - dGPR(_Rd_); sep; - if (_Rd_ != _Rs_) { - dGPR(_Rs_); sep; - } - dGPR(_Rt_); - Invalidate(_Rd_); - d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " ^ " + registers[_Rt_]); -) - -/********************************************************* -* Register arithmetic & Register trap logic * -* Format: OP rs, rt * -*********************************************************/ -MakeDisF(disDIV, - dName("div"); - - dGPR(_Rs_); sep; - dGPR(_Rt_); - - String c1 = String(registers[_Rs_]) + " / " + registers[_Rt_]; - String c2 = String(registers[_Rs_]) + " %% " + registers[_Rt_]; - - d->Comment("lo = " + c1 + "; hi = " + c2); -) - -MakeDisF(disDIVU, - dName("divu"); - - dGPR(_Rs_); sep; - dGPR(_Rt_); - - d->Comment(String("lo = " ) + registers[_Rs_] + " / " + registers[_Rt_] + "; hi = " + registers[_Rs_] + " % " + registers[_Rt_]); -) - -MakeDisF(disMULT, - dName("mult"); - - dGPR(_Rs_); sep; - dGPR(_Rt_); - - d->Comment(String("hilo = ") + registers[_Rs_] + " * " + registers[_Rt_]); -) - -MakeDisF(disMULTU, - dName("multu"); - - dGPR(_Rs_); sep; - dGPR(_Rt_); - - d->Comment(String("hilo = ") + registers[_Rs_] + " * " + registers[_Rt_]); -) - -/********************************************************* -* Register branch logic * -* Format: OP rs, offset * -*********************************************************/ -MakeDisF(disBGEZ, - dName("bgez"); - - dGPR(_Rs_); sep; - dOffset(); - Branch(_Branch_); - d->Comment("Branch if " + String(registers[_Rs_]) + " >= 0"); -) - -MakeDisF(disBGEZAL, - dName("bgezal"); - - dGPR(_Rs_); sep; - dOffset(); - Branch(_Branch_); - d->Comment("Branch and link if " + String(registers[_Rs_]) + " >= 0"); -) - -MakeDisF(disBGTZ, - dName("bgtz"); - - dGPR(_Rs_); sep; - dOffset(); - Branch(_Branch_); - d->Comment("Branch if " + String(registers[_Rs_]) + " > 0"); -) - -MakeDisF(disBLEZ, - dName("blez"); - - dGPR(_Rs_); sep; - dOffset(); - Branch(_Branch_); - d->Comment("Branch if " + String(registers[_Rs_]) + " <= 0"); -) - -MakeDisF(disBLTZ, - dName("bltz"); - - dGPR(_Rs_); sep; - dOffset(); - Branch(_Branch_); - d->Comment("Branch if " + String(registers[_Rs_]) + " < 0"); -) - -MakeDisF(disBLTZAL, - dName("bltzal"); - - dGPR(_Rs_); sep; - dOffset(); - Branch(_Branch_); - d->Comment("Branch and link if " + String(registers[_Rs_]) + " <= 0"); -) - -/********************************************************* -* Shift arithmetic with constant shift * -* Format: OP rd, rt, sa * -*********************************************************/ -MakeDisF(disSLL, - if ((!_Rd_) && (!_Rt_)) { - dName("nop"); - if (code) { - dSuspect(); - } - } else { - dName("sll"); - - dGPR(_Rd_); sep; - if (_Rd_ != _Rt_) { - dGPR(_Rt_); sep; - } - dSa(); - Invalidate(_Rd_); - d->Comment(String(registers[_Rd_]) + " = " + registers[_Rt_] + " << immediate"); - } -) - -MakeDisF(disSRA, - dName("sra"); - - dGPR(_Rd_); sep; - if (_Rd_ != _Rt_) { - dGPR(_Rt_); sep; - } - dSa(); - Invalidate(_Rd_); - d->Comment(String(registers[_Rd_]) + " = " + registers[_Rt_] + " >> immediate (arithmetic)"); -) - -MakeDisF(disSRL, - dName("srl"); - - dGPR(_Rd_); sep; - if (_Rd_ != _Rt_) { - dGPR(_Rt_); sep; - } - dSa(); - Invalidate(_Rd_); - d->Comment(String(registers[_Rd_]) + " = " + registers[_Rt_] + " >> immediate (logical)"); -) - -/********************************************************* -* Shift arithmetic with variant register shift * -* Format: OP rd, rt, rs * -*********************************************************/ -MakeDisF(disSLLV, - dName("sllv"); - - dGPR(_Rd_); sep; - if (_Rd_ != _Rt_) { - dGPR(_Rt_); sep; - } - dGPR(_Rs_); - Invalidate(_Rd_); - d->Comment(String(registers[_Rd_]) + " = " + registers[_Rt_] + " << " + registers[_Rs_]); -) - -MakeDisF(disSRAV, - dName("srav"); - - dGPR(_Rd_); sep; - if (_Rd_ != _Rt_) { - dGPR(_Rt_); sep; - } - dGPR(_Rs_); - Invalidate(_Rd_); - d->Comment(String(registers[_Rd_]) + " = " + registers[_Rt_] + " >> " + registers[_Rs_] + " (arithmetic)"); -) - -MakeDisF(disSRLV, - dName("srlv"); - - dGPR(_Rd_); sep; - if (_Rd_ != _Rt_) { - dGPR(_Rt_); sep; - } - dGPR(_Rs_); - Invalidate(_Rd_); - d->Comment(String(registers[_Rd_]) + " = " + registers[_Rt_] + " >> " + registers[_Rs_] + " (logical)"); -) - -/********************************************************* -* Load higher 16 bits of the first word in GPR with imm * -* Format: OP rt, immediate * -*********************************************************/ -MakeDisF(disLUI, - dName("lui"); - - dGPR(_Rt_); sep; - dImm(); - - Invalidate(_Rt_); - - d->Comment("Load upper immediate"); -) - -/********************************************************* -* Move from HI/LO to GPR * -* Format: OP rd * -*********************************************************/ -MakeDisF(disMFHI, - dName("mfhi"); - - dGPR(_Rd_); - Invalidate(_Rd_); - - d->Comment(String(registers[_Rd_]) + " = hi"); -) - -MakeDisF(disMFLO, - dName("mflo"); - - dGPR(_Rd_); - Invalidate(_Rd_); - - d->Comment(String(registers[_Rd_]) + " = lo"); -) - -/********************************************************* -* Move from GPR to HI/LO * -* Format: OP rd * -*********************************************************/ -MakeDisF(disMTHI, - dName("mthi"); - - dGPR(_Rd_); - - d->Comment("hi = " + String(registers[_Rd_])); -) - -MakeDisF(disMTLO, - dName("mtlo"); - - dGPR(_Rd_); - - d->Comment("lo = " + String(registers[_Rd_])); -) - -/********************************************************* -* Special purpose instructions * -* Format: OP * -*********************************************************/ -MakeDisF(disBREAK, - dName("break"); - - Stop(pc + 4); - - d->Comment("Stops the machine"); -) -MakeDisF(disRFE, dName("rfe")) - -MakeDisF(disSYSCALL, - int syscall; - dName("syscall"); - syscall = code & 0xfffff; - - d->Comment(String("Syscall number ") + syscall); -) - -MakeDisF(disHLE, dName("hle")) - -MakeDisF(disRTPS, dName("rtps")) -MakeDisF(disOP , dName("op")) -MakeDisF(disNCLIP, dName("nclip")) -MakeDisF(disDPCS, dName("dpcs")) -MakeDisF(disINTPL, dName("intpl")) -MakeDisF(disMVMVA, dName("mvmva")) -MakeDisF(disNCDS , dName("ncds")) -MakeDisF(disCDP , dName("cdp")) -MakeDisF(disNCDT , dName("ncdt")) -MakeDisF(disNCCS , dName("nccs")) -MakeDisF(disCC , dName("cc")) -MakeDisF(disNCS , dName("ncs")) -MakeDisF(disNCT , dName("nct")) -MakeDisF(disSQR , dName("sqr")) -MakeDisF(disDCPL , dName("dcpl")) -MakeDisF(disDPCT , dName("dpct")) -MakeDisF(disAVSZ3, dName("avsz3")) -MakeDisF(disAVSZ4, dName("avsz4")) -MakeDisF(disRTPT , dName("rtpt")) -MakeDisF(disGPF , dName("gpf")) -MakeDisF(disGPL , dName("gpl")) -MakeDisF(disNCCT , dName("ncct")) - -MakeDisF(disMFC2, dName("mfc2"); dGPR(_Rt_); Invalidate(_Rt_); ) -MakeDisF(disCFC2, dName("cfc2"); dGPR(_Rt_); Invalidate(_Rt_); ) -MakeDisF(disMTC2, dName("mtc2"); dGPR(_Rt_);) -MakeDisF(disCTC2, dName("ctc2"); dGPR(_Rt_);) - -/********************************************************* -* Register branch logic * -* Format: OP rs, rt, offset * -*********************************************************/ -MakeDisF(disBEQ, - if ((!_Rt_) && (!_Rs_)) { - dName("b"); - - dOffset(); - Branch(_Branch_); - Stop(pc + 8); - - d->Comment("Branch always"); - } - if (!_Rt_) { - dName("bez"); - - dGPR(_Rs_); sep; - dOffset(); - Branch(_Branch_); - - d->Comment(String("Branch if ") + registers[_Rs_] + " == 0"); - } else { - dName("beq"); - - dGPR(_Rs_); sep; - dGPR(_Rt_); sep; - dOffset(); - Branch(_Branch_); - - d->Comment(String("Branch if ") + registers[_Rs_] + " == " + registers[_Rt_]); - } -) - -MakeDisF(disBNE, - if (!_Rt_) { - dName("bnz"); - - dGPR(_Rs_); sep; - dOffset(); - Branch(_Branch_); - - d->Comment(String("Branch if ") + registers[_Rs_] + " != 0"); - } else { - dName("bne"); - - dGPR(_Rs_); sep; - dGPR(_Rt_); sep; - dOffset(); - Branch(_Branch_); - - d->Comment(String("Branch if ") + registers[_Rs_] + " != " + registers[_Rt_]); - } -) - -/********************************************************* -* Jump to target * -* Format: OP target * -*********************************************************/ -MakeDisF(disJ, - dName("j"); - - dTarget(); - Jump(_Target_); - Stop(pc + 8); - - d->Comment("Jump always"); -) - -MakeDisF(disJAL, - dName("jal"); - - dTarget(); - Invalidate(Rra); - MarkFunction(_Target_); - - d->Comment("Jump and link (function call)"); -) - -/********************************************************* -* Register jump * -* Format: OP rs, rd * -*********************************************************/ -MakeDisF(disJR, - dName("jr"); - dGPR(_Rs_); - Stop(pc + 8); - - d->Comment("Jump register"); -) - -MakeDisF(disJALR, - dName("jalr"); - - dGPR(_Rs_); - - if ((_Rd_) != Rra) { - sep; dGPR(_Rd_); - } - - Invalidate(_Rd_); - - d->Comment("Jump and link register (function call)"); -) - -/********************************************************* -* Load and store for GPR * -* Format: OP rt, offset(base) * -*********************************************************/ -MakeDisF(disLB, - int width = 8; - dName("lb"); - - dGPR(_Rt_); sep; - dOfB(); - - Invalidate(_Rt_); - d->Comment("Load signed byte"); -) - -MakeDisF(disLBU, - int width = 8; - dName("lbu"); - - dGPR(_Rt_); sep; - dOfB(); - - Invalidate(_Rt_); - d->Comment("Load unsigned byte"); -) - -MakeDisF(disLH, - int width = 16; - dName("lh"); - - dGPR(_Rt_); sep; - dOfB(); - - Invalidate(_Rt_); - d->Comment("Load signed half"); -) - -MakeDisF(disLHU, - int width = 16; - dName("lhu"); - - dGPR(_Rt_); sep; - dOfB(); - - Invalidate(_Rt_); - d->Comment("Load unsigned half"); -) - -MakeDisF(disLW, - int width = 32; - dName("lw"); - - dGPR(_Rt_); sep; - dOfB(); - - Invalidate(_Rt_); - d->Comment("Load word"); -) - -MakeDisF(disLWL, - int width = 32; - dName("lwl"); - - dGPR(_Rt_); sep; - dOfB(); - - Invalidate(_Rt_); - d->Comment("Load word left"); -) - -MakeDisF(disLWR, - int width = 32; - dName("lwr"); - - dGPR(_Rt_); sep; - dOfB(); - - Invalidate(_Rt_); - d->Comment("Load word right"); -) - -MakeDisF(disLWC2, - int width = 32; - dName("lwc2"); - - dCP0(_Rt_); sep; - dOfB(); -) - -MakeDisF(disSB, - int width = 8; - dName("sb"); - - dGPR(_Rt_); sep; - dOfB(); - d->Comment("Store byte"); -) - -MakeDisF(disSH, - int width = 16; - dName("sh"); - - dGPR(_Rt_); sep; - dOfB(); - d->Comment("Store half"); -) - -MakeDisF(disSW, - int width = 32; - dName("sw"); - - dGPR(_Rt_); sep; - dOfB(); - d->Comment("Store word"); -) - -MakeDisF(disSWL, - int width = 32; - dName("swl"); - - dGPR(_Rt_); sep; - dOfB(); - d->Comment("Store word left"); -) - -MakeDisF(disSWR, - int width = 32; - dName("swr"); - - dGPR(_Rt_); sep; - dOfB(); - d->Comment("Store word right"); -) - -MakeDisF(disSWC2, - int width = 32; - dName("swc2"); - - dGPR(_Rt_); sep; - dOfB(); -) - -/********************************************************* -* Moves between GPR and COPx * -* Format: OP rt, fs * -*********************************************************/ -MakeDisF(disMFC0, dName("mfc0"); dGPR(_Rt_); sep; dCP0(_Rd_); Invalidate(_Rt_);) -MakeDisF(disMTC0, dName("mtc0"); dCP0(_Rd_); sep; dGPR(_Rt_);) -MakeDisF(disCFC0, dName("cfc0"); dGPR(_Rt_); sep; dCP0(_Rd_); Invalidate(_Rt_);) -MakeDisF(disCTC0, dName("ctc0"); dCP0(_Rd_); sep; dGPR(_Rt_);) - -/********************************************************* -* Unknow instruction (would generate an exception) * -* Format: ? * -*********************************************************/ -MakeDisF(disNULL, - dName("*** Bad OP ***"); - dInvalid(); -) - - -TdisR3000AF disR3000A_SPECIAL[] = { // Subset of disSPECIAL - disSLL , disNULL , disSRL , disSRA , disSLLV , disNULL , disSRLV , disSRAV , - disJR , disJALR , disNULL, disNULL, disSYSCALL, disBREAK , disNULL , disNULL , - disMFHI, disMTHI , disMFLO, disMTLO, disNULL , disNULL , disNULL , disNULL , - disMULT, disMULTU, disDIV , disDIVU, disNULL , disNULL , disNULL , disNULL , - disADD , disADDU , disSUB , disSUBU, disAND , disOR , disXOR , disNOR , - disNULL, disNULL , disSLT , disSLTU, disNULL , disNULL , disNULL , disNULL , - disNULL, disNULL , disNULL, disNULL, disNULL , disNULL , disNULL , disNULL , - disNULL, disNULL , disNULL, disNULL, disNULL , disNULL , disNULL , disNULL}; - -MakeDisF(disSPECIAL, disR3000A_SPECIAL[_Funct_](d, code, pc)) - -TdisR3000AF disR3000A_BCOND[] = { // Subset of disBCOND - disBLTZ , disBGEZ , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, - disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, - disBLTZAL, disBGEZAL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, - disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL}; - -MakeDisF(disBCOND, disR3000A_BCOND[_Rt_](d, code, pc)) - -TdisR3000AF disR3000A_COP0[] = { // Subset of disCOP0 - disMFC0, disNULL, disCFC0, disNULL, disMTC0, disNULL, disCTC0, disNULL, - disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, - disRFE , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, - disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL}; - -MakeDisF(disCOP0, disR3000A_COP0[_Rs_](d, code, pc)) - -TdisR3000AF disR3000A_BASIC[] = { // Subset of disBASIC (based on rs) - disMFC2, disNULL, disCFC2, disNULL, disMTC2, disNULL, disCTC2, disNULL, - disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, - disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, - disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL}; - -MakeDisF(disBASIC, disR3000A_BASIC[_Rs_](d, code, pc)) - -TdisR3000AF disR3000A_COP2[] = { // Subset of disR3000F_COP2 (based on funct) - disBASIC, disRTPS , disNULL , disNULL , disNULL, disNULL , disNCLIP, disNULL, - disNULL , disNULL , disNULL , disNULL , disOP , disNULL , disNULL , disNULL, - disDPCS , disINTPL, disMVMVA, disNCDS , disCDP , disNULL , disNCDT , disNULL, - disNULL , disNULL , disNULL , disNCCS , disCC , disNULL , disNCS , disNULL, - disNCT , disNULL , disNULL , disNULL , disNULL, disNULL , disNULL , disNULL, - disSQR , disDCPL , disDPCT , disNULL , disNULL, disAVSZ3, disAVSZ4, disNULL, - disRTPT , disNULL , disNULL , disNULL , disNULL, disNULL , disNULL , disNULL, - disNULL , disNULL , disNULL , disNULL , disNULL, disGPF , disGPL , disNCCT }; - -MakeDisF(disCOP2, disR3000A_COP2[_Funct_](d, code, pc)) - -TdisR3000AF disR3000A[] = { - disSPECIAL , disBCOND , disJ , disJAL , disBEQ , disBNE , disBLEZ , disBGTZ , - disADDI , disADDIU , disSLTI , disSLTIU, disANDI, disORI , disXORI , disLUI , - disCOP0 , disNULL , disCOP2 , disNULL , disNULL, disNULL, disNULL , disNULL , - disNULL , disNULL , disNULL , disNULL , disNULL, disNULL, disNULL , disNULL , - disLB , disLH , disLWL , disLW , disLBU , disLHU , disLWR , disNULL , - disSB , disSH , disSWL , disSW , disNULL, disNULL, disSWR , disNULL , - disNULL , disNULL , disLWC2 , disNULL , disNULL, disNULL, disNULL , disNULL , - disNULL , disNULL , disSWC2 , disHLE , disNULL, disNULL, disNULL , disNULL }; - -//MakeDisFg(disR3000AF, disR3000A[code >> 26](code, pc)) - -void decode(TDis * d, Uint32 pc) { - Uint32 code = d->getmem()->Read32(pc); - disR3000A[code >> 26](d, code, pc); -} +/* + * PSX-Tools Bundle Pack + * Copyright (C) 2002-2003 Nicolas "Pixel" Noble + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id: mips.cpp,v 1.4 2004-11-27 21:44:48 pixel Exp $ */ + +#include "mips.h" + +/* Code HIGHLY ripped off^W^W inspired from PCSX. */ + +#if 1 +char * registers[] = { + "0", "at", "v0", "v1", "a0", "a1", "a2", "a3", + "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", + "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", + "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra", +}; +#else +char * registers[] = { + "00", "01", "02", "03", "04", "05", "06", "07", + "08", "09", "0a", "0b", "0c", "0d", "0e", "0f", + "10", "11", "12", "13", "14", "15", "16", "17", + "18", "19", "1a", "1b", "1c", "1d", "1e", "1f", +}; +#endif + +char * CP0registers[] = { + "Index" , "Random" , "EntryLo0", "EntryLo1", "Context" , "PageMask" , "Wired" , "*Check me*", + "BadVAddr" , "Count" , "EntryHi" , "Compare" , "Status" , "Cause" , "ExceptPC" , "PRevID" , + "Config" , "LLAddr" , "WatchLo" , "WatchHi" , "XContext", "*RES*" , "*RES*" , "*RES*" , + "*RES*" , "*RES* " , "PErr" , "CacheErr", "TagLo" , "TagHi" , "ErrorEPC" , "*RES*" }; + +typedef void (*TdisR3000AF)(TDis *, Uint32 code, Uint32 pc); + +// These macros are used to assemble the disassembler functions +#define MakeDisF(fn, b) \ + static void fn(TDis * d, Uint32 code, Uint32 pc) { \ + d->pc = pc; \ + b; \ + } + +#define _Funct_ ((code ) & 0x3F) // The funct part of the instruction register +#define _Rd_ ((code >> 11) & 0x1F) // The rd part of the instruction register +#define _Rt_ ((code >> 16) & 0x1F) // The rt part of the instruction register +#define _Rs_ ((code >> 21) & 0x1F) // The rs part of the instruction register +#define _Sa_ ((code >> 6) & 0x1F) // The sa part of the instruction register +#define _Im_ ( code & 0xFFFF) // The immediate part of the instruction register + // The signed immediate part of the instruction register +#define _sIm_ (code & 0x8000 ? - (((~code) & 0x7FFF) + 1) : ( code & 0x7FFF)) + +#define _Target_ (0x80000000 + ((code & 0x03ffffff) * 4)) +#define _Branch_ (pc + 4 + ((short)_Im_ * 4)) +#define _OfB_ _Im_, _nRs_ + +#define dName(n) { d->Name(n); } +#define dGPR(i) { d->PushGPReg(i); } +#define dCP0(i) { d->PushCPReg(i); } +#define dImm() { d->PushImm(_Im_); } +#define dTarget() { d->PushTarget(_Target_); } +#define dSa() { d->PushSa(_Sa_); } +#if 0 +#define dOfB() { \ + Uint32 pcode = d->getmem()->Read32(pc - 4); \ + if ((((pcode >> 16) & 0x1F) == _Rs_) && ((pcode >> 26) == 0xf)) { \ + Uint32 full; \ + Uint16 lower; \ + int16 slower; \ + lower = _Im_; \ + slower = *((int16 *) &lower); \ + \ + full = ((pcode & 0xffff) << 16) + slower; \ + \ + d->PushOfB(_Rs_, full, width); \ + \ + dMemRefer(full, width); \ + } else { \ + d->PushOfB(_Rs_, _Im_, width); \ + } \ +} +#else +#define dOfB() { \ + d->PushOfB(_Rs_, _Im_, width); \ +} +#endif +#define dOffset() { \ + d->PushOffset(_Branch_); \ +} +// printf(" ; Maybe RefTo %8.8lX", offset); +#define dFull(full) { \ + d->PushFull(full); \ + d->Comment("MaybeRefTo..."); \ +} + +#define sep + +#define dInvalid() { \ + d->SetTag(pc, CODE, false); \ + d->SetTag(pc, STOP, true); \ + d->Invalid(); \ +} + +#define dSuspect() { \ + d->Suspect(); \ + d->Comment("Suspect!"); \ +} +#if 0 // with OfB... +// printf(" ; RefTo %8.8lX - %i bits", offset, width); +#define dMemRefer(offset, width) { \ + d->PushMemref(offset, width); \ + d->Comment("RefTo..."); \ +} +#endif + +#define Invalidate(reg) { \ + if (!reg) \ + dSuspect(); \ +} + +#define SetReg(reg, val) { \ + if (!reg) \ + dSuspect(); \ +} + +#define MarkFunction(target) { \ + d->add_function(target); \ +} + +#define Branch(branch) { \ + d->add_branch(branch); \ +} + +#define Jump(target) { \ + d->add_jump(target); \ +} + +#define Stop(target) { \ + d->SetTag(target, STOP, true); \ +} + +/********************************************************* +* Arithmetic with immediate operand * +* Format: OP rt, rs, immediate * +*********************************************************/ + +MakeDisF(disADDI, + dName("addi"); + + dGPR(_Rt_); sep; + if (_Rt_ != _Rs_) { + dGPR(_Rs_); sep; + } + dImm(); + + Invalidate(_Rt_); + + d->Comment("Add immediate"); +) + +MakeDisF(disADDIU, + if (!_Rs_) { + dName("li"); + + dGPR(_Rt_); sep; + dImm(); + + Uint32 full; + int32 sfull; + Uint16 lower; + int16 slower; + lower = _Im_; + slower = *((int16 *) &lower); + + sfull = slower; + full = *((Uint32 *) &sfull); + + SetReg(_Rt_, full); + + d->Comment("Load immediate"); + } else { + Uint32 pcode = d->getmem()->Read32(pc - 4); + if ((((pcode >> 16) & 0x1F) == _Rt_) && (_Rt_ == _Rs_) && ((pcode >> 26) == 0xf)) { + Uint32 full; + Uint16 lower; + int16 slower; + lower = _Im_; + slower = *((int16 *) &lower); + + full = ((pcode & 0xffff) << 16) + slower; + + dName("li"); + dGPR(_Rt_); sep; + dFull(full); + SetReg(_Rt_, full); + d->Comment("Load immediate (aggregate)"); + } else { + dName("addiu"); + + dGPR(_Rt_); sep; + if (_Rt_ != _Rs_) { + dGPR(_Rs_); sep; + } + dImm(); + + Invalidate(_Rt_); + + d->Comment("Add immediate"); + } + } +) + +MakeDisF(disANDI, + dName("andi"); + + dGPR(_Rt_); sep; + if (_Rt_ != _Rs_) { + dGPR(_Rs_); sep; + } + dImm(); + + Invalidate(_Rt_); + + d->Comment("And immediate"); +) + +MakeDisF(disORI, + if (!_Rs_) { + dName("liu"); + + dGPR(_Rt_); sep; + dImm(); + SetReg(_Rt_, _Im_); + + d->Comment("Load immediate without sign extension"); + } else { + dName("ori"); + + dGPR(_Rt_); sep; + if (_Rt_ != _Rs_) { + dGPR(_Rs_); sep; + } + dImm(); + Invalidate(_Rt_); + d->Comment("Or immediate"); + } +) + +MakeDisF(disSLTI, + dName("slti"); + + dGPR(_Rt_); sep; + if (_Rt_ != _Rs_) { + dGPR(_Rs_); sep; + } + dImm(); + + Invalidate(_Rt_); + + d->Comment(registers[_Rt_] + String(" = ") + registers[_Rs_] + " < immediate ? 1 : 0 (signed)"); +) + +MakeDisF(disSLTIU, + dName("sltiu"); + + dGPR(_Rt_); sep; + if (_Rt_ != _Rs_) { + dGPR(_Rs_); sep; + } + dImm(); + + Invalidate(_Rt_); + + d->Comment(registers[_Rt_] + String(" = ") + registers[_Rs_] + " < immediate ? 1 : 0 (unsigned)"); +) + +MakeDisF(disXORI, + dName("xori"); + + dGPR(_Rt_); sep; + if (_Rt_ != _Rs_) { + dGPR(_Rs_); sep; + } + dImm(); + + Invalidate(_Rt_); + + d->Comment("XOr immediate"); +) + +/********************************************************* +* Register arithmetic * +* Format: OP rd, rs, rt * +*********************************************************/ +MakeDisF(disADD, + dName("add"); + + dGPR(_Rd_); sep; + if (_Rd_ != _Rs_) { + dGPR(_Rs_); sep; + } + dGPR(_Rt_); + + Invalidate(_Rt_); + + d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " + " + registers[_Rt_]); +) + +MakeDisF(disADDU, + if (!_Rt_) { + dName("move"); + + dGPR(_Rd_); sep; + dGPR(_Rs_); + if (_Rs_) { + Invalidate(_Rd_); + } else { + SetReg(_Rd_, 0); + } + d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_]); + } else { + dName("addu"); + + dGPR(_Rd_); sep; + if (_Rd_ != _Rs_) { + dGPR(_Rs_); sep; + } + dGPR(_Rt_); + Invalidate(_Rd_); + d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " + " + registers[_Rt_]); + } +) + +MakeDisF(disAND, + dName("and"); + + dGPR(_Rd_); sep; + if (_Rd_ != _Rs_) { + dGPR(_Rs_); sep; + } + dGPR(_Rt_); + Invalidate(_Rd_); + d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " & " + registers[_Rt_]); +) + +MakeDisF(disNOR, + dName("nor"); + + dGPR(_Rd_); sep; + if (_Rd_ != _Rs_) { + dGPR(_Rs_); sep; + } + dGPR(_Rt_); + Invalidate(_Rd_); + d->Comment(String(registers[_Rd_]) + " = ~(" + registers[_Rs_] + " & " + registers[_Rt_] + ")"); +) + +MakeDisF(disOR, + dName("or"); + + dGPR(_Rd_); sep; + if (_Rd_ != _Rs_) { + dGPR(_Rs_); sep; + } + dGPR(_Rt_); + Invalidate(_Rd_); + d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " | " + registers[_Rt_]); +) + +MakeDisF(disSLT, + dName("slt"); + + dGPR(_Rd_); sep; + if (_Rd_ != _Rs_) { + dGPR(_Rs_); sep; + } + dGPR(_Rt_); + Invalidate(_Rd_); + d->Comment(registers[_Rd_] + String(" = ") + registers[_Rs_] + " < " + registers[_Rt_] + " ? 1 : 0 (signed)"); +) + +MakeDisF(disSLTU, + dName("sltu"); + + dGPR(_Rd_); sep; + if (_Rd_ != _Rs_) { + dGPR(_Rs_); sep; + } + dGPR(_Rt_); + Invalidate(_Rd_); + d->Comment(registers[_Rd_] + String(" = ") + registers[_Rs_] + " < " + registers[_Rt_] + " ? 1 : 0 (unsigned)"); +) + +MakeDisF(disSUB, + dName("sub"); + + dGPR(_Rd_); sep; + if (_Rd_ != _Rs_) { + dGPR(_Rs_); sep; + } + dGPR(_Rt_); + Invalidate(_Rd_); + d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " - " + registers[_Rt_]); +) + +MakeDisF(disSUBU, + dName("subu"); + + dGPR(_Rd_); sep; + if (_Rd_ != _Rs_) { + dGPR(_Rs_); sep; + } + dGPR(_Rt_); + Invalidate(_Rd_); + d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " - " + registers[_Rt_]); +) + +MakeDisF(disXOR, + dName("xor"); + + dGPR(_Rd_); sep; + if (_Rd_ != _Rs_) { + dGPR(_Rs_); sep; + } + dGPR(_Rt_); + Invalidate(_Rd_); + d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " ^ " + registers[_Rt_]); +) + +/********************************************************* +* Register arithmetic & Register trap logic * +* Format: OP rs, rt * +*********************************************************/ +MakeDisF(disDIV, + dName("div"); + + dGPR(_Rs_); sep; + dGPR(_Rt_); + + String c1 = String(registers[_Rs_]) + " / " + registers[_Rt_]; + String c2 = String(registers[_Rs_]) + " %% " + registers[_Rt_]; + + d->Comment("lo = " + c1 + "; hi = " + c2); +) + +MakeDisF(disDIVU, + dName("divu"); + + dGPR(_Rs_); sep; + dGPR(_Rt_); + + d->Comment(String("lo = " ) + registers[_Rs_] + " / " + registers[_Rt_] + "; hi = " + registers[_Rs_] + " % " + registers[_Rt_]); +) + +MakeDisF(disMULT, + dName("mult"); + + dGPR(_Rs_); sep; + dGPR(_Rt_); + + d->Comment(String("hilo = ") + registers[_Rs_] + " * " + registers[_Rt_]); +) + +MakeDisF(disMULTU, + dName("multu"); + + dGPR(_Rs_); sep; + dGPR(_Rt_); + + d->Comment(String("hilo = ") + registers[_Rs_] + " * " + registers[_Rt_]); +) + +/********************************************************* +* Register branch logic * +* Format: OP rs, offset * +*********************************************************/ +MakeDisF(disBGEZ, + dName("bgez"); + + dGPR(_Rs_); sep; + dOffset(); + Branch(_Branch_); + d->Comment("Branch if " + String(registers[_Rs_]) + " >= 0"); +) + +MakeDisF(disBGEZAL, + dName("bgezal"); + + dGPR(_Rs_); sep; + dOffset(); + Branch(_Branch_); + d->Comment("Branch and link if " + String(registers[_Rs_]) + " >= 0"); +) + +MakeDisF(disBGTZ, + dName("bgtz"); + + dGPR(_Rs_); sep; + dOffset(); + Branch(_Branch_); + d->Comment("Branch if " + String(registers[_Rs_]) + " > 0"); +) + +MakeDisF(disBLEZ, + dName("blez"); + + dGPR(_Rs_); sep; + dOffset(); + Branch(_Branch_); + d->Comment("Branch if " + String(registers[_Rs_]) + " <= 0"); +) + +MakeDisF(disBLTZ, + dName("bltz"); + + dGPR(_Rs_); sep; + dOffset(); + Branch(_Branch_); + d->Comment("Branch if " + String(registers[_Rs_]) + " < 0"); +) + +MakeDisF(disBLTZAL, + dName("bltzal"); + + dGPR(_Rs_); sep; + dOffset(); + Branch(_Branch_); + d->Comment("Branch and link if " + String(registers[_Rs_]) + " <= 0"); +) + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ +MakeDisF(disSLL, + if ((!_Rd_) && (!_Rt_)) { + dName("nop"); + if (code) { + dSuspect(); + } + } else { + dName("sll"); + + dGPR(_Rd_); sep; + if (_Rd_ != _Rt_) { + dGPR(_Rt_); sep; + } + dSa(); + Invalidate(_Rd_); + d->Comment(String(registers[_Rd_]) + " = " + registers[_Rt_] + " << immediate"); + } +) + +MakeDisF(disSRA, + dName("sra"); + + dGPR(_Rd_); sep; + if (_Rd_ != _Rt_) { + dGPR(_Rt_); sep; + } + dSa(); + Invalidate(_Rd_); + d->Comment(String(registers[_Rd_]) + " = " + registers[_Rt_] + " >> immediate (arithmetic)"); +) + +MakeDisF(disSRL, + dName("srl"); + + dGPR(_Rd_); sep; + if (_Rd_ != _Rt_) { + dGPR(_Rt_); sep; + } + dSa(); + Invalidate(_Rd_); + d->Comment(String(registers[_Rd_]) + " = " + registers[_Rt_] + " >> immediate (logical)"); +) + +/********************************************************* +* Shift arithmetic with variant register shift * +* Format: OP rd, rt, rs * +*********************************************************/ +MakeDisF(disSLLV, + dName("sllv"); + + dGPR(_Rd_); sep; + if (_Rd_ != _Rt_) { + dGPR(_Rt_); sep; + } + dGPR(_Rs_); + Invalidate(_Rd_); + d->Comment(String(registers[_Rd_]) + " = " + registers[_Rt_] + " << " + registers[_Rs_]); +) + +MakeDisF(disSRAV, + dName("srav"); + + dGPR(_Rd_); sep; + if (_Rd_ != _Rt_) { + dGPR(_Rt_); sep; + } + dGPR(_Rs_); + Invalidate(_Rd_); + d->Comment(String(registers[_Rd_]) + " = " + registers[_Rt_] + " >> " + registers[_Rs_] + " (arithmetic)"); +) + +MakeDisF(disSRLV, + dName("srlv"); + + dGPR(_Rd_); sep; + if (_Rd_ != _Rt_) { + dGPR(_Rt_); sep; + } + dGPR(_Rs_); + Invalidate(_Rd_); + d->Comment(String(registers[_Rd_]) + " = " + registers[_Rt_] + " >> " + registers[_Rs_] + " (logical)"); +) + +/********************************************************* +* Load higher 16 bits of the first word in GPR with imm * +* Format: OP rt, immediate * +*********************************************************/ +MakeDisF(disLUI, + dName("lui"); + + dGPR(_Rt_); sep; + dImm(); + + Invalidate(_Rt_); + + d->Comment("Load upper immediate"); +) + +/********************************************************* +* Move from HI/LO to GPR * +* Format: OP rd * +*********************************************************/ +MakeDisF(disMFHI, + dName("mfhi"); + + dGPR(_Rd_); + Invalidate(_Rd_); + + d->Comment(String(registers[_Rd_]) + " = hi"); +) + +MakeDisF(disMFLO, + dName("mflo"); + + dGPR(_Rd_); + Invalidate(_Rd_); + + d->Comment(String(registers[_Rd_]) + " = lo"); +) + +/********************************************************* +* Move from GPR to HI/LO * +* Format: OP rd * +*********************************************************/ +MakeDisF(disMTHI, + dName("mthi"); + + dGPR(_Rd_); + + d->Comment("hi = " + String(registers[_Rd_])); +) + +MakeDisF(disMTLO, + dName("mtlo"); + + dGPR(_Rd_); + + d->Comment("lo = " + String(registers[_Rd_])); +) + +/********************************************************* +* Special purpose instructions * +* Format: OP * +*********************************************************/ +MakeDisF(disBREAK, + dName("break"); + + Stop(pc + 4); + + d->Comment("Stops the machine"); +) +MakeDisF(disRFE, dName("rfe")) + +MakeDisF(disSYSCALL, + int syscall; + dName("syscall"); + syscall = code & 0xfffff; + + d->Comment(String("Syscall number ") + syscall); +) + +MakeDisF(disHLE, dName("hle")) + +MakeDisF(disRTPS, dName("rtps")) +MakeDisF(disOP , dName("op")) +MakeDisF(disNCLIP, dName("nclip")) +MakeDisF(disDPCS, dName("dpcs")) +MakeDisF(disINTPL, dName("intpl")) +MakeDisF(disMVMVA, dName("mvmva")) +MakeDisF(disNCDS , dName("ncds")) +MakeDisF(disCDP , dName("cdp")) +MakeDisF(disNCDT , dName("ncdt")) +MakeDisF(disNCCS , dName("nccs")) +MakeDisF(disCC , dName("cc")) +MakeDisF(disNCS , dName("ncs")) +MakeDisF(disNCT , dName("nct")) +MakeDisF(disSQR , dName("sqr")) +MakeDisF(disDCPL , dName("dcpl")) +MakeDisF(disDPCT , dName("dpct")) +MakeDisF(disAVSZ3, dName("avsz3")) +MakeDisF(disAVSZ4, dName("avsz4")) +MakeDisF(disRTPT , dName("rtpt")) +MakeDisF(disGPF , dName("gpf")) +MakeDisF(disGPL , dName("gpl")) +MakeDisF(disNCCT , dName("ncct")) + +MakeDisF(disMFC2, dName("mfc2"); dGPR(_Rt_); Invalidate(_Rt_); ) +MakeDisF(disCFC2, dName("cfc2"); dGPR(_Rt_); Invalidate(_Rt_); ) +MakeDisF(disMTC2, dName("mtc2"); dGPR(_Rt_);) +MakeDisF(disCTC2, dName("ctc2"); dGPR(_Rt_);) + +/********************************************************* +* Register branch logic * +* Format: OP rs, rt, offset * +*********************************************************/ +MakeDisF(disBEQ, + if ((!_Rt_) && (!_Rs_)) { + dName("b"); + + dOffset(); + Branch(_Branch_); + Stop(pc + 8); + + d->Comment("Branch always"); + } + if (!_Rt_) { + dName("bez"); + + dGPR(_Rs_); sep; + dOffset(); + Branch(_Branch_); + + d->Comment(String("Branch if ") + registers[_Rs_] + " == 0"); + } else { + dName("beq"); + + dGPR(_Rs_); sep; + dGPR(_Rt_); sep; + dOffset(); + Branch(_Branch_); + + d->Comment(String("Branch if ") + registers[_Rs_] + " == " + registers[_Rt_]); + } +) + +MakeDisF(disBNE, + if (!_Rt_) { + dName("bnz"); + + dGPR(_Rs_); sep; + dOffset(); + Branch(_Branch_); + + d->Comment(String("Branch if ") + registers[_Rs_] + " != 0"); + } else { + dName("bne"); + + dGPR(_Rs_); sep; + dGPR(_Rt_); sep; + dOffset(); + Branch(_Branch_); + + d->Comment(String("Branch if ") + registers[_Rs_] + " != " + registers[_Rt_]); + } +) + +/********************************************************* +* Jump to target * +* Format: OP target * +*********************************************************/ +MakeDisF(disJ, + dName("j"); + + dTarget(); + Jump(_Target_); + Stop(pc + 8); + + d->Comment("Jump always"); +) + +MakeDisF(disJAL, + dName("jal"); + + dTarget(); + Invalidate(Rra); + MarkFunction(_Target_); + + d->Comment("Jump and link (function call)"); +) + +/********************************************************* +* Register jump * +* Format: OP rs, rd * +*********************************************************/ +MakeDisF(disJR, + dName("jr"); + dGPR(_Rs_); + Stop(pc + 8); + + d->Comment("Jump register"); +) + +MakeDisF(disJALR, + dName("jalr"); + + dGPR(_Rs_); + + if ((_Rd_) != Rra) { + sep; dGPR(_Rd_); + } + + Invalidate(_Rd_); + + d->Comment("Jump and link register (function call)"); +) + +/********************************************************* +* Load and store for GPR * +* Format: OP rt, offset(base) * +*********************************************************/ +MakeDisF(disLB, + int width = 8; + dName("lb"); + + dGPR(_Rt_); sep; + dOfB(); + + Invalidate(_Rt_); + d->Comment("Load signed byte"); +) + +MakeDisF(disLBU, + int width = 8; + dName("lbu"); + + dGPR(_Rt_); sep; + dOfB(); + + Invalidate(_Rt_); + d->Comment("Load unsigned byte"); +) + +MakeDisF(disLH, + int width = 16; + dName("lh"); + + dGPR(_Rt_); sep; + dOfB(); + + Invalidate(_Rt_); + d->Comment("Load signed half"); +) + +MakeDisF(disLHU, + int width = 16; + dName("lhu"); + + dGPR(_Rt_); sep; + dOfB(); + + Invalidate(_Rt_); + d->Comment("Load unsigned half"); +) + +MakeDisF(disLW, + int width = 32; + dName("lw"); + + dGPR(_Rt_); sep; + dOfB(); + + Invalidate(_Rt_); + d->Comment("Load word"); +) + +MakeDisF(disLWL, + int width = 32; + dName("lwl"); + + dGPR(_Rt_); sep; + dOfB(); + + Invalidate(_Rt_); + d->Comment("Load word left"); +) + +MakeDisF(disLWR, + int width = 32; + dName("lwr"); + + dGPR(_Rt_); sep; + dOfB(); + + Invalidate(_Rt_); + d->Comment("Load word right"); +) + +MakeDisF(disLWC2, + int width = 32; + dName("lwc2"); + + dCP0(_Rt_); sep; + dOfB(); +) + +MakeDisF(disSB, + int width = 8; + dName("sb"); + + dGPR(_Rt_); sep; + dOfB(); + d->Comment("Store byte"); +) + +MakeDisF(disSH, + int width = 16; + dName("sh"); + + dGPR(_Rt_); sep; + dOfB(); + d->Comment("Store half"); +) + +MakeDisF(disSW, + int width = 32; + dName("sw"); + + dGPR(_Rt_); sep; + dOfB(); + d->Comment("Store word"); +) + +MakeDisF(disSWL, + int width = 32; + dName("swl"); + + dGPR(_Rt_); sep; + dOfB(); + d->Comment("Store word left"); +) + +MakeDisF(disSWR, + int width = 32; + dName("swr"); + + dGPR(_Rt_); sep; + dOfB(); + d->Comment("Store word right"); +) + +MakeDisF(disSWC2, + int width = 32; + dName("swc2"); + + dGPR(_Rt_); sep; + dOfB(); +) + +/********************************************************* +* Moves between GPR and COPx * +* Format: OP rt, fs * +*********************************************************/ +MakeDisF(disMFC0, dName("mfc0"); dGPR(_Rt_); sep; dCP0(_Rd_); Invalidate(_Rt_);) +MakeDisF(disMTC0, dName("mtc0"); dCP0(_Rd_); sep; dGPR(_Rt_);) +MakeDisF(disCFC0, dName("cfc0"); dGPR(_Rt_); sep; dCP0(_Rd_); Invalidate(_Rt_);) +MakeDisF(disCTC0, dName("ctc0"); dCP0(_Rd_); sep; dGPR(_Rt_);) + +/********************************************************* +* Unknow instruction (would generate an exception) * +* Format: ? * +*********************************************************/ +MakeDisF(disNULL, + dName("*** Bad OP ***"); + dInvalid(); +) + + +TdisR3000AF disR3000A_SPECIAL[] = { // Subset of disSPECIAL + disSLL , disNULL , disSRL , disSRA , disSLLV , disNULL , disSRLV , disSRAV , + disJR , disJALR , disNULL, disNULL, disSYSCALL, disBREAK , disNULL , disNULL , + disMFHI, disMTHI , disMFLO, disMTLO, disNULL , disNULL , disNULL , disNULL , + disMULT, disMULTU, disDIV , disDIVU, disNULL , disNULL , disNULL , disNULL , + disADD , disADDU , disSUB , disSUBU, disAND , disOR , disXOR , disNOR , + disNULL, disNULL , disSLT , disSLTU, disNULL , disNULL , disNULL , disNULL , + disNULL, disNULL , disNULL, disNULL, disNULL , disNULL , disNULL , disNULL , + disNULL, disNULL , disNULL, disNULL, disNULL , disNULL , disNULL , disNULL}; + +MakeDisF(disSPECIAL, disR3000A_SPECIAL[_Funct_](d, code, pc)) + +TdisR3000AF disR3000A_BCOND[] = { // Subset of disBCOND + disBLTZ , disBGEZ , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disBLTZAL, disBGEZAL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disBCOND, disR3000A_BCOND[_Rt_](d, code, pc)) + +TdisR3000AF disR3000A_COP0[] = { // Subset of disCOP0 + disMFC0, disNULL, disCFC0, disNULL, disMTC0, disNULL, disCTC0, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disRFE , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disCOP0, disR3000A_COP0[_Rs_](d, code, pc)) + +TdisR3000AF disR3000A_BASIC[] = { // Subset of disBASIC (based on rs) + disMFC2, disNULL, disCFC2, disNULL, disMTC2, disNULL, disCTC2, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disBASIC, disR3000A_BASIC[_Rs_](d, code, pc)) + +TdisR3000AF disR3000A_COP2[] = { // Subset of disR3000F_COP2 (based on funct) + disBASIC, disRTPS , disNULL , disNULL , disNULL, disNULL , disNCLIP, disNULL, + disNULL , disNULL , disNULL , disNULL , disOP , disNULL , disNULL , disNULL, + disDPCS , disINTPL, disMVMVA, disNCDS , disCDP , disNULL , disNCDT , disNULL, + disNULL , disNULL , disNULL , disNCCS , disCC , disNULL , disNCS , disNULL, + disNCT , disNULL , disNULL , disNULL , disNULL, disNULL , disNULL , disNULL, + disSQR , disDCPL , disDPCT , disNULL , disNULL, disAVSZ3, disAVSZ4, disNULL, + disRTPT , disNULL , disNULL , disNULL , disNULL, disNULL , disNULL , disNULL, + disNULL , disNULL , disNULL , disNULL , disNULL, disGPF , disGPL , disNCCT }; + +MakeDisF(disCOP2, disR3000A_COP2[_Funct_](d, code, pc)) + +TdisR3000AF disR3000A[] = { + disSPECIAL , disBCOND , disJ , disJAL , disBEQ , disBNE , disBLEZ , disBGTZ , + disADDI , disADDIU , disSLTI , disSLTIU, disANDI, disORI , disXORI , disLUI , + disCOP0 , disNULL , disCOP2 , disNULL , disNULL, disNULL, disNULL , disNULL , + disNULL , disNULL , disNULL , disNULL , disNULL, disNULL, disNULL , disNULL , + disLB , disLH , disLWL , disLW , disLBU , disLHU , disLWR , disNULL , + disSB , disSH , disSWL , disSW , disNULL, disNULL, disSWR , disNULL , + disNULL , disNULL , disLWC2 , disNULL , disNULL, disNULL, disNULL , disNULL , + disNULL , disNULL , disSWC2 , disHLE , disNULL, disNULL, disNULL , disNULL }; + +//MakeDisFg(disR3000AF, disR3000A[code >> 26](code, pc)) + +void decode(TDis * d, Uint32 pc) { + Uint32 code = d->getmem()->Read32(pc); + disR3000A[code >> 26](d, code, pc); +} diff --git a/lib/mipsdis.cpp b/lib/mipsdis.cpp index cbaf9e3..bb6364c 100644 --- a/lib/mipsdis.cpp +++ b/lib/mipsdis.cpp @@ -1,180 +1,180 @@ -/* - * PSX-Tools Bundle Pack - * Copyright (C) 2002-2003 Nicolas "Pixel" Noble - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* $Id: mipsdis.cpp,v 1.2 2004-01-26 15:31:55 pixel Exp $ */ - -#include "mipsdis.h" -#include "mips.h" - -TDis::TDis(mipsmem * _m) : mm(_m) { - reset(); -} - -void TDis::reset() { - invalid = false; -} - -mipsmem * TDis::getmem() { - return mm; -} - -void TDis::add_branch(Uint32 target) { - bheap.push(target); -} - -void TDis::add_jump(Uint32 target) { - jheap.push(target); -} - -void TDis::add_function(Uint32 target) { - fheap.push(target); -} - -void TDis::SetTag(Uint32 target, int tag, bool v) { - mm->SetTag(target, tag, v); -} - -void TDis::Name(const String & name) { -} - -void TDis::PushGPReg(int reg) { -} - -void TDis::PushCPReg(int reg) { -} - -void TDis::PushImm(Uint32 imm) { -} - -void TDis::PushTarget(Uint32 target) { - new refto_t(target, memdata::getmem(pc, getmem())); -} - -void TDis::PushSa(Uint32 sa) { -} - -void TDis::PushOfB(int reg, Uint32 offset, int width) { -} - -void TDis::PushOffset(Uint32 offset) { - new refto_t(offset, memdata::getmem(pc, getmem())); -} - -void TDis::PushFull(Uint32 full) { - if ((full >= 0x80000000) && (full < (0x80000000 + PSXMEM))) - new refto_t(full, memdata::getmem(pc, getmem())); -} - -void TDis::Invalid() { - invalid = true; -} - -void TDis::Suspect() { -} - -void TDis::Comment(const String & c) { -} - -Disassembler::Disassembler(mipsmem * _mm) : mm(_mm), dis(new TDis(mm)), started(false), infunction(false) { -} - -Disassembler::~Disassembler() { - delete dis; -} - -void Disassembler::crawl_code(Uint32 pc) { - Uint32 branched, ipc; - - if (pc == 0xffffffff) { - pc = mm->GetPC(); - } - - dis->bheap.push(pc); - - while (dis->bheap.size()) { - branched = pc = dis->bheap.top(); - dis->bheap.pop(); - printm(M_STATUS, "Crawling to branch %8.8lX\n", pc); - do { - if (pc >= (0x80000000 + PSXMEM)) { - dis->invalid = true; - break; - } - if (mm->GetTag(pc, CODE) || mm->GetTag(pc, INVALID)) { - pc += 4; - continue; - } - mm->SetTag(pc, CODE, true); - - printm(M_STATUS, "Working at %8.8lX\n", pc); - decode(dis, pc); - - pc += 4; - dis->reset(); - } while (!mm->GetTag(pc, STOP) && !dis->invalid); - - if (dis->invalid) { - for (ipc = branched; ipc <= pc; ipc += 4) { - mm->SetTag(ipc, CODE, false); - mm->SetTag(ipc, INVALID, true); - } - } - - if (dis->invalid && infunction) { - } - } -} - -void Disassembler::mainloop(void) { - Uint32 pc; - - infunction = false; - - // Crawl the start part. - printm(M_STATUS, "Starting crawl at %8.8lX\n", mm->GetPC()); - if (!started) - crawl_code(); - - started = true; - - // Work out all the functions. - printm(M_STATUS, "Crawling all detected functions\n"); - infunction = true; - while (dis->fheap.size()) { - pc = dis->fheap.top(); - dis->fheap.pop(); - printm(M_STATUS, "Crawling function %8.8lX\n", pc); - if (mm->GetTag(pc, CODE)) - continue; - crawl_code(pc); - } - - // Complete functions and all the detected jumps. - printm(M_STATUS, "Fixing all the remaining jumps\n"); -#if 0 - infunction = false; - while (dis->jheap.size()) { - pc = dis->jheap.top(); - dis->jheap.pop(); - if (mm->GetTag(pc, CODE)) - continue; - crawl_code(pc); - } -#endif -} +/* + * PSX-Tools Bundle Pack + * Copyright (C) 2002-2003 Nicolas "Pixel" Noble + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id: mipsdis.cpp,v 1.3 2004-11-27 21:44:48 pixel Exp $ */ + +#include "mipsdis.h" +#include "mips.h" + +TDis::TDis(mipsmem * _m) : mm(_m) { + reset(); +} + +void TDis::reset() { + invalid = false; +} + +mipsmem * TDis::getmem() { + return mm; +} + +void TDis::add_branch(Uint32 target) { + bheap.push(target); +} + +void TDis::add_jump(Uint32 target) { + jheap.push(target); +} + +void TDis::add_function(Uint32 target) { + fheap.push(target); +} + +void TDis::SetTag(Uint32 target, int tag, bool v) { + mm->SetTag(target, tag, v); +} + +void TDis::Name(const String & name) { +} + +void TDis::PushGPReg(int reg) { +} + +void TDis::PushCPReg(int reg) { +} + +void TDis::PushImm(Uint32 imm) { +} + +void TDis::PushTarget(Uint32 target) { + new refto_t(target, memdata::getmem(pc, getmem())); +} + +void TDis::PushSa(Uint32 sa) { +} + +void TDis::PushOfB(int reg, Uint32 offset, int width) { +} + +void TDis::PushOffset(Uint32 offset) { + new refto_t(offset, memdata::getmem(pc, getmem())); +} + +void TDis::PushFull(Uint32 full) { + if ((full >= 0x80000000) && (full < (0x80000000 + PSXMEM))) + new refto_t(full, memdata::getmem(pc, getmem())); +} + +void TDis::Invalid() { + invalid = true; +} + +void TDis::Suspect() { +} + +void TDis::Comment(const String & c) { +} + +Disassembler::Disassembler(mipsmem * _mm) : mm(_mm), dis(new TDis(mm)), started(false), infunction(false) { +} + +Disassembler::~Disassembler() { + delete dis; +} + +void Disassembler::crawl_code(Uint32 pc) { + Uint32 branched, ipc; + + if (pc == 0xffffffff) { + pc = mm->GetPC(); + } + + dis->bheap.push(pc); + + while (dis->bheap.size()) { + branched = pc = dis->bheap.top(); + dis->bheap.pop(); + printm(M_STATUS, "Crawling to branch %8.8lX\n", pc); + do { + if (pc >= (0x80000000 + PSXMEM)) { + dis->invalid = true; + break; + } + if (mm->GetTag(pc, CODE) || mm->GetTag(pc, INVALID)) { + pc += 4; + continue; + } + mm->SetTag(pc, CODE, true); + + printm(M_STATUS, "Working at %8.8lX\n", pc); + decode(dis, pc); + + pc += 4; + dis->reset(); + } while (!mm->GetTag(pc, STOP) && !dis->invalid); + + if (dis->invalid) { + for (ipc = branched; ipc <= pc; ipc += 4) { + mm->SetTag(ipc, CODE, false); + mm->SetTag(ipc, INVALID, true); + } + } + + if (dis->invalid && infunction) { + } + } +} + +void Disassembler::mainloop(void) { + Uint32 pc; + + infunction = false; + + // Crawl the start part. + printm(M_STATUS, "Starting crawl at %8.8lX\n", mm->GetPC()); + if (!started) + crawl_code(); + + started = true; + + // Work out all the functions. + printm(M_STATUS, "Crawling all detected functions\n"); + infunction = true; + while (dis->fheap.size()) { + pc = dis->fheap.top(); + dis->fheap.pop(); + printm(M_STATUS, "Crawling function %8.8lX\n", pc); + if (mm->GetTag(pc, CODE)) + continue; + crawl_code(pc); + } + + // Complete functions and all the detected jumps. + printm(M_STATUS, "Fixing all the remaining jumps\n"); +#if 0 + infunction = false; + while (dis->jheap.size()) { + pc = dis->jheap.top(); + dis->jheap.pop(); + if (mm->GetTag(pc, CODE)) + continue; + crawl_code(pc); + } +#endif +} diff --git a/lib/mipsdump.cpp b/lib/mipsdump.cpp index ac77b33..1eb59f7 100644 --- a/lib/mipsdump.cpp +++ b/lib/mipsdump.cpp @@ -1,207 +1,207 @@ -/* - * PSX-Tools Bundle Pack - * Copyright (C) 2002-2003 Nicolas "Pixel" Noble - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* $Id: mipsdump.cpp,v 1.1 2004-01-03 15:04:47 pixel Exp $ */ - -#include "mipsdump.h" -#include "mips.h" - -TDump::TDump(mipsmem * mm) : TDis(mm) { - reset(); -} - -void TDump::reset() { - invalid = false; - hasbr = false; - hastg = false; - hasfc = false; - name = ""; - comments = ""; - args.clear(); -} - -void TDump::add_branch(Uint32 _tg) { - tg = _tg; - hasbr = true; -} - -void TDump::add_jump(Uint32 _tg) { - tg = _tg; - hastg = true; -} - -void TDump::add_function(Uint32 _tg) { - tg = _tg; - hasfc = true; -} - -void TDump::SetTag(Uint32 a, int t, bool v) { -} - -void TDump::Name(const String & _name) { - name = _name; -} - -void TDump::PushGPReg(int r) { - pairarg p; - - p.left = T_GPREGISTER; - p.right.v = r; - - args.push_back(p); -} - -void TDump::PushCPReg(int r) { - pairarg p; - - p.left = T_CPREGISTER; - p.right.v = r; - - args.push_back(p); -} - -void TDump::PushImm(Uint32 imm) { - pairarg p; - - p.left = T_IMM16; - p.right.v = imm; - - args.push_back(p); -} - -void TDump::PushTarget(Uint32 target) { - pairarg p; - - p.left = T_IMM32; - p.right.v = target; - - args.push_back(p); -} - -void TDump::PushSa(Uint32 sa) { - pairarg p; - - p.left = T_IMM8; - p.right.v = sa; - - args.push_back(p); -} - -void TDump::PushOfB(int reg, Uint32 offset, int width) { - pairarg p; - - p.left = T_OFB; - p.right.OfB.o = offset; - p.right.OfB.r = reg; - p.right.OfB.w = width; - - args.push_back(p); -} - -void TDump::PushOffset(Uint32 offset) { - pairarg p; - - p.left = T_IMM32; - p.right.v = offset; - - args.push_back(p); -} - -void TDump::PushFull(Uint32 full) { - pairarg p; - - p.left = T_IMM32; - p.right.v = full; - - args.push_back(p); -} - -void TDump::Invalid() { - invalid = true; -} - -void TDump::Suspect() { -} - -void TDump::Comment(const String & c) { - comments = c; -} - -Dumper::Dumper(mipsmem * _mm) : dump(new TDump(_mm)), mm(_mm) { -} - -void Dumper::process() { - Uint32 pc, code; - memdata * mem; - - for (pc = 0x80000000; pc < (0x80000000 + PSXMEM); pc++) { - if (mm->GetTag(pc, CODE)) { - decode(dump, pc); - code = mm->Read32(pc); - printm(M_STATUS, "%8.8lX %8.8lX: " + dump->name + "\t", pc, code); - for (std::vector::iterator i = dump->args.begin(); i != dump->args.end(); i++) { - switch(i->left) { - case T_GPREGISTER: - printm(M_BARE, "$%s", registers[i->right.v]); - break; - case T_CPREGISTER: - printm(M_BARE, "$%s", CP0registers[i->right.v]); - break; - case T_IMM8: - printm(M_BARE, "0x%2.2lX", i->right.v); - break; - case T_IMM16: - printm(M_BARE, "0x%4.4lX", i->right.v); - break; - case T_IMM32: - printm(M_BARE, "0x%8.8lX", i->right.v); - break; - case T_OFB: - printm(M_BARE, "0x%4.4lX($%s)", i->right.OfB.o, registers[i->right.OfB.r]); - break; - } - if ((i + 1) != dump->args.end()) { - printm(M_BARE, ", "); - } - } - if (dump->comments != "") { - printm(M_BARE, "\t; " + dump->comments); - } - printm(M_BARE, "\n"); - mem = mm->GetDatas(pc); - if (mem) { - reffrom_t * from; - refto_t * to; - - from = mem->getreffrom(); - to = mem->getrefto(); - - for (from = mem->getreffrom(); from; from = from->getnext()) { - printm(M_STATUS, " Reference from 0x%8.8lX\n", from->getref()->getaddress()); - } - - if (to) { - printm(M_STATUS, " Reference to 0x%8.8lX\n", to->getref()->getaddress()); - } - } - pc += 3; - dump->reset(); - } - } -} +/* + * PSX-Tools Bundle Pack + * Copyright (C) 2002-2003 Nicolas "Pixel" Noble + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id: mipsdump.cpp,v 1.2 2004-11-27 21:44:48 pixel Exp $ */ + +#include "mipsdump.h" +#include "mips.h" + +TDump::TDump(mipsmem * mm) : TDis(mm) { + reset(); +} + +void TDump::reset() { + invalid = false; + hasbr = false; + hastg = false; + hasfc = false; + name = ""; + comments = ""; + args.clear(); +} + +void TDump::add_branch(Uint32 _tg) { + tg = _tg; + hasbr = true; +} + +void TDump::add_jump(Uint32 _tg) { + tg = _tg; + hastg = true; +} + +void TDump::add_function(Uint32 _tg) { + tg = _tg; + hasfc = true; +} + +void TDump::SetTag(Uint32 a, int t, bool v) { +} + +void TDump::Name(const String & _name) { + name = _name; +} + +void TDump::PushGPReg(int r) { + pairarg p; + + p.left = T_GPREGISTER; + p.right.v = r; + + args.push_back(p); +} + +void TDump::PushCPReg(int r) { + pairarg p; + + p.left = T_CPREGISTER; + p.right.v = r; + + args.push_back(p); +} + +void TDump::PushImm(Uint32 imm) { + pairarg p; + + p.left = T_IMM16; + p.right.v = imm; + + args.push_back(p); +} + +void TDump::PushTarget(Uint32 target) { + pairarg p; + + p.left = T_IMM32; + p.right.v = target; + + args.push_back(p); +} + +void TDump::PushSa(Uint32 sa) { + pairarg p; + + p.left = T_IMM8; + p.right.v = sa; + + args.push_back(p); +} + +void TDump::PushOfB(int reg, Uint32 offset, int width) { + pairarg p; + + p.left = T_OFB; + p.right.OfB.o = offset; + p.right.OfB.r = reg; + p.right.OfB.w = width; + + args.push_back(p); +} + +void TDump::PushOffset(Uint32 offset) { + pairarg p; + + p.left = T_IMM32; + p.right.v = offset; + + args.push_back(p); +} + +void TDump::PushFull(Uint32 full) { + pairarg p; + + p.left = T_IMM32; + p.right.v = full; + + args.push_back(p); +} + +void TDump::Invalid() { + invalid = true; +} + +void TDump::Suspect() { +} + +void TDump::Comment(const String & c) { + comments = c; +} + +Dumper::Dumper(mipsmem * _mm) : dump(new TDump(_mm)), mm(_mm) { +} + +void Dumper::process() { + Uint32 pc, code; + memdata * mem; + + for (pc = 0x80000000; pc < (0x80000000 + PSXMEM); pc++) { + if (mm->GetTag(pc, CODE)) { + decode(dump, pc); + code = mm->Read32(pc); + printm(M_STATUS, "%8.8lX %8.8lX: " + dump->name + "\t", pc, code); + for (std::vector::iterator i = dump->args.begin(); i != dump->args.end(); i++) { + switch(i->left) { + case T_GPREGISTER: + printm(M_BARE, "$%s", registers[i->right.v]); + break; + case T_CPREGISTER: + printm(M_BARE, "$%s", CP0registers[i->right.v]); + break; + case T_IMM8: + printm(M_BARE, "0x%2.2lX", i->right.v); + break; + case T_IMM16: + printm(M_BARE, "0x%4.4lX", i->right.v); + break; + case T_IMM32: + printm(M_BARE, "0x%8.8lX", i->right.v); + break; + case T_OFB: + printm(M_BARE, "0x%4.4lX($%s)", i->right.OfB.o, registers[i->right.OfB.r]); + break; + } + if ((i + 1) != dump->args.end()) { + printm(M_BARE, ", "); + } + } + if (dump->comments != "") { + printm(M_BARE, "\t; " + dump->comments); + } + printm(M_BARE, "\n"); + mem = mm->GetDatas(pc); + if (mem) { + reffrom_t * from; + refto_t * to; + + from = mem->getreffrom(); + to = mem->getrefto(); + + for (from = mem->getreffrom(); from; from = from->getnext()) { + printm(M_STATUS, " Reference from 0x%8.8lX\n", from->getref()->getaddress()); + } + + if (to) { + printm(M_STATUS, " Reference to 0x%8.8lX\n", to->getref()->getaddress()); + } + } + pc += 3; + dump->reset(); + } + } +} diff --git a/lib/mipsmem.cpp b/lib/mipsmem.cpp index 761df13..660c3fc 100644 --- a/lib/mipsmem.cpp +++ b/lib/mipsmem.cpp @@ -1,349 +1,349 @@ -/* - * PSX-Tools Bundle Pack - * Copyright (C) 2002-2003 Nicolas "Pixel" Noble - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* $Id: mipsmem.cpp,v 1.1 2004-01-03 15:04:47 pixel Exp $ */ - -#include "mipsmem.h" - -refto_t::refto_t(Uint32 to, memdata * _m) : reffrom(new reffrom_t(this, _m->getmem(to))), mem(_m) { - refto_t * t = mem->getrefto(); - if (t) - delete t; - mem->setrefto(this); -} - -refto_t::~refto_t() { - mem->setrefto(0); - delete reffrom; -} - -memdata * refto_t::getmem() { - return mem; -} - -memdata * refto_t::getref() { - return reffrom->getmem(); -} - -reffrom_t::reffrom_t(refto_t * _refto, memdata * _m) : refto(_refto), header(_m) { - next = header->getreffrom(); - prev = 0; - header->setreffrom(this); - if (next) - next->prev = this; -} - -reffrom_t::~reffrom_t() { - if (next) - next->prev = prev; - if (prev) - prev->next = next; - else - header->setreffrom(next); -} - -memdata * reffrom_t::getmem() { - return header; -} - -memdata * reffrom_t::getref() { - return refto->getmem(); -} - -reffrom_t * reffrom_t::getnext() { - return next; -} - -memdata::memdata(Uint32 _address, mipsmem * _mm) : address(_address), mm(_mm), func(0), refto(0), reffrom(0) { - mm->SetDatas(address, this); -} - -memdata::~memdata() { - mm->SetDatas(address, 0); -} - -Uint32 memdata::getaddress() { - return address; -} - -memdata * memdata::getmem(Uint32 addr) { - return getmem(addr, mm); -} - -memdata * memdata::getmem(Uint32 addr, mipsmem * mm) { - memdata * t = mm->GetDatas(addr); - - if (!t) { - t = new memdata(addr, mm); - } - return t; -} - -func_t * memdata::getfunc() { - return func; -} - -refto_t * memdata::getrefto() { - return refto; -} - -reffrom_t * memdata::getreffrom() { - return reffrom; -} - -void memdata::setfunc(func_t * f) { - func = f; - checkdestroy(); -} - -void memdata::setrefto(refto_t * r) { - refto = r; - checkdestroy(); -} - -void memdata::setreffrom(reffrom_t * r) { - reffrom = r; - checkdestroy(); -} - -void memdata::checkdestroy() { - if (!func && !refto && !reffrom) { - delete this; - } -} - - -mipsmem::mipsmem() { - memset(psyqhead, 0, 0x800); - memset(plainmemory, 0, PSXMEM); - memset(patches, 0, PSXMEM); - memset(patchesmap, 0, PSXMEM / 8); - memset(tags, 0, PSXMEM); - memset(datas, 0, PSXMEM * sizeof(memdata *)); -} - -Uint8 mipsmem::Read8(Uint32 mem) { - if ((mem < 0x80000000) || (mem >= (0x80000000 + PSXMEM))) { - printm(M_WARNING, "Reading at out of bound of memory: 0x%08x\n", mem); - return 0xff; - } - - mem -= 0x80000000; - - if (IsPatched(mem)) { - return patches[mem]; - } else { - return plainmemory[mem]; - } -} - -Uint16 mipsmem::Read16(Uint32 mem) { - Uint8 a, b; - - if (mem & 1) { - printm(M_WARNING, "Read16 at a non 16-bits boundary: 0x%08x\n", mem); - } - - a = Read8(mem); - b = Read8(mem + 1); - - return a | (b << 8); -} - -Uint32 mipsmem::Read32(Uint32 mem) { - Uint8 a, b, c, d; - - if (mem & 3) { - printm(M_WARNING, "Read32 at a non 32-bits boundary: 0x%08x\n", mem); - } - - a = Read8(mem); - b = Read8(mem + 1); - c = Read8(mem + 2); - d = Read8(mem + 3); - - return a | (b << 8) | (c << 16) | (d << 24); -} - -void mipsmem::Write8(Uint32 mem, Uint8 value) { - if ((mem < 0x80000000) || (mem > (0x80000000 + PSXMEM - 1))) { - printm(M_WARNING, "Writing at out of bound of memory: 0x%08x\n", mem); - return; - } - - mem -= 0x80000000; - - patch(mem, 1); - patches[mem] = value; -} - -void mipsmem::Write16(Uint32 mem, Uint16 value) { - if ((mem < 0x80000000) || (mem > (0x80000000 + PSXMEM - 2))) { - printm(M_WARNING, "Writing at out of bound of memory: 0x%08x\n", mem); - return; - } - - mem -= 0x80000000; - - patch(mem, 2); - patches[mem] = value & 0xff; - patches[mem + 1] = (value >> 8) & 0xff; -} - -void mipsmem::Write32(Uint32 mem, Uint32 value) { - if ((mem < 0x80000000) || (mem > (0x80000000 + PSXMEM - 4))) { - printm(M_WARNING, "Writing at out of bound of memory: 0x%08x\n", mem); - return; - } - - mem -= 0x80000000; - - patch(mem, 4); - patches[mem] = value & 0xff; - patches[mem + 1] = (value >> 8) & 0xff; - patches[mem + 2] = (value >> 16) & 0xff; - patches[mem + 3] = (value >> 24) & 0xff; -} - -void mipsmem::unpatch8(Uint32 mem) { - unpatch(mem, 1); -} - -void mipsmem::unpatch16(Uint32 mem) { - unpatch(mem, 2); -} - -void mipsmem::unpatch32(Uint32 mem) { - unpatch(mem, 4); -} - -bool mipsmem::IsPatched(Uint32 mem) { - int mask, pos; - - pos = mem / 8; - mask = 1 << (mem % 8); - - return patchesmap[pos] & mask; -} - -void mipsmem::LoadPSYQ(Handle * h) { - h->read(psyqhead, 0x800); - memset(plainmemory, 0, PSXMEM); - paddr = ((psyq*)psyqhead)->t_addr; - psize = ((psyq*)psyqhead)->t_size; - startpc = ((psyq*)psyqhead)->pc0; - - printm(M_INFO, "Loading %i (%08x) bytes of data at %i (%08x).\n", psize, psize, paddr - 0x80000000, paddr); - - h->read(plainmemory + paddr - 0x80000000, psize); -} - -void mipsmem::SavePSYQ(Handle * h) {\ - Uint32 i; - - if (!*((Uint32 *)psyqhead)) - return; - h->write(psyqhead, 0x800); - paddr = ((psyq*)psyqhead)->t_addr; - psize = ((psyq*)psyqhead)->t_size; - - printm(M_INFO, "Writing %i (%08x) bytes of data from %i (%08x).\n", psize, psize, paddr - 0x80000000, paddr); - - for (i = paddr - 0x80000000; i < psize; i++) { - h->writeU8(Read8(i)); - } -} - -bool mipsmem::GetTag(Uint32 addr, char tag) { - int mask; - - if ((addr < 0x80000000) || (addr >= (0x80000000 + PSXMEM))) { - printm(M_WARNING, "Reading tag at out of bound of memory: 0x%08x\n", addr); - return false; - } - - mask = 1 << tag; - addr -= 0x80000000; - - return tags[addr] & mask; -} - -void mipsmem::SetTag(Uint32 addr, char tag, bool t) { - int mask; - - if ((addr < 0x80000000) || (addr >= (0x80000000 + PSXMEM))) { - printm(M_WARNING, "Setting tag at out of bound of memory: 0x%08x\n", addr); - return; - } - - mask = 1 << tag; - addr -= 0x80000000; - - if (t) { - tags[addr] |= mask; - } else { - tags[addr] &= ~mask; - } -} - -memdata * mipsmem::GetDatas(Uint32 addr) { - return datas[addr]; -} - -void mipsmem::SetDatas(Uint32 addr, memdata * p) { - datas[addr] = p; -} - -Uint32 mipsmem::GetPC() { - return startpc; -} - -Uint32 mipsmem::GetLower() { - return paddr; -} - -Uint32 mipsmem::GetUpper() { - return paddr + psize; -} - -void mipsmem::patch(Uint32 mem, int size) { - int mask, pos; - - pos = mem / 8; - mask = 1 << (mem % 8); - - patchesmap[pos] |= mask; - - if (size != 1) { - patch(mem + 1, size - 1); - } -} - -void mipsmem::unpatch(Uint32 mem, int size) { - int mask, pos; - - pos = mem / 8; - mask = ~(1 << (mem % 8)); - - patchesmap[pos] &= mask; - - if (size != 1) { - unpatch(mem + 1, size - 1); - } -} +/* + * PSX-Tools Bundle Pack + * Copyright (C) 2002-2003 Nicolas "Pixel" Noble + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id: mipsmem.cpp,v 1.2 2004-11-27 21:44:48 pixel Exp $ */ + +#include "mipsmem.h" + +refto_t::refto_t(Uint32 to, memdata * _m) : reffrom(new reffrom_t(this, _m->getmem(to))), mem(_m) { + refto_t * t = mem->getrefto(); + if (t) + delete t; + mem->setrefto(this); +} + +refto_t::~refto_t() { + mem->setrefto(0); + delete reffrom; +} + +memdata * refto_t::getmem() { + return mem; +} + +memdata * refto_t::getref() { + return reffrom->getmem(); +} + +reffrom_t::reffrom_t(refto_t * _refto, memdata * _m) : refto(_refto), header(_m) { + next = header->getreffrom(); + prev = 0; + header->setreffrom(this); + if (next) + next->prev = this; +} + +reffrom_t::~reffrom_t() { + if (next) + next->prev = prev; + if (prev) + prev->next = next; + else + header->setreffrom(next); +} + +memdata * reffrom_t::getmem() { + return header; +} + +memdata * reffrom_t::getref() { + return refto->getmem(); +} + +reffrom_t * reffrom_t::getnext() { + return next; +} + +memdata::memdata(Uint32 _address, mipsmem * _mm) : address(_address), mm(_mm), func(0), refto(0), reffrom(0) { + mm->SetDatas(address, this); +} + +memdata::~memdata() { + mm->SetDatas(address, 0); +} + +Uint32 memdata::getaddress() { + return address; +} + +memdata * memdata::getmem(Uint32 addr) { + return getmem(addr, mm); +} + +memdata * memdata::getmem(Uint32 addr, mipsmem * mm) { + memdata * t = mm->GetDatas(addr); + + if (!t) { + t = new memdata(addr, mm); + } + return t; +} + +func_t * memdata::getfunc() { + return func; +} + +refto_t * memdata::getrefto() { + return refto; +} + +reffrom_t * memdata::getreffrom() { + return reffrom; +} + +void memdata::setfunc(func_t * f) { + func = f; + checkdestroy(); +} + +void memdata::setrefto(refto_t * r) { + refto = r; + checkdestroy(); +} + +void memdata::setreffrom(reffrom_t * r) { + reffrom = r; + checkdestroy(); +} + +void memdata::checkdestroy() { + if (!func && !refto && !reffrom) { + delete this; + } +} + + +mipsmem::mipsmem() { + memset(psyqhead, 0, 0x800); + memset(plainmemory, 0, PSXMEM); + memset(patches, 0, PSXMEM); + memset(patchesmap, 0, PSXMEM / 8); + memset(tags, 0, PSXMEM); + memset(datas, 0, PSXMEM * sizeof(memdata *)); +} + +Uint8 mipsmem::Read8(Uint32 mem) { + if ((mem < 0x80000000) || (mem >= (0x80000000 + PSXMEM))) { + printm(M_WARNING, "Reading at out of bound of memory: 0x%08x\n", mem); + return 0xff; + } + + mem -= 0x80000000; + + if (IsPatched(mem)) { + return patches[mem]; + } else { + return plainmemory[mem]; + } +} + +Uint16 mipsmem::Read16(Uint32 mem) { + Uint8 a, b; + + if (mem & 1) { + printm(M_WARNING, "Read16 at a non 16-bits boundary: 0x%08x\n", mem); + } + + a = Read8(mem); + b = Read8(mem + 1); + + return a | (b << 8); +} + +Uint32 mipsmem::Read32(Uint32 mem) { + Uint8 a, b, c, d; + + if (mem & 3) { + printm(M_WARNING, "Read32 at a non 32-bits boundary: 0x%08x\n", mem); + } + + a = Read8(mem); + b = Read8(mem + 1); + c = Read8(mem + 2); + d = Read8(mem + 3); + + return a | (b << 8) | (c << 16) | (d << 24); +} + +void mipsmem::Write8(Uint32 mem, Uint8 value) { + if ((mem < 0x80000000) || (mem > (0x80000000 + PSXMEM - 1))) { + printm(M_WARNING, "Writing at out of bound of memory: 0x%08x\n", mem); + return; + } + + mem -= 0x80000000; + + patch(mem, 1); + patches[mem] = value; +} + +void mipsmem::Write16(Uint32 mem, Uint16 value) { + if ((mem < 0x80000000) || (mem > (0x80000000 + PSXMEM - 2))) { + printm(M_WARNING, "Writing at out of bound of memory: 0x%08x\n", mem); + return; + } + + mem -= 0x80000000; + + patch(mem, 2); + patches[mem] = value & 0xff; + patches[mem + 1] = (value >> 8) & 0xff; +} + +void mipsmem::Write32(Uint32 mem, Uint32 value) { + if ((mem < 0x80000000) || (mem > (0x80000000 + PSXMEM - 4))) { + printm(M_WARNING, "Writing at out of bound of memory: 0x%08x\n", mem); + return; + } + + mem -= 0x80000000; + + patch(mem, 4); + patches[mem] = value & 0xff; + patches[mem + 1] = (value >> 8) & 0xff; + patches[mem + 2] = (value >> 16) & 0xff; + patches[mem + 3] = (value >> 24) & 0xff; +} + +void mipsmem::unpatch8(Uint32 mem) { + unpatch(mem, 1); +} + +void mipsmem::unpatch16(Uint32 mem) { + unpatch(mem, 2); +} + +void mipsmem::unpatch32(Uint32 mem) { + unpatch(mem, 4); +} + +bool mipsmem::IsPatched(Uint32 mem) { + int mask, pos; + + pos = mem / 8; + mask = 1 << (mem % 8); + + return patchesmap[pos] & mask; +} + +void mipsmem::LoadPSYQ(Handle * h) { + h->read(psyqhead, 0x800); + memset(plainmemory, 0, PSXMEM); + paddr = ((psyq*)psyqhead)->t_addr; + psize = ((psyq*)psyqhead)->t_size; + startpc = ((psyq*)psyqhead)->pc0; + + printm(M_INFO, "Loading %i (%08x) bytes of data at %i (%08x).\n", psize, psize, paddr - 0x80000000, paddr); + + h->read(plainmemory + paddr - 0x80000000, psize); +} + +void mipsmem::SavePSYQ(Handle * h) {\ + Uint32 i; + + if (!*((Uint32 *)psyqhead)) + return; + h->write(psyqhead, 0x800); + paddr = ((psyq*)psyqhead)->t_addr; + psize = ((psyq*)psyqhead)->t_size; + + printm(M_INFO, "Writing %i (%08x) bytes of data from %i (%08x).\n", psize, psize, paddr - 0x80000000, paddr); + + for (i = paddr - 0x80000000; i < psize; i++) { + h->writeU8(Read8(i)); + } +} + +bool mipsmem::GetTag(Uint32 addr, char tag) { + int mask; + + if ((addr < 0x80000000) || (addr >= (0x80000000 + PSXMEM))) { + printm(M_WARNING, "Reading tag at out of bound of memory: 0x%08x\n", addr); + return false; + } + + mask = 1 << tag; + addr -= 0x80000000; + + return tags[addr] & mask; +} + +void mipsmem::SetTag(Uint32 addr, char tag, bool t) { + int mask; + + if ((addr < 0x80000000) || (addr >= (0x80000000 + PSXMEM))) { + printm(M_WARNING, "Setting tag at out of bound of memory: 0x%08x\n", addr); + return; + } + + mask = 1 << tag; + addr -= 0x80000000; + + if (t) { + tags[addr] |= mask; + } else { + tags[addr] &= ~mask; + } +} + +memdata * mipsmem::GetDatas(Uint32 addr) { + return datas[addr]; +} + +void mipsmem::SetDatas(Uint32 addr, memdata * p) { + datas[addr] = p; +} + +Uint32 mipsmem::GetPC() { + return startpc; +} + +Uint32 mipsmem::GetLower() { + return paddr; +} + +Uint32 mipsmem::GetUpper() { + return paddr + psize; +} + +void mipsmem::patch(Uint32 mem, int size) { + int mask, pos; + + pos = mem / 8; + mask = 1 << (mem % 8); + + patchesmap[pos] |= mask; + + if (size != 1) { + patch(mem + 1, size - 1); + } +} + +void mipsmem::unpatch(Uint32 mem, int size) { + int mask, pos; + + pos = mem / 8; + mask = ~(1 << (mem % 8)); + + patchesmap[pos] &= mask; + + if (size != 1) { + unpatch(mem + 1, size - 1); + } +} diff --git a/lib/mipsobj.cpp b/lib/mipsobj.cpp index 97663e6..233c5c5 100644 --- a/lib/mipsobj.cpp +++ b/lib/mipsobj.cpp @@ -1,269 +1,269 @@ -#include "mipsobj.h" - -section::section(const String & _name, int _type) : name(_name), type(_type), datas(0), length(0) { } -section::section() : name(""), type(-1), datas(0), length(0) { } - -section::~section() { - if (datas) - free(datas); -} - -void section::setname(const String & _name) { - name = _name; -} - -void section::settype(int _type) { - type = _type; -} - -void section::putdatas(const Uint8 * _datas, int _length) { - if (type != BSS) { - datas = (Uint8 *) realloc(datas, length + _length); - memcpy(datas + length, _datas, _length); - } - length += _length; -} - -int section::gettype() { - return type; -} - -int section::getsize() { - return length; -} - -const Uint8 * section::getdatas() { - return datas; -} - -void section::putreloc(const String & _symbol, int _type, Uint32 _offset) { - struct reloc_t r; - - r.symbol = _symbol; - r.type = _type; - r.offset = _offset; - - putreloc(r); -} - -void section::putreloc(const struct reloc_t & r) { - relocs.push_back(r); -} - -mipsobj::mipsobj() : loaded(false) { } - -mipsobj::~mipsobj() { } - -void loadELF(Handle * elf) throw (GeneralException) { -} - -#define OBJSIG 0x024b4e4c - -#define READNAME(_str, _file) { \ - char _name[256]; \ - int _len; \ - \ - _len = _file->readU8(); \ - _file->read(_name, _len); \ - _name[_len] = 0; \ - _str = _name; \ -} - -void mipsobj::loadOBJ(Handle * obj) throw (GeneralException) { - int cursec, len, reloctype, relocexpr, id; - bool eof = false; - std::map secnames; - std::map symbolnames; - Uint8 * datas; - struct reloc_t reloc; - struct symbol_t symbol; - String name; - - while (!eof) { - int entryid = obj->readU8(); - - switch (entryid) { - case 0x00: - eof = true; - break; - - case 0x02: - len = obj->readU16(); - datas = (Uint8 *) malloc(len); - - obj->read(datas, len); - sections[secnames[cursec]].putdatas(datas, len); - - free(datas); - break; - - case 0x06: - cursec = obj->readU16(); - break; - - case 0x08: - len = obj->readU32(); - - sections[secnames[cursec]].putdatas(0, len); - break; - - case 0x0a: - reloctype = obj->readU8(); - reloc.offset = obj->readU16(); - - switch (reloctype) { - case 0x10: - reloc.type = R_MIPS_32; - break; - case 0x4a: - reloc.type = R_MIPS_26; - break; - case 0x52: - reloc.type = R_MIPS_HI16; - break; - case 0x54: - reloc.type = R_MIPS_LO16; - break; - case 0x0a: - case 0x26: - case 0x28: - case 0x64: - printm(M_ERROR, "Relocation type %02x not supported.\n", reloctype); - exit(-1); - break; - default: - printm(M_ERROR, "Relocation type %02x UNKNOWN! Please send the object to the author.\n", reloctype); - exit(-1); - } - - relocexpr = obj->readU8(); - - switch (relocexpr) { - case 0x02: - reloc.symbol = symbolnames[obj->readU16()]; - break; - case 0x04: - reloc.symbol = secnames[obj->readU16()]; - break; - case 0x00: - case 0x0c: - case 0x16: - case 0x2c: - case 0x2e: - case 0x30: - case 0x32: - case 0x36: - printm(M_ERROR, "Relocation expression %02x not supported.\n", relocexpr); - exit(-1); - break; - default: - printm(M_ERROR, "Relocation expression %02x UNKNOWN! Please mail the author.\n", relocexpr); - exit(-1); - break; - } - - sections[secnames[cursec]].relocs.push_back(reloc); - - break; - - case 0x0c: - id = obj->readU16(); - symbol.section = obj->readU16(); - symbol.offset = obj->readU32(); - READNAME(symbol.name, obj); - symbol.type = GLOBAL; - - symbolnames[id] = symbol.name; - - break; - - case 0x0e: - id = obj->readU16(); - READNAME(symbol.name, obj); - symbol.type = EXTERN; - - symbolnames[id] = symbol.name; - - break; - - case 0x10: - id = obj->readU16(); - obj->readU8(); - obj->readU16(); - READNAME(name, obj); - - secnames[id] = name; - - break; - - case 0x12: - printm(M_WARNING, "Local symbol not supported.\n"); - obj->readU16(); - obj->readU32(); - READNAME(name, obj); - break; - - case 0x1c: - printm(M_WARNING, "File number and name not supported.\n"); - obj->readU16(); - READNAME(name, obj); - break; - - case 0x2e: - if ((id = obj->readU8()) != 7) { - printm(M_ERROR, "CPU type %i not supported.\n", id); - exit(-1); - } - break; - - case 0x30: - printm(M_ERROR, "Constant not supported.\n"); - exit(-1); - break; - - default: - printm(M_ERROR, "Object entry type %i UNKNOWN! Please send the object to the author.\n", entryid); - exit(-1); - break; - } - } -} - -#define LIBSIG 0x0142494c - -void mipsobj::loadLIB(Handle * lib, const String & objname) throw (GeneralException) { - char _name[9]; - String name; - int hsize, size, ptr; - bool found = false; - - lib->seek(0); - - if (lib->readU32() != LIBSIG) { - throw GeneralException("Not a Psy-Q lib file"); - } - - while (lib->tell() != lib->GetSize()) { - ptr = lib->tell(); - - lib->read(_name, 8); - name = _name; - lib->seek(4, SEEK_CUR); - hsize = lib->readU32(); - size = lib->readU32(); - - if (objname == name.trim()) { - lib->seek(ptr + hsize); - found = true; - break; - } - - lib->seek(ptr + size); - } - - if (!found) { - throw GeneralException("Object `" + objname + "' not found in archive " + lib->GetName()); - } - - loadOBJ(lib); -} +#include "mipsobj.h" + +section::section(const String & _name, int _type) : name(_name), type(_type), datas(0), length(0) { } +section::section() : name(""), type(-1), datas(0), length(0) { } + +section::~section() { + if (datas) + free(datas); +} + +void section::setname(const String & _name) { + name = _name; +} + +void section::settype(int _type) { + type = _type; +} + +void section::putdatas(const Uint8 * _datas, int _length) { + if (type != BSS) { + datas = (Uint8 *) realloc(datas, length + _length); + memcpy(datas + length, _datas, _length); + } + length += _length; +} + +int section::gettype() { + return type; +} + +int section::getsize() { + return length; +} + +const Uint8 * section::getdatas() { + return datas; +} + +void section::putreloc(const String & _symbol, int _type, Uint32 _offset) { + struct reloc_t r; + + r.symbol = _symbol; + r.type = _type; + r.offset = _offset; + + putreloc(r); +} + +void section::putreloc(const struct reloc_t & r) { + relocs.push_back(r); +} + +mipsobj::mipsobj() : loaded(false) { } + +mipsobj::~mipsobj() { } + +void loadELF(Handle * elf) throw (GeneralException) { +} + +#define OBJSIG 0x024b4e4c + +#define READNAME(_str, _file) { \ + char _name[256]; \ + int _len; \ + \ + _len = _file->readU8(); \ + _file->read(_name, _len); \ + _name[_len] = 0; \ + _str = _name; \ +} + +void mipsobj::loadOBJ(Handle * obj) throw (GeneralException) { + int cursec, len, reloctype, relocexpr, id; + bool eof = false; + std::map secnames; + std::map symbolnames; + Uint8 * datas; + struct reloc_t reloc; + struct symbol_t symbol; + String name; + + while (!eof) { + int entryid = obj->readU8(); + + switch (entryid) { + case 0x00: + eof = true; + break; + + case 0x02: + len = obj->readU16(); + datas = (Uint8 *) malloc(len); + + obj->read(datas, len); + sections[secnames[cursec]].putdatas(datas, len); + + free(datas); + break; + + case 0x06: + cursec = obj->readU16(); + break; + + case 0x08: + len = obj->readU32(); + + sections[secnames[cursec]].putdatas(0, len); + break; + + case 0x0a: + reloctype = obj->readU8(); + reloc.offset = obj->readU16(); + + switch (reloctype) { + case 0x10: + reloc.type = R_MIPS_32; + break; + case 0x4a: + reloc.type = R_MIPS_26; + break; + case 0x52: + reloc.type = R_MIPS_HI16; + break; + case 0x54: + reloc.type = R_MIPS_LO16; + break; + case 0x0a: + case 0x26: + case 0x28: + case 0x64: + printm(M_ERROR, "Relocation type %02x not supported.\n", reloctype); + exit(-1); + break; + default: + printm(M_ERROR, "Relocation type %02x UNKNOWN! Please send the object to the author.\n", reloctype); + exit(-1); + } + + relocexpr = obj->readU8(); + + switch (relocexpr) { + case 0x02: + reloc.symbol = symbolnames[obj->readU16()]; + break; + case 0x04: + reloc.symbol = secnames[obj->readU16()]; + break; + case 0x00: + case 0x0c: + case 0x16: + case 0x2c: + case 0x2e: + case 0x30: + case 0x32: + case 0x36: + printm(M_ERROR, "Relocation expression %02x not supported.\n", relocexpr); + exit(-1); + break; + default: + printm(M_ERROR, "Relocation expression %02x UNKNOWN! Please mail the author.\n", relocexpr); + exit(-1); + break; + } + + sections[secnames[cursec]].relocs.push_back(reloc); + + break; + + case 0x0c: + id = obj->readU16(); + symbol.section = obj->readU16(); + symbol.offset = obj->readU32(); + READNAME(symbol.name, obj); + symbol.type = GLOBAL; + + symbolnames[id] = symbol.name; + + break; + + case 0x0e: + id = obj->readU16(); + READNAME(symbol.name, obj); + symbol.type = EXTERN; + + symbolnames[id] = symbol.name; + + break; + + case 0x10: + id = obj->readU16(); + obj->readU8(); + obj->readU16(); + READNAME(name, obj); + + secnames[id] = name; + + break; + + case 0x12: + printm(M_WARNING, "Local symbol not supported.\n"); + obj->readU16(); + obj->readU32(); + READNAME(name, obj); + break; + + case 0x1c: + printm(M_WARNING, "File number and name not supported.\n"); + obj->readU16(); + READNAME(name, obj); + break; + + case 0x2e: + if ((id = obj->readU8()) != 7) { + printm(M_ERROR, "CPU type %i not supported.\n", id); + exit(-1); + } + break; + + case 0x30: + printm(M_ERROR, "Constant not supported.\n"); + exit(-1); + break; + + default: + printm(M_ERROR, "Object entry type %i UNKNOWN! Please send the object to the author.\n", entryid); + exit(-1); + break; + } + } +} + +#define LIBSIG 0x0142494c + +void mipsobj::loadLIB(Handle * lib, const String & objname) throw (GeneralException) { + char _name[9]; + String name; + int hsize, size, ptr; + bool found = false; + + lib->seek(0); + + if (lib->readU32() != LIBSIG) { + throw GeneralException("Not a Psy-Q lib file"); + } + + while (lib->tell() != lib->GetSize()) { + ptr = lib->tell(); + + lib->read(_name, 8); + name = _name; + lib->seek(4, SEEK_CUR); + hsize = lib->readU32(); + size = lib->readU32(); + + if (objname == name.trim()) { + lib->seek(ptr + hsize); + found = true; + break; + } + + lib->seek(ptr + size); + } + + if (!found) { + throw GeneralException("Object `" + objname + "' not found in archive " + lib->GetName()); + } + + loadOBJ(lib); +} diff --git a/lib/yazedc.cpp b/lib/yazedc.cpp index 6350ef7..100cd38 100644 --- a/lib/yazedc.cpp +++ b/lib/yazedc.cpp @@ -1,273 +1,273 @@ -/* - * PSX-Tools Bundle Pack - * Copyright (C) 1998 Heiko Eissfeldt - * portions used& Chris Smith - * Modified by Yazoo, then by - * Nicolas "Pixel" Noble - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* $Id: yazedc.cpp,v 1.3 2003-12-04 01:47:37 pixel Exp $ */ - -#include -#include -#include -#include -#include -#include -#include "yazedc.h" - -yazedc::yazedc() : minute(0), second(2), frame(0), sectortype(0) {} - -/* ------------- tables generated by gen_encodes --------------*/ - -#include "crctables" - -static int encode_L2_Q(unsigned char inout[4 + L2_RAW + 4 + 8 + L2_P + L2_Q]) -{ - unsigned char *Q; - int i,j; - - Q = inout + 4 + L2_RAW + 4 + 8 + L2_P; - memset(Q, 0, L2_Q); - for (j = 0; j < 26; j++) { - for (i = 0; i < 43; i++) { - unsigned char data; - - /* LSB */ - data = inout[(j*43*2+i*2*44) % (4 + L2_RAW + 4 + 8 + L2_P)]; - if (data != 0) { - unsigned int base = rs_l12_log[data]; - - unsigned int sum = base + DQ[0][i]; - if (sum >= ((1 << RS_L12_BITS)-1)) - sum -= (1 << RS_L12_BITS)-1; - - Q[0] ^= rs_l12_alog[sum]; - - sum = base + DQ[1][i]; - if (sum >= ((1 << RS_L12_BITS)-1)) - sum -= (1 << RS_L12_BITS)-1; - - Q[26*2] ^= rs_l12_alog[sum]; - } - /* MSB */ - data = inout[(j*43*2+i*2*44+1) % (4 + L2_RAW + 4 + 8 + L2_P)]; - if (data != 0) { - unsigned int base = rs_l12_log[data]; - - unsigned int sum = base+DQ[0][i]; - if (sum >= ((1 << RS_L12_BITS)-1)) - sum -= (1 << RS_L12_BITS)-1; - - Q[1] ^= rs_l12_alog[sum]; - - sum = base + DQ[1][i]; - if (sum >= ((1 << RS_L12_BITS)-1)) - sum -= (1 << RS_L12_BITS)-1; - - Q[26*2+1] ^= rs_l12_alog[sum]; - } - } - Q += 2; - } - return 0; -} - -static int encode_L2_P(unsigned char inout[4 + L2_RAW + 4 + 8 + L2_P]) -{ - unsigned char *P; - int i,j; - - P = inout + 4 + L2_RAW + 4 + 8; - memset(P, 0, L2_P); - for (j = 0; j < 43; j++) { - for (i = 0; i < 24; i++) { - unsigned char data; - - /* LSB */ - data = inout[i*2*43]; - if (data != 0) { - unsigned int base = rs_l12_log[data]; - - unsigned int sum = base + DP[0][i]; - if (sum >= ((1 << RS_L12_BITS)-1)) - sum -= (1 << RS_L12_BITS)-1; - - P[0] ^= rs_l12_alog[sum]; - - sum = base + DP[1][i]; - if (sum >= ((1 << RS_L12_BITS)-1)) - sum -= (1 << RS_L12_BITS)-1; - - P[43*2] ^= rs_l12_alog[sum]; - } - /* MSB */ - data = inout[i*2*43+1]; - if (data != 0) { - unsigned int base = rs_l12_log[data]; - - unsigned int sum = base + DP[0][i]; - if (sum >= ((1 << RS_L12_BITS)-1)) - sum -= (1 << RS_L12_BITS)-1; - - P[1] ^= rs_l12_alog[sum]; - - sum = base + DP[1][i]; - if (sum >= ((1 << RS_L12_BITS)-1)) - sum -= (1 << RS_L12_BITS)-1; - - P[43*2+1] ^= rs_l12_alog[sum]; - } - } - P += 2; - inout += 2; - } - return 0; -} - -int yazedc::scramble_L2(unsigned char *inout) -{ - unsigned char *r = inout + 12; - const unsigned char *s = yellowbook_scrambler; - unsigned int i; - unsigned int *f = (unsigned int *)inout; - - for (i = (L2_RAW + L2_Q + L2_P +16)/sizeof(unsigned char); i; i--) { - *r++ ^= *s++; - } - - /* generate F1 frames */ - for (i = (2352/sizeof(unsigned int)); i; i--) { - *f++ = ((*f & 0xff00ff00UL) >> 8) | ((*f & 0x00ff00ffUL) << 8); - } - - return 0; -} - -int yazedc::build_address(unsigned char inout[], int sectortype, unsigned address) -{ - inout[12] = minute; - inout[13] = second; - inout[14] = frame; - if (sectortype == MODE_0) - inout[15] = 0; - else if (sectortype == MODE_1) - inout[15] = 1; - else if (sectortype == MODE_2) - inout[15] = 2; - else if (sectortype == MODE_2_FORM_1) - inout[15] = 2; - else if (sectortype == MODE_2_FORM_2) - inout[15] = 2; - else - return -1; - return 0; -} - -#include "crctable.out" -unsigned long int build_edc(unsigned char inout[], int from, int upto) -{ - unsigned char *p = inout+from; - unsigned long result = 0; - - for (; from <= upto; from++) - result = EDC_crctable[(result ^ *p++) & 0xffL] ^ (result >> 8); - - return result; -} - -/* Layer 2 Product code en/decoder */ -int yazedc::do_encode_L2(unsigned char inout[(12 + 4 + L2_RAW+4+8+L2_Q+L2_P)], int sectortype, unsigned address) -{ - unsigned long int result; - -#define SYNCPATTERN "\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" - - /* supply initial sync pattern */ - memcpy(inout, SYNCPATTERN, sizeof(SYNCPATTERN)); - - if (sectortype == MODE_0) { - memset(inout + sizeof(SYNCPATTERN), 0, 4 + L2_RAW + 12 + L2_P + L2_Q); - build_address(inout, sectortype, address); - return 0; - } - - switch (sectortype) { - case MODE_1: - build_address(inout, sectortype, address); - result = build_edc(inout, 0, 16+2048-1); - inout[2064+0] = result >> 0L; - inout[2064+1] = result >> 8L; - inout[2064+2] = result >> 16L; - inout[2064+3] = result >> 24L; - memset(inout+2064+4, 0, 8); - encode_L2_P(inout+12); - encode_L2_Q(inout+12); - break; - case MODE_2: - build_address(inout, sectortype, address); - break; - case MODE_2_FORM_1: - result = build_edc(inout, 16, 16+8+2048-1); - inout[2072+0] = result >> 0L; - inout[2072+1] = result >> 8L; - inout[2072+2] = result >> 16L; - inout[2072+3] = result >> 24L; - - /* clear header for P/Q parity calculation */ - inout[12] = 0; - inout[12+1] = 0; - inout[12+2] = 0; - inout[12+3] = 0; - encode_L2_P(inout+12); - encode_L2_Q(inout+12); - build_address(inout, sectortype, address); - break; - case MODE_2_FORM_2: - build_address(inout, sectortype, address); - result = build_edc(inout, 16, 16+8+2324-1); - inout[2348+0] = result >> 0L; - inout[2348+1] = result >> 8L; - inout[2348+2] = result >> 16L; - inout[2348+3] = result >> 24L; - break; - default: - return -1; - } - - return 0; -} - -int yazedc::get_sector_type(void) -{ - return sectortype; -} - -int yazedc::set_sector_type(int st) -{ - switch(st) { - case MODE_0: - case MODE_1: - case MODE_2: - case MODE_2_FORM_1: - case MODE_2_FORM_2: - sectortype = st; - default: - return -1; - } - return 0; -} +/* + * PSX-Tools Bundle Pack + * Copyright (C) 1998 Heiko Eissfeldt + * portions used& Chris Smith + * Modified by Yazoo, then by + * Nicolas "Pixel" Noble + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id: yazedc.cpp,v 1.4 2004-11-27 21:44:48 pixel Exp $ */ + +#include +#include +#include +#include +#include +#include +#include "yazedc.h" + +yazedc::yazedc() : minute(0), second(2), frame(0), sectortype(0) {} + +/* ------------- tables generated by gen_encodes --------------*/ + +#include "crctables" + +static int encode_L2_Q(unsigned char inout[4 + L2_RAW + 4 + 8 + L2_P + L2_Q]) +{ + unsigned char *Q; + int i,j; + + Q = inout + 4 + L2_RAW + 4 + 8 + L2_P; + memset(Q, 0, L2_Q); + for (j = 0; j < 26; j++) { + for (i = 0; i < 43; i++) { + unsigned char data; + + /* LSB */ + data = inout[(j*43*2+i*2*44) % (4 + L2_RAW + 4 + 8 + L2_P)]; + if (data != 0) { + unsigned int base = rs_l12_log[data]; + + unsigned int sum = base + DQ[0][i]; + if (sum >= ((1 << RS_L12_BITS)-1)) + sum -= (1 << RS_L12_BITS)-1; + + Q[0] ^= rs_l12_alog[sum]; + + sum = base + DQ[1][i]; + if (sum >= ((1 << RS_L12_BITS)-1)) + sum -= (1 << RS_L12_BITS)-1; + + Q[26*2] ^= rs_l12_alog[sum]; + } + /* MSB */ + data = inout[(j*43*2+i*2*44+1) % (4 + L2_RAW + 4 + 8 + L2_P)]; + if (data != 0) { + unsigned int base = rs_l12_log[data]; + + unsigned int sum = base+DQ[0][i]; + if (sum >= ((1 << RS_L12_BITS)-1)) + sum -= (1 << RS_L12_BITS)-1; + + Q[1] ^= rs_l12_alog[sum]; + + sum = base + DQ[1][i]; + if (sum >= ((1 << RS_L12_BITS)-1)) + sum -= (1 << RS_L12_BITS)-1; + + Q[26*2+1] ^= rs_l12_alog[sum]; + } + } + Q += 2; + } + return 0; +} + +static int encode_L2_P(unsigned char inout[4 + L2_RAW + 4 + 8 + L2_P]) +{ + unsigned char *P; + int i,j; + + P = inout + 4 + L2_RAW + 4 + 8; + memset(P, 0, L2_P); + for (j = 0; j < 43; j++) { + for (i = 0; i < 24; i++) { + unsigned char data; + + /* LSB */ + data = inout[i*2*43]; + if (data != 0) { + unsigned int base = rs_l12_log[data]; + + unsigned int sum = base + DP[0][i]; + if (sum >= ((1 << RS_L12_BITS)-1)) + sum -= (1 << RS_L12_BITS)-1; + + P[0] ^= rs_l12_alog[sum]; + + sum = base + DP[1][i]; + if (sum >= ((1 << RS_L12_BITS)-1)) + sum -= (1 << RS_L12_BITS)-1; + + P[43*2] ^= rs_l12_alog[sum]; + } + /* MSB */ + data = inout[i*2*43+1]; + if (data != 0) { + unsigned int base = rs_l12_log[data]; + + unsigned int sum = base + DP[0][i]; + if (sum >= ((1 << RS_L12_BITS)-1)) + sum -= (1 << RS_L12_BITS)-1; + + P[1] ^= rs_l12_alog[sum]; + + sum = base + DP[1][i]; + if (sum >= ((1 << RS_L12_BITS)-1)) + sum -= (1 << RS_L12_BITS)-1; + + P[43*2+1] ^= rs_l12_alog[sum]; + } + } + P += 2; + inout += 2; + } + return 0; +} + +int yazedc::scramble_L2(unsigned char *inout) +{ + unsigned char *r = inout + 12; + const unsigned char *s = yellowbook_scrambler; + unsigned int i; + unsigned int *f = (unsigned int *)inout; + + for (i = (L2_RAW + L2_Q + L2_P +16)/sizeof(unsigned char); i; i--) { + *r++ ^= *s++; + } + + /* generate F1 frames */ + for (i = (2352/sizeof(unsigned int)); i; i--) { + *f++ = ((*f & 0xff00ff00UL) >> 8) | ((*f & 0x00ff00ffUL) << 8); + } + + return 0; +} + +int yazedc::build_address(unsigned char inout[], int sectortype, unsigned address) +{ + inout[12] = minute; + inout[13] = second; + inout[14] = frame; + if (sectortype == MODE_0) + inout[15] = 0; + else if (sectortype == MODE_1) + inout[15] = 1; + else if (sectortype == MODE_2) + inout[15] = 2; + else if (sectortype == MODE_2_FORM_1) + inout[15] = 2; + else if (sectortype == MODE_2_FORM_2) + inout[15] = 2; + else + return -1; + return 0; +} + +#include "crctable.out" +unsigned long int build_edc(unsigned char inout[], int from, int upto) +{ + unsigned char *p = inout+from; + unsigned long result = 0; + + for (; from <= upto; from++) + result = EDC_crctable[(result ^ *p++) & 0xffL] ^ (result >> 8); + + return result; +} + +/* Layer 2 Product code en/decoder */ +int yazedc::do_encode_L2(unsigned char inout[(12 + 4 + L2_RAW+4+8+L2_Q+L2_P)], int sectortype, unsigned address) +{ + unsigned long int result; + +#define SYNCPATTERN "\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + + /* supply initial sync pattern */ + memcpy(inout, SYNCPATTERN, sizeof(SYNCPATTERN)); + + if (sectortype == MODE_0) { + memset(inout + sizeof(SYNCPATTERN), 0, 4 + L2_RAW + 12 + L2_P + L2_Q); + build_address(inout, sectortype, address); + return 0; + } + + switch (sectortype) { + case MODE_1: + build_address(inout, sectortype, address); + result = build_edc(inout, 0, 16+2048-1); + inout[2064+0] = result >> 0L; + inout[2064+1] = result >> 8L; + inout[2064+2] = result >> 16L; + inout[2064+3] = result >> 24L; + memset(inout+2064+4, 0, 8); + encode_L2_P(inout+12); + encode_L2_Q(inout+12); + break; + case MODE_2: + build_address(inout, sectortype, address); + break; + case MODE_2_FORM_1: + result = build_edc(inout, 16, 16+8+2048-1); + inout[2072+0] = result >> 0L; + inout[2072+1] = result >> 8L; + inout[2072+2] = result >> 16L; + inout[2072+3] = result >> 24L; + + /* clear header for P/Q parity calculation */ + inout[12] = 0; + inout[12+1] = 0; + inout[12+2] = 0; + inout[12+3] = 0; + encode_L2_P(inout+12); + encode_L2_Q(inout+12); + build_address(inout, sectortype, address); + break; + case MODE_2_FORM_2: + build_address(inout, sectortype, address); + result = build_edc(inout, 16, 16+8+2324-1); + inout[2348+0] = result >> 0L; + inout[2348+1] = result >> 8L; + inout[2348+2] = result >> 16L; + inout[2348+3] = result >> 24L; + break; + default: + return -1; + } + + return 0; +} + +int yazedc::get_sector_type(void) +{ + return sectortype; +} + +int yazedc::set_sector_type(int st) +{ + switch(st) { + case MODE_0: + case MODE_1: + case MODE_2: + case MODE_2_FORM_1: + case MODE_2_FORM_2: + sectortype = st; + default: + return -1; + } + return 0; +} -- cgit v1.2.3