load param.sfo

This commit is contained in:
InoriRus 2022-05-31 16:18:55 +10:00
parent 50b54b2607
commit 877560b7f6
54 changed files with 10562 additions and 245 deletions

View File

@ -1,4 +1,4 @@
version: 0.1.3.build-{build}
version: 0.1.4.build-{build}
image: Visual Studio 2019
environment:
matrix:

37
source/3rdparty/stb/LICENSE vendored Normal file
View File

@ -0,0 +1,37 @@
This software is available under 2 licenses -- choose whichever you prefer.
------------------------------------------------------------------------------
ALTERNATIVE A - MIT License
Copyright (c) 2017 Sean Barrett
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
------------------------------------------------------------------------------
ALTERNATIVE B - Public Domain (www.unlicense.org)
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
software, either in source code form or as a compiled binary, for any purpose,
commercial or non-commercial, and by any means.
In jurisdictions that recognize copyright laws, the author or authors of this
software dedicate any and all copyright interest in the software to the public
domain. We make this dedication for the benefit of the public at large and to
the detriment of our heirs and successors. We intend this dedication to be an
overt act of relinquishment in perpetuity of all present and future rights to
this software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

7897
source/3rdparty/stb/stb_image.h vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -82,7 +82,7 @@ if (KYTY_LINKER STREQUAL LD)
set(KYTY_LD_OPTIONS "-Wl,--image-base=0x100000000000")
endif()
project(Kyty${KYTY_PROJECT_NAME}${CMAKE_BUILD_TYPE}${KYTY_COMPILER} VERSION 0.1.3)
project(Kyty${KYTY_PROJECT_NAME}${CMAKE_BUILD_TYPE}${KYTY_COMPILER} VERSION 0.1.4)
include(src_script.cmake)

View File

@ -5,6 +5,7 @@ file(GLOB emulator_src
src/Graphics/*.cpp
src/Graphics/Objects/*.cpp
src/Kernel/*.cpp
src/Loader/*.cpp
include/*.h
)
@ -27,6 +28,7 @@ list(APPEND inc_headers
${CMAKE_SOURCE_DIR}/3rdparty/easy_profiler/include
${CMAKE_SOURCE_DIR}/3rdparty/xxhash/include
${CMAKE_SOURCE_DIR}/3rdparty/cpuinfo/include
${CMAKE_SOURCE_DIR}/3rdparty/stb
)
if (MSVC AND CLANG)

View File

@ -3,8 +3,8 @@
#include "Kyty/Core/Common.h"
#if (KYTY_COMPILER == KYTY_COMPILER_CLANG || KYTY_COMPILER == KYTY_COMPILER_MINGW) && KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS && KYTY_BITNESS == 64 && \
KYTY_ENDIAN == KYTY_ENDIAN_LITTLE && KYTY_ABI == KYTY_ABI_X86_64 && KYTY_PROJECT == KYTY_PROJECT_EMULATOR
#if (KYTY_COMPILER == KYTY_COMPILER_CLANG || KYTY_COMPILER == KYTY_COMPILER_MINGW) && KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS && \
KYTY_BITNESS == 64 && KYTY_ENDIAN == KYTY_ENDIAN_LITTLE && KYTY_ABI == KYTY_ABI_X86_64 && KYTY_PROJECT == KYTY_PROJECT_EMULATOR
#define KYTY_EMU_ENABLED
#endif

View File

@ -0,0 +1,312 @@
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_COLOR_H_
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_COLOR_H_
#include "Kyty/Core/Common.h"
#include "Kyty/Math/MathAll.h"
#include "Emulator/Common.h"
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs::Graphics {
using rgba32_t = uint32_t;
struct ColorHsv
{
explicit ColorHsv(float h = 0.0f, float s = 0.0f, float v = 0.0f): H(h), S(s), V(v) {}
float H; /*NOLINT(readability-identifier-naming)*/ // [0..360]
float S; /*NOLINT(readability-identifier-naming)*/ // [0..1]
float V; /*NOLINT(readability-identifier-naming)*/ // [0..1]
};
constexpr float COLOR_LAB_L_MIN = (0.0f);
constexpr float COLOR_LAB_L_MAX = (100.0f);
constexpr float COLOR_LAB_A_MIN = (-128.0f);
constexpr float COLOR_LAB_A_MAX = (+127.0f);
constexpr float COLOR_LAB_B_MIN = (-128.0f);
constexpr float COLOR_LAB_B_MAX = (+127.0f);
using lab64_t = uint64_t;
constexpr lab64_t COLOR_LAB_L_BITS = 16u;
constexpr lab64_t COLOR_LAB_A_BITS = 16u;
constexpr lab64_t COLOR_LAB_B_BITS = 16u;
constexpr lab64_t COLOR_LAB_L_MASK = ((static_cast<lab64_t>(1) << (COLOR_LAB_L_BITS)) - static_cast<lab64_t>(1));
constexpr lab64_t COLOR_LAB_A_MASK = ((static_cast<lab64_t>(1) << (COLOR_LAB_A_BITS)) - static_cast<lab64_t>(1));
constexpr lab64_t COLOR_LAB_B_MASK = ((static_cast<lab64_t>(1) << (COLOR_LAB_B_BITS)) - static_cast<lab64_t>(1));
struct ColorLab
{
ColorLab() = default;
ColorLab(float l, float a, float b): L(l), A(a), B(b) {}
float L = 0; /*NOLINT(readability-identifier-naming)*/ // [COLOR_LAB_L_MIN..COLOR_LAB_L_MAX]
float A = 0; /*NOLINT(readability-identifier-naming)*/ // [COLOR_LAB_A_MIN..COLOR_LAB_A_MAX]
float B = 0; /*NOLINT(readability-identifier-naming)*/ // [COLOR_LAB_B_MIN..COLOR_LAB_B_MAX]
explicit ColorLab(lab64_t lab32)
: ColorLab((static_cast<float>((lab32 >> (0u)) & COLOR_LAB_L_MASK) / static_cast<float>(COLOR_LAB_L_MASK)) *
(COLOR_LAB_L_MAX - COLOR_LAB_L_MIN) +
COLOR_LAB_L_MIN,
(static_cast<float>((lab32 >> (COLOR_LAB_L_BITS)) & COLOR_LAB_A_MASK) / static_cast<float>(COLOR_LAB_A_MASK)) *
(COLOR_LAB_A_MAX - COLOR_LAB_A_MIN) +
COLOR_LAB_A_MIN,
(static_cast<float>((lab32 >> (COLOR_LAB_L_BITS + COLOR_LAB_A_BITS)) & COLOR_LAB_B_MASK) /
static_cast<float>(COLOR_LAB_B_MASK)) *
(COLOR_LAB_B_MAX - COLOR_LAB_B_MIN) +
COLOR_LAB_B_MIN)
{
}
[[nodiscard]] lab64_t ToLab64() const
{
auto l = static_cast<int64_t>(
Math::math_round(static_cast<float>(COLOR_LAB_L_MASK) * ((L - COLOR_LAB_L_MIN) / (COLOR_LAB_L_MAX - COLOR_LAB_L_MIN))));
if (l < 0)
{
l = 0;
}
if (l > static_cast<int64_t>(COLOR_LAB_L_MASK))
{
l = static_cast<int64_t>(COLOR_LAB_L_MASK);
}
auto a = static_cast<int64_t>(
Math::math_round(static_cast<float>(COLOR_LAB_A_MASK) * ((A - COLOR_LAB_A_MIN) / (COLOR_LAB_A_MAX - COLOR_LAB_A_MIN))));
if (a < 0)
{
a = 0;
}
if (a > static_cast<int64_t>(COLOR_LAB_A_MASK))
{
a = static_cast<int64_t>(COLOR_LAB_A_MASK);
}
auto b = static_cast<int64_t>(
Math::math_round(static_cast<float>(COLOR_LAB_B_MASK) * ((B - COLOR_LAB_B_MIN) / (COLOR_LAB_B_MAX - COLOR_LAB_B_MIN))));
if (b < 0)
{
b = 0;
}
if (b > static_cast<int64_t>(COLOR_LAB_B_MASK))
{
b = static_cast<int64_t>(COLOR_LAB_B_MASK);
}
return (static_cast<lab64_t>(l) << 0u) | (static_cast<lab64_t>(a) << (COLOR_LAB_L_BITS)) |
(static_cast<lab64_t>(b) << (COLOR_LAB_L_BITS + COLOR_LAB_A_BITS));
}
[[nodiscard]] float Distance(const ColorLab& other) const
{
float d1 = L - other.L;
float d2 = A - other.A;
float d3 = B - other.B;
return sqrtf(d1 * d1 + d2 * d2 + d3 * d3);
}
bool operator==(const ColorLab& c) const { return (L == c.L && A == c.A && B == c.B); }
bool operator!=(const ColorLab& c) const { return (L != c.L || A != c.A || B != c.B); }
void Clip();
};
struct ColorXyz
{
float X; /*NOLINT(readability-identifier-naming)*/
float Y; /*NOLINT(readability-identifier-naming)*/
float Z; /*NOLINT(readability-identifier-naming)*/
[[nodiscard]] float Distance(const ColorXyz& other) const
{
float d1 = X - other.X;
float d2 = Y - other.Y;
float d3 = Z - other.Z;
return sqrtf(d1 * d1 + d2 * d2 + d3 * d3);
}
};
inline rgba32_t Rgb(int r, int g, int b, int a = 255)
{
return (static_cast<uint32_t>(r) << 0u) | (static_cast<uint32_t>(g) << 8u) | (static_cast<uint32_t>(b) << 16u) |
(static_cast<uint32_t>(a) << 24u);
}
inline int RgbToRed(rgba32_t c)
{
return static_cast<int>(c & 0xffU);
}
inline int RgbToGreen(rgba32_t c)
{
return static_cast<int>((c >> 8u) & 0xffU);
}
inline int RgbToBlue(rgba32_t c)
{
return static_cast<int>((c >> 16u) & 0xffU);
}
inline int RgbToAlpha(rgba32_t c)
{
return static_cast<int>((c >> 24u) & 0xffU);
}
inline float RgbDistance(rgba32_t a, rgba32_t b)
{
int dr = RgbToRed(a) - RgbToRed(b);
int dg = RgbToGreen(a) - RgbToGreen(b);
int db = RgbToBlue(a) - RgbToBlue(b);
return sqrtf(static_cast<float>(dr * dr + dg * dg + db * db));
}
class Color final
{
public:
Color() = default;
~Color() = default;
Color(float r, float g, float b, float a = 1.0f): m_v(r, g, b, a) {}
explicit Color(const vec4& av): m_v(av) {}
KYTY_CLASS_DEFAULT_COPY(Color);
static Color FromRgb(int r, int g, int b, int a = 255)
{
return {static_cast<float>(r) / 255.0f, static_cast<float>(g) / 255.0f, static_cast<float>(b) / 255.0f,
static_cast<float>(a) / 255.0f};
}
explicit Color(rgba32_t rgba32)
: m_v(static_cast<float>((rgba32 >> 0u) & 0xffU) / 255.0f, static_cast<float>((rgba32 >> 8u) & 0xffU) / 255.0f,
static_cast<float>((rgba32 >> 16u) & 0xffU) / 255.0f, static_cast<float>((rgba32 >> 24u) & 0xffU) / 255.0f)
{
}
[[nodiscard]] rgba32_t ToRgba32() const
{
return (static_cast<uint32_t>(Red()) << 0u) | (static_cast<uint32_t>(Green()) << 8u) | (static_cast<uint32_t>(Blue()) << 16u) |
(static_cast<uint32_t>(Alpha()) << 24u);
}
[[nodiscard]] ColorXyz ToXyz() const;
[[nodiscard]] ColorLab ToLab() const;
[[nodiscard]] Color ToLinear() const;
[[nodiscard]] Color ToAdobeRGB() const;
void ToHcl(float* h, float* c, float* l) const;
[[nodiscard]] ColorHsv ToHsv() const;
[[nodiscard]] Color AlphaBlendOver(const Color& bg) const
{
return {m_v.r * m_v.a + bg.m_v.r * (1.0f - m_v.a), m_v.g * m_v.a + bg.m_v.g * (1.0f - m_v.a),
m_v.b * m_v.a + bg.m_v.b * (1.0f - m_v.a), 1.0f};
}
static Color FromLab(const ColorLab& l);
static Color FromXyz(const ColorXyz& l);
static Color FromLinear(const Color& l);
static Color FromAdobeRGB(const Color& c);
static Color FromHsl(float h, float s, float l, float a = 1.0f);
static Color FromHsv(const ColorHsv& l);
static Color Black() { return FromRgb(0, 0, 0); }
static Color White() { return FromRgb(255, 255, 255); }
void Clip();
[[nodiscard]] bool InGamut() const;
[[nodiscard]] float Distance(const Color& other) const
{
float d1 = m_v.x - other.m_v.x;
float d2 = m_v.y - other.m_v.y;
float d3 = m_v.z - other.m_v.z;
return sqrtf(d1 * d1 + d2 * d2 + d3 * d3);
}
[[nodiscard]] uint8_t Red() const
{
int t = static_cast<int>(Math::math_round(m_v.r * 255.0f));
if (t < 0)
{
t = 0;
}
if (t > 255)
{
t = 255;
}
return t;
}
[[nodiscard]] uint8_t Green() const
{
int t = static_cast<int>(Math::math_round(m_v.g * 255.0f));
if (t < 0)
{
t = 0;
}
if (t > 255)
{
t = 255;
}
return t;
}
[[nodiscard]] uint8_t Blue() const
{
int t = static_cast<int>(Math::math_round(m_v.b * 255.0f));
if (t < 0)
{
t = 0;
}
if (t > 255)
{
t = 255;
}
return t;
}
[[nodiscard]] uint8_t Alpha() const
{
int t = static_cast<int>(Math::math_round(m_v.a * 255.0f));
if (t < 0)
{
t = 0;
}
if (t > 255)
{
t = 255;
}
return t;
}
[[nodiscard]] bool IsBlack() const { return (m_v.r == 0.0f && m_v.g == 0.0f && m_v.b == 0.0f); }
[[nodiscard]] bool IsWhite() const { return (m_v.r == 1.0f && m_v.g == 1.0f && m_v.b == 1.0f); }
[[nodiscard]] vec3 Rgb() const { return m_v.Rgb(); }
[[nodiscard]] vec4 Rgba() const { return m_v; }
[[nodiscard]] const float& R() const { return m_v.r; }
[[nodiscard]] const float& G() const { return m_v.g; }
[[nodiscard]] const float& B() const { return m_v.b; }
[[nodiscard]] const float& A() const { return m_v.a; }
float& R() { return m_v.r; }
float& G() { return m_v.g; }
float& B() { return m_v.b; }
float& A() { return m_v.a; }
friend bool operator==(const Color& v1, const Color& v2) { return v1.m_v == v2.m_v; }
friend bool operator!=(const Color& v1, const Color& v2) { return v1.m_v != v2.m_v; }
private:
vec4 m_v;
};
} // namespace Kyty::Libs::Graphics
using Color = Kyty::Libs::Graphics::Color;
#endif // KYTY_EMU_ENABLED
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_COLOR_H_ */

