mirror of
https://github.com/isledecomp/isle-portable.git
synced 2026-02-03 12:31:15 +00:00
Merge branch 'flatpak' of github.com:iAmSomeone2/isle-portable into flatpak
This commit is contained in:
commit
2d5bf86ca4
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@ -66,7 +66,7 @@ jobs:
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y \
|
||||
libx11-dev libxext-dev libxrandr-dev libxrender-dev libxfixes-dev libxi-dev libxinerama-dev \
|
||||
libxcursor-dev libwayland-dev libxkbcommon-dev wayland-protocols libgl1-mesa-dev libglew-dev qt6-base-dev \
|
||||
libxcursor-dev libwayland-dev libxkbcommon-dev wayland-protocols libgl1-mesa-dev qt6-base-dev \
|
||||
libasound2-dev
|
||||
|
||||
- name: Install macOS dependencies (brew)
|
||||
|
||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@ -48,7 +48,7 @@ jobs:
|
||||
sudo apt update
|
||||
sudo apt install -y \
|
||||
libx11-dev libxext-dev libxrandr-dev libxrender-dev libxfixes-dev libxi-dev libxinerama-dev \
|
||||
libxcursor-dev libwayland-dev libxkbcommon-dev wayland-protocols libgl1-mesa-dev libglew-dev qt6-base-dev \
|
||||
libxcursor-dev libwayland-dev libxkbcommon-dev wayland-protocols libgl1-mesa-dev qt6-base-dev \
|
||||
libasound2-dev
|
||||
|
||||
- name: Install macOS dependencies (brew)
|
||||
|
||||
@ -525,7 +525,7 @@ endif()
|
||||
if (ISLE_BUILD_CONFIG)
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Widgets)
|
||||
qt_standard_project_setup()
|
||||
qt_add_executable(config WIN32
|
||||
qt_add_executable(isle-config WIN32
|
||||
LEGO1/mxdirectx/mxdirectxinfo.cpp
|
||||
LEGO1/mxdirectx/legodxinfo.cpp
|
||||
CONFIG/config.cpp
|
||||
@ -535,22 +535,22 @@ if (ISLE_BUILD_CONFIG)
|
||||
CONFIG/res/config.rc
|
||||
CONFIG/res/config.qrc
|
||||
)
|
||||
target_link_libraries(config PRIVATE Qt6::Core Qt6::Widgets)
|
||||
set_property(TARGET config PROPERTY AUTOMOC ON)
|
||||
set_property(TARGET config PROPERTY AUTORCC ON)
|
||||
set_property(TARGET config PROPERTY AUTOUIC ON)
|
||||
set_property(TARGET config PROPERTY AUTOUIC_SEARCH_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/CONFIG/res")
|
||||
list(APPEND isle_targets config)
|
||||
target_compile_definitions(config PRIVATE _AFXDLL MXDIRECTX_FOR_CONFIG)
|
||||
target_include_directories(config PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/LEGO1")
|
||||
target_include_directories(config PUBLIC "$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/util>")
|
||||
target_link_libraries(isle-config PRIVATE Qt6::Core Qt6::Widgets)
|
||||
set_property(TARGET isle-config PROPERTY AUTOMOC ON)
|
||||
set_property(TARGET isle-config PROPERTY AUTORCC ON)
|
||||
set_property(TARGET isle-config PROPERTY AUTOUIC ON)
|
||||
set_property(TARGET isle-config PROPERTY AUTOUIC_SEARCH_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/CONFIG/res")
|
||||
list(APPEND isle_targets isle-config)
|
||||
target_compile_definitions(isle-config PRIVATE _AFXDLL MXDIRECTX_FOR_CONFIG)
|
||||
target_include_directories(isle-config PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/LEGO1")
|
||||
target_include_directories(isle-config PUBLIC "$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/util>")
|
||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 14)
|
||||
target_link_libraries(config PRIVATE DirectX5::DirectX5)
|
||||
target_link_libraries(isle-config PRIVATE DirectX5::DirectX5)
|
||||
endif()
|
||||
target_compile_definitions(config PRIVATE DIRECT3D_VERSION=0x500)
|
||||
target_link_libraries(config PRIVATE SDL3::SDL3 Isle::iniparser)
|
||||
target_compile_definitions(isle-config PRIVATE DIRECT3D_VERSION=0x500)
|
||||
target_link_libraries(isle-config PRIVATE SDL3::SDL3 Isle::iniparser)
|
||||
if (NOT ISLE_MINIWIN)
|
||||
target_link_libraries(config PRIVATE ddraw dxguid)
|
||||
target_link_libraries(isle-config PRIVATE ddraw dxguid)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@ -564,8 +564,8 @@ if (MSVC)
|
||||
if (TARGET isle)
|
||||
target_compile_definitions(isle PRIVATE "_CRT_SECURE_NO_WARNINGS")
|
||||
endif()
|
||||
if (TARGET config)
|
||||
target_compile_definitions(config PRIVATE "_CRT_SECURE_NO_WARNINGS")
|
||||
if (TARGET isle-config)
|
||||
target_compile_definitions(isle-config PRIVATE "_CRT_SECURE_NO_WARNINGS")
|
||||
endif()
|
||||
endif()
|
||||
# Visual Studio 2017 version 15.7 needs "/Zc:__cplusplus" for __cplusplus
|
||||
@ -574,8 +574,8 @@ if (MSVC)
|
||||
if (TARGET isle)
|
||||
target_compile_options(isle PRIVATE "-Zc:__cplusplus")
|
||||
endif()
|
||||
if (TARGET config)
|
||||
target_compile_options(config PRIVATE "-Zc:__cplusplus")
|
||||
if (TARGET isle-config)
|
||||
target_compile_options(isle-config PRIVATE "-Zc:__cplusplus")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
@ -633,7 +633,7 @@ install(TARGETS isle ${install_extra_targets}
|
||||
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||
)
|
||||
if (ISLE_BUILD_CONFIG)
|
||||
install(TARGETS config
|
||||
install(TARGETS isle-config
|
||||
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
|
||||
)
|
||||
endif()
|
||||
|
||||
@ -11,6 +11,8 @@
|
||||
#include "res/resource.h"
|
||||
|
||||
#include <QKeyEvent>
|
||||
#include <QMessageBox>
|
||||
#include <QProcess>
|
||||
#include <mxdirectx/legodxinfo.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->sound3DCheckBox, &QCheckBox::toggled, this, &CMainDialog::OnCheckbox3DSound);
|
||||
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->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->cdPathOpen, &QPushButton::clicked, this, &CMainDialog::SelectCDPathDialog);
|
||||
connect(m_ui->mediaPathOpen, &QPushButton::clicked, this, &CMainDialog::SelectMediaPathDialog);
|
||||
connect(m_ui->dataPathOpen, &QPushButton::clicked, this, &CMainDialog::SelectDataPathDialog);
|
||||
connect(m_ui->savePathOpen, &QPushButton::clicked, this, &CMainDialog::SelectSavePathDialog);
|
||||
|
||||
connect(m_ui->diskPath, &QLineEdit::textEdited, this, &CMainDialog::DiskPathEdited);
|
||||
connect(m_ui->cdPath, &QLineEdit::textEdited, this, &CMainDialog::CDPathEdited);
|
||||
connect(m_ui->mediaPath, &QLineEdit::textEdited, this, &CMainDialog::MediaPathEdited);
|
||||
connect(m_ui->savePath, &QLineEdit::textEdited, this, &CMainDialog::SavePathEdited);
|
||||
connect(m_ui->dataPath, &QLineEdit::editingFinished, this, &CMainDialog::DataPathEdited);
|
||||
connect(m_ui->savePath, &QLineEdit::editingFinished, this, &CMainDialog::SavePathEdited);
|
||||
|
||||
connect(m_ui->maxLoDSlider, &QSlider::valueChanged, this, &CMainDialog::MaxLoDChanged);
|
||||
connect(m_ui->maxActorsSlider, &QSlider::valueChanged, this, &CMainDialog::MaxActorsChanged);
|
||||
@ -158,6 +158,30 @@ void CMainDialog::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
|
||||
void CMainDialog::UpdateInterface()
|
||||
{
|
||||
@ -187,9 +211,8 @@ void CMainDialog::UpdateInterface()
|
||||
}
|
||||
m_ui->joystickCheckBox->setChecked(currentConfigApp->m_use_joystick);
|
||||
m_ui->musicCheckBox->setChecked(currentConfigApp->m_music);
|
||||
m_ui->diskPath->setText(QString::fromStdString(currentConfigApp->m_base_path));
|
||||
m_ui->cdPath->setText(QString::fromStdString(currentConfigApp->m_cd_path));
|
||||
m_ui->mediaPath->setText(QString::fromStdString(currentConfigApp->m_media_path));
|
||||
m_ui->fullscreenCheckBox->setChecked(currentConfigApp->m_full_screen);
|
||||
m_ui->dataPath->setText(QString::fromStdString(currentConfigApp->m_cd_path));
|
||||
m_ui->savePath->setText(QString::fromStdString(currentConfigApp->m_save_path));
|
||||
}
|
||||
|
||||
@ -266,54 +289,33 @@ void CMainDialog::OnCheckboxMusic(bool checked)
|
||||
UpdateInterface();
|
||||
}
|
||||
|
||||
void CMainDialog::SelectDiskPathDialog()
|
||||
void CMainDialog::OnCheckboxFullscreen(bool checked)
|
||||
{
|
||||
QString disk_path = QString::fromStdString(currentConfigApp->m_base_path);
|
||||
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;
|
||||
UpdateInterface();
|
||||
}
|
||||
currentConfigApp->m_full_screen = checked;
|
||||
m_modified = true;
|
||||
UpdateInterface();
|
||||
}
|
||||
|
||||
void CMainDialog::SelectCDPathDialog()
|
||||
void CMainDialog::SelectDataPathDialog()
|
||||
{
|
||||
QString cd_path = QString::fromStdString(currentConfigApp->m_cd_path);
|
||||
cd_path = QFileDialog::getExistingDirectory(
|
||||
QString data_path = QString::fromStdString(currentConfigApp->m_cd_path);
|
||||
data_path = QFileDialog::getExistingDirectory(
|
||||
this,
|
||||
tr("Open Directory"),
|
||||
cd_path,
|
||||
data_path,
|
||||
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks
|
||||
);
|
||||
|
||||
if (cd_path.toStdString() != "") {
|
||||
currentConfigApp->m_cd_path = cd_path.toStdString();
|
||||
m_modified = true;
|
||||
UpdateInterface();
|
||||
}
|
||||
}
|
||||
QDir data_dir = QDir(data_path);
|
||||
|
||||
void CMainDialog::SelectMediaPathDialog()
|
||||
{
|
||||
QString media_path = QString::fromStdString(currentConfigApp->m_media_path);
|
||||
media_path = QFileDialog::getExistingDirectory(
|
||||
this,
|
||||
tr("Open Directory"),
|
||||
media_path,
|
||||
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks
|
||||
);
|
||||
if (media_path.toStdString() != "") {
|
||||
currentConfigApp->m_media_path = media_path.toStdString();
|
||||
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;
|
||||
UpdateInterface();
|
||||
}
|
||||
UpdateInterface();
|
||||
}
|
||||
|
||||
void CMainDialog::SelectSavePathDialog()
|
||||
@ -326,38 +328,39 @@ void CMainDialog::SelectSavePathDialog()
|
||||
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks
|
||||
);
|
||||
|
||||
if (save_path.toStdString() != "") {
|
||||
currentConfigApp->m_save_path = save_path.toStdString();
|
||||
QDir save_dir = QDir(save_path);
|
||||
|
||||
if (save_dir.exists()) {
|
||||
currentConfigApp->m_save_path = save_dir.absolutePath().toStdString();
|
||||
m_modified = true;
|
||||
UpdateInterface();
|
||||
}
|
||||
}
|
||||
|
||||
void CMainDialog::DiskPathEdited(const QString& text)
|
||||
{
|
||||
currentConfigApp->m_base_path = text.toStdString();
|
||||
m_modified = true;
|
||||
UpdateInterface();
|
||||
}
|
||||
|
||||
void CMainDialog::CDPathEdited(const QString& text)
|
||||
void CMainDialog::DataPathEdited()
|
||||
{
|
||||
currentConfigApp->m_cd_path = text.toStdString();
|
||||
m_modified = true;
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
currentConfigApp->m_save_path = text.toStdString();
|
||||
m_modified = true;
|
||||
QDir save_dir = QDir(m_ui->savePath->text());
|
||||
|
||||
if (save_dir.exists()) {
|
||||
currentConfigApp->m_save_path = save_dir.absolutePath().toStdString();
|
||||
m_modified = true;
|
||||
}
|
||||
UpdateInterface();
|
||||
}
|
||||
|
||||
|
||||
@ -42,16 +42,14 @@ private slots:
|
||||
void OnRadiobuttonTextureHighQuality(bool checked);
|
||||
void OnCheckboxJoystick(bool checked);
|
||||
void OnCheckboxMusic(bool checked);
|
||||
void OnCheckboxFullscreen(bool checked);
|
||||
void accept() override;
|
||||
void reject() override;
|
||||
void SelectDiskPathDialog();
|
||||
void SelectCDPathDialog();
|
||||
void SelectMediaPathDialog();
|
||||
void launch();
|
||||
void SelectDataPathDialog();
|
||||
void SelectSavePathDialog();
|
||||
void DiskPathEdited(const QString& text);
|
||||
void CDPathEdited(const QString& text);
|
||||
void MediaPathEdited(const QString& text);
|
||||
void SavePathEdited(const QString& text);
|
||||
void DataPathEdited();
|
||||
void SavePathEdited();
|
||||
void MaxLoDChanged(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_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_display_bit_depth = iniparser_getint(dict, "isle:Display Bit Depth", -1);
|
||||
m_flip_surfaces = iniparser_getboolean(dict, "isle:Flip Surfaces", m_flip_surfaces);
|
||||
@ -166,10 +165,6 @@ bool CConfigApp::ValidateSettings()
|
||||
{
|
||||
BOOL is_modified = FALSE;
|
||||
|
||||
if (!IsPrimaryDriver() && !m_full_screen) {
|
||||
m_full_screen = TRUE;
|
||||
is_modified = TRUE;
|
||||
}
|
||||
if (IsDeviceInBasicRGBMode()) {
|
||||
if (m_3d_video_ram) {
|
||||
m_3d_video_ram = FALSE;
|
||||
@ -203,10 +198,6 @@ bool CConfigApp::ValidateSettings()
|
||||
m_3d_video_ram = 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)) {
|
||||
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: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());
|
||||
|
||||
SetIniInt(dict, "isle:Display Bit Depth", m_display_bit_depth);
|
||||
|
||||
@ -77,7 +77,6 @@ class CConfigApp {
|
||||
std::string m_iniPath;
|
||||
std::string m_base_path;
|
||||
std::string m_cd_path;
|
||||
std::string m_media_path;
|
||||
std::string m_save_path;
|
||||
float m_max_lod;
|
||||
int m_max_actors;
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>575</width>
|
||||
<height>650</height>
|
||||
<height>600</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@ -44,6 +44,9 @@
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Jaws.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
@ -76,13 +79,7 @@
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="cdPath"/>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="mediaPath"/>
|
||||
</item>
|
||||
<item row="7" column="2">
|
||||
<item row="5" column="2">
|
||||
<widget class="QPushButton" name="savePathOpen">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
@ -101,68 +98,8 @@
|
||||
</property>
|
||||
</widget>
|
||||
</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">
|
||||
<widget class="QPushButton" name="diskPathOpen">
|
||||
<widget class="QPushButton" name="dataPathOpen">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
@ -180,26 +117,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" 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">
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="savePathLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
@ -218,8 +136,22 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="mediaPathLabel">
|
||||
<item row="0" column="1">
|
||||
<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">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
@ -227,7 +159,7 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Media Path:</string>
|
||||
<string>Data Path:</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
@ -237,9 +169,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QLineEdit" name="savePath"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@ -266,6 +195,9 @@
|
||||
<height>120</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Set 3D model detail level.</string>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Island Model Quality</string>
|
||||
</property>
|
||||
@ -345,6 +277,9 @@
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QGroupBox" name="textureQualityGroup">
|
||||
<property name="toolTip">
|
||||
<string>Set texture detail level.</string>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Island Texture Quality</string>
|
||||
</property>
|
||||
@ -422,16 +357,13 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="musicJoystickWidget" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="checkboxWidget" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="sound3DCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>Enable 3D positional audio effects.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>3D Sound</string>
|
||||
</property>
|
||||
@ -439,6 +371,9 @@
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="musicCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>Enable in-game background music.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Music</string>
|
||||
</property>
|
||||
@ -446,11 +381,24 @@
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="joystickCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>Enable joystick and gamepad support for LEGO Island.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use Joystick</string>
|
||||
</property>
|
||||
</widget>
|
||||
</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>
|
||||
</widget>
|
||||
</item>
|
||||
@ -462,6 +410,9 @@
|
||||
<height>225</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>3D graphics device used to render the game.</string>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string/>
|
||||
</property>
|
||||
@ -557,8 +508,11 @@
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="okButton">
|
||||
<property name="toolTip">
|
||||
<string>Save configuration and close the config tool.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>OK</string>
|
||||
<string>Save and Exit</string>
|
||||
</property>
|
||||
<property name="default">
|
||||
<bool>true</bool>
|
||||
@ -566,9 +520,22 @@
|
||||
</widget>
|
||||
</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">
|
||||
<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>
|
||||
</widget>
|
||||
</item>
|
||||
@ -581,12 +548,8 @@
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>diskPath</tabstop>
|
||||
<tabstop>diskPathOpen</tabstop>
|
||||
<tabstop>cdPath</tabstop>
|
||||
<tabstop>cdPathOpen</tabstop>
|
||||
<tabstop>mediaPath</tabstop>
|
||||
<tabstop>mediaPathOpen</tabstop>
|
||||
<tabstop>dataPath</tabstop>
|
||||
<tabstop>dataPathOpen</tabstop>
|
||||
<tabstop>savePath</tabstop>
|
||||
<tabstop>savePathOpen</tabstop>
|
||||
<tabstop>textureQualityFastRadioButton</tabstop>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
diff --git a/src/lib/libwasmfs_fetch.js b/src/lib/libwasmfs_fetch.js
|
||||
index e8c9f7e21..5c3a3dfbe 100644
|
||||
index e8c9f7e21..caf1971d2 100644
|
||||
--- a/src/lib/libwasmfs_fetch.js
|
||||
+++ b/src/lib/libwasmfs_fetch.js
|
||||
@@ -38,36 +38,7 @@ addToLibrary({
|
||||
@ -49,7 +49,7 @@ index e8c9f7e21..5c3a3dfbe 100644
|
||||
allPresent = false;
|
||||
break;
|
||||
}
|
||||
@@ -90,16 +61,36 @@ addToLibrary({
|
||||
@@ -90,16 +61,37 @@ addToLibrary({
|
||||
// one request for all the chunks we need, rather than one
|
||||
// request per chunk.
|
||||
var start = firstChunk * chunkSize;
|
||||
@ -66,8 +66,10 @@ index e8c9f7e21..5c3a3dfbe 100644
|
||||
if (!response.ok) {
|
||||
throw response;
|
||||
}
|
||||
- var bytes = await response['bytes']();
|
||||
+
|
||||
var bytes = await response['bytes']();
|
||||
+ const buffer = await response.arrayBuffer();
|
||||
+ const bytes = new Uint8Array(buffer);
|
||||
+ if (!(file in wasmFS$JSMemoryRanges)) {
|
||||
+ var size = Math.max(
|
||||
+ parseInt(response.headers.get('Content-Range').split('/')[1], 10),
|
||||
@ -87,7 +89,21 @@ index e8c9f7e21..5c3a3dfbe 100644
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
@@ -164,6 +155,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;
|
||||
},
|
||||
};
|
||||
|
||||
@ -96,11 +96,7 @@ IsleApp::IsleApp()
|
||||
m_cdPath = NULL;
|
||||
m_deviceId = NULL;
|
||||
m_savePath = NULL;
|
||||
#ifdef __EMSCRIPTEN__
|
||||
m_fullScreen = FALSE;
|
||||
#else
|
||||
m_fullScreen = TRUE;
|
||||
#endif
|
||||
m_flipSurfaces = FALSE;
|
||||
m_backBuffersInVram = TRUE;
|
||||
m_using8bit = FALSE;
|
||||
@ -140,6 +136,7 @@ IsleApp::IsleApp()
|
||||
m_iniPath = NULL;
|
||||
m_maxLod = RealtimeView::GetUserMaxLOD();
|
||||
m_maxAllowedExtras = m_islandQuality <= 1 ? 10 : 20;
|
||||
m_transitionType = MxTransitionManager::e_mosaic;
|
||||
}
|
||||
|
||||
// FUNCTION: ISLE 0x4011a0
|
||||
@ -394,6 +391,7 @@ SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event)
|
||||
#endif
|
||||
|
||||
switch (event->type) {
|
||||
case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
|
||||
case SDL_EVENT_MOUSE_MOTION:
|
||||
case SDL_EVENT_MOUSE_BUTTON_DOWN:
|
||||
case SDL_EVENT_MOUSE_BUTTON_UP:
|
||||
@ -658,6 +656,8 @@ MxResult IsleApp::SetupWindow()
|
||||
SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING, WINDOW_TITLE);
|
||||
#ifdef MINIWIN
|
||||
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_OPENGL_BOOLEAN, true);
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
|
||||
#endif
|
||||
|
||||
window = SDL_CreateWindowWithProperties(props);
|
||||
@ -701,6 +701,7 @@ MxResult IsleApp::SetupWindow()
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
DetectGameVersion();
|
||||
GameState()->SerializePlayersInfo(LegoStorage::c_read);
|
||||
GameState()->SerializeScoreHistory(LegoStorage::c_read);
|
||||
|
||||
@ -723,6 +724,7 @@ MxResult IsleApp::SetupWindow()
|
||||
LegoBuildingManager::configureLegoBuildingManager(m_islandQuality);
|
||||
LegoROI::configureLegoROI(iVar10);
|
||||
LegoAnimationManager::configureLegoAnimationManager(m_maxAllowedExtras);
|
||||
MxTransitionManager::configureMxTransitionManager(m_transitionType);
|
||||
RealtimeView::SetUserMaxLOD(m_maxLod);
|
||||
if (LegoOmni::GetInstance()) {
|
||||
if (LegoOmni::GetInstance()->GetInputManager()) {
|
||||
@ -821,6 +823,7 @@ bool IsleApp::LoadConfig()
|
||||
SDL_snprintf(buf, sizeof(buf), "%f", m_maxLod);
|
||||
iniparser_set(dict, "isle:Max LOD", buf);
|
||||
iniparser_set(dict, "isle:Max Allowed Extras", SDL_itoa(m_maxAllowedExtras, buf, 10));
|
||||
iniparser_set(dict, "isle:Transition Type", SDL_itoa(m_transitionType, buf, 10));
|
||||
|
||||
iniparser_dump_ini(dict, iniFP);
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "New config written at '%s'", iniConfig);
|
||||
@ -850,7 +853,13 @@ bool IsleApp::LoadConfig()
|
||||
strcpy(m_mediaPath, mediaPath);
|
||||
|
||||
m_flipSurfaces = iniparser_getboolean(dict, "isle:Flip Surfaces", m_flipSurfaces);
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
m_fullScreen = FALSE;
|
||||
#else
|
||||
m_fullScreen = iniparser_getboolean(dict, "isle:Full Screen", m_fullScreen);
|
||||
#endif
|
||||
|
||||
m_wideViewAngle = iniparser_getboolean(dict, "isle:Wide View Angle", m_wideViewAngle);
|
||||
m_use3dSound = iniparser_getboolean(dict, "isle:3DSound", m_use3dSound);
|
||||
m_useMusic = iniparser_getboolean(dict, "isle:Music", m_useMusic);
|
||||
@ -877,6 +886,8 @@ bool IsleApp::LoadConfig()
|
||||
m_islandTexture = iniparser_getint(dict, "isle:Island Texture", m_islandTexture);
|
||||
m_maxLod = iniparser_getdouble(dict, "isle:Max LOD", m_maxLod);
|
||||
m_maxAllowedExtras = iniparser_getint(dict, "isle:Max Allowed Extras", m_maxAllowedExtras);
|
||||
m_transitionType =
|
||||
(MxTransitionManager::TransitionType) iniparser_getint(dict, "isle:Transition Type", m_transitionType);
|
||||
|
||||
const char* deviceId = iniparser_getstring(dict, "isle:3D Device ID", NULL);
|
||||
if (deviceId != NULL) {
|
||||
@ -909,7 +920,7 @@ inline bool IsleApp::Tick()
|
||||
static MxLong g_lastFrameTime = 0;
|
||||
|
||||
// GLOBAL: ISLE 0x4101bc
|
||||
static MxS32 g_startupDelay = 200;
|
||||
static MxS32 g_startupDelay = 1;
|
||||
|
||||
if (IsleDebug_Paused() && IsleDebug_StepModeEnabled()) {
|
||||
IsleDebug_SetPaused(false);
|
||||
@ -1096,6 +1107,34 @@ MxResult IsleApp::VerifyFilesystem()
|
||||
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()
|
||||
{
|
||||
LegoVideoManager* videoManager = LegoOmni::GetInstance()->GetVideoManager();
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
|
||||
#include "lego1_export.h"
|
||||
#include "legoutils.h"
|
||||
#include "mxtransitionmanager.h"
|
||||
#include "mxtypes.h"
|
||||
#include "mxvideoparam.h"
|
||||
|
||||
@ -56,6 +57,7 @@ class IsleApp {
|
||||
|
||||
MxResult ParseArguments(int argc, char** argv);
|
||||
MxResult VerifyFilesystem();
|
||||
void DetectGameVersion();
|
||||
|
||||
private:
|
||||
char* m_hdPath; // 0x00
|
||||
@ -90,6 +92,7 @@ class IsleApp {
|
||||
char* m_iniPath;
|
||||
MxFloat m_maxLod;
|
||||
MxU32 m_maxAllowedExtras;
|
||||
MxTransitionManager::TransitionType m_transitionType;
|
||||
};
|
||||
|
||||
extern IsleApp* g_isle;
|
||||
|
||||
@ -11,6 +11,12 @@ class MxEndActionNotificationParam;
|
||||
// SIZE 0x24
|
||||
class AmbulanceMissionState : public LegoState {
|
||||
public:
|
||||
enum {
|
||||
e_ready = 0,
|
||||
e_enteredAmbulance = 1,
|
||||
e_prepareAmbulance = 2,
|
||||
};
|
||||
|
||||
AmbulanceMissionState();
|
||||
|
||||
// FUNCTION: LEGO1 0x10037440
|
||||
@ -125,18 +131,18 @@ class AmbulanceMissionState : public LegoState {
|
||||
// SYNTHETIC: LEGO1 0x100376c0
|
||||
// AmbulanceMissionState::`scalar deleting destructor'
|
||||
|
||||
undefined4 m_unk0x08; // 0x08
|
||||
MxLong m_startTime; // 0x0c
|
||||
MxS16 m_peScore; // 0x10
|
||||
MxS16 m_maScore; // 0x12
|
||||
MxS16 m_paScore; // 0x14
|
||||
MxS16 m_niScore; // 0x16
|
||||
MxS16 m_laScore; // 0x18
|
||||
MxS16 m_peHighScore; // 0x1a
|
||||
MxS16 m_maHighScore; // 0x1c
|
||||
MxS16 m_paHighScore; // 0x1e
|
||||
MxS16 m_niHighScore; // 0x20
|
||||
MxS16 m_laHighScore; // 0x22
|
||||
MxU32 m_state; // 0x08
|
||||
MxLong m_startTime; // 0x0c
|
||||
MxS16 m_peScore; // 0x10
|
||||
MxS16 m_maScore; // 0x12
|
||||
MxS16 m_paScore; // 0x14
|
||||
MxS16 m_niScore; // 0x16
|
||||
MxS16 m_laScore; // 0x18
|
||||
MxS16 m_peHighScore; // 0x1a
|
||||
MxS16 m_maHighScore; // 0x1c
|
||||
MxS16 m_paHighScore; // 0x1e
|
||||
MxS16 m_niHighScore; // 0x20
|
||||
MxS16 m_laHighScore; // 0x22
|
||||
};
|
||||
|
||||
// VTABLE: LEGO1 0x100d71a8
|
||||
@ -177,15 +183,21 @@ class Ambulance : public IslePathActor {
|
||||
virtual MxLong HandleEndAction(MxEndActionNotificationParam& p_param); // vtable+0xf4
|
||||
|
||||
void CreateState();
|
||||
void FUN_10036e60();
|
||||
void Init();
|
||||
void ActivateSceneActions();
|
||||
void StopActions();
|
||||
void FUN_10037250();
|
||||
void Reset();
|
||||
|
||||
// SYNTHETIC: LEGO1 0x10036130
|
||||
// Ambulance::`scalar deleting destructor'
|
||||
|
||||
private:
|
||||
enum {
|
||||
e_none = 0,
|
||||
e_waiting = 1,
|
||||
e_finished = 3,
|
||||
};
|
||||
|
||||
void PlayAnimation(IsleScript::Script p_objectId);
|
||||
void PlayFinalAnimation(IsleScript::Script p_objectId);
|
||||
void StopAction(IsleScript::Script p_objectId);
|
||||
@ -196,9 +208,9 @@ class Ambulance : public IslePathActor {
|
||||
AmbulanceMissionState* m_state; // 0x164
|
||||
MxS16 m_unk0x168; // 0x168
|
||||
MxS16 m_actorId; // 0x16a
|
||||
MxS16 m_unk0x16c; // 0x16c
|
||||
MxS16 m_unk0x16e; // 0x16e
|
||||
MxS16 m_unk0x170; // 0x170
|
||||
MxS16 m_atPoliceTask; // 0x16c
|
||||
MxS16 m_atBeachTask; // 0x16e
|
||||
MxS16 m_taskState; // 0x170
|
||||
MxS16 m_unk0x172; // 0x172
|
||||
IsleScript::Script m_lastAction; // 0x174
|
||||
IsleScript::Script m_lastAnimation; // 0x178
|
||||
|
||||
@ -123,7 +123,7 @@ class Hospital : public LegoWorld {
|
||||
MxLong m_copLedAnimTimer; // 0x11c
|
||||
MxLong m_pizzaLedAnimTimer; // 0x120
|
||||
MxLong m_time; // 0x124
|
||||
undefined m_unk0x128; // 0x128
|
||||
MxBool m_exited; // 0x128
|
||||
};
|
||||
|
||||
#endif // HOSPITAL_H
|
||||
|
||||
@ -121,7 +121,7 @@ class LegoAnimPresenter : public MxVideoPresenter {
|
||||
void SubstituteVariables();
|
||||
void FUN_1006b900(LegoAnim* p_anim, MxLong p_time, Matrix4* p_matrix);
|
||||
void FUN_1006b9a0(LegoAnim* p_anim, MxLong p_time, Matrix4* p_matrix);
|
||||
void FUN_1006c8a0(MxBool p_bool);
|
||||
void SetDisabled(MxBool p_disabled);
|
||||
|
||||
LegoAnim* m_anim; // 0x64
|
||||
LegoROI** m_roiMap; // 0x68
|
||||
|
||||
@ -79,7 +79,7 @@ class LegoBuildingManager : public MxCore {
|
||||
MxBool SwitchMove(LegoEntity* p_entity);
|
||||
MxBool SwitchMood(LegoEntity* p_entity);
|
||||
MxU32 GetAnimationId(LegoEntity* p_entity);
|
||||
MxU32 GetSoundId(LegoEntity* p_entity, MxBool p_state);
|
||||
MxU32 GetSoundId(LegoEntity* p_entity, MxBool p_basedOnMood);
|
||||
MxBool DecrementCounter(LegoEntity* p_entity);
|
||||
MxBool DecrementCounter(MxS32 p_index);
|
||||
MxBool DecrementCounter(LegoBuildingInfo* p_data);
|
||||
|
||||
@ -88,7 +88,7 @@ class LegoCharacterManager {
|
||||
MxBool SwitchMove(LegoROI* p_roi);
|
||||
MxBool SwitchMood(LegoROI* p_roi);
|
||||
MxU32 GetAnimationId(LegoROI* p_roi);
|
||||
MxU32 GetSoundId(LegoROI* p_roi, MxBool p_und);
|
||||
MxU32 GetSoundId(LegoROI* p_roi, MxBool p_basedOnMood);
|
||||
MxU8 GetMood(LegoROI* p_roi);
|
||||
LegoROI* CreateAutoROI(const char* p_name, const char* p_lodName, MxBool p_createEntity);
|
||||
MxResult UpdateBoundingSphereAndBox(LegoROI* p_roi);
|
||||
|
||||
@ -28,7 +28,7 @@ class LegoEntity : public MxEntity {
|
||||
};
|
||||
|
||||
enum {
|
||||
c_altBit1 = 0x01
|
||||
c_disabled = 0x01
|
||||
};
|
||||
|
||||
LegoEntity() { Init(); }
|
||||
@ -68,13 +68,13 @@ class LegoEntity : public MxEntity {
|
||||
// FUNCTION: BETA10 0x10013260
|
||||
virtual void SetWorldSpeed(MxFloat p_worldSpeed) { m_worldSpeed = p_worldSpeed; } // vtable+0x30
|
||||
|
||||
virtual void ClickSound(MxBool p_und); // vtable+0x34
|
||||
virtual void ClickAnimation(); // vtable+0x38
|
||||
virtual void SwitchVariant(); // vtable+0x3c
|
||||
virtual void SwitchSound(); // vtable+0x40
|
||||
virtual void SwitchMove(); // vtable+0x44
|
||||
virtual void SwitchColor(LegoROI* p_roi); // vtable+0x48
|
||||
virtual void SwitchMood(); // vtable+0x4c
|
||||
virtual void ClickSound(MxBool p_basedOnMood); // vtable+0x34
|
||||
virtual void ClickAnimation(); // vtable+0x38
|
||||
virtual void SwitchVariant(); // vtable+0x3c
|
||||
virtual void SwitchSound(); // vtable+0x40
|
||||
virtual void SwitchMove(); // vtable+0x44
|
||||
virtual void SwitchColor(LegoROI* p_roi); // vtable+0x48
|
||||
virtual void SwitchMood(); // vtable+0x4c
|
||||
|
||||
void FUN_10010c30();
|
||||
void SetType(MxU8 p_type);
|
||||
@ -83,7 +83,7 @@ class LegoEntity : public MxEntity {
|
||||
Mx3DPointFloat GetWorldUp();
|
||||
Mx3DPointFloat GetWorldPosition();
|
||||
|
||||
MxBool GetUnknown0x10IsSet(MxU8 p_flag) { return m_unk0x10 & p_flag; }
|
||||
MxBool IsInteraction(MxU8 p_flag) { return m_interaction & p_flag; }
|
||||
MxBool GetFlagsIsSet(MxU8 p_flag) { return m_flags & p_flag; }
|
||||
MxU8 GetFlags() { return m_flags; }
|
||||
|
||||
@ -101,14 +101,14 @@ class LegoEntity : public MxEntity {
|
||||
void SetFlags(MxU8 p_flags) { m_flags = p_flags; }
|
||||
void SetFlag(MxU8 p_flag) { m_flags |= p_flag; }
|
||||
void ClearFlag(MxU8 p_flag) { m_flags &= ~p_flag; }
|
||||
void SetUnknown0x10Flag(MxU8 p_flag) { m_unk0x10 |= p_flag; }
|
||||
void ClearUnknown0x10Flag(MxU8 p_flag) { m_unk0x10 &= ~p_flag; }
|
||||
void SetInteractionFlag(MxU8 p_flag) { m_interaction |= p_flag; }
|
||||
void ClearInteractionFlag(MxU8 p_flag) { m_interaction &= ~p_flag; }
|
||||
|
||||
protected:
|
||||
void Init();
|
||||
void SetWorld();
|
||||
|
||||
MxU8 m_unk0x10; // 0x10
|
||||
MxU8 m_interaction; // 0x10
|
||||
MxU8 m_flags; // 0x11
|
||||
Mx3DPointFloat m_worldLocation; // 0x14
|
||||
Mx3DPointFloat m_worldDirection; // 0x28
|
||||
|
||||
@ -200,6 +200,9 @@ class LegoOmni : public MxOmni {
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
|
||||
void SetVersion10(MxBool p_version10) { m_version10 = p_version10; }
|
||||
MxBool IsVersion10() { return m_version10; }
|
||||
|
||||
// SYNTHETIC: LEGO1 0x10058b30
|
||||
// LegoOmni::`scalar deleting destructor'
|
||||
|
||||
@ -221,6 +224,7 @@ class LegoOmni : public MxOmni {
|
||||
MxDSAction m_action; // 0xa0
|
||||
MxBackgroundAudioManager* m_bkgAudioManager; // 0x134
|
||||
MxTransitionManager* m_transitionManager; // 0x138
|
||||
MxBool m_version10;
|
||||
|
||||
public:
|
||||
MxBool m_unk0x13c; // 0x13c
|
||||
|
||||
@ -13,7 +13,7 @@ struct LegoPathEdgeContainer;
|
||||
struct LegoOrientedEdge;
|
||||
class LegoWEEdge;
|
||||
|
||||
extern MxLong g_unk0x100f3308;
|
||||
extern MxLong g_timeLastHitSoundPlayed;
|
||||
extern const char* g_strHIT_WALL_SOUND;
|
||||
|
||||
// VTABLE: LEGO1 0x100d6e28
|
||||
|
||||
@ -49,12 +49,12 @@ class LEGO1_EXPORT LegoPlantManager : public MxCore {
|
||||
MxBool SwitchMove(LegoEntity* p_entity);
|
||||
MxBool SwitchMood(LegoEntity* p_entity);
|
||||
MxU32 GetAnimationId(LegoEntity* p_entity);
|
||||
MxU32 GetSoundId(LegoEntity* p_entity, MxBool p_state);
|
||||
MxU32 GetSoundId(LegoEntity* p_entity, MxBool p_basedOnMood);
|
||||
LegoPlantInfo* GetInfoArray(MxS32& p_length);
|
||||
LegoEntity* CreatePlant(MxS32 p_index, LegoWorld* p_world, LegoOmni::World p_worldId);
|
||||
MxBool DecrementCounter(LegoEntity* p_entity);
|
||||
void ScheduleAnimation(LegoEntity* p_entity, MxLong p_length);
|
||||
MxResult FUN_10026410();
|
||||
MxResult DetermineBoundaries();
|
||||
void ClearCounters();
|
||||
void SetInitialCounters();
|
||||
|
||||
@ -77,11 +77,11 @@ class LEGO1_EXPORT LegoPlantManager : public MxCore {
|
||||
static MxS32 g_maxMove[4];
|
||||
static MxU32 g_maxSound;
|
||||
|
||||
LegoOmni::World m_worldId; // 0x08
|
||||
undefined m_unk0x0c; // 0x0c
|
||||
AnimEntry* m_entries[5]; // 0x10
|
||||
MxS8 m_numEntries; // 0x24
|
||||
LegoWorld* m_world; // 0x28
|
||||
LegoOmni::World m_worldId; // 0x08
|
||||
MxBool m_boundariesDetermined; // 0x0c
|
||||
AnimEntry* m_entries[5]; // 0x10
|
||||
MxS8 m_numEntries; // 0x24
|
||||
LegoWorld* m_world; // 0x28
|
||||
|
||||
friend class DebugViewer;
|
||||
};
|
||||
|
||||
@ -144,10 +144,10 @@ class LegoRaceCar : public LegoCarRaceActor, public LegoRaceMap {
|
||||
MxResult VTable0x9c() override; // vtable+0x9c
|
||||
|
||||
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);
|
||||
|
||||
static void FUN_10012de0();
|
||||
static void InitYouCantStopSound();
|
||||
static void InitSoundIndices();
|
||||
|
||||
// SYNTHETIC: LEGO1 0x10014240
|
||||
@ -155,7 +155,7 @@ class LegoRaceCar : public LegoCarRaceActor, public LegoRaceMap {
|
||||
|
||||
private:
|
||||
undefined m_userState; // 0x54
|
||||
float m_unk0x58; // 0x58
|
||||
float m_kickStart; // 0x58
|
||||
Mx3DPointFloat m_unk0x5c; // 0x5c
|
||||
|
||||
// Names verified by BETA10 0x100cb4a9
|
||||
|
||||
@ -44,8 +44,11 @@ class LegoCarRaceActor : public virtual LegoRaceActor {
|
||||
Vector3& p_v3
|
||||
) override; // vtable+0x6c
|
||||
void Animate(float p_time) override; // vtable+0x70
|
||||
void SwitchBoundary(LegoPathBoundary*& p_boundary, LegoOrientedEdge*& p_edge, float& p_unk0xe4)
|
||||
override; // vtable+0x98
|
||||
void SwitchBoundary(
|
||||
LegoPathBoundary*& p_boundary,
|
||||
LegoOrientedEdge*& p_edge,
|
||||
float& p_unk0xe4
|
||||
) override; // vtable+0x98
|
||||
MxResult VTable0x9c() override; // vtable+0x9c
|
||||
|
||||
// LegoCarRaceActor vtable
|
||||
@ -83,7 +86,7 @@ class LegoCarRaceActor : public virtual LegoRaceActor {
|
||||
|
||||
protected:
|
||||
MxFloat m_unk0x08; // 0x08
|
||||
MxU8 m_unk0x0c; // 0x0c
|
||||
MxU8 m_animState; // 0x0c
|
||||
|
||||
// Could be a multiplier for the maximum speed when going straight
|
||||
MxFloat m_unk0x10; // 0x10
|
||||
|
||||
@ -55,6 +55,8 @@ class MxTransitionManager : public MxCore {
|
||||
|
||||
TransitionType GetTransitionType() { return m_mode; }
|
||||
|
||||
LEGO1_EXPORT static void configureMxTransitionManager(TransitionType p_transitionManagerConfig);
|
||||
|
||||
// SYNTHETIC: LEGO1 0x1004b9e0
|
||||
// MxTransitionManager::`scalar deleting destructor'
|
||||
|
||||
|
||||
@ -40,9 +40,9 @@ Ambulance::Ambulance()
|
||||
m_state = NULL;
|
||||
m_unk0x168 = 0;
|
||||
m_actorId = -1;
|
||||
m_unk0x16c = 0;
|
||||
m_unk0x16e = 0;
|
||||
m_unk0x170 = 0;
|
||||
m_atPoliceTask = 0;
|
||||
m_atBeachTask = 0;
|
||||
m_taskState = Ambulance::e_none;
|
||||
m_lastAction = IsleScript::c_noneIsle;
|
||||
m_unk0x172 = 0;
|
||||
m_lastAnimation = IsleScript::c_noneIsle;
|
||||
@ -73,7 +73,7 @@ MxResult Ambulance::Create(MxDSAction& p_dsAction)
|
||||
m_state = (AmbulanceMissionState*) GameState()->GetState("AmbulanceMissionState");
|
||||
if (!m_state) {
|
||||
m_state = new AmbulanceMissionState();
|
||||
m_state->m_unk0x08 = 0;
|
||||
m_state->m_state = AmbulanceMissionState::e_ready;
|
||||
GameState()->RegisterState(m_state);
|
||||
}
|
||||
}
|
||||
@ -173,25 +173,25 @@ MxLong Ambulance::HandleEndAction(MxEndActionNotificationParam& p_param)
|
||||
m_lastAction = IsleScript::c_noneIsle;
|
||||
}
|
||||
else if (objectId == IsleScript::c_hho027en_RunAnim) {
|
||||
m_state->m_unk0x08 = 1;
|
||||
m_state->m_state = AmbulanceMissionState::e_enteredAmbulance;
|
||||
CurrentWorld()->PlaceActor(UserActor());
|
||||
HandleClick();
|
||||
m_unk0x172 = 0;
|
||||
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) {
|
||||
if (m_unk0x170 == 3) {
|
||||
if (m_taskState == Ambulance::e_finished) {
|
||||
PlayAnimation(IsleScript::c_hpz055pa_RunAnim);
|
||||
m_unk0x170 = 0;
|
||||
m_taskState = Ambulance::e_none;
|
||||
}
|
||||
else {
|
||||
PlayAnimation(IsleScript::c_hpz053pa_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);
|
||||
m_unk0x170 = 0;
|
||||
m_taskState = Ambulance::e_none;
|
||||
}
|
||||
else {
|
||||
PlayAnimation(IsleScript::c_hpz052ma_RunAnim);
|
||||
@ -204,18 +204,18 @@ MxLong Ambulance::HandleEndAction(MxEndActionNotificationParam& p_param)
|
||||
m_unk0x172 = 0;
|
||||
TickleManager()->RegisterClient(this, 40000);
|
||||
|
||||
if (m_unk0x16c != 0) {
|
||||
if (m_atPoliceTask != 0) {
|
||||
StopActions();
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
if (m_unk0x170 == 3) {
|
||||
if (m_taskState == Ambulance::e_finished) {
|
||||
PlayAnimation(IsleScript::c_hps117bd_RunAnim);
|
||||
m_unk0x170 = 0;
|
||||
m_taskState = Ambulance::e_none;
|
||||
}
|
||||
else {
|
||||
PlayAnimation(IsleScript::c_hps118re_RunAnim);
|
||||
@ -228,12 +228,12 @@ MxLong Ambulance::HandleEndAction(MxEndActionNotificationParam& p_param)
|
||||
m_unk0x172 = 0;
|
||||
TickleManager()->RegisterClient(this, 40000);
|
||||
|
||||
if (m_unk0x16e != 0) {
|
||||
if (m_atBeachTask != 0) {
|
||||
StopActions();
|
||||
}
|
||||
}
|
||||
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
|
||||
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());
|
||||
|
||||
if (roi != NULL && !SDL_strcasecmp(roi->GetName(), "ps-gate")) {
|
||||
m_unk0x170 = 3;
|
||||
m_taskState = Ambulance::e_finished;
|
||||
return 1;
|
||||
}
|
||||
|
||||
roi = PickRootROI(p_param.GetX(), p_param.GetY());
|
||||
|
||||
if (roi != NULL && !SDL_strcasecmp(roi->GetName(), "gd")) {
|
||||
m_unk0x170 = 3;
|
||||
m_taskState = Ambulance::e_finished;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -273,9 +273,9 @@ MxLong Ambulance::HandlePathStruct(LegoPathStructNotificationParam& p_param)
|
||||
}
|
||||
|
||||
if (p_param.GetTrigger() == LegoPathStruct::c_camAnim && p_param.GetData() == 0x0b) {
|
||||
if (m_unk0x16e != 0) {
|
||||
if (m_unk0x16c != 0) {
|
||||
m_state->m_unk0x08 = 2;
|
||||
if (m_atBeachTask != 0) {
|
||||
if (m_atPoliceTask != 0) {
|
||||
m_state->m_state = AmbulanceMissionState::e_prepareAmbulance;
|
||||
|
||||
if (m_lastAction != IsleScript::c_noneIsle) {
|
||||
InvokeAction(Extra::e_stop, *g_isleScript, m_lastAction, NULL);
|
||||
@ -300,7 +300,7 @@ MxLong Ambulance::HandlePathStruct(LegoPathStructNotificationParam& p_param)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (m_unk0x16e != 0) {
|
||||
if (m_atBeachTask != 0) {
|
||||
if (m_lastAction != IsleScript::c_noneIsle) {
|
||||
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) {
|
||||
InvokeAction(Extra::e_stop, *g_isleScript, m_lastAction, NULL);
|
||||
}
|
||||
@ -318,9 +318,9 @@ MxLong Ambulance::HandlePathStruct(LegoPathStructNotificationParam& p_param)
|
||||
PlayAction(IsleScript::c_Avo915In_PlayWav);
|
||||
}
|
||||
}
|
||||
else if (p_param.GetTrigger() == LegoPathStruct::c_s && p_param.GetData() == 0x131 && m_unk0x16e == 0) {
|
||||
m_unk0x16e = 1;
|
||||
m_unk0x170 = 1;
|
||||
else if (p_param.GetTrigger() == LegoPathStruct::c_s && p_param.GetData() == 0x131 && m_atBeachTask == 0) {
|
||||
m_atBeachTask = 1;
|
||||
m_taskState = Ambulance::e_waiting;
|
||||
|
||||
if (m_lastAction != IsleScript::c_noneIsle) {
|
||||
InvokeAction(Extra::e_stop, *g_isleScript, m_lastAction, NULL);
|
||||
@ -348,9 +348,9 @@ MxLong Ambulance::HandlePathStruct(LegoPathStructNotificationParam& p_param)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (p_param.GetTrigger() == LegoPathStruct::c_camAnim && (p_param.GetData() == 0x22 || p_param.GetData() == 0x23 || p_param.GetData() == 0x24) && m_unk0x16c == 0) {
|
||||
m_unk0x16c = 1;
|
||||
m_unk0x170 = 1;
|
||||
else if (p_param.GetTrigger() == LegoPathStruct::c_camAnim && (p_param.GetData() == 0x22 || p_param.GetData() == 0x23 || p_param.GetData() == 0x24) && m_atPoliceTask == 0) {
|
||||
m_atPoliceTask = 1;
|
||||
m_taskState = Ambulance::e_waiting;
|
||||
|
||||
if (m_lastAction != IsleScript::c_noneIsle) {
|
||||
InvokeAction(Extra::e_stop, *g_isleScript, m_lastAction, NULL);
|
||||
@ -371,7 +371,7 @@ MxLong Ambulance::HandleClick()
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (m_state->m_unk0x08 == 2) {
|
||||
if (m_state->m_state == AmbulanceMissionState::e_prepareAmbulance) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -390,7 +390,7 @@ MxLong Ambulance::HandleClick()
|
||||
InvokeAction(Extra::e_start, *g_isleScript, IsleScript::c_AmbulanceDashboard, NULL);
|
||||
ControlManager()->Register(this);
|
||||
|
||||
if (m_state->m_unk0x08 == 1) {
|
||||
if (m_state->m_state == AmbulanceMissionState::e_enteredAmbulance) {
|
||||
SpawnPlayer(LegoGameState::e_hospitalExited, TRUE, 0);
|
||||
m_state->m_startTime = Timer()->GetTime();
|
||||
InvokeAction(Extra::e_start, *g_isleScript, IsleScript::c_pns018rd_RunAnim, NULL);
|
||||
@ -401,9 +401,9 @@ MxLong Ambulance::HandleClick()
|
||||
|
||||
// FUNCTION: LEGO1 0x10036e60
|
||||
// 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);
|
||||
m_lastAction = IsleScript::c_noneIsle;
|
||||
m_lastAnimation = IsleScript::c_noneIsle;
|
||||
@ -414,7 +414,7 @@ void Ambulance::Exit()
|
||||
{
|
||||
GameState()->m_currentArea = LegoGameState::e_hospitalExterior;
|
||||
StopActions();
|
||||
FUN_10037250();
|
||||
Reset();
|
||||
Leave();
|
||||
}
|
||||
|
||||
@ -470,11 +470,11 @@ void Ambulance::ActivateSceneActions()
|
||||
{
|
||||
PlayMusic(JukeboxScript::c_Hospital_Music);
|
||||
|
||||
if (m_state->m_unk0x08 == 1) {
|
||||
m_state->m_unk0x08 = 0;
|
||||
if (m_state->m_state == AmbulanceMissionState::e_enteredAmbulance) {
|
||||
m_state->m_state = AmbulanceMissionState::e_ready;
|
||||
PlayAction(IsleScript::c_ham033cl_PlayWav);
|
||||
}
|
||||
else if (m_unk0x16c != 0 && m_unk0x16e != 0) {
|
||||
else if (m_atPoliceTask != 0 && m_atBeachTask != 0) {
|
||||
IsleScript::Script objectId;
|
||||
|
||||
switch (SDL_rand(2)) {
|
||||
@ -574,14 +574,14 @@ void Ambulance::StopActions()
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x10037250
|
||||
void Ambulance::FUN_10037250()
|
||||
void Ambulance::Reset()
|
||||
{
|
||||
StopAction(m_lastAction);
|
||||
BackgroundAudioManager()->RaiseVolume();
|
||||
((Act1State*) GameState()->GetState("Act1State"))->m_unk0x018 = 0;
|
||||
m_state->m_unk0x08 = 0;
|
||||
m_unk0x16e = 0;
|
||||
m_unk0x16c = 0;
|
||||
m_state->m_state = AmbulanceMissionState::e_ready;
|
||||
m_atBeachTask = 0;
|
||||
m_atPoliceTask = 0;
|
||||
g_isleFlags |= Isle::c_playMusic;
|
||||
AnimationManager()->EnableCamAnims(TRUE);
|
||||
AnimationManager()->FUN_1005f6d0(TRUE);
|
||||
@ -629,7 +629,7 @@ void Ambulance::PlayAction(IsleScript::Script p_objectId)
|
||||
// FUNCTION: LEGO1 0x100373a0
|
||||
AmbulanceMissionState::AmbulanceMissionState()
|
||||
{
|
||||
m_unk0x08 = 0;
|
||||
m_state = AmbulanceMissionState::e_ready;
|
||||
m_startTime = 0;
|
||||
m_peScore = 0;
|
||||
m_maScore = 0;
|
||||
|
||||
@ -488,7 +488,7 @@ void LegoCarBuild::FUN_100236d0()
|
||||
m_unk0x110 = NULL;
|
||||
m_unk0x100 = 0;
|
||||
|
||||
if (m_animPresenter->AllPartsPlaced()) {
|
||||
if (m_animPresenter->AllPartsPlaced() && !Lego()->IsVersion10()) {
|
||||
// Note the code duplication with LEGO1 0x10025ee0
|
||||
switch (m_carId) {
|
||||
case 1:
|
||||
|
||||
@ -199,10 +199,10 @@ LegoBuildingInfo g_buildingInfoInit[16] = {
|
||||
MxU32 LegoBuildingManager::g_maxSound = 6;
|
||||
|
||||
// GLOBAL: LEGO1 0x100f373c
|
||||
MxU32 g_unk0x100f373c = 0x3c;
|
||||
MxU32 g_buildingSoundIdOffset = 0x3c;
|
||||
|
||||
// GLOBAL: LEGO1 0x100f3740
|
||||
MxU32 g_unk0x100f3740 = 0x42;
|
||||
MxU32 g_buildingSoundIdMoodOffset = 0x42;
|
||||
|
||||
// clang-format off
|
||||
// GLOBAL: LEGO1 0x100f3788
|
||||
@ -227,6 +227,8 @@ LegoBuildingInfo g_buildingInfo[16];
|
||||
// GLOBAL: LEGO1 0x100f3748
|
||||
MxS32 LegoBuildingManager::g_maxMove[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 0};
|
||||
|
||||
#define HAUS1_INDEX 12
|
||||
|
||||
// FUNCTION: LEGO1 0x1002f8b0
|
||||
void LegoBuildingManager::configureLegoBuildingManager(MxS32 p_buildingManagerConfig)
|
||||
{
|
||||
@ -392,6 +394,9 @@ MxResult LegoBuildingManager::Read(LegoStorage* p_storage)
|
||||
m_nextVariant = 0;
|
||||
}
|
||||
|
||||
// Bugfix: allow Pepper to change variant building after save game load
|
||||
g_buildingInfo[HAUS1_INDEX].m_variant = g_buildingInfoVariants[m_nextVariant];
|
||||
|
||||
result = SUCCESS;
|
||||
|
||||
done:
|
||||
@ -461,7 +466,7 @@ MxBool LegoBuildingManager::SwitchVariant(LegoEntity* p_entity)
|
||||
|
||||
roi->SetVisibility(FALSE);
|
||||
info->m_variant = g_buildingInfoVariants[m_nextVariant];
|
||||
CreateBuilding(12, CurrentWorld());
|
||||
CreateBuilding(HAUS1_INDEX, CurrentWorld());
|
||||
|
||||
if (info->m_entity != NULL) {
|
||||
info->m_entity->GetROI()->SetVisibility(TRUE);
|
||||
@ -548,7 +553,7 @@ MxU32 LegoBuildingManager::GetAnimationId(LegoEntity* p_entity)
|
||||
|
||||
// FUNCTION: LEGO1 0x1002ff40
|
||||
// FUNCTION: BETA10 0x10064398
|
||||
MxU32 LegoBuildingManager::GetSoundId(LegoEntity* p_entity, MxBool p_state)
|
||||
MxU32 LegoBuildingManager::GetSoundId(LegoEntity* p_entity, MxBool p_basedOnMood)
|
||||
{
|
||||
LegoBuildingInfo* info = GetInfo(p_entity);
|
||||
|
||||
@ -556,12 +561,12 @@ MxU32 LegoBuildingManager::GetSoundId(LegoEntity* p_entity, MxBool p_state)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (p_state) {
|
||||
return info->m_mood + g_unk0x100f3740;
|
||||
if (p_basedOnMood) {
|
||||
return info->m_mood + g_buildingSoundIdMoodOffset;
|
||||
}
|
||||
|
||||
if (info != NULL) {
|
||||
return info->m_sound + g_unk0x100f373c;
|
||||
return info->m_sound + g_buildingSoundIdOffset;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@ -39,10 +39,10 @@ MxU32 g_characterAnimationId = 10;
|
||||
char* LegoCharacterManager::g_customizeAnimFile = NULL;
|
||||
|
||||
// GLOBAL: LEGO1 0x100fc4d8
|
||||
MxU32 g_soundIdOffset = 50;
|
||||
MxU32 g_characterSoundIdOffset = 50;
|
||||
|
||||
// GLOBAL: LEGO1 0x100fc4dc
|
||||
MxU32 g_soundIdMoodOffset = 66;
|
||||
MxU32 g_characterSoundIdMoodOffset = 66;
|
||||
|
||||
// GLOBAL: LEGO1 0x100fc4e8
|
||||
MxU32 g_headTextureCounter = 0;
|
||||
@ -636,7 +636,7 @@ MxBool LegoCharacterManager::SetHeadTexture(LegoROI* p_roi, LegoTextureInfo* p_t
|
||||
LegoLOD* clone = lod->Clone(renderer);
|
||||
|
||||
if (p_texture != NULL) {
|
||||
clone->FUN_100aad70(p_texture);
|
||||
clone->UpdateTextureInfo(p_texture);
|
||||
}
|
||||
|
||||
dupLodList->PushBack(clone);
|
||||
@ -933,16 +933,16 @@ MxU32 LegoCharacterManager::GetAnimationId(LegoROI* p_roi)
|
||||
|
||||
// FUNCTION: LEGO1 0x10085140
|
||||
// FUNCTION: BETA10 0x10076855
|
||||
MxU32 LegoCharacterManager::GetSoundId(LegoROI* p_roi, MxBool p_und)
|
||||
MxU32 LegoCharacterManager::GetSoundId(LegoROI* p_roi, MxBool p_basedOnMood)
|
||||
{
|
||||
LegoActorInfo* info = GetActorInfo(p_roi);
|
||||
|
||||
if (p_und) {
|
||||
return info->m_mood + g_soundIdMoodOffset;
|
||||
if (p_basedOnMood) {
|
||||
return info->m_mood + g_characterSoundIdMoodOffset;
|
||||
}
|
||||
|
||||
if (info != NULL) {
|
||||
return info->m_sound + g_soundIdOffset;
|
||||
return info->m_sound + g_characterSoundIdOffset;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
|
||||
@ -40,10 +40,10 @@ MxU8 g_counters[] = {1, 2, 2, 3};
|
||||
MxU32 LegoPlantManager::g_maxSound = 8;
|
||||
|
||||
// GLOBAL: LEGO1 0x100f3160
|
||||
MxU32 g_unk0x100f3160 = 56;
|
||||
MxU32 g_plantSoundIdOffset = 56;
|
||||
|
||||
// GLOBAL: LEGO1 0x100f3164
|
||||
MxU32 g_unk0x100f3164 = 66;
|
||||
MxU32 g_plantSoundIdMoodOffset = 66;
|
||||
|
||||
// GLOBAL: LEGO1 0x100f3168
|
||||
MxS32 LegoPlantManager::g_maxMove[4] = {3, 3, 3, 3};
|
||||
@ -83,7 +83,7 @@ void LegoPlantManager::Init()
|
||||
}
|
||||
|
||||
m_worldId = LegoOmni::e_undefined;
|
||||
m_unk0x0c = 0;
|
||||
m_boundariesDetermined = FALSE;
|
||||
m_numEntries = 0;
|
||||
}
|
||||
|
||||
@ -98,7 +98,7 @@ void LegoPlantManager::LoadWorldInfo(LegoOmni::World p_worldId)
|
||||
CreatePlant(i, world, p_worldId);
|
||||
}
|
||||
|
||||
m_unk0x0c = 0;
|
||||
m_boundariesDetermined = FALSE;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100263a0
|
||||
@ -119,12 +119,12 @@ void LegoPlantManager::Reset(LegoOmni::World p_worldId)
|
||||
}
|
||||
|
||||
m_worldId = LegoOmni::e_undefined;
|
||||
m_unk0x0c = 0;
|
||||
m_boundariesDetermined = FALSE;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x10026410
|
||||
// FUNCTION: BETA10 0x100c50e9
|
||||
MxResult LegoPlantManager::FUN_10026410()
|
||||
MxResult LegoPlantManager::DetermineBoundaries()
|
||||
{
|
||||
// similar to LegoBuildingManager::FUN_10030630()
|
||||
|
||||
@ -192,7 +192,7 @@ MxResult LegoPlantManager::FUN_10026410()
|
||||
}
|
||||
}
|
||||
|
||||
m_unk0x0c = TRUE;
|
||||
m_boundariesDetermined = TRUE;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@ -200,8 +200,8 @@ MxResult LegoPlantManager::FUN_10026410()
|
||||
// FUNCTION: BETA10 0x100c55e0
|
||||
LegoPlantInfo* LegoPlantManager::GetInfoArray(MxS32& p_length)
|
||||
{
|
||||
if (!m_unk0x0c) {
|
||||
FUN_10026410();
|
||||
if (!m_boundariesDetermined) {
|
||||
DetermineBoundaries();
|
||||
}
|
||||
|
||||
p_length = sizeOfArray(g_plantInfo);
|
||||
@ -214,7 +214,7 @@ LegoEntity* LegoPlantManager::CreatePlant(MxS32 p_index, LegoWorld* p_world, Leg
|
||||
{
|
||||
LegoEntity* entity = NULL;
|
||||
|
||||
if (p_index < sizeOfArray(g_plantInfo)) {
|
||||
if (p_worldId != LegoOmni::e_undefined && p_index < sizeOfArray(g_plantInfo)) {
|
||||
MxU32 world = 1 << (MxU8) p_worldId;
|
||||
|
||||
if (g_plantInfo[p_index].m_worlds & world && g_plantInfo[p_index].m_counter != 0) {
|
||||
@ -514,16 +514,16 @@ MxU32 LegoPlantManager::GetAnimationId(LegoEntity* p_entity)
|
||||
|
||||
// FUNCTION: LEGO1 0x10026ba0
|
||||
// FUNCTION: BETA10 0x100c61ba
|
||||
MxU32 LegoPlantManager::GetSoundId(LegoEntity* p_entity, MxBool p_state)
|
||||
MxU32 LegoPlantManager::GetSoundId(LegoEntity* p_entity, MxBool p_basedOnMood)
|
||||
{
|
||||
LegoPlantInfo* info = GetInfo(p_entity);
|
||||
|
||||
if (p_state) {
|
||||
return (info->m_mood & 1) + g_unk0x100f3164;
|
||||
if (p_basedOnMood) {
|
||||
return (info->m_mood & 1) + g_plantSoundIdMoodOffset;
|
||||
}
|
||||
|
||||
if (info != NULL) {
|
||||
return info->m_sound + g_unk0x100f3160;
|
||||
return info->m_sound + g_plantSoundIdOffset;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@ -83,7 +83,7 @@ LegoTextureInfo* LegoTextureInfo::Create(const char* p_name, LegoTexture* p_text
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
desc.dwSize = sizeof(desc);
|
||||
|
||||
if (textureInfo->m_surface->Lock(NULL, &desc, DDLOCK_SURFACEMEMORYPTR, NULL) != DD_OK) {
|
||||
if (textureInfo->m_surface->Lock(NULL, &desc, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WRITEONLY, NULL) != DD_OK) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -193,7 +193,7 @@ LegoResult LegoTextureInfo::LoadBits(const LegoU8* p_bits)
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
desc.dwSize = sizeof(desc);
|
||||
|
||||
if (m_surface->Lock(NULL, &desc, DDLOCK_SURFACEMEMORYPTR, NULL) == DD_OK) {
|
||||
if (m_surface->Lock(NULL, &desc, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WRITEONLY, NULL) == DD_OK) {
|
||||
MxU8* surface = (MxU8*) desc.lpSurface;
|
||||
const LegoU8* bits = p_bits;
|
||||
|
||||
|
||||
@ -708,7 +708,7 @@ void WriteDefaultTexture(LegoStorage* p_storage, const char* p_name)
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
desc.dwSize = sizeof(desc);
|
||||
|
||||
if (surface->Lock(NULL, &desc, DDLOCK_SURFACEMEMORYPTR, NULL) == DD_OK) {
|
||||
if (surface->Lock(NULL, &desc, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WRITEONLY, NULL) == DD_OK) {
|
||||
LegoImage* image = new LegoImage(desc.dwWidth, desc.dwHeight);
|
||||
|
||||
if (image != NULL) {
|
||||
|
||||
@ -16,6 +16,8 @@
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxTransitionManager, 0x900)
|
||||
|
||||
MxTransitionManager::TransitionType g_transitionManagerConfig = MxTransitionManager::e_mosaic;
|
||||
|
||||
// GLOBAL: LEGO1 0x100f4378
|
||||
RECT g_fullScreenRect = {0, 0, 640, 480};
|
||||
|
||||
@ -105,7 +107,7 @@ MxResult MxTransitionManager::StartTransition(
|
||||
backgroundAudioManager->Stop();
|
||||
}
|
||||
|
||||
m_mode = p_animationType;
|
||||
m_mode = g_transitionManagerConfig;
|
||||
|
||||
m_copyFlags.m_bit0 = p_doCopy;
|
||||
|
||||
@ -210,10 +212,10 @@ void MxTransitionManager::DissolveTransition()
|
||||
memset(&ddsd, 0, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
|
||||
HRESULT res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL);
|
||||
HRESULT res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
|
||||
if (res == DDERR_SURFACELOST) {
|
||||
m_ddSurface->Restore();
|
||||
res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL);
|
||||
res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
|
||||
}
|
||||
|
||||
if (res == DD_OK) {
|
||||
@ -402,10 +404,10 @@ void MxTransitionManager::WipeDownTransition()
|
||||
memset(&ddsd, 0, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
|
||||
HRESULT res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL);
|
||||
HRESULT res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
|
||||
if (res == DDERR_SURFACELOST) {
|
||||
m_ddSurface->Restore();
|
||||
res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL);
|
||||
res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
|
||||
}
|
||||
|
||||
if (res == DD_OK) {
|
||||
@ -439,10 +441,10 @@ void MxTransitionManager::WindowsTransition()
|
||||
memset(&ddsd, 0, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
|
||||
HRESULT res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL);
|
||||
HRESULT res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
|
||||
if (res == DDERR_SURFACELOST) {
|
||||
m_ddSurface->Restore();
|
||||
res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL);
|
||||
res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
|
||||
}
|
||||
|
||||
if (res == DD_OK) {
|
||||
@ -483,10 +485,10 @@ void MxTransitionManager::BrokenTransition()
|
||||
memset(&ddsd, 0, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
|
||||
HRESULT res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL);
|
||||
HRESULT res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
|
||||
if (res == DDERR_SURFACELOST) {
|
||||
m_ddSurface->Restore();
|
||||
res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL);
|
||||
res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
|
||||
}
|
||||
|
||||
if (res == DD_OK) {
|
||||
@ -632,3 +634,8 @@ void MxTransitionManager::SetupCopyRect(LPDDSURFACEDESC p_ddsc)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void MxTransitionManager::configureMxTransitionManager(TransitionType p_transitionManagerConfig)
|
||||
{
|
||||
g_transitionManagerConfig = p_transitionManagerConfig;
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@ LegoActor::LegoActor()
|
||||
m_frequencyFactor = 0.0f;
|
||||
m_sound = NULL;
|
||||
m_unk0x70 = 0.0f;
|
||||
m_unk0x10 = 0;
|
||||
m_interaction = 0;
|
||||
m_actorId = 0;
|
||||
}
|
||||
|
||||
|
||||
@ -31,7 +31,7 @@ void LegoEntity::Init()
|
||||
m_roi = NULL;
|
||||
m_cameraFlag = FALSE;
|
||||
m_siFile = NULL;
|
||||
m_unk0x10 = 0;
|
||||
m_interaction = 0;
|
||||
m_flags = 0;
|
||||
m_actionType = Extra::ActionType::e_unknown;
|
||||
m_targetEntityId = -1;
|
||||
@ -266,23 +266,23 @@ void LegoEntity::ParseAction(char* p_extra)
|
||||
|
||||
// FUNCTION: LEGO1 0x10010f10
|
||||
// FUNCTION: BETA10 0x1007ee87
|
||||
void LegoEntity::ClickSound(MxBool p_und)
|
||||
void LegoEntity::ClickSound(MxBool p_basedOnMood)
|
||||
{
|
||||
if (!GetUnknown0x10IsSet(c_altBit1)) {
|
||||
if (!IsInteraction(c_disabled)) {
|
||||
MxU32 objectId = 0;
|
||||
const char* name = m_roi->GetName();
|
||||
|
||||
switch (m_type) {
|
||||
case e_actor:
|
||||
objectId = CharacterManager()->GetSoundId(m_roi, p_und);
|
||||
objectId = CharacterManager()->GetSoundId(m_roi, p_basedOnMood);
|
||||
break;
|
||||
case e_unk1:
|
||||
break;
|
||||
case e_plant:
|
||||
objectId = PlantManager()->GetSoundId(this, p_und);
|
||||
objectId = PlantManager()->GetSoundId(this, p_basedOnMood);
|
||||
break;
|
||||
case e_building:
|
||||
objectId = BuildingManager()->GetSoundId(this, p_und);
|
||||
objectId = BuildingManager()->GetSoundId(this, p_basedOnMood);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -300,7 +300,7 @@ void LegoEntity::ClickSound(MxBool p_und)
|
||||
// FUNCTION: BETA10 0x1007f062
|
||||
void LegoEntity::ClickAnimation()
|
||||
{
|
||||
if (!GetUnknown0x10IsSet(c_altBit1)) {
|
||||
if (!IsInteraction(c_disabled)) {
|
||||
MxU32 objectId = 0;
|
||||
MxDSAction action;
|
||||
const char* name = m_roi->GetName();
|
||||
@ -332,7 +332,7 @@ void LegoEntity::ClickAnimation()
|
||||
action.SetObjectId(objectId);
|
||||
action.AppendExtra(strlen(extra) + 1, extra);
|
||||
LegoOmni::GetInstance()->GetAnimationManager()->StartEntityAction(action, this);
|
||||
m_unk0x10 |= c_altBit1;
|
||||
m_interaction |= c_disabled;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -697,7 +697,7 @@ MxLong LegoNavController::Notify(MxParam& p_param)
|
||||
for (MxS32 i = 0; i < numPlants; i++) {
|
||||
LegoEntity* entity = plantMgr->CreatePlant(i, NULL, LegoOmni::e_act1);
|
||||
|
||||
if (entity != NULL && !entity->GetUnknown0x10IsSet(LegoEntity::c_altBit1)) {
|
||||
if (entity != NULL && !entity->IsInteraction(LegoEntity::c_disabled)) {
|
||||
LegoROI* roi = entity->GetROI();
|
||||
|
||||
if (roi != NULL && roi->GetVisibility()) {
|
||||
|
||||
@ -76,6 +76,7 @@ void LegoOmni::Init()
|
||||
m_bkgAudioManager = NULL;
|
||||
m_unk0x13c = TRUE;
|
||||
m_transitionManager = NULL;
|
||||
m_version10 = FALSE;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x10058c30
|
||||
|
||||
@ -37,7 +37,7 @@ const char* g_strHIT_WALL_SOUND = "HIT_WALL_SOUND";
|
||||
|
||||
// GLOBAL: LEGO1 0x100f3308
|
||||
// GLOBAL: BETA10 0x101f1e1c
|
||||
MxLong g_unk0x100f3308 = 0;
|
||||
MxLong g_timeLastHitSoundPlayed = 0;
|
||||
|
||||
// FUNCTION: LEGO1 0x1002d700
|
||||
// FUNCTION: BETA10 0x100ae6e0
|
||||
@ -292,8 +292,8 @@ MxS32 LegoPathActor::VTable0x8c(float p_time, Matrix4& p_transform)
|
||||
if (m_boundary == oldBoundary) {
|
||||
MxLong time = Timer()->GetTime();
|
||||
|
||||
if (time - g_unk0x100f3308 > 1000) {
|
||||
g_unk0x100f3308 = time;
|
||||
if (time - g_timeLastHitSoundPlayed > 1000) {
|
||||
g_timeLastHitSoundPlayed = time;
|
||||
const char* var = VariableTable()->GetVariable(g_strHIT_WALL_SOUND);
|
||||
|
||||
if (var && var[0] != 0) {
|
||||
|
||||
@ -246,7 +246,7 @@ MxLong CarRace::HandlePathStruct(LegoPathStructNotificationParam& p_param)
|
||||
VariableTable()->SetVariable(g_strHIT_WALL_SOUND, "");
|
||||
NavController()->SetDeadZone(NavController()->GetDefaultDeadZone());
|
||||
NavController()->SetTrackDefault(1);
|
||||
LegoRaceCar::FUN_10012de0();
|
||||
LegoRaceCar::InitYouCantStopSound();
|
||||
m_raceState->m_unk0x28 = 2;
|
||||
|
||||
RaceState::Entry* raceState = m_raceState->GetState(GameState()->GetActorId());
|
||||
@ -348,7 +348,7 @@ MxLong CarRace::HandleClick(LegoEventNotificationParam& p_param)
|
||||
VariableTable()->SetVariable(g_strHIT_WALL_SOUND, "");
|
||||
NavController()->SetDeadZone(NavController()->GetDefaultDeadZone());
|
||||
NavController()->SetTrackDefault(1);
|
||||
LegoRaceCar::FUN_10012de0();
|
||||
LegoRaceCar::InitYouCantStopSound();
|
||||
m_destLocation = LegoGameState::e_infomain;
|
||||
TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE);
|
||||
GameState()->GetBackgroundColor()->SetValue("reset");
|
||||
@ -360,7 +360,7 @@ MxLong CarRace::HandleClick(LegoEventNotificationParam& p_param)
|
||||
VariableTable()->SetVariable(g_strHIT_WALL_SOUND, "");
|
||||
NavController()->SetDeadZone(NavController()->GetDefaultDeadZone());
|
||||
NavController()->SetTrackDefault(1);
|
||||
LegoRaceCar::FUN_10012de0();
|
||||
LegoRaceCar::InitYouCantStopSound();
|
||||
m_destLocation = LegoGameState::e_carraceExterior;
|
||||
TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE);
|
||||
GameState()->GetBackgroundColor()->SetValue("reset");
|
||||
@ -424,7 +424,7 @@ MxBool CarRace::Escape()
|
||||
NavController()->SetDeadZone(NavController()->GetDefaultDeadZone());
|
||||
|
||||
NavController()->SetTrackDefault(1);
|
||||
LegoRaceCar::FUN_10012de0();
|
||||
LegoRaceCar::InitYouCantStopSound();
|
||||
|
||||
GameState()->GetBackgroundColor()->SetValue("reset");
|
||||
m_destLocation = LegoGameState::e_infomain;
|
||||
|
||||
@ -132,7 +132,7 @@ MxLong JetskiRace::HandleClick(LegoEventNotificationParam& p_param)
|
||||
m_act1State->m_unk0x018 = 0;
|
||||
VariableTable()->SetVariable(g_raceState, "");
|
||||
VariableTable()->SetVariable(g_strHIT_WALL_SOUND, "");
|
||||
LegoRaceCar::FUN_10012de0();
|
||||
LegoRaceCar::InitYouCantStopSound();
|
||||
m_destLocation = LegoGameState::e_jetraceExterior;
|
||||
TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE);
|
||||
break;
|
||||
@ -140,7 +140,7 @@ MxLong JetskiRace::HandleClick(LegoEventNotificationParam& p_param)
|
||||
m_act1State->m_unk0x018 = 0;
|
||||
VariableTable()->SetVariable(g_raceState, "");
|
||||
VariableTable()->SetVariable(g_strHIT_WALL_SOUND, "");
|
||||
LegoRaceCar::FUN_10012de0();
|
||||
LegoRaceCar::InitYouCantStopSound();
|
||||
m_destLocation = LegoGameState::e_infomain;
|
||||
result = 1;
|
||||
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_strHIT_WALL_SOUND, "");
|
||||
LegoRaceCar::FUN_10012de0();
|
||||
LegoRaceCar::InitYouCantStopSound();
|
||||
m_raceState->m_unk0x28 = 2;
|
||||
|
||||
RaceState::Entry* raceStateEntry = m_raceState->GetState(GameState()->GetActorId());
|
||||
@ -294,6 +294,6 @@ MxBool JetskiRace::Escape()
|
||||
VariableTable()->SetVariable(g_raceState, "");
|
||||
VariableTable()->SetVariable(g_strHIT_WALL_SOUND, "");
|
||||
m_destLocation = LegoGameState::e_infomain;
|
||||
LegoRaceCar::FUN_10012de0();
|
||||
LegoRaceCar::InitYouCantStopSound();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -31,8 +31,8 @@ MxS32 LegoRaceActor::VTable0x68(Vector3& p_v1, Vector3& p_v2, Vector3& p_v3)
|
||||
|
||||
if (m_userNavFlag && result) {
|
||||
MxLong time = Timer()->GetTime();
|
||||
if (time - g_unk0x100f3308 > 1000) {
|
||||
g_unk0x100f3308 = time;
|
||||
if (time - g_timeLastHitSoundPlayed > 1000) {
|
||||
g_timeLastHitSoundPlayed = time;
|
||||
const char* soundKey = VariableTable()->GetVariable(g_strHIT_ACTOR_SOUND);
|
||||
|
||||
if (soundKey && *soundKey) {
|
||||
|
||||
@ -178,7 +178,7 @@ LegoRaceCar::LegoRaceCar()
|
||||
m_skelKick1Anim = 0;
|
||||
m_skelKick2Anim = 0;
|
||||
m_unk0x5c.Clear();
|
||||
m_unk0x58 = 0;
|
||||
m_kickStart = 0;
|
||||
m_kick1B = 0;
|
||||
m_kick2B = 0;
|
||||
NotificationManager()->Register(this);
|
||||
@ -201,10 +201,10 @@ MxLong LegoRaceCar::Notify(MxParam& p_param)
|
||||
// Initialized at LEGO1 0x10012db0
|
||||
// GLOBAL: LEGO1 0x10102af0
|
||||
// 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
|
||||
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
|
||||
g_playedYouCantStopSound = TRUE;
|
||||
@ -229,7 +229,7 @@ void LegoRaceCar::InitSoundIndices()
|
||||
void LegoRaceCar::SetWorldSpeed(MxFloat p_worldSpeed)
|
||||
{
|
||||
if (!m_userNavFlag) {
|
||||
if (!LegoCarRaceActor::m_unk0x0c) {
|
||||
if (!LegoCarRaceActor::m_animState) {
|
||||
m_maxLinearVel = p_worldSpeed;
|
||||
}
|
||||
LegoAnimActor::SetWorldSpeed(p_worldSpeed);
|
||||
@ -244,7 +244,7 @@ void LegoRaceCar::SetWorldSpeed(MxFloat p_worldSpeed)
|
||||
void LegoRaceCar::SetMaxLinearVelocity(float p_maxLinearVelocity)
|
||||
{
|
||||
if (p_maxLinearVelocity < 0) {
|
||||
LegoCarRaceActor::m_unk0x0c = 2;
|
||||
LegoCarRaceActor::m_animState = 2;
|
||||
m_maxLinearVel = 0;
|
||||
SetWorldSpeed(0);
|
||||
}
|
||||
@ -299,7 +299,7 @@ void LegoRaceCar::ParseAction(char* p_extra)
|
||||
|
||||
// FUNCTION: LEGO1 0x10012ff0
|
||||
// FUNCTION: BETA10 0x100cb60e
|
||||
void LegoRaceCar::FUN_10012ff0(float p_param)
|
||||
void LegoRaceCar::KickCamera(float p_param)
|
||||
{
|
||||
LegoAnimActorStruct* a; // called `a` in BETA10
|
||||
float deltaTime;
|
||||
@ -315,7 +315,7 @@ void LegoRaceCar::FUN_10012ff0(float p_param)
|
||||
assert(a && a->GetAnimTreePtr() && a->GetAnimTreePtr()->GetCamAnim());
|
||||
|
||||
if (a->GetAnimTreePtr()) {
|
||||
deltaTime = p_param - m_unk0x58;
|
||||
deltaTime = p_param - m_kickStart;
|
||||
|
||||
if (a->GetDuration() <= deltaTime || deltaTime < 0.0) {
|
||||
if (m_userState == LEGORACECAR_KICK1) {
|
||||
@ -390,7 +390,7 @@ MxU32 LegoRaceCar::HandleSkeletonKicks(float p_param1)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
m_unk0x58 = p_param1;
|
||||
m_kickStart = p_param1;
|
||||
SoundManager()->GetCacheSoundManager()->Play(g_soundSkel3, NULL, FALSE);
|
||||
|
||||
return TRUE;
|
||||
@ -401,7 +401,7 @@ MxU32 LegoRaceCar::HandleSkeletonKicks(float p_param1)
|
||||
void LegoRaceCar::Animate(float p_time)
|
||||
{
|
||||
if (m_userNavFlag && (m_userState == LEGORACECAR_KICK1 || m_userState == LEGORACECAR_KICK2)) {
|
||||
FUN_10012ff0(p_time);
|
||||
KickCamera(p_time);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -413,7 +413,7 @@ void LegoRaceCar::Animate(float p_time)
|
||||
}
|
||||
}
|
||||
|
||||
if (LegoCarRaceActor::m_unk0x0c == 1) {
|
||||
if (LegoCarRaceActor::m_animState == 1) {
|
||||
FUN_1005d4b0();
|
||||
|
||||
if (!m_userNavFlag) {
|
||||
@ -471,7 +471,7 @@ MxResult LegoRaceCar::HitActor(LegoPathActor* p_actor, MxBool p_bool)
|
||||
assert(roi);
|
||||
matr = roi->GetLocal2World();
|
||||
|
||||
Vector3(matr[3]) += g_unk0x10102af0;
|
||||
Vector3(matr[3]) += g_hitOffset;
|
||||
roi->SetLocal2World(matr);
|
||||
|
||||
p_actor->SetActorState(c_two);
|
||||
@ -516,7 +516,7 @@ MxResult LegoRaceCar::HitActor(LegoPathActor* p_actor, MxBool p_bool)
|
||||
|
||||
if (soundKey) {
|
||||
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)
|
||||
{
|
||||
if (!m_userNavFlag) {
|
||||
if (!LegoCarRaceActor::m_unk0x0c) {
|
||||
if (!LegoCarRaceActor::m_animState) {
|
||||
m_maxLinearVel = p_worldSpeed;
|
||||
}
|
||||
LegoAnimActor::SetWorldSpeed(p_worldSpeed);
|
||||
@ -597,7 +597,7 @@ void LegoJetski::SetWorldSpeed(MxFloat p_worldSpeed)
|
||||
void LegoJetski::FUN_100136f0(float p_worldSpeed)
|
||||
{
|
||||
if (p_worldSpeed < 0) {
|
||||
LegoCarRaceActor::m_unk0x0c = 2;
|
||||
LegoCarRaceActor::m_animState = 2;
|
||||
m_maxLinearVel = 0;
|
||||
SetWorldSpeed(0);
|
||||
}
|
||||
@ -612,7 +612,7 @@ void LegoJetski::Animate(float p_time)
|
||||
{
|
||||
LegoJetskiRaceActor::Animate(p_time);
|
||||
|
||||
if (LegoCarRaceActor::m_unk0x0c == 1) {
|
||||
if (LegoCarRaceActor::m_animState == 1) {
|
||||
FUN_1005d4b0();
|
||||
|
||||
if (!m_userNavFlag) {
|
||||
@ -685,7 +685,7 @@ MxResult LegoJetski::HitActor(LegoPathActor* p_actor, MxBool p_bool)
|
||||
LegoROI* roi = p_actor->GetROI();
|
||||
matr = roi->GetLocal2World();
|
||||
|
||||
Vector3(matr[3]) += g_unk0x10102af0;
|
||||
Vector3(matr[3]) += g_hitOffset;
|
||||
roi->SetLocal2World(matr);
|
||||
|
||||
p_actor->SetActorState(c_two);
|
||||
@ -714,7 +714,7 @@ MxResult LegoJetski::HitActor(LegoPathActor* p_actor, MxBool p_bool)
|
||||
|
||||
if (soundKey) {
|
||||
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_unk0x70 = 0.0f;
|
||||
m_unk0x0c = 0;
|
||||
m_animState = 0;
|
||||
m_maxLinearVel = 0.0f;
|
||||
m_frequencyFactor = 1.0f;
|
||||
m_unk0x1c = 0;
|
||||
@ -224,18 +224,18 @@ void LegoCarRaceActor::SwitchBoundary(LegoPathBoundary*& p_boundary, LegoOriente
|
||||
// FUNCTION: BETA10 0x100cdbae
|
||||
void LegoCarRaceActor::Animate(float p_time)
|
||||
{
|
||||
// m_unk0x0c is not an MxBool, there are places where it is set to 2 or higher
|
||||
if (m_unk0x0c == 0) {
|
||||
// m_animState is not an MxBool, there are places where it is set to 2 or higher
|
||||
if (m_animState == 0) {
|
||||
const char* value = VariableTable()->GetVariable(g_raceState);
|
||||
|
||||
if (SDL_strcasecmp(value, g_racing) == 0) {
|
||||
m_unk0x0c = 1;
|
||||
m_animState = 1;
|
||||
m_lastTime = p_time - 1.0f;
|
||||
m_unk0x1c = p_time;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_unk0x0c == 1) {
|
||||
if (m_animState == 1) {
|
||||
LegoAnimActor::Animate(p_time);
|
||||
}
|
||||
}
|
||||
@ -399,10 +399,10 @@ MxS32 LegoJetskiRaceActor::VTable0x1c(LegoPathBoundary* p_boundary, LegoEdge* p_
|
||||
// FUNCTION: LEGO1 0x10081550
|
||||
void LegoJetskiRaceActor::Animate(float p_time)
|
||||
{
|
||||
if (m_unk0x0c == 0) {
|
||||
if (m_animState == 0) {
|
||||
const LegoChar* raceState = VariableTable()->GetVariable(g_raceState);
|
||||
if (!SDL_strcasecmp(raceState, g_racing)) {
|
||||
m_unk0x0c = 1;
|
||||
m_animState = 1;
|
||||
m_lastTime = p_time - 1.0f;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -793,7 +793,7 @@ void LegoAnimPresenter::StartingTickle()
|
||||
}
|
||||
|
||||
FUN_10069b10();
|
||||
FUN_1006c8a0(TRUE);
|
||||
SetDisabled(TRUE);
|
||||
|
||||
if (m_unk0x78 == NULL) {
|
||||
if (fabs(m_action->GetDirection()[0]) >= 0.00000047683716F ||
|
||||
@ -1093,7 +1093,7 @@ void LegoAnimPresenter::EndAction()
|
||||
}
|
||||
}
|
||||
|
||||
FUN_1006c8a0(FALSE);
|
||||
SetDisabled(FALSE);
|
||||
FUN_1006ab70();
|
||||
VTable0x90();
|
||||
|
||||
@ -1154,18 +1154,18 @@ void LegoAnimPresenter::VTable0x90()
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1006c8a0
|
||||
void LegoAnimPresenter::FUN_1006c8a0(MxBool p_bool)
|
||||
void LegoAnimPresenter::SetDisabled(MxBool p_disabled)
|
||||
{
|
||||
if (m_roiMapSize != 0 && m_roiMap != NULL) {
|
||||
for (MxU32 i = 1; i <= m_roiMapSize; i++) {
|
||||
LegoEntity* entity = m_roiMap[i]->GetEntity();
|
||||
|
||||
if (entity != NULL) {
|
||||
if (p_bool) {
|
||||
entity->SetUnknown0x10Flag(LegoEntity::c_altBit1);
|
||||
if (p_disabled) {
|
||||
entity->SetInteractionFlag(LegoEntity::c_disabled);
|
||||
}
|
||||
else {
|
||||
entity->ClearUnknown0x10Flag(LegoEntity::c_altBit1);
|
||||
entity->ClearInteractionFlag(LegoEntity::c_disabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,7 +48,7 @@ Hospital::Hospital()
|
||||
m_flashingLeds = 0;
|
||||
m_copLedAnimTimer = 0;
|
||||
m_pizzaLedAnimTimer = 0;
|
||||
m_unk0x128 = 0;
|
||||
m_exited = FALSE;
|
||||
NotificationManager()->Register(this);
|
||||
}
|
||||
|
||||
@ -369,8 +369,8 @@ MxLong Hospital::HandleEndAction(MxEndActionNotificationParam& p_param)
|
||||
act1State = (Act1State*) GameState()->GetState("Act1State");
|
||||
act1State->SetUnknown18(9);
|
||||
case HospitalState::e_exitToFront:
|
||||
if (m_unk0x128 == 0) {
|
||||
m_unk0x128 = 1;
|
||||
if (m_exited == FALSE) {
|
||||
m_exited = TRUE;
|
||||
m_destLocation = LegoGameState::e_hospitalExited;
|
||||
|
||||
DeleteObjects(&m_atomId, HospitalScript::c_hho002cl_RunAnim, HospitalScript::c_hho006cl_RunAnim);
|
||||
@ -378,8 +378,8 @@ MxLong Hospital::HandleEndAction(MxEndActionNotificationParam& p_param)
|
||||
}
|
||||
break;
|
||||
case HospitalState::e_exitToInfocenter:
|
||||
if (m_unk0x128 == 0) {
|
||||
m_unk0x128 = 1;
|
||||
if (m_exited == FALSE) {
|
||||
m_exited = TRUE;
|
||||
m_destLocation = LegoGameState::e_infomain;
|
||||
|
||||
DeleteObjects(&m_atomId, HospitalScript::c_hho002cl_RunAnim, HospitalScript::c_hho006cl_RunAnim);
|
||||
@ -412,8 +412,8 @@ MxLong Hospital::HandleButtonDown(LegoControlManagerNotificationParam& p_param)
|
||||
m_interactionMode = 3;
|
||||
|
||||
if (m_hospitalState->m_state == HospitalState::e_explainQuestShort) {
|
||||
if (m_unk0x128 == 0) {
|
||||
m_unk0x128 = 1;
|
||||
if (m_exited == FALSE) {
|
||||
m_exited = TRUE;
|
||||
|
||||
TickleManager()->UnregisterClient(this);
|
||||
|
||||
@ -568,8 +568,8 @@ MxBool Hospital::HandleControl(LegoControlManagerNotificationParam& p_param)
|
||||
m_currentAction = HospitalScript::c_hho016cl_RunAnim;
|
||||
m_setWithCurrentAction = 1;
|
||||
}
|
||||
else if (m_unk0x128 == 0) {
|
||||
m_unk0x128 = 1;
|
||||
else if (m_exited == FALSE) {
|
||||
m_exited = TRUE;
|
||||
m_hospitalState->m_state = HospitalState::e_exitImmediately;
|
||||
m_destLocation = LegoGameState::e_infomain;
|
||||
|
||||
@ -589,8 +589,8 @@ MxBool Hospital::HandleControl(LegoControlManagerNotificationParam& p_param)
|
||||
m_currentAction = HospitalScript::c_hho016cl_RunAnim;
|
||||
m_setWithCurrentAction = 1;
|
||||
}
|
||||
else if (m_unk0x128 == 0) {
|
||||
m_unk0x128 = 1;
|
||||
else if (m_exited == FALSE) {
|
||||
m_exited = TRUE;
|
||||
m_hospitalState->m_state = HospitalState::e_exitImmediately;
|
||||
m_destLocation = LegoGameState::e_hospitalExited;
|
||||
|
||||
|
||||
@ -306,29 +306,32 @@ MxLong Infocenter::HandleEndAction(MxEndActionNotificationParam& p_param)
|
||||
|
||||
if (!m_unk0x1d4) {
|
||||
PlayMusic(JukeboxScript::c_InformationCenter_Music);
|
||||
GameState()->SetActor(m_selectedCharacter);
|
||||
|
||||
switch (m_selectedCharacter) {
|
||||
case e_pepper:
|
||||
PlayAction(InfomainScript::c_avo901in_RunAnim);
|
||||
break;
|
||||
case e_mama:
|
||||
PlayAction(InfomainScript::c_avo902in_RunAnim);
|
||||
break;
|
||||
case e_papa:
|
||||
PlayAction(InfomainScript::c_avo903in_RunAnim);
|
||||
break;
|
||||
case e_nick:
|
||||
PlayAction(InfomainScript::c_avo904in_RunAnim);
|
||||
break;
|
||||
case e_laura:
|
||||
PlayAction(InfomainScript::c_avo905in_RunAnim);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
if (!Lego()->IsVersion10()) {
|
||||
GameState()->SetActor(m_selectedCharacter);
|
||||
|
||||
switch (m_selectedCharacter) {
|
||||
case e_pepper:
|
||||
PlayAction(InfomainScript::c_avo901in_RunAnim);
|
||||
break;
|
||||
case e_mama:
|
||||
PlayAction(InfomainScript::c_avo902in_RunAnim);
|
||||
break;
|
||||
case e_papa:
|
||||
PlayAction(InfomainScript::c_avo903in_RunAnim);
|
||||
break;
|
||||
case e_nick:
|
||||
PlayAction(InfomainScript::c_avo904in_RunAnim);
|
||||
break;
|
||||
case e_laura:
|
||||
PlayAction(InfomainScript::c_avo905in_RunAnim);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
UpdateFrameHot(TRUE);
|
||||
}
|
||||
|
||||
UpdateFrameHot(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -338,7 +341,7 @@ MxLong Infocenter::HandleEndAction(MxEndActionNotificationParam& p_param)
|
||||
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);
|
||||
m_unk0x1d6 = 0;
|
||||
}
|
||||
@ -478,7 +481,7 @@ void Infocenter::ReadyWorld()
|
||||
InfomainScript::Script script = m_infocenterState->GetNextReturnDialogue();
|
||||
PlayAction(script);
|
||||
|
||||
if (script == InfomainScript::c_iicx26in_RunAnim) {
|
||||
if (script == InfomainScript::c_iicx26in_RunAnim - Lego()->IsVersion10()) {
|
||||
m_unk0x1d6 = 1;
|
||||
}
|
||||
|
||||
@ -1186,13 +1189,13 @@ MxLong Infocenter::HandleNotification0(MxNotificationParam& p_param)
|
||||
m_currentInfomainScript == InfomainScript::c_Pepper_All_Movie ||
|
||||
m_currentInfomainScript == InfomainScript::c_Nick_All_Movie ||
|
||||
m_currentInfomainScript == InfomainScript::c_Laura_All_Movie ||
|
||||
m_currentInfomainScript == InfomainScript::c_iic007ra_PlayWav ||
|
||||
m_currentInfomainScript == InfomainScript::c_ijs002ra_PlayWav ||
|
||||
m_currentInfomainScript == InfomainScript::c_irt001ra_PlayWav ||
|
||||
m_currentInfomainScript == InfomainScript::c_ipz006ra_PlayWav ||
|
||||
m_currentInfomainScript == InfomainScript::c_igs004ra_PlayWav ||
|
||||
m_currentInfomainScript == InfomainScript::c_iho003ra_PlayWav ||
|
||||
m_currentInfomainScript == InfomainScript::c_ips005ra_PlayWav) {
|
||||
m_currentInfomainScript == InfomainScript::c_iic007ra_PlayWav - Lego()->IsVersion10() ||
|
||||
m_currentInfomainScript == InfomainScript::c_ijs002ra_PlayWav - Lego()->IsVersion10() ||
|
||||
m_currentInfomainScript == InfomainScript::c_irt001ra_PlayWav - Lego()->IsVersion10() ||
|
||||
m_currentInfomainScript == InfomainScript::c_ipz006ra_PlayWav - Lego()->IsVersion10() ||
|
||||
m_currentInfomainScript == InfomainScript::c_igs004ra_PlayWav - Lego()->IsVersion10() ||
|
||||
m_currentInfomainScript == InfomainScript::c_iho003ra_PlayWav - Lego()->IsVersion10() ||
|
||||
m_currentInfomainScript == InfomainScript::c_ips005ra_PlayWav - Lego()->IsVersion10()) {
|
||||
StopCurrentAction();
|
||||
}
|
||||
}
|
||||
@ -1506,6 +1509,17 @@ void Infocenter::StopCredits()
|
||||
// FUNCTION: BETA10 0x1002ee8c
|
||||
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;
|
||||
action.SetObjectId(p_script);
|
||||
action.SetAtomId(*g_infomainScript);
|
||||
|
||||
@ -810,7 +810,7 @@ void Isle::Enable(MxBool p_enable)
|
||||
AnimationManager()->EnableCamAnims(FALSE);
|
||||
|
||||
g_isleFlags &= ~c_playMusic;
|
||||
m_ambulance->FUN_10036e60();
|
||||
m_ambulance->Init();
|
||||
break;
|
||||
case 11:
|
||||
m_act1state->m_unk0x018 = 0;
|
||||
@ -1209,7 +1209,7 @@ MxBool Isle::Escape()
|
||||
case 10:
|
||||
if (UserActor() != NULL && !UserActor()->IsA("Ambulance")) {
|
||||
m_ambulance->StopActions();
|
||||
m_ambulance->FUN_10037250();
|
||||
m_ambulance->Reset();
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1250,7 +1250,7 @@ void Isle::FUN_10033350()
|
||||
if (m_act1state->m_unk0x018 == 10) {
|
||||
if (UserActor() != NULL && !UserActor()->IsA("Ambulance")) {
|
||||
m_ambulance->StopActions();
|
||||
m_ambulance->FUN_10037250();
|
||||
m_ambulance->Reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -254,7 +254,7 @@ void Score::Paint()
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
desc.dwSize = sizeof(desc);
|
||||
|
||||
HRESULT result = cube->m_surface->Lock(NULL, &desc, DDLOCK_SURFACEMEMORYPTR, NULL);
|
||||
HRESULT result = cube->m_surface->Lock(NULL, &desc, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WRITEONLY, NULL);
|
||||
if (result == DD_OK) {
|
||||
if (desc.lPitch != desc.dwWidth) {
|
||||
cube->m_surface->Unlock(desc.lpSurface);
|
||||
|
||||
@ -154,7 +154,7 @@ double Lego3DView::Render(double p_und)
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ab2b0
|
||||
ViewROI* Lego3DView::Pick(unsigned int x, unsigned int y)
|
||||
ViewROI* Lego3DView::Pick(int x, int y)
|
||||
{
|
||||
return m_pViewManager->Pick(GetView(), x, y);
|
||||
}
|
||||
|
||||
@ -27,7 +27,7 @@ class Lego3DView : public LegoView1 {
|
||||
|
||||
double Render(double p_und);
|
||||
|
||||
ViewROI* Pick(unsigned int x, unsigned int y);
|
||||
ViewROI* Pick(int x, int y);
|
||||
|
||||
ViewROI* GetPointOfView();
|
||||
ViewManager* GetViewManager();
|
||||
|
||||
@ -22,7 +22,7 @@ LegoTextureInfo* LegoTextureContainer::GetCached(LegoTextureInfo* p_textureInfo)
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
desc.dwSize = sizeof(desc);
|
||||
|
||||
if (p_textureInfo->m_surface->Lock(NULL, &desc, DDLOCK_SURFACEMEMORYPTR, NULL) == DD_OK) {
|
||||
if (p_textureInfo->m_surface->Lock(NULL, &desc, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WRITEONLY, NULL) == DD_OK) {
|
||||
width = desc.dwWidth;
|
||||
height = desc.dwHeight;
|
||||
p_textureInfo->m_surface->Unlock(desc.lpSurface);
|
||||
@ -35,7 +35,7 @@ LegoTextureInfo* LegoTextureContainer::GetCached(LegoTextureInfo* p_textureInfo)
|
||||
memset(&newDesc, 0, sizeof(newDesc));
|
||||
newDesc.dwSize = sizeof(newDesc);
|
||||
|
||||
if (surface->Lock(NULL, &newDesc, DDLOCK_SURFACEMEMORYPTR, NULL) == DD_OK) {
|
||||
if (surface->Lock(NULL, &newDesc, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WRITEONLY, NULL) == DD_OK) {
|
||||
BOOL und = FALSE;
|
||||
if (newDesc.dwWidth == width && newDesc.dwHeight == height) {
|
||||
und = TRUE;
|
||||
|
||||
@ -353,7 +353,7 @@ LegoResult LegoLOD::SetTextureInfo(LegoTextureInfo* p_textureInfo)
|
||||
}
|
||||
|
||||
// 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++) {
|
||||
if (m_melems[i].m_textured) {
|
||||
|
||||
@ -31,7 +31,7 @@ class LegoLOD : public ViewLOD {
|
||||
LegoLOD* Clone(Tgl::Renderer* p_renderer);
|
||||
LegoResult SetColor(LegoFloat p_red, LegoFloat p_green, LegoFloat p_blue, LegoFloat p_alpha);
|
||||
LegoResult SetTextureInfo(LegoTextureInfo* p_textureInfo);
|
||||
LegoResult FUN_100aad70(LegoTextureInfo* p_textureInfo);
|
||||
LegoResult UpdateTextureInfo(LegoTextureInfo* p_textureInfo);
|
||||
void ClearMeshOffset();
|
||||
LegoResult GetTextureInfo(LegoTextureInfo*& p_textureInfo);
|
||||
|
||||
|
||||
@ -174,7 +174,7 @@ BOOL MxDirect3D::D3DSetMode()
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
desc.dwSize = sizeof(desc);
|
||||
|
||||
if (backBuffer->Lock(NULL, &desc, DDLOCK_WAIT, NULL) == DD_OK) {
|
||||
if (backBuffer->Lock(NULL, &desc, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL) == DD_OK) {
|
||||
unsigned char* surface = (unsigned char*) desc.lpSurface;
|
||||
|
||||
for (int i = 0; i < mode.height; i++) {
|
||||
@ -192,7 +192,7 @@ BOOL MxDirect3D::D3DSetMode()
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
desc.dwSize = sizeof(desc);
|
||||
|
||||
if (frontBuffer->Lock(NULL, &desc, DDLOCK_WAIT, NULL) == DD_OK) {
|
||||
if (frontBuffer->Lock(NULL, &desc, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL) == DD_OK) {
|
||||
unsigned char* surface = (unsigned char*) desc.lpSurface;
|
||||
|
||||
for (int i = 0; i < mode.height; i++) {
|
||||
|
||||
@ -539,10 +539,10 @@ void MxDirectDraw::ClearBackBuffers()
|
||||
memset(&ddsd, 0, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
|
||||
result = m_pBackBuffer->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL);
|
||||
result = m_pBackBuffer->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
|
||||
if (result == DDERR_SURFACELOST) {
|
||||
m_pBackBuffer->Restore();
|
||||
result = m_pBackBuffer->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL);
|
||||
result = m_pBackBuffer->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
|
||||
}
|
||||
|
||||
if (result != DD_OK) {
|
||||
|
||||
@ -20,10 +20,10 @@ class MxString : public MxCore {
|
||||
void ToLowerCase();
|
||||
void MapPathToFilesystem() { MapPathToFilesystem(m_data); }
|
||||
|
||||
MxString& operator=(const MxString& p_str);
|
||||
const MxString& operator=(const char* p_str);
|
||||
MxString operator+(const MxString& p_str) const;
|
||||
MxString operator+(const char* p_str) const;
|
||||
LEGO1_EXPORT MxString& operator=(const MxString& p_str);
|
||||
LEGO1_EXPORT const MxString& operator=(const char* p_str);
|
||||
LEGO1_EXPORT MxString operator+(const MxString& p_str) const;
|
||||
LEGO1_EXPORT MxString operator+(const char* p_str) const;
|
||||
LEGO1_EXPORT MxString& operator+=(const char* p_str);
|
||||
|
||||
static void CharSwap(char* p_a, char* p_b);
|
||||
|
||||
@ -9,6 +9,8 @@
|
||||
#include "mxticklethread.h"
|
||||
#include "mxwavepresenter.h"
|
||||
|
||||
#include <SDL3/SDL_log.h>
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxSoundManager, 0x3c);
|
||||
|
||||
// GLOBAL LEGO1 0x10101420
|
||||
@ -98,12 +100,17 @@ MxResult MxSoundManager::Create(MxU32 p_frequencyMS, MxBool p_createThread)
|
||||
spec.format = SDL_AUDIO_F32;
|
||||
spec.channels = ma_engine_get_channels(m_engine);
|
||||
|
||||
if ((m_stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &spec, &AudioStreamCallback, this)) ==
|
||||
if ((m_stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &spec, &AudioStreamCallback, this)) !=
|
||||
NULL) {
|
||||
goto done;
|
||||
SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(m_stream));
|
||||
}
|
||||
else {
|
||||
SDL_LogError(
|
||||
SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Failed to open default audio device for playback: %s",
|
||||
SDL_GetError()
|
||||
);
|
||||
}
|
||||
|
||||
SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(m_stream));
|
||||
|
||||
if (p_createThread) {
|
||||
m_thread = new MxTickleThread(this, p_frequencyMS);
|
||||
|
||||
@ -402,10 +402,10 @@ void MxDisplaySurface::VTable0x28(
|
||||
memset(&ddsd, 0, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
|
||||
HRESULT hr = m_ddSurface2->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL);
|
||||
HRESULT hr = m_ddSurface2->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
|
||||
if (hr == DDERR_SURFACELOST) {
|
||||
m_ddSurface2->Restore();
|
||||
hr = m_ddSurface2->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL);
|
||||
hr = m_ddSurface2->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
|
||||
}
|
||||
|
||||
if (hr != DD_OK) {
|
||||
@ -514,10 +514,10 @@ void MxDisplaySurface::VTable0x30(
|
||||
memset(&ddsd, 0, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
|
||||
HRESULT hr = m_ddSurface2->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL);
|
||||
HRESULT hr = m_ddSurface2->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
|
||||
if (hr == DDERR_SURFACELOST) {
|
||||
m_ddSurface2->Restore();
|
||||
hr = m_ddSurface2->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL);
|
||||
hr = m_ddSurface2->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
|
||||
}
|
||||
|
||||
if (hr != DD_OK) {
|
||||
@ -726,11 +726,11 @@ void MxDisplaySurface::VTable0x34(MxU8* p_pixels, MxS32 p_bpp, MxS32 p_width, Mx
|
||||
memset(&surfaceDesc, 0, sizeof(surfaceDesc));
|
||||
surfaceDesc.dwSize = sizeof(surfaceDesc);
|
||||
|
||||
HRESULT result = m_ddSurface2->Lock(NULL, &surfaceDesc, DDLOCK_WAIT, NULL);
|
||||
HRESULT result = m_ddSurface2->Lock(NULL, &surfaceDesc, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
|
||||
|
||||
if (result == DDERR_SURFACELOST) {
|
||||
m_ddSurface2->Restore();
|
||||
result = m_ddSurface2->Lock(NULL, &surfaceDesc, DDLOCK_WAIT, NULL);
|
||||
result = m_ddSurface2->Lock(NULL, &surfaceDesc, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
|
||||
}
|
||||
|
||||
if (result == DD_OK) {
|
||||
@ -784,7 +784,7 @@ void MxDisplaySurface::Display(MxS32 p_left, MxS32 p_top, MxS32 p_left2, MxS32 p
|
||||
DDSURFACEDESC ddsd;
|
||||
memset(&ddsd, 0, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
if (m_ddSurface2->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL) == DD_OK) {
|
||||
if (m_ddSurface2->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL) == DD_OK) {
|
||||
MxU8* surface = (MxU8*) ddsd.lpSurface;
|
||||
MxS32 height = m_videoParam.GetRect().GetHeight();
|
||||
|
||||
@ -891,7 +891,7 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::VTable0x44(
|
||||
memset(&ddsd, 0, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
|
||||
if (surface->Lock(NULL, &ddsd, DDLOCK_WAIT, 0) != DD_OK) {
|
||||
if (surface->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, 0) != DD_OK) {
|
||||
surface->Release();
|
||||
surface = NULL;
|
||||
}
|
||||
@ -1067,7 +1067,7 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::CreateCursorSurface()
|
||||
memset(&ddsd, 0, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
|
||||
if (newSurface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL) != DD_OK) {
|
||||
if (newSurface->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL) != DD_OK) {
|
||||
goto done;
|
||||
}
|
||||
else {
|
||||
|
||||
@ -252,8 +252,8 @@ class ViewImpl : public View {
|
||||
Result TransformWorldToScreen(const float world[3], float screen[4]) override;
|
||||
Result TransformScreenToWorld(const float screen[4], float world[3]) override;
|
||||
Result Pick(
|
||||
unsigned int x,
|
||||
unsigned int y,
|
||||
int x,
|
||||
int y,
|
||||
const Group** ppGroupsToPickFrom,
|
||||
int groupsToPickFromCount,
|
||||
const Group**& rppPickedGroups,
|
||||
@ -277,8 +277,8 @@ class ViewImpl : public View {
|
||||
Result SetCamera(const CameraImpl& rCamera);
|
||||
Result Render(const GroupImpl& rScene);
|
||||
Result Pick(
|
||||
unsigned int x,
|
||||
unsigned int y,
|
||||
int x,
|
||||
int y,
|
||||
const GroupImpl** ppGroupsToPickFrom,
|
||||
int groupsToPickFromCount,
|
||||
const Group**& rppPickedGroups,
|
||||
|
||||
@ -495,8 +495,8 @@ Result ViewImpl::ForceUpdate(unsigned int x, unsigned int y, unsigned int width,
|
||||
|
||||
// FUNCTION: BETA10 0x101710f0
|
||||
inline Result ViewImpl::Pick(
|
||||
unsigned int x,
|
||||
unsigned int y,
|
||||
int x,
|
||||
int y,
|
||||
const GroupImpl** ppGroupsToPickFrom,
|
||||
int groupsToPickFromCount,
|
||||
const Group**& rppPickedGroups,
|
||||
@ -519,8 +519,8 @@ inline Result ViewImpl::Pick(
|
||||
// FUNCTION: LEGO1 0x100a30c0
|
||||
// FUNCTION: BETA10 0x1016ee10
|
||||
Result ViewImpl::Pick(
|
||||
unsigned int x,
|
||||
unsigned int y,
|
||||
int x,
|
||||
int y,
|
||||
const Group** ppGroupsToPickFrom,
|
||||
int groupsToPickFromCount,
|
||||
const Group**& rppPickedGroups,
|
||||
|
||||
@ -257,8 +257,8 @@ class View : public Object {
|
||||
// output parameter
|
||||
// size of rppPickedGroups
|
||||
virtual Result Pick(
|
||||
unsigned int x,
|
||||
unsigned int y,
|
||||
int x,
|
||||
int y,
|
||||
const Group** ppGroupsToPickFrom,
|
||||
int groupsToPickFromCount,
|
||||
const Group**& rppPickedGroups,
|
||||
|
||||
@ -499,7 +499,7 @@ float ViewManager::ProjectedSize(const BoundingSphere& p_bounding_sphere)
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100a6e00
|
||||
ViewROI* ViewManager::Pick(Tgl::View* p_view, unsigned int x, unsigned int y)
|
||||
ViewROI* ViewManager::Pick(Tgl::View* p_view, int x, int y)
|
||||
{
|
||||
LPDIRECT3DRMPICKEDARRAY picked = NULL;
|
||||
ViewROI* result = NULL;
|
||||
|
||||
@ -33,7 +33,7 @@ class ViewManager {
|
||||
void RemoveROIDetailFromScene(ViewROI* p_roi);
|
||||
void SetPOVSource(const OrientableROI* point_of_view);
|
||||
float ProjectedSize(const BoundingSphere& p_bounding_sphere);
|
||||
ViewROI* Pick(Tgl::View* p_view, unsigned int x, unsigned int y);
|
||||
ViewROI* Pick(Tgl::View* p_view, int x, int y);
|
||||
void SetResolution(int width, int height);
|
||||
void SetFrustrum(float fov, float front, float back);
|
||||
inline void ManageVisibilityAndDetailRecursively(ViewROI* p_from, int p_lodLevel);
|
||||
|
||||
@ -27,15 +27,21 @@ add_library(miniwin STATIC EXCLUDE_FROM_ALL
|
||||
src/d3drm/backends/software/renderer.cpp
|
||||
)
|
||||
|
||||
target_compile_definitions(miniwin PRIVATE
|
||||
$<$<CONFIG:Debug>:DEBUG>
|
||||
)
|
||||
|
||||
find_package(OpenGL)
|
||||
find_package(GLEW)
|
||||
if(OpenGL_FOUND AND GLEW_FOUND)
|
||||
message(STATUS "Found OpenGL and GLEW: enabling OpenGL 1.x renderer")
|
||||
target_sources(miniwin PRIVATE src/d3drm/backends/opengl1/renderer.cpp)
|
||||
if(OpenGL_FOUND)
|
||||
message(STATUS "Found OpenGL: enabling OpenGL 1.x renderer")
|
||||
target_sources(miniwin PRIVATE
|
||||
src/d3drm/backends/opengl1/actual.cpp
|
||||
src/d3drm/backends/opengl1/renderer.cpp
|
||||
)
|
||||
target_compile_definitions(miniwin PRIVATE USE_OPENGL1)
|
||||
target_link_libraries(miniwin PRIVATE OpenGL::GL GLEW::GLEW)
|
||||
target_link_libraries(miniwin PRIVATE OpenGL::GL)
|
||||
else()
|
||||
message(STATUS "🧩 OpenGL 1.x support not enabled — needs OpenGL and GLEW")
|
||||
message(STATUS "🧩 OpenGL 1.x support not enabled — needs OpenGL")
|
||||
endif()
|
||||
|
||||
find_library(OPENGL_ES2_LIBRARY NAMES GLESv2)
|
||||
|
||||
@ -159,12 +159,15 @@ enum class DDBltFastFlags : uint32_t {
|
||||
};
|
||||
ENABLE_BITMASK_OPERATORS(DDBltFastFlags)
|
||||
|
||||
#define DDLOCK_WAIT DDLockFlags::WAIT
|
||||
#define DDLOCK_SURFACEMEMORYPTR DDLockFlags::SURFACEMEMORYPTR
|
||||
#define DDLOCK_WAIT DDLockFlags::WAIT
|
||||
#define DDLOCK_WRITEONLY DDLockFlags::WRITEONLY
|
||||
enum class DDLockFlags : uint32_t {
|
||||
SURFACEMEMORYPTR,
|
||||
WAIT,
|
||||
SURFACEMEMORYPTR = 0,
|
||||
WAIT = 1 << 0,
|
||||
WRITEONLY = 1 << 5,
|
||||
};
|
||||
ENABLE_BITMASK_OPERATORS(DDLockFlags)
|
||||
|
||||
#define DDSCL_FULLSCREEN DDSCLFlags::FULLSCREEN
|
||||
#define DDSCL_ALLOWREBOOT DDSCLFlags::ALLOWREBOOT
|
||||
|
||||
@ -11,19 +11,22 @@
|
||||
static LPDIRECT3D9 g_d3d;
|
||||
static LPDIRECT3DDEVICE9 g_device;
|
||||
static HWND g_hwnd;
|
||||
static LPDIRECT3DTEXTURE9 g_renderTargetTex;
|
||||
static LPDIRECT3DSURFACE9 g_renderTargetSurf;
|
||||
static LPDIRECT3DSURFACE9 g_oldRenderTarget;
|
||||
static int m_width;
|
||||
static int m_height;
|
||||
static std::vector<BridgeSceneLight> m_lights;
|
||||
static Matrix4x4 m_projection;
|
||||
static int g_width;
|
||||
static int g_height;
|
||||
static int g_virtualWidth;
|
||||
static int g_virtualHeight;
|
||||
static bool g_hasScene = false;
|
||||
static std::vector<BridgeSceneLight> g_lights;
|
||||
static Matrix4x4 g_projection;
|
||||
static ViewportTransform g_viewportTransform;
|
||||
|
||||
bool Actual_Initialize(void* hwnd, int width, int height)
|
||||
{
|
||||
g_hwnd = (HWND) hwnd;
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
g_width = width;
|
||||
g_height = height;
|
||||
g_virtualWidth = width;
|
||||
g_virtualHeight = height;
|
||||
g_d3d = Direct3DCreate9(D3D_SDK_VERSION);
|
||||
if (!g_d3d) {
|
||||
return false;
|
||||
@ -52,45 +55,17 @@ bool Actual_Initialize(void* hwnd, int width, int height)
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = g_device->CreateTexture(
|
||||
width,
|
||||
height,
|
||||
1,
|
||||
D3DUSAGE_RENDERTARGET,
|
||||
D3DFMT_A8R8G8B8,
|
||||
D3DPOOL_DEFAULT,
|
||||
&g_renderTargetTex,
|
||||
nullptr
|
||||
);
|
||||
if (FAILED(hr)) {
|
||||
g_device->Release();
|
||||
g_d3d->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = g_renderTargetTex->GetSurfaceLevel(0, &g_renderTargetSurf);
|
||||
if (FAILED(hr)) {
|
||||
g_renderTargetTex->Release();
|
||||
g_device->Release();
|
||||
g_d3d->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
g_device->SetFVF(D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Actual_Shutdown()
|
||||
{
|
||||
if (g_renderTargetSurf) {
|
||||
g_renderTargetSurf->Release();
|
||||
g_renderTargetSurf = nullptr;
|
||||
}
|
||||
if (g_renderTargetTex) {
|
||||
g_renderTargetTex->Release();
|
||||
g_renderTargetTex = nullptr;
|
||||
}
|
||||
if (g_device) {
|
||||
g_device->Release();
|
||||
g_device = nullptr;
|
||||
@ -103,12 +78,12 @@ void Actual_Shutdown()
|
||||
|
||||
void Actual_PushLights(const BridgeSceneLight* lightsArray, size_t count)
|
||||
{
|
||||
m_lights.assign(lightsArray, lightsArray + count);
|
||||
g_lights.assign(lightsArray, lightsArray + count);
|
||||
}
|
||||
|
||||
void Actual_SetProjection(const Matrix4x4* projection, float front, float back)
|
||||
{
|
||||
memcpy(&m_projection, projection, sizeof(Matrix4x4));
|
||||
memcpy(&g_projection, projection, sizeof(Matrix4x4));
|
||||
}
|
||||
|
||||
IDirect3DTexture9* UploadSurfaceToD3DTexture(SDL_Surface* surface)
|
||||
@ -188,18 +163,71 @@ void UploadMeshBuffers(
|
||||
cache.ibo->Unlock();
|
||||
}
|
||||
|
||||
constexpr float PI = 3.14159265358979323846f;
|
||||
|
||||
void SetupLights()
|
||||
void Actual_Resize(int width, int height, const ViewportTransform& viewportTransform)
|
||||
{
|
||||
g_width = width;
|
||||
g_height = height;
|
||||
g_viewportTransform = viewportTransform;
|
||||
|
||||
D3DPRESENT_PARAMETERS pp = {};
|
||||
pp.Windowed = TRUE;
|
||||
pp.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
||||
pp.hDeviceWindow = g_hwnd;
|
||||
pp.BackBufferFormat = D3DFMT_A8R8G8B8;
|
||||
pp.BackBufferWidth = width;
|
||||
pp.BackBufferHeight = height;
|
||||
pp.EnableAutoDepthStencil = TRUE;
|
||||
pp.AutoDepthStencilFormat = D3DFMT_D24S8;
|
||||
g_device->Reset(&pp);
|
||||
}
|
||||
|
||||
void StartScene()
|
||||
{
|
||||
if (g_hasScene) {
|
||||
return;
|
||||
}
|
||||
g_device->BeginScene();
|
||||
g_hasScene = true;
|
||||
}
|
||||
|
||||
void Actual_Clear(float r, float g, float b)
|
||||
{
|
||||
StartScene();
|
||||
|
||||
g_device->Clear(
|
||||
0,
|
||||
nullptr,
|
||||
D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
|
||||
D3DCOLOR_ARGB(255, static_cast<int>(r * 255), static_cast<int>(g * 255), static_cast<int>(b * 255)),
|
||||
1.0f,
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
uint32_t Actual_BeginFrame()
|
||||
{
|
||||
StartScene();
|
||||
|
||||
g_device->SetRenderState(D3DRS_LIGHTING, TRUE);
|
||||
|
||||
g_device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
|
||||
g_device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
|
||||
g_device->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
|
||||
|
||||
g_device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
|
||||
g_device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
||||
g_device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
|
||||
|
||||
for (DWORD i = 0; i < 8; ++i) {
|
||||
g_device->LightEnable(i, FALSE);
|
||||
}
|
||||
|
||||
DWORD lightIdx = 0;
|
||||
for (const auto& l : m_lights) {
|
||||
for (const auto& l : g_lights) {
|
||||
if (lightIdx >= 8) {
|
||||
break;
|
||||
}
|
||||
@ -235,30 +263,16 @@ void SetupLights()
|
||||
}
|
||||
|
||||
light.Falloff = 1.0f;
|
||||
light.Phi = PI;
|
||||
light.Theta = PI / 2;
|
||||
light.Phi = M_PI;
|
||||
light.Theta = M_PI / 2;
|
||||
|
||||
if (SUCCEEDED(g_device->SetLight(lightIdx, &light))) {
|
||||
g_device->LightEnable(lightIdx, TRUE);
|
||||
}
|
||||
++lightIdx;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t Actual_BeginFrame()
|
||||
{
|
||||
g_device->GetRenderTarget(0, &g_oldRenderTarget);
|
||||
g_device->SetRenderTarget(0, g_renderTargetSurf);
|
||||
|
||||
g_device->Clear(0, nullptr, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0, 0, 0, 0), 1.0f, 0);
|
||||
|
||||
g_device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
|
||||
g_device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
|
||||
g_device->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
|
||||
|
||||
g_device->BeginScene();
|
||||
|
||||
SetupLights();
|
||||
g_device->SetFVF(D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1);
|
||||
|
||||
return D3D_OK;
|
||||
}
|
||||
@ -286,15 +300,19 @@ D3DMATRIX ToD3DMATRIX(const Matrix4x4& in)
|
||||
void Actual_SubmitDraw(
|
||||
const D3D9MeshCacheEntry* mesh,
|
||||
const Matrix4x4* modelViewMatrix,
|
||||
const Matrix4x4* worldMatrix,
|
||||
const Matrix4x4* viewMatrix,
|
||||
const Matrix3x3* normalMatrix,
|
||||
const Appearance* appearance,
|
||||
IDirect3DTexture9* texture
|
||||
)
|
||||
{
|
||||
D3DMATRIX worldView = ToD3DMATRIX(*modelViewMatrix);
|
||||
g_device->SetTransform(D3DTS_WORLD, &worldView);
|
||||
D3DMATRIX proj = ToD3DMATRIX(m_projection);
|
||||
D3DMATRIX proj = ToD3DMATRIX(g_projection);
|
||||
g_device->SetTransform(D3DTS_PROJECTION, &proj);
|
||||
D3DMATRIX view = ToD3DMATRIX(*viewMatrix);
|
||||
g_device->SetTransform(D3DTS_VIEW, &view);
|
||||
D3DMATRIX world = ToD3DMATRIX(*worldMatrix);
|
||||
g_device->SetTransform(D3DTS_WORLD, &world);
|
||||
|
||||
D3DMATERIAL9 mat = {};
|
||||
mat.Diffuse.r = appearance->color.r / 255.0f;
|
||||
@ -342,44 +360,149 @@ void Actual_SubmitDraw(
|
||||
g_device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, mesh->vertexCount, 0, mesh->indexCount / 3);
|
||||
}
|
||||
|
||||
uint32_t Actual_FinalizeFrame(void* pixels, int pitch)
|
||||
uint32_t Actual_Flip()
|
||||
{
|
||||
g_device->EndScene();
|
||||
|
||||
g_device->SetRenderTarget(0, g_oldRenderTarget);
|
||||
g_oldRenderTarget->Release();
|
||||
|
||||
LPDIRECT3DSURFACE9 sysMemSurf;
|
||||
HRESULT hr =
|
||||
g_device
|
||||
->CreateOffscreenPlainSurface(m_width, m_height, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &sysMemSurf, nullptr);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = g_device->GetRenderTargetData(g_renderTargetSurf, sysMemSurf);
|
||||
if (FAILED(hr)) {
|
||||
sysMemSurf->Release();
|
||||
return hr;
|
||||
}
|
||||
|
||||
D3DLOCKED_RECT lockedRect;
|
||||
hr = sysMemSurf->LockRect(&lockedRect, nullptr, D3DLOCK_READONLY);
|
||||
if (FAILED(hr)) {
|
||||
sysMemSurf->Release();
|
||||
return hr;
|
||||
}
|
||||
|
||||
BYTE* src = static_cast<BYTE*>(lockedRect.pBits);
|
||||
BYTE* dst = static_cast<BYTE*>(pixels);
|
||||
int copyWidth = m_width * 4;
|
||||
|
||||
for (int y = 0; y < m_height; y++) {
|
||||
memcpy(dst + y * pitch, src + y * lockedRect.Pitch, copyWidth);
|
||||
}
|
||||
|
||||
sysMemSurf->UnlockRect();
|
||||
sysMemSurf->Release();
|
||||
|
||||
return hr;
|
||||
g_hasScene = false;
|
||||
return g_device->Present(nullptr, nullptr, nullptr, nullptr);
|
||||
}
|
||||
|
||||
void Actual_Draw2DImage(IDirect3DTexture9* texture, const SDL_Rect& srcRect, const SDL_Rect& dstRect)
|
||||
{
|
||||
StartScene();
|
||||
|
||||
float left = -g_viewportTransform.offsetX / g_viewportTransform.scale;
|
||||
float right = (g_width - g_viewportTransform.offsetX) / g_viewportTransform.scale;
|
||||
float top = -g_viewportTransform.offsetY / g_viewportTransform.scale;
|
||||
float bottom = (g_height - g_viewportTransform.offsetY) / g_viewportTransform.scale;
|
||||
|
||||
auto virtualToScreenX = [&](float x) { return ((x - left) / (right - left)) * g_width; };
|
||||
auto virtualToScreenY = [&](float y) { return ((y - top) / (bottom - top)) * g_height; };
|
||||
|
||||
float x1_virtual = static_cast<float>(dstRect.x);
|
||||
float y1_virtual = static_cast<float>(dstRect.y);
|
||||
float x2_virtual = x1_virtual + dstRect.w;
|
||||
float y2_virtual = y1_virtual + dstRect.h;
|
||||
|
||||
float x1 = virtualToScreenX(x1_virtual);
|
||||
float y1 = virtualToScreenY(y1_virtual);
|
||||
float x2 = virtualToScreenX(x2_virtual);
|
||||
float y2 = virtualToScreenY(y2_virtual);
|
||||
|
||||
D3DMATRIX identity =
|
||||
{1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
|
||||
g_device->SetTransform(D3DTS_PROJECTION, &identity);
|
||||
g_device->SetTransform(D3DTS_VIEW, &identity);
|
||||
g_device->SetTransform(D3DTS_WORLD, &identity);
|
||||
|
||||
g_device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
|
||||
g_device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
|
||||
|
||||
g_device->SetRenderState(D3DRS_ZENABLE, FALSE);
|
||||
g_device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
|
||||
g_device->SetRenderState(D3DRS_LIGHTING, FALSE);
|
||||
g_device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
g_device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
|
||||
g_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
||||
|
||||
g_device->SetTexture(0, texture);
|
||||
g_device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
||||
g_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
|
||||
g_device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
|
||||
|
||||
D3DSURFACE_DESC texDesc;
|
||||
texture->GetLevelDesc(0, &texDesc);
|
||||
float texW = static_cast<float>(texDesc.Width);
|
||||
float texH = static_cast<float>(texDesc.Height);
|
||||
|
||||
float u1 = static_cast<float>(srcRect.x) / texW;
|
||||
float v1 = static_cast<float>(srcRect.y) / texH;
|
||||
float u2 = static_cast<float>(srcRect.x + srcRect.w) / texW;
|
||||
float v2 = static_cast<float>(srcRect.y + srcRect.h) / texH;
|
||||
|
||||
struct Vertex {
|
||||
float x, y, z, rhw;
|
||||
float u, v;
|
||||
};
|
||||
|
||||
Vertex quad[4] = {
|
||||
{x1, y1, 0.0f, 1.0f, u1, v1},
|
||||
{x2, y1, 0.0f, 1.0f, u2, v1},
|
||||
{x2, y2, 0.0f, 1.0f, u2, v2},
|
||||
{x1, y2, 0.0f, 1.0f, u1, v2},
|
||||
};
|
||||
|
||||
g_device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
|
||||
g_device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, sizeof(Vertex));
|
||||
}
|
||||
|
||||
uint32_t Actual_Download(SDL_Surface* target)
|
||||
{
|
||||
IDirect3DSurface9* backBuffer;
|
||||
HRESULT hr = g_device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
IDirect3DSurface9* sysMemSurface;
|
||||
hr = g_device->CreateOffscreenPlainSurface(
|
||||
g_width,
|
||||
g_height,
|
||||
D3DFMT_A8R8G8B8,
|
||||
D3DPOOL_SYSTEMMEM,
|
||||
&sysMemSurface,
|
||||
nullptr
|
||||
);
|
||||
if (FAILED(hr)) {
|
||||
backBuffer->Release();
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = g_device->GetRenderTargetData(backBuffer, sysMemSurface);
|
||||
backBuffer->Release();
|
||||
if (FAILED(hr)) {
|
||||
sysMemSurface->Release();
|
||||
return hr;
|
||||
}
|
||||
|
||||
D3DLOCKED_RECT locked;
|
||||
hr = sysMemSurface->LockRect(&locked, nullptr, D3DLOCK_READONLY);
|
||||
if (FAILED(hr)) {
|
||||
sysMemSurface->Release();
|
||||
return hr;
|
||||
}
|
||||
|
||||
SDL_Surface* srcSurface =
|
||||
SDL_CreateSurfaceFrom(g_width, g_height, SDL_PIXELFORMAT_ARGB8888, locked.pBits, locked.Pitch);
|
||||
if (!srcSurface) {
|
||||
sysMemSurface->UnlockRect();
|
||||
sysMemSurface->Release();
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
float srcAspect = static_cast<float>(g_width) / g_height;
|
||||
float dstAspect = static_cast<float>(target->w) / target->h;
|
||||
|
||||
SDL_Rect srcRect;
|
||||
if (srcAspect > dstAspect) {
|
||||
int cropWidth = static_cast<int>(g_height * dstAspect);
|
||||
srcRect = {(g_width - cropWidth) / 2, 0, cropWidth, g_height};
|
||||
}
|
||||
else {
|
||||
int cropHeight = static_cast<int>(g_width / dstAspect);
|
||||
srcRect = {0, (g_height - cropHeight) / 2, g_width, cropHeight};
|
||||
}
|
||||
|
||||
if (SDL_BlitSurfaceScaled(srcSurface, &srcRect, target, nullptr, SDL_SCALEMODE_NEAREST)) {
|
||||
SDL_DestroySurface(srcSurface);
|
||||
sysMemSurface->UnlockRect();
|
||||
sysMemSurface->Release();
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
SDL_DestroySurface(srcSurface);
|
||||
sysMemSurface->UnlockRect();
|
||||
sysMemSurface->Release();
|
||||
|
||||
return D3D_OK;
|
||||
}
|
||||
|
||||
@ -69,8 +69,14 @@ void Actual_EnableTransparency();
|
||||
void Actual_SubmitDraw(
|
||||
const D3D9MeshCacheEntry* mesh,
|
||||
const Matrix4x4* modelViewMatrix,
|
||||
const Matrix4x4* worldMatrix,
|
||||
const Matrix4x4* viewMatrix,
|
||||
const Matrix3x3* normalMatrix,
|
||||
const Appearance* appearance,
|
||||
IDirect3DTexture9* texture
|
||||
);
|
||||
uint32_t Actual_FinalizeFrame(void* pixels, int pitch);
|
||||
void Actual_Resize(int width, int height, const ViewportTransform& viewportTransform);
|
||||
void Actual_Clear(float r, float g, float b);
|
||||
uint32_t Actual_Flip();
|
||||
void Actual_Draw2DImage(IDirect3DTexture9* texture, const SDL_Rect& srcRect, const SDL_Rect& dstRect);
|
||||
uint32_t Actual_Download(SDL_Surface* target);
|
||||
|
||||
@ -20,14 +20,18 @@ Direct3DRMRenderer* DirectX9Renderer::Create(DWORD width, DWORD height)
|
||||
return new DirectX9Renderer(width, height);
|
||||
}
|
||||
|
||||
DirectX9Renderer::DirectX9Renderer(DWORD width, DWORD height) : m_width(width), m_height(height)
|
||||
DirectX9Renderer::DirectX9Renderer(DWORD width, DWORD height)
|
||||
{
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_virtualWidth = width;
|
||||
m_virtualHeight = height;
|
||||
Actual_Initialize(
|
||||
SDL_GetPointerProperty(SDL_GetWindowProperties(DDWindow), SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL),
|
||||
width,
|
||||
height
|
||||
);
|
||||
m_renderedImage = SDL_CreateSurface(m_width, m_height, SDL_PIXELFORMAT_ARGB8888);
|
||||
m_renderedImage = SDL_CreateSurface(m_width, m_height, SDL_PIXELFORMAT_RGBA32);
|
||||
}
|
||||
|
||||
DirectX9Renderer::~DirectX9Renderer()
|
||||
@ -212,16 +216,6 @@ Uint32 DirectX9Renderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshG
|
||||
return static_cast<Uint32>(m_meshs.size() - 1);
|
||||
}
|
||||
|
||||
DWORD DirectX9Renderer::GetWidth()
|
||||
{
|
||||
return m_width;
|
||||
}
|
||||
|
||||
DWORD DirectX9Renderer::GetHeight()
|
||||
{
|
||||
return m_height;
|
||||
}
|
||||
|
||||
void DirectX9Renderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc)
|
||||
{
|
||||
halDesc->dcmColorModel = D3DCOLORMODEL::RGB;
|
||||
@ -253,6 +247,8 @@ void DirectX9Renderer::EnableTransparency()
|
||||
void DirectX9Renderer::SubmitDraw(
|
||||
DWORD meshId,
|
||||
const D3DRMMATRIX4D& modelViewMatrix,
|
||||
const D3DRMMATRIX4D& worldMatrix,
|
||||
const D3DRMMATRIX4D& viewMatrix,
|
||||
const Matrix3x3& normalMatrix,
|
||||
const Appearance& appearance
|
||||
)
|
||||
@ -261,17 +257,46 @@ void DirectX9Renderer::SubmitDraw(
|
||||
if (appearance.textureId != NO_TEXTURE_ID) {
|
||||
texture = m_textures[appearance.textureId].dxTexture;
|
||||
}
|
||||
Actual_SubmitDraw(&m_meshs[meshId], &modelViewMatrix, &normalMatrix, &appearance, texture);
|
||||
Actual_SubmitDraw(
|
||||
&m_meshs[meshId],
|
||||
&modelViewMatrix,
|
||||
&worldMatrix,
|
||||
&viewMatrix,
|
||||
&normalMatrix,
|
||||
&appearance,
|
||||
texture
|
||||
);
|
||||
}
|
||||
|
||||
HRESULT DirectX9Renderer::FinalizeFrame()
|
||||
{
|
||||
HRESULT hr = Actual_FinalizeFrame(m_renderedImage->pixels, m_renderedImage->pitch);
|
||||
if (hr != DD_OK) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
// Composite onto SDL backbuffer
|
||||
SDL_BlitSurface(m_renderedImage, nullptr, DDBackBuffer, nullptr);
|
||||
return hr;
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
void DirectX9Renderer::Resize(int width, int height, const ViewportTransform& viewportTransform)
|
||||
{
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_viewportTransform = viewportTransform;
|
||||
Actual_Resize(width, height, viewportTransform);
|
||||
}
|
||||
|
||||
void DirectX9Renderer::Clear(float r, float g, float b)
|
||||
{
|
||||
Actual_Clear(r, g, b);
|
||||
}
|
||||
|
||||
void DirectX9Renderer::Flip()
|
||||
{
|
||||
Actual_Flip();
|
||||
}
|
||||
|
||||
void DirectX9Renderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect)
|
||||
{
|
||||
Actual_Draw2DImage(m_textures[textureId].dxTexture, srcRect, dstRect);
|
||||
}
|
||||
|
||||
void DirectX9Renderer::Download(SDL_Surface* target)
|
||||
{
|
||||
Actual_Download(target);
|
||||
}
|
||||
|
||||
354
miniwin/src/d3drm/backends/opengl1/actual.cpp
Normal file
354
miniwin/src/d3drm/backends/opengl1/actual.cpp
Normal file
@ -0,0 +1,354 @@
|
||||
// This file cannot include any minwin headers.
|
||||
|
||||
#include "actual.h"
|
||||
|
||||
#include "structs.h"
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
#include <SDL3/SDL_opengl.h>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
// GL extension API functions.
|
||||
bool g_useVBOs;
|
||||
PFNGLGENBUFFERSPROC mwglGenBuffers;
|
||||
PFNGLBINDBUFFERPROC mwglBindBuffer;
|
||||
PFNGLBUFFERDATAPROC mwglBufferData;
|
||||
PFNGLDELETEBUFFERSPROC mwglDeleteBuffers;
|
||||
|
||||
void GL11_InitState()
|
||||
{
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
glFrontFace(GL_CW);
|
||||
}
|
||||
|
||||
void GL11_LoadExtensions()
|
||||
{
|
||||
g_useVBOs = SDL_GL_ExtensionSupported("GL_ARB_vertex_buffer_object");
|
||||
|
||||
if (g_useVBOs) {
|
||||
// Load the required GL function pointers.
|
||||
mwglGenBuffers = (PFNGLGENBUFFERSPROC) SDL_GL_GetProcAddress("glGenBuffersARB");
|
||||
mwglBindBuffer = (PFNGLBINDBUFFERPROC) SDL_GL_GetProcAddress("glBindBufferARB");
|
||||
mwglBufferData = (PFNGLBUFFERDATAPROC) SDL_GL_GetProcAddress("glBufferDataARB");
|
||||
mwglDeleteBuffers = (PFNGLDELETEBUFFERSPROC) SDL_GL_GetProcAddress("glDeleteBuffersARB");
|
||||
}
|
||||
}
|
||||
|
||||
void GL11_DestroyTexture(GLuint texId)
|
||||
{
|
||||
glDeleteTextures(1, &texId);
|
||||
}
|
||||
|
||||
GLuint GL11_UploadTextureData(void* pixels, int width, int height)
|
||||
{
|
||||
GLuint texId;
|
||||
glGenTextures(1, &texId);
|
||||
glBindTexture(GL_TEXTURE_2D, texId);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
return texId;
|
||||
}
|
||||
|
||||
void GL11_UploadMesh(GLMeshCacheEntry& cache, bool hasTexture)
|
||||
{
|
||||
if (g_useVBOs) {
|
||||
mwglGenBuffers(1, &cache.vboPositions);
|
||||
mwglBindBuffer(GL_ARRAY_BUFFER_ARB, cache.vboPositions);
|
||||
mwglBufferData(
|
||||
GL_ARRAY_BUFFER_ARB,
|
||||
cache.positions.size() * sizeof(GL11_BridgeVector),
|
||||
cache.positions.data(),
|
||||
GL_STATIC_DRAW_ARB
|
||||
);
|
||||
|
||||
mwglGenBuffers(1, &cache.vboNormals);
|
||||
mwglBindBuffer(GL_ARRAY_BUFFER_ARB, cache.vboNormals);
|
||||
mwglBufferData(
|
||||
GL_ARRAY_BUFFER_ARB,
|
||||
cache.normals.size() * sizeof(GL11_BridgeVector),
|
||||
cache.normals.data(),
|
||||
GL_STATIC_DRAW_ARB
|
||||
);
|
||||
|
||||
if (hasTexture) {
|
||||
mwglGenBuffers(1, &cache.vboTexcoords);
|
||||
mwglBindBuffer(GL_ARRAY_BUFFER_ARB, cache.vboTexcoords);
|
||||
mwglBufferData(
|
||||
GL_ARRAY_BUFFER_ARB,
|
||||
cache.texcoords.size() * sizeof(GL11_BridgeTexCoord),
|
||||
cache.texcoords.data(),
|
||||
GL_STATIC_DRAW_ARB
|
||||
);
|
||||
}
|
||||
|
||||
mwglGenBuffers(1, &cache.ibo);
|
||||
mwglBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, cache.ibo);
|
||||
mwglBufferData(
|
||||
GL_ELEMENT_ARRAY_BUFFER_ARB,
|
||||
cache.indices.size() * sizeof(cache.indices[0]),
|
||||
cache.indices.data(),
|
||||
GL_STATIC_DRAW_ARB
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void GL11_DestroyMesh(GLMeshCacheEntry& cache)
|
||||
{
|
||||
if (g_useVBOs) {
|
||||
mwglDeleteBuffers(1, &cache.vboPositions);
|
||||
mwglDeleteBuffers(1, &cache.vboNormals);
|
||||
mwglDeleteBuffers(1, &cache.vboTexcoords);
|
||||
mwglDeleteBuffers(1, &cache.ibo);
|
||||
}
|
||||
}
|
||||
|
||||
void GL11_BeginFrame(const Matrix4x4* projection)
|
||||
{
|
||||
glDisable(GL_BLEND);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_TRUE);
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_COLOR_MATERIAL);
|
||||
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
|
||||
|
||||
// Disable all lights and reset global ambient
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
glDisable(GL_LIGHT0 + i);
|
||||
}
|
||||
const GLfloat zeroAmbient[4] = {0.f, 0.f, 0.f, 1.f};
|
||||
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, zeroAmbient);
|
||||
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
|
||||
|
||||
// Projection and view
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadMatrixf((const GLfloat*) projection);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
}
|
||||
|
||||
void GL11_UploadLight(int lightIdx, GL11_BridgeSceneLight* l)
|
||||
{
|
||||
// Setup light
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
GLenum lightId = GL_LIGHT0 + lightIdx++;
|
||||
const FColor& c = l->color;
|
||||
GLfloat col[4] = {c.r, c.g, c.b, c.a};
|
||||
const GLfloat zeroAmbient[4] = {0.f, 0.f, 0.f, 1.f};
|
||||
|
||||
if (l->positional == 0.f && l->directional == 0.f) {
|
||||
// Ambient light only
|
||||
glLightfv(lightId, GL_AMBIENT, col);
|
||||
const GLfloat black[4] = {0.f, 0.f, 0.f, 1.f};
|
||||
glLightfv(lightId, GL_DIFFUSE, black);
|
||||
glLightfv(lightId, GL_SPECULAR, black);
|
||||
const GLfloat dummyPos[4] = {0.f, 0.f, 1.f, 0.f};
|
||||
glLightfv(lightId, GL_POSITION, dummyPos);
|
||||
}
|
||||
else {
|
||||
glLightfv(lightId, GL_AMBIENT, zeroAmbient);
|
||||
glLightfv(lightId, GL_DIFFUSE, col);
|
||||
if (l->directional == 1.0f) {
|
||||
glLightfv(lightId, GL_SPECULAR, col);
|
||||
}
|
||||
else {
|
||||
const GLfloat black[4] = {0.f, 0.f, 0.f, 1.f};
|
||||
glLightfv(lightId, GL_SPECULAR, black);
|
||||
}
|
||||
|
||||
GLfloat pos[4];
|
||||
if (l->directional == 1.f) {
|
||||
pos[0] = -l->direction.x;
|
||||
pos[1] = -l->direction.y;
|
||||
pos[2] = -l->direction.z;
|
||||
pos[3] = 0.f;
|
||||
}
|
||||
else {
|
||||
pos[0] = l->position.x;
|
||||
pos[1] = l->position.y;
|
||||
pos[2] = l->position.z;
|
||||
pos[3] = 1.f;
|
||||
}
|
||||
glLightfv(lightId, GL_POSITION, pos);
|
||||
}
|
||||
glEnable(lightId);
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
void GL11_EnableTransparency()
|
||||
{
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDepthMask(GL_FALSE);
|
||||
}
|
||||
|
||||
#define NO_TEXTURE_ID 0xffffffff
|
||||
|
||||
void GL11_SubmitDraw(
|
||||
GLMeshCacheEntry& mesh,
|
||||
const Matrix4x4& modelViewMatrix,
|
||||
const Appearance& appearance,
|
||||
GLuint texId
|
||||
)
|
||||
{
|
||||
glLoadMatrixf(&modelViewMatrix[0][0]);
|
||||
glEnable(GL_NORMALIZE);
|
||||
|
||||
glColor4ub(appearance.color.r, appearance.color.g, appearance.color.b, appearance.color.a);
|
||||
|
||||
if (appearance.shininess != 0.0f) {
|
||||
GLfloat whiteSpec[] = {1.f, 1.f, 1.f, 1.f};
|
||||
glMaterialfv(GL_FRONT, GL_SPECULAR, whiteSpec);
|
||||
glMaterialf(GL_FRONT, GL_SHININESS, appearance.shininess);
|
||||
}
|
||||
else {
|
||||
GLfloat noSpec[] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
glMaterialfv(GL_FRONT, GL_SPECULAR, noSpec);
|
||||
glMaterialf(GL_FRONT, GL_SHININESS, 0.0f);
|
||||
}
|
||||
|
||||
if (mesh.flat) {
|
||||
glShadeModel(GL_FLAT);
|
||||
}
|
||||
else {
|
||||
glShadeModel(GL_SMOOTH);
|
||||
}
|
||||
|
||||
// Bind texture if present
|
||||
if (appearance.textureId != NO_TEXTURE_ID) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, texId);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
else {
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
if (g_useVBOs) {
|
||||
mwglBindBuffer(GL_ARRAY_BUFFER_ARB, mesh.vboPositions);
|
||||
glVertexPointer(3, GL_FLOAT, 0, nullptr);
|
||||
|
||||
mwglBindBuffer(GL_ARRAY_BUFFER_ARB, mesh.vboNormals);
|
||||
glNormalPointer(GL_FLOAT, 0, nullptr);
|
||||
|
||||
if (appearance.textureId != NO_TEXTURE_ID) {
|
||||
mwglBindBuffer(GL_ARRAY_BUFFER_ARB, mesh.vboTexcoords);
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, nullptr);
|
||||
}
|
||||
|
||||
mwglBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, mesh.ibo);
|
||||
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(mesh.indices.size()), GL_UNSIGNED_SHORT, nullptr);
|
||||
|
||||
mwglBindBuffer(GL_ARRAY_BUFFER_ARB, 0);
|
||||
mwglBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
|
||||
}
|
||||
else {
|
||||
glVertexPointer(3, GL_FLOAT, 0, mesh.positions.data());
|
||||
glNormalPointer(GL_FLOAT, 0, mesh.normals.data());
|
||||
if (appearance.textureId != NO_TEXTURE_ID) {
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, mesh.texcoords.data());
|
||||
}
|
||||
|
||||
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(mesh.indices.size()), GL_UNSIGNED_SHORT, mesh.indices.data());
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
void GL11_Resize(int width, int height)
|
||||
{
|
||||
glViewport(0, 0, width, height);
|
||||
}
|
||||
|
||||
void GL11_Clear(float r, float g, float b)
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_TRUE);
|
||||
glClearColor(r, g, b, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
void GL11_Draw2DImage(
|
||||
GLuint texId,
|
||||
const SDL_Rect& srcRect,
|
||||
const SDL_Rect& dstRect,
|
||||
float left,
|
||||
float right,
|
||||
float bottom,
|
||||
float top
|
||||
)
|
||||
{
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_FALSE);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
glOrtho(left, right, bottom, top, -1, 1);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, texId);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
GLint boundTexture = 0;
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &boundTexture);
|
||||
|
||||
GLfloat texW, texH;
|
||||
glGetTexLevelParameterfv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &texW);
|
||||
glGetTexLevelParameterfv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &texH);
|
||||
|
||||
float u1 = srcRect.x / texW;
|
||||
float v1 = srcRect.y / texH;
|
||||
float u2 = (srcRect.x + srcRect.w) / texW;
|
||||
float v2 = (srcRect.y + srcRect.h) / texH;
|
||||
|
||||
float x1 = (float) dstRect.x;
|
||||
float y1 = (float) dstRect.y;
|
||||
float x2 = x1 + dstRect.w;
|
||||
float y2 = y1 + dstRect.h;
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(u1, v1);
|
||||
glVertex2f(x1, y1);
|
||||
glTexCoord2f(u2, v1);
|
||||
glVertex2f(x2, y1);
|
||||
glTexCoord2f(u2, v2);
|
||||
glVertex2f(x2, y2);
|
||||
glTexCoord2f(u1, v2);
|
||||
glVertex2f(x1, y2);
|
||||
glEnd();
|
||||
|
||||
// Restore state
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
void GL11_Download(SDL_Surface* target)
|
||||
{
|
||||
glFinish();
|
||||
glReadPixels(0, 0, target->w, target->h, GL_RGBA, GL_UNSIGNED_BYTE, target->pixels);
|
||||
}
|
||||
88
miniwin/src/d3drm/backends/opengl1/actual.h
Normal file
88
miniwin/src/d3drm/backends/opengl1/actual.h
Normal file
@ -0,0 +1,88 @@
|
||||
#pragma once
|
||||
|
||||
#include "structs.h"
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
// We don't want to transitively include windows.h, but we need GLuint
|
||||
typedef unsigned int GLuint;
|
||||
struct IDirect3DRMTexture;
|
||||
struct MeshGroup;
|
||||
|
||||
typedef float Matrix4x4[4][4];
|
||||
|
||||
struct GL11_BridgeVector {
|
||||
float x, y, z;
|
||||
};
|
||||
|
||||
struct GL11_BridgeTexCoord {
|
||||
float u, v;
|
||||
};
|
||||
|
||||
struct GL11_BridgeSceneLight {
|
||||
FColor color;
|
||||
GL11_BridgeVector position;
|
||||
float positional;
|
||||
GL11_BridgeVector direction;
|
||||
float directional;
|
||||
};
|
||||
|
||||
struct GL11_BridgeSceneVertex {
|
||||
GL11_BridgeVector position;
|
||||
GL11_BridgeVector normal;
|
||||
float tu, tv;
|
||||
};
|
||||
|
||||
struct GLTextureCacheEntry {
|
||||
IDirect3DRMTexture* texture;
|
||||
Uint32 version;
|
||||
GLuint glTextureId;
|
||||
};
|
||||
|
||||
struct GLMeshCacheEntry {
|
||||
const MeshGroup* meshGroup;
|
||||
int version;
|
||||
bool flat;
|
||||
|
||||
// non-VBO cache
|
||||
std::vector<GL11_BridgeVector> positions;
|
||||
std::vector<GL11_BridgeVector> normals;
|
||||
std::vector<GL11_BridgeTexCoord> texcoords;
|
||||
std::vector<uint16_t> indices;
|
||||
|
||||
// VBO cache
|
||||
GLuint vboPositions;
|
||||
GLuint vboNormals;
|
||||
GLuint vboTexcoords;
|
||||
GLuint ibo;
|
||||
};
|
||||
|
||||
void GL11_InitState();
|
||||
void GL11_LoadExtensions();
|
||||
void GL11_DestroyTexture(GLuint texId);
|
||||
GLuint GL11_UploadTextureData(void* pixels, int width, int height);
|
||||
void GL11_UploadMesh(GLMeshCacheEntry& cache, bool hasTexture);
|
||||
void GL11_DestroyMesh(GLMeshCacheEntry& cache);
|
||||
void GL11_BeginFrame(const Matrix4x4* projection);
|
||||
void GL11_UploadLight(int lightIdx, GL11_BridgeSceneLight* l);
|
||||
void GL11_EnableTransparency();
|
||||
void GL11_SubmitDraw(
|
||||
GLMeshCacheEntry& mesh,
|
||||
const Matrix4x4& modelViewMatrix,
|
||||
const Appearance& appearance,
|
||||
GLuint texId
|
||||
);
|
||||
void GL11_Resize(int width, int height);
|
||||
void GL11_Clear(float r, float g, float b);
|
||||
void GL11_Draw2DImage(
|
||||
GLuint texId,
|
||||
const SDL_Rect& srcRect,
|
||||
const SDL_Rect& dstRect,
|
||||
float left,
|
||||
float right,
|
||||
float bottom,
|
||||
float top
|
||||
);
|
||||
void GL11_Download(SDL_Surface* target);
|
||||
@ -1,5 +1,4 @@
|
||||
#include <GL/glew.h>
|
||||
// must come after GLEW
|
||||
#include "actual.h"
|
||||
#include "d3drmrenderer_opengl1.h"
|
||||
#include "ddraw_impl.h"
|
||||
#include "ddsurface_impl.h"
|
||||
@ -11,21 +10,38 @@
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
static_assert(sizeof(Matrix4x4) == sizeof(D3DRMMATRIX4D), "Matrix4x4 is wrong size");
|
||||
static_assert(sizeof(GL11_BridgeVector) == sizeof(D3DVECTOR), "GL11_BridgeVector is wrong size");
|
||||
static_assert(sizeof(GL11_BridgeTexCoord) == sizeof(TexCoord), "GL11_BridgeTexCoord is wrong size");
|
||||
static_assert(sizeof(GL11_BridgeSceneLight) == sizeof(SceneLight), "GL11_BridgeSceneLight is wrong size");
|
||||
static_assert(sizeof(GL11_BridgeSceneVertex) == sizeof(D3DRMVERTEX), "GL11_BridgeSceneVertex is wrong size");
|
||||
|
||||
Direct3DRMRenderer* OpenGL1Renderer::Create(DWORD width, DWORD height)
|
||||
{
|
||||
// We have to reset the attributes here after having enumerated the
|
||||
// OpenGL ES 2.0 renderer, or else SDL gets very confused by SDL_GL_DEPTH_SIZE
|
||||
// call below when on an EGL-based backend, and crashes with EGL_BAD_MATCH.
|
||||
SDL_GL_ResetAttributes();
|
||||
// But ResetAttributes resets it to 16.
|
||||
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
|
||||
|
||||
SDL_Window* window = DDWindow;
|
||||
bool testWindow = false;
|
||||
if (!window) {
|
||||
window = SDL_CreateWindow("OpenGL 1.2 test", width, height, SDL_WINDOW_HIDDEN | SDL_WINDOW_OPENGL);
|
||||
window = SDL_CreateWindow("OpenGL 1.1 test", width, height, SDL_WINDOW_HIDDEN | SDL_WINDOW_OPENGL);
|
||||
if (!window) {
|
||||
SDL_Log("SDL_CreateWindow: %s", SDL_GetError());
|
||||
return nullptr;
|
||||
}
|
||||
testWindow = true;
|
||||
}
|
||||
|
||||
SDL_GLContext context = SDL_GL_CreateContext(window);
|
||||
if (!context) {
|
||||
SDL_Log("SDL_GL_CreateContext: %s", SDL_GetError());
|
||||
if (testWindow) {
|
||||
SDL_DestroyWindow(window);
|
||||
}
|
||||
@ -33,85 +49,44 @@ Direct3DRMRenderer* OpenGL1Renderer::Create(DWORD width, DWORD height)
|
||||
}
|
||||
|
||||
if (!SDL_GL_MakeCurrent(window, context)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GLenum err = glewInit();
|
||||
if (err != GLEW_OK) {
|
||||
SDL_Log("SDL_GL_MakeCurrent: %s", SDL_GetError());
|
||||
if (testWindow) {
|
||||
SDL_DestroyWindow(window);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!GLEW_EXT_framebuffer_object) {
|
||||
if (testWindow) {
|
||||
SDL_DestroyWindow(window);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
glFrontFace(GL_CCW);
|
||||
|
||||
// Setup FBO
|
||||
GLuint fbo;
|
||||
glGenFramebuffers(1, &fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
|
||||
// Create color texture
|
||||
GLuint colorTex;
|
||||
glGenTextures(1, &colorTex);
|
||||
glBindTexture(GL_TEXTURE_2D, colorTex);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTex, 0);
|
||||
|
||||
// Create depth renderbuffer
|
||||
GLuint depthRb;
|
||||
glGenRenderbuffers(1, &depthRb);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, depthRb);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRb);
|
||||
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||
return nullptr;
|
||||
}
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
GL11_InitState();
|
||||
|
||||
if (testWindow) {
|
||||
SDL_DestroyWindow(window);
|
||||
}
|
||||
|
||||
return new OpenGL1Renderer(width, height, context, fbo, colorTex, depthRb);
|
||||
return new OpenGL1Renderer(width, height, context);
|
||||
}
|
||||
|
||||
OpenGL1Renderer::OpenGL1Renderer(
|
||||
DWORD width,
|
||||
DWORD height,
|
||||
SDL_GLContext context,
|
||||
GLuint fbo,
|
||||
GLuint colorTex,
|
||||
GLuint depthRb
|
||||
)
|
||||
: m_width(width), m_height(height), m_context(context), m_fbo(fbo), m_colorTex(colorTex), m_depthRb(depthRb)
|
||||
OpenGL1Renderer::OpenGL1Renderer(DWORD width, DWORD height, SDL_GLContext context) : m_context(context)
|
||||
{
|
||||
m_renderedImage = SDL_CreateSurface(m_width, m_height, SDL_PIXELFORMAT_ABGR8888);
|
||||
m_useVBOs = GLEW_ARB_vertex_buffer_object;
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_virtualWidth = width;
|
||||
m_virtualHeight = height;
|
||||
m_renderedImage = SDL_CreateSurface(m_width, m_height, SDL_PIXELFORMAT_RGBA32);
|
||||
GL11_LoadExtensions();
|
||||
}
|
||||
|
||||
OpenGL1Renderer::~OpenGL1Renderer()
|
||||
{
|
||||
SDL_DestroySurface(m_renderedImage);
|
||||
glDeleteFramebuffers(1, &m_fbo);
|
||||
glDeleteRenderbuffers(1, &m_depthRb);
|
||||
glDeleteTextures(1, &m_colorTex);
|
||||
}
|
||||
|
||||
void OpenGL1Renderer::PushLights(const SceneLight* lightsArray, size_t count)
|
||||
{
|
||||
if (count > 8) {
|
||||
SDL_Log("Unsupported number of lights (%d)", static_cast<int>(count));
|
||||
count = 8;
|
||||
}
|
||||
|
||||
m_lights.assign(lightsArray, lightsArray + count);
|
||||
}
|
||||
|
||||
@ -122,7 +97,6 @@ void OpenGL1Renderer::SetFrustumPlanes(const Plane* frustumPlanes)
|
||||
void OpenGL1Renderer::SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back)
|
||||
{
|
||||
memcpy(&m_projection, projection, sizeof(D3DRMMATRIX4D));
|
||||
m_projection[1][1] *= -1.0f; // OpenGL is upside down
|
||||
}
|
||||
|
||||
struct TextureDestroyContextGL {
|
||||
@ -138,7 +112,7 @@ void OpenGL1Renderer::AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* t
|
||||
auto* ctx = static_cast<TextureDestroyContextGL*>(arg);
|
||||
auto& cache = ctx->renderer->m_textures[ctx->textureId];
|
||||
if (cache.glTextureId != 0) {
|
||||
glDeleteTextures(1, &cache.glTextureId);
|
||||
GL11_DestroyTexture(cache.glTextureId);
|
||||
cache.glTextureId = 0;
|
||||
cache.texture = nullptr;
|
||||
}
|
||||
@ -157,18 +131,14 @@ Uint32 OpenGL1Renderer::GetTextureId(IDirect3DRMTexture* iTexture)
|
||||
auto& tex = m_textures[i];
|
||||
if (tex.texture == texture) {
|
||||
if (tex.version != texture->m_version) {
|
||||
glDeleteTextures(1, &tex.glTextureId);
|
||||
glGenTextures(1, &tex.glTextureId);
|
||||
glBindTexture(GL_TEXTURE_2D, tex.glTextureId);
|
||||
GL11_DestroyTexture(tex.glTextureId);
|
||||
|
||||
SDL_Surface* surf = SDL_ConvertSurface(surface->m_surface, SDL_PIXELFORMAT_ABGR8888);
|
||||
SDL_Surface* surf = SDL_ConvertSurface(surface->m_surface, SDL_PIXELFORMAT_RGBA32);
|
||||
if (!surf) {
|
||||
return NO_TEXTURE_ID;
|
||||
}
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, surf->w, surf->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surf->pixels);
|
||||
tex.glTextureId = GL11_UploadTextureData(surf->pixels, surf->w, surf->h);
|
||||
SDL_DestroySurface(surf);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
tex.version = texture->m_version;
|
||||
}
|
||||
@ -177,17 +147,13 @@ Uint32 OpenGL1Renderer::GetTextureId(IDirect3DRMTexture* iTexture)
|
||||
}
|
||||
|
||||
GLuint texId;
|
||||
glGenTextures(1, &texId);
|
||||
glBindTexture(GL_TEXTURE_2D, texId);
|
||||
|
||||
SDL_Surface* surf = SDL_ConvertSurface(surface->m_surface, SDL_PIXELFORMAT_ABGR8888);
|
||||
SDL_Surface* surf = SDL_ConvertSurface(surface->m_surface, SDL_PIXELFORMAT_RGBA32);
|
||||
if (!surf) {
|
||||
return NO_TEXTURE_ID;
|
||||
}
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, surf->w, surf->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surf->pixels);
|
||||
texId = GL11_UploadTextureData(surf->pixels, surf->w, surf->h);
|
||||
SDL_DestroySurface(surf);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
for (Uint32 i = 0; i < m_textures.size(); ++i) {
|
||||
auto& tex = m_textures[i];
|
||||
@ -234,52 +200,19 @@ GLMeshCacheEntry GLUploadMesh(const MeshGroup& meshGroup, bool useVBOs)
|
||||
if (meshGroup.texture) {
|
||||
cache.texcoords.resize(vertices.size());
|
||||
std::transform(vertices.begin(), vertices.end(), cache.texcoords.begin(), [](const D3DRMVERTEX& v) {
|
||||
return v.texCoord;
|
||||
return GL11_BridgeTexCoord{v.texCoord.u, v.texCoord.v};
|
||||
});
|
||||
}
|
||||
cache.positions.resize(vertices.size());
|
||||
std::transform(vertices.begin(), vertices.end(), cache.positions.begin(), [](const D3DRMVERTEX& v) {
|
||||
return v.position;
|
||||
return GL11_BridgeVector{v.position.x, v.position.y, v.position.z};
|
||||
});
|
||||
cache.normals.resize(vertices.size());
|
||||
std::transform(vertices.begin(), vertices.end(), cache.normals.begin(), [](const D3DRMVERTEX& v) {
|
||||
return v.normal;
|
||||
return GL11_BridgeVector{v.normal.x, v.normal.y, v.normal.z};
|
||||
});
|
||||
|
||||
if (useVBOs) {
|
||||
glGenBuffers(1, &cache.vboPositions);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, cache.vboPositions);
|
||||
glBufferData(
|
||||
GL_ARRAY_BUFFER,
|
||||
cache.positions.size() * sizeof(D3DVECTOR),
|
||||
cache.positions.data(),
|
||||
GL_STATIC_DRAW
|
||||
);
|
||||
|
||||
glGenBuffers(1, &cache.vboNormals);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, cache.vboNormals);
|
||||
glBufferData(GL_ARRAY_BUFFER, cache.normals.size() * sizeof(D3DVECTOR), cache.normals.data(), GL_STATIC_DRAW);
|
||||
|
||||
if (meshGroup.texture != nullptr) {
|
||||
glGenBuffers(1, &cache.vboTexcoords);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, cache.vboTexcoords);
|
||||
glBufferData(
|
||||
GL_ARRAY_BUFFER,
|
||||
cache.texcoords.size() * sizeof(TexCoord),
|
||||
cache.texcoords.data(),
|
||||
GL_STATIC_DRAW
|
||||
);
|
||||
}
|
||||
|
||||
glGenBuffers(1, &cache.ibo);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cache.ibo);
|
||||
glBufferData(
|
||||
GL_ELEMENT_ARRAY_BUFFER,
|
||||
cache.indices.size() * sizeof(cache.indices[0]),
|
||||
cache.indices.data(),
|
||||
GL_STATIC_DRAW
|
||||
);
|
||||
}
|
||||
GL11_UploadMesh(cache, meshGroup.texture != nullptr);
|
||||
|
||||
return cache;
|
||||
}
|
||||
@ -297,12 +230,7 @@ void OpenGL1Renderer::AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh)
|
||||
auto* ctx = static_cast<GLMeshDestroyContext*>(arg);
|
||||
auto& cache = ctx->renderer->m_meshs[ctx->id];
|
||||
cache.meshGroup = nullptr;
|
||||
if (ctx->renderer->m_useVBOs) {
|
||||
glDeleteBuffers(1, &cache.vboPositions);
|
||||
glDeleteBuffers(1, &cache.vboNormals);
|
||||
glDeleteBuffers(1, &cache.vboTexcoords);
|
||||
glDeleteBuffers(1, &cache.ibo);
|
||||
}
|
||||
GL11_DestroyMesh(cache);
|
||||
delete ctx;
|
||||
},
|
||||
ctx
|
||||
@ -337,16 +265,6 @@ Uint32 OpenGL1Renderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGr
|
||||
return (Uint32) (m_meshs.size() - 1);
|
||||
}
|
||||
|
||||
DWORD OpenGL1Renderer::GetWidth()
|
||||
{
|
||||
return m_width;
|
||||
}
|
||||
|
||||
DWORD OpenGL1Renderer::GetHeight()
|
||||
{
|
||||
return m_height;
|
||||
}
|
||||
|
||||
void OpenGL1Renderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc)
|
||||
{
|
||||
halDesc->dcmColorModel = D3DCOLORMODEL::RGB;
|
||||
@ -362,191 +280,119 @@ void OpenGL1Renderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc)
|
||||
|
||||
const char* OpenGL1Renderer::GetName()
|
||||
{
|
||||
return "OpenGL 1.2 HAL";
|
||||
return "OpenGL 1.1 HAL";
|
||||
}
|
||||
|
||||
HRESULT OpenGL1Renderer::BeginFrame()
|
||||
{
|
||||
SDL_GL_MakeCurrent(DDWindow, m_context);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
|
||||
glViewport(0, 0, m_width, m_height);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_TRUE);
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_COLOR_MATERIAL);
|
||||
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
|
||||
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// Disable all lights and reset global ambient
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
glDisable(GL_LIGHT0 + i);
|
||||
}
|
||||
const GLfloat zeroAmbient[4] = {0.f, 0.f, 0.f, 1.f};
|
||||
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, zeroAmbient);
|
||||
glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
|
||||
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
|
||||
|
||||
// Setup lights
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
GL11_BeginFrame((Matrix4x4*) &m_projection[0][0]);
|
||||
|
||||
int lightIdx = 0;
|
||||
for (const auto& l : m_lights) {
|
||||
if (lightIdx > 7) {
|
||||
break;
|
||||
}
|
||||
GLenum lightId = GL_LIGHT0 + lightIdx++;
|
||||
const FColor& c = l.color;
|
||||
GLfloat col[4] = {c.r, c.g, c.b, c.a};
|
||||
GL11_UploadLight(lightIdx, (GL11_BridgeSceneLight*) &l);
|
||||
|
||||
if (l.positional == 0.f && l.directional == 0.f) {
|
||||
// Ambient light only
|
||||
glLightfv(lightId, GL_AMBIENT, col);
|
||||
const GLfloat black[4] = {0.f, 0.f, 0.f, 1.f};
|
||||
glLightfv(lightId, GL_DIFFUSE, black);
|
||||
glLightfv(lightId, GL_SPECULAR, black);
|
||||
const GLfloat dummyPos[4] = {0.f, 0.f, 1.f, 0.f};
|
||||
glLightfv(lightId, GL_POSITION, dummyPos);
|
||||
}
|
||||
else {
|
||||
glLightfv(lightId, GL_AMBIENT, zeroAmbient);
|
||||
glLightfv(lightId, GL_DIFFUSE, col);
|
||||
if (l.directional == 1.0f) {
|
||||
glLightfv(lightId, GL_SPECULAR, col);
|
||||
}
|
||||
else {
|
||||
const GLfloat black[4] = {0.f, 0.f, 0.f, 1.f};
|
||||
glLightfv(lightId, GL_SPECULAR, black);
|
||||
}
|
||||
|
||||
GLfloat pos[4];
|
||||
if (l.directional == 1.f) {
|
||||
pos[0] = -l.direction.x;
|
||||
pos[1] = -l.direction.y;
|
||||
pos[2] = -l.direction.z;
|
||||
pos[3] = 0.f;
|
||||
}
|
||||
else {
|
||||
pos[0] = l.position.x;
|
||||
pos[1] = l.position.y;
|
||||
pos[2] = l.position.z;
|
||||
pos[3] = 1.f;
|
||||
}
|
||||
glLightfv(lightId, GL_POSITION, pos);
|
||||
}
|
||||
glEnable(lightId);
|
||||
lightIdx++;
|
||||
}
|
||||
glPopMatrix();
|
||||
|
||||
// Projection and view
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadMatrixf(&m_projection[0][0]);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
void OpenGL1Renderer::EnableTransparency()
|
||||
{
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDepthMask(GL_FALSE);
|
||||
GL11_EnableTransparency();
|
||||
}
|
||||
|
||||
void OpenGL1Renderer::SubmitDraw(
|
||||
DWORD meshId,
|
||||
const D3DRMMATRIX4D& modelViewMatrix,
|
||||
const D3DRMMATRIX4D& worldMatrix,
|
||||
const D3DRMMATRIX4D& viewMatrix,
|
||||
const Matrix3x3& normalMatrix,
|
||||
const Appearance& appearance
|
||||
)
|
||||
{
|
||||
auto& mesh = m_meshs[meshId];
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
|
||||
glLoadMatrixf(&modelViewMatrix[0][0]);
|
||||
glEnable(GL_NORMALIZE);
|
||||
|
||||
glColor4ub(appearance.color.r, appearance.color.g, appearance.color.b, appearance.color.a);
|
||||
|
||||
if (appearance.shininess != 0.0f) {
|
||||
GLfloat whiteSpec[] = {1.f, 1.f, 1.f, 1.f};
|
||||
glMaterialfv(GL_FRONT, GL_SPECULAR, whiteSpec);
|
||||
glMaterialf(GL_FRONT, GL_SHININESS, appearance.shininess);
|
||||
}
|
||||
else {
|
||||
GLfloat noSpec[] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
glMaterialfv(GL_FRONT, GL_SPECULAR, noSpec);
|
||||
glMaterialf(GL_FRONT, GL_SHININESS, 0.0f);
|
||||
}
|
||||
|
||||
if (mesh.flat) {
|
||||
glShadeModel(GL_FLAT);
|
||||
}
|
||||
else {
|
||||
glShadeModel(GL_SMOOTH);
|
||||
}
|
||||
|
||||
// Bind texture if present
|
||||
if (appearance.textureId != NO_TEXTURE_ID) {
|
||||
auto& tex = m_textures[appearance.textureId];
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, tex.glTextureId);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
GL11_SubmitDraw(mesh, modelViewMatrix, appearance, tex.glTextureId);
|
||||
}
|
||||
else {
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
GL11_SubmitDraw(mesh, modelViewMatrix, appearance, 0);
|
||||
}
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
if (m_useVBOs) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mesh.vboPositions);
|
||||
glVertexPointer(3, GL_FLOAT, 0, nullptr);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mesh.vboNormals);
|
||||
glNormalPointer(GL_FLOAT, 0, nullptr);
|
||||
|
||||
if (appearance.textureId != NO_TEXTURE_ID) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mesh.vboTexcoords);
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, nullptr);
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.ibo);
|
||||
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(mesh.indices.size()), GL_UNSIGNED_SHORT, nullptr);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
}
|
||||
else {
|
||||
glVertexPointer(3, GL_FLOAT, 0, mesh.positions.data());
|
||||
glNormalPointer(GL_FLOAT, 0, mesh.normals.data());
|
||||
if (appearance.textureId != NO_TEXTURE_ID) {
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, mesh.texcoords.data());
|
||||
}
|
||||
|
||||
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(mesh.indices.size()), GL_UNSIGNED_SHORT, mesh.indices.data());
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
HRESULT OpenGL1Renderer::FinalizeFrame()
|
||||
{
|
||||
glReadPixels(0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_BYTE, m_renderedImage->pixels);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
// Composite onto SDL backbuffer
|
||||
SDL_BlitSurface(m_renderedImage, nullptr, DDBackBuffer, nullptr);
|
||||
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
void OpenGL1Renderer::Resize(int width, int height, const ViewportTransform& viewportTransform)
|
||||
{
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_viewportTransform = viewportTransform;
|
||||
SDL_DestroySurface(m_renderedImage);
|
||||
m_renderedImage = SDL_CreateSurface(m_width, m_height, SDL_PIXELFORMAT_RGBA32);
|
||||
GL11_Resize(width, height);
|
||||
}
|
||||
|
||||
void OpenGL1Renderer::Clear(float r, float g, float b)
|
||||
{
|
||||
m_dirty = true;
|
||||
GL11_Clear(r, g, b);
|
||||
}
|
||||
|
||||
void OpenGL1Renderer::Flip()
|
||||
{
|
||||
if (m_dirty) {
|
||||
SDL_GL_SwapWindow(DDWindow);
|
||||
m_dirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGL1Renderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect)
|
||||
{
|
||||
m_dirty = true;
|
||||
|
||||
float left = -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 bottom = (m_height - m_viewportTransform.offsetY) / m_viewportTransform.scale;
|
||||
|
||||
GL11_Draw2DImage(m_textures[textureId].glTextureId, srcRect, dstRect, left, right, bottom, top);
|
||||
}
|
||||
|
||||
void OpenGL1Renderer::Download(SDL_Surface* target)
|
||||
{
|
||||
GL11_Download(m_renderedImage);
|
||||
|
||||
SDL_Rect srcRect = {
|
||||
static_cast<int>(m_viewportTransform.offsetX),
|
||||
static_cast<int>(m_viewportTransform.offsetY),
|
||||
static_cast<int>(target->w * m_viewportTransform.scale),
|
||||
static_cast<int>(target->h * m_viewportTransform.scale),
|
||||
};
|
||||
|
||||
SDL_Surface* bufferClone = SDL_CreateSurface(target->w, target->h, SDL_PIXELFORMAT_RGBA32);
|
||||
if (!bufferClone) {
|
||||
SDL_Log("SDL_CreateSurface: %s", SDL_GetError());
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_BlitSurfaceScaled(m_renderedImage, &srcRect, bufferClone, nullptr, SDL_SCALEMODE_NEAREST);
|
||||
|
||||
// Flip image vertically into target
|
||||
SDL_Rect rowSrc = {0, 0, bufferClone->w, 1};
|
||||
SDL_Rect rowDst = {0, 0, bufferClone->w, 1};
|
||||
for (int y = 0; y < bufferClone->h; ++y) {
|
||||
rowSrc.y = y;
|
||||
rowDst.y = bufferClone->h - 1 - y;
|
||||
SDL_BlitSurface(bufferClone, &rowSrc, target, &rowDst);
|
||||
}
|
||||
|
||||
SDL_DestroySurface(bufferClone);
|
||||
}
|
||||
|
||||
@ -30,6 +30,12 @@ struct SceneLightGLES2 {
|
||||
|
||||
Direct3DRMRenderer* OpenGLES2Renderer::Create(DWORD width, DWORD height)
|
||||
{
|
||||
// We have to reset the attributes here after having enumerated the
|
||||
// OpenGL ES 2.0 renderer, or else SDL gets very confused by SDL_GL_DEPTH_SIZE
|
||||
// call below when on an EGL-based backend, and crashes with EGL_BAD_MATCH.
|
||||
SDL_GL_ResetAttributes();
|
||||
// But ResetAttributes resets it to 16.
|
||||
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||
@ -50,51 +56,16 @@ Direct3DRMRenderer* OpenGLES2Renderer::Create(DWORD width, DWORD height)
|
||||
}
|
||||
|
||||
if (!SDL_GL_MakeCurrent(window, context)) {
|
||||
if (testWindow) {
|
||||
SDL_DestroyWindow(window);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
glFrontFace(GL_CCW);
|
||||
|
||||
// Setup FBO
|
||||
GLuint fbo;
|
||||
glGenFramebuffers(1, &fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
|
||||
// Create color texture
|
||||
GLuint colorTex;
|
||||
glGenTextures(1, &colorTex);
|
||||
glBindTexture(GL_TEXTURE_2D, colorTex);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTex, 0);
|
||||
|
||||
// Create depth renderbuffer
|
||||
GLuint depthRb;
|
||||
glGenRenderbuffers(1, &depthRb);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, depthRb);
|
||||
const char* extensions = (const char*) glGetString(GL_EXTENSIONS);
|
||||
if (extensions) {
|
||||
if (strstr(extensions, "GL_OES_depth24")) {
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES, width, height);
|
||||
}
|
||||
else if (strstr(extensions, "GL_OES_depth32")) {
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32_OES, width, height);
|
||||
}
|
||||
}
|
||||
else {
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
|
||||
}
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRb);
|
||||
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||
return nullptr;
|
||||
}
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glFrontFace(GL_CW);
|
||||
|
||||
const char* vertexShaderSource = R"(
|
||||
attribute vec3 a_position;
|
||||
@ -183,6 +154,7 @@ Direct3DRMRenderer* OpenGLES2Renderer::Create(DWORD width, DWORD height)
|
||||
if (u_useTexture != 0) {
|
||||
vec4 texel = texture2D(u_texture, v_texCoord);
|
||||
finalColor.rgb = clamp(texel.rgb * finalColor.rgb, 0.0, 1.0);
|
||||
finalColor.a = texel.a;
|
||||
}
|
||||
|
||||
gl_FragColor = finalColor;
|
||||
@ -206,31 +178,23 @@ Direct3DRMRenderer* OpenGLES2Renderer::Create(DWORD width, DWORD height)
|
||||
SDL_DestroyWindow(window);
|
||||
}
|
||||
|
||||
return new OpenGLES2Renderer(width, height, context, fbo, colorTex, depthRb, shaderProgram);
|
||||
return new OpenGLES2Renderer(width, height, context, shaderProgram);
|
||||
}
|
||||
|
||||
OpenGLES2Renderer::OpenGLES2Renderer(
|
||||
DWORD width,
|
||||
DWORD height,
|
||||
SDL_GLContext context,
|
||||
GLuint fbo,
|
||||
GLuint colorTex,
|
||||
GLuint depthRb,
|
||||
GLuint shaderProgram
|
||||
)
|
||||
: m_width(width), m_height(height), m_context(context), m_fbo(fbo), m_colorTex(colorTex), m_depthRb(depthRb),
|
||||
m_shaderProgram(shaderProgram)
|
||||
OpenGLES2Renderer::OpenGLES2Renderer(DWORD width, DWORD height, SDL_GLContext context, GLuint shaderProgram)
|
||||
: m_context(context), m_shaderProgram(shaderProgram)
|
||||
{
|
||||
m_renderedImage = SDL_CreateSurface(m_width, m_height, SDL_PIXELFORMAT_ABGR8888);
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_virtualWidth = width;
|
||||
m_virtualHeight = height;
|
||||
m_renderedImage = SDL_CreateSurface(m_width, m_height, SDL_PIXELFORMAT_RGBA32);
|
||||
}
|
||||
|
||||
OpenGLES2Renderer::~OpenGLES2Renderer()
|
||||
{
|
||||
SDL_DestroySurface(m_renderedImage);
|
||||
glDeleteFramebuffers(1, &m_fbo);
|
||||
glDeleteRenderbuffers(1, &m_depthRb);
|
||||
glDeleteProgram(m_shaderProgram);
|
||||
glDeleteTextures(1, &m_colorTex);
|
||||
}
|
||||
|
||||
void OpenGLES2Renderer::PushLights(const SceneLight* lightsArray, size_t count)
|
||||
@ -250,7 +214,6 @@ void OpenGLES2Renderer::SetFrustumPlanes(const Plane* frustumPlanes)
|
||||
void OpenGLES2Renderer::SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back)
|
||||
{
|
||||
memcpy(&m_projection, projection, sizeof(D3DRMMATRIX4D));
|
||||
m_projection[1][1] *= -1.0f; // OpenGL is upside down
|
||||
}
|
||||
|
||||
struct TextureDestroyContextGLS2 {
|
||||
@ -289,14 +252,12 @@ Uint32 OpenGLES2Renderer::GetTextureId(IDirect3DRMTexture* iTexture)
|
||||
glGenTextures(1, &tex.glTextureId);
|
||||
glBindTexture(GL_TEXTURE_2D, tex.glTextureId);
|
||||
|
||||
SDL_Surface* surf = SDL_ConvertSurface(surface->m_surface, SDL_PIXELFORMAT_ABGR8888);
|
||||
SDL_Surface* surf = SDL_ConvertSurface(surface->m_surface, SDL_PIXELFORMAT_RGBA32);
|
||||
if (!surf) {
|
||||
return NO_TEXTURE_ID;
|
||||
}
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surf->w, surf->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surf->pixels);
|
||||
SDL_DestroySurface(surf);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
tex.version = texture->m_version;
|
||||
}
|
||||
@ -308,14 +269,11 @@ Uint32 OpenGLES2Renderer::GetTextureId(IDirect3DRMTexture* iTexture)
|
||||
glGenTextures(1, &texId);
|
||||
glBindTexture(GL_TEXTURE_2D, texId);
|
||||
|
||||
SDL_Surface* surf = SDL_ConvertSurface(surface->m_surface, SDL_PIXELFORMAT_ABGR8888);
|
||||
SDL_Surface* surf = SDL_ConvertSurface(surface->m_surface, SDL_PIXELFORMAT_RGBA32);
|
||||
if (!surf) {
|
||||
return NO_TEXTURE_ID;
|
||||
}
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surf->w, surf->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surf->pixels);
|
||||
SDL_DestroySurface(surf);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
for (Uint32 i = 0; i < m_textures.size(); ++i) {
|
||||
auto& tex = m_textures[i];
|
||||
@ -323,12 +281,15 @@ Uint32 OpenGLES2Renderer::GetTextureId(IDirect3DRMTexture* iTexture)
|
||||
tex.texture = texture;
|
||||
tex.version = texture->m_version;
|
||||
tex.glTextureId = texId;
|
||||
tex.width = surf->w;
|
||||
tex.height = surf->h;
|
||||
AddTextureDestroyCallback(i, texture);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
m_textures.push_back({texture, texture->m_version, texId});
|
||||
m_textures.push_back({texture, texture->m_version, texId, (uint16_t) surf->w, (uint16_t) surf->h});
|
||||
SDL_DestroySurface(surf);
|
||||
AddTextureDestroyCallback((Uint32) (m_textures.size() - 1), texture);
|
||||
return (Uint32) (m_textures.size() - 1);
|
||||
}
|
||||
@ -366,7 +327,6 @@ GLES2MeshCacheEntry GLES2UploadMesh(const MeshGroup& meshGroup)
|
||||
return v.texCoord;
|
||||
});
|
||||
}
|
||||
|
||||
std::vector<D3DVECTOR> positions(vertices.size());
|
||||
std::transform(vertices.begin(), vertices.end(), positions.begin(), [](const D3DRMVERTEX& v) {
|
||||
return v.position;
|
||||
@ -451,16 +411,6 @@ Uint32 OpenGLES2Renderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* mesh
|
||||
return (Uint32) (m_meshs.size() - 1);
|
||||
}
|
||||
|
||||
DWORD OpenGLES2Renderer::GetWidth()
|
||||
{
|
||||
return m_width;
|
||||
}
|
||||
|
||||
DWORD OpenGLES2Renderer::GetHeight()
|
||||
{
|
||||
return m_height;
|
||||
}
|
||||
|
||||
void OpenGLES2Renderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc)
|
||||
{
|
||||
halDesc->dcmColorModel = D3DCOLORMODEL::RGB;
|
||||
@ -490,9 +440,7 @@ const char* OpenGLES2Renderer::GetName()
|
||||
|
||||
HRESULT OpenGLES2Renderer::BeginFrame()
|
||||
{
|
||||
SDL_GL_MakeCurrent(DDWindow, m_context);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
|
||||
glViewport(0, 0, m_width, m_height);
|
||||
m_dirty = true;
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
@ -500,9 +448,6 @@ HRESULT OpenGLES2Renderer::BeginFrame()
|
||||
|
||||
glUseProgram(m_shaderProgram);
|
||||
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
SceneLightGLES2 lightData[3];
|
||||
int lightCount = std::min(static_cast<int>(m_lights.size()), 3);
|
||||
|
||||
@ -531,7 +476,6 @@ HRESULT OpenGLES2Renderer::BeginFrame()
|
||||
glUniform4fv(glGetUniformLocation(m_shaderProgram, (base + ".direction").c_str()), 1, lightData[i].direction);
|
||||
}
|
||||
glUniform1i(glGetUniformLocation(m_shaderProgram, "u_lightCount"), lightCount);
|
||||
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
@ -545,6 +489,8 @@ void OpenGLES2Renderer::EnableTransparency()
|
||||
void OpenGLES2Renderer::SubmitDraw(
|
||||
DWORD meshId,
|
||||
const D3DRMMATRIX4D& modelViewMatrix,
|
||||
const D3DRMMATRIX4D& worldMatrix,
|
||||
const D3DRMMATRIX4D& viewMatrix,
|
||||
const Matrix3x3& normalMatrix,
|
||||
const Appearance& appearance
|
||||
)
|
||||
@ -570,6 +516,8 @@ void OpenGLES2Renderer::SubmitDraw(
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, m_textures[appearance.textureId].glTextureId);
|
||||
glUniform1i(glGetUniformLocation(m_shaderProgram, "u_texture"), 0);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
}
|
||||
else {
|
||||
glUniform1i(glGetUniformLocation(m_shaderProgram, "u_useTexture"), 0);
|
||||
@ -606,11 +554,168 @@ HRESULT OpenGLES2Renderer::FinalizeFrame()
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
glUseProgram(0);
|
||||
|
||||
glReadPixels(0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_BYTE, m_renderedImage->pixels);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
// Composite onto SDL backbuffer
|
||||
SDL_BlitSurface(m_renderedImage, nullptr, DDBackBuffer, nullptr);
|
||||
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
void OpenGLES2Renderer::Resize(int width, int height, const ViewportTransform& viewportTransform)
|
||||
{
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_viewportTransform = viewportTransform;
|
||||
SDL_DestroySurface(m_renderedImage);
|
||||
m_renderedImage = SDL_CreateSurface(m_width, m_height, SDL_PIXELFORMAT_RGBA32);
|
||||
glViewport(0, 0, m_width, m_height);
|
||||
}
|
||||
|
||||
void OpenGLES2Renderer::Clear(float r, float g, float b)
|
||||
{
|
||||
m_dirty = true;
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_TRUE);
|
||||
glClearColor(r, g, b, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
void OpenGLES2Renderer::Flip()
|
||||
{
|
||||
if (m_dirty) {
|
||||
SDL_GL_SwapWindow(DDWindow);
|
||||
m_dirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
void CreateOrthoMatrix(float left, float right, float bottom, float top, D3DRMMATRIX4D& outMatrix)
|
||||
{
|
||||
float near = -1.0f;
|
||||
float far = 1.0f;
|
||||
float rl = right - left;
|
||||
float tb = top - bottom;
|
||||
float fn = far - near;
|
||||
|
||||
outMatrix[0][0] = 2.0f / rl;
|
||||
outMatrix[0][1] = 0.0f;
|
||||
outMatrix[0][2] = 0.0f;
|
||||
outMatrix[0][3] = 0.0f;
|
||||
|
||||
outMatrix[1][0] = 0.0f;
|
||||
outMatrix[1][1] = 2.0f / tb;
|
||||
outMatrix[1][2] = 0.0f;
|
||||
outMatrix[1][3] = 0.0f;
|
||||
|
||||
outMatrix[2][0] = 0.0f;
|
||||
outMatrix[2][1] = 0.0f;
|
||||
outMatrix[2][2] = -2.0f / fn;
|
||||
outMatrix[2][3] = 0.0f;
|
||||
|
||||
outMatrix[3][0] = -(right + left) / rl;
|
||||
outMatrix[3][1] = -(top + bottom) / tb;
|
||||
outMatrix[3][2] = -(far + near) / fn;
|
||||
outMatrix[3][3] = 1.0f;
|
||||
}
|
||||
|
||||
void OpenGLES2Renderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect)
|
||||
{
|
||||
m_dirty = true;
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_FALSE);
|
||||
|
||||
glUseProgram(m_shaderProgram);
|
||||
|
||||
float color[] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
float blank[] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
glUniform4fv(glGetUniformLocation(m_shaderProgram, "u_lights[0].color"), 1, color);
|
||||
glUniform4fv(glGetUniformLocation(m_shaderProgram, "u_lights[0].position"), 1, blank);
|
||||
glUniform4fv(glGetUniformLocation(m_shaderProgram, "u_lights[0].direction"), 1, blank);
|
||||
glUniform1i(glGetUniformLocation(m_shaderProgram, "u_lightCount"), 1);
|
||||
|
||||
glUniform4f(glGetUniformLocation(m_shaderProgram, "u_color"), 1.0f, 1.0f, 1.0f, 1.0f);
|
||||
glUniform1f(glGetUniformLocation(m_shaderProgram, "u_shininess"), 0.0f);
|
||||
|
||||
float left = -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 bottom = (m_height - m_viewportTransform.offsetY) / m_viewportTransform.scale;
|
||||
|
||||
D3DRMMATRIX4D projection;
|
||||
CreateOrthoMatrix(left, right, bottom, top, projection);
|
||||
|
||||
D3DRMMATRIX4D identity = {{1.f, 0.f, 0.f, 0.f}, {0.f, 1.f, 0.f, 0.f}, {0.f, 0.f, 1.f, 0.f}, {0.f, 0.f, 0.f, 1.f}};
|
||||
glUniformMatrix4fv(glGetUniformLocation(m_shaderProgram, "u_modelViewMatrix"), 1, GL_FALSE, &identity[0][0]);
|
||||
glUniformMatrix3fv(glGetUniformLocation(m_shaderProgram, "u_normalMatrix"), 1, GL_FALSE, &identity[0][0]);
|
||||
glUniformMatrix4fv(glGetUniformLocation(m_shaderProgram, "u_projectionMatrix"), 1, GL_FALSE, &projection[0][0]);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glUniform1i(glGetUniformLocation(m_shaderProgram, "u_useTexture"), 1);
|
||||
const GLES2TextureCacheEntry& texture = m_textures[textureId];
|
||||
glBindTexture(GL_TEXTURE_2D, texture.glTextureId);
|
||||
glUniform1i(glGetUniformLocation(m_shaderProgram, "u_texture"), 0);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
float texW = texture.width;
|
||||
float texH = texture.height;
|
||||
|
||||
float u1 = srcRect.x / texW;
|
||||
float v1 = srcRect.y / texH;
|
||||
float u2 = (srcRect.x + srcRect.w) / texW;
|
||||
float v2 = (srcRect.y + srcRect.h) / texH;
|
||||
|
||||
float x1 = static_cast<float>(dstRect.x);
|
||||
float y1 = static_cast<float>(dstRect.y);
|
||||
float x2 = x1 + dstRect.w;
|
||||
float y2 = y1 + dstRect.h;
|
||||
|
||||
GLfloat vertices[] = {x1, y1, u1, v1, x2, y1, u2, v1, x1, y2, u1, v2, x2, y2, u2, v2};
|
||||
|
||||
GLint posLoc = glGetAttribLocation(m_shaderProgram, "a_position");
|
||||
GLint texLoc = glGetAttribLocation(m_shaderProgram, "a_texCoord");
|
||||
|
||||
glEnableVertexAttribArray(posLoc);
|
||||
glEnableVertexAttribArray(texLoc);
|
||||
|
||||
glVertexAttribPointer(posLoc, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), vertices);
|
||||
glVertexAttribPointer(texLoc, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), vertices + 2);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
glDisableVertexAttribArray(posLoc);
|
||||
glDisableVertexAttribArray(texLoc);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
void OpenGLES2Renderer::Download(SDL_Surface* target)
|
||||
{
|
||||
glFinish();
|
||||
glReadPixels(0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_BYTE, m_renderedImage->pixels);
|
||||
|
||||
SDL_Rect srcRect = {
|
||||
static_cast<int>(m_viewportTransform.offsetX),
|
||||
static_cast<int>(m_viewportTransform.offsetY),
|
||||
static_cast<int>(target->w * m_viewportTransform.scale),
|
||||
static_cast<int>(target->h * m_viewportTransform.scale),
|
||||
};
|
||||
|
||||
SDL_Surface* bufferClone = SDL_CreateSurface(target->w, target->h, SDL_PIXELFORMAT_RGBA32);
|
||||
if (!bufferClone) {
|
||||
SDL_Log("SDL_CreateSurface: %s", SDL_GetError());
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_BlitSurfaceScaled(m_renderedImage, &srcRect, bufferClone, nullptr, SDL_SCALEMODE_NEAREST);
|
||||
|
||||
// Flip image vertically into target
|
||||
SDL_Rect rowSrc = {0, 0, bufferClone->w, 1};
|
||||
SDL_Rect rowDst = {0, 0, bufferClone->w, 1};
|
||||
for (int y = 0; y < bufferClone->h; ++y) {
|
||||
rowSrc.y = y;
|
||||
rowDst.y = bufferClone->h - 1 - y;
|
||||
SDL_BlitSurface(bufferClone, &rowSrc, target, &rowDst);
|
||||
}
|
||||
|
||||
SDL_DestroySurface(bufferClone);
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
#include "miniwin.h"
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
|
||||
struct ScopedSurface {
|
||||
@ -91,7 +92,12 @@ struct ScopedShader {
|
||||
void release() { ptr = nullptr; }
|
||||
};
|
||||
|
||||
static SDL_GPUGraphicsPipeline* InitializeGraphicsPipeline(SDL_GPUDevice* device, bool depthWrite)
|
||||
static SDL_GPUGraphicsPipeline* InitializeGraphicsPipeline(
|
||||
SDL_GPUDevice* device,
|
||||
SDL_Window* window,
|
||||
bool depthTest,
|
||||
bool depthWrite
|
||||
)
|
||||
{
|
||||
const SDL_GPUShaderCreateInfo* vertexCreateInfo =
|
||||
GetVertexShaderCode(VertexShaderId::PositionColor, SDL_GetGPUShaderFormats(device));
|
||||
@ -141,8 +147,8 @@ static SDL_GPUGraphicsPipeline* InitializeGraphicsPipeline(SDL_GPUDevice* device
|
||||
vertexInputState.num_vertex_attributes = SDL_arraysize(vertexAttrs);
|
||||
|
||||
SDL_GPUColorTargetDescription colorTargets = {};
|
||||
colorTargets.format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM;
|
||||
if (depthWrite) {
|
||||
colorTargets.format = SDL_GetGPUSwapchainTextureFormat(device, window);
|
||||
if (depthTest && depthWrite) {
|
||||
colorTargets.blend_state.enable_blend = false;
|
||||
}
|
||||
else {
|
||||
@ -170,7 +176,7 @@ static SDL_GPUGraphicsPipeline* InitializeGraphicsPipeline(SDL_GPUDevice* device
|
||||
pipelineCreateInfo.rasterizer_state = rasterizerState;
|
||||
pipelineCreateInfo.depth_stencil_state.compare_op = SDL_GPU_COMPAREOP_GREATER;
|
||||
pipelineCreateInfo.depth_stencil_state.write_mask = 0xff;
|
||||
pipelineCreateInfo.depth_stencil_state.enable_depth_test = true;
|
||||
pipelineCreateInfo.depth_stencil_state.enable_depth_test = depthTest;
|
||||
pipelineCreateInfo.depth_stencil_state.enable_depth_write = depthWrite;
|
||||
pipelineCreateInfo.depth_stencil_state.enable_stencil_test = false;
|
||||
pipelineCreateInfo.target_info.color_target_descriptions = &colorTargets;
|
||||
@ -178,16 +184,18 @@ static SDL_GPUGraphicsPipeline* InitializeGraphicsPipeline(SDL_GPUDevice* device
|
||||
pipelineCreateInfo.target_info.depth_stencil_format = SDL_GPU_TEXTUREFORMAT_D32_FLOAT;
|
||||
pipelineCreateInfo.target_info.has_depth_stencil_target = true;
|
||||
|
||||
SDL_GPUGraphicsPipeline* pipeline = SDL_CreateGPUGraphicsPipeline(device, &pipelineCreateInfo);
|
||||
|
||||
return pipeline;
|
||||
return SDL_CreateGPUGraphicsPipeline(device, &pipelineCreateInfo);
|
||||
}
|
||||
|
||||
Direct3DRMRenderer* Direct3DRMSDL3GPURenderer::Create(DWORD width, DWORD height)
|
||||
{
|
||||
ScopedDevice device{SDL_CreateGPUDevice(
|
||||
SDL_GPU_SHADERFORMAT_SPIRV | SDL_GPU_SHADERFORMAT_DXIL | SDL_GPU_SHADERFORMAT_MSL,
|
||||
#ifdef DEBUG
|
||||
true,
|
||||
#else
|
||||
false,
|
||||
#endif
|
||||
nullptr
|
||||
)};
|
||||
if (!device.ptr) {
|
||||
@ -195,63 +203,63 @@ Direct3DRMRenderer* Direct3DRMSDL3GPURenderer::Create(DWORD width, DWORD height)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ScopedPipeline opaquePipeline{device.ptr, InitializeGraphicsPipeline(device.ptr, true)};
|
||||
SDL_Window* window = DDWindow;
|
||||
bool testWindow = false;
|
||||
if (!window) {
|
||||
window = SDL_CreateWindow("SDL_GPU test", width, height, SDL_WINDOW_HIDDEN);
|
||||
if (!window) {
|
||||
SDL_Log("SDL_CreateWindow: %s", SDL_GetError());
|
||||
return nullptr;
|
||||
}
|
||||
testWindow = true;
|
||||
}
|
||||
|
||||
if (!SDL_ClaimWindowForGPUDevice(device.ptr, window)) {
|
||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_ClaimWindowForGPUDevice: %s", SDL_GetError());
|
||||
if (testWindow) {
|
||||
SDL_DestroyWindow(window);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ScopedPipeline opaquePipeline{device.ptr, InitializeGraphicsPipeline(device.ptr, window, true, true)};
|
||||
if (!opaquePipeline.ptr) {
|
||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "InitializeGraphicsPipeline for opaquePipeline");
|
||||
if (testWindow) {
|
||||
SDL_DestroyWindow(window);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ScopedPipeline transparentPipeline{device.ptr, InitializeGraphicsPipeline(device.ptr, false)};
|
||||
ScopedPipeline transparentPipeline{device.ptr, InitializeGraphicsPipeline(device.ptr, window, true, false)};
|
||||
if (!transparentPipeline.ptr) {
|
||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "InitializeGraphicsPipeline for transparentPipeline");
|
||||
if (testWindow) {
|
||||
SDL_DestroyWindow(window);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SDL_GPUTextureCreateInfo textureInfo = {};
|
||||
textureInfo.type = SDL_GPU_TEXTURETYPE_2D;
|
||||
textureInfo.format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM;
|
||||
textureInfo.usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET;
|
||||
textureInfo.width = width;
|
||||
textureInfo.height = height;
|
||||
textureInfo.layer_count_or_depth = 1;
|
||||
textureInfo.num_levels = 1;
|
||||
textureInfo.sample_count = SDL_GPU_SAMPLECOUNT_1;
|
||||
ScopedTexture transferTexture{device.ptr, SDL_CreateGPUTexture(device.ptr, &textureInfo)};
|
||||
if (!transferTexture.ptr) {
|
||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_CreateGPUTexture for backbuffer failed (%s)", SDL_GetError());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SDL_GPUTextureCreateInfo depthTexInfo = textureInfo;
|
||||
depthTexInfo.format = SDL_GPU_TEXTUREFORMAT_D32_FLOAT;
|
||||
depthTexInfo.usage = SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET;
|
||||
ScopedTexture depthTexture{device.ptr, SDL_CreateGPUTexture(device.ptr, &depthTexInfo)};
|
||||
if (!depthTexture.ptr) {
|
||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_CreateGPUTexture for depth buffer (%s)", SDL_GetError());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Setup texture GPU-to-CPU transfer
|
||||
SDL_GPUTransferBufferCreateInfo downloadBufferInfo = {};
|
||||
downloadBufferInfo.usage = SDL_GPU_TRANSFERBUFFERUSAGE_DOWNLOAD;
|
||||
downloadBufferInfo.size = width * height * 4;
|
||||
ScopedTransferBuffer downloadBuffer{device.ptr, SDL_CreateGPUTransferBuffer(device.ptr, &downloadBufferInfo)};
|
||||
if (!downloadBuffer.ptr) {
|
||||
SDL_LogError(
|
||||
LOG_CATEGORY_MINIWIN,
|
||||
"SDL_CreateGPUTransferBuffer filed for download buffer (%s)",
|
||||
SDL_GetError()
|
||||
);
|
||||
ScopedPipeline uiPipeline{device.ptr, InitializeGraphicsPipeline(device.ptr, window, false, false)};
|
||||
if (!uiPipeline.ptr) {
|
||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "InitializeGraphicsPipeline for uiPipeline");
|
||||
if (testWindow) {
|
||||
SDL_DestroyWindow(window);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Setup texture CPU-to-GPU transfer
|
||||
SDL_GPUTransferBufferCreateInfo uploadBufferInfo = {};
|
||||
uploadBufferInfo.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD;
|
||||
uploadBufferInfo.size = 256 * 256 * 4; // Largest known game texture
|
||||
int uploadBufferSize = 640 * 480 * 4; // Largest known game texture
|
||||
uploadBufferInfo.size = uploadBufferSize;
|
||||
ScopedTransferBuffer uploadBuffer{device.ptr, SDL_CreateGPUTransferBuffer(device.ptr, &uploadBufferInfo)};
|
||||
if (!uploadBuffer.ptr) {
|
||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_CreateGPUTransferBuffer filed for upload buffer (%s)", SDL_GetError());
|
||||
if (testWindow) {
|
||||
SDL_DestroyWindow(window);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -265,31 +273,54 @@ Direct3DRMRenderer* Direct3DRMSDL3GPURenderer::Create(DWORD width, DWORD height)
|
||||
ScopedSampler sampler{device.ptr, SDL_CreateGPUSampler(device.ptr, &samplerInfo)};
|
||||
if (!sampler.ptr) {
|
||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "Failed to create sampler: %s", SDL_GetError());
|
||||
if (testWindow) {
|
||||
SDL_DestroyWindow(window);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SDL_GPUSamplerCreateInfo uiSamplerInfo = {};
|
||||
uiSamplerInfo.min_filter = SDL_GPU_FILTER_LINEAR;
|
||||
uiSamplerInfo.mag_filter = SDL_GPU_FILTER_NEAREST;
|
||||
uiSamplerInfo.mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_LINEAR;
|
||||
uiSamplerInfo.address_mode_u = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE;
|
||||
uiSamplerInfo.address_mode_v = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE;
|
||||
uiSamplerInfo.address_mode_w = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE;
|
||||
ScopedSampler uiSampler{device.ptr, SDL_CreateGPUSampler(device.ptr, &uiSamplerInfo)};
|
||||
if (!uiSampler.ptr) {
|
||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "Failed to create sampler: %s", SDL_GetError());
|
||||
if (testWindow) {
|
||||
SDL_DestroyWindow(window);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (testWindow) {
|
||||
SDL_ReleaseWindowFromGPUDevice(device.ptr, window);
|
||||
SDL_DestroyWindow(window);
|
||||
}
|
||||
|
||||
auto renderer = new Direct3DRMSDL3GPURenderer(
|
||||
width,
|
||||
height,
|
||||
device.ptr,
|
||||
opaquePipeline.ptr,
|
||||
transparentPipeline.ptr,
|
||||
transferTexture.ptr,
|
||||
depthTexture.ptr,
|
||||
uiPipeline.ptr,
|
||||
sampler.ptr,
|
||||
uiSampler.ptr,
|
||||
uploadBuffer.ptr,
|
||||
downloadBuffer.ptr
|
||||
uploadBufferSize
|
||||
);
|
||||
|
||||
// Release resources so they don't get cleaned up
|
||||
device.release();
|
||||
opaquePipeline.release();
|
||||
transparentPipeline.release();
|
||||
transferTexture.release();
|
||||
depthTexture.release();
|
||||
uiPipeline.release();
|
||||
sampler.release();
|
||||
uiSampler.release();
|
||||
uploadBuffer.release();
|
||||
downloadBuffer.release();
|
||||
|
||||
return renderer;
|
||||
}
|
||||
@ -300,17 +331,21 @@ Direct3DRMSDL3GPURenderer::Direct3DRMSDL3GPURenderer(
|
||||
SDL_GPUDevice* device,
|
||||
SDL_GPUGraphicsPipeline* opaquePipeline,
|
||||
SDL_GPUGraphicsPipeline* transparentPipeline,
|
||||
SDL_GPUTexture* transferTexture,
|
||||
SDL_GPUTexture* depthTexture,
|
||||
SDL_GPUGraphicsPipeline* uiPipeline,
|
||||
SDL_GPUSampler* sampler,
|
||||
SDL_GPUSampler* uiSampler,
|
||||
SDL_GPUTransferBuffer* uploadBuffer,
|
||||
SDL_GPUTransferBuffer* downloadBuffer
|
||||
int uploadBufferSize
|
||||
)
|
||||
: m_width(width), m_height(height), m_device(device), m_opaquePipeline(opaquePipeline),
|
||||
m_transparentPipeline(transparentPipeline), m_transferTexture(transferTexture), m_depthTexture(depthTexture),
|
||||
m_sampler(sampler), m_uploadBuffer(uploadBuffer), m_downloadBuffer(downloadBuffer)
|
||||
: m_device(device), m_opaquePipeline(opaquePipeline), m_transparentPipeline(transparentPipeline),
|
||||
m_uiPipeline(uiPipeline), m_sampler(sampler), m_uiSampler(uiSampler), m_uploadBuffer(uploadBuffer),
|
||||
m_uploadBufferSize(uploadBufferSize)
|
||||
{
|
||||
SDL_Surface* dummySurface = SDL_CreateSurface(1, 1, SDL_PIXELFORMAT_ABGR8888);
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_virtualWidth = width;
|
||||
m_virtualHeight = height;
|
||||
SDL_Surface* dummySurface = SDL_CreateSurface(1, 1, SDL_PIXELFORMAT_RGBA32);
|
||||
if (!dummySurface) {
|
||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "Failed to create surface: %s", SDL_GetError());
|
||||
return;
|
||||
@ -324,35 +359,67 @@ Direct3DRMSDL3GPURenderer::Direct3DRMSDL3GPURenderer(
|
||||
SDL_UnlockSurface(dummySurface);
|
||||
|
||||
m_dummyTexture = CreateTextureFromSurface(dummySurface);
|
||||
if (!m_dummyTexture) {
|
||||
SDL_DestroySurface(dummySurface);
|
||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "Failed to create surface: %s", SDL_GetError());
|
||||
return;
|
||||
}
|
||||
SDL_DestroySurface(dummySurface);
|
||||
|
||||
ViewportTransform viewportTransform = {1.0f, 0.0f, 0.0f};
|
||||
Resize(m_width, m_height, viewportTransform);
|
||||
|
||||
m_uiMesh.vertices = {
|
||||
{{0.0f, 0.0f, 0.0f}, {0, 0, -1}, {0.0f, 0.0f}},
|
||||
{{1.0f, 0.0f, 0.0f}, {0, 0, -1}, {1.0f, 0.0f}},
|
||||
{{1.0f, 1.0f, 0.0f}, {0, 0, -1}, {1.0f, 1.0f}},
|
||||
{{0.0f, 1.0f, 0.0f}, {0, 0, -1}, {0.0f, 1.0f}}
|
||||
};
|
||||
m_uiMesh.indices = {0, 1, 2, 0, 2, 3};
|
||||
m_uiMeshCache = UploadMesh(m_uiMesh);
|
||||
}
|
||||
|
||||
Direct3DRMSDL3GPURenderer::~Direct3DRMSDL3GPURenderer()
|
||||
{
|
||||
SDL_ReleaseGPUTransferBuffer(m_device, m_downloadBuffer);
|
||||
SDL_ReleaseGPUBuffer(m_device, m_uiMeshCache.vertexBuffer);
|
||||
SDL_ReleaseGPUBuffer(m_device, m_uiMeshCache.indexBuffer);
|
||||
if (DDWindow) {
|
||||
SDL_ReleaseWindowFromGPUDevice(m_device, DDWindow);
|
||||
}
|
||||
if (m_downloadBuffer) {
|
||||
SDL_ReleaseGPUTransferBuffer(m_device, m_downloadBuffer);
|
||||
}
|
||||
if (m_uploadBuffer) {
|
||||
SDL_ReleaseGPUTransferBuffer(m_device, m_uploadBuffer);
|
||||
}
|
||||
SDL_ReleaseGPUSampler(m_device, m_sampler);
|
||||
SDL_ReleaseGPUTexture(m_device, m_dummyTexture);
|
||||
SDL_ReleaseGPUTexture(m_device, m_depthTexture);
|
||||
SDL_ReleaseGPUTexture(m_device, m_transferTexture);
|
||||
SDL_ReleaseGPUSampler(m_device, m_uiSampler);
|
||||
if (m_dummyTexture) {
|
||||
SDL_ReleaseGPUTexture(m_device, m_dummyTexture);
|
||||
}
|
||||
if (m_depthTexture) {
|
||||
SDL_ReleaseGPUTexture(m_device, m_depthTexture);
|
||||
}
|
||||
if (m_transferTexture) {
|
||||
SDL_ReleaseGPUTexture(m_device, m_transferTexture);
|
||||
}
|
||||
SDL_ReleaseGPUGraphicsPipeline(m_device, m_opaquePipeline);
|
||||
SDL_ReleaseGPUGraphicsPipeline(m_device, m_transparentPipeline);
|
||||
SDL_ReleaseGPUGraphicsPipeline(m_device, m_uiPipeline);
|
||||
if (m_uploadFence) {
|
||||
SDL_ReleaseGPUFence(m_device, m_uploadFence);
|
||||
}
|
||||
SDL_DestroyGPUDevice(m_device);
|
||||
}
|
||||
|
||||
void Direct3DRMSDL3GPURenderer::PushLights(const SceneLight* vertices, size_t count)
|
||||
void Direct3DRMSDL3GPURenderer::PushLights(const SceneLight* lights, size_t count)
|
||||
{
|
||||
if (count > 3) {
|
||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "Unsupported number of lights (%d)", static_cast<int>(count));
|
||||
count = 3;
|
||||
}
|
||||
int lightCount = std::min(static_cast<int>(count), 3);
|
||||
memcpy(&m_fragmentShadingData.lights, vertices, sizeof(SceneLight) * lightCount);
|
||||
memcpy(&m_fragmentShadingData.lights, lights, sizeof(SceneLight) * lightCount);
|
||||
m_fragmentShadingData.lightCount = lightCount;
|
||||
}
|
||||
|
||||
@ -364,7 +431,7 @@ void Direct3DRMSDL3GPURenderer::SetProjection(const D3DRMMATRIX4D& projection, D
|
||||
{
|
||||
m_front = front;
|
||||
m_back = back;
|
||||
memcpy(&m_uniforms.projection, projection, sizeof(D3DRMMATRIX4D));
|
||||
memcpy(&m_projection, projection, sizeof(D3DRMMATRIX4D));
|
||||
}
|
||||
|
||||
void Direct3DRMSDL3GPURenderer::WaitForPendingUpload()
|
||||
@ -405,7 +472,7 @@ void Direct3DRMSDL3GPURenderer::AddTextureDestroyCallback(Uint32 id, IDirect3DRM
|
||||
|
||||
SDL_GPUTexture* Direct3DRMSDL3GPURenderer::CreateTextureFromSurface(SDL_Surface* surface)
|
||||
{
|
||||
ScopedSurface surf{SDL_ConvertSurface(surface, SDL_PIXELFORMAT_ABGR8888)};
|
||||
ScopedSurface surf{SDL_ConvertSurface(surface, SDL_PIXELFORMAT_RGBA32)};
|
||||
if (!surf.ptr) {
|
||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_ConvertSurface (%s)", SDL_GetError());
|
||||
return nullptr;
|
||||
@ -607,6 +674,7 @@ void Direct3DRMSDL3GPURenderer::AddMeshDestroyCallback(Uint32 id, IDirect3DRMMes
|
||||
auto* ctx = static_cast<SDLMeshDestroyContext*>(arg);
|
||||
auto& cache = ctx->renderer->m_meshs[ctx->id];
|
||||
SDL_ReleaseGPUBuffer(ctx->renderer->m_device, cache.vertexBuffer);
|
||||
SDL_ReleaseGPUBuffer(ctx->renderer->m_device, cache.indexBuffer);
|
||||
cache.meshGroup = nullptr;
|
||||
delete ctx;
|
||||
},
|
||||
@ -621,6 +689,7 @@ Uint32 Direct3DRMSDL3GPURenderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGro
|
||||
if (cache.meshGroup == meshGroup) {
|
||||
if (cache.version != meshGroup->version) {
|
||||
SDL_ReleaseGPUBuffer(m_device, cache.vertexBuffer);
|
||||
SDL_ReleaseGPUBuffer(m_device, cache.indexBuffer);
|
||||
cache = std::move(UploadMesh(*meshGroup));
|
||||
}
|
||||
return i;
|
||||
@ -643,16 +712,6 @@ Uint32 Direct3DRMSDL3GPURenderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGro
|
||||
return (Uint32) (m_meshs.size() - 1);
|
||||
}
|
||||
|
||||
DWORD Direct3DRMSDL3GPURenderer::GetWidth()
|
||||
{
|
||||
return m_width;
|
||||
}
|
||||
|
||||
DWORD Direct3DRMSDL3GPURenderer::GetHeight()
|
||||
{
|
||||
return m_height;
|
||||
}
|
||||
|
||||
void Direct3DRMSDL3GPURenderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc)
|
||||
{
|
||||
halDesc->dcmColorModel = D3DCOLORMODEL::RGB;
|
||||
@ -708,32 +767,45 @@ SDL_GPUTransferBuffer* Direct3DRMSDL3GPURenderer::GetUploadBuffer(size_t size)
|
||||
return m_uploadBuffer;
|
||||
}
|
||||
|
||||
HRESULT Direct3DRMSDL3GPURenderer::BeginFrame()
|
||||
void Direct3DRMSDL3GPURenderer::StartRenderPass(float r, float g, float b, bool clear)
|
||||
{
|
||||
if (!DDBackBuffer) {
|
||||
return DDERR_GENERIC;
|
||||
m_cmdbuf = SDL_AcquireGPUCommandBuffer(m_device);
|
||||
if (!m_cmdbuf) {
|
||||
SDL_LogError(
|
||||
LOG_CATEGORY_MINIWIN,
|
||||
"SDL_AcquireGPUCommandBuffer in StartRenderPass failed (%s)",
|
||||
SDL_GetError()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear color and depth targets
|
||||
SDL_GPUColorTargetInfo colorTargetInfo = {};
|
||||
colorTargetInfo.texture = m_transferTexture;
|
||||
colorTargetInfo.clear_color = {0, 0, 0, 0};
|
||||
colorTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR;
|
||||
colorTargetInfo.clear_color = {r, g, b, 1.0f};
|
||||
colorTargetInfo.load_op = clear ? SDL_GPU_LOADOP_CLEAR : SDL_GPU_LOADOP_DONT_CARE;
|
||||
|
||||
SDL_GPUDepthStencilTargetInfo depthStencilTargetInfo = {};
|
||||
depthStencilTargetInfo.texture = m_depthTexture;
|
||||
depthStencilTargetInfo.clear_depth = 0.0f;
|
||||
depthStencilTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR;
|
||||
depthStencilTargetInfo.load_op = clear ? SDL_GPU_LOADOP_CLEAR : SDL_GPU_LOADOP_DONT_CARE;
|
||||
depthStencilTargetInfo.store_op = SDL_GPU_STOREOP_STORE;
|
||||
|
||||
m_cmdbuf = SDL_AcquireGPUCommandBuffer(m_device);
|
||||
if (!m_cmdbuf) {
|
||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_AcquireGPUCommandBuffer in BeginFrame failed (%s)", SDL_GetError());
|
||||
return DDERR_GENERIC;
|
||||
}
|
||||
|
||||
m_renderPass = SDL_BeginGPURenderPass(m_cmdbuf, &colorTargetInfo, 1, &depthStencilTargetInfo);
|
||||
}
|
||||
|
||||
void Direct3DRMSDL3GPURenderer::Clear(float r, float g, float b)
|
||||
{
|
||||
StartRenderPass(r, g, b, true);
|
||||
}
|
||||
|
||||
HRESULT Direct3DRMSDL3GPURenderer::BeginFrame()
|
||||
{
|
||||
if (!m_renderPass) {
|
||||
StartRenderPass(0, 0, 0, false);
|
||||
}
|
||||
SDL_BindGPUGraphicsPipeline(m_renderPass, m_opaquePipeline);
|
||||
memcpy(&m_uniforms.projection, m_projection, sizeof(D3DRMMATRIX4D));
|
||||
|
||||
return DD_OK;
|
||||
}
|
||||
@ -746,6 +818,8 @@ void Direct3DRMSDL3GPURenderer::EnableTransparency()
|
||||
void Direct3DRMSDL3GPURenderer::SubmitDraw(
|
||||
DWORD meshId,
|
||||
const D3DRMMATRIX4D& modelViewMatrix,
|
||||
const D3DRMMATRIX4D& worldMatrix,
|
||||
const D3DRMMATRIX4D& viewMatrix,
|
||||
const Matrix3x3& normalMatrix,
|
||||
const Appearance& appearance
|
||||
)
|
||||
@ -774,15 +848,210 @@ void Direct3DRMSDL3GPURenderer::SubmitDraw(
|
||||
|
||||
HRESULT Direct3DRMSDL3GPURenderer::FinalizeFrame()
|
||||
{
|
||||
SDL_EndGPURenderPass(m_renderPass);
|
||||
m_renderPass = nullptr;
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
void Direct3DRMSDL3GPURenderer::Resize(int width, int height, const ViewportTransform& viewportTransform)
|
||||
{
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_viewportTransform = viewportTransform;
|
||||
|
||||
if (!DDWindow) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_transferTexture) {
|
||||
SDL_ReleaseGPUTexture(m_device, m_transferTexture);
|
||||
}
|
||||
SDL_GPUTextureCreateInfo textureInfo = {};
|
||||
textureInfo.type = SDL_GPU_TEXTURETYPE_2D;
|
||||
textureInfo.format = SDL_GetGPUSwapchainTextureFormat(m_device, DDWindow);
|
||||
textureInfo.usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET | SDL_GPU_TEXTUREUSAGE_SAMPLER;
|
||||
textureInfo.width = m_width;
|
||||
textureInfo.height = m_height;
|
||||
textureInfo.layer_count_or_depth = 1;
|
||||
textureInfo.num_levels = 1;
|
||||
textureInfo.sample_count = SDL_GPU_SAMPLECOUNT_1;
|
||||
m_transferTexture = SDL_CreateGPUTexture(m_device, &textureInfo);
|
||||
if (!m_transferTexture) {
|
||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_CreateGPUTexture for backbuffer failed (%s)", SDL_GetError());
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_depthTexture) {
|
||||
SDL_ReleaseGPUTexture(m_device, m_depthTexture);
|
||||
}
|
||||
SDL_GPUTextureCreateInfo depthTexInfo = textureInfo;
|
||||
depthTexInfo.format = SDL_GPU_TEXTUREFORMAT_D32_FLOAT;
|
||||
depthTexInfo.usage = SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET;
|
||||
m_depthTexture = SDL_CreateGPUTexture(m_device, &depthTexInfo);
|
||||
if (!m_depthTexture) {
|
||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_CreateGPUTexture for depth buffer (%s)", SDL_GetError());
|
||||
return;
|
||||
}
|
||||
|
||||
// Setup texture GPU-to-CPU transfer
|
||||
SDL_GPUTransferBufferCreateInfo downloadBufferInfo = {};
|
||||
downloadBufferInfo.usage = SDL_GPU_TRANSFERBUFFERUSAGE_DOWNLOAD;
|
||||
downloadBufferInfo.size =
|
||||
((m_width - (m_viewportTransform.offsetX * 2)) * (m_height - (m_viewportTransform.offsetY * 2))) * 4;
|
||||
m_downloadBuffer = SDL_CreateGPUTransferBuffer(m_device, &downloadBufferInfo);
|
||||
if (!m_downloadBuffer) {
|
||||
SDL_LogError(
|
||||
LOG_CATEGORY_MINIWIN,
|
||||
"SDL_CreateGPUTransferBuffer filed for download buffer (%s)",
|
||||
SDL_GetError()
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void Direct3DRMSDL3GPURenderer::Flip()
|
||||
{
|
||||
if (!m_cmdbuf) {
|
||||
return;
|
||||
}
|
||||
if (m_renderPass) {
|
||||
SDL_EndGPURenderPass(m_renderPass);
|
||||
m_renderPass = nullptr;
|
||||
}
|
||||
|
||||
SDL_GPUTexture* swapchainTexture;
|
||||
if (!SDL_WaitAndAcquireGPUSwapchainTexture(m_cmdbuf, DDWindow, &swapchainTexture, nullptr, nullptr) ||
|
||||
!swapchainTexture) {
|
||||
SDL_Log("SDL_WaitAndAcquireGPUSwapchainTexture: %s", SDL_GetError());
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_GPUBlitInfo blit = {};
|
||||
blit.source.texture = m_transferTexture;
|
||||
blit.source.w = m_width;
|
||||
blit.source.h = m_height;
|
||||
blit.destination.texture = swapchainTexture;
|
||||
blit.destination.w = m_width;
|
||||
blit.destination.h = m_height;
|
||||
blit.load_op = SDL_GPU_LOADOP_DONT_CARE;
|
||||
blit.flip_mode = SDL_FLIP_NONE;
|
||||
blit.filter = SDL_GPU_FILTER_NEAREST;
|
||||
blit.cycle = false;
|
||||
SDL_BlitGPUTexture(m_cmdbuf, &blit);
|
||||
SDL_SubmitGPUCommandBuffer(m_cmdbuf);
|
||||
m_cmdbuf = nullptr;
|
||||
}
|
||||
|
||||
// TODO use SDL_SetGPUScissor(SDL_GPURenderPass *render_pass, const SDL_Rect *scissor) when srcRect isn't 100% of
|
||||
// texture
|
||||
|
||||
void Create2DTransformMatrix(
|
||||
const SDL_Rect& dstRect,
|
||||
float scale,
|
||||
float offsetX,
|
||||
float offsetY,
|
||||
D3DRMMATRIX4D& outMatrix
|
||||
)
|
||||
{
|
||||
float x = static_cast<float>(dstRect.x) * scale + offsetX;
|
||||
float y = static_cast<float>(dstRect.y) * scale + offsetY;
|
||||
float w = static_cast<float>(dstRect.w) * scale;
|
||||
float h = static_cast<float>(dstRect.h) * scale;
|
||||
|
||||
D3DVALUE tmp[4][4] = {{w, 0, 0, 0}, {0, h, 0, 0}, {0, 0, 1, 0}, {x, y, 0, 1}};
|
||||
memcpy(outMatrix, tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
void CreateOrthographicProjection(float width, float height, D3DRMMATRIX4D& outProj)
|
||||
{
|
||||
D3DVALUE tmp[4][4] = {
|
||||
{2.0f / width, 0.0f, 0.0f, 0.0f},
|
||||
{0.0f, -2.0f / height, 0.0f, 0.0f},
|
||||
{0.0f, 0.0f, 1.0f, 0.0f},
|
||||
{-1.0f, 1.0f, 0.0f, 1.0f}
|
||||
};
|
||||
memcpy(outProj, tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
void Direct3DRMSDL3GPURenderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect)
|
||||
{
|
||||
if (!m_renderPass) {
|
||||
StartRenderPass(0, 0, 0, false);
|
||||
}
|
||||
SDL_BindGPUGraphicsPipeline(m_renderPass, m_uiPipeline);
|
||||
|
||||
const SDL3TextureCache& tex = m_textures[textureId];
|
||||
|
||||
auto surface = static_cast<DirectDrawSurfaceImpl*>(tex.texture->m_surface);
|
||||
float scaleX = static_cast<float>(dstRect.w) / srcRect.w;
|
||||
float scaleY = static_cast<float>(dstRect.h) / srcRect.h;
|
||||
SDL_Rect expandedDstRect = {
|
||||
static_cast<int>(std::round(dstRect.x - srcRect.x * scaleX)),
|
||||
static_cast<int>(std::round(dstRect.y - srcRect.y * scaleY)),
|
||||
static_cast<int>(std::round(static_cast<float>(surface->m_surface->w) * scaleX)),
|
||||
static_cast<int>(std::round(static_cast<float>(surface->m_surface->h) * scaleY)),
|
||||
};
|
||||
|
||||
Create2DTransformMatrix(
|
||||
expandedDstRect,
|
||||
m_viewportTransform.scale,
|
||||
m_viewportTransform.offsetX,
|
||||
m_viewportTransform.offsetY,
|
||||
m_uniforms.worldViewMatrix
|
||||
);
|
||||
|
||||
CreateOrthographicProjection((float) m_width, (float) m_height, m_uniforms.projection);
|
||||
|
||||
SceneLight fullBright = {{1, 1, 1, 1}, {0, 0, 0}, 0, {0, 0, 0}, 0};
|
||||
memcpy(&m_fragmentShadingData.lights, &fullBright, sizeof(SceneLight));
|
||||
m_fragmentShadingData.lightCount = 1;
|
||||
m_fragmentShadingData.color = {0xff, 0xff, 0xff, 0xff};
|
||||
m_fragmentShadingData.shininess = 0.0f;
|
||||
m_fragmentShadingData.useTexture = 1;
|
||||
|
||||
SDL_GPUTextureSamplerBinding samplerBinding = {tex.gpuTexture, m_uiSampler};
|
||||
SDL_BindGPUFragmentSamplers(m_renderPass, 0, &samplerBinding, 1);
|
||||
SDL_PushGPUVertexUniformData(m_cmdbuf, 0, &m_uniforms, sizeof(m_uniforms));
|
||||
SDL_PushGPUFragmentUniformData(m_cmdbuf, 0, &m_fragmentShadingData, sizeof(m_fragmentShadingData));
|
||||
SDL_GPUBufferBinding vertexBufferBinding = {m_uiMeshCache.vertexBuffer};
|
||||
SDL_BindGPUVertexBuffers(m_renderPass, 0, &vertexBufferBinding, 1);
|
||||
SDL_GPUBufferBinding indexBufferBinding = {m_uiMeshCache.indexBuffer};
|
||||
SDL_BindGPUIndexBuffer(m_renderPass, &indexBufferBinding, SDL_GPU_INDEXELEMENTSIZE_16BIT);
|
||||
|
||||
SDL_Rect scissor;
|
||||
scissor.x = static_cast<int>(std::round(dstRect.x * m_viewportTransform.scale + m_viewportTransform.offsetX));
|
||||
scissor.y = static_cast<int>(std::round(dstRect.y * m_viewportTransform.scale + m_viewportTransform.offsetY));
|
||||
scissor.w = static_cast<int>(std::round(dstRect.w * m_viewportTransform.scale));
|
||||
scissor.h = static_cast<int>(std::round(dstRect.h * m_viewportTransform.scale));
|
||||
SDL_SetGPUScissor(m_renderPass, &scissor);
|
||||
|
||||
SDL_DrawGPUIndexedPrimitives(m_renderPass, m_uiMeshCache.indexCount, 1, 0, 0, 0);
|
||||
|
||||
SDL_Rect fullViewport = {0, 0, m_width, m_height};
|
||||
SDL_SetGPUScissor(m_renderPass, &fullViewport);
|
||||
}
|
||||
|
||||
void Direct3DRMSDL3GPURenderer::Download(SDL_Surface* target)
|
||||
{
|
||||
if (!m_cmdbuf) {
|
||||
StartRenderPass(0, 0, 0, false);
|
||||
}
|
||||
if (m_renderPass) {
|
||||
SDL_EndGPURenderPass(m_renderPass);
|
||||
m_renderPass = nullptr;
|
||||
}
|
||||
|
||||
const int offsetX = static_cast<int>(m_viewportTransform.offsetX);
|
||||
const int offsetY = static_cast<int>(m_viewportTransform.offsetY);
|
||||
const int width = m_width - offsetX * 2;
|
||||
const int height = m_height - offsetY * 2;
|
||||
|
||||
// Download rendered image
|
||||
SDL_GPUTextureRegion region = {};
|
||||
region.texture = m_transferTexture;
|
||||
region.w = m_width;
|
||||
region.h = m_height;
|
||||
region.x = offsetX;
|
||||
region.y = offsetY;
|
||||
region.w = width;
|
||||
region.h = height;
|
||||
region.d = 1;
|
||||
|
||||
SDL_GPUTextureTransferInfo transferInfo = {};
|
||||
transferInfo.transfer_buffer = m_downloadBuffer;
|
||||
|
||||
@ -792,27 +1061,24 @@ HRESULT Direct3DRMSDL3GPURenderer::FinalizeFrame()
|
||||
|
||||
WaitForPendingUpload();
|
||||
|
||||
// Render the frame
|
||||
SDL_GPUFence* fence = SDL_SubmitGPUCommandBufferAndAcquireFence(m_cmdbuf);
|
||||
m_cmdbuf = nullptr;
|
||||
if (!fence) {
|
||||
return DDERR_GENERIC;
|
||||
|
||||
if (!fence || !SDL_WaitForGPUFences(m_device, true, &fence, 1)) {
|
||||
SDL_ReleaseGPUFence(m_device, fence);
|
||||
return;
|
||||
}
|
||||
bool success = SDL_WaitForGPUFences(m_device, true, &fence, 1);
|
||||
SDL_ReleaseGPUFence(m_device, fence);
|
||||
if (!success) {
|
||||
return DDERR_GENERIC;
|
||||
}
|
||||
|
||||
void* downloadedData = SDL_MapGPUTransferBuffer(m_device, m_downloadBuffer, false);
|
||||
if (!downloadedData) {
|
||||
return DDERR_GENERIC;
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_Surface* renderedImage =
|
||||
SDL_CreateSurfaceFrom(m_width, m_height, SDL_PIXELFORMAT_ABGR8888, downloadedData, m_width * 4);
|
||||
SDL_BlitSurface(renderedImage, nullptr, DDBackBuffer, nullptr);
|
||||
SDL_CreateSurfaceFrom(width, height, SDL_PIXELFORMAT_ARGB8888, downloadedData, width * 4);
|
||||
|
||||
SDL_BlitSurfaceScaled(renderedImage, nullptr, target, nullptr, SDL_SCALEMODE_NEAREST);
|
||||
SDL_DestroySurface(renderedImage);
|
||||
SDL_UnmapGPUTransferBuffer(m_device, m_downloadBuffer);
|
||||
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
@ -10,9 +10,9 @@
|
||||
|
||||
// DXIL only makes sense on Windows platforms
|
||||
#if defined(SDL_PLATFORM_WINDOWS)
|
||||
static const Uint8 SolidColor_frag_dxil[6640] = {
|
||||
0x44, 0x58, 0x42, 0x43, 0x91, 0x24, 0xbe, 0xd8, 0x43, 0x8d, 0x7f, 0xf4, 0x71, 0x2b, 0x59, 0x98,
|
||||
0x2d, 0x7f, 0x8d, 0xac, 0x01, 0x00, 0x00, 0x00, 0xf0, 0x19, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
|
||||
static const Uint8 SolidColor_frag_dxil[6648] = {
|
||||
0x44, 0x58, 0x42, 0x43, 0xd8, 0xfe, 0x4c, 0xec, 0x17, 0x1b, 0x52, 0xee, 0xf7, 0xc8, 0x8d, 0xcf,
|
||||
0x47, 0x0e, 0xfe, 0xb7, 0x01, 0x00, 0x00, 0x00, 0xf8, 0x19, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
|
||||
0x3c, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00, 0x58, 0x01, 0x00, 0x00,
|
||||
0xc4, 0x02, 0x00, 0x00, 0x94, 0x0c, 0x00, 0x00, 0xb0, 0x0c, 0x00, 0x00, 0x53, 0x46, 0x49, 0x30,
|
||||
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31,
|
||||
@ -52,7 +52,7 @@ static const Uint8 SolidColor_frag_dxil[6640] = {
|
||||
0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x44, 0x10,
|
||||
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x11,
|
||||
0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x53, 0x54, 0x41, 0x54, 0xc8, 0x09, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
|
||||
@ -113,9 +113,9 @@ static const Uint8 SolidColor_frag_dxil[6640] = {
|
||||
0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x22, 0x4a, 0x60, 0x04, 0xa0, 0x18, 0x8a, 0xa0, 0x24,
|
||||
0xca, 0xa0, 0x80, 0x05, 0x0a, 0xac, 0x1c, 0x4a, 0xa3, 0x10, 0x0a, 0xa4, 0x80, 0x0a, 0x54, 0xa0,
|
||||
0x50, 0x05, 0x0a, 0x56, 0xa0, 0x14, 0x0a, 0x57, 0xa0, 0x20, 0xca, 0xa3, 0x06, 0xca, 0x34, 0xa0,
|
||||
0x24, 0x07, 0xa8, 0x28, 0x89, 0x11, 0x80, 0x22, 0x28, 0x83, 0x42, 0x28, 0x90, 0x12, 0x29, 0x81,
|
||||
0x2c, 0x07, 0xa8, 0x28, 0x89, 0x11, 0x80, 0x22, 0x28, 0x83, 0x42, 0x28, 0x90, 0x12, 0x29, 0x81,
|
||||
0x1a, 0xa0, 0xad, 0x06, 0x48, 0x9c, 0x01, 0xa0, 0x71, 0x06, 0x80, 0xca, 0x19, 0x00, 0x32, 0x67,
|
||||
0x00, 0x08, 0x9d, 0x01, 0xa0, 0x74, 0x2c, 0x09, 0x22, 0x8e, 0xe3, 0x00, 0x8e, 0x03, 0x00, 0x8e,
|
||||
0x00, 0x08, 0x9d, 0x01, 0xa0, 0x74, 0x2c, 0x09, 0x22, 0x8e, 0xe3, 0x00, 0x9e, 0x07, 0x00, 0x8e,
|
||||
0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
|
||||
0x1a, 0x03, 0x4c, 0x90, 0x46, 0x02, 0x13, 0xc4, 0x31, 0x20, 0xc3, 0x1b, 0x43, 0x81, 0x93, 0x4b,
|
||||
0xb3, 0x0b, 0xa3, 0x2b, 0x4b, 0x01, 0x89, 0x71, 0xc1, 0x71, 0x81, 0x71, 0xa1, 0xb9, 0xc1, 0xc9,
|
||||
@ -213,10 +213,10 @@ static const Uint8 SolidColor_frag_dxil[6640] = {
|
||||
0xe3, 0x4b, 0x93, 0x13, 0x11, 0x28, 0x35, 0x3d, 0xd4, 0xe4, 0x17, 0xb7, 0x6d, 0x04, 0xcf, 0x70,
|
||||
0xf9, 0xce, 0xe3, 0x53, 0x0d, 0x10, 0x61, 0x7e, 0x71, 0xdb, 0x06, 0x40, 0x30, 0x00, 0xd2, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x48, 0x41, 0x53, 0x48, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x58, 0x63, 0x6a, 0xf1, 0xca, 0xdc, 0xf6, 0x75, 0x3d, 0x1e, 0x21, 0x9a, 0xb8, 0xa2, 0x91, 0xc3,
|
||||
0x44, 0x58, 0x49, 0x4c, 0x38, 0x0d, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x4e, 0x03, 0x00, 0x00,
|
||||
0x44, 0x58, 0x49, 0x4c, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x20, 0x0d, 0x00, 0x00,
|
||||
0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0x45, 0x03, 0x00, 0x00, 0x0b, 0x82, 0x20, 0x00,
|
||||
0xeb, 0x0f, 0x40, 0x5f, 0x0e, 0x75, 0xec, 0xd9, 0x61, 0x1b, 0x68, 0x81, 0x54, 0xd3, 0xf4, 0x48,
|
||||
0x44, 0x58, 0x49, 0x4c, 0x40, 0x0d, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x50, 0x03, 0x00, 0x00,
|
||||
0x44, 0x58, 0x49, 0x4c, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x28, 0x0d, 0x00, 0x00,
|
||||
0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0x47, 0x03, 0x00, 0x00, 0x0b, 0x82, 0x20, 0x00,
|
||||
0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49,
|
||||
0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62,
|
||||
0x80, 0x18, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0xc4, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x4b,
|
||||
@ -272,7 +272,7 @@ static const Uint8 SolidColor_frag_dxil[6640] = {
|
||||
0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x22, 0x4a, 0x60, 0x04, 0xa0, 0x20, 0x8a, 0xa1, 0x08,
|
||||
0x4a, 0xa2, 0x0c, 0x0a, 0x58, 0xa0, 0x1c, 0xca, 0xa3, 0x06, 0xa8, 0x28, 0x89, 0x11, 0x80, 0x22,
|
||||
0x28, 0x83, 0x42, 0x28, 0x90, 0x12, 0x29, 0x81, 0x1a, 0x20, 0x71, 0x06, 0x80, 0xcc, 0x19, 0x00,
|
||||
0x42, 0x67, 0x00, 0x28, 0x1d, 0x4b, 0x82, 0x88, 0xe3, 0x38, 0x80, 0xe3, 0x00, 0x80, 0xe3, 0x38,
|
||||
0x42, 0x67, 0x00, 0x28, 0x1d, 0x4b, 0x82, 0x88, 0xe3, 0x38, 0x80, 0xe7, 0x01, 0x80, 0xe3, 0x38,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00,
|
||||
0x1a, 0x03, 0x4c, 0x90, 0x46, 0x02, 0x13, 0xc4, 0x31, 0x20, 0xc3, 0x1b, 0x43, 0x81, 0x93, 0x4b,
|
||||
0xb3, 0x0b, 0xa3, 0x2b, 0x4b, 0x01, 0x89, 0x71, 0xc1, 0x71, 0x81, 0x71, 0xa1, 0xb9, 0xc1, 0xc9,
|
||||
@ -336,7 +336,7 @@ static const Uint8 SolidColor_frag_dxil[6640] = {
|
||||
0x9b, 0x01, 0x34, 0x5c, 0xbe, 0xf3, 0xf8, 0x12, 0xc0, 0x3c, 0x0b, 0xe1, 0x17, 0xb7, 0x6d, 0x02,
|
||||
0xd5, 0x70, 0xf9, 0xce, 0xe3, 0x4b, 0x93, 0x13, 0x11, 0x28, 0x35, 0x3d, 0xd4, 0xe4, 0x17, 0xb7,
|
||||
0x6d, 0x04, 0xcf, 0x70, 0xf9, 0xce, 0xe3, 0x53, 0x0d, 0x10, 0x61, 0x7e, 0x71, 0xdb, 0x06, 0x40,
|
||||
0x30, 0x00, 0xd2, 0x00, 0x61, 0x20, 0x00, 0x00, 0x64, 0x01, 0x00, 0x00, 0x13, 0x04, 0x52, 0x2c,
|
||||
0x30, 0x00, 0xd2, 0x00, 0x61, 0x20, 0x00, 0x00, 0x66, 0x01, 0x00, 0x00, 0x13, 0x04, 0x52, 0x2c,
|
||||
0x10, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0xb4, 0x8d, 0x00, 0x10, 0x51, 0x78, 0x05, 0x52,
|
||||
0x30, 0xa5, 0x32, 0x03, 0x50, 0x76, 0x85, 0x50, 0x46, 0x85, 0x54, 0x6e, 0xa5, 0x50, 0x72, 0x25,
|
||||
0x53, 0xfe, 0x03, 0xe5, 0x42, 0xc3, 0x0c, 0xc0, 0x18, 0x41, 0x48, 0x82, 0x21, 0xde, 0x8d, 0x11,
|
||||
@ -413,25 +413,26 @@ static const Uint8 SolidColor_frag_dxil[6640] = {
|
||||
0xc4, 0xe0, 0x00, 0x40, 0x10, 0x0c, 0x9c, 0xd8, 0x58, 0x8b, 0x21, 0x2c, 0x46, 0x13, 0xb8, 0x61,
|
||||
0xb8, 0x21, 0x68, 0x0d, 0x30, 0x98, 0x65, 0x88, 0xa0, 0x60, 0xc4, 0xe0, 0x01, 0x40, 0x10, 0x0c,
|
||||
0xa6, 0xd9, 0xb0, 0x0b, 0xb1, 0x08, 0x8b, 0x9d, 0xd0, 0x89, 0xb3, 0x38, 0x0b, 0xd7, 0x70, 0x0d,
|
||||
0xb9, 0x38, 0x8b, 0xd1, 0x84, 0x00, 0x18, 0x4d, 0x10, 0x82, 0xd1, 0x84, 0x41, 0xb0, 0x21, 0x91,
|
||||
0x8f, 0x0d, 0x89, 0x7c, 0x6c, 0x48, 0xe4, 0x33, 0x62, 0x70, 0x00, 0x20, 0x08, 0x06, 0xce, 0x6e,
|
||||
0xd8, 0xc5, 0xa0, 0x16, 0x23, 0x06, 0x07, 0x00, 0x82, 0x60, 0xe0, 0xf0, 0xc6, 0x5d, 0x0c, 0x6b,
|
||||
0x31, 0x62, 0x70, 0x00, 0x20, 0x08, 0x06, 0x4e, 0x6f, 0xe0, 0xc5, 0xc0, 0x16, 0x23, 0x06, 0x07,
|
||||
0x00, 0x82, 0x60, 0xe0, 0xf8, 0x06, 0x5e, 0x0c, 0x6e, 0x31, 0x62, 0x70, 0x00, 0x20, 0x08, 0x06,
|
||||
0xce, 0x6f, 0xe4, 0xc5, 0xf0, 0x16, 0x23, 0x06, 0x07, 0x00, 0x82, 0x60, 0xe0, 0x80, 0x87, 0x5e,
|
||||
0x0c, 0x70, 0x31, 0x4b, 0x10, 0x0d, 0x54, 0x0c, 0x06, 0x44, 0x06, 0xcf, 0x40, 0xc5, 0x60, 0x40,
|
||||
0x64, 0xf0, 0x0c, 0x54, 0x0c, 0x06, 0x44, 0x06, 0xcf, 0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x20,
|
||||
0xe7, 0xc1, 0x17, 0xbe, 0xe1, 0x1b, 0xb3, 0x31, 0x8c, 0x18, 0x24, 0x00, 0x08, 0x82, 0x01, 0x72,
|
||||
0x1e, 0x7c, 0xe1, 0x1b, 0xbe, 0xd1, 0x1a, 0xc2, 0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x20, 0xe7,
|
||||
0xc1, 0x17, 0xbe, 0xe1, 0x1b, 0xb2, 0x11, 0x8c, 0x18, 0x24, 0x00, 0x08, 0x82, 0x01, 0x72, 0x1e,
|
||||
0x7c, 0xe1, 0x1b, 0xbe, 0x11, 0x1b, 0x6a, 0x30, 0x62, 0x90, 0x00, 0x20, 0x08, 0x06, 0xc8, 0x79,
|
||||
0xf0, 0xc5, 0x6f, 0xf8, 0xc6, 0x6c, 0x98, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xb9, 0x38, 0x8b, 0xd1, 0x84, 0x00, 0x18, 0x4d, 0x10, 0x82, 0xd1, 0x84, 0x41, 0x18, 0x4d, 0x20,
|
||||
0x06, 0x23, 0x14, 0xf9, 0x18, 0xa1, 0xc8, 0xc7, 0x08, 0x45, 0x3e, 0x23, 0x06, 0x07, 0x00, 0x82,
|
||||
0x60, 0xe0, 0xf0, 0xc6, 0x5d, 0x0c, 0x6b, 0x31, 0x62, 0x70, 0x00, 0x20, 0x08, 0x06, 0x4e, 0x6f,
|
||||
0xe0, 0xc5, 0xc0, 0x16, 0x23, 0x06, 0x07, 0x00, 0x82, 0x60, 0xe0, 0xf8, 0x46, 0x5e, 0x0c, 0x6d,
|
||||
0x31, 0x62, 0x70, 0x00, 0x20, 0x08, 0x06, 0xce, 0x6f, 0xe4, 0xc5, 0xf0, 0x16, 0x23, 0x06, 0x07,
|
||||
0x00, 0x82, 0x60, 0xe0, 0x80, 0x87, 0x5e, 0x0c, 0x70, 0x31, 0x62, 0x70, 0x00, 0x20, 0x08, 0x06,
|
||||
0x4e, 0x78, 0xec, 0xc5, 0x10, 0x17, 0xb3, 0x04, 0xd1, 0x40, 0xc5, 0x60, 0x40, 0x66, 0xf0, 0x0c,
|
||||
0x54, 0x0c, 0x06, 0x64, 0x06, 0xcf, 0x40, 0xc5, 0x60, 0x40, 0x66, 0xf0, 0x0c, 0x54, 0x0c, 0x1a,
|
||||
0x64, 0x0b, 0xcf, 0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x20, 0xe9, 0xe1, 0x17, 0xe0, 0x01, 0x1e,
|
||||
0xb5, 0x41, 0x8c, 0x18, 0x24, 0x00, 0x08, 0x82, 0x01, 0x92, 0x1e, 0x7e, 0x01, 0x1e, 0xe0, 0xf1,
|
||||
0x1a, 0xc3, 0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x20, 0xe9, 0xe1, 0x17, 0xe0, 0x01, 0x1e, 0xb4,
|
||||
0x21, 0x8c, 0x18, 0x24, 0x00, 0x08, 0x82, 0x01, 0x92, 0x1e, 0x7e, 0x01, 0x1e, 0xe0, 0x31, 0x1b,
|
||||
0xc1, 0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x20, 0xe9, 0xe1, 0x17, 0xe1, 0x01, 0x1e, 0xb5, 0x81,
|
||||
0x16, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
#endif
|
||||
|
||||
// MSL only makes sense on Apple platforms
|
||||
#if defined(SDL_PLATFORM_APPLE)
|
||||
static const Uint8 SolidColor_frag_msl[3333] = {
|
||||
static const Uint8 SolidColor_frag_msl[3377] = {
|
||||
0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x3c, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x5f,
|
||||
0x73, 0x74, 0x64, 0x6c, 0x69, 0x62, 0x3e, 0x0a, 0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65,
|
||||
0x20, 0x3c, 0x73, 0x69, 0x6d, 0x64, 0x2f, 0x73, 0x69, 0x6d, 0x64, 0x2e, 0x68, 0x3e, 0x0a, 0x0a,
|
||||
@ -620,32 +621,35 @@ static const Uint8 SolidColor_frag_msl[3333] = {
|
||||
0x78, 0x79, 0x7a, 0x29, 0x20, 0x2b, 0x20, 0x5f, 0x36, 0x32, 0x2c, 0x20, 0x66, 0x6c, 0x6f, 0x61,
|
||||
0x74, 0x33, 0x28, 0x30, 0x2e, 0x30, 0x29, 0x2c, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x28,
|
||||
0x31, 0x2e, 0x30, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74,
|
||||
0x33, 0x20, 0x5f, 0x31, 0x36, 0x34, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28,
|
||||
0x34, 0x20, 0x5f, 0x31, 0x37, 0x34, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28,
|
||||
0x46, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x68, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x44,
|
||||
0x61, 0x74, 0x61, 0x2e, 0x55, 0x73, 0x65, 0x54, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x20, 0x21,
|
||||
0x3d, 0x20, 0x30, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x5f, 0x31, 0x36, 0x34, 0x20, 0x3d, 0x20, 0x66, 0x61, 0x73, 0x74, 0x3a, 0x3a,
|
||||
0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x54, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x2e, 0x73, 0x61,
|
||||
0x6d, 0x70, 0x6c, 0x65, 0x28, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x2c, 0x20, 0x69, 0x6e,
|
||||
0x2e, 0x69, 0x6e, 0x5f, 0x76, 0x61, 0x72, 0x5f, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44,
|
||||
0x31, 0x29, 0x2e, 0x78, 0x79, 0x7a, 0x20, 0x2a, 0x20, 0x5f, 0x31, 0x35, 0x31, 0x2c, 0x20, 0x66,
|
||||
0x6c, 0x6f, 0x61, 0x74, 0x33, 0x28, 0x30, 0x2e, 0x30, 0x29, 0x2c, 0x20, 0x66, 0x6c, 0x6f, 0x61,
|
||||
0x74, 0x33, 0x28, 0x31, 0x2e, 0x30, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7b, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5f, 0x31, 0x36, 0x34, 0x20, 0x3d, 0x20, 0x5f, 0x31,
|
||||
0x35, 0x31, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x75,
|
||||
0x74, 0x2e, 0x6f, 0x75, 0x74, 0x5f, 0x76, 0x61, 0x72, 0x5f, 0x53, 0x56, 0x5f, 0x54, 0x61, 0x72,
|
||||
0x67, 0x65, 0x74, 0x30, 0x20, 0x3d, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x5f, 0x31,
|
||||
0x36, 0x34, 0x2c, 0x20, 0x5f, 0x31, 0x34, 0x36, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f,
|
||||
0x75, 0x74, 0x2e, 0x67, 0x6c, 0x5f, 0x46, 0x72, 0x61, 0x67, 0x44, 0x65, 0x70, 0x74, 0x68, 0x20,
|
||||
0x3d, 0x20, 0x67, 0x6c, 0x5f, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x2e, 0x77,
|
||||
0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x75, 0x74,
|
||||
0x3b, 0x0a, 0x7d, 0x0a, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x5f, 0x31, 0x36, 0x31, 0x20, 0x3d,
|
||||
0x20, 0x54, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x2e, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x28,
|
||||
0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x2c, 0x20, 0x69, 0x6e, 0x2e, 0x69, 0x6e, 0x5f, 0x76,
|
||||
0x61, 0x72, 0x5f, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x31, 0x29, 0x3b, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5f, 0x31, 0x37, 0x34, 0x20, 0x3d, 0x20, 0x66, 0x6c,
|
||||
0x6f, 0x61, 0x74, 0x34, 0x28, 0x66, 0x61, 0x73, 0x74, 0x3a, 0x3a, 0x63, 0x6c, 0x61, 0x6d, 0x70,
|
||||
0x28, 0x5f, 0x31, 0x36, 0x31, 0x2e, 0x78, 0x79, 0x7a, 0x20, 0x2a, 0x20, 0x5f, 0x31, 0x35, 0x31,
|
||||
0x2c, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x28, 0x30, 0x2e, 0x30, 0x29, 0x2c, 0x20, 0x66,
|
||||
0x6c, 0x6f, 0x61, 0x74, 0x33, 0x28, 0x31, 0x2e, 0x30, 0x29, 0x29, 0x2c, 0x20, 0x5f, 0x31, 0x36,
|
||||
0x31, 0x2e, 0x77, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x65, 0x6c, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x5f, 0x31, 0x37, 0x34, 0x20, 0x3d, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34,
|
||||
0x28, 0x5f, 0x31, 0x35, 0x31, 0x2c, 0x20, 0x5f, 0x31, 0x34, 0x36, 0x29, 0x3b, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x75, 0x74, 0x2e, 0x6f, 0x75, 0x74, 0x5f,
|
||||
0x76, 0x61, 0x72, 0x5f, 0x53, 0x56, 0x5f, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x30, 0x20, 0x3d,
|
||||
0x20, 0x5f, 0x31, 0x37, 0x34, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x75, 0x74, 0x2e, 0x67,
|
||||
0x6c, 0x5f, 0x46, 0x72, 0x61, 0x67, 0x44, 0x65, 0x70, 0x74, 0x68, 0x20, 0x3d, 0x20, 0x67, 0x6c,
|
||||
0x5f, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x2e, 0x77, 0x3b, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x75, 0x74, 0x3b, 0x0a, 0x7d, 0x0a,
|
||||
0x0a,
|
||||
};
|
||||
#endif
|
||||
|
||||
static const Uint8 SolidColor_frag_spirv[4492] = {
|
||||
0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0xab, 0x00, 0x00, 0x00,
|
||||
static const Uint8 SolidColor_frag_spirv[4616] = {
|
||||
0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0xb1, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
@ -902,28 +906,36 @@ static const Uint8 SolidColor_frag_spirv[4492] = {
|
||||
0x16, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0xab, 0x00, 0x05, 0x00,
|
||||
0x1a, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
|
||||
0xf7, 0x00, 0x03, 0x00, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00,
|
||||
0x9a, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x9b, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
|
||||
0x9c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x9d, 0x00, 0x00, 0x00,
|
||||
0x0d, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00,
|
||||
0x0f, 0x00, 0x00, 0x00, 0x56, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00,
|
||||
0x9d, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, 0x57, 0x00, 0x06, 0x00, 0x27, 0x00, 0x00, 0x00,
|
||||
0xa0, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x4f, 0x00, 0x08, 0x00, 0x14, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00,
|
||||
0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||
0x85, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00,
|
||||
0x97, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x14, 0x00, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
|
||||
0x1e, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x9b, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
|
||||
0x9b, 0x00, 0x00, 0x00, 0xf5, 0x00, 0x07, 0x00, 0x14, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00,
|
||||
0x97, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00,
|
||||
0x51, 0x00, 0x05, 0x00, 0x12, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x12, 0x00, 0x00, 0x00, 0xa6, 0x00, 0x00, 0x00,
|
||||
0xa4, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x12, 0x00, 0x00, 0x00,
|
||||
0xa7, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00,
|
||||
0x27, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0xa6, 0x00, 0x00, 0x00,
|
||||
0xa7, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x38, 0x00, 0x00, 0x00,
|
||||
0xa9, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
|
||||
0x12, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0xa9, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
|
||||
0x07, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00,
|
||||
0xaa, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00,
|
||||
0x9a, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x9d, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
|
||||
0x9c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00,
|
||||
0x0d, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00,
|
||||
0x0f, 0x00, 0x00, 0x00, 0x56, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00,
|
||||
0x9e, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x57, 0x00, 0x06, 0x00, 0x27, 0x00, 0x00, 0x00,
|
||||
0xa1, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x4f, 0x00, 0x08, 0x00, 0x14, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00,
|
||||
0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||
0x85, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00,
|
||||
0x97, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x14, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
|
||||
0x1e, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x12, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00,
|
||||
0xa1, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x12, 0x00, 0x00, 0x00,
|
||||
0xa6, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00,
|
||||
0x12, 0x00, 0x00, 0x00, 0xa7, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x51, 0x00, 0x05, 0x00, 0x12, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00,
|
||||
0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00, 0x27, 0x00, 0x00, 0x00, 0xa9, 0x00, 0x00, 0x00,
|
||||
0xa6, 0x00, 0x00, 0x00, 0xa7, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00,
|
||||
0xf9, 0x00, 0x02, 0x00, 0x9b, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x9d, 0x00, 0x00, 0x00,
|
||||
0x51, 0x00, 0x05, 0x00, 0x12, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x12, 0x00, 0x00, 0x00, 0xab, 0x00, 0x00, 0x00,
|
||||
0x97, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x12, 0x00, 0x00, 0x00,
|
||||
0xac, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00,
|
||||
0x27, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0xab, 0x00, 0x00, 0x00,
|
||||
0xac, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x9b, 0x00, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x02, 0x00, 0x9b, 0x00, 0x00, 0x00, 0xf5, 0x00, 0x07, 0x00, 0x27, 0x00, 0x00, 0x00,
|
||||
0xae, 0x00, 0x00, 0x00, 0xa9, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, 0x00,
|
||||
0x9d, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x38, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x12, 0x00, 0x00, 0x00,
|
||||
0xb0, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00,
|
||||
0xae, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00,
|
||||
0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00,
|
||||
};
|
||||
|
||||
@ -72,8 +72,11 @@ FS_Output main(FS_Input input)
|
||||
if (UseTexture != 0) {
|
||||
float4 texel = Texture.Sample(Sampler, input.TexCoord);
|
||||
finalColor = saturate(texel.rgb * finalColor);
|
||||
output.Color = float4(finalColor, texel.a);
|
||||
}
|
||||
else {
|
||||
output.Color = float4(finalColor, Color.a);
|
||||
}
|
||||
output.Color = float4(finalColor, Color.a);
|
||||
output.Depth = input.Position.w;
|
||||
return output;
|
||||
}
|
||||
|
||||
@ -23,9 +23,22 @@
|
||||
#include <wasm_simd128.h>
|
||||
#endif
|
||||
|
||||
Direct3DRMSoftwareRenderer::Direct3DRMSoftwareRenderer(DWORD width, DWORD height) : m_width(width), m_height(height)
|
||||
Direct3DRMSoftwareRenderer::Direct3DRMSoftwareRenderer(DWORD width, DWORD height)
|
||||
{
|
||||
m_zBuffer.resize(m_width * m_height);
|
||||
m_virtualWidth = width;
|
||||
m_virtualHeight = height;
|
||||
|
||||
m_renderer = SDL_CreateRenderer(DDWindow, NULL);
|
||||
|
||||
ViewportTransform viewportTransform = {1.0f, 0.0f, 0.0f};
|
||||
Resize(width, height, viewportTransform);
|
||||
}
|
||||
|
||||
Direct3DRMSoftwareRenderer::~Direct3DRMSoftwareRenderer()
|
||||
{
|
||||
SDL_DestroySurface(m_renderedImage);
|
||||
SDL_DestroyTexture(m_uploadBuffer);
|
||||
SDL_DestroyRenderer(m_renderer);
|
||||
}
|
||||
|
||||
void Direct3DRMSoftwareRenderer::PushLights(const SceneLight* lights, size_t count)
|
||||
@ -354,8 +367,8 @@ void Direct3DRMSoftwareRenderer::DrawTriangleProjected(
|
||||
c2 = ApplyLighting(v2.position, v2.normal, appearance);
|
||||
}
|
||||
|
||||
Uint8* pixels = (Uint8*) DDBackBuffer->pixels;
|
||||
int pitch = DDBackBuffer->pitch;
|
||||
Uint8* pixels = (Uint8*) m_renderedImage->pixels;
|
||||
int pitch = m_renderedImage->pitch;
|
||||
|
||||
VertexXY verts[3] = {
|
||||
{p0.x, p0.y, p0.z, p0.w, c0, v0.texCoord.u, v0.texCoord.v},
|
||||
@ -553,7 +566,7 @@ Uint32 Direct3DRMSoftwareRenderer::GetTextureId(IDirect3DRMTexture* iTexture)
|
||||
if (texRef.version != texture->m_version) {
|
||||
// Update animated textures
|
||||
SDL_DestroySurface(texRef.cached);
|
||||
texRef.cached = SDL_ConvertSurface(surface->m_surface, DDBackBuffer->format);
|
||||
texRef.cached = SDL_ConvertSurface(surface->m_surface, m_renderedImage->format);
|
||||
SDL_LockSurface(texRef.cached);
|
||||
texRef.version = texture->m_version;
|
||||
}
|
||||
@ -561,7 +574,7 @@ Uint32 Direct3DRMSoftwareRenderer::GetTextureId(IDirect3DRMTexture* iTexture)
|
||||
}
|
||||
}
|
||||
|
||||
SDL_Surface* convertedRender = SDL_ConvertSurface(surface->m_surface, DDBackBuffer->format);
|
||||
SDL_Surface* convertedRender = SDL_ConvertSurface(surface->m_surface, m_renderedImage->format);
|
||||
SDL_LockSurface(convertedRender);
|
||||
|
||||
// Reuse freed slot
|
||||
@ -651,16 +664,6 @@ Uint32 Direct3DRMSoftwareRenderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGr
|
||||
return (Uint32) (m_meshs.size() - 1);
|
||||
}
|
||||
|
||||
DWORD Direct3DRMSoftwareRenderer::GetWidth()
|
||||
{
|
||||
return m_width;
|
||||
}
|
||||
|
||||
DWORD Direct3DRMSoftwareRenderer::GetHeight()
|
||||
{
|
||||
return m_height;
|
||||
}
|
||||
|
||||
void Direct3DRMSoftwareRenderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc)
|
||||
{
|
||||
memset(halDesc, 0, sizeof(D3DDEVICEDESC));
|
||||
@ -681,13 +684,13 @@ const char* Direct3DRMSoftwareRenderer::GetName()
|
||||
|
||||
HRESULT Direct3DRMSoftwareRenderer::BeginFrame()
|
||||
{
|
||||
if (!DDBackBuffer || !SDL_LockSurface(DDBackBuffer)) {
|
||||
if (!m_renderedImage || !SDL_LockSurface(m_renderedImage)) {
|
||||
return DDERR_GENERIC;
|
||||
}
|
||||
ClearZBuffer();
|
||||
|
||||
m_format = SDL_GetPixelFormatDetails(DDBackBuffer->format);
|
||||
m_palette = SDL_GetSurfacePalette(DDBackBuffer);
|
||||
m_format = SDL_GetPixelFormatDetails(m_renderedImage->format);
|
||||
m_palette = SDL_GetSurfacePalette(m_renderedImage);
|
||||
m_bytesPerPixel = m_format->bits_per_pixel / 8;
|
||||
|
||||
return DD_OK;
|
||||
@ -700,6 +703,8 @@ void Direct3DRMSoftwareRenderer::EnableTransparency()
|
||||
void Direct3DRMSoftwareRenderer::SubmitDraw(
|
||||
DWORD meshId,
|
||||
const D3DRMMATRIX4D& modelViewMatrix,
|
||||
const D3DRMMATRIX4D& worldMatrix,
|
||||
const D3DRMMATRIX4D& viewMatrix,
|
||||
const Matrix3x3& normalMatrix,
|
||||
const Appearance& appearance
|
||||
)
|
||||
@ -731,7 +736,84 @@ void Direct3DRMSoftwareRenderer::SubmitDraw(
|
||||
|
||||
HRESULT Direct3DRMSoftwareRenderer::FinalizeFrame()
|
||||
{
|
||||
SDL_UnlockSurface(DDBackBuffer);
|
||||
SDL_UnlockSurface(m_renderedImage);
|
||||
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
void Direct3DRMSoftwareRenderer::Resize(int width, int height, const ViewportTransform& viewportTransform)
|
||||
{
|
||||
m_viewportTransform = viewportTransform;
|
||||
float aspect = static_cast<float>(width) / height;
|
||||
float virtualAspect = static_cast<float>(m_virtualWidth) / m_virtualHeight;
|
||||
|
||||
// Cap to virtual canvase for performance
|
||||
if (aspect > virtualAspect) {
|
||||
m_height = std::min(height, m_virtualHeight);
|
||||
m_width = static_cast<int>(m_height * aspect);
|
||||
}
|
||||
else {
|
||||
m_width = std::min(width, m_virtualWidth);
|
||||
m_height = static_cast<int>(m_width / aspect);
|
||||
}
|
||||
|
||||
m_viewportTransform.scale =
|
||||
std::min(static_cast<float>(m_width) / m_virtualWidth, static_cast<float>(m_height) / m_virtualHeight);
|
||||
|
||||
m_viewportTransform.offsetX = (m_width - (m_virtualWidth * m_viewportTransform.scale)) / 2.0f;
|
||||
m_viewportTransform.offsetY = (m_height - (m_virtualHeight * m_viewportTransform.scale)) / 2.0f;
|
||||
|
||||
if (m_renderedImage) {
|
||||
SDL_DestroySurface(m_renderedImage);
|
||||
}
|
||||
m_renderedImage = SDL_CreateSurface(m_width, m_height, SDL_PIXELFORMAT_RGBA32);
|
||||
|
||||
if (m_uploadBuffer) {
|
||||
SDL_DestroyTexture(m_uploadBuffer);
|
||||
}
|
||||
m_uploadBuffer =
|
||||
SDL_CreateTexture(m_renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STREAMING, m_width, m_height);
|
||||
|
||||
m_zBuffer.resize(m_width * m_height);
|
||||
}
|
||||
|
||||
void Direct3DRMSoftwareRenderer::Clear(float r, float g, float b)
|
||||
{
|
||||
SDL_Rect rect = {0, 0, m_renderedImage->w, m_renderedImage->h};
|
||||
const SDL_PixelFormatDetails* details = SDL_GetPixelFormatDetails(m_renderedImage->format);
|
||||
Uint32 color = SDL_MapRGB(details, m_palette, r * 255, g * 255, b * 255);
|
||||
SDL_FillSurfaceRect(m_renderedImage, &rect, color);
|
||||
}
|
||||
|
||||
void Direct3DRMSoftwareRenderer::Flip()
|
||||
{
|
||||
SDL_UpdateTexture(m_uploadBuffer, nullptr, m_renderedImage->pixels, m_renderedImage->pitch);
|
||||
SDL_RenderTexture(m_renderer, m_uploadBuffer, nullptr, nullptr);
|
||||
SDL_RenderPresent(m_renderer);
|
||||
}
|
||||
|
||||
void Direct3DRMSoftwareRenderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect)
|
||||
{
|
||||
SDL_Surface* surface = m_textures[textureId].cached;
|
||||
SDL_UnlockSurface(surface);
|
||||
SDL_Rect centeredRect = {
|
||||
static_cast<int>(dstRect.x * m_viewportTransform.scale + m_viewportTransform.offsetX),
|
||||
static_cast<int>(dstRect.y * m_viewportTransform.scale + m_viewportTransform.offsetY),
|
||||
static_cast<int>(dstRect.w * m_viewportTransform.scale),
|
||||
static_cast<int>(dstRect.h * m_viewportTransform.scale),
|
||||
};
|
||||
SDL_BlitSurfaceScaled(surface, &srcRect, m_renderedImage, ¢eredRect, SDL_SCALEMODE_LINEAR);
|
||||
SDL_LockSurface(surface);
|
||||
}
|
||||
|
||||
void Direct3DRMSoftwareRenderer::Download(SDL_Surface* target)
|
||||
{
|
||||
SDL_Rect srcRect = {
|
||||
static_cast<int>(m_viewportTransform.offsetX),
|
||||
static_cast<int>(m_viewportTransform.offsetY),
|
||||
static_cast<int>(m_virtualWidth * m_viewportTransform.scale),
|
||||
static_cast<int>(m_virtualHeight * m_viewportTransform.scale),
|
||||
};
|
||||
|
||||
SDL_BlitSurfaceScaled(m_renderedImage, &srcRect, target, nullptr, SDL_SCALEMODE_LINEAR);
|
||||
}
|
||||
|
||||
@ -127,7 +127,7 @@ HRESULT Direct3DRMImpl::CreateDeviceFromD3D(
|
||||
{
|
||||
auto renderer = static_cast<Direct3DRMRenderer*>(d3dDevice);
|
||||
*outDevice = static_cast<IDirect3DRMDevice2*>(
|
||||
new Direct3DRMDevice2Impl(renderer->GetWidth(), renderer->GetHeight(), renderer)
|
||||
new Direct3DRMDevice2Impl(renderer->GetVirtualWidth(), renderer->GetVirtualHeight(), renderer)
|
||||
);
|
||||
return DD_OK;
|
||||
}
|
||||
@ -143,26 +143,25 @@ HRESULT Direct3DRMImpl::CreateDeviceFromSurface(
|
||||
DDSDesc.dwSize = sizeof(DDSURFACEDESC);
|
||||
surface->GetSurfaceDesc(&DDSDesc);
|
||||
|
||||
Direct3DRMRenderer* renderer;
|
||||
if (SDL_memcmp(&guid, &SDL3_GPU_GUID, sizeof(GUID)) == 0) {
|
||||
renderer = Direct3DRMSDL3GPURenderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight);
|
||||
DDRenderer = Direct3DRMSDL3GPURenderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight);
|
||||
}
|
||||
else if (SDL_memcmp(&guid, &SOFTWARE_GUID, sizeof(GUID)) == 0) {
|
||||
renderer = new Direct3DRMSoftwareRenderer(DDSDesc.dwWidth, DDSDesc.dwHeight);
|
||||
DDRenderer = new Direct3DRMSoftwareRenderer(DDSDesc.dwWidth, DDSDesc.dwHeight);
|
||||
}
|
||||
#ifdef USE_OPENGLES2
|
||||
else if (SDL_memcmp(&guid, &OpenGLES2_GUID, sizeof(GUID)) == 0) {
|
||||
renderer = OpenGLES2Renderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight);
|
||||
DDRenderer = OpenGLES2Renderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_OPENGL1
|
||||
else if (SDL_memcmp(&guid, &OpenGL1_GUID, sizeof(GUID)) == 0) {
|
||||
renderer = OpenGL1Renderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight);
|
||||
DDRenderer = OpenGL1Renderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight);
|
||||
}
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
else if (SDL_memcmp(&guid, &DirectX9_GUID, sizeof(GUID)) == 0) {
|
||||
renderer = DirectX9Renderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight);
|
||||
DDRenderer = DirectX9Renderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight);
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
@ -170,7 +169,7 @@ HRESULT Direct3DRMImpl::CreateDeviceFromSurface(
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
*outDevice =
|
||||
static_cast<IDirect3DRMDevice2*>(new Direct3DRMDevice2Impl(DDSDesc.dwWidth, DDSDesc.dwHeight, renderer));
|
||||
static_cast<IDirect3DRMDevice2*>(new Direct3DRMDevice2Impl(DDSDesc.dwWidth, DDSDesc.dwHeight, DDRenderer));
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
@ -181,9 +180,8 @@ HRESULT Direct3DRMImpl::CreateTexture(D3DRMIMAGE* image, IDirect3DRMTexture2** o
|
||||
}
|
||||
|
||||
HRESULT Direct3DRMImpl::CreateTextureFromSurface(LPDIRECTDRAWSURFACE surface, IDirect3DRMTexture2** outTexture)
|
||||
|
||||
{
|
||||
*outTexture = static_cast<IDirect3DRMTexture2*>(new Direct3DRMTextureImpl(surface));
|
||||
*outTexture = static_cast<IDirect3DRMTexture2*>(new Direct3DRMTextureImpl(surface, true));
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -11,8 +11,9 @@
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
Direct3DRMDevice2Impl::Direct3DRMDevice2Impl(DWORD width, DWORD height, Direct3DRMRenderer* renderer)
|
||||
: m_width(width), m_height(height), m_renderer(renderer), m_viewports(new Direct3DRMViewportArrayImpl)
|
||||
: m_virtualWidth(width), m_virtualHeight(height), m_renderer(renderer), m_viewports(new Direct3DRMViewportArrayImpl)
|
||||
{
|
||||
Resize();
|
||||
}
|
||||
|
||||
Direct3DRMDevice2Impl::~Direct3DRMDevice2Impl()
|
||||
@ -43,16 +44,6 @@ HRESULT Direct3DRMDevice2Impl::QueryInterface(const GUID& riid, void** ppvObject
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
DWORD Direct3DRMDevice2Impl::GetWidth()
|
||||
{
|
||||
return m_width;
|
||||
}
|
||||
|
||||
DWORD Direct3DRMDevice2Impl::GetHeight()
|
||||
{
|
||||
return m_height;
|
||||
}
|
||||
|
||||
HRESULT Direct3DRMDevice2Impl::SetBufferCount(int count)
|
||||
{
|
||||
MINIWIN_NOT_IMPLEMENTED();
|
||||
@ -133,7 +124,9 @@ HRESULT Direct3DRMDevice2Impl::Update()
|
||||
|
||||
HRESULT Direct3DRMDevice2Impl::AddViewport(IDirect3DRMViewport* viewport)
|
||||
{
|
||||
return m_viewports->AddElement(viewport);
|
||||
HRESULT status = m_viewports->AddElement(viewport);
|
||||
Resize();
|
||||
return status;
|
||||
}
|
||||
|
||||
HRESULT Direct3DRMDevice2Impl::GetViewports(IDirect3DRMViewportArray** ppViewportArray)
|
||||
@ -143,7 +136,53 @@ HRESULT Direct3DRMDevice2Impl::GetViewports(IDirect3DRMViewportArray** ppViewpor
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
ViewportTransform CalculateViewportTransform(int virtualW, int virtualH, int windowW, int windowH)
|
||||
{
|
||||
float scaleX = (float) windowW / virtualW;
|
||||
float scaleY = (float) windowH / virtualH;
|
||||
float scale = (scaleX < scaleY) ? scaleX : scaleY;
|
||||
|
||||
float viewportW = virtualW * scale;
|
||||
float viewportH = virtualH * scale;
|
||||
|
||||
float offsetX = (windowW - viewportW) * 0.5f;
|
||||
float offsetY = (windowH - viewportH) * 0.5f;
|
||||
|
||||
return {scale, offsetX, offsetY};
|
||||
}
|
||||
|
||||
void Direct3DRMDevice2Impl::Resize()
|
||||
{
|
||||
int width, height;
|
||||
SDL_GetWindowSizeInPixels(DDWindow, &width, &height);
|
||||
m_viewportTransform = CalculateViewportTransform(m_virtualWidth, m_virtualHeight, width, height);
|
||||
m_renderer->Resize(width, height, m_viewportTransform);
|
||||
for (int i = 0; i < m_viewports->GetSize(); i++) {
|
||||
IDirect3DRMViewport* viewport;
|
||||
m_viewports->GetElement(i, &viewport);
|
||||
static_cast<Direct3DRMViewportImpl*>(viewport)->UpdateProjectionMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
bool Direct3DRMDevice2Impl::ConvertEventToRenderCoordinates(SDL_Event* event)
|
||||
{
|
||||
return m_renderer->ConvertEventToRenderCoordinates(event);
|
||||
switch (event->type) {
|
||||
case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: {
|
||||
Resize();
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_MOUSE_MOTION:
|
||||
case SDL_EVENT_MOUSE_BUTTON_DOWN:
|
||||
case SDL_EVENT_MOUSE_BUTTON_UP: {
|
||||
int rawX = event->motion.x;
|
||||
int rawY = event->motion.y;
|
||||
float x = (rawX - m_viewportTransform.offsetX) / m_viewportTransform.scale;
|
||||
float y = (rawY - m_viewportTransform.offsetY) / m_viewportTransform.scale;
|
||||
event->motion.x = static_cast<Sint32>(x);
|
||||
event->motion.y = static_cast<Sint32>(y);
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -59,7 +59,7 @@ HRESULT Direct3DRMMeshImpl::AddGroup(
|
||||
MeshGroup group;
|
||||
group.vertexPerFace = vertexPerFace;
|
||||
|
||||
DWORD* src = faceBuffer;
|
||||
unsigned int* src = faceBuffer;
|
||||
group.indices.assign(src, src + faceCount * vertexPerFace);
|
||||
|
||||
m_groups.push_back(std::move(group));
|
||||
|
||||
@ -6,8 +6,19 @@ Direct3DRMTextureImpl::Direct3DRMTextureImpl(D3DRMIMAGE* image)
|
||||
MINIWIN_NOT_IMPLEMENTED();
|
||||
}
|
||||
|
||||
Direct3DRMTextureImpl::Direct3DRMTextureImpl(IDirectDrawSurface* surface) : m_surface(surface)
|
||||
Direct3DRMTextureImpl::Direct3DRMTextureImpl(IDirectDrawSurface* surface, bool holdsRef)
|
||||
: m_surface(surface), m_holdsRef(holdsRef)
|
||||
{
|
||||
if (holdsRef && m_surface) {
|
||||
m_surface->AddRef();
|
||||
}
|
||||
}
|
||||
|
||||
Direct3DRMTextureImpl::~Direct3DRMTextureImpl()
|
||||
{
|
||||
if (m_holdsRef && m_surface) {
|
||||
m_surface->Release();
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT Direct3DRMTextureImpl::QueryInterface(const GUID& riid, void** ppvObject)
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
#include <math.h>
|
||||
|
||||
Direct3DRMViewportImpl::Direct3DRMViewportImpl(DWORD width, DWORD height, Direct3DRMRenderer* renderer)
|
||||
: m_width(width), m_height(height), m_renderer(renderer)
|
||||
: m_virtualWidth(width), m_virtualHeight(height), m_renderer(renderer)
|
||||
{
|
||||
}
|
||||
|
||||
@ -151,7 +151,7 @@ void Direct3DRMViewportImpl::CollectLightsFromFrame(
|
||||
void Direct3DRMViewportImpl::BuildViewFrustumPlanes()
|
||||
{
|
||||
|
||||
float aspect = (float) m_width / (float) m_height;
|
||||
float aspect = (float) m_renderer->GetWidth() / (float) m_renderer->GetHeight();
|
||||
float tanFovX = m_field;
|
||||
float tanFovY = m_field / aspect;
|
||||
|
||||
@ -268,18 +268,22 @@ void Direct3DRMViewportImpl::CollectMeshesFromFrame(IDirect3DRMFrame* frame, D3D
|
||||
if (appearance.color.a != 255) {
|
||||
m_deferredDraws.push_back(
|
||||
{m_renderer->GetMeshId(mesh, &meshGroup),
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
appearance,
|
||||
CalculateDepth(m_viewProjectionwMatrix, worldMatrix)}
|
||||
);
|
||||
memcpy(m_deferredDraws.back().modelViewMatrix, modelViewMatrix, sizeof(D3DRMMATRIX4D));
|
||||
memcpy(m_deferredDraws.back().worldMatrix, worldMatrix, sizeof(D3DRMMATRIX4D));
|
||||
memcpy(m_deferredDraws.back().normalMatrix, worldMatrixInvert, sizeof(Matrix3x3));
|
||||
}
|
||||
else {
|
||||
m_renderer->SubmitDraw(
|
||||
m_renderer->GetMeshId(mesh, &meshGroup),
|
||||
modelViewMatrix,
|
||||
worldMatrix,
|
||||
m_viewMatrix,
|
||||
worldMatrixInvert,
|
||||
appearance
|
||||
);
|
||||
@ -325,7 +329,14 @@ HRESULT Direct3DRMViewportImpl::RenderScene()
|
||||
);
|
||||
m_renderer->EnableTransparency();
|
||||
for (const DeferredDrawCommand& cmd : m_deferredDraws) {
|
||||
m_renderer->SubmitDraw(cmd.meshId, cmd.modelViewMatrix, cmd.normalMatrix, cmd.appearance);
|
||||
m_renderer->SubmitDraw(
|
||||
cmd.meshId,
|
||||
cmd.modelViewMatrix,
|
||||
cmd.worldMatrix,
|
||||
m_viewMatrix,
|
||||
cmd.normalMatrix,
|
||||
cmd.appearance
|
||||
);
|
||||
}
|
||||
m_deferredDraws.clear();
|
||||
|
||||
@ -349,16 +360,14 @@ HRESULT Direct3DRMViewportImpl::ForceUpdate(int x, int y, int w, int h)
|
||||
|
||||
HRESULT Direct3DRMViewportImpl::Clear()
|
||||
{
|
||||
if (!DDBackBuffer) {
|
||||
if (!m_renderer) {
|
||||
return DDERR_GENERIC;
|
||||
}
|
||||
|
||||
uint8_t r = (m_backgroundColor >> 16) & 0xFF;
|
||||
uint8_t g = (m_backgroundColor >> 8) & 0xFF;
|
||||
uint8_t b = m_backgroundColor & 0xFF;
|
||||
|
||||
Uint32 color = SDL_MapRGB(SDL_GetPixelFormatDetails(DDBackBuffer->format), nullptr, r, g, b);
|
||||
SDL_FillSurfaceRect(DDBackBuffer, nullptr, color);
|
||||
m_renderer->Clear(r / 255.0f, g / 255.0f, b / 255.0f);
|
||||
|
||||
return DD_OK;
|
||||
}
|
||||
@ -427,13 +436,24 @@ HRESULT Direct3DRMViewportImpl::SetField(D3DVALUE field)
|
||||
|
||||
void Direct3DRMViewportImpl::UpdateProjectionMatrix()
|
||||
{
|
||||
float aspect = (float) m_width / (float) m_height;
|
||||
float f = m_front / m_field;
|
||||
float virtualAspect = (float) m_virtualWidth / (float) m_virtualHeight;
|
||||
float windowAspect = (float) m_renderer->GetWidth() / (float) m_renderer->GetHeight();
|
||||
|
||||
float base_f = m_front / m_field;
|
||||
float f_v = base_f * virtualAspect;
|
||||
float f_h = base_f;
|
||||
if (windowAspect >= virtualAspect) {
|
||||
f_h *= virtualAspect / windowAspect;
|
||||
}
|
||||
else {
|
||||
f_v *= windowAspect / virtualAspect;
|
||||
}
|
||||
|
||||
float depth = m_back - m_front;
|
||||
|
||||
D3DRMMATRIX4D projection = {
|
||||
{f, 0, 0, 0},
|
||||
{0, f * aspect, 0, 0},
|
||||
{f_h, 0, 0, 0},
|
||||
{0, f_v, 0, 0},
|
||||
{0, 0, m_back / depth, 1},
|
||||
{0, 0, (-m_front * m_back) / depth, 0},
|
||||
};
|
||||
@ -442,8 +462,8 @@ void Direct3DRMViewportImpl::UpdateProjectionMatrix()
|
||||
m_renderer->SetProjection(projection, m_front, m_back);
|
||||
|
||||
D3DRMMATRIX4D inverseProjectionMatrix = {
|
||||
{1.0f / f, 0, 0, 0},
|
||||
{0, 1.0f / (f * aspect), 0, 0},
|
||||
{1.0f / f_h, 0, 0, 0},
|
||||
{0, 1.0f / f_v, 0, 0},
|
||||
{0, 0, 0, depth / (-m_front * m_back)},
|
||||
{0, 0, 1, -(m_back / depth) * depth / (-m_front * m_back)},
|
||||
};
|
||||
@ -455,16 +475,6 @@ D3DVALUE Direct3DRMViewportImpl::GetField()
|
||||
return m_field;
|
||||
}
|
||||
|
||||
DWORD Direct3DRMViewportImpl::GetWidth()
|
||||
{
|
||||
return m_width;
|
||||
}
|
||||
|
||||
DWORD Direct3DRMViewportImpl::GetHeight()
|
||||
{
|
||||
return m_height;
|
||||
}
|
||||
|
||||
inline float FromNDC(float ndcCoord, float dim)
|
||||
{
|
||||
return (ndcCoord * 0.5f + 0.5f) * dim;
|
||||
@ -492,8 +502,8 @@ HRESULT Direct3DRMViewportImpl::Transform(D3DRMVECTOR4D* screen, D3DVECTOR* worl
|
||||
float ndcX = projVec.x * invW;
|
||||
float ndcY = projVec.y * invW;
|
||||
|
||||
screen->x = FromNDC(ndcX, m_width);
|
||||
screen->y = FromNDC(-ndcY, m_height); // Y-flip
|
||||
screen->x = FromNDC(ndcX, m_virtualWidth);
|
||||
screen->y = FromNDC(-ndcY, m_virtualHeight); // Y-flip
|
||||
|
||||
// Undo perspective divide for screen-space coords
|
||||
screen->x *= projVec.z;
|
||||
@ -509,8 +519,8 @@ HRESULT Direct3DRMViewportImpl::InverseTransform(D3DVECTOR* world, D3DRMVECTOR4D
|
||||
float screenY = screen->y / screen->w;
|
||||
|
||||
// Convert screen coordinates to NDC
|
||||
float ndcX = screenX / m_width * 2.0f - 1.0f;
|
||||
float ndcY = 1.0f - (screenY / m_height) * 2.0f;
|
||||
float ndcX = screenX / m_virtualWidth * 2.0f - 1.0f;
|
||||
float ndcY = 1.0f - (screenY / m_virtualHeight) * 2.0f;
|
||||
|
||||
D3DRMVECTOR4D clipVec = {ndcX * screen->w, ndcY * screen->w, screen->z, screen->w};
|
||||
|
||||
@ -753,13 +763,13 @@ HRESULT Direct3DRMViewportImpl::Pick(float x, float y, LPDIRECT3DRMPICKEDARRAY*
|
||||
Ray pickRay = BuildPickingRay(
|
||||
x,
|
||||
y,
|
||||
m_width,
|
||||
m_height,
|
||||
m_virtualWidth,
|
||||
m_virtualHeight,
|
||||
m_camera,
|
||||
m_front,
|
||||
m_back,
|
||||
m_field,
|
||||
(float) m_width / (float) m_height
|
||||
(float) m_virtualWidth / (float) m_virtualHeight
|
||||
);
|
||||
|
||||
std::function<void(IDirect3DRMFrame*, std::vector<IDirect3DRMFrame*>&)> recurse;
|
||||
|
||||
@ -18,14 +18,13 @@
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
#include <assert.h>
|
||||
#include <cinttypes>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
SDL_Window* DDWindow;
|
||||
SDL_Surface* DDBackBuffer;
|
||||
FrameBufferImpl* DDFrameBuffer;
|
||||
SDL_Renderer* DDRenderer;
|
||||
Direct3DRMRenderer* DDRenderer;
|
||||
|
||||
HRESULT DirectDrawImpl::QueryInterface(const GUID& riid, void** ppvObject)
|
||||
{
|
||||
@ -77,18 +76,18 @@ HRESULT DirectDrawImpl::CreateSurface(
|
||||
if ((lpDDSurfaceDesc->dwFlags & DDSD_ZBUFFERBITDEPTH) != DDSD_ZBUFFERBITDEPTH) {
|
||||
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);
|
||||
return DD_OK;
|
||||
}
|
||||
if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) == DDSCAPS_PRIMARYSURFACE) {
|
||||
DDFrameBuffer = new FrameBufferImpl();
|
||||
*lplpDDSurface = static_cast<IDirectDrawSurface*>(DDFrameBuffer);
|
||||
m_frameBuffer = new FrameBufferImpl(m_virtualWidth, m_virtualHeight);
|
||||
*lplpDDSurface = static_cast<IDirectDrawSurface*>(m_frameBuffer);
|
||||
return DD_OK;
|
||||
}
|
||||
if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) == DDSCAPS_3DDEVICE) {
|
||||
DDFrameBuffer->AddRef();
|
||||
*lplpDDSurface = static_cast<IDirectDrawSurface*>(DDFrameBuffer);
|
||||
m_frameBuffer->AddRef();
|
||||
*lplpDDSurface = static_cast<IDirectDrawSurface*>(m_frameBuffer);
|
||||
return DD_OK;
|
||||
}
|
||||
if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_TEXTURE) == DDSCAPS_TEXTURE) {
|
||||
@ -100,7 +99,7 @@ HRESULT DirectDrawImpl::CreateSurface(
|
||||
#ifdef MINIWIN_PIXELFORMAT
|
||||
format = MINIWIN_PIXELFORMAT;
|
||||
#else
|
||||
format = SDL_PIXELFORMAT_RGBA8888;
|
||||
format = SDL_PIXELFORMAT_RGBA32;
|
||||
#endif
|
||||
if ((lpDDSurfaceDesc->dwFlags & DDSD_PIXELFORMAT) == DDSD_PIXELFORMAT) {
|
||||
if ((lpDDSurfaceDesc->ddpfPixelFormat.dwFlags & DDPF_RGB) == DDPF_RGB) {
|
||||
@ -284,6 +283,12 @@ HRESULT DirectDrawImpl::SetCooperativeLevel(HWND hWnd, DDSCLFlags dwFlags)
|
||||
{
|
||||
SDL_Window* sdlWindow = reinterpret_cast<SDL_Window*>(hWnd);
|
||||
|
||||
if (m_virtualWidth == 0 || m_virtualHeight == 0) {
|
||||
if (!SDL_GetWindowSize(sdlWindow, &m_virtualWidth, &m_virtualHeight)) {
|
||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_GetWindowSizeInPixels: %s", SDL_GetError());
|
||||
}
|
||||
}
|
||||
|
||||
if (sdlWindow) {
|
||||
bool fullscreen;
|
||||
if ((dwFlags & DDSCL_NORMAL) == DDSCL_NORMAL) {
|
||||
@ -302,15 +307,14 @@ HRESULT DirectDrawImpl::SetCooperativeLevel(HWND hWnd, DDSCLFlags dwFlags)
|
||||
#endif
|
||||
}
|
||||
DDWindow = sdlWindow;
|
||||
DDRenderer = SDL_CreateRenderer(DDWindow, NULL);
|
||||
SDL_PropertiesID prop = SDL_GetRendererProperties(DDRenderer);
|
||||
SDL_SetRenderLogicalPresentation(DDRenderer, 640, 480, SDL_LOGICAL_PRESENTATION_LETTERBOX);
|
||||
}
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
HRESULT DirectDrawImpl::SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP)
|
||||
{
|
||||
m_virtualWidth = dwWidth;
|
||||
m_virtualHeight = dwHeight;
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
@ -325,33 +329,32 @@ HRESULT DirectDrawImpl::CreateDevice(
|
||||
DDSDesc.dwSize = sizeof(DDSURFACEDESC);
|
||||
pBackBuffer->GetSurfaceDesc(&DDSDesc);
|
||||
|
||||
Direct3DRMRenderer* renderer;
|
||||
if (SDL_memcmp(&guid, &SDL3_GPU_GUID, sizeof(GUID)) == 0) {
|
||||
renderer = Direct3DRMSDL3GPURenderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight);
|
||||
DDRenderer = Direct3DRMSDL3GPURenderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight);
|
||||
}
|
||||
#ifdef USE_OPENGLES2
|
||||
else if (SDL_memcmp(&guid, &OpenGLES2_GUID, sizeof(GUID)) == 0) {
|
||||
renderer = OpenGLES2Renderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight);
|
||||
DDRenderer = OpenGLES2Renderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_OPENGL1
|
||||
else if (SDL_memcmp(&guid, &OpenGL1_GUID, sizeof(GUID)) == 0) {
|
||||
renderer = OpenGL1Renderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight);
|
||||
DDRenderer = OpenGL1Renderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight);
|
||||
}
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
else if (SDL_memcmp(&guid, &DirectX9_GUID, sizeof(GUID)) == 0) {
|
||||
renderer = DirectX9Renderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight);
|
||||
DDRenderer = DirectX9Renderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight);
|
||||
}
|
||||
#endif
|
||||
else if (SDL_memcmp(&guid, &SOFTWARE_GUID, sizeof(GUID)) == 0) {
|
||||
renderer = new Direct3DRMSoftwareRenderer(DDSDesc.dwWidth, DDSDesc.dwHeight);
|
||||
DDRenderer = new Direct3DRMSoftwareRenderer(DDSDesc.dwWidth, DDSDesc.dwHeight);
|
||||
}
|
||||
else {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Device GUID not recognized");
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
*ppDirect3DDevice = static_cast<IDirect3DDevice2*>(renderer);
|
||||
*ppDirect3DDevice = static_cast<IDirect3DDevice2*>(DDRenderer);
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
#include "d3drmtexture_impl.h"
|
||||
#include "ddpalette_impl.h"
|
||||
#include "ddraw_impl.h"
|
||||
#include "ddsurface_impl.h"
|
||||
@ -19,6 +20,9 @@ DirectDrawSurfaceImpl::~DirectDrawSurfaceImpl()
|
||||
if (m_palette) {
|
||||
m_palette->Release();
|
||||
}
|
||||
if (m_texture) {
|
||||
m_texture->Release();
|
||||
}
|
||||
}
|
||||
|
||||
// IUnknown interface
|
||||
@ -69,6 +73,9 @@ HRESULT DirectDrawSurfaceImpl::Blt(
|
||||
if (blitSource != other->m_surface) {
|
||||
SDL_DestroySurface(blitSource);
|
||||
}
|
||||
if (m_texture) {
|
||||
m_texture->Changed(TRUE, FALSE);
|
||||
}
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
@ -203,6 +210,10 @@ HRESULT DirectDrawSurfaceImpl::SetPalette(LPDIRECTDRAWPALETTE lpDDPalette)
|
||||
MINIWIN_NOT_IMPLEMENTED();
|
||||
}
|
||||
|
||||
if (m_texture) {
|
||||
m_texture->Changed(FALSE, TRUE);
|
||||
}
|
||||
|
||||
if (m_palette) {
|
||||
m_palette->Release();
|
||||
}
|
||||
@ -216,5 +227,16 @@ HRESULT DirectDrawSurfaceImpl::SetPalette(LPDIRECTDRAWPALETTE lpDDPalette)
|
||||
HRESULT DirectDrawSurfaceImpl::Unlock(LPVOID lpSurfaceData)
|
||||
{
|
||||
SDL_UnlockSurface(m_surface);
|
||||
if (m_texture) {
|
||||
m_texture->Changed(TRUE, FALSE);
|
||||
}
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
IDirect3DRMTexture2* DirectDrawSurfaceImpl::ToTexture()
|
||||
{
|
||||
if (!m_texture) {
|
||||
m_texture = new Direct3DRMTextureImpl(this, false);
|
||||
}
|
||||
return m_texture;
|
||||
}
|
||||
|
||||
@ -6,21 +6,15 @@
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
FrameBufferImpl::FrameBufferImpl()
|
||||
FrameBufferImpl::FrameBufferImpl(DWORD virtualWidth, DWORD virtualHeight)
|
||||
: m_virtualWidth(virtualWidth), m_virtualHeight(virtualHeight)
|
||||
{
|
||||
int width, height;
|
||||
SDL_GetRenderOutputSize(DDRenderer, &width, &height);
|
||||
DDBackBuffer = SDL_CreateSurface(width, height, SDL_PIXELFORMAT_RGBA8888);
|
||||
if (!DDBackBuffer) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to create surface: %s", SDL_GetError());
|
||||
}
|
||||
m_uploadBuffer =
|
||||
SDL_CreateTexture(DDRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, width, height);
|
||||
m_transferBuffer = new DirectDrawSurfaceImpl(m_virtualWidth, m_virtualHeight, SDL_PIXELFORMAT_RGBA32);
|
||||
}
|
||||
|
||||
FrameBufferImpl::~FrameBufferImpl()
|
||||
{
|
||||
SDL_DestroySurface(DDBackBuffer);
|
||||
m_transferBuffer->Release();
|
||||
if (m_palette) {
|
||||
m_palette->Release();
|
||||
}
|
||||
@ -51,44 +45,30 @@ HRESULT FrameBufferImpl::Blt(
|
||||
LPDDBLTFX lpDDBltFx
|
||||
)
|
||||
{
|
||||
if (!DDRenderer) {
|
||||
return DDERR_GENERIC;
|
||||
}
|
||||
if (dynamic_cast<FrameBufferImpl*>(lpDDSrcSurface) == this) {
|
||||
return Flip(nullptr, DDFLIP_WAIT);
|
||||
}
|
||||
if ((dwFlags & DDBLT_COLORFILL) == DDBLT_COLORFILL) {
|
||||
SDL_Rect rect = {0, 0, DDBackBuffer->w, DDBackBuffer->h};
|
||||
const SDL_PixelFormatDetails* details = SDL_GetPixelFormatDetails(DDBackBuffer->format);
|
||||
Uint8 r = (lpDDBltFx->dwFillColor >> 16) & 0xFF;
|
||||
Uint8 g = (lpDDBltFx->dwFillColor >> 8) & 0xFF;
|
||||
Uint8 b = lpDDBltFx->dwFillColor & 0xFF;
|
||||
DirectDrawPaletteImpl* ddPal = static_cast<DirectDrawPaletteImpl*>(m_palette);
|
||||
SDL_Palette* sdlPalette = ddPal ? ddPal->m_palette : nullptr;
|
||||
Uint32 color = SDL_MapRGB(details, sdlPalette, r, g, b);
|
||||
SDL_FillSurfaceRect(DDBackBuffer, &rect, color);
|
||||
DDRenderer->Clear(r / 255.0f, g / 255.0f, b / 255.0f);
|
||||
return DD_OK;
|
||||
}
|
||||
auto other = static_cast<DirectDrawSurfaceImpl*>(lpDDSrcSurface);
|
||||
if (!other) {
|
||||
auto surface = static_cast<DirectDrawSurfaceImpl*>(lpDDSrcSurface);
|
||||
if (!surface) {
|
||||
return DDERR_GENERIC;
|
||||
}
|
||||
SDL_Rect srcRect = lpSrcRect ? ConvertRect(lpSrcRect) : SDL_Rect{0, 0, other->m_surface->w, other->m_surface->h};
|
||||
SDL_Rect dstRect = lpDestRect ? ConvertRect(lpDestRect) : SDL_Rect{0, 0, DDBackBuffer->w, DDBackBuffer->h};
|
||||
Uint32 textureId = DDRenderer->GetTextureId(surface->ToTexture());
|
||||
SDL_Rect srcRect =
|
||||
lpSrcRect ? ConvertRect(lpSrcRect) : SDL_Rect{0, 0, surface->m_surface->w, surface->m_surface->h};
|
||||
SDL_Rect dstRect =
|
||||
lpDestRect ? ConvertRect(lpDestRect) : SDL_Rect{0, 0, (int) m_virtualWidth, (int) m_virtualHeight};
|
||||
DDRenderer->Draw2DImage(textureId, srcRect, dstRect);
|
||||
|
||||
SDL_Surface* blitSource = other->m_surface;
|
||||
|
||||
if (other->m_surface->format != DDBackBuffer->format) {
|
||||
blitSource = SDL_ConvertSurface(other->m_surface, DDBackBuffer->format);
|
||||
if (!blitSource) {
|
||||
return DDERR_GENERIC;
|
||||
}
|
||||
}
|
||||
|
||||
if (!SDL_BlitSurfaceScaled(blitSource, &srcRect, DDBackBuffer, &dstRect, SDL_SCALEMODE_NEAREST)) {
|
||||
return DDERR_GENERIC;
|
||||
}
|
||||
|
||||
if (blitSource != other->m_surface) {
|
||||
SDL_DestroySurface(blitSource);
|
||||
}
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
@ -100,20 +80,20 @@ HRESULT FrameBufferImpl::BltFast(
|
||||
DDBltFastFlags dwTrans
|
||||
)
|
||||
{
|
||||
RECT destRect = {
|
||||
(int) dwX,
|
||||
(int) dwY,
|
||||
(int) (lpSrcRect->right - lpSrcRect->left + dwX),
|
||||
(int) (lpSrcRect->bottom - lpSrcRect->top + dwY)
|
||||
};
|
||||
auto surface = static_cast<DirectDrawSurfaceImpl*>(lpDDSrcSurface);
|
||||
int width = lpSrcRect ? (lpSrcRect->right - lpSrcRect->left) : surface->m_surface->w;
|
||||
int height = lpSrcRect ? (lpSrcRect->bottom - lpSrcRect->top) : surface->m_surface->h;
|
||||
RECT destRect = {(int) dwX, (int) dwY, (int) (dwX + width), (int) (dwY + height)};
|
||||
|
||||
return Blt(&destRect, lpDDSrcSurface, lpSrcRect, DDBLT_NONE, nullptr);
|
||||
}
|
||||
|
||||
HRESULT FrameBufferImpl::Flip(LPDIRECTDRAWSURFACE lpDDSurfaceTargetOverride, DDFlipFlags dwFlags)
|
||||
{
|
||||
SDL_UpdateTexture(m_uploadBuffer, nullptr, DDBackBuffer->pixels, DDBackBuffer->pitch);
|
||||
SDL_RenderTexture(DDRenderer, m_uploadBuffer, nullptr, nullptr);
|
||||
SDL_RenderPresent(DDRenderer);
|
||||
if (!DDRenderer) {
|
||||
return DDERR_GENERIC;
|
||||
}
|
||||
DDRenderer->Flip();
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
@ -146,7 +126,7 @@ HRESULT FrameBufferImpl::GetPixelFormat(LPDDPIXELFORMAT lpDDPixelFormat)
|
||||
{
|
||||
memset(lpDDPixelFormat, 0, sizeof(*lpDDPixelFormat));
|
||||
lpDDPixelFormat->dwFlags = DDPF_RGB;
|
||||
const SDL_PixelFormatDetails* details = SDL_GetPixelFormatDetails(DDBackBuffer->format);
|
||||
const SDL_PixelFormatDetails* details = SDL_GetPixelFormatDetails(m_transferBuffer->m_surface->format);
|
||||
if (details->bits_per_pixel == 8) {
|
||||
lpDDPixelFormat->dwFlags |= DDPF_PALETTEINDEXED8;
|
||||
}
|
||||
@ -163,25 +143,28 @@ HRESULT FrameBufferImpl::GetSurfaceDesc(LPDDSURFACEDESC lpDDSurfaceDesc)
|
||||
lpDDSurfaceDesc->dwFlags = DDSD_PIXELFORMAT;
|
||||
GetPixelFormat(&lpDDSurfaceDesc->ddpfPixelFormat);
|
||||
lpDDSurfaceDesc->dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
|
||||
lpDDSurfaceDesc->dwWidth = DDBackBuffer->w;
|
||||
lpDDSurfaceDesc->dwHeight = DDBackBuffer->h;
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
HRESULT FrameBufferImpl::IsLost()
|
||||
{
|
||||
lpDDSurfaceDesc->dwWidth = m_transferBuffer->m_surface->w;
|
||||
lpDDSurfaceDesc->dwHeight = m_transferBuffer->m_surface->h;
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
HRESULT FrameBufferImpl::Lock(LPRECT lpDestRect, DDSURFACEDESC* lpDDSurfaceDesc, DDLockFlags dwFlags, HANDLE hEvent)
|
||||
{
|
||||
if (!SDL_LockSurface(DDBackBuffer)) {
|
||||
if (!DDRenderer) {
|
||||
return DDERR_GENERIC;
|
||||
}
|
||||
if ((dwFlags & DDLOCK_WRITEONLY) == DDLOCK_WRITEONLY) {
|
||||
SDL_Rect rect = {0, 0, m_transferBuffer->m_surface->w, m_transferBuffer->m_surface->h};
|
||||
const SDL_PixelFormatDetails* details = SDL_GetPixelFormatDetails(m_transferBuffer->m_surface->format);
|
||||
SDL_Palette* palette = m_palette ? static_cast<DirectDrawPaletteImpl*>(m_palette)->m_palette : nullptr;
|
||||
Uint32 color = SDL_MapRGBA(details, palette, 0, 0, 0, 0);
|
||||
SDL_FillSurfaceRect(m_transferBuffer->m_surface, &rect, color);
|
||||
}
|
||||
else {
|
||||
DDRenderer->Download(m_transferBuffer->m_surface);
|
||||
}
|
||||
|
||||
GetSurfaceDesc(lpDDSurfaceDesc);
|
||||
lpDDSurfaceDesc->lpSurface = DDBackBuffer->pixels;
|
||||
lpDDSurfaceDesc->lPitch = DDBackBuffer->pitch;
|
||||
m_transferBuffer->Lock(lpDestRect, lpDDSurfaceDesc, dwFlags, hEvent);
|
||||
|
||||
return DD_OK;
|
||||
}
|
||||
@ -198,11 +181,6 @@ HRESULT FrameBufferImpl::Restore()
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
HRESULT FrameBufferImpl::SetClipper(LPDIRECTDRAWCLIPPER lpDDClipper)
|
||||
{
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
HRESULT FrameBufferImpl::SetColorKey(DDColorKeyFlags dwFlags, LPDDCOLORKEY lpDDColorKey)
|
||||
{
|
||||
MINIWIN_NOT_IMPLEMENTED();
|
||||
@ -211,7 +189,7 @@ HRESULT FrameBufferImpl::SetColorKey(DDColorKeyFlags dwFlags, LPDDCOLORKEY lpDDC
|
||||
|
||||
HRESULT FrameBufferImpl::SetPalette(LPDIRECTDRAWPALETTE lpDDPalette)
|
||||
{
|
||||
if (DDBackBuffer->format != SDL_PIXELFORMAT_INDEX8) {
|
||||
if (m_transferBuffer->m_surface->format != SDL_PIXELFORMAT_INDEX8) {
|
||||
MINIWIN_NOT_IMPLEMENTED();
|
||||
}
|
||||
|
||||
@ -220,13 +198,15 @@ HRESULT FrameBufferImpl::SetPalette(LPDIRECTDRAWPALETTE lpDDPalette)
|
||||
}
|
||||
|
||||
m_palette = lpDDPalette;
|
||||
SDL_SetSurfacePalette(DDBackBuffer, ((DirectDrawPaletteImpl*) m_palette)->m_palette);
|
||||
SDL_SetSurfacePalette(m_transferBuffer->m_surface, ((DirectDrawPaletteImpl*) m_palette)->m_palette);
|
||||
m_palette->AddRef();
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
HRESULT FrameBufferImpl::Unlock(LPVOID lpSurfaceData)
|
||||
{
|
||||
SDL_UnlockSurface(DDBackBuffer);
|
||||
m_transferBuffer->Unlock(lpSurfaceData);
|
||||
BltFast(0, 0, m_transferBuffer, nullptr, DDBLTFAST_WAIT);
|
||||
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
@ -11,8 +11,8 @@ struct Direct3DRMDevice2Impl : public Direct3DRMObjectBaseImpl<IDirect3DRMDevice
|
||||
Direct3DRMDevice2Impl(DWORD width, DWORD height, Direct3DRMRenderer* renderer);
|
||||
~Direct3DRMDevice2Impl() override;
|
||||
HRESULT QueryInterface(const GUID& riid, void** ppvObject) override;
|
||||
DWORD GetWidth() override;
|
||||
DWORD GetHeight() override;
|
||||
DWORD GetWidth() override { return m_virtualWidth; }
|
||||
DWORD GetHeight() override { return m_virtualHeight; }
|
||||
HRESULT SetBufferCount(int count) override;
|
||||
DWORD GetBufferCount() override;
|
||||
HRESULT SetShades(DWORD shadeCount) override;
|
||||
@ -38,7 +38,10 @@ struct Direct3DRMDevice2Impl : public Direct3DRMObjectBaseImpl<IDirect3DRMDevice
|
||||
Direct3DRMRenderer* m_renderer;
|
||||
|
||||
private:
|
||||
DWORD m_width;
|
||||
DWORD m_height;
|
||||
void Resize();
|
||||
|
||||
uint32_t m_virtualWidth;
|
||||
uint32_t m_virtualHeight;
|
||||
ViewportTransform m_viewportTransform;
|
||||
IDirect3DRMViewportArray* m_viewports;
|
||||
};
|
||||
|
||||
@ -10,7 +10,7 @@ struct MeshGroup {
|
||||
IDirect3DRMTexture* texture = nullptr;
|
||||
IDirect3DRMMaterial* material = nullptr;
|
||||
D3DRMRENDERQUALITY quality = D3DRMRENDER_GOURAUD;
|
||||
int vertexPerFace = 0;
|
||||
int vertexPerFace = 3;
|
||||
int version = 0;
|
||||
std::vector<D3DRMVERTEX> vertices;
|
||||
std::vector<DWORD> indices;
|
||||
|
||||
@ -26,8 +26,6 @@ struct Plane {
|
||||
float d;
|
||||
};
|
||||
|
||||
extern SDL_Renderer* DDRenderer;
|
||||
|
||||
class Direct3DRMRenderer : public IDirect3DDevice2 {
|
||||
public:
|
||||
virtual void PushLights(const SceneLight* vertices, size_t count) = 0;
|
||||
@ -35,8 +33,10 @@ class Direct3DRMRenderer : public IDirect3DDevice2 {
|
||||
virtual void SetFrustumPlanes(const Plane* frustumPlanes) = 0;
|
||||
virtual Uint32 GetTextureId(IDirect3DRMTexture* texture) = 0;
|
||||
virtual Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) = 0;
|
||||
virtual DWORD GetWidth() = 0;
|
||||
virtual DWORD GetHeight() = 0;
|
||||
int GetWidth() { return m_width; }
|
||||
int GetHeight() { return m_height; }
|
||||
int GetVirtualWidth() { return m_virtualWidth; }
|
||||
int GetVirtualHeight() { return m_virtualHeight; }
|
||||
virtual void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) = 0;
|
||||
virtual const char* GetName() = 0;
|
||||
virtual HRESULT BeginFrame() = 0;
|
||||
@ -44,13 +44,20 @@ class Direct3DRMRenderer : public IDirect3DDevice2 {
|
||||
virtual void SubmitDraw(
|
||||
DWORD meshId,
|
||||
const D3DRMMATRIX4D& modelViewMatrix,
|
||||
const D3DRMMATRIX4D& worldMatrix,
|
||||
const D3DRMMATRIX4D& viewMatrix,
|
||||
const Matrix3x3& normalMatrix,
|
||||
const Appearance& appearance
|
||||
) = 0;
|
||||
virtual HRESULT FinalizeFrame() = 0;
|
||||
virtual void Resize(int width, int height, const ViewportTransform& viewportTransform) = 0;
|
||||
virtual void Clear(float r, float g, float b) = 0;
|
||||
virtual void Flip() = 0;
|
||||
virtual void Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect) = 0;
|
||||
virtual void Download(SDL_Surface* target) = 0;
|
||||
|
||||
bool ConvertEventToRenderCoordinates(SDL_Event* event)
|
||||
{
|
||||
return SDL_ConvertEventToRenderCoordinates(DDRenderer, event);
|
||||
}
|
||||
protected:
|
||||
int m_width, m_height;
|
||||
int m_virtualWidth, m_virtualHeight;
|
||||
ViewportTransform m_viewportTransform;
|
||||
};
|
||||
|
||||
@ -20,8 +20,6 @@ class DirectX9Renderer : public Direct3DRMRenderer {
|
||||
void SetFrustumPlanes(const Plane* frustumPlanes) override;
|
||||
Uint32 GetTextureId(IDirect3DRMTexture* texture) override;
|
||||
Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override;
|
||||
DWORD GetWidth() override;
|
||||
DWORD GetHeight() override;
|
||||
void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override;
|
||||
const char* GetName() override;
|
||||
HRESULT BeginFrame() override;
|
||||
@ -29,17 +27,23 @@ class DirectX9Renderer : public Direct3DRMRenderer {
|
||||
void SubmitDraw(
|
||||
DWORD meshId,
|
||||
const D3DRMMATRIX4D& modelViewMatrix,
|
||||
const D3DRMMATRIX4D& worldMatrix,
|
||||
const D3DRMMATRIX4D& viewMatrix,
|
||||
const Matrix3x3& normalMatrix,
|
||||
const Appearance& appearance
|
||||
) override;
|
||||
HRESULT FinalizeFrame() override;
|
||||
void Resize(int width, int height, const ViewportTransform& viewportTransform) override;
|
||||
void Clear(float r, float g, float b) override;
|
||||
void Flip() override;
|
||||
void Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect) override;
|
||||
void Download(SDL_Surface* target) override;
|
||||
|
||||
private:
|
||||
void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture);
|
||||
void AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh);
|
||||
|
||||
SDL_Surface* m_renderedImage;
|
||||
DWORD m_width, m_height;
|
||||
std::vector<SceneLight> m_lights;
|
||||
std::vector<D3D9MeshCacheEntry> m_meshs;
|
||||
std::vector<D3D9TextureCacheEntry> m_textures;
|
||||
|
||||
@ -1,48 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "../d3drm/backends/opengl1/actual.h"
|
||||
#include "d3drmrenderer.h"
|
||||
#include "d3drmtexture_impl.h"
|
||||
#include "ddraw_impl.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <OpenGL/gl.h>
|
||||
#else
|
||||
#include <GL/gl.h>
|
||||
#endif
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
#include <vector>
|
||||
|
||||
DEFINE_GUID(OpenGL1_GUID, 0x682656F3, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03);
|
||||
|
||||
struct GLTextureCacheEntry {
|
||||
IDirect3DRMTexture* texture;
|
||||
Uint32 version;
|
||||
GLuint glTextureId;
|
||||
};
|
||||
|
||||
struct GLMeshCacheEntry {
|
||||
const MeshGroup* meshGroup;
|
||||
int version;
|
||||
bool flat;
|
||||
|
||||
// non-VBO cache
|
||||
std::vector<D3DVECTOR> positions;
|
||||
std::vector<D3DVECTOR> normals;
|
||||
std::vector<TexCoord> texcoords;
|
||||
std::vector<uint16_t> indices;
|
||||
|
||||
// VBO cache
|
||||
GLuint vboPositions;
|
||||
GLuint vboNormals;
|
||||
GLuint vboTexcoords;
|
||||
GLuint ibo;
|
||||
};
|
||||
|
||||
class OpenGL1Renderer : public Direct3DRMRenderer {
|
||||
public:
|
||||
static Direct3DRMRenderer* Create(DWORD width, DWORD height);
|
||||
OpenGL1Renderer(DWORD width, DWORD height, SDL_GLContext context, GLuint fbo, GLuint colorTex, GLuint depthRb);
|
||||
OpenGL1Renderer(DWORD width, DWORD height, SDL_GLContext context);
|
||||
~OpenGL1Renderer() override;
|
||||
|
||||
void PushLights(const SceneLight* lightsArray, size_t count) override;
|
||||
@ -50,8 +20,6 @@ class OpenGL1Renderer : public Direct3DRMRenderer {
|
||||
void SetFrustumPlanes(const Plane* frustumPlanes) override;
|
||||
Uint32 GetTextureId(IDirect3DRMTexture* texture) override;
|
||||
Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override;
|
||||
DWORD GetWidth() override;
|
||||
DWORD GetHeight() override;
|
||||
void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override;
|
||||
const char* GetName() override;
|
||||
HRESULT BeginFrame() override;
|
||||
@ -59,10 +27,17 @@ class OpenGL1Renderer : public Direct3DRMRenderer {
|
||||
void SubmitDraw(
|
||||
DWORD meshId,
|
||||
const D3DRMMATRIX4D& modelViewMatrix,
|
||||
const D3DRMMATRIX4D& worldMatrix,
|
||||
const D3DRMMATRIX4D& viewMatrix,
|
||||
const Matrix3x3& normalMatrix,
|
||||
const Appearance& appearance
|
||||
) override;
|
||||
HRESULT FinalizeFrame() override;
|
||||
void Resize(int width, int height, const ViewportTransform& viewportTransform) override;
|
||||
void Clear(float r, float g, float b) override;
|
||||
void Flip() override;
|
||||
void Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect) override;
|
||||
void Download(SDL_Surface* target) override;
|
||||
|
||||
private:
|
||||
void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture);
|
||||
@ -72,13 +47,11 @@ class OpenGL1Renderer : public Direct3DRMRenderer {
|
||||
std::vector<GLMeshCacheEntry> m_meshs;
|
||||
D3DRMMATRIX4D m_projection;
|
||||
SDL_Surface* m_renderedImage;
|
||||
DWORD m_width, m_height;
|
||||
bool m_useVBOs;
|
||||
bool m_dirty = false;
|
||||
std::vector<SceneLight> m_lights;
|
||||
SDL_GLContext m_context;
|
||||
GLuint m_fbo;
|
||||
GLuint m_colorTex;
|
||||
GLuint m_depthRb;
|
||||
ViewportTransform m_viewportTransform;
|
||||
};
|
||||
|
||||
inline static void OpenGL1Renderer_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx)
|
||||
|
||||
@ -14,6 +14,8 @@ struct GLES2TextureCacheEntry {
|
||||
IDirect3DRMTexture* texture;
|
||||
Uint32 version;
|
||||
GLuint glTextureId;
|
||||
uint16_t width;
|
||||
uint16_t height;
|
||||
};
|
||||
|
||||
struct GLES2MeshCacheEntry {
|
||||
@ -31,15 +33,7 @@ struct GLES2MeshCacheEntry {
|
||||
class OpenGLES2Renderer : public Direct3DRMRenderer {
|
||||
public:
|
||||
static Direct3DRMRenderer* Create(DWORD width, DWORD height);
|
||||
OpenGLES2Renderer(
|
||||
DWORD width,
|
||||
DWORD height,
|
||||
SDL_GLContext context,
|
||||
GLuint fbo,
|
||||
GLuint colorTex,
|
||||
GLuint vertexBuffer,
|
||||
GLuint shaderProgram
|
||||
);
|
||||
OpenGLES2Renderer(DWORD width, DWORD height, SDL_GLContext context, GLuint shaderProgram);
|
||||
~OpenGLES2Renderer() override;
|
||||
|
||||
void PushLights(const SceneLight* lightsArray, size_t count) override;
|
||||
@ -47,8 +41,6 @@ class OpenGLES2Renderer : public Direct3DRMRenderer {
|
||||
void SetFrustumPlanes(const Plane* frustumPlanes) override;
|
||||
Uint32 GetTextureId(IDirect3DRMTexture* texture) override;
|
||||
Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override;
|
||||
DWORD GetWidth() override;
|
||||
DWORD GetHeight() override;
|
||||
void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override;
|
||||
const char* GetName() override;
|
||||
HRESULT BeginFrame() override;
|
||||
@ -56,10 +48,17 @@ class OpenGLES2Renderer : public Direct3DRMRenderer {
|
||||
void SubmitDraw(
|
||||
DWORD meshId,
|
||||
const D3DRMMATRIX4D& modelViewMatrix,
|
||||
const D3DRMMATRIX4D& worldMatrix,
|
||||
const D3DRMMATRIX4D& viewMatrix,
|
||||
const Matrix3x3& normalMatrix,
|
||||
const Appearance& appearance
|
||||
) override;
|
||||
HRESULT FinalizeFrame() override;
|
||||
void Resize(int width, int height, const ViewportTransform& viewportTransform) override;
|
||||
void Clear(float r, float g, float b) override;
|
||||
void Flip() override;
|
||||
void Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect) override;
|
||||
void Download(SDL_Surface* target) override;
|
||||
|
||||
private:
|
||||
void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture);
|
||||
@ -69,13 +68,11 @@ class OpenGLES2Renderer : public Direct3DRMRenderer {
|
||||
std::vector<GLES2MeshCacheEntry> m_meshs;
|
||||
D3DRMMATRIX4D m_projection;
|
||||
SDL_Surface* m_renderedImage;
|
||||
DWORD m_width, m_height;
|
||||
bool m_dirty = false;
|
||||
std::vector<SceneLight> m_lights;
|
||||
SDL_GLContext m_context;
|
||||
GLuint m_fbo;
|
||||
GLuint m_colorTex;
|
||||
GLuint m_depthRb;
|
||||
GLuint m_shaderProgram;
|
||||
ViewportTransform m_viewportTransform;
|
||||
};
|
||||
|
||||
inline static void OpenGLES2Renderer_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx)
|
||||
|
||||
@ -51,8 +51,6 @@ class Direct3DRMSDL3GPURenderer : public Direct3DRMRenderer {
|
||||
Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override;
|
||||
void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override;
|
||||
void SetFrustumPlanes(const Plane* frustumPlanes) override;
|
||||
DWORD GetWidth() override;
|
||||
DWORD GetHeight() override;
|
||||
void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override;
|
||||
const char* GetName() override;
|
||||
HRESULT BeginFrame() override;
|
||||
@ -60,10 +58,17 @@ class Direct3DRMSDL3GPURenderer : public Direct3DRMRenderer {
|
||||
void SubmitDraw(
|
||||
DWORD meshId,
|
||||
const D3DRMMATRIX4D& modelViewMatrix,
|
||||
const D3DRMMATRIX4D& worldMatrix,
|
||||
const D3DRMMATRIX4D& viewMatrix,
|
||||
const Matrix3x3& normalMatrix,
|
||||
const Appearance& appearance
|
||||
) override;
|
||||
HRESULT FinalizeFrame() override;
|
||||
void Resize(int width, int height, const ViewportTransform& viewportTransform) override;
|
||||
void Clear(float r, float g, float b) override;
|
||||
void Flip() override;
|
||||
void Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect) override;
|
||||
void Download(SDL_Surface* target) override;
|
||||
|
||||
private:
|
||||
Direct3DRMSDL3GPURenderer(
|
||||
@ -72,12 +77,13 @@ class Direct3DRMSDL3GPURenderer : public Direct3DRMRenderer {
|
||||
SDL_GPUDevice* device,
|
||||
SDL_GPUGraphicsPipeline* opaquePipeline,
|
||||
SDL_GPUGraphicsPipeline* transparentPipeline,
|
||||
SDL_GPUTexture* transferTexture,
|
||||
SDL_GPUTexture* depthTexture,
|
||||
SDL_GPUGraphicsPipeline* uiPipeline,
|
||||
SDL_GPUSampler* sampler,
|
||||
SDL_GPUSampler* uiSampler,
|
||||
SDL_GPUTransferBuffer* uploadBuffer,
|
||||
SDL_GPUTransferBuffer* downloadBuffer
|
||||
int uploadBufferSize
|
||||
);
|
||||
void StartRenderPass(float r, float g, float b, bool clear);
|
||||
void WaitForPendingUpload();
|
||||
void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture);
|
||||
SDL_GPUTransferBuffer* GetUploadBuffer(size_t size);
|
||||
@ -85,26 +91,29 @@ class Direct3DRMSDL3GPURenderer : public Direct3DRMRenderer {
|
||||
void AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh);
|
||||
SDL3MeshCache UploadMesh(const MeshGroup& meshGroup);
|
||||
|
||||
DWORD m_width;
|
||||
DWORD m_height;
|
||||
MeshGroup m_uiMesh;
|
||||
SDL3MeshCache m_uiMeshCache;
|
||||
D3DVALUE m_front;
|
||||
D3DVALUE m_back;
|
||||
ViewportUniforms m_uniforms;
|
||||
FragmentShadingData m_fragmentShadingData;
|
||||
D3DDEVICEDESC m_desc;
|
||||
D3DRMMATRIX4D m_projection;
|
||||
std::vector<SDL3TextureCache> m_textures;
|
||||
std::vector<SDL3MeshCache> m_meshs;
|
||||
SDL_GPUDevice* m_device;
|
||||
SDL_GPUGraphicsPipeline* m_opaquePipeline;
|
||||
SDL_GPUGraphicsPipeline* m_transparentPipeline;
|
||||
SDL_GPUTexture* m_transferTexture;
|
||||
SDL_GPUTexture* m_depthTexture;
|
||||
SDL_GPUGraphicsPipeline* m_uiPipeline;
|
||||
SDL_GPUTexture* m_transferTexture = nullptr;
|
||||
SDL_GPUTexture* m_depthTexture = nullptr;
|
||||
SDL_GPUTexture* m_dummyTexture;
|
||||
int m_uploadBufferSize;
|
||||
SDL_GPUTransferBuffer* m_uploadBuffer;
|
||||
SDL_GPUTransferBuffer* m_downloadBuffer;
|
||||
SDL_GPUTransferBuffer* m_downloadBuffer = nullptr;
|
||||
SDL_GPUBuffer* m_vertexBuffer = nullptr;
|
||||
SDL_GPUSampler* m_sampler;
|
||||
SDL_GPUSampler* m_uiSampler;
|
||||
SDL_GPUCommandBuffer* m_cmdbuf = nullptr;
|
||||
SDL_GPURenderPass* m_renderPass = nullptr;
|
||||
SDL_GPUFence* m_uploadFence = nullptr;
|
||||
|
||||
@ -27,13 +27,12 @@ struct MeshCache {
|
||||
class Direct3DRMSoftwareRenderer : public Direct3DRMRenderer {
|
||||
public:
|
||||
Direct3DRMSoftwareRenderer(DWORD width, DWORD height);
|
||||
~Direct3DRMSoftwareRenderer() override;
|
||||
void PushLights(const SceneLight* vertices, size_t count) override;
|
||||
Uint32 GetTextureId(IDirect3DRMTexture* texture) override;
|
||||
Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override;
|
||||
void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override;
|
||||
void SetFrustumPlanes(const Plane* frustumPlanes) override;
|
||||
DWORD GetWidth() override;
|
||||
DWORD GetHeight() override;
|
||||
void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override;
|
||||
const char* GetName() override;
|
||||
HRESULT BeginFrame() override;
|
||||
@ -41,10 +40,17 @@ class Direct3DRMSoftwareRenderer : public Direct3DRMRenderer {
|
||||
void SubmitDraw(
|
||||
DWORD meshId,
|
||||
const D3DRMMATRIX4D& modelViewMatrix,
|
||||
const D3DRMMATRIX4D& worldMatrix,
|
||||
const D3DRMMATRIX4D& viewMatrix,
|
||||
const Matrix3x3& normalMatrix,
|
||||
const Appearance& appearance
|
||||
) override;
|
||||
HRESULT FinalizeFrame() override;
|
||||
void Resize(int width, int height, const ViewportTransform& viewportTransform) override;
|
||||
void Clear(float r, float g, float b) override;
|
||||
void Flip() override;
|
||||
void Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect) override;
|
||||
void Download(SDL_Surface* target) override;
|
||||
|
||||
private:
|
||||
void ClearZBuffer();
|
||||
@ -61,9 +67,10 @@ class Direct3DRMSoftwareRenderer : public Direct3DRMRenderer {
|
||||
void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture);
|
||||
void AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh);
|
||||
|
||||
DWORD m_width;
|
||||
DWORD m_height;
|
||||
SDL_Surface* m_renderedImage = nullptr;
|
||||
SDL_Palette* m_palette;
|
||||
SDL_Texture* m_uploadBuffer = nullptr;
|
||||
SDL_Renderer* m_renderer;
|
||||
const SDL_PixelFormatDetails* m_format;
|
||||
int m_bytesPerPixel;
|
||||
std::vector<SceneLight> m_lights;
|
||||
|
||||
@ -4,10 +4,12 @@
|
||||
|
||||
struct Direct3DRMTextureImpl : public Direct3DRMObjectBaseImpl<IDirect3DRMTexture2> {
|
||||
Direct3DRMTextureImpl(D3DRMIMAGE* image);
|
||||
Direct3DRMTextureImpl(IDirectDrawSurface* surface);
|
||||
Direct3DRMTextureImpl(IDirectDrawSurface* surface, bool holdsRef);
|
||||
~Direct3DRMTextureImpl() override;
|
||||
HRESULT QueryInterface(const GUID& riid, void** ppvObject) override;
|
||||
HRESULT Changed(BOOL pixels, BOOL palette) override;
|
||||
|
||||
IDirectDrawSurface* m_surface = nullptr;
|
||||
Uint8 m_version = 0;
|
||||
bool m_holdsRef;
|
||||
};
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
struct DeferredDrawCommand {
|
||||
DWORD meshId;
|
||||
D3DRMMATRIX4D modelViewMatrix;
|
||||
D3DRMMATRIX4D worldMatrix;
|
||||
Matrix3x3 normalMatrix;
|
||||
Appearance appearance;
|
||||
float depth;
|
||||
@ -36,24 +37,24 @@ struct Direct3DRMViewportImpl : public Direct3DRMObjectBaseImpl<IDirect3DRMViewp
|
||||
D3DVALUE GetBack() override;
|
||||
HRESULT SetField(D3DVALUE field) override;
|
||||
D3DVALUE GetField() override;
|
||||
DWORD GetWidth() override;
|
||||
DWORD GetHeight() override;
|
||||
DWORD GetWidth() override { return m_virtualWidth; }
|
||||
DWORD GetHeight() override { return m_virtualHeight; }
|
||||
HRESULT Transform(D3DRMVECTOR4D* screen, D3DVECTOR* world) override;
|
||||
HRESULT InverseTransform(D3DVECTOR* world, D3DRMVECTOR4D* screen) override;
|
||||
HRESULT Pick(float x, float y, LPDIRECT3DRMPICKEDARRAY* pickedArray) override;
|
||||
void CloseDevice();
|
||||
void UpdateProjectionMatrix();
|
||||
|
||||
private:
|
||||
HRESULT RenderScene();
|
||||
void CollectLightsFromFrame(IDirect3DRMFrame* frame, D3DRMMATRIX4D parentMatrix, std::vector<SceneLight>& lights);
|
||||
void CollectMeshesFromFrame(IDirect3DRMFrame* frame, D3DRMMATRIX4D parentMatrix);
|
||||
void BuildViewFrustumPlanes();
|
||||
void UpdateProjectionMatrix();
|
||||
Direct3DRMRenderer* m_renderer;
|
||||
std::vector<DeferredDrawCommand> m_deferredDraws;
|
||||
D3DCOLOR m_backgroundColor = 0xFF000000;
|
||||
DWORD m_width;
|
||||
DWORD m_height;
|
||||
DWORD m_virtualWidth;
|
||||
DWORD m_virtualHeight;
|
||||
D3DRMMATRIX4D m_viewProjectionwMatrix;
|
||||
D3DRMMATRIX4D m_viewMatrix;
|
||||
D3DRMMATRIX4D m_projectionMatrix;
|
||||
|
||||
@ -8,9 +8,7 @@
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
extern SDL_Window* DDWindow;
|
||||
extern SDL_Surface* DDBackBuffer;
|
||||
extern FrameBufferImpl* DDFrameBuffer;
|
||||
extern SDL_Renderer* DDRenderer;
|
||||
extern Direct3DRMRenderer* DDRenderer;
|
||||
|
||||
inline static SDL_Rect ConvertRect(const RECT* r)
|
||||
{
|
||||
@ -47,6 +45,11 @@ struct DirectDrawImpl : public IDirectDraw2, public IDirect3D2 {
|
||||
HRESULT CreateDevice(const GUID& guid, IDirectDrawSurface* pBackBuffer, IDirect3DDevice2** ppDirect3DDevice)
|
||||
override;
|
||||
HRESULT EnumDevices(LPD3DENUMDEVICESCALLBACK cb, void* ctx) override;
|
||||
|
||||
private:
|
||||
FrameBufferImpl* m_frameBuffer;
|
||||
int m_virtualWidth = 0;
|
||||
int m_virtualHeight = 0;
|
||||
};
|
||||
|
||||
HRESULT DirectDrawEnumerate(LPDDENUMCALLBACKA cb, void* context);
|
||||
|
||||
@ -35,8 +35,11 @@ struct DirectDrawSurfaceImpl : public IDirectDrawSurface3 {
|
||||
HRESULT SetPalette(LPDIRECTDRAWPALETTE lpDDPalette) override;
|
||||
HRESULT Unlock(LPVOID lpSurfaceData) override;
|
||||
|
||||
IDirect3DRMTexture2* ToTexture();
|
||||
|
||||
SDL_Surface* m_surface = nullptr;
|
||||
|
||||
private:
|
||||
IDirect3DRMTexture2* m_texture = nullptr;
|
||||
IDirectDrawPalette* m_palette = nullptr;
|
||||
};
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
#include <miniwin/ddraw.h>
|
||||
|
||||
struct FrameBufferImpl : public IDirectDrawSurface3 {
|
||||
FrameBufferImpl();
|
||||
FrameBufferImpl(DWORD virtualWidth, DWORD virtualHeight);
|
||||
~FrameBufferImpl() override;
|
||||
|
||||
// IUnknown interface
|
||||
@ -27,16 +27,18 @@ struct FrameBufferImpl : public IDirectDrawSurface3 {
|
||||
HRESULT GetPalette(LPDIRECTDRAWPALETTE* lplpDDPalette) override;
|
||||
HRESULT GetPixelFormat(LPDDPIXELFORMAT lpDDPixelFormat) override;
|
||||
HRESULT GetSurfaceDesc(DDSURFACEDESC* lpDDSurfaceDesc) override;
|
||||
HRESULT IsLost() override;
|
||||
HRESULT IsLost() override { return DD_OK; }
|
||||
HRESULT Lock(LPRECT lpDestRect, DDSURFACEDESC* lpDDSurfaceDesc, DDLockFlags dwFlags, HANDLE hEvent) override;
|
||||
HRESULT ReleaseDC(HDC hDC) override;
|
||||
HRESULT Restore() override;
|
||||
HRESULT SetClipper(IDirectDrawClipper* lpDDClipper) override;
|
||||
HRESULT SetClipper(IDirectDrawClipper* lpDDClipper) override { return DD_OK; }
|
||||
HRESULT SetColorKey(DDColorKeyFlags dwFlags, LPDDCOLORKEY lpDDColorKey) override;
|
||||
HRESULT SetPalette(LPDIRECTDRAWPALETTE lpDDPalette) override;
|
||||
HRESULT Unlock(LPVOID lpSurfaceData) override;
|
||||
|
||||
private:
|
||||
SDL_Texture* m_uploadBuffer;
|
||||
uint32_t m_virtualWidth;
|
||||
uint32_t m_virtualHeight;
|
||||
DirectDrawSurfaceImpl* m_transferBuffer;
|
||||
IDirectDrawPalette* m_palette = nullptr;
|
||||
};
|
||||
|
||||
@ -15,3 +15,9 @@ struct Appearance {
|
||||
uint32_t textureId;
|
||||
uint32_t flat;
|
||||
};
|
||||
|
||||
struct ViewportTransform {
|
||||
float scale;
|
||||
float offsetX;
|
||||
float offsetY;
|
||||
};
|
||||
|
||||
@ -4,6 +4,7 @@ configureLegoModelPresenter(MxS32): 'DLL exported function'
|
||||
configureLegoPartPresenter(MxS32, MxS32): 'DLL exported function'
|
||||
configureLegoROI(int): 'DLL exported function'
|
||||
configureLegoWorldPresenter(MxS32): 'DLL exported function'
|
||||
configureMxTransitionManager(TransitionType): 'DLL exported function'
|
||||
GetNoCD_SourceName(): 'DLL exported function'
|
||||
m_3dView: 'Allow this variable name'
|
||||
m_3dManager: 'Allow this variable name'
|
||||
|
||||
Loading…
Reference in New Issue
Block a user