├── .gitattributes
├── resources
└── oxe_icon_trans.ico
├── resources.qrc
├── Source
├── main.cpp
├── Decryptors
│ ├── INosDecryptor.h
│ ├── NosZlibDecryptor.cpp
│ ├── NosZlibDecryptor.h
│ ├── NosTextOthersFileDecryptor.h
│ ├── NosTextOthersFileDecryptor.cpp
│ ├── NosTextDatFileDecryptor.h
│ └── NosTextDatFileDecryptor.cpp
├── Ui
│ ├── FileInfo.h
│ ├── OnexTreeText.h
│ ├── SingleTextFilePreview.cpp
│ ├── OnexNStcData.h
│ ├── OnexNS4BbData.h
│ ├── OnexTreeText.cpp
│ ├── SingleTextFilePreview.h
│ ├── OnexNSipData.h
│ ├── OnexNStpData.h
│ ├── OnexTreeZlibItem.h
│ ├── SingleTextFilePreview.ui
│ ├── SingleImagePreview.ui
│ ├── FileInfo.cpp
│ ├── OnexTreeImage.h
│ ├── SingleImagePreview.h
│ ├── OnexNSipData.cpp
│ ├── OnexTreeItem.h
│ ├── OnexNS4BbData.cpp
│ ├── OnexNStcData.cpp
│ ├── OnexTreeZlibItem.cpp
│ ├── SingleImagePreview.cpp
│ ├── OnexNStpData.cpp
│ ├── OnexTreeImage.cpp
│ ├── FileInfo.ui
│ └── OnexTreeItem.cpp
├── Openers
│ ├── INosFileOpener.h
│ ├── NosTextOpener.h
│ ├── INosFileOpener.cpp
│ ├── NosZlibOpener.h
│ ├── NosTextOpener.cpp
│ └── NosZlibOpener.cpp
├── NosEnumTypes.h
├── ImageConverter.h
├── MainWindow.h
├── mainwindow.ui
├── MainWindow.cpp
└── ImageConverter.cpp
├── .gitignore
├── README.MD
├── LICENSE
└── OnexExplorer.pro
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
--------------------------------------------------------------------------------
/resources/oxe_icon_trans.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OnexTale/OnexExplorer/HEAD/resources/oxe_icon_trans.ico
--------------------------------------------------------------------------------
/resources.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | resources/oxe_icon_trans.ico
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Source/main.cpp:
--------------------------------------------------------------------------------
1 | #include "MainWindow.h"
2 | #include
3 |
4 | int main(int argc, char *argv[])
5 | {
6 | QApplication a(argc, argv);
7 | MainWindow w;
8 | w.show();
9 |
10 | return a.exec();
11 | }
12 |
--------------------------------------------------------------------------------
/Source/Decryptors/INosDecryptor.h:
--------------------------------------------------------------------------------
1 | #ifndef INOSDECRYPTOR_H
2 | #define INOSDECRYPTOR_H
3 | #include
4 |
5 | class INosDecryptor
6 | {
7 | public:
8 | virtual QByteArray encrypt(QByteArray& array) = 0;
9 | virtual QByteArray decrypt(QByteArray& array) = 0;
10 | };
11 |
12 | #endif // INOSDECRYPTOR_H
13 |
--------------------------------------------------------------------------------
/Source/Decryptors/NosZlibDecryptor.cpp:
--------------------------------------------------------------------------------
1 | #include "NosZlibDecryptor.h"
2 |
3 | NosZlibDecryptor::NosZlibDecryptor()
4 | {
5 |
6 | }
7 |
8 | QByteArray NosZlibDecryptor::encrypt(QByteArray &array)
9 | {
10 | return qCompress(array, 1);
11 | }
12 |
13 | QByteArray NosZlibDecryptor::decrypt(QByteArray &array)
14 | {
15 | return qUncompress(array);
16 | }
17 |
--------------------------------------------------------------------------------
/Source/Decryptors/NosZlibDecryptor.h:
--------------------------------------------------------------------------------
1 | #ifndef NOSZLIBDECRYPTOR_H
2 | #define NOSZLIBDECRYPTOR_H
3 | #include "INosDecryptor.h"
4 | #include
5 |
6 | class NosZlibDecryptor
7 | {
8 | public:
9 | NosZlibDecryptor();
10 | virtual QByteArray encrypt(QByteArray& array);
11 | virtual QByteArray decrypt(QByteArray& array);
12 | };
13 |
14 | #endif // NOSZLIBDECRYPTOR_H
15 |
--------------------------------------------------------------------------------
/Source/Ui/FileInfo.h:
--------------------------------------------------------------------------------
1 | #ifndef FILEINFO_H
2 | #define FILEINFO_H
3 |
4 | #include
5 | #include "OnexTreeItem.h"
6 |
7 | namespace Ui {
8 | class FileInfo;
9 | }
10 |
11 | class FileInfo : public QDialog
12 | {
13 | Q_OBJECT
14 |
15 | public:
16 | explicit FileInfo(OnexTreeItem* item, QWidget *parent = 0);
17 | ~FileInfo();
18 |
19 | private:
20 | Ui::FileInfo *ui;
21 | };
22 |
23 | #endif // FILEINFO_H
24 |
--------------------------------------------------------------------------------
/Source/Decryptors/NosTextOthersFileDecryptor.h:
--------------------------------------------------------------------------------
1 | #ifndef NOSTEXTOTHERSFILEDECRYPTOR_H
2 | #define NOSTEXTOTHERSFILEDECRYPTOR_H
3 | #include "INosDecryptor.h"
4 |
5 | class NosTextOthersFileDecryptor : public INosDecryptor
6 | {
7 | public:
8 | NosTextOthersFileDecryptor();
9 | virtual QByteArray encrypt(QByteArray& array);
10 | virtual QByteArray decrypt(QByteArray& array);
11 | };
12 |
13 | #endif // NOSTEXTOTHERSFILEDECRYPTOR_H
14 |
--------------------------------------------------------------------------------
/Source/Ui/OnexTreeText.h:
--------------------------------------------------------------------------------
1 | #ifndef ONEXTREETEXT_H
2 | #define ONEXTREETEXT_H
3 | #include "OnexTreeItem.h"
4 |
5 | class OnexTreeText : public OnexTreeItem
6 | {
7 | private:
8 | int fileNmber;
9 | int isDat;
10 | public:
11 | OnexTreeText(QString name, int fileNumber = 0, int isDat = 0, QByteArray content = QByteArray());
12 | virtual QWidget* onClicked() override;
13 |
14 | virtual ~OnexTreeText();
15 | };
16 |
17 | #endif // ONEXTREETEXT_H
18 |
--------------------------------------------------------------------------------
/Source/Ui/SingleTextFilePreview.cpp:
--------------------------------------------------------------------------------
1 | #include "SingleTextFilePreview.h"
2 | #include "ui_SingleTextFilePreview.h"
3 |
4 | SingleTextFilePreview::SingleTextFilePreview(QByteArray &item, QWidget *parent) :
5 | QWidget(parent),
6 | ui(new Ui::SingleTextFilePreview)
7 | {
8 | ui->setupUi(this);
9 | ui->plainTextEdit->appendPlainText(QString::fromLocal8Bit(item));
10 | }
11 |
12 | SingleTextFilePreview::~SingleTextFilePreview()
13 | {
14 | delete ui;
15 | }
16 |
--------------------------------------------------------------------------------
/Source/Decryptors/NosTextOthersFileDecryptor.cpp:
--------------------------------------------------------------------------------
1 | #include "NosTextOthersFileDecryptor.h"
2 |
3 | NosTextOthersFileDecryptor::NosTextOthersFileDecryptor()
4 | {
5 |
6 | }
7 |
8 | QByteArray NosTextOthersFileDecryptor::encrypt(QByteArray &array)
9 | {
10 | return QByteArray();
11 | }
12 |
13 | QByteArray NosTextOthersFileDecryptor::decrypt(QByteArray &array)
14 | {
15 | QByteArray result;
16 |
17 | for (auto& byte : array)
18 | result.push_back(byte ^ 0x1);
19 |
20 | return result;
21 | }
22 |
--------------------------------------------------------------------------------
/Source/Openers/INosFileOpener.h:
--------------------------------------------------------------------------------
1 | #ifndef INOSFILEOPENER_H
2 | #define INOSFILEOPENER_H
3 | #include
4 | #include
5 | #include "../Ui/OnexTreeItem.h"
6 |
7 | class INosFileOpener
8 | {
9 | protected:
10 | int readNextInt(QFile& file);
11 | QByteArray writeNextInt(int number);
12 | QString neatFileName(QString fileName);
13 | public:
14 | virtual OnexTreeItem* decrypt(QFile& file) = 0;
15 | virtual QByteArray encrypt(OnexTreeItem* item) = 0;
16 | };
17 |
18 | #endif // INOSFILEOPENER_H
19 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # C++ objects and libs
2 |
3 | *.slo
4 | *.lo
5 | *.o
6 | *.a
7 | *.la
8 | *.lai
9 | *.so
10 | *.dll
11 | *.dylib
12 |
13 | # Qt-es
14 |
15 | /.qmake.cache
16 | /.qmake.stash
17 | *.pro.user
18 | *.pro.user.*
19 | *.qbs.user
20 | *.qbs.user.*
21 | *.moc
22 | moc_*.cpp
23 | qrc_*.cpp
24 | ui_*.h
25 | Makefile*
26 | *build-*
27 |
28 | # QtCreator
29 |
30 | *.autosave
31 |
32 | # QtCtreator Qml
33 | *.qmlproject.user
34 | *.qmlproject.user.*
35 |
36 | # QtCtreator CMake
37 | CMakeLists.txt.user*
38 |
39 | # Windows trash
40 | *.db
--------------------------------------------------------------------------------
/Source/Decryptors/NosTextDatFileDecryptor.h:
--------------------------------------------------------------------------------
1 | #ifndef NOSTEXTFILEDECRYPTOR_H
2 | #define NOSTEXTFILEDECRYPTOR_H
3 | #include
4 | #include "INosDecryptor.h"
5 |
6 | class NosTextDatFileDecryptor : public INosDecryptor
7 | {
8 | private:
9 | const std::array cryptoArray;
10 | public:
11 | NosTextDatFileDecryptor();
12 | virtual QByteArray encrypt(QByteArray& array);
13 | virtual QByteArray decrypt(QByteArray& array);
14 | ~NosTextDatFileDecryptor();
15 | };
16 |
17 | #endif // NOSTEXTFILEDECRYPTOR_H
18 |
--------------------------------------------------------------------------------
/Source/Ui/OnexNStcData.h:
--------------------------------------------------------------------------------
1 | #ifndef ONEXNSTCDATA_H
2 | #define ONEXNSTCDATA_H
3 | #include "OnexTreeImage.h"
4 |
5 | class OnexNStcData : public OnexTreeImage
6 | {
7 | public:
8 | OnexNStcData(QString name, QByteArray content, NosZlibOpener* opener, int id, int creationDate, bool compressed);
9 |
10 | virtual QImage getImage() override;
11 | virtual ImageResolution getResolution() override;
12 |
13 | virtual ~OnexNStcData();
14 |
15 | private slots:
16 | virtual void onReplace() override;
17 | };
18 |
19 | #endif // ONEXNSTCDATA_H
20 |
--------------------------------------------------------------------------------
/Source/Ui/OnexNS4BbData.h:
--------------------------------------------------------------------------------
1 | #ifndef ONEXNS4BBDATA_H
2 | #define ONEXNS4BBDATA_H
3 | #include "OnexTreeImage.h"
4 |
5 |
6 | class OnexNS4BbData : public OnexTreeImage
7 | {
8 | public:
9 | OnexNS4BbData(QString name, QByteArray content, NosZlibOpener* opener, int id, int creationDate, bool compressed);
10 |
11 | virtual QImage getImage() override;
12 | virtual ImageResolution getResolution() override;
13 |
14 | virtual ~OnexNS4BbData();
15 |
16 | private slots:
17 | virtual void onReplace() override;
18 | };
19 |
20 | #endif // ONEXNS4BBDATA_H
21 |
--------------------------------------------------------------------------------
/Source/Ui/OnexTreeText.cpp:
--------------------------------------------------------------------------------
1 | #include "OnexTreeText.h"
2 | #include "SingleTextFilePreview.h"
3 |
4 | OnexTreeText::OnexTreeText(QString name, int fileNumber, int isDat, QByteArray content) : OnexTreeItem(name, content)
5 | {
6 | this->fileNmber = fileNumber;
7 | this->isDat = isDat;
8 | }
9 |
10 | QWidget *OnexTreeText::onClicked()
11 | {
12 | SingleTextFilePreview* window = new SingleTextFilePreview(content);
13 | window->setWindowTitle(this->getName());
14 |
15 | return window;
16 | }
17 |
18 | OnexTreeText::~OnexTreeText()
19 | {
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/Source/Ui/SingleTextFilePreview.h:
--------------------------------------------------------------------------------
1 | #ifndef SINGLETEXTFILEPREVIEW_H
2 | #define SINGLETEXTFILEPREVIEW_H
3 |
4 | #include
5 | #include
6 | #include "OnexTreeText.h"
7 |
8 | namespace Ui {
9 | class SingleTextFilePreview;
10 | }
11 |
12 | class SingleTextFilePreview : public QWidget
13 | {
14 | Q_OBJECT
15 |
16 | public:
17 | explicit SingleTextFilePreview(QByteArray &item, QWidget *parent = 0);
18 | ~SingleTextFilePreview();
19 |
20 | private:
21 | Ui::SingleTextFilePreview *ui;
22 | };
23 |
24 | #endif // SINGLETEXTFILEPREVIEW_H
25 |
--------------------------------------------------------------------------------
/Source/Ui/OnexNSipData.h:
--------------------------------------------------------------------------------
1 | #ifndef ONEXNSIPDATA_H
2 | #define ONEXNSIPDATA_H
3 | #include "OnexTreeImage.h"
4 |
5 | class OnexNSipData : public OnexTreeImage
6 | {
7 | private:
8 |
9 | public:
10 | OnexNSipData(QString name, QByteArray content, NosZlibOpener* opener, int id, int creationDate, bool compressed);
11 |
12 | virtual QImage getImage() override;
13 | virtual ImageResolution getResolution() override;
14 | virtual ~OnexNSipData();
15 |
16 | private slots:
17 | virtual void onReplace() override;
18 |
19 |
20 | };
21 |
22 | #endif // ONEXNSIPDATA_H
23 |
--------------------------------------------------------------------------------
/Source/Ui/OnexNStpData.h:
--------------------------------------------------------------------------------
1 | #ifndef ONEXNSTPDATA_H
2 | #define ONEXNSTPDATA_H
3 | #include "OnexTreeImage.h"
4 |
5 | class OnexNStpData : public OnexTreeImage
6 | {
7 | public:
8 | OnexNStpData(QString name, QByteArray content, NosZlibOpener* opener, int id, int creationDate, bool compressed);
9 |
10 | int getFormat();
11 | virtual QImage getImage() override;
12 | virtual ImageResolution getResolution() override;
13 |
14 | virtual ~OnexNStpData();
15 |
16 | private slots:
17 | virtual void onReplace() override;
18 | };
19 |
20 | #endif // ONEXNSTPDATA_H
21 |
--------------------------------------------------------------------------------
/Source/Openers/NosTextOpener.h:
--------------------------------------------------------------------------------
1 | #ifndef NOSTEXTOPENER_H
2 | #define NOSTEXTOPENER_H
3 |
4 | #include
5 | #include
6 | #include "INosFileOpener.h"
7 | #include "../Decryptors/NosTextDatFileDecryptor.h"
8 | #include "../Ui/OnexTreeText.h"
9 |
10 | class NosTextOpener : public QObject, INosFileOpener
11 | {
12 | Q_OBJECT
13 | private:
14 | NosTextDatFileDecryptor datDecryptor;
15 | public:
16 | NosTextOpener();
17 | virtual OnexTreeItem* decrypt(QFile& file);
18 | virtual QByteArray encrypt(OnexTreeItem* item);
19 |
20 | };
21 |
22 | #endif // NOSTEXTOPENER_H
23 |
--------------------------------------------------------------------------------
/Source/Openers/INosFileOpener.cpp:
--------------------------------------------------------------------------------
1 | #include "INosFileOpener.h"
2 |
3 | int INosFileOpener::readNextInt(QFile &file)
4 | {
5 | return qFromLittleEndian(reinterpret_cast(file.read(4).data()));
6 | }
7 |
8 | QByteArray INosFileOpener::writeNextInt(int number)
9 | {
10 | QByteArray writeArray;
11 | writeArray.resize(4);
12 | qToLittleEndian(number, reinterpret_cast(writeArray.data()));
13 | return writeArray;
14 | }
15 |
16 | QString INosFileOpener::neatFileName(QString fileName)
17 | {
18 | QStringList list = fileName.split("/");
19 |
20 | if (list.empty())
21 | return fileName;
22 |
23 | return list.back();
24 | }
25 |
--------------------------------------------------------------------------------
/Source/Ui/OnexTreeZlibItem.h:
--------------------------------------------------------------------------------
1 | #ifndef ONEXTREEZLIBITEM_H
2 | #define ONEXTREEZLIBITEM_H
3 | #include "OnexTreeItem.h"
4 | #include "../Openers/NosZlibOpener.h"
5 |
6 | class OnexTreeZlibItem : public OnexTreeItem
7 | {
8 | protected:
9 | int id;
10 | int creationDate;
11 | bool compressed;
12 | NosZlibOpener* opener;
13 | public:
14 | OnexTreeZlibItem(QString name, QByteArray content, NosZlibOpener* opener, int id, int creationDate, bool compressed);
15 | virtual QWidget *onClicked() override;
16 | virtual void onExporAsOriginal() override;
17 | int getId();
18 | int getCreationDate();
19 | bool isCompressed();
20 | virtual ~OnexTreeZlibItem();
21 | };
22 |
23 | #endif // ONEXTREEZLIBITEM_H
24 |
--------------------------------------------------------------------------------
/Source/Ui/SingleTextFilePreview.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | SingleTextFilePreview
4 |
5 |
6 |
7 | 0
8 | 0
9 | 531
10 | 421
11 |
12 |
13 |
14 | Text
15 |
16 |
17 | -
18 |
19 |
20 | true
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/Source/Ui/SingleImagePreview.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | SingleImagePreview
4 |
5 |
6 |
7 | 0
8 | 0
9 | 400
10 | 300
11 |
12 |
13 |
14 | Image
15 |
16 |
17 | -
18 |
19 |
20 | TextLabel
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/README.MD:
--------------------------------------------------------------------------------
1 | # OnexExplorer #
2 | OnexExplorer is an open-source tool for unpacking and repacking .NOS data files from game called NosTale. It can open almost all .NOS files and show the data stored in them. Our software works on Qt 5.5+
3 |
4 | [
](https://discord.gg/VARTAuY)
5 |
6 | ## Currently supported files ##
7 | - NSipData
8 | - NStpData, NStpeData, NStpuData
9 | - all lang (txt&dat, lst is NOT supported yet)
10 | - NStcData
11 | - NS4BbData
12 | Other files will be added in future updates.
13 |
14 | ## License ##
15 | Our project is based on **Boost Software License**:
16 | > [LICENSE](https://github.com/OnexTale/OnexExplorer/blob/master/LICENSE)
17 |
18 | ## Installation ##
19 | 1. Compile given sourcecode using Qt 5.5+
20 | 2. Move required Qt DLL's to EXE's location
21 | 3. Run the program
22 |
--------------------------------------------------------------------------------
/Source/NosEnumTypes.h:
--------------------------------------------------------------------------------
1 | #ifndef NOSENUMTYPES_H
2 | #define NOSENUMTYPES_H
3 |
4 | #define PCHPKG 1
5 | #define NStuData 2
6 | #define NStkData 3
7 | #define NStcData 5
8 | #define NStgData 6
9 | #define NStpData 7
10 | #define NStsData 9
11 | #define NStgeData 10
12 | #define NStpeData 11
13 | #define NStpuData 12
14 | #define NSpcData 13
15 | #define NSppData 14
16 | #define NSpmData 15
17 | #define NSmcData 16
18 | #define NSmpData 17
19 | #define NSedData 20
20 | #define NSemData 21
21 | #define NSesData 22
22 | #define NSeffData 23
23 | #define NSipData 24
24 | #define NSgrdData 26
25 |
26 | #define NS4BbData 101 //temporary
27 | #define NSipData2006 103
28 |
29 | /*
30 | #define NSpnData
31 | #define NSmnData
32 |
33 | #define PCHPKG_DATA
34 |
35 | #define NScliData
36 | #define NSetcData
37 | #define NSlangData
38 | #define NSgtdData
39 | */
40 |
41 |
42 | #endif // NOSENUMTYPES_H
43 |
--------------------------------------------------------------------------------
/Source/Ui/FileInfo.cpp:
--------------------------------------------------------------------------------
1 | #include "FileInfo.h"
2 | #include "ui_FileInfo.h"
3 |
4 | FileInfo::FileInfo(OnexTreeItem *item, QWidget *parent) :
5 | QDialog(parent, Qt::WindowCloseButtonHint),
6 | ui(new Ui::FileInfo)
7 | {
8 | ui->setupUi(this);
9 |
10 | /*
11 | ui->name->setText(item->getName());
12 | ui->header->setText(QString::number(item->getHeaderValue()));
13 | ui->sizeb->setText(QString::number(item->getContent().size()));
14 | int timestamp = item->getTimestamp();
15 | int year = (timestamp & 0xFFFF0000) >> 0x10;
16 | int month = (timestamp & 0xFF00) >> 0x08;
17 | int day = timestamp & 0xFF;
18 |
19 | QString date = QString("%1/%2/%3").arg(day, 2, 16, QChar('0')).arg(month, 2, 16, QChar('0')).arg(year, 4, 16, QChar('0'));
20 | ui->date->setText(date);
21 | */
22 | }
23 |
24 | FileInfo::~FileInfo()
25 | {
26 | delete ui;
27 | }
28 |
--------------------------------------------------------------------------------
/Source/Ui/OnexTreeImage.h:
--------------------------------------------------------------------------------
1 | #ifndef ONEXTREEIMAGE_H
2 | #define ONEXTREEIMAGE_H
3 | #include "OnexTreeZlibItem.h"
4 | #include "SingleImagePreview.h"
5 |
6 | struct ImageResolution
7 | {
8 | int x;
9 | int y;
10 | };
11 |
12 | class OnexTreeImage : public OnexTreeZlibItem
13 | {
14 | Q_OBJECT
15 | protected:
16 | bool hasGoodResolution(int x, int y);
17 | QImage importQImageFromSelectedUserFile();
18 | public:
19 | OnexTreeImage(QString name, QByteArray content, NosZlibOpener* opener, int id, int creationDate, bool compressed);
20 |
21 | virtual QWidget *onClicked() override;
22 | virtual QImage getImage() = 0;
23 | virtual ImageResolution getResolution() = 0;
24 |
25 | private slots:
26 | virtual void onExportAll();
27 | virtual void onExportSingle();
28 |
29 | signals:
30 | void replaceSignal(QImage newImage);
31 |
32 | };
33 |
34 | #endif // ONEXTREEIMAGE_H
35 |
--------------------------------------------------------------------------------
/Source/Openers/NosZlibOpener.h:
--------------------------------------------------------------------------------
1 | #ifndef NOSZLIBOPENER_H
2 | #define NOSZLIBOPENER_H
3 | #include "INosFileOpener.h"
4 | #include "../NosEnumTypes.h"
5 | #include "../Decryptors/NosZlibDecryptor.h"
6 | #include "../ImageConverter.h"
7 | #include
8 | #include
9 | class NosZlibOpener : public INosFileOpener
10 | {
11 | private:
12 | static const int NOS_HEADER_SIZE = 0x10;
13 | NosZlibDecryptor decryptor;
14 | ImageConverter imageConverter;
15 | QByteArray toBigEndian(qint32 value);
16 | int getNTHeaderNumber(QByteArray& array);
17 |
18 | OnexTreeItem *createItemFromHeader(int header, QString name, QByteArray &array, int fileId = 0, int creationDate = 0, bool compressed = 0);
19 | public:
20 | NosZlibOpener();
21 | ImageConverter &getImageConverter();
22 | virtual OnexTreeItem* decrypt(QFile& file);
23 | virtual QByteArray encrypt(OnexTreeItem* item);
24 | };
25 |
26 | #endif // NOSZLIBOPENER_H
27 |
--------------------------------------------------------------------------------
/Source/Ui/SingleImagePreview.h:
--------------------------------------------------------------------------------
1 | #ifndef SINGLEIMAGEPREVIEW_H
2 | #define SINGLEIMAGEPREVIEW_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include "../ImageConverter.h"
12 | #include "../NosEnumTypes.h"
13 |
14 | namespace Ui {
15 | class SingleImagePreview;
16 | }
17 |
18 | class SingleImagePreview : public QWidget
19 | {
20 | Q_OBJECT
21 |
22 | public:
23 | explicit SingleImagePreview(QImage image, QWidget *parent = 0);
24 | ~SingleImagePreview();
25 | private:
26 | Ui::SingleImagePreview *ui;
27 | ImageConverter converter;
28 | qint16 byteArrayToShort(QByteArray array);
29 | void showWarningMessage();
30 | private slots:
31 | void showCustomMenu(const QPoint &pos);
32 | void exportImage();
33 | void onReplaced(QImage newImage);
34 | };
35 |
36 | #endif // SINGLEIMAGEPREVIEW_H
37 |
--------------------------------------------------------------------------------
/Source/Openers/NosTextOpener.cpp:
--------------------------------------------------------------------------------
1 | #include "NosTextOpener.h"
2 |
3 | NosTextOpener::NosTextOpener()
4 | {
5 |
6 | }
7 |
8 | OnexTreeItem *NosTextOpener::decrypt(QFile &file)
9 | {
10 | file.seek(0);
11 |
12 | OnexTreeText *item = new OnexTreeText(neatFileName(file.fileName()));
13 | int fileAmount = readNextInt(file);
14 |
15 | for (int i = 0; i < fileAmount; ++i)
16 | {
17 | int fileNumber = readNextInt(file);
18 | int stringNameSize = readNextInt(file);
19 | QString stringName = file.read(stringNameSize);
20 | int isDat = readNextInt(file);
21 | int fileSize = readNextInt(file);
22 | QByteArray fileContent = file.read(fileSize);
23 |
24 | QByteArray decryptedArray = datDecryptor.decrypt(fileContent);
25 |
26 | item->addChild(new OnexTreeText(stringName, fileNumber, isDat, decryptedArray));
27 | }
28 |
29 | return item;
30 | }
31 |
32 | QByteArray NosTextOpener::encrypt(OnexTreeItem *item)
33 | {
34 | return QByteArray();
35 | }
36 |
--------------------------------------------------------------------------------
/Source/ImageConverter.h:
--------------------------------------------------------------------------------
1 | #ifndef IMAGECONVERTER_H
2 | #define IMAGECONVERTER_H
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | class ImageConverter
9 | {
10 | private:
11 | QMap colors;
12 | public:
13 | QImage convertGBAR4444(QByteArray& array, int width, int height, int startByte = 0);
14 | QImage convertBGRA8888(QByteArray& array, int width, int height, int startByte = 0);
15 | QImage convertARGB555(QByteArray& array, int width, int height, int startByte = 0);
16 | QImage convertNSTC(QByteArray& array, int width, int height, int startByte = 0);
17 | QImage convertBGRA8888_INTERLACED(QByteArray& array, int width, int height, int startByte = 0);
18 | QImage convertBARG4444(QByteArray& array, int width, int height, int startByte = 0);
19 | QByteArray toGBAR4444(QImage& image);
20 | QByteArray toNSTC(QImage& image);
21 | QByteArray toBGRA8888(QImage& image);
22 | QByteArray toARGB555(QImage& image);
23 | QByteArray toBGRA8888_INTERLACED(QImage& image);
24 | QByteArray toBARG4444(QImage& image);
25 | ImageConverter();
26 | };
27 |
28 | #endif // IMAGECONVERTER_H
29 |
--------------------------------------------------------------------------------
/Source/Ui/OnexNSipData.cpp:
--------------------------------------------------------------------------------
1 | #include "OnexNSipData.h"
2 |
3 | OnexNSipData::OnexNSipData(QString name, QByteArray content, NosZlibOpener *opener, int id, int creationDate, bool compressed) :
4 | OnexTreeImage(name, content, opener, id, creationDate, compressed)
5 | {
6 |
7 | }
8 |
9 | QImage OnexNSipData::getImage()
10 | {
11 | ImageResolution resolution = this->getResolution();
12 |
13 | return opener->getImageConverter().convertGBAR4444(content, resolution.x, resolution.y, 13);
14 | }
15 |
16 | ImageResolution OnexNSipData::getResolution()
17 | {
18 | int x = fromLittleEndianToShort(content.mid(1, 2));
19 | int y = fromLittleEndianToShort(content.mid(3, 2));
20 |
21 | return ImageResolution{x, y};
22 | }
23 |
24 | void OnexNSipData::onReplace()
25 | {
26 | QImage image = importQImageFromSelectedUserFile();
27 | if (image.isNull())
28 | return;
29 |
30 | if (!hasGoodResolution(image.width(), image.height()))
31 | return;
32 |
33 | QByteArray newContent;
34 | newContent.push_back(content.mid(0, 13));
35 | newContent.push_back(opener->getImageConverter().toGBAR4444(image));
36 |
37 | content = newContent;
38 |
39 | emit OnexTreeImage::replaceSignal(this->getImage());
40 | }
41 |
42 | OnexNSipData::~OnexNSipData()
43 | {
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/Source/Ui/OnexTreeItem.h:
--------------------------------------------------------------------------------
1 | #ifndef ONEXTREEITEM_H
2 | #define ONEXTREEITEM_H
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | class OnexTreeItem : public QObject, public QTreeWidgetItem
11 | {
12 | Q_OBJECT
13 | protected:
14 | QByteArray content;
15 | QString name;
16 |
17 | QString getSelectedDirectory();
18 | QString getSaveDirectory(QString name, QString filter);
19 | QString getOpenDirectory(QString filter);
20 | QMessageBox getMsgBox(QString title, QString message, QMessageBox::Icon icon);
21 | public:
22 | OnexTreeItem(QString name, QByteArray content = QByteArray());
23 | QByteArray getContent();
24 | bool hasParent();
25 | short fromLittleEndianToShort(QByteArray array);
26 | int getContentSize();
27 |
28 | virtual QString getName();
29 | virtual QMenu* getContextMenu();
30 | virtual QWidget *onClicked() = 0;
31 | virtual ~OnexTreeItem();
32 |
33 | public slots:
34 | virtual void onExportAll();
35 | virtual void onExportSingle();
36 | virtual void onExporSingleRaw();
37 | virtual void onExporAsOriginal();
38 | virtual void onReplace();
39 | virtual void actionClose();
40 | };
41 |
42 | #endif // ONEXTREEITEM_H
43 |
--------------------------------------------------------------------------------
/Source/Ui/OnexNS4BbData.cpp:
--------------------------------------------------------------------------------
1 | #include "OnexNS4BbData.h"
2 |
3 | OnexNS4BbData::OnexNS4BbData(QString name, QByteArray content, NosZlibOpener *opener, int id, int creationDate, bool compressed) :
4 | OnexTreeImage(name, content, opener, id, creationDate, compressed)
5 | {
6 |
7 | }
8 |
9 | QImage OnexNS4BbData::getImage()
10 | {
11 | ImageResolution resolution = this->getResolution();
12 |
13 | return opener->getImageConverter().convertBGRA8888_INTERLACED(content, resolution.x, resolution.y, 4);
14 | }
15 |
16 | ImageResolution OnexNS4BbData::getResolution()
17 | {
18 | int x = fromLittleEndianToShort(content.mid(0, 2));
19 | int y = fromLittleEndianToShort(content.mid(2, 2));
20 |
21 | return ImageResolution{x, y};
22 | }
23 |
24 | void OnexNS4BbData::onReplace()
25 | {
26 | QImage image = importQImageFromSelectedUserFile();
27 | if (image.isNull())
28 | return;
29 |
30 | if (!hasGoodResolution(image.width(), image.height()))
31 | return;
32 |
33 | QByteArray newContent;
34 | newContent.push_back(content.mid(0, 4));
35 | newContent.push_back(opener->getImageConverter().toBGRA8888_INTERLACED(image));
36 |
37 | content = newContent;
38 |
39 | emit OnexTreeImage::replaceSignal(this->getImage());
40 | }
41 |
42 | OnexNS4BbData::~OnexNS4BbData()
43 | {
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Boost Software License - Version 1.0 - August 17th, 2003
2 |
3 | Permission is hereby granted, free of charge, to any person or organization
4 | obtaining a copy of the software and accompanying documentation covered by
5 | this license (the "Software") to use, reproduce, display, distribute,
6 | execute, and transmit the Software, and to prepare derivative works of the
7 | Software, and to permit third-parties to whom the Software is furnished to
8 | do so, all subject to the following:
9 |
10 | The copyright notices in the Software and this entire statement, including
11 | the above license grant, this restriction and the following disclaimer,
12 | must be included in all copies of the Software, in whole or in part, and
13 | all derivative works of the Software, unless such copies or derivative
14 | works are solely in the form of machine-executable object code generated by
15 | a source language processor.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
20 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
21 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
22 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 | DEALINGS IN THE SOFTWARE.
24 |
--------------------------------------------------------------------------------
/Source/Ui/OnexNStcData.cpp:
--------------------------------------------------------------------------------
1 | #include "OnexNStcData.h"
2 |
3 | OnexNStcData::OnexNStcData(QString name, QByteArray content, NosZlibOpener *opener, int id, int creationDate, bool compressed) :
4 | OnexTreeImage(name, content, opener, id, creationDate, compressed)
5 | {
6 |
7 | }
8 |
9 | QImage OnexNStcData::getImage()
10 | {
11 | ImageResolution resolution = this->getResolution();
12 |
13 | return opener->getImageConverter().convertNSTC(content, resolution.x, resolution.y, 4);
14 | }
15 |
16 | ImageResolution OnexNStcData::getResolution()
17 | {
18 | int x = fromLittleEndianToShort(content.mid(0, 2));
19 | int y = fromLittleEndianToShort(content.mid(2, 2));
20 |
21 | return ImageResolution{x, y};
22 | }
23 |
24 | void OnexNStcData::onReplace()
25 | {
26 | QImage image = importQImageFromSelectedUserFile();
27 | if (image.isNull())
28 | return;
29 |
30 | image = image.scaled(image.width()/2, image.height()/2);
31 |
32 | if (!hasGoodResolution(image.width(), image.height()))
33 | {
34 | qDebug() << "NStc wrong resolution";
35 | return;
36 | }
37 |
38 | QByteArray newContent;
39 | newContent.push_back(content.mid(0, 4));
40 | newContent.push_back(opener->getImageConverter().toNSTC(image));
41 |
42 | content = newContent;
43 |
44 | emit OnexTreeImage::replaceSignal(this->getImage());
45 | }
46 |
47 | OnexNStcData::~OnexNStcData()
48 | {
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/Source/Ui/OnexTreeZlibItem.cpp:
--------------------------------------------------------------------------------
1 | #include "OnexTreeZlibItem.h"
2 |
3 | OnexTreeZlibItem::OnexTreeZlibItem(QString name, QByteArray content, NosZlibOpener *opener, int id, int creationDate, bool compressed) :
4 | OnexTreeItem(name, content),
5 | id(id),
6 | creationDate(creationDate),
7 | compressed(compressed),
8 | opener(opener)
9 | {
10 |
11 | }
12 |
13 | QWidget *OnexTreeZlibItem::onClicked()
14 | {
15 | return nullptr;
16 | }
17 |
18 | void OnexTreeZlibItem::onExporAsOriginal()
19 | {
20 | QString fileName = getSaveDirectory(this->getName(), "NOS Archive (*.NOS)");
21 |
22 | if (fileName.isEmpty())
23 | return;
24 |
25 | if (!fileName.endsWith(".NOS"))
26 | fileName += ".NOS";
27 |
28 | QFile file(fileName);
29 | if (!file.open(QIODevice::WriteOnly))
30 | {
31 | QMessageBox::critical(NULL, "Woops", "Couldn't open this file for writing");
32 | return;
33 | }
34 |
35 | if (file.write(opener->encrypt(this)) == -1)
36 | {
37 | QMessageBox::critical(NULL, "Woops", "Couldn't write to this file");
38 | return;
39 | }
40 |
41 | QMessageBox::information(NULL, "Yeah", "File exported into .NOS");
42 |
43 | }
44 |
45 | int OnexTreeZlibItem::getId()
46 | {
47 | return id;
48 | }
49 |
50 | int OnexTreeZlibItem::getCreationDate()
51 | {
52 | return creationDate;
53 | }
54 |
55 | bool OnexTreeZlibItem::isCompressed()
56 | {
57 | return compressed;
58 | }
59 |
60 | OnexTreeZlibItem::~OnexTreeZlibItem()
61 | {
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/Source/Ui/SingleImagePreview.cpp:
--------------------------------------------------------------------------------
1 | #include "SingleImagePreview.h"
2 | #include "ui_SingleImagePreview.h"
3 |
4 | SingleImagePreview::SingleImagePreview(QImage image, QWidget *parent) :
5 | QWidget(parent),
6 | ui(new Ui::SingleImagePreview)
7 | {
8 | ui->setupUi(this);
9 | ui->imgContent->setContextMenuPolicy(Qt::CustomContextMenu);
10 | connect(ui->imgContent, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showCustomMenu(QPoint)));
11 |
12 | ui->imgContent->setPixmap(QPixmap::fromImage(image));
13 |
14 | }
15 |
16 | SingleImagePreview::~SingleImagePreview()
17 | {
18 | delete ui;
19 | }
20 |
21 | void SingleImagePreview::showCustomMenu(const QPoint &pos)
22 | {
23 | Q_UNUSED(pos);
24 |
25 | QMenu contextMenu(this);
26 |
27 | QAction exportAction("Export", this);
28 | connect(&exportAction, SIGNAL(triggered()), this, SLOT(exportImage()));
29 | contextMenu.addAction(&exportAction);
30 |
31 | contextMenu.exec(QCursor::pos());
32 | }
33 |
34 | void SingleImagePreview::exportImage()
35 | {
36 | QString fileName = QFileDialog::getSaveFileName(0, tr("Save as..."), "", tr("PNG Image (*.png)"));
37 |
38 | if (fileName.isEmpty())
39 | return;
40 |
41 | if (!fileName.endsWith(".png"))
42 | fileName += ".png";
43 |
44 | if (ui->imgContent->pixmap()->toImage().save(fileName, "PNG", 100))
45 | QMessageBox::information(NULL, "Yeah", "Image exported");
46 | else
47 | QMessageBox::critical(NULL, "Woops", "Couldn't export that image");
48 |
49 | }
50 |
51 | void SingleImagePreview::onReplaced(QImage newImage)
52 | {
53 | ui->imgContent->setPixmap(QPixmap::fromImage(newImage));
54 | }
55 |
56 |
--------------------------------------------------------------------------------
/Source/MainWindow.h:
--------------------------------------------------------------------------------
1 | #ifndef MAINWINDOW_H
2 | #define MAINWINDOW_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include "Ui/SingleTextFilePreview.h"
10 | #include "Ui/FileInfo.h"
11 | #include "Openers/NosTextOpener.h"
12 | #include "Openers/NosZlibOpener.h"
13 | #include "Ui/SingleImagePreview.h"
14 | namespace Ui {
15 | class MainWindow;
16 | }
17 |
18 | class MainWindow : public QMainWindow
19 | {
20 | Q_OBJECT
21 |
22 | public:
23 | explicit MainWindow(QWidget *parent = 0);
24 | ~MainWindow();
25 |
26 | private slots:
27 | void onCustomMenuShow(const QPoint& point);
28 | void clearMenu();
29 | void on_actionOpen_triggered();
30 |
31 | void on_treeWidget_itemDoubleClicked(QTreeWidgetItem *treeItem, int column);
32 |
33 | void on_actionClose_selected_triggered();
34 |
35 | void on_actionExit_triggered();
36 |
37 | void on_actionClose_all_triggered();
38 |
39 | void on_actionOptions_triggered();
40 |
41 | void on_actionReplace_triggered();
42 |
43 | void on_actionImport_triggered();
44 |
45 | void on_actionExport_triggered();
46 |
47 | void on_actionAbout_triggered();
48 |
49 | void on_actionSave_as_triggered();
50 |
51 | private:
52 | Ui::MainWindow *ui;
53 | NosTextOpener textOpener;
54 | NosZlibOpener zlibOpener;
55 | QMenu* contextMenu = nullptr;
56 |
57 | void openFile(QString path);
58 | void handleOpenResults(OnexTreeItem* item);
59 | bool hasValidHeader(QFile& file);
60 |
61 | virtual void dropEvent(QDropEvent *e) override;
62 | virtual void dragEnterEvent(QDragEnterEvent *e) override;
63 | };
64 |
65 | #endif // MAINWINDOW_H
66 |
--------------------------------------------------------------------------------
/Source/Decryptors/NosTextDatFileDecryptor.cpp:
--------------------------------------------------------------------------------
1 | #include "NosTextDatFileDecryptor.h"
2 |
3 | NosTextDatFileDecryptor::NosTextDatFileDecryptor() :
4 | cryptoArray({ 0x00, 0x20, 0x2D, 0x2E, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x0A, 0x00 })
5 | {
6 |
7 | }
8 |
9 | QByteArray NosTextDatFileDecryptor::encrypt(QByteArray &array)
10 | {
11 | return QByteArray();
12 | }
13 |
14 | QByteArray NosTextDatFileDecryptor::decrypt(QByteArray &array)
15 | {
16 | QByteArray decryptedFile;
17 | int currIndex = 0;
18 | while (currIndex < array.size())
19 | {
20 | unsigned char currentByte = array.at(currIndex);
21 | currIndex++;
22 | if (currentByte == 0xFF)
23 | {
24 | decryptedFile.push_back(0xD);
25 | continue;
26 | }
27 |
28 | int validate = currentByte & 0x7F;
29 |
30 | if (currentByte & 0x80)
31 | {
32 | for (; validate > 0; validate -= 2)
33 | {
34 | if (currIndex >= array.size())
35 | break;
36 |
37 | currentByte = array.at(currIndex);
38 | currIndex++;
39 |
40 | int firstByte = cryptoArray.at((currentByte & 0xF0) >> 4);
41 | decryptedFile.push_back(firstByte);
42 |
43 | if (validate <= 1)
44 | break;
45 | int secondByte = cryptoArray.at(currentByte & 0xF);
46 |
47 | if (!secondByte)
48 | break;
49 |
50 | decryptedFile.push_back(secondByte);
51 | }
52 | }
53 | else
54 | {
55 | for (; validate > 0; --validate)
56 | {
57 | if (currIndex >= array.size())
58 | break;
59 |
60 | currentByte = array.at(currIndex);
61 | currIndex++;
62 |
63 | decryptedFile.push_back(currentByte ^ 0x33);
64 | }
65 | }
66 | }
67 |
68 | return decryptedFile;
69 | }
70 |
71 | NosTextDatFileDecryptor::~NosTextDatFileDecryptor()
72 | {
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/Source/Ui/OnexNStpData.cpp:
--------------------------------------------------------------------------------
1 | #include "OnexNStpData.h"
2 |
3 | OnexNStpData::OnexNStpData(QString name, QByteArray content, NosZlibOpener *opener, int id, int creationDate, bool compressed) :
4 | OnexTreeImage(name, content, opener, id, creationDate, compressed)
5 | {
6 |
7 | }
8 |
9 | int OnexNStpData::getFormat()
10 | {
11 | return content.at(4);
12 | }
13 |
14 | QImage OnexNStpData::getImage()
15 | {
16 | ImageResolution resolution = this->getResolution();
17 |
18 | int format = this->getFormat();
19 |
20 | if (format == 0)
21 | return opener->getImageConverter().convertGBAR4444(content, resolution.x, resolution.y, 8);
22 | else if (format == 1)
23 | return opener->getImageConverter().convertARGB555(content, resolution.x, resolution.y, 8);
24 | else if (format == 2)
25 | return opener->getImageConverter().convertBGRA8888(content, resolution.x, resolution.y, 8);
26 | else
27 | {
28 | qDebug().noquote().nospace() << "Unknown format! (" << format << ")";
29 | return QImage(resolution.x, resolution.y, QImage::Format_Invalid);
30 | }
31 | }
32 |
33 | ImageResolution OnexNStpData::getResolution()
34 | {
35 | int x = fromLittleEndianToShort(content.mid(0, 2));
36 | int y = fromLittleEndianToShort(content.mid(2, 2));
37 |
38 | return ImageResolution{x, y};
39 | }
40 |
41 | void OnexNStpData::onReplace()
42 | {
43 | QImage image = importQImageFromSelectedUserFile();
44 | if (image.isNull())
45 | return;
46 |
47 | if (!hasGoodResolution(image.width(), image.height()))
48 | return;
49 |
50 | int format = this->getFormat();
51 |
52 | if (format < 0 || format > 2)
53 | return;
54 |
55 | QByteArray newContent;
56 | newContent.push_back(content.mid(0, 8));
57 | if (format == 0)
58 | newContent.push_back(opener->getImageConverter().toGBAR4444(image));
59 | else if (format == 1)
60 | newContent.push_back(opener->getImageConverter().toARGB555(image));
61 | else if (format == 2)
62 | newContent.push_back(opener->getImageConverter().toBGRA8888(image));
63 |
64 | content = newContent;
65 |
66 | emit OnexTreeImage::replaceSignal(this->getImage());
67 | }
68 |
69 | OnexNStpData::~OnexNStpData()
70 | {
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/Source/Ui/OnexTreeImage.cpp:
--------------------------------------------------------------------------------
1 | #include "OnexTreeImage.h"
2 |
3 | OnexTreeImage::OnexTreeImage(QString name, QByteArray content, NosZlibOpener *opener, int id, int creationDate, bool compressed) :
4 | OnexTreeZlibItem(name, content, opener, id, creationDate, compressed)
5 | {
6 |
7 | }
8 |
9 | bool OnexTreeImage::hasGoodResolution(int x, int y)
10 | {
11 | ImageResolution currentResolution = this->getResolution();
12 | return (x == currentResolution.x && y == currentResolution.y);
13 | }
14 |
15 | QImage OnexTreeImage::importQImageFromSelectedUserFile()
16 | {
17 | QString fileName = getOpenDirectory("PNG Image (*.png)");
18 | if (fileName.isEmpty())
19 | return QImage();
20 |
21 | QFile file(fileName);
22 | file.open(QIODevice::ReadOnly);
23 | QImage image = QImage::fromData(file.readAll());
24 | file.close();
25 |
26 | return image;
27 | }
28 |
29 | QWidget *OnexTreeImage::onClicked()
30 | {
31 | SingleImagePreview* imagePreview = new SingleImagePreview(this->getImage());
32 | imagePreview->setWindowTitle(this->getName());
33 |
34 | connect(this, SIGNAL(replaceSignal(QImage)), imagePreview, SLOT(onReplaced(QImage)));
35 |
36 | return imagePreview;
37 | }
38 |
39 | void OnexTreeImage::onExportAll()
40 | {
41 | QString directory = this->getSelectedDirectory();
42 | if (directory.isEmpty())
43 | return;
44 |
45 | int count = 0;
46 | for (int i = 0; i != this->childCount(); ++i)
47 | {
48 | OnexTreeImage* item = static_cast(this->child(i));
49 | if (item->getImage().save(directory + item->getName() + ".png", "PNG", 100))
50 | count++;
51 | }
52 | QString text = "Saved " + QString::number(count) + " of " + QString::number(this->childCount()) + " files.";
53 | QMessageBox msgBox(QMessageBox::Information, tr("End of operation"), text);
54 | msgBox.exec();
55 | }
56 |
57 | void OnexTreeImage::onExportSingle()
58 | {
59 | QString fileName = getSaveDirectory(this->getName(), "PNG Image (*.png)");
60 |
61 | if (fileName.isEmpty())
62 | return;
63 |
64 | if (!fileName.endsWith(".png"))
65 | fileName += ".png";
66 |
67 | if (this->getImage().save(fileName, "PNG", 100))
68 | QMessageBox::information(NULL, "Yeah", "Image exported");
69 | else
70 | QMessageBox::critical(NULL, "Woops", "Couldn't export that image");
71 | }
72 |
--------------------------------------------------------------------------------
/Source/Ui/FileInfo.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | FileInfo
4 |
5 |
6 |
7 | 0
8 | 0
9 | 200
10 | 116
11 |
12 |
13 |
14 |
15 | 200
16 | 116
17 |
18 |
19 |
20 |
21 | 16777215
22 | 116
23 |
24 |
25 |
26 | Selected item info
27 |
28 |
29 |
30 | :/resources/oxe_icon_trans.ico:/resources/oxe_icon_trans.ico
31 |
32 |
33 | 1.000000000000000
34 |
35 |
36 | -
37 |
38 |
39 |
40 |
41 |
42 | true
43 |
44 |
45 |
46 | -
47 |
48 |
49 | true
50 |
51 |
52 |
53 | -
54 |
55 |
56 | Size (bytes)
57 |
58 |
59 |
60 | -
61 |
62 |
63 | true
64 |
65 |
66 |
67 | -
68 |
69 |
70 | true
71 |
72 |
73 |
74 | -
75 |
76 |
77 | Name
78 |
79 |
80 |
81 | -
82 |
83 |
84 | Header
85 |
86 |
87 |
88 | -
89 |
90 |
91 | Date
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/OnexExplorer.pro:
--------------------------------------------------------------------------------
1 | #-------------------------------------------------
2 | #
3 | # Project created by QtCreator 2017-03-12T15:48:27
4 | #
5 | #-------------------------------------------------
6 |
7 | QT += core gui
8 |
9 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
10 |
11 | TARGET = OnexExplorer
12 | TEMPLATE = app
13 |
14 | # The following define makes your compiler emit warnings if you use
15 | # any feature of Qt which as been marked as deprecated (the exact warnings
16 | # depend on your compiler). Please consult the documentation of the
17 | # deprecated API in order to know how to port your code away from it.
18 | DEFINES += QT_DEPRECATED_WARNINGS
19 |
20 | # You can also make your code fail to compile if you use deprecated APIs.
21 | # In order to do so, uncomment the following line.
22 | # You can also select to disable deprecated APIs only up to a certain version of Qt.
23 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
24 |
25 |
26 | SOURCES += \
27 | Source/main.cpp \
28 | Source/Decryptors/NosTextDatFileDecryptor.cpp \
29 | Source/Openers/NosTextOpener.cpp \
30 | Source/MainWindow.cpp \
31 | Source/Decryptors/NosTextOthersFileDecryptor.cpp \
32 | Source/Openers/INosFileOpener.cpp \
33 | Source/Ui/OnexTreeItem.cpp \
34 | Source/Ui/SingleTextFilePreview.cpp \
35 | Source/Decryptors/NosZlibDecryptor.cpp \
36 | Source/Openers/NosZlibOpener.cpp \
37 | Source/Ui/SingleImagePreview.cpp \
38 | Source/ImageConverter.cpp \
39 | Source/Ui/FileInfo.cpp \
40 | Source/Ui/OnexTreeImage.cpp \
41 | Source/Ui/OnexTreeText.cpp \
42 | Source/Ui/OnexTreeZlibItem.cpp \
43 | Source/Ui/OnexNSipData.cpp \
44 | Source/Ui/OnexNS4BbData.cpp \
45 | Source/Ui/OnexNStcData.cpp \
46 | Source/Ui/OnexNStpData.cpp
47 |
48 | HEADERS += \
49 | Source/Decryptors/NosTextDatFileDecryptor.h \
50 | Source/Decryptors/INosDecryptor.h \
51 | Source/Openers/INosFileOpener.h \
52 | Source/Openers/NosTextOpener.h \
53 | Source/MainWindow.h \
54 | Source/Decryptors/NosTextOthersFileDecryptor.h \
55 | Source/Ui/OnexTreeItem.h \
56 | Source/Ui/OnexTreeItem.h \
57 | Source/Ui/SingleTextFilePreview.h \
58 | Source/Decryptors/NosZlibDecryptor.h \
59 | Source/Openers/NosZlibOpener.h \
60 | Source/NosEnumTypes.h \
61 | Source/Ui/SingleImagePreview.h \
62 | Source/ImageConverter.h \
63 | Source/Ui/FileInfo.h \
64 | Source/Ui/OnexTreeImage.h \
65 | Source/Ui/OnexTreeText.h \
66 | Source/Ui/OnexTreeZlibItem.h \
67 | Source/Ui/OnexNSipData.h \
68 | Source/Ui/OnexNS4BbData.h \
69 | Source/Ui/OnexNStcData.h \
70 | Source/Ui/OnexNStpData.h
71 |
72 | FORMS += \
73 | Source/mainwindow.ui \
74 | Source/Ui/SingleTextFilePreview.ui \
75 | Source/Ui/SingleImagePreview.ui \
76 | Source/Ui/FileInfo.ui
77 |
78 | DISTFILES +=
79 |
80 | RESOURCES += \
81 | resources.qrc
82 |
83 | RC_ICONS = ./resources/oxe_icon_trans.ico
84 |
--------------------------------------------------------------------------------
/Source/Ui/OnexTreeItem.cpp:
--------------------------------------------------------------------------------
1 | #include "OnexTreeItem.h"
2 |
3 | OnexTreeItem::OnexTreeItem(QString name, QByteArray content)
4 | {
5 | this->name = name;
6 | this->content = content;
7 | this->setText(0, name);
8 | }
9 |
10 | QString OnexTreeItem::getSelectedDirectory()
11 | {
12 | QString dir = QFileDialog::getExistingDirectory(0, tr("Select Directory"));
13 | if (dir.isEmpty())
14 | return dir;
15 |
16 | return dir + "/";
17 | }
18 |
19 | QString OnexTreeItem::getSaveDirectory(QString name, QString filter)
20 | {
21 | return QFileDialog::getSaveFileName(0, tr("Save as..."), name, filter);
22 | }
23 |
24 | QString OnexTreeItem::getOpenDirectory(QString filter)
25 | {
26 | return QFileDialog::getOpenFileName(0, tr("Open..."), "", filter);
27 | }
28 |
29 | QByteArray OnexTreeItem::getContent()
30 | {
31 | return content;
32 | }
33 |
34 | bool OnexTreeItem::hasParent()
35 | {
36 | return QTreeWidgetItem::parent();
37 | }
38 |
39 | short OnexTreeItem::fromLittleEndianToShort(QByteArray array)
40 | {
41 | return qFromLittleEndian(reinterpret_cast(array.data()));
42 | }
43 |
44 | int OnexTreeItem::getContentSize()
45 | {
46 | return content.size();
47 | }
48 |
49 | QString OnexTreeItem::getName()
50 | {
51 | return name;
52 | }
53 |
54 | QMenu *OnexTreeItem::getContextMenu()
55 | {
56 | QMenu* contextMenu = new QMenu();
57 | if (!hasParent())
58 | {
59 | QAction* exportAllAction = new QAction(QObject::tr("Export all"), contextMenu);
60 | contextMenu->addAction(exportAllAction);
61 | QObject::connect(exportAllAction, SIGNAL(triggered(bool)), this, SLOT(onExportAll()));
62 |
63 | QAction* exportOriginalAction = new QAction(QObject::tr("Export as original"), contextMenu);
64 | contextMenu->addAction(exportOriginalAction);
65 | QObject::connect(exportOriginalAction, SIGNAL(triggered(bool)), this, SLOT(onExporAsOriginal()));
66 |
67 | QAction* closeThisItem = new QAction(QObject::tr("Close"), contextMenu);
68 | contextMenu->addAction(closeThisItem);
69 | QObject::connect(closeThisItem, SIGNAL(triggered(bool)), this, SLOT(actionClose()));
70 |
71 | }
72 | else
73 | {
74 | QAction* exportSingleAction = new QAction(QObject::tr("Export"), contextMenu);
75 | contextMenu->addAction(exportSingleAction);
76 | QObject::connect(exportSingleAction, SIGNAL(triggered(bool)), this, SLOT(onExportSingle()));
77 |
78 | QAction* exportSingleToRawAction = new QAction(QObject::tr("Export to raw"), contextMenu);
79 | contextMenu->addAction(exportSingleToRawAction);
80 | QObject::connect(exportSingleToRawAction, SIGNAL(triggered(bool)), this, SLOT(onExporSingleRaw()));
81 |
82 | QAction* replaceAction = new QAction(QObject::tr("Replace"), contextMenu);
83 | contextMenu->addAction(replaceAction);
84 | QObject::connect(replaceAction, SIGNAL(triggered(bool)), this, SLOT(onReplace()));
85 | }
86 |
87 | return contextMenu;
88 | }
89 |
90 | OnexTreeItem::~OnexTreeItem()
91 | {
92 |
93 | }
94 |
95 | void OnexTreeItem::onExportAll()
96 | {
97 | QMessageBox::warning(NULL, tr("Not yet"), tr("This isn't implemented yet"));
98 | }
99 |
100 | void OnexTreeItem::onExportSingle()
101 | {
102 | QMessageBox::warning(NULL, tr("Not yet"), tr("This isn't implemented yet"));
103 | }
104 |
105 | void OnexTreeItem::onExporSingleRaw()
106 | {
107 | QString fileName = getSaveDirectory(this->getName(), "Raw data (*.rawdata)");
108 | if (fileName.isEmpty())
109 | return;
110 |
111 | if (!fileName.endsWith(tr(".rawdata")))
112 | fileName += ".rawdata";
113 |
114 | QFile file(fileName);
115 | file.open(QIODevice::WriteOnly);
116 | if (file.write(this->getContent()) == -1)
117 | QMessageBox::critical(NULL, tr("Woops"), tr("Couldn't save that file"));
118 | else
119 | QMessageBox::information(NULL, tr("Yeah"), tr("File exported"));
120 | file.close();
121 | }
122 |
123 | void OnexTreeItem::onExporAsOriginal()
124 | {
125 | QMessageBox::warning(NULL, tr("Not yet"), tr("This isn't implemented yet"));
126 | }
127 |
128 | void OnexTreeItem::onReplace()
129 | {
130 | QMessageBox::warning(NULL, tr("Not yet"), tr("This isn't implemented yet"));
131 | }
132 |
133 | void OnexTreeItem::actionClose()
134 | {
135 | QList selectedItems = this->treeWidget()->selectedItems();
136 |
137 | foreach (auto& item, selectedItems)
138 | delete item;
139 | }
140 |
--------------------------------------------------------------------------------
/Source/Openers/NosZlibOpener.cpp:
--------------------------------------------------------------------------------
1 | #include "NosZlibOpener.h"
2 | #include "../Ui/OnexTreeZlibItem.h"
3 | #include "../Ui/OnexNSipData.h"
4 | #include "../Ui/OnexNS4BbData.h"
5 | #include "../Ui/OnexNStcData.h"
6 | #include "../Ui/OnexNStpData.h"
7 |
8 |
9 | QByteArray NosZlibOpener::toBigEndian(qint32 value)
10 | {
11 | QByteArray result;
12 | result.resize(4);
13 |
14 | qToBigEndian(value, reinterpret_cast(result.data()));
15 |
16 | return result;
17 | }
18 |
19 | int NosZlibOpener::getNTHeaderNumber(QByteArray &array)
20 | {
21 | if (array.mid(0, 7) == "NT Data")
22 | return array.mid(8, 2).toInt();
23 | else if (array.mid(0, 10) == "32GBS V1.0")
24 | return 101;
25 | else if (array.mid(0, 11) == "CCINF V1.20")
26 | return 102;
27 | else if (array.mid(0, 10) == "ITEMS V1.0")
28 | return 103;
29 | else
30 | return 199;
31 | }
32 |
33 | OnexTreeItem *NosZlibOpener::createItemFromHeader(int header, QString name, QByteArray& array, int fileId, int creationDate, bool compressed)
34 | {
35 | switch (header)
36 | {
37 | case NSipData:
38 | return new OnexNSipData(name, array, this, fileId, creationDate, compressed);
39 | break;
40 |
41 | case NS4BbData:
42 | return new OnexNS4BbData(name, array, this, fileId, creationDate, compressed);
43 | break;
44 |
45 | case NStcData:
46 | return new OnexNStcData(name, array, this, fileId, creationDate, compressed);
47 | break;
48 |
49 | case NStpData:
50 | return new OnexNStpData(name, array, this, fileId, creationDate, compressed);
51 | break;
52 |
53 | case NStpeData:
54 | return new OnexNStpData(name, array, this, fileId, creationDate, compressed);
55 | break;
56 |
57 | case NStpuData:
58 | return new OnexNStpData(name, array, this, fileId, creationDate, compressed);
59 | break;
60 |
61 | default:
62 | return new OnexTreeZlibItem(name, array, this, fileId, creationDate, compressed);
63 | break;
64 | }
65 | }
66 |
67 | NosZlibOpener::NosZlibOpener()
68 | {
69 |
70 | }
71 |
72 | ImageConverter &NosZlibOpener::getImageConverter()
73 | {
74 | return imageConverter;
75 | }
76 |
77 | OnexTreeItem *NosZlibOpener::decrypt(QFile &file)
78 | {
79 |
80 | file.seek(0);
81 |
82 | QByteArray header = file.read(NOS_HEADER_SIZE);
83 |
84 | int ntHeaderNumber = getNTHeaderNumber(header);
85 | int fileAmount = readNextInt(file);
86 |
87 | OnexTreeItem *item = createItemFromHeader(ntHeaderNumber, neatFileName(file.fileName()), header);
88 |
89 | QByteArray separatorByte = file.read(1);
90 |
91 | for (int i = 0; i != fileAmount; ++i)
92 | {
93 | int id = readNextInt(file);
94 | int offset = readNextInt(file);
95 |
96 | int previousOffset = file.pos();
97 |
98 | file.seek(offset);
99 |
100 | int creationDate = readNextInt(file);
101 | int dataSize = readNextInt(file);
102 | int compressedDataSize = readNextInt(file);
103 | bool isCompressed = file.read(1).at(0);
104 | QByteArray data = file.read(compressedDataSize);
105 | if (isCompressed)
106 | {
107 | QByteArray bigEndian = toBigEndian(dataSize);
108 | data.push_front(bigEndian);
109 | data = decryptor.decrypt(data);
110 | }
111 |
112 | item->addChild(createItemFromHeader(ntHeaderNumber, QString::number(id), data, id, creationDate, isCompressed));
113 | file.seek(previousOffset);
114 |
115 | }
116 |
117 | //encrypt(item);
118 |
119 | return item;
120 | }
121 |
122 | QByteArray NosZlibOpener::encrypt(OnexTreeItem *item)
123 | {
124 | if (item->hasParent())
125 | return QByteArray();
126 |
127 | QByteArray fileHeader = item->getContent();
128 | fileHeader.push_back(writeNextInt(item->childCount()));
129 | fileHeader.push_back((char)0x0);//separator byte
130 |
131 | QByteArray offsetArray;
132 | int sizeOfOffsetArray = item->childCount() * 8;
133 |
134 | QByteArray contentArray;
135 |
136 | int firstFileOffset = fileHeader.size() + sizeOfOffsetArray;
137 |
138 | for(int i = 0; i != item->childCount(); ++i)
139 | {
140 | int currentFileOffset = firstFileOffset + contentArray.size();
141 | OnexTreeZlibItem* currentItem = static_cast(item->child(i));
142 | contentArray.push_back(writeNextInt(currentItem->getCreationDate()));
143 | QByteArray content = currentItem->getContent();
144 | contentArray.push_back(writeNextInt(content.size()));
145 |
146 | if (currentItem->isCompressed())
147 | content = decryptor.encrypt(content);
148 |
149 | int compressedContentSize = content.size();
150 | if (currentItem->isCompressed())
151 | compressedContentSize -= 4; //qCompress add the size at the front of array
152 |
153 |
154 | contentArray.push_back(writeNextInt(compressedContentSize));
155 | contentArray.push_back(currentItem->isCompressed());
156 |
157 | if (currentItem->isCompressed())
158 | contentArray.push_back(content.mid(4));
159 | else
160 | contentArray.push_back(content);
161 |
162 | offsetArray.push_back(writeNextInt(currentItem->getId()));
163 | offsetArray.push_back(writeNextInt(currentFileOffset));
164 |
165 | }
166 |
167 | QByteArray result;
168 | result.push_back(fileHeader);
169 | result.push_back(offsetArray);
170 | result.push_back(contentArray);
171 |
172 |
173 | return result;
174 | }
175 |
--------------------------------------------------------------------------------
/Source/mainwindow.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | MainWindow
4 |
5 |
6 |
7 | 0
8 | 0
9 | 800
10 | 600
11 |
12 |
13 |
14 |
15 | 500
16 | 300
17 |
18 |
19 |
20 | false
21 |
22 |
23 | OnexExplorer [Beta]
24 |
25 |
26 |
27 | :/resources/oxe_icon_trans.ico
28 | :/resources/oxe_icon_trans.ico:/resources/oxe_icon_trans.ico
29 |
30 |
31 |
32 | -
33 |
34 |
35 | QFrame::StyledPanel
36 |
37 |
38 | QFrame::Plain
39 |
40 |
41 | 1
42 |
43 |
44 | 0
45 |
46 |
47 |
48 |
49 | 255
50 | 255
51 | 255
52 |
53 |
54 |
55 |
56 |
57 | -
58 |
59 |
60 |
61 | 0
62 | 0
63 |
64 |
65 |
66 |
67 | 171
68 | 16777215
69 |
70 |
71 |
72 | false
73 |
74 |
75 |
76 | 1
77 |
78 |
79 |
80 |
81 |
82 |
83 |
129 |
130 |
131 | Open
132 |
133 |
134 | Ctrl+O
135 |
136 |
137 |
138 |
139 | true
140 |
141 |
142 | Save as...
143 |
144 |
145 | Ctrl+S
146 |
147 |
148 |
149 |
150 | Close selected
151 |
152 |
153 | Ctrl+W
154 |
155 |
156 |
157 |
158 | true
159 |
160 |
161 | Export
162 |
163 |
164 | Ctrl+E
165 |
166 |
167 |
168 |
169 | true
170 |
171 |
172 | Import
173 |
174 |
175 | Ctrl+I
176 |
177 |
178 |
179 |
180 | false
181 |
182 |
183 | Help
184 |
185 |
186 |
187 |
188 | Exit
189 |
190 |
191 | Ctrl+Q
192 |
193 |
194 |
195 |
196 | false
197 |
198 |
199 | Options
200 |
201 |
202 | Ctrl+,
203 |
204 |
205 |
206 |
207 | true
208 |
209 |
210 | Close all
211 |
212 |
213 | Ctrl+Shift+W
214 |
215 |
216 |
217 |
218 | Replace
219 |
220 |
221 | Ctrl+R
222 |
223 |
224 |
225 |
226 | About
227 |
228 |
229 |
230 |
231 |
232 | treeWidget
233 |
234 |
235 |
236 |
237 |
238 |
239 |
--------------------------------------------------------------------------------
/Source/MainWindow.cpp:
--------------------------------------------------------------------------------
1 | #include "MainWindow.h"
2 | #include "ui_mainwindow.h"
3 |
4 | MainWindow::MainWindow(QWidget *parent) :
5 | QMainWindow(parent),
6 | ui(new Ui::MainWindow)
7 | {
8 | ui->setupUi(this);
9 | this->setAcceptDrops(true);
10 |
11 | ui->treeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
12 |
13 | connect(ui->treeWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onCustomMenuShow(QPoint)));
14 | }
15 |
16 | MainWindow::~MainWindow()
17 | {
18 | if (contextMenu)
19 | {
20 | clearMenu();
21 | delete contextMenu;
22 | }
23 |
24 | delete ui;
25 | }
26 |
27 | void MainWindow::onCustomMenuShow(const QPoint &point)
28 | {
29 | Q_UNUSED(point);
30 |
31 | if (contextMenu)
32 | {
33 | clearMenu();
34 | delete contextMenu;
35 | contextMenu = nullptr;
36 | }
37 | OnexTreeItem* item = static_cast(ui->treeWidget->currentItem());
38 | if (item == nullptr)
39 | return;
40 |
41 | contextMenu = item->getContextMenu();
42 |
43 | if (contextMenu->isEmpty())
44 | return;
45 | qDebug() << contextMenu->height();
46 | contextMenu->exec(QCursor::pos());
47 | }
48 |
49 | void MainWindow::clearMenu()
50 | {
51 | qDebug() << "Disposing menu";
52 | QList actions = contextMenu->actions();
53 |
54 | for (auto& action : actions)
55 | delete action;
56 |
57 | contextMenu->clear();
58 | }
59 |
60 | void MainWindow::on_actionOpen_triggered()
61 | {
62 | QFileDialog openDialog(this);
63 |
64 | openDialog.setFileMode(QFileDialog::ExistingFiles);
65 | openDialog.setNameFilter(tr("NosTale Files (*.NOS)"));
66 | openDialog.setViewMode(QFileDialog::Detail);
67 |
68 | QStringList selectedFiles;
69 | if (openDialog.exec())
70 | selectedFiles = openDialog.selectedFiles();
71 |
72 | if (!selectedFiles.empty())
73 | {
74 | for (auto& file : selectedFiles)
75 | openFile(file);
76 | }
77 | }
78 |
79 | void MainWindow::openFile(QString path)
80 | {
81 | QFile file(path);
82 |
83 | if (!file.open(QIODevice::ReadOnly))
84 | return;
85 |
86 | if (hasValidHeader(file))
87 | handleOpenResults(zlibOpener.decrypt(file));
88 | else
89 | handleOpenResults(textOpener.decrypt(file));
90 |
91 | file.close();
92 | }
93 |
94 | void MainWindow::handleOpenResults(OnexTreeItem *item)
95 | {
96 | ui->treeWidget->addTopLevelItem(item);
97 | item->setExpanded(true);
98 | }
99 |
100 | bool MainWindow::hasValidHeader(QFile &file)
101 | {
102 | file.seek(0);
103 | QByteArray header = file.read(0x0B);
104 | if (header.mid(0, 7) == "NT Data" || header.mid(0, 10) == "32GBS V1.0" || header.mid(0, 10) == "ITEMS V1.0")
105 | return true;
106 | return false;
107 | }
108 |
109 | void MainWindow::dropEvent(QDropEvent *e)
110 | {
111 | for (auto& url : e->mimeData()->urls())
112 | {
113 | QString fileName = url.toLocalFile();
114 | openFile(fileName);
115 | }
116 | }
117 |
118 | void MainWindow::dragEnterEvent(QDragEnterEvent *e)
119 | {
120 | for (auto& url : e->mimeData()->urls())
121 | {
122 | QString fileName = url.toLocalFile();
123 | if (QFileInfo(fileName).suffix() != "NOS")
124 | return;
125 | }
126 | e->acceptProposedAction();
127 | }
128 |
129 | void MainWindow::on_treeWidget_itemDoubleClicked(QTreeWidgetItem *treeItem, int column)
130 | {
131 | Q_UNUSED(column);
132 |
133 | OnexTreeItem* item = static_cast(treeItem);
134 |
135 | if (item->childCount() != 0)
136 | return;
137 |
138 | if (!item->hasParent())
139 | return;
140 |
141 | QWidget* previewWindow = item->onClicked();
142 |
143 |
144 | if (!previewWindow)
145 | {
146 | QMessageBox::warning(this, "Not supported", "This NosTale file cannot be opened yet.");
147 | return;
148 | }
149 |
150 | ui->mdiArea->addSubWindow(previewWindow);
151 | previewWindow->setAttribute(Qt::WA_DeleteOnClose);
152 | previewWindow->show();
153 | }
154 |
155 | void MainWindow::on_actionClose_selected_triggered()
156 | {
157 | QList selectedItems = ui->treeWidget->selectedItems();
158 | foreach (auto& item, selectedItems)
159 | delete item;
160 | }
161 |
162 | void MainWindow::on_actionReplace_triggered()
163 | {
164 | if(ui->treeWidget->currentItem()){
165 |
166 | OnexTreeItem* item = static_cast(ui->treeWidget->currentItem());
167 | if(item->hasParent()){
168 |
169 | item->onReplace();
170 | }else{
171 | QMessageBox::information(NULL, tr("Info"), tr("Select correct file not *.NOS"));
172 | }
173 | }else{
174 | QMessageBox::information(NULL, tr("Info"), tr("Select file first"));
175 | }
176 | }
177 | void MainWindow::on_actionExport_triggered()
178 | {
179 | if(ui->treeWidget->currentItem()){
180 |
181 | OnexTreeItem* item = static_cast(ui->treeWidget->currentItem());
182 | if(item->hasParent()){
183 |
184 | item->onExportSingle();
185 | }else{
186 | QMessageBox::information(NULL, tr("Info"), tr("Select correct file not *.NOS"));
187 | }
188 | }else{
189 | QMessageBox::information(NULL, tr("Info"), tr("Select file first"));
190 | }
191 | }
192 | void MainWindow::on_actionImport_triggered()
193 | {
194 | QMessageBox::warning(NULL, tr("Not yet"), tr("This isn't implemented yet"));
195 | }
196 |
197 | void MainWindow::on_actionAbout_triggered()
198 | {
199 | QMessageBox::information(NULL, tr("About Project"), tr("OnexExplorer is an open-source tool for unpacking and repacking .NOS data files from game called NosTale. "
200 | "
It can open almost all .NOS files and show the data stored in them."
201 | "
GitHub: https://github.com/OnexTale/OnexExplorer"));
202 | }
203 |
204 | void MainWindow::on_actionSave_as_triggered()
205 | {
206 | if(ui->treeWidget->currentItem()){
207 |
208 | OnexTreeItem* item = static_cast(ui->treeWidget->currentItem());
209 | if(!item->hasParent()){
210 | item->onExporAsOriginal();
211 | }else{
212 | QMessageBox::information(NULL, tr("Info"), tr("Select correct *.NOS file"));
213 | }
214 | }else{
215 | QMessageBox::information(NULL, tr("Info"), tr("Select .NOS file first"));
216 | }
217 | }
218 |
219 | void MainWindow::on_actionExit_triggered()
220 | {
221 | QMessageBox::StandardButton message = QMessageBox::question(this, "",
222 | "Exit program?",
223 | QMessageBox::Yes | QMessageBox::No,
224 | QMessageBox::No);
225 | if (message == QMessageBox::Yes)
226 | QApplication::quit();
227 | }
228 |
229 | void MainWindow::on_actionClose_all_triggered()
230 | {
231 | QMessageBox::StandardButton message = QMessageBox::question(this, "",
232 | "Close all items?",
233 | QMessageBox::Yes | QMessageBox::No,
234 | QMessageBox::No);
235 |
236 | if (message == QMessageBox::Yes)
237 | {
238 | ui->treeWidget->clear();
239 | }
240 | }
241 |
242 | void MainWindow::on_actionOptions_triggered()
243 | {
244 | OnexTreeItem* item = static_cast(ui->treeWidget->currentItem());
245 | if (item == nullptr)
246 | return;
247 | if (item->childCount() != 0)
248 | return;
249 | FileInfo dialog(item);
250 | dialog.exec();
251 | }
252 |
--------------------------------------------------------------------------------
/Source/ImageConverter.cpp:
--------------------------------------------------------------------------------
1 | #include "ImageConverter.h"
2 | #include
3 |
4 | QImage ImageConverter::convertGBAR4444(QByteArray &array, int width, int height, int startByte)
5 | ///GBAR = ARGB (endianness)
6 | {
7 | qDebug() << "Opened GBAR4444 image.";
8 | QImage img(width, height, QImage::Format_ARGB32);
9 |
10 | img.fill(Qt::transparent);
11 |
12 | for (int y = 0; y < height; ++y)
13 | {
14 | for (int x = 0; x < width; ++x)
15 | {
16 | uchar gb = array.at(startByte + y * 2 * height + x * 2);
17 | uchar ar = array.at(startByte + y * 2 * height + x * 2 + 1);
18 |
19 | uchar g = gb >> 4;
20 | uchar b = gb & 0xF;
21 | uchar a = ar >> 4;
22 | uchar r = ar & 0xF;
23 |
24 | img.setPixel(x, y, qRgba(r * 0x11, g * 0x11, b * 0x11, a * 0x11));
25 | }
26 | }
27 |
28 | return img;
29 | }
30 |
31 | QImage ImageConverter::convertBGRA8888(QByteArray &array, int width, int height, int startByte)
32 | {
33 | qDebug() << "Opened BGRA8888 image.";
34 | QImage img(width, height, QImage::Format_ARGB32);
35 |
36 | img.fill(Qt::transparent);
37 |
38 | for (int y = 0; y < height; ++y)
39 | {
40 | for (int x = 0; x < width; ++x)
41 | {
42 | uchar b = array.at(startByte + y * 4 * height + x * 4);
43 | uchar g = array.at(startByte + y * 4 * height + x * 4 + 1);
44 | uchar r = array.at(startByte + y * 4 * height + x * 4 + 2);
45 | uchar a = array.at(startByte + y * 4 * height + x * 4 + 3);
46 |
47 | img.setPixel(x, y, qRgba(r, g, b, a));
48 | }
49 | }
50 |
51 | return img;
52 | }
53 |
54 | QImage ImageConverter::convertARGB555(QByteArray& array, int width, int height, int startByte)
55 | {
56 | qDebug() << "Opened ARGB555 image.";
57 | QImage img(width, height, QImage::Format_ARGB32);
58 |
59 | img.fill(Qt::transparent);
60 |
61 | for (int y = 0; y < height; ++y)
62 | {
63 | for (int x = 0; x < width; ++x)
64 | {
65 | ushort bytes = qFromLittleEndian(reinterpret_cast(array.mid(startByte + y * 2 * height + x * 2, 2).data()));
66 |
67 | uchar a = 255*(bytes & 0x8000) >> 15; // 0x8000 = 0b1000000000000000
68 | uchar r = 8*(bytes & 0x7C00) >> 10; // 0x7C00 = 0b0111110000000000
69 | uchar g = 8*(bytes & 0x3E0) >> 5; //0x3E0 = 0b0000001111100000
70 | uchar b = 8*(bytes & 0x1F); // 0x1F = 0b0000000000011111
71 |
72 | img.setPixel(x, y, qRgba(r, g, b, a));
73 | }
74 | }
75 |
76 | return img;
77 | }
78 |
79 | QImage ImageConverter::convertNSTC(QByteArray &array, int width, int height, int startByte)
80 | {
81 | qDebug() << "Opened NSTC image.";
82 | QImage img(width, height, QImage::Format_ARGB32);
83 | img.fill(Qt::transparent);
84 |
85 | for (int x = 0; x < width; ++x)
86 | {
87 | for (int y = 0; y < height; ++y)
88 | {
89 | uchar value = array.at(startByte + y * width + x);
90 | if (colors.contains(value))
91 | img.setPixel(x, y, colors[value].rgb());
92 | else
93 | img.setPixel(x, y, colors[0xFF].rgb());
94 | }
95 | }
96 |
97 | return img.scaled(QSize(width*2, height*2));
98 | }
99 |
100 | QImage ImageConverter::convertBGRA8888_INTERLACED(QByteArray &array, int width, int height, int startByte)
101 | {
102 | qDebug() << "Opened BGRA888_INTERLACED image.";
103 | QImage img(width, height, QImage::Format_RGBA8888);
104 | img.fill(Qt::transparent);
105 |
106 | short num = 0, x = 0, y = 0;
107 | for (int i = 0; i < array.size() - startByte;)
108 | {
109 | uchar b = array.at(startByte + i++);
110 | uchar g = array.at(startByte + i++);
111 | uchar r = array.at(startByte + i++);
112 | uchar a = array.at(startByte + i++);
113 | img.setPixel(x, y, qRgba(r, g, b, a));
114 |
115 | x++;
116 | if (x == (num + 256) || x == width)
117 | {
118 | x = num;
119 | y++;
120 | }
121 | if (y == height)
122 | {
123 | y = 0;
124 | num += 256;
125 | x = num;
126 | }
127 | }
128 | return img;
129 | }
130 |
131 | QImage ImageConverter::convertBARG4444(QByteArray &array, int width, int height, int startByte)
132 | ///BARG = RGBA (endianness)
133 | {
134 | qDebug() << "Opened BARG4444 image.";
135 | QImage img(width, height, QImage::Format_ARGB32);
136 |
137 | img.fill(Qt::transparent);
138 |
139 | for (int y = 0; y < height; ++y)
140 | {
141 | for (int x = 0; x < width; ++x)
142 | {
143 | uchar ba = array.at(startByte + y * 2 * height + x * 2);
144 | uchar rg = array.at(startByte + y * 2 * height + x * 2 + 1);
145 |
146 | uchar b = ba >> 4;
147 | uchar a = ba & 0xF;
148 | uchar r = rg >> 4;
149 | uchar g = rg & 0xF;
150 |
151 | img.setPixel(x, y, qRgba(r * 0x11, g * 0x11, b * 0x11, a * 0x11));
152 | }
153 | }
154 |
155 | return img;
156 | }
157 | // ////////////////////////////////////////////////////////////////////////////////////////////////////////
158 | QByteArray ImageConverter::toGBAR4444(QImage &image)
159 | {
160 | qDebug() << "Replaced GBAR4444 image.";
161 | QByteArray data;
162 |
163 | for (int y = 0; y < image.height(); ++y)
164 | {
165 | for (int x = 0; x < image.width(); ++x)
166 | {
167 | QRgb currentPixel = image.pixel(x, y);
168 |
169 | uchar green = qGreen(currentPixel) / 0x11;
170 | uchar blue = qBlue(currentPixel) / 0x11;
171 | uchar alpha = qAlpha(currentPixel) / 0x11;
172 | uchar red = qRed(currentPixel) / 0x11;
173 |
174 | uchar gb = (green << 4) + blue;
175 | uchar ar = (alpha << 4) + red;
176 |
177 | data.push_back(gb);
178 | data.push_back(ar);
179 | }
180 | }
181 |
182 | return data;
183 | }
184 |
185 | QByteArray ImageConverter::toNSTC(QImage &image)
186 | {
187 | qDebug() << "Replaced NSTC image.";
188 | QByteArray data;
189 | int i = 0, j = 0;
190 |
191 | for (int y = 0; y < image.height(); ++y)
192 | {
193 | for (int x = 0; x < image.width(); ++x)
194 | {
195 | QRgb currentPixel = image.pixel(x, y);
196 | QColor pixColor = qRgb(qRed(currentPixel), qGreen(currentPixel), qBlue(currentPixel));
197 | if (colors.values().contains(pixColor))
198 | {
199 | i++;
200 | data.push_back(colors.key(pixColor));
201 | }
202 | else
203 | {
204 | j++;
205 | data.push_back(0xFF);
206 | }
207 | }
208 | }
209 | return data;
210 | }
211 |
212 | QByteArray ImageConverter::toBGRA8888(QImage &image)
213 | {
214 | qDebug() << "Replaced BGRA8888 image.";
215 | QByteArray data;
216 |
217 | for (int y = 0; y < image.height(); ++y)
218 | {
219 | for (int x = 0; x < image.width(); ++x)
220 | {
221 | QRgb currentPixel = image.pixel(x, y);
222 | uchar alpha = qAlpha(currentPixel);
223 | uchar red = qRed(currentPixel);
224 | uchar green = qGreen(currentPixel);
225 | uchar blue = qBlue(currentPixel);
226 |
227 | data.push_back(blue);
228 | data.push_back(green);
229 | data.push_back(red);
230 | data.push_back(alpha);
231 | }
232 | }
233 |
234 | return data;
235 | }
236 |
237 | QByteArray ImageConverter::toARGB555(QImage &image)
238 | {
239 | qDebug() << "Replaced ARGB555 image.";
240 | //NOPE
241 | QByteArray data;
242 |
243 | for (int y = 0; y < image.height(); ++y)
244 | {
245 | for (int x = 0; x < image.width(); ++x)
246 | {
247 | QRgb currentPixel = image.pixel(x, y);
248 |
249 | uchar alpha = qAlpha(currentPixel) / 0xFF; //full alpha or gtfo
250 | uchar red = qRed(currentPixel) / 0x08;
251 | uchar green = qGreen(currentPixel) / 0x08;
252 | uchar blue = qBlue(currentPixel) / 0x08;
253 |
254 | ushort bytes = (alpha << 15) | (red << 10) | (green << 5) | (blue);
255 |
256 | uchar first = bytes >> 8;
257 | uchar second = bytes & 0xFF;
258 | data.push_back(second);
259 | data.push_back(first);
260 | }
261 | }
262 |
263 | return data;
264 | }
265 |
266 | QByteArray ImageConverter::toBGRA8888_INTERLACED(QImage &image)
267 | {
268 | qDebug() << "Replaced BGRA8888_INTERLACED image.";
269 | QByteArray data;
270 |
271 | short num = 0, x = 0, y = 0;
272 | for (int i = 0; i < image.width()*image.height(); i++)
273 | {
274 | QRgb currentPixel = image.pixel(x, y);
275 | uchar b = qBlue(currentPixel);
276 | uchar g = qGreen(currentPixel);
277 | uchar r = qRed(currentPixel);
278 | uchar a = qAlpha(currentPixel);
279 | data.push_back(b);
280 | data.push_back(g);
281 | data.push_back(r);
282 | data.push_back(a);
283 |
284 | x++;
285 | if (x == (num + 256) || x == image.width())
286 | {
287 | x = num;
288 | y++;
289 | }
290 | if (y == image.height())
291 | {
292 | y = 0;
293 | num += 256;
294 | x = num;
295 | }
296 | }
297 |
298 | return data;
299 | }
300 |
301 | QByteArray ImageConverter::toBARG4444(QImage &image)
302 | {
303 | qDebug() << "Replaced BARG4444 image.";
304 | //only in 2k6 NSip, not tested, should work tho as its the same as GBAR4444 but different order.
305 | QByteArray data;
306 |
307 | for (int y = 0; y < image.height(); ++y)
308 | {
309 | for (int x = 0; x < image.width(); ++x)
310 | {
311 | QRgb currentPixel = image.pixel(x, y);
312 |
313 | uchar blue = qBlue(currentPixel) / 0x11;
314 | uchar alpha = qAlpha(currentPixel) / 0x11;
315 | uchar red = qRed(currentPixel) / 0x11;
316 | uchar green = qGreen(currentPixel) / 0x11;
317 |
318 | uchar ba = (blue << 4) + alpha;
319 | uchar rg = (red << 4) + green;
320 |
321 | data.push_back(ba);
322 | data.push_back(rg);
323 | }
324 | }
325 |
326 | return data;
327 | }
328 |
329 | ImageConverter::ImageConverter()
330 | {
331 | colors[0x0] = qRgb(255, 255, 255);
332 | colors[0x1] = qRgb(100, 100, 100);
333 | colors[0x2] = qRgb(100, 150, 100);
334 | colors[0x3] = qRgb(0, 0, 0);
335 | colors[0x9] = qRgb(100, 100, 150);
336 | colors[0x0a] = qRgb(0, 50, 200);
337 | colors[0x0b] = qRgb(150, 100, 100);
338 | colors[0x0d] = qRgb(150, 150, 100);
339 | colors[0x10] = qRgb(150, 100, 150);
340 | colors[0x11] = qRgb(0, 200, 50);
341 | colors[0x12] = qRgb(200, 50, 0);
342 | colors[0x13] = qRgb(250, 230, 10);
343 | colors[0xFF] = qRgb(150, 0, 255);
344 | }
345 |
346 |
--------------------------------------------------------------------------------