View File

@ -0,0 +1,86 @@
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_IMAGE_H_
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_IMAGE_H_
#include "Kyty/Core/Common.h"
#include "Kyty/Core/String.h"
#include "Kyty/Math/MathAll.h"
#include "Emulator/Common.h"
#include "Emulator/Graphics/Color.h"
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs::Graphics {
enum class ImageOrder
{
Unknown,
Rgb,
Rgba,
Argb,
Bgr,
Bgra,
Abgr,
Alpha
};
class ImagePrivate;
class Image
{
public:
explicit Image(const String& name);
virtual ~Image();
[[nodiscard]] Image* Clone() const;
void LoadSdl(void* sdl);
void Load();
void Load(const String& file_name);
void Save(const String& file_name) const;
[[nodiscard]] const String& GetName() const { return m_name; }
[[nodiscard]] uint32_t GetWidth() const { return m_width; }
[[nodiscard]] uint32_t GetHeight() const { return m_height; }
[[nodiscard]] uint32_t GetPitch() const { return m_pitch; }
[[nodiscard]] int GetBitsPerPixel() const { return m_bits_per_pixel; }
[[nodiscard]] int GetBytesPerPixel() const { return static_cast<int>(static_cast<unsigned int>(m_bits_per_pixel) >> 3u); }
[[nodiscard]] int GetAlignment() const
{
static const int p[] = {8, 1, 2, 1, 4, 1, 2, 1};
return p[m_pitch & 7u];
}
[[nodiscard]] ImageOrder GetOrder() const { return m_order; }
[[nodiscard]] const void* GetData() const { return m_pixels; }
[[nodiscard]] void* GetSdlSurface() const;
void DbgPrint() const;
bool DbgEqual(const Image* img) const;
static Image* Create(const String& name, uint32_t width, uint32_t height, int bits_per_pixel);
static Math::Size GetSize(const String& name);
bool BlitTo(Image* img, const Math::Rect& src, const Math::Rect& dst) const;
[[nodiscard]] rgba32_t GetPixel(uint32_t x, uint32_t y) const;
[[nodiscard]] rgba32_t GetAvgPixel(uint32_t x, uint32_t y, uint32_t width, uint32_t height) const;
void SetPixel(uint32_t x, uint32_t y, rgba32_t color);
KYTY_CLASS_NO_COPY(Image);
private:
String m_name;
uint32_t m_width = 0;
uint32_t m_height = 0;
uint32_t m_pitch = 0;
int m_bits_per_pixel = 0;
ImageOrder m_order = ImageOrder::Unknown;
void* m_pixels = nullptr;
ImagePrivate* m_image = nullptr;
};
} // namespace Kyty::Libs::Graphics
#endif // KYTY_EMU_ENABLED
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_IMAGE_H_ */

View File

@ -4,7 +4,7 @@
#include "Kyty/Core/String.h"
#include "Emulator/Common.h"
#include "Emulator/Timer.h" // IWYU pragma: keep
#include "Emulator/Loader/Timer.h" // IWYU pragma: keep
#ifdef KYTY_EMU_ENABLED

View File

@ -1,5 +1,5 @@
#ifndef EMULATOR_INCLUDE_EMULATOR_ELF_H_
#define EMULATOR_INCLUDE_EMULATOR_ELF_H_
#ifndef EMULATOR_INCLUDE_EMULATOR_LOADER_ELF_H_
#define EMULATOR_INCLUDE_EMULATOR_LOADER_ELF_H_
#include "Kyty/Core/Common.h"
#include "Kyty/Core/String.h"
@ -306,4 +306,4 @@ private:
#endif // KYTY_EMU_ENABLED
#endif /* EMULATOR_INCLUDE_EMULATOR_ELF_H_ */
#endif /* EMULATOR_INCLUDE_EMULATOR_LOADER_ELF_H_ */

View File

@ -1,5 +1,5 @@
#ifndef EMULATOR_INCLUDE_EMULATOR_JIT_H_
#define EMULATOR_INCLUDE_EMULATOR_JIT_H_
#ifndef EMULATOR_INCLUDE_EMULATOR_LOADER_JIT_H_
#define EMULATOR_INCLUDE_EMULATOR_LOADER_JIT_H_
#include "Emulator/Common.h"
@ -147,4 +147,4 @@ struct SafeCall
#endif // KYTY_EMU_ENABLED
#endif /* EMULATOR_INCLUDE_EMULATOR_JIT_H_ */
#endif /* EMULATOR_INCLUDE_EMULATOR_LOADER_JIT_H_ */

View File

@ -0,0 +1,27 @@
#ifndef EMULATOR_INCLUDE_EMULATOR_LOADER_PARAM_H_
#define EMULATOR_INCLUDE_EMULATOR_LOADER_PARAM_H_
#include "Kyty/Core/Common.h"
#include "Kyty/Core/String.h"
#include "Emulator/Common.h"
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs::Graphics {
class Image;
} // namespace Kyty::Libs::Graphics
namespace Kyty::Loader {
void ParamSfoLoad(const String& file_name);
bool ParamSfoGetInt(const char* name, int32_t* value);
bool ParamSfoGetString(const char* name, String* value);
bool ParamSfoGetString(const char* name, char* value, size_t value_size);
Libs::Graphics::Image* ParamSfoGetIcon();
} // namespace Kyty::Loader
#endif // KYTY_EMU_ENABLED
#endif /* EMULATOR_INCLUDE_EMULATOR_LOADER_PARAM_H_ */

View File

@ -1,5 +1,5 @@
#ifndef EMULATOR_INCLUDE_EMULATOR_RUNTIMELINKER_H_
#define EMULATOR_INCLUDE_EMULATOR_RUNTIMELINKER_H_
#ifndef EMULATOR_INCLUDE_EMULATOR_LOADER_RUNTIMELINKER_H_
#define EMULATOR_INCLUDE_EMULATOR_LOADER_RUNTIMELINKER_H_
#include "Kyty/Core/Common.h"
#include "Kyty/Core/Hashmap.h"
@ -8,7 +8,7 @@
#include "Kyty/Core/Vector.h"
#include "Emulator/Common.h"
#include "Emulator/SymbolDatabase.h"
#include "Emulator/Loader/SymbolDatabase.h"
#ifdef KYTY_EMU_ENABLED
@ -186,4 +186,4 @@ private:
#endif // KYTY_EMU_ENABLED
#endif /* EMULATOR_INCLUDE_EMULATOR_RUNTIMELINKER_H_ */
#endif /* EMULATOR_INCLUDE_EMULATOR_LOADER_RUNTIMELINKER_H_ */

View File

@ -1,5 +1,5 @@
#ifndef EMULATOR_INCLUDE_EMULATOR_SYMBOLDATABASE_H_
#define EMULATOR_INCLUDE_EMULATOR_SYMBOLDATABASE_H_
#ifndef EMULATOR_INCLUDE_EMULATOR_LOADER_SYMBOLDATABASE_H_
#define EMULATOR_INCLUDE_EMULATOR_LOADER_SYMBOLDATABASE_H_
#include "Kyty/Core/Common.h"
#include "Kyty/Core/Hashmap.h"
@ -65,4 +65,4 @@ private:
#endif // KYTY_EMU_ENABLED
#endif /* EMULATOR_INCLUDE_EMULATOR_SYMBOLDATABASE_H_ */
#endif /* EMULATOR_INCLUDE_EMULATOR_LOADER_SYMBOLDATABASE_H_ */

View File

@ -1,5 +1,5 @@
#ifndef EMULATOR_INCLUDE_EMULATOR_TIMER_H_
#define EMULATOR_INCLUDE_EMULATOR_TIMER_H_
#ifndef EMULATOR_INCLUDE_EMULATOR_LOADER_TIMER_H_
#define EMULATOR_INCLUDE_EMULATOR_LOADER_TIMER_H_
#include "Kyty/Core/Common.h"
#include "Kyty/Core/DateTime.h"
@ -23,4 +23,4 @@ uint64_t GetFrequency();
#endif // KYTY_EMU_ENABLED
#endif /* EMULATOR_INCLUDE_EMULATOR_TIMER_H_ */
#endif /* EMULATOR_INCLUDE_EMULATOR_LOADER_TIMER_H_ */

View File

@ -1,5 +1,5 @@
#ifndef EMULATOR_INCLUDE_EMULATOR_VIRTUALMEMORY_H_
#define EMULATOR_INCLUDE_EMULATOR_VIRTUALMEMORY_H_
#ifndef EMULATOR_INCLUDE_EMULATOR_LOADER_VIRTUALMEMORY_H_
#define EMULATOR_INCLUDE_EMULATOR_LOADER_VIRTUALMEMORY_H_
#include "Kyty/Core/Common.h"
#include "Kyty/Core/String.h"
@ -112,4 +112,4 @@ bool PatchReplace(uint64_t vaddr, uint64_t value);
#endif // KYTY_EMU_ENABLED
#endif /* EMULATOR_INCLUDE_EMULATOR_VIRTUALMEMORY_H_ */
#endif /* EMULATOR_INCLUDE_EMULATOR_LOADER_VIRTUALMEMORY_H_ */

View File

@ -4,15 +4,17 @@
#include "Emulator/Common.h"
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Emulator {
#ifdef KYTY_EMU_ENABLED
void kyty_reg();
#endif
KYTY_SUBSYSTEM_INIT(Emulator)
{
#ifdef KYTY_EMU_ENABLED
kyty_reg();
#endif
}
KYTY_SUBSYSTEM_UNEXPECTED_SHUTDOWN(Emulator) {}
@ -20,5 +22,3 @@ KYTY_SUBSYSTEM_UNEXPECTED_SHUTDOWN(Emulator) {}
KYTY_SUBSYSTEM_DESTROY(Emulator) {}
} // namespace Kyty::Emulator
#endif // KYTY_EMU_ENABLED

View File

