diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/cdabstract.cpp | 384 | ||||
| -rw-r--r-- | lib/cdreader.cpp | 668 | ||||
| -rw-r--r-- | lib/dteutils.cpp | 638 | ||||
| -rw-r--r-- | lib/luapsx.cpp | 614 | ||||
| -rw-r--r-- | lib/lzss.cpp | 928 | ||||
| -rw-r--r-- | lib/mips.cpp | 2136 | ||||
| -rw-r--r-- | lib/mipsdis.cpp | 360 | ||||
| -rw-r--r-- | lib/mipsdump.cpp | 414 | ||||
| -rw-r--r-- | lib/mipsmem.cpp | 698 | ||||
| -rw-r--r-- | lib/mipsobj.cpp | 538 | ||||
| -rw-r--r-- | lib/yazedc.cpp | 546 | 
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;
 +}
  | 
