mirror of
https://github.com/isledecomp/isle-portable.git
synced 2026-02-03 12:31:15 +00:00
commit
929b5767d4
@ -525,7 +525,7 @@ endif()
|
|||||||
if (ISLE_BUILD_CONFIG)
|
if (ISLE_BUILD_CONFIG)
|
||||||
find_package(Qt6 REQUIRED COMPONENTS Core Widgets)
|
find_package(Qt6 REQUIRED COMPONENTS Core Widgets)
|
||||||
qt_standard_project_setup()
|
qt_standard_project_setup()
|
||||||
qt_add_executable(config WIN32
|
qt_add_executable(isle-config WIN32
|
||||||
LEGO1/mxdirectx/mxdirectxinfo.cpp
|
LEGO1/mxdirectx/mxdirectxinfo.cpp
|
||||||
LEGO1/mxdirectx/legodxinfo.cpp
|
LEGO1/mxdirectx/legodxinfo.cpp
|
||||||
CONFIG/config.cpp
|
CONFIG/config.cpp
|
||||||
@ -535,22 +535,22 @@ if (ISLE_BUILD_CONFIG)
|
|||||||
CONFIG/res/config.rc
|
CONFIG/res/config.rc
|
||||||
CONFIG/res/config.qrc
|
CONFIG/res/config.qrc
|
||||||
)
|
)
|
||||||
target_link_libraries(config PRIVATE Qt6::Core Qt6::Widgets)
|
target_link_libraries(isle-config PRIVATE Qt6::Core Qt6::Widgets)
|
||||||
set_property(TARGET config PROPERTY AUTOMOC ON)
|
set_property(TARGET isle-config PROPERTY AUTOMOC ON)
|
||||||
set_property(TARGET config PROPERTY AUTORCC ON)
|
set_property(TARGET isle-config PROPERTY AUTORCC ON)
|
||||||
set_property(TARGET config PROPERTY AUTOUIC ON)
|
set_property(TARGET isle-config PROPERTY AUTOUIC ON)
|
||||||
set_property(TARGET config PROPERTY AUTOUIC_SEARCH_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/CONFIG/res")
|
set_property(TARGET isle-config PROPERTY AUTOUIC_SEARCH_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/CONFIG/res")
|
||||||
list(APPEND isle_targets config)
|
list(APPEND isle_targets isle-config)
|
||||||
target_compile_definitions(config PRIVATE _AFXDLL MXDIRECTX_FOR_CONFIG)
|
target_compile_definitions(isle-config PRIVATE _AFXDLL MXDIRECTX_FOR_CONFIG)
|
||||||
target_include_directories(config PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/LEGO1")
|
target_include_directories(isle-config PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/LEGO1")
|
||||||
target_include_directories(config PUBLIC "$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/util>")
|
target_include_directories(isle-config PUBLIC "$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/util>")
|
||||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 14)
|
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 14)
|
||||||
target_link_libraries(config PRIVATE DirectX5::DirectX5)
|
target_link_libraries(isle-config PRIVATE DirectX5::DirectX5)
|
||||||
endif()
|
endif()
|
||||||
target_compile_definitions(config PRIVATE DIRECT3D_VERSION=0x500)
|
target_compile_definitions(isle-config PRIVATE DIRECT3D_VERSION=0x500)
|
||||||
target_link_libraries(config PRIVATE SDL3::SDL3 Isle::iniparser)
|
target_link_libraries(isle-config PRIVATE SDL3::SDL3 Isle::iniparser)
|
||||||
if (NOT ISLE_MINIWIN)
|
if (NOT ISLE_MINIWIN)
|
||||||
target_link_libraries(config PRIVATE ddraw dxguid)
|
target_link_libraries(isle-config PRIVATE ddraw dxguid)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@ -564,8 +564,8 @@ if (MSVC)
|
|||||||
if (TARGET isle)
|
if (TARGET isle)
|
||||||
target_compile_definitions(isle PRIVATE "_CRT_SECURE_NO_WARNINGS")
|
target_compile_definitions(isle PRIVATE "_CRT_SECURE_NO_WARNINGS")
|
||||||
endif()
|
endif()
|
||||||
if (TARGET config)
|
if (TARGET isle-config)
|
||||||
target_compile_definitions(config PRIVATE "_CRT_SECURE_NO_WARNINGS")
|
target_compile_definitions(isle-config PRIVATE "_CRT_SECURE_NO_WARNINGS")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
# Visual Studio 2017 version 15.7 needs "/Zc:__cplusplus" for __cplusplus
|
# Visual Studio 2017 version 15.7 needs "/Zc:__cplusplus" for __cplusplus
|
||||||
@ -574,8 +574,8 @@ if (MSVC)
|
|||||||
if (TARGET isle)
|
if (TARGET isle)
|
||||||
target_compile_options(isle PRIVATE "-Zc:__cplusplus")
|
target_compile_options(isle PRIVATE "-Zc:__cplusplus")
|
||||||
endif()
|
endif()
|
||||||
if (TARGET config)
|
if (TARGET isle-config)
|
||||||
target_compile_options(config PRIVATE "-Zc:__cplusplus")
|
target_compile_options(isle-config PRIVATE "-Zc:__cplusplus")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
@ -633,7 +633,7 @@ install(TARGETS isle ${install_extra_targets}
|
|||||||
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||||
)
|
)
|
||||||
if (ISLE_BUILD_CONFIG)
|
if (ISLE_BUILD_CONFIG)
|
||||||
install(TARGETS config
|
install(TARGETS isle-config
|
||||||
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
|
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
@ -652,7 +652,7 @@ if(NINTENDO_3DS)
|
|||||||
DESCRIPTION "LEGO Island for the Nintendo 3DS"
|
DESCRIPTION "LEGO Island for the Nintendo 3DS"
|
||||||
AUTHOR "LEGO Island Decompilation and Porting Team"
|
AUTHOR "LEGO Island Decompilation and Porting Team"
|
||||||
VERSION "${PROJECT_VERSION}"
|
VERSION "${PROJECT_VERSION}"
|
||||||
ICON "isle/res/3ds/isle.png"
|
ICON "ISLE/res/3ds/isle.png"
|
||||||
)
|
)
|
||||||
|
|
||||||
ctr_create_3dsx(isle SMDH isle.smdh)
|
ctr_create_3dsx(isle SMDH isle.smdh)
|
||||||
|
|||||||
@ -11,6 +11,8 @@
|
|||||||
#include "res/resource.h"
|
#include "res/resource.h"
|
||||||
|
|
||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QProcess>
|
||||||
#include <mxdirectx/legodxinfo.h>
|
#include <mxdirectx/legodxinfo.h>
|
||||||
#include <ui_maindialog.h>
|
#include <ui_maindialog.h>
|
||||||
|
|
||||||
@ -56,18 +58,16 @@ CMainDialog::CMainDialog(QWidget* pParent) : QDialog(pParent)
|
|||||||
connect(m_ui->musicCheckBox, &QCheckBox::toggled, this, &CMainDialog::OnCheckboxMusic);
|
connect(m_ui->musicCheckBox, &QCheckBox::toggled, this, &CMainDialog::OnCheckboxMusic);
|
||||||
connect(m_ui->sound3DCheckBox, &QCheckBox::toggled, this, &CMainDialog::OnCheckbox3DSound);
|
connect(m_ui->sound3DCheckBox, &QCheckBox::toggled, this, &CMainDialog::OnCheckbox3DSound);
|
||||||
connect(m_ui->joystickCheckBox, &QCheckBox::toggled, this, &CMainDialog::OnCheckboxJoystick);
|
connect(m_ui->joystickCheckBox, &QCheckBox::toggled, this, &CMainDialog::OnCheckboxJoystick);
|
||||||
|
connect(m_ui->fullscreenCheckBox, &QCheckBox::toggled, this, &CMainDialog::OnCheckboxFullscreen);
|
||||||
connect(m_ui->okButton, &QPushButton::clicked, this, &CMainDialog::accept);
|
connect(m_ui->okButton, &QPushButton::clicked, this, &CMainDialog::accept);
|
||||||
connect(m_ui->cancelButton, &QPushButton::clicked, this, &CMainDialog::reject);
|
connect(m_ui->cancelButton, &QPushButton::clicked, this, &CMainDialog::reject);
|
||||||
|
connect(m_ui->launchButton, &QPushButton::clicked, this, &CMainDialog::launch);
|
||||||
|
|
||||||
connect(m_ui->diskPathOpen, &QPushButton::clicked, this, &CMainDialog::SelectDiskPathDialog);
|
connect(m_ui->dataPathOpen, &QPushButton::clicked, this, &CMainDialog::SelectDataPathDialog);
|
||||||
connect(m_ui->cdPathOpen, &QPushButton::clicked, this, &CMainDialog::SelectCDPathDialog);
|
|
||||||
connect(m_ui->mediaPathOpen, &QPushButton::clicked, this, &CMainDialog::SelectMediaPathDialog);
|
|
||||||
connect(m_ui->savePathOpen, &QPushButton::clicked, this, &CMainDialog::SelectSavePathDialog);
|
connect(m_ui->savePathOpen, &QPushButton::clicked, this, &CMainDialog::SelectSavePathDialog);
|
||||||
|
|
||||||
connect(m_ui->diskPath, &QLineEdit::textEdited, this, &CMainDialog::DiskPathEdited);
|
connect(m_ui->dataPath, &QLineEdit::editingFinished, this, &CMainDialog::DataPathEdited);
|
||||||
connect(m_ui->cdPath, &QLineEdit::textEdited, this, &CMainDialog::CDPathEdited);
|
connect(m_ui->savePath, &QLineEdit::editingFinished, this, &CMainDialog::SavePathEdited);
|
||||||
connect(m_ui->mediaPath, &QLineEdit::textEdited, this, &CMainDialog::MediaPathEdited);
|
|
||||||
connect(m_ui->savePath, &QLineEdit::textEdited, this, &CMainDialog::SavePathEdited);
|
|
||||||
|
|
||||||
connect(m_ui->maxLoDSlider, &QSlider::valueChanged, this, &CMainDialog::MaxLoDChanged);
|
connect(m_ui->maxLoDSlider, &QSlider::valueChanged, this, &CMainDialog::MaxLoDChanged);
|
||||||
connect(m_ui->maxActorsSlider, &QSlider::valueChanged, this, &CMainDialog::MaxActorsChanged);
|
connect(m_ui->maxActorsSlider, &QSlider::valueChanged, this, &CMainDialog::MaxActorsChanged);
|
||||||
@ -158,6 +158,30 @@ void CMainDialog::accept()
|
|||||||
QDialog::accept();
|
QDialog::accept();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CMainDialog::launch()
|
||||||
|
{
|
||||||
|
if (m_modified) {
|
||||||
|
currentConfigApp->WriteRegisterSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
QDir::setCurrent(QCoreApplication::applicationDirPath());
|
||||||
|
|
||||||
|
QMessageBox msgBox = QMessageBox(
|
||||||
|
QMessageBox::Warning,
|
||||||
|
QString("Error!"),
|
||||||
|
QString("Unable to locate isle executable!"),
|
||||||
|
QMessageBox::Close
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!QProcess::startDetached("./isle")) { // Check in isle-config directory
|
||||||
|
if (!QProcess::startDetached("isle")) { // Check in $PATH
|
||||||
|
msgBox.exec();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QDialog::accept();
|
||||||
|
}
|
||||||
|
|
||||||
// FUNCTION: CONFIG 0x00404360
|
// FUNCTION: CONFIG 0x00404360
|
||||||
void CMainDialog::UpdateInterface()
|
void CMainDialog::UpdateInterface()
|
||||||
{
|
{
|
||||||
@ -187,9 +211,8 @@ void CMainDialog::UpdateInterface()
|
|||||||
}
|
}
|
||||||
m_ui->joystickCheckBox->setChecked(currentConfigApp->m_use_joystick);
|
m_ui->joystickCheckBox->setChecked(currentConfigApp->m_use_joystick);
|
||||||
m_ui->musicCheckBox->setChecked(currentConfigApp->m_music);
|
m_ui->musicCheckBox->setChecked(currentConfigApp->m_music);
|
||||||
m_ui->diskPath->setText(QString::fromStdString(currentConfigApp->m_base_path));
|
m_ui->fullscreenCheckBox->setChecked(currentConfigApp->m_full_screen);
|
||||||
m_ui->cdPath->setText(QString::fromStdString(currentConfigApp->m_cd_path));
|
m_ui->dataPath->setText(QString::fromStdString(currentConfigApp->m_cd_path));
|
||||||
m_ui->mediaPath->setText(QString::fromStdString(currentConfigApp->m_media_path));
|
|
||||||
m_ui->savePath->setText(QString::fromStdString(currentConfigApp->m_save_path));
|
m_ui->savePath->setText(QString::fromStdString(currentConfigApp->m_save_path));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,54 +289,33 @@ void CMainDialog::OnCheckboxMusic(bool checked)
|
|||||||
UpdateInterface();
|
UpdateInterface();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMainDialog::SelectDiskPathDialog()
|
void CMainDialog::OnCheckboxFullscreen(bool checked)
|
||||||
{
|
{
|
||||||
QString disk_path = QString::fromStdString(currentConfigApp->m_base_path);
|
currentConfigApp->m_full_screen = checked;
|
||||||
disk_path = QFileDialog::getExistingDirectory(
|
|
||||||
this,
|
|
||||||
tr("Open Directory"),
|
|
||||||
disk_path,
|
|
||||||
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks
|
|
||||||
);
|
|
||||||
|
|
||||||
if (disk_path.toStdString() != "") {
|
|
||||||
currentConfigApp->m_base_path = disk_path.toStdString();
|
|
||||||
m_modified = true;
|
m_modified = true;
|
||||||
UpdateInterface();
|
UpdateInterface();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void CMainDialog::SelectCDPathDialog()
|
void CMainDialog::SelectDataPathDialog()
|
||||||
{
|
{
|
||||||
QString cd_path = QString::fromStdString(currentConfigApp->m_cd_path);
|
QString data_path = QString::fromStdString(currentConfigApp->m_cd_path);
|
||||||
cd_path = QFileDialog::getExistingDirectory(
|
data_path = QFileDialog::getExistingDirectory(
|
||||||
this,
|
this,
|
||||||
tr("Open Directory"),
|
tr("Open Directory"),
|
||||||
cd_path,
|
data_path,
|
||||||
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks
|
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks
|
||||||
);
|
);
|
||||||
|
|
||||||
if (cd_path.toStdString() != "") {
|
QDir data_dir = QDir(data_path);
|
||||||
currentConfigApp->m_cd_path = cd_path.toStdString();
|
|
||||||
m_modified = true;
|
|
||||||
UpdateInterface();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMainDialog::SelectMediaPathDialog()
|
if (data_dir.exists()) {
|
||||||
{
|
currentConfigApp->m_cd_path = data_dir.absolutePath().toStdString();
|
||||||
QString media_path = QString::fromStdString(currentConfigApp->m_media_path);
|
data_dir.cd(QString("DATA"));
|
||||||
media_path = QFileDialog::getExistingDirectory(
|
data_dir.cd(QString("disk"));
|
||||||
this,
|
currentConfigApp->m_base_path = data_dir.absolutePath().toStdString();
|
||||||
tr("Open Directory"),
|
|
||||||
media_path,
|
|
||||||
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks
|
|
||||||
);
|
|
||||||
if (media_path.toStdString() != "") {
|
|
||||||
currentConfigApp->m_media_path = media_path.toStdString();
|
|
||||||
m_modified = true;
|
m_modified = true;
|
||||||
UpdateInterface();
|
|
||||||
}
|
}
|
||||||
|
UpdateInterface();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMainDialog::SelectSavePathDialog()
|
void CMainDialog::SelectSavePathDialog()
|
||||||
@ -326,38 +328,39 @@ void CMainDialog::SelectSavePathDialog()
|
|||||||
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks
|
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks
|
||||||
);
|
);
|
||||||
|
|
||||||
if (save_path.toStdString() != "") {
|
QDir save_dir = QDir(save_path);
|
||||||
currentConfigApp->m_save_path = save_path.toStdString();
|
|
||||||
m_modified = true;
|
|
||||||
UpdateInterface();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMainDialog::DiskPathEdited(const QString& text)
|
if (save_dir.exists()) {
|
||||||
{
|
currentConfigApp->m_save_path = save_dir.absolutePath().toStdString();
|
||||||
currentConfigApp->m_base_path = text.toStdString();
|
|
||||||
m_modified = true;
|
m_modified = true;
|
||||||
|
}
|
||||||
UpdateInterface();
|
UpdateInterface();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMainDialog::CDPathEdited(const QString& text)
|
void CMainDialog::DataPathEdited()
|
||||||
{
|
{
|
||||||
currentConfigApp->m_cd_path = text.toStdString();
|
QDir data_dir = QDir(m_ui->dataPath->text());
|
||||||
|
|
||||||
|
if (data_dir.exists()) {
|
||||||
|
currentConfigApp->m_cd_path = data_dir.absolutePath().toStdString();
|
||||||
|
data_dir.cd(QString("DATA"));
|
||||||
|
data_dir.cd(QString("disk"));
|
||||||
|
currentConfigApp->m_base_path = data_dir.absolutePath().toStdString();
|
||||||
m_modified = true;
|
m_modified = true;
|
||||||
|
}
|
||||||
|
|
||||||
UpdateInterface();
|
UpdateInterface();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMainDialog::MediaPathEdited(const QString& text)
|
void CMainDialog::SavePathEdited()
|
||||||
{
|
{
|
||||||
currentConfigApp->m_media_path = text.toStdString();
|
|
||||||
m_modified = true;
|
|
||||||
UpdateInterface();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMainDialog::SavePathEdited(const QString& text)
|
QDir save_dir = QDir(m_ui->savePath->text());
|
||||||
{
|
|
||||||
currentConfigApp->m_save_path = text.toStdString();
|
if (save_dir.exists()) {
|
||||||
|
currentConfigApp->m_save_path = save_dir.absolutePath().toStdString();
|
||||||
m_modified = true;
|
m_modified = true;
|
||||||
|
}
|
||||||
UpdateInterface();
|
UpdateInterface();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -42,16 +42,14 @@ private slots:
|
|||||||
void OnRadiobuttonTextureHighQuality(bool checked);
|
void OnRadiobuttonTextureHighQuality(bool checked);
|
||||||
void OnCheckboxJoystick(bool checked);
|
void OnCheckboxJoystick(bool checked);
|
||||||
void OnCheckboxMusic(bool checked);
|
void OnCheckboxMusic(bool checked);
|
||||||
|
void OnCheckboxFullscreen(bool checked);
|
||||||
void accept() override;
|
void accept() override;
|
||||||
void reject() override;
|
void reject() override;
|
||||||
void SelectDiskPathDialog();
|
void launch();
|
||||||
void SelectCDPathDialog();
|
void SelectDataPathDialog();
|
||||||
void SelectMediaPathDialog();
|
|
||||||
void SelectSavePathDialog();
|
void SelectSavePathDialog();
|
||||||
void DiskPathEdited(const QString& text);
|
void DataPathEdited();
|
||||||
void CDPathEdited(const QString& text);
|
void SavePathEdited();
|
||||||
void MediaPathEdited(const QString& text);
|
|
||||||
void SavePathEdited(const QString& text);
|
|
||||||
void MaxLoDChanged(int value);
|
void MaxLoDChanged(int value);
|
||||||
void MaxActorsChanged(int value);
|
void MaxActorsChanged(int value);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -141,7 +141,6 @@ bool CConfigApp::ReadRegisterSettings()
|
|||||||
}
|
}
|
||||||
m_base_path = iniparser_getstring(dict, "isle:diskpath", m_base_path.c_str());
|
m_base_path = iniparser_getstring(dict, "isle:diskpath", m_base_path.c_str());
|
||||||
m_cd_path = iniparser_getstring(dict, "isle:cdpath", m_cd_path.c_str());
|
m_cd_path = iniparser_getstring(dict, "isle:cdpath", m_cd_path.c_str());
|
||||||
m_media_path = iniparser_getstring(dict, "isle:mediapath", m_media_path.c_str());
|
|
||||||
m_save_path = iniparser_getstring(dict, "isle:savepath", m_save_path.c_str());
|
m_save_path = iniparser_getstring(dict, "isle:savepath", m_save_path.c_str());
|
||||||
m_display_bit_depth = iniparser_getint(dict, "isle:Display Bit Depth", -1);
|
m_display_bit_depth = iniparser_getint(dict, "isle:Display Bit Depth", -1);
|
||||||
m_flip_surfaces = iniparser_getboolean(dict, "isle:Flip Surfaces", m_flip_surfaces);
|
m_flip_surfaces = iniparser_getboolean(dict, "isle:Flip Surfaces", m_flip_surfaces);
|
||||||
@ -166,10 +165,6 @@ bool CConfigApp::ValidateSettings()
|
|||||||
{
|
{
|
||||||
BOOL is_modified = FALSE;
|
BOOL is_modified = FALSE;
|
||||||
|
|
||||||
if (!IsPrimaryDriver() && !m_full_screen) {
|
|
||||||
m_full_screen = TRUE;
|
|
||||||
is_modified = TRUE;
|
|
||||||
}
|
|
||||||
if (IsDeviceInBasicRGBMode()) {
|
if (IsDeviceInBasicRGBMode()) {
|
||||||
if (m_3d_video_ram) {
|
if (m_3d_video_ram) {
|
||||||
m_3d_video_ram = FALSE;
|
m_3d_video_ram = FALSE;
|
||||||
@ -203,10 +198,6 @@ bool CConfigApp::ValidateSettings()
|
|||||||
m_3d_video_ram = TRUE;
|
m_3d_video_ram = TRUE;
|
||||||
is_modified = TRUE;
|
is_modified = TRUE;
|
||||||
}
|
}
|
||||||
if (!m_full_screen) {
|
|
||||||
m_full_screen = TRUE;
|
|
||||||
is_modified = TRUE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if ((m_display_bit_depth != 8 && m_display_bit_depth != 16) && (m_display_bit_depth != 0 || m_full_screen)) {
|
if ((m_display_bit_depth != 8 && m_display_bit_depth != 16) && (m_display_bit_depth != 0 || m_full_screen)) {
|
||||||
m_display_bit_depth = 16;
|
m_display_bit_depth = 16;
|
||||||
@ -302,7 +293,6 @@ void CConfigApp::WriteRegisterSettings() const
|
|||||||
}
|
}
|
||||||
iniparser_set(dict, "isle:diskpath", m_base_path.c_str());
|
iniparser_set(dict, "isle:diskpath", m_base_path.c_str());
|
||||||
iniparser_set(dict, "isle:cdpath", m_cd_path.c_str());
|
iniparser_set(dict, "isle:cdpath", m_cd_path.c_str());
|
||||||
iniparser_set(dict, "isle:mediapath", m_media_path.c_str());
|
|
||||||
iniparser_set(dict, "isle:savepath", m_save_path.c_str());
|
iniparser_set(dict, "isle:savepath", m_save_path.c_str());
|
||||||
|
|
||||||
SetIniInt(dict, "isle:Display Bit Depth", m_display_bit_depth);
|
SetIniInt(dict, "isle:Display Bit Depth", m_display_bit_depth);
|
||||||
|
|||||||
@ -77,7 +77,6 @@ class CConfigApp {
|
|||||||
std::string m_iniPath;
|
std::string m_iniPath;
|
||||||
std::string m_base_path;
|
std::string m_base_path;
|
||||||
std::string m_cd_path;
|
std::string m_cd_path;
|
||||||
std::string m_media_path;
|
|
||||||
std::string m_save_path;
|
std::string m_save_path;
|
||||||
float m_max_lod;
|
float m_max_lod;
|
||||||
int m_max_actors;
|
int m_max_actors;
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>575</width>
|
<width>575</width>
|
||||||
<height>650</height>
|
<height>600</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
@ -44,6 +44,9 @@
|
|||||||
<height>16777215</height>
|
<height>16777215</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Jaws.</string>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
@ -76,13 +79,7 @@
|
|||||||
<property name="bottomMargin">
|
<property name="bottomMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="2" column="1">
|
<item row="5" column="2">
|
||||||
<widget class="QLineEdit" name="cdPath"/>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
|
||||||
<widget class="QLineEdit" name="mediaPath"/>
|
|
||||||
</item>
|
|
||||||
<item row="7" column="2">
|
|
||||||
<widget class="QPushButton" name="savePathOpen">
|
<widget class="QPushButton" name="savePathOpen">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||||
@ -101,68 +98,8 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="2">
|
|
||||||
<widget class="QPushButton" name="mediaPathOpen">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>55</width>
|
|
||||||
<height>16777215</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Open</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="2">
|
|
||||||
<widget class="QPushButton" name="cdPathOpen">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>55</width>
|
|
||||||
<height>16777215</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Open</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="cdPathLabel">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>CD Path:</string>
|
|
||||||
</property>
|
|
||||||
<property name="textFormat">
|
|
||||||
<enum>Qt::PlainText</enum>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QLineEdit" name="diskPath"/>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="2">
|
<item row="0" column="2">
|
||||||
<widget class="QPushButton" name="diskPathOpen">
|
<widget class="QPushButton" name="dataPathOpen">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@ -180,26 +117,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="0">
|
<item row="5" column="0">
|
||||||
<widget class="QLabel" name="diskPathLabel">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Disk Path:</string>
|
|
||||||
</property>
|
|
||||||
<property name="textFormat">
|
|
||||||
<enum>Qt::PlainText</enum>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="7" column="0">
|
|
||||||
<widget class="QLabel" name="savePathLabel">
|
<widget class="QLabel" name="savePathLabel">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
@ -218,8 +136,22 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="0" column="1">
|
||||||
<widget class="QLabel" name="mediaPathLabel">
|
<widget class="QLineEdit" name="dataPath">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Path to the game data files. Set this to the CD image root.</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="1">
|
||||||
|
<widget class="QLineEdit" name="savePath">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Folder where save files are kept.</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="dataPathLabel">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@ -227,7 +159,7 @@
|
|||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Media Path:</string>
|
<string>Data Path:</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="textFormat">
|
<property name="textFormat">
|
||||||
<enum>Qt::PlainText</enum>
|
<enum>Qt::PlainText</enum>
|
||||||
@ -237,9 +169,6 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="1">
|
|
||||||
<widget class="QLineEdit" name="savePath"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -266,6 +195,9 @@
|
|||||||
<height>120</height>
|
<height>120</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Set 3D model detail level.</string>
|
||||||
|
</property>
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Island Model Quality</string>
|
<string>Island Model Quality</string>
|
||||||
</property>
|
</property>
|
||||||
@ -345,6 +277,9 @@
|
|||||||
</item>
|
</item>
|
||||||
<item row="0" column="2">
|
<item row="0" column="2">
|
||||||
<widget class="QGroupBox" name="textureQualityGroup">
|
<widget class="QGroupBox" name="textureQualityGroup">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Set texture detail level.</string>
|
||||||
|
</property>
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Island Texture Quality</string>
|
<string>Island Texture Quality</string>
|
||||||
</property>
|
</property>
|
||||||
@ -422,16 +357,13 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QWidget" name="musicJoystickWidget" native="true">
|
<widget class="QWidget" name="checkboxWidget" native="true">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
<property name="topMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="sound3DCheckBox">
|
<widget class="QCheckBox" name="sound3DCheckBox">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Enable 3D positional audio effects.</string>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>3D Sound</string>
|
<string>3D Sound</string>
|
||||||
</property>
|
</property>
|
||||||
@ -439,6 +371,9 @@
|
|||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="musicCheckBox">
|
<widget class="QCheckBox" name="musicCheckBox">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Enable in-game background music.</string>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Music</string>
|
<string>Music</string>
|
||||||
</property>
|
</property>
|
||||||
@ -446,11 +381,24 @@
|
|||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="joystickCheckBox">
|
<widget class="QCheckBox" name="joystickCheckBox">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Enable joystick and gamepad support for LEGO Island.</string>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Use Joystick</string>
|
<string>Use Joystick</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="fullscreenCheckBox">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Toggle fullscreen display mode.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Fullscreen</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -462,6 +410,9 @@
|
|||||||
<height>225</height>
|
<height>225</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>3D graphics device used to render the game.</string>
|
||||||
|
</property>
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
@ -557,8 +508,11 @@
|
|||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="okButton">
|
<widget class="QPushButton" name="okButton">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Save configuration and close the config tool.</string>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>OK</string>
|
<string>Save and Exit</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="default">
|
<property name="default">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
@ -566,9 +520,22 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="cancelButton">
|
<widget class="QPushButton" name="launchButton">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Save configuration and launch LEGO Island.</string>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Cancel</string>
|
<string>Save and Launch</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="cancelButton">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Discard changed settings and close the config tool.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Exit without saving</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -581,12 +548,8 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<tabstops>
|
<tabstops>
|
||||||
<tabstop>diskPath</tabstop>
|
<tabstop>dataPath</tabstop>
|
||||||
<tabstop>diskPathOpen</tabstop>
|
<tabstop>dataPathOpen</tabstop>
|
||||||
<tabstop>cdPath</tabstop>
|
|
||||||
<tabstop>cdPathOpen</tabstop>
|
|
||||||
<tabstop>mediaPath</tabstop>
|
|
||||||
<tabstop>mediaPathOpen</tabstop>
|
|
||||||
<tabstop>savePath</tabstop>
|
<tabstop>savePath</tabstop>
|
||||||
<tabstop>savePathOpen</tabstop>
|
<tabstop>savePathOpen</tabstop>
|
||||||
<tabstop>textureQualityFastRadioButton</tabstop>
|
<tabstop>textureQualityFastRadioButton</tabstop>
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
diff --git a/src/lib/libwasmfs_fetch.js b/src/lib/libwasmfs_fetch.js
|
diff --git a/src/lib/libwasmfs_fetch.js b/src/lib/libwasmfs_fetch.js
|
||||||
index e8c9f7e21..1c0eea957 100644
|
index e8c9f7e21..caf1971d2 100644
|
||||||
--- a/src/lib/libwasmfs_fetch.js
|
--- a/src/lib/libwasmfs_fetch.js
|
||||||
+++ b/src/lib/libwasmfs_fetch.js
|
+++ b/src/lib/libwasmfs_fetch.js
|
||||||
@@ -38,36 +38,7 @@ addToLibrary({
|
@@ -38,36 +38,7 @@ addToLibrary({
|
||||||
@ -89,7 +89,21 @@ index e8c9f7e21..1c0eea957 100644
|
|||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,6 +156,21 @@ addToLibrary({
|
@@ -156,14 +148,31 @@ addToLibrary({
|
||||||
|
return readLength;
|
||||||
|
},
|
||||||
|
getSize: async (file) => {
|
||||||
|
- try {
|
||||||
|
- await getFileRange(file, 0, 0);
|
||||||
|
- } catch (failedResponse) {
|
||||||
|
- return 0;
|
||||||
|
+ if (!(file in wasmFS$JSMemoryRanges)) {
|
||||||
|
+ try {
|
||||||
|
+ await getFileRange(file, undefined, undefined);
|
||||||
|
+ } catch (failedResponse) {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
return wasmFS$JSMemoryRanges[file].size;
|
return wasmFS$JSMemoryRanges[file].size;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -704,6 +704,7 @@ MxResult IsleApp::SetupWindow()
|
|||||||
return FAILURE;
|
return FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DetectGameVersion();
|
||||||
GameState()->SerializePlayersInfo(LegoStorage::c_read);
|
GameState()->SerializePlayersInfo(LegoStorage::c_read);
|
||||||
GameState()->SerializeScoreHistory(LegoStorage::c_read);
|
GameState()->SerializeScoreHistory(LegoStorage::c_read);
|
||||||
|
|
||||||
@ -912,7 +913,7 @@ inline bool IsleApp::Tick()
|
|||||||
static MxLong g_lastFrameTime = 0;
|
static MxLong g_lastFrameTime = 0;
|
||||||
|
|
||||||
// GLOBAL: ISLE 0x4101bc
|
// GLOBAL: ISLE 0x4101bc
|
||||||
static MxS32 g_startupDelay = 200;
|
static MxS32 g_startupDelay = 1;
|
||||||
|
|
||||||
if (IsleDebug_Paused() && IsleDebug_StepModeEnabled()) {
|
if (IsleDebug_Paused() && IsleDebug_StepModeEnabled()) {
|
||||||
IsleDebug_SetPaused(false);
|
IsleDebug_SetPaused(false);
|
||||||
@ -1099,6 +1100,34 @@ MxResult IsleApp::VerifyFilesystem()
|
|||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IsleApp::DetectGameVersion()
|
||||||
|
{
|
||||||
|
const char* file = "/lego/scripts/infocntr/infomain.si";
|
||||||
|
SDL_PathInfo info;
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
|
MxString path = MxString(m_hdPath) + file;
|
||||||
|
path.MapPathToFilesystem();
|
||||||
|
if (!(success = SDL_GetPathInfo(path.GetData(), &info))) {
|
||||||
|
path = MxString(m_cdPath) + file;
|
||||||
|
path.MapPathToFilesystem();
|
||||||
|
success = SDL_GetPathInfo(path.GetData(), &info);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(success);
|
||||||
|
|
||||||
|
// File sizes of INFOMAIN.SI in English 1.0 and Japanese 1.0
|
||||||
|
Lego()->SetVersion10(info.size == 58130432 || info.size == 57737216);
|
||||||
|
|
||||||
|
if (Lego()->IsVersion10()) {
|
||||||
|
SDL_Log("Detected game version 1.0");
|
||||||
|
SDL_SetWindowTitle(reinterpret_cast<SDL_Window*>(m_windowHandle), "Lego Island");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SDL_Log("Detected game version 1.1");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
IDirect3DRMMiniwinDevice* GetD3DRMMiniwinDevice()
|
IDirect3DRMMiniwinDevice* GetD3DRMMiniwinDevice()
|
||||||
{
|
{
|
||||||
LegoVideoManager* videoManager = LegoOmni::GetInstance()->GetVideoManager();
|
LegoVideoManager* videoManager = LegoOmni::GetInstance()->GetVideoManager();
|
||||||
|
|||||||
@ -56,6 +56,7 @@ class IsleApp {
|
|||||||
|
|
||||||
MxResult ParseArguments(int argc, char** argv);
|
MxResult ParseArguments(int argc, char** argv);
|
||||||
MxResult VerifyFilesystem();
|
MxResult VerifyFilesystem();
|
||||||
|
void DetectGameVersion();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char* m_hdPath; // 0x00
|
char* m_hdPath; // 0x00
|
||||||
|
|||||||
@ -309,7 +309,7 @@ void IsleDebug_Render()
|
|||||||
if (ImGui::TreeNode("Sound Manager")) {
|
if (ImGui::TreeNode("Sound Manager")) {
|
||||||
LegoSoundManager* soundManager = lego->GetSoundManager();
|
LegoSoundManager* soundManager = lego->GetSoundManager();
|
||||||
Sint32 oldVolume = soundManager->GetVolume();
|
Sint32 oldVolume = soundManager->GetVolume();
|
||||||
Sint32 volume = oldVolume;
|
int volume = oldVolume;
|
||||||
ImGui::SliderInt("volume", &volume, 0, 100);
|
ImGui::SliderInt("volume", &volume, 0, 100);
|
||||||
if (volume != oldVolume) {
|
if (volume != oldVolume) {
|
||||||
soundManager->SetVolume(volume);
|
soundManager->SetVolume(volume);
|
||||||
|
|||||||
@ -11,6 +11,12 @@ class MxEndActionNotificationParam;
|
|||||||
// SIZE 0x24
|
// SIZE 0x24
|
||||||
class AmbulanceMissionState : public LegoState {
|
class AmbulanceMissionState : public LegoState {
|
||||||
public:
|
public:
|
||||||
|
enum {
|
||||||
|
e_ready = 0,
|
||||||
|
e_enteredAmbulance = 1,
|
||||||
|
e_prepareAmbulance = 2,
|
||||||
|
};
|
||||||
|
|
||||||
AmbulanceMissionState();
|
AmbulanceMissionState();
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x10037440
|
// FUNCTION: LEGO1 0x10037440
|
||||||
@ -125,7 +131,7 @@ class AmbulanceMissionState : public LegoState {
|
|||||||
// SYNTHETIC: LEGO1 0x100376c0
|
// SYNTHETIC: LEGO1 0x100376c0
|
||||||
// AmbulanceMissionState::`scalar deleting destructor'
|
// AmbulanceMissionState::`scalar deleting destructor'
|
||||||
|
|
||||||
undefined4 m_unk0x08; // 0x08
|
MxU32 m_state; // 0x08
|
||||||
MxLong m_startTime; // 0x0c
|
MxLong m_startTime; // 0x0c
|
||||||
MxS16 m_peScore; // 0x10
|
MxS16 m_peScore; // 0x10
|
||||||
MxS16 m_maScore; // 0x12
|
MxS16 m_maScore; // 0x12
|
||||||
@ -177,15 +183,21 @@ class Ambulance : public IslePathActor {
|
|||||||
virtual MxLong HandleEndAction(MxEndActionNotificationParam& p_param); // vtable+0xf4
|
virtual MxLong HandleEndAction(MxEndActionNotificationParam& p_param); // vtable+0xf4
|
||||||
|
|
||||||
void CreateState();
|
void CreateState();
|
||||||
void FUN_10036e60();
|
void Init();
|
||||||
void ActivateSceneActions();
|
void ActivateSceneActions();
|
||||||
void StopActions();
|
void StopActions();
|
||||||
void FUN_10037250();
|
void Reset();
|
||||||
|
|
||||||
// SYNTHETIC: LEGO1 0x10036130
|
// SYNTHETIC: LEGO1 0x10036130
|
||||||
// Ambulance::`scalar deleting destructor'
|
// Ambulance::`scalar deleting destructor'
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
enum {
|
||||||
|
e_none = 0,
|
||||||
|
e_waiting = 1,
|
||||||
|
e_finished = 3,
|
||||||
|
};
|
||||||
|
|
||||||
void PlayAnimation(IsleScript::Script p_objectId);
|
void PlayAnimation(IsleScript::Script p_objectId);
|
||||||
void PlayFinalAnimation(IsleScript::Script p_objectId);
|
void PlayFinalAnimation(IsleScript::Script p_objectId);
|
||||||
void StopAction(IsleScript::Script p_objectId);
|
void StopAction(IsleScript::Script p_objectId);
|
||||||
@ -196,9 +208,9 @@ class Ambulance : public IslePathActor {
|
|||||||
AmbulanceMissionState* m_state; // 0x164
|
AmbulanceMissionState* m_state; // 0x164
|
||||||
MxS16 m_unk0x168; // 0x168
|
MxS16 m_unk0x168; // 0x168
|
||||||
MxS16 m_actorId; // 0x16a
|
MxS16 m_actorId; // 0x16a
|
||||||
MxS16 m_unk0x16c; // 0x16c
|
MxS16 m_atPoliceTask; // 0x16c
|
||||||
MxS16 m_unk0x16e; // 0x16e
|
MxS16 m_atBeachTask; // 0x16e
|
||||||
MxS16 m_unk0x170; // 0x170
|
MxS16 m_taskState; // 0x170
|
||||||
MxS16 m_unk0x172; // 0x172
|
MxS16 m_unk0x172; // 0x172
|
||||||
IsleScript::Script m_lastAction; // 0x174
|
IsleScript::Script m_lastAction; // 0x174
|
||||||
IsleScript::Script m_lastAnimation; // 0x178
|
IsleScript::Script m_lastAnimation; // 0x178
|
||||||
|
|||||||
@ -200,6 +200,9 @@ class LegoOmni : public MxOmni {
|
|||||||
SDL_PushEvent(&event);
|
SDL_PushEvent(&event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetVersion10(MxBool p_version10) { m_version10 = p_version10; }
|
||||||
|
MxBool IsVersion10() { return m_version10; }
|
||||||
|
|
||||||
// SYNTHETIC: LEGO1 0x10058b30
|
// SYNTHETIC: LEGO1 0x10058b30
|
||||||
// LegoOmni::`scalar deleting destructor'
|
// LegoOmni::`scalar deleting destructor'
|
||||||
|
|
||||||
@ -221,6 +224,7 @@ class LegoOmni : public MxOmni {
|
|||||||
MxDSAction m_action; // 0xa0
|
MxDSAction m_action; // 0xa0
|
||||||
MxBackgroundAudioManager* m_bkgAudioManager; // 0x134
|
MxBackgroundAudioManager* m_bkgAudioManager; // 0x134
|
||||||
MxTransitionManager* m_transitionManager; // 0x138
|
MxTransitionManager* m_transitionManager; // 0x138
|
||||||
|
MxBool m_version10;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MxBool m_unk0x13c; // 0x13c
|
MxBool m_unk0x13c; // 0x13c
|
||||||
|
|||||||
@ -13,7 +13,7 @@ struct LegoPathEdgeContainer;
|
|||||||
struct LegoOrientedEdge;
|
struct LegoOrientedEdge;
|
||||||
class LegoWEEdge;
|
class LegoWEEdge;
|
||||||
|
|
||||||
extern MxLong g_unk0x100f3308;
|
extern MxLong g_timeLastHitSoundPlayed;
|
||||||
extern const char* g_strHIT_WALL_SOUND;
|
extern const char* g_strHIT_WALL_SOUND;
|
||||||
|
|
||||||
// VTABLE: LEGO1 0x100d6e28
|
// VTABLE: LEGO1 0x100d6e28
|
||||||
|
|||||||
@ -54,7 +54,7 @@ class LEGO1_EXPORT LegoPlantManager : public MxCore {
|
|||||||
LegoEntity* CreatePlant(MxS32 p_index, LegoWorld* p_world, LegoOmni::World p_worldId);
|
LegoEntity* CreatePlant(MxS32 p_index, LegoWorld* p_world, LegoOmni::World p_worldId);
|
||||||
MxBool DecrementCounter(LegoEntity* p_entity);
|
MxBool DecrementCounter(LegoEntity* p_entity);
|
||||||
void ScheduleAnimation(LegoEntity* p_entity, MxLong p_length);
|
void ScheduleAnimation(LegoEntity* p_entity, MxLong p_length);
|
||||||
MxResult FUN_10026410();
|
MxResult DetermineBoundaries();
|
||||||
void ClearCounters();
|
void ClearCounters();
|
||||||
void SetInitialCounters();
|
void SetInitialCounters();
|
||||||
|
|
||||||
@ -78,7 +78,7 @@ class LEGO1_EXPORT LegoPlantManager : public MxCore {
|
|||||||
static MxU32 g_maxSound;
|
static MxU32 g_maxSound;
|
||||||
|
|
||||||
LegoOmni::World m_worldId; // 0x08
|
LegoOmni::World m_worldId; // 0x08
|
||||||
undefined m_unk0x0c; // 0x0c
|
MxBool m_boundariesDetermined; // 0x0c
|
||||||
AnimEntry* m_entries[5]; // 0x10
|
AnimEntry* m_entries[5]; // 0x10
|
||||||
MxS8 m_numEntries; // 0x24
|
MxS8 m_numEntries; // 0x24
|
||||||
LegoWorld* m_world; // 0x28
|
LegoWorld* m_world; // 0x28
|
||||||
|
|||||||
@ -144,10 +144,10 @@ class LegoRaceCar : public LegoCarRaceActor, public LegoRaceMap {
|
|||||||
MxResult VTable0x9c() override; // vtable+0x9c
|
MxResult VTable0x9c() override; // vtable+0x9c
|
||||||
|
|
||||||
virtual void SetMaxLinearVelocity(float p_maxLinearVelocity);
|
virtual void SetMaxLinearVelocity(float p_maxLinearVelocity);
|
||||||
virtual void FUN_10012ff0(float p_param);
|
virtual void KickCamera(float p_param);
|
||||||
virtual MxU32 HandleSkeletonKicks(float p_param1);
|
virtual MxU32 HandleSkeletonKicks(float p_param1);
|
||||||
|
|
||||||
static void FUN_10012de0();
|
static void InitYouCantStopSound();
|
||||||
static void InitSoundIndices();
|
static void InitSoundIndices();
|
||||||
|
|
||||||
// SYNTHETIC: LEGO1 0x10014240
|
// SYNTHETIC: LEGO1 0x10014240
|
||||||
@ -155,7 +155,7 @@ class LegoRaceCar : public LegoCarRaceActor, public LegoRaceMap {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
undefined m_userState; // 0x54
|
undefined m_userState; // 0x54
|
||||||
float m_unk0x58; // 0x58
|
float m_kickStart; // 0x58
|
||||||
Mx3DPointFloat m_unk0x5c; // 0x5c
|
Mx3DPointFloat m_unk0x5c; // 0x5c
|
||||||
|
|
||||||
// Names verified by BETA10 0x100cb4a9
|
// Names verified by BETA10 0x100cb4a9
|
||||||
|
|||||||
@ -44,8 +44,11 @@ class LegoCarRaceActor : public virtual LegoRaceActor {
|
|||||||
Vector3& p_v3
|
Vector3& p_v3
|
||||||
) override; // vtable+0x6c
|
) override; // vtable+0x6c
|
||||||
void Animate(float p_time) override; // vtable+0x70
|
void Animate(float p_time) override; // vtable+0x70
|
||||||
void SwitchBoundary(LegoPathBoundary*& p_boundary, LegoOrientedEdge*& p_edge, float& p_unk0xe4)
|
void SwitchBoundary(
|
||||||
override; // vtable+0x98
|
LegoPathBoundary*& p_boundary,
|
||||||
|
LegoOrientedEdge*& p_edge,
|
||||||
|
float& p_unk0xe4
|
||||||
|
) override; // vtable+0x98
|
||||||
MxResult VTable0x9c() override; // vtable+0x9c
|
MxResult VTable0x9c() override; // vtable+0x9c
|
||||||
|
|
||||||
// LegoCarRaceActor vtable
|
// LegoCarRaceActor vtable
|
||||||
@ -83,7 +86,7 @@ class LegoCarRaceActor : public virtual LegoRaceActor {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
MxFloat m_unk0x08; // 0x08
|
MxFloat m_unk0x08; // 0x08
|
||||||
MxU8 m_unk0x0c; // 0x0c
|
MxU8 m_animState; // 0x0c
|
||||||
|
|
||||||
// Could be a multiplier for the maximum speed when going straight
|
// Could be a multiplier for the maximum speed when going straight
|
||||||
MxFloat m_unk0x10; // 0x10
|
MxFloat m_unk0x10; // 0x10
|
||||||
|
|||||||
@ -40,9 +40,9 @@ Ambulance::Ambulance()
|
|||||||
m_state = NULL;
|
m_state = NULL;
|
||||||
m_unk0x168 = 0;
|
m_unk0x168 = 0;
|
||||||
m_actorId = -1;
|
m_actorId = -1;
|
||||||
m_unk0x16c = 0;
|
m_atPoliceTask = 0;
|
||||||
m_unk0x16e = 0;
|
m_atBeachTask = 0;
|
||||||
m_unk0x170 = 0;
|
m_taskState = Ambulance::e_none;
|
||||||
m_lastAction = IsleScript::c_noneIsle;
|
m_lastAction = IsleScript::c_noneIsle;
|
||||||
m_unk0x172 = 0;
|
m_unk0x172 = 0;
|
||||||
m_lastAnimation = IsleScript::c_noneIsle;
|
m_lastAnimation = IsleScript::c_noneIsle;
|
||||||
@ -73,7 +73,7 @@ MxResult Ambulance::Create(MxDSAction& p_dsAction)
|
|||||||
m_state = (AmbulanceMissionState*) GameState()->GetState("AmbulanceMissionState");
|
m_state = (AmbulanceMissionState*) GameState()->GetState("AmbulanceMissionState");
|
||||||
if (!m_state) {
|
if (!m_state) {
|
||||||
m_state = new AmbulanceMissionState();
|
m_state = new AmbulanceMissionState();
|
||||||
m_state->m_unk0x08 = 0;
|
m_state->m_state = AmbulanceMissionState::e_ready;
|
||||||
GameState()->RegisterState(m_state);
|
GameState()->RegisterState(m_state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -173,25 +173,25 @@ MxLong Ambulance::HandleEndAction(MxEndActionNotificationParam& p_param)
|
|||||||
m_lastAction = IsleScript::c_noneIsle;
|
m_lastAction = IsleScript::c_noneIsle;
|
||||||
}
|
}
|
||||||
else if (objectId == IsleScript::c_hho027en_RunAnim) {
|
else if (objectId == IsleScript::c_hho027en_RunAnim) {
|
||||||
m_state->m_unk0x08 = 1;
|
m_state->m_state = AmbulanceMissionState::e_enteredAmbulance;
|
||||||
CurrentWorld()->PlaceActor(UserActor());
|
CurrentWorld()->PlaceActor(UserActor());
|
||||||
HandleClick();
|
HandleClick();
|
||||||
m_unk0x172 = 0;
|
m_unk0x172 = 0;
|
||||||
TickleManager()->RegisterClient(this, 40000);
|
TickleManager()->RegisterClient(this, 40000);
|
||||||
}
|
}
|
||||||
else if (objectId == IsleScript::c_hpz047pe_RunAnim || objectId == IsleScript::c_hpz048pe_RunAnim || objectId == IsleScript::c_hpz049bd_RunAnim || objectId == IsleScript::c_hpz053pa_RunAnim) {
|
else if (objectId == IsleScript::c_hpz047pe_RunAnim || objectId == IsleScript::c_hpz048pe_RunAnim || objectId == IsleScript::c_hpz049bd_RunAnim || objectId == IsleScript::c_hpz053pa_RunAnim) {
|
||||||
if (m_unk0x170 == 3) {
|
if (m_taskState == Ambulance::e_finished) {
|
||||||
PlayAnimation(IsleScript::c_hpz055pa_RunAnim);
|
PlayAnimation(IsleScript::c_hpz055pa_RunAnim);
|
||||||
m_unk0x170 = 0;
|
m_taskState = Ambulance::e_none;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
PlayAnimation(IsleScript::c_hpz053pa_RunAnim);
|
PlayAnimation(IsleScript::c_hpz053pa_RunAnim);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (objectId == IsleScript::c_hpz050bd_RunAnim || objectId == IsleScript::c_hpz052ma_RunAnim) {
|
else if (objectId == IsleScript::c_hpz050bd_RunAnim || objectId == IsleScript::c_hpz052ma_RunAnim) {
|
||||||
if (m_unk0x170 == 3) {
|
if (m_taskState == Ambulance::e_finished) {
|
||||||
PlayAnimation(IsleScript::c_hpz057ma_RunAnim);
|
PlayAnimation(IsleScript::c_hpz057ma_RunAnim);
|
||||||
m_unk0x170 = 0;
|
m_taskState = Ambulance::e_none;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
PlayAnimation(IsleScript::c_hpz052ma_RunAnim);
|
PlayAnimation(IsleScript::c_hpz052ma_RunAnim);
|
||||||
@ -204,18 +204,18 @@ MxLong Ambulance::HandleEndAction(MxEndActionNotificationParam& p_param)
|
|||||||
m_unk0x172 = 0;
|
m_unk0x172 = 0;
|
||||||
TickleManager()->RegisterClient(this, 40000);
|
TickleManager()->RegisterClient(this, 40000);
|
||||||
|
|
||||||
if (m_unk0x16c != 0) {
|
if (m_atPoliceTask != 0) {
|
||||||
StopActions();
|
StopActions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (objectId == IsleScript::c_hps116bd_RunAnim || objectId == IsleScript::c_hps118re_RunAnim) {
|
else if (objectId == IsleScript::c_hps116bd_RunAnim || objectId == IsleScript::c_hps118re_RunAnim) {
|
||||||
if (objectId == IsleScript::c_hps116bd_RunAnim && m_unk0x170 != 3) {
|
if (objectId == IsleScript::c_hps116bd_RunAnim && m_taskState != Ambulance::e_finished) {
|
||||||
PlayAction(IsleScript::c_Avo923In_PlayWav);
|
PlayAction(IsleScript::c_Avo923In_PlayWav);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_unk0x170 == 3) {
|
if (m_taskState == Ambulance::e_finished) {
|
||||||
PlayAnimation(IsleScript::c_hps117bd_RunAnim);
|
PlayAnimation(IsleScript::c_hps117bd_RunAnim);
|
||||||
m_unk0x170 = 0;
|
m_taskState = Ambulance::e_none;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
PlayAnimation(IsleScript::c_hps118re_RunAnim);
|
PlayAnimation(IsleScript::c_hps118re_RunAnim);
|
||||||
@ -228,12 +228,12 @@ MxLong Ambulance::HandleEndAction(MxEndActionNotificationParam& p_param)
|
|||||||
m_unk0x172 = 0;
|
m_unk0x172 = 0;
|
||||||
TickleManager()->RegisterClient(this, 40000);
|
TickleManager()->RegisterClient(this, 40000);
|
||||||
|
|
||||||
if (m_unk0x16e != 0) {
|
if (m_atBeachTask != 0) {
|
||||||
StopActions();
|
StopActions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (objectId == IsleScript::c_hho142cl_RunAnim || objectId == IsleScript::c_hho143cl_RunAnim || objectId == IsleScript::c_hho144cl_RunAnim) {
|
else if (objectId == IsleScript::c_hho142cl_RunAnim || objectId == IsleScript::c_hho143cl_RunAnim || objectId == IsleScript::c_hho144cl_RunAnim) {
|
||||||
FUN_10037250();
|
Reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,18 +244,18 @@ MxLong Ambulance::HandleEndAction(MxEndActionNotificationParam& p_param)
|
|||||||
// FUNCTION: BETA10 0x100230bf
|
// FUNCTION: BETA10 0x100230bf
|
||||||
MxLong Ambulance::HandleButtonDown(LegoControlManagerNotificationParam& p_param)
|
MxLong Ambulance::HandleButtonDown(LegoControlManagerNotificationParam& p_param)
|
||||||
{
|
{
|
||||||
if (m_unk0x170 == 1) {
|
if (m_taskState == Ambulance::e_waiting) {
|
||||||
LegoROI* roi = PickROI(p_param.GetX(), p_param.GetY());
|
LegoROI* roi = PickROI(p_param.GetX(), p_param.GetY());
|
||||||
|
|
||||||
if (roi != NULL && !SDL_strcasecmp(roi->GetName(), "ps-gate")) {
|
if (roi != NULL && !SDL_strcasecmp(roi->GetName(), "ps-gate")) {
|
||||||
m_unk0x170 = 3;
|
m_taskState = Ambulance::e_finished;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
roi = PickRootROI(p_param.GetX(), p_param.GetY());
|
roi = PickRootROI(p_param.GetX(), p_param.GetY());
|
||||||
|
|
||||||
if (roi != NULL && !SDL_strcasecmp(roi->GetName(), "gd")) {
|
if (roi != NULL && !SDL_strcasecmp(roi->GetName(), "gd")) {
|
||||||
m_unk0x170 = 3;
|
m_taskState = Ambulance::e_finished;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -273,9 +273,9 @@ MxLong Ambulance::HandlePathStruct(LegoPathStructNotificationParam& p_param)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (p_param.GetTrigger() == LegoPathStruct::c_camAnim && p_param.GetData() == 0x0b) {
|
if (p_param.GetTrigger() == LegoPathStruct::c_camAnim && p_param.GetData() == 0x0b) {
|
||||||
if (m_unk0x16e != 0) {
|
if (m_atBeachTask != 0) {
|
||||||
if (m_unk0x16c != 0) {
|
if (m_atPoliceTask != 0) {
|
||||||
m_state->m_unk0x08 = 2;
|
m_state->m_state = AmbulanceMissionState::e_prepareAmbulance;
|
||||||
|
|
||||||
if (m_lastAction != IsleScript::c_noneIsle) {
|
if (m_lastAction != IsleScript::c_noneIsle) {
|
||||||
InvokeAction(Extra::e_stop, *g_isleScript, m_lastAction, NULL);
|
InvokeAction(Extra::e_stop, *g_isleScript, m_lastAction, NULL);
|
||||||
@ -300,7 +300,7 @@ MxLong Ambulance::HandlePathStruct(LegoPathStructNotificationParam& p_param)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_unk0x16e != 0) {
|
if (m_atBeachTask != 0) {
|
||||||
if (m_lastAction != IsleScript::c_noneIsle) {
|
if (m_lastAction != IsleScript::c_noneIsle) {
|
||||||
InvokeAction(Extra::e_stop, *g_isleScript, m_lastAction, NULL);
|
InvokeAction(Extra::e_stop, *g_isleScript, m_lastAction, NULL);
|
||||||
}
|
}
|
||||||
@ -310,7 +310,7 @@ MxLong Ambulance::HandlePathStruct(LegoPathStructNotificationParam& p_param)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_unk0x16c != 0) {
|
if (m_atPoliceTask != 0) {
|
||||||
if (m_lastAction != IsleScript::c_noneIsle) {
|
if (m_lastAction != IsleScript::c_noneIsle) {
|
||||||
InvokeAction(Extra::e_stop, *g_isleScript, m_lastAction, NULL);
|
InvokeAction(Extra::e_stop, *g_isleScript, m_lastAction, NULL);
|
||||||
}
|
}
|
||||||
@ -318,9 +318,9 @@ MxLong Ambulance::HandlePathStruct(LegoPathStructNotificationParam& p_param)
|
|||||||
PlayAction(IsleScript::c_Avo915In_PlayWav);
|
PlayAction(IsleScript::c_Avo915In_PlayWav);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (p_param.GetTrigger() == LegoPathStruct::c_s && p_param.GetData() == 0x131 && m_unk0x16e == 0) {
|
else if (p_param.GetTrigger() == LegoPathStruct::c_s && p_param.GetData() == 0x131 && m_atBeachTask == 0) {
|
||||||
m_unk0x16e = 1;
|
m_atBeachTask = 1;
|
||||||
m_unk0x170 = 1;
|
m_taskState = Ambulance::e_waiting;
|
||||||
|
|
||||||
if (m_lastAction != IsleScript::c_noneIsle) {
|
if (m_lastAction != IsleScript::c_noneIsle) {
|
||||||
InvokeAction(Extra::e_stop, *g_isleScript, m_lastAction, NULL);
|
InvokeAction(Extra::e_stop, *g_isleScript, m_lastAction, NULL);
|
||||||
@ -348,9 +348,9 @@ MxLong Ambulance::HandlePathStruct(LegoPathStructNotificationParam& p_param)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (p_param.GetTrigger() == LegoPathStruct::c_camAnim && (p_param.GetData() == 0x22 || p_param.GetData() == 0x23 || p_param.GetData() == 0x24) && m_unk0x16c == 0) {
|
else if (p_param.GetTrigger() == LegoPathStruct::c_camAnim && (p_param.GetData() == 0x22 || p_param.GetData() == 0x23 || p_param.GetData() == 0x24) && m_atPoliceTask == 0) {
|
||||||
m_unk0x16c = 1;
|
m_atPoliceTask = 1;
|
||||||
m_unk0x170 = 1;
|
m_taskState = Ambulance::e_waiting;
|
||||||
|
|
||||||
if (m_lastAction != IsleScript::c_noneIsle) {
|
if (m_lastAction != IsleScript::c_noneIsle) {
|
||||||
InvokeAction(Extra::e_stop, *g_isleScript, m_lastAction, NULL);
|
InvokeAction(Extra::e_stop, *g_isleScript, m_lastAction, NULL);
|
||||||
@ -371,7 +371,7 @@ MxLong Ambulance::HandleClick()
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_state->m_unk0x08 == 2) {
|
if (m_state->m_state == AmbulanceMissionState::e_prepareAmbulance) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -390,7 +390,7 @@ MxLong Ambulance::HandleClick()
|
|||||||
InvokeAction(Extra::e_start, *g_isleScript, IsleScript::c_AmbulanceDashboard, NULL);
|
InvokeAction(Extra::e_start, *g_isleScript, IsleScript::c_AmbulanceDashboard, NULL);
|
||||||
ControlManager()->Register(this);
|
ControlManager()->Register(this);
|
||||||
|
|
||||||
if (m_state->m_unk0x08 == 1) {
|
if (m_state->m_state == AmbulanceMissionState::e_enteredAmbulance) {
|
||||||
SpawnPlayer(LegoGameState::e_hospitalExited, TRUE, 0);
|
SpawnPlayer(LegoGameState::e_hospitalExited, TRUE, 0);
|
||||||
m_state->m_startTime = Timer()->GetTime();
|
m_state->m_startTime = Timer()->GetTime();
|
||||||
InvokeAction(Extra::e_start, *g_isleScript, IsleScript::c_pns018rd_RunAnim, NULL);
|
InvokeAction(Extra::e_start, *g_isleScript, IsleScript::c_pns018rd_RunAnim, NULL);
|
||||||
@ -401,9 +401,9 @@ MxLong Ambulance::HandleClick()
|
|||||||
|
|
||||||
// FUNCTION: LEGO1 0x10036e60
|
// FUNCTION: LEGO1 0x10036e60
|
||||||
// FUNCTION: BETA10 0x100236bb
|
// FUNCTION: BETA10 0x100236bb
|
||||||
void Ambulance::FUN_10036e60()
|
void Ambulance::Init()
|
||||||
{
|
{
|
||||||
m_state->m_unk0x08 = 2;
|
m_state->m_state = AmbulanceMissionState::e_prepareAmbulance;
|
||||||
PlayAnimation(IsleScript::c_hho027en_RunAnim);
|
PlayAnimation(IsleScript::c_hho027en_RunAnim);
|
||||||
m_lastAction = IsleScript::c_noneIsle;
|
m_lastAction = IsleScript::c_noneIsle;
|
||||||
m_lastAnimation = IsleScript::c_noneIsle;
|
m_lastAnimation = IsleScript::c_noneIsle;
|
||||||
@ -414,7 +414,7 @@ void Ambulance::Exit()
|
|||||||
{
|
{
|
||||||
GameState()->m_currentArea = LegoGameState::e_hospitalExterior;
|
GameState()->m_currentArea = LegoGameState::e_hospitalExterior;
|
||||||
StopActions();
|
StopActions();
|
||||||
FUN_10037250();
|
Reset();
|
||||||
Leave();
|
Leave();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -470,11 +470,11 @@ void Ambulance::ActivateSceneActions()
|
|||||||
{
|
{
|
||||||
PlayMusic(JukeboxScript::c_Hospital_Music);
|
PlayMusic(JukeboxScript::c_Hospital_Music);
|
||||||
|
|
||||||
if (m_state->m_unk0x08 == 1) {
|
if (m_state->m_state == AmbulanceMissionState::e_enteredAmbulance) {
|
||||||
m_state->m_unk0x08 = 0;
|
m_state->m_state = AmbulanceMissionState::e_ready;
|
||||||
PlayAction(IsleScript::c_ham033cl_PlayWav);
|
PlayAction(IsleScript::c_ham033cl_PlayWav);
|
||||||
}
|
}
|
||||||
else if (m_unk0x16c != 0 && m_unk0x16e != 0) {
|
else if (m_atPoliceTask != 0 && m_atBeachTask != 0) {
|
||||||
IsleScript::Script objectId;
|
IsleScript::Script objectId;
|
||||||
|
|
||||||
switch (SDL_rand(2)) {
|
switch (SDL_rand(2)) {
|
||||||
@ -574,14 +574,14 @@ void Ambulance::StopActions()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x10037250
|
// FUNCTION: LEGO1 0x10037250
|
||||||
void Ambulance::FUN_10037250()
|
void Ambulance::Reset()
|
||||||
{
|
{
|
||||||
StopAction(m_lastAction);
|
StopAction(m_lastAction);
|
||||||
BackgroundAudioManager()->RaiseVolume();
|
BackgroundAudioManager()->RaiseVolume();
|
||||||
((Act1State*) GameState()->GetState("Act1State"))->m_unk0x018 = 0;
|
((Act1State*) GameState()->GetState("Act1State"))->m_unk0x018 = 0;
|
||||||
m_state->m_unk0x08 = 0;
|
m_state->m_state = AmbulanceMissionState::e_ready;
|
||||||
m_unk0x16e = 0;
|
m_atBeachTask = 0;
|
||||||
m_unk0x16c = 0;
|
m_atPoliceTask = 0;
|
||||||
g_isleFlags |= Isle::c_playMusic;
|
g_isleFlags |= Isle::c_playMusic;
|
||||||
AnimationManager()->EnableCamAnims(TRUE);
|
AnimationManager()->EnableCamAnims(TRUE);
|
||||||
AnimationManager()->FUN_1005f6d0(TRUE);
|
AnimationManager()->FUN_1005f6d0(TRUE);
|
||||||
@ -629,7 +629,7 @@ void Ambulance::PlayAction(IsleScript::Script p_objectId)
|
|||||||
// FUNCTION: LEGO1 0x100373a0
|
// FUNCTION: LEGO1 0x100373a0
|
||||||
AmbulanceMissionState::AmbulanceMissionState()
|
AmbulanceMissionState::AmbulanceMissionState()
|
||||||
{
|
{
|
||||||
m_unk0x08 = 0;
|
m_state = AmbulanceMissionState::e_ready;
|
||||||
m_startTime = 0;
|
m_startTime = 0;
|
||||||
m_peScore = 0;
|
m_peScore = 0;
|
||||||
m_maScore = 0;
|
m_maScore = 0;
|
||||||
|
|||||||
@ -488,7 +488,7 @@ void LegoCarBuild::FUN_100236d0()
|
|||||||
m_unk0x110 = NULL;
|
m_unk0x110 = NULL;
|
||||||
m_unk0x100 = 0;
|
m_unk0x100 = 0;
|
||||||
|
|
||||||
if (m_animPresenter->AllPartsPlaced()) {
|
if (m_animPresenter->AllPartsPlaced() && !Lego()->IsVersion10()) {
|
||||||
// Note the code duplication with LEGO1 0x10025ee0
|
// Note the code duplication with LEGO1 0x10025ee0
|
||||||
switch (m_carId) {
|
switch (m_carId) {
|
||||||
case 1:
|
case 1:
|
||||||
|
|||||||
@ -636,7 +636,7 @@ MxBool LegoCharacterManager::SetHeadTexture(LegoROI* p_roi, LegoTextureInfo* p_t
|
|||||||
LegoLOD* clone = lod->Clone(renderer);
|
LegoLOD* clone = lod->Clone(renderer);
|
||||||
|
|
||||||
if (p_texture != NULL) {
|
if (p_texture != NULL) {
|
||||||
clone->FUN_100aad70(p_texture);
|
clone->UpdateTextureInfo(p_texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
dupLodList->PushBack(clone);
|
dupLodList->PushBack(clone);
|
||||||
|
|||||||
@ -83,7 +83,7 @@ void LegoPlantManager::Init()
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_worldId = LegoOmni::e_undefined;
|
m_worldId = LegoOmni::e_undefined;
|
||||||
m_unk0x0c = 0;
|
m_boundariesDetermined = FALSE;
|
||||||
m_numEntries = 0;
|
m_numEntries = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,7 +98,7 @@ void LegoPlantManager::LoadWorldInfo(LegoOmni::World p_worldId)
|
|||||||
CreatePlant(i, world, p_worldId);
|
CreatePlant(i, world, p_worldId);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_unk0x0c = 0;
|
m_boundariesDetermined = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x100263a0
|
// FUNCTION: LEGO1 0x100263a0
|
||||||
@ -119,12 +119,12 @@ void LegoPlantManager::Reset(LegoOmni::World p_worldId)
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_worldId = LegoOmni::e_undefined;
|
m_worldId = LegoOmni::e_undefined;
|
||||||
m_unk0x0c = 0;
|
m_boundariesDetermined = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x10026410
|
// FUNCTION: LEGO1 0x10026410
|
||||||
// FUNCTION: BETA10 0x100c50e9
|
// FUNCTION: BETA10 0x100c50e9
|
||||||
MxResult LegoPlantManager::FUN_10026410()
|
MxResult LegoPlantManager::DetermineBoundaries()
|
||||||
{
|
{
|
||||||
// similar to LegoBuildingManager::FUN_10030630()
|
// similar to LegoBuildingManager::FUN_10030630()
|
||||||
|
|
||||||
@ -192,7 +192,7 @@ MxResult LegoPlantManager::FUN_10026410()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_unk0x0c = TRUE;
|
m_boundariesDetermined = TRUE;
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,8 +200,8 @@ MxResult LegoPlantManager::FUN_10026410()
|
|||||||
// FUNCTION: BETA10 0x100c55e0
|
// FUNCTION: BETA10 0x100c55e0
|
||||||
LegoPlantInfo* LegoPlantManager::GetInfoArray(MxS32& p_length)
|
LegoPlantInfo* LegoPlantManager::GetInfoArray(MxS32& p_length)
|
||||||
{
|
{
|
||||||
if (!m_unk0x0c) {
|
if (!m_boundariesDetermined) {
|
||||||
FUN_10026410();
|
DetermineBoundaries();
|
||||||
}
|
}
|
||||||
|
|
||||||
p_length = sizeOfArray(g_plantInfo);
|
p_length = sizeOfArray(g_plantInfo);
|
||||||
|
|||||||
@ -76,6 +76,7 @@ void LegoOmni::Init()
|
|||||||
m_bkgAudioManager = NULL;
|
m_bkgAudioManager = NULL;
|
||||||
m_unk0x13c = TRUE;
|
m_unk0x13c = TRUE;
|
||||||
m_transitionManager = NULL;
|
m_transitionManager = NULL;
|
||||||
|
m_version10 = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x10058c30
|
// FUNCTION: LEGO1 0x10058c30
|
||||||
|
|||||||
@ -37,7 +37,7 @@ const char* g_strHIT_WALL_SOUND = "HIT_WALL_SOUND";
|
|||||||
|
|
||||||
// GLOBAL: LEGO1 0x100f3308
|
// GLOBAL: LEGO1 0x100f3308
|
||||||
// GLOBAL: BETA10 0x101f1e1c
|
// GLOBAL: BETA10 0x101f1e1c
|
||||||
MxLong g_unk0x100f3308 = 0;
|
MxLong g_timeLastHitSoundPlayed = 0;
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x1002d700
|
// FUNCTION: LEGO1 0x1002d700
|
||||||
// FUNCTION: BETA10 0x100ae6e0
|
// FUNCTION: BETA10 0x100ae6e0
|
||||||
@ -292,8 +292,8 @@ MxS32 LegoPathActor::VTable0x8c(float p_time, Matrix4& p_transform)
|
|||||||
if (m_boundary == oldBoundary) {
|
if (m_boundary == oldBoundary) {
|
||||||
MxLong time = Timer()->GetTime();
|
MxLong time = Timer()->GetTime();
|
||||||
|
|
||||||
if (time - g_unk0x100f3308 > 1000) {
|
if (time - g_timeLastHitSoundPlayed > 1000) {
|
||||||
g_unk0x100f3308 = time;
|
g_timeLastHitSoundPlayed = time;
|
||||||
const char* var = VariableTable()->GetVariable(g_strHIT_WALL_SOUND);
|
const char* var = VariableTable()->GetVariable(g_strHIT_WALL_SOUND);
|
||||||
|
|
||||||
if (var && var[0] != 0) {
|
if (var && var[0] != 0) {
|
||||||
|
|||||||
@ -246,7 +246,7 @@ MxLong CarRace::HandlePathStruct(LegoPathStructNotificationParam& p_param)
|
|||||||
VariableTable()->SetVariable(g_strHIT_WALL_SOUND, "");
|
VariableTable()->SetVariable(g_strHIT_WALL_SOUND, "");
|
||||||
NavController()->SetDeadZone(NavController()->GetDefaultDeadZone());
|
NavController()->SetDeadZone(NavController()->GetDefaultDeadZone());
|
||||||
NavController()->SetTrackDefault(1);
|
NavController()->SetTrackDefault(1);
|
||||||
LegoRaceCar::FUN_10012de0();
|
LegoRaceCar::InitYouCantStopSound();
|
||||||
m_raceState->m_unk0x28 = 2;
|
m_raceState->m_unk0x28 = 2;
|
||||||
|
|
||||||
RaceState::Entry* raceState = m_raceState->GetState(GameState()->GetActorId());
|
RaceState::Entry* raceState = m_raceState->GetState(GameState()->GetActorId());
|
||||||
@ -348,7 +348,7 @@ MxLong CarRace::HandleClick(LegoEventNotificationParam& p_param)
|
|||||||
VariableTable()->SetVariable(g_strHIT_WALL_SOUND, "");
|
VariableTable()->SetVariable(g_strHIT_WALL_SOUND, "");
|
||||||
NavController()->SetDeadZone(NavController()->GetDefaultDeadZone());
|
NavController()->SetDeadZone(NavController()->GetDefaultDeadZone());
|
||||||
NavController()->SetTrackDefault(1);
|
NavController()->SetTrackDefault(1);
|
||||||
LegoRaceCar::FUN_10012de0();
|
LegoRaceCar::InitYouCantStopSound();
|
||||||
m_destLocation = LegoGameState::e_infomain;
|
m_destLocation = LegoGameState::e_infomain;
|
||||||
TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE);
|
TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE);
|
||||||
GameState()->GetBackgroundColor()->SetValue("reset");
|
GameState()->GetBackgroundColor()->SetValue("reset");
|
||||||
@ -360,7 +360,7 @@ MxLong CarRace::HandleClick(LegoEventNotificationParam& p_param)
|
|||||||
VariableTable()->SetVariable(g_strHIT_WALL_SOUND, "");
|
VariableTable()->SetVariable(g_strHIT_WALL_SOUND, "");
|
||||||
NavController()->SetDeadZone(NavController()->GetDefaultDeadZone());
|
NavController()->SetDeadZone(NavController()->GetDefaultDeadZone());
|
||||||
NavController()->SetTrackDefault(1);
|
NavController()->SetTrackDefault(1);
|
||||||
LegoRaceCar::FUN_10012de0();
|
LegoRaceCar::InitYouCantStopSound();
|
||||||
m_destLocation = LegoGameState::e_carraceExterior;
|
m_destLocation = LegoGameState::e_carraceExterior;
|
||||||
TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE);
|
TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE);
|
||||||
GameState()->GetBackgroundColor()->SetValue("reset");
|
GameState()->GetBackgroundColor()->SetValue("reset");
|
||||||
@ -424,7 +424,7 @@ MxBool CarRace::Escape()
|
|||||||
NavController()->SetDeadZone(NavController()->GetDefaultDeadZone());
|
NavController()->SetDeadZone(NavController()->GetDefaultDeadZone());
|
||||||
|
|
||||||
NavController()->SetTrackDefault(1);
|
NavController()->SetTrackDefault(1);
|
||||||
LegoRaceCar::FUN_10012de0();
|
LegoRaceCar::InitYouCantStopSound();
|
||||||
|
|
||||||
GameState()->GetBackgroundColor()->SetValue("reset");
|
GameState()->GetBackgroundColor()->SetValue("reset");
|
||||||
m_destLocation = LegoGameState::e_infomain;
|
m_destLocation = LegoGameState::e_infomain;
|
||||||
|
|||||||
@ -132,7 +132,7 @@ MxLong JetskiRace::HandleClick(LegoEventNotificationParam& p_param)
|
|||||||
m_act1State->m_unk0x018 = 0;
|
m_act1State->m_unk0x018 = 0;
|
||||||
VariableTable()->SetVariable(g_raceState, "");
|
VariableTable()->SetVariable(g_raceState, "");
|
||||||
VariableTable()->SetVariable(g_strHIT_WALL_SOUND, "");
|
VariableTable()->SetVariable(g_strHIT_WALL_SOUND, "");
|
||||||
LegoRaceCar::FUN_10012de0();
|
LegoRaceCar::InitYouCantStopSound();
|
||||||
m_destLocation = LegoGameState::e_jetraceExterior;
|
m_destLocation = LegoGameState::e_jetraceExterior;
|
||||||
TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE);
|
TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE);
|
||||||
break;
|
break;
|
||||||
@ -140,7 +140,7 @@ MxLong JetskiRace::HandleClick(LegoEventNotificationParam& p_param)
|
|||||||
m_act1State->m_unk0x018 = 0;
|
m_act1State->m_unk0x018 = 0;
|
||||||
VariableTable()->SetVariable(g_raceState, "");
|
VariableTable()->SetVariable(g_raceState, "");
|
||||||
VariableTable()->SetVariable(g_strHIT_WALL_SOUND, "");
|
VariableTable()->SetVariable(g_strHIT_WALL_SOUND, "");
|
||||||
LegoRaceCar::FUN_10012de0();
|
LegoRaceCar::InitYouCantStopSound();
|
||||||
m_destLocation = LegoGameState::e_infomain;
|
m_destLocation = LegoGameState::e_infomain;
|
||||||
result = 1;
|
result = 1;
|
||||||
TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE);
|
TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE);
|
||||||
@ -193,7 +193,7 @@ MxLong JetskiRace::HandlePathStruct(LegoPathStructNotificationParam& p_param)
|
|||||||
|
|
||||||
VariableTable()->SetVariable(g_raceState, "");
|
VariableTable()->SetVariable(g_raceState, "");
|
||||||
VariableTable()->SetVariable(g_strHIT_WALL_SOUND, "");
|
VariableTable()->SetVariable(g_strHIT_WALL_SOUND, "");
|
||||||
LegoRaceCar::FUN_10012de0();
|
LegoRaceCar::InitYouCantStopSound();
|
||||||
m_raceState->m_unk0x28 = 2;
|
m_raceState->m_unk0x28 = 2;
|
||||||
|
|
||||||
RaceState::Entry* raceStateEntry = m_raceState->GetState(GameState()->GetActorId());
|
RaceState::Entry* raceStateEntry = m_raceState->GetState(GameState()->GetActorId());
|
||||||
@ -294,6 +294,6 @@ MxBool JetskiRace::Escape()
|
|||||||
VariableTable()->SetVariable(g_raceState, "");
|
VariableTable()->SetVariable(g_raceState, "");
|
||||||
VariableTable()->SetVariable(g_strHIT_WALL_SOUND, "");
|
VariableTable()->SetVariable(g_strHIT_WALL_SOUND, "");
|
||||||
m_destLocation = LegoGameState::e_infomain;
|
m_destLocation = LegoGameState::e_infomain;
|
||||||
LegoRaceCar::FUN_10012de0();
|
LegoRaceCar::InitYouCantStopSound();
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,8 +31,8 @@ MxS32 LegoRaceActor::VTable0x68(Vector3& p_v1, Vector3& p_v2, Vector3& p_v3)
|
|||||||
|
|
||||||
if (m_userNavFlag && result) {
|
if (m_userNavFlag && result) {
|
||||||
MxLong time = Timer()->GetTime();
|
MxLong time = Timer()->GetTime();
|
||||||
if (time - g_unk0x100f3308 > 1000) {
|
if (time - g_timeLastHitSoundPlayed > 1000) {
|
||||||
g_unk0x100f3308 = time;
|
g_timeLastHitSoundPlayed = time;
|
||||||
const char* soundKey = VariableTable()->GetVariable(g_strHIT_ACTOR_SOUND);
|
const char* soundKey = VariableTable()->GetVariable(g_strHIT_ACTOR_SOUND);
|
||||||
|
|
||||||
if (soundKey && *soundKey) {
|
if (soundKey && *soundKey) {
|
||||||
|
|||||||
@ -178,7 +178,7 @@ LegoRaceCar::LegoRaceCar()
|
|||||||
m_skelKick1Anim = 0;
|
m_skelKick1Anim = 0;
|
||||||
m_skelKick2Anim = 0;
|
m_skelKick2Anim = 0;
|
||||||
m_unk0x5c.Clear();
|
m_unk0x5c.Clear();
|
||||||
m_unk0x58 = 0;
|
m_kickStart = 0;
|
||||||
m_kick1B = 0;
|
m_kick1B = 0;
|
||||||
m_kick2B = 0;
|
m_kick2B = 0;
|
||||||
NotificationManager()->Register(this);
|
NotificationManager()->Register(this);
|
||||||
@ -201,10 +201,10 @@ MxLong LegoRaceCar::Notify(MxParam& p_param)
|
|||||||
// Initialized at LEGO1 0x10012db0
|
// Initialized at LEGO1 0x10012db0
|
||||||
// GLOBAL: LEGO1 0x10102af0
|
// GLOBAL: LEGO1 0x10102af0
|
||||||
// GLOBAL: BETA10 0x102114c0
|
// GLOBAL: BETA10 0x102114c0
|
||||||
Mx3DPointFloat g_unk0x10102af0 = Mx3DPointFloat(0.0f, 2.0f, 0.0f);
|
Mx3DPointFloat g_hitOffset = Mx3DPointFloat(0.0f, 2.0f, 0.0f);
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x10012de0
|
// FUNCTION: LEGO1 0x10012de0
|
||||||
void LegoRaceCar::FUN_10012de0()
|
void LegoRaceCar::InitYouCantStopSound()
|
||||||
{
|
{
|
||||||
// Init to TRUE so we don't play "you can't stop in the middle of the race!" before the player ever moves
|
// Init to TRUE so we don't play "you can't stop in the middle of the race!" before the player ever moves
|
||||||
g_playedYouCantStopSound = TRUE;
|
g_playedYouCantStopSound = TRUE;
|
||||||
@ -229,7 +229,7 @@ void LegoRaceCar::InitSoundIndices()
|
|||||||
void LegoRaceCar::SetWorldSpeed(MxFloat p_worldSpeed)
|
void LegoRaceCar::SetWorldSpeed(MxFloat p_worldSpeed)
|
||||||
{
|
{
|
||||||
if (!m_userNavFlag) {
|
if (!m_userNavFlag) {
|
||||||
if (!LegoCarRaceActor::m_unk0x0c) {
|
if (!LegoCarRaceActor::m_animState) {
|
||||||
m_maxLinearVel = p_worldSpeed;
|
m_maxLinearVel = p_worldSpeed;
|
||||||
}
|
}
|
||||||
LegoAnimActor::SetWorldSpeed(p_worldSpeed);
|
LegoAnimActor::SetWorldSpeed(p_worldSpeed);
|
||||||
@ -244,7 +244,7 @@ void LegoRaceCar::SetWorldSpeed(MxFloat p_worldSpeed)
|
|||||||
void LegoRaceCar::SetMaxLinearVelocity(float p_maxLinearVelocity)
|
void LegoRaceCar::SetMaxLinearVelocity(float p_maxLinearVelocity)
|
||||||
{
|
{
|
||||||
if (p_maxLinearVelocity < 0) {
|
if (p_maxLinearVelocity < 0) {
|
||||||
LegoCarRaceActor::m_unk0x0c = 2;
|
LegoCarRaceActor::m_animState = 2;
|
||||||
m_maxLinearVel = 0;
|
m_maxLinearVel = 0;
|
||||||
SetWorldSpeed(0);
|
SetWorldSpeed(0);
|
||||||
}
|
}
|
||||||
@ -299,7 +299,7 @@ void LegoRaceCar::ParseAction(char* p_extra)
|
|||||||
|
|
||||||
// FUNCTION: LEGO1 0x10012ff0
|
// FUNCTION: LEGO1 0x10012ff0
|
||||||
// FUNCTION: BETA10 0x100cb60e
|
// FUNCTION: BETA10 0x100cb60e
|
||||||
void LegoRaceCar::FUN_10012ff0(float p_param)
|
void LegoRaceCar::KickCamera(float p_param)
|
||||||
{
|
{
|
||||||
LegoAnimActorStruct* a; // called `a` in BETA10
|
LegoAnimActorStruct* a; // called `a` in BETA10
|
||||||
float deltaTime;
|
float deltaTime;
|
||||||
@ -315,7 +315,7 @@ void LegoRaceCar::FUN_10012ff0(float p_param)
|
|||||||
assert(a && a->GetAnimTreePtr() && a->GetAnimTreePtr()->GetCamAnim());
|
assert(a && a->GetAnimTreePtr() && a->GetAnimTreePtr()->GetCamAnim());
|
||||||
|
|
||||||
if (a->GetAnimTreePtr()) {
|
if (a->GetAnimTreePtr()) {
|
||||||
deltaTime = p_param - m_unk0x58;
|
deltaTime = p_param - m_kickStart;
|
||||||
|
|
||||||
if (a->GetDuration() <= deltaTime || deltaTime < 0.0) {
|
if (a->GetDuration() <= deltaTime || deltaTime < 0.0) {
|
||||||
if (m_userState == LEGORACECAR_KICK1) {
|
if (m_userState == LEGORACECAR_KICK1) {
|
||||||
@ -390,7 +390,7 @@ MxU32 LegoRaceCar::HandleSkeletonKicks(float p_param1)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_unk0x58 = p_param1;
|
m_kickStart = p_param1;
|
||||||
SoundManager()->GetCacheSoundManager()->Play(g_soundSkel3, NULL, FALSE);
|
SoundManager()->GetCacheSoundManager()->Play(g_soundSkel3, NULL, FALSE);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -401,7 +401,7 @@ MxU32 LegoRaceCar::HandleSkeletonKicks(float p_param1)
|
|||||||
void LegoRaceCar::Animate(float p_time)
|
void LegoRaceCar::Animate(float p_time)
|
||||||
{
|
{
|
||||||
if (m_userNavFlag && (m_userState == LEGORACECAR_KICK1 || m_userState == LEGORACECAR_KICK2)) {
|
if (m_userNavFlag && (m_userState == LEGORACECAR_KICK1 || m_userState == LEGORACECAR_KICK2)) {
|
||||||
FUN_10012ff0(p_time);
|
KickCamera(p_time);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -413,7 +413,7 @@ void LegoRaceCar::Animate(float p_time)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LegoCarRaceActor::m_unk0x0c == 1) {
|
if (LegoCarRaceActor::m_animState == 1) {
|
||||||
FUN_1005d4b0();
|
FUN_1005d4b0();
|
||||||
|
|
||||||
if (!m_userNavFlag) {
|
if (!m_userNavFlag) {
|
||||||
@ -471,7 +471,7 @@ MxResult LegoRaceCar::HitActor(LegoPathActor* p_actor, MxBool p_bool)
|
|||||||
assert(roi);
|
assert(roi);
|
||||||
matr = roi->GetLocal2World();
|
matr = roi->GetLocal2World();
|
||||||
|
|
||||||
Vector3(matr[3]) += g_unk0x10102af0;
|
Vector3(matr[3]) += g_hitOffset;
|
||||||
roi->SetLocal2World(matr);
|
roi->SetLocal2World(matr);
|
||||||
|
|
||||||
p_actor->SetActorState(c_two);
|
p_actor->SetActorState(c_two);
|
||||||
@ -516,7 +516,7 @@ MxResult LegoRaceCar::HitActor(LegoPathActor* p_actor, MxBool p_bool)
|
|||||||
|
|
||||||
if (soundKey) {
|
if (soundKey) {
|
||||||
SoundManager()->GetCacheSoundManager()->Play(soundKey, NULL, FALSE);
|
SoundManager()->GetCacheSoundManager()->Play(soundKey, NULL, FALSE);
|
||||||
g_timeLastRaceCarSoundPlayed = g_unk0x100f3308 = time;
|
g_timeLastRaceCarSoundPlayed = g_timeLastHitSoundPlayed = time;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -582,7 +582,7 @@ void LegoJetski::InitSoundIndices()
|
|||||||
void LegoJetski::SetWorldSpeed(MxFloat p_worldSpeed)
|
void LegoJetski::SetWorldSpeed(MxFloat p_worldSpeed)
|
||||||
{
|
{
|
||||||
if (!m_userNavFlag) {
|
if (!m_userNavFlag) {
|
||||||
if (!LegoCarRaceActor::m_unk0x0c) {
|
if (!LegoCarRaceActor::m_animState) {
|
||||||
m_maxLinearVel = p_worldSpeed;
|
m_maxLinearVel = p_worldSpeed;
|
||||||
}
|
}
|
||||||
LegoAnimActor::SetWorldSpeed(p_worldSpeed);
|
LegoAnimActor::SetWorldSpeed(p_worldSpeed);
|
||||||
@ -597,7 +597,7 @@ void LegoJetski::SetWorldSpeed(MxFloat p_worldSpeed)
|
|||||||
void LegoJetski::FUN_100136f0(float p_worldSpeed)
|
void LegoJetski::FUN_100136f0(float p_worldSpeed)
|
||||||
{
|
{
|
||||||
if (p_worldSpeed < 0) {
|
if (p_worldSpeed < 0) {
|
||||||
LegoCarRaceActor::m_unk0x0c = 2;
|
LegoCarRaceActor::m_animState = 2;
|
||||||
m_maxLinearVel = 0;
|
m_maxLinearVel = 0;
|
||||||
SetWorldSpeed(0);
|
SetWorldSpeed(0);
|
||||||
}
|
}
|
||||||
@ -612,7 +612,7 @@ void LegoJetski::Animate(float p_time)
|
|||||||
{
|
{
|
||||||
LegoJetskiRaceActor::Animate(p_time);
|
LegoJetskiRaceActor::Animate(p_time);
|
||||||
|
|
||||||
if (LegoCarRaceActor::m_unk0x0c == 1) {
|
if (LegoCarRaceActor::m_animState == 1) {
|
||||||
FUN_1005d4b0();
|
FUN_1005d4b0();
|
||||||
|
|
||||||
if (!m_userNavFlag) {
|
if (!m_userNavFlag) {
|
||||||
@ -685,7 +685,7 @@ MxResult LegoJetski::HitActor(LegoPathActor* p_actor, MxBool p_bool)
|
|||||||
LegoROI* roi = p_actor->GetROI();
|
LegoROI* roi = p_actor->GetROI();
|
||||||
matr = roi->GetLocal2World();
|
matr = roi->GetLocal2World();
|
||||||
|
|
||||||
Vector3(matr[3]) += g_unk0x10102af0;
|
Vector3(matr[3]) += g_hitOffset;
|
||||||
roi->SetLocal2World(matr);
|
roi->SetLocal2World(matr);
|
||||||
|
|
||||||
p_actor->SetActorState(c_two);
|
p_actor->SetActorState(c_two);
|
||||||
@ -714,7 +714,7 @@ MxResult LegoJetski::HitActor(LegoPathActor* p_actor, MxBool p_bool)
|
|||||||
|
|
||||||
if (soundKey) {
|
if (soundKey) {
|
||||||
SoundManager()->GetCacheSoundManager()->Play(soundKey, NULL, FALSE);
|
SoundManager()->GetCacheSoundManager()->Play(soundKey, NULL, FALSE);
|
||||||
g_timeLastJetskiSoundPlayed = g_unk0x100f3308 = time;
|
g_timeLastJetskiSoundPlayed = g_timeLastHitSoundPlayed = time;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -45,7 +45,7 @@ LegoCarRaceActor::LegoCarRaceActor()
|
|||||||
{
|
{
|
||||||
m_unk0x08 = 1.0f;
|
m_unk0x08 = 1.0f;
|
||||||
m_unk0x70 = 0.0f;
|
m_unk0x70 = 0.0f;
|
||||||
m_unk0x0c = 0;
|
m_animState = 0;
|
||||||
m_maxLinearVel = 0.0f;
|
m_maxLinearVel = 0.0f;
|
||||||
m_frequencyFactor = 1.0f;
|
m_frequencyFactor = 1.0f;
|
||||||
m_unk0x1c = 0;
|
m_unk0x1c = 0;
|
||||||
@ -224,18 +224,18 @@ void LegoCarRaceActor::SwitchBoundary(LegoPathBoundary*& p_boundary, LegoOriente
|
|||||||
// FUNCTION: BETA10 0x100cdbae
|
// FUNCTION: BETA10 0x100cdbae
|
||||||
void LegoCarRaceActor::Animate(float p_time)
|
void LegoCarRaceActor::Animate(float p_time)
|
||||||
{
|
{
|
||||||
// m_unk0x0c is not an MxBool, there are places where it is set to 2 or higher
|
// m_animState is not an MxBool, there are places where it is set to 2 or higher
|
||||||
if (m_unk0x0c == 0) {
|
if (m_animState == 0) {
|
||||||
const char* value = VariableTable()->GetVariable(g_raceState);
|
const char* value = VariableTable()->GetVariable(g_raceState);
|
||||||
|
|
||||||
if (SDL_strcasecmp(value, g_racing) == 0) {
|
if (SDL_strcasecmp(value, g_racing) == 0) {
|
||||||
m_unk0x0c = 1;
|
m_animState = 1;
|
||||||
m_lastTime = p_time - 1.0f;
|
m_lastTime = p_time - 1.0f;
|
||||||
m_unk0x1c = p_time;
|
m_unk0x1c = p_time;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_unk0x0c == 1) {
|
if (m_animState == 1) {
|
||||||
LegoAnimActor::Animate(p_time);
|
LegoAnimActor::Animate(p_time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -399,10 +399,10 @@ MxS32 LegoJetskiRaceActor::VTable0x1c(LegoPathBoundary* p_boundary, LegoEdge* p_
|
|||||||
// FUNCTION: LEGO1 0x10081550
|
// FUNCTION: LEGO1 0x10081550
|
||||||
void LegoJetskiRaceActor::Animate(float p_time)
|
void LegoJetskiRaceActor::Animate(float p_time)
|
||||||
{
|
{
|
||||||
if (m_unk0x0c == 0) {
|
if (m_animState == 0) {
|
||||||
const LegoChar* raceState = VariableTable()->GetVariable(g_raceState);
|
const LegoChar* raceState = VariableTable()->GetVariable(g_raceState);
|
||||||
if (!SDL_strcasecmp(raceState, g_racing)) {
|
if (!SDL_strcasecmp(raceState, g_racing)) {
|
||||||
m_unk0x0c = 1;
|
m_animState = 1;
|
||||||
m_lastTime = p_time - 1.0f;
|
m_lastTime = p_time - 1.0f;
|
||||||
m_unk0x1c = p_time;
|
m_unk0x1c = p_time;
|
||||||
}
|
}
|
||||||
@ -411,7 +411,7 @@ void LegoJetskiRaceActor::Animate(float p_time)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_unk0x0c == 1) {
|
if (m_animState == 1) {
|
||||||
LegoAnimActor::Animate(p_time);
|
LegoAnimActor::Animate(p_time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -306,6 +306,8 @@ MxLong Infocenter::HandleEndAction(MxEndActionNotificationParam& p_param)
|
|||||||
|
|
||||||
if (!m_unk0x1d4) {
|
if (!m_unk0x1d4) {
|
||||||
PlayMusic(JukeboxScript::c_InformationCenter_Music);
|
PlayMusic(JukeboxScript::c_InformationCenter_Music);
|
||||||
|
|
||||||
|
if (!Lego()->IsVersion10()) {
|
||||||
GameState()->SetActor(m_selectedCharacter);
|
GameState()->SetActor(m_selectedCharacter);
|
||||||
|
|
||||||
switch (m_selectedCharacter) {
|
switch (m_selectedCharacter) {
|
||||||
@ -331,6 +333,7 @@ MxLong Infocenter::HandleEndAction(MxEndActionNotificationParam& p_param)
|
|||||||
UpdateFrameHot(TRUE);
|
UpdateFrameHot(TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MxLong result = m_radio.Notify(p_param);
|
MxLong result = m_radio.Notify(p_param);
|
||||||
|
|
||||||
@ -338,7 +341,7 @@ MxLong Infocenter::HandleEndAction(MxEndActionNotificationParam& p_param)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action->GetObjectId() == InfomainScript::c_iicx26in_RunAnim) {
|
if (action->GetObjectId() == InfomainScript::c_iicx26in_RunAnim - Lego()->IsVersion10()) {
|
||||||
ControlManager()->FUN_100293c0(InfomainScript::c_BigInfo_Ctl, action->GetAtomId().GetInternal(), 0);
|
ControlManager()->FUN_100293c0(InfomainScript::c_BigInfo_Ctl, action->GetAtomId().GetInternal(), 0);
|
||||||
m_unk0x1d6 = 0;
|
m_unk0x1d6 = 0;
|
||||||
}
|
}
|
||||||
@ -478,7 +481,7 @@ void Infocenter::ReadyWorld()
|
|||||||
InfomainScript::Script script = m_infocenterState->GetNextReturnDialogue();
|
InfomainScript::Script script = m_infocenterState->GetNextReturnDialogue();
|
||||||
PlayAction(script);
|
PlayAction(script);
|
||||||
|
|
||||||
if (script == InfomainScript::c_iicx26in_RunAnim) {
|
if (script == InfomainScript::c_iicx26in_RunAnim - Lego()->IsVersion10()) {
|
||||||
m_unk0x1d6 = 1;
|
m_unk0x1d6 = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1186,13 +1189,13 @@ MxLong Infocenter::HandleNotification0(MxNotificationParam& p_param)
|
|||||||
m_currentInfomainScript == InfomainScript::c_Pepper_All_Movie ||
|
m_currentInfomainScript == InfomainScript::c_Pepper_All_Movie ||
|
||||||
m_currentInfomainScript == InfomainScript::c_Nick_All_Movie ||
|
m_currentInfomainScript == InfomainScript::c_Nick_All_Movie ||
|
||||||
m_currentInfomainScript == InfomainScript::c_Laura_All_Movie ||
|
m_currentInfomainScript == InfomainScript::c_Laura_All_Movie ||
|
||||||
m_currentInfomainScript == InfomainScript::c_iic007ra_PlayWav ||
|
m_currentInfomainScript == InfomainScript::c_iic007ra_PlayWav - Lego()->IsVersion10() ||
|
||||||
m_currentInfomainScript == InfomainScript::c_ijs002ra_PlayWav ||
|
m_currentInfomainScript == InfomainScript::c_ijs002ra_PlayWav - Lego()->IsVersion10() ||
|
||||||
m_currentInfomainScript == InfomainScript::c_irt001ra_PlayWav ||
|
m_currentInfomainScript == InfomainScript::c_irt001ra_PlayWav - Lego()->IsVersion10() ||
|
||||||
m_currentInfomainScript == InfomainScript::c_ipz006ra_PlayWav ||
|
m_currentInfomainScript == InfomainScript::c_ipz006ra_PlayWav - Lego()->IsVersion10() ||
|
||||||
m_currentInfomainScript == InfomainScript::c_igs004ra_PlayWav ||
|
m_currentInfomainScript == InfomainScript::c_igs004ra_PlayWav - Lego()->IsVersion10() ||
|
||||||
m_currentInfomainScript == InfomainScript::c_iho003ra_PlayWav ||
|
m_currentInfomainScript == InfomainScript::c_iho003ra_PlayWav - Lego()->IsVersion10() ||
|
||||||
m_currentInfomainScript == InfomainScript::c_ips005ra_PlayWav) {
|
m_currentInfomainScript == InfomainScript::c_ips005ra_PlayWav - Lego()->IsVersion10()) {
|
||||||
StopCurrentAction();
|
StopCurrentAction();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1506,6 +1509,17 @@ void Infocenter::StopCredits()
|
|||||||
// FUNCTION: BETA10 0x1002ee8c
|
// FUNCTION: BETA10 0x1002ee8c
|
||||||
void Infocenter::PlayAction(InfomainScript::Script p_script)
|
void Infocenter::PlayAction(InfomainScript::Script p_script)
|
||||||
{
|
{
|
||||||
|
if (Lego()->IsVersion10()) {
|
||||||
|
if (p_script == InfomainScript::c_iicx18in_RunAnim) {
|
||||||
|
// Alternative dialogue after signing in (1.0 version)
|
||||||
|
p_script = InfomainScript::c_iic016in_RunAnim;
|
||||||
|
}
|
||||||
|
else if (p_script > InfomainScript::c_iicx18in_RunAnim) {
|
||||||
|
// Shift all other actions by 1
|
||||||
|
p_script = (InfomainScript::Script)((int) p_script - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MxDSAction action;
|
MxDSAction action;
|
||||||
action.SetObjectId(p_script);
|
action.SetObjectId(p_script);
|
||||||
action.SetAtomId(*g_infomainScript);
|
action.SetAtomId(*g_infomainScript);
|
||||||
|
|||||||
@ -810,7 +810,7 @@ void Isle::Enable(MxBool p_enable)
|
|||||||
AnimationManager()->EnableCamAnims(FALSE);
|
AnimationManager()->EnableCamAnims(FALSE);
|
||||||
|
|
||||||
g_isleFlags &= ~c_playMusic;
|
g_isleFlags &= ~c_playMusic;
|
||||||
m_ambulance->FUN_10036e60();
|
m_ambulance->Init();
|
||||||
break;
|
break;
|
||||||
case 11:
|
case 11:
|
||||||
m_act1state->m_unk0x018 = 0;
|
m_act1state->m_unk0x018 = 0;
|
||||||
@ -1209,7 +1209,7 @@ MxBool Isle::Escape()
|
|||||||
case 10:
|
case 10:
|
||||||
if (UserActor() != NULL && !UserActor()->IsA("Ambulance")) {
|
if (UserActor() != NULL && !UserActor()->IsA("Ambulance")) {
|
||||||
m_ambulance->StopActions();
|
m_ambulance->StopActions();
|
||||||
m_ambulance->FUN_10037250();
|
m_ambulance->Reset();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1250,7 +1250,7 @@ void Isle::FUN_10033350()
|
|||||||
if (m_act1state->m_unk0x018 == 10) {
|
if (m_act1state->m_unk0x018 == 10) {
|
||||||
if (UserActor() != NULL && !UserActor()->IsA("Ambulance")) {
|
if (UserActor() != NULL && !UserActor()->IsA("Ambulance")) {
|
||||||
m_ambulance->StopActions();
|
m_ambulance->StopActions();
|
||||||
m_ambulance->FUN_10037250();
|
m_ambulance->Reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -353,7 +353,7 @@ LegoResult LegoLOD::SetTextureInfo(LegoTextureInfo* p_textureInfo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x100aad70
|
// FUNCTION: LEGO1 0x100aad70
|
||||||
LegoResult LegoLOD::FUN_100aad70(LegoTextureInfo* p_textureInfo)
|
LegoResult LegoLOD::UpdateTextureInfo(LegoTextureInfo* p_textureInfo)
|
||||||
{
|
{
|
||||||
for (LegoU32 i = m_meshOffset; i < m_numMeshes; i++) {
|
for (LegoU32 i = m_meshOffset; i < m_numMeshes; i++) {
|
||||||
if (m_melems[i].m_textured) {
|
if (m_melems[i].m_textured) {
|
||||||
|
|||||||
@ -31,7 +31,7 @@ class LegoLOD : public ViewLOD {
|
|||||||
LegoLOD* Clone(Tgl::Renderer* p_renderer);
|
LegoLOD* Clone(Tgl::Renderer* p_renderer);
|
||||||
LegoResult SetColor(LegoFloat p_red, LegoFloat p_green, LegoFloat p_blue, LegoFloat p_alpha);
|
LegoResult SetColor(LegoFloat p_red, LegoFloat p_green, LegoFloat p_blue, LegoFloat p_alpha);
|
||||||
LegoResult SetTextureInfo(LegoTextureInfo* p_textureInfo);
|
LegoResult SetTextureInfo(LegoTextureInfo* p_textureInfo);
|
||||||
LegoResult FUN_100aad70(LegoTextureInfo* p_textureInfo);
|
LegoResult UpdateTextureInfo(LegoTextureInfo* p_textureInfo);
|
||||||
void ClearMeshOffset();
|
void ClearMeshOffset();
|
||||||
LegoResult GetTextureInfo(LegoTextureInfo*& p_textureInfo);
|
LegoResult GetTextureInfo(LegoTextureInfo*& p_textureInfo);
|
||||||
|
|
||||||
|
|||||||
@ -20,10 +20,10 @@ class MxString : public MxCore {
|
|||||||
void ToLowerCase();
|
void ToLowerCase();
|
||||||
void MapPathToFilesystem() { MapPathToFilesystem(m_data); }
|
void MapPathToFilesystem() { MapPathToFilesystem(m_data); }
|
||||||
|
|
||||||
MxString& operator=(const MxString& p_str);
|
LEGO1_EXPORT MxString& operator=(const MxString& p_str);
|
||||||
const MxString& operator=(const char* p_str);
|
LEGO1_EXPORT const MxString& operator=(const char* p_str);
|
||||||
MxString operator+(const MxString& p_str) const;
|
LEGO1_EXPORT MxString operator+(const MxString& p_str) const;
|
||||||
MxString operator+(const char* p_str) const;
|
LEGO1_EXPORT MxString operator+(const char* p_str) const;
|
||||||
LEGO1_EXPORT MxString& operator+=(const char* p_str);
|
LEGO1_EXPORT MxString& operator+=(const char* p_str);
|
||||||
|
|
||||||
static void CharSwap(char* p_a, char* p_b);
|
static void CharSwap(char* p_a, char* p_b);
|
||||||
|
|||||||
@ -1,232 +1,102 @@
|
|||||||
#include "SDL3/SDL_surface.h"
|
|
||||||
#include "d3drmrenderer_citro3d.h"
|
#include "d3drmrenderer_citro3d.h"
|
||||||
|
#include "d3drmtexture_impl.h"
|
||||||
|
#include "ddraw_impl.h"
|
||||||
|
#include "meshutils.h"
|
||||||
#include "miniwin.h"
|
#include "miniwin.h"
|
||||||
#include "miniwin/d3d.h"
|
|
||||||
#include "miniwin/d3drm.h"
|
|
||||||
#include "miniwin/windows.h"
|
|
||||||
|
|
||||||
#include <3ds/console.h>
|
|
||||||
#include <3ds/gfx.h>
|
|
||||||
#include <3ds/gpu/enums.h>
|
|
||||||
#include <3ds/gpu/gx.h>
|
|
||||||
#include <3ds/gpu/shaderProgram.h>
|
|
||||||
#include <c3d/framebuffer.h>
|
|
||||||
#include <c3d/renderqueue.h>
|
|
||||||
#include <c3d/texture.h>
|
|
||||||
#include <3ds.h>
|
|
||||||
#include <citro3d.h>
|
|
||||||
#include <tex3ds.h>
|
|
||||||
|
|
||||||
#include "vshader_shbin.h"
|
#include "vshader_shbin.h"
|
||||||
|
|
||||||
int projectionShaderUniformLocation, modelViewUniformLocation;
|
#include <cstring>
|
||||||
|
|
||||||
typedef struct {
|
bool g_rendering = false;
|
||||||
float positions[3];
|
|
||||||
float texcoords[2];
|
|
||||||
float normals[3];
|
|
||||||
} Vertex;
|
|
||||||
|
|
||||||
// from this wiki: https://github.com/tommai78101/homebrew/wiki/Version-002:-Core-Engine
|
static DVLB_s* vshader_dvlb;
|
||||||
static const Vertex vertexList[] =
|
static shaderProgram_s program;
|
||||||
|
static int uLoc_projection;
|
||||||
|
static int uLoc_modelView;
|
||||||
|
static int uLoc_meshColor;
|
||||||
|
static int uLoc_lightVec;
|
||||||
|
static int uLoc_lightClr;
|
||||||
|
static int uLoc_shininess;
|
||||||
|
|
||||||
|
Citro3DRenderer::Citro3DRenderer(DWORD width, DWORD height)
|
||||||
{
|
{
|
||||||
// First face (PZ)
|
m_width = 320;
|
||||||
// First triangle
|
m_height = 240;
|
||||||
{ {-0.5f, -0.5f, +0.5f}, {0.0f, 0.0f}, {0.0f, 0.0f, +1.0f} },
|
m_virtualWidth = width;
|
||||||
{ {+0.5f, -0.5f, +0.5f}, {1.0f, 0.0f}, {0.0f, 0.0f, +1.0f} },
|
m_virtualHeight = height;
|
||||||
{ {+0.5f, +0.5f, +0.5f}, {1.0f, 1.0f}, {0.0f, 0.0f, +1.0f} },
|
|
||||||
// Second triangle
|
|
||||||
{ {+0.5f, +0.5f, +0.5f}, {1.0f, 1.0f}, {0.0f, 0.0f, +1.0f} },
|
|
||||||
{ {-0.5f, +0.5f, +0.5f}, {0.0f, 1.0f}, {0.0f, 0.0f, +1.0f} },
|
|
||||||
{ {-0.5f, -0.5f, +0.5f}, {0.0f, 0.0f}, {0.0f, 0.0f, +1.0f} },
|
|
||||||
|
|
||||||
// Second face (MZ)
|
gfxInitDefault();
|
||||||
// First triangle
|
consoleInit(GFX_TOP, nullptr);
|
||||||
{ {-0.5f, -0.5f, -0.5f}, {0.0f, 0.0f}, {0.0f, 0.0f, -1.0f} },
|
C3D_Init(C3D_DEFAULT_CMDBUF_SIZE);
|
||||||
{ {-0.5f, +0.5f, -0.5f}, {1.0f, 0.0f}, {0.0f, 0.0f, -1.0f} },
|
|
||||||
{ {+0.5f, +0.5f, -0.5f}, {1.0f, 1.0f}, {0.0f, 0.0f, -1.0f} },
|
|
||||||
// Second triangle
|
|
||||||
{ {+0.5f, +0.5f, -0.5f}, {1.0f, 1.0f}, {0.0f, 0.0f, -1.0f} },
|
|
||||||
{ {+0.5f, -0.5f, -0.5f}, {0.0f, 1.0f}, {0.0f, 0.0f, -1.0f} },
|
|
||||||
{ {-0.5f, -0.5f, -0.5f}, {0.0f, 0.0f}, {0.0f, 0.0f, -1.0f} },
|
|
||||||
|
|
||||||
// Third face (PX)
|
m_renderTarget = C3D_RenderTargetCreate(m_height, m_width, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8);
|
||||||
// First triangle
|
C3D_RenderTargetSetOutput(
|
||||||
{ {+0.5f, -0.5f, -0.5f}, {0.0f, 0.0f}, {+1.0f, 0.0f, 0.0f} },
|
m_renderTarget,
|
||||||
{ {+0.5f, +0.5f, -0.5f}, {1.0f, 0.0f}, {+1.0f, 0.0f, 0.0f} },
|
GFX_BOTTOM,
|
||||||
{ {+0.5f, +0.5f, +0.5f}, {1.0f, 1.0f}, {+1.0f, 0.0f, 0.0f} },
|
GFX_LEFT,
|
||||||
// Second triangle
|
GX_TRANSFER_FLIP_VERT(0) | GX_TRANSFER_OUT_TILED(0) | GX_TRANSFER_RAW_COPY(0) |
|
||||||
{ {+0.5f, +0.5f, +0.5f}, {1.0f, 1.0f}, {+1.0f, 0.0f, 0.0f} },
|
GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8) |
|
||||||
{ {+0.5f, -0.5f, +0.5f}, {0.0f, 1.0f}, {+1.0f, 0.0f, 0.0f} },
|
GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO)
|
||||||
{ {+0.5f, -0.5f, -0.5f}, {0.0f, 0.0f}, {+1.0f, 0.0f, 0.0f} },
|
);
|
||||||
|
|
||||||
// Fourth face (MX)
|
vshader_dvlb = DVLB_ParseFile((u32*) vshader_shbin, vshader_shbin_size);
|
||||||
// First triangle
|
shaderProgramInit(&program);
|
||||||
{ {-0.5f, -0.5f, -0.5f}, {0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f} },
|
shaderProgramSetVsh(&program, &vshader_dvlb->DVLE[0]);
|
||||||
{ {-0.5f, -0.5f, +0.5f}, {1.0f, 0.0f}, {-1.0f, 0.0f, 0.0f} },
|
C3D_BindProgram(&program);
|
||||||
{ {-0.5f, +0.5f, +0.5f}, {1.0f, 1.0f}, {-1.0f, 0.0f, 0.0f} },
|
|
||||||
// Second triangle
|
|
||||||
{ {-0.5f, +0.5f, +0.5f}, {1.0f, 1.0f}, {-1.0f, 0.0f, 0.0f} },
|
|
||||||
{ {-0.5f, +0.5f, -0.5f}, {0.0f, 1.0f}, {-1.0f, 0.0f, 0.0f} },
|
|
||||||
{ {-0.5f, -0.5f, -0.5f}, {0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f} },
|
|
||||||
|
|
||||||
// Fifth face (PY)
|
C3D_CullFace(GPU_CULL_FRONT_CCW);
|
||||||
// First triangle
|
|
||||||
{ {-0.5f, +0.5f, -0.5f}, {0.0f, 0.0f}, {0.0f, +1.0f, 0.0f} },
|
|
||||||
{ {-0.5f, +0.5f, +0.5f}, {1.0f, 0.0f}, {0.0f, +1.0f, 0.0f} },
|
|
||||||
{ {+0.5f, +0.5f, +0.5f}, {1.0f, 1.0f}, {0.0f, +1.0f, 0.0f} },
|
|
||||||
// Second triangle
|
|
||||||
{ {+0.5f, +0.5f, +0.5f}, {1.0f, 1.0f}, {0.0f, +1.0f, 0.0f} },
|
|
||||||
{ {+0.5f, +0.5f, -0.5f}, {0.0f, 1.0f}, {0.0f, +1.0f, 0.0f} },
|
|
||||||
{ {-0.5f, +0.5f, -0.5f}, {0.0f, 0.0f}, {0.0f, +1.0f, 0.0f} },
|
|
||||||
|
|
||||||
// Sixth face (MY)
|
uLoc_projection = shaderInstanceGetUniformLocation(program.vertexShader, "projection");
|
||||||
// First triangle
|
uLoc_modelView = shaderInstanceGetUniformLocation(program.vertexShader, "modelView");
|
||||||
{ {-0.5f, -0.5f, -0.5f}, {0.0f, 0.0f}, {0.0f, -1.0f, 0.0f} },
|
uLoc_meshColor = shaderInstanceGetUniformLocation(program.vertexShader, "meshColor");
|
||||||
{ {+0.5f, -0.5f, -0.5f}, {1.0f, 0.0f}, {0.0f, -1.0f, 0.0f} },
|
uLoc_lightVec = shaderInstanceGetUniformLocation(program.vertexShader, "lightVec");
|
||||||
{ {+0.5f, -0.5f, +0.5f}, {1.0f, 1.0f}, {0.0f, -1.0f, 0.0f} },
|
uLoc_lightClr = shaderInstanceGetUniformLocation(program.vertexShader, "lightClr");
|
||||||
// Second triangle
|
uLoc_shininess = shaderInstanceGetUniformLocation(program.vertexShader, "shininess");
|
||||||
{ {+0.5f, -0.5f, +0.5f}, {1.0f, 1.0f}, {0.0f, -1.0f, 0.0f} },
|
|
||||||
{ {-0.5f, -0.5f, +0.5f}, {0.0f, 1.0f}, {0.0f, -1.0f, 0.0f} },
|
|
||||||
{ {-0.5f, -0.5f, -0.5f}, {0.0f, 0.0f}, {0.0f, -1.0f, 0.0f} },
|
|
||||||
};
|
|
||||||
|
|
||||||
void *vbo_data;
|
|
||||||
void sceneInit(shaderProgram_s* prog) {
|
|
||||||
MINIWIN_TRACE("set uniform loc");
|
|
||||||
projectionShaderUniformLocation = shaderInstanceGetUniformLocation(prog->vertexShader, "projection");
|
|
||||||
modelViewUniformLocation = shaderInstanceGetUniformLocation(prog->vertexShader, "modelView");
|
|
||||||
|
|
||||||
// src: https://github.com/devkitPro/citro3d/blob/9f21cf7b380ce6f9e01a0420f19f0763e5443ca7/test/3ds/source/main.cpp#L122C3-L126C62
|
|
||||||
MINIWIN_TRACE("pre attr info");
|
|
||||||
C3D_AttrInfo* attrInfo = C3D_GetAttrInfo();
|
C3D_AttrInfo* attrInfo = C3D_GetAttrInfo();
|
||||||
AttrInfo_Init(attrInfo);
|
AttrInfo_Init(attrInfo);
|
||||||
AttrInfo_AddLoader(attrInfo, 0, GPU_FLOAT, 3); // v0=position
|
AttrInfo_AddLoader(attrInfo, 0, GPU_FLOAT, 3); // v0=position
|
||||||
AttrInfo_AddLoader(attrInfo, 1, GPU_FLOAT, 2); // v1=texcoord
|
AttrInfo_AddLoader(attrInfo, 1, GPU_FLOAT, 3); // v2=normal
|
||||||
AttrInfo_AddLoader(attrInfo, 2, GPU_FLOAT, 3); // v2=normal
|
AttrInfo_AddLoader(attrInfo, 2, GPU_FLOAT, 2); // v1=texcoord
|
||||||
|
|
||||||
MINIWIN_TRACE("pre alloc");
|
|
||||||
vbo_data = linearAlloc(sizeof(vertexList));
|
|
||||||
memcpy(vbo_data, vertexList, sizeof(vertexList));
|
|
||||||
|
|
||||||
//Initialize and configure buffers.
|
|
||||||
MINIWIN_TRACE("pre buf");
|
|
||||||
C3D_BufInfo* bufferInfo = C3D_GetBufInfo();
|
|
||||||
BufInfo_Init(bufferInfo);
|
|
||||||
BufInfo_Add(bufferInfo, vbo_data, sizeof(Vertex), 3, 0x210);
|
|
||||||
|
|
||||||
// this is probably wrong
|
|
||||||
MINIWIN_TRACE("pre tex");
|
|
||||||
C3D_TexEnv* env = C3D_GetTexEnv(0);
|
|
||||||
C3D_TexEnvSrc(env, C3D_Both, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR);
|
|
||||||
C3D_TexEnvFunc(env, C3D_Both, GPU_REPLACE);
|
|
||||||
}
|
|
||||||
|
|
||||||
Direct3DRMRenderer* Citro3DRenderer::Create(DWORD width, DWORD height)
|
|
||||||
{
|
|
||||||
// TODO: Doesn't SDL call this function?
|
|
||||||
// Actually it's in ctrulib -max
|
|
||||||
gfxInitDefault();
|
|
||||||
gfxSetWide(true);
|
|
||||||
gfxSet3D(false);
|
|
||||||
consoleInit(GFX_BOTTOM, nullptr);
|
|
||||||
|
|
||||||
C3D_Init(C3D_DEFAULT_CMDBUF_SIZE);
|
|
||||||
|
|
||||||
return new Citro3DRenderer(width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
// constructor parameters not finalized
|
|
||||||
Citro3DRenderer::Citro3DRenderer(DWORD width, DWORD height)
|
|
||||||
{
|
|
||||||
static shaderProgram_s program;
|
|
||||||
DVLB_s *vsh_dvlb;
|
|
||||||
|
|
||||||
m_width = width;
|
|
||||||
m_height = height / 2;
|
|
||||||
m_virtualWidth = width;
|
|
||||||
m_virtualHeight = height / 2;
|
|
||||||
|
|
||||||
// FIXME: is this the right pixel format?
|
|
||||||
|
|
||||||
shaderProgramInit(&program);
|
|
||||||
vsh_dvlb = DVLB_ParseFile((u32*)vshader_shbin, vshader_shbin_size);
|
|
||||||
shaderProgramSetVsh(&program, &vsh_dvlb->DVLE[0]);
|
|
||||||
|
|
||||||
// WARNING: This might crash, not sure
|
|
||||||
SDL_Log("pre bind");
|
|
||||||
C3D_BindProgram(&program);
|
|
||||||
|
|
||||||
// todo: move to scene init next
|
|
||||||
SDL_Log("setting uniform loc");
|
|
||||||
sceneInit(&program);
|
|
||||||
|
|
||||||
// TODO: is GPU_RB_RGBA8 correct?
|
|
||||||
// TODO: is GPU_RB_DEPTH24_STENCIL8 correct?
|
|
||||||
m_renderTarget = C3D_RenderTargetCreate(width, height, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8);
|
|
||||||
|
|
||||||
// TODO: what color should be used, if we shouldn't use 0x777777FF
|
|
||||||
C3D_RenderTargetClear(m_renderTarget, C3D_CLEAR_ALL, 0x777777FF, 0);
|
|
||||||
|
|
||||||
// TODO: Cleanup as we see what is needed
|
|
||||||
m_flipVertFlag = 0;
|
|
||||||
m_outTiledFlag = 0;
|
|
||||||
m_rawCopyFlag = 0;
|
|
||||||
|
|
||||||
// TODO: correct values?
|
|
||||||
m_transferInputFormatFlag = GX_TRANSFER_FMT_RGBA8;
|
|
||||||
m_transferOutputFormatFlag = GX_TRANSFER_FMT_RGB8;
|
|
||||||
|
|
||||||
m_transferScaleFlag = GX_TRANSFER_SCALE_NO;
|
|
||||||
|
|
||||||
m_transferFlags = (GX_TRANSFER_FLIP_VERT(m_flipVertFlag) | GX_TRANSFER_OUT_TILED(m_outTiledFlag) | \
|
|
||||||
GX_TRANSFER_RAW_COPY(m_rawCopyFlag) | GX_TRANSFER_IN_FORMAT(m_transferInputFormatFlag) | \
|
|
||||||
GX_TRANSFER_OUT_FORMAT(m_transferOutputFormatFlag) | GX_TRANSFER_SCALING(m_transferScaleFlag));
|
|
||||||
|
|
||||||
C3D_RenderTargetSetOutput(m_renderTarget, GFX_TOP, GFX_LEFT, m_transferFlags);
|
|
||||||
|
|
||||||
m_renderedImage = SDL_CreateSurface(m_width, m_height, SDL_PIXELFORMAT_RGBA32);
|
|
||||||
MINIWIN_NOT_IMPLEMENTED();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Citro3DRenderer::~Citro3DRenderer()
|
Citro3DRenderer::~Citro3DRenderer()
|
||||||
{
|
{
|
||||||
SDL_DestroySurface(m_renderedImage);
|
shaderProgramFree(&program);
|
||||||
C3D_RenderTargetDelete(m_renderTarget);
|
DVLB_Free(vshader_dvlb);
|
||||||
|
C3D_Fini();
|
||||||
|
gfxExit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Citro3DRenderer::PushLights(const SceneLight* lightsArray, size_t count)
|
void Citro3DRenderer::PushLights(const SceneLight* lights, size_t count)
|
||||||
{
|
{
|
||||||
MINIWIN_NOT_IMPLEMENTED();
|
m_lights.assign(lights, lights + count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Citro3DRenderer::SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back)
|
void Citro3DRenderer::SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back)
|
||||||
{
|
{
|
||||||
MINIWIN_TRACE("Set projection");
|
|
||||||
memcpy(&m_projection, projection, sizeof(D3DRMMATRIX4D));
|
memcpy(&m_projection, projection, sizeof(D3DRMMATRIX4D));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Citro3DRenderer::SetFrustumPlanes(const Plane* frustumPlanes)
|
void Citro3DRenderer::SetFrustumPlanes(const Plane* frustumPlanes)
|
||||||
{
|
{
|
||||||
MINIWIN_NOT_IMPLEMENTED();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TextureDestroyContextC3D {
|
struct Citro3DCacheDestroyContext {
|
||||||
Citro3DRenderer* renderer;
|
Citro3DRenderer* renderer;
|
||||||
Uint32 textureId;
|
Uint32 id;
|
||||||
};
|
};
|
||||||
|
|
||||||
void Citro3DRenderer::AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture)
|
void Citro3DRenderer::AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture)
|
||||||
{
|
{
|
||||||
auto* ctx = new TextureDestroyContextC3D{this, id};
|
auto* ctx = new Citro3DCacheDestroyContext{this, id};
|
||||||
texture->AddDestroyCallback(
|
texture->AddDestroyCallback(
|
||||||
[](IDirect3DRMObject* obj, void* arg) {
|
[](IDirect3DRMObject* obj, void* arg) {
|
||||||
auto* ctx = static_cast<TextureDestroyContextC3D*>(arg);
|
auto* ctx = static_cast<Citro3DCacheDestroyContext*>(arg);
|
||||||
auto& cache = ctx->renderer->m_textures[ctx->textureId];
|
auto& entry = ctx->renderer->m_textures[ctx->id];
|
||||||
if (cache.c3dTex != nullptr) {
|
if (entry.texture) {
|
||||||
C3D_TexDelete(cache.c3dTex);
|
C3D_TexDelete(&entry.c3dTex);
|
||||||
cache.c3dTex = nullptr;
|
entry.texture = nullptr;
|
||||||
cache.texture = nullptr;
|
|
||||||
}
|
}
|
||||||
delete ctx;
|
delete ctx;
|
||||||
},
|
},
|
||||||
@ -234,90 +104,256 @@ void Citro3DRenderer::AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* t
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int NearestPowerOfTwoClamp(int val)
|
||||||
|
{
|
||||||
|
static const int sizes[] = {512, 256, 128, 64, 32, 16, 8};
|
||||||
|
for (int size : sizes) {
|
||||||
|
if (val >= size) {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SDL_Surface* ConvertAndResizeSurface(SDL_Surface* original)
|
||||||
|
{
|
||||||
|
SDL_Surface* converted = SDL_ConvertSurface(original, SDL_PIXELFORMAT_RGBA8888);
|
||||||
|
if (!converted) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int newW = NearestPowerOfTwoClamp(converted->w);
|
||||||
|
int newH = converted->h == 480 ? 256 : NearestPowerOfTwoClamp(converted->h);
|
||||||
|
|
||||||
|
if (converted->w == newW && converted->h == newH) {
|
||||||
|
return converted;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Surface* resized = SDL_CreateSurface(newW, newH, SDL_PIXELFORMAT_RGBA8888);
|
||||||
|
if (!resized) {
|
||||||
|
SDL_DestroySurface(converted);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_BlitSurfaceScaled(converted, nullptr, resized, nullptr, SDL_SCALEMODE_NEAREST);
|
||||||
|
|
||||||
|
SDL_DestroySurface(converted);
|
||||||
|
return resized;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int mortonInterleave(int x, int y)
|
||||||
|
{
|
||||||
|
int answer = 0;
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
answer |= ((y >> i) & 1) << (2 * i + 1);
|
||||||
|
answer |= ((x >> i) & 1) << (2 * i);
|
||||||
|
}
|
||||||
|
return answer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void EncodeTextureLayout(const u8* src, u8* dst, int width, int height)
|
||||||
|
{
|
||||||
|
const int tileSize = 8;
|
||||||
|
const int bytesPerPixel = 4;
|
||||||
|
|
||||||
|
int tilesPerRow = (width + tileSize - 1) / tileSize;
|
||||||
|
|
||||||
|
for (int tileY = 0; tileY < height; tileY += tileSize) {
|
||||||
|
for (int tileX = 0; tileX < width; tileX += tileSize) {
|
||||||
|
int tileIndex = (tileY / tileSize) * tilesPerRow + (tileX / tileSize);
|
||||||
|
tileIndex *= tileSize * tileSize;
|
||||||
|
|
||||||
|
for (int y = 0; y < tileSize; ++y) {
|
||||||
|
for (int x = 0; x < tileSize; ++x) {
|
||||||
|
int srcX = tileX + x;
|
||||||
|
int srcY = tileY + y;
|
||||||
|
|
||||||
|
if (srcX >= width || srcY >= height) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mortonIndex = mortonInterleave(x, y);
|
||||||
|
int dstIndex = (tileIndex + mortonIndex) * bytesPerPixel;
|
||||||
|
int srcIndex = ((height - 1 - srcY) * width + srcX) * bytesPerPixel;
|
||||||
|
|
||||||
|
std::memcpy(&dst[dstIndex], &src[srcIndex], bytesPerPixel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ConvertAndUploadTexture(C3D_Tex* tex, SDL_Surface* originalSurface)
|
||||||
|
{
|
||||||
|
SDL_Surface* resized = ConvertAndResizeSurface(originalSurface);
|
||||||
|
if (!resized) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int width = resized->w;
|
||||||
|
int height = resized->h;
|
||||||
|
|
||||||
|
if (!C3D_TexInit(tex, width, height, GPU_RGBA8)) {
|
||||||
|
SDL_DestroySurface(resized);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate buffer for tiled texture
|
||||||
|
uint8_t* tiledData = (uint8_t*) malloc(width * height * 4);
|
||||||
|
if (!tiledData) {
|
||||||
|
SDL_DestroySurface(resized);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
EncodeTextureLayout((const u8*) resized->pixels, tiledData, width, height);
|
||||||
|
|
||||||
|
C3D_TexUpload(tex, tiledData);
|
||||||
|
C3D_TexSetFilter(tex, GPU_LINEAR, GPU_NEAREST);
|
||||||
|
|
||||||
|
free(tiledData);
|
||||||
|
SDL_DestroySurface(resized);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
Uint32 Citro3DRenderer::GetTextureId(IDirect3DRMTexture* iTexture)
|
Uint32 Citro3DRenderer::GetTextureId(IDirect3DRMTexture* iTexture)
|
||||||
{
|
{
|
||||||
auto texture = static_cast<Direct3DRMTextureImpl*>(iTexture);
|
auto texture = static_cast<Direct3DRMTextureImpl*>(iTexture);
|
||||||
auto surface = static_cast<DirectDrawSurfaceImpl*>(texture->m_surface);
|
auto surface = static_cast<DirectDrawSurfaceImpl*>(texture->m_surface);
|
||||||
|
SDL_Surface* originalSurface = surface->m_surface;
|
||||||
|
|
||||||
|
int originalW = originalSurface->w;
|
||||||
|
int originalH = originalSurface->h;
|
||||||
|
|
||||||
for (Uint32 i = 0; i < m_textures.size(); ++i) {
|
for (Uint32 i = 0; i < m_textures.size(); ++i) {
|
||||||
auto& tex = m_textures[i];
|
auto& tex = m_textures[i];
|
||||||
if (tex.texture == texture) {
|
if (tex.texture == texture) {
|
||||||
if (tex.version != texture->m_version) {
|
if (tex.version != texture->m_version) {
|
||||||
C3D_TexDelete(tex.c3dTex);
|
C3D_TexDelete(&tex.c3dTex);
|
||||||
|
if (!ConvertAndUploadTexture(&tex.c3dTex, originalSurface)) {
|
||||||
SDL_Surface* surf = SDL_ConvertSurface(surface->m_surface, SDL_PIXELFORMAT_RGBA32);
|
|
||||||
if (!surf) {
|
|
||||||
return NO_TEXTURE_ID;
|
return NO_TEXTURE_ID;
|
||||||
}
|
}
|
||||||
// Apparently a crash may be caused due to large textures? Hopefully this fixes that.
|
|
||||||
surf = SDL_ScaleSurface(surf, (surf->w / 2), (surf->h / 2), SDL_SCALEMODE_LINEAR);
|
|
||||||
|
|
||||||
// TODO: C3D_TexGenerateMipmap or C3D_TexInit?
|
|
||||||
// glGenTextures(1, &tex.glTextureId);
|
|
||||||
// FIXME: GPU_RGBA8 may be wrong
|
|
||||||
C3D_TexInitMipmap(tex.c3dTex, surf->w, surf->h, GPU_RGBA8);
|
|
||||||
Tex3DS_Texture t3x = Tex3DS_TextureImport(t3x, (size_t)(surf->w * surf->h), tex.c3dTex, NULL, false);
|
|
||||||
Tex3DS_TextureFree(t3x);
|
|
||||||
|
|
||||||
C3D_TexBind(0, tex.c3dTex);
|
|
||||||
C3D_TexUpload(tex.c3dTex, surf->pixels);
|
|
||||||
SDL_DestroySurface(surf);
|
|
||||||
|
|
||||||
tex.version = texture->m_version;
|
tex.version = texture->m_version;
|
||||||
|
tex.width = originalW;
|
||||||
|
tex.height = originalH;
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
C3D_Tex newTex;
|
C3DTextureCacheEntry entry;
|
||||||
|
entry.texture = texture;
|
||||||
|
entry.version = texture->m_version;
|
||||||
|
entry.width = originalW;
|
||||||
|
entry.height = originalH;
|
||||||
|
|
||||||
SDL_Surface* surf = SDL_ConvertSurface(surface->m_surface, SDL_PIXELFORMAT_RGBA32);
|
if (!ConvertAndUploadTexture(&entry.c3dTex, originalSurface)) {
|
||||||
if (!surf) {
|
|
||||||
return NO_TEXTURE_ID;
|
return NO_TEXTURE_ID;
|
||||||
}
|
}
|
||||||
C3D_TexInit(&newTex, surf->w, surf->h, GPU_RGBA8);
|
|
||||||
C3D_TexBind(0, &newTex);
|
|
||||||
C3D_TexUpload(&newTex, surf->pixels);
|
|
||||||
SDL_DestroySurface(surf);
|
|
||||||
|
|
||||||
for (Uint32 i = 0; i < m_textures.size(); ++i) {
|
for (Uint32 i = 0; i < m_textures.size(); ++i) {
|
||||||
auto& tex = m_textures[i];
|
if (!m_textures[i].texture) {
|
||||||
if (!tex.texture) {
|
m_textures[i] = std::move(entry);
|
||||||
tex.texture = texture;
|
|
||||||
tex.version = texture->m_version;
|
|
||||||
tex.c3dTex = &newTex;
|
|
||||||
AddTextureDestroyCallback(i, texture);
|
AddTextureDestroyCallback(i, texture);
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_textures.push_back({texture, texture->m_version, &newTex});
|
m_textures.push_back(std::move(entry));
|
||||||
AddTextureDestroyCallback((Uint32) (m_textures.size() - 1), texture);
|
AddTextureDestroyCallback((Uint32) (m_textures.size() - 1), texture);
|
||||||
return (Uint32) (m_textures.size() - 1);
|
return (Uint32) (m_textures.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
C3DMeshCacheEntry C3DUploadMesh(const MeshGroup& meshGroup)
|
||||||
|
{
|
||||||
|
C3DMeshCacheEntry cache{&meshGroup, meshGroup.version};
|
||||||
|
|
||||||
|
std::vector<D3DRMVERTEX> vertexBuffer;
|
||||||
|
std::vector<uint16_t> indexBuffer;
|
||||||
|
|
||||||
|
if (meshGroup.quality == D3DRMRENDER_FLAT || meshGroup.quality == D3DRMRENDER_UNLITFLAT) {
|
||||||
|
FlattenSurfaces(
|
||||||
|
meshGroup.vertices.data(),
|
||||||
|
meshGroup.vertices.size(),
|
||||||
|
meshGroup.indices.data(),
|
||||||
|
meshGroup.indices.size(),
|
||||||
|
meshGroup.texture != nullptr,
|
||||||
|
vertexBuffer,
|
||||||
|
indexBuffer
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
vertexBuffer.assign(meshGroup.vertices.begin(), meshGroup.vertices.end());
|
||||||
|
indexBuffer.assign(meshGroup.indices.begin(), meshGroup.indices.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
MINIWIN_NOT_IMPLEMENTED();
|
||||||
|
|
||||||
|
// TODO use ibo instead of flattening verticies, see
|
||||||
|
// https://github.com/devkitPro/3ds-examples/blob/44faa81d79d5781c0e149e4a7005f2e005edb736/graphics/gpu/loop_subdivision/source/main.c#L104
|
||||||
|
std::vector<D3DRMVERTEX> vertexUploadBuffer;
|
||||||
|
vertexUploadBuffer.reserve(indexBuffer.size());
|
||||||
|
|
||||||
|
for (size_t i = 0; i < indexBuffer.size(); ++i) {
|
||||||
|
vertexUploadBuffer.emplace_back(vertexBuffer[indexBuffer[i]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t vertexBufferSize = vertexUploadBuffer.size() * sizeof(D3DRMVERTEX);
|
||||||
|
cache.vbo = linearAlloc(vertexBufferSize);
|
||||||
|
memcpy(cache.vbo, vertexUploadBuffer.data(), vertexBufferSize);
|
||||||
|
cache.vertexCount = vertexUploadBuffer.size();
|
||||||
|
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Citro3DRenderer::AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh)
|
||||||
|
{
|
||||||
|
auto* ctx = new Citro3DCacheDestroyContext{this, id};
|
||||||
|
mesh->AddDestroyCallback(
|
||||||
|
[](IDirect3DRMObject* obj, void* arg) {
|
||||||
|
auto* ctx = static_cast<Citro3DCacheDestroyContext*>(arg);
|
||||||
|
auto& cacheEntry = ctx->renderer->m_meshs[ctx->id];
|
||||||
|
if (cacheEntry.meshGroup) {
|
||||||
|
cacheEntry.meshGroup = nullptr;
|
||||||
|
linearFree(cacheEntry.vbo);
|
||||||
|
cacheEntry.vertexCount = 0;
|
||||||
|
}
|
||||||
|
delete ctx;
|
||||||
|
},
|
||||||
|
ctx
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Uint32 Citro3DRenderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup)
|
Uint32 Citro3DRenderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup)
|
||||||
{
|
{
|
||||||
MINIWIN_NOT_IMPLEMENTED();
|
for (Uint32 i = 0; i < m_meshs.size(); ++i) {
|
||||||
return 0;
|
auto& cache = m_meshs[i];
|
||||||
|
if (cache.meshGroup == meshGroup) {
|
||||||
|
if (cache.version != meshGroup->version) {
|
||||||
|
cache = std::move(C3DUploadMesh(*meshGroup));
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto newCache = C3DUploadMesh(*meshGroup);
|
||||||
|
|
||||||
|
for (Uint32 i = 0; i < m_meshs.size(); ++i) {
|
||||||
|
auto& cache = m_meshs[i];
|
||||||
|
if (!cache.meshGroup) {
|
||||||
|
cache = std::move(newCache);
|
||||||
|
AddMeshDestroyCallback(i, mesh);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_meshs.push_back(std::move(newCache));
|
||||||
|
AddMeshDestroyCallback((Uint32) (m_meshs.size() - 1), mesh);
|
||||||
|
return (Uint32) (m_meshs.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Citro3DRenderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc)
|
void Citro3DRenderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc)
|
||||||
{
|
{
|
||||||
// not sure if this is correct?
|
|
||||||
MINIWIN_NOT_IMPLEMENTED();
|
|
||||||
|
|
||||||
halDesc->dcmColorModel = D3DCOLORMODEL::RGB;
|
|
||||||
helDesc->dwFlags = D3DDD_DEVICEZBUFFERBITDEPTH;
|
|
||||||
helDesc->dwDeviceZBufferBitDepth = DDBD_24;
|
|
||||||
helDesc->dwDeviceRenderBitDepth = DDBD_24;
|
|
||||||
helDesc->dpcTriCaps.dwTextureCaps = D3DPTEXTURECAPS_PERSPECTIVE;
|
|
||||||
helDesc->dpcTriCaps.dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND;
|
|
||||||
|
|
||||||
// TODO: shouldn't this be bilinear
|
|
||||||
helDesc->dpcTriCaps.dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR;
|
|
||||||
|
|
||||||
memset(helDesc, 0, sizeof(D3DDEVICEDESC));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* Citro3DRenderer::GetName()
|
const char* Citro3DRenderer::GetName()
|
||||||
@ -325,20 +361,84 @@ const char* Citro3DRenderer::GetName()
|
|||||||
return "Citro3D";
|
return "Citro3D";
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT Citro3DRenderer::BeginFrame()
|
void Citro3DRenderer::StartFrame()
|
||||||
{
|
{
|
||||||
MINIWIN_NOT_IMPLEMENTED();
|
if (g_rendering) {
|
||||||
gfxFlushBuffers();
|
return;
|
||||||
gfxSwapBuffers();
|
}
|
||||||
gspWaitForVBlank(); // FIXME: is this the right place to call, if we should at all?
|
|
||||||
C3D_FrameBegin(C3D_FRAME_SYNCDRAW);
|
C3D_FrameBegin(C3D_FRAME_SYNCDRAW);
|
||||||
C3D_FrameDrawOn(m_renderTarget);
|
C3D_FrameDrawOn(m_renderTarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConvertPerspective(const D3DRMMATRIX4D in, C3D_Mtx* out)
|
||||||
|
{
|
||||||
|
float f_h = in[0][0];
|
||||||
|
float f_v = in[1][1];
|
||||||
|
|
||||||
|
float aspect = f_v / f_h;
|
||||||
|
float fovY = 2.0f * atanf(1.0f / f_v);
|
||||||
|
|
||||||
|
float nearZ = -in[3][2] / in[2][2];
|
||||||
|
float farZ = nearZ * in[2][2] / (in[2][2] - 1.0f);
|
||||||
|
|
||||||
|
Mtx_PerspTilt(out, fovY, aspect, nearZ, farZ, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT Citro3DRenderer::BeginFrame()
|
||||||
|
{
|
||||||
|
StartFrame();
|
||||||
|
C3D_DepthTest(true, GPU_GREATER, GPU_WRITE_ALL);
|
||||||
|
|
||||||
|
C3D_Mtx projection;
|
||||||
|
ConvertPerspective(m_projection, &projection);
|
||||||
|
C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uLoc_projection, &projection);
|
||||||
|
|
||||||
|
for (const auto& light : m_lights) {
|
||||||
|
FColor lightColor = light.color;
|
||||||
|
if (light.positional == 0.0f && light.directional == 0.0f) {
|
||||||
|
// Ambient light
|
||||||
|
C3D_FVUnifSet(GPU_VERTEX_SHADER, uLoc_lightClr + 2, lightColor.r, lightColor.g, lightColor.b, 1.0f);
|
||||||
|
}
|
||||||
|
else if (light.directional == 1.0f) {
|
||||||
|
C3D_FVUnifSet(
|
||||||
|
GPU_VERTEX_SHADER,
|
||||||
|
uLoc_lightVec + 1,
|
||||||
|
-light.direction.x,
|
||||||
|
-light.direction.y,
|
||||||
|
-light.direction.z,
|
||||||
|
0.0f
|
||||||
|
);
|
||||||
|
C3D_FVUnifSet(GPU_VERTEX_SHADER, uLoc_lightClr + 1, lightColor.r, lightColor.g, lightColor.b, 0.0f);
|
||||||
|
}
|
||||||
|
else if (light.positional == 1.0f) {
|
||||||
|
C3D_FVUnifSet(
|
||||||
|
GPU_VERTEX_SHADER,
|
||||||
|
uLoc_lightVec + 0,
|
||||||
|
light.position.x,
|
||||||
|
light.position.y,
|
||||||
|
light.position.z,
|
||||||
|
0.0f
|
||||||
|
);
|
||||||
|
C3D_FVUnifSet(GPU_VERTEX_SHADER, uLoc_lightClr + 0, lightColor.r, lightColor.g, lightColor.b, 0.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Citro3DRenderer::EnableTransparency()
|
void Citro3DRenderer::EnableTransparency()
|
||||||
{
|
{
|
||||||
MINIWIN_NOT_IMPLEMENTED();
|
C3D_DepthTest(true, GPU_GREATER, GPU_WRITE_COLOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConvertMatrix(const D3DRMMATRIX4D in, C3D_Mtx* out)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
out->r[i].x = in[0][i];
|
||||||
|
out->r[i].y = in[1][i];
|
||||||
|
out->r[i].z = in[2][i];
|
||||||
|
out->r[i].w = in[3][i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Citro3DRenderer::SubmitDraw(
|
void Citro3DRenderer::SubmitDraw(
|
||||||
@ -350,47 +450,56 @@ void Citro3DRenderer::SubmitDraw(
|
|||||||
const Appearance& appearance
|
const Appearance& appearance
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
MINIWIN_NOT_IMPLEMENTED();
|
C3D_Mtx projection, modelView;
|
||||||
|
ConvertPerspective(m_projection, &projection);
|
||||||
|
ConvertMatrix(modelViewMatrix, &modelView);
|
||||||
|
C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uLoc_modelView, &modelView);
|
||||||
|
|
||||||
|
auto& mesh = m_meshs[meshId];
|
||||||
|
|
||||||
|
C3D_BufInfo* bufInfo = C3D_GetBufInfo();
|
||||||
|
BufInfo_Init(bufInfo);
|
||||||
|
BufInfo_Add(bufInfo, mesh.vbo, sizeof(D3DRMVERTEX), 3, 0x210);
|
||||||
|
|
||||||
|
C3D_FVUnifSet(
|
||||||
|
GPU_VERTEX_SHADER,
|
||||||
|
uLoc_meshColor,
|
||||||
|
appearance.color.r / 255.0f,
|
||||||
|
appearance.color.g / 255.0f,
|
||||||
|
appearance.color.b / 255.0f,
|
||||||
|
appearance.color.a / 255.0f
|
||||||
|
);
|
||||||
|
|
||||||
|
C3D_FVUnifSet(GPU_VERTEX_SHADER, uLoc_shininess, appearance.shininess / 255.0f, 0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
if (appearance.textureId != NO_TEXTURE_ID) {
|
||||||
|
C3D_TexBind(0, &m_textures[appearance.textureId].c3dTex);
|
||||||
|
C3D_TexEnv* env = C3D_GetTexEnv(0);
|
||||||
|
C3D_TexEnvInit(env);
|
||||||
|
C3D_TexEnvSrc(env, C3D_Both, GPU_TEXTURE0, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR);
|
||||||
|
C3D_TexEnvFunc(env, C3D_Both, GPU_MODULATE);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
C3D_TexBind(0, nullptr);
|
||||||
|
C3D_TexEnv* env = C3D_GetTexEnv(0);
|
||||||
|
C3D_TexEnvInit(env);
|
||||||
|
C3D_TexEnvSrc(env, C3D_Both, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR);
|
||||||
|
C3D_TexEnvFunc(env, C3D_Both, GPU_REPLACE);
|
||||||
|
}
|
||||||
|
|
||||||
|
C3D_DrawArrays(GPU_TRIANGLES, 0, mesh.vertexCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT Citro3DRenderer::FinalizeFrame()
|
HRESULT Citro3DRenderer::FinalizeFrame()
|
||||||
{
|
{
|
||||||
MINIWIN_NOT_IMPLEMENTED();
|
|
||||||
Mtx_PerspStereoTilt(&this->m_projectionMatrix, 40.0f * (acos(-1) / 180.0f), 400.0f / 240.0f, 0.01f, 1000.0f, 1, 2.0f, false);
|
|
||||||
Mtx_Translate(&this->m_projectionMatrix, 0.0, 0.0, -10.0, 0);
|
|
||||||
|
|
||||||
//Calculate model view matrix.
|
|
||||||
C3D_Mtx modelView;
|
|
||||||
Mtx_Identity(&modelView);
|
|
||||||
// Mtx_Translate(&modelView, 0.0, 0.0, -2.0 + sinf(this->angleX));
|
|
||||||
// Mtx_RotateX(&modelView, this->angleX, true);
|
|
||||||
// Mtx_RotateY(&modelView, this->angleY, true);
|
|
||||||
|
|
||||||
// if (interOcularDistance >= 0.0f){
|
|
||||||
// this->angleX += radian;
|
|
||||||
// this->angleY += radian;
|
|
||||||
// }
|
|
||||||
|
|
||||||
//Update uniforms
|
|
||||||
C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, m_projectionShaderUniformLocation, &this->m_projectionMatrix);
|
|
||||||
C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, modelViewUniformLocation, &modelView);
|
|
||||||
|
|
||||||
//Draw the vertex buffer objects.
|
|
||||||
C3D_DrawArrays(GPU_TRIANGLES, 0, sizeof(vertexList));
|
|
||||||
C3D_FrameEnd(0);
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Citro3DRenderer::Resize(int width, int height, const ViewportTransform& viewportTransform)
|
void Citro3DRenderer::Resize(int width, int height, const ViewportTransform& viewportTransform)
|
||||||
{
|
{
|
||||||
MINIWIN_NOT_IMPLEMENTED();
|
|
||||||
m_width = width;
|
m_width = width;
|
||||||
m_height = height;
|
m_height = height;
|
||||||
m_viewportTransform = viewportTransform;
|
m_viewportTransform = viewportTransform;
|
||||||
|
|
||||||
SDL_DestroySurface(m_renderedImage);
|
|
||||||
// FIXME: is this the right pixel format?
|
|
||||||
m_renderedImage = SDL_CreateSurface(m_width, m_height, SDL_PIXELFORMAT_RGBA32);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Citro3DRenderer::Clear(float r, float g, float b)
|
void Citro3DRenderer::Clear(float r, float g, float b)
|
||||||
@ -402,26 +511,91 @@ void Citro3DRenderer::Clear(float r, float g, float b)
|
|||||||
|
|
||||||
void Citro3DRenderer::Flip()
|
void Citro3DRenderer::Flip()
|
||||||
{
|
{
|
||||||
MINIWIN_NOT_IMPLEMENTED();
|
C3D_FrameEnd(0);
|
||||||
|
gfxFlushBuffers();
|
||||||
|
gspWaitForVBlank();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Citro3DRenderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect)
|
void Citro3DRenderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect)
|
||||||
{
|
{
|
||||||
MINIWIN_NOT_IMPLEMENTED();
|
C3D_AlphaBlend(GPU_BLEND_ADD, GPU_BLEND_ADD, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
|
||||||
MINIWIN_TRACE("on draw 2d image");
|
StartFrame();
|
||||||
|
C3D_DepthTest(false, GPU_GREATER, GPU_WRITE_COLOR);
|
||||||
|
|
||||||
float left = -m_viewportTransform.offsetX / m_viewportTransform.scale;
|
float left = -m_viewportTransform.offsetX / m_viewportTransform.scale;
|
||||||
float right = (m_width - m_viewportTransform.offsetX) / m_viewportTransform.scale;
|
float right = (m_width - m_viewportTransform.offsetX) / m_viewportTransform.scale;
|
||||||
float top = -m_viewportTransform.offsetY / m_viewportTransform.scale;
|
float top = -m_viewportTransform.offsetY / m_viewportTransform.scale;
|
||||||
float bottom = (m_height - m_viewportTransform.offsetY) / m_viewportTransform.scale;
|
float bottom = (m_height - m_viewportTransform.offsetY) / m_viewportTransform.scale;
|
||||||
|
|
||||||
C3D_Mtx mtx;
|
C3D_Mtx projection, modelView;
|
||||||
|
Mtx_OrthoTilt(&projection, left, right, bottom, top, 0.0f, 1.0f, true);
|
||||||
|
C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uLoc_projection, &projection);
|
||||||
|
Mtx_Identity(&modelView);
|
||||||
|
C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uLoc_modelView, &modelView);
|
||||||
|
|
||||||
// TODO: isLeftHanded set to false. Should it be true?
|
// Set light directions
|
||||||
MINIWIN_TRACE("pre orthotilt");
|
C3D_FVUnifSet(GPU_VERTEX_SHADER, uLoc_lightVec + 0, 0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
Mtx_OrthoTilt(&mtx, left, right, bottom, top, -1, 1, false);
|
C3D_FVUnifSet(GPU_VERTEX_SHADER, uLoc_lightVec + 1, 0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
MINIWIN_TRACE("pre fvunifmtx4x4");
|
// Set light colors
|
||||||
C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, projectionShaderUniformLocation, &mtx);
|
C3D_FVUnifSet(GPU_VERTEX_SHADER, uLoc_lightClr + 0, 0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
|
C3D_FVUnifSet(GPU_VERTEX_SHADER, uLoc_lightClr + 1, 0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
|
C3D_FVUnifSet(GPU_VERTEX_SHADER, uLoc_lightClr + 2, 1.0f, 1.0f, 1.0f, 1.0f); // Ambient
|
||||||
|
|
||||||
|
C3D_FVUnifSet(GPU_VERTEX_SHADER, uLoc_shininess, 0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
|
C3D_FVUnifSet(GPU_VERTEX_SHADER, uLoc_meshColor, 1.0f, 1.0f, 1.0f, 1.0f);
|
||||||
|
|
||||||
|
C3DTextureCacheEntry& texture = m_textures[textureId];
|
||||||
|
|
||||||
|
C3D_TexBind(0, &texture.c3dTex);
|
||||||
|
C3D_TexEnv* env = C3D_GetTexEnv(0);
|
||||||
|
C3D_TexEnvInit(env);
|
||||||
|
C3D_TexEnvSrc(env, C3D_Both, GPU_TEXTURE0, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR);
|
||||||
|
C3D_TexEnvFunc(env, C3D_Both, GPU_MODULATE);
|
||||||
|
|
||||||
|
// Use dstRect size directly for quad size
|
||||||
|
float quadW = static_cast<float>(dstRect.w);
|
||||||
|
float quadH = static_cast<float>(dstRect.h);
|
||||||
|
|
||||||
|
float x1 = static_cast<float>(dstRect.x);
|
||||||
|
float y1 = static_cast<float>(dstRect.y);
|
||||||
|
float x2 = x1 + quadW;
|
||||||
|
float y2 = y1 + quadH;
|
||||||
|
|
||||||
|
float u0 = static_cast<float>(srcRect.x) / texture.width;
|
||||||
|
float u1 = static_cast<float>(srcRect.x + srcRect.w) / texture.width;
|
||||||
|
float v0 = static_cast<float>(srcRect.y) / texture.height;
|
||||||
|
float v1 = static_cast<float>(srcRect.y + srcRect.h) / texture.height;
|
||||||
|
|
||||||
|
C3D_ImmDrawBegin(GPU_TRIANGLES);
|
||||||
|
|
||||||
|
// Triangle 1
|
||||||
|
C3D_ImmSendAttrib(x1, y1, 0.5f, 0.0f);
|
||||||
|
C3D_ImmSendAttrib(0.0f, 0.0f, 1.0f, 0.0f);
|
||||||
|
C3D_ImmSendAttrib(u0, v0, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
C3D_ImmSendAttrib(x2, y1, 0.5f, 0.0f);
|
||||||
|
C3D_ImmSendAttrib(0.0f, 0.0f, 1.0f, 0.0f);
|
||||||
|
C3D_ImmSendAttrib(u1, v0, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
C3D_ImmSendAttrib(x2, y2, 0.5f, 0.0f);
|
||||||
|
C3D_ImmSendAttrib(0.0f, 0.0f, 1.0f, 0.0f);
|
||||||
|
C3D_ImmSendAttrib(u1, v1, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
// Triangle 2
|
||||||
|
C3D_ImmSendAttrib(x2, y2, 0.5f, 0.0f);
|
||||||
|
C3D_ImmSendAttrib(0.0f, 0.0f, 1.0f, 0.0f);
|
||||||
|
C3D_ImmSendAttrib(u1, v1, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
C3D_ImmSendAttrib(x1, y2, 0.5f, 0.0f);
|
||||||
|
C3D_ImmSendAttrib(0.0f, 0.0f, 1.0f, 0.0f);
|
||||||
|
C3D_ImmSendAttrib(u0, v1, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
C3D_ImmSendAttrib(x1, y1, 0.5f, 0.0f);
|
||||||
|
C3D_ImmSendAttrib(0.0f, 0.0f, 1.0f, 0.0f);
|
||||||
|
C3D_ImmSendAttrib(u0, v0, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
C3D_ImmDrawEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Citro3DRenderer::Download(SDL_Surface* target)
|
void Citro3DRenderer::Download(SDL_Surface* target)
|
||||||
|
|||||||
@ -1,36 +1,29 @@
|
|||||||
; From https://github.com/devkitPro/citro3d/blob/master/test/3ds/source/vshader.v.pica
|
|
||||||
; zlib license
|
|
||||||
; ----------
|
|
||||||
|
|
||||||
; Example PICA200 vertex shader
|
|
||||||
|
|
||||||
; Uniforms
|
; Uniforms
|
||||||
.fvec projection[4], modelView[4], texView[2]
|
.fvec projection[4], modelView[4], meshColor
|
||||||
.fvec lightVec, lightHalfVec, lightClr, material[4]
|
.fvec lightVec[2], lightClr[3], shininess
|
||||||
.alias mat_amb material[0]
|
|
||||||
.alias mat_dif material[1]
|
|
||||||
.alias mat_spe material[2]
|
|
||||||
.alias mat_emi material[3]
|
|
||||||
|
|
||||||
; Constants
|
; Constants
|
||||||
.constf myconst(0.0, 1.0, -1.0, -0.5)
|
.constf myconst(0.0, 1.0, -1.0, -0.5)
|
||||||
.alias zeros myconst.xxxx ; Vector full of zeros
|
|
||||||
.alias ones myconst.yyyy ; Vector full of ones
|
|
||||||
|
|
||||||
; Outputs
|
; Outputs
|
||||||
.out outpos position
|
.out outpos position
|
||||||
.out outtc0 texcoord0
|
.out outtc0 texcoord0
|
||||||
.out outclr color
|
.out outclr color
|
||||||
|
|
||||||
; Inputs (defined as aliases for convenience)
|
; Inputs
|
||||||
.alias inpos v0
|
.alias inpos v0
|
||||||
.alias intex v1
|
.alias innrm v1
|
||||||
.alias innrm v2
|
.alias intex v2
|
||||||
|
|
||||||
.proc main
|
.proc main
|
||||||
|
; Prepare constants in usable temp regs
|
||||||
|
mov r15.x, myconst.x ; 0.0
|
||||||
|
mov r15.y, myconst.y ; 1.0
|
||||||
|
mov r15.z, myconst.z ; -1.0
|
||||||
|
|
||||||
; Force the w component of inpos to be 1.0
|
; Force the w component of inpos to be 1.0
|
||||||
mov r0.xyz, inpos
|
mov r0.xyz, inpos
|
||||||
mov r0.w, ones
|
mov r0.w, r15.y
|
||||||
|
|
||||||
; r1 = modelView * inpos
|
; r1 = modelView * inpos
|
||||||
dp4 r1.x, modelView[0], r0
|
dp4 r1.x, modelView[0], r0
|
||||||
@ -45,49 +38,93 @@
|
|||||||
dp4 outpos.w, projection[3], r1
|
dp4 outpos.w, projection[3], r1
|
||||||
|
|
||||||
; outtex = intex
|
; outtex = intex
|
||||||
dp4 outtc0.x, texView[0], intex
|
mov outtc0, intex
|
||||||
dp4 outtc0.y, texView[1], intex
|
|
||||||
mov outtc0.zw, myconst.xy
|
mov outtc0.zw, myconst.xy
|
||||||
|
|
||||||
; Transform the normal vector with the modelView matrix
|
; Transform normal
|
||||||
; r1 = normalize(modelView * innrm)
|
mov r2.xyz, innrm
|
||||||
mov r0.xyz, innrm
|
mov r2.w, r15.x
|
||||||
mov r0.w, zeros
|
dp4 r3.x, modelView[0], r2
|
||||||
dp4 r1.x, modelView[0], r0
|
dp4 r3.y, modelView[1], r2
|
||||||
dp4 r1.y, modelView[1], r0
|
dp4 r3.z, modelView[2], r2
|
||||||
dp4 r1.z, modelView[2], r0
|
mov r3.w, r15.x
|
||||||
mov r1.w, zeros
|
dp3 r4.x, r3, r3
|
||||||
dp3 r2, r1, r1 ; r2 = x^2+y^2+z^2 for each component
|
rsq r4.x, r4.x
|
||||||
rsq r2, r2 ; r2 = 1/sqrt(r2) ''
|
mul r3, r4.xxxx, r3 ; r3 = normalized normal
|
||||||
mul r1, r2, r1 ; r1 = r1*r2
|
|
||||||
|
|
||||||
; Calculate the diffuse level (r0.x) and the shininess level (r0.y)
|
; Normalize lightVec[0]
|
||||||
; r0.x = max(0, -(lightVec * r1))
|
mov r5, lightVec[0]
|
||||||
; r0.y = max(0, (-lightHalfVec[i]) * r1) ^ 2
|
dp3 r6.x, r5, r5
|
||||||
dp3 r0.x, lightVec, r1
|
rsq r6.x, r6.x
|
||||||
add r0.x, zeros, -r0
|
mul r5, r6.xxxx, r5
|
||||||
dp3 r0.y, -lightHalfVec, r1
|
|
||||||
max r0, zeros, r0
|
|
||||||
mul r0.y, r0, r0
|
|
||||||
|
|
||||||
; Accumulate the vertex color in r1, initializing it to the emission color
|
; dot(normal, lightVec[0])
|
||||||
mov r1, mat_emi
|
dp3 r6.x, r3, r5
|
||||||
|
max r6.x, r6.x, r15.xxxx
|
||||||
|
|
||||||
; r1 += specularColor * lightClr * shininessLevel
|
; Normalize lightVec[1]
|
||||||
mul r2, lightClr, r0.yyyy
|
mov r7, lightVec[1]
|
||||||
mad r1, r2, mat_spe, r1
|
dp3 r8.x, r7, r7
|
||||||
|
rsq r8.x, r8.x
|
||||||
|
mul r7, r8.xxxx, r7
|
||||||
|
|
||||||
; r1 += diffuseColor * lightClr * diffuseLevel
|
; dot(normal, lightVec[1])
|
||||||
mul r2, lightClr, r0.xxxx
|
dp3 r6.y, r3, r7
|
||||||
mad r1, r2, mat_dif, r1
|
max r6.y, r6.y, r15.xxxx
|
||||||
|
|
||||||
; r1 += ambientColor * lightClr
|
; Load lightClr
|
||||||
mov r2, lightClr
|
mov r8, lightClr[2] ; ambient
|
||||||
mad r1, r2, mat_amb, r1
|
mov r9, lightClr[0] ; point
|
||||||
|
mov r10, lightClr[1] ; directional
|
||||||
|
|
||||||
; outclr = clamp r1 to [0,1]
|
; diffuse = ambient + (lightClr[0] * dot0) + (lightClr[1] * dot1)
|
||||||
min outclr, ones, r1
|
mul r11, r9, r6.xxxx
|
||||||
|
add r8, r8, r11
|
||||||
|
mul r11, r10, r6.yyyy
|
||||||
|
add r8, r8, r11 ; r8 = diffuse
|
||||||
|
|
||||||
|
; Check if shininess > 0
|
||||||
|
mov r12, shininess
|
||||||
|
slt r13.x, r15.x, r12.x
|
||||||
|
|
||||||
|
; viewVec = normalize(-position.xyz)
|
||||||
|
mov r14.xyz, r1.xyz
|
||||||
|
mul r14.xyz, r14.xyz, r15.zzz
|
||||||
|
dp3 r4.x, r14, r14
|
||||||
|
rsq r4.x, r4.x
|
||||||
|
mul r14, r4.xxxx, r14
|
||||||
|
|
||||||
|
; H = normalize(view + lightVec[1])
|
||||||
|
add r11, r14, r7
|
||||||
|
dp3 r4.x, r11, r11
|
||||||
|
rsq r4.x, r4.x
|
||||||
|
mul r11, r4.xxxx, r11
|
||||||
|
|
||||||
|
; dot(normal, H)
|
||||||
|
dp3 r4.x, r3, r11
|
||||||
|
max r4.x, r4.x, r15.x
|
||||||
|
|
||||||
|
; Approximate pow(dotNH, 10) by repeated multiplication
|
||||||
|
mul r5.x, r4.x, r4.x ; dotNH^2
|
||||||
|
mul r5.x, r5.x, r5.x ; dotNH^4
|
||||||
|
mul r5.x, r5.x, r5.x ; dotNH^8
|
||||||
|
mul r4.x, r5.x, r4.x ; dotNH^9
|
||||||
|
mul r4.x, r4.x, r4.x ; dotNH^10
|
||||||
|
|
||||||
|
; Multiply by shininess > 0 flag
|
||||||
|
mul r4.x, r4.x, r13.x
|
||||||
|
|
||||||
|
; specular = lightClr[1] * spec
|
||||||
|
mul r5, r10, r4.xxxx
|
||||||
|
|
||||||
|
; final = diffuse * meshColor + specular * lightClr[1]
|
||||||
|
mov r9, meshColor
|
||||||
|
mul r6, r8, r9 ; diffuse * meshColor
|
||||||
|
add r7.xyz, r6.xyz, r5.xyz ; add specular (already multiplied by lightClr)
|
||||||
|
min r7.xyz, r7.xyz, r15.yyyy
|
||||||
|
|
||||||
|
mov outclr.xyz, r7.xyz
|
||||||
|
mov outclr.w, meshColor.w
|
||||||
|
|
||||||
; We're finished
|
|
||||||
end
|
end
|
||||||
.end
|
.end
|
||||||
|
|||||||
@ -221,7 +221,7 @@ void DirectX9Renderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc)
|
|||||||
halDesc->dcmColorModel = D3DCOLORMODEL::RGB;
|
halDesc->dcmColorModel = D3DCOLORMODEL::RGB;
|
||||||
halDesc->dwFlags = D3DDD_DEVICEZBUFFERBITDEPTH;
|
halDesc->dwFlags = D3DDD_DEVICEZBUFFERBITDEPTH;
|
||||||
halDesc->dwDeviceZBufferBitDepth = DDBD_24;
|
halDesc->dwDeviceZBufferBitDepth = DDBD_24;
|
||||||
helDesc->dwDeviceRenderBitDepth = DDBD_32;
|
halDesc->dwDeviceRenderBitDepth = DDBD_32;
|
||||||
halDesc->dpcTriCaps.dwTextureCaps = D3DPTEXTURECAPS_PERSPECTIVE;
|
halDesc->dpcTriCaps.dwTextureCaps = D3DPTEXTURECAPS_PERSPECTIVE;
|
||||||
halDesc->dpcTriCaps.dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND;
|
halDesc->dpcTriCaps.dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND;
|
||||||
halDesc->dpcTriCaps.dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR;
|
halDesc->dpcTriCaps.dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR;
|
||||||
|
|||||||
@ -314,7 +314,7 @@ void OpenGL1Renderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc)
|
|||||||
halDesc->dcmColorModel = D3DCOLORMODEL::RGB;
|
halDesc->dcmColorModel = D3DCOLORMODEL::RGB;
|
||||||
halDesc->dwFlags = D3DDD_DEVICEZBUFFERBITDEPTH;
|
halDesc->dwFlags = D3DDD_DEVICEZBUFFERBITDEPTH;
|
||||||
halDesc->dwDeviceZBufferBitDepth = DDBD_24;
|
halDesc->dwDeviceZBufferBitDepth = DDBD_24;
|
||||||
helDesc->dwDeviceRenderBitDepth = DDBD_32;
|
halDesc->dwDeviceRenderBitDepth = DDBD_32;
|
||||||
halDesc->dpcTriCaps.dwTextureCaps = D3DPTEXTURECAPS_PERSPECTIVE;
|
halDesc->dpcTriCaps.dwTextureCaps = D3DPTEXTURECAPS_PERSPECTIVE;
|
||||||
halDesc->dpcTriCaps.dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND;
|
halDesc->dpcTriCaps.dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND;
|
||||||
halDesc->dpcTriCaps.dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR;
|
halDesc->dpcTriCaps.dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR;
|
||||||
|
|||||||
@ -421,7 +421,7 @@ void OpenGLES2Renderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc)
|
|||||||
halDesc->dwDeviceZBufferBitDepth |= DDBD_32;
|
halDesc->dwDeviceZBufferBitDepth |= DDBD_32;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
helDesc->dwDeviceRenderBitDepth = DDBD_32;
|
halDesc->dwDeviceRenderBitDepth = DDBD_32;
|
||||||
halDesc->dpcTriCaps.dwTextureCaps = D3DPTEXTURECAPS_PERSPECTIVE;
|
halDesc->dpcTriCaps.dwTextureCaps = D3DPTEXTURECAPS_PERSPECTIVE;
|
||||||
halDesc->dpcTriCaps.dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND;
|
halDesc->dpcTriCaps.dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND;
|
||||||
halDesc->dpcTriCaps.dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR;
|
halDesc->dpcTriCaps.dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR;
|
||||||
|
|||||||
@ -164,7 +164,7 @@ HRESULT Direct3DRMImpl::CreateDeviceFromSurface(
|
|||||||
#endif
|
#endif
|
||||||
#ifdef USE_CITRO3D
|
#ifdef USE_CITRO3D
|
||||||
else if (SDL_memcmp(&guid, &Citro3D_GUID, sizeof(GUID)) == 0) {
|
else if (SDL_memcmp(&guid, &Citro3D_GUID, sizeof(GUID)) == 0) {
|
||||||
DDRenderer = Citro3DRenderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight);
|
DDRenderer = new Citro3DRenderer(DDSDesc.dwWidth, DDSDesc.dwHeight);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|||||||
@ -155,6 +155,10 @@ void Direct3DRMDevice2Impl::Resize()
|
|||||||
{
|
{
|
||||||
int width, height;
|
int width, height;
|
||||||
SDL_GetWindowSizeInPixels(DDWindow, &width, &height);
|
SDL_GetWindowSizeInPixels(DDWindow, &width, &height);
|
||||||
|
#ifdef USE_CITRO3D
|
||||||
|
width = 320; // We are on the lower screen
|
||||||
|
height = 240;
|
||||||
|
#endif
|
||||||
m_viewportTransform = CalculateViewportTransform(m_virtualWidth, m_virtualHeight, width, height);
|
m_viewportTransform = CalculateViewportTransform(m_virtualWidth, m_virtualHeight, width, height);
|
||||||
m_renderer->Resize(width, height, m_viewportTransform);
|
m_renderer->Resize(width, height, m_viewportTransform);
|
||||||
for (int i = 0; i < m_viewports->GetSize(); i++) {
|
for (int i = 0; i < m_viewports->GetSize(); i++) {
|
||||||
|
|||||||
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <cinttypes>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@ -78,7 +79,7 @@ HRESULT DirectDrawImpl::CreateSurface(
|
|||||||
if ((lpDDSurfaceDesc->dwFlags & DDSD_ZBUFFERBITDEPTH) != DDSD_ZBUFFERBITDEPTH) {
|
if ((lpDDSurfaceDesc->dwFlags & DDSD_ZBUFFERBITDEPTH) != DDSD_ZBUFFERBITDEPTH) {
|
||||||
return DDERR_INVALIDPARAMS;
|
return DDERR_INVALIDPARAMS;
|
||||||
}
|
}
|
||||||
SDL_Log("Todo: Set %dbit Z-Buffer", lpDDSurfaceDesc->dwZBufferBitDepth);
|
SDL_Log("Todo: Set %" PRIu32 "bit Z-Buffer", lpDDSurfaceDesc->dwZBufferBitDepth);
|
||||||
*lplpDDSurface = static_cast<IDirectDrawSurface*>(new DummySurfaceImpl);
|
*lplpDDSurface = static_cast<IDirectDrawSurface*>(new DummySurfaceImpl);
|
||||||
return DD_OK;
|
return DD_OK;
|
||||||
}
|
}
|
||||||
@ -349,7 +350,7 @@ HRESULT DirectDrawImpl::CreateDevice(
|
|||||||
#endif
|
#endif
|
||||||
#ifdef USE_CITRO3D
|
#ifdef USE_CITRO3D
|
||||||
else if (SDL_memcmp(&guid, &Citro3D_GUID, sizeof(GUID)) == 0) {
|
else if (SDL_memcmp(&guid, &Citro3D_GUID, sizeof(GUID)) == 0) {
|
||||||
DDRenderer = Citro3DRenderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight);
|
DDRenderer = new Citro3DRenderer(DDSDesc.dwWidth, DDSDesc.dwHeight);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|||||||
@ -1,28 +1,30 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "SDL3/SDL_log.h"
|
|
||||||
#include "d3drmrenderer.h"
|
#include "d3drmrenderer.h"
|
||||||
#include "d3drmtexture_impl.h"
|
|
||||||
#include "ddraw_impl.h"
|
|
||||||
|
|
||||||
#include <citro3d.h>
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
#include <c3d/texture.h>
|
#include <citro3d.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
DEFINE_GUID(Citro3D_GUID, 0x682656F3, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07);
|
DEFINE_GUID(Citro3D_GUID, 0x682656F3, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3D, 0x53);
|
||||||
|
|
||||||
struct C3DTextureCacheEntry {
|
struct C3DTextureCacheEntry {
|
||||||
IDirect3DRMTexture* texture;
|
IDirect3DRMTexture* texture;
|
||||||
Uint32 version;
|
Uint32 version;
|
||||||
C3D_Tex* c3dTex;
|
C3D_Tex c3dTex;
|
||||||
|
uint16_t width;
|
||||||
|
uint16_t height;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct C3DMeshCacheEntry {
|
||||||
|
const MeshGroup* meshGroup = nullptr;
|
||||||
|
int version = 0;
|
||||||
|
void* vbo = nullptr;
|
||||||
|
int vertexCount = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Citro3DRenderer : public Direct3DRMRenderer {
|
class Citro3DRenderer : public Direct3DRMRenderer {
|
||||||
public:
|
public:
|
||||||
static Direct3DRMRenderer* Create(DWORD width, DWORD height);
|
|
||||||
|
|
||||||
// constructor parameters not finalized
|
|
||||||
Citro3DRenderer(DWORD width, DWORD height);
|
Citro3DRenderer(DWORD width, DWORD height);
|
||||||
~Citro3DRenderer() override;
|
~Citro3DRenderer() override;
|
||||||
|
|
||||||
@ -49,31 +51,38 @@ class Citro3DRenderer : public Direct3DRMRenderer {
|
|||||||
void Flip() override;
|
void Flip() override;
|
||||||
void Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect) override;
|
void Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect) override;
|
||||||
void Download(SDL_Surface* target) override;
|
void Download(SDL_Surface* target) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture);
|
void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture);
|
||||||
|
void AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh);
|
||||||
|
void StartFrame();
|
||||||
|
|
||||||
D3DRMMATRIX4D m_projection;
|
D3DRMMATRIX4D m_projection;
|
||||||
C3D_Mtx m_projectionMatrix;
|
|
||||||
SDL_Surface* m_renderedImage;
|
SDL_Surface* m_renderedImage;
|
||||||
C3D_RenderTarget* m_renderTarget;
|
C3D_RenderTarget* m_renderTarget;
|
||||||
int m_projectionShaderUniformLocation;
|
|
||||||
std::vector<C3DTextureCacheEntry> m_textures;
|
std::vector<C3DTextureCacheEntry> m_textures;
|
||||||
|
std::vector<C3DMeshCacheEntry> m_meshs;
|
||||||
// TODO: All these flags can likely be cleaned up
|
ViewportTransform m_viewportTransform;
|
||||||
bool m_flipVertFlag;
|
std::vector<SceneLight> m_lights;
|
||||||
bool m_outTiledFlag;
|
|
||||||
bool m_rawCopyFlag;
|
|
||||||
GX_TRANSFER_FORMAT m_transferInputFormatFlag;
|
|
||||||
GX_TRANSFER_FORMAT m_transferOutputFormatFlag;
|
|
||||||
GX_TRANSFER_SCALE m_transferScaleFlag;
|
|
||||||
u32 m_transferFlags;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline static void Citro3DRenderer_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx)
|
inline static void Citro3DRenderer_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx)
|
||||||
{
|
{
|
||||||
SDL_Log("Hello, enuming device");
|
GUID guid = Citro3D_GUID;
|
||||||
Direct3DRMRenderer* device = Citro3DRenderer::Create(400, 240);
|
char* deviceNameDup = SDL_strdup("Citro3D");
|
||||||
if (device) {
|
char* deviceDescDup = SDL_strdup("Miniwin driver");
|
||||||
EnumDevice(cb, ctx, device, Citro3D_GUID);
|
D3DDEVICEDESC halDesc = {};
|
||||||
delete device;
|
halDesc.dcmColorModel = D3DCOLOR_RGB;
|
||||||
}
|
halDesc.dwFlags = D3DDD_DEVICEZBUFFERBITDEPTH;
|
||||||
|
halDesc.dwDeviceZBufferBitDepth = DDBD_24;
|
||||||
|
halDesc.dwDeviceRenderBitDepth = DDBD_32;
|
||||||
|
halDesc.dpcTriCaps.dwTextureCaps = D3DPTEXTURECAPS_PERSPECTIVE;
|
||||||
|
halDesc.dpcTriCaps.dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND;
|
||||||
|
halDesc.dpcTriCaps.dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR;
|
||||||
|
D3DDEVICEDESC helDesc = {};
|
||||||
|
|
||||||
|
cb(&guid, deviceNameDup, deviceDescDup, &halDesc, &helDesc, ctx);
|
||||||
|
|
||||||
|
SDL_free(deviceDescDup);
|
||||||
|
SDL_free(deviceNameDup);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user