@ -0,0 +1,670 @@
#include "Emulator/Graphics/Color.h"
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs::Graphics {
static void rgb_to_lab(const Color& c, ColorLab* l)
{
double var_r = c.R();
double var_g = c.G();
double var_b = c.B();
if (var_r > 0.04045)
{
var_r = pow(((var_r + 0.055) / 1.055), 2.4);
} else
{
var_r = var_r / 12.92;
}
if (var_g > 0.04045)
{
var_g = pow(((var_g + 0.055) / 1.055), 2.4);
} else
{
var_g = var_g / 12.92;
}
if (var_b > 0.04045)
{
var_b = pow(((var_b + 0.055) / 1.055), 2.4);
} else
{
var_b = var_b / 12.92;
}
var_r = var_r * 100.0;
var_g = var_g * 100.0;
var_b = var_b * 100.0;
// Observer. = 2°, Illuminant = D65
double x = var_r * 0.4124 + var_g * 0.3576 + var_b * 0.1805;
double y = var_r * 0.2126 + var_g * 0.7152 + var_b * 0.0722;
double z = var_r * 0.0193 + var_g * 0.1192 + var_b * 0.9505;
double ref_x = 95.047;
double ref_y = 100.000;
double ref_z = 108.883;
double var_x = x / ref_x;
double var_y = y / ref_y;
double var_z = z / ref_z;
if (var_x > 0.008856)
{
var_x = pow(var_x, (1.0 / 3.0));
} else
{
var_x = (7.787 * var_x) + (16.0 / 116.0);
}
if (var_y > 0.008856)
{
var_y = pow(var_y, (1.0 / 3.0));
} else
{
var_y = (7.787 * var_y) + (16.0 / 116.0);
}
if (var_z > 0.008856)
{
var_z = pow(var_z, (1.0 / 3.0));
} else
{
var_z = (7.787 * var_z) + (16.0 / 116.0);
}
l->L = static_cast<float>((116.0 * var_y) - 16.0);
l->A = static_cast<float>(500.0 * (var_x - var_y));
l->B = static_cast<float>(200.0 * (var_y - var_z));
}
static void lab_to_rgb(const ColorLab& l, Color* c)
{
double var_y = (l.L + 16.0) / 116.0;
double var_x = l.A / 500.0 + var_y;
double var_z = var_y - l.B / 200.0;
if (pow(var_y, 3) > 0.008856)
{
var_y = pow(var_y, 3);
} else
{
var_y = (var_y - 16.0 / 116.0) / 7.787;
}
if (pow(var_x, 3) > 0.008856)
{
var_x = pow(var_x, 3);
} else
{
var_x = (var_x - 16.0 / 116.0) / 7.787;
}
if (pow(var_z, 3) > 0.008856)
{
var_z = pow(var_z, 3);
} else
{
var_z = (var_z - 16.0 / 116.0) / 7.787;
}
double ref_x = 95.047;
double ref_y = 100.000;
double ref_z = 108.883;
// Observer. = 2°, Illuminant = D65
double x = ref_x * var_x;
double y = ref_y * var_y;
double z = ref_z * var_z;
var_x = x / 100.0;
var_y = y / 100.0;
var_z = z / 100.0;
double var_r = var_x * 3.2406 + var_y * -1.5372 + var_z * -0.4986;
double var_g = var_x * -0.9689 + var_y * 1.8758 + var_z * 0.0415;
double var_b = var_x * 0.0557 + var_y * -0.2040 + var_z * 1.0570;
if (var_r > 0.0031308)
{
var_r = 1.055 * (pow(var_r, (1.0 / 2.4))) - 0.055;
} else
{
var_r = 12.92 * var_r;
}
if (var_g > 0.0031308)
{
var_g = 1.055 * (pow(var_g, (1.0 / 2.4))) - 0.055;
} else
{
var_g = 12.92 * var_g;
}
if (var_b > 0.0031308)
{
var_b = 1.055 * (pow(var_b, (1.0 / 2.4))) - 0.055;
} else
{
var_b = 12.92 * var_b;
}
c->R() = static_cast<float>(var_r);
c->G() = static_cast<float>(var_g);
c->B() = static_cast<float>(var_b);
}
static void xyz_to_rgb(const ColorXyz& l, Color* c)
{
double x = l.X;
double y = l.Y;
double z = l.Z;
double var_x = x / 100.0;
double var_y = y / 100.0;
double var_z = z / 100.0;
double var_r = var_x * 3.2406 + var_y * -1.5372 + var_z * -0.4986;
double var_g = var_x * -0.9689 + var_y * 1.8758 + var_z * 0.0415;
double var_b = var_x * 0.0557 + var_y * -0.2040 + var_z * 1.0570;
if (var_r > 0.0031308)
{
var_r = 1.055 * (pow(var_r, (1.0 / 2.4))) - 0.055;
} else
{
var_r = 12.92 * var_r;
}
if (var_g > 0.0031308)
{
var_g = 1.055 * (pow(var_g, (1.0 / 2.4))) - 0.055;
} else
{
var_g = 12.92 * var_g;
}
if (var_b > 0.0031308)
{
var_b = 1.055 * (pow(var_b, (1.0 / 2.4))) - 0.055;
} else
{
var_b = 12.92 * var_b;
}
c->R() = static_cast<float>(var_r);
c->G() = static_cast<float>(var_g);
c->B() = static_cast<float>(var_b);
}
static void xyz_to_adobe_rgb(const ColorXyz& l, Color* c)
{
double x_a = l.X * 1.6;
double y_a = l.Y * 1.6;
double z_a = l.Z * 1.6;
double x_w = 152.07;
double y_w = 160.00;
double z_w = 174.25;
double x_k = 0.5282;
double y_k = 0.5557;
double z_k = 0.6052;
double x = ((x_a - x_k) / (x_w - x_k)) * (x_w / y_w);
double y = ((y_a - y_k) / (y_w - y_k));
double z = ((z_a - z_k) / (z_w - z_k)) * (z_w / y_w);
double r = x * 2.04159 + y * -0.56501 + z * -0.34473;
double g = x * -0.96924 + y * 1.87597 + z * 0.04156;
double b = x * 0.01344 + y * -0.11836 + z * 1.01517;
r = pow(r, (1.0 / 2.19921875));
g = pow(g, (1.0 / 2.19921875));
b = pow(b, (1.0 / 2.19921875));
c->R() = static_cast<float>(r);
c->G() = static_cast<float>(g);
c->B() = static_cast<float>(b);
}
static void adobe_rgb_to_xyz(const Color& c, ColorXyz* l)
{
double x_w = 152.07;
double y_w = 160.00;
double z_w = 174.25;
double x_k = 0.5282;
double y_k = 0.5557;
double z_k = 0.6052;
double r = c.R();
double g = c.G();
double b = c.B();
r = pow(r, (2.19921875));
g = pow(g, (2.19921875));
b = pow(b, (2.19921875));
double x = r * 0.57667 + g * 0.18556 + b * 0.18823;
double y = r * 0.29734 + g * 0.62736 + b * 0.07529;
double z = r * 0.02703 + g * 0.07069 + b * 0.99134;
double x_a = x * (x_w - x_k) * (y_w / x_w) + x_k;
double y_a = y * (y_w - y_k) * (y_w / y_w) + y_k;
double z_a = z * (z_w - z_k) * (y_w / z_w) + z_k;
l->X = static_cast<float>(x_a / 1.6);
l->Y = static_cast<float>(y_a / 1.6);
l->Z = static_cast<float>(z_a / 1.6);
}
static void linear_to_rgb(const Color& l, Color* c)
{
double var_r = l.R();
double var_g = l.G();
double var_b = l.B();
if (var_r > 0.0031308)
{
var_r = 1.055 * (pow(var_r, (1.0 / 2.4))) - 0.055;
} else
{
var_r = 12.92 * var_r;
}
if (var_g > 0.0031308)
{
var_g = 1.055 * (pow(var_g, (1.0 / 2.4))) - 0.055;
} else
{
var_g = 12.92 * var_g;
}
if (var_b > 0.0031308)
{
var_b = 1.055 * (pow(var_b, (1.0 / 2.4))) - 0.055;
} else
{
var_b = 12.92 * var_b;
}
c->R() = static_cast<float>(var_r); // if (c.r < 0.0) c.r = 0.0; if (c.r > 1.0) c.r = 1.0;
c->G() = static_cast<float>(var_g); // if (c.g < 0.0) c.g = 0.0; if (c.g > 1.0) c.g = 1.0;
c->B() = static_cast<float>(var_b); // if (c.b < 0.0) c.b = 0.0; if (c.b > 1.0) c.b = 1.0;
}
static void rgb_to_xyz(const Color& c, ColorXyz* l)
{
double var_r = c.R();
double var_g = c.G();
double var_b = c.B();
if (var_r > 0.04045)
{
var_r = pow(((var_r + 0.055) / 1.055), 2.4);
} else
{
var_r = var_r / 12.92;
}
if (var_g > 0.04045)
{
var_g = pow(((var_g + 0.055) / 1.055), 2.4);
} else
{
var_g = var_g / 12.92;
}
if (var_b > 0.04045)
{
var_b = pow(((var_b + 0.055) / 1.055), 2.4);
} else
{
var_b = var_b / 12.92;
}
var_r = var_r * 100.0;
var_g = var_g * 100.0;
var_b = var_b * 100.0;
// Observer. = 2°, Illuminant = D65
double x = var_r * 0.4124 + var_g * 0.3576 + var_b * 0.1805;
double y = var_r * 0.2126 + var_g * 0.7152 + var_b * 0.0722;
double z = var_r * 0.0193 + var_g * 0.1192 + var_b * 0.9505;
l->X = static_cast<float>(x);
l->Y = static_cast<float>(y);
l->Z = static_cast<float>(z);
}
static void rgb_to_linear(const Color& c, Color* l)
{
double var_r = c.R();
double var_g = c.G();
double var_b = c.B();
if (var_r > 0.04045)
{
var_r = pow(((var_r + 0.055) / 1.055), 2.4);
} else
{
var_r = var_r / 12.92;
}
if (var_g > 0.04045)
{
var_g = pow(((var_g + 0.055) / 1.055), 2.4);
} else
{
var_g = var_g / 12.92;
}
if (var_b > 0.04045)
{
var_b = pow(((var_b + 0.055) / 1.055), 2.4);
} else
{
var_b = var_b / 12.92;
}
l->R() = static_cast<float>(var_r);
l->G() = static_cast<float>(var_g);
l->B() = static_cast<float>(var_b);
}
static float Max(float x, float y)
{
if (x < y)
{
return y;
}
return x;
}
static float Min(float x, float y)
{
if (x < y)
{
return x;
}
return y;
}
void rgb_to_hsv(const Color& c, ColorHsv* l)
{
float r = c.R();
float g = c.G();
float b = c.B();
float m_x = Max(r, Max(g, b));
float mn = Min(r, Min(g, b));
if (m_x == mn)
{
l->H = 0.0f;
} else if (m_x == r)
{
if (g >= b)
{
l->H = 60.0f * (g - b) / (m_x - mn);
} else
{
l->H = 60.0f * (g - b) / (m_x - mn) + 360;
}
} else if (m_x == g)
{
l->H = 60.0f * (b - r) / (m_x - mn) + 120;
} else
{
l->H = 60.0f * (r - g) / (m_x - mn) + 240;
}
l->S = (m_x == 0.0f) ? 0.0f : 1.0f - mn / m_x;
l->V = m_x;
}
void hsv_to_rgb(const ColorHsv& l, Color* c)
{
float h = fmodf((l.H >= 0.0 ? l.H : l.H + 360.0f) / 60.0f, 6.0f);
float cc = l.V * l.S;
float x = cc * (1.0f - fabsf(fmodf(h, 2.0f) - 1.0f));
float r = 0;
float g = 0;
float b = 0;
if (0.0f <= h && h <= 1.0f)
{
r = cc;
g = x;
} else if (1.0f <= h && h <= 2.0f)
{
r = x;
g = cc;
} else if (2.0f <= h && h <= 3.0f)
{
g = cc;
b = x;
} else if (3.0f <= h && h <= 4.0f)
{
g = x;
b = cc;
} else if (4.0f <= h && h <= 5.0f)
{
r = x;
b = cc;
} else if (5.0f <= h && h <= 6.0f)
{
r = cc;
b = x;
}
float m = l.V - cc;
c->R() = r + m;
c->G() = g + m;
c->B() = b + m;
}
void rgb_to_hcl(float r, float g, float b, float* h, float* c, float* l)
{
float m_x = Max(r, Max(g, b));
float mn = Min(r, Min(g, b));
float cc = m_x - mn;
if (cc == 0)
{
*h = -1;
} else if (m_x == r)
{
if (g >= b)
{
*h = ((g - b) / cc);
} else
{
*h = ((g - b) / cc) + 6;
}
} else if (m_x == g)
{
*h = ((b - r) / cc) + 2;
} else
{
*h = ((r - g) / cc) + 4;
}
if (*h > 0)
{
*h *= 60;
}
*c = cc;
*l = static_cast<float>(0.3 * r + 0.59 * g + 0.11 * b);
}
bool Color::InGamut() const
{
return !(R() < 0.0f || R() > 1.0f || G() < 0.0f || G() > 1.0f || B() < 0.0f || B() > 1.0f || A() < 0.0f || A() > 1.0f);
}
ColorXyz Color::ToXyz() const
{
ColorXyz r {};
rgb_to_xyz(*this, &r);
return r;
}
ColorLab Color::ToLab() const
{
ColorLab r;
rgb_to_lab(*this, &r);
return r;
}
Color Color::FromLab(const ColorLab& l)
{
Color r {};
lab_to_rgb(l, &r);
r.A() = 1.0f;
return r;
}
Color Color::FromXyz(const ColorXyz& l)
{
Color r {};
xyz_to_rgb(l, &r);
r.A() = 1.0f;
return r;
}
vec3 HUEToRGB(float h)
{
h = fmodf(h, 1.0f);
if (h < 0.0f)
{
h += 1.0f;
}
float r = fabsf(h * 6.0f - 3.0f) - 1.0f;
float g = 2 - fabsf(h * 6.0f - 2.0f);
float b = 2 - fabsf(h * 6.0f - 4.0f);
return Math::math_clamp(vec3(r, g, b), 0.0f, 1.0f);
}
// All values are all in range [0..1]
Color Color::FromHsl(float h, float s, float l, float a)
{
vec3 r_g_b = HUEToRGB(h);
float cc = (1.0f - fabsf(2.0f * l - 1.0f)) * s;
vec3 rgb = (r_g_b - 0.5f) * cc + l;
return {rgb.r, rgb.g, rgb.b, a};
}
void Color::ToHcl(float* h, float* c, float* l) const
{
rgb_to_hcl(Red(), Green(), Blue(), h, c, l);
}
ColorHsv Color::ToHsv() const
{
ColorHsv r;
rgb_to_hsv(*this, &r);
return r;
}
Color Color::FromHsv(const ColorHsv& l)
{
Color r {};
hsv_to_rgb(l, &r);
r.A() = 1.0f;
return r;
}
void Color::Clip()
{
if (R() < 0.0f)
{
R() = 0.0f;
}
if (R() > 1.0f)
{
R() = 1.0f;
}
if (G() < 0.0f)
{
G() = 0.0f;
}
if (G() > 1.0f)
{
G() = 1.0f;
}
if (B() < 0.0f)
{
B() = 0.0f;
}
if (B() > 1.0f)
{
B() = 1.0f;
}
if (A() < 0.0f)
{
A() = 0.0f;
}
if (A() > 1.0f)
{
A() = 1.0f;
}
}
Color Color::ToLinear() const
{
Color r {};
rgb_to_linear(*this, &r);
r.A() = A();
return r;
}
Color Color::FromLinear(const Color& l)
{
Color r {};
linear_to_rgb(l, &r);
r.A() = l.A();
return r;
}
Color Color::ToAdobeRGB() const
{
Color r {};
ColorXyz xyz {};
rgb_to_xyz(*this, &xyz);
xyz_to_adobe_rgb(xyz, &r);
r.A() = A();
return r;
}
Color Color::FromAdobeRGB(const Color& c)
{
Color r {};
ColorXyz xyz {};
adobe_rgb_to_xyz(c, &xyz);
xyz_to_rgb(xyz, &r);
r.A() = c.A();
return r;
}
void ColorLab::Clip()
{
if (L < COLOR_LAB_L_MIN)
{
L = COLOR_LAB_L_MIN;
}
if (L > COLOR_LAB_L_MAX)
{
L = COLOR_LAB_L_MAX;
}
if (A < COLOR_LAB_A_MIN)
{
A = COLOR_LAB_A_MIN;
}
if (A > COLOR_LAB_A_MAX)
{
A = COLOR_LAB_A_MAX;
}
if (B < COLOR_LAB_B_MIN)
{
B = COLOR_LAB_B_MIN;
}
if (B > COLOR_LAB_B_MAX)
{
B = COLOR_LAB_B_MAX;
}
}
} // namespace Kyty::Libs::Graphics
#endif // KYTY_EMU_ENABLED

View File

