Compare commits
82 Commits
WindowsCla
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
16b527e3cf | ||
|
|
683204519c | ||
|
|
ecdf802d68 | ||
|
|
dc00dbde0d | ||
|
|
862fe13dcd | ||
|
|
6c299ed103 | ||
|
|
fc1975a607 | ||
|
|
e61bbd634c | ||
|
|
917b68d630 | ||
|
|
46d3ae324c | ||
|
|
d27740bd38 | ||
|
|
cfd30419c2 | ||
|
|
3ec96b84ad | ||
|
|
34cb964ea5 | ||
|
|
5789492021 | ||
|
|
38cf08e298 | ||
|
|
5cd01807b2 | ||
|
|
57af3af800 | ||
|
|
8e07b7fc3f | ||
|
|
0076f8947c | ||
|
|
43ce86571c | ||
|
|
4188cd3455 | ||
|
|
685dfe78c2 | ||
|
|
348d79ef38 | ||
|
|
9088c44b3e | ||
|
|
06b760e8dd | ||
|
|
d06aa1c736 | ||
|
|
787c623cfe | ||
|
|
b7bf1563e5 | ||
|
|
f56abf0596 | ||
|
|
a7e3503e2c | ||
|
|
2ee40560ee | ||
|
|
5682640e36 | ||
|
|
7ec2ab9a76 | ||
|
|
82d4d8719f | ||
|
|
f302687c7f | ||
|
|
fd973f049c | ||
|
|
5947727f80 | ||
|
|
69ecce88df | ||
|
|
43593b168d | ||
|
|
d80074b9b6 | ||
|
|
69027eca53 | ||
|
|
ac289c7f48 | ||
|
|
87e44b700b | ||
|
|
48721e5811 | ||
|
|
7ee508118c | ||
|
|
8c4f38c0af | ||
|
|
167a2c2bd1 | ||
|
|
f1c6c48b36 | ||
|
|
8d2745fc33 | ||
|
|
5e03978cd7 | ||
|
|
261457a959 | ||
|
|
93de90b680 | ||
|
|
dc5915b4f8 | ||
|
|
c3b6daefc9 | ||
|
|
81c2034a16 | ||
|
|
8a421a2623 | ||
|
|
a281000308 | ||
|
|
03deda2f9d | ||
|
|
ba5a0f3044 | ||
|
|
b37f5d6d76 | ||
|
|
593b4d161c | ||
|
|
7c29c05d64 | ||
|
|
89f4b6d535 | ||
|
|
373351c2ba | ||
|
|
65037e0e69 | ||
|
|
e2a2037a99 | ||
|
|
b843e9a6cb | ||
|
|
b4cb827d73 | ||
|
|
22ce8ac538 | ||
|
|
625a6e7498 | ||
|
|
fd9de493e6 | ||
|
|
4c196a9290 | ||
|
|
c63c6701ac | ||
|
|
8bae7a5b05 | ||
|
|
af5a70785e | ||
|
|
c5b7c0ad16 | ||
|
|
28e2417ef9 | ||
|
|
2fe6d6d33a | ||
|
|
e0638c598d | ||
|
|
9a10d72e1f | ||
|
|
a09ea75d80 |
10
.gitignore
vendored
10
.gitignore
vendored
@@ -266,11 +266,13 @@ __pycache__/
|
|||||||
/Export
|
/Export
|
||||||
/DrMem
|
/DrMem
|
||||||
/Doc private
|
/Doc private
|
||||||
|
# Windows local libraries
|
||||||
# Cmake stuff
|
|
||||||
/Libs
|
/Libs
|
||||||
/out
|
|
||||||
|
|
||||||
# WinXp stuff
|
#CMake generated
|
||||||
|
out/
|
||||||
|
/cmake-build-debug
|
||||||
|
|
||||||
|
# Windows XP stuff
|
||||||
DebugWinXp/
|
DebugWinXp/
|
||||||
ReleaseWinXp/
|
ReleaseWinXp/
|
||||||
|
|||||||
219
CMakeLists.txt
Normal file
219
CMakeLists.txt
Normal file
@@ -0,0 +1,219 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.0)
|
||||||
|
project(SpaceCadetPinball)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
|
|
||||||
|
|
||||||
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/bin)
|
||||||
|
|
||||||
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMakeModules")
|
||||||
|
|
||||||
|
# On Windows, set paths to SDL-devel packages here
|
||||||
|
if(WIN32)
|
||||||
|
list(APPEND SDL2_PATH "${CMAKE_CURRENT_LIST_DIR}/Libs/SDL2")
|
||||||
|
list(APPEND SDL2_MIXER_PATH "${CMAKE_CURRENT_LIST_DIR}/Libs/SDL2_mixer")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Link mingw libs static
|
||||||
|
if(MINGW)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# SDL2main is not needed
|
||||||
|
set(SDL2_BUILDING_LIBRARY ON)
|
||||||
|
|
||||||
|
find_package(SDL2 REQUIRED)
|
||||||
|
FIND_PACKAGE(SDL2_mixer REQUIRED)
|
||||||
|
|
||||||
|
include_directories(${SDL2_INCLUDE_DIR} ${SDL2_MIXER_INCLUDE_DIR})
|
||||||
|
get_property(dirs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES)
|
||||||
|
foreach(dir ${dirs})
|
||||||
|
message(STATUS "Include dir='${dir}'")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
set(SOURCE_FILES
|
||||||
|
SpaceCadetPinball/control.cpp
|
||||||
|
SpaceCadetPinball/control.h
|
||||||
|
SpaceCadetPinball/EmbeddedData.cpp
|
||||||
|
SpaceCadetPinball/EmbeddedData.h
|
||||||
|
SpaceCadetPinball/fullscrn.cpp
|
||||||
|
SpaceCadetPinball/fullscrn.h
|
||||||
|
SpaceCadetPinball/gdrv.cpp
|
||||||
|
SpaceCadetPinball/gdrv.h
|
||||||
|
SpaceCadetPinball/GroupData.cpp
|
||||||
|
SpaceCadetPinball/GroupData.h
|
||||||
|
SpaceCadetPinball/high_score.cpp
|
||||||
|
SpaceCadetPinball/high_score.h
|
||||||
|
SpaceCadetPinball/loader.cpp
|
||||||
|
SpaceCadetPinball/loader.h
|
||||||
|
SpaceCadetPinball/maths.cpp
|
||||||
|
SpaceCadetPinball/maths.h
|
||||||
|
SpaceCadetPinball/midi.cpp
|
||||||
|
SpaceCadetPinball/midi.h
|
||||||
|
SpaceCadetPinball/nudge.cpp
|
||||||
|
SpaceCadetPinball/nudge.h
|
||||||
|
SpaceCadetPinball/options.cpp
|
||||||
|
SpaceCadetPinball/options.h
|
||||||
|
SpaceCadetPinball/partman.cpp
|
||||||
|
SpaceCadetPinball/partman.h
|
||||||
|
SpaceCadetPinball/pb.cpp
|
||||||
|
SpaceCadetPinball/pb.h
|
||||||
|
SpaceCadetPinball/pch.h
|
||||||
|
SpaceCadetPinball/pinball.cpp
|
||||||
|
SpaceCadetPinball/pinball.h
|
||||||
|
SpaceCadetPinball/proj.cpp
|
||||||
|
SpaceCadetPinball/proj.h
|
||||||
|
SpaceCadetPinball/render.cpp
|
||||||
|
SpaceCadetPinball/render.h
|
||||||
|
SpaceCadetPinball/score.cpp
|
||||||
|
SpaceCadetPinball/score.h
|
||||||
|
SpaceCadetPinball/Sound.cpp
|
||||||
|
SpaceCadetPinball/Sound.h
|
||||||
|
SpaceCadetPinball/SpaceCadetPinball.cpp
|
||||||
|
SpaceCadetPinball/TBall.cpp
|
||||||
|
SpaceCadetPinball/TBall.h
|
||||||
|
SpaceCadetPinball/TBlocker.cpp
|
||||||
|
SpaceCadetPinball/TBlocker.h
|
||||||
|
SpaceCadetPinball/TBumper.cpp
|
||||||
|
SpaceCadetPinball/TBumper.h
|
||||||
|
SpaceCadetPinball/TCircle.cpp
|
||||||
|
SpaceCadetPinball/TCircle.h
|
||||||
|
SpaceCadetPinball/TCollisionComponent.cpp
|
||||||
|
SpaceCadetPinball/TCollisionComponent.h
|
||||||
|
SpaceCadetPinball/TComponentGroup.cpp
|
||||||
|
SpaceCadetPinball/TComponentGroup.h
|
||||||
|
SpaceCadetPinball/TDemo.cpp
|
||||||
|
SpaceCadetPinball/TDemo.h
|
||||||
|
SpaceCadetPinball/TDrain.cpp
|
||||||
|
SpaceCadetPinball/TDrain.h
|
||||||
|
SpaceCadetPinball/TEdgeBox.h
|
||||||
|
SpaceCadetPinball/TEdgeManager.cpp
|
||||||
|
SpaceCadetPinball/TEdgeManager.h
|
||||||
|
SpaceCadetPinball/TEdgeSegment.cpp
|
||||||
|
SpaceCadetPinball/TEdgeSegment.h
|
||||||
|
SpaceCadetPinball/TFlagSpinner.cpp
|
||||||
|
SpaceCadetPinball/TFlagSpinner.h
|
||||||
|
SpaceCadetPinball/TFlipper.cpp
|
||||||
|
SpaceCadetPinball/TFlipper.h
|
||||||
|
SpaceCadetPinball/TFlipperEdge.cpp
|
||||||
|
SpaceCadetPinball/TFlipperEdge.h
|
||||||
|
SpaceCadetPinball/TGate.cpp
|
||||||
|
SpaceCadetPinball/TGate.h
|
||||||
|
SpaceCadetPinball/THole.cpp
|
||||||
|
SpaceCadetPinball/THole.h
|
||||||
|
SpaceCadetPinball/timer.cpp
|
||||||
|
SpaceCadetPinball/timer.h
|
||||||
|
SpaceCadetPinball/TKickback.cpp
|
||||||
|
SpaceCadetPinball/TKickback.h
|
||||||
|
SpaceCadetPinball/TKickout.cpp
|
||||||
|
SpaceCadetPinball/TKickout.h
|
||||||
|
SpaceCadetPinball/TLight.cpp
|
||||||
|
SpaceCadetPinball/TLight.h
|
||||||
|
SpaceCadetPinball/TLightBargraph.cpp
|
||||||
|
SpaceCadetPinball/TLightBargraph.h
|
||||||
|
SpaceCadetPinball/TLightGroup.cpp
|
||||||
|
SpaceCadetPinball/TLightGroup.h
|
||||||
|
SpaceCadetPinball/TLightRollover.cpp
|
||||||
|
SpaceCadetPinball/TLightRollover.h
|
||||||
|
SpaceCadetPinball/TLine.cpp
|
||||||
|
SpaceCadetPinball/TLine.h
|
||||||
|
SpaceCadetPinball/TOneway.cpp
|
||||||
|
SpaceCadetPinball/TOneway.h
|
||||||
|
SpaceCadetPinball/TPinballComponent.cpp
|
||||||
|
SpaceCadetPinball/TPinballComponent.h
|
||||||
|
SpaceCadetPinball/TPinballTable.cpp
|
||||||
|
SpaceCadetPinball/TPinballTable.h
|
||||||
|
SpaceCadetPinball/TPlunger.cpp
|
||||||
|
SpaceCadetPinball/TPlunger.h
|
||||||
|
SpaceCadetPinball/TPopupTarget.cpp
|
||||||
|
SpaceCadetPinball/TPopupTarget.h
|
||||||
|
SpaceCadetPinball/TRamp.cpp
|
||||||
|
SpaceCadetPinball/TRamp.h
|
||||||
|
SpaceCadetPinball/TRollover.cpp
|
||||||
|
SpaceCadetPinball/TRollover.h
|
||||||
|
SpaceCadetPinball/TSink.cpp
|
||||||
|
SpaceCadetPinball/TSink.h
|
||||||
|
SpaceCadetPinball/TSoloTarget.cpp
|
||||||
|
SpaceCadetPinball/TSoloTarget.h
|
||||||
|
SpaceCadetPinball/TSound.cpp
|
||||||
|
SpaceCadetPinball/TSound.h
|
||||||
|
SpaceCadetPinball/TTableLayer.cpp
|
||||||
|
SpaceCadetPinball/TTableLayer.h
|
||||||
|
SpaceCadetPinball/TTextBox.cpp
|
||||||
|
SpaceCadetPinball/TTextBox.h
|
||||||
|
SpaceCadetPinball/TTextBoxMessage.cpp
|
||||||
|
SpaceCadetPinball/TTextBoxMessage.h
|
||||||
|
SpaceCadetPinball/TTimer.cpp
|
||||||
|
SpaceCadetPinball/TTimer.h
|
||||||
|
SpaceCadetPinball/TTripwire.cpp
|
||||||
|
SpaceCadetPinball/TTripwire.h
|
||||||
|
SpaceCadetPinball/TWall.cpp
|
||||||
|
SpaceCadetPinball/TWall.h
|
||||||
|
SpaceCadetPinball/winmain.cpp
|
||||||
|
SpaceCadetPinball/winmain.h
|
||||||
|
SpaceCadetPinball/zdrv.cpp
|
||||||
|
SpaceCadetPinball/zdrv.h
|
||||||
|
SpaceCadetPinball/imconfig.h
|
||||||
|
SpaceCadetPinball/imgui_internal.h
|
||||||
|
SpaceCadetPinball/imgui.cpp
|
||||||
|
SpaceCadetPinball/imgui.h
|
||||||
|
SpaceCadetPinball/imgui_sdl.cpp
|
||||||
|
SpaceCadetPinball/imgui_sdl.h
|
||||||
|
SpaceCadetPinball/imgui_draw.cpp
|
||||||
|
SpaceCadetPinball/imgui_widgets.cpp
|
||||||
|
SpaceCadetPinball/imgui_tables.cpp
|
||||||
|
SpaceCadetPinball/imgui_demo.cpp
|
||||||
|
SpaceCadetPinball/imgui_impl_sdl.cpp
|
||||||
|
SpaceCadetPinball/imgui_impl_sdl.h
|
||||||
|
SpaceCadetPinball/imstb_textedit.h
|
||||||
|
SpaceCadetPinball/imstb_rectpack.h
|
||||||
|
SpaceCadetPinball/imstb_truetype.h
|
||||||
|
)
|
||||||
|
|
||||||
|
# On Windows, include resource file with the icon
|
||||||
|
if(WIN32)
|
||||||
|
set_source_files_properties(SpaceCadetPinball/SpaceCadetPinball.rc LANGUAGE RC)
|
||||||
|
list(APPEND SOURCE_FILES SpaceCadetPinball/SpaceCadetPinball.rc)
|
||||||
|
endif(WIN32)
|
||||||
|
|
||||||
|
add_executable(SpaceCadetPinball ${SOURCE_FILES})
|
||||||
|
|
||||||
|
# Skip pch on foreign code
|
||||||
|
set_source_files_properties(
|
||||||
|
SpaceCadetPinball/imgui.cpp
|
||||||
|
SpaceCadetPinball/imgui_sdl.cpp
|
||||||
|
SpaceCadetPinball/imgui_draw.cpp
|
||||||
|
SpaceCadetPinball/imgui_widgets.cpp
|
||||||
|
SpaceCadetPinball/imgui_tables.cpp
|
||||||
|
SpaceCadetPinball/imgui_demo.cpp
|
||||||
|
SpaceCadetPinball/imgui_impl_sdl.cpp
|
||||||
|
PROPERTIES SKIP_PRECOMPILE_HEADERS 1
|
||||||
|
)
|
||||||
|
|
||||||
|
if(${CMAKE_VERSION} VERSION_GREATER "3.16.0" OR ${CMAKE_VERSION} VERSION_EQUAL "3.16.0")
|
||||||
|
target_precompile_headers(SpaceCadetPinball
|
||||||
|
PUBLIC
|
||||||
|
SpaceCadetPinball/pch.h
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_link_libraries(SpaceCadetPinball ${SDL2_LIBRARY} ${SDL2_MIXER_LIBRARY})
|
||||||
|
|
||||||
|
# On Windows, copy DLL to output
|
||||||
|
if(WIN32)
|
||||||
|
list(GET SDL2_LIBRARY -1 SDL2_DLL_PATH)
|
||||||
|
list(GET SDL2_MIXER_LIBRARY -1 SDL2_MIXER_DLL_PATH)
|
||||||
|
get_filename_component(SDL2_DLL_PATH ${SDL2_DLL_PATH} DIRECTORY)
|
||||||
|
get_filename_component(SDL2_MIXER_DLL_PATH ${SDL2_MIXER_DLL_PATH} DIRECTORY)
|
||||||
|
if(MINGW)
|
||||||
|
string(REGEX REPLACE "lib$" "bin" SDL2_DLL_PATH ${SDL2_DLL_PATH})
|
||||||
|
string(REGEX REPLACE "lib$" "bin" SDL2_MIXER_DLL_PATH ${SDL2_MIXER_DLL_PATH})
|
||||||
|
endif()
|
||||||
|
message(STATUS "copy paths='${SDL2_DLL_PATH}' '${SDL2_MIXER_DLL_PATH}'")
|
||||||
|
add_custom_command(TARGET SpaceCadetPinball POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${SDL2_DLL_PATH}/SDL2.dll" $<TARGET_FILE_DIR:SpaceCadetPinball>
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${SDL2_MIXER_DLL_PATH}/SDL2_mixer.dll" $<TARGET_FILE_DIR:SpaceCadetPinball>
|
||||||
|
)
|
||||||
|
endif()
|
||||||
173
CMakeModules/FindSDL2.cmake
Normal file
173
CMakeModules/FindSDL2.cmake
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
|
||||||
|
# This module defines
|
||||||
|
# SDL2_LIBRARY, the name of the library to link against
|
||||||
|
# SDL2_FOUND, if false, do not try to link to SDL2
|
||||||
|
# SDL2_INCLUDE_DIR, where to find SDL.h
|
||||||
|
#
|
||||||
|
# This module responds to the the flag:
|
||||||
|
# SDL2_BUILDING_LIBRARY
|
||||||
|
# If this is defined, then no SDL2main will be linked in because
|
||||||
|
# only applications need main().
|
||||||
|
# Otherwise, it is assumed you are building an application and this
|
||||||
|
# module will attempt to locate and set the the proper link flags
|
||||||
|
# as part of the returned SDL2_LIBRARY variable.
|
||||||
|
#
|
||||||
|
# Don't forget to include SDLmain.h and SDLmain.m your project for the
|
||||||
|
# OS X framework based version. (Other versions link to -lSDL2main which
|
||||||
|
# this module will try to find on your behalf.) Also for OS X, this
|
||||||
|
# module will automatically add the -framework Cocoa on your behalf.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Additional Note: If you see an empty SDL2_LIBRARY_TEMP in your configuration
|
||||||
|
# and no SDL2_LIBRARY, it means CMake did not find your SDL2 library
|
||||||
|
# (SDL2.dll, libsdl2.so, SDL2.framework, etc).
|
||||||
|
# Set SDL2_LIBRARY_TEMP to point to your SDL2 library, and configure again.
|
||||||
|
# Similarly, if you see an empty SDL2MAIN_LIBRARY, you should set this value
|
||||||
|
# as appropriate. These values are used to generate the final SDL2_LIBRARY
|
||||||
|
# variable, but when these values are unset, SDL2_LIBRARY does not get created.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# $SDL2DIR is an environment variable that would
|
||||||
|
# correspond to the ./configure --prefix=$SDL2DIR
|
||||||
|
# used in building SDL2.
|
||||||
|
# l.e.galup 9-20-02
|
||||||
|
#
|
||||||
|
# Modified by Eric Wing.
|
||||||
|
# Added code to assist with automated building by using environmental variables
|
||||||
|
# and providing a more controlled/consistent search behavior.
|
||||||
|
# Added new modifications to recognize OS X frameworks and
|
||||||
|
# additional Unix paths (FreeBSD, etc).
|
||||||
|
# Also corrected the header search path to follow "proper" SDL guidelines.
|
||||||
|
# Added a search for SDL2main which is needed by some platforms.
|
||||||
|
# Added a search for threads which is needed by some platforms.
|
||||||
|
# Added needed compile switches for MinGW.
|
||||||
|
#
|
||||||
|
# On OSX, this will prefer the Framework version (if found) over others.
|
||||||
|
# People will have to manually change the cache values of
|
||||||
|
# SDL2_LIBRARY to override this selection or set the CMake environment
|
||||||
|
# CMAKE_INCLUDE_PATH to modify the search paths.
|
||||||
|
#
|
||||||
|
# Note that the header path has changed from SDL2/SDL.h to just SDL.h
|
||||||
|
# This needed to change because "proper" SDL convention
|
||||||
|
# is #include "SDL.h", not <SDL2/SDL.h>. This is done for portability
|
||||||
|
# reasons because not all systems place things in SDL2/ (see FreeBSD).
|
||||||
|
|
||||||
|
#=============================================================================
|
||||||
|
# Copyright 2003-2009 Kitware, Inc.
|
||||||
|
#
|
||||||
|
# Distributed under the OSI-approved BSD License (the "License");
|
||||||
|
# see accompanying file Copyright.txt for details.
|
||||||
|
#
|
||||||
|
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||||
|
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
# See the License for more information.
|
||||||
|
#=============================================================================
|
||||||
|
# (To distribute this file outside of CMake, substitute the full
|
||||||
|
# License text for the above reference.)
|
||||||
|
|
||||||
|
# message("<FindSDL2.cmake>")
|
||||||
|
|
||||||
|
SET(SDL2_SEARCH_PATHS
|
||||||
|
~/Library/Frameworks
|
||||||
|
/Library/Frameworks
|
||||||
|
/usr/local
|
||||||
|
/usr
|
||||||
|
/sw # Fink
|
||||||
|
/opt/local # DarwinPorts
|
||||||
|
/opt/csw # Blastwave
|
||||||
|
/opt
|
||||||
|
${SDL2_PATH}
|
||||||
|
)
|
||||||
|
|
||||||
|
FIND_PATH(SDL2_INCLUDE_DIR SDL.h
|
||||||
|
HINTS
|
||||||
|
$ENV{SDL2DIR}
|
||||||
|
PATH_SUFFIXES include/SDL2 include SDL2
|
||||||
|
PATHS ${SDL2_SEARCH_PATHS}
|
||||||
|
)
|
||||||
|
|
||||||
|
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
|
set(PATH_SUFFIXES lib64 lib/x64 lib)
|
||||||
|
else()
|
||||||
|
set(PATH_SUFFIXES lib/x86 lib)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
FIND_LIBRARY(SDL2_LIBRARY_TEMP
|
||||||
|
NAMES SDL2
|
||||||
|
HINTS
|
||||||
|
$ENV{SDL2DIR}
|
||||||
|
PATH_SUFFIXES ${PATH_SUFFIXES}
|
||||||
|
PATHS ${SDL2_SEARCH_PATHS}
|
||||||
|
)
|
||||||
|
|
||||||
|
IF(NOT SDL2_BUILDING_LIBRARY)
|
||||||
|
IF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework")
|
||||||
|
# Non-OS X framework versions expect you to also dynamically link to
|
||||||
|
# SDL2main. This is mainly for Windows and OS X. Other (Unix) platforms
|
||||||
|
# seem to provide SDL2main for compatibility even though they don't
|
||||||
|
# necessarily need it.
|
||||||
|
FIND_LIBRARY(SDL2MAIN_LIBRARY
|
||||||
|
NAMES SDL2main
|
||||||
|
HINTS
|
||||||
|
$ENV{SDL2DIR}
|
||||||
|
PATH_SUFFIXES ${PATH_SUFFIXES}
|
||||||
|
PATHS ${SDL2_SEARCH_PATHS}
|
||||||
|
)
|
||||||
|
ENDIF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework")
|
||||||
|
ENDIF(NOT SDL2_BUILDING_LIBRARY)
|
||||||
|
|
||||||
|
# SDL2 may require threads on your system.
|
||||||
|
# The Apple build may not need an explicit flag because one of the
|
||||||
|
# frameworks may already provide it.
|
||||||
|
# But for non-OSX systems, I will use the CMake Threads package.
|
||||||
|
IF(NOT APPLE)
|
||||||
|
FIND_PACKAGE(Threads)
|
||||||
|
ENDIF(NOT APPLE)
|
||||||
|
|
||||||
|
# MinGW needs an additional link flag, -mwindows
|
||||||
|
# It's total link flags should look like -lmingw32 -lSDL2main -lSDL2 -mwindows
|
||||||
|
IF(MINGW)
|
||||||
|
SET(MINGW32_LIBRARY mingw32 "-mwindows" CACHE STRING "mwindows for MinGW")
|
||||||
|
ENDIF(MINGW)
|
||||||
|
|
||||||
|
IF(SDL2_LIBRARY_TEMP)
|
||||||
|
# For SDL2main
|
||||||
|
IF(NOT SDL2_BUILDING_LIBRARY)
|
||||||
|
IF(SDL2MAIN_LIBRARY)
|
||||||
|
SET(SDL2_LIBRARY_TEMP ${SDL2MAIN_LIBRARY} ${SDL2_LIBRARY_TEMP})
|
||||||
|
ENDIF(SDL2MAIN_LIBRARY)
|
||||||
|
ENDIF(NOT SDL2_BUILDING_LIBRARY)
|
||||||
|
|
||||||
|
# For OS X, SDL2 uses Cocoa as a backend so it must link to Cocoa.
|
||||||
|
# CMake doesn't display the -framework Cocoa string in the UI even
|
||||||
|
# though it actually is there if I modify a pre-used variable.
|
||||||
|
# I think it has something to do with the CACHE STRING.
|
||||||
|
# So I use a temporary variable until the end so I can set the
|
||||||
|
# "real" variable in one-shot.
|
||||||
|
IF(APPLE)
|
||||||
|
SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} "-framework Cocoa")
|
||||||
|
ENDIF(APPLE)
|
||||||
|
|
||||||
|
# For threads, as mentioned Apple doesn't need this.
|
||||||
|
# In fact, there seems to be a problem if I used the Threads package
|
||||||
|
# and try using this line, so I'm just skipping it entirely for OS X.
|
||||||
|
IF(NOT APPLE)
|
||||||
|
SET(SDL2_LIBRARY_TEMP ${CMAKE_THREAD_LIBS_INIT} ${SDL2_LIBRARY_TEMP})
|
||||||
|
ENDIF(NOT APPLE)
|
||||||
|
|
||||||
|
# For MinGW library
|
||||||
|
IF(MINGW)
|
||||||
|
SET(SDL2_LIBRARY_TEMP ${MINGW32_LIBRARY} ${SDL2_LIBRARY_TEMP})
|
||||||
|
ENDIF(MINGW)
|
||||||
|
|
||||||
|
# Set the final string here so the GUI reflects the final state.
|
||||||
|
SET(SDL2_LIBRARY ${SDL2_LIBRARY_TEMP} CACHE STRING "Where the SDL2 Library can be found")
|
||||||
|
# Set the temp variable to INTERNAL so it is not seen in the CMake GUI
|
||||||
|
SET(SDL2_LIBRARY_TEMP "${SDL2_LIBRARY_TEMP}" CACHE INTERNAL "")
|
||||||
|
ENDIF(SDL2_LIBRARY_TEMP)
|
||||||
|
|
||||||
|
# message("</FindSDL2.cmake>")
|
||||||
|
|
||||||
|
INCLUDE(FindPackageHandleStandardArgs)
|
||||||
|
|
||||||
|
FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2 REQUIRED_VARS SDL2_LIBRARY SDL2_INCLUDE_DIR)
|
||||||
100
CMakeModules/FindSDL2_mixer.cmake
Normal file
100
CMakeModules/FindSDL2_mixer.cmake
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
# Locate SDL_MIXER library
|
||||||
|
#
|
||||||
|
# This module defines:
|
||||||
|
#
|
||||||
|
# ::
|
||||||
|
#
|
||||||
|
# SDL2_MIXER_LIBRARIES, the name of the library to link against
|
||||||
|
# SDL2_MIXER_INCLUDE_DIRS, where to find the headers
|
||||||
|
# SDL2_MIXER_FOUND, if false, do not try to link against
|
||||||
|
# SDL2_MIXER_VERSION_STRING - human-readable string containing the version of SDL_MIXER
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# For backward compatibility the following variables are also set:
|
||||||
|
#
|
||||||
|
# ::
|
||||||
|
#
|
||||||
|
# SDLMIXER_LIBRARY (same value as SDL2_MIXER_LIBRARIES)
|
||||||
|
# SDLMIXER_INCLUDE_DIR (same value as SDL2_MIXER_INCLUDE_DIRS)
|
||||||
|
# SDLMIXER_FOUND (same value as SDL2_MIXER_FOUND)
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# $SDLDIR is an environment variable that would correspond to the
|
||||||
|
# ./configure --prefix=$SDLDIR used in building SDL.
|
||||||
|
#
|
||||||
|
# Created by Eric Wing. This was influenced by the FindSDL.cmake
|
||||||
|
# module, but with modifications to recognize OS X frameworks and
|
||||||
|
# additional Unix paths (FreeBSD, etc).
|
||||||
|
|
||||||
|
#=============================================================================
|
||||||
|
# Copyright 2005-2009 Kitware, Inc.
|
||||||
|
# Copyright 2012 Benjamin Eikel
|
||||||
|
#
|
||||||
|
# Distributed under the OSI-approved BSD License (the "License");
|
||||||
|
# see accompanying file Copyright.txt for details.
|
||||||
|
#
|
||||||
|
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||||
|
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
# See the License for more information.
|
||||||
|
#=============================================================================
|
||||||
|
# (To distribute this file outside of CMake, substitute the full
|
||||||
|
# License text for the above reference.)
|
||||||
|
|
||||||
|
find_path(SDL2_MIXER_INCLUDE_DIR SDL_mixer.h
|
||||||
|
HINTS
|
||||||
|
ENV SDL2MIXERDIR
|
||||||
|
ENV SDL2DIR
|
||||||
|
PATH_SUFFIXES SDL2
|
||||||
|
# path suffixes to search inside ENV{SDLDIR}
|
||||||
|
include/SDL2 include
|
||||||
|
PATHS ${SDL2_MIXER_PATH}
|
||||||
|
)
|
||||||
|
|
||||||
|
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
|
set(VC_LIB_PATH_SUFFIX lib/x64)
|
||||||
|
else()
|
||||||
|
set(VC_LIB_PATH_SUFFIX lib/x86)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_library(SDL2_MIXER_LIBRARY
|
||||||
|
NAMES SDL2_mixer
|
||||||
|
HINTS
|
||||||
|
ENV SDL2MIXERDIR
|
||||||
|
ENV SDL2DIR
|
||||||
|
PATH_SUFFIXES lib bin ${VC_LIB_PATH_SUFFIX}
|
||||||
|
PATHS ${SDL2_MIXER_PATH}
|
||||||
|
)
|
||||||
|
|
||||||
|
if(SDL2_MIXER_INCLUDE_DIR AND EXISTS "${SDL2_MIXER_INCLUDE_DIR}/SDL_mixer.h")
|
||||||
|
file(STRINGS "${SDL2_MIXER_INCLUDE_DIR}/SDL_mixer.h" SDL2_MIXER_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL_MIXER_MAJOR_VERSION[ \t]+[0-9]+$")
|
||||||
|
file(STRINGS "${SDL2_MIXER_INCLUDE_DIR}/SDL_mixer.h" SDL2_MIXER_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL_MIXER_MINOR_VERSION[ \t]+[0-9]+$")
|
||||||
|
file(STRINGS "${SDL2_MIXER_INCLUDE_DIR}/SDL_mixer.h" SDL2_MIXER_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL_MIXER_PATCHLEVEL[ \t]+[0-9]+$")
|
||||||
|
string(REGEX REPLACE "^#define[ \t]+SDL_MIXER_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_MIXER_VERSION_MAJOR "${SDL2_MIXER_VERSION_MAJOR_LINE}")
|
||||||
|
string(REGEX REPLACE "^#define[ \t]+SDL_MIXER_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_MIXER_VERSION_MINOR "${SDL2_MIXER_VERSION_MINOR_LINE}")
|
||||||
|
string(REGEX REPLACE "^#define[ \t]+SDL_MIXER_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_MIXER_VERSION_PATCH "${SDL2_MIXER_VERSION_PATCH_LINE}")
|
||||||
|
set(SDL2_MIXER_VERSION_STRING ${SDL2_MIXER_VERSION_MAJOR}.${SDL2_MIXER_VERSION_MINOR}.${SDL2_MIXER_VERSION_PATCH})
|
||||||
|
unset(SDL2_MIXER_VERSION_MAJOR_LINE)
|
||||||
|
unset(SDL2_MIXER_VERSION_MINOR_LINE)
|
||||||
|
unset(SDL2_MIXER_VERSION_PATCH_LINE)
|
||||||
|
unset(SDL2_MIXER_VERSION_MAJOR)
|
||||||
|
unset(SDL2_MIXER_VERSION_MINOR)
|
||||||
|
unset(SDL2_MIXER_VERSION_PATCH)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(SDL2_MIXER_LIBRARIES ${SDL2_MIXER_LIBRARY})
|
||||||
|
set(SDL2_MIXER_INCLUDE_DIRS ${SDL2_MIXER_INCLUDE_DIR})
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
|
||||||
|
FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2_mixer
|
||||||
|
REQUIRED_VARS SDL2_MIXER_LIBRARIES SDL2_MIXER_INCLUDE_DIRS
|
||||||
|
VERSION_VAR SDL2_MIXER_VERSION_STRING)
|
||||||
|
|
||||||
|
# for backward compatibility
|
||||||
|
set(SDLMIXER_LIBRARY ${SDL2_MIXER_LIBRARIES})
|
||||||
|
set(SDLMIXER_INCLUDE_DIR ${SDL2_MIXER_INCLUDE_DIRS})
|
||||||
|
set(SDLMIXER_FOUND ${SDL2_MIXER_FOUND})
|
||||||
|
|
||||||
|
mark_as_advanced(SDL2_MIXER_LIBRARY SDL2_MIXER_INCLUDE_DIR)
|
||||||
61
CMakeSettings.json
Normal file
61
CMakeSettings.json
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "x64-Debug",
|
||||||
|
"generator": "Ninja",
|
||||||
|
"configurationType": "Debug",
|
||||||
|
"inheritEnvironments": [ "msvc_x64_x64" ],
|
||||||
|
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||||
|
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||||
|
"cmakeCommandArgs": "",
|
||||||
|
"buildCommandArgs": "",
|
||||||
|
"ctestCommandArgs": "",
|
||||||
|
"addressSanitizerEnabled": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "x86-Debug",
|
||||||
|
"generator": "Ninja",
|
||||||
|
"configurationType": "Debug",
|
||||||
|
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||||
|
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||||
|
"cmakeCommandArgs": "",
|
||||||
|
"buildCommandArgs": "",
|
||||||
|
"ctestCommandArgs": "",
|
||||||
|
"inheritEnvironments": [ "msvc_x86" ],
|
||||||
|
"addressSanitizerEnabled": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "x86-Release",
|
||||||
|
"generator": "Ninja",
|
||||||
|
"configurationType": "Release",
|
||||||
|
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||||
|
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||||
|
"cmakeCommandArgs": "-DCMAKE_WIN32_EXECUTABLE:BOOL=1",
|
||||||
|
"buildCommandArgs": "",
|
||||||
|
"ctestCommandArgs": "",
|
||||||
|
"inheritEnvironments": [ "msvc_x86" ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "x64-Release",
|
||||||
|
"generator": "Ninja",
|
||||||
|
"configurationType": "Release",
|
||||||
|
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||||
|
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||||
|
"cmakeCommandArgs": "-DCMAKE_WIN32_EXECUTABLE:BOOL=1",
|
||||||
|
"buildCommandArgs": "",
|
||||||
|
"ctestCommandArgs": "",
|
||||||
|
"inheritEnvironments": [ "msvc_x64_x64" ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "x86-Release-WinXP",
|
||||||
|
"generator": "Visual Studio 16 2019",
|
||||||
|
"configurationType": "Release",
|
||||||
|
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||||
|
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||||
|
"cmakeCommandArgs": "-DCMAKE_WIN32_EXECUTABLE:BOOL=1 -T v141_xp",
|
||||||
|
"buildCommandArgs": "",
|
||||||
|
"ctestCommandArgs": "",
|
||||||
|
"inheritEnvironments": [ "msvc_x86" ]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
11
CONTRIBUTING.md
Normal file
11
CONTRIBUTING.md
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# Issues
|
||||||
|
Don’t forget to mention game version, which release or branch it came from.\
|
||||||
|
Source port issues are handled in their respective repositories.
|
||||||
|
|
||||||
|
# Pull request
|
||||||
|
No source ports in main repository.\
|
||||||
|
I have no way to test and maintain most of them.\
|
||||||
|
The best I can do is to add a link.
|
||||||
|
|
||||||
|
There is no guaranty that any particular PR will be accepted.\
|
||||||
|
If you are unsure, ask first, make PR second.
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
rc /Fo.\DrMem\SpaceCadetPinball.res ".\SpaceCadetPinball\SpaceCadetPinball.rc"
|
|
||||||
|
|
||||||
cl /Zi /MT /MP /EHsc /O /Ob0 /cgthreads4 /Fo.\DrMem\ /Fe.\DrMem\myapp.exe ".\SpaceCadetPinball\*.cpp" Comctl32.lib Winmm.lib Htmlhelp.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ".\DrMem\SpaceCadetPinball.res"
|
|
||||||
108
README.md
108
README.md
@@ -1,39 +1,91 @@
|
|||||||
|
<!-- markdownlint-disable-file MD033 -->
|
||||||
|
|
||||||
# SpaceCadetPinball
|
# SpaceCadetPinball
|
||||||
**Summary:** Reverse engineering of `3D Pinball for Windows – Space Cadet`, a game bundled with Windows.
|
|
||||||
|
|
||||||
**How to play:** Place compiled exe into a folder containing original game resources (not included).\
|
## Summary
|
||||||
|
|
||||||
|
Reverse engineering of `3D Pinball for Windows – Space Cadet`, a game bundled with Windows.
|
||||||
|
|
||||||
|
## How to play
|
||||||
|
|
||||||
|
Place compiled executable into a folder containing original game resources (not included).\
|
||||||
Supports data files from Windows and Full Tilt versions of the game.
|
Supports data files from Windows and Full Tilt versions of the game.
|
||||||
\
|
|
||||||
\
|
|
||||||
\
|
|
||||||
\
|
|
||||||
\
|
|
||||||
\
|
|
||||||
**Source:**
|
|
||||||
* `pinball.exe` from `Windows XP` (SHA-1 `2A5B525E0F631BB6107639E2A69DF15986FB0D05`) and its public PDB
|
|
||||||
* `CADET.EXE` 32bit version from `Full Tilt! Pinball` (SHA-1 `3F7B5699074B83FD713657CD94671F2156DBEDC4`)
|
|
||||||
|
|
||||||
**Tools used:** `Ghidra`, `Ida`, `Visual Studio`
|
## Known source ports
|
||||||
|
|
||||||
**What was done:**
|
| Platform | Author | URL |
|
||||||
* All structures were populated, globals and locals named.
|
| ------------------ | --------------- | ---------------------------------------------------------------------------------------------------------- |
|
||||||
* All subs were decompiled, C pseudo code was converted to compilable C++. Loose (namespace?) subs were assigned to classes.
|
| PS Vita | Axiom | <https://github.com/suicvne/SpaceCadetPinball_Vita> |
|
||||||
|
| Emscripten | alula | <https://github.com/alula/SpaceCadetPinball> <br> Play online: <https://alula.github.io/SpaceCadetPinball> |
|
||||||
|
| Nintendo Switch | averne | <https://github.com/averne/SpaceCadetPinball-NX> |
|
||||||
|
| webOS TV | mariotaku | <https://github.com/webosbrew/SpaceCadetPinball> |
|
||||||
|
| Android (WIP) | Iscle | https://github.com/Iscle/SpaceCadetPinball |
|
||||||
|
| Nintendo Wii | MaikelChan | https://github.com/MaikelChan/SpaceCadetPinball |
|
||||||
|
| Nintendo 3DS | MaikelChan | https://github.com/MaikelChan/SpaceCadetPinball/tree/3ds |
|
||||||
|
| Nintendo Wii U | IntriguingTiles | https://github.com/IntriguingTiles/SpaceCadetPinball-WiiU |
|
||||||
|
|
||||||
**Compiling:**\
|
Platforms covered by this project: desktop Windows, Linux and macOS.
|
||||||
Project uses `C++11` features and depends on Windows libs.\
|
|
||||||
Compile with Visual Studio; tested with 2017 and 2019.
|
|
||||||
|
|
||||||
**Plans:**
|
<br>
|
||||||
* ~~Decompile original game~~
|
<br>
|
||||||
* ~~Resizable window, scaled graphics~~
|
<br>
|
||||||
* ~~Loader for high-res sprites from CADET.DAT~~
|
<br>
|
||||||
* ~~Cross-platform port using SDL2, SDL2_mixer, ImGui~~
|
<br>
|
||||||
* Text translations
|
<br>
|
||||||
* Misc features of Full Tilt: 3 music tracks, multiball, centered textboxes, etc.
|
|
||||||
* Maybe x2: support for other two tables
|
## Source
|
||||||
* Table specific BL (control interactions and missions) is hardcoded, othere parts might be also patched
|
|
||||||
|
* `pinball.exe` from `Windows XP` (SHA-1 `2A5B525E0F631BB6107639E2A69DF15986FB0D05`) and its public PDB
|
||||||
|
* `CADET.EXE` 32bit version from `Full Tilt! Pinball` (SHA-1 `3F7B5699074B83FD713657CD94671F2156DBEDC4`)
|
||||||
|
|
||||||
|
## Tools used
|
||||||
|
|
||||||
|
`Ghidra`, `Ida`, `Visual Studio`
|
||||||
|
|
||||||
|
## What was done
|
||||||
|
|
||||||
|
* All structures were populated, globals and locals named.
|
||||||
|
* All subs were decompiled, C pseudo code was converted to compilable C++. Loose (namespace?) subs were assigned to classes.
|
||||||
|
|
||||||
|
## Compiling
|
||||||
|
|
||||||
|
Project uses `C++11` and depends on `SDL2` libs.
|
||||||
|
|
||||||
|
### On Windows
|
||||||
|
|
||||||
|
Download and unpack devel packages for `SDL2` and `SDL2_mixer`.\
|
||||||
|
Set paths to them in `CMakeLists.txt`, see suggested placement in `/Libs`.\
|
||||||
|
Compile with Visual Studio; tested with 2019.
|
||||||
|
|
||||||
|
### On Linux
|
||||||
|
|
||||||
|
Install devel packages for `SDL2` and `SDL2_mixer`.\
|
||||||
|
Compile with CMake; tested with GCC 10, Clang 11.\
|
||||||
|
To cross-compile for Windows, install a 64-bit version of mingw and its `SDL2` and `SDL2_mixer` distributions, then use the `mingwcc.cmake` toolchain.
|
||||||
|
|
||||||
|
### On macOS
|
||||||
|
|
||||||
|
* **Homebrew**: Install the `SDL2`, `SDL2_mixer` homebrew packages.
|
||||||
|
* **MacPorts**: Install the `libSDL2`, `libSDL2_mixer` macports packages.
|
||||||
|
|
||||||
|
Compile with CMake. Ensure that `CMAKE_OSX_ARCHITECTURES` variable is set for either `x86_64` Apple Intel or `arm64` for Apple Silicon.
|
||||||
|
|
||||||
|
Tested with: macOS Big Sur (Intel) with Xcode 13 & macOS Montery Beta (Apple Silicon) with Xcode 13.
|
||||||
|
|
||||||
|
## Plans
|
||||||
|
|
||||||
|
* ~~Decompile original game~~
|
||||||
|
* ~~Resizable window, scaled graphics~~
|
||||||
|
* ~~Loader for high-res sprites from CADET.DAT~~
|
||||||
|
* ~~Cross-platform port using SDL2, SDL2_mixer, ImGui~~
|
||||||
|
* Misc features of Full Tilt: 3 music tracks, multiball, centered textboxes, etc.
|
||||||
|
* Maybe: Text translations
|
||||||
|
* Maybe: Android port
|
||||||
|
* Maybe x2: support for other two tables
|
||||||
|
* Table specific BL (control interactions and missions) is hardcoded, othere parts might be also patched
|
||||||
|
|
||||||
|
## On 64-bit bug that killed the game
|
||||||
|
|
||||||
**On 64-bit bug that killed the game:**\
|
|
||||||
I did not find it, decompiled game worked in x64 mode on the first try.\
|
I did not find it, decompiled game worked in x64 mode on the first try.\
|
||||||
It was either lost in decompilation or introduced in x64 port/not present in x86 build.\
|
It was either lost in decompilation or introduced in x64 port/not present in x86 build.\
|
||||||
Based on public description of the bug (no ball collision), I guess that the bug was in `TEdgeManager::TestGridBox`
|
Based on public description of the bug (no ball collision), I guess that the bug was in `TEdgeManager::TestGridBox`
|
||||||
|
|||||||
@@ -1,55 +0,0 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
|
||||||
# Visual Studio Version 16
|
|
||||||
VisualStudioVersion = 16.0.31624.102
|
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SpaceCadetPinball", "SpaceCadetPinball\SpaceCadetPinball.vcxproj", "{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}"
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
||||||
Debug|ARM = Debug|ARM
|
|
||||||
Debug|ARM64 = Debug|ARM64
|
|
||||||
Debug|x64 = Debug|x64
|
|
||||||
Debug|x86 = Debug|x86
|
|
||||||
Release|ARM = Release|ARM
|
|
||||||
Release|ARM64 = Release|ARM64
|
|
||||||
Release|x64 = Release|x64
|
|
||||||
Release|x86 = Release|x86
|
|
||||||
ReleaseWinXp|ARM = ReleaseWinXp|ARM
|
|
||||||
ReleaseWinXp|ARM64 = ReleaseWinXp|ARM64
|
|
||||||
ReleaseWinXp|x64 = ReleaseWinXp|x64
|
|
||||||
ReleaseWinXp|x86 = ReleaseWinXp|x86
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
||||||
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Debug|ARM.ActiveCfg = Debug|ARM
|
|
||||||
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Debug|ARM.Build.0 = Debug|ARM
|
|
||||||
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
|
||||||
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Debug|ARM64.Build.0 = Debug|ARM64
|
|
||||||
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Debug|x86.ActiveCfg = Debug|Win32
|
|
||||||
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Debug|x86.Build.0 = Debug|Win32
|
|
||||||
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Release|ARM.ActiveCfg = Release|ARM
|
|
||||||
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Release|ARM.Build.0 = Release|ARM
|
|
||||||
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Release|ARM64.ActiveCfg = Release|ARM64
|
|
||||||
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Release|ARM64.Build.0 = Release|ARM64
|
|
||||||
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Release|x64.Build.0 = Release|x64
|
|
||||||
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Release|x86.ActiveCfg = Release|Win32
|
|
||||||
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Release|x86.Build.0 = Release|Win32
|
|
||||||
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.ReleaseWinXp|ARM.ActiveCfg = ReleaseWinXp|ARM
|
|
||||||
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.ReleaseWinXp|ARM.Build.0 = ReleaseWinXp|ARM
|
|
||||||
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.ReleaseWinXp|ARM64.ActiveCfg = ReleaseWinXp|ARM64
|
|
||||||
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.ReleaseWinXp|ARM64.Build.0 = ReleaseWinXp|ARM64
|
|
||||||
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.ReleaseWinXp|x64.ActiveCfg = ReleaseWinXp|x64
|
|
||||||
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.ReleaseWinXp|x64.Build.0 = ReleaseWinXp|x64
|
|
||||||
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.ReleaseWinXp|x86.ActiveCfg = ReleaseWinXp|Win32
|
|
||||||
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.ReleaseWinXp|x86.Build.0 = ReleaseWinXp|Win32
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
|
||||||
HideSolutionNode = FALSE
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
|
||||||
SolutionGuid = {4B620E0B-FD42-4AEC-BC4A-261C1669A1B5}
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
||||||
46
SpaceCadetPinball/EmbeddedData.cpp
Normal file
46
SpaceCadetPinball/EmbeddedData.cpp
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
#include "EmbeddedData.h"
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
// File: './PB_MSGFT.bin' (21702 bytes)
|
||||||
|
// Exported using binary_to_compressed_c.cpp
|
||||||
|
const char EmbeddedData::PB_MSGFT_bin_compressed_data_base85[5380 + 1] =
|
||||||
|
"7])#######>s+cc'/###Y[fi'.Y`+V*KI@%CtjT%QRR8%D[eW$G$^m&MQ>3'QK#n&FnJm&Vp:0(SWPN'SgYn&E09q%`sYn&V9B6&Z#dn&Hnj5&8uhV$Q?p2'L0K6&;@@<$SA`.2EIes$"
|
||||||
|
"RTp6&A.MZ#?@R8%]IN:-42$4CT5(a4`%5DN$rJfLe7^-#`cb*&]u#K262Q_/CR*a4qTjjMHug;-PgRfM-sJfL9#?9RqM>=-/WDa->?1I$[R/qLuqJfLxj/gLPCg;-r28r7H-ge$wKiWh"
|
||||||
|
"vR.(8.C@lL/<T4MnLT_-VeJe?G-Cx9BEwcMYV$2Mbo4VMm4`;-#K5p%o-L&#*rE2C]x+@'aY.FRpjot7kXjJ2'CDiL)e./M^c'hM2s@/M):*NMt3*NM[i,aOcHLaP7?K4MI1$##0ucDN"
|
||||||
|
")J7FN7^e*N4s(eMcPi+8VZKd4^dTd%_IAgWJCSrL>r&gL-0pKN?lgwL[BCTM5>UkL]`kgMw3US->aDY$,oF	&j-HA3nw'/%=2C:FW'8..w-$ae`n*a2Kwp:(t-$X<8w^V`w_/*TKs-"
|
||||||
|
";c>]OW>pgLSHJ_%=0[GMZMFgMmZGhN>4ZtMsg&gL%o^wL)<N;-`2<r&6lNh#2dNgL8]&,Mdj/,MmM&jL5/K;-Na+p7*O(C&4*'a4exMQ(*k2b$k9Em8W.=2C.bIgj-e$AOZ$Qt$u-d,M"
|
||||||
|
"]mC#8rKXk4^eFX(_4+X_xDe'&+rVF7o)I&#.@T(/D85gj;aIqe9[?29#RGf$ZG^;%(/lJ2A/#dM-,r]$m4qP8.biQj_A5W-m'14+m[(Rs6]f>e6#%'Qg@c(NAvYT%Lc68%WcU4+%pwTM"
|
||||||
|
"3nf8RF:g1We=0W$c%q44SR%UM(nj-$_')B6-&R]4vlm*Mw7gV-1?=$g1cap9>;)6Ms=UkL8L)^%Q`1IN,Dn]-ICHh,flTq)s?[o#Ov1b91_ZGMW($a$Xl1s)?ESw.`EqS-n5TW&goD*8"
|
||||||
|
"9[o?9r3R4$LjYI8n2?2CNT3hc)N:(&%6l'&fDxGMi1$##2j(/NMxGp79r*C9Y&o8Bdh8x0fbMmLkv^)&qwuND;t#hO?mxC%*vbJ2jlW*I2.=2C3[;dMtk?m%Z-'TR[u,JWj>Lh$'j#n8"
|
||||||
|
"`=ujDCQ@J&GeJR9Dfd--eIi,i(]^@%71pauR?VIM)NiIMa6`;-2][N'=,HXCh4`/:lwLG'7i=k#C[-L,$oi/:XaAQ(por''<3,d;kRF&#,56vPnbR'M13oj%nSZEcXG:@-/g#pL;2669"
|
||||||
|
"4WIvRsv]O&LwQHM3l_;-TD[V9R;5r)j4<?[Kc_x&7b4H;fVdX1FIuwTDTIgs<:#-M[lk0MGiF58<P(C&?/%*<[x7RNPrJ&#dOl63[bR5'U62HO&ANf%qvedMHdfZMdL?.'1>NE5:t4X8"
|
||||||
|
"^/l3+Z#_K:7,G$IR.V^)E]JF%wY'q7o&Xt&mV(J;ptLQ(v>Y1'xwvq72F?T0EdRf&=$Rd=oNOg$&;mVQjQn?Gq['dk>IY)NJ27BO`<G-&$JZQ8jbGmU#/a+&vh-'v.xJk$C7+E<^V?hG"
|
||||||
|
"dew$I?##@&3+G&#v5'q7jXFuDb7t?wctq)Z&'U4ZeMT2Vb8.M>r)aF749_4Y_-11jv7U-W&H9n7mL.iL;-o_)+O08)>&=]4^Z`K[r7t9#f$^t7j91r,QqSILQ89aTx9/p/hLX%co7"
|
||||||
|
"rr;p&6*Mb%a,#?POJri%XKxI4A.Eu$ZArt8`97r72T):2X[x&=8GWX(l0^&=3SaJ2R6Q&#a;;6&*]iO9q;H*5?rMY$V)9O$<,Dh:trF_JNx&?>0dY,.h5*g$BC5v([3p6EJs#t&_DIu%"
|
||||||
|
"l5A@':GuP8BD[`&V'/W-hs+^ZrT<j&AC1O+c3Ke=)pul&a)i#>2qF&#t`V^=mb3dXkx/W&WCCgLV8UM9ew4oh;#Bgh;Kas-#`?Q8]JeKul^]m8ctB6X%1fN^#qR<^LFPa*vp(?>?Lc'&"
|
||||||
|
"?Swa<=Mc'&U2u`4w080:h%dm:draZ%U_%?P1_W3M#>w.%?Pm7$)N?@-`bPl$uQh'&]ZDA>fa(4Dq#1a)+a;i#I;[#>G27w%l0=S,=%h)&D=57*dR6@.[?kc%Ia(E<#kPFYb/3M2#D*F."
|
||||||
|
"i<,UVYB<ia.(o(#iDbJ2%+/L,+m[&#[8=L3'_aNMms7jLn'j*OHi`k=k=Uk+rJbJ2)]=Z>oe)vS2.Kg%QRJ^?UbmC?c67l)rTjj&]1lgLNih`<Rbh&?S^3k<?&2Oblx^r9TXQhM.evhL"
|
||||||
|
"rbxh<x;tB8EL]BH;':Q:h6IHF.r]K%CaKH=G8lwM&M9%%W>^q)[T%AOPFJZ$YMg58He`q2I6w:@,[F&#YJ7#:s8fdMM_%Z>]8M'S/8D_6.;jbMa.h1&`d8m8@C-tJ]6^w'6kv;]cdTD&"
|
||||||
|
"gv7*P`Bbc%9*l8KZ@,6;n<nw'QqnP']22*<q>)F7K.4e;/6F2aYML@--;ZT%Z-DIm`KJ<-?22$Xp&Z7@AK@kX;-FQ85ohKaa.k<9wi4ed]XJQ(d@sv7f3i/<]gMeMk+V'F>]ZYo)kMB%"
|
||||||
|
"P^mkie1Fp=Q]2U2i$a#P;.r.*QD>Q8?Wi[(fp.M$s$&(SdVJT@bq):i/2u-MQ;6L-TV,<-9K$n:glR0<,k<nL4%3JNRXr2%K25O4Vs]E-27Dt--D5LMup+x9[R=5r4uMV8-T_Lj,%$t&"
|
||||||
|
"1N'q#Dju#[HMGp'2G2e#MB;*Qg1rAM:Mxp^Ws:o^Z'?/CWD;,`ZBMH-abHQ%@STBoJpaN3l)P*<T$l?KFeR5'+8>3B&ZaJ2fMhG;HY:_A9TAdM3qB#>B?C[I>Y2m&NIb#>[haJ2@5('O"
|
||||||
|
"^o8V%qfQ^?FtjW;2,j;9RD&e@hg_$'e59U)b=;s%2Q_698exI.DM5Kji033&f]fEW5@a$>aV`sBWbm-NOg9[%u<Wm8HNR[@J$_g%eKan:#>%K;/c`'6)RC`N'AeA-ow,=&k_3TRfnxv$"
|
||||||
|
"n()<-0klw$aeIjMB*;.&@&fJ.DUo,;H(6+Y9N[mfE^A0:^IRqL@PD6MxZN$'.21q7#<fR3`9<dMD+'k$FluDN7oto&J$s58,1?j<Bj8$&pVXmA?N,F>3NoIDf3l3+Q5#Q8erke#?2tHW"
|
||||||
|
"9xMY$Qtr&OfkCX%nou#PV:8Z$i1dm8,%(@0n*7EH5=+nMk`rS@It$@'M9XCf(DSgWZf=k%dZ<aNj4XC,b(jL3BUu)N/K8_%9j#3%MUE1M[ks@<^f/w%@wYL%+Qv-$EdOam:DvP&Kf)F7"
|
||||||
|
"f<0j(OX1=?V7EI-i,]mAUl>QqYTc<%Q4_$f`-<iM#=Sc;7W9XqO=_,M(BbP<;,.@'Q>1n85X?hGidK_mlK8f$Lt@KCDihv@C^Hn:dLDc##bp_-Q[J;gcdAh:8_2cYtoL/;=tq$'^XRvR"
|
||||||
|
"@B`/9Lu%=BWKR3<:kRvRFbG-&BU+a<41bJ2e[SoUAjo?MX'-a&&R[k4C4A_8_RrS&t25394Xk,k(XDY&.Svj9176e4'8]u%&.(B@pM?.%,ABgLs[1]$$SF&#NfBdMmp$>+LqZdM.ih;-"
|
||||||
|
"ba1Q*noHj<w8_@'eBDE)uMSi$v0t3MM/%4C(b1;0&VaBDth'HkAb,e)u^&4+M.^:^wrD''=Lh4++Qt[nS17Y'IGu58=v&EYlE<R%KW;R<'w:Z>R=iJs?0@Y)=%&3MHXWn891[w'@aop7"
|
||||||
|
"JUx>._mko&:V6j9BY%`?=TA?&erCj9OTF&#xR7p&Il:Q8B>u`4]/g;-L=hRAS,=LsLISn&w1aZ@&*9,(lv]Gu)#)f;M4.`AK?`<?2cu/*H0e-7/OO[7aVA/&f%YKN]XV5FNCS8:2tV#&"
|
||||||
|
"HkekL:VL;-t]`t%ax_N9F$w.O$$1<(okXQV?qll$oXwZPsa`a'<rLu]V9(X%BDfcZ+u4)'WNIM$8saH=JU^gLo3Wb$1x9HV-FRjP?hDG-MQ/f-Pr6<-6;c`%-b'9Rtj*CO>i>9'KZ_h#"
|
||||||
|
"^96>DuNT@-1XurCV<@`&oe6N;n##?-eGVD&ftt?0=4vV%^>WAJF%3q%k>k(7Q+x4ARL:a4auH6Mg3%4CGo5mACC$=12^0^#DOUV-8)xZgO=1eZ2e+d;J6G]:lRpX'=)I6TBV+@(Q2r,;"
|
||||||
|
"bwgtoAeYd&TrtGM2T6i$dn;m8:[o(m+?B4&bnsG;DT^_I-l9n$.^d7+_^wGMrnXo&0D]gUfQGNA4`FaIZ>wIf#.q0Ii&i1s`FCAR]ea+h`(x#%#AL'U=R;<t7/97Y^=W<6pgm?33&"
|
||||||
|
"EN[v>B=Wac>bpg%'I49R=,.78DdN)Y1D[A-cCULM&<;Y&qs<NBdmuR_(7emL9*-M;7CYn*eNU`-%sd&''>Rg:@6q=8e(sP:YG,iLf,jlJh&s22](6=*bX]a<UuO&#V.g:CFq<<:_DT;'"
|
||||||
|
"E%dgL`3.s-2mZo@>Fu`4jmlsHvJ]c5,kAY'hgE&OEpvw&A@^B'%;Xk#=3`2;0n`=g/K(w'Zok,M82^m@`:bH=>6r`$p.0QJ;#qDlbS;s?OP5'Z.a%G=NsX0NUQ1X%7Bbm8-<T*YrC3)="
|
||||||
|
"9whv@Avo*E,VNC7+eIm%M4k#>Kdgtq,WOvYaNWhZMOH##TWvNb@(%9rSllV$+^8I%OuBv$`)bJ2UiCQ8gjo6*uS)`%-`W/%?)c;-d&?s%GWRh*@O/w7=$O#Rix,`%`a=&FC6$XLYxDH;"
|
||||||
|
"Y5=2C`Fws7Bhki$MJ$-++`_8RWmU9R$ui$G;6Na,I8g$&g5<NKm=mQqg/mW%5e7QAG+gVgal^)O-iT`$h1?qtQq,KlOeMo>x9f$nwTWJ']jk=-3^^m2vZ8@(#O,W8$Gj9DZRV49/J=P;"
|
||||||
|
"``a;&#pbJ28k)e<?_`xfPn;J:H@xNOWj9hjtlH.'lq8-;L&4TBpL0@%49Tp7SRqw.Rfu<'^<FK:ll)FPwl'LMBIDJD/uwd;%V6XA1<.G:-IbQ)=HJv&ZF--M3v[O.m_=p^)A6wJGUn@'"
|
||||||
|
"SK``-)or4#NImdM.O?a$`nOE<Y0:+?v=PkLN34S2T=B<H=k[1E&8,c'whm;-[f*$%_7MaNZg*`+-jD4:XW_c/Y2nZ>AA`/s+j&BH>:oB&&g1<-N:md$bSYm8#u^7).4H0&q3n0#B[G&#"
|
||||||
|
"%baa*`3t,;Nm>v]^JtC(mC:/%*WN7:aarL7;f[=-XbnHbSm`I&Z?ap7[pZ@1dIa:8FZkL:p,kRM^$lf%92@v&mCeA-XHFK&t/c9BBP)CZSu>*(]G8l#>aD<okffx2c@-c*EUkE<_`fG5"
|
||||||
|
"8Wjb:XgxcPEcZ6)8q&_S/]^GMZr6Tg?oOb*i^qpIUDGn(<UI@ZPbm##S%o,;V^8U)_.idDhTF&##h$<?'s-+6W@-C?k+kx'_MuAO;3r2'NH0K:(._r(PCZY#Ij[1$:j61U$h,A-av4A="
|
||||||
|
"W)Y?e>L'k$XRf2Nn-8V8*lb`69FF3N@uNe+.AYXS9ALPSV/-Y$<H=n/4####";
|
||||||
|
#endif
|
||||||
8
SpaceCadetPinball/EmbeddedData.h
Normal file
8
SpaceCadetPinball/EmbeddedData.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
class EmbeddedData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static const char PB_MSGFT_bin_compressed_data_base85[5380 + 1];
|
||||||
|
};
|
||||||
362
SpaceCadetPinball/GroupData.cpp
Normal file
362
SpaceCadetPinball/GroupData.cpp
Normal file
@@ -0,0 +1,362 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
|
||||||
|
#include "GroupData.h"
|
||||||
|
|
||||||
|
#include "EmbeddedData.h"
|
||||||
|
#include "fullscrn.h"
|
||||||
|
#include "gdrv.h"
|
||||||
|
#include "pb.h"
|
||||||
|
#include "pinball.h"
|
||||||
|
#include "zdrv.h"
|
||||||
|
|
||||||
|
|
||||||
|
EntryData::~EntryData()
|
||||||
|
{
|
||||||
|
if (Buffer)
|
||||||
|
{
|
||||||
|
if (EntryType == FieldTypes::Bitmap8bit)
|
||||||
|
{
|
||||||
|
delete reinterpret_cast<gdrv_bitmap8*>(Buffer);
|
||||||
|
}
|
||||||
|
else if (EntryType == FieldTypes::Bitmap16bit)
|
||||||
|
{
|
||||||
|
delete reinterpret_cast<zmap_header_type*>(Buffer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
delete[] Buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GroupData::GroupData(int groupId)
|
||||||
|
{
|
||||||
|
GroupId = groupId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroupData::AddEntry(EntryData* entry)
|
||||||
|
{
|
||||||
|
auto addEntry = true;
|
||||||
|
switch (entry->EntryType)
|
||||||
|
{
|
||||||
|
case FieldTypes::GroupName:
|
||||||
|
GroupName = entry->Buffer;
|
||||||
|
break;
|
||||||
|
case FieldTypes::Bitmap8bit:
|
||||||
|
{
|
||||||
|
auto srcBmp = reinterpret_cast<gdrv_bitmap8*>(entry->Buffer);
|
||||||
|
if (srcBmp->BitmapType == BitmapTypes::Spliced)
|
||||||
|
{
|
||||||
|
// Get rid of spliced bitmap early on, to simplify render pipeline
|
||||||
|
auto bmp = new gdrv_bitmap8(srcBmp->Width, srcBmp->Height, srcBmp->Width);
|
||||||
|
auto zMap = new zmap_header_type(srcBmp->Width, srcBmp->Height, srcBmp->Width);
|
||||||
|
SplitSplicedBitmap(*srcBmp, *bmp, *zMap);
|
||||||
|
|
||||||
|
NeedsSort = true;
|
||||||
|
addEntry = false;
|
||||||
|
AddEntry(new EntryData(FieldTypes::Bitmap8bit, reinterpret_cast<char*>(bmp)));
|
||||||
|
AddEntry(new EntryData(FieldTypes::Bitmap16bit, reinterpret_cast<char*>(zMap)));
|
||||||
|
delete entry;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetBitmap(srcBmp);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FieldTypes::Bitmap16bit:
|
||||||
|
{
|
||||||
|
SetZMap(reinterpret_cast<zmap_header_type*>(entry->Buffer));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addEntry)
|
||||||
|
Entries.push_back(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroupData::FinalizeGroup()
|
||||||
|
{
|
||||||
|
if (NeedsSort)
|
||||||
|
{
|
||||||
|
// Entries within a group are sorted by EntryType, in ascending order.
|
||||||
|
// Dat files follow this rule, zMaps inserted in the middle break it.
|
||||||
|
NeedsSort = false;
|
||||||
|
std::sort(Entries.begin(), Entries.end(), [](const EntryData* lhs, const EntryData* rhs)
|
||||||
|
{
|
||||||
|
return lhs->EntryType < rhs->EntryType;
|
||||||
|
});
|
||||||
|
Entries.shrink_to_fit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gdrv_bitmap8* GroupData::GetBitmap(int resolution) const
|
||||||
|
{
|
||||||
|
return Bitmaps[resolution];
|
||||||
|
}
|
||||||
|
|
||||||
|
zmap_header_type* GroupData::GetZMap(int resolution) const
|
||||||
|
{
|
||||||
|
return ZMaps[resolution];
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroupData::SplitSplicedBitmap(const gdrv_bitmap8& srcBmp, gdrv_bitmap8& bmp, zmap_header_type& zMap)
|
||||||
|
{
|
||||||
|
assertm(srcBmp.BitmapType == BitmapTypes::Spliced, "GroupData: wrong bitmap type");
|
||||||
|
|
||||||
|
std::memset(bmp.IndexedBmpPtr, 0xff, bmp.Stride * bmp.Height);
|
||||||
|
bmp.XPosition = srcBmp.XPosition;
|
||||||
|
bmp.YPosition = srcBmp.YPosition;
|
||||||
|
bmp.Resolution = srcBmp.Resolution;
|
||||||
|
|
||||||
|
zdrv::fill(&zMap, zMap.Width, zMap.Height, 0, 0, 0xFFFF);
|
||||||
|
zMap.Resolution = srcBmp.Resolution;
|
||||||
|
|
||||||
|
auto tableWidth = fullscrn::resolution_array[srcBmp.Resolution].TableWidth;
|
||||||
|
auto src = reinterpret_cast<uint16_t*>(srcBmp.IndexedBmpPtr);
|
||||||
|
auto srcChar = reinterpret_cast<char**>(&src);
|
||||||
|
for (int dstInd = 0;;)
|
||||||
|
{
|
||||||
|
auto stride = static_cast<int16_t>(*src++);
|
||||||
|
if (stride < 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Stride is in terms of dst stride, hardcoded to match vScreen width in current resolution
|
||||||
|
if (stride > bmp.Width)
|
||||||
|
{
|
||||||
|
stride += bmp.Width - tableWidth;
|
||||||
|
assertm(stride >= 0, "Spliced bitmap: negative computed stride");
|
||||||
|
}
|
||||||
|
|
||||||
|
dstInd += stride;
|
||||||
|
for (auto count = *src++; count; count--)
|
||||||
|
{
|
||||||
|
auto depth = *src++;
|
||||||
|
bmp.IndexedBmpPtr[dstInd] = **srcChar;
|
||||||
|
zMap.ZPtr1[dstInd] = depth;
|
||||||
|
|
||||||
|
(*srcChar)++;
|
||||||
|
dstInd++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroupData::SetBitmap(gdrv_bitmap8* bmp)
|
||||||
|
{
|
||||||
|
assertm(Bitmaps[bmp->Resolution] == nullptr, "GroupData: bitmap override");
|
||||||
|
Bitmaps[bmp->Resolution] = bmp;
|
||||||
|
|
||||||
|
auto zMap = ZMaps[bmp->Resolution];
|
||||||
|
if (zMap)
|
||||||
|
{
|
||||||
|
assertm(bmp->Width == zMap->Width && bmp->Height == zMap->Height,
|
||||||
|
"GroupData: mismatched bitmap/zMap dimensions");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroupData::SetZMap(zmap_header_type* zMap)
|
||||||
|
{
|
||||||
|
// Flip zMap to match with flipped non-indexed bitmaps
|
||||||
|
zdrv::FlipZMapHorizontally(*zMap);
|
||||||
|
|
||||||
|
assertm(ZMaps[zMap->Resolution] == nullptr, "GroupData: zMap override");
|
||||||
|
ZMaps[zMap->Resolution] = zMap;
|
||||||
|
|
||||||
|
auto bmp = Bitmaps[zMap->Resolution];
|
||||||
|
if (bmp)
|
||||||
|
{
|
||||||
|
assertm(bmp->Width == zMap->Width && bmp->Height == zMap->Height,
|
||||||
|
"GroupData: mismatched bitmap/zMap dimensions");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DatFile::~DatFile()
|
||||||
|
{
|
||||||
|
for (auto group : Groups)
|
||||||
|
{
|
||||||
|
if (!group)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (const auto entry : group->GetEntries())
|
||||||
|
{
|
||||||
|
delete entry;
|
||||||
|
}
|
||||||
|
delete group;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char* DatFile::field(int groupIndex, FieldTypes targetEntryType)
|
||||||
|
{
|
||||||
|
assertm(targetEntryType != FieldTypes::Bitmap8bit && targetEntryType != FieldTypes::Bitmap16bit,
|
||||||
|
"partman: Use specific get for bitmaps");
|
||||||
|
|
||||||
|
auto group = Groups[groupIndex];
|
||||||
|
for (const auto entry : group->GetEntries())
|
||||||
|
{
|
||||||
|
if (entry->EntryType == targetEntryType)
|
||||||
|
{
|
||||||
|
return entry->Buffer;
|
||||||
|
}
|
||||||
|
if (entry->EntryType > targetEntryType)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char* DatFile::field_nth(int groupIndex, FieldTypes targetEntryType, int skipFirstN)
|
||||||
|
{
|
||||||
|
assertm(targetEntryType != FieldTypes::Bitmap8bit && targetEntryType != FieldTypes::Bitmap16bit,
|
||||||
|
"partman: Use specific get for bitmaps");
|
||||||
|
|
||||||
|
auto group = Groups[groupIndex];
|
||||||
|
auto skipCount = 0;
|
||||||
|
for (const auto entry : group->GetEntries())
|
||||||
|
{
|
||||||
|
if (entry->EntryType > targetEntryType)
|
||||||
|
break;
|
||||||
|
if (entry->EntryType == targetEntryType)
|
||||||
|
if (skipCount++ == skipFirstN)
|
||||||
|
return entry->Buffer;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DatFile::field_size_nth(int groupIndex, FieldTypes targetEntryType, int skipFirstN)
|
||||||
|
{
|
||||||
|
auto group = Groups[groupIndex];
|
||||||
|
auto skipCount = 0;
|
||||||
|
for (const auto entry : group->GetEntries())
|
||||||
|
{
|
||||||
|
if (entry->EntryType > targetEntryType)
|
||||||
|
return 0;
|
||||||
|
if (entry->EntryType == targetEntryType)
|
||||||
|
if (skipCount++ == skipFirstN)
|
||||||
|
return entry->FieldSize;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DatFile::field_size(int groupIndex, FieldTypes targetEntryType)
|
||||||
|
{
|
||||||
|
return field_size_nth(groupIndex, targetEntryType, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int DatFile::record_labeled(LPCSTR targetGroupName)
|
||||||
|
{
|
||||||
|
auto targetLength = strlen(targetGroupName);
|
||||||
|
for (int groupIndex = Groups.size() - 1; groupIndex >= 0; --groupIndex)
|
||||||
|
{
|
||||||
|
auto groupName = field(groupIndex, FieldTypes::GroupName);
|
||||||
|
if (!groupName)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto index = 0u;
|
||||||
|
for (; index < targetLength; index++)
|
||||||
|
if (targetGroupName[index] != groupName[index])
|
||||||
|
break;
|
||||||
|
if (index == targetLength && !targetGroupName[index] && !groupName[index])
|
||||||
|
return groupIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* DatFile::field_labeled(LPCSTR lpString, FieldTypes fieldType)
|
||||||
|
{
|
||||||
|
auto groupIndex = record_labeled(lpString);
|
||||||
|
return groupIndex < 0 ? nullptr : field(groupIndex, fieldType);
|
||||||
|
}
|
||||||
|
|
||||||
|
gdrv_bitmap8* DatFile::GetBitmap(int groupIndex)
|
||||||
|
{
|
||||||
|
auto group = Groups[groupIndex];
|
||||||
|
return group->GetBitmap(fullscrn::GetResolution());
|
||||||
|
}
|
||||||
|
|
||||||
|
zmap_header_type* DatFile::GetZMap(int groupIndex)
|
||||||
|
{
|
||||||
|
auto group = Groups[groupIndex];
|
||||||
|
return group->GetZMap(fullscrn::GetResolution());
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatFile::Finalize()
|
||||||
|
{
|
||||||
|
if (!pb::FullTiltMode)
|
||||||
|
{
|
||||||
|
int groupIndex = record_labeled("pbmsg_ft");
|
||||||
|
assertm(groupIndex < 0, "DatFile: pbmsg_ft is already in .dat");
|
||||||
|
|
||||||
|
// Load 3DPB font into dat to simplify pipeline
|
||||||
|
auto rcData = reinterpret_cast<MsgFont*>(ImFontAtlas::DecompressCompressedBase85Data(
|
||||||
|
EmbeddedData::PB_MSGFT_bin_compressed_data_base85));
|
||||||
|
AddMsgFont(rcData, "pbmsg_ft");
|
||||||
|
IM_FREE(rcData);
|
||||||
|
|
||||||
|
// PINBALL2.MID is an alternative font provided in 3DPB data
|
||||||
|
// Scaled down because it is too large for top text box
|
||||||
|
/*auto file = pinball::make_path_name("PINBALL2.MID");
|
||||||
|
auto fileHandle = fopenu(file.c_str(), "rb");
|
||||||
|
fseek(fileHandle, 0, SEEK_END);
|
||||||
|
auto fileSize = static_cast<uint32_t>(ftell(fileHandle));
|
||||||
|
auto rcData = reinterpret_cast<MsgFont*>(new uint8_t[fileSize]);
|
||||||
|
fseek(fileHandle, 0, SEEK_SET);
|
||||||
|
fread(rcData, 1, fileSize, fileHandle);
|
||||||
|
fclose(fileHandle);
|
||||||
|
auto groupId = Groups.back()->GroupId + 1u;
|
||||||
|
AddMsgFont(rcData, "pbmsg_ft");
|
||||||
|
delete[] rcData;
|
||||||
|
for (auto i = groupId; i < Groups.size(); i++)
|
||||||
|
Groups[i]->GetBitmap(0)->ScaleIndexed(0.84f, 0.84f);*/
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto group : Groups)
|
||||||
|
{
|
||||||
|
group->FinalizeGroup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatFile::AddMsgFont(MsgFont* font, const std::string& fontName)
|
||||||
|
{
|
||||||
|
auto groupId = Groups.back()->GroupId + 1;
|
||||||
|
auto ptrToData = reinterpret_cast<char*>(font->Data);
|
||||||
|
for (auto charInd = 32; charInd < 128; charInd++, groupId++)
|
||||||
|
{
|
||||||
|
auto curChar = reinterpret_cast<MsgFontChar*>(ptrToData);
|
||||||
|
assertm(curChar->Width == font->CharWidths[charInd], "Score: mismatched font width");
|
||||||
|
ptrToData += curChar->Width * font->Height + 1;
|
||||||
|
|
||||||
|
auto bmp = new gdrv_bitmap8(curChar->Width, font->Height, true);
|
||||||
|
auto srcPtr = curChar->Data;
|
||||||
|
auto dstPtr = &bmp->IndexedBmpPtr[bmp->Stride * (bmp->Height - 1)];
|
||||||
|
for (auto y = 0; y < font->Height; ++y)
|
||||||
|
{
|
||||||
|
memcpy(dstPtr, srcPtr, curChar->Width);
|
||||||
|
srcPtr += curChar->Width;
|
||||||
|
dstPtr -= bmp->Stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto group = new GroupData(groupId);
|
||||||
|
group->AddEntry(new EntryData(FieldTypes::Bitmap8bit, reinterpret_cast<char*>(bmp)));
|
||||||
|
if (charInd == 32)
|
||||||
|
{
|
||||||
|
// First font group holds font name and gap width
|
||||||
|
auto groupName = new char[fontName.length() + 1];
|
||||||
|
strcpy(groupName, fontName.c_str());
|
||||||
|
group->AddEntry(new EntryData(FieldTypes::GroupName, groupName));
|
||||||
|
|
||||||
|
auto gaps = new char[2];
|
||||||
|
*reinterpret_cast<int16_t*>(gaps) = font->GapWidth;
|
||||||
|
group->AddEntry(new EntryData(FieldTypes::ShortArray, gaps));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto groupName = new char[30];
|
||||||
|
sprintf(groupName, "char %d='%c'", charInd, charInd);
|
||||||
|
group->AddEntry(new EntryData(FieldTypes::GroupName, groupName));
|
||||||
|
}
|
||||||
|
|
||||||
|
Groups.push_back(group);
|
||||||
|
}
|
||||||
|
}
|
||||||
128
SpaceCadetPinball/GroupData.h
Normal file
128
SpaceCadetPinball/GroupData.h
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct zmap_header_type;
|
||||||
|
struct gdrv_bitmap8;
|
||||||
|
|
||||||
|
|
||||||
|
enum class FieldTypes : int16_t
|
||||||
|
{
|
||||||
|
// One 16 bit signed integer
|
||||||
|
ShortValue = 0,
|
||||||
|
|
||||||
|
// Sprite bitmap, 8bpp, indexed color
|
||||||
|
Bitmap8bit = 1,
|
||||||
|
|
||||||
|
Unknown2 = 2,
|
||||||
|
|
||||||
|
// Group name, char[]. Not all groups have names.
|
||||||
|
GroupName = 3,
|
||||||
|
|
||||||
|
Unknown4 = 4,
|
||||||
|
|
||||||
|
// Palette, contains 256 RBGA 4-byte colors.
|
||||||
|
Palette = 5,
|
||||||
|
|
||||||
|
Unknown6 = 6,
|
||||||
|
|
||||||
|
Unknown7 = 7,
|
||||||
|
|
||||||
|
Unknown8 = 8,
|
||||||
|
|
||||||
|
// String, char[]
|
||||||
|
String = 9,
|
||||||
|
|
||||||
|
// Array of 16 bit signed integers
|
||||||
|
ShortArray = 10,
|
||||||
|
|
||||||
|
// Array of 32 bit floats
|
||||||
|
FloatArray = 11,
|
||||||
|
|
||||||
|
// Sprite depth map, 16bpp, unsigned
|
||||||
|
Bitmap16bit = 12,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EntryData
|
||||||
|
{
|
||||||
|
EntryData() = default;
|
||||||
|
|
||||||
|
EntryData(FieldTypes entryType, char* buffer): EntryType(entryType), FieldSize(-1), Buffer(buffer)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~EntryData();
|
||||||
|
FieldTypes EntryType{};
|
||||||
|
int FieldSize{};
|
||||||
|
char* Buffer{};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
struct MsgFontChar
|
||||||
|
{
|
||||||
|
uint8_t Width;
|
||||||
|
char Data[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MsgFont
|
||||||
|
{
|
||||||
|
int16_t GapWidth;
|
||||||
|
int16_t Unknown1;
|
||||||
|
int16_t Height;
|
||||||
|
uint8_t CharWidths[128];
|
||||||
|
MsgFontChar Data[1];
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
static_assert(sizeof(MsgFont) == 136, "Wrong size of MsgFont");
|
||||||
|
|
||||||
|
|
||||||
|
class GroupData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int GroupId;
|
||||||
|
std::string GroupName;
|
||||||
|
|
||||||
|
GroupData(int groupId);
|
||||||
|
void AddEntry(EntryData* entry);
|
||||||
|
void FinalizeGroup();
|
||||||
|
const std::vector<EntryData*>& GetEntries() const { return Entries; }
|
||||||
|
const EntryData* GetEntry(size_t index) const { return Entries[index]; }
|
||||||
|
size_t EntryCount() const { return Entries.size(); }
|
||||||
|
void ReserveEntries(size_t count) { Entries.reserve(count); }
|
||||||
|
gdrv_bitmap8* GetBitmap(int resolution) const;
|
||||||
|
zmap_header_type* GetZMap(int resolution) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<EntryData*> Entries;
|
||||||
|
gdrv_bitmap8* Bitmaps[3]{};
|
||||||
|
zmap_header_type* ZMaps[3]{};
|
||||||
|
bool NeedsSort = false;
|
||||||
|
|
||||||
|
static void SplitSplicedBitmap(const gdrv_bitmap8& srcBmp, gdrv_bitmap8& bmp, zmap_header_type& zMap);
|
||||||
|
|
||||||
|
void SetBitmap(gdrv_bitmap8* bmp);
|
||||||
|
void SetZMap(zmap_header_type* zMap);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class DatFile
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::string AppName;
|
||||||
|
std::string Description;
|
||||||
|
std::vector<GroupData*> Groups;
|
||||||
|
|
||||||
|
~DatFile();
|
||||||
|
char* field_nth(int groupIndex, FieldTypes targetEntryType, int skipFirstN);
|
||||||
|
char* field(int groupIndex, FieldTypes entryType);
|
||||||
|
int field_size_nth(int groupIndex, FieldTypes targetEntryType, int skipFirstN);
|
||||||
|
int field_size(int groupIndex, FieldTypes targetEntryType);
|
||||||
|
int record_labeled(LPCSTR targetGroupName);
|
||||||
|
char* field_labeled(LPCSTR lpString, FieldTypes fieldType);
|
||||||
|
gdrv_bitmap8* GetBitmap(int groupIndex);
|
||||||
|
zmap_header_type* GetZMap(int groupIndex);
|
||||||
|
void Finalize();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void AddMsgFont(MsgFont* font, const std::string& fontName);
|
||||||
|
};
|
||||||
@@ -1,270 +1,83 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "Sound.h"
|
#include "Sound.h"
|
||||||
|
|
||||||
|
|
||||||
#include "pb.h"
|
|
||||||
#include "pinball.h"
|
|
||||||
#include "WaveMix.h"
|
|
||||||
#include "winmain.h"
|
|
||||||
|
|
||||||
int Sound::num_channels;
|
int Sound::num_channels;
|
||||||
HWND Sound::wavemix_window;
|
bool Sound::enabled_flag = false;
|
||||||
HANDLE Sound::pMem;
|
int* Sound::TimeStamps = nullptr;
|
||||||
unsigned int Sound::enabled_flag;
|
|
||||||
int Sound::channel_time[8];
|
|
||||||
MIXWAVE* Sound::channel_wavePtr[8];
|
|
||||||
void (*Sound::callback_ptr)(int, MIXWAVE*, int);
|
|
||||||
HMODULE Sound::HInstance;
|
|
||||||
|
|
||||||
|
bool Sound::Init(int channels, bool enableFlag)
|
||||||
int Sound::Init(HINSTANCE hInstance, int voices, void (* someFuncPtr)(int, MIXWAVE*, int))
|
|
||||||
{
|
{
|
||||||
WNDCLASSA WndClass;
|
Mix_Init(MIX_INIT_MID_Proxy);
|
||||||
char FileName[300];
|
auto result = Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 1024);
|
||||||
|
SetChannels(channels);
|
||||||
int channelCount = voices;
|
Enable(enableFlag);
|
||||||
if (voices > 8)
|
return !result;
|
||||||
channelCount = 8;
|
|
||||||
num_channels = channelCount;
|
|
||||||
if (wavemix_window || pMem)
|
|
||||||
return 0;
|
|
||||||
enabled_flag = -1;
|
|
||||||
for (int i = 0; i < channelCount; ++i)
|
|
||||||
{
|
|
||||||
channel_time[i] = 0;
|
|
||||||
channel_wavePtr[i] = nullptr;
|
|
||||||
}
|
|
||||||
callback_ptr = someFuncPtr;
|
|
||||||
if (!someFuncPtr)
|
|
||||||
callback_ptr = NullCallback;
|
|
||||||
|
|
||||||
pinball::make_path_name(FileName, "wavemix.inf", 300);
|
|
||||||
FILE* wavemixIniFile = nullptr;
|
|
||||||
fopen_s(&wavemixIniFile, FileName, "r");
|
|
||||||
if (wavemixIniFile)
|
|
||||||
{
|
|
||||||
fclose(wavemixIniFile);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/*FT does not have the file, defaults work OK*/
|
|
||||||
if (!pb::FullTiltMode)
|
|
||||||
MessageBoxW(winmain::hwnd_frame, pinball::get_rc_Wstring(42, 0), L"", 0x2000u);
|
|
||||||
}
|
|
||||||
|
|
||||||
WndClass.style = 0;
|
|
||||||
WndClass.lpfnWndProc = SoundCallBackWndProc;
|
|
||||||
WndClass.cbClsExtra = 0;
|
|
||||||
WndClass.cbWndExtra = 0;
|
|
||||||
WndClass.hInstance = hInstance;
|
|
||||||
WndClass.hIcon = nullptr;
|
|
||||||
WndClass.hCursor = nullptr;
|
|
||||||
WndClass.hbrBackground = nullptr;
|
|
||||||
WndClass.lpszMenuName = nullptr;
|
|
||||||
WndClass.lpszClassName = "WaveMixSoundGuy";
|
|
||||||
RegisterClassA(&WndClass);
|
|
||||||
wavemix_window = CreateWindowExA(
|
|
||||||
0,
|
|
||||||
"WaveMixSoundGuy",
|
|
||||||
nullptr,
|
|
||||||
0x80000000,
|
|
||||||
0x80000000,
|
|
||||||
0,
|
|
||||||
0x80000000,
|
|
||||||
0,
|
|
||||||
nullptr,
|
|
||||||
nullptr,
|
|
||||||
hInstance,
|
|
||||||
nullptr);
|
|
||||||
if (!wavemix_window)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
HInstance = hInstance;
|
|
||||||
HANDLE hMixSession = WaveMix::Init();
|
|
||||||
pMem = hMixSession;
|
|
||||||
if (!hMixSession)
|
|
||||||
return 0;
|
|
||||||
WaveMix::OpenChannel(hMixSession, num_channels, 2u);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sound::Enable(int channelFrom, int channelTo, int enableFlag)
|
void Sound::Enable(bool enableFlag)
|
||||||
{
|
{
|
||||||
if (pMem)
|
enabled_flag = enableFlag;
|
||||||
{
|
if (!enableFlag)
|
||||||
if (channelTo >= num_channels)
|
Mix_HaltChannel(-1);
|
||||||
channelTo = num_channels - 1;
|
|
||||||
|
|
||||||
if (channelFrom >= 0 && channelTo < num_channels)
|
|
||||||
{
|
|
||||||
for (int index = channelFrom; index <= channelTo; ++index)
|
|
||||||
{
|
|
||||||
int channelFlag = 1 << index;
|
|
||||||
if (enableFlag)
|
|
||||||
{
|
|
||||||
enabled_flag |= channelFlag;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
enabled_flag &= ~channelFlag;
|
|
||||||
Flush(index, index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Sound::Idle()
|
|
||||||
{
|
|
||||||
if (pMem)
|
|
||||||
WaveMix::Pump();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sound::Activate()
|
void Sound::Activate()
|
||||||
{
|
{
|
||||||
if (pMem)
|
Mix_Resume(-1);
|
||||||
WaveMix::Activate(pMem, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sound::Deactivate()
|
void Sound::Deactivate()
|
||||||
{
|
{
|
||||||
if (pMem)
|
Mix_Pause(-1);
|
||||||
WaveMix::Activate(pMem, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sound::Close()
|
void Sound::Close()
|
||||||
{
|
{
|
||||||
if (wavemix_window)
|
delete[] TimeStamps;
|
||||||
{
|
TimeStamps = nullptr;
|
||||||
DestroyWindow(wavemix_window);
|
Mix_CloseAudio();
|
||||||
wavemix_window = nullptr;
|
Mix_Quit();
|
||||||
}
|
|
||||||
if (pMem)
|
|
||||||
{
|
|
||||||
WaveMix::CloseChannel(pMem, 0, 1);
|
|
||||||
WaveMix::CloseSession(pMem);
|
|
||||||
pMem = nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sound::PlaySound(MIXWAVE* wavePtr, int minChannel, int maxChannel, unsigned int dwFlags, int16_t loops)
|
void Sound::PlaySound(Mix_Chunk* wavePtr, int time)
|
||||||
{
|
{
|
||||||
MIXPLAYPARAMS mixParams{};
|
if (wavePtr && enabled_flag)
|
||||||
|
|
||||||
if (!pMem)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (maxChannel >= num_channels)
|
|
||||||
maxChannel = num_channels - 1;
|
|
||||||
if (!wavePtr || minChannel < 0 || maxChannel >= num_channels)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if ((dwFlags & 0x8000) != 0 && num_channels > 0)
|
|
||||||
{
|
{
|
||||||
int index2 = 0;
|
if (Mix_Playing(-1) == num_channels)
|
||||||
bool ok = false;
|
|
||||||
while (channel_wavePtr[index2] != wavePtr)
|
|
||||||
{
|
{
|
||||||
if (++index2 >= num_channels)
|
auto oldestChannel = std::min_element(TimeStamps, TimeStamps + num_channels) - TimeStamps;
|
||||||
{
|
Mix_HaltChannel(oldestChannel);
|
||||||
ok = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (!ok)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
auto channel = Mix_PlayChannel(-1, wavePtr, 0);
|
||||||
int playChannel = minChannel;
|
if (channel != -1)
|
||||||
if (minChannel < maxChannel)
|
TimeStamps[channel] = time;
|
||||||
{
|
|
||||||
int curChannel = minChannel;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
++curChannel;
|
|
||||||
if ((1 << curChannel) & enabled_flag &&
|
|
||||||
channel_time[curChannel] < channel_time[playChannel])
|
|
||||||
{
|
|
||||||
playChannel = curChannel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (curChannel < maxChannel);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((1 << playChannel) & enabled_flag)
|
|
||||||
{
|
|
||||||
mixParams.hMixSession = pMem;
|
|
||||||
mixParams.hWndNotify = wavemix_window;
|
|
||||||
mixParams.dwFlags = dwFlags;
|
|
||||||
mixParams.wSize = 28;
|
|
||||||
mixParams.wLoops = loops;
|
|
||||||
mixParams.iChannel = playChannel;
|
|
||||||
mixParams.lpMixWave = wavePtr;
|
|
||||||
|
|
||||||
callback_ptr(1, wavePtr, playChannel);
|
|
||||||
channel_time[playChannel] = timeGetTime();
|
|
||||||
channel_wavePtr[playChannel] = wavePtr;
|
|
||||||
WaveMix::Play(&mixParams);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MIXWAVE* Sound::LoadWaveFile(LPCSTR lpName)
|
Mix_Chunk* Sound::LoadWaveFile(const std::string& lpName)
|
||||||
{
|
{
|
||||||
return pMem ? WaveMix::OpenWave(pMem, lpName, HInstance, 1u) : nullptr;
|
auto wavFile = fopenu(lpName.c_str(), "r");
|
||||||
|
if (!wavFile)
|
||||||
|
return nullptr;
|
||||||
|
fclose(wavFile);
|
||||||
|
|
||||||
|
return Mix_LoadWAV(lpName.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sound::FreeSound(MIXWAVE* wave)
|
void Sound::FreeSound(Mix_Chunk* wave)
|
||||||
{
|
{
|
||||||
if (wave && pMem)
|
if (wave)
|
||||||
WaveMix::FreeWave(pMem, wave);
|
Mix_FreeChunk(wave);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sound::Flush(int channelFrom, int channelTo)
|
void Sound::SetChannels(int channels)
|
||||||
{
|
{
|
||||||
if (pMem)
|
if (channels <= 0)
|
||||||
{
|
channels = 8;
|
||||||
if (channelTo >= num_channels)
|
|
||||||
channelTo = num_channels - 1;
|
|
||||||
|
|
||||||
if (channelFrom >= 0 && channelTo < num_channels)
|
num_channels = channels;
|
||||||
{
|
delete[] TimeStamps;
|
||||||
for (auto index = channelFrom; index <= channelTo; index++)
|
TimeStamps = new int[num_channels]();
|
||||||
{
|
Mix_AllocateChannels(num_channels);
|
||||||
WaveMix::FlushChannel(pMem, index, 0);
|
|
||||||
channel_time[index] = 0;
|
|
||||||
channel_wavePtr[index] = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Sound::NullCallback(int a1, MIXWAVE* a2, int a3)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
LRESULT Sound::SoundCallBackWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
|
|
||||||
{
|
|
||||||
if (Msg != MM_WOM_DONE)
|
|
||||||
return DefWindowProcA(hWnd, Msg, wParam, lParam);
|
|
||||||
|
|
||||||
auto wavePtr = reinterpret_cast<MIXWAVE*>(lParam);
|
|
||||||
int channel = -1;
|
|
||||||
for (auto index = 0; index < num_channels; ++index)
|
|
||||||
{
|
|
||||||
if (channel_wavePtr[index] == wavePtr &&
|
|
||||||
(channel < 0 || channel_time[index] < channel_time[channel]))
|
|
||||||
{
|
|
||||||
channel = index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (channel >= 0)
|
|
||||||
{
|
|
||||||
channel_time[channel] = 0;
|
|
||||||
channel_wavePtr[channel] = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
callback_ptr(2, wavePtr, channel);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +1,20 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "WaveMix.h"
|
|
||||||
|
|
||||||
class Sound
|
class Sound
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static int Init(HINSTANCE hInstance, int voices, void (* someFuncPtr)(int, MIXWAVE*, int));
|
static bool Init(int channels, bool enableFlag);
|
||||||
static void Enable(int channelFrom, int channelTo, int enableFlag);
|
static void Enable(bool enableFlag);
|
||||||
static void Idle();
|
|
||||||
static void Activate();
|
static void Activate();
|
||||||
static void Deactivate();
|
static void Deactivate();
|
||||||
static void Close();
|
static void Close();
|
||||||
static void PlaySound(MIXWAVE* wavePtr, int minChannel, int maxChannel, unsigned int dwFlags, int16_t loops);
|
static void PlaySound(Mix_Chunk* wavePtr, int time);
|
||||||
static MIXWAVE* LoadWaveFile(LPCSTR lpName);
|
static Mix_Chunk* LoadWaveFile(const std::string& lpName);
|
||||||
static void FreeSound(MIXWAVE* wave);
|
static void FreeSound(Mix_Chunk* wave);
|
||||||
static void Flush(int channelFrom, int channelTo);
|
static void SetChannels(int channels);
|
||||||
static void NullCallback(int a1, MIXWAVE* a2, int a3);
|
|
||||||
static LRESULT __stdcall SoundCallBackWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
|
|
||||||
private:
|
private:
|
||||||
static int num_channels;
|
static int num_channels;
|
||||||
static HWND wavemix_window;
|
static bool enabled_flag;
|
||||||
static HANDLE pMem;
|
static int* TimeStamps;
|
||||||
static unsigned int enabled_flag;
|
|
||||||
static int channel_time[8];
|
|
||||||
static MIXWAVE* channel_wavePtr[8];
|
|
||||||
static void (* callback_ptr)(int, MIXWAVE*, int);
|
|
||||||
static HMODULE HInstance;
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,81 +3,58 @@
|
|||||||
|
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include "objlist_class.h"
|
|
||||||
#include "partman.h"
|
|
||||||
#include "gdrv.h"
|
|
||||||
#include "loader.h"
|
|
||||||
#include "pb.h"
|
|
||||||
#include "pinball.h"
|
|
||||||
#include "score.h"
|
|
||||||
#include "TPinballTable.h"
|
|
||||||
#include "TTextBox.h"
|
|
||||||
#include "winmain.h"
|
#include "winmain.h"
|
||||||
|
|
||||||
int main()
|
int MainActual(LPCSTR lpCmdLine)
|
||||||
{
|
{
|
||||||
|
// Todo: get rid of restart to change resolution.
|
||||||
|
int returnCode;
|
||||||
|
do
|
||||||
{
|
{
|
||||||
// Testing with UI
|
returnCode = winmain::WinMain(lpCmdLine);
|
||||||
char cmdLine[1]{};
|
|
||||||
WinMain(GetModuleHandleA(nullptr), nullptr, cmdLine, 10);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
while (winmain::RestartRequested());
|
||||||
std::cout << "Hello World!\n";
|
return returnCode;
|
||||||
gdrv::init(nullptr, nullptr);
|
|
||||||
auto dib = gdrv::DibCreate(8, 1, 1);
|
|
||||||
gdrv::DibSetUsage(dib, nullptr, 1);
|
|
||||||
|
|
||||||
auto d = objlist_class<void>(2, 4);
|
|
||||||
for (size_t i = 0; i < 100; i++)
|
|
||||||
{
|
|
||||||
d.Add((void*)i);
|
|
||||||
}
|
|
||||||
d.Delete((void*)3);
|
|
||||||
|
|
||||||
auto xx = sizeof(datFileHeader);
|
|
||||||
|
|
||||||
lstrcpyA(winmain::DatFileName, "PINBALL.DAT");
|
|
||||||
pb::init();
|
|
||||||
auto datFile = pb::record_table;
|
|
||||||
|
|
||||||
assert(partman::field_size_nth(datFile, 0, datFieldTypes::String, 0) == 43);
|
|
||||||
assert(partman::field_size_nth(datFile, 2, datFieldTypes::Palette, 0) == 1024);
|
|
||||||
assert(partman::field_size_nth(datFile, 101, datFieldTypes::FloatArray, 4) == 32);
|
|
||||||
|
|
||||||
assert(strcmp(partman::field(datFile, 0, datFieldTypes::String), "3D-Pinball: Copyright 1994, Cinematronics") == 0);
|
|
||||||
assert(strcmp(partman::field(datFile, 540, datFieldTypes::GroupName), "table_objects") == 0);
|
|
||||||
|
|
||||||
assert(partman::record_labeled(datFile, "background") == 2);
|
|
||||||
assert(partman::record_labeled(datFile, "a_bump1") == 372);
|
|
||||||
|
|
||||||
assert(memcmp(partman::field_labeled(datFile, "table_size", datFieldTypes::ShortArray), new short[2]{ 600, 416 }, 2 * 2) == 0);
|
|
||||||
|
|
||||||
//loader::error(25, 26);
|
|
||||||
loader::get_sound_id(18);
|
|
||||||
visualStruct visual1{};
|
|
||||||
loader::material(96, &visual1);
|
|
||||||
loader::query_visual(283, 0, &visual1);
|
|
||||||
visualKickerStruct kicker1{};
|
|
||||||
loader::kicker(509, &kicker1);
|
|
||||||
|
|
||||||
auto score1 = score::create("score1", nullptr);
|
|
||||||
|
|
||||||
auto pinballTable = pb::MainTable;
|
|
||||||
//pinballTable->find_component(1);
|
|
||||||
|
|
||||||
for (int i = 0; i < 190; i++)
|
|
||||||
{
|
|
||||||
auto rsc = pinball::get_rc_string(i, 0);
|
|
||||||
if (rsc)
|
|
||||||
printf_s("%d:\t%s\n", i, rsc);
|
|
||||||
}
|
|
||||||
|
|
||||||
//DatParser::Parse(dataFileName);
|
|
||||||
std::cout << "Goodby World!\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
std::string cmdLine;
|
||||||
|
for (int i = 1; i < argc; i++)
|
||||||
|
cmdLine += argv[i];
|
||||||
|
|
||||||
|
return MainActual(cmdLine.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
#if _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
// Windows subsystem main
|
||||||
|
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
|
||||||
|
{
|
||||||
|
return MainActual(lpCmdLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fopen to _wfopen adapter, for UTF-8 paths
|
||||||
|
FILE* fopenu(const char* path, const char* opt)
|
||||||
|
{
|
||||||
|
wchar_t* wideArgs[2]{};
|
||||||
|
for (auto& arg : wideArgs)
|
||||||
|
{
|
||||||
|
auto src = wideArgs[0] ? opt : path;
|
||||||
|
auto length = MultiByteToWideChar(CP_UTF8, 0, src, -1, nullptr, 0);
|
||||||
|
arg = new wchar_t[length];
|
||||||
|
MultiByteToWideChar(CP_UTF8, 0, src, -1, arg, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto fileHandle = _wfopen(wideArgs[0], wideArgs[1]);
|
||||||
|
for (auto arg : wideArgs)
|
||||||
|
delete[] arg;
|
||||||
|
|
||||||
|
return fileHandle;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Run program: Ctrl + F5 or Debug > Start Without Debugging menu
|
// Run program: Ctrl + F5 or Debug > Start Without Debugging menu
|
||||||
// Debug program: F5 or Debug > Start Debugging menu
|
// Debug program: F5 or Debug > Start Debugging menu
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -1,441 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<ItemGroup>
|
|
||||||
<Filter Include="Source Files">
|
|
||||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
|
||||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Header Files">
|
|
||||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
|
||||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Resource Files">
|
|
||||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
|
||||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Header Files\TEdgeSegment">
|
|
||||||
<UniqueIdentifier>{0aa40751-a44a-400e-8809-ee817161e8e0}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Source Files\TEdgeSegment">
|
|
||||||
<UniqueIdentifier>{d70e7fca-2294-41a4-9cf8-78052bdb9aa4}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Source Files\TCollisionComponent">
|
|
||||||
<UniqueIdentifier>{01aed326-d2ec-457a-b99f-08ef32ed97fa}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Header Files\TCollisionComponent">
|
|
||||||
<UniqueIdentifier>{7ed2796a-da4b-4edd-8783-53e45d8d1c88}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Header Files\TPinballComponent">
|
|
||||||
<UniqueIdentifier>{9ee086c2-1a95-48fb-92d8-4b7e7f6682ff}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Source Files\TPinballComponent">
|
|
||||||
<UniqueIdentifier>{33813da8-81ac-449c-b19a-9756272519b9}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClInclude Include="pch.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="objlist_class.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="partman.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="loader.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="pinball.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="score.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TPinballComponent.h">
|
|
||||||
<Filter>Header Files\TPinballComponent</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TBall.h">
|
|
||||||
<Filter>Header Files\TPinballComponent</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="resource.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TComponentGroup.h">
|
|
||||||
<Filter>Header Files\TPinballComponent</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TLight.h">
|
|
||||||
<Filter>Header Files\TPinballComponent</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TLightBargraph.h">
|
|
||||||
<Filter>Header Files\TPinballComponent</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TLightGroup.h">
|
|
||||||
<Filter>Header Files\TPinballComponent</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TSound.h">
|
|
||||||
<Filter>Header Files\TPinballComponent</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TTextBox.h">
|
|
||||||
<Filter>Header Files\TPinballComponent</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TTimer.h">
|
|
||||||
<Filter>Header Files\TPinballComponent</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="memory.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="winmain.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="options.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="Sound.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="pb.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="render.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="fullscrn.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="gdrv.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="maths.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="zdrv.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TEdgeSegment.h">
|
|
||||||
<Filter>Header Files\TEdgeSegment</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TCollisionComponent.h">
|
|
||||||
<Filter>Header Files\TCollisionComponent</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TCircle.h">
|
|
||||||
<Filter>Header Files\TEdgeSegment</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TLine.h">
|
|
||||||
<Filter>Header Files\TEdgeSegment</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TWall.h">
|
|
||||||
<Filter>Header Files\TCollisionComponent</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TBumper.h">
|
|
||||||
<Filter>Header Files\TCollisionComponent</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TBlocker.h">
|
|
||||||
<Filter>Header Files\TCollisionComponent</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TDemo.h">
|
|
||||||
<Filter>Header Files\TCollisionComponent</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TDrain.h">
|
|
||||||
<Filter>Header Files\TCollisionComponent</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TFlagSpinner.h">
|
|
||||||
<Filter>Header Files\TCollisionComponent</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TFlipper.h">
|
|
||||||
<Filter>Header Files\TCollisionComponent</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TGate.h">
|
|
||||||
<Filter>Header Files\TCollisionComponent</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="THole.h">
|
|
||||||
<Filter>Header Files\TCollisionComponent</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TKickback.h">
|
|
||||||
<Filter>Header Files\TCollisionComponent</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TKickout.h">
|
|
||||||
<Filter>Header Files\TCollisionComponent</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TOneway.h">
|
|
||||||
<Filter>Header Files\TCollisionComponent</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TPlunger.h">
|
|
||||||
<Filter>Header Files\TCollisionComponent</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TPopupTarget.h">
|
|
||||||
<Filter>Header Files\TCollisionComponent</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TRamp.h">
|
|
||||||
<Filter>Header Files\TCollisionComponent</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TRollover.h">
|
|
||||||
<Filter>Header Files\TCollisionComponent</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TSink.h">
|
|
||||||
<Filter>Header Files\TCollisionComponent</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TSoloTarget.h">
|
|
||||||
<Filter>Header Files\TCollisionComponent</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TTableLayer.h">
|
|
||||||
<Filter>Header Files\TCollisionComponent</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TPinballTable.h">
|
|
||||||
<Filter>Header Files\TPinballComponent</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TTripwire.h">
|
|
||||||
<Filter>Header Files\TCollisionComponent</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TLightRollover.h">
|
|
||||||
<Filter>Header Files\TCollisionComponent</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="proj.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="timer.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="midi.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="nudge.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TTextBoxMessage.h">
|
|
||||||
<Filter>Header Files\TPinballComponent</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="high_score.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="control.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TEdgeManager.h">
|
|
||||||
<Filter>Header Files\TPinballComponent</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TEdgeBox.h">
|
|
||||||
<Filter>Header Files\TPinballComponent</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TFlipperEdge.h">
|
|
||||||
<Filter>Header Files\TEdgeSegment</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="WaveMix.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="splash.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="pch.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="SpaceCadetPinball.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="partman.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="loader.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="pinball.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="score.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TPinballComponent.cpp">
|
|
||||||
<Filter>Source Files\TPinballComponent</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TPinballTable.cpp">
|
|
||||||
<Filter>Source Files\TPinballComponent</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TBall.cpp">
|
|
||||||
<Filter>Source Files\TPinballComponent</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TComponentGroup.cpp">
|
|
||||||
<Filter>Source Files\TPinballComponent</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TLight.cpp">
|
|
||||||
<Filter>Source Files\TPinballComponent</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TLightBargraph.cpp">
|
|
||||||
<Filter>Source Files\TPinballComponent</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TLightGroup.cpp">
|
|
||||||
<Filter>Source Files\TPinballComponent</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TSound.cpp">
|
|
||||||
<Filter>Source Files\TPinballComponent</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TTextBox.cpp">
|
|
||||||
<Filter>Source Files\TPinballComponent</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TTimer.cpp">
|
|
||||||
<Filter>Source Files\TPinballComponent</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="memory.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="winmain.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="options.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="Sound.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="pb.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="render.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="fullscrn.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="gdrv.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="maths.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="zdrv.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TEdgeSegment.cpp">
|
|
||||||
<Filter>Source Files\TEdgeSegment</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TCollisionComponent.cpp">
|
|
||||||
<Filter>Source Files\TCollisionComponent</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TCircle.cpp">
|
|
||||||
<Filter>Source Files\TEdgeSegment</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TLine.cpp">
|
|
||||||
<Filter>Source Files\TEdgeSegment</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TWall.cpp">
|
|
||||||
<Filter>Source Files\TCollisionComponent</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TBlocker.cpp">
|
|
||||||
<Filter>Source Files\TCollisionComponent</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TBumper.cpp">
|
|
||||||
<Filter>Source Files\TCollisionComponent</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TDemo.cpp">
|
|
||||||
<Filter>Source Files\TCollisionComponent</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TDrain.cpp">
|
|
||||||
<Filter>Source Files\TCollisionComponent</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TFlagSpinner.cpp">
|
|
||||||
<Filter>Source Files\TCollisionComponent</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TFlipper.cpp">
|
|
||||||
<Filter>Source Files\TCollisionComponent</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TGate.cpp">
|
|
||||||
<Filter>Source Files\TCollisionComponent</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="THole.cpp">
|
|
||||||
<Filter>Source Files\TCollisionComponent</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TKickback.cpp">
|
|
||||||
<Filter>Source Files\TCollisionComponent</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TKickout.cpp">
|
|
||||||
<Filter>Source Files\TCollisionComponent</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TOneway.cpp">
|
|
||||||
<Filter>Source Files\TCollisionComponent</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TPlunger.cpp">
|
|
||||||
<Filter>Source Files\TCollisionComponent</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TPopupTarget.cpp">
|
|
||||||
<Filter>Source Files\TCollisionComponent</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TRamp.cpp">
|
|
||||||
<Filter>Source Files\TCollisionComponent</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TRollover.cpp">
|
|
||||||
<Filter>Source Files\TCollisionComponent</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TSink.cpp">
|
|
||||||
<Filter>Source Files\TCollisionComponent</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TSoloTarget.cpp">
|
|
||||||
<Filter>Source Files\TCollisionComponent</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TTableLayer.cpp">
|
|
||||||
<Filter>Source Files\TCollisionComponent</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TTripwire.cpp">
|
|
||||||
<Filter>Source Files\TCollisionComponent</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TLightRollover.cpp">
|
|
||||||
<Filter>Source Files\TCollisionComponent</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="proj.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="timer.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="midi.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="nudge.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TTextBoxMessage.cpp">
|
|
||||||
<Filter>Source Files\TPinballComponent</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="high_score.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="control.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TEdgeManager.cpp">
|
|
||||||
<Filter>Source Files\TPinballComponent</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TEdgeBox.cpp">
|
|
||||||
<Filter>Source Files\TPinballComponent</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TFlipperEdge.cpp">
|
|
||||||
<Filter>Source Files\TEdgeSegment</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="WaveMix.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="splash.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Natvis Include="NatvisFile.natvis" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ResourceCompile Include="SpaceCadetPinball.rc">
|
|
||||||
<Filter>Resource Files</Filter>
|
|
||||||
</ResourceCompile>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="PB_MSGFT.bin">
|
|
||||||
<Filter>Resource Files</Filter>
|
|
||||||
</None>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Image Include="Icon_1.ico">
|
|
||||||
<Filter>Resource Files</Filter>
|
|
||||||
</Image>
|
|
||||||
<Image Include="splash_bitmap.bmp">
|
|
||||||
<Filter>Resource Files</Filter>
|
|
||||||
</Image>
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
||||||
@@ -5,7 +5,6 @@
|
|||||||
#include "fullscrn.h"
|
#include "fullscrn.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "maths.h"
|
#include "maths.h"
|
||||||
#include "objlist_class.h"
|
|
||||||
#include "pb.h"
|
#include "pb.h"
|
||||||
#include "proj.h"
|
#include "proj.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
@@ -32,7 +31,7 @@ TBall::TBall(TPinballTable* table) : TPinballComponent(table, -1, false)
|
|||||||
Position.X = 0.0;
|
Position.X = 0.0;
|
||||||
Position.Y = 0.0;
|
Position.Y = 0.0;
|
||||||
|
|
||||||
ListBitmap = new objlist_class<gdrv_bitmap8>(0, 4);
|
ListBitmap = new std::vector<gdrv_bitmap8*>();
|
||||||
|
|
||||||
/*Full tilt: ball is ballN, where N[0,2] resolution*/
|
/*Full tilt: ball is ballN, where N[0,2] resolution*/
|
||||||
if (pb::FullTiltMode)
|
if (pb::FullTiltMode)
|
||||||
@@ -40,25 +39,18 @@ TBall::TBall(TPinballTable* table) : TPinballComponent(table, -1, false)
|
|||||||
auto groupIndex = loader::query_handle(ballGroupName);
|
auto groupIndex = loader::query_handle(ballGroupName);
|
||||||
|
|
||||||
Offset = *loader::query_float_attribute(groupIndex, 0, 500);
|
Offset = *loader::query_float_attribute(groupIndex, 0, 500);
|
||||||
|
|
||||||
auto visualCount = loader::query_visual_states(groupIndex);
|
auto visualCount = loader::query_visual_states(groupIndex);
|
||||||
auto index = 0;
|
for (auto index = 0; index < visualCount; ++index)
|
||||||
if (visualCount > 0)
|
|
||||||
{
|
{
|
||||||
auto visualZPtr = VisualZArray;
|
loader::query_visual(groupIndex, index, &visual);
|
||||||
do
|
if (ListBitmap)
|
||||||
{
|
ListBitmap->push_back(visual.Bitmap);
|
||||||
loader::query_visual(groupIndex, index, &visual);
|
auto visVec = reinterpret_cast<vector_type*>(loader::query_float_attribute(groupIndex, index, 501));
|
||||||
if (ListBitmap)
|
auto zDepth = proj::z_distance(visVec);
|
||||||
ListBitmap->Add(visual.Bitmap);
|
VisualZArray[index] = zDepth;
|
||||||
auto visVec = reinterpret_cast<vector_type*>(loader::query_float_attribute(groupIndex, index, 501));
|
|
||||||
auto zDepth = proj::z_distance(visVec);
|
|
||||||
++index;
|
|
||||||
*visualZPtr = zDepth;
|
|
||||||
++visualZPtr;
|
|
||||||
}
|
|
||||||
while (index < visualCount);
|
|
||||||
}
|
}
|
||||||
RenderSprite = render::create_sprite(VisualType::Ball, nullptr, nullptr, 0, 0, nullptr);
|
RenderSprite = render::create_sprite(VisualTypes::Ball, nullptr, nullptr, 0, 0, nullptr);
|
||||||
PinballTable->CollisionCompOffset = Offset;
|
PinballTable->CollisionCompOffset = Offset;
|
||||||
Position.Z = Offset;
|
Position.Z = Offset;
|
||||||
}
|
}
|
||||||
@@ -79,13 +71,13 @@ void TBall::Repaint()
|
|||||||
auto zDepth = proj::z_distance(&Position);
|
auto zDepth = proj::z_distance(&Position);
|
||||||
|
|
||||||
auto zArrPtr = VisualZArray;
|
auto zArrPtr = VisualZArray;
|
||||||
int index;
|
auto index = 0u;
|
||||||
for (index = 0; index < ListBitmap->GetCount() - 1; ++index, zArrPtr++)
|
for (; index < ListBitmap->size() - 1; ++index, zArrPtr++)
|
||||||
{
|
{
|
||||||
if (*zArrPtr <= zDepth) break;
|
if (*zArrPtr <= zDepth) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto bmp = ListBitmap->Get(index);
|
auto bmp = ListBitmap->at(index);
|
||||||
render::ball_set(
|
render::ball_set(
|
||||||
RenderSprite,
|
RenderSprite,
|
||||||
bmp,
|
bmp,
|
||||||
@@ -138,10 +130,9 @@ void TBall::throw_ball(TBall* ball, vector_type* acceleration, float angleMult,
|
|||||||
{
|
{
|
||||||
ball->CollisionComp = nullptr;
|
ball->CollisionComp = nullptr;
|
||||||
ball->Acceleration = *acceleration;
|
ball->Acceleration = *acceleration;
|
||||||
float rnd = static_cast<float>(rand());
|
float rnd = RandFloat();
|
||||||
float angle = (1.0f - (rnd * 0.00003051850947599719f + rnd * 0.00003051850947599719f)) * angleMult;
|
float angle = (1.0f - (rnd + rnd)) * angleMult;
|
||||||
maths::RotateVector(&ball->Acceleration, angle);
|
maths::RotateVector(&ball->Acceleration, angle);
|
||||||
rnd = static_cast<float>(rand());
|
rnd = RandFloat();
|
||||||
ball->Speed = (1.0f - (rnd * 0.00003051850947599719f + rnd * 0.00003051850947599719f)) * (speedMult1 *
|
ball->Speed = (1.0f - (rnd + rnd)) * (speedMult1 * speedMult2) + speedMult1;
|
||||||
speedMult2) + speedMult1;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,21 +17,20 @@ public :
|
|||||||
static void throw_ball(TBall* ball, struct vector_type* acceleration, float angleMult, float speedMult1,
|
static void throw_ball(TBall* ball, struct vector_type* acceleration, float angleMult, float speedMult1,
|
||||||
float speedMult2);
|
float speedMult2);
|
||||||
|
|
||||||
vector_type Position;
|
vector_type Position{};
|
||||||
vector_type Acceleration;
|
vector_type Acceleration{};
|
||||||
float Speed;
|
float Speed;
|
||||||
float RayMaxDistance;
|
float RayMaxDistance;
|
||||||
float TimeDelta;
|
float TimeDelta;
|
||||||
float TimeNow;
|
float TimeNow;
|
||||||
vector_type InvAcceleration;
|
vector_type InvAcceleration{};
|
||||||
vector_type RampFieldForce;
|
vector_type RampFieldForce{};
|
||||||
TCollisionComponent* CollisionComp;
|
TCollisionComponent* CollisionComp;
|
||||||
int FieldFlag;
|
int FieldFlag;
|
||||||
TEdgeSegment* Collisions[5];
|
TEdgeSegment* Collisions[5]{};
|
||||||
int EdgeCollisionCount;
|
int EdgeCollisionCount;
|
||||||
vector_type CollisionOffset;
|
vector_type CollisionOffset{};
|
||||||
int CollisionFlag;
|
int CollisionFlag;
|
||||||
float Offset;
|
float Offset;
|
||||||
int Unknown29;
|
float VisualZArray[50]{};
|
||||||
float VisualZArray[50];
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#include "control.h"
|
#include "control.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "objlist_class.h"
|
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
|
||||||
@@ -46,7 +45,7 @@ int TBlocker::Message(int code, float value)
|
|||||||
case 52:
|
case 52:
|
||||||
ActiveFlag = 1;
|
ActiveFlag = 1;
|
||||||
loader::play_sound(SoundIndex4);
|
loader::play_sound(SoundIndex4);
|
||||||
render::sprite_set_bitmap(RenderSprite, ListBitmap->Get(0));
|
render::sprite_set_bitmap(RenderSprite, ListBitmap->at(0));
|
||||||
break;
|
break;
|
||||||
case 59:
|
case 59:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#include "control.h"
|
#include "control.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "objlist_class.h"
|
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "TPinballTable.h"
|
#include "TPinballTable.h"
|
||||||
@@ -29,8 +28,9 @@ int TBumper::Message(int code, float value)
|
|||||||
case 11:
|
case 11:
|
||||||
{
|
{
|
||||||
auto nextBmp = static_cast<int>(floor(value));
|
auto nextBmp = static_cast<int>(floor(value));
|
||||||
if (2 * nextBmp > ListBitmap->GetCount() - 1)
|
auto maxBmp = static_cast<int>(ListBitmap->size()) - 1;
|
||||||
nextBmp = (ListBitmap->GetCount() - 1) / 2;
|
if (2 * nextBmp > maxBmp)
|
||||||
|
nextBmp = maxBmp / 2;
|
||||||
if (nextBmp < 0)
|
if (nextBmp < 0)
|
||||||
nextBmp = 0;
|
nextBmp = 0;
|
||||||
if (nextBmp != BmpIndex)
|
if (nextBmp != BmpIndex)
|
||||||
@@ -48,7 +48,7 @@ int TBumper::Message(int code, float value)
|
|||||||
case 12:
|
case 12:
|
||||||
{
|
{
|
||||||
auto nextBmp = BmpIndex + 1;
|
auto nextBmp = BmpIndex + 1;
|
||||||
auto maxBmp = ListBitmap->GetCount() - 1;
|
auto maxBmp = static_cast<int>(ListBitmap->size()) - 1;
|
||||||
if (2 * nextBmp > maxBmp)
|
if (2 * nextBmp > maxBmp)
|
||||||
nextBmp = maxBmp / 2;
|
nextBmp = maxBmp / 2;
|
||||||
TBumper::Message(11, static_cast<float>(nextBmp));
|
TBumper::Message(11, static_cast<float>(nextBmp));
|
||||||
@@ -124,8 +124,8 @@ int TBumper::get_scoring(int index)
|
|||||||
void TBumper::TimerExpired(int timerId, void* caller)
|
void TBumper::TimerExpired(int timerId, void* caller)
|
||||||
{
|
{
|
||||||
auto bump = static_cast<TBumper*>(caller);
|
auto bump = static_cast<TBumper*>(caller);
|
||||||
auto bmp = bump->ListBitmap->Get(bump->BmpIndex * 2);
|
auto bmp = bump->ListBitmap->at(bump->BmpIndex * 2);
|
||||||
auto zMap = bump->ListZMap->Get(bump->BmpIndex * 2);
|
auto zMap = bump->ListZMap->at(bump->BmpIndex * 2);
|
||||||
bump->Timer = 0;
|
bump->Timer = 0;
|
||||||
render::sprite_set(
|
render::sprite_set(
|
||||||
bump->RenderSprite,
|
bump->RenderSprite,
|
||||||
@@ -139,8 +139,8 @@ void TBumper::TimerExpired(int timerId, void* caller)
|
|||||||
void TBumper::Fire()
|
void TBumper::Fire()
|
||||||
{
|
{
|
||||||
int bmpIndex = 2 * BmpIndex + 1;
|
int bmpIndex = 2 * BmpIndex + 1;
|
||||||
auto bmp = ListBitmap->Get(bmpIndex);
|
auto bmp = ListBitmap->at(bmpIndex);
|
||||||
auto zMap = ListZMap->Get(bmpIndex);
|
auto zMap = ListZMap->at(bmpIndex);
|
||||||
render::sprite_set(
|
render::sprite_set(
|
||||||
RenderSprite,
|
RenderSprite,
|
||||||
bmp,
|
bmp,
|
||||||
|
|||||||
@@ -28,6 +28,6 @@ public:
|
|||||||
float OriginalThreshold;
|
float OriginalThreshold;
|
||||||
int SoundIndex4;
|
int SoundIndex4;
|
||||||
int SoundIndex3;
|
int SoundIndex3;
|
||||||
int Scores[4];
|
int Scores[4]{};
|
||||||
TBumper_player_backup PlayerData[4];
|
TBumper_player_backup PlayerData[4]{};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ class TCircle :
|
|||||||
public TEdgeSegment
|
public TEdgeSegment
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
circle_type Circle;
|
circle_type Circle{};
|
||||||
|
|
||||||
TCircle(TCollisionComponent* collComp, char* activeFlag, unsigned int collisionGroup, vector_type* center,
|
TCircle(TCollisionComponent* collComp, char* activeFlag, unsigned int collisionGroup, vector_type* center,
|
||||||
float radius);
|
float radius);
|
||||||
|
|||||||
@@ -2,17 +2,15 @@
|
|||||||
#include "TCollisionComponent.h"
|
#include "TCollisionComponent.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "maths.h"
|
#include "maths.h"
|
||||||
#include "objlist_class.h"
|
|
||||||
#include "TEdgeSegment.h"
|
#include "TEdgeSegment.h"
|
||||||
#include "TPinballTable.h"
|
#include "TPinballTable.h"
|
||||||
|
|
||||||
|
|
||||||
TCollisionComponent::TCollisionComponent(TPinballTable* table, int groupIndex, bool createWall) : TPinballComponent(
|
TCollisionComponent::TCollisionComponent(TPinballTable* table, int groupIndex, bool createWall) :
|
||||||
table, groupIndex, true)
|
TPinballComponent(table, groupIndex, true)
|
||||||
{
|
{
|
||||||
visualStruct visual{};
|
visualStruct visual{};
|
||||||
|
|
||||||
EdgeList = new objlist_class<TEdgeSegment>(4, 4);
|
|
||||||
ActiveFlag = 1;
|
ActiveFlag = 1;
|
||||||
if (GroupName != nullptr)
|
if (GroupName != nullptr)
|
||||||
UnusedBaseFlag = 1;
|
UnusedBaseFlag = 1;
|
||||||
@@ -42,22 +40,15 @@ TCollisionComponent::TCollisionComponent(TPinballTable* table, int groupIndex, b
|
|||||||
|
|
||||||
TCollisionComponent::~TCollisionComponent()
|
TCollisionComponent::~TCollisionComponent()
|
||||||
{
|
{
|
||||||
for (TEdgeSegment* edge; EdgeList->GetCount() > 0;)
|
for (auto edge : EdgeList)
|
||||||
{
|
|
||||||
edge = EdgeList->Get(0);
|
|
||||||
EdgeList->Delete(edge);
|
|
||||||
delete edge;
|
delete edge;
|
||||||
}
|
|
||||||
delete EdgeList;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TCollisionComponent::port_draw()
|
void TCollisionComponent::port_draw()
|
||||||
{
|
{
|
||||||
for (int index = EdgeList->GetCount() - 1; index >= 0; index--)
|
for (auto edge : EdgeList)
|
||||||
{
|
edge->port_draw();
|
||||||
EdgeList->Get(index)->port_draw();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int TCollisionComponent::DefaultCollision(TBall* ball, vector_type* nextPosition, vector_type* direction)
|
int TCollisionComponent::DefaultCollision(TBall* ball, vector_type* nextPosition, vector_type* direction)
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class TBall;
|
|||||||
class TCollisionComponent : public TPinballComponent
|
class TCollisionComponent : public TPinballComponent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
objlist_class<TEdgeSegment>* EdgeList;
|
std::vector<TEdgeSegment*> EdgeList;
|
||||||
float Elasticity;
|
float Elasticity;
|
||||||
float Smoothness;
|
float Smoothness;
|
||||||
float Boost;
|
float Boost;
|
||||||
|
|||||||
@@ -4,13 +4,11 @@
|
|||||||
|
|
||||||
#include "control.h"
|
#include "control.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "objlist_class.h"
|
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "TPinballTable.h"
|
#include "TPinballTable.h"
|
||||||
|
|
||||||
TComponentGroup::TComponentGroup(TPinballTable* table, int groupIndex) : TPinballComponent(table, groupIndex, false)
|
TComponentGroup::TComponentGroup(TPinballTable* table, int groupIndex) : TPinballComponent(table, groupIndex, false)
|
||||||
{
|
{
|
||||||
List = new objlist_class<TPinballComponent>(4, 4);
|
|
||||||
Timer = 0;
|
Timer = 0;
|
||||||
if (groupIndex > 0)
|
if (groupIndex > 0)
|
||||||
{
|
{
|
||||||
@@ -21,7 +19,7 @@ TComponentGroup::TComponentGroup(TPinballTable* table, int groupIndex) : TPinbal
|
|||||||
{
|
{
|
||||||
auto component = table->find_component(*shortArrPtr);
|
auto component = table->find_component(*shortArrPtr);
|
||||||
if (component)
|
if (component)
|
||||||
List->Add(component);
|
List.push_back(component);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -33,7 +31,6 @@ TComponentGroup::~TComponentGroup()
|
|||||||
timer::kill(Timer);
|
timer::kill(Timer);
|
||||||
Timer = 0;
|
Timer = 0;
|
||||||
}
|
}
|
||||||
delete List;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int TComponentGroup::Message(int code, float value)
|
int TComponentGroup::Message(int code, float value)
|
||||||
@@ -48,11 +45,11 @@ int TComponentGroup::Message(int code, float value)
|
|||||||
if (value > 0.0f)
|
if (value > 0.0f)
|
||||||
this->Timer = timer::set(value, this, NotifyTimerExpired);
|
this->Timer = timer::set(value, this, NotifyTimerExpired);
|
||||||
}
|
}
|
||||||
else if (code <= 1007 || code > 1011 && code != 1020 && code != 1022)
|
else if (code <= 1007 || (code > 1011 && code != 1020 && code != 1022))
|
||||||
{
|
{
|
||||||
for (int i = 0; i < List->GetCount(); i++)
|
for (auto component : List)
|
||||||
{
|
{
|
||||||
List->Get(i)->Message(code, value);
|
component->Message(code, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -11,6 +11,6 @@ public:
|
|||||||
int Message(int code, float value) override;
|
int Message(int code, float value) override;
|
||||||
static void NotifyTimerExpired(int timerId, void* caller);
|
static void NotifyTimerExpired(int timerId, void* caller);
|
||||||
|
|
||||||
objlist_class<TPinballComponent>* List;
|
std::vector<TPinballComponent*> List;
|
||||||
int Timer;
|
int Timer;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -105,8 +105,7 @@ void TDemo::Collision(TBall* ball, vector_type* nextPosition, vector_type* direc
|
|||||||
case 1400:
|
case 1400:
|
||||||
if (!FlipLeftTimer && !FlipLeftFlag)
|
if (!FlipLeftTimer && !FlipLeftFlag)
|
||||||
{
|
{
|
||||||
float time = FlipTimerTime1 + FlipTimerTime2 - static_cast<float>(rand()) *
|
float time = FlipTimerTime1 + FlipTimerTime2 - RandFloat() * (FlipTimerTime2 + FlipTimerTime2);
|
||||||
0.00003051850947599719f * (FlipTimerTime2 + FlipTimerTime2);
|
|
||||||
FlipLeftTimer = timer::set(time, this, FlipLeft);
|
FlipLeftTimer = timer::set(time, this, FlipLeft);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -116,8 +115,7 @@ void TDemo::Collision(TBall* ball, vector_type* nextPosition, vector_type* direc
|
|||||||
case 1402:
|
case 1402:
|
||||||
if (!FlipRightTimer && !FlipRightFlag)
|
if (!FlipRightTimer && !FlipRightFlag)
|
||||||
{
|
{
|
||||||
float time = FlipTimerTime1 + FlipTimerTime2 - static_cast<float>(rand()) *
|
float time = FlipTimerTime1 + FlipTimerTime2 - RandFloat() * (FlipTimerTime2 + FlipTimerTime2);
|
||||||
0.00003051850947599719f * (FlipTimerTime2 + FlipTimerTime2);
|
|
||||||
FlipRightTimer = timer::set(time, this, FlipRight);
|
FlipRightTimer = timer::set(time, this, FlipRight);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -128,7 +126,7 @@ void TDemo::Collision(TBall* ball, vector_type* nextPosition, vector_type* direc
|
|||||||
if (!PlungerFlag)
|
if (!PlungerFlag)
|
||||||
{
|
{
|
||||||
PinballTable->Message(1004, ball->TimeNow);
|
PinballTable->Message(1004, ball->TimeNow);
|
||||||
float time = static_cast<float>(rand()) * 0.00003051850947599719f + 2.0f;
|
float time = RandFloat() + 2.0f;
|
||||||
PlungerFlag = timer::set(time, this, PlungerRelease);
|
PlungerFlag = timer::set(time, this, PlungerRelease);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -172,8 +170,8 @@ void TDemo::FlipRight(int timerId, void* caller)
|
|||||||
}
|
}
|
||||||
demo->PinballTable->Message(1002, pb::time_next);
|
demo->PinballTable->Message(1002, pb::time_next);
|
||||||
demo->FlipRightFlag = 1;
|
demo->FlipRightFlag = 1;
|
||||||
float time = demo->UnFlipTimerTime1 + demo->UnFlipTimerTime2 - static_cast<float>(rand()) *
|
float time = demo->UnFlipTimerTime1 + demo->UnFlipTimerTime2 - RandFloat() *
|
||||||
0.00003051850947599719f * (demo->UnFlipTimerTime2 + demo->UnFlipTimerTime2);
|
(demo->UnFlipTimerTime2 + demo->UnFlipTimerTime2);
|
||||||
timer::set(time, demo, UnFlipRight);
|
timer::set(time, demo, UnFlipRight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -190,8 +188,8 @@ void TDemo::FlipLeft(int timerId, void* caller)
|
|||||||
}
|
}
|
||||||
demo->PinballTable->Message(1000, pb::time_next);
|
demo->PinballTable->Message(1000, pb::time_next);
|
||||||
demo->FlipLeftFlag = 1;
|
demo->FlipLeftFlag = 1;
|
||||||
float time = demo->UnFlipTimerTime1 + demo->UnFlipTimerTime2 - static_cast<float>(rand()) *
|
float time = demo->UnFlipTimerTime1 + demo->UnFlipTimerTime2 - RandFloat() *
|
||||||
0.00003051850947599719f * (demo->UnFlipTimerTime2 + demo->UnFlipTimerTime2);
|
(demo->UnFlipTimerTime2 + demo->UnFlipTimerTime2);
|
||||||
timer::set(time, demo, UnFlipLeft);
|
timer::set(time, demo, UnFlipLeft);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
#include "pch.h"
|
|
||||||
#include "TEdgeBox.h"
|
|
||||||
|
|
||||||
#include "objlist_class.h"
|
|
||||||
|
|
||||||
TEdgeBox::TEdgeBox()
|
|
||||||
{
|
|
||||||
EdgeList = new objlist_class<TEdgeSegment>(0, 4);
|
|
||||||
FieldList = new objlist_class<field_effect_type>(0, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEdgeBox::~TEdgeBox()
|
|
||||||
{
|
|
||||||
delete EdgeList;
|
|
||||||
delete FieldList;
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "objlist_class.h"
|
|
||||||
|
|
||||||
|
|
||||||
struct field_effect_type;
|
struct field_effect_type;
|
||||||
class TEdgeSegment;
|
class TEdgeSegment;
|
||||||
@@ -8,10 +6,6 @@ class TEdgeSegment;
|
|||||||
class TEdgeBox
|
class TEdgeBox
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TEdgeBox();
|
std::vector<TEdgeSegment*> EdgeList{};
|
||||||
~TEdgeBox();
|
std::vector<field_effect_type*> FieldList{};
|
||||||
|
|
||||||
objlist_class<TEdgeSegment>* EdgeList;
|
|
||||||
objlist_class<field_effect_type>* FieldList;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "maths.h"
|
#include "maths.h"
|
||||||
#include "objlist_class.h"
|
|
||||||
#include "TBall.h"
|
#include "TBall.h"
|
||||||
#include "TEdgeBox.h"
|
#include "TEdgeBox.h"
|
||||||
#include "TEdgeSegment.h"
|
#include "TEdgeSegment.h"
|
||||||
@@ -29,32 +28,32 @@ TEdgeManager::~TEdgeManager()
|
|||||||
|
|
||||||
int TEdgeManager::box_x(float x)
|
int TEdgeManager::box_x(float x)
|
||||||
{
|
{
|
||||||
return static_cast<int>((max(0, min(floor((x - X) * AdvanceXInv), (MaxBoxX - 1)))));
|
return std::max(0, std::min(static_cast<int>(floor((x - X) * AdvanceXInv)), MaxBoxX - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
int TEdgeManager::box_y(float y)
|
int TEdgeManager::box_y(float y)
|
||||||
{
|
{
|
||||||
return static_cast<int>((max(0, min(floor((y - Y) * AdvanceYInv), (MaxBoxY - 1)))));
|
return std::max(0, std::min(static_cast<int>(floor((y - Y) * AdvanceYInv)), MaxBoxY - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
int TEdgeManager::increment_box_x(int x)
|
int TEdgeManager::increment_box_x(int x)
|
||||||
{
|
{
|
||||||
return min(x + 1, MaxBoxX - 1);
|
return std::min(x + 1, MaxBoxX - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int TEdgeManager::increment_box_y(int y)
|
int TEdgeManager::increment_box_y(int y)
|
||||||
{
|
{
|
||||||
return min(y + 1, MaxBoxY - 1);
|
return std::min(y + 1, MaxBoxY - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TEdgeManager::add_edge_to_box(int x, int y, TEdgeSegment* edge)
|
void TEdgeManager::add_edge_to_box(int x, int y, TEdgeSegment* edge)
|
||||||
{
|
{
|
||||||
BoxArray[x + y * MaxBoxX].EdgeList->Add(edge);
|
BoxArray[x + y * MaxBoxX].EdgeList.push_back(edge);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TEdgeManager::add_field_to_box(int x, int y, field_effect_type* field)
|
void TEdgeManager::add_field_to_box(int x, int y, field_effect_type* field)
|
||||||
{
|
{
|
||||||
BoxArray[x + y * MaxBoxX].FieldList->Add(field);
|
BoxArray[x + y * MaxBoxX].FieldList.push_back(field);
|
||||||
}
|
}
|
||||||
|
|
||||||
int TEdgeManager::TestGridBox(int x, int y, float* distPtr, TEdgeSegment** edgeDst, ray_type* ray, TBall* ball,
|
int TEdgeManager::TestGridBox(int x, int y, float* distPtr, TEdgeSegment** edgeDst, ray_type* ray, TBall* ball,
|
||||||
@@ -64,9 +63,9 @@ int TEdgeManager::TestGridBox(int x, int y, float* distPtr, TEdgeSegment** edgeD
|
|||||||
{
|
{
|
||||||
TEdgeBox* edgeBox = &BoxArray[x + y * MaxBoxX];
|
TEdgeBox* edgeBox = &BoxArray[x + y * MaxBoxX];
|
||||||
TEdgeSegment** edgePtr = &EdgeArray[edgeIndex];
|
TEdgeSegment** edgePtr = &EdgeArray[edgeIndex];
|
||||||
for (auto index = edgeBox->EdgeList->GetCount() - 1; index >= 0; --index)
|
for (auto it = edgeBox->EdgeList.rbegin(); it != edgeBox->EdgeList.rend(); ++it)
|
||||||
{
|
{
|
||||||
auto edge = edgeBox->EdgeList->Get(index);
|
auto edge = *it;
|
||||||
if (!edge->ProcessedFlag && *edge->ActiveFlag && (edge->CollisionGroup & ray->FieldFlag))
|
if (!edge->ProcessedFlag && *edge->ActiveFlag && (edge->CollisionGroup & ray->FieldFlag))
|
||||||
{
|
{
|
||||||
if (!ball->already_hit(edge))
|
if (!ball->already_hit(edge))
|
||||||
@@ -94,9 +93,9 @@ void TEdgeManager::FieldEffects(TBall* ball, vector_type* dstVec)
|
|||||||
TEdgeBox* edgeBox = &BoxArray[box_x(ball->Position.X) + box_y(ball->Position.Y) *
|
TEdgeBox* edgeBox = &BoxArray[box_x(ball->Position.X) + box_y(ball->Position.Y) *
|
||||||
MaxBoxX];
|
MaxBoxX];
|
||||||
|
|
||||||
for (int index = edgeBox->FieldList->GetCount() - 1; index >= 0; --index)
|
for (auto it = edgeBox->FieldList.rbegin(); it != edgeBox->FieldList.rend(); ++it)
|
||||||
{
|
{
|
||||||
auto field = edgeBox->FieldList->Get(index);
|
auto field = *it;
|
||||||
if (*field->Flag2Ptr && ball->FieldFlag & field->Mask)
|
if (*field->Flag2Ptr && ball->FieldFlag & field->Mask)
|
||||||
{
|
{
|
||||||
if (field->CollisionComp->FieldEffect(ball, &vec))
|
if (field->CollisionComp->FieldEffect(ball, &vec))
|
||||||
|
|||||||
@@ -35,5 +35,5 @@ public:
|
|||||||
float X;
|
float X;
|
||||||
float Y;
|
float Y;
|
||||||
TEdgeBox* BoxArray;
|
TEdgeBox* BoxArray;
|
||||||
TEdgeSegment* EdgeArray[1000];
|
TEdgeSegment* EdgeArray[1000]{};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "TEdgeSegment.h"
|
#include "TEdgeSegment.h"
|
||||||
|
|
||||||
#include "objlist_class.h"
|
|
||||||
#include "TCircle.h"
|
#include "TCircle.h"
|
||||||
#include "TCollisionComponent.h"
|
#include "TCollisionComponent.h"
|
||||||
#include "TLine.h"
|
#include "TLine.h"
|
||||||
@@ -41,7 +40,7 @@ TEdgeSegment* TEdgeSegment::install_wall(float* floatArr, TCollisionComponent* c
|
|||||||
circle->place_in_grid();
|
circle->place_in_grid();
|
||||||
}
|
}
|
||||||
|
|
||||||
collComp->EdgeList->Add(circle);
|
collComp->EdgeList.push_back(circle);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case wall_type::Line:
|
case wall_type::Line:
|
||||||
@@ -58,7 +57,7 @@ TEdgeSegment* TEdgeSegment::install_wall(float* floatArr, TCollisionComponent* c
|
|||||||
line->WallValue = reinterpret_cast<void*>(wallValue);
|
line->WallValue = reinterpret_cast<void*>(wallValue);
|
||||||
line->Offset(offset);
|
line->Offset(offset);
|
||||||
line->place_in_grid();
|
line->place_in_grid();
|
||||||
collComp->EdgeList->Add(line);
|
collComp->EdgeList.push_back(line);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -94,8 +93,8 @@ TEdgeSegment* TEdgeSegment::install_wall(float* floatArr, TCollisionComponent* c
|
|||||||
vec2.X = centerX2 - centerX1;
|
vec2.X = centerX2 - centerX1;
|
||||||
vec2.Y = centerY2 - center.Y;
|
vec2.Y = centerY2 - center.Y;
|
||||||
maths::cross(&vec1, &vec2, &dstVec);
|
maths::cross(&vec1, &vec2, &dstVec);
|
||||||
if (dstVec.Z > 0.0f && offset > 0.0f ||
|
if ((dstVec.Z > 0.0f && offset > 0.0f) ||
|
||||||
dstVec.Z < 0.0f && offset < 0.0f)
|
(dstVec.Z < 0.0f && offset < 0.0f))
|
||||||
{
|
{
|
||||||
float radius = offset * 1.001f;
|
float radius = offset * 1.001f;
|
||||||
auto circle = new TCircle(collComp, activeFlagPtr, collisionGroup, ¢er, radius);
|
auto circle = new TCircle(collComp, activeFlagPtr, collisionGroup, ¢er, radius);
|
||||||
@@ -104,7 +103,7 @@ TEdgeSegment* TEdgeSegment::install_wall(float* floatArr, TCollisionComponent* c
|
|||||||
{
|
{
|
||||||
circle->WallValue = reinterpret_cast<void*>(wallValue);
|
circle->WallValue = reinterpret_cast<void*>(wallValue);
|
||||||
circle->place_in_grid();
|
circle->place_in_grid();
|
||||||
collComp->EdgeList->Add(circle);
|
collComp->EdgeList.push_back(circle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -121,7 +120,7 @@ TEdgeSegment* TEdgeSegment::install_wall(float* floatArr, TCollisionComponent* c
|
|||||||
line->WallValue = reinterpret_cast<void*>(wallValue);
|
line->WallValue = reinterpret_cast<void*>(wallValue);
|
||||||
line->Offset(offset);
|
line->Offset(offset);
|
||||||
line->place_in_grid();
|
line->place_in_grid();
|
||||||
collComp->EdgeList->Add(line);
|
collComp->EdgeList.push_back(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
prevCenter = center;
|
prevCenter = center;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public:
|
|||||||
TCollisionComponent* CollisionComponent;
|
TCollisionComponent* CollisionComponent;
|
||||||
char* ActiveFlag;
|
char* ActiveFlag;
|
||||||
char ProcessedFlag;
|
char ProcessedFlag;
|
||||||
void* WallValue;
|
void* WallValue{};
|
||||||
unsigned int CollisionGroup;
|
unsigned int CollisionGroup;
|
||||||
|
|
||||||
TEdgeSegment(TCollisionComponent* collComp, char* activeFlag, unsigned int collisionGroup);
|
TEdgeSegment(TCollisionComponent* collComp, char* activeFlag, unsigned int collisionGroup);
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#include "control.h"
|
#include "control.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "objlist_class.h"
|
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "TBall.h"
|
#include "TBall.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
@@ -26,7 +25,7 @@ TFlagSpinner::TFlagSpinner(TPinballTable* table, int groupIndex) : TCollisionCom
|
|||||||
if (line)
|
if (line)
|
||||||
{
|
{
|
||||||
line->place_in_grid();
|
line->place_in_grid();
|
||||||
EdgeList->Add(line);
|
EdgeList.push_back(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
line = new TLine(this, &ActiveFlag, visual.CollisionGroup, &end, &start);
|
line = new TLine(this, &ActiveFlag, visual.CollisionGroup, &end, &start);
|
||||||
@@ -34,7 +33,7 @@ TFlagSpinner::TFlagSpinner(TPinballTable* table, int groupIndex) : TCollisionCom
|
|||||||
if (line)
|
if (line)
|
||||||
{
|
{
|
||||||
line->place_in_grid();
|
line->place_in_grid();
|
||||||
EdgeList->Add(line);
|
EdgeList.push_back(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
SpeedDecrement = 0.64999998f;
|
SpeedDecrement = 0.64999998f;
|
||||||
@@ -61,8 +60,8 @@ int TFlagSpinner::Message(int code, float value)
|
|||||||
Timer = 0;
|
Timer = 0;
|
||||||
}
|
}
|
||||||
BmpIndex = 0;
|
BmpIndex = 0;
|
||||||
auto bmp = ListBitmap->Get(0);
|
auto bmp = ListBitmap->at(0);
|
||||||
auto zMap = ListZMap->Get(0);
|
auto zMap = ListZMap->at(0);
|
||||||
render::sprite_set(
|
render::sprite_set(
|
||||||
RenderSprite,
|
RenderSprite,
|
||||||
bmp,
|
bmp,
|
||||||
@@ -108,7 +107,7 @@ void TFlagSpinner::NextFrame()
|
|||||||
{
|
{
|
||||||
BmpIndex += SpinDirection;
|
BmpIndex += SpinDirection;
|
||||||
int bmpIndex = BmpIndex;
|
int bmpIndex = BmpIndex;
|
||||||
int bmpCount = ListBitmap->GetCount();
|
int bmpCount = ListBitmap->size();
|
||||||
if (bmpIndex >= bmpCount)
|
if (bmpIndex >= bmpCount)
|
||||||
BmpIndex = 0;
|
BmpIndex = 0;
|
||||||
else if (bmpIndex < 0)
|
else if (bmpIndex < 0)
|
||||||
@@ -123,8 +122,8 @@ void TFlagSpinner::NextFrame()
|
|||||||
control::handler(62, this);
|
control::handler(62, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto bmp = ListBitmap->Get(BmpIndex);
|
auto bmp = ListBitmap->at(BmpIndex);
|
||||||
auto zMap = ListZMap->Get(BmpIndex);
|
auto zMap = ListZMap->at(BmpIndex);
|
||||||
render::sprite_set(
|
render::sprite_set(
|
||||||
RenderSprite,
|
RenderSprite,
|
||||||
bmp,
|
bmp,
|
||||||
|
|||||||
@@ -15,14 +15,14 @@ public:
|
|||||||
|
|
||||||
static void SpinTimer(int timerId, void* caller);
|
static void SpinTimer(int timerId, void* caller);
|
||||||
|
|
||||||
float Speed;
|
float Speed{};
|
||||||
float MaxSpeed;
|
float MaxSpeed;
|
||||||
float MinSpeed;
|
float MinSpeed;
|
||||||
float SpeedDecrement;
|
float SpeedDecrement;
|
||||||
int SpinDirection;
|
int SpinDirection{};
|
||||||
int BmpIndex;
|
int BmpIndex{};
|
||||||
int Timer;
|
int Timer;
|
||||||
TEdgeSegment* PrevCollider;
|
TEdgeSegment* PrevCollider;
|
||||||
int Scores[2];
|
int Scores[2]{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -4,11 +4,11 @@
|
|||||||
|
|
||||||
#include "control.h"
|
#include "control.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "objlist_class.h"
|
|
||||||
#include "pb.h"
|
#include "pb.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "TFlipperEdge.h"
|
#include "TFlipperEdge.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
#include "TPinballTable.h"
|
||||||
|
|
||||||
TFlipper::TFlipper(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, false)
|
TFlipper::TFlipper(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, false)
|
||||||
{
|
{
|
||||||
@@ -51,8 +51,8 @@ TFlipper::TFlipper(TPinballTable* table, int groupIndex) : TCollisionComponent(t
|
|||||||
FlipperEdge = flipperEdge;
|
FlipperEdge = flipperEdge;
|
||||||
if (flipperEdge)
|
if (flipperEdge)
|
||||||
{
|
{
|
||||||
ExtendAnimationFrameTime = flipperEdge->ExtendTime / static_cast<float>(ListBitmap->GetCount() - 1);
|
ExtendAnimationFrameTime = flipperEdge->ExtendTime / static_cast<float>(ListBitmap->size() - 1);
|
||||||
RetractAnimationFrameTime = flipperEdge->RetractTime / static_cast<float>(ListBitmap->GetCount() - 1);
|
RetractAnimationFrameTime = flipperEdge->RetractTime / static_cast<float>(ListBitmap->size() - 1);
|
||||||
}
|
}
|
||||||
BmpIndex = 0;
|
BmpIndex = 0;
|
||||||
InputTime = 0.0;
|
InputTime = 0.0;
|
||||||
@@ -65,7 +65,7 @@ TFlipper::~TFlipper()
|
|||||||
|
|
||||||
int TFlipper::Message(int code, float value)
|
int TFlipper::Message(int code, float value)
|
||||||
{
|
{
|
||||||
if (code == 1 || code == 2 || code > 1008 && code <= 1011 || code == 1022)
|
if (code == 1 || code == 2 || (code > 1008 && code <= 1011) || code == 1022)
|
||||||
{
|
{
|
||||||
float timerTime;
|
float timerTime;
|
||||||
int command = code;
|
int command = code;
|
||||||
@@ -135,7 +135,7 @@ void TFlipper::Collision(TBall* ball, vector_type* nextPosition, vector_type* di
|
|||||||
void TFlipper::TimerExpired(int timerId, void* caller)
|
void TFlipper::TimerExpired(int timerId, void* caller)
|
||||||
{
|
{
|
||||||
auto flip = static_cast<TFlipper*>(caller);
|
auto flip = static_cast<TFlipper*>(caller);
|
||||||
int bmpCountSub1 = flip->ListBitmap->GetCount() - 1;
|
int bmpCountSub1 = flip->ListBitmap->size() - 1;
|
||||||
|
|
||||||
auto newBmpIndex = static_cast<int>(floor((pb::time_now - flip->InputTime) / flip->TimerTime));
|
auto newBmpIndex = static_cast<int>(floor((pb::time_now - flip->InputTime) / flip->TimerTime));
|
||||||
if (newBmpIndex > bmpCountSub1)
|
if (newBmpIndex > bmpCountSub1)
|
||||||
@@ -173,8 +173,8 @@ void TFlipper::TimerExpired(int timerId, void* caller)
|
|||||||
flip->Timer = timer::set(flip->TimerTime, flip, TimerExpired);
|
flip->Timer = timer::set(flip->TimerTime, flip, TimerExpired);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto bmp = flip->ListBitmap->Get(flip->BmpIndex);
|
auto bmp = flip->ListBitmap->at(flip->BmpIndex);
|
||||||
auto zMap = flip->ListZMap->Get(flip->BmpIndex);
|
auto zMap = flip->ListZMap->at(flip->BmpIndex);
|
||||||
render::sprite_set(
|
render::sprite_set(
|
||||||
flip->RenderSprite,
|
flip->RenderSprite,
|
||||||
bmp,
|
bmp,
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ public:
|
|||||||
int BmpIndex;
|
int BmpIndex;
|
||||||
TFlipperEdge* FlipperEdge;
|
TFlipperEdge* FlipperEdge;
|
||||||
int Timer;
|
int Timer;
|
||||||
float ExtendAnimationFrameTime;
|
float ExtendAnimationFrameTime{};
|
||||||
float RetractAnimationFrameTime;
|
float RetractAnimationFrameTime{};
|
||||||
float TimerTime;
|
float TimerTime{};
|
||||||
float InputTime;
|
float InputTime;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ TFlipperEdge::TFlipperEdge(TCollisionComponent* collComp, char* activeFlag, unsi
|
|||||||
auto distance1 = sqrt(dy * dy + dx * dx) + table->CollisionCompOffset + vecT1->Z;
|
auto distance1 = sqrt(dy * dy + dx * dx) + table->CollisionCompOffset + vecT1->Z;
|
||||||
DistanceDivSq = distance1 * distance1;
|
DistanceDivSq = distance1 * distance1;
|
||||||
|
|
||||||
float minMoveTime = min(ExtendTime, RetractTime);
|
float minMoveTime = std::min(ExtendTime, RetractTime);
|
||||||
auto distance = maths::Distance(vecT1, vecT2);
|
auto distance = maths::Distance(vecT1, vecT2);
|
||||||
CollisionTimeAdvance = minMoveTime / (distance / CircleT1Radius + distance / CircleT1Radius);
|
CollisionTimeAdvance = minMoveTime / (distance / CircleT1Radius + distance / CircleT1Radius);
|
||||||
|
|
||||||
@@ -109,7 +109,6 @@ float TFlipperEdge::FindCollisionDistance(ray_type* ray)
|
|||||||
{
|
{
|
||||||
if (FlipperFlag == 0)
|
if (FlipperFlag == 0)
|
||||||
{
|
{
|
||||||
EdgeCollisionFlag = 0;
|
|
||||||
CollisionFlag1 = 0;
|
CollisionFlag1 = 0;
|
||||||
CollisionFlag2 = 0;
|
CollisionFlag2 = 0;
|
||||||
set_control_points(ogRay->TimeNow);
|
set_control_points(ogRay->TimeNow);
|
||||||
@@ -428,7 +427,7 @@ float TFlipperEdge::flipper_angle(float timeNow)
|
|||||||
else
|
else
|
||||||
angle = 1.0;
|
angle = 1.0;
|
||||||
|
|
||||||
angle = min(1, max(angle, 0));
|
angle = std::min(1.0f, std::max(angle, 0.0f));
|
||||||
if (FlipperFlag == 2)
|
if (FlipperFlag == 2)
|
||||||
angle = 1.0f - angle;
|
angle = 1.0f - angle;
|
||||||
return angle * AngleMax;
|
return angle * AngleMax;
|
||||||
@@ -439,10 +438,10 @@ int TFlipperEdge::is_ball_inside(float x, float y)
|
|||||||
vector_type testPoint{};
|
vector_type testPoint{};
|
||||||
float dx = RotOrigin.X - x;
|
float dx = RotOrigin.X - x;
|
||||||
float dy = RotOrigin.Y - y;
|
float dy = RotOrigin.Y - y;
|
||||||
if ((A2.X - A1.X) * (y - A1.Y) - (A2.Y - A1.Y) * (x - A1.X) >= 0.0f &&
|
if (((A2.X - A1.X) * (y - A1.Y) - (A2.Y - A1.Y) * (x - A1.X) >= 0.0f &&
|
||||||
(B1.X - A2.X) * (y - A2.Y) - (B1.Y - A2.Y) * (x - A2.X) >= 0.0f &&
|
(B1.X - A2.X) * (y - A2.Y) - (B1.Y - A2.Y) * (x - A2.X) >= 0.0f &&
|
||||||
(B2.X - B1.X) * (y - B1.Y) - (B2.Y - B1.Y) * (x - B1.X) >= 0.0f &&
|
(B2.X - B1.X) * (y - B1.Y) - (B2.Y - B1.Y) * (x - B1.X) >= 0.0f &&
|
||||||
(A1.X - B2.X) * (y - B2.Y) - (A1.Y - B2.Y) * (x - B2.X) >= 0.0f ||
|
(A1.X - B2.X) * (y - B2.Y) - (A1.Y - B2.Y) * (x - B2.X) >= 0.0f) ||
|
||||||
dy * dy + dx * dx <= CirclebaseRadiusSq ||
|
dy * dy + dx * dx <= CirclebaseRadiusSq ||
|
||||||
(T1.Y - y) * (T1.Y - y) + (T1.X - x) * (T1.X - x) < CircleT1RadiusSq)
|
(T1.Y - y) * (T1.Y - y) + (T1.X - x) * (T1.X - x) < CircleT1RadiusSq)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ public:
|
|||||||
int FlipperFlag;
|
int FlipperFlag;
|
||||||
float Elasticity;
|
float Elasticity;
|
||||||
float Smoothness;
|
float Smoothness;
|
||||||
vector_type RotOrigin;
|
vector_type RotOrigin{};
|
||||||
float CirclebaseRadius;
|
float CirclebaseRadius;
|
||||||
float CircleT1Radius;
|
float CircleT1Radius;
|
||||||
float CirclebaseRadiusSq;
|
float CirclebaseRadiusSq;
|
||||||
@@ -31,28 +31,28 @@ public:
|
|||||||
float CirclebaseRadiusMSq;
|
float CirclebaseRadiusMSq;
|
||||||
float CircleT1RadiusMSq;
|
float CircleT1RadiusMSq;
|
||||||
float AngleMax;
|
float AngleMax;
|
||||||
float Angle2;
|
float Angle2{};
|
||||||
float Angle1;
|
float Angle1;
|
||||||
int CollisionFlag1;
|
int CollisionFlag1;
|
||||||
int CollisionFlag2;
|
int CollisionFlag2{};
|
||||||
vector_type CollisionLinePerp;
|
vector_type CollisionLinePerp{};
|
||||||
vector_type A1Src;
|
vector_type A1Src{};
|
||||||
vector_type A2Src;
|
vector_type A2Src{};
|
||||||
vector_type B1Src;
|
vector_type B1Src{};
|
||||||
vector_type B2Src;
|
vector_type B2Src{};
|
||||||
float CollisionMult;
|
float CollisionMult;
|
||||||
vector_type T1Src;
|
vector_type T1Src{};
|
||||||
vector_type T2Src;
|
vector_type T2Src{};
|
||||||
float DistanceDivSq;
|
float DistanceDivSq;
|
||||||
float CollisionTimeAdvance;
|
float CollisionTimeAdvance;
|
||||||
vector_type CollisionDirection;
|
vector_type CollisionDirection{};
|
||||||
int EdgeCollisionFlag;
|
int EdgeCollisionFlag;
|
||||||
float InputTime;
|
float InputTime;
|
||||||
float AngleStopTime;
|
float AngleStopTime;
|
||||||
float AngleMult;
|
float AngleMult;
|
||||||
float ExtendTime;
|
float ExtendTime;
|
||||||
float RetractTime;
|
float RetractTime;
|
||||||
vector_type NextBallPosition;
|
vector_type NextBallPosition{};
|
||||||
|
|
||||||
static float flipper_sin_angle, flipper_cos_angle;
|
static float flipper_sin_angle, flipper_cos_angle;
|
||||||
static vector_type A1, A2, B1, B2, T1;
|
static vector_type A1, A2, B1, B2, T1;
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#include "control.h"
|
#include "control.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "objlist_class.h"
|
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
|
|
||||||
TGate::TGate(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, true)
|
TGate::TGate(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, true)
|
||||||
@@ -15,7 +14,7 @@ TGate::TGate(TPinballTable* table, int groupIndex) : TCollisionComponent(table,
|
|||||||
SoundIndex4 = visual.SoundIndex4;
|
SoundIndex4 = visual.SoundIndex4;
|
||||||
SoundIndex3 = visual.SoundIndex3;
|
SoundIndex3 = visual.SoundIndex3;
|
||||||
ActiveFlag = 1;
|
ActiveFlag = 1;
|
||||||
render::sprite_set_bitmap(RenderSprite, ListBitmap->Get(0));
|
render::sprite_set_bitmap(RenderSprite, ListBitmap->at(0));
|
||||||
control::handler(1024, this);
|
control::handler(1024, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,7 +31,7 @@ int TGate::Message(int code, float value)
|
|||||||
else if (code == 54 || code == 1024)
|
else if (code == 54 || code == 1024)
|
||||||
{
|
{
|
||||||
ActiveFlag = 1;
|
ActiveFlag = 1;
|
||||||
render::sprite_set_bitmap(RenderSprite, ListBitmap->Get(0));
|
render::sprite_set_bitmap(RenderSprite, ListBitmap->at(0));
|
||||||
if (code == 54)
|
if (code == 54)
|
||||||
loader::play_sound(SoundIndex4);
|
loader::play_sound(SoundIndex4);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#include "control.h"
|
#include "control.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "objlist_class.h"
|
|
||||||
#include "pb.h"
|
#include "pb.h"
|
||||||
#include "TBall.h"
|
#include "TBall.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
@@ -37,7 +36,7 @@ THole::THole(TPinballTable* table, int groupIndex) : TCollisionComponent(table,
|
|||||||
if (tCircle)
|
if (tCircle)
|
||||||
{
|
{
|
||||||
tCircle->place_in_grid();
|
tCircle->place_in_grid();
|
||||||
EdgeList->Add(tCircle);
|
EdgeList.push_back(tCircle);
|
||||||
}
|
}
|
||||||
|
|
||||||
ZSetValue = loader::query_float_attribute(groupIndex, 0, 408)[2];
|
ZSetValue = loader::query_float_attribute(groupIndex, 0, 408)[2];
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public:
|
|||||||
static void TimerExpired(int timerId, void* caller);
|
static void TimerExpired(int timerId, void* caller);
|
||||||
|
|
||||||
int BallCapturedFlag;
|
int BallCapturedFlag;
|
||||||
int BallCapturedSecondStage;
|
int BallCapturedSecondStage{};
|
||||||
int Timer;
|
int Timer;
|
||||||
float Unknown3;
|
float Unknown3;
|
||||||
float Unknown4;
|
float Unknown4;
|
||||||
@@ -24,6 +24,6 @@ public:
|
|||||||
float ZSetValue;
|
float ZSetValue;
|
||||||
int FieldFlag;
|
int FieldFlag;
|
||||||
float GravityPull;
|
float GravityPull;
|
||||||
circle_type Circle;
|
circle_type Circle{};
|
||||||
field_effect_type Field;
|
field_effect_type Field{};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
#include "control.h"
|
#include "control.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "maths.h"
|
#include "maths.h"
|
||||||
#include "objlist_class.h"
|
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "TPinballTable.h"
|
#include "TPinballTable.h"
|
||||||
@@ -14,8 +13,8 @@ TKickback::TKickback(TPinballTable* table, int groupIndex): TCollisionComponent(
|
|||||||
{
|
{
|
||||||
MessageField = 0;
|
MessageField = 0;
|
||||||
Timer = 0;
|
Timer = 0;
|
||||||
ActiveFlag = 0;
|
KickActiveFlag = 0;
|
||||||
TimerTime = 0.69999999f;
|
TimerTime = 0.7f;
|
||||||
TimerTime2 = 0.1f;
|
TimerTime2 = 0.1f;
|
||||||
Threshold = 1000000000.0f;
|
Threshold = 1000000000.0f;
|
||||||
}
|
}
|
||||||
@@ -28,7 +27,7 @@ int TKickback::Message(int code, float value)
|
|||||||
if (ListBitmap)
|
if (ListBitmap)
|
||||||
render::sprite_set_bitmap(RenderSprite, nullptr);
|
render::sprite_set_bitmap(RenderSprite, nullptr);
|
||||||
Timer = 0;
|
Timer = 0;
|
||||||
ActiveFlag = 0;
|
KickActiveFlag = 0;
|
||||||
Threshold = 1000000000.0;
|
Threshold = 1000000000.0;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -44,14 +43,14 @@ void TKickback::Collision(TBall* ball, vector_type* nextPosition, vector_type* d
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!ActiveFlag)
|
if (!KickActiveFlag)
|
||||||
{
|
{
|
||||||
Threshold = 1000000000.0;
|
Threshold = 1000000000.0;
|
||||||
ActiveFlag = 1;
|
KickActiveFlag = 1;
|
||||||
Timer = timer::set(TimerTime, this, TimerExpired);
|
Timer = timer::set(TimerTime, this, TimerExpired);
|
||||||
}
|
}
|
||||||
if (DefaultCollision(ball, nextPosition, direction))
|
if (DefaultCollision(ball, nextPosition, direction))
|
||||||
ActiveFlag = 0;
|
KickActiveFlag = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,15 +58,15 @@ void TKickback::TimerExpired(int timerId, void* caller)
|
|||||||
{
|
{
|
||||||
auto kick = static_cast<TKickback*>(caller);
|
auto kick = static_cast<TKickback*>(caller);
|
||||||
|
|
||||||
if (kick->ActiveFlag)
|
if (kick->KickActiveFlag)
|
||||||
{
|
{
|
||||||
kick->Threshold = 0.0;
|
kick->Threshold = 0.0;
|
||||||
kick->Timer = timer::set(kick->TimerTime2, kick, TimerExpired);
|
kick->Timer = timer::set(kick->TimerTime2, kick, TimerExpired);
|
||||||
loader::play_sound(kick->HardHitSoundId);
|
loader::play_sound(kick->HardHitSoundId);
|
||||||
if (kick->ListBitmap)
|
if (kick->ListBitmap)
|
||||||
{
|
{
|
||||||
auto bmp = kick->ListBitmap->Get(1);
|
auto bmp = kick->ListBitmap->at(1);
|
||||||
auto zMap = kick->ListZMap->Get(1);
|
auto zMap = kick->ListZMap->at(1);
|
||||||
render::sprite_set(
|
render::sprite_set(
|
||||||
kick->RenderSprite,
|
kick->RenderSprite,
|
||||||
bmp,
|
bmp,
|
||||||
@@ -80,8 +79,8 @@ void TKickback::TimerExpired(int timerId, void* caller)
|
|||||||
{
|
{
|
||||||
if (kick->ListBitmap)
|
if (kick->ListBitmap)
|
||||||
{
|
{
|
||||||
auto bmp = kick->ListBitmap->Get(0);
|
auto bmp = kick->ListBitmap->at(0);
|
||||||
auto zMap = kick->ListZMap->Get(0);
|
auto zMap = kick->ListZMap->at(0);
|
||||||
render::sprite_set(
|
render::sprite_set(
|
||||||
kick->RenderSprite,
|
kick->RenderSprite,
|
||||||
bmp,
|
bmp,
|
||||||
|
|||||||
@@ -15,5 +15,5 @@ public:
|
|||||||
float TimerTime;
|
float TimerTime;
|
||||||
float TimerTime2;
|
float TimerTime2;
|
||||||
int Timer;
|
int Timer;
|
||||||
int ActiveFlag;
|
int KickActiveFlag;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#include "control.h"
|
#include "control.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "objlist_class.h"
|
|
||||||
#include "pb.h"
|
#include "pb.h"
|
||||||
#include "TBall.h"
|
#include "TBall.h"
|
||||||
#include "TCircle.h"
|
#include "TCircle.h"
|
||||||
@@ -41,7 +40,7 @@ TKickout::TKickout(TPinballTable* table, int groupIndex, bool someFlag): TCollis
|
|||||||
if (tCircle)
|
if (tCircle)
|
||||||
{
|
{
|
||||||
tCircle->place_in_grid();
|
tCircle->place_in_grid();
|
||||||
EdgeList->Add(tCircle);
|
EdgeList.push_back(tCircle);
|
||||||
}
|
}
|
||||||
|
|
||||||
Circle.RadiusSq = visual.FloatArr[2] * visual.FloatArr[2];
|
Circle.RadiusSq = visual.FloatArr[2] * visual.FloatArr[2];
|
||||||
|
|||||||
@@ -24,14 +24,14 @@ public:
|
|||||||
float TimerTime1;
|
float TimerTime1;
|
||||||
float TimerTime2;
|
float TimerTime2;
|
||||||
float CollisionBallSetZ;
|
float CollisionBallSetZ;
|
||||||
TBall* Ball;
|
TBall* Ball{};
|
||||||
float FieldMult;
|
float FieldMult;
|
||||||
circle_type Circle;
|
circle_type Circle{};
|
||||||
float OriginalBallZ;
|
float OriginalBallZ{};
|
||||||
vector_type BallAcceleration;
|
vector_type BallAcceleration{};
|
||||||
float ThrowAngleMult;
|
float ThrowAngleMult;
|
||||||
float ThrowSpeedMult1;
|
float ThrowSpeedMult1;
|
||||||
float ThrowSpeedMult2;
|
float ThrowSpeedMult2;
|
||||||
field_effect_type Field;
|
field_effect_type Field{};
|
||||||
int Scores[5];
|
int Scores[5]{};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#include "control.h"
|
#include "control.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "objlist_class.h"
|
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "TPinballTable.h"
|
#include "TPinballTable.h"
|
||||||
@@ -143,14 +142,14 @@ int TLight::Message(int code, float value)
|
|||||||
schedule_timeout(value);
|
schedule_timeout(value);
|
||||||
break;
|
break;
|
||||||
case 11:
|
case 11:
|
||||||
BmpIndex2 = static_cast<int>(floor(value));
|
|
||||||
if (BmpIndex2 > ListBitmap->GetCount())
|
|
||||||
BmpIndex2 = ListBitmap->GetCount();
|
|
||||||
bmpIndex = 0;
|
bmpIndex = 0;
|
||||||
|
BmpIndex2 = static_cast<int>(floor(value));
|
||||||
|
if (BmpIndex2 > static_cast<int>(ListBitmap->size()))
|
||||||
|
BmpIndex2 = ListBitmap->size();
|
||||||
if (BmpIndex2 < 0)
|
if (BmpIndex2 < 0)
|
||||||
BmpIndex2 = 0;
|
BmpIndex2 = 0;
|
||||||
Flasher.BmpArr[0] = nullptr;
|
Flasher.BmpArr[0] = nullptr;
|
||||||
Flasher.BmpArr[1] = ListBitmap->Get(BmpIndex2);
|
Flasher.BmpArr[1] = ListBitmap->at(BmpIndex2);
|
||||||
if (FlasherActive == 0)
|
if (FlasherActive == 0)
|
||||||
{
|
{
|
||||||
if (!FlasherFlag1)
|
if (!FlasherFlag1)
|
||||||
@@ -169,8 +168,8 @@ int TLight::Message(int code, float value)
|
|||||||
break;
|
break;
|
||||||
case 12:
|
case 12:
|
||||||
bmpIndex = BmpIndex2 + 1;
|
bmpIndex = BmpIndex2 + 1;
|
||||||
if (bmpIndex > ListBitmap->GetCount())
|
if (bmpIndex > static_cast<int>(ListBitmap->size()))
|
||||||
bmpIndex = ListBitmap->GetCount();
|
bmpIndex = ListBitmap->size();
|
||||||
Message(11, static_cast<float>(bmpIndex));
|
Message(11, static_cast<float>(bmpIndex));
|
||||||
break;
|
break;
|
||||||
case 13:
|
case 13:
|
||||||
@@ -257,7 +256,7 @@ void TLight::Reset()
|
|||||||
Flasher.Sprite = RenderSprite;
|
Flasher.Sprite = RenderSprite;
|
||||||
Flasher.BmpArr[0] = nullptr;
|
Flasher.BmpArr[0] = nullptr;
|
||||||
if (ListBitmap)
|
if (ListBitmap)
|
||||||
Flasher.BmpArr[1] = ListBitmap->Get(0);
|
Flasher.BmpArr[1] = ListBitmap->at(0);
|
||||||
Flasher.Unknown4 = 0;
|
Flasher.Unknown4 = 0;
|
||||||
Flasher.Unknown3 = 0;
|
Flasher.Unknown3 = 0;
|
||||||
MessageField = 0;
|
MessageField = 0;
|
||||||
|
|||||||
@@ -40,17 +40,16 @@ public:
|
|||||||
static void flasher_start(struct flasher_type* flash, int bmpIndex);
|
static void flasher_start(struct flasher_type* flash, int bmpIndex);
|
||||||
static void flasher_callback(int timerId, void* caller);
|
static void flasher_callback(int timerId, void* caller);
|
||||||
|
|
||||||
flasher_type Flasher;
|
flasher_type Flasher{};
|
||||||
int BmpIndex1;
|
int BmpIndex1{};
|
||||||
int FlasherActive;
|
int FlasherActive;
|
||||||
int FlasherFlag1;
|
int FlasherFlag1{};
|
||||||
int FlasherFlag2;
|
int FlasherFlag2{};
|
||||||
int TurnOffAfterFlashingFg;
|
int TurnOffAfterFlashingFg{};
|
||||||
int BmpIndex2;
|
int BmpIndex2{};
|
||||||
float FlasherDelay[2];
|
float FlasherDelay[2]{};
|
||||||
int Timer1;
|
int Timer1;
|
||||||
int Timer2;
|
int Timer2;
|
||||||
int Unknown19;
|
float Unknown20F{};
|
||||||
float Unknown20F;
|
TLight_player_backup PlayerData[4]{};
|
||||||
TLight_player_backup PlayerData[4];
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,8 +4,6 @@
|
|||||||
|
|
||||||
#include "control.h"
|
#include "control.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "memory.h"
|
|
||||||
#include "objlist_class.h"
|
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "TPinballTable.h"
|
#include "TPinballTable.h"
|
||||||
|
|
||||||
@@ -18,11 +16,11 @@ TLightBargraph::TLightBargraph(TPinballTable* table, int groupIndex) : TLightGro
|
|||||||
float* floatArr = loader::query_float_attribute(groupIndex, 0, 904);
|
float* floatArr = loader::query_float_attribute(groupIndex, 0, 904);
|
||||||
if (floatArr)
|
if (floatArr)
|
||||||
{
|
{
|
||||||
int count = 2 * List->GetCount();
|
auto count = 2 * List.size();
|
||||||
TimerTimeArray = memory::allocate<float>(count);
|
TimerTimeArray = new float[count];
|
||||||
if (TimerTimeArray)
|
if (TimerTimeArray)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < count; ++floatArr)
|
for (auto i = 0u; i < count; ++floatArr)
|
||||||
TimerTimeArray[i++] = *floatArr;
|
TimerTimeArray[i++] = *floatArr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -31,8 +29,7 @@ TLightBargraph::TLightBargraph(TPinballTable* table, int groupIndex) : TLightGro
|
|||||||
|
|
||||||
TLightBargraph::~TLightBargraph()
|
TLightBargraph::~TLightBargraph()
|
||||||
{
|
{
|
||||||
if (TimerTimeArray)
|
delete[] TimerTimeArray;
|
||||||
memory::free(TimerTimeArray);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int TLightBargraph::Message(int code, float value)
|
int TLightBargraph::Message(int code, float value)
|
||||||
@@ -49,7 +46,7 @@ int TLightBargraph::Message(int code, float value)
|
|||||||
TimerBargraph = 0;
|
TimerBargraph = 0;
|
||||||
}
|
}
|
||||||
auto timeIndex = static_cast<int>(floor(value));
|
auto timeIndex = static_cast<int>(floor(value));
|
||||||
auto maxCount = 2 * List->GetCount();
|
auto maxCount = static_cast<int>(List.size()) * 2;
|
||||||
if (timeIndex >= maxCount)
|
if (timeIndex >= maxCount)
|
||||||
timeIndex = maxCount - 1;
|
timeIndex = maxCount - 1;
|
||||||
if (timeIndex >= 0)
|
if (timeIndex >= 0)
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public:
|
|||||||
static void BargraphTimerExpired(int timerId, void* caller);
|
static void BargraphTimerExpired(int timerId, void* caller);
|
||||||
|
|
||||||
float* TimerTimeArray;
|
float* TimerTimeArray;
|
||||||
int TimerBargraph;
|
int TimerBargraph{};
|
||||||
int TimeIndex;
|
int TimeIndex{};
|
||||||
int PlayerTimerIndexBackup[4];
|
int PlayerTimerIndexBackup[4]{};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,17 +4,15 @@
|
|||||||
|
|
||||||
#include "control.h"
|
#include "control.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "objlist_class.h"
|
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "TLight.h"
|
#include "TLight.h"
|
||||||
#include "TPinballTable.h"
|
#include "TPinballTable.h"
|
||||||
|
|
||||||
TLightGroup::TLightGroup(TPinballTable* table, int groupIndex) : TPinballComponent(table, groupIndex, false)
|
TLightGroup::TLightGroup(TPinballTable* table, int groupIndex) : TPinballComponent(table, groupIndex, false)
|
||||||
{
|
{
|
||||||
List = new objlist_class<TLight>(4, 4);
|
|
||||||
Timer = 0;
|
Timer = 0;
|
||||||
NotifyTimer = 0;
|
NotifyTimer = 0;
|
||||||
Reset();
|
TLightGroup::Reset();
|
||||||
if (groupIndex > 0)
|
if (groupIndex > 0)
|
||||||
{
|
{
|
||||||
int count;
|
int count;
|
||||||
@@ -24,19 +22,15 @@ TLightGroup::TLightGroup(TPinballTable* table, int groupIndex) : TPinballCompone
|
|||||||
{
|
{
|
||||||
auto comp = dynamic_cast<TLight*>(table->find_component(*groupIndArr));
|
auto comp = dynamic_cast<TLight*>(table->find_component(*groupIndArr));
|
||||||
if (comp)
|
if (comp)
|
||||||
List->Add(comp);
|
List.push_back(comp);
|
||||||
++index;
|
++index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TLightGroup::~TLightGroup()
|
|
||||||
{
|
|
||||||
delete List;
|
|
||||||
}
|
|
||||||
|
|
||||||
int TLightGroup::Message(int code, float value)
|
int TLightGroup::Message(int code, float value)
|
||||||
{
|
{
|
||||||
|
auto const count = static_cast<int>(List.size());
|
||||||
switch (code)
|
switch (code)
|
||||||
{
|
{
|
||||||
case 1011:
|
case 1011:
|
||||||
@@ -71,8 +65,7 @@ int TLightGroup::Message(int code, float value)
|
|||||||
break;
|
break;
|
||||||
case 24:
|
case 24:
|
||||||
{
|
{
|
||||||
auto count = List->GetCount();
|
auto lastLight = List.at(count - 1);
|
||||||
auto lastLight = List->Get(count - 1);
|
|
||||||
if (lastLight->FlasherActive || lastLight->FlasherFlag2 || lastLight->FlasherFlag1)
|
if (lastLight->FlasherActive || lastLight->FlasherFlag2 || lastLight->FlasherFlag1)
|
||||||
break;
|
break;
|
||||||
if (MessageField2)
|
if (MessageField2)
|
||||||
@@ -85,12 +78,12 @@ int TLightGroup::Message(int code, float value)
|
|||||||
auto bmpIndex1 = lastLight->BmpIndex1;
|
auto bmpIndex1 = lastLight->BmpIndex1;
|
||||||
for (auto index = count - 1; index > 0; --index)
|
for (auto index = count - 1; index > 0; --index)
|
||||||
{
|
{
|
||||||
auto lightCur = List->Get(index);
|
auto lightCur = List.at(index);
|
||||||
auto lightPrev = List->Get(index - 1);
|
auto lightPrev = List.at(index - 1);
|
||||||
lightCur->Message(lightPrev->BmpIndex1 != 0, 0.0);
|
lightCur->Message(lightPrev->BmpIndex1 != 0, 0.0);
|
||||||
lightCur->MessageField = lightPrev->MessageField;
|
lightCur->MessageField = lightPrev->MessageField;
|
||||||
}
|
}
|
||||||
auto firstLight = List->Get(0);
|
auto firstLight = List.at(0);
|
||||||
firstLight->Message(bmpIndex1 != 0, 0.0);
|
firstLight->Message(bmpIndex1 != 0, 0.0);
|
||||||
firstLight->MessageField = lightMessageField;
|
firstLight->MessageField = lightMessageField;
|
||||||
reschedule_animation(value);
|
reschedule_animation(value);
|
||||||
@@ -98,23 +91,22 @@ int TLightGroup::Message(int code, float value)
|
|||||||
}
|
}
|
||||||
case 25:
|
case 25:
|
||||||
{
|
{
|
||||||
auto count = List->GetCount();
|
auto lastLight = List.at(count - 1);
|
||||||
auto lastLight = List->Get(count - 1);
|
|
||||||
if (lastLight->FlasherActive || lastLight->FlasherFlag2 || lastLight->FlasherFlag1)
|
if (lastLight->FlasherActive || lastLight->FlasherFlag2 || lastLight->FlasherFlag1)
|
||||||
break;
|
break;
|
||||||
if (MessageField2)
|
if (MessageField2)
|
||||||
{
|
{
|
||||||
TLightGroup::Message(34, 0.0);
|
TLightGroup::Message(34, 0.0);
|
||||||
}
|
}
|
||||||
auto firstLight = List->Get(0);
|
auto firstLight = List.at(0);
|
||||||
AnimationFlag = 1;
|
AnimationFlag = 1;
|
||||||
MessageField2 = code;
|
MessageField2 = code;
|
||||||
auto lightMessageField = firstLight->MessageField;
|
auto lightMessageField = firstLight->MessageField;
|
||||||
auto bmpIndex1 = firstLight->BmpIndex1;
|
auto bmpIndex1 = firstLight->BmpIndex1;
|
||||||
for (auto index = 0; index < count - 1; index++)
|
for (auto index = 0; index < count - 1; index++)
|
||||||
{
|
{
|
||||||
auto lightCur = List->Get(index);
|
auto lightCur = List.at(index);
|
||||||
auto lightNext = List->Get(index + 1);
|
auto lightNext = List.at(index + 1);
|
||||||
lightCur->Message(lightNext->BmpIndex1 != 0, 0.0);
|
lightCur->Message(lightNext->BmpIndex1 != 0, 0.0);
|
||||||
lightCur->MessageField = lightNext->MessageField;
|
lightCur->MessageField = lightNext->MessageField;
|
||||||
}
|
}
|
||||||
@@ -129,16 +121,15 @@ int TLightGroup::Message(int code, float value)
|
|||||||
start_animation();
|
start_animation();
|
||||||
MessageField2 = code;
|
MessageField2 = code;
|
||||||
AnimationFlag = 0;
|
AnimationFlag = 0;
|
||||||
auto count = List->GetCount();
|
auto lastLight = List.at(count - 1);
|
||||||
auto lastLight = List->Get(count - 1);
|
|
||||||
auto flasherFlag2 = lastLight->FlasherFlag2;
|
auto flasherFlag2 = lastLight->FlasherFlag2;
|
||||||
for (auto i = count - 1; i > 0; --i)
|
for (auto i = count - 1; i > 0; --i)
|
||||||
{
|
{
|
||||||
auto lightCur = List->Get(i);
|
auto lightCur = List.at(i);
|
||||||
auto lightPrev = List->Get(i - 1);
|
auto lightPrev = List.at(i - 1);
|
||||||
lightCur->Message((lightPrev->FlasherFlag2 != 0) + 8, 0.0);
|
lightCur->Message((lightPrev->FlasherFlag2 != 0) + 8, 0.0);
|
||||||
}
|
}
|
||||||
auto firstLight = List->Get(0);
|
auto firstLight = List.at(0);
|
||||||
firstLight->Message((flasherFlag2 != 0) + 8, 0);
|
firstLight->Message((flasherFlag2 != 0) + 8, 0);
|
||||||
reschedule_animation(value);
|
reschedule_animation(value);
|
||||||
break;
|
break;
|
||||||
@@ -149,16 +140,15 @@ int TLightGroup::Message(int code, float value)
|
|||||||
start_animation();
|
start_animation();
|
||||||
MessageField2 = code;
|
MessageField2 = code;
|
||||||
AnimationFlag = 0;
|
AnimationFlag = 0;
|
||||||
auto count = List->GetCount();
|
auto firstLight = List.at(0);
|
||||||
auto firstLight = List->Get(0);
|
|
||||||
auto flasherFlag2 = firstLight->FlasherFlag2;
|
auto flasherFlag2 = firstLight->FlasherFlag2;
|
||||||
for (auto i = 0; i < count - 1; i++)
|
for (auto i = 0; i < count - 1; i++)
|
||||||
{
|
{
|
||||||
auto lightCur = List->Get(i);
|
auto lightCur = List.at(i);
|
||||||
auto lightNext = List->Get(i + 1);
|
auto lightNext = List.at(i + 1);
|
||||||
lightCur->Message((lightNext->FlasherFlag2 != 0) + 8, 0.0);
|
lightCur->Message((lightNext->FlasherFlag2 != 0) + 8, 0.0);
|
||||||
}
|
}
|
||||||
auto lastLight = List->Get(count - 1);
|
auto lastLight = List.at(count - 1);
|
||||||
lastLight->Message((flasherFlag2 != 0) + 8, 0);
|
lastLight->Message((flasherFlag2 != 0) + 8, 0);
|
||||||
reschedule_animation(value);
|
reschedule_animation(value);
|
||||||
break;
|
break;
|
||||||
@@ -169,13 +159,11 @@ int TLightGroup::Message(int code, float value)
|
|||||||
start_animation();
|
start_animation();
|
||||||
MessageField2 = code;
|
MessageField2 = code;
|
||||||
AnimationFlag = 0;
|
AnimationFlag = 0;
|
||||||
auto count = List->GetCount();
|
for (auto light : List)
|
||||||
for (auto i = 0; i < count - 1; i++)
|
|
||||||
{
|
{
|
||||||
if (rand() % 100 > 70)
|
if (rand() % 100 > 70)
|
||||||
{
|
{
|
||||||
auto light = List->Get(i);
|
auto randVal = RandFloat() * value * 3.0f + 0.1f;
|
||||||
auto randVal = static_cast<float>(rand()) * 0.00003051850947599719f * value * 3.0f + 0.1f;
|
|
||||||
light->Message(9, randVal);
|
light->Message(9, randVal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -188,10 +176,8 @@ int TLightGroup::Message(int code, float value)
|
|||||||
start_animation();
|
start_animation();
|
||||||
MessageField2 = code;
|
MessageField2 = code;
|
||||||
AnimationFlag = 0;
|
AnimationFlag = 0;
|
||||||
auto count = List->GetCount();
|
for (auto light : List)
|
||||||
for (auto i = 0; i < count - 1; i++)
|
|
||||||
{
|
{
|
||||||
auto light = List->Get(i);
|
|
||||||
auto randVal = static_cast<float>(rand() % 100 > 70);
|
auto randVal = static_cast<float>(rand() % 100 > 70);
|
||||||
light->Message(18, randVal);
|
light->Message(18, randVal);
|
||||||
}
|
}
|
||||||
@@ -201,22 +187,18 @@ int TLightGroup::Message(int code, float value)
|
|||||||
case 30:
|
case 30:
|
||||||
{
|
{
|
||||||
auto noBmpInd1Count = 0;
|
auto noBmpInd1Count = 0;
|
||||||
auto countSub1 = List->GetCount() - 1;
|
for (auto light : List)
|
||||||
if (countSub1 < 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
for (auto i = countSub1; i >= 0; i--)
|
|
||||||
{
|
{
|
||||||
if (!List->Get(i)->BmpIndex1)
|
if (!light->BmpIndex1)
|
||||||
++noBmpInd1Count;
|
++noBmpInd1Count;
|
||||||
}
|
}
|
||||||
if (!noBmpInd1Count)
|
if (!noBmpInd1Count)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
auto randModCount = rand() % noBmpInd1Count;
|
auto randModCount = rand() % noBmpInd1Count;
|
||||||
for (auto i = countSub1; i >= 0; i--)
|
for (auto it = List.rbegin(); it != List.rend(); ++it)
|
||||||
{
|
{
|
||||||
auto light = List->Get(i);
|
auto light = *it;
|
||||||
if (!light->BmpIndex1 && randModCount-- == 0)
|
if (!light->BmpIndex1 && randModCount-- == 0)
|
||||||
{
|
{
|
||||||
light->Message(1, 0.0);
|
light->Message(1, 0.0);
|
||||||
@@ -231,22 +213,18 @@ int TLightGroup::Message(int code, float value)
|
|||||||
case 31:
|
case 31:
|
||||||
{
|
{
|
||||||
auto bmpInd1Count = 0;
|
auto bmpInd1Count = 0;
|
||||||
auto countSub1 = List->GetCount() - 1;
|
for (auto light : List)
|
||||||
if (countSub1 < 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
for (auto i = countSub1; i >= 0; i--)
|
|
||||||
{
|
{
|
||||||
if (List->Get(i)->BmpIndex1)
|
if (light->BmpIndex1)
|
||||||
++bmpInd1Count;
|
++bmpInd1Count;
|
||||||
}
|
}
|
||||||
if (!bmpInd1Count)
|
if (!bmpInd1Count)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
auto randModCount = rand() % bmpInd1Count;
|
auto randModCount = rand() % bmpInd1Count;
|
||||||
for (auto i = countSub1; i >= 0; i--)
|
for (auto it = List.rbegin(); it != List.rend(); ++it)
|
||||||
{
|
{
|
||||||
auto light = List->Get(i);
|
auto light = *it;
|
||||||
if (light->BmpIndex1 && randModCount-- == 0)
|
if (light->BmpIndex1 && randModCount-- == 0)
|
||||||
{
|
{
|
||||||
light->Message(0, 0.0);
|
light->Message(0, 0.0);
|
||||||
@@ -263,7 +241,7 @@ int TLightGroup::Message(int code, float value)
|
|||||||
auto index = next_light_up();
|
auto index = next_light_up();
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
break;
|
break;
|
||||||
List->Get(index)->Message(1, 0.0);
|
List.at(index)->Message(1, 0.0);
|
||||||
if (MessageField2)
|
if (MessageField2)
|
||||||
start_animation();
|
start_animation();
|
||||||
return 1;
|
return 1;
|
||||||
@@ -273,7 +251,7 @@ int TLightGroup::Message(int code, float value)
|
|||||||
auto index = next_light_down();
|
auto index = next_light_down();
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
break;
|
break;
|
||||||
List->Get(index)->Message(0, 0.0);
|
List.at(index)->Message(0, 0.0);
|
||||||
if (MessageField2)
|
if (MessageField2)
|
||||||
start_animation();
|
start_animation();
|
||||||
return 1;
|
return 1;
|
||||||
@@ -292,10 +270,10 @@ int TLightGroup::Message(int code, float value)
|
|||||||
case 35:
|
case 35:
|
||||||
{
|
{
|
||||||
auto index = static_cast<int>(floor(value));
|
auto index = static_cast<int>(floor(value));
|
||||||
if (index >= List->GetCount() || index < 0)
|
if (index >= count || index < 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
auto light = List->Get(index);
|
auto light = List.at(index);
|
||||||
light->Message(1, 0.0);
|
light->Message(1, 0.0);
|
||||||
if (MessageField2)
|
if (MessageField2)
|
||||||
start_animation();
|
start_animation();
|
||||||
@@ -304,10 +282,10 @@ int TLightGroup::Message(int code, float value)
|
|||||||
case 36:
|
case 36:
|
||||||
{
|
{
|
||||||
auto index = static_cast<int>(floor(value));
|
auto index = static_cast<int>(floor(value));
|
||||||
if (index >= List->GetCount() || index < 0)
|
if (index >= count || index < 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
auto light = List->Get(index);
|
auto light = List.at(index);
|
||||||
light->Message(0, 0.0);
|
light->Message(0, 0.0);
|
||||||
if (MessageField2)
|
if (MessageField2)
|
||||||
start_animation();
|
start_animation();
|
||||||
@@ -316,16 +294,15 @@ int TLightGroup::Message(int code, float value)
|
|||||||
case 37:
|
case 37:
|
||||||
{
|
{
|
||||||
auto bmp1Count = 0;
|
auto bmp1Count = 0;
|
||||||
auto countSub1 = List->GetCount() - 1;
|
for (auto light : List)
|
||||||
for (auto i = countSub1; i >= 0; i--)
|
|
||||||
{
|
{
|
||||||
if (List->Get(i)->BmpIndex1)
|
if (light->BmpIndex1)
|
||||||
++bmp1Count;
|
++bmp1Count;
|
||||||
}
|
}
|
||||||
return bmp1Count;
|
return bmp1Count;
|
||||||
}
|
}
|
||||||
case 38:
|
case 38:
|
||||||
return List->GetCount();
|
return count;
|
||||||
case 39:
|
case 39:
|
||||||
return MessageField2;
|
return MessageField2;
|
||||||
case 40:
|
case 40:
|
||||||
@@ -337,7 +314,7 @@ int TLightGroup::Message(int code, float value)
|
|||||||
break;
|
break;
|
||||||
if (MessageField2 || AnimationFlag)
|
if (MessageField2 || AnimationFlag)
|
||||||
TLightGroup::Message(34, 0.0);
|
TLightGroup::Message(34, 0.0);
|
||||||
List->Get(index)->Message(15, value);
|
List.at(index)->Message(15, value);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
case 42:
|
case 42:
|
||||||
@@ -347,7 +324,7 @@ int TLightGroup::Message(int code, float value)
|
|||||||
break;
|
break;
|
||||||
if (MessageField2 || AnimationFlag)
|
if (MessageField2 || AnimationFlag)
|
||||||
TLightGroup::Message(34, 0.0);
|
TLightGroup::Message(34, 0.0);
|
||||||
List->Get(index)->Message(16, value);
|
List.at(index)->Message(16, value);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
case 43:
|
case 43:
|
||||||
@@ -359,10 +336,9 @@ int TLightGroup::Message(int code, float value)
|
|||||||
break;
|
break;
|
||||||
case 44:
|
case 44:
|
||||||
{
|
{
|
||||||
auto countSub1 = List->GetCount() - 1;
|
for (auto it = List.rbegin(); it != List.rend(); ++it)
|
||||||
for (auto index = countSub1; index >= 0; index--)
|
|
||||||
{
|
{
|
||||||
auto light = List->Get(index);
|
auto light = *it;
|
||||||
if (light->BmpIndex1)
|
if (light->BmpIndex1)
|
||||||
{
|
{
|
||||||
light->Message(0, 0.0);
|
light->Message(0, 0.0);
|
||||||
@@ -374,7 +350,6 @@ int TLightGroup::Message(int code, float value)
|
|||||||
}
|
}
|
||||||
case 45:
|
case 45:
|
||||||
{
|
{
|
||||||
auto count = List->GetCount();
|
|
||||||
control::handler(code, this);
|
control::handler(code, this);
|
||||||
auto index = static_cast<int>(floor(value));
|
auto index = static_cast<int>(floor(value));
|
||||||
if (index >= 0 && index < count)
|
if (index >= 0 && index < count)
|
||||||
@@ -382,13 +357,13 @@ int TLightGroup::Message(int code, float value)
|
|||||||
// Turn off lights (index, end]
|
// Turn off lights (index, end]
|
||||||
for (auto i = count - 1; i > index; i--)
|
for (auto i = count - 1; i > index; i--)
|
||||||
{
|
{
|
||||||
List->Get(i)->Message(20, 0.0);
|
List.at(i)->Message(20, 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Turn on lights [begin, index]
|
// Turn on lights [begin, index]
|
||||||
for (auto i = index; i >= 0; i--)
|
for (auto i = index; i >= 0; i--)
|
||||||
{
|
{
|
||||||
List->Get(i)->Message(19, 0.0);
|
List.at(i)->Message(19, 0.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -398,14 +373,14 @@ int TLightGroup::Message(int code, float value)
|
|||||||
auto index = next_light_down();
|
auto index = next_light_down();
|
||||||
if (index >= 0)
|
if (index >= 0)
|
||||||
{
|
{
|
||||||
List->Get(index)->Message(4, 0.0);
|
List.at(index)->Message(4, 0.0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
for (auto index = List->GetCount() - 1; index >= 0; index--)
|
for (auto it = List.rbegin(); it != List.rend(); ++it)
|
||||||
{
|
{
|
||||||
List->Get(index)->Message(code, value);
|
(*it)->Message(code, value);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -443,9 +418,9 @@ void TLightGroup::reschedule_animation(float time)
|
|||||||
|
|
||||||
void TLightGroup::start_animation()
|
void TLightGroup::start_animation()
|
||||||
{
|
{
|
||||||
for (int index = List->GetCount() - 1; index >= 0; --index)
|
for (auto it = List.rbegin(); it != List.rend(); ++it)
|
||||||
{
|
{
|
||||||
auto light = List->Get(index);
|
auto light = *it;
|
||||||
if (light->BmpIndex1)
|
if (light->BmpIndex1)
|
||||||
light->Message(9, 0.0);
|
light->Message(9, 0.0);
|
||||||
else
|
else
|
||||||
@@ -455,19 +430,19 @@ void TLightGroup::start_animation()
|
|||||||
|
|
||||||
int TLightGroup::next_light_up()
|
int TLightGroup::next_light_up()
|
||||||
{
|
{
|
||||||
for (int index = 0; index < List->GetCount(); ++index)
|
for (auto index = 0u; index < List.size(); ++index)
|
||||||
{
|
{
|
||||||
if (!List->Get(index)->BmpIndex1)
|
if (!List[index]->BmpIndex1)
|
||||||
return index;
|
return static_cast<int>(index);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int TLightGroup::next_light_down()
|
int TLightGroup::next_light_down()
|
||||||
{
|
{
|
||||||
for (int index = List->GetCount() - 1; index >= 0; --index)
|
for (auto index = static_cast<int>(List.size()) - 1; index >= 0; --index)
|
||||||
{
|
{
|
||||||
if (List->Get(index)->BmpIndex1)
|
if (List.at(index)->BmpIndex1)
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ class TLightGroup :
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TLightGroup(TPinballTable* table, int groupIndex);
|
TLightGroup(TPinballTable* table, int groupIndex);
|
||||||
~TLightGroup() override;
|
~TLightGroup() override = default;
|
||||||
int Message(int code, float value) override;
|
int Message(int code, float value) override;
|
||||||
virtual void Reset();
|
virtual void Reset();
|
||||||
void reschedule_animation(float time);
|
void reschedule_animation(float time);
|
||||||
@@ -29,12 +29,12 @@ public:
|
|||||||
static void TimerExpired(int timerId, void* caller);
|
static void TimerExpired(int timerId, void* caller);
|
||||||
static void NotifyTimerExpired(int timerId, void* caller);
|
static void NotifyTimerExpired(int timerId, void* caller);
|
||||||
|
|
||||||
objlist_class<TLight>* List;
|
std::vector<TLight*> List;
|
||||||
float Timer1Time;
|
float Timer1Time{};
|
||||||
float Timer1TimeDefault;
|
float Timer1TimeDefault;
|
||||||
int MessageField2;
|
int MessageField2{};
|
||||||
int AnimationFlag;
|
int AnimationFlag{};
|
||||||
int NotifyTimer;
|
int NotifyTimer;
|
||||||
int Timer;
|
int Timer;
|
||||||
TLightGroup_player_backup PlayerData[4];
|
TLightGroup_player_backup PlayerData[4]{};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#include "control.h"
|
#include "control.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "objlist_class.h"
|
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "TBall.h"
|
#include "TBall.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
@@ -58,7 +57,7 @@ void TLightRollover::Collision(TBall* ball, vector_type* nextPosition, vector_ty
|
|||||||
control::handler(63, this);
|
control::handler(63, this);
|
||||||
RolloverFlag = RolloverFlag == 0;
|
RolloverFlag = RolloverFlag == 0;
|
||||||
if (ListBitmap)
|
if (ListBitmap)
|
||||||
render::sprite_set_bitmap(RenderSprite, ListBitmap->Get(0));
|
render::sprite_set_bitmap(RenderSprite, ListBitmap->at(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ class TLine :
|
|||||||
public TEdgeSegment
|
public TEdgeSegment
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
line_type Line;
|
line_type Line{};
|
||||||
float X0, Y0, X1, Y1;
|
float X0, Y0, X1, Y1;
|
||||||
TLine(TCollisionComponent* collCmp, char* activeFlag, unsigned int collisionGroup, float x0, float y0, float x1, float y1);
|
TLine(TCollisionComponent* collCmp, char* activeFlag, unsigned int collisionGroup, float x0, float y0, float x1, float y1);
|
||||||
TLine(TCollisionComponent* collCmp, char* activeFlag, unsigned int collisionGroup, vector_type* start, vector_type* end);
|
TLine(TCollisionComponent* collCmp, char* activeFlag, unsigned int collisionGroup, vector_type* start, vector_type* end);
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#include "control.h"
|
#include "control.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "objlist_class.h"
|
|
||||||
#include "TBall.h"
|
#include "TBall.h"
|
||||||
#include "TLine.h"
|
#include "TLine.h"
|
||||||
#include "TPinballTable.h"
|
#include "TPinballTable.h"
|
||||||
@@ -27,7 +26,7 @@ TOneway::TOneway(TPinballTable* table, int groupIndex) : TCollisionComponent(tab
|
|||||||
{
|
{
|
||||||
line->Offset(table->CollisionCompOffset);
|
line->Offset(table->CollisionCompOffset);
|
||||||
line->place_in_grid();
|
line->place_in_grid();
|
||||||
EdgeList->Add(line);
|
EdgeList.push_back(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
line = new TLine(this, &ActiveFlag, visual.CollisionGroup, &linePt1, &linePt2);
|
line = new TLine(this, &ActiveFlag, visual.CollisionGroup, &linePt1, &linePt2);
|
||||||
@@ -36,7 +35,7 @@ TOneway::TOneway(TPinballTable* table, int groupIndex) : TCollisionComponent(tab
|
|||||||
{
|
{
|
||||||
line->Offset(-table->CollisionCompOffset * 0.8f);
|
line->Offset(-table->CollisionCompOffset * 0.8f);
|
||||||
Line->place_in_grid();
|
Line->place_in_grid();
|
||||||
EdgeList->Add(Line);
|
EdgeList.push_back(Line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,5 +14,5 @@ public:
|
|||||||
int get_scoring(int index) override;
|
int get_scoring(int index) override;
|
||||||
|
|
||||||
TLine* Line;
|
TLine* Line;
|
||||||
int Scores[6];
|
int Scores[6]{};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "TPinballComponent.h"
|
#include "TPinballComponent.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "objlist_class.h"
|
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "TPinballTable.h"
|
#include "TPinballTable.h"
|
||||||
|
|
||||||
@@ -19,7 +18,7 @@ TPinballComponent::TPinballComponent(TPinballTable* table, int groupIndex, bool
|
|||||||
GroupName = nullptr;
|
GroupName = nullptr;
|
||||||
Control = nullptr;
|
Control = nullptr;
|
||||||
if (table)
|
if (table)
|
||||||
table->ComponentList->Add(this);
|
table->ComponentList.push_back(this);
|
||||||
if (groupIndex >= 0)
|
if (groupIndex >= 0)
|
||||||
GroupName = loader::query_name(groupIndex);
|
GroupName = loader::query_name(groupIndex);
|
||||||
if (loadVisuals && groupIndex >= 0)
|
if (loadVisuals && groupIndex >= 0)
|
||||||
@@ -31,45 +30,31 @@ TPinballComponent::TPinballComponent(TPinballTable* table, int groupIndex, bool
|
|||||||
if (visual.Bitmap)
|
if (visual.Bitmap)
|
||||||
{
|
{
|
||||||
if (!ListBitmap)
|
if (!ListBitmap)
|
||||||
ListBitmap = new objlist_class<gdrv_bitmap8>(visualCount, 4);
|
ListBitmap = new std::vector<gdrv_bitmap8*>();
|
||||||
if (ListBitmap)
|
if (ListBitmap)
|
||||||
ListBitmap->Add(visual.Bitmap);
|
ListBitmap->push_back(visual.Bitmap);
|
||||||
}
|
}
|
||||||
if (visual.ZMap)
|
if (visual.ZMap)
|
||||||
{
|
{
|
||||||
if (!ListZMap)
|
if (!ListZMap)
|
||||||
ListZMap = new objlist_class<zmap_header_type>(visualCount, 4);
|
ListZMap = new std::vector<zmap_header_type*>();
|
||||||
if (ListZMap)
|
if (ListZMap)
|
||||||
ListZMap->Add(visual.ZMap);
|
ListZMap->push_back(visual.ZMap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
zmap_header_type* zMap = nullptr;
|
|
||||||
if (ListZMap)
|
auto zMap = ListZMap ? ListZMap->at(0) : nullptr;
|
||||||
zMap = ListZMap->Get(0);
|
|
||||||
if (ListBitmap)
|
if (ListBitmap)
|
||||||
{
|
{
|
||||||
/* Full tilt hack - spliced bitmap includes zMap
|
|
||||||
* Users access bitmap-zMap in pairs, pad zMap list with 0 for such users
|
|
||||||
* zdrv does not access zMap when drawing spliced bitmap*/
|
|
||||||
if (!ListZMap)
|
|
||||||
{
|
|
||||||
ListZMap = new objlist_class<zmap_header_type>(0, 4);
|
|
||||||
for (int index = 0; index < ListBitmap->GetCount(); index++)
|
|
||||||
{
|
|
||||||
assertm(ListBitmap->Get(index)->BitmapType == BitmapType::Spliced, "Wrong zMap padding");
|
|
||||||
ListZMap->Add(visual.ZMap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rectangle_type bmp1Rect{}, tmpRect{};
|
rectangle_type bmp1Rect{}, tmpRect{};
|
||||||
auto rootBmp = ListBitmap->Get(0);
|
auto rootBmp = ListBitmap->at(0);
|
||||||
bmp1Rect.XPosition = rootBmp->XPosition - table->XOffset;
|
bmp1Rect.XPosition = rootBmp->XPosition - table->XOffset;
|
||||||
bmp1Rect.YPosition = rootBmp->YPosition - table->YOffset;
|
bmp1Rect.YPosition = rootBmp->YPosition - table->YOffset;
|
||||||
bmp1Rect.Width = rootBmp->Width;
|
bmp1Rect.Width = rootBmp->Width;
|
||||||
bmp1Rect.Height = rootBmp->Height;
|
bmp1Rect.Height = rootBmp->Height;
|
||||||
for (int index = 1; index < ListBitmap->GetCount(); index++)
|
for (auto index = 1u; index < ListBitmap->size(); index++)
|
||||||
{
|
{
|
||||||
auto bmp = ListBitmap->Get(index);
|
auto bmp = ListBitmap->at(index);
|
||||||
tmpRect.XPosition = bmp->XPosition - table->XOffset;
|
tmpRect.XPosition = bmp->XPosition - table->XOffset;
|
||||||
tmpRect.YPosition = bmp->YPosition - table->YOffset;
|
tmpRect.YPosition = bmp->YPosition - table->YOffset;
|
||||||
tmpRect.Width = bmp->Width;
|
tmpRect.Width = bmp->Width;
|
||||||
@@ -78,7 +63,7 @@ TPinballComponent::TPinballComponent(TPinballTable* table, int groupIndex, bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
RenderSprite = render::create_sprite(
|
RenderSprite = render::create_sprite(
|
||||||
visualCount > 0 ? VisualType::Sprite : VisualType::None,
|
visualCount > 0 ? VisualTypes::Sprite : VisualTypes::None,
|
||||||
rootBmp,
|
rootBmp,
|
||||||
zMap,
|
zMap,
|
||||||
rootBmp->XPosition - table->XOffset,
|
rootBmp->XPosition - table->XOffset,
|
||||||
@@ -92,9 +77,14 @@ TPinballComponent::TPinballComponent(TPinballTable* table, int groupIndex, bool
|
|||||||
|
|
||||||
TPinballComponent::~TPinballComponent()
|
TPinballComponent::~TPinballComponent()
|
||||||
{
|
{
|
||||||
TPinballTable* table = PinballTable;
|
if (PinballTable)
|
||||||
if (table)
|
{
|
||||||
table->ComponentList->Delete(this);
|
// ComponentList contains one reference to each component.
|
||||||
|
auto& components = PinballTable->ComponentList;
|
||||||
|
auto position = std::find(components.begin(), components.end(), this);
|
||||||
|
if (position != components.end())
|
||||||
|
components.erase(position);
|
||||||
|
}
|
||||||
|
|
||||||
delete ListBitmap;
|
delete ListBitmap;
|
||||||
delete ListZMap;
|
delete ListZMap;
|
||||||
@@ -121,13 +111,3 @@ int TPinballComponent::get_scoring(int index)
|
|||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* TPinballComponent::operator new(size_t Size)
|
|
||||||
{
|
|
||||||
return calloc(1u, Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TPinballComponent::operator delete(void* p)
|
|
||||||
{
|
|
||||||
free(p); /*Original does not have this*/
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "objlist_class.h"
|
|
||||||
|
|
||||||
struct zmap_header_type;
|
struct zmap_header_type;
|
||||||
struct gdrv_bitmap8;
|
struct gdrv_bitmap8;
|
||||||
@@ -25,18 +24,14 @@ public:
|
|||||||
virtual void put_scoring(int index, int score);
|
virtual void put_scoring(int index, int score);
|
||||||
virtual int get_scoring(int index);
|
virtual int get_scoring(int index);
|
||||||
|
|
||||||
void* operator new(size_t Size);
|
|
||||||
void operator delete(void* p);
|
|
||||||
|
|
||||||
char UnusedBaseFlag;
|
char UnusedBaseFlag;
|
||||||
char ActiveFlag;
|
char ActiveFlag;
|
||||||
int MessageField;
|
int MessageField;
|
||||||
char* GroupName;
|
char* GroupName;
|
||||||
int Unknown4;
|
|
||||||
component_control* Control;
|
component_control* Control;
|
||||||
int GroupIndex;
|
int GroupIndex;
|
||||||
render_sprite_type_struct* RenderSprite;
|
render_sprite_type_struct* RenderSprite;
|
||||||
TPinballTable* PinballTable;
|
TPinballTable* PinballTable;
|
||||||
objlist_class<gdrv_bitmap8>* ListBitmap;
|
std::vector<gdrv_bitmap8*>* ListBitmap;
|
||||||
objlist_class<zmap_header_type>* ListZMap;
|
std::vector<zmap_header_type*>* ListZMap;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,12 +4,9 @@
|
|||||||
|
|
||||||
#include "control.h"
|
#include "control.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "memory.h"
|
|
||||||
#include "objlist_class.h"
|
|
||||||
#include "pb.h"
|
#include "pb.h"
|
||||||
#include "pinball.h"
|
#include "pinball.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "Sound.h"
|
|
||||||
#include "TBall.h"
|
#include "TBall.h"
|
||||||
#include "TBlocker.h"
|
#include "TBlocker.h"
|
||||||
#include "TBumper.h"
|
#include "TBumper.h"
|
||||||
@@ -48,8 +45,6 @@ TPinballTable::TPinballTable(): TPinballComponent(nullptr, -1, false)
|
|||||||
{
|
{
|
||||||
int shortArrLength;
|
int shortArrLength;
|
||||||
|
|
||||||
ComponentList = new objlist_class<TPinballComponent>(32, 16);
|
|
||||||
BallList = new objlist_class<TBall>(3, 1);
|
|
||||||
CurScoreStruct = nullptr;
|
CurScoreStruct = nullptr;
|
||||||
ScoreBallcount = nullptr;
|
ScoreBallcount = nullptr;
|
||||||
ScorePlayerNumber1 = nullptr;
|
ScorePlayerNumber1 = nullptr;
|
||||||
@@ -64,7 +59,7 @@ TPinballTable::TPinballTable(): TPinballComponent(nullptr, -1, false)
|
|||||||
PlayerCount = 0;
|
PlayerCount = 0;
|
||||||
|
|
||||||
auto ballObj = new TBall(this);
|
auto ballObj = new TBall(this);
|
||||||
BallList->Add(ballObj);
|
BallList.push_back(ballObj);
|
||||||
if (ballObj)
|
if (ballObj)
|
||||||
ballObj->ActiveFlag = 0;
|
ballObj->ActiveFlag = 0;
|
||||||
new TTableLayer(this);
|
new TTableLayer(this);
|
||||||
@@ -103,7 +98,7 @@ TPinballTable::TPinballTable(): TPinballComponent(nullptr, -1, false)
|
|||||||
Plunger = new TPlunger(this, groupIndex);
|
Plunger = new TPlunger(this, groupIndex);
|
||||||
break;
|
break;
|
||||||
case 1002:
|
case 1002:
|
||||||
LightGroup->List->Add(new TLight(this, groupIndex));
|
LightGroup->List.push_back(new TLight(this, groupIndex));
|
||||||
break;
|
break;
|
||||||
case 1003:
|
case 1003:
|
||||||
FlipperL = new TFlipper(this, groupIndex);
|
FlipperL = new TFlipper(this, groupIndex);
|
||||||
@@ -198,63 +193,55 @@ TPinballTable::TPinballTable(): TPinballComponent(nullptr, -1, false)
|
|||||||
|
|
||||||
TPinballTable::~TPinballTable()
|
TPinballTable::~TPinballTable()
|
||||||
{
|
{
|
||||||
for (int scoreIndex = 0; scoreIndex < 4; scoreIndex++)
|
for (auto& PlayerScore : PlayerScores)
|
||||||
{
|
{
|
||||||
memory::free(PlayerScores[scoreIndex].ScoreStruct);
|
delete PlayerScore.ScoreStruct;
|
||||||
}
|
}
|
||||||
if (ScorePlayerNumber1)
|
if (ScorePlayerNumber1)
|
||||||
{
|
{
|
||||||
memory::free(ScorePlayerNumber1);
|
delete ScorePlayerNumber1;
|
||||||
ScorePlayerNumber1 = nullptr;
|
ScorePlayerNumber1 = nullptr;
|
||||||
}
|
}
|
||||||
if (ScoreBallcount)
|
if (ScoreBallcount)
|
||||||
{
|
{
|
||||||
memory::free(ScoreBallcount);
|
delete ScoreBallcount;
|
||||||
ScoreBallcount = nullptr;
|
ScoreBallcount = nullptr;
|
||||||
}
|
}
|
||||||
delete LightGroup;
|
delete LightGroup;
|
||||||
while (ComponentList->GetCount() > 0)
|
while (!ComponentList.empty())
|
||||||
{
|
{
|
||||||
delete ComponentList->Get(0);
|
// Component destructor removes it from the list.
|
||||||
|
delete ComponentList[0];
|
||||||
}
|
}
|
||||||
delete BallList;
|
control::ClearLinks();
|
||||||
delete ComponentList;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TPinballComponent* TPinballTable::find_component(LPCSTR componentName)
|
TPinballComponent* TPinballTable::find_component(LPCSTR componentName)
|
||||||
{
|
{
|
||||||
int objCount = ComponentList->GetCount();
|
for (auto component : ComponentList)
|
||||||
if (objCount > 0)
|
|
||||||
{
|
{
|
||||||
for (int index = 0; index < objCount; ++index)
|
const char* groupName = component->GroupName;
|
||||||
|
if (groupName && !strcmp(groupName, componentName))
|
||||||
{
|
{
|
||||||
TPinballComponent* obj = ComponentList->Get(index);
|
return component;
|
||||||
const CHAR* groupName = obj->GroupName;
|
|
||||||
if (groupName && !lstrcmpA(groupName, componentName))
|
|
||||||
{
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MessageBoxA(nullptr, "Table cant find:", componentName, 0x2000u);
|
|
||||||
|
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_WARNING, "Table cant find:", componentName, nullptr);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
TPinballComponent* TPinballTable::find_component(int groupIndex)
|
TPinballComponent* TPinballTable::find_component(int groupIndex)
|
||||||
{
|
{
|
||||||
char Buffer[40]{};
|
char Buffer[40]{};
|
||||||
int objCount = ComponentList->GetCount();
|
for (auto component : ComponentList)
|
||||||
if (objCount > 0)
|
|
||||||
{
|
{
|
||||||
for (int index = 0; index < objCount; ++index)
|
if (component->GroupIndex == groupIndex)
|
||||||
{
|
return component;
|
||||||
TPinballComponent* obj = ComponentList->Get(index);
|
|
||||||
if (obj->GroupIndex == groupIndex)
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_itoa_s(groupIndex, Buffer, 10);
|
|
||||||
MessageBoxA(nullptr, "Table cant find (lh):", Buffer, 0x2000u);
|
snprintf(Buffer, sizeof Buffer, "%d", groupIndex);
|
||||||
|
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_WARNING, "Table cant find (lh):", Buffer, nullptr);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -303,13 +290,13 @@ void TPinballTable::tilt(float time)
|
|||||||
{
|
{
|
||||||
pinball::InfoTextBox->Clear();
|
pinball::InfoTextBox->Clear();
|
||||||
pinball::MissTextBox->Clear();
|
pinball::MissTextBox->Clear();
|
||||||
pinball::InfoTextBox->Display(pinball::get_rc_Wstring(35, 0), -1.0);
|
pinball::InfoTextBox->Display(pinball::get_rc_string(35, 0), -1.0);
|
||||||
loader::play_sound(SoundIndex3);
|
loader::play_sound(SoundIndex3);
|
||||||
TiltTimeoutTimer = timer::set(30.0, this, tilt_timeout);
|
TiltTimeoutTimer = timer::set(30.0, this, tilt_timeout);
|
||||||
|
|
||||||
for (int i = 0; i < ComponentList->GetCount(); i++)
|
for (auto component : ComponentList)
|
||||||
{
|
{
|
||||||
ComponentList->Get(i)->Message(1011, time);
|
component->Message(1011, time);
|
||||||
}
|
}
|
||||||
LightGroup->Message(8, 0);
|
LightGroup->Message(8, 0);
|
||||||
TiltLockFlag = 1;
|
TiltLockFlag = 1;
|
||||||
@@ -320,15 +307,15 @@ void TPinballTable::tilt(float time)
|
|||||||
|
|
||||||
void TPinballTable::port_draw()
|
void TPinballTable::port_draw()
|
||||||
{
|
{
|
||||||
for (int index = ComponentList->GetCount() - 1; index >= 0; index--)
|
for (auto component : ComponentList)
|
||||||
{
|
{
|
||||||
ComponentList->Get(index)->port_draw();
|
component->port_draw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int TPinballTable::Message(int code, float value)
|
int TPinballTable::Message(int code, float value)
|
||||||
{
|
{
|
||||||
LPWSTR rc_text;
|
LPSTR rc_text;
|
||||||
switch (code)
|
switch (code)
|
||||||
{
|
{
|
||||||
case 1000:
|
case 1000:
|
||||||
@@ -362,9 +349,9 @@ int TPinballTable::Message(int code, float value)
|
|||||||
case 1008:
|
case 1008:
|
||||||
case 1009:
|
case 1009:
|
||||||
case 1010:
|
case 1010:
|
||||||
for (int i = 0; i < ComponentList->GetCount(); i++)
|
for (auto component : ComponentList)
|
||||||
{
|
{
|
||||||
ComponentList->Get(i)->Message(code, value);
|
component->Message(code, value);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1012:
|
case 1012:
|
||||||
@@ -381,10 +368,10 @@ int TPinballTable::Message(int code, float value)
|
|||||||
LightGroup->Message(34, 0.0);
|
LightGroup->Message(34, 0.0);
|
||||||
LightGroup->Message(20, 0.0);
|
LightGroup->Message(20, 0.0);
|
||||||
Plunger->Message(1016, 0.0);
|
Plunger->Message(1016, 0.0);
|
||||||
if (Demo->ActiveFlag)
|
if (Demo && Demo->ActiveFlag)
|
||||||
rc_text = pinball::get_rc_Wstring(30, 0);
|
rc_text = pinball::get_rc_string(30, 0);
|
||||||
else
|
else
|
||||||
rc_text = pinball::get_rc_Wstring(26, 0);
|
rc_text = pinball::get_rc_string(26, 0);
|
||||||
pinball::InfoTextBox->Display(rc_text, -1.0);
|
pinball::InfoTextBox->Display(rc_text, -1.0);
|
||||||
if (Demo)
|
if (Demo)
|
||||||
Demo->Message(1014, 0.0);
|
Demo->Message(1014, 0.0);
|
||||||
@@ -406,7 +393,7 @@ int TPinballTable::Message(int code, float value)
|
|||||||
{
|
{
|
||||||
CheatsUsed = 0;
|
CheatsUsed = 0;
|
||||||
Message(1024, 0.0);
|
Message(1024, 0.0);
|
||||||
auto ball = BallList->Get(0);
|
auto ball = BallList[0];
|
||||||
ball->Position.Y = 0.0;
|
ball->Position.Y = 0.0;
|
||||||
ball->Position.X = 0.0;
|
ball->Position.X = 0.0;
|
||||||
ball->Position.Z = -0.8f;
|
ball->Position.Z = -0.8f;
|
||||||
@@ -443,25 +430,20 @@ int TPinballTable::Message(int code, float value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
BallCount = MaxBallCount;
|
BallCount = MaxBallCount;
|
||||||
Sound::Idle();
|
|
||||||
ChangeBallCount(BallCount);
|
ChangeBallCount(BallCount);
|
||||||
score::set(ScorePlayerNumber1, CurrentPlayer + 1);
|
score::set(ScorePlayerNumber1, CurrentPlayer + 1);
|
||||||
score::update(ScorePlayerNumber1);
|
score::update(ScorePlayerNumber1);
|
||||||
Sound::Idle();
|
|
||||||
|
|
||||||
for (auto scoreIndex = 4 - PlayerCount; scoreIndex > 0; scoreIndex--)
|
for (auto scoreIndex = 4 - PlayerCount; scoreIndex > 0; scoreIndex--)
|
||||||
{
|
{
|
||||||
score::set(PlayerScores[scoreIndex].ScoreStruct, -1);
|
score::set(PlayerScores[scoreIndex].ScoreStruct, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Sound::Idle();
|
|
||||||
ScoreSpecial3Flag = 0;
|
ScoreSpecial3Flag = 0;
|
||||||
ScoreSpecial2Flag = 0;
|
ScoreSpecial2Flag = 0;
|
||||||
UnknownP71 = 0;
|
UnknownP71 = 0;
|
||||||
pinball::InfoTextBox->Clear();
|
pinball::InfoTextBox->Clear();
|
||||||
Sound::Idle();
|
|
||||||
pinball::MissTextBox->Clear();
|
pinball::MissTextBox->Clear();
|
||||||
Sound::Idle();
|
|
||||||
LightGroup->Message(28, 0.2f);
|
LightGroup->Message(28, 0.2f);
|
||||||
auto time = loader::play_sound(SoundIndex1);
|
auto time = loader::play_sound(SoundIndex1);
|
||||||
LightShowTimer = timer::set(time, this, LightShow_timeout);
|
LightShowTimer = timer::set(time, this, LightShow_timeout);
|
||||||
@@ -477,11 +459,11 @@ int TPinballTable::Message(int code, float value)
|
|||||||
{
|
{
|
||||||
if (PlayerCount <= 1)
|
if (PlayerCount <= 1)
|
||||||
{
|
{
|
||||||
wchar_t* textboxText;
|
char* textboxText;
|
||||||
if (Demo->ActiveFlag)
|
if (Demo->ActiveFlag)
|
||||||
textboxText = pinball::get_rc_Wstring(30, 0);
|
textboxText = pinball::get_rc_string(30, 0);
|
||||||
else
|
else
|
||||||
textboxText = pinball::get_rc_Wstring(26, 0);
|
textboxText = pinball::get_rc_string(26, 0);
|
||||||
pinball::InfoTextBox->Display(textboxText, -1.0);
|
pinball::InfoTextBox->Display(textboxText, -1.0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -513,37 +495,37 @@ int TPinballTable::Message(int code, float value)
|
|||||||
score::set(ScorePlayerNumber1, nextPlayer + 1);
|
score::set(ScorePlayerNumber1, nextPlayer + 1);
|
||||||
score::update(ScorePlayerNumber1);
|
score::update(ScorePlayerNumber1);
|
||||||
|
|
||||||
for (int i = 0; i < ComponentList->GetCount(); i++)
|
for (auto component : ComponentList)
|
||||||
{
|
{
|
||||||
ComponentList->Get(i)->Message(1020, static_cast<float>(nextPlayer));
|
component->Message(1020, static_cast<float>(nextPlayer));
|
||||||
}
|
}
|
||||||
|
|
||||||
wchar_t* textboxText = nullptr;
|
char* textboxText = nullptr;
|
||||||
switch (nextPlayer)
|
switch (nextPlayer)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
if (Demo->ActiveFlag)
|
if (Demo->ActiveFlag)
|
||||||
textboxText = pinball::get_rc_Wstring(30, 0);
|
textboxText = pinball::get_rc_string(30, 0);
|
||||||
else
|
else
|
||||||
textboxText = pinball::get_rc_Wstring(26, 0);
|
textboxText = pinball::get_rc_string(26, 0);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if (Demo->ActiveFlag)
|
if (Demo->ActiveFlag)
|
||||||
textboxText = pinball::get_rc_Wstring(31, 0);
|
textboxText = pinball::get_rc_string(31, 0);
|
||||||
else
|
else
|
||||||
textboxText = pinball::get_rc_Wstring(27, 0);
|
textboxText = pinball::get_rc_string(27, 0);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
if (Demo->ActiveFlag)
|
if (Demo->ActiveFlag)
|
||||||
textboxText = pinball::get_rc_Wstring(32, 0);
|
textboxText = pinball::get_rc_string(32, 0);
|
||||||
else
|
else
|
||||||
textboxText = pinball::get_rc_Wstring(28, 0);
|
textboxText = pinball::get_rc_string(28, 0);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
if (Demo->ActiveFlag)
|
if (Demo->ActiveFlag)
|
||||||
textboxText = pinball::get_rc_Wstring(33, 0);
|
textboxText = pinball::get_rc_string(33, 0);
|
||||||
else
|
else
|
||||||
textboxText = pinball::get_rc_Wstring(29, 0);
|
textboxText = pinball::get_rc_string(29, 0);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -560,13 +542,13 @@ int TPinballTable::Message(int code, float value)
|
|||||||
case 1022:
|
case 1022:
|
||||||
loader::play_sound(SoundIndex2);
|
loader::play_sound(SoundIndex2);
|
||||||
pinball::MissTextBox->Clear();
|
pinball::MissTextBox->Clear();
|
||||||
pinball::InfoTextBox->Display(pinball::get_rc_Wstring(34, 0), -1.0);
|
pinball::InfoTextBox->Display(pinball::get_rc_string(34, 0), -1.0);
|
||||||
EndGameTimeoutTimer = timer::set(3.0, this, EndGame_timeout);
|
EndGameTimeoutTimer = timer::set(3.0, this, EndGame_timeout);
|
||||||
break;
|
break;
|
||||||
case 1024:
|
case 1024:
|
||||||
for (int i = 0; i < ComponentList->GetCount(); i++)
|
for (auto component : ComponentList)
|
||||||
{
|
{
|
||||||
ComponentList->Get(i)->Message(1024, 0);
|
component->Message(1024, 0);
|
||||||
}
|
}
|
||||||
if (ReplayTimer)
|
if (ReplayTimer)
|
||||||
timer::kill(ReplayTimer);
|
timer::kill(ReplayTimer);
|
||||||
@@ -608,14 +590,14 @@ void TPinballTable::EndGame_timeout(int timerId, void* caller)
|
|||||||
table->EndGameTimeoutTimer = 0;
|
table->EndGameTimeoutTimer = 0;
|
||||||
pb::end_game();
|
pb::end_game();
|
||||||
|
|
||||||
for (int i = 0; i < table->ComponentList->GetCount(); i++)
|
for (auto component : table->ComponentList)
|
||||||
{
|
{
|
||||||
table->ComponentList->Get(i)->Message(1022, 0);
|
component->Message(1022, 0);
|
||||||
}
|
}
|
||||||
if (table->Demo)
|
if (table->Demo)
|
||||||
table->Demo->Message(1022, 0.0);
|
table->Demo->Message(1022, 0.0);
|
||||||
control::handler(67, pinball::MissTextBox);
|
control::handler(67, pinball::MissTextBox);
|
||||||
pinball::InfoTextBox->Display(pinball::get_rc_Wstring(24, 0), -1.0);
|
pinball::InfoTextBox->Display(pinball::get_rc_string(24, 0), -1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TPinballTable::LightShow_timeout(int timerId, void* caller)
|
void TPinballTable::LightShow_timeout(int timerId, void* caller)
|
||||||
@@ -640,9 +622,9 @@ void TPinballTable::tilt_timeout(int timerId, void* caller)
|
|||||||
table->TiltTimeoutTimer = 0;
|
table->TiltTimeoutTimer = 0;
|
||||||
if (table->TiltLockFlag)
|
if (table->TiltLockFlag)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < table->BallList->GetCount(); i++)
|
for (auto ball : table->BallList)
|
||||||
{
|
{
|
||||||
table->Drain->Collision(table->BallList->Get(i), &vec, &vec, 0.0, nullptr);
|
table->Drain->Collision(ball, &vec, &vec, 0.0, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,54 +45,54 @@ public:
|
|||||||
scoreStruct* CurScoreStruct;
|
scoreStruct* CurScoreStruct;
|
||||||
scoreStruct* ScoreBallcount;
|
scoreStruct* ScoreBallcount;
|
||||||
scoreStruct* ScorePlayerNumber1;
|
scoreStruct* ScorePlayerNumber1;
|
||||||
int CheatsUsed;
|
int CheatsUsed{};
|
||||||
int SoundIndex1;
|
int SoundIndex1{};
|
||||||
int SoundIndex2;
|
int SoundIndex2{};
|
||||||
int SoundIndex3;
|
int SoundIndex3{};
|
||||||
int BallInSink;
|
int BallInSink;
|
||||||
int CurScore;
|
int CurScore{};
|
||||||
int CurScoreE9;
|
int CurScoreE9{};
|
||||||
int LightShowTimer;
|
int LightShowTimer;
|
||||||
int EndGameTimeoutTimer;
|
int EndGameTimeoutTimer;
|
||||||
int TiltTimeoutTimer;
|
int TiltTimeoutTimer;
|
||||||
score_struct_super PlayerScores[4];
|
score_struct_super PlayerScores[4]{};
|
||||||
int PlayerCount;
|
int PlayerCount;
|
||||||
int CurrentPlayer;
|
int CurrentPlayer;
|
||||||
TPlunger* Plunger;
|
TPlunger* Plunger;
|
||||||
TDrain* Drain;
|
TDrain* Drain;
|
||||||
TDemo* Demo;
|
TDemo* Demo{};
|
||||||
int XOffset;
|
int XOffset{};
|
||||||
int YOffset;
|
int YOffset{};
|
||||||
int Width;
|
int Width{};
|
||||||
int Height;
|
int Height{};
|
||||||
objlist_class<TPinballComponent>* ComponentList;
|
std::vector<TPinballComponent*> ComponentList;
|
||||||
objlist_class<TBall>* BallList;
|
std::vector<TBall*> BallList;
|
||||||
TLightGroup* LightGroup;
|
TLightGroup* LightGroup;
|
||||||
float GravityDirVectMult;
|
float GravityDirVectMult{};
|
||||||
float GravityAngleX;
|
float GravityAngleX{};
|
||||||
float GravityAnglY;
|
float GravityAnglY{};
|
||||||
float CollisionCompOffset;
|
float CollisionCompOffset{};
|
||||||
float PlungerPositionX;
|
float PlungerPositionX{};
|
||||||
float PlungerPositionY;
|
float PlungerPositionY{};
|
||||||
int ScoreMultiplier;
|
int ScoreMultiplier{};
|
||||||
int ScoreAdded;
|
int ScoreAdded{};
|
||||||
int ScoreSpecial1;
|
int ScoreSpecial1{};
|
||||||
int ScoreSpecial2;
|
int ScoreSpecial2{};
|
||||||
int ScoreSpecial2Flag;
|
int ScoreSpecial2Flag{};
|
||||||
int ScoreSpecial3;
|
int ScoreSpecial3{};
|
||||||
int ScoreSpecial3Flag;
|
int ScoreSpecial3Flag{};
|
||||||
int UnknownP71;
|
int UnknownP71{};
|
||||||
int BallCount;
|
int BallCount{};
|
||||||
int MaxBallCount;
|
int MaxBallCount;
|
||||||
int ExtraBalls;
|
int ExtraBalls{};
|
||||||
int UnknownP75;
|
int UnknownP75{};
|
||||||
int BallLockedCounter;
|
int BallLockedCounter{};
|
||||||
int MultiballFlag;
|
int MultiballFlag;
|
||||||
int UnknownP78;
|
int UnknownP78{};
|
||||||
int ReplayActiveFlag;
|
int ReplayActiveFlag{};
|
||||||
int ReplayTimer;
|
int ReplayTimer;
|
||||||
int UnknownP81;
|
int UnknownP81{};
|
||||||
int UnknownP82;
|
int UnknownP82{};
|
||||||
int TiltLockFlag;
|
int TiltLockFlag;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
#include "control.h"
|
#include "control.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "maths.h"
|
#include "maths.h"
|
||||||
#include "objlist_class.h"
|
|
||||||
#include "pb.h"
|
#include "pb.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "TBall.h"
|
#include "TBall.h"
|
||||||
@@ -27,7 +26,7 @@ TPlunger::TPlunger(TPinballTable* table, int groupIndex) : TCollisionComponent(t
|
|||||||
MaxPullback = 100;
|
MaxPullback = 100;
|
||||||
Elasticity = 0.5f;
|
Elasticity = 0.5f;
|
||||||
Smoothness = 0.5f;
|
Smoothness = 0.5f;
|
||||||
PullbackIncrement = static_cast<int>(100.0 / (ListBitmap->GetCount() * 8.0));
|
PullbackIncrement = static_cast<int>(100.0 / (ListBitmap->size() * 8.0));
|
||||||
Unknown4F = 0.025f;
|
Unknown4F = 0.025f;
|
||||||
float* floatArr = loader::query_float_attribute(groupIndex, 0, 601);
|
float* floatArr = loader::query_float_attribute(groupIndex, 0, 601);
|
||||||
table->PlungerPositionX = floatArr[0];
|
table->PlungerPositionX = floatArr[0];
|
||||||
@@ -38,7 +37,7 @@ void TPlunger::Collision(TBall* ball, vector_type* nextPosition, vector_type* di
|
|||||||
{
|
{
|
||||||
if (PinballTable->TiltLockFlag)
|
if (PinballTable->TiltLockFlag)
|
||||||
Message(1017, 0.0);
|
Message(1017, 0.0);
|
||||||
coef = static_cast<float>(rand()) * 0.00003051850947599719f * Boost * 0.1f + Boost;
|
coef = RandFloat() * Boost * 0.1f + Boost; // it is intended that the passed in coef is never used!
|
||||||
maths::basic_collision(ball, nextPosition, direction, Elasticity, Smoothness, Threshold, coef);
|
maths::basic_collision(ball, nextPosition, direction, Elasticity, Smoothness, Threshold, coef);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,31 +54,9 @@ int TPlunger::Message(int code, float value)
|
|||||||
PullbackTimer(0, this);
|
PullbackTimer(0, this);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
case 1005:
|
|
||||||
case 1009:
|
|
||||||
case 1010:
|
|
||||||
{
|
|
||||||
Threshold = 0.0;
|
|
||||||
if (PullbackTimer_)
|
|
||||||
timer::kill(PullbackTimer_);
|
|
||||||
PullbackTimer_ = 0;
|
|
||||||
if (code == 1005)
|
|
||||||
loader::play_sound(SoundIndexP2);
|
|
||||||
auto bmp = ListBitmap->Get(0);
|
|
||||||
auto zMap = ListZMap->Get(0);
|
|
||||||
render::sprite_set(
|
|
||||||
RenderSprite,
|
|
||||||
bmp,
|
|
||||||
zMap,
|
|
||||||
bmp->XPosition - PinballTable->XOffset,
|
|
||||||
bmp->YPosition - PinballTable->YOffset);
|
|
||||||
|
|
||||||
timer::set(Unknown4F, this, PlungerReleasedTimer);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 1015:
|
case 1015:
|
||||||
{
|
{
|
||||||
auto ball = PinballTable->BallList->Get(0);
|
auto ball = PinballTable->BallList.at(0);
|
||||||
ball->Message(1024, 0.0);
|
ball->Message(1024, 0.0);
|
||||||
ball->Position.X = PinballTable->PlungerPositionX;
|
ball->Position.X = PinballTable->PlungerPositionX;
|
||||||
ball->Position.Y = PinballTable->PlungerPositionY;
|
ball->Position.Y = PinballTable->PlungerPositionY;
|
||||||
@@ -101,19 +78,26 @@ int TPlunger::Message(int code, float value)
|
|||||||
Boost = static_cast<float>(MaxPullback);
|
Boost = static_cast<float>(MaxPullback);
|
||||||
timer::set(0.2f, this, PlungerReleasedTimer);
|
timer::set(0.2f, this, PlungerReleasedTimer);
|
||||||
break;
|
break;
|
||||||
|
case 1005:
|
||||||
|
case 1009:
|
||||||
|
case 1010:
|
||||||
case 1024:
|
case 1024:
|
||||||
{
|
{
|
||||||
if (BallFeedTimer_)
|
if (code == 1024)
|
||||||
timer::kill(BallFeedTimer_);
|
{
|
||||||
BallFeedTimer_ = 0;
|
if (BallFeedTimer_)
|
||||||
|
timer::kill(BallFeedTimer_);
|
||||||
|
BallFeedTimer_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
Threshold = 0.0;
|
Threshold = 0.0;
|
||||||
if (PullbackTimer_)
|
if (PullbackTimer_)
|
||||||
timer::kill(PullbackTimer_);
|
timer::kill(PullbackTimer_);
|
||||||
PullbackTimer_ = 0;
|
PullbackTimer_ = 0;
|
||||||
if (code == 1005)
|
if (code == 1005)
|
||||||
loader::play_sound(SoundIndexP2);
|
loader::play_sound(SoundIndexP2);
|
||||||
auto bmp = ListBitmap->Get(0);
|
auto bmp = ListBitmap->at(0);
|
||||||
auto zMap = ListZMap->Get(0);
|
auto zMap = ListZMap->at(0);
|
||||||
render::sprite_set(
|
render::sprite_set(
|
||||||
RenderSprite,
|
RenderSprite,
|
||||||
bmp,
|
bmp,
|
||||||
@@ -151,10 +135,10 @@ void TPlunger::PullbackTimer(int timerId, void* caller)
|
|||||||
plunger->Boost = static_cast<float>(plunger->MaxPullback);
|
plunger->Boost = static_cast<float>(plunger->MaxPullback);
|
||||||
}
|
}
|
||||||
int index = static_cast<int>(floor(
|
int index = static_cast<int>(floor(
|
||||||
static_cast<float>(plunger->ListBitmap->GetCount() - 1) *
|
static_cast<float>(plunger->ListBitmap->size() - 1) *
|
||||||
(plunger->Boost / static_cast<float>(plunger->MaxPullback))));
|
(plunger->Boost / static_cast<float>(plunger->MaxPullback))));
|
||||||
auto bmp = plunger->ListBitmap->Get(index);
|
auto bmp = plunger->ListBitmap->at(index);
|
||||||
auto zMap = plunger->ListZMap->Get(index);
|
auto zMap = plunger->ListZMap->at(index);
|
||||||
render::sprite_set(
|
render::sprite_set(
|
||||||
plunger->RenderSprite,
|
plunger->RenderSprite,
|
||||||
bmp,
|
bmp,
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#include "control.h"
|
#include "control.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "objlist_class.h"
|
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "TPinballTable.h"
|
#include "TPinballTable.h"
|
||||||
@@ -91,7 +90,7 @@ void TPopupTarget::TimerExpired(int timerId, void* caller)
|
|||||||
auto target = static_cast<TPopupTarget*>(caller);
|
auto target = static_cast<TPopupTarget*>(caller);
|
||||||
target->Timer = 0;
|
target->Timer = 0;
|
||||||
target->ActiveFlag = 1;
|
target->ActiveFlag = 1;
|
||||||
render::sprite_set_bitmap(target->RenderSprite, target->ListBitmap->Get(0));
|
render::sprite_set_bitmap(target->RenderSprite, target->ListBitmap->at(0));
|
||||||
if (timerId)
|
if (timerId)
|
||||||
{
|
{
|
||||||
if (target->SoftHitSoundId)
|
if (target->SoftHitSoundId)
|
||||||
|
|||||||
@@ -16,6 +16,6 @@ public:
|
|||||||
|
|
||||||
int Timer;
|
int Timer;
|
||||||
float TimerTime;
|
float TimerTime;
|
||||||
int Scores[3];
|
int Scores[3]{};
|
||||||
int PlayerMessagefieldBackup[4];
|
int PlayerMessagefieldBackup[4]{};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#include "control.h"
|
#include "control.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "objlist_class.h"
|
|
||||||
#include "TBall.h"
|
#include "TBall.h"
|
||||||
#include "TEdgeSegment.h"
|
#include "TEdgeSegment.h"
|
||||||
#include "TLine.h"
|
#include "TLine.h"
|
||||||
@@ -35,7 +34,7 @@ TRamp::TRamp(TPinballTable* table, int groupIndex) : TCollisionComponent(table,
|
|||||||
start.X = floatArr4[4];
|
start.X = floatArr4[4];
|
||||||
start.Y = floatArr4[5];
|
start.Y = floatArr4[5];
|
||||||
Line1 = new TLine(this, &ActiveFlag, 1 << static_cast<int>(floor(floatArr4[0])), &start, &end);
|
Line1 = new TLine(this, &ActiveFlag, 1 << static_cast<int>(floor(floatArr4[0])), &start, &end);
|
||||||
EdgeList->Add(Line1);
|
EdgeList.push_back(Line1);
|
||||||
if (Line1)
|
if (Line1)
|
||||||
{
|
{
|
||||||
Line1->WallValue = nullptr;
|
Line1->WallValue = nullptr;
|
||||||
@@ -53,7 +52,7 @@ TRamp::TRamp(TPinballTable* table, int groupIndex) : TCollisionComponent(table,
|
|||||||
&end2,
|
&end2,
|
||||||
&start2);
|
&start2);
|
||||||
Line2 = new TLine(this, &ActiveFlag, CollisionGroup, start2, end2);
|
Line2 = new TLine(this, &ActiveFlag, CollisionGroup, start2, end2);
|
||||||
EdgeList->Add(Line2);
|
EdgeList.push_back(Line2);
|
||||||
if (Line2)
|
if (Line2)
|
||||||
{
|
{
|
||||||
Line2->WallValue = nullptr;
|
Line2->WallValue = nullptr;
|
||||||
@@ -71,7 +70,7 @@ TRamp::TRamp(TPinballTable* table, int groupIndex) : TCollisionComponent(table,
|
|||||||
&end3,
|
&end3,
|
||||||
&start3);
|
&start3);
|
||||||
Line3 = new TLine(this, &ActiveFlag, CollisionGroup, start3, end3);
|
Line3 = new TLine(this, &ActiveFlag, CollisionGroup, start3, end3);
|
||||||
EdgeList->Add(Line3);
|
EdgeList.push_back(Line3);
|
||||||
if (Line3)
|
if (Line3)
|
||||||
{
|
{
|
||||||
Line3->WallValue = nullptr;
|
Line3->WallValue = nullptr;
|
||||||
@@ -90,10 +89,10 @@ TRamp::TRamp(TPinballTable* table, int groupIndex) : TCollisionComponent(table,
|
|||||||
auto pVec2 = reinterpret_cast<vector_type*>(&plane->V2);
|
auto pVec2 = reinterpret_cast<vector_type*>(&plane->V2);
|
||||||
auto pVec3 = reinterpret_cast<vector_type*>(&plane->V3);
|
auto pVec3 = reinterpret_cast<vector_type*>(&plane->V3);
|
||||||
|
|
||||||
xMin = min(min(min(plane->V3.X, plane->V1.X), plane->V2.X), xMin);
|
xMin = std::min(std::min(std::min(plane->V3.X, plane->V1.X), plane->V2.X), xMin);
|
||||||
yMin = min(min(min(plane->V3.Y, plane->V1.Y), plane->V2.Y), xMin); // Sic
|
yMin = std::min(std::min(std::min(plane->V3.Y, plane->V1.Y), plane->V2.Y), xMin); // Sic
|
||||||
xMax = max(max(max(plane->V3.X, plane->V1.X), plane->V2.X), xMin);
|
xMax = std::max(std::max(std::max(plane->V3.X, plane->V1.X), plane->V2.X), xMin);
|
||||||
yMax = max(max(max(plane->V3.Y, plane->V1.Y), plane->V2.Y), xMin);
|
yMax = std::max(std::max(std::max(plane->V3.Y, plane->V1.Y), plane->V2.Y), xMin);
|
||||||
|
|
||||||
vector_type* pointOrder[4] = {pVec1, pVec2, pVec3, pVec1};
|
vector_type* pointOrder[4] = {pVec1, pVec2, pVec3, pVec1};
|
||||||
for (auto pt = 0; pt < 3; pt++)
|
for (auto pt = 0; pt < 3; pt++)
|
||||||
@@ -118,7 +117,7 @@ TRamp::TRamp(TPinballTable* table, int groupIndex) : TCollisionComponent(table,
|
|||||||
if (collisionGroup)
|
if (collisionGroup)
|
||||||
{
|
{
|
||||||
auto line = new TLine(this, &ActiveFlag, collisionGroup, point1, point2);
|
auto line = new TLine(this, &ActiveFlag, collisionGroup, point1, point2);
|
||||||
EdgeList->Add(line);
|
EdgeList.push_back(line);
|
||||||
if (line)
|
if (line)
|
||||||
{
|
{
|
||||||
line->WallValue = plane;
|
line->WallValue = plane;
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ public:
|
|||||||
int FieldEffect(TBall* ball, vector_type* vecDst) override;
|
int FieldEffect(TBall* ball, vector_type* vecDst) override;
|
||||||
void port_draw() override;
|
void port_draw() override;
|
||||||
|
|
||||||
int Scores[4];
|
int Scores[4]{};
|
||||||
field_effect_type Field;
|
field_effect_type Field{};
|
||||||
int CollisionGroup;
|
int CollisionGroup;
|
||||||
int RampFlag1;
|
int RampFlag1;
|
||||||
int RampPlaneCount;
|
int RampPlaneCount;
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
#include "control.h"
|
#include "control.h"
|
||||||
#include "gdrv.h"
|
#include "gdrv.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "objlist_class.h"
|
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "TBall.h"
|
#include "TBall.h"
|
||||||
#include "TEdgeSegment.h"
|
#include "TEdgeSegment.h"
|
||||||
@@ -20,9 +19,8 @@ TRollover::TRollover(TPinballTable* table, int groupIndex, bool createWall) : TC
|
|||||||
|
|
||||||
TRollover::TRollover(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, false)
|
TRollover::TRollover(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, false)
|
||||||
{
|
{
|
||||||
RolloverFlag = 0;
|
|
||||||
if (ListBitmap)
|
if (ListBitmap)
|
||||||
render::sprite_set_bitmap(RenderSprite, ListBitmap->Get(0));
|
render::sprite_set_bitmap(RenderSprite, ListBitmap->at(0));
|
||||||
build_walls(groupIndex);
|
build_walls(groupIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,7 +32,7 @@ int TRollover::Message(int code, float value)
|
|||||||
this->ActiveFlag = 1;
|
this->ActiveFlag = 1;
|
||||||
this->RolloverFlag = 0;
|
this->RolloverFlag = 0;
|
||||||
if (this->ListBitmap)
|
if (this->ListBitmap)
|
||||||
render::sprite_set_bitmap(this->RenderSprite, this->ListBitmap->Get(0));
|
render::sprite_set_bitmap(this->RenderSprite, this->ListBitmap->at(0));
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -63,7 +61,7 @@ void TRollover::Collision(TBall* ball, vector_type* nextPosition, vector_type* d
|
|||||||
if (ListBitmap)
|
if (ListBitmap)
|
||||||
{
|
{
|
||||||
if (!RolloverFlag)
|
if (!RolloverFlag)
|
||||||
bmp = ListBitmap->Get(0);
|
bmp = ListBitmap->at(0);
|
||||||
render::sprite_set_bitmap(RenderSprite, bmp);
|
render::sprite_set_bitmap(RenderSprite, bmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,6 @@ public:
|
|||||||
|
|
||||||
static void TimerExpired(int timerId, void* caller);
|
static void TimerExpired(int timerId, void* caller);
|
||||||
|
|
||||||
char RolloverFlag;
|
char RolloverFlag{};
|
||||||
int Scores[2];
|
int Scores[2]{};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#include "control.h"
|
#include "control.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "objlist_class.h"
|
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "TPinballTable.h"
|
#include "TPinballTable.h"
|
||||||
#include "TBall.h"
|
#include "TBall.h"
|
||||||
@@ -95,7 +94,7 @@ void TSink::Collision(TBall* ball, vector_type* nextPosition, vector_type* direc
|
|||||||
void TSink::TimerExpired(int timerId, void* caller)
|
void TSink::TimerExpired(int timerId, void* caller)
|
||||||
{
|
{
|
||||||
auto sink = static_cast<TSink*>(caller);
|
auto sink = static_cast<TSink*>(caller);
|
||||||
auto ball = sink->PinballTable->BallList->Get(0);
|
auto ball = sink->PinballTable->BallList.at(0);
|
||||||
ball->CollisionComp = nullptr;
|
ball->CollisionComp = nullptr;
|
||||||
ball->ActiveFlag = 1;
|
ball->ActiveFlag = 1;
|
||||||
ball->Position.X = sink->BallPosition.X;
|
ball->Position.X = sink->BallPosition.X;
|
||||||
|
|||||||
@@ -17,13 +17,13 @@ public:
|
|||||||
|
|
||||||
int Timer;
|
int Timer;
|
||||||
float TimerTime;
|
float TimerTime;
|
||||||
vector_type BallPosition;
|
vector_type BallPosition{};
|
||||||
vector_type BallAcceleration;
|
vector_type BallAcceleration{};
|
||||||
float ThrowAngleMult;
|
float ThrowAngleMult;
|
||||||
float ThrowSpeedMult1;
|
float ThrowSpeedMult1;
|
||||||
float ThrowSpeedMult2;
|
float ThrowSpeedMult2;
|
||||||
int SoundIndex4;
|
int SoundIndex4;
|
||||||
int SoundIndex3;
|
int SoundIndex3;
|
||||||
int Scores[3];
|
int Scores[3]{};
|
||||||
int PlayerMessagefieldBackup[4];
|
int PlayerMessagefieldBackup[4]{};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#include "control.h"
|
#include "control.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "objlist_class.h"
|
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "TPinballTable.h"
|
#include "TPinballTable.h"
|
||||||
@@ -41,8 +40,8 @@ int TSoloTarget::Message(int code, float value)
|
|||||||
if (ListBitmap)
|
if (ListBitmap)
|
||||||
{
|
{
|
||||||
auto index = 1 - ActiveFlag;
|
auto index = 1 - ActiveFlag;
|
||||||
auto bmp = ListBitmap->Get(index);
|
auto bmp = ListBitmap->at(index);
|
||||||
auto zMap = ListZMap->Get(index);
|
auto zMap = ListZMap->at(index);
|
||||||
render::sprite_set(
|
render::sprite_set(
|
||||||
RenderSprite,
|
RenderSprite,
|
||||||
bmp,
|
bmp,
|
||||||
|
|||||||
@@ -14,9 +14,8 @@ public:
|
|||||||
|
|
||||||
static void TimerExpired(int timerId, void* caller);
|
static void TimerExpired(int timerId, void* caller);
|
||||||
|
|
||||||
int Unknown0;
|
|
||||||
int Timer;
|
int Timer;
|
||||||
float TimerTime;
|
float TimerTime;
|
||||||
int SoundIndex4;
|
int SoundIndex4;
|
||||||
int Scores[1];
|
int Scores[1]{};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#include "fullscrn.h"
|
#include "fullscrn.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "objlist_class.h"
|
|
||||||
#include "pb.h"
|
#include "pb.h"
|
||||||
#include "proj.h"
|
#include "proj.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
@@ -33,7 +32,7 @@ TTableLayer::TTableLayer(TPinballTable* table): TCollisionComponent(table, -1, f
|
|||||||
rect.YPosition = 0;
|
rect.YPosition = 0;
|
||||||
rect.Width = bmp->Width;
|
rect.Width = bmp->Width;
|
||||||
rect.Height = bmp->Height;
|
rect.Height = bmp->Height;
|
||||||
render::create_sprite(VisualType::None, bmp, visual.ZMap, 0, 0, &rect);
|
render::create_sprite(VisualTypes::None, bmp, visual.ZMap, 0, 0, &rect);
|
||||||
|
|
||||||
PinballTable->SoundIndex1 = visual.SoundIndex4;
|
PinballTable->SoundIndex1 = visual.SoundIndex4;
|
||||||
PinballTable->SoundIndex2 = visual.SoundIndex3;
|
PinballTable->SoundIndex2 = visual.SoundIndex3;
|
||||||
@@ -71,10 +70,10 @@ TTableLayer::TTableLayer(TPinballTable* table): TCollisionComponent(table, -1, f
|
|||||||
Boost = 15.0f;
|
Boost = 15.0f;
|
||||||
|
|
||||||
auto visArrPtr = visual.FloatArr;
|
auto visArrPtr = visual.FloatArr;
|
||||||
Unknown1F = min(visArrPtr[0], min(visArrPtr[2], visArrPtr[4]));
|
Unknown1F = std::min(visArrPtr[0], std::min(visArrPtr[2], visArrPtr[4]));
|
||||||
Unknown2F = min(visArrPtr[1], min(visArrPtr[3], visArrPtr[5]));
|
Unknown2F = std::min(visArrPtr[1], std::min(visArrPtr[3], visArrPtr[5]));
|
||||||
Unknown3F = max(visArrPtr[0], max(visArrPtr[2], visArrPtr[4]));
|
Unknown3F = std::max(visArrPtr[0], std::max(visArrPtr[2], visArrPtr[4]));
|
||||||
Unknown4F = max(visArrPtr[1], max(visArrPtr[3], visArrPtr[5]));
|
Unknown4F = std::max(visArrPtr[1], std::max(visArrPtr[3], visArrPtr[5]));
|
||||||
auto a2 = Unknown4F - Unknown2F;
|
auto a2 = Unknown4F - Unknown2F;
|
||||||
auto a1 = Unknown3F - Unknown1F;
|
auto a1 = Unknown3F - Unknown1F;
|
||||||
edge_manager = new TEdgeManager(Unknown1F, Unknown2F, a1, a2);
|
edge_manager = new TEdgeManager(Unknown1F, Unknown2F, a1, a2);
|
||||||
@@ -91,7 +90,7 @@ TTableLayer::TTableLayer(TPinballTable* table): TCollisionComponent(table, -1, f
|
|||||||
if (line)
|
if (line)
|
||||||
{
|
{
|
||||||
line->place_in_grid();
|
line->place_in_grid();
|
||||||
EdgeList->Add(line);
|
EdgeList.push_back(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
visArrPtr += 2;
|
visArrPtr += 2;
|
||||||
@@ -112,7 +111,7 @@ TTableLayer::~TTableLayer()
|
|||||||
|
|
||||||
int TTableLayer::FieldEffect(TBall* ball, vector_type* vecDst)
|
int TTableLayer::FieldEffect(TBall* ball, vector_type* vecDst)
|
||||||
{
|
{
|
||||||
vecDst->X = GraityDirX - (0.5f - static_cast<float>(rand()) * 0.00003051850947599719f + ball->Acceleration.X) *
|
vecDst->X = GraityDirX - (0.5f - RandFloat() + ball->Acceleration.X) *
|
||||||
ball->Speed * GraityMult;
|
ball->Speed * GraityMult;
|
||||||
vecDst->Y = GraityDirY - ball->Acceleration.Y * ball->Speed * GraityMult;
|
vecDst->Y = GraityDirY - ball->Acceleration.Y * ball->Speed * GraityMult;
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
@@ -27,9 +27,8 @@ public:
|
|||||||
float Unknown4F;
|
float Unknown4F;
|
||||||
float GraityDirX;
|
float GraityDirX;
|
||||||
float GraityDirY;
|
float GraityDirY;
|
||||||
int Unknown7;
|
|
||||||
float GraityMult;
|
float GraityMult;
|
||||||
field_effect_type Field;
|
field_effect_type Field{};
|
||||||
|
|
||||||
static TEdgeManager* edge_manager;
|
static TEdgeManager* edge_manager;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
#include "control.h"
|
#include "control.h"
|
||||||
#include "fullscrn.h"
|
#include "fullscrn.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "pb.h"
|
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "score.h"
|
#include "score.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
@@ -76,7 +75,7 @@ void TTextBox::Clear()
|
|||||||
gdrv_bitmap8* bmp = BgBmp;
|
gdrv_bitmap8* bmp = BgBmp;
|
||||||
if (bmp)
|
if (bmp)
|
||||||
gdrv::copy_bitmap(
|
gdrv::copy_bitmap(
|
||||||
&render::vscreen,
|
render::vscreen,
|
||||||
Width,
|
Width,
|
||||||
Height,
|
Height,
|
||||||
OffsetX,
|
OffsetX,
|
||||||
@@ -85,15 +84,7 @@ void TTextBox::Clear()
|
|||||||
OffsetX,
|
OffsetX,
|
||||||
OffsetY);
|
OffsetY);
|
||||||
else
|
else
|
||||||
gdrv::fill_bitmap(&render::vscreen, Width, Height, OffsetX, OffsetY, 0);
|
gdrv::fill_bitmap(render::vscreen, Width, Height, OffsetX, OffsetY, 0);
|
||||||
gdrv::blit(
|
|
||||||
&render::vscreen,
|
|
||||||
OffsetX,
|
|
||||||
OffsetY,
|
|
||||||
OffsetX + render::vscreen.XPosition,
|
|
||||||
OffsetY + render::vscreen.YPosition,
|
|
||||||
Width,
|
|
||||||
Height);
|
|
||||||
if (Timer)
|
if (Timer)
|
||||||
{
|
{
|
||||||
if (Timer != -1)
|
if (Timer != -1)
|
||||||
@@ -109,12 +100,12 @@ void TTextBox::Clear()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTextBox::Display(const wchar_t* text, float time)
|
void TTextBox::Display(const char* text, float time)
|
||||||
{
|
{
|
||||||
if (!text)
|
if (!text)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (Message1 && !lstrcmpW(text, Message2->Text))
|
if (Message1 && !strcmp(text, Message2->Text))
|
||||||
{
|
{
|
||||||
Message2->Refresh(time);
|
Message2->Refresh(time);
|
||||||
if (Message2 == Message1)
|
if (Message2 == Message1)
|
||||||
@@ -153,12 +144,12 @@ void TTextBox::Display(const wchar_t* text, float time)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTextBox::Draw(bool redraw)
|
void TTextBox::Draw()
|
||||||
{
|
{
|
||||||
auto bmp = BgBmp;
|
auto bmp = BgBmp;
|
||||||
if (bmp)
|
if (bmp)
|
||||||
gdrv::copy_bitmap(
|
gdrv::copy_bitmap(
|
||||||
&render::vscreen,
|
render::vscreen,
|
||||||
Width,
|
Width,
|
||||||
Height,
|
Height,
|
||||||
OffsetX,
|
OffsetX,
|
||||||
@@ -167,17 +158,11 @@ void TTextBox::Draw(bool redraw)
|
|||||||
OffsetX,
|
OffsetX,
|
||||||
OffsetY);
|
OffsetY);
|
||||||
else
|
else
|
||||||
gdrv::fill_bitmap(&render::vscreen, Width, Height, OffsetX, OffsetY, 0);
|
gdrv::fill_bitmap(render::vscreen, Width, Height, OffsetX, OffsetY, 0);
|
||||||
|
|
||||||
bool display = false;
|
bool display = false;
|
||||||
while (Message1)
|
while (Message1)
|
||||||
{
|
{
|
||||||
if (redraw)
|
|
||||||
{
|
|
||||||
display = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Message1->Time == -1.0f)
|
if (Message1->Time == -1.0f)
|
||||||
{
|
{
|
||||||
if (!Message1->NextMessage)
|
if (!Message1->NextMessage)
|
||||||
@@ -189,9 +174,7 @@ void TTextBox::Draw(bool redraw)
|
|||||||
}
|
}
|
||||||
else if (Message1->TimeLeft() >= -2.0f)
|
else if (Message1->TimeLeft() >= -2.0f)
|
||||||
{
|
{
|
||||||
if (Timer > 0)
|
Timer = timer::set(std::max(Message1->TimeLeft(), 0.25f), this, TimerExpired);
|
||||||
timer::kill(Timer);
|
|
||||||
Timer = timer::set(max(Message1->TimeLeft(), 0.25f), this, TimerExpired);
|
|
||||||
display = true;
|
display = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -206,20 +189,13 @@ void TTextBox::Draw(bool redraw)
|
|||||||
auto font = Font;
|
auto font = Font;
|
||||||
if (!font)
|
if (!font)
|
||||||
{
|
{
|
||||||
gdrv::blit(
|
|
||||||
&render::vscreen,
|
|
||||||
OffsetX,
|
|
||||||
OffsetY,
|
|
||||||
OffsetX + render::vscreen.XPosition,
|
|
||||||
OffsetY + render::vscreen.YPosition,
|
|
||||||
Width,
|
|
||||||
Height);
|
|
||||||
gdrv::grtext_draw_ttext_in_box(
|
gdrv::grtext_draw_ttext_in_box(
|
||||||
Message1->Text,
|
Message1->Text,
|
||||||
render::vscreen.XPosition + OffsetX,
|
render::vscreen->XPosition + OffsetX,
|
||||||
render::vscreen.YPosition + OffsetY,
|
render::vscreen->YPosition + OffsetY,
|
||||||
Width,
|
Width,
|
||||||
Height);
|
Height,
|
||||||
|
255);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,7 +207,7 @@ void TTextBox::Draw(bool redraw)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
auto totalWidth = 0;
|
auto totalWidth = 0;
|
||||||
wchar_t* textEndSpace = nullptr;
|
char* textEndSpace = nullptr;
|
||||||
auto textEnd = text;
|
auto textEnd = text;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
@@ -269,10 +245,10 @@ void TTextBox::Draw(bool redraw)
|
|||||||
auto height = charBmp->Height;
|
auto height = charBmp->Height;
|
||||||
auto width = charBmp->Width;
|
auto width = charBmp->Width;
|
||||||
if (render::background_bitmap)
|
if (render::background_bitmap)
|
||||||
gdrv::copy_bitmap_w_transparency(&render::vscreen, width, height, offX, y, charBmp, 0,
|
gdrv::copy_bitmap_w_transparency(render::vscreen, width, height, offX, y, charBmp, 0,
|
||||||
0);
|
0);
|
||||||
else
|
else
|
||||||
gdrv::copy_bitmap(&render::vscreen, width, height, offX, y, charBmp, 0, 0);
|
gdrv::copy_bitmap(render::vscreen, width, height, offX, y, charBmp, 0, 0);
|
||||||
font = Font;
|
font = Font;
|
||||||
offX += charBmp->Width + font->GapWidth;
|
offX += charBmp->Width + font->GapWidth;
|
||||||
}
|
}
|
||||||
@@ -283,13 +259,4 @@ void TTextBox::Draw(bool redraw)
|
|||||||
++text;
|
++text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gdrv::blit(
|
|
||||||
&render::vscreen,
|
|
||||||
OffsetX,
|
|
||||||
OffsetY,
|
|
||||||
OffsetX + render::vscreen.XPosition,
|
|
||||||
OffsetY + render::vscreen.YPosition,
|
|
||||||
Width,
|
|
||||||
Height);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ public:
|
|||||||
~TTextBox() override;
|
~TTextBox() override;
|
||||||
int Message(int code, float value) override;
|
int Message(int code, float value) override;
|
||||||
void Clear();
|
void Clear();
|
||||||
void Display(const wchar_t* text, float time);
|
void Display(const char* text, float time);
|
||||||
void Draw(bool redraw = false);
|
void Draw();
|
||||||
|
|
||||||
static void TimerExpired(int timerId, void* tb);
|
static void TimerExpired(int timerId, void* tb);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,19 +1,18 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "TTextBoxMessage.h"
|
#include "TTextBoxMessage.h"
|
||||||
#include "memory.h"
|
|
||||||
#include "pb.h"
|
#include "pb.h"
|
||||||
|
|
||||||
TTextBoxMessage::TTextBoxMessage(const wchar_t* text, float time)
|
TTextBoxMessage::TTextBoxMessage(const char* text, float time)
|
||||||
{
|
{
|
||||||
NextMessage = nullptr;
|
NextMessage = nullptr;
|
||||||
Time = time;
|
Time = time;
|
||||||
EndTicks = pb::time_ticks + static_cast<int>(time * 1000.0f);
|
EndTicks = pb::time_ticks + static_cast<int>(time * 1000.0f);
|
||||||
if (text)
|
if (text)
|
||||||
{
|
{
|
||||||
const auto textLen = lstrlenW(text) + 1;
|
const auto textLen = strlen(text) + 1;
|
||||||
Text = memory::allocate<wchar_t>(textLen);
|
Text = new char[textLen];
|
||||||
if (Text)
|
if (Text)
|
||||||
lstrcpynW(Text, text, textLen);
|
strncpy(Text, text, textLen);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Text = nullptr;
|
Text = nullptr;
|
||||||
@@ -21,8 +20,7 @@ TTextBoxMessage::TTextBoxMessage(const wchar_t* text, float time)
|
|||||||
|
|
||||||
TTextBoxMessage::~TTextBoxMessage()
|
TTextBoxMessage::~TTextBoxMessage()
|
||||||
{
|
{
|
||||||
if (Text)
|
delete[] Text;
|
||||||
memory::free(Text);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float TTextBoxMessage::TimeLeft() const
|
float TTextBoxMessage::TimeLeft() const
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ class TTextBoxMessage
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TTextBoxMessage* NextMessage;
|
TTextBoxMessage* NextMessage;
|
||||||
wchar_t* Text;
|
char* Text;
|
||||||
float Time;
|
float Time;
|
||||||
int EndTicks;
|
int EndTicks;
|
||||||
|
|
||||||
TTextBoxMessage(const wchar_t* text, float time);
|
TTextBoxMessage(const char* text, float time);
|
||||||
~TTextBoxMessage();
|
~TTextBoxMessage();
|
||||||
float TimeLeft() const;
|
float TimeLeft() const;
|
||||||
void Refresh(float time);
|
void Refresh(float time);
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
#include "TBall.h"
|
#include "TBall.h"
|
||||||
#include "TPinballTable.h"
|
#include "TPinballTable.h"
|
||||||
|
|
||||||
TTripwire::TTripwire(TPinballTable* table, int groupIndex) : TRollover(table, groupIndex, 1)
|
TTripwire::TTripwire(TPinballTable* table, int groupIndex) : TRollover(table, groupIndex, true)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "control.h"
|
#include "control.h"
|
||||||
#include "objlist_class.h"
|
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
|
||||||
@@ -12,8 +11,7 @@ TWall::TWall(TPinballTable* table, int groupIndex) : TCollisionComponent(table,
|
|||||||
if (RenderSprite)
|
if (RenderSprite)
|
||||||
render::sprite_set_bitmap(RenderSprite, nullptr);
|
render::sprite_set_bitmap(RenderSprite, nullptr);
|
||||||
if (ListBitmap)
|
if (ListBitmap)
|
||||||
BmpPtr = ListBitmap->Get(0);
|
BmpPtr = ListBitmap->at(0);
|
||||||
Timer = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int TWall::Message(int code, float value)
|
int TWall::Message(int code, float value)
|
||||||
|
|||||||
@@ -11,13 +11,13 @@ public:
|
|||||||
TWall(TPinballTable* table, int groupIndex);
|
TWall(TPinballTable* table, int groupIndex);
|
||||||
int Message(int code, float value) override;
|
int Message(int code, float value) override;
|
||||||
void Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef,
|
void Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef,
|
||||||
TEdgeSegment* edge) override;
|
TEdgeSegment* edge) override;
|
||||||
void put_scoring(int index, int score) override;
|
void put_scoring(int index, int score) override;
|
||||||
int get_scoring(int index) override;
|
int get_scoring(int index) override;
|
||||||
|
|
||||||
static void TimerExpired(int timerId, void* caller);
|
static void TimerExpired(int timerId, void* caller);
|
||||||
|
|
||||||
int Timer;
|
int Timer{};
|
||||||
gdrv_bitmap8* BmpPtr;
|
gdrv_bitmap8* BmpPtr{};
|
||||||
int Scores[1];
|
int Scores[1]{};
|
||||||
};
|
};
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,244 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
|
|
||||||
/* flag values for play params */
|
|
||||||
#define WMIX_QUEUEWAVE 0x00
|
|
||||||
#define WMIX_CLEARQUEUE 0x01
|
|
||||||
#define WMIX_USELRUCHANNEL 0x02
|
|
||||||
#define WMIX_HIPRIORITY 0x04
|
|
||||||
#define WMIX_WAIT 0x08
|
|
||||||
#define WMIX_CustomVolume 0x10
|
|
||||||
|
|
||||||
#define MAXCHANNELS 16
|
|
||||||
#define MAXQUEUEDWAVES 100
|
|
||||||
|
|
||||||
struct GLOBALS;
|
|
||||||
|
|
||||||
struct volume_struct
|
|
||||||
{
|
|
||||||
uint16_t L;
|
|
||||||
uint16_t R;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct MIXWAVE
|
|
||||||
{
|
|
||||||
PCMWAVEFORMAT pcm;
|
|
||||||
WAVEHDR wh;
|
|
||||||
char szWaveFilename[16];
|
|
||||||
short wMagic;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MIXPLAYPARAMS
|
|
||||||
{
|
|
||||||
WORD wSize;
|
|
||||||
HANDLE hMixSession;
|
|
||||||
int iChannel;
|
|
||||||
MIXWAVE* lpMixWave;
|
|
||||||
HWND hWndNotify;
|
|
||||||
DWORD dwFlags;
|
|
||||||
WORD wLoops;
|
|
||||||
volume_struct Volume;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CHANNELNODE
|
|
||||||
{
|
|
||||||
CHANNELNODE* next;
|
|
||||||
MIXPLAYPARAMS PlayParams;
|
|
||||||
MIXWAVE* lpMixWave;
|
|
||||||
DWORD dwNumSamples;
|
|
||||||
DWORD dwStartPos;
|
|
||||||
DWORD dwEndPos;
|
|
||||||
unsigned char* lpPos;
|
|
||||||
unsigned char* lpEnd;
|
|
||||||
volume_struct Volume;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MIXCONFIG
|
|
||||||
{
|
|
||||||
WORD wSize;
|
|
||||||
DWORD dwFlags;
|
|
||||||
WORD wChannels;
|
|
||||||
WORD wSamplingRate;
|
|
||||||
uint16_t WaveBlockCount;
|
|
||||||
uint16_t WaveBlockLen;
|
|
||||||
int16_t CmixPtrDefaultFlag;
|
|
||||||
uint16_t ResetMixDefaultFlag;
|
|
||||||
uint16_t GoodWavePos;
|
|
||||||
uint16_t wDeviceID;
|
|
||||||
uint16_t PauseBlocks;
|
|
||||||
int16_t ShowDebugDialogs;
|
|
||||||
HKEY RegistryKey;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct XWAVEHDR
|
|
||||||
{
|
|
||||||
WAVEHDR wh;
|
|
||||||
BOOL fAvailable;
|
|
||||||
DWORD dwWavePos;
|
|
||||||
GLOBALS* g;
|
|
||||||
struct XWAVEHDR* QNext;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PLAYQUEUE
|
|
||||||
{
|
|
||||||
XWAVEHDR* first;
|
|
||||||
XWAVEHDR* last;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GLOBALS
|
|
||||||
{
|
|
||||||
WORD wMagic1;
|
|
||||||
int16_t unknown0;
|
|
||||||
HWND hWndApp;
|
|
||||||
int unknown2;
|
|
||||||
HWAVEOUT hWaveOut;
|
|
||||||
int fActive;
|
|
||||||
int SettingsDialogActiveFlag;
|
|
||||||
unsigned int wDeviceID;
|
|
||||||
char szDevicePName[96];
|
|
||||||
WAVEOUTCAPSA WaveoutCaps;
|
|
||||||
volume_struct DefaultVolume;
|
|
||||||
volume_struct ChannelVolume[MAXCHANNELS];
|
|
||||||
CHANNELNODE* aChannel[MAXCHANNELS];
|
|
||||||
int iChannels;
|
|
||||||
DWORD MRUChannel[MAXCHANNELS];
|
|
||||||
DWORD dwMRU;
|
|
||||||
PCMWAVEFORMAT PCM;
|
|
||||||
DWORD dwWaveBlockLen;
|
|
||||||
int WaveBlockCount;
|
|
||||||
int PauseBlocks;
|
|
||||||
XWAVEHDR** WaveBlockArray;
|
|
||||||
DWORD dwCurrentSample;
|
|
||||||
DWORD dwBaseTime;
|
|
||||||
int fGoodGetPos;
|
|
||||||
DWORD dwWaveOutPos;
|
|
||||||
void (*CmixPtr)(uint8_t* lpDest, uint8_t** rgWaveSrc, volume_struct* volume, int iNumWaves,
|
|
||||||
uint16_t length);
|
|
||||||
int (* pfnRemix)(DWORD, CHANNELNODE*);
|
|
||||||
DWORD (* pfnSampleAdjust)(DWORD, DWORD);
|
|
||||||
CHANNELNODE* pWaitList;
|
|
||||||
int16_t wMagic2;
|
|
||||||
int16_t unknown112;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct dialog_template
|
|
||||||
{
|
|
||||||
DLGTEMPLATE Dialog;
|
|
||||||
WORD menu;
|
|
||||||
WORD windowClass;
|
|
||||||
WCHAR Header[1];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct dialog_item_template
|
|
||||||
{
|
|
||||||
DLGITEMTEMPLATE Item;
|
|
||||||
WORD sysClass;
|
|
||||||
WORD idClass;
|
|
||||||
WCHAR Header[1];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class WaveMix
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static HANDLE Init();
|
|
||||||
static HANDLE ConfigureInit(MIXCONFIG* lpConfig);
|
|
||||||
static int CloseSession(HANDLE hMixSession);
|
|
||||||
static int OpenChannel(HANDLE hMixSession, int iChannel, unsigned int dwFlags);
|
|
||||||
static int CloseChannel(HANDLE hMixSession, int iChannel, unsigned int dwFlags);
|
|
||||||
static int FlushChannel(HANDLE hMixSession, int iChannel, unsigned int dwFlags);
|
|
||||||
static MIXWAVE* OpenWave(HANDLE hMixSession, LPCSTR szWaveFilename, HINSTANCE hInst, unsigned int dwFlags);
|
|
||||||
static int FreeWave(HANDLE hMixSession, MIXWAVE* lpMixWave);
|
|
||||||
static int Activate(HANDLE hMixSession, bool fActivate);
|
|
||||||
static void Pump();
|
|
||||||
static int Play(MIXPLAYPARAMS* lpMixPlayParams);
|
|
||||||
|
|
||||||
private:
|
|
||||||
static GLOBALS* SessionToGlobalDataPtr(HANDLE hMixSession);
|
|
||||||
static int Startup(HMODULE hModule);
|
|
||||||
static int SetIniFileName(HMODULE hModule);
|
|
||||||
static void InitChannelNodes();
|
|
||||||
static void InitVolumeTable();
|
|
||||||
static void ShowWaveOutDevices();
|
|
||||||
static int RemoveInvalidIniNameCharacters(char* lpString);
|
|
||||||
static int ReadConfigSettings(MIXCONFIG* lpConfig);
|
|
||||||
static int ReadRegistryForAppSpecificConfigs(MIXCONFIG* lpConfig);
|
|
||||||
static int ReadRegistryInt(HKEY hKey, LPCSTR lpSubKey, int defaultValue);
|
|
||||||
static int DefaultGoodWavePos(unsigned int uDeviceID);
|
|
||||||
static int DefaultPauseBlocks(int waveBlocks);
|
|
||||||
static int Configure(GLOBALS* hMixSession, HWND hWndParent, MIXCONFIG* lpConfig, int* flag1Ptr, int saveConfigFlag);
|
|
||||||
static int GetConfig(HANDLE hMixSession, MIXCONFIG* lpConfig);
|
|
||||||
static unsigned MyWaveOutGetPosition(HWAVEOUT hWaveOut, int fGoodGetPos);
|
|
||||||
static void FreeChannelNode(CHANNELNODE* channel);
|
|
||||||
static int ResetRemix(DWORD dwRemixSamplePos, CHANNELNODE* channel);
|
|
||||||
static XWAVEHDR* RemoveFromPlayingQueue(XWAVEHDR* lpXWH);
|
|
||||||
static void DestroyPlayQueue();
|
|
||||||
static void SwapWaveBlocks();
|
|
||||||
static XWAVEHDR* GetWaveBlock();
|
|
||||||
static int MixerPlay(XWAVEHDR* lpXWH, int fWriteBlocks);
|
|
||||||
static XWAVEHDR* AddToPlayingQueue(XWAVEHDR* lpXWH);
|
|
||||||
static void MyWaveOutReset(HWAVEOUT hWaveOut);
|
|
||||||
static void SetWaveOutPosition(unsigned int newPosition);
|
|
||||||
static DWORD SubFactor(DWORD a1, DWORD a2);
|
|
||||||
static DWORD AddFactor(DWORD a1, DWORD a2);
|
|
||||||
static dialog_template* MakeSettingsDlgTemplate();
|
|
||||||
static dialog_template* MakeDlgTemplate(size_t* totalSize, unsigned style, int16_t x, int16_t y, int16_t cx,
|
|
||||||
int16_t cy,
|
|
||||||
const wchar_t* String);
|
|
||||||
static dialog_template* AddDlgControl(size_t* totalSize, dialog_template* dlgTemplate, int16_t idClass,
|
|
||||||
unsigned style,
|
|
||||||
WORD id, int16_t x, int16_t y, int16_t cx, int16_t cy,
|
|
||||||
const wchar_t* String);
|
|
||||||
static void DestroySettingsDlgTemplate(LPCVOID pMem);
|
|
||||||
static int Settings_OnInitDialog(HWND hWnd, WPARAM wParam, MIXCONFIG* lpMixconfig);
|
|
||||||
static int Settings_OnCommand(HWND hWnd, int command, LPARAM lParam, int wParam);
|
|
||||||
static int ReadRegistryToGetMachineSpecificInfSection(unsigned wDeviceId, LPSTR lpString1, int maxLength);
|
|
||||||
static const char* GetOperatingSystemPrefix();
|
|
||||||
static unsigned int FigureOutDMABufferSize(unsigned int waveBlockLen, PCMWAVEFORMAT* pcm);
|
|
||||||
static int NoResetRemix(DWORD dwRemixSamplePos, CHANNELNODE* channel);
|
|
||||||
static void SaveConfigSettings(unsigned dwFlags);
|
|
||||||
static void ShowCurrentSettings();
|
|
||||||
static unsigned int GetWaveDevice();
|
|
||||||
static void FreeWaveBlocks(HWAVEOUT hwo, XWAVEHDR** waveBlocks);
|
|
||||||
static int AllocWaveBlocks(HWAVEOUT hwo, XWAVEHDR** waveBlocks);
|
|
||||||
static void ReleaseWaveDevice(GLOBALS* globals);
|
|
||||||
static HPSTR WaveFormatConvert(PCMWAVEFORMAT* lpOutWF, PCMWAVEFORMAT* lpInWF, HPSTR lpInData, DWORD* dwDataSize);
|
|
||||||
static HPSTR BitsPerSampleAlign(HPSTR lpInData, WORD nInBPS, WORD nOutBPS, DWORD* dwDataSize);
|
|
||||||
static HPSTR ChannelAlign(HPSTR lpInData, WORD nInChannels, WORD nOutChannels, WORD nBytesPerSample,
|
|
||||||
DWORD* dwDataSize);
|
|
||||||
static HPSTR SamplesPerSecAlign(HPSTR lpInData, DWORD nInSamplesPerSec, DWORD nOutSamplesPerSec,
|
|
||||||
WORD nBytesPerSample, WORD nChannels, DWORD* dwDataSize);
|
|
||||||
static void AvgSample(HPSTR lpOutData, HPSTR lpInData, unsigned nSkip, int nBytesPerSample, int nChannels);
|
|
||||||
static void RepSample(HPSTR lpOutData, HPSTR lpInData, unsigned nRep, int nBytesPerSample, int nChannels);
|
|
||||||
static bool IsValidLPMIXWAVE(MIXWAVE* lpMixWave);
|
|
||||||
static void FreePlayedBlocks();
|
|
||||||
static int HasCurrentOutputFormat(MIXWAVE* lpMixWave);
|
|
||||||
static CHANNELNODE* GetChannelNode();
|
|
||||||
static void ResetWavePosIfNoChannelData();
|
|
||||||
static void cmixit(uint8_t* lpDest, uint8_t** rgWaveSrc, volume_struct* volumeArr, int iNumWaves,
|
|
||||||
uint16_t length);
|
|
||||||
static LRESULT __stdcall WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
|
|
||||||
static INT_PTR __stdcall SettingsDlgProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
|
|
||||||
|
|
||||||
static int initialized_flag;
|
|
||||||
static char FileName[276];
|
|
||||||
static CHANNELNODE channel_nodes[MAXQUEUEDWAVES];
|
|
||||||
static CHANNELNODE* free_channel_nodes;
|
|
||||||
static unsigned char volume_table[11][256];
|
|
||||||
static int debug_flag;
|
|
||||||
static void (*cmixit_ptr)(uint8_t* lpDest, uint8_t** rgWaveSrc, volume_struct* volume,
|
|
||||||
int iNumWaves, uint16_t length);
|
|
||||||
static HMODULE HModule;
|
|
||||||
static GLOBALS *Globals, *GlobalsActive;
|
|
||||||
static PCMWAVEFORMAT gpFormat;
|
|
||||||
static int ShowDebugDialogs;
|
|
||||||
static char string_buffer[256];
|
|
||||||
static PLAYQUEUE play_queue;
|
|
||||||
static CHANNELNODE* play_channel_array[MAXCHANNELS];
|
|
||||||
static XWAVEHDR* block_array1[10];
|
|
||||||
static XWAVEHDR* block_array2[10];
|
|
||||||
static unsigned char* play_data[MAXCHANNELS];
|
|
||||||
static volume_struct play_volume[MAXCHANNELS];
|
|
||||||
static int play_counter;
|
|
||||||
};
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -71,6 +71,7 @@ public:
|
|||||||
static component_tag_base *wormhole_tag_array1[3], *wormhole_tag_array2[3], *wormhole_tag_array3[3];
|
static component_tag_base *wormhole_tag_array1[3], *wormhole_tag_array2[3], *wormhole_tag_array3[3];
|
||||||
|
|
||||||
static void make_links(TPinballTable* table);
|
static void make_links(TPinballTable* table);
|
||||||
|
static void ClearLinks();
|
||||||
static TPinballComponent* make_component_link(component_tag_base* tag);
|
static TPinballComponent* make_component_link(component_tag_base* tag);
|
||||||
static void handler(int code, TPinballComponent* cmp);
|
static void handler(int code, TPinballComponent* cmp);
|
||||||
static void pbctrl_bdoor_controller(char key);
|
static void pbctrl_bdoor_controller(char key);
|
||||||
|
|||||||
@@ -9,17 +9,9 @@
|
|||||||
|
|
||||||
|
|
||||||
int fullscrn::screen_mode;
|
int fullscrn::screen_mode;
|
||||||
HWND fullscrn::hWnd;
|
|
||||||
tagRECT fullscrn::WindowRect1, fullscrn::WindowRect2;
|
|
||||||
rectangle_type fullscrn::WHRect;
|
|
||||||
int fullscrn::fullscrn_flag1;
|
|
||||||
int fullscrn::display_changed;
|
int fullscrn::display_changed;
|
||||||
int fullscrn::ChangeDisplay, fullscrn::ignoreNextDisplayChangeFg;
|
|
||||||
int fullscrn::trick = 1;
|
|
||||||
int fullscrn::MenuEnabled;
|
|
||||||
HMENU fullscrn::MenuHandle;
|
|
||||||
int fullscrn::resolution = 0;
|
int fullscrn::resolution = 0;
|
||||||
int fullscrn::maxResolution = 0;
|
|
||||||
const resolution_info fullscrn::resolution_array[3] =
|
const resolution_info fullscrn::resolution_array[3] =
|
||||||
{
|
{
|
||||||
{640, 480, 600, 416, 501},
|
{640, 480, 600, 416, 501},
|
||||||
@@ -31,42 +23,9 @@ float fullscrn::ScaleY = 1;
|
|||||||
int fullscrn::OffsetX = 0;
|
int fullscrn::OffsetX = 0;
|
||||||
int fullscrn::OffsetY = 0;
|
int fullscrn::OffsetY = 0;
|
||||||
|
|
||||||
void fullscrn::init(int width, int height, int isFullscreen, HWND winHandle, HMENU menuHandle, int changeDisplay)
|
void fullscrn::init()
|
||||||
{
|
{
|
||||||
WHRect.XPosition = 0;
|
|
||||||
WHRect.YPosition = 0;
|
|
||||||
ChangeDisplay = changeDisplay;
|
|
||||||
hWnd = winHandle;
|
|
||||||
MenuHandle = menuHandle;
|
|
||||||
WHRect.Width = width;
|
|
||||||
WHRect.Height = height;
|
|
||||||
|
|
||||||
GetWindowRect(GetDesktopWindow(), &fullscrn::WindowRect1);
|
|
||||||
int widht2 = width + 2 * GetSystemMetrics(SM_CXBORDER);
|
|
||||||
int height2 = height + 2 * GetSystemMetrics(SM_CYBORDER);
|
|
||||||
int menuHeight = GetSystemMetrics(SM_CYMENU);
|
|
||||||
int captionHeight = GetSystemMetrics(SM_CYCAPTION);
|
|
||||||
int borderHeight = WindowRect1.bottom - WindowRect1.top - height2;
|
|
||||||
|
|
||||||
WindowRect2.bottom = borderHeight / 2 - 2 + height2 + 4;
|
|
||||||
WindowRect2.right = (WindowRect1.right - WindowRect1.left - widht2) / 2 - 2 + widht2 + 4;
|
|
||||||
WindowRect2.left = (WindowRect1.right - WindowRect1.left - widht2) / 2 - 2;
|
|
||||||
WindowRect2.top = borderHeight / 2 - (captionHeight + menuHeight) - 2;
|
|
||||||
|
|
||||||
/*RECT client{0,0,width,height};
|
|
||||||
AdjustWindowRect(&client, winmain::WndStyle, true);*/
|
|
||||||
MoveWindow(
|
|
||||||
hWnd,
|
|
||||||
(WindowRect1.right - WindowRect1.left - widht2) / 2 - 2,
|
|
||||||
WindowRect2.top,
|
|
||||||
WindowRect2.right - WindowRect2.left + 10,
|
|
||||||
WindowRect2.bottom - WindowRect2.top + 10,
|
|
||||||
0);
|
|
||||||
// Todo: WH + 10 hack: original request 640x480 window but somehow receives 650x490, even thought spyxx says it is 640x480
|
|
||||||
fullscrn_flag1 = 0;
|
|
||||||
|
|
||||||
window_size_changed();
|
window_size_changed();
|
||||||
assertm(ScaleX == 1 && ScaleY == 1, "Wrong default client size");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void fullscrn::shutdown()
|
void fullscrn::shutdown()
|
||||||
@@ -83,72 +42,27 @@ int fullscrn::set_screen_mode(int isFullscreen)
|
|||||||
screen_mode = isFullscreen;
|
screen_mode = isFullscreen;
|
||||||
if (isFullscreen)
|
if (isFullscreen)
|
||||||
{
|
{
|
||||||
if (IsWindowVisible(hWnd))
|
|
||||||
GetWindowRect(hWnd, &WindowRect2);
|
|
||||||
enableFullscreen();
|
enableFullscreen();
|
||||||
BYTE1(fullscrn_flag1) |= 0x80u;
|
result = 1;
|
||||||
InvalidateRect(hWnd, nullptr, 1);
|
|
||||||
set_menu_mode(0);
|
|
||||||
result = disableWindowFlagsDisDlg();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
disableFullscreen();
|
disableFullscreen();
|
||||||
BYTE1(fullscrn_flag1) |= 0x80u;
|
result = 1;
|
||||||
InvalidateRect(hWnd, nullptr, 1);
|
|
||||||
set_menu_mode(1);
|
|
||||||
result = RedrawWindow(nullptr, nullptr, nullptr, 0x185u);
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int fullscrn::disableWindowFlagsDisDlg()
|
|
||||||
{
|
|
||||||
long style = GetWindowLongA(hWnd, -16);
|
|
||||||
return SetWindowLongA(hWnd, -16, style & ~(WS_CAPTION | WS_THICKFRAME));
|
|
||||||
}
|
|
||||||
|
|
||||||
int fullscrn::setWindowFlagsDisDlg()
|
|
||||||
{
|
|
||||||
int style = GetWindowLongA(hWnd, -16);
|
|
||||||
return SetWindowLongA(hWnd, -16, style | WS_CAPTION | WS_THICKFRAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
int fullscrn::enableFullscreen()
|
int fullscrn::enableFullscreen()
|
||||||
{
|
{
|
||||||
tagRECT Rect{};
|
if (!display_changed)
|
||||||
DEVMODEA DevMode{};
|
|
||||||
|
|
||||||
if (ChangeDisplay && !display_changed)
|
|
||||||
{
|
{
|
||||||
DevMode.dmSize = sizeof DevMode;
|
if (SDL_SetWindowFullscreen(winmain::MainWindow, SDL_WINDOW_FULLSCREEN_DESKTOP) == 0)
|
||||||
DevMode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
|
|
||||||
DevMode.dmPelsWidth = resolution_array[resolution].ScreenWidth;
|
|
||||||
DevMode.dmPelsHeight = resolution_array[resolution].ScreenHeight;
|
|
||||||
DevMode.dmBitsPerPel = 32;
|
|
||||||
disableWindowFlagsDisDlg();
|
|
||||||
if (trick)
|
|
||||||
{
|
{
|
||||||
GetWindowRect(GetDesktopWindow(), &Rect);
|
display_changed = 1;
|
||||||
SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, Rect.right - Rect.left + 1,
|
|
||||||
Rect.bottom - Rect.top + 1, SWP_NOREDRAW);
|
|
||||||
}
|
|
||||||
ignoreNextDisplayChangeFg = 1;
|
|
||||||
LONG changeDispResult = ChangeDisplaySettingsA(&DevMode, CDS_FULLSCREEN);
|
|
||||||
if (changeDispResult == DISP_CHANGE_RESTART)
|
|
||||||
{
|
|
||||||
DevMode.dmFields &= ~DM_BITSPERPEL;
|
|
||||||
ignoreNextDisplayChangeFg = 1;
|
|
||||||
changeDispResult = ChangeDisplaySettingsA(&DevMode, CDS_FULLSCREEN);
|
|
||||||
}
|
|
||||||
display_changed = changeDispResult == DISP_CHANGE_SUCCESSFUL;
|
|
||||||
if (display_changed)
|
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
GetWindowRect(GetDesktopWindow(), &Rect);
|
|
||||||
disableWindowFlagsDisDlg();
|
|
||||||
SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, Rect.right - Rect.left + 1, Rect.bottom - Rect.top + 1, SWP_NOREDRAW);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,152 +70,11 @@ int fullscrn::disableFullscreen()
|
|||||||
{
|
{
|
||||||
if (display_changed)
|
if (display_changed)
|
||||||
{
|
{
|
||||||
display_changed = 0;
|
if (SDL_SetWindowFullscreen(winmain::MainWindow, 0) == 0)
|
||||||
ignoreNextDisplayChangeFg = 1;
|
|
||||||
ChangeDisplaySettingsA(nullptr, CDS_FULLSCREEN);
|
|
||||||
if (trick)
|
|
||||||
SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
|
|
||||||
}
|
|
||||||
setWindowFlagsDisDlg();
|
|
||||||
SetWindowPos(
|
|
||||||
hWnd,
|
|
||||||
HWND_TOP,
|
|
||||||
WindowRect2.left,
|
|
||||||
WindowRect2.top,
|
|
||||||
WindowRect2.right - WindowRect2.left,
|
|
||||||
WindowRect2.bottom - WindowRect2.top,
|
|
||||||
SWP_NOZORDER | SWP_NOACTIVATE);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool fullscrn::set_menu_mode(int menuEnabled)
|
|
||||||
{
|
|
||||||
BOOL result;
|
|
||||||
|
|
||||||
MenuEnabled = menuEnabled;
|
|
||||||
GetWindowCenter();
|
|
||||||
if (MenuEnabled)
|
|
||||||
{
|
|
||||||
fullscrn_flag1 |= 2u;
|
|
||||||
InvalidateRect(hWnd, nullptr, 1);
|
|
||||||
result = SetMenu(hWnd, MenuHandle);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fullscrn_flag1 |= 1u;
|
|
||||||
InvalidateRect(hWnd, nullptr, 1);
|
|
||||||
result = SetMenu(hWnd, nullptr);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void fullscrn::GetWindowCenter()
|
|
||||||
{
|
|
||||||
int yPos;
|
|
||||||
tagRECT Rect{};
|
|
||||||
|
|
||||||
if (screen_mode)
|
|
||||||
{
|
|
||||||
GetWindowRect(GetDesktopWindow(), &Rect);
|
|
||||||
render::vscreen.XPosition = (Rect.right - render::vscreen.Width - Rect.left) / 2;
|
|
||||||
yPos = (Rect.bottom - render::vscreen.Height - Rect.top) / 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
render::vscreen.XPosition = 0;
|
|
||||||
yPos = GetSystemMetrics(15);
|
|
||||||
}
|
|
||||||
render::vscreen.YPosition = yPos;
|
|
||||||
if (MenuEnabled)
|
|
||||||
render::vscreen.YPosition -= GetSystemMetrics(15);
|
|
||||||
}
|
|
||||||
|
|
||||||
void fullscrn::force_redraw()
|
|
||||||
{
|
|
||||||
BYTE1(fullscrn_flag1) |= 0x80u;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void fullscrn::center_in(HWND parent, HWND child)
|
|
||||||
{
|
|
||||||
LONG right;
|
|
||||||
tagRECT childRect{}, parentRect{}, desktopRect{};
|
|
||||||
|
|
||||||
GetWindowRect(parent, &parentRect);
|
|
||||||
GetWindowRect(child, &childRect);
|
|
||||||
GetWindowRect(GetDesktopWindow(), &desktopRect);
|
|
||||||
if (display_changed)
|
|
||||||
{
|
|
||||||
desktopRect.bottom = 480;
|
|
||||||
desktopRect.left = 0;
|
|
||||||
desktopRect.top = 0;
|
|
||||||
right = 640;
|
|
||||||
desktopRect.right = 640;
|
|
||||||
parentRect.left = 0;
|
|
||||||
parentRect.top = 0;
|
|
||||||
parentRect.right = 640;
|
|
||||||
parentRect.bottom = 480;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
right = desktopRect.right;
|
|
||||||
}
|
|
||||||
|
|
||||||
int childHeight = childRect.bottom - childRect.top;
|
|
||||||
int smthWidth = parentRect.left + (parentRect.right + childRect.left - childRect.right - parentRect.left) / 2;
|
|
||||||
int smthHeight = parentRect.top + (parentRect.bottom + childRect.top - childRect.bottom - parentRect.top) / 2;
|
|
||||||
if (childRect.right - childRect.left + smthWidth > right)
|
|
||||||
smthWidth = right - (childRect.right - childRect.left);
|
|
||||||
if (childHeight + smthHeight > desktopRect.bottom)
|
|
||||||
smthHeight = desktopRect.bottom - childHeight;
|
|
||||||
if (smthWidth < desktopRect.left)
|
|
||||||
smthWidth = desktopRect.left;
|
|
||||||
if (smthHeight < desktopRect.top)
|
|
||||||
smthHeight = desktopRect.top;
|
|
||||||
MoveWindow(child, smthWidth, smthHeight, childRect.right - childRect.left, childRect.bottom - childRect.top, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int fullscrn::displaychange()
|
|
||||||
{
|
|
||||||
int result = 0;
|
|
||||||
if (ignoreNextDisplayChangeFg)
|
|
||||||
{
|
|
||||||
ignoreNextDisplayChangeFg = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (screen_mode && display_changed)
|
|
||||||
{
|
|
||||||
display_changed = 0;
|
display_changed = 0;
|
||||||
screen_mode = 0;
|
|
||||||
setWindowFlagsDisDlg();
|
|
||||||
BYTE1(fullscrn_flag1) |= 0x80u;
|
|
||||||
InvalidateRect(hWnd, nullptr, 1);
|
|
||||||
set_menu_mode(1);
|
|
||||||
SetWindowPos(
|
|
||||||
hWnd,
|
|
||||||
HWND_TOP,
|
|
||||||
WindowRect2.left,
|
|
||||||
WindowRect2.top,
|
|
||||||
WindowRect2.right - WindowRect2.left,
|
|
||||||
WindowRect2.bottom - WindowRect2.top,
|
|
||||||
SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE);
|
|
||||||
result = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SetWindowPos(
|
|
||||||
hWnd,
|
|
||||||
HWND_TOP,
|
|
||||||
WindowRect2.left,
|
|
||||||
WindowRect2.top,
|
|
||||||
WindowRect2.right - WindowRect2.left,
|
|
||||||
WindowRect2.bottom - WindowRect2.top,
|
|
||||||
SWP_NOZORDER | SWP_NOACTIVATE);
|
|
||||||
}
|
|
||||||
center_in(GetDesktopWindow(), hWnd);
|
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fullscrn::activate(int flag)
|
void fullscrn::activate(int flag)
|
||||||
@@ -311,146 +84,49 @@ void fullscrn::activate(int flag)
|
|||||||
if (!flag)
|
if (!flag)
|
||||||
{
|
{
|
||||||
set_screen_mode(0);
|
set_screen_mode(0);
|
||||||
SetWindowPos(hWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void fullscrn::fillRect(int right, int bottom, int left, int top)
|
|
||||||
{
|
|
||||||
RECT rc;
|
|
||||||
auto brush = CreateSolidBrush(0);
|
|
||||||
if (brush)
|
|
||||||
{
|
|
||||||
auto dc = winmain::_GetDC(hWnd);
|
|
||||||
if (dc)
|
|
||||||
{
|
|
||||||
auto prevBrush = SelectObject(dc, brush);
|
|
||||||
rc.right = left + right + 1;
|
|
||||||
rc.bottom = top + bottom + 1;
|
|
||||||
rc.left = left;
|
|
||||||
rc.top = top;
|
|
||||||
FillRect(dc, &rc, brush);
|
|
||||||
SelectObject(dc, prevBrush);
|
|
||||||
ReleaseDC(hWnd, dc);
|
|
||||||
}
|
|
||||||
DeleteObject(brush);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned fullscrn::convert_mouse_pos(unsigned int mouseXY)
|
|
||||||
{
|
|
||||||
uint16_t x = mouseXY & 0xffFF - render::vscreen.XPosition;
|
|
||||||
uint16_t y = (mouseXY >> 16) - render::vscreen.YPosition;
|
|
||||||
return x | y << 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
void fullscrn::getminmaxinfo(MINMAXINFO* maxMin)
|
|
||||||
{
|
|
||||||
/*Block down-scaling lower than min resolution*/
|
|
||||||
maxMin->ptMinTrackSize = POINT
|
|
||||||
{
|
|
||||||
resolution_array[0].ScreenWidth / 2,
|
|
||||||
resolution_array[0].ScreenHeight / 2
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
void fullscrn::paint()
|
|
||||||
{
|
|
||||||
int menuHeight;
|
|
||||||
if (screen_mode)
|
|
||||||
{
|
|
||||||
if ((fullscrn_flag1 & 0x8000) == 0 && fullscrn_flag1)
|
|
||||||
{
|
|
||||||
if (fullscrn_flag1 & 1)
|
|
||||||
{
|
|
||||||
menuHeight = GetSystemMetrics(SM_CYMENU);
|
|
||||||
fillRect(WindowRect1.right - 1, menuHeight, 0, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (MenuEnabled)
|
|
||||||
menuHeight = GetSystemMetrics(SM_CYMENU);
|
|
||||||
else
|
|
||||||
menuHeight = 0;
|
|
||||||
fillRect(WindowRect1.right, menuHeight + WindowRect1.bottom, 0, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pb::paint();
|
|
||||||
fullscrn_flag1 = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int fullscrn::GetResolution()
|
int fullscrn::GetResolution()
|
||||||
{
|
{
|
||||||
return resolution;
|
return resolution;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fullscrn::SetResolution(int resolution)
|
void fullscrn::SetResolution(int value)
|
||||||
{
|
{
|
||||||
if (!pb::FullTiltMode)
|
if (!pb::FullTiltMode)
|
||||||
resolution = 0;
|
value = 0;
|
||||||
assertm(resolution >= 0 && resolution <= 2, "Resolution value out of bounds");
|
assertm(value >= 0 && value <= 2, "Resolution value out of bounds");
|
||||||
fullscrn::resolution = resolution;
|
resolution = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fullscrn::GetMaxResolution()
|
int fullscrn::GetMaxResolution()
|
||||||
{
|
{
|
||||||
return maxResolution;
|
return pb::FullTiltMode ? 2 : 0;
|
||||||
}
|
|
||||||
|
|
||||||
void fullscrn::SetMaxResolution(int resolution)
|
|
||||||
{
|
|
||||||
assertm(resolution >= 0 && resolution <= 2, "Resolution value out of bounds");
|
|
||||||
maxResolution = resolution;
|
|
||||||
}
|
|
||||||
|
|
||||||
int fullscrn::get_max_supported_resolution()
|
|
||||||
{
|
|
||||||
if (!pb::FullTiltMode)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
auto resolutionWH = get_screen_resolution();
|
|
||||||
auto width = LOWORD(resolutionWH);
|
|
||||||
auto height = HIWORD(resolutionWH);
|
|
||||||
auto result = 0;
|
|
||||||
|
|
||||||
for (auto index = 1; index < 3; ++index)
|
|
||||||
{
|
|
||||||
auto resPtr = &resolution_array[index];
|
|
||||||
if (resPtr->ScreenWidth <= width && resPtr->ScreenHeight <= height)
|
|
||||||
result = index;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
int fullscrn::get_screen_resolution()
|
|
||||||
{
|
|
||||||
auto height = static_cast<uint16_t>(GetSystemMetrics(SM_CYSCREEN));
|
|
||||||
return static_cast<uint16_t>(GetSystemMetrics(SM_CXSCREEN)) | (height << 16);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void fullscrn::window_size_changed()
|
void fullscrn::window_size_changed()
|
||||||
{
|
{
|
||||||
/*No scaling in fullscreen mode*/
|
int width, height;
|
||||||
if (display_changed)
|
SDL_GetRendererOutputSize(winmain::Renderer, &width, &height);
|
||||||
{
|
int menuHeight = options::Options.ShowMenu ? winmain::MainMenuHeight : 0;
|
||||||
ScaleY = ScaleX = 1;
|
height -= menuHeight;
|
||||||
OffsetX = OffsetY = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
RECT client{};
|
|
||||||
GetClientRect(hWnd, &client);
|
|
||||||
auto res = &resolution_array[resolution];
|
auto res = &resolution_array[resolution];
|
||||||
ScaleX = static_cast<float>(client.right) / res->TableWidth;
|
ScaleX = static_cast<float>(width) / res->TableWidth;
|
||||||
ScaleY = static_cast<float>(client.bottom) / res->TableHeight;
|
ScaleY = static_cast<float>(height) / res->TableHeight;
|
||||||
OffsetX = OffsetY = 0;
|
OffsetX = OffsetY = 0;
|
||||||
|
|
||||||
if (options::Options.UniformScaling)
|
if (options::Options.UniformScaling)
|
||||||
{
|
{
|
||||||
ScaleY = ScaleX = min(ScaleX, ScaleY);
|
ScaleY = ScaleX = std::min(ScaleX, ScaleY);
|
||||||
OffsetX = static_cast<int>(floor((client.right - res->TableWidth * ScaleX) / 2));
|
OffsetX = static_cast<int>(floor((width - res->TableWidth * ScaleX) / 2));
|
||||||
OffsetY = static_cast<int>(floor((client.bottom - res->TableHeight * ScaleY) / 2));
|
OffsetY = static_cast<int>(floor((height - res->TableHeight * ScaleY) / 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
render::DestinationRect = SDL_Rect
|
||||||
|
{
|
||||||
|
OffsetX, OffsetY + menuHeight,
|
||||||
|
width - OffsetX * 2, height - OffsetY * 2
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "maths.h"
|
|
||||||
|
|
||||||
#define BYTEn(x, n) (*((unsigned char*)&(x)+n))
|
|
||||||
#define BYTE1(x) BYTEn(x, 1) // byte 1 (counting from 0)
|
|
||||||
#define BYTE2(x) BYTEn(x, 2)
|
|
||||||
|
|
||||||
|
|
||||||
struct resolution_info
|
struct resolution_info
|
||||||
{
|
{
|
||||||
@@ -18,49 +12,25 @@ struct resolution_info
|
|||||||
class fullscrn
|
class fullscrn
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static int screen_mode;
|
static int screen_mode;
|
||||||
static HWND hWnd;
|
|
||||||
static tagRECT WindowRect1, WindowRect2;
|
|
||||||
static rectangle_type WHRect;
|
|
||||||
static int fullscrn_flag1;
|
|
||||||
static int display_changed;
|
static int display_changed;
|
||||||
static int ChangeDisplay, ignoreNextDisplayChangeFg;
|
|
||||||
static int trick;
|
|
||||||
static const resolution_info resolution_array[3];
|
static const resolution_info resolution_array[3];
|
||||||
static float ScaleX;
|
static float ScaleX;
|
||||||
static float ScaleY;
|
static float ScaleY;
|
||||||
static int OffsetX;
|
static int OffsetX;
|
||||||
static int OffsetY;
|
static int OffsetY;
|
||||||
|
|
||||||
static void init(int width, int height, int isFullscreen, HWND winHandle, HMENU menuHandle, int changeDisplay);
|
static void init();
|
||||||
static void shutdown();
|
static void shutdown();
|
||||||
static int set_screen_mode(int isFullscreen);
|
static int set_screen_mode(int isFullscreen);
|
||||||
static void force_redraw();
|
|
||||||
static void center_in(HWND parent, HWND child);
|
|
||||||
static int displaychange();
|
|
||||||
static void activate(int flag);
|
static void activate(int flag);
|
||||||
static unsigned convert_mouse_pos(unsigned int mouseXY);
|
|
||||||
static void getminmaxinfo(MINMAXINFO* maxMin);
|
|
||||||
static void paint();
|
|
||||||
static bool set_menu_mode(int menuEnabled);
|
|
||||||
static int GetResolution();
|
static int GetResolution();
|
||||||
static void SetResolution(int resolution);
|
static void SetResolution(int value);
|
||||||
static int GetMaxResolution();
|
static int GetMaxResolution();
|
||||||
static void SetMaxResolution(int resolution);
|
|
||||||
static int get_max_supported_resolution();
|
|
||||||
static int get_screen_resolution();
|
|
||||||
static void window_size_changed();
|
static void window_size_changed();
|
||||||
private :
|
private :
|
||||||
static int MenuEnabled;
|
|
||||||
static HMENU MenuHandle;
|
|
||||||
static int resolution;
|
static int resolution;
|
||||||
static int maxResolution;
|
|
||||||
|
|
||||||
static void GetWindowCenter();
|
|
||||||
static int disableWindowFlagsDisDlg();
|
|
||||||
static int setWindowFlagsDisDlg();
|
|
||||||
static int enableFullscreen();
|
static int enableFullscreen();
|
||||||
static int disableFullscreen();
|
static int disableFullscreen();
|
||||||
static void fillRect(int right, int bottom, int left, int top);
|
|
||||||
};
|
};
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,80 +1,74 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
enum class BitmapType : char
|
enum class BitmapTypes : uint8_t
|
||||||
{
|
{
|
||||||
None = 0,
|
None = 0,
|
||||||
RawBitmap = 1,
|
RawBitmap = 1,
|
||||||
DibBitmap = 2,
|
DibBitmap = 2,
|
||||||
Spliced = 4,
|
Spliced = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct Rgba
|
||||||
|
{
|
||||||
|
uint8_t Blue;
|
||||||
|
uint8_t Green;
|
||||||
|
uint8_t Red;
|
||||||
|
uint8_t Alpha;
|
||||||
|
};
|
||||||
|
|
||||||
|
union ColorRgba
|
||||||
|
{
|
||||||
|
ColorRgba() = default;
|
||||||
|
|
||||||
|
explicit ColorRgba(uint32_t color)
|
||||||
|
: Color(color)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit ColorRgba(Rgba rgba)
|
||||||
|
: rgba(rgba)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t Color;
|
||||||
|
Rgba rgba;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(ColorRgba) == 4, "Wrong size of RGBA color");
|
||||||
|
|
||||||
struct gdrv_bitmap8
|
struct gdrv_bitmap8
|
||||||
{
|
{
|
||||||
BITMAPINFO* Dib;
|
gdrv_bitmap8(int width, int height, bool indexed);
|
||||||
char* BmpBufPtr2;
|
gdrv_bitmap8(const struct dat8BitBmpHeader& header);
|
||||||
char* BmpBufPtr1;
|
~gdrv_bitmap8();
|
||||||
|
void ScaleIndexed(float scaleX, float scaleY);
|
||||||
|
ColorRgba* BmpBufPtr1;
|
||||||
|
char* IndexedBmpPtr;
|
||||||
int Width;
|
int Width;
|
||||||
int Height;
|
int Height;
|
||||||
int Stride;
|
int Stride;
|
||||||
BitmapType BitmapType;
|
int IndexedStride;
|
||||||
int Color6;
|
BitmapTypes BitmapType;
|
||||||
int XPosition;
|
int XPosition;
|
||||||
int YPosition;
|
int YPosition;
|
||||||
};
|
unsigned Resolution;
|
||||||
|
SDL_Texture* Texture;
|
||||||
struct LOGPALETTEx256 : LOGPALETTE
|
|
||||||
{
|
|
||||||
PALETTEENTRY palPalEntry2[256 - 1];
|
|
||||||
|
|
||||||
LOGPALETTEx256() : palPalEntry2{}
|
|
||||||
{
|
|
||||||
palVersion = 0x300;
|
|
||||||
palNumEntries = 256;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class gdrv
|
class gdrv
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static HPALETTE palette_handle;
|
static int display_palette(ColorRgba* plt);
|
||||||
static int sequence_handle;
|
static void fill_bitmap(gdrv_bitmap8* bmp, int width, int height, int xOff, int yOff, uint8_t fillChar);
|
||||||
static HDC sequence_hdc;
|
|
||||||
static int use_wing;
|
|
||||||
|
|
||||||
static int init(HINSTANCE hInst, HWND hWnd);
|
|
||||||
static int uninit();
|
|
||||||
static void get_focus();
|
|
||||||
static BITMAPINFO* DibCreate(int16_t bpp, int width, int height);
|
|
||||||
static void DibSetUsage(BITMAPINFO* dib, HPALETTE hpal, int someFlag);
|
|
||||||
static int create_bitmap_dib(gdrv_bitmap8* bmp, int width, int height);
|
|
||||||
static int create_bitmap(gdrv_bitmap8* bmp, int width, int height);
|
|
||||||
static int create_raw_bitmap(gdrv_bitmap8* bmp, int width, int height, int flag);
|
|
||||||
static int create_spliced_bitmap(gdrv_bitmap8* bmp, int width, int height, int size);
|
|
||||||
static int destroy_bitmap(gdrv_bitmap8* bmp);
|
|
||||||
static int display_palette(PALETTEENTRY* plt);
|
|
||||||
static void start_blit_sequence();
|
|
||||||
static void blit_sequence(gdrv_bitmap8* bmp, int xSrc, int ySrcOff, int xDest, int yDest, int DestWidth,
|
|
||||||
int DestHeight);
|
|
||||||
static void end_blit_sequence();
|
|
||||||
static void blit(gdrv_bitmap8* bmp, int xSrc, int ySrcOff, int xDest, int yDest, int DestWidth, int DestHeight);
|
|
||||||
static void blat(gdrv_bitmap8* bmp, int xDest, int yDest);
|
|
||||||
static void fill_bitmap(gdrv_bitmap8* bmp, int width, int height, int xOff, int yOff, char fillChar);
|
|
||||||
static void copy_bitmap(gdrv_bitmap8* dstBmp, int width, int height, int xOff, int yOff, gdrv_bitmap8* srcBmp,
|
static void copy_bitmap(gdrv_bitmap8* dstBmp, int width, int height, int xOff, int yOff, gdrv_bitmap8* srcBmp,
|
||||||
int srcXOff, int srcYOff);
|
int srcXOff, int srcYOff);
|
||||||
static void copy_bitmap_w_transparency(gdrv_bitmap8* dstBmp, int width, int height, int xOff, int yOff,
|
static void copy_bitmap_w_transparency(gdrv_bitmap8* dstBmp, int width, int height, int xOff, int yOff,
|
||||||
gdrv_bitmap8* srcBmp, int srcXOff, int srcYOff);
|
gdrv_bitmap8* srcBmp, int srcXOff, int srcYOff);
|
||||||
static void grtext_draw_ttext_in_box(LPCWSTR text, int xOff, int yOff, int width, int height);
|
static void grtext_draw_ttext_in_box(LPCSTR text, int xOff, int yOff, int width, int height, int a6);
|
||||||
|
static void ApplyPalette(gdrv_bitmap8& bmp);
|
||||||
|
static void CreatePreview(gdrv_bitmap8& bmp);
|
||||||
private:
|
private:
|
||||||
/*COLORONCOLOR or HALFTONE*/
|
static ColorRgba current_palette[256];
|
||||||
static const int stretchMode = COLORONCOLOR;
|
|
||||||
static HWND hwnd;
|
|
||||||
static HINSTANCE hinst;
|
|
||||||
static int grtext_blue;
|
|
||||||
static int grtext_green;
|
|
||||||
static int grtext_red;
|
|
||||||
|
|
||||||
static int StretchDIBitsScaled(HDC hdc, int xDest, int yDest, int DestWidth, int DestHeight, int xSrc, int ySrc,
|
|
||||||
int SrcWidth, int SrcHeight, gdrv_bitmap8* bmp, UINT iUsage,
|
|
||||||
DWORD rop);
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,110 +1,73 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "high_score.h"
|
#include "high_score.h"
|
||||||
|
|
||||||
#include "fullscrn.h"
|
|
||||||
#include "memory.h"
|
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "resource.h"
|
#include "pinball.h"
|
||||||
#include "winmain.h"
|
#include "score.h"
|
||||||
|
|
||||||
int high_score::dlg_enter_name;
|
int high_score::dlg_enter_name;
|
||||||
int high_score::dlg_score;
|
int high_score::dlg_score;
|
||||||
int high_score::dlg_position;
|
int high_score::dlg_position;
|
||||||
LPCWSTR high_score::default_name;
|
char high_score::default_name[32]{};
|
||||||
high_score_struct* high_score::dlg_hst;
|
high_score_struct* high_score::dlg_hst;
|
||||||
|
bool high_score::ShowDialog = false;
|
||||||
|
|
||||||
winhelp_entry high_score::help[21]
|
|
||||||
|
int high_score::read(high_score_struct* table)
|
||||||
{
|
{
|
||||||
winhelp_entry{0x70, 0x3E9},
|
char Buffer[20];
|
||||||
winhelp_entry{0x191, 0x3EB},
|
|
||||||
winhelp_entry{0x1F5, 0x3EB},
|
|
||||||
winhelp_entry{0x259, 0x3EB},
|
|
||||||
winhelp_entry{0x192, 0x3EB},
|
|
||||||
winhelp_entry{0x193, 0x3EB},
|
|
||||||
winhelp_entry{0x194, 0x3EB},
|
|
||||||
winhelp_entry{0x195, 0x3EB},
|
|
||||||
winhelp_entry{0x1F6, 0x3EB},
|
|
||||||
winhelp_entry{0x1F7, 0x3EB},
|
|
||||||
winhelp_entry{0x1F8, 0x3EB},
|
|
||||||
winhelp_entry{0x1F9, 0x3EB},
|
|
||||||
winhelp_entry{0x2BD, 0x3EB},
|
|
||||||
winhelp_entry{0x2BE, 0x3EB},
|
|
||||||
winhelp_entry{0x2BF, 0x3EB},
|
|
||||||
winhelp_entry{0x2C0, 0x3EB},
|
|
||||||
winhelp_entry{0x2C1, 0x3EB},
|
|
||||||
winhelp_entry{0x2C2, 0x3EB},
|
|
||||||
winhelp_entry{0x2C3, 0x3EB},
|
|
||||||
winhelp_entry{0x2C4, 0x3EB},
|
|
||||||
winhelp_entry{0, 0},
|
|
||||||
};
|
|
||||||
|
|
||||||
int high_score::read(high_score_struct* table, int* ptrToSmth)
|
int checkSum = 0;
|
||||||
{
|
|
||||||
char scoreBuffer[20];
|
|
||||||
wchar_t nameBuffer[20];
|
|
||||||
|
|
||||||
int scoreSum = 0;
|
|
||||||
clear_table(table);
|
clear_table(table);
|
||||||
char* buf1 = memory::allocate(300u);
|
|
||||||
if (!buf1)
|
|
||||||
return 1;
|
|
||||||
char* buf2 = memory::allocate(300u);
|
|
||||||
auto optPath = pinball::get_rc_string(166, 0);
|
|
||||||
for (auto position = 0; position < 5; ++position)
|
for (auto position = 0; position < 5; ++position)
|
||||||
{
|
{
|
||||||
auto tablePtr = &table[position];
|
auto tablePtr = &table[position];
|
||||||
|
|
||||||
wsprintfW(nameBuffer, L"%d.Name", position);
|
snprintf(Buffer, sizeof Buffer, "%d", position);
|
||||||
options::get_string(optPath, nameBuffer, tablePtr->Name, L"", 32);
|
strcat(Buffer, ".Name");
|
||||||
tablePtr->Name[31] = 0;
|
auto name = options::get_string(Buffer, "");
|
||||||
|
strncpy(tablePtr->Name, name.c_str(), sizeof tablePtr->Name);
|
||||||
|
|
||||||
sprintf_s(scoreBuffer, "%d.Score", position);
|
snprintf(Buffer, sizeof Buffer, "%d", position);
|
||||||
options::get_string(optPath, scoreBuffer, buf1, "", 300);
|
strcat(Buffer, ".Score");
|
||||||
tablePtr->Score = atol(buf1);
|
tablePtr->Score = options::get_int(Buffer, tablePtr->Score);
|
||||||
|
|
||||||
for (auto i = lstrlenW(tablePtr->Name) - 1; i >= 0; i--)
|
for (int i = static_cast<int>(strlen(tablePtr->Name)); --i >= 0; checkSum += tablePtr->Name[i])
|
||||||
scoreSum += tablePtr->Name[i];
|
{
|
||||||
scoreSum += tablePtr->Score;
|
}
|
||||||
|
checkSum += tablePtr->Score;
|
||||||
}
|
}
|
||||||
|
|
||||||
scramble_number_string(scoreSum, buf1);
|
auto verification = options::get_int("Verification", 7);
|
||||||
options::get_string(optPath, "Verification", buf2, "", 300);
|
if (checkSum != verification)
|
||||||
if (lstrcmpA(buf1, buf2))
|
|
||||||
clear_table(table);
|
clear_table(table);
|
||||||
memory::free(buf1);
|
|
||||||
memory::free(buf2);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int high_score::write(high_score_struct* table, int* ptrToSmth)
|
int high_score::write(high_score_struct* table)
|
||||||
{
|
{
|
||||||
char scoreBuffer[20];
|
char Buffer[20];
|
||||||
wchar_t nameBuffer[20];
|
|
||||||
|
|
||||||
int scoreSum = 0;
|
int checkSum = 0;
|
||||||
CHAR* buf = memory::allocate(300u);
|
|
||||||
if (!buf)
|
|
||||||
return 1;
|
|
||||||
auto optPath = pinball::get_rc_string(166, 0);
|
|
||||||
for (auto position = 0; position < 5; ++position)
|
for (auto position = 0; position < 5; ++position)
|
||||||
{
|
{
|
||||||
auto tablePtr = &table[position];
|
auto tablePtr = &table[position];
|
||||||
|
|
||||||
wsprintfW(nameBuffer, L"%d.Name", position);
|
snprintf(Buffer, sizeof Buffer, "%d", position);
|
||||||
options::set_string(optPath, nameBuffer, tablePtr->Name);
|
strcat(Buffer, ".Name");
|
||||||
|
options::set_string(Buffer, tablePtr->Name);
|
||||||
|
|
||||||
sprintf_s(scoreBuffer, "%d.Score", position);
|
snprintf(Buffer, sizeof Buffer, "%d", position);
|
||||||
_ltoa_s(tablePtr->Score, buf, 300, 10);
|
strcat(Buffer, ".Score");
|
||||||
options::set_string(optPath, scoreBuffer, buf);
|
options::set_int(Buffer, tablePtr->Score);
|
||||||
|
|
||||||
for (auto i = lstrlenW(tablePtr->Name) - 1; i >= 0; i--)
|
for (int i = static_cast<int>(strlen(tablePtr->Name)); --i >= 0; checkSum += tablePtr->Name[i])
|
||||||
scoreSum += tablePtr->Name[i];
|
{
|
||||||
scoreSum += tablePtr->Score;
|
}
|
||||||
|
checkSum += tablePtr->Score;
|
||||||
}
|
}
|
||||||
|
|
||||||
scramble_number_string(scoreSum, buf);
|
options::set_int("Verification", checkSum);
|
||||||
options::set_string(optPath, "Verification", buf);
|
|
||||||
memory::free(buf);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,7 +94,7 @@ int high_score::get_score_position(high_score_struct* table, int score)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int high_score::place_new_score_into(high_score_struct* table, int score, LPWSTR name, int position)
|
int high_score::place_new_score_into(high_score_struct* table, int score, LPSTR scoreStr, int position)
|
||||||
{
|
{
|
||||||
if (position >= 0)
|
if (position >= 0)
|
||||||
{
|
{
|
||||||
@@ -149,152 +112,120 @@ int high_score::place_new_score_into(high_score_struct* table, int score, LPWSTR
|
|||||||
}
|
}
|
||||||
high_score_struct* posTable = &table[position];
|
high_score_struct* posTable = &table[position];
|
||||||
posTable->Score = score;
|
posTable->Score = score;
|
||||||
if (lstrlenW(name) >= 31)
|
if (strlen(scoreStr) >= 31)
|
||||||
name[31] = 0;
|
scoreStr[31] = 0;
|
||||||
lstrcpyW(posTable->Name, name);
|
strncpy(posTable->Name, scoreStr, sizeof posTable->Name);
|
||||||
posTable->Name[31] = 0;
|
posTable->Name[31] = 0;
|
||||||
}
|
}
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
void high_score::scramble_number_string(int Value, char* Buffer)
|
|
||||||
{
|
|
||||||
_ltoa_s(Value, Buffer, 300, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
void high_score::show_high_score_dialog(high_score_struct* table)
|
void high_score::show_high_score_dialog(high_score_struct* table)
|
||||||
{
|
{
|
||||||
dlg_enter_name = 0;
|
dlg_enter_name = 0;
|
||||||
dlg_score = 0;
|
dlg_score = 0;
|
||||||
dlg_hst = table;
|
dlg_hst = table;
|
||||||
DialogBoxParamW(winmain::hinst, L"dlg_highscores", winmain::hwnd_frame, HighScore, 0);
|
ShowDialog = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void high_score::show_and_set_high_score_dialog(high_score_struct* table, int score, int pos, LPCWSTR defaultName)
|
void high_score::show_and_set_high_score_dialog(high_score_struct* table, int score, int pos, LPCSTR defaultName)
|
||||||
{
|
{
|
||||||
dlg_position = pos;
|
dlg_position = pos;
|
||||||
dlg_score = score;
|
dlg_score = score;
|
||||||
dlg_hst = table;
|
dlg_hst = table;
|
||||||
dlg_enter_name = 1;
|
dlg_enter_name = 1;
|
||||||
default_name = defaultName;
|
strncpy(default_name, defaultName, sizeof default_name - 1);
|
||||||
while (DialogBoxParamW(winmain::hinst, L"dlg_highscores", winmain::hwnd_frame, HighScore, 0))
|
ShowDialog = true;
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
INT_PTR high_score::HighScore(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
void high_score::RenderHighScoreDialog()
|
||||||
{
|
{
|
||||||
HWND parent;
|
if (ShowDialog == true)
|
||||||
int nIDDlgItem;
|
|
||||||
wchar_t name[32];
|
|
||||||
|
|
||||||
switch (msg)
|
|
||||||
{
|
{
|
||||||
case WM_CLOSE:
|
ShowDialog = false;
|
||||||
SendMessageA(hWnd, WM_COMMAND, WM_DESTROY, 0);
|
if (dlg_position == -1)
|
||||||
break;
|
|
||||||
case WM_HELP:
|
|
||||||
WinHelpA(static_cast<HWND>(reinterpret_cast<HELPINFO*>(lParam)->hItemHandle), "pinball.hlp", HELP_WM_HELP,
|
|
||||||
(ULONG_PTR)help);
|
|
||||||
break;
|
|
||||||
case WM_CONTEXTMENU:
|
|
||||||
WinHelpA((HWND)wParam, "pinball.hlp", HELP_CONTEXTMENU, (ULONG_PTR)help);
|
|
||||||
break;
|
|
||||||
case WM_INITDIALOG:
|
|
||||||
show_high_scores(hWnd, dlg_hst);
|
|
||||||
for (nIDDlgItem = DLG_HIGHSCORES_EditName1; nIDDlgItem < 611; ++nIDDlgItem)
|
|
||||||
{
|
{
|
||||||
ShowWindow(GetDlgItem(hWnd, nIDDlgItem), SW_HIDE);
|
dlg_enter_name = 0;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (dlg_enter_name == 1)
|
ImGui::OpenPopup("High Scores");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool unused_open = true;
|
||||||
|
if (ImGui::BeginPopupModal("High Scores", &unused_open, ImGuiWindowFlags_AlwaysAutoResize))
|
||||||
|
{
|
||||||
|
if (ImGui::BeginTable("table1", 3, 0))
|
||||||
{
|
{
|
||||||
if (dlg_position == -1)
|
char buf[36];
|
||||||
|
ImGui::TableSetupColumn("Rank");
|
||||||
|
ImGui::TableSetupColumn("Name");
|
||||||
|
ImGui::TableSetupColumn("Score");
|
||||||
|
ImGui::TableHeadersRow();
|
||||||
|
|
||||||
|
for (int offset = 0, row = 0; row < 5; row++)
|
||||||
{
|
{
|
||||||
dlg_enter_name = 0;
|
ImGui::TableNextRow();
|
||||||
return 1;
|
ImGui::TableNextColumn();
|
||||||
|
snprintf(buf, sizeof buf, "%d", row);
|
||||||
|
ImGui::TextUnformatted(buf);
|
||||||
|
|
||||||
|
auto currentRow = &dlg_hst[row + offset];
|
||||||
|
auto score = currentRow->Score;
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
if (dlg_enter_name == 1 && dlg_position == row)
|
||||||
|
{
|
||||||
|
offset = -1;
|
||||||
|
score = dlg_score;
|
||||||
|
ImGui::PushItemWidth(200);
|
||||||
|
ImGui::InputText("", default_name, IM_ARRAYSIZE(default_name));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ImGui::TextUnformatted(currentRow->Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
score::string_format(score, buf);
|
||||||
|
ImGui::TextUnformatted(buf);
|
||||||
}
|
}
|
||||||
HWND nameTextBox = GetDlgItem(hWnd, dlg_position + DLG_HIGHSCORES_EditName1);
|
ImGui::EndTable();
|
||||||
ShowWindow(nameTextBox, SW_SHOW);
|
|
||||||
EnableWindow(nameTextBox, 1);
|
|
||||||
SetFocus(nameTextBox);
|
|
||||||
if (default_name)
|
|
||||||
{
|
|
||||||
SetWindowTextW(nameTextBox, default_name);
|
|
||||||
SendMessageA(nameTextBox, EM_SETSEL, 0, -1);
|
|
||||||
}
|
|
||||||
SendMessageA(nameTextBox, EM_SETLIMITTEXT, 31u, 0);
|
|
||||||
}
|
}
|
||||||
else
|
ImGui::Separator();
|
||||||
|
|
||||||
|
if (ImGui::Button("Ok"))
|
||||||
{
|
{
|
||||||
SetFocus(hWnd);
|
if (dlg_enter_name)
|
||||||
}
|
|
||||||
parent = GetParent(hWnd);
|
|
||||||
if (parent)
|
|
||||||
fullscrn::center_in(parent, hWnd);
|
|
||||||
return 0;
|
|
||||||
case WM_COMMAND:
|
|
||||||
switch (wParam)
|
|
||||||
{
|
|
||||||
case DLG_HIGHSCORES_Ok:
|
|
||||||
if (dlg_enter_name != 1)
|
|
||||||
{
|
{
|
||||||
break;
|
default_name[31] = 0;
|
||||||
|
place_new_score_into(dlg_hst, dlg_score, default_name, dlg_position);
|
||||||
}
|
}
|
||||||
GetDlgItemTextW(hWnd, dlg_position + DLG_HIGHSCORES_EditName1, name, 32);
|
ImGui::CloseCurrentPopup();
|
||||||
name[31] = 0;
|
}
|
||||||
place_new_score_into(dlg_hst, dlg_score, name, dlg_position);
|
|
||||||
break;
|
ImGui::SameLine();
|
||||||
case DLG_HIGHSCORES_Cancel:
|
if (ImGui::Button("Cancel"))
|
||||||
break;
|
ImGui::CloseCurrentPopup();
|
||||||
case DLG_HIGHSCORES_Clear:
|
|
||||||
if (MessageBoxW(hWnd, pinball::get_rc_Wstring(40, 0),
|
ImGui::SameLine();
|
||||||
pinball::get_rc_Wstring(41, 0), MB_DEFBUTTON2 | MB_OKCANCEL) == 1)
|
if (ImGui::Button("Clear"))
|
||||||
|
ImGui::OpenPopup("Confirm");
|
||||||
|
if (ImGui::BeginPopupModal("Confirm", nullptr, ImGuiWindowFlags_MenuBar))
|
||||||
|
{
|
||||||
|
ImGui::TextUnformatted(pinball::get_rc_string(40, 0));
|
||||||
|
if (ImGui::Button("OK", ImVec2(120, 0)))
|
||||||
{
|
{
|
||||||
clear_table(dlg_hst);
|
clear_table(dlg_hst);
|
||||||
if (dlg_enter_name)
|
ImGui::CloseCurrentPopup();
|
||||||
EndDialog(hWnd, 1);
|
|
||||||
else
|
|
||||||
EndDialog(hWnd, 0);
|
|
||||||
}
|
}
|
||||||
return 0;
|
ImGui::SetItemDefaultFocus();
|
||||||
default:
|
ImGui::SameLine();
|
||||||
return 0;
|
if (ImGui::Button("Cancel", ImVec2(120, 0)))
|
||||||
|
{
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
}
|
||||||
|
ImGui::EndPopup();
|
||||||
}
|
}
|
||||||
|
|
||||||
dlg_enter_name = 0;
|
ImGui::EndPopup();
|
||||||
EndDialog(hWnd, 0);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void high_score::show_high_scores(HWND hDlg, high_score_struct* table)
|
|
||||||
{
|
|
||||||
high_score_struct* tablePtr = table;
|
|
||||||
int nextPosition = 0;
|
|
||||||
for (int i = 0; i < 5; ++i)
|
|
||||||
{
|
|
||||||
if (dlg_enter_name == 1 && dlg_position == i)
|
|
||||||
{
|
|
||||||
hsdlg_show_score(hDlg, L" ", dlg_score, i);
|
|
||||||
nextPosition = 1;
|
|
||||||
}
|
|
||||||
hsdlg_show_score(hDlg, tablePtr->Name, tablePtr->Score, i + nextPosition);
|
|
||||||
++tablePtr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void high_score::hsdlg_show_score(HWND hDlg, LPCWSTR name, int score, int position)
|
|
||||||
{
|
|
||||||
CHAR scoreStr[36];
|
|
||||||
if (position < 5)
|
|
||||||
{
|
|
||||||
score::string_format(score, scoreStr);
|
|
||||||
if (scoreStr[0])
|
|
||||||
{
|
|
||||||
SetWindowTextW(GetDlgItem(hDlg, position + DLG_HIGHSCORES_StaticName1), name);
|
|
||||||
SetWindowTextA(GetDlgItem(hDlg, position + DLG_HIGHSCORES_Score1), scoreStr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "pinball.h"
|
|
||||||
|
|
||||||
struct high_score_struct
|
struct high_score_struct
|
||||||
{
|
{
|
||||||
wchar_t Name[32];
|
char Name[32];
|
||||||
int Score;
|
int Score;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -11,23 +10,20 @@ struct high_score_struct
|
|||||||
class high_score
|
class high_score
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static int read(high_score_struct* table, int* ptrToSmth);
|
static int read(high_score_struct* table);
|
||||||
static int write(high_score_struct* table, int* ptrToSmth);
|
static int write(high_score_struct* table);
|
||||||
static void clear_table(high_score_struct* table);
|
static void clear_table(high_score_struct* table);
|
||||||
static int get_score_position(high_score_struct* table, int score);
|
static int get_score_position(high_score_struct* table, int score);
|
||||||
static int place_new_score_into(high_score_struct* table, int score, LPWSTR name, int position);
|
static int place_new_score_into(high_score_struct* table, int score, LPSTR scoreStr, int position);
|
||||||
static void scramble_number_string(int Value, char* Buffer);
|
|
||||||
|
|
||||||
static void show_high_score_dialog(high_score_struct* table);
|
static void show_high_score_dialog(high_score_struct* table);
|
||||||
static void show_and_set_high_score_dialog(high_score_struct* table, int score, int pos, LPCWSTR defaultName);
|
static void show_and_set_high_score_dialog(high_score_struct* table, int score, int pos, LPCSTR defaultName);
|
||||||
static INT_PTR __stdcall HighScore(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
static void RenderHighScoreDialog();
|
||||||
static void show_high_scores(HWND hDlg, high_score_struct* table);
|
|
||||||
static void hsdlg_show_score(HWND hDlg, LPCWSTR name, int score, int position);
|
|
||||||
private :
|
private :
|
||||||
static int dlg_enter_name;
|
static int dlg_enter_name;
|
||||||
static int dlg_score;
|
static int dlg_score;
|
||||||
static int dlg_position;
|
static int dlg_position;
|
||||||
static LPCWSTR default_name;
|
static char default_name[32];
|
||||||
static high_score_struct* dlg_hst;
|
static high_score_struct* dlg_hst;
|
||||||
static winhelp_entry help[21];
|
static bool ShowDialog;
|
||||||
};
|
};
|
||||||
|
|||||||
123
SpaceCadetPinball/imconfig.h
Normal file
123
SpaceCadetPinball/imconfig.h
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// COMPILE-TIME OPTIONS FOR DEAR IMGUI
|
||||||
|
// Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure.
|
||||||
|
// You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// A) You may edit imconfig.h (and not overwrite it when updating Dear ImGui, or maintain a patch/rebased branch with your modifications to it)
|
||||||
|
// B) or '#define IMGUI_USER_CONFIG "my_imgui_config.h"' in your project and then add directives in your own file without touching this template.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp
|
||||||
|
// files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures.
|
||||||
|
// Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts.
|
||||||
|
// Call IMGUI_CHECKVERSION() from your .cpp files to verify that the data structures your files are using are matching the ones imgui.cpp is using.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
//---- Define assertion handler. Defaults to calling assert().
|
||||||
|
// If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement.
|
||||||
|
//#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
|
||||||
|
//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
|
||||||
|
|
||||||
|
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
|
||||||
|
// Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
|
||||||
|
// DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions()
|
||||||
|
// for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details.
|
||||||
|
//#define IMGUI_API __declspec( dllexport )
|
||||||
|
//#define IMGUI_API __declspec( dllimport )
|
||||||
|
|
||||||
|
//---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names.
|
||||||
|
//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||||
|
|
||||||
|
//---- Disable all of Dear ImGui or don't implement standard windows.
|
||||||
|
// It is very strongly recommended to NOT disable the demo windows during development. Please read comments in imgui_demo.cpp.
|
||||||
|
//#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty.
|
||||||
|
//#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty. Not recommended.
|
||||||
|
//#define IMGUI_DISABLE_METRICS_WINDOW // Disable metrics/debugger window: ShowMetricsWindow() will be empty.
|
||||||
|
|
||||||
|
//---- Don't implement some functions to reduce linkage requirements.
|
||||||
|
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a)
|
||||||
|
//#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with Visual Studio] Implement default IME handler (require imm32.lib/.a, auto-link for Visual Studio, -limm32 on command-line for MinGW)
|
||||||
|
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a)
|
||||||
|
//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, ime).
|
||||||
|
//#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default).
|
||||||
|
//#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf)
|
||||||
|
//#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself.
|
||||||
|
//#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies)
|
||||||
|
//#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function.
|
||||||
|
//#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
|
||||||
|
//#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available
|
||||||
|
|
||||||
|
//---- Include imgui_user.h at the end of imgui.h as a convenience
|
||||||
|
//#define IMGUI_INCLUDE_IMGUI_USER_H
|
||||||
|
|
||||||
|
//---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another)
|
||||||
|
//#define IMGUI_USE_BGRA_PACKED_COLOR
|
||||||
|
|
||||||
|
//---- Use 32-bit for ImWchar (default is 16-bit) to support unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...)
|
||||||
|
//#define IMGUI_USE_WCHAR32
|
||||||
|
|
||||||
|
//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version
|
||||||
|
// By default the embedded implementations are declared static and not available outside of Dear ImGui sources files.
|
||||||
|
//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
|
||||||
|
//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
|
||||||
|
//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
|
||||||
|
//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
|
||||||
|
|
||||||
|
//---- Use stb_printf's faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined)
|
||||||
|
// Requires 'stb_sprintf.h' to be available in the include path. Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by STB sprintf.
|
||||||
|
// #define IMGUI_USE_STB_SPRINTF
|
||||||
|
|
||||||
|
//---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui)
|
||||||
|
// Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided).
|
||||||
|
// On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'.
|
||||||
|
//#define IMGUI_ENABLE_FREETYPE
|
||||||
|
|
||||||
|
//---- Use stb_truetype to build and rasterize the font atlas (default)
|
||||||
|
// The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend.
|
||||||
|
//#define IMGUI_ENABLE_STB_TRUETYPE
|
||||||
|
|
||||||
|
//---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4.
|
||||||
|
// This will be inlined as part of ImVec2 and ImVec4 class declarations.
|
||||||
|
/*
|
||||||
|
#define IM_VEC2_CLASS_EXTRA \
|
||||||
|
ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \
|
||||||
|
operator MyVec2() const { return MyVec2(x,y); }
|
||||||
|
|
||||||
|
#define IM_VEC4_CLASS_EXTRA \
|
||||||
|
ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \
|
||||||
|
operator MyVec4() const { return MyVec4(x,y,z,w); }
|
||||||
|
*/
|
||||||
|
|
||||||
|
//---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices.
|
||||||
|
// Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices).
|
||||||
|
// Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer.
|
||||||
|
// Read about ImGuiBackendFlags_RendererHasVtxOffset for details.
|
||||||
|
//#define ImDrawIdx unsigned int
|
||||||
|
|
||||||
|
//---- Override ImDrawCallback signature (will need to modify renderer backends accordingly)
|
||||||
|
//struct ImDrawList;
|
||||||
|
//struct ImDrawCmd;
|
||||||
|
//typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data);
|
||||||
|
//#define ImDrawCallback MyImDrawCallback
|
||||||
|
|
||||||
|
//---- Debug Tools: Macro to break in Debugger
|
||||||
|
// (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.)
|
||||||
|
//#define IM_DEBUG_BREAK IM_ASSERT(0)
|
||||||
|
//#define IM_DEBUG_BREAK __debugbreak()
|
||||||
|
|
||||||
|
//---- Debug Tools: Have the Item Picker break in the ItemAdd() function instead of ItemHoverable(),
|
||||||
|
// (which comes earlier in the code, will catch a few extra items, allow picking items other than Hovered one.)
|
||||||
|
// This adds a small runtime cost which is why it is not enabled by default.
|
||||||
|
//#define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX
|
||||||
|
|
||||||
|
//---- Debug Tools: Enable slower asserts
|
||||||
|
//#define IMGUI_DEBUG_PARANOID
|
||||||
|
|
||||||
|
//---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files.
|
||||||
|
/*
|
||||||
|
namespace ImGui
|
||||||
|
{
|
||||||
|
void MyFunction(const char* name, const MyMatrix44& v);
|
||||||
|
}
|
||||||
|
*/
|
||||||
11866
SpaceCadetPinball/imgui.cpp
Normal file
11866
SpaceCadetPinball/imgui.cpp
Normal file
File diff suppressed because it is too large
Load Diff
2907
SpaceCadetPinball/imgui.h
Normal file
2907
SpaceCadetPinball/imgui.h
Normal file
File diff suppressed because it is too large
Load Diff
7652
SpaceCadetPinball/imgui_demo.cpp
Normal file
7652
SpaceCadetPinball/imgui_demo.cpp
Normal file
File diff suppressed because it is too large
Load Diff
4190
SpaceCadetPinball/imgui_draw.cpp
Normal file
4190
SpaceCadetPinball/imgui_draw.cpp
Normal file
File diff suppressed because it is too large
Load Diff
443
SpaceCadetPinball/imgui_impl_sdl.cpp
Normal file
443
SpaceCadetPinball/imgui_impl_sdl.cpp
Normal file
@@ -0,0 +1,443 @@
|
|||||||
|
// dear imgui: Platform Backend for SDL2
|
||||||
|
// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
|
||||||
|
// (Info: SDL2 is a cross-platform general purpose library for handling windows, inputs, graphics context creation, etc.)
|
||||||
|
// (Prefer SDL 2.0.5+ for full feature support.)
|
||||||
|
|
||||||
|
// Implemented features:
|
||||||
|
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||||
|
// [X] Platform: Clipboard support.
|
||||||
|
// [X] Platform: Keyboard arrays indexed using SDL_SCANCODE_* codes, e.g. ImGui::IsKeyPressed(SDL_SCANCODE_SPACE).
|
||||||
|
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
|
||||||
|
// Missing features:
|
||||||
|
// [ ] Platform: SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME.
|
||||||
|
|
||||||
|
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||||
|
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||||
|
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||||
|
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||||
|
|
||||||
|
// CHANGELOG
|
||||||
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
|
// 2021-08-17: Calling io.AddFocusEvent() on SDL_WINDOWEVENT_FOCUS_GAINED/SDL_WINDOWEVENT_FOCUS_LOST.
|
||||||
|
// 2021-07-29: Inputs: MousePos is correctly reported when the host platform window is hovered but not focused (using SDL_GetMouseFocus() + SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, requires SDL 2.0.5+)
|
||||||
|
// 2021-06-29: *BREAKING CHANGE* Removed 'SDL_Window* window' parameter to ImGui_ImplSDL2_NewFrame() which was unnecessary.
|
||||||
|
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
|
||||||
|
// 2021-03-22: Rework global mouse pos availability check listing supported platforms explicitly, effectively fixing mouse access on Raspberry Pi. (#2837, #3950)
|
||||||
|
// 2020-05-25: Misc: Report a zero display-size when window is minimized, to be consistent with other backends.
|
||||||
|
// 2020-02-20: Inputs: Fixed mapping for ImGuiKey_KeyPadEnter (using SDL_SCANCODE_KP_ENTER instead of SDL_SCANCODE_RETURN2).
|
||||||
|
// 2019-12-17: Inputs: On Wayland, use SDL_GetMouseState (because there is no global mouse state).
|
||||||
|
// 2019-12-05: Inputs: Added support for ImGuiMouseCursor_NotAllowed mouse cursor.
|
||||||
|
// 2019-07-21: Inputs: Added mapping for ImGuiKey_KeyPadEnter.
|
||||||
|
// 2019-04-23: Inputs: Added support for SDL_GameController (if ImGuiConfigFlags_NavEnableGamepad is set by user application).
|
||||||
|
// 2019-03-12: Misc: Preserve DisplayFramebufferScale when main window is minimized.
|
||||||
|
// 2018-12-21: Inputs: Workaround for Android/iOS which don't seem to handle focus related calls.
|
||||||
|
// 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window.
|
||||||
|
// 2018-11-14: Changed the signature of ImGui_ImplSDL2_ProcessEvent() to take a 'const SDL_Event*'.
|
||||||
|
// 2018-08-01: Inputs: Workaround for Emscripten which doesn't seem to handle focus related calls.
|
||||||
|
// 2018-06-29: Inputs: Added support for the ImGuiMouseCursor_Hand cursor.
|
||||||
|
// 2018-06-08: Misc: Extracted imgui_impl_sdl.cpp/.h away from the old combined SDL2+OpenGL/Vulkan examples.
|
||||||
|
// 2018-06-08: Misc: ImGui_ImplSDL2_InitForOpenGL() now takes a SDL_GLContext parameter.
|
||||||
|
// 2018-05-09: Misc: Fixed clipboard paste memory leak (we didn't call SDL_FreeMemory on the data returned by SDL_GetClipboardText).
|
||||||
|
// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors flag + honor ImGuiConfigFlags_NoMouseCursorChange flag.
|
||||||
|
// 2018-02-16: Inputs: Added support for mouse cursors, honoring ImGui::GetMouseCursor() value.
|
||||||
|
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
|
||||||
|
// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space.
|
||||||
|
// 2018-02-05: Misc: Using SDL_GetPerformanceCounter() instead of SDL_GetTicks() to be able to handle very high framerate (1000+ FPS).
|
||||||
|
// 2018-02-05: Inputs: Keyboard mapping is using scancodes everywhere instead of a confusing mixture of keycodes and scancodes.
|
||||||
|
// 2018-01-20: Inputs: Added Horizontal Mouse Wheel support.
|
||||||
|
// 2018-01-19: Inputs: When available (SDL 2.0.4+) using SDL_CaptureMouse() to retrieve coordinates outside of client area when dragging. Otherwise (SDL 2.0.3 and before) testing for SDL_WINDOW_INPUT_FOCUS instead of SDL_WINDOW_MOUSE_FOCUS.
|
||||||
|
// 2018-01-18: Inputs: Added mapping for ImGuiKey_Insert.
|
||||||
|
// 2017-08-25: Inputs: MousePos set to -FLT_MAX,-FLT_MAX when mouse is unavailable/missing (instead of -1,-1).
|
||||||
|
// 2016-10-15: Misc: Added a void* user_data parameter to Clipboard function handlers.
|
||||||
|
|
||||||
|
#include "imgui.h"
|
||||||
|
#include "imgui_impl_sdl.h"
|
||||||
|
|
||||||
|
// SDL
|
||||||
|
#include <SDL.h>
|
||||||
|
#include <SDL_syswm.h>
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#include <TargetConditionals.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if SDL_VERSION_ATLEAST(2,0,4) && !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IOS)
|
||||||
|
#define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE 1
|
||||||
|
#else
|
||||||
|
#define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE 0
|
||||||
|
#endif
|
||||||
|
#define SDL_HAS_MOUSE_FOCUS_CLICKTHROUGH SDL_VERSION_ATLEAST(2,0,5)
|
||||||
|
#define SDL_HAS_VULKAN SDL_VERSION_ATLEAST(2,0,6)
|
||||||
|
|
||||||
|
// SDL Data
|
||||||
|
struct ImGui_ImplSDL2_Data
|
||||||
|
{
|
||||||
|
SDL_Window* Window;
|
||||||
|
Uint64 Time;
|
||||||
|
bool MousePressed[3];
|
||||||
|
SDL_Cursor* MouseCursors[ImGuiMouseCursor_COUNT];
|
||||||
|
char* ClipboardTextData;
|
||||||
|
bool MouseCanUseGlobalState;
|
||||||
|
|
||||||
|
ImGui_ImplSDL2_Data() { memset(this, 0, sizeof(*this)); }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts
|
||||||
|
// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
|
||||||
|
// FIXME: multi-context support is not well tested and probably dysfunctional in this backend.
|
||||||
|
// FIXME: some shared resources (mouse cursor shape, gamepad) are mishandled when using multi-context.
|
||||||
|
static ImGui_ImplSDL2_Data* ImGui_ImplSDL2_GetBackendData()
|
||||||
|
{
|
||||||
|
return ImGui::GetCurrentContext() ? (ImGui_ImplSDL2_Data*)ImGui::GetIO().BackendPlatformUserData : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Functions
|
||||||
|
static const char* ImGui_ImplSDL2_GetClipboardText(void*)
|
||||||
|
{
|
||||||
|
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
|
||||||
|
if (bd->ClipboardTextData)
|
||||||
|
SDL_free(bd->ClipboardTextData);
|
||||||
|
bd->ClipboardTextData = SDL_GetClipboardText();
|
||||||
|
return bd->ClipboardTextData;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ImGui_ImplSDL2_SetClipboardText(void*, const char* text)
|
||||||
|
{
|
||||||
|
SDL_SetClipboardText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
|
||||||
|
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
|
||||||
|
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||||
|
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||||
|
// If you have multiple SDL events and some of them are not meant to be used by dear imgui, you may need to filter events based on their windowID field.
|
||||||
|
bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
|
||||||
|
|
||||||
|
switch (event->type)
|
||||||
|
{
|
||||||
|
case SDL_MOUSEWHEEL:
|
||||||
|
{
|
||||||
|
if (event->wheel.x > 0) io.MouseWheelH += 1;
|
||||||
|
if (event->wheel.x < 0) io.MouseWheelH -= 1;
|
||||||
|
if (event->wheel.y > 0) io.MouseWheel += 1;
|
||||||
|
if (event->wheel.y < 0) io.MouseWheel -= 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case SDL_MOUSEBUTTONDOWN:
|
||||||
|
{
|
||||||
|
if (event->button.button == SDL_BUTTON_LEFT) { bd->MousePressed[0] = true; }
|
||||||
|
if (event->button.button == SDL_BUTTON_RIGHT) { bd->MousePressed[1] = true; }
|
||||||
|
if (event->button.button == SDL_BUTTON_MIDDLE) { bd->MousePressed[2] = true; }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case SDL_TEXTINPUT:
|
||||||
|
{
|
||||||
|
io.AddInputCharactersUTF8(event->text.text);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case SDL_KEYDOWN:
|
||||||
|
case SDL_KEYUP:
|
||||||
|
{
|
||||||
|
int key = event->key.keysym.scancode;
|
||||||
|
IM_ASSERT(key >= 0 && key < IM_ARRAYSIZE(io.KeysDown));
|
||||||
|
io.KeysDown[key] = (event->type == SDL_KEYDOWN);
|
||||||
|
io.KeyShift = ((SDL_GetModState() & KMOD_SHIFT) != 0);
|
||||||
|
io.KeyCtrl = ((SDL_GetModState() & KMOD_CTRL) != 0);
|
||||||
|
io.KeyAlt = ((SDL_GetModState() & KMOD_ALT) != 0);
|
||||||
|
#ifdef _WIN32
|
||||||
|
io.KeySuper = false;
|
||||||
|
#else
|
||||||
|
io.KeySuper = ((SDL_GetModState() & KMOD_GUI) != 0);
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case SDL_WINDOWEVENT:
|
||||||
|
{
|
||||||
|
if (event->window.event == SDL_WINDOWEVENT_FOCUS_GAINED)
|
||||||
|
io.AddFocusEvent(true);
|
||||||
|
else if (event->window.event == SDL_WINDOWEVENT_FOCUS_LOST)
|
||||||
|
io.AddFocusEvent(false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ImGui_ImplSDL2_Init(SDL_Window* window)
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
IM_ASSERT(io.BackendPlatformUserData == NULL && "Already initialized a platform backend!");
|
||||||
|
|
||||||
|
// Check and store if we are on a SDL backend that supports global mouse position
|
||||||
|
// ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list)
|
||||||
|
bool mouse_can_use_global_state = false;
|
||||||
|
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
|
||||||
|
const char* sdl_backend = SDL_GetCurrentVideoDriver();
|
||||||
|
const char* global_mouse_whitelist[] = { "windows", "cocoa", "x11", "DIVE", "VMAN" };
|
||||||
|
for (int n = 0; n < IM_ARRAYSIZE(global_mouse_whitelist); n++)
|
||||||
|
if (strncmp(sdl_backend, global_mouse_whitelist[n], strlen(global_mouse_whitelist[n])) == 0)
|
||||||
|
mouse_can_use_global_state = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Setup backend capabilities flags
|
||||||
|
ImGui_ImplSDL2_Data* bd = IM_NEW(ImGui_ImplSDL2_Data)();
|
||||||
|
io.BackendPlatformUserData = (void*)bd;
|
||||||
|
io.BackendPlatformName = "imgui_impl_sdl";
|
||||||
|
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
||||||
|
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
|
||||||
|
|
||||||
|
bd->Window = window;
|
||||||
|
bd->MouseCanUseGlobalState = mouse_can_use_global_state;
|
||||||
|
|
||||||
|
// Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array.
|
||||||
|
io.KeyMap[ImGuiKey_Tab] = SDL_SCANCODE_TAB;
|
||||||
|
io.KeyMap[ImGuiKey_LeftArrow] = SDL_SCANCODE_LEFT;
|
||||||
|
io.KeyMap[ImGuiKey_RightArrow] = SDL_SCANCODE_RIGHT;
|
||||||
|
io.KeyMap[ImGuiKey_UpArrow] = SDL_SCANCODE_UP;
|
||||||
|
io.KeyMap[ImGuiKey_DownArrow] = SDL_SCANCODE_DOWN;
|
||||||
|
io.KeyMap[ImGuiKey_PageUp] = SDL_SCANCODE_PAGEUP;
|
||||||
|
io.KeyMap[ImGuiKey_PageDown] = SDL_SCANCODE_PAGEDOWN;
|
||||||
|
io.KeyMap[ImGuiKey_Home] = SDL_SCANCODE_HOME;
|
||||||
|
io.KeyMap[ImGuiKey_End] = SDL_SCANCODE_END;
|
||||||
|
io.KeyMap[ImGuiKey_Insert] = SDL_SCANCODE_INSERT;
|
||||||
|
io.KeyMap[ImGuiKey_Delete] = SDL_SCANCODE_DELETE;
|
||||||
|
io.KeyMap[ImGuiKey_Backspace] = SDL_SCANCODE_BACKSPACE;
|
||||||
|
io.KeyMap[ImGuiKey_Space] = SDL_SCANCODE_SPACE;
|
||||||
|
io.KeyMap[ImGuiKey_Enter] = SDL_SCANCODE_RETURN;
|
||||||
|
io.KeyMap[ImGuiKey_Escape] = SDL_SCANCODE_ESCAPE;
|
||||||
|
io.KeyMap[ImGuiKey_KeyPadEnter] = SDL_SCANCODE_KP_ENTER;
|
||||||
|
io.KeyMap[ImGuiKey_A] = SDL_SCANCODE_A;
|
||||||
|
io.KeyMap[ImGuiKey_C] = SDL_SCANCODE_C;
|
||||||
|
io.KeyMap[ImGuiKey_V] = SDL_SCANCODE_V;
|
||||||
|
io.KeyMap[ImGuiKey_X] = SDL_SCANCODE_X;
|
||||||
|
io.KeyMap[ImGuiKey_Y] = SDL_SCANCODE_Y;
|
||||||
|
io.KeyMap[ImGuiKey_Z] = SDL_SCANCODE_Z;
|
||||||
|
|
||||||
|
io.SetClipboardTextFn = ImGui_ImplSDL2_SetClipboardText;
|
||||||
|
io.GetClipboardTextFn = ImGui_ImplSDL2_GetClipboardText;
|
||||||
|
io.ClipboardUserData = NULL;
|
||||||
|
|
||||||
|
// Load mouse cursors
|
||||||
|
bd->MouseCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
|
||||||
|
bd->MouseCursors[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM);
|
||||||
|
bd->MouseCursors[ImGuiMouseCursor_ResizeAll] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL);
|
||||||
|
bd->MouseCursors[ImGuiMouseCursor_ResizeNS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS);
|
||||||
|
bd->MouseCursors[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE);
|
||||||
|
bd->MouseCursors[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW);
|
||||||
|
bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE);
|
||||||
|
bd->MouseCursors[ImGuiMouseCursor_Hand] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND);
|
||||||
|
bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NO);
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
SDL_SysWMinfo info;
|
||||||
|
SDL_VERSION(&info.version);
|
||||||
|
if (SDL_GetWindowWMInfo(window, &info))
|
||||||
|
io.ImeWindowHandle = info.info.win.window;
|
||||||
|
#else
|
||||||
|
(void)window;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Set SDL hint to receive mouse click events on window focus, otherwise SDL doesn't emit the event.
|
||||||
|
// Without this, when clicking to gain focus, our widgets wouldn't activate even though they showed as hovered.
|
||||||
|
// (This is unfortunately a global SDL setting, so enabling it might have a side-effect on your application.
|
||||||
|
// It is unlikely to make a difference, but if your app absolutely needs to ignore the initial on-focus click:
|
||||||
|
// you can ignore SDL_MOUSEBUTTONDOWN events coming right after a SDL_WINDOWEVENT_FOCUS_GAINED)
|
||||||
|
#if SDL_HAS_MOUSE_FOCUS_CLICKTHROUGH
|
||||||
|
SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context)
|
||||||
|
{
|
||||||
|
IM_UNUSED(sdl_gl_context); // Viewport branch will need this.
|
||||||
|
return ImGui_ImplSDL2_Init(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window)
|
||||||
|
{
|
||||||
|
#if !SDL_HAS_VULKAN
|
||||||
|
IM_ASSERT(0 && "Unsupported");
|
||||||
|
#endif
|
||||||
|
return ImGui_ImplSDL2_Init(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui_ImplSDL2_InitForD3D(SDL_Window* window)
|
||||||
|
{
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
IM_ASSERT(0 && "Unsupported");
|
||||||
|
#endif
|
||||||
|
return ImGui_ImplSDL2_Init(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui_ImplSDL2_InitForMetal(SDL_Window* window)
|
||||||
|
{
|
||||||
|
return ImGui_ImplSDL2_Init(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplSDL2_Shutdown()
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
|
||||||
|
|
||||||
|
if (bd->ClipboardTextData)
|
||||||
|
SDL_free(bd->ClipboardTextData);
|
||||||
|
for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)
|
||||||
|
SDL_FreeCursor(bd->MouseCursors[cursor_n]);
|
||||||
|
|
||||||
|
io.BackendPlatformName = NULL;
|
||||||
|
io.BackendPlatformUserData = NULL;
|
||||||
|
IM_DELETE(bd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ImGui_ImplSDL2_UpdateMousePosAndButtons()
|
||||||
|
{
|
||||||
|
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
|
||||||
|
ImVec2 mouse_pos_prev = io.MousePos;
|
||||||
|
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
|
||||||
|
|
||||||
|
// Update mouse buttons
|
||||||
|
int mouse_x_local, mouse_y_local;
|
||||||
|
Uint32 mouse_buttons = SDL_GetMouseState(&mouse_x_local, &mouse_y_local);
|
||||||
|
io.MouseDown[0] = bd->MousePressed[0] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
|
||||||
|
io.MouseDown[1] = bd->MousePressed[1] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0;
|
||||||
|
io.MouseDown[2] = bd->MousePressed[2] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0;
|
||||||
|
bd->MousePressed[0] = bd->MousePressed[1] = bd->MousePressed[2] = false;
|
||||||
|
|
||||||
|
// Obtain focused and hovered window. We forward mouse input when focused or when hovered (and no other window is capturing)
|
||||||
|
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
|
||||||
|
SDL_Window* focused_window = SDL_GetKeyboardFocus();
|
||||||
|
SDL_Window* hovered_window = SDL_HAS_MOUSE_FOCUS_CLICKTHROUGH ? SDL_GetMouseFocus() : NULL; // This is better but is only reliably useful with SDL 2.0.5+ and SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH.
|
||||||
|
SDL_Window* mouse_window = NULL;
|
||||||
|
if (hovered_window && bd->Window == hovered_window)
|
||||||
|
mouse_window = hovered_window;
|
||||||
|
else if (focused_window && bd->Window == focused_window)
|
||||||
|
mouse_window = focused_window;
|
||||||
|
|
||||||
|
// SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries shouldn't e.g. trigger other operations outside
|
||||||
|
SDL_CaptureMouse(ImGui::IsAnyMouseDown() ? SDL_TRUE : SDL_FALSE);
|
||||||
|
#else
|
||||||
|
// SDL 2.0.3 and non-windowed systems: single-viewport only
|
||||||
|
SDL_Window* mouse_window = (SDL_GetWindowFlags(bd->Window) & SDL_WINDOW_INPUT_FOCUS) ? bd->Window : NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (mouse_window == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
|
||||||
|
if (io.WantSetMousePos)
|
||||||
|
SDL_WarpMouseInWindow(bd->Window, (int)mouse_pos_prev.x, (int)mouse_pos_prev.y);
|
||||||
|
|
||||||
|
// Set Dear ImGui mouse position from OS position + get buttons. (this is the common behavior)
|
||||||
|
if (bd->MouseCanUseGlobalState)
|
||||||
|
{
|
||||||
|
// Single-viewport mode: mouse position in client window coordinates (io.MousePos is (0,0) when the mouse is on the upper-left corner of the app window)
|
||||||
|
// Unlike local position obtained earlier this will be valid when straying out of bounds.
|
||||||
|
int mouse_x_global, mouse_y_global;
|
||||||
|
SDL_GetGlobalMouseState(&mouse_x_global, &mouse_y_global);
|
||||||
|
int window_x, window_y;
|
||||||
|
SDL_GetWindowPosition(mouse_window, &window_x, &window_y);
|
||||||
|
io.MousePos = ImVec2((float)(mouse_x_global - window_x), (float)(mouse_y_global - window_y));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
io.MousePos = ImVec2((float)mouse_x_local, (float)mouse_y_local);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ImGui_ImplSDL2_UpdateMouseCursor()
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
|
||||||
|
return;
|
||||||
|
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
|
||||||
|
|
||||||
|
ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
|
||||||
|
if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None)
|
||||||
|
{
|
||||||
|
// Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
|
||||||
|
SDL_ShowCursor(SDL_FALSE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Show OS mouse cursor
|
||||||
|
SDL_SetCursor(bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]);
|
||||||
|
SDL_ShowCursor(SDL_TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ImGui_ImplSDL2_UpdateGamepads()
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
memset(io.NavInputs, 0, sizeof(io.NavInputs));
|
||||||
|
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Get gamepad
|
||||||
|
SDL_GameController* game_controller = SDL_GameControllerOpen(0);
|
||||||
|
if (!game_controller)
|
||||||
|
{
|
||||||
|
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update gamepad inputs
|
||||||
|
#define MAP_BUTTON(NAV_NO, BUTTON_NO) { io.NavInputs[NAV_NO] = (SDL_GameControllerGetButton(game_controller, BUTTON_NO) != 0) ? 1.0f : 0.0f; }
|
||||||
|
#define MAP_ANALOG(NAV_NO, AXIS_NO, V0, V1) { float vn = (float)(SDL_GameControllerGetAxis(game_controller, AXIS_NO) - V0) / (float)(V1 - V0); if (vn > 1.0f) vn = 1.0f; if (vn > 0.0f && io.NavInputs[NAV_NO] < vn) io.NavInputs[NAV_NO] = vn; }
|
||||||
|
const int thumb_dead_zone = 8000; // SDL_gamecontroller.h suggests using this value.
|
||||||
|
MAP_BUTTON(ImGuiNavInput_Activate, SDL_CONTROLLER_BUTTON_A); // Cross / A
|
||||||
|
MAP_BUTTON(ImGuiNavInput_Cancel, SDL_CONTROLLER_BUTTON_B); // Circle / B
|
||||||
|
MAP_BUTTON(ImGuiNavInput_Menu, SDL_CONTROLLER_BUTTON_X); // Square / X
|
||||||
|
MAP_BUTTON(ImGuiNavInput_Input, SDL_CONTROLLER_BUTTON_Y); // Triangle / Y
|
||||||
|
MAP_BUTTON(ImGuiNavInput_DpadLeft, SDL_CONTROLLER_BUTTON_DPAD_LEFT); // D-Pad Left
|
||||||
|
MAP_BUTTON(ImGuiNavInput_DpadRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT); // D-Pad Right
|
||||||
|
MAP_BUTTON(ImGuiNavInput_DpadUp, SDL_CONTROLLER_BUTTON_DPAD_UP); // D-Pad Up
|
||||||
|
MAP_BUTTON(ImGuiNavInput_DpadDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN); // D-Pad Down
|
||||||
|
MAP_BUTTON(ImGuiNavInput_FocusPrev, SDL_CONTROLLER_BUTTON_LEFTSHOULDER); // L1 / LB
|
||||||
|
MAP_BUTTON(ImGuiNavInput_FocusNext, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); // R1 / RB
|
||||||
|
MAP_BUTTON(ImGuiNavInput_TweakSlow, SDL_CONTROLLER_BUTTON_LEFTSHOULDER); // L1 / LB
|
||||||
|
MAP_BUTTON(ImGuiNavInput_TweakFast, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); // R1 / RB
|
||||||
|
MAP_ANALOG(ImGuiNavInput_LStickLeft, SDL_CONTROLLER_AXIS_LEFTX, -thumb_dead_zone, -32768);
|
||||||
|
MAP_ANALOG(ImGuiNavInput_LStickRight, SDL_CONTROLLER_AXIS_LEFTX, +thumb_dead_zone, +32767);
|
||||||
|
MAP_ANALOG(ImGuiNavInput_LStickUp, SDL_CONTROLLER_AXIS_LEFTY, -thumb_dead_zone, -32767);
|
||||||
|
MAP_ANALOG(ImGuiNavInput_LStickDown, SDL_CONTROLLER_AXIS_LEFTY, +thumb_dead_zone, +32767);
|
||||||
|
|
||||||
|
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
|
||||||
|
#undef MAP_BUTTON
|
||||||
|
#undef MAP_ANALOG
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplSDL2_NewFrame()
|
||||||
|
{
|
||||||
|
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
|
||||||
|
IM_ASSERT(bd != NULL && "Did you call ImGui_ImplSDL2_Init()?");
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
|
||||||
|
// Setup display size (every frame to accommodate for window resizing)
|
||||||
|
int w, h;
|
||||||
|
int display_w, display_h;
|
||||||
|
SDL_GetWindowSize(bd->Window, &w, &h);
|
||||||
|
if (SDL_GetWindowFlags(bd->Window) & SDL_WINDOW_MINIMIZED)
|
||||||
|
w = h = 0;
|
||||||
|
SDL_GL_GetDrawableSize(bd->Window, &display_w, &display_h);
|
||||||
|
io.DisplaySize = ImVec2((float)w, (float)h);
|
||||||
|
if (w > 0 && h > 0)
|
||||||
|
io.DisplayFramebufferScale = ImVec2((float)display_w / w, (float)display_h / h);
|
||||||
|
|
||||||
|
// Setup time step (we don't use SDL_GetTicks() because it is using millisecond resolution)
|
||||||
|
static Uint64 frequency = SDL_GetPerformanceFrequency();
|
||||||
|
Uint64 current_time = SDL_GetPerformanceCounter();
|
||||||
|
io.DeltaTime = bd->Time > 0 ? (float)((double)(current_time - bd->Time) / frequency) : (float)(1.0f / 60.0f);
|
||||||
|
bd->Time = current_time;
|
||||||
|
|
||||||
|
ImGui_ImplSDL2_UpdateMousePosAndButtons();
|
||||||
|
ImGui_ImplSDL2_UpdateMouseCursor();
|
||||||
|
|
||||||
|
// Update game controllers (if enabled and available)
|
||||||
|
ImGui_ImplSDL2_UpdateGamepads();
|
||||||
|
}
|
||||||
34
SpaceCadetPinball/imgui_impl_sdl.h
Normal file
34
SpaceCadetPinball/imgui_impl_sdl.h
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
// dear imgui: Platform Backend for SDL2
|
||||||
|
// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
|
||||||
|
// (Info: SDL2 is a cross-platform general purpose library for handling windows, inputs, graphics context creation, etc.)
|
||||||
|
|
||||||
|
// Implemented features:
|
||||||
|
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||||
|
// [X] Platform: Clipboard support.
|
||||||
|
// [X] Platform: Keyboard arrays indexed using SDL_SCANCODE_* codes, e.g. ImGui::IsKeyPressed(SDL_SCANCODE_SPACE).
|
||||||
|
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
|
||||||
|
// Missing features:
|
||||||
|
// [ ] Platform: SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME.
|
||||||
|
|
||||||
|
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||||
|
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||||
|
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||||
|
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "imgui.h" // IMGUI_IMPL_API
|
||||||
|
|
||||||
|
struct SDL_Window;
|
||||||
|
typedef union SDL_Event SDL_Event;
|
||||||
|
|
||||||
|
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context);
|
||||||
|
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window);
|
||||||
|
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForD3D(SDL_Window* window);
|
||||||
|
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForMetal(SDL_Window* window);
|
||||||
|
IMGUI_IMPL_API void ImGui_ImplSDL2_Shutdown();
|
||||||
|
IMGUI_IMPL_API void ImGui_ImplSDL2_NewFrame();
|
||||||
|
IMGUI_IMPL_API bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event);
|
||||||
|
|
||||||
|
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||||
|
static inline void ImGui_ImplSDL2_NewFrame(SDL_Window*) { ImGui_ImplSDL2_NewFrame(); } // 1.84: removed unnecessary parameter
|
||||||
|
#endif
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user