summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorpixel <pixel>2004-11-27 21:44:15 +0000
committerpixel <pixel>2004-11-27 21:44:15 +0000
commit50f0dd331f8168fb5b2cd60c70178fad627b7fb6 (patch)
tree65fcec7bd507791f0db8a3af1b60ad9ac631f4a7 /lib
parentf1df76865d1751469deff19e62255d50a814f183 (diff)
Large dos2unix commit...
Diffstat (limited to 'lib')
-rw-r--r--lib/cdabstract.cpp384
-rw-r--r--lib/cdreader.cpp668
-rw-r--r--lib/dteutils.cpp638
-rw-r--r--lib/luapsx.cpp614
-rw-r--r--lib/lzss.cpp928
-rw-r--r--lib/mips.cpp2136
-rw-r--r--lib/mipsdis.cpp360
-rw-r--r--lib/mipsdump.cpp414
-rw-r--r--lib/mipsmem.cpp698
-rw-r--r--lib/mipsobj.cpp538
-rw-r--r--lib/yazedc.cpp546
11 files changed, 3962 insertions, 3962 deletions
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 <unistd.h>
-#include <sys/ioctl.h>
-#include <fcntl.h>
-#include <linux/cdrom.h>
-#endif
-
-#if defined (_MSC_VER) || defined (__MINGW32__)
-#include <windowsx.h>
-#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<String> cdabstract::probe() throw (GeneralException) {
- int i;
- std::vector<String> 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 <unistd.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <linux/cdrom.h>
+#endif
+
+#if defined (_MSC_VER) || defined (__MINGW32__)
+#include <windowsx.h>
+#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<String> cdabstract::probe() throw (GeneralException) {
+ int i;
+ std::vector<String> 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 <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#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 <unistd.h>
-#include <sys/ioctl.h>
-#include <linux/cdrom.h>
-
-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 <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#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 <unistd.h>
+#include <sys/ioctl.h>
+#include <linux/cdrom.h>
+
+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 <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#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 <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#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 <LuaHandle.h>
-#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 <LuaHandle.h>
+#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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <iostream>
-#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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <iostream>
+#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<pairarg>::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<pairarg>::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<int, String> secnames;
- std::map<int, String> 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<int, String> secnames;
+ std::map<int, String> 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 <stdio.h>
-#include <string.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#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 <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#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;
+}