@ -0,0 +1,559 @@
#include "Emulator/Graphics/Image.h"
#include "Kyty/Core/DbgAssert.h"
#include "Kyty/Core/File.h"
#include "Kyty/Core/SafeDelete.h"
#include "SDL_blendmode.h"
#include "SDL_error.h"
#include "SDL_pixels.h"
#include "SDL_rect.h"
#include "SDL_rwops.h"
#include "SDL_surface.h"
#define STB_IMAGE_IMPLEMENTATION
#define STBI_ASSERT ASSERT
#define STBI_NO_SIMD
#include "stb_image.h"
#define KYTY_SDL_BITSPERPIXEL(X) (((X) >> 8u) & 0xFFu)
#define KYTY_SDL_PIXELTYPE(X) (((X) >> 24u) & 0x0Fu)
#define KYTY_SDL_PIXELLAYOUT(X) (((X) >> 16u) & 0x0Fu)
#define KYTY_SDL_PIXELORDER(X) (((X) >> 20u) & 0x0Fu)
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs::Graphics {
// using namespace Core;
using Core::File;
class ImagePrivate
{
public:
KYTY_CLASS_NO_COPY(ImagePrivate);
explicit ImagePrivate(SDL_Surface* s): sdl(s) {}
virtual ~ImagePrivate() { SDL_FreeSurface(sdl); }
void BgrToRgb() const
{
auto* rowptr = static_cast<uint8_t*>(sdl->pixels);
int row_num = sdl->h;
int col_num = sdl->w;
int pitch = sdl->pitch;
for (int row = 0; row < row_num; row++)
{
uint8_t* colptr = rowptr;
for (int col = 0; col < col_num; col++)
{
uint8_t t = colptr[0];
colptr[0] = colptr[2];
colptr[2] = t;
colptr += 3;
}
rowptr += pitch;
}
}
void BgraToRgba() const
{
auto* rowptr = static_cast<uint8_t*>(sdl->pixels);
int row_num = sdl->h;
int col_num = sdl->w;
int pitch = sdl->pitch;
for (int row = 0; row < row_num; row++)
{
uint8_t* colptr = rowptr;
for (int col = 0; col < col_num; col++)
{
uint8_t t = colptr[0];
colptr[0] = colptr[2];
colptr[2] = t;
colptr += 4;
}
rowptr += pitch;
}
}
SDL_Surface* sdl;
};
Image::Image(const String& name): m_name(name) {}
Image::~Image()
{
if (m_image != nullptr)
{
Delete(m_image);
}
}
void Image::Load(const String& file_name)
{
m_name = file_name;
Load();
}
static int read(void* user, char* data, int size)
{
auto* src = static_cast<SDL_RWops*>(user);
return static_cast<int>(src->read(src, data, 1, size));
}
static void skip(void* user, int n)
{
auto* src = static_cast<SDL_RWops*>(user);
src->seek(src, n, RW_SEEK_CUR);
}
static int eof(void* user)
{
auto* src = static_cast<SDL_RWops*>(user);
return (src->seek(src, 0, RW_SEEK_CUR) >= src->size(src) ? 1 : 0);
}
static SDL_Surface* IMG_LoadPNG_RW(SDL_RWops* src)
{
int width = 0;
int height = 0;
int bytes_per_pixel = 0;
stbi_io_callbacks cb {};
cb.read = read;
cb.skip = skip;
cb.eof = eof;
void* data = stbi_load_from_callbacks(&cb, src, &width, &height, &bytes_per_pixel, 0);
uint32_t pitch = (width * bytes_per_pixel + 3u) & ~3u;
uint32_t r_mask = 0x000000FF;
uint32_t g_mask = 0x0000FF00;
uint32_t b_mask = 0x00FF0000;
uint32_t a_mask = (bytes_per_pixel == 4) ? 0xFF000000 : 0;
SDL_Surface* surface =
SDL_CreateRGBSurfaceFrom(data, width, height, bytes_per_pixel * 8, static_cast<int>(pitch), r_mask, g_mask, b_mask, a_mask);
EXIT_NOT_IMPLEMENTED(surface == nullptr);
return surface;
}
void Image::Load()
{
if (m_image != nullptr)
{
Delete(m_image);
}
auto file_name = m_name;
File f;
if (!f.Open(file_name, File::Mode::Read))
{
EXIT("Can't open file %s\n", file_name.C_Str());
}
SDL_RWops* ops = f.CreateSdlRWops();
EXIT_IF(ops == nullptr);
SDL_Surface* sdl = nullptr;
if (file_name.EndsWith(U".bmp", String::Case::Insensitive))
{
/* sdl = IMG_LoadBMP_RW(ops); */
KYTY_NOT_IMPLEMENTED;
} else if (file_name.EndsWith(U".tga", String::Case::Insensitive))
{
/* sdl = IMG_LoadTGA_RW(ops); */
KYTY_NOT_IMPLEMENTED;
} else if (file_name.EndsWith(U".png", String::Case::Insensitive))
{
sdl = IMG_LoadPNG_RW(ops);
// KYTY_NOT_IMPLEMENTED;
} else if (file_name.EndsWith(U".webp", String::Case::Insensitive))
{
/* sdl = IMG_LoadWEBP_RW(ops); */
KYTY_NOT_IMPLEMENTED;
} else
{
EXIT("Unknown image type %s\n", file_name.utf8_str().GetData());
}
LoadSdl(sdl);
SDL_RWclose(ops);
}
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
void Image::LoadSdl(void* s)
{
auto* sdl = static_cast<SDL_Surface*>(s);
EXIT_IF(sdl == nullptr);
m_bits_per_pixel = static_cast<int>(KYTY_SDL_BITSPERPIXEL(sdl->format->format));
EXIT_IF(sdl->format->palette != nullptr && m_bits_per_pixel != 8);
m_image = new ImagePrivate(sdl);
m_width = m_image->sdl->w;
m_height = m_image->sdl->h;
m_pitch = m_image->sdl->pitch;
EXIT_IF(KYTY_SDL_PIXELTYPE(m_image->sdl->format->format) != SDL_PIXELTYPE_ARRAYU8 &&
KYTY_SDL_PIXELTYPE(m_image->sdl->format->format) != SDL_PIXELTYPE_INDEX8 &&
KYTY_SDL_PIXELTYPE(m_image->sdl->format->format) != SDL_PIXELTYPE_PACKED32);
EXIT_IF(KYTY_SDL_PIXELLAYOUT(m_image->sdl->format->format) != 0 &&
KYTY_SDL_PIXELLAYOUT(m_image->sdl->format->format) != SDL_PACKEDLAYOUT_8888);
if (m_bits_per_pixel == 8)
{
m_order = ImageOrder::Alpha;
} else if (SDL_ISPIXELFORMAT_PACKED(m_image->sdl->format->format)) // NOLINT(hicpp-signed-bitwise)
{
switch (KYTY_SDL_PIXELORDER(m_image->sdl->format->format))
{
case SDL_PACKEDORDER_NONE: EXIT("SDL_PACKEDORDER_NONE\n"); break;
case SDL_PACKEDORDER_XRGB: EXIT("SDL_PACKEDORDER_XRGB\n"); break;
case SDL_PACKEDORDER_RGBX: EXIT("SDL_PACKEDORDER_RGBX\n"); break;
// TGA32, BMP32
case SDL_PACKEDORDER_ARGB:
m_image->BgraToRgba();
m_order = ImageOrder::Rgba;
break;
case SDL_PACKEDORDER_RGBA: EXIT("SDL_PACKEDORDER_RGBA\n"); break;
case SDL_PACKEDORDER_XBGR: EXIT("SDL_PACKEDORDER_XBGR\n"); break;
case SDL_PACKEDORDER_BGRX: EXIT("SDL_PACKEDORDER_BGRX\n"); break;
// WEBP32, PNG32
case SDL_PACKEDORDER_ABGR: m_order = ImageOrder::Rgba; break;
case SDL_PACKEDORDER_BGRA: EXIT("SDL_PACKEDORDER_BGRA\n"); break;
default: EXIT("unknown packed format %d\n", int(KYTY_SDL_PIXELORDER(m_image->sdl->format->format)));
}
} else if (SDL_ISPIXELFORMAT_ARRAY(m_image->sdl->format->format)) // NOLINT(hicpp-signed-bitwise)
{
switch (KYTY_SDL_PIXELORDER(m_image->sdl->format->format))
{
case SDL_ARRAYORDER_NONE: EXIT("SDL_ARRAYORDER_NONE\n"); break;
// WEBP24, PNG24
case SDL_ARRAYORDER_RGB: m_order = ImageOrder::Rgb; break;
case SDL_ARRAYORDER_RGBA: EXIT("SDL_ARRAYORDER_RGBA\n"); break;
case SDL_ARRAYORDER_ARGB: EXIT("SDL_ARRAYORDER_ARGB\n"); break;
// TGA24, BMP24,
case SDL_ARRAYORDER_BGR:
m_image->BgrToRgb();
m_order = ImageOrder::Rgb;
break;
case SDL_ARRAYORDER_BGRA: EXIT("SDL_ARRAYORDER_BGRA\n"); break;
case SDL_ARRAYORDER_ABGR: EXIT("SDL_ARRAYORDER_ABGR\n"); break;
default: EXIT("unknown array format %d\n", int(KYTY_SDL_PIXELORDER(m_image->sdl->format->format)));
}
} else
{
EXIT("invalid format\n");
}
EXIT_IF((int)KYTY_SDL_BITSPERPIXEL(m_image->sdl->format->format) != m_image->sdl->format->BitsPerPixel);
EXIT_IF(m_bits_per_pixel != 24 && m_bits_per_pixel != 32 && m_bits_per_pixel != 8);
EXIT_IF(m_pitch - ((m_width * m_bits_per_pixel) >> 3u) >= 4);
m_pixels = m_image->sdl->pixels;
}
void Image::DbgPrint() const
{
printf("------\n");
printf("%s:\n", m_name.utf8_str().GetData());
printf("width = %d\n", (m_image->sdl->w));
printf("height = %d\n", (m_image->sdl->h));
printf("pitch = %d\n", (m_image->sdl->pitch));
printf("type = %d\n", static_cast<int>(KYTY_SDL_PIXELTYPE(m_image->sdl->format->format)));
if (m_bits_per_pixel == 8)
{
printf("order = alpha\n");
} else if (SDL_ISPIXELFORMAT_PACKED(m_image->sdl->format->format)) // NOLINT(hicpp-signed-bitwise)
{
switch (KYTY_SDL_PIXELORDER(m_image->sdl->format->format))
{
case SDL_PACKEDORDER_NONE: printf("order = SDL_PACKEDORDER_NONE\n"); break;
case SDL_PACKEDORDER_XRGB: printf("order = SDL_PACKEDORDER_XRGB\n"); break;
case SDL_PACKEDORDER_RGBX: printf("order = SDL_PACKEDORDER_RGBX\n"); break;
case SDL_PACKEDORDER_ARGB: printf("order = SDL_PACKEDORDER_ARGB\n"); break;
case SDL_PACKEDORDER_RGBA: printf("order = SDL_PACKEDORDER_RGBA\n"); break;
case SDL_PACKEDORDER_XBGR: printf("order = SDL_PACKEDORDER_XBGR\n"); break;
case SDL_PACKEDORDER_BGRX: printf("order = SDL_PACKEDORDER_BGRX\n"); break;
case SDL_PACKEDORDER_ABGR: printf("order = SDL_PACKEDORDER_ABGR\n"); break;
case SDL_PACKEDORDER_BGRA: printf("order = SDL_PACKEDORDER_BGRA\n"); break;
default: printf("order = <packed_invalid>\n");
}
} else if (SDL_ISPIXELFORMAT_ARRAY(m_image->sdl->format->format)) // NOLINT(hicpp-signed-bitwise)
{
switch (KYTY_SDL_PIXELORDER(m_image->sdl->format->format))
{
case SDL_ARRAYORDER_NONE: printf("order = SDL_ARRAYORDER_NONE\n"); break;
case SDL_ARRAYORDER_RGB: printf("order = SDL_ARRAYORDER_RGB\n"); break;
case SDL_ARRAYORDER_RGBA: printf("order = SDL_ARRAYORDER_RGBA\n"); break;
case SDL_ARRAYORDER_ARGB: printf("order = SDL_ARRAYORDER_ARGB\n"); break;
case SDL_ARRAYORDER_BGR: printf("order = SDL_ARRAYORDER_BGR\n"); break;
case SDL_ARRAYORDER_BGRA: printf("order = SDL_ARRAYORDER_BGRA\n"); break;
case SDL_ARRAYORDER_ABGR: printf("order = SDL_ARRAYORDER_ABGR\n"); break;
default: printf("order = <array_invalid>\n");
}
}
printf("layout = %d\n", static_cast<int>(KYTY_SDL_PIXELLAYOUT(m_image->sdl->format->format)));
printf("bits_per_pixel = %d\n", static_cast<int>(KYTY_SDL_BITSPERPIXEL(m_image->sdl->format->format)));
printf("bytes_per_pixel = %d\n", static_cast<int>(SDL_BYTESPERPIXEL(m_image->sdl->format->format))); // NOLINT(hicpp-signed-bitwise)
printf("bits_per_pixel = %d\n", static_cast<int>(m_image->sdl->format->BitsPerPixel));
printf("bytes_per_pixel = %d\n", static_cast<int>(m_image->sdl->format->BytesPerPixel));
}
bool Image::DbgEqual(const Image* img) const
{
if (m_width != img->m_width || m_height != img->m_height || m_pitch != img->m_pitch || m_bits_per_pixel != img->m_bits_per_pixel ||
m_order != img->m_order)
{
return false;
}
for (uint32_t yi = 0; yi < m_height; yi++)
{
for (uint32_t xi = 0; xi < m_width; xi++)
{
if (GetPixel(xi, yi) != img->GetPixel(xi, yi))
{
return false;
}
}
}
return true;
}
void Image::Save(const String& file_name) const
{
EXIT_IF(m_image == nullptr);
File f;
f.Create(file_name);
SDL_RWops* ops = f.CreateSdlRWops();
int result = -1;
if (file_name.EndsWith(U".png", String::Case::Insensitive))
{
/*result = IMG_SavePNG_RW(m_image->sdl, ops, 1);*/
KYTY_NOT_IMPLEMENTED;
} else if (file_name.EndsWith(U".bmp", String::Case::Insensitive))
{
result = SDL_SaveBMP_RW(m_image->sdl, ops, 1);
} else
{
EXIT("Unknown image type %s\n", file_name.utf8_str().GetData());
}
if (result != 0)
{
EXIT("SDL error: %s\n", SDL_GetError());
}
}
Image* Image::Clone() const
{
auto* img = new Image(m_name);
if (m_image != nullptr)
{
SDL_Surface* copy_sdl = SDL_ConvertSurface(m_image->sdl, m_image->sdl->format, SDL_SWSURFACE);
img->LoadSdl(copy_sdl);
}
return img;
}
Image* Image::Create(const String& name, uint32_t width, uint32_t height, int bits_per_pixel)
{
auto* img = new Image(name);
EXIT_IF(bits_per_pixel != 24 && bits_per_pixel != 32);
// uint32_t rmask = 0;
// uint32_t gmask = 0;
// uint32_t bmask = 0;
// uint32_t amask = 0;
//
// if (bits_per_pixel == 32)
// {
uint32_t amask = 0xFF000000;
uint32_t bmask = 0x00FF0000;
uint32_t gmask = 0x0000FF00;
uint32_t rmask = 0x000000FF;
// }
SDL_Surface* sdl =
SDL_CreateRGBSurface(0, static_cast<int>(width), static_cast<int>(height), bits_per_pixel, rmask, gmask, bmask, amask);
SDL_Rect r = {0, 0, static_cast<int>(width), static_cast<int>(height)};
SDL_FillRect(sdl, &r, 0);
img->LoadSdl(sdl);
return img;
}
rgba32_t Image::GetPixel(uint32_t x, uint32_t y) const
{
if (m_order == ImageOrder::Rgb && m_bits_per_pixel == 24)
{
uint8_t* p = ((static_cast<uint8_t*>(m_pixels)) + m_pitch * static_cast<size_t>(y) + 3 * static_cast<size_t>(x));
return Rgb(p[0], p[1], p[2]);
}
if (m_order == ImageOrder::Rgba && m_bits_per_pixel == 32)
{
uint8_t* p = ((static_cast<uint8_t*>(m_pixels)) + m_pitch * static_cast<size_t>(y) + 4 * static_cast<size_t>(x));
return Rgb(p[0], p[1], p[2], p[3]);
}
EXIT("invalid format: order = %d, bits = %d\n", int(m_order), int(m_bits_per_pixel));
return 0;
}
void Image::SetPixel(uint32_t x, uint32_t y, rgba32_t color)
{
if (m_order == ImageOrder::Rgb && m_bits_per_pixel == 24)
{
uint8_t* p = ((static_cast<uint8_t*>(m_pixels)) + m_pitch * static_cast<size_t>(y) + 3 * static_cast<size_t>(x));
p[0] = RgbToRed(color);
p[1] = RgbToGreen(color);
p[2] = RgbToBlue(color);
} else if (m_order == ImageOrder::Rgba && m_bits_per_pixel == 32)
{
uint8_t* p = ((static_cast<uint8_t*>(m_pixels)) + m_pitch * static_cast<size_t>(y) + 4 * static_cast<size_t>(x));
p[0] = RgbToRed(color);
p[1] = RgbToGreen(color);
p[2] = RgbToBlue(color);
p[3] = RgbToAlpha(color);
} else
{
EXIT("invalid format: order = %d, bits = %d\n", int(m_order), int(m_bits_per_pixel));
}
}
rgba32_t Image::GetAvgPixel(uint32_t x, uint32_t y, uint32_t w, uint32_t h) const
{
EXIT_IF(x >= m_width);
EXIT_IF(y >= m_height);
EXIT_IF(x + w > m_width);
EXIT_IF(y + h > m_height);
vec4 sum(0.0f);
for (uint32_t yi = y; yi < y + h; yi++)
{
for (uint32_t xi = x; xi < x + w; xi++)
{
Color s(GetPixel(xi, yi));
sum = sum + s.Rgba();
}
}
sum /= static_cast<float>(w * h);
return Color(sum).ToRgba32();
}
bool Image::BlitTo(Image* img, const Math::Rect& src, const Math::Rect& dst) const
{
EXIT_IF(!img);
EXIT_IF(src.x >= m_width || src.y >= m_height || src.x + src.width - 1 >= m_width || src.y + src.height - 1 >= m_height);
EXIT_IF(dst.x >= img->m_width || dst.y >= img->m_height || dst.x + dst.width - 1 >= img->m_width ||
dst.y + dst.height - 1 >= img->m_height);
SDL_SetSurfaceBlendMode(m_image->sdl, SDL_BLENDMODE_NONE);
int result = 0;
SDL_Rect r1 = {static_cast<int>(src.x), static_cast<int>(src.y), static_cast<int>(src.width), static_cast<int>(src.height)};
SDL_Rect r2 = {static_cast<int>(dst.x), static_cast<int>(dst.y), static_cast<int>(dst.width), static_cast<int>(dst.height)};
if (src.width != dst.width || src.height != dst.height)
{
result = SDL_BlitScaled(m_image->sdl, &r1, img->m_image->sdl, &r2);
} else
{
result = SDL_BlitSurface(m_image->sdl, &r1, img->m_image->sdl, &r2);
}
if (result != 0)
{
printf("Blit failed: %s\n", SDL_GetError());
return false;
}
return true;
}
void* Image::GetSdlSurface() const
{
return m_image->sdl;
}
Math::Size Image::GetSize(const String& name)
{
if (!name.EndsWith(U".png", String::Case::Insensitive))
{
EXIT("unsupported format: %s\n", name.C_Str());
}
File f;
if (!f.Open(name, File::Mode::Read))
{
EXIT("Can't open file %s\n", name.C_Str());
}
Math::Size s(0, 0);
uint32_t header = 0;
f.Seek(12);
f.Read(&header, 4);
if (header != 0x52444849)
{
EXIT("wrong png file: %s\n", name.C_Str());
}
f.ReadR(&s.width, 4);
f.ReadR(&s.height, 4);
f.Close();
return s;
}
} // namespace Kyty::Libs::Graphics
#endif // KYTY_EMU_ENABLED

