mirror of
https://github.com/isledecomp/isle-portable.git
synced 2025-08-03 23:56:18 -04:00
Make draw cursor
feature work for modern platforms (#480)
This commit is contained in:
parent
8e9f531b88
commit
0191be7461
@ -473,6 +473,9 @@ if (ISLE_BUILD_APP)
|
||||
ISLE/res/isle.rc
|
||||
ISLE/isleapp.cpp
|
||||
ISLE/islefiles.cpp
|
||||
${CMAKE_SOURCE_DIR}/ISLE/res/arrow_bmp.h
|
||||
${CMAKE_SOURCE_DIR}/ISLE/res/busy_bmp.h
|
||||
${CMAKE_SOURCE_DIR}/ISLE/res/no_bmp.h
|
||||
)
|
||||
list(APPEND isle_targets isle)
|
||||
if (WIN32)
|
||||
@ -529,6 +532,39 @@ if (ISLE_BUILD_APP)
|
||||
ISLE/3ds/config.cpp
|
||||
)
|
||||
endif()
|
||||
if(Python3_FOUND)
|
||||
if(NOT DEFINED PYTHON_PIL_AVAILABLE)
|
||||
execute_process(
|
||||
COMMAND ${Python3_EXECUTABLE} -c "import PIL; print('pil')"
|
||||
RESULT_VARIABLE PIL_RESULT
|
||||
OUTPUT_VARIABLE PIL_OUTPUT
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
if(PIL_RESULT EQUAL 0 AND PIL_OUTPUT STREQUAL "pil")
|
||||
set(PIL_AVAILABLE 1)
|
||||
else()
|
||||
message(STATUS "Python PIL not found, using pre-generated headers.")
|
||||
set(PIL_AVAILABLE 0)
|
||||
endif()
|
||||
set(PYTHON_PIL_AVAILABLE ${PIL_AVAILABLE} CACHE BOOL "Is Python3 Pillow available?")
|
||||
endif()
|
||||
if(PYTHON_PIL_AVAILABLE)
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
${CMAKE_SOURCE_DIR}/ISLE/res/arrow_bmp.h
|
||||
${CMAKE_SOURCE_DIR}/ISLE/res/busy_bmp.h
|
||||
${CMAKE_SOURCE_DIR}/ISLE/res/no_bmp.h
|
||||
COMMAND ${Python3_EXECUTABLE} tools/curpng2h.py ISLE/res/arrow.png ISLE/res/busy.png ISLE/res/no.png
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
DEPENDS
|
||||
${CMAKE_SOURCE_DIR}/tools/curpng2h.py
|
||||
${CMAKE_SOURCE_DIR}/ISLE/res/arrow.png
|
||||
${CMAKE_SOURCE_DIR}/ISLE/res/busy.png
|
||||
${CMAKE_SOURCE_DIR}/ISLE/res/no.png
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (ISLE_BUILD_CONFIG)
|
||||
|
@ -28,7 +28,10 @@
|
||||
#include "mxtransitionmanager.h"
|
||||
#include "mxutilities.h"
|
||||
#include "mxvariabletable.h"
|
||||
#include "res/arrow_bmp.h"
|
||||
#include "res/busy_bmp.h"
|
||||
#include "res/isle_bmp.h"
|
||||
#include "res/no_bmp.h"
|
||||
#include "res/resource.h"
|
||||
#include "roi/legoroi.h"
|
||||
#include "tgl/d3drm/impl.h"
|
||||
@ -135,6 +138,10 @@ IsleApp::IsleApp()
|
||||
m_cursorBusy = NULL;
|
||||
m_cursorNo = NULL;
|
||||
m_cursorCurrent = NULL;
|
||||
m_cursorArrowBitmap = NULL;
|
||||
m_cursorBusyBitmap = NULL;
|
||||
m_cursorNoBitmap = NULL;
|
||||
m_cursorCurrentBitmap = NULL;
|
||||
|
||||
LegoOmni::CreateInstance();
|
||||
|
||||
@ -656,6 +663,12 @@ MxResult IsleApp::SetupWindow()
|
||||
m_cursorBusy = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_WAIT);
|
||||
m_cursorNo = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NOT_ALLOWED);
|
||||
SDL_SetCursor(m_cursorCurrent);
|
||||
if (g_isle->GetDrawCursor()) {
|
||||
SDL_HideCursor();
|
||||
m_cursorCurrentBitmap = m_cursorArrowBitmap = &arrow_cursor;
|
||||
m_cursorBusyBitmap = &busy_cursor;
|
||||
m_cursorNoBitmap = &no_cursor;
|
||||
}
|
||||
|
||||
SDL_PropertiesID props = SDL_CreateProperties();
|
||||
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, g_targetWidth);
|
||||
@ -739,6 +752,9 @@ MxResult IsleApp::SetupWindow()
|
||||
LegoOmni::GetInstance()->GetInputManager()->SetUseJoystick(m_useJoystick);
|
||||
LegoOmni::GetInstance()->GetInputManager()->SetJoystickIndex(m_joystickIndex);
|
||||
}
|
||||
if (LegoOmni::GetInstance()->GetVideoManager() && g_isle->GetDrawCursor()) {
|
||||
LegoOmni::GetInstance()->GetVideoManager()->SetCursorBitmap(m_cursorCurrentBitmap);
|
||||
}
|
||||
MxDirect3D* d3d = LegoOmni::GetInstance()->GetVideoManager()->GetDirect3D();
|
||||
if (d3d) {
|
||||
SDL_Log(
|
||||
@ -1023,15 +1039,19 @@ void IsleApp::SetupCursor(Cursor p_cursor)
|
||||
switch (p_cursor) {
|
||||
case e_cursorArrow:
|
||||
m_cursorCurrent = m_cursorArrow;
|
||||
m_cursorCurrentBitmap = m_cursorArrowBitmap;
|
||||
break;
|
||||
case e_cursorBusy:
|
||||
m_cursorCurrent = m_cursorBusy;
|
||||
m_cursorCurrentBitmap = m_cursorBusyBitmap;
|
||||
break;
|
||||
case e_cursorNo:
|
||||
m_cursorCurrent = m_cursorNo;
|
||||
m_cursorCurrentBitmap = m_cursorNoBitmap;
|
||||
break;
|
||||
case e_cursorNone:
|
||||
m_cursorCurrent = NULL;
|
||||
m_cursorCurrentBitmap = NULL;
|
||||
case e_cursorUnused3:
|
||||
case e_cursorUnused4:
|
||||
case e_cursorUnused5:
|
||||
@ -1043,12 +1063,22 @@ void IsleApp::SetupCursor(Cursor p_cursor)
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_cursorCurrent != NULL) {
|
||||
SDL_SetCursor(m_cursorCurrent);
|
||||
SDL_ShowCursor();
|
||||
if (g_isle->GetDrawCursor()) {
|
||||
if (m_cursorCurrentBitmap == NULL) {
|
||||
VideoManager()->SetCursorBitmap(NULL);
|
||||
}
|
||||
else {
|
||||
VideoManager()->SetCursorBitmap(m_cursorCurrentBitmap);
|
||||
}
|
||||
}
|
||||
else {
|
||||
SDL_HideCursor();
|
||||
if (m_cursorCurrent != NULL) {
|
||||
SDL_SetCursor(m_cursorCurrent);
|
||||
SDL_ShowCursor();
|
||||
}
|
||||
else {
|
||||
SDL_HideCursor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#ifndef ISLEAPP_H
|
||||
#define ISLEAPP_H
|
||||
|
||||
#include "cursor.h"
|
||||
#include "lego1_export.h"
|
||||
#include "legoutils.h"
|
||||
#include "mxtransitionmanager.h"
|
||||
@ -87,6 +88,10 @@ private:
|
||||
SDL_Cursor* m_cursorBusy; // 0x80
|
||||
SDL_Cursor* m_cursorNo; // 0x84
|
||||
SDL_Cursor* m_cursorCurrent; // 0x88
|
||||
const CursorBitmap* m_cursorArrowBitmap;
|
||||
const CursorBitmap* m_cursorBusyBitmap;
|
||||
const CursorBitmap* m_cursorNoBitmap;
|
||||
const CursorBitmap* m_cursorCurrentBitmap;
|
||||
char* m_mediaPath;
|
||||
|
||||
char* m_iniPath;
|
||||
|
BIN
ISLE/res/arrow.png
Normal file
BIN
ISLE/res/arrow.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 165 B |
37
ISLE/res/arrow_bmp.h
Normal file
37
ISLE/res/arrow_bmp.h
Normal file
@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
// Generated from ISLE/res/arrow.png
|
||||
// Dimensions: 32x32
|
||||
// This file is auto-generated, do not edit it.
|
||||
|
||||
#include "cursor.h"
|
||||
|
||||
static const unsigned char arrow_data[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
|
||||
0x48, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00,
|
||||
0x41, 0x00, 0x00, 0x00, 0x40, 0x80, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00,
|
||||
0x40, 0x20, 0x00, 0x00, 0x41, 0xF0, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00,
|
||||
0x54, 0x80, 0x00, 0x00, 0x64, 0x80, 0x00, 0x00, 0x42, 0x40, 0x00, 0x00,
|
||||
0x02, 0x40, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00,
|
||||
0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
static const unsigned char arrow_mask[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
|
||||
0x78, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00,
|
||||
0x7F, 0x00, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00,
|
||||
0x7F, 0xE0, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00,
|
||||
0x77, 0x80, 0x00, 0x00, 0x67, 0x80, 0x00, 0x00, 0x43, 0xC0, 0x00, 0x00,
|
||||
0x03, 0xC0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00,
|
||||
0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
static const CursorBitmap arrow_cursor = { 32, 32, arrow_data, arrow_mask };
|
BIN
ISLE/res/busy.png
Normal file
BIN
ISLE/res/busy.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 173 B |
37
ISLE/res/busy_bmp.h
Normal file
37
ISLE/res/busy_bmp.h
Normal file
@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
// Generated from ISLE/res/busy.png
|
||||
// Dimensions: 32x32
|
||||
// This file is auto-generated, do not edit it.
|
||||
|
||||
#include "cursor.h"
|
||||
|
||||
static const unsigned char busy_data[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0x00,
|
||||
0x00, 0x40, 0x01, 0x00, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x20, 0x02, 0x00,
|
||||
0x00, 0x20, 0x02, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x22, 0xA2, 0x00,
|
||||
0x00, 0x11, 0x44, 0x00, 0x00, 0x08, 0x88, 0x00, 0x00, 0x04, 0x10, 0x00,
|
||||
0x00, 0x02, 0x20, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x02, 0x20, 0x00,
|
||||
0x00, 0x02, 0x20, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x08, 0x88, 0x00,
|
||||
0x00, 0x10, 0x04, 0x00, 0x00, 0x20, 0x82, 0x00, 0x00, 0x21, 0x42, 0x00,
|
||||
0x00, 0x22, 0xA2, 0x00, 0x00, 0x25, 0x52, 0x00, 0x00, 0x7F, 0xFF, 0x00,
|
||||
0x00, 0x40, 0x01, 0x00, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
static const unsigned char busy_mask[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0x00,
|
||||
0x00, 0x7F, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x3F, 0xFE, 0x00,
|
||||
0x00, 0x3F, 0xFE, 0x00, 0x00, 0x3F, 0xFE, 0x00, 0x00, 0x3F, 0xFE, 0x00,
|
||||
0x00, 0x1F, 0xFC, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x07, 0xF0, 0x00,
|
||||
0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00,
|
||||
0x00, 0x03, 0xE0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x0F, 0xF8, 0x00,
|
||||
0x00, 0x1F, 0xFC, 0x00, 0x00, 0x3F, 0xFE, 0x00, 0x00, 0x3F, 0xFE, 0x00,
|
||||
0x00, 0x3F, 0xFE, 0x00, 0x00, 0x3F, 0xFE, 0x00, 0x00, 0x7F, 0xFF, 0x00,
|
||||
0x00, 0x7F, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
static const CursorBitmap busy_cursor = { 32, 32, busy_data, busy_mask };
|
BIN
ISLE/res/no.png
Normal file
BIN
ISLE/res/no.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 191 B |
37
ISLE/res/no_bmp.h
Normal file
37
ISLE/res/no_bmp.h
Normal file
@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
// Generated from ISLE/res/no.png
|
||||
// Dimensions: 32x32
|
||||
// This file is auto-generated, do not edit it.
|
||||
|
||||
#include "cursor.h"
|
||||
|
||||
static const unsigned char no_data[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00, 0x1F, 0xF8, 0x00,
|
||||
0x00, 0x3C, 0x3C, 0x00, 0x00, 0x70, 0x0E, 0x00, 0x00, 0xF8, 0x07, 0x00,
|
||||
0x00, 0xDC, 0x03, 0x00, 0x01, 0xCE, 0x03, 0x80, 0x01, 0x87, 0x01, 0x80,
|
||||
0x01, 0x83, 0x81, 0x80, 0x01, 0x81, 0xC1, 0x80, 0x01, 0x80, 0xE1, 0x80,
|
||||
0x01, 0xC0, 0x73, 0x80, 0x00, 0xC0, 0x3B, 0x00, 0x00, 0xE0, 0x1F, 0x00,
|
||||
0x00, 0x70, 0x0E, 0x00, 0x00, 0x3C, 0x1C, 0x00, 0x00, 0x1F, 0xF8, 0x00,
|
||||
0x00, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
static const unsigned char no_mask[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x07, 0xE0, 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x00, 0x3F, 0xFC, 0x00,
|
||||
0x00, 0x7F, 0xFE, 0x00, 0x00, 0xFC, 0x3F, 0x00, 0x01, 0xFC, 0x0F, 0x80,
|
||||
0x01, 0xFE, 0x07, 0x80, 0x03, 0xFF, 0x07, 0xC0, 0x03, 0xCF, 0x83, 0xC0,
|
||||
0x03, 0xC7, 0xC3, 0xC0, 0x03, 0xC3, 0xE3, 0xC0, 0x03, 0xC1, 0xF3, 0xC0,
|
||||
0x03, 0xE0, 0xFF, 0xC0, 0x01, 0xE0, 0x7F, 0x80, 0x01, 0xF0, 0x3F, 0x80,
|
||||
0x00, 0xFC, 0x1F, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x3F, 0xFC, 0x00,
|
||||
0x00, 0x1F, 0xF8, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
static const CursorBitmap no_cursor = { 32, 32, no_data, no_mask };
|
8
LEGO1/cursor.h
Normal file
8
LEGO1/cursor.h
Normal file
@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
typedef struct CursorBitmap {
|
||||
int width;
|
||||
int height;
|
||||
const unsigned char* data;
|
||||
const unsigned char* mask;
|
||||
} CursorBitmap;
|
@ -1,6 +1,7 @@
|
||||
#ifndef LEGOVIDEOMANAGER_H
|
||||
#define LEGOVIDEOMANAGER_H
|
||||
|
||||
#include "cursor.h"
|
||||
#include "decomp.h"
|
||||
#include "lego1_export.h"
|
||||
#include "legophonemelist.h"
|
||||
@ -37,6 +38,7 @@ public:
|
||||
void EnableFullScreenMovie(MxBool p_enable);
|
||||
LEGO1_EXPORT void EnableFullScreenMovie(MxBool p_enable, MxBool p_scale);
|
||||
LEGO1_EXPORT void MoveCursor(MxS32 p_cursorX, MxS32 p_cursorY);
|
||||
LEGO1_EXPORT void SetCursorBitmap(const CursorBitmap* p_cursorBitmap);
|
||||
void ToggleFPS(MxBool p_visible);
|
||||
|
||||
MxResult Tickle() override; // vtable+0x08
|
||||
|
@ -272,14 +272,13 @@ void LegoVideoManager::MoveCursor(MxS32 p_cursorX, MxS32 p_cursorY)
|
||||
{
|
||||
m_cursorX = p_cursorX;
|
||||
m_cursorY = p_cursorY;
|
||||
m_drawCursor = TRUE;
|
||||
|
||||
if (623 < p_cursorX) {
|
||||
m_cursorX = 623;
|
||||
if (640 < p_cursorX) {
|
||||
m_cursorX = 640;
|
||||
}
|
||||
|
||||
if (463 < p_cursorY) {
|
||||
m_cursorY = 463;
|
||||
if (480 < p_cursorY) {
|
||||
m_cursorY = 480;
|
||||
}
|
||||
}
|
||||
|
||||
@ -836,3 +835,30 @@ void LegoVideoManager::DrawTextToSurface32(
|
||||
++p_text;
|
||||
}
|
||||
}
|
||||
|
||||
void LegoVideoManager::SetCursorBitmap(const CursorBitmap* p_cursorBitmap)
|
||||
{
|
||||
if (p_cursorBitmap == NULL) {
|
||||
m_drawCursor = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_cursorSurface != NULL) {
|
||||
m_cursorSurface->Release();
|
||||
m_cursorSurface = NULL;
|
||||
}
|
||||
|
||||
m_cursorRect.top = 0;
|
||||
m_cursorRect.left = 0;
|
||||
m_cursorRect.bottom = p_cursorBitmap->height;
|
||||
m_cursorRect.right = p_cursorBitmap->width;
|
||||
|
||||
m_cursorSurface = MxDisplaySurface::CreateCursorSurface(p_cursorBitmap);
|
||||
|
||||
if (m_cursorSurface == NULL) {
|
||||
m_drawCursor = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
m_drawCursor = TRUE;
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#ifndef MXDISPLAYSURFACE_H
|
||||
#define MXDISPLAYSURFACE_H
|
||||
|
||||
#include "cursor.h"
|
||||
#include "decomp.h"
|
||||
#include "mxcore.h"
|
||||
#include "mxvideoparam.h"
|
||||
@ -97,6 +98,7 @@ public:
|
||||
|
||||
void ClearScreen();
|
||||
static LPDIRECTDRAWSURFACE CreateCursorSurface();
|
||||
static LPDIRECTDRAWSURFACE CreateCursorSurface(const CursorBitmap* p_cursorBitmap);
|
||||
static LPDIRECTDRAWSURFACE CopySurface(LPDIRECTDRAWSURFACE p_src);
|
||||
|
||||
LPDIRECTDRAWSURFACE GetDirectDrawSurface1() { return m_ddSurface1; }
|
||||
|
@ -1296,3 +1296,125 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::FUN_100bc8b0(MxS32 p_width, MxS32 p_height
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
LPDIRECTDRAWSURFACE MxDisplaySurface::CreateCursorSurface(const CursorBitmap* p_cursorBitmap)
|
||||
{
|
||||
LPDIRECTDRAWSURFACE newSurface = NULL;
|
||||
IDirectDraw* draw = MVideoManager()->GetDirectDraw();
|
||||
MVideoManager();
|
||||
|
||||
DDSURFACEDESC ddsd;
|
||||
memset(&ddsd, 0, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
|
||||
if (draw->GetDisplayMode(&ddsd) != DD_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MxS32 bytesPerPixel = ddsd.ddpfPixelFormat.dwRGBBitCount / 8;
|
||||
|
||||
ddsd.dwWidth = p_cursorBitmap->width;
|
||||
ddsd.dwHeight = p_cursorBitmap->height;
|
||||
ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN;
|
||||
|
||||
if (draw->CreateSurface(&ddsd, &newSurface, NULL) != DD_OK) {
|
||||
ddsd.ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY;
|
||||
ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
|
||||
|
||||
if (draw->CreateSurface(&ddsd, &newSurface, NULL) != DD_OK) {
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
memset(&ddsd, 0, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
|
||||
if (newSurface->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL) != DD_OK) {
|
||||
goto done;
|
||||
}
|
||||
else {
|
||||
for (int y = 0; y < p_cursorBitmap->height; y++) {
|
||||
for (int x = 0; x < p_cursorBitmap->width; x++) {
|
||||
MxS32 bitIndex = y * p_cursorBitmap->width + x;
|
||||
MxS32 byteIndex = bitIndex / 8;
|
||||
MxS32 bitOffset = 7 - (bitIndex % 8);
|
||||
|
||||
MxBool isOpaque = (p_cursorBitmap->mask[byteIndex] >> bitOffset) & 1;
|
||||
MxBool isBlack = (p_cursorBitmap->data[byteIndex] >> bitOffset) & 1;
|
||||
|
||||
switch (bytesPerPixel) {
|
||||
case 1: {
|
||||
MxU8* surface = (MxU8*) ddsd.lpSurface;
|
||||
|
||||
MxU8 pixel;
|
||||
if (!isOpaque) {
|
||||
pixel = 0x10;
|
||||
}
|
||||
else {
|
||||
pixel = isBlack ? 0 : 0xff;
|
||||
}
|
||||
}
|
||||
case 2: {
|
||||
MxU16* surface = (MxU16*) ddsd.lpSurface;
|
||||
|
||||
MxU16 pixel;
|
||||
if (!isOpaque) {
|
||||
pixel = RGB555_CREATE(0x1f, 0, 0x1f);
|
||||
}
|
||||
else {
|
||||
pixel = isBlack ? RGB555_CREATE(0, 0, 0) : RGB555_CREATE(0x1f, 0x1f, 0x1f);
|
||||
}
|
||||
|
||||
surface[x + y * p_cursorBitmap->width] = pixel;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
MxU32* surface = (MxU32*) ddsd.lpSurface;
|
||||
|
||||
MxS32 pixel;
|
||||
if (!isOpaque) {
|
||||
pixel = RGB8888_CREATE(0, 0, 0, 0); // Transparent pixel
|
||||
}
|
||||
else {
|
||||
pixel = isBlack ? RGB8888_CREATE(0, 0, 0, 0xff) : RGB8888_CREATE(0xff, 0xff, 0xff, 0xff);
|
||||
}
|
||||
|
||||
surface[x + y * p_cursorBitmap->width] = pixel;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newSurface->Unlock(ddsd.lpSurface);
|
||||
switch (bytesPerPixel) {
|
||||
case 1: {
|
||||
DDCOLORKEY colorkey;
|
||||
colorkey.dwColorSpaceHighValue = 0x10;
|
||||
colorkey.dwColorSpaceLowValue = 0x10;
|
||||
newSurface->SetColorKey(DDCKEY_SRCBLT, &colorkey);
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
DDCOLORKEY colorkey;
|
||||
colorkey.dwColorSpaceHighValue = RGB555_CREATE(0x1f, 0, 0x1f);
|
||||
colorkey.dwColorSpaceLowValue = RGB555_CREATE(0x1f, 0, 0x1f);
|
||||
newSurface->SetColorKey(DDCKEY_SRCBLT, &colorkey);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return newSurface;
|
||||
}
|
||||
|
||||
done:
|
||||
if (newSurface) {
|
||||
newSurface->Release();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
75
tools/curpng2h.py
Executable file
75
tools/curpng2h.py
Executable file
@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
import itertools
|
||||
from PIL import Image
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def encode_cursor(image_path: Path):
|
||||
img = Image.open(image_path).convert("RGBA")
|
||||
width, height = img.size
|
||||
pixels = img.load()
|
||||
|
||||
num_pixels = width * height
|
||||
num_bytes = (num_pixels + 7) // 8
|
||||
|
||||
data = bytearray(num_bytes)
|
||||
mask = bytearray(num_bytes)
|
||||
|
||||
for y in range(height):
|
||||
for x in range(width):
|
||||
i = y * width + x
|
||||
byte_index = i // 8
|
||||
bit_offset = 7 - (i % 8)
|
||||
|
||||
r, g, b, a = pixels[x, y]
|
||||
|
||||
if a >= 128:
|
||||
mask[byte_index] |= 1 << bit_offset # opaque
|
||||
lum = int(0.299 * r + 0.587 * g + 0.114 * b)
|
||||
if lum < 128:
|
||||
data[byte_index] |= 1 << bit_offset # black pixel
|
||||
|
||||
return data, mask, width, height
|
||||
|
||||
|
||||
def to_c_array(name, data):
|
||||
lines = []
|
||||
for rowdata in itertools.batched(data, 12):
|
||||
lines.append(", ".join(f"0x{byte:02X}" for byte in rowdata) + ",")
|
||||
array_str = "\n ".join(lines)
|
||||
return f"static const unsigned char {name}[] = {{\n {array_str}\n}};\n"
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(allow_abbrev=False)
|
||||
parser.add_argument("inputs", nargs="+", help="PNG images", type=Path)
|
||||
args = parser.parse_args()
|
||||
|
||||
input_files: list[Path] = args.inputs
|
||||
|
||||
for input_file in input_files:
|
||||
data, mask, width, height = encode_cursor(input_file)
|
||||
|
||||
input_file_name = input_file.stem
|
||||
output_file = input_file.with_name(f"{input_file_name}_bmp.h")
|
||||
|
||||
with output_file.open("w", newline="\n") as f:
|
||||
f.write(f"#pragma once\n\n")
|
||||
f.write(f"// Generated from {input_file}\n")
|
||||
f.write(f"// Dimensions: {width}x{height}\n")
|
||||
f.write("// This file is auto-generated, do not edit it.\n\n")
|
||||
f.write(f'#include "cursor.h"\n\n')
|
||||
f.write(to_c_array(f"{input_file_name}_data", data))
|
||||
f.write("\n")
|
||||
f.write(to_c_array(f"{input_file_name}_mask", mask))
|
||||
f.write("\n")
|
||||
f.write(
|
||||
f"static const CursorBitmap {input_file_name}_cursor = {'{'} {width}, {height}, {input_file_name}_data, {input_file_name}_mask {'}'};\n"
|
||||
)
|
||||
|
||||
print(f"Written {output_file} with cursor data.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
Loading…
x
Reference in New Issue
Block a user