diff --git a/msvc/BedlamTools.vcxproj b/msvc/BedlamTools.vcxproj index a37a661..639ddad 100644 --- a/msvc/BedlamTools.vcxproj +++ b/msvc/BedlamTools.vcxproj @@ -157,6 +157,9 @@ + + + @@ -167,6 +170,9 @@ + + + diff --git a/msvc/BedlamTools.vcxproj.filters b/msvc/BedlamTools.vcxproj.filters index 8168720..2c52fc7 100644 --- a/msvc/BedlamTools.vcxproj.filters +++ b/msvc/BedlamTools.vcxproj.filters @@ -52,6 +52,15 @@ Source Files + + Source Files + + + Source Files + + + Source Files + @@ -66,6 +75,15 @@ Header Files + + Header Files + + + Header Files + + + Header Files + diff --git a/qt/bedlamtools.ui b/qt/bedlamtools.ui index 339b77b..96d2eda 100644 --- a/qt/bedlamtools.ui +++ b/qt/bedlamtools.ui @@ -88,7 +88,7 @@ - 1 + 0 9999 @@ -97,7 +97,7 @@ 1 - 1 + 0 diff --git a/src/Bedlam_func.cpp b/src/Bedlam_func.cpp index 3b067cc..656eaa6 100644 --- a/src/Bedlam_func.cpp +++ b/src/Bedlam_func.cpp @@ -1,6 +1,7 @@ #include #include "Bedlam_func.h" +#include "helper.h" //00401E39 void draw_IMG_in_buffer(int32_t image_number, int16_t transparent, int32_t x_pos, int32_t y_pos, uint8_t* buffer, uint8_t* bin_ptr) @@ -186,8 +187,303 @@ void draw_IMG_in_buffer(int32_t image_number, int16_t transparent, int32_t x_pos } } -//no present -bool bittest(int32_t value, int32_t bit) +//00401471 +void draw_tile(int32_t img_num, int32_t ofst, uint8_t* palette, uint8_t* screen_pos, const uint8_t* bin_ptr) { - return value & (1 << bit); -} \ No newline at end of file + const uint8_t* img_adr; // esi + const uint8_t* img_ptr; // esi + const uint8_t* v7; // esi + int v8; // edx + int v9; // edx + const uint8_t* v11; // esi + uint8_t* v12; // edi + const uint8_t* v13; // esi + int v14; // ebx + int j; // edx + int v16; // ecx + unsigned int v17; // ecx + char v18; // cf + unsigned int v19; // ecx + unsigned int v20; // ecx + const uint8_t* line_ofst_ptr; // esi + int line_ofst; // edx + int img_ofst; // edx + const uint8_t* v24; // esi + uint8_t* screen_pos_1; // edi + const uint8_t* v26; // esi + int v27; // ebx + int i; // edx + unsigned int v29; // ecx + unsigned int v30; // ecx + unsigned int v31; // ecx + int v32; // eax + const uint8_t* v36; // esi + int v37; // ecx + int v38; // edx + int v39; // ecx + int v40; // ecx + int v44; // [esp-Ch] [ebp-Ch] + int v45; // [esp-8h] [ebp-8h] + int v46; // [esp-8h] [ebp-8h] + uint8_t* v47; // [esp-4h] [ebp-4h] + uint8_t* v48; // [esp-4h] [ebp-4h] + uint8_t* palette_ptr = palette; + + const int const1_1 = 1; + + uint16_t unkn1; + uint32_t unkn2; + uint16_t unkn3; + uint32_t unkn4; + uint32_t unkn6; + + img_adr = &bin_ptr[4 * img_num + 2]; + img_ptr = &img_adr[*(uint32_t*)img_adr]; + if (*(unsigned __int16*)img_ptr >= 4u) + { + line_ofst_ptr = img_ptr + 2; + line_ofst = 640 * *(unsigned __int16*)line_ofst_ptr; + line_ofst_ptr += 2; + img_ofst = *(unsigned __int16*)line_ofst_ptr + line_ofst; + line_ofst_ptr += 2; + line_ofst = *(uint16_t*)line_ofst_ptr; + v24 = line_ofst_ptr + 2; + if (line_ofst) + { + screen_pos_1 = &screen_pos[img_ofst]; + unkn1 = *(unsigned __int16*)v24; + v26 = v24 + 2; + v27 = unkn1; + if (unkn1) + { + if (palette_ptr && const1_1) + { + LABEL_37: + while (2) + { + v47 = screen_pos_1; + while (1) + { + while (1) + { + ofst &= 0xFFFFFF00; + ofst |= *v26++; + v44 = ofst; + if (bittest(v44, 7u)) + break; + ofst = (ofst & 0x3F) + 1; + v45 = v27; + do + { + *screen_pos_1 = palette_ptr[*v26]; + ++v26; + ++screen_pos_1; + --ofst; + } while (ofst); + v27 = v45; + if (bittest(v44, 6u)) + { + screen_pos_1 = v47 + 640; + v27 = v45 - 1; + if (v45 != 1) + goto LABEL_37; + return; + } + } + if (bittest(ofst, 6u)) + break; + screen_pos_1 += (ofst & 0x3F) + 1; + } + screen_pos_1 = v47 + 640; + if (--v27) + continue; + break; + } + } + else + { + LABEL_24: + while (2) + { + for (i = 640; ; i -= v32) + { + while (1) + { + ofst &= 0xFFFFFF00; + ofst |= *v26++; + unkn2 = ofst; + if (bittest(unkn2, 7u)) + break; + v29 = (ofst & 0x3F) + 1; + i -= v29; + v18 = v29 & 1; + v30 = v29 >> 1; + if (v18) + *screen_pos_1++ = *v26++; + v18 = v30 & 1; + v31 = v30 >> 1; + if (v18) + { + *(uint16_t*)screen_pos_1 = *(uint16_t*)v26; + v26 += 2; + screen_pos_1 += 2; + } + memcpy(screen_pos_1, v26, 4 * v31); + v26 += 4 * v31; + screen_pos_1 += 4 * v31; + ofst = 0; + if (bittest(unkn2, 6u)) + { + screen_pos_1 += i; + if (--v27) + goto LABEL_24; + return; + } + } + if (bittest(ofst, 6u)) + break; + v32 = (ofst & 0x3F) + 1; + screen_pos_1 += v32; + } + screen_pos_1 += i; + if (--v27) + continue; + break; + } + } + } + } + } + else if (*(uint16_t*)img_ptr) + { + v7 = img_ptr + 2; + v8 = 640 * *(unsigned __int16*)v7; + v7 += 2; + v9 = *(unsigned __int16*)v7 + v8; + v7 += 2; + unkn3 = *(unsigned __int16*)v7; + v11 = v7 + 2; + if (unkn3) + { + v12 = &screen_pos[v9]; + unkn3 = *(unsigned __int16*)v11; + v13 = v11 + 2; + v14 = unkn3; + if (unkn3) + { + if (palette_ptr && const1_1) + { + LABEL_55: + while (2) + { + v48 = v12; + while (1) + { + while (1) + { + v39 = *(unsigned __int16*)v13; + v13 += 2; + unkn4 = v39; + if (bittest(unkn4, 0xFu)) + break; + v40 = v39 & 0xFFF; + v46 = v14; + do + { + *v12 = palette_ptr[*v13]; + ++v13; + ++v12; + --v40; + } while (v40); + v14 = v46; + if (bittest(unkn4, 0xEu)) + { + v12 = v48 + 640; + v14 = v46 - 1; + if (v46 != 1) + goto LABEL_55; + return; + } + } + if (bittest(v39, 0xEu)) + break; + v12 += v39 & 0xFFF; + } + v12 = v48 + 640; + if (--v14) + continue; + break; + } + } + else + { + LABEL_7: + while (2) + { + for (j = 640; ; j -= v16 & 0xFFF) + { + while (1) + { + v16 = *(unsigned __int16*)v13; + v13 += 2; + unkn6 = v16; + if (bittest(unkn6, 0xFu)) + break; + v17 = v16 & 0xFFF; + j -= v17; + v18 = v17 & 1; + v19 = v17 >> 1; + if (v18) + *v12++ = *v13++; + v18 = v19 & 1; + v20 = v19 >> 1; + if (v18) + { + *(uint16_t*)v12 = *(uint16_t*)v13; + v13 += 2; + v12 += 2; + } + memcpy(v12, v13, 4 * v20); + v13 += 4 * v20; + v12 += 4 * v20; + if (bittest(unkn6, 0xEu)) + { + v12 += j; + if (--v14) + goto LABEL_7; + return; + } + } + if (bittest(v16, 0xEu)) + break; + v12 += v16 & 0xFFF; + } + v12 += j; + if (--v14) + continue; + break; + } + } + } + } + } + else + { + v36 = img_ptr + 6; + v37 = 64; + do + { + v38 = 64; + do + { + if (*v36) + *screen_pos = *v36; + ++v36; + ++screen_pos; + --v38; + } while (v38); + screen_pos += 576; + --v37; + } while (v37); + } +} diff --git a/src/Bedlam_func.h b/src/Bedlam_func.h index bf0b101..4483987 100644 --- a/src/Bedlam_func.h +++ b/src/Bedlam_func.h @@ -2,4 +2,4 @@ #include "stdafx.h" void draw_IMG_in_buffer(int32_t image_number, int16_t transparent, int32_t x_pos, int32_t y_pos, uint8_t* buffer, uint8_t* bin_ptr); -bool bittest(int32_t value, int32_t bit); \ No newline at end of file +void draw_tile(int32_t img_num, int32_t ofst, uint8_t* palette, uint8_t* screen_pos, const uint8_t* bin_ptr); diff --git a/src/bedlamtools.cpp b/src/bedlamtools.cpp index bd7b9d5..099dc71 100644 --- a/src/bedlamtools.cpp +++ b/src/bedlamtools.cpp @@ -8,6 +8,7 @@ #include "Bedlam_func.h" #include "bedlamtools.h" + BedlamTools::BedlamTools(QWidget *parent) : QMainWindow(parent) { @@ -17,27 +18,19 @@ BedlamTools::BedlamTools(QWidget *parent) void BedlamTools::on_button_open_img_clicked() { QString bin_path = QFileDialog::getOpenFileName(this, "Open a file", "", "*.bin"); - QFile file(bin_path); - if (!file.open(QIODevice::ReadOnly)) { - qWarning("Cannot open file for reading"); - return; - } // set path to label std::filesystem::path file_path = bin_path.toStdString(); ui.label_bin->setText( QString::fromStdString( file_path.filename().string() ) ); // read file - file_bin.clear(); - file_bin = file.readAll(); - file.close(); + file_bin.load(bin_path.toStdString()); // read image info - char* data_ptr = file_bin.data(); - int image_count = *(uint16_t*)data_ptr; + int image_count = file_bin.get_img_count(); ui.img_count->setText(QString::number(image_count)); - ui.spinBox_img->setMaximum(image_count); - if (ui.spinBox_img->value() > image_count) { - ui.spinBox_img->setValue(image_count); + ui.spinBox_img->setMaximum(image_count - 1); + if (ui.spinBox_img->value() >= image_count) { + ui.spinBox_img->setValue(image_count - 1); } bin_redraw(); @@ -46,20 +39,12 @@ void BedlamTools::on_button_open_img_clicked() { void BedlamTools::on_button_open_pal_clicked() { QString pal_path = QFileDialog::getOpenFileName(this, "Open a file", "", "*.pal" ); - QFile file(pal_path); - if (!file.open(QIODevice::ReadOnly)) { - qWarning("Cannot open file for reading"); - return; - } - // set path to label std::filesystem::path file_path = pal_path.toStdString(); ui.label_pal->setText(QString::fromStdString(file_path.filename().string())); // read file - file_pal.clear(); - file_pal = file.readAll(); - file.close(); + file_pal.load(pal_path.toStdString()); bin_redraw(); } @@ -75,23 +60,19 @@ void BedlamTools::update_image() { void BedlamTools::bin_redraw() { - if (file_bin.isEmpty()){ + if (!file_bin.get_size()){ return; } screen_bufer.clear(); - screen_bufer.resize(640 * 480 * 2); + screen_bufer.resize(640 * 480); QImage image(640, 480, QImage::Format_RGB888); - + // read image info int32_t header_size = 2; - char* data_ptr = file_bin.data(); - uint8_t* file_data_ptr = (uint8_t*)data_ptr; - int32_t offset = 4 * (ui.spinBox_img->value() - 1); - data_ptr = data_ptr + header_size + offset; - int32_t image_address = *(uint32_t*)(data_ptr); - char* img = data_ptr + image_address; - uint16_t img_header = *(uint16_t*)img; + uint8_t* file_data_ptr = file_bin.get_ptr(); + int32_t img = ui.spinBox_img->value(); + uint16_t img_header = *reinterpret_cast(file_bin.get_img_header_ptr(img)); ui.img_header->setText(QString::number(img_header)); // read spinbox values @@ -101,7 +82,15 @@ void BedlamTools::bin_redraw() { // print img in buffer, use standard bedlam function uint8_t* screen_buffer_ptr = screen_bufer.data(); - draw_IMG_in_buffer(ui.spinBox_img->value() - 1, 0, scr_y, scr_x, screen_buffer_ptr, file_data_ptr); + if (img_header == 0x0007) + { + draw_tile(img, 0, 0, screen_buffer_ptr + scr_y * 640 + scr_x, file_data_ptr); + } + else + { + draw_IMG_in_buffer(img, 0, scr_y, scr_x, screen_buffer_ptr, file_data_ptr); + } + // print img buffer to QImage int i = 0; @@ -123,10 +112,11 @@ void BedlamTools::bin_redraw() { QRgb BedlamTools::get_color(uint8_t value){ // if invalid .pal file, then return value unchanged - if (file_pal.isEmpty() || file_pal.size() < 255 * 3) { + if (!file_pal.get_size() || file_pal.get_size() < 255 * 3) { return qRgb(value, value, value); } // input value is offset in .pal file. First 2 byte in .pal file is info and contain no color data int brightness = 4; + return qRgb(file_pal.at(value * 3 + 2) * brightness, file_pal.at(value * 3 + 3) * brightness, file_pal.at(value * 3 + 4) * brightness); } diff --git a/src/bedlamtools.h b/src/bedlamtools.h index 72ed8c3..872c68a 100644 --- a/src/bedlamtools.h +++ b/src/bedlamtools.h @@ -1,9 +1,11 @@ #pragma once #include -#include -#include "ui_bedlamtools.h" +#include = +#include "bin_file.h" +#include "file.h" +#include "ui_bedlamtools.h" class BedlamTools : public QMainWindow { @@ -19,8 +21,8 @@ private slots: private: Ui::BedlamToolsClass ui; - QByteArray file_bin; - QByteArray file_pal; + BIN_File file_bin; + File file_pal; std::vector screen_bufer; void bin_redraw(); QRgb get_color(uint8_t value); diff --git a/src/bin_file.cpp b/src/bin_file.cpp new file mode 100644 index 0000000..d065d33 --- /dev/null +++ b/src/bin_file.cpp @@ -0,0 +1,108 @@ +#include +#include "bin_file.h" +#include "helper.h" + +BIN_File::BIN_File() +{ + +} + +BIN_File::BIN_File(const std::string &path) : File(path) +{ + +} + +int BIN_File::get_img_count() const +{ + return get_file_header(); +} + +int BIN_File::get_img_height(int img) const +{ + const uint8_t* img_ptr = get_img_header_ptr(img); + const uint16_t img_header = *(unsigned __int16*)img_ptr; + if (img_ptr) { + if (img_header & 0b10) { + img_ptr += 4; + } + img_ptr += 4; + return *(uint16_t*)img_ptr; + } + return 0; +} + +int BIN_File::get_img_width(int img) const +{ + const uint8_t* img_ptr = get_img_header_ptr(img); + const uint16_t img_header = *(unsigned __int16*)img_ptr; + if (img_ptr) { + if (img_header & 0b10) { + img_ptr += 4; + } + img_ptr += 2; + return *(uint16_t*)img_ptr; + } + return 0; +} + +int BIN_File::get_img_x_offset(int img) const +{ + const uint8_t* img_ptr = get_img_header_ptr(img); + + if (img_ptr) { + const uint16_t img_header = *(unsigned __int16*)img_ptr; + if (img_header & 0b10) { + img_ptr += 4; + return *(uint16_t*)img_ptr; + } + } + return 0; +} + +int BIN_File::get_img_y_offset(int img) const +{ + const uint8_t* img_ptr = get_img_header_ptr(img); + if (img_ptr) { + const uint16_t img_header = *(unsigned __int16*)img_ptr; + if (img_header & 0b10) { + img_ptr += 2; + return *(uint16_t*)img_ptr; + } + + } + return 0; +} + +uint8_t* BIN_File::get_img_header_ptr(int img) +{ + if (img > UINT16_MAX || img > get_img_count() - 1 ) { + std::cout << "ERROR: img > img count: " << img << " > " << get_img_count() - 1; + exit(405); + } + const uint32_t header_size = 2; + uint8_t* bin_ptr = get_ptr(); + const uint32_t img_addr = *(uint32_t*)&bin_ptr[4 * img + header_size]; + return &bin_ptr[4 * img + header_size + img_addr]; +} + +uint8_t* BIN_File::get_img_data_ptr(int img) +{ + return get_img_header_ptr(img) + 10; +} + +const uint8_t* BIN_File::get_img_header_ptr(int img) const +{ + if (img > UINT16_MAX || img > get_img_count() - 1) { + std::cout << "ERROR: img > img count: " << img << " > " << get_img_count() - 1; + exit(405); + } + const uint32_t header_size = 2; + const uint8_t* bin_ptr = get_ptr(); + const uint32_t img_addr = *(uint32_t*)&bin_ptr[4 * img + header_size]; + return &bin_ptr[4 * img + header_size + img_addr]; +} + +const uint8_t* BIN_File::get_img_data_ptr(int img) const +{ + return get_img_header_ptr(img) + 10; +} diff --git a/src/bin_file.h b/src/bin_file.h new file mode 100644 index 0000000..bea49eb --- /dev/null +++ b/src/bin_file.h @@ -0,0 +1,28 @@ +#pragma once +#include "file.h" + + +class BIN_File : public File +{ +public: + BIN_File(); + BIN_File(const std::string &path); + + int get_img_count() const; + int get_img_height(int img) const; + int get_img_width(int img) const; + int get_img_x_offset(int img) const; + int get_img_y_offset(int img) const; + + uint8_t* get_img_header_ptr(int img); + uint8_t* get_img_data_ptr(int img); + const uint8_t* get_img_header_ptr(int img) const; + const uint8_t* get_img_data_ptr(int img) const; + +private: + + + +}; + + diff --git a/src/file.cpp b/src/file.cpp new file mode 100644 index 0000000..fe79171 --- /dev/null +++ b/src/file.cpp @@ -0,0 +1,112 @@ +#include +#include +#include "file.h" + +File::File() +{ + m_file_size = 0; +} + +File::File(const std::string &path ) : m_file( path ) +{ + load_data(); +} + +int File::load(const std::string& path) +{ + const std::filesystem::path new_path = path; + if (new_path == m_file && m_file_size) { + return 0; + } + return set_path(path); +} + + +int File::set_path(const std::string& path) +{ + int retval = 0; + const std::filesystem::path old_path = m_file; + m_file = path; + + if (std::filesystem::exists(m_file)) + { + retval = load_data(); + } + else { + m_file = old_path; + retval = 1; + } + + return retval; +} + +std::string File::get_full_path() const +{ + return m_file.string(); +} + +std::string File::get_directory() const +{ + return m_file.parent_path().string(); +} + +std::string File::get_filename() const +{ + return m_file.filename().string(); +} + +std::string File::get_extension() const +{ + return m_file.extension().string(); +} + +int File::load_data() +{ + std::ifstream file; + file.open( get_full_path().c_str(), std::ios_base::in | std::ios_base::binary ); + if( !file.is_open() ) { + std::cout << "ERROR: can not open file " << get_full_path() << "\n"; + exit(404); + } + + // get filesize + file.seekg( 0, std::ios_base::end ); + const std::ifstream::pos_type file_end_pos = file.tellg(); + file.seekg( 0, std::ios::beg ); + + m_file_size = static_cast( file_end_pos ); + + m_data.clear(); + m_data.resize( m_file_size ); + + file.read( ( char * )&m_data[0], static_cast(m_file_size) ); + + file.close(); + return 0; +} + +uint16_t File::get_file_header() const +{ + + return *((uint16_t*)m_data.data()); +} + +const uint8_t* File::get_ptr() const +{ + return m_data.data(); +} + +uint8_t* File::get_ptr() +{ + return m_data.data(); +} + +size_t File::get_size() const +{ + return m_file_size; +} + +uint8_t File::at(size_t pos) const +{ + return m_data.at(pos); +} diff --git a/src/file.h b/src/file.h new file mode 100644 index 0000000..436c2ea --- /dev/null +++ b/src/file.h @@ -0,0 +1,33 @@ +#pragma once + +#include +#include +#include +#include + + +class File { +public: + + File(); + File(const std::string &path); + + int load(const std::string& path); + const uint8_t* get_ptr() const; + uint8_t* get_ptr(); + std::string get_full_path() const; + std::string get_directory() const; + std::string get_filename() const; + std::string get_extension() const; + uint16_t get_file_header() const; + size_t get_size() const; + uint8_t at(size_t pos) const; + +private: + + std::filesystem::path m_file; + std::vector m_data; + size_t m_file_size; + int load_data(); + int set_path(const std::string& path); +}; diff --git a/src/helper.cpp b/src/helper.cpp new file mode 100644 index 0000000..4397e1c --- /dev/null +++ b/src/helper.cpp @@ -0,0 +1,23 @@ + +#include +#include "helper.h" + + +//00402965 +void clear_buffer(uint32_t size, uint8_t* buffer) +{ + memset(buffer, 0, size); +} + +//not present +bool bittest(int32_t value, int32_t bit) +{ + return value & (1 << bit); +} + +//not present +uint8_t BYTE2(uint32_t value) { + uint32_t ret = (value & 0x00FF0000) >> 16; + return static_cast(ret); +} + diff --git a/src/helper.h b/src/helper.h new file mode 100644 index 0000000..814cb7c --- /dev/null +++ b/src/helper.h @@ -0,0 +1,6 @@ +#pragma once +#include + +void clear_buffer(uint32_t size, uint8_t* buffer); +bool bittest(int32_t value, int32_t bit); +uint8_t BYTE2(uint32_t value); diff --git a/src/ui_bedlamtools.h b/src/ui_bedlamtools.h index edc0dc6..ef240a4 100644 --- a/src/ui_bedlamtools.h +++ b/src/ui_bedlamtools.h @@ -1,13 +1,13 @@ /******************************************************************************** -** Form generated from reading UI file 'bedlamtoolsOYWAwv.ui' +** Form generated from reading UI file 'bedlamtoolsdMvCDn.ui' ** ** Created by: Qt User Interface Compiler version 5.12.10 ** ** WARNING! All changes made in this file will be lost when recompiling UI file! ********************************************************************************/ -#ifndef BEDLAMTOOLSOYWAWV_H -#define BEDLAMTOOLSOYWAWV_H +#ifndef BEDLAMTOOLSDMVCDN_H +#define BEDLAMTOOLSDMVCDN_H #include #include @@ -103,10 +103,10 @@ class Ui_BedlamToolsClass spinBox_img = new QSpinBox(horizontalLayoutWidget); spinBox_img->setObjectName(QString::fromUtf8("spinBox_img")); - spinBox_img->setMinimum(1); + spinBox_img->setMinimum(0); spinBox_img->setMaximum(9999); spinBox_img->setSingleStep(1); - spinBox_img->setValue(1); + spinBox_img->setValue(0); horizontalLayout->addWidget(spinBox_img); @@ -259,4 +259,4 @@ namespace Ui { QT_END_NAMESPACE -#endif // BEDLAMTOOLSOYWAWV_H +#endif // BEDLAMTOOLSDMVCDN_H