View File

@ -13,10 +13,12 @@
#include "Emulator/Controller.h"
#include "Emulator/Graphics/GraphicContext.h"
#include "Emulator/Graphics/GraphicsRender.h"
#include "Emulator/Graphics/Image.h"
#include "Emulator/Graphics/Utils.h"
#include "Emulator/Graphics/VideoOut.h"
#include "Emulator/Loader/Param.h"
#include "Emulator/Loader/VirtualMemory.h"
#include "Emulator/Profiler.h"
#include "Emulator/VirtualMemory.h"
#include "SDL.h"
#include "SDL_error.h"
@ -27,6 +29,7 @@
#include "SDL_keycode.h"
#include "SDL_mouse.h"
#include "SDL_stdinc.h"
#include "SDL_surface.h"
#include "SDL_thread.h"
#include "SDL_touch.h"
#include "SDL_video.h"
@ -2163,12 +2166,33 @@ GraphicContext* WindowGetGraphicContext()
return &g_window_ctx->graphic_ctx;
}
void WindowShowFps()
void WindowUpdateIcon()
{
EXIT_IF(g_window_ctx == nullptr);
static Image* icon = Loader::ParamSfoGetIcon();
if (icon != nullptr)
{
SDL_SetWindowIcon(g_window_ctx->window, static_cast<SDL_Surface*>(icon->GetSdlSurface()));
}
}
void WindowUpdateTitle()
{
EXIT_IF(g_window_ctx == nullptr);
EXIT_IF(g_window_ctx->game == nullptr);
auto fps = String::FromPrintf("[%s] [%s], frame: %d, fps: %f", g_window_ctx->device_name, g_window_ctx->processor_name,
static char title[128];
static char title_id[12];
static char app_ver[8];
static bool has_title = Loader::ParamSfoGetString("TITLE", title, sizeof(title));
static bool has_title_id = Loader::ParamSfoGetString("TITLE_ID", title_id, sizeof(title_id));
static bool has_app_ver = Loader::ParamSfoGetString("APP_VER", app_ver, sizeof(app_ver));
auto fps = String::FromPrintf("%s%s%s%s%s%s[%s] [%s], frame: %d, fps: %f", (has_title ? title : ""), (has_title ? ", " : ""),
(has_title_id ? title_id : ""), (has_title_id ? ", " : ""), (has_app_ver ? app_ver : ""),
(has_app_ver ? ", " : ""), g_window_ctx->device_name, g_window_ctx->processor_name,
g_window_ctx->game->m_frame_num, g_window_ctx->game->m_current_fps);
SDL_SetWindowTitle(g_window_ctx->window, fps.C_Str());
@ -2184,6 +2208,8 @@ void WindowDrawBuffer(VideoOutVulkanImage* image)
if (g_window_ctx->window_hidden)
{
WindowUpdateIcon();
SDL_ShowWindow(g_window_ctx->window);
g_window_ctx->window_hidden = false;
@ -2257,7 +2283,7 @@ void WindowDrawBuffer(VideoOutVulkanImage* image)
result = vkQueuePresentKHR(g_window_ctx->graphic_ctx.queue[GraphicContext::QUEUE_PRESENT], &present);
EXIT_NOT_IMPLEMENTED(result != VK_SUCCESS);
WindowShowFps();
WindowUpdateTitle();
}
} // namespace Kyty::Libs::Graphics

View File

@ -11,7 +11,7 @@
#include "Emulator/Graphics/Window.h"
#include "Emulator/Libs/Errno.h"
#include "Emulator/Libs/Libs.h"
#include "Emulator/VirtualMemory.h"
#include "Emulator/Loader/VirtualMemory.h"
#include <algorithm>

View File

@ -11,8 +11,8 @@
#include "Emulator/Libs/Errno.h"
#include "Emulator/Libs/Libs.h"
#include "Emulator/RuntimeLinker.h"
#include "Emulator/Timer.h"
#include "Emulator/Loader/RuntimeLinker.h"
#include "Emulator/Loader/Timer.h"
#include <atomic>
#include <cerrno>

View File

@ -20,11 +20,12 @@
#include "Emulator/Kernel/Memory.h"
#include "Emulator/Kernel/Pthread.h"
#include "Emulator/Libs/Libs.h"
#include "Emulator/Loader/Param.h"
#include "Emulator/Loader/RuntimeLinker.h"
#include "Emulator/Loader/Timer.h"
#include "Emulator/Loader/VirtualMemory.h"
#include "Emulator/Network.h"
#include "Emulator/Profiler.h"
#include "Emulator/RuntimeLinker.h"
#include "Emulator/Timer.h"
#include "Emulator/VirtualMemory.h"
#include <cstdlib>
@ -211,6 +212,25 @@ KYTY_SCRIPT_FUNC(kyty_load_symbols_func)
return 0;
}
KYTY_SCRIPT_FUNC(kyty_load_param_sfo_func)
{
auto count = Scripts::ArgGetVarCount();
if (count != 1)
{
EXIT("invalid args\n");
}
auto file_name = Scripts::ArgGetVar(0).ToString();
if (!file_name.IsEmpty())
{
Loader::ParamSfoLoad(Scripts::ArgGetVar(0).ToString());
}
return 0;
}
KYTY_SCRIPT_FUNC(kyty_dbg_dump_func)
{
if (Scripts::ArgGetVarCount() != 1)
@ -385,6 +405,7 @@ void kyty_reg()
Scripts::RegisterFunc("kyty_load_elf", LuaFunc::kyty_load_elf_func, LuaFunc::kyty_help);
Scripts::RegisterFunc("kyty_save_main_elf", LuaFunc::kyty_save_main_elf_func, LuaFunc::kyty_help);
Scripts::RegisterFunc("kyty_load_symbols", LuaFunc::kyty_load_symbols_func, LuaFunc::kyty_help);
Scripts::RegisterFunc("kyty_load_param_sfo", LuaFunc::kyty_load_param_sfo_func, LuaFunc::kyty_help);
Scripts::RegisterFunc("kyty_dbg_dump", LuaFunc::kyty_dbg_dump_func, LuaFunc::kyty_help);
Scripts::RegisterFunc("kyty_execute", LuaFunc::kyty_execute_func, LuaFunc::kyty_help);
Scripts::RegisterFunc("kyty_mount", LuaFunc::kyty_mount_func, LuaFunc::kyty_help);

View File

@ -5,7 +5,8 @@
#include "Emulator/Common.h"
#include "Emulator/Libs/Errno.h"
#include "Emulator/Libs/Libs.h"
#include "Emulator/SymbolDatabase.h"
#include "Emulator/Loader/Param.h"
#include "Emulator/Loader/SymbolDatabase.h"
#ifdef KYTY_EMU_ENABLED
@ -66,12 +67,42 @@ int KYTY_SYSV_ABI AppContentGetAddcontInfoList(uint32_t service_label, AppConten
return OK;
}
int KYTY_SYSV_ABI AppContentAppParamGetInt(uint32_t param_id, int32_t* value)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(value == nullptr);
*value = 0;
bool found = false;
printf("\t param_id = %u\n", param_id);
switch (param_id)
{
case 0:
*value = 3;
found = true;
break;
case 1: found = Loader::ParamSfoGetInt("USER_DEFINED_PARAM_1", value); break;
case 2: found = Loader::ParamSfoGetInt("USER_DEFINED_PARAM_2", value); break;
case 3: found = Loader::ParamSfoGetInt("USER_DEFINED_PARAM_3", value); break;
case 4: found = Loader::ParamSfoGetInt("USER_DEFINED_PARAM_4", value); break;
default: EXIT("unknown param_id: %u\n", param_id);
}
printf("\t value = %d [%s]\n", *value, found ? "found" : "not found");
return OK;
}
} // namespace AppContent
LIB_DEFINE(InitAppContent_1)
{
LIB_FUNC("R9lA82OraNs", AppContent::AppContentInitialize);
LIB_FUNC("xnd8BJzAxmk", AppContent::AppContentGetAddcontInfoList);
LIB_FUNC("99b82IKXpH4", AppContent::AppContentAppParamGetInt);
}
} // namespace Kyty::Libs

View File

@ -1,7 +1,7 @@
#include "Emulator/Audio.h"
#include "Emulator/Common.h"
#include "Emulator/Libs/Libs.h"
#include "Emulator/SymbolDatabase.h"
#include "Emulator/Loader/SymbolDatabase.h"
#ifdef KYTY_EMU_ENABLED

View File

@ -9,7 +9,7 @@
#include "Emulator/Libs/Libs.h"
#include "Emulator/Libs/Printf.h"
#include "Emulator/Libs/VaContext.h"
#include "Emulator/SymbolDatabase.h"
#include "Emulator/Loader/SymbolDatabase.h"
#include <cstdlib>

View File

@ -3,7 +3,7 @@
#include "Emulator/Common.h"
#include "Emulator/Libs/Libs.h"
#include "Emulator/SymbolDatabase.h"
#include "Emulator/Loader/SymbolDatabase.h"
#ifdef KYTY_EMU_ENABLED

View File

@ -1,7 +1,7 @@
#include "Emulator/Common.h"
#include "Emulator/Dialog.h"
#include "Emulator/Libs/Libs.h"
#include "Emulator/SymbolDatabase.h"
#include "Emulator/Loader/SymbolDatabase.h"
#ifdef KYTY_EMU_ENABLED

View File

@ -3,7 +3,7 @@
#include "Emulator/Common.h"
#include "Emulator/Libs/Libs.h"
#include "Emulator/SymbolDatabase.h"
#include "Emulator/Loader/SymbolDatabase.h"
#ifdef KYTY_EMU_ENABLED

View File

@ -1,7 +1,7 @@
#include "Emulator/Common.h"
#include "Emulator/Graphics/Graphics.h"
#include "Emulator/Libs/Libs.h"
#include "Emulator/SymbolDatabase.h"
#include "Emulator/Loader/SymbolDatabase.h"
#ifdef KYTY_EMU_ENABLED

View File

@ -14,8 +14,8 @@
#include "Emulator/Kernel/Semaphore.h"
#include "Emulator/Libs/Errno.h"
#include "Emulator/Libs/Libs.h"
#include "Emulator/RuntimeLinker.h"
#include "Emulator/SymbolDatabase.h"
#include "Emulator/Loader/RuntimeLinker.h"
#include "Emulator/Loader/SymbolDatabase.h"
#include <cstdlib>

View File

@ -2,8 +2,8 @@
#include "Emulator/Common.h"
#include "Emulator/Libs/Libs.h"
#include "Emulator/Loader/SymbolDatabase.h"
#include "Emulator/Network.h"
#include "Emulator/SymbolDatabase.h"
#ifdef KYTY_EMU_ENABLED

View File

@ -1,7 +1,7 @@
#include "Emulator/Common.h"
#include "Emulator/Controller.h"
#include "Emulator/Libs/Libs.h"
#include "Emulator/SymbolDatabase.h"
#include "Emulator/Loader/SymbolDatabase.h"
#ifdef KYTY_EMU_ENABLED

View File

@ -5,7 +5,7 @@
#include "Emulator/Common.h"
#include "Emulator/Libs/Errno.h"
#include "Emulator/Libs/Libs.h"
#include "Emulator/SymbolDatabase.h"
#include "Emulator/Loader/SymbolDatabase.h"
#ifdef KYTY_EMU_ENABLED

View File

@ -7,7 +7,7 @@
#include "Emulator/Kernel/FileSystem.h"
#include "Emulator/Libs/Errno.h"
#include "Emulator/Libs/Libs.h"
#include "Emulator/SymbolDatabase.h"
#include "Emulator/Loader/SymbolDatabase.h"
#ifdef KYTY_EMU_ENABLED

View File

@ -4,7 +4,7 @@
#include "Emulator/Common.h"
#include "Emulator/Libs/Libs.h"
#include "Emulator/SymbolDatabase.h"
#include "Emulator/Loader/SymbolDatabase.h"
#ifdef KYTY_EMU_ENABLED

View File

@ -5,7 +5,7 @@
#include "Emulator/Common.h"
#include "Emulator/Libs/Errno.h"
#include "Emulator/Libs/Libs.h"
#include "Emulator/SymbolDatabase.h"
#include "Emulator/Loader/SymbolDatabase.h"
#ifdef KYTY_EMU_ENABLED

View File

@ -4,7 +4,7 @@
#include "Emulator/Common.h"
#include "Emulator/Libs/Errno.h"
#include "Emulator/Libs/Libs.h"
#include "Emulator/SymbolDatabase.h"
#include "Emulator/Loader/SymbolDatabase.h"
#include <cstdio>

View File

@ -1,7 +1,7 @@
#include "Emulator/Common.h"
#include "Emulator/Graphics/VideoOut.h"
#include "Emulator/Libs/Libs.h"
#include "Emulator/SymbolDatabase.h"
#include "Emulator/Loader/SymbolDatabase.h"
#ifdef KYTY_EMU_ENABLED

View File

@ -1,4 +1,4 @@
#include "Emulator/Elf.h"
#include "Emulator/Loader/Elf.h"
#include "Kyty/Core/DbgAssert.h"
#include "Kyty/Core/File.h"

View File

@ -0,0 +1,327 @@
#include "Emulator/Loader/Param.h"
#include "Kyty/Core/ByteBuffer.h"
#include "Kyty/Core/Common.h"
#include "Kyty/Core/DbgAssert.h"
#include "Kyty/Core/File.h"
#include "Kyty/Core/Singleton.h"
#include "Kyty/Core/Threads.h"
#include "Emulator/Graphics/Image.h"
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Loader {
class Psf
{
public:
Psf() = default;
virtual ~Psf();
KYTY_CLASS_NO_COPY(Psf);
void Open(const String& file_name);
void Close();
bool IsValid();
bool GetParamInt(const char* name, int32_t* value);
bool GetParamString(const char* name, String* value);
bool GetParamString(const char* name, char* value, size_t value_size);
void DbgPrint();
private:
struct ParamInfo
{
uint16_t name_offset;
uint16_t type;
uint32_t size1;
uint32_t size2;
uint32_t value_offset;
};
Core::File m_f;
Core::Mutex m_mutex;
bool m_opened = false;
uint32_t m_name_tbl_offset = 0;
uint32_t m_value_tbl_offset = 0;
uint32_t m_params_num = 0;
ParamInfo* m_params = nullptr;
char* m_name_tbl = nullptr;
};
struct SystemContent
{
String psf_path;
Psf psf;
String icon_path;
Libs::Graphics::Image* icon = nullptr;
};
Psf::~Psf()
{
Close();
}
void Psf::Open(const String& file_name)
{
Core::LockGuard lock(m_mutex);
Close();
m_f.Open(file_name, Core::File::Mode::Read);
if (m_f.IsInvalid())
{
printf("Can't open %s\n", file_name.C_Str());
return;
}
uint32_t magic1 = 0;
uint32_t magic2 = 0;
m_f.Read(&magic1, 4);
m_f.Read(&magic2, 4);
if (magic1 != 0x46535000 && magic2 != 0x00000101)
{
printf("invalid file: magic1 = %08" PRIx32 ", magic2 = %08" PRIx32 "\n", magic1, magic2);
return;
}
m_f.Read(&m_name_tbl_offset, 4);
m_f.Read(&m_value_tbl_offset, 4);
m_f.Read(&m_params_num, 4);
EXIT_NOT_IMPLEMENTED(m_name_tbl_offset == 0);
EXIT_NOT_IMPLEMENTED(m_value_tbl_offset == 0);
EXIT_NOT_IMPLEMENTED(m_value_tbl_offset <= m_name_tbl_offset);
EXIT_NOT_IMPLEMENTED(m_params_num == 0);
uint32_t name_tbl_size = m_value_tbl_offset - m_name_tbl_offset;
m_params = new ParamInfo[m_params_num];
m_name_tbl = new char[name_tbl_size];
for (uint32_t i = 0; i < m_params_num; i++)
{
m_f.Read(&m_params[i].name_offset, 2);
m_f.Read(&m_params[i].type, 2);
m_f.Read(&m_params[i].size1, 4);
m_f.Read(&m_params[i].size2, 4);
m_f.Read(&m_params[i].value_offset, 4);
if (m_params[i].type != 0x0204 && m_params[i].type != 0x0404)
{
printf("unknown type %02" PRIx16 "\n", m_params[i].type);
return;
}
}
m_f.Seek(m_name_tbl_offset);
m_f.Read(m_name_tbl, name_tbl_size);
m_opened = true;
}
void Psf::Close()
{
Core::LockGuard lock(m_mutex);
if (!m_f.IsInvalid())
{
m_f.Close();
}
delete[] m_params;
delete[] m_name_tbl;
m_name_tbl = nullptr;
m_params = nullptr;
m_opened = false;
}
bool Psf::IsValid()
{
Core::LockGuard lock(m_mutex);
return m_opened;
}
void Psf::DbgPrint()
{
Core::LockGuard lock(m_mutex);
if (m_opened)
{
for (uint32_t i = 0; i < m_params_num; i++)
{
printf("%s, ", m_name_tbl + m_params[i].name_offset);
switch (m_params[i].type)
{
case 0x0204:
{
m_f.Seek(m_value_tbl_offset + m_params[i].value_offset);
auto buf = m_f.Read(m_params[i].size1);
auto str = String::FromUtf8(reinterpret_cast<const char*>(buf.GetDataConst())).ReplaceChar(U'\n', U',');
printf("string = %s\n", str.C_Str());
break;
}
case 0x0404:
{
uint32_t value = 0;
m_f.Seek(m_value_tbl_offset + m_params[i].value_offset);
m_f.Read(&value, 4);
printf("int = 0x%08" PRIx32 "\n", value);
break;
}
default: EXIT("unknown type %02" PRIx16 "\n", m_params[i].type);
}
}
}
}
bool Psf::GetParamInt(const char* name, int32_t* value)
{
Core::LockGuard lock(m_mutex);
if (m_opened)
{
for (uint32_t i = 0; i < m_params_num; i++)
{
if (strcmp(name, m_name_tbl + m_params[i].name_offset) == 0 && m_params[i].type == 0x0404 && m_params[i].size1 == 4)
{
m_f.Seek(m_value_tbl_offset + m_params[i].value_offset);
m_f.Read(value, 4);
return true;
}
}
}
return false;
}
bool Psf::GetParamString(const char* name, String* value)
{
Core::LockGuard lock(m_mutex);
if (m_opened)
{
for (uint32_t i = 0; i < m_params_num; i++)
{
if (strcmp(name, m_name_tbl + m_params[i].name_offset) == 0 && m_params[i].type == 0x0204)
{
m_f.Seek(m_value_tbl_offset + m_params[i].value_offset);
auto buf = m_f.Read(m_params[i].size1);
*value = String::FromUtf8(reinterpret_cast<const char*>(buf.GetDataConst()));
return true;
}
}
}
return false;
}
bool Psf::GetParamString(const char* name, char* value, size_t value_size)
{
Core::LockGuard lock(m_mutex);
if (m_opened)
{
for (uint32_t i = 0; i < m_params_num; i++)
{
if (strcmp(name, m_name_tbl + m_params[i].name_offset) == 0 && m_params[i].type == 0x0204 && m_params[i].size1 <= value_size)
{
m_f.Seek(m_value_tbl_offset + m_params[i].value_offset);
m_f.Read(value, m_params[i].size1);
return true;
}
}
}
return false;
}
void ParamSfoLoad(const String& file_name)
{
auto* sc = Core::Singleton<SystemContent>::Instance();
if (!Core::File::IsFileExisting(file_name))
{
EXIT("Can't find file: %s\n", file_name.C_Str());
}
sc->psf.Open(file_name);
if (!sc->psf.IsValid())
{
EXIT("invalid file: %s\n", file_name.C_Str());
}
sc->psf_path = file_name;
sc->psf.DbgPrint();
sc->icon_path = file_name.DirectoryWithoutFilename() + U"icon0.png";
delete sc->icon;
if (Core::File::IsFileExisting(sc->icon_path))
{
sc->icon = new Libs::Graphics::Image(sc->icon_path);
sc->icon->Load();
} else
{
sc->icon = nullptr;
}
}
bool ParamSfoGetInt(const char* name, int32_t* value)
{
if (name == nullptr || value == nullptr)
{
return false;
}
auto* sc = Core::Singleton<SystemContent>::Instance();
return sc->psf.GetParamInt(name, value);
}
bool ParamSfoGetString(const char* name, String* value)
{
if (name == nullptr || value == nullptr)
{
return false;
}
auto* sc = Core::Singleton<SystemContent>::Instance();
return sc->psf.GetParamString(name, value);
}
bool ParamSfoGetString(const char* name, char* value, size_t value_size)
{
if (name == nullptr || value == nullptr)
{
return false;
}
auto* sc = Core::Singleton<SystemContent>::Instance();
return sc->psf.GetParamString(name, value, value_size);
}
Libs::Graphics::Image* ParamSfoGetIcon()
{
auto* sc = Core::Singleton<SystemContent>::Instance();
return sc->icon;
}
} // namespace Kyty::Loader
#endif // KYTY_EMU_ENABLED

View File

@ -1,4 +1,4 @@
#include "Emulator/RuntimeLinker.h"
#include "Emulator/Loader/RuntimeLinker.h"
#include "Kyty/Core/Common.h"
#include "Kyty/Core/DbgAssert.h"
@ -9,13 +9,13 @@
#include "Kyty/Core/Threads.h"
#include "Kyty/Sys/SysDbg.h"
#include "Emulator/Elf.h"
#include "Emulator/Graphics/Objects/GpuMemory.h"
#include "Emulator/Jit.h"
#include "Emulator/Kernel/Pthread.h"
#include "Emulator/Loader/Elf.h"
#include "Emulator/Loader/Jit.h"
#include "Emulator/Loader/SymbolDatabase.h"
#include "Emulator/Loader/VirtualMemory.h"
#include "Emulator/Profiler.h"
#include "Emulator/SymbolDatabase.h"
#include "Emulator/VirtualMemory.h"
#ifdef KYTY_EMU_ENABLED
@ -725,9 +725,10 @@ Program* RuntimeLinker::LoadProgram(const String& elf_name)
Libs::LibKernel::SetProgName(elf_name.FilenameWithoutDirectory());
}
if (elf_name.FilenameWithoutExtension().EndsWith(U"libc") || elf_name.FilenameWithoutExtension().EndsWith(U"Fios2") ||
if (/*elf_name.FilenameWithoutExtension().EndsWith(U"libc") || elf_name.FilenameWithoutExtension().EndsWith(U"Fios2") ||
elf_name.FilenameWithoutExtension().EndsWith(U"Fios2_debug") || elf_name.FilenameWithoutExtension().EndsWith(U"NpToolkit") ||
elf_name.FilenameWithoutExtension().EndsWith(U"NpToolkit2") || elf_name.FilenameWithoutExtension().EndsWith(U"JobManager"))
elf_name.FilenameWithoutExtension().EndsWith(U"NpToolkit2") || elf_name.FilenameWithoutExtension().EndsWith(U"JobManager")*/
elf_name.DirectoryWithoutFilename().EndsWith(U"_module/", String::Case::Insensitive))
{
program->fail_if_global_not_resolved = false;
}

View File

@ -1,4 +1,4 @@
#include "Emulator/SymbolDatabase.h"
#include "Emulator/Loader/SymbolDatabase.h"
#include "Kyty/Core/File.h"
#include "Kyty/Core/MagicEnum.h"

View File

@ -4,7 +4,7 @@
#include "Kyty/Core/Subsystems.h"
#include "Emulator/Common.h"
#include "Emulator/Timer.h"
#include "Emulator/Loader/Timer.h"
#ifdef KYTY_EMU_ENABLED

View File

@ -1,9 +1,9 @@
#include "Emulator/VirtualMemory.h"
#include "Emulator/Loader/VirtualMemory.h"
#include "Kyty/Core/DbgAssert.h"
#include "Emulator/Common.h"
#include "Emulator/Jit.h"
#include "Emulator/Loader/Jit.h"
#include "Emulator/Profiler.h"
#include "cpuinfo.h"

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>697</width>
<height>587</height>
<width>837</width>
<height>822</height>
</rect>
</property>
<property name="windowTitle">
@ -17,6 +17,19 @@
<locale language="English" country="UnitedStates"/>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0" rowspan="2">
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="sizeConstraint">
@ -89,6 +102,12 @@
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="MandatoryLineEdit" name="base_directory_lineedit">
<property name="minimumSize">
<size>
<width>550</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Name of the directory where game is located&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
@ -109,6 +128,43 @@
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_17">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Param file</string>
</property>
</widget>
</item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<widget class="QLineEdit" name="param_file_lineedit">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Path to &lt;span style=&quot; font-weight:600;&quot;&gt;param.sfo&lt;/span&gt; file&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="clearButtonEnabled">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="browse_param_file_button">
<property name="text">
<string>Browse...</string>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
@ -132,20 +188,6 @@
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="1" column="0">
<widget class="QLabel" name="label_16">
<property name="text">
<string>Screen resoultion:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="comboBox_screen_resolution">
<property name="toolTip">
<string>Window resolution</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QFrame" name="frame_4">
<property name="frameShape">
@ -168,19 +210,6 @@
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="checkBox_shader_validation">
<property name="toolTip">
<string>Validate SPIR-V binary</string>
</property>
<property name="text">
<string>Shader validation</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="checkBox_vulkan_validation">
<property name="toolTip">
@ -194,6 +223,19 @@
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="checkBox_shader_validation">
<property name="toolTip">
<string>Validate SPIR-V binary</string>
</property>
<property name="text">
<string>Shader validation</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="checkBox_cmd_dump">
<property name="toolTip">
@ -207,22 +249,36 @@
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="checkBox_spirv_printf">
<property name="enabled">
<bool>false</bool>
<item row="1" column="2">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="toolTip">
<string>Enable GL_EXT_debug_printf extension</string>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
<property name="text">
<string>Spirv debug printf</string>
</property>
</widget>
</spacer>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_16">
<property name="text">
<string>Screen resoultion:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="comboBox_screen_resolution">
<property name="toolTip">
<string>Window resolution</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_20">
<property name="text">
@ -237,6 +293,13 @@
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_21">
<property name="text">
<string>Shader log direction:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="comboBox_shader_log_direction">
<property name="toolTip">
@ -244,6 +307,13 @@
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_22">
<property name="text">
<string>Shader log folder:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="MandatoryLineEdit" name="lineEdit_shader_log_folder">
<property name="toolTip">
@ -254,6 +324,13 @@
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_24">
<property name="text">
<string>Command buffer dump folder:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="MandatoryLineEdit" name="lineEdit_cmd_dump_folder">
<property name="toolTip">
@ -264,6 +341,13 @@
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_25">
<property name="text">
<string>Printf direction:</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QComboBox" name="comboBox_printf_direction">
<property name="toolTip">
@ -271,6 +355,13 @@
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_26">
<property name="text">
<string>Printf output file:</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="MandatoryLineEdit" name="lineEdit_printf_file">
<property name="toolTip">
@ -281,6 +372,13 @@
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_27">
<property name="text">
<string>Profiler direction:</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QComboBox" name="comboBox_profiler_direction">
<property name="toolTip">
@ -288,45 +386,10 @@
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_21">
<item row="9" column="0">
<widget class="QLabel" name="label_28">
<property name="text">
<string>Shader log direction:</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_22">
<property name="text">
<string>Shader log folder:</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_24">
<property name="text">
<string>Command buffer dump folder:</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_25">
<property name="text">
<string>Printf direction:</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_26">
<property name="text">
<string>Printf output file:</string>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_27">
<property name="text">
<string>Profiler direction:</string>
<string>Profiler output file:</string>
</property>
</widget>
</item>
@ -340,12 +403,54 @@
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="label_28">
<property name="text">
<string>Profiler output file:</string>
</property>
</widget>
<item row="11" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="image">
<property name="minimumSize">
<size>
<width>240</width>
<height>135</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
@ -426,21 +531,11 @@
</item>
</layout>
</item>
<item>
<widget class="QTableWidget" name="params_table"/>
</item>
</layout>
</item>
<item row="1" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="1">
<layout class="QVBoxLayout" name="verticalLayout">
<item>

View File

@ -102,8 +102,9 @@ public:
Configuration() = default;
QString Name;
QString BaseDir; /* Game base directory */
QString name;
QString basedir; /* Game base directory */
QString param_file; /* Path to param.sfo */
Resolution screen_resolution = Resolution::R1280X720;
bool neo = true;
@ -118,7 +119,6 @@ public:
QString printf_output_file = "_kyty.txt";
ProfilerDirection profiler_direction = ProfilerDirection::None;
QString profiler_output_file = "_profile.prof";
bool spirv_debug_printf_enabled = false;
QStringList elfs;
QStringList elfs_selected;
@ -127,8 +127,9 @@ public:
void WriteSettings(QSettings* s) const
{
KYTY_CFG_SET(Name);
KYTY_CFG_SET(BaseDir);
KYTY_CFG_SET(name);
KYTY_CFG_SET(basedir);
KYTY_CFG_SET(param_file);
KYTY_CFG_SET(screen_resolution);
KYTY_CFG_SET(neo);
KYTY_CFG_SET(vulkan_validation_enabled);
@ -142,7 +143,6 @@ public:
KYTY_CFG_SET(printf_output_file);
KYTY_CFG_SET(profiler_direction);
KYTY_CFG_SET(profiler_output_file);
KYTY_CFG_SET(spirv_debug_printf_enabled);
KYTY_CFG_SETL(elfs);
KYTY_CFG_SETL(elfs_selected);
KYTY_CFG_SETL(libs);
@ -151,8 +151,9 @@ public:
void ReadSettings(QSettings* s)
{
KYTY_CFG_GET(Name);
KYTY_CFG_GET(BaseDir);
KYTY_CFG_GET(name);
KYTY_CFG_GET(basedir);
KYTY_CFG_GET(param_file);
KYTY_CFG_GET(screen_resolution);
KYTY_CFG_GET(neo);
KYTY_CFG_GET(vulkan_validation_enabled);
@ -166,7 +167,6 @@ public:
KYTY_CFG_GET(printf_output_file);
KYTY_CFG_GET(profiler_direction);
KYTY_CFG_GET(profiler_output_file);
KYTY_CFG_GET(spirv_debug_printf_enabled);
KYTY_CFG_GETL(elfs);
KYTY_CFG_GETL(elfs_selected);
KYTY_CFG_GETL(libs);

View File

@ -53,8 +53,10 @@ protected:
void adjust_size();
void save();
void browse_base_path();
void browse_param_file();
void scan_elfs();
void scan_libs();
void load_param_sfo();
void clear();
void test();
};

View File

@ -0,0 +1,118 @@
#ifndef LAUNCHER_INCLUDE_PSF_H_
#define LAUNCHER_INCLUDE_PSF_H_
#include "Common.h"
#include <QFile>
#include <QString>
class Psf
{
public:
Psf() = default;
virtual ~Psf() = default;
KYTY_QT_CLASS_NO_COPY(Psf);
void Load(const QString& file_name);
[[nodiscard]] const QMap<QString, QVariant>& GetMap() const { return m_map; }
private:
QMap<QString, QVariant> m_map;
};
inline void Psf::Load(const QString& file_name)
{
struct ParamInfo
{
uint16_t name_offset;
uint16_t type;
uint32_t size1;
uint32_t size2;
uint32_t value_offset;
};
QFile f(file_name);
if (!f.open(QIODevice::ReadOnly))
{
return;
}
QDataStream s(&f);
s.setByteOrder(QDataStream::LittleEndian);
uint32_t magic1 = 0;
uint32_t magic2 = 0;
s >> magic1;
s >> magic2;
if (magic1 != 0x46535000 && magic2 != 0x00000101)
{
return;
}
uint32_t name_tbl_offset = 0;
uint32_t value_tbl_offset = 0;
uint32_t params_num = 0;
s >> name_tbl_offset;
s >> value_tbl_offset;
s >> params_num;
if (name_tbl_offset == 0 || value_tbl_offset == 0 || value_tbl_offset <= name_tbl_offset || params_num == 0)
{
return;
}
uint32_t name_tbl_size = value_tbl_offset - name_tbl_offset;
auto* params = new ParamInfo[params_num];
auto* name_tbl = new char[name_tbl_size];
for (uint32_t i = 0; i < params_num; i++)
{
s >> params[i].name_offset;
s >> params[i].type;
s >> params[i].size1;
s >> params[i].size2;
s >> params[i].value_offset;
}
s.device()->seek(name_tbl_offset);
s.readRawData(name_tbl, static_cast<int>(name_tbl_size));
for (uint32_t i = 0; i < params_num; i++)
{
QString name = name_tbl + params[i].name_offset;
switch (params[i].type)
{
case 0x0204:
{
s.device()->seek(value_tbl_offset + params[i].value_offset);
QByteArray buf(static_cast<int>(params[i].size1), Qt::Uninitialized);
s.readRawData(buf.data(), static_cast<int>(params[i].size1));
QString value(buf);
m_map.insert(name, value);
break;
}
case 0x0404:
{
uint32_t value = 0;
s.device()->seek(value_tbl_offset + params[i].value_offset);
s >> value;
m_map.insert(name, value);
break;
}
default:;
}
}
delete[] params;
delete[] name_tbl;
}
#endif /* LAUNCHER_INCLUDE_PSF_H_ */

View File

@ -4,6 +4,7 @@
#include "ConfigurationListWidget.h"
#include "MainDialog.h"
#include "MandatoryLineEdit.h"
#include "Psf.h"
#include <QByteArray>
#include <QCheckBox>
@ -20,6 +21,7 @@
#include <QListWidget>
#include <QListWidgetItem>
#include <QMessageBox>
#include <QPicture>
#include <QPushButton>
#include <QSettings>
#include <QStringList>
@ -32,6 +34,7 @@ constexpr char SETTINGS_CFG_LAST_GEOMETRY[] = "geometry";
constexpr char SETTINGS_LAST_BASE_DIR[] = "last_base_dir";
constexpr char COLOR_SELECTED[] = "#e2ffe2";
constexpr char COLOR_NOT_SELECTED[] = "#ffffff";
constexpr char COLOR_ODD_ROW[] = "#fff5e5";
static void ChangeColor(QListWidgetItem* item)
{
@ -53,6 +56,7 @@ ConfigurationEditDialog::ConfigurationEditDialog(Kyty::Configuration* info, Conf
connect(m_ui->clear_button, &QPushButton::clicked, this, &ConfigurationEditDialog::clear);
connect(m_ui->test_button, &QPushButton::clicked, this, &ConfigurationEditDialog::test);
connect(m_ui->browse_base_dir_button, &QPushButton::clicked, this, &ConfigurationEditDialog::browse_base_path);
connect(m_ui->browse_param_file_button, &QPushButton::clicked, this, &ConfigurationEditDialog::browse_param_file);
connect(m_ui->comboBox_shader_log_direction, &QComboBox::currentTextChanged,
[=](const QString& text)
{
@ -74,6 +78,7 @@ ConfigurationEditDialog::ConfigurationEditDialog(Kyty::Configuration* info, Conf
log == Kyty::Configuration::ProfilerDirection::FileAndNetwork);
});
connect(m_ui->base_directory_lineedit, &QLineEdit::textChanged, this, &ConfigurationEditDialog::scan_elfs);
connect(m_ui->param_file_lineedit, &QLineEdit::textChanged, this, &ConfigurationEditDialog::load_param_sfo);
connect(m_ui->listWidget_elfs, &QListWidget::itemChanged, this, &ChangeColor);
connect(m_ui->listWidget_libs, &QListWidget::itemChanged, this, &ChangeColor);
connect(&m_process, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
@ -83,10 +88,17 @@ ConfigurationEditDialog::ConfigurationEditDialog(Kyty::Configuration* info, Conf
restoreGeometry(g_last_geometry);
m_ui->params_table->setWordWrap(false);
m_ui->params_table->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
m_ui->params_table->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
m_ui->params_table->horizontalHeader()->setStretchLastSection(true);
m_ui->params_table->setStyleSheet("selection-background-color: lightgray; selection-color: black;");
Init();
scan_libs();
scan_elfs();
load_param_sfo();
}
QString ConfigurationEditDialog::g_last_base_dir;
@ -134,8 +146,9 @@ static void ListInit(QComboBox* combo, T value)
void ConfigurationEditDialog::Init()
{
m_ui->name_lineedit->setText(m_info->Name);
m_ui->base_directory_lineedit->setText(m_info->BaseDir);
m_ui->name_lineedit->setText(m_info->name);
m_ui->base_directory_lineedit->setText(m_info->basedir);
m_ui->param_file_lineedit->setText(m_info->param_file);
ListInit(m_ui->comboBox_screen_resolution, m_info->screen_resolution);
m_ui->checkBox_neo->setChecked(m_info->neo);
m_ui->checkBox_shader_validation->setChecked(m_info->shader_validation_enabled);
@ -149,7 +162,6 @@ void ConfigurationEditDialog::Init()
m_ui->lineEdit_printf_file->setText(m_info->printf_output_file);
ListInit(m_ui->comboBox_profiler_direction, m_info->profiler_direction);
m_ui->lineEdit_profiler_file->setText(m_info->profiler_output_file);
m_ui->checkBox_spirv_printf->setChecked(m_info->spirv_debug_printf_enabled);
}
void ConfigurationEditDialog::SetTitle(const QString& str)
@ -184,8 +196,9 @@ static void UpdateList(QStringList* list, QStringList* list_selected, QListWidge
static void UpdateInfo(Kyty::Configuration* info, Ui::ConfigurationEditDialog* ui)
{
info->Name = ui->name_lineedit->text();
info->BaseDir = ui->base_directory_lineedit->text();
info->name = ui->name_lineedit->text();
info->basedir = ui->base_directory_lineedit->text();
info->param_file = ui->param_file_lineedit->text();
info->screen_resolution = TextToEnum<Kyty::Configuration::Resolution>(ui->comboBox_screen_resolution->currentText());
info->neo = ui->checkBox_neo->isChecked();
info->vulkan_validation_enabled = ui->checkBox_vulkan_validation->isChecked();
@ -200,7 +213,6 @@ static void UpdateInfo(Kyty::Configuration* info, Ui::ConfigurationEditDialog* u
info->printf_output_file = ui->lineEdit_printf_file->text();
info->profiler_direction = TextToEnum<Kyty::Configuration::ProfilerDirection>(ui->comboBox_profiler_direction->currentText());
info->profiler_output_file = ui->lineEdit_profiler_file->text();
info->spirv_debug_printf_enabled = ui->checkBox_spirv_printf->isChecked();
info->elfs.clear();
info->elfs_selected.clear();
@ -258,6 +270,23 @@ void ConfigurationEditDialog::browse_base_path()
}
}
void ConfigurationEditDialog::browse_param_file()
{
QString text = m_ui->param_file_lineedit->text();
if (text.isEmpty())
{
text = m_ui->base_directory_lineedit->text();
}
QString file = QFileDialog::getOpenFileName(this, tr("Select param.sfo"), text.isEmpty() ? g_last_base_dir : text, "param.sfo");
if (!file.isEmpty())
{
m_ui->param_file_lineedit->setText(file);
}
}
void ConfigurationEditDialog::scan_elfs()
{
auto dir = m_ui->base_directory_lineedit->text();
@ -356,6 +385,62 @@ void ConfigurationEditDialog::scan_libs()
m_ui->listWidget_libs->sortItems();
}
void ConfigurationEditDialog::load_param_sfo()
{
auto file_name = m_ui->param_file_lineedit->text();
m_ui->image->clear();
m_ui->params_table->clear();
m_ui->params_table->setRowCount(0);
m_ui->params_table->setColumnCount(2);
m_ui->params_table->setHorizontalHeaderLabels({tr("Parameter"), tr("Value")});
m_ui->params_table->resizeColumnsToContents();
QFile param(file_name);
if (param.exists())
{
Psf psf;
psf.Load(file_name);
const auto& map = psf.GetMap();
m_ui->params_table->setColumnCount(2);
m_ui->params_table->setRowCount(map.size());
int index = 0;
for (auto& m: map.toStdMap())
{
auto* item1 = new QTableWidgetItem(m.first);
item1->setFlags(item1->flags() ^ Qt::ItemIsEditable);
auto* item2 = new QTableWidgetItem(
m.second.type() == QVariant::UInt ? QString("0x%1").arg(m.second.toUInt(), 8, 16, QLatin1Char('0')) : m.second.toString());
item2->setFlags(item2->flags() ^ Qt::ItemIsEditable);
if (index % 2 != 0)
{
item1->setBackground(QColor(COLOR_ODD_ROW));
item2->setBackground(QColor(COLOR_ODD_ROW));
}
m_ui->params_table->setItem(index, 0, item1);
m_ui->params_table->setItem(index, 1, item2);
index++;
}
m_ui->params_table->resizeRowsToContents();
m_ui->params_table->resizeColumnToContents(0);
QFile image(QFileInfo(file_name).absoluteDir().filePath("pic1.png"));
if (image.exists())
{
QPixmap picture;
picture.load(image.fileName());
m_ui->image->setPixmap(picture.scaledToWidth(m_ui->image->width(), Qt::SmoothTransformation));
}
}
}
void ConfigurationEditDialog::clear()
{
auto* old_info = m_info;
@ -368,6 +453,7 @@ void ConfigurationEditDialog::clear()
scan_elfs();
scan_libs();
load_param_sfo();
}
void ConfigurationEditDialog::test()

View File

@ -11,7 +11,7 @@ ConfigurationItem::ConfigurationItem(Kyty::Configuration* info, QListWidget* par
setSizeHint(QSize(0, 18));
if (m_info != nullptr)
{
setText(m_info->Name);
setText(m_info->name);
}
SetRunning(false);
}
@ -25,7 +25,7 @@ void ConfigurationItem::Update()
{
if (m_info != nullptr)
{
setText(m_info->Name);
setText(m_info->name);
}
}

View File

@ -42,6 +42,7 @@ constexpr char KYTY_MOUNT[] = "kyty_mount";
constexpr char KYTY_EXECUTE[] = "kyty_execute";
constexpr char KYTY_LOAD_ELF[] = "kyty_load_elf";
constexpr char KYTY_LOAD_SYMBOLS[] = "kyty_load_symbols";
constexpr char KYTY_LOAD_PARAM_SFO[] = "kyty_load_param_sfo";
constexpr char KYTY_INIT[] = "kyty_init";
constexpr char KYTY_LUA_FILE[] = "kyty_run.lua";
constexpr DWORD CMD_X_CHARS = 175;
@ -183,6 +184,7 @@ void MainDialogPrivate::FindInterpreter()
found = found && lines.contains(QString("Lua function: ") + KYTY_EXECUTE);
found = found && lines.contains(QString("Lua function: ") + KYTY_LOAD_ELF);
found = found && lines.contains(QString("Lua function: ") + KYTY_LOAD_SYMBOLS);
found = found && lines.contains(QString("Lua function: ") + KYTY_LOAD_PARAM_SFO);
found = found && lines.contains(QString("Lua function: ") + KYTY_INIT);
}
@ -234,11 +236,13 @@ static bool CreateLuaScript(Kyty::Configuration* info, const QString& file_name)
s << "\t PrintfOutputFile = '" << info->printf_output_file << "';\n";
s << "\t ProfilerDirection = '" << EnumToText(info->profiler_direction) << "';\n";
s << "\t ProfilerOutputFile = '" << info->profiler_output_file << "';\n";
s << "\t SpirvDebugPrintfEnabled = " << (info->spirv_debug_printf_enabled ? "true" : "false") << ";\n";
s << "\t SpirvDebugPrintfEnabled = false;\n";
s << "}\n";
s << KYTY_INIT << "(cfg);\n";
s << KYTY_MOUNT << "('" << info->BaseDir << "', '/app0');\n";
s << KYTY_MOUNT << "('" << info->basedir << "', '/app0');\n";
s << KYTY_LOAD_PARAM_SFO << "('" << info->param_file << "');\n";
for (const auto& elf: info->elfs_selected)
{
@ -357,7 +361,7 @@ void MainDialogPrivate::Update()
if (run_enabled && item != nullptr)
{
const auto* info = item->GetInfo();
auto dir = info->BaseDir;
auto dir = info->basedir;
run_enabled = !dir.isEmpty() && QDir(dir).exists();
}

View File

@ -9,225 +9,241 @@
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="43"/>
<location filename="../forms/configuration_edit_dialog.ui" line="56"/>
<source>Name:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="50"/>
<location filename="../forms/configuration_edit_dialog.ui" line="63"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Configuration name&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="84"/>
<location filename="../forms/configuration_edit_dialog.ui" line="97"/>
<source>Mount app0 to</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="93"/>
<location filename="../forms/configuration_edit_dialog.ui" line="112"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Name of the directory where game is located&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="103"/>
<location filename="../forms/configuration_edit_dialog.ui" line="122"/>
<location filename="../forms/configuration_edit_dialog.ui" line="159"/>
<source>Browse...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="138"/>
<location filename="../forms/configuration_edit_dialog.ui" line="271"/>
<source>Screen resoultion:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="145"/>
<location filename="../forms/configuration_edit_dialog.ui" line="278"/>
<source>Window resolution</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="161"/>
<location filename="../forms/configuration_edit_dialog.ui" line="203"/>
<source>Enable PS4 Pro mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="164"/>
<location filename="../forms/configuration_edit_dialog.ui" line="206"/>
<source>Neo</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="174"/>
<location filename="../forms/configuration_edit_dialog.ui" line="229"/>
<source>Validate SPIR-V binary</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="177"/>
<location filename="../forms/configuration_edit_dialog.ui" line="232"/>
<source>Shader validation</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="187"/>
<location filename="../forms/configuration_edit_dialog.ui" line="216"/>
<source>Enable Vulkan validation layers</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="190"/>
<source>Vulkan validation</source>
<location filename="../forms/configuration_edit_dialog.ui" line="140"/>
<source>Param file</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="200"/>
<source>Dump command buffers</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="203"/>
<source>Command buffer dump</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="216"/>
<source>Enable GL_EXT_debug_printf extension</source>
<location filename="../forms/configuration_edit_dialog.ui" line="149"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Path to &lt;span style=&quot; font-weight:600;&quot;&gt;param.sfo&lt;/span&gt; file&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="219"/>
<source>Spirv debug printf</source>
<source>Vulkan validation</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="229"/>
<location filename="../forms/configuration_edit_dialog.ui" line="242"/>
<source>Dump command buffers</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="245"/>
<source>Command buffer dump</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="285"/>
<source>Shader optimization type:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="236"/>
<location filename="../forms/configuration_edit_dialog.ui" line="292"/>
<source>Optimize shaders for code size or performance</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="243"/>
<location filename="../forms/configuration_edit_dialog.ui" line="306"/>
<source>Dump shaders to file or console window. If enabled may decrease emulator performance</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="250"/>
<location filename="../forms/configuration_edit_dialog.ui" line="320"/>
<source>Specify directory to dump shaders</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="260"/>
<location filename="../forms/configuration_edit_dialog.ui" line="337"/>
<source>Specify directory to dump command buffers</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="270"/>
<location filename="../forms/configuration_edit_dialog.ui" line="354"/>
<source>Print logs to file or console window. If enabled may decrease emulator performance</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="277"/>
<location filename="../forms/configuration_edit_dialog.ui" line="368"/>
<source>Specify file to dump logs</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="287"/>
<location filename="../forms/configuration_edit_dialog.ui" line="385"/>
<source>Enable/disable profiler. If enabled may decrease emulator performance</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="294"/>
<location filename="../forms/configuration_edit_dialog.ui" line="299"/>
<source>Shader log direction:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="301"/>
<location filename="../forms/configuration_edit_dialog.ui" line="313"/>
<source>Shader log folder:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="308"/>
<location filename="../forms/configuration_edit_dialog.ui" line="330"/>
<source>Command buffer dump folder:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="315"/>
<location filename="../forms/configuration_edit_dialog.ui" line="347"/>
<source>Printf direction:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="322"/>
<location filename="../forms/configuration_edit_dialog.ui" line="361"/>
<source>Printf output file:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="329"/>
<location filename="../forms/configuration_edit_dialog.ui" line="378"/>
<source>Profiler direction:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="336"/>
<location filename="../forms/configuration_edit_dialog.ui" line="399"/>
<source>Specify file to dump profiler info</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="346"/>
<location filename="../forms/configuration_edit_dialog.ui" line="392"/>
<source>Profiler output file:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="373"/>
<location filename="../forms/configuration_edit_dialog.ui" line="478"/>
<source>Load elf:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="380"/>
<location filename="../forms/configuration_edit_dialog.ui" line="485"/>
<source>Select executables to load</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="408"/>
<location filename="../forms/configuration_edit_dialog.ui" line="513"/>
<source>Select libraries to load</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="418"/>
<location filename="../forms/configuration_edit_dialog.ui" line="523"/>
<source>Load library:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="455"/>
<location filename="../forms/configuration_edit_dialog.ui" line="550"/>
<source>Save</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="471"/>
<location filename="../forms/configuration_edit_dialog.ui" line="566"/>
<source>Cancel</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="491"/>
<location filename="../forms/configuration_edit_dialog.ui" line="586"/>
<source>Clear</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../forms/configuration_edit_dialog.ui" line="507"/>
<location filename="../forms/configuration_edit_dialog.ui" line="602"/>
<source>Test</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/ConfigurationEditDialog.cpp" line="239"/>
<location filename="../src/ConfigurationEditDialog.cpp" line="251"/>
<source>Save failed</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/ConfigurationEditDialog.cpp" line="239"/>
<location filename="../src/ConfigurationEditDialog.cpp" line="251"/>
<source>Please fill all mandatory fields</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/ConfigurationEditDialog.cpp" line="252"/>
<location filename="../src/ConfigurationEditDialog.cpp" line="264"/>
<source>Open Directory</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/ConfigurationEditDialog.cpp" line="282"/>
<source>Select param.sfo</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/ConfigurationEditDialog.cpp" line="396"/>
<source>Parameter</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/ConfigurationEditDialog.cpp" line="396"/>
<source>Value</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ConfigurationListWidget</name>
@ -322,12 +338,12 @@
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/MainDialog.cpp" line="272"/>
<location filename="../src/MainDialog.cpp" line="276"/>
<source>Error</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/MainDialog.cpp" line="272"/>
<location filename="../src/MainDialog.cpp" line="276"/>
<source>Can&apos;t create file:
</source>
<translation type="unfinished"></translation>
@ -336,27 +352,27 @@
<context>
<name>MainDialogPrivate</name>
<message>
<location filename="../src/MainDialog.cpp" line="138"/>
<location filename="../src/MainDialog.cpp" line="139"/>
<source>Settings file: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/MainDialog.cpp" line="164"/>
<location filename="../src/MainDialog.cpp" line="165"/>
<source>Emulator: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/MainDialog.cpp" line="176"/>
<location filename="../src/MainDialog.cpp" line="177"/>
<source>Version: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/MainDialog.cpp" line="191"/>
<location filename="../src/MainDialog.cpp" line="193"/>
<source>Error</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/MainDialog.cpp" line="191"/>
<location filename="../src/MainDialog.cpp" line="193"/>
<source>Can&apos;t find emulator</source>
<translation type="unfinished"></translation>
</message>

View File

@ -13,7 +13,7 @@ add_library(unit_test STATIC ${unit_test_src})
target_link_libraries(unit_test core)
target_link_libraries(unit_test math)
target_include_directories(unit_test PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
#target_include_directories(unit_test PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
list(APPEND inc_headers
${PROJECT_BINARY_DIR}